Browse Source

Added method String::containsNonWhitespaceChars(); changed the XML parser to not strip whitespace from around text elements, and also added XmlDocument::setEmptyTextElementsIgnored() to make it optionally keep all whitespace-only text elements. Added methods File::containsSubDirectories(), WebBrowserComponent::refresh(), TreeView::deleteRootItem(). Ironed out a possible bug with buttons crashing when deleted during a keypress callback. Changed pixel ordering to sort out transparent windows on PPC macs. Also fixed a mac AU build problem, and removed a couple of gcc warnings.

tags/2021-05-28
jules 17 years ago
parent
commit
4c1b6ce430
25 changed files with 3409 additions and 3138 deletions
  1. +4
    -0
      build/linux/platform_specific_code/juce_linux_WebBrowserComponent.cpp
  2. +14
    -2
      build/macosx/platform_specific_code/juce_mac_NSViewComponentPeer.mm
  3. +10
    -0
      build/macosx/platform_specific_code/juce_mac_WebBrowserComponent.mm
  4. +1
    -1
      build/win32/platform_specific_code/juce_win32_FileChooser.cpp
  5. +1
    -1
      build/win32/platform_specific_code/juce_win32_Files.cpp
  6. +6
    -0
      build/win32/platform_specific_code/juce_win32_WebBrowserComponent.cpp
  7. +135
    -45
      juce_amalgamated.cpp
  8. +48
    -3
      juce_amalgamated.h
  9. +3043
    -3042
      src/juce_appframework/audio/plugins/formats/juce_VSTPluginFormat.cpp
  10. +1
    -1
      src/juce_appframework/audio/plugins/juce_KnownPluginList.cpp
  11. +6
    -1
      src/juce_appframework/gui/components/buttons/juce_Button.cpp
  12. +8
    -0
      src/juce_appframework/gui/components/controls/juce_TreeView.cpp
  13. +8
    -1
      src/juce_appframework/gui/components/controls/juce_TreeView.h
  14. +1
    -1
      src/juce_appframework/gui/components/filebrowser/juce_FileChooser.cpp
  15. +3
    -0
      src/juce_appframework/gui/components/special/juce_WebBrowserComponent.h
  16. +8
    -1
      src/juce_core/cryptography/juce_MD5.h
  17. +41
    -12
      src/juce_core/io/files/juce_File.cpp
  18. +5
    -0
      src/juce_core/io/files/juce_File.h
  19. +16
    -0
      src/juce_core/text/juce_String.cpp
  20. +13
    -0
      src/juce_core/text/juce_String.h
  21. +1
    -1
      src/juce_core/text/juce_StringArray.cpp
  22. +8
    -3
      src/juce_core/text/juce_XmlDocument.cpp
  23. +9
    -1
      src/juce_core/text/juce_XmlDocument.h
  24. +1
    -1
      src/juce_core/text/juce_XmlElement.cpp
  25. +18
    -21
      src/juce_core/threads/juce_Thread.cpp

+ 4
- 0
build/linux/platform_specific_code/juce_linux_WebBrowserComponent.cpp View File

@@ -90,6 +90,10 @@ void WebBrowserComponent::goForward()
} }
void WebBrowserComponent::refresh()
{
}
//============================================================================== //==============================================================================
void WebBrowserComponent::paint (Graphics& g) void WebBrowserComponent::paint (Graphics& g)
{ {


+ 14
- 2
build/macosx/platform_specific_code/juce_mac_NSViewComponentPeer.mm View File

@@ -543,6 +543,9 @@ private:
void swapRGBOrder (const int x, const int y, const int w, int h) const void swapRGBOrder (const int x, const int y, const int w, int h) const
{ {
#if JUCE_BIG_ENDIAN
jassert (pixelStride == 4);
#endif
jassert (Rectangle (0, 0, juceImage.getWidth(), juceImage.getHeight()) jassert (Rectangle (0, 0, juceImage.getWidth(), juceImage.getHeight())
.contains (Rectangle (x, y, w, h))); .contains (Rectangle (x, y, w, h)));
@@ -555,9 +558,18 @@ private:
for (int i = w; --i >= 0;) for (int i = w; --i >= 0;)
{ {
const uint8 temp = p[0];
#if JUCE_BIG_ENDIAN
const uint8 oldp3 = p[3];
const uint8 oldp1 = p[1];
p[3] = p[0];
p[0] = oldp1;
p[1] = p[2];
p[2] = oldp3;
#else
const uint8 oldp0 = p[0];
p[0] = p[2]; p[0] = p[2];
p[2] = temp;
p[2] = oldp0;
#endif
p += pixelStride; p += pixelStride;
} }


+ 10
- 0
build/macosx/platform_specific_code/juce_mac_WebBrowserComponent.mm View File

@@ -147,6 +147,11 @@ public:
{ {
[webView stopLoading: nil]; [webView stopLoading: nil];
} }
void refresh()
{
[webView reload: nil];
}
private: private:
WebView* webView; WebView* webView;
@@ -206,6 +211,11 @@ void WebBrowserComponent::goForward()
browser->goForward(); browser->goForward();
} }
void WebBrowserComponent::refresh()
{
browser->refresh();
}
//============================================================================== //==============================================================================
void WebBrowserComponent::paint (Graphics& g) void WebBrowserComponent::paint (Graphics& g)
{ {


+ 1
- 1
build/win32/platform_specific_code/juce_win32_FileChooser.cpp View File

@@ -70,7 +70,7 @@ static int CALLBACK browseCallbackProc (HWND hWnd, UINT msg, LPARAM lParam, LPAR
return 0; return 0;
} }
void juce_setWindowStyleBit (HWND h, int styleType, int feature, bool bitIsSet);
void juce_setWindowStyleBit (HWND h, int styleType, int feature, bool bitIsSet) throw();
static UINT_PTR CALLBACK openCallback (HWND hdlg, UINT uiMsg, WPARAM /*wParam*/, LPARAM lParam) static UINT_PTR CALLBACK openCallback (HWND hdlg, UINT uiMsg, WPARAM /*wParam*/, LPARAM lParam)
{ {


+ 1
- 1
build/win32/platform_specific_code/juce_win32_Files.cpp View File

@@ -77,7 +77,7 @@ bool juce_canWriteToFile (const String& fileName) throw()
} }
bool juce_setFileReadOnly (const String& fileName, bool juce_setFileReadOnly (const String& fileName,
bool isReadOnly)
bool isReadOnly) throw()
{ {
DWORD attr = GetFileAttributes (fileName); DWORD attr = GetFileAttributes (fileName);


+ 6
- 0
build/win32/platform_specific_code/juce_win32_WebBrowserComponent.cpp View File

@@ -272,6 +272,12 @@ void WebBrowserComponent::goForward()
browser->browser->GoForward(); browser->browser->GoForward();
} }
void WebBrowserComponent::refresh()
{
if (browser->browser != 0)
browser->browser->Refresh();
}
//============================================================================== //==============================================================================
void WebBrowserComponent::paint (Graphics& g) void WebBrowserComponent::paint (Graphics& g)
{ {


+ 135
- 45
juce_amalgamated.cpp View File

@@ -5351,6 +5351,12 @@ bool juce_findFileNext (void* handle, String& resultFile,


void juce_findFileClose (void* handle) throw(); void juce_findFileClose (void* handle) throw();


static const String juce_addTrailingSeparator (const String& path) throw()
{
return path.endsWithChar (File::separator) ? path
: path + File::separator;
}

static const String parseAbsolutePath (String path) throw() static const String parseAbsolutePath (String path) throw()
{ {
if (path.isEmpty()) if (path.isEmpty())
@@ -5742,10 +5748,7 @@ const File File::getChildFile (String relativePath) const throw()
} }
} }


if (! path.endsWithChar (separator))
path += separator;

return File (path + relativePath);
return File (juce_addTrailingSeparator (path) + relativePath);
} }
} }


