-Implemented TCS_BUTTONS, TCS_FIXEDWIDTH, TCM_GETITEMRECT,
TCM_SETITEMSIZE and TCM_DELETEITEM.

diff --git a/dlls/comctl32/tab.c b/dlls/comctl32/tab.c
index 02160bd..6e42659 100644
--- a/dlls/comctl32/tab.c
+++ b/dlls/comctl32/tab.c
@@ -31,6 +31,8 @@
 #define DISPLAY_AREA_PADDINGY   5
 #define CONTROL_BORDER_SIZEX    2
 #define CONTROL_BORDER_SIZEY    2
+#define BUTTON_SPACINGX         10
+#define DEFAULT_TAB_WIDTH       96
 
 #define TAB_GetInfoPtr(hwnd) ((TAB_INFO *)GetWindowLongA(hwnd,0))
 
@@ -235,6 +237,12 @@
   return TRUE;
 }
 
+static BOOL TAB_GetItemRect(HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+  return TAB_InternalGetItemRect(hwnd, TAB_GetInfoPtr(hwnd), (INT)wParam, 
+                                 (LPRECT)lParam, (LPRECT)NULL);
+}
+
 /******************************************************************************
  * TAB_KeyUp
  *
@@ -617,6 +625,7 @@
 static void TAB_SetItemBounds (HWND hwnd)
 {
   TAB_INFO*   infoPtr = TAB_GetInfoPtr(hwnd);
+  LONG        lStyle  = GetWindowLongA(hwnd, GWL_STYLE);
   TEXTMETRICA fontMetrics;
   INT         curItem;
   INT         curItemLeftPos;
@@ -645,45 +654,63 @@
    */
   curItemLeftPos = 0;
 
