1. fixed Maximise() mismatch between wxFrame and wxMDIFrame
2. tried (unsuccessfully) to fix the warning in pnghand.cpp 3. fixes for VC and BCC makefiles generation with tmake (still untested) git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@3021 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -28,8 +28,11 @@
|
|||||||
#! needs extra files (sql*.h) so not compiled by default.
|
#! needs extra files (sql*.h) so not compiled by default.
|
||||||
next if $file =~ /^odbc\./;
|
next if $file =~ /^odbc\./;
|
||||||
|
|
||||||
|
$isCFile = $file =~ /\.c$/;
|
||||||
$file =~ s/cp?p?$/obj/;
|
$file =~ s/cp?p?$/obj/;
|
||||||
$project{"WXCOMMONOBJS"} .= "\$(MSWDIR)\\" . $file . " "
|
$obj = "\$(MSWDIR)\\" . $file . " ";
|
||||||
|
$project{"WXCOMMONOBJS"} .= $obj;
|
||||||
|
$project{"WXCOBJS"} .= $obj if $isCFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
#! special hack for Borland in 16 bits needs this file
|
#! special hack for Borland in 16 bits needs this file
|
||||||
@@ -172,8 +175,9 @@ $(COMMDIR)\lex_yy.c: $(COMMDIR)\doslex.c
|
|||||||
my @objs = split;
|
my @objs = split;
|
||||||
foreach (@objs) {
|
foreach (@objs) {
|
||||||
$text .= $_ . ": ";
|
$text .= $_ . ": ";
|
||||||
|
$suffix = $project{"WXCOBJS"} =~ /\Q$_/ ? "c" : '$(SRCSUFF)';
|
||||||
s/MSWDIR/COMMDIR/;
|
s/MSWDIR/COMMDIR/;
|
||||||
s/obj/\$(SRCSUFF)/;
|
s/obj/$suffix/;
|
||||||
$text .= $_ . "\n\n";
|
$text .= $_ . "\n\n";
|
||||||
}
|
}
|
||||||
#$}
|
#$}
|
||||||
|
@@ -9,8 +9,6 @@
|
|||||||
#${
|
#${
|
||||||
open(FILELIST, "filelist.txt") or die "Can't open filelist file: $!\n";
|
open(FILELIST, "filelist.txt") or die "Can't open filelist file: $!\n";
|
||||||
|
|
||||||
my %wxfiles;
|
|
||||||
|
|
||||||
line: while ( defined($_ = <FILELIST>) ) {
|
line: while ( defined($_ = <FILELIST>) ) {
|
||||||
chomp;
|
chomp;
|
||||||
|
|
||||||
|
@@ -185,7 +185,7 @@ metafile.cpp M
|
|||||||
minifram.cpp M
|
minifram.cpp M
|
||||||
msgdlg.cpp M
|
msgdlg.cpp M
|
||||||
nativdlg.cpp M
|
nativdlg.cpp M
|
||||||
notebook.cpp M
|
notebook.cpp M 32
|
||||||
oleutils.cpp M O
|
oleutils.cpp M O
|
||||||
ownerdrw.cpp M
|
ownerdrw.cpp M
|
||||||
palette.cpp M
|
palette.cpp M
|
||||||
|
@@ -102,6 +102,11 @@ $(CPPFLAGS) /Fo$@ /c /Tp $<
|
|||||||
$(CPPFLAGS) /Fo$@ /c /Tp $<
|
$(CPPFLAGS) /Fo$@ /c /Tp $<
|
||||||
<<
|
<<
|
||||||
|
|
||||||
|
{..\common}.c{..\common\$D}.obj:
|
||||||
|
cl @<<
|
||||||
|
$(CPPFLAGS) /Fo$@ /c /Tc $<
|
||||||
|
<<
|
||||||
|
|
||||||
{..\msw}.cpp{..\msw\$D}.obj:
|
{..\msw}.cpp{..\msw\$D}.obj:
|
||||||
cl @<<
|
cl @<<
|
||||||
$(CPPFLAGS) /Fo$@ /c /Tp $<
|
$(CPPFLAGS) /Fo$@ /c /Tp $<
|
||||||
|
@@ -143,7 +143,7 @@ public:
|
|||||||
const wxString& name = wxFrameNameStr);
|
const wxString& name = wxFrameNameStr);
|
||||||
|
|
||||||
// MDI operations
|
// MDI operations
|
||||||
virtual void Maximize();
|
virtual void Maximize(bool maximize = TRUE);
|
||||||
virtual void Restore();
|
virtual void Restore();
|
||||||
virtual void Activate();
|
virtual void Activate();
|
||||||
|
|
||||||
|
@@ -105,7 +105,7 @@ BEGIN_EVENT_TABLE(MyFrame, wxFrame)
|
|||||||
EVT_MENU(Minimal_Quit, MyFrame::OnQuit)
|
EVT_MENU(Minimal_Quit, MyFrame::OnQuit)
|
||||||
EVT_MENU(Minimal_About, MyFrame::OnAbout)
|
EVT_MENU(Minimal_About, MyFrame::OnAbout)
|
||||||
|
|
||||||
EVT_BUTTON(-1, MyFrame::OnTest)
|
EVT_MENU(Minimal_Test, MyFrame::OnTest)
|
||||||
|
|
||||||
EVT_PAINT(MyFrame::OnPaint)
|
EVT_PAINT(MyFrame::OnPaint)
|
||||||
END_EVENT_TABLE()
|
END_EVENT_TABLE()
|
||||||
@@ -159,6 +159,7 @@ MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
|
|||||||
wxMenu *menuFile = new wxMenu(wxMENU_TEAROFF);
|
wxMenu *menuFile = new wxMenu(wxMENU_TEAROFF);
|
||||||
|
|
||||||
menuFile->Append(Minimal_About, "&About...\tCtrl-A", "Show about dialog");
|
menuFile->Append(Minimal_About, "&About...\tCtrl-A", "Show about dialog");
|
||||||
|
menuFile->Append(Minimal_Test, "&Test...\tCtrl-T", "Test");
|
||||||
menuFile->AppendSeparator();
|
menuFile->AppendSeparator();
|
||||||
menuFile->Append(Minimal_Quit, "E&xit\tAlt-X", "Quit this program");
|
menuFile->Append(Minimal_Quit, "E&xit\tAlt-X", "Quit this program");
|
||||||
|
|
||||||
@@ -202,8 +203,52 @@ void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
|
|||||||
wxMessageBox(msg, "About Minimal", wxOK | wxICON_INFORMATION, this);
|
wxMessageBox(msg, "About Minimal", wxOK | wxICON_INFORMATION, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Foo
|
||||||
|
{
|
||||||
|
Foo(int n_) { n = n_; }
|
||||||
|
|
||||||
|
int n;
|
||||||
|
};
|
||||||
|
|
||||||
|
WX_DECLARE_LIST(Foo, FooList);
|
||||||
|
|
||||||
|
#include <wx/listimpl.cpp>
|
||||||
|
|
||||||
|
WX_DEFINE_LIST(FooList);
|
||||||
|
|
||||||
|
int FooSort(const Foo **item1, const Foo **item2)
|
||||||
|
{
|
||||||
|
return (*item2)->n - (*item1)->n;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShowList(const FooList& list)
|
||||||
|
{
|
||||||
|
wxString msg, str;
|
||||||
|
msg = "The list elements: (";
|
||||||
|
for ( FooList::Node *node = list.GetFirst(); node; node = node->GetNext() )
|
||||||
|
{
|
||||||
|
if ( !!str )
|
||||||
|
msg += ", ";
|
||||||
|
str.Printf("%d", node->GetData()->n);
|
||||||
|
msg += str;
|
||||||
|
}
|
||||||
|
|
||||||
|
msg += ')';
|
||||||
|
|
||||||
|
wxMessageBox(msg, "List contents", wxOK | wxICON_INFORMATION);
|
||||||
|
}
|
||||||
|
|
||||||
void MyFrame::OnTest(wxCommandEvent& event)
|
void MyFrame::OnTest(wxCommandEvent& event)
|
||||||
{
|
{
|
||||||
|
FooList list;
|
||||||
|
list.Append(new Foo(12));
|
||||||
|
list.Append(new Foo(3));
|
||||||
|
list.Append(new Foo(1));
|
||||||
|
list.Append(new Foo(7));
|
||||||
|
list.Append(new Foo(4));
|
||||||
|
ShowList(list);
|
||||||
|
list.Sort(FooSort);
|
||||||
|
ShowList(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyFrame::OnPaint(wxPaintEvent& event)
|
void MyFrame::OnPaint(wxPaintEvent& event)
|
||||||
|
@@ -1,8 +1,6 @@
|
|||||||
|
|
||||||
|
|
||||||
|
# This file was automatically generated by tmake at 01:04, 1999/07/17
|
||||||
|
|
||||||
# This file was automatically generated by tmake at 21:00, 1999/07/14
|
|
||||||
# DO NOT CHANGE THIS FILE, YOUR CHANGES WILL BE LOST! CHANGE BCC.T!
|
# DO NOT CHANGE THIS FILE, YOUR CHANGES WILL BE LOST! CHANGE BCC.T!
|
||||||
|
|
||||||
#
|
#
|
||||||
@@ -100,7 +98,6 @@ GENERICOBJS= $(MSWDIR)\busyinfo.obj \
|
|||||||
|
|
||||||
COMMONOBJS = \
|
COMMONOBJS = \
|
||||||
$(MSWDIR)\y_tab.obj \
|
$(MSWDIR)\y_tab.obj \
|
||||||
$(MSWDIR)\extended.obj \
|
|
||||||
$(MSWDIR)\cmndata.obj \
|
$(MSWDIR)\cmndata.obj \
|
||||||
$(MSWDIR)\config.obj \
|
$(MSWDIR)\config.obj \
|
||||||
$(MSWDIR)\date.obj \
|
$(MSWDIR)\date.obj \
|
||||||
@@ -114,6 +111,8 @@ COMMONOBJS = \
|
|||||||
$(MSWDIR)\dynarray.obj \
|
$(MSWDIR)\dynarray.obj \
|
||||||
$(MSWDIR)\dynlib.obj \
|
$(MSWDIR)\dynlib.obj \
|
||||||
$(MSWDIR)\event.obj \
|
$(MSWDIR)\event.obj \
|
||||||
|
$(MSWDIR)\extended.obj \
|
||||||
|
$(MSWDIR)\ffile.obj \
|
||||||
$(MSWDIR)\file.obj \
|
$(MSWDIR)\file.obj \
|
||||||
$(MSWDIR)\fileconf.obj \
|
$(MSWDIR)\fileconf.obj \
|
||||||
$(MSWDIR)\filefn.obj \
|
$(MSWDIR)\filefn.obj \
|
||||||
@@ -146,6 +145,7 @@ COMMONOBJS = \
|
|||||||
$(MSWDIR)\string.obj \
|
$(MSWDIR)\string.obj \
|
||||||
$(MSWDIR)\tbarbase.obj \
|
$(MSWDIR)\tbarbase.obj \
|
||||||
$(MSWDIR)\tbarsmpl.obj \
|
$(MSWDIR)\tbarsmpl.obj \
|
||||||
|
$(MSWDIR)\textcmn.obj \
|
||||||
$(MSWDIR)\textfile.obj \
|
$(MSWDIR)\textfile.obj \
|
||||||
$(MSWDIR)\time.obj \
|
$(MSWDIR)\time.obj \
|
||||||
$(MSWDIR)\timercmn.obj \
|
$(MSWDIR)\timercmn.obj \
|
||||||
@@ -212,7 +212,6 @@ MSWOBJS = $(MSWDIR)\accel.obj \
|
|||||||
$(MSWDIR)\minifram.obj \
|
$(MSWDIR)\minifram.obj \
|
||||||
$(MSWDIR)\msgdlg.obj \
|
$(MSWDIR)\msgdlg.obj \
|
||||||
$(MSWDIR)\nativdlg.obj \
|
$(MSWDIR)\nativdlg.obj \
|
||||||
$(MSWDIR)\notebook.obj \
|
|
||||||
$(MSWDIR)\ownerdrw.obj \
|
$(MSWDIR)\ownerdrw.obj \
|
||||||
$(MSWDIR)\palette.obj \
|
$(MSWDIR)\palette.obj \
|
||||||
$(MSWDIR)\pen.obj \
|
$(MSWDIR)\pen.obj \
|
||||||
@@ -364,8 +363,6 @@ $(MSWDIR)\msgdlg.obj: $(MSWDIR)\msgdlg.$(SRCSUFF)
|
|||||||
|
|
||||||
$(MSWDIR)\nativdlg.obj: $(MSWDIR)\nativdlg.$(SRCSUFF)
|
$(MSWDIR)\nativdlg.obj: $(MSWDIR)\nativdlg.$(SRCSUFF)
|
||||||
|
|
||||||
$(MSWDIR)\notebook.obj: $(MSWDIR)\notebook.$(SRCSUFF)
|
|
||||||
|
|
||||||
$(MSWDIR)\ownerdrw.obj: $(MSWDIR)\ownerdrw.$(SRCSUFF)
|
$(MSWDIR)\ownerdrw.obj: $(MSWDIR)\ownerdrw.$(SRCSUFF)
|
||||||
|
|
||||||
$(MSWDIR)\palette.obj: $(MSWDIR)\palette.$(SRCSUFF)
|
$(MSWDIR)\palette.obj: $(MSWDIR)\palette.$(SRCSUFF)
|
||||||
@@ -451,6 +448,10 @@ $(MSWDIR)\dynlib.obj: $(COMMDIR)\dynlib.$(SRCSUFF)
|
|||||||
|
|
||||||
$(MSWDIR)\event.obj: $(COMMDIR)\event.$(SRCSUFF)
|
$(MSWDIR)\event.obj: $(COMMDIR)\event.$(SRCSUFF)
|
||||||
|
|
||||||
|
$(MSWDIR)\extended.obj: $(COMMDIR)\extended.c
|
||||||
|
|
||||||
|
$(MSWDIR)\ffile.obj: $(COMMDIR)\ffile.$(SRCSUFF)
|
||||||
|
|
||||||
$(MSWDIR)\file.obj: $(COMMDIR)\file.$(SRCSUFF)
|
$(MSWDIR)\file.obj: $(COMMDIR)\file.$(SRCSUFF)
|
||||||
|
|
||||||
$(MSWDIR)\fileconf.obj: $(COMMDIR)\fileconf.$(SRCSUFF)
|
$(MSWDIR)\fileconf.obj: $(COMMDIR)\fileconf.$(SRCSUFF)
|
||||||
@@ -515,6 +516,8 @@ $(MSWDIR)\tbarbase.obj: $(COMMDIR)\tbarbase.$(SRCSUFF)
|
|||||||
|
|
||||||
$(MSWDIR)\tbarsmpl.obj: $(COMMDIR)\tbarsmpl.$(SRCSUFF)
|
$(MSWDIR)\tbarsmpl.obj: $(COMMDIR)\tbarsmpl.$(SRCSUFF)
|
||||||
|
|
||||||
|
$(MSWDIR)\textcmn.obj: $(COMMDIR)\textcmn.$(SRCSUFF)
|
||||||
|
|
||||||
$(MSWDIR)\textfile.obj: $(COMMDIR)\textfile.$(SRCSUFF)
|
$(MSWDIR)\textfile.obj: $(COMMDIR)\textfile.$(SRCSUFF)
|
||||||
|
|
||||||
$(MSWDIR)\time.obj: $(COMMDIR)\time.$(SRCSUFF)
|
$(MSWDIR)\time.obj: $(COMMDIR)\time.$(SRCSUFF)
|
||||||
@@ -525,7 +528,7 @@ $(MSWDIR)\tokenzr.obj: $(COMMDIR)\tokenzr.$(SRCSUFF)
|
|||||||
|
|
||||||
$(MSWDIR)\txtstrm.obj: $(COMMDIR)\txtstrm.$(SRCSUFF)
|
$(MSWDIR)\txtstrm.obj: $(COMMDIR)\txtstrm.$(SRCSUFF)
|
||||||
|
|
||||||
$(MSWDIR)\unzip.obj: $(COMMDIR)\unzip.$(SRCSUFF)
|
$(MSWDIR)\unzip.obj: $(COMMDIR)\unzip.c
|
||||||
|
|
||||||
$(MSWDIR)\utilscmn.obj: $(COMMDIR)\utilscmn.$(SRCSUFF)
|
$(MSWDIR)\utilscmn.obj: $(COMMDIR)\utilscmn.$(SRCSUFF)
|
||||||
|
|
||||||
|
@@ -729,25 +729,35 @@ void wxMDIChildFrame::InternalSetMenuBar()
|
|||||||
// MDI operations
|
// MDI operations
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
void wxMDIChildFrame::Maximize()
|
void wxMDIChildFrame::Maximize(bool maximize)
|
||||||
{
|
{
|
||||||
wxMDIParentFrame *parent = (wxMDIParentFrame *)GetParent();
|
wxMDIParentFrame *parent = (wxMDIParentFrame *)GetParent();
|
||||||
if ( parent && parent->GetClientWindow() )
|
if ( parent && parent->GetClientWindow() )
|
||||||
::SendMessage(GetWinHwnd(parent->GetClientWindow()), WM_MDIMAXIMIZE, (WPARAM) GetHwnd(), 0);
|
{
|
||||||
|
::SendMessage(GetWinHwnd(parent->GetClientWindow()),
|
||||||
|
maximize ? WM_MDIMAXIMIZE : WM_MDIRESTORE,
|
||||||
|
(WPARAM)GetHwnd(), 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxMDIChildFrame::Restore()
|
void wxMDIChildFrame::Restore()
|
||||||
{
|
{
|
||||||
wxMDIParentFrame *parent = (wxMDIParentFrame *)GetParent();
|
wxMDIParentFrame *parent = (wxMDIParentFrame *)GetParent();
|
||||||
if ( parent && parent->GetClientWindow() )
|
if ( parent && parent->GetClientWindow() )
|
||||||
::SendMessage(GetWinHwnd(parent->GetClientWindow()), WM_MDIRESTORE, (WPARAM) GetHwnd(), 0);
|
{
|
||||||
|
::SendMessage(GetWinHwnd(parent->GetClientWindow()), WM_MDIRESTORE,
|
||||||
|
(WPARAM) GetHwnd(), 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxMDIChildFrame::Activate()
|
void wxMDIChildFrame::Activate()
|
||||||
{
|
{
|
||||||
wxMDIParentFrame *parent = (wxMDIParentFrame *)GetParent();
|
wxMDIParentFrame *parent = (wxMDIParentFrame *)GetParent();
|
||||||
if ( parent && parent->GetClientWindow() )
|
if ( parent && parent->GetClientWindow() )
|
||||||
::SendMessage(GetWinHwnd(parent->GetClientWindow()), WM_MDIACTIVATE, (WPARAM) GetHwnd(), 0);
|
{
|
||||||
|
::SendMessage(GetWinHwnd(parent->GetClientWindow()), WM_MDIACTIVATE,
|
||||||
|
(WPARAM) GetHwnd(), 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
@@ -74,7 +74,7 @@ ima_png_error(png_struct *png_ptr, char *message)
|
|||||||
// static wxGifReaderIter* iter;
|
// static wxGifReaderIter* iter;
|
||||||
wxPalette *wxCopyPalette(const wxPalette *cmap);
|
wxPalette *wxCopyPalette(const wxPalette *cmap);
|
||||||
|
|
||||||
wxPNGReader::wxPNGReader(void)
|
wxPNGReader::wxPNGReader()
|
||||||
{
|
{
|
||||||
filetype = 0;
|
filetype = 0;
|
||||||
RawImage = NULL; // Image data
|
RawImage = NULL; // Image data
|
||||||
@@ -265,7 +265,7 @@ void wxPNGReader::NullData()
|
|||||||
Palette = NULL;
|
Palette = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxBitmap* wxPNGReader::GetBitmap(void)
|
wxBitmap* wxPNGReader::GetBitmap()
|
||||||
{
|
{
|
||||||
wxBitmap *bitmap = new wxBitmap;
|
wxBitmap *bitmap = new wxBitmap;
|
||||||
if ( InstantiateBitmap(bitmap) )
|
if ( InstantiateBitmap(bitmap) )
|
||||||
@@ -354,7 +354,7 @@ wxPalette *wxCopyPalette(const wxPalette *cmap)
|
|||||||
return newCmap;
|
return newCmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxMask *wxPNGReader::CreateMask(void)
|
wxMask *wxPNGReader::CreateMask()
|
||||||
{
|
{
|
||||||
HBITMAP hBitmap = ::CreateBitmap(GetWidth(), GetHeight(), 1, 1, NULL);
|
HBITMAP hBitmap = ::CreateBitmap(GetWidth(), GetHeight(), 1, 1, NULL);
|
||||||
|
|
||||||
@@ -393,7 +393,6 @@ bool wxPNGReader::ReadFile(wxChar * ImageFileName)
|
|||||||
FILE *fp;
|
FILE *fp;
|
||||||
png_struct *png_ptr;
|
png_struct *png_ptr;
|
||||||
png_info *info_ptr;
|
png_info *info_ptr;
|
||||||
wxPNGReaderIter iter(this);
|
|
||||||
|
|
||||||
/* open the file */
|
/* open the file */
|
||||||
fp = fopen(wxConvFile.cWX2MB(filename), "rb");
|
fp = fopen(wxConvFile.cWX2MB(filename), "rb");
|
||||||
@@ -484,24 +483,31 @@ bool wxPNGReader::ReadFile(wxChar * ImageFileName)
|
|||||||
number_passes = 1;
|
number_passes = 1;
|
||||||
// printf("NP = %d ", number_passes);
|
// printf("NP = %d ", number_passes);
|
||||||
|
|
||||||
for (int pass=0; pass< number_passes; pass++) {
|
// don't use the object to prevent warnings from VC++ about "unportable
|
||||||
iter.upset();
|
// interaction between setjmp and C++ object destruction" (this is a correct
|
||||||
|
// warning, of course!)
|
||||||
|
wxPNGReaderIter *iter = new wxPNGReaderIter(this);
|
||||||
|
for (int pass=0; pass< number_passes; pass++)
|
||||||
|
{
|
||||||
|
iter->upset();
|
||||||
int y=0;
|
int y=0;
|
||||||
do {
|
do {
|
||||||
//(unsigned char *)iter.GetRow();
|
//(unsigned char *)iter.GetRow();
|
||||||
if (info_ptr->interlace_type) {
|
if (info_ptr->interlace_type) {
|
||||||
if (pass>0)
|
if (pass>0)
|
||||||
iter.GetRow(row_pointers, row_stride);
|
iter->GetRow(row_pointers, row_stride);
|
||||||
png_read_row(png_ptr, row_pointers, NULL);
|
png_read_row(png_ptr, row_pointers, NULL);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
png_read_row(png_ptr, row_pointers, NULL);
|
png_read_row(png_ptr, row_pointers, NULL);
|
||||||
|
|
||||||
iter.SetRow(row_pointers, row_stride);
|
iter->SetRow(row_pointers, row_stride);
|
||||||
y++;
|
y++;
|
||||||
} while(iter.PrevRow());
|
} while(iter->PrevRow());
|
||||||
// printf("Y=%d ",y);
|
// printf("Y=%d ",y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
delete iter;
|
||||||
delete[] row_pointers;
|
delete[] row_pointers;
|
||||||
|
|
||||||
/* read the rest of the file, getting any additional chunks
|
/* read the rest of the file, getting any additional chunks
|
||||||
|
Reference in New Issue
Block a user