{***********************************************************************}
{									}
{ __WriteWin  Write a string to in the current window			}
{									}
{ procedure WriteWin(X,Y : byte; BufferPtr : pointer;			}
{				   NoChars : word;			}
{			    Fore,Back,Mode : byte);			}
{									}
{	      X,Y	Column and row position where the string is to	}
{			be written.					}
{	      BufferPtr Pointer to string (and attributes) which is to	}
{			be displayed.					}
{	      NoChars	The number of characters to be output.		}
{	      Fore,Back Foreground and background attributes used when	}
{			displaying the string.	These parameters are	}
{			ignored if the value of Mode is 2 or 3. 	}
{	      Mode	The mode value tells __WriteWin how the buffer	}
{			is constructed and where to position the cursor }
{			when the string has been written.  The four	}
{			possible values are:				}
{									}
{			Mode Value  Description 			}
{			----------  ----------------------------------- }
{			    0	    The cursor is not moved, and the	}
{				    string contains just characters.	}
{			    1	    The cursor is positioned after the	}
{				    last character written, and the	}
{				    string contains just characters.	}
{			    2	    The cursor is not moved, but the	}
{				    string is made up of character fol- }
{				    lowed by attribute bytes.		}
{			    3	    Like mode 2, but the cursor is	}
{				    positioned as in mode 1.		}
{									}
{ Description __WriteWin displays a string buffer within the current	}
{	      window starting at the specified cursor position. 	}
{	      For modes 2 and 3, it is assumed that the buffer if for-	}
{	      matted in the form char,attr,char,attr,.... (i.e., like	}
{	      the _ScnPos type).  For modes 0 and 1, the string just	}
{	      contains characters, and the attributes are determined	}
{	      by the parameters Fore and Back.	For modes 0 and 2 the	}
{	      cursor is not repositioned, but for modes 1 and 3 it is	}
{	      placed after the last character output.  The value of	}
{	      NoChars is the number of characters to output; in the	}
{	      case of modes 0 and 1, if a pointer to a string is pas-	}
{	      sed, it must point to the first character, not the 0th	}
{	      component (which is the length).				}
{									}
{	      Carriage return, line feed, backspace and bell (Ctrl/G)	}
{	      characters are treated as commands rather than printable	}
{	      characters.						}
{									}
{ Version     4.00 (C)Copyright Blaise Computing Inc.  1987		}
{_______________________________________________________________________}

procedure __WriteWin(X,Y : byte; BufferPtr : pointer;
				   NoChars : word;
			    Fore,Back,Mode : byte);

  type
    MemoryPtr = ^_MemoryChar;

  var
    Attr      : byte;
    ThisCh    : char;
    BufPtr    : ^_ScnImage absolute BufferPtr;
    StrPtr    : MemoryPtr  absolute BufferPtr;
    X1,Y1     : byte;
    X2,Y2     : byte;
    I	      : word;
    CTop,CBot : byte;
    Reg       : registers;

  begin {__WriteWin}

    if (Mode > 4) then
       Mode := 0;		       { Use the default		}
    Attr := __2ByteSup(Back,Fore);

    __WhereWin(X1,Y1,CTop,CBot);       { First get current location,	}
    __GotoWin(X,Y);		       { and go to the new location.	}

    for I := 1 to NoChars do
      with Reg do
	begin
	  if (Mode < 2) then	       { Just a character string	}
	     ThisCh := StrPtr^[I]
	  else			       { Character and attribute	}
	     begin
	       ThisCh := BufPtr^[I]._Ch;
	       Attr   := BufPtr^[I]._Attr
	     end;

	  { If not a special character, then display the character	}
	  { and attribute.  A call to TTY write after, positions the	}
	  { cursor appropriately, and handles the special characters.	}

	  if (not (ThisCh in [#7,#8,#10,#13])) then
	     __AttrScn(ThisCh,1,Attr and $F,__HiNybSup(Attr));
	  AH := $0E;			   { Now do the TTY output	}
	  AL := byte(ThisCh);
	  Intr(_VIDEO,Reg);
	  with _CurWindow do		   { If we have moved outside	}
	    begin			   { the window, adjust the	}
	      __WhereScn(X2,Y2,CTop,CBot); { cursor position and possi- }
	      Y2 := Y2 - _YUpper + 1;	   { bly scroll the window up a }
	      X2 := X2 - _XUpper + 1;	   { line.			}
	      if (X2 > (_XLower - _XUpper + 1)) then
		 begin			   { Simulate a carriage return }
		   X2 := 1;		   { and line feed.		}
		   Inc(Y2)
		 end
	      else if (X2 < 1) then	   { Simulate a carriage return }
		   X2 := 1;
	      if (Y2 > (_YLower - _YUpper + 1)) then	  { Must scroll }
		 begin			   { Use attribute of last	}
		   Y2 := _YLower - _YUpper + 1;
		   __VertScn(_XUpper,_YUpper,_XLower,_YLower,1,
				      Attr and $F,__HiNybSup(Attr),TRUE)
		 end;
	      __GotoWin(X2,Y2)
	    end
	end;
    if (not Odd(Mode)) then		   { Reposition the cursor	}
       __GotoWin(X1,Y1);

  end;	{__WriteWin}