-  /*
-   * Use the current font to determine the height of a tab.
-   */
-  GetTextMetricsA(hdc, &fontMetrics);
-  infoPtr->tabHeight = fontMetrics.tmHeight +     /* Enough space for the letters        */
-                       2*VERTICAL_ITEM_PADDING +  /* Space for growing the selected item */
-                       SELECTED_TAB_OFFSET;       /* Extra space for the selected item   */
-    
+  if (!((lStyle & TCS_FIXEDWIDTH) || (lStyle & TCS_OWNERDRAWFIXED)))
+  {
+    /*
+     * Use the current font to determine the height of a tab.
+     */
+    GetTextMetricsA(hdc, &fontMetrics);
+
+    /*
+     * Make sure there is enough space for the letters + growing the 
+     * selected item + extra space for the selected item.   
+     */
+    infoPtr->tabHeight = fontMetrics.tmHeight + 2*VERTICAL_ITEM_PADDING +  
+      SELECTED_TAB_OFFSET;
+  }
+
   for (curItem = 0; curItem < infoPtr->uNumItem; curItem++)
   {
     /*
      * Calculate the vertical position of the tab
      */
-    if (GetWindowLongA(hwnd, GWL_STYLE) & TCS_BOTTOM) 
+    if (lStyle & TCS_BOTTOM) 
     {
-      infoPtr->items[curItem].rect.bottom = clientRect.bottom - SELECTED_TAB_OFFSET;
-      infoPtr->items[curItem].rect.top    = clientRect.bottom - infoPtr->tabHeight;
+      infoPtr->items[curItem].rect.bottom = clientRect.bottom - 
+                                            SELECTED_TAB_OFFSET;
+      infoPtr->items[curItem].rect.top = clientRect.bottom - 
+                                         infoPtr->tabHeight;
     }
     else 
     {
-      infoPtr->items[curItem].rect.top    = clientRect.top + SELECTED_TAB_OFFSET;
-      infoPtr->items[curItem].rect.bottom = clientRect.top + infoPtr->tabHeight;
+      infoPtr->items[curItem].rect.top = clientRect.top + 
+                                         SELECTED_TAB_OFFSET;
+      infoPtr->items[curItem].rect.bottom = clientRect.top + 
+                                            infoPtr->tabHeight;
     }
 
     /*
      * Set the leftmost position of the tab.
      */
     infoPtr->items[curItem].rect.left = curItemLeftPos;
-    
-    /*
-     * Calculate how wide the tab is depending on the text it contains
-     */
-    GetTextExtentPoint32A(hdc, 
-			  infoPtr->items[curItem].pszText, 
-			  lstrlenA(infoPtr->items[curItem].pszText), &size);
 
-    infoPtr->items[curItem].rect.right = infoPtr->items[curItem].rect.left +
-                                         size.cx +
-                                         2*HORIZONTAL_ITEM_PADDING;
+    if ((lStyle & TCS_FIXEDWIDTH) || (lStyle & TCS_OWNERDRAWFIXED))
+    {
+      infoPtr->items[curItem].rect.right = infoPtr->items[curItem].rect.left +
+                                           infoPtr->tabWidth +
+                                           2*HORIZONTAL_ITEM_PADDING;
+    }
+    else
+    {
+      /*
+       * Calculate how wide the tab is depending on the text it contains
+       */
+      GetTextExtentPoint32A(hdc, infoPtr->items[curItem].pszText, 
+                            lstrlenA(infoPtr->items[curItem].pszText), &size);
+      
+      infoPtr->items[curItem].rect.right = infoPtr->items[curItem].rect.left +
+                                           size.cx + 2*HORIZONTAL_ITEM_PADDING;
+    }
 
     TRACE(tab, "TextSize: %i\n ", size.cx);
     TRACE(tab, "Rect: T %i, L %i, B %i, R %i\n", 
@@ -696,17 +723,19 @@
      * The leftmost position of the next item is the rightmost position
      * of this one.
      */
-    curItemLeftPos = infoPtr->items[curItem].rect.right;
+    if (lStyle & TCS_BUTTONS)
+      curItemLeftPos = infoPtr->items[curItem].rect.right + BUTTON_SPACINGX;
+    else
+      curItemLeftPos = infoPtr->items[curItem].rect.right;
   }
 
   /*
    * Check if we need a scrolling control.
    */
-  infoPtr->needsScrolling = (curItemLeftPos + (2*SELECTED_TAB_OFFSET) > clientRect.right);
+  infoPtr->needsScrolling = (curItemLeftPos + (2*SELECTED_TAB_OFFSET) > 
+                             clientRect.right);
 
-  TAB_SetupScrolling(hwnd,
-		     infoPtr,
-		     &clientRect);      
+  TAB_SetupScrolling(hwnd, infoPtr, &clientRect);      
   
   /*
    * Cleanup
@@ -726,6 +755,7 @@
   INT  iItem)
 {
   TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
+  LONG      lStyle  = GetWindowLongA(hwnd, GWL_STYLE);
   RECT      itemRect;
   RECT      selectedRect;
   BOOL      isVisible;
@@ -740,21 +770,9 @@
 				      &itemRect,
 				      &selectedRect);
 
-  /*
-   * We draw a rectangle of different sizes depending on the selection
-   * state.
-   */
-  if (iItem == infoPtr->iSelected)
-    r = selectedRect;
-  else
-    r = itemRect;
-
-  /*
-   * Only go through the drawing if the item is partially visible.
-   */
   if (isVisible)
   {
-    HBRUSH hbr       = CreateSolidBrush(GetSysColor(COLOR_BACKGROUND));    
+    HBRUSH hbr       = CreateSolidBrush (GetSysColor(COLOR_BACKGROUND));    
     HPEN   hwPen     = GetSysColorPen (COLOR_3DHILIGHT);
     HPEN   hbPen     = GetSysColorPen (COLOR_BTNSHADOW);
     HPEN   hsdPen    = GetSysColorPen (COLOR_BTNTEXT);
@@ -763,52 +781,128 @@
     INT    oldBkMode;
     INT    cx,cy; 
 
-    /*
-     * Erase the background.
-     * This is necessary when drawing the selected item since it is larger 
-     * than the others, it might overlap with stuff already drawn by the other
-     * tabs
-     */     
-    FillRect(hdc, &r, hbr);
-
-    /*
-     * Draw the tab now.
-     * The rectangles calculated exclude the right and bottom
-     * borders of the rectangle. To simply the following code, those
-     * borders are shaved-off beforehand.
-     */
-    r.right--;
-    r.bottom--;
-
-    holdPen = SelectObject (hdc, hwPen);
-
-    if (GetWindowLongA(hwnd, GWL_STYLE) & TCS_BOTTOM) 
+    if (lStyle & TCS_BUTTONS)
     {
-      /* highlight */
-      MoveToEx (hdc, r.left, r.top, NULL);
-      LineTo   (hdc, r.left, r.bottom - ROUND_CORNER_SIZE);
-      LineTo   (hdc, r.left + ROUND_CORNER_SIZE, r.bottom);
+      /* 
+       * Get item rectangle.
+       */
+      r = itemRect;
 
-      /* shadow */
-      SelectObject(hdc, hbPen),
-      LineTo  (hdc, r.right - ROUND_CORNER_SIZE, r.bottom);
-      LineTo  (hdc, r.right, r.bottom - ROUND_CORNER_SIZE);
-      LineTo  (hdc, r.right, r.top);
+      holdPen = SelectObject (hdc, hwPen);
+
+      if (iItem == infoPtr->iSelected)
+      {
+        /* 
+         * Background color. 
+         */
+        if (!(lStyle & TCS_OWNERDRAWFIXED))
+          hbr = CreateSolidBrush(GetSysColor(COLOR_3DHILIGHT));    
+
+        /*
+         * Erase the background.
+         */     
+        FillRect(hdc, &r, hbr);
+
+        /*
+         * Draw the tab now.
+         * The rectangles calculated exclude the right and bottom
+         * borders of the rectangle. To simply the following code, those
+         * borders are shaved-off beforehand.
+         */
+        r.right--;
+        r.bottom--;
+
+        /* highlight */
+        MoveToEx (hdc, r.left, r.bottom, NULL);
+        LineTo   (hdc, r.right, r.bottom);
+        LineTo   (hdc, r.right, r.top);
+        
+        /* shadow */
+        SelectObject(hdc, hbPen);
+        LineTo  (hdc, r.left, r.top);
+        LineTo  (hdc, r.left, r.bottom);
+      }
+      else
+      {
+        /*
+         * Erase the background.
+         */     
+        FillRect(hdc, &r, hbr);
+
+        /* highlight */
+        MoveToEx (hdc, r.left, r.bottom, NULL);
+        LineTo   (hdc, r.left, r.top);
+        LineTo   (hdc, r.right, r.top);
+        
+        /* shadow */
+        SelectObject(hdc, hbPen);
+        LineTo  (hdc, r.right, r.bottom);
+        LineTo  (hdc, r.left, r.bottom);
+      }
     }
-    else 
+    else
     {
-      /* highlight */
-      MoveToEx (hdc, r.left, r.bottom, NULL);
-      LineTo   (hdc, r.left, r.top + ROUND_CORNER_SIZE);
-      LineTo   (hdc, r.left + ROUND_CORNER_SIZE, r.top);
-      LineTo   (hdc, r.right - ROUND_CORNER_SIZE, r.top);
+      /* 
+       * Background color. 
+       */
+      hbr = CreateSolidBrush(GetSysColor(COLOR_BACKGROUND));    
 
-      /* shadow */
-      SelectObject(hdc, hbPen),
-      LineTo (hdc, r.right,  r.top + ROUND_CORNER_SIZE);
-      LineTo (hdc, r.right,  r.bottom);
+      /*
+       * We draw a rectangle of different sizes depending on the selection
+       * state.
+       */
+      if (iItem == infoPtr->iSelected)
+        r = selectedRect;
+      else
+        r = itemRect;
+
+      /*
+       * Erase the background.
+       * This is necessary when drawing the selected item since it is larger 
+       * than the others, it might overlap with stuff already drawn by the 
+       * other tabs
+       */     
+      FillRect(hdc, &r, hbr);
+
+      /*
+       * Draw the tab now.
+       * The rectangles calculated exclude the right and bottom
+       * borders of the rectangle. To simply the following code, those
+       * borders are shaved-off beforehand.
+       */
+      r.right--;
+      r.bottom--;
+      
+      holdPen = SelectObject (hdc, hwPen);
+
+      if (lStyle & TCS_BOTTOM) 
+      {
+        /* highlight */
+        MoveToEx (hdc, r.left, r.top, NULL);
+        LineTo   (hdc, r.left, r.bottom - ROUND_CORNER_SIZE);
+        LineTo   (hdc, r.left + ROUND_CORNER_SIZE, r.bottom);
+        
+        /* shadow */
+        SelectObject(hdc, hbPen);
+        LineTo  (hdc, r.right - ROUND_CORNER_SIZE, r.bottom);
+        LineTo  (hdc, r.right, r.bottom - ROUND_CORNER_SIZE);
+        LineTo  (hdc, r.right, r.top);
+      }
+      else 
+      {
+        /* highlight */
+        MoveToEx (hdc, r.left, r.bottom, NULL);
+        LineTo   (hdc, r.left, r.top + ROUND_CORNER_SIZE);
+        LineTo   (hdc, r.left + ROUND_CORNER_SIZE, r.top);
+        LineTo   (hdc, r.right - ROUND_CORNER_SIZE, r.top);
+        
+        /* shadow */
+        SelectObject(hdc, hbPen);
+        LineTo (hdc, r.right,  r.top + ROUND_CORNER_SIZE);
+        LineTo (hdc, r.right,  r.bottom);
+      }
     }
-
+  
     /*
      * Text pen
      */
@@ -845,7 +939,7 @@
     /*
      * Draw the focus rectangle
      */
-    if ( ((GetWindowLongA(hwnd, GWL_STYLE) & TCS_FOCUSNEVER) == 0) &&
+    if (((lStyle & TCS_FOCUSNEVER) == 0) &&
 	 (GetFocus() == hwnd) &&
 	 (iItem == infoPtr->uFocus) )
     {
@@ -941,25 +1035,35 @@
 
   hOldFont = SelectObject (hdc, infoPtr->hFont);
 
-  /*
-   * Draw all the non selected item first.
-   */
-  for (i = 0; i < infoPtr->uNumItem; i++) 
+  if (GetWindowLongA(hwnd, GWL_STYLE) & TCS_BUTTONS)
   {
-    if (i != infoPtr->iSelected)
+    for (i = 0; i < infoPtr->uNumItem; i++) 
+    {
 	TAB_DrawItem (hwnd, hdc, i);
+    }
   }
+  else
+  {
+    /*
+     * Draw all the non selected item first.
+     */
+    for (i = 0; i < infoPtr->uNumItem; i++) 
+    {
+      if (i != infoPtr->iSelected)
+	TAB_DrawItem (hwnd, hdc, i);
+    }
 
-  /*
-   * Now, draw the border, draw it before the selected item
-   * since the selected item overwrites part of the border.
-   */
-  TAB_DrawBorder (hwnd, hdc);
+    /*
+     * Now, draw the border, draw it before the selected item
+     * since the selected item overwrites part of the border.
+     */
+    TAB_DrawBorder (hwnd, hdc);
 
-  /*
-   * Then, draw the selected item
-   */
-  TAB_DrawItem (hwnd, hdc, infoPtr->iSelected);
+    /*
+     * Then, draw the selected item
+     */
+    TAB_DrawItem (hwnd, hdc, infoPtr->iSelected);
+  }
 
   SelectObject (hdc, hOldFont);
 }
@@ -1189,6 +1293,23 @@
 }
 
 static LRESULT 
+TAB_SetItemSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+  TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
+  LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
+  LONG lResult = 0;
+
+  if ((lStyle & TCS_FIXEDWIDTH) || (lStyle & TCS_OWNERDRAWFIXED))
+  {
+    lResult = MAKELONG(infoPtr->tabWidth, infoPtr->tabHeight);
+    infoPtr->tabWidth = (INT)LOWORD(lParam);
+    infoPtr->tabHeight = (INT)HIWORD(lParam);
+  }
+
+  return lResult;
+}
+
+static LRESULT 
 TAB_SetItemA (HWND hwnd, WPARAM wParam, LPARAM lParam)
 {
   TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
@@ -1270,8 +1391,29 @@
 static LRESULT 
 TAB_DeleteItem (HWND hwnd, WPARAM wParam, LPARAM lParam)
 {
-  FIXME (tab,"stub \n");
-  return TRUE;
+  TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
+  INT iItem = (INT) wParam;
+  BOOL bResult = FALSE;
+
+  if ((iItem >= 0) && (iItem < infoPtr->uNumItem))
+  {
+    TAB_ITEM *oldItems = infoPtr->items;
+    
+    infoPtr->uNumItem--;
+    infoPtr->items = COMCTL32_Alloc(sizeof (TAB_ITEM) * infoPtr->uNumItem);
+    
+    if (iItem > 0) 
+      memcpy(&infoPtr->items[0], &oldItems[0], iItem * sizeof(TAB_ITEM));
+    
+    if (iItem < infoPtr->uNumItem) 
+      memcpy(&infoPtr->items[iItem], &oldItems[iItem + 1],
+              (infoPtr->uNumItem - iItem) * sizeof(TAB_ITEM));
+    
+    COMCTL32_Free (oldItems);
+    bResult = TRUE;
+  }
+
+  return bResult;
 }
 
 static LRESULT 
@@ -1381,6 +1523,9 @@
 TAB_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
 {
   TAB_INFO *infoPtr;
+  TEXTMETRICA fontMetrics;
+  HDC hdc;
+  HFONT hOldFont;
 
   infoPtr = (TAB_INFO *)COMCTL32_Alloc (sizeof(TAB_INFO));
 
@@ -1421,6 +1566,33 @@
     }
   }  
     
+  /*
+   * We need to get text information so we need a DC and we need to select
+   * a font.
+   */
+  hdc = GetDC(hwnd); 
+  hOldFont = SelectObject (hdc, GetStockObject (SYSTEM_FONT));
+
+  /*
+   * Use the system font to determine the initial height of a tab.
+   */
+  GetTextMetricsA(hdc, &fontMetrics);
+
+  /*
+   * Make sure there is enough space for the letters + growing the 
+   * selected item + extra space for the selected item.   
+   */
+  infoPtr->tabHeight = fontMetrics.tmHeight + 2*VERTICAL_ITEM_PADDING +  
+                       SELECTED_TAB_OFFSET;
+
+  /*
+   * Initialize the width of a tab.
+   */
+  infoPtr->tabWidth = DEFAULT_TAB_WIDTH;
+
+  SelectObject (hdc, hOldFont);
+  ReleaseDC(hwnd, hdc);
+
   return 0;
 }
 
