Changeset - r28365:afdff505306b
[Not reviewed]
master
0 2 0
Peter Nelson - 11 months ago 2023-12-30 18:55:16
peter1138@openttd.org
Codechange: Make widget index const to prevent changes. (#11658)

This guards against future widget index manipulation.
2 files changed with 17 insertions and 56 deletions:
0 comments (0 inline, 0 general)
src/widget.cpp
Show inline comments
 
@@ -1205,40 +1205,30 @@ void NWidgetResizeBase::AssignSizePositi
 
}
 

	
 
/**
 
 * Initialization of a 'real' widget.
 
 * @param tp          Type of the widget.
 
 * @param colour      Colour of the widget.
 
 * @param index       Index of the widget.
 
 * @param fill_x      Default horizontal filling.
 
 * @param fill_y      Default vertical filling.
 
 * @param widget_data Data component of the widget. @see Widget::data
 
 * @param tool_tip    Tool tip of the widget. @see Widget::tooltips
 
 */
 
NWidgetCore::NWidgetCore(WidgetType tp, Colours colour, uint fill_x, uint fill_y, uint32_t widget_data, StringID tool_tip) : NWidgetResizeBase(tp, fill_x, fill_y)
 
NWidgetCore::NWidgetCore(WidgetType tp, Colours colour, WidgetID index, uint fill_x, uint fill_y, uint32_t widget_data, StringID tool_tip) : NWidgetResizeBase(tp, fill_x, fill_y), index(index)
 
{
 
	this->colour = colour;
 
	this->index = -1;
 
	this->widget_data = widget_data;
 
	this->tool_tip = tool_tip;
 
	this->scrollbar_index = -1;
 
	this->text_colour = tp == WWT_CAPTION ? TC_WHITE : TC_BLACK;
 
	this->text_size = FS_NORMAL;
 
	this->align = SA_CENTER;
 
}
 

	
 
/**
 
 * Set index of the nested widget in the widget array.
 
 * @param index Index to use.
 
 */
 
void NWidgetCore::SetIndex(WidgetID index)
 
{
 
	assert(index >= 0);
 
	this->index = index;
 
}
 

	
 
/**
 
 * Set data and tool tip of the nested widget.
 
 * @param widget_data Data to use.
 
 * @param tool_tip    Tool tip string to use.
 
 */
 
void NWidgetCore::SetDataTip(uint32_t widget_data, StringID tool_tip)
 
{
 
@@ -1371,20 +1361,14 @@ NWidgetCore *NWidgetContainer::GetWidget
 
	return nullptr;
 
}
 

	
 
/**
 
 * Widgets stacked on top of each other.
 
 */
 
NWidgetStacked::NWidgetStacked() : NWidgetContainer(NWID_SELECTION)
 
NWidgetStacked::NWidgetStacked(WidgetID index) : NWidgetContainer(NWID_SELECTION), index(index)
 
{
 
	this->index = -1;
 
}
 

	
 
void NWidgetStacked::SetIndex(WidgetID index)
 
{
 
	this->index = index;
 
}
 

	
 
void NWidgetStacked::AdjustPaddingForZoom()
 