@@ -5902,9 +5905,7 @@ int File::findChildFiles (OwnedArray<File>& results,
// find child files or directories in this directory first.. // find child files or directories in this directory first..
if (isDirectory()) if (isDirectory())
{ {
String path (fullPath);
if (! path.endsWithChar (separator))
path += separator;
const String path (juce_addTrailingSeparator (fullPath));


String filename; String filename;
bool isDirectory, isHidden; bool isDirectory, isHidden;
@@ -5999,6 +6000,37 @@ int File::getNumberOfChildFiles (const int whatToLookFor,
return count; return count;
} }


bool File::containsSubDirectories() const throw()
{
bool result = false;

if (isDirectory())
{
String filename;
bool isDirectory, isHidden;
void* const handle = juce_findFileStart (juce_addTrailingSeparator (fullPath),
T("*"), filename,
&isDirectory, &isHidden, 0, 0, 0, 0);

if (handle != 0)
{
do
{
if (isDirectory)
{
result = true;
break;
}

} while (juce_findFileNext (handle, filename, &isDirectory, &isHidden, 0, 0, 0, 0));

juce_findFileClose (handle);
}
}

return result;
}

const File File::getNonexistentChildFile (const String& prefix_, const File File::getNonexistentChildFile (const String& prefix_,
const String& suffix, const String& suffix,
bool putNumbersInBrackets) const throw() bool putNumbersInBrackets) const throw()
@@ -6272,11 +6304,8 @@ const String File::getRelativePathFrom (const File& dir) const throw()
thisPath [len] = 0; thisPath [len] = 0;
} }


String dirPath ((dir.existsAsFile()) ? dir.getParentDirectory().getFullPathName()
: dir.fullPath);

if (! dirPath.endsWithChar (separator))
dirPath += separator;
String dirPath (juce_addTrailingSeparator ((dir.existsAsFile()) ? dir.getParentDirectory().getFullPathName()
: dir.fullPath));


const int len = jmin (thisPath.length(), dirPath.length()); const int len = jmin (thisPath.length(), dirPath.length());
int commonBitLength = 0; int commonBitLength = 0;
@@ -11152,11 +11181,15 @@ bool String::startsWithIgnoreCase (const tchar* const other) const throw()


bool String::startsWithChar (const tchar character) const throw() bool String::startsWithChar (const tchar character) const throw()
{ {
jassert (character != 0); // strings can't contain a null character!

return text->text[0] == character; return text->text[0] == character;
} }


bool String::endsWithChar (const tchar character) const throw() bool String::endsWithChar (const tchar character) const throw()
{ {
jassert (character != 0); // strings can't contain a null character!

return text->text[0] != 0 return text->text[0] != 0
&& text->text [length() - 1] == character; && text->text [length() - 1] == character;
} }
@@ -11502,6 +11535,17 @@ bool String::containsAnyOf (const tchar* const chars) const throw()
return false; return false;
} }


bool String::containsNonWhitespaceChars() const throw()
{
const tchar* t = text->text;

while (*t != 0)
if (! CharacterFunctions::isWhitespace (*t++))
return true;

return false;
}

