#include <automask.h>

bool TAutomask::error_box(const char* fmt, ...)
{ 
  TString message(1024);
  char* msg = message.get_buffer();
  va_list argptr;
  va_start(argptr, fmt);
  int len = vsprintf(msg, fmt, argptr);
  CHECKD(len <= message.size(), "Error message too long: ", len);
  va_end(argptr);

  if (is_sheetmask() && !is_running())
    get_sheet()->error_box(msg);
  else
    post_error_message(msg, 3);
  return false;
}

TField_event TAutomask::key2event(TMask_field& f, KEY key) const
{
  const TMask& wm = f.mask();
  TField_event fe = fe_null;
  switch (key)
  {
  case K_TAB:
    if (f.is_edit())
    {
      if (wm.get_sheet())
      {
        if (wm.is_running())
        {
          if (f.focusdirty())
            fe = fe_modify;
        }
        else
        {
          fe = f.focusdirty() ? fe_modify : fe_init;
        }
      }
      else
      {
        if (wm.is_running())
        {
          if (f.focusdirty())
            fe = fe_modify;
        }
        else
          fe = fe_init;
      }
    }
    break;
  case K_SPACE:
    if (f.is_edit())
    {
      if (wm.is_running())
        fe = fe_edit;
    }
    else
    {
      if (f.is_kind_of(CLASS_BUTTON_FIELD) || f.is_kind_of(CLASS_BUTTON_TOOL))
        fe = fe_button; else
      if (f.is_kind_of(CLASS_TREE_FIELD))
        fe = wm.is_running() ? fe_modify : fe_init;
      else
        fe = f.focusdirty() ? fe_modify : fe_init;
    }  
    break;
  case K_CTRL+K_SPACE:
    if (f.is_kind_of(CLASS_TREE_FIELD))
      fe = fe_button;
    break;
  case K_ENTER:
    fe = fe_close;
    break;  
  case K_F8:
    fe = fe_magic;
    break;
  case K_F9:
    if (f.is_edit())
      fe = fe_button;
    break;
  case K_F11:
    fe = fe_info;
    break;
  default:        
    fe = fe_null;
    break;
  }
  return fe;
}

bool TAutomask::universal_handler(TMask_field& f, KEY key)
{
  TOperable_field& of = (TOperable_field&)f;
  TAutomask& am = (TAutomask&)of.mask();
  const TField_event fe = am.key2event(of, key);
  return fe == fe_null ? true : am.on_field_event(of, fe, 0);
}

bool TAutomask::insheet_universal_handler(TMask_field& f, KEY key)
{
  TMask& m = f.mask();
  TSheet_field& s = *m.get_sheet();
  TAutomask& am = (TAutomask&)s.mask();
  
  TOperable_field& of = (TOperable_field&)f;
  TField_event fe = am.key2event(of, key);
  return fe == fe_null ? true : am.on_field_event(of, fe, m.number());
}


bool TAutomask::universal_notifier(TSheet_field& s, int row, KEY key)
{
  TField_event fe = fe_null;
  switch (key)
  {       
  case K_INS:
    fe = se_query_add;
    break;
  case K_CTRL+K_INS:
    fe = se_notify_add;
    break;
  case K_DEL:
    fe = se_query_del;
    break;
  case K_CTRL+K_DEL:
    fe = se_notify_del;
    break;
  case K_TAB:  
    fe = se_enter;
    break;  
  case K_CTRL+K_TAB:  
    fe = se_leave;
    break;  
  case K_SPACE:
    fe = se_query_modify;
    break;  
  case K_ENTER:
    fe = se_notify_modify;
    break;  
  default:
    break;
  }
  
  TAutomask& wm = (TAutomask&)s.mask();
  return fe == fe_null ? true : wm.on_field_event(s, fe, row);
}

void TAutomask::set_handlers()
{
  for (int i = fields()-1; i >= 0; i--)
  {
    TMask_field& f = fld(i);
    if (f.is_operable())
    {
      f.set_handler(universal_handler);
      if (f.is_sheet())
      {
        ((TSheet_field&)f).set_notify(universal_notifier);

        TMask& m = ((TSheet_field&)f).sheet_mask();
        for (int j = m.fields()-1; j >= 0; j--)
        {
          TMask_field& g = m.fld(j);
          if (g.is_operable())
            g.set_handler(insheet_universal_handler);
        }
      }
    }
  }  
}


TAutomask::TAutomask(const char* name, int num)
         : TMask(name, num)
{
  set_handlers();
}

TAutomask::TAutomask(const char* title, int pages, int cols, int rows, int xpos, int ypos)
         : TMask(title, pages, cols, rows, xpos, ypos)
{
}