diff --git a/components/richmemo/richmemo.pas b/components/richmemo/richmemo.pas index 3f99465db..cb8eb563a 100644 --- a/components/richmemo/richmemo.pas +++ b/components/richmemo/richmemo.pas @@ -242,6 +242,8 @@ type function InDelText(const UTF8Text: string; InsStartChar, ReplaceLength: Integer): Integer; virtual; function InDelInline(inlineobj: TRichMemoInline; InsStartChar, ReplaceLength: Integer; const ASize: TSize): Integer; virtual; + function GetText(TextStart, TextLength: Integer): String; + function GetUText(TextStart, TextLength: Integer): UnicodeString; procedure SetSelLengthFor(const aselstr: string); @@ -295,6 +297,7 @@ type property OnKeyDown; property OnKeyPress; property OnKeyUp; + property OnLinkAction; property OnMouseDown; property OnMouseEnter; property OnMouseLeave; @@ -967,6 +970,34 @@ begin inlineObj.Free; end; +function TCustomRichMemo.GetText(TextStart, TextLength: Integer): String; +var + isu : Boolean; + txt : String; + utxt : UnicodeString; +begin + Result:=''; + if not HandleAllocated then HandleNeeded; + if HandleAllocated and not TWSCustomRichMemoClass(WidgetSetClass).GetSubText(Self, TextStart, TextLength, false, isu, txt, utxt) then + Exit; + if isu then Result:=UTF8Decode(utxt) + else Result:=txt; +end; + +function TCustomRichMemo.GetUText(TextStart, TextLength: Integer): UnicodeString; +var + isu : Boolean; + txt : String; + utxt : UnicodeString; +begin + Result:=''; + if not HandleAllocated then HandleNeeded; + if HandleAllocated and not TWSCustomRichMemoClass(WidgetSetClass).GetSubText(Self, TextStart, TextLength, false, isu, txt, utxt) then + Exit; + if isu then Result:=utxt + else Result:=UTF8Encode(txt); +end; + procedure TCustomRichMemo.SetSelLengthFor(const aselstr: string); begin SelLength:=UTF8Length(aselstr); diff --git a/components/richmemo/win32/win32richmemo.pas b/components/richmemo/win32/win32richmemo.pas index f36aa1174..88bf37d54 100644 --- a/components/richmemo/win32/win32richmemo.pas +++ b/components/richmemo/win32/win32richmemo.pas @@ -38,33 +38,25 @@ uses type + { TWin32RichMemoStrings } + TWin32RichMemoStrings = class(TWin32MemoStrings) protected fUpd : Boolean; fHandle : HWND; procedure SetUpdateState(Updating: Boolean); override; + function GetTextStr: string; override; public constructor Create(AHandle: HWND; TheOwner: TWinControl); end; - { TWin32RichMemoStringsW } - - TWin32RichMemoStringsW = class(TWin32RichMemoStrings) - protected - function GetTextStr: string; override; - end; - - { TWin32RichMemoStringsA } - - TWin32RichMemoStringsA = class(TWin32RichMemoStrings) - protected - function GetTextStr: string; override; - end; - { TWin32WSCustomRichMemo } TWin32WSCustomRichMemo = class(TWSCustomRichMemo) published + class function GetText(const AWinControl: TWinControl; var AText: String): Boolean; override; + class function GetTextLen(const AWinControl: TWinControl; var ALength: Integer): Boolean; override; + class function GetStrings(const ACustomMemo: TCustomMemo): TStrings; override; class procedure SetColor(const AWinControl: TWinControl); override; @@ -114,6 +106,8 @@ type var AStopList: TTabStopList): Boolean; override; class procedure InDelText(const AWinControl: TWinControl; const TextUTF8: String; DstStart, DstLen: Integer); override; + class function GetSubText(const AWinControl: TWinControl; TextStart, TextLen: Integer; + AsUnicode: Boolean; var isUnicode: Boolean; var txt: string; var utxt: UnicodeString): Boolean; override; class function Search(const AWinControl: TWinControl; const ANiddle: string; const SearchOpts: TIntSearchOpt): Integer; override; @@ -341,64 +335,39 @@ begin inherited SetUpdateState(Updating); end; -{ TWin32RichMemoStringsW } - -function TWin32RichMemoStringsW.GetTextStr: string; -var - p : GETTEXTLENGTHEX; - t : GETTEXTEX; - res : Integer; - w : WideString; +function TWin32RichMemoStrings.GetTextStr: string; begin - fillchar(p, sizeof(p), 0); - p.flags:=GTL_DEFAULT or GTL_PRECISE or GTL_NUMCHARS; - res := SendMessageW(fHandle, EM_GETTEXTLENGTHEX, WPARAM(@P), CP_WINUNICODE); - if res>0 then begin - SetLength(w, res); - FillChar(t, sizeof(t), 0); - t.cb:=(length(w)+1)*sizeof(WideChar); - t.flags:=GT_DEFAULT; - t.codepage:=CP_WINUNICODE; - res:=SendMessageW(fHandle, EM_GETTEXTEX, WPARAM(@t), LPARAM(@w[1])); - Result:=UTF8Encode(w); - end else - Result:=''; -end; - - -{ TWin32RichMemoStringsA } - -function TWin32RichMemoStringsA.GetTextStr: string; -var - p : GETTEXTLENGTHEX; - t : GETTEXTEX; - res : Integer; - s : WideString; -begin - fillchar(p, sizeof(p), 0); - p.flags:=GTL_DEFAULT or GTL_PRECISE or GTL_NUMBYTES; - res := SendMessageW(fHandle, EM_GETTEXTLENGTHEX, WPARAM(@P), CP_ACP); - if res>0 then begin - SetLength(s, res); - FillChar(t, sizeof(t), 0); - t.cb:=length(s)+1; - t.flags:=GT_DEFAULT; - t.codepage:=CP_ACP; - res:=SendMessageW(fHandle, EM_GETTEXTEX, WPARAM(@t), LPARAM(@s[1])); - Result:=AnsiToUtf8(s); - end else + if Assigned(RichEditManager) then + Result:=RichEditManager.GetTextUtf8(fHandle, false) + else Result:=''; end; { TWin32WSCustomRichMemo } +class function TWin32WSCustomRichMemo.GetText(const AWinControl: TWinControl; + var AText: String): Boolean; +begin + Result:=Assigned(RichEditManager); + if Result then + AText:=RichEditManager.GetTextUtf8(AWinControl.Handle, false); +end; + +class function TWin32WSCustomRichMemo.GetTextLen( + const AWinControl: TWinControl; var ALength: Integer): Boolean; +begin + Result:=false; + ALength:=0; + if not Assigned(RichEditManager) or not Assigned(AWinControl) then Exit; + + Result:=true; + ALength:=RichEditManager.GetTextLength(AWinControl.Handle); +end; + class function TWin32WSCustomRichMemo.GetStrings(const ACustomMemo: TCustomMemo ): TStrings; begin - if UnicodeEnabledOS then - Result := TWin32RichMemoStringsW.Create(ACustomMemo.Handle, ACustomMemo) - else - Result := TWin32RichMemoStringsA.Create(ACustomMemo.Handle, ACustomMemo); + Result := TWin32RichMemoStrings.Create(ACustomMemo.Handle, ACustomMemo) end; class procedure TWin32WSCustomRichMemo.SetColor(const AWinControl: TWinControl); @@ -979,6 +948,44 @@ begin RichEditManager.SetEventMask(AWinControl.Handle, eventmask); end; +class function TWin32WSCustomRichMemo.GetSubText( + const AWinControl: TWinControl; TextStart, TextLen: Integer; + AsUnicode: Boolean; var isUnicode: Boolean; var txt: string; + var utxt: UnicodeString): Boolean; +var + eventmask : Integer; + OrigStart : Integer; + OrigLen : Integer; + NeedLock : Boolean; + Hnd : THandle; +begin + Result:=Assigned(RichEditManager) and Assigned(AWinControl); + if not Result then Exit; + + Hnd:=AWinControl.Handle; + eventmask := RichEditManager.SetEventMask(Hnd, 0); + RichEditManager.GetSelection(Hnd, OrigStart, OrigLen); + + NeedLock := (OrigStart <> TextStart) or (OrigLen <> TextLen); + if NeedLock then begin + LockRedraw( TCustomRichMemo(AWinControl), Hnd); + RichEditManager.SetSelection(Hnd, TextStart, TextLen); + end; + + isUnicode:=AsUnicode; + if AsUnicode then + utxt:=RichEditManager.GetTextW(Hnd, true) + else begin + txt:=RichEditManager.GetTextUtf8(Hnd, true); + end; + + if NeedLock then begin + RichEditManager.SetSelection(Hnd, OrigStart, OrigLen); + UnlockRedraw( TCustomRichMemo(AWinControl), Hnd); + end; + RichEditManager.SetEventMask(Hnd, eventmask); +end; + class function TWin32WSCustomRichMemo.Search(const AWinControl: TWinControl; const ANiddle: string; const SearchOpts: TIntSearchOpt): Integer; begin diff --git a/components/richmemo/win32/win32richmemoproc.pas b/components/richmemo/win32/win32richmemoproc.pas index 5ba61afbe..f4438ebf0 100644 --- a/components/richmemo/win32/win32richmemoproc.pas +++ b/components/richmemo/win32/win32richmemoproc.pas @@ -174,7 +174,12 @@ type class procedure SetHideSelection(RichEditWnd: Handle; AValue: Boolean); virtual; class function LoadRichText(RichEditWnd: Handle; ASrc: TStream): Boolean; virtual; class function SaveRichText(RichEditWnd: Handle; ADst: TStream): Boolean; virtual; + class procedure SetText(RichEditWnd: Handle; const Text: WideString; TextStart, ReplaceLength: Integer); virtual; + class function GetTextW(RichEditWnd: Handle; inSelection: Boolean): WideString; virtual; + class function GetTextA(RichEditWnd: Handle; inSelection: Boolean): AnsiString; virtual; + class function GetTextUtf8(RichEditWnd: Handle; inSelection: Boolean): string; + class procedure GetPara2(RichEditWnd: Handle; TextStart: Integer; var para: PARAFORMAT2); virtual; class procedure SetPara2(RichEditWnd: Handle; TextStart, TextLen: Integer; const para: PARAFORMAT2); virtual; class function Find(RichEditWnd: THandle; const ANiddle: WideString; const ASearch: TIntSearchOpt): Integer; virtual; @@ -192,8 +197,9 @@ function FontStylesToEffects(Styles: TFontStyles): LongWord; function EffectsToFontStyles(Effects: LongWord): TFontStyles; const - CP_UNICODE = 1200; - HardBreak = #13; + GT_SELECTION = 2; + CP_UNICODE = 1200; + HardBreak = #13; const CFE_PROTECTED = $00000010; @@ -643,6 +649,66 @@ begin SetSelection(RichEditWnd, s, l); end; +class function TRichEditManager.GetTextW(RichEditWnd: Handle; + inSelection: Boolean): WideString; +var + t : GETTEXTEX; + res : Integer; + w : WideString; + st : Integer; +begin + if inSelection then + GetSelection(RichEditWnd, st, res) + else + res:=GetTextLength(RichEditWnd); + + if res>0 then begin + SetLength(w, res); + FillChar(t, sizeof(t), 0); + t.cb:=(length(w)+1)*sizeof(WideChar); + t.flags:=GT_DEFAULT; + if inSelection then t.flags:=t.flags or GT_SELECTION; + t.codepage:=CP_WINUNICODE; + res:=SendMessageW(RichEditWnd, EM_GETTEXTEX, WPARAM(@t), LPARAM(@w[1])); + Result:=w; + end else + Result:=''; +end; + +class function TRichEditManager.GetTextA(RichEditWnd: Handle; + inSelection: Boolean): AnsiString; +var + t : GETTEXTEX; + res : Integer; + s : AnsiString; + st : Integer; +begin + if inSelection then + GetSelection(RichEditWnd, st, res) + else + res:=GetTextLength(RichEditWnd); + + if res>0 then begin + SetLength(s, res); + FillChar(t, sizeof(t), 0); + t.cb:=length(s)+1; + t.flags:=GT_DEFAULT; + t.codepage:=CP_ACP; + res:=SendMessageA(RichEditWnd, EM_GETTEXTEX, WPARAM(@t), LPARAM(@s[1])); + Result:=s; + end else + Result:=''; +end; + +class function TRichEditManager.GetTextUtf8(RichEditWnd: Handle; + inSelection: Boolean): string; +begin + if UnicodeEnabledOS then + Result:=UTF8Encode(GetTextW(RichEditWnd, inSelection)) + else + Result:=AnsiToUtf8(GetTextA(RichEditWnd, inSelection)); +end; + class procedure TRichEditManager.GetPara2(RichEditWnd: Handle; TextStart: Integer; var para: PARAFORMAT2); var diff --git a/components/richmemo/wsrichmemo.pas b/components/richmemo/wsrichmemo.pas index 6ee2737e2..13dfec4ac 100644 --- a/components/richmemo/wsrichmemo.pas +++ b/components/richmemo/wsrichmemo.pas @@ -26,6 +26,7 @@ interface uses Types, Classes, SysUtils, LCLType, + LazUTF8, // used for GetSubText Graphics, Controls, Printers, WSStdCtrls, RichMemo; @@ -84,6 +85,9 @@ type var ui: TTextUIParam): Boolean; virtual; class procedure InDelText(const AWinControl: TWinControl; const TextUTF8: String; DstStart, DstLen: Integer); virtual; + class function GetSubText(const AWinControl: TWinControl; TextStart, TextLen: Integer; + AsUnicode: Boolean; var isUnicode: Boolean; var txt: string; var utxt: UnicodeString): Boolean; virtual; + //class procedure SetHideSelection(const ACustomEdit: TCustomEdit; AHideSelection: Boolean); override; class function LoadRichText(const AWinControl: TWinControl; Source: TStream): Boolean; virtual; class function SaveRichText(const AWinControl: TWinControl; Dest: TStream): Boolean; virtual; @@ -224,6 +228,22 @@ begin end; +class function TWSCustomRichMemo.GetSubText(const AWinControl: TWinControl; + TextStart, TextLen: Integer; AsUnicode: Boolean; var isUnicode: Boolean; + var txt: string; var utxt: UnicodeString): Boolean; +begin + // default, ineffecient implementation + if TextLen<0 then GetTextLen(AWinControl, TextLen); + Result:=GetText(AWinControl, txt); + if not Result then Exit; + if TextStart<0 then TextStart:=0; + inc(TextStart); + utxt:=''; + isUnicode:=false; + txt:=UTF8Copy(txt, TextStart, TextLen); + Result:=true; +end; + {class procedure TWSCustomRichMemo.SetHideSelection(const ACustomEdit: TCustomEdit; AHideSelection: Boolean); begin