diff --git a/ChangeLog b/ChangeLog
index 001d4add0219f059149d66a9794e434bf3f033e2..0e61684e88b907727df4b18487ea3e487f255427 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,136 @@
+----------------------------------------------------------------------
+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)
 
@@ -16,7 +149,7 @@ Fri Jun 10 07:56:49 1994  Bob Amstadt  (bob@pooh)
 	* 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 ef6c3b70d814f8f7f1e81a4ad330985811a63b20..d05917607625d392a08184cbcb0ac85d338e6357 100644
--- a/controls/combo.c
+++ b/controls/combo.c
@@ -78,9 +78,9 @@ LONG ComboBoxWndProc( HWND hwnd, WORD message, WORD wParam, LONG lParam )
 				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 abafcfe967e2113e2ef785acf664985c78b8e70c..3aff8f8693467d1ebae343becb710af5ec89a8c2 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 @@ static char Copyright[] = "Copyright  David W. Metcalfe, 1994";
 #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 @@ typedef struct
     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 @@ typedef struct
     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 @@ typedef struct
 #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 @@ static BOOL Print = FALSE;
 
 
 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 @@ void EDIT_ClearSel(HWND hwnd);
 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 @@ LONG EditWndProc(HWND hwnd, WORD uMsg, WORD wParam, LONG lParam)
 
     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 @@ LONG EditWndProc(HWND hwnd, WORD uMsg, WORD wParam, LONG lParam)
 	break;
 
     case EM_GETHANDLE:
-	printf("edit: cannot process EM_GETHANDLE message\n");
+	lResult = es->hText;
 	break;
 
     case EM_GETLINE:
@@ -206,7 +234,10 @@ LONG EditWndProc(HWND hwnd, WORD uMsg, WORD wParam, LONG lParam)
 	break;
 
     case EM_LIMITTEXT:
-	es->MaxTextLen = wParam;
+	if (wParam)
+	    es->MaxTextLen = wParam;
+	else
+	    es->MaxTextLen = 65000;
 	break;
 
     case EM_LINEFROMCHAR:
@@ -221,7 +252,7 @@ LONG EditWndProc(HWND hwnd, WORD uMsg, WORD wParam, LONG lParam)
 	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 @@ LONG EditWndProc(HWND hwnd, WORD uMsg, WORD wParam, LONG lParam)
 	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 @@ LONG EditWndProc(HWND hwnd, WORD uMsg, WORD wParam, LONG lParam)
 	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 @@ LONG EditWndProc(HWND hwnd, WORD uMsg, WORD wParam, LONG lParam)
 	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 @@ LONG EditWndProc(HWND hwnd, WORD uMsg, WORD wParam, LONG lParam)
 	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 @@ LONG EditWndProc(HWND hwnd, WORD uMsg, WORD wParam, LONG lParam)
 	lResult = 0;
 	break;
 
+    case WM_NCCREATE:
+	lResult = EDIT_NCCreateMsg(hwnd, lParam);
+	break;
+	
     case WM_PAINT:
 	EDIT_PaintMsg(hwnd);
 	break;
@@ -353,6 +398,10 @@ LONG EditWndProc(HWND hwnd, WORD uMsg, WORD wParam, LONG lParam)
 	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 @@ LONG EditWndProc(HWND hwnd, WORD uMsg, WORD wParam, LONG lParam)
 
 
 /*********************************************************************
- *  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,31 +448,68 @@ long EDIT_CreateMsg(HWND hwnd, LONG lParam)
     textPtrs = (unsigned int *)EDIT_HEAP_ADDR(es->hTextPtrs);
     es->hCharWidths = EDIT_HEAP_ALLOC(256 * sizeof(short));
 
-    /* initialize state variable structure */
-    /* --- char width array */
-    hdc = GetDC(hwnd);
-    charWidths = (short *)EDIT_HEAP_ADDR(es->hCharWidths);
-    memset(charWidths, 0, 256 * sizeof(short));
-    GetCharWidth(hdc, 0, 255, charWidths);
-
     /* --- text buffer */
+    es->localheap = &HEAP_LocalFindHeap(createStruct->hInstance)->free_list;
     es->MaxTextLen = MAXTEXTLEN + 1;
