/*******************************************************
{                                                       }
{       RichViewActions                                 }
{       Demo project.                                   }
{       You can use it as a basis for your              }
{       applications.                                   }
{                                                       }
{       Copyright (c) Sergey Tkachenko                  }
{       svt@trichview.com                               }
{       Copyright (c) Ilya Zelenskiy                    }
{       ilya@trichview.com                              }
{       http://www.trichview.com                        }
{                                                       }
{*******************************************************/
//---------------------------------------------------------------------------
/*
  Uncomment the defines below to enable support for Gif and Png.

  GifImage (by Anders Melander)
    http://www.torry.net/vcl/graphics/gif/gifimage.exe (original)
    http://www.trichview.com/resources/thirdparty/gifimage.zip (update)
  Note: for Delphi 2007+, use the built in TGifImage instead

  PngObject (by Gustavo Huffenbacher Daud)
    http://www.trichview.com/resources/thirdparty/pngimage.zip
*/

//#define USE_GIFIMAGE
//#define USE_PNGOBJECT

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
#include "DmActionsSRV.h"
#include "RVALocRuler.hpp"
//#include "RVAAddictLanguages.hpp"
#ifdef USE_GIFIMAGE
#include "GifImage.hpp"
#endif
#ifdef USE_PNGOBJECT
#include "PngImage.hpp"
#endif
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "RichViewActions"
#pragma link "Ruler"
#pragma link "RVFontCombos"
#pragma link "RVRuler"
#pragma link "RVScroll"
#pragma link "SclRView"
#pragma link "SclRVRuler"
#pragma link "SRVPageScroll"
#pragma link "SRVSkinManager"
#pragma link "SRVTabSet"
#pragma link "SRVToolWindow"
#pragma link "RVALocRuler"
//#pragma link "RVAAddictLanguages"
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
		: TForm(Owner)
{

#ifdef USE_GIFIMAGE
  RegisterClass(__classid(TGIFImage));
  RV_RegisterHTMLGraphicFormat(__classid(TGIFImage));
#endif
#ifdef USE_PNGOBJECT
  RegisterClass(__classid(TPNGObject));
  RV_RegisterHTMLGraphicFormat(__classid(TPNGObject));
  RV_RegisterPngGraphic(__classid(TPNGObject));
#endif

// IMPORTANT: allowing RichViewActions and TRVAPopupMenu working with TSRichViewEdit
  RVA_GetRichViewEditFromPopupComponent =
   SRVGetRichViewEditFromPopupComponent;
  RVA_GetRichViewEdit = SRVGetRichViewEdit;

}

void ShowInfo(UnicodeString msg, UnicodeString cpt)
{
  Application->MessageBox(msg.w_str(), cpt.w_str(), MB_OK | MB_ICONINFORMATION);
}
//---------------------------------------------------------------------------

void __fastcall TForm1::FormCreate(TObject *Sender)
{
  // Tabbed UI support
  Editors.Length = 1;
  Editors[0] = SRichViewEdit1;
  ActiveEditor = SRichViewEdit1;
  SRVTabSet1->TabIndex = 0;

  // Almost all these assignments could be done at design time in the Object Inspector
  // But in this demo we do not want to modify srvActionsResource
  // (and we recommend to use a copy of it in your applications)

  srvActionsResource->rvActionSave1->OnDocumentFileChange = rvActionSave1DocumentFileChange;

  // Code for making color-picking buttons stay pressed while a
  // color-picker window is visible/
  srvActionsResource->rvActionColor1->OnShowColorPicker = ColorPickerShow;
  srvActionsResource->rvActionColor1->OnHideColorPicker = ColorPickerHide;
  srvActionsResource->rvActionParaColor1->OnShowColorPicker = ColorPickerShow;
  srvActionsResource->rvActionParaColor1->OnHideColorPicker = ColorPickerHide;
  srvActionsResource->rvActionFontColor1->OnShowColorPicker = ColorPickerShow;
  srvActionsResource->rvActionFontColor1->OnHideColorPicker = ColorPickerHide;
  srvActionsResource->rvActionFontBackColor1->OnShowColorPicker = ColorPickerShow;
  srvActionsResource->rvActionFontBackColor1->OnHideColorPicker = ColorPickerHide;

  // Index of the last clicked button in search toolwindow
  VToolButtonIndex = -1;

  // Initializing the action for showing/hiding thumbnails
  srvActionsResource->srvActionThumbnails1->PageScroll = SRVPageScroll1;
  srvActionsResource->srvActionThumbnails1->OnExecuted = srvActionThumbnails1Executed;

  // AutoComplete feature causes OnClick generation when editing combo-box's text.
  // Since in OnClick we move input focus in RichViewEdit1, this effect is
  // undesirable
  cmbFont->AutoComplete = False;
  cmbFontSize->AutoComplete = False;

  // measuring units
  RVA_ConvertToTwips(srvActionsResource);
  RVAControlPanel1->UnitsProgram = rvstuTwips;
  SRichViewEdit1->ConvertToTwips();

  cmbUnits->ItemIndex = (int)(SRichViewEdit1->UnitsProgram);
  RVAControlPanel1->UnitsDisplay = SRichViewEdit1->UnitsProgram;

  // Applying the default language
  Localize();

  // Displaying hints on the status bar
  Application->OnHint = ApplicationHint;

  // Loading initial file via ActionOpen (allowing to update user interface)
  srvActionsResource->rvActionOpen1->LoadFile(ActiveEditor->RichViewEdit,
    ExtractFilePath(Application->ExeName)+"..\\readme.rvf", ffiRVF);

  /*
  // alternative way to start
    srvActionsResource->rvActionNew1->ExecuteTarget(ActiveEditor->RichViewEdit);
  */

  // Tabbed UI support
  srvActionsResource->rvActionNew1->OnExecute = OnNewEditor;
  srvActionsResource->rvActionOpen1->OnExecute = OnOpenEditor;
  ActiveEditor->RichViewEdit->Modified = false;
  UpdateIcon(ActiveEditor);
  SRichViewEdit1ZoomChanged(ActiveEditor);
  SRichViewEdit1CurrentPageChange(ActiveEditor);
}
//---------------------------------------------------------------------------
//--------------- Working with color-picking buttons ------------------------
//---------------------------------------------------------------------------

