| 1 | { **************************************************************
 | 
|---|
| 2 |         Package: XWB - Kernel RPCBroker
 | 
|---|
| 3 |         Date Created: Sept 18, 1997 (Version 1.1)
 | 
|---|
| 4 |         Site Name: Oakland, OI Field Office, Dept of Veteran Affairs
 | 
|---|
| 5 |         Developers: Joel Ivey
 | 
|---|
| 6 |         Description: Provides a RichEdit Component with ability
 | 
|---|
| 7 |                      to recognize a URL within the RichEdit control.
 | 
|---|
| 8 |         Current Release: Version 1.1 Patch 40 (January 7, 2005))
 | 
|---|
| 9 | *************************************************************** }
 | 
|---|
| 10 | {: Unit XWBRich20
 | 
|---|
| 11 |    Based on the article "Detect URLS in the RichEdit Control" by
 | 
|---|
| 12 |    Elias J. Ongpoy in 'Delphi Developer Newsletter', May 2001
 | 
|---|
| 13 |    which incorporates the functionality of the Microsoft Rich Edit
 | 
|---|
| 14 |    Control 2.0 from RichEd20.DLL which incorporates the ability to
 | 
|---|
| 15 |    recognize a URL within the RichEdit control.
 | 
|---|
| 16 | }
 | 
|---|
| 17 | 
 | 
|---|
| 18 | unit XWBRich20;
 | 
|---|
| 19 | interface
 | 
|---|
| 20 | uses Messages, Windows, SysUtils, Classes, Controls, Forms,
 | 
|---|
| 21 |   Menus, Graphics, StdCtrls, RichEdit, ToolWin, ImgList, ExtCtrls, ComCtrls;
 | 
|---|
| 22 | 
 | 
|---|
| 23 | type
 | 
|---|
| 24 |   TXWBCustomRichEdit = class;
 | 
|---|
| 25 | 
 | 
|---|
| 26 |   TAttributeType = (atSelected, atDefaultText);
 | 
|---|
| 27 |   TConsistentAttribute = (caBold, caColor, caFace, caItalic,
 | 
|---|
| 28 |     caSize, caStrikeOut, caUnderline, caProtected);
 | 
|---|
| 29 |   TConsistentAttributes = set of TConsistentAttribute;
 | 
|---|
| 30 | 
 | 
|---|
| 31 |   TXWBTextAttributes = class(TPersistent)
 | 
|---|
| 32 |   private
 | 
|---|
| 33 |     RichEdit: TXWBCustomRichEdit;
 | 
|---|
| 34 |     FType: TAttributeType;
 | 
|---|
| 35 |     procedure GetAttributes(var Format: TCharFormat);
 | 
|---|
| 36 |     function GetCharset: TFontCharset;
 | 
|---|
| 37 |     function GetColor: TColor;
 | 
|---|
| 38 |     function GetConsistentAttributes: TConsistentAttributes;
 | 
|---|
| 39 |     function GetHeight: Integer;
 | 
|---|
| 40 |     function GetName: TFontName;
 | 
|---|
| 41 |     function GetPitch: TFontPitch;
 | 
|---|
| 42 |     function GetProtected: Boolean;
 | 
|---|
| 43 |     function GetSize: Integer;
 | 
|---|
| 44 |     function GetStyle: TFontStyles;
 | 
|---|
| 45 |     procedure SetAttributes(var Format: TCharFormat);
 | 
|---|
| 46 |     procedure SetCharset(Value: TFontCharset);
 | 
|---|
| 47 |     procedure SetColor(Value: TColor);
 | 
|---|
| 48 |     procedure SetHeight(Value: Integer);
 | 
|---|
| 49 |     procedure SetName(Value: TFontName);
 | 
|---|
| 50 |     procedure SetPitch(Value: TFontPitch);
 | 
|---|
| 51 |     procedure SetProtected(Value: Boolean);
 | 
|---|
| 52 |     procedure SetSize(Value: Integer);
 | 
|---|
| 53 |     procedure SetStyle(Value: TFontStyles);
 | 
|---|
| 54 |   protected
 | 
|---|
| 55 |     procedure InitFormat(var Format: TCharFormat);
 | 
|---|
| 56 |     procedure AssignTo(Dest: TPersistent); override;
 | 
|---|
| 57 |   public
 | 
|---|
| 58 |     constructor Create(AOwner: TXWBCustomRichEdit; AttributeType: TAttributeType);
 | 
|---|
| 59 |     procedure Assign(Source: TPersistent); override;
 | 
|---|
| 60 |     property Charset: TFontCharset read GetCharset write SetCharset;
 | 
|---|
| 61 |     property Color: TColor read GetColor write SetColor;
 | 
|---|
| 62 |     property ConsistentAttributes: TConsistentAttributes read GetConsistentAttributes;
 | 
|---|
| 63 |     property Name: TFontName read GetName write SetName;
 | 
|---|
| 64 |     property Pitch: TFontPitch read GetPitch write SetPitch;
 | 
|---|
| 65 |     property Protected: Boolean read GetProtected write SetProtected;
 | 
|---|
| 66 |     property Size: Integer read GetSize write SetSize;
 | 
|---|
| 67 |     property Style: TFontStyles read GetStyle write SetStyle;
 | 
|---|
| 68 |     property Height: Integer read GetHeight write SetHeight;
 | 
|---|
| 69 |   end;
 | 
|---|
| 70 | 
 | 
|---|
| 71 | { TParaAttributes }
 | 
|---|
| 72 | 
 | 
|---|
| 73 |   TNumberingStyle = (nsNone, nsBullet);
 | 
|---|
| 74 | 
 | 
|---|
| 75 |   TParaAttributes = class(TPersistent)
 | 
|---|
| 76 |   private
 | 
|---|
| 77 |     RichEdit: TXWBCustomRichEdit;
 | 
|---|
| 78 |     procedure GetAttributes(var Paragraph: TParaFormat);
 | 
|---|
| 79 |     function GetAlignment: TAlignment;
 | 
|---|
| 80 |     function GetFirstIndent: Longint;
 | 
|---|
| 81 |     function GetLeftIndent: Longint;
 | 
|---|
| 82 |     function GetRightIndent: Longint;
 | 
|---|
| 83 |     function GetNumbering: TNumberingStyle;
 | 
|---|
| 84 |     function GetTab(Index: Byte): Longint;
 | 
|---|
| 85 |     function GetTabCount: Integer;
 | 
|---|
| 86 |     procedure InitPara(var Paragraph: TParaFormat);
 | 
|---|
| 87 |     procedure SetAlignment(Value: TAlignment);
 | 
|---|
| 88 |     procedure SetAttributes(var Paragraph: TParaFormat);
 | 
|---|
| 89 |     procedure SetFirstIndent(Value: Longint);
 | 
|---|
| 90 |     procedure SetLeftIndent(Value: Longint);
 | 
|---|
| 91 |     procedure SetRightIndent(Value: Longint);
 | 
|---|
| 92 |     procedure SetNumbering(Value: TNumberingStyle);
 | 
|---|
| 93 |     procedure SetTab(Index: Byte; Value: Longint);
 | 
|---|
| 94 |     procedure SetTabCount(Value: Integer);
 | 
|---|
| 95 |   public
 | 
|---|
| 96 |     constructor Create(AOwner: TXWBCustomRichEdit);
 | 
|---|
| 97 |     procedure Assign(Source: TPersistent); override;
 | 
|---|
| 98 |     property Alignment: TAlignment read GetAlignment write SetAlignment;
 | 
|---|
| 99 |     property FirstIndent: Longint read GetFirstIndent write SetFirstIndent;
 | 
|---|
| 100 |     property LeftIndent: Longint read GetLeftIndent write SetLeftIndent;
 | 
|---|
| 101 |     property Numbering: TNumberingStyle read GetNumbering write SetNumbering;
 | 
|---|
| 102 |     property RightIndent: Longint read GetRightIndent write SetRightIndent;
 | 
|---|
| 103 |     property Tab[Index: Byte]: Longint read GetTab write SetTab;
 | 
|---|
| 104 |     property TabCount: Integer read GetTabCount write SetTabCount;
 | 
|---|
| 105 |   end;
 | 
|---|
| 106 | 
 | 
|---|
| 107 | { TXWBCustomRichEdit }
 | 
|---|
| 108 | 
 | 
|---|
| 109 |   TRichEditResizeEvent = procedure(Sender: TObject; Rect: TRect) of object;
 | 
|---|
| 110 |   TRichEditProtectChange = procedure(Sender: TObject;
 | 
|---|
| 111 |     StartPos, EndPos: Integer; var AllowChange: Boolean) of object;
 | 
|---|
| 112 |   TRichEditSaveClipboard = procedure(Sender: TObject;
 | 
|---|
| 113 |     NumObjects, NumChars: Integer; var SaveClipboard: Boolean) of object;
 | 
|---|
| 114 |   TSearchType = (stWholeWord, stMatchCase);
 | 
|---|
| 115 |   TSearchTypes = set of TSearchType;
 | 
|---|
| 116 | 
 | 
|---|
| 117 |   TConversion = class(TObject)
 | 
|---|
| 118 |   public
 | 
|---|
| 119 |     function ConvertReadStream(Stream: TStream; Buffer: PChar; BufSize: Integer): Integer; virtual;
 | 
|---|
| 120 |     function ConvertWriteStream(Stream: TStream; Buffer: PChar; BufSize: Integer): Integer; virtual;
 | 
|---|
| 121 |   end;
 | 
|---|
| 122 | 
 | 
|---|
| 123 |   TConversionClass = class of TConversion;
 | 
|---|
| 124 | 
 | 
|---|
| 125 |   PConversionFormat = ^TConversionFormat;
 | 
|---|
| 126 |   TConversionFormat = record
 | 
|---|
| 127 |     ConversionClass: TConversionClass;
 | 
|---|
| 128 |     Extension: string;
 | 
|---|
| 129 |     Next: PConversionFormat;
 | 
|---|
| 130 |   end;
 | 
|---|
| 131 | 
 | 
|---|
| 132 |   PRichEditStreamInfo = ^TRichEditStreamInfo;
 | 
|---|
| 133 |   TRichEditStreamInfo = record
 | 
|---|
| 134 |     Converter: TConversion;
 | 
|---|
| 135 |     Stream: TStream;
 | 
|---|
| 136 |   end;
 | 
|---|
| 137 | 
 | 
|---|
| 138 |   TXWBCustomRichEdit = class(TCustomMemo)
 | 
|---|
| 139 |   private
 | 
|---|
| 140 |     FHideScrollBars: Boolean;
 | 
|---|
| 141 |     FSelAttributes: TXWBTextAttributes;
 | 
|---|
| 142 |     FDefAttributes: TXWBTextAttributes;
 | 
|---|
| 143 |     FParagraph: TParaAttributes;
 | 
|---|
| 144 |     FOldParaAlignment: TAlignment;
 | 
|---|
| 145 |     FScreenLogPixels: Integer;
 | 
|---|
| 146 |     FRichEditStrings: TStrings;
 | 
|---|
| 147 |     FMemStream: TMemoryStream;
 | 
|---|
| 148 |     FOnSelChange: TNotifyEvent;
 | 
|---|
| 149 | 
 | 
|---|
| 150 |     FHideSelection: Boolean;
 | 
|---|
| 151 |     FURLDetect: Boolean;      // for URL Detect Property
 | 
|---|
| 152 | 
 | 
|---|
| 153 |     FModified: Boolean;
 | 
|---|
| 154 |     FDefaultConverter: TConversionClass;
 | 
|---|
| 155 |     FOnResizeRequest: TRichEditResizeEvent;
 | 
|---|
| 156 |     FOnProtectChange: TRichEditProtectChange;
 | 
|---|
| 157 |     FOnSaveClipboard: TRichEditSaveClipboard;
 | 
|---|
| 158 |     FPageRect: TRect;
 | 
|---|
| 159 | 
 | 
|---|
| 160 |     procedure CMBiDiModeChanged(var Message: TMessage); message CM_BIDIMODECHANGED;
 | 
|---|
| 161 |     procedure CMColorChanged(var Message: TMessage); message CM_COLORCHANGED;
 | 
|---|
| 162 |     procedure CMFontChanged(var Message: TMessage); message CM_FONTCHANGED;
 | 
|---|
| 163 |     procedure CNNotify(var Message: TWMNotify); message CN_NOTIFY;
 | 
|---|
| 164 |     function GetPlainText: Boolean;
 | 
|---|
| 165 |     function ProtectChange(StartPos, EndPos: Integer): Boolean;
 | 
|---|
| 166 |     function SaveClipboard(NumObj, NumChars: Integer): Boolean;
 | 
|---|
| 167 |     procedure SetHideScrollBars(Value: Boolean);
 | 
|---|
| 168 |     procedure SetHideSelection(Value: Boolean);
 | 
|---|
| 169 |     procedure SetURLDetect(Value: boolean);
 | 
|---|
| 170 |     
 | 
|---|
| 171 |     procedure SetPlainText(Value: Boolean);
 | 
|---|
| 172 |     procedure SetRichEditStrings(Value: TStrings);
 | 
|---|
| 173 |     procedure SetDefAttributes(Value: TXWBTextAttributes);
 | 
|---|
| 174 |     procedure SetSelAttributes(Value: TXWBTextAttributes);
 | 
|---|
| 175 |     procedure WMNCDestroy(var Message: TWMNCDestroy); message WM_NCDESTROY;
 | 
|---|
| 176 |     procedure WMSetCursor(var Message: TWMSetCursor); message WM_SETCURSOR;
 | 
|---|
| 177 |     procedure WMPaint(var Message: TWMPaint); message WM_PAINT;
 | 
|---|
| 178 |     procedure WMSetFont(var Message: TWMSetFont); message WM_SETFONT;
 | 
|---|
| 179 |     procedure WMRButtonUp(var Message: TWMRButtonUp); message WM_RBUTTONUP;
 | 
|---|
| 180 | 
 | 
|---|
| 181 |   protected
 | 
