/*      $Id: maskfld.h,v 1.13 1994-11-28 11:01:22 guy Exp $  */
#ifndef __MASKFLD_H
#define __MASKFLD_H

#ifndef __ARRAY_H
#include <array.h>
#endif

#ifndef __REAL_H
#include <real.h>
#endif

#ifndef __SCANNER_H
#include <scanner.h>
#endif

class TMask_field;

class TRelation; // __RELATION_H
class TCursor;
class TFieldref;
class TArray_sheet;  // __SHEET_H

// @T
typedef bool (*CONTROL_HANDLER)(TMask_field& field, KEY key);
// @END

enum CheckType { CHECK_NONE, CHECK_NORMAL, CHECK_REQUIRED };
enum CheckTime { RUNNING_CHECK, STARTING_CHECK, FINAL_CHECK };

// @C
// Classe TMask_field : public TObject
// @END

class TMask_field : public TObject
{
  // @DPRIV
  friend class TMask;

  TMask* _mask;         // The mask the control belongs to

  TString _help;        // Help message
  TFieldref* _field;    // Corresponding field on the file
  TBit_array _keys;     // The keys the field belongs to
  TBit_array _groups;   // The groups the field belongs to

protected:
  // @DPROT
  static int _x, _y;          // Coordinate of the control
  static int _width;          // Size of the control
  static TFixed_string _prompt;// Prompt of the field
  CONTROL_HANDLER _handler;

  int _size;                  // Max length of the string

  WINDOW _win;                // Window of the control (not its parent!)
  WINDOW _promptwin;            // Prompt of the control
  short _dlg;                 // Identifier of the control

  int    _validate_func;      // Number of validation function
  TArray _validate_parms;     // Parameters for validation function
  TArray _message;                                              // Messages to send on modify

  struct TField_Flags
  {
    bool automagic      : 1;
    bool dirty          : 2;    // Modified during run ?
    bool enabled        : 1;    // Is editable
    bool enable_default : 1;
    bool firm           : 1;    // Is the current firm ?
    bool focusdirty     : 1;    // Modified during focus ?
    bool ghost          : 1;
    bool password       : 1;
    bool persistent     : 1;
    bool rightjust      : 1;
    bool roman          : 1;      // Is a Roman number ?
    bool showed         : 1;    // Is visible
    bool show_default   : 1;
    bool uppercase      : 1;
    bool exchange       : 1;    // Value exchange
    bool zerofilled     : 1;

    TField_Flags();
    char update(const char*);
  } _flags;

  void construct(TScanner& scanner, WINDOW parent);
  void construct(short id, const char* prompt, int x, int y, int len,
                 WINDOW parent, const char* flags = "", int width = 0);

  virtual WINDOW win() const { return _win; }

  WINDOW wincreate(WIN_TYPE ct, short dx, short dy,
                   const char* title, WINDOW parent, long flags);
  int create_prompt(WINDOW parent, int width = 0, int heigth = 1);

  long default_flags() const;

  virtual void parse_head(TScanner& scanner);
  virtual bool parse_item(TScanner& scanner);

  virtual void create(WINDOW parent);
  virtual void destroy();
  virtual void highlight() const;

  virtual const char* get_window_data() const;
  virtual void set_window_data(const char* data);
  virtual void set_field_data(const char* data);
  virtual const char* get_field_data() const;
  virtual void exchange(bool show_value, const real& n) {}

  bool do_message(int n);
  
public:
  // @FPUB
  short atodlg(const char* s) const;

  WINDOW parent() const;
  short dlg() const { return _dlg; }
  
  virtual bool ok() const;
  
  bool dirty() const { return _flags.dirty; }
  bool focusdirty() const { return _flags.focusdirty; }
  void set_focusdirty(bool d = TRUE) { _flags.focusdirty = d; }
  void set_dirty(bool d = TRUE);

  virtual const char* class_name() const;
  virtual word class_id() const;
  
  int size() const { return _size; }

  bool roman() const { return _flags.roman; }
  bool automagic() const { return _flags.automagic; }
  bool ghost() const { return _flags.ghost; }
  bool exchangeable() const { return _flags.exchange; }

  virtual bool has_check() const { return FALSE;}
  virtual bool has_query() const { return FALSE;}
  virtual bool has_message() const { return _message.items() > 0; }

  virtual CheckType check_type() const { return CHECK_NONE; }
  bool required() const { return check_type() == CHECK_REQUIRED; }
  virtual bool check(CheckTime = RUNNING_CHECK) { return TRUE;}

  virtual void reset();

  virtual void enable(bool on = TRUE);
  void disable() { enable(FALSE); }
  bool enabled() const { return _flags.enabled; }
  void enable_default();
  bool enabled_default() const { return _flags.enable_default; }

  virtual void show(bool on = TRUE);
  void hide() { show(FALSE); }
  bool showed() const { return _flags.showed; }
  void show_default();

  bool active() const;  // Is visible and enabled?

  void set_handler(CONTROL_HANDLER handler) { _handler = handler; }

  bool is_edit() const;
  bool to_check(KEY k, bool checkrun = FALSE) const;

