⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 adtrmbuf.pas

📁 测试用例
💻 PAS
📖 第 1 页 / 共 5 页
字号:
(***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is TurboPower Async Professional
 *
 * The Initial Developer of the Original Code is
 * TurboPower Software
 *
 * Portions created by the Initial Developer are Copyright (C) 1991-2002
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * ***** END LICENSE BLOCK ***** *)

{*********************************************************}
{*                   ADTRMBUF.PAS 4.06                   *}
{*********************************************************}
{*         Terminal: Screen buffer support class         *}
{*********************************************************}

unit ADTrmBuf;

interface

{Notes: The TadTerminalArray class defines a matrix (rows by columns)
        for storing a particular attribute of a terminal. The
        attributes consist of
          - the characters that should be shown on the screen
          - the charset ids
          - the colors for the characters
          - the colors for the background
          - a set of display flags (invisible, blink, etc)
        The array class doesn't 'know' about the values it stores, it
        just knows the size of the values (1, 2, or 4 bytes, default
        1), and knows how to properly resize to take account of
        changes in row or column count.

        This class only knows about item sizes of 1, 2 or 4. The class
        cannot be extended to other sizes that are not powers-of-two.

        All row and column numbers are assumed to be zero-based. This
        class is designed to be used internally by the terminal buffer
        class. Consequently NO RANGE CHECKING IS DONE, unless the
        unit is deliberately compiled with $R+.

        A lot of methods have a case statement on the item size.
        Although the code in each case switch block is duplicated, it
        has been written like this to make the execution more
        efficient. Multiplication by literal 2 or 4 is at least an
        order of magnitude faster than multiplying by an object field
        value.

     The TAdTerminalBuffer class defines a buffer for storing the
        data required to display a terminal display. Essentially, this
        consists of
          - the characters that should be shown on the screen
          - the charset ids (word values)
          - the color for the characters (TColor values)
          - the color for the background (TColor values)
          - a set of display flags (invisible, blink, etc) (bytes)
        To make things more complex, the characters themselves can be
        ANSI or wide/UNICODE.

        There are two views of the data: the "scrollback view" and the
        "display view". The scrollback view shows a history of
        characters/attributes/etc that have scrolled off the top of
        the display view. To make the access to the display view
        easier, there is a pointer to the start of the displayed view.
        There are typically more rows in the scrollback view than in
        the display view (otherwise there wouldn't be anything to
        scroll back through). The number of columns in both the
        scrollback and display views is the same.

        The methods implemented allow strings of characters to be
        written to the buffer, colors to be set, attributes to be
        defined. The class maintains a logical cursor and so also
        supports cursor movement, scrolling, editing, and the like.

        Notice that all row and column numbers external to this class
        are assumed to be one-based. Internally to this class they
        are zero-based for faster computation and are converted at the
        entry/exit of the relevant routines. Also, externally, it is
        only the display view that has positive row numbers. The
        scrollback view uses negative numbers. For example, by default
        there are 200 lines in the scrollback view and 24 lines in the
        display view. Externally these would be known as rows -175..0
        and 1..24, and internally as 0..175 and 176..199.

        External row and column numbers generally refer to the current
        scrolling region. If there is none, or it is inactive, the
        external row and column numbers are counted from the upper
        left corner (1, 1). If a scrolling region is in force,
        external row and column numbers are counted from the upper
        left corner of the scrolling region, not the whole display.
        The row and column numbers are said to be relative to the
        scrolling region, not absolute to the display as a whole.
        Generally, the application sending control sequences to the
        terminal will take account of this and there is nothing to
        worry about. However, to simplify the coding of the redrawing
        of the visual terminal, the methods that return an invalid
        rect provide *absolute* row and column numbers, not relative
        ones.

        UseAutoWrap and UseAutoWrapDelay: automatic wrapping means
        that characters being written to the screen automatically wrap
        at the final column. For example, on an 80-column display if
        we write 'abc' starting at column 79, then 'a' appears at
        column 79, 'b' at col 80, and 'c' at col 1 on the next line.
        If autowrap was off, the 'c' wouldn't appear or would
        overwrite the 'b'. UseAutoWrapDelay encodes the behavior where
        the text cursor doesn't move when you write a character at the
        last column, it will only move when you write the next char.
        So, if AutoWrap is on and UseAutoWrapDelay is off, writing
        'abc' at column 79 would proceed as follows:

        Write 'a' at 79, move cursor to 80
        Write 'b' at 80, move cursor to 1 on the next line
        Write 'c' at 1, move cursor to 2

        With UseAutoWrapDelay on the following occurs:

        Write 'a' at 79, move cursor to 80
        Write 'b' at 80, do not move cursor
        Move cursor to 1 on the next line, write 'c' at 1, move cursor
           to 2

