// Includo stdio senno' dice che ridefinisco FILE
#include <stdio.h>
#include <fstream.h>


#include <applicat.h>
#include <files.h>
#include <utility.h>
#include <expr.h>
#include <isam.h>
#include <mask.h>
#include <sheet.h>
#include <msksheet.h>
#include <urldefid.h>
#include <validate.h>

#include "ba1100.h"

TMask*       TRec_sheet::_mask = NULL;
HIDDEN       TToken_string s(256);


void TDir_sheet::add ()

{
  _dir->get(LF_DIR, _lock, _nordir, _sysdirop);
  const int nitems = (int)_dir->eod() + 1;

  _dir->eod() = nitems;
  _dir->put(LF_DIR);
  _dir->zero();
  _dir->put(nitems);
  _items = nitems;
  
  //  select(nitems - 1);
}

TDir_sheet::TDir_sheet(const char* title, const char * columns, byte buttons)
:TSheet(-1,-1, 0, 0, title,columns,buttons)
{
  _dir = new TDir;
  _rec = new TTrec;
  rebuild();
}

TDir_sheet::~TDir_sheet()
{
  delete _dir;
  delete _rec;
}

void TDir_sheet::page_build(long first, byte rows)

{
  TToken_string l(128);

  for (byte i = 0; i < rows; i++)
  {
    const int n = int(i+first+1);
    _dir->get (n,_nolock,_nordir,_sysdirop);

    l = format("%3d", n); // Numero progressivo del file
    l.add(_dir->name());
    const TRecnotype eod = _dir->eod();
    l.add(format("%ld", eod));
    const TRecnotype eox = _dir->eox();
    l.add(format("%ld", eox));
    const word len = _dir->len();
    l.add(format("%u", len));
    l.add(_dir->des());
    l.add(_dir->expr());
    l.add(format("%ld", _dir->flags()));
    set_row(l, i);
  }
}


TRec_sheet::TRec_sheet(int logicnum) 

{
  _dir = new TDir;
  _rec = new TTrec;
  _rec_old = new TTrec;
  _mask = new TMask("ba1100d");

  _dir->get(logicnum, _lock, _nordir, _sysdirop);
  _rec->get(logicnum);
  *_rec_old = *_rec;
}

TRec_sheet::~TRec_sheet()
{
  delete _dir;
  delete _rec;
  delete _rec_old;
  delete _mask;
  _mask = NULL;
}

bool TRec_sheet::check_key_expr(int key, const char * key_expr)

{
  TExpression expr("", _strexpr);
  return expr.set(key_expr, _strexpr);
}

HIDDEN bool len_handler(TMask_field& f, KEY key)

{
  const int len = atoi(f.get());

  if (len < 0) return FALSE;

  const int typef = atoi(f.mask().get(FLD_TIPO));

  switch (typef)
  {
  case _alfafld: 
    return len <= 254;
  case _intfld: 
    return len <= 5;
  case _longfld: 
    return len <= 10;
  case _realfld:  
    return len <= 18;
  case _wordfld:  
    return len <= 5;
  case _intzerofld:  
    return len <= 5;
  case _longzerofld:  
    return len <= 10;
  default: 
    return TRUE;
  }
  return TRUE;
}


bool TRec_sheet::fld_notify(int r, KEY k)
{
  const TSheet_field& f = (const TSheet_field&) _mask->field(F_FIELDS);

  if (k == K_SPACE)
  {
    TMask& m = f.sheet_mask();

    m.set(F_NUMF, r + 1);
  }
  return TRUE;
}


bool TRec_sheet::key_notify(int r, KEY k)
{
  const TSheet_field& f = (const TSheet_field&) _mask->field(F_KEYS);

  if (k == K_SPACE)
  {
    TMask& m = f.sheet_mask();

    m.enable(F_KDUP, r > 0);
    if (r == 0) m.reset(F_KDUP);
  }
  else
    if (k == K_INS && f.items() >= 8) return FALSE;
  return TRUE;
}

void TRec_sheet::save()

{
  if (*_rec == *_rec_old ||
      !yesnocancel_box("Devo salvare le modifiche")) return;
  TSystemisamfile f(_rec->num());

  f.update(*_rec);
  *_rec_old = *_rec;
}


void TRec_sheet::edit()

{
  TSheet_field& f1 = (TSheet_field&) _mask->field(F_FIELDS);
  TSheet_field& f2 = (TSheet_field&) _mask->field(F_KEYS);
  
  _mask->set (F_NUM, _dir->num());
  _mask->set (F_DES, _dir->des());
  f1.set_notify(fld_notify);
  f1.sheet_mask().field(FLD_LEN).set_handler(len_handler);
  int nfields = _rec->fields();
  for (int i = 0; i < nfields; i++) f1.row(i) = _rec->fielddef(i);
  f2.set_notify(key_notify);
  int nkeys = _rec->keys();
  for (i = 0; i < nkeys; i++) f2.row(i) = _rec->keydef(i);
  while (TRUE)
  {
    switch (_mask->run())
    {
    case K_SAVE:
    {
      nfields = f1.items();
      _rec->set_fields(nfields);
      for (i = 0; i < nfields; i++)
      {
        TToken_string& s = f1.row(i);
        _rec->update_fielddef(i, s);
      }
      _rec->rehash();
      nkeys = f2.items();
      _rec->set_keys(nkeys);
      for (i = 0; i < nkeys; i++)
      {
        TToken_string& s = f2.row(i);
        _rec->update_keydef(i, s);
      }
      save();
    }
  case K_ESC:
    return;
  case K_ENTER:
    main_app().dispatch_e_menu(M_FILE_PRINT);
    break;
  case K_F6:
  {
    TMask m("ba1100f");
    TFilename nout(_dir->name());

    nout.strip("$%");
    nout.ext("trr");
    m.set(F_NOMEF, nout);  
    if (m.run() == K_ENTER)
    {
      TString80 nf(m.get(F_NOMEF));
      
      if (nf.not_empty())
      {
        ofstream out((const char*) nf);
        
        out << *_rec;
      }
    }
  }
    break;
  case K_F7:
  {
    TMask m("ba1100f");
    TFilename nout(_dir->name());

    nout.strip("$%");
    nout.ext("trr");
    m.set(F_NOMEF, nout);  
    if (m.run() == K_ENTER)
    {
      TString80 nf(m.get(F_NOMEF));
      
      if (nf.not_empty())
      {
        ifstream in((const char*) nf);
        
        in >> *_rec;
        nfields = _rec->fields();
        f1.reset();
        for (i = 0; i < nfields; i++) f1.row(i) = _rec->fielddef(i);
        nkeys = _rec->keys();
        f2.reset();
        for (i = 0; i < nkeys; i++) f2.row(i) = _rec->keydef(i);
      }
    }
  }
    break;
  default: break;
  }
  }
}

