You've already forked lazarus-ccr
richmemo: introduced GetText (GetUText). default and win32 implementation
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@4077 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -242,6 +242,8 @@ type
|
|||||||
|
|
||||||
function InDelText(const UTF8Text: string; InsStartChar, ReplaceLength: Integer): Integer; virtual;
|
function InDelText(const UTF8Text: string; InsStartChar, ReplaceLength: Integer): Integer; virtual;
|
||||||
function InDelInline(inlineobj: TRichMemoInline; InsStartChar, ReplaceLength: Integer; const ASize: TSize): Integer; virtual;
|
function InDelInline(inlineobj: TRichMemoInline; InsStartChar, ReplaceLength: Integer; const ASize: TSize): Integer; virtual;
|
||||||
|
function GetText(TextStart, TextLength: Integer): String;
|
||||||
|
function GetUText(TextStart, TextLength: Integer): UnicodeString;
|
||||||
|
|
||||||
procedure SetSelLengthFor(const aselstr: string);
|
procedure SetSelLengthFor(const aselstr: string);
|
||||||
|
|
||||||
@ -295,6 +297,7 @@ type
|
|||||||
property OnKeyDown;
|
property OnKeyDown;
|
||||||
property OnKeyPress;
|
property OnKeyPress;
|
||||||
property OnKeyUp;
|
property OnKeyUp;
|
||||||
|
property OnLinkAction;
|
||||||
property OnMouseDown;
|
property OnMouseDown;
|
||||||
property OnMouseEnter;
|
property OnMouseEnter;
|
||||||
property OnMouseLeave;
|
property OnMouseLeave;
|
||||||
@ -967,6 +970,34 @@ begin
|
|||||||
inlineObj.Free;
|
inlineObj.Free;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TCustomRichMemo.GetText(TextStart, TextLength: Integer): String;
|
||||||
|
var
|
||||||
|
isu : Boolean;
|
||||||
|
txt : String;
|
||||||
|
utxt : UnicodeString;
|
||||||
|
begin
|
||||||
|
Result:='';
|
||||||
|
if not HandleAllocated then HandleNeeded;
|
||||||
|
if HandleAllocated and not TWSCustomRichMemoClass(WidgetSetClass).GetSubText(Self, TextStart, TextLength, false, isu, txt, utxt) then
|
||||||
|
Exit;
|
||||||
|
if isu then Result:=UTF8Decode(utxt)
|
||||||
|
else Result:=txt;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TCustomRichMemo.GetUText(TextStart, TextLength: Integer): UnicodeString;
|
||||||
|
var
|
||||||
|
isu : Boolean;
|
||||||
|
txt : String;
|
||||||
|
utxt : UnicodeString;
|
||||||
|
begin
|
||||||
|
Result:='';
|
||||||
|
if not HandleAllocated then HandleNeeded;
|
||||||
|
if HandleAllocated and not TWSCustomRichMemoClass(WidgetSetClass).GetSubText(Self, TextStart, TextLength, false, isu, txt, utxt) then
|
||||||
|
Exit;
|
||||||
|
if isu then Result:=utxt
|
||||||
|
else Result:=UTF8Encode(txt);
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TCustomRichMemo.SetSelLengthFor(const aselstr: string);
|
procedure TCustomRichMemo.SetSelLengthFor(const aselstr: string);
|
||||||
begin
|
begin
|
||||||
SelLength:=UTF8Length(aselstr);
|
SelLength:=UTF8Length(aselstr);
|
||||||
|
@ -38,33 +38,25 @@ uses
|
|||||||
|
|
||||||
type
|
type
|
||||||
|
|
||||||
|
{ TWin32RichMemoStrings }
|
||||||
|
|
||||||
TWin32RichMemoStrings = class(TWin32MemoStrings)
|
TWin32RichMemoStrings = class(TWin32MemoStrings)
|
||||||
protected
|
protected
|
||||||
fUpd : Boolean;
|
fUpd : Boolean;
|
||||||
fHandle : HWND;
|
fHandle : HWND;
|
||||||
procedure SetUpdateState(Updating: Boolean); override;
|
procedure SetUpdateState(Updating: Boolean); override;
|
||||||
|
function GetTextStr: string; override;
|
||||||
public
|
public
|
||||||
constructor Create(AHandle: HWND; TheOwner: TWinControl);
|
constructor Create(AHandle: HWND; TheOwner: TWinControl);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TWin32RichMemoStringsW }
|
|
||||||
|
|
||||||
TWin32RichMemoStringsW = class(TWin32RichMemoStrings)
|
|
||||||
protected
|
|
||||||
function GetTextStr: string; override;
|
|
||||||
end;
|
|
||||||
|
|
||||||
{ TWin32RichMemoStringsA }
|
|
||||||
|
|
||||||
TWin32RichMemoStringsA = class(TWin32RichMemoStrings)
|
|
||||||
protected
|
|
||||||
function GetTextStr: string; override;
|
|
||||||
end;
|
|
||||||
|
|
||||||
{ TWin32WSCustomRichMemo }
|
{ TWin32WSCustomRichMemo }
|
||||||
|
|
||||||
TWin32WSCustomRichMemo = class(TWSCustomRichMemo)
|
TWin32WSCustomRichMemo = class(TWSCustomRichMemo)
|
||||||
published
|
published
|
||||||
|
class function GetText(const AWinControl: TWinControl; var AText: String): Boolean; override;
|
||||||
|
class function GetTextLen(const AWinControl: TWinControl; var ALength: Integer): Boolean; override;
|
||||||
|
|
||||||
class function GetStrings(const ACustomMemo: TCustomMemo): TStrings; override;
|
class function GetStrings(const ACustomMemo: TCustomMemo): TStrings; override;
|
||||||
class procedure SetColor(const AWinControl: TWinControl); override;
|
class procedure SetColor(const AWinControl: TWinControl); override;
|
||||||
|
|
||||||
@ -114,6 +106,8 @@ type
|
|||||||
var AStopList: TTabStopList): Boolean; override;
|
var AStopList: TTabStopList): Boolean; override;
|
||||||
|
|
||||||
class procedure InDelText(const AWinControl: TWinControl; const TextUTF8: String; DstStart, DstLen: Integer); override;
|
class procedure InDelText(const AWinControl: TWinControl; const TextUTF8: String; DstStart, DstLen: Integer); override;
|
||||||
|
class function GetSubText(const AWinControl: TWinControl; TextStart, TextLen: Integer;
|
||||||
|
AsUnicode: Boolean; var isUnicode: Boolean; var txt: string; var utxt: UnicodeString): Boolean; override;
|
||||||
|
|
||||||
class function Search(const AWinControl: TWinControl; const ANiddle: string;
|
class function Search(const AWinControl: TWinControl; const ANiddle: string;
|
||||||
const SearchOpts: TIntSearchOpt): Integer; override;
|
const SearchOpts: TIntSearchOpt): Integer; override;
|
||||||
@ -341,64 +335,39 @@ begin
|
|||||||
inherited SetUpdateState(Updating);
|
inherited SetUpdateState(Updating);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TWin32RichMemoStringsW }
|
function TWin32RichMemoStrings.GetTextStr: string;
|
||||||
|
|
||||||
function TWin32RichMemoStringsW.GetTextStr: string;
|
|
||||||
var
|
|
||||||
p : GETTEXTLENGTHEX;
|
|
||||||
t : GETTEXTEX;
|
|
||||||
res : Integer;
|
|
||||||
w : WideString;
|
|
||||||
begin
|
begin
|
||||||
fillchar(p, sizeof(p), 0);
|
if Assigned(RichEditManager) then
|
||||||
p.flags:=GTL_DEFAULT or GTL_PRECISE or GTL_NUMCHARS;
|
Result:=RichEditManager.GetTextUtf8(fHandle, false)
|
||||||
res := SendMessageW(fHandle, EM_GETTEXTLENGTHEX, WPARAM(@P), CP_WINUNICODE);
|
else
|
||||||
if res>0 then begin
|
|
||||||
SetLength(w, res);
|
|
||||||
FillChar(t, sizeof(t), 0);
|
|
||||||
t.cb:=(length(w)+1)*sizeof(WideChar);
|
|
||||||
t.flags:=GT_DEFAULT;
|
|
||||||
t.codepage:=CP_WINUNICODE;
|
|
||||||
res:=SendMessageW(fHandle, EM_GETTEXTEX, WPARAM(@t), LPARAM(@w[1]));
|
|
||||||
Result:=UTF8Encode(w);
|
|
||||||
end else
|
|
||||||
Result:='';
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
{ TWin32RichMemoStringsA }
|
|
||||||
|
|
||||||
function TWin32RichMemoStringsA.GetTextStr: string;
|
|
||||||
var
|
|
||||||
p : GETTEXTLENGTHEX;
|
|
||||||
t : GETTEXTEX;
|
|
||||||
res : Integer;
|
|
||||||
s : WideString;
|
|
||||||
begin
|
|
||||||
fillchar(p, sizeof(p), 0);
|
|
||||||
p.flags:=GTL_DEFAULT or GTL_PRECISE or GTL_NUMBYTES;
|
|
||||||
res := SendMessageW(fHandle, EM_GETTEXTLENGTHEX, WPARAM(@P), CP_ACP);
|
|
||||||
if res>0 then begin
|
|
||||||
SetLength(s, res);
|
|
||||||
FillChar(t, sizeof(t), 0);
|
|
||||||
t.cb:=length(s)+1;
|
|
||||||
t.flags:=GT_DEFAULT;
|
|
||||||
t.codepage:=CP_ACP;
|
|
||||||
res:=SendMessageW(fHandle, EM_GETTEXTEX, WPARAM(@t), LPARAM(@s[1]));
|
|
||||||
Result:=AnsiToUtf8(s);
|
|
||||||
end else
|
|
||||||
Result:='';
|
Result:='';
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TWin32WSCustomRichMemo }
|
{ TWin32WSCustomRichMemo }
|
||||||
|
|
||||||
|
class function TWin32WSCustomRichMemo.GetText(const AWinControl: TWinControl;
|
||||||
|
var AText: String): Boolean;
|
||||||
|
begin
|
||||||
|
Result:=Assigned(RichEditManager);
|
||||||
|
if Result then
|
||||||
|
AText:=RichEditManager.GetTextUtf8(AWinControl.Handle, false);
|
||||||
|
end;
|
||||||
|
|
||||||
|
class function TWin32WSCustomRichMemo.GetTextLen(
|
||||||
|
const AWinControl: TWinControl; var ALength: Integer): Boolean;
|
||||||
|
begin
|
||||||
|
Result:=false;
|
||||||
|
ALength:=0;
|
||||||
|
if not Assigned(RichEditManager) or not Assigned(AWinControl) then Exit;
|
||||||
|
|
||||||
|
Result:=true;
|
||||||
|
ALength:=RichEditManager.GetTextLength(AWinControl.Handle);
|
||||||
|
end;
|
||||||
|
|
||||||
class function TWin32WSCustomRichMemo.GetStrings(const ACustomMemo: TCustomMemo
|
class function TWin32WSCustomRichMemo.GetStrings(const ACustomMemo: TCustomMemo
|
||||||
): TStrings;
|
): TStrings;
|
||||||
begin
|
begin
|
||||||
if UnicodeEnabledOS then
|
Result := TWin32RichMemoStrings.Create(ACustomMemo.Handle, ACustomMemo)
|
||||||
Result := TWin32RichMemoStringsW.Create(ACustomMemo.Handle, ACustomMemo)
|
|
||||||
else
|
|
||||||
Result := TWin32RichMemoStringsA.Create(ACustomMemo.Handle, ACustomMemo);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
class procedure TWin32WSCustomRichMemo.SetColor(const AWinControl: TWinControl);
|
class procedure TWin32WSCustomRichMemo.SetColor(const AWinControl: TWinControl);
|
||||||
@ -979,6 +948,44 @@ begin
|
|||||||
RichEditManager.SetEventMask(AWinControl.Handle, eventmask);
|
RichEditManager.SetEventMask(AWinControl.Handle, eventmask);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
class function TWin32WSCustomRichMemo.GetSubText(
|
||||||
|
const AWinControl: TWinControl; TextStart, TextLen: Integer;
|
||||||
|
AsUnicode: Boolean; var isUnicode: Boolean; var txt: string;
|
||||||
|
var utxt: UnicodeString): Boolean;
|
||||||
|
var
|
||||||
|
eventmask : Integer;
|
||||||
|
OrigStart : Integer;
|
||||||
|
OrigLen : Integer;
|
||||||
|
NeedLock : Boolean;
|
||||||
|
Hnd : THandle;
|
||||||
|
begin
|
||||||
|
Result:=Assigned(RichEditManager) and Assigned(AWinControl);
|
||||||
|
if not Result then Exit;
|
||||||
|
|
||||||
|
Hnd:=AWinControl.Handle;
|
||||||
|
eventmask := RichEditManager.SetEventMask(Hnd, 0);
|
||||||
|
RichEditManager.GetSelection(Hnd, OrigStart, OrigLen);
|
||||||
|
|
||||||
|
NeedLock := (OrigStart <> TextStart) or (OrigLen <> TextLen);
|
||||||
|
if NeedLock then begin
|
||||||
|
LockRedraw( TCustomRichMemo(AWinControl), Hnd);
|
||||||
|
RichEditManager.SetSelection(Hnd, TextStart, TextLen);
|
||||||
|
end;
|
||||||
|
|
||||||
|
isUnicode:=AsUnicode;
|
||||||
|
if AsUnicode then
|
||||||
|
utxt:=RichEditManager.GetTextW(Hnd, true)
|
||||||
|
else begin
|
||||||
|
txt:=RichEditManager.GetTextUtf8(Hnd, true);
|
||||||
|
end;
|
||||||
|
|
||||||
|
if NeedLock then begin
|
||||||
|
RichEditManager.SetSelection(Hnd, OrigStart, OrigLen);
|
||||||
|
UnlockRedraw( TCustomRichMemo(AWinControl), Hnd);
|
||||||
|
end;
|
||||||
|
RichEditManager.SetEventMask(Hnd, eventmask);
|
||||||
|
end;
|
||||||
|
|
||||||
class function TWin32WSCustomRichMemo.Search(const AWinControl: TWinControl;
|
class function TWin32WSCustomRichMemo.Search(const AWinControl: TWinControl;
|
||||||
const ANiddle: string; const SearchOpts: TIntSearchOpt): Integer;
|
const ANiddle: string; const SearchOpts: TIntSearchOpt): Integer;
|
||||||
begin
|
begin
|
||||||
|
@ -174,7 +174,12 @@ type
|
|||||||
class procedure SetHideSelection(RichEditWnd: Handle; AValue: Boolean); virtual;
|
class procedure SetHideSelection(RichEditWnd: Handle; AValue: Boolean); virtual;
|
||||||
class function LoadRichText(RichEditWnd: Handle; ASrc: TStream): Boolean; virtual;
|
class function LoadRichText(RichEditWnd: Handle; ASrc: TStream): Boolean; virtual;
|
||||||
class function SaveRichText(RichEditWnd: Handle; ADst: TStream): Boolean; virtual;
|
class function SaveRichText(RichEditWnd: Handle; ADst: TStream): Boolean; virtual;
|
||||||
|
|
||||||
class procedure SetText(RichEditWnd: Handle; const Text: WideString; TextStart, ReplaceLength: Integer); virtual;
|
class procedure SetText(RichEditWnd: Handle; const Text: WideString; TextStart, ReplaceLength: Integer); virtual;
|
||||||
|
class function GetTextW(RichEditWnd: Handle; inSelection: Boolean): WideString; virtual;
|
||||||
|
class function GetTextA(RichEditWnd: Handle; inSelection: Boolean): AnsiString; virtual;
|
||||||
|
class function GetTextUtf8(RichEditWnd: Handle; inSelection: Boolean): string;
|
||||||
|
|
||||||
class procedure GetPara2(RichEditWnd: Handle; TextStart: Integer; var para: PARAFORMAT2); virtual;
|
class procedure GetPara2(RichEditWnd: Handle; TextStart: Integer; var para: PARAFORMAT2); virtual;
|
||||||
class procedure SetPara2(RichEditWnd: Handle; TextStart, TextLen: Integer; const para: PARAFORMAT2); virtual;
|
class procedure SetPara2(RichEditWnd: Handle; TextStart, TextLen: Integer; const para: PARAFORMAT2); virtual;
|
||||||
class function Find(RichEditWnd: THandle; const ANiddle: WideString; const ASearch: TIntSearchOpt): Integer; virtual;
|
class function Find(RichEditWnd: THandle; const ANiddle: WideString; const ASearch: TIntSearchOpt): Integer; virtual;
|
||||||
@ -192,8 +197,9 @@ function FontStylesToEffects(Styles: TFontStyles): LongWord;
|
|||||||
function EffectsToFontStyles(Effects: LongWord): TFontStyles;
|
function EffectsToFontStyles(Effects: LongWord): TFontStyles;
|
||||||
|
|
||||||
const
|
const
|
||||||
CP_UNICODE = 1200;
|
GT_SELECTION = 2;
|
||||||
HardBreak = #13;
|
CP_UNICODE = 1200;
|
||||||
|
HardBreak = #13;
|
||||||
|
|
||||||
const
|
const
|
||||||
CFE_PROTECTED = $00000010;
|
CFE_PROTECTED = $00000010;
|
||||||
@ -643,6 +649,66 @@ begin
|
|||||||
SetSelection(RichEditWnd, s, l);
|
SetSelection(RichEditWnd, s, l);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
class function TRichEditManager.GetTextW(RichEditWnd: Handle;
|
||||||
|
inSelection: Boolean): WideString;
|
||||||
|
var
|
||||||
|
t : GETTEXTEX;
|
||||||
|
res : Integer;
|
||||||
|
w : WideString;
|
||||||
|
st : Integer;
|
||||||
|
begin
|
||||||
|
if inSelection then
|
||||||
|
GetSelection(RichEditWnd, st, res)
|
||||||
|
else
|
||||||
|
res:=GetTextLength(RichEditWnd);
|
||||||
|
|
||||||
|
if res>0 then begin
|
||||||
|
SetLength(w, res);
|
||||||
|
FillChar(t, sizeof(t), 0);
|
||||||
|
t.cb:=(length(w)+1)*sizeof(WideChar);
|
||||||
|
t.flags:=GT_DEFAULT;
|
||||||
|
if inSelection then t.flags:=t.flags or GT_SELECTION;
|
||||||
|
t.codepage:=CP_WINUNICODE;
|
||||||
|
res:=SendMessageW(RichEditWnd, EM_GETTEXTEX, WPARAM(@t), LPARAM(@w[1]));
|
||||||
|
Result:=w;
|
||||||
|
end else
|
||||||
|
Result:='';
|
||||||
|
end;
|
||||||
|
|
||||||
|
class function TRichEditManager.GetTextA(RichEditWnd: Handle;
|
||||||
|
inSelection: Boolean): AnsiString;
|
||||||
|
var
|
||||||
|
t : GETTEXTEX;
|
||||||
|
res : Integer;
|
||||||
|
s : AnsiString;
|
||||||
|
st : Integer;
|
||||||
|
begin
|
||||||
|
if inSelection then
|
||||||
|
GetSelection(RichEditWnd, st, res)
|
||||||
|
else
|
||||||
|
res:=GetTextLength(RichEditWnd);
|
||||||
|
|
||||||
|
if res>0 then begin
|
||||||
|
SetLength(s, res);
|
||||||
|
FillChar(t, sizeof(t), 0);
|
||||||
|
t.cb:=length(s)+1;
|
||||||
|
t.flags:=GT_DEFAULT;
|
||||||
|
t.codepage:=CP_ACP;
|
||||||
|
res:=SendMessageA(RichEditWnd, EM_GETTEXTEX, WPARAM(@t), LPARAM(@s[1]));
|
||||||
|
Result:=s;
|
||||||
|
end else
|
||||||
|
Result:='';
|
||||||
|
end;
|
||||||
|
|
||||||
|
class function TRichEditManager.GetTextUtf8(RichEditWnd: Handle;
|
||||||
|
inSelection: Boolean): string;
|
||||||
|
begin
|
||||||
|
if UnicodeEnabledOS then
|
||||||
|
Result:=UTF8Encode(GetTextW(RichEditWnd, inSelection))
|
||||||
|
else
|
||||||
|
Result:=AnsiToUtf8(GetTextA(RichEditWnd, inSelection));
|
||||||
|
end;
|
||||||
|
|
||||||
class procedure TRichEditManager.GetPara2(RichEditWnd: Handle; TextStart: Integer;
|
class procedure TRichEditManager.GetPara2(RichEditWnd: Handle; TextStart: Integer;
|
||||||
var para: PARAFORMAT2);
|
var para: PARAFORMAT2);
|
||||||
var
|
var
|
||||||
|
@ -26,6 +26,7 @@ interface
|
|||||||
uses
|
uses
|
||||||
Types, Classes, SysUtils,
|
Types, Classes, SysUtils,
|
||||||
LCLType,
|
LCLType,
|
||||||
|
LazUTF8, // used for GetSubText
|
||||||
Graphics, Controls, Printers,
|
Graphics, Controls, Printers,
|
||||||
WSStdCtrls, RichMemo;
|
WSStdCtrls, RichMemo;
|
||||||
|
|
||||||
@ -84,6 +85,9 @@ type
|
|||||||
var ui: TTextUIParam): Boolean; virtual;
|
var ui: TTextUIParam): Boolean; virtual;
|
||||||
|
|
||||||
class procedure InDelText(const AWinControl: TWinControl; const TextUTF8: String; DstStart, DstLen: Integer); virtual;
|
class procedure InDelText(const AWinControl: TWinControl; const TextUTF8: String; DstStart, DstLen: Integer); virtual;
|
||||||
|
class function GetSubText(const AWinControl: TWinControl; TextStart, TextLen: Integer;
|
||||||
|
AsUnicode: Boolean; var isUnicode: Boolean; var txt: string; var utxt: UnicodeString): Boolean; virtual;
|
||||||
|
|
||||||
//class procedure SetHideSelection(const ACustomEdit: TCustomEdit; AHideSelection: Boolean); override;
|
//class procedure SetHideSelection(const ACustomEdit: TCustomEdit; AHideSelection: Boolean); override;
|
||||||
class function LoadRichText(const AWinControl: TWinControl; Source: TStream): Boolean; virtual;
|
class function LoadRichText(const AWinControl: TWinControl; Source: TStream): Boolean; virtual;
|
||||||
class function SaveRichText(const AWinControl: TWinControl; Dest: TStream): Boolean; virtual;
|
class function SaveRichText(const AWinControl: TWinControl; Dest: TStream): Boolean; virtual;
|
||||||
@ -224,6 +228,22 @@ begin
|
|||||||
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
class function TWSCustomRichMemo.GetSubText(const AWinControl: TWinControl;
|
||||||
|
TextStart, TextLen: Integer; AsUnicode: Boolean; var isUnicode: Boolean;
|
||||||
|
var txt: string; var utxt: UnicodeString): Boolean;
|
||||||
|
begin
|
||||||
|
// default, ineffecient implementation
|
||||||
|
if TextLen<0 then GetTextLen(AWinControl, TextLen);
|
||||||
|
Result:=GetText(AWinControl, txt);
|
||||||
|
if not Result then Exit;
|
||||||
|
if TextStart<0 then TextStart:=0;
|
||||||
|
inc(TextStart);
|
||||||
|
utxt:='';
|
||||||
|
isUnicode:=false;
|
||||||
|
txt:=UTF8Copy(txt, TextStart, TextLen);
|
||||||
|
Result:=true;
|
||||||
|
end;
|
||||||
|
|
||||||
{class procedure TWSCustomRichMemo.SetHideSelection(const ACustomEdit: TCustomEdit; AHideSelection: Boolean);
|
{class procedure TWSCustomRichMemo.SetHideSelection(const ACustomEdit: TCustomEdit; AHideSelection: Boolean);
|
||||||
begin
|
begin
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user