int String::getIntValue() const throw() int String::getIntValue() const throw()
{ {
return CharacterFunctions::getIntValue (text->text); return CharacterFunctions::getIntValue (text->text);
@@ -12096,7 +12140,7 @@ void StringArray::removeEmptyStrings (const bool removeWhitespaceStrings) throw(
if (removeWhitespaceStrings) if (removeWhitespaceStrings)
{ {
for (int i = size(); --i >= 0;) for (int i = size(); --i >= 0;)
if (((const String*) strings.getUnchecked(i))->trim().isEmpty())
if (! ((const String*) strings.getUnchecked(i))->containsNonWhitespaceChars())
remove (i); remove (i);
} }
else else
@@ -12525,6 +12569,7 @@ static bool isXmlIdentifierChar_Slow (const tchar c) throw()


XmlDocument::XmlDocument (const String& documentText) throw() XmlDocument::XmlDocument (const String& documentText) throw()
: originalText (documentText), : originalText (documentText),
ignoreEmptyTextElements (true),
inputSource (0) inputSource (0)
{ {
} }
@@ -12548,6 +12593,11 @@ void XmlDocument::setInputSource (InputSource* const newSource) throw()
} }
} }


void XmlDocument::setEmptyTextElementsIgnored (const bool shouldBeIgnored) throw()
{
ignoreEmptyTextElements = shouldBeIgnored;
}

XmlElement* XmlDocument::getDocumentElement (const bool onlyReadOuterDocumentElement) XmlElement* XmlDocument::getDocumentElement (const bool onlyReadOuterDocumentElement)
{ {
String textToParse (originalText); String textToParse (originalText);
@@ -13097,9 +13147,8 @@ void XmlDocument::readChildElements (XmlElement* parent) throw()
} }
} }


textElementContent = textElementContent.trim();

if (textElementContent.isNotEmpty())
if (ignoreEmptyTextElements ? textElementContent.containsNonWhitespaceChars()
: textElementContent.isNotEmpty())
e->setText (textElementContent); e->setText (textElementContent);
} }
} }
@@ -13412,7 +13461,7 @@ XmlElement::XmlElement (const String& tagName_) throw()
attributes (0) attributes (0)
{ {
// the tag name mustn't be empty, or it'll look like a text element! // the tag name mustn't be empty, or it'll look like a text element!
jassert (tagName_.trim().isNotEmpty())
jassert (tagName_.containsNonWhitespaceChars())
} }


XmlElement::XmlElement (int /*dummy*/) throw() XmlElement::XmlElement (int /*dummy*/) throw()
@@ -14684,9 +14733,10 @@ static CriticalSection runningThreadsLock;


void Thread::threadEntryPoint (Thread* const thread) throw() void Thread::threadEntryPoint (Thread* const thread) throw()
{ {
runningThreadsLock.enter();
runningThreads.add (thread);
runningThreadsLock.exit();
{
const ScopedLock sl (runningThreadsLock);
runningThreads.add (thread);
}


JUCE_TRY JUCE_TRY
{ {
@@ -14705,10 +14755,12 @@ void Thread::threadEntryPoint (Thread* const thread) throw()
} }
JUCE_CATCH_ALL_ASSERT JUCE_CATCH_ALL_ASSERT


runningThreadsLock.enter();
jassert (runningThreads.contains (thread));
runningThreads.removeValue (thread);
runningThreadsLock.exit();
{
const ScopedLock sl (runningThreadsLock);

jassert (runningThreads.contains (thread));
runningThreads.removeValue (thread);
}


#if JUCE_WIN32 #if JUCE_WIN32
juce_CloseThreadHandle (thread->threadHandle_); juce_CloseThreadHandle (thread->threadHandle_);
@@ -14872,34 +14924,28 @@ int Thread::getNumRunningThreads() throw()
Thread* Thread::getCurrentThread() throw() Thread* Thread::getCurrentThread() throw()
{ {
const ThreadID thisId = getCurrentThreadId(); const ThreadID thisId = getCurrentThreadId();
Thread* result = 0;


runningThreadsLock.enter();
const ScopedLock sl (runningThreadsLock);


for (int i = runningThreads.size(); --i >= 0;) for (int i = runningThreads.size(); --i >= 0;)
{ {
Thread* const t = (Thread*) (runningThreads.getUnchecked(i)); Thread* const t = (Thread*) (runningThreads.getUnchecked(i));


if (t->threadId_ == thisId) if (t->threadId_ == thisId)
{
result = t;
break;
}
return t;
} }


runningThreadsLock.exit();

return result;
return 0;
} }


void Thread::stopAllThreads (const int timeOutMilliseconds) throw() void Thread::stopAllThreads (const int timeOutMilliseconds) throw()
{ {
runningThreadsLock.enter();

for (int i = runningThreads.size(); --i >= 0;)
((Thread*) runningThreads.getUnchecked(i))->signalThreadShouldExit();
{
const ScopedLock sl (runningThreadsLock);


runningThreadsLock.exit();
for (int i = runningThreads.size(); --i >= 0;)
((Thread*) runningThreads.getUnchecked(i))->signalThreadShouldExit();
}


for (;;) for (;;)
{ {
@@ -27173,7 +27219,7 @@ void KnownPluginList::addToMenu (PopupMenu& menu, const SortMethod sortMethod) c
String thisSubMenuName (sortMethod == sortByCategory ? pd->category String thisSubMenuName (sortMethod == sortByCategory ? pd->category
: pd->manufacturerName); : pd->manufacturerName);


if (thisSubMenuName.trim().isEmpty())
if (! thisSubMenuName.containsNonWhitespaceChars())
thisSubMenuName = T("Other"); thisSubMenuName = T("Other");


if (thisSubMenuName != lastSubMenuName) if (thisSubMenuName != lastSubMenuName)
@@ -41632,9 +41678,14 @@ bool Button::keyStateChanged (Component*)
updateState (0); updateState (0);


if (isEnabled() && wasDown && ! isKeyDown) if (isEnabled() && wasDown && ! isKeyDown)
{
internalClickCallback (ModifierKeys::getCurrentModifiers()); internalClickCallback (ModifierKeys::getCurrentModifiers());


return isKeyDown || wasDown;
// (return immediately - this button may now have been deleted)
return true;
}

return wasDown || isKeyDown;
} }


bool Button::keyPressed (const KeyPress&, Component*) bool Button::keyPressed (const KeyPress&, Component*)
@@ -51504,6 +51555,13 @@ void TreeView::setRootItem (TreeViewItem* const newRootItem)
} }
} }


