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