
{*******************************************************}
{                                                       }
{       RichViewActions                                 }
{       Dialog for customization of list styles         }
{                                                       }
{       Copyright (c) Sergey Tkachenko                  }
{       svt@trichview.com                               }
{       http://www.trichview.com                        }
{                                                       }
{*******************************************************}


unit ParaListRVFrm;

interface

{$I RV_Defs.inc}
{$I RichViewActions.inc}

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
  Dialogs, BaseRVFrm, StdCtrls, RVSpinEdit, RVOfficeRadioBtn, ExtCtrls,
  {$IFDEF USERVKSDEVTE}
  te_controls,
  {$ENDIF}
  RVScroll, RichView, RVStyle, Buttons, ExtDlgs, CRVData, RVALocalize, RVFuncs,
  RVTypes, RVStr;

type


  TBulletCharacter = class
    public
      Text: String;
      TextW: WideString;
      Unicode: Boolean;
      Font: TFont;
      constructor Create;
      destructor Destroy; override;
  end;

  TfrmRVParaList = class(TfrmRVBase)
    btnOk: TButton;
    btnCancel: TButton;
    gbLevels: TGroupBox;
    lstLevels: TListBox;
    seLevels: TRVSpinEdit;
    lblLevelCount: TLabel;
    gbListProperties: TGroupBox;
    cmbNumbers: TComboBox;
    lblNumber: TLabel;
    nb: TNotebook;
    btnFont: TButton;
    rgBullet: TRVOfficeRadioGroup;
    btnBullet: TButton;
    btnNumberFont: TButton;
    lblNumFormat: TLabel;
    txtNumbers: TEdit;
    gbNumber: TGroupBox;
    cmbLevel: TComboBox;
    Panel1: TPanel;
    img: TImage;
    btnImage: TButton;
    gbListTextPos: TGroupBox;
    lblStartAt: TLabel;
    seStartAt: TRVSpinEdit;
    cmbMarkerAlign: TComboBox;
    lblAt: TLabel;
    seMarkerIndent: TRVSpinEdit;
    gbTextPos: TGroupBox;
    lblLI: TLabel;
    seLeftIndent: TRVSpinEdit;
    lblFI: TLabel;
    seFirstIndent: TRVSpinEdit;
    lblFLI: TLabel;
    gbPreview: TGroupBox;
    rv: TRichView;
    rvs: TRVStyle;
    btnInsert: TBitBtn;
    fd: TFontDialog;
    rvs2: TRVStyle;
    cbOneLevelPreview: TCheckBox;
    procedure btnNumberFontClick(Sender: TObject);
    procedure cmbLevelClick(Sender: TObject);
    procedure btnInsertClick(Sender: TObject);
    procedure seLevelsChange(Sender: TObject);
    procedure lstLevelsClick(Sender: TObject);
    procedure btnImageClick(Sender: TObject);
    procedure cmbNumbersClick(Sender: TObject);
    procedure rgBulletCustomDraw(Sender: TRVOfficeRadioGroup;
      ItemIndex: Integer; Canvas: TCanvas; const ARect: TRect;
      var DoDefault: Boolean);
    procedure btnFontClick(Sender: TObject);
    procedure txtNumbersChange(Sender: TObject);
    procedure rvJump(Sender: TObject; id: Integer);
    procedure btnBulletClick(Sender: TObject);
    procedure rgBulletClick(Sender: TObject);
    procedure seMarkerIndentChange(Sender: TObject);
    procedure seLeftIndentChange(Sender: TObject);
    procedure seFirstIndentChange(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure cmbMarkerAlignClick(Sender: TObject);
    procedure seStartAtChange(Sender: TObject);
  private
    { Private declarations }
    FStoredBullet, FStoredNumber, FStoredBulletFontName, FStoredNumberFontName: String;
    FStoredBulletCharset, FStoredNumberCharset: TFontCharset;
    FStoredBulletIndex: Integer;
    FBulletUnicode, FUpdating: Boolean;
    function FormatToEdit(const s: String; LevelNo: Integer): String;
    function EditToFormat(const s: String; LevelNo: Integer): String;
    procedure MakeSample;
  protected
    _btnInsert, _gbListTextPos, _gbListProperties,
    _cmbNumbers, _cmbLevel, _cmbMarkerAlign,
    _cbOneLevelPreview, _lblStartAt, _txtNumbers: TControl;
    _lstLevels: TControl;
    IgnoreLevelsClick: Boolean;
    {$IFDEF RVASKINNED}
    procedure OnCreateThemedControl(OldControl, NewControl: TControl); override;
    {$ENDIF}
  public
    { Public declarations }
    procedure SetListStyle(ListStyle: TRVListInfo; RVStyle: TRVStyle);
    procedure GetListStyle(ListStyle: TRVListInfo);
    procedure SetControls(LevelNo: Integer);
    procedure SetControls2(LevelNo: Integer);
    procedure Localize; override;
  end;

var
  BulletChars: array [0..5] of TBulletCharacter;

implementation
uses InsSymbolRVFrm, RichViewActions;

const
  PAGE_BULLET = 0;
  PAGE_NUMBER = 1;
  PAGE_IMAGE  = 2;
  PAGE_OTHER  = 3;

{$R *.dfm}

{ TfrmRVParaList }
{------------------------------------------------------------------------------}
procedure TfrmRVParaList.SetListStyle(ListStyle: TRVListInfo; RVStyle: TRVStyle);
var i: Integer;
begin
  IgnoreLevelsClick := True;
  seLevels.OnChange := nil;
  try
    UpdateLengthSpinEdit(seMarkerIndent, False, True);
    UpdateLengthSpinEdit(seLeftIndent, False, True);
    UpdateLengthSpinEdit(seFirstIndent, False, True);
    rvs.Units := RVStyle.Units;
    rvs2.Units := RVStyle.Units;
    rvs.ListStyles.Clear;
    rvs.ListStyles.Add.Assign(ListStyle);
    if rvs.ListStyles[0].Levels.Count=0 then
      rvs.ListStyles[0].Levels.Add;
    seLevels.MaxValue := 9;
    if rvs.ListStyles[0].Levels.Count>9 then
      seLevels.MaxValue := rvs.ListStyles[0].Levels.Count;
    seLevels.Value := rvs.ListStyles[0].Levels.Count;
    ClearXBoxItems(_lstLevels);
    for i := 1 to rvs.ListStyles[0].Levels.Count do
      XBoxItemsAddObject(_lstLevels, IntToStr(i), nil);
    SetXBoxItemIndex(_lstLevels, 0);
    SetControls(0);
  finally
    IgnoreLevelsClick := False;
    seLevels.OnChange := seLevelsChange;
  end;
  SetCheckBoxChecked(_cbOneLevelPreview, ListStyle.OneLevelPreview);
end;
{------------------------------------------------------------------------------}
procedure TfrmRVParaList.SetControls(LevelNo: Integer);
var LevelInfo: TRVListLevel;
begin
  LevelInfo := rvs.ListStyles[0].Levels[LevelNo];
  case LevelInfo.ListType of
    rvlstBullet, rvlstUnicodeBullet:
      SetXBoxItemIndex(_cmbNumbers, 0);
    rvlstDecimal:
      SetXBoxItemIndex(_cmbNumbers, 1);
    rvlstUpperRoman:
      SetXBoxItemIndex(_cmbNumbers, 2);
    rvlstLowerRoman:
      SetXBoxItemIndex(_cmbNumbers, 3);
    rvlstUpperAlpha:
      SetXBoxItemIndex(_cmbNumbers, 4);
    rvlstLowerAlpha:
      SetXBoxItemIndex(_cmbNumbers, 5);
    rvlstPicture:
      SetXBoxItemIndex(_cmbNumbers, 6);
    else
      SetXBoxItemIndex(_cmbNumbers, -1);
  end;
  SetControls2(LevelNo);
end;
{------------------------------------------------------------------------------}
procedure TfrmRVParaList.SetControls2(LevelNo: Integer);
var LevelInfo: TRVListLevel;
    i: Integer;
begin
  FUpdating := True;
  try
    LevelInfo := rvs.ListStyles[0].Levels[LevelNo];
    case LevelInfo.ListType of
      rvlstBullet, rvlstUnicodeBullet:
        begin
          if FStoredBulletIndex<0 then
            FStoredBulletIndex := 5;
          BulletChars[FStoredBulletIndex].Font.Assign(LevelInfo.Font);
          if LevelInfo.ListType=rvlstUnicodeBullet then begin
            if Length(LevelInfo.FormatStringW)=1 then
              BulletChars[FStoredBulletIndex].TextW := LevelInfo.FormatStringW
            else
              LevelInfo.FormatStringW := BulletChars[FStoredBulletIndex].TextW;
            BulletChars[FStoredBulletIndex].Unicode := True;
            end
          else begin
            if Length(LevelInfo.FormatString)=1 then
              BulletChars[FStoredBulletIndex].Text := LevelInfo.FormatString
            else
              LevelInfo.FormatString := BulletChars[FStoredBulletIndex].Text;
            BulletChars[FStoredBulletIndex].Unicode := False;
          end;
          rgBullet.ItemIndex := FStoredBulletIndex;
          rgBullet.Invalidate;
          nb.PageIndex := PAGE_BULLET;
          SetControlCaption(_gbListTextPos, RVA_GetSHUnits(rvam_cul_BulletPos, RVA_Units));
        end;
      rvlstDecimal, rvlstLowerAlpha, rvlstUpperAlpha, rvlstLowerRoman, rvlstUpperRoman:
        begin
          SetControlCaption(_txtNumbers, FormatToEdit(LevelInfo.FormatString, LevelNo));
          GetEditFont(_txtNumbers).Assign(LevelInfo.Font);
          GetEditFont(_txtNumbers).Size := 8;
          GetEditFont(_txtNumbers).Color := clWindowText;
          ClearXBoxItems(_cmbLevel);
          for i := 0 to LevelNo-1 do
            XBoxItemsAddObject(_cmbLevel,
              Format(RVA_GetS(rvam_cul_LevelNo),[i+1]), nil);
          XBoxItemsAddObject(_cmbLevel, RVA_GetS(rvam_cul_ThisLevel), nil);
          _btnInsert.Enabled := GetXBoxItemIndex(_cmbLevel)>=0;
          seStartAt.Value := LevelInfo.StartFrom;
          seStartAt.Visible := LevelInfo.StartFrom<>1;
          _lblStartAt.Visible := LevelInfo.StartFrom<>1;
          SetControlCaption(_gbListTextPos, RVA_GetSHUnits(rvam_cul_NumPos, RVA_Units));
          nb.PageIndex := PAGE_NUMBER;
        end;
      rvlstPicture:
        begin
          img.Picture.Graphic := LevelInfo.Picture.Graphic;
          nb.PageIndex := PAGE_IMAGE;
          SetControlCaption(_gbListTextPos, RVA_GetSHUnits(rvam_cul_ImagePos, RVA_Units));
        end;
      else
        begin
          nb.PageIndex := PAGE_OTHER;
        end;
    end;
    SetXBoxItemIndex(_cmbMarkerAlign, ord(LevelInfo.MarkerAlignment));
    seMarkerIndent.Value := rvs.GetAsRVUnits(LevelInfo.MarkerIndent, RVA_Units);
    seLeftIndent.Value   := rvs.GetAsRVUnits(LevelInfo.LeftIndent, RVA_Units);
    seFirstIndent.Value  := rvs.GetAsRVUnits(LevelInfo.FirstIndent, RVA_Units);
  finally
    FUpdating := False;
  end;
  MakeSample;
end;
{------------------------------------------------------------------------------}
function TfrmRVParaList.EditToFormat(const s: String; LevelNo: Integer): String;
var i,p: Integer;
    s2,s3: String;
begin
  Result := s;
  for i := 0 to LevelNo do begin
    s2 := Format('<L%d>',[i+1]);
    s3 := Format('%%%d:s',[i]);
    repeat
      p := pos(s2,Result);
      if p>0 then
        RV_ReplaceStr(Result,s2,s3);
    until p=0;
  end;
end;
{------------------------------------------------------------------------------}
function TfrmRVParaList.FormatToEdit(const s: String; LevelNo: Integer): String;
var CountersVal: array [0..255] of TVarRec;
    CountersStr: array [0..255] of String;
    i: Integer;
begin
  for i := 0 to 255 do begin
    CountersStr[i] := '';
    CountersVal[i].VAnsiString := nil;
    CountersVal[i].VType := vtAnsiString;
  end;
  for i := 0 to LevelNo do begin
    CountersStr[i] := Format('<L%d>',[i+1]);
    CountersVal[i].VAnsiString := PChar(CountersStr[i]);
  end;
  Result := Format(s, CountersVal);
end;
{------------------------------------------------------------------------------}
procedure TfrmRVParaList.btnNumberFontClick(Sender: TObject);
begin
  fd.Font := rvs.ListStyles[0].Levels[GetXBoxItemIndex(_lstLevels)].Font;
  if fd.Execute then begin
    rvs.ListStyles[0].Levels[GetXBoxItemIndex(_lstLevels)].Font.Assign(fd.Font);
    GetEditFont(_txtNumbers).Assign(fd.Font);
    GetEditFont(_txtNumbers).Size := 8;
    GetEditFont(_txtNumbers).Color := clWindowText;
    MakeSample;
  end;
end;
{------------------------------------------------------------------------------}
procedure TfrmRVParaList.cmbLevelClick(Sender: TObject);
begin
  _btnInsert.Enabled := GetXBoxItemIndex(_cmbLevel)>=0;
end;
{------------------------------------------------------------------------------}
procedure TfrmRVParaList.btnInsertClick(Sender: TObject);
var s: String;
    SelStart: Integer;
begin
  if GetXBoxItemIndex(_cmbLevel)<0 then
    exit;
  s := Format('<L%d>',[GetXBoxItemIndex(_cmbLevel)+1]);
  SelStart := GetEditSelStart(_txtNumbers);
  SetEditSelText(_txtNumbers, s);
  TWinControl(_txtNumbers).SetFocus;
  SetEditSelStart(_txtNumbers, SelStart);
  SetEditSelLength(_txtNumbers, Length(s));
end;
{------------------------------------------------------------------------------}
procedure TfrmRVParaList.seLevelsChange(Sender: TObject);
var i, idx: Integer;

begin
  IgnoreLevelsClick := True;
  try
    idx := GetXBoxItemIndex(_lstLevels);
    ClearXBoxItems(_lstLevels);
    for i := 1 to seLevels.AsInteger do
      XBoxItemsAddObject(_lstLevels, IntToStr(i), nil);
    for i := rvs.ListStyles[0].Levels.Count to seLevels.AsInteger-1 do
      rvs.ListStyles[0].Levels.Add;
    if idx>=GetXBoxItemCount(_lstLevels) then
      idx := GetXBoxItemCount(_lstLevels)-1;
    SetXBoxItemIndex(_lstLevels, idx);
    SetControls(idx);
  finally
    IgnoreLevelsClick := False;
  end;
end;
{------------------------------------------------------------------------------}
procedure TfrmRVParaList.lstLevelsClick(Sender: TObject);
begin
  if IgnoreLevelsClick then
    exit;
  FStoredBullet := '';
  FStoredBulletFontName := '';
  FStoredBulletIndex := 5;

  FStoredNumber := Format('%%%d:s.', [GetXBoxItemIndex(_lstLevels)]);
  FStoredNumberFontName := 'Arial';
  FStoredNumberCharset  := ANSI_CHARSET;

  SetControls(GetXBoxItemIndex(_lstLevels));
end;
{------------------------------------------------------------------------------}
procedure TfrmRVParaList.btnImageClick(Sender: TObject);
var
  opd : TOpenPictureDialog;
begin
  opd := TOpenPictureDialog.Create(Self);
  opd.Options := [ofHideReadOnly,ofPathMustExist,ofFileMustExist,ofEnableSizing {,ofDontAddToRecent}];
  if opd.Execute then
    try
      img.Picture.LoadFromFile(opd.FileName);
      rvs.ListStyles[0].Levels[GetXBoxItemIndex(_lstLevels)].Picture.Graphic := img.Picture.Graphic;
      MakeSample;
    except
      RVA_MessageBox(RVA_GetSX(rvam_err_ErrorLoadingImageFile), RVA_GetSX(rvam_err_Title), MB_OK or MB_ICONSTOP);
    end;
  opd.Free;
end;
{------------------------------------------------------------------------------}
procedure TfrmRVParaList.cmbNumbersClick(Sender: TObject);
var LevelInfo: TRVListLevel;
begin
  LevelInfo := rvs.ListStyles[0].Levels[GetXBoxItemIndex(_lstLevels)];
  if LevelInfo.HasNumbering then begin
    FStoredNumber := LevelInfo.FormatString;
    FStoredNumberFontName := LevelInfo.Font.Name;
    FStoredNumberCharset := LevelInfo.Font.Charset;
  end;
  if LevelInfo.ListType in [rvlstBullet, rvlstUnicodeBullet] then begin
    if Length(LevelInfo.FormatString)=1 then
      FStoredBullet := LevelInfo.FormatString
    else
      FStoredBullet := '';
    FStoredBulletFontName := LevelInfo.Font.Name;
    FStoredBulletCharset := LevelInfo.Font.Charset;
    FStoredBulletIndex := rgBullet.ItemIndex;
    FBulletUnicode := LevelInfo.ListType=rvlstUnicodeBullet;
  end;
  if not LevelInfo.HasNumbering and (GetXBoxItemIndex(_cmbNumbers) in [1..5]) then begin
    if FStoredNumber<>'' then
      LevelInfo.FormatString := FStoredNumber;
    if FStoredNumberFontName<>'' then begin
      LevelInfo.Font.Name := FStoredNumberFontName;
      LevelInfo.Font.Charset := FStoredNumberCharset;
    end;
  end;
  case GetXBoxItemIndex(_cmbNumbers) of
    0:
      begin
        if LevelInfo.ListType in [rvlstBullet, rvlstUnicodeBullet] then
          exit;
        if LevelInfo.HasNumbering or (Length(LevelInfo.FormatString)<>1) then begin
          if FStoredBullet<>'' then
            LevelInfo.FormatString := FStoredBullet
          else
            LevelInfo.FormatString := '·';
          if FStoredBulletFontName<>'' then begin
            LevelInfo.Font.Name := FStoredBulletFontName;
            LevelInfo.Font.Charset := FStoredBulletCharset;
          end;
        end;
        if Length(LevelInfo.FormatStringW)<>1 then
          LevelInfo.FormatStringW := '·';
        if FBulletUnicode then
          LevelInfo.ListType := rvlstUnicodeBullet
        else
          LevelInfo.ListType := rvlstBullet;
      end;
    1:
      LevelInfo.ListType := rvlstDecimal;
    2:
      LevelInfo.ListType := rvlstUpperRoman;
    3:
      LevelInfo.ListType := rvlstLowerRoman;
    4:
      LevelInfo.ListType := rvlstUpperAlpha;
    5:
      LevelInfo.ListType := rvlstLowerAlpha;
    6:
      LevelInfo.ListType := rvlstPicture;
  end;
  SetControls2(GetXBoxItemIndex(_lstLevels));
end;
{------------------------------------------------------------------------------}
procedure TfrmRVParaList.rgBulletCustomDraw(Sender: TRVOfficeRadioGroup;
  ItemIndex: Integer; Canvas: TCanvas; const ARect: TRect;
  var DoDefault: Boolean);
var r: TRect;
begin
  r := ARect;
  Canvas.Font := BulletChars[ItemIndex].Font;
  Canvas.Brush.Style := bsClear;
  if BulletChars[ItemIndex].Unicode then
    DrawTextW(Canvas.Handle, PRVUnicodeChar(BulletChars[ItemIndex].TextW),
      Length(BulletChars[ItemIndex].TextW), r, DT_SINGLELINE or DT_CENTER or DT_VCENTER)
  else
    DrawText(Canvas.Handle, PChar(BulletChars[ItemIndex].Text),
      Length(BulletChars[ItemIndex].Text), r, DT_SINGLELINE or DT_CENTER or DT_VCENTER);
end;
{------------------------------------------------------------------------------}
procedure TfrmRVParaList.btnFontClick(Sender: TObject);
begin
  fd.Font := BulletChars[rgBullet.ItemIndex].Font;
  if fd.Execute then begin
    BulletChars[rgBullet.ItemIndex].Font.Assign(fd.Font);
    rvs.ListStyles[0].Levels[GetXBoxItemIndex(_lstLevels)].Font.Assign(fd.Font);
    rgBullet.Repaint;
    MakeSample;
  end;
end;
{------------------------------------------------------------------------------}
procedure TfrmRVParaList.btnBulletClick(Sender: TObject);
var frm: TfrmRVInsertSymbol;
  idx: Integer;
  ch: Word;
  cs: TFontCharset;
  fn: String;
  LevelInfo: TRVListLevel;
begin
  frm := TfrmRVInsertSymbol.Create(Application);
  try
    frm.SetControlCaption(frm._btnOk, RVA_GetS(rvam_btn_OK));
    frm.SetFormCaption(RVA_GetS(rvam_cul_BulletTitle));
    frm.HelpContext := 90501;
    idx := rgBullet.ItemIndex;
    if BulletChars[idx].Unicode then begin
      if BulletChars[idx].TextW<>'' then
        frm.Init(ord(BulletChars[idx].TextW[1]), BulletChars[idx].Font.Name, DEFAULT_CHARSET)
      else
        frm.Init(0, BulletChars[idx].Font.Name, DEFAULT_CHARSET)
      end
    else begin
      {$IFNDEF RVUNICODESTR}
      cs := BulletChars[idx].Font.Charset;
      if cs=DEFAULT_CHARSET then
        cs := ANSI_CHARSET;
      {$ELSE}
      cs := DEFAULT_CHARSET;
      {$ENDIF}
      if BulletChars[idx].Text<>'' then
        frm.Init(ord(BulletChars[idx].Text[1]), BulletChars[idx].Font.Name, cs)
      else
        frm.Init(0, BulletChars[idx].Font.Name, cs)      
    end;
    if frm.ShowModal=mrOk then begin
      frm.GetInfo(ch, fn, cs);
      BulletChars[idx].Font.Name := fn;
      BulletChars[idx].Font.Charset := cs;
      BulletChars[idx].Unicode := cs=DEFAULT_CHARSET;
      LevelInfo := rvs.ListStyles[0].Levels[GetXBoxItemIndex(_lstLevels)];
      LevelInfo.Font.Name := fn;
      LevelInfo.Font.Charset := cs;
      if BulletChars[idx].Unicode then begin
        LevelInfo.FormatStringW := WideChar(ch);
        LevelInfo.ListType := rvlstUnicodeBullet;
        BulletChars[idx].TextW := WideChar(ch);
        end
      else begin
        LevelInfo.FormatString := Chr(ch);
        LevelInfo.ListType := rvlstBullet;
        BulletChars[idx].Text := Chr(ch);
      end;
      rgBullet.Invalidate;
      MakeSample;
    end;
  finally
    frm.Free;
  end;
end;
{------------------------------------------------------------------------------}
procedure TfrmRVParaList.rgBulletClick(Sender: TObject);
var
  idx: Integer;
  LevelInfo: TRVListLevel;
begin
  if FUpdating then
    exit;
  LevelInfo := rvs.ListStyles[0].Levels[GetXBoxItemIndex(_lstLevels)];
  idx := rgBullet.ItemIndex;
  LevelInfo.Font.Assign(BulletChars[idx].Font);
  if BulletChars[idx].Unicode then begin
    LevelInfo.FormatStringW := BulletChars[idx].TextW;
    LevelInfo.ListType := rvlstUnicodeBullet;
    end
  else begin
    LevelInfo.FormatString := BulletChars[idx].Text;
    LevelInfo.ListType := rvlstBullet;
  end;
  MakeSample;
end;
{------------------------------------------------------------------------------}
procedure TfrmRVParaList.txtNumbersChange(Sender: TObject);
var LevelNo: Integer;
begin
  if FUpdating then
    exit;
  LevelNo := GetXBoxItemIndex(_lstLevels);
  rvs.ListStyles[0].Levels[LevelNo].FormatString := EditToFormat(GetEditText(_txtNumbers),LevelNo);
  MakeSample;
end;
{------------------------------------------------------------------------------}
procedure TfrmRVParaList.seStartAtChange(Sender: TObject);
begin
  if FUpdating then
    exit;
  rvs.ListStyles[0].Levels[GetXBoxItemIndex(_lstLevels)].StartFrom := seStartAt.AsInteger;
  MakeSample;
end;
{------------------------------------------------------------------------------}
procedure TfrmRVParaList.cmbMarkerAlignClick(Sender: TObject);
begin
  if FUpdating then
    exit;
  rvs.ListStyles[0].Levels[GetXBoxItemIndex(_lstLevels)].MarkerAlignment := TRVMarkerAlignment(GetXBoxItemIndex(_cmbMarkerAlign));
  MakeSample;
end;
{------------------------------------------------------------------------------}
procedure TfrmRVParaList.seMarkerIndentChange(Sender: TObject);
begin
  if FUpdating then
    exit;
  rvs.ListStyles[0].Levels[GetXBoxItemIndex(_lstLevels)].MarkerIndent := rvs.RVUnitsToUnits(seMarkerIndent.Value, RVA_Units);
  MakeSample;
end;
{------------------------------------------------------------------------------}
procedure TfrmRVParaList.seLeftIndentChange(Sender: TObject);
begin
  if FUpdating then
    exit;
  rvs.ListStyles[0].Levels[GetXBoxItemIndex(_lstLevels)].LeftIndent := rvs.RVUnitsToUnits(seLeftIndent.Value, RVA_Units);
  MakeSample;
end;
{------------------------------------------------------------------------------}
procedure TfrmRVParaList.seFirstIndentChange(Sender: TObject);
begin
  if FUpdating then
    exit;
  rvs.ListStyles[0].Levels[GetXBoxItemIndex(_lstLevels)].FirstIndent := rvs.RVUnitsToUnits(seFirstIndent.Value, RVA_Units);
  MakeSample;
end;
{------------------------------------------------------------------------------}
procedure TfrmRVParaList.MakeSample;
var i, StyleNo: Integer;
    LevelInfo: TRVListLevel;
begin
  if FUpdating then
    exit;
  rv.Clear;
  rvs2.ListStyles := rvs.ListStyles;

  rvs2.TextStyles[0].Charset := RVA_GetCharset;
  rvs2.TextStyles[1].Charset := RVA_GetCharset;  

  for i := 0 to rvs2.ListStyles[0].Levels.Count-1 do begin
    LevelInfo := rvs2.ListStyles[0].Levels[i];
    //LevelInfo.Font.Size := Round(LevelInfo.Font.Size);
    LevelInfo.LeftIndent := Round(LevelInfo.LeftIndent/2);
    LevelInfo.FirstIndent := Round(LevelInfo.FirstIndent/2);
    LevelInfo.MarkerIndent := Round(LevelInfo.MarkerIndent/2);
  end;

  for i := 0 to seLevels.AsInteger-1 do begin
    rv.SetListMarkerInfo(-1, 0, i, 1, 0, False);
    if i=GetXBoxItemIndex(_lstLevels) then
      StyleNo := 1
    else
      StyleNo := 0;
    {$IFDEF RVUNICODESTR}rv.AddNLWTag{$ELSE}rv.AddNLATag{$ENDIF}
      (RVA_GetS(rvam_cul_PreviewText), StyleNo, -1, i);
    rv.SetAddParagraphMode(False);
    {$IFDEF RVUNICODESTR}rv.AddNLWTag{$ELSE}rv.AddNLATag{$ENDIF}
      (RVA_GetS(rvam_cul_PreviewText), StyleNo, 0, i);
    rv.SetAddParagraphMode(True);
  end;
  rv.Format;
end;

{================================== TBulletCharacter ==========================}
constructor TBulletCharacter.Create;
begin
  inherited;
  Font := TFont.Create
end;
{------------------------------------------------------------------------------}
destructor TBulletCharacter.Destroy;
begin
  Font.Free;
  inherited;
end;

procedure InitBullets;
begin
  BulletChars[0] := TBulletCharacter.Create;
  BulletChars[0].Font.Name := 'Symbol';
  BulletChars[0].Font.Size := 12;
  BulletChars[0].Font.Charset := SYMBOL_CHARSET;
  BulletChars[0].Text := RVCHAR_MIDDLEDOT;

  BulletChars[1] := TBulletCharacter.Create;
  BulletChars[1].Font.Name := 'Courier New';
  BulletChars[1].Font.Size := 12;
  BulletChars[1].Font.Charset := ANSI_CHARSET;
  BulletChars[1].Text := 'o';

  BulletChars[2] := TBulletCharacter.Create;
  BulletChars[2].Font.Name := 'Wingdings';
  BulletChars[2].Font.Size := 12;
  BulletChars[2].Font.Charset := SYMBOL_CHARSET;
  BulletChars[2].Text := {$IFDEF RVUNICODESTR}#$00A7{$ELSE}#$A7{$ENDIF};

  BulletChars[3] := TBulletCharacter.Create;
  BulletChars[3].Font.Name := 'Wingdings';
  BulletChars[3].Font.Size := 12;
  BulletChars[3].Font.Charset := SYMBOL_CHARSET;
  BulletChars[3].Text := 'q';

  BulletChars[4] := TBulletCharacter.Create;
  BulletChars[4].Font.Name := 'Wingdings';
  BulletChars[4].Font.Size := 12;
  BulletChars[4].Font.Charset := SYMBOL_CHARSET;
  BulletChars[4].Text := 'v';

  BulletChars[5] := TBulletCharacter.Create;
  BulletChars[5].Font.Name := 'Wingdings';
  BulletChars[5].Font.Size := 12;
  BulletChars[5].Font.Charset := SYMBOL_CHARSET;
  BulletChars[5].Text := {$IFDEF RVUNICODESTR}#$00FC{$ELSE}#$FC{$ENDIF};
end;

procedure DoneBullets;
var i: Integer;
begin
  for i := 0 to 5 do begin
    BulletChars[i].Free;
    BulletChars[i] := nil;
  end;
end;

procedure TfrmRVParaList.rvJump(Sender: TObject; id: Integer);
begin
  SetXBoxItemIndex(_lstLevels, rv.GetItemTag(rv.GetJumpPointItemNo(id)));
  lstLevelsClick(Sender);
end;

procedure TfrmRVParaList.FormCreate(Sender: TObject);
begin
  _btnInsert := btnInsert;
  _gbListTextPos := gbListTextPos;
  _gbListProperties := gbListProperties;
  _cbOneLevelPreview := cbOneLevelPreview;
  _cmbNumbers := cmbNumbers;
  _cmbLevel := cmbLevel;
  _cmbMarkerAlign := cmbMarkerAlign;
  _lblStartAt := lblStartAt;
  _txtNumbers := txtNumbers;
  _lstLevels := lstLevels;
  inherited;
  FStoredBullet := '';
  FStoredBulletFontName := '';
  FStoredBulletIndex := 5;

  FStoredNumber := '%0:s.';
  FStoredNumberFontName := 'Arial';
  FStoredNumberCharset  := ANSI_CHARSET;
end;

procedure TfrmRVParaList.GetListStyle(ListStyle: TRVListInfo);
begin
  ListStyle.Assign(rvs.ListStyles[0]);
  ListStyle.OneLevelPreview :=  GetCheckBoxChecked(_cbOneLevelPreview);
end;

procedure TfrmRVParaList.Localize;
begin
  inherited;
  btnOk.Caption := RVA_GetS(rvam_btn_OK);
  btnCancel.Caption := RVA_GetS(rvam_btn_Cancel);
  Caption := {$IFDEF USERVTNT}_GetWideString{$ENDIF}(RVA_GetS(rvam_cul_Title));
  gbLevels.Caption := RVA_GetSH(rvam_cul_Levels);
  lblLevelCount.Caption := RVA_GetS(rvam_cul_LevelCount);
  gbListProperties.Caption := RVA_GetSH(rvam_cul_ListProperties);
  lblNumber.Caption := RVA_GetS(rvam_cul_ListType);
  lblNumFormat.Caption := RVA_GetS(rvam_cul_NumberFormat);
  gbNumber.Caption := RVA_GetSH(rvam_cul_Number);
  lblStartAt.Caption := RVA_GetS(rvam_cul_StartFrom);
  btnNumberFont.Caption := RVA_GetS(rvam_cul_Font);
  cmbNumbers.Items[0] := RVA_GetS(rvam_cul_ListTypeBullet);
  cmbNumbers.Items[6] := RVA_GetS(rvam_cul_ListTypeImage);
  btnInsert.Hint := RVA_GetS(rvam_cul_InsertNumberHint);
  gbListTextPos.Caption := RVA_GetSHUnits(rvam_cul_ListTextPos, RVA_Units);
  gbTextPos.Caption := RVA_GetSHUnits(rvam_cul_TextPos, RVA_Units);
  lblLI.Caption := RVA_GetS(rvam_cul_LeftIndent);
  lblFI.Caption := RVA_GetS(rvam_cul_FirstIndent);
  lblFLI.Caption := RVA_GetS(rvam_cul_FromLeftIndent);
  cbOneLevelPreview.Caption  := RVA_GetS(rvam_cul_OneLevelPreview);
  btnImage.Caption := RVA_GetS(rvam_cul_Image);
  rgBullet.Caption := RVA_GetSH(rvam_cul_BulletCharacter);
  btnBullet.Caption := RVA_GetS(rvam_cul_Bullet);
  btnFont.Caption := RVA_GetS(rvam_cul_Font);
  gbPreview.Caption := RVA_GetSH(rvam_cul_Preview);
  lblAt.Caption := RVA_GetS(rvam_cul_At);
  cmbMarkerAlign.Items[0] := RVA_GetS(rvam_cul_Left);
  cmbMarkerAlign.Items[1] := RVA_GetS(rvam_cul_Right);
  cmbMarkerAlign.Items[2] := RVA_GetS(rvam_cul_Center);
end;

{$IFDEF RVASKINNED}
procedure TfrmRVParaList.OnCreateThemedControl(OldControl,
  NewControl: TControl);
begin
  if OldControl = _btnInsert then
    _btnInsert := NewControl
  else if OldControl = _gbListTextPos then
    _gbListTextPos := NewControl
  else if OldControl = _gbListProperties then
    _gbListProperties := NewControl
  else if OldControl = _cbOneLevelPreview then
    _cbOneLevelPreview := NewControl
  else if OldControl = _cmbNumbers then
    _cmbNumbers := NewControl
  else if OldControl = _cmbLevel then
    _cmbLevel := NewControl
  else if OldControl = _cmbMarkerAlign then
    _cmbMarkerAlign := NewControl
  else if OldControl = _lblStartAt then
    _lblStartAt := NewControl
  else if OldControl = _txtNumbers then
    _txtNumbers := NewControl
  else if OldControl = _lstLevels then
    _lstLevels := NewControl
end;
{$ENDIF}

initialization
  InitBullets;
finalization
  DoneBullets;

end.
