Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
wine
Manage
Activity
Members
Labels
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Container Registry
Model registry
Operate
Terraform modules
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Jason Beetham
wine
Commits
8ee3144a
Commit
8ee3144a
authored
24 years ago
by
Aric Stewart
Committed by
Alexandre Julliard
24 years ago
Browse files
Options
Downloads
Patches
Plain Diff
Added the ability to use multiline tab controls to wine.
parent
b7ed6df2
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
dlls/comctl32/tab.c
+215
-48
215 additions, 48 deletions
dlls/comctl32/tab.c
include/tab.h
+5
-1
5 additions, 1 deletion
include/tab.h
with
220 additions
and
49 deletions
dlls/comctl32/tab.c
+
215
−
48
View file @
8ee3144a
...
...
@@ -174,14 +174,15 @@ static BOOL TAB_InternalGetItemRect(
RECT
*
itemRect
,
RECT
*
selectedRect
)
{
RECT
tmpItemRect
;
RECT
tmpItemRect
,
clientRect
;
LONG
lStyle
=
GetWindowLongA
(
hwnd
,
GWL_STYLE
);
/*
* Perform a sanity check and a trivial visibility check.
*/
if
(
(
infoPtr
->
uNumItem
<=
0
)
||
(
itemIndex
>=
infoPtr
->
uNumItem
)
||
(
itemIndex
<
infoPtr
->
leftmostVisible
)
)
(
!
(
lStyle
&
TCS_MULTILINE
)
&&
(
itemIndex
<
infoPtr
->
leftmostVisible
)
)
)
return
FALSE
;
/*
...
...
@@ -196,6 +197,31 @@ static BOOL TAB_InternalGetItemRect(
*/
*
itemRect
=
infoPtr
->
items
[
itemIndex
].
rect
;
/*
* calculate the times bottom and top based on the row
*/
GetClientRect
(
hwnd
,
&
clientRect
);
if
(
lStyle
&
TCS_BOTTOM
)
{
itemRect
->
bottom
=
clientRect
.
bottom
-
SELECTED_TAB_OFFSET
-
itemRect
->
top
*
(
infoPtr
->
tabHeight
-
2
);
itemRect
->
top
=
clientRect
.
bottom
-
infoPtr
->
tabHeight
-
itemRect
->
top
*
(
infoPtr
->
tabHeight
-
2
);
}
else
{
itemRect
->
bottom
=
clientRect
.
top
+
infoPtr
->
tabHeight
+
itemRect
->
top
*
(
infoPtr
->
tabHeight
-
2
);
itemRect
->
top
=
clientRect
.
top
+
SELECTED_TAB_OFFSET
+
itemRect
->
top
*
(
infoPtr
->
tabHeight
-
2
);
}
/*
* "scroll" it to make sure the item at the very left of the
* tab control is the leftmost visible tab.
...
...
@@ -463,9 +489,9 @@ static LRESULT TAB_AdjustRect(
* Add the height of the tabs.
*/
if
(
GetWindowLongA
(
hwnd
,
GWL_STYLE
)
&
TCS_BOTTOM
)
prc
->
bottom
+=
infoPtr
->
tabHeight
;
prc
->
bottom
+=
(
infoPtr
->
tabHeight
-
2
)
*
(
infoPtr
->
uNumRows
+
1
)
+
2
;
else
prc
->
top
-=
infoPtr
->
tabHeight
;
prc
->
top
-=
(
infoPtr
->
tabHeight
-
2
)
*
(
infoPtr
->
uNumRows
+
1
)
+
2
;
/*
* Inflate the rectangle for the padding
...
...
@@ -497,9 +523,9 @@ static LRESULT TAB_AdjustRect(
* Remove the height of the tabs.
*/
if
(
GetWindowLongA
(
hwnd
,
GWL_STYLE
)
&
TCS_BOTTOM
)
prc
->
bottom
-=
infoPtr
->
tabHeight
;
prc
->
bottom
-=
(
infoPtr
->
tabHeight
-
2
)
*
(
infoPtr
->
uNumRows
+
1
)
+
2
;
else
prc
->
top
+=
infoPtr
->
tabHeight
;
prc
->
top
+=
(
infoPtr
->
tabHeight
-
2
)
*
(
infoPtr
->
uNumRows
+
1
)
+
2
;
}
...
...
@@ -575,10 +601,6 @@ static void TAB_SetupScrolling(
*/
if
(
infoPtr
->
hwndUpDown
==
0
)
{
/*
* I use a scrollbar since it seems to be more stable than the Updown
* control.
*/
infoPtr
->
hwndUpDown
=
CreateWindowA
(
"msctls_updown32"
,
""
,
WS_VISIBLE
|
WS_CHILD
|
UDS_HORZ
,
...
...
@@ -651,6 +673,7 @@ static void TAB_SetItemBounds (HWND hwnd)
TEXTMETRICA
fontMetrics
;
INT
curItem
;
INT
curItemLeftPos
;
INT
curItemRowCount
;
HFONT
hFont
,
hOldFont
;
HDC
hdc
;
RECT
clientRect
;
...
...
@@ -675,6 +698,7 @@ static void TAB_SetItemBounds (HWND hwnd)
* The leftmost item will be "0" aligned
*/
curItemLeftPos
=
0
;
curItemRowCount
=
0
;
if
(
!
(
lStyle
&
TCS_FIXEDWIDTH
)
&&
!
((
lStyle
&
TCS_OWNERDRAWFIXED
)
&&
infoPtr
->
fSizeSet
)
)
{
...
...
@@ -710,24 +734,6 @@ static void TAB_SetItemBounds (HWND hwnd)
for
(
curItem
=
0
;
curItem
<
infoPtr
->
uNumItem
;
curItem
++
)
{
/*
* Calculate the vertical position of the tab
*/
if
(
lStyle
&
TCS_BOTTOM
)
{
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
;
}
/*
* Set the leftmost position of the tab.
*/
...
...
@@ -764,6 +770,27 @@ static void TAB_SetItemBounds (HWND hwnd)
num
*
HORIZONTAL_ITEM_PADDING
;
}
/*
* Check if this is a multiline tab control and if so
* check to see if we should wrap the tabs
*
* Because we are going to arange all these tabs evenly
* really we are basically just counting rows at this point
*
*/
if
((
lStyle
&
TCS_MULTILINE
)
&&
(
infoPtr
->
items
[
curItem
].
rect
.
right
>
clientRect
.
right
))
{
infoPtr
->
items
[
curItem
].
rect
.
right
-=
infoPtr
->
items
[
curItem
].
rect
.
left
;
infoPtr
->
items
[
curItem
].
rect
.
left
=
0
;
curItemRowCount
++
;
}
infoPtr
->
items
[
curItem
].
rect
.
bottom
=
0
;
infoPtr
->
items
[
curItem
].
rect
.
top
=
curItemRowCount
;
TRACE
(
"TextSize: %i
\n
"
,
size
.
cx
);
TRACE
(
"Rect: T %i, L %i, B %i, R %i
\n
"
,
infoPtr
->
items
[
curItem
].
rect
.
top
,
...
...
@@ -776,23 +803,118 @@ static void TAB_SetItemBounds (HWND hwnd)
* of this one.
*/
if
(
lStyle
&
TCS_BUTTONS
)
curItemLeftPos
=
infoPtr
->
items
[
curItem
].
rect
.
right
+
BUTTON_SPACINGX
;
curItemLeftPos
=
infoPtr
->
items
[
curItem
].
rect
.
right
+
BUTTON_SPACINGX
;
else
curItemLeftPos
=
infoPtr
->
items
[
curItem
].
rect
.
right
;
}
if
(
!
(
lStyle
&
TCS_MULTILINE
))
{
/*
* Check if we need a scrolling control.
*/
infoPtr
->
needsScrolling
=
(
curItemLeftPos
+
(
2
*
SELECTED_TAB_OFFSET
)
>
clientRect
.
right
);
TAB_SetupScrolling
(
hwnd
,
infoPtr
,
&
clientRect
);
}
/*
*
Check if we need a scrolling control.
*
Set the number of rows
*/
infoPtr
->
needsScrolling
=
(
curItemLeftPos
+
(
2
*
SELECTED_TAB_OFFSET
)
>
clientRect
.
right
);
/* Don't need scrolling, then update infoPtr->leftmostVisible */
if
(
!
infoPtr
->
needsScrolling
)
infoPtr
->
leftmostVisible
=
0
;
infoPtr
->
uNumRows
=
curItemRowCount
;
TAB_SetupScrolling
(
hwnd
,
infoPtr
,
&
clientRect
);
if
((
lStyle
&
TCS_MULTILINE
)
&&
(
infoPtr
->
uNumItem
>
0
))
{
INT
widthDiff
,
remainder
;
INT
tabPerRow
,
remTab
;
INT
iRow
,
iItm
;
INT
iIndexStart
=
0
,
iIndexEnd
=
0
,
iCount
=
0
;
/*
* Ok Microsoft trys to even out the rows. place the same
* number of tabs in each row. So lets give that a shot
*
*/
tabPerRow
=
infoPtr
->
uNumItem
/
(
infoPtr
->
uNumRows
+
1
);
remTab
=
infoPtr
->
uNumItem
%
(
infoPtr
->
uNumRows
+
1
);
for
(
iItm
=
0
,
iRow
=
0
,
iCount
=
0
,
curItemLeftPos
=
0
;
iItm
<
infoPtr
->
uNumItem
;
iItm
++
,
iCount
++
)
{
if
(
iCount
>=
((
iRow
<
remTab
)
?
tabPerRow
+
1
:
tabPerRow
))
{
iRow
++
;
curItemLeftPos
=
0
;
iCount
=
0
;
}
/*
* normalize the current rect
*/
infoPtr
->
items
[
iItm
].
rect
.
right
-=
infoPtr
->
items
[
iItm
].
rect
.
left
;
infoPtr
->
items
[
iItm
].
rect
.
left
=
0
;
infoPtr
->
items
[
iItm
].
rect
.
top
=
iRow
;
infoPtr
->
items
[
iItm
].
rect
.
left
+=
curItemLeftPos
;
infoPtr
->
items
[
iItm
].
rect
.
right
+=
curItemLeftPos
;
if
(
lStyle
&
TCS_BUTTONS
)
curItemLeftPos
=
infoPtr
->
items
[
iItm
].
rect
.
right
+
BUTTON_SPACINGX
;
else
curItemLeftPos
=
infoPtr
->
items
[
iItm
].
rect
.
right
;
}
/*
* Justify the rows
*
*/
{
while
(
iIndexStart
<
infoPtr
->
uNumItem
)
{
/*
* find the indexs of the row
*/
for
(
iIndexEnd
=
iIndexStart
;
(
iIndexEnd
<
infoPtr
->
uNumItem
)
&&
(
infoPtr
->
items
[
iIndexEnd
].
rect
.
top
==
infoPtr
->
items
[
iIndexStart
].
rect
.
top
)
;
iIndexEnd
++
)
/* intentionaly blank */
;
/*
* we need to justify these tabs so they fill the whole given
* client area
*
*/
widthDiff
=
clientRect
.
right
-
(
2
*
SELECTED_TAB_OFFSET
)
-
infoPtr
->
items
[
iIndexEnd
-
1
].
rect
.
right
;
iCount
=
iIndexEnd
-
iIndexStart
;
if
(
iCount
)
{
INT
iIndex
;
remainder
=
widthDiff
%
iCount
;
widthDiff
=
widthDiff
/
iCount
;
for
(
iIndex
=
iIndexStart
,
iCount
=
0
;
iIndex
<
iIndexEnd
;
iIndex
++
,
iCount
++
)
{
infoPtr
->
items
[
iIndex
].
rect
.
left
+=
iCount
*
widthDiff
;
infoPtr
->
items
[
iIndex
].
rect
.
right
+=
(
iCount
+
1
)
*
widthDiff
;
}
infoPtr
->
items
[
iIndex
-
1
].
rect
.
right
+=
remainder
;
}
iIndexStart
=
iIndexEnd
;
}
}
}
TAB_EnsureSelectionVisible
(
hwnd
,
infoPtr
);
/*
* Cleanup
*/
...
...
@@ -1044,7 +1166,14 @@ static void TAB_DrawItem(
/*
* Draw the text;
*/
DrawTextA
(
hdc
,
if
(
lStyle
&
TCS_RIGHTJUSTIFY
)
DrawTextA
(
hdc
,
infoPtr
->
items
[
iItem
].
pszText
,
lstrlenA
(
infoPtr
->
items
[
iItem
].
pszText
),
&
r
,
DT_CENTER
|
DT_SINGLELINE
|
DT_VCENTER
);
else
DrawTextA
(
hdc
,
infoPtr
->
items
[
iItem
].
pszText
,
lstrlenA
(
infoPtr
->
items
[
iItem
].
pszText
),
&
r
,
...
...
@@ -1101,11 +1230,11 @@ static void TAB_DrawBorder (HWND hwnd, HDC hdc)
*/
if
(
GetWindowLongA
(
hwnd
,
GWL_STYLE
)
&
TCS_BOTTOM
)
{
rect
.
bottom
-=
infoPtr
->
tabHeight
;
rect
.
bottom
-=
(
infoPtr
->
tabHeight
-
2
)
*
(
infoPtr
->
uNumRows
+
1
)
+
2
;
}
else
{
rect
.
top
+=
infoPtr
->
tabHeight
;
rect
.
top
+=
(
infoPtr
->
tabHeight
-
2
)
*
(
infoPtr
->
uNumRows
+
1
)
+
2
;
}
/*
...
...
@@ -1180,13 +1309,13 @@ static void TAB_Refresh (HWND hwnd, HDC hdc)
* Then, draw the selected item
*/
TAB_DrawItem
(
hwnd
,
hdc
,
infoPtr
->
iSelected
);
/*
* If we haven't set the current focus yet, set it now.
* Only happens when we first paint the tab controls.
*/
if
(
infoPtr
->
uFocus
==
-
1
)
TAB_SetCurFocus
(
hwnd
,
infoPtr
->
iSelected
);
if
(
infoPtr
->
uFocus
==
-
1
)
TAB_SetCurFocus
(
hwnd
,
infoPtr
->
iSelected
);
}
SelectObject
(
hdc
,
hOldFont
);
...
...
@@ -1236,6 +1365,41 @@ static void TAB_EnsureSelectionVisible(
{
INT
iSelected
=
infoPtr
->
iSelected
;
/*
* set the items row to the bottommost row or topmost row depending on
* style
*/
if
(
infoPtr
->
uNumRows
>
0
)
{
INT
newselected
=
infoPtr
->
items
[
iSelected
].
rect
.
top
;
INT
iTargetRow
;
LONG
lStyle
=
GetWindowLongA
(
hwnd
,
GWL_STYLE
);
if
(
lStyle
&
TCS_BOTTOM
)
iTargetRow
=
0
;
else
iTargetRow
=
infoPtr
->
uNumRows
;
if
(
newselected
!=
iTargetRow
)
{
INT
i
;
for
(
i
=
0
;
i
<
infoPtr
->
uNumItem
;
i
++
)
if
(
infoPtr
->
items
[
i
].
rect
.
top
==
newselected
)
infoPtr
->
items
[
i
].
rect
.
top
=
iTargetRow
;
else
if
(
lStyle
&
TCS_BOTTOM
)
{
if
(
infoPtr
->
items
[
i
].
rect
.
top
<
newselected
)
infoPtr
->
items
[
i
].
rect
.
top
+=
1
;
}
else
{
if
(
infoPtr
->
items
[
i
].
rect
.
top
>
newselected
)
infoPtr
->
items
[
i
].
rect
.
top
-=
1
;
}
}
}
/*
* Do the trivial cases first.
*/
...
...
@@ -1301,11 +1465,13 @@ static void TAB_InvalidateTabArea(
if
(
GetWindowLongA
(
hwnd
,
GWL_STYLE
)
&
TCS_BOTTOM
)
{
clientRect
.
top
=
clientRect
.
bottom
-
(
infoPtr
->
tabHeight
+
3
);
clientRect
.
top
=
clientRect
.
bottom
-
(
infoPtr
->
tabHeight
*
(
infoPtr
->
uNumRows
+
1
)
+
3
);
}
else
{
clientRect
.
bottom
=
clientRect
.
top
+
(
infoPtr
->
tabHeight
+
1
);
clientRect
.
bottom
=
clientRect
.
top
+
(
infoPtr
->
tabHeight
*
(
infoPtr
->
uNumRows
+
1
)
+
1
);
}
InvalidateRect
(
hwnd
,
&
clientRect
,
TRUE
);
...
...
@@ -1389,12 +1555,12 @@ TAB_InsertItem (HWND hwnd, WPARAM wParam, LPARAM lParam)
if
(
pti
->
mask
&
TCIF_PARAM
)
infoPtr
->
items
[
iItem
].
lParam
=
pti
->
lParam
;
TAB_SetItemBounds
(
hwnd
);
TAB_InvalidateTabArea
(
hwnd
,
infoPtr
);
TRACE
(
"[%04x]: added item %d '%s'
\n
"
,
hwnd
,
iItem
,
infoPtr
->
items
[
iItem
].
pszText
);
TAB_SetItemBounds
(
hwnd
);
return
iItem
;
}
...
...
@@ -1668,6 +1834,7 @@ TAB_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
SetWindowLongA
(
hwnd
,
0
,
(
DWORD
)
infoPtr
);
infoPtr
->
uNumItem
=
0
;
infoPtr
->
uNumRows
=
0
;
infoPtr
->
hFont
=
0
;
infoPtr
->
items
=
0
;
infoPtr
->
hcurArrow
=
LoadCursorA
(
0
,
IDC_ARROWA
);
...
...
@@ -1938,7 +2105,7 @@ TAB_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
default:
if
(
uMsg
>=
WM_USER
)
WARN
(
"unknown msg %04x wp=%08x lp=%08lx
\n
"
,
ERR
(
"unknown msg %04x wp=%08x lp=%08lx
\n
"
,
uMsg
,
wParam
,
lParam
);
return
DefWindowProcA
(
hwnd
,
uMsg
,
wParam
,
lParam
);
}
...
...
This diff is collapsed.
Click to expand it.
include/tab.h
+
5
−
1
View file @
8ee3144a
...
...
@@ -20,12 +20,16 @@ typedef struct tagTAB_ITEM
LPARAM
lParam
;
RECT
rect
;
/* bounding rectangle of the item relative to the
* leftmost item (the leftmost item, 0, would have a
* "left" member of 0 in this rectangle) */
* "left" member of 0 in this rectangle)
*
* additionally the top member hold the row number
* and bottom is unused and should be 0 */
}
TAB_ITEM
;
typedef
struct
tagTAB_INFO
{
UINT
uNumItem
;
/* number of tab items */
UINT
uNumRows
;
/* number of tab rows */
INT
tabHeight
;
/* height of the tab row */
INT
tabWidth
;
/* width of tabs */
HFONT
hFont
;
/* handle to the current font */
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment