
{*******************************************************}
{                                                       }
{       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
      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
      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
      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
    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 USEJVCL}
  JvWinDialogs,
  {$ENDIF}
  {$IFDEF USETB2K}
  TB2Item,
  {$ENDIF}
  {$IFDEF USETBX}
  TBX,
  {$ENDIF}
  {$IFDEF USESPTBX}
  SpTBXItem, SpTBXSkins,
  {$ENDIF}
  CRVData, RVClasses,RVOfficeCnv, 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, rvaeccCanUndo, rvaeccCopy, rvaeccCut, rvaeccPaste, 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);

  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;
  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;
  {$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 GetUseXPThemes: Boolean;
    procedure SetDialogFontName(const Value: TFontName);
    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 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);
    {$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);
  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 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}
    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;
    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 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;
  end;

  IRVAPopupMenu = interface
    function GetPopupComponent: TComponent;
    function GetActionList: TActionList;
    procedure SetActionList(const Value: TActionList);
    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: TActionList;
    {$IFNDEF RVDONOTUSELIVESPELL}
    FStyleNo: Integer;
    {$ENDIF}
    FMaxSuggestionsCount: Integer;
    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);
  public
    constructor Create(APopupMenu: IRVAPopupMenu); virtual;
    destructor Destroy; override;
  end;

  {$IFDEF USERVTNT}
  TRVAPopupMenuBase = TTntPopupMenu;
  TRVAPopupMenuItem = TTntMenuItem;
  {$ELSE}
  TRVAPopupMenuBase = TPopupMenu;
  TRVAPopupMenuItem = TMenuItem;
  {$ENDIF}

  TRVAPopupMenu = class (TRVAPopupMenuBase, IRVAPopupMenu)
  private
    FPopupMenuHelper: TRVAPopupMenuHelper;
    FOnLiveSpellGetSuggestions: TRVALiveSpellGetSuggestionsEvent;
    FOnLiveSpellAdd: TRVALiveSpellAddEvent;
    FOnLiveSpellIgnoreAll: TRVALiveSpellIgnoreAllEvent;
    FOnLiveSpellWordReplace: TRVALiveSpellReplaceEvent;
  protected
    { IRVAPopupMenu }
    function GetPopupComponent: TComponent;
    function GetActionList: TActionList;
    procedure SetActionList(const Value: TActionList);
    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: TActionList 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: TActionList;
    procedure SetActionList(const Value: TActionList);
    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: TActionList 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: TActionList;
    procedure SetActionList(const Value: TActionList);
    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: TActionList 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: TActionList;
    procedure SetActionList(const Value: TActionList);
    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: TActionList 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;
  public
    procedure Assign(Source: TPersistent); override;  
    {$ENDIF}
  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 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;
    procedure IterateRVData(RVData: TCustomRVData; rve: TCustomRichViewEdit; StartNo, EndNo: Integer;
      var CustomData: Integer);
  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;
  end;

  TrvActionSave = class;

  TrvActionNew = class(TrvAction)
  private
    FActionSave: TrvActionSave;
    FOnNew: TNotifyEvent;
    procedure SetActionSave(const Value: TrvActionSave);
    function GetActionSave: TrvActionSave;
  protected
    procedure Notification(AComponent: TComponent; Operation: TOperation); override;
    procedure Reset(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 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;
    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
    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;
  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 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;
  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 USERVHTML}
    function AllowPasteHTML: Boolean;
    {$ENDIF}
  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;
  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
    procedure ExecuteCommand(rve: TCustomRichViewEdit; Command: Integer);
    procedure ApplyConversion(Editor: TCustomRichViewEdit; FontInfo: TFontInfo;
      StyleNo, Command: Integer); virtual; abstract;
  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;
  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: Integer;
    FSubSuperScriptType: TRVSubSuperScriptType;
    FUnderlineColor: TColor;
    FUnderlineType: TRVUnderlineType;
  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
    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: Integer 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;
  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;
    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: Integer;
    function IsImageTooLarge(gr: TGraphic): Boolean;
    procedure GetProperImageSize(gr: TGraphic; var Width, Height: Integer);
  public
    constructor Create(AOwner: TComponent); override;
    procedure ExecuteTarget(Target: TObject); override;
    procedure UpdateTarget(Target: TObject); 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: Integer read FMaxImageSize write FMaxImageSize default 0;
  end;

  TrvActionInsertHLine = class(TrvAction)
  private
    FWidth: Integer;
    FColor: TColor;
  public
    constructor Create(AOwner: TComponent); override;
    procedure ExecuteTarget(Target: TObject); override;
    procedure UpdateTarget(Target: TObject); override;
  published
    property Color: TColor read FColor write FColor default clWindowText;
    property Width: Integer 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;



  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 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;

  { ------------------ 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;
  public
    constructor Create(AOwner: TComponent); override;
    procedure ExecuteTarget(Target: TObject); override;
  end;

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

  TrvActionParagraph = class(TrvActionParaStyles)
  private
    FAlignment: TRVAlignment;
    FLineSpacing: Integer;
    FLineSpacingType: TRVLineSpacingType;     
    FValidProperties: TRVParaInfoMainProperties;
    FSpaceBefore: Integer;
    FLeftIndent: Integer;
    FFirstIndent: Integer;
    FRightIndent: Integer;
    FSpaceAfter: Integer;
    FUserInterface: Boolean;
    FKeepWithNext: Boolean;
    FKeepLinesTogether: Boolean;
    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: Integer read FLeftIndent write FLeftIndent;
    property RightIndent: Integer read FRightIndent write FRightIndent;
    property FirstIndent: Integer read FFirstIndent write FFirstIndent;
    property SpaceBefore: Integer read FSpaceBefore write FSpaceBefore;
    property SpaceAfter: Integer read FSpaceAfter write FSpaceAfter;
    property Alignment: TRVAlignment read FAlignment write FAlignment;
    property LineSpacing: Integer 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;
  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)
  private
    FAlignment: TRVAlignment;
  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;

  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)
  private
    FIndentStep: Integer;
  published
    property IndentStep: Integer read FIndentStep write FIndentStep default 24;
  public
    constructor Create(AOwner: TComponent); override;
    procedure ExecuteTarget(Target: TObject); override;
  end;

  TrvActionIndentInc = class(TrvActionIndent)
  private
    FIndentMax: Integer;
  protected
    procedure ApplyConversion(Editor: TCustomRichViewEdit; ParaInfo: TParaInfo;
      StyleNo, Command: Integer); override;
  public
    constructor Create(AOwner: TComponent); override;
    procedure ExecuteTarget(Target: TObject); override;
  published
    property IndentMax: Integer 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;
  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;
  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)
  public
    constructor Create(AOwner: TComponent); override;
    procedure ExecuteTarget(Target: TObject); override;
    procedure UpdateTarget(Target: TObject); override;
  end;

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

  TrvActionItemProperties = class (TrvAction)
  private
    FGraphicFilter: String;
    FStoreImageFileName: Boolean;
    FBackgroundGraphicFilter: String;
    FOnCustomItemPropertiesDialog: TRVCustomItemPropertiesDialog;
  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 StoreImageFileName: Boolean
      read FStoreImageFileName write FStoreImageFileName default False;
  end;

  TrvActionBackground = class (TrvAction)
  private
    FOnChange: TRVAEditEvent;
    FImageFileName: String;
  public
    constructor Create(AOwner: TComponent); override;
    procedure ExecuteTarget(Target: TObject); override;
    property ImageFileName: String read FImageFileName;
    property OnChange: TRVAEditEvent read FOnChange write FOnChange;
  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: Integer;
    FCellPadding: Integer;
    FBorderWidth: Integer;
    FCellVSpacing: Integer;
    FHRuleWidth: Integer;
    FCellBorderWidth: Integer;
    FBorderHSpacing: Integer;
    FBorderVSpacing: Integer;
    FVRuleWidth: Integer;
    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: Integer);
    procedure SetTableCellsWidth(table: TRVTableItemInfo; Width: Integer);
    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;
  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: Integer 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: Integer read FBorderVSpacing write FBorderVSpacing default 2;
    property BorderHSpacing: Integer read FBorderHSpacing write FBorderHSpacing default 2;
    // Cells:
    property CellBorderWidth: Integer 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: Integer read FCellPadding write FCellPadding default 1;
    property CellBorderStyle: TRVTableBorderStyle read FCellBorderStyle write FCellBorderStyle default rvtbColor;
    // Between cells:
    property VRuleWidth: Integer read FVRuleWidth write FVRuleWidth default 0;
    property VRuleColor: TColor read FVRuleColor write FVRuleColor default clWindowText;
    property HRuleWidth: Integer read FHRuleWidth write FHRuleWidth default 0;
    property HRuleColor: TColor  read FHRuleColor write FHRuleColor default clWindowText;
    property CellVSpacing: Integer read FCellVSpacing write FCellVSpacing default 2;
    property CellHSpacing: Integer 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: Integer;
    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;
  public
    procedure ExecuteTarget(Target: TObject); override;
    constructor Create(AOwner: TComponent); 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: Integer read FIndentStep write FIndentStep default 24;
  end;

  TrvActionCustomParaListSwitcher = class(TrvAction)
  private
    FListLevels: TRVListLevelCollection;
    procedure SetListLevels(const Value: TRVListLevelCollection);
    function StoreListLevels: Boolean;
  protected
    procedure ResetLevels(AListLevels: TRVListLevelCollection); dynamic; abstract;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure Reset;
    procedure UpdateTarget(Target: TObject); override;
  published
    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 USEINDY}
      FDownloadedPictures: TStringList;
      FSender: TRVAction;
      {$ENDIF}
      FOnAddStyle: TRVAddStyleEvent;
      FOnStyleNeeded: TRVStyleNeededEvent;
      FOnMarginsChanged: TRVAEditEvent;
      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);
      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;

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