  virtual bool on_hit();
  virtual bool on_key(KEY key);

  void set(const char* s);
  TString& get() const;
  
  virtual const char* picture_data(const char* data, bool video);

  bool autoload(const TRelation* r = NULL);
  bool autosave(TRelation* r = NULL) const;

  void undo();

  const char* prompt() const;
  void set_prompt(const char* p);

  bool in_key(byte key) const { return _keys[key]; }
  void set_key(byte key) { _keys.set(long(key)); _keys.set(0L);}
  word last_key() const;

  bool in_group(byte group) const { return _groups[group]; }
  void set_group(byte group) { _groups.set(long(group)); _groups.set(0L);}

  const TFieldref* field() const { return _field; }
  
  void set_focus() const;
  void send_key(KEY k, short to);

  // set focus, message-box, set focus  
  bool message_box(const char* fmt, ...) const;
  bool warning_box(const char* fmt, ...) const;
  bool error_box(const char* fmt, ...) const;
  bool yesno_box(const char* fmt, ...) const;
  KEY yesnocancel_box(const char* fmt, ...) const;

  TMask& mask() const { return *_mask; }
  TMask_field(TMask* mask);
  virtual ~TMask_field();
};


// @C
// Classe TEdit_field : public TMask_field
//
// @END

class TEdit_field : public TMask_field
{
  friend class TBrowse;
  friend class TList_sheet;
  friend class TBrowse_sheet;

protected:
  // @DPROT
  TString80 _str;
  TString16 _picture;
  TString _warning;
  CheckType _check;                       // Accettabilita' di valori nulli
  bool _forced;
  bool _check_enabled;                    // Abilitato

  TBrowse* _browse;
  TList_sheet* _sheet;
  WINDOW _buttonwin;

  const TBrowse* get_browse(TScanner& scanner) const;

  virtual word class_id() const;
  virtual void parse_head(TScanner& scanner);
  virtual bool parse_item(TScanner& scanner);

  virtual void create(WINDOW parent);
  virtual void destroy();

  bool validate(KEY k);

  virtual void set_window_data(const char* data);
  virtual void set_field_data(const char* data);
  virtual const char* get_field_data() const;

public:
  // @FPUB
  virtual bool on_hit();
  virtual bool on_key(KEY key);
  virtual bool has_check() const;
  virtual bool has_query() const { return _browse || _sheet;}
  virtual const char* picture_data(const char* data, bool video);
  virtual void show(bool on = TRUE);
  virtual void enable(bool on = TRUE);
  virtual CheckType check_type() const { return _check; }
  void check_type(CheckType c) { _check = c; }

  bool forced() const { return _forced;}
  virtual bool check(CheckTime = RUNNING_CHECK);
  TBrowse* browse() const { return _browse;}
  TList_sheet* sheet() const { return _sheet;}
  void enable_check(bool on = TRUE) ;
  bool check_enabled() const  { return _check_enabled;}

  const char* format(const char* data);
  const char* picture() const { return _picture; }

  TEdit_field(TMask* mask);
  virtual ~TEdit_field();
};


///////////////////////////////////////////////////////////
// TBrowse
///////////////////////////////////////////////////////////

class TBrowse
{
  TEdit_field* _fld;            // The field owning the sheet
  TRelation*   _relation;       // Main relation
  TCursor*     _cursor;         // Cursor on the relation
  TString      _insert;
  TString      _filter;
  long         _rec;
  bool         _secondary;
  bool         _checked;

  TToken_string _head, _items;
  TToken_string _inp_id, _inp_fn;
  TToken_string _out_id, _out_fn;

protected:
  void do_output(CheckTime = RUNNING_CHECK);
  void do_clear();
  bool do_insert();

  TMask_field& field(short n) const;
  TToken_string& create_siblings(TToken_string& siblings);

public:
  int inputs();
  int do_input(bool filter = FALSE); // Serve ai TCursor_sheet

  TBrowse(TEdit_field* f, TRelation* r, int key = 1, const char* filter = "");
  TBrowse(TEdit_field* f, TCursor* c);
  ~TBrowse();

  void parse_join(TScanner& scanner);
  void parse_input(TScanner& scanner);
  void parse_display(TScanner& scanner);
  void parse_output(TScanner& scanner);
  void parse_insert(TScanner& scanner);
  bool parse_copy(const TString& what, const TBrowse& b);

  void set_insert(const char* s) { _insert = s;}
  const TString& get_insert() const { return _insert;}
  const TString& get_filter() const { return _filter;}

  TEdit_field& field() const { return *_fld; }

  bool check(CheckTime = RUNNING_CHECK);
  bool empty_check();
  const TToken_string& head() const { return _head;}
  const TToken_string& items() const { return _items;}
  TCursor* cursor() const { return _cursor;}
  bool checked() const { return _checked;}
  bool secondary() const { return _secondary;}

  KEY run();
};

///////////////////////////////////////////////////////////
// TList_sheet
///////////////////////////////////////////////////////////

class TList_sheet
{
  TEdit_field* _fld;            // The field owning the sheet
  TArray_sheet* _sheet;         // sheet with data;
  int _row;

