mirror of
https://github.com/gnosygnu/xowa.git
synced 2026-03-02 03:49:30 +00:00
v2.5.4.1
This commit is contained in:
@@ -16,7 +16,7 @@ You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.gfml; import gplx.*;
|
||||
import gplx.lists.*;/*HashAdp_list*/
|
||||
import gplx.lists.*;/*Hash_adp_list*/
|
||||
interface GfmlPragma {
|
||||
String KeyOfPragma();
|
||||
void Exec(GfmlBldr bldr, GfmlNde pragmaNde);
|
||||
@@ -26,7 +26,7 @@ class GfmlPragmaMgr {
|
||||
public void Pragmas_add(GfmlPragma cmd) {pragmas.Add(cmd.KeyOfPragma(), cmd);}
|
||||
public boolean Pragmas_compile(String ndeName, GfmlBldr bldr) {
|
||||
if (pragmas.Count() == 0) return false;
|
||||
GfmlPragma cmd = (GfmlPragma)pragmas.Fetch(ndeName); if (cmd == null) return false;
|
||||
GfmlPragma cmd = (GfmlPragma)pragmas.Get_by(ndeName); if (cmd == null) return false;
|
||||
GfmlNde pragmaNde = bldr.CurNde();
|
||||
pragmaNde.ObjType_set_pragma();
|
||||
cmd.Exec(bldr, pragmaNde);
|
||||
@@ -38,13 +38,13 @@ class GfmlPragmaMgr {
|
||||
public void EndCmds_add(GfmlDocPos pos, GfmlBldrCmd cmd) {endCmds.AddInList(pos.Path(), cmd);}
|
||||
public void EndCmds_del(GfmlDocPos pos, GfmlBldrCmd cmd) {endCmds.DelInList(pos.Path(), cmd);}
|
||||
public void EndCmds_exec(GfmlDocPos pos, GfmlBldr bldr) {Exec(pos, bldr, endCmds);}
|
||||
static void Exec(GfmlDocPos pos, GfmlBldr bldr, HashAdp_list cmds) {
|
||||
ListAdp list = cmds.Fetch(pos.Path()); if (list == null) return;
|
||||
static void Exec(GfmlDocPos pos, GfmlBldr bldr, Hash_adp_list cmds) {
|
||||
List_adp list = cmds.Get_by(pos.Path()); if (list == null) return;
|
||||
for (int i = 0; i < list.Count(); i++) {
|
||||
GfmlBldrCmd cmd = (GfmlBldrCmd)list.FetchAt(i);
|
||||
GfmlBldrCmd cmd = (GfmlBldrCmd)list.Get_at(i);
|
||||
cmd.Exec(bldr, GfmlTkn_.Null);
|
||||
}
|
||||
}
|
||||
HashAdp pragmas = HashAdp_.new_(); HashAdp_list bgnCmds = HashAdp_list.new_(), endCmds = HashAdp_list.new_();
|
||||
Hash_adp pragmas = Hash_adp_.new_(); Hash_adp_list bgnCmds = Hash_adp_list.new_(), endCmds = Hash_adp_list.new_();
|
||||
public static GfmlPragmaMgr new_() {return new GfmlPragmaMgr();} GfmlPragmaMgr() {}
|
||||
}
|
||||
|
||||
@@ -19,22 +19,22 @@ package gplx.gfml; import gplx.*;
|
||||
class GfmlPragmaDefault implements GfmlPragma {
|
||||
public String KeyOfPragma() {return "_default";}
|
||||
public void Exec(GfmlBldr bldr, GfmlNde pragmaNde) {
|
||||
ListAdp list = Compile(pragmaNde);
|
||||
List_adp list = Compile(pragmaNde);
|
||||
GfmlDefaultPragma_bgnCmd.ExecList(bldr.TypeMgr().TypeRegy(), bldr.CurNdeFrame().CurDocPos(), list);
|
||||
// bldr.PragmaMgr.EndCmds_add(GfmlDocPos_.up_(bldr.CurNdeFrame.DocPos), GfmlDefaultPragma_endCmd.new_(list));
|
||||
}
|
||||
@gplx.Internal protected ListAdp Compile(GfmlNde pragmaNde) {
|
||||
ListAdp list = ListAdp_.new_();
|
||||
@gplx.Internal protected List_adp Compile(GfmlNde pragmaNde) {
|
||||
List_adp list = List_adp_.new_();
|
||||
for (int i = 0; i < pragmaNde.SubHnds().Count(); i++) {
|
||||
GfmlNde subNde = (GfmlNde)pragmaNde.SubHnds().FetchAt(i);
|
||||
GfmlNde subNde = (GfmlNde)pragmaNde.SubHnds().Get_at(i);
|
||||
CompileSubNde(subNde, list);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
@gplx.Internal protected void CompileSubNde(GfmlNde nde, ListAdp list) {
|
||||
@gplx.Internal protected void CompileSubNde(GfmlNde nde, List_adp list) {
|
||||
String typeKey = nde.SubKeys().FetchDataOrNull("typeKey"); if (typeKey == null) throw Err_.missing_key_("typeKey");
|
||||
for (int i = 0; i < nde.SubHnds().Count(); i++) {
|
||||
GfmlNde subNde = (GfmlNde)nde.SubHnds().FetchAt(i);
|
||||
GfmlNde subNde = (GfmlNde)nde.SubHnds().Get_at(i);
|
||||
GfmlDefaultItem item = CompileItem(subNde, typeKey);
|
||||
list.Add(item);
|
||||
}
|
||||
@@ -60,7 +60,7 @@ class GfmlDefaultItem {
|
||||
public GfmlObj ValPrev() {return valPrev;} @gplx.Internal protected GfmlDefaultItem ValPrev_(GfmlObj tkn) {valPrev = tkn; return this;} GfmlObj valPrev;
|
||||
|
||||
public void Exec_bgn(GfmlType type) {
|
||||
GfmlFld fld = type.SubFlds().Fetch(key);
|
||||
GfmlFld fld = type.SubFlds().Get_by(key);
|
||||
if (fld == null) { // no default defined; create
|
||||
valPrev = GfmlPragmaDefault.Default_none;
|
||||
fld = GfmlFld.new_(true, key, GfmlType_.StringKey).DefaultTkn_(val);
|
||||
@@ -72,7 +72,7 @@ class GfmlDefaultItem {
|
||||
}
|
||||
}
|
||||
public void Exec_end(GfmlType type) {
|
||||
GfmlFld fld = type.SubFlds().Fetch(key); if (fld == null) return;
|
||||
GfmlFld fld = type.SubFlds().Get_by(key); if (fld == null) return;
|
||||
// if (fld == null) throw Err_.arg_range_msg_("fatal: could not find fld; typeKey={0} fld={1}", typeKey, key);
|
||||
if (valPrev == GfmlPragmaDefault.Default_none) // drop default; (had been created by pragma)
|
||||
type.SubFlds().Del(fld);
|
||||
@@ -90,7 +90,7 @@ class GfmlDefaultItem {
|
||||
class GfmlDefaultPragma_bgnCmd implements GfmlBldrCmd {
|
||||
public String Key() {return "pragma:gfml.default.bgnCmd";}
|
||||
public void Exec(GfmlBldr bldr, GfmlTkn tkn) {ExecList(bldr.TypeMgr().TypeRegy(), bldr.CurNdeFrame().CurDocPos(), list);}
|
||||
@gplx.Internal protected static void ExecList(GfmlTypRegy regy, GfmlDocPos pos, ListAdp list) {
|
||||
@gplx.Internal protected static void ExecList(GfmlTypRegy regy, GfmlDocPos pos, List_adp list) {
|
||||
GfmlType type = GfmlType_.Null;
|
||||
for (Object itemObj : list) {
|
||||
GfmlDefaultItem item = (GfmlDefaultItem)itemObj;
|
||||
@@ -103,8 +103,8 @@ class GfmlDefaultPragma_bgnCmd implements GfmlBldrCmd {
|
||||
item.Exec_bgn(type);
|
||||
}
|
||||
}
|
||||
ListAdp list;
|
||||
public static GfmlDefaultPragma_bgnCmd new_(ListAdp list) {
|
||||
List_adp list;
|
||||
public static GfmlDefaultPragma_bgnCmd new_(List_adp list) {
|
||||
GfmlDefaultPragma_bgnCmd rv = new GfmlDefaultPragma_bgnCmd();
|
||||
rv.list = list;
|
||||
return rv;
|
||||
@@ -113,7 +113,7 @@ class GfmlDefaultPragma_bgnCmd implements GfmlBldrCmd {
|
||||
class GfmlDefaultPragma_endCmd implements GfmlBldrCmd {
|
||||
public String Key() {return "pragma:gfml.default.endCmd";}
|
||||
public void Exec(GfmlBldr bldr, GfmlTkn tkn) {ExecList(bldr.TypeMgr().TypeRegy(), list);}
|
||||
public static void ExecList(GfmlTypRegy regy, ListAdp list) {
|
||||
public static void ExecList(GfmlTypRegy regy, List_adp list) {
|
||||
GfmlType type = GfmlType_.Null;
|
||||
for (Object itemObj : list) {
|
||||
GfmlDefaultItem item = (GfmlDefaultItem)itemObj;
|
||||
@@ -124,8 +124,8 @@ class GfmlDefaultPragma_endCmd implements GfmlBldrCmd {
|
||||
item.Exec_end(type);
|
||||
}
|
||||
}
|
||||
ListAdp list;
|
||||
public static GfmlDefaultPragma_endCmd new_(ListAdp list) {
|
||||
List_adp list;
|
||||
public static GfmlDefaultPragma_endCmd new_(List_adp list) {
|
||||
GfmlDefaultPragma_endCmd rv = new GfmlDefaultPragma_endCmd();
|
||||
rv.list = list;
|
||||
return rv;
|
||||
|
||||
@@ -28,7 +28,7 @@ class GfmlPragmaLxrFrm implements GfmlPragma {
|
||||
String end = ownerNde.SubKeys().FetchDataOrFail("end");
|
||||
GfmlFrame frame = String_.Eq(type, "comment") ? GfmlFrame_.comment_() : GfmlFrame_.quote_();
|
||||
|
||||
GfmlLxr lxr = bldr.Doc().LxrRegy().Fetch(key);
|
||||
GfmlLxr lxr = bldr.Doc().LxrRegy().Get_by(key);
|
||||
if (lxr == null) {
|
||||
lxr = GfmlLxr_.frame_(key, frame, bgn, end);
|
||||
bldr.Doc().LxrRegy().Add(lxr);
|
||||
@@ -48,7 +48,7 @@ class GfmlPragmaLxrFrm implements GfmlPragma {
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < ownerNde.SubHnds().Count(); i++) {
|
||||
GfmlNde subNde = (GfmlNde)ownerNde.SubHnds().FetchAt(i);
|
||||
GfmlNde subNde = (GfmlNde)ownerNde.SubHnds().Get_at(i);
|
||||
GfmlLxr subLxr = null;
|
||||
if (String_.Eq(subNde.Hnd(), "sym"))
|
||||
subLxr = GfmlPragmaLxrSym.Compile(bldr, subNde);
|
||||
|
||||
@@ -28,7 +28,7 @@ class GfmlPragmaLxrSym implements GfmlPragma {
|
||||
GfmlTkn cmdTkn = ownerNde.SubKeys().FetchDataTknOrNull("cmd");
|
||||
GfmlBldrCmd cmd = bldr.Doc().CmdRegy().GetOrFail(cmdTkn.Val());
|
||||
|
||||
GfmlLxr lxr = bldr.Doc().LxrRegy().Fetch(key);
|
||||
GfmlLxr lxr = bldr.Doc().LxrRegy().Get_by(key);
|
||||
if (lxr == null) {
|
||||
lxr = GfmlLxr_.symbol_(key, raw, val, cmd);
|
||||
bldr.Doc().LxrRegy().Add(lxr);
|
||||
|
||||
@@ -20,9 +20,9 @@ import gplx.lists.*;
|
||||
class GfmlPragmaType implements GfmlPragma {
|
||||
public String KeyOfPragma() {return pragmaKey;} private String pragmaKey = "_type";
|
||||
public void Exec(GfmlBldr bldr, GfmlNde pragmaNde) {
|
||||
OrderedHash list = OrderedHash_.new_(); ListAdp replaced = ListAdp_.new_();
|
||||
Ordered_hash list = Ordered_hash_.new_(); List_adp replaced = List_adp_.new_();
|
||||
for (int i = 0 ; i < pragmaNde.SubHnds().Count(); i++) {
|
||||
GfmlNde typNde = pragmaNde.SubHnds().FetchAt(i);
|
||||
GfmlNde typNde = pragmaNde.SubHnds().Get_at(i);
|
||||
GfmlType type = GfmlTypeCompiler.Compile(typNde, GfmlType_.Root, bldr.TypeMgr().TypeRegy(), list);
|
||||
if (i == 0) {
|
||||
GfmlFrame_nde topFrame = GfmlFrame_nde_.as_(bldr.CurFrame());
|
||||
@@ -48,7 +48,7 @@ class GfmlPragmaType implements GfmlPragma {
|
||||
return makr.Xto_bry();
|
||||
}
|
||||
public static final String CacheLog_key = "log:type";
|
||||
@gplx.Internal protected static void ExecList(GfmlTypRegy regy, OrderedHash list, ListAdp replaced) {
|
||||
@gplx.Internal protected static void ExecList(GfmlTypRegy regy, Ordered_hash list, List_adp replaced) {
|
||||
for (Object typeObj : list) {
|
||||
GfmlType type = (GfmlType)typeObj;
|
||||
if (regy.Has(type.Key()))
|
||||
@@ -60,7 +60,7 @@ class GfmlPragmaType implements GfmlPragma {
|
||||
class GfmlPragmaType_endCmd implements GfmlBldrCmd {
|
||||
public String Key() {return "cmd.gfml.type.end";}
|
||||
public void Exec(GfmlBldr bldr, GfmlTkn tkn) {ExecList(bldr.TypeMgr().TypeRegy(), list, replaced);}
|
||||
@gplx.Internal protected static void ExecList(GfmlTypRegy regy, OrderedHash list, ListAdp replaced) {
|
||||
@gplx.Internal protected static void ExecList(GfmlTypRegy regy, Ordered_hash list, List_adp replaced) {
|
||||
for (Object typeObj : list) {
|
||||
GfmlType type = (GfmlType)typeObj;
|
||||
regy.Del(type);
|
||||
@@ -70,8 +70,8 @@ class GfmlPragmaType_endCmd implements GfmlBldrCmd {
|
||||
regy.Add(type);
|
||||
}
|
||||
}
|
||||
OrderedHash list; ListAdp replaced;
|
||||
public static GfmlPragmaType_endCmd new_(OrderedHash list, ListAdp replaced) {
|
||||
Ordered_hash list; List_adp replaced;
|
||||
public static GfmlPragmaType_endCmd new_(Ordered_hash list, List_adp replaced) {
|
||||
GfmlPragmaType_endCmd rv = new GfmlPragmaType_endCmd();
|
||||
rv.list = list; rv.replaced = replaced;
|
||||
return rv;
|
||||
|
||||
@@ -19,14 +19,14 @@ package gplx.gfml; import gplx.*;
|
||||
class GfmlPragmaVar implements GfmlPragma {
|
||||
public String KeyOfPragma() {return pragmaKey;} public void PragmaKey_set(String v) {pragmaKey = v;} private String pragmaKey = "_var";
|
||||
public void Exec(GfmlBldr bldr, GfmlNde pragmaNde) {
|
||||
ListAdp list = Compile(pragmaNde);
|
||||
List_adp list = Compile(pragmaNde);
|
||||
ExecList(bldr.Vars(), list);
|
||||
bldr.Doc().PragmaMgr().EndCmds_add(bldr.CurNdeFrame().CurDocPos().NewUp(), GfmlPragmaVar_scopeEndCmd.new_(list));
|
||||
}
|
||||
@gplx.Internal protected ListAdp Compile(GfmlNde pragmaNde) {
|
||||
ListAdp list = ListAdp_.new_();
|
||||
@gplx.Internal protected List_adp Compile(GfmlNde pragmaNde) {
|
||||
List_adp list = List_adp_.new_();
|
||||
for (int i = 0; i < pragmaNde.SubHnds().Count(); i++) {
|
||||
GfmlNde subNde = (GfmlNde)pragmaNde.SubHnds().FetchAt(i);
|
||||
GfmlNde subNde = (GfmlNde)pragmaNde.SubHnds().Get_at(i);
|
||||
GfmlVarItm itm = CompileItmNde(subNde);
|
||||
list.Add(itm);
|
||||
}
|
||||
@@ -34,7 +34,7 @@ class GfmlPragmaVar implements GfmlPragma {
|
||||
}
|
||||
@gplx.Internal protected GfmlVarItm CompileItmNde(GfmlNde subNde) {
|
||||
String key = subNde.SubKeys().FetchDataOrFail("key");
|
||||
GfmlAtr valAtr = (GfmlAtr)subNde.SubKeys().Fetch("val");
|
||||
GfmlAtr valAtr = (GfmlAtr)subNde.SubKeys().Get_by("val");
|
||||
String ctx = subNde.SubKeys().FetchDataOrNull("ctx"); if (ctx == null) ctx = GfmlVarCtx_.DefaultKey;
|
||||
return GfmlVarItm.new_(key, valAtr.DatTkn(), ctx);
|
||||
}
|
||||
@@ -43,7 +43,7 @@ class GfmlPragmaVar implements GfmlPragma {
|
||||
makr.MakeSubType ( "text", "key", "val", "ctx");
|
||||
return makr.Xto_bry();
|
||||
}
|
||||
void ExecList(HashAdp cache, ListAdp list) {
|
||||
void ExecList(Hash_adp cache, List_adp list) {
|
||||
GfmlVarCtx ctx = null;
|
||||
for (Object varObj : list) {
|
||||
GfmlVarItm var = (GfmlVarItm)varObj;
|
||||
@@ -52,7 +52,7 @@ class GfmlPragmaVar implements GfmlPragma {
|
||||
}
|
||||
}
|
||||
public static GfmlPragmaVar new_() {return new GfmlPragmaVar();} GfmlPragmaVar() {}
|
||||
public static GfmlVarCtx FetchIfNew(GfmlVarCtx ctx, GfmlVarItm var, HashAdp cache) {// reused in two procs
|
||||
public static GfmlVarCtx FetchIfNew(GfmlVarCtx ctx, GfmlVarItm var, Hash_adp cache) {// reused in two procs
|
||||
if (ctx == null || !String_.Eq(ctx.Key(), var.CtxKey()))
|
||||
ctx = GfmlVarCtx_.FetchFromCacheOrNew(cache, var.CtxKey());
|
||||
return ctx;
|
||||
@@ -61,7 +61,7 @@ class GfmlPragmaVar implements GfmlPragma {
|
||||
class GfmlPragmaVar_scopeEndCmd implements GfmlBldrCmd {
|
||||
public String Key() {return "cmd:gfml.var.expire";}
|
||||
public void Exec(GfmlBldr bldr, GfmlTkn tkn) {
|
||||
HashAdp cache = bldr.Vars();
|
||||
Hash_adp cache = bldr.Vars();
|
||||
GfmlVarCtx ctx = null;
|
||||
for (Object varObj : list) {
|
||||
GfmlVarItm var = (GfmlVarItm)varObj;
|
||||
@@ -69,8 +69,8 @@ class GfmlPragmaVar_scopeEndCmd implements GfmlBldrCmd {
|
||||
var.Scope_end(ctx);
|
||||
}
|
||||
}
|
||||
ListAdp list;
|
||||
public static GfmlPragmaVar_scopeEndCmd new_(ListAdp list) {
|
||||
List_adp list;
|
||||
public static GfmlPragmaVar_scopeEndCmd new_(List_adp list) {
|
||||
GfmlPragmaVar_scopeEndCmd rv = new GfmlPragmaVar_scopeEndCmd();
|
||||
rv.list = list;
|
||||
return rv;
|
||||
|
||||
@@ -18,13 +18,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
package gplx.gfml; import gplx.*;
|
||||
class GfmlVarCtx {
|
||||
public String Key() {return key;} private String key;
|
||||
public void AddReplace(GfmlVarItm itm) {hash.AddReplace(itm.Key(), itm);}
|
||||
public void Add_if_dupe_use_nth(GfmlVarItm itm) {hash.Add_if_dupe_use_nth(itm.Key(), itm);}
|
||||
public void Del(String key) {hash.Del(key);}
|
||||
public String Fetch_Val(String key) {
|
||||
GfmlVarItm itm = (GfmlVarItm)hash.Fetch(key); if (itm == null) return null;
|
||||
GfmlVarItm itm = (GfmlVarItm)hash.Get_by(key); if (itm == null) return null;
|
||||
return itm.TknVal();
|
||||
}
|
||||
HashAdp hash = HashAdp_.new_();
|
||||
Hash_adp hash = Hash_adp_.new_();
|
||||
public static GfmlVarCtx new_(String key) {
|
||||
GfmlVarCtx rv = new GfmlVarCtx();
|
||||
rv.key = key;
|
||||
@@ -32,9 +32,9 @@ class GfmlVarCtx {
|
||||
}
|
||||
}
|
||||
class GfmlVarCtx_ {
|
||||
public static GfmlVarCtx FetchFromCacheOrNew(HashAdp cache, String ctxKey) {
|
||||
HashAdp ctxRegy = FetchRegyOrNew(cache);
|
||||
GfmlVarCtx rv = (GfmlVarCtx)ctxRegy.Fetch(ctxKey);
|
||||
public static GfmlVarCtx FetchFromCacheOrNew(Hash_adp cache, String ctxKey) {
|
||||
Hash_adp ctxRegy = FetchRegyOrNew(cache);
|
||||
GfmlVarCtx rv = (GfmlVarCtx)ctxRegy.Get_by(ctxKey);
|
||||
if (rv == null) {
|
||||
rv = (String_.Eq(ctxKey, DefaultKey))
|
||||
? default_(ctxKey)
|
||||
@@ -45,15 +45,15 @@ class GfmlVarCtx_ {
|
||||
}
|
||||
static GfmlVarCtx default_(String ctxKey) {
|
||||
GfmlVarCtx rv = GfmlVarCtx.new_(ctxKey);
|
||||
rv.AddReplace(GfmlVarItm.new_("t", GfmlTkn_.raw_("\t"), GfmlVarCtx_.DefaultKey));
|
||||
rv.AddReplace(GfmlVarItm.new_("n", GfmlTkn_.raw_(String_.CrLf), GfmlVarCtx_.DefaultKey));
|
||||
rv.Add_if_dupe_use_nth(GfmlVarItm.new_("t", GfmlTkn_.raw_("\t"), GfmlVarCtx_.DefaultKey));
|
||||
rv.Add_if_dupe_use_nth(GfmlVarItm.new_("n", GfmlTkn_.raw_(String_.CrLf), GfmlVarCtx_.DefaultKey));
|
||||
return rv;
|
||||
}
|
||||
static HashAdp FetchRegyOrNew(HashAdp cache) {
|
||||
static Hash_adp FetchRegyOrNew(Hash_adp cache) {
|
||||
String key = "gfml.cacheKeys.ctxRegy";
|
||||
HashAdp rv = (HashAdp)cache.Fetch(key);
|
||||
Hash_adp rv = (Hash_adp)cache.Get_by(key);
|
||||
if (rv == null) {
|
||||
rv = HashAdp_.new_();
|
||||
rv = Hash_adp_.new_();
|
||||
cache.Add(key, rv);
|
||||
}
|
||||
return rv;
|
||||
|
||||
@@ -22,7 +22,7 @@ class GfmlVarItm implements GfmlScopeItm {
|
||||
public GfmlTkn Tkn() {return tkn;} public void Tkn_set(GfmlTkn v) {tkn = v;} GfmlTkn tkn;
|
||||
public String TknVal() {return tkn.Val();}
|
||||
public String CtxKey() {return ctxKey;} private String ctxKey;
|
||||
@gplx.Internal protected void Scope_bgn(GfmlVarCtx ctx) {ctx.AddReplace(this);}
|
||||
@gplx.Internal protected void Scope_bgn(GfmlVarCtx ctx) {ctx.Add_if_dupe_use_nth(this);}
|
||||
@gplx.Internal protected void Scope_end(GfmlVarCtx ctx) {ctx.Del(key);}
|
||||
public static GfmlVarItm new_(String key, GfmlTkn tkn, String ctxKey) {
|
||||
GfmlVarItm rv = new GfmlVarItm();
|
||||
|
||||
Reference in New Issue
Block a user