unit Unit1;

interface

{$I RV_Defs.inc}

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
  Dialogs, RVStyle, RVScroll, RichView, RVEdit, Buttons, ExtCtrls, StdCtrls,
  SclRView;

type
  TForm1 = class(TForm)
    RVStyle1: TRVStyle;
    Panel1: TPanel;
    btnBullets: TSpeedButton;
    btnNumbering: TSpeedButton;
    srv: TSRichViewEdit;
    procedure btnBulletsClick(Sender: TObject);
    procedure RichViewEdit1CaretMove(Sender: TObject);
    procedure btnNumberingClick(Sender: TObject);
  private
    { Private declarations }
    function CreateBullets: Integer;
    function CreateNumbering: Integer;
    function GetListNo(rve: TCustomRichViewEdit; ItemNo: Integer): Integer;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{------------------------------------------------------------------------------}
function TForm1.GetListNo(rve: TCustomRichViewEdit;
  ItemNo: Integer): Integer;
var Level, StartFrom: Integer;
    Reset: Boolean;
begin
  rve.GetListMarkerInfo(ItemNo, Result, Level, StartFrom, Reset);
end;
{------------------------------------------------------------------------------}
// Returns index of bulleted list style. Creates it, if necessary.
function TForm1.CreateBullets: Integer;
var ListStyle: TRVListInfo;
begin
  // 1. Creating desired list style
  ListStyle := TRVListInfo.Create(nil);
  with ListStyle.Levels.Add do begin
    ListType  := rvlstBullet;
    Font.Name := 'Symbol';
    {$IFDEF RICHVIEWCBDEF3}
    Font.Charset := SYMBOL_CHARSET;
    {$ENDIF}
    Font.Size := 12;
    FirstIndent := 0;
    LeftIndent  := 24;
  end;
  // 2. Searching for existing style with these properties. Creating it, if not found
  Result := RVStyle1.ListStyles.FindSuchStyle(ListStyle, True);
  ListStyle.Free;
end;
{------------------------------------------------------------------------------}
function TForm1.CreateNumbering: Integer;
var ListStyle: TRVListInfo;
    rve: TCustomRichViewEdit;
    i, StartNo, EndNo, a, b, ListNo: Integer;
begin
  Result := -1;
  // 1. Creating desired list style
  ListStyle := TRVListInfo.Create(nil);
  with ListStyle.Levels.Add do begin
    ListType  := rvlstDecimal;
    Font.Name := 'Arial';
    Font.Size := 12;
    FirstIndent := 0;
    LeftIndent  := 24;
    FormatString := '%0:s.';
  end;
  // 2. Searching for such style in the selected paragraphs, the paragraph before,
  // and the paragraph after. If found, using it.
  rve := srv.RichViewEdit.TopLevelEditor;
  rve.GetSelectionBounds(StartNo, a, EndNo, b, True);
  if StartNo<0 then begin
    StartNo := rve.CurItemNo;
    EndNo   := StartNo;
  end;
  // ExpandToPara is an undocumented method that changes item range StartNo..EndNo
  // so that it completely includes paragraphs containing StartNo..EndNo
  rve.RVData.ExpandToPara(StartNo, EndNo, StartNo, EndNo);
  if StartNo>0 then
    dec(StartNo);
  if EndNo<rve.ItemCount-1 then
    inc(EndNo);
  rve.RVData.ExpandToPara(StartNo, EndNo, StartNo, EndNo);
  for i := StartNo to EndNo do
    if rve.IsParaStart(i) and (rve.GetItemStyle(i)=rvsListMarker) then begin
      ListNo := GetListNo(rve, i);
      if RVStyle1.ListStyles[ListNo].IsSimpleEqual(ListStyle, True, True) then begin
        Result := ListNo;
        break;
      end;
  end;
  // 3. Idea for improving. You can try to reuse existing list style with the
  // given properties, which is not used in the document. If you want to do it,
  // you need to iterate through all items in the document, and check all markers.

  // 4. If not found, creating it
  if Result<0 then begin
    RVStyle1.ListStyles.Add.Assign(ListStyle);
    Result := RVStyle1.ListStyles.Count-1;
    RVStyle1.ListStyles[Result].Standard := False;
  end;
  ListStyle.Free;
end;
{------------------------------------------------------------------------------}
// CARET WAS MOVED: updating buttons
procedure TForm1.RichViewEdit1CaretMove(Sender: TObject);
var FirstParaItemNo: Integer;
    rve: TCustomRichViewEdit;
    ListNo: Integer;
begin
  rve := srv.RichViewEdit.TopLevelEditor;
  FirstParaItemNo := rve.CurItemNo;
  if FirstParaItemNo<0 then // document is cleared
    exit;
  while not rve.IsParaStart(FirstParaItemNo) do
    dec(FirstParaItemNo);
  if rve.GetItemStyle(FirstParaItemNo)=rvsListMarker then begin
    ListNo := GetListNo(rve, FirstParaItemNo);
    btnBullets.Down := not RVStyle1.ListStyles[ListNo].HasNumbering;
    btnNumbering.Down := RVStyle1.ListStyles[ListNo].AllNumbered;
    end
  else begin
    btnBullets.Down := False;
    btnNumbering.Down := False;
  end;
end;
{------------------------------------------------------------------------------}
// TOGGLING BULLETS
procedure TForm1.btnBulletsClick(Sender: TObject);
begin
  if not btnBullets.Down then
    srv.RichViewEdit.RemoveLists(False)
  else
    srv.RichViewEdit.ApplyListStyle(CreateBullets,0,0,False,False);
end;
{------------------------------------------------------------------------------}
// TOGGLING NUMBERING
procedure TForm1.btnNumberingClick(Sender: TObject);
begin
  if not btnNumbering.Down then
    srv.RichViewEdit.RemoveLists(False)
  else
    srv.RichViewEdit.ApplyListStyle(CreateNumbering,0,0,False,False);
end;

end.
