--- /dev/null
+/* File: button.c -- Button type widgets
+ *
+ * Copyright (C) 1993 Johannes Ruscheinski
+ * Copyright (C) 1993 David Metcalfe
+ * Copyright (C) 1994 Alexandre Julliard
+ */
+#include <windows.h>
+#include <user32/win.h>
+#include <user32/button.h>
+#include <user32/paint.h>
+#include <user32/nc.h>
+#include <user32/syscolor.h>
+#include <user32/defwnd.h>
+
+
+static void PB_Paint( WND *wndPtr, HDC hDC, WORD action );
+static void PB_PaintGrayOnGray(HDC hDC,HFONT hFont,RECT *rc,char *text);
+static void CB_Paint( WND *wndPtr, HDC hDC, WORD action );
+static void GB_Paint( WND *wndPtr, HDC hDC, WORD action );
+static void UB_Paint( WND *wndPtr, HDC hDC, WORD action );
+static void OB_Paint( WND *wndPtr, HDC hDC, WORD action );
+static void BUTTON_CheckAutoRadioButton( WND *wndPtr );
+
+#define MAX_BTN_TYPE 12
+
+static const WORD maxCheckState[MAX_BTN_TYPE] =
+{
+ BUTTON_UNCHECKED, /* BS_PUSHBUTTON */
+ BUTTON_UNCHECKED, /* BS_DEFPUSHBUTTON */
+ BUTTON_CHECKED, /* BS_CHECKBOX */
+ BUTTON_CHECKED, /* BS_AUTOCHECKBOX */
+ BUTTON_CHECKED, /* BS_RADIOBUTTON */
+ BUTTON_3STATE, /* BS_3STATE */
+ BUTTON_3STATE, /* BS_AUTO3STATE */
+ BUTTON_UNCHECKED, /* BS_GROUPBOX */
+ BUTTON_UNCHECKED, /* BS_USERBUTTON */
+ BUTTON_CHECKED, /* BS_AUTORADIOBUTTON */
+ BUTTON_UNCHECKED, /* Not defined */
+ BUTTON_UNCHECKED /* BS_OWNERDRAW */
+};
+
+typedef void (*pfPaint)( WND *wndPtr, HDC hdc, WORD action );
+
+static const pfPaint btnPaintFunc[MAX_BTN_TYPE] =
+{
+ PB_Paint, /* BS_PUSHBUTTON */
+ PB_Paint, /* BS_DEFPUSHBUTTON */
+ CB_Paint, /* BS_CHECKBOX */
+ CB_Paint, /* BS_AUTOCHECKBOX */
+ CB_Paint, /* BS_RADIOBUTTON */
+ CB_Paint, /* BS_3STATE */
+ CB_Paint, /* BS_AUTO3STATE */
+ GB_Paint, /* BS_GROUPBOX */
+ UB_Paint, /* BS_USERBUTTON */
+ CB_Paint, /* BS_AUTORADIOBUTTON */
+ NULL, /* Not defined */
+ OB_Paint /* BS_OWNERDRAW */
+};
+
+#define PAINT_BUTTON(wndPtr,style,action) \
+ if (btnPaintFunc[style]) { \
+ HDC hdc = GetDC( (wndPtr)->hwndSelf ); \
+ (btnPaintFunc[style])(wndPtr,hdc,action); \
+ ReleaseDC( (wndPtr)->hwndSelf, hdc ); }
+
+#define BUTTON_SEND_CTLCOLOR(wndPtr,hdc) \
+ SendMessageA( GetParent((wndPtr)->hwndSelf), WM_CTLCOLORBTN, \
+ (WPARAM)(hdc), (LPARAM)(wndPtr)->hwndSelf )
+
+static HBITMAP hbitmapCheckBoxes = 0;
+static WORD checkBoxWidth = 0, checkBoxHeight = 0;
+
+
+/***********************************************************************
+ * ButtonWndProc
+ */
+LRESULT WINAPI ButtonWndProc( HWND hWnd, UINT uMsg,
+ WPARAM wParam, LPARAM lParam )
+{
+ RECT rect;
+ POINT pt = { LOWORD(lParam), HIWORD(lParam) };
+ WND *wndPtr = WIN_FindWndPtr(hWnd);
+ BUTTONINFO *infoPtr = (BUTTONINFO *)wndPtr->wExtra;
+ LONG style = wndPtr->dwStyle & 0x0f;
+
+ switch (uMsg)
+ {
+ case WM_GETDLGCODE:
+ switch(style)
+ {
+ case BS_PUSHBUTTON: return DLGC_BUTTON | DLGC_UNDEFPUSHBUTTON;
+ case BS_DEFPUSHBUTTON: return DLGC_BUTTON | DLGC_DEFPUSHBUTTON;
+ case BS_RADIOBUTTON:
+ case BS_AUTORADIOBUTTON: return DLGC_BUTTON | DLGC_RADIOBUTTON;
+ default: return DLGC_BUTTON;
+ }
+
+ case WM_ENABLE:
+ PAINT_BUTTON( wndPtr, style, ODA_DRAWENTIRE );
+ break;
+
+ case WM_CREATE:
+ if (!hbitmapCheckBoxes)
+ {
+ BITMAP bmp;
+ hbitmapCheckBoxes = LoadBitmapA(0, MAKEINTRESOURCEA(OBM_CHECKBOXES));
+ GetObjectA( hbitmapCheckBoxes, sizeof(bmp), &bmp );
+ checkBoxWidth = bmp.bmWidth / 4;
+ checkBoxHeight = bmp.bmHeight / 3;
+ }
+ if (style < 0L || style >= MAX_BTN_TYPE) return -1; /* abort */
+ infoPtr->state = BUTTON_UNCHECKED;
+ infoPtr->hFont = 0;
+ return 0;
+
+ case WM_ERASEBKGND:
+ return 1;
+
+ case WM_PAINT:
+ if (btnPaintFunc[style])
+ {
+ PAINTSTRUCT ps;
+ HDC hdc = wParam ? (HDC)wParam : BeginPaint( hWnd, &ps );
+ SetBkMode( hdc, OPAQUE );
+ (btnPaintFunc[style])( wndPtr, hdc, ODA_DRAWENTIRE );
+ if( !wParam ) EndPaint( hWnd, &ps );
+ }
+ break;
+
+ case WM_LBUTTONDOWN:
+ case WM_LBUTTONDBLCLK:
+ SendMessageA( hWnd, BM_SETSTATE, TRUE, 0 );
+ SetFocus( hWnd );
+ SetCapture( hWnd );
+ break;
+
+ case WM_LBUTTONUP:
+ ReleaseCapture();
+ if (!(infoPtr->state & BUTTON_HIGHLIGHTED)) break;
+ SendMessageA( hWnd, BM_SETSTATE, FALSE, 0 );
+ GetClientRect( hWnd, &rect );
+ if (PtInRect( &rect, pt ))
+ {
+ switch(style)
+ {
+ case BS_AUTOCHECKBOX:
+ SendMessageA( hWnd, BM_SETCHECK,
+ !(infoPtr->state & BUTTON_CHECKED), 0 );
+ break;
+ case BS_AUTORADIOBUTTON:
+ SendMessageA( hWnd, BM_SETCHECK, TRUE, 0 );
+ break;
+ case BS_AUTO3STATE:
+ SendMessageA( hWnd, BM_SETCHECK,
+ (infoPtr->state & BUTTON_3STATE) ? 0 :
+ ((infoPtr->state & 3) + 1), 0 );
+ break;
+ }
+ SendMessageA( GetParent(hWnd), WM_COMMAND,
+ MAKEWPARAM( wndPtr->wIDmenu, BN_CLICKED ), (LPARAM)hWnd);
+ }
+ break;
+
+ case WM_MOUSEMOVE:
+ if (GetCapture() == hWnd)
+ {
+ GetClientRect( hWnd, &rect );
+ SendMessageA( hWnd, BM_SETSTATE, PtInRect(&rect, pt), 0 );
+ }
+ break;
+
+ case WM_NCHITTEST:
+ if(style == BS_GROUPBOX) return HTTRANSPARENT;
+ return DefWindowProcA( hWnd, uMsg, wParam, lParam );
+
+ case WM_SETTEXT:
+ DEFWND_SetTextA( wndPtr, (LPCSTR)lParam );
+ if( wndPtr->dwStyle & WS_VISIBLE )
+ PAINT_BUTTON( wndPtr, style, ODA_DRAWENTIRE );
+ return 0;
+
+ case WM_SETFONT:
+ infoPtr->hFont = (HFONT)wParam;
+ if (lParam && (wndPtr->dwStyle & WS_VISIBLE))
+ PAINT_BUTTON( wndPtr, style, ODA_DRAWENTIRE );
+ break;
+
+ case WM_GETFONT:
+ return (LRESULT)infoPtr->hFont;
+
+ case WM_SETFOCUS:
+ infoPtr->state |= BUTTON_HASFOCUS;
+ if (style == BS_AUTORADIOBUTTON)
+ {
+ SendMessageA( hWnd, BM_SETCHECK, 1, 0 );
+ }
+ PAINT_BUTTON( wndPtr, style, ODA_FOCUS );
+ break;
+
+ case WM_KILLFOCUS:
+ infoPtr->state &= ~BUTTON_HASFOCUS;
+ PAINT_BUTTON( wndPtr, style, ODA_FOCUS );
+ InvalidateRect( hWnd, NULL, TRUE );
+ break;
+
+ case WM_SYSCOLORCHANGE:
+ InvalidateRect( hWnd, NULL, FALSE );
+ break;
+
+ case BM_SETSTYLE:
+ if ((wParam & 0x0f) >= MAX_BTN_TYPE) break;
+ wndPtr->dwStyle = (wndPtr->dwStyle & 0xfffffff0)
+ | (wParam & 0x0000000f);
+ style = wndPtr->dwStyle & 0x0000000f;
+ PAINT_BUTTON( wndPtr, style, ODA_DRAWENTIRE );
+ break;
+
+ case BM_GETCHECK:
+ return infoPtr->state & 3;
+
+ case BM_SETCHECK:
+ if (wParam > maxCheckState[style]) wParam = maxCheckState[style];
+ if ((infoPtr->state & 3) != wParam)
+ {
+ if ((style == BS_RADIOBUTTON) || (style == BS_AUTORADIOBUTTON))
+ {
+ if (wParam)
+ wndPtr->dwStyle |= WS_TABSTOP;
+ else
+ wndPtr->dwStyle &= ~WS_TABSTOP;
+ }
+ infoPtr->state = (infoPtr->state & ~3) | wParam;
+ PAINT_BUTTON( wndPtr, style, ODA_SELECT );
+ }
+ if ((style == BS_AUTORADIOBUTTON) && (wParam == BUTTON_CHECKED))
+ BUTTON_CheckAutoRadioButton( wndPtr );
+ break;
+
+ case BM_GETSTATE:
+ return infoPtr->state;
+
+ case BM_SETSTATE:
+ if (wParam)
+ {
+ if (infoPtr->state & BUTTON_HIGHLIGHTED) break;
+ infoPtr->state |= BUTTON_HIGHLIGHTED;
+ }
+ else
+ {
+ if (!(infoPtr->state & BUTTON_HIGHLIGHTED)) break;
+ infoPtr->state &= ~BUTTON_HIGHLIGHTED;
+ }
+ PAINT_BUTTON( wndPtr, style, ODA_SELECT );
+ break;
+
+ default:
+ return DefWindowProcA(hWnd, uMsg, wParam, lParam);
+ }
+ return 0;
+}
+
+
+/**********************************************************************
+ * Push Button Functions
+ */
+
+static void PB_Paint( WND *wndPtr, HDC hDC, WORD action )
+{
+ RECT rc;
+ HPEN hOldPen;
+ HBRUSH hOldBrush;
+ BUTTONINFO *infoPtr = (BUTTONINFO *)wndPtr->wExtra;
+
+ GetClientRect( wndPtr->hwndSelf, &rc );
+
+ /* Send WM_CTLCOLOR to allow changing the font (the colors are fixed) */
+ if (infoPtr->hFont) SelectObject( hDC, infoPtr->hFont );
+ BUTTON_SEND_CTLCOLOR( wndPtr, hDC );
+ hOldPen = (HPEN)SelectObject(hDC, GetSysColorPen(COLOR_WINDOWFRAME));
+ hOldBrush =(HBRUSH)SelectObject(hDC,GetSysColorBrush(COLOR_BTNFACE));
+ SetBkMode(hDC, TRANSPARENT);
+ Rectangle(hDC, rc.left, rc.top, rc.right, rc.bottom);
+ if (action == ODA_DRAWENTIRE)
+ {
+ SetPixel( hDC, rc.left, rc.top, GetSysColor(COLOR_WINDOW) );
+ SetPixel( hDC, rc.left, rc.bottom-1, GetSysColor(COLOR_WINDOW) );
+ SetPixel( hDC, rc.right-1, rc.top, GetSysColor(COLOR_WINDOW) );
+ SetPixel( hDC, rc.right-1, rc.bottom-1, GetSysColor(COLOR_WINDOW));
+ }
+ InflateRect( &rc, -1, -1 );
+
+ if ((wndPtr->dwStyle & 0x000f) == BS_DEFPUSHBUTTON)
+ {
+ Rectangle(hDC, rc.left, rc.top, rc.right, rc.bottom);
+ InflateRect( &rc, -1, -1 );
+ }
+
+ if (infoPtr->state & BUTTON_HIGHLIGHTED)
+ {
+ /* draw button shadow: */
+ SelectObject(hDC, GetSysColorBrush(COLOR_BTNSHADOW));
+ PatBlt(hDC, rc.left, rc.top, 1, rc.bottom-rc.top, PATCOPY );
+ PatBlt(hDC, rc.left, rc.top, rc.right-rc.left, 1, PATCOPY );
+ rc.left += 2; /* To position the text down and right */
+ rc.top += 2;
+ } else {
+ rc.right++, rc.bottom++;
+ DrawEdge( hDC, &rc, EDGE_RAISED, BF_RECT );
+ rc.right--, rc.bottom--;
+ }
+
+ /* draw button label, if any: */
+// && wndPtr->text[0]
+ if (wndPtr->text )
+ {
+ LOGBRUSH lb;
+ GetObject( GetSysColorBrush(COLOR_BTNFACE), sizeof(lb), &lb );
+ if (wndPtr->dwStyle & WS_DISABLED &&
+ GetSysColor(COLOR_GRAYTEXT)==lb.lbColor)
+ /* don't write gray text on gray bkg */
+ PB_PaintGrayOnGray(hDC,infoPtr->hFont,&rc,wndPtr->text);
+ else
+ {
+ SetTextColor( hDC, (wndPtr->dwStyle & WS_DISABLED) ?
+ GetSysColor(COLOR_GRAYTEXT) :
+ GetSysColor(COLOR_BTNTEXT) );
+ DrawTextA( hDC, wndPtr->text, -1, &rc,
+ DT_SINGLELINE | DT_CENTER | DT_VCENTER );
+ /* do we have the focus? */
+ if (infoPtr->state & BUTTON_HASFOCUS)
+ {
+ RECT r = { 0, 0, 0, 0 };
+ INT xdelta, ydelta;
+
+ DrawTextA( hDC, wndPtr->text, -1, &r,
+ DT_SINGLELINE | DT_CALCRECT );
+ xdelta = ((rc.right - rc.left) - (r.right - r.left) - 1) / 2;
+ ydelta = ((rc.bottom - rc.top) - (r.bottom - r.top) - 1) / 2;
+ if (xdelta < 0) xdelta = 0;
+ if (ydelta < 0) ydelta = 0;
+ InflateRect( &rc, -xdelta, -ydelta );
+ DrawFocusRect( hDC, &rc );
+ }
+ }
+ }
+
+ SelectObject( hDC, hOldPen );
+ SelectObject( hDC, hOldBrush );
+}
+
+
+/**********************************************************************
+ * Push Button sub function [internal]
+ * using a raster brush to avoid gray text on gray background
+ */
+
+void PB_PaintGrayOnGray(HDC hDC,HFONT hFont,RECT *rc,char *text)
+{
+ static const int Pattern[] = {0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55};
+ HBITMAP hbm = CreateBitmap( 8, 8, 1, 1, Pattern );
+ HDC hdcMem = CreateCompatibleDC(hDC);
+ HBITMAP hbmMem;
+ HBRUSH hBr;
+ RECT rect,rc2;
+
+ rect=*rc;
+ DrawTextA( hDC, text, -1, &rect, DT_SINGLELINE | DT_CALCRECT);
+ rc2=rect;
+ rect.left=(rc->right-rect.right)/2; /* for centering text bitmap */
+ rect.top=(rc->bottom-rect.bottom)/2;
+ hbmMem = CreateCompatibleBitmap( hDC,rect.right,rect.bottom );
+ SelectObject( hdcMem, hbmMem);
+ hBr = SelectObject( hdcMem, CreatePatternBrush(hbm) );
+ DeleteObject( hbm );
+ PatBlt( hdcMem,0,0,rect.right,rect.bottom,WHITENESS);
+ if (hFont) SelectObject( hdcMem, hFont);
+ DrawTextA( hdcMem, text, -1, &rc2, DT_SINGLELINE);
+ PatBlt( hdcMem,0,0,rect.right,rect.bottom,0xFA0089);
+ DeleteObject( SelectObject( hdcMem,hBr) );
+ BitBlt(hDC,rect.left,rect.top,rect.right,rect.bottom,hdcMem,0,0,0x990000);
+ DeleteDC( hdcMem);
+ DeleteObject( hbmMem );
+}
+
+
+/**********************************************************************
+ * Check Box & Radio Button Functions
+ */
+
+static void CB_Paint( WND *wndPtr, HDC hDC, WORD action )
+{
+ RECT rbox, rtext, client;
+ HBRUSH hBrush;
+ int textlen, delta;
+ BUTTONINFO *infoPtr = (BUTTONINFO *)wndPtr->wExtra;
+
+ textlen = 0;
+ GetClientRect(wndPtr->hwndSelf, &client);
+ rbox = rtext = client;
+
+ if (infoPtr->hFont) SelectObject( hDC, infoPtr->hFont );
+
+ /* Something is still not right, checkboxes (and edit controls)
+ * in wsping have white backgrounds instead of dark grey.
+ * BUTTON_SEND_CTLCOLOR() is even worse since it returns 0 in this
+ * particular case and the background is not painted at all.
+ */
+
+ hBrush = GetControlBrush( wndPtr->hwndSelf, hDC, CTLCOLOR_BTN );
+
+ if (wndPtr->dwStyle & BS_LEFTTEXT)
+ {
+ /* magic +4 is what CTL3D expects */
+
+ rtext.right -= checkBoxWidth + 4;
+ rbox.left = rbox.right - checkBoxWidth;
+ }
+ else
+ {
+ rtext.left += checkBoxWidth + 4;
+ rbox.right = checkBoxWidth;
+ }
+
+ /* Draw the check-box bitmap */
+
+
+ if (wndPtr->text) {
+ textlen = lstrlenA( wndPtr->text );
+ }
+ if (action == ODA_DRAWENTIRE || action == ODA_SELECT)
+ {
+ HDC hMemDC = CreateCompatibleDC( hDC );
+ int x = 0, y = 0;
+ delta = (rbox.bottom - rbox.top - checkBoxHeight) >> 1;
+
+ if (action == ODA_SELECT) FillRect( hDC, &rbox, hBrush );
+ else FillRect( hDC, &client, hBrush );
+
+ if (infoPtr->state & BUTTON_HIGHLIGHTED) x += 2 * checkBoxWidth;
+ if (infoPtr->state & (BUTTON_CHECKED | BUTTON_3STATE)) x += checkBoxWidth;
+ if (((wndPtr->dwStyle & 0x0f) == BS_RADIOBUTTON) ||
+ ((wndPtr->dwStyle & 0x0f) == BS_AUTORADIOBUTTON)) y += checkBoxHeight;
+ else if (infoPtr->state & BUTTON_3STATE) y += 2 * checkBoxHeight;
+
+ SelectObject( hMemDC, hbitmapCheckBoxes );
+ BitBlt( hDC, rbox.left, rbox.top + delta, checkBoxWidth,
+ checkBoxHeight, hMemDC, x, y, SRCCOPY );
+ DeleteDC( hMemDC );
+
+ if( textlen && action != ODA_SELECT )
+ {
+ if (wndPtr->dwStyle & WS_DISABLED)
+ SetTextColor( hDC, GetSysColor(COLOR_GRAYTEXT) );
+ DrawTextA( hDC, wndPtr->text, textlen, &rtext,
+ DT_SINGLELINE | DT_VCENTER );
+ textlen = 0; /* skip DrawText() below */
+ }
+ }
+
+ if ((action == ODA_FOCUS) ||
+ ((action == ODA_DRAWENTIRE) && (infoPtr->state & BUTTON_HASFOCUS)))
+ {
+ /* again, this is what CTL3D expects */
+
+ SetRectEmpty(&rbox);
+ if( textlen )
+ DrawTextA( hDC, wndPtr->text, textlen, &rbox,
+ DT_SINGLELINE | DT_CALCRECT );
+ textlen = rbox.bottom - rbox.top;
+ delta = ((rtext.bottom - rtext.top) - textlen)/2;
+ rbox.bottom = (rbox.top = rtext.top + delta - 1) + textlen + 2;
+ textlen = rbox.right - rbox.left;
+ rbox.right = (rbox.left += --rtext.left) + textlen + 2;
+ IntersectRect(&rbox, &rbox, &rtext);
+ DrawFocusRect( hDC, &rbox );
+ }
+}
+
+
+/**********************************************************************
+ * BUTTON_CheckAutoRadioButton
+ *
+ * wndPtr is checked, uncheck every other auto radio button in group
+ */
+static void BUTTON_CheckAutoRadioButton( WND *wndPtr )
+{
+ HWND parent, sibling, start;
+ WND *sibPtr;
+ if (!(wndPtr->dwStyle & WS_CHILD)) return;
+ parent = wndPtr->parent->hwndSelf;
+ /* assure that starting control is not disabled or invisible */
+ start = sibling = GetNextDlgGroupItem( parent, wndPtr->hwndSelf, TRUE );
+ do
+ {
+
+ if (!sibling) break;
+ sibPtr = WIN_FindWndPtr(sibling);
+ if (!sibPtr) break;
+ if ((wndPtr->hwndSelf != sibling) &&
+ ((sibPtr->dwStyle & 0x0f) == BS_AUTORADIOBUTTON))
+ SendMessageA( sibling, BM_SETCHECK, BUTTON_UNCHECKED, 0 );
+ sibling = GetNextDlgGroupItem( parent, sibling, FALSE );
+ } while (sibling != start);
+}
+
+
+/**********************************************************************
+ * Group Box Functions
+ */
+
+static void GB_Paint( WND *wndPtr, HDC hDC, WORD action )
+{
+ RECT rc, rcFrame;
+ BUTTONINFO *infoPtr = (BUTTONINFO *)wndPtr->wExtra;
+
+ if (action != ODA_DRAWENTIRE) return;
+
+ BUTTON_SEND_CTLCOLOR( wndPtr, hDC );
+
+ GetClientRect( wndPtr->hwndSelf, &rc);
+ if (TWEAK_WineLook == WIN31_LOOK) {
+ HPEN hPrevPen = SelectObject( hDC,
+ GetSysColorPen(COLOR_WINDOWFRAME));
+ HBRUSH hPrevBrush = SelectObject( hDC,
+ GetStockObject(NULL_BRUSH) );
+
+ Rectangle( hDC, rc.left, rc.top + 2, rc.right - 1, rc.bottom - 1 );
+ SelectObject( hDC, hPrevBrush );
+ SelectObject( hDC, hPrevPen );
+ } else {
+ TEXTMETRIC tm;
+ rcFrame = rc;
+
+ if (infoPtr->hFont)
+ SelectObject (hDC, infoPtr->hFont);
+ GetTextMetricsA (hDC, &tm);
+ rcFrame.top += (tm.tmHeight / 2) - 1;
+ DrawEdge (hDC, &rcFrame, EDGE_ETCHED, BF_RECT);
+ }
+
+ if (wndPtr->text)
+ {
+ if (infoPtr->hFont) SelectObject( hDC, infoPtr->hFont );
+ if (wndPtr->dwStyle & WS_DISABLED)
+ SetTextColor( hDC, GetSysColor(COLOR_GRAYTEXT) );
+ rc.left += 10;
+ DrawTextA( hDC, wndPtr->text, -1, &rc, DT_SINGLELINE | DT_NOCLIP );
+ }
+}
+
+
+/**********************************************************************
+ * User Button Functions
+ */
+
+static void UB_Paint( WND *wndPtr, HDC hDC, WORD action )
+{
+ RECT rc;
+ HBRUSH hBrush;
+ BUTTONINFO *infoPtr = (BUTTONINFO *)wndPtr->wExtra;
+
+ if (action == ODA_SELECT) return;
+
+ GetClientRect( wndPtr->hwndSelf, &rc);
+
+ if (infoPtr->hFont) SelectObject( hDC, infoPtr->hFont );
+ hBrush = GetControlBrush( wndPtr->hwndSelf, hDC, CTLCOLOR_BTN );
+
+ FillRect( hDC, &rc, hBrush );
+ if ((action == ODA_FOCUS) ||
+ ((action == ODA_DRAWENTIRE) && (infoPtr->state & BUTTON_HASFOCUS)))
+ DrawFocusRect( hDC, &rc );
+}
+
+
+/**********************************************************************
+ * Ownerdrawn Button Functions
+ */
+
+static void OB_Paint( WND *wndPtr, HDC hDC, WORD action )
+{
+ BUTTONINFO *infoPtr = (BUTTONINFO *)wndPtr->wExtra;
+ DRAWITEMSTRUCT dis;
+
+ dis.CtlType = ODT_BUTTON;
+ dis.CtlID = wndPtr->wIDmenu;
+ dis.itemID = 0;
+ dis.itemAction = action;
+ dis.itemState = ((infoPtr->state & BUTTON_HASFOCUS) ? ODS_FOCUS : 0) |
+ ((infoPtr->state & BUTTON_HIGHLIGHTED) ? ODS_SELECTED : 0) |
+ ((wndPtr->dwStyle & WS_DISABLED) ? ODS_DISABLED : 0);
+ dis.hwndItem = wndPtr->hwndSelf;
+ dis.hDC = hDC;
+ dis.itemData = 0;
+ GetClientRect( wndPtr->hwndSelf, &dis.rcItem );
+ SendMessageA( GetParent(wndPtr->hwndSelf), WM_DRAWITEM,
+ wndPtr->wIDmenu, (LPARAM)&dis );
+}
--- /dev/null
+/*
+ * Combo controls
+ *
+ * Copyright 1997 Alex Korobka
+ *
+ * FIXME: roll up in Netscape 3.01.
+ */
+
+#include <string.h>
+
+#include <windows.h>
+#include <user32/sysmetr.h>
+#include <user32/win.h>
+
+#include <user32/heapdup.h>
+#include <user32/combo.h>
+#include <user32/debug.h>
+
+ /* bits in the dwKeyData */
+#define KEYDATA_ALT 0x2000
+#define KEYDATA_PREVSTATE 0x4000
+
+/*
+ * Additional combo box definitions
+ */
+
+#define CB_GETPTR( wnd ) (*(LPHEADCOMBO*)((wnd)->wExtra))
+#define CB_NOTIFY( lphc, code ) \
+ (SendMessageA( (lphc)->owner, WM_COMMAND, \
+ MAKEWPARAM((lphc)->self->wIDmenu, (code)), (LPARAM)(lphc)->self->hwndSelf))
+#define CB_GETEDITTEXTLENGTH( lphc ) \
+ (SendMessageA( (lphc)->hWndEdit, WM_GETTEXTLENGTH, 0, 0 ))
+
+static HBITMAP hComboBmp = 0;
+static UINT CBitHeight, CBitWidth;
+static UINT CBitOffset = 8;
+
+/***********************************************************************
+ * COMBO_Init
+ *
+ * Load combo button bitmap.
+ */
+WINBOOL COMBO_Init(void)
+{
+ HDC hDC;
+
+ if( hComboBmp ) return TRUE;
+ if( (hDC = CreateCompatibleDC(0)) )
+ {
+ WINBOOL bRet = FALSE;
+ if( (hComboBmp = LoadBitmap(0, MAKEINTRESOURCE(OBM_COMBO))) )
+ {
+ BITMAP bm;
+ HBITMAP hPrevB;
+ RECT r;
+
+ GetObjectA( hComboBmp, sizeof(bm), &bm );
+ CBitHeight = bm.bmHeight;
+ CBitWidth = bm.bmWidth;
+
+ DPRINT( "combo bitmap [%i,%i]\n", CBitWidth, CBitHeight );
+
+ hPrevB = SelectObject( hDC, hComboBmp);
+ SetRect( &r, 0, 0, CBitWidth, CBitHeight );
+ InvertRect( hDC, &r );
+ SelectObject( hDC, hPrevB );
+ bRet = TRUE;
+ }
+ DeleteDC( hDC );
+ return bRet;
+ }
+ return FALSE;
+}
+
+/***********************************************************************
+ * COMBO_NCCreate
+ */
+static LRESULT COMBO_NCCreate(WND* wnd, LPARAM lParam)
+{
+ LPHEADCOMBO lphc;
+
+ if ( wnd && COMBO_Init() &&
+ (lphc = HeapAlloc(GetProcessHeap(), 0, sizeof(HEADCOMBO))) )
+ {
+ LPCREATESTRUCTA lpcs = (CREATESTRUCTA*)lParam;
+
+ memset( lphc, 0, sizeof(HEADCOMBO) );
+ *(LPHEADCOMBO*)wnd->wExtra = lphc;
+
+ /* some braindead apps do try to use scrollbar/border flags */
+
+ lphc->dwStyle = (lpcs->style & ~(WS_BORDER | WS_HSCROLL | WS_VSCROLL));
+ wnd->dwStyle &= ~(WS_BORDER | WS_HSCROLL | WS_VSCROLL);
+
+ if( !(lpcs->style & (CBS_OWNERDRAWFIXED | CBS_OWNERDRAWVARIABLE)) )
+ lphc->dwStyle |= CBS_HASSTRINGS;
+ if( !(wnd->dwExStyle & WS_EX_NOPARENTNOTIFY) )
+ lphc->wState |= CBF_NOTIFY;
+
+ DPRINT( "[0x%08x], style = %08x\n",
+ (UINT)lphc, lphc->dwStyle );
+
+ return (LRESULT)(UINT)wnd->hwndSelf;
+ }
+ return (LRESULT)FALSE;
+}
+
+/***********************************************************************
+ * COMBO_NCDestroy
+ */
+static LRESULT COMBO_NCDestroy( LPHEADCOMBO lphc )
+{
+
+ if( lphc )
+ {
+ WND* wnd = lphc->self;
+
+ DPRINT("[%04x]: freeing storage\n", CB_HWND(lphc));
+
+ if( (CB_GETTYPE(lphc) != CBS_SIMPLE) && lphc->hWndLBox )
+ DestroyWindow( lphc->hWndLBox );
+
+ HeapFree( GetProcessHeap(), 0, lphc );
+ wnd->wExtra[0] = 0;
+ }
+ return 0;
+}
+
+/***********************************************************************
+ * CBGetDefaultTextHeight
+ */
+static void CBGetDefaultTextHeight( LPHEADCOMBO lphc, LPSIZE lpSize )
+{
+ if( lphc->editHeight ) /* explicitly set height */
+ lpSize->cy = lphc->editHeight;
+ else
+ {
+ HDC hDC = GetDC( lphc->self->hwndSelf );
+ HFONT hPrevFont = 0;
+
+ if( lphc->hFont ) hPrevFont = SelectObject( hDC, lphc->hFont );
+
+ GetTextExtentPointA( hDC, "0", 1, lpSize);
+
+ lpSize->cy += lpSize->cy / 4 + 4 * SYSMETRICS_CYBORDER;
+
+ if( hPrevFont ) SelectObject( hDC, hPrevFont );
+ ReleaseDC( lphc->self->hwndSelf, hDC );
+ }
+ lpSize->cx = lphc->RectCombo.right - lphc->RectCombo.left;
+}
+
+
+/***********************************************************************
+ * CBCalcPlacement
+ *
+ * Set up component coordinates given valid lphc->RectCombo.
+ */
+static void CBCalcPlacement( LPHEADCOMBO lphc, LPRECT lprEdit,
+ LPRECT lprButton, LPRECT lprLB )
+{
+ RECT rect = lphc->RectCombo;
+ SIZE size;
+
+ /* get combo height and width */
+
+ if( CB_OWNERDRAWN(lphc) )
+ {
+ UINT u = lphc->RectEdit.bottom - lphc->RectEdit.top;
+
+ if( lphc->wState & CBF_MEASUREITEM ) /* first initialization */
+ {
+ MEASUREITEMSTRUCT mi;
+
+ /* calculate defaults before sending WM_MEASUREITEM */
+
+ CBGetDefaultTextHeight( lphc, &size );
+
+ lphc->wState &= ~CBF_MEASUREITEM;
+
+ mi.CtlType = ODT_COMBOBOX;
+ mi.CtlID = lphc->self->wIDmenu;
+ mi.itemID = -1;
+ mi.itemWidth = size.cx;
+ mi.itemHeight = size.cy - 6; /* ownerdrawn cb is taller */
+ mi.itemData = 0;
+ SendMessageA(lphc->owner, WM_MEASUREITEM,
+ (WPARAM)mi.CtlID, (LPARAM)&mi);
+ u = 6 + (UINT)mi.itemHeight;
+ }
+ else
+ size.cx = rect.right - rect.left;
+ size.cy = u;
+ }
+ else
+ CBGetDefaultTextHeight( lphc, &size );
+
+ /* calculate text and button placement */
+
+ lprEdit->left = lprEdit->top = lprButton->top = 0;
+ if( CB_GETTYPE(lphc) == CBS_SIMPLE ) /* no button */
+ lprButton->left = lprButton->right = lprButton->bottom = 0;
+ else
+ {
+ INT i = size.cx - CBitWidth - 10; /* seems ok */
+
+ lprButton->right = size.cx;
+ lprButton->left = (INT)i;
+ lprButton->bottom = lprButton->top + size.cy;
+
+ if( i < 0 ) size.cx = 0;
+ else size.cx = i;
+ }
+
+ if( CB_GETTYPE(lphc) == CBS_DROPDOWN )
+ {
+ size.cx -= CBitOffset;
+ if( size.cx < 0 ) size.cx = 0;
+ }
+
+ lprEdit->right = size.cx; lprEdit->bottom = size.cy;
+
+ /* listbox placement */
+
+ lprLB->left = ( CB_GETTYPE(lphc) == CBS_DROPDOWNLIST ) ? 0 : CBitOffset;
+ lprLB->top = lprEdit->bottom - SYSMETRICS_CYBORDER;
+ lprLB->right = rect.right - rect.left;
+ lprLB->bottom = rect.bottom - rect.top;
+
+ if( lphc->droppedWidth > (lprLB->right - lprLB->left) )
+ lprLB->right = lprLB->left + lphc->droppedWidth;
+
+ DPRINT("[%04x]: (%i,%i-%i,%i) placement\n",
+ CB_HWND(lphc), lphc->RectCombo.left, lphc->RectCombo.top,
+ lphc->RectCombo.right, lphc->RectCombo.bottom);
+
+ DPRINT("\ttext\t= (%i,%i-%i,%i)\n",
+ lprEdit->left, lprEdit->top, lprEdit->right, lprEdit->bottom);
+
+ DPRINT("\tbutton\t= (%i,%i-%i,%i)\n",
+ lprButton->left, lprButton->top, lprButton->right, lprButton->bottom);
+
+ DPRINT("\tlbox\t= (%i,%i-%i,%i)\n",
+ lprLB->left, lprLB->top, lprLB->right, lprLB->bottom );
+}
+
+/***********************************************************************
+ * CBGetDroppedControlRect
+ */
+static void CBGetDroppedControlRect( LPHEADCOMBO lphc, LPRECT lpRect)
+{
+ lpRect->left = lphc->RectCombo.left +
+ (lphc->wState & CBF_EDIT) ? CBitOffset : 0;
+ lpRect->top = lphc->RectCombo.top + lphc->RectEdit.bottom -
+ SYSMETRICS_CYBORDER;
+ lpRect->right = lphc->RectCombo.right;
+ lpRect->bottom = lphc->RectCombo.bottom - SYSMETRICS_CYBORDER;
+}
+
+/***********************************************************************
+ * COMBO_Create
+ */
+LRESULT COMBO_Create( LPHEADCOMBO lphc, WND* wnd, LPARAM lParam)
+{
+ static char clbName[] = "ComboLBox";
+ static char editName[] = "Edit";
+
+ LPCREATESTRUCT lpcs = (CREATESTRUCT*)lParam;
+
+ if( !CB_GETTYPE(lphc) ) lphc->dwStyle |= CBS_SIMPLE;
+ else if( CB_GETTYPE(lphc) != CBS_DROPDOWNLIST ) lphc->wState |= CBF_EDIT;
+
+ lphc->self = wnd;
+ lphc->owner = lpcs->hwndParent;
+
+ /* M$ IE 3.01 actually creates (and rapidly destroys) an ownerless combobox */
+
+ if( lphc->owner || !(lpcs->style & WS_VISIBLE) )
+ {
+ UINT lbeStyle;
+ RECT editRect, btnRect, lbRect;
+
+ GetWindowRect( wnd->hwndSelf, &lphc->RectCombo );
+
+ lphc->wState |= CBF_MEASUREITEM;
+ CBCalcPlacement( lphc, &editRect, &btnRect, &lbRect );
+ lphc->RectButton = btnRect;
+ lphc->droppedWidth = lphc->editHeight = 0;
+
+ /* create listbox popup */
+
+ lbeStyle = (LBS_NOTIFY | WS_BORDER | WS_CLIPSIBLINGS) |
+ (lpcs->style & (WS_VSCROLL | CBS_OWNERDRAWFIXED | CBS_OWNERDRAWVARIABLE));
+
+ if( lphc->dwStyle & CBS_SORT )
+ lbeStyle |= LBS_SORT;
+ if( lphc->dwStyle & CBS_HASSTRINGS )
+ lbeStyle |= LBS_HASSTRINGS;
+ if( lphc->dwStyle & CBS_NOINTEGRALHEIGHT )
+ lbeStyle |= LBS_NOINTEGRALHEIGHT;
+ if( lphc->dwStyle & CBS_DISABLENOSCROLL )
+ lbeStyle |= LBS_DISABLENOSCROLL;
+
+ if( CB_GETTYPE(lphc) == CBS_SIMPLE ) /* child listbox */
+ lbeStyle |= WS_CHILD | WS_VISIBLE;
+ else /* popup listbox */
+ {
+ lbeStyle |= WS_POPUP;
+ OffsetRect( &lbRect, lphc->RectCombo.left, lphc->RectCombo.top );
+ }
+
+ /* Dropdown ComboLBox is not a child window and we cannot pass
+ * ID_CB_LISTBOX directly because it will be treated as a menu handle.
+ */
+
+ lphc->hWndLBox = CreateWindowExA( 0, clbName, NULL, lbeStyle,
+ lbRect.left + SYSMETRICS_CXBORDER,
+ lbRect.top + SYSMETRICS_CYBORDER,
+ lbRect.right - lbRect.left - 2 * SYSMETRICS_CXBORDER,
+ lbRect.bottom - lbRect.top - 2 * SYSMETRICS_CYBORDER,
+ lphc->self->hwndSelf,
+ (lphc->dwStyle & CBS_DROPDOWN)? (HMENU)0 : (HMENU)ID_CB_LISTBOX,
+ lphc->self->hInstance, (LPVOID)lphc );
+ if( lphc->hWndLBox )
+ {
+ WINBOOL bEdit = TRUE;
+ lbeStyle = WS_CHILD | WS_VISIBLE | WS_BORDER | ES_NOHIDESEL | ES_LEFT;
+ if( lphc->wState & CBF_EDIT )
+ {
+ if( lphc->dwStyle & CBS_OEMCONVERT )
+ lbeStyle |= ES_OEMCONVERT;
+ if( lphc->dwStyle & CBS_AUTOHSCROLL )
+ lbeStyle |= ES_AUTOHSCROLL;
+ if( lphc->dwStyle & CBS_LOWERCASE )
+ lbeStyle |= ES_LOWERCASE;
+ else if( lphc->dwStyle & CBS_UPPERCASE )
+ lbeStyle |= ES_UPPERCASE;
+ lphc->hWndEdit = CreateWindowExA( 0, editName, NULL, lbeStyle,
+ editRect.left, editRect.top, editRect.right - editRect.left,
+ editRect.bottom - editRect.top, lphc->self->hwndSelf,
+ (HMENU)ID_CB_EDIT, lphc->self->hInstance, NULL );
+ if( !lphc->hWndEdit ) bEdit = FALSE;
+ }
+
+ if( bEdit )
+ {
+ lphc->RectEdit = editRect;
+ if( CB_GETTYPE(lphc) != CBS_SIMPLE )
+ {
+ lphc->wState |= CBF_NORESIZE;
+ SetWindowPos( wnd->hwndSelf, 0, 0, 0,
+ lphc->RectCombo.right - lphc->RectCombo.left,
+ lphc->RectEdit.bottom - lphc->RectEdit.top,
+ SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE );
+ lphc->wState &= ~CBF_NORESIZE;
+ }
+ DPRINT("init done\n");
+ return (LRESULT)wnd->hwndSelf;
+ }
+ DPRINT("edit control failure.\n");
+ } else DPRINT("listbox failure.\n");
+ } else DPRINT("no owner for visible combo.\n");
+
+ /* CreateWindow() will send WM_NCDESTROY to cleanup */
+
+ return -1;
+}
+
+/***********************************************************************
+ * CBPaintButton
+ *
+ * Paint combo button (normal, pressed, and disabled states).
+ */
+static void CBPaintButton(LPHEADCOMBO lphc, HDC hdc)
+{
+ RECT r;
+ UINT x, y;
+ WINBOOL bWINBOOL;
+ HDC hMemDC;
+ HBRUSH hPrevBrush;
+ COLORREF oldTextColor, oldBkColor;
+
+ if( lphc->wState & CBF_NOREDRAW ) return;
+
+ hPrevBrush = SelectObject(hdc, GetSysColorBrush(COLOR_BTNFACE));
+ r = lphc->RectButton;
+
+ Rectangle(hdc, r.left, r.top, r.right, r.bottom );
+ if( (bWINBOOL = lphc->wState & CBF_BUTTONDOWN) )
+ {
+ DrawEdge( hdc, &r, EDGE_SUNKEN, BF_RECT );
+ OffsetRect( &r, 1, 1 );
+ } else {
+ r.top++, r.left++;
+ DrawEdge( hdc, &r, EDGE_RAISED, BF_RECT );
+ r.top--, r.left--;
+ }
+
+ InflateRect( &r, -1, -1 );
+
+ x = (r.left + r.right - CBitWidth) >> 1;
+ y = (r.top + r.bottom - CBitHeight) >> 1;
+
+ InflateRect( &r, -3, -3 );
+
+ hMemDC = CreateCompatibleDC( hdc );
+ SelectObject( hMemDC, hComboBmp );
+ oldTextColor = SetTextColor( hdc, GetSysColor(COLOR_BTNFACE) );
+ oldBkColor = SetBkColor( hdc, CB_DISABLED(lphc) ? RGB(128,128,128) :
+ RGB(0,0,0) );
+ BitBlt( hdc, x, y, 8, 8, hMemDC, 0, 0, SRCCOPY );
+ SetBkColor( hdc, oldBkColor );
+ SetTextColor( hdc, oldTextColor );
+ DeleteDC( hMemDC );
+ SelectObject( hdc, hPrevBrush );
+}
+
+/***********************************************************************
+ * CBPaintText
+ *
+ * Paint CBS_DROPDOWNLIST text field / update edit control contents.
+ */
+static void CBPaintText(LPHEADCOMBO lphc, HDC hdc)
+{
+ INT id, size = 0;
+ LPSTR pText = NULL;
+
+ if( lphc->wState & CBF_NOREDRAW ) return;
+
+ /* follow Windows combobox that sends a bunch of text
+ * inquiries to its listbox while processing WM_PAINT. */
+
+ if( (id = SendMessageA(lphc->hWndLBox, LB_GETCURSEL, 0, 0) ) != LB_ERR )
+ {
+ size = SendMessageA( lphc->hWndLBox, LB_GETTEXTLEN, id, 0);
+ if( (pText = HeapAlloc( GetProcessHeap(), 0, size + 1)) )
+ {
+ SendMessageA( lphc->hWndLBox, LB_GETTEXT, (WPARAM)id, (LPARAM)pText );
+ pText[size] = '\0'; /* just in case */
+ } else return;
+ }
+
+ if( lphc->wState & CBF_EDIT )
+ {
+ if( CB_HASSTRINGS(lphc) ) SetWindowTextA( lphc->hWndEdit, pText ? pText : "" );
+ if( lphc->wState & CBF_FOCUSED )
+ SendMessageA( lphc->hWndEdit, EM_SETSEL, 0, (LPARAM)(-1));
+ }
+ else /* paint text field ourselves */
+ {
+ HBRUSH hPrevBrush = 0;
+ HDC hDC = hdc;
+
+ if( !hDC )
+ {
+ if ((hDC = GetDC(lphc->self->hwndSelf)))
+ {
+ HBRUSH hBrush = (HBRUSH)SendMessageA( lphc->owner,
+ WM_CTLCOLORLISTBOX,
+ (WPARAM)hDC, (LPARAM)lphc->self->hwndSelf );
+ hPrevBrush = SelectObject( hDC,
+ (hBrush) ? hBrush : GetStockObject(WHITE_BRUSH) );
+ }
+ }
+ if( hDC )
+ {
+ RECT rect;
+ UINT itemState;
+ HFONT hPrevFont = (lphc->hFont) ? SelectObject(hDC, lphc->hFont) : 0;
+
+ PatBlt( hDC, (rect.left = lphc->RectEdit.left + SYSMETRICS_CXBORDER),
+ (rect.top = lphc->RectEdit.top + SYSMETRICS_CYBORDER),
+ (rect.right = lphc->RectEdit.right - SYSMETRICS_CXBORDER),
+ (rect.bottom = lphc->RectEdit.bottom - SYSMETRICS_CYBORDER) - 1, PATCOPY );
+ InflateRect( &rect, -1, -1 );
+
+ if( lphc->wState & CBF_FOCUSED &&
+ !(lphc->wState & CBF_DROPPED) )
+ {
+ /* highlight */
+
+ FillRect( hDC, &rect, GetSysColorBrush(COLOR_HIGHLIGHT) );
+ SetBkColor( hDC, GetSysColor( COLOR_HIGHLIGHT ) );
+ SetTextColor( hDC, GetSysColor( COLOR_HIGHLIGHTTEXT ) );
+ itemState = ODS_SELECTED | ODS_FOCUS;
+ } else itemState = 0;
+
+ if( CB_OWNERDRAWN(lphc) )
+ {
+ DRAWITEMSTRUCT dis;
+
+ if( lphc->self->dwStyle & WS_DISABLED ) itemState |= ODS_DISABLED;
+
+ dis.CtlType = ODT_COMBOBOX;
+ dis.CtlID = lphc->self->wIDmenu;
+ dis.hwndItem = lphc->self->hwndSelf;
+ dis.itemAction = ODA_DRAWENTIRE;
+ dis.itemID = id;
+ dis.itemState = itemState;
+ dis.hDC = hDC;
+ dis.rcItem = rect;
+ dis.itemData = SendMessageA( lphc->hWndLBox, LB_GETITEMDATA,
+ (WPARAM)id, 0 );
+ SendMessageA( lphc->owner, WM_DRAWITEM,
+ lphc->self->wIDmenu, (LPARAM)&dis );
+ }
+ else
+ {
+ ExtTextOutA( hDC, rect.left + 1, rect.top + 1,
+ ETO_OPAQUE | ETO_CLIPPED, &rect,
+ pText ? pText : "" , size, NULL );
+ if(lphc->wState & CBF_FOCUSED && !(lphc->wState & CBF_DROPPED))
+ DrawFocusRect( hDC, &rect );
+ }
+
+ if( hPrevFont ) SelectObject(hDC, hPrevFont );
+ if( !hdc )
+ {
+ if( hPrevBrush ) SelectObject( hDC, hPrevBrush );
+ ReleaseDC( lphc->self->hwndSelf, hDC );
+ }
+ }
+ }
+ if (pText)
+ HeapFree( GetProcessHeap(), 0, pText );
+}
+
+/***********************************************************************
+ * COMBO_Paint
+ */
+static LRESULT COMBO_Paint(LPHEADCOMBO lphc, HDC hParamDC)
+{
+ PAINTSTRUCT ps;
+ HDC hDC;
+
+ hDC = (hParamDC) ? hParamDC
+ : BeginPaint( lphc->self->hwndSelf, &ps);
+ if( hDC && !(lphc->wState & CBF_NOREDRAW) )
+ {
+ HBRUSH hPrevBrush, hBkgBrush;
+
+ hBkgBrush = (HBRUSH)SendMessageA( lphc->owner, WM_CTLCOLORLISTBOX,
+ (WPARAM)hDC, (LPARAM)lphc->self->hwndSelf );
+ if( !hBkgBrush ) hBkgBrush = GetStockObject(WHITE_BRUSH);
+
+ hPrevBrush = SelectObject( hDC, hBkgBrush );
+ if( !IsRectEmpty(&lphc->RectButton) )
+ {
+ /* paint everything to the right of the text field */
+
+ PatBlt( hDC, lphc->RectEdit.right, lphc->RectEdit.top,
+ lphc->RectButton.right - lphc->RectEdit.right,
+ lphc->RectEdit.bottom - lphc->RectEdit.top, PATCOPY );
+ CBPaintButton( lphc, hDC );
+ }
+
+ if( !(lphc->wState & CBF_EDIT) )
+ {
+ /* paint text field */
+
+ HPEN hPrevPen = SelectObject( hDC, GetSysColorPen(
+ COLOR_WINDOWFRAME) );
+
+ Rectangle( hDC, lphc->RectEdit.left, lphc->RectEdit.top,
+ lphc->RectEdit.right, lphc->RectButton.bottom );
+ SelectObject( hDC, hPrevPen );
+ CBPaintText( lphc, hDC );
+ }
+ if( hPrevBrush ) SelectObject( hDC, hPrevBrush );
+ }
+ if( !hParamDC ) EndPaint(lphc->self->hwndSelf, &ps);
+ return 0;
+}
+
+/***********************************************************************
+ * CBUpdateLBox
+ *
+ * Select listbox entry according to the contents of the edit control.
+ */
+static INT CBUpdateLBox( LPHEADCOMBO lphc )
+{
+ INT length, idx, ret;
+ LPSTR pText = NULL;
+
+ idx = ret = LB_ERR;
+ length = CB_GETEDITTEXTLENGTH( lphc );
+
+ if( length > 0 )
+ pText = (LPSTR) HeapAlloc( GetProcessHeap(), 0, length + 1);
+
+ DPRINT("\t edit text length %i\n", length );
+
+ if( pText )
+ {
+ if( length ) GetWindowTextA( lphc->hWndEdit, pText, length + 1);
+ else pText[0] = '\0';
+ idx = SendMessageA( lphc->hWndLBox, LB_FINDSTRING,
+ (WPARAM)(-1), (LPARAM)pText );
+ if( idx == LB_ERR ) idx = 0; /* select first item */
+ else ret = idx;
+ HeapFree( GetProcessHeap(), 0, pText );
+ }
+
+ /* select entry */
+
+ SendMessageA( lphc->hWndLBox, LB_SETCURSEL, (WPARAM)idx, 0 );
+
+ if( idx >= 0 )
+ {
+ SendMessageA( lphc->hWndLBox, LB_SETTOPINDEX, (WPARAM)idx, 0 );
+ /* probably superfluous but Windows sends this too */
+ SendMessageA( lphc->hWndLBox, LB_SETCARETINDEX, (WPARAM)idx, 0 );
+ }
+ return ret;
+}
+
+/***********************************************************************
+ * CBUpdateEdit
+ *
+ * Copy a listbox entry to the edit control.
+ */
+static void CBUpdateEdit( LPHEADCOMBO lphc , INT index )
+{
+ INT length;
+ LPSTR pText = NULL;
+
+ DPRINT("\t %i\n", index );
+
+ if( index == -1 )
+ {
+ length = CB_GETEDITTEXTLENGTH( lphc );
+ if( length )
+ {
+ if( (pText = (LPSTR) HeapAlloc( GetProcessHeap(), 0, length + 1)) )
+ {
+ GetWindowTextA( lphc->hWndEdit, pText, length + 1 );
+ index = SendMessageA( lphc->hWndLBox, LB_FINDSTRING,
+ (WPARAM)(-1), (LPARAM)pText );
+ HeapFree( GetProcessHeap(), 0, pText );
+ }
+ }
+ }
+
+ if( index >= 0 ) /* got an entry */
+ {
+ length = SendMessageA( lphc->hWndLBox, LB_GETTEXTLEN, (WPARAM)index, 0);
+ if( length )
+ {
+ if( (pText = (LPSTR) HeapAlloc( GetProcessHeap(), 0, length + 1)) )
+ {
+ SendMessageA( lphc->hWndLBox, LB_GETTEXT,
+ (WPARAM)index, (LPARAM)pText );
+ SendMessageA( lphc->hWndEdit, WM_SETTEXT, 0, (LPARAM)pText );
+ SendMessageA( lphc->hWndEdit, EM_SETSEL, 0, (LPARAM)(-1) );
+ HeapFree( GetProcessHeap(), 0, pText );
+ }
+ }
+ }
+}
+
+/***********************************************************************
+ * CBDropDown
+ *
+ * Show listbox popup.
+ */
+static void CBDropDown( LPHEADCOMBO lphc )
+{
+ INT index;
+ RECT rect;
+ LPRECT pRect = NULL;
+
+ DPRINT("[%04x]: drop down\n", CB_HWND(lphc));
+
+ CB_NOTIFY( lphc, CBN_DROPDOWN );
+
+ /* set selection */
+
+ lphc->wState |= CBF_DROPPED;
+ if( CB_GETTYPE(lphc) == CBS_DROPDOWN )
+ {
+ index = CBUpdateLBox( lphc );
+ if( !(lphc->wState & CBF_CAPTURE) ) CBUpdateEdit( lphc, index );
+ }
+ else
+ {
+ index = SendMessageA( lphc->hWndLBox, LB_GETCURSEL, 0, 0 );
+ if( index == LB_ERR ) index = 0;
+ SendMessageA( lphc->hWndLBox, LB_SETTOPINDEX, (WPARAM)index, 0 );
+ SendMessageA( lphc->hWndLBox, LB_CARETON, 0, 0 );
+ pRect = &lphc->RectEdit;
+ }
+
+ /* now set popup position */
+
+ GetWindowRect( lphc->self->hwndSelf, &rect );
+
+ rect.top += lphc->RectEdit.bottom - lphc->RectEdit.top - SYSMETRICS_CYBORDER;
+ rect.bottom = rect.top + lphc->RectCombo.bottom -
+ lphc->RectCombo.top - SYSMETRICS_CYBORDER;
+ rect.right = rect.left + lphc->RectCombo.right - lphc->RectCombo.left;
+ rect.left += ( CB_GETTYPE(lphc) == CBS_DROPDOWNLIST ) ? 0 : CBitOffset;
+
+ SetWindowPos( lphc->hWndLBox, HWND_TOP, rect.left, rect.top,
+ rect.right - rect.left, rect.bottom - rect.top,
+ SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOREDRAW);
+
+ if( !(lphc->wState & CBF_NOREDRAW) )
+ if( pRect )
+ RedrawWindow( lphc->self->hwndSelf, pRect, 0, RDW_INVALIDATE |
+ RDW_ERASE | RDW_UPDATENOW | RDW_NOCHILDREN );
+ ShowWindow( lphc->hWndLBox, SW_SHOWNA );
+}
+
+/***********************************************************************
+ * CBRollUp
+ *
+ * Hide listbox popup.
+ */
+static void CBRollUp( LPHEADCOMBO lphc, WINBOOL ok, WINBOOL bButton )
+{
+ HWND hWnd = lphc->self->hwndSelf;
+
+ CB_NOTIFY( lphc, (ok) ? CBN_SELENDOK : CBN_SELENDCANCEL );
+
+ if( IsWindow( hWnd ) && CB_GETTYPE(lphc) != CBS_SIMPLE )
+ {
+
+ DPRINT("[%04x]: roll up [%i]\n", CB_HWND(lphc), (INT)ok );
+
+ /* always send WM_LBUTTONUP? */
+ SendMessageA( lphc->hWndLBox, WM_LBUTTONUP, 0, (LPARAM)(-1) );
+
+ if( lphc->wState & CBF_DROPPED )
+ {
+ RECT rect;
+
+ lphc->wState &= ~CBF_DROPPED;
+ ShowWindow( lphc->hWndLBox, SW_HIDE );
+
+ if( CB_GETTYPE(lphc) == CBS_DROPDOWN )
+ {
+ INT index = SendMessageA( lphc->hWndLBox, LB_GETCURSEL, 0, 0 );
+ CBUpdateEdit( lphc, index );
+ rect = lphc->RectButton;
+ }
+ else
+ {
+ if( bButton )
+ UnionRect( &rect, &lphc->RectButton,
+ &lphc->RectEdit );
+ else
+ rect = lphc->RectEdit;
+ bButton = TRUE;
+ }
+
+ if( bButton && !(lphc->wState & CBF_NOREDRAW) )
+ RedrawWindow( hWnd, &rect, 0, RDW_INVALIDATE |
+ RDW_ERASE | RDW_UPDATENOW | RDW_NOCHILDREN );
+ CB_NOTIFY( lphc, CBN_CLOSEUP );
+ }
+ }
+}
+
+/***********************************************************************
+ * COMBO_FlipListbox
+ *
+ * Used by the ComboLBox to show/hide itself in response to VK_F4, etc...
+ */
+WINBOOL COMBO_FlipListbox( LPHEADCOMBO lphc, WINBOOL bRedrawButton )
+{
+ if( lphc->wState & CBF_DROPPED )
+ {
+ CBRollUp( lphc, TRUE, bRedrawButton );
+ return FALSE;
+ }
+
+ CBDropDown( lphc );
+ return TRUE;
+}
+
+/***********************************************************************
+ * COMBO_GetLBWindow
+ *
+ * Edit control helper.
+ */
+HWND COMBO_GetLBWindow( WND* pWnd )
+{
+ LPHEADCOMBO lphc = CB_GETPTR(pWnd);
+ if( lphc ) return lphc->hWndLBox;
+ return 0;
+}
+
+
+/***********************************************************************
+ * CBRepaintButton
+ */
+static void CBRepaintButton( LPHEADCOMBO lphc )
+{
+ HDC hDC = GetDC( lphc->self->hwndSelf );
+
+ if( hDC )
+ {
+ CBPaintButton( lphc, hDC );
+ ReleaseDC( lphc->self->hwndSelf, hDC );
+ }
+}
+
+/***********************************************************************
+ * COMBO_SetFocus
+ */
+static void COMBO_SetFocus( LPHEADCOMBO lphc )
+{
+ if( !(lphc->wState & CBF_FOCUSED) )
+ {
+ if( CB_GETTYPE(lphc) == CBS_DROPDOWNLIST )
+ SendMessageA( lphc->hWndLBox, LB_CARETON, 0, 0 );
+
+ if( lphc->wState & CBF_EDIT )
+ SendMessageA( lphc->hWndEdit, EM_SETSEL, 0, (LPARAM)(-1) );
+ lphc->wState |= CBF_FOCUSED;
+ if( !(lphc->wState & CBF_EDIT) ) CBPaintText( lphc, 0 );
+
+ CB_NOTIFY( lphc, CBN_SETFOCUS );
+ }
+}
+
+/***********************************************************************
+ * COMBO_KillFocus
+ */
+static void COMBO_KillFocus( LPHEADCOMBO lphc )
+{
+ HWND hWnd = lphc->self->hwndSelf;
+
+ if( lphc->wState & CBF_FOCUSED )
+ {
+ SendMessageA( hWnd, WM_LBUTTONUP, 0, (LPARAM)(-1) );
+
+ CBRollUp( lphc, FALSE, TRUE );
+ if( IsWindow( hWnd ) )
+ {
+ if( CB_GETTYPE(lphc) == CBS_DROPDOWNLIST )
+ SendMessageA( lphc->hWndLBox, LB_CARETOFF, 0, 0 );
+
+ lphc->wState &= ~CBF_FOCUSED;
+
+ /* redraw text */
+ if( lphc->wState & CBF_EDIT )
+ SendMessageA( lphc->hWndEdit, EM_SETSEL, (WPARAM)(-1), 0 );
+ else CBPaintText( lphc, 0 );
+
+ CB_NOTIFY( lphc, CBN_KILLFOCUS );
+ }
+ }
+}
+
+/***********************************************************************
+ * COMBO_Command
+ */
+static LRESULT COMBO_Command( LPHEADCOMBO lphc, WPARAM wParam, HWND hWnd )
+{
+ if( lphc->wState & CBF_EDIT && lphc->hWndEdit == hWnd )
+ {
+ /* ">> 8" makes gcc generate jump-table instead of cmp ladder */
+
+ switch( HIWORD(wParam) >> 8 )
+ {
+ case (EN_SETFOCUS >> 8):
+
+ DPRINT("[%04x]: edit [%04x] got focus\n",
+ CB_HWND(lphc), lphc->hWndEdit );
+
+ if( !(lphc->wState & CBF_FOCUSED) ) COMBO_SetFocus( lphc );
+ break;
+
+ case (EN_KILLFOCUS >> 8):
+
+ DPRINT("[%04x]: edit [%04x] lost focus\n",
+ CB_HWND(lphc), lphc->hWndEdit );
+
+ /* NOTE: it seems that Windows' edit control sends an
+ * undocumented message WM_USER + 0x1B instead of this
+ * notification (only when it happens to be a part of
+ * the combo). ?? - AK.
+ */
+
+ COMBO_KillFocus( lphc );
+ break;
+
+
+ case (EN_CHANGE >> 8):
+ CB_NOTIFY( lphc, CBN_EDITCHANGE );
+ CBUpdateLBox( lphc );
+ break;
+
+ case (EN_UPDATE >> 8):
+ CB_NOTIFY( lphc, CBN_EDITUPDATE );
+ break;
+
+ case (EN_ERRSPACE >> 8):
+ CB_NOTIFY( lphc, CBN_ERRSPACE );
+ }
+ }
+ else if( lphc->hWndLBox == hWnd )
+ {
+ switch( HIWORD(wParam) )
+ {
+ case LBN_ERRSPACE:
+ CB_NOTIFY( lphc, CBN_ERRSPACE );
+ break;
+
+ case LBN_DBLCLK:
+ CB_NOTIFY( lphc, CBN_DBLCLK );
+ break;
+
+ case LBN_SELCHANGE:
+ case LBN_SELCANCEL:
+
+ DPRINT("[%04x]: lbox selection change [%04x]\n",
+ CB_HWND(lphc), lphc->wState );
+
+ /* do not roll up if selection is being tracked
+ * by arrowkeys in the dropdown listbox */
+
+ if( (lphc->wState & CBF_DROPPED) && !(lphc->wState & CBF_NOROLLUP) )
+ CBRollUp( lphc, (HIWORD(wParam) == LBN_SELCHANGE), TRUE );
+ else lphc->wState &= ~CBF_NOROLLUP;
+
+ CB_NOTIFY( lphc, CBN_SELCHANGE );
+ CBPaintText( lphc, 0 );
+ /* fall through */
+
+ case LBN_SETFOCUS:
+ case LBN_KILLFOCUS:
+ /* nothing to do here since ComboLBox always resets the focus to its
+ * combo/edit counterpart */
+ break;
+ }
+ }
+ return 0;
+}
+
+/***********************************************************************
+ * COMBO_ItemOp
+ *
+ * Fixup an ownerdrawn item operation and pass it up to the combobox owner.
+ */
+static LRESULT COMBO_ItemOp( LPHEADCOMBO lphc, UINT msg,
+ WPARAM wParam, LPARAM lParam )
+{
+ HWND hWnd = lphc->self->hwndSelf;
+
+ DPRINT("[%04x]: ownerdraw op %04x\n", CB_HWND(lphc), msg );
+
+#define lpIS ((LPDELETEITEMSTRUCT)lParam)
+
+ /* two first items are the same in all 4 structs */
+ lpIS->CtlType = ODT_COMBOBOX;
+ lpIS->CtlID = lphc->self->wIDmenu;
+
+ switch( msg ) /* patch window handle */
+ {
+ case WM_DELETEITEM:
+ lpIS->hwndItem = hWnd;
+#undef lpIS
+ break;
+ case WM_DRAWITEM:
+#define lpIS ((LPDRAWITEMSTRUCT)lParam)
+ lpIS->hwndItem = hWnd;
+#undef lpIS
+ break;
+ case WM_COMPAREITEM:
+#define lpIS ((LPCOMPAREITEMSTRUCT)lParam)
+ lpIS->hwndItem = hWnd;
+#undef lpIS
+ break;
+ }
+
+ return SendMessageA( lphc->owner, msg, lphc->self->wIDmenu, lParam );
+}
+
+/***********************************************************************
+ * COMBO_GetText
+ */
+static LRESULT COMBO_GetText( LPHEADCOMBO lphc, UINT N, LPSTR lpText)
+{
+ if( lphc->wState & CBF_EDIT )
+ return SendMessageA( lphc->hWndEdit, WM_GETTEXT,
+ (WPARAM)N, (LPARAM)lpText );
+
+ /* get it from the listbox */
+
+ if( lphc->hWndLBox )
+ {
+ INT idx = SendMessageA( lphc->hWndLBox, LB_GETCURSEL, 0, 0 );
+ if( idx != LB_ERR )
+ {
+ LPSTR lpBuffer;
+ INT length = SendMessageA( lphc->hWndLBox, LB_GETTEXTLEN,
+ (WPARAM)idx, 0 );
+
+ /* 'length' is without the terminating character */
+ if( length >= N )
+ lpBuffer = (LPSTR) HeapAlloc( GetProcessHeap(), 0, length + 1 );
+ else
+ lpBuffer = lpText;
+
+ if( lpBuffer )
+ {
+ INT n = SendMessageA( lphc->hWndLBox, LB_GETTEXT,
+ (WPARAM)idx, (LPARAM)lpBuffer );
+
+ /* truncate if buffer is too short */
+
+ if( length >= N )
+ {
+ if (N && lpText) {
+ if( n != LB_ERR ) memcpy( lpText, lpBuffer, (N>n) ? n+1 : N-1 );
+ lpText[N - 1] = '\0';
+ }
+ HeapFree( GetProcessHeap(), 0, lpBuffer );
+ }
+ return (LRESULT)n;
+ }
+ }
+ }
+ return 0;
+}
+
+
+/***********************************************************************
+ * CBResetPos
+ *
+ * This function sets window positions according to the updated
+ * component placement struct.
+ */
+static void CBResetPos( LPHEADCOMBO lphc, LPRECT lbRect, WINBOOL bRedraw )
+{
+ WINBOOL bDrop = (CB_GETTYPE(lphc) != CBS_SIMPLE);
+
+ /* NOTE: logs sometimes have WM_LBUTTONUP before a cascade of
+ * sizing messages */
+
+ if( lphc->wState & CBF_EDIT )
+ SetWindowPos( lphc->hWndEdit, 0, lphc->RectEdit.left, lphc->RectEdit.top,
+ lphc->RectEdit.right - lphc->RectEdit.left,
+ lphc->RectEdit.bottom - lphc->RectEdit.top,
+ SWP_NOZORDER | SWP_NOACTIVATE | ((bDrop) ? SWP_NOREDRAW : 0) );
+
+ if( bDrop )
+ OffsetRect( lbRect, lphc->RectCombo.left, lphc->RectCombo.top );
+
+ lbRect->right -= lbRect->left; /* convert to width */
+ lbRect->bottom -= lbRect->top;
+ SetWindowPos( lphc->hWndLBox, 0, lbRect->left, lbRect->top,
+ lbRect->right, lbRect->bottom,
+ SWP_NOACTIVATE | SWP_NOZORDER | ((bDrop) ? SWP_NOREDRAW : 0) );
+
+ if( bDrop )
+ {
+ if( lphc->wState & CBF_DROPPED )
+ {
+ lphc->wState &= ~CBF_DROPPED;
+ ShowWindow( lphc->hWndLBox, SW_HIDE );
+ }
+
+ lphc->wState |= CBF_NORESIZE;
+ SetWindowPos( lphc->self->hwndSelf, 0, 0, 0,
+ lphc->RectCombo.right - lphc->RectCombo.left,
+ lphc->RectEdit.bottom - lphc->RectEdit.top,
+ SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW );
+ lphc->wState &= ~CBF_NORESIZE;
+
+ if( bRedraw && !(lphc->wState & CBF_NOREDRAW) )
+ RedrawWindow( lphc->self->hwndSelf, NULL, 0,
+ RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW );
+ }
+}
+
+
+/***********************************************************************
+ * COMBO_Size
+ */
+static void COMBO_Size( LPHEADCOMBO lphc )
+{
+ RECT rect;
+ INT w, h;
+
+ GetWindowRect( lphc->self->hwndSelf, &rect );
+ w = rect.right - rect.left; h = rect.bottom - rect.top;
+
+ DPRINT("w = %i, h = %i\n", w, h );
+
+ /* CreateWindow() may send a bogus WM_SIZE, ignore it */
+
+ if( w == (lphc->RectCombo.right - lphc->RectCombo.left) )
+ {
+ if( (CB_GETTYPE(lphc) == CBS_SIMPLE) &&
+ (h == (lphc->RectCombo.bottom - lphc->RectCombo.top)) )
+ return;
+ else if( (lphc->dwStyle & CBS_DROPDOWN) &&
+ (h == (lphc->RectEdit.bottom - lphc->RectEdit.top)) )
+ return;
+ }
+ lphc->RectCombo = rect;
+ CBCalcPlacement( lphc, &lphc->RectEdit, &lphc->RectButton, &rect );
+ CBResetPos( lphc, &rect, TRUE );
+}
+
+
+/***********************************************************************
+ * COMBO_Font
+ */
+static void COMBO_Font( LPHEADCOMBO lphc, HFONT hFont, WINBOOL bRedraw )
+{
+ RECT rect;
+
+ lphc->hFont = hFont;
+
+ if( lphc->wState & CBF_EDIT )
+ SendMessageA( lphc->hWndEdit, WM_SETFONT, (WPARAM)hFont, bRedraw );
+ SendMessageA( lphc->hWndLBox, WM_SETFONT, (WPARAM)hFont, bRedraw );
+
+ GetWindowRect( lphc->self->hwndSelf, &rect );
+ OffsetRect( &lphc->RectCombo, rect.left - lphc->RectCombo.left,
+ rect.top - lphc->RectCombo.top );
+ CBCalcPlacement( lphc, &lphc->RectEdit,
+ &lphc->RectButton, &rect );
+ CBResetPos( lphc, &rect, bRedraw );
+}
+
+
+/***********************************************************************
+ * COMBO_SetItemHeight
+ */
+static LRESULT COMBO_SetItemHeight( LPHEADCOMBO lphc, INT index, INT height )
+{
+ LRESULT lRet = CB_ERR;
+
+ if( index == -1 ) /* set text field height */
+ {
+ if( height < 768 )
+ {
+ RECT rect;
+
+ lphc->editHeight = height;
+ GetWindowRect( lphc->self->hwndSelf, &rect );
+ OffsetRect( &lphc->RectCombo, rect.left - lphc->RectCombo.left,
+ rect.top - lphc->RectCombo.top );
+ CBCalcPlacement( lphc, &lphc->RectEdit,
+ &lphc->RectButton, &rect );
+ CBResetPos( lphc, &rect, TRUE );
+ lRet = height;
+ }
+ }
+ else if ( CB_OWNERDRAWN(lphc) ) /* set listbox item height */
+ lRet = SendMessageA( lphc->hWndLBox, LB_SETITEMHEIGHT,
+ (WPARAM)index, (LPARAM)height );
+ return lRet;
+}
+
+/***********************************************************************
+ * COMBO_SelectString
+ */
+static LRESULT COMBO_SelectString( LPHEADCOMBO lphc, INT start, LPCSTR pText )
+{
+ INT index = SendMessageA( lphc->hWndLBox, LB_SELECTSTRING,
+ (WPARAM)start, (LPARAM)pText );
+ if( index >= 0 )
+ {
+ if( lphc->wState & CBF_EDIT )
+ CBUpdateEdit( lphc, index );
+ else
+ CBPaintText( lphc, 0 );
+ }
+ return (LRESULT)index;
+}
+
+/***********************************************************************
+ * COMBO_LButtonDown
+ */
+static void COMBO_LButtonDown( LPHEADCOMBO lphc, LPARAM lParam )
+{
+ POINT pt = { LOWORD(lParam), HIWORD(lParam) };
+ WINBOOL bButton = PtInRect(&lphc->RectButton, pt);
+ HWND hWnd = lphc->self->hwndSelf;
+
+ if( (CB_GETTYPE(lphc) == CBS_DROPDOWNLIST) ||
+ (bButton && (CB_GETTYPE(lphc) == CBS_DROPDOWN)) )
+ {
+ lphc->wState |= CBF_BUTTONDOWN;
+ if( lphc->wState & CBF_DROPPED )
+ {
+ /* got a click to cancel selection */
+
+ CBRollUp( lphc, TRUE, FALSE );
+ if( !IsWindow( hWnd ) ) return;
+
+ if( lphc->wState & CBF_CAPTURE )
+ {
+ lphc->wState &= ~CBF_CAPTURE;
+ ReleaseCapture();
+ }
+ lphc->wState &= ~CBF_BUTTONDOWN;
+ }
+ else
+ {
+ /* drop down the listbox and start tracking */
+
+ lphc->wState |= CBF_CAPTURE;
+ CBDropDown( lphc );
+ SetCapture( hWnd );
+ }
+ if( bButton ) CBRepaintButton( lphc );
+ }
+}
+
+/***********************************************************************
+ * COMBO_LButtonUp
+ *
+ * Release capture and stop tracking if needed.
+ */
+static void COMBO_LButtonUp( LPHEADCOMBO lphc, LPARAM lParam )
+{
+ if( lphc->wState & CBF_CAPTURE )
+ {
+ lphc->wState &= ~CBF_CAPTURE;
+ if( CB_GETTYPE(lphc) == CBS_DROPDOWN )
+ {
+ INT index = CBUpdateLBox( lphc );
+ CBUpdateEdit( lphc, index );
+ }
+ ReleaseCapture();
+ }
+
+ if( lphc->wState & CBF_BUTTONDOWN )
+ {
+ lphc->wState &= ~CBF_BUTTONDOWN;
+ CBRepaintButton( lphc );
+ }
+}
+
+/***********************************************************************
+ * COMBO_MouseMove
+ *
+ * Two things to do - track combo button and release capture when
+ * pointer goes into the listbox.
+ */
+static void COMBO_MouseMove( LPHEADCOMBO lphc, WPARAM wParam, LPARAM lParam )
+{
+ POINT pt = { LOWORD(lParam), HIWORD(lParam) };
+ RECT lbRect;
+
+ if( lphc->wState & CBF_BUTTONDOWN )
+ {
+ WINBOOL bButton = PtInRect(&lphc->RectButton, pt);
+
+ if( !bButton )
+ {
+ lphc->wState &= ~CBF_BUTTONDOWN;
+ CBRepaintButton( lphc );
+ }
+ }
+
+ GetClientRect( lphc->hWndLBox, &lbRect );
+ MapWindowPoints( lphc->self->hwndSelf, lphc->hWndLBox, &pt, 1 );
+ if( PtInRect(&lbRect, pt) )
+ {
+ lphc->wState &= ~CBF_CAPTURE;
+ ReleaseCapture();
+ if( CB_GETTYPE(lphc) == CBS_DROPDOWN ) CBUpdateLBox( lphc );
+
+ /* hand over pointer tracking */
+ SendMessageA( lphc->hWndLBox, WM_LBUTTONDOWN, wParam, lParam );
+ }
+}
+
+
+/***********************************************************************
+ * ComboWndProc
+ *
+ * http://www.microsoft.com/msdn/sdk/platforms/doc/sdk/win/ctrl/src/combobox_15.htm
+ */
+LRESULT WINAPI ComboWndProc( HWND hwnd, UINT message,
+ WPARAM wParam, LPARAM lParam )
+{
+ WND* pWnd = WIN_FindWndPtr(hwnd);
+
+ if( pWnd )
+ {
+ LPHEADCOMBO lphc = CB_GETPTR(pWnd);
+
+ DPRINT( "[%04x]: msg %s wp %08x lp %08lx\n",
+ pWnd->hwndSelf, SPY_GetMsgName(message), wParam, lParam );
+
+ if( lphc || message == WM_NCCREATE )
+ switch(message)
+ {
+
+ /* System messages */
+
+ case WM_NCCREATE:
+ return COMBO_NCCreate(pWnd, lParam);
+
+ case WM_NCDESTROY:
+ COMBO_NCDestroy(lphc);
+ break;
+
+ case WM_CREATE:
+ return COMBO_Create(lphc, pWnd, lParam);
+
+ case WM_PAINT:
+ /* wParam may contain a valid HDC! */
+ return COMBO_Paint(lphc, wParam);
+
+ case WM_ERASEBKGND:
+ return TRUE;
+
+ case WM_GETDLGCODE:
+ return (LRESULT)(DLGC_WANTARROWS | DLGC_WANTCHARS);
+
+ case WM_SIZE:
+ if( lphc->hWndLBox &&
+ !(lphc->wState & CBF_NORESIZE) ) COMBO_Size( lphc );
+ return TRUE;
+
+ case WM_SETFONT:
+ COMBO_Font( lphc, (HFONT)wParam, (WINBOOL)lParam );
+ return TRUE;
+
+ case WM_GETFONT:
+ return (LRESULT)lphc->hFont;
+
+ case WM_SETFOCUS:
+ if( lphc->wState & CBF_EDIT )
+ SetFocus( lphc->hWndEdit );
+ else
+ COMBO_SetFocus( lphc );
+ return TRUE;
+
+ case WM_KILLFOCUS:
+#define hwndFocus ((HWND)wParam)
+ if( !hwndFocus ||
+ (hwndFocus != lphc->hWndEdit && hwndFocus != lphc->hWndLBox ))
+ COMBO_KillFocus( lphc );
+#undef hwndFocus
+ return TRUE;
+
+ case WM_COMMAND:
+ return COMBO_Command( lphc, wParam, (HWND)lParam );
+
+ case WM_GETTEXT:
+ return COMBO_GetText( lphc, (UINT)wParam, (LPSTR)lParam );
+
+ case WM_SETTEXT:
+ case WM_GETTEXTLENGTH:
+ case WM_CLEAR:
+ case WM_CUT:
+ case WM_PASTE:
+ case WM_COPY:
+ if( lphc->wState & CBF_EDIT )
+ return SendMessageA( lphc->hWndEdit, message, wParam, lParam );
+ return CB_ERR;
+
+ case WM_DRAWITEM:
+ case WM_DELETEITEM:
+ case WM_COMPAREITEM:
+ case WM_MEASUREITEM:
+ return COMBO_ItemOp( lphc, message, wParam, lParam );
+
+ case WM_ENABLE:
+ if( lphc->wState & CBF_EDIT )
+ EnableWindow( lphc->hWndEdit, (WINBOOL)wParam );
+ EnableWindow( lphc->hWndLBox, (WINBOOL)wParam );
+ return TRUE;
+
+ case WM_SETREDRAW:
+ if( wParam )
+ lphc->wState &= ~CBF_NOREDRAW;
+ else
+ lphc->wState |= CBF_NOREDRAW;
+
+ if( lphc->wState & CBF_EDIT )
+ SendMessageA( lphc->hWndEdit, message, wParam, lParam );
+ SendMessageA( lphc->hWndLBox, message, wParam, lParam );
+ return 0;
+
+ case WM_SYSKEYDOWN:
+ if( KEYDATA_ALT & HIWORD(lParam) )
+ if( wParam == VK_UP || wParam == VK_DOWN )
+ COMBO_FlipListbox( lphc, TRUE );
+ break;
+
+ case WM_CHAR:
+ case WM_KEYDOWN:
+ if( lphc->wState & CBF_EDIT )
+ return SendMessageA( lphc->hWndEdit, message, wParam, lParam );
+ else
+ return SendMessageA( lphc->hWndLBox, message, wParam, lParam );
+
+ case WM_LBUTTONDOWN:
+ if( !(lphc->wState & CBF_FOCUSED) ) SetFocus( lphc->self->hwndSelf );
+ if( lphc->wState & CBF_FOCUSED ) COMBO_LButtonDown( lphc, lParam );
+ return TRUE;
+
+ case WM_LBUTTONUP:
+ COMBO_LButtonUp( lphc, lParam );
+ return TRUE;
+
+ case WM_MOUSEMOVE:
+ if( lphc->wState & CBF_CAPTURE )
+ COMBO_MouseMove( lphc, wParam, lParam );
+ return TRUE;
+
+ /* Combo messages */
+
+ case CB_ADDSTRING:
+ return SendMessageA( lphc->hWndLBox, LB_ADDSTRING, 0, lParam);
+
+ case CB_INSERTSTRING:
+ return SendMessageA( lphc->hWndLBox, LB_INSERTSTRING, wParam, lParam);
+
+ case CB_DELETESTRING:
+ return SendMessageA( lphc->hWndLBox, LB_DELETESTRING, wParam, 0);
+
+ case CB_SELECTSTRING:
+ return COMBO_SelectString( lphc, (INT)wParam, (LPSTR)lParam );
+
+ case CB_FINDSTRING:
+ return SendMessageA( lphc->hWndLBox, LB_FINDSTRING, wParam, lParam);
+
+ case CB_FINDSTRINGEXACT:
+ return SendMessageA( lphc->hWndLBox, LB_FINDSTRINGEXACT,
+ wParam, lParam );
+
+ case CB_SETITEMHEIGHT:
+ return COMBO_SetItemHeight( lphc, (INT)wParam, (INT)lParam);
+
+ case CB_GETITEMHEIGHT:
+ if( (INT)wParam >= 0 ) /* listbox item */
+ return SendMessageA( lphc->hWndLBox, LB_GETITEMHEIGHT, wParam, 0);
+ return (lphc->RectEdit.bottom - lphc->RectEdit.top);
+
+ case CB_RESETCONTENT:
+ SendMessageA( lphc->hWndLBox, LB_RESETCONTENT, 0, 0 );
+ CBPaintText( lphc, 0 );
+ return TRUE;
+
+ case CB_INITSTORAGE:
+ return SendMessageA( lphc->hWndLBox, LB_INITSTORAGE, wParam, lParam);
+
+ case CB_GETHORIZONTALEXTENT:
+ return SendMessageA( lphc->hWndLBox, LB_GETHORIZONTALEXTENT, 0, 0);
+
+ case CB_SETHORIZONTALEXTENT:
+ return SendMessageA( lphc->hWndLBox, LB_SETHORIZONTALEXTENT, wParam, 0);
+
+ case CB_GETTOPINDEX:
+ return SendMessageA( lphc->hWndLBox, LB_GETTOPINDEX, 0, 0);
+
+ case CB_GETLOCALE:
+ return SendMessageA( lphc->hWndLBox, LB_GETLOCALE, 0, 0);
+
+ case CB_SETLOCALE:
+ return SendMessageA( lphc->hWndLBox, LB_SETLOCALE, wParam, 0);
+
+ case CB_GETDROPPEDWIDTH:
+ if( lphc->droppedWidth )
+ return lphc->droppedWidth;
+ return lphc->RectCombo.right - lphc->RectCombo.left -
+ (lphc->wState & CBF_EDIT) ? CBitOffset : 0;
+
+ case CB_SETDROPPEDWIDTH:
+ if( (CB_GETTYPE(lphc) != CBS_SIMPLE) &&
+ (INT)wParam < 768 ) lphc->droppedWidth = (INT)wParam;
+ return CB_ERR;
+
+ case CB_GETDROPPEDCONTROLRECT:
+ if( lParam ) CBGetDroppedControlRect(lphc, (LPRECT)lParam );
+ return CB_OKAY;
+
+ case CB_GETDROPPEDSTATE:
+ return (lphc->wState & CBF_DROPPED) ? TRUE : FALSE;
+
+
+ case CB_DIR:
+ return COMBO_Directory( lphc, (UINT)wParam,
+ (LPSTR)lParam, (message == CB_DIR));
+ case CB_SHOWDROPDOWN:
+ if( CB_GETTYPE(lphc) != CBS_SIMPLE )
+ {
+ if( wParam )
+ {
+ if( !(lphc->wState & CBF_DROPPED) )
+ CBDropDown( lphc );
+ }
+ else
+ if( lphc->wState & CBF_DROPPED )
+ CBRollUp( lphc, FALSE, TRUE );
+ }
+ return TRUE;
+
+ case CB_GETCOUNT:
+ return SendMessageA( lphc->hWndLBox, LB_GETCOUNT, 0, 0);
+
+ case CB_GETCURSEL:
+ return SendMessageA( lphc->hWndLBox, LB_GETCURSEL, 0, 0);
+
+ case CB_SETCURSEL:
+ lParam = SendMessageA( lphc->hWndLBox, LB_SETCURSEL, wParam, 0);
+ if( lphc->wState & CBF_SELCHANGE )
+ {
+ /* no LBN_SELCHANGE in this case, update manually */
+
+ CBPaintText( lphc, 0 );
+ lphc->wState &= ~CBF_SELCHANGE;
+ }
+ return lParam;
+
+
+ case CB_GETLBTEXT:
+ return SendMessageA( lphc->hWndLBox, LB_GETTEXT, wParam, lParam);
+
+ case CB_GETLBTEXTLEN:
+ return SendMessageA( lphc->hWndLBox, LB_GETTEXTLEN, wParam, 0);
+
+ case CB_GETITEMDATA:
+ return SendMessageA( lphc->hWndLBox, LB_GETITEMDATA, wParam, 0);
+
+ case CB_SETITEMDATA:
+ return SendMessageA( lphc->hWndLBox, LB_SETITEMDATA, wParam, lParam);
+
+ case CB_GETEDITSEL:
+ if( lphc->wState & CBF_EDIT )
+ {
+ INT a, b;
+
+ return SendMessageA( lphc->hWndEdit, EM_GETSEL,
+ (wParam) ? wParam : (WPARAM)&a,
+ (lParam) ? lParam : (LPARAM)&b );
+ }
+ return CB_ERR;
+
+
+ case CB_SETEDITSEL:
+ if( lphc->wState & CBF_EDIT )
+ return SendMessageA( lphc->hWndEdit, EM_SETSEL,
+ (INT)(INT)LOWORD(lParam), (INT)(INT)HIWORD(lParam) );
+ return CB_ERR;
+
+
+ case CB_SETEXTENDEDUI:
+ if( CB_GETTYPE(lphc) == CBS_SIMPLE ) return CB_ERR;
+
+ if( wParam )
+ lphc->wState |= CBF_EUI;
+ else lphc->wState &= ~CBF_EUI;
+ return CB_OKAY;
+
+
+ case CB_GETEXTENDEDUI:
+ return (lphc->wState & CBF_EUI) ? TRUE : FALSE;
+
+ case (WM_USER + 0x1B):
+ DPRINT( "[%04x]: undocumented msg!\n", hwnd );
+ }
+ return DefWindowProcA(hwnd, message, wParam, lParam);
+ }
+ return CB_ERR;
+}
+
--- /dev/null
+/*
+ * Edit control
+ *
+ * Copyright David W. Metcalfe, 1994
+ * Copyright William Magro, 1995, 1996
+ * Copyright Frans van Dorsselaer, 1996, 1997
+ *
+ */
+
+/*
+ * please read EDIT.TODO (and update it when you change things)
+ */
+
+#include <windows.h>
+#include <user32/win.h>
+#include <user32/class.h>
+#include <user32/nc.h>
+#include <user32/resource.h>
+#include <user32/combo.h>
+#include <user32/debug.h>
+
+#define MAX(x,y) x > y ? x : y
+#define MIN(x,y) x < y ? x : y
+
+#define BUFLIMIT_MULTI 65534 /* maximum buffer size (not including '\0')
+ FIXME: BTW, new specs say 65535 (do you dare ???) */
+#define BUFLIMIT_SINGLE 766 /* maximum buffer size (not including '\0') */
+#define BUFSTART_MULTI 1024 /* starting size */
+#define BUFSTART_SINGLE 256 /* starting size */
+#define GROWLENGTH 64 /* buffers grow by this much */
+#define HSCROLL_FRACTION 3 /* scroll window by 1/3 width */
+
+/*
+ * extra flags for EDITSTATE.flags field
+ */
+#define EF_MODIFIED 0x0001 /* text has been modified */
+#define EF_FOCUSED 0x0002 /* we have input focus */
+#define EF_UPDATE 0x0004 /* notify parent of changed state on next WM_PAINT */
+#define EF_VSCROLL_TRACK 0x0008 /* don't SetScrollPos() since we are tracking the thumb */
+#define EF_HSCROLL_TRACK 0x0010 /* don't SetScrollPos() since we are tracking the thumb */
+#define EF_VSCROLL_HACK 0x0020 /* we already have informed the user of the hacked handler */
+#define EF_HSCROLL_HACK 0x0040 /* we already have informed the user of the hacked handler */
+#define EF_AFTER_WRAP 0x0080 /* the caret is displayed after the last character of a
+ wrapped line, instead of in front of the next character */
+#define EF_USE_SOFTBRK 0x0100 /* Enable soft breaks in text. */
+
+typedef enum
+{
+ END_0 = 0, /* line ends with terminating '\0' character */
+ END_WRAP, /* line is wrapped */
+ END_HARD, /* line ends with a hard return '\r\n' */
+ END_SOFT /* line ends with a soft return '\r\r\n' */
+} LINE_END;
+
+typedef struct tagLINEDEF {
+ INT length; /* bruto length of a line in bytes */
+ INT net_length; /* netto length of a line in visible characters */
+ LINE_END ending;
+ INT width; /* width of the line in pixels */
+ struct tagLINEDEF *next;
+} LINEDEF;
+
+typedef INT (CALLBACK *EDITWORDBREAKPROCA)(LPSTR,INT,INT,INT);
+typedef INT (CALLBACK *EDITWORDBREAKPROCW)(LPWSTR,INT,INT,INT);
+
+typedef struct
+{
+ HANDLE heap; /* our own heap */
+ LPSTR text; /* the actual contents of the control */
+ INT buffer_size; /* the size of the buffer */
+ INT buffer_limit; /* the maximum size to which the buffer may grow */
+ HFONT font; /* NULL means standard system font */
+ INT x_offset; /* scroll offset for multi lines this is in pixels
+ for single lines it's in characters */
+ INT line_height; /* height of a screen line in pixels */
+ INT char_width; /* average character width in pixels */
+ DWORD style; /* sane version of wnd->dwStyle */
+ WORD flags; /* flags that are not in es->style or wnd->flags (EF_XXX) */
+ INT undo_insert_count; /* number of characters inserted in sequence */
+ INT undo_position; /* character index of the insertion and deletion */
+ LPSTR undo_text; /* deleted text */
+ INT undo_buffer_size; /* size of the deleted text buffer */
+ INT selection_start; /* == selection_end if no selection */
+ INT selection_end; /* == current caret position */
+ CHAR password_char; /* == 0 if no password char, and for multi line controls */
+ INT left_margin; /* in pixels */
+ INT right_margin; /* in pixels */
+ RECT format_rect;
+ INT region_posx; /* Position of cursor relative to region: */
+ INT region_posy; /* -1: to left, 0: within, 1: to right */
+ EDITWORDBREAKPROCA word_break_procA;
+ EDITWORDBREAKPROCW word_break_procW;
+ INT line_count; /* number of lines */
+ INT y_offset; /* scroll offset in number of lines */
+ /*
+ * only for multi line controls
+ */
+ INT lock_count; /* amount of re-entries in the EditWndProc */
+ INT tabs_count;
+ LPINT tabs;
+ INT text_width; /* width of the widest line in pixels */
+ LINEDEF *first_line_def; /* linked list of (soft) linebreaks */
+ HLOCAL hloc; /* for controls receiving EM_GETHANDLE */
+} EDITSTATE;
+
+#define SLOWORD(l) ((INT)(LONG)(l))
+#define SHIWORD(l) ((INT)((LONG)(l) >> 16))
+
+
+#define SWAP_INT(x,y) do { INT temp = (INT)(x); (x) = (INT)(y); (y) = temp; } while(0)
+#define ORDER_INT(x,y) do { if ((INT)(y) < (INT)(x)) SWAP_INT((x),(y)); } while(0)
+
+#define SWAP_UINT(x,y) do { UINT temp = (UINT)(x); (x) = (UINT)(y); (y) = temp; } while(0)
+#define ORDER_UINT(x,y) do { if ((UINT)(y) < (UINT)(x)) SWAP_UINT((x),(y)); } while(0)
+
+#define DPRINTF_EDIT_NOTIFY(hwnd, str) \
+ ({DPRINT( "notification " str " sent to hwnd=%08x\n", \
+ (UINT)(hwnd));})
+
+#define EDIT_SEND_CTLCOLOR(wnd,hdc) \
+ (SendMessageA((wnd)->parent->hwndSelf, WM_CTLCOLOREDIT, \
+ (WPARAM)(hdc), (LPARAM)(wnd)->hwndSelf))
+#define EDIT_NOTIFY_PARENT(wnd, wNotifyCode, str) \
+ (DPRINTF_EDIT_NOTIFY((wnd)->parent->hwndSelf, str), \
+ SendMessageA((wnd)->parent->hwndSelf, WM_COMMAND, \
+ MAKEWPARAM((wnd)->wIDmenu, wNotifyCode), \
+ (LPARAM)(wnd)->hwndSelf))
+
+#define DPRINTF_EDIT_MSG(str) \
+ DPRINT( \
+ " bit : " str ": hwnd=%08x, wParam=%08x, lParam=%08x\n", \
+ (UINT)hwnd, (UINT)wParam, (UINT)lParam)
+
+/*********************************************************************
+ *
+ * Declarations
+ *
+ */
+
+/*
+ * These functions have trivial implementations
+ * We still like to call them internally
+ * "static __inline__" makes them more like macro's
+ */
+static __inline__ BOOL EDIT_EM_CanUndo(WND *wnd, EDITSTATE *es);
+static __inline__ void EDIT_EM_EmptyUndoBuffer(WND *wnd, EDITSTATE *es);
+static __inline__ void EDIT_WM_Clear(WND *wnd, EDITSTATE *es);
+static __inline__ void EDIT_WM_Cut(WND *wnd, EDITSTATE *es);
+/*
+ * This is the only exported function
+ */
+LRESULT WINAPI EditWndProc( HWND hwnd, UINT msg,
+ WPARAM wParam, LPARAM lParam );
+/*
+ * Helper functions only valid for one type of control
+ */
+static void EDIT_BuildLineDefs_ML(WND *wnd, EDITSTATE *es);
+static LPSTR EDIT_GetPasswordPointer_SL(WND *wnd, EDITSTATE *es);
+static void EDIT_MoveDown_ML(WND *wnd, EDITSTATE *es, BOOL extend);
+static void EDIT_MovePageDown_ML(WND *wnd, EDITSTATE *es, BOOL extend);
+static void EDIT_MovePageUp_ML(WND *wnd, EDITSTATE *es, BOOL extend);
+static void EDIT_MoveUp_ML(WND *wnd, EDITSTATE *es, BOOL extend);
+/*
+ * Helper functions valid for both single line _and_ multi line controls
+ */
+static INT EDIT_CallWordBreakProc(WND *wnd, EDITSTATE *es, INT start, INT index, INT count, INT action);
+static INT EDIT_CharFromPos(WND *wnd, EDITSTATE *es, INT x, INT y, LPBOOL after_wrap);
+static void EDIT_ConfinePoint(WND *wnd, EDITSTATE *es, LPINT x, LPINT y);
+static void EDIT_GetLineRect(WND *wnd, EDITSTATE *es, INT line, INT scol, INT ecol, LPRECT rc);
+static void EDIT_InvalidateText(WND *wnd, EDITSTATE *es, INT start, INT end);
+static void EDIT_LockBuffer(WND *wnd, EDITSTATE *es);
+static BOOL EDIT_MakeFit(WND *wnd, EDITSTATE *es, INT size);
+static BOOL EDIT_MakeUndoFit(WND *wnd, EDITSTATE *es, INT size);
+static void EDIT_MoveBackward(WND *wnd, EDITSTATE *es, BOOL extend);
+static void EDIT_MoveEnd(WND *wnd, EDITSTATE *es, BOOL extend);
+static void EDIT_MoveForward(WND *wnd, EDITSTATE *es, BOOL extend);
+static void EDIT_MoveHome(WND *wnd, EDITSTATE *es, BOOL extend);
+static void EDIT_MoveWordBackward(WND *wnd, EDITSTATE *es, BOOL extend);
+static void EDIT_MoveWordForward(WND *wnd, EDITSTATE *es, BOOL extend);
+static void EDIT_PaintLine(WND *wnd, EDITSTATE *es, HDC hdc, INT line, BOOL rev);
+static INT EDIT_PaintText(WND *wnd, EDITSTATE *es, HDC hdc, INT x, INT y, INT line, INT col, INT count, BOOL rev);
+static void EDIT_SetCaretPos(WND *wnd, EDITSTATE *es, INT pos, BOOL after_wrap);
+static void EDIT_SetRectNP(WND *wnd, EDITSTATE *es, LPRECT lprc);
+static void EDIT_UnlockBuffer(WND *wnd, EDITSTATE *es, BOOL force);
+static INT EDIT_WordBreakProc(LPSTR s, INT index, INT count, INT action);
+/*
+ * EM_XXX message handlers
+ */
+static LRESULT EDIT_EM_CharFromPos(WND *wnd, EDITSTATE *es, INT x, INT y);
+static BOOL EDIT_EM_FmtLines(WND *wnd, EDITSTATE *es, BOOL add_eol);
+static HLOCAL EDIT_EM_GetHandle(WND *wnd, EDITSTATE *es);
+static INT EDIT_EM_GetLine(WND *wnd, EDITSTATE *es, INT line, LPSTR lpch);
+static LRESULT EDIT_EM_GetSel(WND *wnd, EDITSTATE *es, UINT *start, UINT *end);
+static LRESULT EDIT_EM_GetThumb(WND *wnd, EDITSTATE *es);
+static INT EDIT_EM_LineFromChar(WND *wnd, EDITSTATE *es, INT index);
+static INT EDIT_EM_LineIndex(WND *wnd, EDITSTATE *es, INT line);
+static INT EDIT_EM_LineLength(WND *wnd, EDITSTATE *es, INT index);
+static BOOL EDIT_EM_LineScroll(WND *wnd, EDITSTATE *es, INT dx, INT dy);
+static LRESULT EDIT_EM_PosFromChar(WND *wnd, EDITSTATE *es, INT index, BOOL after_wrap);
+static void EDIT_EM_ReplaceSel(WND *wnd, EDITSTATE *es, BOOL can_undo, LPCSTR lpsz_replace);
+static LRESULT EDIT_EM_Scroll(WND *wnd, EDITSTATE *es, INT action);
+static void EDIT_EM_ScrollCaret(WND *wnd, EDITSTATE *es);
+static void EDIT_EM_SetHandle(WND *wnd, EDITSTATE *es, HLOCAL hloc);
+static void EDIT_EM_SetLimitText(WND *wnd, EDITSTATE *es, INT limit);
+static void EDIT_EM_SetMargins(WND *wnd, EDITSTATE *es, INT action, INT left, INT right);
+static void EDIT_EM_SetPasswordChar(WND *wnd, EDITSTATE *es, CHAR c);
+static void EDIT_EM_SetSel(WND *wnd, EDITSTATE *es, UINT start, UINT end, BOOL after_wrap);
+static BOOL EDIT_EM_SetTabStops(WND *wnd, EDITSTATE *es, INT count, LPINT tabs);
+static void EDIT_EM_SetWordBreakProc(WND *wnd, EDITSTATE *es, EDITWORDBREAKPROCA wbp);
+static BOOL EDIT_EM_Undo(WND *wnd, EDITSTATE *es);
+/*
+ * WM_XXX message handlers
+ */
+static void EDIT_WM_Char(WND *wnd, EDITSTATE *es, CHAR c, DWORD key_data);
+static void EDIT_WM_Command(WND *wnd, EDITSTATE *es, INT code, INT id, HWND conrtol);
+static void EDIT_WM_ContextMenu(WND *wnd, EDITSTATE *es, HWND hwnd, INT x, INT y);
+static void EDIT_WM_Copy(WND *wnd, EDITSTATE *es);
+static LRESULT EDIT_WM_Create(WND *wnd, EDITSTATE *es, LPCREATESTRUCTA cs);
+static void EDIT_WM_Destroy(WND *wnd, EDITSTATE *es);
+static LRESULT EDIT_WM_EraseBkGnd(WND *wnd, EDITSTATE *es, HDC dc);
+static INT EDIT_WM_GetText(WND *wnd, EDITSTATE *es, INT count, LPSTR text);
+static LRESULT EDIT_WM_HScroll(WND *wnd, EDITSTATE *es, INT action, INT pos, HWND scroll_bar);
+static LRESULT EDIT_WM_KeyDown(WND *wnd, EDITSTATE *es, INT key, DWORD key_data);
+static LRESULT EDIT_WM_KillFocus(WND *wnd, EDITSTATE *es, HWND window_getting_focus);
+static LRESULT EDIT_WM_LButtonDblClk(WND *wnd, EDITSTATE *es, DWORD keys, INT x, INT y);
+static LRESULT EDIT_WM_LButtonDown(WND *wnd, EDITSTATE *es, DWORD keys, INT x, INT y);
+static LRESULT EDIT_WM_LButtonUp(WND *wnd, EDITSTATE *es, DWORD keys, INT x, INT y);
+static LRESULT EDIT_WM_MouseMove(WND *wnd, EDITSTATE *es, DWORD keys, INT x, INT y);
+static LRESULT EDIT_WM_NCCreate(WND *wnd, LPCREATESTRUCTA cs);
+static void EDIT_WM_Paint(WND *wnd, EDITSTATE *es);
+static void EDIT_WM_Paste(WND *wnd, EDITSTATE *es);
+static void EDIT_WM_SetFocus(WND *wnd, EDITSTATE *es, HWND window_losing_focus);
+static void EDIT_WM_SetFont(WND *wnd, EDITSTATE *es, HFONT font, BOOL redraw);
+static void EDIT_WM_SetText(WND *wnd, EDITSTATE *es, LPCSTR text);
+static void EDIT_WM_Size(WND *wnd, EDITSTATE *es, UINT action, INT width, INT height);
+static LRESULT EDIT_WM_SysKeyDown(WND *wnd, EDITSTATE *es, INT key, DWORD key_data);
+static void EDIT_WM_Timer(WND *wnd, EDITSTATE *es, INT id, TIMERPROC timer_proc);
+static LRESULT EDIT_WM_VScroll(WND *wnd, EDITSTATE *es, INT action, INT pos, HWND scroll_bar);
+
+
+/*********************************************************************
+ *
+ * EM_CANUNDO
+ *
+ */
+static __inline__ BOOL EDIT_EM_CanUndo(WND *wnd, EDITSTATE *es)
+{
+ return (es->undo_insert_count || lstrlenA(es->undo_text));
+}
+
+
+/*********************************************************************
+ *
+ * EM_EMPTYUNDOBUFFER
+ *
+ */
+static __inline__ void EDIT_EM_EmptyUndoBuffer(WND *wnd, EDITSTATE *es)
+{
+ es->undo_insert_count = 0;
+ *es->undo_text = '\0';
+}
+
+
+/*********************************************************************
+ *
+ * WM_CLEAR
+ *
+ */
+static __inline__ void EDIT_WM_Clear(WND *wnd, EDITSTATE *es)
+{
+ EDIT_EM_ReplaceSel(wnd, es, TRUE, "");
+}
+
+
+/*********************************************************************
+ *
+ * WM_CUT
+ *
+ */
+static __inline__ void EDIT_WM_Cut(WND *wnd, EDITSTATE *es)
+{
+ EDIT_WM_Copy(wnd, es);
+ EDIT_WM_Clear(wnd, es);
+}
+
+
+/*********************************************************************
+ *
+ * EditWndProc()
+ *
+ * The messages are in the order of the actual integer values
+ * (which can be found in include/windows.h)
+ * Whereever possible the 16 bit versions are converted to
+ * the bit ones, so that we can 'fall through' to the
+ * helper functions. These are mostly bit (with a few
+ * exceptions, clearly indicated by a '16' extension to their
+ * names).
+ *
+ */
+LRESULT WINAPI EditWndProc( HWND hwnd, UINT msg,
+ WPARAM wParam, LPARAM lParam )
+{
+ WND *wnd = WIN_FindWndPtr(hwnd);
+ EDITSTATE *es = *(EDITSTATE **)((wnd)->wExtra);
+ LRESULT result = 0;
+
+ switch (msg) {
+ case WM_DESTROY:
+ DPRINTF_EDIT_MSG("WM_DESTROY");
+ EDIT_WM_Destroy(wnd, es);
+ return 0;
+
+ case WM_NCCREATE:
+ DPRINTF_EDIT_MSG("WM_NCCREATE");
+ return EDIT_WM_NCCreate(wnd, (LPCREATESTRUCTA)lParam);
+ }
+
+ if (!es)
+ return DefWindowProcA(hwnd, msg, wParam, lParam);
+
+ EDIT_LockBuffer(wnd, es);
+ switch (msg) {
+ case EM_GETSEL:
+ DPRINTF_EDIT_MSG("EM_GETSEL");
+ result = EDIT_EM_GetSel(wnd, es, (UINT *)wParam, (UINT *)lParam);
+ break;
+
+
+ case EM_SETSEL:
+ DPRINTF_EDIT_MSG("EM_SETSEL");
+ EDIT_EM_SetSel(wnd, es, wParam, lParam, FALSE);
+ result = 1;
+ break;
+
+
+ case EM_GETRECT:
+ DPRINTF_EDIT_MSG("EM_GETRECT");
+ if (lParam)
+ CopyRect((LPRECT)lParam, &es->format_rect);
+ break;
+
+
+ case EM_SETRECT:
+ DPRINTF_EDIT_MSG("EM_SETRECT");
+ if ((es->style & ES_MULTILINE) && lParam) {
+ EDIT_SetRectNP(wnd, es, (LPRECT)lParam);
+ InvalidateRect(wnd->hwndSelf, NULL, TRUE);
+ }
+ break;
+
+
+ case EM_SETRECTNP:
+ DPRINTF_EDIT_MSG("EM_SETRECTNP");
+ if ((es->style & ES_MULTILINE) && lParam)
+ EDIT_SetRectNP(wnd, es, (LPRECT)lParam);
+ break;
+
+
+ case EM_SCROLL:
+ DPRINTF_EDIT_MSG("EM_SCROLL");
+ result = EDIT_EM_Scroll(wnd, es, (INT)wParam);
+ break;
+
+
+ case EM_LINESCROLL:
+ DPRINTF_EDIT_MSG("EM_LINESCROLL");
+ result = (LRESULT)EDIT_EM_LineScroll(wnd, es, (INT)wParam, (INT)lParam);
+ break;
+
+
+ case EM_SCROLLCARET:
+ DPRINTF_EDIT_MSG("EM_SCROLLCARET");
+ EDIT_EM_ScrollCaret(wnd, es);
+ result = 1;
+ break;
+
+ case EM_GETMODIFY:
+ DPRINTF_EDIT_MSG("EM_GETMODIFY");
+ return ((es->flags & EF_MODIFIED) != 0);
+ break;
+
+ case EM_SETMODIFY:
+ DPRINTF_EDIT_MSG("EM_SETMODIFY");
+ if (wParam)
+ es->flags |= EF_MODIFIED;
+ else
+ es->flags &= ~EF_MODIFIED;
+ break;
+
+ case EM_GETLINECOUNT:
+ DPRINTF_EDIT_MSG("EM_GETLINECOUNT");
+ result = (es->style & ES_MULTILINE) ? es->line_count : 1;
+ break;
+
+ case EM_LINEINDEX:
+ DPRINTF_EDIT_MSG("EM_LINEINDEX");
+ result = (LRESULT)EDIT_EM_LineIndex(wnd, es, (INT)wParam);
+ break;
+
+ case EM_SETHANDLE:
+ DPRINTF_EDIT_MSG("EM_SETHANDLE");
+ EDIT_EM_SetHandle(wnd, es, (HLOCAL)wParam);
+ break;
+
+ case EM_GETHANDLE:
+ DPRINTF_EDIT_MSG("EM_GETHANDLE");
+ result = (LRESULT)EDIT_EM_GetHandle(wnd, es);
+ break;
+
+ case EM_GETTHUMB:
+ DPRINTF_EDIT_MSG("EM_GETTHUMB");
+ result = EDIT_EM_GetThumb(wnd, es);
+ break;
+
+ /* messages 0x00bf and 0x00c0 missing from specs */
+
+ case 0x00bf:
+ DPRINTF_EDIT_MSG("undocumented 0x00bf, please report");
+ result = DefWindowProcA(hwnd, msg, wParam, lParam);
+ break;
+
+ case 0x00c0:
+ DPRINTF_EDIT_MSG("undocumented 0x00c0, please report");
+ result = DefWindowProcA(hwnd, msg, wParam, lParam);
+ break;
+
+ case EM_LINELENGTH:
+ DPRINTF_EDIT_MSG("EM_LINELENGTH");
+ result = (LRESULT)EDIT_EM_LineLength(wnd, es, (INT)wParam);
+ break;
+
+
+ case EM_REPLACESEL:
+ DPRINTF_EDIT_MSG("EM_REPLACESEL");
+ EDIT_EM_ReplaceSel(wnd, es, (BOOL)wParam, (LPCSTR)lParam);
+ result = 1;
+ break;
+
+ /* message 0x00c3 missing from specs */
+
+ case 0x00c3:
+ DPRINTF_EDIT_MSG("undocumented 0x00c3, please report");
+ result = DefWindowProcA(hwnd, msg, wParam, lParam);
+ break;
+
+ case EM_GETLINE:
+ DPRINTF_EDIT_MSG("EM_GETLINE");
+ result = (LRESULT)EDIT_EM_GetLine(wnd, es, (INT)wParam, (LPSTR)lParam);
+ break;
+
+ case EM_SETLIMITTEXT:
+ DPRINTF_EDIT_MSG("EM_SETLIMITTEXT");
+ EDIT_EM_SetLimitText(wnd, es, (INT)wParam);
+ break;
+
+ case EM_CANUNDO:
+ DPRINTF_EDIT_MSG("EM_CANUNDO");
+ result = (LRESULT)EDIT_EM_CanUndo(wnd, es);
+ break;
+
+ case EM_UNDO:
+ /* fall through */
+ case WM_UNDO:
+ DPRINTF_EDIT_MSG("EM_UNDO / WM_UNDO");
+ result = (LRESULT)EDIT_EM_Undo(wnd, es);
+ break;
+
+ case EM_FMTLINES:
+ DPRINTF_EDIT_MSG("EM_FMTLINES");
+ result = (LRESULT)EDIT_EM_FmtLines(wnd, es, (BOOL)wParam);
+ break;
+
+ case EM_LINEFROMCHAR:
+ DPRINTF_EDIT_MSG("EM_LINEFROMCHAR");
+ result = (LRESULT)EDIT_EM_LineFromChar(wnd, es, (INT)wParam);
+ break;
+
+ /* message 0x00ca missing from specs */
+
+ case 0x00ca:
+ DPRINTF_EDIT_MSG("undocumented 0x00ca, please report");
+ result = DefWindowProcA(hwnd, msg, wParam, lParam);
+ break;
+
+ case EM_SETTABSTOPS:
+ DPRINTF_EDIT_MSG("EM_SETTABSTOPS");
+ result = (LRESULT)EDIT_EM_SetTabStops(wnd, es, (INT)wParam, (LPINT)lParam);
+ break;
+
+ case EM_SETPASSWORDCHAR:
+ DPRINTF_EDIT_MSG("EM_SETPASSWORDCHAR");
+ EDIT_EM_SetPasswordChar(wnd, es, (CHAR)wParam);
+ break;
+
+ case EM_EMPTYUNDOBUFFER:
+ DPRINTF_EDIT_MSG("EM_EMPTYUNDOBUFFER");
+ EDIT_EM_EmptyUndoBuffer(wnd, es);
+ break;
+
+ case EM_GETFIRSTVISIBLELINE:
+ DPRINTF_EDIT_MSG("EM_GETFIRSTVISIBLELINE");
+ result = (es->style & ES_MULTILINE) ? es->y_offset : es->x_offset;
+ break;
+
+ case EM_SETREADONLY:
+ DPRINTF_EDIT_MSG("EM_SETREADONLY");
+ if (wParam) {
+ wnd->dwStyle |= ES_READONLY;
+ es->style |= ES_READONLY;
+ } else {
+ wnd->dwStyle &= ~ES_READONLY;
+ es->style &= ~ES_READONLY;
+ }
+ return 1;
+ break;
+
+ case EM_SETWORDBREAKPROC:
+ DPRINTF_EDIT_MSG("EM_SETWORDBREAKPROC");
+ EDIT_EM_SetWordBreakProc(wnd, es, (EDITWORDBREAKPROCA)lParam);
+ break;
+
+ case EM_GETWORDBREAKPROC:
+ DPRINTF_EDIT_MSG("EM_GETWORDBREAKPROC");
+ result = (LRESULT)es->word_break_procA;
+ break;
+
+ case EM_GETPASSWORDCHAR:
+ DPRINTF_EDIT_MSG("EM_GETPASSWORDCHAR");
+ result = es->password_char;
+ break;
+
+ /* The following EM_xxx are new to win95 and don't exist for 16 bit */
+
+ case EM_SETMARGINS:
+ DPRINTF_EDIT_MSG("EM_SETMARGINS");
+ EDIT_EM_SetMargins(wnd, es, (INT)wParam, SLOWORD(lParam), SHIWORD(lParam));
+ break;
+
+ case EM_GETMARGINS:
+ DPRINTF_EDIT_MSG("EM_GETMARGINS");
+ result = MAKELONG(es->left_margin, es->right_margin);
+ break;
+
+ case EM_GETLIMITTEXT:
+ DPRINTF_EDIT_MSG("EM_GETLIMITTEXT");
+ result = es->buffer_limit;
+ break;
+
+ case EM_POSFROMCHAR:
+ DPRINTF_EDIT_MSG("EM_POSFROMCHAR");
+ result = EDIT_EM_PosFromChar(wnd, es, (INT)wParam, FALSE);
+ break;
+
+ case EM_CHARFROMPOS:
+ DPRINTF_EDIT_MSG("EM_CHARFROMPOS");
+ result = EDIT_EM_CharFromPos(wnd, es, SLOWORD(lParam), SHIWORD(lParam));
+ break;
+
+ case WM_GETDLGCODE:
+ DPRINTF_EDIT_MSG("WM_GETDLGCODE");
+ result = (es->style & ES_MULTILINE) ?
+ DLGC_WANTALLKEYS | DLGC_HASSETSEL | DLGC_WANTCHARS | DLGC_WANTARROWS :
+ DLGC_HASSETSEL | DLGC_WANTCHARS | DLGC_WANTARROWS;
+ break;
+
+ case WM_CHAR:
+ DPRINTF_EDIT_MSG("WM_CHAR");
+ EDIT_WM_Char(wnd, es, (CHAR)wParam, (DWORD)lParam);
+ break;
+
+ case WM_CLEAR:
+ DPRINTF_EDIT_MSG("WM_CLEAR");
+ EDIT_WM_Clear(wnd, es);
+ break;
+
+ case WM_COMMAND:
+ DPRINTF_EDIT_MSG("WM_COMMAND");
+ EDIT_WM_Command(wnd, es, HIWORD(wParam), LOWORD(wParam), (HWND)lParam);
+ break;
+
+ case WM_CONTEXTMENU:
+ DPRINTF_EDIT_MSG("WM_CONTEXTMENU");
+ EDIT_WM_ContextMenu(wnd, es, (HWND)wParam, SLOWORD(lParam), SHIWORD(lParam));
+ break;
+
+ case WM_COPY:
+ DPRINTF_EDIT_MSG("WM_COPY");
+ EDIT_WM_Copy(wnd, es);
+ break;
+
+ case WM_CREATE:
+ DPRINTF_EDIT_MSG("WM_CREATE");
+ result = EDIT_WM_Create(wnd, es, (LPCREATESTRUCTA)lParam);
+ break;
+
+ case WM_CUT:
+ DPRINTF_EDIT_MSG("WM_CUT");
+ EDIT_WM_Cut(wnd, es);
+ break;
+
+ case WM_ENABLE:
+ DPRINTF_EDIT_MSG("WM_ENABLE");
+ InvalidateRect(hwnd, NULL, TRUE);
+ break;
+
+ case WM_ERASEBKGND:
+ DPRINTF_EDIT_MSG("WM_ERASEBKGND");
+ result = EDIT_WM_EraseBkGnd(wnd, es, (HDC)wParam);
+ break;
+
+ case WM_GETFONT:
+ DPRINTF_EDIT_MSG("WM_GETFONT");
+ result = (LRESULT)es->font;
+ break;
+
+ case WM_GETTEXT:
+ DPRINTF_EDIT_MSG("WM_GETTEXT");
+ result = (LRESULT)EDIT_WM_GetText(wnd, es, (INT)wParam, (LPSTR)lParam);
+ break;
+
+ case WM_GETTEXTLENGTH:
+ DPRINTF_EDIT_MSG("WM_GETTEXTLENGTH");
+ result = lstrlenA(es->text);
+ break;
+
+ case WM_HSCROLL:
+ DPRINTF_EDIT_MSG("WM_HSCROLL");
+ result = EDIT_WM_HScroll(wnd, es, LOWORD(wParam), SHIWORD(wParam), (HWND)lParam);
+ break;
+
+ case WM_KEYDOWN:
+ DPRINTF_EDIT_MSG("WM_KEYDOWN");
+ result = EDIT_WM_KeyDown(wnd, es, (INT)wParam, (DWORD)lParam);
+ break;
+
+ case WM_KILLFOCUS:
+ DPRINTF_EDIT_MSG("WM_KILLFOCUS");
+ result = EDIT_WM_KillFocus(wnd, es, (HWND)wParam);
+ break;
+
+ case WM_LBUTTONDBLCLK:
+ DPRINTF_EDIT_MSG("WM_LBUTTONDBLCLK");
+ result = EDIT_WM_LButtonDblClk(wnd, es, (DWORD)wParam, SLOWORD(lParam), SHIWORD(lParam));
+ break;
+
+ case WM_LBUTTONDOWN:
+ DPRINTF_EDIT_MSG("WM_LBUTTONDOWN");
+ result = EDIT_WM_LButtonDown(wnd, es, (DWORD)wParam, SLOWORD(lParam), SHIWORD(lParam));
+ break;
+
+ case WM_LBUTTONUP:
+ DPRINTF_EDIT_MSG("WM_LBUTTONUP");
+ result = EDIT_WM_LButtonUp(wnd, es, (DWORD)wParam, SLOWORD(lParam), SHIWORD(lParam));
+ break;
+
+ case WM_MOUSEACTIVATE:
+ /*
+ * FIXME: maybe DefWindowProc() screws up, but it seems that
+ * modalless dialog boxes need this. If we don't do this, the focus
+ * will _not_ be set by DefWindowProc() for edit controls in a
+ * modalless dialog box ???
+ */
+ DPRINTF_EDIT_MSG("WM_MOUSEACTIVATE");
+ SetFocus(wnd->hwndSelf);
+ result = MA_ACTIVATE;
+ break;
+
+ case WM_MOUSEMOVE:
+ /*
+ * DPRINTF_EDIT_MSG("WM_MOUSEMOVE");
+ */
+ result = EDIT_WM_MouseMove(wnd, es, (DWORD)wParam, SLOWORD(lParam), SHIWORD(lParam));
+ break;
+
+ case WM_PAINT:
+ DPRINTF_EDIT_MSG("WM_PAINT");
+ EDIT_WM_Paint(wnd, es);
+ break;
+
+ case WM_PASTE:
+ DPRINTF_EDIT_MSG("WM_PASTE");
+ EDIT_WM_Paste(wnd, es);
+ break;
+
+ case WM_SETFOCUS:
+ DPRINTF_EDIT_MSG("WM_SETFOCUS");
+ EDIT_WM_SetFocus(wnd, es, (HWND)wParam);
+ break;
+
+ case WM_SETFONT:
+ DPRINTF_EDIT_MSG("WM_SETFONT");
+ EDIT_WM_SetFont(wnd, es, (HFONT)wParam, LOWORD(lParam) != 0);
+ break;
+
+ case WM_SETTEXT:
+ DPRINTF_EDIT_MSG("WM_SETTEXT");
+ EDIT_WM_SetText(wnd, es, (LPCSTR)lParam);
+ result = TRUE;
+ break;
+
+ case WM_SIZE:
+ DPRINTF_EDIT_MSG("WM_SIZE");
+ EDIT_WM_Size(wnd, es, (UINT)wParam, LOWORD(lParam), HIWORD(lParam));
+ break;
+
+ case WM_SYSKEYDOWN:
+ DPRINTF_EDIT_MSG("WM_SYSKEYDOWN");
+ result = EDIT_WM_SysKeyDown(wnd, es, (INT)wParam, (DWORD)lParam);
+ break;
+
+ case WM_TIMER:
+ DPRINTF_EDIT_MSG("WM_TIMER");
+ EDIT_WM_Timer(wnd, es, (INT)wParam, (TIMERPROC)lParam);
+ break;
+
+ case WM_VSCROLL:
+ DPRINTF_EDIT_MSG("WM_VSCROLL");
+ result = EDIT_WM_VScroll(wnd, es, LOWORD(wParam), SHIWORD(wParam), (HWND)(lParam));
+ break;
+
+ default:
+ result = DefWindowProcA(hwnd, msg, wParam, lParam);
+ break;
+ }
+ EDIT_UnlockBuffer(wnd, es, FALSE);
+ return result;
+}
+
+
+/*********************************************************************
+ *
+ * EDIT_BuildLineDefs_ML
+ *
+ * Build linked list of text lines.
+ * Lines can end with '\0' (last line), a character (if it is wrapped),
+ * a soft return '\r\r\n' or a hard return '\r\n'
+ *
+ */
+static void EDIT_BuildLineDefs_ML(WND *wnd, EDITSTATE *es)
+{
+ HDC dc;
+ HFONT old_font = 0;
+ LPSTR start, cp;
+ INT fw;
+ LINEDEF *current_def;
+ LINEDEF **previous_next;
+
+ current_def = es->first_line_def;
+ do {
+ LINEDEF *next_def = current_def->next;
+ HeapFree(es->heap, 0, current_def);
+ current_def = next_def;
+ } while (current_def);
+ es->line_count = 0;
+ es->text_width = 0;
+
+ dc = GetDC(wnd->hwndSelf);
+ if (es->font)
+ old_font = SelectObject(dc, es->font);
+
+ fw = es->format_rect.right - es->format_rect.left;
+ start = es->text;
+ previous_next = &es->first_line_def;
+ do {
+ current_def = HeapAlloc(es->heap, 0, sizeof(LINEDEF));
+ current_def->next = NULL;
+ cp = start;
+ while (*cp) {
+ if ((*cp == '\r') && (*(cp + 1) == '\n'))
+ break;
+ cp++;
+ }
+ if (!(*cp)) {
+ current_def->ending = END_0;
+ current_def->net_length = lstrlenA(start);
+ } else if ((cp > start) && (*(cp - 1) == '\r')) {
+ current_def->ending = END_SOFT;
+ current_def->net_length = cp - start - 1;
+ } else {
+ current_def->ending = END_HARD;
+ current_def->net_length = cp - start;
+ }
+ current_def->width = (INT)LOWORD(GetTabbedTextExtentA(dc,
+ start, current_def->net_length,
+ es->tabs_count, es->tabs));
+ /* FIXME: check here for lines that are too wide even in AUTOHSCROLL (> 767 ???) */
+ if ((!(es->style & ES_AUTOHSCROLL)) && (current_def->width > fw)) {
+ INT next = 0;
+ INT prev;
+ do {
+ prev = next;
+ next = EDIT_CallWordBreakProc(wnd, es, start - es->text,
+ prev + 1, current_def->net_length, WB_RIGHT);
+ current_def->width = (INT)LOWORD(GetTabbedTextExtentA(dc,
+ start, next, es->tabs_count, es->tabs));
+ } while (current_def->width <= fw);
+ if (!prev) {
+ next = 0;
+ do {
+ prev = next;
+ next++;
+ current_def->width = (INT)LOWORD(GetTabbedTextExtentA(dc,
+ start, next, es->tabs_count, es->tabs));
+ } while (current_def->width <= fw);
+ if (!prev)
+ prev = 1;
+ }
+ current_def->net_length = prev;
+ current_def->ending = END_WRAP;
+ current_def->width = (INT)LOWORD(GetTabbedTextExtentA(dc, start,
+ current_def->net_length, es->tabs_count, es->tabs));
+ }
+ switch (current_def->ending) {
+ case END_SOFT:
+ current_def->length = current_def->net_length + 3;
+ break;
+ case END_HARD:
+ current_def->length = current_def->net_length + 2;
+ break;
+ case END_WRAP:
+ case END_0:
+ current_def->length = current_def->net_length;
+ break;
+ }
+ es->text_width = MAX(es->text_width, current_def->width);
+ start += current_def->length;
+ *previous_next = current_def;
+ previous_next = ¤t_def->next;
+ es->line_count++;
+ } while (current_def->ending != END_0);
+ if (es->font)
+ SelectObject(dc, old_font);
+ ReleaseDC(wnd->hwndSelf, dc);
+}
+
+
+/*********************************************************************
+ *
+ * EDIT_CallWordBreakProc
+ *
+ * Call appropriate WordBreakProc (internal or external).
+ *
+ * Note: The "start" argument should always be an index refering
+ * to es->text. The actual wordbreak proc might be
+ * 16 bit, so we can't always pass any bit LPSTR.
+ * Hence we assume that es->text is the buffer that holds
+ * the string under examination (we can decide this for ourselves).
+ *
+ */
+static INT EDIT_CallWordBreakProc(WND *wnd, EDITSTATE *es, INT start, INT index, INT count, INT action)
+{
+ if (es->word_break_procA)
+ {
+ DPRINT("(wordbrk=%p,str='%s',idx=%d,cnt=%d,act=%d)\n",
+ es->word_break_procA, es->text + start, index,
+ count, action );
+ return (INT)es->word_break_procA( es->text + start, index,
+ count, action );
+ }
+ else
+ return EDIT_WordBreakProc(es->text + start, index, count, action);
+}
+
+
+/*********************************************************************
+ *
+ * EDIT_CharFromPos
+ *
+ * Beware: This is not the function called on EM_CHARFROMPOS
+ * The position _can_ be outside the formatting / client
+ * rectangle
+ * The return value is only the character index
+ *
+ */
+static INT EDIT_CharFromPos(WND *wnd, EDITSTATE *es, INT x, INT y, LPBOOL after_wrap)
+{
+ INT index;
+ HDC dc;
+ HFONT old_font = 0;
+
+ if (es->style & ES_MULTILINE) {
+ INT line = (y - es->format_rect.top) / es->line_height + es->y_offset;
+ INT line_index = 0;
+ LINEDEF *line_def = es->first_line_def;
+ INT low, high;
+ while ((line > 0) && line_def->next) {
+ line_index += line_def->length;
+ line_def = line_def->next;
+ line--;
+ }
+ x += es->x_offset - es->format_rect.left;
+ if (x >= line_def->width) {
+ if (after_wrap)
+ *after_wrap = (line_def->ending == END_WRAP);
+ return line_index + line_def->net_length;
+ }
+ if (x <= 0) {
+ if (after_wrap)
+ *after_wrap = FALSE;
+ return line_index;
+ }
+ dc = GetDC(wnd->hwndSelf);
+ if (es->font)
+ old_font = SelectObject(dc, es->font);
+ low = line_index + 1;
+ high = line_index + line_def->net_length + 1;
+ while (low < high - 1)
+ {
+ INT mid = (low + high) / 2;
+ if (LOWORD(GetTabbedTextExtentA(dc, es->text + line_index,mid - line_index, es->tabs_count, es->tabs)) > x) high = mid;
+ else low = mid;
+ }
+ index = low;
+
+ if (after_wrap)
+ *after_wrap = ((index == line_index + line_def->net_length) &&
+ (line_def->ending == END_WRAP));
+ } else {
+ LPSTR text;
+ SIZE size;
+ if (after_wrap)
+ *after_wrap = FALSE;
+ x -= es->format_rect.left;
+ if (!x)
+ return es->x_offset;
+ text = EDIT_GetPasswordPointer_SL(wnd, es);
+ dc = GetDC(wnd->hwndSelf);
+ if (es->font)
+ old_font = SelectObject(dc, es->font);
+ if (x < 0)
+ {
+ INT low = 0;
+ INT high = es->x_offset;
+ while (low < high - 1)
+ {
+ INT mid = (low + high) / 2;
+ GetTextExtentPointA( dc, text + mid,
+ es->x_offset - mid, &size );
+ if (size.cx > -x) low = mid;
+ else high = mid;
+ }
+ index = low;
+ }
+ else
+ {
+ INT low = es->x_offset;
+ INT high = lstrlenA(es->text) + 1;
+ while (low < high - 1)
+ {
+ INT mid = (low + high) / 2;
+ GetTextExtentPointA( dc, text + es->x_offset,
+ mid - es->x_offset, &size );
+ if (size.cx > x) high = mid;
+ else low = mid;
+ }
+ index = low;
+ }
+ if (es->style & ES_PASSWORD)
+ HeapFree(es->heap, 0 ,text);
+ }
+ if (es->font)
+ SelectObject(dc, old_font);
+ ReleaseDC(wnd->hwndSelf, dc);
+ return index;
+}
+
+
+/*********************************************************************
+ *
+ * EDIT_ConfinePoint
+ *
+ * adjusts the point to be within the formatting rectangle
+ * (so CharFromPos returns the nearest _visible_ character)
+ *
+ */
+static void EDIT_ConfinePoint(WND *wnd, EDITSTATE *es, LPINT x, LPINT y)
+{
+ *x = MIN(MAX(*x, es->format_rect.left), es->format_rect.right - 1);
+ *y = MIN(MAX(*y, es->format_rect.top), es->format_rect.bottom - 1);
+}
+
+
+/*********************************************************************
+ *
+ * EDIT_GetLineRect
+ *
+ * Calculates the bounding rectangle for a line from a starting
+ * column to an ending column.
+ *
+ */
+static void EDIT_GetLineRect(WND *wnd, EDITSTATE *es, INT line, INT scol, INT ecol, LPRECT rc)
+{
+ INT line_index = EDIT_EM_LineIndex(wnd, es, line);
+
+ if (es->style & ES_MULTILINE)
+ rc->top = es->format_rect.top + (line - es->y_offset) * es->line_height;
+ else
+ rc->top = es->format_rect.top;
+ rc->bottom = rc->top + es->line_height;
+ rc->left = (scol == 0) ? es->format_rect.left : SLOWORD(EDIT_EM_PosFromChar(wnd, es, line_index + scol, TRUE));
+ rc->right = (ecol == -1) ? es->format_rect.right : SLOWORD(EDIT_EM_PosFromChar(wnd, es, line_index + ecol, TRUE));
+}
+
+
+/*********************************************************************
+ *
+ * EDIT_GetPasswordPointer_SL
+ *
+ * note: caller should free the (optionally) allocated buffer
+ *
+ */
+static LPSTR EDIT_GetPasswordPointer_SL(WND *wnd, EDITSTATE *es)
+{
+ if (es->style & ES_PASSWORD) {
+ INT len = lstrlenA(es->text);
+ LPSTR text = HeapAlloc(es->heap, 0, len + 1);
+ HEAP_memset(text, len, es->password_char);
+ text[len] = '\0';
+ return text;
+ } else
+ return es->text;
+}
+
+
+/*********************************************************************
+ *
+ * EDIT_LockBuffer
+ *
+ * This acts as a LOCAL_Lock(), but it locks only once. This way
+ * you can call it whenever you like, without unlocking.
+ *
+ */
+static void EDIT_LockBuffer(WND *wnd, EDITSTATE *es)
+{
+ if (!es) {
+ DPRINT( "no EDITSTATE ... please report\n");
+ return;
+ }
+ if (!(es->style & ES_MULTILINE))
+ return;
+ if (!es->text) {
+ if (es->hloc)
+ es->text = LocalLock(es->hloc);
+ else {
+ DPRINT( "no buffer ... please report\n");
+ return;
+ }
+ }
+ es->lock_count++;
+}
+
+
+/*********************************************************************
+ *
+ * EDIT_SL_InvalidateText
+ *
+ * Called from EDIT_InvalidateText().
+ * Does the job for single-line controls only.
+ *
+ */
+static void EDIT_SL_InvalidateText(WND *wnd, EDITSTATE *es, INT start, INT end)
+{
+ RECT line_rect;
+ RECT rc;
+
+ EDIT_GetLineRect(wnd, es, 0, start, end, &line_rect);
+ if (IntersectRect(&rc, &line_rect, &es->format_rect))
+ InvalidateRect(wnd->hwndSelf, &rc, FALSE);
+}
+
+
+/*********************************************************************
+ *
+ * EDIT_ML_InvalidateText
+ *
+ * Called from EDIT_InvalidateText().
+ * Does the job for multi-line controls only.
+ *
+ */
+static void EDIT_ML_InvalidateText(WND *wnd, EDITSTATE *es, INT start, INT end)
+{
+ INT vlc = (es->format_rect.bottom - es->format_rect.top) / es->line_height;
+ INT sl = EDIT_EM_LineFromChar(wnd, es, start);
+ INT el = EDIT_EM_LineFromChar(wnd, es, end);
+ INT sc;
+ INT ec;
+ RECT rc1;
+ RECT rcWnd;
+ RECT rcLine;
+ RECT rcUpdate;
+ INT l;
+
+ if ((el < es->y_offset) || (sl > es->y_offset + vlc))
+ return;
+
+ sc = start - EDIT_EM_LineIndex(wnd, es, sl);
+ ec = end - EDIT_EM_LineIndex(wnd, es, el);
+ if (sl < es->y_offset) {
+ sl = es->y_offset;
+ sc = 0;
+ }
+ if (el > es->y_offset + vlc) {
+ el = es->y_offset + vlc;
+ ec = EDIT_EM_LineLength(wnd, es, EDIT_EM_LineIndex(wnd, es, el));
+ }
+ GetClientRect(wnd->hwndSelf, &rc1);
+ IntersectRect(&rcWnd, &rc1, &es->format_rect);
+ if (sl == el) {
+ EDIT_GetLineRect(wnd, es, sl, sc, ec, &rcLine);
+ if (IntersectRect(&rcUpdate, &rcWnd, &rcLine))
+ InvalidateRect(wnd->hwndSelf, &rcUpdate, FALSE);
+ } else {
+ EDIT_GetLineRect(wnd, es, sl, sc,
+ EDIT_EM_LineLength(wnd, es,
+ EDIT_EM_LineIndex(wnd, es, sl)),
+ &rcLine);
+ if (IntersectRect(&rcUpdate, &rcWnd, &rcLine))
+ InvalidateRect(wnd->hwndSelf, &rcUpdate, FALSE);
+ for (l = sl + 1 ; l < el ; l++) {
+ EDIT_GetLineRect(wnd, es, l, 0,
+ EDIT_EM_LineLength(wnd, es,
+ EDIT_EM_LineIndex(wnd, es, l)),
+ &rcLine);
+ if (IntersectRect(&rcUpdate, &rcWnd, &rcLine))
+ InvalidateRect(wnd->hwndSelf, &rcUpdate, FALSE);
+ }
+ EDIT_GetLineRect(wnd, es, el, 0, ec, &rcLine);
+ if (IntersectRect(&rcUpdate, &rcWnd, &rcLine))
+ InvalidateRect(wnd->hwndSelf, &rcUpdate, FALSE);
+ }
+}
+
+
+/*********************************************************************
+ *
+ * EDIT_InvalidateText
+ *
+ * Invalidate the text from offset start upto, but not including,
+ * offset end. Useful for (re)painting the selection.
+ * Regions outside the linewidth are not invalidated.
+ * end == -1 means end == TextLength.
+ * start and end need not be ordered.
+ *
+ */
+static void EDIT_InvalidateText(WND *wnd, EDITSTATE *es, INT start, INT end)
+{
+ if (end == start)
+ return;
+
+ if (end == -1)
+ end = lstrlenA(es->text);
+
+ ORDER_INT(start, end);
+
+ if (es->style & ES_MULTILINE)
+ EDIT_ML_InvalidateText(wnd, es, start, end);
+ else
+ EDIT_SL_InvalidateText(wnd, es, start, end);
+}
+
+
+/*********************************************************************
+ *
+ * EDIT_MakeFit
+ *
+ * Try to fit size + 1 bytes in the buffer. Constrain to limits.
+ *
+ */
+static BOOL EDIT_MakeFit(WND *wnd, EDITSTATE *es, INT size)
+{
+ HLOCAL hNew;
+
+ if (size <= es->buffer_size)
+ return TRUE;
+ if (size > es->buffer_limit) {
+ EDIT_NOTIFY_PARENT(wnd, EN_MAXTEXT, "EN_MAXTEXT");
+ return FALSE;
+ }
+ size = ((size / GROWLENGTH) + 1) * GROWLENGTH;
+ if (size > es->buffer_limit)
+ size = es->buffer_limit;
+
+ DPRINT( "trying to ReAlloc to %d+1\n", size);
+
+ EDIT_UnlockBuffer(wnd, es, TRUE);
+ if (es->text) {
+ if ((es->text = HeapReAlloc(es->heap, 0, es->text, size + 1)))
+ es->buffer_size = MIN(HeapSize(es->heap, 0, es->text) - 1, es->buffer_limit);
+ else
+ es->buffer_size = 0;
+ } else if (es->hloc) {
+ if ((hNew = LocalReAlloc(es->hloc, size + 1, 0))) {
+ DPRINT( "Old bit handle %08x, new handle %08x\n", es->hloc, hNew);
+ es->hloc = hNew;
+ es->buffer_size = MIN(LocalSize(es->hloc) - 1, es->buffer_limit);
+ }
+ }
+ if (es->buffer_size < size) {
+ EDIT_LockBuffer(wnd, es);
+ DPRINT( "FAILED ! We now have %d+1\n", es->buffer_size);
+ EDIT_NOTIFY_PARENT(wnd, EN_ERRSPACE, "EN_ERRSPACE");
+ return FALSE;
+ } else {
+ EDIT_LockBuffer(wnd, es);
+ DPRINT( "We now have %d+1\n", es->buffer_size);
+ return TRUE;
+ }
+}
+
+
+/*********************************************************************
+ *
+ * EDIT_MakeUndoFit
+ *
+ * Try to fit size + 1 bytes in the undo buffer.
+ *
+ */
+static BOOL EDIT_MakeUndoFit(WND *wnd, EDITSTATE *es, INT size)
+{
+ if (size <= es->undo_buffer_size)
+ return TRUE;
+ size = ((size / GROWLENGTH) + 1) * GROWLENGTH;
+
+ DPRINT( "trying to ReAlloc to %d+1\n", size);
+
+ if ((es->undo_text = HeapReAlloc(es->heap, 0, es->undo_text, size + 1))) {
+ es->undo_buffer_size = HeapSize(es->heap, 0, es->undo_text) - 1;
+ if (es->undo_buffer_size < size) {
+ DPRINT( "FAILED ! We now have %d+1\n", es->undo_buffer_size);
+ return FALSE;
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+/*********************************************************************
+ *
+ * EDIT_MoveBackward
+ *
+ */
+static void EDIT_MoveBackward(WND *wnd, EDITSTATE *es, BOOL extend)
+{
+ INT e = es->selection_end;
+
+ if (e) {
+ e--;
+ if ((es->style & ES_MULTILINE) && e &&
+ (es->text[e - 1] == '\r') && (es->text[e] == '\n')) {
+ e--;
+ if (e && (es->text[e - 1] == '\r'))
+ e--;
+ }
+ }
+ EDIT_EM_SetSel(wnd, es, extend ? es->selection_start : e, e, FALSE);
+ EDIT_EM_ScrollCaret(wnd, es);
+}
+
+
+/*********************************************************************
+ *
+ * EDIT_MoveDown_ML
+ *
+ * Only for multi line controls
+ * Move the caret one line down, on a column with the nearest
+ * x coordinate on the screen (might be a different column).
+ *
+ */
+static void EDIT_MoveDown_ML(WND *wnd, EDITSTATE *es, BOOL extend)
+{
+ INT s = es->selection_start;
+ INT e = es->selection_end;
+ BOOL after_wrap = (es->flags & EF_AFTER_WRAP);
+ LRESULT pos = EDIT_EM_PosFromChar(wnd, es, e, after_wrap);
+ INT x = SLOWORD(pos);
+ INT y = SHIWORD(pos);
+
+ e = EDIT_CharFromPos(wnd, es, x, y + es->line_height, &after_wrap);
+ if (!extend)
+ s = e;
+ EDIT_EM_SetSel(wnd, es, s, e, after_wrap);
+ EDIT_EM_ScrollCaret(wnd, es);
+}
+
+
+/*********************************************************************
+ *
+ * EDIT_MoveEnd
+ *
+ */
+static void EDIT_MoveEnd(WND *wnd, EDITSTATE *es, BOOL extend)
+{
+ BOOL after_wrap = FALSE;
+ INT e;
+
+ if (es->style & ES_MULTILINE)
+ e = EDIT_CharFromPos(wnd, es, 0x7fffffff,
+ HIWORD(EDIT_EM_PosFromChar(wnd, es, es->selection_end, es->flags & EF_AFTER_WRAP)), &after_wrap);
+ else
+ e = lstrlenA(es->text);
+ EDIT_EM_SetSel(wnd, es, extend ? es->selection_start : e, e, after_wrap);
+ EDIT_EM_ScrollCaret(wnd, es);
+}
+
+
+/*********************************************************************
+ *
+ * EDIT_MoveForward
+ *
+ */
+static void EDIT_MoveForward(WND *wnd, EDITSTATE *es, BOOL extend)
+{
+ INT e = es->selection_end;
+
+ if (es->text[e]) {
+ e++;
+ if ((es->style & ES_MULTILINE) && (es->text[e - 1] == '\r')) {
+ if (es->text[e] == '\n')
+ e++;
+ else if ((es->text[e] == '\r') && (es->text[e + 1] == '\n'))
+ e += 2;
+ }
+ }
+ EDIT_EM_SetSel(wnd, es, extend ? es->selection_start : e, e, FALSE);
+ EDIT_EM_ScrollCaret(wnd, es);
+}
+
+
+/*********************************************************************
+ *
+ * EDIT_MoveHome
+ *
+ * Home key: move to beginning of line.
+ *
+ */
+static void EDIT_MoveHome(WND *wnd, EDITSTATE *es, BOOL extend)
+{
+ INT e;
+
+ if (es->style & ES_MULTILINE)
+ e = EDIT_CharFromPos(wnd, es, 0x80000000,
+ HIWORD(EDIT_EM_PosFromChar(wnd, es, es->selection_end, es->flags & EF_AFTER_WRAP)), NULL);
+ else
+ e = 0;
+ EDIT_EM_SetSel(wnd, es, e, extend ? es->selection_start : e, FALSE);
+ EDIT_EM_ScrollCaret(wnd, es);
+}
+
+
+/*********************************************************************
+ *
+ * EDIT_MovePageDown_ML
+ *
+ * Only for multi line controls
+ * Move the caret one page down, on a column with the nearest
+ * x coordinate on the screen (might be a different column).
+ *
+ */
+static void EDIT_MovePageDown_ML(WND *wnd, EDITSTATE *es, BOOL extend)
+{
+ INT s = es->selection_start;
+ INT e = es->selection_end;
+ BOOL after_wrap = (es->flags & EF_AFTER_WRAP);
+ LRESULT pos = EDIT_EM_PosFromChar(wnd, es, e, after_wrap);
+ INT x = SLOWORD(pos);
+ INT y = SHIWORD(pos);
+
+ e = EDIT_CharFromPos(wnd, es, x,
+ y + (es->format_rect.bottom - es->format_rect.top),
+ &after_wrap);
+ if (!extend)
+ s = e;
+ EDIT_EM_SetSel(wnd, es, s, e, after_wrap);
+ EDIT_EM_ScrollCaret(wnd, es);
+}
+
+
+/*********************************************************************
+ *
+ * EDIT_MovePageUp_ML
+ *
+ * Only for multi line controls
+ * Move the caret one page up, on a column with the nearest
+ * x coordinate on the screen (might be a different column).
+ *
+ */
+static void EDIT_MovePageUp_ML(WND *wnd, EDITSTATE *es, BOOL extend)
+{
+ INT s = es->selection_start;
+ INT e = es->selection_end;
+ BOOL after_wrap = (es->flags & EF_AFTER_WRAP);
+ LRESULT pos = EDIT_EM_PosFromChar(wnd, es, e, after_wrap);
+ INT x = SLOWORD(pos);
+ INT y = SHIWORD(pos);
+
+ e = EDIT_CharFromPos(wnd, es, x,
+ y - (es->format_rect.bottom - es->format_rect.top),
+ &after_wrap);
+ if (!extend)
+ s = e;
+ EDIT_EM_SetSel(wnd, es, s, e, after_wrap);
+ EDIT_EM_ScrollCaret(wnd, es);
+}
+
+
+/*********************************************************************
+ *
+ * EDIT_MoveUp_ML
+ *
+ * Only for multi line controls
+ * Move the caret one line up, on a column with the nearest
+ * x coordinate on the screen (might be a different column).
+ *
+ */
+static void EDIT_MoveUp_ML(WND *wnd, EDITSTATE *es, BOOL extend)
+{
+ INT s = es->selection_start;
+ INT e = es->selection_end;
+ BOOL after_wrap = (es->flags & EF_AFTER_WRAP);
+ LRESULT pos = EDIT_EM_PosFromChar(wnd, es, e, after_wrap);
+ INT x = SLOWORD(pos);
+ INT y = SHIWORD(pos);
+
+ e = EDIT_CharFromPos(wnd, es, x, y - es->line_height, &after_wrap);
+ if (!extend)
+ s = e;
+ EDIT_EM_SetSel(wnd, es, s, e, after_wrap);
+ EDIT_EM_ScrollCaret(wnd, es);
+}
+
+
+/*********************************************************************
+ *
+ * EDIT_MoveWordBackward
+ *
+ */
+static void EDIT_MoveWordBackward(WND *wnd, EDITSTATE *es, BOOL extend)
+{
+ INT s = es->selection_start;
+ INT e = es->selection_end;
+ INT l;
+ INT ll;
+ INT li;
+
+ l = EDIT_EM_LineFromChar(wnd, es, e);
+ ll = EDIT_EM_LineLength(wnd, es, e);
+ li = EDIT_EM_LineIndex(wnd, es, l);
+ if (e - li == 0) {
+ if (l) {
+ li = EDIT_EM_LineIndex(wnd, es, l - 1);
+ e = li + EDIT_EM_LineLength(wnd, es, li);
+ }
+ } else {
+ e = li + (INT)EDIT_CallWordBreakProc(wnd, es,
+ li, e - li, ll, WB_LEFT);
+ }
+ if (!extend)
+ s = e;
+ EDIT_EM_SetSel(wnd, es, s, e, FALSE);
+ EDIT_EM_ScrollCaret(wnd, es);
+}
+
+
+/*********************************************************************
+ *
+ * EDIT_MoveWordForward
+ *
+ */
+static void EDIT_MoveWordForward(WND *wnd, EDITSTATE *es, BOOL extend)
+{
+ INT s = es->selection_start;
+ INT e = es->selection_end;
+ INT l;
+ INT ll;
+ INT li;
+
+ l = EDIT_EM_LineFromChar(wnd, es, e);
+ ll = EDIT_EM_LineLength(wnd, es, e);
+ li = EDIT_EM_LineIndex(wnd, es, l);
+ if (e - li == ll) {
+ if ((es->style & ES_MULTILINE) && (l != es->line_count - 1))
+ e = EDIT_EM_LineIndex(wnd, es, l + 1);
+ } else {
+ e = li + EDIT_CallWordBreakProc(wnd, es,
+ li, e - li + 1, ll, WB_RIGHT);
+ }
+ if (!extend)
+ s = e;
+ EDIT_EM_SetSel(wnd, es, s, e, FALSE);
+ EDIT_EM_ScrollCaret(wnd, es);
+}
+
+
+/*********************************************************************
+ *
+ * EDIT_PaintLine
+ *
+ */
+static void EDIT_PaintLine(WND *wnd, EDITSTATE *es, HDC dc, INT line, BOOL rev)
+{
+ INT s = es->selection_start;
+ INT e = es->selection_end;
+ INT li;
+ INT ll;
+ INT x;
+ INT y;
+ LRESULT pos;
+
+ if (es->style & ES_MULTILINE) {
+ INT vlc = (es->format_rect.bottom - es->format_rect.top) / es->line_height;
+ if ((line < es->y_offset) || (line > es->y_offset + vlc) || (line >= es->line_count))
+ return;
+ } else if (line)
+ return;
+
+ DPRINT( "line=%d\n", line);
+
+ pos = EDIT_EM_PosFromChar(wnd, es, EDIT_EM_LineIndex(wnd, es, line), FALSE);
+ x = SLOWORD(pos);
+ y = SHIWORD(pos);
+ li = EDIT_EM_LineIndex(wnd, es, line);
+ ll = EDIT_EM_LineLength(wnd, es, li);
+ s = es->selection_start;
+ e = es->selection_end;
+ ORDER_INT(s, e);
+ s = MIN(li + ll, MAX(li, s));
+ e = MIN(li + ll, MAX(li, e));
+ if (rev && (s != e) &&
+ ((es->flags & EF_FOCUSED) || (es->style & ES_NOHIDESEL))) {
+ x += EDIT_PaintText(wnd, es, dc, x, y, line, 0, s - li, FALSE);
+ x += EDIT_PaintText(wnd, es, dc, x, y, line, s - li, e - s, TRUE);
+ x += EDIT_PaintText(wnd, es, dc, x, y, line, e - li, li + ll - e, FALSE);
+ } else
+ x += EDIT_PaintText(wnd, es, dc, x, y, line, 0, ll, FALSE);
+}
+
+
+/*********************************************************************
+ *
+ * EDIT_PaintText
+ *
+ */
+static INT EDIT_PaintText(WND *wnd, EDITSTATE *es, HDC dc, INT x, INT y, INT line, INT col, INT count, BOOL rev)
+{
+ COLORREF BkColor;
+ COLORREF TextColor;
+ INT ret;
+ INT li;
+ SIZE size;
+
+ if (!count)
+ return 0;
+ BkColor = GetBkColor(dc);
+ TextColor = GetTextColor(dc);
+ if (rev) {
+ SetBkColor(dc, GetSysColor(COLOR_HIGHLIGHT));
+ SetTextColor(dc, GetSysColor(COLOR_HIGHLIGHTTEXT));
+ }
+ li = EDIT_EM_LineIndex(wnd, es, line);
+ if (es->style & ES_MULTILINE) {
+ ret = (INT)LOWORD(TabbedTextOutA(dc, x, y, es->text + li + col, count,
+ es->tabs_count, es->tabs, es->format_rect.left - es->x_offset));
+ } else {
+ LPSTR text = EDIT_GetPasswordPointer_SL(wnd, es);
+ TextOutA(dc, x, y, text + li + col, count);
+ GetTextExtentPointA(dc, text + li + col, count, &size);
+ ret = size.cx;
+ if (es->style & ES_PASSWORD)
+ HeapFree(es->heap, 0, text);
+ }
+ if (rev) {
+ SetBkColor(dc, BkColor);
+ SetTextColor(dc, TextColor);
+ }
+ return ret;
+}
+
+
+/*********************************************************************
+ *
+ * EDIT_SetCaretPos
+ *
+ */
+static void EDIT_SetCaretPos(WND *wnd, EDITSTATE *es, INT pos,
+ BOOL after_wrap)
+{
+ LRESULT res = EDIT_EM_PosFromChar(wnd, es, pos, after_wrap);
+ INT x = SLOWORD(res);
+ INT y = SHIWORD(res);
+
+ if(x < es->format_rect.left)
+ x = es->format_rect.left;
+ if(x > es->format_rect.right - 2)
+ x = es->format_rect.right - 2;
+ if(y > es->format_rect.bottom)
+ y = es->format_rect.bottom;
+ if(y < es->format_rect.top)
+ y = es->format_rect.top;
+ SetCaretPos(x, y);
+ return;
+}
+
+
+/*********************************************************************
+ *
+ * EDIT_SetRectNP
+ *
+ * note: this is not (exactly) the handler called on EM_SETRECTNP
+ * it is also used to set the rect of a single line control
+ *
+ */
+static void EDIT_SetRectNP(WND *wnd, EDITSTATE *es, LPRECT rc)
+{
+ CopyRect(&es->format_rect, rc);
+ if (es->style & WS_BORDER) {
+ INT bw = GetSystemMetrics(SM_CXBORDER) + 1;
+ if(TWEAK_WineLook == WIN31_LOOK)
+ bw += 2;
+ es->format_rect.left += bw;
+ es->format_rect.top += bw;
+ es->format_rect.right -= bw;
+ es->format_rect.bottom -= bw;
+ }
+ es->format_rect.left += es->left_margin;
+ es->format_rect.right -= es->right_margin;
+ es->format_rect.right = MAX(es->format_rect.right, es->format_rect.left + es->char_width);
+ if (es->style & ES_MULTILINE)
+ es->format_rect.bottom = es->format_rect.top +
+ MAX(1, (es->format_rect.bottom - es->format_rect.top) / es->line_height) * es->line_height;
+ else
+ es->format_rect.bottom = es->format_rect.top + es->line_height;
+ if ((es->style & ES_MULTILINE) && !(es->style & ES_AUTOHSCROLL))
+ EDIT_BuildLineDefs_ML(wnd, es);
+}
+
+
+/*********************************************************************
+ *
+ * EDIT_UnlockBuffer
+ *
+ */
+static void EDIT_UnlockBuffer(WND *wnd, EDITSTATE *es, BOOL force)
+{
+ if (!es) {
+ DPRINT( "no EDITSTATE ... please report\n");
+ return;
+ }
+ if (!(es->style & ES_MULTILINE))
+ return;
+ if (!es->lock_count) {
+ DPRINT( "lock_count == 0 ... please report\n");
+ return;
+ }
+ if (!es->text) {
+ DPRINT( "es->text == 0 ... please report\n");
+ return;
+ }
+ if (force || (es->lock_count == 1)) {
+ if (es->hloc) {
+ LocalUnlock(es->hloc);
+ es->text = NULL;
+ }
+ }
+ es->lock_count--;
+}
+
+
+/*********************************************************************
+ *
+ * EDIT_WordBreakProc
+ *
+ * Find the beginning of words.
+ * Note: unlike the specs for a WordBreakProc, this function only
+ * allows to be called without linebreaks between s[0] upto
+ * s[count - 1]. Remember it is only called
+ * internally, so we can decide this for ourselves.
+ *
+ */
+static INT EDIT_WordBreakProc(LPSTR s, INT index, INT count, INT action)
+{
+ INT ret = 0;
+
+ DPRINT( "s=%p, index=%u, count=%u, action=%d\n",
+ s, index, count, action);
+
+ switch (action) {
+ case WB_LEFT:
+ if (!count)
+ break;
+ if (index)
+ index--;
+ if (s[index] == ' ') {
+ while (index && (s[index] == ' '))
+ index--;
+ if (index) {
+ while (index && (s[index] != ' '))
+ index--;
+ if (s[index] == ' ')
+ index++;
+ }
+ } else {
+ while (index && (s[index] != ' '))
+ index--;
+ if (s[index] == ' ')
+ index++;
+ }
+ ret = index;
+ break;
+ case WB_RIGHT:
+ if (!count)
+ break;
+ if (index)
+ index--;
+ if (s[index] == ' ')
+ while ((index < count) && (s[index] == ' ')) index++;
+ else {
+ while (s[index] && (s[index] != ' ') && (index < count))
+ index++;
+ while ((s[index] == ' ') && (index < count)) index++;
+ }
+ ret = index;
+ break;
+ case WB_ISDELIMITER:
+ ret = (s[index] == ' ');
+ break;
+ default:
+ DPRINT( "unknown action code, please report !\n");
+ break;
+ }
+ return ret;
+}
+
+
+/*********************************************************************
+ *
+ * EM_CHARFROMPOS
+ *
+ * FIXME: do the specs mean to return LineIndex or LineNumber ???
+ * Let's assume LineIndex is meant
+ * FIXME: do the specs mean to return -1 if outside client area or
+ * if outside formatting rectangle ???
+ *
+ */
+static LRESULT EDIT_EM_CharFromPos(WND *wnd, EDITSTATE *es, INT x, INT y)
+{
+ POINT pt;
+ RECT rc;
+ INT index;
+
+ pt.x = x;
+ pt.y = y;
+ GetClientRect(wnd->hwndSelf, &rc);
+ if (!PtInRect(&rc, pt))
+ return -1;
+
+ index = EDIT_CharFromPos(wnd, es, x, y, NULL);
+ return MAKELONG(index, EDIT_EM_LineIndex(wnd, es,
+ EDIT_EM_LineFromChar(wnd, es, index)));
+}
+
+
+/*********************************************************************
+ *
+ * EM_FMTLINES
+ *
+ * Enable or disable soft breaks.
+ */
+static BOOL EDIT_EM_FmtLines(WND *wnd, EDITSTATE *es, BOOL add_eol)
+{
+ es->flags &= ~EF_USE_SOFTBRK;
+ if (add_eol) {
+ es->flags |= EF_USE_SOFTBRK;
+ DPRINT( "soft break enabled, not implemented\n");
+ }
+ return add_eol;
+}
+
+
+/*********************************************************************
+ *
+ * EM_GETHANDLE
+ *
+ * Hopefully this won't fire back at us.
+ * We always start with a fixed buffer in our own heap.
+ * However, with this message a bit application requests
+ * a handle to bit moveable local heap memory, where it expects
+ * to find the text.
+ * It's a pity that from this moment on we have to use this
+ * local heap, because applications may rely on the handle
+ * in the future.
+ *
+ * In this function we'll try to switch to local heap.
+ *
+ */
+static HLOCAL EDIT_EM_GetHandle(WND *wnd, EDITSTATE *es)
+{
+ HLOCAL newBuf;
+ LPSTR newText;
+ INT newSize;
+
+ if (!(es->style & ES_MULTILINE))
+ return 0;
+
+ if (es->hloc)
+ return es->hloc;
+
+
+ if (!(newBuf = LocalAlloc(LMEM_MOVEABLE, lstrlenA(es->text) + 1))) {
+ DPRINT( "could not allocate new bit buffer\n");
+ return 0;
+ }
+ newSize = MIN(LocalSize(newBuf) - 1, es->buffer_limit);
+ if (!(newText = LocalLock(newBuf))) {
+ DPRINT( "could not lock new bit buffer\n");
+ LocalFree(newBuf);
+ return 0;
+ }
+ lstrcpyA(newText, es->text);
+ EDIT_UnlockBuffer(wnd, es, TRUE);
+ if (es->text)
+ HeapFree(es->heap, 0, es->text);
+ es->hloc = newBuf;
+ es->buffer_size = newSize;
+ es->text = newText;
+ EDIT_LockBuffer(wnd, es);
+ DPRINT( "switched to bit local heap\n");
+
+ return es->hloc;
+}
+
+
+
+
+/*********************************************************************
+ *
+ * EM_GETLINE
+ *
+ */
+static INT EDIT_EM_GetLine(WND *wnd, EDITSTATE *es, INT line, LPSTR lpch)
+{
+ LPSTR src;
+ INT len;
+ INT i;
+
+ if (es->style & ES_MULTILINE) {
+ if (line >= es->line_count)
+ return 0;
+ } else
+ line = 0;
+ i = EDIT_EM_LineIndex(wnd, es, line);
+ src = es->text + i;
+ len = MIN(*(WORD *)lpch, EDIT_EM_LineLength(wnd, es, i));
+ for (i = 0 ; i < len ; i++) {
+ *lpch = *src;
+ src++;
+ lpch++;
+ }
+ return (LRESULT)len;
+}
+
+
+/*********************************************************************
+ *
+ * EM_GETSEL
+ *
+ */
+static LRESULT EDIT_EM_GetSel(WND *wnd, EDITSTATE *es, UINT * start, UINT * end)
+{
+ UINT s = es->selection_start;
+ UINT e = es->selection_end;
+
+ ORDER_UINT(s, e);
+ if (start)
+ *start = s;
+ if (end)
+ *end = e;
+ return MAKELONG(s, e);
+}
+
+
+/*********************************************************************
+ *
+ * EM_GETTHUMB
+ *
+ * FIXME: is this right ? (or should it be only VSCROLL)
+ * (and maybe only for edit controls that really have their
+ * own scrollbars) (and maybe only for multiline controls ?)
+ * All in all: very poorly documented
+ *
+ * FIXME: now it's also broken, because of the new WM_HSCROLL /
+ * WM_VSCROLL handlers
+ *
+ */
+static LRESULT EDIT_EM_GetThumb(WND *wnd, EDITSTATE *es)
+{
+ return MAKELONG(EDIT_WM_VScroll(wnd, es, EM_GETTHUMB, 0, 0),
+ EDIT_WM_HScroll(wnd, es, EM_GETTHUMB, 0, 0));
+}
+
+
+/*********************************************************************
+ *
+ * EM_LINEFROMCHAR
+ *
+ */
+static INT EDIT_EM_LineFromChar(WND *wnd, EDITSTATE *es, INT index)
+{
+ INT line;
+ LINEDEF *line_def;
+
+ if (!(es->style & ES_MULTILINE))
+ return 0;
+ if (index > lstrlenA(es->text))
+ return es->line_count - 1;
+ if (index == -1)
+ index = MIN(es->selection_start, es->selection_end);
+
+ line = 0;
+ line_def = es->first_line_def;
+ index -= line_def->length;
+ while ((index >= 0) && line_def->next) {
+ line++;
+ line_def = line_def->next;
+ index -= line_def->length;
+ }
+ return line;
+}
+
+
+/*********************************************************************
+ *
+ * EM_LINEINDEX
+ *
+ */
+static INT EDIT_EM_LineIndex(WND *wnd, EDITSTATE *es, INT line)
+{
+ INT line_index;
+ LINEDEF *line_def;
+
+ if (!(es->style & ES_MULTILINE))
+ return 0;
+ if (line >= es->line_count)
+ return -1;
+
+ line_index = 0;
+ line_def = es->first_line_def;
+ if (line == -1) {
+ INT index = es->selection_end - line_def->length;
+ while ((index >= 0) && line_def->next) {
+ line_index += line_def->length;
+ line_def = line_def->next;
+ index -= line_def->length;
+ }
+ } else {
+ while (line > 0) {
+ line_index += line_def->length;
+ line_def = line_def->next;
+ line--;
+ }
+ }
+ return line_index;
+}
+
+
+/*********************************************************************
+ *
+ * EM_LINELENGTH
+ *
+ */
+static INT EDIT_EM_LineLength(WND *wnd, EDITSTATE *es, INT index)
+{
+ LINEDEF *line_def;
+
+ if (!(es->style & ES_MULTILINE))
+ return lstrlenA(es->text);
+
+ if (index == -1) {
+ /* FIXME: broken
+ INT sl = EDIT_EM_LineFromChar(wnd, es, es->selection_start);
+ INT el = EDIT_EM_LineFromChar(wnd, es, es->selection_end);
+ return es->selection_start - es->line_defs[sl].offset +
+ es->line_defs[el].offset +
+ es->line_defs[el].length - es->selection_end;
+ */
+ return 0;
+ }
+ line_def = es->first_line_def;
+ index -= line_def->length;
+ while ((index >= 0) && line_def->next) {
+ line_def = line_def->next;
+ index -= line_def->length;
+ }
+ return line_def->net_length;
+}
+
+
+/*********************************************************************
+ *
+ * EM_LINESCROLL
+ *
+ * FIXME: dx is in average character widths
+ * However, we assume it is in pixels when we use this
+ * function internally
+ *
+ */
+static BOOL EDIT_EM_LineScroll(WND *wnd, EDITSTATE *es, INT dx, INT dy)
+{
+ INT nyoff;
+
+ if (!(es->style & ES_MULTILINE))
+ return FALSE;
+
+ if (-dx > es->x_offset)
+ dx = -es->x_offset;
+ if (dx > es->text_width - es->x_offset)
+ dx = es->text_width - es->x_offset;
+ nyoff = MAX(0, es->y_offset + dy);
+ if (nyoff >= es->line_count)
+ nyoff = es->line_count - 1;
+ dy = (es->y_offset - nyoff) * es->line_height;
+ if (dx || dy) {
+ RECT rc1;
+ RECT rc;
+ GetClientRect(wnd->hwndSelf, &rc1);
+ IntersectRect(&rc, &rc1, &es->format_rect);
+ ScrollWindowEx(wnd->hwndSelf, -dx, dy,
+ NULL, &rc, (HRGN)NULL, NULL, SW_INVALIDATE);
+ es->y_offset = nyoff;
+ es->x_offset += dx;
+ }
+ if (dx && !(es->flags & EF_HSCROLL_TRACK))
+ EDIT_NOTIFY_PARENT(wnd, EN_HSCROLL, "EN_HSCROLL");
+ if (dy && !(es->flags & EF_VSCROLL_TRACK))
+ EDIT_NOTIFY_PARENT(wnd, EN_VSCROLL, "EN_VSCROLL");
+ return TRUE;
+}
+
+
+/*********************************************************************
+ *
+ * EM_POSFROMCHAR
+ *
+ */
+static LRESULT EDIT_EM_PosFromChar(WND *wnd, EDITSTATE *es, INT index, BOOL after_wrap)
+{
+ INT len = lstrlenA(es->text);
+ INT l;
+ INT li;
+ INT x;
+ INT y = 0;
+ HDC dc;
+ HFONT old_font = 0;
+ SIZE size;
+
+ index = MIN(index, len);
+ dc = GetDC(wnd->hwndSelf);
+ if (es->font)
+ old_font = SelectObject(dc, es->font);
+ if (es->style & ES_MULTILINE) {
+ l = EDIT_EM_LineFromChar(wnd, es, index);
+ y = (l - es->y_offset) * es->line_height;
+ li = EDIT_EM_LineIndex(wnd, es, l);
+ if (after_wrap && (li == index) && l) {
+ INT l2 = l - 1;
+ LINEDEF *line_def = es->first_line_def;
+ while (l2) {
+ line_def = line_def->next;
+ l2--;
+ }
+ if (line_def->ending == END_WRAP) {
+ l--;
+ y -= es->line_height;
+ li = EDIT_EM_LineIndex(wnd, es, l);
+ }
+ }
+ x = LOWORD(GetTabbedTextExtentA(dc, es->text + li, index - li,
+ es->tabs_count, es->tabs)) - es->x_offset;
+ } else {
+ LPSTR text = EDIT_GetPasswordPointer_SL(wnd, es);
+ if (index < es->x_offset) {
+ GetTextExtentPointA(dc, text + index,
+ es->x_offset - index, &size);
+ x = -size.cx;
+ } else {
+ GetTextExtentPointA(dc, text + es->x_offset,
+ index - es->x_offset, &size);
+ x = size.cx;
+ }
+ y = 0;
+ if (es->style & ES_PASSWORD)
+ HeapFree(es->heap, 0 ,text);
+ }
+ x += es->format_rect.left;
+ y += es->format_rect.top;
+ if (es->font)
+ SelectObject(dc, old_font);
+ ReleaseDC(wnd->hwndSelf, dc);
+ return MAKELONG((INT)x, (INT)y);
+}
+
+
+/*********************************************************************
+ *
+ * EM_REPLACESEL
+ *
+ * FIXME: handle ES_NUMBER and ES_OEMCONVERT here
+ *
+ */
+static void EDIT_EM_ReplaceSel(WND *wnd, EDITSTATE *es, BOOL can_undo, LPCSTR lpsz_replace)
+{
+ INT strl = lstrlenA(lpsz_replace);
+ INT tl = lstrlenA(es->text);
+ INT utl;
+ UINT s;
+ UINT e;
+ INT i;
+ LPSTR p;
+
+ s = es->selection_start;
+ e = es->selection_end;
+
+ if ((s == e) && !strl)
+ return;
+
+ ORDER_UINT(s, e);
+
+ if (!EDIT_MakeFit(wnd, es, tl - (e - s) + strl))
+ return;
+
+ if (e != s) {
+ /* there is something to be deleted */
+ if (can_undo) {
+ utl = lstrlenA(es->undo_text);
+ if (!es->undo_insert_count && (*es->undo_text && (s == es->undo_position))) {
+ /* undo-buffer is extended to the right */
+ EDIT_MakeUndoFit(wnd, es, utl + e - s);
+ lstrcpynA(es->undo_text + utl, es->text + s, e - s + 1);
+ } else if (!es->undo_insert_count && (*es->undo_text && (e == es->undo_position))) {
+ /* undo-buffer is extended to the left */
+ EDIT_MakeUndoFit(wnd, es, utl + e - s);
+ for (p = es->undo_text + utl ; p >= es->undo_text ; p--)
+ p[e - s] = p[0];
+ for (i = 0 , p = es->undo_text ; i < e - s ; i++)
+ p[i] = (es->text + s)[i];
+ es->undo_position = s;
+ } else {
+ /* new undo-buffer */
+ EDIT_MakeUndoFit(wnd, es, e - s);
+ lstrcpynA(es->undo_text, es->text + s, e - s + 1);
+ es->undo_position = s;
+ }
+ /* any deletion makes the old insertion-undo invalid */
+ es->undo_insert_count = 0;
+ } else
+ EDIT_EM_EmptyUndoBuffer(wnd, es);
+
+ /* now delete */
+ lstrcpyA(es->text + s, es->text + e);
+ }
+ if (strl) {
+ /* there is an insertion */
+ if (can_undo) {
+ if ((s == es->undo_position) ||
+ ((es->undo_insert_count) &&
+ (s == es->undo_position + es->undo_insert_count)))
+ /*
+ * insertion is new and at delete position or
+ * an extension to either left or right
+ */
+ es->undo_insert_count += strl;
+ else {
+ /* new insertion undo */
+ es->undo_position = s;
+ es->undo_insert_count = strl;
+ /* new insertion makes old delete-buffer invalid */
+ *es->undo_text = '\0';
+ }
+ } else
+ EDIT_EM_EmptyUndoBuffer(wnd, es);
+
+ /* now insert */
+ tl = lstrlenA(es->text);
+ for (p = es->text + tl ; p >= es->text + s ; p--)
+ p[strl] = p[0];
+ for (i = 0 , p = es->text + s ; i < strl ; i++)
+ p[i] = lpsz_replace[i];
+ if(es->style & ES_UPPERCASE)
+ CharUpperBuffA(p, strl);
+ else if(es->style & ES_LOWERCASE)
+ CharLowerBuffA(p, strl);
+ s += strl;
+ }
+ /* FIXME: really inefficient */
+ if (es->style & ES_MULTILINE)
+ EDIT_BuildLineDefs_ML(wnd, es);
+
+ EDIT_EM_SetSel(wnd, es, s, s, FALSE);
+ es->flags |= EF_MODIFIED;
+ es->flags |= EF_UPDATE;
+ EDIT_EM_ScrollCaret(wnd, es);
+
+ /* FIXME: really inefficient */
+ InvalidateRect(wnd->hwndSelf, NULL, TRUE);
+}
+
+
+/*********************************************************************
+ *
+ * EM_SCROLL
+ *
+ */
+static LRESULT EDIT_EM_Scroll(WND *wnd, EDITSTATE *es, INT action)
+{
+ INT dy;
+
+ if (!(es->style & ES_MULTILINE))
+ return (LRESULT)FALSE;
+
+ dy = 0;
+
+ switch (action) {
+ case SB_LINEUP:
+ if (es->y_offset)
+ dy = -1;
+ break;
+ case SB_LINEDOWN:
+ if (es->y_offset < es->line_count - 1)
+ dy = 1;
+ break;
+ case SB_PAGEUP:
+ if (es->y_offset)
+ dy = -(es->format_rect.bottom - es->format_rect.top) / es->line_height;
+ break;
+ case SB_PAGEDOWN:
+ if (es->y_offset < es->line_count - 1)
+ dy = (es->format_rect.bottom - es->format_rect.top) / es->line_height;
+ break;
+ default:
+ return (LRESULT)FALSE;
+ }
+ if (dy) {
+ EDIT_EM_LineScroll(wnd, es, 0, dy);
+ EDIT_NOTIFY_PARENT(wnd, EN_VSCROLL, "EN_VSCROLL");
+ }
+ return MAKELONG((INT)dy, (BOOL)TRUE);
+}
+
+
+/*********************************************************************
+ *
+ * EM_SCROLLCARET
+ *
+ */
+static void EDIT_EM_ScrollCaret(WND *wnd, EDITSTATE *es)
+{
+ if (es->style & ES_MULTILINE) {
+ INT l;
+ INT li;
+ INT vlc;
+ INT ww;
+ INT cw = es->char_width;
+ INT x;
+ INT dy = 0;
+ INT dx = 0;
+
+ l = EDIT_EM_LineFromChar(wnd, es, es->selection_end);
+ li = EDIT_EM_LineIndex(wnd, es, l);
+ x = SLOWORD(EDIT_EM_PosFromChar(wnd, es, es->selection_end, es->flags & EF_AFTER_WRAP));
+ vlc = (es->format_rect.bottom - es->format_rect.top) / es->line_height;
+ if (l >= es->y_offset + vlc)
+ dy = l - vlc + 1 - es->y_offset;
+ if (l < es->y_offset)
+ dy = l - es->y_offset;
+ ww = es->format_rect.right - es->format_rect.left;
+ if (x < es->format_rect.left)
+ dx = x - es->format_rect.left - ww / HSCROLL_FRACTION / cw * cw;
+ if (x > es->format_rect.right)
+ dx = x - es->format_rect.left - (HSCROLL_FRACTION - 1) * ww / HSCROLL_FRACTION / cw * cw;
+ if (dy || dx)
+ EDIT_EM_LineScroll(wnd, es, dx, dy);
+ } else {
+ INT x;
+ INT goal;
+ INT format_width;
+
+ if (!(es->style & ES_AUTOHSCROLL))
+ return;
+
+ x = SLOWORD(EDIT_EM_PosFromChar(wnd, es, es->selection_end, FALSE));
+ format_width = es->format_rect.right - es->format_rect.left;
+ if (x < es->format_rect.left) {
+ goal = es->format_rect.left + format_width / HSCROLL_FRACTION;
+ do {
+ es->x_offset--;
+ x = SLOWORD(EDIT_EM_PosFromChar(wnd, es, es->selection_end, FALSE));
+ } while ((x < goal) && es->x_offset);
+ /* FIXME: use ScrollWindow() somehow to improve performance */
+ InvalidateRect(wnd->hwndSelf, NULL, TRUE);
+ } else if (x > es->format_rect.right) {
+ INT x_last;
+ INT len = lstrlenA(es->text);
+ goal = es->format_rect.right - format_width / HSCROLL_FRACTION;
+ do {
+ es->x_offset++;
+ x = SLOWORD(EDIT_EM_PosFromChar(wnd, es, es->selection_end, FALSE));
+ x_last = SLOWORD(EDIT_EM_PosFromChar(wnd, es, len, FALSE));
+ } while ((x > goal) && (x_last > es->format_rect.right));
+ /* FIXME: use ScrollWindow() somehow to improve performance */
+ InvalidateRect(wnd->hwndSelf, NULL, TRUE);
+ }
+ }
+}
+
+
+/*********************************************************************
+ *
+ * EM_SETHANDLE
+ *
+ * FIXME: ES_LOWERCASE, ES_UPPERCASE, ES_OEMCONVERT, ES_NUMBER ???
+ *
+ */
+static void EDIT_EM_SetHandle(WND *wnd, EDITSTATE *es, HLOCAL hloc)
+{
+ if (!(es->style & ES_MULTILINE))
+ return;
+
+ if (!hloc) {
+ DPRINT( "called with NULL handle\n");
+ return;
+ }
+
+ EDIT_UnlockBuffer(wnd, es, TRUE);
+ /*
+ * old buffer is freed by caller, unless
+ * it is still in our own heap. (in that case
+ * we free it, correcting the buggy caller.)
+ */
+ if (es->text)
+ HeapFree(es->heap, 0, es->text);
+
+ es->hloc = hloc;
+ es->text = NULL;
+ es->buffer_size = LocalSize(es->hloc) - 1;
+ EDIT_LockBuffer(wnd, es);
+
+ es->x_offset = es->y_offset = 0;
+ es->selection_start = es->selection_end = 0;
+ EDIT_EM_EmptyUndoBuffer(wnd, es);
+ es->flags &= ~EF_MODIFIED;
+ es->flags &= ~EF_UPDATE;
+ EDIT_BuildLineDefs_ML(wnd, es);
+ InvalidateRect(wnd->hwndSelf, NULL, TRUE);
+ EDIT_EM_ScrollCaret(wnd, es);
+}
+
+
+
+
+
+/*********************************************************************
+ *
+ * EM_SETLIMITTEXT
+ *
+ * FIXME: in WinNT maxsize is 0x7FFFFFFF / 0xFFFFFFFF
+ * However, the windows version is not complied to yet in all of edit.c
+ *
+ */
+static void EDIT_EM_SetLimitText(WND *wnd, EDITSTATE *es, INT limit)
+{
+ if (es->style & ES_MULTILINE) {
+ if (limit)
+ es->buffer_limit = MIN(limit, BUFLIMIT_MULTI);
+ else
+ es->buffer_limit = BUFLIMIT_MULTI;
+ } else {
+ if (limit)
+ es->buffer_limit = MIN(limit, BUFLIMIT_SINGLE);
+ else
+ es->buffer_limit = BUFLIMIT_SINGLE;
+ }
+}
+
+
+/*********************************************************************
+ *
+ * EM_SETMARGINS
+ *
+ * EC_USEFONTINFO is used as a left or right value i.e. lParam and not as an
+ * action wParam despite what the docs say. It also appears not to affect
+ * multiline controls??
+ *
+ */
+static void EDIT_EM_SetMargins(WND *wnd, EDITSTATE *es, INT action,
+ INT left, INT right)
+{
+ if (action & EC_LEFTMARGIN) {
+ if (left != EC_USEFONTINFO)
+ es->left_margin = left;
+ else
+ if (es->style & ES_MULTILINE)
+ es->left_margin = 0; /* ?? */
+ else
+ es->left_margin = es->char_width;
+ }
+
+ if (action & EC_RIGHTMARGIN) {
+ if (right != EC_USEFONTINFO)
+ es->right_margin = right;
+ else
+ if (es->style & ES_MULTILINE)
+ es->right_margin = 0; /* ?? */
+ else
+ es->right_margin = es->char_width;
+ }
+ DPRINT( "left=%d, right=%d\n", es->left_margin, es->right_margin);
+}
+
+
+/*********************************************************************
+ *
+ * EM_SETPASSWORDCHAR
+ *
+ */
+static void EDIT_EM_SetPasswordChar(WND *wnd, EDITSTATE *es, CHAR c)
+{
+ if (es->style & ES_MULTILINE)
+ return;
+
+ if (es->password_char == c)
+ return;
+
+ es->password_char = c;
+ if (c) {
+ wnd->dwStyle |= ES_PASSWORD;
+ es->style |= ES_PASSWORD;
+ } else {
+ wnd->dwStyle &= ~ES_PASSWORD;
+ es->style &= ~ES_PASSWORD;
+ }
+ InvalidateRect(wnd->hwndSelf, NULL, TRUE);
+}
+
+
+/*********************************************************************
+ *
+ * EDIT_EM_SetSel
+ *
+ * note: unlike the specs say: the order of start and end
+ * _is_ preserved in Windows. (i.e. start can be > end)
+ * In other words: this handler is OK
+ *
+ */
+static void EDIT_EM_SetSel(WND *wnd, EDITSTATE *es, UINT start, UINT end, BOOL after_wrap)
+{
+ UINT old_start = es->selection_start;
+ UINT old_end = es->selection_end;
+ UINT len = lstrlenA(es->text);
+
+ if (start == -1) {
+ start = es->selection_end;
+ end = es->selection_end;
+ } else {
+ start = MIN(start, len);
+ end = MIN(end, len);
+ }
+ es->selection_start = start;
+ es->selection_end = end;
+ if (after_wrap)
+ es->flags |= EF_AFTER_WRAP;
+ else
+ es->flags &= ~EF_AFTER_WRAP;
+ if (es->flags & EF_FOCUSED)
+ EDIT_SetCaretPos(wnd, es, end, after_wrap);
+/* This is little bit more efficient than before, not sure if it can be improved. FIXME? */
+ ORDER_UINT(start, end);
+ ORDER_UINT(end, old_end);
+ ORDER_UINT(start, old_start);
+ ORDER_UINT(old_start, old_end);
+ if (end != old_start)
+ {
+/*
+ * One can also do
+ * ORDER_UINT(end, old_start);
+ * EDIT_InvalidateText(wnd, es, start, end);
+ * EDIT_InvalidateText(wnd, es, old_start, old_end);
+ * in place of the following if statement.
+ */
+ if (old_start > end )
+ {
+ EDIT_InvalidateText(wnd, es, start, end);
+ EDIT_InvalidateText(wnd, es, old_start, old_end);
+ }
+ else
+ {
+ EDIT_InvalidateText(wnd, es, start, old_start);
+ EDIT_InvalidateText(wnd, es, end, old_end);
+ }
+ }
+ else EDIT_InvalidateText(wnd, es, start, old_end);
+}
+
+
+/*********************************************************************
+ *
+ * EM_SETTABSTOPS
+ *
+ */
+static BOOL EDIT_EM_SetTabStops(WND *wnd, EDITSTATE *es, INT count, LPINT tabs)
+{
+ if (!(es->style & ES_MULTILINE))
+ return FALSE;
+ if (es->tabs)
+ HeapFree(es->heap, 0, es->tabs);
+ es->tabs_count = count;
+ if (!count)
+ es->tabs = NULL;
+ else {
+ es->tabs = HeapAlloc(es->heap, 0, count * sizeof(INT));
+ memcpy(es->tabs, tabs, count * sizeof(INT));
+ }
+ return TRUE;
+}
+
+
+
+
+/*********************************************************************
+ *
+ * EM_SETWORDBREAKPROC
+ *
+ */
+static void EDIT_EM_SetWordBreakProc(WND *wnd, EDITSTATE *es, EDITWORDBREAKPROCA wbp)
+{
+ if (es->word_break_procA == wbp)
+ return;
+
+ es->word_break_procA = wbp;
+ if ((es->style & ES_MULTILINE) && !(es->style & ES_AUTOHSCROLL)) {
+ EDIT_BuildLineDefs_ML(wnd, es);
+ InvalidateRect(wnd->hwndSelf, NULL, TRUE);
+ }
+}
+
+
+
+
+
+/*********************************************************************
+ *
+ * EM_UNDO / WM_UNDO
+ *
+ */
+static BOOL EDIT_EM_Undo(WND *wnd, EDITSTATE *es)
+{
+ INT ulength = lstrlenA(es->undo_text);
+ LPSTR utext = HeapAlloc(es->heap, 0, ulength + 1);
+
+ lstrcpyA(utext, es->undo_text);
+
+ DPRINT( "before UNDO:insertion length = %d, deletion buffer = %s\n",
+ es->undo_insert_count, utext);
+
+ EDIT_EM_SetSel(wnd, es, es->undo_position, es->undo_position + es->undo_insert_count, FALSE);
+ EDIT_EM_EmptyUndoBuffer(wnd, es);
+ EDIT_EM_ReplaceSel(wnd, es, TRUE, utext);
+ EDIT_EM_SetSel(wnd, es, es->undo_position, es->undo_position + es->undo_insert_count, FALSE);
+ HeapFree(es->heap, 0, utext);
+
+ DPRINT( "after UNDO:insertion length = %d, deletion buffer = %s\n",
+ es->undo_insert_count, es->undo_text);
+
+ return TRUE;
+}
+
+
+/*********************************************************************
+ *
+ * WM_CHAR
+ *
+ */
+static void EDIT_WM_Char(WND *wnd, EDITSTATE *es, CHAR c, DWORD key_data)
+{
+ switch (c) {
+ case '\r':
+ case '\n':
+ if (es->style & ES_MULTILINE) {
+ if (es->style & ES_READONLY) {
+ EDIT_MoveHome(wnd, es, FALSE);
+ EDIT_MoveDown_ML(wnd, es, FALSE);
+ } else
+ EDIT_EM_ReplaceSel(wnd, es, TRUE, "\r\n");
+ }
+ break;
+ case '\t':
+ if ((es->style & ES_MULTILINE) && !(es->style & ES_READONLY))
+ EDIT_EM_ReplaceSel(wnd, es, TRUE, "\t");
+ break;
+ default:
+ if (!(es->style & ES_READONLY) && ((BYTE)c >= ' ') && (c != 127)) {
+ char str[2];
+ str[0] = c;
+ str[1] = '\0';
+ EDIT_EM_ReplaceSel(wnd, es, TRUE, str);
+ }
+ break;
+ }
+}
+
+
+/*********************************************************************
+ *
+ * WM_COMMAND
+ *
+ */
+static void EDIT_WM_Command(WND *wnd, EDITSTATE *es, INT code, INT id, HWND control)
+{
+ if (code || control)
+ return;
+
+ switch (id) {
+ case EM_UNDO:
+ EDIT_EM_Undo(wnd, es);
+ break;
+ case WM_CUT:
+ EDIT_WM_Cut(wnd, es);
+ break;
+ case WM_COPY:
+ EDIT_WM_Copy(wnd, es);
+ break;
+ case WM_PASTE:
+ EDIT_WM_Paste(wnd, es);
+ break;
+ case WM_CLEAR:
+ EDIT_WM_Clear(wnd, es);
+ break;
+ case EM_SETSEL:
+ EDIT_EM_SetSel(wnd, es, 0, -1, FALSE);
+ EDIT_EM_ScrollCaret(wnd, es);
+ break;
+ default:
+ DPRINT( "unknown menu item, please report\n");
+ break;
+ }
+}
+
+
+/*********************************************************************
+ *
+ * WM_CONTEXTMENU
+ *
+ * Note: the resource files resource/sysres_??.rc cannot define a
+ * single popup menu. Hence we use a (dummy) menubar
+ * containing the single popup menu as its first item.
+ *
+ * FIXME: the message identifiers have been chosen arbitrarily,
+ * hence we use MF_BYPOSITION.
+ * We might as well use the "real" values (anybody knows ?)
+ * The menu definition is in resources/sysres_??.rc.
+ * Once these are OK, we better use MF_BYCOMMAND here
+ * (as we do in EDIT_WM_Command()).
+ *
+ */
+static void EDIT_WM_ContextMenu(WND *wnd, EDITSTATE *es, HWND hwnd, INT x, INT y)
+{
+ HMENU menu = LoadMenuIndirectA(SYSRES_GetResPtr(SYSRES_MENU_EDITMENU));
+ HMENU popup = GetSubMenu(menu, 0);
+ UINT start = es->selection_start;
+ UINT end = es->selection_end;
+
+ ORDER_UINT(start, end);
+
+ /* undo */
+ EnableMenuItem(popup, 0, MF_BYPOSITION | (EDIT_EM_CanUndo(wnd, es) ? MF_ENABLED : MF_GRAYED));
+ /* cut */
+ EnableMenuItem(popup, 2, MF_BYPOSITION | ((end - start) && !(es->style & ES_PASSWORD) ? MF_ENABLED : MF_GRAYED));
+ /* copy */
+ EnableMenuItem(popup, 3, MF_BYPOSITION | ((end - start) && !(es->style & ES_PASSWORD) ? MF_ENABLED : MF_GRAYED));
+ /* paste */
+ EnableMenuItem(popup, 4, MF_BYPOSITION | (IsClipboardFormatAvailable(CF_TEXT) ? MF_ENABLED : MF_GRAYED));
+ /* delete */
+ EnableMenuItem(popup, 5, MF_BYPOSITION | ((end - start) ? MF_ENABLED : MF_GRAYED));
+ /* select all */
+ EnableMenuItem(popup, 7, MF_BYPOSITION | (start || (end != lstrlenA(es->text)) ? MF_ENABLED : MF_GRAYED));
+
+ TrackPopupMenu(popup, TPM_LEFTALIGN | TPM_RIGHTBUTTON, x, y, 0, wnd->hwndSelf, NULL);
+ DestroyMenu(menu);
+}
+
+
+/*********************************************************************
+ *
+ * WM_COPY
+ *
+ */
+static void EDIT_WM_Copy(WND *wnd, EDITSTATE *es)
+{
+ INT s = es->selection_start;
+ INT e = es->selection_end;
+ HGLOBAL hdst;
+ LPSTR dst;
+
+ if (e == s)
+ return;
+ ORDER_INT(s, e);
+ hdst = GlobalAlloc(GMEM_MOVEABLE, (DWORD)(e - s + 1));
+ dst = GlobalLock(hdst);
+ lstrcpynA(dst, es->text + s, e - s + 1);
+ GlobalUnlock(hdst);
+ OpenClipboard(wnd->hwndSelf);
+ EmptyClipboard();
+ SetClipboardData(CF_TEXT, hdst);
+ CloseClipboard();
+}
+
+
+/*********************************************************************
+ *
+ * WM_CREATE
+ *
+ */
+static LRESULT EDIT_WM_Create(WND *wnd, EDITSTATE *es, LPCREATESTRUCTA cs)
+{
+ /*
+ * To initialize some final structure members, we call some helper
+ * functions. However, since the EDITSTATE is not consistent (i.e.
+ * not fully initialized), we should be very careful which
+ * functions can be called, and in what order.
+ */
+ EDIT_WM_SetFont(wnd, es, 0, FALSE);
+ if (cs->lpszName && *(cs->lpszName) != '\0') {
+ EDIT_EM_ReplaceSel(wnd, es, FALSE, cs->lpszName);
+ /* if we insert text to the editline, the text scrolls out of the window, as the caret is placed after the insert pos normally; thus we reset es->selection... to 0 and update caret */
+ es->selection_start = es->selection_end = 0;
+ EDIT_EM_ScrollCaret(wnd, es);
+ }
+ return 0;
+}
+
+
+/*********************************************************************
+ *
+ * WM_DESTROY
+ *
+ */
+static void EDIT_WM_Destroy(WND *wnd, EDITSTATE *es)
+{
+ if (es->hloc) {
+ while (LocalUnlock(es->hloc)) ;
+ LocalFree(es->hloc);
+ }
+
+ HeapDestroy(es->heap);
+ HeapFree(GetProcessHeap(), 0, es);
+ *(EDITSTATE **)wnd->wExtra = NULL;
+}
+
+
+/*********************************************************************
+ *
+ * WM_ERASEBKGND
+ *
+ */
+static LRESULT EDIT_WM_EraseBkGnd(WND *wnd, EDITSTATE *es, HDC dc)
+{
+ HBRUSH brush;
+ RECT rc;
+
+ if (!(brush = (HBRUSH)EDIT_SEND_CTLCOLOR(wnd, dc)))
+ brush = (HBRUSH)GetStockObject(WHITE_BRUSH);
+
+ GetClientRect(wnd->hwndSelf, &rc);
+ IntersectClipRect(dc, rc.left, rc.top, rc.right, rc.bottom);
+ GetClipBox(dc, &rc);
+ /*
+ * FIXME: specs say that we should UnrealizeObject() the brush,
+ * but the specs of UnrealizeObject() say that we shouldn't
+ * unrealize a stock object. The default brush that
+ * DefWndProc() returns is ... a stock object.
+ */
+ FillRect(dc, &rc, brush);
+ return -1;
+}
+
+
+/*********************************************************************
+ *
+ * WM_GETTEXT
+ *
+ */
+static INT EDIT_WM_GetText(WND *wnd, EDITSTATE *es, INT count, LPSTR text)
+{
+ INT len = lstrlenA(es->text);
+
+ if (count > len) {
+ lstrcpyA(text, es->text);
+ return len;
+ } else
+ return -1;
+}
+
+
+/*********************************************************************
+ *
+ * EDIT_HScroll_Hack
+ *
+ * 16 bit notepad needs this. Actually it is not _our_ hack,
+ * it is notepad's. Notepad is sending us scrollbar messages with
+ * undocumented parameters without us even having a scrollbar ... !?!?
+ *
+ */
+static LRESULT EDIT_HScroll_Hack(WND *wnd, EDITSTATE *es, INT action, INT pos, HWND scroll_bar)
+{
+ INT dx = 0;
+ INT fw = es->format_rect.right - es->format_rect.left;
+ LRESULT ret = 0;
+
+ if (!(es->flags & EF_HSCROLL_HACK)) {
+ DPRINT( "hacked WM_HSCROLL handler invoked\n");
+ DPRINT( " if you are _not_ running 16 bit notepad, please report\n");
+ DPRINT( " (this message is only displayed once per edit control)\n");
+ es->flags |= EF_HSCROLL_HACK;
+ }
+
+ switch (action) {
+ case SB_LINELEFT:
+ if (es->x_offset)
+ dx = -es->char_width;
+ break;
+ case SB_LINERIGHT:
+ if (es->x_offset < es->text_width)
+ dx = es->char_width;
+ break;
+ case SB_PAGELEFT:
+ if (es->x_offset)
+ dx = -fw / HSCROLL_FRACTION / es->char_width * es->char_width;
+ break;
+ case SB_PAGERIGHT:
+ if (es->x_offset < es->text_width)
+ dx = fw / HSCROLL_FRACTION / es->char_width * es->char_width;
+ break;
+ case SB_LEFT:
+ if (es->x_offset)
+ dx = -es->x_offset;
+ break;
+ case SB_RIGHT:
+ if (es->x_offset < es->text_width)
+ dx = es->text_width - es->x_offset;
+ break;
+ case SB_THUMBTRACK:
+ es->flags |= EF_HSCROLL_TRACK;
+ dx = pos * es->text_width / 100 - es->x_offset;
+ break;
+ case SB_THUMBPOSITION:
+ es->flags &= ~EF_HSCROLL_TRACK;
+ if (!(dx = pos * es->text_width / 100 - es->x_offset))
+ EDIT_NOTIFY_PARENT(wnd, EN_HSCROLL, "EN_HSCROLL");
+ break;
+ case SB_ENDSCROLL:
+ break;
+
+ /*
+ * FIXME : the next two are undocumented !
+ * Are we doing the right thing ?
+ * At least Win 3.1 Notepad makes use of EM_GETTHUMB this way,
+ * although it's also a regular control message.
+ */
+ case EM_GETTHUMB:
+ ret = es->text_width ? es->x_offset * 100 / es->text_width : 0;
+ break;
+ case EM_LINESCROLL:
+ dx = pos;
+ break;
+
+ default:
+ DPRINT( "undocumented (hacked) WM_HSCROLL parameter, please report\n");
+ return 0;
+ }
+ if (dx)
+ EDIT_EM_LineScroll(wnd, es, dx, 0);
+ return ret;
+}
+
+
+/*********************************************************************
+ *
+ * WM_HSCROLL
+ *
+ */
+static LRESULT EDIT_WM_HScroll(WND *wnd, EDITSTATE *es, INT action, INT pos, HWND scroll_bar)
+{
+ INT dx;
+ INT fw;
+
+ if (!(es->style & ES_MULTILINE))
+ return 0;
+
+ if (!(es->style & ES_AUTOHSCROLL))
+ return 0;
+
+ if (!(es->style & WS_HSCROLL))
+ return EDIT_HScroll_Hack(wnd, es, action, pos, scroll_bar);
+
+ dx = 0;
+ fw = es->format_rect.right - es->format_rect.left;
+ switch (action) {
+ case SB_LINELEFT:
+ if (es->x_offset)
+ dx = -es->char_width;
+ break;
+ case SB_LINERIGHT:
+ if (es->x_offset < es->text_width)
+ dx = es->char_width;
+ break;
+ case SB_PAGELEFT:
+ if (es->x_offset)
+ dx = -fw / HSCROLL_FRACTION / es->char_width * es->char_width;
+ break;
+ case SB_PAGERIGHT:
+ if (es->x_offset < es->text_width)
+ dx = fw / HSCROLL_FRACTION / es->char_width * es->char_width;
+ break;
+ case SB_LEFT:
+ if (es->x_offset)
+ dx = -es->x_offset;
+ break;
+ case SB_RIGHT:
+ if (es->x_offset < es->text_width)
+ dx = es->text_width - es->x_offset;
+ break;
+ case SB_THUMBTRACK:
+ es->flags |= EF_HSCROLL_TRACK;
+ dx = pos - es->x_offset;
+ break;
+ case SB_THUMBPOSITION:
+ es->flags &= ~EF_HSCROLL_TRACK;
+ if (!(dx = pos - es->x_offset)) {
+ SetScrollPos(wnd->hwndSelf, SB_HORZ, pos, TRUE);
+ EDIT_NOTIFY_PARENT(wnd, EN_HSCROLL, "EN_HSCROLL");
+ }
+ break;
+ case SB_ENDSCROLL:
+ break;
+
+ default:
+ DPRINT( "undocumented WM_HSCROLL parameter, please report\n");
+ return 0;
+ }
+ if (dx)
+ EDIT_EM_LineScroll(wnd, es, dx, 0);
+ return 0;
+}
+
+
+/*********************************************************************
+ *
+ * EDIT_CheckCombo
+ *
+ */
+static BOOL EDIT_CheckCombo(WND *wnd, UINT msg, INT key, DWORD key_data)
+{
+ HWND hLBox;
+
+ if (WIDGETS_IsControl(wnd->parent, BIC_COMBO) &&
+ (hLBox = COMBO_GetLBWindow(wnd->parent))) {
+ HWND hCombo = wnd->parent->hwndSelf;
+ BOOL bUIFlip = TRUE;
+
+ DPRINT( "[%04x]: handling msg %04x (%04x)\n",
+ wnd->hwndSelf, (UINT)msg, (UINT)key);
+
+ switch (msg) {
+ case WM_KEYDOWN: /* Handle F4 and arrow keys */
+ if (key != VK_F4) {
+ bUIFlip = (BOOL)SendMessageA(hCombo, CB_GETEXTENDEDUI, 0, 0);
+ if (SendMessageA(hCombo, CB_GETDROPPEDSTATE, 0, 0))
+ bUIFlip = FALSE;
+ }
+ if (!bUIFlip)
+ SendMessageA(hLBox, WM_KEYDOWN, (WPARAM)key, 0);
+ else {
+ /* make sure ComboLBox pops up */
+ SendMessageA(hCombo, CB_SETEXTENDEDUI, 0, 0);
+ SendMessageA(hLBox, WM_KEYDOWN, VK_F4, 0);
+ SendMessageA(hCombo, CB_SETEXTENDEDUI, 1, 0);
+ }
+ break;
+ case WM_SYSKEYDOWN: /* Handle Alt+up/down arrows */
+ bUIFlip = (BOOL)SendMessageA(hCombo, CB_GETEXTENDEDUI, 0, 0);
+ if (bUIFlip) {
+ bUIFlip = (BOOL)SendMessageA(hCombo, CB_GETDROPPEDSTATE, 0, 0);
+ SendMessageA(hCombo, CB_SHOWDROPDOWN, (bUIFlip) ? FALSE : TRUE, 0);
+ } else
+ SendMessageA(hLBox, WM_KEYDOWN, VK_F4, 0);
+ break;
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+/*********************************************************************
+ *
+ * WM_KEYDOWN
+ *
+ * Handling of special keys that don't produce a WM_CHAR
+ * (i.e. non-printable keys) & Backspace & Delete
+ *
+ */
+static LRESULT EDIT_WM_KeyDown(WND *wnd, EDITSTATE *es, INT key, DWORD key_data)
+{
+ BOOL shift;
+ BOOL control;
+
+ if (GetKeyState(VK_MENU) & 0x8000)
+ return 0;
+
+ shift = GetKeyState(VK_SHIFT) & 0x8000;
+ control = GetKeyState(VK_CONTROL) & 0x8000;
+
+ switch (key) {
+ case VK_F4:
+ case VK_UP:
+ if (EDIT_CheckCombo(wnd, WM_KEYDOWN, key, key_data))
+ break;
+ if (key == VK_F4)
+ break;
+ /* fall through */
+ case VK_LEFT:
+ if ((es->style & ES_MULTILINE) && (key == VK_UP))
+ EDIT_MoveUp_ML(wnd, es, shift);
+ else
+ if (control)
+ EDIT_MoveWordBackward(wnd, es, shift);
+ else
+ EDIT_MoveBackward(wnd, es, shift);
+ break;
+ case VK_DOWN:
+ if (EDIT_CheckCombo(wnd, WM_KEYDOWN, key, key_data))
+ break;
+ /* fall through */
+ case VK_RIGHT:
+ if ((es->style & ES_MULTILINE) && (key == VK_DOWN))
+ EDIT_MoveDown_ML(wnd, es, shift);
+ else if (control)
+ EDIT_MoveWordForward(wnd, es, shift);
+ else
+ EDIT_MoveForward(wnd, es, shift);
+ break;
+ case VK_HOME:
+ EDIT_MoveHome(wnd, es, shift);
+ break;
+ case VK_END:
+ EDIT_MoveEnd(wnd, es, shift);
+ break;
+ case VK_PRIOR:
+ if (es->style & ES_MULTILINE)
+ EDIT_MovePageUp_ML(wnd, es, shift);
+ break;
+ case VK_NEXT:
+ if (es->style & ES_MULTILINE)
+ EDIT_MovePageDown_ML(wnd, es, shift);
+ break;
+ case VK_BACK:
+ if (!(es->style & ES_READONLY) && !control) {
+ if (es->selection_start != es->selection_end)
+ EDIT_WM_Clear(wnd, es);
+ else {
+ /* delete character left of caret */
+ EDIT_EM_SetSel(wnd, es, -1, 0, FALSE);
+ EDIT_MoveBackward(wnd, es, TRUE);
+ EDIT_WM_Clear(wnd, es);
+ }
+ }
+ break;
+ case VK_DELETE:
+ if (!(es->style & ES_READONLY) && !(shift && control)) {
+ if (es->selection_start != es->selection_end) {
+ if (shift)
+ EDIT_WM_Cut(wnd, es);
+ else
+ EDIT_WM_Clear(wnd, es);
+ } else {
+ if (shift) {
+ /* delete character left of caret */
+ EDIT_EM_SetSel(wnd, es, -1, 0, FALSE);
+ EDIT_MoveBackward(wnd, es, TRUE);
+ EDIT_WM_Clear(wnd, es);
+ } else if (control) {
+ /* delete to end of line */
+ EDIT_EM_SetSel(wnd, es, -1, 0, FALSE);
+ EDIT_MoveEnd(wnd, es, TRUE);
+ EDIT_WM_Clear(wnd, es);
+ } else {
+ /* delete character right of caret */
+ EDIT_EM_SetSel(wnd, es, -1, 0, FALSE);
+ EDIT_MoveForward(wnd, es, TRUE);
+ EDIT_WM_Clear(wnd, es);
+ }
+ }
+ }
+ break;
+ case VK_INSERT:
+ if (shift) {
+ if (!(es->style & ES_READONLY))
+ EDIT_WM_Paste(wnd, es);
+ } else if (control)
+ EDIT_WM_Copy(wnd, es);
+ break;
+ }
+ return 0;
+}
+
+
+/*********************************************************************
+ *
+ * WM_KILLFOCUS
+ *
+ */
+static LRESULT EDIT_WM_KillFocus(WND *wnd, EDITSTATE *es, HWND window_getting_focus)
+{
+ es->flags &= ~EF_FOCUSED;
+ DestroyCaret();
+ if(!(es->style & ES_NOHIDESEL))
+ EDIT_InvalidateText(wnd, es, es->selection_start, es->selection_end);
+ EDIT_NOTIFY_PARENT(wnd, EN_KILLFOCUS, "EN_KILLFOCUS");
+ return 0;
+}
+
+
+/*********************************************************************
+ *
+ * WM_LBUTTONDBLCLK
+ *
+ * The caret position has been set on the WM_LBUTTONDOWN message
+ *
+ */
+static LRESULT EDIT_WM_LButtonDblClk(WND *wnd, EDITSTATE *es, DWORD keys, INT x, INT y)
+{
+ INT s;
+ INT e = es->selection_end;
+ INT l;
+ INT li;
+ INT ll;
+
+ if (!(es->flags & EF_FOCUSED))
+ return 0;
+
+ l = EDIT_EM_LineFromChar(wnd, es, e);
+ li = EDIT_EM_LineIndex(wnd, es, l);
+ ll = EDIT_EM_LineLength(wnd, es, e);
+ s = li + EDIT_CallWordBreakProc (wnd, es, li, e - li, ll, WB_LEFT);
+ e = li + EDIT_CallWordBreakProc(wnd, es, li, e - li, ll, WB_RIGHT);
+ EDIT_EM_SetSel(wnd, es, s, e, FALSE);
+ EDIT_EM_ScrollCaret(wnd, es);
+ return 0;
+}
+
+
+/*********************************************************************
+ *
+ * WM_LBUTTONDOWN
+ *
+ */
+static LRESULT EDIT_WM_LButtonDown(WND *wnd, EDITSTATE *es, DWORD keys, INT x, INT y)
+{
+ INT e;
+ BOOL after_wrap;
+
+ if (!(es->flags & EF_FOCUSED))
+ return 0;
+
+ SetCapture(wnd->hwndSelf);
+ EDIT_ConfinePoint(wnd, es, &x, &y);
+ e = EDIT_CharFromPos(wnd, es, x, y, &after_wrap);
+ EDIT_EM_SetSel(wnd, es, (keys & MK_SHIFT) ? es->selection_start : e, e, after_wrap);
+ EDIT_EM_ScrollCaret(wnd, es);
+ es->region_posx = es->region_posy = 0;
+ SetTimer(wnd->hwndSelf, 0, 100, NULL);
+ return 0;
+}
+
+
+/*********************************************************************
+ *
+ * WM_LBUTTONUP
+ *
+ */
+static LRESULT EDIT_WM_LButtonUp(WND *wnd, EDITSTATE *es, DWORD keys, INT x, INT y)
+{
+ if (GetCapture() == wnd->hwndSelf) {
+ KillTimer(wnd->hwndSelf, 0);
+ ReleaseCapture();
+ }
+ return 0;
+}
+
+
+/*********************************************************************
+ *
+ * WM_MOUSEMOVE
+ *
+ */
+static LRESULT EDIT_WM_MouseMove(WND *wnd, EDITSTATE *es, DWORD keys, INT x, INT y)
+{
+ INT e;
+ BOOL after_wrap;
+ INT prex, prey;
+
+ if (GetCapture() != wnd->hwndSelf)
+ return 0;
+
+ /*
+ * FIXME: gotta do some scrolling if outside client
+ * area. Maybe reset the timer ?
+ */
+ prex = x; prey = y;
+ EDIT_ConfinePoint(wnd, es, &x, &y);
+ es->region_posx = (prex < x) ? -1 : ((prex > x) ? 1 : 0);
+ es->region_posy = (prey < y) ? -1 : ((prey > y) ? 1 : 0);
+ e = EDIT_CharFromPos(wnd, es, x, y, &after_wrap);
+ EDIT_EM_SetSel(wnd, es, es->selection_start, e, after_wrap);
+ return 0;
+}
+
+
+/*********************************************************************
+ *
+ * WM_NCCREATE
+ *
+ */
+static LRESULT EDIT_WM_NCCreate(WND *wnd, LPCREATESTRUCTA cs)
+{
+ EDITSTATE *es;
+
+ if (!(es = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*es))))
+ return FALSE;
+ *(EDITSTATE **)wnd->wExtra = es;
+
+ /*
+ * Note: since the EDITSTATE has not been fully initialized yet,
+ * we can't use any API calls that may send
+ * WM_XXX messages before WM_NCCREATE is completed.
+ */
+
+ if (!(es->heap = HeapCreate(0, 0x10000, 0)))
+ return FALSE;
+ es->style = cs->style;
+
+ if ((es->style & WS_BORDER) && !(es->style & WS_DLGFRAME))
+ wnd->dwStyle &= ~WS_BORDER;
+
+ if (es->style & ES_MULTILINE) {
+ es->buffer_size = BUFSTART_MULTI;
+ es->buffer_limit = BUFLIMIT_MULTI;
+ if (es->style & WS_VSCROLL)
+ es->style |= ES_AUTOVSCROLL;
+ if (es->style & WS_HSCROLL)
+ es->style |= ES_AUTOHSCROLL;
+ es->style &= ~ES_PASSWORD;
+ if ((es->style & ES_CENTER) || (es->style & ES_RIGHT)) {
+ if (es->style & ES_RIGHT)
+ es->style &= ~ES_CENTER;
+ es->style &= ~WS_HSCROLL;
+ es->style &= ~ES_AUTOHSCROLL;
+ }
+
+ /* FIXME: for now, all multi line controls are AUTOVSCROLL */
+ es->style |= ES_AUTOVSCROLL;
+ } else {
+ es->buffer_size = BUFSTART_SINGLE;
+ es->buffer_limit = BUFLIMIT_SINGLE;
+ es->style &= ~ES_CENTER;
+ es->style &= ~ES_RIGHT;
+ es->style &= ~WS_HSCROLL;
+ es->style &= ~WS_VSCROLL;
+ es->style &= ~ES_AUTOVSCROLL;
+ es->style &= ~ES_WANTRETURN;
+ if (es->style & ES_UPPERCASE) {
+ es->style &= ~ES_LOWERCASE;
+ es->style &= ~ES_NUMBER;
+ } else if (es->style & ES_LOWERCASE)
+ es->style &= ~ES_NUMBER;
+ if (es->style & ES_PASSWORD)
+ es->password_char = '*';
+
+ /* FIXME: for now, all single line controls are AUTOHSCROLL */
+ es->style |= ES_AUTOHSCROLL;
+ }
+ if (!(es->text = HeapAlloc(es->heap, 0, es->buffer_size + 1)))
+ return FALSE;
+ es->buffer_size = HeapSize(es->heap, 0, es->text) - 1;
+ if (!(es->undo_text = HeapAlloc(es->heap, 0, es->buffer_size + 1)))
+ return FALSE;
+ es->undo_buffer_size = HeapSize(es->heap, 0, es->undo_text) - 1;
+ *es->text = '\0';
+ if (es->style & ES_MULTILINE)
+ if (!(es->first_line_def = HeapAlloc(es->heap, HEAP_ZERO_MEMORY, sizeof(LINEDEF))))
+ return FALSE;
+ es->line_count = 1;
+
+ return TRUE;
+}
+
+/*********************************************************************
+ *
+ * WM_PAINT
+ *
+ */
+static void EDIT_WM_Paint(WND *wnd, EDITSTATE *es)
+{
+ PAINTSTRUCT ps;
+ INT i;
+ HDC dc;
+ HFONT old_font = 0;
+ RECT rc;
+ RECT rcLine;
+ RECT rcRgn;
+ BOOL rev = IsWindowEnabled(wnd->hwndSelf) &&
+ ((es->flags & EF_FOCUSED) ||
+ (es->style & ES_NOHIDESEL));
+
+ if (es->flags & EF_UPDATE)
+ EDIT_NOTIFY_PARENT(wnd, EN_UPDATE, "EN_UPDATE");
+
+ dc = BeginPaint(wnd->hwndSelf, &ps);
+ if(es->style & WS_BORDER) {
+ GetClientRect(wnd->hwndSelf, &rc);
+ if(es->style & ES_MULTILINE) {
+ if(es->style & WS_HSCROLL) rc.bottom++;
+ if(es->style & WS_VSCROLL) rc.right++;
+ }
+ Rectangle(dc, rc.left, rc.top, rc.right, rc.bottom);
+ }
+ IntersectClipRect(dc, es->format_rect.left,
+ es->format_rect.top,
+ es->format_rect.right,
+ es->format_rect.bottom);
+ if (es->style & ES_MULTILINE) {
+ GetClientRect(wnd->hwndSelf, &rc);
+ IntersectClipRect(dc, rc.left, rc.top, rc.right, rc.bottom);
+ }
+ if (es->font)
+ old_font = SelectObject(dc, es->font);
+ EDIT_SEND_CTLCOLOR(wnd, dc);
+ if (!IsWindowEnabled(wnd->hwndSelf))
+ SetTextColor(dc, GetSysColor(COLOR_GRAYTEXT));
+ GetClipBox(dc, &rcRgn);
+ if (es->style & ES_MULTILINE) {
+ INT vlc = (es->format_rect.bottom - es->format_rect.top) / es->line_height;
+ for (i = es->y_offset ; i <= MIN(es->y_offset + vlc, es->y_offset + es->line_count - 1) ; i++) {
+ EDIT_GetLineRect(wnd, es, i, 0, -1, &rcLine);
+ if (IntersectRect(&rc, &rcRgn, &rcLine))
+ EDIT_PaintLine(wnd, es, dc, i, rev);
+ }
+ } else {
+ EDIT_GetLineRect(wnd, es, 0, 0, -1, &rcLine);
+ if (IntersectRect(&rc, &rcRgn, &rcLine))
+ EDIT_PaintLine(wnd, es, dc, 0, rev);
+ }
+ if (es->font)
+ SelectObject(dc, old_font);
+ if (es->flags & EF_FOCUSED)
+ EDIT_SetCaretPos(wnd, es, es->selection_end,
+ es->flags & EF_AFTER_WRAP);
+ EndPaint(wnd->hwndSelf, &ps);
+ if ((es->style & WS_VSCROLL) && !(es->flags & EF_VSCROLL_TRACK)) {
+ INT vlc = (es->format_rect.bottom - es->format_rect.top) / es->line_height;
+ SCROLLINFO si;
+ si.cbSize = sizeof(SCROLLINFO);
+ si.fMask = SIF_PAGE | SIF_POS | SIF_RANGE | SIF_DISABLENOSCROLL;
+ si.nMin = 0;
+ si.nMax = es->line_count + vlc - 2;
+ si.nPage = vlc;
+ si.nPos = es->y_offset;
+ SetScrollInfo(wnd->hwndSelf, SB_VERT, &si, TRUE);
+ }
+ if ((es->style & WS_HSCROLL) && !(es->flags & EF_HSCROLL_TRACK)) {
+ SCROLLINFO si;
+ INT fw = es->format_rect.right - es->format_rect.left;
+ si.cbSize = sizeof(SCROLLINFO);
+ si.fMask = SIF_PAGE | SIF_POS | SIF_RANGE | SIF_DISABLENOSCROLL;
+ si.nMin = 0;
+ si.nMax = es->text_width + fw - 1;
+ si.nPage = fw;
+ si.nPos = es->x_offset;
+ SetScrollInfo(wnd->hwndSelf, SB_HORZ, &si, TRUE);
+ }
+
+ if (es->flags & EF_UPDATE) {
+ es->flags &= ~EF_UPDATE;
+ EDIT_NOTIFY_PARENT(wnd, EN_CHANGE, "EN_CHANGE");
+ }
+}
+
+
+/*********************************************************************
+ *
+ * WM_PASTE
+ *
+ */
+static void EDIT_WM_Paste(WND *wnd, EDITSTATE *es)
+{
+ HGLOBAL hsrc;
+ LPSTR src;
+
+ OpenClipboard(wnd->hwndSelf);
+ if ((hsrc = GetClipboardData(CF_TEXT))) {
+ src = (LPSTR)GlobalLock(hsrc);
+ EDIT_EM_ReplaceSel(wnd, es, TRUE, src);
+ GlobalUnlock(hsrc);
+ }
+ CloseClipboard();
+}
+
+
+/*********************************************************************
+ *
+ * WM_SETFOCUS
+ *
+ */
+static void EDIT_WM_SetFocus(WND *wnd, EDITSTATE *es, HWND window_losing_focus)
+{
+ es->flags |= EF_FOCUSED;
+ CreateCaret(wnd->hwndSelf, 0, 2, es->line_height);
+ EDIT_SetCaretPos(wnd, es, es->selection_end,
+ es->flags & EF_AFTER_WRAP);
+ if(!(es->style & ES_NOHIDESEL))
+ EDIT_InvalidateText(wnd, es, es->selection_start, es->selection_end);
+ ShowCaret(wnd->hwndSelf);
+ EDIT_NOTIFY_PARENT(wnd, EN_SETFOCUS, "EN_SETFOCUS");
+}
+
+
+/*********************************************************************
+ *
+ * WM_SETFONT
+ *
+ * With Win95 look the margins are set to default font value unless
+ * the system font (font == 0) is being set, in which case they are left
+ * unchanged.
+ *
+ */
+static void EDIT_WM_SetFont(WND *wnd, EDITSTATE *es, HFONT font, BOOL redraw)
+{
+ TEXTMETRIC tm;
+ HDC dc;
+ HFONT old_font = 0;
+
+ es->font = font;
+ dc = GetDC(wnd->hwndSelf);
+ if (font)
+ old_font = SelectObject(dc, font);
+ GetTextMetricsA(dc, &tm);
+ es->line_height = tm.tmHeight;
+ es->char_width = tm.tmAveCharWidth;
+ if (font)
+ SelectObject(dc, old_font);
+ ReleaseDC(wnd->hwndSelf, dc);
+ if (font && (TWEAK_WineLook > WIN31_LOOK))
+ EDIT_EM_SetMargins(wnd, es, EC_LEFTMARGIN | EC_RIGHTMARGIN,
+ EC_USEFONTINFO, EC_USEFONTINFO);
+ if (es->style & ES_MULTILINE)
+ EDIT_BuildLineDefs_ML(wnd, es);
+ else {
+ RECT r;
+ GetClientRect(wnd->hwndSelf, &r);
+ EDIT_SetRectNP(wnd, es, &r);
+ }
+ if (redraw)
+ InvalidateRect(wnd->hwndSelf, NULL, TRUE);
+ if (es->flags & EF_FOCUSED) {
+ DestroyCaret();
+ CreateCaret(wnd->hwndSelf, 0, 2, es->line_height);
+ EDIT_SetCaretPos(wnd, es, es->selection_end,
+ es->flags & EF_AFTER_WRAP);
+ ShowCaret(wnd->hwndSelf);
+ }
+}
+
+
+/*********************************************************************
+ *
+ * WM_SETTEXT
+ *
+ * NOTES
+ * For multiline controls (ES_MULTILINE), reception of WM_SETTEXT triggers:
+ * The modified flag is reset. No notifications are sent.
+ *
+ * For single-line controls, reception of WM_SETTEXT triggers:
+ * The modified flag is reset. EN_UPDATE and EN_CHANGE notifications are sent.
+ *
+ */
+static void EDIT_WM_SetText(WND *wnd, EDITSTATE *es, LPCSTR text)
+{
+ EDIT_EM_SetSel(wnd, es, 0, -1, FALSE);
+ if (text) {
+ DPRINT( "\t'%s'\n", text);
+ EDIT_EM_ReplaceSel(wnd, es, FALSE, text);
+ } else {
+ DPRINT( "\t<NULL>\n");
+ EDIT_EM_ReplaceSel(wnd, es, FALSE, "");
+ }
+ es->x_offset = 0;
+ if (es->style & ES_MULTILINE) {
+ es->flags &= ~EF_UPDATE;
+ } else {
+ es->flags |= EF_UPDATE;
+ }
+ es->flags &= ~EF_MODIFIED;
+ EDIT_EM_SetSel(wnd, es, 0, 0, FALSE);
+ EDIT_EM_ScrollCaret(wnd, es);
+}
+
+
+/*********************************************************************
+ *
+ * WM_SIZE
+ *
+ */
+static void EDIT_WM_Size(WND *wnd, EDITSTATE *es, UINT action, INT width, INT height)
+{
+ if ((action == SIZE_MAXIMIZED) || (action == SIZE_RESTORED)) {
+ RECT rc;
+ SetRect(&rc, 0, 0, width, height);
+ EDIT_SetRectNP(wnd, es, &rc);
+ InvalidateRect(wnd->hwndSelf, NULL, TRUE);
+ }
+}
+
+
+/*********************************************************************
+ *
+ * WM_SYSKEYDOWN
+ *
+ */
+static LRESULT EDIT_WM_SysKeyDown(WND *wnd, EDITSTATE *es, INT key, DWORD key_data)
+{
+ if ((key == VK_BACK) && (key_data & 0x2000)) {
+ if (EDIT_EM_CanUndo(wnd, es))
+ EDIT_EM_Undo(wnd, es);
+ return 0;
+ } else if (key == VK_UP || key == VK_DOWN)
+ if (EDIT_CheckCombo(wnd, WM_SYSKEYDOWN, key, key_data))
+ return 0;
+ return DefWindowProcA(wnd->hwndSelf, WM_SYSKEYDOWN, (WPARAM)key, (LPARAM)key_data);
+}
+
+
+/*********************************************************************
+ *
+ * WM_TIMER
+ *
+ */
+static void EDIT_WM_Timer(WND *wnd, EDITSTATE *es, INT id, TIMERPROC timer_proc)
+{
+ if (es->region_posx < 0) {
+ EDIT_MoveBackward(wnd, es, TRUE);
+ } else if (es->region_posx > 0) {
+ EDIT_MoveForward(wnd, es, TRUE);
+ }
+/*
+ * FIXME: gotta do some vertical scrolling here, like
+ * EDIT_EM_LineScroll(wnd, 0, 1);
+ */
+}
+
+
+/*********************************************************************
+ *
+ * EDIT_VScroll_Hack
+ *
+ * 16 bit notepad needs this. Actually it is not _our_ hack,
+ * it is notepad's. Notepad is sending us scrollbar messages with
+ * undocumented parameters without us even having a scrollbar ... !?!?
+ *
+ */
+static LRESULT EDIT_VScroll_Hack(WND *wnd, EDITSTATE *es, INT action, INT pos, HWND scroll_bar)
+{
+ INT dy = 0;
+ LRESULT ret = 0;
+
+ if (!(es->flags & EF_VSCROLL_HACK)) {
+ DPRINT( "hacked WM_VSCROLL handler invoked\n");
+ DPRINT( " if you are _not_ running 16 bit notepad, please report\n");
+ DPRINT( " (this message is only displayed once per edit control)\n");
+ es->flags |= EF_VSCROLL_HACK;
+ }
+
+ switch (action) {
+ case SB_LINEUP:
+ case SB_LINEDOWN:
+ case SB_PAGEUP:
+ case SB_PAGEDOWN:
+ EDIT_EM_Scroll(wnd, es, action);
+ return 0;
+ case SB_TOP:
+ dy = -es->y_offset;
+ break;
+ case SB_BOTTOM:
+ dy = es->line_count - 1 - es->y_offset;
+ break;
+ case SB_THUMBTRACK:
+ es->flags |= EF_VSCROLL_TRACK;
+ dy = (pos * (es->line_count - 1) + 50) / 100 - es->y_offset;
+ break;
+ case SB_THUMBPOSITION:
+ es->flags &= ~EF_VSCROLL_TRACK;
+ if (!(dy = (pos * (es->line_count - 1) + 50) / 100 - es->y_offset))
+ EDIT_NOTIFY_PARENT(wnd, EN_VSCROLL, "EN_VSCROLL");
+ break;
+ case SB_ENDSCROLL:
+ break;
+
+ /*
+ * FIXME : the next two are undocumented !
+ * Are we doing the right thing ?
+ * At least Win 3.1 Notepad makes use of EM_GETTHUMB this way,
+ * although it's also a regular control message.
+ */
+ case EM_GETTHUMB:
+ ret = (es->line_count > 1) ? es->y_offset * 100 / (es->line_count - 1) : 0;
+ break;
+ case EM_LINESCROLL:
+ dy = pos;
+ break;
+
+ default:
+ DPRINT( "undocumented (hacked) WM_VSCROLL parameter, please report\n");
+ return 0;
+ }
+ if (dy)
+ EDIT_EM_LineScroll(wnd, es, 0, dy);
+ return ret;
+}
+
+
+/*********************************************************************
+ *
+ * WM_VSCROLL
+ *
+ */
+static LRESULT EDIT_WM_VScroll(WND *wnd, EDITSTATE *es, INT action, INT pos, HWND scroll_bar)
+{
+ INT dy;
+
+ if (!(es->style & ES_MULTILINE))
+ return 0;
+
+ if (!(es->style & ES_AUTOVSCROLL))
+ return 0;
+
+ if (!(es->style & WS_VSCROLL))
+ return EDIT_VScroll_Hack(wnd, es, action, pos, scroll_bar);
+
+ dy = 0;
+ switch (action) {
+ case SB_LINEUP:
+ case SB_LINEDOWN:
+ case SB_PAGEUP:
+ case SB_PAGEDOWN:
+ EDIT_EM_Scroll(wnd, es, action);
+ return 0;
+
+ case SB_TOP:
+ dy = -es->y_offset;
+ break;
+ case SB_BOTTOM:
+ dy = es->line_count - 1 - es->y_offset;
+ break;
+ case SB_THUMBTRACK:
+ es->flags |= EF_VSCROLL_TRACK;
+ dy = pos - es->y_offset;
+ break;
+ case SB_THUMBPOSITION:
+ es->flags &= ~EF_VSCROLL_TRACK;
+ if (!(dy = pos - es->y_offset)) {
+ SetScrollPos(wnd->hwndSelf, SB_VERT, pos, TRUE);
+ EDIT_NOTIFY_PARENT(wnd, EN_VSCROLL, "EN_VSCROLL");
+ }
+ break;
+ case SB_ENDSCROLL:
+ break;
+
+ default:
+ DPRINT( "undocumented WM_VSCROLL action %d, please report\n",
+ action);
+ return 0;
+ }
+ if (dy)
+ EDIT_EM_LineScroll(wnd, es, 0, dy);
+ return 0;
+}
+
+// temporary hack
+
+WINBOOL STDCALL IsClipboardFormatAvailable(
+ UINT format
+ )
+{
+ return FALSE;
+}
+
+WINBOOL
+STDCALL
+OpenClipboard(
+ HWND hWndNewOwner)
+{
+ return FALSE;
+}
+
+WINBOOL
+STDCALL
+CloseClipboard(
+ VOID)
+{
+ return TRUE;
+}
+
+WINBOOL
+STDCALL
+EmptyClipboard(
+ VOID)
+{
+ return TRUE;
+}
+
+HANDLE
+STDCALL
+SetClipboardData(
+ UINT uFormat,
+ HANDLE hMem)
+{
+ return NULL;
+}
+
+
+HANDLE
+STDCALL
+GetClipboardData(
+ UINT uFormat)
+{
+ return NULL;
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Icontitle window class.
+ *
+ * Copyright 1997 Alex Korobka
+ */
+
+#include <windows.h>
+#include <user32/widgets.h>
+#include <user32/sysmetr.h>
+#include <user32/win.h>
+#include <user32/heapdup.h>
+
+#define WM_ISACTIVEICON 0x0035
+
+static LPCSTR emptyTitleText = "<...>";
+
+ WINBOOL bMultiLineTitle;
+ HFONT hIconTitleFont;
+
+/***********************************************************************
+ * ICONTITLE_Init
+ */
+WINBOOL ICONTITLE_Init(void)
+{
+ LOGFONT logFont;
+
+ SystemParametersInfoA( SPI_GETICONTITLELOGFONT, 0, &logFont, 0 );
+ SystemParametersInfoA( SPI_GETICONTITLEWRAP, 0, &bMultiLineTitle, 0 );
+ hIconTitleFont = CreateFontIndirectA( &logFont );
+ return (hIconTitleFont) ? TRUE : FALSE;
+}
+
+/***********************************************************************
+ * ICONTITLE_Create
+ */
+HWND ICONTITLE_Create( WND* wnd )
+{
+ WND* wndPtr;
+ HWND hWnd;
+
+ if( wnd->dwStyle & WS_CHILD )
+ hWnd = CreateWindowExA( 0, ICONTITLE_CLASS_ATOM, NULL,
+ WS_CHILD | WS_CLIPSIBLINGS, 0, 0, 1, 1,
+ wnd->parent->hwndSelf, 0, wnd->hInstance, NULL );
+ else
+ hWnd = CreateWindowExA( 0, ICONTITLE_CLASS_ATOM, NULL,
+ WS_CLIPSIBLINGS, 0, 0, 1, 1,
+ wnd->hwndSelf, 0, wnd->hInstance, NULL );
+ wndPtr = WIN_FindWndPtr( hWnd );
+ if( wndPtr )
+ {
+ wndPtr->owner = wnd; /* MDI depends on this */
+ wndPtr->dwStyle &= ~(WS_CAPTION | WS_BORDER);
+ if( wnd->dwStyle & WS_DISABLED ) wndPtr->dwStyle |= WS_DISABLED;
+ return hWnd;
+ }
+ return 0;
+}
+
+/***********************************************************************
+ * ICONTITLE_GetTitlePos
+ */
+WINBOOL ICONTITLE_GetTitlePos( WND* wnd, LPRECT lpRect )
+{
+ LPSTR str;
+ int length = lstrlenA( wnd->owner->text );
+
+ if( length )
+ {
+ str = HeapAlloc( GetProcessHeap(), 0, length + 1 );
+ lstrcpyA( str, wnd->owner->text );
+ while( str[length - 1] == ' ' ) /* remove trailing spaces */
+ {
+ str[--length] = '\0';
+ if( !length )
+ {
+ HeapFree( GetProcessHeap(), 0, str );
+ break;
+ }
+ }
+ }
+ if( !length )
+ {
+ str = (LPSTR)emptyTitleText;
+ length = lstrlenA( str );
+ }
+
+ if( str )
+ {
+ HDC hDC = GetDC( wnd->hwndSelf );
+ if( hDC )
+ {
+ HFONT hPrevFont = SelectObject( hDC, hIconTitleFont );
+
+ SetRect( lpRect, 0, 0, sysMetrics[SM_CXICONSPACING] -
+ SYSMETRICS_CXBORDER * 2, SYSMETRICS_CYBORDER * 2 );
+
+ DrawTextA( hDC, str, length, lpRect, DT_CALCRECT |
+ DT_CENTER | DT_NOPREFIX | DT_WORDBREAK |
+ (( bMultiLineTitle ) ? 0 : DT_SINGLELINE) );
+
+ SelectObject( hDC, hPrevFont );
+ ReleaseDC( wnd->hwndSelf, hDC );
+
+ lpRect->right += 4 * SYSMETRICS_CXBORDER - lpRect->left;
+ lpRect->left = wnd->owner->rectWindow.left + SYSMETRICS_CXICON / 2 -
+ (lpRect->right - lpRect->left) / 2;
+ lpRect->bottom -= lpRect->top;
+ lpRect->top = wnd->owner->rectWindow.top + SYSMETRICS_CYICON;
+ }
+ if( str != emptyTitleText ) HeapFree( GetProcessHeap(), 0, str );
+ return ( hDC ) ? TRUE : FALSE;
+ }
+ return FALSE;
+}
+
+/***********************************************************************
+ * ICONTITLE_Paint
+ */
+WINBOOL ICONTITLE_Paint( WND* wnd, HDC hDC, WINBOOL bActive )
+{
+ HFONT hPrevFont;
+ HBRUSH hBrush = 0;
+ COLORREF textColor = 0;
+
+ if( bActive )
+ {
+ hBrush = GetSysColorBrush(COLOR_ACTIVECAPTION);
+ textColor = GetSysColor(COLOR_CAPTIONTEXT);
+ }
+ else
+ {
+ if( wnd->dwStyle & WS_CHILD )
+ {
+ hBrush = wnd->parent->class->hbrBackground;
+ if( hBrush )
+ {
+ INT level;
+ LOGBRUSH logBrush;
+ GetObjectA( hBrush, sizeof(logBrush), &logBrush );
+ level = GetRValue(logBrush.lbColor) +
+ GetGValue(logBrush.lbColor) +
+ GetBValue(logBrush.lbColor);
+ if( level < (0x7F * 3) )
+ textColor = RGB( 0xFF, 0xFF, 0xFF );
+ }
+ else
+ hBrush = GetStockObject( WHITE_BRUSH );
+ }
+ else
+ {
+ hBrush = GetStockObject( BLACK_BRUSH );
+ textColor = RGB( 0xFF, 0xFF, 0xFF );
+ }
+ }
+
+ FillWindow( wnd->parent->hwndSelf, wnd->hwndSelf, hDC, hBrush );
+
+ hPrevFont = SelectObject( hDC, hIconTitleFont );
+ if( hPrevFont )
+ {
+ RECT rect;
+ INT length;
+ char buffer[80];
+
+ rect.left = rect.top = 0;
+ rect.right = wnd->rectWindow.right - wnd->rectWindow.left;
+ rect.bottom = wnd->rectWindow.bottom - wnd->rectWindow.top;
+
+ length = GetWindowTextA( wnd->owner->hwndSelf, buffer, 80 );
+ SetTextColor( hDC, textColor );
+ SetBkMode( hDC, TRANSPARENT );
+
+ DrawTextA( hDC, buffer, length, &rect, DT_CENTER | DT_NOPREFIX |
+ DT_WORDBREAK | ((bMultiLineTitle) ? 0 : DT_SINGLELINE) );
+
+ SelectObject( hDC, hPrevFont );
+ }
+ return ( hPrevFont ) ? TRUE : FALSE;
+}
+
+/***********************************************************************
+ * IconTitleWndProc
+ */
+LRESULT WINAPI IconTitleWndProc( HWND hWnd, UINT msg,
+ WPARAM wParam, LPARAM lParam )
+{
+ WND *wnd = WIN_FindWndPtr( hWnd );
+
+ switch( msg )
+ {
+ case WM_NCHITTEST:
+ return HTCAPTION;
+
+ case WM_NCMOUSEMOVE:
+ case WM_NCLBUTTONDBLCLK:
+ return SendMessageA( wnd->owner->hwndSelf, msg, wParam, lParam );
+
+ case WM_ACTIVATE:
+ if( wParam ) SetActiveWindow( wnd->owner->hwndSelf );
+ /* fall through */
+
+ case WM_CLOSE:
+ return 0;
+
+ case WM_SHOWWINDOW:
+ if( wnd && wParam )
+ {
+ RECT titleRect;
+
+ ICONTITLE_GetTitlePos( wnd, &titleRect );
+ if( wnd->owner->next != wnd ) /* keep icon title behind the owner */
+ SetWindowPos( hWnd, wnd->owner->hwndSelf,
+ titleRect.left, titleRect.top,
+ titleRect.right, titleRect.bottom, SWP_NOACTIVATE );
+ else
+ SetWindowPos( hWnd, 0, titleRect.left, titleRect.top,
+ titleRect.right, titleRect.bottom,
+ SWP_NOACTIVATE | SWP_NOZORDER );
+ }
+ return 0;
+
+ case WM_ERASEBKGND:
+ if( wnd )
+ {
+ WND* iconWnd = wnd->owner;
+
+ if( iconWnd->dwStyle & WS_CHILD )
+ lParam = SendMessageA( iconWnd->hwndSelf, WM_ISACTIVEICON, 0, 0 );
+ else
+ lParam = (iconWnd->hwndSelf == GetActiveWindow());
+
+ if( ICONTITLE_Paint( wnd, (HDC)wParam, (WINBOOL)lParam ) )
+ ValidateRect( hWnd, NULL );
+ return 1;
+ }
+ }
+
+ return DefWindowProcA( hWnd, msg, wParam, lParam );
+}
+
+
--- /dev/null
+/*
+ * Listbox controls
+ *
+ * Copyright 1996 Alexandre Julliard
+ */
+
+#include <string.h>
+#include <windows.h>
+#include <user32/win.h>
+#include <user32/combo.h>
+#include <user32/scroll.h>
+#include <user32/debug.h>
+#include <user32/nc.h>
+
+#define MAX_DOS_DRIVES 26
+
+#define MAX(x,y) x > y ? x : y
+#define MIN(x,y) x < y ? x : y
+#define abs(x) ((x) < 0 ? -(x) : (x))
+
+#define WM_LBTRACKPOINT 0x0131
+#define WS_EX_DRAGDETECT 0x00000002L
+
+ /* D&D messages */
+#define WM_DROPOBJECT 0x022A
+#define WM_QUERYDROPOBJECT 0x022B
+#define WM_BEGINDRAG 0x022C
+#define WM_DRAGLOOP 0x022D
+#define WM_DRAGSELECT 0x022E
+#define WM_DRAGMOVE 0x022F
+
+
+/* Unimplemented yet:
+ * - LBS_NOSEL
+ * - LBS_USETABSTOPS
+ * - Unicode
+ * - Locale handling
+ */
+
+/* Items array granularity */
+#define LB_ARRAY_GRANULARITY 16
+
+/* Scrolling timeout in ms */
+#define LB_SCROLL_TIMEOUT 50
+
+/* Listbox system timer id */
+#define LB_TIMER_ID 2
+
+/* Item structure */
+typedef struct
+{
+ LPSTR str; /* Item text */
+ BOOL selected; /* Is item selected? */
+ UINT height; /* Item height (only for OWNERDRAWVARIABLE) */
+ DWORD data; /* User data */
+} LB_ITEMDATA;
+
+/* Listbox structure */
+typedef struct
+{
+ HANDLE heap; /* Heap for this listbox */
+ HWND owner; /* Owner window to send notifications to */
+ UINT style; /* Window style */
+ INT width; /* Window width */
+ INT height; /* Window height */
+ LB_ITEMDATA *items; /* Array of items */
+ INT nb_items; /* Number of items */
+ INT top_item; /* Top visible item */
+ INT selected_item; /* Selected item */
+ INT focus_item; /* Item that has the focus */
+ INT anchor_item; /* Anchor item for extended selection */
+ INT item_height; /* Default item height */
+ INT page_size; /* Items per listbox page */
+ INT column_width; /* Column width for multi-column listboxes */
+ INT horz_extent; /* Horizontal extent (0 if no hscroll) */
+ INT horz_pos; /* Horizontal position */
+ INT nb_tabs; /* Number of tabs in array */
+ INT *tabs; /* Array of tabs */
+ BOOL caret_on; /* Is caret on? */
+ HFONT font; /* Current font */
+ LCID locale; /* Current locale for string comparisons */
+ LPHEADCOMBO lphc; /* ComboLBox */
+} LB_DESCR;
+
+
+#define IS_OWNERDRAW(descr) \
+ ((descr)->style & (LBS_OWNERDRAWFIXED | LBS_OWNERDRAWVARIABLE))
+
+#define HAS_STRINGS(descr) \
+ (!IS_OWNERDRAW(descr) || ((descr)->style & LBS_HASSTRINGS))
+
+#define SEND_NOTIFICATION(wnd,descr,code) \
+ (SendMessageA( (descr)->owner, WM_COMMAND, \
+ MAKEWPARAM((((descr)->lphc)?ID_CB_LISTBOX:(wnd)->wIDmenu), (code) ), (LPARAM)(wnd)->hwndSelf ))
+
+/* Current timer status */
+typedef enum
+{
+ LB_TIMER_NONE,
+ LB_TIMER_UP,
+ LB_TIMER_LEFT,
+ LB_TIMER_DOWN,
+ LB_TIMER_RIGHT
+} TIMER_DIRECTION;
+
+static TIMER_DIRECTION LISTBOX_Timer = LB_TIMER_NONE;
+
+
+/***********************************************************************
+ * LISTBOX_DPRINT
+ */
+void LISTBOX_DPRINT( WND *wnd )
+{
+ INT i;
+ LB_ITEMDATA *item;
+ LB_DESCR *descr = *(LB_DESCR **)wnd->wExtra;
+
+ DPRINT( "Listbox:\n" );
+ DPRINT( "hwnd=%04x descr=%08x heap=%08x items=%d top=%d\n",
+ wnd->hwndSelf, (UINT)descr, descr->heap, descr->nb_items,
+ descr->top_item );
+ for (i = 0, item = descr->items; i < descr->nb_items; i++, item++)
+ {
+ DPRINT( "%4d: %-40s %d %08lx %3d\n",
+ i, item->str, item->selected, item->data, item->height );
+ }
+}
+
+
+/***********************************************************************
+ * LISTBOX_GetCurrentPageSize
+ *
+ * Return the current page size
+ */
+static INT LISTBOX_GetCurrentPageSize( WND *wnd, LB_DESCR *descr )
+{
+ INT i, height;
+ if (!(descr->style & LBS_OWNERDRAWVARIABLE)) return descr->page_size;
+ for (i = descr->top_item, height = 0; i < descr->nb_items; i++)
+ {
+ if ((height += descr->items[i].height) > descr->height) break;
+ }
+ if (i == descr->top_item) return 1;
+ else return i - descr->top_item;
+}
+
+
+/***********************************************************************
+ * LISTBOX_GetMaxTopIndex
+ *
+ * Return the maximum possible index for the top of the listbox.
+ */
+static INT LISTBOX_GetMaxTopIndex( WND *wnd, LB_DESCR *descr )
+{
+ INT max, page;
+
+ if (descr->style & LBS_OWNERDRAWVARIABLE)
+ {
+ page = descr->height;
+ for (max = descr->nb_items - 1; max >= 0; max--)
+ if ((page -= descr->items[max].height) < 0) break;
+ if (max < descr->nb_items - 1) max++;
+ }
+ else if (descr->style & LBS_MULTICOLUMN)
+ {
+ if ((page = descr->width / descr->column_width) < 1) page = 1;
+ max = (descr->nb_items + descr->page_size - 1) / descr->page_size;
+ max = (max - page) * descr->page_size;
+ }
+ else
+ {
+ max = descr->nb_items - descr->page_size;
+ }
+ if (max < 0) max = 0;
+ return max;
+}
+
+
+/***********************************************************************
+ * LISTBOX_UpdateScroll
+ *
+ * Update the scrollbars. Should be called whenever the content
+ * of the listbox changes.
+ */
+static void LISTBOX_UpdateScroll( WND *wnd, LB_DESCR *descr )
+{
+ SCROLLINFO info;
+
+ if (!(descr->style & WS_VSCROLL)) return;
+ /* It is important that we check descr->style, and not wnd->dwStyle,
+ for WS_VSCROLL, as the former is exactly the one passed in
+ argument to CreateWindow.
+ In Windows (and from now on in Wine :) a listbox created
+ with such a style (no WS_SCROLL) does not update
+ the scrollbar with listbox-related data, thus letting
+ the programmer use it for his/her own purposes. */
+
+ if (descr->style & LBS_NOREDRAW) return;
+ info.cbSize = sizeof(info);
+
+ if (descr->style & LBS_MULTICOLUMN)
+ {
+ info.nMin = 0;
+ info.nMax = (descr->nb_items - 1) / descr->page_size;
+ info.nPos = descr->top_item / descr->page_size;
+ info.nPage = descr->width / descr->column_width;
+ if (info.nPage < 1) info.nPage = 1;
+ info.fMask = SIF_RANGE | SIF_POS | SIF_PAGE;
+ if (descr->style & LBS_DISABLENOSCROLL)
+ info.fMask |= SIF_DISABLENOSCROLL;
+ SetScrollInfo( wnd->hwndSelf, SB_HORZ, &info, TRUE );
+ info.nMax = 0;
+ info.fMask = SIF_RANGE;
+ SetScrollInfo( wnd->hwndSelf, SB_VERT, &info, TRUE );
+ }
+ else
+ {
+ info.nMin = 0;
+ info.nMax = descr->nb_items - 1;
+ info.nPos = descr->top_item;
+ info.nPage = LISTBOX_GetCurrentPageSize( wnd, descr );
+ info.fMask = SIF_RANGE | SIF_POS | SIF_PAGE;
+ if (descr->style & LBS_DISABLENOSCROLL)
+ info.fMask |= SIF_DISABLENOSCROLL;
+ SetScrollInfo( wnd->hwndSelf, SB_VERT, &info, TRUE );
+
+ if (descr->horz_extent)
+ {
+ info.nMin = 0;
+ info.nMax = descr->horz_extent - 1;
+ info.nPos = descr->horz_pos;
+ info.nPage = descr->width;
+ info.fMask = SIF_RANGE | SIF_POS | SIF_PAGE;
+ if (descr->style & LBS_DISABLENOSCROLL)
+ info.fMask |= SIF_DISABLENOSCROLL;
+ SetScrollInfo( wnd->hwndSelf, SB_HORZ, &info, TRUE );
+ }
+ }
+}
+
+
+/***********************************************************************
+ * LISTBOX_SetTopItem
+ *
+ * Set the top item of the listbox, scrolling up or down if necessary.
+ */
+static LRESULT LISTBOX_SetTopItem( WND *wnd, LB_DESCR *descr, INT index,
+ BOOL scroll )
+{
+ INT max = LISTBOX_GetMaxTopIndex( wnd, descr );
+ if (index > max) index = max;
+ if (index < 0) index = 0;
+ if (descr->style & LBS_MULTICOLUMN) index -= index % descr->page_size;
+ if (descr->top_item == index) return LB_OKAY;
+ if (descr->style & LBS_MULTICOLUMN)
+ {
+ INT diff = (descr->top_item - index) / descr->page_size * descr->column_width;
+ if (scroll && (abs(diff) < descr->width))
+ ScrollWindowEx( wnd->hwndSelf, diff, 0, NULL, NULL, 0, NULL,
+ SW_INVALIDATE | SW_ERASE );
+ else
+ scroll = FALSE;
+ }
+ else if (scroll)
+ {
+ INT diff;
+ if (descr->style & LBS_OWNERDRAWVARIABLE)
+ {
+ INT i;
+ diff = 0;
+ if (index > descr->top_item)
+ {
+ for (i = index - 1; i >= descr->top_item; i--)
+ diff -= descr->items[i].height;
+ }
+ else
+ {
+ for (i = index; i < descr->top_item; i++)
+ diff += descr->items[i].height;
+ }
+ }
+ else
+ diff = (descr->top_item - index) * descr->item_height;
+
+ if (abs(diff) < descr->height)
+ ScrollWindowEx( wnd->hwndSelf, 0, diff, NULL, NULL, 0, NULL,
+ SW_INVALIDATE | SW_ERASE );
+ else
+ scroll = FALSE;
+ }
+ if (!scroll) InvalidateRect( wnd->hwndSelf, NULL, TRUE );
+ descr->top_item = index;
+ LISTBOX_UpdateScroll( wnd, descr );
+ return LB_OKAY;
+}
+
+
+/***********************************************************************
+ * LISTBOX_UpdatePage
+ *
+ * Update the page size. Should be called when the size of
+ * the client area or the item height changes.
+ */
+static void LISTBOX_UpdatePage( WND *wnd, LB_DESCR *descr )
+{
+ INT page_size;
+
+ if ((page_size = descr->height / descr->item_height) < 1) page_size = 1;
+ if (page_size == descr->page_size) return;
+ descr->page_size = page_size;
+ if (descr->style & LBS_MULTICOLUMN)
+ InvalidateRect( wnd->hwndSelf, NULL, TRUE );
+ LISTBOX_SetTopItem( wnd, descr, descr->top_item, FALSE );
+}
+
+
+/***********************************************************************
+ * LISTBOX_UpdateSize
+ *
+ * Update the size of the listbox. Should be called when the size of
+ * the client area changes.
+ */
+static void LISTBOX_UpdateSize( WND *wnd, LB_DESCR *descr )
+{
+ RECT rect;
+
+ GetClientRect( wnd->hwndSelf, &rect );
+ descr->width = rect.right - rect.left;
+ descr->height = rect.bottom - rect.top;
+ if (!(descr->style & LBS_NOINTEGRALHEIGHT) && !IS_OWNERDRAW(descr))
+ {
+ if ((descr->height > descr->item_height) &&
+ (descr->height % descr->item_height))
+ {
+ DPRINT( "[%04x]: changing height %d -> %d\n",
+ wnd->hwndSelf, descr->height,
+ descr->height - descr->height%descr->item_height );
+ SetWindowPos( wnd->hwndSelf, 0, 0, 0,
+ wnd->rectWindow.right - wnd->rectWindow.left,
+ wnd->rectWindow.bottom - wnd->rectWindow.top -
+ (descr->height % descr->item_height),
+ SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE );
+ return;
+ }
+ }
+ DPRINT( "[%04x]: new size = %d,%d\n",
+ wnd->hwndSelf, descr->width, descr->height );
+ LISTBOX_UpdatePage( wnd, descr );
+ LISTBOX_UpdateScroll( wnd, descr );
+}
+
+
+/***********************************************************************
+ * LISTBOX_GetItemRect
+ *
+ * Get the rectangle enclosing an item, in listbox client coordinates.
+ * Return 1 if the rectangle is (partially) visible, 0 if hidden, -1 on error.
+ */
+static LRESULT LISTBOX_GetItemRect( WND *wnd, LB_DESCR *descr, INT index,
+ RECT *rect )
+{
+ /* Index <= 0 is legal even on empty listboxes */
+ if (index && (index >= descr->nb_items)) return -1;
+ SetRect( rect, 0, 0, descr->width, descr->height );
+ if (descr->style & LBS_MULTICOLUMN)
+ {
+ INT col = (index / descr->page_size) -
+ (descr->top_item / descr->page_size);
+ rect->left += col * descr->column_width;
+ rect->right = rect->left + descr->column_width;
+ rect->top += (index % descr->page_size) * descr->item_height;
+ rect->bottom = rect->top + descr->item_height;
+ }
+ else if (descr->style & LBS_OWNERDRAWVARIABLE)
+ {
+ INT i;
+ rect->right += descr->horz_pos;
+ if ((index >= 0) && (index < descr->nb_items))
+ {
+ if (index < descr->top_item)
+ {
+ for (i = descr->top_item-1; i >= index; i--)
+ rect->top -= descr->items[i].height;
+ }
+ else
+ {
+ for (i = descr->top_item; i < index; i++)
+ rect->top += descr->items[i].height;
+ }
+ rect->bottom = rect->top + descr->items[index].height;
+
+ }
+ }
+ else
+ {
+ rect->top += (index - descr->top_item) * descr->item_height;
+ rect->bottom = rect->top + descr->item_height;
+ rect->right += descr->horz_pos;
+ }
+
+ return ((rect->left < descr->width) && (rect->right > 0) &&
+ (rect->top < descr->height) && (rect->bottom > 0));
+}
+
+
+/***********************************************************************
+ * LISTBOX_GetItemFromPoint
+ *
+ * Return the item nearest from point (x,y) (in client coordinates).
+ */
+static INT LISTBOX_GetItemFromPoint( WND *wnd, LB_DESCR *descr,
+ INT x, INT y )
+{
+ INT index = descr->top_item;
+
+ if (!descr->nb_items) return -1; /* No items */
+ if (descr->style & LBS_OWNERDRAWVARIABLE)
+ {
+ INT pos = 0;
+ if (y >= 0)
+ {
+ while (index < descr->nb_items)
+ {
+ if ((pos += descr->items[index].height) > y) break;
+ index++;
+ }
+ }
+ else
+ {
+ while (index > 0)
+ {
+ index--;
+ if ((pos -= descr->items[index].height) <= y) break;
+ }
+ }
+ }
+ else if (descr->style & LBS_MULTICOLUMN)
+ {
+ if (y >= descr->item_height * descr->page_size) return -1;
+ if (y >= 0) index += y / descr->item_height;
+ if (x >= 0) index += (x / descr->column_width) * descr->page_size;
+ else index -= (((x + 1) / descr->column_width) - 1) * descr->page_size;
+ }
+ else
+ {
+ index += (y / descr->item_height);
+ }
+ if (index < 0) return 0;
+ if (index >= descr->nb_items) return -1;
+ return index;
+}
+
+
+/***********************************************************************
+ * LISTBOX_PaintItem
+ *
+ * Paint an item.
+ */
+static void LISTBOX_PaintItem( WND *wnd, LB_DESCR *descr, HDC hdc,
+ const RECT *rect, INT index, UINT action )
+{
+ LB_ITEMDATA *item = NULL;
+ if (index < descr->nb_items) item = &descr->items[index];
+
+ if (IS_OWNERDRAW(descr))
+ {
+ DRAWITEMSTRUCT dis;
+ UINT id = (descr->lphc) ? ID_CB_LISTBOX : wnd->wIDmenu;
+
+ dis.CtlType = ODT_LISTBOX;
+ dis.CtlID = id;
+ dis.hwndItem = wnd->hwndSelf;
+ dis.itemAction = action;
+ dis.hDC = hdc;
+ dis.itemID = index;
+ dis.itemState = 0;
+ if (item && item->selected) dis.itemState |= ODS_SELECTED;
+ if ((descr->focus_item == index) &&
+ (descr->caret_on) &&
+ (GetFocus() == wnd->hwndSelf)) dis.itemState |= ODS_FOCUS;
+ if (wnd->dwStyle & WS_DISABLED) dis.itemState |= ODS_DISABLED;
+ dis.itemData = item ? item->data : 0;
+ dis.rcItem = *rect;
+ DPRINT( "[%04x]: drawitem %d (%s) action=%02x "
+ "state=%02x rect=%d,%d-%d,%d\n",
+ wnd->hwndSelf, index, item ? item->str : "", action,
+ dis.itemState, rect->left, rect->top,
+ rect->right, rect->bottom );
+ SendMessageA(descr->owner, WM_DRAWITEM, id, (LPARAM)&dis);
+ }
+ else
+ {
+ COLORREF oldText = 0, oldBk = 0;
+
+ if (action == ODA_FOCUS)
+ {
+ DrawFocusRect( hdc, rect );
+ return;
+ }
+ if (item && item->selected)
+ {
+ oldBk = SetBkColor( hdc, GetSysColor( COLOR_HIGHLIGHT ) );
+ oldText = SetTextColor( hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
+ }
+
+ DPRINT( "[%04x]: painting %d (%s) action=%02x "
+ "rect=%d,%d-%d,%d\n",
+ wnd->hwndSelf, index, item ? item->str : "", action,
+ rect->left, rect->top, rect->right, rect->bottom );
+ if (!item)
+ ExtTextOutA( hdc, rect->left + 1, rect->top + 1,
+ ETO_OPAQUE | ETO_CLIPPED, rect, NULL, 0, NULL );
+ else if (!(descr->style & LBS_USETABSTOPS))
+ ExtTextOutA( hdc, rect->left + 1, rect->top + 1,
+ ETO_OPAQUE | ETO_CLIPPED, rect, item->str,
+ strlen(item->str), NULL );
+ else
+ {
+ /* Output empty string to paint background in the full width. */
+ ExtTextOutA( hdc, rect->left + 1, rect->top + 1,
+ ETO_OPAQUE | ETO_CLIPPED, rect, NULL, 0, NULL );
+ TabbedTextOutA( hdc, rect->left + 1 , rect->top + 1,
+ item->str, strlen(item->str),
+ descr->nb_tabs, descr->tabs, 0);
+ }
+ if (item && item->selected)
+ {
+ SetBkColor( hdc, oldBk );
+ SetTextColor( hdc, oldText );
+ }
+ if ((descr->focus_item == index) &&
+ (descr->caret_on) &&
+ (GetFocus() == wnd->hwndSelf)) DrawFocusRect( hdc, rect );
+ }
+}
+
+
+/***********************************************************************
+ * LISTBOX_SetRedraw
+ *
+ * Change the redraw flag.
+ */
+static void LISTBOX_SetRedraw( WND *wnd, LB_DESCR *descr, BOOL on )
+{
+ if (on)
+ {
+ if (!(descr->style & LBS_NOREDRAW)) return;
+ descr->style &= ~LBS_NOREDRAW;
+ LISTBOX_UpdateScroll( wnd, descr );
+ }
+ else descr->style |= LBS_NOREDRAW;
+}
+
+
+/***********************************************************************
+ * LISTBOX_RepaintItem
+ *
+ * Repaint a single item synchronously.
+ */
+static void LISTBOX_RepaintItem( WND *wnd, LB_DESCR *descr, INT index,
+ UINT action )
+{
+ HDC hdc;
+ RECT rect;
+ HFONT oldFont = 0;
+ HBRUSH hbrush, oldBrush = 0;
+
+ if (descr->style & LBS_NOREDRAW) return;
+ if (LISTBOX_GetItemRect( wnd, descr, index, &rect ) != 1) return;
+ if (!(hdc = GetDCEx( wnd->hwndSelf, 0, DCX_CACHE ))) return;
+ if (descr->font) oldFont = SelectObject( hdc, descr->font );
+ hbrush = (HBRUSH)SendMessageA( descr->owner, WM_CTLCOLORLISTBOX,
+ (WPARAM)hdc, (LPARAM)wnd->hwndSelf );
+ if (hbrush) oldBrush = SelectObject( hdc, hbrush );
+ if (wnd->dwStyle & WS_DISABLED)
+ SetTextColor( hdc, GetSysColor( COLOR_GRAYTEXT ) );
+ SetWindowOrgEx( hdc, descr->horz_pos, 0, NULL );
+ LISTBOX_PaintItem( wnd, descr, hdc, &rect, index, action );
+ if (oldFont) SelectObject( hdc, oldFont );
+ if (oldBrush) SelectObject( hdc, oldBrush );
+ ReleaseDC( wnd->hwndSelf, hdc );
+}
+
+
+/***********************************************************************
+ * LISTBOX_InitStorage
+ */
+static LRESULT LISTBOX_InitStorage( WND *wnd, LB_DESCR *descr, INT nb_items,
+ DWORD bytes )
+{
+ LB_ITEMDATA *item;
+
+ nb_items += LB_ARRAY_GRANULARITY - 1;
+ nb_items -= (nb_items % LB_ARRAY_GRANULARITY);
+ if (descr->items)
+ nb_items += HeapSize( descr->heap, 0, descr->items ) / sizeof(*item);
+ if (!(item = HeapReAlloc( descr->heap, 0, descr->items,
+ nb_items * sizeof(LB_ITEMDATA) )))
+ {
+ SEND_NOTIFICATION( wnd, descr, LBN_ERRSPACE );
+ return LB_ERRSPACE;
+ }
+ descr->items = item;
+ return LB_OKAY;
+}
+
+
+/***********************************************************************
+ * LISTBOX_SetTabStops
+ */
+static BOOL LISTBOX_SetTabStops( WND *wnd, LB_DESCR *descr, INT count,
+ LPINT tabs, BOOL short_ints )
+{
+ if (!(descr->style & LBS_USETABSTOPS)) return TRUE;
+ if (descr->tabs) HeapFree( descr->heap, 0, descr->tabs );
+ if (!(descr->nb_tabs = count))
+ {
+ descr->tabs = NULL;
+ return TRUE;
+ }
+ /* FIXME: count = 1 */
+ if (!(descr->tabs = (INT *)HeapAlloc( descr->heap, 0,
+ descr->nb_tabs * sizeof(INT) )))
+ return FALSE;
+ if (short_ints)
+ {
+ INT i;
+ INT * p = (INT *)tabs;
+// dbg_decl_str(listbox, 256);
+
+ for (i = 0; i < descr->nb_tabs; i++) {
+ descr->tabs[i] = *p++<<1; /* FIXME */
+ // if(TRACE_ON(listbox))
+ // dsprintf(listbox, "%hd ", descr->tabs[i]);
+ }
+ DPRINT( "[%04x]: settabstops %s\n",
+ wnd->hwndSelf, dbg_str(listbox));
+ }
+ else memcpy( descr->tabs, tabs, descr->nb_tabs * sizeof(INT) );
+ /* FIXME: repaint the window? */
+ return TRUE;
+}
+
+
+/***********************************************************************
+ * LISTBOX_GetText
+ */
+static LRESULT LISTBOX_GetText( WND *wnd, LB_DESCR *descr, INT index,
+ LPSTR buffer )
+{
+ if ((index < 0) || (index >= descr->nb_items)) return LB_ERR;
+ if (HAS_STRINGS(descr))
+ {
+ if (!buffer)
+ return strlen(descr->items[index].str);
+ lstrcpyA( buffer, descr->items[index].str );
+ return strlen(buffer);
+ } else {
+ if (buffer)
+ *((LPDWORD)buffer)=*(LPDWORD)(&descr->items[index].data);
+ return sizeof(DWORD);
+ }
+}
+
+
+/***********************************************************************
+ * LISTBOX_FindStringPos
+ *
+ * Find the nearest string located before a given string in sort order.
+ * If 'exact' is TRUE, return an error if we don't get an exact match.
+ */
+static INT LISTBOX_FindStringPos( WND *wnd, LB_DESCR *descr, LPCSTR str,
+ BOOL exact )
+{
+ INT index, min, max, res = -1;
+
+ if (!(descr->style & LBS_SORT)) return -1; /* Add it at the end */
+ min = 0;
+ max = descr->nb_items;
+ while (min != max)
+ {
+ index = (min + max) / 2;
+ if (HAS_STRINGS(descr))
+ res = lstrcmpiA( descr->items[index].str, str );
+ else
+ {
+ COMPAREITEMSTRUCT cis;
+ UINT id = (descr->lphc) ? ID_CB_LISTBOX : wnd->wIDmenu;
+
+ cis.CtlType = ODT_LISTBOX;
+ cis.CtlID = id;
+ cis.hwndItem = wnd->hwndSelf;
+ cis.itemID1 = index;
+ cis.itemData1 = descr->items[index].data;
+ cis.itemID2 = -1;
+ cis.itemData2 = (DWORD)str;
+ //cis.dwLocaleId = descr->locale;
+ res = SendMessageA( descr->owner, WM_COMPAREITEM,
+ id, (LPARAM)&cis );
+ }
+ if (!res) return index;
+ if (res > 0) max = index;
+ else min = index + 1;
+ }
+ return exact ? -1 : max;
+}
+
+
+/***********************************************************************
+ * LISTBOX_FindFileStrPos
+ *
+ * Find the nearest string located before a given string in directory
+ * sort order (i.e. first files, then directories, then drives).
+ */
+static INT LISTBOX_FindFileStrPos( WND *wnd, LB_DESCR *descr, LPCSTR str )
+{
+ INT min, max, res = -1;
+
+ if (!HAS_STRINGS(descr))
+ return LISTBOX_FindStringPos( wnd, descr, str, FALSE );
+ min = 0;
+ max = descr->nb_items;
+ while (min != max)
+ {
+ INT index = (min + max) / 2;
+ const char *p = descr->items[index].str;
+ if (*p == '[') /* drive or directory */
+ {
+ if (*str != '[') res = -1;
+ else if (p[1] == '-') /* drive */
+ {
+ if (str[1] == '-') res = str[2] - p[2];
+ else res = -1;
+ }
+ else /* directory */
+ {
+ if (str[1] == '-') res = 1;
+ else res = lstrcmpiA( str, p );
+ }
+ }
+ else /* filename */
+ {
+ if (*str == '[') res = 1;
+ else res = lstrcmpiA( str, p );
+ }
+ if (!res) return index;
+ if (res < 0) max = index;
+ else min = index + 1;
+ }
+ return max;
+}
+
+
+/***********************************************************************
+ * LISTBOX_FindString
+ *
+ * Find the item beginning with a given string.
+ */
+static INT LISTBOX_FindString( WND *wnd, LB_DESCR *descr, INT start,
+ LPCSTR str, BOOL exact )
+{
+ INT i;
+ LB_ITEMDATA *item;
+
+ if (start >= descr->nb_items) start = -1;
+ item = descr->items + start + 1;
+ if (HAS_STRINGS(descr))
+ {
+ if (!str) return LB_ERR;
+ if (exact)
+ {
+ for (i = start + 1; i < descr->nb_items; i++, item++)
+ if (!lstrcmpiA( str, item->str )) return i;
+ for (i = 0, item = descr->items; i <= start; i++, item++)
+ if (!lstrcmpiA( str, item->str )) return i;
+ }
+ else
+ {
+ /* Special case for drives and directories: ignore prefix */
+#define CHECK_DRIVE(item) \
+ if ((item)->str[0] == '[') \
+ { \
+ if (!lstrcmpiA( str, (item)->str+1 )) return i; \
+ if (((item)->str[1] == '-') && !lstrcmpiA(str,(item)->str+2)) \
+ return i; \
+ }
+
+ INT len = lstrlenA(str);
+ for (i = start + 1; i < descr->nb_items; i++, item++)
+ {
+ if (!lstrcmpiA( str, item->str )) return i;
+ CHECK_DRIVE(item);
+ }
+ for (i = 0, item = descr->items; i <= start; i++, item++)
+ {
+ if (!lstrcmpiA( str, item->str )) return i;
+ CHECK_DRIVE(item);
+ }
+#undef CHECK_DRIVE
+ }
+ }
+ else
+ {
+ if (exact && (descr->style & LBS_SORT))
+ /* If sorted, use a WM_COMPAREITEM binary search */
+ return LISTBOX_FindStringPos( wnd, descr, str, TRUE );
+
+ /* Otherwise use a linear search */
+ for (i = start + 1; i < descr->nb_items; i++, item++)
+ if (item->data == (DWORD)str) return i;
+ for (i = 0, item = descr->items; i <= start; i++, item++)
+ if (item->data == (DWORD)str) return i;
+ }
+ return LB_ERR;
+}
+
+
+/***********************************************************************
+ * LISTBOX_GetSelCount
+ */
+static LRESULT LISTBOX_GetSelCount( WND *wnd, LB_DESCR *descr )
+{
+ INT i, count;
+ LB_ITEMDATA *item = descr->items;
+
+ if (!(descr->style & LBS_MULTIPLESEL)) return LB_ERR;
+ for (i = count = 0; i < descr->nb_items; i++, item++)
+ if (item->selected) count++;
+ return count;
+}
+
+
+
+
+/***********************************************************************
+ * LISTBOX_GetSelItems
+ */
+static LRESULT LISTBOX_GetSelItems( WND *wnd, LB_DESCR *descr, INT max,
+ LPINT array )
+{
+ INT i, count;
+ LB_ITEMDATA *item = descr->items;
+
+ if (!(descr->style & LBS_MULTIPLESEL)) return LB_ERR;
+ for (i = count = 0; (i < descr->nb_items) && (count < max); i++, item++)
+ if (item->selected) array[count++] = i;
+ return count;
+}
+
+
+/***********************************************************************
+ * LISTBOX_Paint
+ */
+static LRESULT LISTBOX_Paint( WND *wnd, LB_DESCR *descr, HDC hdc )
+{
+ INT i, col_pos = descr->page_size - 1;
+ RECT rect;
+ HFONT oldFont = 0;
+ HBRUSH hbrush, oldBrush = 0;
+
+ SetRect( &rect, 0, 0, descr->width, descr->height );
+ if (descr->style & LBS_NOREDRAW) return 0;
+ if (descr->style & LBS_MULTICOLUMN)
+ rect.right = rect.left + descr->column_width;
+ else if (descr->horz_pos)
+ {
+ SetWindowOrgEx( hdc, descr->horz_pos, 0, NULL );
+ rect.right += descr->horz_pos;
+ }
+
+ if (descr->font) oldFont = SelectObject( hdc, descr->font );
+ hbrush = SendMessageA( descr->owner, WM_CTLCOLORLISTBOX,
+ (WPARAM)hdc, (LPARAM)wnd->hwndSelf );
+ if (hbrush) oldBrush = SelectObject( hdc, hbrush );
+ if (wnd->dwStyle & WS_DISABLED)
+ SetTextColor( hdc, GetSysColor( COLOR_GRAYTEXT ) );
+
+ if (!descr->nb_items && (descr->focus_item != -1) && descr->caret_on &&
+ (GetFocus() == wnd->hwndSelf))
+ {
+ /* Special case for empty listbox: paint focus rect */
+ rect.bottom = rect.top + descr->item_height;
+ LISTBOX_PaintItem( wnd, descr, hdc, &rect, descr->focus_item,
+ ODA_FOCUS );
+ rect.top = rect.bottom;
+ }
+
+ for (i = descr->top_item; i < descr->nb_items; i++)
+ {
+ if (!(descr->style & LBS_OWNERDRAWVARIABLE))
+ rect.bottom = rect.top + descr->item_height;
+ else
+ rect.bottom = rect.top + descr->items[i].height;
+
+ LISTBOX_PaintItem( wnd, descr, hdc, &rect, i, ODA_DRAWENTIRE );
+ rect.top = rect.bottom;
+
+ if ((descr->style & LBS_MULTICOLUMN) && !col_pos)
+ {
+ if (!IS_OWNERDRAW(descr))
+ {
+ /* Clear the bottom of the column */
+ SetBkColor( hdc, GetSysColor( COLOR_WINDOW ) );
+ if (rect.top < descr->height)
+ {
+ rect.bottom = descr->height;
+ ExtTextOutA( hdc, 0, 0, ETO_OPAQUE | ETO_CLIPPED,
+ &rect, NULL, 0, NULL );
+ }
+ }
+
+ /* Go to the next column */
+ rect.left += descr->column_width;
+ rect.right += descr->column_width;
+ rect.top = 0;
+ col_pos = descr->page_size - 1;
+ }
+ else
+ {
+ col_pos--;
+ if (rect.top >= descr->height) break;
+ }
+ }
+
+ if (!IS_OWNERDRAW(descr))
+ {
+ /* Clear the remainder of the client area */
+ SetBkColor( hdc, GetSysColor( COLOR_WINDOW ) );
+ if (rect.top < descr->height)
+ {
+ rect.bottom = descr->height;
+ ExtTextOutA( hdc, 0, 0, ETO_OPAQUE | ETO_CLIPPED,
+ &rect, NULL, 0, NULL );
+ }
+ if (rect.right < descr->width)
+ {
+ rect.left = rect.right;
+ rect.right = descr->width;
+ rect.top = 0;
+ rect.bottom = descr->height;
+ ExtTextOutA( hdc, 0, 0, ETO_OPAQUE | ETO_CLIPPED,
+ &rect, NULL, 0, NULL );
+ }
+ }
+ if (oldFont) SelectObject( hdc, oldFont );
+ if (oldBrush) SelectObject( hdc, oldBrush );
+ return 0;
+}
+
+
+/***********************************************************************
+ * LISTBOX_InvalidateItems
+ *
+ * Invalidate all items from a given item. If the specified item is not
+ * visible, nothing happens.
+ */
+static void LISTBOX_InvalidateItems( WND *wnd, LB_DESCR *descr, INT index )
+{
+ RECT rect;
+
+ if (LISTBOX_GetItemRect( wnd, descr, index, &rect ) == 1)
+ {
+ rect.bottom = descr->height;
+ InvalidateRect( wnd->hwndSelf, &rect, TRUE );
+ if (descr->style & LBS_MULTICOLUMN)
+ {
+ /* Repaint the other columns */
+ rect.left = rect.right;
+ rect.right = descr->width;
+ rect.top = 0;
+ InvalidateRect( wnd->hwndSelf, &rect, TRUE );
+ }
+ }
+}
+
+
+/***********************************************************************
+ * LISTBOX_GetItemHeight
+ */
+static LRESULT LISTBOX_GetItemHeight( WND *wnd, LB_DESCR *descr, INT index )
+{
+ if (descr->style & LBS_OWNERDRAWVARIABLE)
+ {
+ if ((index < 0) || (index >= descr->nb_items)) return LB_ERR;
+ return descr->items[index].height;
+ }
+ else return descr->item_height;
+}
+
+
+/***********************************************************************
+ * LISTBOX_SetItemHeight
+ */
+static LRESULT LISTBOX_SetItemHeight( WND *wnd, LB_DESCR *descr, INT index,
+ UINT height )
+{
+ if (!height) height = 1;
+
+ if (descr->style & LBS_OWNERDRAWVARIABLE)
+ {
+ if ((index < 0) || (index >= descr->nb_items)) return LB_ERR;
+ DPRINT( "[%04x]: item %d height = %d\n",
+ wnd->hwndSelf, index, height );
+ descr->items[index].height = height;
+ LISTBOX_UpdateScroll( wnd, descr );
+ LISTBOX_InvalidateItems( wnd, descr, index );
+ }
+ else if (height != descr->item_height)
+ {
+ DPRINT( "[%04x]: new height = %d\n",
+ wnd->hwndSelf, height );
+ descr->item_height = height;
+ LISTBOX_UpdatePage( wnd, descr );
+ LISTBOX_UpdateScroll( wnd, descr );
+ InvalidateRect( wnd->hwndSelf, 0, TRUE );
+ }
+ return LB_OKAY;
+}
+
+
+/***********************************************************************
+ * LISTBOX_SetHorizontalPos
+ */
+static void LISTBOX_SetHorizontalPos( WND *wnd, LB_DESCR *descr, INT pos )
+{
+ INT diff;
+
+ if (pos > descr->horz_extent - descr->width)
+ pos = descr->horz_extent - descr->width;
+ if (pos < 0) pos = 0;
+ if (!(diff = descr->horz_pos - pos)) return;
+ DPRINT( "[%04x]: new horz pos = %d\n",
+ wnd->hwndSelf, pos );
+ descr->horz_pos = pos;
+ LISTBOX_UpdateScroll( wnd, descr );
+ if (abs(diff) < descr->width)
+ ScrollWindowEx( wnd->hwndSelf, diff, 0, NULL, NULL, 0, NULL,
+ SW_INVALIDATE | SW_ERASE );
+ else
+ InvalidateRect( wnd->hwndSelf, NULL, TRUE );
+}
+
+
+/***********************************************************************
+ * LISTBOX_SetHorizontalExtent
+ */
+static LRESULT LISTBOX_SetHorizontalExtent( WND *wnd, LB_DESCR *descr,
+ UINT extent )
+{
+ if (!descr->horz_extent || (descr->style & LBS_MULTICOLUMN))
+ return LB_OKAY;
+ if (extent <= 0) extent = 1;
+ if (extent == descr->horz_extent) return LB_OKAY;
+ DPRINT( "[%04x]: new horz extent = %d\n",
+ wnd->hwndSelf, extent );
+ descr->horz_extent = extent;
+ if (descr->horz_pos > extent - descr->width)
+ LISTBOX_SetHorizontalPos( wnd, descr, extent - descr->width );
+ else
+ LISTBOX_UpdateScroll( wnd, descr );
+ return LB_OKAY;
+}
+
+
+/***********************************************************************
+ * LISTBOX_SetColumnWidth
+ */
+static LRESULT LISTBOX_SetColumnWidth( WND *wnd, LB_DESCR *descr, UINT width)
+{
+ width += 2; /* For left and right margin */
+ if (width == descr->column_width) return LB_OKAY;
+ DPRINT( "[%04x]: new column width = %d\n",
+ wnd->hwndSelf, width );
+ descr->column_width = width;
+ LISTBOX_UpdatePage( wnd, descr );
+ return LB_OKAY;
+}
+
+
+/***********************************************************************
+ * LISTBOX_SetFont
+ *
+ * Returns the item height.
+ */
+static INT LISTBOX_SetFont( WND *wnd, LB_DESCR *descr, HFONT font )
+{
+ HDC hdc;
+ HFONT oldFont = 0;
+ TEXTMETRIC tm;
+
+ descr->font = font;
+
+ if (!(hdc = GetDCEx( wnd->hwndSelf, 0, DCX_CACHE )))
+ {
+ DPRINT("unable to get DC.\n" );
+ return 16;
+ }
+ if (font) oldFont = SelectObject( hdc, font );
+ GetTextMetricsA( hdc, &tm );
+ if (oldFont) SelectObject( hdc, oldFont );
+ ReleaseDC( wnd->hwndSelf, hdc );
+ if (!IS_OWNERDRAW(descr))
+ LISTBOX_SetItemHeight( wnd, descr, 0, tm.tmHeight );
+ return tm.tmHeight ;
+}
+
+
+/***********************************************************************
+ * LISTBOX_MakeItemVisible
+ *
+ * Make sure that a given item is partially or fully visible.
+ */
+static void LISTBOX_MakeItemVisible( WND *wnd, LB_DESCR *descr, INT index,
+ BOOL fully )
+{
+ INT top;
+
+ if (index <= descr->top_item) top = index;
+ else if (descr->style & LBS_MULTICOLUMN)
+ {
+ INT cols = descr->width;
+ if (!fully) cols += descr->column_width - 1;
+ if (cols >= descr->column_width) cols /= descr->column_width;
+ else cols = 1;
+ if (index < descr->top_item + (descr->page_size * cols)) return;
+ top = index - descr->page_size * (cols - 1);
+ }
+ else if (descr->style & LBS_OWNERDRAWVARIABLE)
+ {
+ INT height = fully ? descr->items[index].height : 1;
+ for (top = index; top > descr->top_item; top--)
+ if ((height += descr->items[top-1].height) > descr->height) break;
+ }
+ else
+ {
+ if (index < descr->top_item + descr->page_size) return;
+ if (!fully && (index == descr->top_item + descr->page_size) &&
+ (descr->height > (descr->page_size * descr->item_height))) return;
+ top = index - descr->page_size + 1;
+ }
+ LISTBOX_SetTopItem( wnd, descr, top, TRUE );
+}
+
+
+/***********************************************************************
+ * LISTBOX_SelectItemRange
+ *
+ * Select a range of items. Should only be used on a MULTIPLESEL listbox.
+ */
+static LRESULT LISTBOX_SelectItemRange( WND *wnd, LB_DESCR *descr, INT first,
+ INT last, BOOL on )
+{
+ INT i;
+
+ /* A few sanity checks */
+
+ if ((last == -1) && (descr->nb_items == 0)) return LB_OKAY;
+ if (!(descr->style & LBS_MULTIPLESEL)) return LB_ERR;
+ if (last == -1) last = descr->nb_items - 1;
+ if ((first < 0) || (first >= descr->nb_items)) return LB_ERR;
+ if ((last < 0) || (last >= descr->nb_items)) return LB_ERR;
+ /* selected_item reflects last selected/unselected item on multiple sel */
+ descr->selected_item = last;
+
+ if (on) /* Turn selection on */
+ {
+ for (i = first; i <= last; i++)
+ {
+ if (descr->items[i].selected) continue;
+ descr->items[i].selected = TRUE;
+ LISTBOX_RepaintItem( wnd, descr, i, ODA_SELECT );
+ }
+ }
+ else /* Turn selection off */
+ {
+ for (i = first; i <= last; i++)
+ {
+ if (!descr->items[i].selected) continue;
+ descr->items[i].selected = FALSE;
+ LISTBOX_RepaintItem( wnd, descr, i, ODA_SELECT );
+ }
+ }
+ return LB_OKAY;
+}
+
+
+/***********************************************************************
+ * LISTBOX_SetCaretIndex
+ *
+ * NOTES
+ * index must be between 0 and descr->nb_items-1, or LB_ERR is returned.
+ *
+ */
+static LRESULT LISTBOX_SetCaretIndex( WND *wnd, LB_DESCR *descr, INT index,
+ BOOL fully_visible )
+{
+ INT oldfocus = descr->focus_item;
+
+ if ((index < 0) || (index >= descr->nb_items)) return LB_ERR;
+ if (index == oldfocus) return LB_OKAY;
+ descr->focus_item = index;
+ if ((oldfocus != -1) && descr->caret_on && (GetFocus() == wnd->hwndSelf))
+ LISTBOX_RepaintItem( wnd, descr, oldfocus, ODA_FOCUS );
+
+ LISTBOX_MakeItemVisible( wnd, descr, index, fully_visible );
+ if (descr->caret_on && (GetFocus() == wnd->hwndSelf))
+ LISTBOX_RepaintItem( wnd, descr, index, ODA_FOCUS );
+
+ return LB_OKAY;
+}
+
+
+/***********************************************************************
+ * LISTBOX_SetSelection
+ */
+static LRESULT LISTBOX_SetSelection( WND *wnd, LB_DESCR *descr, INT index,
+ BOOL on, BOOL send_notify )
+{
+ if ((index < -1) || (index >= descr->nb_items)) return LB_ERR;
+ if (descr->style & LBS_MULTIPLESEL)
+ {
+ if (index == -1) /* Select all items */
+ return LISTBOX_SelectItemRange( wnd, descr, 0, -1, on );
+ else /* Only one item */
+ return LISTBOX_SelectItemRange( wnd, descr, index, index, on );
+ }
+ else
+ {
+ INT oldsel = descr->selected_item;
+ if (index == oldsel) return LB_OKAY;
+ if (oldsel != -1) descr->items[oldsel].selected = FALSE;
+ if (index != -1) descr->items[index].selected = TRUE;
+ descr->selected_item = index;
+ if (oldsel != -1) LISTBOX_RepaintItem( wnd, descr, oldsel, ODA_SELECT);
+ if (index != -1) LISTBOX_RepaintItem( wnd, descr, index, ODA_SELECT );
+ if (send_notify) SEND_NOTIFICATION( wnd, descr,
+ (index != -1) ? LBN_SELCHANGE : LBN_SELCANCEL );
+ else
+ if( descr->lphc ) /* set selection change flag for parent combo */
+ descr->lphc->wState |= CBF_SELCHANGE;
+ }
+ return LB_OKAY;
+}
+
+
+/***********************************************************************
+ * LISTBOX_MoveCaret
+ *
+ * Change the caret position and extend the selection to the new caret.
+ */
+static void LISTBOX_MoveCaret( WND *wnd, LB_DESCR *descr, INT index,
+ BOOL fully_visible )
+{
+ LISTBOX_SetCaretIndex( wnd, descr, index, fully_visible );
+ if (descr->style & LBS_EXTENDEDSEL)
+ {
+ if (descr->anchor_item != -1)
+ {
+ INT first = MIN( descr->focus_item, descr->anchor_item );
+ INT last = MAX( descr->focus_item, descr->anchor_item );
+ if (first > 0)
+ LISTBOX_SelectItemRange( wnd, descr, 0, first - 1, FALSE );
+ LISTBOX_SelectItemRange( wnd, descr, last + 1, -1, FALSE );
+ LISTBOX_SelectItemRange( wnd, descr, first, last, TRUE );
+ }
+ }
+ else if (!(descr->style & LBS_MULTIPLESEL) && (descr->selected_item != -1))
+ {
+ /* Set selection to new caret item */
+ LISTBOX_SetSelection( wnd, descr, index, TRUE, FALSE );
+ }
+}
+
+
+/***********************************************************************
+ * LISTBOX_InsertItem
+ */
+static LRESULT LISTBOX_InsertItem( WND *wnd, LB_DESCR *descr, INT index,
+ LPSTR str, DWORD data )
+{
+ LB_ITEMDATA *item;
+ INT max_items;
+
+ if (index == -1) index = descr->nb_items;
+ else if ((index < 0) || (index > descr->nb_items)) return LB_ERR;
+ if (!descr->items) max_items = 0;
+ else max_items = HeapSize( descr->heap, 0, descr->items ) / sizeof(*item);
+ if (descr->nb_items == max_items)
+ {
+ /* We need to grow the array */
+ max_items += LB_ARRAY_GRANULARITY;
+ if (!(item = HeapReAlloc( descr->heap, 0, descr->items,
+ max_items * sizeof(LB_ITEMDATA) )))
+ {
+ SEND_NOTIFICATION( wnd, descr, LBN_ERRSPACE );
+ return LB_ERRSPACE;
+ }
+ descr->items = item;
+ }
+
+ /* Insert the item structure */
+
+ item = &descr->items[index];
+ if (index < descr->nb_items)
+ MoveMemory( item + 1, item, (descr->nb_items - index) * sizeof(LB_ITEMDATA) );
+ item->str = str;
+ item->data = data;
+ item->height = 0;
+ item->selected = FALSE;
+ descr->nb_items++;
+
+ /* Get item height */
+
+ if (descr->style & LBS_OWNERDRAWVARIABLE)
+ {
+ MEASUREITEMSTRUCT mis;
+ UINT id = (descr->lphc) ? ID_CB_LISTBOX : wnd->wIDmenu;
+
+ mis.CtlType = ODT_LISTBOX;
+ mis.CtlID = id;
+ mis.itemID = index;
+ mis.itemData = descr->items[index].data;
+ mis.itemHeight = descr->item_height;
+ SendMessageA( descr->owner, WM_MEASUREITEM, id, (LPARAM)&mis );
+ item->height = mis.itemHeight ? mis.itemHeight : 1;
+ DPRINT( "[%04x]: measure item %d (%s) = %d\n",
+ wnd->hwndSelf, index, str ? str : "", item->height );
+ }
+
+ /* Repaint the items */
+
+ LISTBOX_UpdateScroll( wnd, descr );
+ LISTBOX_InvalidateItems( wnd, descr, index );
+
+ /* Move selection and focused item */
+
+ if (index <= descr->selected_item) descr->selected_item++;
+ if (index <= descr->focus_item)
+ {
+ descr->focus_item++;
+ LISTBOX_MoveCaret( wnd, descr, descr->focus_item, FALSE );
+ }
+
+ /* If listbox was empty, set focus to the first item */
+
+ if (descr->nb_items == 1) LISTBOX_SetCaretIndex( wnd, descr, 0, FALSE );
+ return LB_OKAY;
+}
+
+
+/***********************************************************************
+ * LISTBOX_InsertString
+ */
+static LRESULT LISTBOX_InsertString( WND *wnd, LB_DESCR *descr, INT index,
+ LPCSTR str )
+{
+ LPSTR new_str = NULL;
+ DWORD data = 0;
+ LRESULT ret;
+
+ if (HAS_STRINGS(descr))
+ {
+ if (!(new_str = HEAP_strdupA( descr->heap, 0, str )))
+ {
+ SEND_NOTIFICATION( wnd, descr, LBN_ERRSPACE );
+ return LB_ERRSPACE;
+ }
+ }
+ else data = (DWORD)str;
+
+ if (index == -1) index = descr->nb_items;
+ if ((ret = LISTBOX_InsertItem( wnd, descr, index, new_str, data )) != 0)
+ {
+ if (new_str) HeapFree( descr->heap, 0, new_str );
+ return ret;
+ }
+
+ DPRINT( "[%04x]: added item %d '%s'\n",
+ wnd->hwndSelf, index, HAS_STRINGS(descr) ? new_str : "" );
+ return index;
+}
+
+
+/***********************************************************************
+ * LISTBOX_DeleteItem
+ *
+ * Delete the content of an item. 'index' must be a valid index.
+ */
+static void LISTBOX_DeleteItem( WND *wnd, LB_DESCR *descr, INT index )
+{
+ /* Note: Win 3.1 only sends DELETEITEM on owner-draw items,
+ * while Win95 sends it for all items with user data.
+ * It's probably better to send it too often than not
+ * often enough, so this is what we do here.
+ */
+ if (IS_OWNERDRAW(descr) || descr->items[index].data)
+ {
+ DELETEITEMSTRUCT dis;
+ UINT id = (descr->lphc) ? ID_CB_LISTBOX : wnd->wIDmenu;
+
+ dis.CtlType = ODT_LISTBOX;
+ dis.CtlID = id;
+ dis.itemID = index;
+ dis.hwndItem = wnd->hwndSelf;
+ dis.itemData = descr->items[index].data;
+ SendMessageA( descr->owner, WM_DELETEITEM, id, (LPARAM)&dis );
+ }
+ if (HAS_STRINGS(descr) && descr->items[index].str)
+ HeapFree( descr->heap, 0, descr->items[index].str );
+}
+
+
+/***********************************************************************
+ * LISTBOX_RemoveItem
+ *
+ * Remove an item from the listbox and delete its content.
+ */
+static LRESULT LISTBOX_RemoveItem( WND *wnd, LB_DESCR *descr, INT index )
+{
+ LB_ITEMDATA *item;
+ INT max_items;
+
+ if (index == -1) index = descr->nb_items - 1;
+ else if ((index < 0) || (index >= descr->nb_items)) return LB_ERR;
+ LISTBOX_DeleteItem( wnd, descr, index );
+
+ /* Remove the item */
+
+ item = &descr->items[index];
+ if (index < descr->nb_items-1)
+ MoveMemory( item, item + 1,
+ (descr->nb_items - index - 1) * sizeof(LB_ITEMDATA) );
+ descr->nb_items--;
+ if (descr->anchor_item == descr->nb_items) descr->anchor_item--;
+
+ /* Shrink the item array if possible */
+
+ max_items = HeapSize( descr->heap, 0, descr->items ) / sizeof(LB_ITEMDATA);
+ if (descr->nb_items < max_items - 2*LB_ARRAY_GRANULARITY)
+ {
+ max_items -= LB_ARRAY_GRANULARITY;
+ item = HeapReAlloc( descr->heap, 0, descr->items,
+ max_items * sizeof(LB_ITEMDATA) );
+ if (item) descr->items = item;
+ }
+
+ /* Repaint the items */
+
+ LISTBOX_UpdateScroll( wnd, descr );
+ LISTBOX_InvalidateItems( wnd, descr, index );
+
+ /* Move selection and focused item */
+
+ if (index <= descr->selected_item) descr->selected_item--;
+ if (index <= descr->focus_item)
+ {
+ descr->focus_item--;
+ LISTBOX_MoveCaret( wnd, descr, descr->focus_item, FALSE );
+ }
+ return LB_OKAY;
+}
+
+
+/***********************************************************************
+ * LISTBOX_ResetContent
+ */
+static void LISTBOX_ResetContent( WND *wnd, LB_DESCR *descr )
+{
+ INT i;
+
+ for (i = 0; i < descr->nb_items; i++) LISTBOX_DeleteItem( wnd, descr, i );
+ if (descr->items) HeapFree( descr->heap, 0, descr->items );
+ descr->nb_items = 0;
+ descr->top_item = 0;
+ descr->selected_item = -1;
+ descr->focus_item = 0;
+ descr->anchor_item = -1;
+ descr->items = NULL;
+ LISTBOX_UpdateScroll( wnd, descr );
+ InvalidateRect( wnd->hwndSelf, NULL, TRUE );
+}
+
+
+/***********************************************************************
+ * LISTBOX_SetCount
+ */
+static LRESULT LISTBOX_SetCount( WND *wnd, LB_DESCR *descr, INT count )
+{
+ LRESULT ret;
+
+ if (HAS_STRINGS(descr)) return LB_ERR;
+ /* FIXME: this is far from optimal... */
+ if (count > descr->nb_items)
+ {
+ while (count > descr->nb_items)
+ if ((ret = LISTBOX_InsertString( wnd, descr, -1, 0 )) < 0)
+ return ret;
+ }
+ else if (count < descr->nb_items)
+ {
+ while (count < descr->nb_items)
+ if ((ret = LISTBOX_RemoveItem( wnd, descr, -1 )) < 0)
+ return ret;
+ }
+ return LB_OKAY;
+}
+
+
+/***********************************************************************
+ * LISTBOX_Directory
+ */
+static LRESULT LISTBOX_Directory( WND *wnd, LB_DESCR *descr, UINT attrib,
+ LPCSTR filespec, BOOL long_names )
+{
+ HANDLE handle;
+ LRESULT ret = LB_OKAY;
+ WIN32_FIND_DATA entry;
+ int pos;
+
+ if ((handle = FindFirstFileA(filespec,&entry)) == INVALID_HANDLE_VALUE)
+ {
+ if (GetLastError() != ERROR_NO_MORE_FILES) return LB_ERR;
+ }
+ else
+ {
+ do
+ {
+ char buffer[270];
+ if (entry.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ {
+ if (!(attrib & DDL_DIRECTORY) ||
+ !strcmp( entry.cAlternateFileName, "." )) continue;
+ if (long_names) sprintf( buffer, "[%s]", entry.cFileName );
+ else sprintf( buffer, "[%s]", entry.cAlternateFileName );
+ }
+ else /* not a directory */
+ {
+#define ATTRIBS (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN | \
+ FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_ARCHIVE)
+
+ if ((attrib & DDL_EXCLUSIVE) &&
+ ((attrib & ATTRIBS) != (entry.dwFileAttributes & ATTRIBS)))
+ continue;
+#undef ATTRIBS
+ if (long_names) strcpy( buffer, entry.cFileName );
+ else strcpy( buffer, entry.cAlternateFileName );
+ }
+ if (!long_names) CharLowerA( buffer );
+ pos = LISTBOX_FindFileStrPos( wnd, descr, buffer );
+ if ((ret = LISTBOX_InsertString( wnd, descr, pos, buffer )) < 0)
+ break;
+ } while (FindNextFileA( handle, &entry ));
+ FindClose( handle );
+ }
+
+ if ((ret >= 0) && (attrib & DDL_DRIVES))
+ {
+ char buffer[] = "[-a-]";
+ int drive;
+ for (drive = 0; drive < MAX_DOS_DRIVES; drive++, buffer[2]++)
+ {
+ //if (!DRIVE_IsValid(drive)) continue;
+ if ((ret = LISTBOX_InsertString( wnd, descr, -1, buffer )) < 0)
+ break;
+ }
+ }
+ return ret;
+}
+
+
+/***********************************************************************
+ * LISTBOX_HandleVScroll
+ */
+static LRESULT LISTBOX_HandleVScroll( WND *wnd, LB_DESCR *descr,
+ WPARAM wParam, LPARAM lParam )
+{
+ SCROLLINFO info;
+
+ if (descr->style & LBS_MULTICOLUMN) return 0;
+ switch(LOWORD(wParam))
+ {
+ case SB_LINEUP:
+ LISTBOX_SetTopItem( wnd, descr, descr->top_item - 1, TRUE );
+ break;
+ case SB_LINEDOWN:
+ LISTBOX_SetTopItem( wnd, descr, descr->top_item + 1, TRUE );
+ break;
+ case SB_PAGEUP:
+ LISTBOX_SetTopItem( wnd, descr, descr->top_item -
+ LISTBOX_GetCurrentPageSize( wnd, descr ), TRUE );
+ break;
+ case SB_PAGEDOWN:
+ LISTBOX_SetTopItem( wnd, descr, descr->top_item +
+ LISTBOX_GetCurrentPageSize( wnd, descr ), TRUE );
+ break;
+ case SB_THUMBPOSITION:
+ LISTBOX_SetTopItem( wnd, descr, HIWORD(wParam), TRUE );
+ break;
+ case SB_THUMBTRACK:
+ info.cbSize = sizeof(info);
+ info.fMask = SIF_TRACKPOS;
+ GetScrollInfo( wnd->hwndSelf, SB_VERT, &info );
+ LISTBOX_SetTopItem( wnd, descr, info.nTrackPos, TRUE );
+ break;
+ case SB_TOP:
+ LISTBOX_SetTopItem( wnd, descr, 0, TRUE );
+ break;
+ case SB_BOTTOM:
+ LISTBOX_SetTopItem( wnd, descr, descr->nb_items, TRUE );
+ break;
+ }
+ return 0;
+}
+
+
+/***********************************************************************
+ * LISTBOX_HandleHScroll
+ */
+static LRESULT LISTBOX_HandleHScroll( WND *wnd, LB_DESCR *descr,
+ WPARAM wParam, LPARAM lParam )
+{
+ SCROLLINFO info;
+ INT page;
+
+ if (descr->style & LBS_MULTICOLUMN)
+ {
+ switch(LOWORD(wParam))
+ {
+ case SB_LINELEFT:
+ LISTBOX_SetTopItem( wnd, descr, descr->top_item-descr->page_size,
+ TRUE );
+ break;
+ case SB_LINERIGHT:
+ LISTBOX_SetTopItem( wnd, descr, descr->top_item+descr->page_size,
+ TRUE );
+ break;
+ case SB_PAGELEFT:
+ page = descr->width / descr->column_width;
+ if (page < 1) page = 1;
+ LISTBOX_SetTopItem( wnd, descr,
+ descr->top_item - page * descr->page_size, TRUE );
+ break;
+ case SB_PAGERIGHT:
+ page = descr->width / descr->column_width;
+ if (page < 1) page = 1;
+ LISTBOX_SetTopItem( wnd, descr,
+ descr->top_item + page * descr->page_size, TRUE );
+ break;
+ case SB_THUMBPOSITION:
+ LISTBOX_SetTopItem( wnd, descr, HIWORD(wParam)*descr->page_size,
+ TRUE );
+ break;
+ case SB_THUMBTRACK:
+ info.cbSize = sizeof(info);
+ info.fMask = SIF_TRACKPOS;
+ GetScrollInfo( wnd->hwndSelf, SB_VERT, &info );
+ LISTBOX_SetTopItem( wnd, descr, info.nTrackPos*descr->page_size,
+ TRUE );
+ break;
+ case SB_LEFT:
+ LISTBOX_SetTopItem( wnd, descr, 0, TRUE );
+ break;
+ case SB_RIGHT:
+ LISTBOX_SetTopItem( wnd, descr, descr->nb_items, TRUE );
+ break;
+ }
+ }
+ else if (descr->horz_extent)
+ {
+ switch(LOWORD(wParam))
+ {
+ case SB_LINELEFT:
+ LISTBOX_SetHorizontalPos( wnd, descr, descr->horz_pos - 1 );
+ break;
+ case SB_LINERIGHT:
+ LISTBOX_SetHorizontalPos( wnd, descr, descr->horz_pos + 1 );
+ break;
+ case SB_PAGELEFT:
+ LISTBOX_SetHorizontalPos( wnd, descr,
+ descr->horz_pos - descr->width );
+ break;
+ case SB_PAGERIGHT:
+ LISTBOX_SetHorizontalPos( wnd, descr,
+ descr->horz_pos + descr->width );
+ break;
+ case SB_THUMBPOSITION:
+ LISTBOX_SetHorizontalPos( wnd, descr, HIWORD(wParam) );
+ break;
+ case SB_THUMBTRACK:
+ info.cbSize = sizeof(info);
+ info.fMask = SIF_TRACKPOS;
+ GetScrollInfo( wnd->hwndSelf, SB_HORZ, &info );
+ LISTBOX_SetHorizontalPos( wnd, descr, info.nTrackPos );
+ break;
+ case SB_LEFT:
+ LISTBOX_SetHorizontalPos( wnd, descr, 0 );
+ break;
+ case SB_RIGHT:
+ LISTBOX_SetHorizontalPos( wnd, descr,
+ descr->horz_extent - descr->width );
+ break;
+ }
+ }
+ return 0;
+}
+
+
+/***********************************************************************
+ * LISTBOX_HandleLButtonDown
+ */
+static LRESULT LISTBOX_HandleLButtonDown( WND *wnd, LB_DESCR *descr,
+ WPARAM wParam, INT x, INT y )
+{
+ INT index = LISTBOX_GetItemFromPoint( wnd, descr, x, y );
+ DPRINT( "[%04x]: lbuttondown %d,%d item %d\n",
+ wnd->hwndSelf, x, y, index );
+ if (!descr->caret_on && (GetFocus() == wnd->hwndSelf)) return 0;
+ if (index != -1)
+ {
+ if (descr->style & LBS_EXTENDEDSEL)
+ {
+ if (!(wParam & MK_SHIFT)) descr->anchor_item = index;
+ if (wParam & MK_CONTROL)
+ {
+ LISTBOX_SetCaretIndex( wnd, descr, index, FALSE );
+ LISTBOX_SetSelection( wnd, descr, index,
+ !descr->items[index].selected, FALSE );
+ }
+ else LISTBOX_MoveCaret( wnd, descr, index, FALSE );
+ }
+ else
+ {
+ LISTBOX_MoveCaret( wnd, descr, index, FALSE );
+ LISTBOX_SetSelection( wnd, descr, index,
+ (!(descr->style & LBS_MULTIPLESEL) ||
+ !descr->items[index].selected), FALSE );
+ }
+ }
+
+ if( !descr->lphc ) SetFocus( wnd->hwndSelf );
+ else SetFocus( (descr->lphc->hWndEdit) ? descr->lphc->hWndEdit
+ : descr->lphc->self->hwndSelf ) ;
+
+ SetCapture( wnd->hwndSelf );
+ if (index != -1 && !descr->lphc)
+ {
+ if (descr->style & LBS_NOTIFY )
+ SendMessageA( descr->owner, WM_LBTRACKPOINT, index,
+ MAKELPARAM( x, y ) );
+ if (wnd->dwExStyle & WS_EX_DRAGDETECT)
+ {
+ POINT pt = { x, y };
+ // if (DragDetect( wnd->hwndSelf, pt ))
+ SendMessageA( descr->owner, WM_BEGINDRAG, 0, 0 );
+ }
+ }
+ return 0;
+}
+
+
+/***********************************************************************
+ * LISTBOX_HandleLButtonUp
+ */
+static LRESULT LISTBOX_HandleLButtonUp( WND *wnd, LB_DESCR *descr )
+{
+ if (LISTBOX_Timer != LB_TIMER_NONE)
+ KillTimer( wnd->hwndSelf, LB_TIMER_ID );
+ LISTBOX_Timer = LB_TIMER_NONE;
+ if (GetCapture() == wnd->hwndSelf)
+ {
+ ReleaseCapture();
+ if (descr->style & LBS_NOTIFY)
+ SEND_NOTIFICATION( wnd, descr, LBN_SELCHANGE );
+ }
+ return 0;
+}
+
+
+/***********************************************************************
+ * LISTBOX_HandleTimer
+ *
+ * Handle scrolling upon a timer event.
+ * Return TRUE if scrolling should continue.
+ */
+static LRESULT LISTBOX_HandleTimer( WND *wnd, LB_DESCR *descr,
+ INT index, TIMER_DIRECTION dir )
+{
+ switch(dir)
+ {
+ case LB_TIMER_UP:
+ if (descr->top_item) index = descr->top_item - 1;
+ else index = 0;
+ break;
+ case LB_TIMER_LEFT:
+ if (descr->top_item) index -= descr->page_size;
+ break;
+ case LB_TIMER_DOWN:
+ index = descr->top_item + LISTBOX_GetCurrentPageSize( wnd, descr );
+ if (index == descr->focus_item) index++;
+ if (index >= descr->nb_items) index = descr->nb_items - 1;
+ break;
+ case LB_TIMER_RIGHT:
+ if (index + descr->page_size < descr->nb_items)
+ index += descr->page_size;
+ break;
+ case LB_TIMER_NONE:
+ break;
+ }
+ if (index == descr->focus_item) return FALSE;
+ LISTBOX_MoveCaret( wnd, descr, index, FALSE );
+ return TRUE;
+}
+
+
+/***********************************************************************
+ * LISTBOX_HandleSystemTimer
+ *
+ * WM_SYSTIMER handler.
+ */
+static LRESULT LISTBOX_HandleSystemTimer( WND *wnd, LB_DESCR *descr )
+{
+ if (!LISTBOX_HandleTimer( wnd, descr, descr->focus_item, LISTBOX_Timer ))
+ {
+ KillTimer( wnd->hwndSelf, LB_TIMER_ID );
+ LISTBOX_Timer = LB_TIMER_NONE;
+ }
+ return 0;
+}
+
+
+/***********************************************************************
+ * LISTBOX_HandleMouseMove
+ *
+ * WM_MOUSEMOVE handler.
+ */
+static void LISTBOX_HandleMouseMove( WND *wnd, LB_DESCR *descr,
+ INT x, INT y )
+{
+ INT index;
+ TIMER_DIRECTION dir;
+
+ if (descr->style & LBS_MULTICOLUMN)
+ {
+ if (y < 0) y = 0;
+ else if (y >= descr->item_height * descr->page_size)
+ y = descr->item_height * descr->page_size - 1;
+
+ if (x < 0)
+ {
+ dir = LB_TIMER_LEFT;
+ x = 0;
+ }
+ else if (x >= descr->width)
+ {
+ dir = LB_TIMER_RIGHT;
+ x = descr->width - 1;
+ }
+ else dir = LB_TIMER_NONE; /* inside */
+ }
+ else
+ {
+ if (y < 0) dir = LB_TIMER_UP; /* above */
+ else if (y >= descr->height) dir = LB_TIMER_DOWN; /* below */
+ else dir = LB_TIMER_NONE; /* inside */
+ }
+
+ index = LISTBOX_GetItemFromPoint( wnd, descr, x, y );
+ if (index == -1) index = descr->focus_item;
+ if (!LISTBOX_HandleTimer( wnd, descr, index, dir )) dir = LB_TIMER_NONE;
+
+ /* Start/stop the system timer */
+
+ if (dir != LB_TIMER_NONE)
+ SetTimer( wnd->hwndSelf, LB_TIMER_ID, LB_SCROLL_TIMEOUT, NULL);
+ else if (LISTBOX_Timer != LB_TIMER_NONE)
+ KillTimer( wnd->hwndSelf, LB_TIMER_ID );
+ LISTBOX_Timer = dir;
+}
+
+
+/***********************************************************************
+ * LISTBOX_HandleKeyDown
+ */
+static LRESULT LISTBOX_HandleKeyDown( WND *wnd, LB_DESCR *descr, WPARAM wParam )
+{
+ INT caret = -1;
+ if (descr->style & LBS_WANTKEYBOARDINPUT)
+ {
+ caret = SendMessageA( descr->owner, WM_VKEYTOITEM,
+ MAKEWPARAM(LOWORD(wParam), descr->focus_item),
+ wnd->hwndSelf );
+ if (caret == -2) return 0;
+ }
+ if (caret == -1) switch(wParam)
+ {
+ case VK_LEFT:
+ if (descr->style & LBS_MULTICOLUMN)
+ {
+ if (descr->focus_item >= descr->page_size)
+ caret = descr->focus_item - descr->page_size;
+ break;
+ }
+ /* fall through */
+ case VK_UP:
+ caret = descr->focus_item - 1;
+ if (caret < 0) caret = 0;
+ break;
+ case VK_RIGHT:
+ if (descr->style & LBS_MULTICOLUMN)
+ {
+ if (descr->focus_item + descr->page_size < descr->nb_items)
+ caret = descr->focus_item + descr->page_size;
+ break;
+ }
+ /* fall through */
+ case VK_DOWN:
+ caret = descr->focus_item + 1;
+ if (caret >= descr->nb_items) caret = descr->nb_items - 1;
+ break;
+ case VK_PRIOR:
+ if (descr->style & LBS_MULTICOLUMN)
+ {
+ INT page = descr->width / descr->column_width;
+ if (page < 1) page = 1;
+ caret = descr->focus_item - (page * descr->page_size) + 1;
+ }
+ else caret = descr->focus_item-LISTBOX_GetCurrentPageSize(wnd,descr)+1;
+ if (caret < 0) caret = 0;
+ break;
+ case VK_NEXT:
+ if (descr->style & LBS_MULTICOLUMN)
+ {
+ INT page = descr->width / descr->column_width;
+ if (page < 1) page = 1;
+ caret = descr->focus_item + (page * descr->page_size) - 1;
+ }
+ else caret = descr->focus_item+LISTBOX_GetCurrentPageSize(wnd,descr)-1;
+ if (caret >= descr->nb_items) caret = descr->nb_items - 1;
+ break;
+ case VK_HOME:
+ caret = 0;
+ break;
+ case VK_END:
+ caret = descr->nb_items - 1;
+ break;
+ case VK_SPACE:
+ if (descr->style & LBS_EXTENDEDSEL) caret = descr->focus_item;
+ else if (descr->style & LBS_MULTIPLESEL)
+ {
+ LISTBOX_SetSelection( wnd, descr, descr->focus_item,
+ !descr->items[descr->focus_item].selected,
+ (descr->style & LBS_NOTIFY) != 0 );
+ }
+ else if (descr->selected_item == -1)
+ {
+ LISTBOX_SetSelection( wnd, descr, descr->focus_item, TRUE,
+ (descr->style & LBS_NOTIFY) != 0 );
+ }
+ break;
+ }
+ if (caret >= 0)
+ {
+ if ((descr->style & LBS_EXTENDEDSEL) &&
+ !(GetKeyState( VK_SHIFT ) & 0x8000))
+ descr->anchor_item = caret;
+ LISTBOX_MoveCaret( wnd, descr, caret, TRUE );
+ if (descr->style & LBS_NOTIFY)
+ {
+ if( descr->lphc && CB_GETTYPE(descr->lphc) != CBS_SIMPLE )
+ {
+ /* make sure that combo parent doesn't hide us */
+ descr->lphc->wState |= CBF_NOROLLUP;
+ }
+ SEND_NOTIFICATION( wnd, descr, LBN_SELCHANGE );
+ }
+ }
+ return 0;
+}
+
+
+/***********************************************************************
+ * LISTBOX_HandleChar
+ */
+static LRESULT LISTBOX_HandleChar( WND *wnd, LB_DESCR *descr,
+ WPARAM wParam )
+{
+ INT caret = -1;
+ char str[2] = { wParam & 0xff, '\0' };
+
+ if (descr->style & LBS_WANTKEYBOARDINPUT)
+ {
+ caret = SendMessageA( descr->owner, WM_CHARTOITEM,
+ MAKEWPARAM(LOWORD(wParam), descr->focus_item),
+ wnd->hwndSelf );
+ if (caret == -2) return 0;
+ }
+ if (caret == -1)
+ caret = LISTBOX_FindString( wnd, descr, descr->focus_item, str, FALSE);
+ if (caret != -1)
+ {
+ LISTBOX_MoveCaret( wnd, descr, caret, TRUE );
+ if (descr->style & LBS_NOTIFY)
+ SEND_NOTIFICATION( wnd, descr, LBN_SELCHANGE );
+ }
+ return 0;
+}
+
+
+/***********************************************************************
+ * LISTBOX_Create
+ */
+static BOOL LISTBOX_Create( WND *wnd, LPHEADCOMBO lphc )
+{
+ LB_DESCR *descr;
+ MEASUREITEMSTRUCT mis;
+ RECT rect;
+
+ if (!(descr = HeapAlloc( GetProcessHeap(), 0, sizeof(*descr) )))
+ return FALSE;
+ if (!(descr->heap = HeapCreate( 0, 0x10000, 0 )))
+ {
+ HeapFree( GetProcessHeap(), 0, descr );
+ return FALSE;
+ }
+ GetClientRect( wnd->hwndSelf, &rect );
+ descr->owner = GetParent( wnd->hwndSelf );
+ descr->style = wnd->dwStyle;
+ descr->width = rect.right - rect.left;
+ descr->height = rect.bottom - rect.top;
+ descr->items = NULL;
+ descr->nb_items = 0;
+ descr->top_item = 0;
+ descr->selected_item = -1;
+ descr->focus_item = 0;
+ descr->anchor_item = -1;
+ descr->item_height = 1;
+ descr->page_size = 1;
+ descr->column_width = 150;
+ descr->horz_extent = (wnd->dwStyle & WS_HSCROLL) ? 1 : 0;
+ descr->horz_pos = 0;
+ descr->nb_tabs = 0;
+ descr->tabs = NULL;
+ descr->caret_on = TRUE;
+ descr->font = 0;
+ descr->locale = 0; /* FIXME */
+ descr->lphc = lphc;
+
+ if( lphc )
+ {
+ DPRINT("[%04x]: resetting owner %04x -> %04x\n",
+ wnd->hwndSelf, descr->owner, lphc->self->hwndSelf );
+ descr->owner = lphc->self->hwndSelf;
+ }
+
+ *(LB_DESCR **)wnd->wExtra = descr;
+
+/* if (wnd->dwExStyle & WS_EX_NOPARENTNOTIFY) descr->style &= ~LBS_NOTIFY;
+ */
+ if (descr->style & LBS_EXTENDEDSEL) descr->style |= LBS_MULTIPLESEL;
+ if (descr->style & LBS_MULTICOLUMN) descr->style &= ~LBS_OWNERDRAWVARIABLE;
+ if (descr->style & LBS_OWNERDRAWVARIABLE) descr->style |= LBS_NOINTEGRALHEIGHT;
+ descr->item_height = LISTBOX_SetFont( wnd, descr, 0 );
+
+ if (descr->style & LBS_OWNERDRAWFIXED)
+ {
+ if( descr->lphc && (descr->lphc->dwStyle & CBS_DROPDOWN))
+ {
+ /* WinWord gets VERY unhappy if we send WM_MEASUREITEM from here */
+ descr->item_height = lphc->RectButton.bottom - lphc->RectButton.top - 6;
+ }
+ else
+ {
+ UINT id = (descr->lphc ) ? ID_CB_LISTBOX : wnd->wIDmenu;
+
+ mis.CtlType = ODT_LISTBOX;
+ mis.CtlID = id;
+ mis.itemID = -1;
+ mis.itemWidth = 0;
+ mis.itemData = 0;
+ mis.itemHeight = descr->item_height;
+ SendMessageA( descr->owner, WM_MEASUREITEM, id, (LPARAM)&mis );
+ descr->item_height = mis.itemHeight ? mis.itemHeight : 1;
+ }
+ }
+
+ return TRUE;
+}
+
+
+/***********************************************************************
+ * LISTBOX_Destroy
+ */
+static BOOL LISTBOX_Destroy( WND *wnd, LB_DESCR *descr )
+{
+ LISTBOX_ResetContent( wnd, descr );
+ HeapDestroy( descr->heap );
+ HeapFree( GetProcessHeap(), 0, descr );
+ wnd->wExtra[0] = 0;
+ return TRUE;
+}
+
+
+/***********************************************************************
+ * ListBoxWndProc
+ */
+LRESULT WINAPI ListBoxWndProc( HWND hwnd, UINT msg,
+ WPARAM wParam, LPARAM lParam )
+{
+ LRESULT ret;
+ LB_DESCR *descr;
+ WND *wnd = WIN_FindWndPtr( hwnd );
+
+ if (!wnd) return 0;
+ if (!(descr = *(LB_DESCR **)wnd->wExtra))
+ {
+ if (msg == WM_CREATE)
+ {
+ if (!LISTBOX_Create( wnd, NULL )) return -1;
+ DPRINT( "creating wnd=%04x descr=%p\n",
+ hwnd, *(LB_DESCR **)wnd->wExtra );
+ return 0;
+ }
+ /* Ignore all other messages before we get a WM_CREATE */
+ return DefWindowProcA( hwnd, msg, wParam, lParam );
+ }
+
+ DPRINT( "[%04x]: msg %s wp %08x lp %08lx\n",
+ wnd->hwndSelf, SPY_GetMsgName(msg), wParam, lParam );
+ switch(msg)
+ {
+ case LB_RESETCONTENT:
+ LISTBOX_ResetContent( wnd, descr );
+ return 0;
+
+ case LB_ADDSTRING:
+ wParam = LISTBOX_FindStringPos( wnd, descr, (LPCSTR)lParam, FALSE );
+ return LISTBOX_InsertString( wnd, descr, wParam, (LPCSTR)lParam );
+
+ case LB_INSERTSTRING:
+ return LISTBOX_InsertString( wnd, descr, wParam, (LPCSTR)lParam );
+
+
+ case LB_ADDFILE:
+ wParam = LISTBOX_FindFileStrPos( wnd, descr, (LPCSTR)lParam );
+ return LISTBOX_InsertString( wnd, descr, wParam, (LPCSTR)lParam );
+
+ case LB_DELETESTRING:
+ return LISTBOX_RemoveItem( wnd, descr, wParam );
+
+ case LB_GETITEMDATA:
+ if (((INT)wParam < 0) || ((INT)wParam >= descr->nb_items))
+ return LB_ERR;
+ return descr->items[wParam].data;
+
+ case LB_SETITEMDATA:
+ if (((INT)wParam < 0) || ((INT)wParam >= descr->nb_items))
+ return LB_ERR;
+ descr->items[wParam].data = (DWORD)lParam;
+ return LB_OKAY;
+
+ case LB_GETCOUNT:
+ return descr->nb_items;
+
+ case LB_GETTEXT:
+ return LISTBOX_GetText( wnd, descr, wParam, (LPSTR)lParam );
+
+ case LB_GETTEXTLEN:
+ if (wParam >= descr->nb_items) return LB_ERR;
+ return (HAS_STRINGS(descr) ? strlen(descr->items[wParam].str)
+ : sizeof(DWORD));
+
+
+ case LB_GETCURSEL:
+ return descr->selected_item;
+
+
+ case LB_GETTOPINDEX:
+ return descr->top_item;
+
+ case LB_GETITEMHEIGHT:
+ return LISTBOX_GetItemHeight( wnd, descr, wParam );
+
+
+ case LB_SETITEMHEIGHT:
+ return LISTBOX_SetItemHeight( wnd, descr, wParam, lParam );
+
+ case LB_ITEMFROMPOINT:
+ {
+ POINT pt = { LOWORD(lParam), HIWORD(lParam) };
+ RECT rect = { 0, 0, descr->width, descr->height };
+ return MAKELONG( LISTBOX_GetItemFromPoint(wnd, descr, pt.x, pt.y),
+ PtInRect( &rect, pt ) );
+ }
+
+
+ case LB_SETCARETINDEX:
+ return LISTBOX_SetCaretIndex( wnd, descr, wParam, !lParam );
+
+
+ case LB_GETCARETINDEX:
+ return descr->focus_item;
+
+
+ case LB_SETTOPINDEX:
+ return LISTBOX_SetTopItem( wnd, descr, wParam, TRUE );
+
+
+ case LB_SETCOLUMNWIDTH:
+ return LISTBOX_SetColumnWidth( wnd, descr, wParam );
+
+
+
+ case LB_GETITEMRECT:
+ return LISTBOX_GetItemRect( wnd, descr, wParam, (RECT *)lParam );
+
+
+ case LB_FINDSTRING:
+ return LISTBOX_FindString( wnd, descr, wParam, (LPCSTR)lParam, FALSE );
+
+
+ case LB_FINDSTRINGEXACT:
+ return LISTBOX_FindString( wnd, descr, wParam, (LPCSTR)lParam, TRUE );
+
+
+ case LB_SELECTSTRING:
+ {
+ INT index = LISTBOX_FindString( wnd, descr, wParam,
+ (LPCSTR)lParam, FALSE );
+ if (index == LB_ERR) return LB_ERR;
+ LISTBOX_SetSelection( wnd, descr, index, TRUE, FALSE );
+ return index;
+ }
+
+
+ case LB_GETSEL:
+ if (((INT)wParam < 0) || ((INT)wParam >= descr->nb_items))
+ return LB_ERR;
+ return descr->items[wParam].selected;
+
+ case LB_SETSEL:
+ return LISTBOX_SetSelection( wnd, descr, lParam, wParam, FALSE );
+
+
+ case LB_SETCURSEL:
+ LISTBOX_SetCaretIndex( wnd, descr, wParam, TRUE );
+ return LISTBOX_SetSelection( wnd, descr, wParam, TRUE, FALSE );
+
+ case LB_GETSELCOUNT:
+ return LISTBOX_GetSelCount( wnd, descr );
+
+
+ case LB_GETSELITEMS:
+ return LISTBOX_GetSelItems( wnd, descr, wParam, (LPINT)lParam );
+
+ case LB_SELITEMRANGE:
+ if (LOWORD(lParam) <= HIWORD(lParam))
+ return LISTBOX_SelectItemRange( wnd, descr, LOWORD(lParam),
+ HIWORD(lParam), wParam );
+ else
+ return LISTBOX_SelectItemRange( wnd, descr, HIWORD(lParam),
+ LOWORD(lParam), wParam );
+
+
+ case LB_SELITEMRANGEEX:
+ if ((INT)lParam >= (INT)wParam)
+ return LISTBOX_SelectItemRange( wnd, descr, wParam, lParam, TRUE );
+ else
+ return LISTBOX_SelectItemRange( wnd, descr, lParam, wParam, FALSE);
+
+
+ case LB_GETHORIZONTALEXTENT:
+ return descr->horz_extent;
+
+
+ case LB_SETHORIZONTALEXTENT:
+ return LISTBOX_SetHorizontalExtent( wnd, descr, wParam );
+
+ case LB_GETANCHORINDEX:
+ return descr->anchor_item;
+
+
+ case LB_SETANCHORINDEX:
+ if (((INT)wParam < -1) || ((INT)wParam >= descr->nb_items))
+ return LB_ERR;
+ descr->anchor_item = (INT)wParam;
+ return LB_OKAY;
+
+
+
+ case LB_DIR:
+ return LISTBOX_Directory( wnd, descr, wParam, (LPCSTR)lParam, TRUE );
+
+ case LB_GETLOCALE:
+ return descr->locale;
+
+ case LB_SETLOCALE:
+ descr->locale = (LCID)wParam; /* FIXME: should check for valid lcid */
+ return LB_OKAY;
+
+ case LB_INITSTORAGE:
+ return LISTBOX_InitStorage( wnd, descr, wParam, (DWORD)lParam );
+
+ case LB_SETCOUNT:
+ return LISTBOX_SetCount( wnd, descr, (INT)wParam );
+
+
+
+ case LB_SETTABSTOPS:
+ return LISTBOX_SetTabStops( wnd, descr, wParam,
+ (LPINT)lParam, FALSE );
+
+
+ case LB_CARETON:
+ if (descr->caret_on) return LB_OKAY;
+ descr->caret_on = TRUE;
+ if ((descr->focus_item != -1) && (GetFocus() == wnd->hwndSelf))
+ LISTBOX_RepaintItem( wnd, descr, descr->focus_item, ODA_FOCUS );
+ return LB_OKAY;
+
+
+ case LB_CARETOFF:
+ if (!descr->caret_on) return LB_OKAY;
+ descr->caret_on = FALSE;
+ if ((descr->focus_item != -1) && (GetFocus() == wnd->hwndSelf))
+ LISTBOX_RepaintItem( wnd, descr, descr->focus_item, ODA_FOCUS );
+ return LB_OKAY;
+
+ case WM_DESTROY:
+ return LISTBOX_Destroy( wnd, descr );
+
+ case WM_ENABLE:
+ InvalidateRect( hwnd, NULL, TRUE );
+ return 0;
+
+ case WM_SETREDRAW:
+ LISTBOX_SetRedraw( wnd, descr, wParam != 0 );
+ return 0;
+
+ case WM_GETDLGCODE:
+ return DLGC_WANTARROWS | DLGC_WANTCHARS;
+
+ case WM_PAINT:
+ {
+ PAINTSTRUCT ps;
+ HDC hdc = ( wParam ) ? ((HDC)wParam)
+ : BeginPaint( hwnd, &ps );
+ ret = LISTBOX_Paint( wnd, descr, hdc );
+ if( !wParam ) EndPaint( hwnd, &ps );
+ }
+ return ret;
+
+ case WM_SIZE:
+ LISTBOX_UpdateSize( wnd, descr );
+ return 0;
+
+ case WM_GETFONT:
+ return descr->font;
+
+ case WM_SETFONT:
+ LISTBOX_SetFont( wnd, descr, (HFONT)wParam );
+ if (lParam) InvalidateRect( wnd->hwndSelf, 0, TRUE );
+ return 0;
+
+ case WM_SETFOCUS:
+ descr->caret_on = TRUE;
+ if (descr->focus_item != -1)
+ LISTBOX_RepaintItem( wnd, descr, descr->focus_item, ODA_FOCUS );
+ SEND_NOTIFICATION( wnd, descr, LBN_SETFOCUS );
+ return 0;
+
+ case WM_KILLFOCUS:
+ if ((descr->focus_item != -1) && descr->caret_on)
+ LISTBOX_RepaintItem( wnd, descr, descr->focus_item, ODA_FOCUS );
+ SEND_NOTIFICATION( wnd, descr, LBN_KILLFOCUS );
+ return 0;
+
+ case WM_HSCROLL:
+ return LISTBOX_HandleHScroll( wnd, descr, wParam, lParam );
+
+ case WM_VSCROLL:
+ return LISTBOX_HandleVScroll( wnd, descr, wParam, lParam );
+
+ case WM_LBUTTONDOWN:
+ return LISTBOX_HandleLButtonDown( wnd, descr, wParam,
+ (INT)LOWORD(lParam),
+ (INT)HIWORD(lParam) );
+
+ case WM_LBUTTONDBLCLK:
+ if (descr->style & LBS_NOTIFY)
+ SEND_NOTIFICATION( wnd, descr, LBN_DBLCLK );
+ return 0;
+
+ case WM_MOUSEMOVE:
+ if (GetCapture() == hwnd)
+ LISTBOX_HandleMouseMove( wnd, descr, (INT)LOWORD(lParam),
+ (INT)HIWORD(lParam) );
+ return 0;
+
+ case WM_LBUTTONUP:
+ return LISTBOX_HandleLButtonUp( wnd, descr );
+
+ case WM_KEYDOWN:
+ return LISTBOX_HandleKeyDown( wnd, descr, wParam );
+
+ case WM_CHAR:
+ return LISTBOX_HandleChar( wnd, descr, wParam );
+
+ case WM_SYSTIMER:
+ return LISTBOX_HandleSystemTimer( wnd, descr );
+
+ case WM_ERASEBKGND:
+ if (IS_OWNERDRAW(descr))
+ {
+ RECT rect = { 0, 0, descr->width, descr->height };
+ HBRUSH hbrush = SendMessageA( descr->owner, WM_CTLCOLORLISTBOX,
+ wParam, (LPARAM)wnd->hwndSelf );
+ if (hbrush) FillRect( (HDC)wParam, &rect, hbrush );
+ }
+ return 1;
+
+ case WM_DROPFILES:
+ if( !descr->lphc )
+ return SendMessageA( descr->owner, msg, wParam, lParam );
+ break;
+
+ case WM_DROPOBJECT:
+ case WM_QUERYDROPOBJECT:
+ case WM_DRAGSELECT:
+ case WM_DRAGMOVE:
+ if( !descr->lphc )
+ {
+ // LPDRAGINFO dragInfo = (LPDRAGINFO)lParam;
+ // dragInfo->l = LISTBOX_GetItemFromPoint( wnd, descr, dragInfo->pt.x,
+ // dragInfo->pt.y );
+ return SendMessageA( descr->owner, msg, wParam, lParam );
+ }
+ break;
+
+ case WM_NCCREATE:
+ if (TWEAK_WineLook > WIN31_LOOK)
+ wnd->dwExStyle |= WS_EX_CLIENTEDGE;
+ return DefWindowProcA( hwnd, msg, wParam, lParam );
+
+ default:
+ if ((msg >= WM_USER) && (msg < 0xc000))
+ DPRINT( "[%04x]: unknown msg %04x wp %08x lp %08lx\n",
+ hwnd, msg, wParam, lParam );
+ return DefWindowProcA( hwnd, msg, wParam, lParam );
+ }
+ return 0;
+}
+
+/***********************************************************************
+ * COMBO_Directory
+ */
+LRESULT COMBO_Directory( LPHEADCOMBO lphc, UINT attrib, LPSTR dir, BOOL bLong)
+{
+ WND *wnd = WIN_FindWndPtr( lphc->hWndLBox );
+
+ if( wnd )
+ {
+ LB_DESCR *descr = *(LB_DESCR **)wnd->wExtra;
+ if( descr )
+ {
+ LRESULT lRet = LISTBOX_Directory( wnd, descr, attrib, dir, bLong );
+
+ RedrawWindow( lphc->self->hwndSelf, NULL, 0,
+ RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW );
+ return lRet;
+ }
+ }
+ return CB_ERR;
+}
+
+/***********************************************************************
+ * ComboLBWndProc
+ *
+ * NOTE: in Windows, winproc address of the ComboLBox is the same
+ * as that of the Listbox.
+ */
+LRESULT WINAPI ComboLBWndProc( HWND hwnd, UINT msg,
+ WPARAM wParam, LPARAM lParam )
+{
+ LRESULT lRet = 0;
+ WND *wnd = WIN_FindWndPtr( hwnd );
+
+ if (wnd)
+ {
+ LB_DESCR *descr = *(LB_DESCR **)wnd->wExtra;
+
+ DPRINT( "[%04x]: msg %s wp %08x lp %08lx\n",
+ wnd->hwndSelf, SPY_GetMsgName(msg), wParam, lParam );
+
+ if( descr || msg == WM_CREATE )
+ {
+ LPHEADCOMBO lphc = (descr) ? descr->lphc : NULL;
+
+ switch( msg )
+ {
+ case WM_CREATE:
+#define lpcs ((LPCREATESTRUCTA)lParam)
+ DPRINT( "\tpassed parent handle = 0x%08x\n",
+ (UINT)lpcs->lpCreateParams);
+
+ lphc = (LPHEADCOMBO)(lpcs->lpCreateParams);
+#undef lpcs
+ return LISTBOX_Create( wnd, lphc );
+
+ case WM_LBUTTONDOWN:
+ return LISTBOX_HandleLButtonDown( wnd, descr, wParam,
+ (INT)LOWORD(lParam), (INT)HIWORD(lParam));
+
+ /* avoid activation at all costs */
+
+ case WM_MOUSEACTIVATE:
+ return MA_NOACTIVATE;
+
+ case WM_NCACTIVATE:
+ return FALSE;
+
+ case WM_KEYDOWN:
+ if( CB_GETTYPE(lphc) != CBS_SIMPLE )
+ {
+ /* for some reason(?) Windows makes it possible to
+ * show/hide ComboLBox by sending it WM_KEYDOWNs */
+
+ if( (!(lphc->wState & CBF_EUI) && wParam == VK_F4) ||
+ ( (lphc->wState & CBF_EUI) && !(lphc->wState & CBF_DROPPED)
+ && (wParam == VK_DOWN || wParam == VK_UP)) )
+ {
+ COMBO_FlipListbox( lphc, FALSE );
+ return 0;
+ }
+ }
+ return LISTBOX_HandleKeyDown( wnd, descr, wParam );
+
+ case LB_SETCURSEL:
+ lRet = ListBoxWndProc( hwnd, msg, wParam, lParam );
+ return (lRet == LB_ERR) ? lRet : descr->selected_item;
+
+ case WM_NCDESTROY:
+ if( CB_GETTYPE(lphc) != CBS_SIMPLE )
+ lphc->hWndLBox = 0;
+ /* fall through */
+
+ default:
+ return ListBoxWndProc( hwnd, msg, wParam, lParam );
+ }
+ }
+ lRet = DefWindowProcA( hwnd, msg, wParam, lParam );
+
+ DPRINT("\t default on msg [%04x]\n", (UINT)msg );
+ }
+
+ return lRet;
+}
+
-#include <assert.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
-#undef WIN32_LEAN_AND_MEAN
+
+
#include <windows.h>
#include <user32/win.h>
-//#include <user32/debug.h>
+#include <user32/debug.h>
#include <user32/resource.h>
#include <user32/sysmetr.h>
#include <user32/menu.h>
+#include <user32/syscolor.h>
+
-#include<stdio.h>
-#define DPRINT printf
/**********************************************************************
menu->hWnd = 0;
menu->items = NULL;
menu->FocusedItem = NO_SELECTED_ITEM;
- //TRACE(menu, "return %04x\n", hMenu );
+ DPRINT( "return %04x\n", hMenu );
return hMenu;
}
*/
HMENU STDCALL LoadMenuA( HINSTANCE instance, LPCSTR name )
{
-// instance should be a module handle GetModuleHandle(NULL)
- HRSRC hrsrc = FindResourceA( instance, name, (LPCSTR)RT_MENU );
+
+ HRSRC hrsrc = FindResourceA( GetModuleHandle(NULL), name, (LPCSTR)RT_MENU );
if (!hrsrc) return 0;
- return LoadMenuIndirectA( (LPCVOID)LoadResource( instance, hrsrc ));
+ return LoadMenuIndirectA( (LPCVOID)LoadResource( GetModuleHandle(NULL), hrsrc ));
}
HMENU STDCALL LoadMenuW( HINSTANCE hInstance, LPCWSTR name )
{
- HRSRC hrsrc = FindResourceW( hInstance, name, (LPCWSTR)RT_MENU );
- if (!hrsrc)
- return 0;
- return LoadMenuIndirectW( (LPCVOID)LoadResource( hInstance, hrsrc ));
+ HRSRC hrsrc = FindResourceW( GetModuleHandle(NULL), name, (LPCSTR)RT_MENU );
+ if (!hrsrc) return 0;
+ return LoadMenuIndirectW( (LPCVOID)LoadResource( GetModuleHandle(NULL), hrsrc ));
}
/*
-
-typedef struct {
- WORD mtOption;
- WORD mtID;
- WCHAR mtString[1];
+A menu template consists of a MENUITEMTEMPLATEHEADER structure
+followed by one or more contiguous MENUITEMTEMPLATE structures.
+In Windows 95, an extended menu template consists of a
+MENUEX_TEMPLATE_HEADER structure followed by one or more
+contiguous MENUEX_TEMPLATE_ITEM structures.
+
+
+typedef struct {
+ WORD wVersion;
+ WORD wOffset;
+ DWORD dwHelpId;
+} MENUEX_TEMPLATE_HEADER;
+
+typedef struct {
+ DWORD dwType;
+ DWORD dwState;
+ UINT uId;
+ BYTE bResInfo;
+ WCHAR szText[1];
+ DWORD dwHelpId;
+} MENUEX_TEMPLATE_ITEM;
+
+typedef struct tagMENUITEMINFO {
+ UINT cbSize;
+ UINT fMask;
+ UINT fType;
+ UINT fState;
+ UINT wID;
+ HMENU hSubMenu;
+ HBITMAP hbmpChecked;
+ HBITMAP hbmpUnchecked;
+ DWORD dwItemData;
+ LPTSTR dwTypeData;
+ UINT cch;
+} MENUITEMINFO, *LPMENUITEMINFO;
+typedef MENUITEMINFO CONST *LPCMENUITEMINFO;
+
+typedef struct {
+ WORD mtOption;
+ WORD mtID;
+ WCHAR mtString[1];
} MENUITEMTEMPLATE;
+
+typedef struct {
+ WORD versionNumber;
+ WORD offset;
+} MENUITEMTEMPLATEHEADER;
+typedef VOID MENUTEMPLATE, *LPMENUTEMPLATE;
+
*/
/**********************************************************************
MENUITEM *item;
int i;
int len;
- //TRACE(menu, "menu=%04x item=%04x ptr=%p len=%d flags=%04x\n",
- // hMenu, wItemID, str, nMaxSiz, wFlags );
+ DPRINT( "menu=%04x item=%04x ptr=%p len=%d flags=%04x\n", hMenu, wItemID, str, nMaxSiz, wFlags );
if (!str || !nMaxSiz)
return 0;
str[0] = '\0';
{
MENUITEM *item;
- //TRACE(menu, "menu=%04x item=%04x ptr=%p len=%d flags=%04x\n",
- // hMenu, wItemID, str, nMaxSiz, wFlags );
+ DPRINT( "menu=%04x item=%04x ptr=%p len=%d flags=%04x\n", hMenu, wItemID, str, nMaxSiz, wFlags );
if (!str || !nMaxSiz)
return 0;
str[0] = '\0';
UINT wHilite )
{
LPPOPUPMENU menu;
-// DPRINT("menu (%04x, %04x, %04x, %04x);\n",
-// hWnd, hMenu, wItemID, wHilite);
+ DPRINT("menu (%04x, %04x, %04x, %04x);\n", hWnd, hMenu, wItemID, wHilite);
+
if (!MENU_FindItem( &hMenu, &wItemID, wHilite )) return FALSE;
if (!(menu = (LPPOPUPMENU) (hMenu))) return FALSE;
if (menu->FocusedItem == wItemID) return TRUE;
GetMenuCheckMarkDimensions(VOID)
{
-
return MAKELONG(GetSystemMetrics(SM_CXMENUCHECK), GetSystemMetrics(SM_CYMENUCHECK) );
}
--- /dev/null
+/*
+ * Scrollbar control
+ *
+ * Copyright 1993 Martin Ayotte
+ * Copyright 1994, 1996 Alexandre Julliard
+ */
+
+#include <windows.h>
+#include <user32/sysmetr.h>
+#include <user32/scroll.h>
+#include <user32/heapdup.h>
+#include <user32/win.h>
+#include <user32/syscolor.h>
+#include <user32/debug.h>
+
+#define MAX(x,y) x > y ? x : y
+#define MIN(x,y) x < y ? x : y
+
+static HBITMAP hUpArrow = 0;
+static HBITMAP hDnArrow = 0;
+static HBITMAP hLfArrow = 0;
+static HBITMAP hRgArrow = 0;
+static HBITMAP hUpArrowD = 0;
+static HBITMAP hDnArrowD = 0;
+static HBITMAP hLfArrowD = 0;
+static HBITMAP hRgArrowD = 0;
+static HBITMAP hUpArrowI = 0;
+static HBITMAP hDnArrowI = 0;
+static HBITMAP hLfArrowI = 0;
+static HBITMAP hRgArrowI = 0;
+
+#define TOP_ARROW(flags,pressed) \
+ (((flags)&ESB_DISABLE_UP) ? hUpArrowI : ((pressed) ? hUpArrowD:hUpArrow))
+#define BOTTOM_ARROW(flags,pressed) \
+ (((flags)&ESB_DISABLE_DOWN) ? hDnArrowI : ((pressed) ? hDnArrowD:hDnArrow))
+#define LEFT_ARROW(flags,pressed) \
+ (((flags)&ESB_DISABLE_LEFT) ? hLfArrowI : ((pressed) ? hLfArrowD:hLfArrow))
+#define RIGHT_ARROW(flags,pressed) \
+ (((flags)&ESB_DISABLE_RIGHT) ? hRgArrowI : ((pressed) ? hRgArrowD:hRgArrow))
+
+
+ /* Minimum size of the rectangle between the arrows */
+#define SCROLL_MIN_RECT 4
+
+ /* Minimum size of the thumb in pixels */
+#define SCROLL_MIN_THUMB 6
+
+ /* Overlap between arrows and thumb */
+#define SCROLL_ARROW_THUMB_OVERLAP 1
+
+ /* Delay (in ms) before first repetition when holding the button down */
+#define SCROLL_FIRST_DELAY 200
+
+ /* Delay (in ms) between scroll repetitions */
+#define SCROLL_REPEAT_DELAY 50
+
+ /* Scroll timer id */
+#define SCROLL_TIMER 0
+
+ /* Scroll-bar hit testing */
+enum SCROLL_HITTEST
+{
+ SCROLL_NOWHERE, /* Outside the scroll bar */
+ SCROLL_TOP_ARROW, /* Top or left arrow */
+ SCROLL_TOP_RECT, /* Rectangle between the top arrow and the thumb */
+ SCROLL_THUMB, /* Thumb rectangle */
+ SCROLL_BOTTOM_RECT, /* Rectangle between the thumb and the bottom arrow */
+ SCROLL_BOTTOM_ARROW /* Bottom or right arrow */
+};
+
+ /* What to do after SCROLL_SetScrollInfo() */
+#define SA_SSI_HIDE 0x0001
+#define SA_SSI_SHOW 0x0002
+#define SA_SSI_REFRESH 0x0004
+#define SA_SSI_REPAINT_ARROWS 0x0008
+
+ /* Thumb-tracking info */
+static HWND SCROLL_TrackingWin = 0;
+static INT SCROLL_TrackingBar = 0;
+static INT SCROLL_TrackingPos = 0;
+static INT SCROLL_TrackingVal = 0;
+ /* Hit test code of the last button-down event */
+static enum SCROLL_HITTEST SCROLL_trackHitTest;
+static BOOL SCROLL_trackVertical;
+
+ /* Is the moving thumb being displayed? */
+static BOOL SCROLL_MovingThumb = FALSE;
+
+ /* Local functions */
+static BOOL SCROLL_ShowScrollBar( HWND hwnd, INT nBar,
+ BOOL fShowH, BOOL fShowV );
+static INT SCROLL_SetScrollInfo( HWND hwnd, INT nBar,
+ const SCROLLINFO *info, INT *action );
+
+/***********************************************************************
+ * SCROLL_LoadBitmaps
+ */
+static void SCROLL_LoadBitmaps(void)
+{
+ hUpArrow = LoadBitmapA( 0, MAKEINTRESOURCE(OBM_UPARROW) );
+ hDnArrow = LoadBitmapA( 0, MAKEINTRESOURCE(OBM_DNARROW) );
+ hLfArrow = LoadBitmapA( 0, MAKEINTRESOURCE(OBM_LFARROW) );
+ hRgArrow = LoadBitmapA( 0, MAKEINTRESOURCE(OBM_RGARROW) );
+ hUpArrowD = LoadBitmapA( 0, MAKEINTRESOURCE(OBM_UPARROWD) );
+ hDnArrowD = LoadBitmapA( 0, MAKEINTRESOURCE(OBM_DNARROWD) );
+ hLfArrowD = LoadBitmapA( 0, MAKEINTRESOURCE(OBM_LFARROWD) );
+ hRgArrowD = LoadBitmapA( 0, MAKEINTRESOURCE(OBM_RGARROWD) );
+ hUpArrowI = LoadBitmapA( 0, MAKEINTRESOURCE(OBM_UPARROWI) );
+ hDnArrowI = LoadBitmapA( 0, MAKEINTRESOURCE(OBM_DNARROWI) );
+ hLfArrowI = LoadBitmapA( 0, MAKEINTRESOURCE(OBM_LFARROWI) );
+ hRgArrowI = LoadBitmapA( 0, MAKEINTRESOURCE(OBM_RGARROWI) );
+}
+
+
+/***********************************************************************
+ * SCROLL_GetPtrScrollInfo
+ */
+static SCROLLBAR_INFO *SCROLL_GetPtrScrollInfo( WND* wndPtr, INT nBar )
+{
+ SCROLLBAR_INFO *infoPtr;
+
+ if (!wndPtr) return NULL;
+ switch(nBar)
+ {
+ case SB_HORZ: infoPtr = (SCROLLBAR_INFO *)wndPtr->pHScroll; break;
+ case SB_VERT: infoPtr = (SCROLLBAR_INFO *)wndPtr->pVScroll; break;
+ case SB_CTL: infoPtr = (SCROLLBAR_INFO *)wndPtr->wExtra; break;
+ default: return NULL;
+ }
+
+ if (!infoPtr) /* Create the info structure if needed */
+ {
+ if ((infoPtr = HeapAlloc( GetProcessHeap(), 0, sizeof(SCROLLBAR_INFO) )))
+ {
+ infoPtr->MinVal = infoPtr->CurVal = infoPtr->Page = 0;
+ infoPtr->MaxVal = 100;
+ infoPtr->flags = ESB_ENABLE_BOTH;
+ if (nBar == SB_HORZ) wndPtr->pHScroll = infoPtr;
+ else wndPtr->pVScroll = infoPtr;
+ }
+ if (!hUpArrow) SCROLL_LoadBitmaps();
+ }
+ return infoPtr;
+}
+
+
+/***********************************************************************
+ * SCROLL_GetScrollInfo
+ */
+static SCROLLBAR_INFO *SCROLL_GetScrollInfo( HWND hwnd, INT nBar )
+{
+ WND *wndPtr = WIN_FindWndPtr( hwnd );
+ return SCROLL_GetPtrScrollInfo( wndPtr, nBar );
+}
+
+
+/***********************************************************************
+ * SCROLL_GetScrollBarRect
+ *
+ * Compute the scroll bar rectangle, in drawing coordinates (i.e. client
+ * coords for SB_CTL, window coords for SB_VERT and SB_HORZ).
+ * 'arrowSize' returns the width or height of an arrow (depending on
+ * the orientation of the scrollbar), 'thumbSize' returns the size of
+ * the thumb, and 'thumbPos' returns the position of the thumb
+ * relative to the left or to the top.
+ * Return TRUE if the scrollbar is vertical, FALSE if horizontal.
+ */
+static BOOL SCROLL_GetScrollBarRect( HWND hwnd, INT nBar, RECT *lprect,
+ INT *arrowSize, INT *thumbSize,
+ INT *thumbPos )
+{
+ INT pixels;
+ BOOL vertical;
+ WND *wndPtr = WIN_FindWndPtr( hwnd );
+
+ switch(nBar)
+ {
+ case SB_HORZ:
+ lprect->left = wndPtr->rectClient.left - wndPtr->rectWindow.left;
+ lprect->top = wndPtr->rectClient.bottom - wndPtr->rectWindow.top;
+ lprect->right = wndPtr->rectClient.right - wndPtr->rectWindow.left;
+ lprect->bottom = lprect->top + SYSMETRICS_CYHSCROLL;
+ if(wndPtr->dwStyle & WS_BORDER) {
+ lprect->left--;
+ lprect->right++;
+ } else if(wndPtr->dwStyle & WS_VSCROLL)
+ lprect->right++;
+ vertical = FALSE;
+ break;
+
+ case SB_VERT:
+ lprect->left = wndPtr->rectClient.right - wndPtr->rectWindow.left;
+ lprect->top = wndPtr->rectClient.top - wndPtr->rectWindow.top;
+ lprect->right = lprect->left + SYSMETRICS_CXVSCROLL;
+ lprect->bottom = wndPtr->rectClient.bottom - wndPtr->rectWindow.top;
+ if(wndPtr->dwStyle & WS_BORDER) {
+ lprect->top--;
+ lprect->bottom++;
+ } else if(wndPtr->dwStyle & WS_HSCROLL)
+ lprect->bottom++;
+ vertical = TRUE;
+ break;
+
+ case SB_CTL:
+ GetClientRect( hwnd, lprect );
+ vertical = ((wndPtr->dwStyle & SBS_VERT) != 0);
+ break;
+
+ default:
+ return FALSE;
+ }
+
+ if (vertical) pixels = lprect->bottom - lprect->top;
+ else pixels = lprect->right - lprect->left;
+
+ if (pixels <= 2*SYSMETRICS_CXVSCROLL + SCROLL_MIN_RECT)
+ {
+ if (pixels > SCROLL_MIN_RECT)
+ *arrowSize = (pixels - SCROLL_MIN_RECT) / 2;
+ else
+ *arrowSize = 0;
+ *thumbPos = *thumbSize = 0;
+ }
+ else
+ {
+ SCROLLBAR_INFO *info = SCROLL_GetPtrScrollInfo( wndPtr, nBar );
+
+ *arrowSize = SYSMETRICS_CXVSCROLL;
+ pixels -= (2 * (SYSMETRICS_CXVSCROLL - SCROLL_ARROW_THUMB_OVERLAP));
+
+ if (info->Page)
+ {
+ *thumbSize = pixels * info->Page / (info->MaxVal-info->MinVal+1);
+ if (*thumbSize < SCROLL_MIN_THUMB) *thumbSize = SCROLL_MIN_THUMB;
+ }
+ else *thumbSize = SYSMETRICS_CXVSCROLL;
+
+ if (((pixels -= *thumbSize ) < 0) ||
+ ((info->flags & ESB_DISABLE_BOTH) == ESB_DISABLE_BOTH))
+ {
+ /* Rectangle too small or scrollbar disabled -> no thumb */
+ *thumbPos = *thumbSize = 0;
+ }
+ else
+ {
+ INT max = info->MaxVal - MAX( info->Page-1, 0 );
+ if (info->MinVal >= max)
+ *thumbPos = *arrowSize - SCROLL_ARROW_THUMB_OVERLAP;
+ else
+ *thumbPos = *arrowSize - SCROLL_ARROW_THUMB_OVERLAP
+ + pixels * (info->CurVal-info->MinVal) / (max - info->MinVal);
+ }
+ }
+ return vertical;
+}
+
+
+/***********************************************************************
+ * SCROLL_GetThumbVal
+ *
+ * Compute the current scroll position based on the thumb position in pixels
+ * from the top of the scroll-bar.
+ */
+static UINT SCROLL_GetThumbVal( SCROLLBAR_INFO *infoPtr, RECT *rect,
+ BOOL vertical, INT pos )
+{
+ INT thumbSize;
+ INT pixels = vertical ? rect->bottom-rect->top : rect->right-rect->left;
+
+ if ((pixels -= 2*(SYSMETRICS_CXVSCROLL - SCROLL_ARROW_THUMB_OVERLAP)) <= 0)
+ return infoPtr->MinVal;
+
+ if (infoPtr->Page)
+ {
+ thumbSize = pixels * infoPtr->Page/(infoPtr->MaxVal-infoPtr->MinVal+1);
+ if (thumbSize < SCROLL_MIN_THUMB) thumbSize = SCROLL_MIN_THUMB;
+ }
+ else thumbSize = SYSMETRICS_CXVSCROLL;
+
+ if ((pixels -= thumbSize) <= 0) return infoPtr->MinVal;
+
+ pos = MAX( 0, pos - (SYSMETRICS_CXVSCROLL - SCROLL_ARROW_THUMB_OVERLAP) );
+ if (pos > pixels) pos = pixels;
+
+ if (!infoPtr->Page) pos *= infoPtr->MaxVal - infoPtr->MinVal;
+ else pos *= infoPtr->MaxVal - infoPtr->MinVal - infoPtr->Page + 1;
+ return infoPtr->MinVal + ((pos + pixels / 2) / pixels);
+}
+
+/***********************************************************************
+ * SCROLL_PtInRectEx
+ */
+static BOOL SCROLL_PtInRectEx( LPRECT lpRect, POINT pt, BOOL vertical )
+{
+ RECT rect = *lpRect;
+
+ if (vertical)
+ {
+ rect.left -= lpRect->right - lpRect->left;
+ rect.right += lpRect->right - lpRect->left;
+ }
+ else
+ {
+ rect.top -= lpRect->bottom - lpRect->top;
+ rect.bottom += lpRect->bottom - lpRect->top;
+ }
+ return PtInRect( &rect, pt );
+}
+
+/***********************************************************************
+ * SCROLL_ClipPos
+ */
+static POINT SCROLL_ClipPos( LPRECT lpRect, POINT pt )
+{
+ if( pt.x < lpRect->left )
+ pt.x = lpRect->left;
+ else
+ if( pt.x > lpRect->right )
+ pt.x = lpRect->right;
+
+ if( pt.y < lpRect->top )
+ pt.y = lpRect->top;
+ else
+ if( pt.y > lpRect->bottom )
+ pt.y = lpRect->bottom;
+
+ return pt;
+}
+
+
+/***********************************************************************
+ * SCROLL_HitTest
+ *
+ * Scroll-bar hit testing (don't confuse this with WM_NCHITTEST!).
+ */
+static enum SCROLL_HITTEST SCROLL_HitTest( HWND hwnd, INT nBar,
+ POINT pt, BOOL bDragging )
+{
+ INT arrowSize, thumbSize, thumbPos;
+ RECT rect;
+
+ BOOL vertical = SCROLL_GetScrollBarRect( hwnd, nBar, &rect,
+ &arrowSize, &thumbSize, &thumbPos );
+
+ if ( (bDragging && !SCROLL_PtInRectEx( &rect, pt, vertical )) ||
+ (!PtInRect( &rect, pt )) ) return SCROLL_NOWHERE;
+
+ if (vertical)
+ {
+ if (pt.y < rect.top + arrowSize) return SCROLL_TOP_ARROW;
+ if (pt.y >= rect.bottom - arrowSize) return SCROLL_BOTTOM_ARROW;
+ if (!thumbPos) return SCROLL_TOP_RECT;
+ pt.y -= rect.top;
+ if (pt.y < thumbPos) return SCROLL_TOP_RECT;
+ if (pt.y >= thumbPos + thumbSize) return SCROLL_BOTTOM_RECT;
+ }
+ else /* horizontal */
+ {
+ if (pt.x < rect.left + arrowSize) return SCROLL_TOP_ARROW;
+ if (pt.x >= rect.right - arrowSize) return SCROLL_BOTTOM_ARROW;
+ if (!thumbPos) return SCROLL_TOP_RECT;
+ pt.x -= rect.left;
+ if (pt.x < thumbPos) return SCROLL_TOP_RECT;
+ if (pt.x >= thumbPos + thumbSize) return SCROLL_BOTTOM_RECT;
+ }
+ return SCROLL_THUMB;
+}
+
+
+/***********************************************************************
+ * SCROLL_DrawArrows
+ *
+ * Draw the scroll bar arrows.
+ */
+static void SCROLL_DrawArrows( HDC hdc, SCROLLBAR_INFO *infoPtr,
+ RECT *rect, INT arrowSize, BOOL vertical,
+ BOOL top_pressed, BOOL bottom_pressed )
+{
+ HDC hdcMem = CreateCompatibleDC( hdc );
+ HBITMAP hbmpPrev = SelectObject( hdcMem, vertical ?
+ TOP_ARROW(infoPtr->flags, top_pressed)
+ : LEFT_ARROW(infoPtr->flags, top_pressed));
+
+ SetStretchBltMode( hdc, STRETCH_DELETESCANS );
+ StretchBlt( hdc, rect->left, rect->top,
+ vertical ? rect->right-rect->left : arrowSize,
+ vertical ? arrowSize : rect->bottom-rect->top,
+ hdcMem, 0, 0,
+ SYSMETRICS_CXVSCROLL, SYSMETRICS_CYHSCROLL,
+ SRCCOPY );
+
+ SelectObject( hdcMem, vertical ?
+ BOTTOM_ARROW( infoPtr->flags, bottom_pressed )
+ : RIGHT_ARROW( infoPtr->flags, bottom_pressed ) );
+ if (vertical)
+ StretchBlt( hdc, rect->left, rect->bottom - arrowSize,
+ rect->right - rect->left, arrowSize,
+ hdcMem, 0, 0,
+ SYSMETRICS_CXVSCROLL, SYSMETRICS_CYHSCROLL,
+ SRCCOPY );
+ else
+ StretchBlt( hdc, rect->right - arrowSize, rect->top,
+ arrowSize, rect->bottom - rect->top,
+ hdcMem, 0, 0,
+ SYSMETRICS_CXVSCROLL, SYSMETRICS_CYHSCROLL,
+ SRCCOPY );
+ SelectObject( hdcMem, hbmpPrev );
+ DeleteDC( hdcMem );
+}
+
+
+/***********************************************************************
+ * SCROLL_DrawMovingThumb
+ *
+ * Draw the moving thumb rectangle.
+ */
+static void SCROLL_DrawMovingThumb( HDC hdc, RECT *rect, BOOL vertical,
+ INT arrowSize, INT thumbSize )
+{
+ RECT r = *rect;
+ if (vertical)
+ {
+ r.top += SCROLL_TrackingPos;
+ if (r.top < rect->top + arrowSize - SCROLL_ARROW_THUMB_OVERLAP)
+ r.top = rect->top + arrowSize - SCROLL_ARROW_THUMB_OVERLAP;
+ if (r.top + thumbSize >
+ rect->bottom - (arrowSize - SCROLL_ARROW_THUMB_OVERLAP))
+ r.top = rect->bottom - (arrowSize - SCROLL_ARROW_THUMB_OVERLAP)
+ - thumbSize;
+ r.bottom = r.top + thumbSize;
+ }
+ else
+ {
+ r.left += SCROLL_TrackingPos;
+ if (r.left < rect->left + arrowSize - SCROLL_ARROW_THUMB_OVERLAP)
+ r.left = rect->left + arrowSize - SCROLL_ARROW_THUMB_OVERLAP;
+ if (r.left + thumbSize >
+ rect->right - (arrowSize - SCROLL_ARROW_THUMB_OVERLAP))
+ r.left = rect->right - (arrowSize - SCROLL_ARROW_THUMB_OVERLAP)
+ - thumbSize;
+ r.right = r.left + thumbSize;
+ }
+ DrawFocusRect( hdc, &r );
+ SCROLL_MovingThumb = !SCROLL_MovingThumb;
+}
+
+
+/***********************************************************************
+ * SCROLL_DrawInterior
+ *
+ * Draw the scroll bar interior (everything except the arrows).
+ */
+static void SCROLL_DrawInterior( HWND hwnd, HDC hdc, INT nBar,
+ RECT *rect, INT arrowSize,
+ INT thumbSize, INT thumbPos,
+ UINT flags, BOOL vertical,
+ BOOL top_selected, BOOL bottom_selected )
+{
+ RECT r;
+
+ /* Select the correct brush and pen */
+
+ SelectObject( hdc, GetSysColorPen(COLOR_WINDOWFRAME) );
+ if ((flags & ESB_DISABLE_BOTH) == ESB_DISABLE_BOTH)
+ {
+ /* This ought to be the color of the parent window */
+ SelectObject( hdc, GetSysColorBrush(COLOR_WINDOW) );
+ }
+ else
+ {
+ if (nBar == SB_CTL) /* Only scrollbar controls send WM_CTLCOLOR */
+ {
+ HBRUSH hbrush = SendMessageA(GetParent(hwnd),
+ WM_CTLCOLORSCROLLBAR, hdc, hwnd );
+ SelectObject( hdc, hbrush );
+ }
+ else SelectObject( hdc, GetSysColorBrush(COLOR_SCROLLBAR) );
+ }
+
+ /* Calculate the scroll rectangle */
+
+ r = *rect;
+ if (vertical)
+ {
+ r.top += arrowSize - SCROLL_ARROW_THUMB_OVERLAP;
+ r.bottom -= (arrowSize - SCROLL_ARROW_THUMB_OVERLAP);
+ }
+ else
+ {
+ r.left += arrowSize - SCROLL_ARROW_THUMB_OVERLAP;
+ r.right -= (arrowSize - SCROLL_ARROW_THUMB_OVERLAP);
+ }
+
+ /* Draw the scroll bar frame */
+
+ Rectangle( hdc, r.left, r.top, r.right, r.bottom );
+
+ /* Draw the scroll rectangles and thumb */
+
+ if (!thumbPos) /* No thumb to draw */
+ {
+ PatBlt( hdc, r.left+1, r.top+1, r.right - r.left - 2,
+ r.bottom - r.top - 2, PATCOPY );
+ return;
+ }
+
+ if (vertical)
+ {
+ PatBlt( hdc, r.left + 1, r.top + 1,
+ r.right - r.left - 2,
+ thumbPos - (arrowSize - SCROLL_ARROW_THUMB_OVERLAP) - 1,
+ top_selected ? 0x0f0000 : PATCOPY );
+ r.top += thumbPos - (arrowSize - SCROLL_ARROW_THUMB_OVERLAP);
+ PatBlt( hdc, r.left + 1, r.top + thumbSize,
+ r.right - r.left - 2,
+ r.bottom - r.top - thumbSize - 1,
+ bottom_selected ? 0x0f0000 : PATCOPY );
+ r.bottom = r.top + thumbSize;
+ }
+ else /* horizontal */
+ {
+ PatBlt( hdc, r.left + 1, r.top + 1,
+ thumbPos - (arrowSize - SCROLL_ARROW_THUMB_OVERLAP) - 1,
+ r.bottom - r.top - 2,
+ top_selected ? 0x0f0000 : PATCOPY );
+ r.left += thumbPos - (arrowSize - SCROLL_ARROW_THUMB_OVERLAP);
+ PatBlt( hdc, r.left + thumbSize, r.top + 1,
+ r.right - r.left - thumbSize - 1,
+ r.bottom - r.top - 2,
+ bottom_selected ? 0x0f0000 : PATCOPY );
+ r.right = r.left + thumbSize;
+ }
+
+ /* Draw the thumb */
+
+ SelectObject( hdc, GetSysColorBrush(COLOR_BTNFACE) );
+ Rectangle( hdc, r.left, r.top, r.right, r.bottom );
+ r.top++, r.left++;
+ DrawEdge( hdc, &r, EDGE_RAISED, BF_RECT );
+ if (SCROLL_MovingThumb &&
+ (SCROLL_TrackingWin == hwnd) &&
+ (SCROLL_TrackingBar == nBar))
+ {
+ SCROLL_DrawMovingThumb( hdc, rect, vertical, arrowSize, thumbSize );
+ SCROLL_MovingThumb = TRUE;
+ }
+}
+
+
+/***********************************************************************
+ * SCROLL_DrawScrollBar
+ *
+ * Redraw the whole scrollbar.
+ */
+void SCROLL_DrawScrollBar( HWND hwnd, HDC hdc, INT nBar,
+ BOOL arrows, BOOL interior )
+{
+ INT arrowSize, thumbSize, thumbPos;
+ RECT rect;
+ BOOL vertical;
+ WND *wndPtr = WIN_FindWndPtr( hwnd );
+ SCROLLBAR_INFO *infoPtr = SCROLL_GetPtrScrollInfo( wndPtr, nBar );
+
+ if (!wndPtr || !infoPtr ||
+ ((nBar == SB_VERT) && !(wndPtr->dwStyle & WS_VSCROLL)) ||
+ ((nBar == SB_HORZ) && !(wndPtr->dwStyle & WS_HSCROLL))) return;
+ if (!WIN_IsWindowDrawable( wndPtr, FALSE )) return;
+
+ vertical = SCROLL_GetScrollBarRect( hwnd, nBar, &rect,
+ &arrowSize, &thumbSize, &thumbPos );
+
+ /* Draw the arrows */
+
+ if (arrows && arrowSize)
+ {
+ if( vertical == SCROLL_trackVertical && GetCapture() == hwnd )
+ SCROLL_DrawArrows( hdc, infoPtr, &rect, arrowSize, vertical,
+ (SCROLL_trackHitTest == SCROLL_TOP_ARROW),
+ (SCROLL_trackHitTest == SCROLL_BOTTOM_ARROW) );
+ else
+ SCROLL_DrawArrows( hdc, infoPtr, &rect, arrowSize, vertical,
+ FALSE, FALSE );
+ }
+ if( interior )
+ SCROLL_DrawInterior( hwnd, hdc, nBar, &rect, arrowSize, thumbSize,
+ thumbPos, infoPtr->flags, vertical, FALSE, FALSE );
+}
+
+
+/***********************************************************************
+ * SCROLL_RefreshScrollBar
+ *
+ * Repaint the scroll bar interior after a SetScrollRange() or
+ * SetScrollPos() call.
+ */
+static void SCROLL_RefreshScrollBar( HWND hwnd, INT nBar,
+ BOOL arrows, BOOL interior )
+{
+ HDC hdc = GetDCEx( hwnd, 0,
+ DCX_CACHE | ((nBar == SB_CTL) ? 0 : DCX_WINDOW) );
+ if (!hdc) return;
+
+ SCROLL_DrawScrollBar( hwnd, hdc, nBar, arrows, interior );
+ ReleaseDC( hwnd, hdc );
+}
+
+
+/***********************************************************************
+ * SCROLL_HandleKbdEvent
+ *
+ * Handle a keyboard event (only for SB_CTL scrollbars).
+ */
+static void SCROLL_HandleKbdEvent( HWND hwnd, WPARAM wParam )
+{
+ WND *wndPtr = WIN_FindWndPtr( hwnd );
+ WPARAM msg;
+
+ switch(wParam)
+ {
+ case VK_PRIOR: msg = SB_PAGEUP; break;
+ case VK_NEXT: msg = SB_PAGEDOWN; break;
+ case VK_HOME: msg = SB_TOP; break;
+ case VK_END: msg = SB_BOTTOM; break;
+ case VK_UP: msg = SB_LINEUP; break;
+ case VK_DOWN: msg = SB_LINEDOWN; break;
+ default:
+ return;
+ }
+ SendMessageA( GetParent(hwnd),
+ (wndPtr->dwStyle & SBS_VERT) ? WM_VSCROLL : WM_HSCROLL,
+ msg, hwnd );
+}
+
+
+/***********************************************************************
+ * SCROLL_HandleScrollEvent
+ *
+ * Handle a mouse or timer event for the scrollbar.
+ * 'pt' is the location of the mouse event in client (for SB_CTL) or
+ * windows coordinates.
+ */
+void SCROLL_HandleScrollEvent( HWND hwnd, INT nBar, UINT msg, POINT pt)
+{
+ /* Previous mouse position for timer events */
+ static POINT prevPt;
+ /* Thumb position when tracking started. */
+ static UINT trackThumbPos;
+ /* Position in the scroll-bar of the last button-down event. */
+ static INT lastClickPos;
+ /* Position in the scroll-bar of the last mouse event. */
+ static INT lastMousePos;
+
+ enum SCROLL_HITTEST hittest;
+ HWND hwndOwner, hwndCtl;
+ BOOL vertical;
+ INT arrowSize, thumbSize, thumbPos;
+ RECT rect;
+ HDC hdc;
+
+ SCROLLBAR_INFO *infoPtr = SCROLL_GetScrollInfo( hwnd, nBar );
+ if (!infoPtr) return;
+ if ((SCROLL_trackHitTest == SCROLL_NOWHERE) && (msg != WM_LBUTTONDOWN))
+ return;
+
+ hdc = GetDCEx( hwnd, 0, DCX_CACHE | ((nBar == SB_CTL) ? 0 : DCX_WINDOW));
+ vertical = SCROLL_GetScrollBarRect( hwnd, nBar, &rect,
+ &arrowSize, &thumbSize, &thumbPos );
+ hwndOwner = (nBar == SB_CTL) ? GetParent(hwnd) : hwnd;
+ hwndCtl = (nBar == SB_CTL) ? hwnd : 0;
+
+ switch(msg)
+ {
+ case WM_LBUTTONDOWN: /* Initialise mouse tracking */
+ SCROLL_trackVertical = vertical;
+ SCROLL_trackHitTest = hittest = SCROLL_HitTest( hwnd, nBar, pt, FALSE );
+ lastClickPos = vertical ? (pt.y - rect.top) : (pt.x - rect.left);
+ lastMousePos = lastClickPos;
+ trackThumbPos = thumbPos;
+ prevPt = pt;
+ SetCapture( hwnd );
+ if (nBar == SB_CTL) SetFocus( hwnd );
+ break;
+
+ case WM_MOUSEMOVE:
+ hittest = SCROLL_HitTest( hwnd, nBar, pt, TRUE );
+ prevPt = pt;
+ break;
+
+ case WM_LBUTTONUP:
+ hittest = SCROLL_NOWHERE;
+ ReleaseCapture();
+ break;
+
+ case WM_TIMER:
+ pt = prevPt;
+ hittest = SCROLL_HitTest( hwnd, nBar, pt, FALSE );
+ break;
+
+ default:
+ return; /* Should never happen */
+ }
+
+ DPRINT( "Event: hwnd=%04x bar=%d msg=%x pt=%d,%d hit=%d\n",
+ hwnd, nBar, msg, pt.x, pt.y, hittest );
+
+ switch(SCROLL_trackHitTest)
+ {
+ case SCROLL_NOWHERE: /* No tracking in progress */
+ break;
+
+ case SCROLL_TOP_ARROW:
+ SCROLL_DrawArrows( hdc, infoPtr, &rect, arrowSize, vertical,
+ (hittest == SCROLL_trackHitTest), FALSE );
+ if (hittest == SCROLL_trackHitTest)
+ {
+ if ((msg == WM_LBUTTONDOWN) || (msg == WM_TIMER))
+ {
+ SendMessageA( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
+ SB_LINEUP, hwndCtl );
+ SetTimer( hwnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ?
+ SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY,
+ (TIMERPROC)0 );
+ }
+ }
+ else KillTimer( hwnd, SCROLL_TIMER );
+ break;
+
+ case SCROLL_TOP_RECT:
+ SCROLL_DrawInterior( hwnd, hdc, nBar, &rect, arrowSize, thumbSize,
+ thumbPos, infoPtr->flags, vertical,
+ (hittest == SCROLL_trackHitTest), FALSE );
+ if (hittest == SCROLL_trackHitTest)
+ {
+ if ((msg == WM_LBUTTONDOWN) || (msg == WM_TIMER))
+ {
+ SendMessageA( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
+ SB_PAGEUP, hwndCtl );
+ SetTimer( hwnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ?
+ SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY,
+ (TIMERPROC)0 );
+ }
+ }
+ else KillTimer( hwnd, SCROLL_TIMER );
+ break;
+
+ case SCROLL_THUMB:
+ if (msg == WM_LBUTTONDOWN)
+ {
+ SCROLL_TrackingWin = hwnd;
+ SCROLL_TrackingBar = nBar;
+ SCROLL_TrackingPos = trackThumbPos + lastMousePos - lastClickPos;
+ SCROLL_DrawMovingThumb(hdc, &rect, vertical, arrowSize, thumbSize);
+ }
+ else if (msg == WM_LBUTTONUP)
+ {
+ SCROLL_TrackingWin = 0;
+ SCROLL_MovingThumb = FALSE;
+ SCROLL_DrawInterior( hwnd, hdc, nBar, &rect, arrowSize, thumbSize,
+ thumbPos, infoPtr->flags, vertical,
+ FALSE, FALSE );
+ }
+ else /* WM_MOUSEMOVE */
+ {
+ UINT pos;
+
+ if (!SCROLL_PtInRectEx( &rect, pt, vertical )) pos = lastClickPos;
+ else
+ {
+ pt = SCROLL_ClipPos( &rect, pt );
+ pos = vertical ? (pt.y - rect.top) : (pt.x - rect.left);
+ }
+ if (pos != lastMousePos)
+ {
+ SCROLL_DrawMovingThumb( hdc, &rect, vertical,
+ arrowSize, thumbSize );
+ lastMousePos = pos;
+ SCROLL_TrackingPos = trackThumbPos + pos - lastClickPos;
+ SCROLL_TrackingVal = SCROLL_GetThumbVal( infoPtr, &rect,
+ vertical,
+ SCROLL_TrackingPos );
+ SendMessageA( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
+ MAKEWPARAM( SB_THUMBTRACK, SCROLL_TrackingVal),
+ hwndCtl );
+ SCROLL_DrawMovingThumb( hdc, &rect, vertical,
+ arrowSize, thumbSize );
+ }
+ }
+ break;
+
+ case SCROLL_BOTTOM_RECT:
+ SCROLL_DrawInterior( hwnd, hdc, nBar, &rect, arrowSize, thumbSize,
+ thumbPos, infoPtr->flags, vertical,
+ FALSE, (hittest == SCROLL_trackHitTest) );
+ if (hittest == SCROLL_trackHitTest)
+ {
+ if ((msg == WM_LBUTTONDOWN) || (msg == WM_TIMER))
+ {
+ SendMessageA( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
+ SB_PAGEDOWN, hwndCtl );
+ SetTimer( hwnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ?
+ SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY,
+ (TIMERPROC)0 );
+ }
+ }
+ else KillTimer( hwnd, SCROLL_TIMER );
+ break;
+
+ case SCROLL_BOTTOM_ARROW:
+ SCROLL_DrawArrows( hdc, infoPtr, &rect, arrowSize, vertical,
+ FALSE, (hittest == SCROLL_trackHitTest) );
+ if (hittest == SCROLL_trackHitTest)
+ {
+ if ((msg == WM_LBUTTONDOWN) || (msg == WM_TIMER))
+ {
+ SendMessageA( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
+ SB_LINEDOWN, (LPARAM)hwndCtl );
+ SetTimer( hwnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ?
+ SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY,
+ (TIMERPROC)0 );
+ }
+ }
+ else KillTimer( hwnd, SCROLL_TIMER );
+ break;
+ }
+
+ if (msg == WM_LBUTTONUP)
+ {
+ hittest = SCROLL_trackHitTest;
+ SCROLL_trackHitTest = SCROLL_NOWHERE; /* Terminate tracking */
+
+ if (hittest == SCROLL_THUMB)
+ {
+ UINT val = SCROLL_GetThumbVal( infoPtr, &rect, vertical,
+ trackThumbPos + lastMousePos - lastClickPos );
+ SendMessageA( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
+ MAKEWPARAM( SB_THUMBPOSITION, val ), (LPARAM)hwndCtl );
+ }
+ else
+ SendMessageA( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
+ SB_ENDSCROLL, (LPARAM)hwndCtl );
+ }
+
+ ReleaseDC( hwnd, hdc );
+}
+
+
+/***********************************************************************
+ * ScrollBarWndProc
+ */
+LRESULT STDCALL ScrollBarWndProc( HWND hwnd, UINT message, WPARAM wParam,
+ LPARAM lParam )
+{
+ POINT *pt;
+ switch(message)
+ {
+ case WM_CREATE:
+ {
+ CREATESTRUCTA *lpCreat = (CREATESTRUCTA *)lParam;
+ if (lpCreat->style & SBS_SIZEBOX)
+ {
+ DPRINT( "FIXME Unimplemented style SBS_SIZEBOX.\n" );
+ return 0;
+ }
+
+ if (lpCreat->style & SBS_VERT)
+ {
+ if (lpCreat->style & SBS_LEFTALIGN)
+ MoveWindow( hwnd, lpCreat->x, lpCreat->y,
+ SYSMETRICS_CXVSCROLL+1, lpCreat->cy, FALSE );
+ else if (lpCreat->style & SBS_RIGHTALIGN)
+ MoveWindow( hwnd,
+ lpCreat->x+lpCreat->cx-SYSMETRICS_CXVSCROLL-1,
+ lpCreat->y,
+ SYSMETRICS_CXVSCROLL+1, lpCreat->cy, FALSE );
+ }
+ else /* SBS_HORZ */
+ {
+ if (lpCreat->style & SBS_TOPALIGN)
+ MoveWindow( hwnd, lpCreat->x, lpCreat->y,
+ lpCreat->cx, SYSMETRICS_CYHSCROLL+1, FALSE );
+ else if (lpCreat->style & SBS_BOTTOMALIGN)
+ MoveWindow( hwnd,
+ lpCreat->x,
+ lpCreat->y+lpCreat->cy-SYSMETRICS_CYHSCROLL-1,
+ lpCreat->cx, SYSMETRICS_CYHSCROLL+1, FALSE );
+ }
+ }
+ if (!hUpArrow) SCROLL_LoadBitmaps();
+ DPRINT( "ScrollBar creation, hwnd=%04x\n", hwnd );
+ return 0;
+
+ case WM_LBUTTONDOWN:
+ case WM_LBUTTONUP:
+ case WM_MOUSEMOVE:
+ case WM_TIMER:
+ pt = (POINT *)&lParam;
+ SCROLL_HandleScrollEvent( hwnd, SB_CTL, message,*pt );
+ break;
+
+ case WM_KEYDOWN:
+ SCROLL_HandleKbdEvent( hwnd, wParam );
+ break;
+
+ case WM_ERASEBKGND:
+ return 1;
+
+ case WM_GETDLGCODE:
+ return DLGC_WANTARROWS; /* Windows returns this value */
+
+ case WM_PAINT:
+ {
+ PAINTSTRUCT ps;
+ HDC hdc = BeginPaint( hwnd, &ps );
+ SCROLL_DrawScrollBar( hwnd, hdc, SB_CTL, TRUE, TRUE );
+ EndPaint( hwnd, &ps );
+ }
+ break;
+
+
+ case SBM_SETPOS:
+ return SetScrollPos( hwnd, SB_CTL, wParam, (BOOL)lParam );
+
+
+ case SBM_GETPOS:
+ return GetScrollPos( hwnd, SB_CTL );
+
+
+ case SBM_SETRANGE:
+ SetScrollRange( hwnd, SB_CTL, wParam, lParam, FALSE );
+ return 0; /* FIXME: return previous position */
+
+
+
+ case SBM_GETRANGE:
+ GetScrollRange( hwnd, SB_CTL, (LPINT)wParam, (LPINT)lParam );
+ return 0;
+
+
+ case SBM_ENABLE_ARROWS:
+ return EnableScrollBar( hwnd, SB_CTL, wParam );
+
+ case SBM_SETRANGEREDRAW:
+ SetScrollRange( hwnd, SB_CTL, wParam, lParam, TRUE );
+ return 0; /* FIXME: return previous position */
+
+ case SBM_SETSCROLLINFO:
+ return SetScrollInfo( hwnd, SB_CTL, (SCROLLINFO *)lParam, wParam );
+
+ case SBM_GETSCROLLINFO:
+ return GetScrollInfo( hwnd, SB_CTL, (SCROLLINFO *)lParam );
+
+ case 0x00e5:
+ case 0x00e7:
+ case 0x00e8:
+ case 0x00eb:
+ case 0x00ec:
+ case 0x00ed:
+ case 0x00ee:
+ case 0x00ef:
+ DPRINT( "unknown Win msg %04x wp=%08x lp=%08lx\n",
+ message, wParam, lParam );
+ break;
+
+ default:
+ if (message >= WM_USER)
+ DPRINT( "unknown msg %04x wp=%04x lp=%08lx\n",
+ message, wParam, lParam );
+ return DefWindowProcA( hwnd, message, wParam, lParam );
+ }
+ return 0;
+}
+
+
+
+
+
+/*************************************************************************
+ * SetScrollInfo (USER.501)
+ * SetScrollInfo can be used to set the position, upper bound,
+ * lower bound, and page size of a scrollbar control.
+ *
+ * RETURNS
+ * Scrollbar position
+ *
+ * NOTE
+ * For 100 lines of text to be displayed in a window of 25 lines,
+ * one would for instance use info->nMin=0, info->nMax=75
+ * (corresponding to the 76 different positions of the window on
+ * the text), and info->nPage=25.
+ */
+INT STDCALL SetScrollInfo( HWND hwnd, INT nBar ,
+const SCROLLINFO *info , BOOL bRedraw )
+{
+ INT action;
+ INT retVal = SCROLL_SetScrollInfo( hwnd, nBar, info, &action );
+
+ if( action & SA_SSI_HIDE )
+ SCROLL_ShowScrollBar( hwnd, nBar, FALSE, FALSE );
+ else
+ {
+ if( action & SA_SSI_SHOW )
+ if( SCROLL_ShowScrollBar( hwnd, nBar, TRUE, TRUE ) )
+ return retVal; /* SetWindowPos() already did the painting */
+
+ if( bRedraw && (action & SA_SSI_REFRESH))
+ SCROLL_RefreshScrollBar( hwnd, nBar, TRUE, TRUE );
+ else if( action & SA_SSI_REPAINT_ARROWS )
+ SCROLL_RefreshScrollBar( hwnd, nBar, TRUE, FALSE );
+ }
+ return retVal;
+}
+
+INT SCROLL_SetScrollInfo( HWND hwnd, INT nBar,
+ const SCROLLINFO *info, INT *action )
+{
+ /* Update the scrollbar state and set action flags according to
+ * what has to be done graphics wise. */
+
+ SCROLLBAR_INFO *infoPtr;
+ UINT new_flags;
+
+// dbg_decl_str(scroll, 256);
+
+ *action = 0;
+
+ if (!(infoPtr = SCROLL_GetScrollInfo(hwnd, nBar))) return 0;
+ if (info->fMask & ~(SIF_ALL | SIF_DISABLENOSCROLL)) return 0;
+ if ((info->cbSize != sizeof(*info)) &&
+ (info->cbSize != sizeof(*info)-sizeof(info->nTrackPos))) return 0;
+
+ /* Set the page size */
+
+ if (info->fMask & SIF_PAGE)
+ {
+ // dsprintf(scroll, " page=%d", info->nPage );
+ if( infoPtr->Page != info->nPage )
+ {
+ infoPtr->Page = info->nPage;
+ *action |= SA_SSI_REFRESH;
+ }
+ }
+
+ /* Set the scroll pos */
+
+ if (info->fMask & SIF_POS)
+ {
+ // dsprintf(scroll, " pos=%d", info->nPos );
+ if( infoPtr->CurVal != info->nPos )
+ {
+ infoPtr->CurVal = info->nPos;
+ *action |= SA_SSI_REFRESH;
+ }
+ }
+
+ /* Set the scroll range */
+
+ if (info->fMask & SIF_RANGE)
+ {
+ // dsprintf(scroll, " min=%d max=%d", info->nMin, info->nMax );
+
+ /* Invalid range -> range is set to (0,0) */
+ if ((info->nMin > info->nMax) ||
+ ((UINT)(info->nMax - info->nMin) >= 0x80000000))
+ {
+ infoPtr->MinVal = 0;
+ infoPtr->MaxVal = 0;
+ }
+ else
+ {
+ if( infoPtr->MinVal != info->nMin ||
+ infoPtr->MaxVal != info->nMax )
+ {
+ *action |= SA_SSI_REFRESH;
+ infoPtr->MinVal = info->nMin;
+ infoPtr->MaxVal = info->nMax;
+ }
+ }
+ }
+
+ DPRINT( "hwnd=%04x bar=%d %s\n",
+ hwnd, nBar, dbg_str(scroll));
+
+ /* Make sure the page size is valid */
+
+ if (infoPtr->Page < 0) infoPtr->Page = 0;
+ else if (infoPtr->Page > infoPtr->MaxVal - infoPtr->MinVal + 1 )
+ infoPtr->Page = infoPtr->MaxVal - infoPtr->MinVal + 1;
+
+ /* Make sure the pos is inside the range */
+
+ if (infoPtr->CurVal < infoPtr->MinVal)
+ infoPtr->CurVal = infoPtr->MinVal;
+ else if (infoPtr->CurVal > infoPtr->MaxVal - MAX( infoPtr->Page-1, 0 ))
+ infoPtr->CurVal = infoPtr->MaxVal - MAX( infoPtr->Page-1, 0 );
+
+ DPRINT( " new values: page=%d pos=%d min=%d max=%d\n",
+ infoPtr->Page, infoPtr->CurVal,
+ infoPtr->MinVal, infoPtr->MaxVal );
+
+ /* Check if the scrollbar should be hidden or disabled */
+
+ if (info->fMask & (SIF_RANGE | SIF_PAGE | SIF_DISABLENOSCROLL))
+ {
+ new_flags = infoPtr->flags;
+ if (infoPtr->MinVal >= infoPtr->MaxVal - MAX( infoPtr->Page-1, 0 ))
+ {
+ /* Hide or disable scroll-bar */
+ if (info->fMask & SIF_DISABLENOSCROLL)
+ {
+ new_flags = ESB_DISABLE_BOTH;
+ *action |= SA_SSI_REFRESH;
+ }
+ else if (nBar != SB_CTL)
+ {
+ *action = SA_SSI_HIDE;
+ goto done;
+ }
+ }
+ else /* Show and enable scroll-bar */
+ {
+ new_flags = 0;
+ if (nBar != SB_CTL)
+ *action |= SA_SSI_SHOW;
+ }
+
+ if (infoPtr->flags != new_flags) /* check arrow flags */
+ {
+ infoPtr->flags = new_flags;
+ *action |= SA_SSI_REPAINT_ARROWS;
+ }
+ }
+
+done:
+ /* Return current position */
+
+ return infoPtr->CurVal;
+}
+
+
+
+
+/*************************************************************************
+ * GetScrollInfo (USER.284)
+ * GetScrollInfo can be used to retrieve the position, upper bound,
+ * lower bound, and page size of a scrollbar control.
+ *
+ * RETURNS STD
+ */
+BOOL STDCALL GetScrollInfo( HWND hwnd ,
+ INT nBar , LPSCROLLINFO info )
+{
+ SCROLLBAR_INFO *infoPtr;
+
+ if (!(infoPtr = SCROLL_GetScrollInfo( hwnd, nBar ))) return FALSE;
+ if (info->fMask & ~(SIF_ALL | SIF_DISABLENOSCROLL)) return FALSE;
+ if ((info->cbSize != sizeof(*info)) &&
+ (info->cbSize != sizeof(*info)-sizeof(info->nTrackPos))) return FALSE;
+
+ if (info->fMask & SIF_PAGE) info->nPage = infoPtr->Page;
+ if (info->fMask & SIF_POS) info->nPos = infoPtr->CurVal;
+ if ((info->fMask & SIF_TRACKPOS) && (info->cbSize == sizeof(*info)))
+ info->nTrackPos = (SCROLL_TrackingWin==hwnd) ? SCROLL_TrackingVal : 0;
+ if (info->fMask & SIF_RANGE)
+ {
+ info->nMin = infoPtr->MinVal;
+ info->nMax = infoPtr->MaxVal;
+ }
+ return (info->fMask & SIF_ALL) != 0;
+}
+
+
+
+
+/*************************************************************************
+ * SetScrollPos (USER.502)
+ *
+ * RETURNS
+ * Success: Scrollbar position
+ * Failure: 0
+ *
+ * REMARKS
+ * Note the ambiguity when 0 is returned. Use GetLastError
+ * to make sure there was an error (and to know which one).
+ */
+INT STDCALL SetScrollPos( HWND hwnd , INT nBar , INT nPos ,BOOL bRedraw )
+{
+ SCROLLINFO info;
+ SCROLLBAR_INFO *infoPtr;
+ INT oldPos;
+
+ if (!(infoPtr = SCROLL_GetScrollInfo( hwnd, nBar ))) return 0;
+ oldPos = infoPtr->CurVal;
+ info.cbSize = sizeof(info);
+ info.nPos = nPos;
+ info.fMask = SIF_POS;
+ SetScrollInfo( hwnd, nBar, &info, bRedraw );
+ return oldPos;
+}
+
+
+
+
+/*************************************************************************
+ * GetScrollPos (USER.285)
+ *
+ * RETURNS
+ * Success: Current position
+ * Failure: 0
+ *
+ * REMARKS
+ * Note the ambiguity when 0 is returned. Use GetLastError
+ * to make sure there was an error (and to know which one).
+ */
+INT STDCALL GetScrollPos( HWND hwnd,INT nBar )
+{
+ SCROLLBAR_INFO *infoPtr;
+
+ if (!(infoPtr = SCROLL_GetScrollInfo( hwnd, nBar ))) return 0;
+ return infoPtr->CurVal;
+}
+
+
+
+
+/*************************************************************************
+ * SetScrollRange (USER.503)
+ *
+ * RETURNS STD
+ */
+BOOL STDCALL SetScrollRange( HWND hwnd, INT nBar,
+INT MinVal, INT MaxVal, BOOL bRedraw )
+{
+ SCROLLINFO info;
+
+ info.cbSize = sizeof(info);
+ info.nMin = MinVal;
+ info.nMax = MaxVal;
+ info.fMask = SIF_RANGE;
+ SetScrollInfo( hwnd, nBar, &info, bRedraw );
+ return TRUE;
+}
+
+
+/*************************************************************************
+ * SCROLL_SetNCSbState
+ *
+ * Updates both scrollbars at the same time. Used by MDI CalcChildScroll().
+ */
+INT SCROLL_SetNCSbState(WND* wndPtr, int vMin, int vMax, int vPos,
+ int hMin, int hMax, int hPos)
+{
+ INT vA, hA;
+ SCROLLINFO vInfo, hInfo;
+
+ vInfo.cbSize = hInfo.cbSize = sizeof(SCROLLINFO);
+ vInfo.nMin = vMin; hInfo.nMin = hMin;
+ vInfo.nMax = vMax; hInfo.nMax = hMax;
+ vInfo.nPos = vPos; hInfo.nPos = hPos;
+ vInfo.fMask = hInfo.fMask = SIF_RANGE | SIF_POS;
+
+ SCROLL_SetScrollInfo( wndPtr->hwndSelf, SB_VERT, &vInfo, &vA );
+ SCROLL_SetScrollInfo( wndPtr->hwndSelf, SB_HORZ, &hInfo, &hA );
+
+ if( !SCROLL_ShowScrollBar( wndPtr->hwndSelf, SB_BOTH,
+ (hA & SA_SSI_SHOW),(vA & SA_SSI_SHOW) ) )
+ {
+ /* SetWindowPos() wasn't called, just redraw the scrollbars if needed */
+ if( vA & SA_SSI_REFRESH )
+ SCROLL_RefreshScrollBar( wndPtr->hwndSelf, SB_VERT, FALSE, TRUE );
+
+ if( hA & SA_SSI_REFRESH )
+ SCROLL_RefreshScrollBar( wndPtr->hwndSelf, SB_HORZ, FALSE, TRUE );
+ }
+ return 0;
+}
+
+
+
+
+/*************************************************************************
+ * GetScrollRange (USER.286)
+ *
+ * RETURNS STD
+ */
+BOOL STDCALL GetScrollRange( HWND hwnd, INT nBar,
+ LPINT lpMin,LPINT lpMax )
+{
+ SCROLLBAR_INFO *infoPtr;
+
+ if (!(infoPtr = SCROLL_GetScrollInfo( hwnd, nBar )))
+ {
+ if (lpMin) lpMin = 0;
+ if (lpMax) lpMax = 0;
+ return FALSE;
+ }
+ if (lpMin) *lpMin = infoPtr->MinVal;
+ if (lpMax) *lpMax = infoPtr->MaxVal;
+ return TRUE;
+}
+
+
+/*************************************************************************
+ * SCROLL_ShowScrollBar()
+ *
+ * Back-end for ShowScrollBar(). Returns FALSE if no action was taken.
+ * NOTE: fShowV/fShowH must be zero when nBar is SB_HORZ/SB_VERT.
+ */
+BOOL SCROLL_ShowScrollBar( HWND hwnd, INT nBar,
+ BOOL fShowH, BOOL fShowV )
+{
+ WND *wndPtr = WIN_FindWndPtr( hwnd );
+
+ if (!wndPtr) return FALSE;
+ DPRINT( "hwnd=%04x bar=%d horz=%d, vert=%d\n",
+ hwnd, nBar, fShowH, fShowV );
+
+ switch(nBar)
+ {
+ case SB_CTL:
+ ShowWindow( hwnd, fShowH ? SW_SHOW : SW_HIDE );
+ return TRUE;
+
+ case SB_BOTH:
+ case SB_HORZ:
+ if (fShowH)
+ {
+ fShowH = !(wndPtr->dwStyle & WS_HSCROLL);
+ wndPtr->dwStyle |= WS_HSCROLL;
+ }
+ else /* hide it */
+ {
+ fShowH = (wndPtr->dwStyle & WS_HSCROLL);
+ wndPtr->dwStyle &= ~WS_HSCROLL;
+ }
+ if( nBar == SB_HORZ ) break;
+ /* fall through */
+
+ case SB_VERT:
+ if (fShowV)
+ {
+ fShowV = !(wndPtr->dwStyle & WS_VSCROLL);
+ wndPtr->dwStyle |= WS_VSCROLL;
+ }
+ else /* hide it */
+ {
+ fShowV = (wndPtr->dwStyle & WS_VSCROLL);
+ wndPtr->dwStyle &= ~WS_VSCROLL;
+ }
+ break;
+
+ default:
+ return FALSE; /* Nothing to do! */
+ }
+
+ if( fShowH || fShowV ) /* frame has been changed, let the window redraw itself */
+ {
+ SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE
+ | SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
+ return TRUE;
+ }
+
+ return FALSE; /* no frame changes */
+}
+
+
+
+/*************************************************************************
+ * SCROLL_FixCaret
+ */
+WINBOOL SCROLL_FixCaret(HWND hWnd, LPRECT lprc, UINT flags)
+{
+ HWND hCaret = CARET_GetHwnd();
+
+ if( hCaret )
+ {
+ RECT rc;
+ CARET_GetRect( &rc );
+ if( hCaret == hWnd ||
+ (flags & SW_SCROLLCHILDREN && IsChild(hWnd, hCaret)) )
+ {
+ POINT pt;
+
+ pt.x = rc.left; pt.y = rc.top;
+ MapWindowPoints( hCaret, hWnd, (LPPOINT)&rc, 2 );
+ if( IntersectRect(lprc, lprc, &rc) )
+ {
+ HideCaret(0);
+ lprc->left = pt.x; lprc->top = pt.y;
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+}
+
+/*************************************************************************
+ * ShowScrollBar (USER.5)
+ *
+ * RETURNS STD
+ */
+BOOL STDCALL ShowScrollBar(
+ HWND hwnd, INT nBar, BOOL fShow )
+{
+ SCROLL_ShowScrollBar( hwnd, nBar, (nBar == SB_VERT) ? 0 : fShow,
+ (nBar == SB_HORZ) ? 0 : fShow );
+ return TRUE;
+}
+
+
+
+
+/*************************************************************************
+ * EnableScrollBar (USER.171)
+ */
+WINBOOL
+STDCALL
+EnableScrollBar(HWND hWnd,UINT wSBflags, UINT wArrows)
+{
+ BOOL bFineWithMe;
+ SCROLLBAR_INFO *infoPtr;
+
+ DPRINT( "%04x %d %d\n", hwnd, nBar, flags );
+
+ wArrows &= ESB_DISABLE_BOTH;
+
+ if (wSBflags == SB_BOTH)
+ {
+ if (!(infoPtr = SCROLL_GetScrollInfo( hWnd, SB_VERT ))) return FALSE;
+ if (!(bFineWithMe = (infoPtr->flags == wArrows)) )
+ {
+ infoPtr->flags = wArrows;
+ SCROLL_RefreshScrollBar( hWnd, SB_VERT, TRUE, TRUE );
+ }
+ wSBflags = SB_HORZ;
+ }
+ else
+ bFineWithMe = TRUE;
+
+ if (!(infoPtr = SCROLL_GetScrollInfo( hWnd, wSBflags ))) return FALSE;
+ if (bFineWithMe && infoPtr->flags == wArrows) return FALSE;
+ infoPtr->flags = wArrows;
+
+ SCROLL_RefreshScrollBar( hWnd, wSBflags, TRUE, TRUE );
+ return TRUE;
+}
--- /dev/null
+/*
+ * Static control
+ *
+ * Copyright David W. Metcalfe, 1993
+ *
+ */
+
+#include <windows.h>
+#include <user32/win.h>
+#include <user32/static.h>
+#include <user32/debug.h>
+#include <user32/syscolor.h>
+#include <user32/nc.h>
+#include <user32/defwnd.h>
+
+
+/* Static Control Styles */
+
+
+
+
+//#define SS_ETCHEDHORZ 0x00000010L
+//#define SS_ETCHEDVERT 0x00000011L
+//#define SS_ETCHEDFRAME 0x00000012L
+#define SS_TYPEMASK 0x0000001FL
+
+//#define SS_NOPREFIX 0x00000080L
+//#define SS_NOTIFY 0x00000100L
+//#define SS_CENTERIMAGE 0x00000200L
+//#define SS_RIGHTJUST 0x00000400L
+//#define SS_REALSIZEIMAGE 0x00000800L
+//#define SS_SUNKEN 0x00001000L
+
+/* Static Control Messages */
+
+//#define STM_SETICON 0x0170
+//#define STM_GETICON 0x0171
+//#define STM_SETIMAGE 0x0172
+//#define STM_GETIMAGE 0x0173
+
+static void STATIC_PaintTextfn( WND *wndPtr, HDC hdc );
+static void STATIC_PaintRectfn( WND *wndPtr, HDC hdc );
+static void STATIC_PaintIconfn( WND *wndPtr, HDC hdc );
+static void STATIC_PaintBitmapfn( WND *wndPtr, HDC hdc );
+static void STATIC_PaintEtchedfn( WND *wndPtr, HDC hdc );
+
+static COLORREF color_windowframe, color_background, color_window;
+
+
+typedef void (*pfPaint)( WND *, HDC );
+
+static pfPaint staticPaintFunc[SS_TYPEMASK+1] =
+{
+ STATIC_PaintTextfn, /* SS_LEFT */
+ STATIC_PaintTextfn, /* SS_CENTER */
+ STATIC_PaintTextfn, /* SS_RIGHT */
+ STATIC_PaintIconfn, /* SS_ICON */
+ STATIC_PaintRectfn, /* SS_BLACKRECT */
+ STATIC_PaintRectfn, /* SS_GRAYRECT */
+ STATIC_PaintRectfn, /* SS_WHITERECT */
+ STATIC_PaintRectfn, /* SS_BLACKFRAME */
+ STATIC_PaintRectfn, /* SS_GRAYFRAME */
+ STATIC_PaintRectfn, /* SS_WHITEFRAME */
+ NULL, /* Not defined */
+ STATIC_PaintTextfn, /* SS_SIMPLE */
+ STATIC_PaintTextfn, /* SS_LEFTNOWORDWRAP */
+ NULL, /* SS_OWNERDRAW */
+ STATIC_PaintBitmapfn, /* SS_BITMAP */
+ NULL, /* SS_ENHMETAFILE */
+ STATIC_PaintEtchedfn, /* SS_ETCHEDHORIZ */
+ STATIC_PaintEtchedfn, /* SS_ETCHEDVERT */
+ STATIC_PaintEtchedfn, /* SS_ETCHEDFRAME */
+};
+
+HICON STATIC_LoadIcon(WND *wndPtr,const void *name )
+{
+ HICON hIcon;
+ if ( wndPtr->class->bUnicode ) {
+ hIcon = LoadIconW(wndPtr->hInstance,(LPCWSTR)name);
+ }
+ else
+ hIcon = LoadIconA(wndPtr->hInstance,(LPCSTR)name);
+
+ return hIcon;
+}
+
+/***********************************************************************
+ * STATIC_SetIcon
+ *
+ * Set the icon for an SS_ICON control.
+ */
+HICON STATIC_SetIcon( WND *wndPtr, HICON hicon )
+{
+ HICON prevIcon;
+ STATICINFO *infoPtr = (STATICINFO *)wndPtr->wExtra;
+ ICONINFO iconinfo;
+ BITMAP info;
+
+ if ( !GetIconInfo(hicon, &iconinfo ) )
+ return NULL;
+
+ if ( iconinfo.hbmColor )
+ GetObject(iconinfo.hbmColor, sizeof(BITMAP),&info);
+ else
+ GetObject(iconinfo.hbmMask, sizeof(BITMAP),&info);
+
+ if ((wndPtr->dwStyle & SS_TYPEMASK) != SS_ICON) return 0;
+
+ prevIcon = infoPtr->hIcon;
+ infoPtr->hIcon = hicon;
+ if (hicon)
+ {
+ SetWindowPos( wndPtr->hwndSelf, 0, 0, 0, info.bmWidth, info.bmHeight,
+ SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER );
+ }
+ return prevIcon;
+}
+
+
+HBITMAP STATIC_LoadBitmap(WND *wndPtr,const void *name )
+{
+ HBITMAP hBitmap;
+ if ( wndPtr->class->bUnicode ) {
+ hBitmap = LoadBitmapW(wndPtr->hInstance,(LPCWSTR)name);
+ }
+ else
+ hBitmap = LoadBitmapA(wndPtr->hInstance,(LPCSTR)name);
+ return hBitmap;
+}
+/***********************************************************************
+ * STATIC_SetBitmap
+ *
+ * Set the bitmap for an SS_BITMAP control.
+ */
+HICON STATIC_SetBitmap( WND *wndPtr, HICON hicon )
+{
+
+ HICON prevIcon;
+ STATICINFO *infoPtr = (STATICINFO *)wndPtr->wExtra;
+ BITMAP info;
+
+ if ( hicon == NULL )
+ return NULL;
+
+ GetObject(hicon, sizeof(BITMAP),&info);
+
+ if ((wndPtr->dwStyle & SS_TYPEMASK) != SS_BITMAP) return 0;
+
+ prevIcon = infoPtr->hIcon;
+ infoPtr->hIcon = hicon;
+ if (hicon)
+ {
+ SetWindowPos( wndPtr->hwndSelf, 0, 0, 0, info.bmWidth, info.bmHeight,
+ SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER );
+ }
+
+ return prevIcon;
+
+}
+
+
+
+
+/***********************************************************************
+ * StaticWndProc
+ */
+LRESULT WINAPI StaticWndProc( HWND hWnd, UINT uMsg, WPARAM wParam,
+ LPARAM lParam )
+{
+ LRESULT lResult = 0;
+ WND *wndPtr = WIN_FindWndPtr(hWnd);
+ LONG style = wndPtr->dwStyle & SS_TYPEMASK;
+ STATICINFO *infoPtr = (STATICINFO *)wndPtr->wExtra;
+
+ switch (uMsg)
+ {
+ case WM_NCCREATE: {
+ CREATESTRUCT *cs = (CREATESTRUCT *)lParam;
+
+ if ((TWEAK_WineLook > WIN31_LOOK) && (wndPtr->dwStyle & SS_SUNKEN))
+ wndPtr->dwExStyle |= WS_EX_STATICEDGE;
+
+ if (style == SS_ICON)
+ {
+ if (cs->lpszName) {
+ STATIC_SetIcon( wndPtr,STATIC_LoadIcon(wndPtr,cs->lpszName));
+ }
+ return 1;
+ }
+ if (style == SS_BITMAP)
+ {
+ if (cs->lpszName) {
+ STATIC_SetBitmap( wndPtr,STATIC_LoadBitmap(wndPtr,cs->lpszName));
+ }
+ return 1;
+ }
+
+ if ( wndPtr->class->bUnicode )
+ return DefWindowProcW( hWnd, uMsg, wParam, lParam );
+ else
+ return DefWindowProcA( hWnd, uMsg, wParam, lParam );
+ }
+ case WM_CREATE:
+ if (style < 0L || style > SS_TYPEMASK)
+ {
+ DPRINT( "Unknown style 0x%02lx\n", style );
+ lResult = -1L;
+ break;
+ }
+ /* initialise colours */
+ color_windowframe = GetSysColor(COLOR_WINDOWFRAME);
+ color_background = GetSysColor(COLOR_BACKGROUND);
+ color_window = GetSysColor(COLOR_WINDOW);
+ break;
+
+ case WM_NCDESTROY:
+ if (style == SS_ICON) {
+/*
+ * FIXME
+ * DestroyIcon( STATIC_SetIcon( wndPtr, 0 ) );
+ *
+ * We don't want to do this yet because DestroyIcon is broken. If the icon
+ * had already been loaded by the application the last thing we want to do is
+ * GlobalFree the handle.
+ */
+ } else {
+ if ( wndPtr->class->bUnicode )
+ lResult = DefWindowProcW( hWnd, uMsg, wParam, lParam );
+ else
+ lResult = DefWindowProcA( hWnd, uMsg, wParam, lParam );
+
+ }
+ break;
+
+ case WM_PAINT:
+ {
+ PAINTSTRUCT ps;
+ BeginPaint( hWnd, &ps );
+ if (staticPaintFunc[style])
+ (staticPaintFunc[style])( wndPtr, ps.hdc );
+ EndPaint( hWnd, &ps );
+ }
+ break;
+
+ case WM_ENABLE:
+ InvalidateRect( hWnd, NULL, FALSE );
+ break;
+
+ case WM_SYSCOLORCHANGE:
+ color_windowframe = GetSysColor(COLOR_WINDOWFRAME);
+ color_background = GetSysColor(COLOR_BACKGROUND);
+ color_window = GetSysColor(COLOR_WINDOW);
+ InvalidateRect( hWnd, NULL, TRUE );
+ break;
+
+ case WM_SETTEXT:
+ if (style == SS_ICON)
+ {
+ if (lParam) {
+ STATIC_SetIcon( wndPtr,STATIC_LoadIcon(wndPtr,(const void *)lParam));
+ }
+
+ }
+ else if (style == SS_BITMAP)
+ {
+ if (lParam) {
+ STATIC_SetBitmap( wndPtr,STATIC_LoadBitmap(wndPtr,(const void *)lParam));
+ }
+
+ }
+ else {
+ DEFWND_SetText( wndPtr, (const void *)lParam );
+
+ }
+ InvalidateRect( hWnd, NULL, FALSE );
+ UpdateWindow( hWnd );
+ break;
+
+ case WM_SETFONT:
+ if (style == SS_ICON) return 0;
+ if (style == SS_BITMAP) return 0;
+ infoPtr->hFont = (HFONT)wParam;
+ if (LOWORD(lParam))
+ {
+ InvalidateRect( hWnd, NULL, FALSE );
+ UpdateWindow( hWnd );
+ }
+ break;
+
+ case WM_GETFONT:
+ return infoPtr->hFont;
+
+ case WM_NCHITTEST:
+ return HTTRANSPARENT;
+
+ case WM_GETDLGCODE:
+ return DLGC_STATIC;
+
+ case STM_GETIMAGE:
+ case STM_GETICON:
+ return infoPtr->hIcon;
+
+ case STM_SETIMAGE:
+ /* FIXME: handle wParam */
+ lResult = STATIC_SetBitmap( wndPtr, (HBITMAP)lParam );
+ InvalidateRect( hWnd, NULL, FALSE );
+ UpdateWindow( hWnd );
+ break;
+
+
+ case STM_SETICON:
+ lResult = STATIC_SetIcon( wndPtr, (HICON)wParam );
+ InvalidateRect( hWnd, NULL, FALSE );
+ UpdateWindow( hWnd );
+ break;
+
+ default:
+ if ( wndPtr->class->bUnicode )
+ lResult = DefWindowProcW( hWnd, uMsg, wParam, lParam );
+ else
+ lResult = DefWindowProcA( hWnd, uMsg, wParam, lParam );
+ break;
+ }
+
+ return lResult;
+}
+
+
+static void STATIC_PaintTextfn( WND *wndPtr, HDC hdc )
+{
+ RECT rc;
+ HBRUSH hBrush;
+ WORD wFormat;
+
+ LONG style = wndPtr->dwStyle;
+ STATICINFO *infoPtr = (STATICINFO *)wndPtr->wExtra;
+
+ GetClientRect( wndPtr->hwndSelf, &rc);
+
+ switch (style & SS_TYPEMASK)
+ {
+ case SS_LEFT:
+ wFormat = DT_LEFT | DT_EXPANDTABS | DT_WORDBREAK | DT_NOCLIP;
+ break;
+
+ case SS_CENTER:
+ wFormat = DT_CENTER | DT_EXPANDTABS | DT_WORDBREAK | DT_NOCLIP;
+ break;
+
+ case SS_RIGHT:
+ wFormat = DT_RIGHT | DT_EXPANDTABS | DT_WORDBREAK | DT_NOCLIP;
+ break;
+
+ case SS_SIMPLE:
+ wFormat = DT_LEFT | DT_SINGLELINE | DT_VCENTER | DT_NOCLIP;
+ break;
+
+ case SS_LEFTNOWORDWRAP:
+ wFormat = DT_LEFT | DT_SINGLELINE | DT_EXPANDTABS | DT_VCENTER | DT_NOCLIP;
+ break;
+
+ default:
+ return;
+ }
+
+ if (style & SS_NOPREFIX)
+ wFormat |= DT_NOPREFIX;
+
+ if (infoPtr->hFont) SelectObject( hdc, infoPtr->hFont );
+ hBrush = MSG_SendMessage( wndPtr->parent, WM_CTLCOLORSTATIC,
+ (WPARAM)hdc,(LPARAM) wndPtr->hwndSelf );
+ if (!hBrush) hBrush = GetStockObject(WHITE_BRUSH);
+ FillRect( hdc, &rc, hBrush );
+ if (wndPtr->text) {
+ if ( wndPtr->class->bUnicode ) {
+ DrawTextW( hdc, wndPtr->text, -1, &rc, wFormat );
+ }
+ else {
+ DrawTextA( hdc, wndPtr->text, -1, &rc, wFormat );
+ }
+ }
+
+}
+
+
+static void STATIC_PaintRectfn( WND *wndPtr, HDC hdc )
+{
+ RECT rc;
+ HBRUSH hBrush;
+
+ GetClientRect( wndPtr->hwndSelf, &rc);
+
+ switch (wndPtr->dwStyle & SS_TYPEMASK)
+ {
+ case SS_BLACKRECT:
+ hBrush = CreateSolidBrush(color_windowframe);
+ FillRect( hdc, &rc, hBrush );
+ break;
+ case SS_GRAYRECT:
+ hBrush = CreateSolidBrush(color_background);
+ FillRect( hdc, &rc, hBrush );
+ break;
+ case SS_WHITERECT:
+ hBrush = CreateSolidBrush(color_window);
+ FillRect( hdc, &rc, hBrush );
+ break;
+ case SS_BLACKFRAME:
+ hBrush = CreateSolidBrush(color_windowframe);
+ FrameRect( hdc, &rc, hBrush );
+ break;
+ case SS_GRAYFRAME:
+ hBrush = CreateSolidBrush(color_background);
+ FrameRect( hdc, &rc, hBrush );
+ break;
+ case SS_WHITEFRAME:
+ hBrush = CreateSolidBrush(color_window);
+ FrameRect( hdc, &rc, hBrush );
+ break;
+ default:
+ return;
+ }
+ DeleteObject( hBrush );
+}
+
+
+static void STATIC_PaintIconfn( WND *wndPtr, HDC hdc )
+{
+ RECT rc;
+ HBRUSH hbrush;
+ STATICINFO *infoPtr = (STATICINFO *)wndPtr->wExtra;
+
+ GetClientRect( wndPtr->hwndSelf, &rc );
+ hbrush = MSG_SendMessage( wndPtr->parent, WM_CTLCOLORSTATIC,
+ (WPARAM)hdc, (LPARAM)wndPtr->hwndSelf );
+ FillRect( hdc, &rc, hbrush );
+ if (infoPtr->hIcon) DrawIcon( hdc, rc.left, rc.top, infoPtr->hIcon );
+}
+
+static void STATIC_PaintBitmapfn(WND *wndPtr, HDC hdc )
+{
+ RECT rc;
+ HBRUSH hbrush;
+ STATICINFO *infoPtr = (STATICINFO *)wndPtr->wExtra;
+ HDC hMemDC;
+ HBITMAP oldbitmap;
+
+ GetClientRect( wndPtr->hwndSelf, &rc );
+ hbrush = MSG_SendMessage( wndPtr->parent, WM_CTLCOLORSTATIC,
+ (WPARAM)hdc,(LPARAM) wndPtr->hwndSelf );
+ FillRect( hdc, &rc, hbrush );
+ if (infoPtr->hIcon) {
+ BITMAP bmp;
+ GetObject( infoPtr->hIcon, sizeof(BITMAP),&bmp);
+
+ if (!(hMemDC = CreateCompatibleDC( hdc ))) return;
+
+ oldbitmap = SelectObject(hMemDC,infoPtr->hIcon);
+ BitBlt(hdc,bmp.bmWidth,bmp.bmHeight,bmp.bmWidth,bmp.bmHeight,hMemDC,0,0,SRCCOPY);
+// BitBlt(hdc,bmp.size.cx,bmp.size.cy,bmp.bmWidth,bmp.bmHeight,hMemDC,0,0,SRCCOPY);
+ DeleteDC(hMemDC);
+
+ }
+}
+
+
+static void STATIC_PaintEtchedfn( WND *wndPtr, HDC hdc )
+{
+ RECT rc;
+ HBRUSH hbrush;
+ HPEN hpen;
+
+ if (TWEAK_WineLook == WIN31_LOOK)
+ return;
+
+ GetClientRect( wndPtr->hwndSelf, &rc );
+ hbrush = MSG_SendMessage( wndPtr->parent, WM_CTLCOLORSTATIC,
+ (WPARAM)hdc, (LPARAM)wndPtr->hwndSelf );
+ FillRect( hdc, &rc, hbrush );
+
+ switch (wndPtr->dwStyle & SS_TYPEMASK)
+ {
+ case SS_ETCHEDHORZ:
+ hpen = SelectObject (hdc, GetSysColorPen (COLOR_3DSHADOW));
+ MoveToEx (hdc, rc.left, rc.bottom / 2 - 1, NULL);
+ LineTo (hdc, rc.right - 1, rc.bottom / 2 - 1);
+ SelectObject (hdc, GetSysColorPen (COLOR_3DHIGHLIGHT));
+ MoveToEx (hdc, rc.left, rc.bottom / 2, NULL);
+ LineTo (hdc, rc.right, rc.bottom / 2);
+ LineTo (hdc, rc.right, rc.bottom / 2 - 1);
+ SelectObject (hdc, hpen);
+ break;
+
+ case SS_ETCHEDVERT:
+ hpen = SelectObject (hdc, GetSysColorPen (COLOR_3DSHADOW));
+ MoveToEx (hdc, rc.right / 2 - 1, rc.top, NULL);
+ LineTo (hdc, rc.right / 2 - 1, rc.bottom - 1);
+ SelectObject (hdc, GetSysColorPen (COLOR_3DHIGHLIGHT));
+ MoveToEx (hdc, rc.right / 2, rc.top, NULL);
+ LineTo (hdc, rc.right / 2, rc.bottom);
+ LineTo (hdc, rc.right / 2 -1 , rc.bottom);
+ SelectObject (hdc, hpen);
+ break;
+
+ case SS_ETCHEDFRAME:
+ DrawEdge (hdc, &rc, EDGE_ETCHED, BF_RECT);
+ break;
+ }
+}
+
--- /dev/null
+/*
+ * Windows widgets (built-in window classes)
+ *
+ * Copyright 1993 Alexandre Julliard
+ */
+
+#define UNICODE
+#include <windows.h>
+#include <user32/widgets.h>
+#include <user32/win.h>
+#include <user32/button.h>
+#include <user32/scroll.h>
+#include <user32/static.h>
+#include <user32/mdi.h>
+#include <user32/dialog.h>
+#include <user32/heapdup.h>
+
+
+/* Built-in classes */
+
+#define DLGWINDOWEXTRA sizeof(DIALOGINFO)
+
+
+static WNDCLASS WIDGETS_BuiltinClasses[BIC_NB_CLASSES+1] =
+{
+ /* BIC_BUTTON */
+ { CS_GLOBALCLASS | CS_DBLCLKS | CS_VREDRAW | CS_HREDRAW | CS_PARENTDC,
+ ButtonWndProc, 0, sizeof(BUTTONINFO), 0, 0,
+ (HCURSOR)IDC_ARROW, 0, 0, BUTTON_CLASS_NAME },
+ /* BIC_EDIT */
+ { CS_GLOBALCLASS | CS_DBLCLKS /*| CS_PARENTDC*/,
+ EditWndProc, 0, sizeof(void *), 0, 0,
+ (HCURSOR)IDC_IBEAM, 0, 0, EDIT_CLASS_NAME },
+ /* BIC_LISTBOX */
+ { CS_GLOBALCLASS | CS_DBLCLKS /*| CS_PARENTDC*/,
+ ListBoxWndProc, 0, sizeof(void *), 0, 0,
+ (HCURSOR)IDC_ARROW, 0, 0, LISTBOX_CLASS_NAME },
+ /* BIC_COMBO */
+ { CS_GLOBALCLASS | CS_PARENTDC | CS_DBLCLKS,
+ ComboWndProc, 0, sizeof(void *), 0, 0,
+ (HCURSOR)IDC_ARROW, 0, 0, COMBOBOX_CLASS_NAME },
+ /* BIC_COMBOLB */
+ { CS_GLOBALCLASS | CS_DBLCLKS | CS_SAVEBITS, ComboLBWndProc,
+ 0, sizeof(void *), 0, 0, (HCURSOR)IDC_ARROW, 0, 0,COMBOLBOX_CLASS_NAME},
+ /* BIC_POPUPMENU */
+// { CS_GLOBALCLASS | CS_SAVEBITS, PopupMenuWndProc, 0, sizeof(HMENU),
+// 0, 0, (HCURSOR)IDC_ARROW, NULL_BRUSH, 0, POPUPMENU_CLASS_NAME },
+ /* BIC_STATIC */
+ { CS_GLOBALCLASS | CS_PARENTDC, StaticWndProc,
+ 0, sizeof(STATICINFO), 0, 0, (HCURSOR)IDC_ARROW, 0, 0, STATIC_CLASS_NAME },
+ /* BIC_SCROLL */
+ { CS_GLOBALCLASS | CS_DBLCLKS | CS_VREDRAW | CS_HREDRAW | CS_PARENTDC,
+ ScrollBarWndProc, 0, sizeof(SCROLLBAR_INFO), 0, 0,
+ (HCURSOR)IDC_ARROW, 0, 0, SCROLLBAR_CLASS_NAME},
+ /* BIC_MDICLIENT */
+// { CS_GLOBALCLASS, MDIClientWndProc,
+// 0, sizeof(MDICLIENTINFO), 0, 0, 0, LTGRAY_BRUSH, 0, "MDIClient" },
+ /* BIC_DESKTOP */
+ // { CS_GLOBALCLASS, DesktopWndProc, 0, sizeof(DESKTOPINFO),
+ // 0, 0, (HCURSOR)IDC_ARROW, 0, 0, DESKTOP_CLASS_NAME },
+ /* BIC_DIALOG */
+ { CS_GLOBALCLASS | CS_SAVEBITS, DefDlgProc, 100, 100,
+ 0, 0, (HCURSOR)IDC_ARROW, 0, 0, DIALOG_CLASS_NAMEW },
+ /* BIC_ICONTITLE */
+ { CS_GLOBALCLASS, IconTitleWndProc, 0, 0,
+ 0, 0, (HCURSOR)IDC_ARROW, 0, 0, ICONTITLE_CLASS_NAME },
+ /* BIC_DIALOG Ascii */
+ { CS_GLOBALCLASS, DefDlgProcA, 100, 100,
+ 0, 0, (HCURSOR)IDC_ARROW, 0, 0, (LPWSTR)DIALOG_CLASS_NAME_A }
+};
+
+
+static ATOM bicAtomTable[BIC_NB_CLASSES+1];
+
+/***********************************************************************
+ * WIDGETS_Init
+ *
+ * Initialize the built-in window classes.
+ */
+WINBOOL WIDGETS_Init(void)
+{
+ int i;
+ WNDCLASS *cls = WIDGETS_BuiltinClasses;
+
+ /* Create builtin classes */
+
+ for (i = 0; i < BIC_NB_CLASSES; i++)
+ {
+
+ cls[i].hCursor = LoadCursorW( 0, (LPCWSTR)cls[i].hCursor );
+ if (!(bicAtomTable[i] = RegisterClassW( &cls[i] ))) return FALSE;
+ }
+
+ cls[i].hCursor = LoadCursorW( 0, (LPCWSTR)cls[i].hCursor );
+ if (!(bicAtomTable[i] = RegisterClassA( &cls[i] ))) return FALSE;
+
+
+ return TRUE;
+}
+
+
+/***********************************************************************
+ * WIDGETS_IsControl
+ *
+ * Check whether pWnd is a built-in control or not.
+ */
+WINBOOL WIDGETS_IsControl( WND* pWnd, BUILTIN_CLASS cls )
+{
+ if( cls >= BIC_NB_CLASSES )
+ return FALSE;
+ return (pWnd->class->atomName == bicAtomTable[cls]);
+}
#include <windows.h>
+
+INT STDCALL FrameRect( HDC hdc, const RECT *rect, HBRUSH hbrush )
+{
+ HBRUSH prevBrush;
+ //int left, top, right, bottom;
+
+ if ( hdc == NULL )
+ return 0;
+
+ //left = XLPTODP( dc, rect->left );
+ //top = YLPTODP( dc, rect->top );
+ //right = XLPTODP( dc, rect->right );
+ //bottom = YLPTODP( dc, rect->bottom );
+
+ //if ( (right <= left) || (bottom <= top) ) return 0;
+ if (!(prevBrush = SelectObject( hdc, hbrush ))) return 0;
+
+ PatBlt( hdc, rect->left, rect->top, 1,
+ rect->bottom - rect->top, PATCOPY );
+ PatBlt( hdc, rect->right - 1, rect->top, 1,
+ rect->bottom - rect->top, PATCOPY );
+ PatBlt( hdc, rect->left, rect->top,
+ rect->right - rect->left, 1, PATCOPY );
+ PatBlt( hdc, rect->left, rect->bottom - 1,
+ rect->right - rect->left, 1, PATCOPY );
+
+ SelectObject( hdc, prevBrush );
+ return 1;
+}
+
+
INT STDCALL FillRect( HDC hdc, const RECT *rect, HBRUSH hbrush )
{
HBRUSH prevBrush;
#include <windows.h>
+#include <user32/static.h>
+HICON LoadStandardIcon(UINT IconId);
HICON
STDCALL
HICON
STDCALL
CreateIconIndirect(
- PICONINFO piconinfo)
+ PICONINFO lpIconInfo)
{
+ BITMAP bmpXor,bmpAnd;
+ HICON hObj;
+ int sizeXor,sizeAnd;
+
+ GetObject(lpIconInfo->hbmColor,sizeof(BITMAP),&bmpXor);
+ GetObject(lpIconInfo->hbmMask,sizeof(BITMAP),&bmpAnd);
+
+
+
+ sizeXor = bmpXor.bmHeight * bmpXor.bmWidthBytes;
+ sizeAnd = bmpAnd.bmHeight * bmpAnd.bmWidthBytes;
+
+ hObj = GlobalAlloc( GMEM_MOVEABLE,
+ sizeof(ICONINFO) + sizeXor + sizeAnd );
+ if (hObj)
+ {
+ ICONINFO *info;
+
+ info = (ICONINFO *)( hObj );
+ info->xHotspot = lpIconInfo->xHotspot;
+ info->yHotspot = lpIconInfo->yHotspot;
+ //info->nWidth = bmpXor.bmWidth;
+ //info->nHeight = bmpXor.bmHeight;
+ //info->nWidthBytes = bmpXor.bmWidthBytes;
+ //info->bPlanes = bmpXor.bmPlanes;
+ //info->bBitsPerPixel = bmpXor.bmBitsPixel;
+
+ /* Transfer the bitmap bits to the CURSORICONINFO structure */
+
+ GetBitmapBits( lpIconInfo->hbmMask ,sizeAnd,(char*)(info + 1) );
+ GetBitmapBits( lpIconInfo->hbmColor,sizeXor,(char*)(info + 1) +sizeAnd);
+
+ }
+ return hObj;
}
HICON LoadIconA(HINSTANCE hInstance,LPCSTR lpIconName )
{
- return CreateIcon(hInstance, GetSystemMetrics(SM_CXSMICON),
- GetSystemMetrics(SM_CYSMICON),
- 0,0,NULL,NULL);
+ HRSRC hrsrc;
+ ICONINFO *IconInfo;
+
+ if ( hInstance == NULL ) {
+ return LoadStandardIcon((UINT)lpIconName);
+ }
+//RT_GROUP_ICON
+hrsrc = FindResourceExA(hInstance,RT_GROUP_ICON, lpIconName, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL));
+
+ if ( hrsrc == NULL )
+ return NULL;
+
+ IconInfo = (ICONINFO *)LoadResource(hInstance, hrsrc);
+ if ( IconInfo != NULL || IconInfo->fIcon == FALSE )
+ return NULL;
+
+ return CreateIconIndirect(IconInfo);
}
HICON LoadIconW(HINSTANCE hInstance,LPCWSTR lpIconName )
{
- return CreateIcon(hInstance, GetSystemMetrics(SM_CXSMICON),
- GetSystemMetrics(SM_CYSMICON),
- 0,0,NULL,NULL);
+ HRSRC hrsrc;
+ ICONINFO *IconInfo;
+
+ if ( hInstance == NULL ) {
+ return LoadStandardIcon((UINT)lpIconName);
+ }
+
+ hrsrc = FindResourceW(hInstance,lpIconName,RT_GROUP_ICON);
+ if ( hrsrc == NULL )
+ return NULL;
+
+ IconInfo = (ICONINFO *)LoadResource(hInstance, hrsrc);
+ if ( IconInfo != NULL || IconInfo->fIcon == FALSE )
+ return NULL;
+
+ return CreateIconIndirect(IconInfo);
+}
+
+HICON LoadStandardIcon(UINT IconId)
+{
+ HMODULE hModule = LoadLibraryA("user32.dll");
+ switch (IconId )
+ {
+ case IDI_APPLICATION:
+ IconId = 100;
+ return LoadIconW(hModule,(LPWSTR)IconId);
+ break;
+ case IDI_ASTERISK:
+ //
+ IconId = 103;
+ return LoadIconW(hModule,(LPWSTR)IconId);
+ break;
+ case IDI_EXCLAMATION:
+ IconId = 101;
+ return LoadIconW(hModule,(LPWSTR)IconId);
+ break;
+ case IDI_HAND:
+ //
+ return LoadIconW(hModule,(LPWSTR)MAKEINTRESOURCE(104));
+ break;
+ case IDI_QUESTION:
+ IconId = 102;
+ return LoadIconW(hModule,(LPWSTR)IconId);
+ break;
+ case IDI_WINLOGO:
+ IconId = 105;
+ return LoadIconW(hModule,(LPWSTR)IconId);
+ break;
+ default:
+ return NULL;
+ break;
+
+ }
+ return NULL;
}
\ No newline at end of file
#include <windows.h>
-//#include <user32/syscolor.h>
+#include <user32/syscolor.h>
#include <user32/nc.h>
-void SYSCOLOR_SetColor( int index, COLORREF color );
-void SYSCOLOR_Init(void);
static const char * const DefSysColors[] =
{
* Windows. However, it is a natural complement for GetSysColorBrush
* in the Win API and is needed quite a bit inside Wine.
*/
-HPEN STDCALL GetSysColorPen( INT index )
+HPEN GetSysColorPen( INT index )
{
/* We can assert here, because this function is internal to Wine */
//assert (0 <= index && index < NUM_SYS_COLORS);
#include <windows.h>
+#include <user32/text.h>
int
dtp.iTabLength = 0;
return TEXT_DrawTextEx(hDC,(void *)lpString,nCount,lpRect,uFormat, &dtp,TRUE);
-}
\ No newline at end of file
+}
+
+/***********************************************************************
+ * GetTabbedTextExtentA (USER32.293)
+ */
+DWORD
+STDCALL
+GetTabbedTextExtentA(HDC hDC, LPCSTR lpString, int nCount, int nTabPositions,
+ LPINT lpnTabStopPositions)
+{
+
+ return TEXT_TabbedTextOutA( hDC, 0, 0, lpString, nCount, nTabPositions,
+ lpnTabStopPositions,0, FALSE );
+}
+
+
+DWORD
+STDCALL
+GetTabbedTextExtentW(HDC hDC, LPCWSTR lpString, int nCount, int nTabPositions,
+ LPINT lpnTabStopPositions)
+{
+
+ return TEXT_TabbedTextOutW( hDC, 0, 0, lpString, nCount, nTabPositions,
+ lpnTabStopPositions, 0, FALSE );
+}
+
+
+LONG
+STDCALL
+TabbedTextOutA( HDC hDC, int X, int Y, LPCSTR lpString,
+ int nCount, int nTabPositions, LPINT lpnTabStopPositions, int nTabOrigin)
+{
+ return TEXT_TabbedTextOutA( hDC, X, Y, lpString, nCount, nTabPositions,
+ lpnTabStopPositions, nTabOrigin, TRUE );
+}
+
+LONG
+STDCALL
+TabbedTextOutW( HDC hDC, int X, int Y, LPCWSTR lpString,
+ int nCount, int nTabPositions, LPINT lpnTabStopPositions, int nTabOrigin)
+{
+ return TEXT_TabbedTextOutW( hDC, 0, 0, lpString, nCount, nTabPositions,
+ lpnTabStopPositions, nTabOrigin, TRUE );
+}
+
#include <user32/dce.h>
#include <user32/sysmetr.h>
#include <user32/paint.h>
+#include <user32/defwnd.h>
#include <user32/debug.h>
*
* Set the window text.
*/
+
+void DEFWND_SetText( WND *wndPtr,const void *text )
+{
+ if ( wndPtr->class->bUnicode )
+ DEFWND_SetTextW( wndPtr, (LPCWSTR) text );
+ else
+ DEFWND_SetTextA( wndPtr, (LPCSTR) text );
+
+}
+
void DEFWND_SetTextA( WND *wndPtr, LPCSTR text )
{
if (!text) text = "";
if (wndPtr->text) HeapFree( GetProcessHeap(), 0, wndPtr->text );
- wndPtr->text = (void *)HEAP_strdupA( GetProcessHeap(), 0, text );
+ wndPtr->text = (void *)HEAP_strdupA( GetProcessHeap(), 0, text );
+ NC_HandleNCPaint( wndPtr->hwndSelf , (HRGN)1 ); /* Repaint caption */
}
{
if (!text) text = L"";
if (wndPtr->text) HeapFree( GetProcessHeap(), 0, wndPtr->text );
- wndPtr->text = (void *)HEAP_strdupW( GetProcessHeap(), 0, text );
+ wndPtr->text = (void *)HEAP_strdupW( GetProcessHeap(), 0, text );
+ NC_HandleNCPaint( wndPtr->hwndSelf , (HRGN)1 ); /* Repaint caption */
}
/***********************************************************************
{
if( !bVisible )
{
- wndPtr->dwStyle |= WS_VISIBLE;
+ //wndPtr->dwStyle |= WS_VISIBLE;
DCE_InvalidateDCE( wndPtr, &wndPtr->rectWindow );
}
}
PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, 0, wParam, 0 );
DCE_InvalidateDCE( wndPtr, &wndPtr->rectWindow );
- wndPtr->dwStyle &= ~WS_VISIBLE;
+// wndPtr->dwStyle &= ~WS_VISIBLE;
}
}
if ((wndPtr->flags & WIN_ISWIN) || (TWEAK_WineLook > WIN31_LOOK))
{
ClientToScreen(wndPtr->hwndSelf, (LPPOINT)&lParam);
- SendMessageA( wndPtr->hwndSelf, WM_CONTEXTMENU,
- wndPtr->hwndSelf, lParam);
+ MSG_SendMessage( wndPtr, WM_CONTEXTMENU,
+ (WPARAM)wndPtr->hwndSelf,(LPARAM) lParam);
}
break;
*/
#include <ctype.h>
-#include <errno.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
-#include "windows.h"
-#include "dialog.h"
-#include "drive.h"
-#include "heap.h"
-#include "win.h"
-#include "ldt.h"
-#include "user.h"
-#include "winproc.h"
-#include "message.h"
-#include "sysmetrics.h"
-#include "debug.h"
-
-
- /* Dialog control information */
-typedef struct
-{
- DWORD style;
- DWORD exStyle;
- DWORD helpId;
- INT16 x;
- INT16 y;
- INT16 cx;
- INT16 cy;
- UINT32 id;
- LPCSTR className;
- LPCSTR windowName;
- LPVOID data;
-} DLG_CONTROL_INFO;
-
- /* Dialog template */
-typedef struct
-{
- DWORD style;
- DWORD exStyle;
- DWORD helpId;
- UINT16 nbItems;
- INT16 x;
- INT16 y;
- INT16 cx;
- INT16 cy;
- LPCSTR menuName;
- LPCSTR className;
- LPCSTR caption;
- WORD pointSize;
- WORD weight;
- WINBOOL italic;
- LPCSTR faceName;
- WINBOOL dialogEx;
-} DLG_TEMPLATE;
+
+#define UNICODE
+#include <windows.h>
+#include <user32/dialog.h>
+#include <user32/heapdup.h>
+#include <user32/win.h>
+#include <user32/sysmetr.h>
+#include <user32/debug.h>
+#include <user32/msg.h>
+#include <user32/widgets.h>
+
+
/* Dialog base units */
-static WORD xBaseUnit = 0, yBaseUnit = 0;
+WORD xBaseUnit = 0, yBaseUnit = 0;
/***********************************************************************
*/
WINBOOL DIALOG_Init(void)
{
- TEXTMETRIC16 tm;
- HDC16 hdc;
+ TEXTMETRIC tm;
+ HDC hdc;
/* Calculate the dialog base units */
- if (!(hdc = CreateDC16( "DISPLAY", NULL, NULL, NULL ))) return FALSE;
- GetTextMetrics16( hdc, &tm );
- DeleteDC32( hdc );
+ if (!(hdc = CreateDC( L"DISPLAY", NULL, NULL, NULL ))) return FALSE;
+ GetTextMetrics( hdc, &tm );
+ DeleteDC( hdc );
xBaseUnit = tm.tmAveCharWidth;
yBaseUnit = tm.tmHeight;
if (!(tm.tmPitchAndFamily & TMPF_FIXED_PITCH))
xBaseUnit = xBaseUnit * 5 / 4;
- TRACE(dialog, "base units = %d,%d\n",
+ DPRINT( "base units = %d,%d\n",
xBaseUnit, yBaseUnit );
return TRUE;
}
-
/***********************************************************************
- * DIALOG_GetControl16
- *
- * Return the class and text of the control pointed to by ptr,
- * fill the header structure and return a pointer to the next control.
+ * DIALOG_DoDialogBox
*/
-static LPCSTR DIALOG_GetControl16( LPCSTR p, DLG_CONTROL_INFO *info )
+INT DIALOG_DoDialogBox( HWND hwnd, HWND owner )
{
- static char buffer[10];
- int int_id;
-
- info->x = GET_WORD(p); p += sizeof(WORD);
- info->y = GET_WORD(p); p += sizeof(WORD);
- info->cx = GET_WORD(p); p += sizeof(WORD);
- info->cy = GET_WORD(p); p += sizeof(WORD);
- info->id = GET_WORD(p); p += sizeof(WORD);
- info->style = GET_DWORD(p); p += sizeof(DWORD);
- info->exStyle = 0;
-
- if (*p & 0x80)
- {
- switch((BYTE)*p)
- {
- case 0x80: strcpy( buffer, "BUTTON" ); break;
- case 0x81: strcpy( buffer, "EDIT" ); break;
- case 0x82: strcpy( buffer, "STATIC" ); break;
- case 0x83: strcpy( buffer, "LISTBOX" ); break;
- case 0x84: strcpy( buffer, "SCROLLBAR" ); break;
- case 0x85: strcpy( buffer, "COMBOBOX" ); break;
- default: buffer[0] = '\0'; break;
- }
- info->className = buffer;
- p++;
- }
- else
- {
- info->className = p;
- p += strlen(p) + 1;
- }
-
- int_id = ((BYTE)*p == 0xff);
- if (int_id)
- {
- /* Integer id, not documented (?). Only works for SS_ICON controls */
- info->windowName = (LPCSTR)(UINT32)GET_WORD(p+1);
- p += 3;
- }
- else
- {
- info->windowName = p;
- p += strlen(p) + 1;
- }
-
- info->data = (LPVOID)(*p ? p + 1 : NULL); /* FIXME: should be a segptr */
- p += *p + 1;
-
- if(int_id)
- TRACE(dialog," %s %04x %d, %d, %d, %d, %d, %08lx, %08lx\n",
- info->className, LOWORD(info->windowName),
- info->id, info->x, info->y, info->cx, info->cy,
- info->style, (DWORD)info->data);
- else
- TRACE(dialog," %s '%s' %d, %d, %d, %d, %d, %08lx, %08lx\n",
- info->className, info->windowName,
- info->id, info->x, info->y, info->cx, info->cy,
- info->style, (DWORD)info->data);
-
- return p;
-}
-
-
-/***********************************************************************
- * DIALOG_GetControl32
- *
- * Return the class and text of the control pointed to by ptr,
- * fill the header structure and return a pointer to the next control.
- */
-static const WORD *DIALOG_GetControl32( const WORD *p, DLG_CONTROL_INFO *info,
- WINBOOL dialogEx )
-{
- if (dialogEx)
- {
- info->helpId = GET_DWORD(p); p += 2;
- info->exStyle = GET_DWORD(p); p += 2;
- info->style = GET_DWORD(p); p += 2;
- }
- else
- {
- info->helpId = 0;
- info->style = GET_DWORD(p); p += 2;
- info->exStyle = GET_DWORD(p); p += 2;
- }
- info->x = GET_WORD(p); p++;
- info->y = GET_WORD(p); p++;
- info->cx = GET_WORD(p); p++;
- info->cy = GET_WORD(p); p++;
-
- if (dialogEx)
- {
- /* id is a DWORD for DIALOGEX */
- info->id = GET_DWORD(p);
- p += 2;
- }
- else
- {
- info->id = GET_WORD(p);
- p++;
- }
-
- if (GET_WORD(p) == 0xffff)
- {
- static const WCHAR class_names[6][10] =
- {
- { 'B','u','t','t','o','n', }, /* 0x80 */
- { 'E','d','i','t', }, /* 0x81 */
- { 'S','t','a','t','i','c', }, /* 0x82 */
- { 'L','i','s','t','B','o','x', }, /* 0x83 */
- { 'S','c','r','o','l','l','B','a','r', }, /* 0x84 */
- { 'C','o','m','b','o','B','o','x', } /* 0x85 */
- };
- WORD id = GET_WORD(p+1);
- if ((id >= 0x80) && (id <= 0x85))
- info->className = (LPCSTR)class_names[id - 0x80];
- else
- {
- info->className = NULL;
- ERR( dialog, "Unknown built-in class id %04x\n", id );
- }
- p += 2;
- }
- else
- {
- info->className = (LPCSTR)p;
- p += lstrlen32W( (LPCWSTR)p ) + 1;
- }
-
- if (GET_WORD(p) == 0xffff) /* Is it an integer id? */
- {
- info->windowName = (LPCSTR)(UINT32)GET_WORD(p + 1);
- p += 2;
- }
- else
- {
- info->windowName = (LPCSTR)p;
- p += lstrlen32W( (LPCWSTR)p ) + 1;
- }
+ WND * wndPtr;
+ DIALOGINFO * dlgInfo;
+ MSG msg;
+ INT retval;
- TRACE(dialog," %s %s %d, %d, %d, %d, %d, %08lx, %08lx, %08lx\n",
- debugstr_w( (LPCWSTR)info->className ),
- debugres_w( (LPCWSTR)info->windowName ),
- info->id, info->x, info->y, info->cx, info->cy,
- info->style, info->exStyle, info->helpId );
+ /* Owner must be a top-level window */
+ owner = WIN_GetTopParent( owner );
+ if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return -1;
+ dlgInfo = (DIALOGINFO *)wndPtr->wExtra;
+ EnableWindow( owner, FALSE );
+ ShowWindow( hwnd, SW_SHOW );
- if (GET_WORD(p))
+ while (MSG_InternalGetMessage(&msg, hwnd, owner, MSGF_DIALOGBOX, PM_REMOVE,
+ !(wndPtr->dwStyle & DS_NOIDLEMSG) ))
{
- if (TRACE_ON(dialog))
- {
- WORD i, count = GET_WORD(p) / sizeof(WORD);
- TRACE(dialog, " BEGIN\n");
- TRACE(dialog, " ");
- for (i = 0; i < count; i++) DUMP( "%04x,", GET_WORD(p+i+1) );
- DUMP("\n");
- TRACE(dialog, " END\n" );
- }
- info->data = (LPVOID)(p + 1);
- p += GET_WORD(p) / sizeof(WORD);
+ if (!IsDialogMessage( hwnd, &msg))
+ {
+ TranslateMessage( &msg );
+ DispatchMessage( &msg );
+ }
+ if (dlgInfo->flags & DF_END) break;
}
- else info->data = NULL;
- p++;
-
- /* Next control is on dword boundary */
- return (const WORD *)((((int)p) + 3) & ~3);
+ retval = dlgInfo->idResult;
+ EnableWindow( owner, TRUE );
+ dlgInfo->flags |= DF_ENDING; /* try to stop it being destroyed twice */
+ DestroyWindow( hwnd );
+ return retval;
}
-/***********************************************************************
- * DIALOG_CreateControls
- *
- * Create the control windows for a dialog.
- */
-static WINBOOL DIALOG_CreateControls( WND *pWnd, LPCSTR template,
- const DLG_TEMPLATE *dlgTemplate,
- HINSTANCE32 hInst, WINBOOL win32 )
-{
- DIALOGINFO *dlgInfo = (DIALOGINFO *)pWnd->wExtra;
- DLG_CONTROL_INFO info;
- HWND32 hwndCtrl, hwndDefButton = 0;
- INT32 items = dlgTemplate->nbItems;
-
- TRACE(dialog, " BEGIN\n" );
- while (items--)
- {
- if (!win32)
- {
- HINSTANCE16 instance;
- template = DIALOG_GetControl16( template, &info );
- if (HIWORD(info.className) && !strcmp( info.className, "EDIT") &&
- ((pWnd->dwStyle & DS_LOCALEDIT) != DS_LOCALEDIT))
- {
- if (!dlgInfo->hDialogHeap)
- {
- dlgInfo->hDialogHeap = GlobalAlloc16(GMEM_FIXED, 0x10000);
- if (!dlgInfo->hDialogHeap)
- {
- ERR(dialog, "Insufficient memory to create heap for edit control\n" );
- continue;
- }
- LocalInit(dlgInfo->hDialogHeap, 0, 0xffff);
- }
- instance = dlgInfo->hDialogHeap;
- }
- else instance = (HINSTANCE16)hInst;
-
- hwndCtrl = CreateWindowEx16( info.exStyle | WS_EX_NOPARENTNOTIFY,
- info.className, info.windowName,
- info.style | WS_CHILD,
- info.x * dlgInfo->xBaseUnit / 4,
- info.y * dlgInfo->yBaseUnit / 8,
- info.cx * dlgInfo->xBaseUnit / 4,
- info.cy * dlgInfo->yBaseUnit / 8,
- pWnd->hwndSelf, (HMENU16)info.id,
- instance, info.data );
- }
- else
- {
- template = (LPCSTR)DIALOG_GetControl32( (WORD *)template, &info,
- dlgTemplate->dialogEx );
- hwndCtrl = CreateWindowEx32W( info.exStyle | WS_EX_NOPARENTNOTIFY,
- (LPCWSTR)info.className,
- (LPCWSTR)info.windowName,
- info.style | WS_CHILD,
- info.x * dlgInfo->xBaseUnit / 4,
- info.y * dlgInfo->yBaseUnit / 8,
- info.cx * dlgInfo->xBaseUnit / 4,
- info.cy * dlgInfo->yBaseUnit / 8,
- pWnd->hwndSelf, (HMENU32)info.id,
- hInst, info.data );
- }
- if (!hwndCtrl) return FALSE;
-
- /* Send initialisation messages to the control */
- if (dlgInfo->hUserFont) SendMessage32A( hwndCtrl, WM_SETFONT,
- (WPARAM32)dlgInfo->hUserFont, 0 );
- if (SendMessage32A(hwndCtrl, WM_GETDLGCODE, 0, 0) & DLGC_DEFPUSHBUTTON)
- {
- /* If there's already a default push-button, set it back */
- /* to normal and use this one instead. */
- if (hwndDefButton)
- SendMessage32A( hwndDefButton, BM_SETSTYLE32,
- BS_PUSHBUTTON,FALSE );
- hwndDefButton = hwndCtrl;
- dlgInfo->idResult = GetWindowWord32( hwndCtrl, GWW_ID );
- }
- }
- TRACE(dialog, " END\n" );
- return TRUE;
-}
-
/***********************************************************************
- * DIALOG_ParseTemplate16
+ * DIALOG_ParseTemplate
*
* Fill a DLG_TEMPLATE structure from the dialog template, and return
* a pointer to the first control.
*/
-static LPCSTR DIALOG_ParseTemplate16( LPCSTR p, DLG_TEMPLATE * result )
+LPCDLGITEMTEMPLATE DIALOG_ParseTemplate( LPCDLGTEMPLATE DlgTemplate, DLG_TEMPLATE * result, WINBOOL bUnicode )
{
- result->style = GET_DWORD(p); p += sizeof(DWORD);
- result->exStyle = 0;
- result->nbItems = *p++;
- result->x = GET_WORD(p); p += sizeof(WORD);
- result->y = GET_WORD(p); p += sizeof(WORD);
- result->cx = GET_WORD(p); p += sizeof(WORD);
- result->cy = GET_WORD(p); p += sizeof(WORD);
- TRACE(dialog, "DIALOG %d, %d, %d, %d\n",
- result->x, result->y, result->cx, result->cy );
- TRACE(dialog, " STYLE %08lx\n", result->style );
+ WORD *p;
+
+
+ result->dialogEx = FALSE;
+ result->helpId = 0;
+ result->exStyle = DlgTemplate->dwExtendedStyle;
+
+ result->nbItems = DlgTemplate->cdit;
+ result->x = DlgTemplate->x;
+ result->y = DlgTemplate->y;
+ result->cx = DlgTemplate->cx;
+ result->cy = DlgTemplate->cy;
+
+
+ p = &(DlgTemplate->cy);
+ p++;
- /* Get the menu name */
+
+ /* Get the menu name */
- switch( (BYTE)*p )
+ switch((WORD)*p)
{
- case 0:
- result->menuName = 0;
+ case 0x0000:
+ result->menuName = NULL;
p++;
break;
- case 0xff:
- result->menuName = (LPCSTR)(UINT32)GET_WORD( p + 1 );
- p += 3;
- TRACE(dialog, " MENU %04x\n", LOWORD(result->menuName) );
+ case 0xffff:
+ p++;
+ result->menuName = (LPWSTR) *p; // Ordinal of Menu resource
+ p++;
break;
default:
- result->menuName = p;
- TRACE(dialog, " MENU '%s'\n", p );
- p += strlen(p) + 1;
+ result->menuName = (LPCWSTR)p;
+ p += lstrlenW( (LPCWSTR)p );
+ p++;
break;
}
/* Get the class name */
- if (*p)
+
+
+ switch((WORD)*p)
{
- result->className = p;
- TRACE(dialog, " CLASS '%s'\n", result->className );
+ case 0x0000:
+ if ( bUnicode == TRUE )
+ result->className = DIALOG_CLASS_NAMEW;
+ else
+ result->className = DIALOG_CLASS_NAMEA;
+ p++;
+ break;
+ case 0xffff:
+ p++;
+ result->className = (LPCWSTR)p; // Ordinal of predefined class
+ p++;
+ break;
+ default:
+ result->className = (LPCWSTR)p;
+ p += lstrlenW( (LPCWSTR)p );
+ p++;
+ break;
}
- else result->className = DIALOG_CLASS_ATOM;
- p += strlen(p) + 1;
/* Get the window caption */
+ if ( *p != 0 ) {
+ result->caption = (LPCWSTR)p;
+ p += lstrlenW( (LPCWSTR)p ) + 1;
+
+ /* Get the font name */
+
+ if (result->style & DS_SETFONT)
+ {
+ result->pointSize = *p;
+ p++;
+ if (result->dialogEx)
+ {
+ result->weight = *p; p++;
+ result->italic = *p; p++;
+ }
+ else
+ {
+ result->weight = FW_DONTCARE;
+ result->italic = FALSE;
+ }
+ result->faceName = (LPCWSTR)p;
+ p += lstrlenW( (LPCWSTR)p );
+ p++;
+
+ }
+ } else {
+ result->caption = L"";
+ }
- result->caption = p;
- p += strlen(p) + 1;
- TRACE(dialog, " CAPTION '%s'\n", result->caption );
- /* Get the font name */
- if (result->style & DS_SETFONT)
- {
- result->pointSize = GET_WORD(p);
- p += sizeof(WORD);
- result->faceName = p;
- p += strlen(p) + 1;
- TRACE(dialog, " FONT %d,'%s'\n",
- result->pointSize, result->faceName );
- }
- return p;
+ /* First control is on dword boundary */
+ return (LPCDLGITEMTEMPLATE )((((int)p) + 3) & ~3);
}
-
/***********************************************************************
- * DIALOG_ParseTemplate32
+ * DIALOG_ParseTemplate
*
* Fill a DLG_TEMPLATE structure from the dialog template, and return
* a pointer to the first control.
*/
-static LPCSTR DIALOG_ParseTemplate32( LPCSTR template, DLG_TEMPLATE * result )
+LPCDLGITEMTEMPLATEEX DIALOG_ParseTemplateEx( LPCDLGTEMPLATEEX DlgTemplate, DLG_TEMPLATE * result,WINBOOL bUnicode )
{
- const WORD *p = (const WORD *)template;
+ WORD *p;
- result->style = GET_DWORD(p); p += 2;
- if (result->style == 0xffff0001) /* DIALOGEX resource */
- {
- result->dialogEx = TRUE;
- result->helpId = GET_DWORD(p); p += 2;
- result->exStyle = GET_DWORD(p); p += 2;
- result->style = GET_DWORD(p); p += 2;
- }
- else
- {
- result->dialogEx = FALSE;
- result->helpId = 0;
- result->exStyle = GET_DWORD(p); p += 2;
- }
- result->nbItems = GET_WORD(p); p++;
- result->x = GET_WORD(p); p++;
- result->y = GET_WORD(p); p++;
- result->cx = GET_WORD(p); p++;
- result->cy = GET_WORD(p); p++;
- TRACE( dialog, "DIALOG%s %d, %d, %d, %d, %ld\n",
- result->dialogEx ? "EX" : "", result->x, result->y,
- result->cx, result->cy, result->helpId );
- TRACE( dialog, " STYLE 0x%08lx\n", result->style );
- TRACE( dialog, " EXSTYLE 0x%08lx\n", result->exStyle );
+
+ result->dialogEx = TRUE;
+ result->helpId = DlgTemplate->helpID;
+ result->exStyle = DlgTemplate->exStyle;
+ result->style = DlgTemplate->style;
+
+ result->nbItems = DlgTemplate->cDlgItems;
+ result->x = DlgTemplate->x;
+ result->y = DlgTemplate->y;
+ result->cx = DlgTemplate->cx;
+ result->cy = DlgTemplate->cy;
+
+ p = &(DlgTemplate->cy);
+ p++;
/* Get the menu name */
- switch(GET_WORD(p))
+ switch(*p)
{
case 0x0000:
result->menuName = NULL;
p++;
break;
case 0xffff:
- result->menuName = (LPCSTR)(UINT32)GET_WORD( p + 1 );
- p += 2;
- TRACE(dialog, " MENU %04x\n", LOWORD(result->menuName) );
+ p++;
+ result->menuName = (LPCWSTR)(WORD)*( p ); // Ordinal of Menu resource
+ p++;
break;
default:
- result->menuName = (LPCSTR)p;
- TRACE(dialog, " MENU %s\n", debugstr_w( (LPCWSTR)p ));
- p += lstrlen32W( (LPCWSTR)p ) + 1;
+ result->menuName = (LPCWSTR)p;
+ p += lstrlenW( (LPCWSTR)p ) + 1;
break;
}
/* Get the class name */
- switch(GET_WORD(p))
+ switch(*p)
{
case 0x0000:
- result->className = DIALOG_CLASS_ATOM;
+ if ( bUnicode == TRUE )
+ result->className = DIALOG_CLASS_NAMEW;
+ else
+ result->className = DIALOG_CLASS_NAMEA;
p++;
break;
case 0xffff:
- result->className = (LPCSTR)(UINT32)GET_WORD( p + 1 );
- p += 2;
- TRACE(dialog, " CLASS %04x\n", LOWORD(result->className) );
+ p++;
+ result->className = (LPCWSTR)(WORD)*( p );
+ p ++;
+ DPRINT( " CLASS %04x\n", LOWORD(result->className) );
break;
default:
- result->className = (LPCSTR)p;
- TRACE(dialog, " CLASS %s\n", debugstr_w( (LPCWSTR)p ));
- p += lstrlen32W( (LPCWSTR)p ) + 1;
+ result->className = (LPCWSTR)p;
+ DPRINT( " CLASS %s\n", debugstr_w( (LPCWSTR)p ));
+ p += lstrlenW( (LPCWSTR)p ) + 1;
break;
}
/* Get the window caption */
+ if ( *p != 0 ) {
+ result->caption = (LPCWSTR)p;
+ p += lstrlenW( (LPCWSTR)p ) + 1;
+
+ /* Get the font name */
+
+ if (result->style & DS_SETFONT)
+ {
+ result->pointSize = LOWORD(p);
+ p++;
+ if (result->dialogEx)
+ {
+ result->weight = *p; p++;
+ result->italic = LOBYTE(*p); p++;
+ }
+ else
+ {
+ result->weight = FW_DONTCARE;
+ result->italic = FALSE;
+ }
+ result->faceName = (LPCWSTR)p;
+ p += lstrlenW( (LPCWSTR)p ) + 1;
+
+ }
+ } else
+ result->caption = L"";
+
+
+ /* First control is on dword boundary */
+ return (LPDLGITEMTEMPLATEEX )((((int)p) + 3) & ~3);
+}
- result->caption = (LPCSTR)p;
- p += lstrlen32W( (LPCWSTR)p ) + 1;
- TRACE(dialog, " CAPTION %s\n", debugstr_w( (LPCWSTR)result->caption ) );
- /* Get the font name */
+/***********************************************************************
+ * DIALOG_GetControl
+ *
+ * Return the class and text of the control pointed to by ptr,
+ * fill the header structure and return a pointer to the next control.
+ */
+LPCDLGITEMTEMPLATE DIALOG_GetControl( LPCDLGITEMTEMPLATE DlgItemTemplate, DLG_CONTROL_INFO *info)
+{
+ WORD *p;
+ WORD id;
- if (result->style & DS_SETFONT)
+ info->helpId = 0;
+ info->exStyle = DlgItemTemplate->dwExtendedStyle;
+ info->style = DlgItemTemplate->style;
+
+ info->x = DlgItemTemplate->x;
+ info->y = DlgItemTemplate->y;
+ info->cx = DlgItemTemplate->cx;
+ info->cy = DlgItemTemplate->cy;
+
+
+ info->id = DlgItemTemplate->id;
+
+
+ p = (char *)DlgItemTemplate + sizeof(DLGITEMTEMPLATE);
+ p--;
+
+ if (*p == 0xffff)
{
- result->pointSize = GET_WORD(p);
- p++;
- if (result->dialogEx)
+
+ static const WCHAR class_names[6][10] =
{
- result->weight = GET_WORD(p); p++;
- result->italic = LOBYTE(GET_WORD(p)); p++;
- }
+ { BUTTON_CLASS_NAME }, /* 0x80 */
+ { EDIT_CLASS_NAME }, /* 0x81 */
+ { STATIC_CLASS_NAME }, /* 0x82 */
+ { LISTBOX_CLASS_NAME}, /* 0x83 */
+ { SCROLLBAR_CLASS_NAME }, /* 0x84 */
+ { COMBOBOX_CLASS_NAME } /* 0x85 */
+ };
+ p++;
+ id = (WORD)*(p);
+ if ((id >= 0x80) && (id <= 0x85))
+ info->className = (LPCSTR)HEAP_strdupW(GetProcessHeap(),0,class_names[id - 0x80]);
else
+ info->className = NULL;
+
+ printf("%S\n",info->className);
+
+ p++;
+ }
+ else
+ {
+ info->className = (LPCWSTR)p;
+ p += lstrlenW( (LPCWSTR)p ) + 1;
+ }
+
+ if (*p == 0xffff) /* Is it an integer id? */
+ {
+ p++;
+ info->windowName = (LPCWSTR)(WORD)*(p + 1);
+ p++;
+ }
+ else
+ {
+ info->windowName = (LPCWSTR)p;
+ p += lstrlenW( (LPCWSTR)p ) + 1;
+ }
+
+
+
+ if (*p)
+ {
+ p++;
+ info->data = (LPVOID)(p);
+ p += *p / sizeof(WORD);
+ }
+ else {
+ info->data = NULL;
+ p++;
+ }
+
+ /* Next control is on dword boundary */
+ return (LPCDLGITEMTEMPLATE)((((int)p) + 3) & ~3);
+}
+
+
+/***********************************************************************
+ * DIALOG_GetControl
+ *
+ * Return the class and text of the control pointed to by ptr,
+ * fill the header structure and return a pointer to the next control.
+ */
+LPCDLGITEMTEMPLATEEX DIALOG_GetControlEx( LPCDLGITEMTEMPLATEEX DlgItemTemplate, DLG_CONTROL_INFO *info )
+{
+ WORD *p;
+ WORD id;
+ info->helpId = DlgItemTemplate->helpID;
+ info->exStyle = DlgItemTemplate->exStyle;
+ info->style = DlgItemTemplate->style;
+
+ info->x = DlgItemTemplate->x;
+ info->y = DlgItemTemplate->y;
+ info->cx = DlgItemTemplate->cx;
+ info->cy = DlgItemTemplate->cy;
+
+
+ /* id is a DWORD for DIALOGEX */
+ info->id = DlgItemTemplate->id;
+
+ p = (char *)DlgItemTemplate + sizeof(DLGITEMTEMPLATEEX);
+ p--;
+
+ if (*p == 0xffff)
+ {
+
+ static const WCHAR class_names[6][10] =
{
- result->weight = FW_DONTCARE;
- result->italic = FALSE;
- }
- result->faceName = (LPCSTR)p;
- p += lstrlen32W( (LPCWSTR)p ) + 1;
- TRACE(dialog, " FONT %d, %s, %d, %s\n",
- result->pointSize, debugstr_w( (LPCWSTR)result->faceName ),
- result->weight, result->italic ? "TRUE" : "FALSE" );
+ { L"Button" }, /* 0x80 */
+ { L"Edit"}, /* 0x81 */
+ { L"Static" }, /* 0x82 */
+ { L"ListBox"}, /* 0x83 */
+ { L"ScrollBar" }, /* 0x84 */
+ { L"ComboBox" } /* 0x85 */
+ };
+ p++;
+ id = (WORD)*(p);
+ if ((id >= 0x80) && (id <= 0x85))
+ info->className = (LPCSTR)HEAP_strdupW(GetProcessHeap(),0,class_names[id - 0x80]);
+ else
+ info->className = NULL;
+
+ p++;
+ }
+ else
+ {
+ info->className = (LPCWSTR)p;
+ p += lstrlenW( (LPCWSTR)p ) + 1;
}
- /* First control is on dword boundary */
- return (LPCSTR)((((int)p) + 3) & ~3);
+ if (*p == 0xffff) /* Is it an integer id? */
+ {
+ p++;
+ info->windowName = (LPCWSTR)(WORD)*(p);
+ p++;
+ }
+ else
+ {
+
+ info->windowName = (LPCWSTR)p;
+ p += lstrlenW( (LPCWSTR)p ) + 1;
+ }
+
+
+
+ if (*p) {
+
+ p++;
+ info->data = (LPVOID)(p);
+ p += *p / sizeof(WORD);
+ }
+ else {
+ info->data = NULL;
+ p++;
+ }
+
+ /* Next control is on dword boundary */
+ return (LPCDLGITEMTEMPLATE)((((int)p) + 3) & ~3);
+}
+
+
+/***********************************************************************
+ * DIALOG_CreateControls
+ *
+ * Create the control windows for a dialog.
+ */
+WINBOOL DIALOG_CreateControls( HANDLE hWndDialog, DIALOGINFO *dlgInfo ,
+ void *template, INT items,
+ HINSTANCE hInst, WINBOOL bDialogEx)
+{
+ DLG_CONTROL_INFO info;
+ HWND hwndCtrl, hwndDefButton = 0;
+
+ while (items--)
+ {
+
+ if ( bDialogEx)
+ template = (void *)DIALOG_GetControlEx( (LPDLGITEMTEMPLATEEX)template, &info );
+ else
+ template = (void *)DIALOG_GetControl( (LPDLGITEMTEMPLATE)template, &info );
+
+ hwndCtrl = CreateWindowExW( info.exStyle | WS_EX_NOPARENTNOTIFY,
+ (LPCWSTR)info.className,
+ (LPCWSTR)info.windowName,
+ info.style | WS_CHILD | WS_THICKFRAME | WS_VISIBLE,
+ info.x * dlgInfo->xBaseUnit / 4,
+ info.y * dlgInfo->yBaseUnit / 8,
+ info.cx * dlgInfo->xBaseUnit / 4 ,
+ info.cy * dlgInfo->yBaseUnit / 8,
+ hWndDialog, (HMENU)info.id,
+ hInst, info.data );
+
+
+ if (hwndCtrl) {
+
+ /* Send initialisation messages to the control */
+ if (dlgInfo->hUserFont) SendMessage( hwndCtrl, WM_SETFONT,
+ (WPARAM)dlgInfo->hUserFont, 0 );
+ if (SendMessage(hwndCtrl, WM_GETDLGCODE, 0, 0) & DLGC_DEFPUSHBUTTON)
+ {
+ /* If there's already a default push-button, set it back */
+ /* to normal and use this one instead. */
+ if (hwndDefButton)
+ SendMessage( hwndDefButton, BM_SETSTYLE, BS_PUSHBUTTON,FALSE );
+ hwndDefButton = hwndCtrl;
+ dlgInfo->idResult = GetWindowLong( hwndCtrl, GWL_ID );
+ }
+ }
+ }
+ return TRUE;
}
+
+
+
/***********************************************************************
* DIALOG_CreateIndirect
*/
-HWND32 DIALOG_CreateIndirect( HINSTANCE32 hInst, LPCSTR dlgTemplate,
- WINBOOL win32Template, HWND32 owner,
- DLGPROC16 dlgProc, LPARAM param,
- WINDOWPROCTYPE procType )
+HWND DIALOG_CreateIndirect( HINSTANCE hInst, void *dlgTemplate, HWND owner,
+ DLGPROC dlgProc, LPARAM param,
+ WINBOOL bUnicode )
{
- HMENU16 hMenu = 0;
- HFONT16 hFont = 0;
- HWND32 hwnd;
- RECT32 rect;
+ HMENU hMenu = 0;
+ HFONT hFont = 0;
+ HWND hwnd;
+ RECT rect;
WND * wndPtr;
DLG_TEMPLATE template;
DIALOGINFO * dlgInfo;
WORD xUnit = xBaseUnit;
WORD yUnit = yBaseUnit;
+ void *dlgItemTemplate;
+
+
+
+ if ( xBaseUnit == 0 )
+ DIALOG_Init();
+
+ xUnit = xBaseUnit;
+ yUnit = yBaseUnit;
/* Parse dialog template */
- if (!dlgTemplate) return 0;
- if (win32Template)
- dlgTemplate = DIALOG_ParseTemplate32( dlgTemplate, &template );
- else
- dlgTemplate = DIALOG_ParseTemplate16( dlgTemplate, &template );
+
+ if (((LPDLGTEMPLATEEX)dlgTemplate)->signature != 0xffff) /* DIALOGEX resource */
+ dlgItemTemplate = (void *)DIALOG_ParseTemplate((LPCDLGTEMPLATE) dlgTemplate, &template, bUnicode );
+ else
+ dlgItemTemplate = (void *)DIALOG_ParseTemplateEx( (LPCDLGTEMPLATEEX)dlgTemplate, &template, bUnicode );
+
/* Load menu */
-
if (template.menuName)
- {
- if (!win32Template)
- {
- LPSTR str = SEGPTR_STRDUP( template.menuName );
- hMenu = LoadMenu16( hInst, SEGPTR_GET(str) );
- SEGPTR_FREE( str );
- }
- else hMenu = LoadMenu32W( hInst, (LPCWSTR)template.menuName );
- }
+ hMenu = LoadMenuW( hInst, (LPCWSTR)template.menuName );
+
/* Create custom font if needed */
/* The font height must be negative as it is a point size */
/* (see CreateFont() documentation in the Windows SDK). */
- if (win32Template)
- hFont = CreateFont32W( -template.pointSize, 0, 0, 0,
+
+ hFont = CreateFontW( -template.pointSize, 0, 0, 0,
template.weight, template.italic, FALSE,
FALSE, DEFAULT_CHARSET, 0, 0, PROOF_QUALITY,
FF_DONTCARE, (LPCWSTR)template.faceName );
- else
- hFont = CreateFont16( -template.pointSize, 0, 0, 0, FW_DONTCARE,
- FALSE, FALSE, FALSE, DEFAULT_CHARSET, 0, 0,
- PROOF_QUALITY, FF_DONTCARE,
- template.faceName );
+
if (hFont)
{
- TEXTMETRIC16 tm;
- HFONT16 oldFont;
-
- HDC32 hdc = GetDC32(0);
- oldFont = SelectObject32( hdc, hFont );
- GetTextMetrics16( hdc, &tm );
- SelectObject32( hdc, oldFont );
- ReleaseDC32( 0, hdc );
+ TEXTMETRIC tm;
+ HFONT oldFont;
+
+ HDC hdc = GetDC(0);
+ oldFont = SelectObject( hdc, hFont );
+ GetTextMetrics( hdc, &tm );
+ SelectObject( hdc, oldFont );
+ ReleaseDC( 0, hdc );
xUnit = tm.tmAveCharWidth;
yUnit = tm.tmHeight;
if (!(tm.tmPitchAndFamily & TMPF_FIXED_PITCH))
xBaseUnit = xBaseUnit * 5 / 4; /* See DIALOG_Init() */
+
}
}
-
+
+
/* Create dialog main window */
rect.left = rect.top = 0;
rect.bottom = template.cy * yUnit / 8;
if (template.style & DS_MODALFRAME)
template.exStyle |= WS_EX_DLGMODALFRAME;
- AdjustWindowRectEx32( &rect, template.style,
+ AdjustWindowRectEx( &rect, template.style,
hMenu ? TRUE : FALSE , template.exStyle );
rect.right -= rect.left;
rect.bottom -= rect.top;
- if ((INT16)template.x == CW_USEDEFAULT16)
+ if ((INT)template.x == CW_USEDEFAULT)
{
- rect.left = rect.top = (procType == WIN_PROC_16) ? CW_USEDEFAULT16
- : CW_USEDEFAULT32;
+ rect.left = rect.top = CW_USEDEFAULT;
}
else
{
}
if ( !(template.style & WS_CHILD) )
{
- INT16 dX, dY;
+ INT dX, dY;
if( !(template.style & DS_ABSALIGN) )
- ClientToScreen32( owner, (POINT32 *)&rect );
+ ClientToScreen( owner, (POINT *)&rect );
/* try to fit it into the desktop */
- if( (dX = rect.left + rect.right + SYSMETRICS_CXDLGFRAME
- - SYSMETRICS_CXSCREEN) > 0 ) rect.left -= dX;
- if( (dY = rect.top + rect.bottom + SYSMETRICS_CYDLGFRAME
- - SYSMETRICS_CYSCREEN) > 0 ) rect.top -= dY;
+ if( (dX = rect.left + rect.right + SYSMETRICS_CXDLGFRAME - SYSMETRICS_CXSCREEN) > 0 )
+ rect.left -= dX;
+ if( (dY = rect.top + rect.bottom + SYSMETRICS_CYDLGFRAME - SYSMETRICS_CYSCREEN) > 0 )
+ rect.top -= dY;
if( rect.left < 0 ) rect.left = 0;
if( rect.top < 0 ) rect.top = 0;
}
}
- if (procType == WIN_PROC_16)
- hwnd = CreateWindowEx16(template.exStyle, template.className,
- template.caption, template.style & ~WS_VISIBLE,
- rect.left, rect.top, rect.right, rect.bottom,
- owner, hMenu, hInst, NULL );
- else
- hwnd = CreateWindowEx32W(template.exStyle, (LPCWSTR)template.className,
+
+// template.style & ~WS_VISIBLE
+
+template.style |= WS_VISIBLE;
+template.style |= WS_THICKFRAME;
+ hwnd = CreateWindowExW(template.exStyle, (LPCWSTR)template.className,
(LPCWSTR)template.caption,
- template.style & ~WS_VISIBLE,
- rect.left, rect.top, rect.right, rect.bottom,
+ template.style ,
+ rect.left, rect.top, rect.right, rect.bottom ,
owner, hMenu, hInst, NULL );
+
+
if (!hwnd)
{
- if (hFont) DeleteObject32( hFont );
- if (hMenu) DestroyMenu32( hMenu );
+ if (hFont) DeleteObject( hFont );
+ if (hMenu) DestroyMenu( hMenu );
return 0;
}
wndPtr = WIN_FindWndPtr( hwnd );
wndPtr->flags |= WIN_ISDIALOG;
wndPtr->helpContext = template.helpId;
+ wndPtr->winproc = dlgProc;
/* Initialise dialog extra data */
dlgInfo = (DIALOGINFO *)wndPtr->wExtra;
- WINPROC_SetProc( &dlgInfo->dlgProc, dlgProc, procType, WIN_PROC_WINDOW );
+ dlgInfo->dlgProc = dlgProc;
dlgInfo->hUserFont = hFont;
dlgInfo->hMenu = hMenu;
dlgInfo->xBaseUnit = xUnit;
dlgInfo->hDialogHeap = 0;
if (dlgInfo->hUserFont)
- SendMessage32A( hwnd, WM_SETFONT, (WPARAM32)dlgInfo->hUserFont, 0 );
+ MSG_SendMessage( wndPtr, WM_SETFONT, (WPARAM)dlgInfo->hUserFont, 0L);
/* Create controls */
- if (DIALOG_CreateControls( wndPtr, dlgTemplate, &template,
- hInst, win32Template ))
+
+
+ if (!DIALOG_CreateControls( hwnd, dlgInfo, dlgItemTemplate, template.nbItems, hInst , template.dialogEx))
{
+ DestroyWindow( hwnd );
+ if (hFont) DeleteObject( hFont );
+ if (hMenu) DestroyMenu( hMenu );
+ return 0;
+ }
+
+
/* Send initialisation messages and set focus */
- dlgInfo->hwndFocus = GetNextDlgTabItem32( hwnd, 0, FALSE );
+ dlgInfo->hwndFocus = GetNextDlgTabItem( hwnd, 0, FALSE );
- if (SendMessage32A( hwnd, WM_INITDIALOG, (WPARAM32)dlgInfo->hwndFocus, param ))
- SetFocus32( dlgInfo->hwndFocus );
+ if (MSG_SendMessage( wndPtr, WM_INITDIALOG, (WPARAM)dlgInfo->hwndFocus, param))
+ SetFocus( dlgInfo->hwndFocus );
- if (template.style & WS_VISIBLE && !(wndPtr->dwStyle & WS_VISIBLE))
- {
- ShowWindow32( hwnd, SW_SHOWNORMAL ); /* SW_SHOW doesn't always work */
- UpdateWindow32( hwnd );
- }
- return hwnd;
- }
- if( IsWindow32(hwnd) ) DestroyWindow32( hwnd );
- return 0;
+ //if (template.style & WS_VISIBLE && !(wndPtr->dwStyle & WS_VISIBLE))
+ //{
+ ShowWindow( hwnd, SW_SHOWNORMAL ); /* SW_SHOW doesn't always work */
+ UpdateWindow( hwnd );
+ // }
+
+
+ PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, 0,
+ RDW_INVALIDATE | RDW_ALLCHILDREN |
+ RDW_FRAME | RDW_ERASENOW | RDW_ERASE, 0 );
+ return hwnd;
+
}
-/**********************************************************************
- * DIALOG_DlgDirSelect
- *
- * Helper function for DlgDirSelect*
- */
-static WINBOOL DIALOG_DlgDirSelect( HWND32 hwnd, LPSTR str, INT32 len,
- INT32 id, WINBOOL win32, WINBOOL unicode,
- WINBOOL combo )
-{
- char *buffer, *ptr;
- INT32 item, size;
- WINBOOL ret;
- HWND32 listbox = GetDlgItem32( hwnd, id );
-
- TRACE(dialog, "%04x '%s' %d\n", hwnd, str, id );
- if (!listbox) return FALSE;
- if (win32)
- {
- item = SendMessage32A(listbox, combo ? CB_GETCURSEL32
- : LB_GETCURSEL32, 0, 0 );
- if (item == LB_ERR) return FALSE;
- size = SendMessage32A(listbox, combo ? CB_GETLBTEXTLEN32
- : LB_GETTEXTLEN32, 0, 0 );
- if (size == LB_ERR) return FALSE;
- }
- else
- {
- item = SendMessage32A(listbox, combo ? CB_GETCURSEL16
- : LB_GETCURSEL16, 0, 0 );
- if (item == LB_ERR) return FALSE;
- size = SendMessage32A(listbox, combo ? CB_GETLBTEXTLEN16
- : LB_GETTEXTLEN16, 0, 0 );
- if (size == LB_ERR) return FALSE;
- }
- if (!(buffer = SEGPTR_ALLOC( size+1 ))) return FALSE;
- if (win32)
- SendMessage32A( listbox, combo ? CB_GETLBTEXT32 : LB_GETTEXT32,
- item, (LPARAM)buffer );
- else
- SendMessage16( listbox, combo ? CB_GETLBTEXT16 : LB_GETTEXT16,
- item, (LPARAM)SEGPTR_GET(buffer) );
- if ((ret = (buffer[0] == '['))) /* drive or directory */
+/***********************************************************************
+ * DIALOG_IsAccelerator
+ */
+WINBOOL DIALOG_IsAccelerator( HWND hwnd, HWND hwndDlg, WPARAM vKey )
+{
+ HWND hwndControl = hwnd;
+ HWND hwndNext;
+ WND *wndPtr;
+ WINBOOL RetVal = FALSE;
+ INT dlgCode;
+
+ if (vKey == VK_SPACE)
{
- if (buffer[1] == '-') /* drive */
+ dlgCode = SendMessage( hwndControl, WM_GETDLGCODE, 0, 0 );
+ if (dlgCode & DLGC_BUTTON)
{
- buffer[3] = ':';
- buffer[4] = 0;
- ptr = buffer + 2;
+ SendMessage( hwndControl, WM_LBUTTONDOWN, 0, 0);
+ SendMessage( hwndControl, WM_LBUTTONUP, 0, 0);
+ RetVal = TRUE;
}
- else
+ }
+ else
+ {
+ do
{
- buffer[strlen(buffer)-1] = '\\';
- ptr = buffer + 1;
+ wndPtr = WIN_FindWndPtr( hwndControl );
+ if (wndPtr != NULL && wndPtr->text != NULL &&
+ (wndPtr->dwStyle & (WS_VISIBLE | WS_DISABLED)) == WS_VISIBLE)
+ {
+ dlgCode = SendMessage( hwndControl, WM_GETDLGCODE, 0, 0 );
+ if (dlgCode & (DLGC_BUTTON | DLGC_STATIC))
+ {
+ /* find the accelerator key */
+ LPSTR p = wndPtr->text - 2;
+ do
+ {
+ p = strchr( p + 2, '&' );
+ }
+ while (p != NULL && p[1] == '&');
+
+ /* and check if it's the one we're looking for */
+ if (p != NULL && toupper( p[1] ) == toupper( vKey ) )
+ {
+ if ((dlgCode & DLGC_STATIC) ||
+ (wndPtr->dwStyle & 0x0f) == BS_GROUPBOX )
+ {
+ /* set focus to the control */
+ SendMessage( hwndDlg, WM_NEXTDLGCTL,
+ hwndControl, 1);
+ /* and bump it on to next */
+ SendMessage( hwndDlg, WM_NEXTDLGCTL, 0, 0);
+ }
+ else if (dlgCode &
+ (DLGC_DEFPUSHBUTTON | DLGC_UNDEFPUSHBUTTON))
+ {
+ /* send command message as from the control */
+ SendMessage( hwndDlg, WM_COMMAND,
+ MAKEWPARAM( LOWORD(wndPtr->wIDmenu),
+ BN_CLICKED ),
+ (LPARAM)hwndControl );
+ }
+ else
+ {
+ /* click the control */
+ SendMessage( hwndControl, WM_LBUTTONDOWN, (WPARAM) 0, (LPARAM)0);
+ SendMessage( hwndControl, WM_LBUTTONUP, (WPARAM)0, (LPARAM)0);
+ }
+ RetVal = TRUE;
+ break;
+ }
+ }
+ }
+ hwndNext = GetWindow( hwndControl, GW_CHILD );
+ if (!hwndNext)
+ {
+ hwndNext = GetWindow( hwndControl, GW_HWNDNEXT );
+ }
+ while (!hwndNext)
+ {
+ hwndControl = GetParent( hwndControl );
+ if (hwndControl == hwndDlg)
+ {
+ hwndNext = GetWindow( hwndDlg, GW_CHILD );
+ }
+ else
+ {
+ hwndNext = GetWindow( hwndControl, GW_HWNDNEXT );
+ }
+ }
+ hwndControl = hwndNext;
}
+ while (hwndControl != hwnd);
}
- else ptr = buffer;
-
- if (unicode) lstrcpynAtoW( (LPWSTR)str, ptr, len );
- else lstrcpyn32A( str, ptr, len );
- SEGPTR_FREE( buffer );
- TRACE(dialog, "Returning %d '%s'\n", ret, str );
- return ret;
+ return RetVal;
}
+
-
-/**********************************************************************
- * DIALOG_DlgDirList
- *
- * Helper function for DlgDirList*
+/***********************************************************************
+ * DIALOG_IsDialogMessage
*/
-static INT32 DIALOG_DlgDirList( HWND32 hDlg, LPSTR spec, INT32 idLBox,
- INT32 idStatic, UINT32 attrib, WINBOOL combo )
+WINBOOL DIALOG_IsDialogMessage( HWND hwnd, HWND hwndDlg,
+ UINT message, WPARAM wParam,
+ LPARAM lParam, WINBOOL *translate,
+ WINBOOL *dispatch, INT dlgCode )
{
- int drive;
- HWND32 hwnd;
- LPSTR orig_spec = spec;
+ *translate = *dispatch = FALSE;
-#define SENDMSG(msg,wparam,lparam) \
- ((attrib & DDL_POSTMSGS) ? PostMessage32A( hwnd, msg, wparam, lparam ) \
- : SendMessage32A( hwnd, msg, wparam, lparam ))
+ if (message == WM_PAINT)
+ {
+ /* Apparently, we have to handle this one as well */
+ *dispatch = TRUE;
+ return TRUE;
+ }
- TRACE(dialog, "%04x '%s' %d %d %04x\n",
- hDlg, spec ? spec : "NULL", idLBox, idStatic, attrib );
+ /* Only the key messages get special processing */
+ if ((message != WM_KEYDOWN) &&
+ (message != WM_SYSCHAR) &&
+ (message != WM_CHAR))
+ return FALSE;
- if (spec && spec[0] && (spec[1] == ':'))
+ if (dlgCode & DLGC_WANTMESSAGE)
{
- drive = toupper( spec[0] ) - 'A';
- spec += 2;
- if (!DRIVE_SetCurrentDrive( drive )) return FALSE;
+ *translate = *dispatch = TRUE;
+ return TRUE;
}
- else drive = DRIVE_GetCurrentDrive();
- /* If the path exists and is a directory, chdir to it */
- if (!spec || !spec[0] || DRIVE_Chdir( drive, spec )) spec = "*.*";
- else
+ switch(message)
{
- char *p, *p2;
- p = spec;
- if ((p2 = strrchr( p, '\\' ))) p = p2;
- if ((p2 = strrchr( p, '/' ))) p = p2;
- if (p != spec)
+ case WM_KEYDOWN:
+ switch(wParam)
{
- char sep = *p;
- *p = 0;
- if (!DRIVE_Chdir( drive, spec ))
+ case VK_TAB:
+ if (!(dlgCode & DLGC_WANTTAB))
{
- *p = sep; /* Restore the original spec */
- return FALSE;
+ SendMessageA( hwndDlg, WM_NEXTDLGCTL,
+ (GetKeyState(VK_SHIFT) & 0x8000), 0 );
+ return TRUE;
}
- spec = p + 1;
- }
- }
+ break;
+
+ case VK_RIGHT:
+ case VK_DOWN:
+ case VK_LEFT:
+ case VK_UP:
+ if (!(dlgCode & DLGC_WANTARROWS))
+ {
+ WINBOOL fPrevious = (wParam == VK_LEFT || wParam == VK_UP);
+ HWND hwndNext =
+ GetNextDlgGroupItem (hwndDlg, GetFocus(), fPrevious );
+ SendMessageA( hwndDlg, WM_NEXTDLGCTL, hwndNext, 1 );
+ return TRUE;
+ }
+ break;
- TRACE(dialog, "path=%c:\\%s mask=%s\n",
- 'A' + drive, DRIVE_GetDosCwd(drive), spec );
+ case VK_ESCAPE:
+ SendMessageA( hwndDlg, WM_COMMAND, IDCANCEL,
+ (LPARAM)GetDlgItem( hwndDlg, IDCANCEL ) );
+ return TRUE;
- if (idLBox && ((hwnd = GetDlgItem32( hDlg, idLBox )) != 0))
- {
- SENDMSG( combo ? CB_RESETCONTENT32 : LB_RESETCONTENT32, 0, 0 );
- if (attrib & DDL_DIRECTORY)
- {
- if (!(attrib & DDL_EXCLUSIVE))
+ case VK_RETURN:
{
- if (SENDMSG( combo ? CB_DIR32 : LB_DIR32,
- attrib & ~(DDL_DIRECTORY | DDL_DRIVES),
- (LPARAM)spec ) == LB_ERR)
- return FALSE;
+ DWORD dw = SendMessage( hwndDlg, DM_GETDEFID, 0, 0 );
+ if (HIWORD(dw) == DC_HASDEFID)
+ {
+ SendMessageA( hwndDlg, WM_COMMAND,
+ MAKEWPARAM( LOWORD(dw), BN_CLICKED ),
+ (LPARAM)GetDlgItem(hwndDlg, LOWORD(dw)));
+ }
+ else
+ {
+ SendMessageA( hwndDlg, WM_COMMAND, IDOK,
+ (LPARAM)GetDlgItem( hwndDlg, IDOK ) );
+
+ }
}
- if (SENDMSG( combo ? CB_DIR32 : LB_DIR32,
- (attrib & (DDL_DIRECTORY | DDL_DRIVES)) | DDL_EXCLUSIVE,
- (LPARAM)"*.*" ) == LB_ERR)
- return FALSE;
+ return TRUE;
}
- else
- {
- if (SENDMSG( combo ? CB_DIR32 : LB_DIR32, attrib,
- (LPARAM)spec ) == LB_ERR)
- return FALSE;
- }
- }
+ *translate = TRUE;
+ break; /* case WM_KEYDOWN */
- if (idStatic && ((hwnd = GetDlgItem32( hDlg, idStatic )) != 0))
- {
- char temp[512];
- int drive = DRIVE_GetCurrentDrive();
- strcpy( temp, "A:\\" );
- temp[0] += drive;
- lstrcpyn32A( temp + 3, DRIVE_GetDosCwd(drive), sizeof(temp)-3 );
- CharLower32A( temp );
- /* Can't use PostMessage() here, because the string is on the stack */
- SetDlgItemText32A( hDlg, idStatic, temp );
- }
+ case WM_CHAR:
+ if (dlgCode & DLGC_WANTCHARS) break;
+ /* drop through */
- if (orig_spec && (spec != orig_spec))
- {
- /* Update the original file spec */
- char *p = spec;
- while ((*orig_spec++ = *p++));
+ case WM_SYSCHAR:
+ if (DIALOG_IsAccelerator( hwnd, hwndDlg, wParam ))
+ {
+ /* don't translate or dispatch */
+ return TRUE;
+ }
+ break;
}
+ /* If we get here, the message has not been treated specially */
+ /* and can be sent to its destination window. */
+ *dispatch = TRUE;
return TRUE;
-#undef SENDMSG
}
-/**********************************************************************
- * DIALOG_DlgDirListW
- *
- * Helper function for DlgDirList*32W
- */
-static INT32 DIALOG_DlgDirListW( HWND32 hDlg, LPWSTR spec, INT32 idLBox,
- INT32 idStatic, UINT32 attrib, WINBOOL combo )
-{
- if (spec)
- {
- LPSTR specA = HEAP_strdupWtoA( GetProcessHeap(), 0, spec );
- INT32 ret = DIALOG_DlgDirList( hDlg, specA, idLBox, idStatic,
- attrib, combo );
- lstrcpyAtoW( spec, specA );
- HeapFree( GetProcessHeap(), 0, specA );
- return ret;
- }
- return DIALOG_DlgDirList( hDlg, NULL, idLBox, idStatic, attrib, combo );
-}
-
if ( ptr1[i] == 0 )
break;
}
+ return i;
}
int lpstrncpyW( LPWSTR ptr1,LPWSTR ptr2, int n)
{
if ( ptr1[i] == 0 )
break;
}
+ return i;
}
LPSTR HEAP_strdupA(HANDLE hHeap,DWORD dwFlags,LPCSTR ptr)
lstrcpyW(lpszString,ptr);
return lpszString;
+}
+
+int HEAP_memset( void *d,int c ,int count)
+{
+ return memset(d,c,count);
+}
+
+int HEAP_memcpy( void *d,void *s,int c)
+{
+ return memcpy(d,s,c);
}
\ No newline at end of file
-#undef WIN32_LEAN_AND_MEAN
+
#include <windows.h>
#include <user32/win.h>
-//#include <user32/debug.h>
+#include <user32/debug.h>
#include <user32/resource.h>
#include <user32/sysmetr.h>
+#include <user32/syscolor.h>
#include <user32/menu.h>
#include <user32/nc.h>
-#include <stdlib.h>
+#include <user32/heapdup.h>
#include <wchar.h>
-#include <stdlib.h>
+//#include <stdlib.h>
typedef struct tagMDINEXTMENU
{
WINBOOL fEndMenu = FALSE;
-#include<stdio.h>
-#define DPRINT printf
-
/***********************************************************************
* debug_print_menuitem
*
* Calculate the size of the menu bar.
*/
-static void MENU_MenuBarCalcSize( HDC hdc, LPRECT lprect,
+void MENU_MenuBarCalcSize( HDC hdc, LPRECT lprect,
LPPOPUPMENU lppop, HWND hwndOwner )
{
MENUITEM *lpitem;
}
menu->items = newItems;
menu->nItems++;
- memset( &newItems[pos], 0, sizeof(*newItems) );
+ HEAP_memset( &newItems[pos], 0, sizeof(*newItems) );
return &newItems[pos];
}
* Copyright 1993, 1994 Alexandre Julliard
*/
-#include <stdlib.h>
+
#include <string.h>
#include <ctype.h>
-#include <sys/time.h>
+//#include <sys/time.h>
#include <sys/types.h>
#include <windows.h>
#include <user32/msg.h>
#include <user32/debug.h>
#include <user32/winpos.h>
#include <user32/queue.h>
+#include <user32/heapdup.h>
if (HOOK_IsHooked( WH_MOUSE ))
{
- MOUSEHOOKSTRUCT *hook = malloc(sizeof(MOUSEHOOKSTRUCT));
+ MOUSEHOOKSTRUCT *hook = HeapAlloc(GetProcessHeap(),0,sizeof(MOUSEHOOKSTRUCT));
if( hook )
{
hook->pt = screen_pt;
hook->hwnd = hWnd;
hook->wHitTestCode = hittest;
hook->dwExtraInfo = 0;
- ret = HOOK_CallHooksA( WH_MOUSE, remove ? HC_ACTION : HC_NOREMOVE,
- message, (LPARAM)(hook) );
- free(hook);
+ ret = HOOK_CallHooks( WH_MOUSE, remove ? HC_ACTION : HC_NOREMOVE,
+ message, (LPARAM)(hook), pWnd->class->bUnicode );
+ HeapFree(GetProcessHeap(),0,hook);
}
if( ret ) return MAKELONG((INT)SYSQ_MSG_SKIP, hittest);
}
return FALSE;
}
+
/***********************************************************************
* MSG_SendMessage
*
* Implementation of an inter-task SendMessage.
*/
-LRESULT MSG_SendMessage( HQUEUE hDestQueue, HWND hwnd, UINT msg,
- WPARAM wParam, LPARAM lParam, WORD flags )
+LRESULT MSG_SendMessageInterTask( HWND hwnd, UINT msg,
+ WPARAM wParam, LPARAM lParam, WINBOOL bUnicode)
{
+
+ WND *wndPtr;
+ WND **list, **ppWnd;
INT prevSMRL = debugSMRL;
QSMCTRL qCtrl = { 0, 1};
MESSAGEQUEUE *queue, *destQ;
+ if (hwnd == HWND_BROADCAST || hwnd == HWND_TOPMOST)
+ {
+ if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
+ return TRUE;
+ for (ppWnd = list; *ppWnd; ppWnd++)
+ {
+ wndPtr = *ppWnd;
+ //if (!WIN_IsWindow(wndPtr))
+ //continue;
+ if (wndPtr->dwStyle & WS_POPUP || wndPtr->dwStyle & WS_CAPTION)
+ MSG_SendMessageInterTask( wndPtr->hwndSelf, msg, wParam, lParam, bUnicode );
+ }
+ HeapFree( GetProcessHeap(), 0, list );
+ return TRUE;
+ }
+
+
+// should turn queue and destQ around
+
if (!(queue = (MESSAGEQUEUE*)GlobalLock( GetFastQueue() ))) return 0;
- if (!(destQ = (MESSAGEQUEUE*)GlobalLock( hDestQueue ))) return 0;
+ if (!(destQ = (MESSAGEQUEUE*)GlobalLock( wndPtr->hmemTaskQ ))) return 0;
- if (
+ //if (
//IsTaskLocked() ||
- !IsWindow(hwnd)) return 0;
+ //!IsWindow(hwnd)) return 0;
debugSMRL+=4;
DPRINT("%*sSM: %s [%04x] (%04x -> %04x)\n",
QUEUE_WaitBits( QS_SMPARAMSFREE );
}
+
+
+
/* resume sending */
queue->hWnd = hwnd;
destQ->hSendingTask = GetFastQueue();
QUEUE_ClearWakeBit( queue, QS_SMPARAMSFREE );
- queue->flags = (queue->flags & ~(QUEUE_SM_ASCII|QUEUE_SM_UNICODE)) | flags;
+// queue->flags = (queue->flags & ~(QUEUE_SM_ASCII|QUEUE_SM_UNICODE)) | flags;
DPRINT("%*ssm: smResultInit = %08x\n", prevSMRL, "", (unsigned)&qCtrl);
WINBOOL MSG_PeekMessage( LPMSG msg, HWND hwnd, WORD first, WORD last,
WORD flags, WINBOOL peek )
{
+#if 0
+ case MOUSE_EVENT:
+ MouseEvent = &Buffer.Event;
+ if ( MouseEvent->dwEventFlags == MOUSE_MOVED ) {
+ msg->hwnd = hwnd;
+ msg->message = WM_MOUSEMOVE;
+ msg->wParam = MouseEvent->dwControlKeyState;
+ msg->lParam =
+ MAKELONG(MouseEvent->dwMousePosition.X,MouseEvent->dwMousePosition.Y);
+ }
+ else if ( MouseEvent->dwEventFlags == DOUBLE_CLICK ) {
+ msg->hwnd = hwnd;
+ msg->message = WM_MBUTTONDBLCLK;
+ msg->wParam = MouseEvent->dwControlKeyState;
+ msg->lParam =
+ MAKELONG(MouseEvent->dwMousePosition.X,MouseEvent->dwMousePosition.Y);
+
+ }
+ else {
+ if (MouseEvent->dwButtonState == FROM_LEFT_1ST_BUTTON_PRESSED ) {
+ msg->hwnd = hwnd;
+ msg->message = WM_MBUTTONDOWN ;
+ msg->wParam = MouseEvent->dwControlKeyState;
+ msg->lParam =
+ MAKELONG(MouseEvent->dwMousePosition.X,MouseEvent->dwMousePosition.Y);
+ }
+ else {
+ msg->hwnd = hwnd;
+ msg->message = WM_MBUTTONUP ;
+ msg->wParam = MouseEvent->dwControlKeyState;
+ msg->lParam =
+ MAKELONG(MouseEvent->dwMousePosition.X,MouseEvent->dwMousePosition.Y);
+ }
+ }
+ break;
+ #endif
+
+
+msg->hwnd = hwnd;
+msg->message = WM_MBUTTONDBLCLK;
+msg->wParam = 0;
+msg->lParam = MAKELONG(200,200);
+
+return TRUE;
+
+#if 0
int pos, mask;
MESSAGEQUEUE *msgQueue;
HQUEUE hQueue;
}
if (peek) return TRUE;
else return (msg->message != WM_QUIT);
+
+ #endif
+
}
/***********************************************************************
}
+LRESULT MSG_SendMessage( WND *wndPtr, UINT msg, WPARAM wParam, LPARAM lParam )
+{
+
+ LRESULT ret;
+
+ if ( wndPtr == NULL )
+ return 0;
+
+ // if (QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))
+ // return 0; /* Don't send anything if the task is dying */
+
+
+
+ if ( wndPtr->class->bUnicode )
+ ret = CallWindowProcW( (WNDPROC)wndPtr->winproc,
+ wndPtr->hwndSelf, msg, wParam, lParam );
+ else
+ ret = CallWindowProcA( (WNDPROC)wndPtr->winproc,
+ wndPtr->hwndSelf, msg, wParam, lParam );
+
+ return ret;
+}
+
HTASK GetCurrentTask(void)
{
return (HTASK)-2;
{
if ( init == 0 ) {
init = 1;
- memset(&Queue,0,sizeof(MESSAGEQUEUE));
+ HEAP_memset(&Queue,0,sizeof(MESSAGEQUEUE));
}
return hThreadQ;
}
#include <windows.h>
#include <stdlib.h>
#include <user32/nc.h>
+#include <user32/syscolor.h>
#include <user32/debug.h>
+// GetBitmapDimensionEx in NC_DrawMaxButton95 returns TRUE on invalid bitmap
+
static HBITMAP hbitmapClose = 0;
static HBITMAP hbitmapCloseD = 0;
static HBITMAP hbitmapMinimize = 0;
/* Decide if the window will be managed (see CreateWindowEx) */
// Options.managed &&
+
if (!( !(style & WS_CHILD) &&
((style & (WS_DLGFRAME | WS_THICKFRAME)) ||
(exStyle & WS_EX_DLGMODALFRAME))))
{
if (HAS_SIZEFRAME(style))
InflateRect( rect, SYSMETRICS_CXFRAME, SYSMETRICS_CYFRAME );
-#if 0
+
if (style & WS_BORDER)
InflateRect( rect, SYSMETRICS_CXBORDER, SYSMETRICS_CYBORDER);
-#endif
+
}
if ((style & WS_CAPTION) == WS_CAPTION)
}
} else {
-
+ if (HAS_SIZEFRAME(style))
+ InflateRect( rect, SYSMETRICS_CXFRAME, SYSMETRICS_CYFRAME );
+#if 0
if (style & WS_BORDER)
InflateRect( rect, SYSMETRICS_CXBORDER, SYSMETRICS_CYBORDER);
-
+#endif
if ((style & WS_CAPTION) == WS_CAPTION)
{
InflateRect( rect, -SYSMETRICS_CXBORDER, -SYSMETRICS_CYBORDER );*/
}
- if (wndPtr->dwStyle & WS_CHILD) {
+// if (wndPtr->dwStyle & WS_CHILD) {
if (wndPtr->dwExStyle & WS_EX_CLIENTEDGE)
InflateRect(rect, -SYSMETRICS_CXEDGE, -SYSMETRICS_CYEDGE);
if (wndPtr->dwExStyle & WS_EX_STATICEDGE)
InflateRect(rect, -SYSMETRICS_CXBORDER, -SYSMETRICS_CYBORDER);
- }
+ // }
return;
}
WND *wndPtr = WIN_FindWndPtr( hwnd );
SIZE bmsz;
HBITMAP bm;
+ BITMAP bmp;
HDC hdcMem;
- if( !(wndPtr->flags & WIN_MANAGED) &&
+
+ if( !(wndPtr->flags & WIN_MANAGED) ) {
GetBitmapDimensionEx((bm = IsZoomed(hwnd) ?
- (down ? hbitmapRestoreD : hbitmapRestore ) :
- (down ? hbitmapMaximizeD : hbitmapMaximize)),
- &bmsz)) {
+ (down ? hbitmapRestoreD : hbitmapRestore ) :
+ (down ? hbitmapMaximizeD : hbitmapMaximize)),
+ &bmsz);
+
+ if ( bmsz.cx == 0 || bmsz.cy == 0 ) {
+ GetObject(bm, sizeof(BITMAP), &bmp);
+ bmsz.cx = bmp.bmWidth;
+ bmsz.cy = bmp.bmHeight;
+ DPRINT("WARN GetBitmapDimensionEx returned 0 size ");
+ }
NC_GetInsideRect95( hwnd, &rect );
*
*****************************************************************************/
-static void NC_DrawCaption95(
+void NC_DrawCaption95(
HDC hdc,
RECT *rect,
HWND hwnd,
WND *wndPtr = WIN_FindWndPtr( hwnd );
char buffer[256];
HPEN hPrevPen;
+ int txt;
if (wndPtr->flags & WIN_MANAGED) return;
MoveToEx( hdc, r.left, r.bottom - 1, NULL );
LineTo( hdc, r.right, r.bottom - 1 );
SelectObject( hdc, hPrevPen );
- r.bottom-2;
+ // r.bottom - 2;
FillRect( hdc, &r, GetSysColorBrush(active ? COLOR_ACTIVECAPTION :
NC_DrawMinButton95( hwnd, hdc, FALSE );
r.right -= SYSMETRICS_CXSIZE + 1;
}
+
+ if ( wndPtr->class->bUnicode )
+ txt = GetWindowTextW( hwnd, buffer, sizeof(buffer) );
+ else
+ txt = GetWindowTextA( hwnd, buffer, sizeof(buffer) );
+
- if (GetWindowTextA( hwnd, buffer, sizeof(buffer) )) {
+ if (txt) {
NONCLIENTMETRICS nclm;
HFONT hFont, hOldFont;
nclm.cbSize = sizeof(NONCLIENTMETRICS);
else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
SetBkMode( hdc, TRANSPARENT );
r.left += 2;
- DrawTextA( hdc, buffer, -1, &r,
+ if ( wndPtr->class->bUnicode )
+ DrawTextW( hdc, buffer, -1, &r,
+ DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT );
+ else
+ DrawTextA( hdc, buffer, -1, &r,
DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT );
DeleteObject(SelectObject (hdc, hOldFont));
}
if (!(hdc = GetDCEx( hwnd, 0, DCX_USESTYLE | DCX_WINDOW ))) return;
- if (ExcludeVisRect( hdc, wndPtr->rectClient.left-wndPtr->rectWindow.left,
- wndPtr->rectClient.top-wndPtr->rectWindow.top,
- wndPtr->rectClient.right-wndPtr->rectWindow.left,
- wndPtr->rectClient.bottom-wndPtr->rectWindow.top )
+ if (ExcludeVisRect( hdc, wndPtr->rectClient.left -wndPtr->rectWindow.left,
+ wndPtr->rectClient.top -wndPtr->rectWindow.top,
+ wndPtr->rectClient.right -wndPtr->rectWindow.left,
+ wndPtr->rectClient.bottom -wndPtr->rectWindow.top )
== NULLREGION)
{
ReleaseDC( hwnd, hdc );
{
WORD wStateChange;
- if( wParam ) wStateChange = !(wndPtr->flags & WIN_NCACTIVATED);
- else wStateChange = wndPtr->flags & WIN_NCACTIVATED;
+// if( wParam ) wStateChange = !(wndPtr->flags & WIN_NCACTIVATED);
+// else wStateChange = wndPtr->flags & WIN_NCACTIVATED;
- if( wStateChange )
+// if( wStateChange )
{
if (wParam) wndPtr->flags |= WIN_NCACTIVATED;
else wndPtr->flags &= ~WIN_NCACTIVATED;
/* Last CTLCOLOR id */
//#define CTLCOLOR_MAX CTLCOLOR_STATIC
+HBRUSH DEFWND_ControlColor( HDC hDC, UINT ctlType );
/***********************************************************************
if (!hwnd) hwnd = GetDesktopWindow();
if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
+
+#ifdef OPTIMIZE
if (!WIN_IsWindowDrawable( wndPtr, !(flags & RDW_FRAME) ) )
return TRUE; /* No redraw needed */
+#endif
bIcon = (wndPtr->dwStyle & WS_MINIMIZE && wndPtr->class->hIcon);
- if (rectUpdate)
- {
- DPRINT( "%04x %d,%d-%d,%d %04x flags=%04x\n",
- hwnd, rectUpdate->left, rectUpdate->top,
- rectUpdate->right, rectUpdate->bottom, hrgnUpdate, flags );
- }
- else
- {
- DPRINT( "%04x NULL %04x flags=%04x\n", hwnd, hrgnUpdate, flags);
- }
-
+
GetClientRect( hwnd, &rectClient );
if (flags & RDW_INVALIDATE) /* Invalidate */
{
int rgnNotEmpty = COMPLEXREGION;
- if (wndPtr->hrgnUpdate > 1) /* Is there already an update region? */
+ if (wndPtr->hrgnUpdate > (HRGN)1) /* Is there already an update region? */
{
if ((hrgn = hrgnUpdate) == 0)
hrgn = CreateRectRgnIndirect( rectUpdate ? rectUpdate :
else if (flags & RDW_VALIDATE) /* Validate */
{
/* We need an update region in order to validate anything */
- if (wndPtr->hrgnUpdate > 1)
+ if (wndPtr->hrgnUpdate > (HRGN)1)
{
if (!hrgnUpdate && !rectUpdate)
{
if (flags & RDW_INTERNALPAINT)
{
- if ( wndPtr->hrgnUpdate <= 1 && !(wndPtr->flags & WIN_INTERNAL_PAINT))
+ if ( wndPtr->hrgnUpdate <= (HRGN)1 && !(wndPtr->flags & WIN_INTERNAL_PAINT))
QUEUE_IncPaintCount( wndPtr->hmemTaskQ );
wndPtr->flags |= WIN_INTERNAL_PAINT;
}
else if (flags & RDW_NOINTERNALPAINT)
{
- if ( wndPtr->hrgnUpdate <= 1 && (wndPtr->flags & WIN_INTERNAL_PAINT))
+ if ( wndPtr->hrgnUpdate <= (HRGN)1 && (wndPtr->flags & WIN_INTERNAL_PAINT))
QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
wndPtr->flags &= ~WIN_INTERNAL_PAINT;
}
}
else if (flags & RDW_ERASENOW)
{
- if (wndPtr->flags & WIN_NEEDS_NCPAINT)
+ //if (wndPtr->flags & WIN_NEEDS_NCPAINT)
WIN_UpdateNCArea( wndPtr, FALSE);
- if (wndPtr->flags & WIN_NEEDS_ERASEBKGND)
+ //if (wndPtr->flags & WIN_NEEDS_ERASEBKGND)
{
HDC hdc = GetDCEx( hwnd, wndPtr->hrgnUpdate,
DCX_INTERSECTRGN | DCX_USESTYLE |
return TRUE;
}
+/***********************************************************************
+ * GetControlBrush Not A Win32 API
+ */
+HBRUSH GetControlBrush( HWND hwnd, HDC hdc, UINT ctlType )
+{
+ WND* wndPtr = WIN_FindWndPtr( hwnd );
+
+ if((ctlType <= CTLCOLOR_MAX) && wndPtr )
+ {
+ WND* parent;
+ if( wndPtr->dwStyle & WS_POPUP ) parent = wndPtr->owner;
+ else parent = wndPtr->parent;
+ if( !parent ) parent = wndPtr;
+ return (HBRUSH)PAINT_GetControlBrush( parent->hwndSelf, hwnd, hdc, ctlType );
+ }
+ return (HBRUSH)0;
+}
+
+/***********************************************************************
+ * PAINT_GetControlBrush
+ */
+HBRUSH PAINT_GetControlBrush( HWND hParent, HWND hWnd, HDC hDC, UINT ctlType )
+{
+ LOGBRUSH LogBrush;
+ HBRUSH bkgBrush = (HBRUSH)SendMessageA( hParent, WM_CTLCOLORMSGBOX + ctlType,
+ (WPARAM)hDC, (LPARAM)hWnd );
+ if( !GetObject(bkgBrush,sizeof(LOGBRUSH),&LogBrush) )
+ bkgBrush = DEFWND_ControlColor( hDC, ctlType );
+ return bkgBrush;
+}
+
+
+
#include <user32/scroll.h>
#include <user32/msg.h>
#include <user32/win.h>
+#include <user32/caret.h>
#include <user32/debug.h>
#define MAKEINTRESOURCEA(x) "x"
/* Return current position */
return infoPtr->CurVal;
+}
+
+/*************************************************************************
+ * SCROLL_FixCaret
+ */
+WINBOOL SCROLL_FixCaret(HWND hWnd, LPRECT lprc, UINT flags)
+{
+ HWND hCaret = CARET_GetHwnd();
+
+ if( hCaret )
+ {
+ RECT rc;
+ CARET_GetRect( &rc );
+ if( hCaret == hWnd ||
+ (flags & SW_SCROLLCHILDREN && IsChild(hWnd, hCaret)) )
+ {
+ POINT pt;
+
+ pt.x = rc.left; pt.y = rc.top;
+ MapWindowPoints( hCaret, hWnd, (LPPOINT)&rc, 2 );
+ if( IntersectRect(lprc, lprc, &rc) )
+ {
+ HideCaret(0);
+ lprc->left = pt.x; lprc->top = pt.y;
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
}
\ No newline at end of file
*/
#include <windows.h>
+#include <user32/syscolor.h>
#include <user32/debug.h>
-HPEN STDCALL GetSysColorPen( INT index );
static const WORD wPattern_AA55[8] = { 0xaaaa, 0x5555, 0xaaaa, 0x5555,
0xaaaa, 0x5555, 0xaaaa, 0x5555 };
* UITOOLS_DrawRectEdge()
*/
-/* DrawEdge() flags */
-#define BDR_RAISEDOUTER 0x0001
-#define BDR_SUNKENOUTER 0x0002
-#define BDR_RAISEDINNER 0x0004
-#define BDR_SUNKENINNER 0x0008
+
#define BDR_OUTER 0x0003
#define BDR_INNER 0x000c
#include <user32/dce.h>
#include <user32/caret.h>
#include <user32/debug.h>
+#include <user32/heapdup.h>
+#include <user32/dialog.h>
WND *rootWnd;
//////////////////////////////////////////////////////////////////////////////////
? MENU_GetSysMenu( hWnd, 0 ) : 0;
if (classPtr->cbWndExtra)
- memset( wndPtr->wExtra, 0, classPtr->cbWndExtra);
+ HEAP_memset( wndPtr->wExtra, 0, classPtr->cbWndExtra);
/* Call the WH_CBT hook */
cbtc.lpcs = cs;
cbtc.hwndInsertAfter = hWndLinkAfter;
- ret = HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND, hWnd, (LPARAM)&cbtc);
+ ret = HOOK_CallHooks(WH_CBT, HCBT_CREATEWND, (INT)hWnd, (LPARAM)&cbtc, classPtr->bUnicode);
if (ret)
{
maxPos.x = wndPtr->rectWindow.left;
maxPos.y = wndPtr->rectWindow.top;
- if ( classPtr->bUnicode == TRUE ) {
- if( SendMessageW( hWnd, WM_NCCREATE, 0, (LPARAM)cs) == 0)
- {
- /* Abort window creation */
- WIN_DestroyWindow( wndPtr );
- return NULL;
- }
- } else {
- if( SendMessageA( hWnd, WM_NCCREATE, 0, (LPARAM)cs) == 0)
- {
+
+ if( MSG_SendMessage( wndPtr, WM_NCCREATE, 0, (LPARAM)cs) == 0)
+ {
/* Abort window creation */
- WIN_DestroyWindow( wndPtr );
- return NULL;
- }
+ WIN_DestroyWindow( wndPtr );
+ return NULL;
}
+
/* Insert the window in the linked list */
maxPos.y - wndPtr->rectWindow.top);
- if( (SendMessageA( hWnd, WM_CREATE, 0, (LPARAM)cs )) == -1 )
+ if( (MSG_SendMessage( wndPtr, WM_CREATE, 0, (LPARAM)cs)) == -1 )
{
WIN_UnlinkWindow( hWnd );
WIN_DestroyWindow( wndPtr );
if (((wndPtr->rectClient.right-wndPtr->rectClient.left) <0)
||((wndPtr->rectClient.bottom-wndPtr->rectClient.top)<0))
- SendMessageA( hWnd, WM_SIZE, SIZE_RESTORED,
+ MSG_SendMessage( wndPtr, WM_SIZE, SIZE_RESTORED,
MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
wndPtr->rectClient.bottom-wndPtr->rectClient.top));
- SendMessageA( hWnd, WM_MOVE, 0,
+ MSG_SendMessage( wndPtr, WM_MOVE, 0,
MAKELONG( wndPtr->rectClient.left,
- wndPtr->rectClient.top ) );
+ wndPtr->rectClient.top) );
}
/* Show the window, maximizing or minimizing if needed */
{
/* Notify the parent window only */
- SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
+ MSG_SendMessage( wndPtr->parent, WM_PARENTNOTIFY,
MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hWnd );
if( !IsWindow(hWnd) ) return 0;
}
/* Call WH_SHELL hook */
if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
- HOOK_CallHooksW( WH_SHELL, HSHELL_WINDOWCREATED, hWnd, 0L );
+ HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (INT)hWnd, 0L, classPtr->bUnicode);
return hWnd;
}
+WINBOOL WIN_IsWindow(HANDLE hWnd)
+{
+ if (WIN_FindWndPtr( hWnd ) == NULL) return FALSE;
+ return TRUE;
+}
+
/***********************************************************************
* WIN_FindWinToRepaint
*
/* Special case for dialog window procedure */
if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
{
- retval = ptr;
+ retval = (LONG)ptr;
*ptr = newval;
return (LONG)retval;
}
else switch(offset)
{
case GWL_ID:
- ptr = (DWORD*)&wndPtr->wIDmenu;
+ ptr = (LONG*)&wndPtr->wIDmenu;
break;
case GWL_HINSTANCE:
- return SetWindowWord( hwnd, offset, newval );
+ return (LONG)SetWindowWord( hwnd, offset, newval );
case GWL_WNDPROC:
- retval = wndPtr->winproc;
+ retval = (LONG)wndPtr->winproc;
wndPtr->winproc = (WNDPROC)newval;
return retval;
case GWL_STYLE:
newval &= ~(WS_VISIBLE | WS_CHILD); /* Some bits can't be changed this way */
style.styleNew = newval | (style.styleOld & (WS_VISIBLE | WS_CHILD));
- //if (wndPtr->flags & WIN_ISWIN32)
- SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
+
+ MSG_SendMessage(wndPtr,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
wndPtr->dwStyle = style.styleNew;
- //if (wndPtr->flags & WIN_ISWIN32)
- SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
+
+ MSG_SendMessage(wndPtr,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
return style.styleOld;
case GWL_USERDATA:
- ptr = &wndPtr->userdata;
+ ptr = (LONG *)&wndPtr->userdata;
break;
case GWL_EXSTYLE:
style.styleOld = wndPtr->dwExStyle;
style.styleNew = newval;
- //if (wndPtr->flags & WIN_ISWIN32)
- SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
- wndPtr->dwExStyle = newval;
- //if (wndPtr->flags & WIN_ISWIN32)
- SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
+ MSG_SendMessage(wndPtr,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
+ wndPtr->dwExStyle = newval;
+ MSG_SendMessage(wndPtr,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
return style.styleOld;
default:
HWND hWnd;
WND *pWnd;
+ if ( wndPtr == NULL )
+ return FALSE;
+
hWnd = wndPtr->hwndSelf;
-#ifdef CONFIG_IPC
- if (main_block)
- DDE_DestroyWindow(wndPtr->hwndSelf);
-#endif /* CONFIG_IPC */
+
/* free child windows */
while ((pWnd = wndPtr->child))
- wndPtr->child = WIN_DestroyWindow( pWnd );
+ if ( !WIN_DestroyWindow( pWnd ) )
+ break;
- SendMessageA( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
+ MSG_SendMessage( wndPtr, WM_NCDESTROY, 0, 0);
/* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
if (!(wndPtr->dwStyle & WS_CHILD))
if (wndPtr->wIDmenu) DestroyMenu( (HMENU)wndPtr->wIDmenu );
if (wndPtr->hSysMenu) DestroyMenu( wndPtr->hSysMenu );
- //wndPtr->pDriver->pDestroyWindow( wndPtr );
+
- //DeleteDC(wndPtr->dc) /* Always do this to catch orphaned DCs */
+ // DeleteDC(wndPtr->dc) /* Always do this to catch orphaned DCs */
wndPtr->winproc = NULL;
wndPtr->hwndSelf = NULL;
void WIN_UpdateNCArea(WND* wnd, BOOL bUpdate)
{
POINT pt = {0, 0};
- HRGN hClip = 1;
-
- DPRINT("hwnd %04x, hrgnUpdate %04x\n",
- wnd->hwndSelf, wnd->hrgnUpdate );
+ HRGN hClip = (HRGN)1;
/* desktop window doesn't have nonclient area */
if(wnd == WIN_GetDesktop())
return;
}
- if( wnd->hrgnUpdate > 1 )
+ if( wnd->hrgnUpdate > (HRGN)1 )
{
ClientToScreen(wnd->hwndSelf, &pt);
if (!CombineRgn( hClip, wnd->hrgnUpdate, 0, RGN_COPY ))
{
DeleteObject(hClip);
- hClip = 1;
+ hClip = (HRGN)1;
}
else
OffsetRgn( hClip, pt.x, pt.y );
hrgn, RGN_AND) == NULLREGION))
{
DeleteObject( wnd->hrgnUpdate );
- wnd->hrgnUpdate = 1;
+ wnd->hrgnUpdate = (HRGN)1;
}
DeleteObject( hrgn );
wnd->flags &= ~WIN_NEEDS_NCPAINT;
+#ifdef OPTIMIZE
if ((wnd->hwndSelf == GetActiveWindow()) &&
!(wnd->flags & WIN_NCACTIVATED))
{
wnd->flags |= WIN_NCACTIVATED;
- if( hClip > 1) DeleteObject( hClip );
- hClip = 1;
+ if( hClip > (HRGN)1) DeleteObject( hClip );
+ hClip = (HRGN)1;
}
+#endif
- if (hClip) SendMessage( wnd->hwndSelf, WM_NCPAINT, hClip, 0L );
+ if (hClip) MSG_SendMessage( wnd, WM_NCPAINT, (WPARAM)hClip, 0L );
- if (hClip > 1) DeleteObject( hClip );
+ if (hClip > (HRGN)1) DeleteObject( hClip );
}
/***********************************************************************
WIN_CheckFocus(pWnd);
if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret();
-// CLIPBOARD_GetDriver()->pResetOwner( pWnd, TRUE );
+
- SendMessageA( pWnd->hwndSelf, WM_DESTROY, 0, 0);
+ MSG_SendMessage( pWnd, WM_DESTROY, 0, 0);
if( IsWindow(pWnd->hwndSelf) )
{
}
+/***********************************************************************
+ * IsDialogMessage (USER32.90)
+ */
+WINBOOL STDCALL WIN_IsDialogMessage( HWND hwndDlg, LPMSG msg )
+{
+
+ WINBOOL ret, translate, dispatch;
+ INT dlgCode;
+
+ if ((hwndDlg != msg->hwnd) && !IsChild( hwndDlg, msg->hwnd ))
+ return FALSE;
+
+ dlgCode = SendMessage( msg->hwnd, WM_GETDLGCODE, 0, (LPARAM)msg);
+ ret = DIALOG_IsDialogMessage( msg->hwnd, hwndDlg, msg->message,
+ msg->wParam, msg->lParam,
+ &translate, &dispatch, dlgCode );
+ if (translate) TranslateMessage( msg );
+ if (dispatch) DispatchMessage( msg );
+ return ret;
+}
all: user32.exe
INTERNAL_OBJECTS = internal/property.o internal/menu.o internal/heapdup.o internal/nc.o\
- internal/scroll.o internal/win.o internal/dce.o internal/msg.o internal/queue.o\
+ internal/win.o internal/dce.o internal/msg.o internal/queue.o\
internal/signal.o internal/event.o internal/timer.o internal/region.o\
- internal/text.o internal/defwnd.o internal/paint.o internal/uitools.o
+ internal/text.o internal/defwnd.o internal/paint.o internal/uitools.o\
+ internal/dialog.o
MISC_OBJECTS = misc/sprintf.o misc/dllmain.o misc/string.o misc/sysmetr.o\
misc/main.o misc/bitmap.o misc/cursor.o misc/vk.o
WINDOWS_OBJECTS = windows/wndproc.o windows/win.o windows/hook.o windows/spy.o\
- windows/queue.o windows/winpos.o windows/class.o windows/menu.o windows/dc.o\
+ windows/queue.o windows/winpos.o windows/class.o windows/dc.o\
windows/timer.o windows/rect.o windows/msg.o windows/input.o windows/property.o\
- windows/focus.o windows/paint.o
+ windows/focus.o windows/paint.o windows/msgbox.o windows/dialog.o\
+ windows/scroll.o windows/defdlg.o
GRAPHICS_OBJECTS = graphics/rect.o graphics/caret.o graphics/text.o graphics/syscol.o graphics/fill.o\
graphics/draw.o graphics/icon.o
-RESOURCE_OBJECTS = resources/sysres.o
+CONTROLS_OBJECTS = controls/button.o controls/combo.o controls/edit.o controls/icontitle.o controls/listbox.o\
+ controls/widgets.o controls/menu.o controls/scroll.o controls/static.o
-OBJECTS = $(MISC_OBJECTS) $(INTERNAL_OBJECTS) $(GRAPHICS_OBJECTS) $(RESOURCE_OBJECTS) $(WINDOWS_OBJECTS)
+RESOURCE_OBJECTS = resources/sysres.o
+
+RESOURCE_OBJECT = user32.coff
+
+OBJECTS = $(MISC_OBJECTS) $(INTERNAL_OBJECTS) $(GRAPHICS_OBJECTS) $(RESOURCE_OBJECTS) $(RESOURCE_OBJECT)\
+ $(CONTROLS_OBJECTS) $(WINDOWS_OBJECTS)
+
+user32.coff: user32.rc ../../include/reactos/resource.h
+ windres user32.rc user32.coff
user32.exe: $(OBJECTS)
$(LD) $(OBJECTS) F:/gnu/cygnus/cygwin-b20/H-i586-cygwin32/i586-cygwin32/lib/crt1.o ./libgdi32.a ./libkernel32.a ./libcrtdll.a -o user32.exe
return hbitmap;
#endif
}
+
+
+
#include <windows.h>
+#include <stdio.h>
+
LRESULT CALLBACK WindowFunc(HWND,UINT,WPARAM, LPARAM);
char szName[] = "Hallo";
+
int _CRT_fmode = 0;
int _CRT_glob = 0;
}
+int i;
+
+
+
int main(int argc, char **argv)
{
+ WIDGETS_Init();
+#if 0
HWND hwnd;
+ HWND User32hWnd;
HMENU hmenu;
MSG msg;
WNDCLASSEX wc1;
HINSTANCE hInst = 0;
int nWinMode = SW_SHOW;
+ unsigned short *test;
- RECT rect;
+
+ HANDLE hMod, hrsrc;
+ RECT rect, cl;
wc1.hInstance = hInst;
wc1.lpszClassName = szName;
wc1.lpfnWndProc = WindowFunc;
wc1.style = 0;
wc1.cbSize = sizeof(WNDCLASSEX);
- wc1.hIcon = NULL;
- wc1.hIconSm = NULL;
+ wc1.hIcon = LoadIcon(NULL,IDI_APPLICATION);
+ wc1.hIconSm = LoadIcon(NULL,IDI_WINLOGO);;
wc1.hCursor = NULL;
wc1.lpszMenuName = NULL;
wc1.cbClsExtra = 0;
wc1.cbWndExtra = 0;
- wc1.hbrBackground = NULL;
+ wc1.hbrBackground = GetStockObject(WHITE_BRUSH);
+
if ( !RegisterClassEx(&wc1)) return 0;
- hmenu = CreateMenu();
- hwnd = CreateWindowEx(0, szName, "test", WS_OVERLAPPEDWINDOW,
+ hwnd = CreateWindowEx
+ (0, szName, "test2", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
- NULL,hmenu,hInst, NULL);
+ NULL,NULL,hInst, NULL);
+
+
+ MessageBox(NULL,"Hallo","Hallo",MB_OK);
-
ShowWindow(hwnd,nWinMode);
UpdateWindow(hwnd);
+#endif
+ MessageBox(NULL,"xxx","yyyy",MB_OK);
+#if 0
+ GetWindowRect(hwnd,&rect);
+ GetClientRect(hwnd,&cl);
- SetWindowText(hwnd,"Hallo");
+ printf("%d\n",(rect.left - rect.right) - (cl.left - cl.right));
+ SetWindowText(hwnd,"Hallo3");
DrawMenuBar(hwnd);
// SendMessage( hwnd, WM_MOVE, 0,MAKELONG(0,0));
}
Sleep(10000);
return msg.wParam;
+#endif
}
- //printf("hallo\n");
+
LPCVOID SYSRES_GetResPtr( int id )
{
// return SYSRES_Resources[Options.language][id]->data;
+
+
return NULL;
}
\ No newline at end of file
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
VS_VERSION_INFO VERSIONINFO
- FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD
- PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD
+ FILEVERSION 0,0,13,RES_UINT_FILE_VERSION
+ PRODUCTVERSION 0,0,13,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
BEGIN
VALUE "CompanyName", RES_STR_COMPANY_NAME
VALUE "FileDescription", "ReactOS User API Client Dll\0"
- VALUE "FileVersion", RES_STR_FILE_VERSION
+ VALUE "FileVersion", "post 0.0.13\0"
VALUE "InternalName", "user32\0"
VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT
VALUE "OriginalFilename", "user32.dll\0"
END
END
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+MSGBOX DIALOG DISCARDABLE 100, 80, 216, 168
+STYLE DS_SYSMODAL | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION |
+ WS_SYSMENU
+FONT 8, "MS Sans Serif"
+BEGIN
+ ICON "", 1088, 9, 20, 16, 16, WS_CHILD | WS_VISIBLE
+ LTEXT "", 100, 32, 4, 176, 48, WS_CHILD | WS_VISIBLE | WS_GROUP
+ PUSHBUTTON "&OK", 1, 16, 56, 40, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP
+ PUSHBUTTON "&Cancel", 2, 64, 56, 40, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP
+ PUSHBUTTON "&Abort", 3, 112, 56, 40, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP
+ PUSHBUTTON "&Retry", 4, 160, 56, 40, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP
+ PUSHBUTTON "&Ignore", 5, 208, 56, 40, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP
+ PUSHBUTTON "&Yes", 6, 256, 56, 40, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP
+ PUSHBUTTON "&No", 7, 304, 56, 40, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP
+END
\ No newline at end of file
-
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS system libraries
+ * FILE: lib/user32/windows/class.c
+ * PURPOSE: Registers a window class
+ * PROGRAMER: Boudewijn Dekker
+ * UPDATE HISTORY:
+ * 28/05/99: Created
+ */
#include <windows.h>
#include <user32/class.h>
#include <user32/win.h>
#include <user32/dce.h>
#include <user32/heapdup.h>
+
CLASS *rootClass;
ATOM STDCALL RegisterClassA(const WNDCLASS* wc)
if (classExtra)
- memset( classPtr->wExtra, 0, classExtra );
+ HEAP_memset( classPtr->wExtra, 0, classExtra );
if (!classPtr) {
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
CLASS *classPtr;
INT classExtra, winExtra;
- int i, len;
+ int len;
if ( wc == NULL || wc->cbSize != sizeof(WNDCLASSEX)) {
SetLastError(ERROR_INVALID_DATA);
return FALSE;
if (classExtra)
- memset( classPtr->wExtra, 0, classExtra );
+ HEAP_memset( classPtr->wExtra, 0, classExtra );
if (!classPtr) {
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
classPtr->dce = (wc->style & CS_CLASSDC) ?
CreateDC( "DISPLAY", NULL,NULL,NULL ) : NULL;
- len = lstrlenW((LPWSTR)wc->lpszMenuName);
- classPtr->menuName = HeapAlloc(GetProcessHeap(),0,(len+1)*2);
- lstrcpyW((LPWSTR)classPtr->menuName, (LPWSTR)wc->lpszMenuName);
+ if ( wc->lpszMenuName != NULL ) {
+ len = lstrlenW(wc->lpszMenuName);
+ classPtr->menuName = HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(len+1));
+ lstrcpyW(classPtr->menuName,wc->lpszMenuName);
+ }
+ else
+ classPtr->menuName = NULL;
len = lstrlenW((LPWSTR)wc->lpszClassName);
- classPtr->className = HeapAlloc(GetProcessHeap(),0,(len+1)*2);
+ classPtr->className = HeapAlloc(GetProcessHeap(),0,(len+1)*sizeof(WCHAR));
lstrcpyW((LPWSTR)classPtr->className,(LPWSTR) wc->lpszClassName );
classPtr->next = rootClass;
if ( HIWORD(lpClassName) != 0 )
a = FindAtomW(lpClassName);
else
- a = lpClassName;
+ a = (ATOM)lpClassName;
classPtr = CLASS_FindClassByAtom( a, hInstance );
if ( classPtr == NULL )
if (nIndex >= 0)
{
if (nIndex <= wndPtr->class->cbClsExtra - sizeof(WORD))
- return (WORD)((char *)wndPtr->class->wExtra) + nIndex;
+ return (WORD)(wndPtr->class->wExtra + nIndex);
}
else switch(nIndex)
{
--- /dev/null
+/*
+ * Default dialog procedure
+ *
+ * Copyright 1993, 1996 Alexandre Julliard
+ *
+ */
+
+#include <windows.h>
+#include <user32/widgets.h>
+#include <user32/dialog.h>
+#include <user32/win.h>
+
+
+
+/***********************************************************************
+ * DEFDLG_SetFocus
+ *
+ * Set the focus to a control of the dialog, selecting the text if
+ * the control is an edit dialog.
+ */
+static void DEFDLG_SetFocus( HWND hwndDlg, HWND hwndCtrl )
+{
+ HWND hwndPrev = GetFocus();
+
+ if (IsChild( hwndDlg, hwndPrev ))
+ {
+ if (SendMessage( hwndPrev, WM_GETDLGCODE, 0, 0 ) & DLGC_HASSETSEL)
+ SendMessage( hwndPrev, EM_SETSEL, TRUE, MAKELONG( -1, 0 ) );
+ }
+ if (SendMessage( hwndCtrl, WM_GETDLGCODE, 0, 0 ) & DLGC_HASSETSEL)
+ SendMessage( hwndCtrl, EM_SETSEL, FALSE, MAKELONG( 0, -1 ) );
+ SetFocus( hwndCtrl );
+}
+
+
+/***********************************************************************
+ * DEFDLG_SaveFocus
+ */
+static BOOL DEFDLG_SaveFocus( HWND hwnd, DIALOGINFO *infoPtr )
+{
+ HWND hwndFocus = GetFocus();
+
+ if (!hwndFocus || !IsChild( hwnd, hwndFocus )) return FALSE;
+ infoPtr->hwndFocus = hwndFocus;
+ /* Remove default button */
+ return TRUE;
+}
+
+
+/***********************************************************************
+ * DEFDLG_RestoreFocus
+ */
+static BOOL DEFDLG_RestoreFocus( HWND hwnd, DIALOGINFO *infoPtr )
+{
+ if (!infoPtr->hwndFocus || IsIconic(hwnd)) return FALSE;
+ if (!IsWindow( infoPtr->hwndFocus )) return FALSE;
+ DEFDLG_SetFocus( hwnd, infoPtr->hwndFocus );
+ /* This used to set infoPtr->hwndFocus to NULL for no apparent reason,
+ sometimes losing focus when receiving WM_SETFOCUS messages. */
+ return TRUE;
+}
+
+
+/***********************************************************************
+ * DEFDLG_FindDefButton
+ *
+ * Find the current default push-button.
+ */
+static HWND DEFDLG_FindDefButton( HWND hwndDlg )
+{
+ HWND hwndChild = GetWindow( hwndDlg, GW_CHILD );
+ while (hwndChild)
+ {
+ if (SendMessage( hwndChild, WM_GETDLGCODE, 0, 0 ) & DLGC_DEFPUSHBUTTON)
+ break;
+ hwndChild = GetWindow( hwndChild, GW_HWNDNEXT );
+ }
+ return hwndChild;
+}
+
+
+/***********************************************************************
+ * DEFDLG_SetDefButton
+ *
+ * Set the new default button to be hwndNew.
+ */
+static BOOL DEFDLG_SetDefButton( HWND hwndDlg, DIALOGINFO *dlgInfo,
+ HWND hwndNew )
+{
+ if (hwndNew &&
+ !(SendMessage(hwndNew, WM_GETDLGCODE, 0, 0 ) & DLGC_UNDEFPUSHBUTTON))
+ return FALSE; /* Destination is not a push button */
+
+ if (dlgInfo->idResult) /* There's already a default pushbutton */
+ {
+ HWND hwndOld = GetDlgItem( hwndDlg, dlgInfo->idResult );
+ if (SendMessageA( hwndOld, WM_GETDLGCODE, 0, 0) & DLGC_DEFPUSHBUTTON)
+ SendMessageA( hwndOld, BM_SETSTYLE, BS_PUSHBUTTON, TRUE );
+ }
+ if (hwndNew)
+ {
+ SendMessageA( hwndNew, BM_SETSTYLE, BS_DEFPUSHBUTTON, TRUE );
+ dlgInfo->idResult = GetDlgCtrlID( hwndNew );
+ }
+ else dlgInfo->idResult = 0;
+ return TRUE;
+}
+
+
+/***********************************************************************
+ * DEFDLG_Proc
+ *
+ * Implementation of DefDlgProc(). Only handle messages that need special
+ * handling for dialogs.
+ */
+LRESULT DEFDLG_Proc( HWND hwnd, UINT msg, WPARAM wParam,
+ LPARAM lParam, DIALOGINFO *dlgInfo )
+{
+ switch(msg)
+ {
+ case WM_ERASEBKGND:
+ FillWindow( hwnd, hwnd, (HDC)wParam, (HBRUSH)CTLCOLOR_DLG );
+ return 1;
+
+ case WM_NCDESTROY:
+
+ /* Free dialog heap (if created) */
+ if (dlgInfo->hDialogHeap)
+ {
+ GlobalUnlock(dlgInfo->hDialogHeap);
+ GlobalFree(dlgInfo->hDialogHeap);
+ dlgInfo->hDialogHeap = 0;
+ }
+
+ /* Delete font */
+ if (dlgInfo->hUserFont)
+ {
+ DeleteObject( dlgInfo->hUserFont );
+ dlgInfo->hUserFont = 0;
+ }
+
+ /* Delete menu */
+ if (dlgInfo->hMenu)
+ {
+ DestroyMenu( dlgInfo->hMenu );
+ dlgInfo->hMenu = 0;
+ }
+
+ /* Delete window procedure */
+ //WINPROC_FreeProc( dlgInfo->dlgProc, WIN_PROC_WINDOW );
+ dlgInfo->dlgProc = NULL;
+ dlgInfo->flags |= DF_END; /* just in case */
+
+ /* Window clean-up */
+ return DefWindowProcA( hwnd, msg, wParam, lParam );
+
+ case WM_SHOWWINDOW:
+ if (!wParam) DEFDLG_SaveFocus( hwnd, dlgInfo );
+ return DefWindowProcA( hwnd, msg, wParam, lParam );
+
+ case WM_ACTIVATE:
+ if (wParam) DEFDLG_RestoreFocus( hwnd, dlgInfo );
+ else DEFDLG_SaveFocus( hwnd, dlgInfo );
+ return 0;
+
+ case WM_SETFOCUS:
+ DEFDLG_RestoreFocus( hwnd, dlgInfo );
+ return 0;
+
+ case DM_SETDEFID:
+ if (dlgInfo->flags & DF_END) return 1;
+ DEFDLG_SetDefButton( hwnd, dlgInfo,
+ wParam ? GetDlgItem( hwnd, wParam ) : 0 );
+ return 1;
+
+ case DM_GETDEFID:
+ {
+ HWND hwndDefId;
+ if (dlgInfo->flags & DF_END) return 0;
+ if (dlgInfo->idResult)
+ return MAKELONG( dlgInfo->idResult, DC_HASDEFID );
+ if ((hwndDefId = DEFDLG_FindDefButton( hwnd )))
+ return MAKELONG( GetDlgCtrlID( hwndDefId ), DC_HASDEFID);
+ }
+ return 0;
+
+ case WM_NEXTDLGCTL:
+ {
+ HWND hwndDest = (HWND)wParam;
+ if (!lParam)
+ hwndDest = GetNextDlgTabItem(hwnd, GetFocus(), wParam);
+ if (hwndDest) DEFDLG_SetFocus( hwnd, hwndDest );
+ DEFDLG_SetDefButton( hwnd, dlgInfo, hwndDest );
+ }
+ return 0;
+
+ case WM_ENTERMENULOOP:
+ case WM_LBUTTONDOWN:
+ case WM_NCLBUTTONDOWN:
+ {
+ HWND hwndFocus = GetFocus();
+ if (hwndFocus)
+ {
+ WND *wnd = WIN_FindWndPtr( hwndFocus );
+
+ if( wnd )
+ {
+ /* always make combo box hide its listbox control */
+
+ if( WIDGETS_IsControl( wnd, BIC_COMBO ) )
+ SendMessageA( hwndFocus, CB_SHOWDROPDOWN,
+ FALSE, 0 );
+ else if( WIDGETS_IsControl( wnd, BIC_EDIT ) &&
+ WIDGETS_IsControl( wnd->parent,
+ BIC_COMBO ))
+ SendMessageA( wnd->parent->hwndSelf,
+ CB_SHOWDROPDOWN, FALSE, 0 );
+ }
+ }
+ }
+ return DefWindowProcA( hwnd, msg, wParam, lParam );
+
+ case WM_GETFONT:
+ return dlgInfo->hUserFont;
+
+ case WM_CLOSE:
+ PostMessageA( hwnd, WM_COMMAND, IDCANCEL,
+ (LPARAM)GetDlgItem( hwnd, IDCANCEL ) );
+ return 0;
+ }
+ return 0;
+}
+
+/***********************************************************************
+ * DEFDLG_Epilog
+ */
+LRESULT DEFDLG_Epilog(DIALOGINFO* dlgInfo, UINT msg, BOOL fResult)
+{
+ /* see SDK 3.1 */
+
+ if ((msg >= WM_CTLCOLORMSGBOX && msg <= WM_CTLCOLORSTATIC) ||
+ msg == WM_CTLCOLOR || msg == WM_COMPAREITEM ||
+ msg == WM_VKEYTOITEM || msg == WM_CHARTOITEM ||
+ msg == WM_QUERYDRAGICON || msg == WM_INITDIALOG)
+ return fResult;
+
+ return dlgInfo->msgResult;
+}
+
+
+
+
+/***********************************************************************
+ * DefDlgProcA (USER.120)
+ */
+LRESULT WINAPI DefDlgProcA( HWND hwnd, UINT msg,
+ WPARAM wParam, LPARAM lParam )
+{
+
+ DIALOGINFO * dlgInfo;
+ BOOL result = FALSE;
+ WND * wndPtr = WIN_FindWndPtr( hwnd );
+
+ if (!wndPtr) return 0;
+ dlgInfo = (DIALOGINFO *)wndPtr->wExtra;
+ dlgInfo->msgResult = 0;
+
+ if (dlgInfo->dlgProc) { /* Call dialog procedure */
+ result = CallWindowProcA( (WNDPROC)dlgInfo->dlgProc,
+ hwnd, msg, wParam, lParam );
+
+ /* Check if window was destroyed by dialog procedure */
+ if (dlgInfo->flags & DF_END && !(dlgInfo->flags & DF_ENDING)) {
+ dlgInfo->flags |= DF_ENDING;
+ DestroyWindow( hwnd );
+ }
+ }
+
+ if (!result && IsWindow(hwnd))
+ {
+ /* callback didn't process this message */
+
+ switch(msg)
+ {
+ case WM_ERASEBKGND:
+ case WM_SHOWWINDOW:
+ case WM_ACTIVATE:
+ case WM_SETFOCUS:
+ case DM_SETDEFID:
+ case DM_GETDEFID:
+ case WM_NEXTDLGCTL:
+ case WM_GETFONT:
+ case WM_CLOSE:
+ case WM_NCDESTROY:
+ case WM_ENTERMENULOOP:
+ case WM_LBUTTONDOWN:
+ case WM_NCLBUTTONDOWN:
+ return DEFDLG_Proc( (HWND)hwnd, msg,
+ (WPARAM)wParam, lParam, dlgInfo );
+ case WM_INITDIALOG:
+ case WM_VKEYTOITEM:
+ case WM_COMPAREITEM:
+ case WM_CHARTOITEM:
+ break;
+
+ default:
+ return DefWindowProcA( hwnd, msg, wParam, lParam );
+ }
+ }
+
+ return DEFDLG_Epilog(dlgInfo, msg, result);
+
+
+}
+
+
+/***********************************************************************
+ * DefDlgProcW (USER.121)
+ */
+LRESULT WINAPI DefDlgProcW( HWND hwnd, UINT msg, WPARAM wParam,
+ LPARAM lParam )
+{
+ DIALOGINFO * dlgInfo;
+ BOOL result = FALSE;
+ WND * wndPtr = WIN_FindWndPtr( hwnd );
+
+ if (!wndPtr) return 0;
+ dlgInfo = (DIALOGINFO *)wndPtr->wExtra;
+ dlgInfo->msgResult = 0;
+
+ if (dlgInfo->dlgProc) { /* Call dialog procedure */
+ result = CallWindowProcW( (WNDPROC)dlgInfo->dlgProc,
+ hwnd, msg, wParam, lParam );
+
+ /* Check if window was destroyed by dialog procedure */
+ if (dlgInfo->flags & DF_END && !(dlgInfo->flags & DF_ENDING)) {
+ dlgInfo->flags |= DF_ENDING;
+ DestroyWindow( hwnd );
+ }
+ }
+
+ if (!result && IsWindow(hwnd))
+ {
+ /* callback didn't process this message */
+
+ switch(msg)
+ {
+ case WM_ERASEBKGND:
+ case WM_SHOWWINDOW:
+ case WM_ACTIVATE:
+ case WM_SETFOCUS:
+ case DM_SETDEFID:
+ case DM_GETDEFID:
+ case WM_NEXTDLGCTL:
+ case WM_GETFONT:
+ case WM_CLOSE:
+ case WM_NCDESTROY:
+ case WM_ENTERMENULOOP:
+ case WM_LBUTTONDOWN:
+ case WM_NCLBUTTONDOWN:
+ return DEFDLG_Proc( (HWND)hwnd, msg,
+ (WPARAM)wParam, lParam, dlgInfo );
+ case WM_INITDIALOG:
+ case WM_VKEYTOITEM:
+ case WM_COMPAREITEM:
+ case WM_CHARTOITEM:
+ break;
+
+ default:
+ return DefWindowProcW( hwnd, msg, wParam, lParam );
+ }
+ }
+ return DEFDLG_Epilog(dlgInfo, msg, result);
+}
+#include <windows.h>
+#include <user32/win.h>
+#include <user32/dialog.h>
+#include <user32/debug.h>
/***********************************************************************
- * CreateDialog16 (USER.89)
+ * CreateDialog (USER32.89)
*/
-HWND16 WINAPI CreateDialog16( HINSTANCE16 hInst, SEGPTR dlgTemplate,
- HWND16 owner, DLGPROC16 dlgProc )
+#undef CreateDialogA
+HWND STDCALL CreateDialogA( HINSTANCE hInst, LPCSTR dlgTemplate,
+ HWND owner, DLGPROC dlgProc )
{
- return CreateDialogParam16( hInst, dlgTemplate, owner, dlgProc, 0 );
+ return CreateDialogParamA( hInst, dlgTemplate, owner, dlgProc, 0 );
}
-
/***********************************************************************
- * CreateDialogParam16 (USER.241)
+ * CreateDialog (USER32.89)
*/
-HWND16 WINAPI CreateDialogParam16( HINSTANCE16 hInst, SEGPTR dlgTemplate,
- HWND16 owner, DLGPROC16 dlgProc,
- LPARAM param )
+
+#undef CreateDialogW
+HWND STDCALL CreateDialogW( HINSTANCE hInst, LPCWSTR dlgTemplate,
+ HWND owner, DLGPROC dlgProc )
{
- HWND16 hwnd = 0;
- HRSRC16 hRsrc;
- HGLOBAL16 hmem;
- LPCVOID data;
+ return CreateDialogParamW( hInst, dlgTemplate, owner, dlgProc, 0 );
+}
- TRACE(dialog, "%04x,%08lx,%04x,%08lx,%ld\n",
- hInst, (DWORD)dlgTemplate, owner, (DWORD)dlgProc, param );
- if (!(hRsrc = FindResource16( hInst, dlgTemplate, RT_DIALOG16 ))) return 0;
- if (!(hmem = LoadResource16( hInst, hRsrc ))) return 0;
- if (!(data = LockResource16( hmem ))) hwnd = 0;
- else hwnd = CreateDialogIndirectParam16( hInst, data, owner,
- dlgProc, param );
- FreeResource16( hmem );
- return hwnd;
-}
/***********************************************************************
- * CreateDialogParam32A (USER32.73)
+ * CreateDialogParamA (USER32.73)
*/
-HWND32 WINAPI CreateDialogParam32A( HINSTANCE32 hInst, LPCSTR name,
- HWND32 owner, DLGPROC32 dlgProc,
+HWND STDCALL CreateDialogParamA( HINSTANCE hInst, LPCSTR name,
+ HWND owner, DLGPROC dlgProc,
LPARAM param )
{
- if (HIWORD(name))
- {
- LPWSTR str = HEAP_strdupAtoW( GetProcessHeap(), 0, name );
- HWND32 hwnd = CreateDialogParam32W( hInst, str, owner, dlgProc, param);
- HeapFree( GetProcessHeap(), 0, str );
- return hwnd;
- }
- return CreateDialogParam32W( hInst, (LPCWSTR)name, owner, dlgProc, param );
+ HANDLE hrsrc = FindResourceA( hInst, name, RT_DIALOG );
+ if (!hrsrc) return 0;
+ return CreateDialogIndirectParamA( hInst,
+ (LPVOID)LoadResource(hInst, hrsrc),
+ owner, dlgProc, param );
}
/***********************************************************************
- * CreateDialogParam32W (USER32.74)
+ * CreateDialogParamW (USER32.74)
*/
-HWND32 WINAPI CreateDialogParam32W( HINSTANCE32 hInst, LPCWSTR name,
- HWND32 owner, DLGPROC32 dlgProc,
+HWND STDCALL CreateDialogParamW( HINSTANCE hInst, LPCWSTR name,
+ HWND owner, DLGPROC dlgProc,
LPARAM param )
{
- HANDLE32 hrsrc = FindResource32W( hInst, name, RT_DIALOG32W );
+ HANDLE hrsrc = FindResourceW( hInst, name, (LPCWSTR)RT_DIALOG );
if (!hrsrc) return 0;
- return CreateDialogIndirectParam32W( hInst,
- (LPVOID)LoadResource32(hInst, hrsrc),
+ return CreateDialogIndirectParamW( hInst,
+ (LPVOID)LoadResource(hInst, hrsrc),
owner, dlgProc, param );
}
/***********************************************************************
- * CreateDialogIndirect16 (USER.219)
+ * CreateDialogIndirect (USER32.219)
*/
-HWND16 WINAPI CreateDialogIndirect16( HINSTANCE16 hInst, LPCVOID dlgTemplate,
- HWND16 owner, DLGPROC16 dlgProc )
+#undef CreateDialogIndirectA
+HWND STDCALL CreateDialogIndirectA( HINSTANCE hInst, LPCDLGTEMPLATE dlgTemplate,
+ HWND owner, DLGPROC dlgProc )
{
- return CreateDialogIndirectParam16( hInst, dlgTemplate, owner, dlgProc, 0);
+ return CreateDialogIndirectParamA( hInst, dlgTemplate, owner, dlgProc, 0);
}
-
/***********************************************************************
- * CreateDialogIndirectParam16 (USER.242)
+ * CreateDialogIndirect (USER32.219)
*/
-HWND16 WINAPI CreateDialogIndirectParam16( HINSTANCE16 hInst,
- LPCVOID dlgTemplate,
- HWND16 owner, DLGPROC16 dlgProc,
- LPARAM param )
+#undef CreateDialogIndirectW
+HWND STDCALL CreateDialogIndirectW( HINSTANCE hInst, LPCDLGTEMPLATE dlgTemplate,
+ HWND owner, DLGPROC dlgProc )
{
- return DIALOG_CreateIndirect( hInst, dlgTemplate, FALSE, owner,
- dlgProc, param, WIN_PROC_16 );
+ return CreateDialogIndirectParamW( hInst, dlgTemplate, owner, dlgProc, 0);
}
/***********************************************************************
- * CreateDialogIndirectParam32A (USER32.69)
+ * CreateDialogIndirectParamA (USER32.69)
*/
-HWND32 WINAPI CreateDialogIndirectParam32A( HINSTANCE32 hInst,
- LPCVOID dlgTemplate,
- HWND32 owner, DLGPROC32 dlgProc,
+HWND STDCALL CreateDialogIndirectParamA( HINSTANCE hInst,
+ LPCDLGTEMPLATE dlgTemplate,
+ HWND owner, DLGPROC dlgProc,
LPARAM param )
{
- return DIALOG_CreateIndirect( hInst, dlgTemplate, TRUE, owner,
- (DLGPROC16)dlgProc, param, WIN_PROC_32A );
+ return DIALOG_CreateIndirect( hInst, dlgTemplate, owner,
+ (DLGPROC)dlgProc, param, FALSE );
}
-/***********************************************************************
- * CreateDialogIndirectParam32AorW (USER32.71)
- */
-HWND32 WINAPI CreateDialogIndirectParam32AorW( HINSTANCE32 hInst,
- LPCVOID dlgTemplate,
- HWND32 owner, DLGPROC32 dlgProc,
- LPARAM param )
-{ FIXME(dialog,"assume WIN_PROC_32W\n");
- return DIALOG_CreateIndirect( hInst, dlgTemplate, TRUE, owner,
- (DLGPROC16)dlgProc, param, WIN_PROC_32W );
-}
/***********************************************************************
- * CreateDialogIndirectParam32W (USER32.72)
+ * CreateDialogIndirectParamW (USER32.72)
*/
-HWND32 WINAPI CreateDialogIndirectParam32W( HINSTANCE32 hInst,
- LPCVOID dlgTemplate,
- HWND32 owner, DLGPROC32 dlgProc,
+HWND STDCALL CreateDialogIndirectParamW( HINSTANCE hInst,
+ LPCDLGTEMPLATE dlgTemplate,
+ HWND owner, DLGPROC dlgProc,
LPARAM param )
{
- return DIALOG_CreateIndirect( hInst, dlgTemplate, TRUE, owner,
- (DLGPROC16)dlgProc, param, WIN_PROC_32W );
+ return DIALOG_CreateIndirect( hInst, dlgTemplate, owner,
+ (DLGPROC)dlgProc, param, TRUE );
}
/***********************************************************************
- * DIALOG_DoDialogBox
+ * DialogBox (USER32.87)
*/
-INT32 DIALOG_DoDialogBox( HWND32 hwnd, HWND32 owner )
-{
- WND * wndPtr;
- DIALOGINFO * dlgInfo;
- MSG16 msg;
- INT32 retval;
-
- /* Owner must be a top-level window */
- owner = WIN_GetTopParent( owner );
- if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return -1;
- dlgInfo = (DIALOGINFO *)wndPtr->wExtra;
- EnableWindow32( owner, FALSE );
- ShowWindow32( hwnd, SW_SHOW );
- while (MSG_InternalGetMessage(&msg, hwnd, owner, MSGF_DIALOGBOX, PM_REMOVE,
- !(wndPtr->dwStyle & DS_NOIDLEMSG) ))
- {
- if (!IsDialogMessage16( hwnd, &msg))
- {
- TranslateMessage16( &msg );
- DispatchMessage16( &msg );
- }
- if (dlgInfo->flags & DF_END) break;
- }
- retval = dlgInfo->idResult;
- EnableWindow32( owner, TRUE );
- dlgInfo->flags |= DF_ENDING; /* try to stop it being destroyed twice */
- DestroyWindow32( hwnd );
- return retval;
+#undef DialogBoxA
+INT STDCALL DialogBoxA( HINSTANCE hInst, LPCSTR dlgTemplate,
+ HWND owner, DLGPROC dlgProc )
+{
+ return DialogBoxParamA( hInst, dlgTemplate, owner, dlgProc, 0 );
}
-
/***********************************************************************
- * DialogBox16 (USER.87)
+ * DialogBox (USER32.87)
*/
-INT16 WINAPI DialogBox16( HINSTANCE16 hInst, SEGPTR dlgTemplate,
- HWND16 owner, DLGPROC16 dlgProc )
+#undef DialogBoxW
+INT STDCALL DialogBoxW( HINSTANCE hInst, LPCWSTR dlgTemplate,
+ HWND owner, DLGPROC dlgProc )
{
- return DialogBoxParam16( hInst, dlgTemplate, owner, dlgProc, 0 );
+ return DialogBoxParamW( hInst, dlgTemplate, owner, dlgProc, 0 );
}
-/***********************************************************************
- * DialogBoxParam16 (USER.239)
- */
-INT16 WINAPI DialogBoxParam16( HINSTANCE16 hInst, SEGPTR template,
- HWND16 owner, DLGPROC16 dlgProc, LPARAM param )
-{
- HWND16 hwnd = CreateDialogParam16( hInst, template, owner, dlgProc, param);
- if (hwnd) return (INT16)DIALOG_DoDialogBox( hwnd, owner );
- return -1;
-}
/***********************************************************************
- * DialogBoxParam32A (USER32.139)
+ * DialogBoxParamA (USER32.139)
*/
-INT32 WINAPI DialogBoxParam32A( HINSTANCE32 hInst, LPCSTR name,
- HWND32 owner, DLGPROC32 dlgProc, LPARAM param )
+INT STDCALL DialogBoxParamA( HINSTANCE hInst, LPCSTR name,
+ HWND owner, DLGPROC dlgProc, LPARAM param )
{
- HWND32 hwnd = CreateDialogParam32A( hInst, name, owner, dlgProc, param );
+ HWND hwnd = CreateDialogParamA( hInst, name, owner, dlgProc, param );
if (hwnd) return DIALOG_DoDialogBox( hwnd, owner );
return -1;
}
/***********************************************************************
- * DialogBoxParam32W (USER32.140)
+ * DialogBoxParamW (USER32.140)
*/
-INT32 WINAPI DialogBoxParam32W( HINSTANCE32 hInst, LPCWSTR name,
- HWND32 owner, DLGPROC32 dlgProc, LPARAM param )
+INT STDCALL DialogBoxParamW( HINSTANCE hInst, LPCWSTR name,
+ HWND owner, DLGPROC dlgProc, LPARAM param )
{
- HWND32 hwnd = CreateDialogParam32W( hInst, name, owner, dlgProc, param );
+ HWND hwnd = CreateDialogParamW( hInst, name, owner, dlgProc, param );
if (hwnd) return DIALOG_DoDialogBox( hwnd, owner );
return -1;
}
/***********************************************************************
- * DialogBoxIndirect16 (USER.218)
+ * DialogBoxIndirect (USER32.218)
*/
-INT16 WINAPI DialogBoxIndirect16( HINSTANCE16 hInst, HANDLE16 dlgTemplate,
- HWND16 owner, DLGPROC16 dlgProc )
+#undef DialogBoxIndirectA
+INT STDCALL DialogBoxIndirectA( HINSTANCE hInst, LPCDLGTEMPLATE dlgTemplate,
+ HWND owner, DLGPROC dlgProc )
{
- return DialogBoxIndirectParam16( hInst, dlgTemplate, owner, dlgProc, 0 );
+ return DialogBoxIndirectParamA( hInst, dlgTemplate, owner, dlgProc, 0 );
}
-
/***********************************************************************
- * DialogBoxIndirectParam16 (USER.240)
+ * DialogBoxIndirect (USER32.218)
*/
-INT16 WINAPI DialogBoxIndirectParam16( HINSTANCE16 hInst, HANDLE16 dlgTemplate,
- HWND16 owner, DLGPROC16 dlgProc,
- LPARAM param )
+#undef DialogBoxIndirectW
+INT STDCALL DialogBoxIndirectW( HINSTANCE hInst, LPCDLGTEMPLATE dlgTemplate,
+ HWND owner, DLGPROC dlgProc )
{
- HWND16 hwnd;
- LPCVOID ptr;
-
- if (!(ptr = GlobalLock16( dlgTemplate ))) return -1;
- hwnd = CreateDialogIndirectParam16( hInst, ptr, owner, dlgProc, param );
- GlobalUnlock16( dlgTemplate );
- if (hwnd) return (INT16)DIALOG_DoDialogBox( hwnd, owner );
- return -1;
+ return DialogBoxIndirectParam( hInst, dlgTemplate, owner, dlgProc, 0 );
}
/***********************************************************************
- * DialogBoxIndirectParam32A (USER32.136)
+ * DialogBoxIndirectParamA (USER32.136)
*/
-INT32 WINAPI DialogBoxIndirectParam32A(HINSTANCE32 hInstance, LPCVOID template,
- HWND32 owner, DLGPROC32 dlgProc,
+INT STDCALL DialogBoxIndirectParamA(HINSTANCE hInstance, LPCDLGTEMPLATE template,
+ HWND owner, DLGPROC dlgProc,
LPARAM param )
{
- HWND32 hwnd = CreateDialogIndirectParam32A( hInstance, template,
+ HWND hwnd = CreateDialogIndirectParamA( hInstance, template,
owner, dlgProc, param );
if (hwnd) return DIALOG_DoDialogBox( hwnd, owner );
return -1;
/***********************************************************************
- * DialogBoxIndirectParam32W (USER32.138)
+ * DialogBoxIndirectParamW (USER32.138)
*/
-INT32 WINAPI DialogBoxIndirectParam32W(HINSTANCE32 hInstance, LPCVOID template,
- HWND32 owner, DLGPROC32 dlgProc,
+INT STDCALL DialogBoxIndirectParamW(HINSTANCE hInstance, LPCDLGTEMPLATE template,
+ HWND owner, DLGPROC dlgProc,
LPARAM param )
{
- HWND32 hwnd = CreateDialogIndirectParam32W( hInstance, template,
+ HWND hwnd = CreateDialogIndirectParamW( hInstance, template,
owner, dlgProc, param );
if (hwnd) return DIALOG_DoDialogBox( hwnd, owner );
return -1;
/***********************************************************************
- * EndDialog16 (USER32.173)
- */
-BOOL16 WINAPI EndDialog16( HWND16 hwnd, INT16 retval )
-{
- return EndDialog32( hwnd, retval );
-}
-
-
-/***********************************************************************
- * EndDialog32 (USER.88)
+ * EndDialog (USER32.88)
*/
-WINBOOL WINAPI EndDialog32( HWND32 hwnd, INT32 retval )
+WINBOOL STDCALL EndDialog( HWND hwnd, INT retval )
{
WND * wndPtr = WIN_FindWndPtr( hwnd );
DIALOGINFO * dlgInfo = (DIALOGINFO *)wndPtr->wExtra;
- TRACE(dialog, "%04x %d\n", hwnd, retval );
+ DPRINT( "%04x %d\n", hwnd, retval );
if( dlgInfo )
{
/***********************************************************************
- * DIALOG_IsAccelerator
- */
-static WINBOOL DIALOG_IsAccelerator( HWND32 hwnd, HWND32 hwndDlg, WPARAM32 vKey )
-{
- HWND32 hwndControl = hwnd;
- HWND32 hwndNext;
- WND *wndPtr;
- WINBOOL RetVal = FALSE;
- INT32 dlgCode;
-
- if (vKey == VK_SPACE)
- {
- dlgCode = SendMessage32A( hwndControl, WM_GETDLGCODE, 0, 0 );
- if (dlgCode & DLGC_BUTTON)
- {
- SendMessage32A( hwndControl, WM_LBUTTONDOWN, 0, 0);
- SendMessage32A( hwndControl, WM_LBUTTONUP, 0, 0);
- RetVal = TRUE;
- }
- }
- else
- {
- do
- {
- wndPtr = WIN_FindWndPtr( hwndControl );
- if (wndPtr != NULL && wndPtr->text != NULL &&
- (wndPtr->dwStyle & (WS_VISIBLE | WS_DISABLED)) == WS_VISIBLE)
- {
- dlgCode = SendMessage32A( hwndControl, WM_GETDLGCODE, 0, 0 );
- if (dlgCode & (DLGC_BUTTON | DLGC_STATIC))
- {
- /* find the accelerator key */
- LPSTR p = wndPtr->text - 2;
- do
- {
- p = strchr( p + 2, '&' );
- }
- while (p != NULL && p[1] == '&');
-
- /* and check if it's the one we're looking for */
- if (p != NULL && toupper( p[1] ) == toupper( vKey ) )
- {
- if ((dlgCode & DLGC_STATIC) ||
- (wndPtr->dwStyle & 0x0f) == BS_GROUPBOX )
- {
- /* set focus to the control */
- SendMessage32A( hwndDlg, WM_NEXTDLGCTL,
- hwndControl, 1);
- /* and bump it on to next */
- SendMessage32A( hwndDlg, WM_NEXTDLGCTL, 0, 0);
- }
- else if (dlgCode &
- (DLGC_DEFPUSHBUTTON | DLGC_UNDEFPUSHBUTTON))
- {
- /* send command message as from the control */
- SendMessage32A( hwndDlg, WM_COMMAND,
- MAKEWPARAM( LOWORD(wndPtr->wIDmenu),
- BN_CLICKED ),
- (LPARAM)hwndControl );
- }
- else
- {
- /* click the control */
- SendMessage32A( hwndControl, WM_LBUTTONDOWN, 0, 0);
- SendMessage32A( hwndControl, WM_LBUTTONUP, 0, 0);
- }
- RetVal = TRUE;
- break;
- }
- }
- }
- hwndNext = GetWindow32( hwndControl, GW_CHILD );
- if (!hwndNext)
- {
- hwndNext = GetWindow32( hwndControl, GW_HWNDNEXT );
- }
- while (!hwndNext)
- {
- hwndControl = GetParent32( hwndControl );
- if (hwndControl == hwndDlg)
- {
- hwndNext = GetWindow32( hwndDlg, GW_CHILD );
- }
- else
- {
- hwndNext = GetWindow32( hwndControl, GW_HWNDNEXT );
- }
- }
- hwndControl = hwndNext;
- }
- while (hwndControl != hwnd);
- }
- return RetVal;
-}
-
-
-/***********************************************************************
- * DIALOG_IsDialogMessage
- */
-static WINBOOL DIALOG_IsDialogMessage( HWND32 hwnd, HWND32 hwndDlg,
- UINT32 message, WPARAM32 wParam,
- LPARAM lParam, WINBOOL *translate,
- WINBOOL *dispatch, INT32 dlgCode )
-{
- *translate = *dispatch = FALSE;
-
- if (message == WM_PAINT)
- {
- /* Apparently, we have to handle this one as well */
- *dispatch = TRUE;
- return TRUE;
- }
-
- /* Only the key messages get special processing */
- if ((message != WM_KEYDOWN) &&
- (message != WM_SYSCHAR) &&
- (message != WM_CHAR))
- return FALSE;
-
- if (dlgCode & DLGC_WANTMESSAGE)
- {
- *translate = *dispatch = TRUE;
- return TRUE;
- }
-
- switch(message)
- {
- case WM_KEYDOWN:
- switch(wParam)
- {
- case VK_TAB:
- if (!(dlgCode & DLGC_WANTTAB))
- {
- SendMessage32A( hwndDlg, WM_NEXTDLGCTL,
- (GetKeyState32(VK_SHIFT) & 0x8000), 0 );
- return TRUE;
- }
- break;
-
- case VK_RIGHT:
- case VK_DOWN:
- case VK_LEFT:
- case VK_UP:
- if (!(dlgCode & DLGC_WANTARROWS))
- {
- WINBOOL fPrevious = (wParam == VK_LEFT || wParam == VK_UP);
- HWND32 hwndNext =
- GetNextDlgGroupItem32 (hwndDlg, GetFocus32(), fPrevious );
- SendMessage32A( hwndDlg, WM_NEXTDLGCTL, hwndNext, 1 );
- return TRUE;
- }
- break;
-
- case VK_ESCAPE:
- SendMessage32A( hwndDlg, WM_COMMAND, IDCANCEL,
- (LPARAM)GetDlgItem32( hwndDlg, IDCANCEL ) );
- return TRUE;
-
- case VK_RETURN:
- {
- DWORD dw = SendMessage16( hwndDlg, DM_GETDEFID, 0, 0 );
- if (HIWORD(dw) == DC_HASDEFID)
- {
- SendMessage32A( hwndDlg, WM_COMMAND,
- MAKEWPARAM( LOWORD(dw), BN_CLICKED ),
- (LPARAM)GetDlgItem32(hwndDlg, LOWORD(dw)));
- }
- else
- {
- SendMessage32A( hwndDlg, WM_COMMAND, IDOK,
- (LPARAM)GetDlgItem32( hwndDlg, IDOK ) );
-
- }
- }
- return TRUE;
- }
- *translate = TRUE;
- break; /* case WM_KEYDOWN */
-
- case WM_CHAR:
- if (dlgCode & DLGC_WANTCHARS) break;
- /* drop through */
-
- case WM_SYSCHAR:
- if (DIALOG_IsAccelerator( hwnd, hwndDlg, wParam ))
- {
- /* don't translate or dispatch */
- return TRUE;
- }
- break;
- }
-
- /* If we get here, the message has not been treated specially */
- /* and can be sent to its destination window. */
- *dispatch = TRUE;
- return TRUE;
-}
-
-
-/***********************************************************************
- * IsDialogMessage16 (USER.90)
+ * IsDialogMessageA (USER32.342)
*/
-BOOL16 WINAPI WIN16_IsDialogMessage16( HWND16 hwndDlg, SEGPTR msg16 )
+WINBOOL STDCALL IsDialogMessageA( HWND hwndDlg, LPMSG msg )
{
- LPMSG16 msg = PTR_SEG_TO_LIN(msg16);
WINBOOL ret, translate, dispatch;
- INT32 dlgCode;
+ INT dlgCode;
- if ((hwndDlg != msg->hwnd) && !IsChild16( hwndDlg, msg->hwnd ))
+ if ((hwndDlg != msg->hwnd) && !IsChild( hwndDlg, msg->hwnd ))
return FALSE;
- dlgCode = SendMessage16( msg->hwnd, WM_GETDLGCODE, 0, (LPARAM)msg16);
+ dlgCode = SendMessageA( msg->hwnd, WM_GETDLGCODE, 0, (LPARAM)msg);
ret = DIALOG_IsDialogMessage( msg->hwnd, hwndDlg, msg->message,
msg->wParam, msg->lParam,
&translate, &dispatch, dlgCode );
- if (translate) TranslateMessage16( msg );
- if (dispatch) DispatchMessage16( msg );
+ if (translate) TranslateMessage( msg );
+ if (dispatch) DispatchMessageA( msg );
return ret;
}
-BOOL16 WINAPI IsDialogMessage16( HWND16 hwndDlg, LPMSG16 msg )
-{
- LPMSG16 msg16 = SEGPTR_NEW(MSG16);
- WINBOOL ret;
-
- *msg16 = *msg;
- ret = WIN16_IsDialogMessage16( hwndDlg, SEGPTR_GET(msg16) );
- SEGPTR_FREE(msg16);
- return ret;
-}
-
/***********************************************************************
- * IsDialogMessage32A (USER32.342)
+ * IsDialogMessageW (USER32.343)
*/
-WINBOOL WINAPI IsDialogMessage32A( HWND32 hwndDlg, LPMSG32 msg )
+WINBOOL STDCALL IsDialogMessageW( HWND hwndDlg, LPMSG msg )
{
WINBOOL ret, translate, dispatch;
- INT32 dlgCode;
+ INT dlgCode;
- if ((hwndDlg != msg->hwnd) && !IsChild32( hwndDlg, msg->hwnd ))
+ if ((hwndDlg != msg->hwnd) && !IsChild( hwndDlg, msg->hwnd ))
return FALSE;
- dlgCode = SendMessage32A( msg->hwnd, WM_GETDLGCODE, 0, (LPARAM)msg);
+ dlgCode = SendMessageW( msg->hwnd, WM_GETDLGCODE, 0, (LPARAM)msg);
ret = DIALOG_IsDialogMessage( msg->hwnd, hwndDlg, msg->message,
msg->wParam, msg->lParam,
&translate, &dispatch, dlgCode );
- if (translate) TranslateMessage32( msg );
- if (dispatch) DispatchMessage32A( msg );
+ if (translate) TranslateMessage( msg );
+ if (dispatch) DispatchMessageW( msg );
return ret;
}
-/***********************************************************************
- * IsDialogMessage32W (USER32.343)
- */
-WINBOOL WINAPI IsDialogMessage32W( HWND32 hwndDlg, LPMSG32 msg )
-{
- WINBOOL ret, translate, dispatch;
- INT32 dlgCode;
-
- if ((hwndDlg != msg->hwnd) && !IsChild32( hwndDlg, msg->hwnd ))
- return FALSE;
-
- dlgCode = SendMessage32W( msg->hwnd, WM_GETDLGCODE, 0, (LPARAM)msg);
- ret = DIALOG_IsDialogMessage( msg->hwnd, hwndDlg, msg->message,
- msg->wParam, msg->lParam,
- &translate, &dispatch, dlgCode );
- if (translate) TranslateMessage32( msg );
- if (dispatch) DispatchMessage32W( msg );
- return ret;
-}
-
-
-/****************************************************************
- * GetDlgCtrlID16 (USER.277)
- */
-INT16 WINAPI GetDlgCtrlID16( HWND16 hwnd )
-{
- WND *wndPtr = WIN_FindWndPtr(hwnd);
- if (wndPtr) return wndPtr->wIDmenu;
- else return 0;
-}
/****************************************************************
- * GetDlgCtrlID32 (USER32.234)
+ * GetDlgCtrlID (USER32.234)
*/
-INT32 WINAPI GetDlgCtrlID32( HWND32 hwnd )
+INT STDCALL GetDlgCtrlID( HWND hwnd )
{
WND *wndPtr = WIN_FindWndPtr(hwnd);
if (wndPtr) return wndPtr->wIDmenu;
else return 0;
}
-
-/***********************************************************************
- * GetDlgItem16 (USER.91)
- */
-HWND16 WINAPI GetDlgItem16( HWND16 hwndDlg, INT16 id )
-{
- WND *pWnd;
-
- if (!(pWnd = WIN_FindWndPtr( hwndDlg ))) return 0;
- for (pWnd = pWnd->child; pWnd; pWnd = pWnd->next)
- if (pWnd->wIDmenu == (UINT16)id) return pWnd->hwndSelf;
- return 0;
-}
-
-
-/***********************************************************************
- * GetDlgItem32 (USER32.235)
- */
-HWND32 WINAPI GetDlgItem32( HWND32 hwndDlg, INT32 id )
+HWND STDCALL GetDlgItem(HWND hDlg, int nIDDlgItem )
{
- WND *pWnd;
-
- if (!(pWnd = WIN_FindWndPtr( hwndDlg ))) return 0;
- for (pWnd = pWnd->child; pWnd; pWnd = pWnd->next)
- if (pWnd->wIDmenu == (UINT16)id) return pWnd->hwndSelf;
- return 0;
}
-/*******************************************************************
- * SendDlgItemMessage16 (USER.101)
- */
-LRESULT WINAPI SendDlgItemMessage16( HWND16 hwnd, INT16 id, UINT16 msg,
- WPARAM16 wParam, LPARAM lParam )
-{
- HWND16 hwndCtrl = GetDlgItem16( hwnd, id );
- if (hwndCtrl) return SendMessage16( hwndCtrl, msg, wParam, lParam );
- else return 0;
-}
/*******************************************************************
- * SendDlgItemMessage32A (USER32.452)
+ * SendDlgItemMessageA (USER32.452)
*/
-LRESULT WINAPI SendDlgItemMessage32A( HWND32 hwnd, INT32 id, UINT32 msg,
- WPARAM32 wParam, LPARAM lParam )
+LRESULT STDCALL SendDlgItemMessageA( HWND hwnd, INT id, UINT msg,
+ WPARAM wParam, LPARAM lParam )
{
- HWND32 hwndCtrl = GetDlgItem32( hwnd, id );
- if (hwndCtrl) return SendMessage32A( hwndCtrl, msg, wParam, lParam );
+ HWND hwndCtrl = GetDlgItem( hwnd, id );
+ if (hwndCtrl) return SendMessageA( hwndCtrl, msg, wParam, lParam );
else return 0;
}
/*******************************************************************
- * SendDlgItemMessage32W (USER32.453)
+ * SendDlgItemMessageW (USER32.453)
*/
-LRESULT WINAPI SendDlgItemMessage32W( HWND32 hwnd, INT32 id, UINT32 msg,
- WPARAM32 wParam, LPARAM lParam )
+LRESULT STDCALL SendDlgItemMessageW( HWND hwnd, INT id, UINT msg,
+ WPARAM wParam, LPARAM lParam )
{
- HWND32 hwndCtrl = GetDlgItem32( hwnd, id );
- if (hwndCtrl) return SendMessage32W( hwndCtrl, msg, wParam, lParam );
+ HWND hwndCtrl = GetDlgItem( hwnd, id );
+ if (hwndCtrl) return SendMessageW( hwndCtrl, msg, wParam, lParam );
else return 0;
}
-/*******************************************************************
- * SetDlgItemText16 (USER.92)
- */
-void WINAPI SetDlgItemText16( HWND16 hwnd, INT16 id, SEGPTR lpString )
-{
- SendDlgItemMessage16( hwnd, id, WM_SETTEXT, 0, (LPARAM)lpString );
-}
-
/*******************************************************************
- * SetDlgItemText32A (USER32.478)
+ * SetDlgItemTextA (USER32.478)
*/
-WINBOOL WINAPI SetDlgItemText32A( HWND32 hwnd, INT32 id, LPCSTR lpString )
+WINBOOL STDCALL SetDlgItemTextA( HWND hwnd, INT id, LPCSTR lpString )
{
- return SendDlgItemMessage32A( hwnd, id, WM_SETTEXT, 0, (LPARAM)lpString );
+ return SendDlgItemMessageA( hwnd, id, WM_SETTEXT, 0, (LPARAM)lpString );
}
/*******************************************************************
- * SetDlgItemText32W (USER32.479)
+ * SetDlgItemTextW (USER32.479)
*/
-WINBOOL WINAPI SetDlgItemText32W( HWND32 hwnd, INT32 id, LPCWSTR lpString )
+WINBOOL STDCALL SetDlgItemTextW( HWND hwnd, INT id, LPCWSTR lpString )
{
- return SendDlgItemMessage32W( hwnd, id, WM_SETTEXT, 0, (LPARAM)lpString );
+ return SendDlgItemMessageW( hwnd, id, WM_SETTEXT, 0, (LPARAM)lpString );
}
-/***********************************************************************
- * GetDlgItemText16 (USER.93)
- */
-INT16 WINAPI GetDlgItemText16( HWND16 hwnd, INT16 id, SEGPTR str, UINT16 len )
-{
- return (INT16)SendDlgItemMessage16( hwnd, id, WM_GETTEXT,
- len, (LPARAM)str );
-}
/***********************************************************************
- * GetDlgItemText32A (USER32.237)
+ * GetDlgItemTextA (USER32.237)
*/
-INT32 WINAPI GetDlgItemText32A( HWND32 hwnd, INT32 id, LPSTR str, UINT32 len )
+UINT STDCALL GetDlgItemTextA( HWND hwnd, INT id, LPSTR str, INT len )
{
- return (INT32)SendDlgItemMessage32A( hwnd, id, WM_GETTEXT,
+ return (UINT)SendDlgItemMessageA( hwnd, id, WM_GETTEXT,
len, (LPARAM)str );
}
/***********************************************************************
- * GetDlgItemText32W (USER32.238)
+ * GetDlgItemTextW (USER32.238)
*/
-INT32 WINAPI GetDlgItemText32W( HWND32 hwnd, INT32 id, LPWSTR str, UINT32 len )
+UINT STDCALL GetDlgItemTextW( HWND hwnd, INT id, LPWSTR str, INT len )
{
- return (INT32)SendDlgItemMessage32W( hwnd, id, WM_GETTEXT,
+ return (UINT)SendDlgItemMessageW( hwnd, id, WM_GETTEXT,
len, (LPARAM)str );
}
-/*******************************************************************
- * SetDlgItemInt16 (USER.94)
- */
-void WINAPI SetDlgItemInt16( HWND16 hwnd, INT16 id, UINT16 value, BOOL16 fSigned )
-{
- return SetDlgItemInt32( hwnd, (UINT32)(UINT16)id, value, fSigned );
-}
/*******************************************************************
- * SetDlgItemInt32 (USER32.477)
+ * SetDlgItemInt (USER32.477)
*/
-void WINAPI SetDlgItemInt32( HWND32 hwnd, INT32 id, UINT32 value,
+WINBOOL STDCALL SetDlgItemInt( HWND hwnd, INT id, UINT value,
WINBOOL fSigned )
{
char str[20];
- if (fSigned) sprintf( str, "%d", (INT32)value );
+ if (fSigned) sprintf( str, "%d", (INT)value );
else sprintf( str, "%u", value );
- SendDlgItemMessage32A( hwnd, id, WM_SETTEXT, 0, (LPARAM)str );
+ SendDlgItemMessageA( hwnd, id, WM_SETTEXT, 0, (LPARAM)str );
}
-/***********************************************************************
- * GetDlgItemInt16 (USER.95)
- */
-UINT16 WINAPI GetDlgItemInt16( HWND16 hwnd, INT16 id, BOOL16 *translated,
- BOOL16 fSigned )
-{
- UINT32 result;
- WINBOOL ok;
-
- if (translated) *translated = FALSE;
- result = GetDlgItemInt32( hwnd, (UINT32)(UINT16)id, &ok, fSigned );
- if (!ok) return 0;
- if (fSigned)
- {
- if (((INT32)result < -32767) || ((INT32)result > 32767)) return 0;
- }
- else
- {
- if (result > 65535) return 0;
- }
- if (translated) *translated = TRUE;
- return (UINT16)result;
-}
/***********************************************************************
- * GetDlgItemInt32 (USER32.236)
+ * GetDlgItemInt (USER32.236)
*/
-UINT32 WINAPI GetDlgItemInt32( HWND32 hwnd, INT32 id, WINBOOL *translated,
+UINT STDCALL GetDlgItemInt( HWND hwnd, INT id, WINBOOL *translated,
WINBOOL fSigned )
{
char str[30];
long result = 0;
if (translated) *translated = FALSE;
- if (!SendDlgItemMessage32A(hwnd, id, WM_GETTEXT, sizeof(str), (LPARAM)str))
+ if (!SendDlgItemMessageA(hwnd, id, WM_GETTEXT, sizeof(str), (LPARAM)str))
return 0;
if (fSigned)
{
result = strtol( str, &endptr, 10 );
if (!endptr || (endptr == str)) /* Conversion was unsuccessful */
return 0;
- if (((result == LONG_MIN) || (result == LONG_MAX)) && (errno==ERANGE))
+ if (((result == LONG_MIN) || (result == LONG_MAX)) ) {
+ // errno == ERANGE
return 0;
+ }
}
else
{
result = strtoul( str, &endptr, 10 );
if (!endptr || (endptr == str)) /* Conversion was unsuccessful */
return 0;
- if ((result == ULONG_MAX) && (errno == ERANGE)) return 0;
+ if ((result == ULONG_MAX) ) {
+ // && (errno == ERANGE)
+ return 0;
+ }
}
if (translated) *translated = TRUE;
- return (UINT32)result;
+ return (UINT)result;
}
/***********************************************************************
- * CheckDlgButton16 (USER.97)
+ * CheckDlgButton (USER32.97)
*/
-BOOL16 WINAPI CheckDlgButton16( HWND16 hwnd, INT16 id, UINT16 check )
+BOOL STDCALL CheckDlgButton( HWND hwnd, INT id, UINT check )
{
- SendDlgItemMessage32A( hwnd, id, BM_SETCHECK32, check, 0 );
+ SendDlgItemMessageW( hwnd, id, BM_SETCHECK, check, 0 );
return TRUE;
}
-/***********************************************************************
- * CheckDlgButton32 (USER32.45)
- */
-WINBOOL WINAPI CheckDlgButton32( HWND32 hwnd, INT32 id, UINT32 check )
-{
- SendDlgItemMessage32A( hwnd, id, BM_SETCHECK32, check, 0 );
- return TRUE;
-}
-
-/***********************************************************************
- * IsDlgButtonChecked16 (USER.98)
- */
-UINT16 WINAPI IsDlgButtonChecked16( HWND16 hwnd, UINT16 id )
-{
- return (UINT16)SendDlgItemMessage32A( hwnd, id, BM_GETCHECK32, 0, 0 );
-}
/***********************************************************************
- * IsDlgButtonChecked32 (USER32.344)
+ * IsDlgButtonChecked (USER32.98)
*/
-UINT32 WINAPI IsDlgButtonChecked32( HWND32 hwnd, UINT32 id )
+UINT STDCALL IsDlgButtonChecked( HWND hwnd, INT id )
{
- return (UINT32)SendDlgItemMessage32A( hwnd, id, BM_GETCHECK32, 0, 0 );
+ return (UINT)SendDlgItemMessageA( hwnd, id, BM_GETCHECK, 0, 0 );
}
-/***********************************************************************
- * CheckRadioButton16 (USER.96)
- */
-BOOL16 WINAPI CheckRadioButton16( HWND16 hwndDlg, UINT16 firstID,
- UINT16 lastID, UINT16 checkID )
-{
- return CheckRadioButton32( hwndDlg, firstID, lastID, checkID );
-}
/***********************************************************************
- * CheckRadioButton32 (USER32.48)
+ * CheckRadioButton (USER32.48)
*/
-WINBOOL WINAPI CheckRadioButton32( HWND32 hwndDlg, UINT32 firstID,
- UINT32 lastID, UINT32 checkID )
+WINBOOL STDCALL CheckRadioButton( HWND hwndDlg, INT firstID,
+ INT lastID, INT checkID )
{
WND *pWnd = WIN_FindWndPtr( hwndDlg );
if (!pWnd) return FALSE;
lastID = firstID; /* Buttons are in reverse order */
while (pWnd)
{
- SendMessage32A( pWnd->hwndSelf, BM_SETCHECK32,
+ SendMessageA( pWnd->hwndSelf, BM_SETCHECK,
(pWnd->wIDmenu == checkID), 0 );
if (pWnd->wIDmenu == lastID) break;
pWnd = pWnd->next;
/***********************************************************************
- * GetDialogBaseUnits (USER.243) (USER32.233)
+ * GetDialogBaseUnits (USER32.243) (USER32.233)
*/
-DWORD WINAPI GetDialogBaseUnits(void)
+LONG STDCALL GetDialogBaseUnits(void)
{
return MAKELONG( xBaseUnit, yBaseUnit );
}
/***********************************************************************
- * MapDialogRect16 (USER.103)
+ * MapDialogRect (USER32.103)
*/
-void WINAPI MapDialogRect16( HWND16 hwnd, LPRECT16 rect )
+WINBOOL STDCALL MapDialogRect( HWND hwnd, LPRECT rect )
{
DIALOGINFO * dlgInfo;
WND * wndPtr = WIN_FindWndPtr( hwnd );
- if (!wndPtr) return;
+ if (!wndPtr) return FALSE;
dlgInfo = (DIALOGINFO *)wndPtr->wExtra;
rect->left = (rect->left * dlgInfo->xBaseUnit) / 4;
rect->right = (rect->right * dlgInfo->xBaseUnit) / 4;
rect->top = (rect->top * dlgInfo->yBaseUnit) / 8;
rect->bottom = (rect->bottom * dlgInfo->yBaseUnit) / 8;
+ return TRUE;
}
-/***********************************************************************
- * MapDialogRect32 (USER32.382)
- */
-void WINAPI MapDialogRect32( HWND32 hwnd, LPRECT32 rect )
-{
- DIALOGINFO * dlgInfo;
- WND * wndPtr = WIN_FindWndPtr( hwnd );
- if (!wndPtr) return;
- dlgInfo = (DIALOGINFO *)wndPtr->wExtra;
- rect->left = (rect->left * dlgInfo->xBaseUnit) / 4;
- rect->right = (rect->right * dlgInfo->xBaseUnit) / 4;
- rect->top = (rect->top * dlgInfo->yBaseUnit) / 8;
- rect->bottom = (rect->bottom * dlgInfo->yBaseUnit) / 8;
-}
-/***********************************************************************
- * GetNextDlgGroupItem16 (USER.227)
- */
-HWND16 WINAPI GetNextDlgGroupItem16( HWND16 hwndDlg, HWND16 hwndCtrl,
- BOOL16 fPrevious )
-{
- return (HWND16)GetNextDlgGroupItem32( hwndDlg, hwndCtrl, fPrevious );
-}
+
+
/***********************************************************************
- * GetNextDlgGroupItem32 (USER32.275)
+ * GetNextDlgGroupItem (USER32.275)
*/
-HWND32 WINAPI GetNextDlgGroupItem32( HWND32 hwndDlg, HWND32 hwndCtrl,
+HWND STDCALL GetNextDlgGroupItem( HWND hwndDlg, HWND hwndCtrl,
WINBOOL fPrevious )
{
WND *pWnd, *pWndLast, *pWndCtrl, *pWndDlg;
}
-/***********************************************************************
- * GetNextDlgTabItem16 (USER.228)
- */
-HWND16 WINAPI GetNextDlgTabItem16( HWND16 hwndDlg, HWND16 hwndCtrl,
- BOOL16 fPrevious )
-{
- return (HWND16)GetNextDlgTabItem32( hwndDlg, hwndCtrl, fPrevious );
-}
+
/***********************************************************************
- * GetNextDlgTabItem32 (USER32.276)
+ * GetNextDlgTabItem (USER32.276)
*/
-HWND32 WINAPI GetNextDlgTabItem32( HWND32 hwndDlg, HWND32 hwndCtrl,
+HWND STDCALL GetNextDlgTabItem( HWND hwndDlg, HWND hwndCtrl,
WINBOOL fPrevious )
{
WND *pWnd, *pWndLast, *pWndCtrl, *pWndDlg;
WPARAM wParam, LPARAM lParam )
{
// MESSAGEQUEUE *queue;
- HANDLE prevHook;
+ //HANDLE prevHook;
HOOKDATA *data = (HOOKDATA *)(hook);
LRESULT ret;
- WPARAM wParamOrig = wParam;
- LPARAM lParamOrig = lParam;
+ //WPARAM wParamOrig = wParam;
+ //LPARAM lParamOrig = lParam;
// HOOK_MapFunc MapFunc;
// HOOK_UnMapFunc UnMapFunc;
return HOOK_GetHook( id, GetThreadQueue(0) ) != 0;
}
+LRESULT HOOK_CallHooks( INT id, INT code, WPARAM wParam,
+ LPARAM lParam ,WINBOOL bUnicode)
+{
+ if ( bUnicode == TRUE )
+ return HOOK_CallHooksW( id, code, wParam,lParam );
+ else
+ return HOOK_CallHooksA( id, code, wParam,lParam );
+ return 0;
+}
/***********************************************************************
* HOOK_CallHooksA
LRESULT STDCALL SendMessageA( HWND hwnd, UINT msg, WPARAM wParam,
LPARAM lParam )
{
- WND * wndPtr;
- WND **list, **ppWnd;
- LRESULT ret;
+ WND *wndPtr;
if (hwnd == HWND_BROADCAST || hwnd == HWND_TOPMOST)
{
- if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
- return TRUE;
- for (ppWnd = list; *ppWnd; ppWnd++)
- {
- wndPtr = *ppWnd;
- if (!IsWindow(wndPtr->hwndSelf)) continue;
- if (wndPtr->dwStyle & WS_POPUP || wndPtr->dwStyle & WS_CAPTION)
- SendMessageA( wndPtr->hwndSelf, msg, wParam, lParam );
- }
- HeapFree( GetProcessHeap(), 0, list );
- return TRUE;
+ return MSG_SendMessageInterTask(hwnd,msg,wParam,lParam,FALSE);
}
- if (HOOK_IsHooked( WH_CALLWNDPROC ))
- MSG_CallWndProcHook( (LPMSG)&hwnd, FALSE);
if (!(wndPtr = WIN_FindWndPtr( hwnd )))
{
return 0;
}
- if (QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))
- return 0; /* Don't send anything if the task is dying */
-
- SPY_EnterMessage( SPY_SENDMESSAGE, hwnd, msg, wParam, lParam );
-
- if (wndPtr->hmemTaskQ != GetFastQueue())
- ret = MSG_SendMessage( wndPtr->hmemTaskQ, hwnd, msg, wParam, lParam,
- QUEUE_SM_ASCII );
- else
- ret = CallWindowProcA( (WNDPROC)wndPtr->winproc,
- hwnd, msg, wParam, lParam );
+ if (HOOK_IsHooked( WH_CALLWNDPROC ))
+ MSG_CallWndProcHook( (LPMSG)&hwnd, FALSE);
- SPY_ExitMessage( SPY_RESULT_OK, hwnd, msg, ret );
- return ret;
+
+ return MSG_SendMessage(wndPtr,msg,wParam,lParam,FALSE);
}
-LRESULT STDCALL SendMessageW(
- HWND hwnd, /* Window to send message to. If HWND_BROADCAST,
- the message will be sent to all top-level windows. */
-
- UINT msg, /* message */
- WPARAM wParam, /* message parameter */
- LPARAM lParam /* additional message parameter */
-) {
- WND * wndPtr;
- WND **list, **ppWnd;
- LRESULT ret;
+LRESULT STDCALL SendMessageW( HWND hwnd, UINT msg, WPARAM wParam,
+ LPARAM lParam )
+{
+ WND *wndPtr;
if (hwnd == HWND_BROADCAST || hwnd == HWND_TOPMOST)
{
- if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
- return TRUE;
- for (ppWnd = list; *ppWnd; ppWnd++)
- {
- wndPtr = *ppWnd;
- if (!IsWindow(wndPtr->hwndSelf)) continue;
- if (wndPtr->dwStyle & WS_POPUP || wndPtr->dwStyle & WS_CAPTION)
- SendMessageW( wndPtr->hwndSelf, msg, wParam, lParam );
- }
- HeapFree( GetProcessHeap(), 0, list );
- return TRUE;
+ return MSG_SendMessageInterTask(hwnd,msg,wParam,lParam,TRUE);
}
- if (HOOK_IsHooked( WH_CALLWNDPROC ))
- MSG_CallWndProcHook( (LPMSG)&hwnd, TRUE);
if (!(wndPtr = WIN_FindWndPtr( hwnd )))
{
DPRINT( "invalid hwnd %08x\n", hwnd );
return 0;
}
- if (QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))
- return 0; /* Don't send anything if the task is dying */
-
- SPY_EnterMessage( SPY_SENDMESSAGE, hwnd, msg, wParam, lParam );
- if (wndPtr->hmemTaskQ != GetFastQueue())
- ret = MSG_SendMessage( wndPtr->hmemTaskQ, hwnd, msg, wParam, lParam,
- QUEUE_SM_ASCII | QUEUE_SM_UNICODE );
- else
- ret = CallWindowProcW( (WNDPROC)wndPtr->winproc,
- hwnd, msg, wParam, lParam );
+ if (HOOK_IsHooked( WH_CALLWNDPROC ))
+ MSG_CallWndProcHook( (LPMSG)&hwnd, FALSE);
- SPY_ExitMessage( SPY_RESULT_OK, hwnd, msg, ret );
- return ret;
+
+ return MSG_SendMessage(wndPtr,msg,wParam,lParam,TRUE);
}
/***********************************************************************
#define UNICODE
#include <windows.h>
#include <user32/win.h>
+#include <user32/nc.h>
#include <user32/resource.h>
#define MB_DEFMASK 0x00000F00
LRESULT CALLBACK MSGBOX_DlgProc( HWND hwnd, UINT message,
- WPARAM wParam, LPARAM lParam );
+ WPARAM wParam, LPARAM lParam, WINBOOL bUnicode );
+LRESULT CALLBACK MSGBOX_DlgProcA( HWND hwnd, UINT message,
+ WPARAM wParam, LPARAM lParam );
+LRESULT CALLBACK MSGBOX_DlgProcW( HWND hwnd, UINT message,
+ WPARAM wParam, LPARAM lParam );
// FIXME ?????????
/* Static text */
UINT type, WORD langid )
{
MSGBOXPARAMS mbox;
-
+ HANDLE hrsrc;
+ HANDLE hDlgTemplate;
if (title == NULL)
title="Error";
if (text == NULL)
mbox.lpszCaption = title;
mbox.lpszText = text;
mbox.dwStyle = type;
- return DialogBoxIndirectParamA( WIN_GetWindowInstance(hWnd),
- SYSRES_GetResPtr( SYSRES_DIALOG_MSGBOX ),
- hWnd, MSGBOX_DlgProc, (LPARAM)&mbox );
+
+ hrsrc = FindResourceA( NULL, "MSGBOX", RT_DIALOG );
+ if (!hrsrc) return 0;
+
+ hDlgTemplate = LockResource(LoadResource(NULL,hrsrc));
+ return DialogBoxIndirectParamA( NULL, hDlgTemplate,
+ hWnd, MSGBOX_DlgProcA, (LPARAM)&mbox );
}
/**************************************************************************
UINT type, WORD langid )
{
MSGBOXPARAMS mbox;
-
+ HANDLE hrsrc;
+ HANDLE hDlgTemplate;
if (title == NULL)
title=L"Error";
if (text == NULL)
mbox.lpszCaption = title;
mbox.lpszText = text;
mbox.dwStyle = type;
- return DialogBoxIndirectParamW( WIN_GetWindowInstance(hWnd),
- SYSRES_GetResPtr( SYSRES_DIALOG_MSGBOX ),
- hWnd, MSGBOX_DlgProc, (LPARAM)&mbox );
+
+ hrsrc = FindResourceW( NULL, L"MSGBOX", RT_DIALOG );
+ if (!hrsrc) return 0;
+
+ hDlgTemplate = LockResource(LoadResource(NULL,hrsrc));
+ return DialogBoxIndirectParamW( NULL,
+ hDlgTemplate,
+ hWnd, MSGBOX_DlgProcW, (LPARAM)&mbox );
}
*/
INT STDCALL MessageBoxIndirectA( LPMSGBOXPARAMS msgbox )
{
-
+ HANDLE hrsrc = FindResourceA( NULL, "MSGBOX", RT_DIALOG );
+ HANDLE hDlgTemplate;
+ if (!hrsrc) return 0;
+ hDlgTemplate = LockResource(LoadResource(NULL,hrsrc));
return DialogBoxIndirectParamA( msgbox->hInstance,
- SYSRES_GetResPtr( SYSRES_DIALOG_MSGBOX ),
- msgbox->hwndOwner, MSGBOX_DlgProc,
+ hDlgTemplate,
+ msgbox->hwndOwner, MSGBOX_DlgProcA,
(LPARAM)msgbox );
}
INT STDCALL MessageBoxIndirectW( LPMSGBOXPARAMS msgbox )
{
+ HANDLE hrsrc = FindResourceW( NULL, L"MSGBOX", RT_DIALOG );
+ HANDLE hDlgTemplate;
+ if (!hrsrc) return 0;
+ hDlgTemplate = LockResource(LoadResource(NULL,hrsrc));
return DialogBoxIndirectParamW( msgbox->hInstance,
- SYSRES_GetResPtr( SYSRES_DIALOG_MSGBOX ),
- msgbox->hwndOwner, MSGBOX_DlgProc,
+ hDlgTemplate,
+ msgbox->hwndOwner, MSGBOX_DlgProcW,
(LPARAM)msgbox );
}
*
* Dialog procedure for message boxes.
*/
-LRESULT CALLBACK MSGBOX_DlgProc( HWND hwnd, UINT message,
+LRESULT CALLBACK MSGBOX_DlgProcA( HWND hwnd, UINT message,
WPARAM wParam, LPARAM lParam )
+{
+ return MSGBOX_DlgProc(hwnd,message,wParam,lParam,FALSE);
+}
+
+LRESULT CALLBACK MSGBOX_DlgProcW( HWND hwnd, UINT message,
+ WPARAM wParam, LPARAM lParam )
+{
+ return MSGBOX_DlgProc(hwnd,message,wParam,lParam,TRUE);
+}
+
+LRESULT CALLBACK MSGBOX_DlgProc( HWND hwnd, UINT message,WPARAM wParam, LPARAM lParam, WINBOOL bUnicode )
{
static HFONT hFont = 0;
LPMSGBOXPARAMS lpmb;
int i, buttons, bwidth, bheight, theight, wwidth, bpos;
int borheight, iheight, tiheight;
- NONCLIENTMETRICS nclm;
switch(message) {
case WM_INITDIALOG:
lpmb = (LPMSGBOXPARAMS)lParam;
- nclm.cbSize = sizeof(NONCLIENTMETRICS);
- SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
- hFont = CreateFontIndirect(&nclm.lfMessageFont);
- /* set button font */
- for (i=1; i < 8; i++)
- SendDlgItemMessageW (hwnd, i, WM_SETFONT, (WPARAM)hFont, 0);
- /* set text font */
- SendDlgItemMessageW (hwnd, 100, WM_SETFONT, (WPARAM)hFont, 0);
+ if (TWEAK_WineLook >= WIN95_LOOK) {
+ NONCLIENTMETRICS nclm;
+ INT i;
+ nclm.cbSize = sizeof(NONCLIENTMETRICS);
+ SystemParametersInfoA(SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
+ hFont = CreateFontIndirect (&nclm.lfMessageFont);
+ /* set button font */
+ for (i=1; i < 8; i++)
+ SendDlgItemMessage (hwnd, i, WM_SETFONT, (WPARAM)hFont, 0);
+ /* set text font */
+ SendDlgItemMessage (hwnd, 100, WM_SETFONT, (WPARAM)hFont, 0);
+ }
+
+
+
- if (lpmb->lpszCaption)
- SetWindowTextW(hwnd, lpmb->lpszCaption);
- SetWindowTextW(GetDlgItem(hwnd, 100), lpmb->lpszText);
+ if ( bUnicode == TRUE ) {
+ if (lpmb->lpszCaption)
+ SetWindowTextW(hwnd, (LPCWSTR)lpmb->lpszCaption);
+ SetWindowTextW(GetDlgItem(hwnd, 100),(LPWSTR) lpmb->lpszText);
+ } else {
+ if (lpmb->lpszCaption)
+ SetWindowTextA(hwnd, lpmb->lpszCaption);
+ SetWindowTextA(GetDlgItem(hwnd, 100), lpmb->lpszText);
+ }
/* Hide not selected buttons */
switch(lpmb->dwStyle & MB_TYPEMASK) {
- case MB_OK:
- ShowWindow(GetDlgItem(hwnd, 2), SW_HIDE);
- /* fall through */
- case MB_OKCANCEL:
- ShowWindow(GetDlgItem(hwnd, 3), SW_HIDE);
- ShowWindow(GetDlgItem(hwnd, 4), SW_HIDE);
- ShowWindow(GetDlgItem(hwnd, 5), SW_HIDE);
- ShowWindow(GetDlgItem(hwnd, 6), SW_HIDE);
- ShowWindow(GetDlgItem(hwnd, 7), SW_HIDE);
- break;
- case MB_ABORTRETRYIGNORE:
- ShowWindow(GetDlgItem(hwnd, 1), SW_HIDE);
- ShowWindow(GetDlgItem(hwnd, 2), SW_HIDE);
- ShowWindow(GetDlgItem(hwnd, 6), SW_HIDE);
- ShowWindow(GetDlgItem(hwnd, 7), SW_HIDE);
- break;
- case MB_YESNO:
- ShowWindow(GetDlgItem(hwnd, 2), SW_HIDE);
- /* fall through */
- case MB_YESNOCANCEL:
- ShowWindow(GetDlgItem(hwnd, 1), SW_HIDE);
- ShowWindow(GetDlgItem(hwnd, 3), SW_HIDE);
- ShowWindow(GetDlgItem(hwnd, 4), SW_HIDE);
- ShowWindow(GetDlgItem(hwnd, 5), SW_HIDE);
- break;
- }
- /* Set the icon */
- switch(lpmb->dwStyle & MB_ICONMASK) {
- case MB_ICONEXCLAMATION:
- SendDlgItemMessage(hwnd, stc1, STM_SETICON,
- (WPARAM)LoadIcon(0, IDI_EXCLAMATION), 0);
- break;
- case MB_ICONQUESTION:
- SendDlgItemMessage(hwnd, stc1, STM_SETICON,
+ case MB_OK:
+ ShowWindow(GetDlgItem(hwnd, 2), SW_HIDE);
+ /* fall through */
+ case MB_OKCANCEL:
+ ShowWindow(GetDlgItem(hwnd, 3), SW_HIDE);
+ ShowWindow(GetDlgItem(hwnd, 4), SW_HIDE);
+ ShowWindow(GetDlgItem(hwnd, 5), SW_HIDE);
+ ShowWindow(GetDlgItem(hwnd, 6), SW_HIDE);
+ ShowWindow(GetDlgItem(hwnd, 7), SW_HIDE);
+ break;
+ case MB_ABORTRETRYIGNORE:
+ ShowWindow(GetDlgItem(hwnd, 1), SW_HIDE);
+ ShowWindow(GetDlgItem(hwnd, 2), SW_HIDE);
+ ShowWindow(GetDlgItem(hwnd, 6), SW_HIDE);
+ ShowWindow(GetDlgItem(hwnd, 7), SW_HIDE);
+ break;
+ case MB_YESNO:
+ ShowWindow(GetDlgItem(hwnd, 2), SW_HIDE);
+ /* fall through */
+ case MB_YESNOCANCEL:
+ ShowWindow(GetDlgItem(hwnd, 1), SW_HIDE);
+ ShowWindow(GetDlgItem(hwnd, 3), SW_HIDE);
+ ShowWindow(GetDlgItem(hwnd, 4), SW_HIDE);
+ ShowWindow(GetDlgItem(hwnd, 5), SW_HIDE);
+ break;
+ }
+ /* Set the icon */
+ switch(lpmb->dwStyle & MB_ICONMASK) {
+ case MB_ICONEXCLAMATION:
+ SendDlgItemMessage(hwnd, stc1, STM_SETICON,
+ (WPARAM)LoadIcon(0, IDI_EXCLAMATION), 0);
+ break;
+ case MB_ICONQUESTION:
+ SendDlgItemMessage(hwnd, stc1, STM_SETICON,
(WPARAM)LoadIcon(0, IDI_QUESTION), 0);
- break;
- case MB_ICONASTERISK:
- SendDlgItemMessage(hwnd, stc1, STM_SETICON,
+ break;
+ case MB_ICONASTERISK:
+ SendDlgItemMessage(hwnd, stc1, STM_SETICON,
(WPARAM)LoadIcon(0, IDI_ASTERISK), 0);
- break;
- case MB_ICONHAND:
- default:
- SendDlgItemMessage(hwnd, stc1, STM_SETICON,
+ break;
+ case MB_ICONHAND:
+ default:
+ SendDlgItemMessage(hwnd, stc1, STM_SETICON,
(WPARAM)LoadIcon(0, IDI_HAND), 0);
- break;
- }
+ break;
+ }
- /* Position everything */
- GetWindowRect(hwnd, &rect);
- borheight = rect.bottom - rect.top;
- wwidth = rect.right - rect.left;
- GetClientRect(hwnd, &rect);
- borheight -= rect.bottom - rect.top;
-
- /* Get the icon height */
- GetWindowRect(GetDlgItem(hwnd, 1088), &rect);
- iheight = rect.bottom - rect.top;
+ /* Position everything */
+ GetWindowRect(hwnd, &rect);
+ borheight = rect.bottom - rect.top;
+ wwidth = rect.right - rect.left;
+ GetClientRect(hwnd, &rect);
+ borheight -= rect.bottom - rect.top;
+
+ /* Get the icon height */
+ GetWindowRect(GetDlgItem(hwnd, 1088), &rect);
+ iheight = rect.bottom - rect.top;
- /* Get the number of visible buttons and their width */
- GetWindowRect(GetDlgItem(hwnd, 2), &rect);
- bheight = rect.bottom - rect.top;
- bwidth = rect.left;
- GetWindowRect(GetDlgItem(hwnd, 1), &rect);
- bwidth -= rect.left;
- for (buttons = 0, i = 1; i < 8; i++)
- {
- hItem = GetDlgItem(hwnd, i);
- if (GetWindowLongW(hItem, GWL_STYLE) & WS_VISIBLE)
- buttons++;
- }
+ /* Get the number of visible buttons and their width */
+ GetWindowRect(GetDlgItem(hwnd, 2), &rect);
+ bheight = rect.bottom - rect.top;
+ bwidth = rect.left;
+ GetWindowRect(GetDlgItem(hwnd, 1), &rect);
+ bwidth -= rect.left;
+ for (buttons = 0, i = 1; i < 8; i++)
+ {
+ hItem = GetDlgItem(hwnd, i);
+ if (GetWindowLong(hItem, GWL_STYLE) & WS_VISIBLE)
+ buttons++;
+ }
- /* Get the text size */
- hItem = GetDlgItem(hwnd, 100);
- GetWindowRect(hItem, &textrect);
- MapWindowPoints(0, hwnd, (LPPOINT)&textrect, 2);
+ /* Get the text size */
+ hItem = GetDlgItem(hwnd, 100);
+ GetWindowRect(hItem, &textrect);
+ MapWindowPoints(0, hwnd, (LPPOINT)&textrect, 2);
- GetClientRect(hItem, &rect);
- hdc = GetDC(hItem);
- lRet = DrawTextW( hdc, lpmb->lpszText, -1, &rect,
+ GetClientRect(hItem, &rect);
+ hdc = GetDC(hItem);
+
+
+ if ( bUnicode )
+ lRet = DrawTextW( hdc, (LPCWSTR)lpmb->lpszText, -1, &rect,
DT_LEFT | DT_EXPANDTABS | DT_WORDBREAK | DT_CALCRECT);
- theight = rect.bottom - rect.top;
- tiheight = 16 + max(iheight, theight);
- ReleaseDC(hItem, hdc);
+ else
+ lRet = DrawTextA( hdc, lpmb->lpszText, -1, &rect,
+ DT_LEFT | DT_EXPANDTABS | DT_WORDBREAK | DT_CALCRECT);
+ theight = rect.bottom - rect.top;
+ tiheight = 16 + max(iheight, theight);
+ ReleaseDC(hItem, hdc);
- /* Position the text */
- SetWindowPos(hItem, 0, textrect.left, (tiheight - theight) / 2,
+ /* Position the text */
+ SetWindowPos(hItem, 0, textrect.left, (tiheight - theight) / 2,
rect.right - rect.left, theight,
SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW);
- /* Position the icon */
- hItem = GetDlgItem(hwnd, 1088);
- GetWindowRect(hItem, &rect);
- MapWindowPoints(0, hwnd, (LPPOINT)&rect, 2);
- SetWindowPos(hItem, 0, rect.left, (tiheight - iheight) / 2, 0, 0,
+ /* Position the icon */
+ hItem = GetDlgItem(hwnd, 1088);
+ GetWindowRect(hItem, &rect);
+ MapWindowPoints(0, hwnd, (LPPOINT)&rect, 2);
+ SetWindowPos(hItem, 0, rect.left, (tiheight - iheight) / 2, 0, 0,
SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW);
/* Resize the window */
- SetWindowPos(hwnd, 0, 0, 0, wwidth, 8 + tiheight + bheight + borheight,
+ SetWindowPos(hwnd, 0, 0, 0, wwidth, 8 + tiheight + bheight + borheight,
SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW);
/* Position the buttons */
- bpos = (wwidth - bwidth * buttons) / 2;
- GetWindowRect(GetDlgItem(hwnd, 1), &rect);
- for (buttons = i = 0; i < 7; i++) {
- /* some arithmetic to get the right order for YesNoCancel windows */
- hItem = GetDlgItem(hwnd, (i + 5) % 7 + 1);
- if (GetWindowLongW(hItem, GWL_STYLE) & WS_VISIBLE) {
- if (buttons++ == ((lpmb->dwStyle & MB_DEFMASK) >> 8)) {
- SetFocus(hItem);
- SendMessageW( hItem, BM_SETSTYLE, BS_DEFPUSHBUTTON, TRUE );
- }
- SetWindowPos(hItem, 0, bpos, tiheight, 0, 0,
- SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOREDRAW);
- bpos += bwidth;
- }
- }
- return 0;
- break;
+ bpos = (wwidth - bwidth * buttons) / 2;
+ GetWindowRect(GetDlgItem(hwnd, 1), &rect);
+ for (buttons = i = 0; i < 7; i++) {
+ /* some arithmetic to get the right order for YesNoCancel windows */
+ hItem = GetDlgItem(hwnd, (i + 5) % 7 + 1);
+ if (GetWindowLong(hItem, GWL_STYLE) & WS_VISIBLE) {
+ if (buttons++ == ((lpmb->dwStyle & MB_DEFMASK) >> 8)) {
+ SetFocus(hItem);
+ SendMessage( hItem, BM_SETSTYLE, BS_DEFPUSHBUTTON, TRUE );
+ }
+ SetWindowPos(hItem, 0, bpos, tiheight, 0, 0,
+ SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOREDRAW);
+ bpos += bwidth;
+ }
+ }
+ return 0;
+ break;
case WM_COMMAND:
switch (wParam)
--- /dev/null
+/*
+ * Scroll windows and DCs
+ *
+ * Copyright David W. Metcalfe, 1993
+ * Alex Korobka 1995,1996
+ *
+ *
+ */
+
+#include <stdlib.h>
+#include <windows.h>
+#include <user32/class.h>
+#include <user32/win.h>
+#include <user32/dce.h>
+#include <user32/sysmetr.h>
+#include <user32/caret.h>
+#include <user32/debug.h>
+
+
+
+/*************************************************************************
+ * ScrollWindow (USER.450)
+ *
+ * FIXME: verify clipping region calculations
+ */
+WINBOOL STDCALL ScrollWindow( HWND hwnd, INT dx, INT dy,
+ const RECT *rect, const RECT *clipRect )
+{
+ HDC hdc;
+ HRGN hrgnUpdate,hrgnClip;
+ RECT rc, cliprc;
+ HWND hCaretWnd = CARET_GetHwnd();
+ WND* wndScroll = WIN_FindWndPtr( hwnd );
+
+
+ if ( !wndScroll || !WIN_IsWindowDrawable( wndScroll, TRUE ) ) return TRUE;
+
+ if ( !rect ) /* do not clip children */
+ {
+ GetClientRect(hwnd, &rc);
+ hrgnClip = CreateRectRgnIndirect( &rc );
+
+ if ((hCaretWnd == hwnd) || IsChild(hwnd,hCaretWnd))
+ HideCaret(hCaretWnd);
+ else hCaretWnd = 0;
+
+ hdc = GetDCEx(hwnd, hrgnClip, DCX_CACHE | DCX_CLIPSIBLINGS);
+ DeleteObject( hrgnClip );
+ }
+ else /* clip children */
+ {
+ CopyRect(&rc, rect);
+
+ if (hCaretWnd == hwnd) HideCaret(hCaretWnd);
+ else hCaretWnd = 0;
+
+ hdc = GetDCEx( hwnd, 0, DCX_CACHE | DCX_USESTYLE );
+ }
+
+ if (clipRect == NULL)
+ GetClientRect(hwnd, &cliprc);
+ else
+ CopyRect(&cliprc, clipRect);
+
+ hrgnUpdate = CreateRectRgn( 0, 0, 0, 0 );
+ ScrollDC( hdc, dx, dy, &rc, &cliprc, hrgnUpdate, NULL );
+ ReleaseDC(hwnd, hdc);
+
+ if( !rect ) /* move child windows and update region */
+ {
+ WND* wndPtr;
+
+ if( wndScroll->hrgnUpdate > 1 )
+ OffsetRgn( wndScroll->hrgnUpdate, dx, dy );
+
+ for (wndPtr = wndScroll->child; wndPtr; wndPtr = wndPtr->next)
+ SetWindowPos(wndPtr->hwndSelf, 0, wndPtr->rectWindow.left + dx,
+ wndPtr->rectWindow.top + dy, 0,0, SWP_NOZORDER |
+ SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOREDRAW |
+ SWP_DEFERERASE );
+ }
+
+ PAINT_RedrawWindow( hwnd, NULL, hrgnUpdate, RDW_ALLCHILDREN |
+ RDW_INVALIDATE | RDW_ERASE | RDW_ERASENOW, RDW_C_USEHRGN );
+
+ DeleteObject( hrgnUpdate );
+ if( hCaretWnd )
+ {
+ POINT pt;
+ GetCaretPos(&pt);
+ pt.x += dx; pt.y += dy;
+ SetCaretPos(pt.x, pt.y);
+ ShowCaret(hCaretWnd);
+ }
+ return TRUE;
+}
+
+
+
+
+
+/*************************************************************************
+ * ScrollDC (USER.449)
+ *
+ * Both 'rc' and 'prLClip' are in logical units but update info is
+ * returned in device coordinates.
+ */
+WINBOOL STDCALL ScrollDC( HDC hdc, INT dx, INT dy, const RECT *rc,
+ const RECT *prLClip, HRGN hrgnUpdate,
+ LPRECT rcUpdate )
+{
+#if 0
+ RECT rClip;
+ POINT src, dest;
+ INT ldx, ldy;
+
+
+ if (!hdc ) return FALSE;
+
+
+ /* compute device clipping region */
+
+ if ( rc )
+ rClip = *rc;
+ else /* maybe we should just return FALSE? */
+ GetClipBox( hdc, &rClip );
+
+ if (prLClip)
+ IntersectRect(&rClip,&rClip,prLClip);
+
+ if( rClip.left >= rClip.right || rClip.top >= rClip.bottom )
+ {
+ return FALSE;
+ }
+
+ SaveVisRgn( hdc );
+ IntersectVisRect( hdc, rClip.left, rClip.top,
+ rClip.right, rClip.bottom );
+
+
+ /* translate coordinates */
+
+ ldx = dx * dc->wndExtX / dc->vportExtX;
+ ldy = dy * dc->wndExtY / dc->vportExtY;
+
+ if (dx > 0)
+ dest.x = (src.x = rClip.left) + ldx;
+ else
+ src.x = (dest.x = rClip.left) - ldx;
+
+ if (dy > 0)
+ dest.y = (src.y = rClip.top) + ldy;
+ else
+ src.y = (dest.y = rClip.top) - ldy;
+
+ /* copy bits */
+
+ if( rClip.right - rClip.left > ldx &&
+ rClip.bottom - rClip.top > ldy )
+ {
+ ldx = rClip.right - rClip.left - ldx;
+ ldy = rClip.bottom - rClip.top - ldy;
+
+ if (!BitBlt( hdc, dest.x, dest.y, ldx, ldy,
+ hdc, src.x, src.y, SRCCOPY))
+ {
+ return FALSE;
+ }
+ }
+
+ /* restore clipping region */
+
+ RestoreVisRgn( hdc );
+
+
+ /* compute update areas */
+
+ if ( (hrgnUpdate || rcUpdate) && dc->w.hVisRgn )
+ {
+ HRGN hrgn = (hrgnUpdate) ? hrgnUpdate : CreateRectRgn( 0,0,0,0 );
+ HRGN hrgnClip;
+
+ LPtoDP( hdc, (LPPOINT)&rClip, 2 );
+ OffsetRect( &rClip, dc->w.DCOrgX, dc->w.DCOrgY );
+ hrgnClip = CreateRectRgnIndirect( &rClip );
+
+ CombineRgn( hrgn, dc->w.hVisRgn, hrgnClip, RGN_AND );
+ OffsetRgn( hrgn, dx, dy );
+ CombineRgn( hrgn, dc->w.hVisRgn, hrgn, RGN_DIFF );
+ CombineRgn( hrgn, hrgn, hrgnClip, RGN_AND );
+ OffsetRgn( hrgn, -dc->w.DCOrgX, -dc->w.DCOrgY );
+
+ if( rcUpdate ) GetRgnBox( hrgnUpdate, rcUpdate );
+
+ if (!hrgnUpdate) DeleteObject( hrgn );
+ DeleteObject( hrgnClip );
+ }
+#endif
+ return TRUE;
+}
+
+
+
+
+
+/*************************************************************************
+ * ScrollWindowEx (USER.451)
+ *
+ * NOTE: Use this function instead of ScrollWindow
+ */
+INT STDCALL ScrollWindowEx( HWND hwnd, INT dx, INT dy,
+ const RECT *rect, const RECT *clipRect,
+ HRGN hrgnUpdate, LPRECT rcUpdate,
+ UINT flags )
+{
+ INT retVal = NULLREGION;
+ WINBOOL bCaret = FALSE, bOwnRgn = TRUE;
+ RECT rc, cliprc;
+ WND* wnd = WIN_FindWndPtr( hwnd );
+
+ if( !wnd || !WIN_IsWindowDrawable( wnd, TRUE )) return ERROR;
+
+ if (rect == NULL) GetClientRect(hwnd, &rc);
+ else rc = *rect;
+
+ if (clipRect) IntersectRect(&cliprc,&rc,clipRect);
+ else cliprc = rc;
+
+ if (!IsRectEmpty(&cliprc) && (dx || dy))
+ {
+
+ HDC hDC;
+ WINBOOL bUpdate = (rcUpdate || hrgnUpdate || flags & (SW_INVALIDATE | SW_ERASE));
+ HRGN hrgnClip = CreateRectRgnIndirect(&cliprc);
+
+
+ rc = cliprc;
+ bCaret = SCROLL_FixCaret(hwnd, &rc, flags);
+
+ if( hrgnUpdate ) bOwnRgn = FALSE;
+ else if( bUpdate ) hrgnUpdate = CreateRectRgn( 0, 0, 0, 0 );
+
+ hDC = GetDCEx( hwnd, hrgnClip, DCX_CACHE | DCX_USESTYLE |
+ ((flags & SW_SCROLLCHILDREN) ? DCX_NOCLIPCHILDREN : 0) );
+ if( hDC != NULL)
+ {
+
+#if 0
+ if( dc->w.hVisRgn && bUpdate )
+ {
+ OffsetRgn( hrgnClip, dc->w.DCOrgX, dc->w.DCOrgY );
+ CombineRgn( hrgnUpdate, dc->w.hVisRgn, hrgnClip, RGN_AND );
+ OffsetRgn( hrgnUpdate, dx, dy );
+ CombineRgn( hrgnUpdate, dc->w.hVisRgn, hrgnUpdate, RGN_DIFF );
+ CombineRgn( hrgnUpdate, hrgnUpdate, hrgnClip, RGN_AND );
+ OffsetRgn( hrgnUpdate, -dc->w.DCOrgX, -dc->w.DCOrgY );
+
+ if( rcUpdate ) GetRgnBox( hrgnUpdate, rcUpdate );
+ }
+#endif
+ ReleaseDC(hwnd, hDC);
+
+ }
+
+ if( wnd->hrgnUpdate > 1 )
+ {
+ if( rect || clipRect )
+ {
+ if( (CombineRgn( hrgnClip, hrgnClip,
+ wnd->hrgnUpdate, RGN_AND ) != NULLREGION) )
+ {
+ CombineRgn( wnd->hrgnUpdate, wnd->hrgnUpdate, hrgnClip, RGN_DIFF );
+ OffsetRgn( hrgnClip, dx, dy );
+ CombineRgn( wnd->hrgnUpdate, wnd->hrgnUpdate, hrgnClip, RGN_OR );
+ }
+ }
+ else
+ OffsetRgn( wnd->hrgnUpdate, dx, dy );
+ }
+
+ if( flags & SW_SCROLLCHILDREN )
+ {
+ RECT r;
+ WND* w;
+ for( w = wnd->child; w; w = w->next )
+ {
+
+ if( !clipRect || IntersectRect(&w->rectWindow, &r, &cliprc) )
+ SetWindowPos(w->hwndSelf, 0, w->rectWindow.left + dx,
+ w->rectWindow.top + dy, 0,0, SWP_NOZORDER |
+ SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOREDRAW |
+ SWP_DEFERERASE );
+ }
+ }
+
+ if( flags & (SW_INVALIDATE | SW_ERASE) )
+ PAINT_RedrawWindow( hwnd, NULL, hrgnUpdate, RDW_INVALIDATE | RDW_ERASE |
+ ((flags & SW_ERASE) ? RDW_ERASENOW : 0) | ((flags & SW_SCROLLCHILDREN) ? RDW_ALLCHILDREN : 0 ), 0 );
+
+ if( bCaret )
+ {
+ SetCaretPos( rc.left + dx, rc.top + dy );
+ ShowCaret(0);
+ }
+
+ if( bOwnRgn && hrgnUpdate ) DeleteObject( hrgnUpdate );
+ DeleteObject( hrgnClip );
+ }
+ return retVal;
+}
+
+
#include <user32/winpos.h>
#include <user32/hook.h>
#include <user32/property.h>
+#include <user32/paint.h>
#include <user32/debug.h>
+// change style on WS_OVERLAPPEDWINDOW
#undef CreateWindowA
HWND STDCALL CreateWindowA(LPCSTR lpClassName, LPCSTR lpWindowName,
//if(exStyle & WS_EX_MDICHILD)
// return MDI_CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, data);
-#if 0
- while ((*lpWindowName)!=0 && i < MAX_PATH)
- {
- WindowNameW[i] = *lpWindowName;
- lpWindowName++;
- i++;
- }
- WindowNameW[i] = 0;
-#endif
+
+ if ( style == WS_OVERLAPPEDWINDOW )
+ style |= (WS_OVERLAPPED| WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX |WS_MAXIMIZEBOX );
/* Create the window */
HWND parent, HMENU menu,
HINSTANCE hInstance, LPVOID data )
{
-// WCHAR WindowNameW[MAX_PATH];
-// WCHAR ClassNameW[MAX_PATH];
CLASS *p;
DWORD status;
CREATESTRUCTW cs;
if ( p == NULL )
return NULL;
-
+ if ( style == WS_OVERLAPPEDWINDOW )
+ style |= (WS_OVERLAPPED| WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX |WS_MAXIMIZEBOX );
/* Create the window */
{
WND * wndPtr;
- DPRINT( "(%04x)\n", hwnd);
-
/* Initialization */
if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
//if (wndPtr == pWndDesktop) return FALSE; /* Can't destroy desktop */
+
+ if ( hwnd == NULL )
+ return FALSE;
+
+
/* Call hooks */
- if( HOOK_CallHooksA( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
+ if( HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, hwnd, 0L, wndPtr->class->bUnicode ) )
return FALSE;
if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
{
- HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
+ HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L, wndPtr->class->bUnicode );
/* FIXME: clean up palette - see "Internals" p.352 */
}
if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
{
/* Notify the parent window only */
- SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
+ if ( wndPtr->parent != NULL )
+ SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
if( !IsWindow(hwnd) ) return TRUE;
}
- // CLIPBOARD_GetDriver()->pResetOwner( wndPtr, FALSE ); /* before the window is unmapped */
+
/* Hide the window */
for (;;)
{
- WND *siblingPtr = wndPtr->parent->child; /* First sibling */
+
+ WND *siblingPtr = NULL;
+ if ( wndPtr->parent != NULL )
+ siblingPtr = wndPtr->parent->child; /* First sibling */
while (siblingPtr)
{
if (siblingPtr->owner == wndPtr)
/***********************************************************************
- * ShowWindow32 (USER32.534)
+ * ShowWindow (USER32.534)
*/
WINBOOL STDCALL ShowWindow( HWND hwnd, INT cmd )
{
WND* wndPtr = WIN_FindWndPtr( hwnd );
- WINBOOL wasVisible, showFlag;
+ WINBOOL wasVisible = FALSE, showFlag;
RECT newPos = {0, 0, 0, 0};
int swp = 0;
if (!wndPtr) return FALSE;
// DPRINT("hwnd=%04x, cmd=%d\n", hwnd, cmd);
+#ifdef OPTIMIZATION
wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0;
+#endif
switch(cmd)
{
// SendMessage(hwnd, WM_NCACTIVATE,TRUE,0);
// SendMessage(hwnd, WM_NCPAINT,CreateRectRgn(100,100,100, 100) ,0);
+
+
return wasVisible;
}
+
+/*******************************************************************
+ * FlashWindow (USER32.202)
+ */
+WINBOOL STDCALL FlashWindow( HWND hWnd, WINBOOL bInvert )
+{
+ WND *wndPtr = WIN_FindWndPtr(hWnd);
+
+
+ if (!wndPtr) return FALSE;
+
+ if (wndPtr->dwStyle & WS_MINIMIZE)
+ {
+ if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
+ {
+ HDC hDC = GetDC(hWnd);
+
+ if (!SendMessage( hWnd, WM_ERASEBKGND, (WPARAM)hDC, 0 ))
+ wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
+
+ ReleaseDC( hWnd, hDC );
+ wndPtr->flags |= WIN_NCACTIVATED;
+ }
+ else
+ {
+ PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
+ RDW_UPDATENOW | RDW_FRAME, 0 );
+ wndPtr->flags &= ~WIN_NCACTIVATED;
+ }
+ return TRUE;
+ }
+ else
+ {
+ WPARAM wparam;
+ if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
+ else wparam = (hWnd == GetActiveWindow());
+
+ SendMessage( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
+ return wparam;
+ }
+}
+
+
WINBOOL
STDCALL
SetWindowPos(
- HWND hWnd,
- HWND hWndInsertAfter ,
- int X,
- int Y,
- int cx,
- int cy,
+ HWND hWnd, HWND hWndInsertAfter ,
+ int X, int Y,
+ int cx, int cy,
UINT flags)
{
- WINDOWPOS winpos;
+
+ WINDOWPOS winpos;
WND * wndPtr;
RECT newWindowRect, newClientRect, oldWindowRect;
HRGN visRgn = 0;
UINT uFlags;
WINBOOL resync = FALSE;
- DPRINT("hwnd %04x, (%i,%i)-(%i,%i) flags %08x\n",
- hWnd, X, Y, X+cx, Y+cy, flags);
+
/* Check window handle */
if (hWnd == GetDesktopWindow()) return FALSE;
+
+ if (hWnd == GetActiveWindow() ) flags |= SWP_NOACTIVATE; /* Already active */
+
+
+ /* Check dimensions */
+
+ if (cx <= 0) cx = 1;
+ if (cy <= 0) cy = 1;
+
if (!(wndPtr = WIN_FindWndPtr( hWnd ))) return FALSE;
+#if OPTIMIZATION
if(wndPtr->dwStyle & WS_VISIBLE)
flags &= ~SWP_SHOWWINDOW;
else
if (!(flags & SWP_SHOWWINDOW)) flags |= SWP_NOREDRAW;
}
-/* Check for windows that may not be resized
- FIXME: this should be done only for Windows 3.0 programs
- if (flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW ) )
- flags |= SWP_NOSIZE | SWP_NOMOVE;
-*/
- /* Check dimensions */
- if (cx <= 0) cx = 1;
- if (cy <= 0) cy = 1;
/* Check flags */
- if (hWnd == hwndActive) flags |= SWP_NOACTIVATE; /* Already active */
if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == cx) &&
(wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == cy))
flags |= SWP_NOSIZE; /* Already the right size */
if ((wndPtr->rectWindow.left == X) && (wndPtr->rectWindow.top == Y))
flags |= SWP_NOMOVE; /* Already the right position */
+#endif
/* Check hWndInsertAfter */
if (!(flags & (SWP_NOZORDER | SWP_NOACTIVATE)))
{
/* Ignore TOPMOST flags when activating a window */
/* _and_ moving it in Z order. */
- if ((hWndInsertAfter == HWND_TOPMOST) ||
- (hWndInsertAfter == HWND_NOTOPMOST))
+
+ if ((hWndInsertAfter == HWND_TOPMOST) || (hWndInsertAfter == HWND_NOTOPMOST))
hWndInsertAfter = HWND_TOP;
}
/* TOPMOST not supported yet */
- if ((hWndInsertAfter == HWND_TOPMOST) ||
- (hWndInsertAfter == HWND_NOTOPMOST)) hWndInsertAfter = HWND_TOP;
+ 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))
/* Send WM_WINDOWPOSCHANGING message */
if (!(winpos.flags & SWP_NOSENDCHANGING))
- SendMessageA( hWnd, WM_WINDOWPOSCHANGING, 0, (LPARAM)&winpos );
+ MSG_SendMessage( wndPtr, WM_WINDOWPOSCHANGING, 0, (LPARAM)&winpos );
/* Calculate new position and size */
- if (!(flags & SWP_NOREDRAW))
+ if (!(flags & SWP_NOREDRAW) && wndPtr->parent != NULL )
PAINT_RedrawWindow( wndPtr->parent->hwndSelf, &oldWindowRect,
0, RDW_INVALIDATE | RDW_ALLCHILDREN |
RDW_ERASE | RDW_ERASENOW, 0 );
+
uFlags |= SMC_NOPARENTERASE;
+
/***********************************************************************
* WINPOS_CreateInternalPosAtom
*/
if( hwnd == hwndActive )
{
hwndActive = 0;
- //WARN(win, "\tattempt to activate destroyed window!\n");
+ DPRINT("\tattempt to activate destroyed window!\n");
}
if( lpPos )
{
- if( IsWindow(lpPos->hwndIconTitle) )
- DestroyWindow( lpPos->hwndIconTitle );
- HeapFree( GetProcessHeap(), 0, lpPos );
+ //if( IsWindow(lpPos->hwndIconTitle) )
+ // DestroyWindow( lpPos->hwndIconTitle );
+ //HeapFree( GetProcessHeap(), 0, lpPos );
}
}
RECT rectParent;
short x, y, xspacing, yspacing;
- GetClientRect( wndPtr->parent->hwndSelf, &rectParent );
+ if ( wndPtr->parent != NULL ) {
+ GetClientRect( wndPtr->parent->hwndSelf, &rectParent );
+ }
+ else {
+
+ rectParent.left = 0;
+ rectParent.right = SYSMETRICS_CXFULLSCREEN;
+
+ rectParent.top = 0;
+ rectParent.right = SYSMETRICS_CYFULLSCREEN;
+ }
+
if ((pt.x >= rectParent.left) && (pt.x + SYSMETRICS_CXICON < rectParent.right) &&
(pt.y >= rectParent.top) && (pt.y + SYSMETRICS_CYICON < rectParent.bottom))
return pt; /* The icon already has a suitable position */
for (x = rectParent.left; x <= rectParent.right-xspacing; x += xspacing)
{
/* Check if another icon already occupies this spot */
- WND *childPtr = wndPtr->parent->child;
+ WND *childPtr = NULL;
+ if ( wndPtr->parent )
+ childPtr = wndPtr->parent->child;
while (childPtr)
{
if ((childPtr->dwStyle & WS_MINIMIZE) && (childPtr != wndPtr))
*(UINT*)&lpPos->ptIconPos = *(UINT*)&lpPos->ptMaxPos = 0xFFFFFFFF;
}
+
if( wnd->dwStyle & WS_MINIMIZE )
memcpy( &lpPos->ptIconPos, &pt,sizeof(POINT) );
else if( wnd->dwStyle & WS_MAXIMIZE )
MinMax.ptMaxPosition.y = -yinc;
}
- SendMessageA( wndPtr->hwndSelf, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax );
+ MSG_SendMessage( wndPtr, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax );
/* Some sanity checks */
//DPRINT("0x%04x %u\n", wndPtr->hwndSelf, cmd );
- if ( wndPtr->class->bUnicode ) {
- if (HOOK_CallHooksW(WH_CBT, HCBT_MINMAX, (INT)wndPtr->hwndSelf, cmd)) {
- swpFlags |= SWP_NOSIZE | SWP_NOMOVE;
- return swpFlags;
- }
- }
- else {
- if (HOOK_CallHooksA(WH_CBT, HCBT_MINMAX, (INT)wndPtr->hwndSelf, cmd)) {
- swpFlags |= SWP_NOSIZE | SWP_NOMOVE;
- return swpFlags;
- }
+
+ if (HOOK_CallHooks(WH_CBT, HCBT_MINMAX, (INT)wndPtr->hwndSelf, cmd, wndPtr->class->bUnicode )) {
+ swpFlags |= SWP_NOSIZE | SWP_NOMOVE;
+ return swpFlags;
}
+
if (lpPos)
{
if( wndPtr->dwStyle & WS_MINIMIZE )
{
- if( !SendMessageA( wndPtr->hwndSelf, WM_QUERYOPEN, 0, 0L ) )
+ if( !MSG_SendMessage( wndPtr->hwndSelf, WM_QUERYOPEN, 0, 0L ) )
return (SWP_NOSIZE | SWP_NOMOVE);
swpFlags |= SWP_NOCOPYBITS;
}
*/
WINBOOL WINPOS_SetActiveWindow( HWND hWnd, WINBOOL fMouse, WINBOOL fChangeFocus)
{
- return FALSE;
+ CBTACTIVATESTRUCT* cbtStruct;
+ WND* wndPtr, *wndTemp;
+ //HQUEUE hOldActiveQueue, hNewActiveQueue;
+ WORD wIconized = 0;
+
+ /* paranoid checks */
+ if( hWnd == GetDesktopWindow || hWnd == hwndActive ) return 0;
+
+/* if (wndPtr && (GetFastQueue() != wndPtr->hmemTaskQ))
+ * return 0;
+ */
+ wndPtr = WIN_FindWndPtr(hWnd);
+ //hOldActiveQueue = (pActiveQueue)?pActiveQueue->self : 0;
+
+ if( (wndTemp = WIN_FindWndPtr(hwndActive)) )
+ wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
+
+
+#if 0
+ /* call CBT hook chain */
+ if ((cbtStruct = SEGPTR_NEW(CBTACTIVATESTRUCT16)))
+ {
+ LRESULT wRet;
+ cbtStruct->fMouse = fMouse;
+ cbtStruct->hWndActive = hwndActive;
+ wRet = HOOK_CallHooks16( WH_CBT, HCBT_ACTIVATE, (WPARAM16)hWnd,
+ (LPARAM)SEGPTR_GET(cbtStruct) );
+ SEGPTR_FREE(cbtStruct);
+ if (wRet) return wRet;
+ }
+#endif
+
+ /* set prev active wnd to current active wnd and send notification */
+ if ((hwndPrevActive = hwndActive) && IsWindow(hwndPrevActive))
+ {
+ if (!SendMessageA( hwndPrevActive, WM_NCACTIVATE, FALSE, 0 ))
+ {
+ //if (GetSysModalWindow16() != hWnd) return 0;
+ /* disregard refusal if hWnd is sysmodal */
+ }
+
+
+ SendMessageA( hwndPrevActive, WM_ACTIVATE,
+ MAKEWPARAM( WA_INACTIVE, wIconized ),
+ (LPARAM)hWnd );
+
+
+ /* check if something happened during message processing */
+ if( hwndPrevActive != hwndActive ) return 0;
+ }
+
+ /* set active wnd */
+ hwndActive = hWnd;
+
+ /* send palette messages */
+ if (hWnd && SendMessage( hWnd, WM_QUERYNEWPALETTE, 0, 0L))
+ SendMessage((HWND)-1, WM_PALETTEISCHANGING, (WPARAM)hWnd, 0L );
+
+ /* if prev wnd is minimized redraw icon title */
+ if( IsIconic( hwndPrevActive ) ) WINPOS_RedrawIconTitle(hwndPrevActive);
+
+#if DESKTOP
+ /* managed windows will get ConfigureNotify event */
+ if (wndPtr && !(wndPtr->dwStyle & WS_CHILD) && !(wndPtr->flags & WIN_MANAGED))
+ {
+ /* check Z-order and bring hWnd to the top */
+ for (wndTemp = WIN_GetDesktop()->child; wndTemp; wndTemp = wndTemp->next)
+ if (wndTemp->dwStyle & WS_VISIBLE) break;
+
+ if( wndTemp != wndPtr )
+ SetWindowPos(hWnd, HWND_TOP, 0,0,0,0,
+ SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
+ if (!IsWindow(hWnd)) return 0;
+ }
+
+#endif
+
+#if 0
+ hNewActiveQueue = wndPtr ? wndPtr->hmemTaskQ : 0;
+
+ /* send WM_ACTIVATEAPP if necessary */
+ if (hOldActiveQueue != hNewActiveQueue)
+ {
+ WND **list, **ppWnd;
+
+ if ((list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
+ {
+ for (ppWnd = list; *ppWnd; ppWnd++)
+ {
+ if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
+
+ if ((*ppWnd)->hmemTaskQ == hOldActiveQueue)
+ SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
+ 0, QUEUE_GetQueueTask(hNewActiveQueue) );
+ }
+ HeapFree( SystemHeap, 0, list );
+ }
+
+ pActiveQueue = (hNewActiveQueue)
+ ? (MESSAGEQUEUE*) GlobalLock16(hNewActiveQueue) : NULL;
+
+ if ((list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
+ {
+ for (ppWnd = list; *ppWnd; ppWnd++)
+ {
+ if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
+
+ if ((*ppWnd)->hmemTaskQ == hNewActiveQueue)
+ SendMessage( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
+ 1, QUEUE_GetQueueTask( hOldActiveQueue ) );
+ }
+ HeapFree( SystemHeap, 0, list );
+ }
+ if (!IsWindow(hWnd)) return 0;
+ }
+
+#endif
+ if (hWnd)
+ {
+ /* walk up to the first unowned window */
+ wndTemp = wndPtr;
+ while (wndTemp->owner) wndTemp = wndTemp->owner;
+ /* and set last active owned popup */
+ wndTemp->hwndLastActive = hWnd;
+
+ wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
+ SendMessageA( hWnd, WM_NCACTIVATE, TRUE, 0 );
+
+ SendMessageA( hWnd, WM_ACTIVATE,
+ MAKEWPARAM( (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE, wIconized),
+ (LPARAM)hwndPrevActive );
+
+
+ if( !IsWindow(hWnd) ) return 0;
+ }
+#if 0
+ /* change focus if possible */
+ if( fChangeFocus && GetFocus() )
+ if( WIN_GetTopParent(GetFocus()) != hwndActive )
+ FOCUS_SwitchFocus( GetFocus(),
+ (wndPtr && (wndPtr->dwStyle & WS_MINIMIZE))?
+ 0:
+ hwndActive
+ );
+#endif
+
+ /* if active wnd is minimized redraw icon title */
+ if( IsIconic(hwndActive) ) WINPOS_RedrawIconTitle(hwndActive);
+
+ return (hWnd == hwndActive);
}
/*******************************************************************
/* child windows get WM_CHILDACTIVATE message */
if( (wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD )
- return SendMessageA(hWnd, WM_CHILDACTIVATE, 0, 0L);
+ return MSG_SendMessage(wndPtr, WM_CHILDACTIVATE, 0, 0L);
/* owned popups imply owner activation - not sure */
if ((wndPtr->dwStyle & WS_POPUP) && wndPtr->owner &&
if( !WINPOS_SetActiveWindow(hWnd ,mouseMsg ,TRUE) )
return FALSE;
+#if DESKTOP
/* switch desktop queue to current active */
if( wndPtr->parent == WIN_GetDesktop())
WIN_GetDesktop()->hmemTaskQ = wndPtr->hmemTaskQ;
-
+#endif
return TRUE;
}
// REMOVED DCX_KEEPCLIPRGN
hDC = GetDCEx( Wnd->parent->hwndSelf, oldVisRgn,
- DCX_INTERSECTRGN |
- DCX_CACHE | DCX_CLIPSIBLINGS);
+ DCX_INTERSECTRGN | DCX_CACHE | DCX_CLIPSIBLINGS);
BitBlt( hDC, xto, yto, width, height, hDC, xfrom, yfrom, SRCCOPY );
ReleaseDC( Wnd->parent->hwndSelf, hDC);
return uFlags;
}
+/***********************************************************************
+ * MoveWindow (USER32.399)
+ */
+WINBOOL STDCALL MoveWindow( HWND hwnd, INT x, INT y, INT cx, INT cy,
+ WINBOOL repaint )
+{
+ int flags = SWP_NOZORDER | SWP_NOACTIVATE;
+ if (!repaint) flags |= SWP_NOREDRAW;
+
+ return SetWindowPos( hwnd, 0, x, y, cx, cy, flags );
+}
+