(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 :)
This commit is contained in:
		
							
								
								
									
										23
									
								
								main_gui.c
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								main_gui.c
									
									
									
									
									
								
							@@ -152,26 +152,6 @@ static void ToolbarFastForwardClick(Window *w)
 | 
				
			|||||||
	SndPlayFx(SND_15_BEEP);
 | 
						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);
 | 
					typedef void MenuClickedProc(int index);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -183,7 +163,7 @@ static void MenuClickSettings(int index)
 | 
				
			|||||||
	case 2: ShowPatchesSelection(); return;
 | 
						case 2: ShowPatchesSelection(); return;
 | 
				
			||||||
	case 3: ShowNewgrf(); return;
 | 
						case 3: ShowNewgrf(); return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	case 5: CloseEveryWindow(); return; 
 | 
						case 5: DeleteAllNonVitalWindows(); return; 
 | 
				
			||||||
	case 6: _display_opt ^= DO_SHOW_TOWN_NAMES; MarkWholeScreenDirty(); return;
 | 
						case 6: _display_opt ^= DO_SHOW_TOWN_NAMES; MarkWholeScreenDirty(); return;
 | 
				
			||||||
	case 7: _display_opt ^= DO_SHOW_STATION_NAMES; MarkWholeScreenDirty(); return;
 | 
						case 7: _display_opt ^= DO_SHOW_STATION_NAMES; MarkWholeScreenDirty(); return;
 | 
				
			||||||
	case 8: _display_opt ^= DO_SHOW_SIGNS; 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_ESC: ResetObjectToPlace(); break;
 | 
				
			||||||
		case WKC_DELETE: DeleteNonVitalWindows(); break;
 | 
							case WKC_DELETE: DeleteNonVitalWindows(); break;
 | 
				
			||||||
 | 
							case WKC_DELETE | WKC_SHIFT: DeleteAllNonVitalWindows(); break;
 | 
				
			||||||
		case 'Q' | WKC_CTRL: AskExitGame(); break;
 | 
							case 'Q' | WKC_CTRL: AskExitGame(); break;
 | 
				
			||||||
		case 'Q' | WKC_META: AskExitGame(); break; // this enables command + Q on mac
 | 
							case 'Q' | WKC_META: AskExitGame(); break; // this enables command + Q on mac
 | 
				
			||||||
		case 'R' | WKC_CTRL: MarkWholeScreenDirty(); break;
 | 
							case 'R' | WKC_CTRL: MarkWholeScreenDirty(); break;
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										63
									
								
								window.c
									
									
									
									
									
								
							
							
						
						
									
										63
									
								
								window.c
									
									
									
									
									
								
							@@ -285,6 +285,34 @@ Window *BringWindowToFront(Window *w)
 | 
				
			|||||||
	return v;
 | 
						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(
 | 
					Window *AllocateWindow(
 | 
				
			||||||
							int x,
 | 
												int x,
 | 
				
			||||||
							int y,
 | 
												int y,
 | 
				
			||||||
@@ -296,21 +324,16 @@ Window *AllocateWindow(
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	Window *w;
 | 
						Window *w;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
restart:;
 | 
					 | 
				
			||||||
	w = _last_window;
 | 
						w = _last_window;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (w >= endof(_windows)) {
 | 
						if (w >= endof(_windows)) {
 | 
				
			||||||
		for(w=_windows; ;w++) {
 | 
							w = FindDeletableWindow();
 | 
				
			||||||
			assert(w < _last_window);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (w->window_class != WC_MAIN_WINDOW && w->window_class != WC_MAIN_TOOLBAR &&
 | 
							if (w == NULL) // no window found, force it!
 | 
				
			||||||
			    w->window_class != WC_STATUS_BAR && w->window_class != WC_NEWS_WINDOW &&
 | 
								w = ForceFindDeletableWindow();
 | 
				
			||||||
					!(w->flags4 & WF_STICKY) ) {
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
					DeleteWindow(w);
 | 
							DeleteWindow(w);
 | 
				
			||||||
					goto restart;
 | 
							w = _last_window;
 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (w != _windows && cls != WC_NEWS_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)
 | 
					int PositionMainToolbar(Window *w)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	DEBUG(misc, 1) ("Repositioning Main Toolbar...");
 | 
						DEBUG(misc, 1) ("Repositioning Main Toolbar...");
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										1
									
								
								window.h
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								window.h
									
									
									
									
									
								
							@@ -459,6 +459,7 @@ void HandleButtonClick(Window *w, byte widget);
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
Window *GetCallbackWnd();
 | 
					Window *GetCallbackWnd();
 | 
				
			||||||
void DeleteNonVitalWindows();
 | 
					void DeleteNonVitalWindows();
 | 
				
			||||||
 | 
					void DeleteAllNonVitalWindows(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* window.c */
 | 
					/* window.c */
 | 
				
			||||||
VARDEF Window _windows[25];
 | 
					VARDEF Window _windows[25];
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user