1: #include <X/mit-copyright.h>
   2: 
   3: /* Copyright    Massachusetts Institute of Technology    1985	*/
   4: 
   5: /* Routines for maintaining windows:
   6:  *
   7:  *	Create_root_window, Create_window, Destroy_window,
   8:  *	Map_root_window, Map_window, Map_subwindows,
   9:  *	Unmap_window, Unmap_subwindows, Remove_subwindows,
  10:  *	Move_window, Change_window, Change_background, Change_border,
  11:  *	Raise_window, Lower_window, Circulate_window_up, Circulate_window_down,
  12:  *	Draw_window, Windex, Free_window_storage
  13:  */
  14: #ifndef lint
  15: static char *rcsid_window_c = "$Header: window.c,v 10.8 86/02/01 15:17:33 tony Rel $";
  16: #endif
  17: 
  18: #include "Xint.h"
  19: 
  20: extern u_char Xstatus;
  21: extern RESOURCE **Resources;
  22: extern PIXMAP *roottile;
  23: extern RECTANGLE *free_rectangles;
  24: extern int mouse_grabber;
  25: extern WINDOW *button_window, *mouse_grab_window, *key_window;
  26: extern RASTER mbox;
  27: 
  28: char *Xalloc();
  29: long Add_resource();
  30: RECTANGLE *Alloc_rectangle();
  31: WINDOW *Unmap_window();
  32: 
  33: #define MBOX(w) if (w->vs.top < mbox.bottom && mbox.top < w->vs.bottom &&\
  34:             w->vs.left < mbox.right && mbox.left < w->vs.right)\
  35:             mbox.bottom = 0
  36: 
  37: #define alloc_at_once 25
  38: 
  39: WINDOW *rootwindow = NULL;  /* The background of the whole tree */
  40: static WINDOW *mapped_list = NULL; /* List of windows mapped to the screeen */
  41: WINDOW *free_windows = NULL;
  42: 
  43: /* Create_root_window creates and maps the root window on the screen.
  44:  * The root window differs from other windows in that it has no parent.
  45:  */
  46: 
  47: Create_root_window (height, width, tile)
  48:     int height, width;
  49:     PIXMAP *tile;
  50: {
  51:     int root;
  52: 
  53:     /* make sure no other windows are in the root's malloc'd area */
  54:     free_windows = (WINDOW *) Xalloc (sizeof (WINDOW));
  55:     free_windows->next = NULL;
  56:     root = Create_window (height, width, 0, 0, 0, (PIXMAP *) NULL,
  57:                   tile, IsOpaque, (WINDOW *) NULL, 0);
  58:     rootwindow = (WINDOW *) Resources[RESIDX(root)]->value;
  59:     rootwindow->clipmode = ClipModeDrawThru;
  60:     Map_root_window ();
  61: }
  62: 
  63: /* Create_window creates a new window with common parameters filled in.
  64:  * The window returned is unmapped.
  65:  */
  66: 
  67: int Create_window (height, width, x, y, bwidth, border, tile, kind,
  68:             parent, client)
  69:     int height, width, x, y, bwidth, kind, client;
  70:     register WINDOW *parent;
  71:     PIXMAP *border, *tile;
  72: {
  73:     register WINDOW *w;
  74:     int i;
  75: 
  76:     if (height <= 0 || width <= 0 || bwidth < 0) {
  77:         Xstatus = BadValue;
  78:         return (NULL);
  79:     } else if (kind != IsTransparent) {
  80:         if (parent && parent->kind == IsTransparent) {
  81:         Xstatus = BadMatch;
  82:         return (NULL);
  83:         } else if (bwidth > 0 && border == NULL) {
  84:         Xstatus = BadPixmap;
  85:         return (NULL);
  86:         } else if ((border && FALSE(border->tile)) ||
  87:                (tile && FALSE(tile->tile))) {
  88:         Xstatus = BadTile;
  89:         return (NULL);
  90:         } else if (tile == NULL) {
  91:         tile = parent->tile;
  92:         }
  93:     }
  94: 
  95:     if ((w = free_windows) == NULL) {
  96:         /* We allocate in chunks to minimize fragmentation. */
  97:         w = (WINDOW *) Xalloc (alloc_at_once * sizeof (WINDOW));
  98:         free_windows = w;
  99:         w->internal = 0;
 100:         i = alloc_at_once;
 101:         while (--i > 0) {
 102:         w->next = w + 1;
 103:         w++;
 104:         w->internal = 1;
 105:         }
 106:         w->next = NULL;
 107:         w = free_windows;
 108:     }
 109:     free_windows = w->next;
 110: 
 111:     w->full.left = x + bwidth;
 112:     w->full.top = y + bwidth;
 113:     w->full.right = w->full.left + width;
 114:     w->full.bottom = w->full.top + height;
 115:     w->bwidth = bwidth;
 116:     if (w->border = border)
 117:         border->refcnt++;
 118:     if (w->tile = tile)
 119:         tile->refcnt++;
 120:     if (kind == IsTransparent)
 121:         w->tilemode = TileModeRelative;
 122:     else
 123:         w->tilemode = TileModeAbsolute;
 124:     w->clipmode = ClipModeClipped;
 125: 
 126:     w->cursor = NULL;
 127:     w->mask = NoEvent;
 128:     w->client = 0;
 129: 
 130:     if (parent)
 131:         w->level = parent->level + 1;
 132:     else
 133:         w->level = 0;
 134:     w->kind = kind;
 135:     w->first_child = w->last_child = NULL;
 136:     w->parent = parent;
 137:     w->visible = NULL;
 138:     w->cmvisible = NULL;
 139:     w->unobscured = OB_NOT;
 140:     w->mapped = w->should_be_mapped = 0;
 141:     w->bgrabs = 0;
 142:     w->name = NULL;
 143:     w->width0 = w->height0 = 0;
 144:     w->widthinc = w->heightinc = 1;
 145:     w->icon = NULL;
 146: 
 147:     if (parent) {
 148:         /* make it the top-most child */
 149:         if (parent->last_child) {
 150:         parent->last_child->next_sib = w;
 151:         w->prev_sib = parent->last_child;
 152:         w->next_sib = NULL;
 153:         parent->last_child = w;
 154:         } else {
 155:         parent->first_child = parent->last_child = w;
 156:         w->next_sib = w->prev_sib = NULL;
 157:         }
 158:     } else {
 159:         w->next_sib = w->prev_sib = NULL;
 160:     }
 161: 
 162:     return (w->rid = Add_resource (RT_WINDOW, client, (caddr_t) w));
 163: }
 164: 
 165: /* Eliminate a window. */
 166: 
 167: Destroy_window (w)
 168:     register WINDOW *w;
 169: {
 170:     register WINDOW *icon;
 171: 
 172:     /* Check icon status */
 173: 
 174:     if (icon = w->icon) {
 175:         if (w->kind == IsIcon && TRUE(w->mapped) && FALSE(icon->mapped))
 176:         Map_window (icon);
 177:         else if (icon->kind == IsIcon && TRUE(icon->mapped)) {
 178:         Unmap_window (icon, 1);
 179:         Stash_simple (icon, (long) UnmapWindow, 0);
 180:         }
 181:         icon->kind = IsOpaque;
 182:         icon->icon = NULL;
 183:     }
 184: 
 185:     /* Unmap it */
 186: 
 187:     if TRUE(w->mapped)
 188:         Unmap_window (w, 1);
 189: 
 190:     /* Destroy all the children */
 191: 
 192:     if (w->first_child)
 193:         Zap_subwindows (w, 1);
 194: 
 195:     /* Remove from parent's list */
 196: 
 197:     if (w->next_sib)
 198:         w->next_sib->prev_sib = w->prev_sib;
 199:     else
 200:         w->parent->last_child = w->prev_sib;
 201: 
 202:     if (w->prev_sib)
 203:         w->prev_sib->next_sib = w->next_sib;
 204:     else
 205:         w->parent->first_child = w->next_sib;
 206: 
 207:     /* Get it out of any binds */
 208: 
 209:     if (w == button_window || (mouse_grabber && w == mouse_grab_window))
 210:         Stash_ungrabs ();
 211:     if (w->bgrabs)
 212:         Unbutton_window (w);
 213:     if (w == key_window) {
 214:         key_window = NULL;
 215:         Focus_keyboard (w->parent);
 216:     }
 217: 
 218:     /* Free the resources */
 219: 
 220:     if (w->cursor)
 221:         Unregister_cursor (w);
 222: 
 223:     if (w->name)
 224:         free (w->name);
 225: 
 226:     if (w->border && --w->border->refcnt == 0)
 227:         FreePixmap (w->border);
 228:     if (w->tile && --w->tile->refcnt == 0)
 229:         FreePixmap (w->tile);
 230: 
 231:     w->next = free_windows;
 232:     free_windows = w;
 233: }
 234: 
 235: /* Maps the root window */
 236: 
 237: Map_root_window ()
 238: {
 239:     register WINDOW *w = rootwindow;
 240:     register RECTANGLE *r;
 241: 
 242:     w->vs = w->full;
 243:     w->ovs = w->full;
 244:     w->clip.left = w->vs.left;
 245:     w->clip.top = w->vs.top;
 246:     w->clip.height = w->vs.bottom - w->vs.top;
 247:     w->clip.width = w->vs.right - w->vs.left;
 248:     RASTRECT(r, w->full, contents_rec);
 249:     r->next = NULL;
 250:     w->visible = r;
 251:     RASTRECT(r, w->full, contents_rec);
 252:     r->next = NULL;
 253:     w->cmvisible = r;
 254: 
 255:     w->next = NULL;
 256:     mapped_list = w;
 257:     w->prev = NULL;
 258: 
 259:     w->mapped = w->should_be_mapped = 1;
 260:     w->unobscured = OB_YES;
 261: 
 262:     Do_background (w, 1);
 263: }
 264: 
 265: /* Map_window raises and displays the specified window on the screen.  It also
 266:  * goes through the window's subwindows and maps all those for whom the
 267:  * should_be_mapped flag is set.
 268:  */
 269: 
 270: Map_window (w)
 271:     register WINDOW *w;
 272: {
 273:     if FALSE(w->parent->mapped) {
 274:         w->should_be_mapped = 1;
 275:         return;
 276:     }
 277: 
 278:     Map_window_main (w, 1, 0);
 279:     MBOX(w);
 280: 
 281:     if (w->first_child)
 282:         Map_subwindows (w, 0, 0);
 283: 
 284:     Draw_window (w, 0, 1);
 285: }
 286: 
 287: /* Does the common work of mapping a window.
 288:  * If top is set, the window is top-most, else it is bottom-most.
 289:  * If dontMove is set, this window is already placed in the parent's list.
 290:  */
 291: 
 292: Map_window_main (w, top, dontMove)
 293:     register WINDOW *w;
 294:     int top, dontMove;
 295: {
 296:     register WINDOW *w1 = w->parent;
 297: 
 298:     w->mapped = w->should_be_mapped = 1;
 299: 
 300:     /* get absolute coordinates */
 301:     w->full.left += w1->full.left;
 302:     w->full.top += w1->full.top;
 303:     w->full.right += w1->full.left;
 304:     w->full.bottom += w1->full.top;
 305: 
 306:     /* clip to parent */
 307:     w->vs = w->full;
 308:     Clip_raster (&w->vs, &w1->vs);
 309: 
 310:     w->ovs.left = w->full.left - w->bwidth;
 311:     w->ovs.right = w->full.right + w->bwidth;
 312:     w->ovs.top  = w->full.top - w->bwidth;
 313:     w->ovs.bottom = w->full.bottom + w->bwidth;
 314:     Clip_raster (&w->ovs, &w1->vs);
 315:     if (w->ovs.right <= w->ovs.left)
 316:         w->ovs.right = w->ovs.bottom = -1;
 317: 
 318:     w->clip.left = w->vs.left;
 319:     w->clip.top = w->vs.top;
 320:     w->clip.height = w->vs.bottom - w->vs.top;
 321:     w->clip.width = w->vs.right - w->vs.left;
 322: 
 323:     if TRUE(top) {
 324:         /* Search the mapped_list backwards starting at w's parent until we
 325: 	     * either find a window with a lower level or we find the beginning
 326: 	     * of the list.  Insert after it.
 327: 	     */
 328: 
 329:         do {
 330:         w1 = w1->prev;
 331:         } while (w1 && w1->level >= w->level);
 332: 
 333:         if (w1) {
 334:         w->prev = w1;
 335:         w->next = w1->next;
 336:         w->next->prev = w;
 337:         w1->next = w;
 338:         } else {
 339:         w->next = mapped_list;
 340:         mapped_list->prev = w;
 341:         mapped_list = w;
 342:         w->prev = NULL;
 343:         }
 344: 
 345:         /* Move w to be the last child of its parent */
 346:         if (w->next_sib && FALSE(dontMove))
 347:         Make_top_child (w);
 348: 
 349:         /* Get its rectangles and obscure other windows */
 350:         if (w->kind != IsTransparent)
 351:         Obscure_top (w);
 352:     } else {
 353:         /* Place w just before its parent in the mapped_list */
 354: 
 355:         w->next = w1;
 356:         if (w->prev = w1->prev)
 357:         w->prev->next = w;
 358:         else
 359:         mapped_list = w;
 360:         w1->prev = w;
 361: 
 362:         /* Move w to be the first child of its parent */
 363:         if (w->prev_sib && FALSE(dontMove))
 364:         Make_bottom_child (w);
 365: 
 366:         /* Get its rectangles and obscure other windows */
 367:         if (w->kind != IsTransparent)
 368:         Obscure_bottom (w);
 369:     }
 370: }
 371: 
 372: /* Maps the subwindows of a window.
 373:  * If dontRedraw is set, the subwindows have already been displayed.
 374:  * If all is set, all subwindows are mapped, not just the should_be_mapped.
 375:  */
 376: 
 377: Map_subwindows (w, dontRedraw, all)
 378:     WINDOW *w;
 379:     int dontRedraw, all;
 380: {
 381:     register WINDOW *w1;
 382: 
 383:     if TRUE(w->mapped) {
 384:         /* mapping from top to bottom is the most efficient */
 385:         for (w1 = w->last_child; w1; w1 = w1->prev_sib) {
 386:         if (FALSE(w1->mapped) &&
 387:             (TRUE(all) || TRUE(w1->should_be_mapped))) {
 388:             Map_window_main (w1, 0, 1);
 389:             if TRUE(all) {
 390:             MBOX(w1);
 391:             }
 392:             if (w1->first_child)
 393:             Map_subwindows (w1, dontRedraw, 0);
 394:             if FALSE(dontRedraw)
 395:             Draw_window (w1, 0, 1);
 396:         }
 397:         }
 398:     } else if TRUE(all) {
 399:         for (w1 = w->first_child; w1; w1 = w1->next_sib)
 400:         w1->should_be_mapped = 1;
 401:     }
 402: }
 403: 
 404: /* Unmap_window removes the window from the list of mapped windows and updates
 405:  * all the windows that it may have been obscuring.  All the subwindows are
 406:  * unmapped but their should_be_mapped flags are unchanged.  If cleanup = 1,
 407:  * then update windows you uncover.  If cleanup < 0, then update the
 408:  * windows you uncover without changing the bits on the screen.
 409:  * Returns the next mapped window in the mapped_list chain.
 410:  */
 411: 
 412: WINDOW *Unmap_window (w, cleanup)
 413:     register WINDOW *w;
 414:     int cleanup;
 415: {
 416:     WINDOW *w1;
 417: 
 418:     if (w->first_child) {
 419:         Zap_subwindows (w, 0);
 420:         Restore_rectangles (w);
 421:     }
 422:     MBOX(w);
 423:     w1 = w->next;
 424:     Unmap_window_main (w, 0, cleanup);
 425:     return (w1);
 426: }
 427: 
 428: /* Restore the visible rectangles as if there were no subwindows, i.e.,
 429:  * make it a copy of cmvisible plus existing borders.
 430:  */
 431: 
 432: Restore_rectangles (w)
 433:     WINDOW *w;
 434: {
 435:     register RECTANGLE *vr, *cr, **prev;
 436: 
 437:     cr = w->cmvisible;
 438:     prev = &w->visible;
 439:     /* reuse what we can */
 440:     while (vr = *prev) {
 441:         if (vr->type != border_rec) {
 442:         if (cr == NULL) {
 443:             *prev = vr->next;
 444:             FREERECT(vr);
 445:             continue;
 446:         }
 447:         *(RASTER *) vr = *(RASTER *) cr;
 448:         vr->type = contents_rec;
 449:         cr = cr->next;
 450:         }
 451:         prev = &vr->next;
 452:     }
 453:     /* allocate the rest */
 454:     for (; cr; cr = cr->next) {
 455:         RASTRECT(vr, *(RASTER *) cr, contents_rec);
 456:         *prev = vr;
 457:         prev = &vr->next;
 458:     }
 459:     *prev = NULL;
 460: }
 461: 
 462: /* Do the common work of unmapping a window.
 463:  * Set should_be_mapped to the indicated state.  If cleanup = 1, then update
 464:  * windows you uncover.  If cleanup < 0, then update the windows you uncover
 465:  * without changing the bits on the screen.
 466:  */
 467: 
 468: Unmap_window_main (w, should_be_mapped, cleanup)
 469:     register WINDOW *w;
 470:     int should_be_mapped, cleanup;
 471: {
 472:     register WINDOW *w1;
 473: 
 474:     /* Remove it from the list */
 475: 
 476:     w1 = w->next;
 477:     if (w1->prev = w->prev)
 478:         w->prev->next = w1;
 479:     else
 480:         mapped_list = w1;
 481: 
 482:     /* Get rid of the rectangles */
 483: 
 484:     if (w->visible) {
 485:         if (w->cmvisible) {
 486:         Free_rectangles (w->cmvisible);
 487:         w->cmvisible = NULL;
 488:         }
 489:         Remove_rectangles (w, w1, cleanup);
 490:     }
 491: 
 492:     w->next = w->prev = NULL;
 493: 
 494:     /* make coordinates relative */
 495:     w1 = w->parent;
 496:     w->full.left -= w1->full.left;
 497:     w->full.top -= w1->full.top;
 498:     w->full.right -= w1->full.left;
 499:     w->full.bottom -= w1->full.top;
 500: 
 501:     w->should_be_mapped = should_be_mapped;
 502:     w->mapped = 0;
 503:     w->unobscured = OB_NOT;
 504: }
 505: 
 506: /* Unmap all the subwindows of a window. */
 507: 
 508: Unmap_subwindows (w)
 509:     WINDOW *w;
 510: {
 511:     register WINDOW *w1;
 512: 
 513:     for (w1 = w->first_child; w1; w1 = w1->next_sib) {
 514:         if TRUE(w1->mapped)
 515:         Stash_simple (w1, (long) UnmapWindow, 0);
 516:     }
 517:     Remove_subwindows (w, 0, 1);
 518: }
 519: 
 520: /* Unmap all subwindows, giving space back to parent.  Destroy the subwindows
 521:  * if destroy flag is set.  Display the window if cleanup is set.
 522:  */
 523: 
 524: Remove_subwindows (w, destroy, cleanup)
 525:     WINDOW *w;
 526:     int destroy;
 527: {
 528:     register WINDOW *w1;
 529:     register RECTANGLE *rec, *rlist, **prev;
 530:     int vn, cn;
 531: 
 532:     /* count visible rectangles */
 533:     vn = 0;
 534:     for (prev = &w->visible; rec = *prev; prev = &rec->next) {
 535:         if (rec->type != border_rec)
 536:         vn++;
 537:     }
 538:     /* collect new visible rectangles and unmap subwindows */
 539:     cn = 0;
 540:     rlist = NULL;
 541:     for (w1 = w->first_child; w1; w1 = w1->next_sib) {
 542:         if TRUE(w1->mapped) {
 543:         if (rec = w1->cmvisible) {
 544:             while (1) {
 545:             rec->type = new_rec;
 546:             cn++;
 547:             if (rec->next == NULL)
 548:                 break;
 549:             rec = rec->next;
 550:             }
 551:             rec->next = rlist;
 552:             rlist = w1->cmvisible;
 553:             w1->cmvisible = NULL;
 554:         }
 555:         while (rec = w1->visible) {
 556:             w1->visible = rec->next;
 557:             if (rec->type == border_rec) {
 558:             rec->type = new_rec;
 559:             rec->next = rlist;
 560:             rlist = rec;
 561:             cn++;
 562:             } else {
 563:             FREERECT(rec);
 564:             }
 565:         }
 566:         if TRUE(cleanup) {
 567:             MBOX(w1);
 568:         }
 569:         if (w1->first_child)
 570:             Zap_subwindows (w1, destroy);
 571:         Unmap_window_main (w1, cleanup ^ 1, 0);
 572:         } else if (TRUE(destroy) && w1->first_child)
 573:         Zap_subwindows (w1, 1);
 574:         else
 575:         w1->should_be_mapped = 0;
 576:     }
 577:     if TRUE(destroy) {
 578:         while (w1 = w->first_child)
 579:         Free_resource (Resources[RESIDX(w1->rid)]);
 580:     }
 581:     if (cn == 0)
 582:         return;
 583:     else if (vn == 0 && cn > 2) {
 584:         Free_rectangles (rlist);
 585:         for (rlist = w->cmvisible; rlist; rlist = rlist->next) {
 586:         RASTRECT(rec, *(RASTER *) rlist, new_rec);
 587:         *prev = rec;
 588:         prev = &rec->next;
 589:         }
 590:         *prev = NULL;
 591:     } else if (w->cmvisible->next == NULL && (cn >> 3) > vn) {
 592:         Free_rectangles (rlist);
 593:         RASTRECT(rec, *(RASTER *) w->cmvisible, new_rec);
 594:         *prev = rec;
 595:         rec->next = NULL;
 596:         for (rec = w->visible; ; rec = rec->next) {
 597:         if (rec->type != border_rec)
 598:             Calc_overlaps ((RASTER *) rec, prev);
 599:         if (prev == &rec->next)
 600:             break;
 601:         }
 602:     } else
 603:         Merge_rectangles (rlist, prev);
 604:     if TRUE(cleanup) {
 605:         Do_background (w, 0);
 606:         Stash_changes (w, 0);
 607:     }
 608: }
 609: 
 610: /* Unmap all subwindows, discarding their rectangles.  Destroy the subwindows
 611:  * if destroy flag is set.
 612:  */
 613: 
 614: Zap_subwindows (w, destroy)
 615:     register WINDOW *w;
 616:     int destroy;
 617: {
 618:     register WINDOW *w1;
 619: 
 620:     for (w1 = w->first_child; w1; w1 = w1->next_sib) {
 621:         if TRUE(w1->mapped) {
 622:         if (w1->visible) {
 623:             Free_rectangles (w1->visible);
 624:             w1->visible = NULL;
 625:         }
 626:         if (w1->cmvisible) {
 627:             Free_rectangles (w1->cmvisible);
 628:             w1->cmvisible = NULL;
 629:         }
 630:         if (w1->first_child)
 631:             Zap_subwindows (w1, destroy);
 632:         Unmap_window_main (w1, 1, 0);
 633:         }
 634:     }
 635:     if TRUE(destroy) {
 636:         while (w1 = w->first_child)
 637:         Free_resource (Resources[RESIDX(w1->rid)]);
 638:     }
 639: }
 640: 
 641: /* Change the x-y coordinates of a window */
 642: 
 643: Move_window (w, new_x, new_y)
 644:     register WINDOW *w;
 645:     int new_x, new_y;
 646: {
 647:     short deltax, deltay;
 648:     register WINDOW *w1 = NULL;
 649:     register RECTANGLE *r;
 650:     register WINDOW *head;
 651:     register RECTANGLE *cr;
 652:     RECTANGLE *vlist;
 653:     WINDOW *tail;
 654:     int unobscured = OB_NOT;
 655: 
 656:     deltax = new_x - (w->full.left - w->bwidth);
 657:     deltay = new_y - (w->full.top - w->bwidth);
 658:     if TRUE(w->mapped) {
 659:         MBOX(w);
 660:         deltax += w->parent->full.left;
 661:         deltay += w->parent->full.top;
 662:         /* Check if all visible */
 663:         if (FALSE(w->tilemode) &&
 664:         (r = w->cmvisible) && r->next == NULL &&
 665:         r->left == w->full.left && r->top == w->full.top &&
 666:         r->right == w->full.right && r->bottom == w->full.bottom)
 667:         unobscured = OB_YES;
 668:         if (w->first_child) {
 669:         if TRUE(unobscured) {
 670:             /* Find earliest mapped subwindow */
 671:             w1 = w;
 672:             do {
 673:             head = w1;
 674:             for (w1 = head->last_child;
 675:                  w1 && FALSE(w1->mapped);
 676:                  w1 = w1->prev_sib) ;
 677:             } while (w1);
 678:             if (head != w) {
 679:             tail = w->prev;
 680:             /* Remove all subwindows from list */
 681:             if (w->prev = head->prev)
 682:                 head->prev->next = w;
 683:             else
 684:                 mapped_list = w;
 685:             /* Extract visible insides */
 686:             vlist = NULL;
 687:             cr = w->visible;
 688:             w->visible = NULL;
 689:             while (r = cr) {
 690:                 cr = r->next;
 691:                 if (r->type == border_rec) {
 692:                 r->next = w->visible;
 693:                 w->visible = r;
 694:                 } else {
 695:                 r->left += deltax;
 696:                 r->right += deltax;
 697:                 r->top += deltay;
 698:                 r->bottom += deltay;
 699:                 r->next = vlist;
 700:                 vlist = r;
 701:                 }
 702:             }
 703:             Restore_rectangles (w);
 704:             }
 705:         } else {
 706:             Zap_subwindows (w, 0);
 707:             Restore_rectangles (w);
 708:         }
 709:         }
 710:         w1 = w->next;
 711:         Unmap_window_main (w, 1, 0);
 712:     }
 713: 
 714:     w->full.left += deltax;
 715:     w->full.right += deltax;
 716:     w->full.top += deltay;
 717:     w->full.bottom += deltay;
 718: 
 719:     if (FALSE(w->should_be_mapped) || FALSE(w->parent->mapped))
 720:         return;
 721:     Map_window_main (w, 1, 0);
 722:     MBOX(w);
 723:     if (w->first_child) {
 724:         if FALSE(unobscured)
 725:         Map_subwindows (w, 0, 0);
 726:         else if (head != w) {
 727:         /* Reinsert subwindows */
 728:         if (head->prev = w->prev)
 729:             w->prev->next = head;
 730:         else
 731:             mapped_list = head;
 732:         tail->next = w;
 733:         w->prev = tail;
 734:         /* Check if still all visible */
 735:         if ((r = w->cmvisible) && r->next == NULL &&
 736:             r->left == w->full.left && r->top == w->full.top &&
 737:             r->right == w->full.right && r->bottom == w->full.bottom) {
 738:             unobscured = OB_TMP;
 739:             /* Move all subwindows */
 740:             do {
 741:             tail = head->next;
 742:             head->full.left += deltax;
 743:             head->full.right += deltax;
 744:             head->full.top += deltay;
 745:             head->full.bottom += deltay;
 746:             head->vs.left += deltax;
 747:             head->vs.right += deltax;
 748:             head->vs.top += deltay;
 749:             head->vs.bottom += deltay;
 750:             head->ovs.left += deltax;
 751:             head->ovs.right += deltax;
 752:             head->ovs.top += deltay;
 753:             head->ovs.bottom += deltay;
 754:             head->clip.left += deltax;
 755:             head->clip.top += deltay;
 756:             for (r = head->visible; r; r = r->next) {
 757:                 r->left += deltax;
 758:                 r->right += deltax;
 759:                 r->top += deltay;
 760:                 r->bottom += deltay;
 761:             }
 762:             for (r = head->cmvisible; r; r = r->next) {
 763:                 r->left += deltax;
 764:                 r->right += deltax;
 765:                 r->top += deltay;
 766:                 r->bottom += deltay;
 767:             }
 768:             } while ((head = tail) != w);
 769:             cr = w->visible;
 770:             while (r = cr) {
 771:             cr = r->next;
 772:             if (r->type == border_rec) {
 773:                 r->next = vlist;
 774:                 vlist = r;
 775:             } else {
 776:                 FREERECT(r);
 777:             }
 778:             }
 779:             w->visible = vlist;
 780:         } else {
 781:             /* Unmap all subwindows and move children */
 782:             do {
 783:             tail = head->next;
 784:             if (head->visible) {
 785:                 Free_rectangles (head->visible);
 786:                 head->visible = NULL;
 787:             }
 788:             if (head->cmvisible) {
 789:                 Free_rectangles (head->cmvisible);
 790:                 head->cmvisible = NULL;
 791:             }
 792:             Unmap_window_main (head, 1, 0);
 793:             if (head->parent == w) {
 794:                 head->full.left += deltax;
 795:                 head->full.right += deltax;
 796:                 head->full.top += deltay;
 797:                 head->full.bottom += deltay;
 798:             }
 799:             } while ((head = tail) != w);
 800:             if (vlist)
 801:             Free_rectangles (vlist);
 802:             /* Remap all subwindows */
 803:             Map_subwindows (w, 1, 0);
 804:         }
 805:         }
 806:     }
 807:     if TRUE(unobscured)
 808:         Do_refill (w, deltax, deltay);
 809:     else
 810:         Draw_window (w, 0, 1);
 811: 
 812:     for (; w1; w1 = w1->next) {
 813:         if (w1->unobscured == OB_TMP) {
 814:         w1->unobscured = OB_NOT;
 815:         Draw_window (w1, 0, 0);
 816:         }
 817:     }
 818: }
 819: 
 820: /* Change the size and position of a window. */
 821: 
 822: Change_window (w, x, y, height, width)
 823:     register WINDOW *w;
 824:     int x, y, height, width;
 825: {
 826:     register WINDOW *w1 = NULL;
 827: 
 828:     if (height <= 0 || width <= 0) {
 829:         Xstatus = BadValue;
 830:         return;
 831:     }
 832: 
 833:     if TRUE(w->mapped) {
 834:         w1 = Unmap_window (w, 0);
 835:         w->should_be_mapped = 1;
 836:     }
 837: 
 838:     x -= w->full.left - w->bwidth;
 839:     y -= w->full.top - w->bwidth;
 840: 
 841:     w->full.left += x;
 842:     w->full.top += y;
 843:     w->full.right = w->full.left + width;
 844:     w->full.bottom = w->full.top + height;
 845: 
 846:     if (FALSE(w->should_be_mapped) || FALSE(w->parent->mapped))
 847:         return;
 848:     Map_window (w);
 849:     for (; w1; w1 = w1->next) {
 850:         if (w1->unobscured == OB_TMP) {
 851:         w1->unobscured = OB_NOT;
 852:         Draw_window (w1, 0, 0);
 853:         }
 854:     }
 855: }
 856: 
 857: /* Change the background tile of a window */
 858: 
 859: Change_background (w, tile)
 860:     register WINDOW *w;
 861:     register PIXMAP *tile;
 862: {
 863:     if (w->kind == IsTransparent) {
 864:         Xstatus = BadMatch;
 865:         return;
 866:     } else if (tile == NULL) {
 867:         if (w->parent)
 868:         tile = w->parent->tile;
 869:         else
 870:         tile = roottile;
 871:     } else if FALSE(tile->tile) {
 872:         Xstatus = BadTile;
 873:         return;
 874:     }
 875:     if (tile != w->tile) {
 876:         tile->refcnt++;
 877:         if (--w->tile->refcnt == 0)
 878:         FreePixmap (w->tile);
 879:         w->tile = tile;
 880:     }
 881: }
 882: 
 883: /* Change the border tile of a window. */
 884: 
 885: Change_border (w, tile)
 886:     register WINDOW *w;
 887:     register PIXMAP *tile;
 888: {
 889:     if (w->bwidth == 0) {
 890:         Xstatus = BadMatch;
 891:         return;
 892:     } else if FALSE(tile->tile) {
 893:         Xstatus = BadTile;
 894:         return;
 895:     }
 896:     if (tile != w->border) {
 897:         tile->refcnt++;
 898:         if (--w->border->refcnt == 0)
 899:         FreePixmap (w->border);
 900:         w->border = tile;
 901:         Do_border (w);
 902:     }
 903: }
 904: 
 905: /* Move a window to the top of (depthwise) the screen. */
 906: 
 907: Raise_window (w)
 908:     register WINDOW *w;
 909: {
 910:     register WINDOW *ww, *nw;
 911:     int changed;
 912: 
 913:     /* Check if we're already on top. */
 914: 
 915:     if (w->next_sib == NULL) return;
 916: 
 917:     /* If w is unmapped, simply put it on top. */
 918: 
 919:     if FALSE(w->mapped) {
 920:         Make_top_child (w);
 921:         return;
 922:     }
 923: 
 924:     MBOX(w);
 925: 
 926:     /* If w is transparent, simply put it on top. */
 927: 
 928:     if (w->kind == IsTransparent) {
 929:         Make_top_child (w);
 930:         return;
 931:     }
 932: 
 933:     changed = 0;
 934: 
 935:     /* Lower any of w's siblings that are above it. */
 936: 
 937:     while (ww = w->next_sib) {
 938:         /* move it over us */
 939:         if (w->next_sib = ww->next_sib)
 940:         ww->next_sib->prev_sib = w;
 941:         else
 942:         w->parent->last_child = w;
 943:         if (ww->prev_sib = w->prev_sib)
 944:         w->prev_sib->next_sib = ww;
 945:         else
 946:         w->parent->first_child = ww;
 947:         w->prev_sib = ww;
 948:         ww->next_sib = w;
 949: 
 950:         /* If ww is unmapped, we're done. */
 951:         if FALSE(ww->mapped) continue;
 952: 
 953:         /* If ww is transparent or doesn't overlap, just reposition */
 954:         if (ww->kind == IsTransparent ||
 955:         ww->ovs.left >= w->ovs.right || w->ovs.left >= ww->ovs.right ||
 956:         ww->ovs.top >= w->ovs.bottom || w->ovs.top >= ww->ovs.bottom) {
 957:         /* Find earliest mapped subwindow of ww */
 958:         do {
 959:             nw = ww;
 960:             for (ww = nw->last_child;
 961:              ww && FALSE(ww->mapped);
 962:              ww = ww->prev_sib) ;
 963:         } while (ww);
 964:         ww = w->prev_sib;
 965:         /* Reposition in mapped_list just after w */
 966:         if (ww->next->prev = nw->prev)
 967:             nw->prev->next = ww->next;
 968:         else
 969:             mapped_list = ww->next;
 970:         ww->next = w->next;
 971:         w->next->prev = ww;
 972:         w->next = nw;
 973:         nw->prev = w;
 974:         continue;
 975:         }
 976: 
 977:         changed = 1;
 978: 
 979:         /* Unmap all the children of ww. */
 980:         if (ww->first_child)
 981:         Remove_subwindows (ww, 0, 0);
 982: 
 983:         /* Remove ww from its current position. */
 984:         nw = ww->next;
 985:         if (nw->prev = ww->prev)
 986:         ww->prev->next = nw;
 987:         else
 988:         mapped_list = nw;
 989: 
 990:         /* Insert ww just after w. */
 991:         ww->next = w->next;
 992:         w->next->prev = ww;
 993:         ww->prev = w;
 994:         w->next = ww;
 995: 
 996:         /* Remove the rectangles from ww as appropriate */
 997:         Remove_rectangles (ww, nw, 1);
 998: 
 999:         /* Remap the children without redrawing */
1000:         if (ww->first_child)
1001:         Map_subwindows (ww, 1, 0);
1002:     }
1003: 
1004:     if TRUE(changed)
1005:         Draw_window (w, 1, 0);
1006: }
1007: 
1008: /* Move a window to the bottom of the screen. */
1009: 
1010: Lower_window (w)
1011:     register WINDOW *w;
1012: {
1013:     register WINDOW *ww, *nw;
1014: 
1015:     /* Check if we're already on bottom. */
1016:     if ((ww = w->prev_sib) == NULL) return;
1017: 
1018:     /* If w is unmapped or all higher siblings are unmapped, simply
1019: 	 * put it on the bottom.
1020: 	 */
1021:     if (FALSE(w->mapped) || w->next == w->parent) {
1022:         Make_bottom_child (w);
1023:         return;
1024:     }
1025: 
1026:     MBOX(w);
1027: 
1028:     /* If w is transparent, simply put it on the bottom. *
1029: 	if (w->kind == IsTransparent) {
1030: 	    Make_bottom_child (w);
1031: 	    return;
1032: 	}
1033: 
1034: 	/* See if w obscures any lower opaque window. */
1035:     while (FALSE(ww->mapped) ||
1036:            ww->kind == IsTransparent ||
1037:            ww->ovs.left >= w->ovs.right || w->ovs.left >= ww->ovs.right ||
1038:            ww->ovs.top >= w->ovs.bottom || w->ovs.top >= ww->ovs.bottom) {
1039:         if ((ww = ww->prev_sib) == NULL)
1040:         break;
1041:     }
1042: 
1043:     /* Move w to be the first child of its parent. */
1044:     Make_bottom_child (w);
1045: 
1046:     if (ww == NULL) {
1047:         /* w doesn't obscure anything, find earliest mapped subwindow */
1048:         ww = w;
1049:         do {
1050:         nw = ww;
1051:         for (ww = nw->last_child; ww && FALSE(ww->mapped); ww = ww->prev_sib) ;
1052:         } while (ww);
1053:         /* Reposition in mapped_list just before parent */
1054:         if (w->next->prev = nw->prev)
1055:         nw->prev->next = w->next;
1056:         else
1057:         mapped_list = w->next;
1058:         ww = w->parent;
1059:         ww->prev->next = nw;
1060:         nw->prev = ww->prev;
1061:         w->next = ww;
1062:         ww->prev = w;
1063:         return;
1064:     }
1065: 
1066:     /* w obscures something, unmap all the children. */
1067:     if (w->first_child)
1068:         Remove_subwindows (w, 0, 0);
1069: 
1070:     /* Remove w from its current position. */
1071:     if (w->next->prev = w->prev)
1072:         w->prev->next = w->next;
1073:     else
1074:         mapped_list = w->next;
1075: 
1076:     nw = w->next;
1077: 
1078:     /* Put w just in front of its parent.  The parent cannot be
1079: 	 * right after w, because we already checked for that.
1080: 	 */
1081: 
1082:     ww = w->parent;
1083:     w->prev = ww->prev;
1084:     ww->prev->next = w;
1085:     w->next = ww;
1086:     ww->prev = w;
1087: 
1088:     /* Remove the rectangles from w as appropriate */
1089:     Remove_rectangles (w, nw, 1);
1090: 
1091:     /* Remap the children */
1092:     if (w->first_child)
1093:         Map_subwindows (w, 1, 0);
1094: }
1095: 
1096: /* Raise the lowest mapped subwindow obscured by another subwindow. */
1097: 
1098: Circulate_window_up (w)
1099:     register WINDOW *w;
1100: {
1101:     register WINDOW *ow;
1102: 
1103:     for (w = w->first_child; w; w = w->next_sib) {
1104:         if FALSE(w->should_be_mapped)
1105:         continue;
1106:         for (ow = w->next_sib; ow; ow = ow->next_sib) {
1107:         if (FALSE(ow->should_be_mapped) || ow->kind == IsTransparent ||
1108:             ow->ovs.left >= w->ovs.right ||
1109:             w->ovs.left >= ow->ovs.right ||
1110:             ow->ovs.top >= w->ovs.bottom ||
1111:             w->ovs.top >= ow->ovs.bottom)
1112:             continue;
1113:         Raise_window (w);
1114:         return;
1115:         }
1116:     }
1117: }
1118: 
1119: /* Lower the highest mapped subwindow obscuring another subwindow. */
1120: 
1121: Circulate_window_down (w)
1122:     register WINDOW *w;
1123: {
1124:     register WINDOW *ow;
1125: 
1126:     for (w = w->last_child; w; w = w->prev_sib) {
1127:         if FALSE(w->should_be_mapped)
1128:         continue;
1129:         for (ow = w->prev_sib; ow; ow = ow->prev_sib) {
1130:         if (FALSE(ow->should_be_mapped) || ow->kind == IsTransparent ||
1131:             ow->ovs.left >= w->ovs.right ||
1132:             w->ovs.left >= ow->ovs.right ||
1133:             ow->ovs.top >= w->ovs.bottom ||
1134:             w->ovs.top >= ow->ovs.bottom)
1135:             continue;
1136:         Lower_window (w);
1137:         return;
1138:         }
1139:     }
1140: }
1141: 
1142: /* Make w the last sibling of its parent, making it top-most */
1143: 
1144: Make_top_child (w)
1145:     register WINDOW *w;
1146: {
1147:     register WINDOW *w1 = w->parent;
1148: 
1149:     if (w->prev_sib)
1150:         w->prev_sib->next_sib = w->next_sib;
1151:     else
1152:         w1->first_child = w->next_sib;
1153: 
1154:     w->next_sib->prev_sib = w->prev_sib;
1155:     w1->last_child->next_sib = w;
1156:     w->prev_sib = w1->last_child;
1157:     w1->last_child = w;
1158:     w->next_sib = NULL;
1159: }
1160: 
1161: /* Make w the first sibling of its parent, making it bottom-most */
1162: 
1163: Make_bottom_child (w)
1164:     register WINDOW *w;
1165: {
1166:     register WINDOW *w1 = w->parent;
1167: 
1168:     if (w->next_sib)
1169:         w->next_sib->prev_sib = w->prev_sib;
1170:     else
1171:         w1->last_child = w->prev_sib;
1172: 
1173:     w->prev_sib->next_sib = w->next_sib;
1174:     w1->first_child->prev_sib = w;
1175:     w->next_sib = w1->first_child;
1176:     w1->first_child = w;
1177:     w->prev_sib = NULL;
1178: }
1179: 
1180: /* Draw_window draws a window of the appropriate type.  If subflag is
1181:    set, it also redisplays the windows subwindows.  If not_just_new
1182:    is set, all the rectangles are redisplayed, not just the new ones.
1183:    If not, after the new rectangles have been displayed they are
1184:    changed to old ones and the window is Windexed. */
1185: 
1186: Draw_window (w, subflag, not_just_new)
1187:     WINDOW *w;
1188:     int subflag, not_just_new;
1189: {
1190:     register WINDOW *w1;
1191: 
1192:     if (w->kind == IsTransparent) return;
1193: 
1194:     if (w->bwidth)
1195:         Do_border (w);
1196:     Do_background (w, not_just_new);
1197: 
1198:     if TRUE(subflag) {
1199:         for (w1 = w->first_child; w1; w1 = w1->next_sib) {
1200:         if TRUE(w1->mapped)
1201:             Draw_window (w1, 1, not_just_new);
1202:         }
1203:     }
1204: 
1205:     Stash_changes (w, not_just_new);
1206: }
1207: 
1208: /* Windex recomputes if the window is obscured. */
1209: 
1210: Windex (w)
1211:     WINDOW *w;
1212: {
1213:     register RECTANGLE *r1;
1214: 
1215:     for (r1 = w->visible; r1; r1 = r1->next) {
1216:         if (r1->type == border_rec)
1217:         continue;
1218:         if (r1->type == contents_rec &&
1219:         r1->left == w->vs.left && r1->top == w->vs.top &&
1220:         r1->right == w->vs.right && r1->bottom == w->vs.bottom)
1221:         w->unobscured = OB_YES;
1222:         break;
1223:     }
1224: }
1225: 
1226: /* Free all storage associated with unused windows */
1227: 
1228: Free_window_storage ()
1229: {
1230:     register WINDOW *w, **pw;
1231: 
1232:     /* drop the "internal" windows */
1233:     pw = &free_windows;
1234:     while (w = *pw) {
1235:         if TRUE(w->internal)
1236:         *pw = w->next;
1237:         else
1238:         pw = &w->next;
1239:     }
1240:     /* now free the "head" windows */
1241:     while (w = free_windows) {
1242:         free_windows = w->next;
1243:         free ((caddr_t) w);
1244:     }
1245:     FREERECT(rootwindow->visible);
1246:     FREERECT(rootwindow->cmvisible);
1247: }

