{***********************************************************************}
{									}
{ __BoxScn    Write a box on the current display page			}
{									}
{ procedure __BoxScn(X1,Y1,X2,Y2,BoxType,Fore,Back : byte);		}
{									}
{	      X1,Y1	Coordinates of upper left corner of the box.	}
{	      X2,Y2	Coordinates of lower right corner of the box.	}
{	      BoxType	The type of box to construct.  If the value of	}
{			BoxType is less than 16, the low order four	}
{			bits are used to determine each side of the box.}
{			If the bit is set, a double line is drawn;	}
{			otherwise a single line.  The four bits, from 0 }
{			to three, represent the left side, top, right	}
{			side and bottom respectively.  The corners are	}
{			constructed properly to match the sides and	}
{			top and bottom.  If the value of BoxType is	}
{			no less than 16, BoxType is the ASCII code of	}
{			character to be used to draw the box.		}
{	      Fore	The foregound attribute of the box borders.	}
{	      Back	The background attribute of the box borders.	}
{									}
{ Description This procedure draws a specified box on the current dis-	}
{	      play page.  It designed to be used with __DispWin ( the	}
{	      display a window procedure), so no error checking is done }
{	      on the parameters.  It is the programmer's responsibility }
{	      to make sure that all parameters are reasonable.		}
{									}
{ Version     4.00 (C)Copyright Blaise Computing Inc.  1987		}
{_______________________________________________________________________}

procedure __BoxScn(X1,Y1,X2,Y2,BoxType,Fore,Back : byte);

  { The typed constants Corners and Lines are used to construct the	}
  { box.  The Corners array consists of an array for each corner.  The	}
  { proper character is chosen by looking at the BoxType parameter and	}
  { indexing into the array.  For example, to determine which character }
  { to use for the Top Left corner, look at the Left and Top lines	}
  { (bits 0 and 1).  The value is in the range 0 to 3 (a bit is set if	}
  { a double line is desired).	This value is the second index of the	}
  { array; the first index is the corner.  The correct horizontal and	}
  { vertical lines are chosen in the same way.				}

  const
    Corners : array[1..4,0..3] of char =
			 ((#218,#214,#213,#201),   { Top left corner	}
			  (#191,#184,#183,#187),   { Top right corner	}
			  (#192,#211,#212,#200),   { Bottom left	}
			  (#217,#189,#190,#188));  { Bottom right	}
    Lines   : array[1..2,0..1] of char =
			 ((#196,#205),		   { Horizontal 	}
			  (#179,#186)); 	   { Vertical		}

  {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  { WrtChrs   Write a character with attributes at a specifed location	}
  {_____________________________________________________________________}

  procedure WrtChrs(X,Y: byte; DisplayCh : char; Num,Fore,Back : byte);

    begin {WrtChrs}

      __GotoScn(X,Y);
      __AttrScn(DisplayCh,word(Num),Fore,Back)

    end;  {WrtChrs}

  var
    BoxCorner	  : array[1..4] of char;
    BoxLine	  : array[1..4] of char;
    BoxChar	  : char;
    HorChars	  : byte;
    VerChars	  : byte;
    I		  : word;
    CursorOn	  : boolean;
    X,Y,XTop,XBot : byte;

  begin {__BoxScn}

    __WhereScn(X,Y,XTop,XBot);	       { Remember where cursor is	}

    { First, determine which characters make up the corners and lines.	}
    { If BoxType is no less than 16, then all characters are just the	}
    { character having ASCII code equal to BoxType.			}

    if (BoxType > 15) then
       begin
	 BoxChar := Chr(BoxType);
	 FillChar(BoxCorner,4,BoxChar);
	 FillChar(BoxLine,4,BoxChar)
       end
    else
       begin
	 BoxCorner[1] := Corners[1,(BoxType and 3)];
	 BoxCorner[2] := Corners[2,((BoxType shr 1) and 3)];
	 BoxCorner[3] := Corners[3,
		    ((BoxType and 1) or ( 2 * ((BoxType shr 3) and 1)))];
	 BoxCorner[4] := Corners[4,((BoxType shr 2) and 3)];
	 BoxLine[1]   := Lines[1,((BoxType shr 1) and 1)];   { Top	}
	 BoxLine[2]   := Lines[1,((BoxType shr 3) and 1)];   { Bottom	}
	 BoxLine[3]   := Lines[2,(BoxType and 1)];	     { Left	}
	 BoxLine[4]   := Lines[2,((BoxType shr 2) and 1)]    { Right	}
       end;

    { Now compute the number of characters to write for vertical and	}
    { horizontal lines.  Note that this is just the box dimensions less }
    { 2 to account for the corners (i.e., (X2 - X1 + 1) - 2 ).		}

    HorChars := X2 - X1 - 1;
    VerChars := Y2 - Y1 - 1;

    { Now actually write the box by making calls to WrtChrs.  The box	}
    { is drawn from top to bottom, left to right.			}

    CursorOn := __IsCurScn;
    if (CursorOn) then
       __COffScn(TRUE); 	       { Turn cursor off if is was on	}

    WrtChrs(X1,Y1,BoxCorner[1],1,Fore,Back);	   { Top left corner	}
    if (HorChars > 0) then			   { Top line		}
       WrtChrs(X1 + 1,Y1,BoxLine[1],HorChars,Fore,Back);
    WrtChrs(X2,Y1,BoxCorner[2],1,Fore,Back);	   { Top right corner	}
    for I := 1 to VerChars do			   { Vertical lines.	}
      begin
	WrtChrs(X1,Y1 + I,BoxLine[3],1,Fore,Back);
	WrtChrs(X2,Y1 + I,BoxLine[4],1,Fore,Back)
      end;
    WrtChrs(X1,Y2,BoxCorner[3],1,Fore,Back);	   { Bottom left corner }
    if (HorChars > 0) then			   { Bottom line	}
       WrtChrs(X1 + 1,Y2,BoxLine[2],HorChars,Fore,Back);
    WrtChrs(X2,Y2,BoxCorner[4],1,Fore,Back);	   { Bottom right	}

    __GotoScn(X,Y);		       { Return to original location	}
    if (CursorOn) then
       __COffScn(FALSE) 	       { Turn back on if was originally }

  end;	{__BoxScn}
