Changeset - r10610:8e0fac091bf3
[Not reviewed]
master
0 7 0
rubidium - 15 years ago 2009-01-07 16:11:27
rubidium@openttd.org
(svn r14899) -Feature: remove the window limit, but leave a configurable limit on the number of non-sticky non-vital windows.
-Fix [FS#2499]: crashes/misbehaviours when (almost) all windows are stickied.
7 files changed with 137 insertions and 139 deletions:
0 comments (0 inline, 0 general)
src/lang/english.txt
Show inline comments
 
@@ -1188,24 +1188,26 @@ STR_CONFIG_PATCHES_TOWN_LAYOUT_NO_ROADS 
 
STR_CONFIG_PATCHES_TOWN_LAYOUT_DEFAULT                          :default
 
STR_CONFIG_PATCHES_TOWN_LAYOUT_BETTER_ROADS                     :better roads
 
STR_CONFIG_PATCHES_TOWN_LAYOUT_2X2_GRID                         :2x2 grid
 
STR_CONFIG_PATCHES_TOWN_LAYOUT_3X3_GRID                         :3x3 grid
 
STR_CONFIG_PATCHES_TOWN_LAYOUT_RANDOM                           :random
 

	
 
STR_CONFIG_PATCHES_TOOLBAR_POS                                  :{LTBLUE}Position of main toolbar: {ORANGE}{STRING1}
 
STR_CONFIG_PATCHES_TOOLBAR_POS_LEFT                             :Left
 
STR_CONFIG_PATCHES_TOOLBAR_POS_CENTER                           :Centre
 
STR_CONFIG_PATCHES_TOOLBAR_POS_RIGHT                            :Right
 
STR_CONFIG_PATCHES_SNAP_RADIUS                                  :{LTBLUE}Window snap radius: {ORANGE}{STRING1} px
 
STR_CONFIG_PATCHES_SNAP_RADIUS_DISABLED                         :{LTBLUE}Window snap radius: {ORANGE}disabled
 
STR_CONFIG_PATCHES_SOFT_LIMIT                                   :{LTBLUE}Window soft limit (non-sticky): {ORANGE}{STRING1}
 
STR_CONFIG_PATCHES_SOFT_LIMIT_DISABLED                          :{LTBLUE}Window soft limit (non-sticky): {ORANGE}disabled
 
STR_CONFIG_PATCHES_TOWN_GROWTH                                  :{LTBLUE}Town growth speed: {ORANGE}{STRING1}
 
STR_CONFIG_PATCHES_TOWN_GROWTH_NONE                             :None
 
STR_CONFIG_PATCHES_TOWN_GROWTH_SLOW                             :Slow
 
STR_CONFIG_PATCHES_TOWN_GROWTH_NORMAL                           :Normal
 
STR_CONFIG_PATCHES_TOWN_GROWTH_FAST                             :Fast
 
STR_CONFIG_PATCHES_TOWN_GROWTH_VERY_FAST                        :Very fast
 
STR_CONFIG_PATCHES_LARGER_TOWNS                                 :{LTBLUE}Proportion of towns that will become cities: {ORANGE}1 in {STRING1}
 
STR_CONFIG_PATCHES_LARGER_TOWNS_DISABLED                        :{LTBLUE}Proportion of towns that will become cities: {ORANGE}None
 
STR_CONFIG_PATCHES_CITY_SIZE_MULTIPLIER                         :{LTBLUE}Initial city size multiplier: {ORANGE}{STRING1}
 
STR_CONFIG_MODIFIED_ROAD_REBUILD                                :{LTBLUE}Remove absurd road-elements during the road construction
 

	
 
STR_CONFIG_PATCHES_GUI                                          :{BLACK}Interface
src/settings.cpp
Show inline comments
 
@@ -1420,24 +1420,25 @@ const SettingDesc _patch_settings[] = {
 
	SDTC_OMANY(gui.date_format_in_default_names,SLE_UINT8,S,MS, 0, 2, "long|short|iso",       STR_CONFIG_PATCHES_DATE_FORMAT_IN_SAVE_NAMES,   NULL),
 
	 SDTC_BOOL(gui.vehicle_speed,                        S,  0,  true,                        STR_CONFIG_PATCHES_VEHICLESPEED,                NULL),
 
	 SDTC_BOOL(gui.status_long_date,                     S,  0,  true,                        STR_CONFIG_PATCHES_LONGDATE,                    NULL),
 
	 SDTC_BOOL(gui.show_finances,                        S,  0,  true,                        STR_CONFIG_PATCHES_SHOWFINANCES,                NULL),
 
	 SDTC_BOOL(gui.autoscroll,                           S,  0, false,                        STR_CONFIG_PATCHES_AUTOSCROLL,                  NULL),
 
	 SDTC_BOOL(gui.reverse_scroll,                       S,  0, false,                        STR_CONFIG_PATCHES_REVERSE_SCROLLING,           NULL),
 
	 SDTC_BOOL(gui.smooth_scroll,                        S,  0, false,                        STR_CONFIG_PATCHES_SMOOTH_SCROLLING,            NULL),
 
	 SDTC_BOOL(gui.left_mouse_btn_scrolling,             S,  0, false,                        STR_CONFIG_PATCHES_LEFT_MOUSE_BTN_SCROLLING,    NULL),
 
	 SDTC_BOOL(gui.measure_tooltip,                      S,  0, false,                        STR_CONFIG_PATCHES_MEASURE_TOOLTIP,             NULL),
 
	  SDTC_VAR(gui.errmsg_duration,           SLE_UINT8, S,  0,     5,        0,       20, 0, STR_CONFIG_PATCHES_ERRMSG_DURATION,             NULL),
 
	  SDTC_VAR(gui.toolbar_pos,               SLE_UINT8, S, MS,     0,        0,        2, 0, STR_CONFIG_PATCHES_TOOLBAR_POS,                 v_PositionMainToolbar),
 
	  SDTC_VAR(gui.window_snap_radius,        SLE_UINT8, S, D0,    10,        1,       32, 0, STR_CONFIG_PATCHES_SNAP_RADIUS,                 NULL),
 
	  SDTC_VAR(gui.window_soft_limit,         SLE_UINT8, S, D0,    20,        5,      255, 1, STR_CONFIG_PATCHES_SOFT_LIMIT,                  NULL),
 
	 SDTC_BOOL(gui.population_in_label,                  S,  0,  true,                        STR_CONFIG_PATCHES_POPULATION_IN_LABEL,         PopulationInLabelActive),
 
	 SDTC_BOOL(gui.link_terraform_toolbar,               S,  0, false,                        STR_CONFIG_PATCHES_LINK_TERRAFORM_TOOLBAR,      NULL),
 
	  SDTC_VAR(gui.liveries,                  SLE_UINT8, S, MS,     2,        0,        2, 0, STR_CONFIG_PATCHES_LIVERIES,                    RedrawScreen),
 
	 SDTC_BOOL(gui.prefer_teamchat,                      S,  0, false,                        STR_CONFIG_PATCHES_PREFER_TEAMCHAT,             NULL),
 
	  SDTC_VAR(gui.scrollwheel_scrolling,     SLE_UINT8, S, MS,     0,        0,        2, 0, STR_CONFIG_PATCHES_SCROLLWHEEL_SCROLLING,       NULL),
 
	  SDTC_VAR(gui.scrollwheel_multiplier,    SLE_UINT8, S,  0,     5,        1,       15, 1, STR_CONFIG_PATCHES_SCROLLWHEEL_MULTIPLIER,      NULL),
 
	 SDTC_BOOL(gui.pause_on_newgame,                     S,  0, false,                        STR_CONFIG_PATCHES_PAUSE_ON_NEW_GAME,           NULL),
 
	  SDTC_VAR(gui.advanced_vehicle_list,     SLE_UINT8, S, MS,     1,        0,        2, 0, STR_CONFIG_PATCHES_ADVANCED_VEHICLE_LISTS,      NULL),
 
	 SDTC_BOOL(gui.timetable_in_ticks,                   S,  0, false,                        STR_CONFIG_PATCHES_TIMETABLE_IN_TICKS,          NULL),
 
	 SDTC_BOOL(gui.quick_goto,                           S,  0, false,                        STR_CONFIG_PATCHES_QUICKGOTO,                   NULL),
 
	  SDTC_VAR(gui.loading_indicators,        SLE_UINT8, S, MS,     1,        0,        2, 0, STR_CONFIG_PATCHES_LOADING_INDICATORS,          RedrawScreen),
 
	  SDTC_VAR(gui.default_rail_type,         SLE_UINT8, S, MS,     4,        0,        6, 0, STR_CONFIG_PATCHES_DEFAULT_RAIL_TYPE,           NULL),
src/settings_gui.cpp
Show inline comments
 
@@ -609,24 +609,25 @@ struct PatchPage {
 
static const char *_patches_ui[] = {
 
	"gui.vehicle_speed",
 
	"gui.status_long_date",
 
	"gui.date_format_in_default_names",
 
	"gui.show_finances",
 
	"gui.autoscroll",
 
	"gui.reverse_scroll",
 
	"gui.smooth_scroll",
 
	"gui.errmsg_duration",
 
	"gui.toolbar_pos",
 
	"gui.measure_tooltip",
 
	"gui.window_snap_radius",
 
	"gui.window_soft_limit",
 
	"gui.population_in_label",
 
	"gui.link_terraform_toolbar",
 
	"gui.liveries",
 
	"gui.prefer_teamchat",
 
	/* While the horizontal scrollwheel scrolling is written as general code, only
 
	 *  the cocoa (OSX) driver generates input for it.
 
	 *  Since it's also able to completely disable the scrollwheel will we display it on all platforms anyway */
 
	"gui.scrollwheel_scrolling",
 
	"gui.scrollwheel_multiplier",
 
#ifdef __APPLE__
 
	/* We might need to emulate a right mouse button on mac */
 
	"gui.right_mouse_btn_emulation",
src/settings_type.h
Show inline comments
 
@@ -48,24 +48,25 @@ struct GUISettings {
 
	byte   errmsg_duration;                  ///< duration of error message
 
	bool   link_terraform_toolbar;           ///< display terraform toolbar when displaying rail, road, water and airport toolbars
 
	bool   reverse_scroll;                   ///< right-Click-Scrolling scrolls in the opposite direction
 
	bool   smooth_scroll;                    ///< smooth scroll viewports
 
	bool   measure_tooltip;                  ///< show a permanent tooltip when dragging tools
 
	byte   liveries;                         ///< options for displaying company liveries, 0=none, 1=self, 2=all
 
	bool   prefer_teamchat;                  ///< choose the chat message target with <ENTER>, true=all clients, false=your team
 
	uint8  advanced_vehicle_list;            ///< use the "advanced" vehicle list
 
	uint8  loading_indicators;               ///< show loading indicators
 
	uint8  default_rail_type;                ///< the default rail type for the rail GUI
 
	uint8  toolbar_pos;                      ///< position of toolbars, 0=left, 1=center, 2=right
 
	uint8  window_snap_radius;               ///< windows snap at each other if closer than this
 
	uint8  window_soft_limit;                ///< soft limit of maximum number of non-stickied non-vital windows (0 = no limit)
 
	bool   always_build_infrastructure;      ///< always allow building of infrastructure, even when you do not have the vehicles for it
 
	byte   autosave;                         ///< how often should we do autosaves?
 
	bool   keep_all_autosave;                ///< name the autosave in a different way
 
	bool   autosave_on_exit;                 ///< save an autosave when you quit the game, but do not ask "Do you really want to quit?"
 
	uint8  date_format_in_default_names;     ///< should the default savegame/screenshot name use long dates (31th Dec 2008), short dates (31-12-2008) or ISO dates (2008-12-31)
 
	byte   max_num_autosaves;                ///< controls how many autosavegames are made before the game starts to overwrite (names them 0 to max_num_autosaves - 1)
 
	bool   population_in_label;              ///< show the population of a town in his label?
 
	uint8  right_mouse_btn_emulation;        ///< should we emulate right mouse clicking?
 
	uint8  scrollwheel_scrolling;            ///< scrolling using the scroll wheel?
 
	uint8  scrollwheel_multiplier;           ///< how much 'wheel' per incoming event from the OS?
 
	bool   left_mouse_btn_scrolling;         ///< left mouse button scroll
 
	bool   pause_on_newgame;                 ///< whether to start new games paused or not
src/viewport.cpp
Show inline comments
 
@@ -208,56 +208,54 @@ void InitializeWindowViewport(Window *w,
 
	vp->scrollpos_x = pt.x;
 
	vp->scrollpos_y = pt.y;
 
	vp->dest_scrollpos_x = pt.x;
 
	vp->dest_scrollpos_y = pt.y;
 

	
 
	w->viewport = vp;
 
	vp->virtual_left = 0;//pt.x;
 
	vp->virtual_top = 0;//pt.y;
 
}
 

	
 
static Point _vp_move_offs;
 

	
 
static void DoSetViewportPosition(Window* const *wz, int left, int top, int width, int height)
 
static void DoSetViewportPosition(const Window *w, int left, int top, int width, int height)
 
{
 

	
 
	for (; wz != _last_z_window; wz++) {
 
		const Window *w = *wz;
 

	
 
	for (; w != NULL; w = w->z_front) {
 
		if (left + width > w->left &&
 
				w->left + w->width > left &&
 
				top + height > w->top &&
 
				w->top + w->height > top) {
 

	
 
			if (left < w->left) {
 
				DoSetViewportPosition(wz, left, top, w->left - left, height);
 
				DoSetViewportPosition(wz, left + (w->left - left), top, width - (w->left - left), height);
 
				DoSetViewportPosition(w, left, top, w->left - left, height);
 
				DoSetViewportPosition(w, left + (w->left - left), top, width - (w->left - left), height);
 
				return;
 
			}
 

	
 
			if (left + width > w->left + w->width) {
 
				DoSetViewportPosition(wz, left, top, (w->left + w->width - left), height);
 
				DoSetViewportPosition(wz, left + (w->left + w->width - left), top, width - (w->left + w->width - left) , height);
 
				DoSetViewportPosition(w, left, top, (w->left + w->width - left), height);
 
				DoSetViewportPosition(w, left + (w->left + w->width - left), top, width - (w->left + w->width - left) , height);
 
				return;
 
			}
 

	
 
			if (top < w->top) {
 
				DoSetViewportPosition(wz, left, top, width, (w->top - top));
 
				DoSetViewportPosition(wz, left, top + (w->top - top), width, height - (w->top - top));
 
				DoSetViewportPosition(w, left, top, width, (w->top - top));
 
				DoSetViewportPosition(w, left, top + (w->top - top), width, height - (w->top - top));
 
				return;
 
			}
 

	
 
			if (top + height > w->top + w->height) {
 
				DoSetViewportPosition(wz, left, top, width, (w->top + w->height - top));
 
				DoSetViewportPosition(wz, left, top + (w->top + w->height - top), width , height - (w->top + w->height - top));
 
				DoSetViewportPosition(w, left, top, width, (w->top + w->height - top));
 
				DoSetViewportPosition(w, left, top + (w->top + w->height - top), width , height - (w->top + w->height - top));
 
				return;
 
			}
 

	
 
			return;
 
		}
 
	}
 

	
 
	{
 
		int xo = _vp_move_offs.x;
 
		int yo = _vp_move_offs.y;
 

	
 
		if (abs(xo) >= width || abs(yo) >= height) {
 
@@ -325,25 +323,25 @@ static void SetViewportPosition(Window *
 
	i = left + width - _screen.width;
 
	if (i >= 0) width -= i;
 

	
 
	if (width > 0) {
 
		if (top < 0) {
 
			height += top;
 
			top = 0;
 
		}
 

	
 
		i = top + height - _screen.height;
 
		if (i >= 0) height -= i;
 

	
 
		if (height > 0) DoSetViewportPosition(FindWindowZPosition(w) + 1, left, top, width, height);
 
		if (height > 0) DoSetViewportPosition(w->z_front, left, top, width, height);
 
	}
 
}
 

	
 
/**
 
 * Is a xy position inside the viewport of the window?
 
 * @param w Window to examine its viewport
 
 * @param x X coordinate of the xy position
 
 * @param y Y coordinate of the xy position
 
 * @return Pointer to the viewport if the xy position is in the viewport of the window,
 
 *         otherwise \c NULL is returned.
 
 */
 
ViewPort *IsPtInWindowViewport(const Window *w, int x, int y)
src/window.cpp
Show inline comments
 
@@ -22,31 +22,28 @@
 
#include "settings_type.h"
 
#include "cheat_func.h"
 
#include "window_func.h"
 
#include "tilehighlight_func.h"
 
#include "network/network.h"
 
#include "querystring_gui.h"
 

	
 
#include "table/sprites.h"
 

	
 
static Point _drag_delta; ///< delta between mouse cursor and upper left corner of dragged window
 
static Window *_mouseover_last_w = NULL; ///< Window of the last MOUSEOVER event
 

	
 
/**
 
 * List of windows opened at the screen.
 
 * Uppermost window is at  _z_windows[_last_z_window - 1],
 
 * bottom window is at _z_windows[0]
 
 */
 
Window *_z_windows[MAX_NUMBER_OF_WINDOWS];
 
Window **_last_z_window; ///< always points to the next free space in the z-array
 
/** List of windows opened at the screen sorted from the front. */
 
Window *_z_front_window = NULL;
 
/** List of windows opened at the screen sorted from the back. */
 
Window *_z_back_window  = NULL;
 

	
 
byte _no_scroll;
 
Point _cursorpos_drag_start;
 

	
 
int _scrollbar_start_pos;
 
int _scrollbar_size;
 
byte _scroller_click_timeout;
 

	
 
bool _scrolling_scrollbar;
 
bool _scrolling_viewport;
 

	
 
byte _special_mouse_mode;
 
@@ -277,110 +274,106 @@ static void DispatchMouseWheelEvent(Wind
 

	
 
		if (sb->count > sb->cap) {
 
			int pos = Clamp(sb->pos + wheel, 0, sb->count - sb->cap);
 
			if (pos != sb->pos) {
 
				sb->pos = pos;
 
				w->SetDirty();
 
			}
 
		}
 
	}
 
}
 

	
 
/**
 
 * Generate repaint events for the visible part of window *wz within the rectangle.
 
 * Generate repaint events for the visible part of window w within the rectangle.
 
 *
 
 * The function goes recursively upwards in the window stack, and splits the rectangle
 
 * into multiple pieces at the window edges, so obscured parts are not redrawn.
 
 *
 
 * @param wz Pointer into window stack, pointing at the window that needs to be repainted
 
 * @param w Window that needs to be repainted
 
 * @param left Left edge of the rectangle that should be repainted
 
 * @param top Top edge of the rectangle that should be repainted
 
 * @param right Right edge of the rectangle that should be repainted
 
 * @param bottom Bottom edge of the rectangle that should be repainted
 
 */
 
static void DrawOverlappedWindow(Window* const *wz, int left, int top, int right, int bottom)
 
static void DrawOverlappedWindow(Window *w, int left, int top, int right, int bottom)
 
{
 
	Window* const *vz = wz;
 

	
 
	while (++vz != _last_z_window) {
 
		const Window *v = *vz;
 

	
 
	for (const Window *v = w->z_front; v != NULL; v = v->z_front) {
 
		if (right > v->left &&
 
				bottom > v->top &&
 
				left < v->left + v->width &&
 
				top < v->top + v->height) {
 
			/* v and rectangle intersect with eeach other */
 
			int x;
 

	
 
			if (left < (x = v->left)) {
 
				DrawOverlappedWindow(wz, left, top, x, bottom);
 
				DrawOverlappedWindow(wz, x, top, right, bottom);
 
				DrawOverlappedWindow(w, left, top, x, bottom);
 
				DrawOverlappedWindow(w, x, top, right, bottom);
 
				return;
 
			}
 

	
 
			if (right > (x = v->left + v->width)) {
 
				DrawOverlappedWindow(wz, left, top, x, bottom);
 
				DrawOverlappedWindow(wz, x, top, right, bottom);
 
				DrawOverlappedWindow(w, left, top, x, bottom);
 
				DrawOverlappedWindow(w, x, top, right, bottom);
 
				return;
 
			}
 

	
 
			if (top < (x = v->top)) {
 
				DrawOverlappedWindow(wz, left, top, right, x);
 
				DrawOverlappedWindow(wz, left, x, right, bottom);
 
				DrawOverlappedWindow(w, left, top, right, x);
 
				DrawOverlappedWindow(w, left, x, right, bottom);
 
				return;
 
			}
 

	
 
			if (bottom > (x = v->top + v->height)) {
 
				DrawOverlappedWindow(wz, left, top, right, x);
 
				DrawOverlappedWindow(wz, left, x, right, bottom);
 
				DrawOverlappedWindow(w, left, top, right, x);
 
				DrawOverlappedWindow(w, left, x, right, bottom);
 
				return;
 
			}
 

	
 
			return;
 
		}
 
	}
 

	
 
	/* Setup blitter, and dispatch a repaint event to window *wz */
 
	DrawPixelInfo *dp = _cur_dpi;
 
	dp->width = right - left;
 
	dp->height = bottom - top;
 
	dp->left = left - (*wz)->left;
 
	dp->top = top - (*wz)->top;
 
	dp->left = left - w->left;
 
	dp->top = top - w->top;
 
	dp->pitch = _screen.pitch;
 
	dp->dst_ptr = BlitterFactoryBase::GetCurrentBlitter()->MoveTo(_screen.dst_ptr, left, top);
 
	dp->zoom = ZOOM_LVL_NORMAL;
 
	(*wz)->OnPaint();
 
	w->OnPaint();
 
}
 

	
 
/**
 
 * From a rectangle that needs redrawing, find the windows that intersect with the rectangle.
 
 * These windows should be re-painted.
 
 * @param left Left edge of the rectangle that should be repainted
 
 * @param top Top edge of the rectangle that should be repainted
 
 * @param right Right edge of the rectangle that should be repainted
 
 * @param bottom Bottom edge of the rectangle that should be repainted
 
 */
 
void DrawOverlappedWindowForAll(int left, int top, int right, int bottom)
 
{
 
	const Window *w;
 
	Window *w;
 
	DrawPixelInfo bk;
 
	_cur_dpi = &bk;
 

	
 
	FOR_ALL_WINDOWS_FROM_BACK(w) {
 
		if (right > w->left &&
 
				bottom > w->top &&
 
				left < w->left + w->width &&
 
				top < w->top + w->height) {
 
			/* Window w intersects with the rectangle => needs repaint */
 
			DrawOverlappedWindow(wz, left, top, right, bottom);
 
			DrawOverlappedWindow(w, left, top, right, bottom);
 
		}
 
	}
 
}
 

	
 
/**
 
 * Mark entire window as dirty (in need of re-paint)
 
 * @ingroup dirty
 
 */
 
void Window::SetDirty() const
 
{
 
	SetDirtyBlocks(this->left, this->top, this->left + this->width, this->top + this->height);
 
}
 
@@ -399,42 +392,24 @@ void SetWindowDirty(const Window *w)
 
 * @param w parent Window to find child of
 
 * @return a Window pointer that is the child of w, or NULL otherwise */
 
static Window *FindChildWindow(const Window *w)
 
{
 
	Window *v;
 
	FOR_ALL_WINDOWS_FROM_BACK(v) {
 
		if (v->parent == w) return v;
 
	}
 

	
 
	return NULL;
 
}
 

	
 
/** Find the z-value of a window. A window must already be open
 
 * or the behaviour is undefined but function should never fail
 
 * @param w window to query Z Position
 
 * @return Pointer into the window-list at the position of \a w
 
 */
 
Window **FindWindowZPosition(const Window *w)
 
{
 
	const Window *v;
 

	
 
	FOR_ALL_WINDOWS_FROM_BACK(v) {
 
		if (v == w) return wz;
 
	}
 

	
 
	DEBUG(misc, 3, "Window (cls %d, number %d) is not open, probably removed by recursive calls",
 
		w->window_class, w->window_number);
 
	return NULL;
 
}
 

	
 
/**
 
 * Delete all children a window might have in a head-recursive manner
 
 */
 
void Window::DeleteChildWindows() const
 
{
 
	Window *child = FindChildWindow(this);
 
	while (child != NULL) {
 
		delete child;
 
		child = FindChildWindow(this);
 
	}
 
}
 

	
 
@@ -447,28 +422,34 @@ Window::~Window()
 
			_thd.window_class == this->window_class &&
 
			_thd.window_number == this->window_number) {
 
		ResetObjectToPlace();
 
	}
 

	
 
	/* Prevent Mouseover() from resetting mouse-over coordinates on a non-existing window */
 
	if (_mouseover_last_w == this) _mouseover_last_w = NULL;
 

	
 
	/* Find the window in the z-array, and effectively remove it
 
	 * by moving all windows after it one to the left. This must be
 
	 * done before removing the child so we cannot cause recursion
 
	 * between the deletion of the parent and the child. */
 
	Window **wz = FindWindowZPosition(this);
 
	if (wz == NULL) return;
 
	memmove(wz, wz + 1, (byte*)_last_z_window - (byte*)wz);
 
	_last_z_window--;
 
	if (this->z_front == NULL) {
 
		_z_front_window = this->z_back;
 
	} else {
 
		this->z_front->z_back = this->z_back;
 
	}
 
	if (this->z_back == NULL) {
 
		_z_back_window  = this->z_front;
 
	} else {
 
		this->z_back->z_front = this->z_front;
 
	}
 

	
 
	this->DeleteChildWindows();
 

	
 
	if (this->viewport != NULL) DeleteWindowViewport(this);
 

	
 
	this->SetDirty();
 

	
 
	if (this->widget != NULL) {
 
		for (const Widget *wi = this->widget; wi->type != WWT_LAST; wi++) {
 
			if (wi->type == WWT_EDITBOX) _no_scroll--;
 
		}
 
		free(this->widget);
 
@@ -571,25 +552,25 @@ void ChangeWindowOwner(Owner old_owner, 
 
			case WC_AIRCRAFT_LIST:
 
			case WC_BUY_COMPANY:
 
			case WC_COMPANY:
 
				continue;
 

	
 
			default:
 
				w->caption_color = new_owner;
 
				break;
 
		}
 
	}
 
}
 

	
 
static void BringWindowToFront(const Window *w);
 
static void BringWindowToFront(Window *w);
 

	
 
/** Find a window and make it the top-window on the screen. The window
 
 * gets a white border for a brief period of time to visualize its "activation"
 
 * @param cls WindowClass of the window to activate
 
 * @param number WindowNumber of the window to activate
 
 * @return a pointer to the window thus activated */
 
Window *BringWindowToFrontById(WindowClass cls, WindowNumber number)
 
{
 
	Window *w = FindWindowById(cls, number);
 

	
 
	if (w != NULL) {
 
		w->flags4 |= WF_WHITE_BORDER_MASK;
 
@@ -613,78 +594,56 @@ static inline bool IsVitalWindow(const W
 
			return false;
 
	}
 
}
 

	
 
/** On clicking on a window, make it the frontmost window of all. However
 
 * there are certain windows that always need to be on-top; these include
 
 * - Toolbar, Statusbar (always on)
 
 * - New window, Chatbar (only if open)
 
 * The window is marked dirty for a repaint if the window is actually moved
 
 * @param w window that is put into the foreground
 
 * @return pointer to the window, the same as the input pointer
 
 */
 
static void BringWindowToFront(const Window *w)
 
static void BringWindowToFront(Window *w)
 
{
 
	Window **wz = FindWindowZPosition(w);
 
	Window **vz = _last_z_window;
 
	Window *v = _z_front_window;
 

	
 
	/* Bring the window just below the vital windows */
 
	do {
 
		if (--vz < _z_windows) return;
 
	} while (IsVitalWindow(*vz));
 
	for (; v != NULL && v != w && IsVitalWindow(v); v = v->z_back) { }
 

	
 
	if (v == NULL || w == v) return; // window is already in the right position
 

	
 
	/* w cannot be at the top already! */
 
	assert(w != _z_front_window);
 

	
 
	if (wz == vz) return; // window is already in the right position
 
	assert(wz < vz);
 
	if (w->z_back == NULL) {
 
		_z_back_window = w->z_front;
 
	} else {
 
		w->z_back->z_front = w->z_front;
 
	}
 
	w->z_front->z_back = w->z_back;
 

	
 
	Window *tempz = *wz;
 
	memmove(wz, wz + 1, (byte*)vz - (byte*)wz);
 
	*vz = tempz;
 
	w->z_front = v->z_front;
 
	w->z_back = v;
 

	
 
	if (v->z_front == NULL) {
 
		_z_front_window = w;
 
	} else {
 
		v->z_front->z_back = w;
 
	}
 
	v->z_front = w;
 

	
 
	w->SetDirty();
 
}
 

	
 
/** We have run out of windows, so find a suitable candidate for replacement.
 
 * Keep all important windows intact. These are
 
 * - Main window (gamefield), Toolbar, Statusbar (always on)
 
 * - News window, Chatbar (when on)
 
 * - Any sticked windows since we wanted to keep these
 
 * @return w pointer to the window that is going to be deleted
 
 */
 
static Window *FindDeletableWindow()
 
{
 
	Window *w;
 
	FOR_ALL_WINDOWS_FROM_BACK(w) {
 
		if (w->window_class != WC_MAIN_WINDOW && !IsVitalWindow(w) && !(w->flags4 & WF_STICKY)) {
 
			return w;
 
		}
 
	}
 
	return NULL;
 
}
 

	
 
/** A window must be freed, and all are marked as important windows. Ease the
 
 * restriction a bit by allowing to delete sticky windows. Keep important/vital
 
 * windows intact (Main window, Toolbar, Statusbar, News Window, Chatbar)
 
 * Start finding an appropiate candidate from the lowest z-values (bottom)
 
 * @see FindDeletableWindow()
 
 * @return w Pointer to the window that is being deleted
 
 */
 
static Window *ForceFindDeletableWindow()
 
{
 
	Window *w;
 
	FOR_ALL_WINDOWS_FROM_BACK(w) {
 
		if (w->window_class != WC_MAIN_WINDOW && !IsVitalWindow(w)) return w;
 
	}
 
	NOT_REACHED();
 
}
 

	
 
/**
 
 * Assign widgets to a new window by initialising its widget pointers, and by
 
 * copying the widget array \a widget to \c w->widget to allow for resizable
 
 * windows.
 
 * @param w Window on which to attach the widget array
 
 * @param widget pointer of widget array to fill the window with
 
 *
 
 * @post \c w->widget points to allocated memory and contains the copied widget array except for the terminating widget,
 
 *       \c w->widget_count contains number of widgets in the allocated memory.
 
 */
 
static void AssignWidgetToWindow(Window *w, const Widget *widget)
 
{
 
@@ -714,67 +673,78 @@ static void AssignWidgetToWindow(Window 
 
 * @param x offset in pixels from the left of the screen
 
 * @param y offset in pixels from the top of the screen
 
 * @param min_width minimum width in pixels of the window
 
 * @param min_height minimum height in pixels of the window
 
 * @param cls see WindowClass class of the window, used for identification and grouping
 
 * @param *widget see Widget pointer to the window layout and various elements
 
 * @param window_number number being assigned to the new window
 
 * @return Window pointer of the newly created window
 
 */
 
void Window::Initialize(int x, int y, int min_width, int min_height,
 
				WindowClass cls, const Widget *widget, int window_number)
 
{
 
	/* We have run out of windows, close one and use that as the place for our new one */
 
	if (_last_z_window == endof(_z_windows)) {
 
		Window *w = FindDeletableWindow();
 
		if (w == NULL) w = ForceFindDeletableWindow();
 
		delete w;
 
	}
 

	
 
	/* Set up window properties */
 
	this->window_class = cls;
 
	this->flags4 = WF_WHITE_BORDER_MASK; // just opened windows have a white border
 
	this->caption_color = 0xFF;
 
	this->left = x;
 
	this->top = y;
 
	this->width = min_width;
 
	this->height = min_height;
 
	AssignWidgetToWindow(this, widget);
 
	this->resize.width = min_width;
 
	this->resize.height = min_height;
 
	this->resize.step_width = 1;
 
	this->resize.step_height = 1;
 
	this->window_number = window_number;
 

	
 
	/* Hacky way of specifying always-on-top windows. These windows are
 
		* always above other windows because they are moved below them.
 
		* status-bar is above news-window because it has been created earlier.
 
		* Also, as the chat-window is excluded from this, it will always be
 
		* the last window, thus always on top.
 
		* XXX - Yes, ugly, probably needs something like w->always_on_top flag
 
		* to implement correctly, but even then you need some kind of distinction
 
		* between on-top of chat/news and status windows, because these conflict */
 
	Window **wz = _last_z_window;
 
	if (wz != _z_windows && this->window_class != WC_SEND_NETWORK_MSG && this->window_class != WC_HIGHSCORE && this->window_class != WC_ENDSCREEN) {
 
		if (FindWindowById(WC_MAIN_TOOLBAR, 0)     != NULL) wz--;
 
		if (FindWindowById(WC_STATUS_BAR, 0)       != NULL) wz--;
 
		if (FindWindowById(WC_NEWS_WINDOW, 0)      != NULL) wz--;
 
		if (FindWindowById(WC_SEND_NETWORK_MSG, 0) != NULL) wz--;
 
	Window *w = _z_front_window;
 
	if (w != NULL && this->window_class != WC_SEND_NETWORK_MSG && this->window_class != WC_HIGHSCORE && this->window_class != WC_ENDSCREEN) {
 
		if (FindWindowById(WC_MAIN_TOOLBAR, 0)     != NULL) w = w->z_back;
 
		if (FindWindowById(WC_STATUS_BAR, 0)       != NULL) w = w->z_back;
 
		if (FindWindowById(WC_NEWS_WINDOW, 0)      != NULL) w = w->z_back;
 
		if (FindWindowById(WC_SEND_NETWORK_MSG, 0) != NULL) w = w->z_back;
 

	
 
		assert(wz >= _z_windows);
 
		if (wz != _last_z_window) memmove(wz + 1, wz, (byte*)_last_z_window - (byte*)wz);
 
		if (w == NULL) {
 
			_z_back_window->z_front = this;
 
			this->z_back = _z_back_window;
 
			_z_back_window = this;
 
		} else {
 
			if (w->z_front == NULL) {
 
				_z_front_window = this;
 
			} else {
 
				this->z_front = w->z_front;
 
				w->z_front->z_back = this;
 
			}
 

	
 
			this->z_back = w;
 
			w->z_front = this;
 
		}
 
	} else {
 
		this->z_back = _z_front_window;
 
		if (_z_front_window != NULL) {
 
			_z_front_window->z_front = this;
 
		} else {
 
			_z_back_window = this;
 
		}
 
		_z_front_window = this;
 
	}
 

	
 
	*wz = this;
 
	_last_z_window++;
 
}
 

	
 
/**
 
 * Resize window towards the default size.
 
 * Prior to construction, a position for the new window (for its default size)
 
 * has been found with LocalGetWindowPlacement(). Initially, the window is
 
 * constructed with minimal size. Resizing the window to its default size is
 
 * done here.
 
 * @param def_width default width in pixels of the window
 
 * @param def_height default height in pixels of the window
 
 * @see Window::Window(), Window::Initialize()
 
 */
 
@@ -1100,36 +1070,37 @@ Window *FindWindowFromPt(int x, int y)
 
	}
 

	
 
	return NULL;
 
}
 

	
 
/**
 
 * (re)initialize the windowing system
 
 */
 
void InitWindowSystem()
 
{
 
	IConsoleClose();
 

	
 
	_last_z_window = _z_windows;
 
	_z_back_window = NULL;
 
	_z_front_window = NULL;
 
	_mouseover_last_w = NULL;
 
	_no_scroll = 0;
 
	_scrolling_viewport = 0;
 
}
 

	
 
/**
 
 * Close down the windowing system
 
 */
 
void UnInitWindowSystem()
 
{
 
	while (_last_z_window != _z_windows) delete _z_windows[0];
 
	while (_z_front_window != NULL) delete _z_front_window;
 
}
 

	
 
/**
 
 * Reset the windowing system, by means of shutting it down followed by re-initialization
 
 */
 
void ResetWindowSystem()
 
{
 
	UnInitWindowSystem();
 
	InitWindowSystem();
 
	_thd.pos.x = 0;
 
	_thd.pos.y = 0;
 
	_thd.new_pos.x = 0;
 
@@ -1592,39 +1563,36 @@ static bool HandleViewportScroll()
 
	_cursor.delta.y = 0;
 
	return false;
 
}
 

	
 
/** Check if a window can be made top-most window, and if so do
 
 * it. If a window does not obscure any other windows, it will not
 
 * be brought to the foreground. Also if the only obscuring windows
 
 * are so-called system-windows, the window will not be moved.
 
 * The function will return false when a child window of this window is a
 
 * modal-popup; function returns a false and child window gets a white border
 
 * @param w Window to bring on-top
 
 * @return false if the window has an active modal child, true otherwise */
 
static bool MaybeBringWindowToFront(const Window *w)
 
static bool MaybeBringWindowToFront(Window *w)
 
{
 
	bool bring_to_front = false;
 

	
 
	if (w->window_class == WC_MAIN_WINDOW ||
 
			IsVitalWindow(w) ||
 
			w->window_class == WC_TOOLTIPS ||
 
			w->window_class == WC_DROPDOWN_MENU) {
 
		return true;
 
	}
 

	
 
	Window * const *wz = FindWindowZPosition(w);
 
	for (Window * const *uz = wz; ++uz != _last_z_window;) {
 
		Window *u = *uz;
 

	
 
	for (Window *u = w->z_front; u != NULL; u = u->z_front) {
 
		/* A modal child will prevent the activation of the parent window */
 
		if (u->parent == w && (u->desc_flags & WDF_MODAL)) {
 
			u->flags4 |= WF_WHITE_BORDER_MASK;
 
			u->SetDirty();
 
			return false;
 
		}
 

	
 
		if (u->window_class == WC_MAIN_WINDOW ||
 
				IsVitalWindow(u) ||
 
				u->window_class == WC_TOOLTIPS ||
 
				u->window_class == WC_DROPDOWN_MENU) {
 
			continue;
 
@@ -1964,28 +1932,54 @@ void HandleMouseEvents()
 

	
 
	int mousewheel = 0;
 
	if (_cursor.wheel) {
 
		mousewheel = _cursor.wheel;
 
		_cursor.wheel = 0;
 
		_input_events_this_tick++;
 
	}
 

	
 
	MouseLoop(click, mousewheel);
 
}
 

	
 
/**
 
 * Check the soft limit of deletable (non vital, non sticky) windows.
 
 */
 
static void CheckSoftLimit()
 
{
 
	if (_settings_client.gui.window_soft_limit == 0) return;
 

	
 
	for (;;) {
 
		uint deletable_count = 0;
 
		Window *w, *last_deletable = NULL;
 
		FOR_ALL_WINDOWS_FROM_FRONT(w) {
 
			if (w->window_class == WC_MAIN_WINDOW || IsVitalWindow(w) || (w->flags4 & WF_STICKY)) continue;
 

	
 
			last_deletable = w;
 
			deletable_count++;
 
		}
 

	
 
		/* We've ot reached the soft limit yet */
 
		if (deletable_count <= _settings_client.gui.window_soft_limit) break;
 

	
 
		assert(last_deletable != NULL);
 
		delete last_deletable;
 
	}
 
}
 

	
 
/**
 
 * Regular call from the global game loop
 
 */
 
void InputLoop()
 
{
 
	CheckSoftLimit();
 
	HandleKeyScrolling();
 

	
 
	if (_input_events_this_tick != 0) {
 
		/* The input loop is called only once per GameLoop() - so we can clear the counter here */
 
		_input_events_this_tick = 0;
 
		/* there were some inputs this tick, don't scroll ??? */
 
		return;
 
	}
 

	
 
	/* HandleMouseEvents was already called for this tick */
 
	HandleMouseEvents();
 
	HandleAutoscroll();
src/window_gui.h
Show inline comments
 
@@ -217,24 +217,26 @@ public:
 
	Scrollbar vscroll;  ///< First vertical scroll bar
 
	Scrollbar vscroll2; ///< Second vertical scroll bar
 
	ResizeInfo resize;  ///< Resize information
 

	
 
	byte caption_color; ///< Background color of the window caption, contains CompanyID
 

	
 
	ViewportData *viewport;      ///< Pointer to viewport data, if present
 
	Widget *widget;        ///< Widgets of the window
 
	uint widget_count;     ///< Number of widgets of the window
 
	uint32 desc_flags;     ///< Window/widgets default flags setting, @see WindowDefaultFlag
 

	
 
	Window *parent;        ///< Parent window
 
	Window *z_front;       ///< The window in front of us in z-order
 
	Window *z_back;        ///< The window behind us in z-order
 

	
 
	void HandleButtonClick(byte widget);
 

	
 
	void SetWidgetDisabledState(byte widget_index, bool disab_stat);
 
	void DisableWidget(byte widget_index);
 
	void EnableWidget(byte widget_index);
 
	bool IsWidgetDisabled(byte widget_index) const;
 
	void SetWidgetHiddenState(byte widget_index, bool hidden_stat);
 
	void HideWidget(byte widget_index);
 
	void ShowWidget(byte widget_index);
 
	bool IsWidgetHidden(byte widget_index) const;
 
	void SetWidgetLoweredState(byte widget_index, bool lowered_stat);
 
@@ -528,30 +530,30 @@ Wcls *AllocateWindowDescFront(const Wind
 
	return new Wcls(desc, window_number);
 
}
 

	
 
void RelocateAllWindows(int neww, int newh);
 

	
 
/* misc_gui.cpp */
 
void GuiShowTooltips(StringID str, uint paramcount = 0, const uint64 params[] = NULL, bool use_left_mouse_button = false);
 

	
 
/* widget.cpp */
 
int GetWidgetFromPos(const Window *w, int x, int y);
 

	
 
/* window.cpp */
 
extern Window *_z_windows[];
 
extern Window **_last_z_window;
 
extern Window *_z_front_window;
 
extern Window *_z_back_window;
 

	
 
/** Iterate over all windows */
 
#define FOR_ALL_WINDOWS_FROM_BACK(w) for (Window **wz = _z_windows; wz != _last_z_window && (w = *wz) != NULL; wz++)
 
#define FOR_ALL_WINDOWS_FROM_FRONT(w) for (Window **wz = _last_z_window; wz != _z_windows && (w = *--wz) != NULL;)
 
#define FOR_ALL_WINDOWS_FROM_BACK(w)  for (w = _z_back_window;  w != NULL; w = w->z_front)
 
#define FOR_ALL_WINDOWS_FROM_FRONT(w) for (w = _z_front_window; w != NULL; w = w->z_back)
 

	
 
/**
 
 * Disable scrolling of the main viewport when an input-window is active.
 
 * This contains the count of windows with a textbox in them.
 
 */
 
extern byte _no_scroll;
 

	
 
extern Point _cursorpos_drag_start;
 

	
 
extern int _scrollbar_start_pos;
 
extern int _scrollbar_size;
 
extern byte _scroller_click_timeout;
 
@@ -559,25 +561,24 @@ extern byte _scroller_click_timeout;
 
extern bool _scrolling_scrollbar;
 
extern bool _scrolling_viewport;
 

	
 
extern byte _special_mouse_mode;
 
enum SpecialMouseMode {
 
	WSM_NONE     = 0,
 
	WSM_DRAGDROP = 1,
 
	WSM_SIZING   = 2,
 
	WSM_PRESIZE  = 3,
 
};
 

	
 
Window *GetCallbackWnd();
 
Window **FindWindowZPosition(const Window *w);
 

	
 
void ScrollbarClickHandler(Window *w, const Widget *wi, int x, int y);
 

	
 
void ResizeButtons(Window *w, byte left, byte right);
 

	
 
void ResizeWindowForWidget(Window *w, uint widget, int delta_x, int delta_y);
 

	
 
void SetVScrollCount(Window *w, int num);
 
void SetVScroll2Count(Window *w, int num);
 
void SetHScrollCount(Window *w, int num);
 

	
 

	
0 comments (0 inline, 0 general)