CTWM
Loading...
Searching...
No Matches
/usr/src/RPM/BUILD/ctwm-4.1.0/r_area_list.c
Go to the documentation of this file.
1/*
2 * Copyright notice...
3 */
4
5#include "ctwm.h"
6
7#include <stdio.h>
8#include <stdlib.h>
9#include <stdarg.h>
10#include <string.h>
11
12#include "r_area_list.h"
13#include "r_area.h"
14
15
16/*
17 * Prototype internal funcs
18 */
20static void RAreaListDelete(RAreaList *self, int index);
21static void RAreaListAddList(RAreaList *self, const RAreaList *other);
23 const RArea *area);
24
25/* Sorts and their internal comparison routines */
26static int _cmpX(const void *av, const void *bv);
27static void RAreaListSortX(const RAreaList *self);
28static int _cmpY(const void *av, const void *bv);
29static void RAreaListSortY(const RAreaList *self);
30
31
32
33/**
34 * Create an RAreaList from a set of RArea's.
35 * \param cap Hint as to the number of RArea's being passed
36 * \param ... Sequence of RArea * to put in it. Don't forget a trailing
37 * NULL.
38 */
41{
42 va_list ap;
44 RArea *area;
45
46 list = malloc(sizeof(RAreaList));
47 if(list == NULL) {
48 abort();
49 }
50 list->len = 0;
51
52 if(cap <= 0) {
53 cap = 1;
54 }
55 list->cap = cap;
56 list->areas = malloc(cap * sizeof(RArea));
57 if(list->areas == NULL) {
58 abort();
59 }
60
61 va_start(ap, cap);
62
63 while((area = va_arg(ap, RArea *)) != NULL) {
64 RAreaListAdd(list, area);
65 }
66
67 va_end(ap);
68
69 return list;
70}
71
72
73/**
74 * Create a copy of a given RAreaList.
75 */
76static RAreaList *
78{
79 RAreaList *new = RAreaListNew(self->cap, NULL);
80
82
83 return new;
84}
85
86
87/**
88 * Create a copy of an RAreaList with given amounts cropped off the
89 * sides. This is used principally during startup, to handle the
90 * BorderBottom/Top/Left/Right config params.
91 */
94 int right_margin,
96{
97 if(left_margin > 0 || right_margin > 0
98 || top_margin > 0 || bottom_margin > 0) {
99 // Start with a big spanning square
101
102 // Guard against negative margins
103 if(left_margin < 0) {
104 left_margin = 0;
105 }
106 if(right_margin < 0) {
107 right_margin = 0;
108 }
109 if(top_margin < 0) {
110 top_margin = 0;
111 }
112 if(bottom_margin < 0) {
113 bottom_margin = 0;
114 }
115
116 // Squeeze down the big square by the asked for amounts
119 big_area.y += top_margin;
121
122 // If we cropped down to nothing, that's a RAreaList with nothing
123 // in it, so give back that.
124 if(big_area.width <= 0 || big_area.height <= 0) {
125 return RAreaListNew(0, NULL); // empty list
126 }
127
128 // Make a new RAreaList cropped down to that size.
130 }
131
132 // Nothing to do; our callers expect getting nothing back.
133 return NULL;
134}
135
136
137/**
138 * Clean up and free an RAreaList.
139 */
140void
142{
143 if(self == NULL) {
144 return;
145 }
146 free(self->areas);
147 free(self);
148}
149
150
151/**
152 * Delete an RArea from inside an RAreaList.
153 */
154static void
156{
157 if(index >= self->len) {
158 return;
159 }
160
161 self->len--;
162
163 if(index == self->len) {
164 return;
165 }
166
167 memcpy(&self->areas[index], &self->areas[index + 1],
168 (self->len - index) * sizeof(RArea));
169}
170
171
172/**
173 * Add an RArea onto an RAreaList.
174 */
175void
177{
178 if(self->cap == self->len) {
179 RArea *new_list = realloc(self->areas, (self->cap + 1) * sizeof(RArea));
180 if(new_list == NULL) {
181 abort();
182 }
183
184 self->cap++;
185 self->areas = new_list;
186 }
187
188 self->areas[self->len++] = *area;
189}
190
191
192/**
193 * Add the RArea's from one RAreaList onto another.
194 */
195static void
197{
198 if(self->cap - self->len < other->len) {
199 RArea *new_list = realloc(self->areas,
200 (self->len + other->len) * sizeof(RArea));
201 if(new_list == NULL) {
202 abort();
203 }
204
205 self->cap = self->len + other->len;
206 self->areas = new_list;
207 }
208
209 memcpy(&self->areas[self->len], other->areas, other->len * sizeof(RArea));
210
211 self->len += other->len;
212}
213
214
215/**
216 * qsort comparison function to sort by RArea.x
217 */
218static int
219_cmpX(const void *av, const void *bv)
220{
221 const RArea *a = (const RArea *)av, *b = (const RArea *)bv;
222
223 if(a->x < b->x) {
224 return -1;
225 }
226
227 if(a->x > b->x) {
228 return 1;
229 }
230
231 return (a->y > b->y) - (a->y < b->y);
232}
233
234
235/**
236 * Sort the RArea's in an RAreaList by their x coordinate.
237 */
238static void
240{
241 if(self->len <= 1) {
242 return;
243 }
244
245 qsort(self->areas, self->len, sizeof(RArea), _cmpX);
246}
247
248
249/**
250 * qsort comparison function to sort by RArea.t
251 */
252static int
253_cmpY(const void *av, const void *bv)
254{
255 const RArea *a = (const RArea *)av, *b = (const RArea *)bv;
256
257 if(a->y < b->y) {
258 return -1;
259 }
260
261 if(a->y > b->y) {
262 return 1;
263 }
264
265 return (a->x > b->x) - (a->x < b->x);
266}
267
268
269/**
270 * Sort the RArea's in an RAreaList by their y coordinate.
271 */
272static void
274{
275 if(self->len <= 1) {
276 return;
277 }
278
279 qsort(self->areas, self->len, sizeof(RArea), _cmpY);
280}
281
282
283/**
284 * Create an RAreaList whose RArea's are the horizontal union of our
285 * RArea's.
286 */
287RAreaList *
289{
291
292refine:
293 // Two areas can't form a horizontal stripe if there's any space
294 // between them. So start by putting them all in x-coord order to be
295 // sure any gaps there are necessary.
297
298 // Try HorizontalUnion'ing each area with the next one. If we can
299 // create a union, replace them with it, and hop back to the top of
300 // the process to start over.
301 for(int i = 0; i < copy->len - 1; i++) {
302 for(int j = i + 1; j < copy->len; j++) {
303 RAreaList *repl = RAreaHorizontalUnion(&copy->areas[i], &copy->areas[j]);
304 if(repl != NULL) {
305 if(repl->len) {
310 goto refine;
311 }
313 }
314 }
315 }
316
317 return copy;
318}
319
320
321/**
322 * Create an RAreaList whose RArea's are the vertical union of our
323 * RArea's.
324 */
325RAreaList *
327{
329
330refine:
331 // X-ref logic above in RAreaListHorizontalUnion()
333
334 for(int i = 0; i < copy->len - 1; i++) {
335 for(int j = i + 1; j < copy->len; j++) {
336 RAreaList *repl = RAreaVerticalUnion(&copy->areas[i], &copy->areas[j]);
337 if(repl != NULL) {
338 if(repl->len) {
343 goto refine;
344 }
346 }
347 }
348 }
349
350 return copy;
351}
352
353
354/**
355 * Create an RAreaList of all the areas in an RAreaList that a given
356 * RArea intersects with.
357 */
358RAreaList *
360{
361 RAreaList *new = RAreaListNew(self->len, NULL);
362
363 for(int i = 0; i < self->len; i++) {
364 if(RAreaIsIntersect(&self->areas[i], area)) {
365 RAreaListAdd(new, &self->areas[i]);
366 }
367 }
368
369 return new;
370}
371
372
373/**
374 * Run a function over each RArea in an RAreaList until one returns true,
375 * allowing them a place to stash other internal data.
376 */
377void
379 bool (*func)(const RArea *cur_area, void *data),
380 void *data)
381{
382 for(int i = 0 ; i < self->len ; i++) {
383 if(func(&(self->areas[i]), data) == true) {
384 break;
385 }
386 }
387}
388
389
390
391/**
392 * Create an RAreaList from another, cropped to a certain area defined by
393 * an RArea.
394 */
395static RAreaList *
397{
398 RAreaList *new = RAreaListNew(self->len, NULL);
399
400 for(int i = 0; i < self->len; i++) {
401 RArea it = RAreaIntersect(&self->areas[i], area);
402 if(RAreaIsValid(&it)) {
403 RAreaListAdd(new, &it);
404 }
405 }
406
407 return new;
408}
409
410
411/**
412 * Create a maximal RArea describing the union of an RAreaList.
413 *
414 * This is used to construct a giant square that contains all our
415 * monitors (and the dead area necessary to cover them). It winds up
416 * being the equivalent of a spanning pseudo-Root window, and is used
417 * when we need to figure some sort of "overall" positioning, like when
418 * figuring "real" x/y coordinates.
419 */
420RArea
422{
423 int x, y, x2, y2;
424
425 // Guard; probably impossible
426 if(self->len < 1) {
427 return RAreaInvalid();
428 }
429
430 for(int i = 0 ; i < self->len ; i++) {
431 const RArea *area = &(self->areas[i]);
432 if(i == 0 || area->x < x) {
433 x = area->x;
434 }
435
436 if(i == 0 || area->y < y) {
437 y = area->y;
438 }
439
440 if(i == 0 || RAreaX2(area) > x2) {
441 x2 = RAreaX2(area);
442 }
443
444 if(i == 0 || RAreaY2(area) > y2) {
445 y2 = RAreaY2(area);
446 }
447 }
448
449 return RAreaNew(x, y, x2 - x + 1, y2 - y + 1);
450}
451
452
453/**
454 * Find the RArea in an RAreaList that has the largest intersection with
455 * a given RArea. Colloquially, which area in an RAreaList does our
456 * RArea mostly fit into? This is used to resize a window to fill one
457 * monitor, by finding which monitor it's on.
458 */
459RArea
461{
463 int max_area = -1;
464
465 for(int i = 0; i < self->len; i++) {
466 RArea it = RAreaIntersect(area, &self->areas[i]);
467 if(RAreaIsValid(&it) && (max_area < 0 || RAreaArea(&it) > max_area)) {
469 full_area = self->areas[i];
470 }
471 }
472
473 return full_area;
474}
475
476
477/**
478 * Find the x coordinate of the right-most RArea in an RAreaList.
479 */
480int
482{
483 RArea *cur_area = &self->areas[0], *area_end = &self->areas[self->len];
484 int max_x = self->len ? cur_area->x : 0;
485
486 // While a for(i=0 ; i<self->len ; i++) loop is generally nicer for
487 // these iterations, it winds up being a little trickier here, so we
488 // leave it as a pointer-stepper.
489 while(++cur_area < area_end) {
490 if(cur_area->x > max_x) {
491 max_x = cur_area->x;
492 }
493 }
494
495 return max_x;
496}
497
498
499/**
500 * Find the y coordinate of the bottom-most RArea in an RAreaList.
501 */
502int
504{
505 RArea *cur_area = &self->areas[0], *area_end = &self->areas[self->len];
506 int max_y = self->len ? cur_area->y : 0;
507
508 while(++cur_area < area_end) {
509 if(cur_area->y > max_y) {
510 max_y = cur_area->y;
511 }
512 }
513
514 return max_y;
515}
516
517
518/**
519 * Find the x coordinate of the right edge of the left-most RArea in an
520 * RAreaList.
521 */
522int
524{
525 RArea *cur_area = &self->areas[0], *area_end = &self->areas[self->len];
526 int min_x = self->len ? RAreaX2(cur_area) : 0;
527
528 while(++cur_area < area_end) {
529 if(RAreaX2(cur_area) < min_x) {
531 }
532 }
533
534 return min_x;
535}
536
537
538/**
539 * Find the y coordinate of the bottom edge of the top-most RArea in an
540 * RAreaList.
541 */
542int
544{
545 RArea *cur_area = &self->areas[0], *area_end = &self->areas[self->len];
546 int min_y = self->len ? RAreaY2(cur_area) : 0;
547
548 while(++cur_area < area_end) {
549 if(RAreaY2(cur_area) < min_y) {
551 }
552 }
553
554 return min_y;
555}
556
557
558/**
559 * Pretty-print an RAreaList.
560 *
561 * Used for dev/debug.
562 */
563void
565{
566 fprintf(stderr, "[len=%d cap=%d", self->len, self->cap);
567
568 for(int i = 0 ; i < self->len ; i++) {
569 RArea *area = &self->areas[i];
570 fprintf(stderr, " ");
571 RAreaPrint(area);
572 }
573
574 fprintf(stderr, "]");
575}
static int PlaceX
Definition add_window.c:82
int y
Definition menus.c:70
int x
Definition menus.c:69
int cap
Definition parse_be.c:2020
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
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
RAreaList * RAreaListNew(int cap,...)
Create an RAreaList from a set of RArea's.
Definition r_area_list.c:40
RArea RAreaListBestTarget(const RAreaList *self, const RArea *area)
Find the RArea in an RAreaList that has the largest intersection with a given RArea.
static int _cmpX(const void *av, const void *bv)
qsort comparison function to sort by RArea.x
int RAreaListMinY2(const RAreaList *self)
Find the y coordinate of the bottom edge of the top-most RArea in an RAreaList.
static void RAreaListSortY(const RAreaList *self)
Sort the RArea's in an RAreaList by their y coordinate.
static RAreaList * RAreaListIntersectCrop(const RAreaList *self, const RArea *area)
Create an RAreaList from another, cropped to a certain area defined by an RArea.
static void RAreaListAddList(RAreaList *self, const RAreaList *other)
Add the RArea's from one RAreaList onto another.
RAreaList * RAreaListVerticalUnion(const RAreaList *self)
Create an RAreaList whose RArea's are the vertical union of our RArea's.
void RAreaListFree(RAreaList *self)
Clean up and free an RAreaList.
RArea RAreaListBigArea(const RAreaList *self)
Create a maximal RArea describing the union of an RAreaList.
int RAreaListMaxY(const RAreaList *self)
Find the y coordinate of the bottom-most RArea in an RAreaList.
void RAreaListPrint(const RAreaList *self)
Pretty-print an RAreaList.
static int _cmpY(const void *av, const void *bv)
qsort comparison function to sort by RArea.t
RAreaList * RAreaListIntersect(const RAreaList *self, const RArea *area)
Create an RAreaList of all the areas in an RAreaList that a given RArea intersects with.
static void RAreaListDelete(RAreaList *self, int index)
Delete an RArea from inside an RAreaList.
int RAreaListMaxX(const RAreaList *self)
Find the x coordinate of the right-most RArea in an RAreaList.
static RAreaList * RAreaListCopy(const RAreaList *self)
Create a copy of a given RAreaList.
Definition r_area_list.c:77
RAreaList * RAreaListHorizontalUnion(const RAreaList *self)
Create an RAreaList whose RArea's are the horizontal union of our RArea's.
void RAreaListForeach(const RAreaList *self, bool(*func)(const RArea *cur_area, void *data), void *data)
Run a function over each RArea in an RAreaList until one returns true, allowing them a place to stash...
static void RAreaListSortX(const RAreaList *self)
Sort the RArea's in an RAreaList by their x coordinate.
RAreaList * RAreaListCopyCropped(const RAreaList *self, int left_margin, int right_margin, int top_margin, int bottom_margin)
Create a copy of an RAreaList with given amounts cropped off the sides.
Definition r_area_list.c:93
void RAreaListAdd(RAreaList *self, const RArea *area)
Add an RArea onto an RAreaList.
int RAreaListMinX2(const RAreaList *self)
Find the x coordinate of the right edge of the left-most RArea in 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 x
X position.
Definition r_structs.h:17