diff options
author | darkvater <darkvater@openttd.org> | 2004-12-22 17:37:21 +0000 |
---|---|---|
committer | darkvater <darkvater@openttd.org> | 2004-12-22 17:37:21 +0000 |
commit | ed0a42f940db567088d39b583f0b66ed274ee20d (patch) | |
tree | 290fdb71f975b684f56bde327d7e01109b379932 | |
parent | b7f71b026d0da7cadb4db0ab674e0e2908227bce (diff) | |
download | openttd-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 :)
-rw-r--r-- | main_gui.c | 23 | ||||
-rw-r--r-- | window.c | 63 | ||||
-rw-r--r-- | window.h | 1 |
3 files changed, 56 insertions, 31 deletions
diff --git a/main_gui.c b/main_gui.c index 93577dbc5..b6442a181 100644 --- a/main_gui.c +++ b/main_gui.c @@ -152,26 +152,6 @@ static void ToolbarFastForwardClick(Window *w) SndPlayFx(SND_15_BEEP); } -/* 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 */ -static void CloseEveryWindow(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++; - } -} - typedef void MenuClickedProc(int index); @@ -183,7 +163,7 @@ static void MenuClickSettings(int index) case 2: ShowPatchesSelection(); return; case 3: ShowNewgrf(); return; - case 5: CloseEveryWindow(); return; + case 5: DeleteAllNonVitalWindows(); return; case 6: _display_opt ^= DO_SHOW_TOWN_NAMES; MarkWholeScreenDirty(); return; case 7: _display_opt ^= DO_SHOW_STATION_NAMES; MarkWholeScreenDirty(); return; case 8: _display_opt ^= DO_SHOW_SIGNS; MarkWholeScreenDirty(); return; @@ -2330,6 +2310,7 @@ static void MainWindowWndProc(Window *w, WindowEvent *e) { case WKC_ESC: ResetObjectToPlace(); break; case WKC_DELETE: DeleteNonVitalWindows(); break; + case WKC_DELETE | WKC_SHIFT: DeleteAllNonVitalWindows(); break; case 'Q' | WKC_CTRL: AskExitGame(); break; case 'Q' | WKC_META: AskExitGame(); break; // this enables command + Q on mac case 'R' | WKC_CTRL: MarkWholeScreenDirty(); break; @@ -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..."); @@ -459,6 +459,7 @@ void HandleButtonClick(Window *w, byte widget); Window *GetCallbackWnd(); void DeleteNonVitalWindows(); +void DeleteAllNonVitalWindows(void); /* window.c */ VARDEF Window _windows[25]; |