{
 
	for (NWidgetBase *child_wid = this->head; child_wid != nullptr; child_wid = child_wid->next) {
 
		child_wid->AdjustPaddingForZoom();
 
@@ -1947,22 +1931,13 @@ void NWidgetSpacer::SetDirty(const Windo
 

	
 
NWidgetCore *NWidgetSpacer::GetWidgetFromPos(int, int)
 
{
 
	return nullptr;
 
}
 

	
 
NWidgetMatrix::NWidgetMatrix() : NWidgetPIPContainer(NWID_MATRIX, NC_EQUALSIZE), index(-1), clicked(-1), count(-1)
 
{
 
}
 

	
 
void NWidgetMatrix::SetIndex(WidgetID index)
 
{
 
	this->index = index;
 
}
 

	
 
void NWidgetMatrix::SetColour(Colours colour)
 
NWidgetMatrix::NWidgetMatrix(Colours colour, WidgetID index) : NWidgetPIPContainer(NWID_MATRIX, NC_EQUALSIZE), index(index), clicked(-1), count(-1)
 
{
 
	this->colour = colour;
 
}
 

	
 
/**
 
 * Sets the clicked element in the matrix.
 
@@ -2188,16 +2163,15 @@ void NWidgetMatrix::GetScrollOffsets(int
 
 * @param colour Colour of the parent widget.
 
 * @param index  Index of the widget.
 
 * @param child  Child container widget (if supplied). If not supplied, a
 
 *               vertical container will be inserted while adding the first
 
 *               child widget.
 
 */
 
NWidgetBackground::NWidgetBackground(WidgetType tp, Colours colour, WidgetID index, NWidgetPIPContainer *child) : NWidgetCore(tp, colour, 1, 1, 0x0, STR_NULL)
 
NWidgetBackground::NWidgetBackground(WidgetType tp, Colours colour, WidgetID index, NWidgetPIPContainer *child) : NWidgetCore(tp, colour, index, 1, 1, 0x0, STR_NULL)
 
{
 
	assert(tp == WWT_PANEL || tp == WWT_INSET || tp == WWT_FRAME);
 
	if (index >= 0) this->SetIndex(index);
 
	this->child = child;
 
	this->SetAlignment(SA_TOP | SA_LEFT);
 
}
 

	
 
NWidgetBackground::~NWidgetBackground()
 
{
 
@@ -2396,15 +2370,14 @@ NWidgetBase *NWidgetBackground::GetWidge
 
	NWidgetBase *nwid = nullptr;
 
	if (this->child != nullptr) nwid = this->child->GetWidgetOfType(tp);
 
	if (nwid == nullptr && this->type == tp) nwid = this;
 
	return nwid;
 
}
 

	
 
NWidgetViewport::NWidgetViewport(WidgetID index) : NWidgetCore(NWID_VIEWPORT, INVALID_COLOUR, 1, 1, 0x0, STR_NULL)
 
NWidgetViewport::NWidgetViewport(WidgetID index) : NWidgetCore(NWID_VIEWPORT, INVALID_COLOUR, index, 1, 1, 0x0, STR_NULL)
 
{
 
	this->SetIndex(index);
 
}
 

	
 
void NWidgetViewport::SetupSmallestSize(Window *)
 
{
 
	this->smallest_x = this->min_x;
 
	this->smallest_y = this->min_y;
 
@@ -2556,16 +2529,15 @@ void Scrollbar::SetCapacityFromWidget(Wi
 
/**
 
 * Scrollbar widget.
 
 * @param tp     Scrollbar type. (horizontal/vertical)
 
 * @param colour Colour of the scrollbar.
 
 * @param index  Index of the widget.
 
 */
 
NWidgetScrollbar::NWidgetScrollbar(WidgetType tp, Colours colour, WidgetID index) : NWidgetCore(tp, colour, 1, 1, 0x0, STR_NULL), Scrollbar(tp != NWID_HSCROLLBAR)
 
NWidgetScrollbar::NWidgetScrollbar(WidgetType tp, Colours colour, WidgetID index) : NWidgetCore(tp, colour, index, 1, 1, 0x0, STR_NULL), Scrollbar(tp != NWID_HSCROLLBAR)
 
{
 
	assert(tp == NWID_HSCROLLBAR || tp == NWID_VSCROLLBAR);
 
	this->SetIndex(index);
 

	
 
	switch (this->type) {
 
		case NWID_HSCROLLBAR:
 
			this->SetResize(1, 0);
 
			this->SetFill(1, 0);
 
			this->SetDataTip(0x0, STR_TOOLTIP_HSCROLL_BAR_SCROLLS_LIST);
 
@@ -2682,16 +2654,15 @@ Dimension NWidgetLeaf::dropdown_dimensio
 
 * @param tp     Type of leaf widget.
 
 * @param colour Colour of the leaf widget.
 
 * @param index  Index of the widget.
 
 * @param data   Data of the widget.
 
 * @param tip    Tooltip of the widget.
 
 */
 
NWidgetLeaf::NWidgetLeaf(WidgetType tp, Colours colour, WidgetID index, uint32_t data, StringID tip) : NWidgetCore(tp, colour, 1, 1, data, tip)
 
NWidgetLeaf::NWidgetLeaf(WidgetType tp, Colours colour, WidgetID index, uint32_t data, StringID tip) : NWidgetCore(tp, colour, index, 1, 1, data, tip)
 
{
 
	assert(index >= 0 || tp == WWT_LABEL || tp == WWT_TEXT || tp == WWT_CAPTION || tp == WWT_RESIZEBOX || tp == WWT_SHADEBOX || tp == WWT_DEFSIZEBOX || tp == WWT_DEBUGBOX || tp == WWT_STICKYBOX || tp == WWT_CLOSEBOX);
 
	if (index >= 0) this->SetIndex(index);
 
	this->min_x = 0;
 
	this->min_y = 0;
 
	this->SetResize(0, 0);
 

	
 
	switch (tp) {
 
		case WWT_EMPTY:
 
@@ -3150,17 +3121,14 @@ static const NWidgetPart *MakeNWidget(co
 
				*dest = new NWidgetVertical(nwid_begin->u.cont_flags);
 
				*fill_dest = true;
 
				break;
 

	
 
			case NWID_MATRIX: {
 
				if (*dest != nullptr) return nwid_begin;
 
				NWidgetMatrix *nwm = new NWidgetMatrix();
 
				*dest = nwm;
 
				*dest = new NWidgetMatrix(nwid_begin->u.widget.colour, nwid_begin->u.widget.index);
 
				*fill_dest = true;
 
				nwm->SetIndex(nwid_begin->u.widget.index);
 
				nwm->SetColour(nwid_begin->u.widget.colour);
 
				break;
 
			}
 

	
 
			case WPT_FUNCTION: {
 
				if (*dest != nullptr) return nwid_begin;
 
				*dest = nwid_begin->u.func_ptr();
 
@@ -3268,16 +3236,14 @@ static const NWidgetPart *MakeNWidget(co
 
				if (*dest != nullptr) return nwid_begin;
 
				*dest = new NWidgetScrollbar(nwid_begin->type, nwid_begin->u.widget.colour, nwid_begin->u.widget.index);
 
				break;
 

	
 
			case NWID_SELECTION: {
 
				if (*dest != nullptr) return nwid_begin;
 
				NWidgetStacked *nws = new NWidgetStacked();
 
				*dest = nws;
 
				*dest = new NWidgetStacked(nwid_begin->u.widget.index);
 
				*fill_dest = true;
 
				nws->SetIndex(nwid_begin->u.widget.index);
 
				break;
 
			}
 

	
 
			default:
 
				if (*dest != nullptr) return nwid_begin;
 
				assert((nwid_begin->type & WWT_MASK) < WWT_LAST || (nwid_begin->type & WWT_MASK) == NWID_BUTTON_DROPDOWN);
 
@@ -3391,13 +3357,13 @@ NWidgetContainer *MakeWindowNWidgetTree(
 

	
 
	/* If the first widget looks like a titlebar, treat it as such.
 
	 * If it has a shading box, silently add a shade selection widget in the tree. */
 
	NWidgetHorizontal *hor_cont = dynamic_cast<NWidgetHorizontal *>(nwid);
 
	NWidgetContainer *body;
 
	if (hor_cont != nullptr && hor_cont->GetWidgetOfType(WWT_CAPTION) != nullptr && hor_cont->GetWidgetOfType(WWT_SHADEBOX) != nullptr) {
 
		*shade_select = new NWidgetStacked;
 
		*shade_select = new NWidgetStacked(-1);
 
		root->Add(*shade_select);
 
		body = new NWidgetVertical;
 
		(*shade_select)->Add(body);
 
	} else {
 
		*shade_select = nullptr;
 
		body = root;
src/widget_type.h
Show inline comments
 
@@ -324,15 +324,14 @@ DECLARE_ENUM_AS_BIT_SET(NWidgetDisplay)
 
/**
 
 * Base class for a 'real' widget.
 
 * @ingroup NestedWidgets
 
 */
 
class NWidgetCore : public NWidgetResizeBase {
 
public:
 
	NWidgetCore(WidgetType tp, Colours colour, uint fill_x, uint fill_y, uint32_t widget_data, StringID tool_tip);
 
	NWidgetCore(WidgetType tp, Colours colour, WidgetID index, uint fill_x, uint fill_y, uint32_t widget_data, StringID tool_tip);
 

	
 
	void SetIndex(WidgetID index);
 
	void SetDataTip(uint32_t widget_data, StringID tool_tip);
 
	void SetToolTip(StringID tool_tip);
 
	void SetTextStyle(TextColour colour, FontSize size);
 
	void SetAlignment(StringAlignment align);
 

	
 
	inline void SetLowered(bool lowered);
 
@@ -345,13 +344,13 @@ public:
 
	bool IsHighlighted() const override;
 
	TextColour GetHighlightColour() const override;
 
	void SetHighlighted(TextColour highlight_colour) override;
 

	
 
	NWidgetDisplay disp_flags; ///< Flags that affect display and interaction with the widget.
 
	Colours colour;            ///< Colour of this widget.
 
	WidgetID index;            ///< Index of the nested widget (\c -1 means 'not used').
 
	const WidgetID index;      ///< Index of the nested widget (\c -1 means 'not used').
 
	uint32_t widget_data;        ///< Data of the widget. @see Widget::data
 
	StringID tool_tip;         ///< Tooltip of the widget. @see Widget::tootips
 
	WidgetID scrollbar_index;  ///< Index of an attached scrollbar.
 
	TextColour highlight_colour; ///< Colour of highlight.
 
	TextColour text_colour;    ///< Colour of text within widget.
 
	FontSize text_size;        ///< Size of text within widget.
 
@@ -455,28 +454,26 @@ enum StackedZeroSizePlanes {
 
 * the other direction) or have zero size in both directions. They are used to make all child planes of the widget disappear.
 
 * Unlike switching between the regular display planes (that all have the same size), switching from or to one of the zero-sized planes means that
 
 * a #Window::ReInit() is needed to re-initialize the window since its size changes.
 
 */
 
class NWidgetStacked : public NWidgetContainer {
 
public:
 
	NWidgetStacked();
 

	
 
	void SetIndex(WidgetID index);
 
	NWidgetStacked(WidgetID index);
 

	
 
	void AdjustPaddingForZoom() override;
 
	void SetupSmallestSize(Window *w) override;
 
	void AssignSizePosition(SizingType sizing, int x, int y, uint given_width, uint given_height, bool rtl) override;
 
	void FillWidgetLookup(WidgetLookup &widget_lookup) override;
 

	
 
	void Draw(const Window *w) override;
 
	NWidgetCore *GetWidgetFromPos(int x, int y) override;
 

	
 
	bool SetDisplayedPlane(int plane);
 

	
 
	int shown_plane; ///< Plane being displayed (for #NWID_SELECTION only).
 
	WidgetID index;  ///< If non-negative, index in the #Window::widget_lookup.
 
	const WidgetID index; ///< If non-negative, index in the #Window::widget_lookup.
 
};
 

	
 
/** Nested widget container flags, */
 
enum NWidContainerFlags {
 
	NCB_EQUALSIZE = 0, ///< Containers should keep all their (resizing) children equally large.
 
	NCB_BIGFIRST  = 1, ///< Allocate space to biggest resize first.
 
@@ -554,29 +551,27 @@ public:
 
 * DrawWidget and OnClick calls will be done to that sub-widget, where the
 
 * 16 high bits are used to encode the index into the matrix.
 
 * @ingroup NestedWidgets
 
 */
 
class NWidgetMatrix : public NWidgetPIPContainer {
 
public:
 
	NWidgetMatrix();
 
	NWidgetMatrix(Colours colour, WidgetID index);
 

	
 
	void SetIndex(WidgetID index);
 
	void SetColour(Colours colour);
 
	void SetClicked(int clicked);
 
	void SetCount(int count);
 
	void SetScrollbar(Scrollbar *sb);
 
	int GetCurrentElement() const;
 

	
 
	void SetupSmallestSize(Window *w) override;
 
	void AssignSizePosition(SizingType sizing, int x, int y, uint given_width, uint given_height, bool rtl) override;
 
	void FillWidgetLookup(WidgetLookup &widget_lookup) override;
 

	
 
	NWidgetCore *GetWidgetFromPos(int x, int y) override;
 
	void Draw(const Window *w) override;
 
protected:
 
	WidgetID index; ///< If non-negative, index in the #Window::widget_lookup.
 
	const WidgetID index; ///< If non-negative, index in the #Window::widget_lookup.
 
	Colours colour; ///< Colour of this widget.
 
	int clicked;    ///< The currently clicked element.
 
	int count;      ///< Amount of valid elements.
 
	int current_element; ///< The element currently being processed.
 
	Scrollbar *sb;  ///< The scrollbar we're associated with.
 
private:
0 comments (0 inline, 0 general)