/*******************************************************}
{                                                       }
{       RichView                                        }
{       Editor Demo.                                    }
{       RichView components.                            }
{                                                       }
{       Copyright (c) Sergey Tkachenko                  }
{       svt@trichview.com                               }
{       http://www.trichview.com                        }
{                                                       }
{*******************************************************/

/*
  This demo uses a predefined set of styles.
  This demo shows how to implement:
  - "Edit" menu (Clipboard and Undo);
  - "Search" command;
  - checkpoints;
  - print preview;
  - inserting document or image;
  - inserting some controls;
  - working with TOleContainer;
  - working with table;
  - changing background properties and other options.
  It does not implement:
  - commands like "make bold" or "apply font";
  - standard "File" commands (Open, Save, SaveAs.
  (see Editor 2 demo for these features)
*/

//---------------------------------------------------------------------------
#include <vcl.h>
#include <Clipbrd.hpp>
#include <Jpeg.hpp>
#include <GifImg.hpp>
#include <PngImage.hpp>
#pragma hdrstop

#include "CtrlImg.hpp"
#include "RVTable.hpp"
#include "RVMisc.hpp"

#include "Unit1.h"
#include "PreviewFrm.h"
#include "RVUndoStr.h"
#include "CPFrm.h"
#include "PropFrm.h"
#include "ListFrm.h"
#include "OptionsFrm.h"
//---------------------------------------------------------------------------
#pragma link "RVEdit"
#pragma link "RichView"
#pragma link "RVScroll"
#pragma link "PtblRV"
#pragma link "RVStyle"
#pragma link "CtrlImg"
#pragma link "RVTable"
#pragma link "RVMisc"
#pragma link "RVUni"
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
}
//---------------------------------------------------------------------------
/* This demo understands both tag modes:
  1. rvoTagsArePChars is in Options (tags are strings)
  2. rvoTagsArePChars is not in Options (tags are integers).
  So this demo uses two simple universal functions below for convering
  tag to String and String to tag.
*/
UnicodeString GetTagStr(int Tag)
{
  if (Form1->RichViewEdit1->Options.Contains(rvoTagsArePChars))
	if (!Tag)
	  return "";
	else
	  return (wchar_t*)Tag;
  else
	return IntToStr(Tag);
}
int MakeTag(UnicodeString TagStr)
{
   if (TagStr!="" &&
	   Form1->RichViewEdit1->Options.Contains(rvoTagsArePChars))
   {
	 wchar_t* r = StrNew(TagStr.w_str());
	 return (int)r;
   }
   else
     return StrToIntDef(TagStr,0);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
   Randomize;

   HTMLSaveOptions << rvsoImageSizes << rvsoUseCheckpointsNames;
   HTMLTitle = "Demo File";

  // We need to register classes in order to load them from rvf files
  TComponentClass Classes[3] = { __classid(TButton), __classid(TEdit), __classid(TOleContainer) };
  RegisterClasses(Classes,2);

  RVStyle1->TextStyles->Items[11]->FontName = GetUnicodeFontName();

   // Items can have associated "tags" - integers or strings.
   // Comment next line to use integer tags
   RichViewEdit1->Options << rvoTagsArePChars;

   RichViewEdit1->LoadRVF(ExtractFilePath(Application->ExeName)+"..\\Readme.rvf");
   FillStyleCombo(RVStyle1->ParaStyles, cmbPara);
   FillStyleCombo(RVStyle1->TextStyles, cmbText);
   RichViewEdit1->Format();
   cmbPara->ItemIndex = RichViewEdit1->CurParaStyleNo;
   cmbText->ItemIndex = RichViewEdit1->CurTextStyleNo;
   UpdateUndoMenu();
}
//---------------------------------------------------------------------------
// Returning available Unicode-enabled font
UnicodeString TForm1::GetUnicodeFontName()
{
  if (Screen->Fonts->IndexOf("Arial Unicode MS")>=0)
    return "Arial Unicode MS";
  if (Screen->Fonts->IndexOf("Lucida Sans Unicode")>=0)
    return "Lucida Sans Unicode";
  return "Arial";
}
//---------------------------------------------------------------------------
// Filling combobox with standard styles 
void TForm1::FillStyleCombo(TCustomRVInfos* Styles, TComboBox* cmb)
{
  /* The simplest way to fill the combo box with style names is:
    cmb->Items->Assign(Styles);
    But this code will fill the combo box with all styles -
    both standard styles (i.e. real styles) and non-standard styles will be
    added in it.
    So we'll fill in the combo box manually.
    For simplification, we'll add only the first standard styles */
  cmb->Items->BeginUpdate();
  cmb->Items->Clear();
  for (int i = 0; i< Styles->Count; i++)
  {
    if (!((TCustomRVInfo*)(Styles->Items[i]))->Standard)
      break;
    cmb->Items->Add(((TCustomRVInfo*)(Styles->Items[i]))->StyleName);
  }
  cmb->Items->EndUpdate();
}
//---------------------------------------------------------------------------
void TForm1::UpdateUndoMenu()
{
  TRVUndoType UndoType = RichViewEdit1->UndoAction();
  mitUndo->Enabled = UndoType!=rvutNone;
  if (UndoType==rvutCustom)
    mitUndo->Caption = "Undo "+RichViewEdit1->UndoName();
  else
    mitUndo->Caption = "Undo "+RVUndoTypeNamesEn[UndoType];

  UndoType = RichViewEdit1->RedoAction();
  mitRedo->Enabled = UndoType!=rvutNone;
  if (UndoType==rvutCustom)
    mitRedo->Caption = "Redo "+RichViewEdit1->RedoName();
  else
    mitRedo->Caption = "Redo "+RVUndoTypeNamesEn[UndoType];
}
//---------------------------------------------------------------------------
void TForm1::DisplayUnicodeWarning()
{
  bool wasclear = RichViewEdit1->ItemCount==0;
  // This method is called before loading Unicode
  // (when inserting Unicode, editor automatically switches to Unicode style,
  // according to RVStyle1->DefUnicodeStyle, if necessary)
  if (!RVStyle1->TextStyles->Items[RichViewEdit1->CurTextStyleNo]->Unicode)
	Application->MessageBox(L"Loading/Inserting Unicode data using non-Unicode text style.\n"
	  L"Text will be converted.\n"
	  L"Choose 'Unicode' style in combo to use Unicode text style",
	  L"Warning", MB_OK | MB_ICONEXCLAMATION);
  if (wasclear)
    RichViewEdit1->Clear();
}
//======================================================================
// Font and paragraph combos
//======================================================================
void __fastcall TForm1::RichViewEdit1CurParaStyleChanged(TObject *Sender)
{
  if (RichViewEdit1->CurParaStyleNo < cmbPara->Items->Count)
    cmbPara->ItemIndex = RichViewEdit1->CurParaStyleNo;
  else
    cmbPara->ItemIndex = -1;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::RichViewEdit1CurTextStyleChanged(TObject *Sender)
{
  if (RichViewEdit1->CurTextStyleNo < cmbText->Items->Count)
    cmbText->ItemIndex = RichViewEdit1->CurTextStyleNo;
  else
    cmbText->ItemIndex = -1;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::cmbParaClick(TObject *Sender)
{
   RichViewEdit1->ApplyParaStyle(cmbPara->ItemIndex);
   RichViewEdit1->SetFocus();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::cmbTextClick(TObject *Sender)
{
   RichViewEdit1->ApplyTextStyle(cmbText->ItemIndex);
   RichViewEdit1->SetFocus();
}
//======================================================================
// Main menu: "File"
//======================================================================
// File|Load...
void __fastcall TForm1::mitLoadClick(TObject *Sender)
{
  OpenDialog1->Title = "Loading & Import";
  OpenDialog1->Filter = "RichView Format Files(*.rvf)|*.rvf|"
                        "RTF Files (*.rtf)|*.rtf|"
                        "Text Files - autodetect (*.txt)|*.txt|"
                        "ANSI Text Files (*.txt)|*.txt|"
                        "Unicode Text Files (*.txt)|*.txt";
  if (OpenDialog1->Execute())
  {
    Screen->Cursor = crHourGlass;
    int CurTextStyleNo = RichViewEdit1->CurTextStyleNo;
    int CurParaStyleNo = RichViewEdit1->CurParaStyleNo;
    bool r;
    CloseOleContainer();
    RichViewEdit1->Clear();
    RichViewEdit1->CurTextStyleNo = CurTextStyleNo;
    RichViewEdit1->CurParaStyleNo = CurParaStyleNo;
    RVStyle1->DefUnicodeStyle = -1;
    switch (OpenDialog1->FilterIndex)
    {
      case 1: // RVF
        r = RichViewEdit1->LoadRVF(OpenDialog1->FileName);
        break;
      case 2: // RTF
        r = RichViewEdit1->LoadRTF(OpenDialog1->FileName);
        break;
      case 3: // Text
        if (RV_TestFileUnicode(OpenDialog1->FileName)==rvutYes)
        {
          DisplayUnicodeWarning();
          r = RichViewEdit1->LoadTextW(OpenDialog1->FileName,CurTextStyleNo,CurParaStyleNo,false);
        }
        else
          r = RichViewEdit1->LoadText(OpenDialog1->FileName,CurTextStyleNo,CurParaStyleNo,false);
        break;
      case 4: // ANSI text
        r = RichViewEdit1->LoadText(OpenDialog1->FileName,CurTextStyleNo,CurParaStyleNo,false);
        break;
      case 5: // Unicode text
        DisplayUnicodeWarning();
        r = RichViewEdit1->LoadTextW(OpenDialog1->FileName,CurTextStyleNo,CurParaStyleNo,false);
        break;
      default:
        r = False;
    }
    Screen->Cursor = crDefault;
    if (!r)
    {
      UnicodeString ErrorMessage = "Error during loading";
      if (OpenDialog1->FilterIndex==1)
        ErrorMessage += GetRVFErrors();
	  Application->MessageBox(ErrorMessage.w_str(), L"Error", 0);
    }
    FillStyleCombo(RVStyle1->ParaStyles, cmbPara);
    FillStyleCombo(RVStyle1->TextStyles, cmbText);
    RichViewEdit1->Format();
    cmbPara->ItemIndex = RichViewEdit1->CurParaStyleNo;
    cmbText->ItemIndex = RichViewEdit1->CurTextStyleNo;
    UpdateUndoMenu();
  }
}
//---------------------------------------------------------------------------
// Event: picture needed while reading from RVF
void __fastcall TForm1::RichViewEdit1RVFPictureNeeded(TCustomRichView *Sender,
	UnicodeString Name, int Tag, TGraphic *&gr)
{
  gr = new Graphics::TBitmap;
  gr->LoadFromFile(ExtractFilePath(Application->ExeName)+"..\\default.bmp");
}
//---------------------------------------------------------------------------
// Event: control needed while reading from RVF
void __fastcall TForm1::RichViewEdit1RVFControlNeeded(TCustomRichView *Sender,
	UnicodeString Name, int Tag, TControl *&ctrl)
{
  ctrl = new TButton ((TComponent*)NULL);
  ((TButton*)(ctrl))->Caption = "from file";
}
//---------------------------------------------------------------------------
// Event: imagelist needed while reading from RVF
void __fastcall TForm1::RichViewEdit1RVFImageListNeeded(TCustomRichView *Sender,
    int ImageListTag, TCustomImageList *&il)
{
  il = this->il;
}
//---------------------------------------------------------------------------
UnicodeString TForm1::GetRVFErrors()
{
  UnicodeString Result = "";
  if (RichViewEdit1->RVFWarnings.Contains(rvfwUnknownPicFmt))
	Result += L"unknown picture format;";
  if (RichViewEdit1->RVFWarnings.Contains(rvfwUnknownCtrls))
	Result += L"unknown control class;";
  if (RichViewEdit1->RVFWarnings.Contains(rvfwConvUnknownStyles))
	Result += L"text, paragraph or list style is not present;";
  if (RichViewEdit1->RVFWarnings.Contains(rvfwConvLargeImageIdx))
	Result += L"invalid image-list index;";
  if (Result.Length()>0)
	Result = L"\n("+Result+L")";
  return Result;
}
//---------------------------------------------------------------------------
// File|Save...
void __fastcall TForm1::mitSaveClick(TObject *Sender)
{
  SaveDialog1->Title = "Save & Export";
  SaveDialog1->Filter = "RichView Format files(*.rvf)|*.rvf|"
                        "RTF Files (*.rtf)|*.rtf|"
                        "Text (*.txt)|*.txt|"
                        "Unicode Text (*.txt)|*.txt|"
                        "HTML - with CSS (*.htm;*.html)|*.htm;*.html"
                        "HTML - Simplified (*.htm;*.html)|*.htm;*.html|";

  SaveDialog1->DefaultExt = "rvf";
  if (SaveDialog1->Execute())
  {
    Screen->Cursor = crHourGlass;
    bool r;
    switch (SaveDialog1->FilterIndex)
    {
      case 1: // RVF
        r = RichViewEdit1->SaveRVF(SaveDialog1->FileName, false);
        break;
      case 2: // RTF
        r = RichViewEdit1->SaveRTF(SaveDialog1->FileName, false);
        break;
      case 3: // ANSI Text (byte per character)
        r = RichViewEdit1->SaveText(SaveDialog1->FileName, 80);
        break;
      case 4: // Unicode Text (2 bytes per character)
        r = RichViewEdit1->SaveTextW(SaveDialog1->FileName, 80);
        break;
      case 5: // HTML with CSS
        r = RichViewEdit1->SaveHTMLEx(SaveDialog1->FileName, HTMLTitle,"img",
          "","","", HTMLSaveOptions);
        break;
      case 6: // HTML
        r = RichViewEdit1->SaveHTML(SaveDialog1->FileName, HTMLTitle,"img",
          HTMLSaveOptions);
        break;
      default:
        r = false;
    }
    Screen->Cursor = crDefault;
    if (!r)
	  Application->MessageBox(L"Error during saving", L"Error", 0);
  }
}
//---------------------------------------------------------------------------
// File | Options
void __fastcall TForm1::OptionsforSavingLoading1Click(TObject *Sender)
{
  TRVFOptions RVFOptions;
  frmOptions->SetOptions(RichViewEdit1->RVFOptions, HTMLSaveOptions, HTMLTitle);
  if (frmOptions->ShowModal()==mrOk)
  {
    frmOptions->GetOptions(RVFOptions, HTMLSaveOptions, HTMLTitle);
    RichViewEdit1->RVFOptions = RVFOptions;
  }
}
//---------------------------------------------------------------------------
// Note: not all browsers support <INPUT> tags outside <FORM></FORM> tags
void __fastcall TForm1::RichViewEdit1SaveComponentToFile(
	TCustomRichView *Sender, UnicodeString Path, TPersistent *SaveMe,
	TRVSaveFormat SaveFormat, UnicodeString &OutStr)
{
  switch (SaveFormat)
  {
   case rvsfText:
	 OutStr = L"("+SaveMe->ClassName()+")";
	 break;
   case rvsfHTML:
	 if (SaveMe->InheritsFrom(__classid(TButton)))
	 {
	   OutStr = "<input type=\"button\" value=\""+((TButton*)SaveMe)->Caption+"\" "
				"onClick=\"alert('Just a demo')\">";
	   return;
	 }
	 if (SaveMe->InheritsFrom(__classid(TEdit)))
	 {
	   OutStr = "<input type=\"text\" value=\""+((TEdit*)SaveMe)->Text+"\">";
	   return;
	 }
	 break;
   case rvsfRTF:
	 OutStr = L"{\\plain\\b ("+SaveMe->ClassName()+")}";
	 break;
  }
}
//---------------------------------------------------------------------------
// Event: saving URLs in HTML and RTF
void __fastcall TForm1::RichViewEdit1WriteHyperlink(TCustomRichView *Sender,
	int id, TCustomRVData *RVData, int ItemNo, TRVSaveFormat SaveFormat,
	UnicodeString &Target, UnicodeString &Extras)
{
  Target = GetTagStr(RVData->GetItemTag(ItemNo));
}
//---------------------------------------------------------------------------
// File|Clear
void __fastcall TForm1::mitClearClick(TObject *Sender)
{
   CloseOleContainer();
   RichViewEdit1->Clear();
   RichViewEdit1->Format();
   cmbPara->ItemIndex = RichViewEdit1->CurParaStyleNo;
   cmbText->ItemIndex = RichViewEdit1->CurTextStyleNo;
   UpdateUndoMenu();
}
//---------------------------------------------------------------------------
// File|Print Preview
void __fastcall TForm1::mitPreviewClick(TObject *Sender)
{
  RVPrint1->AssignSource(RichViewEdit1);
  RVPrint1->FormatPages(TRVDisplayOptions());
  if (RVPrint1->PagesCount>0)
  {
    frmPreview->rvpp->RVPrint = RVPrint1;
    frmPreview->Button1Click(NULL); //  Show First Page
    frmPreview->ShowModal();
  }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::mitPrintClick(TObject *Sender)
{
#if __BORLANDC__ > 0x520
  bool PrintIt = psd->Execute();
#else
  bool PrintIt = true;
#endif
  if (PrintIt)
  {
    RVPrint1->AssignSource(RichViewEdit1);
    RVPrint1->FormatPages(TRVDisplayOptions());
    if (RVPrint1->PagesCount>0)
      RVPrint1->Print("RichView Edit Demo",1,false);
  }
}
//---------------------------------------------------------------------------
// File|Exit
void __fastcall TForm1::mitExitClick(TObject *Sender)
{
  Close();
}
//======================================================================
// Main menu: "Insert"
//======================================================================
// Insert|File...
void __fastcall TForm1::mitInsertFileClick(TObject *Sender)
{
  OpenDialog1->Title = "Inserting File";
  OpenDialog1->Filter = "RichView Format Files(*.rvf)|*.rvf|"
                        "RTF Files(*.rtf)|*.rtf|"
                        "Text Files - autodetect (*.txt)|*.txt|"
                        "ANSI Text Files (*.txt)|*.txt|"
                        "Unicode Text Files (*.txt)|*.txt|"
                        "OEM Text Files (*.txt)|*.txt";
  if (OpenDialog1->Execute())
  {
    Screen->Cursor = crHourGlass;
    bool r;
    switch (OpenDialog1->FilterIndex)
    {
      case 1: // RVF
        r = RichViewEdit1->InsertRVFFromFileEd(OpenDialog1->FileName);
        break;
      case 2: // RTF
        r = RichViewEdit1->InsertRTFFromFileEd(OpenDialog1->FileName);
        break;
      case 3: // Text
        if (RV_TestFileUnicode(OpenDialog1->FileName)==rvutYes)
          r = RichViewEdit1->InsertTextFromFileW(OpenDialog1->FileName);
        else
          r = RichViewEdit1->InsertTextFromFile(OpenDialog1->FileName);
        break;
      case 4: // ANSI Text
        r = RichViewEdit1->InsertTextFromFile(OpenDialog1->FileName);
        break;
      case 5: // Unicode Text
        r = RichViewEdit1->InsertTextFromFileW(OpenDialog1->FileName);
        break;
      case 6: // OEM Text
        r = RichViewEdit1->InsertOEMTextFromFile(OpenDialog1->FileName);
        break;
	  default:
		r = false;
	}
	Screen->Cursor = crDefault;
	if (!r)
	  Application->MessageBox(L"Error reading file", L"Error",
		MB_OK | MB_ICONSTOP);
  }
}
//---------------------------------------------------------------------------
// Insert|Picture...
void __fastcall TForm1::mitPictureClick(TObject *Sender)
{
  OpenDialog1->Title = "Inserting Image";
  OpenDialog1->Filter = "Graphics|*.bmp;*.wmf;*.emf;*.ico;*.jpg;*.gif;*.png|All Files|*.*";
  if (OpenDialog1->Execute())
  {
	TGraphic* gr = NULL;
	UnicodeString ext = UpperCase(ExtractFileExt(OpenDialog1->FileName));
	if (ext==L".PNG")
	  gr = new TPngImage;
	if (ext==L".GIF")
      gr = new TGIFImage;
	if (ext==L".JPG" || ext==L".JPEG")
	  gr = new TJPEGImage;
	else if (ext==L".BMP" || ext==L".DIB")
	  gr = new Graphics::TBitmap;
	else if (ext==L".ICO")
	  gr = new TIcon;
	else if (ext==L".WMF" || ext==L".EMF")
	  gr = new TMetafile;
    else
	  Application->MessageBox((L"Format '"+ext+L"' is not supported").w_str(),
		L"Error", MB_OK | MB_ICONSTOP);
    if (gr)
    {
      gr->LoadFromFile(OpenDialog1->FileName);
      RichViewEdit1->InsertPicture("",gr,rvvaBaseline);
    }
  }
}
//---------------------------------------------------------------------------
// Event: clicking inserted controls
void __fastcall TForm1::OnControlClick(TObject *Sender)
{
  RichViewEdit1->SelectControl((TControl*)Sender);
}
//---------------------------------------------------------------------------
// Insert|Component|Button
void __fastcall TForm1::mitButtonCompClick(TObject *Sender)
{
const UnicodeString Captions[10] =
       {
       "Help","Exit","Cancel","OK","Close","Run","Options...","Minimize",
       "Hide","Show"
       };
  TButton* btn = new TButton((TComponent*)NULL);
  btn->Caption = Captions[random(10)];
  btn->OnClick = OnControlClick;
  RichViewEdit1->InsertControl("",btn,rvvaBaseline);
  if (RichViewEdit1->CurItemStyle==rvsComponent)
    RichViewEdit1->SetCurrentItemExtraIntProperty(rvepResizable, 1, True);
}
//---------------------------------------------------------------------------
// Insert|Component|Edit Box
void __fastcall TForm1::mitEditBoxCompClick(TObject *Sender)
{
const UnicodeString Captions[10] =
       {
       "0","Hello","1","$0","2x2=4","enter text here","x<y","to be or not to be?",
       "(empty)","(full)"
       };
  TEdit* edt = new TEdit((TComponent*)NULL);
  edt->Text = Captions[random(10)];
  edt->OnClick = OnControlClick;
  RichViewEdit1->InsertControl("",edt,rvvaBaseline);
  if (RichViewEdit1->CurItemStyle==rvsComponent)
    RichViewEdit1->SetCurrentItemExtraIntProperty(rvepResizable, 1, True);
}
//---------------------------------------------------------------------------
// Insert|Bullet|"XXX"
void __fastcall TForm1::mitInsertBulletClick(TObject *Sender)
{
  RichViewEdit1->InsertBullet(((TMenuItem*)Sender)->Tag, il);    
}
//---------------------------------------------------------------------------
// Insert|Hot Spot|"XXX"
void __fastcall TForm1::mitInsertHotspotClick(TObject *Sender)
{
  RichViewEdit1->InsertHotspot(((TMenuItem*)Sender)->Tag, ((TMenuItem*)Sender)->Tag+2, il);
}
//---------------------------------------------------------------------------
// Insert|Break
void __fastcall TForm1::mitBreakClick(TObject *Sender)
{
   RichViewEdit1->InsertBreak(1, rvbsLine, Graphics::clNone);
}
//======================================================================
// Main menu : "Edit"
//======================================================================
// Edit
void __fastcall TForm1::mpdEditClick(TObject *Sender)
{
  mitPasteAsRTF->Enabled      = RichViewEdit1->CanPasteRTF();
  mitPasteAsText->Enabled     = Clipboard()->HasFormat(CF_TEXT);
  mitPasteAsUnicodeText->Enabled = Clipboard()->HasFormat(CF_UNICODETEXT);
  mitPasteAsMetafile->Enabled = Clipboard()->HasFormat(CF_METAFILEPICT);
  mitPasteAsBitmap->Enabled   = Clipboard()->HasFormat(CF_BITMAP);
  mitPasteAsRVF->Enabled      = RichViewEdit1->CanPasteRVF();
  mitPaste->Enabled           = RichViewEdit1->CanPaste();

  mitInsertPageBreak->Enabled = !RichViewEdit1->InplaceEditor;
  mitRemovePageBreak->Enabled =
    !RichViewEdit1->InplaceEditor &&
    RichViewEdit1->PageBreaksBeforeItems[RichViewEdit1->CurItemNo];

  // You can edit properties only for item at the caret position.
  // We disable this item because otherwise user can think what he will
  // edit properties of all selected items.
  // More smart programs can determine if there is only one item is selected
  // and do not disable this item in this case
  mitEditProps->Enabled       = ! RichViewEdit1->SelectionExists();
}
//---------------------------------------------------------------------------
// Edit|Undo
void __fastcall TForm1::mitUndoClick(TObject *Sender)
{
  RichViewEdit1->Undo();
}
//---------------------------------------------------------------------------
// Edit|Redo
void __fastcall TForm1::mitRedoClick(TObject *Sender)
{
  RichViewEdit1->Redo();
}
//---------------------------------------------------------------------------
// Edit|Cut
void __fastcall TForm1::mitCutClick(TObject *Sender)
{
  RichViewEdit1->CutDef();
}
//---------------------------------------------------------------------------
// Edit|Copy
void __fastcall TForm1::mitCopyClick(TObject *Sender)
{
  RichViewEdit1->CopyDef();
}
//---------------------------------------------------------------------------
// Edit|Paste
void __fastcall TForm1::mitPasteClick(TObject *Sender)
{
  RichViewEdit1->Paste();
}
//---------------------------------------------------------------------------
// Edit|Paste As|RTF
void __fastcall TForm1::mitPasteAsRTFClick(TObject *Sender)
{
  RichViewEdit1->PasteRTF();
}
//---------------------------------------------------------------------------
// Edit|Paste As|Text
void __fastcall TForm1::mitPasteAsTextClick(TObject *Sender)
{
  RichViewEdit1->PasteText();
}
//---------------------------------------------------------------------------
// Edit|Paste As|Unicode Text
void __fastcall TForm1::mitPasteAsUnicodeTextClick(TObject *Sender)
{
  RichViewEdit1->PasteTextW();
}
//---------------------------------------------------------------------------
// Edit|Paste As|Metafile
void __fastcall TForm1::mitPasteAsMetafileClick(TObject *Sender)
{
  RichViewEdit1->PasteMetafile(false);
}
//---------------------------------------------------------------------------
// Edit|Paste As|Bitmap
void __fastcall TForm1::mitPasteAsBitmapClick(TObject *Sender)
{
  RichViewEdit1->PasteBitmap(false);
}
//---------------------------------------------------------------------------
// Edit|Paste As|RichView Format
void __fastcall TForm1::mitPasteAsRVFClick(TObject *Sender)
{
  RichViewEdit1->PasteRVF();
}
//---------------------------------------------------------------------------
// Edit|Paste As|OLE
void __fastcall TForm1::mitPasteAsOLEClick(TObject *Sender)
{
  TOleContainer* oc = new TOleContainer((TComponent*)NULL);
  if (oc->CanPaste)
  {
    oc->Visible = false;
    oc->BorderStyle = bsNone;
    oc->Parent = RichViewEdit1;
    oc->SizeMode = smAutoSize;
    oc->Paste();
    RichViewEdit1->InsertControl("", oc,rvvaBaseline);
    oc->OnResize = OnOleResize;
    oc->OnActivate = OnOleActivate;
    oc->OnDeactivate = OnOleDeactivate;
    oc->Visible = true;
  }
  else
    delete oc;
}
//---------------------------------------------------------------------------
void TForm1::CloseOleContainer()
{
  if (ActiveOleContainer)
  {
    ActiveOleContainer->Close();
    ActiveOleContainer = NULL;
  }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::OnOleResize(TObject *Sender)
{
  RichViewEdit1->AdjustControlPlacement2((TControl*)Sender);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::OnOleActivate(TObject *Sender)
{
  if (ActiveOleContainer!=Sender)
    CloseOleContainer();
  ActiveOleContainer = (TOleContainer*)Sender;
  RichViewEdit1->AdjustControlPlacement2((TControl*)Sender);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::OnOleDeactivate(TObject *Sender)
{
  RichViewEdit1->AdjustControlPlacement2((TControl*)Sender);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::RichViewEdit1Click(TObject *Sender)
{
  CloseOleContainer();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
  CloseOleContainer();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::RichViewEdit1ControlAction(TCustomRichView *Sender,
	TRVControlAction ControlAction, int ItemNo, TControl *&ctrl)
{
  if (ControlAction==rvcaAfterRVFLoad)
  {
    if (ctrl->InheritsFrom(__classid(TOleContainer)))
    {
      ((TOleContainer*)ctrl)->OnResize = OnOleResize;
      ((TOleContainer*)ctrl)->OnActivate = OnOleActivate;
      ((TOleContainer*)ctrl)->OnDeactivate = OnOleDeactivate;
    }
    else if (ctrl->InheritsFrom(__classid(TButton)))
      ((TButton*)ctrl)->OnClick = OnControlClick;
    else if (ctrl->InheritsFrom(__classid(TEdit)))
      ((TEdit*)ctrl)->OnClick = OnControlClick;
  }
  if (ctrl!=ActiveOleContainer)
    return;
  if (ControlAction==rvcaMoveToUndoList ||
      ControlAction==rvcaDestroy ||
      ControlAction==rvcaBeforeRVFSave)
    CloseOleContainer();
}
//---------------------------------------------------------------------------
// Edit|Delete
void __fastcall TForm1::mitDeleteClick(TObject *Sender)
{
  // Shortcut to this item is Ctrl+Del
  // If you make it Del, you will be unable to use del key in editor
  RichViewEdit1->DeleteSelection();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::mitSelectAllClick(TObject *Sender)
{
  // warning: SelectAll moves caret to the end of the text
  RichViewEdit1->SelectAll();
  RichViewEdit1->SetFocus();
  RichViewEdit1->Invalidate();
}
//---------------------------------------------------------------------------
// Another clipboard-related action
void __fastcall TForm1::RichViewEdit1Select(TObject *Sender)
{
  mitCopy->Enabled   = RichViewEdit1->SelectionExists();
  mitCut->Enabled    = mitCopy->Enabled;
  mitDelete->Enabled = mitCopy->Enabled;
}
//---------------------------------------------------------------------------
// Edit| Insert Page Break
void __fastcall TForm1::mitInsertPageBreakClick(TObject *Sender)
{
  RichViewEdit1->InsertPageBreak();    
}
//---------------------------------------------------------------------------
// Edit| Remove Page Break
void __fastcall TForm1::mitRemovePageBreakClick(TObject *Sender)
{
  RichViewEdit1->RemoveCurrentPageBreak();    
}
//---------------------------------------------------------------------------
// Edit|Checkpoint...
void __fastcall TForm1::mitEditCheckpointClick(TObject *Sender)
{
  int CpNo, Tag;
  UnicodeString Name;
  bool RaiseEvent;
  TCheckpointData CheckpointData = RichViewEdit1->GetCurrentCheckpoint();
  if (CheckpointData)
  {
    RichViewEdit1->GetCheckpointInfo(CheckpointData,Tag,Name,RaiseEvent);
    CpNo = RichViewEdit1->GetCheckpointNo(CheckpointData);
    frmCP->lblStatus->Caption = "Editing checkpoint #"+IntToStr(CpNo);
    frmCP->txtName->Text = Name;
    frmCP->txtTag->Text = GetTagStr(Tag);
    frmCP->btnOk->Caption = "OK";
    frmCP->btnDelete->Enabled = true;
  }
  else
  {
    frmCP->lblStatus->Caption = "Checkpoint does not exist";
    frmCP->txtName->Text = "";
    frmCP->txtTag->Text = GetTagStr(0);
    frmCP->btnOk->Caption = "Add";
    frmCP->btnDelete->Enabled = false;
  }
  switch (frmCP->ShowModal())
  {
    case mrOk: // add new checkpoint or modify existed one
      RichViewEdit1->SetCurrentCheckpointInfo(MakeTag(frmCP->txtTag->Text),
                                             frmCP->txtName->Text,false);
      break;
    case mrYes: // delete checkpoint
      RichViewEdit1->RemoveCurrentCheckpoint();
      break;
  }
}
//---------------------------------------------------------------------------
// Edit|Search... 
void __fastcall TForm1::mitSearchClick(TObject *Sender)
{
  FindDialog1->Execute();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FindDialog1Find(TObject *Sender)
{
  TRVESearchOptions Options = GetRVESearchOptions(FindDialog1->Options);
  if (!RichViewEdit1->SearchText(FindDialog1->FindText,
                           Options))
   Application->MessageBox(L"Can't find", L"Search complete",
     MB_OK | MB_ICONEXCLAMATION);
}
//---------------------------------------------------------------------------
// Edit|Select Current Word
void __fastcall TForm1::mitSelectCurrentWordClick(TObject *Sender)
{
  RichViewEdit1->SelectCurrentWord();
  // now you can do something with the current word:
  // translate or spell check, for example...
}
//---------------------------------------------------------------------------
// Edit|Current Item Properties...
void __fastcall TForm1::mitEditPropsClick(TObject *Sender)
{
  TRVAnsiString s;
  int Tag, ImageIndex;
  TCustomImageList * ImageList;
  TRVVAlign VAlign;
  TControl* ctrl;
  TGraphic* gr;
  TColor BreakColor;
  TRVBreakStyle BreakStyle;
  TRVStyleLength BreakWidth;

  frmProp->PageControl1->Visible   = true;
  frmProp->tsBullet->TabVisible    = false;
  frmProp->tsHotspot->TabVisible   = false;
  frmProp->tsPicture->TabVisible   = false;
  frmProp->tsText->TabVisible      = false;
  frmProp->tsComponent->TabVisible = false;
  frmProp->tsBreak->TabVisible     = false;
  frmProp->txtName->Enabled        = true;
  switch (RichViewEdit1->CurItemStyle)
  {
	case rvsBullet:
	{
	  RichViewEdit1->GetCurrentBulletInfo(s, ImageIndex, ImageList, Tag);
      frmProp->tsBullet->TabVisible = true;
      frmProp->rgBullet->ItemIndex  = ImageIndex;
      frmProp->txtName->Text        = s;
      frmProp->txtTag->Text         = GetTagStr(Tag);
      break;
    }
    case rvsHotspot:
    {
      // you can use GetCurrentBulletInfo or GetCurrentHotspotInfo
      // to receive info about hotspot in caret position->
      // in this demo we need not HotImageIndex, because here
      // HotImageIndex = ImageIndex+2
      // and so we can use GetCurrentBulletInfo
      RichViewEdit1->GetCurrentBulletInfo(s, ImageIndex, ImageList, Tag);
      frmProp->tsHotspot->TabVisible = true;
      frmProp->rgHotspot->ItemIndex  = ImageIndex-3;
      frmProp->txtName->Text         = s;
      frmProp->txtTag->Text          = GetTagStr(Tag);
      break;
    }
    case rvsPicture:
    case rvsHotPicture:
    {
      RichViewEdit1->GetCurrentPictureInfo(s, gr, VAlign, Tag);
      frmProp->tsPicture->TabVisible    = true;
      frmProp->Image1->Picture->Graphic = gr;
      frmProp->txtName->Text            = s;
      frmProp->txtTag->Text             = GetTagStr(Tag);
      frmProp->rgPicVAlign->ItemIndex   = VAlign;
      break;
    }
    case rvsComponent:
    {
      RichViewEdit1->GetCurrentControlInfo(s, ctrl, VAlign, Tag);
      frmProp->tsComponent->TabVisible = true;
      frmProp->txtWidth->Text          = IntToStr(ctrl->Width);
      frmProp->txtHeight->Text         = IntToStr(ctrl->Height);
      frmProp->txtName->Text           = s;
      frmProp->lblComponent->Caption   = ctrl->ClassName();
      frmProp->txtTag->Text            = GetTagStr(Tag);
      frmProp->rgCtrlVAlign->ItemIndex = Integer(VAlign);
      break;
    }
    case rvsBreak:
    {
      RichViewEdit1->GetCurrentBreakInfo(BreakWidth, BreakStyle, BreakColor, Tag);
      frmProp->tsBreak->TabVisible = true;
      frmProp->txtBreakWidth->Text = IntToStr(BreakWidth);
      switch (BreakColor)
      {
      case Graphics::clNone:
        frmProp->rgBreakColor->ItemIndex = 0;
        break;
      case clRed:
        frmProp->rgBreakColor->ItemIndex = 1;
        break;
      case clGreen:
        frmProp->rgBreakColor->ItemIndex = 2;
        break;
      case clBlue:
        frmProp->rgBreakColor->ItemIndex = 3;
        break;
      }
      frmProp->rgBreakStyle->ItemIndex = BreakStyle;
	  frmProp->txtName->Text = L"(not available for breaks)";
	  frmProp->txtName->Enabled = false;
	  frmProp->txtTag->Text = GetTagStr(Tag);
	  break;
	}
	case rvsTable:
	{
	  frmProp->txtName->Text = RichViewEdit1->GetCurrentItemTextW();
	  frmProp->txtTag->Text = GetTagStr(RichViewEdit1->GetCurrentTag());
	  frmProp->PageControl1->Visible = false;
	  break;
	}
	default: // text
	{
	  frmProp->tsText->TabVisible = true;
	  frmProp->txtName->Text = L"(not available for text)";
	  frmProp->txtName->Enabled = false;
	  frmProp->lblText->Caption = RichViewEdit1->GetCurrentItemTextW();
	  frmProp->txtTag->Text = GetTagStr(RichViewEdit1->GetCurrentTag());
	}
  }
  if (frmProp->ShowModal()==mrOk)
  {
	switch (RichViewEdit1->CurItemStyle)
	{
	  case rvsBullet:
	  {
		RichViewEdit1->SetCurrentBulletInfo(
		  frmProp->txtName->Text,
		  frmProp->rgBullet->ItemIndex,
		  NULL,
		  MakeTag(frmProp->txtTag->Text));
		break;
	  }
	  case rvsHotspot:
	  {
		RichViewEdit1->SetCurrentHotspotInfo(
		  frmProp->txtName->Text,
		  frmProp->rgHotspot->ItemIndex+3,
		  frmProp->rgHotspot->ItemIndex+3+2,
		  NULL,
		  MakeTag(frmProp->txtTag->Text));
		break;
	  }
	  case rvsPicture:
	  case rvsHotPicture:
	  {
		// first we need to create a copy of image ...
		// RV_CreateGraphics is a global function pointer, defined in RVItem unit,
		// it creates graphic object by its class
		gr = RV_CreateGraphics(frmProp->Image1->Picture->Graphic->ClassType());
		gr->Assign(frmProp->Image1->Picture->Graphic);
		RichViewEdit1->SetCurrentPictureInfo(
		  frmProp->txtName->Text,
          gr,
          TRVVAlign(frmProp->rgPicVAlign->ItemIndex),
          MakeTag(frmProp->txtTag->Text));
        break;
      }
      case rvsComponent:
      {
        // we wish these setting to be undone as one action,
        // so we use BeginUndoGroup, SetUndoGroupMode(true), settings, SetUndoGroupMode(false)
        RichViewEdit1->BeginUndoGroup(rvutModifyItem);
        // you can use BeginUndoCustomGroup instead of BeginUndoGroup
        // example:
        // RichViewEdit1->BeginUndoCustomGroup("modifying control");
        // In this case undo type will be rvutCustom
        // (look at TForm1->UpdateUndoMenu in this file)
        RichViewEdit1->SetUndoGroupMode(true);
        RichViewEdit1->SetCurrentControlInfo(
          frmProp->txtName->Text,
          TRVVAlign(frmProp->rgCtrlVAlign->ItemIndex),
          MakeTag(frmProp->txtTag->Text));
        RichViewEdit1->ResizeCurrentControl(
          StrToIntDef(frmProp->txtWidth->Text, ctrl->Width),
          StrToIntDef(frmProp->txtHeight->Text, ctrl->Height));
        RichViewEdit1->SetUndoGroupMode(false);
        break;
      }
      case rvsBreak:
      {
        switch (frmProp->rgBreakColor->ItemIndex)
        {
          case -1:
          case 0:
            BreakColor = Graphics::clNone;
            break;
          case 1:
            BreakColor = clRed;
            break;
          case 2:
            BreakColor = clGreen;
            break;
          case 3:
            BreakColor = clBlue;
            break;
        }
        BreakStyle = TRVBreakStyle(frmProp->rgBreakStyle->ItemIndex);
        BreakWidth = (unsigned char)StrToIntDef(frmProp->txtBreakWidth->Text,1);
        RichViewEdit1->SetCurrentBreakInfo(BreakWidth,BreakStyle,BreakColor,
                                           MakeTag(frmProp->txtTag->Text));
        break;
      }
      case rvsTable:
      {
        RichViewEdit1->BeginUndoGroup(rvutModifyItem);
        RichViewEdit1->SetUndoGroupMode(true);
        RichViewEdit1->SetCurrentItemTextW(frmProp->txtName->Text);
        RichViewEdit1->SetCurrentTag(MakeTag(frmProp->txtTag->Text));
        RichViewEdit1->SetUndoGroupMode(false);
        break;
      }
      default:
      {
		RichViewEdit1->SetCurrentTag(MakeTag(frmProp->txtTag->Text));
      }
    }
  }
}
//======================================================================
// Main menu : "Misc"
//======================================================================
// Misc | Go to checkpoint ...
void __fastcall TForm1::mitCheckpointListClick(TObject *Sender)
{
  frmList->lst->Items->Clear();
  TCheckpointData CheckpointData = RichViewEdit1->GetFirstCheckpoint();
  while (CheckpointData)
  {
    int X,Y,Tag;
    UnicodeString Name, s;
    bool RaiseEvent;
    RichViewEdit1->GetCheckpointInfo(CheckpointData,Tag,Name,RaiseEvent);
    RichViewEdit1->GetCheckpointXY(CheckpointData,X,Y);
    s = "(X:"+IntToStr(X)+",Y:"+IntToStr(Y)+") Name:'"+Name+"' Tag:'"+GetTagStr(Tag)+"'";
    frmList->lst->Items->Add(s);
    CheckpointData = RichViewEdit1->GetNextCheckpoint(CheckpointData);
  }
  if (frmList->ShowModal()==mrOk)
    RichViewEdit1->ScrollTo(RichViewEdit1->GetCheckpointY(frmList->lst->ItemIndex));
}
//---------------------------------------------------------------------------
// Misc | Background submenu popups
void __fastcall TForm1::mpdBackgroundClick(TObject *Sender)
{
  // Displaying RichViewEdit1->BackgroundStyle as checkmark in submenu...
  mitBackNoBitmap->Checked         = RichViewEdit1->BackgroundStyle==bsNoBitmap;
  mitBackStretched->Checked        = RichViewEdit1->BackgroundStyle==bsStretched;
  mitBackTiledandScrolled->Checked = RichViewEdit1->BackgroundStyle==bsTiledAndScrolled;
  mitBackTiled->Checked            = RichViewEdit1->BackgroundStyle==bsTiled;
  mitBackCentered->Checked         = RichViewEdit1->BackgroundStyle==bsCentered;
  mitBackTopLeft->Checked          = RichViewEdit1->BackgroundStyle==bsTopLeft;
  mitBackTopRight->Checked         = RichViewEdit1->BackgroundStyle==bsTopRight;
  mitBackBottomLeft->Checked       = RichViewEdit1->BackgroundStyle==bsBottomLeft;
  mitBackBottomRight->Checked      = RichViewEdit1->BackgroundStyle==bsBottomRight;
}
//---------------------------------------------------------------------------
// Misc | Background options
void __fastcall TForm1::mitBackClick(TObject *Sender)
{
  RichViewEdit1->BackgroundStyle = (TBackgroundStyle)(((TMenuItem*)Sender)->Tag);
}
//---------------------------------------------------------------------------
// Misc | Read only
void __fastcall TForm1::mitReadOnlyClick(TObject *Sender)
{
  RichViewEdit1->ReadOnly = ! RichViewEdit1->ReadOnly;
  mitReadOnly->Checked = RichViewEdit1->ReadOnly;
}
//======================================================================
// On Popup
void __fastcall TForm1::PopupMenu1Popup(TObject *Sender)
{
  mitEditProp1->Enabled = !RichViewEdit1->SelectionExists();
}
//---------------------------------------------------------------------------
// OnChange event handler.
void __fastcall TForm1::RichViewEdit1Change(TObject *Sender)
{
  UpdateUndoMenu();
}
//---------------------------------------------------------------------------
// You should manually update palette info when user changes color mode
// without restarting Windows
void __fastcall TForm1::WMDisplayChange(TMessage &Message)
{
  RichViewEdit1->UpdatePaletteInfo();
  RVPrint1->UpdatePaletteInfo();
}
//---------------------------------------------------------------------------
// Event: OnJump (when user clicks hypertext item with pressed Ctrl key
void __fastcall TForm1::RichViewEdit1Jump(TObject *Sender, int id)
{
  // NOTE: OnJump is called after the caret is repositioned to clicked item
  // But warning: a clicked event is not necessarily an active item
  // (when clicking on left part of picture or left part of first character in text item,
  // caret moves before item and previous item becomes active!)
  TCustomRVFormattedData* RVData;
  int ItemNo;
  RichViewEdit1->GetJumpPointLocation(id, RVData, ItemNo);
  UnicodeString s =  GetTagStr(RVData->GetItemTag(ItemNo));
  Application->MessageBox(Sysutils::Format(L"Tag of clicked hyperlink is '%s'",
    ARRAYOFCONST((s.w_str()))).w_str(), L"Hypertext Click", MB_OK | MB_ICONINFORMATION);

}
//---------------------------------------------------------------------------
// Event: OnRVMouseMove (when user moves mouse above hypertext item with pressed Ctrl key
void __fastcall TForm1::RichViewEdit1RVMouseMove(TObject *Sender, int id)
{
  TCustomRVFormattedData* RVData;
  int ItemNo;
  if (id==-1)
    StatusBar1->SimpleText = "";
  else
  {
	RichViewEdit1->GetJumpPointLocation(id, RVData, ItemNo);
	UnicodeString s =  GetTagStr(RVData->GetItemTag(ItemNo));
	StatusBar1->SimpleText =
	  Sysutils::Format("Tag of clicked hyperlink is '%s'", ARRAYOFCONST((s.w_str())));
  }
}
//======================================================================
// Main menu : "Lists"
//======================================================================
// Lists | Apply
void __fastcall TForm1::mitApplyListsClick(TObject *Sender)
{
  /* See more demos about list styles in Demos\CBuilder\Assorted\ListStyles\ */
  if (RVStyle1->ListStyles->Count==0 ||
      RVStyle1->ListStyles->Items[0]->Levels->Count==0)
  {
    Application->MessageBox(L"Default list style is not defined", L"", 0);
    return;
  }
  RichViewEdit1->ApplyListStyle(0, 0, 1, false, false);
}
//---------------------------------------------------------------------------
// Lists | Remove
void __fastcall TForm1::mitRemoveListsClick(TObject *Sender)
{
  RichViewEdit1->RemoveLists(false);
}
//======================================================================
// Main menu : "Table"
//======================================================================
// Table | Insert Table Example 1
void __fastcall TForm1::mitInserttable1Click(TObject *Sender)
{
  TRVTableItemInfo* table = new TRVTableItemInfo(4,3, RichViewEdit1->RVData);

  table->BorderStyle      = rvtbRaisedColor;
  table->CellBorderStyle  = rvtbLoweredColor;
  table->BorderLightColor = (TColor)0x00FAF1C9;
  table->BorderColor      = (TColor)0x00A98E10;
  table->CellBorderLightColor = (TColor)0x00FAF1C9;
  table->CellBorderColor  = (TColor)0x00A98E10;
  table->Color            = (TColor)0x00EAC724;
  table->BorderWidth      = 5;
  table->CellBorderWidth  = 2;
  table->CellPadding      = 5;
  table->CellVSpacing     = 1;
  table->CellHSpacing     = 1;
  table->BorderVSpacing   = 1;
  table->BorderHSpacing   = 1;

  for (int r = 0; r<table->Rows->Count; r++)
    for (int c = 0; c<table->Rows->Items[r]->Count; c++)
      table->Cells[r][c]->BestWidth = 100;

  table->MergeCells(0,0,3,1, false);
  table->MergeCells(1,0,1,3, false);
  TRVTableCellData* Cell = table->Cells[0][0];
  Cell->Color = clInfoBk;
  Cell->Clear();
  Cell->AddBulletEx("",0,il,2);
  Cell->AddNLWTag(" Example 1 ",1,-1,0);
  Cell->AddBulletEx("",0,il,-1);
  Cell->AddNLWTag("All cells have 100 pixels width, width of table itself is calculated basing on width of cells.",0,0,0);

  if (RichViewEdit1->InsertItem("", table))
  {
  }
}
//---------------------------------------------------------------------------
// Table | Insert Table Example 2
void __fastcall TForm1::mitInsertTable2Click(TObject *Sender)
{
  TRVTableItemInfo* table = new TRVTableItemInfo(10,6, RichViewEdit1->RVData);

  table->Color     = clWhite;
  table->BestWidth = -90;
  table->BorderStyle      = rvtbRaisedColor;
  table->CellBorderStyle  = rvtbLoweredColor;
  table->BorderLightColor = clWhite;
  table->BorderColor      = clBlack;
  table->CellBorderLightColor = clWhite;
  table->CellBorderColor  = clBlack;

  table->BorderWidth     = 2;
  table->BorderVSpacing  = 0;
  table->BorderHSpacing  = 0;
  table->CellBorderWidth = 2;
  table->CellPadding     = 3;
  table->CellVSpacing    = 0;
  table->CellHSpacing    = 0;
  table->Cells[0][0]->BestWidth = -16;
  table->Cells[0][1]->BestWidth = -16;
  table->Cells[0][2]->BestWidth = -16;
  table->Cells[0][3]->BestWidth = -16;
  table->Cells[0][4]->BestWidth = -16;
  table->Cells[0][5]->BestWidth = -16;
  table->MergeCells(2,0,2,8, false);

  TRVTableCellData* Cell = table->Cells[2][0];
  Cell->Clear();
  Cell->AddNLWTag("Another example.",0,0,0);
  TButton* btn = new TButton((TComponent*)NULL);
  btn->Caption = "With button inside";
  btn->Width   = 150;
  btn->OnClick = OnControlClick;
  Cell->AddControlEx("",btn,2,rvvaBaseline);
  Cell->SetItemExtraIntProperty(Cell->ItemCount-1, rvepResizable, 1);
  Cell->AddNLWTag("Width of table = 90% of document width. Widths of cells = 16%",0,0,0);

  if (RichViewEdit1->InsertItem("", table))
  {
  }
}
//---------------------------------------------------------------------------
// Table | Insert Table Example 3
void __fastcall TForm1::mitInsertTable3Click(TObject *Sender)
{
  TRVTableItemInfo* table = new TRVTableItemInfo(5,6, RichViewEdit1->RVData);

  table->Color            = (TColor)0x00A5CCE7;
  table->BorderStyle      = rvtbColor;
  table->CellBorderStyle  = rvtbColor;
  table->BorderColor      = (TColor)0x002E1234;
  table->CellBorderColor  = (TColor)0x002E1234;

  table->BorderWidth     = 2;
  table->BorderVSpacing  = 2;
  table->BorderHSpacing  = 2;
  table->CellBorderWidth = 1;
  table->CellPadding     = 3;
  table->CellVSpacing    = 0;
  table->CellHSpacing    = 0;
  table->BestWidth       = 400;

  int r,c;

  for (c = 0; c<table->Rows->Items[0]->Count; c++)
   table->Cells[0][c]->Color = (TColor)0x00A5E1F8;

  for (r = 1; r<table->Rows->Count; r++)
   table->Cells[r][0]->Color = (TColor)0x00A5E1F8;

  for (r = 1; r<table->Rows->Count; r++)
    for (c = 1; c<table->Rows->Items[r]->Count; c++)
    {
      table->Cells[r][c]->Color = (TColor)0x007AB4DA;
      if (c>1)
        table->Cells[r][c]->VisibleBorders->Left = false;
      if (c<table->Rows->Items[r]->Count-1)
        table->Cells[r][c]->VisibleBorders->Right = false;
    }

  RichViewEdit1->InsertText("Third example: width of table = 400 pixels, widths of cells - unspecified.", false);
  if (RichViewEdit1->InsertItem("", table))
  {
  }
}
//---------------------------------------------------------------------------
// Table | Insert Table Example 4
void __fastcall TForm1::mitInsertTable4Click(TObject *Sender)
{
  TRVTableItemInfo* table = new TRVTableItemInfo(3,3, RichViewEdit1->RVData);

  table->Color           = Graphics::clNone;
  table->BorderStyle     = rvtbColor;
  table->CellBorderStyle = rvtbColor;

  table->BorderWidth     = 1;
  table->BorderVSpacing  = 2;
  table->BorderHSpacing  = 2;
  table->CellBorderWidth = 1;
  table->CellPadding     = 3;
  table->CellVSpacing    = 5;
  table->CellHSpacing    = 5;
  table->VRuleWidth      = 1;
  table->HRuleWidth      = 1;
  for (int r=0; r<table->Rows->Count; r++)
    for (int c=0; c<table->Rows->Items[r]->Count; c++)
    {
      table->Cells[r][c]->BestWidth = 40;
      table->Cells[r][c]->Clear();
	  table->Cells[r][c]->AddFmt("%d,%d",ARRAYOFCONST((r,c)),0,0);
      table->Cells[r][c]->Color = clWhite;
    }
  RichViewEdit1->InsertText("Transparent table with rules", false);
  if (RichViewEdit1->InsertItem("", table))
  {
  }
}
//---------------------------------------------------------------------------
// Table submenu popups
void __fastcall TForm1::mpdTableClick(TObject *Sender)
{
  TCustomRichViewEdit* rve;
  TCustomRVItemInfo* item;
  if (!RichViewEdit1->GetCurrentItemEx(__classid(TRVTableItemInfo), rve, item))
  {
    mitRowsAbove->Enabled         = false;
    mitRowsBelow->Enabled         = false;
    mitColsLeft->Enabled          = false;
    mitColsRight->Enabled         = false;
    mitDelRows->Enabled           = false;
    mitDelColumns->Enabled        = false;
    mitMergeCells->Enabled        = false;
    mitUmRows->Enabled            = false;
    mitUmCols->Enabled            = false;
    mitUmRowsandCols->Enabled     = false;
    mitSplitVertically->Enabled   = false;
    mitSplitHorizontally->Enabled = false;
    return;
  }
  TRVTableItemInfo* table = (TRVTableItemInfo*)item;
  int r,c,cs,rs;
  bool Selected = table->GetNormalizedSelectionBounds(true,r,c,cs,rs);
  mitRowsAbove->Enabled         = Selected;
  mitRowsBelow->Enabled         = Selected;
  mitColsLeft->Enabled          = Selected;
  mitColsRight->Enabled         = Selected;
  mitDelRows->Enabled           = Selected;
  mitDelColumns->Enabled        = Selected;
  mitMergeCells->Enabled        = table->CanMergeSelectedCells(true);
  bool SelectionRectangular = Selected &&
                          (table->CanMergeSelectedCells(true) ||
                           table->GetEditedCell(r,c));
  mitSplitVertically->Enabled   = SelectionRectangular;
  mitSplitHorizontally->Enabled = SelectionRectangular;
  mitUmRows->Enabled            = SelectionRectangular;
  mitUmCols->Enabled            = SelectionRectangular;
  mitUmRowsandCols->Enabled     = SelectionRectangular;
}
//---------------------------------------------------------------------------
// Table | All other commands
void __fastcall TForm1::mitCellOperation(TObject *Sender)
{
  TCustomRVItemInfo* item;
  TCustomRichViewEdit* rve;
  int r,c,cs,rs;
  if (!RichViewEdit1->CanChange() ||
	  !RichViewEdit1->GetCurrentItemEx(__classid(TRVTableItemInfo), rve, item))
    return;
  TRVTableItemInfo* table = (TRVTableItemInfo*)item;
  int ItemNo = rve->GetItemNo(table);
  int Data;
  rve->BeginItemModify(ItemNo, Data);
  switch (((TMenuItem*)Sender)->Tag)
  {
    case 1:
      table->InsertRowsAbove(1);
      break;
    case 2:
      table->InsertRowsBelow(1);
      break;
    case 3:
      table->InsertColsLeft(1);
      break;
    case 4:
      table->InsertColsRight(1);
      break;
    case 5:
      {
        table->GetNormalizedSelectionBounds(true,r,c,cs,rs);
        if (rs==table->Rows->Count)
        {
          // deleting whole table
          rve->SetSelectionBounds(ItemNo,0,ItemNo,1);
          rve->DeleteSelection();
          return;
        }
        rve->BeginUndoGroup(rvutModifyItem);
        rve->SetUndoGroupMode(true);
        table->DeleteSelectedRows();
        // it's possible all-NULL rows/cols appear after deleting
        table->DeleteEmptyRows();
        table->DeleteEmptyCols();
        rve->SetUndoGroupMode(false);
        break;
      }
    case 6:
      {
        table->GetNormalizedSelectionBounds(true,r,c,cs,rs);
        if (cs==table->Rows->Items[0]->Count)
        {
          // deleting whole table
          rve->SetSelectionBounds(ItemNo,0,ItemNo,1);
          rve->DeleteSelection();
          return;
        }
        rve->BeginUndoGroup(rvutModifyItem);
        rve->SetUndoGroupMode(true);
        table->DeleteSelectedCols();
        // it's possible all-NULL rows/cols appear after deleting
        table->DeleteEmptyRows();
        table->DeleteEmptyCols();
        rve->SetUndoGroupMode(false);
        break;
      }
    case 7:
      {
        // 3 methods: MergeSelectedCells, DeleteEmptyRows, DeleteEmptyCols
        // must be undone as one action.
        // So using BeginUndoGroup - SetUndoGroupMode(true) - ... - SetUndoGroupMode(false)
        rve->BeginUndoGroup(rvutModifyItem);
        rve->SetUndoGroupMode(true);
        table->MergeSelectedCells(true);
        table->DeleteEmptyRows();
        table->DeleteEmptyCols();
        rve->SetUndoGroupMode(false);
        // table.MergeSelectedCells(False) will not allow to create empty columns
        // or rows
        break;
      }
    case 8:
      table->UnmergeSelectedCells(true, false);
      break;
    case 9:
      table->UnmergeSelectedCells(false, true);
      break;
    case 10:
      table->UnmergeSelectedCells(true, true);
      break;
    case 11:
      {
		UnicodeString s = L"2";
		if (InputQuery(L"Split Vertically", L"Columns (in each selected cell):",s))
		  table->SplitSelectedCellsVertically(StrToIntDef(s,0));
		break;
	  }
	case 12:
	  {
		UnicodeString s = L"2";
        if (InputQuery(L"Split Horizontally", L"Rows (in each selected cell):",s))
          table->SplitSelectedCellsHorizontally(StrToIntDef(s,0));
        break;
      }
  }
  rve->EndItemModify(ItemNo, Data);
  rve->Change();
}
//---------------------------------------------------------------------------