RxRichEd.pas
上传用户:hylc_2004
上传日期:2014-01-23
资源大小:46800k
文件大小:155k
源码类别:

Delphi控件源码

开发平台:

Delphi

  1. {*******************************************************}
  2. {                                                       }
  3. {         Delphi VCL Extensions (RX)                    }
  4. {                                                       }
  5. {         Copyright (c) 1998 Master-Bank                }
  6. {                                                       }
  7. {*******************************************************}
  8. unit RxRichEd;
  9. {$I RX.INC}
  10. {.$DEFINE RICHEDIT_VER_10}
  11. {$R-}
  12. interface
  13. uses Windows, {$IFDEF RX_D3} ActiveX, ComObj {$ELSE} Ole2, OleAuto {$ENDIF},
  14.   CommCtrl, Messages, SysUtils, Classes, Controls, Forms, Graphics, StdCtrls,
  15.   Dialogs, RichEdit, Menus, ComCtrls;
  16. type
  17.   TRichEditVersion = 1..3;
  18. {$IFNDEF RX_D3}
  19.   TCharFormat2A = record
  20.     cbSize: UINT;
  21.     dwMask: DWORD;
  22.     dwEffects: DWORD;
  23.     yHeight: Longint;
  24.     yOffset: Longint;
  25.     crTextColor: TColorRef;
  26.     bCharSet: Byte;
  27.     bPitchAndFamily: Byte;
  28.     szFaceName: array[0..LF_FACESIZE - 1] of AnsiChar;
  29.     { new fields in version 2.0 }
  30.     wWeight: Word;                   { Font weight (LOGFONT value)             }
  31.     sSpacing: Smallint;              { Amount to space between letters         }
  32.     crBackColor: TColorRef;          { Background color                        }
  33.     lid: LCID;                       { Locale ID                               }
  34.     dwReserved: DWORD;               { Reserved. Must be 0                     }
  35.     sStyle: Smallint;                { Style handle                            }
  36.     wKerning: Word;                  { Twip size above which to kern char pair }
  37.     bUnderlineType: Byte;            { Underline type                          }
  38.     bAnimation: Byte;                { Animated text like marching ants        }
  39.     bRevAuthor: Byte;                { Revision author index                   }
  40.     bReserved1: Byte;
  41.   end;
  42.   TCharFormat2 = TCharFormat2A;
  43.   TParaFormat2 = record
  44.     cbSize: UINT;
  45.     dwMask: DWORD;
  46.     wNumbering: Word;
  47.     wReserved: Word;
  48.     dxStartIndent: Longint;
  49.     dxRightIndent: Longint;
  50.     dxOffset: Longint;
  51.     wAlignment: Word;
  52.     cTabCount: Smallint;
  53.     rgxTabs: array [0..MAX_TAB_STOPS - 1] of Longint;
  54.     { new fields in version 2.0 }
  55.     dySpaceBefore: Longint;     { Vertical spacing before paragraph      }
  56.     dySpaceAfter: Longint;      { Vertical spacing after paragraph       }
  57.     dyLineSpacing: Longint;     { Line spacing depending on Rule         }
  58.     sStyle: Smallint;           { Style handle                           }
  59.     bLineSpacingRule: Byte;     { Rule for line spacing (see tom.doc)    }
  60.     bCRC: Byte;                 { Reserved for CRC for rapid searching   }
  61.     wShadingWeight: Word;       { Shading in hundredths of a per cent    }
  62.     wShadingStyle: Word;        { Nibble 0: style, 1: cfpat, 2: cbpat    }
  63.     wNumberingStart: Word;      { Starting value for numbering           }
  64.     wNumberingStyle: Word;      { Alignment, roman/arabic, (), ), ., etc.}
  65.     wNumberingTab: Word;        { Space bet 1st indent and 1st-line text }
  66.     wBorderSpace: Word;         { Space between border and text (twips)  }
  67.     wBorderWidth: Word;         { Border pen width (twips)               }
  68.     wBorders: Word;             { Byte 0: bits specify which borders     }
  69.                                 { Nibble 2: border style, 3: color index }
  70.   end;
  71. {$ENDIF RX_D3}
  72. {$IFDEF RX_D5}
  73.   TCharFormat2 = TCharFormat2A;
  74. {$ENDIF}
  75. type
  76.   TRxCustomRichEdit = class;
  77. { TRxTextAttributes }
  78.   TRxAttributeType = (atDefaultText, atSelected, atWord);
  79.   TRxConsistentAttribute = (caBold, caColor, caFace, caItalic, caSize,
  80.     caStrikeOut, caUnderline, caProtected, caOffset, caHidden, caLink,
  81.     caBackColor, caDisabled, caWeight, caSubscript, caRevAuthor);
  82.   TRxConsistentAttributes = set of TRxConsistentAttribute;
  83.   TSubscriptStyle = (ssNone, ssSubscript, ssSuperscript);
  84.   TUnderlineType = (utNone, utSolid, utWord, utDouble, utDotted, utWave);
  85.   TRxTextAttributes = class(TPersistent)
  86.   private
  87.     RichEdit: TRxCustomRichEdit;
  88.     FType: TRxAttributeType;
  89.     procedure AssignFont(Font: TFont);
  90.     procedure GetAttributes(var Format: TCharFormat2);
  91. {$IFNDEF VER90}
  92.     function GetCharset: TFontCharset;
  93.     procedure SetCharset(Value: TFontCharset);
  94. {$ENDIF}
  95.     function GetSubscriptStyle: TSubscriptStyle;
  96.     procedure SetSubscriptStyle(Value: TSubscriptStyle);
  97.     function GetBackColor: TColor;
  98.     function GetColor: TColor;
  99.     function GetConsistentAttributes: TRxConsistentAttributes;
  100.     function GetHeight: Integer;
  101.     function GetHidden: Boolean;
  102.     function GetDisabled: Boolean;
  103.     function GetLink: Boolean;
  104.     function GetName: TFontName;
  105.     function GetOffset: Integer;
  106.     function GetPitch: TFontPitch;
  107.     function GetProtected: Boolean;
  108.     function GetRevAuthorIndex: Byte;
  109.     function GetSize: Integer;
  110.     function GetStyle: TFontStyles;
  111.     function GetUnderlineType: TUnderlineType;
  112.     procedure SetAttributes(var Format: TCharFormat2);
  113.     procedure SetBackColor(Value: TColor);
  114.     procedure SetColor(Value: TColor);
  115.     procedure SetDisabled(Value: Boolean);
  116.     procedure SetHeight(Value: Integer);
  117.     procedure SetHidden(Value: Boolean);
  118.     procedure SetLink(Value: Boolean);
  119.     procedure SetName(Value: TFontName);
  120.     procedure SetOffset(Value: Integer);
  121.     procedure SetPitch(Value: TFontPitch);
  122.     procedure SetProtected(Value: Boolean);
  123.     procedure SetRevAuthorIndex(Value: Byte);
  124.     procedure SetSize(Value: Integer);
  125.     procedure SetStyle(Value: TFontStyles);
  126.     procedure SetUnderlineType(Value: TUnderlineType);
  127.   protected
  128.     procedure InitFormat(var Format: TCharFormat2);
  129.     procedure AssignTo(Dest: TPersistent); override;
  130.   public
  131.     constructor Create(AOwner: TRxCustomRichEdit; AttributeType: TRxAttributeType);
  132.     procedure Assign(Source: TPersistent); override;
  133. {$IFNDEF VER90}
  134.     property Charset: TFontCharset read GetCharset write SetCharset;
  135. {$ENDIF}
  136.     property BackColor: TColor read GetBackColor write SetBackColor;
  137.     property Color: TColor read GetColor write SetColor;
  138.     property ConsistentAttributes: TRxConsistentAttributes read GetConsistentAttributes;
  139.     property Disabled: Boolean read GetDisabled write SetDisabled;
  140.     property Hidden: Boolean read GetHidden write SetHidden;
  141.     property Link: Boolean read GetLink write SetLink;
  142.     property Name: TFontName read GetName write SetName;
  143.     property Offset: Integer read GetOffset write SetOffset;
  144.     property Pitch: TFontPitch read GetPitch write SetPitch;
  145.     property Protected: Boolean read GetProtected write SetProtected;
  146.     property RevAuthorIndex: Byte read GetRevAuthorIndex write SetRevAuthorIndex;
  147.     property SubscriptStyle: TSubscriptStyle read GetSubscriptStyle write SetSubscriptStyle;
  148.     property Size: Integer read GetSize write SetSize;
  149.     property Style: TFontStyles read GetStyle write SetStyle;
  150.     property Height: Integer read GetHeight write SetHeight;
  151.     property UnderlineType: TUnderlineType read GetUnderlineType write SetUnderlineType;
  152.   end;
  153. { TRxParaAttributes }
  154.   TRxNumbering = (nsNone, nsBullet, nsArabicNumbers, nsLoCaseLetter,
  155.     nsUpCaseLetter, nsLoCaseRoman, nsUpCaseRoman);
  156.   TRxNumberingStyle = (nsParenthesis, nsPeriod, nsEnclosed, nsSimple);
  157.   TParaAlignment = (paLeftJustify, paRightJustify, paCenter, paJustify);
  158.   TLineSpacingRule = (lsSingle, lsOneAndHalf, lsDouble, lsSpecifiedOrMore,
  159.     lsSpecified, lsMultiple);
  160.   THeadingStyle = 0..9;
  161.   TParaTableStyle = (tsNone, tsTableRow, tsTableCellEnd, tsTableCell);
  162.   TRxParaAttributes = class(TPersistent)
  163.   private
  164.     RichEdit: TRxCustomRichEdit;
  165.     procedure GetAttributes(var Paragraph: TParaFormat2);
  166.     function GetAlignment: TParaAlignment;
  167.     function GetFirstIndent: Longint;
  168.     function GetHeadingStyle: THeadingStyle;
  169.     function GetLeftIndent: Longint;
  170.     function GetRightIndent: Longint;
  171.     function GetSpaceAfter: Longint;
  172.     function GetSpaceBefore: Longint;
  173.     function GetLineSpacing: Longint;
  174.     function GetLineSpacingRule: TLineSpacingRule;
  175.     function GetNumbering: TRxNumbering;
  176.     function GetNumberingStyle: TRxNumberingStyle;
  177.     function GetNumberingTab: Word;
  178.     function GetTab(Index: Byte): Longint;
  179.     function GetTabCount: Integer;
  180.     function GetTableStyle: TParaTableStyle;
  181.     procedure SetAlignment(Value: TParaAlignment);
  182.     procedure SetAttributes(var Paragraph: TParaFormat2);
  183.     procedure SetFirstIndent(Value: Longint);
  184.     procedure SetHeadingStyle(Value: THeadingStyle);
  185.     procedure SetLeftIndent(Value: Longint);
  186.     procedure SetRightIndent(Value: Longint);
  187.     procedure SetSpaceAfter(Value: Longint);
  188.     procedure SetSpaceBefore(Value: Longint);
  189.     procedure SetLineSpacing(Value: Longint);
  190.     procedure SetLineSpacingRule(Value: TLineSpacingRule);
  191.     procedure SetNumbering(Value: TRxNumbering);
  192.     procedure SetNumberingStyle(Value: TRxNumberingStyle);
  193.     procedure SetNumberingTab(Value: Word);
  194.     procedure SetTab(Index: Byte; Value: Longint);
  195.     procedure SetTabCount(Value: Integer);
  196.     procedure SetTableStyle(Value: TParaTableStyle);
  197.   protected
  198.     procedure InitPara(var Paragraph: TParaFormat2);
  199.     procedure AssignTo(Dest: TPersistent); override;
  200.   public
  201.     constructor Create(AOwner: TRxCustomRichEdit);
  202.     procedure Assign(Source: TPersistent); override;
  203.     property Alignment: TParaAlignment read GetAlignment write SetAlignment;
  204.     property FirstIndent: Longint read GetFirstIndent write SetFirstIndent;
  205.     property HeadingStyle: THeadingStyle read GetHeadingStyle write SetHeadingStyle;
  206.     property LeftIndent: Longint read GetLeftIndent write SetLeftIndent;
  207.     property LineSpacing: Longint read GetLineSpacing write SetLineSpacing;
  208.     property LineSpacingRule: TLineSpacingRule read GetLineSpacingRule write SetLineSpacingRule;
  209.     property Numbering: TRxNumbering read GetNumbering write SetNumbering;
  210.     property NumberingStyle: TRxNumberingStyle read GetNumberingStyle write SetNumberingStyle;
  211.     property NumberingTab: Word read GetNumberingTab write SetNumberingTab;
  212.     property RightIndent: Longint read GetRightIndent write SetRightIndent;
  213.     property SpaceAfter: Longint read GetSpaceAfter write SetSpaceAfter;
  214.     property SpaceBefore: Longint read GetSpaceBefore write SetSpaceBefore;
  215.     property Tab[Index: Byte]: Longint read GetTab write SetTab;
  216.     property TabCount: Integer read GetTabCount write SetTabCount;
  217.     property TableStyle: TParaTableStyle read GetTableStyle write SetTableStyle;
  218.   end;
  219. { TOEMConversion }
  220.   TOEMConversion = class(TConversion)
  221.   public
  222.     function ConvertReadStream(Stream: TStream; Buffer: PChar; BufSize: Integer): Integer; override;
  223.     function ConvertWriteStream(Stream: TStream; Buffer: PChar; BufSize: Integer): Integer; override;
  224.   end;
  225. { TRxCustomRichEdit }
  226.   TUndoName = (unUnknown, unTyping, unDelete, unDragDrop, unCut, unPaste);
  227.   TRichSearchType = (stWholeWord, stMatchCase, stBackward, stSetSelection);
  228.   TRichSearchTypes = set of TRichSearchType;
  229.   TRichSelection = (stText, stObject, stMultiChar, stMultiObject);
  230.   TRichSelectionType = set of TRichSelection;
  231.   TRichLangOption = (rlAutoKeyboard, rlAutoFont, rlImeCancelComplete,
  232.     rlImeAlwaysSendNotify);
  233.   TRichLangOptions = set of TRichLangOption;
  234.   TRichStreamFormat = (sfDefault, sfRichText, sfPlainText);
  235.   TRichStreamMode = (smSelection, smPlainRtf, smNoObjects, smUnicode);
  236.   TRichStreamModes = set of TRichStreamMode;
  237.   TRichEditURLClickEvent = procedure(Sender: TObject; const URLText: string;
  238.     Button: TMouseButton) of object;
  239.   TRichEditProtectChangeEx = procedure(Sender: TObject; const Message: TMessage;
  240.     StartPos, EndPos: Integer; var AllowChange: Boolean) of object;
  241.   TRichEditFindErrorEvent = procedure(Sender: TObject; const FindText: string) of object;
  242. {$IFDEF RX_D3}
  243.   TRichEditFindCloseEvent = procedure(Sender: TObject; Dialog: TFindDialog) of object;
  244. {$ENDIF}
  245.   PRichConversionFormat = ^TRichConversionFormat;
  246.   TRichConversionFormat = record
  247.     ConversionClass: TConversionClass;
  248.     Extension: string;
  249.     PlainText: Boolean;
  250.     Next: PRichConversionFormat;
  251.   end;
  252.   TRxCustomRichEdit = class(TCustomMemo)
  253.   private
  254.     FHideScrollBars: Boolean;
  255.     FSelectionBar: Boolean;
  256.     FAutoURLDetect: Boolean;
  257.     FWordSelection: Boolean;
  258.     FPlainText: Boolean;
  259.     FSelAttributes: TRxTextAttributes;
  260.     FDefAttributes: TRxTextAttributes;
  261.     FWordAttributes: TRxTextAttributes;
  262.     FParagraph: TRxParaAttributes;
  263.     FOldParaAlignment: TParaAlignment;
  264.     FScreenLogPixels: Integer;
  265.     FUndoLimit: Integer;
  266.     FRichEditStrings: TStrings;
  267.     FMemStream: TMemoryStream;
  268.     FHideSelection: Boolean;
  269.     FLangOptions: TRichLangOptions;
  270.     FModified: Boolean;
  271.     FLinesUpdating: Boolean;
  272.     FPageRect: TRect;
  273.     FClickRange: TCharRange;
  274.     FClickBtn: TMouseButton;
  275.     FFindDialog: TFindDialog;
  276.     FReplaceDialog: TReplaceDialog;
  277.     FLastFind: TFindDialog;
  278.     FAllowObjects: Boolean;
  279.     FCallback: TObject;
  280.     FRichEditOle: IUnknown;
  281.     FPopupVerbMenu: TPopupMenu;
  282.     FTitle: string;
  283.     FAutoVerbMenu: Boolean;
  284. {$IFDEF RX_D3}
  285.     FAllowInPlace: Boolean;
  286. {$ENDIF}
  287.     FDefaultConverter: TConversionClass;
  288.     FOnSelChange: TNotifyEvent;
  289.     FOnResizeRequest: TRichEditResizeEvent;
  290.     FOnProtectChange: TRichEditProtectChange;
  291.     FOnProtectChangeEx: TRichEditProtectChangeEx;
  292.     FOnSaveClipboard: TRichEditSaveClipboard;
  293.     FOnURLClick: TRichEditURLClickEvent;
  294.     FOnTextNotFound: TRichEditFindErrorEvent;
  295. {$IFDEF RX_D3}
  296.     FOnCloseFindDialog: TRichEditFindCloseEvent;
  297. {$ENDIF}
  298.     function GetAutoURLDetect: Boolean;
  299.     function GetWordSelection: Boolean;
  300.     function GetLangOptions: TRichLangOptions;
  301.     function GetCanRedo: Boolean;
  302.     function GetCanPaste: Boolean;
  303. {$IFNDEF RX_V110}
  304.     function GetCanUndo: Boolean;
  305. {$ENDIF}
  306.     function GetRedoName: TUndoName;
  307.     function GetUndoName: TUndoName;
  308.     function GetStreamFormat: TRichStreamFormat;
  309.     function GetStreamMode: TRichStreamModes;
  310.     function GetSelectionType: TRichSelectionType;
  311.     procedure PopupVerbClick(Sender: TObject);
  312.     procedure ObjectPropsClick(Sender: TObject);
  313.     procedure CloseObjects;
  314.     procedure UpdateHostNames;
  315.     procedure SetAllowObjects(Value: Boolean);
  316.     procedure SetStreamFormat(Value: TRichStreamFormat);
  317.     procedure SetStreamMode(Value: TRichStreamModes);
  318.     procedure SetAutoURLDetect(Value: Boolean);
  319.     procedure SetWordSelection(Value: Boolean);
  320.     procedure SetHideScrollBars(Value: Boolean);
  321.     procedure SetHideSelection(Value: Boolean);
  322.     procedure SetTitle(const Value: string);
  323.     procedure SetLangOptions(Value: TRichLangOptions);
  324.     procedure SetRichEditStrings(Value: TStrings);
  325.     procedure SetDefAttributes(Value: TRxTextAttributes);
  326.     procedure SetSelAttributes(Value: TRxTextAttributes);
  327.     procedure SetWordAttributes(Value: TRxTextAttributes);
  328.     procedure SetSelectionBar(Value: Boolean);
  329.     procedure SetUndoLimit(Value: Integer);
  330.     procedure UpdateTextModes(Plain: Boolean);
  331.     procedure AdjustFindDialogPosition(Dialog: TFindDialog);
  332.     procedure SetupFindDialog(Dialog: TFindDialog; const SearchStr,
  333.       ReplaceStr: string);
  334.     function FindEditText(Dialog: TFindDialog; AdjustPos, Events: Boolean): Boolean;
  335.     function GetCanFindNext: Boolean;
  336.     procedure FindDialogFind(Sender: TObject);
  337.     procedure ReplaceDialogReplace(Sender: TObject);
  338. {$IFDEF RX_D3}
  339.     procedure FindDialogClose(Sender: TObject);
  340.     procedure SetUIActive(Active: Boolean);
  341.     procedure CMDocWindowActivate(var Message: TMessage); message CM_DOCWINDOWACTIVATE;
  342.     procedure CMUIDeactivate(var Message: TMessage); message CM_UIDEACTIVATE;
  343. {$ENDIF}
  344. {$IFDEF RX_D4}
  345.     procedure CMBiDiModeChanged(var Message: TMessage); message CM_BIDIMODECHANGED;
  346. {$ENDIF}
  347.     procedure CMColorChanged(var Message: TMessage); message CM_COLORCHANGED;
  348.     procedure CMFontChanged(var Message: TMessage); message CM_FONTCHANGED;
  349.     procedure CNNotify(var Message: TWMNotify); message CN_NOTIFY;
  350.     procedure EMReplaceSel(var Message: TMessage); message EM_REPLACESEL;
  351.     procedure WMDestroy(var Msg: TWMDestroy); message WM_DESTROY;
  352.     procedure WMMouseMove(var Message: TMessage); message WM_MOUSEMOVE;
  353.     procedure WMPaint(var Message: TWMPaint); message WM_PAINT;
  354.     procedure WMSetCursor(var Message: TWMSetCursor); message WM_SETCURSOR;
  355.     procedure WMSetFont(var Message: TWMSetFont); message WM_SETFONT;
  356. {$IFDEF RX_D5}
  357.     procedure WMRButtonUp(var Message: TMessage); message WM_RBUTTONUP;
  358. {$ENDIF}
  359.   protected
  360.     procedure CreateParams(var Params: TCreateParams); override;
  361.     procedure CreateWindowHandle(const Params: TCreateParams); override;
  362.     procedure CreateWnd; override;
  363.     procedure DestroyWnd; override;
  364.     function GetPopupMenu: TPopupMenu; override;
  365.     procedure TextNotFound(Dialog: TFindDialog); virtual;
  366.     procedure RequestSize(const Rect: TRect); virtual;
  367.     procedure SelectionChange; dynamic;
  368.     function ProtectChange(const Message: TMessage; StartPos,
  369.       EndPos: Integer): Boolean; dynamic;
  370.     function SaveClipboard(NumObj, NumChars: Integer): Boolean; dynamic;
  371.     procedure URLClick(const URLText: string; Button: TMouseButton); dynamic;
  372.     procedure SetPlainText(Value: Boolean); virtual;
  373. {$IFDEF RX_D3}
  374.     procedure CloseFindDialog(Dialog: TFindDialog); virtual;
  375.     procedure DoSetMaxLength(Value: Integer); override;
  376.     function GetSelLength: Integer; override;
  377.     function GetSelStart: Integer; override;
  378.     function GetSelText: string; override;
  379.     procedure SetSelLength(Value: Integer); override;
  380.     procedure SetSelStart(Value: Integer); override;
  381.     property AllowInPlace: Boolean read FAllowInPlace write FAllowInPlace default True;
  382. {$ENDIF}
  383.     property AllowObjects: Boolean read FAllowObjects write SetAllowObjects default True;
  384.     property AutoURLDetect: Boolean read GetAutoURLDetect write SetAutoURLDetect default True;
  385.     property AutoVerbMenu: Boolean read FAutoVerbMenu write FAutoVerbMenu default True;
  386.     property HideSelection: Boolean read FHideSelection write SetHideSelection default True;
  387.     property HideScrollBars: Boolean read FHideScrollBars
  388.       write SetHideScrollBars default True;
  389.     property Title: string read FTitle write SetTitle;
  390.     property LangOptions: TRichLangOptions read GetLangOptions write SetLangOptions default [rlAutoFont];
  391.     property Lines: TStrings read FRichEditStrings write SetRichEditStrings;
  392.     property PlainText: Boolean read FPlainText write SetPlainText default False;
  393.     property SelectionBar: Boolean read FSelectionBar write SetSelectionBar default True;
  394.     property StreamFormat: TRichStreamFormat read GetStreamFormat write SetStreamFormat default sfDefault;
  395.     property StreamMode: TRichStreamModes read GetStreamMode write SetStreamMode default [];
  396.     property UndoLimit: Integer read FUndoLimit write SetUndoLimit default 100;
  397.     property WordSelection: Boolean read GetWordSelection write SetWordSelection default True;
  398.     property ScrollBars default ssBoth;
  399.     property TabStop default True;
  400.     property OnSaveClipboard: TRichEditSaveClipboard read FOnSaveClipboard
  401.       write FOnSaveClipboard;
  402.     property OnSelectionChange: TNotifyEvent read FOnSelChange write FOnSelChange;
  403.     property OnProtectChange: TRichEditProtectChange read FOnProtectChange
  404.       write FOnProtectChange; { obsolete }
  405.     property OnProtectChangeEx: TRichEditProtectChangeEx read FOnProtectChangeEx
  406.       write FOnProtectChangeEx;
  407.     property OnResizeRequest: TRichEditResizeEvent read FOnResizeRequest
  408.       write FOnResizeRequest;
  409.     property OnURLClick: TRichEditURLClickEvent read FOnURLClick write FOnURLClick;
  410.     property OnTextNotFound: TRichEditFindErrorEvent read FOnTextNotFound write FOnTextNotFound;
  411. {$IFDEF RX_D3}
  412.     property OnCloseFindDialog: TRichEditFindCloseEvent read FOnCloseFindDialog
  413.       write FOnCloseFindDialog;
  414. {$ENDIF}
  415.   public
  416.     constructor Create(AOwner: TComponent); override;
  417.     destructor Destroy; override;
  418.     procedure Clear; {$IFDEF RX_D3} override; {$ENDIF}
  419.     procedure SetSelection(StartPos, EndPos: Longint; ScrollCaret: Boolean);
  420.     function GetSelection: TCharRange;
  421.     function GetTextRange(StartPos, EndPos: Longint): string;
  422.     function LineFromChar(CharIndex: Integer): Integer;
  423.     function GetLineIndex(LineNo: Integer): Integer;
  424.     function GetLineLength(CharIndex: Integer): Integer;
  425.     function WordAtCursor: string;
  426.     function FindText(const SearchStr: string;
  427.       StartPos, Length: Integer; Options: TRichSearchTypes): Integer;
  428.     function GetSelTextBuf(Buffer: PChar; BufSize: Integer): Integer;
  429.       {$IFDEF RX_D3} override; {$ENDIF}
  430.     function GetCaretPos: TPoint; {$IFDEF RX_V110} override; {$ENDIF}
  431.     function GetCharPos(CharIndex: Integer): TPoint;
  432.     function InsertObjectDialog: Boolean;
  433.     function ObjectPropertiesDialog: Boolean;
  434.     function PasteSpecialDialog: Boolean;
  435.     function FindDialog(const SearchStr: string): TFindDialog;
  436.     function ReplaceDialog(const SearchStr, ReplaceStr: string): TReplaceDialog;
  437.     function FindNext: Boolean;
  438.     procedure Print(const Caption: string); virtual;
  439.     class procedure RegisterConversionFormat(const AExtension: string;
  440.       APlainText: Boolean; AConversionClass: TConversionClass);
  441.     procedure ClearUndo;
  442.     procedure Redo;
  443.     procedure StopGroupTyping;
  444.     property CanFindNext: Boolean read GetCanFindNext;
  445.     property CanRedo: Boolean read GetCanRedo;
  446.     property CanPaste: Boolean read GetCanPaste;
  447. {$IFNDEF RX_V110}
  448.     procedure Undo;
  449.     property CanUndo: Boolean read GetCanUndo;
  450.     property CaretPos: TPoint read GetCaretPos;
  451. {$ENDIF}
  452.     property RedoName: TUndoName read GetRedoName;
  453.     property UndoName: TUndoName read GetUndoName;
  454.     property DefaultConverter: TConversionClass read FDefaultConverter
  455.       write FDefaultConverter;
  456.     property DefAttributes: TRxTextAttributes read FDefAttributes write SetDefAttributes;
  457.     property SelAttributes: TRxTextAttributes read FSelAttributes write SetSelAttributes;
  458.     property WordAttributes: TRxTextAttributes read FWordAttributes write SetWordAttributes;
  459.     property PageRect: TRect read FPageRect write FPageRect;
  460.     property Paragraph: TRxParaAttributes read FParagraph;
  461.     property SelectionType: TRichSelectionType read GetSelectionType;
  462.   end;
  463.   TRxRichEdit = class(TRxCustomRichEdit)
  464.   published
  465.     property Align;
  466.     property Alignment;
  467.     property AutoURLDetect;
  468.     property AutoVerbMenu;
  469.     property AllowObjects;
  470. {$IFDEF RX_D3}
  471.     property AllowInPlace;
  472. {$ENDIF}
  473. {$IFDEF RX_D4}
  474.     property Anchors;
  475.     property BiDiMode;
  476.     property BorderWidth;
  477.     property DragKind;
  478. {$ENDIF}
  479.     property BorderStyle;
  480.     property Color;
  481.     property Ctl3D;
  482.     property DragCursor;
  483.     property DragMode;
  484.     property Enabled;
  485.     property Font;
  486.     property HideSelection;
  487.     property HideScrollBars;
  488.     property Title;
  489. {$IFNDEF VER90}
  490.     property ImeMode;
  491.     property ImeName;
  492. {$ENDIF}
  493. {$IFDEF RX_D4}
  494.     property Constraints;
  495.     property ParentBiDiMode;
  496. {$ENDIF}
  497.     property LangOptions;
  498.     property Lines;
  499.     property MaxLength;
  500.     property ParentColor;
  501.     property ParentCtl3D;
  502.     property ParentFont;
  503.     property ParentShowHint;
  504.     property PlainText;
  505.     property PopupMenu;
  506.     property ReadOnly;
  507.     property ScrollBars;
  508.     property SelectionBar;
  509.     property ShowHint;
  510.     property StreamFormat;
  511.     property StreamMode;
  512.     property TabOrder;
  513.     property TabStop;
  514.     property UndoLimit;
  515.     property Visible;
  516.     property WantTabs;
  517.     property WantReturns;
  518.     property WordSelection;
  519.     property WordWrap;
  520.     property OnChange;
  521.     property OnDblClick;
  522.     property OnDragDrop;
  523.     property OnDragOver;
  524. {$IFDEF RX_D5}
  525.     property OnContextPopup;
  526. {$ENDIF}
  527. {$IFDEF RX_D4}
  528.     property OnEndDock;
  529.     property OnStartDock;
  530. {$ENDIF}
  531.     property OnEndDrag;
  532.     property OnEnter;
  533.     property OnExit;
  534.     property OnKeyDown;
  535.     property OnKeyPress;
  536.     property OnKeyUp;
  537.     property OnMouseDown;
  538.     property OnMouseMove;
  539.     property OnMouseUp;
  540. {$IFDEF RX_D4}
  541.     property OnMouseWheel;
  542.     property OnMouseWheelDown;
  543.     property OnMouseWheelUp;
  544. {$ENDIF}
  545.     property OnProtectChange; { obsolete }
  546.     property OnProtectChangeEx;
  547.     property OnResizeRequest;
  548.     property OnSaveClipboard;
  549.     property OnSelectionChange;
  550.     property OnStartDrag;
  551.     property OnTextNotFound;
  552. {$IFDEF RX_D3}
  553.     property OnCloseFindDialog;
  554. {$ENDIF}
  555.     property OnURLClick;
  556.   end;
  557. var
  558.   RichEditVersion: TRichEditVersion;
  559. implementation
  560. uses Printers, ComStrs, OleConst, OleDlg {$IFDEF RX_D3}, OleCtnrs {$ENDIF},
  561.   MaxMin;
  562. const
  563.   RTFConversionFormat: TRichConversionFormat = (
  564.     ConversionClass: TConversion;
  565.     Extension: 'rtf';
  566.     PlainText: False;
  567.     Next: nil);
  568.   TextConversionFormat: TRichConversionFormat = (
  569.     ConversionClass: TConversion;
  570.     Extension: 'txt';
  571.     PlainText: True;
  572.     Next: @RTFConversionFormat);
  573. var
  574.   ConversionFormatList: PRichConversionFormat = @TextConversionFormat;
  575. const
  576.   RichEdit10ModuleName = 'RICHED32.DLL';
  577.   RichEdit20ModuleName = 'RICHED20.DLL';
  578. {$IFNDEF RX_D3}
  579.   RICHEDIT_CLASSA      = 'RichEdit20A';     { Richedit 2.0 Window Class }
  580.   RICHEDIT_CLASSW      = 'RichEdit20W';     { Richedit 2.0 Unicode }
  581.   RICHEDIT_CLASS10A    = 'RICHEDIT';        { Richedit 1.0 }
  582.   RICHEDIT_CLASS       = RICHEDIT_CLASSA;
  583. {$ENDIF}
  584. {$IFNDEF RX_D3}
  585. const
  586.   EM_SETUNDOLIMIT                     = WM_USER + 82; 
  587.   EM_REDO                             = WM_USER + 84; 
  588.   EM_CANREDO                          = WM_USER + 85;
  589.   EM_GETUNDONAME                      = WM_USER + 86; 
  590.   EM_GETREDONAME                      = WM_USER + 87; 
  591.   EM_STOPGROUPTYPING                  = WM_USER + 88; 
  592.   EM_SETTEXTMODE                      = WM_USER + 89; 
  593.   EM_GETTEXTMODE                      = WM_USER + 90; 
  594. { for use with EM_GET/SETTEXTMODE }
  595.   TM_PLAINTEXT                       = 1; 
  596.   TM_RICHTEXT                        = 2;     { default behavior }
  597.   TM_SINGLELEVELUNDO                 = 4;
  598.   TM_MULTILEVELUNDO                  = 8;     { default behavior }
  599.   TM_SINGLECODEPAGE                  = 16; 
  600.   TM_MULTICODEPAGE                   = 32;    { default behavior }
  601.   EM_AUTOURLDETECT                    = WM_USER + 91; 
  602.   EM_GETAUTOURLDETECT                 = WM_USER + 92;
  603.   EM_SETPALETTE                       = WM_USER + 93;
  604.   EM_GETTEXTEX                        = WM_USER + 94; 
  605.   EM_GETTEXTLENGTHEX                  = WM_USER + 95; 
  606.   EM_SETLANGOPTIONS                   = WM_USER + 120;
  607.   EM_GETLANGOPTIONS                   = WM_USER + 121;
  608.   EM_GETIMECOMPMODE                   = WM_USER + 122;
  609. { Options for EM_SETLANGOPTIONS and EM_GETLANGOPTIONS }
  610.   IMF_AUTOKEYBOARD            = $0001;
  611.   IMF_AUTOFONT                = $0002;
  612.   IMF_IMECANCELCOMPLETE       = $0004;  { high completes the comp string when aborting, low cancels. }
  613.   IMF_IMEALWAYSSENDNOTIFY     = $0008;
  614. { New notifications }
  615.   EN_OLEOPFAILED                      = $0709;
  616.   EN_OBJECTPOSITIONS                  = $070A;
  617.   EN_LINK                             = $070B;
  618.   EN_DRAGDROPDONE                     = $070C;
  619. { Event notification masks }
  620.   ENM_SCROLLEVENTS                    = $00000008;
  621.   ENM_DRAGDROPDONE                    = $00000010;
  622.   ENM_LANGCHANGE                      = $01000000; 
  623.   ENM_OBJECTPOSITIONS                 = $02000000; 
  624.   ENM_LINK                            = $04000000;
  625. { New edit control styles }
  626.   ES_NOOLEDRAGDROP                    = $00000008; 
  627. const
  628.   CFM_LINK = $00000020;  { Exchange hyperlink extension }
  629.   CFM_EFFECTS = CFM_BOLD or CFM_ITALIC or CFM_UNDERLINE or CFM_COLOR or
  630.     CFM_STRIKEOUT or CFE_PROTECTED or CFM_LINK;
  631.   CFM_ALL = CFM_EFFECTS or CFM_SIZE or CFM_FACE or CFM_OFFSET or CFM_CHARSET;
  632.   PFM_ALL = PFM_STARTINDENT or PFM_RIGHTINDENT or PFM_OFFSET or
  633.     PFM_ALIGNMENT or PFM_TABSTOPS or PFM_NUMBERING or PFM_OFFSETINDENT;
  634. { New masks and effects -- a parenthesized asterisk indicates that
  635.    the data is stored by RichEdit2.0, but not displayed }
  636.   CFM_SMALLCAPS               = $0040;                  { (*)    }
  637.   CFM_ALLCAPS                 = $0080;                  { (*)    }
  638.   CFM_HIDDEN                  = $0100;                  { (*)    }
  639.   CFM_OUTLINE                 = $0200;                  { (*)    }
  640.   CFM_SHADOW                  = $0400;                  { (*)    }
  641.   CFM_EMBOSS                  = $0800;                  { (*)    }
  642.   CFM_IMPRINT                 = $1000;                  { (*)    }
  643.   CFM_DISABLED                = $2000;
  644.   CFM_REVISED                 = $4000;
  645.   CFM_BACKCOLOR               = $04000000; 
  646.   CFM_LCID                    = $02000000; 
  647.   CFM_UNDERLINETYPE           = $00800000;              { (*)    }
  648.   CFM_WEIGHT                  = $00400000;
  649.   CFM_SPACING                 = $00200000;              { (*)    }
  650.   CFM_KERNING                 = $00100000;              { (*)    }
  651.   CFM_STYLE                   = $00080000;              { (*)    }
  652.   CFM_ANIMATION               = $00040000;              { (*)    }
  653.   CFM_REVAUTHOR               = $00008000; 
  654.   CFE_LINK                    = $00000020;
  655.   CFE_AUTOCOLOR               = $40000000;   { NOTE: this corresponds to CFM_COLOR, }
  656.                                              { which controls it }
  657.   CFE_SUBSCRIPT               = $00010000;   { Superscript and subscript are }
  658.   CFE_SUPERSCRIPT             = $00020000;   { mutually exclusive            }
  659.   CFM_SUBSCRIPT               = CFE_SUBSCRIPT or CFE_SUPERSCRIPT;
  660.   CFM_SUPERSCRIPT             = CFM_SUBSCRIPT;
  661.   CFM_EFFECTS2 = CFM_EFFECTS or CFM_DISABLED or CFM_SMALLCAPS or CFM_ALLCAPS or 
  662.     CFM_HIDDEN  or CFM_OUTLINE or CFM_SHADOW or CFM_EMBOSS or 
  663.     CFM_IMPRINT or CFM_DISABLED or CFM_REVISED or 
  664.     CFM_SUBSCRIPT or CFM_SUPERSCRIPT or CFM_BACKCOLOR;
  665.   CFM_ALL2 = CFM_ALL or CFM_EFFECTS2 or CFM_BACKCOLOR or CFM_LCID or 
  666.     CFM_UNDERLINETYPE or CFM_WEIGHT or CFM_REVAUTHOR or 
  667.     CFM_SPACING or CFM_KERNING or CFM_STYLE or CFM_ANIMATION;
  668.   CFE_SMALLCAPS               = CFM_SMALLCAPS; 
  669.   CFE_ALLCAPS                 = CFM_ALLCAPS; 
  670.   CFE_HIDDEN                  = CFM_HIDDEN; 
  671.   CFE_OUTLINE                 = CFM_OUTLINE;
  672.   CFE_SHADOW                  = CFM_SHADOW; 
  673.   CFE_EMBOSS                  = CFM_EMBOSS;
  674.   CFE_IMPRINT                 = CFM_IMPRINT;
  675.   CFE_DISABLED                = CFM_DISABLED;
  676.   CFE_REVISED                 = CFM_REVISED;
  677.   CFE_AUTOBACKCOLOR           = CFM_BACKCOLOR; 
  678. { Underline types }
  679.   CFU_CF1UNDERLINE            = $FF;    { map charformat's bit underline to CF2. }
  680.   CFU_INVERT                  = $FE;    { For IME composition fake a selection.  }
  681.   CFU_UNDERLINEDOTTED         = $4;     { (*) displayed as ordinary underline    }
  682.   CFU_UNDERLINEDOUBLE         = $3;     { (*) displayed as ordinary underline    }
  683.   CFU_UNDERLINEWORD           = $2;     { (*) displayed as ordinary underline    }
  684.   CFU_UNDERLINE               = $1; 
  685.   CFU_UNDERLINENONE           = 0; 
  686. { PARAFORMAT 2.0 masks and effects }
  687. const
  688.   PFM_SPACEBEFORE                     = $00000040;
  689.   PFM_SPACEAFTER                      = $00000080;
  690.   PFM_LINESPACING                     = $00000100; 
  691.   PFM_STYLE                           = $00000400;
  692.   PFM_BORDER                          = $00000800;      { (*)    }
  693.   PFM_SHADING                         = $00001000;      { (*)    }
  694.   PFM_NUMBERINGSTYLE                  = $00002000;      { (*)    }
  695.   PFM_NUMBERINGTAB                    = $00004000;      { (*)    }
  696.   PFM_NUMBERINGSTART                  = $00008000;      { (*)    }
  697.   PFM_RTLPARA                         = $00010000; 
  698.   PFM_KEEP                            = $00020000;      { (*)    }
  699.   PFM_KEEPNEXT                        = $00040000;      { (*)    }
  700.   PFM_PAGEBREAKBEFORE                 = $00080000;      { (*)    }
  701.   PFM_NOLINENUMBER                    = $00100000;      { (*)    }
  702.   PFM_NOWIDOWCONTROL                  = $00200000;      { (*)    }
  703.   PFM_DONOTHYPHEN                     = $00400000;      { (*)    }
  704.   PFM_SIDEBYSIDE                      = $00800000;      { (*)    }
  705.   PFM_TABLE                           = $C0000000;      { (*)    }
  706. { Note: PARAFORMAT has no effects }
  707.   PFM_EFFECTS = PFM_RTLPARA or PFM_KEEP or PFM_KEEPNEXT or PFM_TABLE or
  708.     PFM_PAGEBREAKBEFORE or PFM_NOLINENUMBER or 
  709.     PFM_NOWIDOWCONTROL or PFM_DONOTHYPHEN or PFM_SIDEBYSIDE or PFM_TABLE; 
  710.   PFM_ALL2 = PFM_ALL or PFM_EFFECTS or PFM_SPACEBEFORE or PFM_SPACEAFTER or 
  711.     PFM_LINESPACING or PFM_STYLE or PFM_SHADING or PFM_BORDER or 
  712.     PFM_NUMBERINGTAB or PFM_NUMBERINGSTART or PFM_NUMBERINGSTYLE;
  713.   PFE_RTLPARA                         = PFM_RTLPARA              shr 16; 
  714.   PFE_KEEP                            = PFM_KEEP                 shr 16;    { (*)    }
  715.   PFE_KEEPNEXT                        = PFM_KEEPNEXT             shr 16;    { (*)    }
  716.   PFE_PAGEBREAKBEFORE                 = PFM_PAGEBREAKBEFORE      shr 16;    { (*)    }
  717.   PFE_NOLINENUMBER                    = PFM_NOLINENUMBER         shr 16;    { (*)    }
  718.   PFE_NOWIDOWCONTROL                  = PFM_NOWIDOWCONTROL       shr 16;    { (*)    }
  719.   PFE_DONOTHYPHEN                     = PFM_DONOTHYPHEN          shr 16;    { (*)    }
  720.   PFE_SIDEBYSIDE                      = PFM_SIDEBYSIDE           shr 16;    { (*)    }
  721.   PFE_TABLEROW                        = $C000;          { These 3 options are mutually   }
  722.   PFE_TABLECELLEND                    = $8000;          {  exclusive and each imply      }
  723.   PFE_TABLECELL                       = $4000;          {  that para is part of a table  }
  724.   PFA_JUSTIFY                         = 4;      { New paragraph-alignment option 2.0 (*) }
  725. const
  726.   SF_UNICODE = $0010;  { Unicode file of some kind }
  727. type
  728.   TFindTextExA = record
  729.     chrg: TCharRange;
  730.     lpstrText: PAnsiChar;
  731.     chrgText: TCharRange;
  732.   end;
  733.   TObjectPositions = packed record 
  734.     nmhdr: TNMHdr;
  735.     cObjectCount: Longint;
  736.     pcpPositions: PLongint;
  737.   end;
  738.   TENLink = record 
  739.     nmhdr: TNMHdr;
  740.     msg: UINT;
  741.     wParam: WPARAM;
  742.     lParam: LPARAM;
  743.     chrg: TCharRange;
  744.   end;
  745.   TENOleOpFailed = packed record 
  746.     nmhdr: TNMHdr;
  747.     iob: Longint;
  748.     lOper: Longint;
  749.     hr: HRESULT;
  750.   end;
  751. { flags for the GETTEXTLENGTHEX data structure }
  752. const
  753.   GTL_DEFAULT         = 0;      { do the default (return # of chars)        }
  754.   GTL_USECRLF         = 1;      { compute answer using CRLFs for paragraphs }
  755.   GTL_PRECISE         = 2;      { compute a precise answer                  }
  756.   GTL_CLOSE           = 4;      { fast computation of a "close" answer      }
  757.   GTL_NUMCHARS        = 8;      { return the number of characters           }
  758.   GTL_NUMBYTES        = 16;     { return the number of _bytes_              }
  759. { EM_GETTEXTLENGTHEX info; this struct is passed in the wparam of the msg }
  760. type
  761.   TGetTextLengthEx = record 
  762.     flags: DWORD;              { flags (see GTL_XXX defines)  }
  763.     codepage: UINT;            { code page for translation    }
  764.   end;
  765. const
  766.   OLEOP_DOVERB = 1;
  767. {$ENDIF RX_D3}
  768. const
  769.   FT_DOWN = 1;
  770. type
  771.   PENLink = ^TENLink;
  772.   PENOleOpFailed = ^TENOleOpFailed;
  773.   TFindTextEx = TFindTextExA;
  774.   TTextRangeA = record
  775.     chrg: TCharRange;
  776.     lpstrText: PAnsiChar;
  777.   end;
  778.   TTextRangeW = record
  779.     chrg: TCharRange;
  780.     lpstrText: PWideChar;
  781.   end;
  782.   TTextRange = TTextRangeA;
  783. {$IFDEF RX_D3}
  784. function ResStr(const Ident: string): string;
  785. begin
  786.   Result := Ident;
  787. end;
  788. {$ELSE}
  789. function ResStr(Ident: Cardinal): string;
  790. begin
  791.   Result := LoadStr(Ident);
  792. end;
  793. {$ENDIF}
  794. { TRxTextAttributes }
  795. const
  796.   AttrFlags: array[TRxAttributeType] of Word = (0, SCF_SELECTION,
  797.     SCF_WORD or SCF_SELECTION);
  798. constructor TRxTextAttributes.Create(AOwner: TRxCustomRichEdit;
  799.   AttributeType: TRxAttributeType);
  800. begin
  801.   inherited Create;
  802.   RichEdit := AOwner;
  803.   FType := AttributeType;
  804. end;
  805. procedure TRxTextAttributes.InitFormat(var Format: TCharFormat2);
  806. begin
  807.   FillChar(Format, SizeOf(Format), 0);
  808.   if RichEditVersion >= 2 then Format.cbSize := SizeOf(Format)
  809.   else Format.cbSize := SizeOf(TCharFormat);
  810. end;
  811. function TRxTextAttributes.GetConsistentAttributes: TRxConsistentAttributes;
  812. var
  813.   Format: TCharFormat2;
  814. begin
  815.   Result := [];
  816.   if RichEdit.HandleAllocated and (FType <> atDefaultText) then begin
  817.     InitFormat(Format);
  818.     SendMessage(RichEdit.Handle, EM_GETCHARFORMAT,
  819.       AttrFlags[FType], LPARAM(@Format));
  820.     with Format do begin
  821.       if (dwMask and CFM_BOLD) <> 0 then Include(Result, caBold);
  822.       if (dwMask and CFM_COLOR) <> 0 then Include(Result, caColor);
  823.       if (dwMask and CFM_FACE) <> 0 then Include(Result, caFace);
  824.       if (dwMask and CFM_ITALIC) <> 0 then Include(Result, caItalic);
  825.       if (dwMask and CFM_SIZE) <> 0 then Include(Result, caSize);
  826.       if (dwMask and CFM_STRIKEOUT) <> 0 then Include(Result, caStrikeOut);
  827.       if (dwMask and CFM_UNDERLINE) <> 0 then Include(Result, caUnderline);
  828.       if (dwMask and CFM_PROTECTED) <> 0 then Include(Result, caProtected);
  829.       if (dwMask and CFM_OFFSET) <> 0 then Include(Result, caOffset);
  830.       if (dwMask and CFM_HIDDEN) <> 0 then Include(result, caHidden);
  831.       if RichEditVersion >= 2 then begin
  832.         if (dwMask and CFM_LINK) <> 0 then Include(Result, caLink);
  833.         if (dwMask and CFM_BACKCOLOR) <> 0 then Include(Result, caBackColor);
  834.         if (dwMask and CFM_DISABLED) <> 0 then Include(Result, caDisabled);
  835.         if (dwMask and CFM_WEIGHT) <> 0 then Include(Result, caWeight);
  836.         if (dwMask and CFM_SUBSCRIPT) <> 0 then Include(Result, caSubscript);
  837.         if (dwMask and CFM_REVAUTHOR) <> 0 then Include(Result, caRevAuthor);
  838.       end;
  839.     end;
  840.   end;
  841. end;
  842. procedure TRxTextAttributes.GetAttributes(var Format: TCharFormat2);
  843. begin
  844.   InitFormat(Format);
  845.   if RichEdit.HandleAllocated then
  846.     SendMessage(RichEdit.Handle, EM_GETCHARFORMAT, AttrFlags[FType],
  847.       LPARAM(@Format));
  848. end;
  849. procedure TRxTextAttributes.SetAttributes(var Format: TCharFormat2);
  850. begin
  851.   if RichEdit.HandleAllocated then
  852.     SendMessage(RichEdit.Handle, EM_SETCHARFORMAT, AttrFlags[FType],
  853.       LPARAM(@Format));
  854. end;
  855. {$IFNDEF VER90}
  856. function TRxTextAttributes.GetCharset: TFontCharset;
  857. var
  858.   Format: TCharFormat2;
  859. begin
  860.   GetAttributes(Format);
  861.   Result := Format.bCharset;
  862. end;
  863. procedure TRxTextAttributes.SetCharset(Value: TFontCharset);
  864. var
  865.   Format: TCharFormat2;
  866. begin
  867.   InitFormat(Format);
  868.   with Format do
  869.   begin
  870.     dwMask := CFM_CHARSET;
  871.     bCharSet := Value;
  872.   end;
  873.   SetAttributes(Format);
  874. end;
  875. {$ENDIF}
  876. function TRxTextAttributes.GetProtected: Boolean;
  877. var
  878.   Format: TCharFormat2;
  879. begin
  880.   GetAttributes(Format);
  881.   with Format do
  882.     Result := (dwEffects and CFE_PROTECTED) <> 0;
  883. end;
  884. procedure TRxTextAttributes.SetProtected(Value: Boolean);
  885. var
  886.   Format: TCharFormat2;
  887. begin
  888.   InitFormat(Format);
  889.   with Format do begin
  890.     dwMask := CFM_PROTECTED;
  891.     if Value then dwEffects := CFE_PROTECTED;
  892.   end;
  893.   SetAttributes(Format);
  894. end;
  895. function TRxTextAttributes.GetLink: Boolean;
  896. var
  897.   Format: TCharFormat2;
  898. begin
  899.   Result := False;
  900.   if RichEditVersion < 2 then Exit;
  901.   GetAttributes(Format);
  902.   with Format do Result := (dwEffects and CFE_LINK) <> 0;
  903. end;
  904. procedure TRxTextAttributes.SetLink(Value: Boolean);
  905. var
  906.   Format: TCharFormat2;
  907. begin
  908.   if RichEditVersion < 2 then Exit;
  909.   InitFormat(Format);
  910.   with Format do begin
  911.     dwMask := CFM_LINK;
  912.     if Value then dwEffects := CFE_LINK;
  913.   end;
  914.   SetAttributes(Format);
  915. end;
  916. function TRxTextAttributes.GetRevAuthorIndex: Byte;
  917. var
  918.   Format: TCharFormat2;
  919. begin
  920.   GetAttributes(Format);
  921.   Result := Format.bRevAuthor;
  922. end;
  923. procedure TRxTextAttributes.SetRevAuthorIndex(Value: Byte);
  924. var
  925.   Format: TCharFormat2;
  926. begin
  927.   if RichEditVersion < 2 then Exit;
  928.   InitFormat(Format);
  929.   with Format do begin
  930.     dwMask := CFM_REVAUTHOR;
  931.     bRevAuthor := Value;
  932.   end;
  933.   SetAttributes(Format);
  934. end;
  935. function TRxTextAttributes.GetHidden: Boolean;
  936. var
  937.   Format: TCharFormat2;
  938. begin
  939.   Result := False;
  940.   if RichEditVersion < 2 then Exit;
  941.   GetAttributes(Format);
  942.   Result := Format.dwEffects and CFE_HIDDEN <> 0;
  943. end;
  944. procedure TRxTextAttributes.SetHidden(Value: Boolean);
  945. var
  946.   Format: TCharFormat2;
  947. begin
  948.   if RichEditVersion < 2 then Exit;
  949.   InitFormat(Format);
  950.   with Format do begin
  951.     dwMask := CFM_HIDDEN;
  952.     if Value then dwEffects := CFE_HIDDEN;
  953.   end;
  954.   SetAttributes(Format);
  955. end;
  956. function TRxTextAttributes.GetDisabled: Boolean;
  957. var
  958.   Format: TCharFormat2;
  959. begin
  960.   Result := False;
  961.   if RichEditVersion < 2 then Exit;
  962.   GetAttributes(Format);
  963.   Result := Format.dwEffects and CFE_DISABLED <> 0;
  964. end;
  965. procedure TRxTextAttributes.SetDisabled(Value: Boolean);
  966. var
  967.   Format: TCharFormat2;
  968. begin
  969.   if RichEditVersion < 2 then Exit;
  970.   InitFormat(Format);
  971.   with Format do begin
  972.     dwMask := CFM_DISABLED;
  973.     if Value then dwEffects := CFE_DISABLED;
  974.   end;
  975.   SetAttributes(Format);
  976. end;
  977. function TRxTextAttributes.GetColor: TColor;
  978. var
  979.   Format: TCharFormat2;
  980. begin
  981.   GetAttributes(Format);
  982.   with Format do
  983.     if (dwEffects and CFE_AUTOCOLOR) <> 0 then Result := clWindowText
  984.     else Result := crTextColor;
  985. end;
  986. procedure TRxTextAttributes.SetColor(Value: TColor);
  987. var
  988.   Format: TCharFormat2;
  989. begin
  990.   InitFormat(Format);
  991.   with Format do begin
  992.     dwMask := CFM_COLOR;
  993.     if (Value = clWindowText) or (Value = clDefault) then
  994.       dwEffects := CFE_AUTOCOLOR
  995.     else crTextColor := ColorToRGB(Value);
  996.   end;
  997.   SetAttributes(Format);
  998. end;
  999. function TRxTextAttributes.GetBackColor: TColor;
  1000. var
  1001.   Format: TCharFormat2;
  1002. begin
  1003.   if RichEditVersion < 2 then begin
  1004.     Result := clWindow;
  1005.     Exit;
  1006.   end;
  1007.   GetAttributes(Format);
  1008.   with Format do
  1009.     if (dwEffects and CFE_AUTOBACKCOLOR) <> 0 then Result := clWindow
  1010.     else Result := crBackColor;
  1011. end;
  1012. procedure TRxTextAttributes.SetBackColor(Value: TColor);
  1013. var
  1014.   Format: TCharFormat2;
  1015. begin
  1016.   if RichEditVersion < 2 then Exit;
  1017.   InitFormat(Format);
  1018.   with Format do begin
  1019.     dwMask := CFM_BACKCOLOR;
  1020.     if (Value = clWindow) or (Value = clDefault) then
  1021.       dwEffects := CFE_AUTOBACKCOLOR
  1022.     else crBackColor := ColorToRGB(Value);
  1023.   end;
  1024.   SetAttributes(Format);
  1025. end;
  1026. function TRxTextAttributes.GetName: TFontName;
  1027. var
  1028.   Format: TCharFormat2;
  1029. begin
  1030.   GetAttributes(Format);
  1031.   Result := Format.szFaceName;
  1032. end;
  1033. procedure TRxTextAttributes.SetName(Value: TFontName);
  1034. var
  1035.   Format: TCharFormat2;
  1036. begin
  1037.   InitFormat(Format);
  1038.   with Format do begin
  1039.     dwMask := CFM_FACE;
  1040.     StrPLCopy(szFaceName, Value, SizeOf(szFaceName));
  1041.   end;
  1042.   SetAttributes(Format);
  1043. end;
  1044. function TRxTextAttributes.GetStyle: TFontStyles;
  1045. var
  1046.   Format: TCharFormat2;
  1047. begin
  1048.   Result := [];
  1049.   GetAttributes(Format);
  1050.   with Format do begin
  1051.     if (dwEffects and CFE_BOLD) <> 0 then Include(Result, fsBold);
  1052.     if (dwEffects and CFE_ITALIC) <> 0 then Include(Result, fsItalic);
  1053.     if (dwEffects and CFE_UNDERLINE) <> 0 then Include(Result, fsUnderline);
  1054.     if (dwEffects and CFE_STRIKEOUT) <> 0 then Include(Result, fsStrikeOut);
  1055.   end;
  1056. end;
  1057. procedure TRxTextAttributes.SetStyle(Value: TFontStyles);
  1058. var
  1059.   Format: TCharFormat2;
  1060. begin
  1061.   InitFormat(Format);
  1062.   with Format do begin
  1063.     dwMask := CFM_BOLD or CFM_ITALIC or CFM_UNDERLINE or CFM_STRIKEOUT;
  1064.     if fsBold in Value then dwEffects := dwEffects or CFE_BOLD;
  1065.     if fsItalic in Value then dwEffects := dwEffects or CFE_ITALIC;
  1066.     if fsUnderline in Value then dwEffects := dwEffects or CFE_UNDERLINE;
  1067.     if fsStrikeOut in Value then dwEffects := dwEffects or CFE_STRIKEOUT;
  1068.   end;
  1069.   SetAttributes(Format);
  1070. end;
  1071. function TRxTextAttributes.GetUnderlineType: TUnderlineType;
  1072. var
  1073.   Format: TCharFormat2;
  1074. begin
  1075.   Result := utNone;
  1076.   if RichEditVersion < 2 then Exit;
  1077.   GetAttributes(Format);
  1078.   with Format do begin
  1079.     if (dwEffects and CFE_UNDERLINE <> 0) and
  1080.       (dwMask and CFM_UNDERLINETYPE = CFM_UNDERLINETYPE) then
  1081.       Result := TUnderlineType(bUnderlineType);
  1082.   end;
  1083. end;
  1084. procedure TRxTextAttributes.SetUnderlineType(Value: TUnderlineType);
  1085. var
  1086.   Format: TCharFormat2;
  1087. begin
  1088.   if RichEditVersion < 2 then Exit;
  1089.   InitFormat(Format);
  1090.   with Format do begin
  1091.     dwMask := CFM_UNDERLINETYPE or CFM_UNDERLINE;
  1092.     bUnderlineType := Ord(Value);
  1093.     if Value <> utNone then dwEffects := dwEffects or CFE_UNDERLINE;
  1094.   end;
  1095.   SetAttributes(Format);
  1096. end;
  1097. function TRxTextAttributes.GetOffset: Integer;
  1098. var
  1099.   Format: TCharFormat2;
  1100. begin
  1101.   GetAttributes(Format);
  1102.   Result := Format.yOffset div 20;
  1103. end;
  1104. procedure TRxTextAttributes.SetOffset(Value: Integer);
  1105. var
  1106.   Format: TCharFormat2;
  1107. begin
  1108.   InitFormat(Format);
  1109.   with Format do begin
  1110.     dwMask := DWORD(CFM_OFFSET);
  1111.     yOffset := Value * 20;
  1112.   end;
  1113.   SetAttributes(Format);
  1114. end;
  1115. function TRxTextAttributes.GetSize: Integer;
  1116. var
  1117.   Format: TCharFormat2;
  1118. begin
  1119.   GetAttributes(Format);
  1120.   Result := Format.yHeight div 20;
  1121. end;
  1122. procedure TRxTextAttributes.SetSize(Value: Integer);
  1123. var
  1124.   Format: TCharFormat2;
  1125. begin
  1126.   InitFormat(Format);
  1127.   with Format do begin
  1128.     dwMask := DWORD(CFM_SIZE);
  1129.     yHeight := Value * 20;
  1130.   end;
  1131.   SetAttributes(Format);
  1132. end;
  1133. function TRxTextAttributes.GetHeight: Integer;
  1134. begin
  1135.   Result := MulDiv(Size, RichEdit.FScreenLogPixels, 72);
  1136. end;
  1137. procedure TRxTextAttributes.SetHeight(Value: Integer);
  1138. begin
  1139.   Size := MulDiv(Value, 72, RichEdit.FScreenLogPixels);
  1140. end;
  1141. function TRxTextAttributes.GetPitch: TFontPitch;
  1142. var
  1143.   Format: TCharFormat2;
  1144. begin
  1145.   GetAttributes(Format);
  1146.   case (Format.bPitchAndFamily and $03) of
  1147.     DEFAULT_PITCH: Result := fpDefault;
  1148.     VARIABLE_PITCH: Result := fpVariable;
  1149.     FIXED_PITCH: Result := fpFixed;
  1150.     else Result := fpDefault;
  1151.   end;
  1152. end;
  1153. procedure TRxTextAttributes.SetPitch(Value: TFontPitch);
  1154. var
  1155.   Format: TCharFormat2;
  1156. begin
  1157.   InitFormat(Format);
  1158.   with Format do begin
  1159.     case Value of
  1160.       fpVariable: bPitchAndFamily := VARIABLE_PITCH;
  1161.       fpFixed: bPitchAndFamily := FIXED_PITCH;
  1162.       else bPitchAndFamily := DEFAULT_PITCH;
  1163.     end;
  1164.   end;
  1165.   SetAttributes(Format);
  1166. end;
  1167. function TRxTextAttributes.GetSubscriptStyle: TSubscriptStyle;
  1168. var
  1169.   Format: TCharFormat2;
  1170. begin
  1171.   Result := ssNone;
  1172.   if RichEditVersion < 2 then Exit;
  1173.   GetAttributes(Format);
  1174.   with Format do begin
  1175.     if (dwEffects and CFE_SUBSCRIPT) <> 0 then
  1176.       Result := ssSubscript
  1177.     else if (dwEffects and CFE_SUPERSCRIPT) <> 0 then
  1178.       Result := ssSuperscript;
  1179.   end;
  1180. end;
  1181. procedure TRxTextAttributes.SetSubscriptStyle(Value: TSubscriptStyle);
  1182. var
  1183.   Format: TCharFormat2;
  1184. begin
  1185.   if RichEditVersion < 2 then Exit;
  1186.   InitFormat(Format);
  1187.   with Format do begin
  1188.     dwMask := DWORD(CFM_SUBSCRIPT);
  1189.     case Value of
  1190.       ssSubscript: dwEffects := CFE_SUBSCRIPT;
  1191.       ssSuperscript: dwEffects := CFE_SUPERSCRIPT;
  1192.     end;
  1193.   end;
  1194.   SetAttributes(Format);
  1195. end;
  1196. procedure TRxTextAttributes.AssignFont(Font: TFont);
  1197. var
  1198.   LogFont: TLogFont;
  1199.   Format: TCharFormat2;
  1200. begin
  1201.   InitFormat(Format);
  1202.   with Format do begin
  1203.     case Font.Pitch of
  1204.       fpVariable: bPitchAndFamily := VARIABLE_PITCH;
  1205.       fpFixed: bPitchAndFamily := FIXED_PITCH;
  1206.       else bPitchAndFamily := DEFAULT_PITCH;
  1207.     end;
  1208.     dwMask := dwMask or CFM_SIZE or CFM_BOLD or CFM_ITALIC or
  1209.       CFM_UNDERLINE or CFM_STRIKEOUT or CFM_FACE or CFM_COLOR;
  1210.     yHeight := Font.Size * 20;
  1211.     if fsBold in Font.Style then dwEffects := dwEffects or CFE_BOLD;
  1212.     if fsItalic in Font.Style then dwEffects := dwEffects or CFE_ITALIC;
  1213.     if fsUnderline in Font.Style then dwEffects := dwEffects or CFE_UNDERLINE;
  1214.     if fsStrikeOut in Font.Style then dwEffects := dwEffects or CFE_STRIKEOUT;
  1215.     StrPLCopy(szFaceName, Font.Name, SizeOf(szFaceName));
  1216.     if (Font.Color = clWindowText) or (Font.Color = clDefault) then
  1217.       dwEffects := CFE_AUTOCOLOR
  1218.     else crTextColor := ColorToRGB(Font.Color);
  1219. {$IFNDEF VER90}
  1220.     dwMask := dwMask or CFM_CHARSET;
  1221.     bCharSet := Font.Charset;
  1222. {$ENDIF}
  1223.     if GetObject(Font.Handle, SizeOf(LogFont), @LogFont) <> 0 then begin
  1224.       dwMask := dwMask or DWORD(CFM_WEIGHT);
  1225.       wWeight := Word(LogFont.lfWeight);
  1226.     end;
  1227.   end;
  1228.   SetAttributes(Format);
  1229. end;
  1230. procedure TRxTextAttributes.Assign(Source: TPersistent);
  1231. var
  1232.   Format: TCharFormat2;
  1233. begin
  1234.   if Source is TFont then AssignFont(TFont(Source))
  1235.   else if Source is TTextAttributes then begin
  1236.     Name := TTextAttributes(Source).Name;
  1237. {$IFDEF RX_D3}
  1238.     Charset := TTextAttributes(Source).Charset;
  1239. {$ENDIF}
  1240.     Style := TTextAttributes(Source).Style;
  1241.     Pitch := TTextAttributes(Source).Pitch;
  1242.     Color := TTextAttributes(Source).Color;
  1243.   end
  1244.   else if Source is TRxTextAttributes then begin
  1245.     TRxTextAttributes(Source).GetAttributes(Format);
  1246.     SetAttributes(Format);
  1247.   end
  1248.   else inherited Assign(Source);
  1249. end;
  1250. procedure TRxTextAttributes.AssignTo(Dest: TPersistent);
  1251. begin
  1252.   if Dest is TFont then begin
  1253.     TFont(Dest).Color := Color;
  1254.     TFont(Dest).Name := Name;
  1255. {$IFNDEF VER90}
  1256.     TFont(Dest).Charset := Charset;
  1257. {$ENDIF}
  1258.     TFont(Dest).Style := Style;
  1259.     TFont(Dest).Size := Size;
  1260.     TFont(Dest).Pitch := Pitch;
  1261.   end
  1262.   else if Dest is TTextAttributes then begin
  1263.     TTextAttributes(Dest).Color := Color;
  1264.     TTextAttributes(Dest).Name := Name;
  1265. {$IFDEF RX_D3}
  1266.     TTextAttributes(Dest).Charset := Charset;
  1267. {$ENDIF}
  1268.     TTextAttributes(Dest).Style := Style;
  1269.     TTextAttributes(Dest).Pitch := Pitch;
  1270.   end
  1271.   else inherited AssignTo(Dest);
  1272. end;
  1273. { TRxParaAttributes }
  1274. constructor TRxParaAttributes.Create(AOwner: TRxCustomRichEdit);
  1275. begin
  1276.   inherited Create;
  1277.   RichEdit := AOwner;
  1278. end;
  1279. procedure TRxParaAttributes.InitPara(var Paragraph: TParaFormat2);
  1280. begin
  1281.   FillChar(Paragraph, SizeOf(Paragraph), 0);
  1282.   if RichEditVersion >= 2 then
  1283.     Paragraph.cbSize := SizeOf(Paragraph)
  1284.   else
  1285.     Paragraph.cbSize := SizeOf(TParaFormat);
  1286. end;
  1287. procedure TRxParaAttributes.GetAttributes(var Paragraph: TParaFormat2);
  1288. begin
  1289.   InitPara(Paragraph);
  1290.   if RichEdit.HandleAllocated then
  1291.     SendMessage(RichEdit.Handle, EM_GETPARAFORMAT, 0, LPARAM(@Paragraph));
  1292. end;
  1293. procedure TRxParaAttributes.SetAttributes(var Paragraph: TParaFormat2);
  1294. begin
  1295. {$IFDEF RX_D4}
  1296.   RichEdit.HandleNeeded; { we REALLY need the handle for BiDi }
  1297. {$ENDIF}
  1298.   if RichEdit.HandleAllocated then begin
  1299. {$IFDEF RX_D4}
  1300.     if RichEdit.UseRightToLeftAlignment then
  1301.       if Paragraph.wAlignment = PFA_LEFT then
  1302.         Paragraph.wAlignment := PFA_RIGHT
  1303.       else if Paragraph.wAlignment = PFA_RIGHT then
  1304.         Paragraph.wAlignment := PFA_LEFT;
  1305. {$ENDIF}
  1306.     SendMessage(RichEdit.Handle, EM_SETPARAFORMAT, 0, LPARAM(@Paragraph));
  1307.   end;
  1308. end;
  1309. function TRxParaAttributes.GetAlignment: TParaAlignment;
  1310. var
  1311.   Paragraph: TParaFormat2;
  1312. begin
  1313.   GetAttributes(Paragraph);
  1314.   Result := TParaAlignment(Paragraph.wAlignment - 1);
  1315. end;
  1316. procedure TRxParaAttributes.SetAlignment(Value: TParaAlignment);
  1317. var
  1318.   Paragraph: TParaFormat2;
  1319. begin
  1320.   InitPara(Paragraph);
  1321.   with Paragraph do
  1322.   begin
  1323.     dwMask := PFM_ALIGNMENT;
  1324.     wAlignment := Ord(Value) + 1;
  1325.   end;
  1326.   SetAttributes(Paragraph);
  1327. end;
  1328. function TRxParaAttributes.GetNumbering: TRxNumbering;
  1329. var
  1330.   Paragraph: TParaFormat2;
  1331. begin
  1332.   GetAttributes(Paragraph);
  1333.   Result := TRxNumbering(Paragraph.wNumbering);
  1334.   if RichEditVersion = 1 then
  1335.     if Result <> nsNone then Result := nsBullet;
  1336. end;
  1337. procedure TRxParaAttributes.SetNumbering(Value: TRxNumbering);
  1338. var
  1339.   Paragraph: TParaFormat2;
  1340. begin
  1341.   if RichEditVersion = 1 then
  1342.     if Value <> nsNone then Value := TRxNumbering(PFN_BULLET);
  1343.   case Value of
  1344.     nsNone: LeftIndent := 0;
  1345.     else if LeftIndent < 10 then LeftIndent := 10;
  1346.   end;
  1347.   InitPara(Paragraph);
  1348.   with Paragraph do begin
  1349.     dwMask := PFM_NUMBERING;
  1350.     wNumbering := Ord(Value);
  1351.   end;
  1352.   SetAttributes(Paragraph);
  1353. end;
  1354. function TRxParaAttributes.GetNumberingStyle: TRxNumberingStyle;
  1355. var
  1356.   Paragraph: TParaFormat2;
  1357. begin
  1358.   if RichEditVersion < 2 then
  1359.     Result := nsSimple
  1360.   else begin
  1361.     GetAttributes(Paragraph);
  1362.     Result := TRxNumberingStyle(Paragraph.wNumberingStyle);
  1363.   end;
  1364. end;
  1365. procedure TRxParaAttributes.SetNumberingStyle(Value: TRxNumberingStyle);
  1366. var
  1367.   Paragraph: TParaFormat2;
  1368. begin
  1369.   if RichEditVersion < 2 then Exit;
  1370.   InitPara(Paragraph);
  1371.   with Paragraph do begin
  1372.     dwMask := PFM_NUMBERINGSTYLE;
  1373.     wNumberingStyle := Ord(Value);
  1374.   end;
  1375.   SetAttributes(Paragraph);
  1376. end;
  1377. function TRxParaAttributes.GetNumberingTab: Word;
  1378. var
  1379.   Paragraph: TParaFormat2;
  1380. begin
  1381.   GetAttributes(Paragraph);
  1382.   Result := Paragraph.wNumberingTab div 20;
  1383. end;
  1384. procedure TRxParaAttributes.SetNumberingTab(Value: Word);
  1385. var
  1386.   Paragraph: TParaFormat2;
  1387. begin
  1388.   if RichEditVersion < 2 then Exit;
  1389.   InitPara(Paragraph);
  1390.   with Paragraph do begin
  1391.     dwMask := PFM_NUMBERINGTAB;
  1392.     wNumberingTab := Value * 20;
  1393.   end;
  1394.   SetAttributes(Paragraph);
  1395. end;
  1396. function TRxParaAttributes.GetFirstIndent: Longint;
  1397. var
  1398.   Paragraph: TParaFormat2;
  1399. begin
  1400.   GetAttributes(Paragraph);
  1401.   Result := Paragraph.dxStartIndent div 20;
  1402. end;
  1403. procedure TRxParaAttributes.SetFirstIndent(Value: Longint);
  1404. var
  1405.   Paragraph: TParaFormat2;
  1406. begin
  1407.   InitPara(Paragraph);
  1408.   with Paragraph do
  1409.   begin
  1410.     dwMask := PFM_STARTINDENT;
  1411.     dxStartIndent := Value * 20;
  1412.   end;
  1413.   SetAttributes(Paragraph);
  1414. end;
  1415. function TRxParaAttributes.GetHeadingStyle: THeadingStyle;
  1416. var
  1417.   Paragraph: TParaFormat2;
  1418. begin
  1419.   if RichEditVersion < 3 then Result := 0
  1420.   else begin
  1421.     GetAttributes(Paragraph);
  1422.     Result := Paragraph.sStyle;
  1423.   end;
  1424. end;
  1425. procedure TRxParaAttributes.SetHeadingStyle(Value: THeadingStyle);
  1426. var
  1427.   Paragraph: TParaFormat2;
  1428. begin
  1429.   if RichEditVersion < 3 then Exit;
  1430.   InitPara(Paragraph);
  1431.   with Paragraph do begin
  1432.     dwMask := PFM_STYLE;
  1433.     sStyle := Value;
  1434.   end;
  1435.   SetAttributes(Paragraph);
  1436. end;
  1437. function TRxParaAttributes.GetLeftIndent: Longint;
  1438. var
  1439.   Paragraph: TParaFormat2;
  1440. begin
  1441.   GetAttributes(Paragraph);
  1442.   Result := Paragraph.dxOffset div 20;
  1443. end;
  1444. procedure TRxParaAttributes.SetLeftIndent(Value: Longint);
  1445. var
  1446.   Paragraph: TParaFormat2;
  1447. begin
  1448.   InitPara(Paragraph);
  1449.   with Paragraph do
  1450.   begin
  1451.     dwMask := PFM_OFFSET;
  1452.     dxOffset := Value * 20;
  1453.   end;
  1454.   SetAttributes(Paragraph);
  1455. end;
  1456. function TRxParaAttributes.GetRightIndent: Longint;
  1457. var
  1458.   Paragraph: TParaFormat2;
  1459. begin
  1460.   GetAttributes(Paragraph);
  1461.   Result := Paragraph.dxRightIndent div 20;
  1462. end;
  1463. procedure TRxParaAttributes.SetRightIndent(Value: Longint);
  1464. var
  1465.   Paragraph: TParaFormat2;
  1466. begin
  1467.   InitPara(Paragraph);
  1468.   with Paragraph do
  1469.   begin
  1470.     dwMask := PFM_RIGHTINDENT;
  1471.     dxRightIndent := Value * 20;
  1472.   end;
  1473.   SetAttributes(Paragraph);
  1474. end;
  1475. function TRxParaAttributes.GetSpaceAfter: Longint;
  1476. var
  1477.   Paragraph: TParaFormat2;
  1478. begin
  1479.   GetAttributes(Paragraph);
  1480.   Result := Paragraph.dySpaceAfter div 20;
  1481. end;
  1482. procedure TRxParaAttributes.SetSpaceAfter(Value: Longint);
  1483. var
  1484.   Paragraph: TParaFormat2;
  1485. begin
  1486.   if RichEditVersion < 2 then Exit;
  1487.   InitPara(Paragraph);
  1488.   with Paragraph do begin
  1489.     dwMask := PFM_SPACEAFTER;
  1490.     dySpaceAfter := Value * 20;
  1491.   end;
  1492.   SetAttributes(Paragraph);
  1493. end;
  1494. function TRxParaAttributes.GetSpaceBefore: Longint;
  1495. var
  1496.   Paragraph: TParaFormat2;
  1497. begin
  1498.   GetAttributes(Paragraph);
  1499.   Result := Paragraph.dySpaceBefore div 20;
  1500. end;
  1501. procedure TRxParaAttributes.SetSpaceBefore(Value: Longint);
  1502. var
  1503.   Paragraph: TParaFormat2;
  1504. begin
  1505.   if RichEditVersion < 2 then Exit;
  1506.   InitPara(Paragraph);
  1507.   with Paragraph do begin
  1508.     dwMask := PFM_SPACEBEFORE;
  1509.     dySpaceBefore := Value * 20;
  1510.   end;
  1511.   SetAttributes(Paragraph);
  1512. end;
  1513. function TRxParaAttributes.GetLineSpacing: Longint;
  1514. var
  1515.   Paragraph: TParaFormat2;
  1516. begin
  1517.   GetAttributes(Paragraph);
  1518.   Result := Paragraph.dyLineSpacing div 20;
  1519. end;
  1520. procedure TRxParaAttributes.SetLineSpacing(Value: Longint);
  1521. var
  1522.   Paragraph: TParaFormat2;
  1523. begin
  1524.   if RichEditVersion < 2 then Exit;
  1525.   GetAttributes(Paragraph);
  1526.   with Paragraph do begin
  1527.     dwMask := PFM_LINESPACING;
  1528.     dyLineSpacing := Value * 20;
  1529.   end;
  1530.   SetAttributes(Paragraph);
  1531. end;
  1532. function TRxParaAttributes.GetLineSpacingRule: TLineSpacingRule;
  1533. var
  1534.   Paragraph: TParaFormat2;
  1535. begin
  1536.   GetAttributes(Paragraph);
  1537.   Result := TLineSpacingRule(Paragraph.bLineSpacingRule);
  1538. end;
  1539. procedure TRxParaAttributes.SetLineSpacingRule(Value: TLineSpacingRule);
  1540. var
  1541.   Paragraph: TParaFormat2;
  1542. begin
  1543.   if RichEditVersion < 2 then Exit;
  1544.   GetAttributes(Paragraph);
  1545.   with Paragraph do begin
  1546.     dwMask := PFM_LINESPACING;
  1547.     bLineSpacingRule := Ord(Value);
  1548.   end;
  1549.   SetAttributes(Paragraph);
  1550. end;
  1551. function TRxParaAttributes.GetTab(Index: Byte): Longint;
  1552. var
  1553.   Paragraph: TParaFormat2;
  1554. begin
  1555.   GetAttributes(Paragraph);
  1556.   Result := Paragraph.rgxTabs[Index] div 20;
  1557. end;
  1558. procedure TRxParaAttributes.SetTab(Index: Byte; Value: Longint);
  1559. var
  1560.   Paragraph: TParaFormat2;
  1561. begin
  1562.   GetAttributes(Paragraph);
  1563.   with Paragraph do
  1564.   begin
  1565.     rgxTabs[Index] := Value * 20;
  1566.     dwMask := PFM_TABSTOPS;
  1567.     if cTabCount < Index then cTabCount := Index;
  1568.     SetAttributes(Paragraph);
  1569.   end;
  1570. end;
  1571. function TRxParaAttributes.GetTabCount: Integer;
  1572. var
  1573.   Paragraph: TParaFormat2;
  1574. begin
  1575.   GetAttributes(Paragraph);
  1576.   Result := Paragraph.cTabCount;
  1577. end;
  1578. procedure TRxParaAttributes.SetTabCount(Value: Integer);
  1579. var
  1580.   Paragraph: TParaFormat2;
  1581. begin
  1582.   GetAttributes(Paragraph);
  1583.   with Paragraph do
  1584.   begin
  1585.     dwMask := PFM_TABSTOPS;
  1586.     cTabCount := Value;
  1587.     SetAttributes(Paragraph);
  1588.   end;
  1589. end;
  1590. function TRxParaAttributes.GetTableStyle: TParaTableStyle;
  1591. var
  1592.   Paragraph: TParaFormat2;
  1593. begin
  1594.   Result := tsNone;
  1595.   if RichEditVersion < 2 then Exit;
  1596.   GetAttributes(Paragraph);
  1597.   with Paragraph do begin
  1598.     if (wReserved and PFE_TABLEROW) <> 0 then
  1599.       Result := tsTableRow
  1600.     else if (wReserved and PFE_TABLECELLEND) <> 0 then
  1601.       Result := tsTableCellEnd
  1602.     else if (wReserved and PFE_TABLECELL) <> 0 then
  1603.       Result := tsTableCell;
  1604.   end;
  1605. end;
  1606. procedure TRxParaAttributes.SetTableStyle(Value: TParaTableStyle);
  1607. var
  1608.   Paragraph: TParaFormat2;
  1609. begin
  1610.   if RichEditVersion < 2 then Exit;
  1611.   InitPara(Paragraph);
  1612.   with Paragraph do begin
  1613.     dwMask := PFM_TABLE;
  1614.     case Value of
  1615.       tsTableRow: wReserved := PFE_TABLEROW;
  1616.       tsTableCellEnd: wReserved := PFE_TABLECELLEND;
  1617.       tsTableCell: wReserved := PFE_TABLECELL;
  1618.     end;
  1619.   end;
  1620.   SetAttributes(Paragraph);
  1621. end;
  1622. procedure TRxParaAttributes.AssignTo(Dest: TPersistent);
  1623. var
  1624.   I: Integer;
  1625. begin
  1626.   if Dest is TParaAttributes then begin
  1627.     with TParaAttributes(Dest) do begin
  1628.       if Self.Alignment = paJustify then Alignment := taLeftJustify
  1629.       else Alignment := TAlignment(Self.Alignment);
  1630.       FirstIndent := Self.FirstIndent;
  1631.       LeftIndent := Self.LeftIndent;
  1632.       RightIndent := Self.RightIndent;
  1633.       if Self.Numbering <> nsNone then
  1634.         Numbering := TNumberingStyle(nsBullet)
  1635.       else Numbering := TNumberingStyle(nsNone);
  1636.       for I := 0 to MAX_TAB_STOPS - 1 do
  1637.         Tab[I] := Self.Tab[I];
  1638.     end;
  1639.   end
  1640.   else inherited AssignTo(Dest);
  1641. end;
  1642. procedure TRxParaAttributes.Assign(Source: TPersistent);
  1643. var
  1644.   I: Integer;
  1645.   Paragraph: TParaFormat2;
  1646. begin
  1647.   if Source is TParaAttributes then begin
  1648.     Alignment := TParaAlignment(TParaAttributes(Source).Alignment);
  1649.     FirstIndent := TParaAttributes(Source).FirstIndent;
  1650.     LeftIndent := TParaAttributes(Source).LeftIndent;
  1651.     RightIndent := TParaAttributes(Source).RightIndent;
  1652.     Numbering := TRxNumbering(TParaAttributes(Source).Numbering);
  1653.     for I := 0 to MAX_TAB_STOPS - 1 do
  1654.       Tab[I] := TParaAttributes(Source).Tab[I];
  1655.   end
  1656.   else if Source is TRxParaAttributes then begin
  1657.     TRxParaAttributes(Source).GetAttributes(Paragraph);
  1658.     SetAttributes(Paragraph);
  1659.   end
  1660.   else inherited Assign(Source);
  1661. end;
  1662. { OLE utility routines }
  1663. function WStrLen(Str: PWideChar): Integer;
  1664. begin
  1665.   Result := 0;
  1666.   while Str[Result] <> #0 do Inc(Result);
  1667. end;
  1668. procedure ReleaseObject(var Obj);
  1669. begin
  1670.   if IUnknown(Obj) <> nil then begin
  1671. {$IFNDEF RX_D3}
  1672.     IUnknown(Obj).Release;
  1673. {$ENDIF}
  1674.     IUnknown(Obj) := nil;
  1675.   end;
  1676. end;
  1677. procedure CreateStorage(var Storage: IStorage);
  1678. var
  1679.   LockBytes: ILockBytes;
  1680. begin
  1681.   OleCheck(CreateILockBytesOnHGlobal(0, True, LockBytes));
  1682.   try
  1683.     OleCheck(StgCreateDocfileOnILockBytes(LockBytes, STGM_READWRITE
  1684.       or STGM_SHARE_EXCLUSIVE or STGM_CREATE, 0, Storage));
  1685.   finally
  1686.     ReleaseObject(LockBytes);
  1687.   end;
  1688. end;
  1689. procedure DestroyMetaPict(MetaPict: HGlobal);
  1690. begin
  1691.   if MetaPict <> 0 then begin
  1692.     DeleteMetaFile(PMetaFilePict(GlobalLock(MetaPict))^.hMF);
  1693.     GlobalUnlock(MetaPict);
  1694.     GlobalFree(MetaPict);
  1695.   end;
  1696. end;
  1697. function OleSetDrawAspect(OleObject: IOleObject; Iconic: Boolean;
  1698.   IconMetaPict: HGlobal; var DrawAspect: Longint): HResult;
  1699. var
  1700.   OleCache: IOleCache;
  1701.   EnumStatData: IEnumStatData;
  1702.   OldAspect, AdviseFlags, Connection: Longint;
  1703.   TempMetaPict: HGlobal;
  1704.   FormatEtc: TFormatEtc;
  1705.   Medium: TStgMedium;
  1706.   ClassID: TCLSID;
  1707.   StatData: TStatData;
  1708. begin
  1709.   Result := S_OK;
  1710.   OldAspect := DrawAspect;
  1711.   if Iconic then begin
  1712.     DrawAspect := DVASPECT_ICON;
  1713.     AdviseFlags := ADVF_NODATA;
  1714.   end
  1715.   else begin
  1716.     DrawAspect := DVASPECT_CONTENT;
  1717.     AdviseFlags := ADVF_PRIMEFIRST;
  1718.   end;
  1719.   if (DrawAspect <> OldAspect) or (DrawAspect = DVASPECT_ICON) then begin
  1720. {$IFDEF RX_D3}
  1721.     Result := OleObject.QueryInterface(IOleCache, OleCache);
  1722. {$ELSE}
  1723.     Result := OleObject.QueryInterface(IID_IOleCache, OleCache);
  1724. {$ENDIF}
  1725.     if Succeeded(Result) then
  1726.     try
  1727.       if DrawAspect <> OldAspect then begin
  1728.         { Setup new cache with the new aspect }
  1729.         FillChar(FormatEtc, SizeOf(FormatEtc), 0);
  1730.         FormatEtc.dwAspect := DrawAspect;
  1731.         FormatEtc.lIndex := -1;
  1732.         Result := OleCache.Cache(FormatEtc, AdviseFlags, Connection);
  1733.       end;
  1734.       if Succeeded(Result) and (DrawAspect = DVASPECT_ICON) then begin
  1735.         TempMetaPict := 0;
  1736.         if IconMetaPict = 0 then begin
  1737.           if Succeeded(OleObject.GetUserClassID(ClassID)) then begin
  1738.             TempMetaPict := OleGetIconOfClass(ClassID, nil, True);
  1739.             IconMetaPict := TempMetaPict;
  1740.           end;
  1741.         end;
  1742.         try
  1743.           FormatEtc.cfFormat := CF_METAFILEPICT;
  1744.           FormatEtc.ptd := nil;
  1745.           FormatEtc.dwAspect := DVASPECT_ICON;
  1746.           FormatEtc.lIndex := -1;
  1747.           FormatEtc.tymed := TYMED_MFPICT;
  1748.           Medium.tymed := TYMED_MFPICT;
  1749.           Medium.hMetaFilePict := IconMetaPict;
  1750.           Medium.unkForRelease := nil;
  1751.           Result := OleCache.SetData(FormatEtc, Medium, False);
  1752.         finally
  1753.           DestroyMetaPict(TempMetaPict);
  1754.         end;
  1755.       end;
  1756.       if Succeeded(Result) and (DrawAspect <> OldAspect) then begin
  1757.         { remove any existing caches that are set up for the old display aspect }
  1758.         OleCache.EnumCache(EnumStatData);
  1759.         if EnumStatData <> nil then
  1760.         try
  1761.           while EnumStatData.Next(1, StatData, nil) = 0 do
  1762.             if StatData.formatetc.dwAspect = OldAspect then
  1763.               OleCache.Uncache(StatData.dwConnection);
  1764.         finally
  1765.           ReleaseObject(EnumStatData);
  1766.         end;
  1767.       end;
  1768.     finally
  1769.       ReleaseObject(OleCache);
  1770.     end;
  1771.     if Succeeded(Result) and (DrawAspect <> DVASPECT_ICON) then
  1772.       OleObject.Update;
  1773.   end;
  1774. end;
  1775. function GetIconMetaPict(OleObject: IOleObject; DrawAspect: Longint): HGlobal;
  1776. var
  1777.   DataObject: IDataObject;
  1778.   FormatEtc: TFormatEtc;
  1779.   Medium: TStgMedium;
  1780.   ClassID: TCLSID;
  1781. begin
  1782.   Result := 0;
  1783.   if DrawAspect = DVASPECT_ICON then begin
  1784. {$IFDEF RX_D3}
  1785.     OleObject.QueryInterface(IDataObject, DataObject);
  1786. {$ELSE}
  1787.     OleObject.QueryInterface(IID_IDataObject, DataObject);
  1788. {$ENDIF}
  1789.     if DataObject <> nil then begin
  1790.       FormatEtc.cfFormat := CF_METAFILEPICT;
  1791.       FormatEtc.ptd := nil;
  1792.       FormatEtc.dwAspect := DVASPECT_ICON;
  1793.       FormatEtc.lIndex := -1;
  1794.       FormatEtc.tymed := TYMED_MFPICT;
  1795.       if Succeeded(DataObject.GetData(FormatEtc, Medium)) then
  1796.         Result := Medium.hMetaFilePict;
  1797.       ReleaseObject(DataObject);
  1798.     end;
  1799.   end;
  1800.   if Result = 0 then begin
  1801.     OleCheck(OleObject.GetUserClassID(ClassID));
  1802.     Result := OleGetIconOfClass(ClassID, nil, True);
  1803.   end;
  1804. end;
  1805. { Return the first piece of a moniker }
  1806. function OleStdGetFirstMoniker(Moniker: IMoniker): IMoniker;
  1807. var
  1808.   Mksys: Longint;
  1809.   EnumMoniker: IEnumMoniker;
  1810. begin
  1811.   Result := nil;
  1812.   if Moniker <> nil then begin
  1813.     if (Moniker.IsSystemMoniker(Mksys) = 0) and
  1814.       (Mksys = MKSYS_GENERICCOMPOSITE) then
  1815.     begin
  1816.       if Moniker.Enum(True, EnumMoniker) <> 0 then Exit;
  1817.       EnumMoniker.Next(1, Result, nil);
  1818.       ReleaseObject(EnumMoniker);
  1819.     end
  1820.     else begin
  1821. {$IFNDEF RX_D3}
  1822.       Moniker.AddRef;
  1823. {$ENDIF}
  1824.       Result := Moniker;
  1825.     end;
  1826.   end;
  1827. end;
  1828. { Return length of file moniker piece of the given moniker }
  1829. function OleStdGetLenFilePrefixOfMoniker(Moniker: IMoniker): Integer;
  1830. var
  1831.   MkFirst: IMoniker;
  1832.   BindCtx: IBindCtx;
  1833.   Mksys: Longint;
  1834.   P: PWideChar;
  1835. begin
  1836.   Result := 0;
  1837.   if Moniker <> nil then begin
  1838.     MkFirst := OleStdGetFirstMoniker(Moniker);
  1839.     if MkFirst <> nil then begin
  1840.       if (MkFirst.IsSystemMoniker(Mksys) = 0) and
  1841.         (Mksys = MKSYS_FILEMONIKER) then
  1842.       begin
  1843.         if CreateBindCtx(0, BindCtx) = 0 then begin
  1844.           if (MkFirst.GetDisplayName(BindCtx, nil, P) = 0) and (P <> nil) then
  1845.           begin
  1846.             Result := WStrLen(P);
  1847.             CoTaskMemFree(P);
  1848.           end;
  1849.           ReleaseObject(BindCtx);
  1850.         end;
  1851.       end;
  1852.       ReleaseObject(MkFirst);
  1853.     end;
  1854.   end;
  1855. end;
  1856. function CoAllocCStr(const S: string): PChar;
  1857. begin
  1858.   Result := StrCopy(CoTaskMemAlloc(Length(S) + 1), PChar(S));
  1859. end;
  1860. function WStrToString(P: PWideChar): string;
  1861. begin
  1862.   Result := '';
  1863.   if P <> nil then begin
  1864.     Result := WideCharToString(P);
  1865.     CoTaskMemFree(P);
  1866.   end;
  1867. end;
  1868. function GetFullNameStr(OleObject: IOleObject): string;
  1869. var
  1870.   P: PWideChar;
  1871. begin
  1872.   OleObject.GetUserType(USERCLASSTYPE_FULL, P);
  1873.   Result := WStrToString(P);
  1874. end;
  1875. function GetShortNameStr(OleObject: IOleObject): string;
  1876. var
  1877.   P: PWideChar;
  1878. begin
  1879.   OleObject.GetUserType(USERCLASSTYPE_SHORT, P);
  1880.   Result := WStrToString(P);
  1881. end;
  1882. function GetDisplayNameStr(OleLink: IOleLink): string;
  1883. var
  1884.   P: PWideChar;
  1885. begin
  1886.   OleLink.GetSourceDisplayName(P);
  1887.   Result := WStrToString(P);
  1888. end;
  1889. {$IFDEF RX_D3}
  1890. function GetVCLFrameForm(Form: TCustomForm): IVCLFrameForm;
  1891. begin
  1892.   if Form.OleFormObject = nil then TOleForm.Create(Form);
  1893.   Result := Form.OleFormObject as IVCLFrameForm;
  1894. end;
  1895. function IsFormMDIChild(Form: TCustomForm): Boolean;
  1896. begin
  1897.   Result := (Form is TForm) and (TForm(Form).FormStyle = fsMDIChild);
  1898. end;
  1899. {$ENDIF}
  1900. { Clipboard formats }
  1901. var
  1902.   CFEmbeddedObject: Integer;
  1903.   CFLinkSource: Integer;
  1904.   CFRtf: Integer;
  1905.   CFRtfNoObjs: Integer;
  1906. const
  1907. {$IFNDEF RX_D3}
  1908.   CF_RTFNOOBJS = 'Rich Text Format Without Objects';
  1909. {$ENDIF}
  1910.   CF_EMBEDDEDOBJECT = 'Embedded Object';
  1911.   CF_LINKSOURCE = 'Link Source';
  1912. {************************************************************************}
  1913. { OLE Extensions to the Rich Text Editor }
  1914. { Converted from RICHOLE.H               }
  1915. { Structure passed to GetObject and InsertObject }
  1916. type
  1917.   _ReObject = record
  1918.     cbStruct: DWORD;           { Size of structure                }
  1919.     cp: ULONG;                 { Character position of object     }
  1920.     clsid: TCLSID;             { Class ID of object               }
  1921.     poleobj: IOleObject;       { OLE object interface             }
  1922.     pstg: IStorage;            { Associated storage interface     }
  1923.     polesite: IOleClientSite;  { Associated client site interface }
  1924.     sizel: TSize;              { Size of object (may be 0,0)      }
  1925.     dvAspect: Longint;         { Display aspect to use            }
  1926.     dwFlags: DWORD;            { Object status flags              }
  1927.     dwUser: DWORD;             { Dword for user's use             }
  1928.   end;
  1929.   TReObject = _ReObject;
  1930. const
  1931. { Flags to specify which interfaces should be returned in the structure above }
  1932.   REO_GETOBJ_NO_INTERFACES   =  $00000000;
  1933.   REO_GETOBJ_POLEOBJ         =  $00000001;
  1934.   REO_GETOBJ_PSTG            =  $00000002;
  1935.   REO_GETOBJ_POLESITE        =  $00000004;
  1936.   REO_GETOBJ_ALL_INTERFACES  =  $00000007;
  1937. { Place object at selection }
  1938.   REO_CP_SELECTION    = ULONG(-1);
  1939. { Use character position to specify object instead of index }
  1940.   REO_IOB_SELECTION   = ULONG(-1);
  1941.   REO_IOB_USE_CP      = ULONG(-2);
  1942. { Object flags }
  1943.   REO_NULL            = $00000000;  { No flags                         }
  1944.   REO_READWRITEMASK   = $0000003F;  { Mask out RO bits                 }
  1945.   REO_DONTNEEDPALETTE = $00000020;  { Object doesn't need palette      }
  1946.   REO_BLANK           = $00000010;  { Object is blank                  }
  1947.   REO_DYNAMICSIZE     = $00000008;  { Object defines size always       }
  1948.   REO_INVERTEDSELECT  = $00000004;  { Object drawn all inverted if sel }
  1949.   REO_BELOWBASELINE   = $00000002;  { Object sits below the baseline   }
  1950.   REO_RESIZABLE       = $00000001;  { Object may be resized            }
  1951.   REO_LINK            = $80000000;  { Object is a link (RO)            }
  1952.   REO_STATIC          = $40000000;  { Object is static (RO)            }
  1953.   REO_SELECTED        = $08000000;  { Object selected (RO)             }
  1954.   REO_OPEN            = $04000000;  { Object open in its server (RO)   }
  1955.   REO_INPLACEACTIVE   = $02000000;  { Object in place active (RO)      }
  1956.   REO_HILITED         = $01000000;  { Object is to be hilited (RO)     }
  1957.   REO_LINKAVAILABLE   = $00800000;  { Link believed available (RO)     }
  1958.   REO_GETMETAFILE     = $00400000;  { Object requires metafile (RO)    }
  1959. { Flags for IRichEditOle.GetClipboardData,   }
  1960. { IRichEditOleCallback.GetClipboardData and  }
  1961. { IRichEditOleCallback.QueryAcceptData       }
  1962.   RECO_PASTE          = $00000000;  { paste from clipboard  }
  1963.   RECO_DROP           = $00000001;  { drop                  }
  1964.   RECO_COPY           = $00000002;  { copy to the clipboard }
  1965.   RECO_CUT            = $00000003;  { cut to the clipboard  }
  1966.   RECO_DRAG           = $00000004;  { drag                  }
  1967. { RichEdit GUIDs }
  1968.   IID_IRichEditOle: TGUID = (
  1969.     D1:$00020D00;D2:$0000;D3:$0000;D4:($C0,$00,$00,$00,$00,$00,$00,$46));
  1970.   IID_IRichEditOleCallback: TGUID = (
  1971.     D1:$00020D03;D2:$0000;D3:$0000;D4:($C0,$00,$00,$00,$00,$00,$00,$46));
  1972. type
  1973. {
  1974.  *  IRichEditOle
  1975.  *
  1976.  *  Purpose:
  1977.  *    Interface used by the client of RichEdit to perform OLE-related
  1978.  *    operations.
  1979.  *
  1980.  *    The methods herein may just want to be regular Windows messages.
  1981. }
  1982. {$IFDEF RX_D3}
  1983.   IRichEditOle = interface(IUnknown)
  1984.     ['{00020d00-0000-0000-c000-000000000046}']
  1985.     function GetClientSite(out clientSite: IOleClientSite): HResult; stdcall;
  1986.     function GetObjectCount: HResult; stdcall;
  1987.     function GetLinkCount: HResult; stdcall;
  1988.     function GetObject(iob: Longint; out reobject: TReObject;
  1989.       dwFlags: DWORD): HResult; stdcall;
  1990.     function InsertObject(var reobject: TReObject): HResult; stdcall;
  1991.     function ConvertObject(iob: Longint; rclsidNew: TIID;
  1992.       lpstrUserTypeNew: LPCSTR): HResult; stdcall;
  1993.     function ActivateAs(rclsid: TIID; rclsidAs: TIID): HResult; stdcall;
  1994.     function SetHostNames(lpstrContainerApp: LPCSTR;
  1995.       lpstrContainerObj: LPCSTR): HResult; stdcall;
  1996.     function SetLinkAvailable(iob: Longint; fAvailable: BOOL): HResult; stdcall;
  1997.     function SetDvaspect(iob: Longint; dvaspect: DWORD): HResult; stdcall;
  1998.     function HandsOffStorage(iob: Longint): HResult; stdcall;
  1999.     function SaveCompleted(iob: Longint; const stg: IStorage): HResult; stdcall;
  2000.     function InPlaceDeactivate: HResult; stdcall;
  2001.     function ContextSensitiveHelp(fEnterMode: BOOL): HResult; stdcall;
  2002.     function GetClipboardData(var chrg: TCharRange; reco: DWORD;
  2003.       out dataobj: IDataObject): HResult; stdcall;
  2004.     function ImportDataObject(dataobj: IDataObject; cf: TClipFormat;
  2005.       hMetaPict: HGLOBAL): HResult; stdcall;
  2006.   end;
  2007. {$ELSE}
  2008.   IRichEditOle = class(IUnknown)
  2009.     function GetClientSite(var clientSite: IOleClientSite): HResult; virtual; stdcall; abstract;
  2010.     function GetObjectCount: HResult; virtual; stdcall; abstract;
  2011.     function GetLinkCount: HResult; virtual; stdcall; abstract;
  2012.     function GetObject(iob: Longint; var reobject: TReObject;
  2013.       dwFlags: DWORD): HResult; virtual; stdcall; abstract;
  2014.     function InsertObject(var reobject: TReObject): HResult; virtual; stdcall; abstract;
  2015.     function ConvertObject(iob: Longint; rclsidNew: TIID;
  2016.       lpstrUserTypeNew: LPCSTR): HResult; virtual; stdcall; abstract;
  2017.     function ActivateAs(rclsid: TIID; rclsidAs: TIID): HResult; virtual; stdcall; abstract;
  2018.     function SetHostNames(lpstrContainerApp: LPCSTR;
  2019.       lpstrContainerObj: LPCSTR): HResult; virtual; stdcall; abstract;
  2020.     function SetLinkAvailable(iob: Longint; fAvailable: BOOL): HResult; virtual; stdcall; abstract;
  2021.     function SetDvaspect(iob: Longint; dvaspect: DWORD): HResult; virtual; stdcall; abstract;
  2022.     function HandsOffStorage(iob: Longint): HResult; virtual; stdcall; abstract;
  2023.     function SaveCompleted(iob: Longint; const stg: IStorage): HResult; virtual; stdcall; abstract;
  2024.     function InPlaceDeactivate: HResult; virtual; stdcall; abstract;
  2025.     function ContextSensitiveHelp(fEnterMode: BOOL): HResult; virtual; stdcall; abstract;
  2026.     function GetClipboardData(var chrg: TCharRange; reco: DWORD;
  2027.       var dataobj: IDataObject): HResult; virtual; stdcall; abstract;
  2028.     function ImportDataObject(dataobj: IDataObject; cf: TClipFormat;
  2029.       hMetaPict: HGLOBAL): HResult; virtual; stdcall; abstract;
  2030.   end;
  2031. {$ENDIF}
  2032. {
  2033.  *  IRichEditOleCallback
  2034.  *
  2035.  *  Purpose:
  2036.  *    Interface used by the RichEdit to get OLE-related stuff from the
  2037.  *    application using RichEdit.
  2038. }
  2039. {$IFDEF RX_D3}
  2040.   IRichEditOleCallback = interface(IUnknown)
  2041.     ['{00020d03-0000-0000-c000-000000000046}']
  2042.     function GetNewStorage(out stg: IStorage): HResult; stdcall;
  2043.     function GetInPlaceContext(out Frame: IOleInPlaceFrame;
  2044.       out Doc: IOleInPlaceUIWindow;
  2045.       lpFrameInfo: POleInPlaceFrameInfo): HResult; stdcall;
  2046.     function ShowContainerUI(fShow: BOOL): HResult; stdcall;
  2047.     function QueryInsertObject(const clsid: TCLSID; const stg: IStorage;
  2048.       cp: Longint): HResult; stdcall;
  2049.     function DeleteObject(const oleobj: IOleObject): HResult; stdcall;
  2050.     function QueryAcceptData(const dataobj: IDataObject;
  2051.       var cfFormat: TClipFormat; reco: DWORD; fReally: BOOL;
  2052.       hMetaPict: HGLOBAL): HResult; stdcall;
  2053.     function ContextSensitiveHelp(fEnterMode: BOOL): HResult; stdcall;
  2054.     function GetClipboardData(const chrg: TCharRange; reco: DWORD;
  2055.       out dataobj: IDataObject): HResult; stdcall;
  2056.     function GetDragDropEffect(fDrag: BOOL; grfKeyState: DWORD;
  2057.       var dwEffect: DWORD): HResult; stdcall;
  2058.     function GetContextMenu(seltype: Word; const oleobj: IOleObject;
  2059.       const chrg: TCharRange; out menu: HMENU): HResult; stdcall;
  2060.   end;
  2061. {$ELSE}
  2062.   IRichEditOleCallback = class(IUnknown)
  2063.     function GetNewStorage(var stg: IStorage): HResult; virtual; stdcall; abstract;
  2064.     function GetInPlaceContext(var Frame: IOleInPlaceFrame;
  2065.       var Doc: IOleInPlaceUIWindow;
  2066.       lpFrameInfo: POleInPlaceFrameInfo): HResult; virtual; stdcall; abstract;
  2067.     function ShowContainerUI(fShow: BOOL): HResult; virtual; stdcall; abstract;
  2068.     function QueryInsertObject(const clsid: TCLSID; const stg: IStorage;
  2069.       cp: Longint): HResult; virtual; stdcall; abstract;
  2070.     function DeleteObject(const oleobj: IOleObject): HResult; virtual; stdcall; abstract;
  2071.     function QueryAcceptData(const dataobj: IDataObject;
  2072.       var cfFormat: TClipFormat; reco: DWORD; fReally: BOOL;
  2073.       hMetaPict: HGLOBAL): HResult; virtual; stdcall; abstract;
  2074.     function ContextSensitiveHelp(fEnterMode: BOOL): HResult; virtual; stdcall; abstract;
  2075.     function GetClipboardData(const chrg: TCharRange; reco: DWORD;
  2076.       var dataobj: IDataObject): HResult; virtual; stdcall; abstract;
  2077.     function GetDragDropEffect(fDrag: BOOL; grfKeyState: DWORD;
  2078.       var dwEffect: DWORD): HResult; virtual; stdcall; abstract;
  2079.     function GetContextMenu(seltype: Word; const oleobj: IOleObject;
  2080.       const chrg: TCharRange; var menu: HMENU): HResult; virtual; stdcall; abstract;
  2081.   end;
  2082. {$ENDIF}
  2083. {************************************************************************}
  2084. { TRichEditOleCallback }
  2085. type
  2086. {$IFDEF RX_D3}
  2087.   TRichEditOleCallback = class(TObject, IUnknown, IRichEditOleCallback)
  2088.   private
  2089.     FDocForm: IVCLFrameForm;
  2090.     FFrameForm: IVCLFrameForm;
  2091.     FAccelTable: HAccel;
  2092.     FAccelCount: Integer;
  2093. {$IFDEF RX_D4}
  2094.     FAutoScroll: Boolean;
  2095. {$ENDIF}
  2096.     procedure CreateAccelTable;
  2097.     procedure DestroyAccelTable;
  2098.     procedure AssignFrame;
  2099. {$ELSE}
  2100.   TRichEditOleCallback = class(IRichEditOleCallback)
  2101. {$ENDIF}
  2102.   private
  2103.     FRefCount: Longint;
  2104.     FRichEdit: TRxCustomRichEdit;
  2105.   public
  2106.     constructor Create(RichEdit: TRxCustomRichEdit);
  2107.     destructor Destroy; override;
  2108. {$IFDEF RX_D3}
  2109.     function QueryInterface(const iid: TGUID; out Obj): HResult; stdcall;
  2110.     function _AddRef: Longint; stdcall;
  2111.     function _Release: Longint; stdcall;
  2112.     function GetNewStorage(out stg: IStorage): HResult; stdcall;
  2113.     function GetInPlaceContext(out Frame: IOleInPlaceFrame;
  2114.       out Doc: IOleInPlaceUIWindow;
  2115.       lpFrameInfo: POleInPlaceFrameInfo): HResult; stdcall;
  2116.     function GetClipboardData(const chrg: TCharRange; reco: DWORD;
  2117.       out dataobj: IDataObject): HResult; stdcall;
  2118.     function GetContextMenu(seltype: Word; const oleobj: IOleObject;
  2119.       const chrg: TCharRange; out menu: HMENU): HResult; stdcall;
  2120. {$ELSE}
  2121.     function QueryInterface(const iid: TIID; var Obj): HResult; override;
  2122.     function AddRef: Longint; override;
  2123.     function Release: Longint; override;
  2124.     function GetNewStorage(var stg: IStorage): HResult; override;
  2125.     function GetInPlaceContext(var Frame: IOleInPlaceFrame;
  2126.       var Doc: IOleInPlaceUIWindow;
  2127.       lpFrameInfo: POleInPlaceFrameInfo): HResult; override;
  2128.     function GetClipboardData(const chrg: TCharRange; reco: DWORD;
  2129.       var dataobj: IDataObject): HResult; override;
  2130.     function GetContextMenu(seltype: Word; const oleobj: IOleObject;
  2131.       const chrg: TCharRange; var menu: HMENU): HResult; override;
  2132. {$ENDIF}
  2133.     function ShowContainerUI(fShow: BOOL): HResult;
  2134.       {$IFDEF RX_D3} stdcall {$ELSE} override {$ENDIF};
  2135.     function QueryInsertObject(const clsid: TCLSID; const stg: IStorage;
  2136.       cp: Longint): HResult;
  2137.       {$IFDEF RX_D3} stdcall {$ELSE} override {$ENDIF};
  2138.     function DeleteObject(const oleobj: IOleObject): HResult;
  2139.       {$IFDEF RX_D3} stdcall {$ELSE} override {$ENDIF};
  2140.     function QueryAcceptData(const dataobj: IDataObject; var cfFormat: TClipFormat;
  2141.       reco: DWORD; fReally: BOOL; hMetaPict: HGLOBAL): HResult;
  2142.       {$IFDEF RX_D3} stdcall {$ELSE} override {$ENDIF};
  2143.     function ContextSensitiveHelp(fEnterMode: BOOL): HResult;
  2144.       {$IFDEF RX_D3} stdcall {$ELSE} override {$ENDIF};
  2145.     function GetDragDropEffect(fDrag: BOOL; grfKeyState: DWORD;
  2146.       var dwEffect: DWORD): HResult;
  2147.       {$IFDEF RX_D3} stdcall {$ELSE} override {$ENDIF};
  2148.   end;
  2149. constructor TRichEditOleCallback.Create(RichEdit: TRxCustomRichEdit);
  2150. begin
  2151.   inherited Create;
  2152.   FRichEdit := RichEdit;
  2153. end;
  2154. destructor TRichEditOleCallback.Destroy;
  2155. begin
  2156. {$IFDEF RX_D3}
  2157.   DestroyAccelTable;
  2158.   FFrameForm := nil;
  2159.   FDocForm := nil;
  2160. {$ENDIF}
  2161.   inherited Destroy;
  2162. end;
  2163. {$IFDEF RX_D3}
  2164. function TRichEditOleCallback.QueryInterface(const iid: TGUID; out Obj): HResult;
  2165. begin
  2166.   if GetInterface(iid, Obj) then Result := S_OK
  2167.   else Result := E_NOINTERFACE;
  2168. end;
  2169. function TRichEditOleCallback._AddRef: Longint;
  2170. begin
  2171.   Inc(FRefCount);
  2172.   Result := FRefCount;
  2173. end;
  2174. function TRichEditOleCallback._Release: Longint;
  2175. begin
  2176.   Dec(FRefCount);
  2177.   Result := FRefCount;
  2178. end;
  2179. procedure TRichEditOleCallback.CreateAccelTable;
  2180. var
  2181.   Menu: TMainMenu;
  2182. begin
  2183.   if (FAccelTable = 0) and Assigned(FFrameForm) then begin
  2184.     Menu := FFrameForm.Form.Menu;
  2185.     if Menu <> nil then
  2186.       Menu.GetOle2AcceleratorTable(FAccelTable, FAccelCount, [0, 2, 4]);
  2187.   end;
  2188. end;
  2189. procedure TRichEditOleCallback.DestroyAccelTable;
  2190. begin
  2191.   if FAccelTable <> 0 then begin
  2192.     DestroyAcceleratorTable(FAccelTable);
  2193.     FAccelTable := 0;
  2194.     FAccelCount := 0;
  2195.   end;
  2196. end;
  2197. procedure TRichEditOleCallback.AssignFrame;
  2198. begin
  2199.   if (GetParentForm(FRichEdit) <> nil) and not Assigned(FFrameForm) and
  2200.     FRichEdit.AllowInPlace then
  2201.   begin
  2202.     FDocForm := GetVCLFrameForm(ValidParentForm(FRichEdit));
  2203.     FFrameForm := FDocForm;
  2204.     if IsFormMDIChild(FDocForm.Form) then
  2205.       FFrameForm := GetVCLFrameForm(Application.MainForm);
  2206.   end;
  2207. end;
  2208. {$ELSE}
  2209. function TRichEditOleCallback.QueryInterface(const iid: TIID; var Obj): HResult;
  2210. begin
  2211.   if IsEqualIID(iid, IID_IUnknown) or
  2212.     IsEqualIID(iid, IID_IRichEditOleCallback) then
  2213.   begin
  2214.     Pointer(Obj) := Self;
  2215.     AddRef;
  2216.     Result := S_OK;
  2217.   end else begin
  2218.     Pointer(Obj) := nil;
  2219.     Result := E_NOINTERFACE;
  2220.   end;
  2221. end;
  2222. function TRichEditOleCallback.AddRef: Longint;
  2223. begin
  2224.   Inc(FRefCount);
  2225.   Result := FRefCount;
  2226. end;
  2227. function TRichEditOleCallback.Release: Longint;
  2228. begin
  2229.   Dec(FRefCount);
  2230.   Result := FRefCount;
  2231. end;
  2232. {$ENDIF RX_D3}
  2233. function TRichEditOleCallback.GetNewStorage(
  2234.   {$IFDEF RX_D3} out {$ELSE} var {$ENDIF} stg: IStorage): HResult;
  2235. begin
  2236.   try
  2237.     CreateStorage(stg);
  2238.     Result := S_OK;
  2239.   except
  2240.     Result:= E_OUTOFMEMORY;
  2241.   end;
  2242. end;
  2243. function TRichEditOleCallback.GetInPlaceContext(
  2244.   {$IFDEF RX_D3} out {$ELSE} var {$ENDIF} Frame: IOleInPlaceFrame;
  2245.   {$IFDEF RX_D3} out {$ELSE} var {$ENDIF} Doc: IOleInPlaceUIWindow;
  2246.   lpFrameInfo: POleInPlaceFrameInfo): HResult;
  2247. begin
  2248. {$IFDEF RX_D3}
  2249.   AssignFrame;
  2250.   if Assigned(FFrameForm) and FRichEdit.AllowInPlace then begin