Defined functions

Change_background defined in line 859; used 3 times
Change_border defined in line 885; used 1 times
Change_window defined in line 822; used 2 times
Circulate_window_down defined in line 1121; used 1 times
Circulate_window_up defined in line 1098; used 1 times
Create_root_window defined in line 47; used 1 times
Create_window defined in line 67; used 3 times
Destroy_window defined in line 167; used 1 times
Draw_window defined in line 1186; used 9 times
Free_window_storage defined in line 1228; used 1 times
Lower_window defined in line 1010; used 2 times
Make_bottom_child defined in line 1163; used 3 times
Make_top_child defined in line 1144; used 3 times
Map_root_window defined in line 237; used 2 times
Map_subwindows defined in line 377; used 7 times
Map_window defined in line 270; used 3 times
Map_window_main defined in line 292; used 3 times
Move_window defined in line 643; used 1 times
Raise_window defined in line 907; used 2 times
Remove_subwindows defined in line 524; used 4 times
Restore_rectangles defined in line 432; used 3 times
Unmap_subwindows defined in line 508; used 1 times
Unmap_window defined in line 412; used 7 times
Unmap_window_main defined in line 468; used 5 times
Windex defined in line 1210; used 5 times
Zap_subwindows defined in line 614; used 6 times

Defined variables

free_windows defined in line 41; used 11 times
mapped_list defined in line 40; used 12 times
rcsid_window_c defined in line 15; never used
rootwindow defined in line 39; used 38 times

Defined macros

MBOX defined in line 33; used 8 times
alloc_at_once defined in line 37; used 2 times
Last modified: 1986-02-01
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2710
Valid CSS Valid XHTML 1.0 Strict