// Code for making color-picking buttons pressed while
// a color-picker window is visible.
void __fastcall TForm1::ColorPickerShow(TObject* Sender)
{
  if (((TAction*)Sender)->ActionComponent->InheritsFrom(__classid(TToolButton)))
    ((TToolButton*)(((TAction*)Sender)->ActionComponent))->Down = true;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ColorPickerHide(TObject* Sender)
{
  if (((TAction*)Sender)->ActionComponent->InheritsFrom(__classid(TToolButton)))
    ((TToolButton*)(((TAction*)Sender)->ActionComponent))->Down = false;
}
//---------------------------------------------------------------------------
//-------------- Set of events for processing hypertext links ---------------
//---------------------------------------------------------------------------
// Hyperlink click
void __fastcall TForm1::SRichViewEdit1Jump(TObject *Sender, int id)
{
  srvActionsResource->rvActionInsertHyperlink1->GoToLink(ActiveEditor->ActiveEditor, id);
}
//---------------------------------------------------------------------------
// Importing hyperlink
void __fastcall TForm1::SRichViewEdit1ReadHyperlink(
      TCustomRichView *Sender, const UnicodeString Target,
      const UnicodeString Extras, TRVLoadFormat DocFormat, int &StyleNo,
      int &ItemTag, TRVRawByteString &ItemName)
{
  if (DocFormat==rvlfURL)
    StyleNo =
      srvActionsResource->rvActionInsertHyperlink1->GetHyperlinkStyleNo(
        (TCustomRichViewEdit*)Sender);
  UnicodeString URL = srvActionsResource->rvActionInsertHyperlink1->EncodeTarget(Target);
  ItemTag = (int)StrNew(URL.w_str());
}
//---------------------------------------------------------------------------
// Exporting hyperlink to RTF and HTML
void __fastcall TForm1::SRichViewEdit1WriteHyperlink(
      TCustomRichView *Sender, int id, TCustomRVData *RVData, int ItemNo,
      TRVSaveFormat SaveFormat, UnicodeString &Target, UnicodeString &Extras)
{
  Target = (char*)RVData->GetItemTag(ItemNo);
}
//---------------------------------------------------------------------------

void __fastcall TForm1::SRichViewEdit1KeyDown(TObject *Sender, WORD &Key,
      TShiftState Shift)
{
  if (Key==VK_SPACE || Key==VK_RETURN || Key==VK_TAB)
  {
    /*
      // uncomment if you use Addict3/4
      RVA_Addict3AutoCorrect(ActiveEditor->ActiveEditor);
    */
    srvActionsResource->rvActionInsertHyperlink1->DetectURL(ActiveEditor->ActiveEditor);
    srvActionsResource->rvActionInsertHyperlink1->TerminateHyperlink(ActiveEditor->ActiveEditor);
  }

}
//---------------------------------------------------------------------------

void __fastcall TForm1::SRichViewEdit1KeyPress(TObject *Sender, char &Key)
{
  /*
  // uncomment if you use Addict3/4
  if (Key=='\'' || (Key!=' ' && ActiveEditor->ActiveEditor->Delimiters.Pos(Key)))
    RVA_Addict3AutoCorrect(ActiveEditor->ActiveEditor);
  */
}
//---------------------------------------------------------------------------
//----------------------- Insert table popup      ---------------------------
//---------------------------------------------------------------------------
// We use a trick: insert-table button has style tbsDropDown and assigned
// DropDownMenu (pmFakeDropDown). This menu is empty, but shows table size
// popup instead of itself
void __fastcall TForm1::pmFakeDropDownPopup(TObject *Sender)
{
  srvActionsResource->rvActionInsertTable1->ShowTableSizeDialog(
    ActiveEditor->ActiveEditor, ToolButton12);
}
//---------------------------------------------------------------------------
//--------------------- Working with font combo-boxes -----------------------
//---------------------------------------------------------------------------
// Switching focus to the ActiveEditor without accidental applying combos
// (they apply changes on exiting)
void TForm1::FocusActiveEditor()
{
  if (Visible)
  {
    UpdatingCombos = true;
    ActiveEditor->SetFocus();
    UpdatingCombos = false;
  }
}
//---------------------------------------------------------------------------
// Current font is changed. Updating the combo-boxes.
void __fastcall TForm1::SRichViewEdit1CurTextStyleChanged(TObject *Sender)
{
  UpdatingCombos = true;
  __try
  {
    TCustomRichViewEdit* rve = (TCustomRichViewEdit*)Sender;
    if (rve==ActiveEditor->ActiveEditor)
    {
      TFontInfo* CurStyle = rve->Style->TextStyles->Items[rve->CurTextStyleNo];
      cmbFont->Text = CurStyle->FontName;
      cmbFont->OnClick(Sender);
      cmbFontSize->FontName = CurStyle->FontName;
      cmbFontSize->Text = IntToStr(CurStyle->Size);
    }
  }
  __finally
  {
    UpdatingCombos = false;
  }
}
//---------------------------------------------------------------------------
// Applying the font name
void __fastcall TForm1::cmbFontClick(TObject *Sender)
{
  UnicodeString FontName;
  if (UpdatingCombos)
    return;
  if (cmbFont->ItemIndex<0)
    FontName = cmbFont->Text;
  else
    FontName = cmbFont->Items->Strings[cmbFont->ItemIndex];
  UpdatingCombos = true;
  cmbFontSize->FontName = FontName;
  UpdatingCombos = false;
  if (cmbFont->ItemIndex<0)
    cmbFont->ItemIndex = cmbFont->Items->IndexOf(FontName);
  if (cmbFont->ItemIndex<0)
  {
    if (Visible)
      Beep();
  }
  else
  {
    srvActionsResource->rvActionFontEx1->UserInterface = false;
    __try
    {
      TRVFontInfoMainProperties ValidProperties = TRVFontInfoMainProperties();
      ValidProperties << rvfimFontName;
      srvActionsResource->rvActionFontEx1->ValidProperties = ValidProperties;
      srvActionsResource->rvActionFontEx1->Font->Name = FontName;
      srvActionsResource->rvActionFontEx1->ExecuteTarget(ActiveEditor->ActiveEditor);
    }
    __finally
    {
      srvActionsResource->rvActionFontEx1->UserInterface = true;
    }
  }
  ActiveEditor->SetFocus();
}
//---------------------------------------------------------------------------
// Changing the font size
void __fastcall TForm1::cmbFontSizeClick(TObject *Sender)
{
  if (UpdatingCombos)
    return;
  try
  {
    int FontSize = StrToInt(cmbFontSize->Text);
    srvActionsResource->rvActionFontEx1->UserInterface = false;
    __try
    {
      TRVFontInfoMainProperties ValidProperties = TRVFontInfoMainProperties();
      ValidProperties << rvfimSize;
      srvActionsResource->rvActionFontEx1->ValidProperties = ValidProperties;
      srvActionsResource->rvActionFontEx1->Font->Size = FontSize;
      srvActionsResource->rvActionFontEx1->ExecuteTarget(ActiveEditor->ActiveEditor);
    }
    __finally
    {
      srvActionsResource->rvActionFontEx1->UserInterface = true;
    }
  }
  catch(...)
  {
    if (Visible)
      Beep();
  }
  ActiveEditor->SetFocus();
}
//---------------------------------------------------------------------------

void __fastcall TForm1::cmbKeyDown(TObject *Sender, WORD &Key,
      TShiftState Shift)
{
  if (Key==VK_RETURN)
  {
    Key = 0;
    ((TComboBox*)Sender)->OnClick(Sender);
  }
}
//---------------------------------------------------------------------------
//---------------------- Zooming combo box ----------------------------------
//---------------------------------------------------------------------------
// We could implement zooming using only actions, without a combo box
void __fastcall TForm1::SRichViewEdit1ZoomChanged(TObject *Sender)
{
  if (Sender!=ActiveEditor)
    return;
  UpdatingCombos = true;
  __try
  {
    switch (ActiveEditor->ViewProperty->ZoomMode)
    {
      case rvzmPageWidth:
        cmbZoom->ItemIndex = cmbZoom->Items->Count-2;
        break;
      case rvzmFullPage:
        cmbZoom->ItemIndex = cmbZoom->Items->Count-1;
        break;
      case rvzmCustom:
        cmbZoom->ItemIndex = cmbZoom->Items->IndexOf(
          IntToStr((int)ActiveEditor->ViewProperty->ZoomPercent));
        break;
    }
  }
  __finally
  {
    UpdatingCombos = false;
  }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::RVAControlPanel1ViewChanged(
      TrvCustomAction *Sender, TCustomRichViewEdit *Edit)
{
  SRichViewEdit1ZoomChanged(Edit);
}
//---------------------------------------------------------------------------
// Applying zooming
void __fastcall TForm1::cmbZoomChange(TObject *Sender)
{
  if (UpdatingCombos)
    return;
  if (cmbZoom->ItemIndex == cmbZoom->Items->Count-1)
    ActiveEditor->ViewProperty->ZoomMode = rvzmFullPage;
  else if (cmbZoom->ItemIndex == cmbZoom->Items->Count-2)
    ActiveEditor->ViewProperty->ZoomMode = rvzmPageWidth;
  else if (cmbZoom->ItemIndex>=0)
  {
    ActiveEditor->ViewProperty->ZoomPercent = StrToIntDef(cmbZoom->Text, 0);
    ActiveEditor->ViewProperty->ZoomMode = rvzmCustom;
  }
}
//---------------------------------------------------------------------------
//----------------------------- Units combo box -----------------------------
//---------------------------------------------------------------------------
// Applying units

void __fastcall TForm1::cmbUnitsClick(TObject *Sender)
{
  for (int i = 0; i<Editors.Length; i++)
    Editors[i]->UnitsProgram = (TRVUnits)(cmbUnits->ItemIndex);
  RVAControlPanel1->UnitsDisplay = (TRVUnits)(cmbUnits->ItemIndex);
  SclRVRuler1->UnitsDisplay = (TRulerUnits)(cmbUnits->ItemIndex);
  SclRVRuler2->UnitsDisplay = (TRulerUnits)(cmbUnits->ItemIndex);
}
//---------------------------------------------------------------------------
//------- Synchronizing ScaleRichView after non-editing operations ----------
//---------------------------------------------------------------------------
void __fastcall TForm1::RVAControlPanel1MarginsChanged(TrvAction *Sender,
      TCustomRichViewEdit *Edit)
{

  TSRichViewEdit* SRichViewEdit = Editors[GetIndexOfEditorByRichViewEdit(Edit)];
  bool WasModified = Edit->Modified;

  Edit->RVData->State << rvstSkipFormatting;
  SRichViewEdit->SetRVMargins();

  SclRVRuler1->UnitsDisplay = (TRulerUnits)(ActiveEditor->UnitsProgram);
  SclRVRuler2->UnitsDisplay = (TRulerUnits)(ActiveEditor->UnitsProgram);
  SclRVRuler1->CheckMargin();
  SclRVRuler2->CheckMargin();

  Edit->RVData->State >> rvstSkipFormatting;
  Edit->Modified = WasModified;
  UpdateIcon(SRichViewEdit);
}
//---------------------------------------------------------------------------

void __fastcall TForm1::RVAControlPanel1BackgroundChange(TrvAction *Sender,
      TCustomRichViewEdit *Edit)
{
  ActiveEditor->Repaint();
}
//---------------------------------------------------------------------------
//---------------------------- Localization ---------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
  if (RVA_ChooseLanguage())
    Localize();
}
//---------------------------------------------------------------------------
void TForm1::Localize()
{
  // Fonts
  Font->Charset = RVA_GetCharset();
  stat1->Font->Charset = RVA_GetCharset();
  Screen->HintFont->Charset = RVA_GetCharset();
  Screen->MenuFont->Charset = RVA_GetCharset();
  // Localizing all actions on srvActionsResource
  RVA_LocalizeForm(srvActionsResource);
  // Localizing all actions on this form
  RVA_LocalizeForm(this);
  // Localizing ruler
  RVALocalizeRuler(SclRVRuler1);
  RVALocalizeRuler(SclRVRuler2);
  // Localizing the editors
  for (int i=0; i<Editors.Length; i++)
  {
    SRVA_LocalizeSRichViewEdit(Editors[i]);
    ((TSRVToolButton*)(Editors[i]->MenuHButtons->Items[0]))->Hint = RVADeleteAmp(SRVA_GetS(srvam_act_Draft));
    ((TSRVToolButton*)(Editors[i]->MenuHButtons->Items[1]))->Hint = RVADeleteAmp(SRVA_GetS(srvam_act_WebLayout));
    ((TSRVToolButton*)(Editors[i]->MenuHButtons->Items[2]))->Hint = RVADeleteAmp(SRVA_GetS(srvam_act_PrintLayout));
  }
  // Localizing the search tool window
  SRVA_LocalizeToolWindow(srvtwSearch);
  // Localizing menus and tool buttons
  mitFile->Caption = RVA_GetS(rvam_menu_File);
  mitEdit->Caption = RVA_GetS(rvam_menu_Edit);
  mitFont->Caption = RVA_GetS(rvam_menu_Font);
  mitPara->Caption = RVA_GetS(rvam_menu_Para);
  mitFormat->Caption = RVA_GetS(rvam_menu_Format);
  mitInsert->Caption = RVA_GetS(rvam_menu_Insert);
  mitTable->Caption = RVA_GetS(rvam_menu_Table);
  mitExit->Caption = RVA_GetS(rvam_menu_Exit);

  mitFontSize->Caption = RVA_GetS(rvam_menu_FontSize);
  mitFontStyle->Caption = RVA_GetS(rvam_menu_FontStyle);
  mitTextFlow->Caption = RVA_GetS(rvam_menu_TextFlow);

  mitTableSelect->Caption = RVA_GetS(rvam_menu_TableSelect);
  mitTableCellBorders->Caption = RVA_GetS(rvam_menu_TableCellBorders);
  mitTableAlignCellContents->Caption = RVA_GetS(rvam_menu_TableCellAlign);

  btnPageFormat->Caption = SRVA_GetS(srvam_menu_PageSize);
  btnPageFormat->Hint = RVADeleteAmp(btnPageFormat->Caption);
  // In your application, you can use either TrvActionFonts or TrvActionFontEx
  srvActionsResource->rvActionFonts1->Caption = srvActionsResource->rvActionFonts1->Caption+" (Standard)";
  srvActionsResource->rvActionFontEx1->Caption = srvActionsResource->rvActionFontEx1->Caption+" (Advanced)";

  // Localizing measuring units
  int Index = cmbUnits->ItemIndex;
  RVA_TranslateUnits(cmbUnits->Items);
  cmbUnits->ItemIndex = Index;

  // Localizing the zoom combo box

  Index = cmbZoom->ItemIndex;
  cmbZoom->Items->Strings[cmbZoom->Items->Count-2] = RVA_GetS(rvam_pp_PageWidth);
  cmbZoom->Items->Strings[cmbZoom->Items->Count-1] = RVA_GetS(rvam_pp_FullPage);
  cmbZoom->ItemIndex = Index;


  // Localizing text on the status bar
  SRichViewEdit1CurrentPageChange(ActiveEditor);
  SRichViewEdit1PageScrolled(ActiveEditor);
  SRichViewEdit1CaretMove(ActiveEditor);

  /*
  // uncomment if you use Addict3/4. It's assumed that RVAddictSpell31
  // and RVThesaurus31 are on this form.
  RVAddictSpell31->UILanguage = GetAddictSpellLanguage(RVA_GetLanguageName);
  RVThesaurus31->UILanguage = GetAddictThesLanguage(RVA_GetLanguageName);
  */
}
//---------------------------------------------------------------------------
//---------------------- Live spelling with Addict 3 ------------------------
//---------------------------------------------------------------------------
/*
// Add these events if you use Addict3
// (Assuming that you have RVAddictSpell31: TRVAddictSpell3 on the form)

// OnSpellingCheck event
void __fastcall TForm1::SRichViewEdit1SpellingCheck(TCustomRichView* Sender,
  cont UnicodeString AWord, int StyleNo, bool & Misspelled)
{
  Misspelled = ! (RVAddictSpell31->WordAcceptable(AWord));
}

// RVAddictSpell31.OnParserIgnoreWord: if Ignore All or Add buttons were pressed
// in spellchecker dialog, removing underlines from the ignored word
void __fastcall TForm1::RVAddictSpell31ParserIgnoreWord(TObject* Sender,
  bool Before, int State)
{
  if (!Before && (State==IgnoreState_IgnoreAll || State==IgnoreState_Add))
    ActiveEditor->ActiveEditor.LiveSpellingValidateWord(RVAddictSpell31->CurrentWord);
}

// Besides, if you want spelling check starting when loading document, call
// ActiveEditor->RichViewEdit->StartLiveSpelling in rvActionFileOpen->OnOpenFile event
*/
//---------------------------------------------------------------------------
//------------------------------ Status bar ---------------------------------
//---------------------------------------------------------------------------
// Displaying the index of the edited page{
void __fastcall TForm1::SRichViewEdit1CurrentPageChange(TObject *Sender)
{
  if (Sender==ActiveEditor)
    stat1->Panels->Items[1]->Text = Format(SRVA_GetS(srvam_PageMofN),
      ARRAYOFCONST((ActiveEditor->CurrentPage, ActiveEditor->PageCount)));
}
//---------------------------------------------------------------------------
// Displaying the index of the visible page
void __fastcall TForm1::SRichViewEdit1PageScrolled(TObject *Sender)
{
  if (Sender==ActiveEditor)
  {
    int PageNo = ActiveEditor->ScrolledPage;
    stat1->Panels->Items[0]->Text  = Format(SRVA_GetS(srvam_ViewPageX),
      ARRAYOFCONST((PageNo)));
  }
}
//---------------------------------------------------------------------------
// Displaying the current line and column
void __fastcall TForm1::SRichViewEdit1CaretMove(TObject *Sender)
{
  int Line, Column;
  if (ActiveEditor && Sender==ActiveEditor->ActiveEditor)
  {
    ActiveEditor->GetCurrentLineCol(Line, Column);
    stat1->Panels->Items[2]->Text = Format(SRVA_GetS(srvam_LineX), ARRAYOFCONST((Line)));
    stat1->Panels->Items[3]->Text = Format(SRVA_GetS(srvam_ColX), ARRAYOFCONST((Column)));
  }
}
//---------------------------------------------------------------------------
// switching to header/footer/main
void __fastcall TForm1::SRichViewEdit1ChangeActiveEditor(
      TSRichViewEdit *Sender, TRichViewEdit *ActiveEditor)
{
  SRichViewEdit1CaretMove(ActiveEditor);
}
//---------------------------------------------------------------------------
// Displaying hints
void __fastcall TForm1::ApplicationHint(TObject* Sender)
{
  UnicodeString s = GetLongHint(Application->Hint);
  stat1->SimplePanel = ! s.IsEmpty();
  stat1->SimpleText = s;
  stat1->Repaint();
}
//---------------------------------------------------------------------------
//--------------------- Buttons on scroll-bars ------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::SRichViewEdit1HMenuClickButton(TObject *Sender,
      TSRVToolButton *ToolButton)
{
  if (!ToolButton)
    return;
  ActiveEditor->CanUpdate = false;
  __try
  {
    switch (ToolButton->Index)
    {
      case 0:
        srvActionsResource->srvActionLayoutDraft1->Execute();
        break;
      case 1:
        srvActionsResource->srvActionLayoutWeb1->Execute();
        break;
      case 2:
        srvActionsResource->srvActionLayoutPrint1->Execute();
        break;
    }
  }
  __finally
  {
  ActiveEditor->CanUpdate = true;
  }
}
//---------------------------------------------------------------------------
// On vertical scroll bar

