CTWM
Loading...
Searching...
No Matches
/usr/src/RPM/BUILD/ctwm-4.1.0/r_area.c
Go to the documentation of this file.
1/*
2 * Copyright notice...
3 */
4
5#include "ctwm.h"
6
7#include <stdlib.h>
8#include <stdio.h>
9
10#include "r_area.h"
11#include "r_area_list.h"
12#include "util.h"
13
14
15/**
16 * Construct an RArea from given components.
17 */
19RAreaNew(int x, int y, int width, int height)
20{
21 RArea area = { x, y, width, height };
22 return area;
23}
24
25
26/**
27 * Return a pointer to a static newly constructed RArea.
28 *
29 * This is a thin wrapper around RAreaNew() that returns a static
30 * pointer. This is used in places that need to take RArea pointers, but
31 * we don't want to futz with making local intermediate vars. Currently
32 * exclusively used inline in RAreaListNew() calls.
33 */
34RArea *
35RAreaNewStatic(int x, int y, int width, int height)
36{
37 static RArea area;
38 area = RAreaNew(x, y, width, height);
39 return &area;
40}
41
42
43/**
44 * Return a facially-invalid RArea.
45 *
46 * This is used in places that need a sentinel value.
47 */
50{
51 RArea area = { -1, -1, -1, -1 };
52 return area;
53}
54
55
56/**
57 * Is an RArea facially valid?
58 *
59 * Mostly used to check against sentinel values in places that may or may
60 * not have a real value to work with.
61 */
62bool
64{
65 return self->width >= 0 && self->height >= 0;
66}
67
68
69/**
70 * Return the right edge of an RArea.
71 */
72int
74{
75 return self->x + self->width - 1;
76}
77
78
79/**
80 * Return the bottom edge of an RArea.
81 */
82int
84{
85 return self->y + self->height - 1;
86}
87
88
89/**
90 * Return the area of an RArea.
91 */
92int
94{
95 return self->width * self->height;
96}
97
98
99/**
100 * Return an RArea describing the intersection of two RArea's.
101 */
102RArea
104{
105 // Do they even intersect?
107 int x1, x2, y1, y2;
108
109 x1 = max(other->x, self->x);
111
112 y1 = max(other->y, self->y);
114
115 return RAreaNew(x1, y1, x2 - x1 + 1, y2 - y1 + 1);
116 }
117
118 // Nope, so nothing
119 return RAreaInvalid();
120}
121
122
123/**
124 * Do two areas intersect?
125 */
126bool
128{
129 // [other][self]
130 if(RAreaX2(other) < self->x) {
131 return false;
132 }
133
134 // [self][other]
135 if(other->x > RAreaX2(self)) {
136 return false;
137 }
138
139 // [other]
140 // [self]
141 if(RAreaY2(other) < self->y) {
142 return false;
143 }
144
145 // [self]
146 // [other]
147 if(other->y > RAreaY2(self)) {
148 return false;
149 }
150
151 return true;
152}
153
154
155/**
156 * Is a given coordinate inside a RArea?
157 */
158bool
159RAreaContainsXY(const RArea *self, int x, int y)
160{
161 return x >= self->x && x <= RAreaX2(self)
162 && y >= self->y && y <= RAreaY2(self);
163}
164
165
166/**
167 * Create a list of maximal horizontal stripes of two RArea's.
168 *
169 * This yields a set of RArea's that completely cover (without overlap)
170 * the pair of input RArea's (or NULL if the inputs are disjoint). That
171 * could be just a single RArea if e.g. they're the same height and
172 * touch/overlap horizontally, or they're the same width and
173 * touch/overlap vertically. Otherwise it will wind up being multiple
174 * rows (2 or 3).
175 *
176 * Only used in startup to populate the RLayout.horiz list.
177 */
178RAreaList *
180{
181 // If there's horizontal space between them, they can't possibly
182 // combine.
183 // [other] [self] or [self] [other]
184 if(RAreaX2(other) < self->x - 1) {
185 return NULL;
186 }
187 if(other->x > RAreaX2(self) + 1) {
188 return NULL;
189 }
190
191 // No vertical overlap (though maybe they touch?)
192 // [other] or [self]
193 // [self] [other]
194 if(RAreaY2(other) < self->y || other->y > RAreaY2(self)) {
195 // Special case: if they're the same width, and start at the same
196 // X coordinate, _and_ are touching each other vertically, we can
197 // combine them into a single block.
198 if(self->width == other->width && self->x == other->x) {
199 // [other]
200 // [self ]
201 if(RAreaY2(other) + 1 == self->y) {
202 return RAreaListNew(
203 1,
205 self->width, self->height + other->height),
206 NULL);
207 }
208
209 // [self ]
210 // [other]
211 if(RAreaY2(self) + 1 == other->y) {
212 return RAreaListNew(
213 1,
214 RAreaNewStatic(self->x, self->y,
215 self->width, self->height + other->height),
216 NULL);
217 }
218
219 // Nope, there must be vertical space between us
220 }
221
222 // Can't combine
223 return NULL;
224 }
225
226 // No horizontal space between the two (may be touching, or
227 // overlapping), and there's some vertical overlap.
228 // So there must be some horizontal stripes we can create.
229 {
230 // left- and right-most x coords, which define the maximum width
231 // a union could be.
232 const int min_x = min(self->x, other->x);
233 const int max_x = max(RAreaX2(self), RAreaX2(other));
234 const int max_width = max_x - min_x + 1;
235
237
238 // Figure which starts higher.
239 const RArea *top, *bot;
240 if(self->y < other->y) {
241 top = self;
242 bot = other;
243 }
244 else {
245 top = other;
246 bot = self;
247 }
248 // bot now starts even with or below top
249
250 // [ ] [ ]
251 // [bot][top] or [top][bot]
252 // [ ] [ ]
253
254 // Room in top before bot starts? That's one stripe.
255 if(bot->y != top->y) {
256 RAreaListAdd(res, RAreaNewStatic(top->x, top->y,
257 top->width, bot->y - top->y));
258 }
259
260 // Next there's a stripe across both of them.
263 max_width,
264 min(RAreaY2(top), RAreaY2(bot)) - max(top->y, bot->y) + 1));
265
266 // If their bottoms aren't coincident, there's another stripe
267 // below them of whichever one is taller.
268 if(RAreaY2(top) != RAreaY2(bot)) {
269 if(RAreaY2(bot) < RAreaY2(top)) {
270 // [ ] [ ]
271 // [bot][top] or [top][bot]
272 // [ ] [ ]
274 RAreaNewStatic(top->x, RAreaY2(bot) + 1,
275 top->width, RAreaY2(top) - RAreaY2(bot)));
276 }
277 else {
278 // [ ] [ ]
279 // [bot][top] or [top][bot]
280 // [ ] [ ]
282 RAreaNewStatic(bot->x, RAreaY2(top) + 1,
283 bot->width, RAreaY2(bot) - RAreaY2(top)));
284 }
285 }
286
287 // And there they are.
288 return res;
289 }
290}
291
292
293/**
294 * Create a list of maximal vertical stripes of two RArea's.
295 *
296 * This yields a set of RArea's that completely cover (without overlap)
297 * the pair of input RArea's (or NULL if the inputs are disjoint). This
298 * is the equivalent of RAreaHorizontalUnion(), except with vertical
299 * stripes.
300 *
301 * Only used in startup to populate the RLayout.vert list.
302 */
303RAreaList *
305{
306 // Vertical space between them; can't possibly combine.
307 if(RAreaY2(other) < self->y - 1) {
308 return NULL;
309 }
310 if(other->y > RAreaY2(self) + 1) {
311 return NULL;
312 }
313
314 // No horizontal overlap (though perhaps touching)
315 // [other][self] or [self][other]
316 if(RAreaX2(other) < self->x || other->x > RAreaX2(self)) {
317 // Special case: if they're the same height, and start at the same
318 // Y coordinate, _and_ are touching each other horizontally, we can
319 // combine them into a single block.
320 if(self->height == other->height && self->y == other->y) {
321 // [other][self]
322 if(RAreaX2(other) + 1 == self->x) {
323 return RAreaListNew(
324 1,
326 self->width + other->width, self->height),
327 NULL);
328 }
329
330 // [self][other]
331 if(RAreaX2(self) + 1 == other->x) {
332 return RAreaListNew(
333 1,
334 RAreaNewStatic(self->x, self->y,
335 self->width + other->width, self->height),
336 NULL);
337 }
338
339 // Nope, not touching; horizontal space means no combining.
340 }
341 return NULL;
342 }
343
344 // No vertical space (touching or overlap), and some horizontal
345 // overlap. So there are vertical stripes we can make.
346 {
347 // top- and bottom-most y coords, giving a maximum height
348 const int min_y = min(self->y, other->y);
349 const int max_y = max(RAreaY2(self), RAreaY2(other));
350 const int max_height = max_y - min_y + 1;
351
353
354 // Which starts left-most
355 const RArea *left, *right;
356 if(self->x < other->x) {
357 left = self;
358 right = other;
359 }
360 else {
361 left = other;
362 right = self;
363 }
364
365 // [--left--] or [right] or [right] or [left]
366 // [right] [--left--] [left] [right]
367
368 // Room to the left before right starts? That's one stripe.
369 if(right->x != left->x) {
371 RAreaNewStatic(left->x, left->y,
372 right->x - left->x, left->height));
373 }
374
375 // There's a stripe of their overlap.
377 RAreaNewStatic(right->x, min_y,
378 min(RAreaX2(left), RAreaX2(right)) - max(left->x, right->x) + 1,
379 max_height));
380
381 // If they don't end at the same x coord, there's a third stripe
382 // of a piece to the right of one or the other.
383 if(RAreaX2(left) != RAreaX2(right)) {
384 if(RAreaX2(right) < RAreaX2(left)) {
385 // [--left--] or [right]
386 // [right] [--left--]
388 RAreaNewStatic(RAreaX2(right) + 1, left->y,
389 RAreaX2(left) - RAreaX2(right), left->height));
390 }
391 else {
392 // [right] or [left]
393 // [left] [right]
395 RAreaNewStatic(RAreaX2(left) + 1, right->y,
396 RAreaX2(right) - RAreaX2(left), right->height));
397 }
398 }
399
400 return res;
401 }
402}
403
404
405/**
406 * Pretty-print an RArea.
407 *
408 * Used for dev/debug.
409 */
410void
412{
413 fprintf(stderr, "[x=%d y=%d w=%d h=%d]", self->x, self->y, self->width,
414 self->height);
415}
static int PlaceX
Definition add_window.c:82
int y
Definition menus.c:70
int x
Definition menus.c:69
RArea RAreaInvalid(void)
Return a facially-invalid RArea.
Definition r_area.c:49
RArea RAreaNew(int x, int y, int width, int height)
Construct an RArea from given components.
Definition r_area.c:19
RArea RAreaIntersect(const RArea *self, const RArea *other)
Return an RArea describing the intersection of two RArea's.
Definition r_area.c:103
int RAreaArea(const RArea *self)
Return the area of an RArea.
Definition r_area.c:93
RAreaList * RAreaHorizontalUnion(const RArea *self, const RArea *other)
Create a list of maximal horizontal stripes of two RArea's.
Definition r_area.c:179
bool RAreaIsIntersect(const RArea *self, const RArea *other)
Do two areas intersect?
Definition r_area.c:127
RArea * RAreaNewStatic(int x, int y, int width, int height)
Return a pointer to a static newly constructed RArea.
Definition r_area.c:35
bool RAreaIsValid(const RArea *self)
Is an RArea facially valid?
Definition r_area.c:63
void RAreaPrint(const RArea *self)
Pretty-print an RArea.
Definition r_area.c:411
int RAreaY2(const RArea *self)
Return the bottom edge of an RArea.
Definition r_area.c:83
int RAreaX2(const RArea *self)
Return the right edge of an RArea.
Definition r_area.c:73
RAreaList * RAreaVerticalUnion(const RArea *self, const RArea *other)
Create a list of maximal vertical stripes of two RArea's.
Definition r_area.c:304
bool RAreaContainsXY(const RArea *self, int x, int y)
Is a given coordinate inside a RArea?
Definition r_area.c:159
RAreaList * RAreaListNew(int cap,...)
Create an RAreaList from a set of RArea's.
Definition r_area_list.c:40
void RAreaListAdd(RAreaList *self, const RArea *area)
Add an RArea onto an RAreaList.
A set of RArea's.
Definition r_structs.h:30
A particular extent of space.
Definition r_structs.h:16
int y
Y position.
Definition r_structs.h:18
int width
X dimension.
Definition r_structs.h:19
int height
Y dimension.
Definition r_structs.h:20
int x
X position.
Definition r_structs.h:17
static int min(int a, int b)
Definition util.h:30
static int max(int a, int b)
Definition util.h:25