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);
}