{$I OVC.INC}

{$B-} {Complete Boolean Evaluation}
{$I+} {Input/Output-Checking}
{$P+} {Open Parameters}
{$T-} {Typed @ Operator}
{$W-} {Windows Stack Frame}
{$X+} {Extended Syntax}

{$IFNDEF Win32}
{$G+} {286 Instructions}
{$N+} {Numeric Coprocessor}
{$C MOVEABLE,DEMANDLOAD,DISCARDABLE}
{$ENDIF}

{*********************************************************}
{*                  OVCVIEWR.PAS 2.00                    *}
{*     Copyright (c) TurboPower Software Co 1995-96      *}
{*                 All rights reserved.                  *}
{*********************************************************}

unit OvcViewr;

interface

uses
  {$IFDEF Win32} Windows, {$ELSE} WinTypes, WinProcs, {$ENDIF}
  Classes, Controls, Forms, Graphics, Menus, Messages, StdCtrls, SysUtils,
  OvcBase, OvcCaret, OvcCmd, OvcColor, OvcConst, OvcData,
  OvcExcpt, OvcFxFnt, OvcMisc, OvcStr;

type
  {text position record for editor and viewer}
  TOvcTextPos = packed record
    Line : LongInt;
    Col  : SmallInt;
  end;

  {a range of text in a viewer}
  TOvcRange = record
    Start, Stop : TOvcTextPos;
  end;

  TSmallPoint = record
    X, Y : SmallInt;
  end;

const
  {default property values for viewer and descendants}
  DefBorderStyle     = bsSingle;
  DefBufferPageCount = 16;
  DefColor           = clWindow;
  DefExpandTabs      = True;
  DefFilterChars     = True;
  DefHeight          = 150;
  DefHexMode         = False;
  DefHighlightBack   = clHighlight;
  DefHighlightText   = clHighlightText;
  DefIsOpen          = False;
  DefMarginColor     = clWindow;
  DefScrollBars      = ssBoth;
  DefShowBookmarks   = True;
  DefShowCaret       = True;
  DefTabSize         = 8;
  DefTabStop         = True;
  DefWidth           = 200;

  MaxMarkers         = 10;    {maximum number of text markers}

