Ignore:
Timestamp:
May 22, 2000, 7:25:13 PM (25 years ago)
Author:
cbratschi
Message:

merged with Corel WINE 20000513, added new DPA_* functions

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/comctl32/tab.cpp

    r3369 r3585  
    1 /* $Id: tab.cpp,v 1.3 2000-04-12 16:38:59 cbratschi Exp $ */
     1/* $Id: tab.cpp,v 1.4 2000-05-22 17:25:11 cbratschi Exp $ */
    22/*
    33 * Tab control
     
    1212 *  Image list support
    1313 *  Multiline support
    14  *  Unicode support
    1514 */
    1615
    1716/* inconsistent: report! */
    1817/*
    19  - Corel WINE 20000317 level
     18 - Corel WINE 20000513 level
    2019 - (WINE 991212 level)
    2120*/
     
    4948
    5049/******************************************************************************
     50 * Hot-tracking timer constants
     51 */
     52#define TAB_HOTTRACK_TIMER            1
     53#define TAB_HOTTRACK_TIMER_INTERVAL   100   /* milliseconds */
     54
     55/******************************************************************************
    5156 * Prototypes
    5257 */
     
    5459static void TAB_InvalidateTabArea(HWND      hwnd, TAB_INFO* infoPtr);
    5560static void TAB_EnsureSelectionVisible(HWND hwnd, TAB_INFO* infoPtr);
     61static void TAB_DrawItem(HWND hwnd, HDC hdc, INT iItem);
     62static void TAB_DrawItemInterior(HWND hwnd, HDC hdc, INT iItem, RECT* drawRect);
    5663
    5764static VOID
     
    123130  if ((iItem < 0) || (iItem >= infoPtr->uNumItem)) return 0;
    124131
    125   infoPtr->uFocus=iItem;
    126   if (GetWindowLongA(hwnd, GWL_STYLE) & TCS_BUTTONS) {
    127 //    FIXME (tab,"Should set input focus\n");
    128   } else {
    129     if (infoPtr->iSelected != iItem) {
    130       if (sendNotify(hwnd,TCN_SELCHANGING) != TRUE)  {
     132  if (GetWindowLongA(hwnd, GWL_STYLE) & TCS_BUTTONS)
     133  {
     134    //FIXME (tab,"Should set input focus\n");
     135  } else
     136  {
     137    if (infoPtr->iSelected != iItem || infoPtr->uFocus == -1)
     138    {
     139      infoPtr->uFocus = iItem;
     140      if (sendNotify(hwnd,TCN_SELCHANGING) != TRUE)
     141      {
    131142        infoPtr->iSelected = iItem;
    132143        sendNotify(hwnd,TCN_SELCHANGE);
     
    166177  RECT*       selectedRect)
    167178{
    168   RECT tmpItemRect;
     179  RECT tmpItemRect,clientRect;
     180  LONG        lStyle  = GetWindowLongA(hwnd, GWL_STYLE);
    169181
    170182  /*
    171183   * Perform a sanity check and a trivial visibility check.
    172184   */
    173   if ( (infoPtr->uNumItem == 0) ||
     185  if ( (infoPtr->uNumItem <= 0) ||
    174186       (itemIndex >= infoPtr->uNumItem) ||
    175        (itemIndex < infoPtr->leftmostVisible) )
     187       (!(lStyle &TCS_MULTILINE) && (itemIndex < infoPtr->leftmostVisible)) )
    176188    return FALSE;
    177189
     
    187199   */
    188200  *itemRect = infoPtr->items[itemIndex].rect;
     201
     202  /*
     203   * calculate the times bottom and top based on the row
     204   */
     205  GetClientRect(hwnd, &clientRect);
     206
     207  if (lStyle & TCS_BOTTOM)
     208  {
     209    itemRect->bottom = clientRect.bottom -
     210                      SELECTED_TAB_OFFSET -
     211                      itemRect->top * (infoPtr->tabHeight - 2);
     212
     213    itemRect->top = clientRect.bottom -
     214                   infoPtr->tabHeight -
     215                   itemRect->top * ( infoPtr->tabHeight - 2);
     216  }
     217  else
     218  {
     219    itemRect->bottom = clientRect.top +
     220                      infoPtr->tabHeight +
     221                      itemRect->top * (infoPtr->tabHeight - 2);
     222    itemRect->top = clientRect.top +
     223                   SELECTED_TAB_OFFSET+
     224                   itemRect->top * (infoPtr->tabHeight - 2);
     225 }
    189226
    190227  /*
     
    409446TAB_LButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam)
    410447{
     448  sendNotify(hwnd,NM_CLICK);
     449
     450  return 0;
     451}
     452
     453static LRESULT
     454TAB_RButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
     455{
     456  sendNotify(hwnd,NM_RCLICK);
     457
     458  return 0;
     459}
     460
     461/******************************************************************************
     462 * TAB_DrawLoneItemInterior
     463 *
     464 * This calls TAB_DrawItemInterior.  However, TAB_DrawItemInterior is normally
     465 * called by TAB_DrawItem which is normally called by TAB_Refresh which sets
     466 * up the device context and font.  This routine does the same setup but
     467 * only calls TAB_DrawItemInterior for the single specified item.
     468 */
     469static void
     470TAB_DrawLoneItemInterior(HWND hwnd, TAB_INFO* infoPtr, int iItem)
     471{
     472  HDC hdc = GetDC(hwnd);
     473  HFONT hOldFont = SelectObject(hdc, infoPtr->hFont);
     474  TAB_DrawItemInterior(hwnd, hdc, iItem, NULL);
     475  SelectObject(hdc, hOldFont);
     476  ReleaseDC(hwnd, hdc);
     477}
     478
     479/******************************************************************************
     480 * TAB_HotTrackTimerProc
     481 *
     482 * When a mouse-move event causes a tab to be highlighted (hot-tracking), a
     483 * timer is setup so we can check if the mouse is moved out of our window.
     484 * (We don't get an event when the mouse leaves, the mouse-move events just
     485 * stop being delivered to our window and just start being delivered to
     486 * another window.)  This function is called when the timer triggers so
     487 * we can check if the mouse has left our window.  If so, we un-highlight
     488 * the hot-tracked tab.
     489 */
     490static VOID CALLBACK
     491TAB_HotTrackTimerProc
     492  (
     493  HWND hwnd,    // handle of window for timer messages
     494  UINT uMsg,    // WM_TIMER message
     495  UINT idEvent, // timer identifier
     496  DWORD dwTime  // current system time
     497  )
     498{
     499  TAB_INFO* infoPtr = TAB_GetInfoPtr(hwnd);
     500
     501  if (infoPtr != NULL && infoPtr->iHotTracked >= 0)
     502  {
     503    POINT pt;
     504
     505    /*
     506    ** If we can't get the cursor position, or if the cursor is outside our
     507    ** window, we un-highlight the hot-tracked tab.  Note that the cursor is
     508    ** "outside" even if it is within our bounding rect if another window
     509    ** overlaps.  Note also that the case where the cursor stayed within our
     510    ** window but has moved off the hot-tracked tab will be handled by the
     511    ** WM_MOUSEMOVE event.
     512    */
     513    if (!GetCursorPos(&pt) || WindowFromPoint(pt) != hwnd)
     514    {
     515      // Redraw iHotTracked to look normal
     516      INT iRedraw = infoPtr->iHotTracked;
     517      infoPtr->iHotTracked = -1;
     518      TAB_DrawLoneItemInterior(hwnd, infoPtr, iRedraw);
     519
     520      // Kill this timer
     521      KillTimer(hwnd, TAB_HOTTRACK_TIMER);
     522    }
     523  }
     524}
     525
     526/******************************************************************************
     527 * TAB_RecalcHotTrack
     528 *
     529 * If a tab control has the TCS_HOTTRACK style, then the tab under the mouse
     530 * should be highlighted.  This function determines which tab in a tab control,
     531 * if any, is under the mouse and records that information.  The caller may
     532 * supply output parameters to receive the item number of the tab item which
     533 * was highlighted but isn't any longer and of the tab item which is now
     534 * highlighted but wasn't previously.  The caller can use this information to
     535 * selectively redraw those tab items.
     536 *
     537 * If the caller has a mouse position, it can supply it through the pos
     538 * parameter.  For example, TAB_MouseMove does this.  Otherwise, the caller
     539 * supplies NULL and this function determines the current mouse position
     540 * itself.
     541 */
     542static void
     543TAB_RecalcHotTrack
     544  (
     545  HWND            hwnd,
     546  const LPARAM*   pos,
     547  int*            out_redrawLeave,
     548  int*            out_redrawEnter
     549  )
     550{
     551  TAB_INFO* infoPtr = TAB_GetInfoPtr(hwnd);
     552
     553  int item = -1;
     554
     555
     556  if (out_redrawLeave != NULL)
     557    *out_redrawLeave = -1;
     558  if (out_redrawEnter != NULL)
     559    *out_redrawEnter = -1;
     560
     561  if (GetWindowLongA(hwnd, GWL_STYLE) & TCS_HOTTRACK)
     562  {
     563    POINT pt;
     564    UINT  flags;
     565
     566    if (pos == NULL)
     567    {
     568      GetCursorPos(&pt);
     569      ScreenToClient(hwnd, &pt);
     570    }
     571    else
     572    {
     573      pt.x = LOWORD(*pos);
     574      pt.y = HIWORD(*pos);
     575    }
     576
     577    item = TAB_InternalHitTest(hwnd, infoPtr, pt, &flags);
     578  }
     579
     580  if (item != infoPtr->iHotTracked)
     581  {
     582    if (infoPtr->iHotTracked >= 0)
     583    {
     584      // Mark currently hot-tracked to be redrawn to look normal
     585      if (out_redrawLeave != NULL)
     586        *out_redrawLeave = infoPtr->iHotTracked;
     587
     588      if (item < 0)
     589      {
     590        // Kill timer which forces recheck of mouse pos
     591        KillTimer(hwnd, TAB_HOTTRACK_TIMER);
     592      }
     593    }
     594    else
     595    {
     596      // Start timer so we recheck mouse pos
     597      UINT timerID = SetTimer
     598        (
     599        hwnd,
     600        TAB_HOTTRACK_TIMER,
     601        TAB_HOTTRACK_TIMER_INTERVAL,
     602        TAB_HotTrackTimerProc
     603        );
     604
     605      if (timerID == 0)
     606        return; /* Hot tracking not available */
     607    }
     608
     609    infoPtr->iHotTracked = item;
     610
     611    if (item >= 0)
     612    {
     613      // Mark new hot-tracked to be redrawn to look highlighted
     614      if (out_redrawEnter != NULL)
     615        *out_redrawEnter = item;
     616    }
     617  }
     618}
     619
     620/******************************************************************************
     621 * TAB_MouseMove
     622 *
     623 * Handles the mouse-move event.  Updates tooltips.  Updates hot-tracking.
     624 */
     625static LRESULT
     626TAB_MouseMove (HWND hwnd, WPARAM wParam, LPARAM lParam)
     627{
     628  int redrawLeave;
     629  int redrawEnter;
     630
    411631  TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
    412   POINT pt;
    413   INT newItem;
    414   UINT dummy;
    415632
    416633  if (infoPtr->hwndToolTip)
     
    418635                    WM_LBUTTONDOWN, wParam, lParam);
    419636
    420   pt.x = (INT)LOWORD(lParam);
    421   pt.y = (INT)HIWORD(lParam);
    422 
    423   newItem=TAB_InternalHitTest (hwnd, infoPtr,pt,&dummy);
    424 
    425 //  TRACE(tab, "On Tab, item %d\n", newItem);
    426 
    427   if ( (newItem!=-1) &&
    428        (infoPtr->iSelected != newItem) )
    429   {
    430     if (sendNotify(hwnd,TCN_SELCHANGING) != TRUE)
    431     {
    432       infoPtr->iSelected = newItem;
    433       infoPtr->uFocus    = newItem;
    434       sendNotify(hwnd,TCN_SELCHANGE);
    435 
    436       TAB_EnsureSelectionVisible(hwnd, infoPtr);
    437 
    438       TAB_InvalidateTabArea(hwnd, infoPtr);
    439     }
    440   }
    441   sendNotify(hwnd,NM_CLICK);
    442 
    443   return 0;
    444 }
    445 
    446 static LRESULT
    447 TAB_RButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
    448 {
    449   sendNotify(hwnd,NM_RCLICK);
    450 
    451   return 0;
    452 }
    453 
    454 static LRESULT
    455 TAB_MouseMove (HWND hwnd, WPARAM wParam, LPARAM lParam)
    456 {
    457   TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
    458 
    459   if (infoPtr->hwndToolTip)
    460     TAB_RelayEvent (infoPtr->hwndToolTip, hwnd,
    461                     WM_LBUTTONDOWN, wParam, lParam);
     637  /* Determine which tab to highlight.  Redraw tabs which change highlight
     638  ** status. */
     639  TAB_RecalcHotTrack(hwnd, &lParam, &redrawLeave, &redrawEnter);
     640
     641  if (redrawLeave != -1)
     642    TAB_DrawLoneItemInterior(hwnd, infoPtr, redrawLeave);
     643  if (redrawEnter != -1)
     644    TAB_DrawLoneItemInterior(hwnd, infoPtr, redrawEnter);
     645
    462646  return 0;
    463647}
     
    486670     */
    487671    if (GetWindowLongA(hwnd, GWL_STYLE) & TCS_BOTTOM)
    488       prc->bottom += infoPtr->tabHeight;
     672      prc->bottom += (infoPtr->tabHeight - 2) * (infoPtr->uNumRows + 1) + 2;
    489673    else
    490       prc->top -= infoPtr->tabHeight;
     674      prc->top -= (infoPtr->tabHeight - 2) * (infoPtr->uNumRows + 1) + 2;
    491675
    492676    /*
     
    520704     */
    521705    if (GetWindowLongA(hwnd, GWL_STYLE) & TCS_BOTTOM)
    522       prc->bottom -= infoPtr->tabHeight;
     706      prc->bottom -= (infoPtr->tabHeight - 2) * (infoPtr->uNumRows + 1) + 2;
    523707    else
    524       prc->top += infoPtr->tabHeight;
     708      prc->top += (infoPtr->tabHeight - 2) * (infoPtr->uNumRows + 1) + 2;
    525709
    526710  }
     
    543727  TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
    544728
    545   if (nScrollCode == SB_LINELEFT)
    546   {
    547     if (infoPtr->leftmostVisible>0)
    548     {
    549       infoPtr->leftmostVisible--;
    550 
    551       TAB_InvalidateTabArea(hwnd, infoPtr);
    552     }
    553   }
    554   else if (nScrollCode == SB_LINERIGHT)
    555   {
    556     if (infoPtr->leftmostVisible< (infoPtr->uNumItem-1))
    557     {
    558       infoPtr->leftmostVisible++;
    559 
    560       TAB_InvalidateTabArea(hwnd, infoPtr);
    561     }
    562   }
    563 
    564   return 0;
     729  if(nScrollCode == SB_THUMBPOSITION && nPos != infoPtr->leftmostVisible)
     730  {
     731     if(nPos < infoPtr->leftmostVisible)
     732        infoPtr->leftmostVisible--;
     733     else
     734        infoPtr->leftmostVisible++;
     735
     736     TAB_RecalcHotTrack(hwnd, NULL, NULL, NULL);
     737     TAB_InvalidateTabArea(hwnd, infoPtr);
     738     SendMessageA(infoPtr->hwndUpDown, UDM_SETPOS, 0,
     739                   MAKELONG(infoPtr->leftmostVisible, 0));
     740   }
     741
     742   return 0;
    565743}
    566744
     
    576754  const RECT* clientRect)
    577755{
     756  INT maxRange = 0;
     757
    578758  if (infoPtr->needsScrolling)
    579759  {
    580760    RECT controlPos;
     761    INT vsize, tabwidth;
    581762
    582763    /*
     
    607788       * control.
    608789       */
    609       infoPtr->hwndUpDown = CreateWindowA("ScrollBar",
    610                                           "",
    611                                           WS_VISIBLE | WS_CHILD | WS_OVERLAPPED | SBS_HORZ,
     790      infoPtr->hwndUpDown = CreateWindowA("msctls_updown32",
     791                                          "",
     792                                          WS_VISIBLE | WS_CHILD | UDS_HORZ,
    612793                                          controlPos.left, controlPos.top,
    613794                                          controlPos.right - controlPos.left,
     
    627808                   SWP_SHOWWINDOW | SWP_NOZORDER);
    628809    }
     810
     811    /* Now calculate upper limit of the updown control range.
     812     * We do this by calculating how many tabs will be offscreen when the
     813     * last tab is visible.
     814     */
     815    if(infoPtr->uNumItem)
     816    {
     817       vsize = clientRect->right - (controlPos.right - controlPos.left + 1);
     818       maxRange = infoPtr->uNumItem;
     819       tabwidth = infoPtr->items[maxRange-1].rect.right;
     820
     821       for(; maxRange > 0; maxRange--)
     822       {
     823          if(tabwidth - infoPtr->items[maxRange - 1].rect.left > vsize)
     824             break;
     825       }
     826
     827       if(maxRange == infoPtr->uNumItem)
     828          maxRange--;
     829    }
    629830  }
    630831  else
     
    638839    }
    639840  }
     841
     842  if (infoPtr->hwndUpDown)
     843     SendMessageA(infoPtr->hwndUpDown, UDM_SETRANGE32, 0, maxRange);
    640844}
    641845
     
    657861  INT         curItem;
    658862  INT         curItemLeftPos;
     863  INT         curItemRowCount;
    659864  HFONT       hFont, hOldFont;
    660865  HDC         hdc;
     
    681886   */
    682887  curItemLeftPos = 0;
    683 
    684   if (!((lStyle & TCS_FIXEDWIDTH) || (lStyle & TCS_OWNERDRAWFIXED)))
     888  curItemRowCount = 0;
     889
     890  if (!(lStyle & TCS_FIXEDWIDTH) && !((lStyle & TCS_OWNERDRAWFIXED) && infoPtr->fSizeSet))
    685891  {
    686892    int item_height;
     
    717923  {
    718924    /*
    719      * Calculate the vertical position of the tab
    720      */
    721     if (lStyle & TCS_BOTTOM)
    722     {
    723       infoPtr->items[curItem].rect.bottom = clientRect.bottom -
    724                                             SELECTED_TAB_OFFSET;
    725       infoPtr->items[curItem].rect.top = clientRect.bottom -
    726                                          infoPtr->tabHeight;
    727     }
    728     else
    729     {
    730       infoPtr->items[curItem].rect.top = clientRect.top +
    731                                          SELECTED_TAB_OFFSET;
    732       infoPtr->items[curItem].rect.bottom = clientRect.top +
    733                                             infoPtr->tabHeight;
    734     }
    735 
    736     /*
    737925     * Set the leftmost position of the tab.
    738926     */
    739927    infoPtr->items[curItem].rect.left = curItemLeftPos;
    740928
    741     if ((lStyle & TCS_FIXEDWIDTH) || (lStyle & TCS_OWNERDRAWFIXED))
     929    if ((lStyle & TCS_FIXEDWIDTH) || ((lStyle & TCS_OWNERDRAWFIXED) && infoPtr->fSizeSet))
    742930    {
    743931      infoPtr->items[curItem].rect.right = infoPtr->items[curItem].rect.left +
     
    753941       * Calculate how wide the tab is depending on the text it contains
    754942       */
    755       //SvL: Bugfix: text is unicode, not ascii
    756943      GetTextExtentPoint32W(hdc, infoPtr->items[curItem].pszText,
    757944                            lstrlenW(infoPtr->items[curItem].pszText), &size);
     
    771958    }
    772959
     960    /*
     961     * Check if this is a multiline tab control and if so
     962     * check to see if we should wrap the tabs
     963     *
     964     * Because we are going to arange all these tabs evenly
     965     * really we are basically just counting rows at this point
     966     *
     967     */
     968
     969    if ((lStyle & TCS_MULTILINE)&&
     970        (infoPtr->items[curItem].rect.right > clientRect.right))
     971    {
     972        infoPtr->items[curItem].rect.right -=
     973                                      infoPtr->items[curItem].rect.left;
     974        infoPtr->items[curItem].rect.left = 0;
     975        curItemRowCount ++;
     976    }
     977
     978    infoPtr->items[curItem].rect.bottom = 0;
     979    infoPtr->items[curItem].rect.top = curItemRowCount;
     980
    773981//    TRACE("TextSize: %i\n ", size.cx);
    774982//    TRACE("Rect: T %i, L %i, B %i, R %i\n",
     
    788996  }
    789997
    790   /*
    791    * Check if we need a scrolling control.
    792    */
    793   infoPtr->needsScrolling = (curItemLeftPos + (2*SELECTED_TAB_OFFSET) >
    794                              clientRect.right);
    795 
    796   /* Don't need scrolling, then update infoPtr->leftmostVisible */
    797   if(!infoPtr->needsScrolling)
    798     infoPtr->leftmostVisible = 0;
    799 
    800   TAB_SetupScrolling(hwnd, infoPtr, &clientRect);
     998  if (!(lStyle & TCS_MULTILINE))
     999  {
     1000    /*
     1001     * Check if we need a scrolling control.
     1002     */
     1003    infoPtr->needsScrolling = (curItemLeftPos + (2*SELECTED_TAB_OFFSET) >
     1004                               clientRect.right);
     1005
     1006    /* Don't need scrolling, then update infoPtr->leftmostVisible */
     1007    if(!infoPtr->needsScrolling)
     1008      infoPtr->leftmostVisible = 0;
     1009
     1010    TAB_SetupScrolling(hwnd, infoPtr, &clientRect);
     1011  }
     1012
     1013  /*
     1014   * Set the number of rows
     1015   */
     1016
     1017  infoPtr->uNumRows = curItemRowCount;
     1018
     1019   if ((lStyle & TCS_MULTILINE)&&(infoPtr->uNumItem > 0))
     1020   {
     1021      INT widthDiff,remainder;
     1022      INT tabPerRow,remTab;
     1023      INT iRow,iItm;
     1024      INT iIndexStart=0,iIndexEnd=0, iCount=0;
     1025
     1026      /*
     1027       * Ok Microsoft trys to even out the rows. place the same
     1028       * number of tabs in each row. So lets give that a shot
     1029       *
     1030       */
     1031
     1032      tabPerRow = infoPtr->uNumItem / (infoPtr->uNumRows + 1);
     1033      remTab = infoPtr->uNumItem % (infoPtr->uNumRows + 1);
     1034
     1035      for (iItm=0,iRow=0,iCount=0,curItemLeftPos=0;
     1036           iItm<infoPtr->uNumItem;
     1037           iItm++,iCount++)
     1038      {
     1039          if (iCount >= ((iRow<remTab)?tabPerRow+1:tabPerRow))
     1040          {
     1041              iRow++;
     1042              curItemLeftPos = 0;
     1043              iCount = 0;
     1044          }
     1045          /*
     1046           * normalize the current rect
     1047           */
     1048          infoPtr->items[iItm].rect.right -=
     1049            infoPtr->items[iItm].rect.left;
     1050          infoPtr->items[iItm].rect.left = 0;
     1051
     1052          infoPtr->items[iItm].rect.top = iRow;
     1053          infoPtr->items[iItm].rect.left +=curItemLeftPos;
     1054          infoPtr->items[iItm].rect.right +=curItemLeftPos;
     1055          if (lStyle & TCS_BUTTONS)
     1056            curItemLeftPos = infoPtr->items[iItm].rect.right +
     1057                             BUTTON_SPACINGX;
     1058          else
     1059            curItemLeftPos = infoPtr->items[iItm].rect.right;
     1060      }
     1061
     1062      /*
     1063       * Justify the rows
     1064       *
     1065       */
     1066      {
     1067         while(iIndexStart < infoPtr->uNumItem)
     1068        {
     1069        /*
     1070         * find the indexs of the row
     1071         */
     1072        for (iIndexEnd=iIndexStart;
     1073             (iIndexEnd < infoPtr->uNumItem) &&
     1074               (infoPtr->items[iIndexEnd].rect.top ==
     1075                infoPtr->items[iIndexStart].rect.top) ;
     1076            iIndexEnd++)
     1077        /* intentionaly blank */;
     1078
     1079        /*
     1080         * we need to justify these tabs so they fill the whole given
     1081         * client area
     1082         *
     1083         */
     1084        widthDiff = clientRect.right - (2*SELECTED_TAB_OFFSET) -
     1085                            infoPtr->items[iIndexEnd-1].rect.right;
     1086
     1087        iCount = iIndexEnd-iIndexStart;
     1088
     1089        if (iCount)
     1090        {
     1091           INT iIndex;
     1092           remainder = widthDiff % iCount;
     1093           widthDiff = widthDiff / iCount;
     1094           for (iIndex=iIndexStart,iCount=0; iIndex < iIndexEnd;
     1095                iIndex++,iCount++)
     1096           {
     1097              infoPtr->items[iIndex].rect.left +=iCount*widthDiff;
     1098              infoPtr->items[iIndex].rect.right +=(iCount+1)*widthDiff;
     1099           }
     1100           infoPtr->items[iIndex-1].rect.right += remainder;
     1101        }
     1102
     1103        iIndexStart=iIndexEnd;
     1104        }
     1105      }
     1106  }
     1107
     1108  TAB_EnsureSelectionVisible(hwnd,infoPtr);
     1109  TAB_RecalcHotTrack(hwnd, NULL, NULL, NULL);
    8011110
    8021111  /*
     
    8051114  SelectObject (hdc, hOldFont);
    8061115  ReleaseDC (hwnd, hdc);
     1116}
     1117
     1118/******************************************************************************
     1119 * TAB_DrawItemInterior
     1120 *
     1121 * This method is used to draw the interior (text and icon) of a single tab
     1122 * into the tab control.
     1123 */
     1124static void
     1125TAB_DrawItemInterior
     1126  (
     1127  HWND        hwnd,
     1128  HDC         hdc,
     1129  INT         iItem,
     1130  RECT*       drawRect
     1131  )
     1132{
     1133  TAB_INFO* infoPtr = TAB_GetInfoPtr(hwnd);
     1134  LONG      lStyle  = GetWindowLongA(hwnd, GWL_STYLE);
     1135
     1136  RECT localRect;
     1137
     1138  HPEN   htextPen   = GetSysColorPen (COLOR_BTNTEXT);
     1139  HPEN   holdPen;
     1140  INT    oldBkMode;
     1141
     1142  if (drawRect == NULL)
     1143  {
     1144    BOOL isVisible;
     1145    RECT itemRect;
     1146    RECT selectedRect;
     1147
     1148    /*
     1149     * Get the rectangle for the item.
     1150     */
     1151    isVisible = TAB_InternalGetItemRect
     1152      (
     1153      hwnd,
     1154      infoPtr,
     1155      iItem,
     1156      &itemRect,
     1157      &selectedRect
     1158      );
     1159    if (!isVisible)
     1160      return;
     1161
     1162    /*
     1163     * Make sure drawRect points to something valid; simplifies code.
     1164     */
     1165    drawRect = &localRect;
     1166
     1167    /*
     1168     * This logic copied from the part of TAB_DrawItem which draws
     1169     * the tab background.  It's important to keep it in sync.  I
     1170     * would have liked to avoid code duplication, but couldn't figure
     1171     * out how without making spaghetti of TAB_DrawItem.
     1172     */
     1173    if (lStyle & TCS_BUTTONS)
     1174    {
     1175      *drawRect = itemRect;
     1176      if (iItem == infoPtr->iSelected)
     1177      {
     1178        drawRect->right--;
     1179        drawRect->bottom--;
     1180      }
     1181    }
     1182    else
     1183    {
     1184      if (iItem == infoPtr->iSelected)
     1185        *drawRect = selectedRect;
     1186      else
     1187        *drawRect = itemRect;
     1188      drawRect->right--;
     1189      drawRect->bottom--;
     1190    }
     1191  }
     1192
     1193  /*
     1194   * Text pen
     1195   */
     1196  holdPen = SelectObject(hdc, htextPen);
     1197
     1198  oldBkMode = SetBkMode(hdc, TRANSPARENT);
     1199  SetTextColor
     1200    (
     1201    hdc,
     1202    GetSysColor
     1203      (
     1204      (iItem == infoPtr->iHotTracked) ? COLOR_HIGHLIGHT : COLOR_BTNTEXT
     1205      )
     1206    );
     1207
     1208  /*
     1209   * Deflate the rectangle to acount for the padding
     1210   */
     1211  InflateRect(drawRect, -HORIZONTAL_ITEM_PADDING, -VERTICAL_ITEM_PADDING);
     1212
     1213  /*
     1214   * if owner draw, tell the owner to draw
     1215   */
     1216  if ( (lStyle & TCS_OWNERDRAWFIXED) && GetParent(hwnd) )
     1217  {
     1218    DRAWITEMSTRUCT dis;
     1219    UINT id;
     1220
     1221    /*
     1222     * get the control id
     1223     */
     1224    id = GetWindowLongA(hwnd,GWL_ID);
     1225
     1226    /*
     1227     * put together the DRAWITEMSTRUCT
     1228     */
     1229    dis.CtlType    = ODT_TAB;   
     1230    dis.CtlID      = id;               
     1231    dis.itemID     = iItem;             
     1232    dis.itemAction = ODA_DRAWENTIRE;   
     1233    if ( iItem == infoPtr->iSelected )
     1234      dis.itemState = ODS_SELECTED;     
     1235    else                               
     1236      dis.itemState = 0;               
     1237    dis.hwndItem = hwnd;                /* */
     1238    dis.hDC      = hdc;         
     1239    dis.rcItem   = *drawRect;           /* */
     1240    dis.itemData = infoPtr->items[iItem].lParam;
     1241
     1242    /*
     1243     * send the draw message
     1244     */
     1245    SendMessageA( GetParent(hwnd), WM_DRAWITEM, (WPARAM)id, (LPARAM)&dis );
     1246  }
     1247  else
     1248  {
     1249    UINT uHorizAlign;
     1250
     1251    /*
     1252     * If not owner draw, then do the drawing ourselves.
     1253     *
     1254     * Draw the icon.
     1255     */
     1256    if (infoPtr->himl && (infoPtr->items[iItem].mask & TCIF_IMAGE))
     1257    {
     1258      INT cx;
     1259      INT cy;
     1260
     1261      ImageList_Draw
     1262        (
     1263        infoPtr->himl,
     1264        infoPtr->items[iItem].iImage,
     1265        hdc,
     1266        drawRect->left,
     1267        drawRect->top + 1,
     1268        ILD_NORMAL
     1269        );
     1270      ImageList_GetIconSize(infoPtr->himl, &cx, &cy);
     1271      drawRect->left += (cx + HORIZONTAL_ITEM_PADDING);
     1272    }
     1273
     1274    /*
     1275     * Draw the text;
     1276     */
     1277    if (lStyle & TCS_RIGHTJUSTIFY)
     1278      uHorizAlign = DT_CENTER;
     1279    else
     1280      uHorizAlign = DT_LEFT;
     1281
     1282    DrawTextW
     1283      (
     1284      hdc,
     1285      infoPtr->items[iItem].pszText,
     1286      lstrlenW(infoPtr->items[iItem].pszText),
     1287      drawRect,
     1288      uHorizAlign | DT_SINGLELINE | DT_VCENTER
     1289      );
     1290  }
     1291
     1292  /*
     1293  * Cleanup
     1294  */
     1295  SetBkMode(hdc, oldBkMode);
     1296  SelectObject(hdc, holdPen);
    8071297}
    8081298
     
    8381328    HPEN   hwPen     = GetSysColorPen (COLOR_3DHILIGHT);
    8391329    HPEN   hbPen     = GetSysColorPen (COLOR_BTNSHADOW);
    840     HPEN   hsdPen    = GetSysColorPen (COLOR_BTNTEXT);
    8411330    HPEN   hfocusPen = CreatePen(PS_DOT, 1, GetSysColor(COLOR_BTNTEXT));
    8421331    HPEN   holdPen;
    8431332    INT    oldBkMode;
    844     INT    cx,cy;
    8451333    BOOL deleteBrush = TRUE;
    8461334
     
    8591347         * Background color.
    8601348         */
    861         if (!(lStyle & TCS_OWNERDRAWFIXED))
     1349        if (!((lStyle & TCS_OWNERDRAWFIXED) && infoPtr->fSizeSet))
    8621350        {
    8631351          COLORREF bk = GetSysColor(COLOR_3DHILIGHT);
     
    8671355          SetBkColor(hdc, bk);
    8681356
     1357          /* if COLOR_WINDOW happens to be the same as COLOR_3DHILIGHT
     1358           * we better use 0x55aa bitmap brush to make scrollbar's background
     1359           * look different from the window background.
     1360           */
     1361          if (bk == GetSysColor(COLOR_WINDOW))
     1362              hbr = GetPattern55AABrush();
     1363
     1364          deleteBrush = FALSE;
    8691365        }
    8701366
     
    9751471    }
    9761472
    977     /*
    978      * Text pen
    979      */
    980     SelectObject(hdc, hsdPen);
    981 
    9821473    oldBkMode = SetBkMode(hdc, TRANSPARENT);
    983     SetTextColor (hdc, COLOR_BTNTEXT);
    984 
    985     /*
    986      * Deflate the rectangle to acount for the padding
    987      */
    988     InflateRect(&r, -HORIZONTAL_ITEM_PADDING, -VERTICAL_ITEM_PADDING);
    989 
    990     /*
    991      * Draw the icon.
    992      */
    993     if (infoPtr->himl)
    994     {
    995       ImageList_Draw (infoPtr->himl, iItem, hdc,
    996                       r.left, r.top+1, ILD_NORMAL);
    997       ImageList_GetIconSize (infoPtr->himl, &cx, &cy);
    998       r.left+=(cx + HORIZONTAL_ITEM_PADDING);
    999     }
    1000 
    1001     /*
    1002      * Draw the text;
    1003      */
    1004     DrawTextW(hdc,
    1005               infoPtr->items[iItem].pszText,
    1006               lstrlenW(infoPtr->items[iItem].pszText),
    1007               &r,
    1008               DT_LEFT|DT_SINGLELINE|DT_VCENTER);
     1474
     1475    /* This modifies r to be the text rectangle. */
     1476    TAB_DrawItemInterior(hwnd, hdc, iItem, &r);
    10091477
    10101478    /*
     
    10321500    SelectObject(hdc, holdPen);
    10331501    DeleteObject(hfocusPen);
    1034     DeleteObject(hbr);
     1502    if (deleteBrush) DeleteObject(hbr);
    10351503  }
    10361504}
     
    10581526  if (GetWindowLongA(hwnd, GWL_STYLE) & TCS_BOTTOM)
    10591527  {
    1060     rect.bottom -= infoPtr->tabHeight;
     1528    rect.bottom -= (infoPtr->tabHeight - 2) * (infoPtr->uNumRows + 1) + 2;
    10611529  }
    10621530  else
    10631531  {
    1064     rect.top += infoPtr->tabHeight;
     1532    rect.top += (infoPtr->tabHeight - 2) * (infoPtr->uNumRows + 1) + 2;
    10651533  }
    10661534
     
    11371605     */
    11381606    TAB_DrawItem (hwnd, hdc, infoPtr->iSelected);
     1607
     1608    /*
     1609     * If we haven't set the current focus yet, set it now.
     1610     * Only happens when we first paint the tab controls.
     1611     */
     1612     if (infoPtr->uFocus == -1)
     1613       TAB_SetCurFocus(hwnd, infoPtr->iSelected);
    11391614  }
    11401615
     
    11841659  TAB_INFO* infoPtr)
    11851660{
    1186   RECT selectedRect;
    1187   RECT visibleRect;
    1188   RECT scrollerRect;
    1189   BOOL isVisible;
     1661  INT iSelected = infoPtr->iSelected;
     1662
     1663  INT iOrigLeftmostVisible = infoPtr->leftmostVisible;
     1664
     1665  /*
     1666   * set the items row to the bottommost row or topmost row depending on
     1667   * style
     1668   */
     1669
     1670  if (infoPtr->uNumRows > 0)
     1671  {
     1672      INT newselected=infoPtr->items[iSelected].rect.top;
     1673      INT iTargetRow;
     1674      LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
     1675
     1676      if (lStyle & TCS_BOTTOM)
     1677          iTargetRow = 0;
     1678      else
     1679          iTargetRow = infoPtr->uNumRows;
     1680
     1681      if (newselected != iTargetRow)
     1682      {
     1683         INT i;
     1684         for (i=0; i < infoPtr->uNumItem; i++)
     1685             if (infoPtr->items[i].rect.top == newselected )
     1686                 infoPtr->items[i].rect.top = iTargetRow;
     1687             else if (lStyle&TCS_BOTTOM)
     1688                 {
     1689                  if (infoPtr->items[i].rect.top < newselected)
     1690                     infoPtr->items[i].rect.top+=1;
     1691                 }
     1692                 else
     1693                 {
     1694                   if (infoPtr->items[i].rect.top > newselected)
     1695                     infoPtr->items[i].rect.top-=1;
     1696                 }
     1697
     1698        TAB_RecalcHotTrack(hwnd, NULL, NULL, NULL);
     1699      }
     1700  }
    11901701
    11911702  /*
     
    11961707    return;
    11971708
    1198   if (infoPtr->leftmostVisible > infoPtr->iSelected)
    1199   {
    1200     infoPtr->leftmostVisible = infoPtr->iSelected;
    1201     return;
    1202   }
    1203 
    1204   /*
    1205    * Calculate the part of the client area that is visible.
    1206    */
    1207   GetClientRect(hwnd, &visibleRect);
    1208   GetClientRect(infoPtr->hwndUpDown, &scrollerRect);
    1209   visibleRect.right -= scrollerRect.right;
    1210 
    1211   /*
    1212    * Get the rectangle for the item
    1213    */
    1214   isVisible = TAB_InternalGetItemRect(hwnd,
    1215                                       infoPtr,
    1216                                       infoPtr->iSelected,
    1217                                       NULL,
    1218                                       &selectedRect);
    1219 
    1220   /*
    1221    * If this function can't say it's completely invisible, maybe it
    1222    * is partially visible. Let's check.
    1223    */
    1224   if (isVisible)
    1225   {
    1226     POINT pt1;
    1227     POINT pt2;
    1228 
    1229     pt1.x = selectedRect.left;
    1230     pt1.y = selectedRect.top;
    1231     pt2.x = selectedRect.right - 1;
    1232     pt2.y = selectedRect.bottom - 1;
    1233 
    1234     isVisible = PtInRect(&visibleRect, pt1) &&  PtInRect(&visibleRect, pt2);
    1235   }
    1236 
    1237   while ( (infoPtr->leftmostVisible < infoPtr->iSelected) &&
    1238           !isVisible)
    1239   {
    1240     infoPtr->leftmostVisible++;
    1241 
    1242     /*
    1243      * Get the rectangle for the item
    1244      */
    1245     isVisible = TAB_InternalGetItemRect(hwnd,
    1246                                         infoPtr,
    1247                                         infoPtr->iSelected,
    1248                                         NULL,
    1249                                         &selectedRect);
    1250 
    1251     /*
    1252      * If this function can't say it's completely invisible, maybe it
    1253      * is partially visible. Let's check.
    1254      */
    1255     if (isVisible)
    1256     {
    1257       POINT pt1;
    1258       POINT pt2;
    1259 
    1260       pt1.x = selectedRect.left;
    1261       pt1.y = selectedRect.top;
    1262       pt2.x = selectedRect.right - 1;
    1263       pt2.y = selectedRect.bottom - 1;
    1264 
    1265       isVisible = PtInRect(&visibleRect, pt1) &&  PtInRect(&visibleRect, pt2);
    1266     }
    1267   }
     1709  if (infoPtr->leftmostVisible >= iSelected)
     1710  {
     1711    infoPtr->leftmostVisible = iSelected;
     1712  }
     1713  else
     1714  {
     1715     RECT r;
     1716     INT  width, i;
     1717     /*
     1718      * Calculate the part of the client area that is visible.
     1719      */
     1720     GetClientRect(hwnd, &r);
     1721     width = r.right;
     1722
     1723     GetClientRect(infoPtr->hwndUpDown, &r);
     1724     width -= r.right;
     1725
     1726     if ((infoPtr->items[iSelected].rect.right -
     1727          infoPtr->items[iSelected].rect.left) >= width )
     1728     {
     1729        /* Special case: width of selected item is greater than visible
     1730         * part of control.
     1731         */
     1732        infoPtr->leftmostVisible = iSelected;
     1733     }
     1734     else
     1735     {
     1736        for (i = infoPtr->leftmostVisible; i < infoPtr->uNumItem; i++)
     1737        {
     1738           if ((infoPtr->items[iSelected].rect.right -
     1739                infoPtr->items[i].rect.left) < width)
     1740              break;
     1741        }
     1742        infoPtr->leftmostVisible = i;
     1743     }
     1744  }
     1745
     1746  if (infoPtr->leftmostVisible != iOrigLeftmostVisible)
     1747    TAB_RecalcHotTrack(hwnd, NULL, NULL, NULL);
     1748
     1749  SendMessageA(infoPtr->hwndUpDown, UDM_SETPOS, 0,
     1750               MAKELONG(infoPtr->leftmostVisible, 0));
    12681751}
    12691752
     
    12851768  if (GetWindowLongA(hwnd, GWL_STYLE) & TCS_BOTTOM)
    12861769  {
    1287     clientRect.top = clientRect.bottom - (infoPtr->tabHeight + 1);
     1770    clientRect.top = clientRect.bottom - (infoPtr->tabHeight *
     1771                                           (infoPtr->uNumRows + 1) + 3);
    12881772  }
    12891773  else
    12901774  {
    1291     clientRect.bottom = clientRect.top + (infoPtr->tabHeight + 1);
     1775    clientRect.bottom = clientRect.top + (infoPtr->tabHeight *
     1776                                           (infoPtr->uNumRows + 1) + 1);
    12921777  }
    12931778
     
    14621947  }
    14631948
     1949  infoPtr->fSizeSet = TRUE;
     1950
    14641951  return lResult;
    14651952}
     
    14941981  if (tabItem->mask & TCIF_TEXT) {
    14951982   len=lstrlenA (tabItem->pszText);
    1496    if (len>wineItem->cchTextMax)
    1497      wineItem->pszText= (WCHAR*)COMCTL32_ReAlloc (wineItem->pszText, len+1);
    1498    lstrcpyA ((LPSTR)wineItem->pszText, tabItem->pszText);
     1983   if (len > wineItem->cchTextMax)
     1984     wineItem->pszText = (WCHAR*)COMCTL32_ReAlloc(wineItem->pszText,(len+1)*sizeof(WCHAR));
     1985   lstrcpyAtoW(wineItem->pszText,tabItem->pszText);
    14991986  }
    15001987
     
    16732160  infoPtr->uNumItem = 0;
    16742161  infoPtr->iSelected = -1;
     2162  if (infoPtr->iHotTracked >= 0)
     2163    KillTimer(hwnd, TAB_HOTTRACK_TIMER);
     2164  infoPtr->iHotTracked = -1;
     2165
     2166  TAB_SetItemBounds(hwnd);
     2167  TAB_InvalidateTabArea(hwnd,infoPtr);
    16752168
    16762169  return TRUE;
     
    17812274
    17822275  infoPtr->uNumItem        = 0;
     2276  infoPtr->uNumRows        = 0;
    17832277  infoPtr->hFont           = 0;
    17842278  infoPtr->items           = 0;
    17852279  infoPtr->hcurArrow       = LoadCursorA (0, IDC_ARROWA);
    17862280  infoPtr->iSelected       = -1;
    1787   infoPtr->uFocus          = 0;
     2281  infoPtr->iHotTracked     = -1;
     2282  infoPtr->uFocus          = -1;
    17882283  infoPtr->hwndToolTip     = 0;
    17892284  infoPtr->DoRedraw        = TRUE;
     
    17912286  infoPtr->hwndUpDown      = 0;
    17922287  infoPtr->leftmostVisible = 0;
     2288  infoPtr->fSizeSet        = FALSE;
    17932289
    17942290  /* The tab control always has the WS_CLIPSIBLINGS style. Even
     
    18472343  }
    18482344
    1849   if (infoPtr->hwndToolTip)
    1850     DestroyWindow (infoPtr->hwndToolTip);
    1851 
    1852   if (infoPtr->hwndUpDown)
    1853     DestroyWindow(infoPtr->hwndUpDown);
     2345  if (infoPtr->iHotTracked >= 0)
     2346    KillTimer(hwnd, TAB_HOTTRACK_TIMER);
    18542347
    18552348  doneControl(hwnd);
     2349
     2350  return 0;
     2351}
     2352
     2353static LRESULT TAB_StyleChanged(HWND hwnd,WPARAM wParam,LPARAM lParam)
     2354{
     2355  TAB_SetItemBounds (hwnd);
     2356  InvalidateRect(hwnd, NULL, TRUE);
    18562357
    18572358  return 0;
     
    19302431      return 0;
    19312432
    1932     case TCM_GETUNICODEFORMAT:
    1933 //      FIXME (tab, "Unimplemented msg TCM_GETUNICODEFORMAT\n");
    1934       return 0;
    1935 
    1936     case TCM_SETUNICODEFORMAT:
    1937 //      FIXME (tab, "Unimplemented msg TCM_SETUNICODEFORMAT\n");
    1938       return 0;
    1939 
    19402433    case TCM_HIGHLIGHTITEM:
    19412434//      FIXME (tab, "Unimplemented msg TCM_HIGHLIGHTITEM\n");
     
    20112504    case WM_HSCROLL:
    20122505      return TAB_OnHScroll(hwnd, (int)LOWORD(wParam), (int)HIWORD(wParam), (HWND)lParam);
     2506
     2507    case WM_STYLECHANGED:
     2508      return TAB_StyleChanged(hwnd,wParam,lParam);
    20132509
    20142510    case WM_KILLFOCUS:
     
    20352531
    20362532  ZeroMemory (&wndClass, sizeof(WNDCLASSA));
    2037   wndClass.style         = CS_GLOBALCLASS | CS_DBLCLKS | CS_SAVEBITS;
     2533  wndClass.style         = CS_GLOBALCLASS | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
    20382534  wndClass.lpfnWndProc   = (WNDPROC)TAB_WindowProc;
    20392535  wndClass.cbClsExtra    = 0;
Note: See TracChangeset for help on using the changeset viewer.