|---|
| 182 |     procedure CreateParams(var Params: TCreateParams); override;
 | 
|---|
| 183 |     procedure CreateWnd; override;
 | 
|---|
| 184 |     procedure DestroyWnd; override;
 | 
|---|
| 185 |     procedure RequestSize(const Rect: TRect); virtual;
 | 
|---|
| 186 |     procedure SelectionChange; dynamic;
 | 
|---|
| 187 |     procedure DoSetMaxLength(Value: Integer); override;
 | 
|---|
| 188 |     function GetCaretPos: TPoint; override;
 | 
|---|
| 189 |     function GetSelLength: Integer; override;
 | 
|---|
| 190 |     function GetSelStart: Integer; override;
 | 
|---|
| 191 |     function GetSelText: string; override;
 | 
|---|
| 192 |     procedure SetSelLength(Value: Integer); override;
 | 
|---|
| 193 |     procedure SetSelStart(Value: Integer); override;
 | 
|---|
| 194 |     property HideSelection: Boolean read FHideSelection write SetHideSelection default True;
 | 
|---|
| 195 |     
 | 
|---|
| 196 | // New Property - URL Detect
 | 
|---|
| 197 |     property URLDetect : boolean read FURLDetect write SetURLDetect default FALSE;
 | 
|---|
| 198 | 
 | 
|---|
| 199 |     property HideScrollBars: Boolean read FHideScrollBars
 | 
|---|
| 200 |       write SetHideScrollBars default True;
 | 
|---|
| 201 |     property Lines: TStrings read FRichEditStrings write SetRichEditStrings;
 | 
|---|
| 202 |     property OnSaveClipboard: TRichEditSaveClipboard read FOnSaveClipboard
 | 
|---|
| 203 |       write FOnSaveClipboard;
 | 
|---|
| 204 |     property OnSelectionChange: TNotifyEvent read FOnSelChange write FOnSelChange;
 | 
|---|
| 205 |     property OnProtectChange: TRichEditProtectChange read FOnProtectChange
 | 
|---|
| 206 |       write FOnProtectChange;
 | 
|---|
| 207 |     property OnResizeRequest: TRichEditResizeEvent read FOnResizeRequest
 | 
|---|
| 208 |       write FOnResizeRequest;
 | 
|---|
| 209 |     property PlainText: Boolean read GetPlainText write SetPlainText default False;
 | 
|---|
| 210 | 
 | 
|---|
| 211 |   public
 | 
|---|
| 212 |     constructor Create(AOwner: TComponent); override;
 | 
|---|
| 213 |     destructor Destroy; override;
 | 
|---|
| 214 |     procedure Clear; override;
 | 
|---|
| 215 |     function FindText(const SearchStr: string;
 | 
|---|
| 216 |       StartPos, Length: Integer; Options: TSearchTypes): Integer;
 | 
|---|
| 217 |     function GetSelTextBuf(Buffer: PChar; BufSize: Integer): Integer; override;
 | 
|---|
| 218 |     procedure Print(const Caption: string); virtual;
 | 
|---|
| 219 |     class procedure RegisterConversionFormat(const AExtension: string;
 | 
|---|
| 220 |       AConversionClass: TConversionClass);
 | 
|---|
| 221 |     property DefaultConverter: TConversionClass
 | 
|---|
| 222 |       read FDefaultConverter write FDefaultConverter;
 | 
|---|
| 223 |     property DefAttributes: TXWBTextAttributes read FDefAttributes write SetDefAttributes;
 | 
|---|
| 224 |     property SelAttributes: TXWBTextAttributes read FSelAttributes write SetSelAttributes;
 | 
|---|
| 225 |     property PageRect: TRect read FPageRect write FPageRect;
 | 
|---|
| 226 |     property Paragraph: TParaAttributes read FParagraph;
 | 
|---|
| 227 |   end;
 | 
|---|
| 228 | 
 | 
|---|
| 229 |   TXWBRichEdit = class(TXWBCustomRichEdit)
 | 
|---|
| 230 |   published
 | 
|---|
| 231 |     property Align;
 | 
|---|
| 232 |     property Alignment;
 | 
|---|
| 233 |     property Anchors;
 | 
|---|
| 234 |     property BiDiMode;
 | 
|---|
| 235 |     property BorderStyle;
 | 
|---|
| 236 |     property BorderWidth;
 | 
|---|
| 237 |     property Color;
 | 
|---|
| 238 |     property Ctl3D;
 | 
|---|
| 239 |     property DragCursor;
 | 
|---|
| 240 |     property DragKind;
 | 
|---|
| 241 |     property DragMode;
 | 
|---|
| 242 |     property Enabled;
 | 
|---|
| 243 |     property Font;
 | 
|---|
| 244 |     property HideSelection;
 | 
|---|
| 245 |     property URLDetect;            // New URL Detect property
 | 
|---|
| 246 |     property HideScrollBars;
 | 
|---|
| 247 |     property ImeMode;
 | 
|---|
| 248 |     property ImeName;
 | 
|---|
| 249 |     property Constraints;
 | 
|---|
| 250 |     property Lines;
 | 
|---|
| 251 |     property MaxLength;
 | 
|---|
| 252 |     property ParentBiDiMode;
 | 
|---|
| 253 |     property ParentColor;
 | 
|---|
| 254 |     property ParentCtl3D;
 | 
|---|
| 255 |     property ParentFont;
 | 
|---|
| 256 |     property ParentShowHint;
 | 
|---|
| 257 |     property PlainText;
 | 
|---|
| 258 |     property PopupMenu;
 | 
|---|
| 259 |     property ReadOnly;
 | 
|---|
| 260 |     property ScrollBars;
 | 
|---|
| 261 |     property ShowHint;
 | 
|---|
| 262 |     property TabOrder;
 | 
|---|
| 263 |     property TabStop default True;
 | 
|---|
| 264 | 
 | 
|---|
| 265 |     property Visible;
 | 
|---|
| 266 |     property WantTabs;
 | 
|---|
| 267 |     property WantReturns;
 | 
|---|
| 268 |     property WordWrap;
 | 
|---|
| 269 |     property OnChange;
 | 
|---|
| 270 | //    property OnContextPopup;
 | 
|---|
| 271 |     property OnDragDrop;
 | 
|---|
| 272 |     property OnDragOver;
 | 
|---|
| 273 |     property OnEndDock;
 | 
|---|
| 274 |     property OnEndDrag;
 | 
|---|
| 275 |     property OnEnter;
 | 
|---|
| 276 |     property OnExit;
 | 
|---|
| 277 |     property OnKeyDown;
 | 
|---|
| 278 |     property OnKeyPress;
 | 
|---|
| 279 |     property OnKeyUp;
 | 
|---|
| 280 |     property OnMouseDown;
 | 
|---|
| 281 |     property OnMouseMove;
 | 
|---|
| 282 |     property OnMouseUp;
 | 
|---|
| 283 |     property OnMouseWheel;
 | 
|---|
| 284 |     property OnMouseWheelDown;
 | 
|---|
| 285 |     property OnMouseWheelUp;
 | 
|---|
| 286 |     property OnProtectChange;
 | 
|---|
| 287 |     property OnResizeRequest;
 | 
|---|
| 288 |     property OnSaveClipboard;
 | 
|---|
| 289 |     property OnSelectionChange;
 | 
|---|
| 290 |     property OnStartDock;
 | 
|---|
| 291 |     property OnStartDrag;
 | 
|---|
| 292 |   end;
 | 
|---|
| 293 | 
 | 
|---|
| 294 | implementation
 | 
|---|
| 295 | 
 | 
|---|
| 296 | uses Printers, Consts, ComStrs, ActnList, StdActns, ShellAPI;
 | 
|---|
| 297 | 
 | 
|---|
| 298 | type
 | 
|---|
| 299 |   PFontHandles = ^TFontHandles;
 | 
|---|
| 300 |   TFontHandles = record
 | 
|---|
| 301 |     OurFont,
 | 
|---|
| 302 |     StockFont: Integer;
 | 
|---|
| 303 |   end;
 | 
|---|
| 304 | 
 | 
|---|
| 305 |   const
 | 
|---|
| 306 |   SectionSizeArea = 8;
 | 
|---|
| 307 |   RTFConversionFormat: TConversionFormat = (
 | 
|---|
| 308 |     ConversionClass: TConversion;
 | 
|---|
| 309 |     Extension: 'rtf';
 | 
|---|
| 310 |     Next: nil);
 | 
|---|
| 311 |   TextConversionFormat: TConversionFormat = (
 | 
|---|
| 312 |     ConversionClass: TConversion;
 | 
|---|
| 313 |     Extension: 'txt';
 | 
|---|
| 314 |     Next: @RTFConversionFormat);
 | 
|---|
| 315 | 
 | 
|---|
| 316 | var
 | 
|---|
| 317 |   ConversionFormatList: PConversionFormat = @TextConversionFormat;
 | 
|---|
| 318 |   FRichEditModule: THandle;
 | 
|---|
| 319 | 
 | 
|---|
| 320 | { TXWBTextAttributes }
 | 
|---|
| 321 | 
 | 
|---|
| 322 | constructor TXWBTextAttributes.Create(AOwner: TXWBCustomRichEdit;
 | 
|---|
| 323 |   AttributeType: TAttributeType);
 | 
|---|
| 324 | begin
 | 
|---|
| 325 |   inherited Create;
 | 
|---|
| 326 |   RichEdit := AOwner;
 | 
|---|
| 327 |   FType := AttributeType;
 | 
|---|
| 328 | end;
 | 
|---|
| 329 | 
 | 
|---|
| 330 | procedure TXWBTextAttributes.InitFormat(var Format: TCharFormat);
 | 
|---|
| 331 | begin
 | 
|---|
| 332 |   FillChar(Format, SizeOf(TCharFormat), 0);
 | 
|---|
| 333 |   Format.cbSize := SizeOf(TCharFormat);
 | 
|---|
| 334 | end;
 | 
|---|
| 335 | 
 | 
|---|
| 336 | function TXWBTextAttributes.GetConsistentAttributes: TConsistentAttributes;
 | 
|---|
| 337 | var
 | 
|---|
| 338 |   Format: TCharFormat;
 | 
|---|
| 339 | begin
 | 
|---|
| 340 |   Result := [];
 | 
|---|
| 341 |   if RichEdit.HandleAllocated and (FType = atSelected) then
 | 
|---|
| 342 |   begin
 | 
|---|
| 343 |     InitFormat(Format);
 | 
|---|
| 344 |     SendMessage(RichEdit.Handle, EM_GETCHARFORMAT,
 | 
|---|
| 345 |       WPARAM(FType = atSelected), LPARAM(@Format));
 | 
|---|
| 346 |     with Format do
 | 
|---|
| 347 |     begin
 | 
|---|
| 348 |       if (dwMask and CFM_BOLD) <> 0 then Include(Result, caBold);
 | 
|---|
| 349 |       if (dwMask and CFM_COLOR) <> 0 then Include(Result, caColor);
 | 
|---|
| 350 |       if (dwMask and CFM_FACE) <> 0 then Include(Result, caFace);
 | 
|---|
| 351 |       if (dwMask and CFM_ITALIC) <> 0 then Include(Result, caItalic);
 | 
|---|
| 352 |       if (dwMask and CFM_SIZE) <> 0 then Include(Result, caSize);
 | 
|---|
| 353 |       if (dwMask and CFM_STRIKEOUT) <> 0 then Include(Result, caStrikeOut);
 | 
|---|
| 354 |       if (dwMask and CFM_UNDERLINE) <> 0 then Include(Result, caUnderline);
 | 
|---|
| 355 |       if (dwMask and CFM_PROTECTED) <> 0 then Include(Result, caProtected);
 | 
|---|
| 356 |     end;
 | 
|---|
| 357 |   end;
 | 
|---|
| 358 | end;
 | 
|---|
| 359 | 
 | 
|---|
| 360 | procedure TXWBTextAttributes.GetAttributes(var Format: TCharFormat);
 | 
|---|
| 361 | begin
 | 
|---|
| 362 |   InitFormat(Format);
 | 
|---|
| 363 |   if RichEdit.HandleAllocated then
 | 
|---|
| 364 |     SendMessage(RichEdit.Handle, EM_GETCHARFORMAT,
 | 
|---|
| 365 |       WPARAM(FType = atSelected), LPARAM(@Format));
 | 
|---|
| 366 | end;
 | 
|---|
| 367 | 
 | 
|---|
| 368 | procedure TXWBTextAttributes.SetAttributes(var Format: TCharFormat);
 | 
|---|
| 369 | var
 | 
|---|
| 370 |   Flag: Longint;
 | 
|---|
| 371 | begin
 | 
|---|
| 372 |   if FType = atSelected then Flag := SCF_SELECTION
 | 
|---|
| 373 |   else Flag := 0;
 | 
|---|
| 374 |   if RichEdit.HandleAllocated then
 | 
|---|
| 375 |     SendMessage(RichEdit.Handle, EM_SETCHARFORMAT, Flag, LPARAM(@Format))
 | 
|---|
| 376 | end;
 | 
|---|
| 377 | 
 | 
|---|
| 378 | function TXWBTextAttributes.GetCharset: TFontCharset;
 | 
|---|
| 379 | var
 | 
|---|
| 380 |   Format: TCharFormat;
 | 
|---|
| 381 | begin
 | 
|---|
| 382 |   GetAttributes(Format);
 | 
|---|
| 383 |   Result := Format.bCharset;
 | 
|---|
| 384 | end;
 | 
|---|
| 385 | 
 | 
|---|
| 386 | procedure TXWBTextAttributes.SetCharset(Value: TFontCharset);
 | 
|---|
| 387 | var
 | 
|---|
| 388 |   Format: TCharFormat;
 | 
|---|
| 389 | begin
 | 
|---|
| 390 |   InitFormat(Format);
 | 
|---|
| 391 |   with Format do
 | 
|---|
| 392 |   begin
 | 
|---|
| 393 |     dwMask := CFM_CHARSET;
 | 