var RVA_DialogFontName: TFontName;
    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 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_UserInterface: TRVAUserInterface;


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);

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

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


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

{$IFDEF USERVHTML}
procedure PasteHTML(rve: TCustomRichViewEdit);
{$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;



implementation

uses
  CRVFData,
  {$IFDEF USEGLYFX}
  dmActionsGlyFX,
  {$ELSE}
  dmActions,
  {$ENDIF}
  BaseRVFrm,
  InsTableRVFrm, ColorRVFrm,
  IntegerRVFrm, SplitRVFrm, ParaRVFrm, FontRVFrm,
  FillColorRVFrm, ListRVFrm, RVStr, ParaBrdrRVFrm, ItemPropRVFrm, PreviewRVFrm,
  HypRVFrm, ListGalleryRVFrm, ListGallery2RVFrm, InsSymbolRVFrm, BackRVFrm, PageSetupRVFrm,
  RVCharCase, TableSizeRVFrm, RVLinear;

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 } { TrvaReplaceDialog }

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

  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;

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;

procedure RVA_DrawCmbWidthItem(Canvas: TCanvas; Rect: TRect; Index: Integer;
  Color: TColor; State: TOwnerDrawState);
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;
  Canvas.Pen.Width := Index+1;
  Canvas.MoveTo(Rect.Left-3, (Rect.Top+Rect.Bottom) div 2);
  Canvas.LineTo(Rect.Right+3, (Rect.Top+Rect.Bottom) div 2);
  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 i: Integer;
