window.c
branchcustombridgeheads
changeset 5623 ef2a8a524a95
parent 5568 75f13d7bfaed
equal deleted inserted replaced
5622:2f0cb276d32a 5623:ef2a8a524a95
   285 {
   285 {
   286 	if (w == NULL) return;
   286 	if (w == NULL) return;
   287 	SetDirtyBlocks(w->left, w->top, w->left + w->width, w->top + w->height);
   287 	SetDirtyBlocks(w->left, w->top, w->left + w->width, w->top + w->height);
   288 }
   288 }
   289 
   289 
       
   290 /** Find the Window whose parent pointer points to this window
       
   291  * @parent w Window to find child of
       
   292  * @return return a Window pointer that is the child of w, or NULL otherwise */
       
   293 static Window *FindChildWindow(const Window *w)
       
   294 {
       
   295 	Window* const *wz;
       
   296 
       
   297 	FOR_ALL_WINDOWS(wz) {
       
   298 		Window *v = *wz;
       
   299 		if (v->parent == w) return v;
       
   300 	}
       
   301 
       
   302 	return NULL;
       
   303 }
       
   304 
   290 /** Find the z-value of a window. A window must already be open
   305 /** Find the z-value of a window. A window must already be open
   291  * or the behaviour is undefined but function should never fail */
   306  * or the behaviour is undefined but function should never fail */
   292 Window **FindWindowZPosition(const Window *w)
   307 Window **FindWindowZPosition(const Window *w)
   293 {
   308 {
   294 	Window **wz;
   309 	Window **wz;
   295 
   310 
   296 	for (wz = _z_windows;; wz++) {
   311 	for (wz = _z_windows; wz != _last_z_window; wz++) {
   297 		assert(wz < _last_z_window);
       
   298 		if (*wz == w) return wz;
   312 		if (*wz == w) return wz;
   299 	}
   313 	}
       
   314 
       
   315 	DEBUG(misc, 3, "Window (class %d, number %d) is not open, probably removed by recursive calls",
       
   316 		w->window_class, w->window_number);
       
   317 	return NULL;
   300 }
   318 }
   301 
   319 
   302 void DeleteWindow(Window *w)
   320 void DeleteWindow(Window *w)
   303 {
   321 {
       
   322 	Window *v;
   304 	Window **wz;
   323 	Window **wz;
   305 	if (w == NULL) return;
   324 	if (w == NULL) return;
       
   325 
       
   326 	/* Delete any children a window might have in a head-recursive manner */
       
   327 	v = FindChildWindow(w);
       
   328 	if (v != NULL) DeleteWindow(v);
   306 
   329 
   307 	if (_thd.place_mode != VHM_NONE &&
   330 	if (_thd.place_mode != VHM_NONE &&
   308 			_thd.window_class == w->window_class &&
   331 			_thd.window_class == w->window_class &&
   309 			_thd.window_number == w->window_number) {
   332 			_thd.window_number == w->window_number) {
   310 		ResetObjectToPlace();
   333 		ResetObjectToPlace();
   315 
   338 
   316 	SetWindowDirty(w);
   339 	SetWindowDirty(w);
   317 	free(w->widget);
   340 	free(w->widget);
   318 	w->widget = NULL;
   341 	w->widget = NULL;
   319 	w->widget_count = 0;
   342 	w->widget_count = 0;
       
   343 	w->parent = NULL;
   320 
   344 
   321 	/* Find the window in the z-array, and effectively remove it
   345 	/* Find the window in the z-array, and effectively remove it
   322 	 * by moving all windows after it one to the left */
   346 	 * by moving all windows after it one to the left */
   323 	wz = FindWindowZPosition(w);
   347 	wz = FindWindowZPosition(w);
       
   348 	if (wz == NULL) return;
   324 	memmove(wz, wz + 1, (byte*)_last_z_window - (byte*)wz);
   349 	memmove(wz, wz + 1, (byte*)_last_z_window - (byte*)wz);
   325 	_last_z_window--;
   350 	_last_z_window--;
   326 }
   351 }
   327 
   352 
   328 Window *FindWindowById(WindowClass cls, WindowNumber number)
   353 Window *FindWindowById(WindowClass cls, WindowNumber number)
   873 	_no_scroll = 0;
   898 	_no_scroll = 0;
   874 }
   899 }
   875 
   900 
   876 void UnInitWindowSystem(void)
   901 void UnInitWindowSystem(void)
   877 {
   902 {
   878 	Window* const *wz;
   903 	Window **wz;
   879 	// delete all malloced widgets
   904 	/* Delete all malloced widgets, and reset z-array */
   880 	FOR_ALL_WINDOWS(wz) {
   905 	FOR_ALL_WINDOWS(wz) {
   881 		free((*wz)->widget);
   906 		free((*wz)->widget);
   882 		(*wz)->widget = NULL;
   907 		(*wz)->widget = NULL;
   883 		(*wz)->widget_count = 0;
   908 		(*wz)->widget_count = 0;
   884 	}
   909 		*wz = NULL;
       
   910 	}
       
   911 	_last_z_window = _z_windows;
   885 }
   912 }
   886 
   913 
   887 void ResetWindowSystem(void)
   914 void ResetWindowSystem(void)
   888 {
   915 {
   889 	UnInitWindowSystem();
   916 	UnInitWindowSystem();
  1380 	_cursor.delta.x = 0;
  1407 	_cursor.delta.x = 0;
  1381 	_cursor.delta.y = 0;
  1408 	_cursor.delta.y = 0;
  1382 	return false;
  1409 	return false;
  1383 }
  1410 }
  1384 
  1411 
  1385 static void MaybeBringWindowToFront(const Window *w)
  1412 /** Check if a window can be made top-most window, and if so do
  1386 {
  1413  * it. If a window does not obscure any other windows, it will not
       
  1414  * be brought to the foreground. Also if the only obscuring windows
       
  1415  * are so-called system-windows, the window will not be moved.
       
  1416  * The function will return false when a child window of this window is a
       
  1417  * modal-popup; function returns a false and child window gets a white border
       
  1418  * @param w Window to bring on-top
       
  1419  * @return false if the window has an active modal child, true otherwise */
       
  1420 static bool MaybeBringWindowToFront(const Window *w)
       
  1421 {
       
  1422 	bool bring_to_front = false;
  1387 	Window* const *wz;
  1423 	Window* const *wz;
  1388 	Window* const *uz;
  1424 	Window* const *uz;
  1389 
  1425 
  1390 	if (w->window_class == WC_MAIN_WINDOW ||
  1426 	if (w->window_class == WC_MAIN_WINDOW ||
  1391 			IsVitalWindow(w) ||
  1427 			IsVitalWindow(w) ||
  1392 			w->window_class == WC_TOOLTIPS ||
  1428 			w->window_class == WC_TOOLTIPS ||
  1393 			w->window_class == WC_DROPDOWN_MENU) {
  1429 			w->window_class == WC_DROPDOWN_MENU) {
  1394 		return;
  1430 		return true;
  1395 	}
  1431 	}
  1396 
  1432 
  1397 	wz = FindWindowZPosition(w);
  1433 	wz = FindWindowZPosition(w);
  1398 	for (uz = wz; ++uz != _last_z_window;) {
  1434 	for (uz = wz; ++uz != _last_z_window;) {
  1399 		const Window *u = *uz;
  1435 		Window *u = *uz;
       
  1436 
       
  1437 		/* A modal child will prevent the activation of the parent window */
       
  1438 		if (u->parent == w && (u->desc_flags & WDF_MODAL)) {
       
  1439 			u->flags4 |= WF_WHITE_BORDER_MASK;
       
  1440 			SetWindowDirty(u);
       
  1441 			return false;
       
  1442 		}
  1400 
  1443 
  1401 		if (u->window_class == WC_MAIN_WINDOW ||
  1444 		if (u->window_class == WC_MAIN_WINDOW ||
  1402 				IsVitalWindow(u) ||
  1445 				IsVitalWindow(u) ||
  1403 				u->window_class == WC_TOOLTIPS ||
  1446 				u->window_class == WC_TOOLTIPS ||
  1404 				u->window_class == WC_DROPDOWN_MENU) {
  1447 				u->window_class == WC_DROPDOWN_MENU) {
  1405 			continue;
  1448 			continue;
  1406 		}
  1449 		}
  1407 
  1450 
       
  1451 		/* Window sizes don't interfere, leave z-order alone */
  1408 		if (w->left + w->width <= u->left ||
  1452 		if (w->left + w->width <= u->left ||
  1409 				u->left + u->width <= w->left ||
  1453 				u->left + u->width <= w->left ||
  1410 				w->top  + w->height <= u->top ||
  1454 				w->top  + w->height <= u->top ||
  1411 				u->top + u->height <= w->top) {
  1455 				u->top + u->height <= w->top) {
  1412 			continue;
  1456 			continue;
  1413 		}
  1457 		}
  1414 
  1458 
  1415 		BringWindowToFront(w);
  1459 		bring_to_front = true;
  1416 		return;
  1460 	}
  1417 	}
  1461 
       
  1462 	if (bring_to_front) BringWindowToFront(w);
       
  1463 	return true;
  1418 }
  1464 }
  1419 
  1465 
  1420 /** Send a message from one window to another. The receiving window is found by
  1466 /** Send a message from one window to another. The receiving window is found by
  1421  * @param w @see Window pointer pointing to the other window
  1467  * @param w @see Window pointer pointing to the other window
  1422  * @param msg Specifies the message to be sent
  1468  * @param msg Specifies the message to be sent
  1591 
  1637 
  1592 	if (click == 0 && mousewheel == 0) return;
  1638 	if (click == 0 && mousewheel == 0) return;
  1593 
  1639 
  1594 	w = FindWindowFromPt(x, y);
  1640 	w = FindWindowFromPt(x, y);
  1595 	if (w == NULL) return;
  1641 	if (w == NULL) return;
  1596 	MaybeBringWindowToFront(w);
  1642 	if (!MaybeBringWindowToFront(w)) return;
  1597 	vp = IsPtInWindowViewport(w, x, y);
  1643 	vp = IsPtInWindowViewport(w, x, y);
  1598 
  1644 
  1599 	/* Don't allow any action in a viewport if either in menu of in generating world */
  1645 	/* Don't allow any action in a viewport if either in menu of in generating world */
  1600 	if (vp != NULL && (_game_mode == GM_MENU || IsGeneratingWorld())) return;
  1646 	if (vp != NULL && (_game_mode == GM_MENU || IsGeneratingWorld())) return;
  1601 
  1647