diff --git a/include/wx/wxcrt.h b/include/wx/wxcrt.h index 2cbd853ecf..1a3e5e0dbf 100644 --- a/include/wx/wxcrt.h +++ b/include/wx/wxcrt.h @@ -257,7 +257,7 @@ inline size_t wxStrlcpy(char *dest, const char *src, size_t n) { if ( n-- > len ) n = len; - wxCRT_StrncpyA(dest, src, n); + wxTmemcpy(dest, src, n); dest[n] = '\0'; } @@ -270,7 +270,7 @@ inline size_t wxStrlcpy(wchar_t *dest, const wchar_t *src, size_t n) { if ( n-- > len ) n = len; - wxCRT_StrncpyW(dest, src, n); + wxTmemcpy(dest, src, n); dest[n] = L'\0'; } diff --git a/src/common/imagpng.cpp b/src/common/imagpng.cpp index 11b63b58fa..0b7c485321 100644 --- a/src/common/imagpng.cpp +++ b/src/common/imagpng.cpp @@ -68,6 +68,8 @@ wxIMPLEMENT_DYNAMIC_CLASS(wxPNGHandler,wxImageHandler); #endif #endif +namespace +{ // VS: wxPNGInfoStruct declared below is a hack that needs some explanation. // First, let me describe what's the problem: libpng uses jmp_buf in @@ -93,10 +95,72 @@ struct wxPNGInfoStruct wxInputStream *in; wxOutputStream *out; } stream; + }; #define WX_PNG_INFO(png_ptr) ((wxPNGInfoStruct*)png_get_io_ptr(png_ptr)) +// This is another helper struct which is used to pass parameters to +// DoLoadPNGFile(). It allows us to use the usual RAII for freeing memory, +// which wouldn't be possible inside DoLoadPNGFile() because it uses +// setjmp/longjmp() functions for error handling, which are incompatible with +// C++ destructors. +struct wxPNGImageData +{ + wxPNGImageData() + { + lines = NULL; + numLines = 0; + info_ptr = (png_infop) NULL; + png_ptr = (png_structp) NULL; + ok = false; + } + + bool Alloc(png_uint_32 width, png_uint_32 height) + { + lines = (unsigned char **)malloc(height * sizeof(unsigned char *)); + if ( !lines ) + return false; + + for ( png_uint_32 n = 0; n < height; n++ ) + { + lines[n] = (unsigned char *)malloc( (size_t)(width * 4)); + if ( lines[n] ) + ++numLines; + else + return false; + } + + return true; + } + + ~wxPNGImageData() + { + for ( unsigned int n = 0; n < numLines; n++ ) + free( lines[n] ); + + free( lines ); + + if ( png_ptr ) + { + if ( info_ptr ) + png_destroy_read_struct( &png_ptr, &info_ptr, (png_infopp) NULL ); + else + png_destroy_read_struct( &png_ptr, (png_infopp) NULL, (png_infopp) NULL ); + } + } + + void DoLoadPNGFile(wxImage* image, wxPNGInfoStruct& wxinfo); + + unsigned char** lines; + png_uint_32 numLines; + png_infop info_ptr; + png_structp png_ptr; + bool ok; +}; + +} // anonymous namespace + // ---------------------------------------------------------------------------- // helper functions // ---------------------------------------------------------------------------- @@ -247,28 +311,20 @@ void CopyDataFromPNG(wxImage *image, #pragma warning(disable:4611) #endif /* VC++ */ -bool -wxPNGHandler::LoadFile(wxImage *image, - wxInputStream& stream, - bool verbose, - int WXUNUSED(index)) +// This function uses wxPNGImageData to store some of its "local" variables in +// order to avoid clobbering these variables by longjmp(): having them inside +// the stack frame of the caller prevents this from happening. It also +// "returns" its result via wxPNGImageData: use its "ok" field to check +// whether loading succeeded or failed. +void +wxPNGImageData::DoLoadPNGFile(wxImage* image, wxPNGInfoStruct& wxinfo) { - // VZ: as this function uses setjmp() the only fool-proof error handling - // method is to use goto (setjmp is not really C++ dtors friendly...) - - unsigned char **lines = NULL; - png_infop info_ptr = (png_infop) NULL; - wxPNGInfoStruct wxinfo; - - png_uint_32 i, width, height = 0; + png_uint_32 width, height = 0; int bit_depth, color_type, interlace_type; - wxinfo.verbose = verbose; - wxinfo.stream.in = &stream; - image->Destroy(); - png_structp png_ptr = png_create_read_struct + png_ptr = png_create_read_struct ( PNG_LIBPNG_VER_STRING, NULL, @@ -276,7 +332,7 @@ wxPNGHandler::LoadFile(wxImage *image, wx_PNG_warning ); if (!png_ptr) - goto error; + return; // NB: please see the comment near wxPNGInfoStruct declaration for // explanation why this line is mandatory @@ -284,10 +340,10 @@ wxPNGHandler::LoadFile(wxImage *image, info_ptr = png_create_info_struct( png_ptr ); if (!info_ptr) - goto error; + return; if (setjmp(wxinfo.jmpbuf)) - goto error; + return; png_read_info( png_ptr, info_ptr ); png_get_IHDR( png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL ); @@ -308,19 +364,10 @@ wxPNGHandler::LoadFile(wxImage *image, image->Create((int)width, (int)height, (bool) false /* no need to init pixels */); if (!image->IsOk()) - goto error; + return; - // initialize all line pointers to NULL to ensure that they can be safely - // free()d if an error occurs before all of them could be allocated - lines = (unsigned char **)calloc(height, sizeof(unsigned char *)); - if ( !lines ) - goto error; - - for (i = 0; i < height; i++) - { - if ((lines[i] = (unsigned char *)malloc( (size_t)(width * 4))) == NULL) - goto error; - } + if ( !Alloc(width, height) ) + return; png_read_image( png_ptr, lines ); png_read_end( png_ptr, info_ptr ); @@ -392,47 +439,42 @@ wxPNGHandler::LoadFile(wxImage *image, } - png_destroy_read_struct( &png_ptr, &info_ptr, (png_infopp) NULL ); - // loaded successfully, now init wxImage with this data CopyDataFromPNG(image, lines, width, height, color_type); - for ( i = 0; i < height; i++ ) - free( lines[i] ); - free( lines ); + // This will indicate to the caller that loading succeeded. + ok = true; +} + +bool +wxPNGHandler::LoadFile(wxImage *image, + wxInputStream& stream, + bool verbose, + int WXUNUSED(index)) +{ + wxPNGInfoStruct wxinfo; + wxinfo.verbose = verbose; + wxinfo.stream.in = &stream; + + wxPNGImageData data; + data.DoLoadPNGFile(image, wxinfo); + + if ( !data.ok ) + { + if (verbose) + { + wxLogError(_("Couldn't load a PNG image - file is corrupted or not enough memory.")); + } + + if ( image->IsOk() ) + { + image->Destroy(); + } + + return false; + } return true; - -error: - if (verbose) - { - wxLogError(_("Couldn't load a PNG image - file is corrupted or not enough memory.")); - } - - if ( image->IsOk() ) - { - image->Destroy(); - } - - if ( lines ) - { - for ( unsigned int n = 0; n < height; n++ ) - free( lines[n] ); - - free( lines ); - } - - if ( png_ptr ) - { - if ( info_ptr ) - { - png_destroy_read_struct( &png_ptr, &info_ptr, (png_infopp) NULL ); - free(info_ptr); - } - else - png_destroy_read_struct( &png_ptr, (png_infopp) NULL, (png_infopp) NULL ); - } - return false; } // ---------------------------------------------------------------------------- diff --git a/src/generic/statusbr.cpp b/src/generic/statusbr.cpp index f364677c7b..c0581dd679 100644 --- a/src/generic/statusbr.cpp +++ b/src/generic/statusbr.cpp @@ -231,12 +231,12 @@ void wxStatusBarGeneric::DrawFieldText(wxDC& dc, const wxRect& rect, int i, int // eventually ellipsize the text so that it fits the field width - wxEllipsizeMode ellmode = (wxEllipsizeMode)-1; + wxEllipsizeMode ellmode = wxELLIPSIZE_NONE; if (HasFlag(wxSTB_ELLIPSIZE_START)) ellmode = wxELLIPSIZE_START; else if (HasFlag(wxSTB_ELLIPSIZE_MIDDLE)) ellmode = wxELLIPSIZE_MIDDLE; else if (HasFlag(wxSTB_ELLIPSIZE_END)) ellmode = wxELLIPSIZE_END; - if (ellmode == (wxEllipsizeMode)-1) + if (ellmode == wxELLIPSIZE_NONE) { // if we have the wxSTB_SHOW_TIPS we must set the ellipsized flag even if // we don't ellipsize the text but just truncate it @@ -267,7 +267,7 @@ void wxStatusBarGeneric::DrawFieldText(wxDC& dc, const wxRect& rect, int i, int // draw the text dc.DrawText(text, xpos, ypos); - if (ellmode == (wxEllipsizeMode)-1) + if (ellmode == wxELLIPSIZE_NONE) dc.DestroyClippingRegion(); } diff --git a/src/msw/statusbar.cpp b/src/msw/statusbar.cpp index 52ed30fa79..ad9b4eff96 100644 --- a/src/msw/statusbar.cpp +++ b/src/msw/statusbar.cpp @@ -287,12 +287,12 @@ void wxStatusBar::DoUpdateStatusText(int nField) wxString text = GetStatusText(nField); // do we need to ellipsize this string? - wxEllipsizeMode ellmode = (wxEllipsizeMode)-1; + wxEllipsizeMode ellmode = wxELLIPSIZE_NONE; if (HasFlag(wxSTB_ELLIPSIZE_START)) ellmode = wxELLIPSIZE_START; else if (HasFlag(wxSTB_ELLIPSIZE_MIDDLE)) ellmode = wxELLIPSIZE_MIDDLE; else if (HasFlag(wxSTB_ELLIPSIZE_END)) ellmode = wxELLIPSIZE_END; - if (ellmode == (wxEllipsizeMode)-1) + if (ellmode == wxELLIPSIZE_NONE) { // if we have the wxSTB_SHOW_TIPS we must set the ellipsized flag even if // we don't ellipsize the text but just truncate it diff --git a/src/propgrid/propgridpagestate.cpp b/src/propgrid/propgridpagestate.cpp index ad9fdc5858..870354a27f 100644 --- a/src/propgrid/propgridpagestate.cpp +++ b/src/propgrid/propgridpagestate.cpp @@ -1371,8 +1371,7 @@ void wxPropertyGridPageState::DoRemoveFromSelection( wxPGProperty* prop ) { // If first item (i.e. one with the active editor) was // deselected, then we need to take some extra measures. - wxArrayPGProperty sel = m_selection; - sel.erase( sel.begin() + i ); + wxArrayPGProperty sel(m_selection.begin() + 1, m_selection.end()); wxPGProperty* newFirst = sel.empty()? NULL: sel[0];