2111 lines
		
	
	
		
			55 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			2111 lines
		
	
	
		
			55 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
#if XVT_OS == XVT_OS_WIN
 | 
						|
#define STRICT
 | 
						|
#define XVT_INCL_NATIVE
 | 
						|
#endif
 | 
						|
 | 
						|
#include <colors.h>
 | 
						|
#include <config.h>
 | 
						|
#include <controls.h>
 | 
						|
#include <mask.h>
 | 
						|
#include <urldefid.h>
 | 
						|
 | 
						|
COLOR MASK_BACK_COLOR = COLOR_DKCYAN;
 | 
						|
COLOR MASK_LIGHT_COLOR = COLOR_CYAN;
 | 
						|
COLOR MASK_DARK_COLOR = COLOR_GRAY;
 | 
						|
COLOR BTN_BACK_COLOR = COLOR_LTGRAY;
 | 
						|
COLOR BTN_LIGHT_COLOR = COLOR_WHITE;
 | 
						|
COLOR BTN_DARK_COLOR = COLOR_GRAY;
 | 
						|
COLOR TOOL_BACK_COLOR = COLOR_GRAY;
 | 
						|
COLOR NORMAL_COLOR = COLOR_BLACK;
 | 
						|
COLOR NORMAL_BACK_COLOR = COLOR_LTGRAY;
 | 
						|
COLOR DISABLED_COLOR = COLOR_GRAY;
 | 
						|
COLOR DISABLED_BACK_COLOR = MASK_BACK_COLOR;
 | 
						|
COLOR FOCUS_COLOR = NORMAL_COLOR;
 | 
						|
COLOR FOCUS_BACK_COLOR = COLOR_CYAN;
 | 
						|
BOOLEAN CAMPI_SCAVATI = FALSE;
 | 
						|
BOOLEAN AUTOSELECT = FALSE;
 | 
						|
 | 
						|
#ifndef STX_DATA
 | 
						|
// Very deep hacking
 | 
						|
typedef struct _stx_data
 | 
						|
{
 | 
						|
  int cid;
 | 
						|
  WINDOW win;
 | 
						|
  RCT rct;
 | 
						|
  unsigned long attrib;
 | 
						|
} STX_DATA;
 | 
						|
 | 
						|
extern "C" 
 | 
						|
{
 | 
						|
#include <xiutils.h>
 | 
						|
}
 | 
						|
 | 
						|
#endif
 | 
						|
 | 
						|
HIDDEN bool _button_blocked = FALSE;
 | 
						|
HIDDEN int  _last_mouse_button = 0;
 | 
						|
 | 
						|