|---|
| 394 |     bCharSet := Value;
 | 
|---|
| 395 |   end;
 | 
|---|
| 396 |   SetAttributes(Format);
 | 
|---|
| 397 | end;
 | 
|---|
| 398 | 
 | 
|---|
| 399 | function TXWBTextAttributes.GetProtected: Boolean;
 | 
|---|
| 400 | var
 | 
|---|
| 401 |   Format: TCharFormat;
 | 
|---|
| 402 | begin
 | 
|---|
| 403 |   GetAttributes(Format);
 | 
|---|
| 404 |   with Format do
 | 
|---|
| 405 |     if (dwEffects and CFE_PROTECTED) <> 0 then
 | 
|---|
| 406 |       Result := True else
 | 
|---|
| 407 |       Result := False;
 | 
|---|
| 408 | end;
 | 
|---|
| 409 | 
 | 
|---|
| 410 | procedure TXWBTextAttributes.SetProtected(Value: Boolean);
 | 
|---|
| 411 | var
 | 
|---|
| 412 |   Format: TCharFormat;
 | 
|---|
| 413 | begin
 | 
|---|
| 414 |   InitFormat(Format);
 | 
|---|
| 415 |   with Format do
 | 
|---|
| 416 |   begin
 | 
|---|
| 417 |     dwMask := CFM_PROTECTED;
 | 
|---|
| 418 |     if Value then dwEffects := CFE_PROTECTED;
 | 
|---|
| 419 |   end;
 | 
|---|
| 420 |   SetAttributes(Format);
 | 
|---|
| 421 | end;
 | 
|---|
| 422 | 
 | 
|---|
| 423 | function TXWBTextAttributes.GetColor: TColor;
 | 
|---|
| 424 | var
 | 
|---|
| 425 |   Format: TCharFormat;
 | 
|---|
| 426 | begin
 | 
|---|
| 427 |   GetAttributes(Format);
 | 
|---|
| 428 |   with Format do
 | 
|---|
| 429 |     if (dwEffects and CFE_AUTOCOLOR) <> 0 then
 | 
|---|
| 430 |       Result := clWindowText else
 | 
|---|
| 431 |       Result := crTextColor;
 | 
|---|
| 432 | end;
 | 
|---|
| 433 | 
 | 
|---|
| 434 | procedure TXWBTextAttributes.SetColor(Value: TColor);
 | 
|---|
| 435 | var
 | 
|---|
| 436 |   Format: TCharFormat;
 | 
|---|
| 437 | begin
 | 
|---|
| 438 |   InitFormat(Format);
 | 
|---|
| 439 |   with Format do
 | 
|---|
| 440 |   begin
 | 
|---|
| 441 |     dwMask := CFM_COLOR;
 | 
|---|
| 442 |     if Value = clWindowText then
 | 
|---|
| 443 |       dwEffects := CFE_AUTOCOLOR else
 | 
|---|
| 444 |       crTextColor := ColorToRGB(Value);
 | 
|---|
| 445 |   end;
 | 
|---|
| 446 |   SetAttributes(Format);
 | 
|---|
| 447 | end;
 | 
|---|
| 448 | 
 | 
|---|
| 449 | function TXWBTextAttributes.GetName: TFontName;
 | 
|---|
| 450 | var
 | 
|---|
| 451 |   Format: TCharFormat;
 | 
|---|
| 452 | begin
 | 
|---|
| 453 |   GetAttributes(Format);
 | 
|---|
| 454 |   Result := Format.szFaceName;
 | 
|---|
| 455 | end;
 | 
|---|
| 456 | 
 | 
|---|
| 457 | procedure TXWBTextAttributes.SetName(Value: TFontName);
 | 
|---|
| 458 | var
 | 
|---|
| 459 |   Format: TCharFormat;
 | 
|---|
| 460 | begin
 | 
|---|
| 461 |   InitFormat(Format);
 | 
|---|
| 462 |   with Format do
 | 
|---|
| 463 |   begin
 | 
|---|
| 464 |     dwMask := CFM_FACE;
 | 
|---|
| 465 |     StrPLCopy(szFaceName, Value, SizeOf(szFaceName));
 | 
|---|
| 466 |   end;
 | 
|---|
| 467 |   SetAttributes(Format);
 | 
|---|
| 468 | end;
 | 
|---|
| 469 | 
 | 
|---|
| 470 | function TXWBTextAttributes.GetStyle: TFontStyles;
 | 
|---|
| 471 | var
 | 
|---|
| 472 |   Format: TCharFormat;
 | 
|---|
| 473 | begin
 | 
|---|
| 474 |   Result := [];
 | 
|---|
| 475 |   GetAttributes(Format);
 | 
|---|
| 476 |   with Format do
 | 
|---|
| 477 |   begin
 | 
|---|
| 478 |     if (dwEffects and CFE_BOLD) <> 0 then Include(Result, fsBold);
 | 
|---|
| 479 |     if (dwEffects and CFE_ITALIC) <> 0 then Include(Result, fsItalic);
 | 
|---|
| 480 |     if (dwEffects and CFE_UNDERLINE) <> 0 then Include(Result, fsUnderline);
 | 
|---|
| 481 |     if (dwEffects and CFE_STRIKEOUT) <> 0 then Include(Result, fsStrikeOut);
 | 
|---|
| 482 |   end;
 | 
|---|
| 483 | end;
 | 
|---|
| 484 | 
 | 
|---|
| 485 | procedure TXWBTextAttributes.SetStyle(Value: TFontStyles);
 | 
|---|
| 486 | var
 | 
|---|
| 487 |   Format: TCharFormat;
 | 
|---|
| 488 | begin
 | 
|---|
| 489 |   InitFormat(Format);
 | 
|---|
| 490 |   with Format do
 | 
|---|
| 491 |   begin
 | 
|---|
| 492 |     dwMask := CFM_BOLD or CFM_ITALIC or CFM_UNDERLINE or CFM_STRIKEOUT;
 | 
|---|
| 493 |     if fsBold in Value then dwEffects := dwEffects or CFE_BOLD;
 | 
|---|
| 494 |     if fsItalic in Value then dwEffects := dwEffects or CFE_ITALIC;
 | 
|---|
| 495 |     if fsUnderline in Value then dwEffects := dwEffects or CFE_UNDERLINE;
 | 
|---|
| 496 |     if fsStrikeOut in Value then dwEffects := dwEffects or CFE_STRIKEOUT;
 | 
|---|
| 497 |   end;
 | 
|---|
| 498 | 
 | 
|---|
| 499 |   SetAttributes(Format);
 | 
|---|
| 500 | end;
 | 
|---|
| 501 | 
 | 
|---|
| 502 | function TXWBTextAttributes.GetSize: Integer;
 | 
|---|
| 503 | var
 | 
|---|
| 504 |   Format: TCharFormat;
 | 
|---|
| 505 | begin
 | 
|---|
| 506 |   GetAttributes(Format);
 | 
|---|
| 507 |   Result := Format.yHeight div 20;
 | 
|---|
| 508 | end;
 | 
|---|
| 509 | 
 | 
|---|
| 510 | procedure TXWBTextAttributes.SetSize(Value: Integer);
 | 
|---|
| 511 | var
 | 
|---|
| 512 |   Format: TCharFormat;
 | 
|---|
| 513 | begin
 | 
|---|
| 514 |   InitFormat(Format);
 | 
|---|
| 515 |   with Format do
 | 
|---|
| 516 |   begin
 | 
|---|
| 517 |     dwMask := Integer(CFM_SIZE);
 | 
|---|
| 518 |     yHeight := Value * 20;
 | 
|---|
| 519 |   end;
 | 
|---|
| 520 |   SetAttributes(Format);
 | 
|---|
| 521 | end;
 | 
|---|
| 522 | 
 | 
|---|
| 523 | function TXWBTextAttributes.GetHeight: Integer;
 | 
|---|
| 524 | begin
 | 
|---|
| 525 |   Result := MulDiv(Size, RichEdit.FScreenLogPixels, 72);
 | 
|---|
| 526 | end;
 | 
|---|
| 527 | 
 | 
|---|
| 528 | procedure TXWBTextAttributes.SetHeight(Value: Integer);
 | 
|---|
| 529 | begin
 | 
|---|
| 530 |   Size := MulDiv(Value, 72, RichEdit.FScreenLogPixels);
 | 
|---|
| 531 | end;
 | 
|---|
| 532 | 
 | 
|---|
| 533 | function TXWBTextAttributes.GetPitch: TFontPitch;
 | 
|---|
| 534 | var
 | 
|---|
| 535 |   Format: TCharFormat;
 | 
|---|
| 536 | begin
 | 
|---|
| 537 |   GetAttributes(Format);
 | 
|---|
| 538 |   case (Format.bPitchAndFamily and $03) of
 | 
|---|
| 539 |     DEFAULT_PITCH: Result := fpDefault;
 | 
|---|
| 540 |     VARIABLE_PITCH: Result := fpVariable;
 | 
|---|
| 541 |     FIXED_PITCH: Result := fpFixed;
 | 
|---|
| 542 |   else
 | 
|---|
| 543 |     Result := fpDefault;
 | 
|---|
| 544 |   end;
 | 
|---|
| 545 | end;
 | 
|---|
| 546 | 
 | 
|---|
| 547 | procedure TXWBTextAttributes.SetPitch(Value: TFontPitch);
 | 
|---|
| 548 | var
 | 
|---|
| 549 |   Format: TCharFormat;
 | 
|---|
| 550 | begin
 | 
|---|
| 551 |   InitFormat(Format);
 | 
|---|
| 552 |   with Format do
 | 
|---|
| 553 |   begin
 | 
|---|
| 554 |     case Value of
 | 
|---|
| 555 |       fpVariable: Format.bPitchAndFamily := VARIABLE_PITCH;
 | 
|---|
| 556 |       fpFixed: Format.bPitchAndFamily := FIXED_PITCH;
 | 
|---|
| 557 |     else
 | 
|---|
| 558 |       Format.bPitchAndFamily := DEFAULT_PITCH;
 | 
|---|
| 559 |     end;
 | 
|---|
| 560 |   end;
 | 
|---|
| 561 |   SetAttributes(Format);
 | 
|---|
| 562 | end;
 | 
|---|
| 563 | 
 | 
|---|
| 564 | procedure TXWBTextAttributes.Assign(Source: TPersistent);
 | 
|---|
| 565 | begin
 | 
|---|
| 566 |   if Source is TFont then
 | 
|---|
| 567 |   begin
 | 
|---|
| 568 |     Color := TFont(Source).Color;
 | 
|---|
| 569 |     Name := TFont(Source).Name;
 | 
|---|
| 570 |     Charset := TFont(Source).Charset;
 | 
|---|
| 571 |     Style := TFont(Source).Style;
 | 
|---|
| 572 |     Size := TFont(Source).Size;
 | 
|---|
| 573 |     Pitch := TFont(Source).Pitch;
 | 
|---|
| 574 |   end
 | 
|---|
| 575 |   else if Source is TXWBTextAttributes then
 | 
|---|
| 576 |   begin
 | 
|---|
| 577 |     Color := TXWBTextAttributes(Source).Color;
 | 
|---|
| 578 |     Name := TXWBTextAttributes(Source).Name;
 | 
|---|
| 579 |     Charset := TXWBTextAttributes(Source).Charset;
 | 
|---|
| 580 |     Style := TXWBTextAttributes(Source).Style;
 | 
|---|
| 581 |     Pitch := TXWBTextAttributes(Source).Pitch;
 | 
|---|
| 582 |   end
 | 
|---|
| 583 |   else inherited Assign(Source);
 | 
|---|
| 584 | end;
 | 
|---|
| 585 | 
 | 
|---|
| 586 | procedure TXWBTextAttributes.AssignTo(Dest: TPersistent);
 | 
|---|
| 587 | begin
 | 
|---|
| 588 |   if Dest is TFont then
 | 
|---|
| 589 |   begin
 | 
|---|
| 590 |     TFont(Dest).Color := Color;
 | 
|---|
| 591 |     TFont(Dest).Name := Name;
 | 
|---|
| 592 |     TFont(Dest).Charset := Charset;
 | 
|---|
| 593 |     TFont(Dest).Style := Style;
 | 
|---|
| 594 |     TFont(Dest).Size := Size;
 | 
|---|
| 595 |     TFont(Dest).Pitch := Pitch;
 | 
|---|
| 596 |   end
 | 
|---|
| 597 |   else if Dest is TXWBTextAttributes then
 | 
|---|
| 598 |   begin
 | 
|---|
| 599 |     TXWBTextAttributes(Dest).Color := Color;
 | 
|---|
| 600 |     TXWBTextAttributes(Dest).Name := Name;
 | 
|---|
| 601 |     TXWBTextAttributes(Dest).Charset := Charset;
 | 
|---|
| 602 |     TXWBTextAttributes(Dest).Style := Style;
 | 
|---|
| 603 |     TXWBTextAttributes(Dest).Pitch := Pitch;
 | 
|---|
| 604 |   end
 | 
|---|
| 605 |   else inherited AssignTo(Dest);
 | 
|---|
| 606 | end;
 | 
|---|
| 607 | 
 | 
|---|
| 608 | { TParaAttributes }
 | 
|---|
| 609 | 
 | 
|---|
| 610 | constructor TParaAttributes.Create(AOwner: TXWBCustomRichEdit);
 | 
|---|
| 611 | begin
 | 
|---|
| 612 |   inherited Create;
 | 
|---|
| 613 |   RichEdit := AOwner;
 | 
|---|
| 614 | end;
 | 
|---|
| 615 | 
 | 
|---|
| 616 | procedure TParaAttributes.InitPara(var Paragraph: TParaFormat);
 | 
|---|
| 617 | begin
 | 
|---|
| 618 |   FillChar(Paragraph, SizeOf(TParaFormat), 0);
 | 
|---|
| 619 |   Paragraph.cbSize := SizeOf(TParaFormat);
 | 
|---|
| 620 | end;
 | 
|---|
| 621 | 
 | 