type
  {The ancestor viewer class}
  TOvcBaseViewer = class(TOvcBase)
  {.Z+}
  protected {private}
    {property fields - persistent}
    FBorderStyle      : TBorderStyle;
    FExpandTabs       : Boolean;
    FFixedFont        : TOvcFixedFont;
    FHighlightColors  : TOvcColors;
    FMarginColor      : TColor;
    FScrollBars       : TScrollStyle;
    FShowBookmarks    : Boolean;
    FShowCaret        : Boolean;
    FTabSize          : Byte;

    {property fields - set at runtime}
    FCaretEffCol      : SmallInt;
    FCaretPos         : TOvcTextPos;
    FLineCount        : LongInt;
    FMarkers          : array[0..MaxMarkers-1] of TOvcTextPos;
    FTopLine          : LongInt;

    {event variables}
    FOnShowStatus     : TShowStatusEvent;
    FOnTopLineChanged : TTopLineChangedEvent;
    FOnUserCommand    : TUserCommandEvent;

    {other internal fields}
    vwAmFocused       : Boolean;         {True if focused}
    vwAnchor          : TOvcTextPos;     {anchor for highlighting}
    vwBMGlyphs        : TBitMap;         {marker glyphs}
    vwCaret           : TOvcSingleCaret; {our caret}
    vwCols            : SmallInt;        {number of columns in window}
    vwColWid          : SmallInt;        {width of one column}
    vwDefaultChar     : Char;            {replacement Char for current font}
    vwDitheredBG      : Boolean;         {True if a background color is dithered}
    vwDivisor         : LongInt;         {divisor for scroll bars}
    vwFile            : Integer;         {handle of file being browsed}
    vwFirstChar       : Char;            {first Char in current font}
    vwHighlight       : TOvcRange;       {highlight range}
    vwHDelta          : SmallInt;        {horizontal scroll delta}
    vwHScroll         : Boolean;         {True if we have a horizontal scroll bar}
    vwHSHigh          : SmallInt;        {horizontal scroll limit}
    vwLastChar        : Char;            {last Char in current font}
    vwLineSelCursor   : hCursor;         {line selection cursor}
    vwLineSelCursorOn : Boolean;         {is line selection cursor in use?}
    vwRowHt           : SmallInt;        {height of one row}
    vwRows            : SmallInt;        {number of rows in window}
    vwSaveCursor      : HCursor;         {saved cursor for lengthy waits}
    vwVScroll         : Boolean;         {True if we have a vertical scroll bar}
    vwVSHigh          : LongInt;         {vertical scroll limit}
    vwVSMax           : LongInt;         {max value for vertical scroll bar}
    vwWaiting         : Boolean;         {True if wait cursor is shown}

    {property access methods}
    function GetCaretActualPos : TOvcTextPos;
    function GetCaretEffectivePos : TOvcTextPos;
    function GetCaretType : TOvcCaret;
    function GetLineLength(LineNum : LongInt) : SmallInt;
    function GetStringLine(LineNum : LongInt) : string;
    function GetTopLine : LongInt;
    procedure SetBorderStyle(BS : TBorderStyle);
    procedure SetCaretType(CT : TOvcCaret);
    procedure SetCaretActualPos(LC : TOvcTextPos);
    procedure SetCaretEffectivePos(LC : TOvcTextPos);
    procedure SetExpandTabs(E : Boolean);
    procedure SetFixedFont(FF : TOvcFixedFont);
    procedure SetLineCount(N : LongInt);
    procedure SetMarginColor(C : TColor);
    procedure SetScrollBars(SB : TScrollStyle);
    procedure SetShowBookmarks(SB : Boolean);
    procedure SetShowCaret(Value : Boolean);
    procedure SetTabSize(N : Byte);
    procedure SetTopLine(LineNum : LongInt);

    {VCL control messages}
    procedure CMColorChanged(var Msg: TMessage);
      message CM_COLORCHANGED;
    procedure CMFontChanged(var Msg: TMessage);
      message CM_FONTCHANGED;

    {windows message methods}
    procedure WMGetDlgCode(var Msg : TWMGetDlgCode);
      message WM_GETDLGCODE;
    procedure WMHScroll(var Msg : TWMScroll);
      message WM_HSCROLL;
    procedure WMKeyDown(var Msg : TWMKeyDown);
      message WM_KEYDOWN;
    procedure WMKillFocus(var Msg : TWMKillFocus);
      message WM_KILLFOCUS;
    procedure WMLButtonDown(var Msg : TWMMouse);
      message WM_LBUTTONDOWN;
    procedure WMLButtonDblClk(var Msg : TWMMouse);
      message WM_LBUTTONDBLCLK;
    procedure WMLButtonUp(var Msg : TWMMouse);
      message WM_LBUTTONUP;
    procedure WMMouseActivate(var Msg : TWMMouseActivate);
      message WM_MOUSEACTIVATE;
    procedure WMMouseMove(var Msg : TWMMouse);
      message WM_MOUSEMOVE;
    procedure WMNCHitTest(var Msg : TWMNCHitTest);
      message WM_NCHITTEST;
    procedure WMSetCursor(var Msg : TWMSetCursor);
      message WM_SETCURSOR;
    procedure WMSetFocus(var Msg : TWMSetFocus);
      message WM_SETFOCUS;
    procedure WMVScroll(var Msg : TWMScroll);
      message WM_VSCROLL;

  protected
    {private message methods}
    procedure OMShowStatus(var Msg : TOMShowStatus);
      message om_ShowStatus;

    procedure CreateParams(var Params: TCreateParams);
      override;
    procedure CreateWnd;
      override;
    procedure Paint;
      override;
    procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
      override;

    {virtual methods}
    procedure DoOnShowStatus(LineNum : LongInt; ColNum : Word);
      dynamic;
      {-call the OnShowStatus method, if assigned}
    procedure DoOnTopLineChanged(Line : LongInt);
      dynamic;
      {-perform notification of a top line changed}
    procedure DoOnUserCommand(Command : Word);
      dynamic;
      {-perform notification of a user command}
    function GetLinePtr(LineNum : LongInt; var Len : SmallInt) : PAnsiChar;
      virtual; abstract;
      {-return a pointer to the specified line}

    {general methods}
    procedure vwCalcColorFields;
    procedure vwCalcFontFields;
    function vwCaretIsVisible : Boolean;
    procedure vwChangeLineCount(N : LongInt);
    procedure vwFixedFontChanged(Sender : TObject);
    function vwGetLineEffLen(N : LongInt) : SmallInt;
    procedure vwGetMousePos(var MousePos : TOvcTextPos; XPixel, YPixel : SmallInt);
    procedure vwHighlightColorsChanged(Sender : TObject);
    procedure vwInitInternalFields;
    procedure vwInvalidateLine(LineNum : LongInt);
    procedure vwMoveCaret(HDelta : SmallInt; VDelta : LongInt;
                        MoveByPage, AmSelecting : Boolean);
    procedure vwMoveCaretPrim(HDelta : SmallInt; VDelta : LongInt;
                            MoveByPage, AmSelecting, AbsMove : Boolean);
    procedure vwMoveCaretTo(Line : LongInt; Col : SmallInt; AmSelecting : Boolean);
    procedure vwPositionCaret;
    procedure vwReadBookmarkGlyphs;
    procedure vwRefreshLines(const Start, Stop : TOvcTextPos);
    procedure vwResetHighlight(Refresh : Boolean);
    procedure vwScrollPrim(HDelta : SmallInt; VDelta : LongInt);
    procedure vwScrollPrimHorz(Delta : SmallInt);
    procedure vwScrollPrimVert(Delta : LongInt);
    procedure vwSetHScrollPos;
    procedure vwSetHScrollRange;
    procedure vwSetVScrollPos;
    procedure vwSetVScrollRange;
    procedure vwShowWaitCursor(ShowIt : Boolean);
    procedure vwUpdateHighlight(Refresh : Boolean);
  {.Z-}

    {properties}
    property BorderStyle : TBorderStyle
      read FBorderStyle
      write SetBorderStyle
      default DefBorderStyle;

    property Caret : TOvcCaret
      read GetCaretType
      write SetCaretType;

    property ExpandTabs : Boolean
      read FExpandTabs
      write SetExpandTabs
      default DefExpandTabs;

    property FixedFont : TOvcFixedFont
      read FFixedFont
      write SetFixedFont;

    property HighlightColors : TOvcColors
      read FHighlightColors
      write FHighlightColors;

    property MarginColor : TColor
      read FMarginColor
      write SetMarginColor
      default DefMarginColor;

    property ScrollBars : TScrollStyle
      read FScrollBars
      write SetScrollBars
      default DefScrollBars;

    property ShowBookmarks : Boolean
      read FShowBookmarks
      write SetShowBookmarks
      default DefShowBookmarks;

    property ShowCaret : Boolean
      read FShowCaret
      write SetShowCaret
      default DefShowCaret;

    property TabSize : Byte
      read FTabSize
      write SetTabSize
      default DefTabSize;

    {events}
    property OnShowStatus : TShowStatusEvent
       read FOnShowStatus
       write FOnShowStatus;

    property OnTopLineChanged : TTopLineChangedEvent
      read FOnTopLineChanged
      write FOnTopLineChanged;

    property OnUserCommand : TUserCommandEvent
      read FOnUserCommand
      write FOnUserCommand;

  public
    {VCL methods}
    constructor Create(AOwner : TComponent);
      override;
    destructor Destroy;
      override;

    function CheckLine(LineNum : LongInt) : LongInt;
      virtual;

    function ActualColumn(Line : LongInt; EffectiveCol : SmallInt) : SmallInt;
      {-return the actual column given the line and effective column}
    procedure ClearMarker(N : Byte);
      {-remove the specified text marker}
    procedure CopyToClipboard;
      {-copy highlighted text to the clipboard}
    function EffectiveColumn(Line : LongInt; ActualCol : SmallInt) : SmallInt;
      {-return the effective column given the line and actual column}
    function GetCaretPosition(var Col : SmallInt) : LongInt;
      {-return the current position of the caret}
    function GetLine(LineNum : LongInt; Dest : PAnsiChar; DestLen : SmallInt) : PAnsiChar;
      {-get the specified line}
    function GetMarkerPosition(N : Byte; var Col : SmallInt) : LongInt;
      {-return the current position of the specified marker}
    function GetPrintableLine(LineNum : LongInt; Dest : PAnsiChar;
                              DestLen : SmallInt) : SmallInt;
      {-get a line in a format suitable for printing}
    function GetSelection(var Line1 : LongInt; var Col1 : SmallInt;
                          var Line2 : LongInt; var Col2 : SmallInt) : Boolean;
      {-return True if any text is currently selected}
    procedure GotoMarker(N : Byte);
      {-move the caret to the specified text marker}
    function Search(const S : string; Options : TSearchOptionSet) : Boolean;
      {-search for a string returning True if found}
      virtual;
    procedure SelectAll(CaretAtEnd : Boolean);
      {-select all text in the editor}
    procedure SetCaretPosition(Line : LongInt; Col : SmallInt);
      {-move the caret to a specified line and column}
    procedure SetMarker(N : Byte);
      {-set a text marker at the current caret position}
    procedure SetMarkerAt(N : Byte; Line : LongInt; Col : SmallInt);
      {-set a text marker at the specified position}
    procedure SetSelection(Line1 : LongInt; Col1 : SmallInt;
                           Line2 : LongInt; Col2 : SmallInt;
                           CaretAtEnd : Boolean);
      {-select a region of text}

    {public properties}
    property CaretActualPos : TOvcTextPos
      read GetCaretActualPos
      write SetCaretActualPos;

    property CaretEffectivePos : TOvcTextPos
      read GetCaretEffectivePos
      write SetCaretEffectivePos;

    property Color default DefColor;

    property LineCount : LongInt
      read FLineCount
      write SetLineCount;

    property LineLength[LineNum : LongInt] : SmallInt
      read GetLineLength;

    property Lines[LineNum : LongInt] : string
      read GetStringLine;

    property TopLine : LongInt
      read GetTopLine
      write SetTopLine
      stored False;
  end;

  {.Z+}
  {TOvcTextFileViewer related definitions}
  TStringNode = class
  protected
    snNext : TStringNode;  {Points to the next node in the list}
    snPrev : TStringNode;  {Points to the previous node in the list}
    snS    : PAnsiChar;        {Points to the string}
    snSLen : Word;         {Length of snS}

    constructor Create(P : PAnsiChar);
    destructor Destroy;
      override;
    function GetS(var Len : SmallInt) : PAnsiChar;
  end;

  TVwrStringList = class
  protected
    slHead     : TStringNode;     {Start of list}
    slTail     : TStringNode;     {End of list}
    slCount    : LongInt;         {Size of list}
    slLastN    : LongInt;         {Index of last node found}
    slLastNode : TStringNode;     {Last node found}

    constructor Create;
      {-Initialize an empty list}
    destructor Destroy;
      override;
      {-Destroy the list}
    function Count : LongInt;
      {-Return the size of the list}
    procedure Append(P : TStringNode);
      {-Add a node to the end of the list}
    function Nth(N : LongInt) : TStringNode;
      {-Return a pointer to the Nth node in the list}
  end;
  {.Z-}

  TOvcCustomTextFileViewer = class(TOvcBaseViewer)
  {.Z+}
  protected {private}
    {properties}
    FFileName : PString;
    FFileSize : LongInt;

    {Other fields}
    fvLines : TVwrStringList;

    {property access methods}
    function GetFileName : string;
    function GetIsOpen : Boolean;
    procedure SetFileName(const N : string);
    procedure SetIsOpen(OpenIt : Boolean);

  protected
    function GetLinePtr(LineNum : LongInt; var Len : SmallInt) : PAnsiChar;
      override;
  {.Z-}

    {properties}
    property FileName : string
      read GetFileName
      write SetFileName;

    property IsOpen : Boolean
      read GetIsOpen
      write SetIsOpen
      default DefIsOpen;

  public
    {VCL methods}
    constructor Create(AOwner : TComponent);
      override;
    destructor Destroy;
      override;

    function CheckLine(LineNum : LongInt) : LongInt;
      override;

    {public properties}
    property FileSize : LongInt
       read FFileSize;
  end;