short get_focus_id(WINDOW win)
 | 
						|
{
 | 
						|
  XI_OBJ * itf = xi_get_itf(win);
 | 
						|
  XI_OBJ * obj = xi_get_focus(itf);
 | 
						|
 | 
						|
  if (obj == NULL || obj->type == XIT_ITF)
 | 
						|
    return -1;
 | 
						|
  if (obj->type == XIT_CELL || (obj->type == XIT_BTN && obj->parent != obj->itf))
 | 
						|
    obj = obj->parent;
 | 
						|
  
 | 
						|
  return obj->cid;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
// #define CAMPI_SCAVATI FALSE
 | 
						|
HIDDEN int X_FU_MULTIPLE = 0;
 | 
						|
HIDDEN int Y_FU_MULTIPLE = 0;
 | 
						|
HIDDEN const int ITF_CID = 30000;
 | 
						|
 | 
						|
KEY TControl::xiev_to_key(const XI_EVENT* xiev)
 | 
						|
{
 | 
						|
  KEY key = xiev->v.chr.ch;
 | 
						|
  if (key < K_INS || key > K_HELP)
 | 
						|
  {
 | 
						|
    if (xiev->v.chr.shift && (key < ' ' || key >= K_UP)) key += K_SHIFT;
 | 
						|
    if (xiev->v.chr.control && key >=  ' ') key += K_CTRL;
 | 
						|
  }
 | 
						|
  return key;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
// @doc INTERNAL
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// TPicture_array
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
class TPicture_array : public TArray
 | 
						|
{
 | 
						|
public:
 | 
						|
  TImage& add(short id);
 | 
						|
 | 
						|
  const TImage& image(short id) const { return (const TImage&)operator[](id); }
 | 
						|
  bool exist(short id) const { return objptr(id) != NULL; }
 | 
						|
  void reload();
 | 
						|
 | 
						|
  TPicture_array() : TArray(128) {}
 | 
						|
  virtual ~TPicture_array() {}
 | 
						|
};
 | 
						|
 | 
						|
TImage& TPicture_array::add(short id)
 | 
						|
{
 | 
						|
  TImage* i = (TImage*)objptr(id);
 | 
						|
 | 
						|
  if (i == NULL)
 | 
						|
  {
 | 
						|
    i = new TImage(id);
 | 
						|
    i->convert_transparent_color(BTN_BACK_COLOR);
 | 
						|
    TArray::add(i, id);
 | 
						|
  }
 | 
						|
 | 
						|
  return *i;
 | 
						|
}   
 | 
						|
 | 
						|
void TPicture_array::reload()
 | 
						|
{    
 | 
						|
  for (int id = last(); id >= 0; id--)
 | 
						|
  {
 | 
						|
    TImage* i = (TImage*)objptr(id);
 | 
						|
    if (i)
 | 
						|
    {
 | 
						|
      i->load(id);
 | 
						|
      i->convert_transparent_color(BTN_BACK_COLOR);
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// Utility functions
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
HIDDEN TPicture_array* _picture = NULL;
 | 
						|
HIDDEN XVT_FNTID DEF_FONT = NULL;
 | 
						|
HIDDEN XVT_FNTID FAT_FONT = NULL;
 | 
						|
 | 
						|
XVT_FNTID xvt_default_font(bool bold)
 | 
						|
{
 | 
						|
  if (DEF_FONT == NULL)
 | 
						|
  {
 | 
						|
    DEF_FONT = xvt_dwin_get_font(TASK_WIN);
 | 
						|
 | 
						|
    TConfig font(CONFIG_USER, "Font");
 | 
						|
    TString font_ser_desc(font.get("FontDesc"));
 | 
						|
    if (font_ser_desc.empty())
 | 
						|
      font_ser_desc << "01\\Courier\\0\\10\\WIN01/-13/0/0/0/400/0/0/0/0/1/2/1/49/Courier";
 | 
						|
    xvt_font_deserialize(DEF_FONT, (char *)(const char *) font_ser_desc);
 | 
						|
    xvt_font_map_using_default(DEF_FONT);
 | 
						|
    CHECK(xvt_font_is_mapped(DEF_FONT), "Can't map native font");
 | 
						|
 | 
						|
    xvt_dwin_set_font(TASK_WIN, DEF_FONT);
 | 
						|
    xvt_menu_set_font_sel(TASK_WIN, DEF_FONT);
 | 
						|
 | 
						|
    FAT_FONT = xvt_font_create();
 | 
						|
    xvt_font_copy(FAT_FONT, DEF_FONT, XVT_FA_ALL);
 | 
						|
    xvt_font_set_style(FAT_FONT, XVT_FS_BOLD);
 | 
						|
    xvt_font_map_using_default(FAT_FONT);
 | 
						|
    CHECK(xvt_font_is_mapped(FAT_FONT), "Can't map native font");
 | 
						|
    // Get true text size
 | 
						|
#if XVT_OS == XVT_OS_WIN
 | 
						|
    TEXTMETRIC tm;
 | 
						|
    HDC hdc = (HDC)xvt_vobj_get_attr(TASK_WIN, ATTR_NATIVE_GRAPHIC_CONTEXT);
 | 
						|
    GetTextMetrics(hdc, &tm);
 | 
						|
    
 | 
						|
    RCT pc; xvt_vobj_get_client_rect(TASK_WIN, &pc);
 | 
						|
 | 
						|
    ROWY = (pc.bottom - pc.top) / 23;
 | 
						|
    const int COLX = (pc.right - pc.left) / 80;
 | 
						|
    
 | 
						|
    CHARX = tm.tmAveCharWidth+1;
 | 
						|
    if (CHARX > COLX) 
 | 
						|
      CHARX = COLX;
 | 
						|
 | 
						|
    CHARY = tm.tmHeight;
 | 
						|
    BASEY = tm.tmAscent;
 | 
						|
    if (CHARY > ROWY-2) 
 | 
						|
      CHARY = ROWY-2;
 | 
						|
#endif
 | 
						|
  }
 | 
						|
 | 
						|
  return bold ? FAT_FONT : DEF_FONT;
 | 
						|
}
 | 
						|
 | 
						|
XVT_FNTID xvt_load_default_font()
 | 
						|
{
 | 
						|
  if (DEF_FONT)
 | 
						|
  {
 | 
						|
    xvt_font_destroy(DEF_FONT);
 | 
						|
    DEF_FONT = NULL;
 | 
						|
  }
 | 
						|
  if (FAT_FONT)
 | 
						|
  {
 | 
						|
    xvt_font_destroy(FAT_FONT);
 | 
						|
    FAT_FONT = NULL;
 | 
						|
  }           
 | 
						|
  
 | 
						|
  X_FU_MULTIPLE = Y_FU_MULTIPLE = 0;
 | 
						|
  
 | 
						|
  return xvt_default_font(FALSE);
 | 
						|
}
 | 
						|
 | 
						|
static byte event_map[XIE_POST_NAVIGATION+1];
 | 
						|
enum event_action { a_ignore, a_xvt, a_xvt_post, a_obj, a_child, a_update, a_select, a_post, a_debug };
 | 
						|
 | 
						|
HIDDEN void set_default_palette(WINDOW win)
 | 
						|
{
 | 
						|
  COLOR colori[12] = { MASK_BACK_COLOR, MASK_LIGHT_COLOR, MASK_DARK_COLOR,
 | 
						|
                     NORMAL_COLOR, NORMAL_BACK_COLOR,
 | 
						|
                     FOCUS_COLOR, FOCUS_BACK_COLOR,
 | 
						|
                     DISABLED_COLOR, DISABLED_BACK_COLOR,
 | 
						|
                     BTN_BACK_COLOR, BTN_LIGHT_COLOR, BTN_DARK_COLOR };
 | 
						|
                     
 | 
						|
  XVT_PALETTE wp = xvt_vobj_get_palet(win);                   
 | 
						|
  if (wp != NULL)
 | 
						|
  {
 | 
						|
    XVT_PALETTE up = xvt_palet_create(XVT_PALETTE_USER, NULL);
 | 
						|
    if (up != NULL)
 | 
						|
    {
 | 
						|
      xvt_palet_set_tolerance(up, xvt_palet_get_tolerance(wp));
 | 
						|
      
 | 
						|
      const int MAXCOL = 256;
 | 
						|
      COLOR colors[MAXCOL];
 | 
						|
      const int num = xvt_palet_get_colors(wp, colors, MAXCOL);
 | 
						|
      xvt_palet_add_colors(up, colors, num);  
 | 
						|
      const int add = xvt_palet_add_colors(up, colori, 12);   
 | 
						|
      if (add > 0)
 | 
						|
      {
 | 
						|
        xvt_vobj_set_palet(win, up);
 | 
						|
        xvt_palet_destroy(wp);
 | 
						|
      }     
 | 
						|
      else
 | 
						|
        xvt_palet_destroy(up);
 | 
						|
    }    
 | 
						|
  }  
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
// @func Permette di cambiare i colori attivi del programma
 | 
						|
void customize_colors()
 | 
						|
 | 
						|
  // @comm Legge dal file di configurazione i colori scelti dall'utente e
 | 
						|
  //       ne setta le variabili in modo da poter personalizzare i colori
 | 
						|
  //
 | 
						|
  // @xref <c TConfig>
 | 
						|
  
 | 
						|
{    
 | 
						|
  TConfig colors(CONFIG_USER, "Colors");
 | 
						|
  
 | 
						|
  MASK_BACK_COLOR = colors.get_color("MaskBack", NULL, -1, MASK_BACK_COLOR);
 | 
						|
  MASK_LIGHT_COLOR = colors.get_color("MaskLight", NULL, -1, MASK_LIGHT_COLOR);
 | 
						|
  MASK_DARK_COLOR = colors.get_color("MaskDark", NULL, -1, MASK_DARK_COLOR);
 | 
						|
  NORMAL_COLOR = colors.get_color("Normal", NULL, -1, NORMAL_COLOR);
 | 
						|
  NORMAL_BACK_COLOR = colors.get_color("NormalBack", NULL, -1, NORMAL_BACK_COLOR);
 | 
						|
  DISABLED_COLOR = colors.get_color("Disabled", NULL, -1, DISABLED_COLOR);
 | 
						|
  DISABLED_BACK_COLOR = colors.get_color("DisabledBack", NULL, -1, DISABLED_BACK_COLOR);
 | 
						|
  FOCUS_COLOR = colors.get_color("Focus", NULL, -1, FOCUS_COLOR);
 | 
						|
  FOCUS_BACK_COLOR = colors.get_color("FocusBack", NULL, -1, FOCUS_BACK_COLOR);
 | 
						|
  TOOL_BACK_COLOR = colors.get_color("ToolBack", NULL, -1, MASK_DARK_COLOR);
 | 
						|
  CAMPI_SCAVATI = colors.get_bool("Campi3D", NULL, -1, (bool)CAMPI_SCAVATI);
 | 
						|
  AUTOSELECT = colors.get_bool("AutoSelect", NULL, -1, (bool)AUTOSELECT);
 | 
						|
  
 | 
						|
  xi_set_pref(XI_PREF_NATIVE_CTRLS, FALSE);
 | 
						|
  xi_set_pref(XI_PREF_3D_LOOK,      TRUE);
 | 
						|
 | 
						|
  xi_set_pref(XI_PREF_COLOR_LIGHT,    MASK_LIGHT_COLOR);
 | 
						|
  xi_set_pref(XI_PREF_COLOR_CTRL,     MASK_BACK_COLOR);
 | 
						|
  xi_set_pref(XI_PREF_COLOR_DARK,     MASK_DARK_COLOR);
 | 
						|
  xi_set_pref(XI_PREF_COLOR_DISABLED, DISABLED_COLOR);
 | 
						|
 | 
						|
  BTN_BACK_COLOR = colors.get_color("ButtonBack", NULL, -1, BTN_BACK_COLOR);
 | 
						|
  aga_set_pref(AGA_PREF_BTN_COLOR_LIGHT,    BTN_LIGHT_COLOR);
 | 
						|
 | 
						|
  BTN_LIGHT_COLOR = colors.get_color("ButtonLight", NULL, -1, BTN_LIGHT_COLOR);
 | 
						|
  aga_set_pref(AGA_PREF_BTN_COLOR_CTRL,     BTN_BACK_COLOR);
 | 
						|
 | 
						|
  BTN_DARK_COLOR = colors.get_color("ButtonDark", NULL, -1, BTN_DARK_COLOR);
 | 
						|
  aga_set_pref(AGA_PREF_BTN_COLOR_DARK, BTN_DARK_COLOR);
 | 
						|
  
 | 
						|
  set_default_palette(TASK_WIN);
 | 
						|
  
 | 
						|
  if (_picture)
 | 
						|
    _picture->reload();
 | 
						|
}
 | 
						|
 | 
						|
void init_controls()
 | 
						|
{
 | 
						|
  xi_set_font_id(xvt_load_default_font());
 | 
						|
 | 
						|
  xi_set_pref(XI_PREF_CARET_WIDTH,  2);
 | 
						|
 | 
						|
  xi_init();
 | 
						|
 | 
						|
  event_map[XIE_CHAR_FIELD]     = a_obj;
 | 
						|
  event_map[XIE_DBL_FIELD]      = a_obj;
 | 
						|
  event_map[XIE_CHG_FIELD]      = a_obj;
 | 
						|
  event_map[XIE_OFF_FIELD]      = a_obj;
 | 
						|
  event_map[XIE_ON_FIELD]       = a_obj;
 | 
						|
  event_map[XIE_OFF_GROUP]      = a_ignore;
 | 
						|
  event_map[XIE_ON_GROUP]       = a_ignore;
 | 
						|
  event_map[XIE_OFF_FORM]       = a_ignore;
 | 
						|
  event_map[XIE_ON_FORM]        = a_ignore;
 | 
						|
  event_map[XIE_VIR_PAN]        = a_ignore;
 | 
						|
  event_map[XIE_XVT_EVENT]      = a_xvt;
 | 
						|
  event_map[XIE_XVT_POST_EVENT] = a_xvt_post;
 | 
						|
  event_map[XIE_INIT]           = a_ignore;
 | 
						|
  event_map[XIE_BUTTON]         = a_obj;
 | 
						|
  event_map[XIE_CHAR_CELL]      = a_child;
 | 
						|
  event_map[XIE_CLEANUP]        = a_ignore;
 | 
						|
  event_map[XIE_CLOSE]          = a_ignore;
 | 
						|
  event_map[XIE_COMMAND]        = a_ignore;
 | 
						|
  event_map[XIE_DBL_CELL]       = a_child;
 | 
						|
  event_map[XIE_GET_FIRST]      = a_obj;
 | 
						|
  event_map[XIE_GET_LAST]       = a_obj;
 | 
						|
  event_map[XIE_GET_NEXT]       = a_obj;
 | 
						|
  event_map[XIE_GET_PERCENT]    = a_obj;
 | 
						|
  event_map[XIE_GET_PREV]       = a_obj;
 | 
						|
  event_map[XIE_CELL_REQUEST]   = a_obj;
 | 
						|
  event_map[XIE_CHG_CELL]       = a_child;
 | 
						|
  event_map[XIE_OFF_CELL]       = a_child;
 | 
						|
  event_map[XIE_ON_CELL]        = a_child;
 | 
						|
  event_map[XIE_OFF_ROW]        = a_child;
 | 
						|
  event_map[XIE_ON_ROW]         = a_child;
 | 
						|
  event_map[XIE_OFF_COLUMN]     = a_ignore;
 | 
						|
  event_map[XIE_ON_COLUMN]      = a_ignore;
 | 
						|
  event_map[XIE_OFF_LIST]       = a_obj;
 | 
						|
  event_map[XIE_ON_LIST]        = a_obj;
 | 
						|
  event_map[XIE_REC_ALLOCATE]   = a_ignore;
 | 
						|
  event_map[XIE_REC_FREE]       = a_ignore;
 | 
						|
  event_map[XIE_ROW_SIZE]       = a_ignore;
 | 
						|
  event_map[XIE_SELECT]         = a_select;
 | 
						|
  event_map[XIE_UPDATE]         = a_update;
 | 
						|
  event_map[XIE_COL_DELETE]     = a_ignore;
 | 
						|
  event_map[XIE_COL_MOVE]       = a_obj;
 | 
						|
  event_map[XIE_COL_SIZE]       = a_obj;
 | 
						|
  event_map[XIE_POST_NAVIGATION]= a_post;
 | 
						|
 | 
						|
  if (_picture == NULL)
 | 
						|
    _picture = new TPicture_array;
 | 
						|
}
 | 
						|
 | 
						|
void free_controls()
 | 
						|
{
 | 
						|
  if (_picture)
 | 
						|
  {
 | 
						|
    delete _picture;
 | 
						|
    _picture = NULL;
 | 
						|
  }
 | 
						|
  if (DEF_FONT)
 | 
						|
  {
 | 
						|
    xvt_font_destroy(DEF_FONT);
 | 
						|
    DEF_FONT = NULL;
 | 
						|
  }
 | 
						|
  if (FAT_FONT)
 | 
						|
  {
 | 
						|
    xvt_font_destroy(FAT_FONT);
 | 
						|
    FAT_FONT = NULL;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// Interface creation
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
HIDDEN void xi_event_handler(XI_OBJ *itf, XI_EVENT *xiev);
 | 
						|
 | 
						|
#define MASK_RECT_ID -883
 | 
						|
 | 
						|
WINDOW create_interface(WINDOW parent, short x, short y, short dx, short dy,
 | 
						|
                        const char* caption, TWindow* msk, bool tag)
 | 
						|
{
 | 
						|
  if (parent == NULL_WIN)
 | 
						|
    parent = TASK_WIN;
 | 
						|
 | 
						|
  short left   =  x * CHARX;
 | 
						|
  short top    =  y * ROWY;
 | 
						|
  short width  = dx * CHARX;
 | 
						|
  short height = dy * ROWY;
 | 
						|
 | 
						|
  if (x <= 0 || y <= 0 || dx <= 0 || dy <= 0)
 | 
						|
  {
 | 
						|
    RCT max; xvt_vobj_get_client_rect(parent, &max);
 | 
						|
    if (parent == TASK_WIN)
 | 
						|
      max.bottom -= 26;              // Non contare la status bar
 | 
						|
 | 
						|
    if (dy <= 0)
 | 
						|
      height = max.bottom - top + dy * ROWY;
 | 
						|
 | 
						|
    if (dx <= 0)
 | 
						|
    {
 | 
						|
      width = max.right - left + dx * CHARX;
 | 
						|
      if (!tag && dx == 0 && y > 0)           // Aggiusta toolbar
 | 
						|
        top++;
 | 
						|
    }
 | 
						|
 | 
						|
    if (x < 0) left = (max.right - width) >> 1;
 | 
						|
    if (y < 0) top = (max.bottom - height) >> 1;
 | 
						|
  }
 | 
						|
  RCT r; xvt_rect_set(&r, left, top, left+width, top+height);
 | 
						|
 | 
						|
  const WIN_TYPE wt = (dx == 0) ? W_PLAIN : W_DOC;
 | 
						|
  long wsf = WSF_INVISIBLE | WSF_NO_MENUBAR;
 | 
						|
 | 
						|
  WINDOW win = xvt_win_create(wt, &r, (char*)caption, NULL, parent, wsf,
 | 
						|
                              EM_ALL, (EVENT_HANDLER)xi_event, (long)msk);
 | 
						|
  CHECK(win, "Can't create an XVT window for an interface");
 | 
						|
  set_default_palette(win);
 | 
						|
 | 
						|
  XI_OBJ_DEF* def = xi_create_itf_def(ITF_CID, xi_event_handler, &r, (char*)caption, (long)msk);
 | 
						|
  CHECK(def, "Can't define an interface");
 | 
						|
 | 
						|
  def->v.itf->automatic_back_color = FALSE;
 | 
						|
  def->v.itf->back_color = MASK_BACK_COLOR;
 | 
						|
  def->v.itf->font_id = xvt_default_font(FALSE);
 | 
						|
  def->v.itf->tab_on_enter = TRUE;
 | 
						|
  def->v.itf->win = win;
 | 
						|
 | 
						|
  XI_OBJ* itf = xi_create(NULL, def);
 | 
						|
  CHECK(itf, "Can't create an interface");
 | 
						|
 | 
						|
  xi_dequeue();
 | 
						|
  xi_tree_free(def);
 | 
						|
 | 
						|
  if (Y_FU_MULTIPLE == 0)
 | 
						|
  {
 | 
						|
    RCT max; xvt_vobj_get_client_rect(TASK_WIN, &max);
 | 
						|
    xi_pu_to_fu(itf, (PNT*)&max, 2);
 | 
						|
    X_FU_MULTIPLE = max.right  / 80;
 | 
						|
    Y_FU_MULTIPLE = max.bottom / 25;
 | 
						|
  }
 | 
						|
 | 
						|
  if (dx > 0)
 | 
						|
  {
 | 
						|
    xi_pu_to_fu(itf, (PNT*)&r, 2);
 | 
						|
    r.right  = r.left + (dx+1) * XI_FU_MULTIPLE;
 | 
						|
    r.bottom = r.top  + (dy+1) * Y_FU_MULTIPLE;
 | 
						|
    xi_fu_to_pu(itf, (PNT*)&r, 2);
 | 
						|
    xvt_vobj_move(win, &r);
 | 
						|
  }
 | 
						|
 | 
						|
  if (tag)
 | 
						|
  {
 | 
						|
    XI_RCT rct; xi_get_xi_rct(itf, &rct);
 | 
						|
    rct.top += Y_FU_MULTIPLE;                // Lascia lo spazio per i Bottoni di cambio pagina
 | 
						|
 | 
						|
    def = xi_add_rect_def(NULL, MASK_RECT_ID, &rct, XI_ATR_VISIBLE, 0, 0);
 | 
						|
    XI_OBJ* obj = xi_create(itf, def);
 | 
						|
    CHECK(obj, "Can't create page rectangle");
 | 
						|
 | 
						|
    // Fa coincidere esattamente il rettangolo con la finestra che lo contiene
 | 
						|
    RCT& rect = obj->v.rect->rct;
 | 
						|
    const int oldy = rect.top;
 | 
						|
    xvt_vobj_get_client_rect(win, &rect);
 | 
						|
    rect.top = oldy;
 | 
						|
 | 
						|
    xi_dequeue();
 | 
						|
    xi_tree_free(def);
 | 
						|
  }    
 | 
						|
  
 | 
						|
  return win;
 | 
						|
}
 | 
						|
 | 
						|
void attach_interface(WINDOW win, COLOR back)
 | 
						|
{
 | 
						|
  xvt_win_set_handler(win, (EVENT_HANDLER)xi_event);
 | 
						|
  RCT rc; xvt_vobj_get_client_rect(win, &rc);
 | 
						|
  WINDOW wp = xvt_vobj_get_parent(win);
 | 
						|
  xvt_vobj_translate_points(win, wp, (PNT*)&rc, 2);
 | 
						|
  char caption[80]; xvt_vobj_get_title(win, caption, 80);
 | 
						|
  TWindow* parent = (TWindow*)xvt_vobj_get_data(win);
 | 
						|
  XI_OBJ_DEF* def = xi_create_itf_def(ITF_CID, xi_event_handler, &rc, caption, (long)parent);
 | 
						|
  CHECK(def, "Can't define an interface");
 | 
						|
 | 
						|
  def->v.itf->automatic_back_color = FALSE;
 | 
						|
  def->v.itf->back_color = back;
 | 
						|
  def->v.itf->tab_on_enter = TRUE;
 | 
						|
  def->v.itf->win = win;
 | 
						|
 | 
						|
  XI_OBJ* itf = xi_create(NULL, def);
 | 
						|
  CHECK(itf, "Can't create an interface");
 | 
						|
 | 
						|
  xi_dequeue();
 | 
						|
  xi_tree_free(def);
 | 
						|
}
 | 
						|
 | 
						|
HIDDEN void xi_event_handler(XI_OBJ* itf, XI_EVENT* xiev)
 | 
						|
{
 | 
						|
  static bool notify_xvt = TRUE;
 | 
						|
 | 
						|
  TControl* ctl = NULL;
 | 
						|
 | 
						|
  switch (event_map[xiev->type])
 | 
						|
  {
 | 
						|
  case a_obj:
 | 
						|
    ctl = (TControl*)xi_get_app_data(xiev->v.xi_obj);
 | 
						|
    break;
 | 
						|
  case a_child:
 | 
						|
    ctl = (TControl*)xi_get_app_data(xiev->v.xi_obj->parent);
 | 
						|
    break;
 | 
						|
  case a_update:
 | 
						|
    {
 | 
						|
      int num;
 | 
						|
      XI_OBJ** button = xi_get_member_list(itf, &num);
 | 
						|
      for (int i = num-1; i >= 0; i--)
 | 
						|
      {
 | 
						|
        XI_OBJ* b = button[i];
 | 
						|
        if (b->type == XIT_BTN && b->v.btn->drawable)
 | 
						|
        {
 | 
						|
          if (xvt_rect_intersect(NULL, &b->v.btn->rct, &xiev->v.xvte.v.update.rct))
 | 
						|
          {
 | 
						|
            TPushbutton_control* p = (TPushbutton_control*)b->app_data;
 | 
						|
            p->update();
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
    break;
 | 
						|
  case a_select:
 | 
						|
    if (xiev->v.xi_obj->type == XIT_LIST)
 | 
						|
      ctl = (TControl*)xi_get_app_data(xiev->v.xi_obj);
 | 
						|
    else
 | 
						|
      ctl = (TControl*)xi_get_app_data(xiev->v.xi_obj->parent);
 | 
						|
    break;                                      
 | 
						|
  case a_xvt:
 | 
						|
    switch (xiev->v.xvte.type)
 | 
						|
    {
 | 
						|
    case E_MOUSE_DOWN:
 | 
						|
      _last_mouse_button = xiev->v.xvte.v.mouse.button;
 | 
						|
      break;
 | 
						|
    case E_CHAR:
 | 
						|
      {
 | 
						|
        XI_OBJ* fo = xi_get_focus(itf);
 | 
						|
        if (fo != NULL && fo->type == XIT_CELL)
 | 
						|
          ctl = (TControl*)xi_get_app_data(fo->parent);
 | 
						|
      }
 | 
						|
      break;
 | 
						|
    default:
 | 
						|
      break;  
 | 
						|
    }  
 | 
						|
    break;
 | 
						|
  case a_xvt_post:
 | 
						|
    if (notify_xvt)
 | 
						|
    {
 | 
						|
      TWindow* w = (TWindow*)xi_get_app_data(itf);
 | 
						|
      CHECK(w, "Can't send XVT event to a null window");
 | 
						|
      w->handler(w->win(), &xiev->v.xvte);
 | 
						|
      
 | 
						|
      if (xiev->v.xvte.type == E_MOUSE_UP)
 | 
						|
        _button_blocked = FALSE;
 | 
						|
    }
 | 
						|
    else
 | 
						|
      notify_xvt = TRUE;
 | 
						|
    break;
 | 
						|
  case a_post:
 | 
						|
    {
 | 
						|
      XI_OBJ * obj = xi_get_focus(itf);
 | 
						|
 | 
						|
      if ((obj != NULL && obj->type != XIT_ITF))
 | 
						|
      {
 | 
						|
        if ((obj->type == XIT_CELL || (obj->type == XIT_BTN && obj->v.btn->type == XIBT_RADIOBTN)))
 | 
						|
          obj = obj->parent;
 | 
						|
        CHECK(obj != NULL, "Unexpected null obj");
 | 
						|
        ctl = (TControl*)xi_get_app_data(obj);
 | 
						|
      }
 | 
						|
    }
 | 
						|
    break;
 | 
						|
  case a_debug:
 | 
						|
    break;         // Put your breakpoint here
 | 
						|
  default:
 | 
						|
    break;
 | 
						|
  }
 | 
						|
 | 
						|
  if (ctl != NULL)
 | 
						|
  {
 | 
						|
    const bool ok = ctl->event_handler(itf, xiev);
 | 
						|
    if (!ok)
 | 
						|
    {
 | 
						|
      xiev->refused = TRUE;
 | 
						|
      if (xiev->type == XIE_CHAR_FIELD || xiev->type == XIE_CHAR_CELL ||
 | 
						|
          xiev->type == XIE_XVT_EVENT)
 | 
						|
        notify_xvt = FALSE;
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// TControl
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
TControl::TControl()
 | 
						|
        : _obj(NULL), _fld(NULL)
 | 
						|
{}
 | 
						|
 | 
						|
// Virtual destructor needed to make derived descrutors live!
 | 
						|
TControl::~TControl()
 | 
						|
{}
 | 
						|
 | 
						|
XI_OBJ* TControl::get_interface(WINDOW win) const
 | 
						|
{
 | 
						|
  XI_OBJ* itf;
 | 
						|
  if (win == NULL_WIN)
 | 
						|
  {
 | 
						|
    CHECK(_obj, "Can't get the interface from NULL XI object");
 | 
						|
    itf = _obj->itf;
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    itf = xi_get_itf(win);
 | 
						|
    CHECK(itf, "Can't get the interface from a window");
 | 
						|
  }
 | 
						|
  return itf;
 | 
						|
}
 | 
						|
 | 
						|
void TControl::set_tab_cid(XI_OBJ* obj, short cid) const
 | 
						|
{
 | 
						|
  CHECK(obj, "Can't set tab cid to null control");
 | 
						|
    
 | 
						|
  switch(obj->type)
 | 
						|
  {
 | 
						|
  case XIT_BTN:
 | 
						|
    obj->v.btn->tab_cid = cid; 
 | 
						|
    break;
 | 
						|
  case XIT_CONTAINER:
 | 
						|
    obj->v.container->tab_cid = cid; 
 | 
						|
    break;
 | 
						|
  case XIT_FIELD:
 | 
						|
    obj->v.field->tab_cid = cid;
 | 
						|
    break;
 | 
						|
  case XIT_FORM:
 | 
						|
    obj->v.form->tab_cid = cid; 
 | 
						|
    break;
 | 
						|
  case XIT_LIST:
 | 
						|
    obj->v.list->tab_cid = cid; 
 | 
						|
    break;
 | 
						|
  case XIT_COLUMN:     
 | 
						|
    obj->parent->v.list->tab_cid = cid;
 | 
						|
    break;  
 | 
						|
  default:
 | 
						|
    NFCHECK(0, "Can't set tab_cid to a static control: ", _obj->cid); break;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
HIDDEN bool is_container(const XI_OBJ* obj)
 | 
						|
{
 | 
						|
  return obj->type == XIT_CONTAINER || obj->type == XIT_FORM || obj->type == XIT_GROUP;
 | 
						|
}
 | 
						|
 | 
						|
XI_OBJ* TControl::find_operable(XI_OBJ* container, bool forward, bool normal) const
 | 
						|
{
 | 
						|
  int num; 
 | 
						|
  XI_OBJ** child = xi_get_member_list(container, &num);
 | 
						|
  CHECK(num > 0, "Container too empty");
 | 
						|
  
 | 
						|
  const int first = forward ? 0 : num-2;
 | 
						|
  const int last  = forward ? num-1 : -1;
 | 
						|
  const int delta = forward ? +1 : -1;
 | 
						|
  
 | 
						|
  XI_OBJ* found = NULL;
 | 
						|
  for (int c = first; c != last && found == NULL; c += delta)
 | 
						|
  {
 | 
						|
    XI_OBJ* obj = child[c];
 | 
						|
    switch (obj->type) 
 | 
						|
    {
 | 
						|
    case XIT_LIST:
 | 
						|
    case XIT_BTN:
 | 
						|
    case XIT_FIELD:
 | 
						|
      if (normal && obj->cid > 0)
 | 
						|
        found = obj;
 | 
						|
      break;        
 | 
						|
    case XIT_CONTAINER:
 | 
						|
    case XIT_FORM:  
 | 
						|
    case XIT_GROUP:
 | 
						|
      if (obj->cid > 0)
 | 
						|
      {
 | 
						|
        if (normal)
 | 
						|
        {
 | 
						|
          int num;
 | 
						|
          XI_OBJ** child = xi_get_member_list(obj, &num);
 | 
						|
          found = forward ? child[0] : child[num-1];
 | 
						|
        }  
 | 
						|
        else
 | 
						|
          found = obj;
 | 
						|
      }  
 | 
						|
      break;
 | 
						|
    default:
 | 
						|
      break;      
 | 
						|
    }  
 | 
						|
  }
 | 
						|
  
 | 
						|
  if (found == NULL)
 | 
						|
  {   
 | 
						|
    found = child[num-1];
 | 
						|
    if (is_container(found) && normal) 
 | 
						|
    {
 | 
						|
      int num;
 | 
						|
      XI_OBJ** child = xi_get_member_list(found, &num);
 | 
						|
      found = forward ? child[0] : child[num-1];
 | 
						|
    }
 | 
						|
  }  
 | 
						|
  
 | 
						|
  return found;  
 | 
						|
}
 | 
						|
 | 
						|
void TControl::update_tab_cid()
 | 
						|
{                            
 | 
						|
  const bool is_cont = is_container(_obj);
 | 
						|
  
 | 
						|
  XI_OBJ *first = find_operable(_obj->itf, TRUE, !is_cont);
 | 
						|
  set_tab_cid(_obj, first->cid);
 | 
						|
  
 | 
						|
  XI_OBJ *last = find_operable(_obj->itf, FALSE, !is_cont);
 | 
						|
  set_tab_cid(last, _obj->cid);
 | 
						|
 | 
						|
  if (is_cont)
 | 
						|
  {
 | 
						|
    XI_OBJ* first = find_operable(_obj->itf, TRUE,  TRUE);
 | 
						|
    XI_OBJ* last  = find_operable(_obj->itf, FALSE, TRUE);
 | 
						|
    int num; 
 | 
						|
    XI_OBJ** child = xi_get_member_list(_obj, &num);
 | 
						|
    set_tab_cid(child[num-1], first->cid);
 | 
						|
    set_tab_cid(last, child[0]->cid);
 | 
						|
  } else 
 | 
						|
  if (_obj->parent != _obj->itf)
 | 
						|
  {
 | 
						|
    XI_OBJ* first = find_operable(_obj->itf, TRUE,  FALSE);
 | 
						|
    XI_OBJ* last  = find_operable(_obj->itf, FALSE, FALSE);
 | 
						|
    set_tab_cid(_obj->parent, first->cid);
 | 
						|
    set_tab_cid(last, _obj->parent->cid);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void TControl::coord2rct(WINDOW win, short x, short y, short dx, short dy, XI_RCT& rct) const
 | 
						|
{
 | 
						|
  // Spazio da lasciare prima di toccare i bordi
 | 
						|
  const int X_FU_DELTA = XI_FU_MULTIPLE / 4;
 | 
						|
  const int Y_FU_DELTA = XI_FU_MULTIPLE / 8;
 | 
						|
 | 
						|
  XI_OBJ* itf = get_interface(win);
 | 
						|
 | 
						|
  // Se ci sono i tab controls sulla pagina salta una riga
 | 
						|
  if (y >= 0)
 | 
						|
  {
 | 
						|
    int num;
 | 
						|
    XI_OBJ** child = xi_get_member_list(itf, &num);
 | 
						|
    if (num > 0 && child[0]->cid == MASK_RECT_ID)
 | 
						|
      y++;
 | 
						|
  }
 | 
						|
 | 
						|
  RCT max; xvt_vobj_get_client_rect(win, &max);
 | 
						|
  xi_pu_to_fu(itf, (PNT*)&max, 2);
 | 
						|
  const int& MAXX = max.right;
 | 
						|
  const int& MAXY = max.bottom;
 | 
						|
 | 
						|
  int width = XI_FU_MULTIPLE;
 | 
						|
  if (dx > 0)
 | 
						|
    width = dx * XI_FU_MULTIPLE;
 | 
						|
 | 
						|
  int height = XI_FU_MULTIPLE;
 | 
						|
  if (dy > 1)
 | 
						|
    height += (dy-1) * Y_FU_MULTIPLE;
 | 
						|
 | 
						|
  if (x < 0)
 | 
						|
  {
 | 
						|
    x = -x;
 | 
						|
    if (x > 10)
 | 
						|
    {
 | 
						|
      const int num = x / 10 -1;
 | 
						|
      const int tot = x % 10;
 | 
						|
      const int spc = (MAXX - tot*width) / (tot+1);
 | 
						|
      rct.left = spc + num * (spc+width);
 | 
						|
    }
 | 
						|
    else
 | 
						|
      rct.left = MAXX - width - x * XI_FU_MULTIPLE;
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    rct.left = x * XI_FU_MULTIPLE + X_FU_DELTA;
 | 
						|
 | 
						|
    if (dx > 0 && MAXX > 80 * XI_FU_MULTIPLE)
 | 
						|
      rct.left += (MAXX - 80 * XI_FU_MULTIPLE) / 2;
 | 
						|
  }
 | 
						|
 | 
						|
  if (y < 0)
 | 
						|
  {
 | 
						|
    y = -y;
 | 
						|
    if (y > 10)
 | 
						|
    {
 | 
						|
      const int num = y / 10 -1;
 | 
						|
      const int tot = y % 10;
 | 
						|
      const int spc = (MAXY - tot*height) / (tot+1);
 | 
						|
      rct.top = spc + num * (spc+height);
 | 
						|
    }
 | 
						|
    else
 | 
						|
      rct.top = MAXY - height - (y-1) * Y_FU_MULTIPLE - Y_FU_DELTA;
 | 
						|
  }
 | 
						|
  else
 | 
						|
    rct.top = y * Y_FU_MULTIPLE + Y_FU_DELTA;
 | 
						|
 | 
						|
  if (dx > 0)
 | 
						|
    rct.right = rct.left + width;
 | 
						|
  else
 | 
						|
    rct.right = MAXX + (dx-1) * XI_FU_MULTIPLE - X_FU_DELTA;
 | 
						|
 | 
						|
  if (dy > 0)
 | 
						|
    rct.bottom = rct.top + height;
 | 
						|
  else
 | 
						|
    rct.bottom = MAXY + dy * Y_FU_MULTIPLE - X_FU_DELTA;
 | 
						|
}
 | 
						|
 | 
						|
RCT& TControl::get_rect(RCT& r) const
 | 
						|
{
 | 
						|
  xi_get_rect(_obj, &r);
 | 
						|
  return r;
 | 
						|
}
 | 
						|
 | 
						|
void TControl::set_rect(const RCT&)
 | 
						|
{
 | 
						|
  CHECK(0, "Can't set_rect to generic TControl");
 | 
						|
}
 | 
						|
 | 
						|
unsigned long TControl::flags2attr(const char* flags) const
 | 
						|
{
 | 
						|
  unsigned long attrib = XI_ATR_VISIBLE | XI_ATR_ENABLED;
 | 
						|
  for (const char* f = flags; *f; f++)
 | 
						|
  {
 | 
						|
    switch(toupper(*f))
 | 
						|
    {
 | 
						|
      case '*': attrib |= XI_ATR_PASSWORD; break;
 | 
						|
      case 'C': attrib |= XI_ATR_HCENTER;  break;
 | 
						|
      case 'D': attrib &= ~XI_ATR_ENABLED; break;
 | 
						|
      case 'H': attrib &= ~XI_ATR_VISIBLE; break;
 | 
						|
      case 'R': attrib |= XI_ATR_RJUST;    break;
 | 
						|
      default : break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return attrib;
 | 
						|
}
 | 
						|
 | 
						|
const char* TControl::parse_caption(const char* cap, bool& bold, COLOR& color) const
 | 
						|
{
 | 
						|
  bold = FALSE;
 | 
						|
  color = NORMAL_COLOR;
 | 
						|
  for (const char* t = cap; *t == '@' || *t == '$'; t++)
 | 
						|
  {
 | 
						|
    if (*t == '@')
 | 
						|
    {
 | 
						|
      const char code = toupper(*(t+1));
 | 
						|
      if (code == 'B')
 | 
						|
      {
 | 
						|
        bold = TRUE;
 | 
						|
        t++;
 | 
						|
      }
 | 
						|
      else
 | 
						|
      {
 | 
						|
        NFCHECK(0, "Bad character after @ in prompt");
 | 
						|
        break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
      if (*(t+1) == '[')
 | 
						|
      {
 | 
						|
        t += 2;                          // Skip [
 | 
						|
        if (isalpha(*t))
 | 
						|
           color = trans_color(*t);
 | 
						|
        else
 | 
						|
        {
 | 
						|
          int r = 0, g = 0, b = 0;
 | 
						|
          sscanf(t, "%d,%d,%d", &r, &g, &b);
 | 
						|
          if (r == 0 && g == 0 && b == 0)
 | 
						|
            color = COLOR_BLACK;
 | 
						|
          else  
 | 
						|
            color = MAKE_COLOR(r, g, b);
 | 
						|
        }
 | 
						|
        while (*t && *t != ']') t++;
 | 
						|
      }
 | 
						|
      else
 | 
						|
      {
 | 
						|
        NFCHECK(0, "Bad character after $ in prompt");
 | 
						|
        break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return t;
 | 
						|
}
 | 
						|
 | 
						|
WINDOW TControl::parent() const
 | 
						|
{
 | 
						|
  return xi_get_window(_obj->itf);
 | 
						|
}
 | 
						|
 | 
						|
void TControl::set_focus() const
 | 
						|
{
 | 
						|
  xi_set_focus(_obj);
 | 
						|
}
 | 
						|
 | 
						|
bool TControl::notify_key(KEY k)
 | 
						|
{
 | 
						|
  bool ok = TRUE;
 | 
						|
 | 
						|
  if (_fld == NULL)
 | 
						|
  {
 | 
						|
    TWindow* msk = (TWindow*)xi_get_app_data(get_interface());
 | 
						|
    CHECK(msk, "Can't get TMask from XI interface");
 | 
						|
    if (msk->is_kind_of(CLASS_MASK))
 | 
						|
    {
 | 
						|
      const TMask& m = (TMask&)*msk;
 | 
						|
      const int pos = m.id2pos(id());
 | 
						|
      if (pos >= 0)
 | 
						|
        _fld = &m.fld(pos);
 | 
						|
    }
 | 
						|
  }
 | 
						|
  if (_fld)
 | 
						|
    ok = _fld->on_key(k);
 | 
						|
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
bool TControl::is_edit_key(KEY k) const
 | 
						|
{
 | 
						|
  return k >= ' ' && k < 255 && k != K_DEL;
 | 
						|
}
 | 
						|
 | 
						|
bool TControl::event_handler(XI_OBJ* itf, XI_EVENT* xiev)
 | 
						|
{
 | 
						|
  bool ok = TRUE;
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
void TControl::change_attrib(unsigned long mask, bool on, XI_OBJ* obj)
 | 
						|
{
 | 
						|
  if (obj == NULL) obj = _obj;
 | 
						|
  const unsigned long old_attr = xi_get_attrib(obj);
 | 
						|
  unsigned long attr = old_attr;
 | 
						|
  if (on) attr |= mask;
 | 
						|
  else    attr &= ~mask;
 | 
						|
  if (attr != old_attr)     // C'e' un vero cambiamento d'attributo
 | 
						|
  {
 | 
						|
    // Se la finestra e' chiusa e il campo e un bottone o e' editabile allora cambia l'attributo
 | 
						|
    // senza ridisegnare il campo, il che provocherebbe problemi di funzionamento degli sheet
 | 
						|
    if (_obj->type == XIT_BTN || _obj->type == XIT_FIELD)
 | 
						|
    {
 | 
						|
      const TWindow* w = (const TWindow*)_obj->itf->app_data;
 | 
						|
      if (!w->is_open())
 | 
						|
      {
 | 
						|
        if (_obj->type == XIT_FIELD)
 | 
						|
          ((STX_DATA*)_obj->v.field->stx)->attrib = attr;
 | 
						|
        else
 | 
						|
          _obj->v.btn->attrib = attr;
 | 
						|
        return;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    // Usa tranquillamente il metodo ortodosso
 | 
						|
    xi_set_attrib(obj, attr);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
// @doc INTERNAL
 | 
						|
 | 
						|
// @mfunc Mostra/Nasconde il controllo
 | 
						|
void TControl::show(
 | 
						|
     bool on)  // @parm Operazione da svolgere sul controllo:
 | 
						|
         // @flag TRUE | Il controllo viene mostrato
 | 
						|
         // @flag FALSE | Il controllo viene nascosto
 | 
						|
{
 | 
						|
  change_attrib(XI_ATR_VISIBLE, on);
 | 
						|
}
 | 
						|
 | 
						|
// @doc INTERNAL
 | 
						|
 | 
						|
// @mfunc Abilita/disabilita il controllo
 | 
						|
void TControl::enable(
 | 
						|
     bool on)  // @parm Operazione da svolgere sul controllo:
 | 
						|
         // @flag TRUE | Il controllo viene abilitato
 | 
						|
         // @flag FALSE | Il controllo viene disabilitato
 | 
						|
{
 | 
						|
  change_attrib(XI_ATR_ENABLED, on);
 | 
						|
}
 | 
						|
 | 
						|
// @mfunc Abilita/disabilita l'autoselezione del testo
 | 
						|
void TControl::autoselect(bool on)
 | 
						|
{
 | 
						|
  change_attrib(XI_ATR_AUTOSELECT, on);
 | 
						|
}
 | 
						|
 | 
						|
// @doc INTERNAL
 | 
						|
 | 
						|
const char* TControl::caption() const
 | 
						|
{
 | 
						|
  const char* c = xi_get_text(_obj, NULL, 512);
 | 
						|
  return c;
 | 
						|
}
 | 
						|
 | 
						|
void TControl::set_caption(const char* c)
 | 
						|
{
 | 
						|
  xi_set_text(_obj, (char*)c);
 | 
						|
}
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// TText
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
TText_control::TText_control(WINDOW win, short cid,
 | 
						|
                             short left, short top, short width, short height,
 | 
						|
                             const char* flags, const char* text)
 | 
						|
{
 | 
						|
  bool bold;
 | 
						|
  COLOR color;
 | 
						|
  TString t = parse_caption(text, bold, color);
 | 
						|
  t.rtrim();
 | 
						|
  if (width <= 0)
 | 
						|
    width = t.len();
 | 
						|
 | 
						|
  XI_RCT rct; coord2rct(win, left, top, width, height, rct);
 | 
						|
  rct.right += bold ? (width*XI_FU_MULTIPLE/4) : XI_FU_MULTIPLE;
 | 
						|
 | 
						|
  const unsigned long attrib = flags2attr(flags);
 | 
						|
  XI_OBJ_DEF* def = xi_add_text_def(NULL, cid, &rct, attrib, (char*)(const char*)t);
 | 
						|
  CHECKS(def, "Can't create the definition of TText_control:", text);
 | 
						|
  def->v.text->fore_color = color;
 | 
						|
  if (bold)
 | 
						|
    def->v.text->font_id = xvt_default_font(TRUE);
 | 
						|
  _obj = xi_create(get_interface(win), def);
 | 
						|
  CHECKS(_obj, "Can't create TText_control ", text);
 | 
						|
 | 
						|
  xi_dequeue();
 | 
						|
  xi_tree_free(def);
 | 
						|
}
 | 
						|
 | 
						|
void TText_control::set_caption(const char* text)
 | 
						|
{
 | 
						|
  bool bold;
 | 
						|
  COLOR color;
 | 
						|
  const char* c = parse_caption(text, bold, color);
 | 
						|
  xi_set_text(_obj, (char*)c);
 | 
						|
  _obj->v.text->fore_color = color;    
 | 
						|
  
 | 
						|
  FONT_OBJ* &font = _obj->v.text->font;
 | 
						|
  if (font == NULL)
 | 
						|
    font = (FONT_OBJ*)xi_tree_malloc(sizeof(FONT_OBJ), _obj->v.text);
 | 
						|
  *font = xi_create_copy_font_id(get_interface(), xvt_default_font(bold), NULL);
 | 
						|
  
 | 
						|
  RCT rct; get_rect(rct);
 | 
						|
  xi_invalidate_rect(parent(), &rct);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// TGroupbox_control
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
TGroupbox_control::TGroupbox_control(WINDOW win, short cid,
 | 
						|
                                     short left, short top, short width, short height,
 | 
						|
                                     const char* flags, const char* text)
 | 
						|
                 : TText_control(win, cid, left, top, width, 1, flags, text)
 | 
						|
{
 | 
						|
  // Alza di un pixel il rettangolo per non coprire il rettangolo
 | 
						|
  RCT& tr = _obj->v.text->rct;
 | 
						|
  tr.top--; tr.bottom--;
 | 
						|
 | 
						|
  XI_RCT rct; coord2rct(win, left, top, width, height, rct);
 | 
						|
  rct.top += XI_FU_MULTIPLE - 2;
 | 
						|
  rct.bottom -= Y_FU_MULTIPLE / 2;
 | 
						|
 | 
						|
  XI_OBJ_DEF* def = xi_add_rect_def(NULL, cid, &rct, XI_ATR_VISIBLE, 0, 0); // Ignore colors
 | 
						|
  CHECKS(def, "Can't create the definition of TGroupbox_control ", text);
 | 
						|
  def->v.rect->hilight_color = MASK_LIGHT_COLOR;
 | 
						|
  def->v.rect->back_color    = MASK_BACK_COLOR;
 | 
						|
  def->v.rect->shadow_color  = MASK_DARK_COLOR;
 | 
						|
 | 
						|
  const bool erre = strchr(flags, 'R') != NULL;
 | 
						|
  if (erre)
 | 
						|
  {
 | 
						|
    def->v.rect->well = TRUE;                  // Mette in rilievo il rettangolo
 | 
						|
    change_attrib(XI_ATR_RJUST, FALSE, _obj);  // Toglie l'erroneo allineamento a destra del titolo
 | 
						|
  }
 | 
						|
  _rct = xi_create(get_interface(win), def);
 | 
						|
  CHECKD(_rct, "Can't create Groupbox_control ", cid);
 | 
						|
 | 
						|
  RCT& rt = _obj->v.text->rct;
 | 
						|
  rt.top--; rt.bottom--;
 | 
						|
 | 
						|
  xi_dequeue();
 | 
						|
  xi_tree_free(def);
 | 
						|
}
 | 
						|
 | 
						|
void TGroupbox_control::show(bool on)
 | 
						|
{
 | 
						|
  TText_control::show(on);
 | 
						|
  change_attrib(XI_ATR_VISIBLE, on, _rct);
 | 
						|
}
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// TField
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
static bool in_create = FALSE;
 | 
						|
 | 
						|
TField_control::TField_control(WINDOW win, short cid,
 | 
						|
                               short left, short top, short width, short maxlen,
 | 
						|
                               const char* flags, const char* text)
 | 
						|
{
 | 
						|
  const bool button = strchr(flags, 'B') != NULL;
 | 
						|
  create(win, cid, left, top, width, 1, maxlen, flags, text, button);
 | 
						|
}
 | 
						|
 | 
						|
void TField_control::create(WINDOW win, short cid,
 | 
						|
                       short left, short top, short width, short height, short maxlen,
 | 
						|
                       const char* flags, const char* text, bool button)
 | 
						|
{
 | 
						|
  in_create = TRUE;
 | 
						|
 | 
						|
  const short fcid = cid > 0 ? cid + 2000 : cid - 2000;
 | 
						|
  XI_OBJ_DEF* frm_def = xi_add_form_def(NULL, fcid, fcid);
 | 
						|
  frm_def->app_data = (long)this;
 | 
						|
 | 
						|
  XI_RCT rct; coord2rct(win, left, top, width, height, rct);
 | 
						|
  rct.right += XI_FU_MULTIPLE/4;
 | 
						|
 | 
						|
  unsigned long attrib = flags2attr(flags);
 | 
						|
  if (AUTOSELECT) 
 | 
						|
    attrib |= XI_ATR_AUTOSELECT;
 | 
						|
  if (!CAMPI_SCAVATI)
 | 
						|
    attrib |= XI_ATR_BORDER;
 | 
						|
  if (maxlen > width)
 | 
						|
    attrib |= XI_ATR_AUTOSCROLL;
 | 
						|
 | 
						|
  XI_OBJ_DEF* def = xi_add_field_def(frm_def, cid,
 | 
						|
                                     rct.top, rct.left,
 | 
						|
                                     rct.right - rct.left,
 | 
						|
                                     attrib, cid, maxlen+1,
 | 
						|
                                     NORMAL_COLOR, NORMAL_BACK_COLOR,
 | 
						|
                                     NORMAL_COLOR, DISABLED_BACK_COLOR,
 | 
						|
                                     FOCUS_COLOR);
 | 
						|
 | 
						|
  def->app_data = (long)this;
 | 
						|
  XI_FIELD_DEF* f = def->v.field;
 | 
						|
  f->well = CAMPI_SCAVATI;
 | 
						|
  f->auto_tab = TRUE;
 | 
						|
  f->active_back_color = FOCUS_BACK_COLOR;
 | 
						|
  if (button)
 | 
						|
  {
 | 
						|
    f->button = TRUE;
 | 
						|
    f->pixel_button_distance = 1;
 | 
						|
  }
 | 
						|
  if (height != 1)   // E' un multiline, quindi setto il rettangolo
 | 
						|
    f->xi_rct = rct;
 | 
						|
 | 
						|
  XI_OBJ* itf = get_interface(win);
 | 
						|
  XI_OBJ* form = xi_create(itf, frm_def);
 | 
						|
  CHECKD(form, "Can't create the form for field ", cid);
 | 
						|
  _obj = xi_get_obj(form, cid);
 | 
						|
  CHECKD(_obj, "Can't create field ", cid);
 | 
						|
  STX_DATA* stx = (STX_DATA*)_obj->v.field->stx;
 | 
						|
  CHECKD(stx, "NULL stx for field ", cid);
 | 
						|
  
 | 
						|
  // Aggiusta il rettangolo del bottone in modo da allinearlo al testo
 | 
						|
  RCT& br = _obj->v.field->btn_rct;
 | 
						|
  const int offset = stx->rct.right - br.left - 1;
 | 
						|
  br.left  += offset; 
 | 
						|
  br.right += offset; 
 | 
						|
 | 
						|
  update_tab_cid();
 | 
						|
 | 
						|
  xi_dequeue();
 | 
						|
  xi_tree_free(frm_def);
 | 
						|
 | 
						|
  in_create = FALSE;
 | 
						|
}
 | 
						|
 | 
						|
void TField_control::show_button(bool on)
 | 
						|
{
 | 
						|
  XI_FIELD_DATA* f = _obj->v.field;
 | 
						|
  if (f->button != on)
 | 
						|
  {
 | 
						|
    f->button = on;
 | 
						|
    xi_invalidate_rect(parent(), &f->btn_rct);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
bool TField_control::event_handler(XI_OBJ* itf, XI_EVENT* xiev)
 | 
						|
{
 | 
						|
  if (in_create)
 | 
						|
    return FALSE;
 | 
						|
 | 
						|
  bool ok = TRUE;
 | 
						|
 | 
						|
  switch(xiev->type)
 | 
						|
  {
 | 
						|
  case XIE_OFF_FIELD:
 | 
						|
    ok = notify_key(K_TAB);
 | 
						|
    break;
 | 
						|
  case XIE_ON_FIELD:
 | 
						|
    notify_key(K_CTRL+K_TAB);
 | 
						|
    break;
 | 
						|
  case XIE_DBL_FIELD:
 | 
						|
    notify_key(K_F9);
 | 
						|
    break;
 | 
						|
  case XIE_CHAR_FIELD:
 | 
						|
    {
 | 
						|
      KEY k = xiev_to_key(xiev);
 | 
						|
      if (k == K_PREV || k == K_NEXT || k > K_CTRL)
 | 
						|
      {
 | 
						|
        k = K_TAB;
 | 
						|
        xiev->refused = TRUE;
 | 
						|
      }  
 | 
						|
      if (k == K_TAB || is_edit_key(k) || (k > K_F1 && k < K_F12))
 | 
						|
        ok = notify_key(k);
 | 
						|
    }
 | 
						|
    break;
 | 
						|
  case XIE_CHG_FIELD:
 | 
						|
    notify_key(K_CTRL+K_SPACE);
 | 
						|
    break;
 | 
						|
  case XIE_BUTTON:
 | 
						|
    notify_key(K_F9);
 | 
						|
    break;
 | 
						|
  default:
 | 
						|
    ok = TControl::event_handler(itf, xiev);
 | 
						|
    break;
 | 
						|
  }
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
void TField_control::set_focus() const
 | 
						|
{
 | 
						|
  TControl::set_focus();
 | 
						|
}
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// TMultiline_control
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
TMultiline_control::TMultiline_control(WINDOW win, short cid,
 | 
						|
                                       short left, short top,
 | 
						|
                                       short width, short height, short maxlen,
 | 
						|
                                       const char* flags, const char* text)
 | 
						|
{
 | 
						|
  create(win, cid, left, top, width, height, maxlen, flags, text, FALSE);
 | 
						|
}
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// TButton_control
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
void TButton_control::create(WINDOW win, short cid,
 | 
						|
                             short left, short top, short width, short height,
 | 
						|
                             const char* flags, const char* text,
 | 
						|
                             WIN_TYPE wc, XI_OBJ* container)
 | 
						|
{
 | 
						|
  bool bold;
 | 
						|
  COLOR color;
 | 
						|
  TString txt(text); txt.strip("&~");
 | 
						|
  const char* t = parse_caption(txt, bold, color);
 | 
						|
  if (width <= 0) width = strlen(t)+3;
 | 
						|
 | 
						|
  RCT rct; coord2rct(win, left, top, width, height, rct);
 | 
						|
 | 
						|
  const unsigned long attrib = flags2attr(flags);
 | 
						|
  XI_OBJ_DEF* def = xi_add_button_def(NULL, cid, &rct, attrib, (char*)t, cid);
 | 
						|
  CHECKD(def, "Can't create the interface of TButton_control ", cid);
 | 
						|
  def->v.btn->fore_color = color;
 | 
						|
  def->app_data = (long)this;
 | 
						|
  switch (wc)
 | 
						|
  {
 | 
						|
    case WC_PUSHBUTTON : def->v.btn->type = XIBT_BUTTON; break;
 | 
						|
    case WC_CHECKBOX   : def->v.btn->type = XIBT_CHECKBOX; break;
 | 
						|
    case WC_RADIOBUTTON: def->v.btn->type = XIBT_RADIOBTN; break;
 | 
						|
    default            : def->v.btn->type = XIBT_TABBTN; break;
 | 
						|
  }
 | 
						|
 | 
						|
  if (container == NULL)
 | 
						|
    container = get_interface(win);
 | 
						|
  _obj = xi_create(container, def);
 | 
						|
  CHECKD(_obj, "Can't create TButton_control ", cid);
 | 
						|
 | 
						|
  // Aggiusta bottoni con icona a sinistra
 | 
						|
  if (wc == WC_CHECKBOX || wc == WC_RADIOBUTTON)
 | 
						|
  {
 | 
						|
    RCT& r = _obj->v.btn->rct;
 | 
						|
    r.top++; r.bottom-=2;
 | 
						|
    r.right += XI_FU_MULTIPLE / 2;
 | 
						|
  }
 | 
						|
 | 
						|
  xi_dequeue();
 | 
						|
  xi_tree_free(def);
 | 
						|
 | 
						|
  update_tab_cid();
 | 
						|
}
 | 
						|
 | 
						|
XI_BTN_TYPE TButton_control::button_type() const
 | 
						|
{
 | 
						|
  return _obj->v.btn->type;
 | 
						|
}
 | 
						|
 | 
						|
XI_OBJ* TButton_control::container() const
 | 
						|
{
 | 
						|
  return _obj->parent;
 | 
						|
}
 | 
						|
 | 
						|
void TButton_control::check(bool on)
 | 
						|
{
 | 
						|
  xi_check(_obj, on);
 | 
						|
}
 | 
						|
 | 
						|
bool TButton_control::checked() const
 | 
						|
{
 | 
						|
  return xi_is_checked(_obj) ? TRUE : FALSE;
 | 
						|
}
 | 
						|
 | 
						|
bool TButton_control::toggle()
 | 
						|
{
 | 
						|
  const bool on = !checked();
 | 
						|
  check(on);
 | 
						|
  return on;
 | 
						|
}
 | 
						|
 | 
						|
void TButton_control::set_rect(const RCT& r)
 | 
						|
{
 | 
						|
  _obj->v.btn->rct = r;
 | 
						|
}
 | 
						|
 | 
						|
bool TButton_control::event_handler(XI_OBJ* itf, XI_EVENT* xiev)
 | 
						|
{
 | 
						|
  bool ok = TRUE;
 | 
						|
 | 
						|
  if (xiev->type == XIE_BUTTON)
 | 
						|
  {
 | 
						|
    if (_last_mouse_button == 0 && xi_move_focus(_obj))
 | 
						|
    {               
 | 
						|
      switch (_obj->v.btn->type)
 | 
						|
      {
 | 
						|
        case XIBT_CHECKBOX:
 | 
						|
        case XIBT_BUTTON_CHECKBOX:
 | 
						|
          toggle();
 | 
						|
          break;
 | 
						|
        default:
 | 
						|
          break;
 | 
						|
      }
 | 
						|
      ok = notify_key(K_SPACE);
 | 
						|
    }
 | 
						|
  }
 | 
						|
  else
 | 
						|
    if (xiev->type == XIE_POST_NAVIGATION)
 | 
						|
      ok == notify_key(K_CTRL + K_TAB);
 | 
						|
    else
 | 
						|
      ok = TControl::event_handler(itf, xiev);
 | 
						|
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// TPushbutton_control
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
TPushbutton_control::TPushbutton_control(WINDOW win, short cid,
 | 
						|
                                         short left, short top, short width, short height,
 | 
						|
                                         const char* flags, const char* text,
 | 
						|
                                         short bmp_up, short bmp_dn)
 | 
						|
                   : _bmp_up(bmp_up), _bmp_dn(bmp_dn)
 | 
						|
 | 
						|
{         
 | 
						|
  bool bold;
 | 
						|
  COLOR color;
 | 
						|
  _caption = parse_caption(text, bold, color);
 | 
						|
  
 | 
						|
  _underscore = _caption.find('~');
 | 
						|
  if (_underscore < 0)
 | 
						|
    _underscore = _caption.find('&');
 | 
						|
  if (_underscore >= 0)  
 | 
						|
    _caption.strip("~&");
 | 
						|
    
 | 
						|
  create(win, cid, left, top, width, height, flags, text, WC_PUSHBUTTON, NULL);
 | 
						|
  _obj->v.btn->drawable = TRUE;
 | 
						|
  *_obj->v.btn->text = '\0';
 | 
						|
 | 
						|
  set_bmp(bmp_up, bmp_dn);
 | 
						|
}
 | 
						|
 | 
						|
void TPushbutton_control::set_bmp(short bmp_up, short bmp_dn)
 | 
						|
{
 | 
						|
  if (bmp_up > 0)
 | 
						|
  {
 | 
						|
    _picture->add(_bmp_up = bmp_up);
 | 
						|
    if (bmp_dn > 0)
 | 
						|
      _picture->add(_bmp_dn = bmp_dn);
 | 
						|
    else
 | 
						|
      _bmp_dn = _bmp_up;
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    _bmp_up = _bmp_dn = 0;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void TPushbutton_control::update()
 | 
						|
{
 | 
						|
  const long attrib = xi_get_attrib(_obj);
 | 
						|
  const WINDOW win = parent();
 | 
						|
 | 
						|
  if (attrib & XI_ATR_VISIBLE)
 | 
						|
  {
 | 
						|
    const short bmp = (_bmp_dn > 0 && _obj->v.btn->down) ? _bmp_dn : _bmp_up;
 | 
						|
    if (bmp > 0)
 | 
						|
    {
 | 
						|
      const TImage& i = _picture->image(bmp);
 | 
						|
      const RCT& rct = _obj->v.btn->rct;
 | 
						|
      int x = rct.left + (rct.right - rct.left - i.width()) / 2;
 | 
						|
      int y = rct.top + (rct.bottom - rct.top - i.height()) / 2;
 | 
						|
      if (_obj->v.btn->down)
 | 
						|
      {
 | 
						|
        x += 2;
 | 
						|
        y += 2;
 | 
						|
      }
 | 
						|
 | 
						|
      i.draw(win, x, y);
 | 
						|
      if (!(attrib & XI_ATR_ENABLED))
 | 
						|
      {
 | 
						|
        CPEN pen;
 | 
						|
        pen.width = 1;
 | 
						|
        pen.pat   = PAT_SOLID;
 | 
						|
        pen.style = P_SOLID;
 | 
						|
        pen.color = BTN_BACK_COLOR;
 | 
						|
        xvt_dwin_set_cpen(win, &pen);
 | 
						|
        for (int py = y + i.height(); py >= y; py -= 2)
 | 
						|
        {
 | 
						|
          PNT p; p.v = py; p.h = x;
 | 
						|
          xvt_dwin_draw_set_pos(win, p);
 | 
						|
          p.h += i.width();
 | 
						|
          xvt_dwin_draw_line(win, p);
 | 
						|
        }
 | 
						|
        for (int px = x + i.width(); px >= x; px -= 2)
 | 
						|
        {
 | 
						|
          PNT p; p.v = y; p.h = px;
 | 
						|
          xvt_dwin_draw_set_pos(win, p);
 | 
						|
          p.v += i.height();
 | 
						|
          xvt_dwin_draw_line(win, p);
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {             
 | 
						|
      RCT& r = _obj->v.btn->rct;
 | 
						|
      xvt_dwin_set_font(win, xvt_default_font());
 | 
						|
        
 | 
						|
      int ascent, descent;
 | 
						|
      xvt_dwin_get_font_metrics(win, NULL, &ascent, &descent);
 | 
						|
      const int w = xvt_dwin_get_text_width(win, (char*)(const char*)_caption, -1); 
 | 
						|
        
 | 
						|
      int x = r.left + (r.right - r.left - w) / 2; 
 | 
						|
      int y = r.top + (r.bottom - r.top + ascent - (descent+1)) / 2;
 | 
						|
        
 | 
						|
      if (_obj->v.btn->down)
 | 
						|
      {
 | 
						|
        x += 2;
 | 
						|
        y += 2;
 | 
						|
      }                                             
 | 
						|
        
 | 
						|
      DRAW_CTOOLS ct;
 | 
						|
      xvt_dwin_get_draw_ctools(win, &ct);
 | 
						|
      ct.opaque_text = FALSE;                 
 | 
						|
      ct.fore_color = (attrib & XI_ATR_ENABLED) ? _obj->v.btn->fore_color : DISABLED_COLOR;
 | 
						|
      xvt_dwin_set_draw_ctools(win, &ct);
 | 
						|
        
 | 
						|
      xvt_dwin_draw_text(win, x, y, (char*)(const char*)_caption, -1);
 | 
						|
        
 | 
						|
      if (_underscore >= 0)
 | 
						|
      {
 | 
						|
        TString80 cap = _caption;
 | 
						|
        cap[_underscore] = '_';
 | 
						|
        xvt_dwin_draw_text(win, x, y, (char*)(const char*)cap, _underscore+1);
 | 
						|
      }  
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
bool TPushbutton_control::event_handler(XI_OBJ* itf, XI_EVENT* xiev)
 | 
						|
{
 | 
						|
  bool ok = TButton_control::event_handler(itf, xiev);
 | 
						|
 | 
						|
  switch (xiev->type)
 | 
						|
  {
 | 
						|
    case XIE_BUTTON:
 | 
						|
      {
 | 
						|
        TWindow* w = (TWindow*)xi_get_app_data(get_interface());
 | 
						|
        w->on_button(id());
 | 
						|
      }
 | 
						|
      break;
 | 
						|
    default:
 | 
						|
      break;
 | 
						|
  }
 | 
						|
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// TCheckbox_control
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
TCheckbox_control::TCheckbox_control(WINDOW win, short cid,
 | 
						|
                                     short left, short top, short width,
 | 
						|
                                     const char* flags, const char* text)
 | 
						|
{ create(win, cid, left, top, width, 1, flags, text, WC_CHECKBOX, NULL); }
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// TRadiobutton_control
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
TRadiobutton_control::TRadiobutton_control(WINDOW win, short cid,
 | 
						|
                                           short left, short top, short width, short height,
 | 
						|
                                           const char* flags, const char* text)
 | 
						|
{
 | 
						|
  TToken_string testo(text); testo.strip("&~");
 | 
						|
  const int tot = testo.items();
 | 
						|
 | 
						|
  const XI_CONTAINER_ORIENTATION orient = height == 1 ? XI_STACK_HORIZONTAL : XI_STACK_VERTICAL;
 | 
						|
  XI_RCT rct; coord2rct(win, left, top, width, height, rct);
 | 
						|
 | 
						|
  if (height > 1)
 | 
						|
  {
 | 
						|
    // Aggiusta rettangolo in modo da centrare i bottoni
 | 
						|
    const int extra = rct.bottom - rct.top - tot * XI_FU_MULTIPLE;
 | 
						|
    if (extra > 0)
 | 
						|
      rct.top += extra / 2;
 | 
						|
    else
 | 
						|
      if (extra < 0)
 | 
						|
        rct.bottom -= extra;
 | 
						|
    rct.left  -= XI_FU_MULTIPLE / 4; 
 | 
						|
    rct.right += XI_FU_MULTIPLE / 4;
 | 
						|
  }
 | 
						|
  XI_OBJ_DEF* def = xi_add_container_def(NULL, cid, &rct, orient, cid);
 | 
						|
  def->app_data = (long)this;
 | 
						|
 | 
						|
  const unsigned long attrib = flags2attr(flags);
 | 
						|
  for (int b = 1; b <= tot; b++)
 | 
						|
  {
 | 
						|
    bool bold;
 | 
						|
    COLOR color;
 | 
						|
    const char* t = parse_caption(testo.get(), bold, color);
 | 
						|
 | 
						|
    const int next = cid + (b+1)*1000;
 | 
						|
    XI_OBJ_DEF* btn_def = xi_add_button_def(def, cid + b*1000, NULL, attrib, (char*)t, next);
 | 
						|
    CHECKD(btn_def, "Can't create definition for radio-button ", cid);
 | 
						|
    btn_def->app_data = (long)this;
 | 
						|
 | 
						|
    XI_BTN_DEF* btn = btn_def->v.btn;
 | 
						|
    btn->type = XIBT_RADIOBTN;
 | 
						|
    btn->fore_color = color;
 | 
						|
    btn->checked = b == 1;
 | 
						|
  }
 | 
						|
 | 
						|
  XI_OBJ* itf = get_interface(win);
 | 
						|
  _obj = xi_create(itf, def);
 | 
						|
  CHECKD(_obj, "Can't create radio-button container ", cid);
 | 
						|
 | 
						|
  update_tab_cid();
 | 
						|
 | 
						|
  xi_dequeue();
 | 
						|
  xi_tree_free(def);
 | 
						|
}
 | 
						|
 | 
						|
void TRadiobutton_control::show(bool on)
 | 
						|
{
 | 
						|
  int children;
 | 
						|
  XI_OBJ** child = xi_get_member_list(_obj, &children);
 | 
						|
  for (int c = children-1; c >= 0; c--)
 | 
						|
    change_attrib(XI_ATR_VISIBLE, on, child[c]);
 | 
						|
}
 | 
						|
 | 
						|
void TRadiobutton_control::enable(bool on)
 | 
						|
{
 | 
						|
  int children;
 | 
						|
  XI_OBJ** child = xi_get_member_list(_obj, &children);
 | 
						|
  for (int c = children-1; c >= 0; c--)
 | 
						|
    change_attrib(XI_ATR_ENABLED, on, child[c]);
 | 
						|
}
 | 
						|
 | 
						|
byte TRadiobutton_control::get_checked() const
 | 
						|
{
 | 
						|
  int children;
 | 
						|
  XI_OBJ** child = xi_get_member_list(_obj, &children);
 | 
						|
  for (int c = children-1; c > 0; c--)
 | 
						|
    if (xi_is_checked(child[c])) break;
 | 
						|
  return (byte)c;
 | 
						|
}
 | 
						|
 | 
						|
void TRadiobutton_control::check_button(byte c)
 | 
						|
{
 | 
						|
  int children;
 | 
						|
  XI_OBJ** child = xi_get_member_list(_obj, &children);
 | 
						|
  CHECKD(c < children, "This radio is rather old, it doesn't have button ", c);
 | 
						|
  if (!xi_is_checked(child[c]))
 | 
						|
    xi_check(child[c], TRUE);
 | 
						|
}
 | 
						|
 | 
						|
void TRadiobutton_control::show_button(byte c, bool on)
 | 
						|
{
 | 
						|
  int children;
 | 
						|
  XI_OBJ** child = xi_get_member_list(_obj, &children);
 | 
						|
  CHECKD(c < children, "This radio is rather old, it doesn't have button ", c);
 | 
						|
  change_attrib(XI_ATR_VISIBLE, on, child[c]);
 | 
						|
}
 | 
						|
 | 
						|
bool TRadiobutton_control::event_handler(XI_OBJ* itf, XI_EVENT* xiev)
 | 
						|
{
 | 
						|
  bool ok = TRUE;
 | 
						|
  if (xiev->type == XIE_BUTTON)
 | 
						|
  {
 | 
						|
    XI_OBJ* obj = xiev->v.xi_obj;       // Elemento del gruppo di radio buttons da premere
 | 
						|
    if (xi_move_focus(obj))             // Tenta di dargli il focus
 | 
						|
    {
 | 
						|
      if (!xi_is_checked(obj))          // Se non e' gia' premuto ...
 | 
						|
      {
 | 
						|
        xi_check(obj, TRUE);            // ... allora premilo e ...
 | 
						|
        ok = notify_key(K_SPACE);       // ... avverti il mask_field proprietario
 | 
						|
      }
 | 
						|
    }
 | 
						|
    else
 | 
						|
      ok = FALSE;
 | 
						|
  }
 | 
						|
  else
 | 
						|
    ok = TButton_control::event_handler(itf, xiev);
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
void TRadiobutton_control::set_focus() const
 | 
						|
{
 | 
						|
  int children;
 | 
						|
  XI_OBJ** child = xi_get_member_list(_obj, &children);
 | 
						|
  for (int c = children-1; c > 0; c--)
 | 
						|
    if (xi_is_checked(child[c])) break;
 | 
						|
  xi_set_focus(child[c]);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// TTagbutton_control
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
 | 
						|
TTagbutton_control::TTagbutton_control(WINDOW win, short cid,
 | 
						|
                                       short left, short top, short width, short height,
 | 
						|
                                       const char* flags, const char* text, int tag)
 | 
						|
{
 | 
						|
  XI_OBJ* itf = get_interface(win);
 | 
						|
  XI_RCT rct; xi_get_xi_rct(itf, &rct);
 | 
						|
  rct.bottom = rct.top + Y_FU_MULTIPLE;
 | 
						|
  XI_OBJ_DEF* cnt_def = xi_add_container_def(NULL, cid, &rct, XI_STACK_HORIZONTAL, cid);
 | 
						|
  cnt_def->app_data = (long)this;
 | 
						|
 | 
						|
  const unsigned long attrib = flags2attr(flags);
 | 
						|
 | 
						|
  TToken_string titolo(text);
 | 
						|
  const int tot = titolo.items();
 | 
						|
 | 
						|
  for (int b = 1; b <= tot; b++)
 | 
						|
  {
 | 
						|
    bool bold;
 | 
						|
    COLOR color;
 | 
						|
    const char* t = parse_caption(titolo.get(), bold, color);
 | 
						|
 | 
						|
    const int next_bid = b == tot ? cid+1 : cid+b+1;
 | 
						|
    XI_OBJ_DEF* btn_def = xi_add_button_def(cnt_def, cid+b, NULL, attrib, (char*)t, next_bid);
 | 
						|
    btn_def->v.btn->type = XIBT_TABBTN;
 | 
						|
    btn_def->v.btn->fore_color = color;
 | 
						|
    btn_def->v.btn->checked = tag == b-1;
 | 
						|
    btn_def->app_data = (long)this;
 | 
						|
  }
 | 
						|
 | 
						|
  _obj = xi_create(itf, cnt_def);
 | 
						|
  CHECKD(_obj, "Can't create tab-button container ", cid);
 | 
						|
  
 | 
						|
  update_tab_cid();
 | 
						|
 | 
						|
  xi_dequeue();
 | 
						|
  xi_tree_free(cnt_def);
 | 
						|
}
 | 
						|
 | 
						|
bool TTagbutton_control::event_handler(XI_OBJ* itf, XI_EVENT* xiev)
 | 
						|
{                         
 | 
						|
  bool ok = TRUE;    
 | 
						|
  if (xiev->type == XIE_BUTTON)
 | 
						|
  {                          
 | 
						|
    XI_OBJ* obj = xiev->v.xi_obj;        // Elemento del gruppo di radio buttons da premere
 | 
						|
    if (!xi_is_checked(obj))             // Se e' gia' selezionato ignoralo completamente
 | 
						|
    {
 | 
						|
      if (xi_move_focus(itf))            // Controlla se si puo' cambiare pagina
 | 
						|
      {
 | 
						|
        TWindow* w = (TWindow*)xi_get_app_data(itf);                       
 | 
						|
        const KEY k = K_CTRL + K_F1 + xiev->v.xi_obj->cid - id() - 1;
 | 
						|
        w->on_key(k);
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  else
 | 
						|
    ok = TRadiobutton_control::event_handler(itf, xiev);
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
void TTagbutton_control::set_caption(const char* text)
 | 
						|
{
 | 
						|
  TToken_string cap = text;
 | 
						|
  int num;
 | 
						|
  XI_OBJ** tag = xi_get_member_list(_obj, &num);
 | 
						|
   for (int i = 0; i < num; i++)
 | 
						|
  {
 | 
						|
    text = cap.get();
 | 
						|
    if (text == NULL)
 | 
						|
      text = cap.get(0);
 | 
						|
    xi_set_text(tag[i], (char*)text);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// TListbox_control
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
long TDropDownList::row2rec(int row) const
 | 
						|
{
 | 
						|
  int rows;
 | 
						|
  const long* handle = xi_get_list_info(_xi_lst, &rows);
 | 
						|
 | 
						|
  if (row < 0) row = 0;
 | 
						|
  else
 | 
						|
    if (row >= rows)
 | 
						|
      row = rows-1;
 | 
						|
  const long r = handle[row];
 | 
						|
  CHECKD(r >= 0 && r < items(), "Sheet line out of range: ", row);
 | 
						|
 | 
						|
  return r;
 | 
						|
}
 | 
						|
 | 
						|
int TDropDownList::rec2row(long rec) const
 | 
						|
{
 | 
						|
  int rows;
 | 
						|
  const long* handle = xi_get_list_info(_xi_lst, &rows);
 | 
						|
 | 
						|
  int r = int(rec - handle[0]);
 | 
						|
  if (r < 0 || r >= rows)
 | 
						|
    r = -1;
 | 
						|
 | 
						|
  return r;
 | 
						|
}
 | 
						|
 | 
						|
void TDropDownList::update_selection(XI_EVENT* xiev) const
 | 
						|
{
 | 
						|
  if (xiev->v.rec_request.data_rec == selected())
 | 
						|
    xiev->v.rec_request.attrib |= XI_ATR_SELECTED;
 | 
						|
  else
 | 
						|
    xiev->v.rec_request.attrib &= ~XI_ATR_SELECTED;
 | 
						|
}
 | 
						|
 | 
						|
void TDropDownList::ddl_str_eh(XI_OBJ* itf, XI_EVENT* xiev)
 | 
						|
{
 | 
						|
   TDropDownList* ddl = (TDropDownList*)xi_get_app_data(itf);
 | 
						|
   const char* row = NULL;
 | 
						|
   long rec = 0l;
 | 
						|
 | 
						|
   if (!ddl->is_open()) return;
 | 
						|
 | 
						|
   switch(xiev->type)
 | 
						|
   {
 | 
						|
     case XIE_CELL_REQUEST:
 | 
						|
       rec = xiev->v.cell_request.rec;
 | 
						|
       row = ddl->item((int)rec);
 | 
						|
       strncpy(xiev->v.cell_request.s, (char *)row, xiev->v.cell_request.len);
 | 
						|
       xiev->v.cell_request.s[xiev->v.cell_request.len - 1] = '\0';
 | 
						|
       break;
 | 
						|
     case XIE_GET_FIRST:
 | 
						|
       if (ddl->items() == 0)
 | 
						|
         xiev->refused = TRUE;
 | 
						|
       else
 | 
						|
       {
 | 
						|
         xiev->v.rec_request.data_rec = ddl->items() * xiev->v.rec_request.percent/100;
 | 
						|
         ddl->update_selection(xiev);
 | 
						|
       }
 | 
						|
       break;
 | 
						|
     case XIE_GET_LAST:
 | 
						|
       xiev->v.rec_request.data_rec = ddl->items() - 1;
 | 
						|
       ddl->update_selection(xiev);
 | 
						|
       break;
 | 
						|
     case XIE_GET_NEXT:
 | 
						|
       if (xiev->v.rec_request.spec_rec >= ddl->items()-1)
 | 
						|
         xiev->refused = TRUE;
 | 
						|
       else
 | 
						|
       {
 | 
						|
         xiev->v.rec_request.data_rec = xiev->v.rec_request.spec_rec + 1;
 | 
						|
         ddl->update_selection(xiev);
 | 
						|
       }  
 | 
						|
       break;
 | 
						|
     case XIE_GET_PREV:
 | 
						|
       if (xiev->v.rec_request.spec_rec <= 0)
 | 
						|
         xiev->refused = TRUE;
 | 
						|
       else
 | 
						|
       {
 | 
						|
         xiev->v.rec_request.data_rec = xiev->v.rec_request.spec_rec - 1;
 | 
						|
         ddl->update_selection(xiev);
 | 
						|
       }  
 | 
						|
       break;
 | 
						|
     case XIE_GET_PERCENT:
 | 
						|
       if (ddl->items() > 1)
 | 
						|
         xiev->v.get_percent.percent = int((xiev->v.get_percent.record * 100L)/(ddl->items()-1));
 | 
						|
       break;
 | 
						|
     case XIE_DBL_CELL:
 | 
						|
       ddl->select((int)(ddl->row2rec(xiev->v.xi_obj->v.cell.row)));
 | 
						|
       ddl->close();
 | 
						|
       break;
 | 
						|
     case XIE_SELECT:      
 | 
						|
       if (xiev->v.xi_obj->type == XIT_ROW)
 | 
						|
       {
 | 
						|
         const long rec = ddl->row2rec(xiev->v.xi_obj->v.row);
 | 
						|
         ddl->select((int)rec);
 | 
						|
       }    
 | 
						|
       break;
 | 
						|
     case XIE_XVT_EVENT:
 | 
						|
       if ((xiev->v.xvte.type == E_FOCUS && xiev->v.xvte.v.active == FALSE) || 
 | 
						|
           xiev->v.xvte.type == E_MOUSE_UP)
 | 
						|
       {
 | 
						|
         ddl->close();      
 | 
						|
         if (xiev->v.xvte.type == E_FOCUS)
 | 
						|
           _button_blocked = TRUE;
 | 
						|
       }  
 | 
						|
       else if (xiev->v.xvte.type == E_CHAR)
 | 
						|
       {
 | 
						|
         const KEY k = xiev->v.xvte.v.chr.ch;
 | 
						|
         if (k == K_ENTER || k == K_ESC)
 | 
						|
           ddl->close();
 | 
						|
         else
 | 
						|
         {
 | 
						|
           if (k >= ' ' && k <= 'z')
 | 
						|
             ddl->select_by_initial(k);
 | 
						|
         }    
 | 
						|
       }
 | 
						|
       break;
 | 
						|
     case XIE_CHAR_CELL:   // TBI: questa e' copiata da edit
 | 
						|
        break;
 | 
						|
     default:
 | 
						|
       break;
 | 
						|
   }
 | 
						|
}
 | 
						|
 | 
						|
void TDropDownList::close()
 | 
						|
{
 | 
						|
  if (_open)
 | 
						|
  {
 | 
						|
    _open = _displayed = FALSE;
 | 
						|
    xvt_vobj_destroy(xi_get_window(_xi_lst->itf));
 | 
						|
    xvt_dwin_update (xi_get_window(_obj->itf));
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
bool TDropDownList::select(int i, bool force)
 | 
						|
{
 | 
						|
  if (force || i != _selected)
 | 
						|
  {
 | 
						|
    _selected = i;
 | 
						|
 | 
						|
    if (_obj->type == XIT_FIELD)
 | 
						|
    {
 | 
						|
      xi_set_text(_obj, (char*)_values.get(i));
 | 
						|
      TListbox_control* listbox = (TListbox_control *)xi_get_app_data(_obj);
 | 
						|
      listbox->notify_key(K_SPACE);
 | 
						|
    }
 | 
						|
    else
 | 
						|
      xi_set_text(_obj, (char*)_codes.get(i));
 | 
						|
 | 
						|
    if (force && is_open())
 | 
						|
      xi_scroll_rec(_xi_lst, i, FOCUS_COLOR, XI_ATR_ENABLED | XI_ATR_SELECTED, 0);
 | 
						|
 
 | 
						|
    return TRUE;
 | 
						|
  }
 | 
						|
 | 
						|
  return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
bool TDropDownList::select_by_initial(char c)
 | 
						|
{
 | 
						|
  const int tot = _values.items();
 | 
						|
  int i = _selected;
 | 
						|
  c = toupper(c);
 | 
						|
  while(TRUE)
 | 
						|
  {
 | 
						|
    i++;
 | 
						|
    if (i >= tot) 
 | 
						|
      i = 0;
 | 
						|
    if (i == _selected)
 | 
						|
      break;          
 | 
						|
    const char p = toupper(*(_values.get(i)));
 | 
						|
    if (p == c)
 | 
						|
      break;
 | 
						|
  }
 | 
						|
 | 
						|
  bool ok = FALSE;
 | 
						|
  if (i != selected())
 | 
						|
  {                                
 | 
						|
    if (is_open())
 | 
						|
    {                                   
 | 
						|
      const int oldsel = selected();
 | 
						|
 | 
						|
      // Scrolla alla selezione corrente
 | 
						|
      xi_scroll_rec(_xi_lst, i, FOCUS_COLOR, XI_ATR_SELECTED | XI_ATR_ENABLED, 0);
 | 
						|
      
 | 
						|
      const int r = rec2row(oldsel);
 | 
						|
      if (r >= 0)
 | 
						|
      {
 | 
						|
        XI_OBJ riga; XI_MAKE_ROW(&riga, _xi_lst, r);
 | 
						|
        long attr = xi_get_attrib(&riga);
 | 
						|
        attr &= ~XI_ATR_SELECTED;
 | 
						|
        xi_set_attrib(&riga, attr);
 | 
						|
        xi_dequeue();
 | 
						|
      }
 | 
						|
    
 | 
						|
    }  
 | 
						|
    ok = select(i);
 | 
						|
  }  
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
bool TDropDownList::select_by_ofs(int i)
 | 
						|
{
 | 
						|
  i += _selected;
 | 
						|
  if (i >= 0 && i < _values.items())
 | 
						|
    return select(i);
 | 
						|
  return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
TDropDownList::TDropDownList(XI_OBJ* o, const char* codes, const char* values)
 | 
						|
  : _obj(o), _codes(codes), _values(values),
 | 
						|
    _open(FALSE), _xi_lst(NULL), _displayed(FALSE), _selected(0)
 | 
						|
{                       
 | 
						|
  if (o->type == XIT_CELL)
 | 
						|
  {
 | 
						|
    const char* val = xi_get_text(o, NULL, -1);
 | 
						|
    _selected = _codes.get_pos(val);
 | 
						|
    if (_selected < 0)
 | 
						|
      _selected = 0;
 | 
						|
  }  
 | 
						|
}
 | 
						|
 | 
						|
void TDropDownList::set_values(const char* c, const char* v)
 | 
						|
{
 | 
						|
  _codes = c;
 | 
						|
  _values = v;
 | 
						|
} 
 | 
						|
 | 
						|
int TDropDownList::calc_min_width()
 | 
						|
{
 | 
						|
  int len = 1;
 | 
						|
  for (const char* v = _values.get(0); v; v = _values.get())
 | 
						|
  {
 | 
						|
    const int l = strlen(v);
 | 
						|
    if (l > len) len = l;
 | 
						|
  }
 | 
						|
  
 | 
						|
  return len * XI_FU_MULTIPLE;
 | 
						|
}
 | 
						|
 | 
						|
void TDropDownList::open()
 | 
						|
{
 | 
						|
  if (_open) return;
 | 
						|
  
 | 
						|
  XI_OBJ_DEF* itfdef = xi_create_itf_def(ITF_CID, (XI_EVENT_HANDLER)ddl_str_eh, NULL, "",
 | 
						|
                                         (long)this);
 | 
						|
  itfdef->v.itf->automatic_back_color = TRUE;
 | 
						|
  
 | 
						|
  const int hei = items() <= 1 ? 2*XI_FU_MULTIPLE + 1 : (min(6,items()) * XI_FU_MULTIPLE) + 1;
 | 
						|
  XI_OBJ_DEF* lstdef = xi_add_list_def(itfdef, _obj->cid+1000, 0, 0, hei,
 | 
						|
                                       XI_ATR_ENABLED|XI_ATR_VISIBLE, 
 | 
						|
                                       FOCUS_COLOR, FOCUS_BACK_COLOR,
 | 
						|
                                       DISABLED_COLOR, DISABLED_BACK_COLOR, 
 | 
						|
                                       FOCUS_COLOR, 0);
 | 
						|
  XI_LIST_DEF* ld = lstdef->v.list;
 | 
						|
  ld->active_back_color = FOCUS_BACK_COLOR;
 | 
						|
  ld->scroll_bar = items() > 6;
 | 
						|
  ld->no_heading = TRUE;
 | 
						|
  ld->no_horz_lines = TRUE;
 | 
						|
//  ld->no_vert_lines = TRUE;
 | 
						|
  ld->resize_with_window = TRUE;
 | 
						|
  ld->single_select = TRUE;
 | 
						|
  
 | 
						|
  // compute size in pixel of field (with button enclosed)
 | 
						|
  RCT r; xi_get_rect(_obj, &r);
 | 
						|
  
 | 
						|
  // Larghezza in pixel dell'edit field
 | 
						|
  int len = r.right - r.left;
 | 
						|
  if (lstdef->v.list->scroll_bar) 
 | 
						|
  {    
 | 
						|
    // Larghezza in pixel del bottone
 | 
						|
    const int bw = int(_obj->itf->v.itf->fu_height * XI_FU_MULTIPLE / _obj->itf->v.itf->fu_width);
 | 
						|
    len -= bw;
 | 
						|
  }                               
 | 
						|
  // Larghezza in form units dell'edit field 
 | 
						|
  len = len * XI_FU_MULTIPLE / _obj->itf->v.itf->fu_width - 2;
 | 
						|
  
 | 
						|
  if (_obj->type == XIT_CELL)
 | 
						|
  {
 | 
						|
    const int m = calc_min_width();
 | 
						|
    if (len < m) 
 | 
						|
    {
 | 
						|
      len = m;
 | 
						|
      r.right = r.left + m * _obj->itf->v.itf->fu_width / XI_FU_MULTIPLE;
 | 
						|
    }  
 | 
						|
  }
 | 
						|
 | 
						|
  XI_OBJ_DEF* coldef = xi_add_column_def(lstdef, _obj->cid+2000,
 | 
						|
                         XI_ATR_VISIBLE|XI_ATR_ENABLED|XI_ATR_READONLY|XI_ATR_SELECTABLE,
 | 
						|
                         0, len, 80, "");
 | 
						|
 | 
						|
  RCT l; xi_get_def_rect(lstdef, &l);
 | 
						|
  PNT p; p.h = r.left;
 | 
						|
  WINDOW pwin = xi_get_window(_obj->itf);
 | 
						|
  RCT w; xvt_vobj_get_client_rect(pwin, &w);
 | 
						|
  // place rectangle
 | 
						|
  if (r.bottom + l.bottom - l.top <= w.bottom)
 | 
						|
    p.v = r.bottom;
 | 
						|
  else
 | 
						|
  {
 | 
						|
    p.v = r.top - l.bottom - l.top;
 | 
						|
    if (p.v < w.top) p.v = w.top;
 | 
						|
  }
 | 
						|
  RCT wr;
 | 
						|
  wr.left = p.h; wr.top = p.v;
 | 
						|
  xi_get_def_rect(lstdef, &l);
 | 
						|
  wr.right  = r.right; // wr.left + (l.right - l.left) -1;
 | 
						|
  wr.bottom = wr.top + l.bottom - l.top;
 | 
						|
  const int delta_x = _obj->itf->v.itf->delta_x;
 | 
						|
  const int delta_y = _obj->itf->v.itf->delta_y;
 | 
						|
  wr.left   -= delta_x;
 | 
						|
  wr.right  -= delta_x;
 | 
						|
  wr.top    -= delta_y;
 | 
						|
  wr.bottom -= delta_y;
 | 
						|
 | 
						|
  WINDOW win = xvt_win_create(W_PLAIN, &wr, "", 0, pwin, WSF_NO_MENUBAR, EM_ALL,
 | 
						|
                             (EVENT_HANDLER)xi_event, 0L);
 | 
						|
  itfdef->v.itf->win  = win;
 | 
						|
  itfdef->v.itf->rctp = ≀
 | 
						|
  XI_OBJ* itfobj = xi_create(NULL, itfdef);
 | 
						|
  xi_tree_free(itfdef);
 | 
						|
 | 
						|
  CHECK(itfobj != NULL, "Oggetto del cazzo!");
 | 
						|
 | 
						|
  _xi_lst = xi_get_obj(itfobj, _obj->cid+1000);
 | 
						|
 | 
						|
  CHECK(_xi_lst != NULL, "Lista del cazzo!");
 | 
						|
 | 
						|
  _open = TRUE;
 | 
						|
  xi_cell_request(_xi_lst);
 | 
						|
  xvt_scr_set_focus_vobj(win);
 | 
						|
  xvt_vobj_raise(win);
 | 
						|
  _displayed = TRUE;
 | 
						|
 | 
						|
  select(_selected, TRUE);
 | 
						|
 | 
						|
  xi_dequeue();
 | 
						|
}
 | 
						|
 | 
						|
// ------------------------------------------------------------------
 | 
						|
 | 
						|
bool TListbox_control::event_handler(XI_OBJ* itf, XI_EVENT* xiev)
 | 
						|
{
 | 
						|
  bool ok = TRUE;
 | 
						|
  switch (xiev->type)
 | 
						|
  {
 | 
						|
    case XIE_DBL_FIELD:
 | 
						|
    case XIE_BUTTON:
 | 
						|
      if (!_ddl->is_open() && !_button_blocked)
 | 
						|
        _ddl->open();
 | 
						|
      break;
 | 
						|
    case XIE_CHAR_FIELD:
 | 
						|
      {
 | 
						|
        const KEY k = xiev_to_key(xiev);
 | 
						|
        if (k >= ' ' && k <= 'z')
 | 
						|
          _ddl->select_by_initial(k);
 | 
						|
        else if (k == K_F9)
 | 
						|
          _ddl->open();
 | 
						|
        else if (k == K_RIGHT)   // poor man's substitute for down arrow
 | 
						|
          _ddl->select_by_ofs(1);
 | 
						|
        else if (k == K_LEFT)   // poor man's substitute for up arrow
 | 
						|
          _ddl->select_by_ofs(-1);                                      
 | 
						|
        else if (k == K_F2 || k == K_F11 || k == K_F12)
 | 
						|
          notify_key(k);
 | 
						|
        xiev->refused = TRUE;
 | 
						|
      }
 | 
						|
      break;
 | 
						|
    case XIE_CHG_FIELD:
 | 
						|
      // Ignore changes: they are notified by the drop-down list
 | 
						|
      break;
 | 
						|
    default:
 | 
						|
      ok =  TField_control::event_handler(itf, xiev);
 | 
						|
      break;
 | 
						|
  }
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
void TListbox_control::set_values(const char* cod, const char* val)
 | 
						|
{
 | 
						|
  _ddl->set_values(cod, val);
 | 
						|
  if (selected() >= items())
 | 
						|
    _ddl->select(0, TRUE);
 | 
						|
  else
 | 
						|
    _ddl->select(selected(), TRUE);
 | 
						|
}
 | 
						|
 | 
						|
TListbox_control::TListbox_control(WINDOW win, short cid,
 | 
						|
                                   short left, short top, short width,
 | 
						|
                                   const char* flags, const char* text,
 | 
						|
                                   const char* codes, const char* values)
 | 
						|
{
 | 
						|
   create(win, cid, left, top, width , 1, width, flags, text, TRUE);
 | 
						|
   _ddl = new TDropDownList(_obj, codes, values);
 | 
						|
  _ddl->select(0, TRUE);
 | 
						|
}
 | 
						|
 | 
						|
TListbox_control::~TListbox_control()
 | 
						|
{
 | 
						|
  delete _ddl;
 | 
						|
}
 |