siemens-rtl/try_place.c
2023-07-11 14:40:13 +02:00

462 lines
13 KiB
C

#ifndef lint
static char sccs_id[] = "@(#)try_place.c 5.3 9/1/88";
#endif
/*
* Copyright 1988 by Siemens Research and Technology Laboratories, Princeton, NJ
*
* All Rights Reserved
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose and without fee is hereby granted,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation, and that the name of Siemens Research and Technology
* Laboratories not be used in advertising or publicity pertaining to
* distribution of the software without specific, written prior permission.
*
*
* SIEMENS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
* SIEMENS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
* ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
* WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*/
#include "copyright.h"
#include "basetype.h"
#include "twinD.h"
#include "twin.h"
#include "gravity.h"
#include "check.h"
/* Checks to see if the given rectangle meets the global and window-specific
* (if appropriate) minimum and maximum requirements. Adjusts the rectangle
* with respect to gravity (if appropriate). Checks adjusted rectangle to make
* sure min-max criteria are still meet. Return TRUE if the rectangle has been
* changed, otherwise return FALSE.
* NOTE: This routine assumes the following partial ordering on the elements
* abs_min (absolute minimums), win_min, win_max, and abs_max (absolute
* maximums):
* abs_min <= win_max, abs_min <= abs_max,
* win_min <= win_max, win_min <= abs_max
* However if this ordering does not hold (e.g. win_max < win_min), the maximum
* constraints are satisfied at the expense of violating the minimum
* constraints.
*/
bool
Trial_Place(rectp, side, win_min, win_max)
TWRectangle *rectp;
Side side;
Size win_min,
win_max;
{
Size size,
original_size,
abs_min, abs_max;
TWPoint location;
TWRectangle rect,
original_rect;
Basetype left_diff, right_diff,
top_diff, bottom_diff;
bool changed = FALSE;
rect = *rectp;
original_rect = *rectp;
COMPUTE_SIZE(rect, size);
COMPUTE_CENTER(rect, location);
/* check rectangle against absolute minimums */
abs_min = Tilwin_Get_Absolute_Minimums();
if (Get_Width(size) < Get_Width(abs_min)){
switch (side) {
case Left:
case Top_Left:
case Bottom_Left:
Get_LeftX(rect) = Get_RightX(rect) - (Get_Width(abs_min) - 1);
COMPUTE_SIZE(rect, size);
break;
case Right:
case Top_Right:
case Bottom_Right:
Get_RightX(rect) = Get_LeftX(rect) + (Get_Width(abs_min) - 1);
COMPUTE_SIZE(rect, size);
break;
case NoSide:
Get_Width(size) = Get_Width(abs_min);
MAKE_RECTANGLE(location, size, rect);
break;
}
changed = TRUE;
}
if (Get_Height(size) < Get_Height(abs_min)){
switch (side){
case Top:
case Top_Left:
case Top_Right:
Get_TopY(rect) = Get_BottomY(rect) - (Get_Height(abs_min) - 1);
COMPUTE_SIZE(rect, size);
break;
case Bottom:
case Bottom_Left:
case Bottom_Right:
Get_BottomY(rect) = Get_TopY(rect) + (Get_Height(abs_min) - 1);
COMPUTE_SIZE(rect, size);
break;
case NoSide:
Get_Height(size) = Get_Height(abs_min);
MAKE_RECTANGLE(location, size, rect);
break;
}
changed = TRUE;
}
/* check rectangle against window minimums (if appropriate) */
if (Tilwin_Get_Global_Option(ENFORCE_MINIMUMS) == TRUE){
if (Get_Width(size) < Get_Width(win_min)){
switch (side) {
case Left:
case Top_Left:
case Bottom_Left:
Get_LeftX(rect) = Get_RightX(rect) - (Get_Width(win_min) - 1);
COMPUTE_SIZE(rect, size);
break;
case Right:
case Top_Right:
case Bottom_Right:
Get_RightX(rect) = Get_LeftX(rect) + (Get_Width(win_min) - 1);
COMPUTE_SIZE(rect, size);
break;
case NoSide:
Get_Width(size) = Get_Width(win_min);
MAKE_RECTANGLE(location, size, rect);
break;
}
changed = TRUE;
}
if (Get_Height(size) < Get_Height(win_min)){
switch (side){
case Top:
case Top_Left:
case Top_Right:
Get_TopY(rect) = Get_BottomY(rect) - (Get_Height(win_min) - 1);
COMPUTE_SIZE(rect, size);
break;
case Bottom:
case Bottom_Left:
case Bottom_Right:
Get_BottomY(rect) = Get_TopY(rect) + (Get_Height(win_min) - 1);
COMPUTE_SIZE(rect, size);
break;
case NoSide:
Get_Height(size) = Get_Height(win_min);
MAKE_RECTANGLE(location, size, rect);
break;
}
changed = TRUE;
}
}
/* check rectangle against the desktop size */
abs_max = Tilwin_Get_Desktop_Size();
if (Get_Width(size) > Get_Width(abs_max)){
switch (side) {
case Left:
case Top_Left:
case Bottom_Left:
Get_LeftX(rect) = Get_RightX(rect) - (Get_Width(abs_max) - 1);
COMPUTE_SIZE(rect, size);
break;
case Right:
case Top_Right:
case Bottom_Right:
Get_RightX(rect) = Get_LeftX(rect) + (Get_Width(abs_max) - 1);
COMPUTE_SIZE(rect, size);
break;
case NoSide:
Get_Width(size) = Get_Width(abs_max);
MAKE_RECTANGLE(location, size, rect);
break;
}
changed = TRUE;
}
if (Get_Height(size) > Get_Height(abs_max)){
switch (side){
case Top:
case Top_Left:
case Top_Right:
Get_TopY(rect) = Get_BottomY(rect) - (Get_Height(abs_max) - 1);
COMPUTE_SIZE(rect, size);
break;
case Bottom:
case Bottom_Left:
case Bottom_Right:
Get_BottomY(rect) = Get_TopY(rect) + (Get_Height(abs_max) - 1);
COMPUTE_SIZE(rect, size);
break;
case NoSide:
Get_Height(size) = Get_Height(abs_max);
MAKE_RECTANGLE(location, size, rect);
break;
}
changed = TRUE;
}
/* check the rectangle against window max (if appropriate) */
if (Tilwin_Get_Global_Option(ENFORCE_MAXIMUMS) == TRUE){
if (Get_Width(size) > Get_Width(win_max)){
switch (side) {
case Left:
case Top_Left:
case Bottom_Left:
Get_LeftX(rect) = Get_RightX(rect) - (Get_Width(win_max) - 1);
COMPUTE_SIZE(rect, size);
break;
case Right:
case Top_Right:
case Bottom_Right:
Get_RightX(rect) = Get_LeftX(rect) + (Get_Width(win_max) - 1);
COMPUTE_SIZE(rect, size);
break;
case NoSide:
Get_Width(size) = Get_Width(win_max);
MAKE_RECTANGLE(location, size, rect);
break;
}
changed = TRUE;
}
if (Get_Height(size) > Get_Height(win_max)){
switch (side){
case Top:
case Top_Left:
case Top_Right:
Get_TopY(rect) = Get_BottomY(rect) - (Get_Height(win_max) - 1);
COMPUTE_SIZE(rect, size);
break;
case Bottom:
case Bottom_Left:
case Bottom_Right:
Get_BottomY(rect) = Get_TopY(rect) + (Get_Height(win_max) - 1);
COMPUTE_SIZE(rect, size);
break;
case NoSide:
Get_Height(size) = Get_Height(win_max);
MAKE_RECTANGLE(location, size, rect);
break;
}
changed = TRUE;
}
}
/* adjust the rectangle for gravity */
if (side == Left || side == Top_Left || side == Bottom_Left)
Get_LeftX(rect) = Gravity_Adjust_Edge(Get_LeftX(rect), Left);
else if (side == Right || side == Top_Right || side == Bottom_Right)
Get_RightX(rect) = Gravity_Adjust_Edge(Get_RightX(rect), Right);
if (side == Top || side == Top_Left || side == Top_Right)
Get_TopY(rect) = Gravity_Adjust_Edge(Get_TopY(rect), Top);
else if (side == Bottom || side == Bottom_Left || side == Bottom_Right)
Get_BottomY(rect) = Gravity_Adjust_Edge(Get_BottomY(rect), Bottom);
if (side == NoSide) {
/* original_size is the size the obeys mins and maxes */
COMPUTE_SIZE(rect, original_size);
Gravity_Adjust(&rect);
/* if the size has changed, restore the original size by
finding the edge which is furthest from the nearest gravity
point and changing that edge.
*/
COMPUTE_SIZE(rect, size);
if (Get_Width(size) != Get_Width(original_size)) {
left_diff = Gravity_Difference(Get_LeftX(original_rect), Left);
right_diff = Gravity_Difference(Get_RightX(original_rect), Right);
if (left_diff <= right_diff)
Get_RightX(rect) = Get_LeftX(rect) + (Get_Width(original_size) - 1);
else
Get_LeftX(rect) = Get_RightX(rect) - (Get_Width(original_size) - 1);
}
if (Get_Height(size) != Get_Height(original_size)) {
top_diff = Gravity_Difference(Get_TopY(original_rect), Top);
bottom_diff = Gravity_Difference(Get_BottomY(original_rect), Bottom);
if (top_diff <= bottom_diff)
Get_BottomY(rect) = Get_TopY(rect) + (Get_Height(original_size) - 1);
else
Get_TopY(rect) = Get_BottomY(rect) - (Get_Height(original_size) - 1);
}
}
/* changes due to gravity may have caused mins or maxs to be violated.
* Check appropriate mins and maxs again. This is the same code as above
* except when side == NoSide.
*/
COMPUTE_SIZE(rect, size);
abs_min = Tilwin_Get_Absolute_Minimums();
if (Get_Width(size) < Get_Width(abs_min)){
switch (side) {
case Left:
case Top_Left:
case Bottom_Left:
Get_LeftX(rect) = Get_RightX(rect) - (Get_Width(abs_min) - 1);
break;
case Right:
case Top_Right:
case Bottom_Right:
Get_RightX(rect) = Get_LeftX(rect) + (Get_Width(abs_min) - 1);
break;
case NoSide:
break;
}
COMPUTE_SIZE(rect, size);
changed = TRUE;
}
if (Get_Height(size) < Get_Height(abs_min)){
switch (side){
case Top:
case Top_Left:
case Top_Right:
Get_TopY(rect) = Get_BottomY(rect) - (Get_Height(abs_min) - 1);
break;
case Bottom:
case Bottom_Left:
case Bottom_Right:
Get_BottomY(rect) = Get_TopY(rect) + (Get_Height(abs_min) - 1);
break;
case NoSide:
break;
}
COMPUTE_SIZE(rect, size);
changed = TRUE;
}
if (Tilwin_Get_Global_Option(ENFORCE_MINIMUMS) == TRUE){
if (Get_Width(size) < Get_Width(win_min)){
switch (side) {
case Left:
case Top_Left:
case Bottom_Left:
Get_LeftX(rect) = Get_RightX(rect) - (Get_Width(win_min) - 1);
break;
case Right:
case Top_Right:
case Bottom_Right:
Get_RightX(rect) = Get_LeftX(rect) + (Get_Width(win_min) - 1);
break;
case NoSide:
break;
}
COMPUTE_SIZE(rect, size);
changed = TRUE;
}
if (Get_Height(size) < Get_Height(win_min)){
switch (side){
case Top:
case Top_Left:
case Top_Right:
Get_TopY(rect) = Get_BottomY(rect) - (Get_Height(win_min) - 1);
break;
case Bottom:
case Bottom_Left:
case Bottom_Right:
Get_BottomY(rect) = Get_TopY(rect) + (Get_Height(win_min) - 1);
break;
case NoSide:
break;
}
COMPUTE_SIZE(rect, size);
changed = TRUE;
}
}
abs_max = Tilwin_Get_Desktop_Size();
if (Get_Width(size) > Get_Width(abs_max)){
switch (side) {
case Left:
case Top_Left:
case Bottom_Left:
Get_LeftX(rect) = Get_RightX(rect) - (Get_Width(abs_max) - 1);
break;
case Right:
case Top_Right:
case Bottom_Right:
Get_RightX(rect) = Get_LeftX(rect) + (Get_Width(abs_max) - 1);
break;
case NoSide:
break;
}
COMPUTE_SIZE(rect, size);
changed = TRUE;
}
if (Get_Height(size) > Get_Height(abs_max)){
switch (side){
case Top:
case Top_Left:
case Top_Right:
Get_TopY(rect) = Get_BottomY(rect) - (Get_Height(abs_max) - 1);
break;
case Bottom:
case Bottom_Left:
case Bottom_Right:
Get_BottomY(rect) = Get_TopY(rect) + (Get_Height(abs_max) - 1);
break;
case NoSide:
break;
}
COMPUTE_SIZE(rect, size);
changed = TRUE;
}
if (Tilwin_Get_Global_Option(ENFORCE_MAXIMUMS) == TRUE){
if (Get_Width(size) > Get_Width(win_max)){
switch (side) {
case Left:
case Top_Left:
case Bottom_Left:
Get_LeftX(rect) = Get_RightX(rect) - (Get_Width(win_max) - 1);
break;
case Right:
case Top_Right:
case Bottom_Right:
Get_RightX(rect) = Get_LeftX(rect) + (Get_Width(win_max) - 1);
break;
case NoSide:
break;
}
changed = TRUE;
}
if (Get_Height(size) > Get_Height(win_max)){
switch (side){
case Top:
case Top_Left:
case Top_Right:
Get_TopY(rect) = Get_BottomY(rect) - (Get_Height(win_max) - 1);
break;
case Bottom:
case Bottom_Left:
case Bottom_Right:
Get_BottomY(rect) = Get_TopY(rect) + (Get_Height(win_max) - 1);
break;
case NoSide:
break;
}
changed = TRUE;
}
}
#ifdef WM_DEBUG
COMPUTE_SIZE(rect, size);
#endif
/* return the "new" rectangle */
*rectp = rect;
return(changed);
}