Now that SkipGarbage doesn't skip all multi-byte utf-8 characters, string control codes are not skipped either. This gave unintended sorting when NewGRF names start with colour codes.
Use StrMakeValid() before comparing. This has to make a copy of the string for each sort step, so there is likely a performance penalty.
Set colour for these widget types to INVALID_COLOUR to avoid giving the impression that the colour has a purpose.
A runtime exception is added to catch this the existing widget unit test.
All GRFConfigs have space allocated for parameters, but only configured GRFConfigs need them.
Using a vector instead means that space is only used when parameters are used.
Use member-initialisation, reorder members to reduce space, and prefer references.
SetValue/GetValue are moved to GRFConfig as they set the config's parameter values.
For non-WWT_MATRIX widgets, scrollbars need to take account of the internal padding used for the widget.
This is not normally noticeable as framerect padding is only 2 extra pixels
After sorting and filter lists for GUI, we often shirnk them to reduce size. However this has very little benefit:
1) The memory has already been allocated, so it doesn't prevent that memory being required.
2) It causes a new allocation and copy when the vector is shrunk, actually using more memory.
3) The list is in window state, so the lifetime is only while the window is open.
4) When a filter is clearer, the original size will be needed again, which will cause another allocation.
In fact it is beneficial to reserve to the known maximum in most cases, so do that instead.
GUIList has a pointer only to the start of each sort/filter func list, which has the potential for UB as it is unable to validate that the selected sort or filter type is in range.
Use a std::span instead and check if the selected type is in range before using it.
SetStringParameters() was called during widget tree init in the constructor.
Calls within a constructor cannot call the derived classes methods. This would result in invalid data being passed to the string system, which could then crash.
Having two ways (`FillNestedArray` and `SetupSmallestSize`) to initialize
`Window::nested_array` introduces confusion.
Instead, make `FillNestedArray` the canonical way, always call it, and remove
init_array from `SetupSmallestSize`.
When clicked, the button is still highlighted to show that it is active.
The bevel is controlled with widget_data by RWV_SHOW_BEVEL or RWV_HIDE_BEVEL values.