|---|
| 622 | procedure TParaAttributes.GetAttributes(var Paragraph: TParaFormat);
 | 
|---|
| 623 | begin
 | 
|---|
| 624 |   InitPara(Paragraph);
 | 
|---|
| 625 |   if RichEdit.HandleAllocated then
 | 
|---|
| 626 |     SendMessage(RichEdit.Handle, EM_GETPARAFORMAT, 0, LPARAM(@Paragraph));
 | 
|---|
| 627 | end;
 | 
|---|
| 628 | 
 | 
|---|
| 629 | procedure TParaAttributes.SetAttributes(var Paragraph: TParaFormat);
 | 
|---|
| 630 | begin
 | 
|---|
| 631 |   RichEdit.HandleNeeded; { we REALLY need the handle for BiDi }
 | 
|---|
| 632 |   if RichEdit.HandleAllocated then
 | 
|---|
| 633 |   begin
 | 
|---|
| 634 |     if RichEdit.UseRightToLeftAlignment then
 | 
|---|
| 635 |       if Paragraph.wAlignment = PFA_LEFT then
 | 
|---|
| 636 |         Paragraph.wAlignment := PFA_RIGHT
 | 
|---|
| 637 |       else if Paragraph.wAlignment = PFA_RIGHT then
 | 
|---|
| 638 |         Paragraph.wAlignment := PFA_LEFT;
 | 
|---|
| 639 |     SendMessage(RichEdit.Handle, EM_SETPARAFORMAT, 0, LPARAM(@Paragraph));
 | 
|---|
| 640 |   end;
 | 
|---|
| 641 | end;
 | 
|---|
| 642 | 
 | 
|---|
| 643 | function TParaAttributes.GetAlignment: TAlignment;
 | 
|---|
| 644 | var
 | 
|---|
| 645 |   Paragraph: TParaFormat;
 | 
|---|
| 646 | begin
 | 
|---|
| 647 |   GetAttributes(Paragraph);
 | 
|---|
| 648 |   Result := TAlignment(Paragraph.wAlignment - 1);
 | 
|---|
| 649 | end;
 | 
|---|
| 650 | 
 | 
|---|
| 651 | procedure TParaAttributes.SetAlignment(Value: TAlignment);
 | 
|---|
| 652 | var
 | 
|---|
| 653 |   Paragraph: TParaFormat;
 | 
|---|
| 654 | begin
 | 
|---|
| 655 |   InitPara(Paragraph);
 | 
|---|
| 656 |   with Paragraph do
 | 
|---|
| 657 |   begin
 | 
|---|
| 658 |     dwMask := PFM_ALIGNMENT;
 | 
|---|
| 659 |     wAlignment := Ord(Value) + 1;
 | 
|---|
| 660 |   end;
 | 
|---|
| 661 |   SetAttributes(Paragraph);
 | 
|---|
| 662 | end;
 | 
|---|
| 663 | 
 | 
|---|
| 664 | function TParaAttributes.GetNumbering: TNumberingStyle;
 | 
|---|
| 665 | var
 | 
|---|
| 666 |   Paragraph: TParaFormat;
 | 
|---|
| 667 | begin
 | 
|---|
| 668 |   GetAttributes(Paragraph);
 | 
|---|
| 669 |   Result := TNumberingStyle(Paragraph.wNumbering);
 | 
|---|
| 670 | end;
 | 
|---|
| 671 | 
 | 
|---|
| 672 | procedure TParaAttributes.SetNumbering(Value: TNumberingStyle);
 | 
|---|
| 673 | var
 | 
|---|
| 674 |   Paragraph: TParaFormat;
 | 
|---|
| 675 | begin
 | 
|---|
| 676 |   case Value of
 | 
|---|
| 677 |     nsBullet: if LeftIndent < 10 then LeftIndent := 10;
 | 
|---|
| 678 |     nsNone: LeftIndent := 0;
 | 
|---|
| 679 |   end;
 | 
|---|
| 680 |   InitPara(Paragraph);
 | 
|---|
| 681 |   with Paragraph do
 | 
|---|
| 682 |   begin
 | 
|---|
| 683 |     dwMask := PFM_NUMBERING;
 | 
|---|
| 684 |     wNumbering := Ord(Value);
 | 
|---|
| 685 |   end;
 | 
|---|
| 686 |   SetAttributes(Paragraph);
 | 
|---|
| 687 | end;
 | 
|---|
| 688 | 
 | 
|---|
| 689 | function TParaAttributes.GetFirstIndent: Longint;
 | 
|---|
| 690 | var
 | 
|---|
| 691 |   Paragraph: TParaFormat;
 | 
|---|
| 692 | begin
 | 
|---|
| 693 |   GetAttributes(Paragraph);
 | 
|---|
| 694 |   Result := Paragraph.dxStartIndent div 20
 | 
|---|
| 695 | end;
 | 
|---|
| 696 | 
 | 
|---|
| 697 | procedure TParaAttributes.SetFirstIndent(Value: Longint);
 | 
|---|
| 698 | var
 | 
|---|
| 699 |   Paragraph: TParaFormat;
 | 
|---|
| 700 | begin
 | 
|---|
| 701 |   InitPara(Paragraph);
 | 
|---|
| 702 |   with Paragraph do
 | 
|---|
| 703 |   begin
 | 
|---|
| 704 |     dwMask := PFM_STARTINDENT;
 | 
|---|
| 705 |     dxStartIndent := Value * 20;
 | 
|---|
| 706 |   end;
 | 
|---|
| 707 |   SetAttributes(Paragraph);
 | 
|---|
| 708 | end;
 | 
|---|
| 709 | 
 | 
|---|
| 710 | function TParaAttributes.GetLeftIndent: Longint;
 | 
|---|
| 711 | var
 | 
|---|
| 712 |   Paragraph: TParaFormat;
 | 
|---|
| 713 | begin
 | 
|---|
| 714 |   GetAttributes(Paragraph);
 | 
|---|
| 715 |   Result := Paragraph.dxOffset div 20;
 | 
|---|
| 716 | end;
 | 
|---|
| 717 | 
 | 
|---|
| 718 | procedure TParaAttributes.SetLeftIndent(Value: Longint);
 | 
|---|
| 719 | var
 | 
|---|
| 720 |   Paragraph: TParaFormat;
 | 
|---|
| 721 | begin
 | 
|---|
| 722 |   InitPara(Paragraph);
 | 
|---|
| 723 |   with Paragraph do
 | 
|---|
| 724 |   begin
 | 
|---|
| 725 |     dwMask := PFM_OFFSET;
 | 
|---|
| 726 |     dxOffset := Value * 20;
 | 
|---|
| 727 |   end;
 | 
|---|
| 728 |   SetAttributes(Paragraph);
 | 
|---|
| 729 | end;
 | 
|---|
| 730 | 
 | 
|---|
| 731 | function TParaAttributes.GetRightIndent: Longint;
 | 
|---|
| 732 | var
 | 
|---|
| 733 |   Paragraph: TParaFormat;
 | 
|---|
| 734 | begin
 | 
|---|
| 735 |   GetAttributes(Paragraph);
 | 
|---|
| 736 |   Result := Paragraph.dxRightIndent div 20;
 | 
|---|
| 737 | end;
 | 
|---|
| 738 | 
 | 
|---|
| 739 | procedure TParaAttributes.SetRightIndent(Value: Longint);
 | 
|---|
| 740 | var
 | 
|---|
| 741 |   Paragraph: TParaFormat;
 | 
|---|
| 742 | begin
 | 
|---|
| 743 |   InitPara(Paragraph);
 | 
|---|
| 744 |   with Paragraph do
 | 
|---|
| 745 |   begin
 | 
|---|
| 746 |     dwMask := PFM_RIGHTINDENT;
 | 
|---|
| 747 |     dxRightIndent := Value * 20;
 | 
|---|
| 748 |   end;
 | 
|---|
| 749 |   SetAttributes(Paragraph);
 | 
|---|
| 750 | end;
 | 
|---|
| 751 | 
 | 
|---|
| 752 | function TParaAttributes.GetTab(Index: Byte): Longint;
 | 
|---|
| 753 | var
 | 
|---|
| 754 |   Paragraph: TParaFormat;
 | 
|---|
| 755 | begin
 | 
|---|
| 756 |   GetAttributes(Paragraph);
 | 
|---|
| 757 |   Result := Paragraph.rgxTabs[Index] div 20;
 | 
|---|
| 758 | end;
 | 
|---|
| 759 | 
 | 
|---|
| 760 | procedure TParaAttributes.SetTab(Index: Byte; Value: Longint);
 | 
|---|
| 761 | var
 | 
|---|
| 762 |   Paragraph: TParaFormat;
 | 
|---|
| 763 | begin
 | 
|---|
| 764 |   GetAttributes(Paragraph);
 | 
|---|
| 765 |   with Paragraph do
 | 
|---|
| 766 |   begin
 | 
|---|
| 767 |     rgxTabs[Index] := Value * 20;
 | 
|---|
| 768 |     dwMask := PFM_TABSTOPS;
 | 
|---|
| 769 |     if cTabCount < Index then cTabCount := Index;
 | 
|---|
| 770 |     SetAttributes(Paragraph);
 | 
|---|
| 771 |   end;
 | 
|---|
| 772 | end;
 | 
|---|
| 773 | 
 | 
|---|
| 774 | function TParaAttributes.GetTabCount: Integer;
 | 
|---|
| 775 | var
 | 
|---|
| 776 |   Paragraph: TParaFormat;
 | 
|---|
| 777 | begin
 | 
|---|
| 778 |   GetAttributes(Paragraph);
 | 
|---|
| 779 |   Result := Paragraph.cTabCount;
 | 
|---|
| 780 | end;
 | 
|---|
| 781 | 
 | 
|---|
| 782 | procedure TParaAttributes.SetTabCount(Value: Integer);
 | 
|---|
| 783 | var
 | 
|---|
| 784 |   Paragraph: TParaFormat;
 | 
|---|
| 785 | begin
 | 
|---|
| 786 |   GetAttributes(Paragraph);
 | 
|---|
| 787 |   with Paragraph do
 | 
|---|
| 788 |   begin
 | 
|---|
| 789 |     dwMask := PFM_TABSTOPS;
 | 
|---|
| 790 |     cTabCount := Value;
 | 
|---|
| 791 |     SetAttributes(Paragraph);
 | 
|---|
| 792 |   end;
 | 
|---|
| 793 | end;
 | 
|---|
| 794 | 
 | 
|---|
| 795 | procedure TParaAttributes.Assign(Source: TPersistent);
 | 
|---|
| 796 | var
 | 
|---|
| 797 |   I: Integer;
 | 
|---|
| 798 | begin
 | 
|---|
| 799 |   if Source is TParaAttributes then
 | 
|---|
| 800 |   begin
 | 
|---|
| 801 |     Alignment := TParaAttributes(Source).Alignment;
 | 
|---|
| 802 |     FirstIndent := TParaAttributes(Source).FirstIndent;
 | 
|---|
| 803 |     LeftIndent := TParaAttributes(Source).LeftIndent;
 | 
|---|
| 804 |     RightIndent := TParaAttributes(Source).RightIndent;
 | 
|---|
| 805 |     Numbering := TParaAttributes(Source).Numbering;
 | 
|---|
| 806 |     for I := 0 to MAX_TAB_STOPS - 1 do
 | 
|---|
| 807 |       Tab[I] := TParaAttributes(Source).Tab[I];
 | 
|---|
| 808 |   end
 | 
|---|
| 809 |   else inherited Assign(Source);
 | 
|---|
| 810 | end;
 | 
|---|
| 811 | 
 | 
|---|
| 812 | { TConversion }
 | 
|---|
| 813 | 
 | 
|---|
| 814 | function TConversion.ConvertReadStream(Stream: TStream; Buffer: PChar; BufSize: Integer): Integer;
 | 
|---|
| 815 | begin
 | 
|---|
| 816 |   Result := Stream.Read(Buffer^, BufSize);
 | 
|---|
| 817 | end;
 | 
|---|
| 818 | 
 | 
|---|
| 819 | function TConversion.ConvertWriteStream(Stream: TStream; Buffer: PChar; BufSize: Integer): Integer;
 | 
|---|
| 820 | begin
 | 
|---|
| 821 |   Result := Stream.Write(Buffer^, BufSize);
 | 
|---|
| 822 | end;
 | 
|---|
| 823 | 
 | 
|---|
| 824 | { TRichEditStrings }
 | 
|---|
| 825 | 
 | 
|---|
| 826 | const
 | 
|---|
| 827 |   ReadError = $0001;
 | 
|---|
| 828 |   WriteError = $0002;
 | 
|---|
| 829 |   NoError = $0000;
 | 
|---|
| 830 | 
 | 
|---|
| 831 | type
 | 
|---|
| 832 |   TSelection = record
 | 
|---|
| 833 |     StartPos, EndPos: Integer;
 | 
|---|
| 834 |   end;
 | 
|---|
| 835 | 
 | 
|---|
| 836 |   TRichEditStrings = class(TStrings)
 | 
|---|
| 837 |   private
 | 
|---|
| 838 |     RichEdit: TXWBCustomRichEdit;
 | 
|---|
| 839 |     FPlainText: Boolean;
 | 
|---|
| 840 |     FConverter: TConversion;
 | 
|---|
| 841 |     procedure EnableChange(const Value: Boolean);
 | 
|---|
| 842 |   protected
 | 
|---|
| 843 |     function Get(Index: Integer): string; override;
 | 
|---|
| 844 |     function GetCount: Integer; override;
 | 
|---|
| 845 |     procedure Put(Index: Integer; const S: string); override;
 | 
|---|
| 846 |     procedure SetUpdateState(Updating: Boolean); override;
 | 
|---|
| 847 |     procedure SetTextStr(const Value: string); override;
 | 
|---|
| 848 |   public
 | 
|---|
| 849 |     destructor Destroy; override;
 | 
|---|
| 850 |     procedure Clear; override;
 | 
|---|
| 851 |     procedure AddStrings(Strings: TStrings); override;
 | 
