[User32]
authorJames Tabor <james.tabor@reactos.org>
Wed, 7 Dec 2011 09:23:04 +0000 (09:23 +0000)
committerJames Tabor <james.tabor@reactos.org>
Wed, 7 Dec 2011 09:23:04 +0000 (09:23 +0000)
- Sync up with wine controls. See http://www.winehq.org/pipermail/wine-cvs/ for log data.

svn path=/trunk/; revision=54604

12 files changed:
reactos/dll/win32/user32/CMakeLists.txt
reactos/dll/win32/user32/controls/button.c
reactos/dll/win32/user32/controls/combo.c
reactos/dll/win32/user32/controls/edit.c
reactos/dll/win32/user32/controls/listbox.c
reactos/dll/win32/user32/controls/regcontrol.c
reactos/dll/win32/user32/controls/static.c
reactos/dll/win32/user32/include/controls.h
reactos/dll/win32/user32/include/user32.h
reactos/dll/win32/user32/user32.rbuild
reactos/dll/win32/user32/windows/cursoricon.c
reactos/dll/win32/user32/windows/dialog.c

index b1ace09..e1b0657 100644 (file)
@@ -72,7 +72,7 @@ target_link_libraries(user32
     win32ksys
     ${PSEH_LIB})
 
-add_delay_importlibs(user32 imm32)
+add_delay_importlibs(user32 imm32 usp10)
 add_importlibs(user32 gdi32 advapi32 msvcrt kernel32 ntdll)
 add_pch(user32 include/user32.h)
 add_cd_file(TARGET user32 DESTINATION reactos/system32 FOR all)
index af205c5..49c34d7 100644 (file)
@@ -31,7 +31,6 @@
  *  Styles
  *  - BS_NOTIFY: is it complete?
  *  - BS_RIGHTBUTTON: same as BS_LEFTTEXT
- *  - BS_TYPEMASK
  *
  *  Messages
  *  - WM_CHAR: Checks a (manual or automatic) check box on '+' or '=', clears it on '-' key.
@@ -75,14 +74,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(button);
 #define UISTATE_GWL_OFFSET (HIMAGE_GWL_OFFSET+sizeof(HFONT))
 #define NB_EXTRA_BYTES    (UISTATE_GWL_OFFSET+sizeof(LONG))
 
-  /* Button state values */
-#define BUTTON_UNCHECKED       0x00
-#define BUTTON_CHECKED         0x01
-#define BUTTON_3STATE          0x02
-#define BUTTON_HIGHLIGHTED     0x04
-#define BUTTON_HASFOCUS        0x08
-#define BUTTON_NSTATES         0x0F
   /* undocumented flags */
+#define BUTTON_NSTATES         0x0F
 #define BUTTON_BTNPRESSED      0x40
 #define BUTTON_UNKNOWN2        0x20
 #define BUTTON_UNKNOWN3        0x10
@@ -103,22 +96,22 @@ static void UB_Paint( HWND hwnd, HDC hDC, UINT action );
 static void OB_Paint( HWND hwnd, HDC hDC, UINT action );
 static void BUTTON_CheckAutoRadioButton( HWND hwnd );
 
-#define MAX_BTN_TYPE  12
+#define MAX_BTN_TYPE  16
 
 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 */
+    BST_UNCHECKED,      /* BS_PUSHBUTTON */
+    BST_UNCHECKED,      /* BS_DEFPUSHBUTTON */
+    BST_CHECKED,        /* BS_CHECKBOX */
+    BST_CHECKED,        /* BS_AUTOCHECKBOX */
+    BST_CHECKED,        /* BS_RADIOBUTTON */
+    BST_INDETERMINATE,  /* BS_3STATE */
+    BST_INDETERMINATE,  /* BS_AUTO3STATE */
+    BST_UNCHECKED,      /* BS_GROUPBOX */
+    BST_UNCHECKED,      /* BS_USERBUTTON */
+    BST_CHECKED,        /* BS_AUTORADIOBUTTON */
+    BST_UNCHECKED,      /* BS_PUSHBOX */
+    BST_UNCHECKED       /* BS_OWNERDRAW */
 };
 
 typedef void (*pfPaint)( HWND hwnd, HDC hdc, UINT action );
@@ -135,7 +128,7 @@ static const pfPaint btnPaintFunc[MAX_BTN_TYPE] =
     GB_Paint,    /* BS_GROUPBOX */
     UB_Paint,    /* BS_USERBUTTON */
     CB_Paint,    /* BS_AUTORADIOBUTTON */
-    NULL,        /* Not defined */
+    NULL,        /* BS_PUSHBOX */
     OB_Paint     /* BS_OWNERDRAW */
 };
 
@@ -191,7 +184,7 @@ static inline void set_button_font( HWND hwnd, HFONT font )
 
 static inline UINT get_button_type( LONG window_style )
 {
-    return (window_style & 0x0f);
+    return (window_style & BS_TYPEMASK);
 }
 
 /* paint a button of any type */
@@ -214,15 +207,6 @@ static inline WCHAR *get_button_text( HWND hwnd )
     return buffer;
 }
 