-    if (!(wndPtr->hText))
+    if (!(es->hText))
     {
-	es->textlen = EditBufLen(wndPtr);
-	es->hText = EDIT_HEAP_ALLOC(EditBufLen(wndPtr) + 2);
-	text = (LPSTR)EDIT_HEAP_ADDR(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
     {
-	es->hText = wndPtr->hText;
-	wndPtr->hText = 0;
-	es->textlen = GetWindowTextLength(hwnd) + 1;
+	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);
+    charWidths = (short *)EDIT_HEAP_ADDR(es->hCharWidths);
+    memset(charWidths, 0, 256 * sizeof(short));
+    GetCharWidth(hdc, 0, 255, charWidths);
+
     /* --- other structure variables */
     GetTextMetrics(hdc, &tm);
     es->txtht = tm.tmHeight + tm.tmExternalLeading;
@@ -435,8 +519,11 @@ long EDIT_CreateMsg(HWND hwnd, LONG lParam)
     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 @@ void EDIT_BuildTextPointers(HWND hwnd)
     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 @@ char *EDIT_TextLine(HWND hwnd, int sel)
 {
     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 @@ void EDIT_WriteText(HWND hwnd, char *lp, int off, int len, int row,
     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 @@ void EDIT_WriteText(HWND hwnd, char *lp, int off, int len, int row,
     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 @@ void EDIT_WriteText(HWND hwnd, char *lp, int off, int len, int row,
 	}
     }
 
+    if (es->hFont)
+	SelectObject(hdc, (HANDLE)oldfont);
+
     EDIT_HEAP_FREE(hStr);
     ReleaseDC(hwnd, hdc);
 }
@@ -988,7 +1082,7 @@ void EDIT_KeyTyped(HWND hwnd, short ch)
 {
     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 @@ void EDIT_KeyTyped(HWND hwnd, short ch)
 	/* 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 @@ void EDIT_Forward(HWND hwnd)
 {
     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 @@ void EDIT_Backward(HWND hwnd)
 {
     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 @@ void EDIT_End(HWND hwnd)
     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 @@ LONG EDIT_SetTextMsg(HWND hwnd, LONG lParam)
 	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 @@ void EDIT_ClearText(HWND hwnd)
     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 @@ void EDIT_SetSelMsg(HWND hwnd, LONG lParam)
     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 @@ void EDIT_GetLineCol(HWND hwnd, int off, int *line, int *col)
     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 @@ void EDIT_DeleteSel(HWND hwnd)
     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 @@ void EDIT_ClearSel(HWND hwnd)
     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 @@ int EDIT_TextLineNumber(HWND hwnd, char *lp)
     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 @@ int EDIT_TextLineNumber(HWND hwnd, char *lp)
 
 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_SetAnchor(HWND hwnd, int row, int col)
 
 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 @@ void EDIT_ExtendSel(HWND hwnd, int x, int y)
     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,22 +2361,90 @@ void EDIT_ExtendSel(HWND hwnd, int x, int y)
     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;
+
+    bel = es->SelEndLine;
+    bec = es->SelEndCol;
+
+    /* return if no new characters to mark */
+    if (bbl == bel && bbc == bec)
+	return;
 
-    bbl = min(es->SelBegLine, es->SelEndLine);
-    bel = max(es->SelBegLine, es->SelEndLine);
-    while (ptop < bbl)
+    /* 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);
 }
 
 
@@ -2331,6 +2509,53 @@ LONG EDIT_GetSelMsg(HWND hwnd)
 }
 
 
+/*********************************************************************
+ *  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
  */
@@ -2367,6 +2592,239 @@ LONG EDIT_LineIndexMsg(HWND hwnd, WORD wParam)
 }
 
 
+/*********************************************************************
+ *  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 58a98654030116aff0260d171fa9613b6b137bb2..7b05747dd8bf20bffc93e932da3e287ff98fbf39 100644
--- a/controls/menu.c
+++ b/controls/menu.c
@@ -37,6 +37,8 @@ void MenuButtonUp(HWND hWnd, LPPOPUPMENU lppop, int x, int y);
 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 @@ BOOL FAR PASCAL AboutWine_Proc(HWND hDlg, WORD msg, WORD wParam, LONG lParam);
 
 /***********************************************************************
  *           PopupMenuWndProc
+				SetWindow
+				SetWindow
  */
 LONG PopupMenuWndProc( HWND hwnd, WORD message, WORD wParam, LONG lParam )
 {    
@@ -90,6 +94,7 @@ LONG PopupMenuWndProc( HWND hwnd, WORD message, WORD wParam, LONG lParam )
 #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 @@ LONG PopupMenuWndProc( HWND hwnd, WORD message, WORD wParam, LONG lParam )
 		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 @@ LONG PopupMenuWndProc( HWND hwnd, WORD message, WORD wParam, LONG lParam )
 		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 @@ LONG PopupMenuWndProc( HWND hwnd, WORD message, WORD wParam, LONG lParam )
 				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 MenuMouseMove(HWND hWnd, LPPOPUPMENU lppop, WORD wParam, int x, int y)
 }
 
 
+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 @@ BOOL SetMenu(HWND hWnd, HMENU hMenu)
 	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 @@ void DrawMenuBar(HWND hWnd)
 			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 @@ void DrawMenuBar(HWND hWnd)
 				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 7210e6861525da31cc52fd50d5ba72552f76a96c..7c42967103e631a87319e91ee44ca26ced805070 100644
--- a/if1632/call.S
+++ b/if1632/call.S
@@ -105,7 +105,7 @@ _CallToInit16:
 	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 668b05a5524f20da4c7a76ffc6ee164b805354fb..4cba3a68bb676225773e832fcb58ca25dfc07b61 100644
--- a/if1632/kernel.spec
+++ b/if1632/kernel.spec
@@ -44,7 +44,7 @@ length	415
 #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 @@ length	415
 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 df33e6db6fff69ec39dceaa527a706cd93ac3c22..d599d196c4e0b4669f09a973a555550f7576d758 100644
--- a/if1632/mmsystem.spec
+++ b/if1632/mmsystem.spec
@@ -82,6 +82,13 @@ length 1226
 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 6ea4084d75c136a034c73bfe4f6de91f91ba6011..59fdbd870baecb96f218fe31a9b818b499eec8a4 100644
--- a/include/accel.h
+++ b/include/accel.h
@@ -19,4 +19,5 @@ typedef struct {
 #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 7c389f1c032b7fcd4a373e51c28c31d098dedb6e..7ff97a09c1bcf77b77b9bdfd77af4e246dbc8f59 100644
--- a/include/heap.h
+++ b/include/heap.h
@@ -36,6 +36,7 @@ extern int  HEAP_Free(MDESC **free_list, void *block);
 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 a3cd796d7a5ef576e5ca6e38a4781d541b753db1..2c56e3427f214c8017fae8994dab56a629c0cf0e 100644
--- a/include/metafile.h
+++ b/include/metafile.h
@@ -41,8 +41,14 @@ BOOL MF_MetaParam8(DC *dc, short func, short param1, short param2,
 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 192863269cbb6d8b8ad1f6ba2cc6229e1c9eeb25..1c3fcc800a3e2bed1f542d3ba017bd257f4702fb 100644
--- a/include/win.h
+++ b/include/win.h
@@ -49,6 +49,9 @@ typedef struct tagWND
     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 21898e927f3a0e5871c3b325261cc9bd0026f9e4..8253cb5343897e77478103c49e97a7fbdd95debc 100644
--- a/loader/library.c
+++ b/loader/library.c
@@ -6,8 +6,6 @@ static char Copyright[] = "Copyright  Martin Ayotte, 1994";
 /*
 #define DEBUG_MODULE
 */
-
-#ifndef WINELIB
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -15,9 +13,9 @@ static char Copyright[] = "Copyright  Martin Ayotte, 1994";
 #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 @@ FARPROC GetProcAddress(HANDLE hModule, char *proc_name)
     return (FARPROC) ret;
 }
 
-#endif /* ifndef WINELIB */
-
 /* internal dlls */
 static void 
 FillModStructBuiltIn(MODULEENTRY *lpModule, struct dll_name_table_entry_s *dll)
@@ -412,3 +408,4 @@ HMODULE ModuleFindName(MODULEENTRY *lpModule, LPCSTR lpstrName)
 {
 	return (ModuleFindHandle(lpModule, GetModuleHandle((char*)lpstrName)));
 }
+
diff --git a/loader/main.c b/loader/main.c
index 90ec7e516d914c157b38a1e451fd39e4e5737697..8161854eb729df834f24ba52a1f6a29829dd6895 100644
--- a/loader/main.c
+++ b/loader/main.c
@@ -92,6 +92,7 @@ GetFileInfo(unsigned short instance)
     return w;
 }
 
+#ifndef WINELIB
 /**********************************************************************
  *
  * Load MZ Header
@@ -104,6 +105,7 @@ void load_mz_header(int fd, struct mz_header_s *mz_header)
 	myerror("Unable to read MZ header from file");
     }
 }
+#endif
 
 int IsDLLLoaded(char *name)
 {
@@ -233,7 +235,6 @@ HINSTANCE LoadImage(char *module, int filetype, int change_dir)
     return 14;
 }
 
-
 #ifndef WINELIB
 /**********************************************************************
  *					main
@@ -395,4 +396,4 @@ void InitializeLoadedDLLs(struct w_files *wpnt)
     for( ; wpnt != final_wpnt; wpnt = wpnt->next)
 	InitDLL(wpnt);
 }
-#endif
+#endif /* #ifndef WINELIB */
diff --git a/loader/resource.c b/loader/resource.c
index 902242f221bb0367ae27b49ef858aad422c298df..7814e66b27e126b8e3bb566db50181beeff7c19b 100644
--- a/loader/resource.c
+++ b/loader/resource.c
@@ -344,7 +344,7 @@ FindResourceByNumber(struct resource_nameinfo_s *result_p,
 		    }
 #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));
@@ -478,6 +478,60 @@ FindResourceByName(struct resource_nameinfo_s *result_p,
 }
 
 
+/**********************************************************************
+ *					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]
  */
@@ -685,12 +739,26 @@ int TranslateAccelerator(HWND hWnd, HANDLE hAccel, LPMSG msg)
 #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 @@ int TranslateAccelerator(HWND hWnd, HANDLE hAccel, LPMSG msg)
 	    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 @@ HANDLE FindResource(HANDLE instance, LPSTR resource_name, LPSTR type_name)
     
     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;
     }
@@ -780,6 +851,36 @@ HANDLE FindResource(HANDLE instance, LPSTR resource_name, LPSTR type_name)
     return rh;
 }
 
+/**********************************************************************
+ *			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]
  */
@@ -851,24 +952,62 @@ HANDLE FreeResource(HANDLE hResData)
     
     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 734520a8f16fe0d8f415bf7912323ba2cc9f10ed..be39fe0c0a35221d572efc40cf805edd853250bc 100644
--- a/memory/heap.c
+++ b/memory/heap.c
@@ -195,13 +195,14 @@ HEAP_ReAlloc(MDESC **free_list, void *old_block,
 	    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.
      */
@@ -399,6 +400,22 @@ HEAP_LocalInit(unsigned short owner, void *start, int length)
     LocalHeaps = lh;
 }
 
+/**********************************************************************
+ *					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
  */
diff --git a/misc/main.c b/misc/main.c
index ae0d5c9f686efccb64448d8586658689332cd70d..f238568d376e914a48a2847d4edd59cc71d2f809 100644
--- a/misc/main.c
+++ b/misc/main.c
@@ -22,7 +22,16 @@ static char Copyright[] = "Copyright  Alexandre Julliard, 1994";
 
 #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 @@ int main( int argc, char *argv[] )
     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 @@ LONG GetWinFlags(void)
  */
 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 SetEnvironment(LPSTR lpPortName, LPSTR lpEnviron, WORD nCount)
  */
 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 6e22c5cda77408b201cac39d2a2e05f1bfcc1e05..90fc2de9b9e800b8aba675067966d9dac529081f 100644
--- a/misc/mmsystem.c
+++ b/misc/mmsystem.c
@@ -12,7 +12,24 @@ static char Copyright[] = "Copyright  Martin Ayotte, 1993";
 #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 @@ DWORD WINAPI waveInMessage(HWAVEIN hWaveIn, UINT uMessage,
 }
 
 