void __fastcall TForm1::SRichViewEdit1VMenuClickButton(TObject *Sender,
      TSRVToolButton *ToolButton)
{
  if (!ToolButton)
    return;
  int ItemStyles[4];
  switch (ToolButton->Index)
  {
    case 0 :  // "Up arrows" button, performs search to the top
    {
      switch (VToolButtonIndex)
      {
        case SRV_TOOLWIN_PAGE: case -1:
          ActiveEditor->PriorCurPage();
          break;
        case SRV_TOOLWIN_TABLE:
          ItemStyles[0] = rvsTable;
          ActiveEditor->PriorCurItem(ItemStyles, 0);
          break;
        case SRV_TOOLWIN_PICTURE:
          ItemStyles[0] = rvsPicture;
          ItemStyles[1] = rvsHotPicture;
          ItemStyles[2] = rvsBullet;
          ItemStyles[3] = rvsHotspot;
          ActiveEditor->PriorCurItem(ItemStyles, 3);
          break;
        case SRV_TOOLWIN_HEADLINE:
          ActiveEditor->PriorCurHeading();
          break;
        case SRV_TOOLWIN_HYPERLINK:
          ActiveEditor->PriorCurHyperlink();
          break;
        case SRV_TOOLWIN_TEXT:
          fd->Options >> frDown;
          fdFind(NULL);
          break;
      }
      break;
    }
    case 1: // "Circle" button, shows tool window
    {
      int sbX = ActiveEditor->MenuVertical->SRVToolBar->Width;
      int sbY = ActiveEditor->MenuVertical->SRVToolBar->Height / 3;
      TPoint p = ActiveEditor->MenuVertical->SRVToolBar->ClientToScreen(Point(0, 0));
      p.y += sbY;
      srvtwSearch->Execute(Bounds(p.x, p.y, sbX, sbY));
      break;
    }
    case 2: // "Down arrows" button, performs search to the bottom
    {
      switch (VToolButtonIndex)
      {
        case SRV_TOOLWIN_PAGE: case -1:
          ActiveEditor->NextCurPage();
          break;
        case SRV_TOOLWIN_TABLE:
          ItemStyles[0] = rvsTable;
          ActiveEditor->NextCurItem(ItemStyles, 0);
          break;
        case SRV_TOOLWIN_PICTURE:
          ItemStyles[0] = rvsPicture;
          ItemStyles[1] = rvsHotPicture;
          ItemStyles[2] = rvsBullet;
          ItemStyles[3] = rvsHotspot;
          ActiveEditor->NextCurItem(ItemStyles, 3);
          break;
        case SRV_TOOLWIN_HEADLINE:
          ActiveEditor->NextCurHeading();
          break;
        case SRV_TOOLWIN_HYPERLINK:
          ActiveEditor->NextCurHyperlink();
          break;
        case SRV_TOOLWIN_TEXT:
          fd->Options << frDown;
          fdFind(NULL);
          break;
      }
      break;
    }
  }
}
//---------------------------------------------------------------------------
// Button on the tool window is clicked
void __fastcall TForm1::srvtwSearchClickButton(TObject *Sender,
      TSRVToolButton *ToolButton)
{
  if (!ToolButton)
  {
    VToolButtonIndex = -1;
    return;
  }
  VToolButtonIndex = ToolButton->Index;
  if (ToolButton->Index == SRV_TOOLWIN_TEXT) // starting text search
  {
    ActiveEditor->SetFocus();
    ActiveEditor->StartEditing(srvrveMain);
    fd->CloseDialog();
    if (ActiveEditor->RichViewEdit->SelectionExists())
    {
      UnicodeString s = ActiveEditor->RichViewEdit->GetSelText();
      int p = s.Pos('\r');
      if (p)
        s = s.SubString(1,p-1);
      fd->FindText = s;
    }
    fd->Execute();
  }
  else // starting search
    SRichViewEdit1VMenuClickButton(Sender,
      (TSRVToolButton*)(ActiveEditor->MenuVButtons->Items[2]));
}
//---------------------------------------------------------------------------
// text search
void __fastcall TForm1::fdFind(TObject *Sender)
{
  if (!ActiveEditor->RichViewEdit->SearchText(fd->FindText,GetRVESearchOptions(fd->Options)))
  {
    UnicodeString s = fd->FindText;
    ShowInfo(Format(RVA_GetS(rvam_src_NotFound), ARRAYOFCONST((s))), RVA_GetS(rvam_src_Complete));
  }
}
//---------------------------------------------------------------------------
//-------------------------------- Misc. ------------------------------------
//---------------------------------------------------------------------------
// On dowloading image