type
  TOvcTextFileViewer = class(TOvcCustomTextFileViewer)
  published
    {properties}
    property BorderStyle;
    property Caret;
    property Controller;
    property ExpandTabs;
    property FileName;
    property FixedFont;
    property HighlightColors;
    property IsOpen;
    property MarginColor;
    property ScrollBars;
    property ShowBookmarks;
    property ShowCaret;
    property TabSize;

    property Align;
    property Color;
    property Ctl3D;
    property DragCursor;
    property DragMode;
    property ParentColor;
    property ParentCtl3D;
    property ParentShowHint;
    property PopupMenu;
    property ShowHint;
    property TabOrder;
    property TabStop default DefTabStop;
    property Visible;

    {events}
    property OnShowStatus;
    property OnTopLineChanged;
    property OnUserCommand;

    property OnClick;
    property OnDblClick;
    property OnDragDrop;
    property OnDragOver;
    property OnEndDrag;
    property OnEnter;
    property OnExit;
    property OnKeyDown;
    property OnKeyPress;
    property OnKeyUp;
    property OnMouseDown;
    property OnMouseMove;
    property OnMouseUp;
    {$IFDEF Win32}
    property OnStartDrag;
    {$ENDIF}
  end;

{.Z+}
{TOvcFileViewer related definitions}
type
  PfvBufferArray = ^TfvBufferArray;
  TfvBufferArray = array [0..65520] of Char;

  TfvPageRec = record
    BlockNum : Word;              {BlkNum * fvBufSize = file pos of block start}
    ByteCount: Cardinal;          {Number of Bytes used in buffer}
    LastUsed : Word;              {Quasi-time when last accessed}
    Buffer   : PfvBufferArray;    {Points to page buffer}
  end;

