From 3f1fc5e502f0fba40f8b33bdcf2fc7e90cb3c0a8 Mon Sep 17 00:00:00 2001 From: skalogryz Date: Mon, 16 Mar 2015 17:41:08 +0000 Subject: [PATCH] richmemo: * added tabstops support for the RichMemo and Win32Implementation * added initialization to factory unit to prevent a warning on package compilation * clean up uses for richedit helpers * code cleanup (removing empty lines) git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@4040 8e941d3f-bd1b-0410-a28a-d453659cc2b4 --- components/richmemo/richmemo.pas | 50 ++++++++ components/richmemo/richmemofactory.pas | 4 + components/richmemo/richmemohelpers.pas | 3 +- components/richmemo/win32/win32richmemo.pas | 113 +++++++++++++++--- .../richmemo/win32/win32richmemoproc.pas | 2 - components/richmemo/wsrichmemo.pas | 30 +++-- 6 files changed, 171 insertions(+), 31 deletions(-) diff --git a/components/richmemo/richmemo.pas b/components/richmemo/richmemo.pas index 12d5083b2..137d53e1d 100644 --- a/components/richmemo/richmemo.pas +++ b/components/richmemo/richmemo.pas @@ -90,6 +90,18 @@ type // thus length = lengthNoBr end; +type + TTabAlignment = (taHead, taCenter, taTail, taDecimal, taWordBar); + + TTabStop = record + Offset : Double; + Align : TTabAlignment; // not used + end; + + TTabStopList = record + Count : Integer; + Tabs : array of TTabStop; + end; type TRichMemoObject = class(TObject); @@ -150,6 +162,9 @@ type function GetParaRange(CharOfs: Integer; var ParaRange: TParaRange): Boolean; virtual; function GetParaRange(CharOfs: Integer; var TextStart, TextLength: Integer): Boolean; + procedure SetParaTabs(TextStart, TextLen: Integer; const AStopList: TTabStopList); virtual; + function GetParaTabs(CharOfs: Integer; var AStopList: TTabStopList): Boolean; virtual; + procedure SetTextAttributes(TextStart, TextLen: Integer; AFont: TFont); procedure SetRangeColor(TextStart, TextLength: Integer; FontColor: TColor); procedure SetRangeParams(TextStart, TextLength: Integer; ModifyMask: TTextModifyMask; @@ -253,6 +268,9 @@ procedure InitParaMetric(var m: TParaMetric); procedure InitParaNumbering(var n: TParaNumbering); procedure InitParaNumber(var n: TParaNumbering; ASepChar: WideChar = SepPar; StartNum: Integer = 1); procedure InitParaBullet(var n: TParaNumbering); +procedure InitTabStopList(var tabs: TTabStopList); overload; +procedure InitTabStopList(var tabs: TTabStopList; const TabStopsPt: array of double); overload; + var RTFLoadStream : function (AMemo: TCustomRichMemo; Source: TStream): Boolean = nil; @@ -379,6 +397,23 @@ begin n.Style:=pnBullet; end; +procedure InitTabStopList(var tabs: TTabStopList); +begin + FillChar(tabs, sizeof(tabs), 0); +end; + +procedure InitTabStopList(var tabs: TTabStopList; const TabStopsPt: array of double); +var + i : Integer; +begin + InitTabStopList(tabs); + tabs.count:=length(TabStopsPt); + SetLength(tabs.tabs, tabs.Count); + for i:=0 to tabs.Count-1 do begin + tabs.tabs[i].Offset:=TabStopsPt[i]; + end; +end; + { TRichMemoInline } procedure TRichMemoInline.Draw(Canvas: TCanvas; const ASize: TSize); @@ -611,6 +646,21 @@ begin TextLength:=p.length; end; +procedure TCustomRichMemo.SetParaTabs(TextStart, TextLen: Integer; + const AStopList: TTabStopList); +begin + if HandleAllocated then + TWSCustomRichMemoClass(WidgetSetClass).SetParaTabs(Self, TextStart, TextLen, AStopList); +end; + +function TCustomRichMemo.GetParaTabs(CharOfs: Integer; var AStopList: TTabStopList): Boolean; +begin + Result:=false; + if not HandleAllocated then HandleNeeded; + if HandleAllocated then + Result:=TWSCustomRichMemoClass(WidgetSetClass).GetParaTabs(Self, CharOfs, AStopList); +end; + function TCustomRichMemo.GetContStyleLength(TextStart: Integer): Integer; var ofs, len : Integer; diff --git a/components/richmemo/richmemofactory.pas b/components/richmemo/richmemofactory.pas index 132a2d160..104df4fbe 100644 --- a/components/richmemo/richmemofactory.pas +++ b/components/richmemo/richmemofactory.pas @@ -51,6 +51,10 @@ begin {$ifdef NoRichMemo}RegisterWSComponent(TCustomRichMemo, TWSCustomRichMemo);{$endif} end; +initialization + // initialization is here just to prevent compiler warning about not being used + // the unit is actually used by providing an implementation for WSREgisterCustomRichMemo class + // thus it shouldn't be smart-linked out by a smartlinker. hmm end. diff --git a/components/richmemo/richmemohelpers.pas b/components/richmemo/richmemohelpers.pas index 6e56b8ad7..4330856c7 100644 --- a/components/richmemo/richmemohelpers.pas +++ b/components/richmemo/richmemohelpers.pas @@ -22,8 +22,7 @@ interface {$IFDEF FPC_FULLVERSION >= 20600} uses - SysUtils, StrUtils, Graphics, - RichMemo; + SysUtils, Graphics, RichMemo; type TRichEditFromRichMemo = class(TObject); diff --git a/components/richmemo/win32/win32richmemo.pas b/components/richmemo/win32/win32richmemo.pas index 482c0e48d..92670c423 100644 --- a/components/richmemo/win32/win32richmemo.pas +++ b/components/richmemo/win32/win32richmemo.pas @@ -99,6 +99,11 @@ type class procedure SetParaNumbering(const AWinControl: TWinControl; TextStart, TextLen: Integer; const ANumber: TIntParaNumbering); override; + class procedure SetParaTabs(const AWinControl: TWinControl; TextStart, TextLen: Integer; + const AStopList: TTabStopList); override; + class function GetParaTabs(const AWinControl: TWinControl; TextStart: integer; + var AStopList: TTabStopList): Boolean; override; + class procedure InDelText(const AWinControl: TWinControl; const TextUTF8: String; DstStart, DstLen: Integer); override; class function Search(const AWinControl: TWinControl; const ANiddle: string; @@ -140,6 +145,10 @@ const { taCenter } ES_CENTER ); +const + TAB_OFFSET_MASK = $7FFFFF; + TAB_OFFSET_BITS = 24; + TWIP_PT = 20; // Twips in Point. Twips are commonly used measurement unit for RichEdit inteface procedure LockRedraw(AHandle: HWND); begin @@ -617,12 +626,12 @@ begin RichEditManager.GetPara2(AWinControl.Handle, TextStart, para); - AMetrics.FirstLine:=para.dxStartIndent/20; - AMetrics.TailIndent:=para.dxRightIndent/20; - AMetrics.HeadIndent:=(para.dxStartIndent+para.dxOffset)/20; - AMetrics.SpaceAfter:=para.dySpaceAfter/20; - AMetrics.SpaceBefore:=para.dySpaceBefore/20; - AMetrics.LineSpacing:=para.dyLineSpacing*DefLineSpacing/20; + AMetrics.FirstLine:=para.dxStartIndent/TWIP_PT; + AMetrics.TailIndent:=para.dxRightIndent/TWIP_PT; + AMetrics.HeadIndent:=(para.dxStartIndent+para.dxOffset)/TWIP_PT; + AMetrics.SpaceAfter:=para.dySpaceAfter/TWIP_PT; + AMetrics.SpaceBefore:=para.dySpaceBefore/TWIP_PT; + AMetrics.LineSpacing:=para.dyLineSpacing*DefLineSpacing/TWIP_PT; RichEditManager.SetEventMask(AWinControl.Handle, eventmask); end; @@ -643,14 +652,14 @@ begin or PFM_OFFSET or PFM_SPACEAFTER or PFM_SPACEBEFORE or PFM_LINESPACING; - para.dxStartIndent:=round(AMetrics.FirstLine*20); - para.dxRightIndent:=round(AMetrics.TailIndent*20); - para.dxOffset:=round((AMetrics.HeadIndent-AMetrics.FirstLine)*20); - //round(AMetrics.HeadIndent*20); - para.dySpaceAfter:=round(AMetrics.SpaceAfter*20); - para.dySpaceBefore:=round(AMetrics.SpaceBefore*20); + para.dxStartIndent:=round(AMetrics.FirstLine*TWIP_PT); + para.dxRightIndent:=round(AMetrics.TailIndent*TWIP_PT); + para.dxOffset:=round((AMetrics.HeadIndent-AMetrics.FirstLine)*TWIP_PT); + //round(AMetrics.HeadIndent*TWIP_PT); + para.dySpaceAfter:=round(AMetrics.SpaceAfter*TWIP_PT); + para.dySpaceBefore:=round(AMetrics.SpaceBefore*TWIP_PT); if AMetrics.LineSpacing > 0 then begin - para.dyLineSpacing:=round(AMetrics.LineSpacing/DefLineSpacing*20); + para.dyLineSpacing:=round(AMetrics.LineSpacing/DefLineSpacing*TWIP_PT); para.bLineSpacingRule:=5; // always line spacing? end; @@ -713,7 +722,7 @@ begin ANumber.SepChar:=SepDot else if (ANumber.Style<>pnNone) and ((para.wNumberingStyle and PFNS_SOMESEPCHAR)= 0) then ANumber.SepChar:=SepPar; - ANumber.Indent:=para.wNumberingTab/20; + ANumber.Indent:=para.wNumberingTab/TWIP_PT; Result:=true; end; @@ -762,12 +771,86 @@ begin para.wNumberingStyle:=numbstyle; end; - para.wNumberingTab:=round(ANumber.Indent*20); + para.wNumberingTab:=round(ANumber.Indent*TWIP_PT); eventmask:=RichEditManager.SetEventMask(AWinControl.Handle, 0); RichEditManager.SetPara2(AWinControl.Handle, TextStart, TextLen, para); RichEditManager.SetEventMask(AWinControl.Handle, eventmask) end; +class procedure TWin32WSCustomRichMemo.SetParaTabs( + const AWinControl: TWinControl; TextStart, TextLen: Integer; + const AStopList: TTabStopList); +var + para : PARAFORMAT2; + eventmask: Integer; + cnt : Integer; + i : Integer; +const + PARAALIGN : array [TTabAlignment] of LongWord = ( + 0 shl TAB_OFFSET_BITS, // taHead, + 1 shl TAB_OFFSET_BITS, // taCenter, + 2 shl TAB_OFFSET_BITS, // taTail, + 3 shl TAB_OFFSET_BITS, // taDecimal, + 4 shl TAB_OFFSET_BITS // taWordBar + ); + +begin + if not Assigned(RichEditManager) or not Assigned(AWinControl) then Exit; + FillChar(para, SizeOf(para), 0); + + para.cbSize:=sizeof(para); + para.dwMask:=PFM_TABSTOPS; + + if AStopList.Count > MAX_TAB_STOPS then cnt:=MAX_TAB_STOPS + else cnt:=AStopList.Count; + + para.cTabCount:=cnt; + for i:=0 to cnt-1 do begin + para.rgxTabs[i]:=((round(AStopList.Tabs[i].Offset*TWIP_PT)) and TAB_OFFSET_MASK) or PARAALIGN[AStopList.Tabs[i].Align] ; + end; + + eventmask:=RichEditManager.SetEventMask(AWinControl.Handle, 0); + RichEditManager.SetPara2(AWinControl.Handle, TextStart, TextLen, para); + + RichEditManager.SetEventMask(AWinControl.Handle, eventmask); +end; + +class function TWin32WSCustomRichMemo.GetParaTabs( + const AWinControl: TWinControl; TextStart: integer; + var AStopList: TTabStopList): Boolean; +var + para : PARAFORMAT2; + eventmask: Integer; + v : LongWord; + al : TTabAlignment; + i : Integer; +begin + Result:=False; + if not Assigned(RichEditManager) or not Assigned(AWinControl) then Exit; + + eventmask:=RichEditManager.SetEventMask(AWinControl.Handle, 0); + RichEditManager.GetPara2(AWinControl.Handle, TextStart, para); + RichEditManager.SetEventMask(AWinControl.Handle, eventmask); + + InitTabStopList(AStopList); + AStopList.Count:=para.cTabCount; + SetLength(AStopList.Tabs, AStopList.Count); + for i:=0 to AStopList.Count-1 do begin + v:=para.rgxTabs[i]; + AStopList.Tabs[i].Offset:=(v and TAB_OFFSET_MASK) / TWIP_PT; + case v shr TAB_OFFSET_BITS of + 1: al:=taCenter; + 2: al:=taTail; + 3: al:=taDecimal; + 4: al:=taWordBar; + else + al:=taHead + end; + AStopList.Tabs[i].Align:=al; + end; + Result:=true; +end; + class procedure TWin32WSCustomRichMemo.InDelText(const AWinControl:TWinControl; const TextUTF8:String;DstStart,DstLen:Integer); var diff --git a/components/richmemo/win32/win32richmemoproc.pas b/components/richmemo/win32/win32richmemoproc.pas index bf4e7a301..cd4f7887b 100644 --- a/components/richmemo/win32/win32richmemoproc.pas +++ b/components/richmemo/win32/win32richmemoproc.pas @@ -602,9 +602,7 @@ var begin GetSelection(RichEditWnd, s, l); SetSelection(RichEditWnd, TextStart, TextLen); - SendMessagea(RichEditWnd, EM_SETPARAFORMAT, 0, LPARAM(@para)); - SetSelection(RichEditWnd, s, l); end; diff --git a/components/richmemo/wsrichmemo.pas b/components/richmemo/wsrichmemo.pas index 3aa1bc421..eb305a856 100644 --- a/components/richmemo/wsrichmemo.pas +++ b/components/richmemo/wsrichmemo.pas @@ -37,18 +37,6 @@ type TIntParaMetric = RichMemo.TParaMetric; TIntParaNumbering = RichMemo.TParaNumbering; - TTabAlignment = (taLeft, taCenter, taRight, taDecimal, taWordBar); - - TTabInfo = record - Offset : Double; - Align : TTabAlignment; - end; - - TIntParaTabs = record - Count : Integer; - Tabs : array of TTabInfo; - end; - TIntSearchOpt = record start : Integer; len : Integer; @@ -84,6 +72,12 @@ type 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 SetParaTabs(const AWinControl: TWinControl; TextStart, TextLen: Integer; + const AStopList: TTabStopList); virtual; + class function GetParaTabs(const AWinControl: TWinControl; TextStart: integer; + var AStopList: TTabStopList): Boolean; virtual; + class procedure InDelText(const AWinControl: TWinControl; const TextUTF8: String; DstStart, DstLen: Integer); virtual; //class procedure SetHideSelection(const ACustomEdit: TCustomEdit; AHideSelection: Boolean); override; class function LoadRichText(const AWinControl: TWinControl; Source: TStream): Boolean; virtual; @@ -194,6 +188,18 @@ begin end; +class procedure TWSCustomRichMemo.SetParaTabs(const AWinControl: TWinControl; + TextStart, TextLen: Integer; const AStopList: TTabStopList); +begin + +end; + +class function TWSCustomRichMemo.GetParaTabs(const AWinControl: TWinControl; + TextStart: integer; var AStopList: TTabStopList): Boolean; +begin + Result:=False; +end; + class procedure TWSCustomRichMemo.InDelText(const AWinControl: TWinControl; const TextUTF8: String; DstStart, DstLen: Integer); begin