Page 1 of 1

BlockQuote support

Posted: Sun Jul 01, 2007 10:22 am
by cychia
As from what I know, RV currently does not support blockquote feature. So I have to come out with some alternative solution to achieve this

Any good alternative you may suggest to me? I will process the HTML again after it is export by RV. Therefore I just need some special indicator that I can make a replace to <blockquote> it will be nice.

Besides, I would like to ask how can I apply a parainfo to a selected text?

example I have a para of text as below:

my name is someone somebody nobody. yourname is somesome some. nice to meet you

then in RV editor, "yourname is somesome some" is highlighted, the when i click on a button, it will apply the whole selected text with the parainfo.

Thanks.

Posted: Tue Jul 03, 2007 4:44 pm
by Sergey Tkachenko
You can insert additional code around some paragraphs using OnSaveParaToHTML event.

Posted: Thu Jul 05, 2007 12:02 am
by cychia
May I have an example ?


Besides, I would like to ask how can I apply a parainfo to a selected text?

example I have a para of text as below:

my name is someone somebody nobody. yourname is somesome some. nice to meet you

then in RV editor, "yourname is somesome some" is highlighted, the when i click on a button, it will apply the whole selected text with the parainfo.

Thanks.

Posted: Thu Jul 05, 2007 9:47 am
by Sergey Tkachenko
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.

works but not enough

Posted: Mon Jul 09, 2007 1:25 pm
by cychia
the solution does work, but it still have some problem which does not fully suitmy purpose.

1. Everytime Enter button is pressed, it will start anonother blockquote paragraph, and when output to html file, it will have multiple blockquote, like:
<BLOCKQUOTE><DIV></DIV></BLOCKQUOTE><BLOCKQUOTE><DIV></DIV></BLOCKQUOTE>

rather than:
<BLOCKQUOTE>
<DIV></DIV>
<DIV></DIV>
</BLOCKQUOTE>

You get what I mean?

Does RV support nested paragraph? If not, anyway that I can achieve what I have explain above?

Thanks a lot!

Posted: Mon Jul 09, 2007 3:02 pm
by Sergey Tkachenko
No, nested paragraphs are not supported (moreover, in strict HTML, they are not supported too)
I suggest to abandon blockquote and use table instead.

Posted: Mon Jul 16, 2007 3:59 am
by cychia
if I were to use table, how can I create an invisible table so that the table looks exactly like I have just made an indent to a paragraph? And can I give a name to the table so that when it is exported to HTML, the name will also be saved into HTML. Then after exported, I will parse the content again to replace the table to blockquote.

Posted: Mon Jul 16, 2007 5:39 am
by Sergey Tkachenko
Table is invisible if it has transparent background and zero-width borders (in editor, you may want to turn off grid lines).
You can add some content to the first row of this table, for example "Quote:", and use it to distinguish this table from other tables.