Fix display of Spin Options with negative range
[xboard.git] / winboard / wlayout.c
1 /*\r
2  * Layout management\r
3  *\r
4  * Author: Alessandro Scotti (Dec 2005)\r
5  *\r
6  * Copyright 2005 Alessandro Scotti\r
7  *\r
8  * Enhancements Copyright 2009, 2012, 2013, 2014 Free Software Foundation, Inc.\r
9  *\r
10  * ------------------------------------------------------------------------\r
11  *\r
12  * GNU XBoard is free software: you can redistribute it and/or modify\r
13  * it under the terms of the GNU General Public License as published by\r
14  * the Free Software Foundation, either version 3 of the License, or (at\r
15  * your option) any later version.\r
16  *\r
17  * GNU XBoard is distributed in the hope that it will be useful, but\r
18  * WITHOUT ANY WARRANTY; without even the implied warranty of\r
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
20  * General Public License for more details.\r
21  *\r
22  * You should have received a copy of the GNU General Public License\r
23  * along with this program. If not, see http://www.gnu.org/licenses/.  *\r
24  *\r
25  *------------------------------------------------------------------------\r
26  ** See the file ChangeLog for a revision history.  */\r
27 \r
28 #include "config.h"\r
29 \r
30 #include <windows.h> /* required for all Windows applications */\r
31 #include <stdio.h>\r
32 #include <stdlib.h>\r
33 #include <malloc.h>\r
34 #include <commdlg.h>\r
35 #include <dlgs.h>\r
36 \r
37 #include "common.h"\r
38 #include "frontend.h"\r
39 #include "winboard.h"\r
40 \r
41 VOID RestoreWindowPlacement( HWND hWnd, WindowPlacement * wp )\r
42 {\r
43     if( wp->x != CW_USEDEFAULT || \r
44         wp->y != CW_USEDEFAULT ||\r
45         wp->width != CW_USEDEFAULT || \r
46         wp->height != CW_USEDEFAULT )\r
47     {\r
48         WINDOWPLACEMENT stWP;\r
49 \r
50         ZeroMemory( &stWP, sizeof(stWP) );\r
51 \r
52         EnsureOnScreen( &wp->x, &wp->y, 0, 0);\r
53 \r
54         stWP.length = sizeof(stWP);\r
55         stWP.flags = 0;\r
56         stWP.showCmd = SW_SHOW;\r
57         stWP.ptMaxPosition.x = 0;\r
58         stWP.ptMaxPosition.y = 0;\r
59         stWP.rcNormalPosition.left = wp->x;\r
60         stWP.rcNormalPosition.right = wp->x + wp->width;\r
61         stWP.rcNormalPosition.top = wp->y;\r
62         stWP.rcNormalPosition.bottom = wp->y + wp->height;\r
63 \r
64         SetWindowPlacement(hWnd, &stWP);\r
65     }\r
66 }\r
67 \r
68 VOID InitWindowPlacement( WindowPlacement * wp )\r
69 {\r
70     wp->visible = TRUE;\r
71     wp->x = CW_USEDEFAULT;\r
72     wp->y = CW_USEDEFAULT;\r
73     wp->width = CW_USEDEFAULT;\r
74     wp->height = CW_USEDEFAULT;\r
75 }\r
76 \r
77 static BOOL IsAttachDistance( int a, int b )\r
78 {\r
79     BOOL result = FALSE;\r
80 \r
81     if( a == b ) {\r
82         result = TRUE;\r
83     }\r
84 \r
85     return result;\r
86 }\r
87 \r
88 static BOOL IsDefaultPlacement( WindowPlacement * wp )\r
89 {\r
90     BOOL result = FALSE;\r
91 \r
92     if( wp->x == CW_USEDEFAULT || wp->y == CW_USEDEFAULT || wp->width == CW_USEDEFAULT || wp->height == CW_USEDEFAULT ) {\r
93         result = TRUE;\r
94     }\r
95 \r
96     return result;\r
97 }\r
98 \r
99 BOOL GetActualPlacement( HWND hWnd, WindowPlacement * wp )\r
100 {\r
101     BOOL result = FALSE;\r
102 \r
103     if( hWnd != NULL ) {\r
104         WINDOWPLACEMENT stWP;\r
105 \r
106         ZeroMemory( &stWP, sizeof(stWP) );\r
107 \r
108         stWP.length = sizeof(stWP);\r
109 \r
110         GetWindowPlacement( hWnd, &stWP );\r
111 \r
112         wp->x = stWP.rcNormalPosition.left;\r
113         wp->y = stWP.rcNormalPosition.top;\r
114         wp->width = stWP.rcNormalPosition.right - stWP.rcNormalPosition.left;\r
115         wp->height = stWP.rcNormalPosition.bottom - stWP.rcNormalPosition.top;\r
116 \r
117         result = TRUE;\r
118     }\r
119 \r
120     return result;\r
121 }\r
122 \r
123 static BOOL IsAttachedByWindowPlacement( LPRECT lprcMain, WindowPlacement * wp )\r
124 {\r
125     BOOL result = FALSE;\r
126 \r
127     if( ! IsDefaultPlacement(wp) ) {\r
128         if( IsAttachDistance( lprcMain->right, wp->x ) ||\r
129             IsAttachDistance( lprcMain->bottom, wp->y ) ||\r
130             IsAttachDistance( lprcMain->left, (wp->x + wp->width) ) ||\r
131             IsAttachDistance( lprcMain->top, (wp->y + wp->height) ) )\r
132         {\r
133             result = TRUE;\r
134         }\r
135     }\r
136 \r
137     return result;\r
138 }\r
139 \r
140 VOID ReattachAfterMove( LPRECT lprcOldPos, int new_x, int new_y, HWND hWndChild, WindowPlacement * pwpChild )\r
141 {\r
142     if( ! IsDefaultPlacement( pwpChild ) ) {\r
143         GetActualPlacement( hWndChild, pwpChild );\r
144 \r
145         if( IsAttachedByWindowPlacement( lprcOldPos, pwpChild ) ) {\r
146             /* Get position delta */\r
147             int delta_x = pwpChild->x - lprcOldPos->left;\r
148             int delta_y = pwpChild->y - lprcOldPos->top;\r
149 \r
150             /* Adjust placement */\r
151             pwpChild->x = new_x + delta_x;\r
152             pwpChild->y = new_y + delta_y;\r
153 \r
154             /* Move window */\r
155             if( hWndChild != NULL ) {\r
156                 SetWindowPos( hWndChild, HWND_TOP,\r
157                     pwpChild->x, pwpChild->y,\r
158                     0, 0,\r
159                     SWP_NOZORDER | SWP_NOSIZE );\r
160             }\r
161         }\r
162     }\r
163 }\r
164 \r
165 extern FILE *debugFP;\r
166 VOID ReattachAfterSize( LPRECT lprcOldPos, int new_w, int new_h, HWND hWndChild, WindowPlacement * pwpChild )\r
167 {\r
168     if( ! IsDefaultPlacement( pwpChild ) ) {\r
169         GetActualPlacement( hWndChild, pwpChild );\r
170 \r
171         if( IsAttachedByWindowPlacement( lprcOldPos, pwpChild ) ) {\r
172             /* Get delta of lower right corner */\r
173             int delta_x = new_w - (lprcOldPos->right  - lprcOldPos->left);\r
174             int delta_y = new_h - (lprcOldPos->bottom - lprcOldPos->top);\r
175 \r
176             /* Adjust size & placement */\r
177             if(pwpChild->x + pwpChild->width  >= lprcOldPos->right &&\r
178               (pwpChild->x + pwpChild->width  < screenGeometry.right - 5 || delta_x > 0) ) // keep right edge glued to display edge if touching\r
179                 pwpChild->width += delta_x;\r
180             if(pwpChild->x + pwpChild->width  >= screenGeometry.right  ) // don't move right edge off screen\r
181                 pwpChild->width = screenGeometry.right - pwpChild->x;\r
182             if(pwpChild->y + pwpChild->height >= lprcOldPos->bottom &&\r
183               (pwpChild->y + pwpChild->height < screenGeometry.bottom - 35 || delta_y > 0) ) // keep bottom edge glued to display edge if touching\r
184                 pwpChild->height += delta_y;\r
185             if(pwpChild->y + pwpChild->height >= screenGeometry.bottom - 30 ) // don't move bottom edge off screen\r
186                 pwpChild->height = screenGeometry.bottom - 30 - pwpChild->y;\r
187             if(pwpChild->x >= lprcOldPos->right)  pwpChild->width  -= delta_x, pwpChild->x += delta_x;\r
188             if(pwpChild->y >= lprcOldPos->bottom) pwpChild->height -= delta_y, pwpChild->y += delta_y;\r
189             if(pwpChild->width  < 30) pwpChild->width = 30;  // force minimum width\r
190             if(pwpChild->height < 50) pwpChild->height = 50; // force minimum height\r
191             /* Move window */\r
192             if( hWndChild != NULL ) {\r
193                 SetWindowPos( hWndChild, HWND_TOP,\r
194                     pwpChild->x, pwpChild->y,\r
195                     pwpChild->width, pwpChild->height,\r
196                     SWP_NOZORDER );\r
197             }\r
198         }\r
199     }\r
200 }\r