diff --git a/Builds/Linux/Makefile b/Builds/Linux/Makefile index ee676c8539..d1f1a93a2e 100644 --- a/Builds/Linux/Makefile +++ b/Builds/Linux/Makefile @@ -106,6 +106,7 @@ OBJECTS := \ $(OBJDIR)/juce_Logger_4f4f7f72.o \ $(OBJDIR)/juce_PerformanceCounter_6422080e.o \ $(OBJDIR)/juce_RelativeTime_bc5ef35b.o \ + $(OBJDIR)/juce_Result_d8f437f.o \ $(OBJDIR)/juce_SystemStats_c00d8758.o \ $(OBJDIR)/juce_Time_16acdd6f.o \ $(OBJDIR)/juce_Uuid_f277575d.o \ @@ -719,6 +720,11 @@ $(OBJDIR)/juce_RelativeTime_bc5ef35b.o: ../../src/core/juce_RelativeTime.cpp @echo "Compiling juce_RelativeTime.cpp" @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" +$(OBJDIR)/juce_Result_d8f437f.o: ../../src/core/juce_Result.cpp + -@mkdir -p $(OBJDIR) + @echo "Compiling juce_Result.cpp" + @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" + $(OBJDIR)/juce_SystemStats_c00d8758.o: ../../src/core/juce_SystemStats.cpp -@mkdir -p $(OBJDIR) @echo "Compiling juce_SystemStats.cpp" diff --git a/Builds/MacOSX/Juce.xcodeproj/project.pbxproj b/Builds/MacOSX/Juce.xcodeproj/project.pbxproj index 6e69297824..a49a0da196 100644 --- a/Builds/MacOSX/Juce.xcodeproj/project.pbxproj +++ b/Builds/MacOSX/Juce.xcodeproj/project.pbxproj @@ -75,6 +75,7 @@ 6A53DA58B55E2DE7241BF2C8 = { isa = PBXBuildFile; fileRef = 4555F03DBD059EEDECEF9F85; }; 0FF71870483AC46D5B7AC5B0 = { isa = PBXBuildFile; fileRef = DF6CAC67C0F2D379BDA03062; }; FA01B3EABA192AE041D4FE4D = { isa = PBXBuildFile; fileRef = CFAECB6551F48A1695DEC243; }; + 43047D78351C2D7047F4F81E = { isa = PBXBuildFile; fileRef = 0AD73B8EA0D60D9927B36624; }; 5BF44F954E56B7C2DD15EAEA = { isa = PBXBuildFile; fileRef = 18B170E96511BBA1019C66F8; }; B14EB5F3829CA26DA906D5C0 = { isa = PBXBuildFile; fileRef = 8D2DE1F3CB15D003C90042E7; }; D75943C2812EA68CA74D9FDA = { isa = PBXBuildFile; fileRef = CEF91E0C9CBB3EBFF9500FDA; }; @@ -539,6 +540,8 @@ 8D499CED6DCF525ACD6E39B2 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_PlatformUtilities.h; path = ../../src/core/juce_PlatformUtilities.h; sourceTree = SOURCE_ROOT; }; CFAECB6551F48A1695DEC243 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_RelativeTime.cpp; path = ../../src/core/juce_RelativeTime.cpp; sourceTree = SOURCE_ROOT; }; B4137E4612C1D161894D0D27 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_RelativeTime.h; path = ../../src/core/juce_RelativeTime.h; sourceTree = SOURCE_ROOT; }; + 0AD73B8EA0D60D9927B36624 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_Result.cpp; path = ../../src/core/juce_Result.cpp; sourceTree = SOURCE_ROOT; }; + F51969AF328D2C7D52D7436D = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_Result.h; path = ../../src/core/juce_Result.h; sourceTree = SOURCE_ROOT; }; C25D6136DF9CE441D6EB4C42 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_Singleton.h; path = ../../src/core/juce_Singleton.h; sourceTree = SOURCE_ROOT; }; CA66415F6EAA172B83755954 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_StandardHeader.h; path = ../../src/core/juce_StandardHeader.h; sourceTree = SOURCE_ROOT; }; 18B170E96511BBA1019C66F8 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_SystemStats.cpp; path = ../../src/core/juce_SystemStats.cpp; sourceTree = SOURCE_ROOT; }; @@ -1303,6 +1306,8 @@ 8D499CED6DCF525ACD6E39B2, CFAECB6551F48A1695DEC243, B4137E4612C1D161894D0D27, + 0AD73B8EA0D60D9927B36624, + F51969AF328D2C7D52D7436D, C25D6136DF9CE441D6EB4C42, CA66415F6EAA172B83755954, 18B170E96511BBA1019C66F8, @@ -2100,6 +2105,7 @@ 6A53DA58B55E2DE7241BF2C8, 0FF71870483AC46D5B7AC5B0, FA01B3EABA192AE041D4FE4D, + 43047D78351C2D7047F4F81E, 5BF44F954E56B7C2DD15EAEA, B14EB5F3829CA26DA906D5C0, D75943C2812EA68CA74D9FDA, diff --git a/Builds/VisualStudio2005/Juce.vcproj b/Builds/VisualStudio2005/Juce.vcproj index 5aac2608d3..fc8e2d75f0 100644 --- a/Builds/VisualStudio2005/Juce.vcproj +++ b/Builds/VisualStudio2005/Juce.vcproj @@ -373,6 +373,8 @@ + + diff --git a/Builds/VisualStudio2008/Juce.vcproj b/Builds/VisualStudio2008/Juce.vcproj index a9aca45a18..2ad8bd0713 100644 --- a/Builds/VisualStudio2008/Juce.vcproj +++ b/Builds/VisualStudio2008/Juce.vcproj @@ -373,6 +373,8 @@ + + diff --git a/Builds/VisualStudio2008_DLL/Juce.vcproj b/Builds/VisualStudio2008_DLL/Juce.vcproj index 27d832d9ca..4c360ccb9f 100644 --- a/Builds/VisualStudio2008_DLL/Juce.vcproj +++ b/Builds/VisualStudio2008_DLL/Juce.vcproj @@ -375,6 +375,8 @@ + + diff --git a/Builds/VisualStudio2010/Juce.vcxproj b/Builds/VisualStudio2010/Juce.vcxproj index 59c7090bd6..a8eb80285e 100644 --- a/Builds/VisualStudio2010/Juce.vcxproj +++ b/Builds/VisualStudio2010/Juce.vcxproj @@ -189,6 +189,7 @@ + @@ -549,6 +550,7 @@ + diff --git a/Builds/VisualStudio2010/Juce.vcxproj.filters b/Builds/VisualStudio2010/Juce.vcxproj.filters index 4f15d71616..479c8ce8f5 100644 --- a/Builds/VisualStudio2010/Juce.vcxproj.filters +++ b/Builds/VisualStudio2010/Juce.vcxproj.filters @@ -424,6 +424,9 @@ Juce\Source\core + + Juce\Source\core + Juce\Source\core @@ -1578,6 +1581,9 @@ Juce\Source\core + + Juce\Source\core + Juce\Source\core diff --git a/Builds/iOS/Juce.xcodeproj/project.pbxproj b/Builds/iOS/Juce.xcodeproj/project.pbxproj index 406ad43600..4959420fff 100644 --- a/Builds/iOS/Juce.xcodeproj/project.pbxproj +++ b/Builds/iOS/Juce.xcodeproj/project.pbxproj @@ -75,6 +75,7 @@ 6A53DA58B55E2DE7241BF2C8 = { isa = PBXBuildFile; fileRef = 4555F03DBD059EEDECEF9F85; }; 0FF71870483AC46D5B7AC5B0 = { isa = PBXBuildFile; fileRef = DF6CAC67C0F2D379BDA03062; }; FA01B3EABA192AE041D4FE4D = { isa = PBXBuildFile; fileRef = CFAECB6551F48A1695DEC243; }; + 43047D78351C2D7047F4F81E = { isa = PBXBuildFile; fileRef = 0AD73B8EA0D60D9927B36624; }; 5BF44F954E56B7C2DD15EAEA = { isa = PBXBuildFile; fileRef = 18B170E96511BBA1019C66F8; }; B14EB5F3829CA26DA906D5C0 = { isa = PBXBuildFile; fileRef = 8D2DE1F3CB15D003C90042E7; }; D75943C2812EA68CA74D9FDA = { isa = PBXBuildFile; fileRef = CEF91E0C9CBB3EBFF9500FDA; }; @@ -539,6 +540,8 @@ 8D499CED6DCF525ACD6E39B2 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_PlatformUtilities.h; path = ../../src/core/juce_PlatformUtilities.h; sourceTree = SOURCE_ROOT; }; CFAECB6551F48A1695DEC243 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_RelativeTime.cpp; path = ../../src/core/juce_RelativeTime.cpp; sourceTree = SOURCE_ROOT; }; B4137E4612C1D161894D0D27 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_RelativeTime.h; path = ../../src/core/juce_RelativeTime.h; sourceTree = SOURCE_ROOT; }; + 0AD73B8EA0D60D9927B36624 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_Result.cpp; path = ../../src/core/juce_Result.cpp; sourceTree = SOURCE_ROOT; }; + F51969AF328D2C7D52D7436D = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_Result.h; path = ../../src/core/juce_Result.h; sourceTree = SOURCE_ROOT; }; C25D6136DF9CE441D6EB4C42 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_Singleton.h; path = ../../src/core/juce_Singleton.h; sourceTree = SOURCE_ROOT; }; CA66415F6EAA172B83755954 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_StandardHeader.h; path = ../../src/core/juce_StandardHeader.h; sourceTree = SOURCE_ROOT; }; 18B170E96511BBA1019C66F8 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_SystemStats.cpp; path = ../../src/core/juce_SystemStats.cpp; sourceTree = SOURCE_ROOT; }; @@ -1303,6 +1306,8 @@ 8D499CED6DCF525ACD6E39B2, CFAECB6551F48A1695DEC243, B4137E4612C1D161894D0D27, + 0AD73B8EA0D60D9927B36624, + F51969AF328D2C7D52D7436D, C25D6136DF9CE441D6EB4C42, CA66415F6EAA172B83755954, 18B170E96511BBA1019C66F8, @@ -2104,6 +2109,7 @@ 6A53DA58B55E2DE7241BF2C8, 0FF71870483AC46D5B7AC5B0, FA01B3EABA192AE041D4FE4D, + 43047D78351C2D7047F4F81E, 5BF44F954E56B7C2DD15EAEA, B14EB5F3829CA26DA906D5C0, D75943C2812EA68CA74D9FDA, diff --git a/Juce.jucer b/Juce.jucer index ca0d02cbf9..b633b3a426 100644 --- a/Juce.jucer +++ b/Juce.jucer @@ -419,6 +419,8 @@ file="src/core/juce_RelativeTime.cpp"/> + + maxNumberOfItems) - files.remove (getNumFiles() - 1); + files.removeRange (maxNumberOfItems, getNumFiles()); } int RecentlyOpenedFilesList::getNumFiles() const @@ -19665,10 +19736,8 @@ void RecentlyOpenedFilesList::clear() void RecentlyOpenedFilesList::addFile (const File& file) { - const String path (file.getFullPathName()); - - files.removeString (path, true); - files.insert (0, path); + removeFile (file); + files.insert (0, file.getFullPathName()); setMaxNumberOfItems (maxNumberOfItems); } @@ -37110,29 +37179,40 @@ private: Entry* findEntry (const uint32 destNodeId, int& insertIndex) const noexcept { Entry* result = nullptr; - int firstElement = 0, lastElement = entries.size(); - while (firstElement < lastElement) + int start = 0; + int end = entries.size(); + + for (;;) { - Entry* const firstEntry = entries.getUnchecked (firstElement); - if (destNodeId == firstEntry->destNodeId) + if (start >= end) { - result = firstEntry; break; } - - const int halfway = (firstElement + lastElement) / 2; - - if (halfway <= firstElement) + else if (destNodeId == entries.getUnchecked (start)->destNodeId) + { + result = entries.getUnchecked (start); break; - - if (destNodeId >= entries.getUnchecked (halfway)->destNodeId) - firstElement = halfway; + } else - lastElement = halfway; + { + const int halfway = (start + end) / 2; + + if (halfway == start) + { + if (destNodeId >= entries.getUnchecked (halfway)->destNodeId) + ++start; + + break; + } + else if (destNodeId >= entries.getUnchecked (halfway)->destNodeId) + start = halfway; + else + end = halfway; + } } - insertIndex = firstElement; + insertIndex = start; return result; } @@ -49857,7 +49937,7 @@ const Image ListBox::createSnapshotOfSelectedRows (int& imageX, int& imageY) return snapshot; } -void ListBox::startDragAndDrop (const MouseEvent& e, const var& dragDescription) +void ListBox::startDragAndDrop (const MouseEvent& e, const var& dragDescription, bool allowDraggingToOtherWindows) { DragAndDropContainer* const dragContainer = DragAndDropContainer::findParentDragContainerFor (this); @@ -49869,7 +49949,7 @@ void ListBox::startDragAndDrop (const MouseEvent& e, const var& dragDescription) MouseEvent e2 (e.getEventRelativeTo (this)); const Point p (x - e2.x, y - e2.y); - dragContainer->startDragging (dragDescription, this, dragImage, true, &p); + dragContainer->startDragging (dragDescription, this, dragImage, allowDraggingToOtherWindows, &p); } else { @@ -243728,6 +243808,17 @@ namespace WindowsFileHelpers return File::nonexistent; } + + const Result getResultForLastError() + { + TCHAR messageBuffer [256] = { 0 }; + + FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + nullptr, GetLastError(), MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), + messageBuffer, numElementsInArray (messageBuffer) - 1, nullptr); + + return Result::fail (String (messageBuffer)); + } } const juce_wchar File::separator = '\\'; @@ -243823,9 +243914,10 @@ bool File::moveInternal (const File& dest) const return MoveFile (fullPath.toWideCharPointer(), dest.getFullPathName().toWideCharPointer()) != 0; } -void File::createDirectoryInternal (const String& fileName) const +const Result File::createDirectoryInternal (const String& fileName) const { - CreateDirectory (fileName.toWideCharPointer(), 0); + return CreateDirectory (fileName.toWideCharPointer(), 0) ? Result::ok() + : WindowsFileHelpers::getResultForLastError(); } int64 juce_fileSetPosition (void* handle, int64 pos) @@ -243845,6 +243937,8 @@ void FileInputStream::openHandle() if (h != INVALID_HANDLE_VALUE) fileHandle = (void*) h; + else + status = WindowsFileHelpers::getResultForLastError(); } void FileInputStream::closeHandle() @@ -243857,7 +243951,9 @@ size_t FileInputStream::readInternal (void* buffer, size_t numBytes) if (fileHandle != 0) { DWORD actualNum = 0; - ReadFile ((HANDLE) fileHandle, buffer, numBytes, &actualNum, 0); + if (! ReadFile ((HANDLE) fileHandle, buffer, numBytes, &actualNum, 0)) + status = WindowsFileHelpers::getResultForLastError(); + return (size_t) actualNum; } @@ -243879,8 +243975,11 @@ void FileOutputStream::openHandle() { fileHandle = (void*) h; currentPosition = li.QuadPart; + return; } } + + status = WindowsFileHelpers::getResultForLastError(); } void FileOutputStream::closeHandle() @@ -243890,10 +243989,12 @@ void FileOutputStream::closeHandle() int FileOutputStream::writeInternal (const void* buffer, int numBytes) { - if (fileHandle != 0) + if (fileHandle != nullptr) { DWORD actualNum = 0; - WriteFile ((HANDLE) fileHandle, buffer, numBytes, &actualNum, 0); + if (! WriteFile ((HANDLE) fileHandle, buffer, numBytes, &actualNum, 0)) + status = WindowsFileHelpers::getResultForLastError(); + return (int) actualNum; } @@ -243902,8 +244003,9 @@ int FileOutputStream::writeInternal (const void* buffer, int numBytes) void FileOutputStream::flushInternal() { - if (fileHandle != 0) - FlushFileBuffers ((HANDLE) fileHandle); + if (fileHandle != nullptr) + if (! FlushFileBuffers ((HANDLE) fileHandle)) + status = WindowsFileHelpers::getResultForLastError(); } int64 File::getSize() const @@ -259463,6 +259565,16 @@ namespace if (isReadOnly != nullptr) *isReadOnly = access (path.toUTF8(), W_OK) != 0; } + + const Result getResultForErrno() + { + return Result::fail (String (strerror (errno))); + } + + const Result getResultForReturnValue (int value) + { + return value == -1 ? getResultForErrno() : Result::ok(); + } } bool File::isDirectory() const @@ -259582,9 +259694,9 @@ bool File::moveInternal (const File& dest) const return false; } -void File::createDirectoryInternal (const String& fileName) const +const Result File::createDirectoryInternal (const String& fileName) const { - mkdir (fileName.toUTF8(), 0777); + return getResultForReturnValue (mkdir (fileName.toUTF8(), 0777)); } int64 juce_fileSetPosition (void* handle, int64 pos) @@ -259603,6 +259715,8 @@ void FileInputStream::openHandle() if (f != -1) fileHandle = (void*) f; + else + status = getResultForErrno(); } void FileInputStream::closeHandle() @@ -259616,10 +259730,20 @@ void FileInputStream::closeHandle() size_t FileInputStream::readInternal (void* const buffer, const size_t numBytes) { + ssize_t result = 0; + if (fileHandle != 0) - return jmax ((ssize_t) 0, ::read ((int) (pointer_sized_int) fileHandle, buffer, numBytes)); + { + result = ::read ((int) (pointer_sized_int) fileHandle, buffer, numBytes); - return 0; + if (result < 0) + { + status = getResultForErrno(); + result = 0; + } + } + + return (size_t) result; } void FileOutputStream::openHandle() @@ -259633,9 +259757,18 @@ void FileOutputStream::openHandle() currentPosition = lseek (f, 0, SEEK_END); if (currentPosition >= 0) + { fileHandle = (void*) f; + } else + { + status = getResultForErrno(); close (f); + } + } + else + { + status = getResultForErrno(); } } else @@ -259644,6 +259777,8 @@ void FileOutputStream::openHandle() if (f != -1) fileHandle = (void*) f; + else + status = getResultForErrno(); } } @@ -259658,16 +259793,24 @@ void FileOutputStream::closeHandle() int FileOutputStream::writeInternal (const void* const data, const int numBytes) { + ssize_t result = 0; + if (fileHandle != 0) - return (int) ::write ((int) (pointer_sized_int) fileHandle, data, numBytes); + { + result = ::write ((int) (pointer_sized_int) fileHandle, data, numBytes); - return 0; + if (result == -1) + status = getResultForErrno(); + } + + return (int) result; } void FileOutputStream::flushInternal() { if (fileHandle != 0) - fsync ((int) (pointer_sized_int) fileHandle); + if (fsync ((int) (pointer_sized_int) fileHandle) == -1) + status = getResultForErrno(); } const File juce_getExecutableFile() @@ -269382,6 +269525,16 @@ namespace if (isReadOnly != nullptr) *isReadOnly = access (path.toUTF8(), W_OK) != 0; } + + const Result getResultForErrno() + { + return Result::fail (String (strerror (errno))); + } + + const Result getResultForReturnValue (int value) + { + return value == -1 ? getResultForErrno() : Result::ok(); + } } bool File::isDirectory() const @@ -269501,9 +269654,9 @@ bool File::moveInternal (const File& dest) const return false; } -void File::createDirectoryInternal (const String& fileName) const +const Result File::createDirectoryInternal (const String& fileName) const { - mkdir (fileName.toUTF8(), 0777); + return getResultForReturnValue (mkdir (fileName.toUTF8(), 0777)); } int64 juce_fileSetPosition (void* handle, int64 pos) @@ -269522,6 +269675,8 @@ void FileInputStream::openHandle() if (f != -1) fileHandle = (void*) f; + else + status = getResultForErrno(); } void FileInputStream::closeHandle() @@ -269535,10 +269690,20 @@ void FileInputStream::closeHandle() size_t FileInputStream::readInternal (void* const buffer, const size_t numBytes) { + ssize_t result = 0; + if (fileHandle != 0) - return jmax ((ssize_t) 0, ::read ((int) (pointer_sized_int) fileHandle, buffer, numBytes)); + { + result = ::read ((int) (pointer_sized_int) fileHandle, buffer, numBytes); - return 0; + if (result < 0) + { + status = getResultForErrno(); + result = 0; + } + } + + return (size_t) result; } void FileOutputStream::openHandle() @@ -269552,9 +269717,18 @@ void FileOutputStream::openHandle() currentPosition = lseek (f, 0, SEEK_END); if (currentPosition >= 0) + { fileHandle = (void*) f; + } else + { + status = getResultForErrno(); close (f); + } + } + else + { + status = getResultForErrno(); } } else @@ -269563,6 +269737,8 @@ void FileOutputStream::openHandle() if (f != -1) fileHandle = (void*) f; + else + status = getResultForErrno(); } } @@ -269577,16 +269753,24 @@ void FileOutputStream::closeHandle() int FileOutputStream::writeInternal (const void* const data, const int numBytes) { + ssize_t result = 0; + if (fileHandle != 0) - return (int) ::write ((int) (pointer_sized_int) fileHandle, data, numBytes); + { + result = ::write ((int) (pointer_sized_int) fileHandle, data, numBytes); - return 0; + if (result == -1) + status = getResultForErrno(); + } + + return (int) result; } void FileOutputStream::flushInternal() { if (fileHandle != 0) - fsync ((int) (pointer_sized_int) fileHandle); + if (fsync ((int) (pointer_sized_int) fileHandle) == -1) + status = getResultForErrno(); } const File juce_getExecutableFile() @@ -285777,6 +285961,16 @@ namespace if (isReadOnly != nullptr) *isReadOnly = access (path.toUTF8(), W_OK) != 0; } + + const Result getResultForErrno() + { + return Result::fail (String (strerror (errno))); + } + + const Result getResultForReturnValue (int value) + { + return value == -1 ? getResultForErrno() : Result::ok(); + } } bool File::isDirectory() const @@ -285896,9 +286090,9 @@ bool File::moveInternal (const File& dest) const return false; } -void File::createDirectoryInternal (const String& fileName) const +const Result File::createDirectoryInternal (const String& fileName) const { - mkdir (fileName.toUTF8(), 0777); + return getResultForReturnValue (mkdir (fileName.toUTF8(), 0777)); } int64 juce_fileSetPosition (void* handle, int64 pos) @@ -285917,6 +286111,8 @@ void FileInputStream::openHandle() if (f != -1) fileHandle = (void*) f; + else + status = getResultForErrno(); } void FileInputStream::closeHandle() @@ -285930,10 +286126,20 @@ void FileInputStream::closeHandle() size_t FileInputStream::readInternal (void* const buffer, const size_t numBytes) { + ssize_t result = 0; + if (fileHandle != 0) - return jmax ((ssize_t) 0, ::read ((int) (pointer_sized_int) fileHandle, buffer, numBytes)); + { + result = ::read ((int) (pointer_sized_int) fileHandle, buffer, numBytes); - return 0; + if (result < 0) + { + status = getResultForErrno(); + result = 0; + } + } + + return (size_t) result; } void FileOutputStream::openHandle() @@ -285947,9 +286153,18 @@ void FileOutputStream::openHandle() currentPosition = lseek (f, 0, SEEK_END); if (currentPosition >= 0) + { fileHandle = (void*) f; + } else + { + status = getResultForErrno(); close (f); + } + } + else + { + status = getResultForErrno(); } } else @@ -285958,6 +286173,8 @@ void FileOutputStream::openHandle() if (f != -1) fileHandle = (void*) f; + else + status = getResultForErrno(); } } @@ -285972,16 +286189,24 @@ void FileOutputStream::closeHandle() int FileOutputStream::writeInternal (const void* const data, const int numBytes) { + ssize_t result = 0; + if (fileHandle != 0) - return (int) ::write ((int) (pointer_sized_int) fileHandle, data, numBytes); + { + result = ::write ((int) (pointer_sized_int) fileHandle, data, numBytes); - return 0; + if (result == -1) + status = getResultForErrno(); + } + + return (int) result; } void FileOutputStream::flushInternal() { if (fileHandle != 0) - fsync ((int) (pointer_sized_int) fileHandle); + if (fsync ((int) (pointer_sized_int) fileHandle) == -1) + status = getResultForErrno(); } const File juce_getExecutableFile() diff --git a/juce_amalgamated.h b/juce_amalgamated.h index 465b50f623..95826beb53 100644 --- a/juce_amalgamated.h +++ b/juce_amalgamated.h @@ -73,7 +73,7 @@ namespace JuceDummyNamespace {} */ #define JUCE_MAJOR_VERSION 1 #define JUCE_MINOR_VERSION 53 -#define JUCE_BUILDNUMBER 75 +#define JUCE_BUILDNUMBER 76 /** Current Juce version number. @@ -11998,6 +11998,85 @@ JUCE_API bool operator>= (const Time& time1, const Time& time2); #endif // __JUCE_TIME_JUCEHEADER__ /*** End of inlined file: juce_Time.h ***/ + +/*** Start of inlined file: juce_Result.h ***/ +#ifndef __JUCE_RESULT_JUCEHEADER__ +#define __JUCE_RESULT_JUCEHEADER__ + +/** + Represents the 'success' or 'failure' of an operation, and holds an associated + error message to describe the error when there's a failure. + + E.g. + @code + const Result myOperation() + { + if (doSomeKindOfFoobar()) + return Result::ok(); + else + return Result::fail ("foobar didn't work!"); + } + + const Result result (myOperation()); + + if (result.wasOk()) + { + ...it's all good... + } + else + { + warnUserAboutFailure ("The foobar operation failed! Error message was: " + + result.getErrorMessage()); + } + @endcode +*/ +class Result +{ +public: + + /** Creates and returns a 'successful' result. */ + static const Result ok() noexcept; + + /** Creates a 'failure' result. + If you pass a blank error message in here, a default "Unknown Error" message + will be used instead. + */ + static const Result fail (const String& errorMessage) noexcept; + + /** Returns true if this result indicates a success. */ + bool wasOk() const noexcept; + + /** Returns true if this result indicates a failure. + You can use getErrorMessage() to retrieve the error message associated + with the failure. + */ + bool failed() const noexcept; + + /** Returns true if this result indicates a success. + This is equivalent to calling wasOk(). + */ + operator bool() const noexcept; + + /** Returns the error message that was set when this result was created. + For a successful result, this will be an empty string; + */ + const String getErrorMessage() const noexcept; + + Result (const Result& other); + Result& operator= (const Result& other); + + bool operator== (const Result& other) const noexcept; + bool operator!= (const Result& other) const noexcept; + +private: + String errorMessage; + + explicit Result (const String& errorMessage) noexcept; +}; + +#endif // __JUCE_RESULT_JUCEHEADER__ +/*** End of inlined file: juce_Result.h ***/ + class FileInputStream; class FileOutputStream; @@ -12378,18 +12457,18 @@ public: @returns true if the file has been created (or if it already existed). @see createDirectory */ - bool create() const; + const Result create() const; /** Creates a new directory for this filename. This will try to create the file as a directory, and fill also create any parent directories it needs in order to complete the operation. - @returns true if the directory has been created successfully, (or if it - already existed beforehand). + @returns a result to indicate whether the directory was created successfully, or + an error message if it failed. @see create */ - bool createDirectory() const; + const Result createDirectory() const; /** Deletes a file. @@ -12869,7 +12948,7 @@ private: File (const String&, int); const String getPathUpToLastSlash() const; - void createDirectoryInternal (const String& fileName) const; + const Result createDirectoryInternal (const String& fileName) const; bool copyInternal (const File& dest) const; bool moveInternal (const File& dest) const; bool setFileTimesInternal (int64 modificationTime, int64 accessTime, int64 creationTime) const; @@ -17832,6 +17911,9 @@ private: #endif #ifndef __JUCE_RELATIVETIME_JUCEHEADER__ +#endif +#ifndef __JUCE_RESULT_JUCEHEADER__ + #endif #ifndef __JUCE_SINGLETON_JUCEHEADER__ @@ -19086,7 +19168,14 @@ public: /** Destructor. */ ~FileInputStream(); - const File& getFile() const noexcept { return file; } + /** Returns the file that this stream is reading from. */ + const File& getFile() const noexcept { return file; } + + /** Returns the status of the file stream. + The result will be ok if the file opened successfully. If an error occurs while + opening or reading from the file, this will contain an error message. + */ + const Result getStatus() const { return status; } int64 getTotalLength(); int read (void* destBuffer, int maxBytesToRead); @@ -19099,6 +19188,7 @@ private: File file; void* fileHandle; int64 currentPosition, totalSize; + Result status; bool needToSeek; void openHandle(); @@ -19154,9 +19244,16 @@ public: */ const File& getFile() const { return file; } + /** Returns the status of the file stream. + The result will be ok if the file opened successfully. If an error occurs while + opening or writing to the file, this will contain an error message. + */ + const Result getStatus() const { return status; } + /** Returns true if the stream couldn't be opened for some reason. + @see getResult() */ - bool failedToOpen() const { return fileHandle == 0; } + bool failedToOpen() const { return status.failed(); } void flush(); int64 getPosition(); @@ -19167,6 +19264,7 @@ private: File file; void* fileHandle; + Result status; int64 currentPosition; int bufferSize, bytesInBuffer; HeapBlock buffer; @@ -22219,6 +22317,13 @@ public: If signal() is called when nothing is waiting, the next thread to call wait() will return immediately and reset the signal. + If the WaitableEvent is manual reset, all threads that are currently waiting on this + object will be woken. + + If the WaitableEvent is automatic reset, and there are one or more threads waiting + on the object, then one of them will be woken up. If no threads are currently waiting, + then the next thread to call wait() will be woken up. + @see wait, reset */ void signal() const noexcept; @@ -46884,7 +46989,7 @@ public: /** @internal */ void colourChanged(); /** @internal */ - void startDragAndDrop (const MouseEvent& e, const var& dragDescription); + void startDragAndDrop (const MouseEvent& e, const var& dragDescription, bool allowDraggingToOtherWindows = true); private: diff --git a/src/audio/processors/juce_AudioProcessorGraph.cpp b/src/audio/processors/juce_AudioProcessorGraph.cpp index fded460da3..b321fd8a30 100644 --- a/src/audio/processors/juce_AudioProcessorGraph.cpp +++ b/src/audio/processors/juce_AudioProcessorGraph.cpp @@ -703,29 +703,40 @@ private: Entry* findEntry (const uint32 destNodeId, int& insertIndex) const noexcept { Entry* result = nullptr; - int firstElement = 0, lastElement = entries.size(); - while (firstElement < lastElement) + int start = 0; + int end = entries.size(); + + for (;;) { - Entry* const firstEntry = entries.getUnchecked (firstElement); - if (destNodeId == firstEntry->destNodeId) + if (start >= end) { - result = firstEntry; break; } - - const int halfway = (firstElement + lastElement) / 2; - - if (halfway <= firstElement) + else if (destNodeId == entries.getUnchecked (start)->destNodeId) + { + result = entries.getUnchecked (start); break; - - if (destNodeId >= entries.getUnchecked (halfway)->destNodeId) - firstElement = halfway; + } else - lastElement = halfway; + { + const int halfway = (start + end) / 2; + + if (halfway == start) + { + if (destNodeId >= entries.getUnchecked (halfway)->destNodeId) + ++start; + + break; + } + else if (destNodeId >= entries.getUnchecked (halfway)->destNodeId) + start = halfway; + else + end = halfway; + } } - insertIndex = firstElement; + insertIndex = start; return result; } diff --git a/src/core/juce_Result.cpp b/src/core/juce_Result.cpp new file mode 100644 index 0000000000..c78205f7bf --- /dev/null +++ b/src/core/juce_Result.cpp @@ -0,0 +1,92 @@ +/* + ============================================================================== + + This file is part of the JUCE library - "Jules' Utility Class Extensions" + Copyright 2004-11 by Raw Material Software Ltd. + + ------------------------------------------------------------------------------ + + JUCE can be redistributed and/or modified under the terms of the GNU General + Public License (Version 2), as published by the Free Software Foundation. + A copy of the license is included in the JUCE distribution, or can be found + online at www.gnu.org/licenses. + + JUCE is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + To release a closed-source product which uses JUCE, commercial licenses are + available: visit www.rawmaterialsoftware.com/juce for more information. + + ============================================================================== +*/ + +#include "juce_StandardHeader.h" + +BEGIN_JUCE_NAMESPACE + +#include "juce_Result.h" + + +//============================================================================== +Result::Result (const String& message) noexcept + : errorMessage (message) +{ +} + +Result::Result (const Result& other) + : errorMessage (other.errorMessage) +{ +} + +Result& Result::operator= (const Result& other) +{ + errorMessage = other.errorMessage; + return *this; +} + +bool Result::operator== (const Result& other) const noexcept +{ + return errorMessage == other.errorMessage; +} + +bool Result::operator!= (const Result& other) const noexcept +{ + return errorMessage != other.errorMessage; +} + +const Result Result::ok() noexcept +{ + return Result (String::empty); +} + +const Result Result::fail (const String& errorMessage) noexcept +{ + return Result (errorMessage.isEmpty() ? "Unknown Error" : errorMessage); +} + +//============================================================================== +bool Result::wasOk() const noexcept +{ + return errorMessage.isEmpty(); +} + +bool Result::failed() const noexcept +{ + return errorMessage.isNotEmpty(); +} + +Result::operator bool() const noexcept +{ + return errorMessage.isEmpty(); +} + +const String Result::getErrorMessage() const noexcept +{ + return errorMessage; +} + + +END_JUCE_NAMESPACE diff --git a/src/core/juce_Result.h b/src/core/juce_Result.h new file mode 100644 index 0000000000..1e5ea53259 --- /dev/null +++ b/src/core/juce_Result.h @@ -0,0 +1,107 @@ +/* + ============================================================================== + + This file is part of the JUCE library - "Jules' Utility Class Extensions" + Copyright 2004-11 by Raw Material Software Ltd. + + ------------------------------------------------------------------------------ + + JUCE can be redistributed and/or modified under the terms of the GNU General + Public License (Version 2), as published by the Free Software Foundation. + A copy of the license is included in the JUCE distribution, or can be found + online at www.gnu.org/licenses. + + JUCE is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + To release a closed-source product which uses JUCE, commercial licenses are + available: visit www.rawmaterialsoftware.com/juce for more information. + + ============================================================================== +*/ + +#ifndef __JUCE_RESULT_JUCEHEADER__ +#define __JUCE_RESULT_JUCEHEADER__ + +#include "../text/juce_String.h" + + +//============================================================================== +/** + Represents the 'success' or 'failure' of an operation, and holds an associated + error message to describe the error when there's a failure. + + E.g. + @code + const Result myOperation() + { + if (doSomeKindOfFoobar()) + return Result::ok(); + else + return Result::fail ("foobar didn't work!"); + } + + const Result result (myOperation()); + + if (result.wasOk()) + { + ...it's all good... + } + else + { + warnUserAboutFailure ("The foobar operation failed! Error message was: " + + result.getErrorMessage()); + } + @endcode +*/ +class Result +{ +public: + //============================================================================== + /** Creates and returns a 'successful' result. */ + static const Result ok() noexcept; + + /** Creates a 'failure' result. + If you pass a blank error message in here, a default "Unknown Error" message + will be used instead. + */ + static const Result fail (const String& errorMessage) noexcept; + + //============================================================================== + /** Returns true if this result indicates a success. */ + bool wasOk() const noexcept; + + /** Returns true if this result indicates a failure. + You can use getErrorMessage() to retrieve the error message associated + with the failure. + */ + bool failed() const noexcept; + + /** Returns true if this result indicates a success. + This is equivalent to calling wasOk(). + */ + operator bool() const noexcept; + + /** Returns the error message that was set when this result was created. + For a successful result, this will be an empty string; + */ + const String getErrorMessage() const noexcept; + + //============================================================================== + Result (const Result& other); + Result& operator= (const Result& other); + + bool operator== (const Result& other) const noexcept; + bool operator!= (const Result& other) const noexcept; + +private: + String errorMessage; + + explicit Result (const String& errorMessage) noexcept; +}; + + +#endif // __JUCE_RESULT_JUCEHEADER__ diff --git a/src/core/juce_StandardHeader.h b/src/core/juce_StandardHeader.h index 7150c26882..d4dd7d3a83 100644 --- a/src/core/juce_StandardHeader.h +++ b/src/core/juce_StandardHeader.h @@ -33,7 +33,7 @@ */ #define JUCE_MAJOR_VERSION 1 #define JUCE_MINOR_VERSION 53 -#define JUCE_BUILDNUMBER 75 +#define JUCE_BUILDNUMBER 76 /** Current Juce version number. diff --git a/src/gui/components/controls/juce_ListBox.cpp b/src/gui/components/controls/juce_ListBox.cpp index c4e764df45..f0fc67a3cf 100644 --- a/src/gui/components/controls/juce_ListBox.cpp +++ b/src/gui/components/controls/juce_ListBox.cpp @@ -915,7 +915,7 @@ const Image ListBox::createSnapshotOfSelectedRows (int& imageX, int& imageY) return snapshot; } -void ListBox::startDragAndDrop (const MouseEvent& e, const var& dragDescription) +void ListBox::startDragAndDrop (const MouseEvent& e, const var& dragDescription, bool allowDraggingToOtherWindows) { DragAndDropContainer* const dragContainer = DragAndDropContainer::findParentDragContainerFor (this); @@ -927,7 +927,7 @@ void ListBox::startDragAndDrop (const MouseEvent& e, const var& dragDescription) MouseEvent e2 (e.getEventRelativeTo (this)); const Point p (x - e2.x, y - e2.y); - dragContainer->startDragging (dragDescription, this, dragImage, true, &p); + dragContainer->startDragging (dragDescription, this, dragImage, allowDraggingToOtherWindows, &p); } else { diff --git a/src/gui/components/controls/juce_ListBox.h b/src/gui/components/controls/juce_ListBox.h index e9e5b6e703..4155cf93f1 100644 --- a/src/gui/components/controls/juce_ListBox.h +++ b/src/gui/components/controls/juce_ListBox.h @@ -560,7 +560,7 @@ public: /** @internal */ void colourChanged(); /** @internal */ - void startDragAndDrop (const MouseEvent& e, const var& dragDescription); + void startDragAndDrop (const MouseEvent& e, const var& dragDescription, bool allowDraggingToOtherWindows = true); private: //============================================================================== diff --git a/src/io/files/juce_File.cpp b/src/io/files/juce_File.cpp index 737efdf4ca..6adeae239e 100644 --- a/src/io/files/juce_File.cpp +++ b/src/io/files/juce_File.cpp @@ -445,37 +445,44 @@ const String File::descriptionOfSizeInBytes (const int64 bytes) } //============================================================================== -bool File::create() const +const Result File::create() const { if (exists()) - return true; + return Result::ok(); - { - const File parentDir (getParentDirectory()); + const File parentDir (getParentDirectory()); - if (parentDir == *this || ! parentDir.createDirectory()) - return false; + if (parentDir == *this) + return Result::fail ("Cannot create parent directory"); + + Result r (parentDir.createDirectory()); + if (r.wasOk()) + { FileOutputStream fo (*this, 8); + + r = fo.getStatus(); } - return exists(); + return r; } -bool File::createDirectory() const +const Result File::createDirectory() const { - if (! isDirectory()) - { - const File parentDir (getParentDirectory()); + if (isDirectory()) + return Result::ok(); - if (parentDir == *this || ! parentDir.createDirectory()) - return false; + const File parentDir (getParentDirectory()); - createDirectoryInternal (fullPath.trimCharactersAtEnd (separatorString)); - return isDirectory(); - } + if (parentDir == *this) + return Result::fail ("Cannot create parent directory"); - return true; + Result r (parentDir.createDirectory()); + + if (r.wasOk()) + r = createDirectoryInternal (fullPath.trimCharactersAtEnd (separatorString)); + + return r; } //============================================================================== diff --git a/src/io/files/juce_File.h b/src/io/files/juce_File.h index 26d8ef6441..23447665f6 100644 --- a/src/io/files/juce_File.h +++ b/src/io/files/juce_File.h @@ -31,6 +31,7 @@ #include "../../text/juce_StringArray.h" #include "../../memory/juce_MemoryBlock.h" #include "../../memory/juce_ScopedPointer.h" +#include "../../core/juce_Result.h" class FileInputStream; class FileOutputStream; @@ -425,18 +426,18 @@ public: @returns true if the file has been created (or if it already existed). @see createDirectory */ - bool create() const; + const Result create() const; /** Creates a new directory for this filename. This will try to create the file as a directory, and fill also create any parent directories it needs in order to complete the operation. - @returns true if the directory has been created successfully, (or if it - already existed beforehand). + @returns a result to indicate whether the directory was created successfully, or + an error message if it failed. @see create */ - bool createDirectory() const; + const Result createDirectory() const; /** Deletes a file. @@ -928,7 +929,7 @@ private: File (const String&, int); const String getPathUpToLastSlash() const; - void createDirectoryInternal (const String& fileName) const; + const Result createDirectoryInternal (const String& fileName) const; bool copyInternal (const File& dest) const; bool moveInternal (const File& dest) const; bool setFileTimesInternal (int64 modificationTime, int64 accessTime, int64 creationTime) const; diff --git a/src/io/files/juce_FileInputStream.cpp b/src/io/files/juce_FileInputStream.cpp index 2c7168c27b..c2a9ca564c 100644 --- a/src/io/files/juce_FileInputStream.cpp +++ b/src/io/files/juce_FileInputStream.cpp @@ -40,6 +40,7 @@ FileInputStream::FileInputStream (const File& f) fileHandle (nullptr), currentPosition (0), totalSize (0), + status (Result::ok()), needToSeek (true) { openHandle(); diff --git a/src/io/files/juce_FileInputStream.h b/src/io/files/juce_FileInputStream.h index 47d2671d8f..1c5a13f6c7 100644 --- a/src/io/files/juce_FileInputStream.h +++ b/src/io/files/juce_FileInputStream.h @@ -51,7 +51,14 @@ public: ~FileInputStream(); //============================================================================== - const File& getFile() const noexcept { return file; } + /** Returns the file that this stream is reading from. */ + const File& getFile() const noexcept { return file; } + + /** Returns the status of the file stream. + The result will be ok if the file opened successfully. If an error occurs while + opening or reading from the file, this will contain an error message. + */ + const Result getStatus() const { return status; } //============================================================================== int64 getTotalLength(); @@ -66,6 +73,7 @@ private: File file; void* fileHandle; int64 currentPosition, totalSize; + Result status; bool needToSeek; void openHandle(); diff --git a/src/io/files/juce_FileOutputStream.cpp b/src/io/files/juce_FileOutputStream.cpp index ab1eafb81f..46d51b82cf 100644 --- a/src/io/files/juce_FileOutputStream.cpp +++ b/src/io/files/juce_FileOutputStream.cpp @@ -36,6 +36,7 @@ int64 juce_fileSetPosition (void* handle, int64 pos); FileOutputStream::FileOutputStream (const File& f, const int bufferSize_) : file (f), fileHandle (nullptr), + status (Result::ok()), currentPosition (0), bufferSize (bufferSize_), bytesInBuffer (0), diff --git a/src/io/files/juce_FileOutputStream.h b/src/io/files/juce_FileOutputStream.h index 83c748a003..f43a6cadac 100644 --- a/src/io/files/juce_FileOutputStream.h +++ b/src/io/files/juce_FileOutputStream.h @@ -67,9 +67,16 @@ public: */ const File& getFile() const { return file; } + /** Returns the status of the file stream. + The result will be ok if the file opened successfully. If an error occurs while + opening or writing to the file, this will contain an error message. + */ + const Result getStatus() const { return status; } + /** Returns true if the stream couldn't be opened for some reason. + @see getResult() */ - bool failedToOpen() const { return fileHandle == 0; } + bool failedToOpen() const { return status.failed(); } //============================================================================== void flush(); @@ -82,6 +89,7 @@ private: //============================================================================== File file; void* fileHandle; + Result status; int64 currentPosition; int bufferSize, bytesInBuffer; HeapBlock buffer; diff --git a/src/juce_core_includes.h b/src/juce_core_includes.h index 6c12b8aaca..d88894e9d4 100644 --- a/src/juce_core_includes.h +++ b/src/juce_core_includes.h @@ -98,6 +98,9 @@ #ifndef __JUCE_RELATIVETIME_JUCEHEADER__ #include "core/juce_RelativeTime.h" #endif +#ifndef __JUCE_RESULT_JUCEHEADER__ + #include "core/juce_Result.h" +#endif #ifndef __JUCE_SINGLETON_JUCEHEADER__ #include "core/juce_Singleton.h" #endif diff --git a/src/native/common/juce_posix_SharedCode.h b/src/native/common/juce_posix_SharedCode.h index ce755b54d6..a4af1cdfa7 100644 --- a/src/native/common/juce_posix_SharedCode.h +++ b/src/native/common/juce_posix_SharedCode.h @@ -272,6 +272,16 @@ namespace if (isReadOnly != nullptr) *isReadOnly = access (path.toUTF8(), W_OK) != 0; } + + const Result getResultForErrno() + { + return Result::fail (String (strerror (errno))); + } + + const Result getResultForReturnValue (int value) + { + return value == -1 ? getResultForErrno() : Result::ok(); + } } bool File::isDirectory() const @@ -392,9 +402,9 @@ bool File::moveInternal (const File& dest) const return false; } -void File::createDirectoryInternal (const String& fileName) const +const Result File::createDirectoryInternal (const String& fileName) const { - mkdir (fileName.toUTF8(), 0777); + return getResultForReturnValue (mkdir (fileName.toUTF8(), 0777)); } //============================================================================== @@ -414,6 +424,8 @@ void FileInputStream::openHandle() if (f != -1) fileHandle = (void*) f; + else + status = getResultForErrno(); } void FileInputStream::closeHandle() @@ -427,10 +439,20 @@ void FileInputStream::closeHandle() size_t FileInputStream::readInternal (void* const buffer, const size_t numBytes) { + ssize_t result = 0; + if (fileHandle != 0) - return jmax ((ssize_t) 0, ::read ((int) (pointer_sized_int) fileHandle, buffer, numBytes)); + { + result = ::read ((int) (pointer_sized_int) fileHandle, buffer, numBytes); - return 0; + if (result < 0) + { + status = getResultForErrno(); + result = 0; + } + } + + return (size_t) result; } //============================================================================== @@ -445,9 +467,18 @@ void FileOutputStream::openHandle() currentPosition = lseek (f, 0, SEEK_END); if (currentPosition >= 0) + { fileHandle = (void*) f; + } else + { + status = getResultForErrno(); close (f); + } + } + else + { + status = getResultForErrno(); } } else @@ -456,6 +487,8 @@ void FileOutputStream::openHandle() if (f != -1) fileHandle = (void*) f; + else + status = getResultForErrno(); } } @@ -470,16 +503,24 @@ void FileOutputStream::closeHandle() int FileOutputStream::writeInternal (const void* const data, const int numBytes) { + ssize_t result = 0; + if (fileHandle != 0) - return (int) ::write ((int) (pointer_sized_int) fileHandle, data, numBytes); + { + result = ::write ((int) (pointer_sized_int) fileHandle, data, numBytes); - return 0; + if (result == -1) + status = getResultForErrno(); + } + + return (int) result; } void FileOutputStream::flushInternal() { if (fileHandle != 0) - fsync ((int) (pointer_sized_int) fileHandle); + if (fsync ((int) (pointer_sized_int) fileHandle) == -1) + status = getResultForErrno(); } //============================================================================== diff --git a/src/native/windows/juce_win32_Files.cpp b/src/native/windows/juce_win32_Files.cpp index 53aeb0d3dd..cacc24c2d9 100644 --- a/src/native/windows/juce_win32_Files.cpp +++ b/src/native/windows/juce_win32_Files.cpp @@ -93,6 +93,17 @@ namespace WindowsFileHelpers return File::nonexistent; } + + const Result getResultForLastError() + { + TCHAR messageBuffer [256] = { 0 }; + + FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + nullptr, GetLastError(), MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), + messageBuffer, numElementsInArray (messageBuffer) - 1, nullptr); + + return Result::fail (String (messageBuffer)); + } } //============================================================================== @@ -192,9 +203,10 @@ bool File::moveInternal (const File& dest) const return MoveFile (fullPath.toWideCharPointer(), dest.getFullPathName().toWideCharPointer()) != 0; } -void File::createDirectoryInternal (const String& fileName) const +const Result File::createDirectoryInternal (const String& fileName) const { - CreateDirectory (fileName.toWideCharPointer(), 0); + return CreateDirectory (fileName.toWideCharPointer(), 0) ? Result::ok() + : WindowsFileHelpers::getResultForLastError(); } //============================================================================== @@ -215,6 +227,8 @@ void FileInputStream::openHandle() if (h != INVALID_HANDLE_VALUE) fileHandle = (void*) h; + else + status = WindowsFileHelpers::getResultForLastError(); } void FileInputStream::closeHandle() @@ -227,7 +241,9 @@ size_t FileInputStream::readInternal (void* buffer, size_t numBytes) if (fileHandle != 0) { DWORD actualNum = 0; - ReadFile ((HANDLE) fileHandle, buffer, numBytes, &actualNum, 0); + if (! ReadFile ((HANDLE) fileHandle, buffer, numBytes, &actualNum, 0)) + status = WindowsFileHelpers::getResultForLastError(); + return (size_t) actualNum; } @@ -250,8 +266,11 @@ void FileOutputStream::openHandle() { fileHandle = (void*) h; currentPosition = li.QuadPart; + return; } } + + status = WindowsFileHelpers::getResultForLastError(); } void FileOutputStream::closeHandle() @@ -261,10 +280,12 @@ void FileOutputStream::closeHandle() int FileOutputStream::writeInternal (const void* buffer, int numBytes) { - if (fileHandle != 0) + if (fileHandle != nullptr) { DWORD actualNum = 0; - WriteFile ((HANDLE) fileHandle, buffer, numBytes, &actualNum, 0); + if (! WriteFile ((HANDLE) fileHandle, buffer, numBytes, &actualNum, 0)) + status = WindowsFileHelpers::getResultForLastError(); + return (int) actualNum; } @@ -273,8 +294,9 @@ int FileOutputStream::writeInternal (const void* buffer, int numBytes) void FileOutputStream::flushInternal() { - if (fileHandle != 0) - FlushFileBuffers ((HANDLE) fileHandle); + if (fileHandle != nullptr) + if (! FlushFileBuffers ((HANDLE) fileHandle)) + status = WindowsFileHelpers::getResultForLastError(); } //============================================================================== diff --git a/src/threads/juce_WaitableEvent.h b/src/threads/juce_WaitableEvent.h index 2be1c394f6..1e4697a6ca 100644 --- a/src/threads/juce_WaitableEvent.h +++ b/src/threads/juce_WaitableEvent.h @@ -79,6 +79,13 @@ public: If signal() is called when nothing is waiting, the next thread to call wait() will return immediately and reset the signal. + If the WaitableEvent is manual reset, all threads that are currently waiting on this + object will be woken. + + If the WaitableEvent is automatic reset, and there are one or more threads waiting + on the object, then one of them will be woken up. If no threads are currently waiting, + then the next thread to call wait() will be woken up. + @see wait, reset */ void signal() const noexcept; diff --git a/src/utilities/juce_RecentlyOpenedFilesList.cpp b/src/utilities/juce_RecentlyOpenedFilesList.cpp index 8ae1f61185..cb12f890b3 100644 --- a/src/utilities/juce_RecentlyOpenedFilesList.cpp +++ b/src/utilities/juce_RecentlyOpenedFilesList.cpp @@ -45,8 +45,7 @@ void RecentlyOpenedFilesList::setMaxNumberOfItems (const int newMaxNumber) { maxNumberOfItems = jmax (1, newMaxNumber); - while (getNumFiles() > maxNumberOfItems) - files.remove (getNumFiles() - 1); + files.removeRange (maxNumberOfItems, getNumFiles()); } int RecentlyOpenedFilesList::getNumFiles() const @@ -66,10 +65,8 @@ void RecentlyOpenedFilesList::clear() void RecentlyOpenedFilesList::addFile (const File& file) { - const String path (file.getFullPathName()); - - files.removeString (path, true); - files.insert (0, path); + removeFile (file); + files.insert (0, file.getFullPathName()); setMaxNumberOfItems (maxNumberOfItems); }