Release 960302

Sat Mar  2 18:19:06 1996  Alexandre Julliard  <julliard@lrc.epfl.ch>

	* [controls/scroll.c]
	Fixed SCROLL_THUMB painting fixes from Alex Korobka to store the
 	current tracking window.

	* [files/file.c]
	Fixed two file descriptor leaks in FILE_OpenFile().

	* [if1632/relay32.c] [loader/module.c] [loader/pe_image.c]
	  [tools/build.c]
	Replaced LOADEDFILEINFO structure by OFSTRUCT.

	* [memory/atom.c]
	Reload the pointer to the atom table in ATOM_GetTable() and
 	ATOM_AddAtom() in case the LOCAL_Alloc() calls caused the table to
 	move in linear memory.

Fri Mar  1 11:57:13 1996  Frans van Dorsselaer <dorssel@rulhm1.leidenuniv.nl>

	* [include/callback.h]
	Added support for CallWordBreakProc().

	* [controls/edit.c]
	New caret handling (really efficient / fast).
	Implemented EM_SETWORDBREAKPROC and EM_GETWORDBREAKPROC.
	Fixed EM_SETFONT so it now also creates a proper new caret.

Wed Feb 28 22:03:34 1996  Daniel Schepler  <daniel@frobnitz.wustl.edu>

	* [controls/desktop.c] [misc/main.c] [windows/event.c] [windows/win.c]
	Added WM_DELETE protocol to top-level windows.

	* [controls/scroll.c]
	Fixed a problem which caused slow scrolling to continue	uncontrollably.

	* [misc/exec.c]
	Implemented ExitWindows().

	* [windows/win.c]
	Set top-level owned windows to be transient.

Wed Feb 28 19:13:22 1996  Ulrich Schmid  <uschmid@mail.hh.provi.de>

	* [programs/progman/*]
	Added a program manager.

Wed Feb 28 18:38:01 1996  Duncan C Thomson <duncan@spd.eee.strath.ac.uk>

	* [resources/sysres_Eo.c]
	Added support for Esperanto [Eo] language.

Wed Feb 28 00:23:00 1996  Thomas Sandford <t.d.g.sandford@prds-grn.demon.co.uk>

	* [if1632/user32.spec]
	Added EndDialog, GetDlgItem, GetDlgItemInt, SetDlgItemInt,

	* [win32/init.c]
	Added task.h to includes. GetModuleHandleA() - return hInstance
	if called with NULL parameter. Freecell needs this. NOTE this
	may indicate a problem with differentiation between hModule and
	hInstance within Wine.

	* [win32/resource.c]
	FindResource32() and LoadResource32() - Removed #if 0's around
	conversion from hInstance to hModule. See remarks above.

	* [win32/string32.c]
	WIN32_UniLen() - removed stray semicolon.

Tue Feb 27 21:05:18 1996  Jim Peterson <jspeter@birch.ee.vt.edu>
	
	* [windows/caret.c]
	Set blink rate with call to GetProfileInt().

	* [rc/winerc.c]
	In new_style(), made initial flag settings WS_CHILD | WS_VISIBLE
 	instead of 0.  This seems to correspond to Borland's defaults, and
 	the flags can be unset by using the (rather obtuse) "| NOT WS_CHILD"
	or "| NOT WS_VISIBLE" technique in the *.rc file.

	* [win32/time.c]
	In GetLocalTime() and GetSystemTime(), used tv_sec field of result
 	returned by gettimeofday() instead of making second call to
 	time().  This eliminates clock jitter if the seconds change
 	between the two calls (rare, but possible).

	* [include/wintypes.h]
	Added "#define _far" and "#define _pascal".

	* [windows/win.c]
	Added function GetDesktopHwnd().

	* [include/xmalloc.h]
	Removed the '#ifdef HAVE_STDLIB_H' structure, since it seemed to
 	have been removed from 'configure', and was causing redefinition
 	warnings.

Tue Feb 27 19:31:11 1996  Albrecht Kleine <kleine@ak.sax.de>

	* [windows/winpos.c] 
	Added RDW_ALLCHILDREN flag in SetWindowPos (handling SWP_FRAMECHANGED)
	to force a repaint when setting menu bars with different rows.

Sun Feb 25 21:15:00 1996 Alex Korobka <alex@phm30.pharm.sunysb.edu>

	* [windows/syscolors.c] [controls/scroll.c]
	Fixed DrawFocusRect pen and SCROLL_THUMB painting.
diff --git a/controls/edit.c b/controls/edit.c
index 73ce404..e952589 100644
--- a/controls/edit.c
+++ b/controls/edit.c
@@ -19,7 +19,7 @@
 #include "stddebug.h"
 #include "debug.h"
 #include "xmalloc.h"
-
+#include "callback.h"
 
 #ifdef WINELIB32
 #define NOTIFY_PARENT(hWndCntrl, wNotifyCode) \
@@ -71,8 +71,15 @@
     int ClientWidth;         /* computed from the window's ClientRect */
     int ClientHeight;        /* ditto */
     char PasswordChar;       /* The password character */
+    EDITWORDBREAKPROC WordBreakProc;
+    BOOL WeOwnCaret;         /* Do we own the caret ? */
+    int CaretPrepareCount;   /* Did we already prepare the caret ? */
+    BOOL CaretHidden;        /* Did we hide the caret during painting ? */
+    int oldWndCol;           /* WndCol before we started painting */
+    int oldWndRow;           /* ditto for WndRow */
 } EDITSTATE;
 