void TreeView::deleteRootItem()
{
TreeViewItem* const oldItem = rootItem;
setRootItem (0);
delete oldItem;
}

void TreeView::setRootItemVisible (const bool shouldBeVisible) void TreeView::setRootItemVisible (const bool shouldBeVisible)
{ {
rootItemVisible = shouldBeVisible; rootItemVisible = shouldBeVisible;
@@ -53286,7 +53344,7 @@ FileChooser::FileChooser (const String& chooserBoxTitle,
useNativeDialogBox = false; useNativeDialogBox = false;
#endif #endif


if (fileFilters.trim().isEmpty())
if (! fileFilters.containsNonWhitespaceChars())
filters = T("*"); filters = T("*");
} }


@@ -239911,7 +239969,7 @@ bool juce_canWriteToFile (const String& fileName) throw()
} }


bool juce_setFileReadOnly (const String& fileName, bool juce_setFileReadOnly (const String& fileName,
bool isReadOnly)
bool isReadOnly) throw()
{ {
DWORD attr = GetFileAttributes (fileName); DWORD attr = GetFileAttributes (fileName);


@@ -245012,7 +245070,7 @@ static int CALLBACK browseCallbackProc (HWND hWnd, UINT msg, LPARAM lParam, LPAR
return 0; return 0;
} }


void juce_setWindowStyleBit (HWND h, int styleType, int feature, bool bitIsSet);
void juce_setWindowStyleBit (HWND h, int styleType, int feature, bool bitIsSet) throw();


static UINT_PTR CALLBACK openCallback (HWND hdlg, UINT uiMsg, WPARAM /*wParam*/, LPARAM lParam) static UINT_PTR CALLBACK openCallback (HWND hdlg, UINT uiMsg, WPARAM /*wParam*/, LPARAM lParam)
{ {
@@ -246576,6 +246634,12 @@ void WebBrowserComponent::goForward()
browser->browser->GoForward(); browser->browser->GoForward();
} }


void WebBrowserComponent::refresh()
{
if (browser->browser != 0)
browser->browser->Refresh();
}

void WebBrowserComponent::paint (Graphics& g) void WebBrowserComponent::paint (Graphics& g)
{ {
if (browser->browser == 0) if (browser->browser == 0)
@@ -259370,6 +259434,10 @@ void WebBrowserComponent::goForward()


} }


void WebBrowserComponent::refresh()
{
}

void WebBrowserComponent::paint (Graphics& g) void WebBrowserComponent::paint (Graphics& g)
{ {
g.fillAll (Colours::white); g.fillAll (Colours::white);
@@ -265555,6 +265623,9 @@ private:


void swapRGBOrder (const int x, const int y, const int w, int h) const void swapRGBOrder (const int x, const int y, const int w, int h) const
{ {
#if JUCE_BIG_ENDIAN
jassert (pixelStride == 4);
#endif
jassert (Rectangle (0, 0, juceImage.getWidth(), juceImage.getHeight()) jassert (Rectangle (0, 0, juceImage.getWidth(), juceImage.getHeight())
.contains (Rectangle (x, y, w, h))); .contains (Rectangle (x, y, w, h)));


@@ -265567,9 +265638,18 @@ private:


for (int i = w; --i >= 0;) for (int i = w; --i >= 0;)
{ {
const uint8 temp = p[0];
#if JUCE_BIG_ENDIAN
const uint8 oldp3 = p[3];
const uint8 oldp1 = p[1];
p[3] = p[0];
p[0] = oldp1;
p[1] = p[2];
p[2] = oldp3;
#else
const uint8 oldp0 = p[0];
p[0] = p[2]; p[0] = p[2];
p[2] = temp;
p[2] = oldp0;
#endif


p += pixelStride; p += pixelStride;
} }
@@ -269370,6 +269450,11 @@ public:
[webView stopLoading: nil]; [webView stopLoading: nil];
} }


void refresh()
{
[webView reload: nil];
}

private: private:
WebView* webView; WebView* webView;
DownloadClickDetector* clickListener; DownloadClickDetector* clickListener;
@@ -269426,6 +269511,11 @@ void WebBrowserComponent::goForward()
browser->goForward(); browser->goForward();
} }


void WebBrowserComponent::refresh()
{
browser->refresh();
}

void WebBrowserComponent::paint (Graphics& g) void WebBrowserComponent::paint (Graphics& g)
{ {
} }


+ 48
- 3
juce_amalgamated.h View File

@@ -1535,12 +1535,16 @@ public:
/** Returns true if the string contains no characters. /** Returns true if the string contains no characters.


Note that there's also an isNotEmpty() method to help write readable code. Note that there's also an isNotEmpty() method to help write readable code.

@see containsNonWhitespaceChars()
*/ */
inline bool isEmpty() const throw() { return text->text[0] == 0; } inline bool isEmpty() const throw() { return text->text[0] == 0; }


/** Returns true if the string contains at least one character. /** Returns true if the string contains at least one character.


Note that there's also an isEmpty() method to help write readable code. Note that there's also an isEmpty() method to help write readable code.

@see containsNonWhitespaceChars()
*/ */
inline bool isNotEmpty() const throw() { return text->text[0] != 0; } inline bool isNotEmpty() const throw() { return text->text[0] != 0; }


@@ -1700,6 +1704,15 @@ public:
*/ */
bool containsOnly (const tchar* const charactersItMightContain) const throw(); bool containsOnly (const tchar* const charactersItMightContain) const throw();


/** Returns true if this string contains any non-whitespace characters.

This will return false if the string contains only whitespace characters, or
if it's empty.

It is equivalent to calling "myString.trim().isNotEmpty()".
*/
bool containsNonWhitespaceChars() const throw();

/** Returns true if the string matches this simple wildcard expression. /** Returns true if the string matches this simple wildcard expression.


So for example String ("abcdef").matchesWildcard ("*DEF", true) would return true. So for example String ("abcdef").matchesWildcard ("*DEF", true) would return true.
@@ -6534,6 +6547,11 @@ public:
int getNumberOfChildFiles (const int whatToLookFor, int getNumberOfChildFiles (const int whatToLookFor,
const String& wildCardPattern = JUCE_T("*")) const throw(); const String& wildCardPattern = JUCE_T("*")) const throw();


/** Returns true if this file is a directory that contains one or more subdirectories.
@see isDirectory, findChildFiles
*/
bool File::containsSubDirectories() const throw();

/** Creates a stream to read from this file. /** Creates a stream to read from this file.


@returns a stream that will read from this file (initially positioned at the @returns a stream that will read from this file (initially positioned at the
@@ -11812,7 +11830,14 @@ public:
/** Creates a checksum for a block of binary data. */ /** Creates a checksum for a block of binary data. */
MD5 (const char* data, const int numBytes); MD5 (const char* data, const int numBytes);


/** Creates a checksum for a string. */
/** Creates a checksum for a string.

Note that this operates on the string as a block of unicode characters, so the
result you get will differ from the value you'd get if the string was treated
as a block of utf8 or ascii. Bear this in mind if you're comparing the result
of this method with a checksum created by a different framework, which may have
used a different encoding.
*/
MD5 (const String& text); MD5 (const String& text);


/** Creates a checksum for the input from a stream. /** Creates a checksum for the input from a stream.
@@ -13751,6 +13776,15 @@ public:
*/ */
void setInputSource (InputSource* const newSource) throw(); void setInputSource (InputSource* const newSource) throw();


/** Sets a flag to change the treatment of empty text elements.

If this is true (the default state), then any text elements that contain only
whitespace characters will be ingored during parsing. If you need to catch
whitespace-only text, then you should set this to false before calling the
getDocumentElement() method.
*/
void setEmptyTextElementsIgnored (const bool shouldBeIgnored) throw();

juce_UseDebuggingNewOperator juce_UseDebuggingNewOperator


private: private:
@@ -13761,7 +13795,7 @@ private:
bool identifierLookupTable [128]; bool identifierLookupTable [128];
String lastError, dtdText; String lastError, dtdText;
StringArray tokenisedDTD; StringArray tokenisedDTD;
bool needToLoadDTD;
bool needToLoadDTD, ignoreEmptyTextElements;
InputSource* inputSource; InputSource* inputSource;


void setLastError (const String& desc, const bool carryOn) throw(); void setLastError (const String& desc, const bool carryOn) throw();
@@ -43179,7 +43213,8 @@ public:
The object passed in will not be deleted by the treeview, it's up to the caller The object passed in will not be deleted by the treeview, it's up to the caller
to delete it when no longer needed. BUT make absolutely sure that you don't delete to delete it when no longer needed. BUT make absolutely sure that you don't delete
this item until you've removed it from the tree, either by calling setRootItem (0), this item until you've removed it from the tree, either by calling setRootItem (0),
or by deleting the tree first.
or by deleting the tree first. You can also use deleteRootItem() as a quick way
to delete it.
*/ */
void setRootItem (TreeViewItem* const newRootItem); void setRootItem (TreeViewItem* const newRootItem);


@@ -43189,6 +43224,12 @@ public:
*/ */
TreeViewItem* getRootItem() const throw() { return rootItem; } TreeViewItem* getRootItem() const throw() { return rootItem; }


/** This will remove and delete the current root item.

It's a convenient way of deleting the item and calling setRootItem (0).
*/
void deleteRootItem();

/** Changes whether the tree's root item is shown or not. /** Changes whether the tree's root item is shown or not.


If the root item is hidden, only its sub-items will be shown in the treeview - this If the root item is hidden, only its sub-items will be shown in the treeview - this
@@ -52820,6 +52861,10 @@ public:
*/ */
void goForward(); void goForward();


/** Refreshes the browser.
*/
void refresh();

/** This callback is called when the browser is about to navigate /** This callback is called when the browser is about to navigate
to a new location. to a new location.




+ 3043
- 3042
src/juce_appframework/audio/plugins/formats/juce_VSTPluginFormat.cpp
File diff suppressed because it is too large
View File


+ 1
- 1
src/juce_appframework/audio/plugins/juce_KnownPluginList.cpp View File

@@ -416,7 +416,7 @@ void KnownPluginList::addToMenu (PopupMenu& menu, const SortMethod sortMethod) c
String thisSubMenuName (sortMethod == sortByCategory ? pd->category String thisSubMenuName (sortMethod == sortByCategory ? pd->category
: pd->manufacturerName); : pd->manufacturerName);
if (thisSubMenuName.trim().isEmpty())
if (! thisSubMenuName.containsNonWhitespaceChars())
thisSubMenuName = T("Other"); thisSubMenuName = T("Other");
if (thisSubMenuName != lastSubMenuName) if (thisSubMenuName != lastSubMenuName)


+ 6
- 1
src/juce_appframework/gui/components/buttons/juce_Button.cpp View File

@@ -613,9 +613,14 @@ bool Button::keyStateChanged (Component*)
updateState (0); updateState (0);
if (isEnabled() && wasDown && ! isKeyDown) if (isEnabled() && wasDown && ! isKeyDown)
{
internalClickCallback (ModifierKeys::getCurrentModifiers()); internalClickCallback (ModifierKeys::getCurrentModifiers());
return isKeyDown || wasDown;
// (return immediately - this button may now have been deleted)
return true;
}
return wasDown || isKeyDown;
} }
bool Button::keyPressed (const KeyPress&, Component*) bool Button::keyPressed (const KeyPress&, Component*)


+ 8
- 0
src/juce_appframework/gui/components/controls/juce_TreeView.cpp View File

@@ -435,6 +435,14 @@ void TreeView::setRootItem (TreeViewItem* const newRootItem)
} }
} }
void TreeView::deleteRootItem()
{
TreeViewItem* const oldItem = rootItem;
setRootItem (0);
delete oldItem;
}
void TreeView::setRootItemVisible (const bool shouldBeVisible) void TreeView::setRootItemVisible (const bool shouldBeVisible)
{ {
rootItemVisible = shouldBeVisible; rootItemVisible = shouldBeVisible;


+ 8
- 1
src/juce_appframework/gui/components/controls/juce_TreeView.h View File

@@ -414,7 +414,8 @@ public:
The object passed in will not be deleted by the treeview, it's up to the caller The object passed in will not be deleted by the treeview, it's up to the caller
to delete it when no longer needed. BUT make absolutely sure that you don't delete to delete it when no longer needed. BUT make absolutely sure that you don't delete
this item until you've removed it from the tree, either by calling setRootItem (0), this item until you've removed it from the tree, either by calling setRootItem (0),
or by deleting the tree first.
or by deleting the tree first. You can also use deleteRootItem() as a quick way
to delete it.
*/ */
void setRootItem (TreeViewItem* const newRootItem); void setRootItem (TreeViewItem* const newRootItem);
@@ -424,6 +425,12 @@ public:
*/ */
TreeViewItem* getRootItem() const throw() { return rootItem; } TreeViewItem* getRootItem() const throw() { return rootItem; }
/** This will remove and delete the current root item.
It's a convenient way of deleting the item and calling setRootItem (0).
*/
void deleteRootItem();
/** Changes whether the tree's root item is shown or not. /** Changes whether the tree's root item is shown or not.
If the root item is hidden, only its sub-items will be shown in the treeview - this If the root item is hidden, only its sub-items will be shown in the treeview - this


+ 1
- 1
src/juce_appframework/gui/components/filebrowser/juce_FileChooser.cpp View File

@@ -54,7 +54,7 @@ FileChooser::FileChooser (const String& chooserBoxTitle,
useNativeDialogBox = false; useNativeDialogBox = false;
#endif #endif
if (fileFilters.trim().isEmpty())
if (! fileFilters.containsNonWhitespaceChars())
filters = T("*"); filters = T("*");
} }


+ 3
- 0
src/juce_appframework/gui/components/special/juce_WebBrowserComponent.h View File

@@ -86,6 +86,9 @@ public:
*/ */
void goForward(); void goForward();
/** Refreshes the browser.
*/
void refresh();
//============================================================================== //==============================================================================
/** This callback is called when the browser is about to navigate /** This callback is called when the browser is about to navigate


+ 8
- 1
src/juce_core/cryptography/juce_MD5.h View File

@@ -66,7 +66,14 @@ public:
/** Creates a checksum for a block of binary data. */ /** Creates a checksum for a block of binary data. */
MD5 (const char* data, const int numBytes); MD5 (const char* data, const int numBytes);
/** Creates a checksum for a string. */
/** Creates a checksum for a string.
Note that this operates on the string as a block of unicode characters, so the
result you get will differ from the value you'd get if the string was treated
as a block of utf8 or ascii. Bear this in mind if you're comparing the result
of this method with a checksum created by a different framework, which may have
used a different encoding.
*/
MD5 (const String& text); MD5 (const String& text);
/** Creates a checksum for the input from a stream. /** Creates a checksum for the input from a stream.


+ 41
- 12
src/juce_core/io/files/juce_File.cpp View File

@@ -96,6 +96,12 @@ bool juce_findFileNext (void* handle, String& resultFile,
void juce_findFileClose (void* handle) throw(); void juce_findFileClose (void* handle) throw();
//==============================================================================
static const String juce_addTrailingSeparator (const String& path) throw()
{
return path.endsWithChar (File::separator) ? path
: path + File::separator;
}
//============================================================================== //==============================================================================
static const String parseAbsolutePath (String path) throw() static const String parseAbsolutePath (String path) throw()
@@ -498,10 +504,7 @@ const File File::getChildFile (String relativePath) const throw()
} }
} }
if (! path.endsWithChar (separator))
path += separator;
return File (path + relativePath);
return File (juce_addTrailingSeparator (path) + relativePath);
} }
} }
@@ -663,9 +666,7 @@ int File::findChildFiles (OwnedArray<File>& results,
// find child files or directories in this directory first.. // find child files or directories in this directory first..
if (isDirectory()) if (isDirectory())
{ {
String path (fullPath);
if (! path.endsWithChar (separator))
path += separator;
const String path (juce_addTrailingSeparator (fullPath));
String filename; String filename;
bool isDirectory, isHidden; bool isDirectory, isHidden;
@@ -760,6 +761,37 @@ int File::getNumberOfChildFiles (const int whatToLookFor,
return count; return count;
} }
bool File::containsSubDirectories() const throw()
{
bool result = false;
if (isDirectory())
{
String filename;
bool isDirectory, isHidden;
void* const handle = juce_findFileStart (juce_addTrailingSeparator (fullPath),
T("*"), filename,
&isDirectory, &isHidden, 0, 0, 0, 0);
if (handle != 0)
{
do
{
if (isDirectory)
{
result = true;
break;
}
} while (juce_findFileNext (handle, filename, &isDirectory, &isHidden, 0, 0, 0, 0));
juce_findFileClose (handle);
}
}
return result;
}
//============================================================================== //==============================================================================
const File File::getNonexistentChildFile (const String& prefix_, const File File::getNonexistentChildFile (const String& prefix_,
const String& suffix, const String& suffix,
@@ -1040,11 +1072,8 @@ const String File::getRelativePathFrom (const File& dir) const throw()
thisPath [len] = 0; thisPath [len] = 0;
} }
String dirPath ((dir.existsAsFile()) ? dir.getParentDirectory().getFullPathName()
: dir.fullPath);
if (! dirPath.endsWithChar (separator))
dirPath += separator;
String dirPath (juce_addTrailingSeparator ((dir.existsAsFile()) ? dir.getParentDirectory().getFullPathName()
: dir.fullPath));
const int len = jmin (thisPath.length(), dirPath.length()); const int len = jmin (thisPath.length(), dirPath.length());
int commonBitLength = 0; int commonBitLength = 0;


+ 5
- 0
src/juce_core/io/files/juce_File.h View File

@@ -548,6 +548,11 @@ public:
int getNumberOfChildFiles (const int whatToLookFor, int getNumberOfChildFiles (const int whatToLookFor,
const String& wildCardPattern = JUCE_T("*")) const throw(); const String& wildCardPattern = JUCE_T("*")) const throw();
/** Returns true if this file is a directory that contains one or more subdirectories.
@see isDirectory, findChildFiles
*/
bool File::containsSubDirectories() const throw();
//============================================================================== //==============================================================================
/** Creates a stream to read from this file. /** Creates a stream to read from this file.


+ 16
- 0
src/juce_core/text/juce_String.cpp View File

@@ -1483,11 +1483,15 @@ bool String::startsWithIgnoreCase (const tchar* const other) const throw()
bool String::startsWithChar (const tchar character) const throw() bool String::startsWithChar (const tchar character) const throw()
{ {
jassert (character != 0); // strings can't contain a null character!
return text->text[0] == character; return text->text[0] == character;
} }
bool String::endsWithChar (const tchar character) const throw() bool String::endsWithChar (const tchar character) const throw()
{ {
jassert (character != 0); // strings can't contain a null character!
return text->text[0] != 0 return text->text[0] != 0
&& text->text [length() - 1] == character; && text->text [length() - 1] == character;
} }
@@ -1838,6 +1842,18 @@ bool String::containsAnyOf (const tchar* const chars) const throw()
return false; return false;
} }
bool String::containsNonWhitespaceChars() const throw()
{
const tchar* t = text->text;
while (*t != 0)
if (! CharacterFunctions::isWhitespace (*t++))
return true;
return false;
}
//============================================================================== //==============================================================================
int String::getIntValue() const throw() int String::getIntValue() const throw()
{ {


+ 13
- 0
src/juce_core/text/juce_String.h View File

@@ -176,12 +176,16 @@ public:
/** Returns true if the string contains no characters. /** Returns true if the string contains no characters.
Note that there's also an isNotEmpty() method to help write readable code. Note that there's also an isNotEmpty() method to help write readable code.
@see containsNonWhitespaceChars()
*/ */
inline bool isEmpty() const throw() { return text->text[0] == 0; } inline bool isEmpty() const throw() { return text->text[0] == 0; }
/** Returns true if the string contains at least one character. /** Returns true if the string contains at least one character.
Note that there's also an isEmpty() method to help write readable code. Note that there's also an isEmpty() method to help write readable code.
@see containsNonWhitespaceChars()
*/ */
inline bool isNotEmpty() const throw() { return text->text[0] != 0; } inline bool isNotEmpty() const throw() { return text->text[0] != 0; }
@@ -341,6 +345,15 @@ public:
*/ */
bool containsOnly (const tchar* const charactersItMightContain) const throw(); bool containsOnly (const tchar* const charactersItMightContain) const throw();
/** Returns true if this string contains any non-whitespace characters.
This will return false if the string contains only whitespace characters, or
if it's empty.
It is equivalent to calling "myString.trim().isNotEmpty()".
*/
bool containsNonWhitespaceChars() const throw();
/** Returns true if the string matches this simple wildcard expression. /** Returns true if the string matches this simple wildcard expression.
So for example String ("abcdef").matchesWildcard ("*DEF", true) would return true. So for example String ("abcdef").matchesWildcard ("*DEF", true) would return true.


+ 1
- 1
src/juce_core/text/juce_StringArray.cpp View File

@@ -271,7 +271,7 @@ void StringArray::removeEmptyStrings (const bool removeWhitespaceStrings) throw(
if (removeWhitespaceStrings) if (removeWhitespaceStrings)
{ {
for (int i = size(); --i >= 0;) for (int i = size(); --i >= 0;)
if (((const String*) strings.getUnchecked(i))->trim().isEmpty())
if (! ((const String*) strings.getUnchecked(i))->containsNonWhitespaceChars())
remove (i); remove (i);
} }
else else


+ 8
- 3
src/juce_core/text/juce_XmlDocument.cpp View File

@@ -54,6 +54,7 @@ static bool isXmlIdentifierChar_Slow (const tchar c) throw()
//============================================================================== //==============================================================================
XmlDocument::XmlDocument (const String& documentText) throw() XmlDocument::XmlDocument (const String& documentText) throw()
: originalText (documentText), : originalText (documentText),
ignoreEmptyTextElements (true),
inputSource (0) inputSource (0)
{ {
} }
@@ -77,6 +78,11 @@ void XmlDocument::setInputSource (InputSource* const newSource) throw()
} }
} }
void XmlDocument::setEmptyTextElementsIgnored (const bool shouldBeIgnored) throw()
{
ignoreEmptyTextElements = shouldBeIgnored;
}
XmlElement* XmlDocument::getDocumentElement (const bool onlyReadOuterDocumentElement) XmlElement* XmlDocument::getDocumentElement (const bool onlyReadOuterDocumentElement)
{ {
String textToParse (originalText); String textToParse (originalText);
@@ -626,9 +632,8 @@ void XmlDocument::readChildElements (XmlElement* parent) throw()
} }
} }
textElementContent = textElementContent.trim();
if (textElementContent.isNotEmpty())
if (ignoreEmptyTextElements ? textElementContent.containsNonWhitespaceChars()
: textElementContent.isNotEmpty())
e->setText (textElementContent); e->setText (textElementContent);
} }
} }


+ 9
- 1
src/juce_core/text/juce_XmlDocument.h View File

@@ -122,6 +122,14 @@ public:
*/ */
void setInputSource (InputSource* const newSource) throw(); void setInputSource (InputSource* const newSource) throw();
/** Sets a flag to change the treatment of empty text elements.
If this is true (the default state), then any text elements that contain only
whitespace characters will be ingored during parsing. If you need to catch
whitespace-only text, then you should set this to false before calling the
getDocumentElement() method.
*/
void setEmptyTextElementsIgnored (const bool shouldBeIgnored) throw();
//============================================================================== //==============================================================================
juce_UseDebuggingNewOperator juce_UseDebuggingNewOperator
@@ -134,7 +142,7 @@ private:
bool identifierLookupTable [128]; bool identifierLookupTable [128];
String lastError, dtdText; String lastError, dtdText;
StringArray tokenisedDTD; StringArray tokenisedDTD;
bool needToLoadDTD;
bool needToLoadDTD, ignoreEmptyTextElements;
InputSource* inputSource; InputSource* inputSource;
void setLastError (const String& desc, const bool carryOn) throw(); void setLastError (const String& desc, const bool carryOn) throw();


+ 1
- 1
src/juce_core/text/juce_XmlElement.cpp View File

@@ -63,7 +63,7 @@ XmlElement::XmlElement (const String& tagName_) throw()
attributes (0) attributes (0)
{ {
// the tag name mustn't be empty, or it'll look like a text element! // the tag name mustn't be empty, or it'll look like a text element!
jassert (tagName_.trim().isNotEmpty())
jassert (tagName_.containsNonWhitespaceChars())
} }
XmlElement::XmlElement (int /*dummy*/) throw() XmlElement::XmlElement (int /*dummy*/) throw()


+ 18
- 21
src/juce_core/threads/juce_Thread.cpp View File

@@ -55,9 +55,10 @@ static CriticalSection runningThreadsLock;
//============================================================================== //==============================================================================
void Thread::threadEntryPoint (Thread* const thread) throw() void Thread::threadEntryPoint (Thread* const thread) throw()
{ {
runningThreadsLock.enter();
runningThreads.add (thread);
runningThreadsLock.exit();
{
const ScopedLock sl (runningThreadsLock);
runningThreads.add (thread);
}
JUCE_TRY JUCE_TRY
{ {
@@ -76,10 +77,12 @@ void Thread::threadEntryPoint (Thread* const thread) throw()
} }
JUCE_CATCH_ALL_ASSERT JUCE_CATCH_ALL_ASSERT
runningThreadsLock.enter();
jassert (runningThreads.contains (thread));
runningThreads.removeValue (thread);
runningThreadsLock.exit();
{
const ScopedLock sl (runningThreadsLock);
jassert (runningThreads.contains (thread));
runningThreads.removeValue (thread);
}
#if JUCE_WIN32 #if JUCE_WIN32
juce_CloseThreadHandle (thread->threadHandle_); juce_CloseThreadHandle (thread->threadHandle_);
@@ -250,34 +253,28 @@ int Thread::getNumRunningThreads() throw()
Thread* Thread::getCurrentThread() throw() Thread* Thread::getCurrentThread() throw()
{ {
const ThreadID thisId = getCurrentThreadId(); const ThreadID thisId = getCurrentThreadId();
Thread* result = 0;
runningThreadsLock.enter();
const ScopedLock sl (runningThreadsLock);
for (int i = runningThreads.size(); --i >= 0;) for (int i = runningThreads.size(); --i >= 0;)
{ {
Thread* const t = (Thread*) (runningThreads.getUnchecked(i)); Thread* const t = (Thread*) (runningThreads.getUnchecked(i));
if (t->threadId_ == thisId) if (t->threadId_ == thisId)
{
result = t;
break;
}
return t;
} }
runningThreadsLock.exit();
return result;
return 0;
} }
void Thread::stopAllThreads (const int timeOutMilliseconds) throw() void Thread::stopAllThreads (const int timeOutMilliseconds) throw()
{ {
runningThreadsLock.enter();
for (int i = runningThreads.size(); --i >= 0;)
((Thread*) runningThreads.getUnchecked(i))->signalThreadShouldExit();
{
const ScopedLock sl (runningThreadsLock);
runningThreadsLock.exit();
for (int i = runningThreads.size(); --i >= 0;)
((Thread*) runningThreads.getUnchecked(i))->signalThreadShouldExit();
}
for (;;) for (;;)
{ {


Loading…
Cancel
Save