Implement multiline labels in the Large Item view by using DrawText
Note that this now highlights weaknesses in the label measuring code
etc. which cannot correctly handle multiline labels.

diff --git a/dlls/comctl32/listview.c b/dlls/comctl32/listview.c
index 81e9ec1..27c672b 100644
--- a/dlls/comctl32/listview.c
+++ b/dlls/comctl32/listview.c
@@ -3248,9 +3248,9 @@
  * PARAMETER(S):
  * [I] HWND : window handle
  * [I] HDC : device context handle
- * [I] LISTVIEW_ITEM * : item
  * [I] INT : item index
- * [I] RECT * : clipping rectangle
+ * [I] RECT : clipping rectangle
+ * [O] RECT * : The text rectangle about which to draw the focus
  *
  * RETURN:
  * None
@@ -3259,10 +3259,11 @@
                                    RECT *SuggestedFocus)
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongW(hwnd, 0); 
-  UINT textoutOptions = ETO_CLIPPED | ETO_OPAQUE;
   WCHAR szDispText[DISP_TEXT_SIZE] = { '\0' };
-  INT nDrawPosX, nLabelWidth, rcWidth;
   LVITEMW lvItem;
+  UINT uFormat = DT_TOP | DT_CENTER | DT_WORDBREAK | DT_NOPREFIX |
+                 DT_EDITCONTROL ;
+  /* Maintain this format in line with the one in LISTVIEW_UpdateLargeItemRect*/
   RECT rcTemp;
 
   TRACE("(hwnd=%x, hdc=%x, nItem=%d, left=%d, top=%d, right=%d, bottom=%d)\n",
@@ -3286,19 +3287,42 @@
     rcTemp.right = infoPtr->rcList.right;
   else
     rcTemp.right+=WIDTH_PADDING;
+    /* The comment doesn't say WIDTH_PADDING applies to large icons */
   
   TRACE("background rect (%d,%d)-(%d,%d)\n",
         rcTemp.left, rcTemp.top, rcTemp.right, rcTemp.bottom);
   
   LISTVIEW_FillBackground(hwnd, hdc, &rcTemp);
 
+
+  /* Figure out text colours etc. depending on state
+   * At least the following states exist; there may be more.
+   * Many items may be selected
+   * At most one item may have the focus
+   * The application may not actually be active currently
+   * 1. The item is not selected in any way
+   * 2. The cursor is flying over the icon or text and the text is being 
+   *    expanded because it is not fully displayed currently.
+   * 3. The item is selected and is focussed, i.e. the user has not clicked
+   *    in the blank area of the window, and the window (or application?)
+   *    still has the focus.
+   * 4. As 3 except that a different window has the focus
+   * 5. The item is the selected item of all the items, but the user has
+   *    clicked somewhere else on the window.
+   * Only a few of these are handled currently. In particular 2 is not yet
+   * handled since we do not support the functionality currently (or at least
+   * we didn't when I wrote this)
+   */
+
   if (lvItem.state & LVIS_SELECTED)
   {
     /* set item colors */ 
     SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT));
     SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
+    SetBkMode (hdc, OPAQUE);
     /* set raster mode */
     SetROP2(hdc, R2_XORPEN);