  TToken_string _inp_id;
  TToken_string _out_id;

protected:
  int do_input();
  void do_output(CheckTime = RUNNING_CHECK);
  bool do_insert();
  TMask_field& field(short id) const;

public:
  TList_sheet(TEdit_field* f, const char* caption, const char* head);
  ~TList_sheet();

  void parse_input(TScanner& scanner);
  void read_item(TScanner& scanner);
  void parse_output(TScanner& scanner);
  TArray_sheet* sheet() { return _sheet; }
  TEdit_field& field() const { return *_fld; }

  bool check(CheckTime = RUNNING_CHECK);

  KEY run();
};

// @C
// class TReal_field : public TEdit_field
// @END

class TReal_field : public TEdit_field
{
  int _decimals;

protected:
  // @FPROT
  virtual word class_id() const;

  virtual const char* get_window_data() const;
  virtual void set_window_data(const char* data);
  virtual void exchange(bool show_value, const real& n);

  virtual void create(WINDOW parent);
  virtual void parse_head(TScanner& scanner);
  virtual bool on_key(KEY key);

public:
  // @FPUB
  void set_decimals(int d);                         // Set precision & picture
  int decimals() const { return _decimals; }        // Get precision
  
  TReal_field(TMask* mask);
};


// @C
// class TDate_field : public TEdit_field
//@END

class TDate_field : public TEdit_field
{
protected:
  // @FPROT
  virtual word class_id() const;
  virtual void create(WINDOW parent);
  virtual bool on_key(KEY key);
  virtual const char* get_window_data() const;
  virtual void set_window_data(const char* data);

public:
  // @FPUB
  void parse_head(TScanner& scanner);
  TDate_field(TMask* mask);
};


// @C
// class TBoolean_field : public TMask_field
// @END

class TBoolean_field : public TMask_field
{
protected:
  // @DPROT
  bool _on;

  virtual word class_id() const;

  virtual void create(WINDOW parent);
  virtual const char* get_window_data() const;
  virtual void set_window_data(const char* data);
  virtual void set_field_data(const char* data = NULL);
  virtual const char* get_field_data() const;
  virtual bool parse_item(TScanner& scanner);
  virtual void enable(bool on);
  virtual bool on_hit();
  virtual bool on_key(KEY key);

public:
  // @FPUB
  TBoolean_field(TMask* mask);
};


// @C
// class TList_field : public TMask_field
// @END

class TList_field : public TMask_field
{
  // @FPRIV
  void add_list();

protected:
  // @FPROT
  TToken_string _values;
  TToken_string _codes;
  TString80 _str;

  virtual word class_id() const;

  virtual void set_window_data(const char* data);
  virtual const char* get_window_data() const;
  virtual void set_field_data(const char* data = NULL);
  virtual const char* get_field_data() const;
  
  virtual void create(WINDOW parent);

  virtual void current(int n);
  virtual int current() const;

  int str2curr(const char* data);
  virtual bool on_hit();
  virtual bool on_key(KEY key);
  virtual void read_item(TScanner& scanner);

  virtual void parse_head(TScanner& scanner);
  virtual bool parse_item(TScanner& scanner);

public:
  // @FPUB
  TList_field(TMask* mask);
  virtual void replace_items(const char* codes, const char* values);
  virtual void add_item(const char* code_value);
  virtual void delete_item(const char* code);
  int items() const;
};


// @C
// class TRadio_field : public TList_field
// @END

class TRadio_field : public TList_field
{
  enum { MAX_RADIO = 8 };

  // @FPRIV
  int             _nitems;
  int             _active_item;
  WINDOW          _radio_ctl_win[MAX_RADIO];

protected:
  // @FPROT
  virtual word class_id() const;
  virtual void create(WINDOW parent);
  virtual void destroy();
  virtual void enable(bool on);
  virtual void show(bool on);

  virtual void current(int n);
  virtual int current() const;
  WINDOW win() const { return _radio_ctl_win[_active_item]; }

public:
  // @FPUB
  TRadio_field(TMask* mask);

  void check_radiobutton(WINDOW checked);
  bool move_focus(int d);
};



// @C
// class TButton_field : public TMask_field
// @END

class TButton_field : public TMask_field
{        
  KEY _virtual_key, _exit_key;
  
protected:
  // @FPROT
  virtual word class_id() const;
  virtual void create(WINDOW parent);

  void parse_head(TScanner& scanner);
  bool parse_item(TScanner& scanner);
  virtual void enable(bool);
  virtual void show(bool);
  virtual bool on_key(KEY key);

public:
  // @FPUB
  TButton_field(TMask* mask);
  KEY virtual_key() const { return _virtual_key; }
  KEY exit_key() const { return _exit_key; }
};


// @C
// class TGroup_field : public TMask_field
// @END

class TGroup_field : public TMask_field
{
protected:
  // @DPROT
  virtual void parse_head(TScanner& scanner);
  virtual void create(WINDOW parent);

public:
  // @FPUB
  TGroup_field(TMask* mask);
};

#endif // __MASKFLD_H
