diff --git a/components/richmemo/richmemo.pas b/components/richmemo/richmemo.pas index 252df0c18..46028b4db 100644 --- a/components/richmemo/richmemo.pas +++ b/components/richmemo/richmemo.pas @@ -63,6 +63,14 @@ type TSearchOption = (soMatchCase, soWholeWord, soBackward); TSearchOptions = set of TSearchOption; + TParaRange = record + start : Integer; // the first character in the paragraph + lenghtNoBr : Integer; // the length of the paragraph, excluding the line break character + length : Integer; // the length of the paragrpah, including the line break, if present + // the last line in the control doesn't contain a line break character, + // thus length = lengthNoBr + end; + type TRichMemoObject = class(TObject); @@ -97,6 +105,8 @@ type procedure SetParaMetric(TextStart, TextLen: Integer; const AMetric: TParaMetric); virtual; function GetParaNumbering(TextStart: Integer; var ANumber: TParaNumbering): Boolean; virtual; procedure SetParaNumbering(TextStart, TextLen: Integer; const ANumber: TParaNumbering); virtual; + function GetParaRange(CharOfs: Integer; var ParaRange: TParaRange): Boolean; virtual; + function GetParaRange(CharOfs: Integer; var TextStart, TextLength: Integer): Boolean; procedure SetTextAttributes(TextStart, TextLen: Integer; AFont: TFont); procedure SetRangeColor(TextStart, TextLength: Integer; FontColor: TColor); @@ -350,6 +360,25 @@ begin TWSCustomRichMemoClass(WidgetSetClass).SetParaNumbering(Self, TextStart, TextLen, ANumber); end; +function TCustomRichMemo.GetParaRange(CharOfs: Integer; + var ParaRange: TParaRange): Boolean; +begin + Result:=false; + if not HandleAllocated then HandleNeeded; + if HandleAllocated then + Result:=TWSCustomRichMemoClass(WidgetSetClass).GetParaRange(Self, CharOfs, ParaRange); +end; + +function TCustomRichMemo.GetParaRange(CharOfs: Integer; var TextStart, + TextLength: Integer): Boolean; +var + p : TParaRange; +begin + Result:=GetParaRange(CharOfs, p); + TextStart:=p.start; + TextLength:=p.length; +end; + function TCustomRichMemo.GetContStyleLength(TextStart: Integer): Integer; var ofs, len : Integer; diff --git a/components/richmemo/win32/win32richmemo.pas b/components/richmemo/win32/win32richmemo.pas index d599375f4..b7b99f04a 100644 --- a/components/richmemo/win32/win32richmemo.pas +++ b/components/richmemo/win32/win32richmemo.pas @@ -91,6 +91,8 @@ type var AMetrics: TIntParaMetric): Boolean; override; class procedure SetParaMetric(const AWinControl: TWinControl; TextStart, TextLength: Integer; const AMetrics: TIntParaMetric); override; + class function GetParaRange(const AWinControl: TWinControl; TextStart: Integer; + var ParaRange: TParaRange): Boolean; override; class function GetParaNumbering(const AWinControl: TWinControl; TextStart: Integer; var ANumber: TIntParaNumbering): Boolean; override; @@ -519,6 +521,17 @@ begin RichEditManager.SetPara2(AWinControl.Handle, TextStart, TextLength, para); end; +class function TWin32WSCustomRichMemo.GetParaRange(const AWinControl: TWinControl; + TextStart: Integer; var ParaRange: TParaRange): Boolean; +begin + if not Assigned(AWinControl) then + Result:=False + else begin + RichEditManager.GetParaRange(AWinControl.Handle, TextStart, ParaRange); + Result:=true; + end; +end; + const PFN_ARABIC = 2; PFN_LCLETTER = 3; diff --git a/components/richmemo/win32/win32richmemoproc.pas b/components/richmemo/win32/win32richmemoproc.pas index 4294245d8..8acaaa2eb 100644 --- a/components/richmemo/win32/win32richmemoproc.pas +++ b/components/richmemo/win32/win32richmemoproc.pas @@ -33,7 +33,7 @@ uses // RichMemoUnits RichMemo, WSRichMemo, RichMemoUtils, // Win32 widgetset units - win32proc,ActiveX, ComObj; + win32proc, ActiveX, ComObj; const IID_IRichEditOle: TGUID = '{00020D00-0000-0000-C000-000000000046}'; @@ -148,6 +148,7 @@ type TRichEditManager = class(TObject) public + class function GetTextLength(RichEditWnd: Handle): Integer; class function SetSelectedTextStyle(RichEditWnd: Handle; Params: TIntFontParams): Boolean; virtual; class function GetSelectedTextStyle(RichEditWnd: Handle; var Params: TIntFontParams): Boolean; virtual; class function GetStyleRange(RichEditWnd: Handle; TextStart: Integer; var RangeStart, RangeLen: Integer): Boolean; virtual; @@ -160,6 +161,7 @@ type 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; + class procedure GetParaRange(RichEditWnd: Handle; TextStart: integer; var para: TParaRange); virtual; end; TRichManagerClass = class of TRichEditManager; @@ -172,6 +174,10 @@ procedure CopyStringToCharArray(const s: String; var Chrs: array of Char; ChrsSi function FontStylesToEffects(Styles: TFontStyles): LongWord; function EffectsToFontStyles(Effects: LongWord): TFontStyles; +const + CP_UNICODE = 1200; + HardBreak = #13; + implementation const @@ -240,6 +246,16 @@ end; { TRichEditManager } +class function TRichEditManager.GetTextLength(RichEditWnd: Handle): Integer; +var + textlen : TGETTEXTEX; +begin + FillChar(textlen, sizeof(textlen), 0); + textlen.flags := GTL_NUMCHARS or GTL_PRECISE; + textlen.codepage := CP_UNICODE; + Result := SendMessage(RichEditWnd, EM_GETTEXTLENGTHEX, WPARAM(@textlen), 0); +end; + class function TRichEditManager.SetSelectedTextStyle(RichEditWnd: Handle; Params: TIntFontParams): Boolean; var @@ -314,7 +330,6 @@ var last : Integer; const - CP_UNICODE = 1200; ALL_MASK = CFM_BOLD or CFM_ITALIC or CFM_STRIKEOUT or CFM_UNDERLINE or CFM_SIZE or CFM_COLOR or CFM_FACE; begin @@ -322,7 +337,7 @@ begin if (RichEditWnd = 0) then Exit; FillChar(textlen, sizeof(textlen), 0); - textlen.flags := GTL_NUMCHARS or GTL_USECRLF or GTL_PRECISE; + textlen.flags := GTL_NUMCHARS or GTL_PRECISE; textlen.codepage := CP_UNICODE; len := SendMessage(RichEditWnd, EM_GETTEXTLENGTHEX, WPARAM(@textlen), 0); Result := TextStart < len; @@ -584,6 +599,58 @@ begin end; end; +class procedure TRichEditManager.GetParaRange(RichEditWnd: Handle; TextStart: integer; + var para: TParaRange); +var + line: Integer; + txtlen: Integer; + st: Integer; + ln: Integer; + toend: Integer; + tost: Integer; + buf : string[16]; + rng : TTEXTRANGEA; + res : Integer; +begin + txtlen:=GetTextLength(RichEditWnd); + // lines are NOT paragraphs, but wordwrapped lines + line:=SendMessage(RichEditWnd, EM_EXLINEFROMCHAR, 0, TextStart); + st:=SendMessage(RichEditWnd, EM_LINEINDEX, line, 0); + tost:=st; + toend:=0; + + while tost>0 do begin + rng.lpstrText:=@buf[1]; + rng.chrg.cpMin:=tost-1; + rng.chrg.cpMax:=tost; + buf[1]:=#0; + res:=SendMessageA(RichEditWnd, EM_GETTEXTRANGE, 0, LPARAM(@rng)); + if (buf[1]=HardBreak) then + Break // found the beggining of the paragraph + else begin + line:=SendMessage(RichEditWnd, EM_EXLINEFROMCHAR, 0, tost-2); // getting the line before the linebreak + tost:=SendMessage(RichEditWnd, EM_LINEINDEX, line, 0); + inc(toend, SendMessage(RichEditWnd, EM_LINELENGTH, line, 0)); + end; + end; + + repeat + ln:=SendMessage(RichEditWnd, EM_LINELENGTH, st, 0); + inc(toend, ln); + inc(st, ln); + rng.lpstrText:=@buf[1]; + rng.chrg.cpMin:=st; + rng.chrg.cpMax:=st+1; + buf[1]:=#0; + res:=SendMessage(RichEditWnd, EM_GETTEXTRANGE, 0, LPARAM(@rng)); + until (res=0) or (buf[1] = HardBreak); + + para.start:=tost; + para.lenghtNoBr:=toend; + if res>0 then inc(toend); // there's a line break character - add it to the range + para.length:=toend; +end; + function WinInsertImageFromFile (const ARichMemo: TCustomRichMemo; APos: Integer; const FileNameUTF8: string; const AImgSize: TSize): Boolean; diff --git a/components/richmemo/wsrichmemo.pas b/components/richmemo/wsrichmemo.pas index 0b25bbd8d..58c70d242 100644 --- a/components/richmemo/wsrichmemo.pas +++ b/components/richmemo/wsrichmemo.pas @@ -80,6 +80,7 @@ type const AMetric: TIntParaMetric); virtual; class function GetParaNumbering(const AWinControl: TWinControl; TextStart: Integer; var ANumber: TIntParaNumbering): Boolean; virtual; + class function GetParaRange(const AWinControl: TWinControl; TextStart: Integer; var rng: TParaRange): Boolean; virtual; class procedure SetParaNumbering(const AWinControl: TWinControl; TextStart, TextLen: Integer; const ANumber: TIntParaNumbering); virtual; class procedure InDelText(const AWinControl: TWinControl; const TextUTF8: String; DstStart, DstLen: Integer); virtual; @@ -167,6 +168,12 @@ begin Result := false; end; +class function TWSCustomRichMemo.GetParaRange(const AWinControl: TWinControl; + TextStart: Integer; var rng: TParaRange): Boolean; +begin + Result:=False; +end; + class procedure TWSCustomRichMemo.SetParaNumbering( const AWinControl: TWinControl; TextStart, TextLen: Integer; const ANumber: TIntParaNumbering);