window.c
changeset 763 8ff348acf75e
parent 682 7f5de4abac85
child 842 ebfd36603ab9
--- a/window.c	Wed Dec 22 16:54:55 2004 +0000
+++ b/window.c	Wed Dec 22 17:37:21 2004 +0000
@@ -285,6 +285,34 @@
 	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 *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 @@
 	}
 }
 
+/* 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...");