{***********************************************************************}
{									}
{ __FastScn   Write a string to the screen directly			}
{									}
{ procedure __FastScn(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 0 or 2. 	}
{	      Mode	The mode value tells __FastScn how the buffer	}
{			is constructed: The three values are:		}
{									}
{			Mode Value  Description 			}
{			----------  ----------------------------------- }
{			    0	    The buffer contains just characters }
{				    and the attributes are not altered. }
{			    1	    The buffer contains just characters,}
{				    but the characters are written with }
{				    the specified attributes.		}
{			    2	    The buffer is made up of characters }
{				    followed by attribute bytes.	}
{			    3	    The buffer is ignored, and the	}
{				    characters on the screen are not	}
{				    altered, but the attributes are	}
{				    altered to the values of Fore and	}
{				    Back.				}
{									}
{ Description __FastScn displays a string buffer on the current display }
{	      page starting at the specified cursor position.  This	}
{	      routine is designed for those application requiring fast	}
{	      screen update.  Under less stringent speed requirements,	}
{	      __WriteScn is probably a better choice, because it can	}
{	      function in graphics modes and treats CR/LF, Backspace	}
{	      Ctrl/G as commands rather than displayable characters.	}
{									}
{	      For mode two (2), it is assumed that the buffer is for-	}
{	      matted in the form char,attr,char,attr,.... (i.e., like	}
{	      the _ScnPos type).  For all other modes, the string just	}
{	      contains characters, and the attributes are determined	}
{	      by the parameters Fore and Back or by the current screen	}
{	      settings. The cursor position and size is not altered by	}
{	      __FastScn.						}
{									}
{	      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).	For mode 3, NoChars	}
{	      is the number of characters on the screen whose		}
{	      attributes are altered.					}
{									}
{	      Carriage return, line feed, backspace and bell (Ctrl/G)	}
{	      characters are treated as standard characters rather than }
{	      commands (see __WriteScn).  If the screen mode is not a	}
{	      standard text mode (0,1,2,3 and 7), or the requested	}
{	      cursor position is out of range, then no action is taken	}
{	      and control returns immediately.				}
{									}
{ Version     4.00 (C)Copyright Blaise Computing Inc. 1987		}
{_______________________________________________________________________}

procedure __FastScn(X,Y : byte; BufferPtr : Pointer;
				  NoChars : word;
			   Fore,Back,Mode : byte);

  var
    PageLength : word absolute _BIOSSEG:$004C;
    PageSize   : word;
    ScnPtr     : Pointer;
    Offset     : word;
    Attr       : byte;
    Wait       : boolean;

  begin {__FastScn}

    if (NoChars <= 0) then	       { Nothing to do, so exit 	}
       Exit;

    { Check for reasonable values for X and Y and to make sure that we	}
    { are in a text mode.						}

    if ( ((_CurMode > 3) and (_CurMode <> 7)) or
			      ((X < 0) or (X > _CurColumns) or
				  (Y < 0) or (Y > _CurRows)) ) then
       Exit;

    { Force reasonable values for the mode and attributes.		}

    if (Mode > 3) then
       Mode := 0
    else if (Mode = 3) then
       Mode := 4;		       { __SpeedScn expects 4		}
    Attr := __2ByteSup(Back,Fore);

    { Now compute the offset into adapter memory where the string will	}
    { be written.  The offset is used together with _ScnLoc to con-	}
    { struct the pointer to the adapter memory location.		}

    OffSet   := (((Y - 1) * _CurColumns) + (X - 1)) * 2;
    PageSize := _CurRows * _CurColumns * 2;	  { Don't write beyond	}
    if ((OffSet + (2 * NoChars)) > PageSize) then { the page.		}
       NoChars := (PageSize - Offset) div 2;
    if (_CurDisplayPage <> 0) then		 { Offset into the cor- }
       OffSet := PageLength * _CurDisplayPage + Offset; { rect page	}
    ScnPtr := Ptr(_VectorAddr(_ScnLoc)._Seg,
				     _VectorAddr(_ScnLoc)._Ofs + OffSet);

    Wait := (_CurDevice = _ColorAdapter);

    __SpeedScn(BufferPtr,ScnPtr,NoChars,word(Mode),word(Attr),Wait)

  end;	{__FastScn}