void __fastcall TForm1::RVAControlPanel1Download(TrvAction *Sender,
      const UnicodeString Source)
{
  if (Source.IsEmpty())
    Application->Hint = "";
  else
    Application->Hint = "Downloading "+Source+"...";
}
//---------------------------------------------------------------------------
// On clicking a table icon
void __fastcall TForm1::SRichViewEdit1TableIconClick(
      TSRichViewEdit *Sender, TMouseButton Button, TShiftState Shift,
      int X, int Y, int PageNo)
{
  Sender->GetTableIconItem()->SelectRows(0, Sender->GetTableIconItem()->RowCount);
  Sender->Repaint();
}
//---------------------------------------------------------------------------
//  Double clicking on the rulers' margins shows the page setup dialog
void __fastcall TForm1::SclRVRuler1MarginDblClick(TObject *Sender,
      TMarginType Margin)
{
   srvActionsResource->srvActionPageSetup1->ExecuteTarget(ActiveEditor);
}
//---------------------------------------------------------------------------
// After TsrvActionThumbnails is executed
void __fastcall TForm1::srvActionThumbnails1Executed(TObject* Sender)
{
  Splitter1->Visible = ((TsrvActionThumbnails*)Sender)->Checked;
  SRVPageScroll1->Visible = ((TsrvActionThumbnails*)Sender)->Checked;
}
//---------------------------------------------------------------------------
//-------------------------- Tabbed User Interface --------------------------
//---------------------------------------------------------------------------
/*
  Main variables:
  Editors[] - array of opened editors, in the order of tabs
  ActiveEditor - focused editor (on the active tab). This editor is visible,
    others are hidden.
*/

