Initially I did not understand your question about applying paragraph style to the selected text. Paragraph style is applied to the whole paragraphs containing the selected text.
But now I think I understand. You want to make paragraph(s) from the selected fragment, and then apply paragraph style to it. It is like applying "blockquote" to the selection. Am I right?
The example is below.
The first function returns paragraph style that will be used for blockquote.
I make it with indents from all 4 sides, with background (clInfoBk color) and border (clWindowText color). All other properties are taken from the ParaNo-th style.
One more important note. By default, when comparing styles (for example, for style searching), TRichView ignores style names (StyleName property). But later we will rely on the style name (special support for paragraph styles having StyleName='blockquote'). So we need to take StyleName into account. To do it, set global variable:
Code: Select all
RichViewCompareStyleNames := True;
So, the first function is:
Code: Select all
function GetQuoteParaNo(rvs: TRVStyle; ParaNo: Integer): Integer;
var ParaStyle: TParaInfo;
begin
ParaStyle := TParaInfo.Create(nil);
try
ParaStyle.Assign(rvs.ParaStyles[ParaNo]);
ParaStyle.SpaceBefore := 20;
ParaStyle.SpaceAfter := 20;
ParaStyle.LeftIndent := 20;
ParaStyle.RightIndent := 20;
ParaStyle.Border.BorderOffsets.SetAll(10);
ParaStyle.Border.Style := rvbSingle;
ParaStyle.Background.BorderOffsets.SetAll(10);
ParaStyle.Background.Color := clInfoBk;
ParaStyle.StyleName := 'blockquote';
Result := rvs.ParaStyles.FindSuchStyle(ParaNo, ParaStyle, RVAllParaInfoProperties);
if Result<0 then begin
rvs.ParaStyles.Add;
Result := rvs.ParaStyles.Count-1;
rvs.ParaStyles[Result].Assign(ParaStyle);
rvs.ParaStyles[Result].Standard := False;
end;
finally
ParaStyle.Free;
end;
end;
The next function applies this style to the selected fragment.
Code: Select all
uses RVLinear;
procedure ApplyBlockQuote(rve: TCustomRichViewEdit);
var IsParaStart, IsParaEnd: Boolean;
StartNo, StartOffs, EndNo, EndOffs, SelStart, SelLength: Integer;
ParaNo: Integer;
begin
rve := rve.TopLevelEditor;
rve.GetSelectionBounds(StartNo, StartOffs, EndNo, EndOffs, True);
if (StartNo<0) or ((StartNo=EndNo) and (StartOffs=EndOffs)) then
exit; // cannot apply blockquote to empty selection
// Does the selection start from the beginning of paragraph?
IsParaStart := (StartOffs<=rve.GetOffsBeforeItem(StartNo)) and
(rve.IsParaStart(StartNo) or ((StartNo>0) and (rve.GetItemStyle(StartNo-1)=rvsListMarker)));
// Does the selection end at the end of paragraph?
IsParaEnd := (EndOffs>=rve.GetOffsAfterItem(EndNo)) and
((EndNo=rve.ItemCount-1) or rve.IsParaStart(EndNo+1));
// Storing the paragraph style index for the current paragraph.
// Later, we will create "blockquote" paragraph style basing on this style
ParaNo := rve.CurParaStyleNo;
// All changes will be grouped and user will be able to undo them as one action
rve.BeginUndoGroup(rvutPara);
rve.SetUndoGroupMode(True);
try
// Storing selection in richedit-like variables
RVGetSelection(rve, SelStart, SelLength);
// If the selection was done from bottom to top, normalizing it
if SelLength<0 then begin
inc(SelStart, SelLength);
SelLength := - SelLength;
end;
// Adding line break to the end, if necessary
if not IsParaEnd then begin
rve.SetSelectionBounds(EndNo, EndOffs, EndNo, EndOffs);
rve.InsertText(#13);
end;
// Adding line break to the start, if necessary (and updating SelStart)
if not IsParaStart then begin
rve.SetSelectionBounds(StartNo, StartOffs, StartNo, StartOffs);
rve.InsertText(#13);
SelStart := RVGetLinearCaretPos(rve);
end;
// Selecting the same fragment again
RVSetSelection(rve, SelStart, SelLength);
// Applying "blockquote"
rve.ApplyParaStyle(GetQuoteParaNo(rve.Style, ParaNo));
finally
rve.SetUndoGroupMode(False);
end;
end;
That's all about applying.
Now to saving to HTML.
OnSaveParaToHTML event is public, not published (because it rarely needs to be used, so I wanted to hide it in the Object Inspector).
Create this procedure in your form
Code: Select all
procedure TForm3.DoSaveBlockQuote(Sender: TCustomRichView;
RVData: TCustomRVData; ItemNo: Integer; ParaStart, CSSVersion: Boolean;
var HTMLCode: String);
begin
if not ParaStart then
dec(ItemNo);
if Sender.Style.ParaStyles[RVData.GetItemPara(ItemNo)].StyleName='blockquote' then
if ParaStart then
HTMLCode := '<blockquote>'
else
HTMLCode := '</blockquote>';
end;
and assign it to the event:
Code: Select all
RichViewEdit1.OnSaveParaToHTML := DoSaveBlockQuote;
I think the result is good enough and you do not need to parse HTML file afterwards.