updated strings
This commit is contained in:
parent
b23eba293d
commit
a313c5b95b
|
@ -33,30 +33,67 @@
|
||||||
#define _INCLUDE_CSTRING_H
|
#define _INCLUDE_CSTRING_H
|
||||||
|
|
||||||
//by David "BAILOPAN" Anderson
|
//by David "BAILOPAN" Anderson
|
||||||
class CString
|
class String
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CString() { v = NULL; mSize = 0; }
|
String()
|
||||||
~CString() { if (v) delete [] v; }
|
{
|
||||||
|
v = NULL;
|
||||||
|
mSize = 0;
|
||||||
|
cSize = 0;
|
||||||
|
Grow(2);
|
||||||
|
assign("");
|
||||||
|
}
|
||||||
|
|
||||||
//added these for amxx
|
~String()
|
||||||
CString(const char *src) { v = NULL; mSize = 0; assign(src); }
|
{
|
||||||
CString(CString &src) { v = NULL; mSize = 0; assign(src.c_str()); }
|
if (v)
|
||||||
|
delete [] v;
|
||||||
|
}
|
||||||
|
|
||||||
|
String(const char *src)
|
||||||
|
{
|
||||||
|
v = NULL;
|
||||||
|
mSize = 0;
|
||||||
|
cSize = 0; assign(src);
|
||||||
|
}
|
||||||
|
|
||||||
|
String(String &src)
|
||||||
|
{
|
||||||
|
v = NULL;
|
||||||
|
mSize = 0;
|
||||||
|
cSize = 0;
|
||||||
|
assign(src.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
const char *c_str() { return v?v:""; }
|
const char *c_str() { return v?v:""; }
|
||||||
const char *c_str() const { return v?v:""; }
|
const char *c_str() const { return v?v:""; }
|
||||||
|
|
||||||
void append(const char *t)
|
void append(const char *t)
|
||||||
{
|
{
|
||||||
Grow(strlen(v) + strlen(t));
|
Grow(cSize + strlen(t));
|
||||||
strcat(v, t);
|
strcat(v, t);
|
||||||
|
cSize = strlen(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
void append(CString &d)
|
void append(const char c)
|
||||||
|
{
|
||||||
|
Grow(cSize + 2);
|
||||||
|
v[cSize] = c;
|
||||||
|
v[++cSize] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void append(String &d)
|
||||||
{
|
{
|
||||||
const char *t = d.c_str();
|
const char *t = d.c_str();
|
||||||
Grow(strlen(v) + strlen(t));
|
Grow(cSize + strlen(t));
|
||||||
strcat(v, t);
|
strcat(v, t);
|
||||||
|
cSize = strlen(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
void assign(const String &src)
|
||||||
|
{
|
||||||
|
assign(src.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void assign(const char *d)
|
void assign(const char *d)
|
||||||
|
@ -64,20 +101,27 @@ public:
|
||||||
if (!d)
|
if (!d)
|
||||||
{
|
{
|
||||||
Grow(1);
|
Grow(1);
|
||||||
|
cSize = 0;
|
||||||
strcpy(v, "");
|
strcpy(v, "");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Grow(strlen(d));
|
Grow(strlen(d));
|
||||||
if (v)
|
if (v)
|
||||||
|
{
|
||||||
strcpy(v, d);
|
strcpy(v, d);
|
||||||
|
cSize = strlen(v);
|
||||||
|
} else {
|
||||||
|
cSize = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear()
|
void clear()
|
||||||
{
|
{
|
||||||
if (v)
|
if (v)
|
||||||
delete [] v;
|
{
|
||||||
v = NULL;
|
v[0] = 0;
|
||||||
mSize = 0;
|
cSize = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int compare (const char *d)
|
int compare (const char *d)
|
||||||
|
@ -100,7 +144,7 @@ public:
|
||||||
//Added this for amxx inclusion
|
//Added this for amxx inclusion
|
||||||
bool empty()
|
bool empty()
|
||||||
{
|
{
|
||||||
if (!v || !mSize)
|
if (!v || !cSize)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -110,20 +154,239 @@ public:
|
||||||
{
|
{
|
||||||
if (!v)
|
if (!v)
|
||||||
return 0;
|
return 0;
|
||||||
return strlen(v);
|
return cSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char * _fread(FILE *fp)
|
||||||
|
{
|
||||||
|
Grow(512);
|
||||||
|
char * ret = fgets(v, 511, fp);
|
||||||
|
cSize = strlen(v);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int find(const char c, int index = 0)
|
||||||
|
{
|
||||||
|
if (!v)
|
||||||
|
return npos;
|
||||||
|
if (index >= (int)cSize || index < 0)
|
||||||
|
return npos;
|
||||||
|
unsigned int i = 0;
|
||||||
|
for (i=index; i<cSize; i++)
|
||||||
|
{
|
||||||
|
if (v[i] == c)
|
||||||
|
{
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return npos;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_space(int c)
|
||||||
|
{
|
||||||
|
if (c == '\f' || c == '\n' ||
|
||||||
|
c == '\t' || c == '\r' ||
|
||||||
|
c == 'v' || c == ' ')
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void trim()
|
||||||
|
{
|
||||||
|
if (!v)
|
||||||
|
return;
|
||||||
|
unsigned int i = 0;
|
||||||
|
unsigned int j = 0;
|
||||||
|
|
||||||
|
if (cSize == 1)
|
||||||
|
{
|
||||||
|
if (is_space(v[i]))
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char c0 = v[0];
|
||||||
|
|
||||||
|
if (is_space(c0))
|
||||||
|
{
|
||||||
|
for (i=0; i<cSize; i++)
|
||||||
|
{
|
||||||
|
if (!is_space(v[i]) || (is_space(v[i]) && ((unsigned char)i==cSize-1)))
|
||||||
|
{
|
||||||
|
erase(0, i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cSize = strlen(v);
|
||||||
|
|
||||||
|
if (cSize < 1)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_space(v[cSize-1]))
|
||||||
|
{
|
||||||
|
for (i=cSize-1; i>=0; i--)
|
||||||
|
{
|
||||||
|
if (!is_space(v[i])
|
||||||
|
|| (is_space(v[i]) && i==0))
|
||||||
|
{
|
||||||
|
erase(i+1, j);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cSize == 1)
|
||||||
|
{
|
||||||
|
if (is_space(v[0]))
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String & erase(unsigned int start, int num = npos)
|
||||||
|
{
|
||||||
|
if (!v)
|
||||||
|
return (*this);
|
||||||
|
unsigned int i = 0;
|
||||||
|
//check for bounds
|
||||||
|
if (num == npos || start+num > cSize-num+1)
|
||||||
|
num = cSize - start;
|
||||||
|
//do the erasing
|
||||||
|
bool copyflag = false;
|
||||||
|
for (i=0; i<cSize; i++)
|
||||||
|
{
|
||||||
|
if (i>=start && i<start+num)
|
||||||
|
{
|
||||||
|
if (i+num < cSize)
|
||||||
|
{
|
||||||
|
v[i] = v[i+num];
|
||||||
|
} else {
|
||||||
|
v[i] = 0;
|
||||||
|
}
|
||||||
|
copyflag = true;
|
||||||
|
} else if (copyflag) {
|
||||||
|
if (i+num < cSize)
|
||||||
|
{
|
||||||
|
v[i] = v[i+num];
|
||||||
|
} else {
|
||||||
|
v[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cSize -= num;
|
||||||
|
v[cSize] = 0;
|
||||||
|
|
||||||
|
return (*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
String substr(unsigned int index, int num = npos)
|
||||||
|
{
|
||||||
|
String ns;
|
||||||
|
|
||||||
|
if (index >= cSize || !v)
|
||||||
|
return ns;
|
||||||
|
|
||||||
|
if (num == npos)
|
||||||
|
{
|
||||||
|
num = cSize - index;
|
||||||
|
} else if (index+num >= cSize) {
|
||||||
|
num = cSize - index;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int i = 0, j=0;
|
||||||
|
char *s = new char[cSize+1];
|
||||||
|
|
||||||
|
for (i=index; i<index+num; i++)
|
||||||
|
{
|
||||||
|
s[j++] = v[i];
|
||||||
|
}
|
||||||
|
s[j] = 0;
|
||||||
|
|
||||||
|
ns.assign(s);
|
||||||
|
|
||||||
|
delete [] s;
|
||||||
|
|
||||||
|
return ns;
|
||||||
|
}
|
||||||
|
|
||||||
|
void toLower()
|
||||||
|
{
|
||||||
|
if (!v)
|
||||||
|
return;
|
||||||
|
unsigned int i = 0;
|
||||||
|
for (i=0; i<cSize; i++)
|
||||||
|
{
|
||||||
|
if (v[i] >= 65 && v[i] <= 90)
|
||||||
|
v[i] |= 32;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String & operator = (const String &src)
|
||||||
|
{
|
||||||
|
assign(src);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
String & operator = (const char *src)
|
||||||
|
{
|
||||||
|
assign(src);
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
char operator [] (unsigned int index)
|
||||||
|
{
|
||||||
|
if (index > cSize)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
return v[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int at(int a)
|
||||||
|
{
|
||||||
|
if (a < 0 || a >= (int)cSize)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return v[a];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool at(int at, char c)
|
||||||
|
{
|
||||||
|
if (at < 0 || at >= (int)cSize)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
v[at] = c;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Grow(int d)
|
void Grow(unsigned int d)
|
||||||
{
|
{
|
||||||
if (d<1)
|
if (d<1)
|
||||||
return;
|
return;
|
||||||
if (d > mSize)
|
if (d > mSize)
|
||||||
{
|
{
|
||||||
|
mSize = d + 16; // allocate a buffer
|
||||||
char *t = new char[d+1];
|
char *t = new char[d+1];
|
||||||
if (v) {
|
if (v) {
|
||||||
strcpy(t, v);
|
strcpy(t, v);
|
||||||
t[strlen(v)] = 0;
|
t[cSize] = 0;
|
||||||
delete [] v;
|
delete [] v;
|
||||||
}
|
}
|
||||||
v = t;
|
v = t;
|
||||||
|
@ -132,8 +395,10 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
char *v;
|
char *v;
|
||||||
int mSize;
|
unsigned int mSize;
|
||||||
|
unsigned int cSize;
|
||||||
|
public:
|
||||||
|
static const int npos = -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //_INCLUDE_CSTRING_H
|
#endif //_INCLUDE_CSTRING_H
|
||||||
|
|
||||||
|
|
|
@ -173,6 +173,6 @@ for ($i=0; $i<=$#CPP_SOURCE_FILES; $i++)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$gcc = "$gccf $cflags -shared -ldl -lm @LINK -o $outdir/$bin";
|
$gcc = "$gccf $cflags -shared -fPIC -ldl -lm -o $outdir/$bin @LINK";
|
||||||
print "$gcc\n";
|
print "$gcc\n";
|
||||||
`$gcc`;
|
`$gcc`;
|
||||||
|
|
|
@ -28,14 +28,15 @@ static cell AMX_NATIVE_CALL register_think(AMX *amx, cell *params)
|
||||||
|
|
||||||
EntClass *p = new EntClass;
|
EntClass *p = new EntClass;
|
||||||
const char *clsname = MF_GetAmxString(amx, params[1], 0, &len);
|
const char *clsname = MF_GetAmxString(amx, params[1], 0, &len);
|
||||||
p->Class = new char[strlen(clsname)+1];
|
p->Class.assign(clsname);
|
||||||
strcpy(p->Class, clsname);
|
|
||||||
|
|
||||||
p->Forward = MF_RegisterSPForwardByName(amx, MF_GetAmxString(amx, params[2], 0, &len), FP_CELL, FP_DONE);
|
p->Forward = MF_RegisterSPForwardByName(amx, MF_GetAmxString(amx, params[2], 0, &len), FP_CELL, FP_DONE);
|
||||||
|
|
||||||
Thinks.push_back(p);
|
Thinks.push_back(p);
|
||||||
|
|
||||||
|
if (!g_pFunctionTable->pfnThink)
|
||||||
g_pFunctionTable->pfnThink=Think;
|
g_pFunctionTable->pfnThink=Think;
|
||||||
|
|
||||||
return p->Forward;
|
return p->Forward;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,7 +51,9 @@ static cell AMX_NATIVE_CALL register_impulse(AMX *amx, cell *params)
|
||||||
|
|
||||||
Impulses.push_back(p);
|
Impulses.push_back(p);
|
||||||
|
|
||||||
|
if (!g_pFunctionTable->pfnCmdStart)
|
||||||
g_pFunctionTable->pfnCmdStart=CmdStart;
|
g_pFunctionTable->pfnCmdStart=CmdStart;
|
||||||
|
|
||||||
return p->Forward;
|
return p->Forward;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,22 +67,21 @@ static cell AMX_NATIVE_CALL register_touch(AMX *amx, cell *params)
|
||||||
Touch *p = new Touch;
|
Touch *p = new Touch;
|
||||||
|
|
||||||
if (!strlen(Toucher) || strcmp(Toucher, "*")==0) {
|
if (!strlen(Toucher) || strcmp(Toucher, "*")==0) {
|
||||||
p->Toucher = 0;
|
p->Toucher.assign("");
|
||||||
} else {
|
} else {
|
||||||
p->Toucher = new char[strlen(Toucher)+1];
|
p->Toucher.assign(Toucher);
|
||||||
strcpy(p->Toucher, Toucher);
|
|
||||||
}
|
}
|
||||||
if (!strlen(Touched) || strcmp(Touched, "*")==0) {
|
if (!strlen(Touched) || strcmp(Touched, "*")==0) {
|
||||||
p->Touched = 0;
|
p->Touched.assign("");
|
||||||
} else {
|
} else {
|
||||||
p->Touched = new char[strlen(Touched)+1];
|
p->Touched.assign(Touched);
|
||||||
strcpy(p->Touched, Touched);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
p->Forward = MF_RegisterSPForwardByName(amx, MF_GetAmxString(amx, params[3], 2, &len), FP_CELL, FP_CELL, FP_DONE);
|
p->Forward = MF_RegisterSPForwardByName(amx, MF_GetAmxString(amx, params[3], 2, &len), FP_CELL, FP_CELL, FP_DONE);
|
||||||
|
|
||||||
Touches.push_back(p);
|
Touches.push_back(p);
|
||||||
|
|
||||||
|
if (!g_pFunctionTable->pfnTouch)
|
||||||
g_pFunctionTable->pfnTouch=pfnTouch;
|
g_pFunctionTable->pfnTouch=pfnTouch;
|
||||||
|
|
||||||
return p->Forward;
|
return p->Forward;
|
||||||
|
|
|
@ -133,18 +133,10 @@ class Touch
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
int Forward;
|
int Forward;
|
||||||
char *Toucher;
|
String Toucher;
|
||||||
char *Touched;
|
String Touched;
|
||||||
~Touch()
|
~Touch()
|
||||||
{
|
{
|
||||||
if (Toucher) {
|
|
||||||
delete [] Toucher;
|
|
||||||
Toucher = 0;
|
|
||||||
}
|
|
||||||
if (Touched) {
|
|
||||||
delete [] Touched;
|
|
||||||
Touched = 0;
|
|
||||||
}
|
|
||||||
if (Forward != -1)
|
if (Forward != -1)
|
||||||
MF_UnregisterSPForward(Forward);
|
MF_UnregisterSPForward(Forward);
|
||||||
}
|
}
|
||||||
|
@ -154,13 +146,11 @@ class EntClass
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
int Forward;
|
int Forward;
|
||||||
char *Class;
|
String Class;
|
||||||
~EntClass()
|
~EntClass()
|
||||||
{
|
{
|
||||||
if (Class) {
|
if (Forward != -1)
|
||||||
delete [] Class;
|
MF_UnregisterSPForward(Forward);
|
||||||
Class = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -229,31 +229,31 @@ void pfnTouch(edict_t *pToucher, edict_t *pTouched)
|
||||||
META_RES res=MRES_IGNORED;
|
META_RES res=MRES_IGNORED;
|
||||||
for (i=0; i<Touches.size(); i++)
|
for (i=0; i<Touches.size(); i++)
|
||||||
{
|
{
|
||||||
if (Touches[i]->Toucher == 0)
|
if (Touches[i]->Toucher.size() == 0)
|
||||||
{
|
{
|
||||||
if (Touches[i]->Touched == 0)
|
if (Touches[i]->Touched.size() == 0)
|
||||||
{
|
{
|
||||||
retVal = MF_ExecuteForward(Touches[i]->Forward, ENTINDEX(pToucher), ENTINDEX(pTouched));
|
retVal = MF_ExecuteForward(Touches[i]->Forward, ENTINDEX(pToucher), ENTINDEX(pTouched));
|
||||||
if (retVal & 2/*PLUGIN_HANDLED_MAIN*/)
|
if (retVal & 2/*PLUGIN_HANDLED_MAIN*/)
|
||||||
RETURN_META(MRES_SUPERCEDE);
|
RETURN_META(MRES_SUPERCEDE);
|
||||||
else if (retVal)
|
else if (retVal)
|
||||||
res=MRES_SUPERCEDE;
|
res=MRES_SUPERCEDE;
|
||||||
} else if (fstrcmp(Touches[i]->Touched, ptdClass)) {
|
} else if (Touches[i]->Touched.compare(ptdClass)==0) {
|
||||||
retVal = MF_ExecuteForward(Touches[i]->Forward, ENTINDEX(pToucher), ENTINDEX(pTouched));
|
retVal = MF_ExecuteForward(Touches[i]->Forward, ENTINDEX(pToucher), ENTINDEX(pTouched));
|
||||||
if (retVal & 2/*PLUGIN_HANDLED_MAIN*/)
|
if (retVal & 2/*PLUGIN_HANDLED_MAIN*/)
|
||||||
RETURN_META(MRES_SUPERCEDE);
|
RETURN_META(MRES_SUPERCEDE);
|
||||||
else if (retVal)
|
else if (retVal)
|
||||||
res=MRES_SUPERCEDE;
|
res=MRES_SUPERCEDE;
|
||||||
}
|
}
|
||||||
} else if (fstrcmp(Touches[i]->Toucher, ptrClass)) {
|
} else if (Touches[i]->Toucher.compare(ptrClass)==0) {
|
||||||
if (Touches[i]->Touched == 0)
|
if (Touches[i]->Touched.size() == 0)
|
||||||
{
|
{
|
||||||
retVal = MF_ExecuteForward(Touches[i]->Forward, ENTINDEX(pToucher), ENTINDEX(pTouched));
|
retVal = MF_ExecuteForward(Touches[i]->Forward, ENTINDEX(pToucher), ENTINDEX(pTouched));
|
||||||
if (retVal & 2/*PLUGIN_HANDLED_MAIN*/)
|
if (retVal & 2/*PLUGIN_HANDLED_MAIN*/)
|
||||||
RETURN_META(MRES_SUPERCEDE);
|
RETURN_META(MRES_SUPERCEDE);
|
||||||
else if (retVal)
|
else if (retVal)
|
||||||
res=MRES_SUPERCEDE;
|
res=MRES_SUPERCEDE;
|
||||||
} else if (fstrcmp(Touches[i]->Touched, ptdClass)) {
|
} else if (Touches[i]->Touched.compare(ptdClass)==0) {
|
||||||
retVal = MF_ExecuteForward(Touches[i]->Forward, ENTINDEX(pToucher), ENTINDEX(pTouched));
|
retVal = MF_ExecuteForward(Touches[i]->Forward, ENTINDEX(pToucher), ENTINDEX(pTouched));
|
||||||
if (retVal & 2/*PLUGIN_HANDLED_MAIN*/)
|
if (retVal & 2/*PLUGIN_HANDLED_MAIN*/)
|
||||||
RETURN_META(MRES_SUPERCEDE);
|
RETURN_META(MRES_SUPERCEDE);
|
||||||
|
@ -285,7 +285,7 @@ void Think(edict_t *pent)
|
||||||
int retVal=0;
|
int retVal=0;
|
||||||
for (i=0; i<Thinks.size(); i++)
|
for (i=0; i<Thinks.size(); i++)
|
||||||
{
|
{
|
||||||
if (fstrcmp(cls, Thinks[i]->Class))
|
if (Thinks[i]->Class.compare(cls)==0)
|
||||||
{
|
{
|
||||||
retVal=MF_ExecuteForward(Thinks[i]->Forward, ENTINDEX(pent));
|
retVal=MF_ExecuteForward(Thinks[i]->Forward, ENTINDEX(pent));
|
||||||
if (retVal & 2/*PLUGIN_HANDLED_MAIN*/)
|
if (retVal & 2/*PLUGIN_HANDLED_MAIN*/)
|
||||||
|
|
|
@ -36,7 +36,7 @@ public:
|
||||||
|
|
||||||
int type;
|
int type;
|
||||||
REAL fData;
|
REAL fData;
|
||||||
CString cData;
|
String cData;
|
||||||
int iData;
|
int iData;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user