begin
  Canvas.Brush.Style := bsSolid;
  Canvas.Brush.Color := clWindow;
  Canvas.FillRect(Rect);
  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;
  InflateRect(Rect,-4,-4);
  Canvas.Pen.Style := psSolid;
  Canvas.Pen.Width := 1;

  for i := 0 to Index do begin
    Canvas.Pen.Color := Color1;
    Canvas.MoveTo(Rect.Left, Rect.Bottom);
    Canvas.LineTo(Rect.Left, Rect.Top);
    Canvas.LineTo(Rect.Right, Rect.Top);
    Canvas.Pen.Color := Color2;
    Canvas.LineTo(Rect.Right, Rect.Bottom);
    Canvas.LineTo(Rect.Left, Rect.Bottom);
    InflateRect(Rect,-1,-1);
  end;
end;

function FindComponentByClass(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 USERVHTML}
procedure PasteHTML(rve: TCustomRichViewEdit);
var rv: TRichView;
    rvs: TRVStyle;
    RVData: TCustomRVData;
    StartNo, EndNo: Integer;
    Stream : TMemoryStream;
    SelRec : TRVSelection;
begin
  if RVA_RVHTML=nil then
    exit;
  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);
      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;
    finally
      rv.Free;
      rvs.Free;
      RVA_RVHTML.RichView := nil;
    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;

{----------------------- 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}