+/**************************************************************************
+* 				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 29e65080c5c72f7a89cc4be8eb3ab9431288ff59..7bd94881d6c52d610808a0636de05c7faa535e50 100644
--- a/misc/profile.c
+++ b/misc/profile.c
@@ -332,13 +332,13 @@ int GetProfileString (LPSTR AppName, LPSTR KeyName, LPSTR Default,
 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 92f57a40f9a9d8d31185409d918e77898f32d14c..b58d1731dd8c5854e35cb8ee0b9d3372c1b12f44 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 @@ static char Copyright[] = "Copyright Martin Ayotte, 1994";
 #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 @@ HANDLE RemoveProp(HWND hWnd, LPSTR lpStr)
     	}
 	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 @@ HANDLE RemoveProp(HWND hWnd, LPSTR lpStr)
 			(((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 @@ HANDLE RemoveProp(HWND hWnd, LPSTR lpStr)
 		lpProp = lpProp->lpNextProp;
 		}
 	GlobalUnlock(wndPtr->hProp);
+#ifdef DEBUG_PROP
    	printf("RemoveProp // Property not found !\n");
+#endif
 	return 0;
 }
 
@@ -95,7 +101,9 @@ HANDLE GetProp(HWND hWnd, LPSTR lpStr)
     	}
 	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 @@ HANDLE GetProp(HWND hWnd, LPSTR lpStr)
 			(((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 d55368d1ee3a8c0344e68d6496209553ab1858ab..0b6e55270d18d024fe7ef9020681e4891a98c3c6 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 @@ INT AboutDlgProc(HWND hWnd, WORD msg, WORD wParam, LONG lParam)
  */
 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 2b748b78c2a06090e9af9260bc00769638c282f2..e503ef9d7b18af060c2f7586f0fbe41f6eb259cb 100644