@@ -1466,14 +1638,14 @@
       return TAB_GetItemA (hwnd, wParam, lParam);
       
     case TCM_GETITEMW:
-      FIXME (tab, "Unimplemented msg TCM_GETITEM32W\n");
+      FIXME (tab, "Unimplemented msg TCM_GETITEMW\n");
       return 0;
       
     case TCM_SETITEMA:
       return TAB_SetItemA (hwnd, wParam, lParam);
       
     case TCM_SETITEMW:
-      FIXME (tab, "Unimplemented msg TCM_GETITEM32W\n");
+      FIXME (tab, "Unimplemented msg TCM_SETITEMW\n");
       return 0;
       
     case TCM_DELETEITEM:
@@ -1483,8 +1655,7 @@
      return TAB_DeleteAllItems (hwnd, wParam, lParam);
      
     case TCM_GETITEMRECT:
-      FIXME (tab, "Unimplemented msg TCM_GETITEMRECT\n");
-      return 0;
+     return TAB_GetItemRect (hwnd, wParam, lParam);
       
     case TCM_GETCURSEL:
       return TAB_GetCurSel (hwnd);
@@ -1510,8 +1681,7 @@
       return TAB_AdjustRect (hwnd, (BOOL)wParam, (LPRECT)lParam);
       
     case TCM_SETITEMSIZE:
