1: #include <X/mit-copyright.h> 2: 3: /* Copyright Massachusetts Institute of Technology 1985 */ 4: 5: /* Routines for calculating how windows obscure each other: 6: * 7: * Obscure_top, Obscure_bottom, Remove_rectangles 8: */ 9: 10: #ifndef lint 11: static char *rcsid_obscure_c = "$Header: obscure.c,v 10.7 86/02/01 15:16:51 tony Rel $"; 12: #endif 13: 14: #include "Xint.h" 15: 16: extern RECTANGLE *free_rectangles; 17: 18: RECTANGLE *Alloc_rectangle(), **Do_overlap(); 19: 20: /* Obscure_top allocates the rectangles for a top window, and updates the lists 21: * of visible rectangles in other mapped windows to reflect obscuring. 22: */ 23: 24: Obscure_top (w) 25: register WINDOW *w; 26: { 27: register WINDOW *w1; 28: register RECTANGLE *pr, *v, *r; 29: RECTANGLE crec, brec1, brec2, brec3, brec4; 30: int done; 31: 32: /* Compute visible rectangles from what parent has to offer */ 33: 34: *(RASTER *) &crec = w->vs; 35: done = 0; 36: for (pr = w->parent->cmvisible; pr; pr = pr->next) { 37: if (crec.left >= pr->right || pr->left >= crec.right || 38: crec.top >= pr->bottom || pr->top >= crec.bottom) 39: continue; 40: NEWRECT(v, max(crec.left, pr->left), min(crec.right, pr->right), 41: max(crec.top, pr->top), min(crec.bottom, pr->bottom), 42: contents_rec); 43: if (v->left == crec.left && v->right == crec.right && 44: v->top == crec.top && v->bottom == crec.bottom) 45: done = 1; 46: RASTRECT(r, *(RASTER *) v, contents_rec); 47: if (w->visible && TRUE(Merge_vertical (v, &w->visible, 1))) 48: Merge_vertical (r, &w->cmvisible, 1); 49: else { 50: v->next = w->visible; 51: w->visible = v; 52: r->next = w->cmvisible; 53: w->cmvisible = r; 54: } 55: if TRUE(done) break; 56: } 57: w->unobscured = OB_NOT; 58: Windex (w); 59: 60: if (w->bwidth) { 61: /* Compute the visible border */ 62: brec1.left = w->full.left - w->bwidth; 63: brec1.right = w->full.left; 64: brec1.top = w->full.top; 65: brec1.bottom = w->full.bottom; 66: brec1.next = &brec2; 67: brec2.left = w->full.right; 68: brec2.right = w->full.right + w->bwidth; 69: brec2.top = w->full.top; 70: brec2.bottom = w->full.bottom; 71: brec2.next = &brec3; 72: brec3.left = w->full.left - w->bwidth; 73: brec3.right = w->full.right + w->bwidth; 74: brec3.top = w->full.top - w->bwidth; 75: brec3.bottom = w->full.top; 76: brec3.next = &brec4; 77: brec4.left = w->full.left - w->bwidth; 78: brec4.right = w->full.right + w->bwidth; 79: brec4.top = w->full.bottom; 80: brec4.bottom = w->full.bottom + w->bwidth; 81: brec4.type = border_rec; 82: brec4.next = NULL; 83: 84: r = &brec1; 85: do { 86: done = 0; 87: /* again, use what parent has to offer */ 88: for (pr = w->parent->cmvisible; pr; pr = pr->next) { 89: if (r->left >= pr->right || pr->left >= r->right || 90: r->top >= pr->bottom || pr->top >= r->bottom) 91: continue; 92: NEWRECT(v, max(r->left, pr->left), min(r->right, pr->right), 93: max(r->top, pr->top), min(r->bottom, pr->bottom), 94: border_rec); 95: if (v->left == r->left && v->right == r->right && 96: v->top == r->top && v->bottom == r->bottom) 97: done = 1; 98: if (w->visible == NULL || 99: FALSE(Merge_vertical (v, &w->visible, 1))) { 100: v->next = w->visible; 101: w->visible = v; 102: } 103: if TRUE(done) break; 104: } 105: } while (r = r->next); 106: } 107: 108: if (w->visible == NULL) 109: return; 110: 111: /* Let the window obscure the rest of the list */ 112: 113: w1 = w; 114: while (1) { 115: w1 = w1->next; 116: 117: if (w1->kind == IsTransparent || 118: w->ovs.left >= w1->ovs.right || w1->ovs.left >= w->ovs.right || 119: w->ovs.top >= w1->ovs.bottom || w1->ovs.top >= w->ovs.bottom) { 120: if (w1 != w->parent) 121: continue; 122: return; 123: } 124: 125: if (TRUE(Calc_overlaps (&w->ovs, &w1->visible)) && w1->unobscured == OB_YES) 126: w1->unobscured = OB_NOT; 127: if (w1 == w->parent) 128: return; 129: Calc_overlaps (&w->ovs, &w1->cmvisible); 130: } 131: } 132: 133: /* Obscure_bottom allocates the rectangles for a bottom window, and updates the 134: * lists of visible rectangles in the parent to reflect obscuring. 135: */ 136: 137: Obscure_bottom (w) 138: register WINDOW *w; 139: { 140: register WINDOW *w1; 141: register RECTANGLE **prev, *v, *pr, *r; 142: RECTANGLE crec, brec1, brec2, brec3, brec4; 143: int done; 144: 145: /* Compute visible rectangles from what parent has left */ 146: 147: *(RASTER *) &crec = w->vs; 148: done = 0; 149: w1 = w->parent; 150: prev = &w1->visible; 151: while (pr = *prev) { 152: if (pr->type == border_rec || 153: crec.left >= pr->right || pr->left >= crec.right || 154: crec.top >= pr->bottom || pr->top >= crec.bottom) { 155: prev = &pr->next; 156: continue; 157: } 158: NEWRECT(v, max(crec.left, pr->left), min(crec.right, pr->right), 159: max(crec.top, pr->top), min(crec.bottom, pr->bottom), 160: contents_rec); 161: if (v->left == crec.left && v->right == crec.right && 162: v->top == crec.top && v->bottom == crec.bottom) 163: done = 1; 164: /* compute what remains for parent */ 165: prev = Do_overlap ((RASTER *) v, prev, &w1->visible); 166: if (w1->unobscured == OB_YES) 167: w1->unobscured = OB_NOT; 168: RASTRECT(r, *(RASTER *) v, contents_rec); 169: if (w->visible && TRUE(Merge_vertical (v, &w->visible, 1))) 170: Merge_vertical (r, &w->cmvisible, 1); 171: else { 172: v->next = w->visible; 173: w->visible = v; 174: r->next = w->cmvisible; 175: w->cmvisible = r; 176: } 177: if TRUE(done) break; 178: } 179: w->unobscured = OB_NOT; 180: Windex (w); 181: 182: if (w->bwidth) { 183: /* Compute visible border from what parent has left */ 184: brec1.left = w->full.left - w->bwidth; 185: brec1.right = w->full.left; 186: brec1.top = w->full.top; 187: brec1.bottom = w->full.bottom; 188: brec1.next = &brec2; 189: brec2.left = w->full.right; 190: brec2.right = w->full.right + w->bwidth; 191: brec2.top = w->full.top; 192: brec2.bottom = w->full.bottom; 193: brec2.next = &brec3; 194: brec3.left = w->full.left - w->bwidth; 195: brec3.right = w->full.right + w->bwidth; 196: brec3.top = w->full.top - w->bwidth; 197: brec3.bottom = w->full.top; 198: brec3.next = &brec4; 199: brec4.left = w->full.left - w->bwidth; 200: brec4.right = w->full.right + w->bwidth; 201: brec4.top = w->full.bottom; 202: brec4.bottom = w->full.bottom + w->bwidth; 203: brec4.type = border_rec; 204: brec4.next = NULL; 205: 206: r = &brec1; 207: do { 208: done = 0; 209: prev = &w1->visible; 210: while (pr = *prev) { 211: if (pr->type == border_rec || 212: r->left >= pr->right || pr->left >= r->right || 213: r->top >= pr->bottom || pr->top >= r->bottom) { 214: prev = &pr->next; 215: continue; 216: } 217: NEWRECT(v, max(r->left, pr->left), min(r->right, pr->right), 218: max(r->top, pr->top), min(r->bottom, pr->bottom), 219: border_rec); 220: if (v->left == r->left && v->right == r->right && 221: v->top == r->top && v->bottom == r->bottom) 222: done = 1; 223: /* compute what remains in parent */ 224: prev = Do_overlap ((RASTER *) v, prev, &w1->visible); 225: if (w1->unobscured == OB_YES) 226: w1->unobscured = OB_NOT; 227: if (w->visible == NULL || 228: FALSE(Merge_vertical (v, &w->visible, 1))) { 229: v->next = w->visible; 230: w->visible = v; 231: } 232: if TRUE(done) break; 233: } 234: } while (r = r->next); 235: } 236: } 237: 238: /* Remove_rectangles removes rectangles from remw and gives the space to 239: * the various windows in the chain. It does this by moving down the list, 240: * giving space to each window in turn. If cleanup = 1, then update and 241: * display windows you give space to. If cleanup < 0, then update the 242: * windows without changing the bits on the screen. If, in the course 243: * of following the chain, remw is encountered, we stop. 244: */ 245: 246: Remove_rectangles (remw, chain, cleanup) 247: register WINDOW *remw; 248: WINDOW *chain; 249: int cleanup; 250: { 251: register RECTANGLE *r, **oldr; 252: register WINDOW *w, *ww; 253: register RECTANGLE *addrec; 254: RECTANGLE *new; 255: 256: for (w = chain; remw->visible && w != remw; w = w->next) { 257: 258: if (w->kind == IsTransparent || 259: w->ovs.left >= remw->ovs.right || remw->ovs.left >= w->ovs.right || 260: w->ovs.top >= remw->ovs.bottom || remw->ovs.top >= w->ovs.bottom) 261: continue; 262: 263: new = NULL; 264: 265: oldr = &remw->visible; 266: while (r = *oldr) { 267: if (w->ovs.left >= r->right || r->left >= w->ovs.right || 268: w->ovs.top >= r->bottom || r->top >= w->ovs.bottom) { 269: oldr = &r->next; 270: } else { 271: /* compute what remains */ 272: oldr = Do_overlap (&w->ovs, oldr, &remw->visible); 273: remw->unobscured = OB_NOT; 274: /* get the piece it wants */ 275: Clip_rectangle (r, &w->ovs); 276: /* remove it */ 277: if (r->type != border_rec && remw->cmvisible) 278: Calc_overlaps ((RASTER *)r, &remw->cmvisible); 279: 280: /* give it to our elders too */ 281: if (w->level > remw->level) { 282: ww = w; 283: while ((ww = ww->parent)->level >= remw->level) { 284: RASTRECT(addrec, *(RASTER *) r, new_rec); 285: addrec->next = ww->cmvisible; 286: ww->cmvisible = addrec; 287: } 288: } 289: 290: /* If the rectangle enters the border of w, split it up */ 291: 292: if (w->bwidth) { 293: if (r->left < w->vs.left) { 294: if (r->right <= w->vs.left) { 295: r->type = border_rec; 296: r->next = new; 297: new = r; 298: continue; 299: } 300: NEWRECT(addrec, r->left, w->vs.left, 301: r->top, r->bottom, border_rec); 302: addrec->next = new; 303: new = addrec; 304: r->left = w->vs.left; 305: } 306: if (r->right > w->vs.right) { 307: if (r->left >= w->vs.right) { 308: r->type = border_rec; 309: r->next = new; 310: new = r; 311: continue; 312: } 313: NEWRECT(addrec, w->vs.right, r->right, 314: r->top, r->bottom, border_rec); 315: addrec->next = new; 316: new = addrec; 317: r->right = w->vs.right; 318: } 319: if (r->top < w->vs.top) { 320: if (r->bottom <= w->vs.top) { 321: r->type = border_rec; 322: r->next = new; 323: new = r; 324: continue; 325: } 326: NEWRECT(addrec, r->left, r->right, 327: r->top, w->vs.top, border_rec); 328: addrec->next = new; 329: new = addrec; 330: r->top = w->vs.top; 331: } 332: if (r->bottom > w->vs.bottom) { 333: if (r->top >= w->vs.bottom) { 334: r->type = border_rec; 335: r->next = new; 336: new = r; 337: continue; 338: } 339: NEWRECT(addrec, r->left, r->right, 340: w->vs.bottom, r->bottom, border_rec); 341: addrec->next = new; 342: new = addrec; 343: r->bottom = w->vs.bottom; 344: } 345: } 346: 347: /* give it to ourselves too */ 348: if (w->level >= remw->level) { 349: RASTRECT(addrec, *(RASTER *) r, new_rec); 350: addrec->next = w->cmvisible; 351: w->cmvisible = addrec; 352: } 353: 354: if (cleanup >= 0) 355: r->type = new_rec; 356: else 357: r->type = contents_rec; 358: r->next = new; 359: new = r; 360: } 361: } 362: 363: if (new) { 364: for (ww = w; ww->level >= remw->level; ww = ww->parent) { 365: /* find any new stuff and merge it */ 366: addrec = NULL; 367: while ((r = ww->cmvisible) && r->type == new_rec) { 368: r->type = contents_rec; 369: ww->cmvisible = r->next; 370: r->next = addrec; 371: addrec = r; 372: } 373: if (addrec) 374: Merge_rectangles (addrec, &ww->cmvisible); 375: } 376: Merge_rectangles (new, &w->visible); 377: Windex (w); 378: if (cleanup > 0) 379: Draw_window (w, 0, 0); 380: else if (cleanup == 0) 381: w->unobscured = OB_TMP; 382: } 383: } 384: }