mirror of https://github.com/OpenTTD/OpenTTD
Fix #12086: Crash if NWidgetMatrix holds content taller than 64K pixels.
Scale NWidgetMatrix's scrollbar count to ensure it is within limits.pull/12151/head
parent
5d2e6e4efa
commit
fcdf71ada8
|
@ -1774,8 +1774,8 @@ void NWidgetMatrix::SetClicked(int clicked)
|
||||||
int vpos = (this->clicked / this->widgets_x) * this->widget_h; // Vertical position of the top.
|
int vpos = (this->clicked / this->widgets_x) * this->widget_h; // Vertical position of the top.
|
||||||
/* Need to scroll down -> Scroll to the bottom.
|
/* Need to scroll down -> Scroll to the bottom.
|
||||||
* However, last entry has no 'this->pip_inter' underneath, and we must stay below this->sb->GetCount() */
|
* However, last entry has no 'this->pip_inter' underneath, and we must stay below this->sb->GetCount() */
|
||||||
if (this->sb->GetPosition() < vpos) vpos += this->widget_h - this->pip_inter - 1;
|
if (this->sb->GetPosition() * this->count_adjust < vpos) vpos += this->widget_h - this->pip_inter - 1;
|
||||||
this->sb->ScrollTowards(vpos);
|
this->sb->ScrollTowards(vpos / this->count_adjust);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1799,9 +1799,11 @@ void NWidgetMatrix::SetCount(int count)
|
||||||
count *= (this->sb->IsVertical() ? this->children.front()->smallest_y : this->children.front()->smallest_x) + this->pip_inter;
|
count *= (this->sb->IsVertical() ? this->children.front()->smallest_y : this->children.front()->smallest_x) + this->pip_inter;
|
||||||
if (count > 0) count -= this->pip_inter; // We counted an inter too much in the multiplication above
|
if (count > 0) count -= this->pip_inter; // We counted an inter too much in the multiplication above
|
||||||
count += this->pip_pre + this->pip_post;
|
count += this->pip_pre + this->pip_post;
|
||||||
|
this->count_adjust = CeilDiv(count, Scrollbar::GetMaxCount());
|
||||||
|
count /= this->count_adjust;
|
||||||
this->sb->SetCount(count);
|
this->sb->SetCount(count);
|
||||||
this->sb->SetCapacity(this->sb->IsVertical() ? this->current_y : this->current_x);
|
this->sb->SetCapacity((this->sb->IsVertical() ? this->current_y : this->current_x) / this->count_adjust);
|
||||||
this->sb->SetStepSize(this->sb->IsVertical() ? this->widget_h : this->widget_w);
|
this->sb->SetStepSize((this->sb->IsVertical() ? this->widget_h : this->widget_w) / this->count_adjust);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1966,11 +1968,11 @@ void NWidgetMatrix::GetScrollOffsets(int &start_x, int &start_y, int &base_offs_
|
||||||
start_y = 0;
|
start_y = 0;
|
||||||
if (this->sb != nullptr) {
|
if (this->sb != nullptr) {
|
||||||
if (this->sb->IsVertical()) {
|
if (this->sb->IsVertical()) {
|
||||||
start_y = this->sb->GetPosition() / this->widget_h;
|
start_y = this->sb->GetPosition() * this->count_adjust / this->widget_h;
|
||||||
base_offs_y += -this->sb->GetPosition() + start_y * this->widget_h;
|
base_offs_y += -this->sb->GetPosition() * this->count_adjust + start_y * this->widget_h;
|
||||||
} else {
|
} else {
|
||||||
start_x = this->sb->GetPosition() / this->widget_w;
|
start_x = this->sb->GetPosition() * this->count_adjust / this->widget_w;
|
||||||
int sub_x = this->sb->GetPosition() - start_x * this->widget_w;
|
int sub_x = this->sb->GetPosition() * this->count_adjust - start_x * this->widget_w;
|
||||||
if (_current_text_dir == TD_RTL) {
|
if (_current_text_dir == TD_RTL) {
|
||||||
base_offs_x += sub_x;
|
base_offs_x += sub_x;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -607,6 +607,7 @@ private:
|
||||||
int widget_h; ///< The height of the child widget including inter spacing.
|
int widget_h; ///< The height of the child widget including inter spacing.
|
||||||
int widgets_x; ///< The number of visible widgets in horizontal direction.
|
int widgets_x; ///< The number of visible widgets in horizontal direction.
|
||||||
int widgets_y; ///< The number of visible widgets in vertical direction.
|
int widgets_y; ///< The number of visible widgets in vertical direction.
|
||||||
|
int count_adjust; ///< Multiplier/divisor applied to count to ensure it fits below Scrollbar's storage type.
|
||||||
|
|
||||||
void GetScrollOffsets(int &start_x, int &start_y, int &base_offs_x, int &base_offs_y);
|
void GetScrollOffsets(int &start_x, int &start_y, int &base_offs_x, int &base_offs_y);
|
||||||
};
|
};
|
||||||
|
@ -697,6 +698,15 @@ public:
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the maximum possible number of elements in a list.
|
||||||
|
* @return the maximum possible number of elements.
|
||||||
|
*/
|
||||||
|
static constexpr uint16_t GetMaxCount()
|
||||||
|
{
|
||||||
|
return std::numeric_limits<decltype(count)>::max();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the number of elements in the list
|
* Gets the number of elements in the list
|
||||||
* @return the number of elements
|
* @return the number of elements
|
||||||
|
|
Loading…
Reference in New Issue