chiark / gitweb /
debian/changelog: start -4~
[vtwm.git] / regions.c
1 /*
2  * Copyright 1989 Massachusetts Institute of Technology
3  *
4  * Permission to use, copy, modify, and distribute this software and its
5  * documentation for any purpose and without fee is hereby granted, provided
6  * that the above copyright notice appear in all copies and that both that
7  * copyright notice and this permission notice appear in supporting
8  * documentation, and that the name of M.I.T. not be used in advertising
9  * or publicity pertaining to distribution of the software without specific,
10  * written prior permission.  M.I.T. makes no representations about the
11  * suitability of this software for any purpose.  It is provided "as is"
12  * without express or implied warranty.
13  *
14  * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
16  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
18  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 
19  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20  */
21
22 /**********************************************************************
23  *
24  * regions.c
25  *
26  * Region related routines
27  *
28  * 4/26/99 D. J. Hawkey Jr.
29  *
30  **********************************************************************/
31
32 #include <stdio.h>
33 #include <string.h>
34 #include "twm.h"
35 #include "screen.h"
36 #include "list.h"
37 #include "regions.h"
38 #include "gram.h"
39 #include "parse.h"
40 #include "util.h"
41
42 void
43 splitRegionEntry (re, grav1, grav2, w, h)
44     RegionEntry *re;
45     int         grav1, grav2;
46     int         w, h;
47 {
48     RegionEntry *new;
49
50     switch (grav1) {
51     case D_NORTH:
52     case D_SOUTH:
53         if (w != re->w)
54             splitRegionEntry (re, grav2, grav1, w, re->h);
55         if (h != re->h) {
56             new = (RegionEntry *)malloc (sizeof (RegionEntry));
57             new->u.twm_win = 0;
58             /* djhjr - 10/20/01 */
59             new->type = LTYPE_EXACT_NAME;
60             new->usedby = 0;
61             new->next = re->next;
62             re->next = new;
63             new->x = re->x;
64             new->h = (re->h - h);
65             new->w = re->w;
66             re->h = h;
67             if (grav1 == D_SOUTH) {
68                 new->y = re->y;
69                 re->y = new->y + new->h;
70             } else
71                 new->y = re->y + re->h;
72         }
73         break;
74     case D_EAST:
75     case D_WEST:
76         if (h != re->h)
77             splitRegionEntry (re, grav2, grav1, re->w, h);
78         if (w != re->w) {
79             new = (RegionEntry *)malloc (sizeof (RegionEntry));
80             new->u.twm_win = 0;
81             /* djhjr - 10/20/01 */
82             new->type = LTYPE_EXACT_NAME;
83             new->usedby = 0;
84             new->next = re->next;
85             re->next = new;
86             new->y = re->y;
87             new->w = (re->w - w);
88             new->h = re->h;
89             re->w = w;
90             if (grav1 == D_EAST) {
91                 new->x = re->x;
92                 re->x = new->x + new->w;
93             } else
94                 new->x = re->x + re->w;
95         }
96         break;
97     }
98 }
99
100 int
101 roundEntryUp (v, multiple)
102 {
103     return ((v + multiple - 1) / multiple) * multiple;
104 }
105
106 RegionEntry *
107 prevRegionEntry (re, rr)
108     RegionEntry *re;
109     RootRegion  *rr;
110 {
111     RegionEntry *ep;
112
113     if (re == rr->entries)
114         return 0;
115     for (ep = rr->entries; ep->next != re; ep=ep->next)
116         ;
117     return ep;
118 }
119
120 /*
121  * old is being freed; and is adjacent to re.  Merge regions together.
122  */
123 void
124 mergeRegionEntries (old, re)
125     RegionEntry *old, *re;
126 {
127     if (old->y == re->y) {
128         re->w = old->w + re->w;
129         if (old->x < re->x)
130             re->x = old->x;
131     } else {
132         re->h = old->h + re->h;
133         if (old->y < re->y)
134             re->y = old->y;
135     }
136 }
137
138 void
139 downRegionEntry(rr, re)
140 RootRegion      *rr;
141 RegionEntry     *re;
142 {
143         RegionEntry     *ep, *en;
144
145         re->u.twm_win = 0;
146         re->usedby = 0;
147         ep = prevRegionEntry (re, rr);
148         en = re->next;
149         for (;;) {
150                 if (ep && ep->usedby == 0 &&
151                                 ((ep->x == re->x && ep->w == re->w) ||
152                                 (ep->y == re->y && ep->h == re->h)))
153                 {
154                         ep->next = re->next;
155                         mergeRegionEntries (re, ep);
156                         if (re->usedby == USEDBY_NAME)
157                                 free(re->u.name);
158 /* djhjr - 10/20/01 */
159 #ifndef NO_REGEX_SUPPORT
160                         if (re->type & LTYPE_C_REGEXP)
161                                 regfree(&re->re);
162 #endif
163                         free ((char *) re);
164                         re = ep;
165                         ep = prevRegionEntry (ep, rr);
166                 } else if (en && en->usedby == 0 &&
167                                 ((en->x == re->x && en->w == re->w) ||
168                                 (en->y == re->y && en->h == re->h)))
169                 {
170                         re->next = en->next;
171                         mergeRegionEntries (en, re);
172                         if (en->usedby == USEDBY_NAME)
173                                 free(en->u.name);
174 /* djhjr - 10/20/01 */
175 #ifndef NO_REGEX_SUPPORT
176                         if (en->type & LTYPE_C_REGEXP)
177                                 regfree(&en->re);
178 #endif
179                         free ((char *) en);
180                         en = re->next;
181                 } else
182                         break;
183         }
184 }
185
186 RootRegion *
187 AddRegion(geom, grav1, grav2, stepx, stepy)
188 char *geom;
189 int grav1, grav2, stepx, stepy;
190 {
191     RootRegion *rr;
192     int mask;
193
194     rr = (RootRegion *)malloc(sizeof(RootRegion));
195     rr->next = NULL;
196     rr->grav1 = grav1;
197     rr->grav2 = grav2;
198     rr->stepx = (stepx <= 0) ? 2 : stepx; /* hard-coded value was '1' - djhjr - 9/26/99 */
199     rr->stepy = (stepy <= 0) ? 1 : stepy;
200     rr->x = rr->y = rr->w = rr->h = 0;
201
202     mask = XParseGeometry(geom, &rr->x, &rr->y, (unsigned int *)&rr->w, (unsigned int *)&rr->h);
203     if (mask & XNegative)
204         rr->x += Scr->MyDisplayWidth - rr->w;
205     if (mask & YNegative)
206         rr->y += Scr->MyDisplayHeight - rr->h;
207
208     rr->entries = (RegionEntry *)malloc(sizeof(RegionEntry));
209     rr->entries->next = 0;
210     rr->entries->x = rr->x;
211     rr->entries->y = rr->y;
212     rr->entries->w = rr->w;
213     rr->entries->h = rr->h;
214     rr->entries->u.twm_win = 0;
215     /* djhjr - 10/20/01 */
216     rr->entries->type = LTYPE_EXACT_NAME;
217     rr->entries->usedby = 0;
218
219     return rr;
220 }
221
222 void
223 FreeRegionEntries (rr)
224     RootRegion  *rr;
225 {
226     RegionEntry *re, *tmp;
227
228     for (re = rr->entries; re; re=tmp)
229     {
230         tmp = re->next;
231         if (re->usedby == USEDBY_NAME)
232                 free(re->u.name);
233 /* djhjr - 10/20/01 */
234 #ifndef NO_REGEX_SUPPORT
235         if (re->type & LTYPE_C_REGEXP)
236                 regfree(&re->re);
237 #endif
238         free ((char *) re);
239     }
240 }
241
242 void
243 FreeRegions (first, last)
244     RootRegion  *first, *last;
245 {
246     RootRegion *rr, *tmp;
247
248     for (rr = first; rr != NULL;)
249     {
250         tmp = rr;
251         FreeRegionEntries (rr);
252         rr = rr->next;
253         free((char *) tmp);
254     }
255     first = NULL;
256     last = NULL;
257 }
258