Apply patch from George Garvey to make Fl_Text_Display/Buffer based on
NEdit 5.3... git-svn-id: file:///fltk/svn/fltk/branches/branch-1.1@2631 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
parent
f9f28ad12a
commit
e04a3734e7
2
CHANGES
2
CHANGES
@ -1,5 +1,7 @@
|
||||
CHANGES IN FLTK 1.1.0rc7
|
||||
|
||||
- Updated the Fl_Text_Buffer and Fl_Text_Display classes
|
||||
to be based on NEdit 5.3 (patch from George Garvey).
|
||||
- Fixed a problem with Fl::wait(0.0) on MacOS X 10.2;
|
||||
this affected the fractals demo and other OpenGL
|
||||
applications.
|
||||
|
1
CREDITS
1
CREDITS
@ -34,6 +34,7 @@ OTHER CONTRIBUTORS
|
||||
Fabien Costantini
|
||||
Stephen Davies
|
||||
Greg Ercolano
|
||||
George Garvey
|
||||
Stuart Levy
|
||||
Mike Lindner
|
||||
Alexander Mai
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// "$Id: Fl_Text_Buffer.H,v 1.3.2.4 2002/08/09 03:17:29 easysw Exp $"
|
||||
// "$Id: Fl_Text_Buffer.H,v 1.3.2.5 2002/09/20 19:59:45 easysw Exp $"
|
||||
//
|
||||
// Header file for Fl_Text_Buffer class.
|
||||
//
|
||||
@ -65,6 +65,7 @@ class FL_EXPORT Fl_Text_Selection {
|
||||
typedef void (*Fl_Text_Modify_Cb)(int pos, int nInserted, int nDeleted,
|
||||
int nRestyled, const char* deletedText,
|
||||
void* cbArg);
|
||||
typedef void (*Fl_Text_Predelete_Cb)(int pos, int nDeleted, void* cbArg);
|
||||
|
||||
class FL_EXPORT Fl_Text_Buffer {
|
||||
public:
|
||||
@ -142,6 +143,11 @@ class FL_EXPORT Fl_Text_Buffer {
|
||||
|
||||
void call_modify_callbacks() { call_modify_callbacks(0, 0, 0, 0, 0); }
|
||||
|
||||
void add_predelete_callback(Fl_Text_Predelete_Cb bufPredelCB, void* cbArg);
|
||||
void remove_predelete_callback(Fl_Text_Predelete_Cb predelCB, void* cbArg);
|
||||
|
||||
void call_predelete_callbacks() { call_predelete_callbacks(0, 0); }
|
||||
|
||||
char* line_text(int pos);
|
||||
int line_start(int pos);
|
||||
int line_end(int pos);
|
||||
@ -179,6 +185,7 @@ class FL_EXPORT Fl_Text_Buffer {
|
||||
protected:
|
||||
void call_modify_callbacks(int pos, int nDeleted, int nInserted,
|
||||
int nRestyled, const char* deletedText);
|
||||
void call_predelete_callbacks(int pos, int nDeleted);
|
||||
|
||||
int insert_(int pos, const char* text);
|
||||
void remove_(int start, int end);
|
||||
@ -226,6 +233,10 @@ class FL_EXPORT Fl_Text_Buffer {
|
||||
Fl_Text_Modify_Cb* /* procedures to call when buffer is */
|
||||
mNodifyProcs; /* modified to redisplay contents */
|
||||
void** mCbArgs; /* caller arguments for modifyProcs above */
|
||||
int mNPredeleteProcs; /* number of pre-delete procs attached */
|
||||
Fl_Text_Predelete_Cb* /* procedure to call before text is deleted */
|
||||
mPredeleteProcs; /* from the buffer; at most one is supported. */
|
||||
void **mPredeleteCbArgs; /* caller argument for pre-delete proc above */
|
||||
int mCursorPosHint; /* hint for reasonable cursor position after
|
||||
a buffer modification operation */
|
||||
char mNullSubsChar; /* NEdit is based on C null-terminated strings,
|
||||
@ -238,5 +249,5 @@ class FL_EXPORT Fl_Text_Buffer {
|
||||
#endif
|
||||
|
||||
//
|
||||
// End of "$Id: Fl_Text_Buffer.H,v 1.3.2.4 2002/08/09 03:17:29 easysw Exp $".
|
||||
// End of "$Id: Fl_Text_Buffer.H,v 1.3.2.5 2002/09/20 19:59:45 easysw Exp $".
|
||||
//
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// "$Id: Fl_Text_Display.H,v 1.4.2.11 2002/08/14 16:49:38 easysw Exp $"
|
||||
// "$Id: Fl_Text_Display.H,v 1.4.2.12 2002/09/20 19:59:45 easysw Exp $"
|
||||
//
|
||||
// Header file for Fl_Text_Display class.
|
||||
//
|
||||
@ -53,7 +53,7 @@ class FL_EXPORT Fl_Text_Display: public Fl_Group {
|
||||
};
|
||||
friend void fl_text_drag_me(int pos, Fl_Text_Display* d);
|
||||
|
||||
typedef void (*Unfinished_Style_Cb)();
|
||||
typedef void (*Unfinished_Style_Cb)(int, void *);
|
||||
|
||||
// style attributes - currently not implemented!
|
||||
enum {
|
||||
@ -88,6 +88,11 @@ class FL_EXPORT Fl_Text_Display: public Fl_Group {
|
||||
int move_left();
|
||||
int move_up();
|
||||
int move_down();
|
||||
int count_lines(int start, int end, bool start_pos_is_line_start);
|
||||
int line_start(int pos);
|
||||
int line_end(int pos, bool start_pos_is_line_start);
|
||||
int skip_lines(int startPos, int nLines, bool startPosIsLineStart);
|
||||
int rewind_lines(int startPos, int nLines);
|
||||
void next_word(void);
|
||||
void previous_word(void);
|
||||
void show_cursor(int b = 1);
|
||||
@ -117,6 +122,10 @@ class FL_EXPORT Fl_Text_Display: public Fl_Group {
|
||||
Fl_Color textcolor() const {return (Fl_Color)textcolor_;}
|
||||
void textcolor(unsigned n) {textcolor_ = n;}
|
||||
|
||||
int wrapped_column(int row, int column);
|
||||
int wrapped_row(int row);
|
||||
void wrap_mode(int wrap, int wrap_margin);
|
||||
|
||||
virtual void resize(int X, int Y, int W, int H);
|
||||
|
||||
protected:
|
||||
@ -136,6 +145,8 @@ class FL_EXPORT Fl_Text_Display: public Fl_Group {
|
||||
void draw_vline(int visLineNum, int leftClip, int rightClip,
|
||||
int leftCharIndex, int rightCharIndex);
|
||||
|
||||
void draw_line_numbers(bool clearAll);
|
||||
|
||||
void clear_rect(int style, int x, int y, int width, int height);
|
||||
void display_insert();
|
||||
|
||||
@ -151,6 +162,7 @@ class FL_EXPORT Fl_Text_Display: public Fl_Group {
|
||||
int position_to_line( int pos, int* lineNum );
|
||||
int string_width(const char* string, int length, int style);
|
||||
|
||||
static void buffer_predelete_cb(int pos, int nDeleted, void* cbArg);
|
||||
static void buffer_modified_cb(int pos, int nInserted, int nDeleted,
|
||||
int nRestyled, const char* deletedText,
|
||||
void* cbArg);
|
||||
@ -169,11 +181,31 @@ class FL_EXPORT Fl_Text_Display: public Fl_Group {
|
||||
int PosType = CHARACTER_POS);
|
||||
|
||||
int position_to_xy(int pos, int* x, int* y);
|
||||
void maintain_absolute_top_line_number(int state);
|
||||
int get_absolute_top_line_number();
|
||||
void absolute_top_line_number(int oldFirstChar);
|
||||
int maintaining_absolute_top_line_number();
|
||||
void reset_absolute_top_line_number();
|
||||
int position_to_linecol(int pos, int* lineNum, int* column);
|
||||
void scroll_(int topLineNum, int horizOffset);
|
||||
|
||||
void extend_range_for_styles(int* start, int* end);
|
||||
|
||||
void find_wrap_range(const char *deletedText, int pos, int nInserted,
|
||||
int nDeleted, int *modRangeStart, int *modRangeEnd,
|
||||
int *linesInserted, int *linesDeleted);
|
||||
void measure_deleted_lines(int pos, int nDeleted);
|
||||
void wrapped_line_counter(Fl_Text_Buffer *buf, int startPos, int maxPos,
|
||||
int maxLines, bool startPosIsLineStart,
|
||||
int styleBufOffset, int *retPos, int *retLines,
|
||||
int *retLineStart, int *retLineEnd,
|
||||
bool countLastLineMissingNewLine = true);
|
||||
void find_line_end(int pos, bool start_pos_is_line_start, int *lineEnd,
|
||||
int *nextLineStart);
|
||||
int measure_proportional_character(char c, int colNum, int pos);
|
||||
int wrap_uses_character(int lineEndPos);
|
||||
int range_touches_selection(Fl_Text_Selection *sel, int rangeStart,
|
||||
int rangeEnd);
|
||||
|
||||
int damage_range1_start, damage_range1_end;
|
||||
int damage_range2_start, damage_range2_end;
|
||||
@ -194,9 +226,19 @@ class FL_EXPORT Fl_Text_Display: public Fl_Group {
|
||||
displayed character (lastChar points
|
||||
either to a newline or one character
|
||||
beyond the end of the buffer) */
|
||||
int mContinuousWrap; /* Wrap long lines when displaying */
|
||||
int mWrapMargin; /* Margin in # of char positions for
|
||||
wrapping in continuousWrap mode */
|
||||
int* mLineStarts;
|
||||
int mTopLineNum; /* Line number of top displayed line
|
||||
of file (first line of file is 1) */
|
||||
int mAbsTopLineNum; /* In continuous wrap mode, the line
|
||||
number of the top line if the text
|
||||
were not wrapped (note that this is
|
||||
only maintained as needed). */
|
||||
int mNeedAbsTopLineNum; /* Externally settable flag to continue
|
||||
maintaining absTopLineNum even if
|
||||
it isn't needed for line # display */
|
||||
int mHorizOffset; /* Horizontal scroll pos. in pixels */
|
||||
int mTopLineNumHint; /* Line number of top displayed line
|
||||
of file (first line of file is 1) */
|
||||
@ -214,6 +256,13 @@ class FL_EXPORT Fl_Text_Display: public Fl_Group {
|
||||
|
||||
int mFixedFontWidth; /* Font width if all current fonts are
|
||||
fixed and match in width, else -1 */
|
||||
int mSuppressResync; /* Suppress resynchronization of line
|
||||
starts during buffer updates */
|
||||
int mNLinesDeleted; /* Number of lines deleted during
|
||||
buffer modification (only used
|
||||
when resynchronization is suppressed) */
|
||||
int mModifyingTabDistance; /* Whether tab distance is being
|
||||
modified */
|
||||
|
||||
Fl_Color mCursor_color;
|
||||
|
||||
@ -229,19 +278,15 @@ class FL_EXPORT Fl_Text_Display: public Fl_Group {
|
||||
uchar textsize_;
|
||||
unsigned textcolor_;
|
||||
|
||||
// The following are not presently used from the original NEdit
|
||||
// code, but are being put here so that future versions of
|
||||
// Fl_Text_Display can implement wrapping and line numbers
|
||||
// without breaking binary compatibility.
|
||||
// The following are not presently used from the original NEdit code,
|
||||
// but are being put here so that future versions of Fl_Text_Display
|
||||
// can implement line numbers without breaking binary compatibility.
|
||||
int mLineNumLeft, mLineNumWidth;
|
||||
/* Line number margin and width */
|
||||
int mContinuousWrap; /* Wrap long lines when displaying */
|
||||
int mWrapMargin; /* Margin in # of char positions for
|
||||
wrapping in continuousWrap mode */
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
//
|
||||
// End of "$Id: Fl_Text_Display.H,v 1.4.2.11 2002/08/14 16:49:38 easysw Exp $".
|
||||
// End of "$Id: Fl_Text_Display.H,v 1.4.2.12 2002/09/20 19:59:45 easysw Exp $".
|
||||
//
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// "$Id: Fl_Text_Buffer.cxx,v 1.9.2.11 2002/08/09 03:17:30 easysw Exp $"
|
||||
// "$Id: Fl_Text_Buffer.cxx,v 1.9.2.12 2002/09/20 19:59:45 easysw Exp $"
|
||||
//
|
||||
// Copyright 2001-2002 by Bill Spitzak and others.
|
||||
// Original code Copyright Mark Edel. Permission to distribute under
|
||||
@ -93,6 +93,9 @@ Fl_Text_Buffer::Fl_Text_Buffer( int requestedSize ) {
|
||||
mNodifyProcs = NULL;
|
||||
mCbArgs = NULL;
|
||||
mNModifyProcs = 0;
|
||||
mNPredeleteProcs = 0;
|
||||
mPredeleteProcs = NULL;
|
||||
mPredeleteCbArgs = NULL;
|
||||
mCursorPosHint = 0;
|
||||
mNullSubsChar = '\0';
|
||||
#ifdef PURIFY
|
||||
@ -109,6 +112,10 @@ Fl_Text_Buffer::~Fl_Text_Buffer() {
|
||||
free( ( void * ) mNodifyProcs );
|
||||
free( ( void * ) mCbArgs );
|
||||
}
|
||||
if ( mNPredeleteProcs != 0 ) {
|
||||
free( ( void * ) mPredeleteProcs );
|
||||
free( ( void * ) mPredeleteCbArgs );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -133,6 +140,8 @@ void Fl_Text_Buffer::text( const char *t ) {
|
||||
int insertedLength, deletedLength;
|
||||
const char *deletedText;
|
||||
|
||||
call_predelete_callbacks(0, length());
|
||||
|
||||
/* Save information for redisplay, and get rid of the old buffer */
|
||||
deletedText = text();
|
||||
deletedLength = mLength;
|
||||
@ -220,6 +229,9 @@ void Fl_Text_Buffer::insert( int pos, const char *s ) {
|
||||
if ( pos > mLength ) pos = mLength;
|
||||
if ( pos < 0 ) pos = 0;
|
||||
|
||||
/* Even if nothing is deleted, we must call these callbacks */
|
||||
call_predelete_callbacks( pos, 0 );
|
||||
|
||||
/* insert and redisplay */
|
||||
nInserted = insert_( pos, s );
|
||||
mCursorPosHint = pos + nInserted;
|
||||
@ -234,6 +246,7 @@ void Fl_Text_Buffer::replace( int start, int end, const char *s ) {
|
||||
const char * deletedText;
|
||||
int nInserted;
|
||||
|
||||
call_predelete_callbacks( start, end-start );
|
||||
deletedText = text_range( start, end );
|
||||
remove_( start, end );
|
||||
nInserted = insert_( start, s );
|
||||
@ -256,6 +269,7 @@ void Fl_Text_Buffer::remove( int start, int end ) {
|
||||
if ( end > mLength ) end = mLength;
|
||||
if ( end < 0 ) end = 0;
|
||||
|
||||
call_predelete_callbacks( start, end-start );
|
||||
/* Remove and redisplay */
|
||||
deletedText = text_range( start, end );
|
||||
remove_( start, end );
|
||||
@ -314,6 +328,7 @@ void Fl_Text_Buffer::insert_column( int column, int startPos, const char *s,
|
||||
lineStartPos = line_start( startPos );
|
||||
nDeleted = line_end( skip_lines( startPos, nLines ) ) -
|
||||
lineStartPos;
|
||||
call_predelete_callbacks( lineStartPos, nDeleted );
|
||||
deletedText = text_range( lineStartPos, lineStartPos + nDeleted );
|
||||
insert_column_( column, lineStartPos, s, &insertDeleted, &nInserted,
|
||||
&mCursorPosHint );
|
||||
@ -342,6 +357,7 @@ void Fl_Text_Buffer::overlay_rectangular( int startPos, int rectStart,
|
||||
lineStartPos = line_start( startPos );
|
||||
nDeleted = line_end( skip_lines( startPos, nLines ) ) -
|
||||
lineStartPos;
|
||||
call_predelete_callbacks( lineStartPos, nDeleted );
|
||||
deletedText = text_range( lineStartPos, lineStartPos + nDeleted );
|
||||
overlay_rectangular_( lineStartPos, rectStart, rectEnd, s, &insertDeleted,
|
||||
&nInserted, &mCursorPosHint );
|
||||
@ -374,6 +390,8 @@ void Fl_Text_Buffer::replace_rectangular( int start, int end, int rectStart,
|
||||
start = line_start( start );
|
||||
end = line_end( end );
|
||||
|
||||
call_predelete_callbacks( start, end-start );
|
||||
|
||||
/* If more lines will be deleted than inserted, pad the inserted text
|
||||
with newlines to make it as long as the number of deleted lines. This
|
||||
will indent all of the text to the right of the rectangle to the same
|
||||
@ -424,6 +442,7 @@ void Fl_Text_Buffer::remove_rectangular( int start, int end, int rectStart,
|
||||
|
||||
start = line_start( start );
|
||||
end = line_end( end );
|
||||
call_predelete_callbacks( start, end-start );
|
||||
deletedText = text_range( start, end );
|
||||
remove_rectangular_( start, end, rectStart, rectEnd, &nInserted,
|
||||
&mCursorPosHint );
|
||||
@ -492,6 +511,10 @@ char * Fl_Text_Buffer::text_in_rectangle( int start, int end,
|
||||
void Fl_Text_Buffer::tab_distance( int tabDist ) {
|
||||
const char * deletedText;
|
||||
|
||||
/* First call the pre-delete callbacks with the previous tab setting
|
||||
still active. */
|
||||
call_predelete_callbacks( 0, mLength );
|
||||
|
||||
/* Change the tab setting */
|
||||
mTabDist = tabDist;
|
||||
|
||||
@ -692,6 +715,80 @@ void Fl_Text_Buffer::remove_modify_callback( Fl_Text_Modify_Cb bufModifiedCB,
|
||||
mCbArgs = newCBArgs;
|
||||
}
|
||||
|
||||
/*
|
||||
** Add a callback routine to be called before text is deleted from the buffer.
|
||||
*/
|
||||
void Fl_Text_Buffer::add_predelete_callback(Fl_Text_Predelete_Cb bufPreDeleteCB,
|
||||
void *cbArg) {
|
||||
Fl_Text_Predelete_Cb *newPreDeleteProcs;
|
||||
void **newCBArgs;
|
||||
int i;
|
||||
|
||||
newPreDeleteProcs = new Fl_Text_Predelete_Cb[ mNPredeleteProcs + 1 ];
|
||||
newCBArgs = new void * [ mNPredeleteProcs + 1 ];
|
||||
for ( i = 0; i < mNPredeleteProcs; i++ ) {
|
||||
newPreDeleteProcs[i + 1] = mPredeleteProcs[i];
|
||||
newCBArgs[i + 1] = mPredeleteCbArgs[i];
|
||||
}
|
||||
if (! mNPredeleteProcs != 0) {
|
||||
delete [] mPredeleteProcs;
|
||||
delete [] mPredeleteCbArgs;
|
||||
}
|
||||
newPreDeleteProcs[0] = bufPreDeleteCB;
|
||||
newCBArgs[0] = cbArg;
|
||||
mNPredeleteProcs++;
|
||||
mPredeleteProcs = newPreDeleteProcs;
|
||||
mPredeleteCbArgs = newCBArgs;
|
||||
}
|
||||
|
||||
void Fl_Text_Buffer::remove_predelete_callback(
|
||||
Fl_Text_Predelete_Cb bufPreDeleteCB, void *cbArg) {
|
||||
int i, toRemove = -1;
|
||||
Fl_Text_Predelete_Cb *newPreDeleteProcs;
|
||||
void **newCBArgs;
|
||||
|
||||
/* find the matching callback to remove */
|
||||
for ( i = 0; i < mNPredeleteProcs; i++) {
|
||||
if (mPredeleteProcs[i] == bufPreDeleteCB &&
|
||||
mPredeleteCbArgs[i] == cbArg) {
|
||||
toRemove = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (toRemove == -1) {
|
||||
fprintf(stderr, "Internal Error: Can't find pre-delete CB to remove\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Allocate new lists for remaining callback procs and args (if
|
||||
any are left) */
|
||||
mNPredeleteProcs--;
|
||||
if (mNPredeleteProcs == 0) {
|
||||
mNPredeleteProcs = 0;
|
||||
delete[] mPredeleteProcs;
|
||||
mPredeleteProcs = NULL;
|
||||
delete[] mPredeleteCbArgs;
|
||||
mPredeleteCbArgs = NULL;
|
||||
return;
|
||||
}
|
||||
newPreDeleteProcs = new Fl_Text_Predelete_Cb [ mNPredeleteProcs ];
|
||||
newCBArgs = new void * [ mNPredeleteProcs ];
|
||||
|
||||
/* copy out the remaining members and free the old lists */
|
||||
for ( i = 0; i < toRemove; i++) {
|
||||
newPreDeleteProcs[i] = mPredeleteProcs[i];
|
||||
newCBArgs[i] = mPredeleteCbArgs[i];
|
||||
}
|
||||
for ( ; i < mNPredeleteProcs; i++) {
|
||||
newPreDeleteProcs[i] = mPredeleteProcs[i+1];
|
||||
newCBArgs[i] = mPredeleteCbArgs[i+1];
|
||||
}
|
||||
delete[] mPredeleteProcs;
|
||||
delete[] mPredeleteCbArgs;
|
||||
mPredeleteProcs = newPreDeleteProcs;
|
||||
mPredeleteCbArgs = newCBArgs;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the text from the entire line containing position "pos"
|
||||
*/
|
||||
@ -1810,6 +1907,17 @@ void Fl_Text_Buffer::call_modify_callbacks( int pos, int nDeleted,
|
||||
deletedText, mCbArgs[ i ] );
|
||||
}
|
||||
|
||||
/*
|
||||
** Call the stored pre-delete callback procedure(s) for this buffer to update
|
||||
** the changed area(s) on the screen and any other listeners.
|
||||
*/
|
||||
void Fl_Text_Buffer::call_predelete_callbacks(int pos, int nDeleted) {
|
||||
int i;
|
||||
|
||||
for (i=0; i<mNPredeleteProcs; i++)
|
||||
(*mPredeleteProcs[i])(pos, nDeleted, mPredeleteCbArgs[i]);
|
||||
}
|
||||
|
||||
/*
|
||||
** Call the stored redisplay procedure(s) for this buffer to update the
|
||||
** screen for a change in a selection.
|
||||
@ -2289,5 +2397,5 @@ Fl_Text_Buffer::outputfile(const char *file, int start, int end, int buflen) {
|
||||
|
||||
|
||||
//
|
||||
// End of "$Id: Fl_Text_Buffer.cxx,v 1.9.2.11 2002/08/09 03:17:30 easysw Exp $".
|
||||
// End of "$Id: Fl_Text_Buffer.cxx,v 1.9.2.12 2002/09/20 19:59:45 easysw Exp $".
|
||||
//
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
//
|
||||
// "$Id: editor.cxx,v 1.2.2.3.2.13 2002/07/14 21:25:39 easysw Exp $"
|
||||
// "$Id: editor.cxx,v 1.2.2.3.2.14 2002/09/20 19:59:45 easysw Exp $"
|
||||
//
|
||||
// A simple text editor program for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
@ -306,7 +306,7 @@ style_init(void) {
|
||||
//
|
||||
|
||||
void
|
||||
style_unfinished_cb() {
|
||||
style_unfinished_cb(int, void*) {
|
||||
}
|
||||
|
||||
|
||||
@ -762,5 +762,5 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
|
||||
//
|
||||
// End of "$Id: editor.cxx,v 1.2.2.3.2.13 2002/07/14 21:25:39 easysw Exp $".
|
||||
// End of "$Id: editor.cxx,v 1.2.2.3.2.14 2002/09/20 19:59:45 easysw Exp $".
|
||||
//
|
||||
|
Loading…
Reference in New Issue
Block a user