/* * Copyright 1989 Massachusetts Institute of Technology * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, provided * that the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of M.I.T. not be used in advertising * or publicity pertaining to distribution of the software without specific, * written prior permission. M.I.T. makes no representations about the * suitability of this software for any purpose. It is provided "as is" * without express or implied warranty. * * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T. * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /********************************************************************** * * regions.c * * Region related routines * * 4/26/99 D. J. Hawkey Jr. * **********************************************************************/ #include #include #include "twm.h" #include "screen.h" #include "list.h" #include "regions.h" #include "gram.h" #include "parse.h" #include "image_formats.h" #include "util.h" #include "prototypes.h" void splitRegionEntry(RegionEntry * re, int grav1, int grav2, int w, int h) { RegionEntry *new; switch (grav1) { case D_NORTH: case D_SOUTH: if (w != re->w) splitRegionEntry(re, grav2, grav1, w, re->h); if (h != re->h) { new = (RegionEntry *) malloc(sizeof(RegionEntry)); new->u.twm_win = 0; new->type = LTYPE_EXACT_NAME; new->usedby = 0; new->next = re->next; re->next = new; new->x = re->x; new->h = (re->h - h); new->w = re->w; re->h = h; if (grav1 == D_SOUTH) { new->y = re->y; re->y = new->y + new->h; } else new->y = re->y + re->h; } break; case D_EAST: case D_WEST: if (h != re->h) splitRegionEntry(re, grav2, grav1, re->w, h); if (w != re->w) { new = (RegionEntry *) malloc(sizeof(RegionEntry)); new->u.twm_win = 0; new->type = LTYPE_EXACT_NAME; new->usedby = 0; new->next = re->next; re->next = new; new->y = re->y; new->w = (re->w - w); new->h = re->h; re->w = w; if (grav1 == D_EAST) { new->x = re->x; re->x = new->x + new->w; } else new->x = re->x + re->w; } break; } } int roundEntryUp(int v, int multiple) { return ((v + multiple - 1) / multiple) * multiple; } RegionEntry * prevRegionEntry(RegionEntry * re, RootRegion * rr) { RegionEntry *ep; if (re == rr->entries) return 0; for (ep = rr->entries; ep->next != re; ep = ep->next) ; return ep; } /* * old is being freed; and is adjacent to re. Merge regions together. */ void mergeRegionEntries(RegionEntry * old, RegionEntry * re) { if (old->y == re->y) { re->w = old->w + re->w; if (old->x < re->x) re->x = old->x; } else { re->h = old->h + re->h; if (old->y < re->y) re->y = old->y; } } void downRegionEntry(RootRegion * rr, RegionEntry * re) { RegionEntry *ep, *en; re->u.twm_win = 0; re->usedby = 0; ep = prevRegionEntry(re, rr); en = re->next; for (;;) { if (ep && ep->usedby == 0 && ((ep->x == re->x && ep->w == re->w) || (ep->y == re->y && ep->h == re->h))) { ep->next = re->next; mergeRegionEntries(re, ep); if (re->usedby == USEDBY_NAME) free(re->u.name); #ifndef NO_REGEX_SUPPORT if (re->type & LTYPE_C_REGEXP) regfree(&re->re); #endif free((char *)re); re = ep; ep = prevRegionEntry(ep, rr); } else if (en && en->usedby == 0 && ((en->x == re->x && en->w == re->w) || (en->y == re->y && en->h == re->h))) { re->next = en->next; mergeRegionEntries(en, re); if (en->usedby == USEDBY_NAME) free(en->u.name); #ifndef NO_REGEX_SUPPORT if (en->type & LTYPE_C_REGEXP) regfree(&en->re); #endif free((char *)en); en = re->next; } else break; } } RootRegion * AddRegion(char *geom, int grav1, int grav2, int stepx, int stepy) { RootRegion *rr; int mask; /* * panel name is encoded into geometry string as "1200x20+10-10@1" * where "@1" is panel "1" */ int tile; char *tile_name = strchr (geom, '@'); if (tile_name != NULL) *tile_name++ = '\0'; tile = ParsePanelIndex (tile_name); rr = (RootRegion *) malloc(sizeof(RootRegion)); rr->next = NULL; rr->grav1 = grav1; rr->grav2 = grav2; rr->stepx = (stepx <= 0) ? 2 : stepx; /* hard-coded value was '1' - djhjr - 9/26/99 */ rr->stepy = (stepy <= 0) ? 1 : stepy; rr->x = rr->y = rr->w = rr->h = 0; mask = XParseGeometry(geom, &rr->x, &rr->y, (unsigned int *)&rr->w, (unsigned int *)&rr->h); #ifdef TILED_SCREEN if (Scr->use_tiles == TRUE) EnsureGeometryVisibility(tile, mask, &rr->x, &rr->y, rr->w, rr->h); else #endif { if (mask & XNegative) rr->x += Scr->MyDisplayWidth - rr->w; if (mask & YNegative) rr->y += Scr->MyDisplayHeight - rr->h; } rr->entries = (RegionEntry *) malloc(sizeof(RegionEntry)); rr->entries->next = 0; rr->entries->x = rr->x; rr->entries->y = rr->y; rr->entries->w = rr->w; rr->entries->h = rr->h; rr->entries->u.twm_win = 0; rr->entries->type = LTYPE_EXACT_NAME; rr->entries->usedby = 0; return rr; } void FreeRegionEntries(RootRegion * rr) { RegionEntry *re, *tmp; for (re = rr->entries; re; re = tmp) { tmp = re->next; if (re->usedby == USEDBY_NAME) free(re->u.name); #ifndef NO_REGEX_SUPPORT if (re->type & LTYPE_C_REGEXP) regfree(&re->re); #endif free((char *)re); } } void FreeRegions(RootRegion * first, RootRegion * last) { RootRegion *rr, *tmp; for (rr = first; rr != NULL;) { tmp = rr; FreeRegionEntries(rr); rr = rr->next; free((char *)tmp); } first = NULL; last = NULL; } /* Local Variables: mode:c c-file-style:"GNU" c-file-offsets:((substatement-open 0)(brace-list-open 0)(c-hanging-comment-ender-p . nil)(c-hanging-comment-beginner-p . nil)(comment-start . "// ")(comment-end . "")(comment-column . 48)) End: */ /* vim: sw=2 */