const
  MaxPageArrayElements = Pred($10000 div sizeof(TfvPageRec));

type
  PfvPageArray = ^TfvPageArray;
  TfvPageArray = array[0..Pred(MaxPageArrayElements)] of TfvPageRec;
{.Z-}

type
  TOvcCustomFileViewer = class(TOvcBaseViewer)
  {.Z+}
  protected {private}
    {properties}
    FBufferPageCount : SmallInt;    {Number of pages in fvPages}
    FFileName        : PString;     {Name of file}
    FFileSize        : LongInt;     {File size of file if open, else 0}
    FFilterChars     : Boolean;     {True if filtering 'bad' chars}
    FInHexMode       : Boolean;     {True if displaying in Hex}
    FIsOpen          : Boolean;     {True if file is open}

    {other fields}
    fvCurLine        : LongInt;     {Current line in file           (not used in hex mode)}
    fvCurOffset      : LongInt;     {Offset of start of fvCurLine   (not used in hex mode)}
    fvKnownLine      : LongInt;     {Some known line number         (not used in hex mode)}
    fvKnownOffset    : LongInt;     {Offset of start of fvKnownLine (not used in hex mode)}
    fvLastLine       : LongInt;     {Final line number in file}
    fvLastLine2      : LongInt;     {Final line number in 'other' mode (text/hex)}
    fvLastLineOffset : LongInt;     {Offset of start of fvLastLine  (not used in hex mode)}
    fvLnBuf          : PAnsiChar;   {Line buffer}
    fvLineInBuf      : LongInt;     {Line currently in fvLnBuf}
    fvLnBufLen       : SmallInt;    {Length of line currently in fvLnBuf}
    fvMaxPage        : SmallInt;    {Max page number in fvPages}
    fvNewLine        : LongInt;     {Newest line in file            (not used in hex mode)}
    fvNewOffset      : LongInt;     {Offset of start of fvNewLine   (not used in hex mode)}
    fvPageArraySize  : Word;        {Size of the page array}
    fvPages          : PfvPageArray;{Array of page buffers, 0..fvMaxPage}
    fvTicks          : Word;        {Quasi-time, for page buffer replacement}
    fvWorkBeg        : Integer;     {First valid offset of fvWorkPtr}   {actual ptr in 32-bit}
    fvWorkBlk        : Word;        {Working block number}
    fvWorkEnd        : Cardinal;    {Next invalid offset of fvWorkPtr}  {actual ptr in 32-bit}
    fvWorkOffset     : LongInt;     {Working file position}
    fvWorkPtr        : ^AnsiChar;   {Pointer to working character}

    {property access methods}
    function GetFileName : string;
    procedure SetBufferPageCount(BPC : SmallInt);
    procedure SetFileName(const N : string);
    procedure SetFilterChars(FC : Boolean);
    procedure SetInHexMode(HM : Boolean);
    procedure SetIsOpen(OpenIt : Boolean);

    {general methods}
    procedure fvDeallocateBuffers;
    function fvGetLineAsText(LineNum : LongInt; var Len : SmallInt) : PAnsiChar;
    function fvGetLineInHex(LineNum : LongInt; var Len : SmallInt) : PAnsiChar;
    function fvGetWorkingChar : Boolean;
    procedure fvGetWorkingPage;
    procedure fvGotoHexLine(Line : LongInt);
    procedure fvGotoTextLine(Line : LongInt);
    procedure fvInitFileFields;
    procedure fvInitObjectFields;
    procedure fvNewWorkingSet;

  protected
    {virtual methods}
    function GetLinePtr(LineNum : LongInt; var Len : SmallInt) : PAnsiChar;
      override;
  {.Z-}

    {properties}
    property BufferPageCount : SmallInt
      read FBufferPageCount
      write SetBufferPageCount
      default DefBufferPageCount;

    property FileName : string
      read GetFileName
      write SetFileName;

    property FilterChars : Boolean
      read FFilterChars
      write SetFilterChars
      default DefFilterChars;

    property InHexMode : Boolean
      read FInHexMode
      write SetInHexMode
      default DefHexMode;

    property IsOpen : Boolean
      read FIsOpen
      write SetIsOpen
      default DefIsOpen;

  public
    {VCL methods}
    constructor Create(AOwner : TComponent);
      override;
    destructor Destroy;
      override;

    {other methods}
    function CheckLine(LineNum : LongInt) : LongInt;
      override;
    function Search(const S : string; Options : TSearchOptionSet) : Boolean;
      {-search for a string returning True if found}
      override;

    {public properties}
    property FileSize : LongInt
      read FFileSize;
  end;

type
  TOvcFileViewer = class(TOvcCustomFileViewer)
  published
    {properties}
    property BorderStyle;
    property BufferPageCount;
    property Caret;
    property Controller;
    property ExpandTabs;
    property FileName;
    property FilterChars;
    property FixedFont;
    property InHexMode;
    property HighlightColors;
    property IsOpen;
    property MarginColor;
    property ScrollBars;
    property ShowBookmarks;
    property ShowCaret;
    property TabSize;

    property Align;
    property Color;
    property Ctl3D;
    property DragCursor;
    property DragMode;
    property ParentColor;
    property ParentCtl3D;
    property ParentShowHint;
    property PopupMenu;
    property ShowHint;
    property TabOrder;
    property TabStop default DefTabStop;
    property Visible;

    {events}
    property OnShowStatus;
    property OnTopLineChanged;
    property OnUserCommand;

    property OnClick;
    property OnDblClick;
    property OnDragDrop;
    property OnDragOver;
    property OnEndDrag;
    property OnEnter;
    property OnExit;
    property OnKeyDown;
    property OnKeyPress;
    property OnKeyUp;
    property OnMouseDown;
    property OnMouseMove;
    property OnMouseUp;
  end;


implementation
