-- Copyright (C) 1982, 1984  by Xerox Corporation. All rights reserved. 
-- File: WindowOps.mesa - last edit by
-- Daniels,	 7-Jun-84 14:36:12
-- Bruce,	20-Dec-82 12:09:58

DIRECTORY
  BitBlt: TYPE USING [BBptr, GrayParm, SrcDesc],
  Inline: TYPE USING [LongMult],
  SpecialDisplay: TYPE USING [defaultContext, Special],
  Window: TYPE USING [Box, BoxHandle, Error, ErrorCode, Place];

WindowOps: DEFINITIONS IMPORTS Inline, SpecialDisplay, Window =
  BEGIN

  Handle: TYPE = LONG POINTER TO Object;
  Object: TYPE = RECORD [
    beingDisplayed, useBadPhosphor: BOOLEAN,
    cookieCutterVariant, cookie: BOOLEAN,
    underVariant, underNow: BOOLEAN,
    clearingRequired: BOOLEAN,
    inTree: BOOLEAN,
    parent, sibling, child: Handle,
    box: Window.Box,
    place: Window.Place,
    display: PROCEDURE [Handle] ← TRASH, -- keep Ed happy
    invalid, badPhosphor: RecList];
  
  ScanLine: TYPE = LONG ORDERED POINTER TO PACKED ARRAY [0..0) OF BOOLEAN;
  
  ScreenBox: TYPE = RECORD [		 -- (0, 0) is upper left
    left, top, right, bottom: INTEGER];	 -- (right, bottom) is not in the box
    
  RecList: TYPE = LONG POINTER TO Rectangle;
  Rectangle: TYPE = RECORD [
    box: ScreenBox, link: RecList, src, dst: Handle ← NIL];

  
  nullGray: BitBlt.SrcDesc = [gray[BitBlt.GrayParm[0,0,0,0]]];
  
  -- exported variables

  rootWindow: Handle;  -- same as Window but this is not ReadOnly
  
  lock: MONITORLOCK;

  bbPtr: BitBlt.BBptr;
  bitmapAddress: LONG ORDERED POINTER;
  bitmapHeight: CARDINAL;
  
  -- internal utilities
  
  AssertUnobscured: PROC [w: Handle, code: Window.ErrorCode];
  
  InvalidateTree: --INTERNAL-- PROC [
    window, dirtyChild: Handle, invalid: RecList, butNot: Handle ← NIL];
  
  WhitenRecList: --INTERNAL-- PROC [boxes: RecList];
  
  -- these procedures are for use ONLY by the routines implementing Display
  AbsoluteBox: PROC [w: Handle, box: Window.Box] 
    RETURNS [sb: ScreenBox] = INLINE {
    sb.left ← w.place.x + box.place.x;
    sb.right ← sb.left + box.dims.w;
    sb.top ← w.place.y + box.place.y;
    sb.bottom ← sb.top + box.dims.h};
    
  AbsoluteBoxHandle: PROC [w: Handle, box: Window.BoxHandle] 
    RETURNS [sb: ScreenBox] = INLINE {
    sb.left ← w.place.x + box.place.x;
    sb.right ← sb.left + box.dims.w;
    sb.top ← w.place.y + box.place.y;
    sb.bottom ← sb.top + box.dims.h};
    
  Bounds: PROC [w: Handle] RETURNS [sb: ScreenBox] = INLINE {
    sb.left ← w.place.x;
    sb.right ← sb.left + w.box.dims.w;
    sb.top ← w.place.y;
    sb.bottom ← sb.top + w.box.dims.h};
  
  DisplayList: --INTERNAL-- PROC [w: Handle] RETURNS [RecList] = INLINE {
    RETURN[
      IF w.beingDisplayed AND w.useBadPhosphor AND w.badPhosphor # NIL
        THEN w.badPhosphor 
      ELSE GetRecList[w]]};
    
  GetRecList: PRIVATE --INTERNAL-- PROC [window: Handle] RETURNS [RecList];

  GetContext: --INTERNAL-- PROC [r: RecList, default: SpecialDisplay.Special] 
    RETURNS [SpecialDisplay.Special] = INLINE {
    IF r.src # NIL THEN ERROR Window.Error[illegalBitmap];
    RETURN[IF r.dst = NIL THEN default ELSE MakeContext[r]]};
  
  GetBpl: --INTERNAL-- PROC [w: Handle] RETURNS [CARDINAL] = INLINE {
    RETURN[(CARDINAL[w.box.dims.w] + 31)/16 * 16]};
    
  MakeContext: PRIVATE PROC [RecList] RETURNS [SpecialDisplay.Special];
  
  DIVMOD16: PROC [d: CARDINAL] RETURNS [--q, r:-- CARDINAL, CARDINAL] = INLINE {
    RETURN[d/16, d MOD 16]};
  -- ↑ 1 more code byte than Inline.DIVMOD, but significantly faster. --
  
  Offset: PROC [x: INTEGER] RETURNS [word: INTEGER, bit: CARDINAL] = INLINE {
    IF x < 0 THEN {
      x ← -x;
      [word, bit] ← DIVMOD16[CARDINAL[x]];
      IF bit # 0 THEN {word ← word + 1; bit ← 16 - bit};
      RETURN[-word, bit]}
    ELSE RETURN[CARDINAL[x]/16, CARDINAL[x] MOD 16]};
  
  SpecialTimesWpl: PROC [
    w: INTEGER, s: SpecialDisplay.Special ← SpecialDisplay.defaultContext] 
    RETURNS [LONG INTEGER] = INLINE {
    IF w >= 0 THEN RETURN[Inline.LongMult[w, s.wpl]]
    ELSE RETURN[-Inline.LongMult[-w, s.wpl]]};
     
  END.