        The important difference is that the cursor can move backwards
        in the second case prior to attempting to write the 'c',
        whereas in the first case it's too late. Note that
        UseAutoWrapDelay is only used if AutoWrap is on. The internal
        field used to store whether this case applies is the
        FBeyondMargin boolean.
}

{$I AWDEFINE.INC}

{$Z-}

{$IFOPT R+}
{$DEFINE UseRangeChecks}
{$ENDIF}

uses
  SysUtils,
  {$IFDEF Win32} Windows, {$ELSE} WinTypes, WinProcs, {$ENDIF}
  Classes,
  Graphics,
  OOMisc, AdExcept;

const
  {Buffer default property values}
  adc_TermBufForeColor = clSilver;
  adc_TermBufBackColor = clBlack;
  adc_TermBufColCount = 80;
  adc_TermBufRowCount = 24;
  {$IFDEF Windows}
  adc_TermBufScrollRowCount = 50;
  {$ELSE}
  adc_TermBufScrollRowCount = 200;
  {$ENDIF}
  adc_TermBufUseAbsAddress = true; {use absolute rows/col values}
  adc_TermBufUseAutoWrap = true; {chars wrap at end of line}
  adc_TermBufUseAutoWrapDelay = true; {..but delay slightly}
  adc_TermBufUseInsertMode = false; {no insert mode}
  adc_TermBufUseNewLineMode = false; {LF char is a pure linefeed}
  adc_TermBufUseScrollRegion = false; {no scroll region used}

type
  TadtWordArray = array [0..MaxInt div sizeof(word) - 1] of word;
  PadtWordArray = ^TadtWordArray;
  TadtLongArray = array [0..MaxInt div sizeof(longint) - 1] of longint;
  PadtLongArray = ^TadtLongArray;

  TAdTerminalCharAttr = (  {character attributes}
         tcaBold,          {..bold}
         tcaUnderline,     {..underlined}
         tcaStrikethrough, {..struck through as if deleted}
         tcaBlink,         {..blinking}
         tcaReverse,       {..back/foreground colors reversed}
         tcaInvisible,     {..invisible}
         tcaSelected);     {..selected}
  TAdTerminalCharAttrs = set of TAdTerminalCharAttr;

  TAdScrollRowsNotifyEvent =
     procedure (aSender : TObject;
                aCount, aTop, aBottom : integer) of object;

  TAdOnCursorMovedEvent =                                              
     procedure (ASender  : TObject;                                    
                Row, Col : integer) of object;                         

  TadTerminalArray = class
    private
      FActColCount : integer;
      FColCount    : integer;
      FDefaultItem : longint;
      FItems       : PAnsiChar;
      FItemSize    : integer;
      FRowCount    : integer;
    protected
      procedure taSetColCount(aNewCount : integer);
      procedure taSetRowCount(aNewCount : integer);

      procedure taClearRows(aBuffer : PAnsiChar;
                            aActColCount : integer;
                            aStartRow, aEndRow : integer);
      procedure taGrowArray(aRowCount,
                            aColCount, aActColCount : integer);
    public
      constructor Create(aItemSize : integer);
      destructor Destroy; override;

      procedure Clear;
        {-clear the entire array, filling with DefaultItem}

      procedure ClearItems(aRow : integer;
                           aFromCol, aToCol : integer);
        {-clear the row in between the two inclusive columns, filling
          with DefaultItem (equivalent to 'erase')}

      procedure DeleteItems(aCount : integer;
                            aRow   : integer;
                            aCol   : integer);
        {-delete aCount default items at aRow , aCol; items currently
          beyond these positions are pulled left, and their original
          positions filled with default items; this action does not
          extend beyond the row}


      function GetItemPtr(aRow, aCol : integer) : pointer;
        {-return a pointer to the item at aRow, aCol; caller must
          properly dereference, and not memory overread}

      procedure InsertItems(aCount : integer;
                            aRow   : integer;
                            aCol   : integer);
        {-insert aCount default items at aRow , aCol; items currently
          in these positions are pushed right, but not beyond the row
          boundary}

      procedure ReplaceItems(aOldItem : pointer;           {new !!.02}
                             aNewItem : pointer);
        {-replace every incidence of aOldItem with aNewItem}

      procedure SetDefaultItem(aDefaultItem : pointer);
        {-define the default item to be used to fill new items, eg,
          during scrolling, clearing or resizing}

      procedure ScrollRows(aCount : integer;
                           aStartRow, aEndRow : integer);
        {-scroll the data by aCount rows, filling new rows with
          DefaultItem; scroll just between aStartRow and aEndRow
          inclusive; if aCount is +ve it means scroll upwards (ie, the
          usual sense), if -ve scroll downwards}

      procedure WriteItems(aItems : pointer;
                           aCount : integer;
                           aRow, aCol : integer);
        {-write aCount items to aRow, aCol, without wrapping at the
          end of the row}

      procedure WriteDupItems(aItem  : pointer;
                              aCount : integer;
                              aRow, aCol : integer);
        {-write aCount copies of aItem to aRow, aCol, without wrapping
          at the end of the row}

      property ColCount : integer read FColCount write taSetColCount;
      property ItemSize : integer read FItemSize;
      property RowCount : integer read FRowCount write taSetRowCount;
  end;