--- a/misc/stress.c
+++ b/misc/stress.c
@@ -88,7 +88,7 @@ int GetFreeFileHandles(void)
 #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 eaee32683a599c0ca66d6b30064ae5ee6e179b41..3d4500ce09e067fb3adb579791f292a791c072c1 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 c90b9e2158571184100158c443c5584f72915d41..bb83f993cc37a69be1f136e3f0bf64b6b233e9c7 100644
--- a/objects/bitblt.c
+++ b/objects/bitblt.c
@@ -66,6 +66,7 @@ BOOL BitBlt( HDC hdcDest, short xDest, short yDest, short width, short height,
 {
     int xs1, xs2, ys1, ys2;
     int xd1, xd2, yd1, yd2;
+    DWORD saverop = rop;
     DC *dcDest, *dcSrc;
 
 #ifdef DEBUG_GDI    
@@ -83,10 +84,17 @@ BOOL BitBlt( HDC hdcDest, short xDest, short yDest, short width, short height,
 	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 @@ BOOL StretchBlt( HDC hdcDest, short xDest, short yDest, short widthDest, short h
     int xd1, xd2, yd1, yd2;
     DC *dcDest, *dcSrc;
     XImage *sxi, *dxi;
+    DWORD saverop = rop;
     WORD stretchmode;
 	BOOL	flg;
 
@@ -351,10 +360,17 @@ BOOL StretchBlt( HDC hdcDest, short xDest, short yDest, short widthDest, short h
         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 6e8c1b0206ed9502472094d3480e3c72f79e2d78..b068a2a6bebe3e000cd8661a85bc18183025449d 100644
--- a/objects/bitmap.c
+++ b/objects/bitmap.c
@@ -115,6 +115,13 @@ HBITMAP CreateBitmapIndirect( BITMAP * bmp )
     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 fba3ab2ee15300b642412ec9cf56322a2989617f..63a5543be4c5bfc9c655a2664324b949e4da3dcc 100644
--- a/objects/font.c
+++ b/objects/font.c
@@ -195,6 +195,9 @@ HFONT FONT_SelectObject( DC * dc, HFONT hfont, FONTOBJ * font )
 	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 5ff49ed3617cbfc7d345f9d0130b9d51c70c0571..544e6e48272e4d173bbeba06dc1d1d70d9a0c92d 100644
--- a/objects/metafile.c
+++ b/objects/metafile.c
@@ -431,6 +431,11 @@ void PlayMetaFileRecord(HDC hdc, HANDLETABLE *ht, METARECORD *mr,
 		     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))));
@@ -798,6 +803,41 @@ BOOL MF_CreatePenIndirect(DC *dc, HPEN hPen, LOGPEN *logpen)
 }
 
 
+/******************************************************************
+ *         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
  */
@@ -850,3 +890,24 @@ BOOL MF_MetaPoly(DC *dc, short func, LPPOINT pt, short count)
     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 93071569c21ecc593bd2caf0ce521029a081d81b..002257f7481b9c1eb2aa8502042e7d4101560278 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 @@ HANDLE GlobalReAlloc(HANDLE hMem, DWORD new_size, WORD flags)
 	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 0000000000000000000000000000000000000000..d9d9978930aac5bca8f6ddcd8d1e883565c4a20f
--- /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 c5720cb5955f2efda64c1bd6da43b824380f564f..53412bc94ce9d4fcc3e90cdac7059a60a620462e 100644
--- a/windows/Imakefile
+++ b/windows/Imakefile
@@ -14,6 +14,7 @@ SRCS = \
 	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 3dfe56ef66cebd313c1a31762a6df334b31ca253..58216b4b7999067a29a38b147f57eb6584c78bbf 100644
--- a/windows/dce.c
+++ b/windows/dce.c
@@ -11,6 +11,7 @@ static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
 #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 @@ HDC GetDCEx( HWND hwnd, HRGN hrgnClip, DWORD flags )
     DCE * dce;
     DC * dc;
     WND * wndPtr;
+    ICONALLOC   *lpico;
     
     if (hwnd)
     {
@@ -181,6 +183,25 @@ HDC GetDCEx( HWND hwnd, HRGN hrgnClip, DWORD flags )
 	    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 @@ HDC GetDCEx( HWND hwnd, HRGN hrgnClip, DWORD flags )
     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 2434840e5ce36ecfa9516ee9ed17bc9c75e4217a..e91e3a8368fe241445aa67c5013eccd89d7bb525 100644
--- a/windows/defwnd.c
+++ b/windows/defwnd.c
@@ -38,11 +38,9 @@ void DEFWND_SetText( HWND hwnd, LPSTR text )
     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 @@ LONG DefWindowProc( HWND hwnd, WORD msg, WORD wParam, LONG lParam )
     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 b873befc71b88bf9ab9a12ee473cdfbb699ce921..04358df59283311834d155891075b978bf31c61b 100644
--- a/windows/event.c
+++ b/windows/event.c
@@ -23,6 +23,11 @@ typedef char *XPointer;
 #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 @@ static XContext winContext = 0;
 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 @@ static void EVENT_Expose( HWND hwnd, XExposeEvent *event )
     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 @@ static void EVENT_key( HWND hwnd, XKeyEvent *event )
     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 @@ static void EVENT_key( HWND hwnd, XKeyEvent *event )
 	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 @@ static void EVENT_key( HWND hwnd, XKeyEvent *event )
     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 @@ static void EVENT_key( HWND hwnd, XKeyEvent *event )
 	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 dda491a1df2d0b148b81a1ff517e3d2dd5f7b626..0d2392f503ceecd71944306d849156051e43269c 100644
--- a/windows/graphics.c
+++ b/windows/graphics.c
@@ -20,6 +20,15 @@ static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
 
 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 @@ BOOL Ellipse( HDC hdc, int left, int top, int right, int bottom )
     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 @@ BOOL Rectangle( HDC hdc, int left, int top, int right, int bottom )
 	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 0000000000000000000000000000000000000000..dc9648e41450948e84caea01563deda893debaa8
--- /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 bdde31ebf6740dfccfa040818bf1cc8fbb632371..e8181cb107af93e378a8431d9efa81dd99009cfb 100644
--- a/windows/keyboard.c
+++ b/windows/keyboard.c
@@ -12,6 +12,7 @@ static char Copyright[] = "Copyright  Bob Amstadt, 1993";
 extern BOOL MouseButtonsStates[3];
 extern BOOL AsyncMouseButtonsStates[3];
 extern BYTE KeyStateTable[256];
+extern BYTE AsyncKeyStateTable[256];
 
 /**********************************************************************
  *		GetKeyState			[USER.106]
@@ -26,7 +27,7 @@ int GetKeyState(int keycode)
 		case VK_RBUTTON:
 		    return MouseButtonsStates[2];
 		default:
-		    return 0;
+		    return KeyStateTable[keycode];
 		}
 }
 
@@ -35,25 +36,26 @@ int GetKeyState(int keycode)
  */
 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 @@ int GetAsyncKeyState(int nKey)
 		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 08f45bba119284ec4790ace368a78a184d1b3902..0835c8a8ef52a44ae0fca532c9372b63f3bad829 100644
--- a/windows/mdi.c
+++ b/windows/mdi.c
@@ -296,6 +296,8 @@ LONG MDIRestoreChild(HWND parent, MDICLIENTINFO *ci)
     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 @@ DefMDIChildProc(HWND hwnd, WORD message, WORD wParam, LONG lParam)
 	    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 a356f519c01a30e0581f0b8534ce0a722b681b20..dfafcdef88d20d1be31484bc36f37e35f3227437 100644
--- a/windows/message.c
+++ b/windows/message.c
@@ -387,6 +387,12 @@ void hardware_event( WORD message, WORD wParam, LONG lParam,
       /* 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 e31a8752d3dd1d618c35f368e349046bd277913e..f7998265c9d134340fe83a5b5f6124812936e732 100644
--- a/windows/nonclient.c
+++ b/windows/nonclient.c
@@ -647,6 +647,47 @@ void NC_DoNCPaint( HWND hwnd, HRGN hrgn, BOOL active, BOOL suppress_menupaint )
 }
 
 
+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 @@ LONG NC_HandleSysCommand( HWND hwnd, WORD wParam, POINT pt )
 	break;
 
     case SC_MINIMIZE:
-	ShowWindow( hwnd, SW_MINIMIZE );
+	ICON_Iconify( hwnd );
+	/*ShowWindow( hwnd, SW_MINIMIZE );*/
 	break;
 
     case SC_MAXIMIZE:
@@ -1191,6 +1233,7 @@ LONG NC_HandleSysCommand( HWND hwnd, WORD wParam, POINT pt )
 	break;
 
     case SC_RESTORE:
+	ICON_Deiconify(hwnd);
 	ShowWindow( hwnd, SW_RESTORE );
 	break;
 
diff --git a/windows/painting.c b/windows/painting.c
index 36c72e722b54d2a1f13ea6ad63d42387d933e177..65a17ca6ae2e19adac36d00c861fd2596df274bd 100644
--- a/windows/painting.c
+++ b/windows/painting.c
@@ -10,6 +10,7 @@ static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
 
 #include "win.h"
 #include "message.h"
+#include "gdi.h"
 
   /* Last CTLCOLOR id */
 #define CTLCOLOR_MAX   CTLCOLOR_STATIC
@@ -43,6 +44,13 @@ HDC BeginPaint( HWND hwnd, LPPAINTSTRUCT lps )
 
     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 041c2274c01f74ab6af6b66dc829157c8ae4a59b..cc11dd19f9bc8732398d1bc78bf4d3dec54a82e7 100644
--- a/windows/win.c
+++ b/windows/win.c
@@ -17,6 +17,7 @@ static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
 #include "dce.h"
 #include "sysmetrics.h"
 #include "scroll.h"
+#include "icon.h"
 
 extern Colormap COLOR_WinColormap;
 
@@ -244,7 +245,8 @@ HWND CreateWindowEx( DWORD exStyle, LPSTR className, LPSTR windowName,
     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 @@ HWND CreateWindowEx( DWORD exStyle, LPSTR className, LPSTR windowName,
        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 @@ HWND CreateWindowEx( DWORD exStyle, LPSTR className, LPSTR windowName,
 		   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 @@ HWND CreateWindowEx( DWORD exStyle, LPSTR className, LPSTR windowName,
     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 ) );