-static void setup_clipping( HWND hwnd, HDC hdc )
-{
-    RECT rc;
-
-    GetClientRect( hwnd, &rc );
-    DPtoLP( hdc, (POINT *)&rc, 2 );
-    IntersectClipRect( hdc, rc.left, rc.top, rc.right, rc.bottom );
-}
-
 /* Retrieve the UI state for the control */
 static BOOL button_update_uistate(HWND hwnd, BOOL unicode)
 {
@@ -313,10 +297,15 @@ LRESULT WINAPI ButtonWndProc_common(HWND hWnd, UINT uMsg,
         /* XP turns a BS_USERBUTTON into BS_PUSHBUTTON */
         if (btn_type == BS_USERBUTTON )
         {
-            style = (style & ~0x0f) | BS_PUSHBUTTON;
+#ifdef __REACTOS__
+            style = (style & ~BS_TYPEMASK) | BS_PUSHBUTTON;
             SetWindowLongPtrW( hWnd, GWL_STYLE, style );
+#else
+            style = (style & ~BS_TYPEMASK) | BS_PUSHBUTTON;
+            WIN_SetStyle( hWnd, style, BS_TYPEMASK & ~style );
+#endif
         }
-        set_button_state( hWnd, BUTTON_UNCHECKED );
+        set_button_state( hWnd, BST_UNCHECKED );
         button_update_uistate( hWnd, unicode );
         return 0;
 
@@ -389,7 +378,7 @@ LRESULT WINAPI ButtonWndProc_common(HWND hWnd, UINT uMsg,
         if (!(state & BUTTON_BTNPRESSED)) break;
         state &= BUTTON_NSTATES;
         set_button_state( hWnd, state );
-        if (!(state & BUTTON_HIGHLIGHTED))
+        if (!(state & BST_PUSHED))
         {
             ReleaseCapture();
             break;
@@ -403,14 +392,14 @@ LRESULT WINAPI ButtonWndProc_common(HWND hWnd, UINT uMsg,
             switch(btn_type)
             {
             case BS_AUTOCHECKBOX:
-                SendMessageW( hWnd, BM_SETCHECK, !(state & BUTTON_CHECKED), 0 );
+                SendMessageW( hWnd, BM_SETCHECK, !(state & BST_CHECKED), 0 );
                 break;
             case BS_AUTORADIOBUTTON:
                 SendMessageW( hWnd, BM_SETCHECK, TRUE, 0 );
                 break;
             case BS_AUTO3STATE:
                 SendMessageW( hWnd, BM_SETCHECK,
-                                (state & BUTTON_3STATE) ? 0 : ((state & 3) + 1), 0 );
+                                (state & BST_INDETERMINATE) ? 0 : ((state & 3) + 1), 0 );
                 break;
             }
             BUTTON_NOTIFY_PARENT(hWnd, BN_CLICKED);
@@ -424,7 +413,7 @@ LRESULT WINAPI ButtonWndProc_common(HWND hWnd, UINT uMsg,
         {
             state &= BUTTON_NSTATES;
             set_button_state( hWnd, state );
-            if (state & BUTTON_HIGHLIGHTED) SendMessageW( hWnd, BM_SETSTATE, FALSE, 0 );
+            if (state & BST_PUSHED) SendMessageW( hWnd, BM_SETSTATE, FALSE, 0 );
         }
         break;
 
@@ -490,7 +479,7 @@ LRESULT WINAPI ButtonWndProc_common(HWND hWnd, UINT uMsg,
 
     case WM_SETFOCUS:
         TRACE("WM_SETFOCUS %p\n",hWnd);
-        set_button_state( hWnd, get_button_state(hWnd) | BUTTON_HASFOCUS );
+        set_button_state( hWnd, get_button_state(hWnd) | BST_FOCUS );
         paint_button( hWnd, btn_type, ODA_FOCUS );
         if (style & BS_NOTIFY)
             BUTTON_NOTIFY_PARENT(hWnd, BN_SETFOCUS);
@@ -499,7 +488,7 @@ LRESULT WINAPI ButtonWndProc_common(HWND hWnd, UINT uMsg,
     case WM_KILLFOCUS:
         TRACE("WM_KILLFOCUS %p\n",hWnd);
         state = get_button_state( hWnd );
-        set_button_state( hWnd, state & ~BUTTON_HASFOCUS );
+        set_button_state( hWnd, state & ~BST_FOCUS );
        paint_button( hWnd, btn_type, ODA_FOCUS );
 
         if ((state & BUTTON_BTNPRESSED) && GetCapture() == hWnd)
@@ -515,10 +504,11 @@ LRESULT WINAPI ButtonWndProc_common(HWND hWnd, UINT uMsg,
         break;
 
     case BM_SETSTYLE:
-        if ((wParam & 0x0f) >= MAX_BTN_TYPE) break;
-        btn_type = wParam & 0x0f;
-        style = (style & ~0x0f) | btn_type;
+        if ((wParam & BS_TYPEMASK) >= MAX_BTN_TYPE) break;
+        btn_type = wParam & BS_TYPEMASK;
+        style = (style & ~BS_TYPEMASK) | btn_type;
         SetWindowLongPtrW( hWnd, GWL_STYLE, style );
+        //WIN_SetStyle( hWnd, style, BS_TYPEMASK & ~style );
 
         /* Only redraw if lParam flag is set.*/
         if (lParam)
@@ -559,16 +549,21 @@ LRESULT WINAPI ButtonWndProc_common(HWND hWnd, UINT uMsg,
         state = get_button_state( hWnd );
         if ((btn_type == BS_RADIOBUTTON) || (btn_type == BS_AUTORADIOBUTTON))
         {
+#ifdef __REACTOS__
             if (wParam) style |= WS_TABSTOP;
             else style &= ~WS_TABSTOP;
             SetWindowLongPtrW( hWnd, GWL_STYLE, style );
+#else
+            if (wParam) WIN_SetStyle( hWnd, WS_TABSTOP, 0 );
+            else WIN_SetStyle( hWnd, 0, WS_TABSTOP );
+#endif
         }
         if ((state & 3) != wParam)
         {
             set_button_state( hWnd, (state & ~3) | wParam );
             paint_button( hWnd, btn_type, ODA_SELECT );
         }
-        if ((btn_type == BS_AUTORADIOBUTTON) && (wParam == BUTTON_CHECKED) && (style & WS_CHILD))
+        if ((btn_type == BS_AUTORADIOBUTTON) && (wParam == BST_CHECKED) && (style & WS_CHILD))
             BUTTON_CheckAutoRadioButton( hWnd );
         break;
 
@@ -578,15 +573,10 @@ LRESULT WINAPI ButtonWndProc_common(HWND hWnd, UINT uMsg,
     case BM_SETSTATE:
         state = get_button_state( hWnd );
         if (wParam)
-        {
-            if (state & BUTTON_HIGHLIGHTED) break;
-            set_button_state( hWnd, state | BUTTON_HIGHLIGHTED );
-        }
+            set_button_state( hWnd, state | BST_PUSHED );
         else
-        {
-            if (!(state & BUTTON_HIGHLIGHTED)) break;
-            set_button_state( hWnd, state & ~BUTTON_HIGHLIGHTED );
-        }
+            set_button_state( hWnd, state & ~BST_PUSHED );
+
         paint_button( hWnd, btn_type, ODA_SELECT );
         break;
 
@@ -642,7 +632,7 @@ static UINT BUTTON_BStoDT( DWORD style, DWORD ex_style )
 
    /* "Convert" pushlike buttons to pushbuttons */
    if (style & BS_PUSHLIKE)
-      style &= ~0x0F;
+      style &= ~BS_TYPEMASK;
 
    if (!(style & BS_MULTILINE))
       dtStyle |= DT_SINGLELINE;
@@ -821,7 +811,7 @@ static void BUTTON_DrawLabel(HWND hwnd, HDC hdc, UINT dtFlags, const RECT *rc)
     * I don't have Win31 on hand to verify that, so I leave it as is.
     */
 
-   if ((style & BS_PUSHLIKE) && (state & BUTTON_3STATE))
+   if ((style & BS_PUSHLIKE) && (state & BST_INDETERMINATE))
    {
       hbr = GetSysColorBrush(COLOR_GRAYTEXT);
       flags |= DSS_MONO;
@@ -873,8 +863,9 @@ static void PB_Paint( HWND hwnd, HDC hDC, UINT action )
     HFONT hFont;
     LONG state = get_button_state( hwnd );
     LONG style = GetWindowLongPtrW( hwnd, GWL_STYLE );
-    BOOL pushedState = (state & BUTTON_HIGHLIGHTED);
+    BOOL pushedState = (state & BST_PUSHED);
     HWND parent;
+    HRGN hrgn;
 
     GetClientRect( hwnd, &rc );
 
@@ -884,7 +875,7 @@ static void PB_Paint( HWND hwnd, HDC hDC, UINT action )
     if (!parent) parent = hwnd;
     GetControlColor( parent, hwnd, hDC, WM_CTLCOLORBTN);
 
-    setup_clipping( hwnd, hDC );
+    hrgn = set_control_clipping( hDC, &rc );
 #ifdef __REACTOS__
     hOldPen = SelectObject(hDC, GetStockObject(DC_PEN));
     SetDCPenColor(hDC, GetSysColor(COLOR_WINDOWFRAME));
@@ -916,7 +907,7 @@ static void PB_Paint( HWND hwnd, HDC hDC, UINT action )
            uState |= DFCS_PUSHED;
     }
 
-    if (state & (BUTTON_CHECKED | BUTTON_3STATE))
+    if (state & (BST_CHECKED | BST_INDETERMINATE))
         uState |= DFCS_CHECKED;
 
     DrawFrameControl( hDC, &rc, DFC_BUTTON, uState );
@@ -938,8 +929,7 @@ static void PB_Paint( HWND hwnd, HDC hDC, UINT action )
     SetTextColor( hDC, oldTxtColor );
 
 draw_focus:
-    if ((action == ODA_FOCUS) ||
-        ((action == ODA_DRAWENTIRE) && (state & BUTTON_HASFOCUS)))
+    if (action == ODA_FOCUS || (state & BST_FOCUS))
     {
         if (!(get_ui_state(hwnd) & UISF_HIDEFOCUS))
         {
@@ -952,6 +942,8 @@ draw_focus:
     SelectObject( hDC, hOldPen );
     SelectObject( hDC, hOldBrush );
     SetBkMode(hDC, oldBkMode);
+    SelectClipRgn( hDC, hrgn );
+    if (hrgn) DeleteObject( hrgn );
 }
 
 /**********************************************************************
@@ -968,6 +960,7 @@ static void CB_Paint( HWND hwnd, HDC hDC, UINT action )
     LONG state = get_button_state( hwnd );
     LONG style = GetWindowLongPtrW( hwnd, GWL_STYLE );
     HWND parent;
+    HRGN hrgn;
 
     if (style & BS_PUSHLIKE)
     {
@@ -983,7 +976,7 @@ static void CB_Paint( HWND hwnd, HDC hDC, UINT action )
     parent = GetParent(hwnd);
     if (!parent) parent = hwnd;
     hBrush = GetControlColor( parent, hwnd, hDC, WM_CTLCOLORSTATIC);
-    setup_clipping( hwnd, hDC );
+    hrgn = set_control_clipping( hDC, &client );
 
     if (style & BS_LEFTTEXT)
     {
@@ -1020,11 +1013,11 @@ static void CB_Paint( HWND hwnd, HDC hDC, UINT action )
 
        if ((get_button_type(style) == BS_RADIOBUTTON) ||
            (get_button_type(style) == BS_AUTORADIOBUTTON)) flags = DFCS_BUTTONRADIO;
-       else if (state & BUTTON_3STATE) flags = DFCS_BUTTON3STATE;
+       else if (state & BST_INDETERMINATE) flags = DFCS_BUTTON3STATE;
        else flags = DFCS_BUTTONCHECK;
 
-       if (state & (BUTTON_CHECKED | BUTTON_3STATE)) flags |= DFCS_CHECKED;
-       if (state & BUTTON_HIGHLIGHTED) flags |= DFCS_PUSHED;
+       if (state & (BST_CHECKED | BST_INDETERMINATE)) flags |= DFCS_CHECKED;
+       if (state & BST_PUSHED) flags |= DFCS_PUSHED;
 
        if (style & WS_DISABLED) flags |= DFCS_INACTIVE;
 
@@ -1067,8 +1060,7 @@ static void CB_Paint( HWND hwnd, HDC hDC, UINT action )
        BUTTON_DrawLabel(hwnd, hDC, dtFlags, &rtext);
 
     /* ... and focus */
-    if ((action == ODA_FOCUS) ||
-        ((action == ODA_DRAWENTIRE) && (state & BUTTON_HASFOCUS)))
+    if (action == ODA_FOCUS || (state & BST_FOCUS))
     {
         if (!(get_ui_state(hwnd) & UISF_HIDEFOCUS))
         {
@@ -1078,6 +1070,8 @@ static void CB_Paint( HWND hwnd, HDC hDC, UINT action )
             DrawFocusRect( hDC, &rtext );
         }
     }
+    SelectClipRgn( hDC, hrgn );
+    if (hrgn) DeleteObject( hrgn );
 }
 
 
@@ -1097,8 +1091,8 @@ static void BUTTON_CheckAutoRadioButton( HWND hwnd )
     {
         if (!sibling) break;
         if ((hwnd != sibling) &&
-            ((GetWindowLongPtrW( sibling, GWL_STYLE) & 0x0f) == BS_AUTORADIOBUTTON))
-            SendMessageW( sibling, BM_SETCHECK, BUTTON_UNCHECKED, 0 );
+            ((GetWindowLongPtrW( sibling, GWL_STYLE) & BS_TYPEMASK) == BS_AUTORADIOBUTTON))
+            SendMessageW( sibling, BM_SETCHECK, BST_UNCHECKED, 0 );
         sibling = GetNextDlgGroupItem( parent, sibling, FALSE );
     } while (sibling != start);
 }
@@ -1117,16 +1111,17 @@ static void GB_Paint( HWND hwnd, HDC hDC, UINT action )
     TEXTMETRICW tm;
     LONG style = GetWindowLongPtrW( hwnd, GWL_STYLE );
     HWND parent;
+    HRGN hrgn;
 
     if ((hFont = get_button_font( hwnd ))) SelectObject( hDC, hFont );
     /* GroupBox acts like static control, so it sends CTLCOLORSTATIC */
     parent = GetParent(hwnd);
     if (!parent) parent = hwnd;
     hbr = GetControlColor( parent, hwnd, hDC, WM_CTLCOLORSTATIC);
-    setup_clipping( hwnd, hDC );
-
+    
     GetClientRect( hwnd, &rc);
     rcFrame = rc;
+    hrgn = set_control_clipping( hDC, &rc );
 
     GetTextMetricsW (hDC, &tm);
     rcFrame.top += (tm.tmHeight / 2) - 1;
@@ -1135,20 +1130,22 @@ static void GB_Paint( HWND hwnd, HDC hDC, UINT action )
     InflateRect(&rc, -7, 1);
     dtFlags = BUTTON_CalcLabelRect(hwnd, hDC, &rc);
 
-    if (dtFlags == (UINT)-1L)
-       return;
-
-    /* Because buttons have CS_PARENTDC class style, there is a chance
-     * that label will be drawn out of client rect.
-     * But Windows doesn't clip label's rect, so do I.
-     */
+    if (dtFlags != (UINT)-1L)
+    {
+        /* Because buttons have CS_PARENTDC class style, there is a chance
+         * that label will be drawn out of client rect.
+         * But Windows doesn't clip label's rect, so do I.
+         */
 
-    /* There is 1-pixel margin at the left, right, and bottom */
-    rc.left--; rc.right++; rc.bottom++;
-    FillRect(hDC, &rc, hbr);
-    rc.left++; rc.right--; rc.bottom--;
+        /* There is 1-pixel margin at the left, right, and bottom */
+        rc.left--; rc.right++; rc.bottom++;
+        FillRect(hDC, &rc, hbr);
+        rc.left++; rc.right--; rc.bottom--;
 
-    BUTTON_DrawLabel(hwnd, hDC, dtFlags, &rc);
+        BUTTON_DrawLabel(hwnd, hDC, dtFlags, &rc);
+    }
+    SelectClipRgn( hDC, hrgn );
+    if (hrgn) DeleteObject( hrgn );
 }
 
 
@@ -1164,8 +1161,6 @@ static void UB_Paint( HWND hwnd, HDC hDC, UINT action )
     LONG state = get_button_state( hwnd );
     HWND parent;
 
-    if (action == ODA_SELECT) return;
-
     GetClientRect( hwnd, &rc);
 
     if ((hFont = get_button_font( hwnd ))) SelectObject( hDC, hFont );
@@ -1175,14 +1170,26 @@ static void UB_Paint( HWND hwnd, HDC hDC, UINT action )
     hBrush = GetControlColor( parent, hwnd, hDC, WM_CTLCOLORBTN);
 
     FillRect( hDC, &rc, hBrush );
-    if ((action == ODA_FOCUS) ||
-        ((action == ODA_DRAWENTIRE) && (state & BUTTON_HASFOCUS)))
+    if (action == ODA_FOCUS || (state & BST_FOCUS))
     {
         if (!(get_ui_state(hwnd) & UISF_HIDEFOCUS))
             DrawFocusRect( hDC, &rc );
     }
 
-    BUTTON_NOTIFY_PARENT( hwnd, BN_PAINT );
+    switch (action)
+    {
+    case ODA_FOCUS:
+        BUTTON_NOTIFY_PARENT( hwnd, (state & BST_FOCUS) ? BN_SETFOCUS : BN_KILLFOCUS );
+        break;
+
+    case ODA_SELECT:
+        BUTTON_NOTIFY_PARENT( hwnd, (state & BST_PUSHED) ? BN_HILITE : BN_UNHILITE );
+        break;
+
+    default:
+        BUTTON_NOTIFY_PARENT( hwnd, BN_PAINT );
+        break;
+    }
 }
 
 
@@ -1197,13 +1204,14 @@ static void OB_Paint( HWND hwnd, HDC hDC, UINT action )
     LONG_PTR id = GetWindowLongPtrW( hwnd, GWLP_ID );
     HWND parent;
     HFONT hFont, hPrevFont = 0;
+    HRGN hrgn;
 
     dis.CtlType    = ODT_BUTTON;
     dis.CtlID      = id;
     dis.itemID     = 0;
     dis.itemAction = action;
-    dis.itemState  = ((state & BUTTON_HASFOCUS) ? ODS_FOCUS : 0) |
-                     ((state & BUTTON_HIGHLIGHTED) ? ODS_SELECTED : 0) |
+    dis.itemState  = ((state & BST_FOCUS) ? ODS_FOCUS : 0) |
+                     ((state & BST_PUSHED) ? ODS_SELECTED : 0) |
                      (IsWindowEnabled(hwnd) ? 0: ODS_DISABLED);
     dis.hwndItem   = hwnd;
     dis.hDC        = hDC;
@@ -1215,8 +1223,10 @@ static void OB_Paint( HWND hwnd, HDC hDC, UINT action )
     if (!parent) parent = hwnd;
     GetControlColor( parent, hwnd, hDC, WM_CTLCOLORBTN);
 
-    setup_clipping( hwnd, hDC );
+    hrgn = set_control_clipping( hDC, &dis.rcItem );
 
     SendMessageW( GetParent(hwnd), WM_DRAWITEM, id, (LPARAM)&dis );
     if (hPrevFont) SelectObject(hDC, hPrevFont);
+    SelectClipRgn( hDC, hrgn );
+    if (hrgn) DeleteObject( hrgn );
 }
index 6d053f5..0edcbf7 100644 (file)
@@ -751,19 +751,6 @@ static void CBPaintText(
            !(lphc->wState & CBF_DROPPED) )
           itemState |= ODS_SELECTED | ODS_FOCUS;
 
-       /*
-       * Save the current clip region.
-       * To retrieve the clip region, we need to create one "dummy"
-       * clip region.
-       */
-       clipRegion = CreateRectRgnIndirect(&rectEdit);
-
-       if (GetClipRgn(hdc, clipRegion)!=1)
-       {
-        DeleteObject(clipRegion);
-        clipRegion=NULL;
-       }
-
        if (!IsWindowEnabled(lphc->self)) itemState |= ODS_DISABLED;
 
        dis.CtlType     = ODT_COMBOBOX;
@@ -774,22 +761,17 @@ static void CBPaintText(
        dis.itemState   = itemState;
        dis.hDC         = hdc;
        dis.rcItem      = rectEdit;
-       dis.itemData    = SendMessageW(lphc->hWndLBox, LB_GETITEMDATA,
-                                       (WPARAM)id, 0 );
+       dis.itemData    = SendMessageW(lphc->hWndLBox, LB_GETITEMDATA, id, 0 );
 
        /*
        * Clip the DC and have the parent draw the item.
        */
-       IntersectClipRect(hdc,
-                        rectEdit.left,  rectEdit.top,
-                        rectEdit.right, rectEdit.bottom);
+       clipRegion = set_control_clipping( hdc, &rectEdit );
 
        SendMessageW(lphc->owner, WM_DRAWITEM, ctlid, (LPARAM)&dis );
 
-       /*
-       * Reset the clipping region.
-       */
-       SelectClipRgn(hdc, clipRegion);
+       SelectClipRgn( hdc, clipRegion);
+       if (clipRegion) DeleteObject( clipRegion );
      }
      else
      {
@@ -2153,14 +2135,24 @@ LRESULT WINAPI ComboWndProc_common( HWND hwnd, UINT message,
                return SendMessageW(lphc->hWndLBox, LB_GETLOCALE, 0, 0);
        case CB_SETLOCALE:
                return SendMessageW(lphc->hWndLBox, LB_SETLOCALE, wParam, 0);
+        case CB_SETDROPPEDWIDTH:
+                if( (CB_GETTYPE(lphc) == CBS_SIMPLE) ||
+                    (INT)wParam >= 32768 )
+                    return CB_ERR;
+                /* new value must be higher than combobox width */
+                if((INT)wParam >= lphc->droppedRect.right - lphc->droppedRect.left)
+                    lphc->droppedWidth = wParam;
+                else if(wParam)
+                    lphc->droppedWidth = 0;
+
+                /* recalculate the combobox area */
+                CBCalcPlacement(hwnd, lphc, &lphc->textRect, &lphc->buttonRect, &lphc->droppedRect );
+
+                /* fall through */
        case CB_GETDROPPEDWIDTH:
                if( lphc->droppedWidth )
                     return  lphc->droppedWidth;
                return  lphc->droppedRect.right - lphc->droppedRect.left;
-       case CB_SETDROPPEDWIDTH:
-               if( (CB_GETTYPE(lphc) != CBS_SIMPLE) &&
-                   (INT)wParam < 32768 ) lphc->droppedWidth = (INT)wParam;
-               return  CB_ERR;
        case CB_GETDROPPEDCONTROLRECT:
                if( lParam ) CBGetDroppedControlRect(lphc, (LPRECT)lParam );
                return  CB_OKAY;
@@ -2233,7 +2225,7 @@ LRESULT WINAPI ComboWndProc_common( HWND hwnd, UINT message,
        case CB_LIMITTEXT:
                if( lphc->wState & CBF_EDIT )
                        return SendMessageW(lphc->hWndEdit, EM_LIMITTEXT, wParam, lParam);
-                break; // ReactOS!!! removed at revision 38715
+                return  TRUE;
 
     case WM_UPDATEUISTATE:
         if (unicode)
index 3fd65ef..8401b22 100644 (file)
@@ -85,6 +85,7 @@ typedef struct tagLINEDEF {
        LINE_END ending;
        INT width;                      /* width of the line in pixels */
        INT index;                      /* line index into the buffer */
+       SCRIPT_STRING_ANALYSIS ssa;     /* Uniscribe Data */
        struct tagLINEDEF *next;
 } LINEDEF;
 
@@ -141,6 +142,11 @@ typedef struct
         */
        UINT composition_len;   /* length of composition, 0 == no composition */
        int composition_start;  /* the character position for the composition */
+       /*
+        * Uniscribe Data
+        */
+       SCRIPT_LOGATTR *logAttr;
+       SCRIPT_STRING_ANALYSIS ssa; /* Uniscribe Data for single line controls */
 } EDITSTATE;
 
 
@@ -158,6 +164,7 @@ typedef struct
        } while(0)
 
 static const WCHAR empty_stringW[] = {0};
+static LRESULT EDIT_EM_PosFromChar(EDITSTATE *es, INT index, BOOL after_wrap);
 
 /*********************************************************************
  *
@@ -233,6 +240,14 @@ static HBRUSH EDIT_NotifyCtlColor(EDITSTATE *es, HDC hdc)
 }
 
 
+static inline UINT get_text_length(EDITSTATE *es)
+{
+    if(es->text_length == (UINT)-1)
+        es->text_length = strlenW(es->text);
+    return es->text_length;
+}
+
+
 /*********************************************************************
  *
  *     EDIT_WordBreakProc
@@ -242,61 +257,51 @@ static HBRUSH EDIT_NotifyCtlColor(EDITSTATE *es, HDC hdc)
  *             allows to be called without linebreaks between s[0] up to
  *             s[count - 1].  Remember it is only called
  *             internally, so we can decide this for ourselves.
+ *             Additional we will always be breaking the full string.
  *
  */
-static INT EDIT_WordBreakProc(LPWSTR s, INT index, INT count, INT action)
+static INT EDIT_WordBreakProc(EDITSTATE *es, LPWSTR s, INT index, INT count, INT action)
 {
-       INT ret = 0;
+    INT ret = 0;
 
-       TRACE("s=%p, index=%d, count=%d, action=%d\n", s, index, count, action);
+    TRACE("s=%p, index=%d, count=%d, action=%d\n", s, index, count, action);
 
-       if(!s) return 0;
+    if(!s) return 0;
 
-       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:
-               ERR("unknown action code, please report !\n");
-               break;
-       }
-       return ret;
+    if (!es->logAttr)
+    {
+        SCRIPT_ANALYSIS psa;
+
+        memset(&psa,0,sizeof(SCRIPT_ANALYSIS));
+        psa.eScript = SCRIPT_UNDEFINED;
+
+        es->logAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(SCRIPT_LOGATTR) * get_text_length(es));
+        ScriptBreak(es->text, get_text_length(es), &psa, es->logAttr);
+    }
+
+    switch (action) {
+    case WB_LEFT:
+        if (index)
+            index--;
+        while (index && !es->logAttr[index].fSoftBreak)
+            index--;
+        ret = index;
+        break;
+    case WB_RIGHT:
+        if (!count)
+            break;
+        while (s[index] && index < count && !es->logAttr[index].fSoftBreak)
+            index++;
+        ret = index;
+        break;
+    case WB_ISDELIMITER:
+        ret = es->logAttr[index].fWhiteSpace;
+        break;
+    default:
+        ERR("unknown action code, please report !\n");
+        break;
+    }
+    return ret;
 }
 
 
@@ -344,11 +349,110 @@ static INT EDIT_CallWordBreakProc(EDITSTATE *es, INT start, INT index, INT count
            }
         }
        else
-            ret = EDIT_WordBreakProc(es->text + start, index, count, action);
+            ret = EDIT_WordBreakProc(es, es->text, index+start, count+start, action) - start;
 
        return ret;
 }
 
+static inline void EDIT_InvalidateUniscribeData_linedef(LINEDEF *line_def)
+{
+       if (line_def->ssa)
+       {
+               ScriptStringFree(&line_def->ssa);
+               line_def->ssa = NULL;
+       }
+}
+
+static inline void EDIT_InvalidateUniscribeData(EDITSTATE *es)
+{
+       LINEDEF *line_def = es->first_line_def;
+       while (line_def)
+       {
+               EDIT_InvalidateUniscribeData_linedef(line_def);
+               line_def = line_def->next;
+       }
+       if (es->ssa)
+       {
+               ScriptStringFree(&es->ssa);
+               es->ssa = NULL;
+       }
+}
+
+static SCRIPT_STRING_ANALYSIS EDIT_UpdateUniscribeData_linedef(EDITSTATE *es, HDC dc, LINEDEF *line_def)
+{
+       if (!line_def)
+               return NULL;
+
+       if (line_def->net_length && !line_def->ssa)
+       {
+               int index = line_def->index;
+               HFONT old_font = NULL;
+               HDC udc = dc;
+               SCRIPT_TABDEF tabdef;
+
+               if (!udc)
+                       udc = GetDC(es->hwndSelf);
+               if (es->font)
+                       old_font = SelectObject(udc, es->font);
+
+               tabdef.cTabStops = es->tabs_count;
+               tabdef.iScale = 0;
+               tabdef.pTabStops = es->tabs;
+               tabdef.iTabOrigin = 0;
+
+               ScriptStringAnalyse(udc, &es->text[index], line_def->net_length, (1.5*line_def->net_length+16), -1, SSA_LINK|SSA_FALLBACK|SSA_GLYPHS|SSA_TAB, -1, NULL, NULL, NULL, &tabdef, NULL, &line_def->ssa);
+
+               if (es->font)
+                       SelectObject(udc, old_font);
+               if (udc != dc)
+                       ReleaseDC(es->hwndSelf, udc);
+       }
+
+       return line_def->ssa;
+}
+
+static SCRIPT_STRING_ANALYSIS EDIT_UpdateUniscribeData(EDITSTATE *es, HDC dc, INT line)
+{
+       LINEDEF *line_def;
+
+       if (!(es->style & ES_MULTILINE))
+       {
+               if (!es->ssa)
+               {
+                       INT length = get_text_length(es);
+                       HFONT old_font = NULL;
+                       HDC udc = dc;
+
+                       if (!udc)
+                               udc = GetDC(es->hwndSelf);
+                       if (es->font)
+                               old_font = SelectObject(udc, es->font);
+
+                       if (es->style & ES_PASSWORD)
+                               ScriptStringAnalyse(udc, &es->password_char, length, (1.5*length+16), -1, SSA_LINK|SSA_FALLBACK|SSA_GLYPHS|SSA_PASSWORD, -1, NULL, NULL, NULL, NULL, NULL, &es->ssa);
+                       else
+                               ScriptStringAnalyse(udc, es->text, length, (1.5*length+16), -1, SSA_LINK|SSA_FALLBACK|SSA_GLYPHS, -1, NULL, NULL, NULL, NULL, NULL, &es->ssa);
+
+                       if (es->font)
+                               SelectObject(udc, old_font);
+                       if (udc != dc)
+                               ReleaseDC(es->hwndSelf, udc);
+               }
+               return es->ssa;
+       }
+       else
+       {
+               line_def = es->first_line_def;
+               while (line_def && line)
+               {
+                       line_def = line_def->next;
+                       line--;
+               }
+
+               return EDIT_UpdateUniscribeData_linedef(es,dc,line_def);
+       }
+}
+
 /*********************************************************************
  *
  *     EDIT_BuildLineDefs_ML
@@ -360,8 +464,6 @@ static INT EDIT_CallWordBreakProc(EDITSTATE *es, INT start, INT index, INT count
  */
 static void EDIT_BuildLineDefs_ML(EDITSTATE *es, INT istart, INT iend, INT delta, HRGN hrgn)
 {
-       HDC dc;
-       HFONT old_font = 0;
        LPWSTR current_position, cp;
        INT fw;
        LINEDEF *current_line;
@@ -375,10 +477,6 @@ static void EDIT_BuildLineDefs_ML(EDITSTATE *es, INT istart, INT iend, INT delta
        if (istart == iend && delta == 0)
                return;
 
-       dc = GetDC(es->hwndSelf);
-       if (es->font)
-               old_font = SelectObject(dc, es->font);
-
        previous_line = NULL;
        current_line = es->first_line_def;
 
@@ -397,7 +495,6 @@ static void EDIT_BuildLineDefs_ML(EDITSTATE *es, INT istart, INT iend, INT delta
        if (!current_line) /* Error occurred start is not inside previous buffer */
        {
                FIXME(" modification occurred outside buffer\n");
-               ReleaseDC(es->hwndSelf, dc);
                return;
        }
 
@@ -423,9 +520,9 @@ static void EDIT_BuildLineDefs_ML(EDITSTATE *es, INT istart, INT iend, INT delta
                        {
                                /* The buffer has been expanded, create a new line and
                                   insert it into the link list */
-                               LINEDEF *new_line = HeapAlloc(GetProcessHeap(), 0, sizeof(LINEDEF));
-                if (new_line == NULL) // reactos r33509
-                    break; // reactos r33509
+                               LINEDEF *new_line = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LINEDEF));
+                               if (new_line == NULL) // reactos r33509
+                                  break; // reactos r33509
                                new_line->next = previous_line->next;
                                previous_line->next = new_line;
                                current_line = new_line;
@@ -475,33 +572,69 @@ static void EDIT_BuildLineDefs_ML(EDITSTATE *es, INT istart, INT iend, INT delta
                        current_line->net_length = cp - current_position;
                }
 
-               /* Calculate line width */
-               current_line->width = (INT)LOWORD(GetTabbedTextExtentW(dc,
-                                       current_position, current_line->net_length,
-                                       es->tabs_count, es->tabs));
+               if (current_line->net_length)
+               {
+                       const SIZE *sz;
+                       EDIT_InvalidateUniscribeData_linedef(current_line);
+                       EDIT_UpdateUniscribeData_linedef(es, NULL, current_line);
+                       sz = ScriptString_pSize(current_line->ssa);
+                       /* Calculate line width */
+                       current_line->width = sz->cx;
+               }
+               else current_line->width = 0;
 
                /* FIXME: check here for lines that are too wide even in AUTOHSCROLL (> 32767 ???) */
+
+/* Line breaks just look back from the end and find the next break and try that. */
+
                if (!(es->style & ES_AUTOHSCROLL)) {
-                  if (current_line->width > fw) {
-                       INT next = 0;
-                       INT prev;
+                  if (current_line->width > fw && fw > es->char_width) {
+
+                       INT prev, next;
+                       int w;
+                       const SIZE *sz;
+                       float d;
+
+                       prev = current_line->net_length - 1;
+                       w = current_line->net_length;
+                       d = (float)current_line->width/(float)fw;
+                       if (d > 1.2) d -= 0.2;
+                       next = prev/d;
+                       if (next >= prev) next = prev-1;
                        do {
-                               prev = next;
-                               next = EDIT_CallWordBreakProc(es, current_position - es->text,
-                                               prev + 1, current_line->net_length, WB_RIGHT);
-                               current_line->width = (INT)LOWORD(GetTabbedTextExtentW(dc,
-                                                       current_position, next, es->tabs_count, es->tabs));
-                       } while (current_line->width <= fw);
-                       if (!prev) { /* Didn't find a line break so force a break */
-                               next = 0;
+                               prev = EDIT_CallWordBreakProc(es, current_position - es->text,
+                                               next, current_line->net_length, WB_LEFT);
+                               current_line->net_length = prev;
+                               EDIT_InvalidateUniscribeData_linedef(current_line);
+                               EDIT_UpdateUniscribeData_linedef(es, NULL, current_line);
+                               sz = ScriptString_pSize(current_line->ssa);
+                               if (sz)
+                                       current_line->width = sz->cx;
+                               else
+                                       prev = 0;
+                               next = prev - 1;
+                       } while (prev && current_line->width > fw);
+                       current_line->net_length = w;
+
+                       if (prev == 0) { /* Didn't find a line break so force a break */
+                               INT *piDx;
+                               const INT *count;
+
+                               EDIT_InvalidateUniscribeData_linedef(current_line);
+                               EDIT_UpdateUniscribeData_linedef(es, NULL, current_line);
+
+                               count = ScriptString_pcOutChars(current_line->ssa);
+                               piDx = HeapAlloc(GetProcessHeap(),0,sizeof(INT) * (*count));
+                               ScriptStringGetLogicalWidths(current_line->ssa,piDx);
+
+                               prev = current_line->net_length-1;
                                do {
-                                       prev = next;
-                                       next++;
-                                       current_line->width = (INT)LOWORD(GetTabbedTextExtentW(dc,
-                                                               current_position, next, es->tabs_count, es->tabs));
-                               } while (current_line->width <= fw);
-                               if (!prev)
+                                       current_line->width -= piDx[prev];
+                                       prev--;
+                               } while ( prev > 0 && current_line->width > fw);
+                               if (prev<=0)
                                        prev = 1;
+                               HeapFree(GetProcessHeap(),0,piDx);
                        }
 
                        /* If the first line we are calculating, wrapped before istart, we must
@@ -522,8 +655,14 @@ static void EDIT_BuildLineDefs_ML(EDITSTATE *es, INT istart, INT iend, INT delta
 
                        current_line->net_length = prev;
                        current_line->ending = END_WRAP;
-                       current_line->width = (INT)LOWORD(GetTabbedTextExtentW(dc, current_position,
-                                       current_line->net_length, es->tabs_count, es->tabs));
+
+                       if (current_line->net_length > 0)
+                       {
+                               EDIT_UpdateUniscribeData_linedef(es, NULL, current_line);
+                               sz = ScriptString_pSize(current_line->ssa);
+                               current_line->width = sz->cx;
+                       }
+                       else current_line->width = 0;
                    }
                    else if (current_line == start_line &&
                              current_line->index != nstart_index &&
@@ -570,6 +709,7 @@ static void EDIT_BuildLineDefs_ML(EDITSTATE *es, INT istart, INT iend, INT delta
                while (current_line)
                {
                        pnext = current_line->next;
+                       EDIT_InvalidateUniscribeData_linedef(current_line);
                        HeapFree(GetProcessHeap(), 0, current_line);
                        current_line = pnext;
                        es->line_count--;
@@ -599,9 +739,7 @@ static void EDIT_BuildLineDefs_ML(EDITSTATE *es, INT istart, INT iend, INT delta
                if ((es->style & ES_CENTER) || (es->style & ES_RIGHT))
                        rc.left = es->format_rect.left;
                else
-                       rc.left = es->format_rect.left + (INT)LOWORD(GetTabbedTextExtentW(dc,
-                                       es->text + nstart_index, istart - nstart_index,
-                                       es->tabs_count, es->tabs)) - es->x_offset; /* Adjust for horz scroll */
+            rc.left = LOWORD(EDIT_EM_PosFromChar(es, nstart_index, FALSE));
                rc.right = es->format_rect.right;
                SetRectRgn(hrgn, rc.left, rc.top, rc.right, rc.bottom);
 
@@ -624,40 +762,6 @@ static void EDIT_BuildLineDefs_ML(EDITSTATE *es, INT istart, INT iend, INT delta
                CombineRgn(hrgn, hrgn, tmphrgn, RGN_OR);
                DeleteObject(tmphrgn);
        }
-
-       if (es->font)
-               SelectObject(dc, old_font);
-
-       ReleaseDC(es->hwndSelf, dc);
-}
-
-
-static inline UINT get_text_length(EDITSTATE *es)
-{
-    if(es->text_length == (UINT)-1)
-        es->text_length = strlenW(es->text);
-    return es->text_length;
-}
-
-/*********************************************************************
- *
- *     EDIT_GetPasswordPointer_SL
- *
- *     note: caller should free the (optionally) allocated buffer
- *
- */
-static LPWSTR EDIT_GetPasswordPointer_SL(EDITSTATE *es)
-{
-       if (es->style & ES_PASSWORD) {
-               INT len = get_text_length(es);
-               LPWSTR text = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
-        if (text == NULL)
-            return NULL;
-               text[len] = '\0';
-               while(len) text[--len] = es->password_char;
-               return text;
-       } else
-               return es->text;
 }
 
 
@@ -668,27 +772,15 @@ static LPWSTR EDIT_GetPasswordPointer_SL(EDITSTATE *es)
  */
 static void EDIT_CalcLineWidth_SL(EDITSTATE *es)
 {
-       SIZE size;
-       LPWSTR text;
-       HDC dc;
-       HFONT old_font = 0;
-
-       text = EDIT_GetPasswordPointer_SL(es);
-
-       dc = GetDC(es->hwndSelf);
-       if (es->font)
-               old_font = SelectObject(dc, es->font);
-
-       GetTextExtentPoint32W(dc, text, strlenW(text), &size);
-
-       if (es->font)
-               SelectObject(dc, old_font);
-       ReleaseDC(es->hwndSelf, dc);
-
-       if (es->style & ES_PASSWORD)
-               HeapFree(GetProcessHeap(), 0, text);
-
-       es->text_width = size.cx;
+       EDIT_UpdateUniscribeData(es, NULL, 0);
+       if (es->ssa)
+       {
+               const SIZE *size;
+               size = ScriptString_pSize(es->ssa);
+               es->text_width = size->cx;
+       }
+       else
+               es->text_width = 0;
 }
 
 /*********************************************************************
@@ -704,20 +796,19 @@ static void EDIT_CalcLineWidth_SL(EDITSTATE *es)
 static INT EDIT_CharFromPos(EDITSTATE *es, INT x, INT y, LPBOOL after_wrap)
 {
        INT index;
-       HDC dc;
-       HFONT old_font = 0;
-       INT x_high = 0, x_low = 0;
 
        if (es->style & ES_MULTILINE) {
+               int trailing;
                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;
+               EDIT_UpdateUniscribeData(es, NULL, line);
                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 (es->style & ES_RIGHT)
                        x -= (es->format_rect.right - es->format_rect.left) - line_def->width;
@@ -728,39 +819,21 @@ static INT EDIT_CharFromPos(EDITSTATE *es, INT x, INT y, LPBOOL after_wrap)
                                *after_wrap = (line_def->ending == END_WRAP);
                        return line_index + line_def->net_length;
                }
-               if (x <= 0) {
+               if (x <= 0 || !line_def->ssa) {
                        if (after_wrap)
                                *after_wrap = FALSE;
                        return line_index;
                }
-               dc = GetDC(es->hwndSelf);
-               if (es->font)
-                       old_font = SelectObject(dc, es->font);
-                    low = line_index;
-                    high = line_index + line_def->net_length + 1;
-                    while (low < high - 1)
-                    {
-                        INT mid = (low + high) / 2;
-                        INT x_now = LOWORD(GetTabbedTextExtentW(dc, es->text + line_index, mid - line_index, es->tabs_count, es->tabs));
-                        if (x_now > x) {
-                            high = mid;
-                            x_high = x_now;
-                        } else {
-                            low = mid;
-                            x_low = x_now;
-                        }
-                    }
-                    if (abs(x_high - x) + 1 <= abs(x_low - x))
-                        index = high;
-                    else
-                        index = low;
 
+               ScriptStringXtoCP(line_def->ssa, x , &index, &trailing);
+               if (trailing) index++;
+               index += line_index;
                if (after_wrap)
                        *after_wrap = ((index == line_index + line_def->net_length) &&
                                                        (line_def->ending == END_WRAP));
        } else {
-               LPWSTR text;
-               SIZE size;
+               INT xoff = 0;
+               INT trailing;
                if (after_wrap)
                        *after_wrap = FALSE;
                x -= es->format_rect.left;
@@ -776,60 +849,55 @@ static INT EDIT_CharFromPos(EDITSTATE *es, INT x, INT y, LPBOOL after_wrap)
                                x -= indent / 2;
                }
 
-               text = EDIT_GetPasswordPointer_SL(es);
-               dc = GetDC(es->hwndSelf);
-               if (es->font)
-                       old_font = SelectObject(dc, es->font);
+               EDIT_UpdateUniscribeData(es, NULL, 0);
+               if (es->x_offset)
+               {
+                       if (es->ssa)
+                       {
+                               if (es->x_offset>= get_text_length(es))
+                               {
+                                       const SIZE *size;
+                                       size = ScriptString_pSize(es->ssa);
+                                       xoff = size->cx;
+                               }
+                               ScriptStringCPtoX(es->ssa, es->x_offset, FALSE, &xoff);
+                       }
+                       else
+                               xoff = 0;
+               }
                if (x < 0)
-                {
-                    INT low = 0;
-                    INT high = es->x_offset;
-                    while (low < high - 1)
-                    {
-                        INT mid = (low + high) / 2;
-                        GetTextExtentPoint32W( dc, text + mid,
-                                               es->x_offset - mid, &size );
-                        if (size.cx > -x) {
-                            low = mid;
-                            x_low = size.cx;
-                        } else {
-                            high = mid;
-                            x_high = size.cx;
-                        }
-                    }
-                    if (abs(x_high + x) <= abs(x_low + x) + 1)
-                        index = high;
-                    else
-                        index = low;
+               {
+                       if (x + xoff > 0 || !es->ssa)
+                       {
+                               ScriptStringXtoCP(es->ssa, x+xoff, &index, &trailing);
+                               if (trailing) index++;
+                       }
+                       else
+                               index = 0;
                }
-                else
-                {
-                    INT low = es->x_offset;
-                    INT high = get_text_length(es) + 1;
-                    while (low < high - 1)
-                    {
-                        INT mid = (low + high) / 2;
-                        GetTextExtentPoint32W( dc, text + es->x_offset,
-                                               mid - es->x_offset, &size );
-                        if (size.cx > x) {
-                               high = mid;
-                               x_high = size.cx;
-                        } else {
-                               low = mid;
-                               x_low = size.cx;
-                       }
-                    }
-                   if (abs(x_high - x) <= abs(x_low - x) + 1)
-                       index = high;
-                   else
-                       index = low;
+               else
+               {
+                       if (x)
+                       {
+                               const SIZE *size = NULL;
+                               if (es->ssa)
+                                       size = ScriptString_pSize(es->ssa);
+                               if (!size)
+                                       index = 0;
+                               else if (x > size->cx)
+                                       index = get_text_length(es);
+                               else if (es->ssa)
+                               {
+                                       ScriptStringXtoCP(es->ssa, x+xoff, &index, &trailing);
+                                       if (trailing) index++;
+                               }
+                               else
+                                        index = 0;
+                       }
+                       else
+                               index = es->x_offset;
                }
-               if (es->style & ES_PASSWORD)
-                       HeapFree(GetProcessHeap(), 0, text);
        }
-       if (es->font)
-               SelectObject(dc, old_font);
-       ReleaseDC(es->hwndSelf, dc);
        return index;
 }
 
@@ -959,22 +1027,17 @@ static LRESULT EDIT_EM_PosFromChar(EDITSTATE *es, INT index, BOOL after_wrap)
        INT len = get_text_length(es);
        INT l;
        INT li;
-       INT x;
+       INT x = 0;
        INT y = 0;
        INT w;
        INT lw = 0;
-       INT ll = 0;
-       HDC dc;
-       HFONT old_font = 0;
-       SIZE size;
        LINEDEF *line_def;
 
        index = min(index, len);
-       dc = GetDC(es->hwndSelf);
-       if (es->font)
-               old_font = SelectObject(dc, es->font);
        if (es->style & ES_MULTILINE) {
                l = EDIT_EM_LineFromChar(es, index);
+               EDIT_UpdateUniscribeData(es, NULL, l);
+
                y = (l - es->y_offset) * es->line_height;
                li = EDIT_EM_LineIndex(es, l);
                if (after_wrap && (li == index) && l) {
@@ -995,38 +1058,63 @@ static LRESULT EDIT_EM_PosFromChar(EDITSTATE *es, INT index, BOOL after_wrap)
                while (line_def->index != li)
                        line_def = line_def->next;
 
-               ll = line_def->net_length;
-               lw = line_def->width;
+                if (!line_def->ssa)
+                    return 0;
 
+               lw = line_def->width;
                w = es->format_rect.right - es->format_rect.left;
+               ScriptStringCPtoX(line_def->ssa, (index - 1) - li, TRUE, &x);
+               x -= es->x_offset;
+
                if (es->style & ES_RIGHT)
-               {
-                       x = LOWORD(GetTabbedTextExtentW(dc, es->text + li + (index - li), ll - (index - li),
-                               es->tabs_count, es->tabs)) - es->x_offset;
-                       x = w - x;
-               }
+                       x = w - (lw - x);
                else if (es->style & ES_CENTER)
-               {
-                       x = LOWORD(GetTabbedTextExtentW(dc, es->text + li, index - li,
-                               es->tabs_count, es->tabs)) - es->x_offset;
                        x += (w - lw) / 2;
+       } else {
+               INT xoff = 0;
+               INT xi = 0;
+               EDIT_UpdateUniscribeData(es, NULL, 0);
+               if (es->x_offset)
+               {
+                       if (es->ssa)
+                       {
+                               if (es->x_offset >= get_text_length(es))
+                               {
+                                       if (es->ssa)
+                                       {
+                                               const SIZE *size;
+                                               size = ScriptString_pSize(es->ssa);
+                                               xoff = size->cx;
+                                       }
+                                       else
+                                               xoff = 0;
+                               }
+                               ScriptStringCPtoX(es->ssa, es->x_offset, FALSE, &xoff);
+                       }
+                       else
+                               xoff = 0;
                }
-               else /* ES_LEFT */
+               if (index)
                {
-                   x = LOWORD(GetTabbedTextExtentW(dc, es->text + li, index - li,
-                               es->tabs_count, es->tabs)) - es->x_offset;
+                       if (index >= get_text_length(es))
+                       {
+                               if (es->ssa)
+                               {
+                                       const SIZE *size;
+                                       size = ScriptString_pSize(es->ssa);
+                                       xi = size->cx;
+                               }
+                               else
+                                       xi = 0;
+                       }
+                       else if (es->ssa)
+                               ScriptStringCPtoX(es->ssa, index, FALSE, &xi);
+                        else
+                                xi = 0;
                }
-       } else {
-               LPWSTR text = EDIT_GetPasswordPointer_SL(es);
-               if (index < es->x_offset) {
-                       GetTextExtentPoint32W(dc, text + index,
-                                       es->x_offset - index, &size);
-                       x = -size.cx;
-               } else {
-                       GetTextExtentPoint32W(dc, text + es->x_offset,
-                                       index - es->x_offset, &size);
-                        x = size.cx;
+               x = xi - xoff;
 
+               if (index >= es->x_offset) {
                        if (!es->x_offset && (es->style & (ES_RIGHT | ES_CENTER)))
                        {
                                w = es->format_rect.right - es->format_rect.left;
@@ -1040,14 +1128,9 @@ static LRESULT EDIT_EM_PosFromChar(EDITSTATE *es, INT index, BOOL after_wrap)
                        }
                }
                y = 0;
-               if (es->style & ES_PASSWORD)
-                       HeapFree(GetProcessHeap(), 0, text);
        }
        x += es->format_rect.left;
        y += es->format_rect.top;
-       if (es->font)
-               SelectObject(dc, old_font);
-       ReleaseDC(es->hwndSelf, dc);
        return MAKELONG((INT16)x, (INT16)y);
 }
 
@@ -1063,20 +1146,27 @@ static LRESULT EDIT_EM_PosFromChar(EDITSTATE *es, INT index, BOOL after_wrap)
 static void EDIT_GetLineRect(EDITSTATE *es, INT line, INT scol, INT ecol, LPRECT rc)
 {
        INT line_index =  EDIT_EM_LineIndex(es, line);
+        INT pt1, pt2;
 
        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 : (short)LOWORD(EDIT_EM_PosFromChar(es, line_index + scol, TRUE));
-       rc->right = (ecol == -1) ? es->format_rect.right : (short)LOWORD(EDIT_EM_PosFromChar(es, line_index + ecol, TRUE));
+        pt1 = (scol == 0) ? es->format_rect.left : (short)LOWORD(EDIT_EM_PosFromChar(es, line_index + scol, TRUE));
+        pt2 = (ecol == -1) ? es->format_rect.right : (short)LOWORD(EDIT_EM_PosFromChar(es, line_index + ecol, TRUE));
+        rc->right = max(pt1 , pt2);
+        rc->left = min(pt1, pt2);
 }
 
 
 static inline void text_buffer_changed(EDITSTATE *es)
 {
     es->text_length = (UINT)-1;
+
+    HeapFree( GetProcessHeap(), 0, es->logAttr );
+    es->logAttr = NULL;
+    EDIT_InvalidateUniscribeData(es);
 }
 
 /*********************************************************************
@@ -2035,7 +2125,7 @@ static INT EDIT_PaintText(EDITSTATE *es, HDC dc, INT x, INT y, INT line, INT col
                ret = (INT)LOWORD(TabbedTextOutW(dc, x, y, es->text + li + col, count,
                                        es->tabs_count, es->tabs, es->format_rect.left - es->x_offset));
        } else {
-               LPWSTR text = EDIT_GetPasswordPointer_SL(es);
+               LPWSTR text = es->text;
                TextOutW(dc, x, y, text + li + col, count);
                GetTextExtentPoint32W(dc, text + li + col, count, &size);
                ret = size.cx;
@@ -2068,13 +2158,14 @@ static INT EDIT_PaintText(EDITSTATE *es, HDC dc, INT x, INT y, INT line, INT col
  */
 static void EDIT_PaintLine(EDITSTATE *es, HDC dc, INT line, BOOL rev)
 {
-       INT s = es->selection_start;
-       INT e = es->selection_end;
-       INT li;
-       INT ll;
+       INT s = 0;
+       INT e = 0;
+       INT li = 0;
+       INT ll = 0;
        INT x;
        INT y;
        LRESULT pos;
+       SCRIPT_STRING_ANALYSIS ssa;
 
        if (es->style & ES_MULTILINE) {
                INT vlc = get_vertical_line_count(es);
@@ -2086,16 +2177,49 @@ static void EDIT_PaintLine(EDITSTATE *es, HDC dc, INT line, BOOL rev)
 
        TRACE("line=%d\n", line);
 
+        ssa = EDIT_UpdateUniscribeData(es, dc, line);
        pos = EDIT_EM_PosFromChar(es, EDIT_EM_LineIndex(es, line), FALSE);
        x = (short)LOWORD(pos);
        y = (short)HIWORD(pos);
-       li = EDIT_EM_LineIndex(es, line);
-       ll = EDIT_EM_LineLength(es, li);
-       s = min(es->selection_start, es->selection_end);
-       e = max(es->selection_start, es->selection_end);
-       s = min(li + ll, max(li, s));
-       e = min(li + ll, max(li, e));
-       if (rev && (s != e) &&
+
+       if (es->style & ES_MULTILINE)
+       {
+               int line_idx = line;
+               x =  -es->x_offset;
+               if (es->style & ES_RIGHT || es->style & ES_CENTER)
+               {
+                       LINEDEF *line_def = es->first_line_def;
+                       int w, lw;
+
+                       while (line_def && line_idx)
+                       {
+                               line_def = line_def->next;
+                               line_idx--;
+                       }
+                       w = es->format_rect.right - es->format_rect.left;
+                       lw = line_def->width;
+
+                       if (es->style & ES_RIGHT)
+                               x = w - (lw - x);
+                       else if (es->style & ES_CENTER)
+                               x += (w - lw) / 2;
+               }
+               x += es->format_rect.left;
+       }
+
+       if (rev)
+       {
+               li = EDIT_EM_LineIndex(es, line);
+               ll = EDIT_EM_LineLength(es, li);
+               s = min(es->selection_start, es->selection_end);
+               e = max(es->selection_start, es->selection_end);
+               s = min(li + ll, max(li, s));
+               e = min(li + ll, max(li, e));
+       }
+
+       if (ssa)
+               ScriptStringOut(ssa, x, y, 0, &es->format_rect, s - li, e - li, FALSE);
+       else if (rev && (s != e) &&
                        ((es->flags & EF_FOCUSED) || (es->style & ES_NOHIDESEL))) {
                x += EDIT_PaintText(es, dc, x, y, line, 0, s - li, FALSE);
                x += EDIT_PaintText(es, dc, x, y, line, s - li, e - s, TRUE);
@@ -2391,6 +2515,7 @@ static void EDIT_EM_ReplaceSel(EDITSTATE *es, BOOL can_undo, LPCWSTR lpsz_replac
        s = es->selection_start;
        e = es->selection_end;
 
+        EDIT_InvalidateUniscribeData(es);
        if ((s == e) && !strl)
                return;
 
@@ -2466,12 +2591,15 @@ static void EDIT_EM_ReplaceSel(EDITSTATE *es, BOOL can_undo, LPCWSTR lpsz_replac
        }
        else {
                INT fw = es->format_rect.right - es->format_rect.left;
+               EDIT_InvalidateUniscribeData(es);
                EDIT_CalcLineWidth_SL(es);
                /* remove chars that don't fit */
                if (honor_limit && !(es->style & ES_AUTOHSCROLL) && (es->text_width > fw)) {
                        while ((es->text_width > fw) && s + strl >= s) {
                                strcpyW(es->text + s + strl - 1, es->text + s + strl);
                                strl--;
+                               es->text_length = -1;
+                               EDIT_InvalidateUniscribeData(es);
                                EDIT_CalcLineWidth_SL(es);
                        }
                         text_buffer_changed(es);
@@ -2569,6 +2697,7 @@ static void EDIT_EM_ReplaceSel(EDITSTATE *es, BOOL can_undo, LPCWSTR lpsz_replac
            es->flags &= ~EF_UPDATE;
            EDIT_NOTIFY_PARENT(es, EN_CHANGE);
        }
+       EDIT_InvalidateUniscribeData(es);
 }
 
 
@@ -2769,6 +2898,7 @@ static void EDIT_EM_SetPasswordChar(EDITSTATE *es, WCHAR c)
             SetWindowLongW( es->hwndSelf, GWL_STYLE, style & ~ES_PASSWORD );
             es->style &= ~ES_PASSWORD;
        }
+       EDIT_InvalidateUniscribeData(es);
        EDIT_UpdateText(es, NULL, TRUE);
 }
 
@@ -2795,6 +2925,7 @@ static BOOL EDIT_EM_SetTabStops(EDITSTATE *es, INT count, const INT *tabs)
         } // reactos r33503
                memcpy(es->tabs, tabs, count * sizeof(INT));
        }
+       EDIT_InvalidateUniscribeData(es);
        return TRUE;
 }
 
@@ -3125,6 +3256,7 @@ static void EDIT_WM_ContextMenu(EDITSTATE *es, INT x, INT y)
             /* Windows places the menu at the edit's center in this case */
             GetClientRect(es->hwndSelf, &rc);
             MapWindowPoints(es->hwndSelf, 0, (POINT *)&rc, 2);
+            //WIN_GetRectangles( es->hwndSelf, COORDS_SCREEN, NULL, &rc );
             x = rc.left + (rc.right - rc.left) / 2;
             y = rc.top + (rc.bottom - rc.top) / 2;
         }
@@ -3534,6 +3666,9 @@ static void EDIT_WM_Paint(EDITSTATE *es, HDC hdc)
                                        (es->style & ES_NOHIDESEL));
         dc = hdc ? hdc : BeginPaint(es->hwndSelf, &ps);
 
+       /* The dc we use for calcualting may not be the one we paint into.
+          This is the safest action. */
+        EDIT_InvalidateUniscribeData(es);
        GetClientRect(es->hwndSelf, &rcClient);
 
        /* get the background brush */
@@ -3646,6 +3781,7 @@ static void EDIT_WM_SetFont(EDITSTATE *es, HFONT font, BOOL redraw)
        RECT clientRect;
 
        es->font = font;
+       EDIT_InvalidateUniscribeData(es);
        dc = GetDC(es->hwndSelf);
        if (font)
                old_font = SelectObject(dc, font);
@@ -3736,7 +3872,8 @@ static void EDIT_WM_SetText(EDITSTATE *es, LPCWSTR text, BOOL unicode)
         EDIT_NOTIFY_PARENT(es, EN_CHANGE);
     }
     EDIT_EM_ScrollCaret(es);
-    EDIT_UpdateScrollInfo(es);    
+    EDIT_UpdateScrollInfo(es);
+    EDIT_InvalidateUniscribeData(es);    
 }
 
 
@@ -4357,9 +4494,11 @@ static LRESULT EDIT_WM_NCCreate(HWND hwnd, LPCREATESTRUCTW lpcs, BOOL unicode)
 
 cleanup:
        SetWindowLongPtrW(es->hwndSelf, 0, 0);
+       EDIT_InvalidateUniscribeData(es);
        HeapFree(GetProcessHeap(), 0, es->first_line_def);
        HeapFree(GetProcessHeap(), 0, es->undo_text);
        if (es->hloc32W) LocalFree(es->hloc32W);
+       HeapFree(GetProcessHeap(), 0, es->logAttr);
        HeapFree(GetProcessHeap(), 0, es);
        return FALSE;
 }
index 07165d3..ed48931 100644 (file)
@@ -540,9 +540,7 @@ static void LISTBOX_PaintItem( LB_DESCR *descr, HDC hdc, const RECT *rect,
         after they are done, so a region has better to exist
         else everything ends clipped */
         GetClientRect(descr->self, &r);
-        hrgn = CreateRectRgnIndirect(&r);
-        SelectClipRgn( hdc, hrgn);
-        DeleteObject( hrgn );
+        hrgn = set_control_clipping( hdc, &r );
 
         dis.CtlType      = ODT_LISTBOX;
         dis.CtlID        = GetWindowLongPtrW( descr->self, GWLP_ID );
@@ -562,6 +560,8 @@ static void LISTBOX_PaintItem( LB_DESCR *descr, HDC hdc, const RECT *rect,
               descr->self, index, item ? debugstr_w(item->str) : "", action,
               dis.itemState, wine_dbgstr_rect(rect) );
         SendMessageW(descr->owner, WM_DRAWITEM, dis.CtlID, (LPARAM)&dis);
+        SelectClipRgn( hdc, hrgn );
+        if (hrgn) DeleteObject( hrgn );
     }
     else
     {
index cf500b3..60de50e 100644 (file)
@@ -19,12 +19,33 @@ static PFNCLIENT pfnClientA;
 static PFNCLIENT pfnClientW;
 static PFNCLIENTWORKER pfnClientWorker;
 
-//
-// FIXME!
-// These are not "System Classes" but Global Classes that are registered
-// every time a process is created, so these can be unregistered as the msdn
-// documents states.
-//
+
+/***********************************************************************
+ *           set_control_clipping
+ *
+ * Set clipping for a builtin control that uses CS_PARENTDC.
+ * Return the previous clip region if any.
+ */
+HRGN set_control_clipping( HDC hdc, const RECT *rect )
+{
+    RECT rc = *rect;
+    HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
+
+    if (GetClipRgn( hdc, hrgn ) != 1)
+    {
+        DeleteObject( hrgn );
+        hrgn = 0;
+    }
+    DPtoLP( hdc, (POINT *)&rc, 2 );
+    if (GetLayout( hdc ) & LAYOUT_RTL)  /* compensate for the shifting done by IntersectClipRect */
+    {
+        rc.left++;
+        rc.right++;
+    }
+    IntersectClipRect( hdc, rc.left, rc.top, rc.right, rc.bottom );
+    return hrgn;
+}
+
 static const struct
 {
     const struct builtin_class_descr *desc;
index 3a38820..fbf8d96 100644 (file)
@@ -105,34 +105,6 @@ const struct builtin_class_descr STATIC_builtin_class =
     0                    /* brush */
 };
 
-static void setup_clipping(HWND hwnd, HDC hdc, HRGN *orig)
-{
-    RECT rc;
-    HRGN hrgn;
-
-    /* Native control has always a clipping region set (this may be because
-     * builtin controls uses CS_PARENTDC) and an application depends on it
-     */
-    hrgn = CreateRectRgn(0, 0, 1, 1);
-    if (GetClipRgn(hdc, hrgn) != 1)
-    {
-        DeleteObject(hrgn);
-        *orig = NULL;
-    } else
-        *orig = hrgn;
-
-    GetClientRect(hwnd, &rc);
-    DPtoLP(hdc, (POINT *)&rc, 2);
-    IntersectClipRect(hdc, rc.left, rc.top, rc.right, rc.bottom);
-}
-
-static void restore_clipping(HDC hdc, HRGN hrgn)
-{
-    SelectClipRgn(hdc, hrgn);
-    if (hrgn != NULL)
-        DeleteObject(hrgn);
-}
-
 /***********************************************************************
  *           STATIC_SetIcon
  *
@@ -314,12 +286,13 @@ static VOID STATIC_TryPaintFcn(HWND hwnd, LONG full_style)
     if (!IsRectEmpty(&rc) && IsWindowVisible(hwnd) && staticPaintFunc[style])
     {
        HDC hdc;
-        HRGN hOrigClipping;
+        HRGN hrgn;
 
        hdc = GetDC( hwnd );
-        setup_clipping(hwnd, hdc, &hOrigClipping);
+        hrgn = set_control_clipping( hdc, &rc );
        (staticPaintFunc[style])( hwnd, hdc, full_style );
-        restore_clipping(hdc, hOrigClipping);
+        SelectClipRgn( hdc, hrgn );
+        if (hrgn) DeleteObject( hrgn );
        ReleaseDC( hwnd, hdc );
     }
 }
@@ -426,13 +399,15 @@ LRESULT WINAPI StaticWndProc_common( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM
     case WM_PAINT:
         {
             PAINTSTRUCT ps;
+            RECT rect;
             HDC hdc = wParam ? (HDC)wParam : BeginPaint(hwnd, &ps);
+            GetClientRect( hwnd, &rect );
             if (staticPaintFunc[style])
             {
-                HRGN hOrigClipping;
-                setup_clipping(hwnd, hdc, &hOrigClipping);
+                HRGN hrgn = set_control_clipping( hdc, &rect );
                 (staticPaintFunc[style])( hwnd, hdc, full_style );
-                restore_clipping(hdc, hOrigClipping);
+                SelectClipRgn( hdc, hrgn );
+                if (hrgn) DeleteObject( hrgn );
             }
             if (!wParam) EndPaint(hwnd, &ps);
         }
index e1b1056..f80b7dc 100644 (file)
@@ -88,6 +88,8 @@ extern BOOL COMBO_FlipListbox( LPHEADCOMBO, BOOL, BOOL );
 #define LB_ADDSTRING_UPPER        0x1AC
 #define LB_ADDSTRING_LOWER        0x1AD
 
+HRGN set_control_clipping( HDC hdc, const RECT *rect );
+
 LRESULT WINAPI DesktopWndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam );
 LRESULT WINAPI User32DefWindowProc(HWND,UINT,WPARAM,LPARAM,BOOL);
 BOOL WINAPI RegisterClientPFN(VOID);
index 9f5472e..4dd40c7 100644 (file)
@@ -22,6 +22,7 @@
 #include <windowsx.h>
 #include <winnls32.h>
 #include <strsafe.h>
+#include <usp10.h>
 #include <ndk/cmfuncs.h>
 #include <ndk/kefuncs.h>
 #include <ndk/obfuncs.h>
index 213e757..f973fc1 100644 (file)
@@ -9,6 +9,7 @@
        <library>gdi32</library>
        <library>advapi32</library>
        <library>imm32</library>
+       <library>usp10</library>
        <library>win32ksys</library>
        <library>pseh</library>
        <library>ntdll</library>
index c951766..eef5b24 100644 (file)
@@ -1453,31 +1453,31 @@ HICON WINAPI CreateIconIndirect(PICONINFO iconinfo)
         // the size of the mask bitmap always determines the icon size!
         width = bmpAnd.bmWidth;
         height = bmpAnd.bmHeight;
-        if (bmpXor.bmPlanes * bmpXor.bmBitsPixel != 1)
+        if (bmpXor.bmPlanes * bmpXor.bmBitsPixel != 1 )
         {
             color = CreateBitmap( width, height, bmpXor.bmPlanes, bmpXor.bmBitsPixel, NULL );
-                       if(!color)
-                       {
-                               ERR("Unable to create color bitmap!\n");
-                               return NULL;
-                       }
+            if(!color)
+            {
+                ERR("Unable to create color bitmap!\n");
+               return NULL;
+            }
             mask = CreateBitmap( width, height, 1, 1, NULL );
-                       if(!mask)
-                       {
-                               ERR("Unable to create mask bitmap!\n");
-                               DeleteObject(color);
-                               return NULL;
-                       }
+           if(!mask)
+           {
+               ERR("Unable to create mask bitmap!\n");
+               DeleteObject(color);
+               return NULL;
+           }
         }
         else 
-               {
-                       mask = CreateBitmap( width, height * 2, 1, 1, NULL );
-                       if(!mask)
-                       {
-                               ERR("Unable to create mask bitmap!\n");
-                               return NULL;
-                       }
-               }
+       {
+           mask = CreateBitmap( width, height * 2, 1, 1, NULL );
+           if(!mask)
+           {
+              ERR("Unable to create mask bitmap!\n");
+              return NULL;
+           }
+        }
     }
     else
     {
index 1d93861..414e178 100644 (file)
@@ -342,7 +342,9 @@ static BOOL DIALOG_CreateControls32( HWND hwnd, LPCSTR template, const DLG_TEMPL
     {
         template = (LPCSTR)DIALOG_GetControl32( (const WORD *)template, &info,
                                                 dlgTemplate->dialogEx );
-        /* Is this it? */
+        info.style &= ~WS_POPUP;
+        info.style |= WS_CHILD;
+
         if (info.style & WS_BORDER)
         {
             info.style &= ~WS_BORDER;
@@ -405,6 +407,8 @@ static BOOL DIALOG_CreateControls32( HWND hwnd, LPCSTR template, const DLG_TEMPL
 
         if (!hwndCtrl)
         {
+            WARN("control %s %s creation failed\n", debugstr_w(info.className),
+                  debugstr_w(info.windowName));
             if (dlgTemplate->style & DS_NOFAILCREATE) continue;
             return FALSE;
         }
@@ -1013,6 +1017,7 @@ static HWND DIALOG_CreateIndirect( HINSTANCE hInst, LPCVOID dlgTemplate,
         if (dlgProc)
         {
             HWND focus = GetNextDlgTabItem( hwnd, 0, FALSE );
+            if (!focus) focus = GetNextDlgGroupItem( hwnd, 0, FALSE );
             if (SendMessageW( hwnd, WM_INITDIALOG, (WPARAM)focus, param ) && IsWindow( hwnd ) &&
                 ((~template.style & DS_CONTROL) || (template.style & WS_VISIBLE)))
             {
@@ -1020,6 +1025,7 @@ static HWND DIALOG_CreateIndirect( HINSTANCE hInst, LPCVOID dlgTemplate,
                  * WM_INITDIALOG may have changed the tab order, so find the first
                  * tabstop control again. */
                 dlgInfo->hwndFocus = GetNextDlgTabItem( hwnd, 0, FALSE );
+                if (!dlgInfo->hwndFocus) dlgInfo->hwndFocus = GetNextDlgGroupItem( hwnd, 0, FALSE );
                 if( dlgInfo->hwndFocus )
                     SetFocus( dlgInfo->hwndFocus );
             }
@@ -1983,41 +1989,52 @@ DlgDirSelectExW(
 BOOL
 WINAPI
 EndDialog(
-  HWND hDlg,
-  INT_PTR nResult)
+  HWND hwnd,
+  INT_PTR retval)
 {
     BOOL wasEnabled = TRUE;
     DIALOGINFO * dlgInfo;
     HWND owner;
 
-    if (!(dlgInfo = GETDLGINFO(hDlg)))
+    TRACE("%p %ld\n", hwnd, retval );
+
+    if (!(dlgInfo = GETDLGINFO(hwnd)))
     {
-        ERR("got invalid window handle (%p); buggy app !?\n", hDlg);
+        ERR("got invalid window handle (%p); buggy app !?\n", hwnd);
         return FALSE;
     }
-
-    dlgInfo->idResult = nResult;
+    dlgInfo->idResult = retval;
     dlgInfo->flags |= DF_END;
     wasEnabled = (dlgInfo->flags & DF_OWNERENABLED);
 
-    if (wasEnabled && (owner = GetWindow( hDlg, GW_OWNER )))
+    owner = GetWindow( hwnd, GW_OWNER );
+    if (wasEnabled && owner)
         DIALOG_EnableOwner( owner );
 
     /* Windows sets the focus to the dialog itself in EndDialog */
 
-    if (IsChild(hDlg, GetFocus()))
-       SetFocus( hDlg );
+    if (IsChild(hwnd, GetFocus()))
+       SetFocus( hwnd );
 
     /* Don't have to send a ShowWindow(SW_HIDE), just do
        SetWindowPos with SWP_HIDEWINDOW as done in Windows */
 
-    SetWindowPos(hDlg, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE
+    SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE
                  | SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW);
 
-    if (hDlg == GetActiveWindow()) WinPosActivateOtherWindow( hDlg );
+    if (hwnd == GetActiveWindow())
+    {
+        /* If this dialog was given an owner then set the focus to that owner
+           even when the owner is disabled (normally when a window closes any
+           disabled windows cannot receive the focus). */
+        if (owner)
+            SetForegroundWindow( owner );
+        else
+            WinPosActivateOtherWindow( hwnd );
+    }
 
     /* unblock dialog loop */
-    PostMessageA(hDlg, WM_NULL, 0, 0);
+    PostMessageA(hwnd, WM_NULL, 0, 0);
     return TRUE;
 }