-      FIXME (tab, "Unimplemented msg TCM_SETITEMSIZE\n");
-      return 0;
+      return TAB_SetItemSize (hwnd, wParam, lParam);
       
     case TCM_REMOVEIMAGE:
       FIXME (tab, "Unimplemented msg TCM_REMOVEIMAGE\n");
@@ -1524,6 +1694,18 @@
     case TCM_GETROWCOUNT:
       FIXME (tab, "Unimplemented msg TCM_GETROWCOUNT\n");
       return 0;
+
+    case TCM_GETUNICODEFORMAT:
+      FIXME (tab, "Unimplemented msg TCM_GETUNICODEFORMAT\n");
+      return 0;
+
+    case TCM_SETUNICODEFORMAT:
+      FIXME (tab, "Unimplemented msg TCM_SETUNICODEFORMAT\n");
+      return 0;
+
+    case TCM_HIGHLIGHTITEM:
+      FIXME (tab, "Unimplemented msg TCM_HIGHLIGHTITEM\n");
+      return 0;
       
     case TCM_GETTOOLTIPS:
       return TAB_GetToolTips (hwnd, wParam, lParam);
@@ -1545,6 +1727,14 @@
       FIXME (tab, "Unimplemented msg TCM_DESELECTALL\n");
       return 0;
       
+    case TCM_GETEXTENDEDSTYLE:
+      FIXME (tab, "Unimplemented msg TCM_GETEXTENDEDSTYLE\n");
+      return 0;
+
+    case TCM_SETEXTENDEDSTYLE:
+      FIXME (tab, "Unimplemented msg TCM_SETEXTENDEDSTYLE\n");
+      return 0;
+
     case WM_GETFONT:
       return TAB_GetFont (hwnd, wParam, lParam);
       
diff --git a/include/tab.h b/include/tab.h
index e2ee7e5..853f7f6 100644
--- a/include/tab.h
+++ b/include/tab.h
@@ -24,6 +24,7 @@
 {
   UINT       uNumItem;        /* number of tab items */
   INT        tabHeight;       /* height of the tab row */
+  INT        tabWidth;        /* width of tabs */
   HFONT      hFont;           /* handle to the current font */
   HCURSOR    hcurArrow;       /* handle to the current cursor */
   HIMAGELIST himl;            /* handle to a image list (may be 0) */