
{*******************************************************}
{                                                       }
{       RichViewActions                                 }
{       Main RichViewActions unit                       }
{                                                       }
{       Copyright (c) 2002-2008, Sergey Tkachenko       }
{       svt@trichview.com                               }
{       http://www.trichview.com                        }
{                                                       }
{*******************************************************}

unit RichViewActions;


{$I RichViewActions.inc}

{
  See history.txt
  ----------------------------------------------------------------------------
  TrvCustomAction
    TrvAction - base action                    : MH
      TrvActionNew
        TrvActionOpen
      TrvActionSave
      TrvActionCustomIO
        TrvActionCustomFileIO
          TrvActionSaveAs
          TrvActionExport
          TrvActionInsertFile
        TrvActionInsertPicture
      TrvActionFind
      TrvActionFindNext
      TrvActionReplace
      TrvCustomEditAction
        TrvActionUndo                            : MH
        TrvActionCut                             : MH
        TrvActionCopy                            : MH
        TrvActionPaste                           : MH
          TrvActionPasteSpecial
        TrvActionPasteAsText
      TrvActionRedo                            : MH
      TrvActionCharCase
      TrvActionTextStyles
        TrvActionFonts                           : MB
          TrvActionFontEx
        TrvActionSSScript
          TrvActionSubscript
          TrvActionSuperscript
        TrvActionTextBiDi
          TrvActionTextLTR
          TrvActionTextRTL
        TrvActionFontStyle                       : MH, MB
          TrvActionFontBold                      : MH, MB
          TrvActionFontItalic                    : MH, MB
          TrvActionFontUnderline                 : MH, MB
          TrvActionFontStrikeout                 : MH, MB
        TrvActionFontStyleEx
          TrvActionFontAllCaps
          TrvActionFontOverline
        TrvActionFontShrinkGrow
          TrvActionFontGrow
          TrvActionFontShrink
        TrvActionFontGrowOnePoint
        TrvActionFontShrinkOnePoint
        TRVActionInsertHyperlink
        TRVActionHide
      TRVActionRemoveHyperlinks
      TrvActionInsertTable                     : MH

      TrvCustomPrintAction
        TrvActionPrintPreview                  : MB
        TrvActionQuickPrint
        TrvActionPrint                         : MB
      TrvActionParaStyles                      : MB
        TrvActionLineSpacing
          TrvActionLineSpacing100
          TrvActionLineSpacing150
          TrvActionLineSpacing200
        TrvActionParaBorder
        TrvActionAlignment                     : MB
          TrvActionAlignLeft                   : MB
          TrvActionAlignRight                  : MB
          TrvActionAlignCenter                 : MB
          TrvActionAlignJustify
        TrvActionParaBiDi
          TrvActionParaLTR
          TrvActionParaRTL
        TrvActionIndent
          TrvActionIndentInc                   : MB
          TrvActionIndentDec                   : MB
        TrvActionParagraph
        TrvActionWordWrap                      : MB
      TrvActionSelectAll                       : MB
      TrvActionItemProperties
      TrvActionVAlign
      TRVActionInsertHLine
      TrvActionInsertSymbol

      TrvActionFillColor
      TrvActionCustomColor
        TrvActionFontCustomColor
          TrvActionFontColor;
          TrvActionFontBackColor;
        TrvActionParaCustomColor
          TrvActionParaColor;
        TrvActionColor;
      TrvActionBackground

      TrvActionParaList
      TrvActionCustomParaListSwitcher
        TrvActionParaBullets
        TrvActionParaNumbering

      TrvActionTableCell
        TrvActionTableRCBase
          TrvActionTableInsertRowsAbove
          TrvActionTableInsertRowsBelow
          TrvActionTableInsertColLeft
          TrvActionTableInsertColRight
          TrvActionTableDeleteRows
          TrvActionTableDeleteCols
          TrvActionTableSelectRows
          TrvActionTableSelectCols
        TrvActionTableMergeCells
        TrvActionTableSplitCells
        TrvActionTableSelectTable
        TrvActionTableSelectCell
        TrvActionTableProperties
        TrvActionTableMultiCellAttributes
          TrvActionTableCellVAlign
            TrvActionTableCellVAlignTop
            TrvActionTableCellVAlignMiddle
            TrvActionTableCellVAlignBottom
            TrvActionTableCellVAlignDefault
          TrvActionTableCellBorder
            TrvActionTableCellLeftBorder
            TrvActionTableCellRightBorder
            TrvActionTableCellTopBorder
            TrvActionTableCellBottomBorder
            TrvActionTableCellAllBorders
            TrvActionTableCellNoBorders
      TrvActionInsertPageBreak
      TrvActionRemovePageBreak
      TrvActionClearTextFlow
        TrvActionClearLeft
        TrvActionClearRight
        TrvActionClearNone
        TrvActionClearBoth
    TrvActionTableGrid
    TrvActionPageSetup      
  ----------------------------------------------------------------------------

  TRichViewEdit Actions

  These components are freely distributable in source form provided all copyrights
  and acknowledgements remain intact.  Authors would also appreciate receiving
  notification of all changes, improvements or additions made to these components.

  You can use these components in any project, including commercial applications.

  RichViewActions are based on work made by
    Matt Harward, Phat Rock Ventures, LLC (MH) mharward@phatrock.com
    Michael Beck (MB) mbeck1@compuserve.com
  Actions initially created by these authors are marked with MH or MB in
  the list above.
  ----------------------------------------------------------------------------
}

interface

{$I RV_Defs.inc}

uses
  Windows, Messages, Classes, Graphics, SysUtils, Controls, StdCtrls,
  Printers, Dialogs, Forms, ShellApi, Clipbrd,
  {$IFDEF RICHVIEWDEF6}
  DateUtils,
  {$ENDIF}
  RichView, rvrvData, rvEdit, ActnList, RVTable,
  RVItem, RVStyle, RVTInplace, rvScroll, RVUni, PtblRV, RVERVData, RVMisc,
  {$IFDEF USERVXML}
  RichViewXML,
  {$ENDIF}
  RVNormalize,
  {$IFDEF USERVHTML}
  RVHTMLImport,
  {$ENDIF}
  {$IFDEF USERVHTMLVIEWER}
  rvHtmlViewImport,
  {$ENDIF}
  {$IFDEF USERVADDICT3}
  ad3RichViewCmpnts,  ad3SpellBase,
  {$ENDIF}
  {$IFDEF USERVKSDEVTE}
  te_controls, te_forms,
  {$ENDIF}
  {$IFDEF USEINDY}
  idhttp,
  {$ENDIF}
  {$IFDEF USECLEVERCOMPONENTS}
  clHttp,
  {$ENDIF}
  {$IFDEF USEJVCL}
  JvWinDialogs,
  {$ENDIF}
  {$IFDEF USETB2K}
  TB2Item,
  {$ENDIF}
  {$IFDEF USETBX}
  TBX,
  {$ENDIF}
  {$IFDEF USESPTBX}
  SpTBXItem, SpTBXSkins,
  {$ENDIF}
  CRVData, RVClasses,RVOfficeCnv, RVDocParams, ExtDlgs, RVFuncs, Menus,
  {$IFDEF USERVTNT}
  TntClasses, TntActnList, TntStdActns, TntDialogs, TntStdCtrls, TntMenus,
  {$ENDIF}
  RVALocalize, RVTypes;

type


  TrvFileImportFilter = (ffiRVF, ffiRTF, {$IFDEF USERVXML}ffiXML,{$ENDIF} ffiTextANSI, ffiTextUnicode, ffiTextAuto, ffiCustom, {$IFDEF RVAHTML}ffiHTML,{$ENDIF} ffiOfficeConverters);
  TrvFileOpenFilter = ffiRVF..{$IFDEF USERVHTMLVIEWER}ffiHTML{$ELSE}ffiCustom{$ENDIF};
  TrvFileExportFilter = (ffeRVF, ffeRTF, {$IFDEF USERVXML}ffeXML,{$ENDIF} ffeTextANSI, ffeTextUnicode, ffeCustom, ffeHTMLCSS, ffeHTML,
    ffeOfficeConverters);
  TrvFileSaveFilter = ffeRVF..{$IFDEF USERVHTMLVIEWER}ffeHTMLCSS{$ELSE}ffeCustom{$ENDIF};

  TrvFileImportFilterSet = set of TrvFileImportFilter;
  TrvFileOpenFilterSet   = set of TrvFileOpenFilter;
  TrvFileExportFilterSet = set of TrvFileExportFilter;
  TrvFileSaveFilterSet   = set of TrvFileSaveFilter;

  TrvPaperMarginsUnits = (rvpmuMillimeters, rvpmuInches);

  TrvaColorInterface = (rvacNone, rvacColorDialog, rvacAdvanced);

  TRVFileChangeEvent = procedure (Sender: TObject;
    Editor: TCustomRichViewEdit; const FileName: String;
    FileFormat: TrvFileSaveFilter; IsNew: Boolean) of object;

  TRVOpenFileEvent = procedure (Sender: TObject;
    Editor: TCustomRichViewEdit; const FileName: String;
    FileFormat: TrvFileOpenFilter; CustomFilterIndex: Integer) of object;

  TRVSaveFileEvent = procedure (Sender: TObject;
    Editor: TCustomRichViewEdit; const FileName: String;
    FileFormat: TrvFileSaveFilter; CustomFilterIndex: Integer) of object;


  TRVAEditorControlCommand = (rvaeccIsEditorControl, rvaeccHasSelection,
    rvaeccCanPaste, rvaeccCanPasteText, rvaeccCanUndo, rvaeccCopy, rvaeccCut,
    rvaeccPaste, rvaeccPasteText, rvaeccUndo);

  TRVCustomItemPropertiesDialog = procedure (Sender: TObject;
    Editor: TCustomRichViewEdit; var DoDefault: Boolean) of object;

  TRVAEvent = procedure(Sender: TObject;
    Editor: TCustomRichViewEdit) of object;

  TRVGetFormClassEvent = procedure (Sender: TObject;
    var FormClass: TFormClass) of object;

  TRVAUserInterface = (rvauiFull, rvauiHTML, rvauiRTF, rvauiText);

  THFInfo = class
    private
     FFont: TFont;
      procedure SetFont(const Value: TFont);
    public
      Text: String;
      Alignment: TAlignment;
      PrintOnFirstPage: Boolean;
      constructor Create;
      destructor Destroy; override;
      property Font: TFont read FFont write SetFont;
  end;


  TrvAction = class;
  TrvCustomAction = class;  
  TRVAPopupMenu = class;

  TRVStyleNeededEvent = procedure (Sender: TrvAction; RVStyle: TRVStyle;
    StyleInfo: TCustomRVInfo; var StyleNo: Integer) of object;
  TRVAddStyleEvent = procedure (Sender: TrvAction; StyleInfo: TCustomRVInfo) of object;
  TRVAEditEvent = procedure (Sender: TrvAction; Edit: TCustomRichViewEdit) of object;
  TRVAEditEvent2 = procedure (Sender: TrvCustomAction; Edit: TCustomRichViewEdit) of object;  
  {$IFDEF USERVKSDEVTE}
  TRVCreateTeFormEvent = procedure (Sender: TForm; teForm: TTeForm) of object;
  {$ENDIF}
  TRVAFileOperation = (rvafoOpen, rvafoSave, rvafoExport, rvafoInsert);
  TRVCustomFileOperationEvent = procedure (Sender: TrvAction; Edit: TCustomRichViewEdit;
    const FileName: String; Operation: TRVAFileOperation;
    var SaveFormat: TrvFileSaveFilter;
    var CustomFilterIndex: Integer; var Success: Boolean) of object;
  TRVADownloadEvent = procedure (Sender: TrvAction; const Source: String) of object;

  TRVALiveSpellGetSuggestionsEvent = procedure (Sender: TRVAPopupMenu;
    Edit: TCustomRichViewEdit; const Word: String; StyleNo: Integer;
    Suggestions: TStrings) of object;
  TRVALiveSpellIgnoreAllEvent = procedure (Sender: TRVAPopupMenu;
    Edit: TCustomRichViewEdit; const Word: String; StyleNo: Integer) of object;
  TRVALiveSpellAddEvent = procedure (Sender: TRVAPopupMenu;
    Edit: TCustomRichViewEdit; const Word: String; StyleNo: Integer) of object;
  TRVALiveSpellReplaceEvent = procedure (Sender: TRVAPopupMenu;
    Edit: TCustomRichViewEdit; const Word, Correction: String; StyleNo: Integer) of object;

  {$IFDEF USETB2K}
  TRVA2LiveSpellGetSuggestionsEvent = procedure (Sender: TObject;
    Edit: TCustomRichViewEdit; const Word: String; StyleNo: Integer;
    Suggestions: TStrings) of object;
  TRVA2LiveSpellIgnoreAllEvent = procedure (Sender: TObject;
    Edit: TCustomRichViewEdit; const Word: String; StyleNo: Integer) of object;
  TRVA2LiveSpellAddEvent = procedure (Sender: TObject;
    Edit: TCustomRichViewEdit; const Word: String; StyleNo: Integer) of object;
  TRVA2LiveSpellReplaceEvent = procedure (Sender: TObject;
    Edit: TCustomRichViewEdit; const Word, Correction: String; StyleNo: Integer) of object;
  {$ENDIF}

  TRVASearchScope = (rvssFromCursor, rvssAskUser, rvssGlobal);

  TRVAControlPanel = class (TComponent)
  private
    function GetDialogFontName: TFontName;
    function GetDialogFontSize: Integer;
    function GetUseXPThemes: Boolean;
    procedure SetDialogFontName(const Value: TFontName);
    procedure SetDialogFontSize(Value: Integer);
    procedure SetUseXPThemes(const Value: Boolean);
    function GetDefaultControl: TCustomRichViewEdit;
    procedure SetDefaultControl(const Value: TCustomRichViewEdit);
    function GetColorDialog: TColorDialog;
    procedure SetColorDialog(const Value: TColorDialog);
    function GetTableGridStyle: TPenStyle;
    procedure SetTableGridStyle(const Value: TPenStyle);
    function GetRVFFilter: String;
    procedure SetRVFFilter(const Value: String);
    {$IFDEF USERVXML}
    procedure SetXMLFilter(const Value: String);
    function GetXMLFilter: String;
    procedure SetRVXML(const Value: TRichViewXML);
    function GetRVXML: TRichViewXML;
    {$ENDIF}
    {$IFDEF USERVHTML}
    function GetRVHTML: TRvHtmlImporter;
    procedure SetRVHTML(const Value: TRvHtmlImporter);
    {$ENDIF}
    {$IFDEF USERVHTMLVIEWER}
    function GetRVHTMLView: TRVHTMLViewImporter;
    procedure SetRVHTMLView(const Value: TRVHTMLViewImporter);
    {$ENDIF}
    {$IFDEF USEINDY}
    function GetIdHTTP: TIdHTTP;
    procedure SetIdHTTP(const Value: TIdHTTP);
    {$ENDIF}
    {$IFDEF USECLEVERCOMPONENTS}
    function GetClHTTP: TClHTTP;
    procedure SetClHTTP(const Value: TClHTTP);
    {$ENDIF}
    {$IFDEF USERVADDICT3}
    function GetRVAddictSpell3: TRVAddictSpell3;
    function GetRVAddictThesaurus3: TRVThesaurus3;
    procedure SetRVAddictSpell3(const Value: TRVAddictSpell3);
    procedure SetRVAddictThesaurus3(const Value: TRVThesaurus3);
    {$ENDIF}
    function GetDefaultExt: String;
    procedure SetDefaultExt(const Value: String);
    function GetRVFormatName: String;
    procedure SetRVFormatName(const Value: String);
    function GetDefaultFileName: String;
    procedure SetDefaultFileName(const Value: String);
    function GetAutoDeleteUnusedStyles: Boolean;
    procedure SetAutoDeleteUnusedStyles(const Value: Boolean);
    function GetDefaultColor: TColor;
    function GetDefaultMargin: Integer;
    procedure SetDefaultColor(const Value: TColor);
    procedure SetDefaultMargin(const Value: Integer);
    function GetRVPrint: TRVPrint;
    function GetShowSoftPageBreaks: Boolean;
    procedure SetRVPrint(const Value: TRVPrint);
    procedure SetShowSoftPageBreaks(const Value: Boolean);
    function GetLanguage: TRVALanguageName;
    procedure SetLanguage(const Value: TRVALanguageName);
    function GetActionsEnabled: Boolean;
    procedure SetActionsEnabled(const Value: Boolean);
    function GetRVFLocalizable: Boolean;
    function GetXMLLocalizable: Boolean;
    procedure SetRVFLocalizable(const Value: Boolean);
    procedure SetXMLLocalizable(const Value: Boolean);
    function GetFirstPageNumber: Integer;
    procedure SetFirstPageNumber(Value: Integer);
    function GetUseHelpFiles: Boolean;
    procedure SetUseHelpFiles(const Value: Boolean);
    function GetAddColorNameToHints: Boolean;
    procedure SetAddColorNameToHints(const Value: Boolean);
    function GetOnAddStyle: TRVAddStyleEvent;
    procedure SetOnAddStyle(const Value: TRVAddStyleEvent);
    function GetOnStyleNeeded: TRVStyleNeededEvent;
    procedure SetOnStyleNeeded(const Value: TRVStyleNeededEvent);
    function GetOnMarginsChanged: TRVAEditEvent;
    procedure SetOnMarginsChanged(const Value: TRVAEditEvent);
    function GetOnViewChanged: TRVAEditEvent2;
    procedure SetOnViewChanged(const Value: TRVAEditEvent2);
    {$IFDEF USERVKSDEVTE}
    function GetOnCreateTeForm: TRVCreateTeFormEvent;
    procedure SetOnCreateTeForm(const Value: TRVCreateTeFormEvent);
    {$ENDIF}
    function GetOnCustomFileOperation: TRVCustomFileOperationEvent;
    procedure SetOnCustomFileOperation(
      const Value: TRVCustomFileOperationEvent);
    function GetOnDownload: TRVADownloadEvent;
    procedure SetOnDownload(const Value: TRVADownloadEvent);
    function GetSearchScope: TRVASearchScope;
    procedure SetSearchScope(const Value: TRVASearchScope);
    function GetDefaultFileFormat: TrvFileSaveFilter;
    procedure SetDefaultFileFormat(const Value: TrvFileSaveFilter);
    function GetDefaultCustomFilterIndex: Integer;
    procedure SetDefaultCustomFilterIndex(const Value: Integer);
    function GetOnBackgroundChange: TRVAEditEvent;
    procedure SetOnBackgroundChange(const Value: TRVAEditEvent);
    function GetUserInterface: TRVAUserInterface;
    procedure SetUserInterface(const Value: TRVAUserInterface);
    {$IFNDEF RVDONOTUSEDOCPARAMS}
    function GetDefaultDocParameters: TRVDocParameters;
    procedure SetDefaultDocParameters(const Value: TRVDocParameters);
    {$ENDIF}
    function GetUnits: TRVUnits;
    procedure SetUnits(const Value: TRVUnits);
    function GetPixelBorders: Boolean;
    procedure SetPixelBorders(const Value: Boolean);
    function GetUnitsProgram: TRVStyleUnits;
    procedure SetUnitsProgram(const Value: TRVStyleUnits);
  protected
    procedure Notification(AComponent: TComponent; Operation: TOperation); override;
    procedure Loaded; override;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    property FirstPageNumber: Integer read GetFirstPageNumber write SetFirstPageNumber;
  published
    property UseXPThemes: Boolean read GetUseXPThemes write SetUseXPThemes default True;
    property DialogFontName: TFontName read GetDialogFontName write SetDialogFontName;
    property DialogFontSize: Integer read GetDialogFontSize write SetDialogFontSize default 8;
    property DefaultControl: TCustomRichViewEdit read GetDefaultControl write SetDefaultControl;
    property ColorDialog: TColorDialog read GetColorDialog write SetColorDialog;
    property TableGridStyle: TPenStyle read GetTableGridStyle write SetTableGridStyle default psDot;
    property RVFFilter: String read GetRVFFilter write SetRVFFilter;
    property DefaultExt: String read GetDefaultExt write SetDefaultExt;
    property RVFormatTitle: String read GetRVFormatName write SetRVFormatName;
    property DefaultFileName: String read GetDefaultFileName write SetDefaultFileName;
    property DefaultFileFormat: TrvFileSaveFilter read GetDefaultFileFormat write SetDefaultFileFormat default ffeRVF;
    property DefaultCustomFilterIndex: Integer read GetDefaultCustomFilterIndex write SetDefaultCustomFilterIndex default 1;
    property AutoDeleteUnusedStyles: Boolean read GetAutoDeleteUnusedStyles write SetAutoDeleteUnusedStyles default True;
    {$IFDEF USERVXML}
    property XMLFilter: String read GetXMLFilter write SetXMLFilter;
    property RVXML: TRichViewXML read GetRVXML write SetRVXML;
    {$ENDIF}
    {$IFDEF USERVADDICT3}
    property RVAddictSpell3: TRVAddictSpell3 read GetRVAddictSpell3 write SetRVAddictSpell3;
    property RVAddictThesaurus3: TRVThesaurus3 read GetRVAddictThesaurus3 write SetRVAddictThesaurus3;
    {$ENDIF}
    {$IFDEF USERVHTML}
    property RVHTMLImporter: TRvHtmlImporter read GetRVHTML write SetRVHTML;
    {$ENDIF}
    {$IFDEF USERVHTMLVIEWER}
    property RVHTMLViewImporter: TRVHTMLViewImporter read GetRVHTMLView write SetRVHTMLView;
    {$ENDIF}
    {$IFDEF USEINDY}
    property IdHTTP: TIdHTTP read GetIdHTTP write SetIdHTTP;
    {$ENDIF}
    {$IFDEF USECLEVERCOMPONENTS}
    property ClHTTP: TClHTTP read GetClHTTP write SetClHTTP;
    {$ENDIF}
    property ActionsEnabled: Boolean read GetActionsEnabled write SetActionsEnabled default True;
    property UseHelpFiles: Boolean read GetUseHelpFiles write SetUseHelpFiles default True;
    property AddColorNameToHints: Boolean read GetAddColorNameToHints write SetAddColorNameToHints default True;
    property DefaultMargin: Integer read GetDefaultMargin write SetDefaultMargin default 5;
    property DefaultColor: TColor read GetDefaultColor write SetDefaultColor default clWindow;
    {$IFNDEF RVDONOTUSEDOCPARAMS}
    property DefaultDocParameters: TRVDocParameters read GetDefaultDocParameters write SetDefaultDocParameters;
    {$ENDIF}
    property RVPrint: TRVPrint read GetRVPrint write SetRVPrint;
    property ShowSoftPageBreaks: Boolean read GetShowSoftPageBreaks write SetShowSoftPageBreaks default True;
    property Language: TRVALanguageName read GetLanguage write SetLanguage;
    property RVFLocalizable: Boolean read GetRVFLocalizable write SetRVFLocalizable default True;
    property XMLLocalizable: Boolean read GetXMLLocalizable write SetXMLLocalizable default True;
    property OnStyleNeeded: TRVStyleNeededEvent read GetOnStyleNeeded write SetOnStyleNeeded;
    property OnAddStyle: TRVAddStyleEvent read GetOnAddStyle write SetOnAddStyle;
    property OnMarginsChanged: TRVAEditEvent read GetOnMarginsChanged write SetOnMarginsChanged;
    property OnViewChanged: TRVAEditEvent2 read GetOnViewChanged write SetOnViewChanged;
    property OnCustomFileOperation: TRVCustomFileOperationEvent read GetOnCustomFileOperation write SetOnCustomFileOperation;
    property OnDownload: TRVADownloadEvent read GetOnDownload write SetOnDownload;
    property OnBackgroundChange: TRVAEditEvent read GetOnBackgroundChange write SetOnBackgroundChange;
    {$IFDEF USERVKSDEVTE}
    property OnCreateTeForm: TRVCreateTeFormEvent read GetOnCreateTeForm write SetOnCreateTeForm;
    {$ENDIF}
    property SearchScope: TRVASearchScope read GetSearchScope write SetSearchScope default rvssAskUser;
    property UserInterface: TRVAUserInterface read GetUserInterface write SetUserInterface default rvauiFull;
    property UnitsDisplay: TRVUnits read GetUnits write SetUnits default rvuPixels;
    property UnitsProgram: TRVStyleUnits read GetUnitsProgram write SetUnitsProgram default rvstuPixels;
    property PixelBorders: Boolean read GetPixelBorders write SetPixelBorders default False;
  end;

  IRVAPopupMenu = interface
    function GetPopupComponent: TComponent;
    function GetActionList: TCustomActionList;
    procedure SetActionList(const Value: TCustomActionList);
    function GetMaxSuggestionsCount: Integer;
    procedure SetMaxSuggestionsCount(Value: Integer);
    procedure ClearItems;
    procedure AddActionItem(Action: TAction; const Caption: String='');
    procedure AddSeparatorItem;
    procedure DeleteLastSeparatorItem;
    function GetItemCaption(Sender: TObject): string;
    {$IFNDEF RVDONOTUSELIVESPELL}
    procedure AddClickItem(Click: TNotifyEvent; const Caption: String;
      Charset: TFontCharset; Enabled, Default: Boolean);
    function WantLiveSpellGetSuggestions: Boolean;
    procedure LiveSpellGetSuggestions(Edit: TCustomRichViewEdit; const Word: String; StyleNo: Integer;
      Suggestions: TStrings);
    procedure LiveSpellWordReplace(Edit: TCustomRichViewEdit; const Word, Correction: String; StyleNo: Integer);
    function WantLiveSpellIgnoreAll: Boolean;
    procedure LiveSpellIgnoreAll(Edit: TCustomRichViewEdit; const Word: String; StyleNo: Integer);
    function WantLiveSpellAdd: Boolean;
    procedure LiveSpellAdd(Edit: TCustomRichViewEdit; const Word: String; StyleNo: Integer);
    {$ENDIF}
  end;

  TRVAPopupMenuHelper = class
  private
    FPopupMenu: IRVAPopupMenu;
    FActionList: TCustomActionList;
    {$IFNDEF RVDONOTUSELIVESPELL}
    FStyleNo: Integer;
    {$ENDIF}
    FMaxSuggestionsCount: Integer;
  public
    function FindAction(ActionClass: TClass): TrvAction;
    procedure AddAction(ActionClass: TClass; const Caption: String='');
    {$IFNDEF RVDONOTUSELIVESPELL}
    function GetSuggestions(const Word: String; StyleNo: Integer): TStringList;
    procedure CorrectMisspelling(Sender: TObject);
    procedure OnIgnoreAll(Sender: TObject);
    procedure OnAddToDict(Sender: TObject);
    {$ENDIF}
    procedure PreparePopup(X, Y: Integer);
    constructor Create(APopupMenu: IRVAPopupMenu); virtual;
    destructor Destroy; override;
    property ActionList: TCustomActionList read FActionList write FActionList;
    property MaxSuggestionsCount: Integer read FMaxSuggestionsCount write FMaxSuggestionsCount;
  end;

  {$IFDEF USERVTNT}
  TRVAPopupMenuBase = TTntPopupMenu;
  TRVAPopupMenuItem = TTntMenuItem;
  TRVAMessageBox = function(const Text, Caption: WideString; Flags: Longint): Integer;
  {$ELSE}
  TRVAPopupMenuBase = TPopupMenu;
  TRVAPopupMenuItem = TMenuItem;
  TRVAMessageBox = function(const Text, Caption: String; Flags: Longint): Integer;  
  {$ENDIF}

  TRVAPopupMenu = class (TRVAPopupMenuBase, IRVAPopupMenu)
  private
    FPopupMenuHelper: TRVAPopupMenuHelper;
    FOnLiveSpellGetSuggestions: TRVALiveSpellGetSuggestionsEvent;
    FOnLiveSpellAdd: TRVALiveSpellAddEvent;
    FOnLiveSpellIgnoreAll: TRVALiveSpellIgnoreAllEvent;
    FOnLiveSpellWordReplace: TRVALiveSpellReplaceEvent;
  protected
    { IRVAPopupMenu }
    function GetPopupComponent: TComponent;
    function GetActionList: TCustomActionList;
    procedure SetActionList(const Value: TCustomActionList);
    function GetMaxSuggestionsCount: Integer;
    procedure SetMaxSuggestionsCount(Value: Integer);
    procedure ClearItems;
    procedure AddActionItem(Action: TAction; const Caption: String='');
    procedure AddSeparatorItem;
    procedure DeleteLastSeparatorItem;
    function GetItemCaption(Sender: TObject): string;
    {$IFNDEF RVDONOTUSELIVESPELL}
    procedure AddClickItem(Click: TNotifyEvent; const Caption: String;
      Charset: TFontCharset; Enabled, Default: Boolean);
    function WantLiveSpellGetSuggestions: Boolean;
    procedure LiveSpellGetSuggestions(Edit: TCustomRichViewEdit; const Word: String; StyleNo: Integer;
      Suggestions: TStrings);
    procedure LiveSpellWordReplace(Edit: TCustomRichViewEdit; const Word, Correction: String; StyleNo: Integer);
    function WantLiveSpellIgnoreAll: Boolean;
    procedure LiveSpellIgnoreAll(Edit: TCustomRichViewEdit; const Word: String; StyleNo: Integer);
    function WantLiveSpellAdd: Boolean;
    procedure LiveSpellAdd(Edit: TCustomRichViewEdit; const Word: String; StyleNo: Integer);
    {$ENDIF}
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure Notification(AComponent: TComponent; Operation: TOperation); override;
    procedure Popup(X,Y: Integer); override;
  published
    property ActionList: TCustomActionList read GetActionList write SetActionList;
    property OnLiveSpellGetSuggestions: TRVALiveSpellGetSuggestionsEvent
      read FOnLiveSpellGetSuggestions write FOnLiveSpellGetSuggestions;
    property OnLiveSpellIgnoreAll: TRVALiveSpellIgnoreAllEvent
      read FOnLiveSpellIgnoreAll write FOnLiveSpellIgnoreAll;
    property OnLiveSpellAdd: TRVALiveSpellAddEvent
      read FOnLiveSpellAdd write FOnLiveSpellAdd;
    property OnLiveSpellWordReplace: TRVALiveSpellReplaceEvent
      read FOnLiveSpellWordReplace write FOnLiveSpellWordReplace;
    property MaxSuggestionsCount: Integer read GetMaxSuggestionsCount write SetMaxSuggestionsCount default 0;
  end;

  {$IFDEF USETB2K}
  TRVATBPopupMenu = class (TTBPopupMenu, IRVAPopupMenu)
  private
    FPopupMenuHelper: TRVAPopupMenuHelper;
    FOnLiveSpellGetSuggestions: TRVA2LiveSpellGetSuggestionsEvent;
    FOnLiveSpellAdd: TRVA2LiveSpellAddEvent;
    FOnLiveSpellIgnoreAll: TRVA2LiveSpellIgnoreAllEvent;
    FOnLiveSpellWordReplace: TRVA2LiveSpellReplaceEvent;
  protected
    { IRVAPopupMenu }
    function GetPopupComponent: TComponent;
    function GetActionList: TCustomActionList;
    procedure SetActionList(const Value: TCustomActionList);
    function GetMaxSuggestionsCount: Integer;
    procedure SetMaxSuggestionsCount(Value: Integer);
    procedure ClearItems;
    procedure AddActionItem(Action: TAction; const Caption: String='');
    procedure AddSeparatorItem;
    procedure DeleteLastSeparatorItem;
    function GetItemCaption(Sender: TObject): string;
    {$IFNDEF RVDONOTUSELIVESPELL}
    procedure AddClickItem(Click: TNotifyEvent; const Caption: String;
      Charset: TFontCharset; Enabled, Default: Boolean);
    function WantLiveSpellGetSuggestions: Boolean;
    procedure LiveSpellGetSuggestions(Edit: TCustomRichViewEdit; const Word: String; StyleNo: Integer;
      Suggestions: TStrings);
    procedure LiveSpellWordReplace(Edit: TCustomRichViewEdit; const Word, Correction: String; StyleNo: Integer);
    function WantLiveSpellIgnoreAll: Boolean;
    procedure LiveSpellIgnoreAll(Edit: TCustomRichViewEdit; const Word: String; StyleNo: Integer);
    function WantLiveSpellAdd: Boolean;
    procedure LiveSpellAdd(Edit: TCustomRichViewEdit; const Word: String; StyleNo: Integer);
    {$ENDIF}
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure Notification(AComponent: TComponent; Operation: TOperation); override;
    procedure Popup(X,Y: Integer); override;
  published
    property ActionList: TCustomActionList read GetActionList write SetActionList;
    property OnLiveSpellGetSuggestions: TRVA2LiveSpellGetSuggestionsEvent
      read FOnLiveSpellGetSuggestions write FOnLiveSpellGetSuggestions;
    property OnLiveSpellIgnoreAll: TRVA2LiveSpellIgnoreAllEvent
      read FOnLiveSpellIgnoreAll write FOnLiveSpellIgnoreAll;
    property OnLiveSpellAdd: TRVA2LiveSpellAddEvent
      read FOnLiveSpellAdd write FOnLiveSpellAdd;
    property OnLiveSpellWordReplace: TRVA2LiveSpellReplaceEvent
      read FOnLiveSpellWordReplace write FOnLiveSpellWordReplace;
    property MaxSuggestionsCount: Integer read GetMaxSuggestionsCount write SetMaxSuggestionsCount default 0;
  end;
  {$ENDIF}

  {$IFDEF USETBX}
  TRVATBXPopupMenu = class (TTBXPopupMenu, IRVAPopupMenu)
  private
    FPopupMenuHelper: TRVAPopupMenuHelper;
    FOnLiveSpellGetSuggestions: TRVA2LiveSpellGetSuggestionsEvent;
    FOnLiveSpellAdd: TRVA2LiveSpellAddEvent;
    FOnLiveSpellIgnoreAll: TRVA2LiveSpellIgnoreAllEvent;
    FOnLiveSpellWordReplace: TRVA2LiveSpellReplaceEvent;
  protected
    { IRVAPopupMenu }
    function GetPopupComponent: TComponent;
    function GetActionList: TCustomActionList;
    procedure SetActionList(const Value: TCustomActionList);
    function GetMaxSuggestionsCount: Integer;
    procedure SetMaxSuggestionsCount(Value: Integer);
    procedure ClearItems;
    procedure AddActionItem(Action: TAction; const Caption: String='');
    procedure AddSeparatorItem;
    procedure DeleteLastSeparatorItem;
    function GetItemCaption(Sender: TObject): string;
    {$IFNDEF RVDONOTUSELIVESPELL}
    procedure AddClickItem(Click: TNotifyEvent; const Caption: String;
      Charset: TFontCharset; Enabled, Default: Boolean);
    function WantLiveSpellGetSuggestions: Boolean;
    procedure LiveSpellGetSuggestions(Edit: TCustomRichViewEdit; const Word: String; StyleNo: Integer;
      Suggestions: TStrings);
    procedure LiveSpellWordReplace(Edit: TCustomRichViewEdit; const Word, Correction: String; StyleNo: Integer);
    function WantLiveSpellIgnoreAll: Boolean;
    procedure LiveSpellIgnoreAll(Edit: TCustomRichViewEdit; const Word: String; StyleNo: Integer);
    function WantLiveSpellAdd: Boolean;
    procedure LiveSpellAdd(Edit: TCustomRichViewEdit; const Word: String; StyleNo: Integer);
    {$ENDIF}
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure Notification(AComponent: TComponent; Operation: TOperation); override;
    procedure Popup(X,Y: Integer); override;
  published
    property ActionList: TCustomActionList read GetActionList write SetActionList;
    property OnLiveSpellGetSuggestions: TRVA2LiveSpellGetSuggestionsEvent
      read FOnLiveSpellGetSuggestions write FOnLiveSpellGetSuggestions;
    property OnLiveSpellIgnoreAll: TRVA2LiveSpellIgnoreAllEvent
      read FOnLiveSpellIgnoreAll write FOnLiveSpellIgnoreAll;
    property OnLiveSpellAdd: TRVA2LiveSpellAddEvent
      read FOnLiveSpellAdd write FOnLiveSpellAdd;
    property OnLiveSpellWordReplace: TRVA2LiveSpellReplaceEvent
      read FOnLiveSpellWordReplace write FOnLiveSpellWordReplace;
    property MaxSuggestionsCount: Integer read GetMaxSuggestionsCount write SetMaxSuggestionsCount default 0;
  end;
  {$ENDIF}

  {$IFDEF USESPTBX}
  TRVASPTBXPopupMenu = class (TSPTBXPopupMenu, IRVAPopupMenu)
  private
    FPopupMenuHelper: TRVAPopupMenuHelper;
    FOnLiveSpellGetSuggestions: TRVA2LiveSpellGetSuggestionsEvent;
    FOnLiveSpellAdd: TRVA2LiveSpellAddEvent;
    FOnLiveSpellIgnoreAll: TRVA2LiveSpellIgnoreAllEvent;
    FOnLiveSpellWordReplace: TRVA2LiveSpellReplaceEvent;
  protected
    { IRVAPopupMenu }
    function GetPopupComponent: TComponent;
    function GetActionList: TCustomActionList;
    procedure SetActionList(const Value: TCustomActionList);
    function GetMaxSuggestionsCount: Integer;
    procedure SetMaxSuggestionsCount(Value: Integer);
    procedure ClearItems;
    procedure AddActionItem(Action: TAction; const Caption: String='');
    procedure AddSeparatorItem;
    procedure DeleteLastSeparatorItem;
    function GetItemCaption(Sender: TObject): string;
    {$IFNDEF RVDONOTUSELIVESPELL}
    procedure AddClickItem(Click: TNotifyEvent; const Caption: String;
      Charset: TFontCharset; Enabled, Default: Boolean);
    function WantLiveSpellGetSuggestions: Boolean;
    procedure LiveSpellGetSuggestions(Edit: TCustomRichViewEdit; const Word: String; StyleNo: Integer;
      Suggestions: TStrings);
    procedure LiveSpellWordReplace(Edit: TCustomRichViewEdit; const Word, Correction: String; StyleNo: Integer);
    function WantLiveSpellIgnoreAll: Boolean;
    procedure LiveSpellIgnoreAll(Edit: TCustomRichViewEdit; const Word: String; StyleNo: Integer);
    function WantLiveSpellAdd: Boolean;
    procedure LiveSpellAdd(Edit: TCustomRichViewEdit; const Word: String; StyleNo: Integer);
    {$ENDIF}
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure Notification(AComponent: TComponent; Operation: TOperation); override;
    procedure Popup(X,Y: Integer); override;
  published
    property ActionList: TCustomActionList read GetActionList write SetActionList;
    property OnLiveSpellGetSuggestions: TRVA2LiveSpellGetSuggestionsEvent
      read FOnLiveSpellGetSuggestions write FOnLiveSpellGetSuggestions;
    property OnLiveSpellIgnoreAll: TRVA2LiveSpellIgnoreAllEvent
      read FOnLiveSpellIgnoreAll write FOnLiveSpellIgnoreAll;
    property OnLiveSpellAdd: TRVA2LiveSpellAddEvent
      read FOnLiveSpellAdd write FOnLiveSpellAdd;
    property OnLiveSpellWordReplace: TRVA2LiveSpellReplaceEvent
      read FOnLiveSpellWordReplace write FOnLiveSpellWordReplace;
    property MaxSuggestionsCount: Integer read GetMaxSuggestionsCount write SetMaxSuggestionsCount default 0;
  end;
  {$ENDIF}


  TrvCustomAction = class(TAction {$IFDEF USERVTNT},ITntAction{$ENDIF})
  private
    {$IFDEF USERVTNT}
    function GetCaption: WideString;
    procedure SetCaption(const Value: WideString);
    function GetHint: WideString;
    procedure SetHint(const Value: WideString);
    {$ENDIF}
  protected
    FMessageID: TRVAMessageID;
    FDisabled: Boolean;
    procedure Localize; dynamic;
    {$IFDEF USERVTNT}
    procedure DefineProperties(Filer: TFiler); override;
    {$ENDIF}
  public
    {$IFDEF USERVTNT}
    procedure Assign(Source: TPersistent); override;
    {$ENDIF}
    procedure ConvertToPixels; dynamic;
    procedure ConvertToTwips; dynamic;
  published
    property Disabled: Boolean read FDisabled write FDisabled default False;
    {$IFDEF USERVTNT}
    property Caption: WideString read GetCaption write SetCaption;
    property Hint: WideString read GetHint write SetHint;
    {$ENDIF}
  end;

  TrvAction = class(TrvCustomAction)
  private
    FControl: TCustomRichViewEdit;
    procedure SetControl(Value: TCustomRichViewEdit);
  protected
    function RequiresMainDoc: Boolean; virtual;
    function GetControl(Target: TObject): TCustomRichViewEdit; virtual;
    procedure Notification(AComponent: TComponent; Operation: TOperation); override;
    procedure IterateProc(RVData: TCustomRVData; ItemNo: Integer; rve: TCustomRichViewEdit; var CustomData: Integer); virtual;
    function ContinueIteration(var CustomData: Integer): Boolean; virtual;
    function IterateRVData(RVData: TCustomRVData; rve: TCustomRichViewEdit; StartNo, EndNo: Integer;
      var CustomData: Integer): Boolean;
    function CanApplyToPlainText: Boolean; dynamic;
  public
    function HandlesTarget(Target: TObject): Boolean; override;
    procedure UpdateTarget(Target: TObject); override;
  published
    property Control: TCustomRichViewEdit read FControl write SetControl;
  end;

  TrvActionEvent = class(TrvAction)
  private
    FOnUpdate, FOnExecute: TRVAEvent;
  protected
  public
    procedure ExecuteTarget(Target: TObject); override;
    procedure UpdateTarget(Target: TObject); override;
  published
    property OnUpdate: TRVAEvent read FOnUpdate write FOnUpdate;
    property OnExecute: TRVAEvent read FOnExecute write FOnExecute;
  end;

{ ------------------ File ------------------------- }
  TrvaDocumentInfo = class
    public
      rve: TCustomRichViewEdit;
      FileName: String;
      FileFormat: TrvFileSaveFilter;
      CustomFilterIndex: Integer;
      Defined, LFWarned: Boolean;
      LFWFileFormat: TrvFileSaveFilter;
      LFWCustomFilterIndex: Integer;
      constructor Create; dynamic;
      procedure Update; dynamic;
  end;

  TrvaDocumentInfoClass = class of TrvaDocumentInfo;

  TrvActionSave = class;

  TrvActionNew = class(TrvAction)
  private
    FActionSave: TrvActionSave;
    FOnNew: TNotifyEvent;
    procedure SetActionSave(const Value: TrvActionSave);
    function GetActionSave: TrvActionSave;
  protected
    function RequiresMainDoc: Boolean; override;
    procedure Notification(AComponent: TComponent; Operation: TOperation); override;
    procedure ResetProperties(rve: TCustomRichViewEdit);
    procedure Reset(rve: TCustomRichViewEdit);
    procedure CompleteClear(rve: TCustomRichViewEdit);
    procedure CompleteFormat(rve: TCustomRichViewEdit);
    procedure CompleteDeleteUnusedStyles(rve: TCustomRichViewEdit);
    procedure UpdateHFProperties(rve: TCustomRichViewEdit);
  public
    constructor Create(AOwner: TComponent); override;
    procedure ExecuteTarget(Target: TObject); override;
  published
    property ActionSave: TrvActionSave read FActionSave write SetActionSave;
    property OnNew: TNotifyEvent read FOnNew write FOnNew;
  end;

  TrvActionOpen = class(TrvActionNew)
  private
    FDialogTitle: string;
    FFilter: TrvFileOpenFilterSet;
    FLastFilterIndex: Integer;
    FInitialDir: String;
    FCustomFilter: String;
    FOnOpenFile: TRVOpenFileEvent;
  public
    procedure ExecuteTarget(Target: TObject); override;
    constructor Create(AOwner: TComponent); override;
    procedure LoadFile(rve: TCustomRichViewEdit; const FileName: String;
      FileFormat: TrvFileOpenFilter; CustomFilterIndex: Integer=0);
    property LastFilterIndex: Integer read FLastFilterIndex write FLastFilterIndex;
  published
    property DialogTitle: String read FDialogTitle write FDialogTitle;
    property InitialDir: String read FInitialDir write FInitialDir;
    property Filter: TrvFileOpenFilterSet read FFilter write FFilter
      default [ffiRVF..{$IFDEF USERVHTMLVIEWER}ffiHTML{$ELSE}ffiCustom{$ENDIF}];
    property CustomFilter: String read FCustomFilter write FCustomFilter;
    property OnOpenFile: TRVOpenFileEvent read FOnOpenFile write FOnOpenFile;
  end;

  TrvActionSaveAs = class;

  TrvActionSave = class(TrvAction)
  private
    FDocuments: TRVList;
    FActionSaveAs: TrvActionSaveAs;
    FOnDocumentFileChange: TRVFileChangeEvent;
    FLostFormatWarning: TrvFileSaveFilterSet;
    FSuppressNextErrorMessage: Boolean;
    FOnSaving: TRVSaveFileEvent;
    {$IFDEF USERVHTMLVIEWER}
    FFileTitle, FImagePrefix: String;
    FSaveOptions: TRVSaveOptions;
    FCreateDirectoryForHTMLImages: Boolean;
    {$ENDIF}
    procedure SetActionSaveAs(const Value: TrvActionSaveAs);
    function GetActionSaveAs: TrvActionSaveAs;
  protected
    function RequiresMainDoc: Boolean; override;
    function AddDoc(rve: TCustomRichViewEdit; const FileName: String;
      FileFormat: TrvFileSaveFilter; CustomFilterIndex: Integer; Defined: Boolean;
      SaveFile, SuppressLFWarn, LFWarned: Boolean): Integer;
    procedure DeleteDoc(rve: TCustomRichViewEdit);
    function SaveDoc(Index: Integer; SuppressLFWarn: Boolean): Boolean;
    function SaveDocEx(rve: TCustomRichViewEdit): Boolean;
    procedure Notification(AComponent: TComponent; Operation: TOperation); override;
    procedure DoDocumentFileChange(Index: Integer);
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure ExecuteTarget(Target: TObject); override;
    function CanCloseDoc(rve: TCustomRichViewEdit): Boolean;
    function FindDoc(rve: TCustomRichViewEdit): Integer;
    function GetDoc(rve: TCustomRichViewEdit): TrvaDocumentInfo;
    property Documents: TRVList read FDocuments;
    property SuppressNextErrorMessage: Boolean read FSuppressNextErrorMessage write FSuppressNextErrorMessage;
  published
    {$IFDEF USERVHTMLVIEWER}
    property FileTitle: String read FFileTitle write FFileTitle;
    property ImagePrefix: String read FImagePrefix write FImagePrefix;
    property SaveOptions: TRVSaveOptions read FSaveOptions write FSaveOptions;
    property CreateDirectoryForHTMLImages: Boolean read FCreateDirectoryForHTMLImages write FCreateDirectoryForHTMLImages default True;
    {$ENDIF}
    property ActionSaveAs: TrvActionSaveAs read FActionSaveAs write SetActionSaveAs;
    property OnDocumentFileChange: TRVFileChangeEvent read FOnDocumentFileChange write FOnDocumentFileChange;
    property LostFormatWarning: TrvFileSaveFilterSet read FLostFormatWarning write FLostFormatWarning
      default [ffeRTF, ffeTextANSI, ffeTextUnicode, ffeCustom
      {$IFDEF USERVHTMLVIEWER}, ffeHTMLCSS{$ENDIF}];
    property OnSaving: TRVSaveFileEvent read FOnSaving write FOnSaving;
  end;

  TrvActionCustomIO = class(TrvAction)
  private
    FDialogTitle: string;
    FLastFilterIndex: Integer;
    FFileName: String;
    FAutoUpdateFileName: Boolean;
  protected
    FInitialDir: String;
    property FileName: String read FFileName write FFileName;
    property AutoUpdateFileName: Boolean read FAutoUpdateFileName write FAutoUpdateFileName default True;
  public
    constructor Create(AOwner: TComponent); override;
  published
    property DialogTitle: string read FDialogTitle write FDialogTitle;
    property InitialDir: String read FInitialDir write FInitialDir;
  end;

  TrvActionCustomFileIO = class(TrvActionCustomIO)
  private
    FCustomFilter: String;
  protected
    property CustomFilter: String read FCustomFilter write FCustomFilter;
  end;

  TrvActionSaveAs = class(TrvActionCustomFileIO)
  private
    FActionSave: TrvActionSave;
    FFilter: TrvFileSaveFilterSet;
    procedure SetActionSave(const Value: TrvActionSave);
    function GetActionSave: TrvActionSave;
  protected
    function RequiresMainDoc: Boolean; override;
    procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  public
    constructor Create(AOwner: TComponent); override;
    procedure ExecuteTarget(Target: TObject); override;
  published
    property Filter: TrvFileSaveFilterSet read FFilter write FFilter
      default [ffeRVF..{$IFDEF USERVHTMLVIEWER}ffeHTMLCSS{$ELSE}ffeCustom{$ENDIF}];
    property ActionSave: TrvActionSave read FActionSave write SetActionSave;
    property CustomFilter;
  end;

  TrvActionExport = class(TrvActionCustomFileIO)
  private
    FFilter: TrvFileExportFilterSet;
    FFileTitle, FImagePrefix: String;
    FSaveOptions: TRVSaveOptions;
    FCreateDirectoryForHTMLImages: Boolean;
  protected
    function RequiresMainDoc: Boolean; override;
  public
    constructor Create(AOwner: TComponent); override;
    procedure ExecuteTarget(Target: TObject); override;
    function ExportToFile(Edit: TCustomRichViewEdit; const FileName: String;
      ExportFormat: TrvFileExportFilter; ConverterOrCustomIndex: Integer;
      rvc: TRVOfficeConverter): Boolean;
    property FileName;
  published
    property Filter: TrvFileExportFilterSet read FFilter write FFilter default [ffeRVF..ffeOfficeConverters];
    property FileTitle: String read FFileTitle write FFileTitle;
    property ImagePrefix: String read FImagePrefix write FImagePrefix;
    property SaveOptions: TRVSaveOptions read FSaveOptions write FSaveOptions;
    property CreateDirectoryForHTMLImages: Boolean read FCreateDirectoryForHTMLImages write FCreateDirectoryForHTMLImages default True;
    property AutoUpdateFileName;
    property CustomFilter;
  end;

{ ------------------ Printing ------------------------- }



  TrvCustomPrintAction = class(TrvAction)
  private
    FOldOnPagePrepaint: TRVPagePrepaintEvent;
  protected
    function RequiresMainDoc: Boolean; override;
    function FindRVPrint(Form: TComponent): TRVPrint;
    procedure InitRVPrint(Form: TComponent; var ARVPrint: TRVPrint;
      var ACreated: Boolean);
    procedure DoneRVPrint(ARVPrint: TRVPrint; ACreated: Boolean);
    procedure PagePrepaint(Sender: TRVPrint; PageNo: Integer; Canvas: TCanvas;
      Preview: Boolean; PageRect, PrintAreaRect: TRect);
  public
    procedure UpdateTarget(Target: TObject); override;
  end;

  TrvActionPrint = class;
  TrvActionPageSetup = class;

  TrvActionPrintPreview = class(TrvCustomPrintAction)
  private
    FActionPrint: TrvActionPrint;
    FMaximized: Boolean;
    FActionPageSetup: TrvActionPageSetup;
    FOnGetPreviewFormClass: TRVGetFormClassEvent;
    procedure SetActionPrint(const Value: TrvActionPrint);
    function GetActionPrint: TrvActionPrint;
    procedure SetActionPageSetup(const Value: TrvActionPageSetup);
    function GetPreviewFormClass: TFormClass;
  public
    constructor Create(AOwner: TComponent); override;
    procedure ExecuteTarget(Target: TObject); override;
  published
    property ActionPrint: TrvActionPrint read FActionPrint write SetActionPrint;
    property ActionPageSetup: TrvActionPageSetup read FActionPageSetup write SetActionPageSetup;
    property Maximized: Boolean read FMaximized write FMaximized default False;
    property OnGetPreviewFormClass: TRVGetFormClassEvent
      read FOnGetPreviewFormClass write FOnGetPreviewFormClass;
  end;

  TrvActionPrint = class(TrvCustomPrintAction)
  private
    FTitle: string;
  public
    constructor Create(AOwner: TComponent); override;
    procedure ExecuteTarget(Target: TObject); override;
  published
    property Title: string read FTitle write FTitle;
  end;

  TrvActionQuickPrint = class(TrvCustomPrintAction)
  private
    FTitle: string;
  protected
    procedure Localize; override;
  public
    constructor Create(AOwner: TComponent); override;
    procedure ExecuteTarget(Target: TObject); override;
  published
    property Title: string read FTitle write FTitle;
  end;

  TrvActionPageSetup = class(TrvCustomAction)
  private
    FMarginsUnits: TrvPaperMarginsUnits;
    FOnChange: TNotifyEvent;
  public
    constructor Create(AOwner: TComponent); override;
    function HandlesTarget(Target: TObject): Boolean; override;
    procedure UpdateTarget(Target: TObject); override;
    procedure ExecuteTarget(Target: TObject); override;
  published
    property MarginsUnits: TrvPaperMarginsUnits read FMarginsUnits write FMarginsUnits default rvpmuMillimeters;
    property OnChange: TNotifyEvent read FOnChange write FOnChange;
  end;


  { ------------------ Find and Replace ------------------------- }

  {$IFDEF USERVTNT}
  TRVABasicFindDialog = TTntFindDialog;
  TRVABasicReplaceDialog = TTntReplaceDialog;
  {$ELSE}
  TRVABasicFindDialog = TFindDialog;
  TRVABasicReplaceDialog = TReplaceDialog;
  {$ENDIF}

  TrvActionReplace = class;

  TrvActionFind = class(TrvAction)
  private
    FEdit: TCustomRichViewEdit;
    FFindDialog: TRVABasicFindDialog;
    FActionReplace: TrvActionReplace;
    FFindDialogVisible: Boolean;
    procedure FindDialogFind(Sender: TObject);
    procedure FindDialogClose(Sender: TObject);
    procedure SetActionReplace(const Value: TrvActionReplace);
    function GetActionReplace: TrvActionReplace;
  protected
    procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  public
    constructor Create(AOwner: TComponent); override;
    procedure UpdateTarget(Target: TObject); override;
    procedure ExecuteTarget(Target: TObject); override;
    procedure CloseDialog;
    destructor Destroy; override;
  published
    property ActionReplace: TrvActionReplace read FActionReplace write SetActionReplace;
  end;

  TrvActionFindNext = class(TrvAction)
  private
    FActionFind: TrvActionFind;
    procedure SetActionFind(const Value: TrvActionFind);
    function GetActionFind: TrvActionFind;
  protected
    procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  public
    constructor Create(AOwner: TComponent); override;
    procedure ExecuteTarget(Target: TObject); override;
  published
    property ActionFind: TrvActionFind read FActionFind write SetActionFind;
  end;

  TRVAReplacingEvent = procedure (Sender: TObject; Editor: TCustomRichViewEdit;
    const NewText: String) of object;


  TrvActionReplace = class(TrvAction)
  private
    FEdit: TCustomRichViewEdit;
    FReplaceDialog: TRVABasicReplaceDialog;
    FShowReplaceAllSummary: Boolean;
    FActionFind: TrvActionFind;
    FOnReplacing: TRVAReplacingEvent;
    FOnReplaceAllEnd: TRVAEditEvent;
    FOnReplaceAllStart: TRVAEditEvent;
    FReplaceDialogVisible: Boolean;
    procedure ReplaceDialogFind(Sender: TObject);
    procedure ReplaceDialogClose(Sender: TObject);
    procedure ReplaceDialogReplace(Sender: TObject);
    procedure SetActionFind(const Value: TrvActionFind);
    function GetActionFind: TrvActionFind;
    procedure DoReplacing(Editor: TCustomRichViewEdit;
      const NewText: String);
  protected
    procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure UpdateTarget(Target: TObject); override;
    procedure ExecuteTarget(Target: TObject); override;
    procedure CloseDialog;
  published
    property ShowReplaceAllSummary: Boolean read FShowReplaceAllSummary write FShowReplaceAllSummary default True;
    property ActionFind: TrvActionFind read FActionFind write SetActionFind;
    property OnReplacing: TRVAReplacingEvent read FOnReplacing write FOnReplacing;
    property OnReplaceAllStart: TRVAEditEvent read FOnReplaceAllStart write FOnReplaceAllStart;
    property OnReplaceAllEnd: TRVAEditEvent read FOnReplaceAllEnd write FOnReplaceAllEnd;
  end;

  { ------------------ Edit ------------------------- }

  TrvCustomEditAction = class(TrvAction)
  protected
    function IsDifferentEditor(Target: TObject): Boolean;
    function GetDefaultControl: TCustomRichViewEdit;
  public
    function HandlesTarget(Target: TObject): Boolean; override;
    procedure UpdateTarget(Target: TObject); override;
  end;

  TrvActionUndo = class(TrvCustomEditAction)
  public
    constructor Create(AOwner: TComponent); override;
    procedure ExecuteTarget(Target: TObject); override;
    procedure UpdateTarget(Target: TObject); override;
  end;

  TrvActionRedo = class(TrvAction)
  public
    constructor Create(AOwner: TComponent); override;
    procedure ExecuteTarget(Target: TObject); override;
    procedure UpdateTarget(Target: TObject); override;
  end;

  TrvActionCut = class(TrvCustomEditAction)
  public
    constructor Create(AOwner: TComponent); override;
    procedure ExecuteTarget(Target: TObject); override;
  end;

  TrvActionCopy = class(TrvCustomEditAction)
  public
    constructor Create(AOwner: TComponent); override;
    procedure ExecuteTarget(Target: TObject); override;
  end;

  TrvActionPaste = class(TrvCustomEditAction)
  private
    {$IFDEF RVAHTML}
    function AllowPasteHTML: Boolean;
    {$ENDIF}
  public
    constructor Create(AOwner: TComponent); override;
    procedure ExecuteTarget(Target: TObject); override;
    procedure UpdateTarget(Target: TObject); override;
  end;

  TrvActionPasteAsText = class(TrvCustomEditAction)
  public
    constructor Create(AOwner: TComponent); override;
    procedure ExecuteTarget(Target: TObject); override;
    procedure UpdateTarget(Target: TObject); override;
  end;

  TrvActionPasteSpecial = class;

  TRVACustomPasteEvent = procedure (Sender: TrvActionPasteSpecial;
    Editor: TCustomRichViewEdit; Format: Word) of object;
  TRVACanPasteEvent = procedure (Sender: TrvActionPasteSpecial;
    var CanPaste: Boolean) of object;


  TrvActionPasteSpecial = class(TrvActionPaste)
  private
    FListForm: TForm;
    FOnShowing: TNotifyEvent;
    FOnCustomPaste: TRVACustomPasteEvent;
    FStoreFileName: Boolean;
    FStoreFileNameInItemName: Boolean;
    FOnCanPaste: TRVACanPasteEvent;
  public
    constructor Create(AOwner: TComponent); override;
    procedure ExecuteTarget(Target: TObject); override;
    function HandlesTarget(Target: TObject): Boolean; override;
    procedure AddFormat(const FormatName: String; Format: Word);
    procedure UpdateTarget(Target: TObject); override;
  published
    property OnShowing: TNotifyEvent read FOnShowing write FOnShowing;
    property OnCanPaste: TRVACanPasteEvent read FOnCanPaste write FOnCanPaste;
    property OnCustomPaste: TRVACustomPasteEvent read FOnCustomPaste write FOnCustomPaste;
    property StoreFileName: Boolean
      read FStoreFileName write FStoreFileName default False;
    property StoreFileNameInItemName: Boolean
      read FStoreFileNameInItemName write FStoreFileNameInItemName default False;
  end;

  TrvActionSelectAll = class(TrvAction)
  public
    constructor Create(AOwner: TComponent); override;
    procedure ExecuteTarget(Target: TObject); override;
  end;

  TrvActionCharCase = class(TrvAction)
  public
    constructor Create(AOwner: TComponent); override;
    procedure ExecuteTarget(Target: TObject); override;
    procedure UpdateTarget(Target: TObject); override;    
  end;

  { ------------------ Basic Color Action  ------------------------- }

  TrvActionCustomColor = class(TrvAction)
  private
    FColorPicker: TForm;
    FColor: TColor;
    FOnHideColorPicker: TNotifyEvent;
    FOnShowColorPicker: TNotifyEvent;
    FUserInterface: TrvaColorInterface;
    FEdit: TCustomRichViewEdit;
    FDefaultColor: TColor;
    FCallerControl: TControl;
    procedure ColorPickerDestroy(Sender: TObject);
    procedure InitColorDialog(var AColorDialog: TColorDialog; var ACreated: Boolean);
    procedure DoneColorDialog(AColorDialog: TColorDialog; ACreated: Boolean);
    procedure SetCallerControl(const Value: TControl);
    procedure SetColor(const Value: TColor);
  protected
    procedure Notification(AComponent: TComponent; Operation: TOperation); override;
    procedure ExecuteCommand(rve: TCustomRichViewEdit; Command: Integer); virtual; abstract;
    function GetCurrentColor(FEdit: TCustomRichViewEdit): TColor; virtual; abstract;
    function CanApplyToPlainText: Boolean; override;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure ExecuteTarget(Target: TObject); override;
    procedure Localize; override;
    function GetColorName: String;
  published
    property CallerControl: TControl read FCallerControl write SetCallerControl;
    property Color: TColor read FColor write SetColor default clNone;
    property UserInterface: TrvaColorInterface read FUserInterface write FUserInterface default rvacAdvanced;
    property OnShowColorPicker: TNotifyEvent read FOnShowColorPicker write FOnShowColorPicker;
    property OnHideColorPicker: TNotifyEvent read FOnHideColorPicker write FOnHideColorPicker;
  end;

  { ------------------ Text Styles ------------------------- }

  TrvActionTextStyles = class(TrvAction)
  private
    procedure NewOnStyleConversion(Sender: TCustomRichViewEdit;
      StyleNo, UserData: Integer; AppliedToText: Boolean; var NewStyleNo: Integer);
  protected
    function IsRecursive: Boolean; dynamic;
    procedure ExecuteCommand(rve: TCustomRichViewEdit; Command: Integer);
    procedure ApplyConversion(Editor: TCustomRichViewEdit; FontInfo: TFontInfo;
      StyleNo, Command: Integer); virtual; abstract;
    function CanApplyToPlainText: Boolean; override;
  public
    procedure ExecuteTarget(Target: TObject); override;
  end;

  TrvActionFontCustomColor = class(TrvActionCustomColor)
  private
    procedure NewOnStyleConversion(Sender: TCustomRichViewEdit;
      StyleNo, UserData: Integer; AppliedToText: Boolean; var NewStyleNo: Integer);
  protected
    procedure ExecuteCommand(rve: TCustomRichViewEdit; Command: Integer); override;
    procedure ApplyConversion(Editor: TCustomRichViewEdit; FontInfo: TFontInfo;
      StyleNo, Command: Integer); virtual; abstract;
  end;

  TrvActionFontColor = class(TRVActionFontCustomColor)
  protected
    procedure ApplyConversion(Editor: TCustomRichViewEdit; FontInfo: TFontInfo;
      StyleNo, Command: Integer); override;
    function GetCurrentColor(FEdit: TCustomRichViewEdit): TColor; override;
  public
    constructor Create(AOwner: TComponent); override;
  published
    property Color default clWindowText;
  end;

  TrvActionFontBackColor = class(TRVActionFontCustomColor)
  protected
    procedure ApplyConversion(Editor: TCustomRichViewEdit; FontInfo: TFontInfo;
      StyleNo, Command: Integer); override;
    function GetCurrentColor(FEdit: TCustomRichViewEdit): TColor; override;
  public
    constructor Create(AOwner: TComponent); override;
  end;

  TrvActionFonts = class(TrvActionTextStyles)
  private
    FFont: TFont;
    FUserInterface: Boolean;
    procedure SetFont(const Value: TFont);
  protected
    procedure ApplyConversion(Editor: TCustomRichViewEdit; FontInfo: TFontInfo;
      StyleNo, Command: Integer); override;
    function CanApplyToPlainText: Boolean; override;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure ExecuteTarget(Target: TObject); override;
    property Font: TFont read FFont write SetFont;
  published
    property UserInterface: Boolean read FUserInterface write FUserInterface default True;
  end;

  TRVFontInfoMainProperty = (rvfimFontName, rvfimSize, rvfimCharset,
    rvfimBold, rvfimItalic, rvfimUnderline, rvfimStrikeout,
    rvfimOverline, rvfimAllCaps, rvfimVShift, rvfimColor,
    rvfimCharScale, rvfimCharSpacing, rvfimSubSuperScriptType,
    rvfimUnderlineType, rvfimUnderlineColor);

  TRVFontInfoMainProperties = set of TRVFontInfoMainProperty;

  TrvActionFontEx = class(TrvActionFonts)
  private
    FValidProperties: TRVFontInfoMainProperties;
    FVShift: Integer;
    FCharScale: Integer;
    FFontStyleEx: TRVFontStyles;
    FCharSpacing: TRVStyleLength;
    FSubSuperScriptType: TRVSubSuperScriptType;
    FUnderlineColor: TColor;
    FUnderlineType: TRVUnderlineType;
    FAutoApplySymbolCharset: Boolean;
    procedure AdjustCharset;
  protected
    procedure ApplyConversion(Editor: TCustomRichViewEdit; FontInfo: TFontInfo;
      StyleNo, Command: Integer); override;
    procedure IterateProc(RVData: TCustomRVData; ItemNo: Integer;
      rve: TCustomRichViewEdit; var CustomData: Integer); override;
    function ContinueIteration(var CustomData: Integer): Boolean; override;
    function CanApplyToPlainText: Boolean; override;
  public
    constructor Create(AOwner: TComponent); override;
    procedure ExecuteTarget(Target: TObject); override;
    procedure GetFromEditor(rve: TCustomRichViewEdit);

    property FontStyleEx: TRVFontStyles read FFontStyleEx write FFontStyleEx;
    property VShift: Integer read FVShift write FVShift;
    property CharScale: Integer read FCharScale write FCharScale;
    property CharSpacing: TRVStyleLength read FCharSpacing write FCharSpacing;
    property SubSuperScriptType: TRVSubSuperScriptType read FSubSuperScriptType write FSubSuperScriptType;
    property UnderlineType: TRVUnderlineType read FUnderlineType write FUnderlineType;
    property UnderlineColor: TColor read FUnderlineColor write FUnderlineColor;
    property ValidProperties: TRVFontInfoMainProperties read FValidProperties write FValidProperties;
  published
    property AutoApplySymbolCharset: Boolean read FAutoApplySymbolCharset write FAutoApplySymbolCharset default True;
  end;

  TrvActionFontStyle = class(TrvActionTextStyles)
  protected
    FFontStyle: TFontStyle;
    procedure ApplyConversion(Editor: TCustomRichViewEdit; FontInfo: TFontInfo;
      StyleNo, Command: Integer); override;
    procedure IterateProc(RVData: TCustomRVData; ItemNo: Integer;
      rve: TCustomRichViewEdit; var CustomData: Integer); override;
    function ContinueIteration(var CustomData: Integer): Boolean; override;
    function AdditionalCheckCondition(TextStyle: TFontInfo): Boolean; virtual;
  public
    procedure UpdateTarget(Target: TObject); override;
  end;

  TrvActionFontBold = class(TrvActionFontStyle)
  public
    constructor Create(AOwner: TComponent); override;
  end;

  TrvActionFontItalic = class(TrvActionFontStyle)
  public
    constructor Create(AOwner: TComponent); override;
  end;

  TrvActionFontUnderline = class(TrvActionFontStyle)
  protected
    procedure ApplyConversion(Editor: TCustomRichViewEdit; FontInfo: TFontInfo;
      StyleNo, Command: Integer); override;
    function AdditionalCheckCondition(TextStyle: TFontInfo): Boolean; override;
  public
    constructor Create(AOwner: TComponent); override;
  end;

  TrvActionFontStrikeout = class(TrvActionFontStyle)
  public
    constructor Create(AOwner: TComponent); override;
  end;

  TrvActionFontStyleEx = class(TrvActionTextStyles)
  protected
    FFontStyleEx: TRVFontStyle;
    procedure ApplyConversion(Editor: TCustomRichViewEdit; FontInfo: TFontInfo;
      StyleNo, Command: Integer); override;
    procedure IterateProc(RVData: TCustomRVData; ItemNo: Integer;
      rve: TCustomRichViewEdit; var CustomData: Integer); override;
    function ContinueIteration(var CustomData: Integer): Boolean; override;
  public
    procedure UpdateTarget(Target: TObject); override;
  end;

  TrvActionFontAllCaps = class(TrvActionFontStyleEx)
  public
    constructor Create(AOwner: TComponent); override;
  end;

  TrvActionFontOverline = class(TrvActionFontStyleEx)
  public
    constructor Create(AOwner: TComponent); override;
  end;

  TrvActionSSScript = class (TrvActionTextStyles)
  protected
    FSubSuperSctiptType: TRVSubSuperScriptType;
    procedure ApplyConversion(Editor: TCustomRichViewEdit; FontInfo: TFontInfo;
      StyleNo, Command: Integer); override;
    procedure IterateProc(RVData: TCustomRVData; ItemNo: Integer;
      rve: TCustomRichViewEdit; var CustomData: Integer); override;
    function ContinueIteration(var CustomData: Integer): Boolean; override;
  public
    procedure UpdateTarget(Target: TObject); override;
  end;

  TrvActionSubscript = class (TrvActionSSScript)
  public
    constructor Create(AOwner: TComponent); override;
  end;

  TrvActionSuperscript = class (TrvActionSSScript)
  public
    constructor Create(AOwner: TComponent); override;
  end;


  TrvActionTextBiDi = class (TrvActionTextStyles)
  private
    FBiDiMode: TRVBiDiMode;
  protected
    procedure ApplyConversion(Editor: TCustomRichViewEdit; FontInfo: TFontInfo;
      StyleNo, Command: Integer); override;
    procedure IterateProc(RVData: TCustomRVData; ItemNo: Integer;
      rve: TCustomRichViewEdit; var CustomData: Integer); override;
    function ContinueIteration(var CustomData: Integer): Boolean; override;
  public
    procedure UpdateTarget(Target: TObject); override;
  end;

  TrvActionTextLTR = class (TrvActionTextBiDi)
  public
    constructor Create(AOwner: TComponent); override;
  end;

  TrvActionTextRTL = class (TrvActionTextBiDi)
  public
    constructor Create(AOwner: TComponent); override;
  end;


  TrvActionFontShrinkGrow = class (TrvActionTextStyles)
  private
    FPercent: Integer;
  public
    constructor Create(AOwner: TComponent); override;
  published
    property Percent: Integer read FPercent write FPercent default 10;
  end;

  TrvActionFontShrink = class (TrvActionFontShrinkGrow)
  private
    FMinSize: Integer;
  protected
    procedure ApplyConversion(Editor: TCustomRichViewEdit; FontInfo: TFontInfo;
      StyleNo, Command: Integer); override;
  public
    constructor Create(AOwner: TComponent); override;
  published
    property MinSize: Integer read FMinSize write FMinSize default 1;
  end;

  TrvActionFontGrow = class (TrvActionFontShrinkGrow)
  private
    FMaxSize: Integer;
  protected
    procedure ApplyConversion(Editor: TCustomRichViewEdit; FontInfo: TFontInfo;
      StyleNo, Command: Integer); override;
  public
    constructor Create(AOwner: TComponent); override;
  published
    property MaxSize: Integer read FMaxSize write FMaxSize default 100;
  end;

  TrvActionFontShrinkOnePoint = class (TrvActionTextStyles)
  private
    FMinSize: Integer;
  protected
    procedure ApplyConversion(Editor: TCustomRichViewEdit; FontInfo: TFontInfo;
      StyleNo, Command: Integer); override;
  public
    constructor Create(AOwner: TComponent); override;
  published
    property MinSize: Integer read FMinSize write FMinSize default 1;
  end;

  TrvActionFontGrowOnePoint = class (TrvActionTextStyles)
  private
    FMaxSize: Integer;
  protected
    procedure ApplyConversion(Editor: TCustomRichViewEdit; FontInfo: TFontInfo;
      StyleNo, Command: Integer); override;
  public
    constructor Create(AOwner: TComponent); override;
  published
    property MaxSize: Integer read FMaxSize write FMaxSize default 100;
  end;

{ --------------------- Insert ------------------------ }

  TrvActionInsertFile = class(TrvActionCustomFileIO)
  private
    FFilter: TrvFileImportFilterSet;
  public
    constructor Create(AOwner: TComponent); override;
    procedure ExecuteTarget(Target: TObject); override;
    procedure UpdateTarget(Target: TObject); override;
    function InsertFile(rve: TCustomRichViewEdit; const FileName: String;
      FileFormat: TrvFileImportFilter;
      ConverterOrCustomIndex: Integer=0;
      rvc: TRVOfficeConverter=nil;
      Silent: Boolean=False): Boolean;
    property FileName;
  published
    property Filter: TrvFileImportFilterSet read FFilter write FFilter default [ffiRVF..ffiOfficeConverters];
    property AutoUpdateFileName;
    property CustomFilter;
  end;

  TRVAInsertTextEvent = procedure (Sender: TObject; Editor: TCustomRichViewEdit;
    var Text: String) of object;

  TrvActionInsertText = class(TrvAction)
  private
    FOnInsertText: TRVAInsertTextEvent;
  public
    procedure ExecuteTarget(Target: TObject); override;
    procedure UpdateTarget(Target: TObject); override;    
  published
    property OnInsertText: TRVAInsertTextEvent read FOnInsertText write FOnInsertText;
  end;

  TrvActionInsertPicture = class(TrvActionCustomIO)
  private
    FDefaultExt: String;
    FFilter: String;
    FVAlign: TRVVAlign;
    FStoreFileName, FStoreFileNameInItemName: Boolean;
    FMaxImageSize: TRVStyleLength;
    FSpacing: TRVStyleLength;
    function IsImageTooLarge(gr: TGraphic): Boolean;
    procedure GetProperImageSize(gr: TGraphic; RVStyle: TRVStyle;
      var Width, Height: TRVStyleLength);
  public
    constructor Create(AOwner: TComponent); override;
    procedure ExecuteTarget(Target: TObject); override;
    procedure UpdateTarget(Target: TObject); override;
    procedure ConvertToPixels; override;
    procedure ConvertToTwips; override;
    property FileName;
  published
    property Filter: String read FFilter write FFilter;
    property VAlign: TRVVAlign read FVAlign write FVAlign;
    property DefaultExt: String read FDefaultExt write FDefaultExt;
    property StoreFileName: Boolean
      read FStoreFileName write FStoreFileName default False;
    property StoreFileNameInItemName: Boolean
      read FStoreFileNameInItemName write FStoreFileNameInItemName default False;
    property MaxImageSize: TRVStyleLength read FMaxImageSize write FMaxImageSize default 0;
    property Spacing: TRVStyleLength read FSpacing write FSpacing default 0;
  end;

  TrvActionInsertHLine = class(TrvAction)
  private
    FWidth: TRVStyleLength;
    FColor: TColor;
    FStyle: TRVBreakStyle;
  public
    constructor Create(AOwner: TComponent); override;
    procedure ExecuteTarget(Target: TObject); override;
    procedure UpdateTarget(Target: TObject); override;
    procedure ConvertToPixels; override;
    procedure ConvertToTwips; override;
  published
    property Color: TColor read FColor write FColor default clWindowText;
    property Style: TRVBreakStyle read FStyle write FStyle default rvbsLine;
    property Width: TRVStyleLength read FWidth write FWidth default 1;
  end;

  TRVInsertSymbolType = (rvisBoth, rvisUnicode, rvisSingleByte);

  TrvActionInsertSymbol = class(TrvAction)
  private
    FFontName: String;
    FCharset: TFontCharset;
    FCharCode: Word;
    FUnicode: Boolean;
    FInitialized: Boolean;
    FSymbolType: TRVInsertSymbolType;
    FAlwaysInsertUnicode: Boolean;
    FDisplayUnicodeBlocks: Boolean;
    FUseCurrentFont: Boolean;
  public
    constructor Create(AOwner: TComponent); override;
    procedure ExecuteTarget(Target: TObject); override;
    procedure UpdateTarget(Target: TObject); override;
  published
    property SymbolType: TRVInsertSymbolType read FSymbolType write FSymbolType default rvisBoth;
    property AlwaysInsertUnicode: Boolean read FAlwaysInsertUnicode write FAlwaysInsertUnicode
      default {$IFDEF RVUNICODESTR}True{$ELSE}False{$ENDIF};
    property DisplayUnicodeBlocks: Boolean read FDisplayUnicodeBlocks write FDisplayUnicodeBlocks default True;
    property UseCurrentFont: Boolean read FUseCurrentFont write FUseCurrentFont default False;
  end;

  TRVHyperlinkProperty = (rvhlBold, rvhlItalic, rvhlUnderline, rvhlStrikeout,
                         rvhlColor, rvhlBackColor, rvhlHoverColor, rvhlHoverBackColor,
                         rvhlCursor, rvhlJump);
  TRVHyperlinkProperties = set of TRVHyperlinkProperty;

  TRVHyperlinkFormEvent = procedure (Sender: TObject; InsertNew: Boolean;
    var Text, Target: String; var Proceed: Boolean) of object;
  TRVApplyHyperlinkToItemEvent = procedure (Sender: TObject;
    Editor: TCustomRichViewEdit; RVData: TCustomRVData; ItemNo: Integer;
    const Target: String) of object;
  TRVGetHyperlinkTargetFromItem = procedure (Sender: TObject;
    Editor: TCustomRichViewEdit; RVData: TCustomRVData; ItemNo: Integer;
    var Target: String) of object;
  TRVCanApplyEvent = procedure (Sender: TObject; Editor: TCustomRichViewEdit;
    Item: TCustomRVItemInfo; var CanApply: Boolean) of object;


  TrvActionInsertHyperlink = class(TrvActionTextStyles)
  private
    FColor: TColor;
    FHoverColor: TColor;
    FBackColor: TColor;
    FHoverBackColor: TColor;
    FCursor: TCursor;
    FStyle: TFontStyles;
    FValidProperties: TRVHyperlinkProperties;
    FSetToPictures: Boolean;
    FDefaultFontInfo: TFontInfo;
    FSpaceFiller: String;
    FOnHyperlinkForm: TRVHyperlinkFormEvent;
    FOnApplyHyperlinkToItem: TRVApplyHyperlinkToItemEvent;
    FOnGetHyperlinkTargetFromItem: TRVGetHyperlinkTargetFromItem;
    function DoShowForm(InsertNew: Boolean; var Text, Target: String): Boolean;
  protected
    function IsRecursive: Boolean; override;
    function HasItems(rve: TCustomRichViewEdit; var Target: String): Boolean;
  public
    constructor Create(AOwner: TComponent); override;
    procedure ApplyConversion(Editor: TCustomRichViewEdit; FontInfo: TFontInfo;
      StyleNo, Command: Integer); override;
    procedure ExecuteTarget(Target: TObject); override;
    procedure UpdateTarget(Target: TObject); override;
    procedure GoToLink(rve: TCustomRichViewEdit; id: Integer);
    function EncodeTarget(const Target: String): String;
    procedure SetTags(rve: TCustomRichViewEdit; const Target: String);
    function GetHyperlinkStyleNo(rve: TCustomRichViewEdit; StyleNo: Integer=-1): Integer;
    function GetNormalStyleNo(rve: TCustomRichViewEdit; StyleNo: Integer=-1): Integer;
    procedure TerminateHyperlink(rve: TCustomRichViewEdit);
    procedure DetectURL(rve: TCustomRichViewEdit);
  published
    property Color: TColor read FColor write FColor default clBlue;
    property HoverColor: TColor read FHoverColor write FHoverColor default clBlue;
    property BackColor: TColor read FBackColor write FBackColor default clNone;
    property HoverBackColor: TColor read FHoverBackColor write FHoverBackColor default clNone;
    property Style: TFontStyles read FStyle write FStyle default [fsUnderline];
    property Cursor: TCursor read FCursor write FCursor default crJump;
    property ValidProperties: TRVHyperlinkProperties read FValidProperties write FValidProperties default
      [rvhlUnderline, rvhlColor, rvhlBackColor, rvhlHoverColor, rvhlHoverBackColor, rvhlCursor, rvhlJump];
    property SetToPictures: Boolean read FSetToPictures write FSetToPictures default True;
    property SpaceFiller: String read FSpaceFiller write FSpaceFiller;
    property OnHyperlinkForm: TRVHyperlinkFormEvent read FOnHyperlinkForm write FOnHyperlinkForm;
    property OnApplyHyperlinkToItem: TRVApplyHyperlinkToItemEvent read FOnApplyHyperlinkToItem write FOnApplyHyperlinkToItem;
    property OnGetHyperlinkTargetFromItem: TRVGetHyperlinkTargetFromItem read FOnGetHyperlinkTargetFromItem write FOnGetHyperlinkTargetFromItem;
  end;

  TrvActionHide = class(TrvActionTextStyles)
  protected
    function IsRecursive: Boolean; override;
  public
    constructor Create(AOwner: TComponent); override;
    procedure ApplyConversion(Editor: TCustomRichViewEdit; FontInfo: TFontInfo;
      StyleNo, Command: Integer); override;
    procedure ExecuteTarget(Target: TObject); override;
    procedure UpdateTarget(Target: TObject); override;
  end;

  TrvActionRemoveHyperlinks = class(TrvAction)
  private
    FActionInsertHyperlink: TrvActionInsertHyperlink;
    function GetActionInsertHyperlink: TrvActionInsertHyperlink;
  public
    constructor Create(AOwner: TComponent); override;
    procedure ExecuteTarget(Target: TObject); override;
    procedure UpdateTarget(Target: TObject); override;
  published
    property ActionInsertHyperlink: TrvActionInsertHyperlink read FActionInsertHyperlink
     write FActionInsertHyperlink;
  end;

  { ------------------ Paragraph Styles ------------------------- }

  TrvActionParaStyles = class(TrvAction)
  private
    procedure NewOnParaStyleConversion(Sender: TCustomRichViewEdit; StyleNo, UserData: Integer; AppliedToText: Boolean;
      var NewStyleNo: Integer);
  protected
    procedure ExecuteCommand(rve: TCustomRichViewEdit; Command: Integer);
    procedure ApplyConversion(Editor: TCustomRichViewEdit; ParaInfo: TParaInfo;
      StyleNo, Command: Integer); virtual; abstract;
    function CanApplyToPlainText: Boolean; override;
  public
    constructor Create(AOwner: TComponent); override;
    procedure ExecuteTarget(Target: TObject); override;
  end;

  TRVParaInfoMainProperty = (rvpimFirstIndent, rvpimLeftIndent, rvpimRightIndent,
    rvpimSpaceBefore, rvpimSpaceAfter, rvpimAlignment, rvpimOutlineLevel,
    rvpimLineSpacing, rvpimKeepLinesTogether, rvpimKeepWithNext,
    rvpimTabs);
  TRVParaInfoMainProperties = set of TRVParaInfoMainProperty;

  TrvActionParagraph = class(TrvActionParaStyles)
  private
    FAlignment: TRVAlignment;
    FLineSpacing: TRVLineSpacingValue;
    FLineSpacingType: TRVLineSpacingType;     
    FValidProperties: TRVParaInfoMainProperties;
    FSpaceBefore: TRVStyleLength;
    FLeftIndent: TRVStyleLength;
    FFirstIndent: TRVStyleLength;
    FRightIndent: TRVStyleLength;
    FSpaceAfter: TRVStyleLength;
    FUserInterface: Boolean;
    FKeepWithNext: Boolean;
    FKeepLinesTogether: Boolean;
    FOtlineLevel: Integer;
    FDeleteAllTabs: Boolean;
    FTabsToDelete: TRVIntegerList;
    FTabs: TRVTabInfos;
    procedure SetTabs(const Value: TRVTabInfos);
    procedure SetTabsToDelete(const Value: TRVIntegerList);
  protected
    procedure ApplyConversion(Editor: TCustomRichViewEdit; ParaInfo: TParaInfo;
      StyleNo, Command: Integer); override;
    procedure IterateProc(RVData: TCustomRVData; ItemNo: Integer; rve: TCustomRichViewEdit; var CustomData: Integer); override;
    function ContinueIteration(var CustomData: Integer): Boolean; override;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure ExecuteTarget(Target: TObject); override;
    procedure GetFromEditor(rve: TCustomRichViewEdit);
    property ValidProperties: TRVParaInfoMainProperties read FValidProperties write FValidProperties;
    property LeftIndent: TRVStyleLength read FLeftIndent write FLeftIndent;
    property RightIndent: TRVStyleLength read FRightIndent write FRightIndent;
    property FirstIndent: TRVStyleLength read FFirstIndent write FFirstIndent;
    property SpaceBefore: TRVStyleLength read FSpaceBefore write FSpaceBefore;
    property SpaceAfter: TRVStyleLength read FSpaceAfter write FSpaceAfter;
    property Alignment: TRVAlignment read FAlignment write FAlignment;
    property LineSpacing: TRVLineSpacingValue read FLineSpacing write FLineSpacing;
    property LineSpacingType: TRVLineSpacingType read FLineSpacingType write FLineSpacingType;
    property KeepLinesTogether: Boolean read FKeepLinesTogether write FKeepLinesTogether;
    property KeepWithNext: Boolean read FKeepWithNext write FKeepWithNext;
    property DeleteAllTabs: Boolean read FDeleteAllTabs write FDeleteAllTabs;
    property TabsToDelete: TRVIntegerList read FTabsToDelete write SetTabsToDelete;
    property Tabs: TRVTabInfos read FTabs write SetTabs;
    property OutlineLevel: Integer read FOtlineLevel write FOtlineLevel;
  published
    property UserInterface: Boolean read FUserInterface write FUserInterface default True;
  end;

  TrvActionParaCustomColor = class(TrvActionCustomColor)
  private
    procedure NewOnParaStyleConversion(Sender: TCustomRichViewEdit; StyleNo, UserData: Integer; AppliedToText: Boolean;
      var NewStyleNo: Integer);
  protected
    procedure ExecuteCommand(rve: TCustomRichViewEdit; Command: Integer); override;
    procedure ApplyConversion(Editor: TCustomRichViewEdit; ParaInfo: TParaInfo;
      StyleNo, Command: Integer); virtual; abstract;
  end;

  TrvActionParaColor = class (TrvActionParaCustomColor)
  protected
    function GetCurrentColor(FEdit: TCustomRichViewEdit): TColor; override;
    procedure ApplyConversion(Editor: TCustomRichViewEdit; ParaInfo: TParaInfo;
      StyleNo, Command: Integer); override;
  public
    constructor Create(AOwner: TComponent); override;
  end;

  TrvActionParaColorAndPadding = class (TrvActionParaColor)
  private
    FUsePadding: TRVBooleanRect;
    FPadding: TRVRect;
    procedure SetPadding(const Value: TRVRect);
    procedure SetUsePadding(const Value: TRVBooleanRect);
  protected
    procedure ApplyConversion(Editor: TCustomRichViewEdit; ParaInfo: TParaInfo;
      StyleNo, Command: Integer); override;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    property Padding: TRVRect read FPadding write SetPadding;
    property UsePadding: TRVBooleanRect read FUsePadding write SetUsePadding;
  end;

  TrvActionAlignment = class(TrvActionParaStyles)
  protected
    FAlignment: TRVAlignment;
    procedure ApplyConversion(Editor: TCustomRichViewEdit; ParaInfo: TParaInfo;
      StyleNo, Command: Integer); override;
    procedure IterateProc(RVData: TCustomRVData; ItemNo: Integer;
      rve: TCustomRichViewEdit; var CustomData: Integer); override;
    function ContinueIteration(var CustomData: Integer): Boolean; override;      
  public
    procedure UpdateTarget(Target: TObject); override;
  end;

  TrvActionAlignLeft = class(TrvActionAlignment)
  public
    constructor Create(AOwner: TComponent); override;
  end;

  TrvActionAlignCenter = class(TrvActionAlignment)
  public
    constructor Create(AOwner: TComponent); override;
  end;

  TrvActionAlignRight = class(TrvActionAlignment)
  public
    constructor Create(AOwner: TComponent); override;
  end;

  TrvActionAlignJustify = class(TrvActionAlignment)
  public
    constructor Create(AOwner: TComponent); override;
  end;

  TrvActionParaBiDi = class (TrvActionParaStyles)
  private
    FBiDiMode: TRVBiDiMode;
  protected
    procedure ApplyConversion(Editor: TCustomRichViewEdit; ParaInfo: TParaInfo;
      StyleNo, Command: Integer); override;
    procedure IterateProc(RVData: TCustomRVData; ItemNo: Integer;
      rve: TCustomRichViewEdit; var CustomData: Integer); override;
    function ContinueIteration(var CustomData: Integer): Boolean; override;      
  public
    procedure UpdateTarget(Target: TObject); override;
  end;

  TrvActionParaLTR = class (TrvActionParaBiDi)
  public
    constructor Create(AOwner: TComponent); override;
  end;

  TrvActionParaRTL = class (TrvActionParaBiDi)
  public
    constructor Create(AOwner: TComponent); override;
  end;

  TrvActionIndent = class(TrvActionParaStyles)
  protected
    FIndentStep, FIndentStepTmp: TRVStyleLength;
  public
    constructor Create(AOwner: TComponent); override;
    procedure ExecuteTarget(Target: TObject); override;
    procedure ConvertToPixels; override;
    procedure ConvertToTwips; override;
  published
    property IndentStep: TRVStyleLength read FIndentStep write FIndentStep default 24;
  end;

  TrvActionIndentInc = class(TrvActionIndent)
  private
    FIndentMax, FIndentMaxTmp: TRVStyleLength;
  protected
    procedure ApplyConversion(Editor: TCustomRichViewEdit; ParaInfo: TParaInfo;
      StyleNo, Command: Integer); override;
  public
    constructor Create(AOwner: TComponent); override;
    procedure ExecuteTarget(Target: TObject); override;
    procedure ConvertToPixels; override;
    procedure ConvertToTwips; override;
  published
    property IndentMax: TRVStyleLength read FIndentMax write FIndentMax default 240;
  end;

  TrvActionIndentDec = class(TrvActionIndent)
  protected
    procedure ApplyConversion(Editor: TCustomRichViewEdit; ParaInfo: TParaInfo;
      StyleNo, Command: Integer); override;
  public
    constructor Create(AOwner: TComponent); override;
    procedure ExecuteTarget(Target: TObject); override;
  end;

  TrvActionWordWrap = class(TrvActionParaStyles)
  protected
    procedure ApplyConversion(Editor: TCustomRichViewEdit; ParaInfo: TParaInfo;
      StyleNo, Command: Integer); override;
    procedure IterateProc(RVData: TCustomRVData; ItemNo: Integer;
      rve: TCustomRichViewEdit; var CustomData: Integer); override;
    function ContinueIteration(var CustomData: Integer): Boolean; override;      
  public
    constructor Create(AOwner: TComponent); override;
    procedure UpdateTarget(Target: TObject); override;
  end;

  TrvActionLineSpacing = class(TrvActionParaStyles)
  private
    FLineSpacing: Integer;
  protected
    procedure ApplyConversion(Editor: TCustomRichViewEdit; ParaInfo: TParaInfo;
      StyleNo, Command: Integer); override;
    procedure IterateProc(RVData: TCustomRVData; ItemNo: Integer;
      rve: TCustomRichViewEdit; var CustomData: Integer); override;
    function ContinueIteration(var CustomData: Integer): Boolean; override;      
  public
    procedure UpdateTarget(Target: TObject); override;
  end;

  TrvActionLineSpacing100 = class(TrvActionLineSpacing)
  public
    constructor Create(AOwner: TComponent); override;
  end;

  TrvActionLineSpacing150 = class(TrvActionLineSpacing)
  public
    constructor Create(AOwner: TComponent); override;
  end;

  TrvActionLineSpacing200 = class(TrvActionLineSpacing)
  public
    constructor Create(AOwner: TComponent); override;
  end;

  TRVParaInfoBorderProperty = (
                         rvpibBackground_Color,
                         rvpibBackground_BO_Left, rvpibBackground_BO_Top,
                         rvpibBackground_BO_Right, rvpibBackground_BO_Bottom,
                         rvpibBorder_Color, rvpibBorder_Style,
                         rvpibBorder_Width, rvpibBorder_InternalWidth,
                         rvpibBorder_BO_Left,
                         rvpibBorder_BO_Top,
                         rvpibBorder_BO_Right,
                         rvpibBorder_BO_Bottom,
                         rvpibBorder_Vis_Left,
                         rvpibBorder_Vis_Top,
                         rvpibBorder_Vis_Right,
                         rvpibBorder_Vis_Bottom);
  TRVParaInfoBorderProperties = set of TRVParaInfoBorderProperty;

  TrvActionParaBorder = class(TrvActionParaStyles)
  private
    FUserInterface: Boolean;
    FBorder: TRVBorder;
    FValidProperties: TRVParaInfoBorderProperties;
    FBackground: TRVBackgroundRect;
    procedure SetBorder(const Value: TRVBorder);
    procedure SetBackground(const Value: TRVBackgroundRect);
  protected
    procedure ApplyConversion(Editor: TCustomRichViewEdit; ParaInfo: TParaInfo;
      StyleNo, Command: Integer); override;
    procedure IterateProc(RVData: TCustomRVData; ItemNo: Integer;
      rve: TCustomRichViewEdit; var CustomData: Integer); override;
    function ContinueIteration(var CustomData: Integer): Boolean; override;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure ExecuteTarget(Target: TObject); override;
    procedure GetFromEditor(rve: TCustomRichViewEdit);
    property ValidProperties: TRVParaInfoBorderProperties read FValidProperties write FValidProperties;
    property Border: TRVBorder read FBorder write SetBorder;
    property Background: TRVBackgroundRect read FBackground write SetBackground;
  published
    property UserInterface: Boolean read FUserInterface write FUserInterface default True;
  end;

  { ------------------ Misc ------------------------------------- }

  TrvActionShowSpecialCharacters = class(TrvAction)
  public
    constructor Create(AOwner: TComponent); override;
    procedure ExecuteTarget(Target: TObject); override;
    procedure UpdateTarget(Target: TObject); override;
  end;

  TrvActionColor = class(TrvActionCustomColor)
  protected
    procedure ExecuteCommand(rve: TCustomRichViewEdit; Command: Integer); override;
    function GetCurrentColor(FEdit: TCustomRichViewEdit): TColor; override;
  public
    constructor Create(AOwner: TComponent); override;
    procedure UpdateTarget(Target: TObject); override;
  end;

  TRVAFillColorApplyToElement = (rvafcaText, rvafcaParagraph, rvafcaCell, rvafcaTable);
  TRVAFillColorApplyToSet = set of TRVAFillColorApplyToElement;

  TrvActionFillColor = class(TrvAction)
  private
    FTextColor, FParaColor: TColor;
    Padding: TRVRect;
    UsePadding: TRVBooleanRect;
    FTextColorSet, FParaColorSet: Boolean;
    FTextColorMultiple, FParaColorMultiple: Boolean;
    FAllowApplyingTo: TRVAFillColorApplyToSet;
  protected
    procedure IterateProc(RVData: TCustomRVData; ItemNo: Integer; rve: TCustomRichViewEdit; var CustomData: Integer); override;
    function CanApplyToPlainText: Boolean; override;
  public
    constructor Create(AOwner: TComponent); override;
    procedure ExecuteTarget(Target: TObject); override;
  published
    property AllowApplyingTo: TRVAFillColorApplyToSet read FAllowApplyingTo write FAllowApplyingTo default [rvafcaText..rvafcaTable];
  end;

  TrvActionInsertPageBreak = class(TrvAction)
  protected
    function RequiresMainDoc: Boolean; override;
  public
    constructor Create(AOwner: TComponent); override;
    procedure ExecuteTarget(Target: TObject); override;
    procedure UpdateTarget(Target: TObject); override;
  end;

  TrvActionRemovePageBreak = class(TrvAction)
  protected
    function RequiresMainDoc: Boolean; override;
  public
    constructor Create(AOwner: TComponent); override;
    procedure ExecuteTarget(Target: TObject); override;
    procedure UpdateTarget(Target: TObject); override;
  end;

  TrvActionClearTextFlow = class(TrvAction)
  protected
    function ClearLeft: Boolean; dynamic;
    function ClearRight: Boolean; dynamic;
  public
    procedure ExecuteTarget(Target: TObject); override;
    procedure UpdateTarget(Target: TObject); override;
  end;

  TrvActionClearLeft = class(TrvActionClearTextFlow)
  protected
    function ClearLeft: Boolean; override;
  public
    constructor Create(AOwner: TComponent); override;
  end;

  TrvActionClearRight = class(TrvActionClearTextFlow)
  protected
    function ClearRight: Boolean; override;
  public
    constructor Create(AOwner: TComponent); override;
  end;

  TrvActionClearNone = class(TrvActionClearTextFlow)
  public
    constructor Create(AOwner: TComponent); override;
  end;

  TrvActionClearBoth = class(TrvActionClearTextFlow)
  protected
    function ClearLeft: Boolean; override;
    function ClearRight: Boolean; override;
  public
    constructor Create(AOwner: TComponent); override;
  end;


  TrvActionItemProperties = class (TrvAction)
  private
    FGraphicFilter: String;
    FStoreImageFileName: Boolean;
    FBackgroundGraphicFilter: String;
    FOnCustomItemPropertiesDialog: TRVCustomItemPropertiesDialog;
    FOnCanApply: TRVCanApplyEvent;
  public
    constructor Create(AOwner: TComponent); override;
    procedure ExecuteTarget(Target: TObject); override;
    procedure UpdateTarget(Target: TObject); override;
  published
    property GraphicFilter: String read FGraphicFilter write FGraphicFilter;
    property BackgroundGraphicFilter: String read FBackgroundGraphicFilter write FBackgroundGraphicFilter;
    property OnCustomItemPropertiesDialog: TRVCustomItemPropertiesDialog
      read FOnCustomItemPropertiesDialog write FOnCustomItemPropertiesDialog;
    property OnCanApply: TRVCanApplyEvent read FOnCanApply write FOnCanApply;
    property StoreImageFileName: Boolean
      read FStoreImageFileName write FStoreImageFileName default False;
  end;

  TrvActionVAlign = class (TrvAction)
  public
    constructor Create(AOwner: TComponent); override;
    procedure ExecuteTarget(Target: TObject); override;
    procedure UpdateTarget(Target: TObject); override;
  end;

  TrvActionBackground = class (TrvAction)
  private
    FOnChange: TRVAEditEvent;
    FImageFileName: String;
    FCanChangeMargins: Boolean;
  public
    constructor Create(AOwner: TComponent); override;
    procedure ExecuteTarget(Target: TObject); override;
    procedure UpdateTarget(Target: TObject); override;
    property ImageFileName: String read FImageFileName;
    property OnChange: TRVAEditEvent read FOnChange write FOnChange;
  published
    property CanChangeMargins: Boolean read FCanChangeMargins write FCanChangeMargins default True;
  end;

  { ------------------ Tables ----------------------------------- }

  TrvActionInsertTable = class;

  TRVAInsertTableEvent = procedure (Sender: TrvActionInsertTable; table: TRVTableItemInfo) of object;

  TrvActionInsertTable = class(TrvAction)
  private
    FEdit: TCustomRichViewEdit;
    FTableSizeForm : TForm;
    FVOutermostRule: Boolean;
    FHOutermostRule: Boolean;
    FCellHSpacing: TRVStyleLength;
    FCellPadding: TRVStyleLength;
    FBorderWidth: TRVStyleLength;
    FCellVSpacing: TRVStyleLength;
    FHRuleWidth: TRVStyleLength;
    FCellBorderWidth: TRVStyleLength;
    FBorderHSpacing: TRVStyleLength;
    FBorderVSpacing: TRVStyleLength;
    FVRuleWidth: TRVStyleLength;
    FBorderLightColor: TColor;
    FBorderColor: TColor;
    FCellBorderColor: TColor;
    FHRuleColor: TColor;
    FColor: TColor;
    FCellBorderLightColor: TColor;
    FVRuleColor: TColor;
    FBestWidth: TRVHTMLLength;
    FBorderStyle: TRVTableBorderStyle;
    FCellBorderStyle: TRVTableBorderStyle;
    FOptions: TRVTableOptions;
    FPrintOptions: TRVTablePrintOptions;
    FColCount: Integer;
    FRowCount: Integer;
    FHeadingRowCount: Integer;
    FOnInserting: TRVAInsertTableEvent;
    FOnCloseTableSizeDialog: TNotifyEvent;
    FItemText: String;
    procedure ApplyToTable(table: TRVTableItemInfo; ABestWidth: TRVHTMLLength);
    procedure SetTableCellsWidth(table: TRVTableItemInfo; Width: TRVStyleLength);
    procedure TableSizeFormDestroy(Sender: TObject);
  protected
    procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  public
    procedure ExecuteTarget(Target: TObject); override;
    procedure ShowTableSizeDialog(Target: TCustomRichViewEdit; Button: TControl); overload;
    procedure ShowTableSizeDialog(Target: TCustomRichViewEdit; const ButtonRect: TRect); overload;
    procedure UpdateTarget(Target: TObject); override;
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure Localize; override;
    procedure ConvertToPixels; override;
    procedure ConvertToTwips; override;    
  published
    property RowCount: Integer read FRowCount write FRowCount default 2;
    property ColCount: Integer read FColCount write FColCount default 2;
    property TableOptions: TRVTableOptions read FOptions write FOptions default RVTABLEDEFAULTOPTIONS;
    property TablePrintOptions: TRVTablePrintOptions read FPrintOptions write FPrintOptions default RVTABLEDEFAULTPRINTOPTIONS;
    property BestWidth: TRVHTMLLength read FBestWidth write FBestWidth default 0;
    property Color: TColor read FColor write FColor default clNone;
    property HeadingRowCount: Integer read FHeadingRowCount write FHeadingRowCount default 0;
    // Border around the table:
    property BorderWidth: TRVStyleLength read FBorderWidth write FBorderWidth default 1;
    property BorderColor: TColor read FBorderColor write FBorderColor default clWindowText;
    property BorderLightColor: TColor read FBorderLightColor write FBorderLightColor default clBtnHighlight;
    property BorderStyle: TRVTableBorderStyle read FBorderStyle write FBorderStyle default rvtbColor;
    property BorderVSpacing: TRVStyleLength read FBorderVSpacing write FBorderVSpacing default 2;
    property BorderHSpacing: TRVStyleLength read FBorderHSpacing write FBorderHSpacing default 2;
    // Cells:
    property CellBorderWidth: TRVStyleLength read FCellBorderWidth write FCellBorderWidth default 1;
    property CellBorderColor: TColor read FCellBorderColor write FCellBorderColor default clWindowText;
    property CellBorderLightColor: TColor read FCellBorderLightColor write FCellBorderLightColor default clBtnHighlight;
    property CellPadding: TRVStyleLength read FCellPadding write FCellPadding default 1;
    property CellBorderStyle: TRVTableBorderStyle read FCellBorderStyle write FCellBorderStyle default rvtbColor;
    // Between cells:
    property VRuleWidth: TRVStyleLength read FVRuleWidth write FVRuleWidth default 0;
    property VRuleColor: TColor read FVRuleColor write FVRuleColor default clWindowText;
    property HRuleWidth: TRVStyleLength read FHRuleWidth write FHRuleWidth default 0;
    property HRuleColor: TColor  read FHRuleColor write FHRuleColor default clWindowText;
    property CellVSpacing: TRVStyleLength read FCellVSpacing write FCellVSpacing default 2;
    property CellHSpacing: TRVStyleLength read FCellHSpacing write FCellHSpacing default 2;
    property VOutermostRule: Boolean read FVOutermostRule write FVOutermostRule default False;
    property HOutermostRule: Boolean read FHOutermostRule write FHOutermostRule default False;
    // Item text
    property ItemText: String read FItemText write FItemText;
    // events
    property OnInserting: TRVAInsertTableEvent read FOnInserting write FOnInserting;
    property OnCloseTableSizeDialog: TNotifyEvent read FOnCloseTableSizeDialog write FOnCloseTableSizeDialog;
  end;

  TrvActionTableCell = class(TrvAction)
  protected
    function ExecuteCommand(rve: TCustomRichViewEdit; table: TRVTableItemInfo;
      ItemNo: Integer): Boolean; virtual; abstract;
    function IsApplicable(rve: TCustomRichViewEdit; table: TRVTableItemInfo;
      ItemNo: Integer): Boolean; virtual; abstract;
  public
    procedure ExecuteTarget(Target: TObject); override;
    procedure UpdateTarget(Target: TObject); override;
  end;

  TrvActionTableRCBase = class(TrvActionTableCell)
  protected
    function IsApplicable(rve: TCustomRichViewEdit; table: TRVTableItemInfo;
      ItemNo: Integer): Boolean; override;
  end;

  TrvActionTableInsertRowsAbove = class(TrvActionTableRCBase)
  protected
    function ExecuteCommand(rve: TCustomRichViewEdit; table: TRVTableItemInfo;
      ItemNo: Integer): Boolean; override;
  public
    constructor Create(AOwner: TComponent); override;
  end;

  TrvActionTableInsertRowsBelow = class(TrvActionTableRCBase)
  private
    FAllowMultiple: Boolean;
  protected
    function ExecuteCommand(rve: TCustomRichViewEdit; table: TRVTableItemInfo;
      ItemNo: Integer): Boolean; override;
  public
    constructor Create(AOwner: TComponent); override;
  published
    property AllowMultiple: Boolean read FAllowMultiple write FAllowMultiple;
  end;

  TrvActionTableInsertColLeft = class(TrvActionTableRCBase)
  protected
    function ExecuteCommand(rve: TCustomRichViewEdit; table: TRVTableItemInfo;
      ItemNo: Integer): Boolean; override;
  public
    constructor Create(AOwner: TComponent); override;
  end;

  TrvActionTableInsertColRight = class(TrvActionTableRCBase)
  protected
    function ExecuteCommand(rve: TCustomRichViewEdit; table: TRVTableItemInfo;
      ItemNo: Integer): Boolean; override;
  public
    constructor Create(AOwner: TComponent); override;
  end;

  TrvActionTableDeleteRows = class(TrvActionTableRCBase)
  protected
    function ExecuteCommand(rve: TCustomRichViewEdit; table: TRVTableItemInfo;
      ItemNo: Integer): Boolean; override;
  public
    constructor Create(AOwner: TComponent); override;
  end;

  TrvActionTableDeleteCols = class(TrvActionTableRCBase)
  protected
    function ExecuteCommand(rve: TCustomRichViewEdit; table: TRVTableItemInfo;
      ItemNo: Integer): Boolean; override;
  public
    constructor Create(AOwner: TComponent); override;
  end;

  TrvActionTableDeleteTable = class (TrvActionTableCell)
  protected
    function ExecuteCommand(rve: TCustomRichViewEdit; table: TRVTableItemInfo;
      ItemNo: Integer): Boolean; override;
    function IsApplicable(rve: TCustomRichViewEdit; table: TRVTableItemInfo;
      ItemNo: Integer): Boolean; override;
  public
    constructor Create(AOwner: TComponent); override;
  end;

  TrvActionTableMergeCells = class(TrvActionTableCell)
  protected
    function ExecuteCommand(rve: TCustomRichViewEdit; table: TRVTableItemInfo;
      ItemNo: Integer): Boolean; override;
    function IsApplicable(rve: TCustomRichViewEdit; table: TRVTableItemInfo;
      ItemNo: Integer): Boolean; override;
  public
    constructor Create(AOwner: TComponent); override;
  end;

  TrvActionTableSplitCells = class(TrvActionTableCell)
  protected
    function ExecuteCommand(rve: TCustomRichViewEdit; table: TRVTableItemInfo;
      ItemNo: Integer): Boolean; override;
    function IsApplicable(rve: TCustomRichViewEdit; table: TRVTableItemInfo;
      ItemNo: Integer): Boolean; override;
  public
    constructor Create(AOwner: TComponent); override;
  end;

  TrvActionTableSelectTable = class(TrvActionTableCell)
  protected
    function IsApplicable(rve: TCustomRichViewEdit; table: TRVTableItemInfo;
      ItemNo: Integer): Boolean; override;
    function ExecuteCommand(rve: TCustomRichViewEdit; table: TRVTableItemInfo;
      ItemNo: Integer): Boolean; override;
  public
    constructor Create(AOwner: TComponent); override;
  end;

  TrvActionTableSelectRows = class(TrvActionTableRCBase)
  protected
    function ExecuteCommand(rve: TCustomRichViewEdit; table: TRVTableItemInfo;
      ItemNo: Integer): Boolean; override;
  public
    constructor Create(AOwner: TComponent); override;
  end;

  TrvActionTableSelectCols = class(TrvActionTableRCBase)
  protected
    function ExecuteCommand(rve: TCustomRichViewEdit; table: TRVTableItemInfo;
      ItemNo: Integer): Boolean; override;
  public
    constructor Create(AOwner: TComponent); override;
  end;

  TrvActionTableSelectCell = class(TrvActionTableCell)
  protected
    function IsApplicable(rve: TCustomRichViewEdit; table: TRVTableItemInfo;
      ItemNo: Integer): Boolean; override;
    function ExecuteCommand(rve: TCustomRichViewEdit; table: TRVTableItemInfo;
      ItemNo: Integer): Boolean; override;
  public
    constructor Create(AOwner: TComponent); override;
  end;

  TrvActionTableMultiCellAttributes = class(TrvActionTableCell)
  protected
    function IterateCellProc(table: TRVTableItemInfo; FirstCell: Boolean; Row, Col, CustomData: Integer): Boolean; virtual;
    procedure IterateCells(table: TRVTableItemInfo; CustomData: Integer);
  end;

  TrvActionTableCellVAlign = class(TrvActionTableMultiCellAttributes)
  private
    FVAlign: TRVCellVAlign;
    FAllEqual: Boolean;
  protected
    function IterateCellProc(table: TRVTableItemInfo; FirstCell: Boolean; Row, Col, CustomData: Integer): Boolean; override;
    function IsApplicable(rve: TCustomRichViewEdit; table: TRVTableItemInfo;
      ItemNo: Integer): Boolean; override;
    function ExecuteCommand(rve: TCustomRichViewEdit; table: TRVTableItemInfo;
      ItemNo: Integer): Boolean; override;
  end;

  TrvActionTableCellVAlignTop = class (TrvActionTableCellVAlign)
  public
    constructor Create(AOwner: TComponent); override;
  end;

  TrvActionTableCellVAlignMiddle = class (TrvActionTableCellVAlign)
  public
    constructor Create(AOwner: TComponent); override;
  end;

  TrvActionTableCellVAlignBottom = class (TrvActionTableCellVAlign)
  public
    constructor Create(AOwner: TComponent); override;
  end;

  TrvActionTableCellVAlignDefault = class (TrvActionTableCellVAlign)
  public
    constructor Create(AOwner: TComponent); override;
  end;

  TrvActionTableProperties = class (TrvActionTableCell)
  private
    FBackgroundGraphicFilter: String;
    FStoreImageFileName: Boolean;
  protected
    function ExecuteCommand(rve: TCustomRichViewEdit; table: TRVTableItemInfo;
      ItemNo: Integer): Boolean; override;
    function IsApplicable(rve: TCustomRichViewEdit; table: TRVTableItemInfo;
      ItemNo: Integer): Boolean; override;
  public
    constructor Create(AOwner: TComponent); override;
  published
    property BackgroundGraphicFilter: String
      read FBackgroundGraphicFilter write FBackgroundGraphicFilter;
    property StoreImageFileName: Boolean
      read FStoreImageFileName write FStoreImageFileName default False;
  end;

  TrvActionTableGrid = class(TrvCustomAction)
  public
    function HandlesTarget(Target: TObject): Boolean; override;
    procedure UpdateTarget(Target: TObject); override;
    procedure ExecuteTarget(Target: TObject); override;
    constructor Create(AOwner: TComponent); override;
  end;

  TrvActionTableCellBorder = class(TrvActionTableMultiCellAttributes)
  private
    FAllEqual: Boolean;
  protected
    function IsBordered(aVisibleBorders: TRVBooleanRect): Boolean;
      virtual; abstract;
    procedure SetBorder(table: TRVTableItemInfo; r,c: Integer;
      const aValue: Boolean); virtual; abstract;
    function IsApplicable(rve: TCustomRichViewEdit;
      table: TRVTableItemInfo; ItemNo: Integer): Boolean; override;
    function IterateCellProc(table: TRVTableItemInfo; FirstCell: Boolean;
      Row: Integer; Col: Integer; CustomData: Integer): Boolean; override;
    function ExecuteCommand(rve: TCustomRichViewEdit;
      table: TRVTableItemInfo; ItemNo: Integer): Boolean; override;
  end;

  TrvActionTableCellLeftBorder = class(TrvActionTableCellBorder)
  protected
    function IsBordered(aVisibleBorders: TRVBooleanRect): Boolean;
      override;
    procedure SetBorder(table: TRVTableItemInfo; r,c: Integer;
      const aValue: Boolean); override;
  public
    constructor Create(AOwner: TComponent); override;
  end;

  TrvActionTableCellRightBorder = class(TrvActionTableCellBorder)
  protected
    function IsBordered(aVisibleBorders: TRVBooleanRect): Boolean;
      override;
    procedure SetBorder(table: TRVTableItemInfo; r,c: Integer;
      const aValue: Boolean); override;
  public
    constructor Create(AOwner: TComponent); override;
  end;

  TrvActionTableCellTopBorder = class(TrvActionTableCellBorder)
  protected
    function IsBordered(aVisibleBorders: TRVBooleanRect): Boolean;
      override;
    procedure SetBorder(table: TRVTableItemInfo; r,c: Integer;
      const aValue: Boolean); override;
  public
    constructor Create(AOwner: TComponent); override;
  end;

  TrvActionTableCellBottomBorder = class(TrvActionTableCellBorder)
  protected
    function IsBordered(aVisibleBorders: TRVBooleanRect): Boolean;
      override;
    procedure SetBorder(table: TRVTableItemInfo; r,c: Integer;
      const aValue: Boolean); override;
  public
    constructor Create(AOwner: TComponent); override;
  end;

  TrvActionTableCellAllBorders = class(TrvActionTableCellBorder)
  protected
    function IsBordered(aVisibleBorders: TRVBooleanRect): Boolean;
      override;
    procedure SetBorder(table: TRVTableItemInfo; r,c: Integer;
      const aValue: Boolean); override;
  public
    constructor Create(AOwner: TComponent); override;
  end;

  TrvActionTableCellNoBorders = class(TrvActionTableCellBorder)
  protected
    function IsApplicable(rve: TCustomRichViewEdit;
      table: TRVTableItemInfo; ItemNo: Integer): Boolean; override;
    function ExecuteCommand(rve: TCustomRichViewEdit;
      table: TRVTableItemInfo; ItemNo: Integer): Boolean; override;
    procedure SetBorder(table: TRVTableItemInfo; r,c: Integer;
      const aValue: Boolean); override;
  public
    constructor Create(AOwner: TComponent); override;
  end;

  { ------------------ List Styles ------------------------- }
  TrvActionParaBullets = class;
  TrvActionParaNumbering = class;

  TrvActionParaList = class(TrvAction)
  private
    FUpdateAllActionsOnForm: Boolean;
    FActionParaBullets: TrvActionParaBullets;
    FActionParaNumbering: TrvActionParaNumbering;
    FIndentStep: TRVStyleLength;
    procedure SetActionParaBullets(const Value: TrvActionParaBullets);
    procedure SetActionParaNumbering(const Value: TrvActionParaNumbering);
    procedure UpdateBulletsAction(RVStyle: TRVStyle; ListNo: Integer);
    procedure UpdateNumberingAction(RVStyle: TRVStyle; ListNo: Integer);
    function ShowForm(rve: TCustomRichViewEdit; var ListStyle: TRVListInfo;
      var ListNo, StartFrom: Integer; var UseStartFrom: Boolean): TForm;
  protected
    procedure Notification(AComponent: TComponent; Operation: TOperation); override;
    function CanApplyToPlainText: Boolean; override;
  public
    procedure ExecuteTarget(Target: TObject); override;
    constructor Create(AOwner: TComponent); override;
    procedure ConvertToPixels; override;
    procedure ConvertToTwips; override;
    property ActionParaBullets: TrvActionParaBullets read FActionParaBullets write SetActionParaBullets;
    property ActionParaNumbering: TrvActionParaNumbering read FActionParaNumbering write SetActionParaNumbering;
    property UpdateAllActionsOnForm: Boolean read FUpdateAllActionsOnForm write FUpdateAllActionsOnForm default True;
  published
    property IndentStep: TRVStyleLength read FIndentStep write FIndentStep default 24;
  end;

  TrvActionCustomParaListSwitcher = class(TrvAction)
  private
    FListLevels: TRVListLevelCollection;
    FIndentStep: TRVStyleLength;
    procedure SetListLevels(const Value: TRVListLevelCollection);
    function StoreListLevels: Boolean;
    procedure SetIndentStep(const Value: TRVStyleLength);
  protected
    procedure ResetLevels(AListLevels: TRVListLevelCollection); dynamic; abstract;
    function GetTempLevels(RVStyle: TRVStyle): TRVListLevelCollection;    
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure Reset;
    procedure UpdateTarget(Target: TObject); override;
    procedure ConvertToPixels; override;
    procedure ConvertToTwips; override;
  published
    property IndentStep: TRVStyleLength read FIndentStep write SetIndentStep default 24;
    property ListLevels: TRVListLevelCollection read FListLevels write SetListLevels stored StoreListLevels;
  end;

  TrvActionParaBullets = class(TrvActionCustomParaListSwitcher)
  protected
    procedure ResetLevels(AListLevels: TRVListLevelCollection); override;
  public
    constructor Create(AOwner: TComponent); override;
    procedure ExecuteTarget(Target: TObject); override;
  end;

  TrvActionParaNumbering = class(TrvActionCustomParaListSwitcher)
  protected
    procedure ResetLevels(AListLevels: TRVListLevelCollection); override;
  public
    constructor Create(AOwner: TComponent); override;
    procedure ExecuteTarget(Target: TObject); override;
  end;

  {$IFDEF USERVADDICT3}
  TrvActionAddictSpell3 = class(TrvAction)
  public
    constructor Create(AOwner: TComponent); override;
    procedure UpdateTarget(Target: TObject); override;
    procedure ExecuteTarget(Target: TObject); override;
  end;

  TrvActionAddictThesaurus3 = class(TrvAction)
  public
    constructor Create(AOwner: TComponent); override;
    procedure UpdateTarget(Target: TObject); override;
    procedure ExecuteTarget(Target: TObject); override;
  end;
  {$ENDIF}

  TRVAEvents = class
    private
      {$IFDEF RVAUSEHTTPDOWNLOADER}
      FDownloadedPictures: TStringList;
      FSender: TRVAction;
      {$ENDIF}
      FOnAddStyle: TRVAddStyleEvent;
      FOnStyleNeeded: TRVStyleNeededEvent;
      FOnMarginsChanged: TRVAEditEvent;
      FOnViewChanged: TRVAEditEvent2;      
      FOnCustomFileOperation: TRVCustomFileOperationEvent;
      FOnDownload: TRVADownloadEvent;
      FOnBackgroundChange: TRVAEditEvent;
      {$IFDEF USERVKSDEVTE}
      FOnCreateTeForm: TRVCreateTeFormEvent;
      {$ENDIF}
    public
      procedure DoOnBackgroundChange(Sender: TrvAction; Edit: TCustomRichViewEdit);
      procedure DoOnDownload(Sender: TrvAction; const Source: String);
      procedure DoOnAddStyle(Sender: TrvAction; StyleInfo: TCustomRVInfo);
      function DoStyleNeeded(Sender: TrvAction; RVStyle: TRVStyle;
        StyleInfo: TCustomRVInfo): Integer;
      procedure DoOnMarginsChanged(Sender: TrvAction; Edit: TCustomRichViewEdit);
      procedure DoOnViewChanged(Sender: TrvCustomAction; Edit: TCustomRichViewEdit);
      function DoOnCustomFileOperation(Sender: TrvAction; Edit: TCustomRichViewEdit;
        const FileName: String; Operation: TRVAFileOperation;
        var SaveFormat: TrvFileSaveFilter;
        var CustomFilterIndex: Integer): Boolean;
      procedure DoImportPicture(Sender: TCustomRichView; const Location: String;
        Width, Height: Integer; var Graphic: TGraphic);
      procedure InitImportPictures(Sender: TRVAction);
      procedure DoneImportPictures;
      {$IFDEF USERVKSDEVTE}
      procedure DoOnCreateTeForm(Sender: TForm; teForm: TTeForm);
      {$ENDIF}
  end;

  TRVAEditorControlCommandFunction =
    function (Control: TControl; Command: TRVAEditorControlCommand): Boolean;

  TRVAGetRichViewEditFromPopupComponentFunction =
    function (PopupComponent: TComponent): TCustomRichViewEdit;

  TRVAGetRichViewEditFunction = function (Target: TCustomRichViewEdit;
    MainDoc: Boolean): TCustomRichViewEdit;

function RVA_EditorControlFunctionDef(Control: TControl;
  Command: TRVAEditorControlCommand): Boolean;
function RvHtmlHelp(HelpFileName: TRVUnicodeString): Boolean;

function GetRichViewEditFromPopupComponent(
  PopupComponent: TComponent): TCustomRichViewEdit;



var RVA_DialogFontName: TFontName;
    RVA_DialogFontSize: Integer;
    RVA_DefaultMargin, RVA_FirstPageNumber: Integer;
    RVA_DefaultColor: TColor;
    RVA_UseXPThemes, RVA_AutoDeleteUnusedStyles,
    RVA_RVFLocalizable, RVA_XMLLocalizable: Boolean;
    RVA_DefaultControl: TCustomRichViewEdit;
    RVA_ColorDialog: TColorDialog;
    RVA_TableGridStyle: TPenStyle;
    RVA_RVPrint: TRVPrint;
    RVA_ShowSoftPageBreaks, RVA_ActionsEnabled, RVA_UseHelpFiles,
    RVA_AddColorNameToHints: Boolean;
    {$IFDEF USEINDY}
    RVA_IdHTTP: TIdHTTP;
    {$ENDIF}
    {$IFDEF USECLEVERCOMPONENTS}
    RVA_ClHTTP: TClHTTP;
    {$ENDIF}
    {$IFDEF USERVXML}
    RVA_RVXML: TRichViewXML;
    {$ENDIF}
    {$IFDEF USERVHTML}
    RVA_RVHTML: TRvHtmlImporter;
    {$ENDIF}
    {$IFDEF USERVHTMLVIEWER}
    RVA_RVHTMLView: TRVHTMLViewImporter;
    {$ENDIF}
    {$IFDEF USERVADDICT3}
    RVA_Addict3: TRVAddictSpell3;
    RVA_Thes3: TRVThesaurus3;
    {$ENDIF}
    RVA_RVFormatName, RVA_DefaultExt, RVA_DefaultFileName,
    RVA_RVFFilter {$IFDEF USERVXML}, RVA_XMLFilter{$ENDIF}: String;
    RVA_DefaultFileFormat: TrvFileSaveFilter;
    RVA_DefaultCustomFilterIndex: Integer;
    RVA_SearchScope: TRVASearchScope;
    RVA_Events: TRVAEvents;
    RVA_EditorControlFunction: TRVAEditorControlCommandFunction;
    RVA_GetRichViewEditFromPopupComponent: TRVAGetRichViewEditFromPopupComponentFunction=nil;
    RVA_GetRichViewEdit: TRVAGetRichViewEditFunction=nil;
    RVA_UserInterface: TRVAUserInterface;
    {$IFNDEF RVDONOTUSEDOCPARAMS}
    RVA_DocParameters: TRVDocParameters;
    {$ENDIF}
    RVA_DocumentInfoClass: TrvaDocumentInfoClass = TrvaDocumentInfo;
    RVA_Units: TRVUnits = rvuPixels;
    RVA_UnitsProgram: TRVStyleUnits = rvstuPixels;
    RVA_PixelBorders: Boolean = False;


function RVA_GetComboBorderWidth(Index: Integer): Integer;
function RVA_GetComboBorderWidth2(Index: Integer; RVStyle: TRVStyle): TRVStyleLength;
function RVA_GetComboBorderItemIndex(Width: TRVStyleLength; RVStyle: TRVStyle;
  Count: Integer): Integer;
procedure RVA_FillWidthComboBox(cmb: TComboBox);
procedure RVA_DrawCmbWidthItem(Canvas: TCanvas; Rect: TRect; Index: Integer;
  Color: TColor; State: TOwnerDrawState);
procedure RVA_DrawCmbWidthItem2(Canvas: TCanvas; Rect: TRect; Index: Integer;
  Color1,Color2: TColor; State: TOwnerDrawState);

function RVA_ChooseLanguage: Boolean;
procedure RVA_LocalizeForm(Form: TComponent);
procedure RVA_ConvertToTwips(Form: TComponent);
procedure RVA_ConvertToPixels(Form: TComponent);

function RVA_HeaderInfo: THFInfo;
function RVA_FooterInfo: THFInfo;
function RVA_GetColorName(Color: TColor): String;
function RVA_GetFineUnits: TRVUnits;
function RVA_GetBorderUnits: TRVUnits;

function MakeImportFilter(FileFilter: TrvFileImportFilterSet; List: TRVIntegerList;
  const RVFFilter, CustomFilter: String; rvc: TRVOfficeConverter): String;
function MakeExportFilter(FileFilter: TrvFileExportFilterSet; List: TRVIntegerList;
  const RVFFilter, CustomFilter: String; rvc: TRVOfficeConverter): String;
procedure GetImportFilterFormat(List: TRVIntegerList; Index: Integer;
  var FileFilter: TrvFileImportFilter; var ConverterOrCustomIndex: Integer);
procedure GetExportFilterFormat(List: TRVIntegerList; Index: Integer;
  var FileFilter: TrvFileExportFilter; var ConverterOrCustomIndex: Integer);
  
function RVAFindComponentByClass(Owner: TComponent; CClass: TComponentClass): TComponent;

{$IFDEF USERVADDICT3}
function RVA_Addict3AutoCorrect(rve: TCustomRichViewEdit): Boolean;
{$ENDIF}


procedure ConvertToUnicode(rv: TCustomRichView);
function GoToCheckpoint(rv: TCustomRichViewEdit; const CPName: String): Boolean;

{$IFDEF RVAHTML}
procedure PasteHTML(rve: TCustomRichViewEdit);
{$ENDIF}

function RVADeleteAmp(const S: String): String;

{$IFDEF USERVTNT}
function RVA_GetSX(MsgId: TRVAMessageID): WideString;
function RVAFormat(const FormatStr: WideString; const Args: array of const): WideString;
{$ELSE}
function RVA_GetSX(MsgId: TRVAMessageID): String;
function RVAFormat(const FormatStr: String; const Args: array of const): String;
{$ENDIF}

{
  By default, focused non-richviewedit controls have higher priority in editing
  actions (such as Cut, Copy, Paste) than Control property or
  RVAControlPanel.DefaultControl.
  If you want to change this priority, assign RVA_EditForceDefControl := True.
}
var
  RVA_EditForceDefControl: Boolean = False;
  RVA_MessageBox: TRVAMessageBox;

{$IFDEF USELOREMIPSUM}
resourcestring
  LoremIpsum1 =
  'Lorem ipsum dolor sit amet, consectetur adipisicing elit, '+
  'sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.';
  LoremIpsum2 =
  ' Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut '+
  'aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in '+
  'voluptate velit esse cillum dolore eu fugiat nulla pariatur. '+
  'Excepteur sint occaecat cupidatat non proident, '+
  'sunt in culpa qui officia deserunt mollit anim id est laborum.';
{$ENDIF}

implementation

uses
  CRVFData,
  BaseRVFrm,
  {$IFNDEF RVDONOTUSESEQ}
  RVNote,
  {$ENDIF}
  {$IFNDEF RVDONOTUSELISTS}
  RVMarker,
  {$ENDIF}
  InsTableRVFrm, ColorRVFrm,
  IntegerRVFrm, SplitRVFrm, ParaRVFrm, FontRVFrm,
  FillColorRVFrm, ListRVFrm, RVStr, ParaBrdrRVFrm, ItemPropRVFrm, PreviewRVFrm,
  HypRVFrm, ListGalleryRVFrm, ListGallery2RVFrm, InsSymbolRVFrm, BackRVFrm, PageSetupRVFrm,
  ObjectAlignRVFrm,
  RVCharCase, TableSizeRVFrm, RVLinear;

const Eps = 1e-20;  

resourcestring

  sFileFilterRVF = 'RichView Files (*.rvf)|*.rvf';
  {$IFDEF USERVXML}
  sFileFilterXML = 'XML Files (*.xml)|*.xml';
  {$ENDIF}

  sRVFExtension = 'rvf';

  srverrNoActionFind = 'TrvActionFind object is not assigned!';
  srverrNoActionSaveAs = 'TrvActionSaveAs object is not assigned!';
  srverrNoActionSave = 'TrvActionSave object is not assigned!';

type
  TGetComboBoxInfoFunction = function (hwndCombo: HWND; var pcbi: TComboBoxInfo): LongBool; stdcall;

var
  RVA_HeaderInfo_, RVA_FooterInfo_: THFInfo;
  RVGetComboBoxInfo: TGetComboBoxInfoFunction;

type

  { TrvaFindDialog }

  TrvaFindDialog = class (TRVABasicFindDialog)
  private
    FAction: TrvActionFind;
  public
    destructor Destroy; override;
  end;

  { TrvaReplaceDialog }

  TrvaReplaceDialog = class (TRVABasicReplaceDialog)
  private
    FAction: TrvActionReplace;
  public
    destructor Destroy; override;
  end;

destructor TrvaFindDialog.Destroy;
begin
  if FAction<>nil then
    FAction.FFindDialog := nil;
  inherited;
end;

destructor TrvaReplaceDialog.Destroy;
begin
  if FAction<>nil then
    FAction.FReplaceDialog := nil;
  inherited;
end;

{$IFDEF USERVTNT}
function RVA_GetSX(MsgId: TRVAMessageID): WideString;
begin
  Result := _GetWideString(RVA_GetS(MsgId));
end;

function RVAFormat(const FormatStr: WideString; const Args: array of const): WideString;
begin
  {$IFDEF RICHVIEWDEF6}
  Result := WideFormat(FormatStr, Args);
  {$ELSE}
  Result := _GetWideString(Format(_GetString(FormatStr), Args));
  {$ENDIF}
end;
{$ELSE}
function RVA_GetSX(MsgId: TRVAMessageID): String;
begin
  Result := RVA_GetS(MsgId);
end;

function RVAFormat(const FormatStr: String; const Args: array of const): String;
begin
  Result := Format(FormatStr, Args);
end;
{$ENDIF}

function RVADeleteAmp(const S: String): String;
var i: Integer;
begin
  Result := s;
  for i := 1 to Length(S) do
    if (s[i]='&') and
       ((i=Length(s)) or (s[i+1]<>'&')) and
       ((i=1) or (s[i-1]<>'&'))then begin
      Delete(Result, i, 1);
      break;
    end;
end;

function GetRichViewEditFromPopupComponent(
  PopupComponent: TComponent): TCustomRichViewEdit;
begin
  if PopupComponent is TCustomRichViewEdit then
    Result := TCustomRichViewEdit(PopupComponent)
  else if Assigned(RVA_GetRichViewEditFromPopupComponent) then
    Result := RVA_GetRichViewEditFromPopupComponent(PopupComponent)
  else
    Result := nil;
end;

function RVA_GetColorName(Color: TColor): String;
var i, rgb: Integer;
begin
  if Color = clNone then begin
    Result := RVA_GetS(rvam_cl_Transparent);
    exit;
  end;
  if (Color = clWindow) or (Color = clBtnFace) or
     (Color = clWindowText) then begin
    Result := RVA_GetS(rvam_cl_Auto);
    exit;
  end;
  for i := 0 to ColorCount-1 do
    if Colors[i].Color=Color then begin
      Result := Colors[i].Name;
      exit;
    end;
  rgb := ColorToRGB(Color);
  Result := 'RGB('+
    IntToStr(rgb and $0000FF)+','+
    IntToStr((rgb and $00FF00) shr 8)+','+
    IntToStr((rgb and $FF0000) shr 16)+')';
end;

function RVA_GetComboBorderWidth(Index: Integer): Integer;
begin
  if RVA_GetBorderUnits=rvuPixels then
    Result := Index+1
  else
    case Index of
    0: Result := 5;
    1: Result := 10;
    2: Result := 15;
    3: Result := 20;
    4: Result := 30;
    5: Result := 45;
    6: Result := 60;
    7: Result := 90;
    else Result := 120;
    end;
end;

function RVA_GetComboBorderWidth2(Index: Integer; RVStyle: TRVStyle): TRVStyleLength;
begin
  Result := RVA_GetComboBorderWidth(Index);
  if RVA_GetBorderUnits=rvuPixels then
    Result := RVStyle.PixelsToUnits(Result)
  else
    Result := RVStyle.TwipsToUnits(Result);
end;

function RVA_GetComboBorderItemIndex(Width: TRVStyleLength; RVStyle: TRVStyle; Count: Integer): Integer;
var i, w: Integer;
begin
  if RVA_GetBorderUnits=rvuPixels then
    w := RVStyle.GetAsPixels(Width)
  else
    w := RVStyle.GetAsTwips(Width);
  for i := 0 to Count-1 do
    if w=RVA_GetComboBorderWidth(i) then begin
      Result := i;
      exit;
    end;
  Result := -1;
end;

procedure RVA_FillWidthComboBox(cmb: TComboBox);
var i, Count: Integer;
begin
  cmb.Items.BeginUpdate;
  cmb.Items.Clear;
  if RVA_GetBorderUnits=rvuPixels then
    Count := 8
  else
    Count := 9;
  for i := 0 to Count-1 do
    cmb.Items.Add(IntToStr(RVA_GetComboBorderWidth(i)));
  cmb.Items.EndUpdate;
end;

function GetBorderWidthStr(Index: Integer): String;
var w: Integer;
begin
  w := RVA_GetComboBorderWidth(Index);
  if RVA_GetBorderUnits<>rvuPixels then begin
    // points
    Result := ' '+FloatToStr(w / 20)+' '+RVA_GetUnitsName(rvuPoints, True)+' ';
    end
  else begin
    // pixels
    Result := ' '+IntToStr(w)+' '+RVA_GetUnitsName(rvuPixels, True)+' ';
  end;
end;

function GetBorderWidthMaxStr(Index: Integer): String;
begin
  if RVA_GetBorderUnits<>rvuPixels then begin
    // points
    Result := ' '+FloatToStr(9.99)+' '+RVA_GetUnitsName(rvuPoints, True)+' ';
    end
  else begin
    // pixels
    Result := ' '+IntToStr(9)+' '+RVA_GetUnitsName(rvuPixels, True)+' ';
  end;
end;

procedure RVA_DrawCmbWidthItem(Canvas: TCanvas; Rect: TRect; Index: Integer;
  Color: TColor; State: TOwnerDrawState);
var s, smax: String;
    w, w2, mid, whalf: Integer;
    RectText: TRect;
begin
  with Rect do
    IntersectClipRect(Canvas.Handle, Left, Top, Right, Bottom);
  Canvas.Brush.Style := bsSolid;
  Canvas.Brush.Color := clWindow;
  Canvas.FillRect(Rect);
  Canvas.Pen.Style := psSolid;
  Canvas.Pen.Color := Color;

  w2 := RVA_GetComboBorderWidth(Index);
  if RVA_GetBorderUnits<>rvuPixels then begin
    w := Round(w2 / 20);
    if (w=0) and (w2<>0) then
      w := 1
    end
  else
    w := w2;
  Canvas.Font.Color := clWindowText;
  Canvas.Font.Name := RVA_DialogFontName;
  Canvas.Font.Size := RVA_DialogFontSize;
  s := GetBorderWidthStr(Index);
  smax := GetBorderWidthMaxStr(Index);
  RectText := Rect;
  RectText.Right := Rect.Left+3+Canvas.TextWidth(smax);
  DrawText(Canvas.Handle, PChar(s), Length(s), RectText, DT_SINGLELINE or DT_VCENTER or DT_RIGHT);
  Canvas.Pen.Width := 1;
  Canvas.Brush.Color := Color;
  mid := (Rect.Top+Rect.Bottom) div 2;
  if w=1 then begin
    Canvas.MoveTo(RectText.Right, mid);
    Canvas.LineTo(Rect.Right-3, mid);
    end
  else begin
    whalf := w div 2;
    Canvas.Rectangle(RectText.Right, mid - whalf,
      Rect.Right-3, mid+(w-whalf));
  end;
  if odSelected in State then begin
    Canvas.Pen.Style := psInsideFrame;
    Canvas.Pen.Color := clHighlight;
    Canvas.Pen.Width := 2;
    Canvas.Brush.Style := bsClear;
    with Rect do
      Canvas.Rectangle(Left, Top, Right,Bottom);
  end;
  SelectClipRgn(Canvas.Handle,0);
end;

procedure RVA_DrawCmbWidthItem2(Canvas: TCanvas; Rect: TRect; Index: Integer;
  Color1, Color2: TColor; State: TOwnerDrawState);
var s, smax: String;
    w, w2, i: Integer;
    RectText, RectFrame: TRect;
begin
  Canvas.Brush.Style := bsSolid;
  Canvas.Brush.Color := clWindow;
  Canvas.FillRect(Rect);
  Canvas.Font.Color := clWindowText;
  Canvas.Font.Name := RVA_DialogFontName;
  Canvas.Font.Size := RVA_DialogFontSize;  
  s := GetBorderWidthStr(Index);
  smax := GetBorderWidthMaxStr(Index);
  RectText := Rect;
  RectText.Right := Rect.Left+3+Canvas.TextWidth(smax);
  DrawText(Canvas.Handle, PChar(s), Length(s), RectText, DT_SINGLELINE or DT_VCENTER or DT_RIGHT);
  Canvas.Pen.Width := 1;

  RectFrame := Rect;
  RectFrame.Left := RectText.Right;

  InflateRect(RectFrame,-4,-4);
  Canvas.Pen.Style := psSolid;
  Canvas.Pen.Width := 1;

  w2 := RVA_GetComboBorderWidth(Index);
  if RVA_GetBorderUnits<>rvuPixels then begin
    w := Round(w2 / 20);
    if (w=0) and (w2<>0) then
      w := 1
    end
  else
    w := w2;

  for i := 1 to w do begin
    Canvas.Pen.Color := Color1;
    Canvas.MoveTo(RectFrame.Left, RectFrame.Bottom);
    Canvas.LineTo(RectFrame.Left, RectFrame.Top);
    Canvas.LineTo(RectFrame.Right, RectFrame.Top);
    Canvas.Pen.Color := Color2;
    Canvas.LineTo(RectFrame.Right, RectFrame.Bottom);
    Canvas.LineTo(RectFrame.Left, RectFrame.Bottom);
    InflateRect(RectFrame,-1,-1);
  end;
  
  if odSelected in State then begin
    Canvas.Pen.Style := psInsideFrame;
    Canvas.Pen.Color := clHighlight;
    Canvas.Pen.Width := 2;
    Canvas.Brush.Style := bsClear;
    with Rect do
      Canvas.Rectangle(Left, Top, Right,Bottom);
  end;
end;

function RVAFindComponentByClass(Owner: TComponent; CClass: TComponentClass): TComponent;
var I: Integer;
begin
  Result := nil;
  for I := 0 to Owner.ComponentCount - 1 do
    if Owner.Components[i] is CClass then
    begin
      Result := Owner.Components[i];
      exit;
    end;
end;

procedure SetStyleConversionEvent(rve: TCustomRichViewEdit; Event: TRVStyleConversionEvent);
begin
  while rve<>nil do begin
    rve.OnStyleConversion := Event;
    rve := TCustomRichViewEdit(rve.InplaceEditor);
  end;
end;

procedure SetParaStyleConversionEvent(rve: TCustomRichViewEdit; Event: TRVStyleConversionEvent);
begin
  while rve<>nil do begin
    rve.OnParaStyleConversion := Event;
    rve := TCustomRichViewEdit(rve.InplaceEditor);
  end;
end;

function GetInteger(const Caption, Prompt: String; var Value: Integer): Boolean;
var frm: TfrmInteger;
begin
  frm := TfrmInteger.Create(Application);
  try
    frm.SetFormCaption(Caption);
    frm.SetControlCaption(frm._lbl, Prompt);
    frm.Value := Value;
    Result := frm.ShowModal = mrOk;
    if Result then
      Value := frm.Value;
  finally
    frm.Free;
  end;
end;

function CanUnmergeRows(table: TRVTableItemInfo): Boolean;
var fr,fc,r,c,cs,rs,mr,mc: Integer;
begin
  Result := table.GetNormalizedSelectionBounds(True, fr, fc, cs, rs);
  if Result then begin
    for r := fr to fr+rs-1 do
      for c := fc to fc+cs-1 do
        if table.Rows.GetMainCell(r,c,mr,mc).RowSpan>1 then
          exit;
    Result := False;
  end;
end;

function CanUnmergeCols(table: TRVTableItemInfo): Boolean;
var fr,fc,r,c,cs,rs,mr,mc: Integer;
begin
  Result := table.GetNormalizedSelectionBounds(True, fr, fc, cs, rs);
  if Result then begin
    for r := fr to fr+rs-1 do
      for c := fc to fc+cs-1 do
        if table.Rows.GetMainCell(r,c,mr,mc).ColSpan>1 then
          exit;
    Result := False;
  end;
end;

function GetCharCount(ch: Char; const s: String): Integer;
var i: Integer;
begin
  Result := 0;
  for i := 1 to Length(s) do
    if s[i]=ch then
      inc(Result);
end;

function MakeImportFilter(FileFilter: TrvFileImportFilterSet; List: TRVIntegerList;
  const RVFFilter, CustomFilter: String; rvc: TRVOfficeConverter): String;
var i: Integer;
begin
  Result := '';
  if ffiRVF in FileFilter then begin
    List.Add(ord(ffiRVF));
    if RVA_RVFLocalizable then
      Result := RVA_GetS(rvam_flt_RVF)
    else
      Result := RVFFilter;
  end;
  if ffiRTF in FileFilter then begin
    List.Add(ord(ffiRTF));
    if Result<>'' then
      Result := Result+'|';
    Result := Result + RVA_GetS(rvam_flt_RTF);
  end;
  {$IFDEF USERVXML}
  if (RVA_RVXML<>nil) and (ffiXML in FileFilter) then begin
    List.Add(ord(ffiXML));
    if Result<>'' then
      Result := Result+'|';
    if RVA_XMLLocalizable then
      Result := Result + RVA_GetS(rvam_flt_XML)
    else
      Result := Result + RVA_XMLFilter;
  end;
  {$ENDIF}
  if ffiTextAuto in FileFilter then begin
    List.Add(ord(ffiTextAuto));
    if Result<>'' then
      Result := Result+'|';
    Result := Result + RVA_GetS(rvam_flt_TextAuto);
  end;
  if ffiTextANSI in FileFilter then begin
    List.Add(ord(ffiTextANSI));
    if Result<>'' then
      Result := Result+'|';
    Result := Result + RVA_GetS(rvam_flt_TextAnsi);
  end;
  if ffiTextUnicode in FileFilter then begin
    List.Add(ord(ffiTextUnicode));
    if Result<>'' then
      Result := Result+'|';
    Result := Result + RVA_GetS(rvam_flt_TextUnicode);
  end;
  {$IFDEF USERVHTMLVIEWER}
  if (RVA_RVHTMLView<>nil) and (RVA_RVHTMLView.HTMLViewer<>nil) and (ffiHTML in FileFilter) then begin
    List.Add(ord(ffiHTML));
    if Result<>'' then
      Result := Result+'|';
    Result := Result + RVA_GetS(rvam_flt_HTMLOpen);
  end;
  {$ELSE}
  {$IFDEF USERVHTML}
  if (RVA_RVHTML<>nil) and (ffiHTML in FileFilter) then begin
    List.Add(ord(ffiHTML));
    if Result<>'' then
      Result := Result+'|';
    Result := Result + RVA_GetS(rvam_flt_HTMLOpen);
  end;
  {$ENDIF}
  {$ENDIF}
  if (ffiCustom in FileFilter) and (CustomFilter<>'') then begin
    for i := 1 to (GetCharCount('|', CustomFilter)+1) div 2 do
      List.Add(-i);
    if Result<>'' then
      Result := Result+'|';
    Result := Result + CustomFilter;
  end;
  if (ffiOfficeConverters in FileFilter) and (rvc<>nil) then begin
    if Result<>'' then
      Result := Result+'|';
    Result := Result+rvc.GetImportFilter;
  end;
end;

procedure GetImportFilterFormat(List: TRVIntegerList; Index: Integer;
  var FileFilter: TrvFileImportFilter; var ConverterOrCustomIndex: Integer);
begin
  ConverterOrCustomIndex := 0; 
  if Index<List.Count then begin
    if List[Index]>=0 then
      FileFilter := TrvFileImportFilter(List[Index])
    else begin
      FileFilter := ffiCustom;
      ConverterOrCustomIndex := -List[Index];
    end;
    end
  else begin
    FileFilter := ffiOfficeConverters;
    ConverterOrCustomIndex := Index-List.Count;
  end;
end;

function MakeExportFilter(FileFilter: TrvFileExportFilterSet; List: TRVIntegerList;
  const RVFFilter, CustomFilter: String; rvc: TRVOfficeConverter): String;
var i: Integer;
begin
  Result := '';
  if ffeRVF in FileFilter then begin
    List.Add(ord(ffeRVF));
    if RVA_RVFLocalizable then
      Result := RVA_GetS(rvam_flt_RVF)
    else
      Result := RVFFilter;
  end;
  if ffeRTF in FileFilter then begin
    List.Add(ord(ffeRTF));
    if Result<>'' then
      Result := Result+'|';
    Result := Result + RVA_GetS(rvam_flt_RTF);
  end;
  {$IFDEF USERVXML}
  if (RVA_RVXML<>nil) and (ffeXML in FileFilter) then begin
    List.Add(ord(ffeXML));
    if Result<>'' then
      Result := Result+'|';
    if RVA_XMLLocalizable then
      Result := Result + RVA_GetS(rvam_flt_XML)
    else
      Result := Result + RVA_XMLFilter;
  end;
  {$ENDIF}
  if ffeTextANSI in FileFilter then begin
    List.Add(ord(ffeTextANSI));
    if Result<>'' then
      Result := Result+'|';
    Result := Result + RVA_GetS(rvam_flt_TextAnsi);
  end;
  if ffeTextUnicode in FileFilter then begin
    List.Add(ord(ffeTextUnicode));
    if Result<>'' then
      Result := Result+'|';
    Result := Result + RVA_GetS(rvam_flt_TextUnicode);
  end;
  if ffeHTMLCSS in FileFilter then begin
    List.Add(ord(ffeHTMLCSS));
    if Result<>'' then
      Result := Result+'|';
    Result := Result + RVA_GetS(rvam_flt_HTMLCSS);
  end;
  if ffeHTML in FileFilter then begin
    List.Add(ord(ffeHTML));
    if Result<>'' then
      Result := Result+'|';
    Result := Result + RVA_GetS(rvam_flt_HTMLPlain);
  end;
  if (ffeCustom in FileFilter) and (CustomFilter<>'') then begin
    for i := 1 to (GetCharCount('|', CustomFilter)+1) div 2 do
      List.Add(-i);
    if Result<>'' then
      Result := Result+'|';
    Result := Result + CustomFilter;      
  end;
  if (ffeOfficeConverters in FileFilter) and (rvc<>nil) then begin
    if Result<>'' then
      Result := Result+'|';
    Result := Result+rvc.GetExportFilter;
  end;
end;

procedure GetExportFilterFormat(List: TRVIntegerList; Index: Integer;
  var FileFilter: TrvFileExportFilter; var ConverterOrCustomIndex: Integer);
begin
  ConverterOrCustomIndex := 0;   
  if Index<List.Count then begin
    if List[Index]>=0 then
      FileFilter := TrvFileExportFilter(List[Index])
    else begin
      FileFilter := ffeCustom;
      ConverterOrCustomIndex := -List[Index];
    end;
    end
  else begin
    FileFilter := ffeOfficeConverters;
    ConverterOrCustomIndex := Index-List.Count;
  end;
end;

procedure GetSelectionBounds(rve: TCustomRichViewEdit;
  var StartNo, EndNo: Integer);
var StartOffs, EndOffs: Integer;
begin
   rve.RVData.GetSelectionBoundsEx(StartNo, StartOffs, EndNo, EndOffs, True);
   if (StartNo<>EndNo) or (StartOffs<>EndOffs) then begin
     if StartOffs>=rve.GetOffsAfterItem(StartNo) then
       inc(StartNo);
     if EndOffs<=rve.GetOffsBeforeItem(EndNo) then
       dec(EndNo);
   end;
end;

function GetSelectedItem(rve: TCustomRichViewEdit): TCustomRVItemInfo;
var a,b: Integer;
begin
  GetSelectionBounds(rve, a,b);
  if a=b then
    Result := rve.GetItem(a)
  else
    Result := nil;
end;

function GetColorOfSelectedCells(table: TRVTableItemInfo; var Color: TColor): Boolean;
var r,c: Integer;
begin
  Result := False;
  for r := 0 to table.Rows.Count-1 do
    for c := 0 to table.Rows[r].Count-1 do
      if (table.Cells[r,c]<>nil) and table.IsCellSelected(r,c) then
        if not Result then begin
          Color := table.Cells[r,c].Color;
          Result := True;
          end
        else if Color<>table.Cells[r,c].Color then begin
          Result := False;
          break;
        end;
end;

procedure SetColorToSelectedCells(rve: TCustomRichViewEdit; table: TRVTableItemInfo; Color: TColor);
var r,c: Integer;
    ec: TRVTableCellData;
begin
  rve.BeginUndoGroup(rvutModifyItem);
  rve.SetUndoGroupMode(True);
  if table.GetEditedCell(r,c)<>nil then
    ec := TRVTableCellData(table.GetEditedCell(r,c).RVData.GetSourceRVData)
  else
    ec := nil;
  for r := 0 to table.Rows.Count-1 do
    for c := 0 to table.Rows[r].Count-1 do
      if (table.Cells[r,c]<>nil) and (table.IsCellSelected(r,c) or (table.Cells[r,c]=ec)) then
        table.SetCellColor(Color,  r,c);
  rve.SetUndoGroupMode(False);
  rve.Change;
end;

procedure RepaintSubRichViews(Control: TWinControl);
var i: Integer;
begin
  for i := 0 to Control.ControlCount-1 do
    if Control.Controls[i] is TWinControl then
      RepaintSubRichViews(TWinControl(Control.Controls[i]));
  if Control is TCustomRichView then
    Control.Invalidate;
end;

procedure RepaintRichViews;
var i: Integer;
begin
  for i := 0 to Screen.CustomFormCount-1 do
    RepaintSubRichViews(Screen.CustomForms[i]);
end;

function GetTitleFromMenu(const s: String): String;
var i: Integer;
begin
  Result := s;
  for i := Length(Result) downto 1 do
    if Result[i]='&' then
      Delete(Result, i, 1);
  if Length(Result)<3 then
    exit;
  if Copy(Result, Length(Result)-2, 3)='...' then
    Result := Copy(Result, 1, Length(Result)-3)
end;

procedure ConvertRVToUnicode(RVData: TCustomRVData);
var i,r,c, StyleNo: Integer;
    table: TRVTableItemInfo;
begin
  for i := 0 to RVData.ItemCount-1 do begin
    StyleNo := RVData.GetItemStyle(i);
    if StyleNo>=0 then begin
      if not RVData.GetRVStyle.TextStyles[StyleNo].Unicode then begin
        RVData.SetItemTextR(i, RVU_GetRawUnicode(RVData.GetItemTextW(i)));
        Include(RVData.GetItem(i).ItemOptions, rvioUnicode);
      end;
      end
    else if RVData.GetItemStyle(i)=rvsTable then begin
      table := TRVTableItemInfo(RVData.GetItem(i));
      for r := 0 to table.Rows.Count-1 do
        for c := 0 to table.Rows[r].Count-1 do
          if table.Cells[r,c]<>nil then
            ConvertRVToUnicode(table.Cells[r,c].GetRVData);
    end;
  end;
end;

procedure ConvertToUnicode(rv: TCustomRichView);
var i: Integer;
begin
  ConvertRVToUnicode(rv.RVData);
  for i := 0 to rv.Style.TextStyles.Count-1 do
    rv.Style.TextStyles[i].Unicode := True;
end;

{$IFDEF RVAHTML}
procedure PasteHTML(rve: TCustomRichViewEdit);
var rv: TRichView;
    rvs: TRVStyle;
    Stream : TMemoryStream;    
    {$IFDEF USERVHTML}
    RVData: TCustomRVData;
    StartNo, EndNo: Integer;
    SelRec : TRVSelection;
    {$ENDIF}
begin
  {$IFDEF USERVHTMLVIEWER}
  if RVA_RVHTMLView=nil then
    exit;
  {$ELSE}
  {$IFDEF USERVHTML}
  if RVA_RVHTML=nil then
    exit;
  {$ENDIF}
  {$ENDIF}
  try
    rv := TRichView.Create(nil);
    rvs := TRVStyle.Create(nil);
    try
      rvs.ListStyles := rve.Style.ListStyles;
      rvs.TextStyles := rve.Style.TextStyles;
      rvs.ParaStyles := rve.Style.ParaStyles;
      rvs.DefCodePage := rve.Style.DefCodePage;
      rv.Visible := False;
      rv.Parent := rve.Parent;
      rv.Style  := rvs;
      rv.Options := rve.Options;
      rv.RVFOptions := rve.RVFOptions;
      rv.RTFReadProperties.UnicodeMode := rve.RTFReadProperties.UnicodeMode;
      rv.AssignEvents(rve);
      {$IFDEF USERVHTMLVIEWER}
      RVA_RVHTMLView.LoadFromClipboard(rv);
      if rv.ItemCount>0 then begin
        if rve.RTFReadProperties.UnicodeMode=rvruOnlyUnicode then
          ConvertToUnicode(rv);
        NormalizeRichView(rv.RVData);
        Stream := TMemoryStream.Create;
        try
          rv.SaveRVFToStream(Stream, False);
          Stream.Position := 0;
          rve.InsertRVFFromStreamEd(Stream);
        finally
          Stream.Free;
        end;
      end;
      {$ELSE}
      {$IFDEF USERVHTML}
      RVA_RVHTML.RichView := rv;
      RVA_RVHTML.LoadFromClipboard;
      if rv.ItemCount>0 then begin
        if rve.RTFReadProperties.UnicodeMode=rvruOnlyUnicode then
          ConvertToUnicode(rv);
        rv.Format;
        if RVA_RVHTML.GetSelectionBounds(RVData, StartNo, EndNo) then begin
          TCustomRVFormattedData(RVData).AssignChosenRVData(nil, nil);
          TCustomRVFormattedData(RVData).SetSelectionBounds(StartNo,
            RVData.GetOffsBeforeItem(StartNo),
            EndNo, RVData.GetOffsAfterItem(EndNo))
          end
        else begin
          RVData := rv.RVData;
          rv.SelectAll;
        end;
        RVGetSelectionEx(rv, SelRec);
        NormalizeRichView(rv.RVData);
        rv.Format;
        RVSetSelectionEx(rv, SelRec);
        Stream := TMemoryStream.Create;
        try
          rv.SaveRVFToStream(Stream, True);
          Stream.Position := 0;
          rve.InsertRVFFromStreamEd(Stream);
        finally
          Stream.Free;
        end;
      end;
      {$ENDIF}
      {$ENDIF}
    finally
      rv.Free;
      rvs.Free;
      {$IFNDEF USERVHTMLVIEWER}
      {$IFDEF USERVHTML}
      RVA_RVHTML.RichView := nil;
      {$ENDIF}
      {$ENDIF}
    end;
  except;
  end;
end;

{$ENDIF}

function DirectoryExists(const Name: string): Boolean;
var
  Code: Cardinal;
begin
  Code := GetFileAttributes(PChar(Name));
  Result := (Code <> $FFFFFFFF) and (FILE_ATTRIBUTE_DIRECTORY and Code <> 0);
end;

function GetImagesDirectory(const FileName: String; CreateDirectoryForHTMLImages: Boolean;
  var Created: Boolean): String;
var Ext: String;
    rnd: Integer;
begin
  Created := False;
  if not CreateDirectoryForHTMLImages then begin
    Result := '';
    exit;
  end;
  Result := FileName;
  Ext := ExtractFileExt(FileName);
  Result := Copy(Result, 1, Length(Result)-Length(Ext));
  Result := Result + '.files';
  if not DirectoryExists(Result) then begin
    if FileExists(Result) then begin
      rnd := Random(MaxInt div 2);
      while DirectoryExists(Result+IntToStr(rnd)) or
            FileExists(Result+IntToStr(rnd)) do
        inc(rnd);
      Result := Result+IntToStr(rnd);
    end;
    Created := CreateDir(Result);
    if not Created then
      Result := ExtractFilePath(Result);
  end;
  Result := ExtractFileName(Result);
end;

{----------------------------- TrvaDocumentInfo -------------------------------}

constructor TrvaDocumentInfo.Create;
begin
  inherited;
end;

procedure TrvaDocumentInfo.Update;
begin

end;

{----------------------- Basic Action -----------------------------------------}

{ TrvCustomAction }

procedure TrvCustomAction.Localize;
begin
  if FMessageID<>rvam_Empty then begin
    Caption := {$IFDEF USERVTNT}_GetWideString{$ENDIF}(RVA_GetS(FMessageID));
    Hint    := {$IFDEF USERVTNT}_GetWideString{$ENDIF}(RVA_GetS(succ(FMessageID)));
  end;
end;

{$IFDEF USERVTNT}
procedure TrvCustomAction.DefineProperties(Filer: TFiler);
begin
  inherited;
  TntPersistent_AfterInherited_DefineProperties(Filer, Self);
end;

procedure TrvCustomAction.Assign(Source: TPersistent);
begin
  inherited;
  TntStdActn_AfterInherited_Assign(Self, Source);
end;

function TrvCustomAction.GetCaption: WideString;
begin
  Result := TntAction_GetCaption(Self);
end;

procedure TrvCustomAction.SetCaption(const Value: WideString);
begin
  TntAction_SetCaption(Self, Value);
end;

function TrvCustomAction.GetHint: WideString;
begin
  Result := TntAction_GetHint(Self);
end;

procedure TrvCustomAction.SetHint(const Value: WideString);
begin
  TntAction_SetHint(Self, Value);
end;
{$ENDIF}

procedure TrvCustomAction.ConvertToPixels;
begin

end;

procedure TrvCustomAction.ConvertToTwips;
begin

end;

{ TrvAction }

function TrvAction.ContinueIteration(var CustomData: Integer): Boolean;
begin
  Result := True;
end;

procedure TrvAction.IterateProc(RVData: TCustomRVData; ItemNo: Integer;
  rve: TCustomRichViewEdit; var CustomData: Integer);
begin

end;

function TrvAction.CanApplyToPlainText: Boolean;
begin
  Result := True;
end;

function  TrvAction.IterateRVData(RVData: TCustomRVData;
  rve: TCustomRichViewEdit; StartNo, EndNo: Integer;
  var CustomData: Integer): Boolean;
var i: Integer;
    item: TCustomRVItemInfo;
    StoreSub: TRVStoreSubRVData;
    SubRVData: TCustomRVData;
begin
  Result := True;
  item := TCustomRVFormattedData(RVData).PartialSelectedItem;
  if item<>nil then begin
    SubRVData := TCustomRVData(item.GetSubRVData(StoreSub, rvdChosenDown));
    Result := SubRVData<>nil;
    if Result then begin
      repeat
        if rvstCompletelySelected in SubRVData.State then begin
          IterateRVData(SubRVData.GetRVData, rve, 0, SubRVData.Items.Count-1, CustomData);
          if not ContinueIteration(CustomData) then
            break;
        end;
        SubRVData := TCustomRVData(item.GetSubRVData(StoreSub, rvdNext));
      until SubRVData=nil;
      StoreSub.Free;
    end;
    exit;
  end;
  for i := StartNo to EndNo do begin
    if not ContinueIteration(CustomData) then
      exit;
    item := RVData.GetItem(i);
    SubRVData := TCustomRVData(item.GetSubRVData(StoreSub, rvdFirst));
    if SubRVData<>nil then begin
      repeat
        IterateRVData(SubRVData.GetRVData, rve, 0, SubRVData.Items.Count-1, CustomData);
        if not ContinueIteration(CustomData) then
          break;
        SubRVData := TCustomRVData(item.GetSubRVData(StoreSub, rvdNext));
      until SubRVData=nil;
      StoreSub.Free;
    end;
    IterateProc(RVData, i, rve, CustomData);
  end;
end;

function TrvAction.RequiresMainDoc: Boolean;
begin
  Result := False;
end;

function TrvAction.GetControl(Target: TObject): TCustomRichViewEdit;
begin
  if Control<>nil then
   Target := Control
  else if RVA_DefaultControl<>nil then
   Target := RVA_DefaultControl;
  if Target<>nil then
    while Target is TRVTableInplaceEdit do
      Target := TRVTableInplaceEdit(Target).Parent;
  Result := Target as TCustomRichViewEdit;
  if Assigned(RVA_GetRichViewEdit) then
    Result := RVA_GetRichViewEdit(Result, RequiresMainDoc);
end;

function TrvAction.HandlesTarget(Target: TObject): Boolean;
begin
  if Control<>nil then
   Target := Control
  else if RVA_DefaultControl<>nil then
   Target := RVA_DefaultControl;
  Result := Target is TCustomRichViewEdit{and TCustomRichViewEdit(Target).Focused};
end;

procedure TrvAction.Notification(AComponent: TComponent;
  Operation: TOperation);
begin
  inherited Notification(AComponent, Operation);
  if (Operation = opRemove) and (AComponent = Control) then
    Control := nil;
end;

procedure TrvAction.SetControl(Value: TCustomRichViewEdit);
begin
  if Value <> FControl then
  begin
    {$IFDEF RICHVIEWDEF5}
    if FControl <> nil then
      FControl.RemoveFreeNotification(Self);
    {$ENDIF}
    FControl := Value;
    if FControl <> nil then
      FControl.FreeNotification(Self);
  end;
end;

procedure TrvAction.UpdateTarget(Target: TObject);
begin
  Enabled := RVA_ActionsEnabled and not Disabled and
    (CanApplyToPlainText or (RVA_UserInterface<>rvauiText));
end;

{ TrvActionEvent }

procedure TrvActionEvent.ExecuteTarget(Target: TObject);
begin
  if Assigned(FOnExecute) then
    OnExecute(Self, GetControl(Target))
  else
    inherited;
end;

procedure TrvActionEvent.UpdateTarget(Target: TObject);
var tmp: Boolean;
begin
  tmp := RVA_ActionsEnabled and not Disabled;
  if tmp and Assigned(FOnUpdate) then
    FOnUpdate(Self, GetControl(Target))
  else if Enabled <> tmp then
    Enabled := tmp;
end;

{---------------------------- File --------------------------------------------}

{ TrvActionNew }

constructor TrvActionNew.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_New;
end;

procedure TrvActionNew.ExecuteTarget(Target: TObject);
var AActionSave: TrvActionSave;
    rve: TCustomRichViewEdit;
begin
  rve := GetControl(Target);
  AActionSave := GetActionSave;
  if AActionSave=nil then
    raise Exception.Create(srverrNoActionSave);
  if AActionSave.FindDoc(rve)<0 then
    AActionSave.AddDoc(rve, RVA_DefaultFileName, RVA_DefaultFileFormat,
      RVA_DefaultCustomFilterIndex, False, False, False, False);
  if not GetActionSave.SaveDocEx(rve) then
    exit;
  CompleteClear(rve);
  Reset(rve);
  AActionSave.GetDoc(rve).Update;
  RVA_Events.DoOnMarginsChanged(Self, rve);
  RVA_Events.DoOnViewChanged(Self, rve);    
  CompleteFormat(rve);
  CompleteDeleteUnusedStyles(rve);
  AActionSave.AddDoc(rve, RVA_DefaultFileName, RVA_DefaultFileFormat,
    RVA_DefaultCustomFilterIndex, False, False, False, False);
  if Assigned(rve.OnCurTextStyleChanged) then
    rve.OnCurTextStyleChanged(rve);
  if Assigned(rve.OnCurParaStyleChanged) then
    rve.OnCurParaStyleChanged(rve);
end;

function TrvActionNew.GetActionSave: TrvActionSave;
begin
  if FActionSave<>nil then begin
    Result := FActionSave;
    exit;
  end;
  Result := nil;
  if Owner=nil then
    exit;
  Result := TrvActionSave(RVAFindComponentByClass(Owner, TrvActionSave));
end;

function TrvActionNew.RequiresMainDoc: Boolean;
begin
  Result := True;
end;

procedure TrvActionNew.Notification(AComponent: TComponent;
  Operation: TOperation);
begin
  inherited;
  if (Operation = opRemove) and (AComponent = FActionSave) then
    FActionSave := nil;
end;

procedure TrvActionNew.ResetProperties(rve: TCustomRichViewEdit);
{$IFNDEF RVDONOTUSEDOCPARAMS}
var Units: TRVUnits;
    ZoomPercent: Integer;
    ZoomMode: TRVZoomMode;
{$ENDIF}
begin
  rve.Color                   := RVA_DefaultColor;
  rve.LeftMargin              := RVA_DefaultMargin;
  rve.RightMargin             := RVA_DefaultMargin;
  rve.TopMargin               := RVA_DefaultMargin;
  rve.BottomMargin            := RVA_DefaultMargin;
  rve.BackgroundBitmap.Handle := 0;
  rve.BackgroundStyle         := bsNoBitmap;
  rve.CurTextStyleNo          := 0;
  rve.CurParaStyleNo          := 0;
  if rvfoSaveDocProperties in rve.RVFOptions then begin
    rve.DocProperties.Clear;
    {$IFNDEF RVDONOTUSEDOCPARAMS}
    Units := rve.DocParameters.Units;
    ZoomPercent := rve.DocParameters.ZoomPercent;
    ZoomMode := rve.DocParameters.ZoomMode;
    rve.DocParameters := RVA_DocParameters;
    rve.DocParameters.ConvertToUnits(Units);
    rve.DocParameters.ZoomPercent := ZoomPercent;
    rve.DocParameters.ZoomMode := ZoomMode;
    {$ENDIF}
  end;
end;

procedure TrvActionNew.UpdateHFProperties(rve: TCustomRichViewEdit);

  procedure CopyProps(src, dst: TCustomRichView);
  begin
    dst.LeftMargin := src.LeftMargin;
    dst.RightMargin := src.RightMargin;
    dst.TopMargin := src.TopMargin;
    dst.BottomMargin := src.BottomMargin;
    dst.Color := src.Color;
  end;

begin
  if (rve.RTFReadProperties.HeaderRVData<>nil) and
     (rve.RTFReadProperties.HeaderRVData is TRichViewRVData) then
    CopyProps(rve,
      TCustomRichView(TRichViewRVData(rve.RTFReadProperties.HeaderRVData).RichView));
  if (rve.RTFReadProperties.FooterRVData<>nil) and
     (rve.RTFReadProperties.FooterRVData is TRichViewRVData) then
    CopyProps(rve,
      TCustomRichView(TRichViewRVData(rve.RTFReadProperties.FooterRVData).RichView));
end;

procedure TrvActionNew.Reset(rve: TCustomRichViewEdit);
begin
  ResetProperties(rve);
  if (rve.RTFReadProperties.HeaderRVData<>nil) and
     (rve.RTFReadProperties.HeaderRVData is TRVEditRVData) then
    ResetProperties(
      TCustomRichViewEdit(TRVEditRVData(rve.RTFReadProperties.HeaderRVData).RichView));
  if (rve.RTFReadProperties.FooterRVData<>nil) and
     (rve.RTFReadProperties.FooterRVData is TRVEditRVData) then
    ResetProperties(
      TCustomRichViewEdit(TRVEditRVData(rve.RTFReadProperties.FooterRVData).RichView));
  if Assigned(FOnNew) then
    FOnNew(Self);
end;

procedure TrvActionNew.SetActionSave(const Value: TrvActionSave);
begin
  {$IFDEF RICHVIEWDEF5}
  if FActionSave<>nil then
    FActionSave.RemoveFreeNotification(Self);
  {$ENDIF}
  FActionSave := Value;
  if FActionSave<>nil then
    FActionSave.FreeNotification(Self);
end;

procedure TrvActionNew.CompleteClear(rve: TCustomRichViewEdit);
begin
  rve.Clear;
  if rve.RTFReadProperties.HeaderRVData<>nil then
    rve.RTFReadProperties.HeaderRVData.Clear;
  if rve.RTFReadProperties.FooterRVData<>nil then
    rve.RTFReadProperties.FooterRVData.Clear;
end;

procedure TrvActionNew.CompleteFormat(rve: TCustomRichViewEdit);
begin
  if (rve.RTFReadProperties.HeaderRVData<>nil) and
     (rve.RTFReadProperties.HeaderRVData is TRichViewRVData) then
    TCustomRichView(TRichViewRVData(rve.RTFReadProperties.HeaderRVData).RichView).Format;
  if (rve.RTFReadProperties.FooterRVData<>nil) and
     (rve.RTFReadProperties.FooterRVData is TRichViewRVData) then
    TCustomRichView(TRichViewRVData(rve.RTFReadProperties.FooterRVData).RichView).Format;
  rve.Format;    
end;

procedure TrvActionNew.CompleteDeleteUnusedStyles(rve: TCustomRichViewEdit);
begin
  if not RVA_AutoDeleteUnusedStyles then
    exit;
  rve.DeleteUnusedStyles(True, True, True);
  if rve.RTFReadProperties.HeaderRVData<>nil then
    rve.RTFReadProperties.HeaderRVData.DeleteUnusedStyles(True, True, True);
  if rve.RTFReadProperties.FooterRVData<>nil then
    rve.RTFReadProperties.FooterRVData.DeleteUnusedStyles(True, True, True);
end;

{ TrvActionLoad }

constructor TrvActionOpen.Create(AOwner: TComponent);
begin
  inherited;
  Filter := [ffiRVF..{$IFDEF USERVHTMLVIEWER}ffiHTML{$ELSE}ffiCustom{$ENDIF}];
  FLastFilterIndex := 1;
  FMessageID := rvam_act_Open;
end;

procedure TrvActionOpen.ExecuteTarget(Target: TObject);
var
  AActionSave: TrvActionSave;
  rve: TCustomRichViewEdit;
  FilterList: TRVIntegerList;
  FilterString: String;
  ChosenFormat: TrvFileImportFilter;
  CustomFilterIndex: Integer;
begin
  rve := GetControl(Target);
  AActionSave := GetActionSave;
  if AActionSave=nil then
    raise Exception.Create(srverrNoActionSave);
  if AActionSave.FindDoc(rve)<0 then
    AActionSave.AddDoc(rve, RVA_DefaultFileName, RVA_DefaultFileFormat,
      RVA_DefaultCustomFilterIndex, False, False, False, False);
  if not GetActionSave.SaveDocEx(rve) then
    exit;
  FilterList := TRVIntegerList.Create;
  try
    FilterString := MakeImportFilter(Filter, FilterList, RVA_RVFFilter, CustomFilter, nil);
    {$IFDEF USEJVCL}
    with TJvOpenDialog2000.Create(Application) do
    {$ELSE}
    with TOpenDialog.Create(Application) do
    {$ENDIF}
    try
      DefaultExt := RVA_DefaultExt;
      Filter := FilterString;
      Options := [ofHideReadOnly, ofPathMustExist, ofFileMustExist, ofEnableSizing];
      Title := DialogTitle;
      if DialogTitle='' then
        Title := GetTitleFromMenu(RVA_GetS(rvam_act_Open));
      FilterIndex := FLastFilterIndex;
      InitialDir := FInitialDir;
      if Execute then begin begin
        if Screen.ActiveForm<>nil then
          Screen.ActiveForm.Update;
        GetImportFilterFormat(FilterList, FilterIndex-1, ChosenFormat, CustomFilterIndex);
        FLastFilterIndex := FilterIndex;
        LoadFile(rve, FileName, ChosenFormat, CustomFilterIndex);
      end;
      end;
    finally
      Free;
    end;
  finally
    FilterList.Free;
  end;
end;

procedure TrvActionOpen.LoadFile(rve: TCustomRichViewEdit; const FileName: String;
  FileFormat: TrvFileOpenFilter; CustomFilterIndex: Integer=0);
var
  r: Boolean;
  AActionSave: TrvActionSave;
  SaveFormat: TrvFileSaveFilter;
  ImpPicAssigned : Boolean;
begin
  Screen.Cursor := crHourglass;
  try
    r := False;
    SaveFormat := ffeRVF;
    AActionSave := GetActionSave;
    if AActionSave=nil then
      raise Exception.Create(srverrNoActionSave);
    CompleteClear(rve);
    Reset(rve);
    ImpPicAssigned := Assigned(rve.OnImportPicture);
    if not ImpPicAssigned then begin
      RVA_Events.InitImportPictures(Self);
      rve.OnImportPicture := RVA_Events.DoImportPicture;
    end;
    try
      case FileFormat of
        ffiRVF:
          begin
            r := rve.LoadRVF(FileName);
            SaveFormat := ffeRVF;
          end;
        ffiRTF:
          begin
            r := rve.LoadRTF(FileName);
            SaveFormat := ffeRTF;
          end;
        {$IFDEF USERVXML}
        ffiXML:
          begin
            try
              r := True;
              RVA_RVXML.RichView := rve;
              if (rve.RTFReadProperties.HeaderRVData<>nil) and
                (rve.RTFReadProperties.HeaderRVData.GetParentControl is TCustomRichView) then
                RVA_RVXML.RVHeader := TCustomRichView(rve.RTFReadProperties.HeaderRVData.GetParentControl)
              else
                RVA_RVXML.RVHeader := nil;
              if (rve.RTFReadProperties.FooterRVData<>nil) and
                (rve.RTFReadProperties.FooterRVData.GetParentControl is TCustomRichView) then
                RVA_RVXML.RVFooter := TCustomRichView(rve.RTFReadProperties.FooterRVData.GetParentControl)
              else
                RVA_RVXML.RVFooter := nil;
              RVA_RVXML.LoadFromFile(FileName);
              SaveFormat := ffeXML;
            except
              r := False;
            end;
          end;
        {$ENDIF}
        ffiTextAuto:
          if RV_TestFileUnicode(FileName) = rvutYes then begin
            r := rve.LoadTextW(FileName, rve.CurTextStyleNo, rve.CurParaStyleNo, False);
            SaveFormat := ffeTextUnicode;
            end
          else begin
            r := rve.LoadText(FileName, rve.CurTextStyleNo, rve.CurParaStyleNo, False);
            SaveFormat := ffeTextANSI;
          end;
        ffiTextANSI:
          begin
            r := rve.LoadText(FileName, rve.CurTextStyleNo, rve.CurParaStyleNo, False);
            SaveFormat := ffeTextANSI;
          end;
        ffiTextUnicode:
          begin
            r := rve.LoadTextW(FileName, rve.CurTextStyleNo, rve.CurParaStyleNo, False);
            SaveFormat := ffeTextUnicode;
          end;
        {$IFDEF USERVHTMLVIEWER}
        ffiHTML:
          begin
            r := (RVA_RVHTMLView<>nil) and (RVA_RVHTMLView.HTMLViewer<>nil);
            if r then
              try
                RVA_RVHTMLView.HTMLViewer.LoadFromFile(FileName);
                RVA_RVHTMLView.ImportHtmlViewer(rve);
                //NormalizeRichView(rve.RVData);
              except
                r := False;
              end;
            SaveFormat := ffeHTMLCSS;
          end;
        {$ENDIF}
        ffiCustom:
          begin
            SaveFormat := ffeCustom;
            r := RVA_Events.DoOnCustomFileOperation(Self, rve, FileName, rvafoOpen,
              SaveFormat, CustomFilterIndex);
          end;
      end;
    finally
      if not ImpPicAssigned then begin
        RVA_Events.DoneImportPictures;
        rve.OnImportPicture := nil;
      end;
    end;
  finally
    Screen.Cursor := crDefault;
  end;
  NormalizeRichView(rve.RVData);
  AActionSave.AddDoc(rve, FileName, SaveFormat, CustomFilterIndex, True, False,
    False, False);
  if not r then begin
    RVA_MessageBox(RVA_GetSX(rvam_err_ErrorLoadingFile), RVA_GetSX(rvam_err_Title),
      MB_OK or MB_ICONSTOP);
    rve.Modified := True;
  end;
  UpdateHFProperties(rve);
  AActionSave.GetDoc(rve).Update;    
  RVA_Events.DoOnMarginsChanged(Self, rve);
  RVA_Events.DoOnViewChanged(Self, rve);
  CompleteFormat(rve);
  CompleteDeleteUnusedStyles(rve);
  if Assigned(FOnOpenFile) then
    FOnOpenFile(Self, rve, FileName, FileFormat, CustomFilterIndex);
  if Assigned(rve.OnCurTextStyleChanged) then
    rve.OnCurTextStyleChanged(rve);
  if Assigned(rve.OnCurParaStyleChanged) then
    rve.OnCurParaStyleChanged(rve);
end;

{ TrvActionSave }

constructor TrvActionSave.Create(AOwner: TComponent);
begin
  inherited;
  FLostFormatWarning := [ffeRTF, ffeTextANSI, ffeTextUnicode, ffeCustom
    {$IFDEF USERVHTMLVIEWER}, ffeHTMLCSS{$ENDIF}];
  FMessageID := rvam_act_Save;
  {$IFDEF USERVHTMLVIEWER}
  ImagePrefix := 'img';
  FCreateDirectoryForHTMLImages := True;
  {$ENDIF}
end;

destructor TrvActionSave.Destroy;
begin
  FDocuments.Free;
  FDocuments := nil;
  inherited;
end;

function TrvActionSave.RequiresMainDoc: Boolean;
begin
  Result := True;
end;

function TrvActionSave.AddDoc(rve: TCustomRichViewEdit;
  const FileName: String; FileFormat: TrvFileSaveFilter;
  CustomFilterIndex: Integer; Defined: Boolean; SaveFile,
  SuppressLFWarn, LFWarned: Boolean): Integer;
var doc: TrvaDocumentInfo;
begin
  if FDocuments=nil then
    FDocuments := TRVList.Create;
  Result := FindDoc(rve);
  if Result<0 then begin
    doc := RVA_DocumentInfoClass.Create;
    FDocuments.Add(doc);
    Result := FDocuments.Count-1;
    end
  else
    doc := TrvaDocumentInfo(FDocuments.Items[Result]);
  doc.rve := rve;
  doc.FileName := FileName;
  doc.FileFormat := FileFormat;
  doc.CustomFilterIndex := CustomFilterIndex;
  doc.Defined := Defined;
  doc.LFWarned := LFWarned;
  if LFWarned then begin
    doc.LFWFileFormat := FileFormat;
    doc.LFWCustomFilterIndex := CustomFilterIndex;
  end;
  if SaveFile then
    SaveDoc(Result, SuppressLFWarn)
  else
    DoDocumentFileChange(Result);
end;

procedure TrvActionSave.DeleteDoc(rve: TCustomRichViewEdit);
var idx: Integer;
begin
  idx := FindDoc(rve);
  if idx>=0 then
    FDocuments.Delete(idx);
end;

function TrvActionSave.FindDoc(rve: TCustomRichViewEdit): Integer;
var i: Integer;
begin
  Result := -1;
  if FDocuments=nil then
    exit;
  for i := 0 to FDocuments.Count-1 do
    if TrvaDocumentInfo(FDocuments.Items[i]).rve = rve then begin
      Result := i;
      exit;
    end;
end;

function TrvActionSave.GetDoc(rve: TCustomRichViewEdit): TrvaDocumentInfo;
var Index: Integer;
begin
  Index := FindDoc(rve);
  if Index>=0 then
    Result := TrvaDocumentInfo(Documents[Index])
  else
    Result := nil;
end;

procedure TrvActionSave.Notification(AComponent: TComponent;
  Operation: TOperation);
begin
  inherited;
  if (Operation = opRemove) then begin
    if AComponent = FActionSaveAs then
      FActionSaveAs := nil
    else if (FDocuments<>nil) and (AComponent is TCustomRichViewEdit) then
      DeleteDoc(TCustomRichViewEdit(AComponent));
  end;
end;

procedure TrvActionSave.ExecuteTarget(Target: TObject);
var idx: Integer;
    rve: TCustomRichViewEdit;
    AActionSaveAs: TrvActionSaveAs;
begin
  rve := GetControl(Target);
  idx := FindDoc(rve);
  if idx<0 then begin
    AActionSaveAs := GetActionSaveAs;
    if AActionSaveAs=nil then
      raise Exception.Create(srverrNoActionSaveAs);
    AActionSaveAs.ExecuteTarget(Target);
    end
  else
    SaveDoc(idx, False);
end;

procedure TrvActionSave.SetActionSaveAs(const Value: TrvActionSaveAs);
begin
  {$IFDEF RICHVIEWDEF5}
  if FActionSaveAs<>nil then
    FActionSaveAs.RemoveFreeNotification(Self);
  {$ENDIF}
  FActionSaveAs := Value;
  if FActionSaveAs<>nil then
    FActionSaveAs.FreeNotification(Self);
end;

function TrvActionSave.GetActionSaveAs: TrvActionSaveAs;
begin
  if FActionSaveAs<>nil then begin
    Result := FActionSaveAs;
    exit;
  end;
  Result := nil;
  if Owner=nil then
    exit;
  Result := TrvActionSaveAs(RVAFindComponentByClass(Owner, TrvActionSaveAs));
end;

function TrvActionSave.SaveDoc(Index: Integer; SuppressLFWarn: Boolean): Boolean;
var doc: TrvaDocumentInfo;
    AActionSaveAs: TrvActionSaveAs;
    {$IFDEF USERVHTMLVIEWER}
    Dir, ImgPath, OldImagePrefix, HTMLTitle: String;
    Created: Boolean;
    {$ENDIF}
begin
  doc := TrvaDocumentInfo(FDocuments.Items[Index]);
  if not doc.Defined then begin
    AActionSaveAs := GetActionSaveAs;
    if AActionSaveAs=nil then
      raise Exception.Create(srverrNoActionSaveAs);
    AActionSaveAs.Execute;
    Result := doc.Defined;
    exit;
  end;
  if not SuppressLFWarn and (doc.FileFormat in FLostFormatWarning) and
     not (doc.LFWarned and (doc.FileFormat=doc.LFWFileFormat) and
          ((doc.LFWFileFormat<>ffeCustom) or (doc.CustomFilterIndex=doc.LFWCustomFilterIndex))) then begin

    if (RVA_MessageBox(RVAFormat(RVA_GetSX(rvam_LostFormat), [ExtractFileName(doc.FileName)]),
        RVA_GetSX(rvam_Confirm), MB_ICONQUESTION or MB_YESNO)=IDNO) then begin
      Result := False;
      exit;
      end
    else begin
      doc.LFWarned := True;
      doc.LFWFileFormat := doc.FileFormat;
      doc.LFWCustomFilterIndex := doc.CustomFilterIndex;
    end;
  end;
  Screen.Cursor := crHourglass;
  try
    if Assigned(FOnSaving) then
      FOnSaving(Self, doc.rve, doc.FileName, doc.FileFormat, doc.CustomFilterIndex);

    case doc.FileFormat of
      ffeRVF:
        Result := doc.rve.SaveRVF(doc.FileName, False);
      ffeRTF:
        Result := doc.rve.SaveRTF(doc.FileName, False);
      {$IFDEF USERVXML}
      ffeXML:
        begin
          try
            Result := True;
            RVA_RVXML.RichView := doc.rve;
            if (doc.rve.RTFReadProperties.HeaderRVData<>nil) and
              (doc.rve.RTFReadProperties.HeaderRVData.GetParentControl is TCustomRichView) then
              RVA_RVXML.RVHeader := TCustomRichView(doc.rve.RTFReadProperties.HeaderRVData.GetParentControl)
            else
              RVA_RVXML.RVHeader := nil;
            if (doc.rve.RTFReadProperties.FooterRVData<>nil) and
              (doc.rve.RTFReadProperties.FooterRVData.GetParentControl is TCustomRichView) then
              RVA_RVXML.RVFooter := TCustomRichView(doc.rve.RTFReadProperties.FooterRVData.GetParentControl)
            else
              RVA_RVXML.RVFooter := nil;
            RVA_RVXML.SaveToFile(doc.FileName);
          except
            Result := False;
          end;
        end;
      {$ENDIF}
      ffeTextANSI:
         Result := doc.rve.SaveText(doc.FileName, 80);
      ffeTextUnicode:
         Result := doc.rve.SaveTextW(doc.FileName, 80);
      ffeCustom:
        begin
         SuppressNextErrorMessage := False;
         Result := RVA_Events.DoOnCustomFileOperation(Self, doc.rve, doc.FileName,
           rvafoSave, doc.FileFormat, doc.CustomFilterIndex);
        end;
      {$IFDEF USERVHTMLVIEWER}
      ffeHTMLCSS:
        begin
          HTMLTitle := FileTitle;
          if FileTitle='' then
            HTMLTitle := ExtractFileName(doc.FileName);
          Dir := GetImagesDirectory(doc.FileName, CreateDirectoryForHTMLImages, Created);
          ImgPath := Dir;
          if (ImgPath<>'') and (ImgPath[Length(ImgPath)]<>'\') then
            ImgPath := ImgPath+'\';
          ImgPath := ImgPath+ImagePrefix;
          OldImagePrefix := ImagePrefix;
          ImagePrefix := ImgPath;
          try
            Result := doc.rve.SaveHTMLEx(doc.FileName, HTMLTitle, ImgPath, '', '', '', SaveOptions);
          finally
            ImagePrefix := OldImagePrefix;
          end;
          if Created then
            RemoveDir(ExtractFilePath(doc.FileName)+Dir);
        end;
      {$ENDIF}
      else
         Result := False;
    end;
    if Result then
      doc.rve.Modified := False
    else
      doc.Defined := False;
  finally
    Screen.Cursor := crDefault;
  end;
  if not Result and not SuppressNextErrorMessage then
    RVA_MessageBox(RVA_GetSX(rvam_err_ErrorSavingFile),
      RVA_GetSX(rvam_err_Title), MB_OK or MB_ICONSTOP);
  DoDocumentFileChange(Index);
  SuppressNextErrorMessage := False;
end;

function TrvActionSave.SaveDocEx(rve: TCustomRichViewEdit): Boolean;
var idx: Integer;
begin
  Result := True;
  idx := FindDoc(rve);
  if idx<0 then  // should not normally happen
    idx := AddDoc(rve, RVA_DefaultFileName, RVA_DefaultFileFormat, 0, False,
      False, False, False);
  if not TrvaDocumentInfo(FDocuments.Items[idx]).rve.Modified then begin
    Result := True;
    exit;
  end;
  case RVA_MessageBox(
      RVAFormat(RVA_GetSX(rvam_SaveChanges), [ExtractFileName(TrvaDocumentInfo(FDocuments.Items[idx]).FileName)]),
      RVA_GetSX(rvam_Confirm), MB_YESNOCANCEL or MB_ICONQUESTION) of
    IDYES:
      Result := SaveDoc(idx, False);
    IDNO:
      Result := True;
    IDCANCEL:
      Result := False;
  end;
end;

function TrvActionSave.CanCloseDoc(rve: TCustomRichViewEdit): Boolean;
begin
  Result := SaveDocEx(rve);
end;

procedure TrvActionSave.DoDocumentFileChange(Index: Integer);
var doc: TrvaDocumentInfo;
begin
  if Assigned(FOnDocumentFileChange) then begin
    doc := TrvaDocumentInfo(FDocuments.Items[Index]);
    FOnDocumentFileChange(Self, doc.rve, doc.FileName, doc.FileFormat, not doc.Defined);
  end;
end;

{ TrvActionCustomIO }

constructor TrvActionCustomIO.Create(AOwner: TComponent);
begin
  inherited;
  FLastFilterIndex := 1;
  FAutoUpdateFileName := True;
end;

{ TrvActionSaveAs }

constructor TrvActionSaveAs.Create(AOwner: TComponent);
begin
  inherited;
  FFilter := [ffeRVF..{$IFDEF USERVHTMLVIEWER}ffeHTMLCSS{$ELSE}ffeCustom{$ENDIF}];
  FMessageID := rvam_act_SaveAs;
end;

function TrvActionSaveAs.GetActionSave: TrvActionSave;
begin
  if FActionSave<>nil then begin
    Result := FActionSave;
    exit;
  end;
  Result := nil;
  if Owner=nil then
    exit;
  Result := TrvActionSave(RVAFindComponentByClass(Owner, TrvActionSave));
end;

function TrvActionSaveAs.RequiresMainDoc: Boolean;
begin
  Result := True;
end;

procedure TrvActionSaveAs.Notification(AComponent: TComponent;
  Operation: TOperation);
begin
  inherited;
  if (Operation = opRemove) and (AComponent = FActionSave) then
    FActionSave := nil;
end;

procedure TrvActionSaveAs.SetActionSave(const Value: TrvActionSave);
begin
  {$IFDEF RICHVIEWDEF5}
  if FActionSave<>nil then
    FActionSave.RemoveFreeNotification(Self);
  {$ENDIF}
  FActionSave := Value;
  if FActionSave<>nil then
    FActionSave.FreeNotification(Self);
end;

procedure TrvActionSaveAs.ExecuteTarget(Target: TObject);
var
  AActionSave: TrvActionSave;
  rve: TCustomRichViewEdit;
  FilterList: TRVIntegerList;
  FilterString: String;
  ChosenFormat: TrvFileExportFilter;
  CustomFilterIndex: Integer;
  doc: TrvaDocumentInfo;
  idx: Integer;
begin
  rve := GetControl(Target);

  AActionSave := GetActionSave;
  if AActionSave=nil then
    raise Exception.Create(srverrNoActionSave);

  idx := AActionSave.FindDoc(rve);
  if idx>=0 then
    doc := TrvaDocumentInfo(AActionSave.FDocuments.Items[idx])
  else
    doc := nil;

  FilterList := TRVIntegerList.Create;
  try
    FilterString := MakeExportFilter(Filter, FilterList, RVA_RVFFilter, CustomFilter, nil);
    {$IFDEF USEJVCL}
    with TJvSaveDialog2000.Create(Application) do
    {$ELSE}
    with TSaveDialog.Create(Application) do
    {$ENDIF}
    try
      DefaultExt := RVA_DefaultExt;
      Filter := FilterString;
      Options := [ofHideReadOnly, ofPathMustExist, ofEnableSizing, ofNoReadOnlyReturn, ofOverwritePrompt];
      Title := DialogTitle;
      if DialogTitle='' then
        Title := GetTitleFromMenu(RVA_GetS(rvam_act_SaveAs));
      if (doc<>nil) then begin
        FileName := ChangeFileExt(doc.FileName,'');
        if doc.FileFormat<>ffeCustom then
          idx := FilterList.IndexOf(Pointer(doc.FileFormat))
        else
          idx := FilterList.IndexOf(Pointer(-doc.CustomFilterIndex));
        if idx>=0 then
          FilterIndex := idx+1;
      end;
      if ExtractFilePath(FileName)='' then
        InitialDir := FInitialDir;
      if Execute then begin
        if Screen.ActiveForm<>nil then
          Screen.ActiveForm.Update;
        GetExportFilterFormat(FilterList, FilterIndex-1, ChosenFormat, CustomFilterIndex);
        if (ChosenFormat in AActionSave.LostFormatWarning) then begin
          if (RVA_MessageBox(RVAFormat(RVA_GetSX(rvam_LostFormat), [ExtractFileName(FileName)]),
              RVA_GetSX(rvam_Confirm), MB_ICONQUESTION or MB_YESNO)=IDNO) then
            exit;
        end;
        AActionSave.AddDoc(rve, FileName, ChosenFormat, CustomFilterIndex, True,
          True, True, True);
      end;
    finally
      Free;
    end;
  finally
    FilterList.Free;
  end;
end;

{ TrvActionExport }

constructor TrvActionExport.Create(AOwner: TComponent);
begin
  inherited;
  FFilter := [ffeRVF..ffeOfficeConverters];
  ImagePrefix := 'img';
  FCreateDirectoryForHTMLImages := True;
  FMessageID := rvam_act_Export;
end;

function TrvActionExport.RequiresMainDoc: Boolean;
begin
  Result := True;
end;

function TrvActionExport.ExportToFile(Edit: TCustomRichViewEdit; const FileName: String;
  ExportFormat: TrvFileExportFilter; ConverterOrCustomIndex: Integer;
  rvc: TRVOfficeConverter): Boolean;
var
  HTMLTitle, Dir, ImgPath: String;
  DummySaveFormat: TrvFileSaveFilter;
  Created: Boolean;
  OldImagePrefix: String;
begin
  HTMLTitle := FileTitle;
  if FileTitle='' then
    HTMLTitle := ExtractFileName(FileName);
  Screen.Cursor := crHourGlass;
  try
    case ExportFormat of
      ffeRVF:
        Result := Edit.SaveRVF(FileName, False);
      ffeRTF:
        Result := Edit.SaveRTF(FileName, False);
      {$IFDEF USERVXML}
      ffeXML:
        begin
          try
            Result := True;
            RVA_RVXML.RichView := Edit;
            if (Edit.RTFReadProperties.HeaderRVData<>nil) and
              (Edit.RTFReadProperties.HeaderRVData.GetParentControl is TCustomRichView) then
              RVA_RVXML.RVHeader := TCustomRichView(Edit.RTFReadProperties.HeaderRVData.GetParentControl)
            else
              RVA_RVXML.RVHeader := nil;
            if (Edit.RTFReadProperties.FooterRVData<>nil) and
              (Edit.RTFReadProperties.FooterRVData.GetParentControl is TCustomRichView) then
              RVA_RVXML.RVFooter := TCustomRichView(Edit.RTFReadProperties.FooterRVData.GetParentControl)
            else
              RVA_RVXML.RVFooter := nil;
            RVA_RVXML.SaveToFile(FileName);
          except
            Result := False;
          end;
        end;
      {$ENDIF}
      ffeTextANSI:
        Result := Edit.SaveText(FileName, 80);
      ffeTextUnicode:
        Result := Edit.SaveTextW(FileName, 80);
      ffeHTMLCSS:
        begin
          Dir := GetImagesDirectory(FileName, CreateDirectoryForHTMLImages, Created);
          ImgPath := Dir;
          if (ImgPath<>'') and (ImgPath[Length(ImgPath)]<>'\') then
            ImgPath := ImgPath+'\';
          ImgPath := ImgPath+ImagePrefix;
          OldImagePrefix := ImagePrefix;
          ImagePrefix := ImgPath;
          try
            Result := Edit.SaveHTMLEx(FileName, HTMLTitle, ImgPath, '', '', '', SaveOptions);
          finally
            ImagePrefix := OldImagePrefix;
          end;
          if Created then
            RemoveDir(ExtractFilePath(FileName)+Dir);
        end;
      ffeHTML:
        begin
          Dir := GetImagesDirectory(FileName, CreateDirectoryForHTMLImages, Created);
          ImgPath := Dir;
          if (ImgPath<>'') and (ImgPath[Length(ImgPath)]<>'\') then
            ImgPath := ImgPath+'\';
          ImgPath := ImgPath+ImagePrefix;
          OldImagePrefix := ImagePrefix;
          ImagePrefix := ImgPath;
          try
            Result := Edit.SaveHTML(FileName, HTMLTitle, ImgPath, SaveOptions);
          finally
            ImagePrefix := OldImagePrefix;
          end;
          if Created then
            RemoveDir(ExtractFilePath(FileName)+Dir);
        end;
      ffeCustom:
        begin
          DummySaveFormat := ffeCustom;
          Result := RVA_Events.DoOnCustomFileOperation(Self, Edit, FileName,
            rvafoExport, DummySaveFormat, ConverterOrCustomIndex);
        end;
      ffeOfficeConverters:
        Result := rvc.ExportRV(FileName, Edit, ConverterOrCustomIndex);
      else
        Result := False;
    end;
  finally
    Screen.Cursor := crDefault;
  end;
  if not Result then
    RVA_MessageBox(RVA_GetSX(rvam_err_ErrorSavingFile),
      RVA_GetSX(rvam_err_Title), MB_OK or MB_ICONSTOP);
end;

procedure TrvActionExport.ExecuteTarget(Target: TObject);
var
  FilterList: TRVIntegerList;
  FilterString: String;
  rve: TCustomRichViewEdit;
  r : Boolean;
  rvc: TRVOfficeConverter;
  ChosenFormat: TrvFileExportFilter;
  ConverterOrCustomIndex: Integer;
begin
  rve := GetControl(Target);
  rvc := nil;
  FilterList := TRVIntegerList.Create;
  try
    if ffeOfficeConverters in Filter then begin
      rvc := TRVOfficeConverter.Create(nil);
      rvc.ExcludeHTMLExportConverter := True;
      rvc.ExtensionsInFilter := True;
    end;
    FilterString := MakeExportFilter(Filter, FilterList, RVA_RVFFilter,
      CustomFilter, rvc);
    {$IFDEF USEJVCL}
    with TJvSaveDialog2000.Create(Application) do
    {$ELSE}
    with TSaveDialog.Create(Application) do
    {$ENDIF}
    try
      DefaultExt := RVA_DefaultExt;
      Filter := FilterString;
      Options := [ofHideReadOnly, ofPathMustExist, ofEnableSizing, ofNoReadOnlyReturn, ofOverwritePrompt];
      Title := DialogTitle;
      if DialogTitle='' then
        Title := GetTitleFromMenu(RVA_GetS(rvam_act_Export));
      FilterIndex := FLastFilterIndex;
      FileName := ChangeFileExt(FFileName, '');
      if FileName='' then
        InitialDir := FInitialDir;
      if Execute then begin
        if Screen.ActiveForm<>nil then
          Screen.ActiveForm.Update;
        FLastFilterIndex := FilterIndex;
        GetExportFilterFormat(FilterList, FilterIndex-1, ChosenFormat,
          ConverterOrCustomIndex);
        r := ExportToFile(rve, FileName, ChosenFormat, ConverterOrCustomIndex, rvc);
        if r and FAutoUpdateFileName then
          FFileName := FileName;
      end;
    finally
      Free;
    end;
  finally
    FilterList.Free;
    rvc.Free;
  end;
end;

{--------------------------- Insert -------------------------------------------}

{ TrvActionInsertFile }

constructor TrvActionInsertFile.Create(AOwner: TComponent);
begin
  inherited;
  Filter := [ffiRVF..ffiOfficeConverters];
  FMessageID := rvam_act_InsertFile;
end;

function TrvActionInsertFile.InsertFile(rve: TCustomRichViewEdit;
  const FileName: String; FileFormat: TrvFileImportFilter;
  ConverterOrCustomIndex: Integer=0; rvc: TRVOfficeConverter=nil;
  Silent: Boolean=False): Boolean;
var
  DummySaveFormat: TrvFileSaveFilter;
  ImpPicAssigned: Boolean;
  {$IFDEF RVAHTML}
  rv: TRichView;
  rvs: TRVStyle;
  Stream: TStream;
  {$IFNDEF USERVHTMLVIEWER}
  {$IFDEF USERVHTML}
  s: TRVRawByteString;
  {$ENDIF}
  {$ENDIF}
  {$ENDIF}
begin
  Screen.Cursor := crHourGlass;
  try
    ImpPicAssigned := Assigned(rve.OnImportPicture);
    if not ImpPicAssigned then begin
      RVA_Events.InitImportPictures(Self);
      rve.OnImportPicture := RVA_Events.DoImportPicture;
    end;
    try
      case FileFormat of
        ffiRVF:
          Result := rve.InsertRVFFromFileEd(FileName);
        ffiRTF:
          Result := rve.InsertRTFFromFileEd(FileName);
        {$IFDEF USERVXML}
        ffiXML:
          begin
            try
              Result := True;
              RVA_RVXML.RichView := rve;
              RVA_RVXML.InsertFromFile(FileName);
            except
              Result := False;
            end;
          end;
        {$ENDIF}
        ffiTextANSI:
          Result := rve.InsertTextFromFile(FileName);
        ffiTextUnicode:
          Result := rve.InsertTextFromFileW(FileName);
        ffiTextAuto:
          if RV_TestFileUnicode(FileName) = rvutYes then
            Result := rve.InsertTextFromFileW(FileName)
          else
            Result := rve.InsertTextFromFile(FileName);
        {$IFDEF RVAHTML}
        ffiHTML:
          begin
            Result := True;
            try
              rv := TRichView.Create(nil);
              rvs := TRVStyle.Create(nil);
              try
                rvs.ListStyles := rve.Style.ListStyles;
                rvs.TextStyles := rve.Style.TextStyles;
                rvs.ParaStyles := rve.Style.ParaStyles;
                rvs.DefCodePage := rve.Style.DefCodePage;
                rv.Visible := False;
                rv.Parent := rve.Parent;
                rv.Style  := rvs;
                rv.Options := rve.Options;
                rv.RVFOptions := rve.RVFOptions;
                rv.AssignEvents(rve);
                {$IFDEF USERVHTMLVIEWER}
                RVA_RVHTMLView.HTMLViewer.LoadFromFile(FileName);
                RVA_RVHTMLView.ImportHtmlViewer(rv);
                {$ELSE}
                {$IFDEF USERVHTML}
                Stream := TFileStream.Create(FileName, fmOpenRead);
                try
                  SetLength(s, Stream.Size);
                  Stream.ReadBuffer(PRVAnsiChar(s)^, Stream.Size);
                finally
                  Stream.Free;
                end;
                RVA_RVHTML.RichView := rv;
                RVA_RVHTML.BasePath := ExtractFilePath(FileName);
                RVA_RVHTML.LoadHtml(s);
                {$ENDIF}
                {$ENDIF}
                NormalizeRichView(rv.RVData);
                if rve.RTFReadProperties.UnicodeMode=rvruOnlyUnicode then
                  ConvertToUnicode(rv);
                Stream := TMemoryStream.Create;
                try
                  rv.SaveRVFToStream(Stream, False);
                  Stream.Position := 0;
                  Result := rve.InsertRVFFromStreamEd(Stream);
                finally
                  Stream.Free;
                end;
              finally
                rv.Free;
                rvs.Free;
                {$IFNDEF USERVHTMLVIEWER}
                {$IFDEF USERVHTML}
                RVA_RVHTML.RichView := nil;
                {$ENDIF}
                {$ENDIF}
              end;
            except
              Result := False;
            end;
          end;
          {$ENDIF}
          ffiCustom:
            begin
              DummySaveFormat := ffeCustom;
              Result := RVA_Events.DoOnCustomFileOperation(Self, rve, FileName,
                rvafoInsert, DummySaveFormat, ConverterOrCustomIndex);
            end;
          ffiOfficeConverters:
            begin
              Result := rvc.ImportRTF(FileName, ConverterOrCustomIndex);
              {
              with TFileStream.Create('d:\1.rtf', fmCreate) do begin
                CopyFrom(rvc.Stream, 0);
                Free;
              end;
              }
              if Result then begin
                rvc.Stream.Position := 0;
                Result := rve.InsertRTFFromStreamEd(rvc.Stream);
              end;
            end;
          else
            Result := False;
      end;
    finally
      if not ImpPicAssigned then begin
        rve.OnImportPicture := nil;
        RVA_Events.DoneImportPictures;
      end;
    end;
  finally
    Screen.Cursor := crDefault;
  end;
  if not Result and not Silent then begin
    rve.Format;
    RVA_MessageBox(RVA_GetSX(rvam_err_ErrorLoadingFile),
      RVA_GetSX(rvam_err_Title), MB_OK or MB_ICONSTOP);
  end;
end;

procedure TrvActionInsertFile.ExecuteTarget(Target: TObject);
var
  FilterList: TRVIntegerList;
  FilterString: String;
  LFilter : TrvFileImportFilterSet;
  rve: TCustomRichViewEdit;
  rvc: TRVOfficeConverter;
  ChosenFormat: TrvFileImportFilter;
  ConverterOrCustomIndex: Integer;
begin
  rve := GetControl(Target);
  rvc := nil;
  LFilter := Filter;
  if RVA_UserInterface=rvauiText then
    LFilter := LFilter * [ffiTextANSI, ffiTextUnicode, ffiTextAuto];
  if LFilter=[] then
    exit;
  FilterList := TRVIntegerList.Create;
  try
    if ffiOfficeConverters in LFilter then begin
      rvc := TRVOfficeConverter.Create(nil);
      {$IFDEF RVAHTML}
      rvc.ExcludeHTMLImportConverter := True;
      {$ENDIF}
      rvc.ExtensionsInFilter := True;
    end;
    FilterString := MakeImportFilter(LFilter, FilterList, RVA_RVFFilter,
      CustomFilter, rvc);
    {$IFDEF USEJVCL}
    with TJvOpenDialog2000.Create(Application) do
    {$ELSE}
    with TOpenDialog.Create(Application) do
    {$ENDIF}
    try
      if RVA_UserInterface=rvauiText then
        DefaultExt := 'txt'
      else begin
        DefaultExt := RVA_DefaultExt;
        FilterIndex := FLastFilterIndex;        
      end;
      Filter := FilterString;
      Options := [ofHideReadOnly, ofPathMustExist, ofFileMustExist, ofEnableSizing];
      Title := DialogTitle;
      if DialogTitle='' then
        Title := GetTitleFromMenu(RVA_GetS(rvam_act_InsertFile));
      FileName := FFileName;
      if FFileName='' then
        InitialDir := FInitialDir;
      if Execute then begin
        if Screen.ActiveForm<>nil then
          Screen.ActiveForm.Update;
        if RVA_UserInterface<>rvauiText then
          FLastFilterIndex := FilterIndex;
        GetImportFilterFormat(FilterList, FilterIndex-1, ChosenFormat,
          ConverterOrCustomIndex);
        if InsertFile(rve, FileName, ChosenFormat, ConverterOrCustomIndex, rvc) and
          FAutoUpdateFileName then
          FFileName := FileName;
      end;
    finally
      Free;
    end;
  finally
    FilterList.Free;
    rvc.Free;
  end;
end;

procedure TrvActionInsertFile.UpdateTarget(Target: TObject);
var rve: TCustomRichViewEdit;
begin
  if not RVA_ActionsEnabled or Disabled then begin
    Enabled := False;
    exit;
  end;
  rve := GetControl(Target).TopLevelEditor;
  Enabled := {not rve.ReadOnly and} (rve.RVData.PartialSelectedItem=nil);
end;

{ TrvActionInsertText }

procedure TrvActionInsertText.ExecuteTarget(Target: TObject);
var rve: TCustomRichViewEdit;
    s: String;
begin
  if Assigned(FOnInsertText) then begin
    rve := GetControl(Target);
    s := '';
    FOnInsertText(Self, rve, s);
    if s<>'' then
      rve.InsertText(s);
    end
  else
    Beep;
end;

procedure TrvActionInsertText.UpdateTarget(Target: TObject);
var rve: TCustomRichViewEdit;
begin
  if not RVA_ActionsEnabled or Disabled then begin
    Enabled := False;
    exit;
  end;
  rve := GetControl(Target).TopLevelEditor;
  Enabled := rve.RVData.PartialSelectedItem=nil;
end;

{ TrvActionInsertPicture }

constructor TrvActionInsertPicture.Create(AOwner: TComponent);
begin
  inherited;
  DefaultExt := 'bmp';
  VAlign := rvvaBaseline;
  FMessageID := rvam_act_InsertPicture;
end;

function TrvActionInsertPicture.IsImageTooLarge(gr: TGraphic): Boolean;
begin
  Result := (MaxImageSize>0) and
    ((gr.Width >TRVStyle.GetAsPixelsEx(MaxImageSize, RVA_UnitsProgram)) or
     (gr.Height>TRVStyle.GetAsPixelsEx(MaxImageSize, RVA_UnitsProgram)));
end;

procedure TrvActionInsertPicture.GetProperImageSize(gr: TGraphic; RVStyle: TRVStyle;
  var Width, Height: TRVStyleLength);
var Max: Integer;
begin
  if gr.Width>gr.Height then
    Max := gr.Width
  else
    Max := gr.Height;
  Width := Round(gr.Width*TRVStyle.GetAsPixelsEx(MaxImageSize, RVA_UnitsProgram)/Max);
  Height := Round(gr.Height*TRVStyle.GetAsPixelsEx(MaxImageSize, RVA_UnitsProgram)/Max);
  Width := RVStyle.PixelsToUnits(Width);
  Height := RVStyle.PixelsToUnits(Height);
end;

procedure TrvActionInsertPicture.ExecuteTarget(Target: TObject);
var pic: TPicture;
    gr: TGraphic;
    rve: TCustomRichViewEdit;
    ItemName: TRVAnsiString;
    IsGroupOperation, IsTooLarge: Boolean;
    ImageWidth, ImageHeight: TRVStyleLength;
begin
  rve := GetControl(Target).TopLevelEditor;
  with TOpenPictureDialog.Create(Application) do
  try
    if FFilter<>'' then
      Filter := FFilter;
    Title := FDialogTitle;
    if DialogTitle='' then
        Title := GetTitleFromMenu(RVA_GetS(rvam_act_InsertPicture));
    DefaultExt := FDefaultExt;
    Options := [ofHideReadOnly, ofPathMustExist, ofFileMustExist, ofEnableSizing];
    FilterIndex := FLastFilterIndex;
    FileName := FFileName;
    if FFileName='' then
      InitialDir := FInitialDir;
    if Execute then begin
      FLastFilterIndex := FilterIndex;
      if Screen.ActiveForm<>nil then
        Screen.ActiveForm.Update;
      pic := TPicture.Create;
      try
        pic.LoadFromFile(FileName);
        gr := RV_CreateGraphics(TGraphicClass(pic.Graphic.ClassType));
        gr.Assign(pic.Graphic);
        IsTooLarge := IsImageTooLarge(gr);
        IsGroupOperation := StoreFileName or IsTooLarge;
        if IsGroupOperation then begin
          rve.BeginUndoGroup(rvutInsert);
          rve.SetUndoGroupMode(True);
          if IsTooLarge then
            rve.BeginUpdate;
        end;
        try
          if StoreFileNameInItemName then
            ItemName := TRVAnsiString(FileName)
          else
            ItemName := '';
          if rve.InsertPicture(ItemName, gr, VAlign) then begin
            if StoreFileName then
              rve.SetCurrentItemExtraStrProperty(rvespImageFileName, FileName, True);
            if IsImageTooLarge(gr) then begin
              GetProperImageSize(gr, rve.Style, ImageWidth, ImageHeight);
              rve.SetCurrentItemExtraIntProperty(rvepImageHeight, ImageHeight, True);
              rve.SetCurrentItemExtraIntProperty(rvepImageWidth, ImageWidth, True);
              rve.SetCurrentItemExtraIntProperty(rvepSpacing,
                rve.Style.DifferentUnitsToUnits(FSpacing, RVA_UnitsProgram), True);
            end;
          end;
        finally
          if IsGroupOperation then begin
            if IsTooLarge then
              rve.EndUpdate;
            rve.SetUndoGroupMode(False);
          end;
        end;
        FFileName := FileName;
      except
        RVA_MessageBox(RVA_GetSX(rvam_err_ErrorLoadingImageFile),
          RVA_GetSX(rvam_err_Title), MB_OK or MB_ICONEXCLAMATION);
      end;
      pic.Free;
    end;
  finally
    Free;
  end;
end;

procedure TrvActionInsertPicture.UpdateTarget(Target: TObject);
var rve: TCustomRichViewEdit;
begin
  if not RVA_ActionsEnabled or Disabled or (RVA_UserInterface=rvauiText) then begin
    Enabled := False;
    exit;
  end;
  rve := GetControl(Target).TopLevelEditor;
  Enabled := {not rve.ReadOnly and} (rve.RVData.PartialSelectedItem=nil);
end;

procedure TrvActionInsertPicture.ConvertToPixels;
begin
  inherited;
  Spacing := TRVStyle.GetAsPixelsEx(Spacing, RVA_UnitsProgram);
  MaxImageSize := TRVStyle.GetAsPixelsEx(MaxImageSize, RVA_UnitsProgram);
end;

procedure TrvActionInsertPicture.ConvertToTwips;
begin
  inherited;
  Spacing := TRVStyle.GetAsTwipsEx(Spacing, RVA_UnitsProgram);
  MaxImageSize := TRVStyle.GetAsTwipsEx(MaxImageSize, RVA_UnitsProgram);
end;

{ TrvActionInsertHLine }

procedure TrvActionInsertHLine.ConvertToPixels;
begin
  inherited;
  Width := TRVStyle.GetAsPixelsEx(Width, RVA_UnitsProgram);
end;

procedure TrvActionInsertHLine.ConvertToTwips;
begin
  inherited;
  Width := TRVStyle.GetAsTwipsEx(Width, RVA_UnitsProgram);
end;

constructor TrvActionInsertHLine.Create(AOwner: TComponent);
begin
  inherited;
  Color := clWindowText;
  Width := 1;
  Style := rvbsLine;
  FMessageID := rvam_act_InsertHLine;
end;

procedure TrvActionInsertHLine.ExecuteTarget(Target: TObject);
begin
  GetControl(Target).InsertBreak(
    GetControl(Target).Style.DifferentUnitsToUnits(Width, RVA_UnitsProgram),
    Style, Color);
end;

procedure TrvActionInsertHLine.UpdateTarget(Target: TObject);
var rve: TCustomRichViewEdit;
begin
  if not RVA_ActionsEnabled or Disabled or (RVA_UserInterface=rvauiText) then begin
    Enabled := False;
    exit;
  end;
  rve := GetControl(Target).TopLevelEditor;
  Enabled := {not rve.ReadOnly and} (rve.RVData.PartialSelectedItem=nil);
end;

{ TrvActionInsertSymbol }

constructor TrvActionInsertSymbol.Create(AOwner: TComponent);
begin
  inherited;
  FFontName := 'Symbol';
  FDisplayUnicodeBlocks := True;
  FMessageID := rvam_act_InsertSymbol;
  FCharCode := 183;
  {$IFNDEF RVUNICODESTR}
  AlwaysInsertUnicode := True;
  {$ENDIF}
end;

procedure TrvActionInsertSymbol.ExecuteTarget(Target: TObject);
var frm: TFrmRVInsertSymbol;
    fi: TFontInfo;
    rve: TCustomRichViewEdit;
    idx, ctsn: Integer;
    Charset: TFontCharset;
    str: TRVRawByteString;
begin
  rve := GetControl(Target);
  frm := TFrmRVInsertSymbol.Create(Application);
  try
    frm.SetOptions(FSymbolType in [rvisBoth, rvisUnicode],
                   FSymbolType in [rvisBoth, rvisSingleByte],
                   FDisplayUnicodeBlocks);
    if FUseCurrentFont then begin
      fi := rve.Style.TextStyles[rve.CurTextStyleNo];
      if fi.Unicode or (FSymbolType=rvisUnicode) then begin
        if not FUnicode then
          FCharCode := 183;
        frm.Init(FCharCode, fi.FontName, DEFAULT_CHARSET)
        end
      else begin
        Charset := fi.Charset;
        if Charset=DEFAULT_CHARSET then
          Charset := RVU_CodePage2Charset(GetACP);
        if FUnicode <> (Charset=DEFAULT_CHARSET) then
          FCharCode := 183;
        frm.Init(FCharCode, fi.FontName, Charset);
      end;
      end
    else
      if FInitialized then
        frm.Init(FCharCode, FFontName, FCharset);
    if frm.ShowModal=mrOk then begin
      frm.GetInfo(FCharCode, FFontName, FCharset);
      FInitialized := True;
      fi := TFontInfo.Create(nil);
      ctsn := rve.CurTextStyleNo;
      fi.Assign(rve.Style.TextStyles[ctsn]);
      fi.FontName := FFontName;
      fi.Charset := FCharset;
      fi.Unicode := (FCharset = DEFAULT_CHARSET);
      if not fi.Unicode and AlwaysInsertUnicode then begin
        str := RVU_AnsiToUnicode(RVU_Charset2CodePage(FCharset), TRVAnsiChar(FCharCode));
        FCharCode := PWord(Pointer(str))^;
        fi.Unicode := True;
      end;
      FUnicode := fi.Unicode;
      fi.Protection := fi.Protection+[rvprDoNotAutoSwitch];
      fi.Standard := False;
      idx := RVA_Events.DoStyleNeeded(Self, rve.Style, fi);
      if idx<0 then begin
        idx := rve.Style.TextStyles.FindSuchStyle(ctsn, fi, RVAllFontInfoProperties);
        if idx<0 then begin
          rve.Style.TextStyles.Add.Assign(fi);
          idx := rve.Style.TextStyles.Count-1;
          RVA_Events.DoOnAddStyle(Self, rve.Style.TextStyles[idx]);
        end;
      end;
      rve.CurTextStyleNo := idx;
      if fi.Unicode then
        rve.InsertTextW(WideChar(FCharCode))
      else
        rve.InsertTextA(TRVAnsiChar(FCharCode));
      rve.CurTextStyleNo := ctsn;
      fi.Free;
    end;
  finally
    frm.Free;
  end;
end;

procedure TrvActionInsertSymbol.UpdateTarget(Target: TObject);
var rve: TCustomRichViewEdit;
begin
  if not RVA_ActionsEnabled or Disabled then begin
    Enabled := False;
    exit;
  end;
  rve := GetControl(Target).TopLevelEditor;
  Enabled := {not rve.ReadOnly and} (rve.RVData.PartialSelectedItem=nil);
end;

{ TrvActionInsertHyperlink }

constructor TrvActionInsertHyperlink.Create(AOwner: TComponent);
begin
  inherited;
  Color          := clBlue;
  HoverColor     := clBlue;
  BackColor      := clNone;
  HoverBackColor := clNone;
  Style          := [fsUnderline];
  Cursor         := crJump;
  ValidProperties :=
    [rvhlUnderline, rvhlColor, rvhlBackColor, rvhlHoverColor, rvhlHoverBackColor, rvhlCursor, rvhlJump];
  SetToPictures := True;
  SpaceFiller   := ' ';
  FMessageID    := rvam_act_Hyperlink;
end;

procedure TrvActionInsertHyperlink.UpdateTarget(Target: TObject);
var rve: TCustomRichViewEdit;
    en: Boolean;
begin
  if not RVA_ActionsEnabled or Disabled or (RVA_UserInterface=rvauiText) then begin
    Enabled := False;
    exit;
  end;
  try
    rve := GetControl(Target).TopLevelEditor;
    en := (rvoTagsArePChars in rve.Options) and
          {not rve.ReadOnly and}
          (rve.RVData.PartialSelectedItem=nil);
    Enabled := en;
  except
    Enabled := False;
  end;
end;

type
  TControlControlHack = class (TControl)
    public
      property Color;
  end;

function TrvActionInsertHyperlink.DoShowForm(InsertNew: Boolean; var Text,
  Target: String): Boolean;
var frm: TfrmRVHyp;
begin
  if Assigned(FOnHyperlinkForm) then begin
    Result := True;
    FOnHyperlinkForm(Self, InsertNew, Text, Target, Result);
    end
  else begin
    frm := TfrmRVHyp.Create(Application);
    try
      frm.TextColor := Color;
      frm.BackColor := BackColor;
      frm.HoverColor := HoverColor;
      frm.HoverBackColor := HoverBackColor;
      if not InsertNew then begin
        frm._txtText.Enabled := False;
        if Text='' then
          frm.SetControlCaption(frm._txtText, RVA_GetS(rvam_hl_Selection))
        else
          frm.SetControlCaption(frm._txtText, Text);
        TControlControlHack(frm._txtText).Color := clBtnFace;
        frm.SetControlCaption(frm._txtTarget, Target);
      end;
      Result := frm.ShowModal=mrOk;
      if Result then begin
        Color := frm.TextColor;
        BackColor := frm.BackColor;
        HoverColor := frm.HoverColor;
        HoverBackColor := frm.HoverBackColor;
        Text := frm.GetEditText(frm._txtText);
        Target := frm.GetEditText(frm._txtTarget);
      end;
    finally
      frm.Free;
    end;
  end;
end;

procedure TrvActionInsertHyperlink.ExecuteTarget(Target: TObject);
var
    rve: TCustomRichViewEdit;
    Text, LinkTarget: String;
    InsertNew: Boolean;
    OldStyleNo: Integer;
begin
  rve := GetControl(Target);
  InsertNew := not HasItems(rve, LinkTarget);
  Text := rve.GetSelText;
  if (Pos(#13,Text)>0) or (Pos(#10,Text)>0) then
    Text := '';
  if DoShowForm(InsertNew, Text, LinkTarget) then begin
    OldStyleNo := rve.CurTextStyleNo;
    if InsertNew then begin
      rve.CurTextStyleNo := GetHyperlinkStyleNo(rve);
      rve.InsertStringTag(Text, Integer(StrNew(PChar(EncodeTarget(LinkTarget)))));
      end
    else
      SetTags(rve, EncodeTarget(LinkTarget));
    rve.CurTextStyleNo := OldStyleNo;      
  end;
end;

function TrvActionInsertHyperlink.HasItems(
  rve: TCustomRichViewEdit; var Target: String): Boolean;
  {......................................}
  function CheckItem(ItemNo: Integer): Boolean;
  begin
    Result := (rve.GetItemStyle(ItemNo)>=0) and (rve.Style.TextStyles[rve.GetItemStyle(ItemNo)].Jump);
    if Result then begin
      rve.SetSelectionBounds(ItemNo, rve.GetOffsBeforeItem(ItemNo),
                             ItemNo, rve.GetOffsAfterItem(ItemNo));
      rve.Refresh;
    end;
  end;
  {......................................}
  function CheckItem2(ItemNo: Integer): Boolean;
  var Target: String;
  begin
    Result := SetToPictures and (rve.GetItem(ItemNo) is TRVGraphicItemInfo);
    if not Result and (rve.GetItemStyle(ItemNo)<0) and
       Assigned(OnGetHyperlinkTargetFromItem) then begin
      Target := '';
      OnGetHyperlinkTargetFromItem(Self, rve, rve.RVData, ItemNo, Target);
      Result := Target<>'';
    end;
    if Result then begin
      rve.SetSelectionBounds(ItemNo, rve.GetOffsBeforeItem(ItemNo),
                             ItemNo, rve.GetOffsAfterItem(ItemNo));
      rve.Refresh;
    end;
  end;
  {......................................}
var ItemNo, StartItemNo, EndItemNo, StartOffs, EndOffs: Integer;
    s: String;
    Expanded, IsFirst: Boolean;
begin
  rve := rve.TopLevelEditor;
  if not rve.SelectionExists then begin
    ItemNo := rve.CurItemNo;
    Expanded := False;
    if not CheckItem(ItemNo) then begin
      if (ItemNo>0) and not rve.IsFromNewLine(ItemNo) and (rve.OffsetInCurItem<=rve.GetOffsBeforeItem(ItemNo)) then
        Expanded := CheckItem(ItemNo-1)
      else if (ItemNo+1<rve.ItemCount) and not rve.IsFromNewLine(ItemNo+1) and (rve.OffsetInCurItem>=rve.GetOffsAfterItem(ItemNo)) then
        Expanded := CheckItem(ItemNo+1)
      end
    else
      Expanded := True;
    if not Expanded then
      CheckItem2(ItemNo);
  end;
  Target := '';
  rve.GetSelectionBounds(StartItemNo, StartOffs, EndItemNo, EndOffs, True);
  Result := (StartItemNo>=0) and not ((StartItemNo=EndItemNo) and (StartOffs=EndOffs));
  if not Result then exit;
  IsFirst := True;
  for ItemNo := StartItemNo to EndItemNo do
    if (rve.GetItemStyle(ItemNo)>=0) or
       (SetToPictures and (rve.GetItem(ItemNo) is TRVGraphicItemInfo)) then begin
      s := PChar(rve.GetItemTag(ItemNo));
      if IsFirst then
        Target := s
      else if Target<>s then begin
        Target := '';
        exit;
      end;
      IsFirst := False;
      end
    else if (rve.GetItemStyle(ItemNo)<0) and Assigned(OnGetHyperlinkTargetFromItem) then begin
      OnGetHyperlinkTargetFromItem(Self, rve, rve.RVData, ItemNo, s);
      if s='' then
        continue;
      if IsFirst then
        Target := s
      else if Target<>s then begin
        Target := '';
        exit;
      end;
      IsFirst := False;
    end;
end;

function TrvActionInsertHyperlink.GetHyperlinkStyleNo(rve: TCustomRichViewEdit;
  StyleNo: Integer=-1): Integer;
var FontInfo: TFontInfo;
begin
  if StyleNo<0 then
    StyleNo := rve.CurTextStyleNo;
  FontInfo := TFontInfo.Create(nil);
  FontInfo.Assign(rve.Style.TextStyles[StyleNo]);
  ApplyConversion(rve, FontInfo, StyleNo, 1);
  Result := RVA_Events.DoStyleNeeded(Self, rve.Style, FontInfo);
  if Result<0 then begin
    Result := rve.Style.TextStyles.FindSuchStyle(StyleNo, FontInfo, RVAllFontInfoProperties);
    if Result<0 then begin
      rve.Style.TextStyles.Add.Assign(FontInfo);
      Result := rve.Style.TextStyles.Count-1;
      rve.Style.TextStyles[Result].Standard := False;
      rve.Style.TextStyles[Result].NextStyleNo := StyleNo;
      RVA_Events.DoOnAddStyle(Self, rve.Style.TextStyles[Result]);
    end;
  end;
  FontInfo.Free;
end;

function TrvActionInsertHyperlink.GetNormalStyleNo(rve: TCustomRichViewEdit; StyleNo: Integer=-1): Integer;
var FontInfo: TFontInfo;
begin
  if StyleNo<0 then
    StyleNo := rve.CurTextStyleNo;
  Result := rve.Style.TextStyles[StyleNo].NextStyleNo;
  if Result>=0 then
    exit;
  FontInfo := TFontInfo.Create(nil);
  FontInfo.Assign(rve.Style.TextStyles[StyleNo]);
  FDefaultFontInfo := rve.Style.TextStyles[0];
  ApplyConversion(rve, FontInfo, StyleNo, 0);
  FDefaultFontInfo := nil;
  Result := RVA_Events.DoStyleNeeded(Self, rve.Style, FontInfo);
  if Result<0 then begin
    Result := rve.Style.TextStyles.FindSuchStyle(StyleNo, FontInfo, RVAllFontInfoProperties);
    if Result<0 then begin
      rve.Style.TextStyles.Add.Assign(FontInfo);
      Result := rve.Style.TextStyles.Count-1;
      rve.Style.TextStyles[Result].Standard := False;
      rve.Style.TextStyles[Result].NextStyleNo := -1;
      RVA_Events.DoOnAddStyle(Self, rve.Style.TextStyles[Result]);
    end;
  end;
  FontInfo.Free;
end;

function IsPunctuation(Ch: Char; IncludeClosingBrackets, IncludeDot: Boolean): Boolean;
begin
  case Ch of
   '<', '>', '[', '"', '''',
   ',', ':', ';', '(','{',
   RVCHAR_LQUOTE, RVCHAR_RQUOTE,
   RVCHAR_LDQUOTE, RVCHAR_RDQUOTE:
     Result := True;
   ')', ']':
     Result := IncludeClosingBrackets;
   '.':
     Result := IncludeDot;
   else
     Result := False;
  end;
end;

procedure TrvActionInsertHyperlink.DetectURL(rve: TCustomRichViewEdit);
var ItemNo, WordEnd, WordStart, CurStyleNo: Integer;
    s: String;
    EndShifted: Boolean;
begin
  if not (rvoTagsArePChars in rve.Options) then
    exit;
  rve := rve.TopLevelEditor;
  if rve.SelectionExists then
    exit;
  ItemNo := rve.CurItemNo;
  if (rve.GetItemStyle(ItemNo)<0) or rve.Style.TextStyles[rve.GetItemStyle(ItemNo)].Jump then
    exit;
  WordEnd := rve.OffsetInCurItem;
  if WordEnd<=1 then
    exit;
  s := rve.GetItemText(ItemNo);
  WordStart := WordEnd-1;
  while (WordStart>1) and (s[WordStart-1]<>' ') do
    dec(WordStart);
  EndShifted := False;
  s := Copy(s, WordStart, WordEnd-WordStart);
  if (Length(s)>0) and IsPunctuation(s[1], True, False) then begin
    inc(WordStart);
    s := Copy(s, 2, Length(s)-1);
  end;
  if (Length(s)>0) and (
      IsPunctuation(s[Length(s)], False, True) or
     ((s[Length(s)]=')') and (AnsiPos('(',s)=0)) or
     ((s[Length(s)]='}') and (AnsiPos('{',s)=0)) or
     ((s[Length(s)]=']') and (AnsiPos('[',s)=0))) then begin
    dec(WordEnd);
    s := Copy(s, 1, Length(s)-1);
    EndShifted := True;
  end;
  if RVIsEmail(s) or RVIsURL(s) then begin
    CurStyleNo := rve.CurTextStyleNo;
    rve.SetSelectionBounds(ItemNo, WordStart, ItemNo, WordEnd);
    rve.BeginUndoGroup(rvutTag);
    rve.SetUndoGroupMode(True);
    try
      rve.ApplyTextStyle(GetHyperlinkStyleNo(rve));
      if not RVIsURL(s) and RVIsEmail(s) then
        s := 'mailto:'+s;
      rve.SetCurrentTag(Integer(StrNew(PChar(EncodeTarget(s)))));
    finally
      rve.SetUndoGroupMode(False);
    end;
    rve.SetSelectionBounds(rve.CurItemNo, rve.OffsetInCurItem, rve.CurItemNo, rve.OffsetInCurItem);
    if EndShifted then
      SendMessage(rve.Handle, WM_KEYDOWN, VK_RIGHT, 0);
    rve.CurTextStyleNo := CurStyleNo;
  end;
end;

procedure TrvActionInsertHyperlink.TerminateHyperlink(rve: TCustomRichViewEdit);
begin
  if (rve.CurTextStyleNo=rve.CurItemStyle) and
     rve.Style.TextStyles[rve.CurTextStyleNo].Jump and
     not rve.SelectionExists then begin
    rve := rve.TopLevelEditor;
    if rve.OffsetInCurItem>=rve.GetOffsAfterItem(rve.CurItemNo) then
      rve.CurTextStyleNo := GetNormalStyleNo(rve);
  end;
end;

procedure TrvActionInsertHyperlink.SetTags(rve: TCustomRichViewEdit;
  const Target: String);
var i, StartNo, EndNo: Integer;
begin
  rve := rve.TopLevelEditor;
  rve.BeginUndoGroup(rvutTag);
  rve.SetUndoGroupMode(True);
  try
    FDefaultFontInfo := rve.Style.TextStyles[0];
    if Target='' then
      ExecuteCommand(rve, 0)
    else
      ExecuteCommand(rve, 1);
    FDefaultFontInfo := nil;
    GetSelectionBounds(rve, StartNo, EndNo);
    for i := StartNo to EndNo do begin
      if SetToPictures then begin
        if rvhlJump in ValidProperties then begin
          if (Target<>'') and (rve.GetItemStyle(i)=rvsPicture) then
            rve.ConvertToHotPicture(i)
          else if (Target='') and (rve.GetItemStyle(i)=rvsHotPicture) then
            rve.ConvertToPicture(i);
        end;
      end;
      if (rve.GetItemStyle(i)>=0) or (SetToPictures and (rve.GetItem(i) is TRVGraphicItemInfo)) then
        rve.SetItemTagEd(i, Integer(StrNew(PChar(Target))))
      else if Assigned(FOnApplyHyperlinkToItem) then
        FOnApplyHyperlinkToItem(Self, rve, rve.RVData, i, Target);
    end;
  finally
    rve.SetUndoGroupMode(False);
  end;
end;

function TrvActionInsertHyperlink.IsRecursive: Boolean;
begin
  Result := False;
end;

procedure TrvActionInsertHyperlink.ApplyConversion(Editor: TCustomRichViewEdit;
  FontInfo: TFontInfo; StyleNo, Command: Integer);

  procedure SetFontStyle(fs: TFontStyle; Prop: TRVHyperlinkProperty; Style: TFontStyles);
  begin
    if Prop in ValidProperties then
      if fs in Style then
        FontInfo.Style := FontInfo.Style+[fs]
      else
        FontInfo.Style := FontInfo.Style-[fs];
  end;
begin
  case Command of
  0: // clearing hyperlink style
    begin
      if rvhlJump in ValidProperties then
        FontInfo.Jump := False;
      if rvhlColor in ValidProperties then
        FontInfo.Color := FDefaultFontInfo.Color;
      if rvhlHoverColor in ValidProperties then
        FontInfo.HoverColor := FDefaultFontInfo.HoverColor;
      if rvhlBackColor in ValidProperties then
        FontInfo.BackColor := FDefaultFontInfo.BackColor;
      if rvhlHoverBackColor in ValidProperties then
        FontInfo.HoverBackColor := FDefaultFontInfo.HoverBackColor;
      if rvhlCursor in ValidProperties then
        FontInfo.JumpCursor := FDefaultFontInfo.JumpCursor;
      SetFontStyle(fsBold, rvhlBold, FDefaultFontInfo.Style);
      SetFontStyle(fsItalic, rvhlItalic, FDefaultFontInfo.Style);
      SetFontStyle(fsUnderline, rvhlUnderline, FDefaultFontInfo.Style);
      SetFontStyle(fsStrikeOut, rvhlStrikeout, FDefaultFontInfo.Style);
      FontInfo.NextStyleNo := -1;
    end;
  1: // applying hyperlink style
    begin
      if rvhlJump in ValidProperties then
        FontInfo.Jump := True;
      if rvhlColor in ValidProperties then
        FontInfo.Color := Color;
      if rvhlHoverColor in ValidProperties then
        FontInfo.HoverColor := HoverColor;
      if rvhlBackColor in ValidProperties then
        FontInfo.BackColor := BackColor;
      if rvhlHoverBackColor in ValidProperties then
        FontInfo.HoverBackColor := HoverBackColor;
      if rvhlCursor in ValidProperties then
        FontInfo.JumpCursor := Cursor;
      SetFontStyle(fsBold, rvhlBold, Style);
      SetFontStyle(fsItalic, rvhlItalic, Style);
      SetFontStyle(fsUnderline, rvhlUnderline, Style);
      SetFontStyle(fsStrikeOut, rvhlStrikeout, Style);
      if Editor.Style.TextStyles[StyleNo].Jump then
        FontInfo.NextStyleNo := Editor.Style.TextStyles[StyleNo].NextStyleNo
      else
        FontInfo.NextStyleNo := StyleNo;
    end;
  end;
end;

function GoToCheckpoint(rv: TCustomRichViewEdit; const CPName: String): Boolean;

function _GoToCheckpoint(RVData: TCustomRVFormattedData;
  rv: TCustomRichViewEdit; const CPName: String): Boolean;
var i,r,c,Tag: Integer;
    CPD: TCheckpointData;
    Name: String;
    RI: Boolean;
    table: TRVTableItemInfo;
begin
  for i := 0 to RVData.ItemCount-1 do begin
    CPD := RVData.GetItemCheckpoint(i);
    if Assigned(CPD) then begin
      RVData.GetCheckpointInfo(CPD, Tag, Name, RI);
      if Name=CPName then begin
        RVData := TCustomRVFormattedData(RVData.Edit);
        RVData.SetSelectionBounds(i, RVData.GetOffsBeforeItem(i), i, RVData.GetOffsBeforeItem(i));
        Result := True;
        exit;
      end;
    end;
    if RVData.GetItemStyle(i)=rvsTable then begin
      table := TRVTableItemInfo(RVData.GetItem(i));
      for r := 0 to table.Rows.Count-1 do
        for c := 0 to table.Rows[r].Count-1 do
          if table.Cells[r,c]<>nil then begin
            Result := _GoToCheckpoint(
              TCustomRVFormattedData(table.Cells[r,c].GetRVData),
              rv, CPName);
            if Result then
              exit;
          end;
    end;
  end;
  Result := False;
end;

begin
  Result := _GoToCheckpoint(rv.RVData, rv, CPName);
end;

procedure TrvActionInsertHyperlink.GoToLink(rve: TCustomRichViewEdit;
  id: Integer);
var RVData: TCustomRVFormattedData;
    ItemNo: Integer;
    URL: String;
begin
  rve.GetJumpPointLocation(id, RVData, ItemNo);
  URL := PChar(RVData.GetItemTag(ItemNo));
  if URL='' then
    exit;
  if URL[1]='#' then begin
    if not GoToCheckpoint(rve, Copy(URL, 2, Length(URL)-1)) then
      RVA_MessageBox(RVAFormat(RVA_GetSX(rvam_hl_CannotNavigate),[URL]),
        RVA_GetSX(rvam_err_Title), MB_OK or MB_ICONEXCLAMATION);
    exit;
  end;
  //if AnsiLowerCase(Copy(URL, 1, 8))='file:///' then
  //   URL := Copy(URL, 9, Length(URL)-8);
  if ShellExecute(0, 'open', PChar(URL), nil, nil, SW_SHOW)<=32 then
    RVA_MessageBox(RVAFormat(RVA_GetSX(rvam_hl_CannotNavigate),[URL]),
      RVA_GetSX(rvam_err_Title), MB_OK or MB_ICONEXCLAMATION);
end;

function TrvActionInsertHyperlink.EncodeTarget(const Target: String): String;
var p: Integer;
begin
  Result := Target;
  for p := Length(Result) downto 1 do
    if (Result[p]=#10) or (Result[p]=#13) then
      Delete(Result, p, 1);
  if Pos(' ', SpaceFiller)>0 then
    exit;
  while True do begin
    p := Pos(' ', Result);
    if p=0 then
      exit;
    Delete(Result, p, 1);
    Insert(SpaceFiller, Result, p);
  end;
end;

{ TrvActionHide }

procedure TrvActionHide.ApplyConversion(Editor: TCustomRichViewEdit;
  FontInfo: TFontInfo; StyleNo, Command: Integer);
begin
  if Checked then
    FontInfo.Options := FontInfo.Options - [rvteoHidden]
  else
    FontInfo.Options := FontInfo.Options + [rvteoHidden];
end;

constructor TrvActionHide.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_Hide;
end;

function TrvActionHide.IsRecursive: Boolean;
begin
  Result := False;
end;

procedure TrvActionHide.ExecuteTarget(Target: TObject);
var i, StartNo, EndNo: Integer;
    rve: TCustomRichViewEdit;
begin
  rve := GetControl(Target).TopLevelEditor;
  rve.BeginUpdate;
  rve.BeginUndoGroup(rvutStyleNo);
  rve.SetUndoGroupMode(True);
  try
    GetSelectionBounds(rve, StartNo, EndNo);
    for i := StartNo to EndNo do begin
      if rve.GetItemStyle(i)<0 then begin
        rve.SetItemExtraIntPropertyEd(i, rvepHidden, ord(not Checked), True);
      end;
    end;
    ExecuteCommand(rve, 0);    
  finally
    rve.SetUndoGroupMode(False);
    rve.EndUpdate;
  end;
end;

procedure TrvActionHide.UpdateTarget(Target: TObject);
var rve: TCustomRichViewEdit;
    Chk: Integer;
begin
  try
    rve := GetControl(Target).TopLevelEditor;
    Enabled := RVA_ActionsEnabled and not Disabled and Assigned(rve.Style) and
      (rve.RVData.PartialSelectedItem=nil) and
      (RVA_UserInterface<>rvauiText);
    if not Enabled then begin
      Checked := False;
      exit;
    end;
    if rve.CurItemStyle<0 then
      if rve.GetCurrentItemExtraIntProperty(rvepHidden, Chk) then
        Checked := Chk<>0
      else
        Checked := False
    else
      Checked := (rvteoHidden in rve.Style.TextStyles[rve.CurTextStyleNo].Options);
  except
    Enabled := False;
  end;
end;

{ TrvActionRemoveHyperlinks }


constructor TrvActionRemoveHyperlinks.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_RemoveHyperlinks;
end;


procedure TrvActionRemoveHyperlinks.ExecuteTarget(Target: TObject);
var act: TrvActionInsertHyperlink;
    tmp: String;
begin
  act := GetActionInsertHyperlink;
  if (act=nil) then
    exit;
  act.HasItems(GetControl(Target), tmp);
  act.SetTags(GetControl(Target), '');
end;

procedure TrvActionRemoveHyperlinks.UpdateTarget(Target: TObject);
var act: TrvActionInsertHyperlink;
begin
  act := GetActionInsertHyperlink;
  if not RVA_ActionsEnabled or Disabled or (act=nil) then begin
    Enabled := False;
    exit;
  end;
  act.UpdateTarget(Target);
end;

function TrvActionRemoveHyperlinks.GetActionInsertHyperlink: TrvActionInsertHyperlink;
begin
  if FActionInsertHyperlink<>nil then begin
    Result := FActionInsertHyperlink;
    exit;
  end;
  Result := nil;
  if Owner=nil then
    exit;
  Result := TrvActionInsertHyperlink(RVAFindComponentByClass(Owner, TrvActionInsertHyperlink));
end;


{---------------------------- Printing ----------------------------------------}


{ TrvCustomPrintAction }

function TrvCustomPrintAction.FindRVPrint(Form: TComponent): TRVPrint;
begin
  Result := TRVPrint(RVAFindComponentByClass(Form, TRVPrint));
end;

procedure TrvCustomPrintAction.InitRVPrint(Form: TComponent;
  var ARVPrint: TRVPrint; var ACreated: Boolean);
begin
  ACreated := False;
  ARVPrint := RVA_RVPrint;
  if ARVPrint=nil then
    ARVPrint := FindRVPrint(Form);
  if ARVPrint=nil then
  begin
    ARVPrint := TRVPrint.Create(Form);
    ACreated := True;
  end;
  FOldOnPagePrepaint := ARVPrint.OnPagePrepaint;
  ARVPrint.OnPagePrepaint := PagePrepaint;
end;

procedure TrvCustomPrintAction.DoneRVPrint(ARVPrint: TRVPrint;
  ACreated: Boolean);
begin
  ARVPrint.OnPagePrepaint := FOldOnPagePrepaint;
  if ACreated then
    ARVPrint.Free;
end;

procedure TrvCustomPrintAction.UpdateTarget(Target: TObject);
begin
  if not RVA_ActionsEnabled or Disabled then begin
    Enabled := False;
    exit;
  end;
  Enabled := (GetControl(Target).ItemCount > 0) and (Printer.Printers.Count>0);
end;

procedure TrvCustomPrintAction.PagePrepaint(Sender: TRVPrint; PageNo: Integer;
  Canvas: TCanvas; Preview: Boolean; PageRect, PrintAreaRect: TRect);

  function Parse(const s: String): String;
  var i,j: Integer;
      Field: Boolean;
      s2: String;
  begin
    Result := '';
    Field := False;
    j := 1;
    for i := 1 to Length(s) do
      if Field then begin
        if {$IFDEF RVUNICODESTR}
           CharInSet(s[i], ['&', 'p', 'P', 'd', 't'])
           {$ELSE}
           s[i] in ['&', 'p', 'P', 'd', 't']
           {$ENDIF} then begin
          Result := Result+Copy(s, j, i-j-1);
          case s[i] of
            '&':
              Result := Result+'&';
            'p':
              Result := Result+IntToStr(PageNo+RVA_FirstPageNumber-1);
            'P':
              Result := Result+IntToStr(Sender.PagesCount);
            'd':
              Result := Result+DateToStr(Date);
            't':
              begin
                DateTimeToString(s2, {$IFDEF RICHVIEWDEFXE}FormatSettings.{$ENDIF}ShortTimeFormat, Time);
                Result := Result+s2;
              end;
          end;
          j := i+1;
        end;
        Field := False;
        end
      else
        Field := s[i]='&';
    if j<Length(s) then
      Result := Result+Copy(s, j, Length(s)-j+1);
  end;


  procedure PrintHF(HF: THFInfo; Header: Boolean);
  var s: String;
      ppi, y, h, flag: Integer;
      r: TRect;
  begin
    if (HF.Text='') or ((PageNo=1) and not HF.PrintOnFirstPage) then
      exit;
    s := Parse(HF.Text);
    ppi := Canvas.Font.PixelsPerInch;
    Canvas.Font := HF.Font;
    Canvas.Font.PixelsPerInch := ppi;
    h := Canvas.TextHeight(s);
    if Header then
      y := PrintAreaRect.Top-h-ppi div 20
    else
      y := PrintAreaRect.Bottom+ppi div 20;
    r := Rect(PrintAreaRect.Left,y, PrintAreaRect.Right, y+h);
    case HF.Alignment of
      taRightJustify:
        flag := DT_RIGHT;
      taCenter:
        flag := DT_CENTER;
      else
        flag := DT_LEFT;
    end;
    DrawText(Canvas.Handle, PChar(s), Length(s), r,
      DT_SINGLELINE or DT_NOCLIP or DT_NOPREFIX or flag);
  end;

begin
  if Assigned(FOldOnPagePrepaint) then
    FOldOnPagePrepaint(Sender, PageNo, Canvas, Preview, PageRect, PrintAreaRect);
  PrintHF(RVA_HeaderInfo, True);
  PrintHF(RVA_FooterInfo, False);
end;

function TrvCustomPrintAction.RequiresMainDoc: Boolean;
begin
  Result := True;
end;

{ TrvActionPrintPreview }

constructor TrvActionPrintPreview.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_Preview;
end;

procedure TrvActionPrintPreview.ExecuteTarget(Target: TObject);
var
  ARVPrint: TRVPrint;
  ACreated: Boolean;
  PreviewForm: TfrmRVPreview;
  AActionPrint: TrvActionPrint;
  rve, OldControl: TCustomRichViewEdit;

begin
  AActionPrint := GetActionPrint;
  PreviewForm := GetPreviewFormClass.Create(Application) as TfrmRVPreview;
  if FMaximized then
    PreviewForm.WindowState := wsMaximized;
  rve := GetControl(Target);
  InitRVPrint(rve.Owner, ARVPrint, ACreated);
  try
    Screen.Cursor := crHourGlass;
    PreviewForm.actPrint.Enabled := AActionPrint<>nil;
    try
      ARVPrint.AssignSource(rve);
      ARVPrint.FormatPages(rvdoALL);
      if RVA_ShowSoftPageBreaks then
        rve.AssignSoftPageBreaks(ARVPrint);
    finally
      Screen.Cursor := crDefault;
    end;
    if ARVPrint.PagesCount > 0 then begin
      PreviewForm.rvpp.RVPrint := ARVPrint;
      PreviewForm.actFirst.Execute;
      if FActionPageSetup<>nil then
        PreviewForm.SetPageSetup(FActionPageSetup);
      if (PreviewForm.ShowModal=mrOk) and (AActionPrint<>nil) then
        if Assigned(AActionPrint.OnExecute) then
          AActionPrint.OnExecute(AActionPrint)
        else begin
          OldControl := AActionPrint.Control;
          AActionPrint.Control := Control;
          try
            AActionPrint.ExecuteTarget(Target);
          finally
            AActionPrint.Control := OldControl;          
          end;
        end;
      end
    else
      Beep;
  finally
    DoneRVPrint(ARVPrint, ACreated);
    PreviewForm.Free;
  end;
end;

function TrvActionPrintPreview.GetActionPrint: TrvActionPrint;
begin
  if FActionPrint<>nil then begin
    Result := FActionPrint;
    exit;
  end;
  Result := nil;
  if Owner=nil then
    exit;
  Result := TrvActionPrint(RVAFindComponentByClass(Owner, TrvActionPrint));
end;

function TrvActionPrintPreview.GetPreviewFormClass: TFormClass;
begin
  if Assigned(OnGetPreviewFormClass) then
    OnGetPreviewFormClass(Self, Result)
  else
    Result := TfrmRVPreview;
  if not Result.InheritsFrom(TfrmRVPreview) then
    raise ERichViewError.Create(
      'Preview form must be inherited from TfrmRVPreview');
end;

procedure TrvActionPrintPreview.SetActionPageSetup(
  const Value: TrvActionPageSetup);
begin
  {$IFDEF RICHVIEWDEF5}
  if FActionPageSetup<>nil then
    FActionPageSetup.RemoveFreeNotification(Self);
  {$ENDIF}
  FActionPageSetup := Value;
  if FActionPageSetup<>nil then
    FActionPageSetup.FreeNotification(Self);
end;

procedure TrvActionPrintPreview.SetActionPrint(
  const Value: TrvActionPrint);
begin
  {$IFDEF RICHVIEWDEF5}
  if FActionPrint<>nil then
    FActionPrint.RemoveFreeNotification(Self);
  {$ENDIF}
  FActionPrint := Value;
  if FActionPrint<>nil then
    FActionPrint.FreeNotification(Self);
end;

{ TrvActionPrint }

constructor TrvActionPrint.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_Print;
end;

procedure TrvActionPrint.ExecuteTarget(Target: TObject);
var
  ARVPrint: TRVPrint;
  ACreated: Boolean;
  Dlg: TPrintDialog;
  rve: TCustomRichViewEdit;
  rv: TRichView;
  Stream: TMemoryStream;
begin
  rve := GetControl(Target);
  InitRVPrint(rve.Owner, ARVPrint, ACreated);
  try
    Screen.Cursor := crHourGlass;
    ARVPrint.AssignSource(rve);
    ARVPrint.FormatPages(rvdoALL);
    if RVA_ShowSoftPageBreaks then
      rve.AssignSoftPageBreaks(ARVPrint);
    Screen.Cursor := crDefault;
    if (ARVPrint.PagesCount > 0) and (ARVPrint.FirstPageNo<=ARVPrint.LastPageNo) then begin
      Dlg := TPrintDialog.Create(Application);
      try
        Dlg.Options := Dlg.Options + [poPageNums];
        if rve.SelectionExists then
          Dlg.Options := Dlg.Options + [poSelection];
        Dlg.MinPage := ARVPrint.FirstPageNo;
        Dlg.MaxPage := ARVPrint.LastPageNo;
        Dlg.FromPage := ARVPrint.FirstPageNo;
        Dlg.ToPage := ARVPrint.LastPageNo;
        if Dlg.Execute then begin
          Screen.Cursor := crHourGlass;
          ARVPrint.FormatPages(rvdoALL);
          if (Dlg.PrintRange<>prSelection) and RVA_ShowSoftPageBreaks then
            rve.AssignSoftPageBreaks(ARVPrint);
          case Dlg.PrintRange of
            prAllPages:
              ARVPrint.Print(Title, Dlg.Copies, Dlg.Collate);
            prPageNums:
              ARVPrint.PrintPages(Dlg.FromPage, Dlg.ToPage, Title, Dlg.Copies,
                Dlg.Collate);
            prSelection:
              begin
                rv := TRichView.Create(nil);
                try
                  rv.Visible := False;
                  rv.Parent := rve.Parent;
                  rv.Style := rve.Style;
                  rv.Options := rve.Options;
                  rv.RVFTextStylesReadMode := rvf_sIgnore;
                  rv.RVFParaStylesReadMode := rvf_sIgnore;
                  Stream := TMemoryStream.Create;
                  try
                    rve.SaveRVFToStream(Stream, True);
                    Stream.Position := 0;
                    rv.LoadRVFFromStream(Stream);
                  finally
                    Stream.Free;
                  end;
                  ARVPrint.AssignSource(rv);
                  ARVPrint.FormatPages(rvdoALL);
                  ARVPrint.Print(Title, Dlg.Copies, Dlg.Collate);
                finally
                  rv.Free;
                end;
              end;
          end;
        end;
      finally
        ARVPrint.Clear;
        Screen.Cursor := crDefault;
        Dlg.Free;
      end;
      end
    else
      Beep;
  finally
    DoneRVPrint(ARVPrint, ACreated);
  end;
end;

{ TrvActionQuickPrint }

constructor TrvActionQuickPrint.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_QuickPrint;
end;

procedure TrvActionQuickPrint.ExecuteTarget(Target: TObject);
var
  ARVPrint: TRVPrint;
  ACreated: Boolean;
  rve: TCustomRichViewEdit;
begin
  rve := GetControl(Target);
  InitRVPrint(rve.Owner, ARVPrint, ACreated);
  Screen.Cursor := crHourGlass;
  try
    ARVPrint.AssignSource(rve);
    ARVPrint.FormatPages(rvdoALL);
    if ARVPrint.PagesCount > 0 then begin
      if RVA_ShowSoftPageBreaks then
        rve.AssignSoftPageBreaks(ARVPrint);
      ARVPrint.Print(Title, 1, False);
      end
    else
      Beep;
  finally
    Screen.Cursor := crDefault;
    DoneRVPrint(ARVPrint, ACreated);
  end;
end;

procedure TrvActionQuickPrint.Localize;
begin
  Caption := {$IFDEF USERVTNT}_GetWideString{$ENDIF}(RVA_GetS(rvam_act_QuickPrint));
  Hint    := {$IFDEF USERVTNT}_GetWideString{$ENDIF}(RVA_GetS(rvam_act_QuickPrintH));
end;

{ TrvActionPageSetup }


constructor TrvActionPageSetup.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_PageSetup;
end;

procedure TrvActionPageSetup.ExecuteTarget(Target: TObject);
var frm: TfrmRVPageSetup;
begin
  frm := TfrmRVPageSetup.Create(Application);
  try
    if MarginsUnits=rvpmuInches then
      frm.UseInches;
    if frm.Init and (frm.ShowModal=mrOk) then begin
      frm.Apply;
      if Assigned(FOnChange) then
         FOnChange(Self);
    end;
  finally
    frm.Free;
  end;
end;

function TrvActionPageSetup.HandlesTarget(Target: TObject): Boolean;
begin
  Result := True;
end;

procedure TrvActionPageSetup.UpdateTarget(Target: TObject);
begin
  Enabled := RVA_ActionsEnabled and not Disabled and
    (RVA_RVPrint<>nil) and (Printer.Printers.Count>0);
end;
{---------------------------- Find and Replace --------------------------------}

{ TrvActionFind }

procedure TrvActionFind.CloseDialog;
begin
  if FFindDialog<>nil then
    FFindDialog.CloseDialog;
end;

constructor TrvActionFind.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_Find;
end;

destructor TrvActionFind.Destroy;
begin
  if FFindDialog<>nil then
    TrvaFindDialog(FFindDialog).FAction := nil;
  inherited;
end;

{.$DEFINE RVUNICODESEARCH}

{$IFDEF USERVTNT}
{$DEFINE RVUNICODESEARCH}
{$ENDIF}
{$IFDEF RVUNICODESTR}
{$DEFINE RVUNICODESEARCH}
{$ENDIF}

procedure TrvActionFind.ExecuteTarget(Target: TObject);
var AActionReplace: TrvActionReplace;
{$IFDEF USERVTNT}
  s: WideString;
{$ELSE}
  s: String;
{$ENDIF}
begin
  AActionReplace := GetActionReplace;
  if AActionReplace<>nil then
    AActionReplace.CloseDialog;

  FEdit := GetControl(Target);
  FEdit.FreeNotification(Self);

  if FFindDialog=nil then begin
    FFindDialog := TrvaFindDialog.Create(GetControl(Target).Owner);
    FFindDialog.OnFind := FindDialogFind;
    FFindDialog.OnClose := FindDialogClose;
    TrvaFindDialog(FFindDialog).FAction := Self;
  end;
  if not FFindDialogVisible then begin
    {$IFDEF RVUNICODESEARCH}
    s := GetControl(Target).GetSelTextW;
    {$ELSE}
    s := GetControl(Target).GetSelText;
    {$ENDIF}
    if Pos(#13, s)=0 then
      FFindDialog.FindText := s;
  end;
  FFindDialogVisible := True;
  FFindDialog.Execute;
end;

procedure TrvActionFind.FindDialogFind(Sender: TObject);
var AActionReplace: TrvActionReplace;
    Found: Boolean;
    {$IFDEF USERVTNT}
    s: WideString;
    {$ELSE}
    s: String;
    {$ENDIF}
    SelStart: Integer;
    SecondAttempt: Boolean;
begin
  if FEdit=nil then
    exit;
  AActionReplace := GetActionReplace;
  if AActionReplace<>nil then
    AActionReplace.CloseDialog;
  {$IFDEF RVUNICODESEARCH}
  Found := FEdit.SearchTextW(FFindDialog.FindText,
    GetRVESearchOptions(FFindDialog.Options));
  {$ELSE}
  Found := FEdit.SearchText(FFindDialog.FindText,
    GetRVESearchOptions(FFindDialog.Options));
  {$ENDIF}
  {SecondAttempt := False;}
  if not Found then begin
    if frDown in FFindDialog.Options then begin
      s := RVA_GetSX(rvam_src_ContinueFromStart);
      SecondAttempt := (FEdit.InplaceEditor<>nil) or
        (((FEdit.CurItemNo>0) or (FEdit.OffsetInCurItem>FEdit.GetOffsBeforeItem(0))));
      end
    else begin
      s := RVA_GetSX(rvam_src_ContinueFromEnd);
      SecondAttempt := (FEdit.InplaceEditor<>nil) or
        (((FEdit.CurItemNo<FEdit.ItemCount-1) or (FEdit.OffsetInCurItem<FEdit.GetOffsAfterItem(FEdit.ItemCount-1))));
    end;
    if SecondAttempt and ((RVA_SearchScope=rvssGlobal) or
      ((RVA_SearchScope=rvssAskUser) and
       (RVA_MessageBox(s, RVA_GetSX(rvam_src_Complete), MB_ICONQUESTION or MB_YESNO)=IDYES))) then begin
      {SecondAttempt := False;}
      SelStart := RVGetLinearCaretPos(FEdit);
      if frDown in FFindDialog.Options then
        FEdit.SetSelectionBounds(0, FEdit.GetOffsBeforeItem(0), 0, FEdit.GetOffsBeforeItem(0))
      else
        FEdit.SetSelectionBounds(FEdit.ItemCount-1, FEdit.GetOffsAfterItem(FEdit.ItemCount-1),
          FEdit.ItemCount-1, FEdit.GetOffsAfterItem(FEdit.ItemCount-1));
      {$IFDEF RVUNICODESEARCH}
      Found := FEdit.SearchTextW(FFindDialog.FindText,
        GetRVESearchOptions(FFindDialog.Options));
      {$ELSE}
      Found := FEdit.SearchText(FFindDialog.FindText,
        GetRVESearchOptions(FFindDialog.Options));
      {$ENDIF}
      if not Found then
        RVSetLinearCaretPos(FEdit, SelStart);
    end;
  end;
  if not Found {and not (SecondAttempt and (RVA_SearchScope=rvssAskUser))} then
   RVA_MessageBox(
     RVAFormat(RVA_GetSX(rvam_src_NotFound),[FFindDialog.FindText]),
     RVA_GetSX(rvam_src_Complete), MB_OK or MB_ICONINFORMATION);
end;

procedure TrvActionFind.FindDialogClose(Sender: TObject);
begin
  FFindDialogVisible := False;
end;

function TrvActionFind.GetActionReplace: TrvActionReplace;
begin
  if FActionReplace<>nil then begin
    Result := FActionReplace;
    exit;
  end;
  Result := nil;
  if Owner=nil then
    exit;
  Result := TrvActionReplace(RVAFindComponentByClass(Owner, TrvActionReplace));
end;

procedure TrvActionFind.Notification(AComponent: TComponent;
  Operation: TOperation);
begin
  inherited;
  if (Operation=opRemove) and (AComponent=FEdit) then
    FEdit := nil;
  if (Operation=opRemove) and (AComponent=FActionReplace) then
    FActionReplace := nil;
end;

procedure TrvActionFind.SetActionReplace(const Value: TrvActionReplace);
begin
  {$IFDEF RICHVIEWDEF5}
  if FActionReplace<>nil then
    FActionReplace.RemoveFreeNotification(Self);
  {$ENDIF}
  FActionReplace := Value;
  if FActionReplace<>nil then
    FActionReplace.FreeNotification(Self);
end;

procedure TrvActionFind.UpdateTarget(Target: TObject);
begin
  Enabled := RVA_ActionsEnabled and not Disabled and
    (GetControl(Target).Owner<>nil);
end;

{ TrvActionFindNext }

constructor TrvActionFindNext.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_FindNext;
end;

procedure TrvActionFindNext.ExecuteTarget(Target: TObject);
var AActionFind: TrvActionFind;
begin
  AActionFind := GetActionFind;
  if AActionFind=nil then
    raise Exception.Create(srverrNoActionFind);
  if (AActionFind.FFindDialog=nil) or
     (AActionFind.FFindDialog.FindText='') then
    AActionFind.Execute
  else
    AActionFind.FindDialogFind(AActionFind.FFindDialog);
end;

function TrvActionFindNext.GetActionFind: TrvActionFind;
begin
  if FActionFind<>nil then begin
    Result := FActionFind;
    exit;
  end;
  Result := nil;
  if Owner=nil then
    exit;
  Result := TrvActionFind(RVAFindComponentByClass(Owner, TrvActionFind));
end;

procedure TrvActionFindNext.Notification(AComponent: TComponent;
  Operation: TOperation);
begin
  inherited;
  if (Operation=opRemove) and (AComponent=FActionFind) then
    FActionFind := nil;
end;


procedure TrvActionFindNext.SetActionFind(const Value: TrvActionFind);
begin
  {$IFDEF RICHVIEWDEF5}
  if FActionFind<>nil then
    FActionFind.RemoveFreeNotification(Self);
  {$ENDIF}
  FActionFind := Value;
  if FActionFind<>nil then
    FActionFind.FreeNotification(Self);
end;

{ TrvActionReplace }

procedure TrvActionReplace.CloseDialog;
begin
  if FReplaceDialog<>nil then
    FReplaceDialog.CloseDialog;
end;

constructor TrvActionReplace.Create(AOwner: TComponent);
begin
  inherited;
  FShowReplaceAllSummary := True;
  FMessageID := rvam_act_Replace;
end;

destructor TrvActionReplace.Destroy;
begin
  if FReplaceDialog<>nil then
    TrvaReplaceDialog(FReplaceDialog).FAction := nil;
  inherited;
end;

procedure TrvActionReplace.DoReplacing(Editor: TCustomRichViewEdit;
  const NewText: String);
begin
  if Assigned(FOnReplacing) then begin
    Editor := TCustomRichViewEdit(Editor.RVData.GetAbsoluteRootData.GetParentControl);
    FOnReplacing(Self, Editor, NewText);
  end;
end;

procedure TrvActionReplace.ExecuteTarget(Target: TObject);
var AActionFind: TrvActionFind;
{$IFDEF USERVTNT}
  s: WideString;
{$ELSE}
  s: String;
{$ENDIF}
begin
  AActionFind := GetActionFind;
  if AActionFind<>nil then
    AActionFind.CloseDialog;
  FEdit := GetControl(Target);
  FEdit.FreeNotification(Self);
  if FReplaceDialog=nil then begin
    FReplaceDialog := TrvaReplaceDialog.Create(GetControl(Target).Owner);
    FReplaceDialog.OnFind := ReplaceDialogFind;
    FReplaceDialog.OnReplace := ReplaceDialogReplace;
    FReplaceDialog.OnClose := ReplaceDialogClose;
    TrvaReplaceDialog(FReplaceDialog).FAction := Self;
  end;
  if not FReplaceDialogVisible then begin
    {$IFDEF RVUNICODESEARCH}
    s := GetControl(Target).GetSelTextW;
    {$ELSE}
    s := GetControl(Target).GetSelText;
    {$ENDIF}
    if Pos(#13, s)=0 then
      FReplaceDialog.FindText := s;
  end;
  FReplaceDialogVisible := True;
  FReplaceDialog.Execute;
end;

function TrvActionReplace.GetActionFind: TrvActionFind;
begin
  if FActionFind<>nil then begin
    Result := FActionFind;
    exit;
  end;
  Result := nil;
  if Owner=nil then
    exit;
  Result := TrvActionFind(RVAFindComponentByClass(Owner, TrvActionFind));
end;

procedure TrvActionReplace.Notification(AComponent: TComponent;
  Operation: TOperation);
begin
  inherited;
  if (Operation=opRemove) and (AComponent=FEdit) then
    FEdit := nil;
  if (Operation=opRemove) and (AComponent=FActionFind) then
    FActionFind := nil;
end;

procedure TrvActionReplace.ReplaceDialogFind(Sender: TObject);
var
    Found: Boolean;
    {$IFDEF USERVTNT}
    s: WideString;
    {$ELSE}
    s: String;
    {$ENDIF}
    SelStart: Integer;
    SecondAttempt: Boolean;
begin
  if FEdit=nil then
    exit;
  {$IFDEF RVUNICODESEARCH}
  Found := FEdit.SearchTextW(FReplaceDialog.FindText,
    GetRVESearchOptions(FReplaceDialog.Options));
  {$ELSE}
  Found := FEdit.SearchText(FReplaceDialog.FindText,
    GetRVESearchOptions(FReplaceDialog.Options));
  {$ENDIF}
  if not Found then begin
    if frDown in FReplaceDialog.Options then begin
      s := RVA_GetSX(rvam_src_ContinueFromStart);
      SecondAttempt := (FEdit.InplaceEditor<>nil) or
        (((FEdit.CurItemNo>0) or (FEdit.OffsetInCurItem>FEdit.GetOffsBeforeItem(0))));
      end
    else begin
      s := RVA_GetSX(rvam_src_ContinueFromEnd);
      SecondAttempt := (FEdit.InplaceEditor<>nil) or
        (((FEdit.CurItemNo<FEdit.ItemCount-1) or (FEdit.OffsetInCurItem<FEdit.GetOffsAfterItem(FEdit.ItemCount-1))));
    end;
    if SecondAttempt and ((RVA_SearchScope=rvssGlobal) or
      ((RVA_SearchScope=rvssAskUser) and
       (RVA_MessageBox(s, RVA_GetSX(rvam_src_Complete), MB_ICONQUESTION or MB_YESNO)=IDYES))) then begin
      SelStart := RVGetLinearCaretPos(FEdit);
      if frDown in FReplaceDialog.Options then
        FEdit.SetSelectionBounds(0, FEdit.GetOffsBeforeItem(0), 0, FEdit.GetOffsBeforeItem(0))
      else
        FEdit.SetSelectionBounds(FEdit.ItemCount-1, FEdit.GetOffsAfterItem(FEdit.ItemCount-1),
          FEdit.ItemCount-1, FEdit.GetOffsAfterItem(FEdit.ItemCount-1));
      {$IFDEF RVUNICODESEARCH}
      Found := FEdit.SearchTextW(FReplaceDialog.FindText,
        GetRVESearchOptions(FReplaceDialog.Options));
      {$ELSE}
      Found := FEdit.SearchText(FReplaceDialog.FindText,
        GetRVESearchOptions(FReplaceDialog.Options));
      {$ENDIF}
      if not Found then
        RVSetLinearCaretPos(FEdit, SelStart);
    end;
  end;
  if not Found then
   RVA_MessageBox(RVAFormat(RVA_GetSX(rvam_src_NotFound),[FReplaceDialog.FindText]),
     RVA_GetSX(rvam_src_Complete), MB_OK or MB_ICONINFORMATION);
end;

procedure TrvActionReplace.ReplaceDialogClose(Sender: TObject);
begin
  FReplaceDialogVisible := False;
end;

procedure TrvActionReplace.ReplaceDialogReplace(Sender: TObject);
var i,c: Integer;
    SecondAttempt: Boolean;
    {$IFDEF USERVTNT}
    s, sq: WideString;
    {$ELSE}
    s, sq: String;
    {$ENDIF}
    SelStart: Integer;

    function IsTextEqual(const s1, s2: String): Boolean;
    begin
      if frMatchCase in FReplaceDialog.Options then
        Result := s1=s2
      else
        Result := AnsiCompareText(s1,s2)=0;
    end;

begin
  if FEdit=nil then
    exit;
  if frReplace in FReplaceDialog.Options then begin
    if IsTextEqual(
      {$IFDEF RVUNICODESEARCH}FEdit.GetSelTextW{$ELSE}FEdit.GetSelText{$ENDIF},
      FReplaceDialog.FindText) then begin
      DoReplacing(FEdit, FReplaceDialog.ReplaceText);
      {$IFDEF RVUNICODESEARCH}
      FEdit.InsertTextW
      {$ELSE}
      FEdit.InsertTextA
      {$ENDIF}
        (FReplaceDialog.ReplaceText, not (frDown in FReplaceDialog.Options));
    end;
    ReplaceDialogFind(Sender);
    end
  else if frReplaceAll in FReplaceDialog.Options then begin
    c := 0;
    SelStart := -1;
    for i := 1 to 2 do begin
      if Assigned(FOnReplaceAllStart) then
        FOnReplaceAllStart(Self, FEdit);
      if (RVA_SearchScope=rvssGlobal) then
        if frDown in FReplaceDialog.Options then
          FEdit.SetSelectionBounds(0, FEdit.GetOffsBeforeItem(0), 0, FEdit.GetOffsBeforeItem(0))
        else
          FEdit.SetSelectionBounds(FEdit.ItemCount-1, FEdit.GetOffsAfterItem(FEdit.ItemCount-1),
            FEdit.ItemCount-1, FEdit.GetOffsAfterItem(FEdit.ItemCount-1));
      Screen.Cursor := crHourGlass;
      try
        if (i=1) and IsTextEqual(
          {$IFDEF RVUNICODESEARCH}FEdit.GetSelTextW{$ELSE}FEdit.GetSelText{$ENDIF},
          FReplaceDialog.FindText) then begin
          DoReplacing(FEdit, FReplaceDialog.ReplaceText);
          {$IFDEF RVUNICODESEARCH}
          FEdit.InsertTextW
          {$ELSE}
          FEdit.InsertTextA
          {$ENDIF}
            (FReplaceDialog.ReplaceText, not (frDown in FReplaceDialog.Options));
          inc(c);
        end;
        while
          {$IFDEF RVUNICODESEARCH}
          FEdit.SearchTextW(FReplaceDialog.FindText, GetRVESearchOptions(FReplaceDialog.Options))
          {$ELSE}
          FEdit.SearchText(FReplaceDialog.FindText, GetRVESearchOptions(FReplaceDialog.Options))
          {$ENDIF}
          do begin
          DoReplacing(FEdit, FReplaceDialog.ReplaceText);
          {$IFDEF RVUNICODESEARCH}
          FEdit.InsertTextW
          {$ELSE}
          FEdit.InsertTextA
          {$ENDIF}
            (FReplaceDialog.ReplaceText, not (frDown in FReplaceDialog.Options));
          inc(c);
          SelStart := -1;
        end;
      finally
        if Assigned(FOnReplaceAllEnd) then
          FOnReplaceAllEnd(Self, FEdit);
        Screen.Cursor := crDefault;
        FEdit.Refresh;
      end;
      if frDown in FReplaceDialog.Options then begin
        sq := RVA_GetSX(rvam_src_ContinueFromStart);
        SecondAttempt := (FEdit.InplaceEditor=nil) and
          ((FEdit.CurItemNo>0) or (FEdit.OffsetInCurItem>FEdit.GetOffsBeforeItem(0)));
        end
      else begin
        sq := RVA_GetSX(rvam_src_ContinueFromEnd);
        SecondAttempt := (FEdit.InplaceEditor=nil) and
          ((FEdit.CurItemNo<FEdit.ItemCount-1) or (FEdit.OffsetInCurItem<FEdit.GetOffsAfterItem(FEdit.ItemCount-1)));
      end;
      if (i=2) or (RVA_SearchScope<>rvssAskUser) then
        SecondAttempt := False;
      if FShowReplaceAllSummary and not SecondAttempt then begin
        if c=1 then
          s := RVA_GetSX(rvam_src_1Replaced)
        else
          s := RVAFormat(RVA_GetSX(rvam_src_NReplaced), [c]);
        RVA_MessageBox(s, RVA_GetSX(rvam_src_Complete), MB_OK or MB_ICONINFORMATION);
      end;
      if SecondAttempt then begin
        if FShowReplaceAllSummary then begin
          if c=1 then
            s := RVA_GetSX(rvam_src_1Replaced)
          else
            s := RVAFormat(RVA_GetSX(rvam_src_NReplaced), [c]);
          sq := s+#13+sq;
        end;
        SecondAttempt := (RVA_SearchScope=rvssAskUser) and
          (RVA_MessageBox(sq, RVA_GetSX(rvam_src_Complete), MB_ICONQUESTION or MB_YESNO)=IDYES);
        if SecondAttempt then begin
          SelStart := RVGetLinearCaretPos(FEdit);
          if frDown in FReplaceDialog.Options then
            FEdit.SetSelectionBounds(0, FEdit.GetOffsBeforeItem(0), 0, FEdit.GetOffsBeforeItem(0))
          else
            FEdit.SetSelectionBounds(FEdit.ItemCount-1, FEdit.GetOffsAfterItem(FEdit.ItemCount-1),
              FEdit.ItemCount-1, FEdit.GetOffsAfterItem(FEdit.ItemCount-1));
        end;
      end;
      if not SecondAttempt then
        break;
    end;
    if SelStart>=0 then
      RVSetLinearCaretPos(FEdit, SelStart);
  end;
end;

procedure TrvActionReplace.SetActionFind(const Value: TrvActionFind);
begin
  {$IFDEF RICHVIEWDEF5}
  if FActionFind<>nil then
    FActionFind.RemoveFreeNotification(Self);
  {$ENDIF}
  FActionFind := Value;
  if FActionFind<>nil then
    FActionFind.FreeNotification(Self);
end;

procedure TrvActionReplace.UpdateTarget(Target: TObject);
var rve: TCustomRichViewEdit;
begin
  if not RVA_ActionsEnabled or Disabled then begin
    Enabled := False;
    exit;
  end;
  rve := GetControl(Target);
  Enabled := {not rve.ReadOnly and} (rve.Owner<>nil);
end;

{---------------------------- Edit --------------------------------------------}

{ TrvCustomEditAction }

function TrvCustomEditAction.IsDifferentEditor(Target: TObject): Boolean;
begin
  Result := (Target is TControl) and
    (not RVA_EditForceDefControl or (GetDefaultControl=nil)) and
    RVA_EditorControlFunction(TControl(Target), rvaeccIsEditorControl);
end;

function TrvCustomEditAction.GetDefaultControl: TCustomRichViewEdit;
begin
  Result := Control;
  if Control=nil then
    Control := RVA_DefaultControl;
end;

function TrvCustomEditAction.HandlesTarget(Target: TObject): Boolean;
begin
  if Control<>nil then
   Target := Control
  else if RVA_DefaultControl<>nil then
   Target := RVA_DefaultControl;
  Result := (Target is TCustomRichViewEdit) or IsDifferentEditor(Target);
end;

procedure TrvCustomEditAction.UpdateTarget(Target: TObject);
var rve: TCustomRichViewEdit;
begin
  if not RVA_ActionsEnabled or Disabled then begin
    Enabled := False;
    exit;
  end;
  if IsDifferentEditor(Target) then
    Enabled := RVA_EditorControlFunction(TControl(Target), rvaeccHasSelection)
  else begin
    rve := GetControl(Target);
    Enabled := rve.SelectionExists;
  end;
end;

{ TrvActionUndo }

constructor TrvActionUndo.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_Undo;
end;

procedure TrvActionUndo.ExecuteTarget(Target: TObject);
begin
  if IsDifferentEditor(Target) then
    RVA_EditorControlFunction(TControl(Target), rvaeccUndo)
  else
    GetControl(Target).Undo;
end;

procedure TrvActionUndo.UpdateTarget(Target: TObject);
var rve: TCustomRichViewEdit;
begin
  if not RVA_ActionsEnabled or Disabled then begin
    Enabled := False;
    exit;
  end;
  if IsDifferentEditor(Target) then
    Enabled := RVA_EditorControlFunction(TControl(Target), rvaeccCanUndo)
  else begin
    rve := GetControl(Target);
    Enabled := (rve.UndoAction <> rvutNone);
  end;
end;

{ TrvActionRedo }

constructor TrvActionRedo.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_Redo;
end;

procedure TrvActionRedo.ExecuteTarget(Target: TObject);
begin
  GetControl(Target).Redo;
end;

procedure TrvActionRedo.UpdateTarget(Target: TObject);
var rve: TCustomRichViewEdit;
begin
  if not RVA_ActionsEnabled or Disabled then begin
    Enabled := False;
    exit;
  end;
  rve := GetControl(Target);
  Enabled := {not rve.ReadOnly and} (rve.RedoAction <> rvutNone);
end;

{ TrvActionCut }

constructor TrvActionCut.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_Cut;
end;

procedure TrvActionCut.ExecuteTarget(Target: TObject);
begin
  if IsDifferentEditor(Target) then
    RVA_EditorControlFunction(TControl(Target), rvaeccCut)
  else
    GetControl(Target).CutDef;
end;

{ TrvActionCopy }

constructor TrvActionCopy.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_Copy;
end;

procedure TrvActionCopy.ExecuteTarget(Target: TObject);
begin
  if IsDifferentEditor(Target) then
    RVA_EditorControlFunction(TControl(Target), rvaeccCopy)
  else
    GetControl(Target).CopyDef;
end;

{ TrvActionPaste }

{$IFDEF RVAHTML}
function TrvActionPaste.AllowPasteHTML: Boolean;
var mem: Cardinal;
begin
  Result := False;
  if not IsClipboardFormatAvailable(CFRV_HTML) then
    exit;
  if IsClipboardFormatAvailable(CFRV_RVF) then
    exit;
  Result := True;
  if IsClipboardFormatAvailable(CFRV_RTF) then begin
    OpenClipboard(0);
    try
      mem := GetClipboardData(CFRV_RTF);
      Result := GlobalSize(mem)=0;
    finally
      CloseClipboard;
    end;
  end;
end;
{$ENDIF}

constructor TrvActionPaste.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_Paste;
end;

procedure TrvActionPaste.ExecuteTarget(Target: TObject);
var rve: TCustomRichViewEdit;
    ImpPicAssigned: Boolean;
begin
  if IsDifferentEditor(Target) then
    RVA_EditorControlFunction(TControl(Target), rvaeccPaste)
  else begin
    rve := GetControl(Target);
    if RVA_UserInterface=rvauiText then begin
      if rve.Style.TextStyles[rve.CurTextStyleNo].Unicode then
        rve.PasteTextW
      else
       rve.PasteTextA;
      exit;
    end;
    ImpPicAssigned := Assigned(rve.OnImportPicture);
    if not ImpPicAssigned then begin
      RVA_Events.InitImportPictures(Self);
      rve.OnImportPicture := RVA_Events.DoImportPicture;
    end;
    try
      {$IFDEF RVAHTML}
      if {$IFDEF USERVHTMLVIEWER}(RVA_RVHTMLView<>nil)
         {$ELSE}{$IFDEF USERVHTML}(RVA_RVHTML<>nil){$ENDIF}{$ENDIF}
        and AllowPasteHTML then
        PasteHTML(GetControl(Target))
      else
      {$ENDIF}
        GetControl(Target).Paste;
    finally
      if not ImpPicAssigned then begin
        RVA_Events.DoneImportPictures;
        rve.OnImportPicture := nil;
      end;
    end;
  end;
end;

procedure TrvActionPaste.UpdateTarget(Target: TObject);
begin
  if IsDifferentEditor(Target) then
    Enabled := RVA_ActionsEnabled and not Disabled and RVA_EditorControlFunction(TControl(Target), rvaeccCanPaste)
  else
    if RVA_UserInterface=rvauiText then
      Enabled := RVA_ActionsEnabled and not Disabled and
        Clipboard.HasFormat(CF_TEXT)
    else
      Enabled := RVA_ActionsEnabled and not Disabled and
        GetControl(Target).CanPaste;
end;

{ TrvActionPasteAsText }

constructor TrvActionPasteAsText.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_PasteAsText;
end;

procedure TrvActionPasteAsText.ExecuteTarget(Target: TObject);
var rve: TCustomRichViewEdit;
begin
  if IsDifferentEditor(Target) then
    RVA_EditorControlFunction(TControl(Target), rvaeccPasteText)
  else begin
    rve := GetControl(Target);
    if rve.Style.TextStyles[rve.CurTextStyleNo].Unicode then
      rve.PasteTextW
    else
     rve.PasteTextA;
  end;
end;

procedure TrvActionPasteAsText.UpdateTarget(Target: TObject);
begin
  if IsDifferentEditor(Target) then
    Enabled := RVA_ActionsEnabled and not Disabled and
      RVA_EditorControlFunction(TControl(Target), rvaeccCanPasteText)
  else
    Enabled := RVA_ActionsEnabled and not Disabled and
      Clipboard.HasFormat(CF_TEXT);
end;

{ TrvActionPasteSpecial }

constructor TrvActionPasteSpecial.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_PasteSpecial;
end;

function TrvActionPasteSpecial.HandlesTarget(Target: TObject): Boolean;
begin
  if Control<>nil then
   Target := Control
  else if RVA_DefaultControl<>nil then
   Target := RVA_DefaultControl;
  Result := Target is TCustomRichViewEdit;
end;

procedure TrvActionPasteSpecial.UpdateTarget(Target: TObject);
var rve: TCustomRichViewEdit;
    CanPaste: Boolean;
begin
  if not RVA_ActionsEnabled or Disabled or (RVA_UserInterface=rvauiText) then begin
    Enabled := False;
    exit;
  end;
  rve := GetControl(Target);
  CanPaste := rve.CanPaste;
  if Assigned(OnCanPaste) then
    OnCanPaste(Self, CanPaste);
  Enabled := CanPaste;
end;

procedure TrvActionPasteSpecial.AddFormat(const FormatName: String; Format: Word);
begin
  if FListForm=nil then begin
    Beep;
    exit;
  end;
  TfrmRVList(FListForm).XBoxItemsAddObject(TfrmRVList(FListForm)._lst,
    FormatName, TObject(-Integer(Format)));
end;

procedure TrvActionPasteSpecial.ExecuteTarget(Target: TObject);
var frm: TfrmRVList;
    rve: TCustomRichViewEdit;
    ImpPicAssigned: Boolean;
    Format: Word;
begin
  rve := GetControl(Target);
  frm := TfrmRVList.Create(Application);
  try
    FListForm := frm;
    if RVA_RVFLocalizable then
      frm.InitPasteAs(RVA_GetS(rvam_RVF))
    else
      frm.InitPasteAs(RVA_RVFormatName);
    if Assigned(OnShowing) then
      OnShowing(Self);
    if (frm.GetXBoxItemCount(frm._lst)>0) and (frm.ShowModal=mrOk) then
      case Integer(frm.GetXBoxObject(frm._lst, frm.GetXBoxItemIndex(frm._lst))) of
        1: rve.PasteRVF;
        2:
          begin
            ImpPicAssigned := Assigned(rve.OnImportPicture);
            if not ImpPicAssigned then begin
              RVA_Events.InitImportPictures(Self);
              rve.OnImportPicture := RVA_Events.DoImportPicture;
            end;
            try
              rve.PasteRTF;
            finally
              if not ImpPicAssigned then begin
                rve.OnImportPicture := nil;
                RVA_Events.DoneImportPictures;
              end;
            end;
          end;
        3: rve.PasteTextA;
        4: rve.PasteTextW;
        5: rve.PasteBitmap(False);
        6: rve.PasteMetafile(False);
        {$IFDEF RVAHTML}
        7:
          begin
            ImpPicAssigned := Assigned(rve.OnImportPicture);
            if not ImpPicAssigned then begin
              RVA_Events.InitImportPictures(Self);
              rve.OnImportPicture := RVA_Events.DoImportPicture;
            end;
            try
              PasteHTML(rve);
            finally
              if not ImpPicAssigned then begin
                rve.OnImportPicture := nil;
                RVA_Events.DoneImportPictures;
              end;
            end;
          end;
        {$ENDIF}
        8: rve.PasteGraphicFiles(FStoreFileNameInItemName, FStoreFileName);
        else begin
          if Assigned(OnCustomPaste) then begin
            Format := Word(-Integer(
              frm.GetXBoxObject(frm._lst, frm.GetXBoxItemIndex(frm._lst))));
            OnCustomPaste(Self, rve, Format);
          end;
        end;
      end;
  finally
    FListForm := nil;
    frm.Free;
  end;
end;

{ TrvActionSelectAll }

constructor TrvActionSelectAll.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_SelectAll;
end;

procedure TrvActionSelectAll.ExecuteTarget(Target: TObject);
var rve: TCustomRichViewEdit;
begin
  rve := GetControl(Target);
  rve.SelectAll;
  rve.SetFocus;
  rve.Invalidate;
end;

{ TrvActionCharCase }

constructor TrvActionCharCase.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_CharCase;
end;

procedure TrvActionCharCase.ExecuteTarget(Target: TObject);
var AllUpperCase, AllLowerCase: Boolean;
   rve: TCustomRichViewEdit;
begin
  rve := GetControl(Target);
  RVGetCharCase(rve, AllUpperCase, AllLowerCase);
  if AllUpperCase and AllLowerCase then
    exit;
  if AllUpperCase then
    RVChangeCharCase(rve, rvccTitleWord)
  else if AllLowerCase then
    RVChangeCharCase(rve, rvccUpperCase)
  else
    RVChangeCharCase(rve, rvccLowerCase);
end;

procedure TrvActionCharCase.UpdateTarget(Target: TObject);
begin
  if not RVA_ActionsEnabled or Disabled then begin
    Enabled := False;
    exit;
  end;
  Enabled := GetControl(Target).SelectionExists;
end;

{---------------------------- Basic Color Action ------------------------------}

{ TrvActionCustomColor }

procedure TrvActionCustomColor.ColorPickerDestroy(Sender: TObject);
begin
  if TfrmColor(Sender).Chosen then begin
    Color := TfrmColor(Sender).ChosenColor;
    ExecuteCommand(FEdit, 0);
  end;
  FColorPicker := nil;
  if Assigned(FOnHideColorPicker) then
    FOnHideColorPicker(Self);
  {$IFDEF RICHVIEWDEF5}
  if FEdit <> nil then
    FEdit.RemoveFreeNotification(Self);
  {$ENDIF}
  FEdit := nil;
end;

constructor TrvActionCustomColor.Create(AOwner: TComponent);
begin
  inherited;
  Color := clNone;
  FDefaultColor := clNone;
  UserInterface := rvacAdvanced;
end;

destructor TrvActionCustomColor.Destroy;
begin
  if FColorPicker<>nil then
    FColorPicker.OnClose := nil;
  inherited;
end;

procedure TrvActionCustomColor.InitColorDialog(
  var AColorDialog: TColorDialog; var ACreated: Boolean);
begin
  ACreated := RVA_ColorDialog=nil;
  if RVA_ColorDialog<>nil then
    AColorDialog := RVA_ColorDialog
  else
    AColorDialog := TColorDialog.Create(nil);
end;

procedure TrvActionCustomColor.DoneColorDialog(AColorDialog: TColorDialog; ACreated: Boolean);
begin
  if ACreated then
    AColorDialog.Free;
end;

procedure TrvActionCustomColor.Notification(AComponent: TComponent;
  Operation: TOperation);
begin
  inherited;
  if (Operation=opRemove) then begin
    if (AComponent=FEdit) then
      FEdit := nil;
    if (AComponent=FCallerControl) then
      FCallerControl := nil;
  end;
end;

function TrvActionCustomColor.CanApplyToPlainText: Boolean;
begin
  Result := False;
end;

procedure TrvActionCustomColor.SetCallerControl(const Value: TControl);
begin
  if Value <> FCallerControl then
  begin
    {$IFDEF RICHVIEWDEF5}
    if FCallerControl <> nil then
      FCallerControl.RemoveFreeNotification(Self);
    {$ENDIF}
    FCallerControl := Value;
    if FCallerControl<> nil then
      FCallerControl.FreeNotification(Self);
  end;
end;

procedure TrvActionCustomColor.ExecuteTarget(Target: TObject);
var  r: TRect;
     AColorDialog: TColorDialog;
     ACreated: Boolean;
     AColor: TColor;
     Caller: TControl;
     {.................................................}
     function GetCaller: TControl;
     begin
       {$IFDEF RICHVIEWDEF6}
       if (ActionComponent<>nil) and (ActionComponent is TControl) then
         Result := TControl(ActionComponent)
       else
         Result := nil;
       {$ELSE}
       Result := CallerControl;
       {$ENDIF}
     end;
     {.................................................}
begin
  if FColorPicker<>nil then begin
    FColorPicker.Close;
    exit;
  end;
  case UserInterface of
    rvacAdvanced:
      begin
        FEdit := GetControl(Target);
        FEdit.FreeNotification(Self);
        AColor := GetCurrentColor(FEdit);
        FColorPicker := TfrmColor.Create(FEdit.Owner);
        FColorPicker.OnDestroy := ColorPickerDestroy;
        TfrmColor(FColorPicker).Init(FDefaultColor, RVA_ColorDialog, AColor);
        if Assigned(FOnShowColorPicker) then
          FOnShowColorPicker(Self);
        Caller := GetCaller;
        if Caller<>nil then begin
          r := Rect(0,0, Caller.Width, Caller.Height);
          r.TopLeft := Caller.ClientToScreen(r.TopLeft);
          r.BottomRight := Caller.ClientToScreen(r.BottomRight);
          TfrmColor(FColorPicker).PopupAt(r);
          end
        else
          TfrmColor(FColorPicker).PopupAtMouse;
      end;
    rvacColorDialog:
      begin
        AColor := GetCurrentColor(GetControl(Target));
        InitColorDialog(AColorDialog,ACreated);
        if AColor=clNone then
          AColorDialog.Color := clYellow
        else
          AColorDialog.Color := AColor;
        if Assigned(FOnShowColorPicker) then
          FOnShowColorPicker(Self);
        if AColorDialog.Execute then begin
          Color := AColorDialog.Color;
          ExecuteCommand(GetControl(Target), 0);
        end;
        if Assigned(FOnHideColorPicker) then
          FOnHideColorPicker(Self);
        DoneColorDialog(AColorDialog,ACreated);
      end;
    rvacNone:
      ExecuteCommand(GetControl(Target), 0);
  end;
end;

function TrvActionCustomColor.GetColorName: String;
begin
  Result := RVA_GetColorName(Color);
end;

procedure TrvActionCustomColor.Localize;
begin
  if FMessageID<>rvam_Empty then begin
    Caption := RVA_GetS(FMessageID);
    if RVA_AddColorNameToHints and (UserInterface=rvacNone) then
      Hint := GetShortHint(RVA_GetS(succ(FMessageID)))+' ('+GetColorName+')|'+
        GetLongHint(RVA_GetS(succ(FMessageID)))
    else
      Hint := RVA_GetS(succ(FMessageID));
  end;
end;

procedure TrvActionCustomColor.SetColor(const Value: TColor);
begin
  FColor := Value;
  if RVA_AddColorNameToHints then
    Localize;
end;

{---------------------------- Text Styles -------------------------------------}


{ TrvActionTextStyles }

procedure TrvActionTextStyles.ExecuteCommand(rve: TCustomRichViewEdit;
  Command: Integer);
var FOldOnStyleConversion: TRVStyleConversionEvent;
begin
  FOldOnStyleConversion := rve.OnStyleConversion;
  SetStyleConversionEvent(rve, NewOnStyleConversion);
  try
    rve.ApplyStyleConversion(Command, IsRecursive);
  finally
    SetStyleConversionEvent(rve, FOldOnStyleConversion);
  end;
end;

function TrvActionTextStyles.IsRecursive: Boolean;
begin
  Result := True;
end;

function TrvActionTextStyles.CanApplyToPlainText: Boolean;
begin
  Result := False;
end;

procedure TrvActionTextStyles.ExecuteTarget(Target: TObject);
begin
  ExecuteCommand(GetControl(Target), 0);
end;

procedure TrvActionTextStyles.NewOnStyleConversion(
  Sender: TCustomRichViewEdit; StyleNo, UserData: Integer;
  AppliedToText: Boolean; var NewStyleNo: Integer);
var
  FontInfo: TFontInfo;
begin
  if AppliedToText and (rvprStyleProtect in Sender.Style.TextStyles[StyleNo].Protection) then
    exit;
  if not AppliedToText and
    ((rvprStyleProtect in Sender.Style.TextStyles[StyleNo].Protection) or
     (rvprDoNotAutoSwitch in Sender.Style.TextStyles[StyleNo].Protection)) then
    exit;
  FontInfo := TFontInfo.Create(nil);
  try
    FontInfo.Assign(Sender.Style.TextStyles[StyleNo]);
    ApplyConversion(Sender, FontInfo, StyleNo, UserData);
    NewStyleNo := RVA_Events.DoStyleNeeded(Self, Sender.Style, FontInfo);
    if NewStyleNo<0 then begin
      NewStyleNo := Sender.Style.TextStyles.FindSuchStyle(StyleNo, FontInfo, RVAllFontInfoProperties);
      if NewStyleNo<0 then begin
        Sender.Style.TextStyles.Add;
        NewStyleNo := Sender.Style.TextStyles.Count - 1;
        Sender.Style.TextStyles[NewStyleNo].Assign(FontInfo);
        Sender.Style.TextStyles[NewStyleNo].Standard := False;
        RVA_Events.DoOnAddStyle(Self, Sender.Style.TextStyles[NewStyleNo]);
      end;
    end;
  finally
    FontInfo.Free;
  end;
end;

{ TrvActionFontCustomColor }
// Unfortunately, it is impossible to inherit this action from TrvActionTextStyles,
// so it duplicates methods of TrvActionTextStyles

procedure TrvActionFontCustomColor.ExecuteCommand(rve: TCustomRichViewEdit;
  Command: Integer);
var FOldOnStyleConversion: TRVStyleConversionEvent;
begin
  FOldOnStyleConversion := rve.OnStyleConversion;
  SetStyleConversionEvent(rve, NewOnStyleConversion);
  try
    rve.ApplyStyleConversion(Command);
  finally
    SetStyleConversionEvent(rve, FOldOnStyleConversion);
  end;
end;

procedure TrvActionFontCustomColor.NewOnStyleConversion(
  Sender: TCustomRichViewEdit; StyleNo, UserData: Integer;
  AppliedToText: Boolean; var NewStyleNo: Integer);
var
  FontInfo: TFontInfo;
begin
  if AppliedToText and (rvprStyleProtect in Sender.Style.TextStyles[StyleNo].Protection) then
    exit;
  if not AppliedToText and
    ((rvprStyleProtect in Sender.Style.TextStyles[StyleNo].Protection) or
     (rvprDoNotAutoSwitch in Sender.Style.TextStyles[StyleNo].Protection)) then
    exit;
  FontInfo := TFontInfo.Create(nil);
  try
    FontInfo.Assign(Sender.Style.TextStyles[StyleNo]);
    ApplyConversion(Sender, FontInfo, StyleNo, UserData);
    NewStyleNo := RVA_Events.DoStyleNeeded(Self, Sender.Style, FontInfo);
    if NewStyleNo<0 then begin
      NewStyleNo := Sender.Style.TextStyles.FindSuchStyle(StyleNo, FontInfo, RVAllFontInfoProperties);
      if NewStyleNo<0 then begin
        Sender.Style.TextStyles.Add;
        NewStyleNo := Sender.Style.TextStyles.Count - 1;
        Sender.Style.TextStyles[NewStyleNo].Assign(FontInfo);
        Sender.Style.TextStyles[NewStyleNo].Standard := False;
        RVA_Events.DoOnAddStyle(Self, Sender.Style.TextStyles[NewStyleNo]);
      end;
    end;
  finally
    FontInfo.Free;
  end;
end;

{ TRVActionFontColor }

constructor TrvActionFontColor.Create(AOwner: TComponent);
begin
  inherited;
  FColor := clWindowText;
  FDefaultColor := clWindowText;
  FMessageID := rvam_act_TextColor;
end;

procedure TRVActionFontColor.ApplyConversion(Editor: TCustomRichViewEdit;
  FontInfo: TFontInfo; StyleNo, Command: Integer);
begin
  FontInfo.Color := Color;
end;

function TrvActionFontColor.GetCurrentColor(
  FEdit: TCustomRichViewEdit): TColor;
begin
  Result := FEdit.Style.TextStyles[FEdit.CurTextStyleNo].Color;
end;

{ TRVActionFontBackColor }

procedure TRVActionFontBackColor.ApplyConversion(Editor: TCustomRichViewEdit;
  FontInfo: TFontInfo; StyleNo, Command: Integer);
begin
  if FontInfo.Jump and (FontInfo.BackColor=FontInfo.HoverBackColor) then
    FontInfo.HoverBackColor := Color;
  FontInfo.BackColor := Color;
end;

constructor TrvActionFontBackColor.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_TextBackColor;
end;

function TrvActionFontBackColor.GetCurrentColor(
  FEdit: TCustomRichViewEdit): TColor;
begin
  Result := FEdit.Style.TextStyles[FEdit.CurTextStyleNo].BackColor;
end;

{ TrvActionFonts }
constructor TrvActionFonts.Create(AOwner: TComponent);
begin
  inherited;
  FFont := TFont.Create;
  FUserInterface := True;
  FMessageID := rvam_act_Font;
end;

destructor TrvActionFonts.Destroy;
begin
  FFont.Free;
  inherited;
end;

procedure TrvActionFonts.ApplyConversion(Editor: TCustomRichViewEdit;
  FontInfo: TFontInfo; StyleNo, Command: Integer);
begin
  FontInfo.Assign(FFont);
end;

function TrvActionFonts.CanApplyToPlainText: Boolean;
begin
  Result := False;
end;

procedure TrvActionFonts.ExecuteTarget(Target: TObject);
begin
  if not FUserInterface then begin
    ExecuteCommand(GetControl(Target), 0);
    exit;
  end;
  with TFontDialog.Create(Application) do
  try
    Self.Font.Assign(GetControl(Target).Style.TextStyles[GetControl(Target).CurTextStyleNo]);
    Font.Assign(Self.Font);
    if Execute then begin
      Self.Font.Assign(Font);
      ExecuteCommand(GetControl(Target), 0);
    end;
  finally
    Free;
  end;
end;

procedure TrvActionFonts.SetFont(const Value: TFont);
begin
  FFont.Assign(Value);
end;

{ TrvActionFontEx }

constructor TrvActionFontEx.Create(AOwner: TComponent);
begin
  inherited;
  CharScale := 100;
  FUnderlineColor := clNone;
  FAutoApplySymbolCharset := True;
end;

procedure TrvActionFontEx.ExecuteTarget(Target: TObject);
  {.......................................................}
  procedure SetCB(Prop: TRVFontInfoMainProperty; Checked: Boolean; cb: TControl;
    frm: TfrmRVFont);
  begin
    if Prop in ValidProperties then
      frm.SetCheckBoxChecked(cb, Checked)
    else
      frm.SetCheckBoxState(cb, cbGrayed);
  end;

  procedure SetToForm(frm: TfrmRVFont; rve: TCustomRichViewEdit);
  begin
    frm.rvs.Units := rve.Style.Units;

    SetCB(rvfimBold, fsBold in Font.Style, frm._cbB, frm);
    SetCB(rvfimItalic, fsItalic in Font.Style, frm._cbI, frm);
    SetCB(rvfimStrikeOut, fsStrikeOut in Font.Style, frm._cbS, frm);
    SetCB(rvfimOverline, rvfsOverline in FontStyleEx, frm._cbO, frm);
    SetCB(rvfimAllCaps, rvfsAllCaps in FontStyleEx, frm._cbAC, frm);

    if rvfimUnderline in ValidProperties then
      if fsUnderline in Font.Style then begin
          if rvfimUnderlineType in ValidProperties then
            frm.SetXBoxItemIndex(frm._cmbUnderline, ord(UnderlineType)+1)
        end
      else begin
        frm.SetXBoxItemIndex(frm._cmbUnderline, 0);
        frm.cmbUnderlineColor.Enabled := False;
      end;
    if (rvfimUnderlineColor in ValidProperties) then
      if not frm.cmbUnderlineColor.Enabled then
        frm.cmbUnderlineColor.Indeterminate := True
      else
        frm.cmbUnderlineColor.ChosenColor := UnderlineColor;

    if rvfimFontName in ValidProperties then
      frm.cmbFont.Text := Font.Name
    else
      frm.cmbFont.Text := '';
    if rvfimColor in ValidProperties then
      frm.cmbColor.ChosenColor := Font.Color;
    frm.cmbFont.ItemIndex := frm.cmbFont.Items.IndexOf(frm.cmbFont.Text);
    frm.cmbFontClick(nil);
    if rvfimSize in ValidProperties then
      frm.cmbSize.Text := IntToStr(Font.Size)
    else
      frm.cmbSize.Text := '';
    if rvfimCharset in ValidProperties then
      frm.cmbCharset.ItemIndex := frm.cmbCharset.IndexOfCharset(Font.Charset)
    else
      frm.cmbCharset.ItemIndex := -1;
    if rvfimCharSpacing in ValidProperties then
      if CharSpacing>=0 then begin
        frm.seSpacing.Value := rve.Style.GetAsRVUnits(CharSpacing, RVA_GetFineUnits);
        frm.rbExp.Checked := True;
        end
      else begin
        frm.seSpacing.Value := rve.Style.GetAsRVUnits(-CharSpacing, RVA_GetFineUnits);
        frm.rbCond.Checked := True;      
      end;
    if rvfimCharScale in ValidProperties then
      frm.seCharScale.Value := CharScale;
    if rvfimVShift  in ValidProperties then begin
      if VShift<0 then
        frm.rbDown.Checked := True
      else if VShift>0 then
        frm.rbUp.Checked := True;
      frm.seShift.Value := abs(VShift);
    end;
    if rvfimSubSuperScriptType in ValidProperties then
      case SubSuperScriptType of
        rvsssNormal:
          frm.rbNormal.Checked := True;
        rvsssSubscript:
          frm.rbSub.Checked := True;
        rvsssSuperScript:
          frm.rbSuper.Checked := True;
      end;
  end;
  {.......................................................}
  procedure GetCB(Prop: TRVFontInfoMainProperty; cb: TControl;
    var Style: TFontStyles; OneStyle: TFontStyle;
    frm: TfrmRVFont);
  begin
    if frm.GetCheckBoxState(cb)<>cbGrayed then begin
      ValidProperties := ValidProperties+[Prop];
      if frm.GetCheckBoxChecked(cb) then
        Style := Style+[OneStyle];
    end;
  end;

  procedure GetCB2(Prop: TRVFontInfoMainProperty; cb: TControl;
    var Style: TRVFontStyles; OneStyle: TRVFontStyle;
    frm: TfrmRVFont);
  begin
    if frm.GetCheckBoxState(cb)<>cbGrayed then begin
      ValidProperties := ValidProperties+[Prop];
      if frm.GetCheckBoxChecked(cb) then
        Style := Style+[OneStyle];
    end;
  end;

  procedure GetFromForm(frm: TfrmRVFont);
  var AStyle: TFontStyles;
      AStyleEx: TRVFontStyles;
  begin
    ValidProperties := [];
    AStyle := [];
    AStyleEx := [];
    GetCB(rvfimBold,      frm._cbB, AStyle, fsBold, frm);
    GetCB(rvfimItalic,    frm._cbI, AStyle, fsItalic, frm);
    GetCB(rvfimStrikeOut, frm._cbS, AStyle, fsStrikeOut, frm);
    GetCB2(rvfimOverline, frm._cbO, AStyleEx, rvfsOverline, frm);
    GetCB2(rvfimAllCaps,  frm._cbAC, AStyleEx, rvfsAllCaps, frm);
    if frm.GetXBoxItemIndex(frm._cmbUnderline)>=0 then begin
      Include(FValidProperties, rvfimUnderline);
      if frm.GetXBoxItemIndex(frm._cmbUnderline)>0 then begin
        Include(AStyle, fsUnderline);
        Include(FValidProperties, rvfimUnderlineType);
        UnderlineType := TRVUnderlineType(frm.GetXBoxItemIndex(frm._cmbUnderline)-1);
      end;
    end;
    if frm.cmbUnderlineColor.Enabled and not frm.cmbUnderlineColor.Indeterminate then begin
      Include(FValidProperties, rvfimUnderlineColor);
      UnderlineColor := frm.cmbUnderlineColor.ChosenColor;
    end;

    Font.Style := AStyle;
    FontStyleEx := AStyleEx;
    if frm.cmbFont.Text<>'' then begin
      Include(FValidProperties, rvfimFontName);
      Font.Name := frm.cmbFont.Text;
    end;
    if frm.cmbSize.Text<>'' then begin
      Include(FValidProperties, rvfimSize);
      Font.Size := StrToIntDef(frm.cmbSize.Text, 10);
    end;
    if frm.cmbCharset.ItemIndex>=0 then begin
      Include(FValidProperties, rvfimCharset);
      Font.Charset := frm.cmbCharset.Charsets[frm.cmbCharset.ItemIndex];
    end;
    if not frm.seSpacing.Indeterminate then begin
      Include(FValidProperties, rvfimCharSpacing);
      if frm.rbCond.Checked then
        CharSpacing := -frm.rvs.RVUnitsToUnits(frm.seSpacing.Value, RVA_GetFineUnits)
      else
        CharSpacing := frm.rvs.RVUnitsToUnits(frm.seSpacing.Value, RVA_GetFineUnits);
    end;
    if not frm.seCharScale.Indeterminate then begin
      Include(FValidProperties, rvfimCharScale);
      CharScale := frm.seCharScale.AsInteger;
    end;
    if not frm.seShift.Indeterminate then begin
      Include(FValidProperties, rvfimVShift);
      if frm.rbUp.Checked then
        VShift := frm.seShift.AsInteger
      else
        VShift := -frm.seShift.AsInteger;
    end;
    if not frm.cmbColor.Indeterminate then begin
      Font.Color := frm.cmbColor.ChosenColor;
      Include(FValidProperties, rvfimColor);
    end;

    Include(FValidProperties, rvfimSubSuperScriptType);
    if frm.rbNormal.Checked then
      SubSuperScriptType := rvsssNormal
    else if frm.rbSuper.Checked then
      SubSuperScriptType := rvsssSuperscript
    else if frm.rbSub.Checked then
      SubSuperScriptType := rvsssSubscript
    else
      Exclude(FValidProperties, rvfimSubSuperScriptType);

    if RVA_UserInterface=rvauiHTML then begin
      Include(FValidProperties, rvfimVShift);
      VShift := 0;
      Include(FValidProperties, rvfimCharScale);
      CharScale := 0;
    end;
  end;
  {.......................................................}
var frm: TfrmRVFont;
    rve: TCustomRichViewEdit;
    s: WideString;
    p: Integer;
begin
  rve := GetControl(Target);
  if not UserInterface then begin
    AdjustCharset;  
    ExecuteCommand(rve, 0);
    exit;
  end;
  GetFromEditor(rve);
  AdjustCharset;  
  frm := TfrmRVFont.Create(Application);
  try
    frm.ColorDialog := RVA_ColorDialog;
    SetToForm(frm, rve);
    s := rve.GetSelTextW;
    p := pos(#13,s);
    if p>0 then
      s := Copy(s,1,p-1);
    frm.PreviewString := s;
    if frm.ShowModal=mrOk then begin
      GetFromForm(frm);
      ExecuteCommand(rve, 0);
    end;
  finally
    frm.Free;
  end;
end;

function EnumFontCharsetsSym(var EnumLogFont: TEnumLogFontEx; 
  PTextMetric: PNewTextMetricEx; FontType: Integer; Data: LPARAM): Integer; 
  export; stdcall; 
begin 
  Result := 1; 
  if EnumLogFont.elfLogFont.lfCharSet=SYMBOL_CHARSET then begin
    PInteger(Data)^ := 1; 
    Result := 0; 
  end; 
end; 

function IsSymbolFont(const FontName: String): Boolean;
var Res: Integer;
    DC: HDC;
    lf: TLogFont;
begin
  Res := 0;
  DC := GetDC(0);
  try
    FillChar(lf, sizeof(lf), 0);
    lf.lfCharset  := SYMBOL_CHARSET;
    Move(PChar(FontName)^, lf.lfFaceName, Length(FontName));
    EnumFontFamiliesEx(DC, lf, @EnumFontCharsetsSym, LongInt(@Res), 0);
    Result := Res<>0;
  finally
    ReleaseDC(0, DC);
  end;
end;

procedure TrvActionFontEx.AdjustCharset;
begin
  if not AutoApplySymbolCharset or
    (rvfimCharset in ValidProperties) or
    (Font.Name='') or not (rvfimFontName in ValidProperties) then
    exit;
  if IsSymbolFont(Font.Name) then begin
    ValidProperties := ValidProperties+[rvfimCharset];
    Font.Charset := SYMBOL_CHARSET;
  end;
end;

procedure TrvActionFontEx.ApplyConversion(Editor: TCustomRichViewEdit;
  FontInfo: TFontInfo; StyleNo, Command: Integer);
begin
  if rvfimFontName in ValidProperties then
    FontInfo.FontName := Font.Name;
  if rvfimSize in ValidProperties then
    FontInfo.Size := Font.Size;
  if rvfimCharset in ValidProperties then
    FontInfo.Charset := Font.Charset;
  if rvfimColor in ValidProperties then
    FontInfo.Color := Font.Color;
  if rvfimBold in ValidProperties then
    if fsBold in Font.Style then
      FontInfo.Style := FontInfo.Style+[fsBold]
    else
      FontInfo.Style := FontInfo.Style-[fsBold];
  if rvfimItalic in ValidProperties then
    if fsItalic in Font.Style then
      FontInfo.Style := FontInfo.Style+[fsItalic]
    else
      FontInfo.Style := FontInfo.Style-[fsItalic];
  if rvfimUnderline in ValidProperties then
    if fsUnderline in Font.Style then
      FontInfo.Style := FontInfo.Style+[fsUnderline]
    else
      FontInfo.Style := FontInfo.Style-[fsUnderline];
  if (rvfimUnderlineType in ValidProperties) and (fsUnderline in FontInfo.Style) then
    FontInfo.UnderlineType := UnderlineType;
  if (rvfimUnderlineColor in ValidProperties) and (fsUnderline in FontInfo.Style) then
    FontInfo.UnderlineColor := UnderlineColor;


  if rvfimStrikeOut in ValidProperties then
    if fsStrikeOut in Font.Style then
      FontInfo.Style := FontInfo.Style+[fsStrikeOut]
    else
      FontInfo.Style := FontInfo.Style-[fsStrikeOut];
  if rvfimOverline in ValidProperties then
    if rvfsOverline in FontStyleEx then
      FontInfo.StyleEx := FontInfo.StyleEx+[rvfsOverline]
    else
      FontInfo.StyleEx := FontInfo.StyleEx-[rvfsOverline];
  if rvfimAllCaps in ValidProperties then
    if rvfsAllCaps in FontStyleEx then
      FontInfo.StyleEx := FontInfo.StyleEx+[rvfsAllCaps]
    else
      FontInfo.StyleEx := FontInfo.StyleEx-[rvfsAllCaps];
  if rvfimVShift in ValidProperties then
    FontInfo.VShift := VShift;
  if rvfimCharScale in ValidProperties then
    FontInfo.CharScale := CharScale;
  if rvfimCharSpacing in ValidProperties then
    FontInfo.CharSpacing := CharSpacing;
  if rvfimSubSuperScriptType in ValidProperties then
    FontInfo.SubSuperScriptType := SubSuperScriptType;  
end;

function TrvActionFontEx.ContinueIteration(var CustomData: Integer): Boolean;
begin
  Result := ValidProperties<>[];
end;

function TrvActionFontEx.CanApplyToPlainText: Boolean;
begin
  Result := False;
end;

procedure TrvActionFontEx.IterateProc(RVData: TCustomRVData; ItemNo: Integer;
  rve: TCustomRichViewEdit; var CustomData: Integer);
var StyleNo: Integer;
    FontInfo: TFontInfo;
    item: TCustomRVItemInfo;
begin
  item := RVData.GetItem(ItemNo);
  if item.StyleNo<0 then
    exit;
  StyleNo := item.StyleNo;
  if StyleNo=CustomData then
    exit;
  FontInfo   := rve.Style.TextStyles[StyleNo];
  if CustomData=-1 then begin
    Font.Assign(FontInfo);
    FontStyleEx := FontInfo.StyleEx;
    VShift  := FontInfo.VShift;
    CharScale := FontInfo.CharScale;
    CharSpacing := FontInfo.CharSpacing;
    SubSuperScriptType := FontInfo.SubSuperScriptType;
    UnderlineType := FontInfo.UnderlineType;
    UnderlineColor := FontInfo.UnderlineColor;
    end
  else begin
    if AnsiCompareText(Font.Name, FontInfo.FontName)<>0 then
       Exclude(FValidProperties, rvfimFontName);
    if Font.Size<>FontInfo.Size then
       Exclude(FValidProperties, rvfimSize);
    if Font.Charset<>FontInfo.Charset then
       Exclude(FValidProperties, rvfimCharset);
    if Font.Color<>FontInfo.Color then
       Exclude(FValidProperties, rvfimColor);
    if (fsBold in Font.Style)<>(fsBold in FontInfo.Style) then
       Exclude(FValidProperties, rvfimBold);
    if (fsItalic in Font.Style)<>(fsItalic in FontInfo.Style) then
       Exclude(FValidProperties, rvfimItalic);
    if (fsUnderline in Font.Style)<>(fsUnderline in FontInfo.Style) then
       Exclude(FValidProperties, rvfimUnderline);
    if fsUnderline in FontInfo.Style then begin
      if UnderlineType<>FontInfo.UnderlineType then
        Exclude(FValidProperties, rvfimUnderlineType);
      if UnderlineColor<>FontInfo.UnderlineColor then
         Exclude(FValidProperties, rvfimUnderlineColor);
    end;
    if (fsStrikeOut in Font.Style)<>(fsStrikeOut in FontInfo.Style) then
       Exclude(FValidProperties, rvfimStrikeOut);
    if (rvfsOverline in FontStyleEx)<>(rvfsOverline in FontInfo.StyleEx) then
       Exclude(FValidProperties, rvfimOverline);
    if (rvfsAllCaps in FontStyleEx)<>(rvfsAllCaps in FontInfo.StyleEx) then
       Exclude(FValidProperties, rvfimAllCaps);
    if VShift<>FontInfo.VShift then
       Exclude(FValidProperties, rvfimVShift);
    if CharScale<>FontInfo.CharScale then
       Exclude(FValidProperties, rvfimCharScale);
    if CharSpacing<>FontInfo.CharSpacing then
       Exclude(FValidProperties, rvfimCharSpacing);
    if SubSuperScriptType<>FontInfo.SubSuperScriptType then
       Exclude(FValidProperties, rvfimSubSuperScriptType);    
  end;
  CustomData := StyleNo;
end;

procedure TrvActionFontEx.GetFromEditor(rve: TCustomRichViewEdit);
var StartNo, EndNo: Integer;
    StyleNo: Integer;
begin
   rve := rve.TopLevelEditor;
   ValidProperties := [Low(TRVFontInfoMainProperty)..High(TRVFontInfoMainProperty)];
   GetSelectionBounds(rve, StartNo, EndNo);
   StyleNo := -1;
   IterateRVData(rve.RVData, rve, StartNo, EndNo, StyleNo);
end;


{ TrvActionFontStyle }

procedure TrvActionFontStyle.UpdateTarget(Target: TObject);
var rve: TCustomRichViewEdit;
    Chk: Integer;
begin
  try
    rve := GetControl(Target);
    Enabled := RVA_ActionsEnabled and not Disabled and Assigned(rve.Style) and
      (RVA_UserInterface<>rvauiText);
    if not Enabled then begin
      Checked := False;
      exit;
    end;
    rve := rve.TopLevelEditor;
    if rve.RVData.PartialSelectedItem=nil then begin
      Checked := (FFontStyle in rve.Style.TextStyles[rve.CurTextStyleNo].Style) and
        AdditionalCheckCondition(rve.Style.TextStyles[rve.CurTextStyleNo]);
      exit;
    end;
    Chk := 1;
    if IterateRVData(rve.RVData, rve, -1, -1, Chk) then
      Checked := Chk<>0
    else begin
      Checked := False;
    end;
  except
    Enabled := False;
  end;
end;

function TrvActionFontStyle.AdditionalCheckCondition(TextStyle: TFontInfo): Boolean;
begin
  Result := True;
end;

procedure TrvActionFontStyle.ApplyConversion(Editor: TCustomRichViewEdit;
  FontInfo: TFontInfo; StyleNo, Command: Integer);
begin
  if Checked then
    FontInfo.Style := FontInfo.Style - [FFontStyle]
  else
    FontInfo.Style := FontInfo.Style + [FFontStyle];
end;

function TrvActionFontStyle.ContinueIteration(
  var CustomData: Integer): Boolean;
begin
  Result := CustomData<>0;
end;

procedure TrvActionFontStyle.IterateProc(RVData: TCustomRVData;
  ItemNo: Integer; rve: TCustomRichViewEdit; var CustomData: Integer);
begin
  if (RVData.GetItemStyle(ItemNo)>=0) and
     (not (FFontStyle in rve.Style.TextStyles[RVData.GetItemStyle(ItemNo)].Style) or
     not AdditionalCheckCondition(rve.Style.TextStyles[RVData.GetItemStyle(ItemNo)])) then
    CustomData := 0;
end;

{ TrvActionFontBold }

constructor TrvActionFontBold.Create(AOwner: TComponent);
begin
  inherited;
  FFontStyle := fsBold;
  FMessageID := rvam_act_Bold;
end;

{ TrvActionFontItalic }

constructor TrvActionFontItalic.Create(AOwner: TComponent);
begin
  inherited;
  FFontStyle := fsItalic;
  FMessageID := rvam_act_Italic;
end;

{ TrvActionFontUnderline }

constructor TrvActionFontUnderline.Create(AOwner: TComponent);
begin
  inherited;
  FFontStyle := fsUnderline;
  FMessageID := rvam_act_Underline;
end;

procedure TrvActionFontUnderline.ApplyConversion(
  Editor: TCustomRichViewEdit; FontInfo: TFontInfo; StyleNo,
  Command: Integer);
begin
  inherited;
  if not Checked then
    FontInfo.UnderlineType := rvutNormal;
end;


function TrvActionFontUnderline.AdditionalCheckCondition(TextStyle: TFontInfo): Boolean;
begin
  Result := TextStyle.UnderlineType=rvutNormal;
end;


{ TrvActionFontStrikeout }

constructor TrvActionFontStrikeout.Create(AOwner: TComponent);
begin
  inherited;
  FFontStyle := fsStrikeout;
  FMessageID := rvam_act_StrikeOut;
end;

{ TrvActionFontStyleEx }

procedure TrvActionFontStyleEx.ApplyConversion(Editor: TCustomRichViewEdit;
  FontInfo: TFontInfo; StyleNo, Command: Integer);
begin
  if Checked then
    FontInfo.StyleEx := FontInfo.StyleEx - [FFontStyleEx]
  else
    FontInfo.StyleEx := FontInfo.StyleEx + [FFontStyleEx];
end;

function TrvActionFontStyleEx.ContinueIteration(
  var CustomData: Integer): Boolean;
begin
  Result := CustomData<>0;
end;

procedure TrvActionFontStyleEx.IterateProc(RVData: TCustomRVData;
  ItemNo: Integer; rve: TCustomRichViewEdit; var CustomData: Integer);
begin
  if (RVData.GetItemStyle(ItemNo)>=0) and
     not (FFontStyleEx in rve.Style.TextStyles[RVData.GetItemStyle(ItemNo)].StyleEx) then
    CustomData := 0;
end;

procedure TrvActionFontStyleEx.UpdateTarget(Target: TObject);
var rve: TCustomRichViewEdit;
    Chk: Integer;
begin
  try
    rve := GetControl(Target);
    Enabled := RVA_ActionsEnabled and not Disabled and Assigned(rve.Style) and
      (RVA_UserInterface<>rvauiText);
    if not Enabled then begin
      Checked := False;
      exit;
    end;
    rve := rve.TopLevelEditor;
    if rve.RVData.PartialSelectedItem=nil then begin
      Checked := (FFontStyleEx in rve.Style.TextStyles[rve.CurTextStyleNo].StyleEx);
      exit;
    end;
    Chk := 1;
    if IterateRVData(rve.RVData, rve, -1, -1, Chk) then
      Checked := Chk<>0
    else
      Checked := False;
  except
    Enabled := False;
  end;
end;

{ TrvActionFontAllCaps }

constructor TrvActionFontAllCaps.Create(AOwner: TComponent);
begin
  inherited;
  FFontStyleEx := rvfsAllCaps;
  FMessageID := rvam_act_AllCaps;
end;

{ TrvActionFontOverline }

constructor TrvActionFontOverline.Create(AOwner: TComponent);
begin
  inherited;
  FFontStyleEx := rvfsOverline;
  FMessageID := rvam_act_Overline;
end;

{ TrvActionSubscript }

procedure TrvActionSSScript.ApplyConversion(Editor: TCustomRichViewEdit;
  FontInfo: TFontInfo; StyleNo, Command: Integer);
begin
  if Checked then
    FontInfo.SubSuperScriptType := rvsssNormal
  else
    FontInfo.SubSuperScriptType := FSubSuperSctiptType;
end;

function TrvActionSSScript.ContinueIteration(
  var CustomData: Integer): Boolean;
begin
  Result := CustomData<>0;
end;

procedure TrvActionSSScript.IterateProc(RVData: TCustomRVData;
  ItemNo: Integer; rve: TCustomRichViewEdit; var CustomData: Integer);
begin
  if (RVData.GetItemStyle(ItemNo)>=0) and
     (rve.Style.TextStyles[RVData.GetItemStyle(ItemNo)].SubSuperScriptType<>FSubSuperSctiptType) then
    CustomData := 0;
end;

procedure TrvActionSSScript.UpdateTarget(Target: TObject);
var rve: TCustomRichViewEdit;
    Chk: Integer;
begin
  try
    rve := GetControl(Target);
    Enabled := RVA_ActionsEnabled and not Disabled and Assigned(rve.Style) and
      (RVA_UserInterface<>rvauiText);
    if not Enabled then begin
      Checked := False;
      exit;
    end;
    rve := rve.TopLevelEditor;
    rve := rve.TopLevelEditor;
    if rve.RVData.PartialSelectedItem=nil then begin
      Checked :=
        (rve.Style.TextStyles[rve.CurTextStyleNo].SubSuperScriptType=FSubSuperSctiptType);
      exit;
    end;
    Chk := 1;
    if IterateRVData(rve.RVData, rve, -1, -1, Chk) then
      Checked := Chk<>0
    else
      Checked := False;
  except
    Enabled := False;
  end;
end;

{ TrvActionSubscript }

constructor TrvActionSubscript.Create(AOwner: TComponent);
begin
  inherited;
  FSubSuperSctiptType := rvsssSubscript;
  FMessageID := rvam_act_Subscript;
end;

{ TrvActionSuperscript }

constructor TrvActionSuperscript.Create(AOwner: TComponent);
begin
  inherited;
  FSubSuperSctiptType := rvsssSuperscript;
  FMessageID := rvam_act_Superscript;
end;

{ TrvActionTextBiDi }

procedure TrvActionTextBiDi.ApplyConversion(Editor: TCustomRichViewEdit;
  FontInfo: TFontInfo; StyleNo, Command: Integer);
begin
  FontInfo.BiDiMode := FBiDiMode;
end;

function TrvActionTextBiDi.ContinueIteration(var CustomData: Integer): Boolean;
begin
  Result := CustomData<>0;
end;

procedure TrvActionTextBiDi.IterateProc(RVData: TCustomRVData;
  ItemNo: Integer; rve: TCustomRichViewEdit; var CustomData: Integer);
begin
  if (RVData.GetItemStyle(ItemNo)>=0) and
     (FBiDiMode <> rve.Style.TextStyles[RVData.GetItemStyle(ItemNo)].BiDiMode) then
    CustomData := 0;
end;

procedure TrvActionTextBiDi.UpdateTarget(Target: TObject);
var rve: TCustomRichViewEdit;
    Chk: Integer;
begin
  try
    rve := GetControl(Target);
    Enabled := RVA_ActionsEnabled and not Disabled and Assigned(rve.Style) and
      (RVA_UserInterface<>rvauiText);
    if not Enabled then begin
      Checked := False;
      exit;
    end;
    rve := rve.TopLevelEditor;
    if rve.RVData.PartialSelectedItem=nil then begin
      Checked := rve.Style.TextStyles[rve.CurTextStyleNo].BiDiMode=FBiDiMode;
      exit;
    end;
    Chk := 1;
    if IterateRVData(rve.RVData, rve, -1, -1, Chk) then
      Checked := Chk<>0
    else
      Checked := False;
  except
    Enabled := False;
  end;
end;

{ TrvActionTextRTL }

constructor TrvActionTextRTL.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_TextRTL;
  FBiDiMode  := rvbdRightToLeft;
end;

{ TrvActionTextLTR }

constructor TrvActionTextLTR.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_TextLTR;
  FBiDiMode  := rvbdLeftToRight;
end;

{ TrvActionFontShrinkGrow }

constructor TrvActionFontShrinkGrow.Create(AOwner: TComponent);
begin
  inherited;
  FPercent := 10;
end;

{ TrvActionFontShrink }

constructor TrvActionFontShrink.Create(AOwner: TComponent);
begin
  inherited;
  FMinSize := 1;
  FMessageID := rvam_act_FontShrink;
end;

procedure TrvActionFontShrink.ApplyConversion(Editor: TCustomRichViewEdit;
  FontInfo: TFontInfo; StyleNo, Command: Integer);
var Size: Integer;
begin
  Size := Round(FontInfo.Size * (100-Percent) / 100);
  if Size=FontInfo.Size then
    if Size>0 then
      dec(Size)
    else
      inc(Size);
  if (Size>0) and (Size<FMinSize) then
    Size := FMinSize;
  if Size=0 then
    Size := 1;
  FontInfo.Size := Size;
end;

{ TrvActionFontGrow }

constructor TrvActionFontGrow.Create(AOwner: TComponent);
begin
  inherited;
  FMaxSize := 100;
  FMessageID := rvam_act_FontGrow;
end;

procedure TrvActionFontGrow.ApplyConversion(Editor: TCustomRichViewEdit;
  FontInfo: TFontInfo; StyleNo, Command: Integer);
var Size: Integer;
begin
  Size := Round(FontInfo.Size * (100+Percent) / 100);
  if Size=FontInfo.Size then
    if Size>0 then
      inc(Size)
    else
      dec(Size);
  if (Size>FMaxSize) then
    Size := FMaxSize;
  FontInfo.Size := Size;
end;

{ TrvActionFontShrinkOnePoint }

constructor TrvActionFontShrinkOnePoint.Create(AOwner: TComponent);
begin
  inherited;
  FMinSize := 1;
  FMessageID := rvam_act_FontShrink1Pt;
end;

procedure TrvActionFontShrinkOnePoint.ApplyConversion(Editor: TCustomRichViewEdit;
  FontInfo: TFontInfo; StyleNo, Command: Integer);
var Size: Integer;
begin
  Size := FontInfo.Size;
  if Size>0 then begin
    Size := FontInfo.Size-1;
    if Size<Abs(MinSize) then
      Size := Abs(MinSize);
    end
  else begin
    Size := FontInfo.Size+1;
    if Abs(Size)<Abs(MinSize) then
      Size := -Abs(MinSize);
  end;
  FontInfo.Size := Size;
end;

{ TrvActionFontGrowOnePoint }

constructor TrvActionFontGrowOnePoint.Create(AOwner: TComponent);
begin
  inherited;
  FMaxSize := 100;
  FMessageID := rvam_act_FontGrow1Pt;
end;


procedure TrvActionFontGrowOnePoint.ApplyConversion(Editor: TCustomRichViewEdit;
  FontInfo: TFontInfo; StyleNo, Command: Integer);
var Size: Integer;
begin
  Size := FontInfo.Size;
  if Size>0 then begin
    Size := FontInfo.Size+1;
    if Size>Abs(MaxSize) then
      Size := Abs(MaxSize);
    end
  else begin
    Size := FontInfo.Size-1;
    if Abs(Size)>Abs(MaxSize) then
      Size := -Abs(MaxSize);
  end;
  FontInfo.Size := Size;
end;

{-------------------------- Paragraph Styles ----------------------------------}

{ TrvActionParaStyles }

constructor TrvActionParaStyles.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_Paragraph;
end;

procedure TrvActionParaStyles.ExecuteCommand(rve: TCustomRichViewEdit; Command: Integer);
var FOldOnParaStyleConversion: TRVStyleConversionEvent;
begin
  FOldOnParaStyleConversion := rve.OnParaStyleConversion;
  SetParaStyleConversionEvent(rve, NewOnParaStyleConversion);
  try
    rve.ApplyParaStyleConversion(Command);
  finally
    SetParaStyleConversionEvent(rve, FOldOnParaStyleConversion);
  end;
end;

function TrvActionParaStyles.CanApplyToPlainText: Boolean;
begin
  Result := False;
end;

procedure TrvActionParaStyles.ExecuteTarget(Target: TObject);
begin
  ExecuteCommand(GetControl(Target), 0);
end;

procedure TrvActionParaStyles.NewOnParaStyleConversion(Sender: TCustomRichViewEdit; StyleNo, UserData: Integer;
  AppliedToText: Boolean; var NewStyleNo: Integer);
var
  ParaInfo: TParaInfo;
begin
  if rvpaoStyleProtect in Sender.Style.ParaStyles[StyleNo].Options then
    exit;
  ParaInfo := TParaInfo.Create(nil);
  try
    ParaInfo.Assign(Sender.Style.ParaStyles[StyleNo]);
    ApplyConversion(Sender, ParaInfo, StyleNo, UserData);
    NewStyleNo := RVA_Events.DoStyleNeeded(Self, Sender.Style, ParaInfo);
    if NewStyleNo<0 then begin
      NewStyleNo := Sender.Style.ParaStyles.FindSuchStyle(StyleNo, ParaInfo, RVAllParaInfoProperties);
      if NewStyleNo<0 then begin
        Sender.Style.ParaStyles.Add;
        NewStyleNo := Sender.Style.ParaStyles.Count - 1;
        Sender.Style.ParaStyles[NewStyleNo].Assign(ParaInfo);
        Sender.Style.ParaStyles[NewStyleNo].Standard := False;
        RVA_Events.DoOnAddStyle(Self, Sender.Style.ParaStyles[NewStyleNo]);
      end;
    end;
  finally
    ParaInfo.Free;
  end;
end;

{ TrvActionParagraph }

constructor TrvActionParagraph.Create(AOwner: TComponent);
begin
  inherited;
  FUserInterface := True;
  FTabs := TRVTabInfos.Create(Self);
  FTabsToDelete := TRVIntegerList.Create;
end;

destructor TrvActionParagraph.Destroy;
begin
  FTabs.Free;
  FTabsToDelete.Free;
  inherited;
end;

procedure TrvActionParagraph.ApplyConversion(Editor: TCustomRichViewEdit;
  ParaInfo: TParaInfo; StyleNo, Command: Integer);
var w: Integer;
begin
  if rvpimAlignment in ValidProperties then
    ParaInfo.Alignment   := Alignment;
  if rvpimFirstIndent in ValidProperties then
    ParaInfo.FirstIndent := FirstIndent;
  if rvpimLeftIndent in ValidProperties then
    ParaInfo.LeftIndent  := LeftIndent;
  if rvpimRightIndent in ValidProperties then
    ParaInfo.RightIndent := RightIndent;
  if rvpimSpaceBefore in ValidProperties then
    ParaInfo.SpaceBefore := SpaceBefore;
  if rvpimSpaceAfter in ValidProperties then
    ParaInfo.SpaceAfter  := SpaceAfter;
  if rvpimLineSpacing in ValidProperties then begin
    ParaInfo.LineSpacing := LineSpacing;
    ParaInfo.LineSpacingType := LineSpacingType;
  end;
  if rvpimOutlineLevel in ValidProperties then
    ParaInfo.OutlineLevel := OutlineLevel;
  if rvpimKeepLinesTogether in ValidProperties then
    if KeepLinesTogether then
      ParaInfo.Options := ParaInfo.Options+[rvpaoKeepLinesTogether]
    else
      ParaInfo.Options := ParaInfo.Options-[rvpaoKeepLinesTogether];
  if rvpimKeepWithNext in ValidProperties then
    if KeepWithNext then
      ParaInfo.Options := ParaInfo.Options+[rvpaoKeepWithNext]
    else
      ParaInfo.Options := ParaInfo.Options-[rvpaoKeepWithNext];
  if ParaInfo.Border.Style<>rvbNone then begin
    w := ParaInfo.Border.GetTotalWidth;
    if ParaInfo.LeftIndent<ParaInfo.Border.BorderOffsets.Left+w then
      ParaInfo.LeftIndent := ParaInfo.Border.BorderOffsets.Left+w;
    if ParaInfo.SpaceBefore<ParaInfo.Border.BorderOffsets.Top+w then
      ParaInfo.SpaceBefore := ParaInfo.Border.BorderOffsets.Top+w;
    if ParaInfo.RightIndent<ParaInfo.Border.BorderOffsets.Right+w then
      ParaInfo.RightIndent := ParaInfo.Border.BorderOffsets.Right+w;
    if ParaInfo.SpaceAfter<ParaInfo.Border.BorderOffsets.Bottom+w then
      ParaInfo.SpaceAfter := ParaInfo.Border.BorderOffsets.Bottom+w;
  end;
  if rvpimTabs in ValidProperties then begin
    if DeleteAllTabs then
      ParaInfo.Tabs.Clear
    else if TabsToDelete.Count>0 then
      ParaInfo.Tabs.DeleteList(TabsToDelete);
    ParaInfo.Tabs.AddFrom(Tabs);
  end;
end;

procedure TrvActionParagraph.ExecuteTarget(Target: TObject);
var frm: TfrmRVPara;
    rve: TCustomRichViewEdit;
    {...............................................................}
    procedure SetToForm;
    begin
      frm.rvs.Units := rve.Style.Units;
      if rvpimAlignment in ValidProperties then
        frm.gbAlignment.ItemIndex := ord(Alignment);
      if rvpimFirstIndent in ValidProperties then begin
        if FirstIndent>0 then
          frm.rbPositive.Checked := True
        else if FirstIndent<0 then
          frm.rbNegative.Checked := True;
        frm.seFirstLineIndent.Value := rve.Style.GetAsRVUnits(Abs(FirstIndent), RVA_Units);
      end;
      if rvpimLeftIndent in ValidProperties then
        frm.seLeftIndent.Value := rve.Style.GetAsRVUnits(LeftIndent, RVA_Units);
      if rvpimRightIndent in ValidProperties then
        frm.seRightIndent.Value := rve.Style.GetAsRVUnits(RightIndent, RVA_Units);
      if rvpimSpaceBefore in ValidProperties then
        frm.seSpaceBefore.Value := rve.Style.GetAsRVUnits(SpaceBefore, RVA_GetFineUnits);
      if rvpimSpaceAfter in ValidProperties then
        frm.seSpaceAfter.Value := rve.Style.GetAsRVUnits(SpaceAfter, RVA_GetFineUnits);
      if rvpimOutlineLevel in ValidProperties then
        if (OutlineLevel>=0) and (OutlineLevel<=10) then
          frm.SetXBoxItemIndex(frm._cmbOutlineLevel, OutlineLevel);
      if rvpimLineSpacing in ValidProperties then
        case LineSpacingType of
          rvlsPercent:
            case LineSpacing of
              100:
                frm.SetXBoxItemIndex(frm._cmbLineSpacing, 0);
              150:
                frm.SetXBoxItemIndex(frm._cmbLineSpacing, 1);
              200:
                frm.SetXBoxItemIndex(frm._cmbLineSpacing, 2);
              else begin
                frm.SetXBoxItemIndex(frm._cmbLineSpacing, 5);
                frm.seLineSpacingValue.Value := LineSpacing / 100;
              end;
            end;
          rvlsLineHeightAtLeast, rvlsLineHeightExact:
            begin
              if LineSpacingType=rvlsLineHeightAtLeast then
                frm.SetXBoxItemIndex(frm._cmbLineSpacing, 3)
              else
                frm.SetXBoxItemIndex(frm._cmbLineSpacing, 4);
              frm.UpdateLengthSpinEdit(frm.seLineSpacingValue, True, True);
              frm.seLineSpacingValue.MinValue := frm.seLineSpacingValue.Increment*5;
              frm.seLineSpacingValue.Value := rve.Style.GetAsRVUnits(LineSpacing, RVA_GetFineUnits);
            end;
        end
      else
        frm.SetXBoxItemIndex(frm._cmbLineSpacing, 5);
      frm.rv.LeftMargin := rve.LeftMargin  div 2;
      frm.rv.RightMargin := rve.RightMargin div 2;
      if rvpimKeepWithNext in ValidProperties then
        frm.SetCheckBoxChecked(frm._cbKeepWithNext, KeepWithNext);
      if rvpimKeepLinesTogether in ValidProperties then
        frm.SetCheckBoxChecked(frm._cbKeepLinesTogether, KeepLinesTogether);
      if rvpimTabs in ValidProperties then
        frm.Tabs := Tabs
      else
        frm.HideTabsPage;
    end;
    {...............................................................}
    procedure GetFromForm;
    begin
      ValidProperties := [];
      if frm.gbAlignment.ItemIndex>=0 then begin
        Include(FValidProperties, rvpimAlignment);
        Alignment :=  TRVAlignment(frm.gbAlignment.ItemIndex);
      end;
      if not frm.seSpaceBefore.Indeterminate then begin
        Include(FValidProperties, rvpimSpaceBefore);
        SpaceBefore := rve.Style.RVUnitsToUnits(frm.seSpaceBefore.Value, RVA_GetFineUnits);
      end;
      if not frm.seSpaceAfter.Indeterminate then begin
        Include(FValidProperties, rvpimSpaceAfter);
        SpaceAfter :=  rve.Style.RVUnitsToUnits(frm.seSpaceAfter.Value, RVA_GetFineUnits);
      end;
      if not frm.seLeftIndent.Indeterminate then begin
        Include(FValidProperties, rvpimLeftIndent);
        LeftIndent :=  rve.Style.RVUnitsToUnits(frm.seLeftIndent.Value, RVA_Units);
      end;
      if not frm.seRightIndent.Indeterminate then begin
        Include(FValidProperties, rvpimRightIndent);
        RightIndent :=  rve.Style.RVUnitsToUnits(frm.seRightIndent.Value, RVA_Units);
      end;
      if not frm.seFirstLineIndent.Indeterminate then begin
        Include(FValidProperties, rvpimFirstIndent);
        if frm.rbNegative.Checked then
          FirstIndent := -rve.Style.RVUnitsToUnits(frm.seFirstLineIndent.Value, RVA_Units)
        else
          FirstIndent := rve.Style.RVUnitsToUnits(frm.seFirstLineIndent.Value, RVA_Units);
      end;
      if frm.GetXBoxItemIndex(frm._cmbOutlineLevel)>=0 then begin
        OutlineLevel := frm.GetXBoxItemIndex(frm._cmbOutlineLevel);
        Include(FValidProperties, rvpimOutlineLevel);
      end;
      Include(FValidProperties, rvpimLineSpacing);
      LineSpacingType := rvlsPercent;
      case frm.GetXBoxItemIndex(frm._cmbLineSpacing) of
        0: LineSpacing := 100;
        1: LineSpacing := 150;
        2: LineSpacing := 200;
        3: begin
             LineSpacingType := rvlsLineHeightAtLeast;
             if frm.seLineSpacingValue.Indeterminate then
               Exclude(FValidProperties, rvpimLineSpacing)
             else
               LineSpacing := rve.Style.RVUnitsToUnits(frm.seLineSpacingValue.AsInteger, RVA_GetFineUnits);
           end;
        4: begin
             LineSpacingType := rvlsLineHeightExact;
             if frm.seLineSpacingValue.Indeterminate then
               Exclude(FValidProperties, rvpimLineSpacing)
             else
               LineSpacing := rve.Style.RVUnitsToUnits(frm.seLineSpacingValue.Value, RVA_GetFineUnits);
           end;
        5: begin
            if frm.seLineSpacingValue.Indeterminate then
              Exclude(FValidProperties, rvpimLineSpacing)
            else
              LineSpacing := Round(frm.seLineSpacingValue.Value * 100);
           end;
      end;
      if frm.GetCheckBoxState(frm._cbKeepWithNext)<>cbGrayed then begin
        KeepWithNext := frm.GetCheckBoxChecked(frm._cbKeepWithNext);
        Include(FValidProperties, rvpimKeepWithNext);
      end;
      if frm.GetCheckBoxState(frm._cbKeepLinesTogether)<>cbGrayed then begin
        KeepLinesTogether := frm.GetCheckBoxChecked(frm._cbKeepLinesTogether);
        Include(FValidProperties, rvpimKeepLinesTogether);
      end;
      if RVA_UserInterface=rvauiHTML then begin
        Include(FValidProperties, rvpimTabs);
        Tabs.Clear;
        DeleteAllTabs := True;
        TabsToDelete.Clear;
        end
      else if frm.TabsModified then begin
        Include(FValidProperties, rvpimTabs);
        Tabs := frm.Tabs;
        DeleteAllTabs := frm.DeleteAllTabs;
        if not DeleteAllTabs then
          TabsToDelete := frm.TabsToDelete;
      end;
    end;
    {...............................................................}
begin
  if not UserInterface then begin
    ExecuteCommand(GetControl(Target), 0);
    exit;
  end;
  rve := GetControl(Target);
  GetFromEditor(rve);
  frm := TfrmRVPara.Create(Application);
  try
    SetToForm;
    if frm.ShowModal = mrOk then begin
      GetFromForm;
      ExecuteCommand(GetControl(Target), 0);
    end;
  finally
    frm.Free;
  end;
end;

function TrvActionParagraph.ContinueIteration(
  var CustomData: Integer): Boolean;
begin
  Result := ValidProperties<>[];
end;

procedure TrvActionParagraph.IterateProc(RVData: TCustomRVData; ItemNo: Integer; rve: TCustomRichViewEdit;
  var CustomData: Integer);
var ParaNo: Integer;
    ParaInfo: TParaInfo;
    item: TCustomRVItemInfo;
begin
  item := RVData.GetItem(ItemNo);
  ParaNo := item.ParaNo;
  if ParaNo=CustomData then
    exit;
  ParaInfo   := rve.Style.ParaStyles[ParaNo];
  if CustomData=-1 then begin
    Alignment   := ParaInfo.Alignment;
    FirstIndent := ParaInfo.FirstIndent;
    LeftIndent  := ParaInfo.LeftIndent;
    RightIndent := ParaInfo.RightIndent;
    SpaceBefore := ParaInfo.SpaceBefore;
    SpaceAfter  := ParaInfo.SpaceAfter;
    OutlineLevel := ParaInfo.OutlineLevel;
    if ParaInfo.LineSpacingType=rvlsSpaceBetween then
      Exclude(FValidProperties, rvpimLineSpacing)
    else begin
      LineSpacing := ParaInfo.LineSpacing;
      LineSpacingType := ParaInfo.LineSpacingType;
    end;
    KeepLinesTogether := rvpaoKeepLinesTogether in ParaInfo.Options;
    KeepWithNext := rvpaoKeepWithNext in ParaInfo.Options;
    if rvpimTabs in ValidProperties then
      Tabs := ParaInfo.Tabs;
    end
  else begin
    if Alignment<>ParaInfo.Alignment then
       Exclude(FValidProperties, rvpimAlignment);
    if FirstIndent<>ParaInfo.FirstIndent then
       Exclude(FValidProperties, rvpimFirstIndent);
    if LeftIndent<>ParaInfo.LeftIndent then
       Exclude(FValidProperties, rvpimLeftIndent);
    if RightIndent<>ParaInfo.RightIndent then
       Exclude(FValidProperties, rvpimRightIndent);
    if SpaceBefore<>ParaInfo.SpaceBefore then
       Exclude(FValidProperties, rvpimSpaceBefore);
    if SpaceAfter<>ParaInfo.SpaceAfter then
       Exclude(FValidProperties, rvpimSpaceAfter);
    if OutlineLevel<>ParaInfo.OutlineLevel then
       Exclude(FValidProperties, rvpimOutlineLevel);
    if (LineSpacingType<>ParaInfo.LineSpacingType) or
       (LineSpacing<>ParaInfo.LineSpacing) then
       Exclude(FValidProperties, rvpimLineSpacing);
    if KeepLinesTogether<>(rvpaoKeepLinesTogether in ParaInfo.Options) then
      Exclude(FValidProperties, rvpimKeepLinesTogether);
    if KeepWithNext<>(rvpaoKeepWithNext in ParaInfo.Options) then
      Exclude(FValidProperties, rvpimKeepWithNext);
    if (rvpimTabs in ValidProperties) and (Tabs.Count>0) then
      Tabs.Intersect(ParaInfo.Tabs);
  end;
  CustomData := ParaNo;
end;

procedure TrvActionParagraph.GetFromEditor(rve: TCustomRichViewEdit);
var StartNo, EndNo: Integer;
    ParaNo: Integer;
begin
   rve := rve.TopLevelEditor;
   ValidProperties := [Low(TRVParaInfoMainProperty)..High(TRVParaInfoMainProperty)];
   if rve.Style.SpacesInTab>0 then
     ValidProperties := ValidProperties-[rvpimTabs];
   DeleteAllTabs := False;
   TabsToDelete.Clear;
   Tabs.Clear;
   GetSelectionBounds(rve, StartNo, EndNo);
   ParaNo := -1;
   if not rve.SelectionExists then
     IterateProc(rve.RVData, StartNo, rve, ParaNo)
   else
     IterateRVData(rve.RVData, rve, StartNo, EndNo, ParaNo);
end;

procedure TrvActionParagraph.SetTabs(const Value: TRVTabInfos);
begin
  if Value<>FTabs then
    FTabs.Assign(Value);
end;

procedure TrvActionParagraph.SetTabsToDelete(const Value: TRVIntegerList);
begin
  if Value<>FTabsToDelete then
    FTabsToDelete.Assign(Value);
end;

{ TrvActionParaCustomColor }

procedure TrvActionParaCustomColor.ExecuteCommand(rve: TCustomRichViewEdit;
  Command: Integer);
var FOldOnParaStyleConversion: TRVStyleConversionEvent;
begin
  FOldOnParaStyleConversion := rve.OnParaStyleConversion;
  SetParaStyleConversionEvent(rve, NewOnParaStyleConversion);
  try
    rve.ApplyParaStyleConversion(Command);
  finally
    SetParaStyleConversionEvent(rve, FOldOnParaStyleConversion);
  end;
end;

procedure TrvActionParaCustomColor.NewOnParaStyleConversion(
  Sender: TCustomRichViewEdit; StyleNo, UserData: Integer;
  AppliedToText: Boolean; var NewStyleNo: Integer);
var
  ParaInfo: TParaInfo;
begin
  if rvpaoStyleProtect in Sender.Style.ParaStyles[StyleNo].Options then
    exit;
  ParaInfo := TParaInfo.Create(nil);
  try
    ParaInfo.Assign(Sender.Style.ParaStyles[StyleNo]);
    ApplyConversion(Sender, ParaInfo, StyleNo, UserData);
    NewStyleNo := RVA_Events.DoStyleNeeded(Self, Sender.Style, ParaInfo);
    if NewStyleNo<0 then begin
      NewStyleNo := Sender.Style.ParaStyles.FindSuchStyle(StyleNo, ParaInfo, RVAllParaInfoProperties);
      if NewStyleNo<0 then begin
        Sender.Style.ParaStyles.Add;
        NewStyleNo := Sender.Style.ParaStyles.Count - 1;
        Sender.Style.ParaStyles[NewStyleNo].Assign(ParaInfo);
        Sender.Style.ParaStyles[NewStyleNo].Standard := False;
        RVA_Events.DoOnAddStyle(Self, Sender.Style.ParaStyles[NewStyleNo]);
      end;
    end;
  finally
    ParaInfo.Free;
  end;
end;

{ TrvActionParaColor }

constructor TrvActionParaColor.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_ParaColor;
end;

procedure TrvActionParaColor.ApplyConversion(Editor: TCustomRichViewEdit;
  ParaInfo: TParaInfo; StyleNo, Command: Integer);
begin
  ParaInfo.Background.Color := FColor;
end;

function TrvActionParaColor.GetCurrentColor(
  FEdit: TCustomRichViewEdit): TColor;
begin
  Result := FEdit.Style.ParaStyles[FEdit.CurParaStyleNo].Background.Color;
end;

{ TrvActionParaColorAndPadding }

procedure TrvActionParaColorAndPadding.ApplyConversion(Editor: TCustomRichViewEdit;
  ParaInfo: TParaInfo; StyleNo, Command: Integer);
begin
  ParaInfo.Background.Color := FColor;
  if UsePadding.Left then begin
    ParaInfo.Background.BorderOffsets.Left := Padding.Left;
    if ParaInfo.LeftIndent<Padding.Left then
      ParaInfo.LeftIndent := Padding.Left;
  end;
  if UsePadding.Right then begin
    ParaInfo.Background.BorderOffsets.Right := Padding.Right;
    if ParaInfo.RightIndent<Padding.Right then
      ParaInfo.RightIndent := Padding.Right;
  end;
  if UsePadding.Top then begin
    ParaInfo.Background.BorderOffsets.Top := Padding.Top;
    if ParaInfo.SpaceBefore<Padding.Top then
      ParaInfo.SpaceBefore := Padding.Top;
  end;
  if UsePadding.Bottom then begin
    ParaInfo.Background.BorderOffsets.Bottom := Padding.Bottom;
    if ParaInfo.SpaceAfter<Padding.Bottom then
      ParaInfo.SpaceAfter := Padding.Bottom;
  end;  
end;

constructor TrvActionParaColorAndPadding.Create(AOwner: TComponent);
begin
  inherited;
  FPadding := TRVRect.Create;
  FUsePadding := TRVBooleanRect.Create(True);
end;

destructor TrvActionParaColorAndPadding.Destroy;
begin
  FPadding.Free;
  FUsePadding.Free;
  inherited;
end;

procedure TrvActionParaColorAndPadding.SetPadding(const Value: TRVRect);
begin
  FPadding.Assign(Value);
end;

procedure TrvActionParaColorAndPadding.SetUsePadding(
  const Value: TRVBooleanRect);
begin
  FUsePadding.Assign(Value);
end;

{ TrvActionWordWrap }

constructor TrvActionWordWrap.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_WordWrap;
end;

procedure TrvActionWordWrap.ApplyConversion(Editor: TCustomRichViewEdit;
  ParaInfo: TParaInfo; StyleNo, Command: Integer);
begin
  if Checked then
    ParaInfo.Options := ParaInfo.Options + [rvpaoNoWrap]
  else
    ParaInfo.Options := ParaInfo.Options - [rvpaoNoWrap];
end;

function TrvActionWordWrap.ContinueIteration(
  var CustomData: Integer): Boolean;
begin
  Result := CustomData<>0;
end;

procedure TrvActionWordWrap.IterateProc(RVData: TCustomRVData;
  ItemNo: Integer; rve: TCustomRichViewEdit; var CustomData: Integer);
begin
  if not (rvpaoNoWrap in rve.Style.ParaStyles[RVData.GetItemPara(ItemNo)].Options) then
    CustomData := 0;
end;

procedure TrvActionWordWrap.UpdateTarget(Target: TObject);
var rve: TCustomRichViewEdit;
    Chk: Integer;
begin
  try
    Enabled := RVA_ActionsEnabled and not Disabled and (RVA_UserInterface<>rvauiText);
    rve := GetControl(Target).TopLevelEditor;
    if rve.RVData.PartialSelectedItem=nil then begin
      Checked := not (rvpaoNoWrap in rve.Style.ParaStyles[rve.CurParaStyleNo].Options);
      exit;
    end;
    Chk := 1;
    if IterateRVData(rve.RVData, rve, -1, -1, Chk) then
      Checked := Chk=0
    else
      Checked := False;
  except
    Enabled := False;
  end;
end;

{ TrvActionAlignment }

procedure TrvActionAlignment.ApplyConversion(Editor: TCustomRichViewEdit;
  ParaInfo: TParaInfo; StyleNo, Command: Integer);
begin
  ParaInfo.Alignment := FAlignment;
end;

function TrvActionAlignment.ContinueIteration(var CustomData: Integer): Boolean;
begin
  Result := CustomData<>0;
end;

procedure TrvActionAlignment.IterateProc(RVData: TCustomRVData;
  ItemNo: Integer; rve: TCustomRichViewEdit; var CustomData: Integer);
begin
  if FAlignment<>rve.Style.ParaStyles[RVData.GetItemPara(ItemNo)].Alignment then
    CustomData := 0;
end;

procedure TrvActionAlignment.UpdateTarget(Target: TObject);
var rve: TCustomRichViewEdit;
    Chk: Integer;
begin
  try
    Enabled := RVA_ActionsEnabled and not Disabled and (RVA_UserInterface<>rvauiText);
    rve := GetControl(Target).TopLevelEditor;
    if rve.RVData.PartialSelectedItem=nil then begin
      Checked := rve.Style.ParaStyles[rve.CurParaStyleNo].Alignment = FAlignment;
      exit;
    end;
    Chk := 1;
    if IterateRVData(rve.RVData, rve, -1, -1, Chk) then
      Checked := Chk<>0
    else
      Checked := False;
  except
    Enabled := False;
  end;
end;

{ TrvActionAlignLeft }

constructor TrvActionAlignLeft.Create(AOwner: TComponent);
begin
  inherited;
  FAlignment := rvaLeft;
  FMessageID := rvam_act_AlignLeft;
end;

{ TrvActionAlignCenter }

constructor TrvActionAlignCenter.Create(AOwner: TComponent);
begin
  inherited;
  FAlignment := rvaCenter;
  FMessageID := rvam_act_AlignCenter;
end;

{ TrvActionAlignRight }

constructor TrvActionAlignRight.Create(AOwner: TComponent);
begin
  inherited;
  FAlignment := rvaRight;
  FMessageID := rvam_act_AlignRight;
end;

{ TrvActionAlignJustify }

constructor TrvActionAlignJustify.Create(AOwner: TComponent);
begin
  inherited;
  FAlignment := rvaJustify;
  FMessageID := rvam_act_AlignJustify;
end;

{ TrvActionParaBiDi }

procedure TrvActionParaBiDi.ApplyConversion(Editor: TCustomRichViewEdit;
  ParaInfo: TParaInfo; StyleNo, Command: Integer);
begin
  if ParaInfo.BiDiMode<>FBiDiMode then begin
    ParaInfo.BiDiMode := FBiDiMode;
    if ParaInfo.Alignment = rvaLeft then
      ParaInfo.Alignment := rvaRight
    else if ParaInfo.Alignment = rvaRight then
      ParaInfo.Alignment := rvaLeft;
  end;
end;

function TrvActionParaBiDi.ContinueIteration(var CustomData: Integer): Boolean;
begin
  Result := CustomData<>0;
end;

procedure TrvActionParaBiDi.IterateProc(RVData: TCustomRVData;
  ItemNo: Integer; rve: TCustomRichViewEdit; var CustomData: Integer);
begin
  if FBiDiMode<>rve.Style.ParaStyles[RVData.GetItemPara(ItemNo)].BiDiMode then
    CustomData := 0;
end;

procedure TrvActionParaBiDi.UpdateTarget(Target: TObject);
var rve: TCustomRichViewEdit;
    Chk: Integer;
begin
  try
    Enabled := RVA_ActionsEnabled and not Disabled and (RVA_UserInterface<>rvauiText);
    rve := GetControl(Target).TopLevelEditor;
    if rve.RVData.PartialSelectedItem=nil then begin
      Checked := rve.Style.ParaStyles[rve.CurParaStyleNo].BiDiMode=FBiDiMode;
      exit;
    end;
    Chk := 1;
    if IterateRVData(rve.RVData, rve, -1, -1, Chk) then
      Checked := Chk<>0
    else
      Checked := False;
  except
    Enabled := False;
  end;
end;


{ TrvActionParaLTR }

constructor TrvActionParaLTR.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_ParaLTR;
  FBiDiMode := rvbdLeftToRight;
end;

{ TrvActionParaRTL }

constructor TrvActionParaRTL.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_ParaRTL;
  FBiDiMode := rvbdRightToLeft;
end;

{ TrvActionIndent }

constructor TrvActionIndent.Create(AOwner: TComponent);
begin
  inherited;
  IndentStep := 24;
end;

procedure TrvActionIndent.ExecuteTarget(Target: TObject);
begin
  FIndentStepTmp := GetControl(Target).Style.DifferentUnitsToUnits(IndentStep, RVA_UnitsProgram);
  ExecuteCommand(GetControl(Target), GetControl(Target).LeftMargin);
end;

procedure TrvActionIndent.ConvertToPixels;
begin
  inherited;
  IndentStep := TRVStyle.GetAsPixelsEx(IndentStep, RVA_UnitsProgram);
end;

procedure TrvActionIndent.ConvertToTwips;
begin
  inherited;
  IndentStep := TRVStyle.GetAsTwipsEx(IndentStep, RVA_UnitsProgram);
end;

{ TrvActionIndentDec }

procedure TrvActionIndentDec.ApplyConversion(Editor: TCustomRichViewEdit;
  ParaInfo: TParaInfo; StyleNo, Command: Integer);
var BiDiMode: TRVBiDiMode;
begin
  Editor := Editor.TopLevelEditor;
  BiDiMode := ParaInfo.BiDiMode;
  if BiDiMode=rvbdUnspecified then
    BiDiMode := Editor.BiDiMode;
  if BiDiMode<>rvbdRightToLeft then begin
    ParaInfo.LeftIndent := ParaInfo.LeftIndent - FIndentStepTmp;
    if ParaInfo.LeftIndent < 0 then
      ParaInfo.LeftIndent := 0;
    if ParaInfo.LeftIndent + ParaInfo.FirstIndent < 0 then
      ParaInfo.FirstIndent := -ParaInfo.LeftIndent;
    if ParaInfo.Border.Style<>rvbNone then begin
      if ParaInfo.LeftIndent<ParaInfo.Border.BorderOffsets.Left+ParaInfo.Border.GetTotalWidth then
        ParaInfo.LeftIndent := ParaInfo.Border.BorderOffsets.Left+ParaInfo.Border.GetTotalWidth;
    end;
    end
  else begin
    ParaInfo.RightIndent := ParaInfo.RightIndent - FIndentStepTmp;
    if ParaInfo.RightIndent < 0 then
      ParaInfo.RightIndent := 0;
    if ParaInfo.RightIndent + ParaInfo.FirstIndent < 0 then
      ParaInfo.FirstIndent := -ParaInfo.RightIndent;
    if ParaInfo.Border.Style<>rvbNone then begin
      if ParaInfo.RightIndent<ParaInfo.Border.BorderOffsets.Right+ParaInfo.Border.GetTotalWidth then
        ParaInfo.RightIndent := ParaInfo.Border.BorderOffsets.Right+ParaInfo.Border.GetTotalWidth;
    end;
  end;
end;

constructor TrvActionIndentDec.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_IndentDec;
end;

procedure TrvActionIndentDec.ExecuteTarget(Target: TObject);
var rve: TCustomRichViewEdit;
begin
  rve := GetControl(Target).TopLevelEditor;
  rve.BeginUndoGroup(rvutPara);
  rve.SetUndoGroupMode(True);
  try
    inherited;
    GetControl(Target).ChangeListLevels(-1);
  finally
    rve.SetUndoGroupMode(False);
  end;
end;

{ TrvActionIndentInc }

constructor TrvActionIndentInc.Create(AOwner: TComponent);
begin
  inherited;
  IndentMax := 200;
  FMessageID := rvam_act_IndentInc;
end;

procedure TrvActionIndentInc.ApplyConversion(Editor: TCustomRichViewEdit;
  ParaInfo: TParaInfo; StyleNo, Command: Integer);
var BiDiMode: TRVBiDiMode;
begin
  BiDiMode := ParaInfo.BiDiMode;
  if BiDiMode=rvbdUnspecified then
    BiDiMode := Editor.BiDiMode;
  if BiDiMode<>rvbdRightToLeft then begin
    ParaInfo.LeftIndent := ParaInfo.LeftIndent + FIndentStepTmp;
    if ParaInfo.LeftIndent > FIndentMaxTmp then
      ParaInfo.LeftIndent := FIndentMaxTmp;
    end
  else begin
    ParaInfo.RightIndent := ParaInfo.RightIndent + FIndentStepTmp;
    if ParaInfo.RightIndent > FIndentMaxTmp then
      ParaInfo.RightIndent := FIndentMaxTmp;
  end;
end;

procedure TrvActionIndentInc.ExecuteTarget(Target: TObject);
var rve: TCustomRichViewEdit;
begin
  rve := GetControl(Target).TopLevelEditor;
  rve.BeginUndoGroup(rvutPara);
  rve.SetUndoGroupMode(True);
  try
    FIndentMaxTmp := GetControl(Target).Style.DifferentUnitsToUnits(IndentMax, RVA_UnitsProgram);
    inherited;
    GetControl(Target).ChangeListLevels(+1);
  finally
    rve.SetUndoGroupMode(False);
  end;
end;

procedure TrvActionIndentInc.ConvertToPixels;
begin
  inherited;
  IndentMax := TRVStyle.GetAsPixelsEx(IndentMax, RVA_UnitsProgram);
end;

procedure TrvActionIndentInc.ConvertToTwips;
begin
  inherited;
  IndentMax := TRVStyle.GetAsTwipsEx(IndentMax, RVA_UnitsProgram);
end;

{ TrvActionLineSpacing }

procedure TrvActionLineSpacing.ApplyConversion(Editor: TCustomRichViewEdit;
  ParaInfo: TParaInfo; StyleNo, Command: Integer);
begin
  ParaInfo.LineSpacing := FLineSpacing;
  ParaInfo.LineSpacingType := rvlsPercent;
end;

function TrvActionLineSpacing.ContinueIteration(var CustomData: Integer): Boolean;
begin
  Result := CustomData<>0;
end;

procedure TrvActionLineSpacing.IterateProc(RVData: TCustomRVData;
  ItemNo: Integer; rve: TCustomRichViewEdit; var CustomData: Integer);
begin
  if (FLineSpacing<>rve.Style.ParaStyles[RVData.GetItemPara(ItemNo)].LineSpacing) or
     (rvlsPercent<>rve.Style.ParaStyles[RVData.GetItemPara(ItemNo)].LineSpacingType) then
    CustomData := 0;
end;

procedure TrvActionLineSpacing.UpdateTarget(Target: TObject);
var rve: TCustomRichViewEdit;
    Chk: Integer;
begin
  try
    inherited;
    if RVA_UserInterface=rvauiText then
      Enabled := False;
    rve := GetControl(Target).TopLevelEditor;
    if rve.RVData.PartialSelectedItem=nil then begin
      Checked := (rve.Style.ParaStyles[rve.CurParaStyleNo].LineSpacing = FLineSpacing)
             and (rve.Style.ParaStyles[rve.CurParaStyleNo].LineSpacingType = rvlsPercent);
      exit;
    end;
    Chk := 1;
    if IterateRVData(rve.RVData, rve, -1, -1, Chk) then
      Checked := Chk<>0
    else
      Checked := False;
  except
    Enabled := False;
  end;
end;


{ TrvActionLineSpacing100 }

constructor TrvActionLineSpacing100.Create(AOwner: TComponent);
begin
  inherited;
  FLineSpacing := 100;
  FMessageID := rvam_act_LS100;
end;

{ TrvActionLineSpacing150 }

constructor TrvActionLineSpacing150.Create(AOwner: TComponent);
begin
  inherited;
  FLineSpacing := 150;
  FMessageID := rvam_act_LS150;
end;

{ TrvActionLineSpacing200 }

constructor TrvActionLineSpacing200.Create(AOwner: TComponent);
begin
  inherited;
  FLineSpacing := 200;
  FMessageID := rvam_act_LS200;  
end;

{ TrvActionParaBorder }

constructor TrvActionParaBorder.Create(AOwner: TComponent);
begin
  inherited;
  FUserInterface := True;
  FBorder := TRVBorder.Create(Self);
  FBackground := TRVBackgroundRect.Create(Self);
  FMessageID := rvam_act_ParaBorder;
end;

destructor TrvActionParaBorder.Destroy;
begin
  FBorder.Free;
  FBackground.Free;
  inherited;
end;

procedure TrvActionParaBorder.ApplyConversion(Editor: TCustomRichViewEdit;
  ParaInfo: TParaInfo; StyleNo, Command: Integer);
var w: Integer;
    procedure NormalizeIndents(Offsets: TRVRect; w: Integer);
    begin
      if ParaInfo.LeftIndent<Offsets.Left+w then
        ParaInfo.LeftIndent := Offsets.Left+w;
      if ParaInfo.SpaceBefore<Offsets.Top+w then
        ParaInfo.SpaceBefore := Offsets.Top+w;
      if ParaInfo.RightIndent<Offsets.Right+w then
        ParaInfo.RightIndent := Offsets.Right+w;
      if ParaInfo.SpaceAfter<Offsets.Bottom+w then
        ParaInfo.SpaceAfter := Offsets.Bottom+w;
    end;
begin
  if rvpibBorder_Width in ValidProperties then
    ParaInfo.Border.Width := FBorder.Width;
  if rvpibBorder_Color in ValidProperties then
    ParaInfo.Border.Color := FBorder.Color;
  if rvpibBackground_Color in ValidProperties then
    ParaInfo.Background.Color := FBackground.Color;
  if rvpibBorder_Style in ValidProperties then
    ParaInfo.Border.Style := FBorder.Style;
  if rvpibBorder_InternalWidth in ValidProperties then
    ParaInfo.Border.InternalWidth := FBorder.InternalWidth;

  if rvpibBorder_BO_Left in ValidProperties then
    ParaInfo.Border.BorderOffsets.Left := FBorder.BorderOffsets.Left;
  if rvpibBorder_BO_Top in ValidProperties then
    ParaInfo.Border.BorderOffsets.Top := FBorder.BorderOffsets.Top;
  if rvpibBorder_BO_Right in ValidProperties then
    ParaInfo.Border.BorderOffsets.Right := FBorder.BorderOffsets.Right;
  if rvpibBorder_BO_Bottom in ValidProperties then
    ParaInfo.Border.BorderOffsets.Bottom := FBorder.BorderOffsets.Bottom;

  if rvpibBackground_BO_Left in ValidProperties then
    ParaInfo.Background.BorderOffsets.Left := FBackground.BorderOffsets.Left;
  if rvpibBackground_BO_Top in ValidProperties then
    ParaInfo.Background.BorderOffsets.Top := FBackground.BorderOffsets.Top;
  if rvpibBackground_BO_Right in ValidProperties then
    ParaInfo.Background.BorderOffsets.Right := FBackground.BorderOffsets.Right;
  if rvpibBackground_BO_Bottom in ValidProperties then
    ParaInfo.Background.BorderOffsets.Bottom := FBackground.BorderOffsets.Bottom;

  if rvpibBorder_Vis_Left in ValidProperties then
    ParaInfo.Border.VisibleBorders.Left := FBorder.VisibleBorders.Left;
  if rvpibBorder_Vis_Top in ValidProperties then
    ParaInfo.Border.VisibleBorders.Top := FBorder.VisibleBorders.Top;
  if rvpibBorder_Vis_Right in ValidProperties then
    ParaInfo.Border.VisibleBorders.Right := FBorder.VisibleBorders.Right;
  if rvpibBorder_Vis_Bottom in ValidProperties then
    ParaInfo.Border.VisibleBorders.Bottom := FBorder.VisibleBorders.Bottom;
  if ParaInfo.Border.Style<>rvbNone then begin
    w := ParaInfo.Border.GetTotalWidth;
    NormalizeIndents(ParaInfo.Border.BorderOffsets, w);
  end;
  NormalizeIndents(ParaInfo.Background.BorderOffsets, 0);
end;

procedure TrvActionParaBorder.ExecuteTarget(Target: TObject);

  procedure SetToForm(frm: TfrmRVParaBrdr; rve: TCustomRichViewEdit);
  var idx: Integer;
      br: TRVBooleanRect;
  begin
    frm.rvs.Units := rve.Style.Units;
    frm.ColorDialog := RVA_ColorDialog;

    if rvpibBorder_Width in ValidProperties then begin
      idx := RVA_GetComboBorderItemIndex(FBorder.Width, rve.Style,
        frm.GetXBoxItemCount(frm._cmbWidth));
      frm.SetXBoxItemIndex(frm._cmbWidth, idx);
    end;
    if rvpibBorder_Color in ValidProperties then
      frm.cmbColor.ChosenColor := FBorder.Color;
    if rvpibBackground_Color in ValidProperties then begin
      frm.BCIndeterminate := False;
      frm.BackColor := FBackground.Color;
    end;

    if rvpibBorder_Style in ValidProperties then
      if ord(FBorder.Style)<= frm.rgBorderType.Items.Count then
        frm.rgBorderType.ItemIndex := ord(FBorder.Style)
      else
        frm.rgBorderType.ItemIndex := 2; // double
    if rvpibBorder_InternalWidth in ValidProperties then
      frm.seIW.Value := rve.Style.GetAsRVUnits(FBorder.InternalWidth, RVA_GetBorderUnits);
    br := TRVBooleanRect.Create(False);
    br.Left   := rvpibBorder_BO_Left   in ValidProperties;
    br.Top    := rvpibBorder_BO_Top    in ValidProperties;
    br.Right  := rvpibBorder_BO_Right  in ValidProperties;
    br.Bottom := rvpibBorder_BO_Bottom in ValidProperties;
    frm.SetBO(FBorder.BorderOffsets, br);
    br.Left   := rvpibBackground_BO_Left   in ValidProperties;
    br.Top    := rvpibBackground_BO_Top    in ValidProperties;
    br.Right  := rvpibBackground_BO_Right  in ValidProperties;
    br.Bottom := rvpibBackground_BO_Bottom in ValidProperties;
    frm.SetPadding(FBackground.BorderOffsets, br);    
    br.Free;
    if rvpibBorder_Vis_Left in ValidProperties then begin
      frm.btnLeft.Flat := False;
      frm.btnLeft.Down := FBorder.VisibleBorders.Left;
    end;
    if rvpibBorder_Vis_Top in ValidProperties then begin
      frm.btnTop.Flat := False;
      frm.btnTop.Down := FBorder.VisibleBorders.Top;
    end;
    if rvpibBorder_Vis_Right in ValidProperties then begin
      frm.btnRight.Flat := False;
      frm.btnRight.Down := FBorder.VisibleBorders.Right;
    end;
    if rvpibBorder_Vis_Bottom in ValidProperties then begin
      frm.btnBottom.Flat := False;
      frm.btnBottom.Down := FBorder.VisibleBorders.Bottom;
    end;
  end;

  procedure GetFromForm(frm: TfrmRVParaBrdr);
  var br: TRVBooleanRect;
  begin
    ValidProperties := [];
    if frm.GetXBoxItemIndex(frm._cmbWidth)>=0 then begin
      Include(FValidProperties,rvpibBorder_Width);
      FBorder.Width := RVA_GetComboBorderWidth2(frm.GetXBoxItemIndex(frm._cmbWidth),
        frm.rvs);
    end;
    if not frm.cmbColor.Indeterminate then begin
      Include(FValidProperties,rvpibBorder_Color);
      FBorder.Color := frm.cmbColor.ChosenColor;
    end;
    if not frm.BCIndeterminate then begin
      Include(FValidProperties,rvpibBackground_Color);
      FBackground.Color := frm.BackColor;
    end;
    if frm.rgBorderType.ItemIndex>=0 then begin
      Include(FValidProperties,rvpibBorder_Style);
      FBorder.Style := TRVBorderStyle(frm.rgBorderType.ItemIndex);
    end;
    if not frm.seIW.Indeterminate then begin
      Include(FValidProperties,rvpibBorder_InternalWidth);
      FBorder.InternalWidth := frm.rvs.RVUnitsToUnits(frm.seIW.Value, RVA_GetBorderUnits);
    end;
    br := TRVBooleanRect.Create(False);
    frm.GetBO(FBorder.BorderOffsets, br);    
    if br.Left then
      Include(FValidProperties, rvpibBorder_BO_Left);
    if br.Top then
      Include(FValidProperties, rvpibBorder_BO_Top);
    if br.Right then
      Include(FValidProperties, rvpibBorder_BO_Right);
    if br.Bottom then
      Include(FValidProperties, rvpibBorder_BO_Bottom);
    frm.GetPadding(FBackground.BorderOffsets, br);
    if br.Left then
      Include(FValidProperties, rvpibBackground_BO_Left);
    if br.Top then
      Include(FValidProperties, rvpibBackground_BO_Top);
    if br.Right then
      Include(FValidProperties, rvpibBackground_BO_Right);
    if br.Bottom then
      Include(FValidProperties, rvpibBackground_BO_Bottom);
    br.Free;

    if not frm.btnLeft.Flat then begin
      Include(FValidProperties, rvpibBorder_Vis_Left);
      FBorder.VisibleBorders.Left := frm.btnLeft.Down;
    end;
    if not frm.btnTop.Flat then begin
      Include(FValidProperties, rvpibBorder_Vis_Top);
      FBorder.VisibleBorders.Top := frm.btnTop.Down;
    end;
    if not frm.btnRight.Flat then begin
      Include(FValidProperties, rvpibBorder_Vis_Right);
      FBorder.VisibleBorders.Right := frm.btnRight.Down;
    end;
    if not frm.btnBottom.Flat then begin
      Include(FValidProperties, rvpibBorder_Vis_Bottom);
      FBorder.VisibleBorders.Bottom := frm.btnBottom.Down;
    end;
  end;

var frm: TfrmRVParaBrdr;
    rve: TCustomRichViewEdit;
begin
  rve := GetControl(Target);
  if not UserInterface then begin
    ExecuteCommand(rve, 0);
    exit;
  end;
  GetFromEditor(rve);
  frm := TfrmRVParaBrdr.Create(Application);
  try
    SetToForm(frm, rve);
    if frm.ShowModal=mrOk then begin
      GetFromForm(frm);
      ExecuteCommand(rve, 0);
    end;
  finally
    frm.Free;
  end;
end;

procedure TrvActionParaBorder.GetFromEditor(rve: TCustomRichViewEdit);
var StartNo, EndNo: Integer;
    ParaNo: Integer;
begin
   rve := rve.TopLevelEditor;
   ValidProperties := [Low(TRVParaInfoBorderProperty)..High(TRVParaInfoBorderProperty)];
   GetSelectionBounds(rve, StartNo, EndNo);
   ParaNo := -1;
   if not rve.SelectionExists then
     IterateProc(rve.RVData, StartNo, rve, ParaNo)
   else
     IterateRVData(rve.RVData, rve, StartNo, EndNo, ParaNo);
end;

procedure TrvActionParaBorder.SetBorder(const Value: TRVBorder);
begin
  FBorder.Assign(Value);
end;

procedure TrvActionParaBorder.SetBackground(
  const Value: TRVBackgroundRect);
begin
  FBackground.Assign(Value);
end;

function TrvActionParaBorder.ContinueIteration(
  var CustomData: Integer): Boolean;
begin
  Result := ValidProperties<>[];
end;

procedure TrvActionParaBorder.IterateProc(RVData: TCustomRVData; ItemNo: Integer;
  rve: TCustomRichViewEdit; var CustomData: Integer);
var ParaNo: Integer;
    ParaInfo: TParaInfo;
    item: TCustomRVItemInfo;
begin
  item := RVData.GetItem(ItemNo);
  ParaNo := item.ParaNo;
  if ParaNo=CustomData then
    exit;
  ParaInfo   := rve.Style.ParaStyles[ParaNo];
  if CustomData=-1 then begin
    FBorder.Assign(ParaInfo.Border);
    FBackground.Assign(ParaInfo.Background);
    end
  else begin
    if ParaInfo.Border.Width<>FBorder.Width then
     Exclude(FValidProperties, rvpibBorder_Width);
    if ParaInfo.Border.Color<>FBorder.Color then
     Exclude(FValidProperties, rvpibBorder_Color);
    if ParaInfo.Background.Color<>FBackground.Color then
     Exclude(FValidProperties, rvpibBackground_Color);
    if ParaInfo.Border.Style<>FBorder.Style then
     Exclude(FValidProperties, rvpibBorder_Style);
    if ParaInfo.Border.InternalWidth<>FBorder.InternalWidth then
     Exclude(FValidProperties, rvpibBorder_InternalWidth);

    if ParaInfo.Border.BorderOffsets.Left<>FBorder.BorderOffsets.Left then
     Exclude(FValidProperties, rvpibBorder_BO_Left);
    if ParaInfo.Border.BorderOffsets.Top<>FBorder.BorderOffsets.Top then
     Exclude(FValidProperties, rvpibBorder_BO_Top);
    if ParaInfo.Border.BorderOffsets.Right<>FBorder.BorderOffsets.Right then
     Exclude(FValidProperties, rvpibBorder_BO_Right);
    if ParaInfo.Border.BorderOffsets.Bottom<>FBorder.BorderOffsets.Bottom then
     Exclude(FValidProperties, rvpibBorder_BO_Bottom);

    if ParaInfo.Background.BorderOffsets.Left<>FBackground.BorderOffsets.Left then
     Exclude(FValidProperties, rvpibBackground_BO_Left);
    if ParaInfo.Background.BorderOffsets.Top<>FBackground.BorderOffsets.Top then
     Exclude(FValidProperties, rvpibBackground_BO_Top);
    if ParaInfo.Background.BorderOffsets.Right<>FBackground.BorderOffsets.Right then
     Exclude(FValidProperties, rvpibBackground_BO_Right);
    if ParaInfo.Background.BorderOffsets.Bottom<>FBackground.BorderOffsets.Bottom then
     Exclude(FValidProperties, rvpibBackground_BO_Bottom);

    if ParaInfo.Border.VisibleBorders.Left<>FBorder.VisibleBorders.Left then
     Exclude(FValidProperties, rvpibBorder_Vis_Left);
    if ParaInfo.Border.VisibleBorders.Top<>FBorder.VisibleBorders.Top then
     Exclude(FValidProperties, rvpibBorder_Vis_Top);
    if ParaInfo.Border.VisibleBorders.Right<>FBorder.VisibleBorders.Right then
     Exclude(FValidProperties, rvpibBorder_Vis_Right);
    if ParaInfo.Border.VisibleBorders.Bottom<>FBorder.VisibleBorders.Bottom then
     Exclude(FValidProperties, rvpibBorder_Vis_Bottom);
  end;
  CustomData := ParaNo;
end;

{---------------------------- Misc --------------------------------------------}

{ TrvActionShowSpecialCharacters }

constructor TrvActionShowSpecialCharacters.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_ShowSpecialCharacters;
end;

procedure TrvActionShowSpecialCharacters.ExecuteTarget(Target: TObject);
var rve: TCustomRichViewEdit;
    Excl: Boolean;
begin
  rve := GetControl(Target);
  Excl := rvoShowSpecialCharacters in rve.Options;
  while rve<>nil do begin
    if Excl then
      rve.Options := rve.Options-[rvoShowSpecialCharacters, rvoShowHiddenText]
    else
      rve.Options := rve.Options+[rvoShowSpecialCharacters, rvoShowHiddenText];
    rve := TCustomRichViewEdit(rve.InplaceEditor);
  end;
  GetControl(Target).Reformat;  
end;

procedure TrvActionShowSpecialCharacters.UpdateTarget(Target: TObject);
begin
  inherited;
  Checked := rvoShowSpecialCharacters in GetControl(Target).Options;
end;

{ TrvActionColor }

constructor TrvActionColor.Create(AOwner: TComponent);
begin
  inherited;
  FColor := clWindow;
  FDefaultColor := clWindow;
  FMessageID := rvam_act_Color;
end;

procedure TrvActionColor.UpdateTarget(Target: TObject);
begin
  Enabled := RVA_ActionsEnabled and not Disabled and
    (RVA_UserInterface<>rvauiText) and (RVA_UserInterface<>rvauiRTF);
end;

procedure TrvActionColor.ExecuteCommand(rve: TCustomRichViewEdit;
  Command: Integer);
begin
  rve.Color := Color;
  if rvfoSaveBack in rve.RVFOptions then
    rve.Modified := True;
  RVA_Events.DoOnBackgroundChange(Self, rve);
end;

function TrvActionColor.GetCurrentColor(
  FEdit: TCustomRichViewEdit): TColor;
begin
  Result := FEdit.Color;
  if Result = clNone then
    Result := FEdit.Style.Color;
end;

{ TrvActionFillColor }

constructor TrvActionFillColor.Create(AOwner: TComponent);
begin
  inherited;
  FAllowApplyingTo := [rvafcaText..rvafcaTable];
  FMessageID := rvam_act_FillColor;
end;

procedure TrvActionFillColor.ExecuteTarget(Target: TObject);
var frm: TfrmRVFillColor;
    rvemain,rve: TCustomRichViewEdit;
    item: TCustomRVItemInfo;
    table: TRVTableItemInfo;
    r,c,cs,rs: Integer;
    StartNo, EndNo, Data: Integer;
    DefaultSet: Boolean;
    Color: TColor;
    TextAction: TrvActionFontBackColor;
    ParaAction: TrvActionParaColorAndPadding;
begin
  FTextColorSet := False;
  FTextColorMultiple := False;
  FParaColorSet := False;
  FParaColorMultiple := False;
  cs := 0;
  rs := 0;
  DefaultSet := False;

  Padding    := TRVRect.Create;
  UsePadding := TRVBooleanRect.Create(False);
  try
    frm := TfrmRVFillColor.Create(Application);
    try
      frm.ColorDialog := RVA_ColorDialog;
      rvemain := GetControl(Target);

      GetSelectionBounds(rvemain, StartNo, EndNo);
      IterateRVData(rvemain.RVData, rvemain, StartNo, EndNo, Data);
      if rvafcaText in FAllowApplyingTo then
        frm.XBoxItemsAddObject(frm._cmb, RVA_GetS(rvam_fillc_Text), TObject(4));
      if rvafcaParagraph in FAllowApplyingTo then
        frm.XBoxItemsAddObject(frm._cmb, RVA_GetS(rvam_fillc_Paragraph), TObject(3));
      table := nil;
      if rvemain.GetCurrentItemEx(TRVTableItemInfo, rve, item) then begin
        table := TRVTableItemInfo(item);
        if table.GetNormalizedSelectionBounds(True,r,c,cs,rs) then begin
          if rvafcaCell in FAllowApplyingTo then begin
            frm.XBoxItemsAddObject(frm._cmb, RVA_GetS(rvam_fillc_Cell), TObject(2));
            if (table.GetEditedCell(r,c)=nil) then begin
              if GetColorOfSelectedCells(table, Color) then begin
                frm.Indeterminate := False;
                frm.ChosenColor := Color;
              end;
              DefaultSet := True;
              frm.SetXBoxItemIndex(frm._cmb, 2);
            end;
          end;
        end;
        if rvafcaTable in FAllowApplyingTo then begin
          frm.XBoxItemsAddObject(frm._cmb, RVA_GetS(rvam_fillc_Table), TObject(1));
          if not table.GetNormalizedSelectionBounds(True,r,c,cs,rs) then begin
            frm.Indeterminate := False;
            frm.ChosenColor := table.Color;
            DefaultSet := True;
            frm.SetXBoxItemIndex(frm._cmb, frm.GetXBoxItemCount(frm._cmb)-1);
          end;
        end;
      end;
      if not DefaultSet then
        if rvemain.SelectionExists and (rvafcaText in FAllowApplyingTo) then begin
          frm.SetXBoxItemIndex(frm._cmb, 0);
          if FTextColorSet and not FTextColorMultiple then begin
            frm.Indeterminate := False;
            frm.ChosenColor := FTextColor
          end;
          end
        else if (rvafcaParagraph in FAllowApplyingTo) then begin
          if Integer(frm.GetXBoxObject(frm._cmb, 0))=3 then
            frm.SetXBoxItemIndex(frm._cmb, 0)
          else
            frm.SetXBoxItemIndex(frm._cmb, 1);
          if FParaColorSet and not FParaColorMultiple then begin
            frm.Indeterminate := False;
            frm.ChosenColor := FParaColor;
          end;
        end;
      frm.SetPadding(Padding, UsePadding, rvemain.Style);
      if frm.GetXBoxItemCount(frm._cmb)=0 then
        Beep
      else if (frm.ShowModal = mrOk) and not frm.Indeterminate then begin
        case Integer(frm.GetXBoxObject(frm._cmb, frm.GetXBoxItemIndex(frm._cmb))) of
           1:
             begin
               table.Color := frm.ChosenColor;
             end;
           2:
             begin
               SetColorToSelectedCells(rve, table, frm.ChosenColor);
             end;
           3:
             begin
               frm.GetPadding(Padding, UsePadding);
               ParaAction := TrvActionParaColorAndPadding.Create(nil);
               try
                 ParaAction.Control := GetControl(Target);
                 ParaAction.UserInterface := rvacNone;
                 ParaAction.Color := frm.ChosenColor;
                 ParaAction.Padding := Padding;
                 ParaAction.UsePadding := UsePadding;
                 ParaAction.Execute;
               finally
                 ParaAction.Free;
               end;
             end;
           4:
             begin
               TextAction := TrvActionFontBackColor.Create(nil);
               try
                 TextAction.Control := GetControl(Target);
                 TextAction.UserInterface := rvacNone;
                 TextAction.Color := frm.ChosenColor;
                 TextAction.Execute;
               finally
                 TextAction.Free;
               end;
             end;
        end;
      end;
    finally
      frm.Free;
    end;
  finally
    Padding.Free;
    UsePadding.Free;
    Padding := nil;
    UsePadding := nil;
  end;
end;

procedure TrvActionFillColor.IterateProc(RVData: TCustomRVData; ItemNo: Integer;
  rve: TCustomRichViewEdit; var CustomData: Integer);
var item: TCustomRVItemInfo;
begin
  item := RVData.GetItem(ItemNo);
  if item.StyleNo>=0 then
    if not FTextColorSet then begin
      FTextColor := rve.Style.TextStyles[item.StyleNo].BackColor;
      FTextColorSet := True;
      end
    else if FTextColor<>rve.Style.TextStyles[item.StyleNo].BackColor then
      FTextColorMultiple := True;

  if not FParaColorSet then
    with rve.Style.ParaStyles[item.ParaNo] do begin
      FParaColor := Background.Color;
      Padding.Assign(Background.BorderOffsets);
      UsePadding.SetAll(True);
      FParaColorSet  := True;
    end
  else if FParaColor<>rve.Style.ParaStyles[item.ParaNo].Background.Color then
    with rve.Style.ParaStyles[item.ParaNo] do begin
      FParaColorMultiple := True;
      if Padding.Left<>Background.BorderOffsets.Left then
        UsePadding.Left := False;
      if Padding.Right<>Background.BorderOffsets.Right then
        UsePadding.Right := False;
      if Padding.Top<>Background.BorderOffsets.Top then
        UsePadding.Top := False;
      if Padding.Bottom<>Background.BorderOffsets.Bottom then
        UsePadding.Bottom := False;
    end;
end;

function TrvActionFillColor.CanApplyToPlainText: Boolean;
begin
  Result := False;
end;


{ TrvActionInsertPageBreak }

constructor TrvActionInsertPageBreak.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_InsertPageBreak;
end;

procedure TrvActionInsertPageBreak.ExecuteTarget(Target: TObject);
begin
  GetControl(Target).InsertPageBreak;
end;

function TrvActionInsertPageBreak.RequiresMainDoc: Boolean;
begin
  Result := True;
end;

procedure TrvActionInsertPageBreak.UpdateTarget(Target: TObject);
var rve: TCustomRichViewEdit;
begin
  rve := GetControl(Target);
  Enabled := RVA_ActionsEnabled and not Disabled and (rve.InplaceEditor=nil);
end;

{ TrvActionRemovePageBreak }

constructor TrvActionRemovePageBreak.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_RemovePageBreak;
end;

procedure TrvActionRemovePageBreak.ExecuteTarget(Target: TObject);
begin
  GetControl(Target).TopLevelEditor.RemoveCurrentPageBreak;
end;

function TrvActionRemovePageBreak.RequiresMainDoc: Boolean;
begin
  Result := True;
end;

procedure TrvActionRemovePageBreak.UpdateTarget(Target: TObject);
var rve: TCustomRichViewEdit;
begin
  if not RVA_ActionsEnabled or Disabled then begin
    Enabled := False;
    exit;
  end;
  try
    rve := GetControl(Target).TopLevelEditor;
    Enabled := rve.PageBreaksBeforeItems[rve.CurItemNo];
  except
    Enabled := False;
  end;    
end;

{ TrvActionClearTextFlow }

function TrvActionClearTextFlow.ClearLeft: Boolean;
begin
  Result := False;
end;

function TrvActionClearTextFlow.ClearRight: Boolean;
begin
  Result := False;
end;

procedure TrvActionClearTextFlow.ExecuteTarget(Target: TObject);
var rve: TCustomRichViewEdit;
begin
  rve := GetControl(Target).TopLevelEditor;
  rve.ClearTextFlow(ClearLeft, ClearRight);
end;

procedure TrvActionClearTextFlow.UpdateTarget(Target: TObject);
var rve: TCustomRichViewEdit;
    StartNo, StartOffs, EndNo, EndOffs: Integer;
begin
  rve := GetControl(Target).TopLevelEditor;
  Enabled := RVA_ActionsEnabled and not Disabled and (rve.RVData.PartialSelectedItem=nil) and
    (RVA_UserInterface<>rvauiText);
  if not Enabled then
    Checked := False
  else begin
    rve.RVData.GetSelectionBoundsEx(StartNo, StartOffs, EndNo, EndOffs, True);
    rve.RVData.ExpandToParaSection(StartNo, EndNo, StartNo, EndNo);
    Checked := (rve.ClearLeft[StartNo]=ClearLeft) and (rve.ClearRight[StartNo]=ClearRight);
  end;
end;

{ TrvActionClearLeft }

function TrvActionClearLeft.ClearLeft: Boolean;
begin
  Result := True;
end;

constructor TrvActionClearLeft.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_ClearLeft;
end;

{ TrvActionClearRight }

function TrvActionClearRight.ClearRight: Boolean;
begin
  Result := True;
end;

constructor TrvActionClearRight.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_ClearRight;
end;

{ TrvActionClearNone }

constructor TrvActionClearNone.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_ClearNone;
end;

{ TrvActionClearBoth }

function TrvActionClearBoth.ClearLeft: Boolean;
begin
  Result := True;
end;

function TrvActionClearBoth.ClearRight: Boolean;
begin
  Result := True;
end;

constructor TrvActionClearBoth.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_ClearBoth;
end;

{ TrvItemProperties }

constructor TrvActionItemProperties.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_ItemProperties;
end;

procedure TrvActionItemProperties.ExecuteTarget(Target: TObject);
var frm: TfrmRVItemProp;
    rve: TCustomRichViewEdit;
    DoDefault: Boolean;
begin
  rve := GetControl(Target);
  if Assigned(OnCustomItemPropertiesDialog) then begin
    DoDefault := True;
    OnCustomItemPropertiesDialog(Self, rve, DoDefault);
    if not DoDefault then
      exit;
  end;
  frm := TfrmRVItemProp.Create(Application);
  try
    frm.ColorDialog := RVA_ColorDialog;
    frm.Filter := GraphicFilter;
    frm.BackgroundFilter := BackgroundGraphicFilter;
    frm.StoreImageFileName := StoreImageFileName;
    if frm.SetItem(rve) and (frm.ShowModal=mrOk) then begin
      frm.GetItem(rve);
    end;
  finally
    frm.Free;
  end;
end;

procedure TrvActionItemProperties.UpdateTarget(Target: TObject);
var rve: TCustomRichViewEdit;
    item: TCustomRVItemInfo;
    en: Boolean;
begin
  if not RVA_ActionsEnabled or Disabled or (RVA_UserInterface=rvauiText) then begin
    Enabled := False;
    exit;
  end;
  try
    rve := GetControl(Target).TopLevelEditor;
    en := not rve.SelectionExists;
    if en or (rve.GetCurrentItem=GetSelectedItem(rve)) then begin
      item := rve.GetCurrentItem;
      en := (item is TRVGraphicItemInfo) or (item is TRVBreakItemInfo) or
            (item is TRVTableItemInfo);
      if not en and Assigned(OnCanApply) and Assigned(OnCustomItemPropertiesDialog) then
        OnCanApply(Self, rve.GetRootEditor, item, en);
    end;
    Enabled := en;
  except
    Enabled := False;
  end;
end;

{ TrvActionVAlign }

constructor TrvActionVAlign.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FMessageID := rvam_act_VAlign;
end;

procedure TrvActionVAlign.ExecuteTarget(Target: TObject);
var rve: TCustomRichViewEdit;
    item: TCustomRVItemInfo;
    ItemNo: Integer;
    frm: TfrmRVObjectAlign;
begin
  rve := GetControl(Target).TopLevelEditor;
  if rve.SelectionExists then
    item := GetSelectedItem(rve)
  else
    item := rve.GetCurrentItem;
  if item=nil then
    exit;
  ItemNo := rve.GetItemNo(item);
  frm := TfrmRVObjectAlign.Create(Application);
  try
    frm.SetVAlign(rve.GetItemVAlign(ItemNo));
    if frm.ShowModal = mrOk then
      rve.SetItemVAlignEd(ItemNo, frm.GetVAlign);    
  finally
    frm.Free;
  end;
end;

procedure TrvActionVAlign.UpdateTarget(Target: TObject);
var rve: TCustomRichViewEdit;
    item: TCustomRVItemInfo;
begin
  if not RVA_ActionsEnabled or Disabled or (RVA_UserInterface in [rvauiRTF, rvauiText]) then begin
    Enabled := False;
    exit;
  end;
  try
    rve := GetControl(Target).TopLevelEditor;
    if rve.SelectionExists then
      item := GetSelectedItem(rve)
    else
      item := rve.GetCurrentItem;
    Enabled := (item<>nil) and (item is TRVRectItemInfo)
       {$IFNDEF RVDONOTUSELISTS}and not (item is TRVMarkerItemInfo){$ENDIF}
      {$IFNDEF RVDONOTUSETABS}and not (item is TRVTabItemInfo){$ENDIF}
      {$IFNDEF RVDONOTUSESEQ}and not (item is TCustomRVNoteItemInfo){$ENDIF}
  except
    Enabled := False;
  end;
end;

{ TrvActionBackground }

constructor TrvActionBackground.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_Background;
  CanChangeMargins := True;
end;

procedure TrvActionBackground.ExecuteTarget(Target: TObject);
var frm: TfrmRVBack;
    rve: TCustomRichViewEdit;
begin
  frm := TfrmRVBack.Create(Application);
  try
    rve := GetControl(Target);
    frm.Init(rve, RVA_ColorDialog, Self, CanChangeMargins);
    if frm.ShowModal=mrOk then begin
      frm.GetResult(rve);
      FImageFileName := frm.ImageFileName;
      if Assigned(FOnChange) then
        FOnChange(Self, rve);
      RVA_Events.DoOnBackgroundChange(Self, rve);
    end;
  finally
    frm.Free;
  end;
end;

procedure TrvActionBackground.UpdateTarget(Target: TObject);
begin
  Enabled := RVA_ActionsEnabled and not Disabled and
    (RVA_UserInterface<>rvauiText) and (RVA_UserInterface<>rvauiRTF);
end;

{-------------------------------- Tables --------------------------------------}

{ TrvActionInsertTable }

procedure TrvActionInsertTable.ApplyToTable(table: TRVTableItemInfo;
  ABestWidth: TRVHTMLLength);
var RVStyle: TRVStyle;
begin
  RVStyle := table.GetRVStyle;
  if ABestWidth<=0 then
    table.BestWidth := ABestWidth
  else
    table.BestWidth := RVStyle.DifferentUnitsToUnits(ABestWidth, RVA_UnitsProgram);
  table.Options              := TableOptions;
  table.PrintOptions         := TablePrintOptions;
  table.Color                := Color;
  table.BorderWidth          := RVStyle.DifferentUnitsToUnits(BorderWidth, RVA_UnitsProgram);
  table.BorderColor          := BorderColor;
  table.BorderLightColor     := BorderLightColor;
  table.BorderStyle          := BorderStyle;
  table.BorderVSpacing       := RVStyle.DifferentUnitsToUnits(BorderVSpacing, RVA_UnitsProgram);
  table.BorderHSpacing       := RVStyle.DifferentUnitsToUnits(BorderHSpacing, RVA_UnitsProgram);
  table.CellBorderWidth      := RVStyle.DifferentUnitsToUnits(CellBorderWidth, RVA_UnitsProgram);
  table.CellBorderColor      := CellBorderColor;
  table.CellBorderLightColor := CellBorderLightColor;
  table.CellPadding          := RVStyle.DifferentUnitsToUnits(CellPadding, RVA_UnitsProgram);
  table.CellBorderStyle      := CellBorderStyle;
  table.VRuleWidth           := RVStyle.DifferentUnitsToUnits(VRuleWidth, RVA_UnitsProgram);
  table.VRuleColor           := VRuleColor;
  table.HRuleWidth           := RVStyle.DifferentUnitsToUnits(HRuleWidth, RVA_UnitsProgram);
  table.HRuleColor           := HRuleColor;
  table.CellVSpacing         := RVStyle.DifferentUnitsToUnits(CellVSpacing, RVA_UnitsProgram);
  table.CellHSpacing         := RVStyle.DifferentUnitsToUnits(CellHSpacing, RVA_UnitsProgram);
  table.VOutermostRule       := VOutermostRule;
  table.HOutermostRule       := HOutermostRule;
  table.HeadingRowCount      := HeadingRowCount;
end;

constructor TrvActionInsertTable.Create(AOwner: TComponent);
begin
  inherited;
  RowCount             := 2;
  ColCount             := 2;
  TableOptions         := RVTABLEDEFAULTOPTIONS;
  TablePrintOptions    := RVTABLEDEFAULTPRINTOPTIONS;
  Color                := clNone;
  BorderWidth          := 1;
  BorderColor          := clWindowText;
  BorderLightColor     := clBtnHighlight;
  BorderStyle          := rvtbColor;
  BorderVSpacing       := 2;
  BorderHSpacing       := 2;
  CellBorderWidth      := 1;
  CellBorderColor      := clWindowText;
  CellBorderLightColor := clBtnHighlight;
  CellPadding          := 1;
  CellBorderStyle      := rvtbColor;
  VRuleColor           := clWindowText;
  HRuleColor           := clWindowText;
  CellVSpacing         := 2;
  CellHSpacing         := 2;
  FMessageID           := rvam_act_InsertTable;
end;

destructor TrvActionInsertTable.Destroy;
begin
  if FTableSizeForm<>nil then
    FTableSizeForm.OnDestroy := nil;
  inherited;
end;

procedure TrvActionInsertTable.ExecuteTarget(Target: TObject);
var
  tbl: TRVTableItemInfo;
  frm: TfrmInsTable;
begin
  frm := TfrmInsTable.Create(Application);
  try
    frm.Rows := RowCount;
    frm.Columns := ColCount;
    frm.BestWidth := BestWidth;
    frm.OptimalBestWidth := TRVStyle.PixelsToUnitsEx(
      GetControl(Target).TopLevelEditor.RVData.TextWidth-10, RVA_UnitsProgram);
    if frm.ShowModal = mrOk then begin
      if frm.GetCheckBoxChecked(frm._cbRemember) then begin
        BestWidth := frm.BestWidth;
        RowCount  := frm.Rows;
        ColCount  := frm.Columns;
      end;
      tbl := TRVTableItemInfo.CreateEx(frm.Rows, frm.Columns, GetControl(Target).RVData);
      ApplyToTable(tbl, frm.BestWidth);
      SetTableCellsWidth(tbl,
        GetControl(Target).Style.PixelsToUnits(
          GetControl(Target).TopLevelEditor.RVData.TextWidth-10));
      if Assigned(OnInserting) then
        OnInserting(Self, tbl);
      if GetControl(Target).InsertItem(ItemText, tbl) then
        tbl.EditCell(0,0);
    end;
  finally
    frm.Free;
  end;
end;

procedure TrvActionInsertTable.ShowTableSizeDialog(Target: TCustomRichViewEdit;
  Button: TControl);
var frm: TfrmRVTableSize;
begin
  UpdateTarget(Target);
  if not Enabled then
    exit;
  if FTableSizeForm<>nil then
    FTableSizeForm.Free;
  FEdit := GetControl(Target);
  FEdit.FreeNotification(Self);
  frm := TfrmRVTableSize.Create(Application);
  FTableSizeForm := frm;
  frm.Init(RVA_GetS(rvam_btn_Cancel), RVA_DialogFontName, RVA_GetCharset);
  frm.OnDestroy := TableSizeFormDestroy;
  if Button=nil then
    frm.PopupAtMouse
  else
    frm.PopupAtControl(Button);
end;

procedure TrvActionInsertTable.ShowTableSizeDialog(Target: TCustomRichViewEdit;
  const ButtonRect: TRect);
var frm: TfrmRVTableSize;
begin
  UpdateTarget(Target);
  if not Enabled then
    exit;
  if FTableSizeForm<>nil then
    FTableSizeForm.Free;
  FEdit := GetControl(Target);
  FEdit.FreeNotification(Self);
  frm := TfrmRVTableSize.Create(Application);
  FTableSizeForm := frm;
  frm.Init(RVA_GetS(rvam_btn_Cancel), RVA_DialogFontName, RVA_GetCharset);
  frm.OnDestroy := TableSizeFormDestroy;
  frm.PopupAt(ButtonRect);
end;

procedure TrvActionInsertTable.TableSizeFormDestroy(Sender: TObject);
var tbl: TRVTableItemInfo;
begin
  if not TfrmRVTableSize(Sender).Cancelled then begin
    tbl := TRVTableItemInfo.CreateEx(TfrmRVTableSize(Sender).grid.Row+1,
      TfrmRVTableSize(Sender).grid.Col+1, FEdit.RVData);
    ApplyToTable(tbl, BestWidth);
    SetTableCellsWidth(tbl, FEdit.Style.PixelsToUnits(FEdit.TopLevelEditor.RVData.TextWidth-10));
    if Assigned(OnInserting) then
      OnInserting(Self, tbl);
    if FEdit.InsertItem(ItemText, tbl) then
      tbl.EditCell(0,0);
  end;
  FTableSizeForm := nil;
  {$IFDEF RICHVIEWDEF5}
  if FEdit <> nil then
    FEdit.RemoveFreeNotification(Self);
  {$ENDIF}
  FEdit := nil;
  if Assigned(OnCloseTableSizeDialog) then
    OnCloseTableSizeDialog(Self);
end;

procedure TrvActionInsertTable.SetTableCellsWidth(table: TRVTableItemInfo;
  Width: TRVStyleLength);
var r,c: Integer;
begin
  if table.BestWidth<>0 then
    exit;
  dec(Width, ((table.BorderWidth+table.BorderHSpacing)*2+(table.CellHSpacing*(table.Rows[0].Count-1)))+
            table.Rows[0].Count*table.CellBorderWidth*2);
  Width := Width div table.Rows[0].Count;
  for r := 0 to table.Rows.Count-1 do
    for c := 0 to table.Rows[r].Count-1 do
      table.Cells[r,c].BestWidth := Width;
end;

procedure TrvActionInsertTable.UpdateTarget(Target: TObject);
begin
  if not RVA_ActionsEnabled or Disabled or (RVA_UserInterface=rvauiText) then begin
    Enabled := False;
    exit;
  end;
  Enabled := GetControl(Target).TopLevelEditor.RVData.PartialSelectedItem=nil;
end;

procedure TrvActionInsertTable.Notification(AComponent: TComponent;
  Operation: TOperation);
begin
  inherited Notification(AComponent, Operation);
  if (Operation = opRemove) and (AComponent = FEdit) then
    FEdit := nil;
end;

procedure TrvActionInsertTable.Localize;
begin
  Caption := {$IFDEF USERVTNT}_GetWideString{$ENDIF}(RVA_GetS(rvam_act_InsertTable));
  Hint    := {$IFDEF USERVTNT}_GetWideString{$ENDIF}(RVA_GetS(rvam_act_InsertTableH));
end;

procedure TrvActionInsertTable.ConvertToPixels;
begin
  if BestWidth>0 then
    BestWidth := TRVStyle.GetAsPixelsEx(BestWidth, RVA_UnitsProgram);
  BorderWidth     := TRVStyle.GetAsPixelsEx(BorderWidth, RVA_UnitsProgram);
  BorderVSpacing  := TRVStyle.GetAsPixelsEx(BorderVSpacing, RVA_UnitsProgram);
  BorderHSpacing  := TRVStyle.GetAsPixelsEx(BorderHSpacing, RVA_UnitsProgram);
  CellBorderWidth := TRVStyle.GetAsPixelsEx(CellBorderWidth, RVA_UnitsProgram);
  CellPadding     := TRVStyle.GetAsPixelsEx(CellPadding, RVA_UnitsProgram);
  VRuleWidth      := TRVStyle.GetAsPixelsEx(VRuleWidth, RVA_UnitsProgram);
  HRuleWidth      := TRVStyle.GetAsPixelsEx(HRuleWidth, RVA_UnitsProgram);
  CellVSpacing    := TRVStyle.GetAsPixelsEx(CellVSpacing, RVA_UnitsProgram);
  CellHSpacing    := TRVStyle.GetAsPixelsEx(CellHSpacing, RVA_UnitsProgram);
end;

procedure TrvActionInsertTable.ConvertToTwips;
begin
  if BestWidth>0 then
    BestWidth := TRVStyle.GetAsTwipsEx(BestWidth, RVA_UnitsProgram);
  BorderWidth     := TRVStyle.GetAsTwipsEx(BorderWidth, RVA_UnitsProgram);
  BorderVSpacing  := TRVStyle.GetAsTwipsEx(BorderVSpacing, RVA_UnitsProgram);
  BorderHSpacing  := TRVStyle.GetAsTwipsEx(BorderHSpacing, RVA_UnitsProgram);
  CellBorderWidth := TRVStyle.GetAsTwipsEx(CellBorderWidth, RVA_UnitsProgram);
  CellPadding     := TRVStyle.GetAsTwipsEx(CellPadding, RVA_UnitsProgram);
  VRuleWidth      := TRVStyle.GetAsTwipsEx(VRuleWidth, RVA_UnitsProgram);
  HRuleWidth      := TRVStyle.GetAsTwipsEx(HRuleWidth, RVA_UnitsProgram);
  CellVSpacing    := TRVStyle.GetAsTwipsEx(CellVSpacing, RVA_UnitsProgram);
  CellHSpacing    := TRVStyle.GetAsTwipsEx(CellHSpacing, RVA_UnitsProgram);
end;

{ TrvActionTableCell }

procedure TrvActionTableCell.ExecuteTarget(Target: TObject);
var
  Data: Integer;
  rve, rvemain: TCustomRichViewEdit;
  item: TCustomRVItemInfo;
  ItemNo: Integer;
  table: TRVTableItemInfo;
begin
  rvemain := GetControl(Target);
  if not rvemain.CanChange or
     not rvemain.GetCurrentItemEx(TRVTableItemInfo, rve, item) then
    exit;
  table := TRVTableItemInfo(item);
  ItemNo := table.GetMyItemNo;
  rve.BeginItemModify(ItemNo, Data);
  if not ExecuteCommand(rve, table, ItemNo) then
    exit;
  rve.EndItemModify(ItemNo, Data);
  rve.Change;
end;

procedure TrvActionTableCell.UpdateTarget(Target: TObject);
var
  rve, rvemain: TCustomRichViewEdit;
  item: TCustomRVItemInfo;
  ItemNo: Integer;
  table: TRVTableItemInfo;
begin
  if not RVA_ActionsEnabled or Disabled or (RVA_UserInterface=rvauiText) then begin
    Enabled := False;
    exit;
  end;
  try
    rvemain := GetControl(Target);
    if not HandlesTarget(Target) or not rvemain.GetCurrentItemEx(TRVTableItemInfo, rve, item) then begin
      Enabled := False;
      exit;
    end;
    table := TRVTableItemInfo(item);
    ItemNo := table.GetMyItemNo;
    Enabled := IsApplicable(rve, table, ItemNo);
  except
    Enabled := False;
  end;    
end;

{ TrvActionTableInsertRC }

function TrvActionTableRCBase.IsApplicable(rve: TCustomRichViewEdit;
  table: TRVTableItemInfo; ItemNo: Integer): Boolean;
var r,c,cs,rs: Integer;
begin
  Result := table.GetNormalizedSelectionBounds(True,r,c,cs,rs);
end;

{ TrvActionTableInsertRowsAbove }

constructor TrvActionTableInsertRowsAbove.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_TableInsertRowsAbove;
end;

function TrvActionTableInsertRowsAbove.ExecuteCommand(
  rve: TCustomRichViewEdit; table: TRVTableItemInfo; ItemNo: Integer): Boolean;
begin
  table.InsertRowsAbove(1);
  Result := True;
end;

{ TrvActionTableInsertRowsBelow }

constructor TrvActionTableInsertRowsBelow.Create(AOwner: TComponent);
begin
  inherited;
  AllowMultiple := True;
  FMessageID := rvam_act_TableInsertRowsBelow;
end;

function TrvActionTableInsertRowsBelow.ExecuteCommand(
  rve: TCustomRichViewEdit; table: TRVTableItemInfo;
  ItemNo: Integer): Boolean;
var r,c,cs,rs, Count: Integer;
begin
  Result := False;
  Count := 1;
  if AllowMultiple then begin
    if not table.GetNormalizedSelectionBounds(True, r,c,cs,rs) then
      exit;
    if r+rs=table.Rows.Count then
      if not GetInteger(RVA_GetS(rvam_ar_Title), RVA_GetS(rvam_ar_Prompt), Count) then
        exit;
  end;
  table.InsertRowsBelow(Count);
  Result := True;
end;

{ TrvActionTableInsertColLeft }

constructor TrvActionTableInsertColLeft.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_TableInsertColsLeft;
end;

function TrvActionTableInsertColLeft.ExecuteCommand(
  rve: TCustomRichViewEdit; table: TRVTableItemInfo;
  ItemNo: Integer): Boolean;
begin
  table.InsertColsLeft(1);
  Result := True;
end;

{ TrvActionTableInsertColRight }

constructor TrvActionTableInsertColRight.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_TableInsertColsRight;
end;

function TrvActionTableInsertColRight.ExecuteCommand(
  rve: TCustomRichViewEdit; table: TRVTableItemInfo;
  ItemNo: Integer): Boolean;
begin
  table.InsertColsRight(1);
  Result := True;
end;

{ TrvActionTableDeleteRows }

constructor TrvActionTableDeleteRows.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_TableDeleteRows;
end;

function TrvActionTableDeleteRows.ExecuteCommand(rve: TCustomRichViewEdit;
  table: TRVTableItemInfo; ItemNo: Integer): Boolean;
var r,c,cs,rs: Integer;
begin
  table.GetNormalizedSelectionBounds(True,r,c,cs,rs);
  if rs=table.Rows.Count then begin
    // deleting whole table
    rve.SetSelectionBounds(ItemNo,0,ItemNo,1);
    rve.DeleteSelection;
    Result := False;
    exit;
  end;
  rve.BeginUndoGroup(rvutModifyItem);
  rve.SetUndoGroupMode(True);
  table.DeleteSelectedRows;
  table.DeleteEmptyRows;
  table.DeleteEmptyCols;
  rve.SetUndoGroupMode(False);
  Result := True;
end;

{ TrvActionTableDeleteCols }

constructor TrvActionTableDeleteCols.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_TableDeleteCols;
end;

function TrvActionTableDeleteCols.ExecuteCommand(rve: TCustomRichViewEdit;
  table: TRVTableItemInfo; ItemNo: Integer): Boolean;
var r,c,cs,rs: Integer;
begin
  table.GetNormalizedSelectionBounds(True,r,c,cs,rs);
  if cs=table.Rows[0].Count then begin
    // deleting whole table
    rve.SetSelectionBounds(ItemNo,0,ItemNo,1);
    rve.DeleteSelection;
    Result := False;
    exit;
  end;
  rve.BeginUndoGroup(rvutModifyItem);
  rve.SetUndoGroupMode(True);
  table.DeleteSelectedCols;
  table.DeleteEmptyRows;
  table.DeleteEmptyCols;
  rve.SetUndoGroupMode(False);
  Result := True;
end;

{ TrvActionTableMergeCells }

constructor TrvActionTableMergeCells.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_TableMergeCells;
end;

function TrvActionTableMergeCells.ExecuteCommand(rve: TCustomRichViewEdit;
  table: TRVTableItemInfo; ItemNo: Integer): Boolean;
var r,c,cs,rs: Integer;
    sel: Boolean;
begin
  rve.BeginUndoGroup(rvutModifyItem);
  rve.SetUndoGroupMode(True);
  try
    sel := table.GetNormalizedSelectionBounds(True,r,c,cs,rs);
    table.MergeSelectedCells(True);
    table.DeleteEmptyRows;
    table.DeleteEmptyCols;
    if sel then
      table.Select(r,c,0,0);
  finally
    rve.SetUndoGroupMode(False);
  end;
  Result := True;
end;

function TrvActionTableMergeCells.IsApplicable(rve: TCustomRichViewEdit;
  table: TRVTableItemInfo; ItemNo: Integer): Boolean;
begin
  Result := table.CanMergeSelectedCells(True);
end;

{ TrvActionTableSplitCells }

constructor TrvActionTableSplitCells.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_TableSplitCells;
end;

function TrvActionTableSplitCells.ExecuteCommand(rve: TCustomRichViewEdit;
  table: TRVTableItemInfo; ItemNo: Integer): Boolean;
var frm: TfrmRVSplit;
begin
  frm := TfrmRVSplit.Create(Application);
  try
    frm._cbUnmergeRows.Enabled := CanUnmergeRows(table);
    frm._cbUnmergeCols.Enabled := CanUnmergeCols(table);
    frm.SetCheckBoxChecked(frm._cbUnmergeRows, frm._cbUnmergeRows.Enabled);
    frm.SetCheckBoxChecked(frm._cbUnmergeCols, frm._cbUnmergeCols.Enabled);
    frm._rbUnmerge.Enabled :=
      frm.GetCheckBoxChecked(frm._cbUnmergeRows) or frm.GetCheckBoxChecked(frm._cbUnmergeCols);
    frm._cbMerge.Enabled := table.CanMergeSelectedCells(True);
    Result := frm.ShowModal=mrOk;
    if Result then begin
      if frm.GetRadioButtonChecked(frm._rbSplit) then begin
        rve.BeginUndoGroup(rvutModifyItem);
        rve.SetUndoGroupMode(True);
        try
          if frm.GetCheckBoxChecked(frm._cbMerge) then
            table.MergeSelectedCells(True);
          if frm.seColumns.Value>1 then
            table.SplitSelectedCellsVertically(frm.seColumns.AsInteger);
          if frm.seRows.Value>1 then
            table.SplitSelectedCellsHorizontally(frm.seRows.AsInteger);
          table.DeleteEmptyRows;
          table.DeleteEmptyCols;
        finally
          rve.SetUndoGroupMode(False);
        end;
        end
      else begin
        table.UnmergeSelectedCells(frm.GetCheckBoxChecked(frm._cbUnmergeRows),
          frm.GetCheckBoxChecked(frm._cbUnmergeCols));
      end;
    end;
  finally
    frm.Free;
  end;
end;


function TrvActionTableSplitCells.IsApplicable(rve: TCustomRichViewEdit;
  table: TRVTableItemInfo; ItemNo: Integer): Boolean;
var r,c,cs,rs: Integer;
begin
  Result := table.GetNormalizedSelectionBounds(True,r,c,cs,rs);
  if Result then begin
    table.Rows.GetMainCell(r,c,r,c);
    Result := (cs = table.Cells[r,c].ColSpan) and
              (rs = table.Cells[r,c].RowSpan);
    Result := Result or table.CanMergeSelectedCells(True);
  end;
end;

{ TrvActionTableSelectTable }

constructor TrvActionTableSelectTable.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_TableSelectTable;
end;

function TrvActionTableSelectTable.ExecuteCommand(rve: TCustomRichViewEdit;
  table: TRVTableItemInfo; ItemNo: Integer): Boolean;
begin
  table.SelectRows(0, table.Rows.Count);
  Result := False;
end;

function TrvActionTableSelectTable.IsApplicable(rve: TCustomRichViewEdit;
  table: TRVTableItemInfo; ItemNo: Integer): Boolean;
begin
  Result := True;
end;

{ TrvActionTableSelectRows }

constructor TrvActionTableSelectRows.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_TableSelectRows;
end;

function TrvActionTableSelectRows.ExecuteCommand(rve: TCustomRichViewEdit;
  table: TRVTableItemInfo; ItemNo: Integer): Boolean;
var r,c,cs,rs: Integer;
begin
  if table.GetNormalizedSelectionBounds(True,r,c,cs,rs) then
    table.SelectRows(r,rs);
  Result := False;
end;

{ TrvActionTableSelectCols }

constructor TrvActionTableSelectCols.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_TableSelectCols;
end;

function TrvActionTableSelectCols.ExecuteCommand(rve: TCustomRichViewEdit;
  table: TRVTableItemInfo; ItemNo: Integer): Boolean;
var r,c,cs,rs: Integer;
begin
  if table.GetNormalizedSelectionBounds(True,r,c,cs,rs) then
    table.SelectCols(c,cs);
  Result := False;
end;

{ TrvActionTableSelectCell }

constructor TrvActionTableSelectCell.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_TableSelectCell;
end;

function TrvActionTableSelectCell.ExecuteCommand(rve: TCustomRichViewEdit;
  table: TRVTableItemInfo; ItemNo: Integer): Boolean;
var r,c: Integer;
begin
  if table.GetEditedCell(r,c)<>nil then
    table.Select(r,c,0,0);
  Result := False;
end;

function TrvActionTableSelectCell.IsApplicable(rve: TCustomRichViewEdit;
  table: TRVTableItemInfo; ItemNo: Integer): Boolean;
var r,c: Integer;
begin
  Result := table.GetEditedCell(r,c)<>nil;
end;

{ TrvActionTableDeleteTable }

constructor TrvActionTableDeleteTable.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_TableDeleteTable;
end;

function TrvActionTableDeleteTable.ExecuteCommand(rve: TCustomRichViewEdit;
  table: TRVTableItemInfo; ItemNo: Integer): Boolean;
begin
  rve.SetSelectionBounds(ItemNo,0,ItemNo,1);
  rve.DeleteSelection;
  Result := False;
end;

function TrvActionTableDeleteTable.IsApplicable(rve: TCustomRichViewEdit;
  table: TRVTableItemInfo; ItemNo: Integer): Boolean;
begin
  Result := True;
end;

{ TrvActionTableMultiCellAttributes }

function TrvActionTableMultiCellAttributes.IterateCellProc(
  table: TRVTableItemInfo; FirstCell: Boolean; Row, Col, CustomData: Integer): Boolean;
begin
  Result := True;
end;

procedure TrvActionTableMultiCellAttributes.IterateCells(
  table: TRVTableItemInfo; CustomData: Integer);
var r,c: Integer;
    FirstTime: Boolean;
    EditedCell: TRVTableCellData;
begin
  FirstTime := True;
  if table.GetEditedCell(r,c)<>nil then
    EditedCell := table.Cells[r,c]
  else
    EditedCell := nil;
  for r := 0 to table.Rows.Count-1 do
    for c := 0 to table.Rows[r].Count-1 do
      if (table.Cells[r,c]<>nil) and
         (table.IsCellSelected(r,c) or (table.Cells[r,c]=EditedCell)) then begin
        if not IterateCellProc(table, FirstTime, r, c, CustomData) then
          exit;
        FirstTime := False;
      end;
end;

{ TrvActionTableCellVAlign }

function TrvActionTableCellVAlign.ExecuteCommand(rve: TCustomRichViewEdit;
  table: TRVTableItemInfo; ItemNo: Integer): Boolean;
begin
  rve.BeginUndoGroup(rvutModifyItem);
  rve.SetUndoGroupMode(True);
  IterateCells(table, 2);
  rve.SetUndoGroupMode(False);
  Result := True;  
end;

function TrvActionTableCellVAlign.IsApplicable(rve: TCustomRichViewEdit;
  table: TRVTableItemInfo; ItemNo: Integer): Boolean;
var r,c,rs,cs: Integer;
begin
  Result := table.GetNormalizedSelectionBounds(True, r,c,cs,rs);
  if Result then begin
    FAllEqual := True;
    IterateCells(table, 1);
    Checked := FAllEqual;
  end;
end;

function TrvActionTableCellVAlign.IterateCellProc(table: TRVTableItemInfo;
  FirstCell: Boolean; Row, Col, CustomData: Integer): Boolean;
begin
  Result := True;
  case CustomData of
    1:
      begin
        FAllEqual := table.Cells[Row,Col].VAlign=FVAlign;
        Result := FAllEqual;
      end;
    2:
      begin
        table.SetCellVAlign(FVAlign, Row, Col);
      end;
  end;
end;

{ TrvActionTableCellVAlignTop }

constructor TrvActionTableCellVAlignTop.Create(AOwner: TComponent);
begin
  inherited;
  FVAlign := rvcTop;
  FMessageID := rvam_act_TableCellVAlignTop;
end;

{ TrvActionTableCellVAlignMiddle }

constructor TrvActionTableCellVAlignMiddle.Create(AOwner: TComponent);
begin
  inherited;
  FVAlign := rvcMiddle;
  FMessageID := rvam_act_TableCellVAlignMiddle;  
end;

{ TrvActionTableCellVAlignBottom }

constructor TrvActionTableCellVAlignBottom.Create(AOwner: TComponent);
begin
  inherited;
  FVAlign := rvcBottom;
  FMessageID := rvam_act_TableCellVAlignBottom;
end;

{ TrvActionTableCellVAlignDefault }

constructor TrvActionTableCellVAlignDefault.Create(AOwner: TComponent);
begin
  inherited;
  FVAlign := rvcVDefault;
  FMessageID := rvam_act_TableCellVAlignDefault;
end;


{ TrvActionTableProperties }

constructor TrvActionTableProperties.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID :=   rvam_act_TableProperties;
end;

function TrvActionTableProperties.ExecuteCommand(rve: TCustomRichViewEdit;
  table: TRVTableItemInfo; ItemNo: Integer): Boolean;
var frm: TfrmRVItemProp;
begin
  frm := TfrmRVItemProp.Create(Application);
  try
    frm.ColorDialog := RVA_ColorDialog;
    frm.SetTable(table, False);
    frm.BackgroundFilter := BackgroundGraphicFilter;
    frm.StoreImageFileName := StoreImageFileName;
    Result := frm.ShowModal=mrOk;
    if Result then begin
      rve.BeginUndoGroup(rvutModifyItem);
      rve.SetUndoGroupMode(True);
      try
        frm.GetTable(rve, table);
      finally
        rve.SetUndoGroupMode(False);
      end;
    end;
  finally
    frm.Free;
  end;
end;


function TrvActionTableProperties.IsApplicable(rve: TCustomRichViewEdit;
  table: TRVTableItemInfo; ItemNo: Integer): Boolean;
begin
  Result := True;
end;

{ TrvActionTableGrid }

constructor TrvActionTableGrid.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_TableGrid;
end;

procedure TrvActionTableGrid.ExecuteTarget(Target: TObject);
begin
  if RichViewTableGridStyle=psClear then
    RichViewTableGridStyle := RVA_TableGridStyle
  else
    RichViewTableGridStyle := psClear;
  RepaintRichViews;
end;

function TrvActionTableGrid.HandlesTarget(Target: TObject): Boolean;
begin
  Result := True;
end;

procedure TrvActionTableGrid.UpdateTarget(Target: TObject);
begin
  Enabled := not Disabled;
  Checked := RichViewTableGridStyle<>psClear;
end;


{ TrvActionTableCellBorder }

function TrvActionTableCellBorder.ExecuteCommand(rve: TCustomRichViewEdit;
  table: TRVTableItemInfo; ItemNo: Integer): Boolean;
begin
  rve.BeginUndoGroup(rvutModifyItem);
  rve.SetUndoGroupMode(True);
  try
    if Checked then
      IterateCells(table, 3)
    else
      IterateCells(table, 2);
  finally
    rve.SetUndoGroupMode(False);
  end;
  Result := True;
end;

function TrvActionTableCellBorder.IsApplicable(rve: TCustomRichViewEdit;
  table: TRVTableItemInfo; ItemNo: Integer): Boolean;
var r,c,rs,cs: Integer;
begin
  if table.CellBorderWidth=0 then begin
    Result := False;
    Checked := False;
    exit;
  end;
  Result := table.GetNormalizedSelectionBounds(True, r,c,cs,rs);
  if Result then begin
    FAllEqual := True;
    IterateCells(table, 1);
    Checked := FAllEqual;
    end
  else
    Checked := False;
end;

function TrvActionTableCellBorder.IterateCellProc(table: TRVTableItemInfo;
  FirstCell: Boolean; Row, Col, CustomData: Integer): Boolean;
begin
  Result := True;
  case CustomData of
    1:
      begin
        FAllEqual := IsBordered(table.Cells[Row, Col].VisibleBorders);
        Result := FAllEqual;
      end;
    2:
      begin
        SetBorder(table, Row, Col, True);
      end;
    3:
      begin
        SetBorder(table, Row, Col, False);
      end;
  end;
end;

{ TrvActionTableCellLeftBorder }

constructor TrvActionTableCellLeftBorder.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_TableCellLeftBorder;
end;

function TrvActionTableCellLeftBorder.IsBordered(
  aVisibleBorders: TRVBooleanRect): Boolean;
begin
  Result := aVisibleBorders.Left;
end;

procedure TrvActionTableCellLeftBorder.SetBorder(
  table: TRVTableItemInfo; r,c: Integer; const aValue: Boolean);
begin
  with table.Cells[r,c].VisibleBorders do
    table.SetCellVisibleBorders(aValue, Top, Right, Bottom, r, c);
end;

{ TrvActionTableCellRightBorder }

constructor TrvActionTableCellRightBorder.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_TableCellRightBorder;
end;

function TrvActionTableCellRightBorder.IsBordered(
  aVisibleBorders: TRVBooleanRect): Boolean;
begin
  Result := aVisibleBorders.Right;
end;

procedure TrvActionTableCellRightBorder.SetBorder(
  table: TRVTableItemInfo; r,c: Integer; const aValue: Boolean);
begin
  with table.Cells[r,c].VisibleBorders do
    table.SetCellVisibleBorders(Left, Top, aValue, Bottom, r, c);
end;

{ TrvActionTableCellTopBorder }

constructor TrvActionTableCellTopBorder.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_TableCellTopBorder;
end;

function TrvActionTableCellTopBorder.IsBordered(
  aVisibleBorders: TRVBooleanRect): Boolean;
begin
  Result := aVisibleBorders.Top;
end;

procedure TrvActionTableCellTopBorder.SetBorder(
  table: TRVTableItemInfo; r,c: Integer; const aValue: Boolean);
begin
  with table.Cells[r,c].VisibleBorders do
    table.SetCellVisibleBorders(Left, aValue, Right, Bottom, r, c);
end;

{ TrvActionTableCellBottomBorder }

constructor TrvActionTableCellBottomBorder.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_TableCellBottomBorder;
end;

function TrvActionTableCellBottomBorder.IsBordered(
  aVisibleBorders: TRVBooleanRect): Boolean;
begin
  Result := aVisibleBorders.Bottom;
end;

procedure TrvActionTableCellBottomBorder.SetBorder(
  table: TRVTableItemInfo; r,c: Integer; const aValue: Boolean);
begin
  with table.Cells[r,c].VisibleBorders do
    table.SetCellVisibleBorders(Left, Top, Right, aValue, r, c);
end;

{ TrvActionTableCellAllBorders }

constructor TrvActionTableCellAllBorders.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_TableCellAllBorders;
end;

function TrvActionTableCellAllBorders.IsBordered(
  aVisibleBorders: TRVBooleanRect): Boolean;
begin
  Result := aVisibleBorders.IsAllEqual(True);
end;

procedure TrvActionTableCellAllBorders.SetBorder(
  table: TRVTableItemInfo; r,c: Integer; const aValue: Boolean);
begin
  table.SetCellVisibleBorders(aValue, aValue, aValue, aValue, r, c);
end;

{ TrvActionTableCellNoBorders }

procedure TrvActionTableCellNoBorders.SetBorder(table: TRVTableItemInfo; r,
  c: Integer; const aValue: Boolean);
begin
  table.SetCellVisibleBorders(False, False, False, False, r, c);
end;

function TrvActionTableCellNoBorders.ExecuteCommand(
  rve: TCustomRichViewEdit; table: TRVTableItemInfo;
  ItemNo: Integer): Boolean;
begin
  rve.BeginUndoGroup(rvutModifyItem);
  rve.SetUndoGroupMode(True);
  try
    IterateCells(table, 3)
  finally
    rve.SetUndoGroupMode(False);
  end;
  Result := True;
end;

function TrvActionTableCellNoBorders.IsApplicable(rve: TCustomRichViewEdit;
  table: TRVTableItemInfo; ItemNo: Integer): Boolean;
var r,c,rs,cs: Integer;
begin
  Result := table.GetNormalizedSelectionBounds(True, r,c,cs,rs);
end;


  { ------------------ List Styles ------------------------- }


constructor TrvActionTableCellNoBorders.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_TableCellNoBorders;
end;

{ TrvActionParaList }

constructor TrvActionParaList.Create(AOwner: TComponent);
begin
  inherited;
  FIndentStep := 24;
  FUpdateAllActionsOnForm := True;
  FMessageID := rvam_act_ParaList;
end;

procedure TrvActionParaList.Notification(AComponent: TComponent;
  Operation: TOperation);
begin
  inherited;
  if (Operation=opRemove) then begin
   if (AComponent=FActionParaBullets) then
     FActionParaBullets := nil;
   if (AComponent=FActionParaNumbering) then
     FActionParaNumbering := nil;
  end;
end;

function TrvActionParaList.CanApplyToPlainText: Boolean;
begin
  Result := False;
end;

procedure TrvActionParaList.SetActionParaBullets(
  const Value: TrvActionParaBullets);
begin
  if Value <> FActionParaBullets then
  begin
    {$IFDEF RICHVIEWDEF5}
    if FActionParaBullets <> nil then
      FActionParaBullets.RemoveFreeNotification(Self);
    {$ENDIF}
    FActionParaBullets := Value;
    if FActionParaBullets<> nil then
      FActionParaBullets.FreeNotification(Self);
  end;
end;

procedure TrvActionParaList.SetActionParaNumbering(
  const Value: TrvActionParaNumbering);
begin
  if Value <> FActionParaNumbering then
  begin
    {$IFDEF RICHVIEWDEF5}
    if FActionParaNumbering <> nil then
      FActionParaNumbering.RemoveFreeNotification(Self);
    {$ENDIF}
    FActionParaNumbering := Value;
    if FActionParaNumbering<> nil then
      FActionParaNumbering.FreeNotification(Self);
  end;
end;

function TrvActionParaList.ShowForm(rve: TCustomRichViewEdit; var ListStyle: TRVListInfo;
      var ListNo, StartFrom: Integer; var UseStartFrom: Boolean): TForm;
var frm: TfrmRVListGallery;
    frm2: TfrmRVListGallery2;
    Level: Integer;
begin
  Result := nil;
  case RVA_UserInterface of
    rvauiHTML:
      begin
        frm2 := TfrmRVListGallery2.Create(Application);
        frm2.Init(rve, rve.Style.DifferentUnitsToUnits(IndentStep, RVA_UnitsProgram));
        if frm2.ShowModal=mrOk then begin
          frm2.GetListStyle(ListStyle, ListNo, Level, StartFrom, UseStartFrom);
          Result := frm2;
          end
        else
          frm2.Free;
      end;
    else
      begin
        frm := TfrmRVListGallery.CreateEx(Application, IndentStep);
        frm.InitStyles(rve);
        if frm.ShowModal=mrOk then begin
          frm.GetListStyle(ListStyle, ListNo, StartFrom, UseStartFrom);
          Result := frm;
          end
        else
          frm.Free;
      end;
  end;
end;

procedure TrvActionParaList.ExecuteTarget(Target: TObject);
var rve: TCustomRichViewEdit;
    ListStyle: TRVListInfo;
    ListNo, StartFrom: Integer;
    UseStartFrom: Boolean;
    Data: TRVDeleteUnusedStylesData;
    i, Index: Integer;
    frm: TForm;
begin
  rve := GetControl(Target);
  frm := ShowForm(rve, ListStyle, ListNo, StartFrom, UseStartFrom);
  if frm=nil  then
    exit;
  try
    if ListStyle=nil then
      rve.RemoveLists(False)
    else begin
      if not ListStyle.HasNumbering then begin
        if ListNo<0 then begin
          Index := RVA_Events.DoStyleNeeded(Self, rve.Style, ListStyle);
          if Index<0 then begin
            ListNo := rve.Style.ListStyles.Count;
            Index := rve.Style.ListStyles.FindSuchStyle(ListStyle, True);
            if Index=ListNo then
              RVA_Events.DoOnAddStyle(Self, rve.Style.ListStyles[Index]);
          end;
          end
        else
          Index := ListNo;
        rve.ApplyListStyle(Index, -1, 1, False, False);
        UpdateBulletsAction(rve.Style, Index);
        end
      else begin
        if ListNo<0 then begin
          Data := TRVDeleteUnusedStylesData.Create(False, False, True);
          try
            rve.RVData.MarkStylesInUse(Data);
            Index := -1;
            for i := 0 to rve.Style.ListStyles.Count-1 do
              if (Data.UsedListStyles[i]=0) and
                  rve.Style.ListStyles[i].IsSimpleEqual(ListStyle, False) then begin
                Index := i;
                break;
              end;
          finally
            Data.Free;
          end;
          if Index<0 then begin
            Index := RVA_Events.DoStyleNeeded(Self, rve.Style, ListStyle);
            if Index<0 then begin
              rve.Style.ListStyles.Add.Assign(ListStyle);
              Index := rve.Style.ListStyles.Count-1;
              rve.Style.ListStyles[Index].Standard := False;
              RVA_Events.DoOnAddStyle(Self, rve.Style.ListStyles[Index]);
            end;
          end;
          end
        else begin
          Index := ListNo;
        end;
        rve.ApplyListStyle(Index, -1, StartFrom, UseStartFrom, False);
        if rve.Style.ListStyles[Index].AllNumbered then
          UpdateNumberingAction(rve.Style, Index);
      end;
    end;
  finally
    frm.Free;
  end;
end;

procedure TrvActionParaList.UpdateBulletsAction(RVStyle: TRVStyle;
  ListNo: Integer);
var i: Integer;
begin
  if FActionParaBullets<>nil then begin
    FActionParaBullets.ListLevels := RVStyle.ListStyles[ListNo].Levels;
    if RVStyle.Units<>RVA_UnitsProgram then
      FActionParaBullets.ListLevels.ConvertToDifferentUnits(RVA_UnitsProgram, nil);
  end;
  if FUpdateAllActionsOnForm then
    for i := 0 to Owner.ComponentCount - 1 do
      if (Owner.Components[i] is TrvActionParaBullets) and
         (Owner.Components[i]<>FActionParaBullets) then begin
        TrvActionParaBullets(Owner.Components[i]).ListLevels := RVStyle.ListStyles[ListNo].Levels;
        if RVStyle.Units<>RVA_UnitsProgram then
          TrvActionParaBullets(Owner.Components[i]).ListLevels.ConvertToDifferentUnits(RVA_UnitsProgram, nil);
      end;
end;

procedure TrvActionParaList.UpdateNumberingAction(RVStyle: TRVStyle;
  ListNo: Integer);
var i: Integer;
begin
  if FActionParaNumbering<>nil then begin
    FActionParaNumbering.ListLevels := RVStyle.ListStyles[ListNo].Levels;
    if RVStyle.Units<>RVA_UnitsProgram then
      FActionParaNumbering.ListLevels.ConvertToDifferentUnits(RVA_UnitsProgram, nil);
  end;
  if FUpdateAllActionsOnForm then
    for i := 0 to Owner.ComponentCount - 1 do
      if (Owner.Components[i] is TrvActionParaNumbering) and
         (Owner.Components[i]<>FActionParaNumbering) then begin
        TrvActionParaNumbering(Owner.Components[i]).ListLevels := RVStyle.ListStyles[ListNo].Levels;
        if RVStyle.Units<>RVA_UnitsProgram then
          TrvActionParaNumbering(Owner.Components[i]).ListLevels.ConvertToDifferentUnits(RVA_UnitsProgram, nil);
      end;
end;

procedure TrvActionParaList.ConvertToPixels;
var i: Integer;
begin
  inherited;
  IndentStep := TRVStyle.GetAsPixelsEx(IndentStep, RVA_UnitsProgram);
  for i := 0 to 1 do
    if ModifiedTemplates[i]<>nil then
      ModifiedTemplates[i].ConvertToPixels;
end;

procedure TrvActionParaList.ConvertToTwips;
var i: Integer;
begin
  inherited;
  IndentStep := TRVStyle.GetAsTwipsEx(IndentStep, RVA_UnitsProgram);
  for i := 0 to 1 do
    if ModifiedTemplates[i]<>nil then
      ModifiedTemplates[i].ConvertToTwips;
end;

{ TrvActionCustomParaListSwitcher }

procedure TrvActionCustomParaListSwitcher.ConvertToPixels;
begin
  inherited;
  FIndentStep := TRVStyle.GetAsPixelsEx(IndentStep, RVA_UnitsProgram);
  if RVA_UnitsProgram = rvstuPixels then
    exit;
  ListLevels.ConvertToDifferentUnits(rvstuPixels, nil);
end;

procedure TrvActionCustomParaListSwitcher.ConvertToTwips;
begin
  inherited;
  FIndentStep := TRVStyle.GetAsTwipsEx(IndentStep, RVA_UnitsProgram);
  if RVA_UnitsProgram = rvstuTwips then
    exit;
  ListLevels.ConvertToDifferentUnits(rvstuTwips, nil);
end;

constructor TrvActionCustomParaListSwitcher.Create(AOwner: TComponent);
begin
  inherited;
  FListLevels := TRVListLevelCollection.Create(Self);
  IndentStep := 24;
  Reset;
end;

destructor TrvActionCustomParaListSwitcher.Destroy;
begin
  FListLevels.Free;
  inherited;
end;

procedure TrvActionCustomParaListSwitcher.Reset;
begin
  ResetLevels(FListLevels);
end;

procedure TrvActionCustomParaListSwitcher.SetIndentStep(
  const Value: TRVStyleLength);
begin
  FIndentStep := Value;
  Reset;
end;

procedure TrvActionCustomParaListSwitcher.SetListLevels(
  const Value: TRVListLevelCollection);
begin
  if FListLevels<>Value then
    FListLevels.Assign(Value);
end;

function TrvActionCustomParaListSwitcher.StoreListLevels: Boolean;
var SampleLevels: TRVListLevelCollection;
begin
  SampleLevels := TRVListLevelCollection.Create(nil);
  ResetLevels(SampleLevels);
  Result := not SampleLevels.IsSimpleEqual(FListLevels);
  SampleLevels.Free;
end;

function TrvActionCustomParaListSwitcher.GetTempLevels(RVStyle: TRVStyle): TRVListLevelCollection;
begin
  if RVStyle.Units<>RVA_UnitsProgram then begin
    Result := TRVListLevelCollection.Create(nil);
    Result.Assign(FListLevels);
    Result.ConvertToDifferentUnits(RVStyle.Units, nil);
    end
  else
    Result := FListLevels;
end;

procedure TrvActionCustomParaListSwitcher.UpdateTarget(Target: TObject);
var StartNo, EndNo, a,b,i: Integer;
   Checked: Boolean;
   rve: TCustomRichViewEdit;
   CorrectListNo, ListNo, ListLevel, StartFrom: Integer;
   TempLevels: TRVListLevelCollection;
   UseStartFrom: Boolean;
begin
  if not RVA_ActionsEnabled or Disabled or (RVA_UserInterface=rvauiText) then begin
    Enabled := False;
    exit;
  end;
  TempLevels := nil;
  try
    inherited;
    rve := GetControl(Target).TopLevelEditor;
    TempLevels := GetTempLevels(rve.Style);
    rve.GetSelectionBounds(StartNo, a, EndNo, b, True);
    if StartNo<0 then begin
      StartNo := rve.CurItemNo;
      EndNo   := StartNo;
    end;
    rve.RVData.ExpandToPara(StartNo, EndNo, StartNo, EndNo);
    Checked := True;
    CorrectListNo := -1;
    for i := StartNo to EndNo do
      if rve.IsParaStart(i) then begin
        if (rve.GetListMarkerInfo(i, ListNo, ListLevel, StartFrom, UseStartFrom)<0) or (ListNo<0) then begin
          Checked := False;
          break;
        end;
        if (i=StartNo) then begin
          if rve.Style.ListStyles[ListNo].Levels.IsSimpleEqual(TempLevels) then
            CorrectListNo := ListNo
          else begin
            Checked := False;
            break;
          end;
          end
        else if ListNo<>CorrectListNo then begin
          Checked := False;
          break;
        end;
      end;
    Self.Checked := Checked;
  except
    Enabled := False;
  end;
  if TempLevels<>FListLevels then
    TempLevels.Free;
end;

{ TrvActionParaBullets }

constructor TrvActionParaBullets.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_Bullets;
end;

procedure TrvActionParaBullets.ExecuteTarget(Target: TObject);
var
  rve: TCustomRichViewEdit;
  Index, ListCount: Integer;
  ListStyle: TRVListInfo;
  TempLevels: TRVListLevelCollection;
begin
  rve := GetControl(Target);
  if not Checked then begin
    ListStyle := TRVListInfo.Create(nil);
    try
      ListStyle.Levels := ListLevels;
      if RVA_UnitsProgram<>rve.Style.Units then
        ListStyle.Levels.ConvertToDifferentUnits(rve.Style.Units, nil);
      Index := RVA_Events.DoStyleNeeded(Self, rve.Style, ListStyle);
    finally
      ListStyle.Free;
    end;
    if Index<0 then begin
      ListCount := rve.Style.ListStyles.Count;
      TempLevels := GetTempLevels(rve.Style);
      try
        Index := rve.Style.ListStyles.FindStyleWithLevels(TempLevels, '2', True);
      finally
        if TempLevels<>FListLevels then
          TempLevels.Free;
      end;
      if ListCount<>rve.Style.ListStyles.Count then
        RVA_Events.DoOnAddStyle(Self, rve.Style.ListStyles[Index]);
    end;
    rve.ApplyListStyle(Index, -1, 1, False, False)
    end
  else
    rve.RemoveLists(False);
end;

procedure TrvActionParaBullets.ResetLevels(AListLevels: TRVListLevelCollection);
var i: Integer;
begin
  AListLevels.Clear;
  for i := 0 to 8 do
    with AListLevels.Add do begin
      FirstIndent := 0;
      LeftIndent := IndentStep+i*IndentStep*2;
      MarkerIndent := i*IndentStep*2;
      Font.Size := 12;
      case i mod 3 of
        0:
          begin
            Font.Name := 'Symbol';
            Font.Charset := SYMBOL_CHARSET;
            FormatString := RVCHAR_MIDDLEDOT;
          end;
        1:
          begin
            Font.Name := 'Courier New';
            Font.Charset := ANSI_CHARSET;
            FormatString := 'o';
          end;
        2:
          begin
            Font.Name := 'Wingdings';
            Font.Charset := SYMBOL_CHARSET;
            FormatString := {$IFDEF RVUNICODESTR}#$00A7{$ELSE}#$A7{$ENDIF};
          end;
      end;
    end;
end;

{ TrvActionParaNumbering }

constructor TrvActionParaNumbering.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_Numbering;
end;

procedure TrvActionParaNumbering.ExecuteTarget(Target: TObject);
var
  rve: TCustomRichViewEdit;
  StartNo, EndNo, a,b: Integer;
  Data: TRVDeleteUnusedStylesData;
  ListNo, ListLevel, StartFrom: Integer;
  UseStartFrom: Boolean;
  i, Index: Integer;
  ListStyle: TRVListInfo;
  TempLevels: TRVListLevelCollection;  
begin
  rve := GetControl(Target);
  if Checked then begin
    rve.RemoveLists(False);
    exit;
  end;
  rve := GetControl(Target).TopLevelEditor;
  TempLevels := GetTempLevels(rve.Style);
  try
    rve.RVData.GetSelectionBoundsEx(StartNo, a, EndNo, b, True);
    rve.RVData.ExpandToPara(StartNo, EndNo, StartNo, EndNo);
    if StartNo>0 then
      dec(StartNo);
    if EndNo<rve.ItemCount-1 then
      inc(EndNo);
    rve.RVData.ExpandToPara(StartNo, EndNo, StartNo, EndNo);
    Index := -1;
    for i := StartNo to EndNo do
      if rve.IsParaStart(i) then
        if (rve.GetListMarkerInfo(i, ListNo, ListLevel, StartFrom, UseStartFrom)>=0) and
           (ListNo>=0) and
           rve.Style.ListStyles[ListNo].Levels.IsSimpleEqual(TempLevels) then begin
          Index := ListNo;
          break;
        end;
    if Index<0 then
      for i := StartNo-1 downto 0 do
        if rve.IsParaStart(i) then
          if (rve.GetListMarkerInfo(i, ListNo, ListLevel, StartFrom, UseStartFrom)>=0) and
           (ListNo>=0) then begin
            if rve.Style.ListStyles[ListNo].Levels.IsSimpleEqual(TempLevels) then begin
              Index := ListNo;
              break;
            end;
            end
          else
            break;
    if Index<0 then begin
      rve := GetControl(Target);
      Data := TRVDeleteUnusedStylesData.Create(False, False, True);
      try
        rve.RVData.MarkStylesInUse(Data);
        Index := -1;
        for i := 0 to rve.Style.ListStyles.Count-1 do
          if (Data.UsedListStyles[i]=0) and rve.Style.ListStyles[i].Levels.IsSimpleEqual(TempLevels) then begin
            Index := i;
            break;
          end;
      finally
        Data.Free;
      end;
      if Index<0 then begin
        ListStyle := TRVListInfo.Create(nil);
        try
          ListStyle.Levels := TempLevels;
          Index := RVA_Events.DoStyleNeeded(Self, rve.Style, ListStyle);
        finally
          ListStyle.Free;
        end;
        if Index<0 then begin
          with rve.Style.ListStyles.Add do begin
            Levels := TempLevels;
            StyleName := '2';
            Standard := False;
            OneLevelPreview := True;
          end;
          Index := rve.Style.ListStyles.Count-1;
          RVA_Events.DoOnAddStyle(Self, rve.Style.ListStyles[Index]);
        end;
      end;
    end;
    rve.ApplyListStyle(Index, -1, 1, False, False);
  finally
    if TempLevels<>FListLevels then
      TempLevels.Free;
  end;
end;

procedure TrvActionParaNumbering.ResetLevels(AListLevels: TRVListLevelCollection);
var i: Integer;
begin
  AListLevels.Clear;
  for i := 0 to 8 do
    with AListLevels.Add do begin
      FirstIndent := 0;
      LeftIndent := IndentStep+i*IndentStep*2;
      MarkerIndent := i*IndentStep*2;
      Font.Size := 10;
      ListType := rvlstDecimal;
      FormatString := Format('%%%d:s.',[i]);
    end;
end;

  { ------------------ Spell Checking ------------------------- }

{$IFDEF USERVADDICT3}

{ TrvActionAddictSpell3 }

constructor TrvActionAddictSpell3.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_Spell;
end;

procedure TrvActionAddictSpell3.ExecuteTarget(Target: TObject);
begin
  RVA_Addict3.CheckRichViewEdit(GetControl(Target), ctSmart);
end;

procedure TrvActionAddictSpell3.UpdateTarget(Target: TObject);
var rve: TCustomRichViewEdit;
begin
  if not RVA_ActionsEnabled or Disabled then begin
    Enabled := False;
    exit;
  end;
  rve := GetControl(Target).TopLevelEditor;
  Enabled := {not rve.ReadOnly and} (rve.RVData.PartialSelectedItem=nil) and (RVA_Addict3<>nil);
end;

{ TrvActionAddictThesaurus3 }

constructor TrvActionAddictThesaurus3.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_Thesaurus;
end;

procedure TrvActionAddictThesaurus3.ExecuteTarget(Target: TObject);
begin
  RVA_Thes3.FastLookupRichViewEdit(GetControl(Target));
end;

procedure TrvActionAddictThesaurus3.UpdateTarget(Target: TObject);
var rve: TCustomRichViewEdit;
begin
  if not RVA_ActionsEnabled or Disabled then begin
    Enabled := False;
    exit;
  end;
  rve := GetControl(Target).TopLevelEditor;
  Enabled := {not rve.ReadOnly and} (rve.RVData.PartialSelectedItem=nil) and (RVA_Thes3<>nil);
end;

function RVA_Addict3AutoCorrect(rve: TCustomRichViewEdit): Boolean;
var ItemNo, WordEnd, WordStart: Integer;
    s,s2: String;
    {$IFNDEF RVUNICODESTR}
    CodePage: TRVCodePage;
    {$ENDIF}
begin
  Result := RVA_Addict3<>nil;
  if not Result then
    exit;
  rve := rve.TopLevelEditor;
  ItemNo := rve.CurItemNo;
  WordEnd := rve.OffsetInCurItem;
  {$IFNDEF RVUNICODESTR}
  CodePage := rve.RVData.GetItemCodePage(ItemNo);
  {$ENDIF}
  if (rve.GetItemStyle(ItemNo)<0) or
    (rve.Style.TextStyles[rve.GetItemStyle(ItemNo)].Charset=SYMBOL_CHARSET) then
    exit;
  s := rve.GetItemText(ItemNo);
  WordStart := WordEnd;
  if WordStart<1 then
    exit;
  while (WordStart-1>0) and not
    {$IFDEF RVUNICODESTR}
    rve.RVData.IsDelimiterW(s[WordStart-1])
    {$ELSE}
    rve.RVData.IsDelimiterA(s[WordStart-1], CodePage)
    {$ENDIF} do
    dec(WordStart);
  s := Copy(s, WordStart, WordEnd-WordStart);
  Result := RVA_Addict3.WordHasCorrection(s,s2);
  if Result then begin
    rve.SetSelectionBounds(ItemNo, WordStart, ItemNo, WordEnd);
    rve.InsertText(s2);
  end;
end;

{$ENDIF}

{================================= TRVAControlPanel ===========================}
constructor TRVAControlPanel.Create(AOwner: TComponent);
begin
  inherited;
  UseXPThemes := True;
  DialogFontName := 'MS Sans Serif';
  DefaultControl := nil;
  ColorDialog := nil;
  TableGridStyle := psDot;
  RVFFilter := sFileFilterRVF;
  DefaultExt := sRVFExtension;
  RVFormatTitle := RVFormatName;
  DefaultFileName := 'Untitled.'+sRVFExtension;
  DefaultFileFormat := ffeRVF;
  DefaultCustomFilterIndex := 1;
  AutoDeleteUnusedStyles := True;
  {$IFDEF USERVXML}
  XMLFilter := sFileFilterXML;
  RVXML := nil;
  {$ENDIF}
  {$IFDEF USERVADDICT3}
  RVAddictSpell3 := nil;
  RVAddictThesaurus3 := nil;
  {$ENDIF}
  {$IFDEF USERVHTML}
  RVHTMLImporter := nil;
  {$ENDIF}
  {$IFDEF USERVHTMLVIEWER}
  RVHTMLViewImporter := nil;
  {$ENDIF}
  {$IFDEF USEINDY}
  IdHTTP := nil;
  {$ENDIF}
  {$IFDEF USECLEVERCOMPONENTS}
  ClHTTP := nil;
  {$ENDIF}
  ActionsEnabled := True;
  UseHelpFiles := True;
  AddColorNameToHints := True;
  DefaultMargin := 5;
  DefaultColor := clWindow;
  RVPrint := nil;
  ShowSoftPageBreaks := True;
  // Language := ?
  RVFLocalizable := True;
  XMLLocalizable := True;
  OnStyleNeeded := nil;
  OnAddStyle := nil;
  OnMarginsChanged := nil;
  OnViewChanged := nil;
  OnCustomFileOperation := nil;
  OnDownload := nil;
  OnBackgroundChange := nil;
  {$IFDEF USERVKSDEVTE}
  OnCreateTeForm := nil;
  {$ENDIF}
  SearchScope := rvssAskUser;
  UserInterface := rvauiFull;
end;


destructor TRVAControlPanel.Destroy;
begin
  DefaultControl := nil;
  ColorDialog    := nil;
  RVPrint        := nil;
  {$IFDEF USERVXML}
  RVXML          := nil;
  {$ENDIF}
  {$IFDEF USERVHTML}
  RVHTMLImporter := nil;
  {$ENDIF}
  {$IFDEF USERVADDICT3}
  RVAddictSpell3 := nil;
  RVAddictThesaurus3 := nil;
  {$ENDIF}
  inherited;
end;

function TRVAControlPanel.GetDialogFontName: TFontName;
begin
  Result := RVA_DialogFontName;
end;

procedure TRVAControlPanel.SetDialogFontName(const Value: TFontName);
begin
  RVA_DialogFontName := Value;
end;

function TRVAControlPanel.GetDialogFontSize: Integer;
begin
  Result := RVA_DialogFontSize;
end;

procedure TRVAControlPanel.SetDialogFontSize(Value: Integer);
begin
  RVA_DialogFontSize := Value;
end;

function TRVAControlPanel.GetUseXPThemes: Boolean;
begin
  Result := RVA_UseXPThemes;
end;

procedure TRVAControlPanel.SetUseXPThemes(const Value: Boolean);
begin
  RVA_UseXPThemes := Value;
end;

function TRVAControlPanel.GetDefaultControl: TCustomRichViewEdit;
begin
  Result := RVA_DefaultControl;
end;

procedure TRVAControlPanel.SetDefaultControl(
  const Value: TCustomRichViewEdit);
begin
  if Value <> RVA_DefaultControl then
  begin
    {$IFDEF RICHVIEWDEF5}
    if RVA_DefaultControl <> nil then
      RVA_DefaultControl.RemoveFreeNotification(Self);
    {$ENDIF}
    RVA_DefaultControl := Value;
    if RVA_DefaultControl<> nil then
      RVA_DefaultControl.FreeNotification(Self);
  end;
end;

procedure TRVAControlPanel.Notification(AComponent: TComponent;
  Operation: TOperation);
begin
  inherited;
  if (Operation=opRemove) then begin
   if (AComponent=RVA_DefaultControl) then
     RVA_DefaultControl := nil;
   if (AComponent=RVA_ColorDialog) then
     RVA_ColorDialog := nil;
   if (AComponent=RVA_RVPrint) then
     RVA_RVPrint := nil;
   {$IFDEF USERVXML}
   if (AComponent=RVA_RVXML) then
     RVA_RVXML := nil;
   {$ENDIF}
   {$IFDEF USERVHTML}
   if (AComponent=RVA_RVHTML) then
     RVA_RVHTML := nil;
   {$ENDIF}
   {$IFDEF USERVHTMLVIEWER}
   if (AComponent=RVA_RVHTMLView) then
     RVA_RVHTMLView := nil;
   {$ENDIF}
   {$IFDEF USERVADDICT3}
   if (AComponent=RVA_Addict3) then
     RVA_Addict3 := nil;
   if (AComponent=RVA_Thes3) then
     RVA_Thes3 := nil;
   {$ENDIF}
   {$IFDEF USEINDY}
    if (AComponent=RVA_IdHTTP) then
     RVA_IdHTTP := nil;
   {$ENDIF}
   {$IFDEF USECLEVERCOMPONENTS}
    if (AComponent=RVA_ClHTTP) then
     RVA_ClHTTP := nil;
   {$ENDIF}   
  end;
end;

function TRVAControlPanel.GetColorDialog: TColorDialog;
begin
  Result := RVA_ColorDialog;
end;

procedure TRVAControlPanel.SetColorDialog(const Value: TColorDialog);
begin
  if Value <> RVA_ColorDialog then
  begin
    {$IFDEF RICHVIEWDEF5}
    if RVA_ColorDialog <> nil then
      RVA_ColorDialog.RemoveFreeNotification(Self);
    {$ENDIF}
    RVA_ColorDialog := Value;
    if RVA_ColorDialog<> nil then
      RVA_ColorDialog.FreeNotification(Self);
  end;
end;

function TRVAControlPanel.GetTableGridStyle: TPenStyle;
begin
  Result := RVA_TableGridStyle;
end;

procedure TRVAControlPanel.SetTableGridStyle(const Value: TPenStyle);
begin
  RVA_TableGridStyle := Value;
  if RichViewTableGridStyle<>psClear then
    RichViewTableGridStyle := Value;
end;

procedure TRVAControlPanel.Loaded;
begin
  inherited;
  RichViewTableGridStyle := RVA_TableGridStyle;
end;

function TRVAControlPanel.GetRVFFilter: String;
begin
  Result := RVA_RVFFilter;
end;

procedure TRVAControlPanel.SetRVFFilter(const Value: String);
begin
  RVA_RVFFilter := Value;
end;

{$IFDEF USERVXML}
function TRVAControlPanel.GetXMLFilter: String;
begin
  Result := RVA_XMLFilter;
end;

procedure TRVAControlPanel.SetXMLFilter(const Value: String);
begin
  RVA_XMLFilter := Value;
end;

function TRVAControlPanel.GetRVXML: TRichViewXML;
begin
  Result := RVA_RVXML;
end;

procedure TRVAControlPanel.SetRVXML(const Value: TRichViewXML);
begin
  {$IFDEF RICHVIEWDEF5}
  if RVA_RVXML<>nil then
    RVA_RVXML.RemoveFreeNotification(Self);
  {$ENDIF}
  RVA_RVXML := Value;
  if RVA_RVXML<>nil then
    RVA_RVXML.FreeNotification(Self);
end;
{$ENDIF}

{$IFDEF USERVHTML}
function TRVAControlPanel.GetRVHTML: TRvHtmlImporter;
begin
  Result := RVA_RVHTML;
end;

procedure TRVAControlPanel.SetRVHTML(const Value: TRvHtmlImporter);
begin
  {$IFDEF RICHVIEWDEF5}
  if RVA_RVHTML<>nil then
    RVA_RVHTML.RemoveFreeNotification(Self);
  {$ENDIF}
  RVA_RVHTML := Value;
  if RVA_RVHTML<>nil then
    RVA_RVHTML.FreeNotification(Self);
end;
{$ENDIF}

{$IFDEF USERVHTMLVIEWER}
function TRVAControlPanel.GetRVHTMLView: TRVHTMLViewImporter;
begin
  Result := RVA_RVHTMLView
end;

procedure TRVAControlPanel.SetRVHTMLView(const Value: TRVHTMLViewImporter);
begin
  {$IFDEF RICHVIEWDEF5}
  if RVA_RVHTMLView<>nil then
    RVA_RVHTMLView.RemoveFreeNotification(Self);
  {$ENDIF}
  RVA_RVHTMLView := Value;
  if RVA_RVHTMLView<>nil then
    RVA_RVHTMLView.FreeNotification(Self);
end;
{$ENDIF}

{$IFDEF USERVADDICT3}
function TRVAControlPanel.GetRVAddictSpell3: TRVAddictSpell3;
begin
  Result := RVA_Addict3;
end;

function TRVAControlPanel.GetRVAddictThesaurus3: TRVThesaurus3;
begin
  Result := RVA_Thes3;
end;

procedure TRVAControlPanel.SetRVAddictSpell3(const Value: TRVAddictSpell3);
begin
  {$IFDEF RICHVIEWDEF5}
  if RVA_Addict3<>nil then
    RVA_Addict3.RemoveFreeNotification(Self);
  {$ENDIF}
  RVA_Addict3 := Value;
  if RVA_Addict3<>nil then
    RVA_Addict3.FreeNotification(Self);
end;

procedure TRVAControlPanel.SetRVAddictThesaurus3(
  const Value: TRVThesaurus3);
begin
  {$IFDEF RICHVIEWDEF5}
  if RVA_Thes3<>nil then
    RVA_Thes3.RemoveFreeNotification(Self);
  {$ENDIF}
  RVA_Thes3 := Value;
  if RVA_Thes3<>nil then
    RVA_Thes3.FreeNotification(Self);
end;
{$ENDIF}

{$IFDEF USEINDY}
function TRVAControlPanel.GetIdHTTP: TIdHTTP;
begin
  Result := RVA_IdHTTP;
end;

procedure TRVAControlPanel.SetIdHTTP(const Value: TIdHTTP);
begin
  {$IFDEF RICHVIEWDEF5}
  if RVA_IdHTTP<>nil then
    RVA_IdHTTP.RemoveFreeNotification(Self);
  {$ENDIF}
  RVA_IdHTTP := Value;
  if RVA_IdHTTP<>nil then
    RVA_IdHTTP.FreeNotification(Self);
end;
{$ENDIF}

{$IFDEF USECLEVERCOMPONENTS}
function TRVAControlPanel.GetClHTTP: TClHTTP;
begin
  Result := RVA_ClHTTP;
end;

procedure TRVAControlPanel.SetClHTTP(const Value: TClHTTP);
begin
  {$IFDEF RICHVIEWDEF5}
  if RVA_ClHTTP<>nil then
    RVA_ClHTTP.RemoveFreeNotification(Self);
  {$ENDIF}
  RVA_ClHTTP := Value;
  if RVA_ClHTTP<>nil then
    RVA_ClHTTP.FreeNotification(Self);
end;
{$ENDIF}

function TRVAControlPanel.GetDefaultExt: String;
begin
  Result := RVA_DefaultExt;
end;

procedure TRVAControlPanel.SetDefaultExt(const Value: String);
begin
  RVA_DefaultExt := Value;
end;

function TRVAControlPanel.GetRVFormatName: String;
begin
  Result := RVA_RVFormatName;
end;

procedure TRVAControlPanel.SetRVFormatName(const Value: String);
begin
  RVA_RVFormatName := Value;
end;

function TRVAControlPanel.GetDefaultFileName: String;
begin
  Result := RVA_DefaultFileName;
end;

procedure TRVAControlPanel.SetDefaultFileName(const Value: String);
begin
  RVA_DefaultFileName :=  Value;
end;

function TRVAControlPanel.GetAutoDeleteUnusedStyles: Boolean;
begin
  Result := RVA_AutoDeleteUnusedStyles;
end;

procedure TRVAControlPanel.SetAutoDeleteUnusedStyles(const Value: Boolean);
begin
  RVA_AutoDeleteUnusedStyles := Value;
end;

function TRVAControlPanel.GetDefaultColor: TColor;
begin
  Result := RVA_DefaultColor;
end;

function TRVAControlPanel.GetDefaultMargin: Integer;
begin
  Result := RVA_DefaultMargin;
end;

procedure TRVAControlPanel.SetDefaultColor(const Value: TColor);
begin
  RVA_DefaultColor := Value;
end;

procedure TRVAControlPanel.SetDefaultMargin(const Value: Integer);
begin
  RVA_DefaultMargin := Value;
end;

function TRVAControlPanel.GetRVPrint: TRVPrint;
begin
  Result := RVA_RVPrint;
end;

procedure TRVAControlPanel.SetRVPrint(const Value: TRVPrint);
begin
  {$IFDEF RICHVIEWDEF5}
  if RVA_RVPrint<>nil then
    RVA_RVPrint.RemoveFreeNotification(Self);
  {$ENDIF}
  RVA_RVPrint := Value;
  if RVA_RVPrint<>nil then
    RVA_RVPrint.FreeNotification(Self);
end;

function TRVAControlPanel.GetShowSoftPageBreaks: Boolean;
begin
  Result := RVA_ShowSoftPageBreaks;
end;

procedure TRVAControlPanel.SetShowSoftPageBreaks(const Value: Boolean);
begin
  RVA_ShowSoftPageBreaks := Value;
end;

function TRVAControlPanel.GetActionsEnabled: Boolean;
begin
  Result := RVA_ActionsEnabled;
end;

procedure TRVAControlPanel.SetActionsEnabled(const Value: Boolean);
begin
  RVA_ActionsEnabled := Value;
end;

function TRVAControlPanel.GetUseHelpFiles: Boolean;
begin
  Result := RVA_UseHelpFiles;
end;

procedure TRVAControlPanel.SetUseHelpFiles(const Value: Boolean);
begin
  RVA_UseHelpFiles := Value;
end;

function TRVAControlPanel.GetAddColorNameToHints: Boolean;
begin
  Result := RVA_AddColorNameToHints;
end;

procedure TRVAControlPanel.SetAddColorNameToHints(const Value: Boolean);
begin
  RVA_AddColorNameToHints := Value;
end;

function TRVAControlPanel.GetRVFLocalizable: Boolean;
begin
  Result := RVA_RVFLocalizable;
end;

procedure TRVAControlPanel.SetRVFLocalizable(const Value: Boolean);
begin
  RVA_RVFLocalizable := Value;
end;

function TRVAControlPanel.GetXMLLocalizable: Boolean;
begin
  Result := RVA_XMLLocalizable;
end;

procedure TRVAControlPanel.SetXMLLocalizable(const Value: Boolean);
begin
  RVA_XMLLocalizable := Value;
end;

function TRVAControlPanel.GetUserInterface: TRVAUserInterface;
begin
  Result := RVA_UserInterface;
end;

procedure TRVAControlPanel.SetUserInterface(
  const Value: TRVAUserInterface);
begin
  RVA_UserInterface := Value;
end;

function TRVAControlPanel.GetUnits: TRVUnits;
begin
  Result := RVA_Units;
end;

procedure TRVAControlPanel.SetUnits(const Value: TRVUnits);
begin
  RVA_Units := Value;
end;

function TRVAControlPanel.GetUnitsProgram: TRVStyleUnits;
begin
  Result := RVA_UnitsProgram;
end;

procedure TRVAControlPanel.SetUnitsProgram(const Value: TRVStyleUnits);
begin
  RVA_UnitsProgram := Value;
end;

function TRVAControlPanel.GetPixelBorders: Boolean;
begin
  Result := RVA_PixelBorders;
end;

procedure TRVAControlPanel.SetPixelBorders(const Value: Boolean);
begin
  RVA_PixelBorders := Value;
end;

function TRVAControlPanel.GetFirstPageNumber: Integer;
begin
  Result := RVA_FirstPageNumber;
end;

procedure TRVAControlPanel.SetFirstPageNumber(Value: Integer);
begin
  RVA_FirstPageNumber := Value;
end;

{$IFNDEF RVDONOTUSEDOCPARAMS}
function TRVAControlPanel.GetDefaultDocParameters: TRVDocParameters;
begin
  if RVA_DocParameters=nil then
    RVA_DocParameters := TRVDocParameters.Create;
  Result := RVA_DocParameters;
end;

procedure TRVAControlPanel.SetDefaultDocParameters(
  const Value: TRVDocParameters);
begin
  GetDefaultDocParameters.Assign(Value);
end;
{$ENDIF}

function TRVAControlPanel.GetOnAddStyle: TRVAddStyleEvent;
begin
  Result := RVA_Events.FOnAddStyle;
end;

procedure TRVAControlPanel.SetOnAddStyle(const Value: TRVAddStyleEvent);
begin
  RVA_Events.FOnAddStyle := Value;
end;

function TRVAControlPanel.GetOnStyleNeeded: TRVStyleNeededEvent;
begin
  Result := RVA_Events.FOnStyleNeeded;
end;

procedure TRVAControlPanel.SetOnStyleNeeded(const Value: TRVStyleNeededEvent);
begin
  RVA_Events.FOnStyleNeeded := Value;
end;

function TRVAControlPanel.GetOnMarginsChanged: TRVAEditEvent;
begin
  Result := RVA_Events.FOnMarginsChanged;
end;

function TRVAControlPanel.GetOnViewChanged: TRVAEditEvent2;
begin
  Result := RVA_Events.FOnViewChanged;
end;

procedure TRVAControlPanel.SetOnMarginsChanged(const Value: TRVAEditEvent);
begin
  RVA_Events.FOnMarginsChanged := Value;
end;

procedure TRVAControlPanel.SetOnViewChanged(const Value: TRVAEditEvent2);
begin
  RVA_Events.FOnViewChanged := Value;
end;

function TRVAControlPanel.GetOnBackgroundChange: TRVAEditEvent;
begin
  Result := RVA_Events.FOnBackgroundChange;
end;

procedure TRVAControlPanel.SetOnBackgroundChange(
  const Value: TRVAEditEvent);
begin
  RVA_Events.FOnBackgroundChange := Value;
end;

{$IFDEF USERVKSDEVTE}
function TRVAControlPanel.GetOnCreateTeForm: TRVCreateTeFormEvent;
begin
  Result := RVA_Events.FOnCreateTeForm;
end;

procedure TRVAControlPanel.SetOnCreateTeForm(
  const Value: TRVCreateTeFormEvent);
begin
  RVA_Events.FOnCreateTeForm := Value;
end;
{$ENDIF}

function TRVAControlPanel.GetOnCustomFileOperation: TRVCustomFileOperationEvent;
begin
  Result := RVA_Events.FOnCustomFileOperation;
end;

procedure TRVAControlPanel.SetOnCustomFileOperation(
  const Value: TRVCustomFileOperationEvent);
begin
  RVA_Events.FOnCustomFileOperation := Value;
end;

function TRVAControlPanel.GetOnDownload: TRVADownloadEvent;
begin
  Result := RVA_Events.FOnDownload;
end;

procedure TRVAControlPanel.SetOnDownload(const Value: TRVADownloadEvent);
begin
  RVA_Events.FOnDownload := Value;
end;

function TRVAControlPanel.GetLanguage: TRVALanguageName;
begin
  Result := RVA_GetLanguagename;
end;

procedure TRVAControlPanel.SetLanguage(const Value: TRVALanguageName);
begin
  RVA_SwitchLanguage(Value);
end;

function TRVAControlPanel.GetSearchScope: TRVASearchScope;
begin
  Result := RVA_SearchScope;
end;

procedure TRVAControlPanel.SetSearchScope(const Value: TRVASearchScope);
begin
  RVA_SearchScope := Value;
end;

function TRVAControlPanel.GetDefaultFileFormat: TrvFileSaveFilter;
begin
  Result := RVA_DefaultFileFormat;
end;

procedure TRVAControlPanel.SetDefaultFileFormat(
  const Value: TrvFileSaveFilter);
begin
  RVA_DefaultFileFormat := Value;
end;

function TRVAControlPanel.GetDefaultCustomFilterIndex: Integer;
begin
  Result := RVA_DefaultCustomFilterIndex;
end;

procedure TRVAControlPanel.SetDefaultCustomFilterIndex(
  const Value: Integer);
begin
  RVA_DefaultCustomFilterIndex := Value;
end;

{================================ TRVAPopupMenuHelper =========================}

constructor TRVAPopupMenuHelper.Create(APopupMenu: IRVAPopupMenu);
begin
  FPopupMenu := APopupMenu;
end;

destructor TRVAPopupMenuHelper.Destroy;
begin
  FPopupMenu := nil;
  inherited Destroy;
end;

function TRVAPopupMenuHelper.FindAction(ActionClass: TClass): TrvAction;
var i: Integer;
begin
  Result := nil;
  for i := 0 to FActionList.ActionCount-1 do
    if (FActionList.Actions[i].ClassType = ActionClass) then
      Result := TrvAction(FActionList.Actions[i]);
end;

procedure TRVAPopupMenuHelper.AddAction(ActionClass: TClass; const Caption: String);
var Action: TrvAction;
begin
  if ActionClass <> nil then
    begin
      Action := FindAction(ActionClass);
      if Action<>nil then
        FPopupMenu.AddActionItem(Action, Caption);
    end
  else
    FPopupMenu.AddSeparatorItem;
end;

{$IFNDEF RVDONOTUSELIVESPELL}
function TRVAPopupMenuHelper.GetSuggestions(const Word: String; StyleNo: Integer): TStringList;
var PopupComp: TComponent;
    Edit: TCustomRichViewEdit;
begin
  PopupComp := FPopupMenu.GetPopupComponent;
  if (PopupComp <> nil) and (PopupComp is TCustomRichViewEdit) then
    Edit := TCustomRichViewEdit(PopupComp)
  else
    Edit := nil;
  Result := TStringList.Create;
  if FPopupMenu.WantLiveSpellGetSuggestions then
    FPopupMenu.LiveSpellGetSuggestions(Edit, Word, StyleNo, Result)
  {$IFDEF USERVADDICT3}
  else if RVA_Addict3<>nil then
    RVA_Addict3.Suggest(Word, Result);
  {$ENDIF}
  ;
  if FMaxSuggestionsCount > 0 then
    while Result.Count > FMaxSuggestionsCount do
      Result.Delete(Result.Count-1);
end;

procedure TRVAPopupMenuHelper.CorrectMisspelling(Sender: TObject);
var PopupComp: TComponent;
    Edit: TCustomRichViewEdit;
    OldWord, Word: String;
    StyleNo, i: Integer;
begin
  PopupComp := FPopupMenu.GetPopupComponent;
  if (PopupComp=nil) or not (PopupComp is TCustomRichViewEdit) then
    exit;
  Edit := TCustomRichViewEdit(PopupComp);
  if Edit.GetCurrentMisspelling(True, OldWord, StyleNo) then begin
    Word := FPopupMenu.GetItemCaption(Sender);
    for i := Length(Word) downto 1 do
      if Word[i]='&' then
        Delete(Word, i, 1);
    FPopupMenu.LiveSpellWordReplace(Edit, OldWord, Word, FStyleNo);
    Edit.InsertText(Word);
  end;
end;

procedure TRVAPopupMenuHelper.OnIgnoreAll(Sender: TObject);
var PopupComp: TComponent;
    Edit: TCustomRichViewEdit;
    AWord: String;
    AStyleNo: Integer;
begin
  PopupComp := FPopupMenu.GetPopupComponent;
  if (PopupComp=nil) or not (PopupComp is TCustomRichViewEdit) then
    exit;
  Edit := TCustomRichViewEdit(PopupComp);
  if Edit.GetCurrentMisspelling(False, AWord, AStyleNo) then begin
    if FPopupMenu.WantLiveSpellIgnoreAll then
      FPopupMenu.LiveSpellIgnoreAll(Edit, AWord, AStyleNo)
    {$IFDEF USERVADDICT3}
    else if RVA_Addict3<>nil then
      RVA_Addict3.AddToIgnoreList(AWord)
    {$ENDIF};
    Edit.LiveSpellingValidateWord(AWord);
  end;
end;

procedure TRVAPopupMenuHelper.OnAddToDict(Sender: TObject);
var PopupComp: TComponent;
    Edit: TCustomRichViewEdit;
    AWord: String;
    AStyleNo: Integer;
begin
  PopupComp := FPopupMenu.GetPopupComponent;
  if (PopupComp=nil) or not (PopupComp is TCustomRichViewEdit) then
    exit;
  Edit := TCustomRichViewEdit(PopupComp);
  if Edit.GetCurrentMisspelling(False, AWord, AStyleNo) then begin
    if FPopupMenu.WantLiveSpellAdd then
      FPopupMenu.LiveSpellAdd(Edit, AWord, AStyleNo)
    {$IFDEF USERVADDICT3}
    else if RVA_Addict3<>nil then
      RVA_Addict3.AddToDictionary(AWord)
    {$ENDIF};
    Edit.LiveSpellingValidateWord(AWord);
  end;
end;
{$ENDIF}

procedure TRVAPopupMenuHelper.PreparePopup(X, Y: Integer);
var
  PopupComp: TComponent;
  rve: TCustomRichViewEdit;
  item: TCustomRVItemInfo;
  table: TRVTableItemInfo;
  a,b,c,d: Integer;
  {$IFNDEF RVDONOTUSELIVESPELL}
  sl: TStringList;
  Word: String;
  {$ENDIF}
begin
  FPopupMenu.ClearItems;
  if FActionList=nil then
    exit;
  PopupComp := FPopupMenu.GetPopupComponent;
  {$IFNDEF RVDONOTUSELIVESPELL}
  if (PopupComp<>nil) and (PopupComp is TCustomRichViewEdit) and
    TCustomRichViewEdit(PopupComp).GetCurrentMisspelling(False, Word, FStyleNo) then begin
    sl := GetSuggestions(Word, FStyleNo);
    for a := 0 to sl.Count-1 do begin
      FPopupMenu.AddClickItem(CorrectMisspelling, sl[a],
        TCustomRichViewEdit(PopupComp).Style.TextStyles[FStyleNo].Charset,
        True, True);
    end;
    if sl.Count>0 then
      AddAction(nil);
    sl.Free;
    if FPopupMenu.WantLiveSpellIgnoreAll
       {$IFDEF USERVADDICT3} or (RVA_Addict3<>nil) {$ENDIF} then begin
      FPopupMenu.AddClickItem(OnIgnoreAll, RVA_GetS(rvam_spell_IgnoreAll),
        RVA_GetCharset, True, False);
    end;
    if FPopupMenu.WantLiveSpellAdd
       {$IFDEF USERVADDICT3} or (RVA_Addict3<>nil) {$ENDIF} then begin
      FPopupMenu.AddClickItem(OnAddToDict, RVA_GetS(rvam_spell_AddToDictionary),
        RVA_GetCharset, FPopupMenu.WantLiveSpellAdd or
        {$IFDEF USERVADDICT3}((RVA_Addict3<>nil) and (RVA_Addict3.ActiveCustomDictionary<>nil)){$ELSE}True{$ENDIF},
        False);
    end;
    {$IFDEF USERVADDICT3}
    AddAction(TrvActionAddictSpell3);
    {$ENDIF}
    AddAction(nil);
  end;
  {$ENDIF}
  AddAction(TrvActionCut);
  AddAction(TrvActionCopy);
  AddAction(TrvActionPaste);
  AddAction(nil);
  AddAction(TrvActionFontEx);
  AddAction(TrvActionParagraph);
  AddAction(TrvActionParaList);
  if (PopupComp<>nil) and (PopupComp is TCustomRichViewEdit) then begin
    rve := TCustomRichViewEdit(PopupComp);
    if (-rve.CurItemStyle) in [-rvsComponent,-rvsPicture,-rvsHotPicture,-rvsBreak] then begin
      AddAction(nil);
      AddAction(TrvActionItemProperties);
    end;
    rve := TCustomRichViewEdit(rve.RVData.GetAbsoluteRootData.GetParentControl);
    if rve.GetCurrentItemEx(TRVTableItemInfo, rve, item) then begin
      AddAction(nil);
      table := TRVTableItemInfo(item);
      if table.GetNormalizedSelectionBounds(True,a,b,c,d) then begin
        AddAction(TrvActionTableInsertRowsAbove);
        AddAction(TrvActionTableInsertRowsBelow);
        AddAction(nil);
        AddAction(TrvActionTableInsertColLeft);
        AddAction(TrvActionTableInsertColRight);
        if d=table.Rows.Count then
          AddAction(TrvActionTableDeleteCols);
        if c=table.Rows[0].Count then
          AddAction(TrvActionTableDeleteRows);
        AddAction(nil);
        if table.GetEditedCell(a,b)=nil then
          AddAction(TrvActionFillColor);
        end
      else
        AddAction(TrvActionFillColor);
      if table.CanMergeSelectedCells(True) then
        AddAction(TrvActionTableMergeCells)
      else
        AddAction(TrvActionTableSplitCells);
      AddAction(TrvActionTableProperties);
    end;
  end;
  AddAction(nil);
  AddAction(TrvActionInsertHyperlink);
  FPopupMenu.DeleteLastSeparatorItem;
  inherited;
end;

{=================================== TRVAPopupMenu ============================}
constructor TRVAPopupMenu.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FPopupMenuHelper := TRVAPopupMenuHelper.Create(Self);
  MaxSuggestionsCount := 0;
end;

destructor TRVAPopupMenu.Destroy;
begin
  FPopupMenuHelper.Free;;
  inherited Destroy;
end;

procedure TRVAPopupMenu.Notification(AComponent: TComponent;
  Operation: TOperation);
begin
  inherited;
  if (Operation=opRemove) then
   if (AComponent=FPopupMenuHelper.FActionList) then
     FPopupMenuHelper.FActionList := nil;
end;

procedure TRVAPopupMenu.Popup(X, Y: Integer);
begin
  FPopupMenuHelper.PreparePopup(X, Y);
  inherited;
end;

function TRVAPopupMenu.GetPopupComponent: TComponent;
begin
  Result := GetRichViewEditFromPopupComponent(PopupComponent);
end;

function TRVAPopupMenu.GetActionList: TCustomActionList;
begin
  Result := FPopupMenuHelper.FActionList;
end;

procedure TRVAPopupMenu.SetActionList(const Value: TCustomActionList);
begin
  if Value <> FPopupMenuHelper.FActionList then
  begin
    {$IFDEF RICHVIEWDEF5}
    if FPopupMenuHelper.FActionList <> nil then
      FPopupMenuHelper.FActionList.RemoveFreeNotification(Self);
    {$ENDIF}
    FPopupMenuHelper.FActionList := Value;
    if FPopupMenuHelper.FActionList<> nil then
      FPopupMenuHelper.FActionList.FreeNotification(Self);
  end;
end;

function TRVAPopupMenu.GetMaxSuggestionsCount: Integer;
begin
  Result := FPopupMenuHelper.FMaxSuggestionsCount;
end;

procedure TRVAPopupMenu.SetMaxSuggestionsCount(Value: Integer);
begin
  FPopupMenuHelper.FMaxSuggestionsCount := Value;
end;

procedure TRVAPopupMenu.ClearItems;
begin
  while Items.Count>0 do
    Items.Items[0].Free;
end;

procedure TRVAPopupMenu.AddActionItem(Action: TAction; const Caption: String='');
var mi: TRVAPopupMenuItem;
begin
  mi := TRVAPopupMenuItem.Create(Self);
  mi.Action := Action;
  if Caption<>'' then
    mi.Caption := Caption;
  Items.Add(mi);
end;

procedure TRVAPopupMenu.AddSeparatorItem;
var mi: TRVAPopupMenuItem;
begin
  if (Items.Count=0) or (Items[Items.Count-1].Caption='-') then
    exit;
  mi := TRVAPopupMenuItem.Create(Self);
  mi.Caption := '-';
  Items.Add(mi);
end;

procedure TRVAPopupMenu.DeleteLastSeparatorItem;
begin
  if (Items.Count>0) and (Items[Items.Count-1].Caption='-') then
    Items.Items[Items.Count-1].Free;
end;

function TRVAPopupMenu.GetItemCaption(Sender: TObject): string;
begin
  Result := (Sender as TRVAPopupMenuItem).Caption;
end;

{$IFNDEF RVDONOTUSELIVESPELL}
procedure TRVAPopupMenu.AddClickItem(Click: TNotifyEvent; const Caption: String;
  Charset: TFontCharset; Enabled, Default: Boolean);
var mi: TRVAPopupMenuItem;
begin
  mi := TRVAPopupMenuItem.Create(Self);
  {$IFDEF USERVTNT}
  mi.Caption := RVU_RawUnicodeToWideString(RVU_AnsiToUnicode(
    RVU_Charset2CodePage(Charset), Caption));
  {$ELSE}
  mi.Caption :=   Caption;
  {$ENDIF}
  mi.Default := Default;
  mi.Enabled := Enabled;
  mi.OnClick := Click;
  Items.Add(mi);
end;

function TRVAPopupMenu.WantLiveSpellGetSuggestions: Boolean;
begin
  Result := Assigned(FOnLiveSpellGetSuggestions);
end;

procedure TRVAPopupMenu.LiveSpellGetSuggestions(Edit: TCustomRichViewEdit; const Word: String; StyleNo: Integer;
  Suggestions: TStrings);
begin
  if WantLiveSpellGetSuggestions then
    FOnLiveSpellGetSuggestions(Self, Edit, Word, StyleNo, Suggestions);
end;

procedure TRVAPopupMenu.LiveSpellWordReplace(Edit: TCustomRichViewEdit; const Word, Correction: String; StyleNo: Integer);
begin
  if Assigned(FOnLiveSpellWordReplace) then
    FOnLiveSpellWordReplace(Self, Edit, Word, Correction, StyleNo);
end;

function TRVAPopupMenu.WantLiveSpellIgnoreAll: Boolean;
begin
  Result := Assigned(FOnLiveSpellIgnoreAll);
end;

procedure TRVAPopupMenu.LiveSpellIgnoreAll(Edit: TCustomRichViewEdit; const Word: String; StyleNo: Integer);
begin
  if WantLiveSpellIgnoreAll then
    FOnLiveSpellIgnoreAll(Self, Edit, Word, StyleNo);
end;

function TRVAPopupMenu.WantLiveSpellAdd: Boolean;
begin
  Result := Assigned(FOnLiveSpellAdd);
end;

procedure TRVAPopupMenu.LiveSpellAdd(Edit: TCustomRichViewEdit; const Word: String; StyleNo: Integer);
begin
  if WantLiveSpellAdd then
    FOnLiveSpellAdd(Self, Edit, Word, StyleNo);
end;
{$ENDIF}

{================================== TRVATBPopupMenu ===========================}
{$IFDEF USETB2K}
constructor TRVATBPopupMenu.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FPopupMenuHelper := TRVAPopupMenuHelper.Create(Self);
  MaxSuggestionsCount := 0;
end;

destructor TRVATBPopupMenu.Destroy;
begin
  FPopupMenuHelper.Free;;
  inherited Destroy;
end;

procedure TRVATBPopupMenu.Notification(AComponent: TComponent;
  Operation: TOperation);
begin
  inherited;
  if (Operation=opRemove) then
   if (AComponent=FPopupMenuHelper.FActionList) then
     FPopupMenuHelper.FActionList := nil;
end;

procedure TRVATBPopupMenu.Popup(X, Y: Integer);
begin
  FPopupMenuHelper.PreparePopup(X, Y);
  inherited;
end;

function TRVATBPopupMenu.GetPopupComponent: TComponent;
begin
  Result := GetRichViewEditFromPopupComponent(PopupComponent);
end;

function TRVATBPopupMenu.GetActionList: TCustomActionList;
begin
  Result := FPopupMenuHelper.FActionList;
end;

procedure TRVATBPopupMenu.SetActionList(const Value: TCustomActionList);
begin
  if Value <> FPopupMenuHelper.FActionList then
  begin
    {$IFDEF RICHVIEWDEF5}
    if FPopupMenuHelper.FActionList <> nil then
      FPopupMenuHelper.FActionList.RemoveFreeNotification(Self);
    {$ENDIF}
    FPopupMenuHelper.FActionList := Value;
    if FPopupMenuHelper.FActionList<> nil then
      FPopupMenuHelper.FActionList.FreeNotification(Self);
  end;
end;

function TRVATBPopupMenu.GetMaxSuggestionsCount: Integer;
begin
  Result := FPopupMenuHelper.FMaxSuggestionsCount;
end;

procedure TRVATBPopupMenu.SetMaxSuggestionsCount(Value: Integer);
begin
  FPopupMenuHelper.FMaxSuggestionsCount := Value;
end;

procedure TRVATBPopupMenu.ClearItems;
begin
  while Items.Count>0 do
    Items.Items[0].Free;
end;

procedure TRVATBPopupMenu.AddActionItem(Action: TAction; const Caption: String='');
var mi: TTBItem;
begin
  mi := TTBItem.Create(Self);
  mi.Action := Action;
  if Caption<>'' then
    mi.Caption := Caption;
  Items.Add(mi);
end;

procedure TRVATBPopupMenu.AddSeparatorItem;
var mi: TTBSeparatorItem;
begin
  if (Items.Count=0) or (Items[Items.Count-1] is TTBSeparatorItem) then
    exit;
  mi := TTBSeparatorItem.Create(Self);
  Items.Add(mi);
end;

procedure TRVATBPopupMenu.DeleteLastSeparatorItem;
begin
  if (Items.Count>0) and (Items[Items.Count-1] is TTBSeparatorItem) then
    Items.Items[Items.Count-1].Free;
end;

function TRVATBPopupMenu.GetItemCaption(Sender: TObject): string;
begin
  Result := (Sender as TTBCustomItem).Caption;
end;

{$IFNDEF RVDONOTUSELIVESPELL}
procedure TRVATBPopupMenu.AddClickItem(Click: TNotifyEvent; const Caption: String;
  Charset: TFontCharset; Enabled, Default: Boolean);
var mi: TTBItem;
begin
  mi := TTBItem.Create(Self);
  mi.Caption := Caption;
  if Default then
    mi.Options := mi.Options + [tboDefault];
  mi.OnClick := Click;
  mi.Enabled := Enabled;
  Items.Add(mi);
end;

function TRVATBPopupMenu.WantLiveSpellGetSuggestions: Boolean;
begin
  Result := Assigned(FOnLiveSpellGetSuggestions);
end;

procedure TRVATBPopupMenu.LiveSpellGetSuggestions(Edit: TCustomRichViewEdit; const Word: String; StyleNo: Integer;
  Suggestions: TStrings);
begin
  if WantLiveSpellGetSuggestions then
    FOnLiveSpellGetSuggestions(Self, Edit, Word, StyleNo, Suggestions);
end;

procedure TRVATBPopupMenu.LiveSpellWordReplace(Edit: TCustomRichViewEdit; const Word, Correction: String; StyleNo: Integer);
begin
  if Assigned(FOnLiveSpellWordReplace) then
    FOnLiveSpellWordReplace(Self, Edit, Word, Correction, StyleNo);
end;

function TRVATBPopupMenu.WantLiveSpellIgnoreAll: Boolean;
begin
  Result := Assigned(FOnLiveSpellIgnoreAll);
end;

procedure TRVATBPopupMenu.LiveSpellIgnoreAll(Edit: TCustomRichViewEdit; const Word: String; StyleNo: Integer);
begin
  if WantLiveSpellIgnoreAll then
    FOnLiveSpellIgnoreAll(Self, Edit, Word, StyleNo);
end;

function TRVATBPopupMenu.WantLiveSpellAdd: Boolean;
begin
  Result := Assigned(FOnLiveSpellAdd);
end;

procedure TRVATBPopupMenu.LiveSpellAdd(Edit: TCustomRichViewEdit; const Word: String; StyleNo: Integer);
begin
  if WantLiveSpellAdd then
    FOnLiveSpellAdd(Self, Edit, Word, StyleNo);
end;
{$ENDIF}
{$ENDIF}


{================================== TRVATBXPopupMenu ===========================}
{$IFDEF USETBX}
constructor TRVATBXPopupMenu.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FPopupMenuHelper := TRVAPopupMenuHelper.Create(Self);
  MaxSuggestionsCount := 0;
end;

destructor TRVATBXPopupMenu.Destroy;
begin
  FPopupMenuHelper.Free;;
  inherited Destroy;
end;

procedure TRVATBXPopupMenu.Notification(AComponent: TComponent;
  Operation: TOperation);
begin
  inherited;
  if (Operation=opRemove) then
   if (AComponent=FPopupMenuHelper.FActionList) then
     FPopupMenuHelper.FActionList := nil;
end;

procedure TRVATBXPopupMenu.Popup(X, Y: Integer);
begin
  FPopupMenuHelper.PreparePopup(X, Y);
  inherited;
end;

function TRVATBXPopupMenu.GetPopupComponent: TComponent;
begin
  Result := GetRichViewEditFromPopupComponent(PopupComponent);
end;

function TRVATBXPopupMenu.GetActionList: TCustomActionList;
begin
  Result := FPopupMenuHelper.FActionList;
end;

procedure TRVATBXPopupMenu.SetActionList(const Value: TCustomActionList);
begin
  if Value <> FPopupMenuHelper.FActionList then
  begin
    {$IFDEF RICHVIEWDEF5}
    if FPopupMenuHelper.FActionList <> nil then
      FPopupMenuHelper.FActionList.RemoveFreeNotification(Self);
    {$ENDIF}
    FPopupMenuHelper.FActionList := Value;
    if FPopupMenuHelper.FActionList<> nil then
      FPopupMenuHelper.FActionList.FreeNotification(Self);
  end;
end;

function TRVATBXPopupMenu.GetMaxSuggestionsCount: Integer;
begin
  Result := FPopupMenuHelper.FMaxSuggestionsCount;
end;

procedure TRVATBXPopupMenu.SetMaxSuggestionsCount(Value: Integer);
begin
  FPopupMenuHelper.FMaxSuggestionsCount := Value;
end;

procedure TRVATBXPopupMenu.ClearItems;
begin
  while Items.Count>0 do
    Items.Items[0].Free;
end;

procedure TRVATBXPopupMenu.AddActionItem(Action: TAction; const Caption: String='');
var mi: TTBXItem;
begin
  mi := TTBXItem.Create(Self);
  mi.Action := Action;
  if Caption<>'' then
    mi.Caption := Caption;
  Items.Add(mi);
end;

procedure TRVATBXPopupMenu.AddSeparatorItem;
var mi: TTBXSeparatorItem;
begin
  if (Items.Count=0) or (Items[Items.Count-1] is TTBXSeparatorItem) then
    exit;
  mi := TTBXSeparatorItem.Create(Self);
  Items.Add(mi);
end;

procedure TRVATBXPopupMenu.DeleteLastSeparatorItem;
begin
  if (Items.Count>0) and (Items[Items.Count-1] is TTBXSeparatorItem) then
    Items.Items[Items.Count-1].Free;
end;

function TRVATBXPopupMenu.GetItemCaption(Sender: TObject): string;
begin
  Result := (Sender as TTBXCustomItem).Caption;
end;

{$IFNDEF RVDONOTUSELIVESPELL}
procedure TRVATBXPopupMenu.AddClickItem(Click: TNotifyEvent; const Caption: String;
  Charset: TFontCharset; Enabled, Default: Boolean);
var mi: TTBXItem;
begin
  mi := TTBXItem.Create(Self);
  mi.Caption := Caption;
  if Default then
    mi.Options := mi.Options + [tboDefault];
  mi.OnClick := Click;
  mi.Enabled := Enabled;
  Items.Add(mi);
end;

function TRVATBXPopupMenu.WantLiveSpellGetSuggestions: Boolean;
begin
  Result := Assigned(FOnLiveSpellGetSuggestions);
end;

procedure TRVATBXPopupMenu.LiveSpellGetSuggestions(Edit: TCustomRichViewEdit; const Word: String; StyleNo: Integer;
  Suggestions: TStrings);
begin
  if WantLiveSpellGetSuggestions then
    FOnLiveSpellGetSuggestions(Self, Edit, Word, StyleNo, Suggestions);
end;

procedure TRVATBXPopupMenu.LiveSpellWordReplace(Edit: TCustomRichViewEdit; const Word, Correction: String; StyleNo: Integer);
begin
  if Assigned(FOnLiveSpellWordReplace) then
    FOnLiveSpellWordReplace(Self, Edit, Word, Correction, StyleNo);
end;

function TRVATBXPopupMenu.WantLiveSpellIgnoreAll: Boolean;
begin
  Result := Assigned(FOnLiveSpellIgnoreAll);
end;

procedure TRVATBXPopupMenu.LiveSpellIgnoreAll(Edit: TCustomRichViewEdit; const Word: String; StyleNo: Integer);
begin
  if WantLiveSpellIgnoreAll then
    FOnLiveSpellIgnoreAll(Self, Edit, Word, StyleNo);
end;

function TRVATBXPopupMenu.WantLiveSpellAdd: Boolean;
begin
  Result := Assigned(FOnLiveSpellAdd);
end;

procedure TRVATBXPopupMenu.LiveSpellAdd(Edit: TCustomRichViewEdit; const Word: String; StyleNo: Integer);
begin
  if WantLiveSpellAdd then
    FOnLiveSpellAdd(Self, Edit, Word, StyleNo);
end;
{$ENDIF}
{$ENDIF}

{==============================================================================}



{==================================Start TRVASPTBXPopupMenu ===================}
{$IFDEF USESPTBX}
constructor TRVASpTBXPopupMenu.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FPopupMenuHelper := TRVAPopupMenuHelper.Create(Self);
  MaxSuggestionsCount := 0;
end;

destructor TRVASpTBXPopupMenu.Destroy;
begin
  FPopupMenuHelper.Free;;
  inherited Destroy;
end;

procedure TRVASpTBXPopupMenu.Notification(AComponent: TComponent;
  Operation: TOperation);
begin
  inherited;
  if (Operation=opRemove) then
   if (AComponent=FPopupMenuHelper.FActionList) then
     FPopupMenuHelper.FActionList := nil;
end;

procedure TRVASpTBXPopupMenu.Popup(X, Y: Integer);
begin
  FPopupMenuHelper.PreparePopup(X, Y);
  inherited;
end;

function TRVASpTBXPopupMenu.GetPopupComponent: TComponent;
begin
  Result := GetRichViewEditFromPopupComponent(PopupComponent);
end;

function TRVASpTBXPopupMenu.GetActionList: TCustomActionList;
begin
  Result := FPopupMenuHelper.FActionList;
end;

procedure TRVASpTBXPopupMenu.SetActionList(const Value: TCustomActionList);
begin
  if Value <> FPopupMenuHelper.FActionList then
  begin
    {$IFDEF RICHVIEWDEF5}
    if FPopupMenuHelper.FActionList <> nil then
      FPopupMenuHelper.FActionList.RemoveFreeNotification(Self);
    {$ENDIF}
    FPopupMenuHelper.FActionList := Value;
    if FPopupMenuHelper.FActionList<> nil then
      FPopupMenuHelper.FActionList.FreeNotification(Self);
  end;
end;

function TRVASpTBXPopupMenu.GetMaxSuggestionsCount: Integer;
begin
  Result := FPopupMenuHelper.FMaxSuggestionsCount;
end;

procedure TRVASpTBXPopupMenu.SetMaxSuggestionsCount(Value: Integer);
begin
  FPopupMenuHelper.FMaxSuggestionsCount := Value;
end;

procedure TRVASpTBXPopupMenu.ClearItems;
begin
  while Items.Count>0 do
    Items.Items[0].Free;
end;

procedure TRVASpTBXPopupMenu.AddActionItem(Action: TAction; const Caption: String='');
var mi: TSpTBXItem;
begin
  mi := TSpTBXItem.Create(Self);
  mi.Action := Action;
  if Caption<>'' then mi.Caption := Caption;
  Items.Add(mi);
end;

procedure TRVASpTBXPopupMenu.AddSeparatorItem;
var mi: TSpTBXSeparatorItem;
begin
  if (Items.Count=0) or (Items[Items.Count-1] is TSpTBXSeparatorItem) then
    exit;
  mi := TSpTBXSeparatorItem.Create(Self);
  Items.Add(mi);
end;

procedure TRVASpTBXPopupMenu.DeleteLastSeparatorItem;
begin
  if (Items.Count>0) and (Items[Items.Count-1] is TSpTBXSeparatorItem) then
    Items.Items[Items.Count-1].Free;
end;

function TRVASpTBXPopupMenu.GetItemCaption(Sender: TObject): string;
begin
  Result := (Sender as TSpTBXCustomItem).Caption;
end;

{$IFNDEF RVDONOTUSELIVESPELL}
procedure TRVASpTBXPopupMenu.AddClickItem(Click: TNotifyEvent; const Caption: String;
  Charset: TFontCharset; Enabled, Default: Boolean);
var mi: TSpTBXItem;
begin
  mi := TSpTBXItem.Create(Self);
  {$IFDEF USERVTNT}
  mi.Caption := RVU_RawUnicodeToWideString(RVU_AnsiToUnicode(
    RVU_Charset2CodePage(Charset), Caption));
  {$ELSE}
  mi.Caption :=   Caption;
  {$ENDIF}
  if Default then mi.Options := mi.Options + [tboDefault];
  mi.OnClick := Click;
  mi.Enabled := Enabled;
  Items.Add(mi);
end;

function TRVASpTBXPopupMenu.WantLiveSpellGetSuggestions: Boolean;
begin
  Result := Assigned(FOnLiveSpellGetSuggestions);
end;

procedure TRVASpTBXPopupMenu.LiveSpellGetSuggestions(Edit: TCustomRichViewEdit; const Word: String; StyleNo: Integer;
  Suggestions: TStrings);
begin
  if WantLiveSpellGetSuggestions then
    FOnLiveSpellGetSuggestions(Self, Edit, Word, StyleNo, Suggestions);
end;

procedure TRVASpTBXPopupMenu.LiveSpellWordReplace(Edit: TCustomRichViewEdit; const Word, Correction: String; StyleNo: Integer);
begin
  if Assigned(FOnLiveSpellWordReplace) then
    FOnLiveSpellWordReplace(Self, Edit, Word, Correction, StyleNo);
end;

function TRVASpTBXPopupMenu.WantLiveSpellIgnoreAll: Boolean;
begin
  Result := Assigned(FOnLiveSpellIgnoreAll);
end;

procedure TRVASpTBXPopupMenu.LiveSpellIgnoreAll(Edit: TCustomRichViewEdit; const Word: String; StyleNo: Integer);
begin
  if WantLiveSpellIgnoreAll then
    FOnLiveSpellIgnoreAll(Self, Edit, Word, StyleNo);
end;

function TRVASpTBXPopupMenu.WantLiveSpellAdd: Boolean;
begin
  Result := Assigned(FOnLiveSpellAdd);
end;

procedure TRVASpTBXPopupMenu.LiveSpellAdd(Edit: TCustomRichViewEdit; const Word: String; StyleNo: Integer);
begin
  if WantLiveSpellAdd then
    FOnLiveSpellAdd(Self, Edit, Word, StyleNo);
end;
{$ENDIF}
{$ENDIF}
{============================= End TRVASPTBXPopupMenu =========================}




procedure RVA_LocalizeForm(Form: TComponent);
var i: Integer;
begin
  for i := 0 to Form.ComponentCount-1 do
    if Form.Components[i] is TrvCustomAction then
      TrvCustomAction(Form.Components[i]).Localize;
end;

procedure RVA_ConvertToTwips(Form: TComponent);
var i: Integer;
begin
  for i := 0 to Form.ComponentCount-1 do
    if Form.Components[i] is TrvCustomAction then
      TrvCustomAction(Form.Components[i]).ConvertToTwips;
end;

procedure RVA_ConvertToPixels(Form: TComponent);
var i: Integer;
begin
  for i := 0 to Form.ComponentCount-1 do
    if Form.Components[i] is TrvCustomAction then
      TrvCustomAction(Form.Components[i]).ConvertToPixels;
end;

function RVA_ChooseLanguage: Boolean;
var frm: TfrmRVList;
    SL: TStringList;
    ItemIndex: Integer;
begin
  Result := False;
  frm := TfrmRVList.Create(Application);
  try
    frm.SetControlCaption(frm._btnOk, 'OK');
    frm.SetControlCaption(frm._btnCancel, 'Cancel');
    frm.SetFormCaption('Choose Language');
    frm.SetControlCaption(frm._lbl, '&Language:');
    frm.SetListBoxSorted(frm._lst);
    frm.HelpContext := 91301;
    SL := TStringList.Create;
    try
      SL.Sorted := True;
      RVA_FillLanguageList(SL);
      frm.SetXBoxItems(frm._lst, SL);
      ItemIndex := SL.IndexOf(RVA_GetLanguagename);
      frm.SetXBoxItemIndex(frm._lst, ItemIndex);
      if frm.ShowModal=mrOk then begin
        RVA_SwitchLanguage(SL[frm.GetXBoxItemIndex(frm._lst)]);
        Result := True;
      end;
    finally
      SL.Free;
    end;
  finally
    frm.Free;
  end;
end;
{================================ THFInfo =====================================}
constructor THFInfo.Create;
begin
  inherited Create;
  FFont := TFont.Create;
  FFont.Name := 'Arial';
  FFont.Size := 10;
  PrintOnFirstPage := True;
  Alignment := taCenter;
end;

destructor THFInfo.Destroy;
begin
  FFont.Free;
  inherited
end;

procedure THFInfo.SetFont(const Value: TFont);
begin
  FFont.Assign(Value);
end;

function RVA_HeaderInfo: THFInfo;
begin
  if RVA_HeaderInfo_=nil then begin
    RVA_HeaderInfo_ := THFInfo.Create;
    RVA_HeaderInfo_.Text := '- &p -';
  end;
  Result := RVA_HeaderInfo_;
end;

function RVA_FooterInfo: THFInfo;
begin
  if RVA_FooterInfo_=nil then begin
    RVA_FooterInfo_ := THFInfo.Create;
  end;
  Result := RVA_FooterInfo_;
end;
{============================== TRVAEvents ====================================}
procedure TRVAEvents.DoOnAddStyle(Sender: TrvAction; StyleInfo: TCustomRVInfo);
begin
  if Assigned(FOnAddStyle) then
    FOnAddStyle(Sender, StyleInfo);
end;

function TRVAEvents.DoStyleNeeded(Sender: TrvAction; RVStyle: TRVStyle;
        StyleInfo: TCustomRVInfo): Integer;
begin
  Result := -1;
  if Assigned(FOnStyleNeeded) then
    FOnStyleNeeded(Sender, RVStyle, StyleInfo, Result);
end;

procedure TRVAEvents.DoOnMarginsChanged(Sender: TrvAction; Edit: TCustomRichViewEdit);
begin
  if Assigned(FOnMarginsChanged) then
    FOnMarginsChanged(Sender, Edit);
end;

procedure TRVAEvents.DoOnViewChanged(Sender: TrvCustomAction; Edit: TCustomRichViewEdit);
begin
  if Assigned(FOnViewChanged) then
    FOnViewChanged(Sender, Edit);
end;

{$IFDEF USERVKSDEVTE}
procedure TRVAEvents.DoOnCreateTeForm(Sender: TForm; teForm: TTeForm);
begin
  if Assigned(FOnCreateTeForm) then
    FOnCreateTeForm(Sender, teForm);
end;
{$ENDIF}

function TRVAEvents.DoOnCustomFileOperation(Sender: TrvAction;
  Edit: TCustomRichViewEdit; const FileName: String; Operation: TRVAFileOperation;
  var SaveFormat: TrvFileSaveFilter;
  var CustomFilterIndex: Integer): Boolean;
var tmp: Integer;
    tmp2: TrvFileSaveFilter;
begin
  Result := False;
  try
    if Assigned(FOnCustomFileOperation) then begin
      tmp := CustomFilterIndex;
      tmp2:= SaveFormat;
      FOnCustomFileOperation(Sender, Edit, FileName, Operation, tmp2, tmp, Result);
      if Result and (Operation=rvafoOpen) then begin
        CustomFilterIndex := tmp;
        SaveFormat := tmp2;
      end;
    end;
  except
    Result := False;
  end;
end;


{$IFDEF RVAUSEHTTPDOWNLOADER}
function GetTempDir: String;
var l: Integer;
begin
  // Warning: : The GetTempPath function
  // does not verify that the returned
  // directory exists.
  SetLength(Result, 300);
  l := GetTempPath(300, PChar(Result));
  SetLength(Result, l);
end;
function GetTempFileName(const Ext: String): String;
var Path: String;
    v: Integer;
begin
  Path := GetTempDir+'tmp';
  v := Random(MaxInt div 2);
  repeat
    inc(v);
    Result := Path+IntToStr(v)+Ext;
  until not FileExists(Result);
end;
{$ENDIF}


procedure TRVAEvents.DoImportPicture(Sender: TCustomRichView;
  const Location: String; Width, Height: Integer; var Graphic: TGraphic);
var pic, pic2: TPicture;
    FileName: String;
    i: Integer;
    bmp: TBitmap;
    {$IFDEF RVAUSEHTTPDOWNLOADER}
    Stream : TMemoryStream;
    FileStream : TFileStream;
    TempFileName: String;
    Graphic2: TGraphic;
    {$ENDIF}
begin
  {$IFDEF RVAUSEHTTPDOWNLOADER}
  try
    if {$IFDEF USEINDY}(RVA_IdHttp<>nil) and{$ELSE}
       {$IFDEF USECLEVERCOMPONENTS}(RVA_ClHttp<>nil) and{$ENDIF}{$ENDIF}
       (Pos('http://', AnsiLowerCase(Location))=1) then begin
      if FDownloadedPictures.Find(Location, i) then begin
        Graphic := RV_CreateGraphics(
          TGraphicClass(TGraphic(FDownloadedPictures.Objects[i]).ClassType));
        Graphic.Assign(TGraphic(FDownloadedPictures.Objects[i]));
        exit;
      end;
      Stream := TMemoryStream.Create;
      try
        DoOnDownload(FSender, Location);
        try
          {$IFDEF USEINDY}
          RVA_IdHttp.Get(Location, Stream);
          {$ELSE}{$IFDEF USECLEVERCOMPONENTS}
          RVA_ClHttp.Get(Location, Stream);
          {$ENDIF}{$ENDIF}
        finally
          DoOnDownload(FSender, '');
        end;
        TempFileName := Location;
        for i := 1 to Length(TempFileName) do
          if {$IFDEF RVUNICODESTR}
           CharInSet(TempFileName[i],['<','>','"','|','?','*'])
           {$ELSE}
           TempFileName[i] in ['<','>','"','|','?','*']
           {$ENDIF} then
            TempFileName[i] := '_';
        TempFileName := GetTempFileName(ExtractFileExt(TempFileName));
        FileStream := TFileStream.Create(TempFileName, fmCreate);
        try
          FileStream.CopyFrom(Stream, 0);
        finally
          FileStream.Free;
        end;
        pic := TPicture.Create;
        try
          pic.LoadFromFile(TempFileName);
          Graphic := RV_CreateGraphics(TGraphicClass(pic.Graphic.ClassType));
          Graphic.Assign(pic.Graphic);
        finally
          pic.Free;
          DeleteFile(TempFileName);
        end;
      finally
        Stream.Free;
      end;
      if Graphic<>nil then begin
        Graphic2 := RV_CreateGraphics(TGraphicClass(Graphic.ClassType));
        Graphic2.Assign(Graphic);
        FDownloadedPictures.AddObject(Location, Graphic2)
      end;
    end;
  except
    Graphic.Free;
    Graphic := nil;
  end;
  if Graphic<>nil then
    exit;
  {$ENDIF}
  pic := TPicture.Create;
  try
    FileName := Location;
    for i := 1 to Length(FileName) do
      if FileName[i]='/' then
        FileName[i] := '\';
    pic.LoadFromFile(FileName);
    Graphic := RV_CreateGraphics(TGraphicClass(pic.Graphic.ClassType));
    Graphic.Assign(pic.Graphic);
  except
    Sender.CurPictureInvalid := True;
    pic2 := Sender.Style.InvalidPicture;
    if (pic2.Graphic<>nil) then
      if (Width<=0) or (Height<=0) then begin
        Graphic := RV_CreateGraphics(TGraphicClass(pic2.Graphic.ClassType));
        Graphic.Assign(pic2.Graphic);
        end
      else begin
        bmp := TBitmap.Create;
        bmp.Width := Width;
        bmp.Height := Height;
        bmp.Canvas.Brush.Color := clWhite;
        bmp.Canvas.FillRect(Rect(0,0,Width,Height));
        bmp.Canvas.Draw(1,1,pic2.Graphic);
        bmp.Canvas.Pen.Color := clWhite;
        bmp.Canvas.Brush.Style := bsClear;
        bmp.Canvas.Rectangle(1,1,pic2.Graphic.Width+1,pic2.Graphic.Height+1);
        bmp.Canvas.Pen.Color := clGray;
        bmp.Canvas.Rectangle(0,0,bmp.Width,bmp.Height);
        Graphic := bmp;
      end;
  end;
  pic.Free;
end;

procedure TRVAEvents.InitImportPictures(Sender: TRVAction);
begin
  {$IFDEF RVAUSEHTTPDOWNLOADER}
  FDownloadedPictures := TStringList.Create;
  FDownloadedPictures.Sorted := True;
  FDownloadedPictures.Duplicates := dupIgnore;
  //FDownloadedPictures.CaseSensitive := False;
  FSender := Sender;
  {$ENDIF}
end;

procedure TRVAEvents.DoneImportPictures;
{$IFDEF RVAUSEHTTPDOWNLOADER}
var i: Integer;
{$ENDIF}
begin
  {$IFDEF RVAUSEHTTPDOWNLOADER}
  for i := 0 to FDownloadedPictures.Count-1 do
    FDownloadedPictures.Objects[i].Free;
  FDownloadedPictures.Free;
  {$ENDIF}
end;

procedure TRVAEvents.DoOnBackgroundChange(Sender: TrvAction;
  Edit: TCustomRichViewEdit);
begin
  if Assigned(FOnBackgroundChange) then
    FOnBackgroundChange(Sender, Edit);
end;

procedure TRVAEvents.DoOnDownload(Sender: TrvAction; const Source: String);
begin
  if Assigned(FOnDownload) then
    FOnDownload(Sender, Source);
end;


function RVA_EditorControlFunctionDef(Control: TControl; Command: TRVAEditorControlCommand): Boolean;

    function GetEditorHandle: HWND;
    var cmbinfo: TComboBoxInfo;
    begin
      if Control is TCustomEdit then
        Result := TCustomEdit(Control).Handle
      else if Control is TCustomComboBox then begin
        FillChar(cmbinfo, sizeof(cmbinfo), 0);
        cmbinfo.cbSize := sizeof(cmbinfo);
        if Assigned(RVGetComboBoxInfo) and RVGetComboBoxInfo(TCustomComboBox(Control).Handle, cmbinfo) then
          Result := cmbinfo.hwndItem
        else
          Result := 0;
        end
      else
        Result := 0;
    end;

var Handle: HWND;
begin
  Result := True;
  case Command of
    rvaeccIsEditorControl:
      Result := (Control is TCustomEdit) or ((Control is TCustomComboBox) and
        (TComboBox(Control).Style in [csDropDown, csSimple]) and Assigned(RVGetComboBoxInfo));
    rvaeccHasSelection:
      if Control is TCustomEdit then
        Result := TCustomEdit(Control).SelLength>0
      else if Control is TCustomComboBox then
        Result := TCustomComboBox(Control).SelLength>0;
    rvaeccCanPaste, rvaeccCanPasteText:
      Result := Clipboard.HasFormat(CF_TEXT);
    rvaeccCanUndo:
      begin
        Handle := GetEditorHandle;
        if Handle<>0 then
          Result := SendMessage(Handle, EM_CANUNDO, 0, 0)<>0
        else
          Result := False;
      end;
    rvaeccCopy:
      begin
        Handle := GetEditorHandle;
        if Handle<>0 then
          SendMessage(Handle, WM_COPY, 0, 0);
       end;
    rvaeccCut:
      begin
        Handle := GetEditorHandle;
        if Handle<>0 then
          SendMessage(Handle, WM_CUT, 0, 0);
      end;
    rvaeccPaste, rvaeccPasteText:
      begin
        Handle := GetEditorHandle;
        if Handle<>0 then
          SendMessage(Handle, WM_PASTE, 0, 0);
      end;
    rvaeccUndo:
      begin
        Handle := GetEditorHandle;
        if Handle<>0 then
          SendMessage(Handle, WM_UNDO, 0, 0);
      end;
  end;
end;

procedure AssignFunctions;
var HLib: HModule;
begin
  HLib := LoadLibrary('user32.dll');
  if HLib<>0 then begin
    RVGetComboBoxInfo := TGetComboBoxInfoFunction(GetProcAddress(HLib, 'GetComboBoxInfo'));
    FreeLibrary(hLib);
  end;
end;

{
function HowManyLines(rv: TCustomRichView; MaxHeight: Integer): Integer;
var i: Integer;
begin
  Result := 0;
  for i := 0 to rv.RVData.DrawItems.Count-1 do
    if rv.RVData.DrawItems[i].FromNewLine then begin
      if rv.RVData.DrawItems[i].Top + rv.RVData.DrawItems[i].Height > MaxHeight then
        exit;
      inc(Result);
    end;
end;
}

type
  THtmlHelpW = function(hwndCaller: HWND; pszFile: PRVUnicodeChar; uCommand: UINT;
    dwData: DWORD): HWND; stdcall;

const
  HH_DISPLAY_TOC = $0001;
  HH_CLOSE_ALL   = $0012;

var FHHCtrlHandle: HMODULE;

function RvHtmlHelp(HelpFileName: TRVUnicodeString): Boolean;
var FHtmlHelpFunction: THtmlHelpW;
begin
  Result := False;
  if FHHCtrlHandle=0 then
    FHHCtrlHandle := LoadLibrary('HHCtrl.ocx');
  if (FHHCtrlHandle <> 0) then begin
    FHtmlHelpFunction := GetProcAddress(FHHCtrlHandle, 'HtmlHelpW');
    if Assigned(FHtmlHelpFunction) then begin
      FHtmlHelpFunction(GetDesktopWindow, PRVUnicodeChar(HelpFileName), HH_DISPLAY_TOC, 0);
      Result := True;
    end;
  end;
end;


procedure FinalizeChm;
var FHtmlHelpFunction: THtmlHelpW;
begin
  if (FHHCtrlHandle <> 0) then begin
    FHtmlHelpFunction := GetProcAddress(FHHCtrlHandle, 'HtmlHelpW');
    if Assigned(FHtmlHelpFunction) then
      FHtmlHelpFunction(0, nil, HH_CLOSE_ALL, 0);
    FreeLibrary(FHHCtrlHandle);
    FHHCtrlHandle := 0;
  end;
end;

function RVA_GetFineUnits: TRVUnits;
begin
  if RVA_Units=rvuPixels then
    Result := rvuPixels
  else
    Result := rvuPoints;
end;

function RVA_GetBorderUnits: TRVUnits;
begin
  if RVA_PixelBorders or (RVA_Units=rvuPixels) then
    Result := rvuPixels
  else
    Result := rvuPoints;
end;

{$IFDEF USERVTNT}
function RVAMessageBoxImpl(const Text, Caption: WideString; Flags: Longint): Integer;
begin
  Result := Windows.MessageBoxW(0, pWideChar(Text), pWideChar(Caption), Flags);
end;
{$ELSE}
function RVAMessageBoxImpl(const Text, Caption: String; Flags: Longint): Integer;
begin
  Result := Application.MessageBox(PChar(Text), PChar(Caption), Flags);
end;
{$ENDIF}

initialization
  Randomize;
  RVA_DialogFontName := 'MS Sans Serif';
  RVA_DialogFontSize := 8;
  RVA_UseXPThemes    := True;
  RVA_AutoDeleteUnusedStyles := True;
  RVA_DefaultControl := nil;
  RVA_ColorDialog    := nil;
  RVA_TableGridStyle := psDot;
  RVA_RVFFilter      := sFileFilterRVF;
  RVA_DefaultExt     := sRVFExtension;
  RVA_RVFormatName   := RVFormatName;
  RVA_DefaultFileName := 'Untitled.'+sRVFExtension;
  {$IFDEF USERVXML}
  RVA_XMLFilter      := sFileFilterXML;
  RVA_RVXML          := nil;
  {$ENDIF}
  {$IFDEF USERVHTML}
  RVA_RVHTML         := nil;
  {$ENDIF}
  {$IFDEF USERVHTMLVIEWER}
  RVA_RVHTMLView     := nil;
  {$ENDIF}
  {$IFDEF USERVADDICT3}
  RVA_Addict3        := nil;
  RVA_Thes3          := nil;
  {$ENDIF}
  {$IFDEF USEINDY}
  RVA_IdHTTP         := nil;
  {$ENDIF}
  {$IFDEF USECLEVERCOMPONENTS}
  RVA_ClHTTP         := nil;
  {$ENDIF}
  RVA_DefaultMargin  := 5;
  RVA_DefaultColor   := clWindow;
  RVA_RVPrint        := nil;
  RVA_ShowSoftPageBreaks := True;
  RVA_ActionsEnabled := True;
  RVA_RVFLocalizable := True;
  RVA_XMLLocalizable := True;
  RVA_HeaderInfo_     := nil;
  RVA_FooterInfo_     := nil;
  RVA_FirstPageNumber := 1;
  RVA_UseHelpFiles   := True;
  RVA_AddColorNameToHints := True;
  RVA_SearchScope := rvssAskUser;
  RVA_Events := TRVAEvents.Create;
  RVA_EditorControlFunction := RVA_EditorControlFunctionDef;
  RVA_DefaultFileFormat := ffeRVF;
  RVA_DefaultCustomFilterIndex := 1;
  RVA_UserInterface := rvauiFull;
  {$IFNDEF RVDONOTUSEDOCPARAMS}
  RVA_DocParameters  := nil;
  {$ENDIF}
  FHHCtrlHandle := 0;
  RVA_Units := rvuPixels;
  RVA_MessageBox := RVAMessageBoxImpl;
  AssignFunctions;
finalization
  RVA_HeaderInfo_.Free;
  RVA_FooterInfo_.Free;
  RVA_DocParameters.Free;
  RVA_Events.Free;
  RVA_HeaderInfo_     := nil;
  RVA_FooterInfo_     := nil;
  RVA_Events          := nil;
  {$IFNDEF RVDONOTUSEDOCPARAMS}
  RVA_DocParameters   := nil;
  {$ENDIF}

  FinalizeChm;

end.