+
 #define EditBufStartLen(hwnd) (GetWindowLong(hwnd,GWL_STYLE) & ES_MULTILINE \
 			       ? EDITLEN : ENTRYLEN)
 #define CurrChar (EDIT_TextLine(hwnd, es->CurrLine) + es->CurrCol)
@@ -98,6 +105,7 @@
 
 #define SWAP_INT(x,y) do { int temp = (x); (x) = (y); (y) = temp; } while(0)
 
+
 /*********************************************************************
  *  EDIT_HeapAlloc
  *
@@ -197,6 +205,105 @@
 }
 
 /*********************************************************************
+ *  EDIT_CaretPrepare
+ *
+ *  Save the caret state before any painting is done.
+ */
+static void EDIT_CaretPrepare(HWND hwnd)
+{
+    EDITSTATE *es = EDIT_GetEditState(hwnd);
+
+    if (!es) return;
+
+    if (!es->CaretPrepareCount)
+    {
+	es->CaretHidden = FALSE;
+	es->oldWndCol = es->WndCol;
+	es->oldWndRow = es->WndRow;
+    }
+
+    es->CaretPrepareCount++;
+}
+
+/*********************************************************************
+ *  EDIT_CaretHide
+ *
+ *  Called before some painting is done.
+ */
+static void EDIT_CaretHide(HWND hwnd)
+{
+    EDITSTATE *es = EDIT_GetEditState(hwnd);
+
+    if (!es) return;
+    if (!es->WeOwnCaret) return;
+    if (!es->CaretPrepareCount) return;
+    
+    if (!es->CaretHidden)
+    {
+    	HideCaret(hwnd);
+    	es->CaretHidden = TRUE;
+    }
+}
+
+/*********************************************************************
+ *  EDIT_CaretUpdate
+ *
+ *  Called after all painting is done.
+ */
+static void EDIT_CaretUpdate(HWND hwnd)
+{
+    EDITSTATE *es = EDIT_GetEditState(hwnd);
+
+    if (!es) return;
+    if (!es->CaretPrepareCount) return;
+    
+    es->CaretPrepareCount--;
+    
+    if (es->CaretPrepareCount) return;
+    if (!es->WeOwnCaret) return;
+
+    if ((es->WndCol != es->oldWndCol) || (es->WndRow != es->oldWndRow))
+	SetCaretPos(es->WndCol, es->WndRow * es->txtht);
+
+    if (es->CaretHidden)
+    {
+	ShowCaret(hwnd);
+	es->CaretHidden = FALSE;
+    }
+}
+
+/*********************************************************************
+ *  EDIT_WordBreakProc
+ *
+ *  Find the beginning of words.
+ */
+static int CALLBACK EDIT_WordBreakProc(char * pch, int ichCurrent,
+					int cch, int code)
+{
+    dprintf_edit(stddeb, "EDIT_WordBreakProc: pch=%p, ichCurrent=%d"
+	", cch=%d, code=%d\n", pch, ichCurrent, cch, code);
+
+    dprintf_edit(stddeb, "string=%s\n", pch);
+    return 0;
+}
+
+/*********************************************************************
+ *  EDIT_CallWordBreakProc
+ *
+ *  Call appropriate WordBreakProc (internal or external).
+ */
+static int CALLBACK EDIT_CallWordBreakProc(HWND hwnd, char *pch, 
+					int ichCurrent, int cch, int code)
+{
+    EDITSTATE *es = EDIT_GetEditState(hwnd);
+    
+    if (es->WordBreakProc) {
+	/* FIXME: do some stuff to make pch a SEGPTR */
+	return CallWordBreakProc((FARPROC)es->WordBreakProc, (LONG)pch, ichCurrent, cch, code);
+    } else return EDIT_WordBreakProc(pch, ichCurrent, cch, code);
+}
+
+/*********************************************************************
  *  EDIT_GetNextTabStop
  *
  *  Return the next tab stop beyond _pcol_.
@@ -466,6 +573,8 @@
 
     dprintf_edit(stddeb,"EDIT_WriteText lp=%s, off=%d, len=%d, row=%d, col=%d, reverse=%d\n", lp, off, len, row, col, reverse);
 
+    EDIT_CaretHide(hwnd);
+
     if( off < 0 ) {
       len += off;
       col -= off;
@@ -832,6 +941,8 @@
 
     if (IsWindowVisible(hwnd))
     {
+	EDIT_CaretHide(hwnd);    
+
 	/* adjust client bottom to nearest whole line */
 	GetClientRect(hwnd, &rc);
 	rc.bottom = (rc.bottom / es->txtht) * es->txtht;
