summaryrefslogtreecommitdiff
path: root/window.c
diff options
context:
space:
mode:
authordarkvater <darkvater@openttd.org>2004-12-22 17:37:21 +0000
committerdarkvater <darkvater@openttd.org>2004-12-22 17:37:21 +0000
commited0a42f940db567088d39b583f0b66ed274ee20d (patch)
tree290fdb71f975b684f56bde327d7e01109b379932 /window.c
parentb7f71b026d0da7cadb4db0ab674e0e2908227bce (diff)
downloadopenttd-ed0a42f940db567088d39b583f0b66ed274ee20d.tar.xz
(svn r1225) -Feature: SHIFT+DEL now deletes all non-vital windows (only status bar and main bar remain)
-Fix: For everyone who tried to crash the game by opening a huge amount of windows and stickying all of them; bad luck. It's fixed now (thanks Tron for the helpful criticism). First all normal windows are a candidate for replacement, then if none are found, sticky windows. Then..well that should not happen :)
Diffstat (limited to 'window.c')
-rw-r--r--window.c63
1 files changed, 53 insertions, 10 deletions
diff --git a/window.c b/window.c
index 7e42c5803..8bcb690f5 100644
--- a/window.c
+++ b/window.c
@@ -285,6 +285,34 @@ Window *BringWindowToFront(Window *w)
return v;
}
+/* We have run out of windows, so find a suitable candidate for replacement.
+ * Keep all important windows intact */
+static Window *FindDeletableWindow(void)
+{
+ Window *w;
+ for (w = _windows; w < endof(_windows); w++) {
+ if (w->window_class != WC_MAIN_WINDOW && w->window_class != WC_MAIN_TOOLBAR &&
+ w->window_class != WC_STATUS_BAR && w->window_class != WC_NEWS_WINDOW &&
+ !(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 */
+static Window *ForceFindDeletableWindow(void)
+{
+ Window *w;
+ for (w = _windows;; w++) {
+ assert(w < _last_window);
+
+ if (w->window_class != WC_MAIN_WINDOW && w->window_class != WC_MAIN_TOOLBAR &&
+ w->window_class != WC_STATUS_BAR && w->window_class != WC_NEWS_WINDOW)
+ return w;
+ }
+}
+
Window *AllocateWindow(
int x,
int y,
@@ -296,21 +324,16 @@ Window *AllocateWindow(
{
Window *w;
-restart:;
w = _last_window;
if (w >= endof(_windows)) {
- for(w=_windows; ;w++) {
- assert(w < _last_window);
+ w = FindDeletableWindow();
- if (w->window_class != WC_MAIN_WINDOW && w->window_class != WC_MAIN_TOOLBAR &&
- w->window_class != WC_STATUS_BAR && w->window_class != WC_NEWS_WINDOW &&
- !(w->flags4 & WF_STICKY) ) {
+ if (w == NULL) // no window found, force it!
+ w = ForceFindDeletableWindow();
- DeleteWindow(w);
- goto restart;
- }
- }
+ DeleteWindow(w);
+ w = _last_window;
}
if (w != _windows && cls != WC_NEWS_WINDOW) {
@@ -1343,6 +1366,26 @@ void DeleteNonVitalWindows()
}
}
+/* It is possible that a stickied window gets to a position where the
+ * 'close' button is outside the gaming area. You cannot close it then; except
+ * with this function. It closes all windows calling the standard function,
+ * then, does a little hacked loop of closing all stickied windows. Note
+ * that standard windows (status bar, etc.) are not stickied, so these aren't affected */
+void DeleteAllNonVitalWindows(void)
+{
+ Window *w;
+ // Delete every window except for stickied ones
+ DeleteNonVitalWindows();
+ // Delete all sticked windows
+ for (w = _windows; w != _last_window;) {
+ if (w->flags4 & WF_STICKY) {
+ DeleteWindow(w);
+ w = _windows;
+ } else
+ w++;
+ }
+}
+
int PositionMainToolbar(Window *w)
{
DEBUG(misc, 1) ("Repositioning Main Toolbar...");