|---|
| 852 |     procedure Delete(Index: Integer); override;
 | 
|---|
| 853 |     procedure Insert(Index: Integer; const S: string); override;
 | 
|---|
| 854 |     procedure LoadFromFile(const FileName: string); override;
 | 
|---|
| 855 |     procedure LoadFromStream(Stream: TStream); override;
 | 
|---|
| 856 |     procedure SaveToFile(const FileName: string); override;
 | 
|---|
| 857 |     procedure SaveToStream(Stream: TStream); override;
 | 
|---|
| 858 |     property PlainText: Boolean read FPlainText write FPlainText;
 | 
|---|
| 859 |   end;
 | 
|---|
| 860 | 
 | 
|---|
| 861 | destructor TRichEditStrings.Destroy;
 | 
|---|
| 862 | begin
 | 
|---|
| 863 |   FConverter.Free;
 | 
|---|
| 864 |   inherited Destroy;
 | 
|---|
| 865 | end;
 | 
|---|
| 866 | 
 | 
|---|
| 867 | procedure TRichEditStrings.AddStrings(Strings: TStrings);
 | 
|---|
| 868 | var
 | 
|---|
| 869 |   SelChange: TNotifyEvent;
 | 
|---|
| 870 | begin
 | 
|---|
| 871 |   SelChange := RichEdit.OnSelectionChange;
 | 
|---|
| 872 |   RichEdit.OnSelectionChange := nil;
 | 
|---|
| 873 |   try
 | 
|---|
| 874 |     inherited AddStrings(Strings);
 | 
|---|
| 875 |   finally
 | 
|---|
| 876 |     RichEdit.OnSelectionChange := SelChange;
 | 
|---|
| 877 |   end;
 | 
|---|
| 878 | end;
 | 
|---|
| 879 | 
 | 
|---|
| 880 | function TRichEditStrings.GetCount: Integer;
 | 
|---|
| 881 | begin
 | 
|---|
| 882 |   Result := SendMessage(RichEdit.Handle, EM_GETLINECOUNT, 0, 0);
 | 
|---|
| 883 |   if SendMessage(RichEdit.Handle, EM_LINELENGTH, SendMessage(RichEdit.Handle,
 | 
|---|
| 884 |     EM_LINEINDEX, Result - 1, 0), 0) = 0 then Dec(Result);
 | 
|---|
| 885 | end;
 | 
|---|
| 886 | 
 | 
|---|
| 887 | function TRichEditStrings.Get(Index: Integer): string;
 | 
|---|
| 888 | var
 | 
|---|
| 889 |   Text: array[0..4095] of Char;
 | 
|---|
| 890 |   L: Integer;
 | 
|---|
| 891 | begin
 | 
|---|
| 892 |   Word((@Text)^) := SizeOf(Text);
 | 
|---|
| 893 |   L := SendMessage(RichEdit.Handle, EM_GETLINE, Index, Longint(@Text));
 | 