@@ -1196,6 +1307,8 @@
 
     if (IsWindowVisible(hwnd))
     {
+	EDIT_CaretHide(hwnd);
+
 	/* adjust client bottom to nearest whole line */
 	GetClientRect(hwnd, &rc);
 	rc.bottom = (rc.bottom / es->txtht) * es->txtht;
@@ -1747,7 +1860,6 @@
     NOTIFY_PARENT(hwnd, EN_UPDATE);
 
     /* re-adjust textwidth, if necessary, and redraw line */
-    HideCaret(hwnd);
     if (IsMultiLine(hwnd) && es->wlines > 1)
     {
 	es->textwidth = MAX(es->textwidth,
@@ -1775,8 +1887,6 @@
 	    rc.top = es->WndRow * es->txtht;
 	InvalidateRect(hwnd, &rc, FALSE);
 
-	SetCaretPos(es->WndCol, es->WndRow * es->txtht);
-	ShowCaret(hwnd);
 	UpdateWindow(hwnd);
 	NOTIFY_PARENT(hwnd, EN_CHANGE);
 	return;
@@ -1795,8 +1905,6 @@
     es->CurrCol++;
     EDIT_SetAnchor(hwnd, es->CurrLine, es->CurrCol);
     EDIT_WriteTextLine(hwnd, NULL, es->wtop + es->WndRow);
-    SetCaretPos(es->WndCol, es->WndRow * es->txtht);
-    ShowCaret(hwnd);
     NOTIFY_PARENT(hwnd, EN_CHANGE);
     dprintf_edit(stddeb,"KeyTyped O.K.\n");
 }
@@ -2150,6 +2258,14 @@
     es->PaintBkgd = TRUE;
     if (lParam) UpdateWindow(hwnd);
     EDIT_RecalcSize(hwnd,es);
+
+    if (es->WeOwnCaret)
+    {
+	EDIT_CaretHide(hwnd);
+	DestroyCaret();
+	CreateCaret(hwnd, 0, 2, es->txtht);
+	SetCaretPos(es->WndCol, es->WndRow * es->txtht);
+    }
 }
 
 /*********************************************************************
@@ -2186,6 +2302,8 @@
     RECT rc;
     EDITSTATE *es = EDIT_GetEditState(hwnd);
 
+    EDIT_CaretHide(hwnd);
+
     hdc = BeginPaint(hwnd, &ps);
     GetClientRect(hwnd, &rc);
     IntersectClipRect(hdc, rc.left, rc.top, rc.right, rc.bottom);
@@ -2237,6 +2355,13 @@
     /* --- text buffer */
     es->MaxTextLen = MAXTEXTLEN + 1;
     es->PasswordChar = '*';
+    
+    es->WordBreakProc = NULL;
+    
+    /* Caret stuff */
+    es->CaretPrepareCount = 1;
+    es->CaretHidden = FALSE;
+    es->WeOwnCaret = FALSE;
     /*
      * Hack - If there is no local heap then hwnd should be a globalHeap block
      * and the local heap needs to be initilised to the same size(minus something)
@@ -2384,12 +2509,11 @@
  */
 static void EDIT_WM_VScroll(HWND hwnd, WORD wParam, LONG lParam)
 {
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
-
+/*
+ *    EDITSTATE *es = EDIT_GetEditState(hwnd);
+ */
     if (IsMultiLine(hwnd))
     {
-	HideCaret(hwnd);
-
 	switch (wParam)
 	{
 	case SB_LINEUP:
@@ -2403,9 +2527,6 @@
 	    break;
 	}
     }
-    
-    SetCaretPos(es->WndCol, es->WndRow);
-    ShowCaret(hwnd);
 }
 
 /*********************************************************************
@@ -2413,16 +2534,13 @@
  */
 static void EDIT_WM_HScroll(HWND hwnd, WORD wParam, LONG lParam)
 {
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
-
+/*
+ *    EDITSTATE *es = EDIT_GetEditState(hwnd);
+ */
     switch (wParam)
     {
     case SB_LINEUP:
     case SB_LINEDOWN:
-	HideCaret(hwnd);
-
-	SetCaretPos(es->WndCol, es->WndRow * es->txtht);
-	ShowCaret(hwnd);
 	break;
     }
 }
@@ -2489,11 +2607,11 @@
  */
 static void EDIT_WM_MouseMove(HWND hwnd, WORD wParam, LONG lParam)
 {
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
-
+/*
+ *    EDITSTATE *es = EDIT_GetEditState(hwnd);
+ */
     if (!(wParam & MK_LBUTTON)) return;
 
-    HideCaret(hwnd);
     if (ButtonDown)
     {
 	TextMarking = TRUE;
@@ -2501,11 +2619,7 @@
     }
 
     if (TextMarking)
-    {
 	EDIT_ExtendSel(hwnd, LOWORD(lParam), HIWORD(lParam));
-        SetCaretPos(es->WndCol, es->WndRow * es->txtht);
-    }
-    ShowCaret(hwnd);
 }
 
 /*********************************************************************
@@ -2548,7 +2662,6 @@
 
     dprintf_edit(stddeb,"EDIT_WM_KeyDown: key=%x\n", wParam);
 
-    HideCaret(hwnd);
     switch (wParam)
     {
     case VK_UP:
@@ -2627,7 +2740,6 @@
         break;
 
     default:
-        ShowCaret(hwnd);
         return;
     }
 
@@ -2641,8 +2753,6 @@
     } else {
         EDIT_SetAnchor(hwnd, es->CurrLine, es->CurrCol);
     }
-    SetCaretPos(es->WndCol, es->WndRow * es->txtht);
-    ShowCaret(hwnd);
 }
 
 /*********************************************************************
@@ -2689,6 +2799,8 @@
     int len;
     EDITSTATE *es = EDIT_GetEditState(hwnd);
 
+    EDIT_CaretPrepare(hwnd);
+
     switch (uMsg) {
     case EM_CANUNDO:
 	lResult = (LONG)es->hDeletedText;
@@ -2733,7 +2845,6 @@
 	break;
 
     case EM_GETPASSWORDCHAR:
-        /* FIXME: is this the right place to return the character? */
         lResult = es->PasswordChar;
 	break;
 
@@ -2746,7 +2857,8 @@
 	break;
 
     case EM_GETWORDBREAKPROC:
-	fprintf(stdnimp,"edit: cannot process EM_GETWORDBREAKPROC message\n");
+	dprintf_edit(stddeb, "EM_GETWORDBREAKPROC\n");
+	lResult = (LONG)es->WordBreakProc;
 	break;
 
     case EM_LIMITTEXT:
@@ -2778,18 +2890,12 @@
 	break;
 
     case EM_REPLACESEL:
-	HideCaret(hwnd);
 	EDIT_ReplaceSel(hwnd, lParam);
-	SetCaretPos(es->WndCol, es->WndRow * es->txtht);
-	ShowCaret(hwnd);
 	break;
 
     case EM_SETHANDLE:
-	HideCaret(hwnd);
 	EDIT_ClearDeletedText(hwnd);
 	EDIT_SetHandleMsg(hwnd, wParam);
-	SetCaretPos(es->WndCol, es->WndRow * es->txtht);
-	ShowCaret(hwnd);
 	break;
 
     case EM_SETMODIFY:
@@ -2810,10 +2916,7 @@
 	break;
 
     case EM_SETSEL:
-	HideCaret(hwnd);
 	EDIT_SetSelMsg(hwnd, wParam, lParam);
-	SetCaretPos(es->WndCol, es->WndRow * es->txtht);
-	ShowCaret(hwnd);
 	break;
 
     case EM_SETTABSTOPS:
@@ -2821,18 +2924,18 @@
 	break;
 
     case EM_SETWORDBREAKPROC:
-	fprintf(stdnimp,"edit: cannot process EM_SETWORDBREAKPROC message\n");
+	dprintf_edit(stddeb, "EM_SETWORDBREAKPROC, lParam=%08lx\n",
+			(DWORD)lParam);
+	es->WordBreakProc = (EDITWORDBREAKPROC)lParam;
 	break;
 
     case EM_UNDO:
-	HideCaret(hwnd);
 	lResult = EDIT_UndoMsg(hwnd);
-	SetCaretPos(es->WndCol, es->WndRow * es->txtht);
-	ShowCaret(hwnd);
 	break;
 
     case WM_GETDLGCODE:
-        return DLGC_HASSETSEL | DLGC_WANTCHARS | DLGC_WANTARROWS;
+        lResult = DLGC_HASSETSEL | DLGC_WANTCHARS | DLGC_WANTARROWS;
+	break;
 
     case WM_CHAR:
 	EDIT_WM_Char(hwnd, wParam);
@@ -2895,6 +2998,7 @@
 	dprintf_edit(stddeb, "WM_KILLFOCUS\n");
 	es->HaveFocus = FALSE;
 	DestroyCaret();
+	es->WeOwnCaret = FALSE;
 	if (SelMarked(es))
             if(GetWindowLong(hwnd,GWL_STYLE) & ES_NOHIDESEL)
 	        EDIT_UpdateSel(hwnd);
@@ -2904,12 +3008,9 @@
 	break;
 
     case WM_LBUTTONDOWN:
-	HideCaret(hwnd);
 	SetFocus(hwnd);
 	SetCapture(hwnd);
 	EDIT_WM_LButtonDown(hwnd, wParam, lParam);
-	SetCaretPos(es->WndCol, es->WndRow * es->txtht);
-	ShowCaret(hwnd);
 	break;
 
     case WM_LBUTTONUP:
@@ -2945,16 +3046,14 @@
 	es->HaveFocus = TRUE;
 	if (SelMarked(es)) EDIT_UpdateSel(hwnd);
 	CreateCaret(hwnd, 0, 2, es->txtht);
+	es->WeOwnCaret = TRUE;
 	SetCaretPos(es->WndCol, es->WndRow * es->txtht);
-	ShowCaret(hwnd);
+	es->CaretHidden = TRUE;
 	NOTIFY_PARENT(hwnd, EN_SETFOCUS);
 	break;
 
     case WM_SETFONT:
-	HideCaret(hwnd);
 	EDIT_WM_SetFont(hwnd, wParam, lParam);
-	SetCaretPos(es->WndCol, es->WndRow * es->txtht);
-	ShowCaret(hwnd);
 	break;
 #if 0
     case WM_SETREDRAW:
@@ -2988,6 +3087,8 @@
 	break;
     }
 
+    EDIT_CaretUpdate(hwnd);
+
     return lResult;
 }