{ 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;

procedure TrvAction.IterateRVData(RVData: TCustomRVData; rve: TCustomRichViewEdit; StartNo, EndNo: Integer;
                        var CustomData: Integer);
var i: Integer;
    item: TCustomRVItemInfo;
    StoreSub: TRVStoreSubRVData;
    SubRVData: TCustomRVData;
begin
  item := TCustomRVFormattedData(RVData).PartialSelectedItem;
  if item<>nil then begin
    SubRVData := TCustomRVData(item.GetSubRVData(StoreSub, rvdChosenDown));
    if SubRVData<>nil 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.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;
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;
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(Target, 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;
  rve.Clear;
  Reset(rve);
  RVA_Events.DoOnMarginsChanged(Self, rve);  
  rve.Format;
  if RVA_AutoDeleteUnusedStyles then
    rve.DeleteUnusedStyles(True, True, True);
  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(FindComponentByClass(Owner, TrvActionSave));
end;

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

procedure TrvActionNew.Reset(rve: TCustomRichViewEdit);
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}
    rve.DocParameters.ResetLayout;
    {$ENDIF}
  end;
  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;

{ 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);
    rve.Clear;
    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;
              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;
  AActionSave.AddDoc(rve, FileName, SaveFormat, CustomFilterIndex, True, False,
    False, False);
  if not r then begin
    Application.MessageBox(RVA_GetPC(rvam_err_ErrorLoadingFile),
      RVA_GetPC(rvam_err_Title), MB_OK or MB_ICONSTOP);
    rve.Modified := True;
  end;
  RVA_Events.DoOnMarginsChanged(Self, rve);
  rve.Format;
  if RVA_AutoDeleteUnusedStyles then
    rve.DeleteUnusedStyles(True,True,True);
  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.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 := TrvaDocumentInfo.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;

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(FindComponentByClass(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 (Application.MessageBox(PChar(Format(RVA_GetS(rvam_LostFormat), [ExtractFileName(doc.FileName)])),
        RVA_GetPC(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;
            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
    Application.MessageBox(RVA_GetPC(rvam_err_ErrorSavingFile),
      RVA_GetPC(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 Application.MessageBox(
    PChar(Format(RVA_GetS(rvam_SaveChanges), [ExtractFileName(TrvaDocumentInfo(FDocuments.Items[idx]).FileName)])),
    RVA_GetPC(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(FindComponentByClass(Owner, TrvActionSave));
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 (Application.MessageBox(PChar(Format(RVA_GetS(rvam_LostFormat), [ExtractFileName(FileName)])),
              RVA_GetPC(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.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;
            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
    Application.MessageBox(RVA_GetPC(rvam_err_ErrorSavingFile),
      RVA_GetPC(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;

procedure TrvActionInsertFile.ExecuteTarget(Target: TObject);
var
  FilterList: TRVIntegerList;
  FilterString: String;
  rve: TCustomRichViewEdit;
  r : Boolean;
  rvc: TRVOfficeConverter;
  ChosenFormat: TrvFileImportFilter;
  ConverterOrCustomIndex: Integer;
  DummySaveFormat: TrvFileSaveFilter;
  ImpPicAssigned: Boolean;
  {$IFDEF RVAHTML}
  rv: TRichView;
  rvs: TRVStyle;
  Stream: TStream;
  {$IFDEF USERVHTML}
  s: TRVRawByteString;
  {$ENDIF}
  {$ENDIF}
begin
  rve := GetControl(Target);
  rvc := nil;
  FilterList := TRVIntegerList.Create;
  try
    if ffiOfficeConverters in Filter then begin
      rvc := TRVOfficeConverter.Create(nil);
      {$IFDEF RVAHTML}
      rvc.ExcludeHTMLImportConverter := True;
      {$ENDIF}
      rvc.ExtensionsInFilter := True;
    end;
    FilterString := MakeImportFilter(Filter, FilterList, RVA_RVFFilter,
      CustomFilter, rvc);
    {$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_InsertFile));
      FilterIndex := FLastFilterIndex;
      FileName := FFileName;
      if FFileName='' then
        InitialDir := FInitialDir;
      if Execute then 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
            if Screen.ActiveForm<>nil then
              Screen.ActiveForm.Update;
            FLastFilterIndex := FilterIndex;
            GetImportFilterFormat(FilterList, FilterIndex-1, ChosenFormat,
              ConverterOrCustomIndex);
            case ChosenFormat of
              ffiRVF:
                r := rve.InsertRVFFromFileEd(FileName);
              ffiRTF:
                r := rve.InsertRTFFromFileEd(FileName);
              {$IFDEF USERVXML}
              ffiXML:
                begin
                  try
                    r := True;
                    RVA_RVXML.RichView := rve;
                    RVA_RVXML.InsertFromFile(FileName);
                  except
                    r := False;
                  end;
                end;
              {$ENDIF}
              ffiTextANSI:
                r := rve.InsertTextFromFile(FileName);
              ffiTextUnicode:
                r := rve.InsertTextFromFileW(FileName);
              ffiTextAuto:
                if RV_TestFileUnicode(FileName) = rvutYes then
                  r := rve.InsertTextFromFileW(FileName)
                else
                  r := rve.InsertTextFromFile(FileName);
              {$IFDEF RVAHTML}
              ffiHTML:
                begin
                  r := 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;
                        r := rve.InsertRVFFromStreamEd(Stream);
                      finally
                        Stream.Free;
                      end;
                    finally
                      rv.Free;
                      rvs.Free;
                      {$IFNDEF USERVHTMLVIEWER}
                      {$IFDEF USERVHTML}
                      RVA_RVHTML.RichView := nil;
                      {$ENDIF}
                      {$ENDIF}
                    end;
                  except
                    r := False;
                  end;
                end;
              {$ENDIF}
              ffiCustom:
                begin
                  DummySaveFormat := ffeCustom;
                  r := RVA_Events.DoOnCustomFileOperation(Self, rve, FileName,
                    rvafoInsert, DummySaveFormat, ConverterOrCustomIndex);
                end;
              ffiOfficeConverters:
                begin
                  r := rvc.ImportRTF(FileName, ConverterOrCustomIndex);
                  {
                  with TFileStream.Create('d:\1.rtf', fmCreate) do begin
                    CopyFrom(rvc.Stream, 0);
                    Free;
                  end;
                  }
                  if r then begin
                    rvc.Stream.Position := 0;
                    r := rve.InsertRTFFromStreamEd(rvc.Stream);
                  end;
                end;
              else
                r := False;
            end;
          finally
            if not ImpPicAssigned then begin
              rve.OnImportPicture := nil;
              RVA_Events.DoneImportPictures;
            end;
          end;
        finally
          Screen.Cursor := crDefault;
        end;
        if not r then begin
          rve.Format;
          Application.MessageBox(RVA_GetPC(rvam_err_ErrorLoadingFile),
            RVA_GetPC(rvam_err_Title), MB_OK or MB_ICONSTOP);
          end
        else if 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>MaxImageSize) or (gr.Height>MaxImageSize));
end;

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

procedure TrvActionInsertPicture.ExecuteTarget(Target: TObject);
var pic: TPicture;
    gr: TGraphic;
    rve: TCustomRichViewEdit;
    ItemName: TRVAnsiString;
    IsGroupOperation, IsTooLarge: Boolean;
    ImageWidth, ImageHeight: Integer;
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, ImageWidth, ImageHeight);
              rve.SetCurrentItemExtraIntProperty(rvepImageHeight, ImageHeight, True);
              rve.SetCurrentItemExtraIntProperty(rvepImageWidth, ImageWidth, True);              
            end;
          end;
        finally
          if IsGroupOperation then begin
            if IsTooLarge then
              rve.EndUpdate;
            rve.SetUndoGroupMode(False);
          end;
        end;
        FFileName := FileName;
      except
        Application.MessageBox(RVA_GetPC(rvam_err_ErrorLoadingImageFile),
          RVA_GetPC(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 then begin
    Enabled := False;
    exit;
  end;
  rve := GetControl(Target).TopLevelEditor;
  Enabled := {not rve.ReadOnly and} (rve.RVData.PartialSelectedItem=nil);
end;

{ TrvActionInsertHLine }

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

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

procedure TrvActionInsertHLine.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;

{ 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;
    i, StartNo, EndNo: Integer;
begin
  if not RVA_ActionsEnabled or Disabled 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);
    if en then begin
      GetSelectionBounds(rve, StartNo, EndNo);
      for i := StartNo to EndNo do
        if rve.GetItemStyle(i)=rvsTable then begin
          en := False;
          break;
        end;
    end;
    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;

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
     {$IFDEF RVUNICODESTR}
     CharInSet(s[1], ['<','(','{','[','''','"','‘','’','“','”'])
     {$ELSE}
     (s[1] in ['<','(','{','[','''','"','‘','’','“','”'])
     {$ENDIF} then begin
    inc(WordStart);
    s := Copy(s, 2, Length(s)-1);
  end;
  if (Length(s)>0) and
     {$IFDEF RVUNICODESTR}
     CharInSet(s[Length(s)], ['>',')','}',']','''','"','‘','’','“','”',',',':',';'])
     {$ELSE}
     (s[Length(s)] in ['>',')','}',']','''','"','‘','’','“','”',',',':',';'])
     {$ENDIF} 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.ApplyTextStyle(GetHyperlinkStyleNo(rve));
    if not RVIsURL(s) and RVIsEmail(s) then
      s := 'mailto:'+s;
    rve.SetCurrentTag(Integer(StrNew(PChar(EncodeTarget(s)))));
    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;


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
      Application.MessageBox(PChar(Format(RVA_GetS(rvam_hl_CannotNavigate),[URL])),
        RVA_GetPC(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
    Application.MessageBox(PChar(Format(RVA_GetS(rvam_hl_CannotNavigate),[URL])),
      RVA_GetPC(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;


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


{ TrvCustomPrintAction }

function TrvCustomPrintAction.FindRVPrint(Form: TComponent): TRVPrint;
begin
  Result := TRVPrint(FindComponentByClass(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, 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;

{ 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: 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
        AActionPrint.ExecuteTarget(Target);
      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(FindComponentByClass(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 then begin
      Dlg := TPrintDialog.Create(Application);
      try
        Dlg.Options := Dlg.Options + [poPageNums];
        if rve.SelectionExists then
          Dlg.Options := Dlg.Options + [poSelection];
        Dlg.MinPage := 1;
        Dlg.MaxPage := ARVPrint.PagesCount;
        Dlg.FromPage := 1;
        Dlg.ToPage := ARVPrint.PagesCount;
        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;

{ 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;

{$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;
    s: String;
    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_GetS(rvam_src_ContinueFromStart);
      SecondAttempt := (FEdit.InplaceEditor=nil) and
        ((FEdit.CurItemNo>0) or (FEdit.OffsetInCurItem>FEdit.GetOffsBeforeItem(0)));
      end
    else begin
      s := RVA_GetS(rvam_src_ContinueFromEnd);
      SecondAttempt := (FEdit.InplaceEditor=nil) and
        ((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
       (Application.MessageBox(PChar(s), RVA_GetPC(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
   Application.MessageBox(
     PChar(Format(RVA_GetS(rvam_src_NotFound),[FFindDialog.FindText])),
     RVA_GetPC(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(FindComponentByClass(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(FindComponentByClass(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(FindComponentByClass(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;
    s: String;
    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_GetS(rvam_src_ContinueFromStart);
      SecondAttempt := (FEdit.InplaceEditor=nil) and
        ((FEdit.CurItemNo>0) or (FEdit.OffsetInCurItem>FEdit.GetOffsBeforeItem(0)));
      end
    else begin
      s := RVA_GetS(rvam_src_ContinueFromEnd);
      SecondAttempt := (FEdit.InplaceEditor=nil) and
        ((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
       (Application.MessageBox(PChar(s), RVA_GetPC(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
   Application.MessageBox(PChar(Format(RVA_GetS(rvam_src_NotFound),[FReplaceDialog.FindText])),
     RVA_GetPC(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;
    s, sq: String;
    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_GetS(rvam_src_ContinueFromStart);
        SecondAttempt := (FEdit.InplaceEditor=nil) and
          ((FEdit.CurItemNo>0) or (FEdit.OffsetInCurItem>FEdit.GetOffsBeforeItem(0)));
        end
      else begin
        sq := RVA_GetS(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_GetS(rvam_src_1Replaced)
        else
          s := Format(RVA_GetS(rvam_src_NReplaced), [c]);
        Application.MessageBox(PChar(s), RVA_GetPC(rvam_src_Complete), MB_OK or MB_ICONINFORMATION);
      end;
      if SecondAttempt then begin
        if FShowReplaceAllSummary then begin
          if c=1 then
            s := RVA_GetS(rvam_src_1Replaced)
          else
            s := Format(RVA_GetS(rvam_src_NReplaced), [c]);
          sq := s+#13+sq;
        end;
        SecondAttempt := (RVA_SearchScope=rvssAskUser) and
          (Application.MessageBox(PChar(sq), RVA_GetPC(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 USERVHTML}
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);
    ImpPicAssigned := Assigned(rve.OnImportPicture);
    if not ImpPicAssigned then begin
      RVA_Events.InitImportPictures(Self);
      rve.OnImportPicture := RVA_Events.DoImportPicture;
    end;
    try
      {$IFDEF USERVHTML}
      if (RVA_RVHTML<>nil) 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_EditorControlFunction(TControl(Target), rvaeccCanPaste)
  else
    Enabled := RVA_ActionsEnabled and not Disabled and
      GetControl(Target).CanPaste;
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 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 USERVHTML}
        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;

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);
  finally
    SetStyleConversionEvent(rve, FOldOnStyleConversion);
  end;
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;

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;
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);
  begin
    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 := CharSpacing;
        frm.rbExp.Checked := True;
        end
      else begin
        frm.seSpacing.Value := -CharSpacing;
        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.seSpacing.AsInteger
      else
        CharSpacing := frm.seSpacing.AsInteger;
    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
    ExecuteCommand(rve, 0);
    exit;
  end;
  GetFromEditor(rve);
  frm := TfrmRVFont.Create(Application);
  try
    frm.ColorDialog := RVA_ColorDialog;
    SetToForm(frm);
    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;

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;

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 not rve.ReadOnly};
    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;
    IterateRVData(rve.RVData, rve, -1, -1, Chk);
    Checked := Chk<>0;
  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);
    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;
    IterateRVData(rve.RVData, rve, -1, -1, Chk);
    Checked := Chk<>0;
  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);
    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;
    IterateRVData(rve.RVData, rve, -1, -1, Chk);
    Checked := Chk<>0;
  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);
    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;
    IterateRVData(rve.RVData, rve, -1, -1, Chk);
    Checked := Chk<>0;
  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;

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 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-1;
    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
      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 := Abs(FirstIndent);
      end;
      if rvpimLeftIndent in ValidProperties then
        frm.seLeftIndent.Value := LeftIndent;
      if rvpimRightIndent in ValidProperties then
        frm.seRightIndent.Value := RightIndent;
      if rvpimSpaceBefore in ValidProperties then
        frm.seSpaceBefore.Value := SpaceBefore;
      if rvpimSpaceAfter in ValidProperties then
        frm.seSpaceAfter.Value := SpaceAfter;
      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.seLineSpacingValue.IntegerValue := True;
              frm.seLineSpacingValue.MinValue := 5;
              frm.seLineSpacingValue.MaxValue := 1000;
              frm.seLineSpacingValue.Value := LineSpacing;
            end;
        end
      else
        frm.SetXBoxItemIndex(frm._cmbLineSpacing, 5);
      frm.seLeftIndent.MinValue := - rve.LeftMargin;
      frm.seRightIndent.MinValue := - rve.RightMargin;
      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 :=  frm.seSpaceBefore.AsInteger;
      end;
      if not frm.seSpaceAfter.Indeterminate then begin
        Include(FValidProperties, rvpimSpaceAfter);
        SpaceAfter :=  frm.seSpaceAfter.AsInteger;
      end;
      if not frm.seLeftIndent.Indeterminate then begin
        Include(FValidProperties, rvpimLeftIndent);
        LeftIndent :=  frm.seLeftIndent.AsInteger;
      end;
      if not frm.seRightIndent.Indeterminate then begin
        Include(FValidProperties, rvpimRightIndent);
        RightIndent :=  frm.seRightIndent.AsInteger;
      end;
      if not frm.seFirstLineIndent.Indeterminate then begin
        Include(FValidProperties, rvpimFirstIndent);
        if frm.rbNegative.Checked then
          FirstIndent := -frm.seFirstLineIndent.AsInteger
        else
          FirstIndent := frm.seFirstLineIndent.AsInteger;
      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 := frm.seLineSpacingValue.AsInteger;
           end;
        4: begin
             LineSpacingType := rvlsLineHeightExact;
             if frm.seLineSpacingValue.Indeterminate then
               Exclude(FValidProperties, rvpimLineSpacing)
             else
               LineSpacing := frm.seLineSpacingValue.AsInteger;
           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;
    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 (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;
    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;
    IterateRVData(rve.RVData, rve, -1, -1, Chk);
    Checked := Chk=0;
  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;
    rve := GetControl(Target).TopLevelEditor;
    if rve.RVData.PartialSelectedItem=nil then begin
      Checked := rve.Style.ParaStyles[rve.CurParaStyleNo].Alignment = FAlignment;
      exit;
    end;
    Chk := 1;
    IterateRVData(rve.RVData, rve, -1, -1, Chk);
    Checked := Chk<>0;
  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;
    rve := GetControl(Target).TopLevelEditor;
    if rve.RVData.PartialSelectedItem=nil then begin
      Checked := rve.Style.ParaStyles[rve.CurParaStyleNo].BiDiMode=FBiDiMode;
      exit;
    end;
    Chk := 1;
    IterateRVData(rve.RVData, rve, -1, -1, Chk);
    Checked := Chk<>0;
  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
  ExecuteCommand(GetControl(Target), GetControl(Target).LeftMargin);
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 - IndentStep;
    if ParaInfo.LeftIndent < 0 then
      ParaInfo.LeftIndent := 0;
    if Editor.LeftMargin + ParaInfo.LeftIndent + ParaInfo.FirstIndent < 0 then
      ParaInfo.FirstIndent := -Editor.LeftMargin -ParaInfo.LeftIndent;
    if ParaInfo.Border.Style<>rvbNone then begin
      if ParaInfo.LeftIndent<ParaInfo.Border.BorderOffsets.Left+ParaInfo.Border.GetTotalWidth-1 then
        ParaInfo.LeftIndent := ParaInfo.Border.BorderOffsets.Left+ParaInfo.Border.GetTotalWidth-1;
    end;
    end
  else begin
    ParaInfo.RightIndent := ParaInfo.RightIndent - IndentStep;
    if ParaInfo.RightIndent < 0 then
      ParaInfo.RightIndent := 0;
    if Editor.RightMargin + ParaInfo.RightIndent + ParaInfo.FirstIndent < 0 then
      ParaInfo.FirstIndent := -Editor.RightMargin -ParaInfo.RightIndent;
    if ParaInfo.Border.Style<>rvbNone then begin
      if ParaInfo.RightIndent<ParaInfo.Border.BorderOffsets.Right+ParaInfo.Border.GetTotalWidth-1 then
        ParaInfo.RightIndent := ParaInfo.Border.BorderOffsets.Right+ParaInfo.Border.GetTotalWidth-1;
    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 + IndentStep;
    if ParaInfo.LeftIndent > IndentMax then
      ParaInfo.LeftIndent := IndentMax;
    end
  else begin
    ParaInfo.RightIndent := ParaInfo.RightIndent + IndentStep;
    if ParaInfo.RightIndent > IndentMax then
      ParaInfo.RightIndent := IndentMax;
  end;
end;

procedure TrvActionIndentInc.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;

{ 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;
    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;
    IterateRVData(rve.RVData, rve, -1, -1, Chk);
    Checked := Chk<>0;
  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;
  FBackground := TRVBackgroundRect.Create;
  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-1;
    NormalizeIndents(ParaInfo.Border.BorderOffsets, w);
  end;
  NormalizeIndents(ParaInfo.Background.BorderOffsets, 0);
end;

procedure TrvActionParaBorder.ExecuteTarget(Target: TObject);

  procedure SetToForm(frm: TfrmRVParaBrdr);
  var idx: Integer;
      br: TRVBooleanRect;
  begin
    frm.ColorDialog := RVA_ColorDialog;

    if rvpibBorder_Width in ValidProperties then begin
      idx := FBorder.Width-1;
      if (idx<0) or (idx>=frm.GetXBoxItemCount(frm._cmbWidth)) then
        idx := -1;
      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 := FBorder.InternalWidth;
    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 := frm.GetXBoxItemIndex(frm._cmbWidth)+1;
    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.seIW.AsInteger;
    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);
    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]
    else
      rve.Options := rve.Options+[rvoShowSpecialCharacters];
    rve.Reformat;      
    rve := TCustomRichViewEdit(rve.InplaceEditor);
  end;
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.ExecuteCommand(rve: TCustomRichViewEdit;
  Command: Integer);
begin
  FEdit.Color := Color;
  if rvfoSaveBack in FEdit.RVFOptions then
    FEdit.Modified := True;
  RVA_Events.DoOnBackgroundChange(Self, FEdit);    
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);
      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;


{ TrvActionInsertPageBreak }

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

procedure TrvActionInsertPageBreak.ExecuteTarget(Target: TObject);
begin
  GetControl(Target).InsertPageBreak;
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;

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;

{ 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 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);
    end;
    Enabled := en;
  except
    Enabled := False;
  end;
end;

{ TrvActionBackground }

constructor TrvActionBackground.Create(AOwner: TComponent);
begin
  inherited;
  FMessageID := rvam_act_Background;
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);
    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;

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

{ TrvActionInsertTable }

procedure TrvActionInsertTable.ApplyToTable(table: TRVTableItemInfo;
  ABestWidth: Integer);
begin
  table.BestWidth            := ABestWidth;
  table.Options              := TableOptions;
  table.PrintOptions         := TablePrintOptions;
  table.Color                := Color;
  table.BorderWidth          := BorderWidth;
  table.BorderColor          := BorderColor;
  table.BorderLightColor     := BorderLightColor;
  table.BorderStyle          := BorderStyle;
  table.BorderVSpacing       := BorderVSpacing;
  table.BorderHSpacing       := BorderHSpacing;
  table.CellBorderWidth      := CellBorderWidth;
  table.CellBorderColor      := CellBorderColor;
  table.CellBorderLightColor := CellBorderLightColor;
  table.CellPadding          := CellPadding;
  table.CellBorderStyle      := CellBorderStyle;
  table.VRuleWidth           := VRuleWidth;
  table.VRuleColor           := VRuleColor;
  table.HRuleWidth           := HRuleWidth;
  table.HRuleColor           := HRuleColor;
  table.CellVSpacing         := CellVSpacing;
  table.CellHSpacing         := CellHSpacing;
  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;
    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).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.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: Integer);
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 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;

{ 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 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;

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, IndentStep);
        if frm2.ShowModal=mrOk then begin
          frm2.GetListStyle(ListStyle, ListNo, Level, StartFrom, UseStartFrom);
          Result := frm2;
          end
        else
          frm2.Free;
      end;
    else
      begin
        frm := TfrmRVListGallery.Create(Application);
        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
    FActionParaBullets.ListLevels := RVStyle.ListStyles[ListNo].Levels;
  if FUpdateAllActionsOnForm then
    for i := 0 to Owner.ComponentCount - 1 do
      if (Owner.Components[i] is TrvActionParaBullets) and
         (Owner.Components[i]<>FActionParaBullets) then
        TrvActionParaBullets(Owner.Components[i]).ListLevels := RVStyle.ListStyles[ListNo].Levels;
end;

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

{ TrvActionCustomParaListSwitcher }

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

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

procedure TrvActionCustomParaListSwitcher.Reset;
begin
  ResetLevels(FListLevels);
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;

procedure TrvActionCustomParaListSwitcher.UpdateTarget(Target: TObject);
var StartNo, EndNo, a,b,i: Integer;
   Checked: Boolean;
   rve: TCustomRichViewEdit;
   CorrectListNo, ListNo, ListLevel, StartFrom: Integer;
   UseStartFrom: Boolean;
begin
  if not RVA_ActionsEnabled or Disabled then begin
    Enabled := False;
    exit;
  end;
  try
    inherited;
    rve := GetControl(Target).TopLevelEditor;
    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(ListLevels) 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;  
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;
begin
  rve := GetControl(Target);
  if not Checked then begin
    ListStyle := TRVListInfo.Create(nil);
    try
      ListStyle.Levels := ListLevels;
      Index := RVA_Events.DoStyleNeeded(Self, rve.Style, ListStyle);
    finally
      ListStyle.Free;
    end;
    if Index<0 then begin
      ListCount := rve.Style.ListStyles.Count;
      Index := rve.Style.ListStyles.FindStyleWithLevels(ListLevels, '2', True);
      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 := 24+i*48;
      MarkerIndent := i*48;
      Font.Size := 12;
      case i mod 3 of
        0:
          begin
            Font.Name := 'Symbol';
            Font.Charset := SYMBOL_CHARSET;
            FormatString := #183;
          end;
        1:
          begin
            Font.Name := 'Courier New';
            Font.Charset := ANSI_CHARSET;
            FormatString := 'o';
          end;
        2:
          begin
            Font.Name := 'Wingdings';
            Font.Charset := SYMBOL_CHARSET;
            FormatString := #167;
          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;
begin
  rve := GetControl(Target);
  if Checked then begin
    rve.RemoveLists(False);
    exit;
  end;
  rve := GetControl(Target).TopLevelEditor;
  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(ListLevels) then begin
        Index := ListNo;
        break;
      end;
  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(ListLevels) then begin
          Index := i;
          break;
        end;
    finally
      Data.Free;
    end;
    if Index<0 then begin
      ListStyle := TRVListInfo.Create(nil);
      try
        ListStyle.Levels := ListLevels;
        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 := ListLevels;
          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);
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 := 24+i*48;
      MarkerIndent := i*48;
      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;
    CodePage: TRVCodePage;
begin
  Result := RVA_Addict3<>nil;
  if not Result then
    exit;
  rve := rve.TopLevelEditor;
  ItemNo := rve.CurItemNo;
  WordEnd := rve.OffsetInCurItem;
  CodePage := rve.RVData.GetItemCodePage(ItemNo);
  if (rve.GetItemStyle(ItemNo)<0) or
    (rve.Style.TextStyles[rve.GetItemStyle(ItemNo)].Charset=SYMBOL_CHARSET) then
    exit;
  s := rve.GetItemTextA(ItemNo);
  WordStart := WordEnd;
  if WordStart<1 then
    exit;
  while (WordStart-1>0) and not rve.RVData.IsDelimiterA(s[WordStart-1], CodePage) 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}
  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;
  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.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 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}
  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}

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.GetFirstPageNumber: Integer;
begin
  Result := RVA_FirstPageNumber;
end;

procedure TRVAControlPanel.SetFirstPageNumber(Value: Integer);
begin
  RVA_FirstPageNumber := Value;
end;

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;

procedure TRVAControlPanel.SetOnMarginsChanged(const Value: TRVAEditEvent);
begin
  RVA_Events.FOnMarginsChanged := 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: TActionList;
begin
  Result := FPopupMenuHelper.FActionList;
end;

procedure TRVAPopupMenu.SetActionList(const Value: TActionList);
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: TActionList;
begin
  Result := FPopupMenuHelper.FActionList;
end;

procedure TRVATBPopupMenu.SetActionList(const Value: TActionList);
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: TActionList;
begin
  Result := FPopupMenuHelper.FActionList;
end;

procedure TRVATBXPopupMenu.SetActionList(const Value: TActionList);
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: TActionList;
begin
  Result := FPopupMenuHelper.FActionList;
end;

procedure TRVASpTBXPopupMenu.SetActionList(const Value: TActionList);
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
      TRVAction(Form.Components[i]).Localize;
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;

{$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 USEINDY}
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 USEINDY}
    Stream : TMemoryStream;
    FileStream : TFileStream;
    TempFileName: String;
    Graphic2: TGraphic;
    {$ENDIF}
begin
  {$IFDEF USEINDY}
  try
    if (RVA_IdHttp<>nil) and (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
          RVA_IdHttp.Get(Location, Stream);
        finally
          DoOnDownload(FSender, '');
        end;
        TempFileName := Location;
        for i := 1 to Length(TempFileName) do
          if TempFileName[i] in ['<','>','"','|','?','*'] 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 USEINDY}
  FDownloadedPictures := TStringList.Create;
  FDownloadedPictures.Sorted := True;
  FDownloadedPictures.Duplicates := dupIgnore;
  //FDownloadedPictures.CaseSensitive := False;
  FSender := Sender;
  {$ENDIF}
end;

procedure TRVAEvents.DoneImportPictures;
{$IFDEF USEINDY}
var i: Integer;
{$ENDIF}
begin
  {$IFDEF USEINDY}
  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:
      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:
      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;

initialization
  Randomize;
  RVA_DialogFontName := 'MS Sans Serif';
  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}
  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;
  FHHCtrlHandle := 0;
  AssignFunctions;
finalization
  RVA_HeaderInfo_.Free;
  RVA_FooterInfo_.Free;
  RVA_Events.Free;
  RVA_HeaderInfo_     := nil;
  RVA_FooterInfo_     := nil;
  RVA_Events          := nil;
  FinalizeChm;

end.