|---|
| 894 |   if (Text[L - 2] = #13) and (Text[L - 1] = #10) then Dec(L, 2);
 | 
|---|
| 895 |   SetString(Result, Text, L);
 | 
|---|
| 896 | end;
 | 
|---|
| 897 | 
 | 
|---|
| 898 | procedure TRichEditStrings.Put(Index: Integer; const S: string);
 | 
|---|
| 899 | var
 | 
|---|
| 900 |   Selection: TCharRange;
 | 
|---|
| 901 | begin
 | 
|---|
| 902 |   if Index >= 0 then
 | 
|---|
| 903 |   begin
 | 
|---|
| 904 |     Selection.cpMin := SendMessage(RichEdit.Handle, EM_LINEINDEX, Index, 0);
 | 
|---|
| 905 |     if Selection.cpMin <> -1 then
 | 
|---|
| 906 |     begin
 | 
|---|
| 907 |       Selection.cpMax := Selection.cpMin +
 | 
|---|
| 908 |         SendMessage(RichEdit.Handle, EM_LINELENGTH, Selection.cpMin, 0);
 | 
|---|
| 909 |       SendMessage(RichEdit.Handle, EM_EXSETSEL, 0, Longint(@Selection));
 | 
|---|
| 910 |       SendMessage(RichEdit.Handle, EM_REPLACESEL, 0, Longint(PChar(S)));
 | 
|---|
| 911 |     end;
 | 
|---|
| 912 |   end;
 | 
|---|
| 913 | end;
 | 
|---|
| 914 | 
 | 
|---|
| 915 | procedure TRichEditStrings.Insert(Index: Integer; const S: string);
 | 
|---|
| 916 | var
 | 
|---|
| 917 |   L: Integer;
 | 
|---|
| 918 |   Selection: TCharRange;
 | 
|---|
| 919 |   Fmt: PChar;
 | 
|---|
| 920 |   Str: string;
 | 
|---|
| 921 | begin
 | 
|---|
| 922 |   if Index >= 0 then
 | 
|---|
| 923 |   begin
 | 
|---|
| 924 |     Selection.cpMin := SendMessage(RichEdit.Handle, EM_LINEINDEX, Index, 0);
 | 
|---|
| 925 |     if Selection.cpMin >= 0 then Fmt := '%s'#13#10
 | 
|---|
| 926 |     else begin
 | 
|---|
| 927 |       Selection.cpMin :=
 | 
|---|
| 928 |         SendMessage(RichEdit.Handle, EM_LINEINDEX, Index - 1, 0);
 | 
|---|
| 929 |       if Selection.cpMin < 0 then Exit;
 | 
|---|
| 930 |       L := SendMessage(RichEdit.Handle, EM_LINELENGTH, Selection.cpMin, 0);
 | 
|---|
| 931 |       if L = 0 then Exit;
 | 
|---|
| 932 |       Inc(Selection.cpMin, L);
 | 
|---|
| 933 |       Fmt := #13#10'%s';
 | 
|---|
| 934 |     end;
 | 
|---|
| 935 | 
 | 
|---|
| 936 |     Selection.cpMax := Selection.cpMin;
 | 
|---|
| 937 |     SendMessage(RichEdit.Handle, EM_EXSETSEL, 0, Longint(@Selection));
 | 
|---|
| 938 | 
 | 
|---|
| 939 |     Str := Format(Fmt, [S]);
 | 
|---|
| 940 |     SendMessage(RichEdit.Handle, EM_REPLACESEL, 0, LongInt(PChar(Str)));
 | 
|---|
| 941 | {
 | 
|---|
| 942 |     if RichEdit.SelStart <> (Selection.cpMax + Length(Str)) then
 | 
|---|
| 943 |       raise EOutOfResources.Create(sRichEditInsertError);
 | 
|---|
| 944 | }
 | 
|---|
| 945 |   end;
 | 
|---|
| 946 | end;
 | 
|---|
| 947 | 
 | 
|---|
| 948 | procedure TRichEditStrings.Delete(Index: Integer);
 | 
|---|
| 949 | const
 | 
|---|
| 950 |   Empty: PChar = '';
 | 
|---|
| 951 | var
 | 
|---|
| 952 |   Selection: TCharRange;
 | 
|---|
| 953 | begin
 | 
|---|
| 954 |   if Index < 0 then Exit;
 | 
|---|
| 955 |   Selection.cpMin := SendMessage(RichEdit.Handle, EM_LINEINDEX, Index, 0);
 | 
|---|
| 956 |   if Selection.cpMin <> -1 then
 | 
|---|
| 957 |   begin
 | 
|---|
| 958 |     Selection.cpMax := SendMessage(RichEdit.Handle, EM_LINEINDEX, Index + 1, 0);
 | 
|---|
| 959 |     if Selection.cpMax = -1 then
 | 
|---|
| 960 |       Selection.cpMax := Selection.cpMin +
 | 
|---|
| 961 |         SendMessage(RichEdit.Handle, EM_LINELENGTH, Selection.cpMin, 0);
 | 
|---|
| 962 |     SendMessage(RichEdit.Handle, EM_EXSETSEL, 0, Longint(@Selection));
 | 
|---|
| 963 |     SendMessage(RichEdit.Handle, EM_REPLACESEL, 0, Longint(Empty));
 | 
|---|
| 964 |   end;
 | 
|---|
| 965 | end;
 | 
|---|
| 966 | 
 | 
|---|
| 967 | procedure TRichEditStrings.Clear;
 | 
|---|
| 968 | begin
 | 
|---|
| 969 |   RichEdit.Clear;
 | 
|---|
| 970 | end;
 | 
|---|
| 971 | 
 | 
|---|
| 972 | procedure TRichEditStrings.SetUpdateState(Updating: Boolean);
 | 
|---|
| 973 | begin
 | 
|---|
| 974 |   if RichEdit.Showing then
 | 
|---|
| 975 |     SendMessage(RichEdit.Handle, WM_SETREDRAW, Ord(not Updating), 0);
 | 
|---|
| 976 |   if not Updating then begin
 | 
|---|
| 977 |     RichEdit.Refresh;
 | 
|---|
| 978 |     RichEdit.Perform(CM_TEXTCHANGED, 0, 0);
 | 
|---|
| 979 |   end;
 | 
|---|
| 980 | end;
 | 
|---|
| 981 | 
 | 
|---|
| 982 | procedure TRichEditStrings.EnableChange(const Value: Boolean);
 | 
|---|
| 983 | var
 | 
|---|
| 984 |   EventMask: Longint;
 | 
|---|
| 985 | begin
 | 
|---|
| 986 |   with RichEdit do
 | 
|---|
| 987 |   begin
 | 
|---|
| 988 |     if Value then
 | 
|---|
| 989 |       EventMask := SendMessage(Handle, EM_GETEVENTMASK, 0, 0) or ENM_CHANGE
 | 
|---|
| 990 |     else
 | 
|---|
| 991 |       EventMask := SendMessage(Handle, EM_GETEVENTMASK, 0, 0) and not ENM_CHANGE;
 | 
|---|
| 992 |     SendMessage(Handle, EM_SETEVENTMASK, 0, EventMask);
 | 
|---|
| 993 |   end;
 | 
|---|
| 994 | end;
 | 
|---|
| 995 | 
 | 
|---|
| 996 | procedure TRichEditStrings.SetTextStr(const Value: string);
 | 
|---|
| 997 | begin
 | 
|---|
| 998 |   EnableChange(False);
 | 
|---|
| 999 |   try
 | 
|---|
| 1000 |     inherited SetTextStr(Value);
 | 
|---|
| 1001 |   finally
 | 
|---|
| 1002 |     EnableChange(True);
 | 
|---|
| 1003 |   end;
 | 
|---|
| 1004 | end;
 | 
|---|
| 1005 | 
 | 
|---|
| 1006 | function AdjustLineBreaks(Dest, Source: PChar): Integer; assembler;
 | 
|---|
| 1007 | asm
 | 
|---|
| 1008 |         PUSH    ESI
 | 
|---|
| 1009 |         PUSH    EDI
 | 
|---|
| 1010 |         MOV     EDI,EAX
 | 
|---|
| 1011 |         MOV     ESI,EDX
 | 
|---|
| 1012 |         MOV     EDX,EAX
 | 
|---|
| 1013 |         CLD
 | 
|---|
| 1014 | @@1:    LODSB
 | 
|---|
| 1015 | @@2:    OR      AL,AL
 | 
|---|
| 1016 |         JE      @@4
 | 
|---|
| 1017 |         CMP     AL,0AH
 | 
|---|
| 1018 |         JE      @@3
 | 
|---|
| 1019 |         STOSB
 | 
|---|
| 1020 |         CMP     AL,0DH
 | 
|---|
| 1021 |         JNE     @@1
 | 
|---|
| 1022 |         MOV     AL,0AH
 | 
|---|
| 1023 |         STOSB
 | 
|---|
| 1024 |         LODSB
 | 
|---|
| 1025 |         CMP     AL,0AH
 | 
|---|
| 1026 |         JE      @@1
 | 
|---|
| 1027 |         JMP     @@2
 | 
|---|
| 1028 | @@3:    MOV     EAX,0A0DH
 | 
|---|
| 1029 |         STOSW
 | 
|---|
| 1030 |         JMP     @@1
 | 
|---|
| 1031 | @@4:    STOSB
 | 
|---|
| 1032 |         LEA     EAX,[EDI-1]
 | 
|---|
| 1033 |         SUB     EAX,EDX
 | 
|---|
| 1034 |         POP     EDI
 | 
|---|
| 1035 |         POP     ESI
 | 
|---|
| 1036 | end;
 | 
|---|
| 1037 | 
 | 
|---|
| 1038 | function StreamSave(dwCookie: Longint; pbBuff: PByte;
 | 
|---|
| 1039 |   cb: Longint; var pcb: Longint): Longint; stdcall;
 | 
|---|
| 1040 | var
 | 
|---|
| 1041 |   StreamInfo: PRichEditStreamInfo;
 | 
|---|
| 1042 | begin
 | 
|---|
| 1043 |   Result := NoError;
 | 
|---|
| 1044 |   StreamInfo := PRichEditStreamInfo(Pointer(dwCookie));
 | 
|---|
| 1045 |   try
 | 
|---|
| 1046 |     pcb := 0;
 | 
|---|
| 1047 |     if StreamInfo^.Converter <> nil then
 | 
|---|
| 1048 |       pcb := StreamInfo^.Converter.ConvertWriteStream(StreamInfo^.Stream, PChar(pbBuff), cb);
 | 
|---|
| 1049 |   except
 | 
|---|
| 1050 |     Result := WriteError;
 | 
|---|
| 1051 |   end;
 | 
|---|
| 1052 | end;
 | 
|---|
| 1053 | 
 | 
|---|
| 1054 | function StreamLoad(dwCookie: Longint; pbBuff: PByte;
 | 
|---|
| 1055 |   cb: Longint; var pcb: Longint): Longint; stdcall;
 | 
|---|
| 1056 | var
 | 
|---|
| 1057 |   Buffer, pBuff: PChar;
 | 
|---|
| 1058 |   StreamInfo: PRichEditStreamInfo;
 | 
|---|
| 1059 | begin
 | 
|---|
| 1060 |   Result := NoError;
 | 
|---|
| 1061 |   StreamInfo := PRichEditStreamInfo(Pointer(dwCookie));
 | 
|---|
| 1062 |   Buffer := StrAlloc(cb + 1);
 | 
|---|
| 1063 |   try
 | 
|---|
| 1064 |     cb := cb div 2;
 | 
|---|
| 1065 |     pcb := 0;
 | 
|---|
| 1066 |     pBuff := Buffer + cb;
 | 
|---|
| 1067 |     try
 | 
|---|
| 1068 |       if StreamInfo^.Converter <> nil then
 | 
|---|
| 1069 |         pcb := StreamInfo^.Converter.ConvertReadStream(StreamInfo^.Stream, pBuff, cb);
 | 
|---|
| 1070 |       if pcb > 0 then
 | 
|---|
| 1071 |       begin
 | 
|---|
| 1072 |         pBuff[pcb] := #0;
 | 
|---|
| 1073 |         if pBuff[pcb - 1] = #13 then pBuff[pcb - 1] := #0;
 | 
|---|
| 1074 |         pcb := AdjustLineBreaks(Buffer, pBuff);
 | 
|---|
| 1075 |         Move(Buffer^, pbBuff^, pcb);
 | 
|---|
| 1076 |       end;
 | 
|---|
| 1077 |     except
 | 
|---|
| 1078 |       Result := ReadError;
 | 
|---|
| 1079 |     end;
 | 
|---|
| 1080 |   finally
 | 
|---|
| 1081 |     StrDispose(Buffer);
 | 
|---|
| 1082 |   end;
 | 
|---|
| 1083 | end;
 | 
|---|
| 1084 | 
 | 
|---|
| 1085 | procedure TRichEditStrings.LoadFromStream(Stream: TStream);
 | 
|---|
| 1086 | var
 | 
|---|
| 1087 |   EditStream: TEditStream;
 | 
|---|
| 1088 |   Position: Longint;
 | 
|---|
| 1089 |   TextType: Longint;
 | 
|---|
| 1090 |   StreamInfo: TRichEditStreamInfo;
 | 
|---|
| 1091 |   Converter: TConversion;
 | 
|---|
| 1092 | begin
 | 
|---|
| 1093 |   StreamInfo.Stream := Stream;
 | 
|---|
| 1094 |   if FConverter <> nil then Converter := FConverter
 | 
|---|
| 1095 |   else Converter := RichEdit.DefaultConverter.Create;
 | 
|---|
| 1096 |   StreamInfo.Converter := Converter;
 | 
|---|
| 1097 |   try
 | 
|---|
| 1098 |     with EditStream do
 | 
|---|
| 1099 |     begin
 | 
|---|
| 1100 |       dwCookie := LongInt(Pointer(@StreamInfo));
 | 
|---|
| 1101 |       pfnCallBack := @StreamLoad;
 | 
|---|
| 1102 |       dwError := 0;
 | 
|---|
| 1103 |     end;
 | 
|---|
| 1104 |     Position := Stream.Position;
 | 
|---|
| 1105 | 
 | 
|---|
| 1106 |     if PlainText then TextType := SF_TEXT
 | 
|---|
| 1107 |     else TextType := SF_RTF;
 | 
|---|
| 1108 |     SendMessage(RichEdit.Handle, EM_STREAMIN, TextType, Longint(@EditStream));
 | 
|---|
| 1109 | 
 | 
|---|
| 1110 |     if (TextType = SF_RTF) and (EditStream.dwError <> 0) then
 | 
|---|
| 1111 |     begin
 | 
|---|
| 1112 |       Stream.Position := Position;
 | 
|---|
| 1113 |       if PlainText then TextType := SF_RTF
 | 
|---|
| 1114 |       else TextType := SF_TEXT;
 | 
|---|
| 1115 |       SendMessage(RichEdit.Handle, EM_STREAMIN, TextType, Longint(@EditStream));
 | 
|---|
| 1116 |       if EditStream.dwError <> 0 then
 | 
|---|
| 1117 |         raise EOutOfResources.Create(sRichEditLoadFail);
 | 
|---|
| 1118 |     end;
 | 
|---|
| 1119 | 
 | 
|---|
| 1120 |   finally
 | 
|---|
| 1121 |     if FConverter = nil then Converter.Free;
 | 
|---|
| 1122 |   end;
 | 
|---|
| 1123 | end;
 | 
|---|
| 1124 | 
 | 
|---|
| 1125 | procedure TRichEditStrings.SaveToStream(Stream: TStream);
 | 
|---|
| 1126 | var
 | 
|---|
| 1127 |   EditStream: TEditStream;
 | 
|---|
| 1128 |   TextType: Longint;
 | 
|---|
| 1129 |   StreamInfo: TRichEditStreamInfo;
 | 
|---|
| 1130 |   Converter: TConversion;
 | 
|---|
| 1131 | begin
 | 
|---|
| 1132 |   if FConverter <> nil then Converter := FConverter
 | 
|---|
| 1133 |   else Converter := RichEdit.DefaultConverter.Create;
 | 
|---|
| 1134 |   StreamInfo.Stream := Stream;
 | 
|---|
| 1135 |   StreamInfo.Converter := Converter;
 | 
|---|
| 1136 |   try
 | 
|---|
| 1137 |     with EditStream do
 | 
|---|
| 1138 |     begin
 | 
|---|
| 1139 |       dwCookie := LongInt(Pointer(@StreamInfo));
 | 
|---|
| 1140 |       pfnCallBack := @StreamSave;
 | 
|---|
| 1141 |       dwError := 0;
 | 
|---|
| 1142 |     end;
 | 
|---|
| 1143 |     if PlainText then TextType := SF_TEXT
 | 
|---|
| 1144 |     else TextType := SF_RTF;
 | 
|---|
| 1145 |     SendMessage(RichEdit.Handle, EM_STREAMOUT, TextType, Longint(@EditStream));
 | 
|---|
| 1146 |     if EditStream.dwError <> 0 then
 | 
|---|
| 1147 |       raise EOutOfResources.Create(sRichEditSaveFail);
 | 
|---|
| 1148 |   finally
 | 
|---|
| 1149 |     if FConverter = nil then Converter.Free;
 | 
|---|
| 1150 |   end;
 | 
|---|
| 1151 | end;
 | 
|---|
| 1152 | 
 | 
|---|
| 1153 | procedure TRichEditStrings.LoadFromFile(const FileName: string);
 | 
|---|
| 1154 | var
 | 
|---|
| 1155 |   Ext: string;
 | 
|---|
| 1156 |   Convert: PConversionFormat;
 | 
|---|
| 1157 | begin
 | 
|---|
| 1158 |   Ext := AnsiLowerCaseFileName(ExtractFileExt(Filename));
 | 
|---|
| 1159 |   System.Delete(Ext, 1, 1);
 | 
|---|
| 1160 |   Convert := ConversionFormatList;
 | 
|---|
| 1161 |   while Convert <> nil do
 | 
|---|
| 1162 |     with Convert^ do
 | 
|---|
| 1163 |       if Extension <> Ext then Convert := Next
 | 
|---|
| 1164 |       else Break;
 | 
|---|
| 1165 |   if Convert = nil then
 | 
|---|
| 1166 |     Convert := @TextConversionFormat;
 | 
|---|
| 1167 |   if FConverter = nil then FConverter := Convert^.ConversionClass.Create;
 | 
|---|
| 1168 |   try
 | 
|---|
| 1169 |     inherited LoadFromFile(FileName);
 | 
|---|
| 1170 |   except
 | 
|---|
| 1171 |     FConverter.Free;
 | 
|---|
| 1172 |     FConverter := nil;
 | 
|---|
| 1173 |     raise;
 | 
|---|
| 1174 |   end;
 | 
|---|
| 1175 |   RichEdit.DoSetMaxLength($7FFFFFF0);
 | 
|---|
| 1176 | end;
 | 
|---|
| 1177 | 
 | 
|---|
| 1178 | procedure TRichEditStrings.SaveToFile(const FileName: string);
 | 
|---|
| 1179 | var
 | 
|---|
| 1180 |   Ext: string;
 | 
|---|
| 1181 |   Convert: PConversionFormat;
 | 
|---|
| 1182 | begin
 | 
|---|
| 1183 |   Ext := AnsiLowerCaseFileName(ExtractFileExt(Filename));
 | 
|---|
| 1184 |   System.Delete(Ext, 1, 1);
 | 
|---|
| 1185 |   Convert := ConversionFormatList;
 | 
|---|
| 1186 |   while Convert <> nil do
 | 
|---|
| 1187 |     with Convert^ do
 | 
|---|
| 1188 |       if Extension <> Ext then Convert := Next
 | 
|---|
| 1189 |       else Break;
 | 
|---|
| 1190 |   if Convert = nil then
 | 
|---|
| 1191 |     Convert := @TextConversionFormat;
 | 
|---|
| 1192 |   if FConverter = nil then FConverter := Convert^.ConversionClass.Create;
 | 
|---|
| 1193 |   try
 | 
|---|
| 1194 |     inherited SaveToFile(FileName);
 | 
|---|
| 1195 |   except
 | 
|---|
| 1196 |     FConverter.Free;
 | 
|---|
| 1197 |     FConverter := nil;
 | 
|---|
| 1198 |     raise;
 | 
|---|
| 1199 |   end;
 | 
|---|
| 1200 | end;
 | 
|---|
| 1201 | 
 | 
|---|
| 1202 | { TRichEdit }
 | 
|---|
| 1203 | 
 | 
|---|
| 1204 | constructor TXWBCustomRichEdit.Create(AOwner: TComponent);
 | 
|---|
| 1205 | var
 | 
|---|
| 1206 |   DC: HDC;
 | 
|---|
| 1207 | begin
 | 
|---|
| 1208 |   inherited Create(AOwner);
 | 
|---|
| 1209 |   FSelAttributes := TXWBTextAttributes.Create(Self, atSelected);
 | 
|---|
| 1210 |   FDefAttributes := TXWBTextAttributes.Create(Self, atDefaultText);
 | 
|---|
| 1211 |   FParagraph := TParaAttributes.Create(Self);
 | 
|---|
| 1212 |   FRichEditStrings := TRichEditStrings.Create;
 | 
|---|
| 1213 |   TRichEditStrings(FRichEditStrings).RichEdit := Self;
 | 
|---|
| 1214 |   TabStop := True;
 | 
|---|
| 1215 |   Width := 185;
 | 
|---|
| 1216 |   Height := 89;
 | 
|---|
| 1217 |   AutoSize := False;
 | 
|---|
| 1218 |   DoubleBuffered := False;
 | 
|---|
| 1219 |   FHideSelection := True;
 | 
|---|
| 1220 |   FURLDetect:= FALSE;
 | 
|---|
| 1221 |   HideScrollBars := True;
 | 
|---|
| 1222 | 
 | 
|---|
| 1223 |   DC := GetDC(0);
 | 
|---|
| 1224 |   FScreenLogPixels := GetDeviceCaps(DC, LOGPIXELSY);
 | 
|---|
| 1225 |   DefaultConverter := TConversion;
 | 
|---|
| 1226 |   ReleaseDC(0, DC);
 | 
|---|
| 1227 |   FOldParaAlignment := Alignment;
 | 
|---|
| 1228 |   Perform(CM_PARENTBIDIMODECHANGED, 0, 0);
 | 
|---|
| 1229 | end;
 | 
|---|
| 1230 | 
 | 
|---|
| 1231 | destructor TXWBCustomRichEdit.Destroy;
 | 
|---|
| 1232 | begin
 | 
|---|
| 1233 |   FSelAttributes.Free;
 | 
|---|
| 1234 |   FDefAttributes.Free;
 | 
|---|
| 1235 |   FParagraph.Free;
 | 
|---|
| 1236 |   FRichEditStrings.Free;
 | 
|---|
| 1237 |   FMemStream.Free;
 | 
|---|
| 1238 |   inherited Destroy;
 | 
|---|
| 1239 | end;
 | 
|---|
| 1240 | 
 | 
|---|
| 1241 | procedure TXWBCustomRichEdit.Clear;
 | 
|---|
| 1242 | begin
 | 
|---|
| 1243 |   inherited Clear;
 | 
|---|
| 1244 |   Modified := False;
 | 
|---|
| 1245 | end;
 | 
|---|
| 1246 | 
 | 
|---|
| 1247 | procedure TXWBCustomRichEdit.CreateParams(var Params: TCreateParams);
 | 
|---|
| 1248 | const
 | 
|---|
| 1249 | // Use version 2.0 of RichEdit, previously RICHED32.DLL
 | 
|---|
| 1250 |   RichEditModuleName = 'RICHED20.DLL';
 | 
|---|
| 1251 | 
 | 
|---|
| 1252 |   HideScrollBar : array[Boolean] of DWORD = (ES_DISABLENOSCROLL, 0);
 | 
|---|
| 1253 |   HideSelections: array[Boolean] of DWORD = (ES_NOHIDESEL, 0);
 | 
|---|
| 1254 | 
 | 
|---|
| 1255 | begin
 | 
|---|
| 1256 |   if FRichEditModule = 0 then
 | 
|---|
| 1257 |   begin
 | 
|---|
| 1258 |     FRichEditModule := LoadLibrary(RichEditModuleName);
 | 
|---|
| 1259 |     if FRichEditModule <= HINSTANCE_ERROR then FRichEditModule := 0;
 | 
|---|
| 1260 |   end;
 | 
|---|
| 1261 | 
 | 
|---|
| 1262 |   inherited CreateParams(Params);
 | 
|---|
| 1263 | 
 | 
|---|
| 1264 | // USE RICHEDIT_CLASSA use ANSI version not Unicode
 | 
|---|
| 1265 |   CreateSubClass(Params, RICHEDIT_CLASSA);
 | 
|---|
| 1266 | 
 | 
|---|
| 1267 |   with Params do
 | 
|---|
| 1268 |   begin
 | 
|---|
| 1269 |     Style := Style or HideScrollBar[HideScrollBars] or
 | 
|---|
| 1270 |       HideSelections[HideSelection];
 | 
|---|
| 1271 |     WindowClass.style := WindowClass.style and not (CS_HREDRAW or CS_VREDRAW);
 | 
|---|
| 1272 |   end;
 | 
|---|
| 1273 | end;
 | 
|---|
| 1274 | 
 | 
|---|
| 1275 | procedure TXWBCustomRichEdit.CreateWnd;
 | 
|---|
| 1276 | var
 | 
|---|
| 1277 |   Plain, DesignMode, WasModified: Boolean;
 | 
|---|
| 1278 | 
 | 
|---|
| 1279 | begin
 | 
|---|
| 1280 |   WasModified := inherited Modified;
 | 
|---|
| 1281 | 
 | 
|---|
| 1282 |   inherited CreateWnd;
 | 
|---|
| 1283 |   if (SysLocale.FarEast) and not (SysLocale.PriLangID = LANG_JAPANESE) then
 | 
|---|
| 1284 |     Font.Charset := GetDefFontCharSet;
 | 
|---|
| 1285 |   SendMessage(Handle, EM_SETEVENTMASK, 0,
 | 
|---|
| 1286 |     ENM_CHANGE or ENM_SELCHANGE or ENM_REQUESTRESIZE or
 | 
|---|
| 1287 |     ENM_PROTECTED or ENM_LINK);      // Added the ENM_LINK to receive EN_LINK message
 | 
|---|
| 1288 | 
 | 
|---|
| 1289 |   SendMessage(Handle, EM_AUTOURLDETECT, Ord(FURLDetect), 0); // Start the URL Detect
 | 
|---|
| 1290 | 
 | 
|---|
| 1291 |   SendMessage(Handle, EM_SETBKGNDCOLOR, 0, ColorToRGB(Color));
 | 
|---|
| 1292 |   if FMemStream <> nil then
 | 
|---|
| 1293 |   begin
 | 
|---|
| 1294 |     Plain := PlainText;
 | 
|---|
| 1295 |     FMemStream.ReadBuffer(DesignMode, sizeof(DesignMode));
 | 
|---|
| 1296 |     PlainText := DesignMode;
 | 
|---|
| 1297 |     try
 | 
|---|
| 1298 |       Lines.LoadFromStream(FMemStream);
 | 
|---|
| 1299 |       FMemStream.Free;
 | 
|---|
| 1300 |       FMemStream := nil;
 | 
|---|
| 1301 |     finally
 | 
|---|
| 1302 |       PlainText := Plain;
 | 
|---|
| 1303 |     end;
 | 
|---|
| 1304 |   end;
 | 
|---|
| 1305 | 
 | 
|---|
| 1306 |   Modified := WasModified;
 | 
|---|
| 1307 | end;
 | 
|---|
| 1308 | 
 | 
|---|
| 1309 | procedure TXWBCustomRichEdit.DestroyWnd;
 | 
|---|
| 1310 | var
 | 
|---|
| 1311 |   Plain, DesignMode: Boolean;
 | 
|---|
| 1312 | begin
 | 
|---|
| 1313 |   FModified := Modified;
 | 
|---|
| 1314 |   FMemStream := TMemoryStream.Create;
 | 
|---|
| 1315 |   Plain := PlainText;
 | 
|---|
| 1316 |   DesignMode := (csDesigning in ComponentState);
 | 
|---|
| 1317 |   PlainText := DesignMode;
 | 
|---|
| 1318 |   FMemStream.WriteBuffer(DesignMode, sizeof(DesignMode));
 | 
|---|
| 1319 |   try
 | 
|---|
| 1320 |     Lines.SaveToStream(FMemStream);
 | 
|---|
| 1321 |     FMemStream.Position := 0;
 | 
|---|
| 1322 |   finally
 | 
|---|
| 1323 |     PlainText := Plain;
 | 
|---|
| 1324 |   end;
 | 
|---|
| 1325 | 
 | 
|---|
| 1326 |   inherited DestroyWnd;
 | 
|---|
| 1327 | end;
 | 
|---|
| 1328 | 
 | 
|---|
| 1329 | procedure TXWBCustomRichEdit.WMNCDestroy(var Message: TWMNCDestroy);
 | 
|---|
| 1330 | begin
 | 
|---|
| 1331 |   inherited;
 | 
|---|
| 1332 | end;
 | 
|---|
| 1333 | 
 | 
|---|
| 1334 | procedure TXWBCustomRichEdit.WMSetFont(var Message: TWMSetFont);
 | 
|---|
| 1335 | begin
 | 
|---|
| 1336 |   FDefAttributes.Assign(Font);
 | 
|---|
| 1337 | end;
 | 
|---|
| 1338 | 
 | 
|---|
| 1339 | procedure TXWBCustomRichEdit.WMRButtonUp(var Message: TWMRButtonUp);
 | 
|---|
| 1340 | begin
 | 
|---|
| 1341 |   // RichEd20 does not pass the WM_RBUTTONUP message to defwndproc,
 | 
|---|
| 1342 |   // so we get no WM_CONTEXTMENU message.  Simulate message here.
 | 
|---|
| 1343 |   if Win32MajorVersion < 5 then
 | 
|---|
| 1344 |     Perform(WM_CONTEXTMENU, Handle, LParam(PointToSmallPoint(
 | 
|---|
| 1345 |       ClientToScreen(SmallPointToPoint(Message.Pos)))));
 | 
|---|
| 1346 |   inherited;
 | 
|---|
| 1347 | end;
 | 
|---|
| 1348 | 
 | 
|---|
| 1349 | procedure TXWBCustomRichEdit.CMFontChanged(var Message: TMessage);
 | 
|---|
| 1350 | begin
 | 
|---|
| 1351 |   FDefAttributes.Assign(Font);
 | 
|---|
| 1352 | end;
 | 
|---|
| 1353 | 
 | 
|---|
| 1354 | procedure TXWBCustomRichEdit.DoSetMaxLength(Value: Integer);
 | 
|---|
| 1355 | begin
 | 
|---|
| 1356 |   SendMessage(Handle, EM_EXLIMITTEXT, 0, Value);
 | 
|---|
| 1357 | end;
 | 
|---|
| 1358 | 
 | 
|---|
| 1359 | function TXWBCustomRichEdit.GetCaretPos;
 | 
|---|
| 1360 | var
 | 
|---|
| 1361 |   CharRange: TCharRange;
 | 
|---|
| 1362 | begin
 | 
|---|
| 1363 |   SendMessage(Handle, EM_EXGETSEL, 0, LongInt(@CharRange));
 | 
|---|
| 1364 |   Result.X := CharRange.cpMax;
 | 
|---|
| 1365 |   Result.Y := SendMessage(Handle, EM_EXLINEFROMCHAR, 0, Result.X);
 | 
|---|
| 1366 |   Result.X := Result.X - SendMessage(Handle, EM_LINEINDEX, -1, 0);
 | 
|---|
| 1367 | end;
 | 
|---|
| 1368 | 
 | 
|---|
| 1369 | function TXWBCustomRichEdit.GetSelLength: Integer;
 | 
|---|
| 1370 | var
 | 
|---|
| 1371 |   CharRange: TCharRange;
 | 
|---|
| 1372 | begin
 | 
|---|
| 1373 |   SendMessage(Handle, EM_EXGETSEL, 0, Longint(@CharRange));
 | 
|---|
| 1374 |   Result := CharRange.cpMax - CharRange.cpMin;
 | 
|---|
| 1375 | end;
 | 
|---|
| 1376 | 
 | 
|---|
| 1377 | function TXWBCustomRichEdit.GetSelStart: Integer;
 | 
|---|
| 1378 | var
 | 
|---|
| 1379 |   CharRange: TCharRange;
 | 
|---|
| 1380 | begin
 | 
|---|
| 1381 |   SendMessage(Handle, EM_EXGETSEL, 0, Longint(@CharRange));
 | 
|---|
| 1382 |   Result := CharRange.cpMin;
 | 
|---|
| 1383 | end;
 | 
|---|
| 1384 | 
 | 
|---|
| 1385 | function TXWBCustomRichEdit.GetSelTextBuf(Buffer: PChar; BufSize: Integer): Integer;
 | 
|---|
| 1386 | var
 | 
|---|
| 1387 |   S: string;
 | 
|---|
| 1388 | begin
 | 
|---|
| 1389 |   S := GetSelText;
 | 
|---|
| 1390 |   Result := Length(S);
 | 
|---|
| 1391 |   if BufSize < Length(S) then Result := BufSize;
 | 
|---|
| 1392 |   StrPLCopy(Buffer, S, Result);
 | 
|---|
| 1393 | end;
 | 
|---|
| 1394 | 
 | 
|---|
| 1395 | function TXWBCustomRichEdit.GetSelText: string;
 | 
|---|
| 1396 | var
 | 
|---|
| 1397 |   Length: Integer;
 | 
|---|
| 1398 | begin
 | 
|---|
| 1399 |   SetLength(Result, GetSelLength + 1);
 | 
|---|
| 1400 |   Length := SendMessage(Handle, EM_GETSELTEXT, 0, Longint(PChar(Result)));
 | 
|---|
| 1401 |   SetLength(Result, Length);
 | 
|---|
| 1402 | end;
 | 
|---|
| 1403 | 
 | 
|---|
| 1404 | procedure TXWBCustomRichEdit.CMBiDiModeChanged(var Message: TMessage);
 | 
|---|
| 1405 | var
 | 
|---|
| 1406 |   AParagraph: TParaFormat;
 | 
|---|
| 1407 | begin
 | 
|---|
| 1408 |   HandleNeeded; { we REALLY need the handle for BiDi }
 | 
|---|
| 1409 |   inherited;
 | 
|---|
| 1410 |   Paragraph.GetAttributes(AParagraph);
 | 
|---|
| 1411 |   AParagraph.dwMask := PFM_ALIGNMENT;
 | 
|---|
| 1412 |   AParagraph.wAlignment := Ord(Alignment) + 1;
 | 
|---|
| 1413 |   Paragraph.SetAttributes(AParagraph);
 | 
|---|
| 1414 | end;
 | 
|---|
| 1415 | 
 | 
|---|
| 1416 | procedure TXWBCustomRichEdit.SetHideScrollBars(Value: Boolean);
 | 
|---|
| 1417 | begin
 | 
|---|
| 1418 |   if HideScrollBars <> Value then
 | 
|---|
| 1419 |   begin
 | 
|---|
| 1420 |     FHideScrollBars := value;
 | 
|---|
| 1421 |     RecreateWnd;
 | 
|---|
| 1422 |   end;
 | 
|---|
| 1423 | end;
 | 
|---|
| 1424 | 
 | 
|---|
| 1425 | procedure TXWBCustomRichEdit.SetHideSelection(Value: Boolean);
 | 
|---|
| 1426 | begin
 | 
|---|
| 1427 |   if HideSelection <> Value then
 | 
|---|
| 1428 |   begin
 | 
|---|
| 1429 |     FHideSelection := Value;
 | 
|---|
| 1430 |     SendMessage(Handle, EM_HIDESELECTION, Ord(HideSelection), LongInt(True));
 | 
|---|
| 1431 |   end;
 | 
|---|
| 1432 | end;
 | 
|---|
| 1433 | 
 | 
|---|
| 1434 | procedure TXWBCustomRichEdit.SetURLDetect(Value: boolean);
 | 
|---|
| 1435 | begin
 | 
|---|
| 1436 |  if URLDetect <> Value then
 | 
|---|
| 1437 |   begin
 | 
|---|
| 1438 |    FURLDetect:= Value;
 | 
|---|
| 1439 |    RecreateWnd;
 | 
|---|
| 1440 |   end;
 | 
|---|
| 1441 | end;
 | 
|---|
| 1442 | 
 | 
|---|
| 1443 | procedure TXWBCustomRichEdit.SetSelAttributes(Value: TXWBTextAttributes);
 | 
|---|
| 1444 | begin
 | 
|---|
| 1445 |   SelAttributes.Assign(Value);
 | 
|---|
| 1446 | end;
 | 
|---|
| 1447 | 
 | 
|---|
| 1448 | procedure TXWBCustomRichEdit.SetSelLength(Value: Integer);
 | 
|---|
| 1449 | var
 | 
|---|
| 1450 |   CharRange: TCharRange;
 | 
|---|
| 1451 | begin
 | 
|---|
| 1452 |   SendMessage(Handle, EM_EXGETSEL, 0, Longint(@CharRange));
 | 
|---|
| 1453 |   CharRange.cpMax := CharRange.cpMin + Value;
 | 
|---|
| 1454 |   SendMessage(Handle, EM_EXSETSEL, 0, Longint(@CharRange));
 | 
|---|
| 1455 |   SendMessage(Handle, EM_SCROLLCARET, 0, 0);
 | 
|---|
| 1456 | end;
 | 
|---|
| 1457 | 
 | 
|---|
| 1458 | procedure TXWBCustomRichEdit.SetDefAttributes(Value: TXWBTextAttributes);
 | 
|---|
| 1459 | begin
 | 
|---|
| 1460 |   DefAttributes.Assign(Value);
 | 
|---|
| 1461 | end;
 | 
|---|
| 1462 | 
 | 
|---|
| 1463 | function TXWBCustomRichEdit.GetPlainText: Boolean;
 | 
|---|
| 1464 | begin
 | 
|---|
| 1465 |   Result := TRichEditStrings(Lines).PlainText;
 | 
|---|
| 1466 | end;
 | 
|---|
| 1467 | 
 | 
|---|
| 1468 | procedure TXWBCustomRichEdit.SetPlainText(Value: Boolean);
 | 
|---|
| 1469 | begin
 | 
|---|
| 1470 |   TRichEditStrings(Lines).PlainText := Value;
 | 
|---|
| 1471 | end;
 | 
|---|
| 1472 | 
 | 
|---|
| 1473 | procedure TXWBCustomRichEdit.CMColorChanged(var Message: TMessage);
 | 
|---|
| 1474 | begin
 | 
|---|
| 1475 |   inherited;
 | 
|---|
| 1476 |   SendMessage(Handle, EM_SETBKGNDCOLOR, 0, ColorToRGB(Color))
 | 
|---|
| 1477 | end;
 | 
|---|
| 1478 | 
 | 
|---|
| 1479 | procedure TXWBCustomRichEdit.SetRichEditStrings(Value: TStrings);
 | 
|---|
| 1480 | begin
 | 
|---|
| 1481 |   FRichEditStrings.Assign(Value);
 | 
|---|
| 1482 | end;
 | 
|---|
| 1483 | 
 | 
|---|
| 1484 | procedure TXWBCustomRichEdit.SetSelStart(Value: Integer);
 | 
|---|
| 1485 | var
 | 
|---|
| 1486 |   CharRange: TCharRange;
 | 
|---|
| 1487 | begin
 | 
|---|
| 1488 |   CharRange.cpMin := Value;
 | 
|---|
| 1489 |   CharRange.cpMax := Value;
 | 
|---|
| 1490 |   SendMessage(Handle, EM_EXSETSEL, 0, Longint(@CharRange));
 | 
|---|
| 1491 | end;
 | 
|---|
| 1492 | 
 | 
|---|
| 1493 | procedure TXWBCustomRichEdit.Print(const Caption: string);
 | 
|---|
| 1494 | var
 | 
|---|
| 1495 |   Range: TFormatRange;
 | 
|---|
| 1496 |   LastChar, MaxLen, LogX, LogY, OldMap: Integer;
 | 
|---|
| 1497 |   SaveRect: TRect;
 | 
|---|
| 1498 | begin
 | 
|---|
| 1499 |   FillChar(Range, SizeOf(TFormatRange), 0);
 | 
|---|
| 1500 |   with Printer, Range do
 | 
|---|
| 1501 |   begin
 | 
|---|
| 1502 |     Title := Caption;
 | 
|---|
| 1503 |     BeginDoc;
 | 
|---|
| 1504 |     hdc := Handle;
 | 
|---|
| 1505 |     hdcTarget := hdc;
 | 
|---|
| 1506 |     LogX := GetDeviceCaps(Handle, LOGPIXELSX);
 | 
|---|
| 1507 |     LogY := GetDeviceCaps(Handle, LOGPIXELSY);
 | 
|---|
| 1508 |     if IsRectEmpty(PageRect) then
 | 
|---|
| 1509 |     begin
 | 
|---|
| 1510 |       rc.right := PageWidth * 1440 div LogX;
 | 
|---|
| 1511 |       rc.bottom := PageHeight * 1440 div LogY;
 | 
|---|
| 1512 |     end
 | 
|---|
| 1513 |     else begin
 | 
|---|
| 1514 |       rc.left := PageRect.Left * 1440 div LogX;
 | 
|---|
| 1515 |       rc.top := PageRect.Top * 1440 div LogY;
 | 
|---|
| 1516 |       rc.right := PageRect.Right * 1440 div LogX;
 | 
|---|
| 1517 |       rc.bottom := PageRect.Bottom * 1440 div LogY;
 | 
|---|
| 1518 |     end;
 | 
|---|
| 1519 |     rcPage := rc;
 | 
|---|
| 1520 |     SaveRect := rc;
 | 
|---|
| 1521 |     LastChar := 0;
 | 
|---|
| 1522 |     MaxLen := GetTextLen;
 | 
|---|
| 1523 |     chrg.cpMax := -1;
 | 
|---|
| 1524 |     // ensure printer DC is in text map mode
 | 
|---|
| 1525 |     OldMap := SetMapMode(hdc, MM_TEXT);
 | 
|---|
| 1526 |     SendMessage(Self.Handle, EM_FORMATRANGE, 0, 0);    // flush buffer
 | 
|---|
| 1527 |     try
 | 
|---|
| 1528 |       repeat
 | 
|---|
| 1529 |         rc := SaveRect;
 | 
|---|
| 1530 |         chrg.cpMin := LastChar;
 | 
|---|
| 1531 |         LastChar := SendMessage(Self.Handle, EM_FORMATRANGE, 1, Longint(@Range));
 | 
|---|
| 1532 |         if (LastChar < MaxLen) and (LastChar <> -1) then NewPage;
 | 
|---|
| 1533 |       until (LastChar >= MaxLen) or (LastChar = -1);
 | 
|---|
| 1534 |       EndDoc;
 | 
|---|
| 1535 |     finally
 | 
|---|
| 1536 |       SendMessage(Self.Handle, EM_FORMATRANGE, 0, 0);  // flush buffer
 | 
|---|
| 1537 |       SetMapMode(hdc, OldMap);       // restore previous map mode
 | 
|---|
| 1538 |     end;
 | 
|---|
| 1539 |   end;
 | 
|---|
| 1540 | end;
 | 
|---|
| 1541 | 
 | 
|---|
| 1542 | var
 | 
|---|
| 1543 |   Painting: Boolean = False;
 | 
|---|
| 1544 | 
 | 
|---|
| 1545 | procedure TXWBCustomRichEdit.WMPaint(var Message: TWMPaint);
 | 
|---|
| 1546 | var
 | 
|---|
| 1547 |   R, R1: TRect;
 | 
|---|
| 1548 | begin
 | 
|---|
| 1549 |   if GetUpdateRect(Handle, R, True) then
 | 
|---|
| 1550 |   begin
 | 
|---|
| 1551 |     with ClientRect do R1 := Rect(Right - 3, Top, Right, Bottom);
 | 
|---|
| 1552 |     if IntersectRect(R, R, R1) then InvalidateRect(Handle, @R1, True);
 | 
|---|
| 1553 |   end;
 | 
|---|
| 1554 |   if Painting then
 | 
|---|
| 1555 |     Invalidate
 | 
|---|
| 1556 |   else begin
 | 
|---|
| 1557 |     Painting := True;
 | 
|---|
| 1558 |     try
 | 
|---|
| 1559 |       inherited;
 | 
|---|
| 1560 |     finally
 | 
|---|
| 1561 |       Painting := False;
 | 
|---|
| 1562 |     end;
 | 
|---|
| 1563 |   end;
 | 
|---|
| 1564 | end;
 | 
|---|
| 1565 | 
 | 
|---|
| 1566 | procedure TXWBCustomRichEdit.WMSetCursor(var Message: TWMSetCursor);
 | 
|---|
| 1567 | var
 | 
|---|
| 1568 |   P: TPoint;
 | 
|---|
| 1569 | begin
 | 
|---|
| 1570 |   inherited;
 | 
|---|
| 1571 |   if Message.Result = 0 then
 | 
|---|
| 1572 |   begin
 | 
|---|
| 1573 |     Message.Result := 1;
 | 
|---|
| 1574 |     GetCursorPos(P);
 | 
|---|
| 1575 |     with PointToSmallPoint(P) do
 | 
|---|
| 1576 |       case Perform(WM_NCHITTEST, 0, MakeLong(X, Y)) of
 | 
|---|
| 1577 |         HTVSCROLL,
 | 
|---|
| 1578 |         HTHSCROLL:
 | 
|---|
| 1579 |           Windows.SetCursor(Screen.Cursors[crArrow]);
 | 
|---|
| 1580 |         HTCLIENT:
 | 
|---|
| 1581 |           Windows.SetCursor(Screen.Cursors[crIBeam]);
 | 
|---|
| 1582 |       end;
 | 
|---|
| 1583 |   end;
 | 
|---|
| 1584 | end;
 | 
|---|
| 1585 | 
 | 
|---|
| 1586 | procedure TXWBCustomRichEdit.CNNotify(var Message: TWMNotify);
 | 
|---|
| 1587 | type
 | 
|---|
| 1588 |   PENLink = ^TENLink;
 | 
|---|
| 1589 | 
 | 
|---|
| 1590 | begin
 | 
|---|
| 1591 |   with Message do
 | 
|---|
| 1592 |     case NMHdr^.code of
 | 
|---|
| 1593 |       EN_SELCHANGE: SelectionChange;
 | 
|---|
| 1594 |       EN_REQUESTRESIZE: RequestSize(PReqSize(NMHdr)^.rc);
 | 
|---|
| 1595 |       EN_SAVECLIPBOARD:
 | 
|---|
| 1596 |         with PENSaveClipboard(NMHdr)^ do
 | 
|---|
| 1597 |           if not SaveClipboard(cObjectCount, cch) then Result := 1;
 | 
|---|
| 1598 |       EN_PROTECTED:
 | 
|---|
| 1599 |         with PENProtected(NMHdr)^.chrg do
 | 
|---|
| 1600 |           if not ProtectChange(cpMin, cpMax) then Result := 1;
 | 
|---|
| 1601 | 
 | 
|---|
| 1602 | // EN_LINK message being received to respond to it
 | 
|---|
| 1603 |       EN_LINK:
 | 
|---|
| 1604 |        begin
 | 
|---|
| 1605 |         Windows.SetCursor(Screen.Cursors[crHandPoint]);
 | 
|---|
| 1606 |         if PEnLink(NMHdr)^.msg = WM_LBUTTONDOWN then
 | 
|---|
| 1607 |           begin
 | 
|---|
| 1608 | // set the selection
 | 
|---|
| 1609 |             SendMessage(Handle, EM_EXSETSEL, 0, Longint(@PEnLink(NMHdr)^.chrg));
 | 
|---|
| 1610 | // send it to windows to open
 | 
|---|
| 1611 |             ShellExecute(handle, 'open', PChar(GetSelText), nil, nil, SW_SHOWNORMAL);
 | 
|---|
| 1612 |           end;
 | 
|---|
| 1613 |        end;
 | 
|---|
| 1614 |     end;
 | 
|---|
| 1615 | end;
 | 
|---|
| 1616 | 
 | 
|---|
| 1617 | function TXWBCustomRichEdit.SaveClipboard(NumObj, NumChars: Integer): Boolean;
 | 
|---|
| 1618 | begin
 | 
|---|
| 1619 |   Result := True;
 | 
|---|
| 1620 |   if Assigned(OnSaveClipboard) then OnSaveClipboard(Self, NumObj, NumChars, Result);
 | 
|---|
| 1621 | end;
 | 
|---|
| 1622 | 
 | 
|---|
| 1623 | function TXWBCustomRichEdit.ProtectChange(StartPos, EndPos: Integer): Boolean;
 | 
|---|
| 1624 | begin
 | 
|---|
| 1625 |   Result := False;
 | 
|---|
| 1626 |   if Assigned(OnProtectChange) then OnProtectChange(Self, StartPos, EndPos, Result);
 | 
|---|
| 1627 | end;
 | 
|---|
| 1628 | 
 | 
|---|
| 1629 | procedure TXWBCustomRichEdit.SelectionChange;
 | 
|---|
| 1630 | begin
 | 
|---|
| 1631 |   if Assigned(OnSelectionChange) then OnSelectionChange(Self);
 | 
|---|
| 1632 | end;
 | 
|---|
| 1633 | 
 | 
|---|
| 1634 | procedure TXWBCustomRichEdit.RequestSize(const Rect: TRect);
 | 
|---|
| 1635 | begin
 | 
|---|
| 1636 |   if Assigned(OnResizeRequest) then OnResizeRequest(Self, Rect);
 | 
|---|
| 1637 | end;
 | 
|---|
| 1638 | 
 | 
|---|
| 1639 | function TXWBCustomRichEdit.FindText(const SearchStr: string;
 | 
|---|
| 1640 |   StartPos, Length: Integer; Options: TSearchTypes): Integer;
 | 
|---|
| 1641 | var
 | 
|---|
| 1642 |   Find: TFindText;
 | 
|---|
| 1643 |   Flags: Integer;
 | 
|---|
| 1644 | begin
 | 
|---|
| 1645 |   with Find.chrg do
 | 
|---|
| 1646 |   begin
 | 
|---|
| 1647 |     cpMin := StartPos;
 | 
|---|
| 1648 |     cpMax := cpMin + Length;
 | 
|---|
| 1649 |   end;
 | 
|---|
| 1650 |   Flags := 0;
 | 
|---|
| 1651 |   if stWholeWord in Options then Flags := Flags or FT_WHOLEWORD;
 | 
|---|
| 1652 |   if stMatchCase in Options then Flags := Flags or FT_MATCHCASE;
 | 
|---|
| 1653 |   Find.lpstrText := PChar(SearchStr);
 | 
|---|
| 1654 |   Result := SendMessage(Handle, EM_FINDTEXT, Flags, LongInt(@Find));
 | 
|---|
| 1655 | end;
 | 
|---|
| 1656 | 
 | 
|---|
| 1657 | procedure AppendConversionFormat(const Ext: string; AClass: TConversionClass);
 | 
|---|
| 1658 | var
 | 
|---|
| 1659 |   NewRec: PConversionFormat;
 | 
|---|
| 1660 | begin
 | 
|---|
| 1661 |   New(NewRec);
 | 
|---|
| 1662 |   with NewRec^ do
 | 
|---|
| 1663 |   begin
 | 
|---|
| 1664 |     Extension := AnsiLowerCaseFileName(Ext);
 | 
|---|
| 1665 |     ConversionClass := AClass;
 | 
|---|
| 1666 |     Next := ConversionFormatList;
 | 
|---|
| 1667 |   end;
 | 
|---|
| 1668 |   ConversionFormatList := NewRec;
 | 
|---|
| 1669 | end;
 | 
|---|
| 1670 | 
 | 
|---|
| 1671 | class procedure TXWBCustomRichEdit.RegisterConversionFormat(const AExtension: string;
 | 
|---|
| 1672 |   AConversionClass: TConversionClass);
 | 
|---|
| 1673 | begin
 | 
|---|
| 1674 |   AppendConversionFormat(AExtension, AConversionClass);
 | 
|---|
| 1675 | end;
 | 
|---|
| 1676 | 
 | 
|---|
| 1677 | end.
 | 
|---|
| 1678 | 
 | 
|---|