{***********************************************************************}
{									}
{ __WriteScn  Write a string to the screen				}
{									}
{ procedure __WriteScn(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 __WriteScn 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 __WriteScn displays a string buffer on the current dis-	}
{	      play page starting at the specified cursor position.	}
{	      For modes 2 and 3, it is assumed that the buffer is 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 passed,}
{	      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 __WriteScn(X,Y : byte; BufferPtr : Pointer;
				   NoChars : word;
			    Fore,Back,Mode : byte);

  type
    MemoryPtr = ^_MemoryChar;	       { _MemoryChar defined in Unit_Sup}

  var
    Attr      : byte;
    DisplayCh : char;
    BufPtr    : _ScnImagePtr absolute BufferPtr;
    StrPtr    : MemoryPtr    absolute BufferPtr;
    I	      : word;
    X1,Y1     : byte;
    Top,Bot   : byte;
    Reg       : registers;

  begin {__WriteScn}

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

    { If we have either a machine that supports it, use BIOS call $13.	}

    if (  (_PCModel = _AT) or
	(_CurDevice = _EgaAdapter) or
	(_CurDevice = _VgaAdapter) or
	(_CurDevice = _McgaAdapter)  ) then
       with Reg do
	 begin
	   AH := $13;			     { BIOS call $13, AL = mode }
	   AL := Mode;
	   BH := _CurDisplayPage;
	   BL := Attr;
	   CX := NoChars;
	   DH := Y - 1;
	   DL := X - 1;
	   ES := _VectorAddr(BufferPtr)._Seg;
	   BP := _VectorAddr(BufferPtr)._Ofs;
	   Intr(_VIDEO,Reg)
	 end
    else			       { Must emulate AT BIOS call $13	}
       begin			       { by using BIOS call 14. 	}
	 __WhereScn(X1,Y1,Top,Bot);    { First get current location,	}
	 __GotoScn(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 }
		  DisplayCh := StrPtr^[I]
	       else			     { Character and attribute }
		  begin
		    DisplayCh := BufPtr^[I]._Ch;
		    Attr      := BufPtr^[I]._Attr
		  end;

	       { If not a special character (BEL, BACKSPACE, LINEFEED,	}
	       { RETURN), then just display the character, otherwise	}
	       { display the character using the BIOS TTY write routine.}
	       { The first call to __AttrScn is required to display	}
	       { attribute, and then TTY write positions the cursor.	}

	       if ( (DisplayCh <> #7)  and (DisplayCh <> #8) and
		    (DisplayCh <> #10) and (DisplayCh <> #13)) then
		  __AttrScn(DisplayCh,1,Attr and $F,__HiNybSup(Attr));
	       AH := $0E;
	       AL := byte(DisplayCh);
	       Intr(_VIDEO,Reg)
	     end;
	 if (not Odd(Mode)) then       { Reposition the cursor if	}
	    __GotoScn(X1,Y1)	       { required by the mode criterion.}
       end

  end;	{__WriteScn}