type
  TAdTerminalBuffer = class
    private
      FAttr         : TAdTerminalCharAttrs; {current attributes}
      FBackColor    : TColor;   {current background color}
      FBeyondMargin : boolean;  {true if cursor's beyond right margin}
      FCharSet      : byte;     {current charset}
      FColCount     : integer;  {count of columns in both views}
      FCursorCol    : integer;  {current internal cursor col position}
      FCursorMoved  : boolean;  {true if cursor has moved}
      FCursorRow    : integer;  {current internal cursor row position}
      FDefAnsiChar  : AnsiChar; {default ANSI character}
      FDefAttr      : TAdTerminalCharAttrs; {default attributes}
      FDefCharSet   : byte;     {default charset}
      FDefBackColor : TColor;   {default background color}
      FDefForeColor : TColor;   {default foreground color}
      {$IFDEF Win32}
      FDefWideChar  : WideChar; {default wide character}
      {$ENDIF}
      FDisplayOriginCol : integer; {column origin of addressable area}
      FDisplayOriginRow : integer; {row origin of addressable area}
      FDisplayColCount  : integer; {column count in addressable area}
      FDisplayRowCount  : integer; {row count in addressable area}
      FForeColor    : TColor;   {current foreground color}
      FHorzTabStops : PByteArray; {bitset of horizontal tab stops}
      FInvRectList  : pointer;  {list of invalid rects}
      FOnScrollRows : TAdScrollRowsNotifyEvent;
      FRowCount     : integer;  {count of rows in display view}
      FSRStartRow   : integer;  {start row of scrolling region}
      FSREndRow     : integer;  {end row of scrolling region}
      FSVRowCount   : integer;  {count of rows in scrollback view}
      FUseAbsAddress: boolean; {true if absolute values for row/col}
      FUseAutoWrap  : boolean;  {true if chars wrap to next line}
      FUseAutoWrapDelay: boolean; {true if cursor stays at last col}
      FUseInsertMode   : boolean; {true if insert rather than replace}
      FUseNewLineMode  : boolean; {true if LF means CR+LF}
      FUseScrollRegion : boolean; {true if limit to scroll region}
      FUseWideChars : boolean;  {true if expecting UNICODE chars}
      FVertTabStops : PByteArray; {bitset of vertical tab stops}

      FCharMatrix   : TAdTerminalArray;    {matrix of chars}
      FCharSetMatrix: TAdTerminalArray;    {matrix of charsets}
      FAttrMatrix   : TAdTerminalArray;    {matrix of attrs}
      FForeColorMatrix : TAdTerminalArray; {matrix of forecolors}
      FBackColorMatrix : TAdTerminalArray; {matrix of backcolors}

      FOnCursorMoved : TAdOnCursorMovedEvent; {Cursor moved event}
      FTerminalHandle : THandle; {Handle of owning terminal}             {!!.05}     

    protected
      function tbGetCol : integer;
      function tbGetOriginCol : integer;
      function tbGetOriginRow : integer;
      function tbGetRow : integer;

      procedure tbSetBackColor(aValue : TColor);
      procedure tbSetCharSet(aValue : byte);
      procedure tbSetDefAnsiChar(aValue : AnsiChar);
      procedure tbSetDefBackColor(aValue : TColor);            
      procedure tbSetDefForeColor(aValue : TColor);            
      procedure tbSetForeColor(aValue : TColor);
      procedure tbSetSVRowCount(aNewCount : integer);
      procedure tbSetCol(aCol : integer);
      procedure tbSetColCount(aNewCount : integer);
      procedure tbSetRow(aRow : integer);
      procedure tbSetRowCount(aNewCount : integer);
      procedure tbSetUseScrollRegion(aValue : boolean);

      procedure tbInvalidateRect(aFromRow, aFromCol,
                                 aToRow, aToCol : integer);

      function tbCvtToInternalCol(aCol : integer;
                                  aAbsolute : boolean) : integer;
      function tbCvtToInternalRow(aRow : integer;
                                  aAbsolute : boolean) : integer;
      function tbCvtToExternalCol(aCol : integer;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -