/*============================================================================
  Very simple "mail merging" application (LabelItem Version).
  It loads a template from TEMPLATE.RVF, and data from CUSTOMERS.TXT.
  Template can be modified with another application in this directory:
  TEMPLATEEDITORLI.

  Main settings:
  - since field names are stored in tags (see the help topic about tags)
    as strings, rvoTagsArePChars is included in Options of rvTemplate and
    rvOutput.
  - fields are represented with LabelItem item type.
  - rvOutput.Style = rvsOutput, rvTemplate.Style = rvsTemplate.
    In rvOutput, fields are not highlighted, in rvTemplate they are always
    highlighted.
===========================================================================*/
#include <vcl.h>
#include <stdio.h>
#pragma hdrstop

#include "MMMainFrm.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "RichView"
#pragma link "RVScroll"
#pragma link "RVStyle"
#pragma resource "*.dfm"
TfrmMainMerge *frmMainMerge;
//---------------------------------------------------------------------------
void ReadString(char*s, FILE*F)
{
   fgets(s, 200, F);
   int i=0;
   while (s[i])
   {
     if (s[i]=='\n')
       s[i]=0;
     i++;
   }
}
//---------------------------------------------------------------------------
/*
  This procedure loads file CUSTOMERS.TXT into:
  - ListBox1->Items (<- names of customers)
  - Codes (<- codes of customers)

  In real applications data can be stored in some database
*/
//---------------------------------------------------------------------------
void TfrmMainMerge::LoadCustomers()
{
  FILE* F = fopen((ExtractFilePath(Application->ExeName)+"Customers.txt").c_str(), "rt");
  char s[200];
  ReadString(s,F);
  int Count = StrToIntDef(s, 0);
  for (int i=0; i<Count; i++)
  {
    ReadString(s,F);
    Codes->Add(s);
    ReadString(s,F);
    ListBox1->Items->Add(Trim((AnsiString)s));
  }
  fclose(F);
}




//---------------------------------------------------------------------------
__fastcall TfrmMainMerge::TfrmMainMerge(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------
// Initialization: loading template into rvOutput, loading customers data.
void __fastcall TfrmMainMerge::FormCreate(TObject *Sender)
{
  Codes = new TStringList;
  LoadCustomers();
  rvTemplate->LoadRVF(ExtractFilePath(Application->ExeName)+"template.rvf");
  rvTemplate->Format();
  if (ListBox1->Items->Count)
  {
    ListBox1->ItemIndex = 0;
    ListBox1->OnClick(NULL);
  }
}
//---------------------------------------------------------------------------
void __fastcall TfrmMainMerge::FormDestroy(TObject *Sender)
{
  delete Codes;
  Codes = NULL;
}
//---------------------------------------------------------------------------
// Returns True if FieldName is a valid field code }
bool TfrmMainMerge::IsFieldCode(const AnsiString FieldName)
{
  return FieldName=="name" || FieldName=="code" ||
    FieldName.SubString(1, 5)=="date:";
}
//---------------------------------------------------------------------------
// This function returns the current field value by the field name.
// In this example, we have two data fields: "name" and "code",
//  and "date" field
AnsiString TfrmMainMerge::GetFieldValueFromDatabase(const AnsiString FieldName)
{
  int Index = ListBox1->ItemIndex;
  if (FieldName=="name")
    return ListBox1->Items->Strings[Index];
  if (FieldName=="code")
    return Codes->Strings[Index];
  if (FieldName.SubString(1, 5)=="date:")
  {
    AnsiString s = FieldName.SubString(6, FieldName.Length());
    TDate Date = (double)StrToFloat(s);
    return DateToStr(Date);
  }
  return "{error: illegal field code}";
}
//---------------------------------------------------------------------------
/*
  This function iterates through all items in RVData, and if tag of
  some label item is a data field, it calls GetFieldValueFromDatabase(tag)
  and replaces the label item's text with the returned value.
  You can move this function to your application unchanged.
  Initial call: FillFields(RichView->RVData);
*/
void TfrmMainMerge::FillFields(TCustomRVData* RVData)
{
  for (int i=0; i<RVData->ItemCount; i++)
    switch(RVData->GetItemStyle(i))
    {
      case rvsTable:
      {
        TRVTableItemInfo* table = (TRVTableItemInfo*)(RVData->GetItem(i));
        for (int r=0; r<table->RowCount; r++)
          for (int c=0; c<table->ColCount; c++)
            if (table->Cells[r][c])
              FillFields(table->Cells[r][c]->GetRVData());
        break;
      }
      case rvsLabel:
      {
        AnsiString FieldName = (char*)(RVData->GetItemTag(i));
        if (IsFieldCode(FieldName))
          ((TRVLabelItemInfo*)(RVData->GetItem(i)))->Text = GetFieldValueFromDatabase(FieldName);
        break;
      }
    }
}
//---------------------------------------------------------------------------
//  On highlighting a new list box item: updating document in rvOutput.
void __fastcall TfrmMainMerge::ListBox1Click(TObject *Sender)
{
   rvOutput->Clear();
  if (ListBox1->ItemIndex>=0)
  {
    rvOutput->LoadRVF(ExtractFilePath(Application->ExeName)+"template.rvf");
    FillFields(rvOutput->RVData);
    rvOutput->Format();
  }
}
//---------------------------------------------------------------------------



