unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, Buttons, ComCtrls, ExtCtrls, Menus,
  RVStyle, RVScroll, RichView, RVEdit, RVFuncs, RVNote, PtblRV, RVItem, RVTable;

{==============================================================================}
{ RichEditor Demo with footnotes, endnotes and print preview.
  See "Notes" main menu.
{==============================================================================}

type
  TDemoFileFormat = (dffRVF, dffRTF);


  TForm1 = class(TForm)
    Panel1: TPanel;
    StatusBar1: TStatusBar;
    rvs: TRVStyle;
    cmbFont: TComboBox;
    btnBold: TSpeedButton;
    btnItalic: TSpeedButton;
    btnUnderline: TSpeedButton;
    btnFont: TSpeedButton;
    btnLeft: TSpeedButton;
    btnCenter: TSpeedButton;
    btnRight: TSpeedButton;
    btnJustify: TSpeedButton;
    btnOpen: TSpeedButton;
    btnSave: TSpeedButton;
    btnSaveAs: TSpeedButton;
    btnNew: TSpeedButton;
    cmbFontSize: TComboBox;
    Label2: TLabel;
    Label3: TLabel;
    MainMenu1: TMainMenu;
    File1: TMenuItem;
    mitOpen: TMenuItem;
    mitSave: TMenuItem;
    mitNew: TMenuItem;
    mitSaveAs: TMenuItem;
    N1: TMenuItem;
    mitExit: TMenuItem;
    Edit1: TMenuItem;
    mitUndo: TMenuItem;
    mitRedo: TMenuItem;
    N2: TMenuItem;
    mitCut: TMenuItem;
    mitCopy: TMenuItem;
    mitPaste: TMenuItem;
    mitDelete: TMenuItem;
    od: TOpenDialog;
    sd: TSaveDialog;
    fd: TFontDialog;
    btnIdentInc: TSpeedButton;
    btnIdentDec: TSpeedButton;
    btnFontColor: TSpeedButton;
    btnFontBackColor: TSpeedButton;
    SpeedButton1: TSpeedButton;
    cd: TColorDialog;
    Panel2: TPanel;
    rveMain: TRichViewEdit;
    Splitter1: TSplitter;
    rveNote: TRichViewEdit;
    Endnotes1: TMenuItem;
    mitInsertEndnote: TMenuItem;
    N3: TMenuItem;
    mitInsertNoteReference: TMenuItem;
    RVPrint1: TRVPrint;
    N4: TMenuItem;
    mitPreview: TMenuItem;
    mitInsertFootnote: TMenuItem;
    procedure mitNewClick(Sender: TObject);
    procedure mitOpenClick(Sender: TObject);
    procedure mitSaveClick(Sender: TObject);
    procedure mitSaveAsClick(Sender: TObject);
    procedure mitExitClick(Sender: TObject);
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
    procedure rveChange(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure rveCurTextStyleChanged(Sender: TObject);
    procedure rveCurParaStyleChanged(Sender: TObject);
    procedure cmbFontClick(Sender: TObject);
    procedure rveStyleConversion(Sender: TCustomRichViewEdit; StyleNo,
      UserData: Integer; AppliedToText: Boolean; var NewStyleNo: Integer);
    procedure mitUndoClick(Sender: TObject);
    procedure mitRedoClick(Sender: TObject);
    procedure mitCutClick(Sender: TObject);
    procedure mitCopyClick(Sender: TObject);
    procedure mitPasteClick(Sender: TObject);
    procedure mitDeleteClick(Sender: TObject);
    procedure mitFontClick(Sender: TObject);
    procedure btnApplyParaClick(Sender: TObject);
    procedure cmbFontSizeClick(Sender: TObject);
    procedure cmbFontSizeKeyPress(Sender: TObject; var Key: Char);
    procedure cmbFontSizeExit(Sender: TObject);
    procedure FontStyleButtonClick(Sender: TObject);
    procedure rveParaStyleConversion(Sender: TCustomRichViewEdit; StyleNo,
      UserData: Integer; AppliedToText: Boolean; var NewStyleNo: Integer);
    procedure btnIdentDecClick(Sender: TObject);
    procedure btnIdentIncClick(Sender: TObject);
    procedure btnFontColorClick(Sender: TObject);
    procedure btnFontBackColorClick(Sender: TObject);
    procedure SpeedButton1Click(Sender: TObject);
    procedure rveNoteEnter(Sender: TObject);
    procedure mitInsertEndnoteClick(Sender: TObject);
    procedure rveMainCaretMove(Sender: TObject);
    procedure rveMainEnter(Sender: TObject);
    procedure rveNoteExit(Sender: TObject);
    procedure mitInsertNoteReferenceClick(Sender: TObject);
    procedure mitPreviewClick(Sender: TObject);
    procedure mitInsertFootnoteClick(Sender: TObject);
  private
    { Private declarations }
    FileName, FontName: String;
    FileFormat: TDemoFileFormat;
    IgnoreChanges: Boolean;
    FontSize: Integer;
    ActiveEditor: TCustomRichViewEdit;
    FActiveNoteItem: TCustomRVNoteItemInfo;
    function SaveIfNeeded: Boolean;
    function Save: Boolean;
    function SaveAs: Boolean;
    procedure Open;
    procedure New;
    function GetAlignmentFromUI: TRVAlignment;
    procedure SetAlignmentToUI(Alignment: TRVAlignment);
    procedure DisableNote(Init: Boolean=False);
    procedure EditNote(NoteItem: TCustomRVNoteItemInfo);
    procedure UpdateNote;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

uses PreviewFrm;

// Parameters for ApplyStyleConversion
const
  TEXT_BOLD       = 1;
  TEXT_ITALIC     = 2;
  TEXT_UNDERLINE  = 3;
  TEXT_APPLYFONTNAME  = 4;
  TEXT_APPLYFONT      = 5;
  TEXT_APPLYFONTSIZE  = 6;
  TEXT_COLOR      = 7;
  TEXT_BACKCOLOR  = 8;
// Parameters for ApplyParaStyleConversion
  PARA_ALIGNMENT  = 1;
  PARA_INDENTINC  = 2;
  PARA_INDENTDEC  = 3;
  PARA_COLOR      = 4;

{$R *.DFM}
{------------------------------------------------------------------------------}
procedure TForm1.FormCreate(Sender: TObject);
begin
  // Filling font names combobox
  cmbFont.Items.Assign(Screen.Fonts);
  ActiveEditor := rveMain;
  New;
end;
{------------------------------------------------------------------------------}
{ Document in rveMain or rveNote was changed }
procedure TForm1.rveChange(Sender: TObject);
begin
  StatusBar1.SimpleText := 'Modified';
end;
{------------------------------------------------------------------------------}
{ Current text style in rveMain or rveNote was changed }
procedure TForm1.rveCurTextStyleChanged(Sender: TObject);
var fi: TFontInfo;
    rve: TCustomRichViewEdit;
begin
  rve := TCustomRichViewEdit(Sender).GetRootEditor;
  if rve<>ActiveEditor then
    exit;
  IgnoreChanges := True;
  // Changing selection in comboboxes with font names and sizes:
  fi := rvs.TextStyles[rve.CurTextStyleNo];
  cmbFont.ItemIndex := cmbFont.Items.IndexOf(fi.FontName);
  cmbFontSize.Text := IntToStr(fi.Size);
  // Checking font buttons
  btnBold.Down      := fsBold      in fi.Style;
  btnItalic.Down    := fsItalic    in fi.Style;
  btnUnderline.Down := fsUnderline in fi.Style;
  IgnoreChanges := False;
end;
{------------------------------------------------------------------------------}
{ Current paragraph style in rveMain or rveNote was changed }
procedure TForm1.rveCurParaStyleChanged(Sender: TObject);
var rve: TCustomRichViewEdit;
begin
  rve := TCustomRichViewEdit(Sender).GetRootEditor;
  if rve<>ActiveEditor then
    exit;
  SetAlignmentToUI(rvs.ParaStyles[rve.CurParaStyleNo].Alignment);
end;
{------------------------------------------------------------------------------}
{ Returns paragraph alignment selected in the toolbar }
function TForm1.GetAlignmentFromUI: TRVAlignment;
begin
  if btnLeft.Down then
    Result := rvaLeft
  else if btnRight.Down then
    Result := rvaRight
  else if btnCenter.Down then
    Result := rvaCenter
  else
    Result := rvaJustify;
end;
{------------------------------------------------------------------------------}
{ Sets Alignment to the toolbar }
procedure TForm1.SetAlignmentToUI(Alignment: TRVAlignment);
begin
  case Alignment of
    rvaLeft:
      btnLeft.Down := True;
    rvaCenter:
      btnCenter.Down := True;
    rvaRight:
      btnRight.Down := True;
    rvaJustify:
      btnJustify.Down := True;
  end;
end;
{------------------------------------------------------------------------------}
{ Applying font name to ActiveEditor }
procedure TForm1.cmbFontClick(Sender: TObject);
begin

  if (cmbFont.ItemIndex<>-1) then begin
    if not IgnoreChanges then begin
      FontName := cmbFont.Items[cmbFont.ItemIndex];
      ActiveEditor.ApplyStyleConversion(TEXT_APPLYFONTNAME);
    end;
  end;
  if Visible then
    ActiveEditor.SetFocus;
end;
{------------------------------------------------------------------------------}
{ Applying font size to ActiveEditor }
procedure TForm1.cmbFontSizeClick(Sender: TObject);
begin
  if (cmbFontSize.Text<>'') and not IgnoreChanges then begin
      FontSize := StrToIntDef(cmbFontSize.Text, 10);
      ActiveEditor.ApplyStyleConversion(TEXT_APPLYFONTSIZE);
  end;
  if Visible then
    ActiveEditor.SetFocus;
end;
{------------------------------------------------------------------------------}
{ Applying bold/italic/underline to ActiveEditor }
procedure TForm1.FontStyleButtonClick(Sender: TObject);
var Button: TSpeedButton;
begin
  Button := Sender as TSpeedButton;
  // constants TEXT_BOLD, TEXT_ITALIC and TEXT_UNDERLINE are
  // assigned to the tags of corresponding buttons
  ActiveEditor.ApplyStyleConversion(Button.Tag);
end;
{------------------------------------------------------------------------------}
{ Applying font to ActiveEditor }
procedure TForm1.mitFontClick(Sender: TObject);
begin
  fd.Font.Assign(rvs.TextStyles[ActiveEditor.CurTextStyleNo]);
  if fd.Execute then begin
    ActiveEditor.ApplyStyleConversion(TEXT_APPLYFONT);
  end;
end;
{------------------------------------------------------------------------------}
{ Applying text color to ActiveEditor }
procedure TForm1.btnFontColorClick(Sender: TObject);
begin
  cd.Color := rvs.TextStyles[ActiveEditor.CurTextStyleNo].Color;
  if cd.Execute then
    ActiveEditor.ApplyStyleConversion(TEXT_COLOR);
end;
{------------------------------------------------------------------------------}
{ Applying text background color to ActiveEditor }
procedure TForm1.btnFontBackColorClick(Sender: TObject);
begin
  case Application.MessageBox('Make the selected text background transparent?'#13+
                            '(YES - make transparent; NO - choose color)',
                            'Text Background', MB_YESNOCANCEL or MB_ICONQUESTION) of
    IDYES:
      cd.Color := clNone;
    IDNO:
      begin
        cd.Color := rvs.TextStyles[ActiveEditor.CurTextStyleNo].BackColor;
        if cd.Color=clNone then
          cd.Color := clWhite;
        if not cd.Execute then
          exit;
      end;
    IDCANCEL:
      exit;
  end;
  ActiveEditor.ApplyStyleConversion(TEXT_BACKCOLOR);
end;
{------------------------------------------------------------------------------}
{ Applying paragraph background color to ActiveEditor }
procedure TForm1.SpeedButton1Click(Sender: TObject);
begin
  case Application.MessageBox('Make the selected paragraph background transparent?'#13+
                            '(YES - make transparent; NO - choose color)',
                            'Text Background', MB_YESNOCANCEL or MB_ICONQUESTION) of
    IDYES:
      cd.Color := clNone;
    IDNO:
      begin
        cd.Color := rvs.ParaStyles[ActiveEditor.CurParaStyleNo].Background.Color;
        if cd.Color=clNone then
          cd.Color := clWhite;
        if not cd.Execute then
          exit;
      end;
    IDCANCEL:
      exit;
  end;
  ActiveEditor.ApplyParaStyleConversion(PARA_COLOR);
end;
{------------------------------------------------------------------------------}
{ Applying paragraph alignment to ActiveEditor }
procedure TForm1.btnApplyParaClick(Sender: TObject);
begin
  ActiveEditor.ApplyParaStyleConversion(PARA_ALIGNMENT);
end;
{------------------------------------------------------------------------------}
{ changing left indents in ActiveEditor }
procedure TForm1.btnIdentDecClick(Sender: TObject);
begin
  ActiveEditor.ApplyParaStyleConversion(PARA_INDENTDEC);
end;

procedure TForm1.btnIdentIncClick(Sender: TObject);
begin
  ActiveEditor.ApplyParaStyleConversion(PARA_INDENTINC);
end;
{------------------------------------------------------------------------------}
{ rveMain's & rveNote's OnStyleConversion }
procedure TForm1.rveStyleConversion(Sender: TCustomRichViewEdit; StyleNo,
  UserData: Integer; AppliedToText: Boolean; var NewStyleNo: Integer);
var FontInfo: TFontInfo;
begin
  FontInfo := TFontInfo.Create(nil);
  try
    FontInfo.Assign(rvs.TextStyles[StyleNo]);
    case UserData of
      TEXT_BOLD:
        if btnBold.Down then
          FontInfo.Style := FontInfo.Style+[fsBold]
        else
          FontInfo.Style := FontInfo.Style-[fsBold];
      TEXT_ITALIC:
        if btnItalic.Down then
          FontInfo.Style := FontInfo.Style+[fsItalic]
        else
          FontInfo.Style := FontInfo.Style-[fsItalic];
      TEXT_UNDERLINE:
        if btnUnderline.Down then
          FontInfo.Style := FontInfo.Style+[fsUnderline]
        else
          FontInfo.Style := FontInfo.Style-[fsUnderline];
      TEXT_APPLYFONTNAME:
        FontInfo.FontName := FontName;
      TEXT_APPLYFONTSIZE:
        FontInfo.Size     := FontSize;
      TEXT_APPLYFONT:
        FontInfo.Assign(fd.Font);
      TEXT_COLOR:
        FontInfo.Color := cd.Color;
      TEXT_BACKCOLOR:
        FontInfo.BackColor := cd.Color;
      // add your code here....
    end;
    NewStyleNo := rvs.TextStyles.FindSuchStyle(StyleNo,FontInfo,RVAllFontInfoProperties);
    if NewStyleNo=-1 then begin
      rvs.TextStyles.Add;
      NewStyleNo := rvs.TextStyles.Count-1;
      rvs.TextStyles[NewStyleNo].Assign(FontInfo);
      rvs.TextStyles[NewStyleNo].Standard := False;
    end;
  finally
    FontInfo.Free;
  end;
end;
{------------------------------------------------------------------------------}
{ rveMain's & rveNote's OnParaStyleConversion }
procedure TForm1.rveParaStyleConversion(Sender: TCustomRichViewEdit;
  StyleNo, UserData: Integer; AppliedToText: Boolean;
  var NewStyleNo: Integer);
var ParaInfo: TParaInfo;
begin
  ParaInfo := TParaInfo.Create(nil);
  try
    ParaInfo.Assign(rvs.ParaStyles[StyleNo]);
    case UserData of
      PARA_ALIGNMENT:
        ParaInfo.Alignment := GetAlignmentFromUI;
      PARA_INDENTINC:
        begin
          ParaInfo.LeftIndent := ParaInfo.LeftIndent+20;
          if ParaInfo.LeftIndent>200 then
            ParaInfo.LeftIndent := 200;
        end;
      PARA_INDENTDEC:
        begin
          ParaInfo.LeftIndent := ParaInfo.LeftIndent-20;
          if ParaInfo.LeftIndent<0 then
            ParaInfo.LeftIndent := 0;
        end;
      PARA_COLOR:
        ParaInfo.Background.Color := cd.Color;
      // add your code here....
    end;
    NewStyleNo := rvs.ParaStyles.FindSuchStyle(StyleNo,ParaInfo,RVAllParaInfoProperties);
    if NewStyleNo=-1 then begin
      rvs.ParaStyles.Add;
      NewStyleNo := rvs.ParaStyles.Count-1;
      rvs.ParaStyles[NewStyleNo].Assign(ParaInfo);
      rvs.ParaStyles[NewStyleNo].Standard := False;
    end;
  finally
    ParaInfo.Free;
  end;
end;
{------------------------------------------------------------------------------}
{ cmbFontSize combobox: Enter key triggers OnClick }
procedure TForm1.cmbFontSizeKeyPress(Sender: TObject; var Key: Char);
begin
  if ord(Key)=VK_RETURN then begin
    Key := #0;
    cmbFontSizeClick(nil);
  end;
end;
{------------------------------------------------------------------------------}
{ cmbFontSize combobox: moving focus from it triggers OnClick }
procedure TForm1.cmbFontSizeExit(Sender: TObject);
begin
  cmbFontSizeClick(nil);
end;
{------------------------------------------------------------------------------}
{ Menu Edit | Undo }
procedure TForm1.mitUndoClick(Sender: TObject);
begin
  ActiveEditor.Undo;
end;
{------------------------------------------------------------------------------}
{ Menu Edit | Redo }
procedure TForm1.mitRedoClick(Sender: TObject);
begin
  ActiveEditor.Redo;
end;
{------------------------------------------------------------------------------}
{ Menu Edit | Cut }
procedure TForm1.mitCutClick(Sender: TObject);
begin
  ActiveEditor.CutDef;
end;
{------------------------------------------------------------------------------}
{ Menu Edit | Copy }
procedure TForm1.mitCopyClick(Sender: TObject);
begin
  ActiveEditor.CopyDef;
end;
{------------------------------------------------------------------------------}
{ Menu Edit | Paste }
procedure TForm1.mitPasteClick(Sender: TObject);
begin
  ActiveEditor.Paste;
end;
{------------------------------------------------------------------------------}
{ Menu Edit | Delete }
procedure TForm1.mitDeleteClick(Sender: TObject);
begin
  ActiveEditor.DeleteSelection;
end;
{------------------------------------------------------------------------------}
{ Saves note text (if it was edited) in the main document, then asks user
  to save the document.
  Returns True if:
  - the user answers "No", or
  - the user answers "Yes" and the document was saved.
  Returns False if:
  - the user answers "Cancel", or
  - the user answers "Yes" and the document was not saved. }
function TForm1.SaveIfNeeded: Boolean;
begin
  Result := True;
  UpdateNote;
  if rveMain.Modified then
    case Application.MessageBox('Save file now?','File was modified',
      MB_ICONQUESTION or MB_YESNOCANCEL) of
      IDYES:
        Result := Save;
      IDNO:
        Result := True;
      IDCANCEL:
        Result := False;
    end;
end;
{------------------------------------------------------------------------------}
{ Saves the document. If this is a new document, calls SaveAs.
  Returns True on successful saving }
function TForm1.Save: Boolean;
begin
  if FileName='' then
    Result := SaveAs
  else begin
    UpdateNote;
    Result := False;
    case FileFormat of
      dffRVF:
        Result := rveMain.SaveRVF(FileName, False);
      dffRTF:
        Result := rveMain.SaveRTF(FileName, False);
    end;
    if Result then begin
      rveMain.Modified := False;
      StatusBar1.SimpleText := '';
      end
    else begin
      Application.MessageBox('Cannot save file','Error', MB_OK or MB_ICONSTOP);
      Result := SaveAs;
    end;
  end;
end;
{------------------------------------------------------------------------------}
{ Displays save dialog and calls Save to save document.
  Returns True on successful saving }
function TForm1.SaveAs: Boolean;
begin
  sd.FileName := FileName;
  sd.FilterIndex := ord(FileFormat)+1;
  if sd.Execute then begin
    FileName := sd.FileName;
    FileFormat := TDemoFileFormat(sd.FilterIndex-1);
    Result := Save;
    if Result then
      Caption := ExtractFileName(FileName) + '- RDemo';
    end
  else
    Result := False;
end;
{------------------------------------------------------------------------------}
{ Asks to save the existing document.
  Opens document from file }
procedure TForm1.Open;
var r: Boolean;
begin
  if not SaveIfNeeded then exit;
  rveMain.Modified := False;
  New;
  if od.Execute then begin
    r := False;
    DisableNote;
    rveMain.Clear;
    rveMain.DeleteUnusedStyles(True, True, True);
    FileName := od.FileName;
    case od.FilterIndex of
      1:
        begin
          r := rveMain.LoadRVF(FileName);
          FileFormat := dffRVF;
        end;
      2:
        begin
          r := rveMain.LoadRTF(FileName);
          FileFormat := dffRTF;
        end;
    end;
    rveMain.Format;
    rveCurTextStyleChanged(ActiveEditor);
    rveCurParaStyleChanged(ActiveEditor);
    DisableNote(True);
    StatusBar1.SimpleText := '';
    Caption := ExtractFileName(FileName) + '- RDemo';
    if not r then
      Application.MessageBox('Error while opening or reading file','Error',
        MB_OK or MB_ICONSTOP);
  end;
end;
{------------------------------------------------------------------------------}
{ Asks to save the existing document. Creates a new document }
procedure TForm1.New;
begin
  if not SaveIfNeeded then exit;
  FileName := '';
  FileFormat := dffRVF;
  StatusBar1.SimpleText := '';
  Caption := 'Unnamed - RDemo';
  DisableNote(True);
  rveMain.LeftMargin := 5;
  rveMain.RightMargin := 5;
  rveMain.TopMargin := 5;
  rveMain.BottomMargin := 5;
  rveMain.BackgroundBitmap := nil;
  rveMain.BackgroundStyle := bsNoBitmap;
  rveMain.Clear;
  rveMain.DeleteUnusedStyles(True, True, True);
  rveMain.Format;
  rveCurTextStyleChanged(ActiveEditor);
  rveCurParaStyleChanged(ActiveEditor);
end;
{------------------------------------------------------------------------------}
{ Menu File | New }
procedure TForm1.mitNewClick(Sender: TObject);
begin
  New;
end;
{------------------------------------------------------------------------------}
{ Menu File | Open }
procedure TForm1.mitOpenClick(Sender: TObject);
begin
  Open;
end;
{------------------------------------------------------------------------------}
{ Menu File | Save }
procedure TForm1.mitSaveClick(Sender: TObject);
begin
  Save;
end;
{------------------------------------------------------------------------------}
{ Menu File | Save As }
procedure TForm1.mitSaveAsClick(Sender: TObject);
begin
  SaveAs;
end;
{------------------------------------------------------------------------------}
{ Menu File | Print Preview }
procedure TForm1.mitPreviewClick(Sender: TObject);
var frm: TfrmPreview;
begin
  UpdateNote;
  RVPrint1.AssignSource(rveMain);
  RVPrint1.FormatPages(rvdoALL);
  frm := TfrmPreview.Create(Application);
  try
    frm.rvpp.RVPrint := RVPrint1;
    frm.Button1Click(nil);
    frm.ShowModal;
  finally
    frm.Free;
  end;
  RVPrint1.Clear;
end;
{------------------------------------------------------------------------------}
{ Menu File | Exit }
procedure TForm1.mitExitClick(Sender: TObject);
begin
  Close;
end;
{------------------------------------------------------------------------------}
{ Form1.OnCloseQuery }
procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
  CanClose := SaveIfNeeded;
end;
{------------------------------------------------------------------------------}
{ Occurs when input focus is set to rveMain }
procedure TForm1.rveMainEnter(Sender: TObject);
begin
  ActiveEditor := rveMain;
  rveCurTextStyleChanged(ActiveEditor);
  rveCurParaStyleChanged(ActiveEditor);
  mitInsertFootnote.Enabled := True;
  mitInsertEndnote.Enabled := True;
  mitInsertNoteReference.Enabled := False;
end;
{------------------------------------------------------------------------------}
{ Occurs when input focus is set to rveNote }
procedure TForm1.rveNoteEnter(Sender: TObject);
begin
  ActiveEditor := rveNote;
  rveCurTextStyleChanged(ActiveEditor);
  rveCurParaStyleChanged(ActiveEditor);
  mitInsertFootnote.Enabled := False;
  mitInsertEndnote.Enabled := False;
  mitInsertNoteReference.Enabled := True;
end;
{------------------------------------------------------------------------------}
{ Disables rveNote }
procedure TForm1.DisableNote(Init: Boolean);
begin
  if Init or (FActiveNoteItem<>nil) then begin
    FActiveNoteItem := nil;
    rveNote.Enabled := False;
    rveNote.Color := clBtnFace;
    rveNote.Clear;
    rveNote.AddNL('(footnote or endnote is not selected)', 0, 0);
    rveNote.Format;
  end;
end;
{------------------------------------------------------------------------------}
{ Starts editing NoteItem's Document in rveNote }
procedure TForm1.EditNote(NoteItem: TCustomRVNoteItemInfo);
var Stream: TMemoryStream;
begin
  if FActiveNoteItem = NoteItem then
    exit;
  FActiveNoteItem := NoteItem;
  rveNote.NoteText := NoteItem.Text; // this text is displayed in
                                     // TRVNoteReferenceItemInfo items

  rveNote.Enabled := True;
  rveNote.Color := clWindow;
  rveNote.Clear;
  Stream := TMemoryStream.Create;
  try
    NoteItem.Document.SaveRVFToStream(Stream);
    Stream.Position := 0;
    rveNote.LoadRVFFromStream(Stream);
  finally
    Stream.Free;
  end;
  with rveNote do begin
    Format;
    SetSelectionBounds(ItemCount-1, GetOffsAfterItem(ItemCount-1),
      ItemCount-1, GetOffsAfterItem(ItemCount-1));
  end;
end;
{------------------------------------------------------------------------------}
{ Saves changes made in rveNote to FActiveNoteItem.Document. This operation
  can be undone and redone by the user  }
procedure TForm1.UpdateNote;
var Stream: TMemoryStream;
begin
  if not rveNote.Modified then
    exit;
  Stream := TMemoryStream.Create;
  try
    rveNote.SaveRVFToStream(Stream, False);
    FActiveNoteItem.ReplaceDocumentEd(Stream); // this is an editing operation
                                               // in rveMain, can be undone by user
  finally
    Stream.Free;
  end;
  rveNote.Modified := False;
end;
{------------------------------------------------------------------------------}
{ Menu Notes | Insert Endnote.
  This command is enabled only if ActiveEditor = rveMain.
  This command inserts a new endnote in rveMain. In the endnote document, it
  adds the note reference (TRVNoteReferenceItemInfo, displays endnote number)
  and one space character. Because of rveMain.CaretMove, this endnote will be
  immediately opened in rveNote.
  Moving input focus to rveNote }
procedure TForm1.mitInsertEndnoteClick(Sender: TObject);
var EndNote: TRVEndnoteItemInfo;
    NoteRef: TRVNoteReferenceItemInfo;
begin
  EndNote := TRVEndnoteItemInfo.CreateEx(rveMain.RVData,
    RVGetNoteTextStyleNo(rvs, rveMain.CurTextStyleNo), 1, False);
  NoteRef := TRVNoteReferenceItemInfo.CreateEx(EndNote.Document, RVGetNoteTextStyleNo(rvs,0));
  EndNote.Document.AddItem('', NoteRef);
  EndNote.Document.AddNL(' ', 0, -1);
  if rveMain.InsertItem('', EndNote) then
    rveNote.SetFocus;
end;
{------------------------------------------------------------------------------}
{ Menu Notes | Insert Footnote. }
procedure TForm1.mitInsertFootnoteClick(Sender: TObject);
var FootNote: TRVFootnoteItemInfo;
    NoteRef: TRVNoteReferenceItemInfo;
begin
  FootNote := TRVFootnoteItemInfo.CreateEx(rveMain.RVData,
    RVGetNoteTextStyleNo(rvs, rveMain.CurTextStyleNo), 1, False);
  NoteRef := TRVNoteReferenceItemInfo.CreateEx(FootNote.Document, RVGetNoteTextStyleNo(rvs,0));
  FootNote.Document.AddItem('', NoteRef);
  FootNote.Document.AddNL(' ', 0, -1);
  if rveMain.InsertItem('', FootNote) then
    rveNote.SetFocus;
end;
{------------------------------------------------------------------------------}
{ Menu Notes | Insert Footnote/Endnote Number.
  This command is enabled only if ActiveEditor = rveNote.
  Inserts note reference (TRVNoteReferenceItemInfo, displays endnote number) in
  rveNote.
  This command is not really necessary, but may be useful if the user acidentally
  deleted the initial reference }
procedure TForm1.mitInsertNoteReferenceClick(Sender: TObject);
var NoteRef: TRVNoteReferenceItemInfo;
begin
  NoteRef := TRVNoteReferenceItemInfo.CreateEx(rveNote.RVData,
    RVGetNoteTextStyleNo(rvs,rveNote.CurTextStyleNo));
  rveNote.InsertItem('', NoteRef);
end;
{------------------------------------------------------------------------------}
{ rveMain.OnCaretMove. Updates rveNote }
procedure TForm1.rveMainCaretMove(Sender: TObject);
begin
  if rveMain.GetCurrentItem is TCustomRVNoteItemInfo then
    EditNote(rveMain.GetCurrentItem as TCustomRVNoteItemInfo)
  else begin
    UpdateNote;
    DisableNote;
  end;
end;
{------------------------------------------------------------------------------}
{ When moving input focus from rveNote, we update note document (if it was edited) }
procedure TForm1.rveNoteExit(Sender: TObject);
begin
  UpdateNote;
end;
{------------------------------------------------------------------------------}

end.
