Patch level : 10.0
Files correlati : agalib Ricompilazione Demo : [ ] Commento : Corretto posizionamento bottone di ricerca nel caso di campi piatti (non 3D) Migliorato controllo sulle power stations git-svn-id: svn://10.65.10.50/trunk@18182 c028cbd2-c16b-5b4b-a496-9718f37d4682
This commit is contained in:
parent
7e114ad9e0
commit
7f7e99821d
@ -42,12 +42,62 @@ bool AUTOZOOM = false;
|
|||||||
bool AUTOEND = false;
|
bool AUTOEND = false;
|
||||||
bool NATIVE_CONTROLS = false;
|
bool NATIVE_CONTROLS = false;
|
||||||
int TOOL_SIZE = 24;
|
int TOOL_SIZE = 24;
|
||||||
bool TOOL_TEXT = false;
|
bool TOOL_TEXT = true;
|
||||||
bool EASY_RIDER = true;
|
bool EASY_RIDER = true;
|
||||||
bool ENTER_AS_TAB = false;
|
bool ENTER_AS_TAB = false;
|
||||||
|
|
||||||
HIDDEN bool _button_blocked = false;
|
HIDDEN bool _button_blocked = false;
|
||||||
HIDDEN int _last_mouse_button = 0;
|
HIDDEN int _last_mouse_button = 0;
|
||||||
|
HIDDEN int X_FU_MULTIPLE = 0;
|
||||||
|
HIDDEN int Y_FU_MULTIPLE = 0;
|
||||||
|
HIDDEN const int ITF_CID = 30000;
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////
|
||||||
|
// TDropDownList
|
||||||
|
///////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class TDropDownList : public TObject
|
||||||
|
{
|
||||||
|
XI_OBJ* _obj; // Owner cell or field
|
||||||
|
XI_OBJ* _xi_lst;
|
||||||
|
|
||||||
|
TToken_string _codes;
|
||||||
|
TToken_string _values;
|
||||||
|
|
||||||
|
int _selected;
|
||||||
|
bool _open;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static void ddl_str_eh (XI_OBJ* itf, XI_EVENT* xiev);
|
||||||
|
void update_selection(XI_EVENT* xiev) const;
|
||||||
|
int calc_min_width();
|
||||||
|
|
||||||
|
void create();
|
||||||
|
void destroy();
|
||||||
|
|
||||||
|
long row2rec(int) const;
|
||||||
|
int rec2row(long rec) const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
const int selected() const { return _selected; }
|
||||||
|
void open();
|
||||||
|
void close();
|
||||||
|
bool is_open() const { return _open; }
|
||||||
|
|
||||||
|
const char* item(long i) { const char* s = _values.get(int(i)); return s ? s : ""; }
|
||||||
|
int items() const { return _values.items(); }
|
||||||
|
void set_values(const char* c, const char* v);
|
||||||
|
|
||||||
|
bool select(int i, bool force = false);
|
||||||
|
bool select_by_initial(char c);
|
||||||
|
bool select_by_ofs(int n);
|
||||||
|
|
||||||
|
void on_mouse_down(const PNT& pt);
|
||||||
|
|
||||||
|
TDropDownList(XI_OBJ* o, const TToken_string& codes, const TToken_string& values);
|
||||||
|
virtual ~TDropDownList();
|
||||||
|
};
|
||||||
|
|
||||||
HIDDEN TDropDownList* _cur_ddl = NULL;
|
HIDDEN TDropDownList* _cur_ddl = NULL;
|
||||||
|
|
||||||
short low_get_focus_id(WINDOW win)
|
short low_get_focus_id(WINDOW win)
|
||||||
@ -63,9 +113,6 @@ short low_get_focus_id(WINDOW win)
|
|||||||
return obj->cid;
|
return obj->cid;
|
||||||
}
|
}
|
||||||
|
|
||||||
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 TControl::xiev_to_key(const XI_EVENT* xiev)
|
||||||
{
|
{
|
||||||
@ -1267,17 +1314,14 @@ TGroupbox_control::TGroupbox_control(WINDOW win, short cid,
|
|||||||
def->v.rect->back_color = MASK_BACK_COLOR;
|
def->v.rect->back_color = MASK_BACK_COLOR;
|
||||||
def->v.rect->shadow_color = MASK_DARK_COLOR;
|
def->v.rect->shadow_color = MASK_DARK_COLOR;
|
||||||
|
|
||||||
if (CAMPI_SCAVATI)
|
|
||||||
{
|
|
||||||
const bool erre = strchr(flags, 'R') != NULL;
|
const bool erre = strchr(flags, 'R') != NULL;
|
||||||
if (erre)
|
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
|
change_attrib(XI_ATR_RJUST, false, _obj); // Toglie l'erroneo allineamento a destra del titolo
|
||||||
}
|
|
||||||
}
|
if (CAMPI_SCAVATI)
|
||||||
|
def->v.rect->well = erre; // Mette eventualmente in rilievo il rettangolo
|
||||||
else
|
else
|
||||||
def->v.rect->ridge = true; // Angoli arrotondati
|
def->v.rect->ridge = true; // Angoli arrotondati in caso di stile piatto (!CAMPI_SCAVATI)
|
||||||
|
|
||||||
_rct = xi_create(get_interface(win), def);
|
_rct = xi_create(get_interface(win), def);
|
||||||
CHECKD(_rct, "Can't create Groupbox_control ", cid);
|
CHECKD(_rct, "Can't create Groupbox_control ", cid);
|
||||||
@ -1410,7 +1454,7 @@ void TField_control::create(WINDOW win, short cid,
|
|||||||
const int offset = stx->rct.right - br.left - 1;
|
const int offset = stx->rct.right - br.left - 1;
|
||||||
br.left += offset;
|
br.left += offset;
|
||||||
br.right += offset;
|
br.right += offset;
|
||||||
br.top = stx->rct.top+1;
|
br.top = stx->rct.top + (CAMPI_SCAVATI ? 1 : 0);
|
||||||
br.bottom = stx->rct.bottom;
|
br.bottom = stx->rct.bottom;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2195,8 +2239,10 @@ void TDropDownList::ddl_str_eh(XI_OBJ* itf, XI_EVENT* xiev)
|
|||||||
case XIE_SELECT:
|
case XIE_SELECT:
|
||||||
if (xiev->v.xi_obj->type == XIT_ROW)
|
if (xiev->v.xi_obj->type == XIT_ROW)
|
||||||
{
|
{
|
||||||
const long rec = ddl->row2rec(xiev->v.xi_obj->v.row);
|
const int rec = ddl->row2rec(xiev->v.xi_obj->v.row);
|
||||||
ddl->select(int(rec));
|
ddl->select(rec);
|
||||||
|
if (itf->v.itf->mouse_is_down)
|
||||||
|
ddl->close();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case XIE_XVT_EVENT:
|
case XIE_XVT_EVENT:
|
||||||
@ -2445,9 +2491,8 @@ void TDropDownList::create()
|
|||||||
|
|
||||||
void TDropDownList::open()
|
void TDropDownList::open()
|
||||||
{
|
{
|
||||||
if (_open)
|
if (!_open)
|
||||||
return;
|
{
|
||||||
|
|
||||||
if (_xi_lst != NULL)
|
if (_xi_lst != NULL)
|
||||||
xvt_vobj_set_visible((WINDOW)xi_get_window(_xi_lst->itf), true);
|
xvt_vobj_set_visible((WINDOW)xi_get_window(_xi_lst->itf), true);
|
||||||
else
|
else
|
||||||
@ -2465,8 +2510,52 @@ void TDropDownList::open()
|
|||||||
xi_dequeue();
|
xi_dequeue();
|
||||||
_cur_ddl = this;
|
_cur_ddl = this;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
void TDropDownList::on_mouse_down(const PNT& pt)
|
||||||
|
{
|
||||||
|
if (_open)
|
||||||
|
{
|
||||||
|
RCT rct; xi_get_rect(_obj, (XinRect*)&rct);
|
||||||
|
if (xvt_rect_has_point(&rct, pt))
|
||||||
|
return; // E' nel campo di testo proprietario della lista
|
||||||
|
|
||||||
|
xvt_vobj_get_outer_rect((WINDOW)xi_get_window(_xi_lst->itf), &rct);
|
||||||
|
if (!xvt_rect_has_point(&rct, pt)) // Fuori dalla lista
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TDropDownList::TDropDownList(XI_OBJ* o, const TToken_string& codes, const TToken_string& values)
|
||||||
|
: _obj(o), _xi_lst(NULL), _codes(codes), _values(values), _selected(0), _open(false)
|
||||||
|
{
|
||||||
|
if (o->type == XIT_CELL)
|
||||||
|
{
|
||||||
|
const char* val = xi_get_text(o, NULL, -1);
|
||||||
|
_selected = _codes.get_pos(val);
|
||||||
|
if (_selected < 0)
|
||||||
|
_selected = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TDropDownList::~TDropDownList()
|
||||||
|
{
|
||||||
|
destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int xvtil_drop_down_list(XI_OBJ* field_or_cell, const TToken_string& codes, const TToken_string& values)
|
||||||
|
{
|
||||||
|
TDropDownList ddl(field_or_cell, codes, values);
|
||||||
|
ddl.open();
|
||||||
|
while (ddl.is_open())
|
||||||
|
do_events();
|
||||||
|
return ddl.selected();
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////
|
||||||
|
// TListbox_control
|
||||||
|
///////////////////////////////////////////////////////////
|
||||||
|
|
||||||
bool TListbox_control::event_handler(XI_OBJ* itf, XI_EVENT* xiev)
|
bool TListbox_control::event_handler(XI_OBJ* itf, XI_EVENT* xiev)
|
||||||
{
|
{
|
||||||
@ -2521,43 +2610,6 @@ bool TListbox_control::event_handler(XI_OBJ* itf, XI_EVENT* xiev)
|
|||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TDropDownList::on_mouse_down(const PNT& pt)
|
|
||||||
{
|
|
||||||
if (_open)
|
|
||||||
{
|
|
||||||
RCT rct;
|
|
||||||
xi_get_rect(_obj, (XinRect*)&rct);
|
|
||||||
if (xvt_rect_has_point(&rct, pt))
|
|
||||||
return; // E' nel campo di testo proprietario della lista
|
|
||||||
|
|
||||||
xvt_vobj_get_outer_rect((WINDOW)xi_get_window(_xi_lst->itf), &rct);
|
|
||||||
if (!xvt_rect_has_point(&rct, pt)) // Fuori dalla lista
|
|
||||||
close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TDropDownList::TDropDownList(XI_OBJ* o, const char* codes, const char* values)
|
|
||||||
: _obj(o), _xi_lst(NULL), _codes(codes),
|
|
||||||
_values(values), _selected(0), _open(false)
|
|
||||||
{
|
|
||||||
if (o->type == XIT_CELL)
|
|
||||||
{
|
|
||||||
const char* val = xi_get_text(o, NULL, -1);
|
|
||||||
_selected = _codes.get_pos(val);
|
|
||||||
if (_selected < 0)
|
|
||||||
_selected = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TDropDownList::~TDropDownList()
|
|
||||||
{
|
|
||||||
destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////
|
|
||||||
// TListbox_control
|
|
||||||
///////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
void TListbox_control::set_values(const char* cod, const char* val)
|
void TListbox_control::set_values(const char* cod, const char* val)
|
||||||
{
|
{
|
||||||
_ddl->set_values(cod, val);
|
_ddl->set_values(cod, val);
|
||||||
|
@ -309,50 +309,7 @@ public:
|
|||||||
virtual ~TCheckbutton_control() {}
|
virtual ~TCheckbutton_control() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////
|
class TDropDownList;
|
||||||
// TDropDownList
|
|
||||||
///////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
class TDropDownList : public TObject
|
|
||||||
{
|
|
||||||
XI_OBJ* _obj; // Owner cell or field
|
|
||||||
XI_OBJ* _xi_lst;
|
|
||||||
|
|
||||||
TToken_string _codes;
|
|
||||||
TToken_string _values;
|
|
||||||
|
|
||||||
int _selected;
|
|
||||||
bool _open;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
static void ddl_str_eh (XI_OBJ* itf, XI_EVENT* xiev);
|
|
||||||
void update_selection(XI_EVENT* xiev) const;
|
|
||||||
int calc_min_width();
|
|
||||||
|
|
||||||
void create();
|
|
||||||
void destroy();
|
|
||||||
|
|
||||||
public:
|
|
||||||
const int selected() const { return _selected; }
|
|
||||||
void open();
|
|
||||||
void close();
|
|
||||||
bool is_open() const { return _open; }
|
|
||||||
|
|
||||||
const char* item(long i) { const char* s = _values.get(int(i)); return s ? s : ""; }
|
|
||||||
int items() const { return _values.items(); }
|
|
||||||
long row2rec(int) const;
|
|
||||||
int rec2row(long rec) const;
|
|
||||||
void set_values(const char* c, const char* v);
|
|
||||||
|
|
||||||
bool select(int i, bool force = FALSE);
|
|
||||||
bool select_by_initial(char c);
|
|
||||||
bool select_by_ofs(int n);
|
|
||||||
|
|
||||||
void on_mouse_down(const PNT& pt);
|
|
||||||
|
|
||||||
TDropDownList(XI_OBJ* o, const char* codes, const char* values);
|
|
||||||
virtual ~TDropDownList();
|
|
||||||
};
|
|
||||||
|
|
||||||
class TListbox_control : public TField_control
|
class TListbox_control : public TField_control
|
||||||
{
|
{
|
||||||
@ -379,4 +336,6 @@ public:
|
|||||||
virtual ~TListbox_control();
|
virtual ~TListbox_control();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int xvtil_drop_down_list(XI_OBJ* field_or_cell, const TToken_string& codes, const TToken_string& values);
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -265,9 +265,18 @@ bool TDongle::already_programmed() const
|
|||||||
#ifndef _DEMO_
|
#ifndef _DEMO_
|
||||||
|
|
||||||
void TDongle::set_developer_permissions()
|
void TDongle::set_developer_permissions()
|
||||||
|
{
|
||||||
|
if (_serno == 0 && is_power_station())
|
||||||
{
|
{
|
||||||
_module.set(255); // Last module on key
|
_module.set(255); // Last module on key
|
||||||
_module.set(); // Activate all modules
|
_module.set(); // Activate all modules
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_module.reset(-1);
|
||||||
|
_module.set(0, true);
|
||||||
|
}
|
||||||
|
|
||||||
_shown.reset();
|
_shown.reset();
|
||||||
|
|
||||||
_max_users = 1;
|
_max_users = 1;
|
||||||
|
@ -169,6 +169,8 @@ class TSpreadsheet : public TControl
|
|||||||
int _needs_update;
|
int _needs_update;
|
||||||
// @cmember:(INTERNAL) Numero della riga a cui saltare appena possibile
|
// @cmember:(INTERNAL) Numero della riga a cui saltare appena possibile
|
||||||
int _selection_posted;
|
int _selection_posted;
|
||||||
|
clock_t _ignore_button;
|
||||||
|
|
||||||
// @cmember:(INTERNAL) Dimensioni delle colonne
|
// @cmember:(INTERNAL) Dimensioni delle colonne
|
||||||
int _default_width[MAX_COL];
|
int _default_width[MAX_COL];
|
||||||
// @cmember:(INTERNAL) Bisogna salvare l'ordien delle colonne
|
// @cmember:(INTERNAL) Bisogna salvare l'ordien delle colonne
|
||||||
@ -415,7 +417,7 @@ TSpreadsheet::TSpreadsheet(
|
|||||||
_mask(), _active(true), _notify(NULL),
|
_mask(), _active(true), _notify(NULL),
|
||||||
_edit_field(NULL), _cur_row(0), _cur_rec(0), _cur_col(1),
|
_edit_field(NULL), _cur_row(0), _cur_rec(0), _cur_col(1),
|
||||||
_row_dirty(false), _cell_dirty(false), _check_enabled(TRUE),
|
_row_dirty(false), _cell_dirty(false), _check_enabled(TRUE),
|
||||||
_needs_update(-1), _selection_posted(-1), _save_columns_order(false),
|
_needs_update(-1), _selection_posted(-1), _ignore_button(0), _save_columns_order(false),
|
||||||
_f9_target(NULL), _auto_append(false), _first_nav_column_id(-1),
|
_f9_target(NULL), _auto_append(false), _first_nav_column_id(-1),
|
||||||
_last_nav_column_id(-1)
|
_last_nav_column_id(-1)
|
||||||
{
|
{
|
||||||
@ -1200,7 +1202,8 @@ bool TSpreadsheet::event_handler(XI_OBJ* itf, XI_EVENT *xiev)
|
|||||||
{
|
{
|
||||||
on_idle(); // Termina tutti gli eventuali update in corso
|
on_idle(); // Termina tutti gli eventuali update in corso
|
||||||
|
|
||||||
XI_CELL_DATA& cell = xiev->v.xi_obj->v.cell;
|
const XI_CELL_DATA& cell = xiev->v.xi_obj->v.cell;
|
||||||
|
|
||||||
int num;
|
int num;
|
||||||
XI_OBJ** column = xi_get_member_list(_obj, &num);
|
XI_OBJ** column = xi_get_member_list(_obj, &num);
|
||||||
CHECK(cell.column < num, "Bad column");
|
CHECK(cell.column < num, "Bad column");
|
||||||
@ -1210,7 +1213,11 @@ bool TSpreadsheet::event_handler(XI_OBJ* itf, XI_EVENT *xiev)
|
|||||||
if (!cell_disabled(rec, col))
|
if (!cell_disabled(rec, col))
|
||||||
{
|
{
|
||||||
if (xi_move_focus(xiev->v.xi_obj))
|
if (xi_move_focus(xiev->v.xi_obj))
|
||||||
|
{
|
||||||
|
if (clock() > _ignore_button)
|
||||||
dispatch_e_char(parent(), K_F9);
|
dispatch_e_char(parent(), K_F9);
|
||||||
|
_ignore_button = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1382,7 +1389,8 @@ bool TSpreadsheet::event_handler(XI_OBJ* itf, XI_EVENT *xiev)
|
|||||||
if (_cur_rec < items() && notify(_cur_rec, K_TAB))
|
if (_cur_rec < items() && notify(_cur_rec, K_TAB))
|
||||||
{
|
{
|
||||||
/* Guy! str2mask(_cur_rec); */
|
/* Guy! str2mask(_cur_rec); */
|
||||||
_row_dirty = _cell_dirty = FALSE;
|
_row_dirty = _cell_dirty = false;
|
||||||
|
_ignore_button = clock()+250; // Ignora i click sui bottoni (invisibili) per un quarto di secondo
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1539,13 +1547,10 @@ bool TSpreadsheet::event_handler(XI_OBJ* itf, XI_EVENT *xiev)
|
|||||||
if (k == K_F9 && _edit_field->is_kind_of(CLASS_LIST_FIELD)) // list
|
if (k == K_F9 && _edit_field->is_kind_of(CLASS_LIST_FIELD)) // list
|
||||||
{
|
{
|
||||||
XI_OBJ cell; XI_MAKE_CELL(&cell, _obj, _cur_row, _cur_col);
|
XI_OBJ cell; XI_MAKE_CELL(&cell, _obj, _cur_row, _cur_col);
|
||||||
// droppa giu'
|
const TList_field& lst = (const TList_field&)(*_edit_field);
|
||||||
TList_field& lst = (TList_field&)(*_edit_field);
|
TToken_string codes = lst.get_codes();
|
||||||
TDropDownList ddl(&cell, lst.get_codes(), lst.get_values());
|
TToken_string values = lst.get_values();
|
||||||
ddl.open();
|
xvtil_drop_down_list(&cell, codes, values);
|
||||||
while (ddl.is_open())
|
|
||||||
do_events();
|
|
||||||
// sdroppa su
|
|
||||||
copy_cell2field();
|
copy_cell2field();
|
||||||
}
|
}
|
||||||
else // edit_field
|
else // edit_field
|
||||||
|
@ -576,11 +576,9 @@ istream & eatwhite(istream & i)
|
|||||||
|
|
||||||
const TString& get_hostname()
|
const TString& get_hostname()
|
||||||
{
|
{
|
||||||
TString& tmp = get_tmp_string(256);
|
TString& tmp = get_tmp_string(80);
|
||||||
char* buff = tmp.get_buffer();
|
xvt_sys_get_host_name(tmp.get_buffer(), tmp.size());
|
||||||
if (xvt_sys_get_host_name(buff, tmp.size()))
|
|
||||||
return tmp;
|
return tmp;
|
||||||
return EMPTY_STRING;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
long daytime()
|
long daytime()
|
||||||
@ -591,16 +589,20 @@ long daytime()
|
|||||||
|
|
||||||
bool is_power_station()
|
bool is_power_station()
|
||||||
{
|
{
|
||||||
bool ok = false;
|
static BOOLEAN ps = -1;
|
||||||
if (dongle().hardware() != _dongle_network)
|
if (ps < 0)
|
||||||
|
{
|
||||||
|
ps = FALSE;
|
||||||
|
if (dongle().number() == 0 && dongle().hardware() != _dongle_network)
|
||||||
{
|
{
|
||||||
const char* const ranger[] = { "ANTARES", "ARCHIMEDE", "BATMOBILE", "KIRK",
|
const char* const ranger[] = { "ANTARES", "ARCHIMEDE", "BATMOBILE", "KIRK",
|
||||||
"MOBILE", "PICARD", "SPOCK", "SULU", "UHURA", NULL };
|
"MOBILE", "PICARD", "SPOCK", "SULU", "UHURA", NULL };
|
||||||
const TString& hostname = get_hostname();
|
const TString& hostname = get_hostname();
|
||||||
for (int i = 0; ranger[i] && !ok; i++)
|
for (int i = 0; ranger[i] && !ps; i++)
|
||||||
ok = hostname.compare(ranger[i], -1, true) == 0;
|
ps = hostname.compare(ranger[i], -1, true) == 0;
|
||||||
}
|
}
|
||||||
return ok;
|
}
|
||||||
|
return ps != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool expand_sys_vars(TString& str)
|
bool expand_sys_vars(TString& str)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user