// Returns the index of tab icon depending on IsNew (document was created
// but never saved), FileFormat, Modified (document has unsaved changes)
int TForm1::GetIconIndex(bool IsNew, TrvFileSaveFilter FileFormat, bool Modified)
{
  int r = 0;
  if (!IsNew)
    switch (FileFormat)
    {
      case ffeRVF:
        r = 1;
        break;
      case ffeRTF:
        r = 2;
        break;
      case ffeTextANSI:
      case ffeTextUnicode:
        r = 3;
        break;
    }
  if (Modified)
    r += 4;
  return r;
}
// rvActionSave1->OnDocumentFileChange: occurs when document is created, saved, loaded...
// This event occurs on New, SaveAs, Open actions
void __fastcall TForm1::rvActionSave1DocumentFileChange(TObject* Sender,
  TCustomRichViewEdit* Editor, const UnicodeString FileName,
  TrvFileSaveFilter FileFormat, bool IsNew)
{
  UnicodeString s = ExtractFileName(FileName);

  srvActionsResource->srvActionPrint1->Title = s;
  srvActionsResource->srvActionQuickPrint1->Title = s;

  int Index = GetIndexOfEditorByRichViewEdit(Editor);

  if (Index >= 0)
  {
    TSRVTabItem* TI = SRVTabSet1->Tabs->Items[Index];
    TI->Text = s;
    TI->ImageIndex = GetIconIndex(IsNew, FileFormat, false);
  }
}
// Prompt for saving when the form closes
void __fastcall TForm1::FormCloseQuery(TObject *Sender, bool &CanClose)
{
  while (SRVTabSet1->Tabs->Count > 0)
  {
    CanClose = srvActionsResource->rvActionSave1->CanCloseDoc(ActiveEditor->RichViewEdit);
    if (CanClose)
      if (SRVTabSet1->Tabs->Count > 1)
      {
        RemoveEditor(SRVTabSet1->TabIndex);
        delete SRVTabSet1->Tabs->Items[SRVTabSet1->TabIndex];
        SetEditor(SRVTabSet1->Tabs->Count-1);
      }
      else
        break;
    else
      break;
  }
}
//---------------------------------------------------------------------------
// exiting
void __fastcall TForm1::mitExitClick(TObject *Sender)
{
  Close();
}
//---------------------------------------------------------------------------
// Returns the index of TSRichViewEdit in Editors[] by its RichViewEdit
int TForm1::GetIndexOfEditorByRichViewEdit(TCustomRichViewEdit* rve)
{
  for (int i=0; i<Editors.Length; i++)
    if (Editors[i]->RichViewEdit==rve)
      return i;
  return -1;
}
//---------------------------------------------------------------------------
// Returns information about document opened in TRichViewEdit
TrvaDocumentInfo* TForm1::GetDocInfo(TCustomRichViewEdit* rve)
{
  int DocIndex = srvActionsResource->rvActionSave1->FindDoc(rve);
  if (DocIndex>=0)
    return (TrvaDocumentInfo*)(srvActionsResource->rvActionSave1->Documents->Items[DocIndex]);
  return NULL;
}
//---------------------------------------------------------------------------
// Returns information about the active document (opened in ActiveEditor)
TrvaDocumentInfo* TForm1::GetActiveDocInfo()
{
  return GetDocInfo(ActiveEditor->RichViewEdit);
}
//---------------------------------------------------------------------------
// Adds a new tab with editor, making it active
void TForm1::AddEditor()
{
  Editors.Length = Editors.Length+1;

  TSRichViewEdit* srve = new TSRichViewEdit(ActiveEditor->Owner);
  srve->Hide();
  srve->Parent = ActiveEditor->Parent;
  srve->Align = alClient;
  srve->BackgroundProperty->Assign(ActiveEditor->BackgroundProperty);
  srve->MenuHorizontal->Assign(ActiveEditor->MenuHorizontal);
  srve->MenuVertical->Assign(ActiveEditor->MenuVertical);
  srve->UnitsProgram = ActiveEditor->UnitsProgram;
  srve->PopupMenu = ActiveEditor->PopupMenu;
  srve->SkinManager = ActiveEditor->SkinManager;
  srve->ViewProperty->MarginsRectVisible = ActiveEditor->ViewProperty->MarginsRectVisible;
  srve->HScrollBarSchemeIndex = ActiveEditor->HScrollBarSchemeIndex;
  srve->VScrollBarSchemeIndex = ActiveEditor->VScrollBarSchemeIndex;
  srve->OnCaretMove = SRichViewEdit1CaretMove;
  srve->OnCurrentPageChange = SRichViewEdit1CurrentPageChange;
  srve->OnCurTextStyleChanged = SRichViewEdit1CurTextStyleChanged;
  srve->OnHMenuClickButton = SRichViewEdit1HMenuClickButton;
  srve->OnJump = SRichViewEdit1Jump;
  srve->OnKeyDown = SRichViewEdit1KeyDown;
  srve->OnCurrentPageChange = SRichViewEdit1CurrentPageChange;
  srve->OnPageScrolled = SRichViewEdit1PageScrolled;
  srve->OnTableIconClick = SRichViewEdit1TableIconClick;
  srve->OnVMenuClickButton = SRichViewEdit1VMenuClickButton;
  srve->OnWriteHyperlink = SRichViewEdit1WriteHyperlink;
  srve->OnReadHyperlink = SRichViewEdit1ReadHyperlink;  
  srve->OnChange = SRichViewEdit1Change;
  srve->OnZoomChanged = SRichViewEdit1ZoomChanged;
  srve->OnZoomViewChanged = SRichViewEdit1ZoomChanged;
  srve->Loaded();
  SRVA_LocalizeSRichViewEdit(srve);
  srve->ConvertToTwips();

  srve->Show();
  ActiveEditor->Hide();
  ActiveEditor = srve;

  srve->ResetEventRuler();
  SclRVRuler1->SRichViewEdit = srve;
  SclRVRuler2->SRichViewEdit = srve;
  SRVPageScroll1->SRichViewEdit = srve;

  Editors[Editors.Length-1] = srve;

  SRVTabSet1->Tabs->Add();
  SRVTabSet1->TabIndex = Editors.Length-1; // calls SetEditor
  // Some assignments may set Modified flag, resetting
  srve->RichViewEdit->Modified = False;
  UpdateIcon(srve);  
  FocusActiveEditor();
}
//---------------------------------------------------------------------------
// Makes Editors[Index] active
void TForm1::SetEditor(int Index)
{
  Index = Min(Max(Index, 0), SRVTabSet1->Tabs->Count-1);

  if (SRVTabSet1->TabIndex != Index)
    SRVTabSet1->TabIndex = Index;

  if (ActiveEditor != Editors[Index])
  {
    if (ActiveEditor)
      ActiveEditor->Hide();
    ActiveEditor = Editors[Index];
    ActiveEditor->Show();
  }
  RVAControlPanel1->DefaultControl = ActiveEditor->RichViewEdit;
  ActiveEditor->ResetEventRuler();
  SclRVRuler1->SRichViewEdit = ActiveEditor;
  SclRVRuler2->SRichViewEdit = ActiveEditor;
  SRVPageScroll1->SRichViewEdit = ActiveEditor;
  TrvaDocumentInfo* DocInfo = GetActiveDocInfo();
  if (DocInfo)
  {
    srvActionsResource->srvActionPrint1->Title = ExtractFileName(DocInfo->FileName);
    srvActionsResource->srvActionQuickPrint1->Title = ExtractFileName(DocInfo->FileName);
  }
  RVAControlPanel1MarginsChanged(NULL, ActiveEditor->RichViewEdit);
  RVAControlPanel1ViewChanged(NULL, ActiveEditor->RichViewEdit);
  SRichViewEdit1CurrentPageChange(ActiveEditor);
  SRichViewEdit1PageScrolled(ActiveEditor);
  FocusActiveEditor();
}
//---------------------------------------------------------------------------
// Deletes Editors[Index] (but does not deletes its tab)
// Usually this function is used to close the active editor
void TForm1::RemoveEditor(int Index)
{
  int i = srvActionsResource->rvActionSave1->FindDoc(Editors[Index]->RichViewEdit);
  if (i>=0)
    srvActionsResource->rvActionSave1->Documents->Delete(i);
  if (Editors[Index]==ActiveEditor)
  {
    SclRVRuler1->SRichViewEdit = NULL;
    SclRVRuler2->SRichViewEdit = NULL;
    SRVPageScroll1->SRichViewEdit = NULL;
    ActiveEditor = NULL;
  }
  delete Editors[Index];
  for (int i = Index; i<Editors.Length-1; i++)
    Editors[i] = Editors[i+1];
  Editors.Length = Editors.Length - 1;
}
// SRVTabSet1.OnChange: another tab became active
void __fastcall TForm1::SRVTabSet1Change(TObject *Sender)
{
  SetEditor(SRVTabSet1->TabIndex);        
}
//---------------------------------------------------------------------------
// SRVTabSet1->OnCloseTab: checking if we can close this tab
void __fastcall TForm1::SRVTabSet1CloseTab(TSRVTabSet *Sender,
      int TabIndex, bool &CanClose)
{
  CanClose = srvActionsResource->rvActionSave1->CanCloseDoc(Editors[TabIndex]->RichViewEdit);
  if (CanClose)
    RemoveEditor(TabIndex);
}
//---------------------------------------------------------------------------
// srvActionsResource->rvActionNew1->OnExecute: "File | New" command
void __fastcall TForm1::OnNewEditor(TObject* Sender)
{
  // Instead of applying to the active editor,
  // we creating a new editor, making it active,
  AddEditor();
  // then execute rvActionNew for this new editor
  srvActionsResource->rvActionNew1->ExecuteTarget(ActiveEditor->RichViewEdit);
  // Some assignments may set Modified flag, resetting
  ActiveEditor->RichViewEdit->Modified = false;
  UpdateIcon(ActiveEditor);
}
//---------------------------------------------------------------------------
// srvActionsResource->rvActionOpen1->OnExecute: "File | Open..." command
void __fastcall TForm1::OnOpenEditor(TObject* Sender)
{
  // Instead of applying to the active editor,
  // we creating a new editor, making it active,
  AddEditor();
  // then execute rvActionOpen for this new editor
  srvActionsResource->rvActionOpen1->ExecuteTarget(ActiveEditor->RichViewEdit);
  // Some assignments may set Modified flag, resetting
  ActiveEditor->RichViewEdit->Modified = false;
  UpdateIcon(ActiveEditor);
  // But may be the user pressed "Cancel" in the file opening dialog.
  // In this case, we closing the new tab.
  TrvaDocumentInfo* DocInfo = GetActiveDocInfo();
  if (!DocInfo || !DocInfo->Defined)
  {
    RemoveEditor(SRVTabSet1->TabIndex);
    delete SRVTabSet1->Tabs->Items[SRVTabSet1->TabIndex];
    SetEditor(Max(SRVTabSet1->TabIndex-1, 0));
  }
}
//---------------------------------------------------------------------------
// updating tab icon depending on Editor.RichViewEdit.Modified
void TForm1::UpdateIcon(TSRichViewEdit* Editor)
{
  // Updating the tab icon to show a "modified" state
  TrvaDocumentInfo* DocInfo = GetDocInfo(Editor->RichViewEdit);
  if (!DocInfo)
    return;
  int EditIndex = GetIndexOfEditorByRichViewEdit(DocInfo->rve);
  if (EditIndex >= 0)
  {
    TSRVTabItem* TI = SRVTabSet1->Tabs->Items[EditIndex];
    TI->ImageIndex = GetIconIndex(!DocInfo->Defined, DocInfo->FileFormat,
      Editor->RichViewEdit->Modified);
  }
}
//---------------------------------------------------------------------------
// OnChange event (usually called for the ActiveEditor)
void __fastcall TForm1::SRichViewEdit1Change(TObject *Sender)
{
  UpdateIcon((TSRichViewEdit*)Sender);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::SRVTabSet1TabMove(TSRVTabSet *Sender,
      int NewTabIndex, int OldTabIndex)
{
  TSRichViewEdit* tmp = Editors[OldTabIndex];
  Editors[OldTabIndex] = Editors[NewTabIndex];
  Editors[NewTabIndex] = tmp;
}
//---------------------------------------------------------------------------
