-- Copyright (C) 1983  by Xerox Corporation. All rights reserved. 
-- DisplayGlueImpl.mesa - last edited by 
-- Rick		16-Nov-83 19:43:06
-- Bruce	24-Feb-83 16:07:32

DIRECTORY
  BitBlt USING [BitBltFlags],
  Display USING [],
  DisplayInternal USING [Circle, Conic, SpecialCircle, SpecialConic],
  SpecialDisplay USING [
    defaultContext, LineStyle, OrthogonalLine, NegativeShallowLine,
    NegativeSteepLine, Negative45Line, PositiveShallowLine, PositiveSteepLine,
    Positive45Line, Special, SpOrthoLine, SpNegativeShallowLine,
    SpNegativeSteepLine, SpNegative45Line, SpPositiveShallowLine,
    SpPositiveSteepLine, SpPositive45Line],
  Window USING [Box, BoxHandle, Handle, Place];

DisplayGlueImpl: PROGRAM
  -- implements routines in Display and SpecialDisplay that call routines
  --  implemented in DisplayImpl*
  IMPORTS DisplayInternal, SpecialDisplay EXPORTS Display, SpecialDisplay =
  BEGIN

  -- copied types because John doesn't like them
  LineStyle: TYPE = SpecialDisplay.LineStyle;
  Special: TYPE = SpecialDisplay.Special;

  -- circles
  Circle: PUBLIC PROC [  -- exported to Display
    window: Window.Handle, place: Window.Place, radius: INTEGER,
    bounds: Window.BoxHandle ← NIL] = {
    DisplayInternal.Circle[window, place, radius, ALL[FALSE], bounds]};

  SpCircle: PUBLIC PROC [  -- exported to SpecialDisplay
    window: Window.Handle, place: Window.Place, radius: INTEGER,
    bounds: Window.BoxHandle, dashes: LineStyle, flags: BitBlt.BitBltFlags,
    context: Special ← SpecialDisplay.defaultContext] = {
    DisplayInternal.SpecialCircle[
      window, place, radius, ALL[FALSE], bounds, dashes, flags, context]};

  -- conics
  Conic: PUBLIC PROC [  -- exported to Display	
    window: Window.Handle, a, b, c, d, e, errorTerm: LONG INTEGER,
    start, stop, errorRef: Window.Place,
    sharpCornered, unboundedStart, unboundedStop: BOOLEAN,
    bounds: Window.BoxHandle ← NIL] = {
    DisplayInternal.Conic[
      window, a, b, c, d, e, errorTerm, start, stop, errorRef, sharpCornered,
      bounds]};

  SpConic: PUBLIC PROC [  -- exported to SpecialDisplay
    window: Window.Handle, a, b, c, d, e, errorTerm: LONG INTEGER,
    start, stop, errorRef: Window.Place, sharpCornered: BOOLEAN,
    bounds: Window.BoxHandle, dashes: LineStyle, flags: BitBlt.BitBltFlags,
    context: Special ← SpecialDisplay.defaultContext] = {
    DisplayInternal.SpecialConic[
      window, a, b, c, d, e, errorTerm, start, stop, errorRef, sharpCornered,
      bounds, dashes, flags, context]};

  -- lines
  Line: PUBLIC PROC [  -- exported to Display
    window: Window.Handle, start, stop: Window.Place,
    bounds: Window.BoxHandle ← NIL] = {
    box: Window.Box;
    IF bounds = NIL THEN {
      box ← [
         place: [x: MIN[start.x, stop.x], y: MIN[start.y, stop.y]],
         dims: [w: ABS[start.x - stop.x] + 1, h: ABS[start.y - stop.y] + 1]];
       bounds ← @box};
    SELECT TRUE FROM
      start.y = stop.y => 	-- horizontal	
        SpecialDisplay.OrthogonalLine[window, bounds↑];
      start.x = stop.x => 	-- vertical
        SpecialDisplay.OrthogonalLine[window, bounds↑];
      ENDCASE => {  -- diagonals
        positive: BOOLEAN;
        dx, dy: INTEGER;
        IF stop.y > start.y THEN {  -- always start at bottom
          temp: Window.Place = start; start ← stop; stop ← temp};
        dx ← stop.x - start.x;
        dy ← start.y - stop.y;  -- dy always positive
        IF ~(positive ← dx > 0) THEN dx ← -dx;  -- now dx positive
        SELECT dx FROM
          < dy =>
            IF positive THEN
              SpecialDisplay.PositiveSteepLine[window, start, stop, bounds]
            ELSE SpecialDisplay.NegativeSteepLine[window, start, stop, bounds];
          = dy =>
            IF positive THEN
              SpecialDisplay.Positive45Line[window, start, stop.x, bounds]
            ELSE SpecialDisplay.Negative45Line[window, start, stop.x, bounds];
          ENDCASE =>
            IF positive THEN
              SpecialDisplay.PositiveShallowLine[window, start, stop, bounds]
            ELSE SpecialDisplay.NegativeShallowLine[window, start, stop,bounds]}};

  SpecialLine: PUBLIC PROC [  -- exported to SpecialDisplay
    window: Window.Handle, start, stop: Window.Place, bounds: Window.BoxHandle,
    dashes: LineStyle, flags: BitBlt.BitBltFlags,
    context: Special ← SpecialDisplay.defaultContext] = {
    box: Window.Box;
    IF bounds = NIL THEN {
      highWidth: CARDINAL = dashes.thickness/2;
      box ← [
        place: [x: MIN[start.x, stop.x], y: MIN[start.y, stop.y]],
        dims: [w: ABS[start.x - stop.x] + 1, h: ABS[start.y - stop.y] + 1]];
      IF ABS[start.x - stop.x] >= ABS[start.y - stop.y] THEN {  -- shallow
        box.place.y ← box.place.y - highWidth;
        box.dims.h ← box.dims.h + dashes.thickness - 1}
      ELSE {
        box.place.x ← box.place.x - highWidth;
        box.dims.w ← box.dims.w + dashes.thickness - 1};
      bounds ← @box};
    SELECT TRUE FROM
      start.y = stop.y =>   -- horizontal
        SpecialDisplay.SpOrthoLine[window, bounds↑, dashes, flags, context];
      start.x = stop.x =>   -- vertical
        SpecialDisplay.SpOrthoLine[window, bounds↑, dashes, flags, context];
      ENDCASE => {  -- diagonals
        positive: BOOLEAN;
        dx, dy: INTEGER;
        IF stop.y > start.y THEN {  -- always start at bottom
          temp: Window.Place = start; start ← stop; stop ← temp};
        dx ← stop.x - start.x;
        dy ← start.y - stop.y;  -- dy always positive
        IF ~(positive ← dx > 0) THEN dx ← -dx;  -- now dx positive
        SELECT dx FROM
          < dy =>
            IF positive THEN
              SpecialDisplay.SpPositiveSteepLine[
                window, start, stop, bounds, dashes, flags, context]
            ELSE
              SpecialDisplay.SpNegativeSteepLine[
                window, start, stop, bounds, dashes, flags, context];
          = dy =>
            IF positive THEN
              SpecialDisplay.SpPositive45Line[
                window, start, stop.x, bounds, dashes, flags, context]
            ELSE
              SpecialDisplay.SpNegative45Line[
                window, start, stop.x, bounds, dashes, flags, context];
          ENDCASE =>
            IF positive THEN
              SpecialDisplay.SpPositiveShallowLine[
                window, start, stop, bounds, dashes, flags, context]
            ELSE
              SpecialDisplay.SpNegativeShallowLine[
                window, start, stop, bounds, dashes, flags, context]}};


  END.