Release 960421
Sat Apr 20 23:23:16 1996 Robert Pouliot <krynos@qbc.clic.net>
* [resources/sysres_Fr.rc] [resources/TODO]
Made changes for Choose_Color dialog.
Sat Apr 20 15:43:49 1996 Alexandre Julliard <julliard@lrc.epfl.ch>
* [controls/button.c]
Fixed test that got miscompiled by some old gcc versions.
* [memory/local.c]
Fixed the layout of handle tables so that moveable handle entries
can be freed on LocalFree().
Implemented LocalFlags(), LocalCountFree(), LocalHandleDelta() and
GetHeapSpaces().
* [misc/main.c] [ANNOUNCE]
Update the list of contributors. Please let me know if I forgot
someone.
Fri Apr 19 20:07:20 1996 Frans van Dorsselaer <dorssel@rulhm1.leidenuniv.nl>
* [controls/edit.c] [controls/EDIT.TODO]
Fixed EM_SETHANDLE / WM_CREATE / EDIT_MakeFir() buffer allocation.
Fixed ES_NOHIDESEL / WM_MOUSEMOVE / WM_LBUTTONDOWN implementation.
Added WM_ENABLE implementation (gray text).
Fixed buffer > 32767 bug.
Fixed argument types / typecasting.
Faster selection (re)drawing.
Thu Apr 18 13:38:26 1996 Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>
* [misc/registry.c] [include/winreg.h]
Changed savefile format again to human readable/editable
(UNICODE chars >0xff are specified by \uXXXX, data by XX).
Has now global / local registry databases (including merging them).
HKEY_CLASSES_ROOT == HKEY_LOCAL_MACHINE\\SOFTWARE\\Classes.
HKEY_CURRENT_USER == HKEY_USERS\\<loginname>.
* [misc/comm.c]
Allow " " as COMx: ... spec delimiter too.
(AOL-CD setup.exe tries to initialize modem2 as "9600,x,x x" (can't
remember the x).
Thu Apr 18 09:00:00 1996 Alex Korobka <alex@phm30.pharm.sunysb.edu>
* [windows/mdi.c]
Miscellaneous changes.
* [windows/winpos.c]
Use BitBlt whenever possible in SetWindowPos.
* [windows/painting.c]
Fix incompatibilities with hrgnUpdate being 1.
Wed Apr 17 19:19:22 1996 Albrecht Kleine <kleine@ak.sax.de>
* [misc/commdlg.c]
Many bugfixes in ChooseColor dialog.
Added a user defined dialog title in FileOpen-/FileSave- dialog.
* [misc/commdlg.c][include/commdlg.h]
[if1632/commdlg.spec][if1632/winprocs.spec]
Introduced dialog-, callback- and enum- stub functions
for ChooseFont dialog
Wed Apr 17 19:08:38 1996 Niels de Carpentier <niels@cindy.et.tudelft.nl>
* [objects/metafile.c] [include/metafile.h] [if1632/gdi.spec]
Implemented EnumMetaFile and CopyMetaFile. Removed METAFILE struct.
Implemented META_STRETCHDIB in PlayMetaFileRecord, several bug
fixes.
* [windows/winpos.c]
Don't try to hide the window if it's already hidden.
* [windows/message.c]
Let MSG_PeekHardwareMsg fill the message queue with events if
it's empty.
Wed Apr 17 17:54:04 1996 Tristan Tarrant <tst@sthinc.demon.co.uk>
* [resources/sysres_It.rc]
Updated to support the new CHOOSE_COLOR_DIALOG.
Tue Apr 16 11:50:00 1996 Anand Kumria <akumria@ozemail.com.au>
* [if1632/Makefile] [if1632/relay.c] [if1631/w32sys.spec]
[include/w32sys.h] [include/dlls.h]
[misc/Makefile] [misc/w32sys.c]
W32SYS.DLL partially implemented.
diff --git a/windows/winpos.c b/windows/winpos.c
index 524f285..09ad76a 100644
--- a/windows/winpos.c
+++ b/windows/winpos.c
@@ -20,16 +20,18 @@
/* #define DEBUG_WIN */
#include "debug.h"
+#define SWP_NOPOSCHANGE (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
+
/* ----- external functions ----- */
void FOCUS_SwitchFocus( HWND , HWND );
+HRGN DCE_GetVisRgn( HWND, WORD );
/* ----- internal variables ----- */
static HWND hwndActive = 0; /* Currently active window */
static HWND hwndPrevActive = 0; /* Previously active window */
-
/***********************************************************************
* WINPOS_FindIconPos
*
@@ -424,6 +426,7 @@
switch(cmd)
{
case SW_HIDE:
+ if (!wasVisible) return FALSE;
swpflags |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE |
SWP_NOACTIVATE | SWP_NOZORDER;
break;
@@ -1040,6 +1043,129 @@
return hwndInsertAfter;
}
+/***********************************************************************
+ * WINPOS_SizeMoveClean
+ *
+ * Make window look nice without excessive repainting
+ *
+ * the pain:
+ *
+ * visible regions are in window coordinates
+ * update regions are in window client coordinates
+ * client and window rectangles are in parent client coordinates
+ */
+static void WINPOS_SizeMoveClean(WND* Wnd, HRGN oldVisRgn, LPRECT lpOldWndRect, LPRECT lpOldClientRect, BOOL bNoCopy )
+{
+ /* visible regions are in window coordinates */
+
+ HRGN newVisRgn = DCE_GetVisRgn(Wnd->hwndSelf, DCX_WINDOW | DCX_CLIPSIBLINGS );
+ HRGN dirtyRgn = CreateRectRgn(0,0,0,0);
+ int other, my;
+
+ dprintf_win(stddeb,"cleaning up...new wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i)\n\
+\t\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
+ Wnd->rectWindow.left, Wnd->rectWindow.top, Wnd->rectWindow.right, Wnd->rectWindow.bottom,
+ lpOldWndRect->left, lpOldWndRect->top, lpOldWndRect->right, lpOldWndRect->bottom,
+ Wnd->rectClient.left,Wnd->rectClient.top,Wnd->rectClient.right,Wnd->rectClient.bottom,
+ lpOldClientRect->left,lpOldClientRect->top,lpOldClientRect->right,lpOldClientRect->bottom);
+
+ CombineRgn( dirtyRgn, newVisRgn, 0, RGN_COPY);
+
+ if( !bNoCopy )
+ {
+ HRGN hRgn = CreateRectRgn( lpOldClientRect->left - lpOldWndRect->left, lpOldClientRect->top - lpOldWndRect->top,
+ lpOldClientRect->right - lpOldWndRect->left, lpOldClientRect->bottom - lpOldWndRect->top);
+ CombineRgn( newVisRgn, newVisRgn, oldVisRgn, RGN_AND );
+ CombineRgn( newVisRgn, newVisRgn, hRgn, RGN_AND );
+ DeleteObject(hRgn);
+ }
+
+ /* map regions to the parent client area */
+
+ OffsetRgn(dirtyRgn, Wnd->rectWindow.left, Wnd->rectWindow.top);
+ OffsetRgn(oldVisRgn, lpOldWndRect->left, lpOldWndRect->top);
+
+ /* compute invalidated region outside Wnd - (in client coordinates of the parent window) */
+
+ other = CombineRgn(dirtyRgn, oldVisRgn, dirtyRgn, RGN_DIFF);
+
+ /* map visible region to the Wnd client area */
+
+ OffsetRgn( newVisRgn, Wnd->rectWindow.left - Wnd->rectClient.left,
+ Wnd->rectWindow.top - Wnd->rectClient.top );
+
+ /* substract previously invalidated region from the Wnd visible region */
+
+ my = (Wnd->hrgnUpdate > 1)? CombineRgn( newVisRgn, newVisRgn, Wnd->hrgnUpdate, RGN_DIFF)
+ : COMPLEXREGION;
+
+ if( bNoCopy ) /* invalidate Wnd visible region */
+ {
+ if (my != NULLREGION) RedrawWindow( Wnd->hwndSelf, NULL, newVisRgn, RDW_INVALIDATE |
+ RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE );
+ }
+ else /* bitblt old client area */
+ {
+ HDC hDC;
+ int update;
+ HRGN updateRgn;
+
+ /* client rect */
+
+ updateRgn = CreateRectRgn( 0,0, Wnd->rectClient.right - Wnd->rectClient.left,
+ Wnd->rectClient.bottom - Wnd->rectClient.top );
+
+ /* clip visible region with client rect */
+
+ my = CombineRgn( newVisRgn, newVisRgn, updateRgn, RGN_AND );
+
+ /* substract result from client rect to get region that won't be copied */
+
+ update = CombineRgn( updateRgn, updateRgn, newVisRgn, RGN_DIFF );
+
+ /* Blt valid bits using parent window DC */
+
+ if( my != NULLREGION )
+ {
+ int xfrom = lpOldClientRect->left;
+ int yfrom = lpOldClientRect->top;
+ int xto = Wnd->rectClient.left;
+ int yto = Wnd->rectClient.top;
+
+ /* check if we can skip copying */
+
+ if( xfrom != xto || yfrom != yto )
+ {
+ /* compute clipping region in parent client coordinates */
+
+ OffsetRgn( newVisRgn, Wnd->rectClient.left, Wnd->rectClient.top);
+ CombineRgn( oldVisRgn, oldVisRgn, newVisRgn, RGN_OR );
+
+ hDC = GetDCEx( Wnd->parent->hwndSelf, oldVisRgn, DCX_INTERSECTRGN | DCX_CACHE | DCX_CLIPSIBLINGS);
+
+ BitBlt(hDC, xto, yto, lpOldClientRect->right - lpOldClientRect->left + 1,
+ lpOldClientRect->bottom - lpOldClientRect->top + 1,
+ hDC, xfrom, yfrom, SRCCOPY );
+
+ ReleaseDC( Wnd->parent->hwndSelf, hDC);
+ }
+ }
+
+ if( update != NULLREGION )
+ RedrawWindow( Wnd->hwndSelf, NULL, updateRgn, RDW_INVALIDATE |
+ RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE );
+ DeleteObject( updateRgn );
+ }
+
+ /* erase uncovered areas */
+
+ if( other != NULLREGION )
+ RedrawWindow( Wnd->parent->hwndSelf, NULL, dirtyRgn,
+ RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE );
+
+ DeleteObject(dirtyRgn);
+ DeleteObject(newVisRgn);
+}
/***********************************************************************
* WINPOS_SetXWindowPos
@@ -1088,10 +1214,13 @@
BOOL SetWindowPos( HWND hwnd, HWND hwndInsertAfter, INT x, INT y,
INT cx, INT cy, WORD flags )
{
- WINDOWPOS winpos;
- WND *wndPtr;
- RECT newWindowRect, newClientRect;
- int result;
+ WINDOWPOS winpos;
+ WND * wndPtr;
+ RECT newWindowRect, newClientRect;
+ HRGN visRgn = 0;
+ int result = 0;
+
+ dprintf_win(stddeb,"SetWindowPos: hwnd %04x, flags %08x\n", hwnd, flags);
/* Check window handle */
@@ -1130,10 +1259,19 @@
/* TOPMOST not supported yet */
if ((hwndInsertAfter == HWND_TOPMOST) ||
(hwndInsertAfter == HWND_NOTOPMOST)) hwndInsertAfter = HWND_TOP;
+
/* hwndInsertAfter must be a sibling of the window */
- if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM) &&
- (wndPtr->parent != WIN_FindWndPtr(hwndInsertAfter)->parent))
- return FALSE;
+ if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM))
+ {
+ WND* wnd = WIN_FindWndPtr(hwndInsertAfter);
+ if( wnd->parent != wndPtr->parent ) return FALSE;
+ if( wnd->next == wndPtr ) flags |= SWP_NOZORDER;
+ }
+ else
+ if (hwndInsertAfter == HWND_TOP)
+ flags |= ( wndPtr->parent->child == wndPtr)? SWP_NOZORDER: 0;
+ else /* HWND_BOTTOM */
+ flags |= ( wndPtr->next )? 0: SWP_NOZORDER;
/* Fill the WINDOWPOS structure */
@@ -1166,8 +1304,13 @@
newWindowRect.top = winpos.y;
newWindowRect.right += winpos.x - wndPtr->rectWindow.left;
newWindowRect.bottom += winpos.y - wndPtr->rectWindow.top;
+
+ OffsetRect(&newClientRect, winpos.x - wndPtr->rectWindow.left,
+ winpos.y - wndPtr->rectWindow.top );
}
+ winpos.flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
+
/* Reposition window in Z order */
if (!(winpos.flags & SWP_NOZORDER))
@@ -1186,17 +1329,42 @@
else WINPOS_MoveWindowZOrder( winpos.hwnd, hwndInsertAfter );
}
- /* Send WM_NCCALCSIZE message to get new client area */
+ if ( !wndPtr->window && !(flags & SWP_NOREDRAW) &&
+ (!(flags & SWP_NOMOVE) || !(flags & SWP_NOSIZE) || (flags & SWP_FRAMECHANGED)) )
+ visRgn = DCE_GetVisRgn(hwnd, DCX_WINDOW | DCX_CLIPSIBLINGS);
- result = WINPOS_SendNCCalcSize( winpos.hwnd, TRUE, &newWindowRect,
+
+ /* Send WM_NCCALCSIZE message to get new client area */
+ if( (flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
+ {
+ result = WINPOS_SendNCCalcSize( winpos.hwnd, TRUE, &newWindowRect,
&wndPtr->rectWindow, &wndPtr->rectClient,
&winpos, &newClientRect );
- /* FIXME: Should handle result here */
+
+ /* FIXME: WVR_ALIGNxxx */
+
+ if( newClientRect.left != wndPtr->rectClient.left ||
+ newClientRect.top != wndPtr->rectClient.top )
+ winpos.flags &= ~SWP_NOCLIENTMOVE;
+
+ if( (newClientRect.right - newClientRect.left !=
+ wndPtr->rectClient.right - wndPtr->rectClient.left) ||
+ (newClientRect.bottom - newClientRect.top !=
+ wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
+ winpos.flags &= ~SWP_NOCLIENTSIZE;
+ }
+ else
+ if( !(flags & SWP_NOMOVE) && (newClientRect.left != wndPtr->rectClient.left ||
+ newClientRect.top != wndPtr->rectClient.top) )
+ winpos.flags &= ~SWP_NOCLIENTMOVE;
/* Perform the moving and resizing */
if (wndPtr->window)
{
+ RECT oldWindowRect = wndPtr->rectWindow;
+ RECT oldClientRect = wndPtr->rectClient;
+
HWND bogusInsertAfter = winpos.hwndInsertAfter;
winpos.hwndInsertAfter = hwndInsertAfter;
@@ -1205,44 +1373,66 @@
wndPtr->rectWindow = newWindowRect;
wndPtr->rectClient = newClientRect;
winpos.hwndInsertAfter = bogusInsertAfter;
+
+ /* FIXME: should do something like WINPOS_SizeMoveClean */
+
+ if( (oldClientRect.left - oldWindowRect.left !=
+ newClientRect.left - newWindowRect.left) ||
+ (oldClientRect.top - oldWindowRect.top !=
+ newClientRect.top - newWindowRect.top) )
+
+ RedrawWindow(wndPtr->hwndSelf, NULL, 0, RDW_ALLCHILDREN | RDW_FRAME | RDW_ERASE);
+ else
+ if( winpos.flags & SWP_FRAMECHANGED )
+ {
+ WORD wErase = 0;
+ RECT rect;
+
+ if( oldClientRect.right > newClientRect.right )
+ {
+ rect.left = newClientRect.right; rect.top = newClientRect.top;
+ rect.right = oldClientRect.right; rect.bottom = newClientRect.bottom;
+ wErase = 1;
+ RedrawWindow(wndPtr->hwndSelf, &rect, 0, RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN);
+ }
+ if( oldClientRect.bottom > newClientRect.bottom )
+ {
+ rect.left = newClientRect.left; rect.top = newClientRect.bottom;
+ rect.right = (wErase)?oldClientRect.right:newClientRect.right;
+ rect.bottom = oldClientRect.bottom;
+ wErase = 1;
+ RedrawWindow(wndPtr->hwndSelf, &rect, 0, RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN);
+ }
+
+ if( !wErase ) wndPtr->flags |= WIN_NEEDS_NCPAINT;
+ }
}
else
{
RECT oldWindowRect = wndPtr->rectWindow;
+ RECT oldClientRect = wndPtr->rectClient;
wndPtr->rectWindow = newWindowRect;
wndPtr->rectClient = newClientRect;
- if (!(flags & SWP_NOREDRAW) &&
- (!(flags & SWP_NOSIZE) || !(flags & SWP_NOMOVE) ||
- (!(flags & SWP_NOZORDER) && (hwndInsertAfter != HWND_TOP))))
- {
- HRGN hrgn1 = CreateRectRgnIndirect( &oldWindowRect );
- HRGN hrgn2 = CreateRectRgnIndirect( &wndPtr->rectWindow );
- HRGN hrgn3 = CreateRectRgn( 0, 0, 0, 0 );
- CombineRgn( hrgn3, hrgn1, hrgn2, RGN_DIFF );
- RedrawWindow( wndPtr->parent->hwndSelf, NULL, hrgn3,
- RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE );
+ if( !(flags & SWP_NOREDRAW) )
+ {
+ BOOL bNoCopy = (flags & SWP_NOCOPYBITS) ||
+ (result >= WVR_HREDRAW && result < WVR_VALIDRECTS);
- /* DCE_GetVisRgn should be called for old coordinates
- * and for new, then OffsetRgn and CombineRgn -
- * voila, a nice update region to use here - AK.
- */
- if ((oldWindowRect.left != wndPtr->rectWindow.left) ||
- (oldWindowRect.top != wndPtr->rectWindow.top))
- {
- RedrawWindow( winpos.hwnd, NULL, 0, RDW_INVALIDATE |
- RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE );
- }
- else
- if( CombineRgn( hrgn3, hrgn2, hrgn1, RGN_DIFF) != NULLREGION )
- RedrawWindow( winpos.hwnd, NULL, hrgn3, RDW_INVALIDATE |
- RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE );
+ if( (winpos.flags & SWP_NOPOSCHANGE) != SWP_NOPOSCHANGE )
+ {
+ /* optimize cleanup by BitBlt'ing where possible */
- DeleteObject( hrgn1 );
- DeleteObject( hrgn2 );
- DeleteObject( hrgn3 );
- }
+ WINPOS_SizeMoveClean(wndPtr, visRgn, &oldWindowRect, &oldClientRect, bNoCopy);
+ DeleteObject(visRgn);
+ }
+ else
+ if( winpos.flags & SWP_FRAMECHANGED )
+ RedrawWindow( winpos.hwnd, NULL, 0, RDW_NOCHILDREN | RDW_FRAME );
+
+ }
+ DeleteObject(visRgn);
}
if (flags & SWP_SHOWWINDOW)
@@ -1271,8 +1461,7 @@
{
if (!(flags & SWP_NOREDRAW))
RedrawWindow( wndPtr->parent->hwndSelf, &wndPtr->rectWindow, 0,
- RDW_INVALIDATE | RDW_FRAME |
- RDW_ALLCHILDREN | RDW_ERASE );
+ RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE );
}
if ((winpos.hwnd == GetFocus()) || IsChild(winpos.hwnd, GetFocus()))
@@ -1303,18 +1492,12 @@
EVENT_DummyMotionNotify(); /* Simulate a mouse event to set the cursor */
- if ((flags & SWP_FRAMECHANGED) && !(flags & SWP_NOREDRAW))
- RedrawWindow( winpos.hwnd, NULL, 0,
- RDW_ALLCHILDREN | /*FIXME: this should not be necessary*/
- RDW_INVALIDATE | RDW_FRAME | RDW_ERASE );
if (!(flags & SWP_DEFERERASE))
RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0,
RDW_ALLCHILDREN | RDW_ERASENOW );
/* And last, send the WM_WINDOWPOSCHANGED message */
- winpos.flags |= SWP_NOMOVE; /* prevent looping.. window is already moved ??? (FIXME)*/
-
if (!(winpos.flags & SWP_NOSENDCHANGING))
SendMessage( winpos.hwnd, WM_WINDOWPOSCHANGED,
0, (LPARAM)MAKE_SEGPTR(&winpos) );