Patch level : 12.0
Files correlati : Aggiunta TVariable_automask git-svn-id: svn://10.65.10.50/branches/R_10_00@23463 c028cbd2-c16b-5b4b-a496-9718f37d4682
This commit is contained in:
parent
380ea39b1e
commit
f1c9bb7e4c
@ -1,183 +1,363 @@
|
||||
#include <automask.h>
|
||||
|
||||
bool TAutomask::error_box(const char* fmt, ...)
|
||||
{
|
||||
TString message(1024);
|
||||
char* msg = message.get_buffer();
|
||||
va_list argptr;
|
||||
va_start(argptr, fmt);
|
||||
vsnprintf_s(msg, message.size(), _TRUNCATE, fmt, argptr);
|
||||
va_end(argptr);
|
||||
|
||||
if (is_sheetmask() && !is_running())
|
||||
get_sheet()->error_box(msg);
|
||||
else
|
||||
post_error_message(msg, 3);
|
||||
return false;
|
||||
}
|
||||
|
||||
TField_event TAutomask::key2event(TMask_field& f, KEY key) const
|
||||
{
|
||||
const TMask& wm = f.mask();
|
||||
TField_event fe = fe_null;
|
||||
switch (key)
|
||||
{
|
||||
case K_TAB:
|
||||
if (f.is_edit())
|
||||
{
|
||||
if (wm.get_sheet())
|
||||
{
|
||||
if (wm.is_running())
|
||||
{
|
||||
if (f.focusdirty())
|
||||
fe = fe_modify;
|
||||
}
|
||||
else
|
||||
{
|
||||
fe = f.focusdirty() ? fe_modify : fe_init;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (wm.is_running())
|
||||
{
|
||||
if (f.focusdirty())
|
||||
fe = fe_modify;
|
||||
}
|
||||
else
|
||||
fe = fe_init;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case K_SPACE:
|
||||
if (f.is_edit())
|
||||
{
|
||||
if (wm.is_running())
|
||||
fe = fe_edit;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (f.is_kind_of(CLASS_BUTTON_FIELD) || f.is_kind_of(CLASS_BUTTON_TOOL))
|
||||
fe = fe_button; else
|
||||
if (f.is_kind_of(CLASS_TREE_FIELD))
|
||||
fe = wm.is_running() ? fe_modify : fe_init;
|
||||
else
|
||||
fe = f.focusdirty() ? fe_modify : fe_init;
|
||||
}
|
||||
break;
|
||||
case K_CTRL+K_SPACE:
|
||||
if (f.is_kind_of(CLASS_TREE_FIELD))
|
||||
fe = fe_button;
|
||||
break;
|
||||
case K_ENTER:
|
||||
fe = fe_close;
|
||||
break;
|
||||
case K_F8:
|
||||
fe = fe_magic;
|
||||
break;
|
||||
case K_F9:
|
||||
if (f.is_edit())
|
||||
fe = fe_button;
|
||||
break;
|
||||
case K_F11:
|
||||
fe = fe_info;
|
||||
break;
|
||||
default:
|
||||
fe = fe_null;
|
||||
break;
|
||||
}
|
||||
return fe;
|
||||
}
|
||||
|
||||
bool TAutomask::universal_handler(TMask_field& f, KEY key)
|
||||
{
|
||||
TOperable_field& of = (TOperable_field&)f;
|
||||
TAutomask& am = (TAutomask&)of.mask();
|
||||
const TField_event fe = am.key2event(of, key);
|
||||
return fe == fe_null ? true : am.on_field_event(of, fe, 0);
|
||||
}
|
||||
|
||||
bool TAutomask::insheet_universal_handler(TMask_field& f, KEY key)
|
||||
{
|
||||
TMask& m = f.mask();
|
||||
TSheet_field& s = *m.get_sheet();
|
||||
TAutomask& am = (TAutomask&)s.mask();
|
||||
|
||||
TOperable_field& of = (TOperable_field&)f;
|
||||
TField_event fe = am.key2event(of, key);
|
||||
return fe == fe_null ? true : am.on_field_event(of, fe, m.number());
|
||||
}
|
||||
|
||||
|
||||
bool TAutomask::universal_notifier(TSheet_field& s, int row, KEY key)
|
||||
{
|
||||
TField_event fe = fe_null;
|
||||
switch (key)
|
||||
{
|
||||
case K_INS:
|
||||
fe = se_query_add;
|
||||
break;
|
||||
case K_CTRL+K_INS:
|
||||
fe = se_notify_add;
|
||||
break;
|
||||
case K_DEL:
|
||||
fe = se_query_del;
|
||||
break;
|
||||
case K_CTRL+K_DEL:
|
||||
fe = se_notify_del;
|
||||
break;
|
||||
case K_TAB:
|
||||
fe = se_enter;
|
||||
break;
|
||||
case K_CTRL+K_TAB:
|
||||
fe = se_leave;
|
||||
break;
|
||||
case K_SPACE:
|
||||
fe = se_query_modify;
|
||||
break;
|
||||
case K_ENTER:
|
||||
fe = se_notify_modify;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
TAutomask& wm = (TAutomask&)s.mask();
|
||||
return fe == fe_null ? true : wm.on_field_event(s, fe, row);
|
||||
}
|
||||
|
||||
void TAutomask::set_handlers()
|
||||
{
|
||||
for (int i = fields()-1; i >= 0; i--)
|
||||
{
|
||||
TMask_field& f = fld(i);
|
||||
if (f.is_operable())
|
||||
{
|
||||
f.set_handler(universal_handler);
|
||||
if (f.is_sheet())
|
||||
{
|
||||
((TSheet_field&)f).set_notify(universal_notifier);
|
||||
|
||||
TMask& m = ((TSheet_field&)f).sheet_mask();
|
||||
for (int j = m.fields()-1; j >= 0; j--)
|
||||
{
|
||||
TMask_field& g = m.fld(j);
|
||||
if (g.is_operable())
|
||||
g.set_handler(insheet_universal_handler);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TAutomask::TAutomask(const char* name, int num)
|
||||
: TMask(name, num)
|
||||
{
|
||||
set_handlers();
|
||||
}
|
||||
|
||||
TAutomask::TAutomask(const char* title, int pages, int cols, int rows, int xpos, int ypos)
|
||||
: TMask(title, pages, cols, rows, xpos, ypos)
|
||||
{
|
||||
}
|
||||
#include <automask.h>
|
||||
|
||||
bool TAutomask::error_box(const char* fmt, ...)
|
||||
{
|
||||
TString message(1024);
|
||||
char* msg = message.get_buffer();
|
||||
va_list argptr;
|
||||
va_start(argptr, fmt);
|
||||
vsnprintf_s(msg, message.size(), _TRUNCATE, fmt, argptr);
|
||||
va_end(argptr);
|
||||
|
||||
if (is_sheetmask() && !is_running())
|
||||
get_sheet()->error_box(msg);
|
||||
else
|
||||
post_error_message(msg, 3);
|
||||
return false;
|
||||
}
|
||||
|
||||
TField_event TAutomask::key2event(TMask_field& f, KEY key) const
|
||||
{
|
||||
const TMask& wm = f.mask();
|
||||
TField_event fe = fe_null;
|
||||
switch (key)
|
||||
{
|
||||
case K_TAB:
|
||||
if (f.is_edit())
|
||||
{
|
||||
if (wm.get_sheet())
|
||||
{
|
||||
if (wm.is_running())
|
||||
{
|
||||
if (f.focusdirty())
|
||||
fe = fe_modify;
|
||||
}
|
||||
else
|
||||
{
|
||||
fe = f.focusdirty() ? fe_modify : fe_init;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (wm.is_running())
|
||||
{
|
||||
if (f.focusdirty())
|
||||
fe = fe_modify;
|
||||
}
|
||||
else
|
||||
fe = fe_init;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case K_SPACE:
|
||||
if (f.is_edit())
|
||||
{
|
||||
if (wm.is_running())
|
||||
fe = fe_edit;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (f.is_kind_of(CLASS_BUTTON_FIELD) || f.is_kind_of(CLASS_BUTTON_TOOL))
|
||||
fe = fe_button; else
|
||||
if (f.is_kind_of(CLASS_TREE_FIELD))
|
||||
fe = wm.is_running() ? fe_modify : fe_init;
|
||||
else
|
||||
fe = f.focusdirty() ? fe_modify : fe_init;
|
||||
}
|
||||
break;
|
||||
case K_CTRL+K_SPACE:
|
||||
if (f.is_kind_of(CLASS_TREE_FIELD))
|
||||
fe = fe_button;
|
||||
break;
|
||||
case K_ENTER:
|
||||
fe = fe_close;
|
||||
break;
|
||||
case K_F8:
|
||||
fe = fe_magic;
|
||||
break;
|
||||
case K_F9:
|
||||
if (f.is_edit())
|
||||
fe = fe_button;
|
||||
break;
|
||||
case K_F11:
|
||||
fe = fe_info;
|
||||
break;
|
||||
default:
|
||||
fe = fe_null;
|
||||
break;
|
||||
}
|
||||
return fe;
|
||||
}
|
||||
|
||||
bool TAutomask::universal_handler(TMask_field& f, KEY key)
|
||||
{
|
||||
TOperable_field& of = (TOperable_field&)f;
|
||||
TAutomask& am = (TAutomask&)of.mask();
|
||||
const TField_event fe = am.key2event(of, key);
|
||||
return fe == fe_null ? true : am.on_field_event(of, fe, 0);
|
||||
}
|
||||
|
||||
bool TAutomask::insheet_universal_handler(TMask_field& f, KEY key)
|
||||
{
|
||||
TMask& m = f.mask();
|
||||
TSheet_field& s = *m.get_sheet();
|
||||
TAutomask& am = (TAutomask&)s.mask();
|
||||
|
||||
TOperable_field& of = (TOperable_field&)f;
|
||||
TField_event fe = am.key2event(of, key);
|
||||
return fe == fe_null ? true : am.on_field_event(of, fe, m.number());
|
||||
}
|
||||
|
||||
|
||||
bool TAutomask::universal_notifier(TSheet_field& s, int row, KEY key)
|
||||
{
|
||||
TField_event fe = fe_null;
|
||||
switch (key)
|
||||
{
|
||||
case K_INS:
|
||||
fe = se_query_add;
|
||||
break;
|
||||
case K_CTRL+K_INS:
|
||||
fe = se_notify_add;
|
||||
break;
|
||||
case K_DEL:
|
||||
fe = se_query_del;
|
||||
break;
|
||||
case K_CTRL+K_DEL:
|
||||
fe = se_notify_del;
|
||||
break;
|
||||
case K_TAB:
|
||||
fe = se_enter;
|
||||
break;
|
||||
case K_CTRL+K_TAB:
|
||||
fe = se_leave;
|
||||
break;
|
||||
case K_SPACE:
|
||||
fe = se_query_modify;
|
||||
break;
|
||||
case K_ENTER:
|
||||
fe = se_notify_modify;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
TAutomask& wm = (TAutomask&)s.mask();
|
||||
return fe == fe_null ? true : wm.on_field_event(s, fe, row);
|
||||
}
|
||||
|
||||
void TAutomask::set_handlers()
|
||||
{
|
||||
for (int i = fields()-1; i >= 0; i--)
|
||||
{
|
||||
TMask_field& f = fld(i);
|
||||
if (f.is_operable())
|
||||
{
|
||||
f.set_handler(universal_handler);
|
||||
if (f.is_sheet())
|
||||
{
|
||||
((TSheet_field&)f).set_notify(universal_notifier);
|
||||
|
||||
TMask& m = ((TSheet_field&)f).sheet_mask();
|
||||
for (int j = m.fields()-1; j >= 0; j--)
|
||||
{
|
||||
TMask_field& g = m.fld(j);
|
||||
if (g.is_operable())
|
||||
g.set_handler(insheet_universal_handler);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TAutomask::TAutomask(const char* name, int num)
|
||||
: TMask(name, num)
|
||||
{
|
||||
set_handlers();
|
||||
}
|
||||
|
||||
TAutomask::TAutomask(const char* title, int pages, int cols, int rows, int xpos, int ypos)
|
||||
: TMask(title, pages, cols, rows, xpos, ypos)
|
||||
{
|
||||
}
|
||||
|
||||
bool TVariable_automask::error_box(const char* fmt, ...)
|
||||
{
|
||||
TString message(1024);
|
||||
char* msg = message.get_buffer();
|
||||
va_list argptr;
|
||||
va_start(argptr, fmt);
|
||||
vsnprintf_s(msg, message.size(), _TRUNCATE, fmt, argptr);
|
||||
va_end(argptr);
|
||||
|
||||
if (is_sheetmask() && !is_running())
|
||||
get_sheet()->error_box(msg);
|
||||
else
|
||||
post_error_message(msg, 3);
|
||||
return false;
|
||||
}
|
||||
|
||||
TField_event TVariable_automask::key2event(TMask_field& f, KEY key) const
|
||||
{
|
||||
const TMask& wm = f.mask();
|
||||
TField_event fe = fe_null;
|
||||
|
||||
switch (key)
|
||||
{
|
||||
case K_TAB:
|
||||
if (f.is_edit())
|
||||
{
|
||||
if (wm.get_sheet())
|
||||
{
|
||||
if (wm.is_running())
|
||||
{
|
||||
if (f.focusdirty())
|
||||
fe = fe_modify;
|
||||
}
|
||||
else
|
||||
{
|
||||
fe = f.focusdirty() ? fe_modify : fe_init;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (wm.is_running())
|
||||
{
|
||||
if (f.focusdirty())
|
||||
fe = fe_modify;
|
||||
}
|
||||
else
|
||||
fe = fe_init;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case K_SPACE:
|
||||
if (f.is_edit())
|
||||
{
|
||||
if (wm.is_running())
|
||||
fe = fe_edit;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (f.is_kind_of(CLASS_BUTTON_FIELD) || f.is_kind_of(CLASS_BUTTON_TOOL))
|
||||
fe = fe_button; else
|
||||
if (f.is_kind_of(CLASS_TREE_FIELD))
|
||||
fe = wm.is_running() ? fe_modify : fe_init;
|
||||
else
|
||||
fe = f.focusdirty() ? fe_modify : fe_init;
|
||||
}
|
||||
break;
|
||||
case K_CTRL+K_SPACE:
|
||||
if (f.is_kind_of(CLASS_TREE_FIELD))
|
||||
fe = fe_button;
|
||||
break;
|
||||
case K_ENTER:
|
||||
fe = fe_close;
|
||||
break;
|
||||
case K_F8:
|
||||
fe = fe_magic;
|
||||
break;
|
||||
case K_F9:
|
||||
if (f.is_edit())
|
||||
fe = fe_button;
|
||||
break;
|
||||
case K_F11:
|
||||
fe = fe_info;
|
||||
break;
|
||||
default:
|
||||
fe = fe_null;
|
||||
break;
|
||||
}
|
||||
return fe;
|
||||
}
|
||||
|
||||
bool TVariable_automask::universal_handler(TMask_field& f, KEY key)
|
||||
{
|
||||
TOperable_field& of = (TOperable_field&)f;
|
||||
TVariable_automask& am = (TVariable_automask&)of.mask();
|
||||
const TField_event fe = am.key2event(of, key);
|
||||
|
||||
return fe == fe_null ? true : am.on_field_event(of, fe, 0);
|
||||
}
|
||||
|
||||
bool TVariable_automask::insheet_universal_handler(TMask_field& f, KEY key)
|
||||
{
|
||||
TMask& m = f.mask();
|
||||
TSheet_field& s = *m.get_sheet();
|
||||
TVariable_automask& am = (TVariable_automask&)s.mask();
|
||||
TOperable_field& of = (TOperable_field&)f;
|
||||
TField_event fe = am.key2event(of, key);
|
||||
|
||||
return fe == fe_null ? true : am.on_field_event(of, fe, m.number());
|
||||
}
|
||||
|
||||
|
||||
bool TVariable_automask::universal_notifier(TSheet_field& s, int row, KEY key)
|
||||
{
|
||||
TField_event fe = fe_null;
|
||||
|
||||
switch (key)
|
||||
{
|
||||
case K_INS:
|
||||
fe = se_query_add;
|
||||
break;
|
||||
case K_CTRL+K_INS:
|
||||
fe = se_notify_add;
|
||||
break;
|
||||
case K_DEL:
|
||||
fe = se_query_del;
|
||||
break;
|
||||
case K_CTRL+K_DEL:
|
||||
fe = se_notify_del;
|
||||
break;
|
||||
case K_TAB:
|
||||
fe = se_enter;
|
||||
break;
|
||||
case K_CTRL+K_TAB:
|
||||
fe = se_leave;
|
||||
break;
|
||||
case K_SPACE:
|
||||
fe = se_query_modify;
|
||||
break;
|
||||
case K_ENTER:
|
||||
fe = se_notify_modify;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
TVariable_automask& wm = (TVariable_automask&)s.mask();
|
||||
return fe == fe_null ? true : wm.on_field_event(s, fe, row);
|
||||
}
|
||||
|
||||
void TVariable_automask::set_handlers()
|
||||
{
|
||||
for (int i = fields()-1; i >= 0; i--)
|
||||
{
|
||||
TMask_field& f = fld(i);
|
||||
if (f.is_operable())
|
||||
{
|
||||
f.set_handler(universal_handler);
|
||||
if (f.is_sheet())
|
||||
{
|
||||
((TSheet_field&)f).set_notify(universal_notifier);
|
||||
|
||||
TMask& m = ((TSheet_field&)f).sheet_mask();
|
||||
for (int j = m.fields()-1; j >= 0; j--)
|
||||
{
|
||||
TMask_field& g = m.fld(j);
|
||||
if (g.is_operable())
|
||||
g.set_handler(insheet_universal_handler);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TVariable_automask::TVariable_automask(const char* name, int num)
|
||||
: TVariable_mask(name, num)
|
||||
{
|
||||
set_handlers();
|
||||
}
|
||||
|
@ -1,51 +1,78 @@
|
||||
#ifndef __AUTOMASK_H
|
||||
#define __AUTOMASK_H
|
||||
|
||||
#ifndef __DEFMASK_H
|
||||
#include <defmask.h>
|
||||
#endif
|
||||
|
||||
#ifndef __MSKSHEET_H
|
||||
#include <msksheet.h>
|
||||
#endif
|
||||
|
||||
enum TField_event { fe_null = 0,
|
||||
fe_init, fe_modify, fe_button, fe_close,
|
||||
fe_magic, fe_info, fe_edit,
|
||||
se_enter = 10, se_leave,
|
||||
se_query_modify, se_notify_modify,
|
||||
se_query_add, se_notify_add,
|
||||
se_query_del, se_notify_del };
|
||||
|
||||
class TAutomask : public TMask
|
||||
{
|
||||
private:
|
||||
static bool universal_handler(TMask_field& f, KEY k);
|
||||
static bool insheet_universal_handler(TMask_field& f, KEY k);
|
||||
static bool universal_notifier(TSheet_field& f, int row, KEY k);
|
||||
|
||||
protected:
|
||||
void set_handlers();
|
||||
TField_event key2event(TMask_field& f, KEY key) const;
|
||||
|
||||
public:
|
||||
virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly) pure;
|
||||
bool error_box(const char* fmt, ...); // No more f.error_box
|
||||
void set_universal_handler(const short id) { set_handler(id, universal_handler);}
|
||||
void set_insheet_universal_handler(const short sid, const short id) { sfield(sid).sheet_mask().set_handler(id, insheet_universal_handler);}
|
||||
|
||||
TAutomask() { }
|
||||
TAutomask(const char* name, int num = 0);
|
||||
TAutomask(const char* title, int pages, int cols, int rows, int xpos = -1, int ypos = -1);
|
||||
virtual ~TAutomask() { }
|
||||
};
|
||||
|
||||
class TSimpleAutomask : public TAutomask
|
||||
{
|
||||
public:
|
||||
virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly) {return true;}
|
||||
TSimpleAutomask() { }
|
||||
virtual ~TSimpleAutomask() { }
|
||||
};
|
||||
|
||||
#endif
|
||||
#ifndef __AUTOMASK_H
|
||||
#define __AUTOMASK_H
|
||||
|
||||
#ifndef __DEFMASK_H
|
||||
#include <defmask.h>
|
||||
#endif
|
||||
|
||||
#ifndef __MSKSHEET_H
|
||||
#include <msksheet.h>
|
||||
#endif
|
||||
|
||||
#ifndef __VARMASK_H
|
||||
#include <varmask.h>
|
||||
#endif
|
||||
|
||||
|
||||
enum TField_event { fe_null = 0,
|
||||
fe_init, fe_modify, fe_button, fe_close,
|
||||
fe_magic, fe_info, fe_edit,
|
||||
se_enter = 10, se_leave,
|
||||
se_query_modify, se_notify_modify,
|
||||
se_query_add, se_notify_add,
|
||||
se_query_del, se_notify_del };
|
||||
|
||||
class TAutomask : public TMask
|
||||
{
|
||||
private:
|
||||
static bool universal_handler(TMask_field& f, KEY k);
|
||||
static bool insheet_universal_handler(TMask_field& f, KEY k);
|
||||
static bool universal_notifier(TSheet_field& f, int row, KEY k);
|
||||
|
||||
protected:
|
||||
void set_handlers();
|
||||
TField_event key2event(TMask_field& f, KEY key) const;
|
||||
|
||||
public:
|
||||
virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly) pure;
|
||||
bool error_box(const char* fmt, ...); // No more f.error_box
|
||||
void set_universal_handler(const short id) { set_handler(id, universal_handler);}
|
||||
void set_insheet_universal_handler(const short sid, const short id) { sfield(sid).sheet_mask().set_handler(id, insheet_universal_handler);}
|
||||
|
||||
TAutomask() { }
|
||||
TAutomask(const char* name, int num = 0);
|
||||
TAutomask(const char* title, int pages, int cols, int rows, int xpos = -1, int ypos = -1);
|
||||
virtual ~TAutomask() { }
|
||||
};
|
||||
|
||||
class TVariable_automask : public TVariable_mask
|
||||
{
|
||||
private:
|
||||
static bool universal_handler(TMask_field& f, KEY k);
|
||||
static bool insheet_universal_handler(TMask_field& f, KEY k);
|
||||
static bool universal_notifier(TSheet_field& f, int row, KEY k);
|
||||
|
||||
protected:
|
||||
void set_handlers();
|
||||
TField_event key2event(TMask_field& f, KEY key) const;
|
||||
|
||||
public:
|
||||
virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly) pure;
|
||||
bool error_box(const char* fmt, ...); // No more f.error_box
|
||||
void set_universal_handler(const short id) { set_handler(id, universal_handler);}
|
||||
void set_insheet_universal_handler(const short sid, const short id) { sfield(sid).sheet_mask().set_handler(id, insheet_universal_handler);}
|
||||
|
||||
TVariable_automask() { }
|
||||
TVariable_automask(const char* name, int num = 0);
|
||||
virtual ~TVariable_automask() { }
|
||||
};
|
||||
|
||||
class TSimpleAutomask : public TAutomask
|
||||
{
|
||||
public:
|
||||
virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly) {return true;}
|
||||
TSimpleAutomask() { }
|
||||
virtual ~TSimpleAutomask() { }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user