+    /* When exactly is it in XOR? while being dragged? */
   }
   else
   {
@@ -3306,7 +3330,6 @@
     if ( (infoPtr->clrTextBk == CLR_DEFAULT) || (infoPtr->clrTextBk == CLR_NONE) )
     {
        SetBkMode(hdc, TRANSPARENT);
-       textoutOptions &= ~ETO_OPAQUE;
     }
     else
     {
@@ -3319,24 +3342,37 @@
     SetROP2(hdc, R2_COPYPEN);
   }
 
+  /* In cases 2,3 and 5 (see above) the full text is displayed, with word
+   * wrapping and long words split.
+   * In cases 1 and 4 only a portion of the text is displayed with word
+   * wrapping and both word and end ellipsis.  (I don't yet know about path
+   * ellipsis)
+   */
+  uFormat |= ( (lvItem.state & LVIS_FOCUSED) && infoPtr->bFocus) ?
+          DT_NOCLIP
+      :
+          DT_WORD_ELLIPSIS | DT_END_ELLIPSIS;
+
   /* draw the icon */
   if (infoPtr->himlNormal != NULL)
   {
-    if ((lvItem.state & LVIS_SELECTED) && (lvItem.iImage>=0))
+    if (lvItem.iImage >= 0)
     {
-      ImageList_Draw(infoPtr->himlNormal, lvItem.iImage, hdc, rcItem.left, 
-                     rcItem.top, ILD_SELECTED);
-    }
-    else if (lvItem.iImage>=0)
-    {
-      ImageList_Draw(infoPtr->himlNormal, lvItem.iImage, hdc, rcItem.left, 
-                     rcItem.top, ILD_NORMAL);
+      ImageList_Draw (infoPtr->himlNormal, lvItem.iImage, hdc, rcItem.left, 
+                      rcItem.top,
+                      (lvItem.state & LVIS_SELECTED) ? ILD_SELECTED : ILD_NORMAL);
     }
   }
 
+  /* Draw the text below the icon */
+
   /* Don't bother painting item being edited */
-  if (infoPtr->hwndEdit && lvItem.state & LVIS_FOCUSED)
+  if ((infoPtr->hwndEdit && (lvItem.state & LVIS_FOCUSED)) ||
+      !lstrlenW(lvItem.pszText))
+  {
+    SetRectEmpty(SuggestedFocus);
     return;
+  }
 
   /* Since rcItem.left is left point of icon, compute left point of item box */
   rcItem.left -= ((infoPtr->nItemWidth - infoPtr->iconSize.cx) / 2);
@@ -3353,56 +3389,36 @@
   
   InflateRect(&rcItem, -(2*CAPTION_BORDER), 0);
   rcItem.top += infoPtr->iconSize.cy + ICON_BOTTOM_PADDING; 
-  nLabelWidth = ListView_GetStringWidthW(hwnd, lvItem.pszText);
-  TRACE("rect for text sizing (%d,%d)-(%d,%d), text width %d\n",
-        rcItem.left, rcItem.top, rcItem.right, rcItem.bottom,
-        nLabelWidth);
-  
-  /* append an ellipse ('...') if the caption won't fit in the rect */
-  rcWidth = max(0, rcItem.right - rcItem.left);
-  if (nLabelWidth > rcWidth)
-  {
-      /* give or take a couple, how many average sized chars would fit? */
-      INT nCharsFit = infoPtr->ntmAveCharWidth > 0 ? 
-	      	      rcWidth/infoPtr->ntmAveCharWidth + 2 : 0;
-      INT eos = min(strlenW(lvItem.pszText), nCharsFit);
-      if (eos > 0) lvItem.pszText[eos-1] = '.';
-      if (eos > 1) lvItem.pszText[eos-2] = '.';
-      if (eos < 3) lvItem.pszText[eos] = '\0'; 
-      for ( ; eos > 2; eos--) 
-      {
- 	 lvItem.pszText[eos - 3] = '.';
- 	 lvItem.pszText[eos] = '\0';
- 	 if (ListView_GetStringWidthW(hwnd, lvItem.pszText) <= rcWidth) break;
-      }
-  }
 
-  InflateRect(&rcItem, 2*CAPTION_BORDER, 0);
-  nDrawPosX = infoPtr->iconSpacing.cx - 2*CAPTION_BORDER - nLabelWidth;
-  if (nDrawPosX > 1)
-  {
-    rcItem.left += nDrawPosX / 2;
-    rcItem.right = rcItem.left + nLabelWidth + 2*CAPTION_BORDER;
-  }
-  else
-  {
-    rcItem.left += 1;
-    rcItem.right = rcItem.left + infoPtr->iconSpacing.cx - 1;
-  }
 
   /* draw label */  
-  rcItem.bottom = rcItem.top + infoPtr->ntmHeight + HEIGHT_PADDING; 
-  TRACE("rect for text (%d,%d)-(%d,%d)\n",
-        rcItem.left, rcItem.top, rcItem.right, rcItem.bottom);
-  if (lstrlenW(lvItem.pszText))
-  {
-    ExtTextOutW(hdc, rcItem.left + CAPTION_BORDER, rcItem.top, textoutOptions, 
-                &rcItem, lvItem.pszText, lstrlenW(lvItem.pszText), NULL);
 
-    CopyRect(SuggestedFocus, &rcItem);
+  /* I am sure of most of the uFormat values.  However I am not sure about
+   * whether we need or do not need the following:
+   * DT_EXTERNALLEADING, DT_INTERNAL, DT_CALCRECT, DT_NOFULLWIDTHCHARBREAK,
+   * DT_PATH_ELLIPSIS, DT_RTLREADING, 
+   * We certainly do not need
+   * DT_BOTTOM, DT_VCENTER, DT_MODIFYSTRING, DT_LEFT, DT_RIGHT, DT_PREFIXONLY,
+   * DT_SINGLELINE, DT_TABSTOP, DT_EXPANDTABS
+   */
+
+  /* If the text is being drawn without clipping (i.e. the full text) then we
+   * need to jump through a few hoops to ensure that it all gets displayed and
+   * that the background is complete
+   */
+  if (uFormat & DT_NOCLIP)
+  {
+      HBRUSH hBrush = CreateSolidBrush(GetBkColor (hdc));
+      DrawTextW (hdc, lvItem.pszText, -1, &rcItem, uFormat | DT_CALCRECT);
+      FillRect(hdc, &rcItem, hBrush);
+      DeleteObject(hBrush);
   }
-  else
-    SetRectEmpty(SuggestedFocus);
+  /* else ? What if we are losing the focus? will we not get a complete 
+   * background?
+   */
+  DrawTextW (hdc, lvItem.pszText, -1, &rcItem, uFormat);
+
+  CopyRect(SuggestedFocus, &rcItem);
 }
 
 /***