1 /* Rectangular class for Midnight Commander widgets
2
3 Copyright (C) 2020-2025
4 The Free Software Foundation, Inc.
5
6 Written by:
7 Andrew Borodin <aborodin@vmail.ru>, 2020-2022
8
9 This file is part of the Midnight Commander.
10
11 The Midnight Commander is free software: you can redistribute it
12 and/or modify it under the terms of the GNU General Public License as
13 published by the Free Software Foundation, either version 3 of the License,
14 or (at your option) any later version.
15
16 The Midnight Commander is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program. If not, see <https://www.gnu.org/licenses/>.
23 */
24
25 /** \file widget-common.c
26 * \brief Source: shared stuff of widgets
27 */
28
29 #include <config.h>
30
31 #include <stdlib.h>
32
33 #include "lib/global.h"
34
35 #include "rect.h"
36
37 /*** global variables ****************************************************************************/
38
39 /*** file scope macro definitions ****************************************************************/
40
41 /*** file scope type declarations ****************************************************************/
42
43 /*** file scope variables ************************************************************************/
44
45 /*** file scope functions ************************************************************************/
46
47 /* --------------------------------------------------------------------------------------------- */
48 /*** public functions ****************************************************************************/
49 /* --------------------------------------------------------------------------------------------- */
50 /**
51 * Create new WRect object.
52 *
53 * @param y y-coordinate of left-up corner
54 * @param x x-coordinate of left-up corner
55 * @param lines height
56 * @param cols width
57 *
58 * @return newly allocated WRect object.
59 */
60
61 WRect *
62 rect_new (int y, int x, int lines, int cols)
/* ![[previous]](../icons/n_left.png)
![[next]](../icons/right.png)
![[first]](../icons/n_first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
63 {
64 WRect *r;
65
66 r = g_try_new (WRect, 1);
67
68 if (r != NULL)
69 rect_init (r, y, x, lines, cols);
70
71 return r;
72 }
73
74 /* --------------------------------------------------------------------------------------------- */
75 /**
76 * Initialize WRect object.
77 *
78 * @param r WRect object
79 * @param y y-coordinate of left-up corner
80 * @param x x-coordinate of left-up corner
81 * @param lines height
82 * @param cols width
83 */
84
85 void
86 rect_init (WRect *r, int y, int x, int lines, int cols)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
87 {
88 r->y = y;
89 r->x = x;
90 r->lines = lines;
91 r->cols = cols;
92 }
93
94 /* --------------------------------------------------------------------------------------------- */
95 /**
96 * Change position of rectangle area.
97 *
98 * @param r WRect object
99 * @param dy y-shift of left-up corner
100 * @param dx x-shift of left-up corner
101 */
102
103 void
104 rect_move (WRect *r, int dy, int dx)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
105 {
106 r->y += dy;
107 r->x += dx;
108 }
109
110 /* --------------------------------------------------------------------------------------------- */
111 /**
112 * Change size of rectangle area keeping it's position.
113 *
114 * @param r WRect object
115 * @param dl change size value of height
116 * @param dc change size value of width
117 */
118
119 void
120 rect_resize (WRect *r, int dl, int dc)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
121 {
122 r->lines += dl;
123 r->cols += dc;
124 }
125
126 /* --------------------------------------------------------------------------------------------- */
127 /**
128 * Change size of rectangle area keeping it's center.
129 *
130 * @param r WRect object
131 * @param dl change size value of y-coordinate and height
132 * Positive value means move up and increase height.
133 * Negative value means move down and decrease height.
134 * @param dc change size value of x-coordinate and width
135 * Positive value means move left and increase width.
136 * Negative value means move right and decrease width.
137 */
138
139 void
140 rect_grow (WRect *r, int dl, int dc)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
141 {
142 r->y -= dl;
143 r->x -= dc;
144 r->lines += dl * 2;
145 r->cols += dc * 2;
146 }
147
148 /* --------------------------------------------------------------------------------------------- */
149 /**
150 * Calculates the intersection of two rectangle areas.
151 * The resulting rectangle is the largest rectangle which contains intersection of rectangle areas.
152 *
153 * @param r first WRect object
154 * @param r1 second WRect object
155 *
156 * The resulting rectangle is stored in r.
157 */
158
159 void
160 rect_intersect (WRect *r, const WRect *r1)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
161 {
162 int y, x;
163 int y1, x1;
164
165 // right-down corners
166 y = r->y + r->lines;
167 x = r->x + r->cols;
168 y1 = r1->y + r1->lines;
169 x1 = r1->x + r1->cols;
170
171 // right-down corner of intersection
172 y = MIN (y, y1);
173 x = MIN (x, x1);
174
175 // left-up corner of intersection
176 r->y = MAX (r->y, r1->y);
177 r->x = MAX (r->x, r1->x);
178
179 // intersection sizes
180 r->lines = y - r->y;
181 r->cols = x - r->x;
182 }
183
184 /* --------------------------------------------------------------------------------------------- */
185 /**
186 * Calculates the union of two rectangle areas.
187 * The resulting rectangle is the largest rectangle which contains both rectangle areas.
188 *
189 * @param r first WRect object
190 * @param r1 second WRect object
191 *
192 * The resulting rectangle is stored in r.
193 */
194
195 void
196 rect_union (WRect *r, const WRect *r1)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
197 {
198 int x, y;
199 int x1, y1;
200
201 // right-down corners
202 y = r->y + r->lines;
203 x = r->x + r->cols;
204 y1 = r1->y + r1->lines;
205 x1 = r1->x + r1->cols;
206
207 // right-down corner of union
208 y = MAX (y, y1);
209 x = MAX (x, x1);
210
211 // left-up corner of union
212 r->y = MIN (r->y, r1->y);
213 r->x = MIN (r->x, r1->x);
214
215 // union sizes
216 r->lines = y - r->y;
217 r->cols = x - r->x;
218 }
219
220 /* --------------------------------------------------------------------------------------------- */
221 /**
222 * Check whether two rectangle areas are overlapped or not.
223 *
224 * @param r1 WRect object
225 * @param r2 WRect object
226 *
227 * @return TRUE if rectangle areas are overlapped, FALSE otherwise.
228 */
229
230 gboolean
231 rects_are_overlapped (const WRect *r1, const WRect *r2)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
232 {
233 return !((r2->x >= r1->x + r1->cols) || (r1->x >= r2->x + r2->cols)
234 || (r2->y >= r1->y + r1->lines) || (r1->y >= r2->y + r2->lines));
235 }
236
237 /* --------------------------------------------------------------------------------------------- */
238 /**
239 * Check whether two rectangle areas are equal or not.
240 *
241 * @param r1 WRect object
242 * @param r2 WRect object
243 *
244 * @return TRUE if rectangle areas are equal, FALSE otherwise.
245 */
246
247 gboolean
248 rects_are_equal (const WRect *r1, const WRect *r2)
/* ![[previous]](../icons/left.png)
![[next]](../icons/n_right.png)
![[first]](../icons/first.png)
![[last]](../icons/n_last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
249 {
250 return (r1->y == r2->y && r1->x == r2->x && r1->lines == r2->lines && r1->cols == r2->cols);
251 }
252
253 /* --------------------------------------------------------------------------------------------- */