| @@ -1035,6 +1035,7 @@ | |||
| 4007410FACA2F865FD8EF769 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_CharPointer_UTF8.h; path = ../../src/text/juce_CharPointer_UTF8.h; sourceTree = SOURCE_ROOT; }; | |||
| 663746215E9BA6C761172B85 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_CharPointer_UTF16.h; path = ../../src/text/juce_CharPointer_UTF16.h; sourceTree = SOURCE_ROOT; }; | |||
| C3FD9D93626F80A45F9B6DDE = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_CharPointer_UTF32.h; path = ../../src/text/juce_CharPointer_UTF32.h; sourceTree = SOURCE_ROOT; }; | |||
| 72F5ED2E8B945988C37EA9CF = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_CharPointer_ASCII.h; path = ../../src/text/juce_CharPointer_ASCII.h; sourceTree = SOURCE_ROOT; }; | |||
| 8273A206FB309671284959DD = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_Identifier.cpp; path = ../../src/text/juce_Identifier.cpp; sourceTree = SOURCE_ROOT; }; | |||
| BF888BC540B64D5C61E46A34 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_Identifier.h; path = ../../src/text/juce_Identifier.h; sourceTree = SOURCE_ROOT; }; | |||
| 4A97C8D2FF6454DDD3AF4BE5 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_LocalisedStrings.cpp; path = ../../src/text/juce_LocalisedStrings.cpp; sourceTree = SOURCE_ROOT; }; | |||
| @@ -1861,6 +1862,7 @@ | |||
| 4007410FACA2F865FD8EF769, | |||
| 663746215E9BA6C761172B85, | |||
| C3FD9D93626F80A45F9B6DDE, | |||
| 72F5ED2E8B945988C37EA9CF, | |||
| 8273A206FB309671284959DD, | |||
| BF888BC540B64D5C61E46A34, | |||
| 4A97C8D2FF6454DDD3AF4BE5, | |||
| @@ -959,6 +959,7 @@ | |||
| <File RelativePath="..\..\src\text\juce_CharPointer_UTF8.h"/> | |||
| <File RelativePath="..\..\src\text\juce_CharPointer_UTF16.h"/> | |||
| <File RelativePath="..\..\src\text\juce_CharPointer_UTF32.h"/> | |||
| <File RelativePath="..\..\src\text\juce_CharPointer_ASCII.h"/> | |||
| <File RelativePath="..\..\src\text\juce_Identifier.cpp"/> | |||
| <File RelativePath="..\..\src\text\juce_Identifier.h"/> | |||
| <File RelativePath="..\..\src\text\juce_LocalisedStrings.cpp"/> | |||
| @@ -959,6 +959,7 @@ | |||
| <File RelativePath="..\..\src\text\juce_CharPointer_UTF8.h"/> | |||
| <File RelativePath="..\..\src\text\juce_CharPointer_UTF16.h"/> | |||
| <File RelativePath="..\..\src\text\juce_CharPointer_UTF32.h"/> | |||
| <File RelativePath="..\..\src\text\juce_CharPointer_ASCII.h"/> | |||
| <File RelativePath="..\..\src\text\juce_Identifier.cpp"/> | |||
| <File RelativePath="..\..\src\text\juce_Identifier.h"/> | |||
| <File RelativePath="..\..\src\text\juce_LocalisedStrings.cpp"/> | |||
| @@ -961,6 +961,7 @@ | |||
| <File RelativePath="..\..\src\text\juce_CharPointer_UTF8.h"/> | |||
| <File RelativePath="..\..\src\text\juce_CharPointer_UTF16.h"/> | |||
| <File RelativePath="..\..\src\text\juce_CharPointer_UTF32.h"/> | |||
| <File RelativePath="..\..\src\text\juce_CharPointer_ASCII.h"/> | |||
| <File RelativePath="..\..\src\text\juce_Identifier.cpp"/> | |||
| <File RelativePath="..\..\src\text\juce_Identifier.h"/> | |||
| <File RelativePath="..\..\src\text\juce_LocalisedStrings.cpp"/> | |||
| @@ -777,6 +777,7 @@ | |||
| <ClInclude Include="..\..\src\text\juce_CharPointer_UTF8.h"/> | |||
| <ClInclude Include="..\..\src\text\juce_CharPointer_UTF16.h"/> | |||
| <ClInclude Include="..\..\src\text\juce_CharPointer_UTF32.h"/> | |||
| <ClInclude Include="..\..\src\text\juce_CharPointer_ASCII.h"/> | |||
| <ClInclude Include="..\..\src\text\juce_Identifier.h"/> | |||
| <ClInclude Include="..\..\src\text\juce_LocalisedStrings.h"/> | |||
| <ClInclude Include="..\..\src\text\juce_NewLine.h"/> | |||
| @@ -2265,6 +2265,9 @@ | |||
| <ClInclude Include="..\..\src\text\juce_CharPointer_UTF32.h"> | |||
| <Filter>Juce\Source\text</Filter> | |||
| </ClInclude> | |||
| <ClInclude Include="..\..\src\text\juce_CharPointer_ASCII.h"> | |||
| <Filter>Juce\Source\text</Filter> | |||
| </ClInclude> | |||
| <ClInclude Include="..\..\src\text\juce_Identifier.h"> | |||
| <Filter>Juce\Source\text</Filter> | |||
| </ClInclude> | |||
| @@ -1035,6 +1035,7 @@ | |||
| 4007410FACA2F865FD8EF769 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_CharPointer_UTF8.h; path = ../../src/text/juce_CharPointer_UTF8.h; sourceTree = SOURCE_ROOT; }; | |||
| 663746215E9BA6C761172B85 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_CharPointer_UTF16.h; path = ../../src/text/juce_CharPointer_UTF16.h; sourceTree = SOURCE_ROOT; }; | |||
| C3FD9D93626F80A45F9B6DDE = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_CharPointer_UTF32.h; path = ../../src/text/juce_CharPointer_UTF32.h; sourceTree = SOURCE_ROOT; }; | |||
| 72F5ED2E8B945988C37EA9CF = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_CharPointer_ASCII.h; path = ../../src/text/juce_CharPointer_ASCII.h; sourceTree = SOURCE_ROOT; }; | |||
| 8273A206FB309671284959DD = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_Identifier.cpp; path = ../../src/text/juce_Identifier.cpp; sourceTree = SOURCE_ROOT; }; | |||
| BF888BC540B64D5C61E46A34 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_Identifier.h; path = ../../src/text/juce_Identifier.h; sourceTree = SOURCE_ROOT; }; | |||
| 4A97C8D2FF6454DDD3AF4BE5 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_LocalisedStrings.cpp; path = ../../src/text/juce_LocalisedStrings.cpp; sourceTree = SOURCE_ROOT; }; | |||
| @@ -1861,6 +1862,7 @@ | |||
| 4007410FACA2F865FD8EF769, | |||
| 663746215E9BA6C761172B85, | |||
| C3FD9D93626F80A45F9B6DDE, | |||
| 72F5ED2E8B945988C37EA9CF, | |||
| 8273A206FB309671284959DD, | |||
| BF888BC540B64D5C61E46A34, | |||
| 4A97C8D2FF6454DDD3AF4BE5, | |||
| @@ -1477,6 +1477,8 @@ | |||
| file="src/text/juce_CharPointer_UTF16.h"/> | |||
| <FILE id="rE1hlF" name="juce_CharPointer_UTF32.h" compile="0" resource="0" | |||
| file="src/text/juce_CharPointer_UTF32.h"/> | |||
| <FILE id="rdfOEc" name="juce_CharPointer_ASCII.h" compile="0" resource="0" | |||
| file="src/text/juce_CharPointer_ASCII.h"/> | |||
| <FILE id="iGtCiI8" name="juce_Identifier.cpp" compile="1" resource="0" | |||
| file="src/text/juce_Identifier.cpp"/> | |||
| <FILE id="CPlhWqs" name="juce_Identifier.h" compile="0" resource="0" | |||
| @@ -62,12 +62,22 @@ void GroupInformationComponent::valueTreePropertyChanged (ValueTree& treeWhosePr | |||
| list.updateContent(); | |||
| } | |||
| void GroupInformationComponent::valueTreeChildrenChanged (ValueTree& treeWhoseChildHasChanged) | |||
| void GroupInformationComponent::valueTreeChildAdded (ValueTree&, ValueTree&) | |||
| { | |||
| list.updateContent(); | |||
| } | |||
| void GroupInformationComponent::valueTreeParentChanged (ValueTree& treeWhoseParentHasChanged) | |||
| void GroupInformationComponent::valueTreeChildRemoved (ValueTree&, ValueTree&) | |||
| { | |||
| list.updateContent(); | |||
| } | |||
| void GroupInformationComponent::valueTreeChildOrderChanged (ValueTree&) | |||
| { | |||
| list.updateContent(); | |||
| } | |||
| void GroupInformationComponent::valueTreeParentChanged (ValueTree&) | |||
| { | |||
| list.updateContent(); | |||
| } | |||
| @@ -49,7 +49,9 @@ public: | |||
| //============================================================================== | |||
| void valueTreePropertyChanged (ValueTree& treeWhosePropertyHasChanged, const Identifier& property); | |||
| void valueTreeChildrenChanged (ValueTree& treeWhoseChildHasChanged); | |||
| void valueTreeChildAdded (ValueTree& parentTree, ValueTree& childWhichHasBeenAdded); | |||
| void valueTreeChildRemoved (ValueTree& parentTree, ValueTree& childWhichHasBeenRemoved); | |||
| void valueTreeChildOrderChanged (ValueTree& parentTree); | |||
| void valueTreeParentChanged (ValueTree& treeWhoseParentHasChanged); | |||
| private: | |||
| @@ -217,7 +217,17 @@ void Project::valueTreePropertyChanged (ValueTree& tree, const Identifier& prope | |||
| changed(); | |||
| } | |||
| void Project::valueTreeChildrenChanged (ValueTree& tree) | |||
| void Project::valueTreeChildAdded (ValueTree& parentTree, ValueTree& childWhichHasBeenAdded) | |||
| { | |||
| changed(); | |||
| } | |||
| void Project::valueTreeChildRemoved (ValueTree& parentTree, ValueTree& childWhichHasBeenRemoved) | |||
| { | |||
| changed(); | |||
| } | |||
| void Project::valueTreeChildOrderChanged (ValueTree& parentTree) | |||
| { | |||
| changed(); | |||
| } | |||
| @@ -298,7 +298,9 @@ public: | |||
| //============================================================================== | |||
| void valueTreePropertyChanged (ValueTree& tree, const Identifier& property); | |||
| void valueTreeChildrenChanged (ValueTree& tree); | |||
| void valueTreeChildAdded (ValueTree& parentTree, ValueTree& childWhichHasBeenAdded); | |||
| void valueTreeChildRemoved (ValueTree& parentTree, ValueTree& childWhichHasBeenRemoved); | |||
| void valueTreeChildOrderChanged (ValueTree& parentTree); | |||
| void valueTreeParentChanged (ValueTree& tree); | |||
| //============================================================================== | |||
| @@ -365,20 +365,35 @@ void ProjectTreeViewBase::itemDropped (const String& sourceDescription, Componen | |||
| } | |||
| //============================================================================== | |||
| void ProjectTreeViewBase::treeChildrenChanged (const ValueTree& parentTree) | |||
| { | |||
| if (parentTree == item.getNode()) | |||
| { | |||
| refreshSubItems(); | |||
| treeHasChanged(); | |||
| setOpen (true); | |||
| } | |||
| } | |||
| void ProjectTreeViewBase::valueTreePropertyChanged (ValueTree& tree, const Identifier& property) | |||
| { | |||
| if (tree == item.getNode()) | |||
| repaintItem(); | |||
| } | |||
| void ProjectTreeViewBase::valueTreeChildrenChanged (ValueTree& tree) | |||
| void ProjectTreeViewBase::valueTreeChildAdded (ValueTree& parentTree, ValueTree& childWhichHasBeenAdded) | |||
| { | |||
| if (tree == item.getNode()) | |||
| { | |||
| refreshSubItems(); | |||
| treeHasChanged(); | |||
| setOpen (true); | |||
| } | |||
| treeChildrenChanged (parentTree); | |||
| } | |||
| void ProjectTreeViewBase::valueTreeChildRemoved (ValueTree& parentTree, ValueTree& childWhichHasBeenRemoved) | |||
| { | |||
| treeChildrenChanged (parentTree); | |||
| } | |||
| void ProjectTreeViewBase::valueTreeChildOrderChanged (ValueTree& parentTree) | |||
| { | |||
| treeChildrenChanged (parentTree); | |||
| } | |||
| void ProjectTreeViewBase::valueTreeParentChanged (ValueTree& tree) | |||
| @@ -70,7 +70,9 @@ public: | |||
| //============================================================================== | |||
| void valueTreePropertyChanged (ValueTree& tree, const Identifier& property); | |||
| void valueTreeChildrenChanged (ValueTree& tree); | |||
| void valueTreeChildAdded (ValueTree& parentTree, ValueTree& childWhichHasBeenAdded); | |||
| void valueTreeChildRemoved (ValueTree& parentTree, ValueTree& childWhichHasBeenRemoved); | |||
| void valueTreeChildOrderChanged (ValueTree& parentTree); | |||
| void valueTreeParentChanged (ValueTree& tree); | |||
| //============================================================================== | |||
| @@ -99,6 +101,7 @@ protected: | |||
| bool isFileMissing; | |||
| //============================================================================== | |||
| void treeChildrenChanged (const ValueTree& parentTree); | |||
| virtual void addSubItems(); | |||
| virtual ProjectTreeViewBase* createSubItem (const Project::Item& node) = 0; | |||
| const Drawable* getIcon() const { return item.getIcon(); } | |||
| @@ -11580,8 +11580,41 @@ String::String (const String& stringToCopy, const size_t charsToAllocate) | |||
| } | |||
| String::String (const char* const t) | |||
| : text (StringHolder::createFromCharPointer (CharPointer_UTF8 (t))) | |||
| { | |||
| : text (StringHolder::createFromCharPointer (CharPointer_ASCII (t))) | |||
| { | |||
| /* If you get an assertion here, then you're trying to create a string from 8-bit data | |||
| that contains values greater than 127. These can NOT be correctly converted to unicode | |||
| because there's no way for the String class to know what encoding was used to | |||
| create them. The source data could be UTF-8, ASCII or one of many local code-pages. | |||
| To get around this problem, you must be more explicit when you pass an ambiguous 8-bit | |||
| string to the String class - so for example if your source data is actually UTF-8, | |||
| you'd call String (CharPointer_UTF8 ("my utf8 string..")), and it would be able to | |||
| correctly convert the multi-byte characters to unicode. It's *highly* recommended that | |||
| you use UTF-8 with escape characters in your source code to represent extended characters, | |||
| because there's no other way to represent these strings in a way that isn't dependent on | |||
| the compiler, source code editor and platform. | |||
| */ | |||
| jassert (CharPointer_ASCII::isValidString (t, std::numeric_limits<int>::max())); | |||
| } | |||
| String::String (const char* const t, const size_t maxChars) | |||
| : text (StringHolder::createFromCharPointer (CharPointer_ASCII (t), maxChars)) | |||
| { | |||
| /* If you get an assertion here, then you're trying to create a string from 8-bit data | |||
| that contains values greater than 127. These can NOT be correctly converted to unicode | |||
| because there's no way for the String class to know what encoding was used to | |||
| create them. The source data could be UTF-8, ASCII or one of many local code-pages. | |||
| To get around this problem, you must be more explicit when you pass an ambiguous 8-bit | |||
| string to the String class - so for example if your source data is actually UTF-8, | |||
| you'd call String (CharPointer_UTF8 ("my utf8 string..")), and it would be able to | |||
| correctly convert the multi-byte characters to unicode. It's *highly* recommended that | |||
| you use UTF-8 with escape characters in your source code to represent extended characters, | |||
| because there's no other way to represent these strings in a way that isn't dependent on | |||
| the compiler, source code editor and platform. | |||
| */ | |||
| jassert (CharPointer_ASCII::isValidString (t, (int) maxChars)); | |||
| } | |||
| String::String (const juce_wchar* const t) | |||
| @@ -11589,6 +11622,11 @@ String::String (const juce_wchar* const t) | |||
| { | |||
| } | |||
| String::String (const juce_wchar* const t, const size_t maxChars) | |||
| : text (StringHolder::createFromCharPointer (CharPointer_UTF32 (t), maxChars)) | |||
| { | |||
| } | |||
| String::String (const CharPointer_UTF8& t) | |||
| : text (StringHolder::createFromCharPointer (t)) | |||
| { | |||
| @@ -11609,6 +11647,11 @@ String::String (const CharPointer_UTF32& t, const size_t maxChars) | |||
| { | |||
| } | |||
| String::String (const CharPointer_ASCII& t) | |||
| : text (StringHolder::createFromCharPointer (t)) | |||
| { | |||
| } | |||
| #if JUCE_WINDOWS | |||
| String::String (const wchar_t* const t) | |||
| : text (StringHolder::createFromCharPointer (CharPointer_UTF16 (t))) | |||
| @@ -11621,16 +11664,6 @@ String::String (const wchar_t* const t, size_t maxChars) | |||
| } | |||
| #endif | |||
| String::String (const char* const t, const size_t maxChars) | |||
| : text (StringHolder::createFromCharPointer (CharPointer_UTF8 (t), maxChars)) | |||
| { | |||
| } | |||
| String::String (const juce_wchar* const t, const size_t maxChars) | |||
| : text (StringHolder::createFromCharPointer (CharPointer_UTF32 (t), maxChars)) | |||
| { | |||
| } | |||
| const String String::charToString (const juce_wchar character) | |||
| { | |||
| String result (Preallocation (1)); | |||
| @@ -12004,7 +12037,7 @@ String& String::operator+= (const juce_wchar ch) | |||
| } | |||
| #if JUCE_WINDOWS | |||
| String& String::operator+= (wchar_t ch) | |||
| String& String::operator+= (const wchar_t ch) | |||
| { | |||
| return operator+= ((juce_wchar) ch); | |||
| } | |||
| @@ -14551,7 +14584,7 @@ XmlElement* XmlDocument::getDocumentElement (const bool onlyReadOuterDocumentEle | |||
| } | |||
| } | |||
| input = static_cast <const juce_wchar*> (textToParse); | |||
| input = textToParse.getCharPointer(); | |||
| lastError = String::empty; | |||
| errorOccurred = false; | |||
| outOfData = false; | |||
| @@ -14662,7 +14695,7 @@ void XmlDocument::skipHeader() | |||
| return; | |||
| input += docTypeIndex + 9; | |||
| const CharPointer_UTF32 docType (input); | |||
| const String::CharPointerType docType (input); | |||
| int n = 1; | |||
| @@ -14751,7 +14784,7 @@ void XmlDocument::readQuotedString (String& result) | |||
| else | |||
| { | |||
| --input; | |||
| const CharPointer_UTF32 start (input); | |||
| const String::CharPointerType start (input); | |||
| for (;;) | |||
| { | |||
| @@ -14759,14 +14792,14 @@ void XmlDocument::readQuotedString (String& result) | |||
| if (character == quote) | |||
| { | |||
| result.append (start.getAddress(), (int) (input.getAddress() - start.getAddress())); | |||
| result.appendCharPointer (start, (int) (input.getAddress() - start.getAddress())); | |||
| ++input; | |||
| return; | |||
| } | |||
| else if (character == '&') | |||
| { | |||
| result.append (start.getAddress(), (int) (input.getAddress() - start.getAddress())); | |||
| result.appendCharPointer (start, (int) (input.getAddress() - start.getAddress())); | |||
| break; | |||
| } | |||
| else if (character == 0) | |||
| @@ -14846,7 +14879,7 @@ XmlElement* XmlDocument::readNextElement (const bool alsoParseSubElements) | |||
| if (attNameLen > 0) | |||
| { | |||
| const CharPointer_UTF32 attNameStart (input); | |||
| const String::CharPointerType attNameStart (input); | |||
| input += attNameLen; | |||
| skipNextWhiteSpace(); | |||
| @@ -14889,7 +14922,7 @@ void XmlDocument::readChildElements (XmlElement* parent) | |||
| for (;;) | |||
| { | |||
| const CharPointer_UTF32 preWhitespaceInput (input); | |||
| const String::CharPointerType preWhitespaceInput (input); | |||
| skipNextWhiteSpace(); | |||
| if (outOfData) | |||
| @@ -14920,7 +14953,7 @@ void XmlDocument::readChildElements (XmlElement* parent) | |||
| && input[8] == '[') | |||
| { | |||
| input += 9; | |||
| const CharPointer_UTF32 inputStart (input); | |||
| const String::CharPointerType inputStart (input); | |||
| int len = 0; | |||
| @@ -14983,10 +15016,10 @@ void XmlDocument::readChildElements (XmlElement* parent) | |||
| if (entity.startsWithChar ('<') && entity [1] != 0) | |||
| { | |||
| const CharPointer_UTF32 oldInput (input); | |||
| const String::CharPointerType oldInput (input); | |||
| const bool oldOutOfData = outOfData; | |||
| input = static_cast <const juce_wchar*> (entity); | |||
| input = entity.getCharPointer(); | |||
| outOfData = false; | |||
| for (;;) | |||
| @@ -15009,7 +15042,7 @@ void XmlDocument::readChildElements (XmlElement* parent) | |||
| } | |||
| else | |||
| { | |||
| const CharPointer_UTF32 start (input); | |||
| const String::CharPointerType start (input); | |||
| int len = 0; | |||
| for (;;) | |||
| @@ -15128,7 +15161,7 @@ void XmlDocument::readEntity (String& result) | |||
| } | |||
| else | |||
| { | |||
| const CharPointer_UTF32 entityNameStart (input); | |||
| const String::CharPointerType entityNameStart (input); | |||
| const int closingSemiColon = input.indexOf ((juce_wchar) ';'); | |||
| if (closingSemiColon < 0) | |||
| @@ -17525,24 +17558,68 @@ void ValueTree::SharedObject::sendPropertyChangeMessage (const Identifier& prope | |||
| } | |||
| } | |||
| void ValueTree::SharedObject::sendChildChangeMessage (ValueTree& tree) | |||
| void ValueTree::SharedObject::sendChildAddedMessage (ValueTree& tree, ValueTree& child) | |||
| { | |||
| for (int i = valueTreesWithListeners.size(); --i >= 0;) | |||
| { | |||
| ValueTree* const v = valueTreesWithListeners[i]; | |||
| if (v != 0) | |||
| v->listeners.call (&ValueTree::Listener::valueTreeChildrenChanged, tree); | |||
| v->listeners.call (&ValueTree::Listener::valueTreeChildAdded, tree, child); | |||
| } | |||
| } | |||
| void ValueTree::SharedObject::sendChildChangeMessage() | |||
| void ValueTree::SharedObject::sendChildAddedMessage (ValueTree child) | |||
| { | |||
| ValueTree tree (this); | |||
| ValueTree::SharedObject* t = this; | |||
| while (t != 0) | |||
| { | |||
| t->sendChildChangeMessage (tree); | |||
| t->sendChildAddedMessage (tree, child); | |||
| t = t->parent; | |||
| } | |||
| } | |||
| void ValueTree::SharedObject::sendChildRemovedMessage (ValueTree& tree, ValueTree& child) | |||
| { | |||
| for (int i = valueTreesWithListeners.size(); --i >= 0;) | |||
| { | |||
| ValueTree* const v = valueTreesWithListeners[i]; | |||
| if (v != 0) | |||
| v->listeners.call (&ValueTree::Listener::valueTreeChildRemoved, tree, child); | |||
| } | |||
| } | |||
| void ValueTree::SharedObject::sendChildRemovedMessage (ValueTree child) | |||
| { | |||
| ValueTree tree (this); | |||
| ValueTree::SharedObject* t = this; | |||
| while (t != 0) | |||
| { | |||
| t->sendChildRemovedMessage (tree, child); | |||
| t = t->parent; | |||
| } | |||
| } | |||
| void ValueTree::SharedObject::sendChildOrderChangedMessage (ValueTree& tree) | |||
| { | |||
| for (int i = valueTreesWithListeners.size(); --i >= 0;) | |||
| { | |||
| ValueTree* const v = valueTreesWithListeners[i]; | |||
| if (v != 0) | |||
| v->listeners.call (&ValueTree::Listener::valueTreeChildOrderChanged, tree); | |||
| } | |||
| } | |||
| void ValueTree::SharedObject::sendChildOrderChangedMessage() | |||
| { | |||
| ValueTree tree (this); | |||
| ValueTree::SharedObject* t = this; | |||
| while (t != 0) | |||
| { | |||
| t->sendChildOrderChangedMessage (tree); | |||
| t = t->parent; | |||
| } | |||
| } | |||
| @@ -17708,7 +17785,7 @@ void ValueTree::SharedObject::addChild (SharedObject* child, int index, UndoMana | |||
| { | |||
| children.insert (index, child); | |||
| child->parent = this; | |||
| sendChildChangeMessage(); | |||
| sendChildAddedMessage (ValueTree (child)); | |||
| child->sendParentChangeMessage(); | |||
| } | |||
| else | |||
| @@ -17738,7 +17815,7 @@ void ValueTree::SharedObject::removeChild (const int childIndex, UndoManager* co | |||
| { | |||
| children.remove (childIndex); | |||
| child->parent = 0; | |||
| sendChildChangeMessage(); | |||
| sendChildRemovedMessage (ValueTree (child)); | |||
| child->sendParentChangeMessage(); | |||
| } | |||
| else | |||
| @@ -17765,7 +17842,7 @@ void ValueTree::SharedObject::moveChild (int currentIndex, int newIndex, UndoMan | |||
| if (undoManager == 0) | |||
| { | |||
| children.move (currentIndex, newIndex); | |||
| sendChildChangeMessage(); | |||
| sendChildOrderChangedMessage(); | |||
| } | |||
| else | |||
| { | |||
| @@ -17784,16 +17861,19 @@ void ValueTree::SharedObject::reorderChildren (const ReferenceCountedArray <Shar | |||
| if (undoManager == 0) | |||
| { | |||
| children = newOrder; | |||
| sendChildChangeMessage(); | |||
| sendChildOrderChangedMessage(); | |||
| } | |||
| else | |||
| { | |||
| for (int i = 0; i < children.size(); ++i) | |||
| { | |||
| if (children.getUnchecked(i) != newOrder.getUnchecked(i)) | |||
| const SharedObjectPtr child (newOrder.getUnchecked(i)); | |||
| if (children.getUnchecked(i) != child) | |||
| { | |||
| jassert (children.contains (newOrder.getUnchecked(i))); | |||
| moveChild (children.indexOf (newOrder.getUnchecked(i)), i, undoManager); | |||
| const int oldIndex = children.indexOf (child); | |||
| jassert (oldIndex >= 0); | |||
| moveChild (oldIndex, i, undoManager); | |||
| } | |||
| } | |||
| } | |||
| @@ -17990,8 +18070,10 @@ public: | |||
| sendChangeMessage (false); | |||
| } | |||
| void valueTreeChildrenChanged (ValueTree&) {} | |||
| void valueTreeParentChanged (ValueTree&) {} | |||
| void valueTreeChildAdded (ValueTree&, ValueTree&) {} | |||
| void valueTreeChildRemoved (ValueTree&, ValueTree&) {} | |||
| void valueTreeChildOrderChanged (ValueTree&) {} | |||
| void valueTreeParentChanged (ValueTree&) {} | |||
| private: | |||
| ValueTree tree; | |||
| @@ -23055,8 +23137,7 @@ public: | |||
| : AudioFormatWriter (out, TRANS (wavFormatName), sampleRate_, numChannels_, bits), | |||
| lengthInSamples (0), | |||
| bytesWritten (0), | |||
| writeFailed (false), | |||
| isRF64 (false) | |||
| writeFailed (false) | |||
| { | |||
| using namespace WavFileHelpers; | |||
| @@ -23123,7 +23204,7 @@ private: | |||
| MemoryBlock tempBlock, bwavChunk, smplChunk; | |||
| uint64 lengthInSamples, bytesWritten; | |||
| int64 headerPosition; | |||
| bool writeFailed, isRF64; | |||
| bool writeFailed; | |||
| static int getChannelMask (const int numChannels) throw() | |||
| { | |||
| @@ -23152,14 +23233,15 @@ private: | |||
| const int bytesPerFrame = numChannels * bitsPerSample / 8; | |||
| int64 audioDataSize = bytesPerFrame * lengthInSamples; | |||
| int64 riffChunkSize = 4 /* 'WAVE' */ + 8 + 40 /* WAVEFORMATEX */ | |||
| const bool isRF64 = (bytesWritten >= literal64bit (0x100000000)); | |||
| int64 riffChunkSize = 4 /* 'RIFF' */ + 8 + 40 /* WAVEFORMATEX */ | |||
| + 8 + audioDataSize + (audioDataSize & 1) | |||
| + (bwavChunk.getSize() > 0 ? (8 + bwavChunk.getSize()) : 0) | |||
| + (smplChunk.getSize() > 0 ? (8 + smplChunk.getSize()) : 0) | |||
| + (8 + 28); // (JUNK chunk) | |||
| + (8 + 28); // (ds64 chunk) | |||
| riffChunkSize += (riffChunkSize & 0x1); | |||
| isRF64 = (riffChunkSize > 0xffffffff); | |||
| output->writeInt (chunkName (isRF64 ? "RF64" : "RIFF")); | |||
| output->writeInt (isRF64 ? -1 : (int) riffChunkSize); | |||
| @@ -23167,10 +23249,9 @@ private: | |||
| if (! isRF64) | |||
| { | |||
| // write Junk chunk | |||
| output->writeInt (chunkName ("JUNK")); | |||
| output->writeInt (28); | |||
| output->writeRepeatedByte (0, 28); | |||
| output->writeInt (28 + 24); | |||
| output->writeRepeatedByte (0, 28 /* ds64 */ + 24 /* extra waveformatex */); | |||
| } | |||
| else | |||
| { | |||
| @@ -23183,29 +23264,44 @@ private: | |||
| } | |||
| output->writeInt (chunkName ("fmt ")); | |||
| output->writeInt (40); // WAVEFORMATEX chunk size | |||
| output->writeShort ((short) (uint16) 0xfffe); // WAVE_FORMAT_EXTENSIBLE | |||
| if (isRF64) | |||
| { | |||
| output->writeInt (40); // chunk size | |||
| output->writeShort ((short) (uint16) 0xfffe); // WAVE_FORMAT_EXTENSIBLE | |||
| } | |||
| else | |||
| { | |||
| output->writeInt (16); // chunk size | |||
| output->writeShort (bitsPerSample < 32 ? (short) 1 /*WAVE_FORMAT_PCM*/ | |||
| : (short) 3 /*WAVE_FORMAT_IEEE_FLOAT*/); | |||
| } | |||
| output->writeShort ((short) numChannels); | |||
| output->writeInt ((int) sampleRate); | |||
| output->writeInt ((int) (bytesPerFrame * sampleRate)); // nAvgBytesPerSec | |||
| output->writeShort ((short) bytesPerFrame); // nBlockAlign | |||
| output->writeShort ((short) bitsPerSample); // wBitsPerSample | |||
| output->writeShort (22); // cbSize (size of the extension) | |||
| output->writeShort ((short) bitsPerSample); // wValidBitsPerSample | |||
| output->writeInt (getChannelMask (numChannels)); | |||
| const ExtensibleWavSubFormat pcmFormat | |||
| = { 0x00000001, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } }; | |||
| if (isRF64) | |||
| { | |||
| output->writeShort (22); // cbSize (size of the extension) | |||
| output->writeShort ((short) bitsPerSample); // wValidBitsPerSample | |||
| output->writeInt (getChannelMask (numChannels)); | |||
| const ExtensibleWavSubFormat pcmFormat | |||
| = { 0x00000001, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } }; | |||
| const ExtensibleWavSubFormat IEEEFloatFormat | |||
| = { 0x00000003, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } }; | |||
| const ExtensibleWavSubFormat IEEEFloatFormat | |||
| = { 0x00000003, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } }; | |||
| const ExtensibleWavSubFormat& subFormat = bitsPerSample < 32 ? pcmFormat : IEEEFloatFormat; | |||
| const ExtensibleWavSubFormat& subFormat = bitsPerSample < 32 ? pcmFormat : IEEEFloatFormat; | |||
| output->writeInt ((int) subFormat.data1); | |||
| output->writeShort ((short) subFormat.data2); | |||
| output->writeShort ((short) subFormat.data3); | |||
| output->write (subFormat.data4, sizeof (subFormat.data4)); | |||
| output->writeInt ((int) subFormat.data1); | |||
| output->writeShort ((short) subFormat.data2); | |||
| output->writeShort ((short) subFormat.data3); | |||
| output->write (subFormat.data4, sizeof (subFormat.data4)); | |||
| } | |||
| if (bwavChunk.getSize() > 0) | |||
| { | |||
| @@ -43750,6 +43846,7 @@ void DrawableButton::buttonStateChanged() | |||
| if (currentImage != 0) | |||
| { | |||
| currentImage->setInterceptsMouseClicks (false, false); | |||
| addAndMakeVisible (currentImage); | |||
| DrawableButton::resized(); | |||
| } | |||
| @@ -54423,6 +54520,11 @@ void TextEditor::coalesceSimilarSections() | |||
| } | |||
| } | |||
| void TextEditor::Listener::textEditorTextChanged (TextEditor&) {} | |||
| void TextEditor::Listener::textEditorReturnKeyPressed (TextEditor&) {} | |||
| void TextEditor::Listener::textEditorEscapeKeyPressed (TextEditor&) {} | |||
| void TextEditor::Listener::textEditorFocusLost (TextEditor&) {} | |||
| END_JUCE_NAMESPACE | |||
| /*** End of inlined file: juce_TextEditor.cpp ***/ | |||
| @@ -61303,7 +61405,17 @@ void ComponentBuilder::valueTreePropertyChanged (ValueTree& tree, const Identifi | |||
| ComponentBuilderHelpers::updateComponent (*this, tree); | |||
| } | |||
| void ComponentBuilder::valueTreeChildrenChanged (ValueTree& tree) | |||
| void ComponentBuilder::valueTreeChildAdded (ValueTree& tree, ValueTree&) | |||
| { | |||
| ComponentBuilderHelpers::updateComponent (*this, tree); | |||
| } | |||
| void ComponentBuilder::valueTreeChildRemoved (ValueTree& tree, ValueTree&) | |||
| { | |||
| ComponentBuilderHelpers::updateComponent (*this, tree); | |||
| } | |||
| void ComponentBuilder::valueTreeChildOrderChanged (ValueTree& tree) | |||
| { | |||
| ComponentBuilderHelpers::updateComponent (*this, tree); | |||
| } | |||
| @@ -68738,17 +68850,21 @@ class PopupMenu::ItemComponent : public Component | |||
| { | |||
| public: | |||
| ItemComponent (const PopupMenu::Item& itemInfo_, int standardItemHeight) | |||
| ItemComponent (const PopupMenu::Item& itemInfo_, int standardItemHeight, Component* const parent) | |||
| : itemInfo (itemInfo_), | |||
| isHighlighted (false) | |||
| { | |||
| if (itemInfo.customComp != 0) | |||
| addAndMakeVisible (itemInfo.customComp); | |||
| parent->addAndMakeVisible (this); | |||
| int itemW = 80; | |||
| int itemH = 16; | |||
| getIdealSize (itemW, itemH, standardItemHeight); | |||
| setSize (itemW, jlimit (2, 600, itemH)); | |||
| addMouseListener (parent, false); | |||
| } | |||
| ~ItemComponent() | |||
| @@ -68877,12 +68993,7 @@ public: | |||
| setOpaque (getLookAndFeel().findColour (PopupMenu::backgroundColourId).isOpaque() || ! Desktop::canUseSemiTransparentWindows()); | |||
| for (int i = 0; i < menu.items.size(); ++i) | |||
| { | |||
| PopupMenu::ItemComponent* const itemComp = new PopupMenu::ItemComponent (*menu.items.getUnchecked(i), standardItemHeight); | |||
| items.add (itemComp); | |||
| addAndMakeVisible (itemComp); | |||
| itemComp->addMouseListener (this, false); | |||
| } | |||
| items.add (new PopupMenu::ItemComponent (*menu.items.getUnchecked(i), standardItemHeight, this)); | |||
| calculateWindowPos (target, alignToRectangle); | |||
| setTopLeftPosition (windowPos.getX(), windowPos.getY()); | |||
| @@ -86175,6 +86286,12 @@ const Rectangle<float> DrawableShape::getDrawableBounds() const | |||
| bool DrawableShape::hitTest (int x, int y) | |||
| { | |||
| bool allowsClicksOnThisComponent, allowsClicksOnChildComponents; | |||
| getInterceptsMouseClicks (allowsClicksOnThisComponent, allowsClicksOnChildComponents); | |||
| if (! allowsClicksOnThisComponent) | |||
| return false; | |||
| const float globalX = (float) (x - originRelativeToComponent.getX()); | |||
| const float globalY = (float) (y - originRelativeToComponent.getY()); | |||
| @@ -244209,7 +244326,7 @@ void SystemClipboard::copyTextToClipboard (const String& text) | |||
| { | |||
| if (EmptyClipboard() != 0) | |||
| { | |||
| const int bytesNeeded = CharPointer_UTF16::getBytesRequiredFor (text.getCharPointer()); | |||
| const int bytesNeeded = CharPointer_UTF16::getBytesRequiredFor (text.getCharPointer()) + 4; | |||
| if (bytesNeeded > 0) | |||
| { | |||
| @@ -263990,7 +264107,7 @@ namespace FileHelpers | |||
| FSRef ref; | |||
| LSItemInfoRecord info; | |||
| return FSPathMakeRefWithOptions ((const UInt8*) path.toUTF8(), kFSPathMakeRefDoNotFollowLeafSymlink, &ref, 0) == noErr | |||
| return FSPathMakeRefWithOptions ((const UInt8*) path.toUTF8().getAddress(), kFSPathMakeRefDoNotFollowLeafSymlink, &ref, 0) == noErr | |||
| && LSCopyItemInfoForRef (&ref, kLSRequestBasicFlagsOnly, &info) == noErr | |||
| && (info.flags & kLSItemInfoIsInvisible) != 0; | |||
| #endif | |||
| @@ -73,7 +73,7 @@ namespace JuceDummyNamespace {} | |||
| */ | |||
| #define JUCE_MAJOR_VERSION 1 | |||
| #define JUCE_MINOR_VERSION 53 | |||
| #define JUCE_BUILDNUMBER 21 | |||
| #define JUCE_BUILDNUMBER 23 | |||
| /** Current Juce version number. | |||
| @@ -2496,9 +2496,9 @@ public: | |||
| if (byte >= 0) | |||
| return byte; | |||
| juce_wchar n = byte; | |||
| juce_wchar mask = 0x7f; | |||
| juce_wchar bit = 0x40; | |||
| uint32 n = (uint32) (uint8) byte; | |||
| uint32 mask = 0x7f; | |||
| uint32 bit = 0x40; | |||
| size_t numExtraValues = 0; | |||
| while ((n & bit) != 0 && bit > 0x10) | |||
| @@ -2521,7 +2521,7 @@ public: | |||
| n |= (nextByte & 0x3f); | |||
| } | |||
| return n; | |||
| return (juce_wchar) n; | |||
| } | |||
| /** Moves this pointer along to the next character in the string. */ | |||
| @@ -2881,6 +2881,51 @@ public: | |||
| /** Returns the first non-whitespace character in the string. */ | |||
| CharPointer_UTF8 findEndOfWhitespace() const throw() { return CharacterFunctions::findEndOfWhitespace (*this); } | |||
| /** Returns true if the given unicode character can be represented in this encoding. */ | |||
| static bool canRepresent (juce_wchar character) throw() | |||
| { | |||
| return ((unsigned int) character) < (unsigned int) 0x10ffff; | |||
| } | |||
| /** Returns true if this data contains a valid string in this encoding. */ | |||
| static bool isValidString (const CharType* dataToTest, int maxBytesToRead) | |||
| { | |||
| while (--maxBytesToRead >= 0 && *dataToTest != 0) | |||
| { | |||
| const char byte = *dataToTest; | |||
| if (byte < 0) | |||
| { | |||
| uint32 n = (uint32) (uint8) byte; | |||
| uint32 mask = 0x7f; | |||
| uint32 bit = 0x40; | |||
| int numExtraValues = 0; | |||
| while ((n & bit) != 0) | |||
| { | |||
| if (bit <= 0x10) | |||
| return false; | |||
| mask >>= 1; | |||
| ++numExtraValues; | |||
| bit >>= 1; | |||
| } | |||
| n &= mask; | |||
| while (--numExtraValues >= 0) | |||
| { | |||
| const uint32 nextByte = (uint32) (uint8) *dataToTest++; | |||
| if ((nextByte & 0xc0) != 0x80) | |||
| return false; | |||
| } | |||
| } | |||
| } | |||
| return true; | |||
| } | |||
| /** These values are the byte-order-mark (BOM) values for a UTF-8 stream. */ | |||
| enum | |||
| { | |||
| @@ -3268,6 +3313,43 @@ public: | |||
| /** Returns the first non-whitespace character in the string. */ | |||
| CharPointer_UTF16 findEndOfWhitespace() const throw() { return CharacterFunctions::findEndOfWhitespace (*this); } | |||
| /** Returns true if the given unicode character can be represented in this encoding. */ | |||
| static bool canRepresent (juce_wchar character) throw() | |||
| { | |||
| return ((unsigned int) character) < (unsigned int) 0x10ffff | |||
| && (((unsigned int) character) < 0xd800 || ((unsigned int) character) > 0xdfff); | |||
| } | |||
| /** Returns true if this data contains a valid string in this encoding. */ | |||
| static bool isValidString (const CharType* dataToTest, int maxBytesToRead) | |||
| { | |||
| maxBytesToRead /= sizeof (CharType); | |||
| while (--maxBytesToRead >= 0 && *dataToTest != 0) | |||
| { | |||
| const uint32 n = (uint32) (uint16) *dataToTest++; | |||
| if (n >= 0xd800) | |||
| { | |||
| if (n > 0x10ffff) | |||
| return false; | |||
| if (n <= 0xdfff) | |||
| { | |||
| if (n > 0xdc00) | |||
| return false; | |||
| const uint32 nextChar = (uint32) (uint16) *dataToTest++; | |||
| if (nextChar < 0xdc00 || nextChar > 0xdfff) | |||
| return false; | |||
| } | |||
| } | |||
| } | |||
| return true; | |||
| } | |||
| /** These values are the byte-order-mark (BOM) values for a UTF-16 stream. */ | |||
| enum | |||
| { | |||
| @@ -3377,7 +3459,7 @@ public: | |||
| CharPointer_UTF32 operator++ (int) throw() | |||
| { | |||
| CharPointer_UTF32 temp (*this); | |||
| ++*this; | |||
| ++data; | |||
| return temp; | |||
| } | |||
| @@ -3612,6 +3694,25 @@ public: | |||
| /** Returns the first non-whitespace character in the string. */ | |||
| CharPointer_UTF32 findEndOfWhitespace() const throw() { return CharacterFunctions::findEndOfWhitespace (*this); } | |||
| /** Returns true if the given unicode character can be represented in this encoding. */ | |||
| static bool canRepresent (juce_wchar character) throw() | |||
| { | |||
| return ((unsigned int) character) < (unsigned int) 0x10ffff; | |||
| } | |||
| /** Returns true if this data contains a valid string in this encoding. */ | |||
| static bool isValidString (const CharType* dataToTest, int maxBytesToRead) | |||
| { | |||
| maxBytesToRead /= sizeof (CharType); | |||
| while (--maxBytesToRead >= 0 && *dataToTest != 0) | |||
| if (! canRepresent (*dataToTest++)) | |||
| return false; | |||
| return true; | |||
| } | |||
| /** Atomically swaps this pointer for a new value, returning the previous value. */ | |||
| CharPointer_UTF32 atomicSwap (const CharPointer_UTF32& newValue) | |||
| { | |||
| return CharPointer_UTF32 (reinterpret_cast <Atomic<CharType*>&> (data).exchange (newValue.data)); | |||
| @@ -3624,6 +3725,364 @@ private: | |||
| #endif // __JUCE_CHARPOINTER_UTF32_JUCEHEADER__ | |||
| /*** End of inlined file: juce_CharPointer_UTF32.h ***/ | |||
| /*** Start of inlined file: juce_CharPointer_ASCII.h ***/ | |||
| #ifndef __JUCE_CHARPOINTER_ASCII_JUCEHEADER__ | |||
| #define __JUCE_CHARPOINTER_ASCII_JUCEHEADER__ | |||
| /** | |||
| Wraps a pointer to a null-terminated ASCII character string, and provides | |||
| various methods to operate on the data. | |||
| A valid ASCII string is assumed to not contain any characters above 127. | |||
| @see CharPointer_UTF8, CharPointer_UTF16, CharPointer_UTF32 | |||
| */ | |||
| class CharPointer_ASCII | |||
| { | |||
| public: | |||
| typedef char CharType; | |||
| inline explicit CharPointer_ASCII (const CharType* const rawPointer) throw() | |||
| : data (const_cast <CharType*> (rawPointer)) | |||
| { | |||
| } | |||
| inline CharPointer_ASCII (const CharPointer_ASCII& other) throw() | |||
| : data (other.data) | |||
| { | |||
| } | |||
| inline CharPointer_ASCII& operator= (const CharPointer_ASCII& other) throw() | |||
| { | |||
| data = other.data; | |||
| return *this; | |||
| } | |||
| inline CharPointer_ASCII& operator= (const CharType* text) throw() | |||
| { | |||
| data = const_cast <CharType*> (text); | |||
| return *this; | |||
| } | |||
| /** This is a pointer comparison, it doesn't compare the actual text. */ | |||
| inline bool operator== (const CharPointer_ASCII& other) const throw() | |||
| { | |||
| return data == other.data; | |||
| } | |||
| /** This is a pointer comparison, it doesn't compare the actual text. */ | |||
| inline bool operator!= (const CharPointer_ASCII& other) const throw() | |||
| { | |||
| return data == other.data; | |||
| } | |||
| /** Returns the address that this pointer is pointing to. */ | |||
| inline CharType* getAddress() const throw() { return data; } | |||
| /** Returns the address that this pointer is pointing to. */ | |||
| inline operator const CharType*() const throw() { return data; } | |||
| /** Returns true if this pointer is pointing to a null character. */ | |||
| inline bool isEmpty() const throw() { return *data == 0; } | |||
| /** Returns the unicode character that this pointer is pointing to. */ | |||
| inline juce_wchar operator*() const throw() { return *data; } | |||
| /** Moves this pointer along to the next character in the string. */ | |||
| inline CharPointer_ASCII& operator++() throw() | |||
| { | |||
| ++data; | |||
| return *this; | |||
| } | |||
| /** Moves this pointer to the previous character in the string. */ | |||
| inline CharPointer_ASCII& operator--() throw() | |||
| { | |||
| --data; | |||
| return *this; | |||
| } | |||
| /** Returns the character that this pointer is currently pointing to, and then | |||
| advances the pointer to point to the next character. */ | |||
| inline juce_wchar getAndAdvance() throw() { return *data++; } | |||
| /** Moves this pointer along to the next character in the string. */ | |||
| CharPointer_ASCII operator++ (int) throw() | |||
| { | |||
| CharPointer_ASCII temp (*this); | |||
| ++data; | |||
| return temp; | |||
| } | |||
| /** Moves this pointer forwards by the specified number of characters. */ | |||
| inline void operator+= (const int numToSkip) throw() | |||
| { | |||
| data += numToSkip; | |||
| } | |||
| inline void operator-= (const int numToSkip) throw() | |||
| { | |||
| data -= numToSkip; | |||
| } | |||
| /** Returns the character at a given character index from the start of the string. */ | |||
| inline juce_wchar operator[] (const int characterIndex) const throw() | |||
| { | |||
| return (juce_wchar) (unsigned char) data [characterIndex]; | |||
| } | |||
| /** Returns a pointer which is moved forwards from this one by the specified number of characters. */ | |||
| CharPointer_ASCII operator+ (const int numToSkip) const throw() | |||
| { | |||
| return CharPointer_ASCII (data + numToSkip); | |||
| } | |||
| /** Returns a pointer which is moved backwards from this one by the specified number of characters. */ | |||
| CharPointer_ASCII operator- (const int numToSkip) const throw() | |||
| { | |||
| return CharPointer_ASCII (data - numToSkip); | |||
| } | |||
| /** Writes a unicode character to this string, and advances this pointer to point to the next position. */ | |||
| inline void write (const juce_wchar charToWrite) throw() | |||
| { | |||
| *data++ = (char) charToWrite; | |||
| } | |||
| inline void replaceChar (const juce_wchar newChar) throw() | |||
| { | |||
| *data = (char) newChar; | |||
| } | |||
| /** Writes a null character to this string (leaving the pointer's position unchanged). */ | |||
| inline void writeNull() const throw() | |||
| { | |||
| *data = 0; | |||
| } | |||
| /** Returns the number of characters in this string. */ | |||
| size_t length() const throw() | |||
| { | |||
| return (size_t) strlen (data); | |||
| } | |||
| /** Returns the number of characters in this string, or the given value, whichever is lower. */ | |||
| size_t lengthUpTo (const size_t maxCharsToCount) const throw() | |||
| { | |||
| return CharacterFunctions::lengthUpTo (*this, maxCharsToCount); | |||
| } | |||
| /** Returns the number of bytes that are used to represent this string. | |||
| This includes the terminating null character. | |||
| */ | |||
| size_t sizeInBytes() const throw() | |||
| { | |||
| return length() + 1; | |||
| } | |||
| /** Returns the number of bytes that would be needed to represent the given | |||
| unicode character in this encoding format. | |||
| */ | |||
| static inline size_t getBytesRequiredFor (const juce_wchar) throw() | |||
| { | |||
| return 1; | |||
| } | |||
| /** Returns the number of bytes that would be needed to represent the given | |||
| string in this encoding format. | |||
| The value returned does NOT include the terminating null character. | |||
| */ | |||
| template <class CharPointer> | |||
| static size_t getBytesRequiredFor (const CharPointer& text) throw() | |||
| { | |||
| return text.length(); | |||
| } | |||
| /** Returns a pointer to the null character that terminates this string. */ | |||
| CharPointer_ASCII findTerminatingNull() const throw() | |||
| { | |||
| return CharPointer_ASCII (data + length()); | |||
| } | |||
| /** Copies a source string to this pointer, advancing this pointer as it goes. */ | |||
| template <typename CharPointer> | |||
| void writeAll (const CharPointer& src) throw() | |||
| { | |||
| CharacterFunctions::copyAll (*this, src); | |||
| } | |||
| /** Copies a source string to this pointer, advancing this pointer as it goes. */ | |||
| void writeAll (const CharPointer_ASCII& src) throw() | |||
| { | |||
| strcpy (data, src.data); | |||
| } | |||
| /** Copies a source string to this pointer, advancing this pointer as it goes. | |||
| The maxDestBytes parameter specifies the maximum number of bytes that can be written | |||
| to the destination buffer before stopping. | |||
| */ | |||
| template <typename CharPointer> | |||
| int writeWithDestByteLimit (const CharPointer& src, const int maxDestBytes) throw() | |||
| { | |||
| return CharacterFunctions::copyWithDestByteLimit (*this, src, maxDestBytes); | |||
| } | |||
| /** Copies a source string to this pointer, advancing this pointer as it goes. | |||
| The maxChars parameter specifies the maximum number of characters that can be | |||
| written to the destination buffer before stopping (including the terminating null). | |||
| */ | |||
| template <typename CharPointer> | |||
| void writeWithCharLimit (const CharPointer& src, const int maxChars) throw() | |||
| { | |||
| CharacterFunctions::copyWithCharLimit (*this, src, maxChars); | |||
| } | |||
| /** Compares this string with another one. */ | |||
| template <typename CharPointer> | |||
| int compare (const CharPointer& other) const throw() | |||
| { | |||
| return CharacterFunctions::compare (*this, other); | |||
| } | |||
| /** Compares this string with another one. */ | |||
| int compare (const CharPointer_ASCII& other) const throw() | |||
| { | |||
| return strcmp (data, other.data); | |||
| } | |||
| /** Compares this string with another one, up to a specified number of characters. */ | |||
| template <typename CharPointer> | |||
| int compareUpTo (const CharPointer& other, const int maxChars) const throw() | |||
| { | |||
| return CharacterFunctions::compareUpTo (*this, other, maxChars); | |||
| } | |||
| /** Compares this string with another one, up to a specified number of characters. */ | |||
| int compareUpTo (const CharPointer_ASCII& other, const int maxChars) const throw() | |||
| { | |||
| return strncmp (data, other.data, (size_t) maxChars); | |||
| } | |||
| /** Compares this string with another one. */ | |||
| template <typename CharPointer> | |||
| int compareIgnoreCase (const CharPointer& other) const | |||
| { | |||
| return CharacterFunctions::compareIgnoreCase (*this, other); | |||
| } | |||
| int compareIgnoreCase (const CharPointer_ASCII& other) const | |||
| { | |||
| #if JUCE_WINDOWS | |||
| return stricmp (data, other.data); | |||
| #else | |||
| return strcasecmp (data, other.data); | |||
| #endif | |||
| } | |||
| /** Compares this string with another one, up to a specified number of characters. */ | |||
| template <typename CharPointer> | |||
| int compareIgnoreCaseUpTo (const CharPointer& other, const int maxChars) const throw() | |||
| { | |||
| return CharacterFunctions::compareIgnoreCaseUpTo (*this, other, maxChars); | |||
| } | |||
| /** Returns the character index of a substring, or -1 if it isn't found. */ | |||
| template <typename CharPointer> | |||
| int indexOf (const CharPointer& stringToFind) const throw() | |||
| { | |||
| return CharacterFunctions::indexOf (*this, stringToFind); | |||
| } | |||
| /** Returns the character index of a unicode character, or -1 if it isn't found. */ | |||
| int indexOf (const juce_wchar charToFind) const throw() | |||
| { | |||
| int i = 0; | |||
| while (data[i] != 0) | |||
| { | |||
| if (data[i] == (char) charToFind) | |||
| return i; | |||
| ++i; | |||
| } | |||
| return -1; | |||
| } | |||
| /** Returns the character index of a unicode character, or -1 if it isn't found. */ | |||
| int indexOf (const juce_wchar charToFind, const bool ignoreCase) const throw() | |||
| { | |||
| return ignoreCase ? CharacterFunctions::indexOfCharIgnoreCase (*this, charToFind) | |||
| : CharacterFunctions::indexOfChar (*this, charToFind); | |||
| } | |||
| /** Returns true if the first character of this string is whitespace. */ | |||
| bool isWhitespace() const { return CharacterFunctions::isWhitespace (*data) != 0; } | |||
| /** Returns true if the first character of this string is a digit. */ | |||
| bool isDigit() const { return CharacterFunctions::isDigit (*data) != 0; } | |||
| /** Returns true if the first character of this string is a letter. */ | |||
| bool isLetter() const { return CharacterFunctions::isLetter (*data) != 0; } | |||
| /** Returns true if the first character of this string is a letter or digit. */ | |||
| bool isLetterOrDigit() const { return CharacterFunctions::isLetterOrDigit (*data) != 0; } | |||
| /** Returns true if the first character of this string is upper-case. */ | |||
| bool isUpperCase() const { return CharacterFunctions::isUpperCase (*data) != 0; } | |||
| /** Returns true if the first character of this string is lower-case. */ | |||
| bool isLowerCase() const { return CharacterFunctions::isLowerCase (*data) != 0; } | |||
| /** Returns an upper-case version of the first character of this string. */ | |||
| juce_wchar toUpperCase() const throw() { return CharacterFunctions::toUpperCase (*data); } | |||
| /** Returns a lower-case version of the first character of this string. */ | |||
| juce_wchar toLowerCase() const throw() { return CharacterFunctions::toLowerCase (*data); } | |||
| /** Parses this string as a 32-bit integer. */ | |||
| int getIntValue32() const throw() { return atoi (data); } | |||
| /** Parses this string as a 64-bit integer. */ | |||
| int64 getIntValue64() const throw() | |||
| { | |||
| #if JUCE_LINUX || JUCE_ANDROID | |||
| return atoll (data); | |||
| #elif JUCE_WINDOWS | |||
| return _atoi64 (data); | |||
| #else | |||
| return CharacterFunctions::getIntValue <int64, CharPointer_ASCII> (*this); | |||
| #endif | |||
| } | |||
| /** Parses this string as a floating point double. */ | |||
| double getDoubleValue() const throw() { return CharacterFunctions::getDoubleValue (*this); } | |||
| /** Returns the first non-whitespace character in the string. */ | |||
| CharPointer_ASCII findEndOfWhitespace() const throw() { return CharacterFunctions::findEndOfWhitespace (*this); } | |||
| /** Returns true if the given unicode character can be represented in this encoding. */ | |||
| static bool canRepresent (juce_wchar character) throw() | |||
| { | |||
| return ((unsigned int) character) < (unsigned int) 128; | |||
| } | |||
| /** Returns true if this data contains a valid string in this encoding. */ | |||
| static bool isValidString (const CharType* dataToTest, int maxBytesToRead) | |||
| { | |||
| while (--maxBytesToRead >= 0) | |||
| { | |||
| if (*dataToTest <= 0) | |||
| return *dataToTest == 0; | |||
| ++dataToTest; | |||
| } | |||
| return true; | |||
| } | |||
| private: | |||
| CharType* data; | |||
| }; | |||
| #endif // __JUCE_CHARPOINTER_ASCII_JUCEHEADER__ | |||
| /*** End of inlined file: juce_CharPointer_ASCII.h ***/ | |||
| #if JUCE_MSVC | |||
| #pragma warning (pop) | |||
| #endif | |||
| @@ -3644,7 +4103,6 @@ class JUCE_API String | |||
| public: | |||
| /** Creates an empty string. | |||
| @see empty | |||
| */ | |||
| String() throw(); | |||
| @@ -3652,15 +4110,36 @@ public: | |||
| /** Creates a copy of another string. */ | |||
| String (const String& other) throw(); | |||
| /** Creates a string from a zero-terminated text string. | |||
| The string is assumed to be stored in the default system encoding. | |||
| /** Creates a string from a zero-terminated ascii text string. | |||
| The string passed-in must not contain any characters with a value above 127, because | |||
| these can't be converted to unicode without knowing the original encoding that was | |||
| used to create the string. If you attempt to pass-in values above 127, you'll get an | |||
| assertion. | |||
| To create strings with extended characters from UTF-8, you should explicitly call | |||
| String (CharPointer_UTF8 ("my utf8 string..")). It's *highly* recommended that you | |||
| use UTF-8 with escape characters in your source code to represent extended characters, | |||
| because there's no other way to represent unicode strings in a way that isn't dependent | |||
| on the compiler, source code editor and platform. | |||
| */ | |||
| String (const char* text); | |||
| /** Creates a string from an string of characters. | |||
| /** Creates a string from a string of 8-bit ascii characters. | |||
| This will use up the the first maxChars characters of the string (or | |||
| less if the string is actually shorter) | |||
| The string passed-in must not contain any characters with a value above 127, because | |||
| these can't be converted to unicode without knowing the original encoding that was | |||
| used to create the string. If you attempt to pass-in values above 127, you'll get an | |||
| assertion. | |||
| To create strings with extended characters from UTF-8, you should explicitly call | |||
| String (CharPointer_UTF8 ("my utf8 string..")). It's *highly* recommended that you | |||
| use UTF-8 with escape characters in your source code to represent extended characters, | |||
| because there's no other way to represent unicode strings in a way that isn't dependent | |||
| on the compiler, source code editor and platform. | |||
| This will use up the the first maxChars characters of the string (or less if the string | |||
| is actually shorter). | |||
| */ | |||
| String (const char* text, size_t maxChars); | |||
| @@ -3686,6 +4165,9 @@ public: | |||
| /** Creates a string from a UTF-32 character string */ | |||
| String (const CharPointer_UTF32& text, size_t maxChars); | |||
| /** Creates a string from an ASCII character string */ | |||
| String (const CharPointer_ASCII& text); | |||
| #if JUCE_WINDOWS | |||
| /** Creates a string from a UTF-16 character string */ | |||
| String (const wchar_t* text); | |||
| @@ -15559,16 +16041,34 @@ public: | |||
| virtual void valueTreePropertyChanged (ValueTree& treeWhosePropertyHasChanged, | |||
| const Identifier& property) = 0; | |||
| /** This method is called when a child sub-tree is added or removed. | |||
| /** This method is called when a child sub-tree is added. | |||
| Note that when you register a listener to a tree, it will receive this callback for | |||
| child changes in both that tree and any of its children, (recursively, at any depth). | |||
| If your tree has sub-trees but you only want to know about changes to the top level tree, | |||
| just check the parentTree parameter to make sure it's the one that you're interested in. | |||
| */ | |||
| virtual void valueTreeChildAdded (ValueTree& parentTree, | |||
| ValueTree& childWhichHasBeenAdded) = 0; | |||
| /** This method is called when a child sub-tree is removed. | |||
| Note that when you register a listener to a tree, it will receive this callback for | |||
| child changes in both that tree and any of its children, (recursively, at any depth). | |||
| If your tree has sub-trees but you only want to know about changes to the top level tree, | |||
| just check the parentTree parameter to make sure it's the one that you're interested in. | |||
| */ | |||
| virtual void valueTreeChildRemoved (ValueTree& parentTree, | |||
| ValueTree& childWhichHasBeenRemoved) = 0; | |||
| The tree parameter indicates the tree whose child was added or removed. | |||
| /** This method is called when a tree's children have been re-shuffled. | |||
| Note that when you register a listener to a tree, it will receive this callback for | |||
| child changes in that tree, and also in any of its children, (recursively, at any depth). | |||
| child changes in both that tree and any of its children, (recursively, at any depth). | |||
| If your tree has sub-trees but you only want to know about changes to the top level tree, | |||
| simply check the tree parameter in this callback to make sure it's the tree you're interested in. | |||
| just check the parameter to make sure it's the tree that you're interested in. | |||
| */ | |||
| virtual void valueTreeChildrenChanged (ValueTree& treeWhoseChildHasChanged) = 0; | |||
| virtual void valueTreeChildOrderChanged (ValueTree& parentTreeWhoseChildrenHaveMoved) = 0; | |||
| /** This method is called when a tree has been added or removed from a parent node. | |||
| @@ -15660,8 +16160,12 @@ private: | |||
| void sendPropertyChangeMessage (const Identifier& property); | |||
| void sendPropertyChangeMessage (ValueTree& tree, const Identifier& property); | |||
| void sendChildChangeMessage(); | |||
| void sendChildChangeMessage (ValueTree& tree); | |||
| void sendChildAddedMessage (ValueTree& parent, ValueTree& child); | |||
| void sendChildAddedMessage (ValueTree child); | |||
| void sendChildRemovedMessage (ValueTree& parent, ValueTree& child); | |||
| void sendChildRemovedMessage (ValueTree child); | |||
| void sendChildOrderChangedMessage (ValueTree& parent); | |||
| void sendChildOrderChangedMessage(); | |||
| void sendParentChangeMessage(); | |||
| const var& getProperty (const Identifier& name) const; | |||
| const var getProperty (const Identifier& name, const var& defaultReturnValue) const; | |||
| @@ -20054,6 +20558,9 @@ private: | |||
| #endif | |||
| #ifndef __JUCE_CHARACTERFUNCTIONS_JUCEHEADER__ | |||
| #endif | |||
| #ifndef __JUCE_CHARPOINTER_ASCII_JUCEHEADER__ | |||
| #endif | |||
| #ifndef __JUCE_CHARPOINTER_UTF16_JUCEHEADER__ | |||
| @@ -20368,7 +20875,7 @@ public: | |||
| private: | |||
| String originalText; | |||
| CharPointer_UTF32 input; | |||
| String::CharPointerType input; | |||
| bool outOfData, errorOccurred; | |||
| String lastError, dtdText; | |||
| @@ -40505,16 +41012,16 @@ public: | |||
| virtual ~Listener() {} | |||
| /** Called when the user changes the text in some way. */ | |||
| virtual void textEditorTextChanged (TextEditor& editor) = 0; | |||
| virtual void textEditorTextChanged (TextEditor& editor); | |||
| /** Called when the user presses the return key. */ | |||
| virtual void textEditorReturnKeyPressed (TextEditor& editor) = 0; | |||
| virtual void textEditorReturnKeyPressed (TextEditor& editor); | |||
| /** Called when the user presses the escape key. */ | |||
| virtual void textEditorEscapeKeyPressed (TextEditor& editor) = 0; | |||
| virtual void textEditorEscapeKeyPressed (TextEditor& editor); | |||
| /** Called when the text editor loses focus. */ | |||
| virtual void textEditorFocusLost (TextEditor& editor) = 0; | |||
| virtual void textEditorFocusLost (TextEditor& editor); | |||
| }; | |||
| /** Registers a listener to be told when things happen to the text. | |||
| @@ -47918,7 +48425,11 @@ public: | |||
| /** @internal */ | |||
| void valueTreePropertyChanged (ValueTree& treeWhosePropertyHasChanged, const Identifier& property); | |||
| /** @internal */ | |||
| void valueTreeChildrenChanged (ValueTree& treeWhoseChildHasChanged); | |||
| void valueTreeChildAdded (ValueTree& parentTree, ValueTree& childWhichHasBeenAdded); | |||
| /** @internal */ | |||
| void valueTreeChildRemoved (ValueTree& parentTree, ValueTree& childWhichHasBeenRemoved); | |||
| /** @internal */ | |||
| void valueTreeChildOrderChanged (ValueTree& parentTree); | |||
| /** @internal */ | |||
| void valueTreeParentChanged (ValueTree& treeWhoseParentHasChanged); | |||
| @@ -498,8 +498,7 @@ public: | |||
| : AudioFormatWriter (out, TRANS (wavFormatName), sampleRate_, numChannels_, bits), | |||
| lengthInSamples (0), | |||
| bytesWritten (0), | |||
| writeFailed (false), | |||
| isRF64 (false) | |||
| writeFailed (false) | |||
| { | |||
| using namespace WavFileHelpers; | |||
| @@ -567,7 +566,7 @@ private: | |||
| MemoryBlock tempBlock, bwavChunk, smplChunk; | |||
| uint64 lengthInSamples, bytesWritten; | |||
| int64 headerPosition; | |||
| bool writeFailed, isRF64; | |||
| bool writeFailed; | |||
| static int getChannelMask (const int numChannels) throw() | |||
| { | |||
| @@ -596,14 +595,15 @@ private: | |||
| const int bytesPerFrame = numChannels * bitsPerSample / 8; | |||
| int64 audioDataSize = bytesPerFrame * lengthInSamples; | |||
| int64 riffChunkSize = 4 /* 'WAVE' */ + 8 + 40 /* WAVEFORMATEX */ | |||
| const bool isRF64 = (bytesWritten >= literal64bit (0x100000000)); | |||
| int64 riffChunkSize = 4 /* 'RIFF' */ + 8 + 40 /* WAVEFORMATEX */ | |||
| + 8 + audioDataSize + (audioDataSize & 1) | |||
| + (bwavChunk.getSize() > 0 ? (8 + bwavChunk.getSize()) : 0) | |||
| + (smplChunk.getSize() > 0 ? (8 + smplChunk.getSize()) : 0) | |||
| + (8 + 28); // (JUNK chunk) | |||
| + (8 + 28); // (ds64 chunk) | |||
| riffChunkSize += (riffChunkSize & 0x1); | |||
| isRF64 = (riffChunkSize > 0xffffffff); | |||
| output->writeInt (chunkName (isRF64 ? "RF64" : "RIFF")); | |||
| output->writeInt (isRF64 ? -1 : (int) riffChunkSize); | |||
| @@ -611,10 +611,9 @@ private: | |||
| if (! isRF64) | |||
| { | |||
| // write Junk chunk | |||
| output->writeInt (chunkName ("JUNK")); | |||
| output->writeInt (28); | |||
| output->writeRepeatedByte (0, 28); | |||
| output->writeInt (28 + 24); | |||
| output->writeRepeatedByte (0, 28 /* ds64 */ + 24 /* extra waveformatex */); | |||
| } | |||
| else | |||
| { | |||
| @@ -627,29 +626,44 @@ private: | |||
| } | |||
| output->writeInt (chunkName ("fmt ")); | |||
| output->writeInt (40); // WAVEFORMATEX chunk size | |||
| output->writeShort ((short) (uint16) 0xfffe); // WAVE_FORMAT_EXTENSIBLE | |||
| if (isRF64) | |||
| { | |||
| output->writeInt (40); // chunk size | |||
| output->writeShort ((short) (uint16) 0xfffe); // WAVE_FORMAT_EXTENSIBLE | |||
| } | |||
| else | |||
| { | |||
| output->writeInt (16); // chunk size | |||
| output->writeShort (bitsPerSample < 32 ? (short) 1 /*WAVE_FORMAT_PCM*/ | |||
| : (short) 3 /*WAVE_FORMAT_IEEE_FLOAT*/); | |||
| } | |||
| output->writeShort ((short) numChannels); | |||
| output->writeInt ((int) sampleRate); | |||
| output->writeInt ((int) (bytesPerFrame * sampleRate)); // nAvgBytesPerSec | |||
| output->writeShort ((short) bytesPerFrame); // nBlockAlign | |||
| output->writeShort ((short) bitsPerSample); // wBitsPerSample | |||
| output->writeShort (22); // cbSize (size of the extension) | |||
| output->writeShort ((short) bitsPerSample); // wValidBitsPerSample | |||
| output->writeInt (getChannelMask (numChannels)); | |||
| const ExtensibleWavSubFormat pcmFormat | |||
| = { 0x00000001, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } }; | |||
| if (isRF64) | |||
| { | |||
| output->writeShort (22); // cbSize (size of the extension) | |||
| output->writeShort ((short) bitsPerSample); // wValidBitsPerSample | |||
| output->writeInt (getChannelMask (numChannels)); | |||
| const ExtensibleWavSubFormat pcmFormat | |||
| = { 0x00000001, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } }; | |||
| const ExtensibleWavSubFormat IEEEFloatFormat | |||
| = { 0x00000003, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } }; | |||
| const ExtensibleWavSubFormat IEEEFloatFormat | |||
| = { 0x00000003, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } }; | |||
| const ExtensibleWavSubFormat& subFormat = bitsPerSample < 32 ? pcmFormat : IEEEFloatFormat; | |||
| const ExtensibleWavSubFormat& subFormat = bitsPerSample < 32 ? pcmFormat : IEEEFloatFormat; | |||
| output->writeInt ((int) subFormat.data1); | |||
| output->writeShort ((short) subFormat.data2); | |||
| output->writeShort ((short) subFormat.data3); | |||
| output->write (subFormat.data4, sizeof (subFormat.data4)); | |||
| output->writeInt ((int) subFormat.data1); | |||
| output->writeShort ((short) subFormat.data2); | |||
| output->writeShort ((short) subFormat.data3); | |||
| output->write (subFormat.data4, sizeof (subFormat.data4)); | |||
| } | |||
| if (bwavChunk.getSize() > 0) | |||
| { | |||
| @@ -250,24 +250,68 @@ void ValueTree::SharedObject::sendPropertyChangeMessage (const Identifier& prope | |||
| } | |||
| } | |||
| void ValueTree::SharedObject::sendChildChangeMessage (ValueTree& tree) | |||
| void ValueTree::SharedObject::sendChildAddedMessage (ValueTree& tree, ValueTree& child) | |||
| { | |||
| for (int i = valueTreesWithListeners.size(); --i >= 0;) | |||
| { | |||
| ValueTree* const v = valueTreesWithListeners[i]; | |||
| if (v != 0) | |||
| v->listeners.call (&ValueTree::Listener::valueTreeChildrenChanged, tree); | |||
| v->listeners.call (&ValueTree::Listener::valueTreeChildAdded, tree, child); | |||
| } | |||
| } | |||
| void ValueTree::SharedObject::sendChildChangeMessage() | |||
| void ValueTree::SharedObject::sendChildAddedMessage (ValueTree child) | |||
| { | |||
| ValueTree tree (this); | |||
| ValueTree::SharedObject* t = this; | |||
| while (t != 0) | |||
| { | |||
| t->sendChildChangeMessage (tree); | |||
| t->sendChildAddedMessage (tree, child); | |||
| t = t->parent; | |||
| } | |||
| } | |||
| void ValueTree::SharedObject::sendChildRemovedMessage (ValueTree& tree, ValueTree& child) | |||
| { | |||
| for (int i = valueTreesWithListeners.size(); --i >= 0;) | |||
| { | |||
| ValueTree* const v = valueTreesWithListeners[i]; | |||
| if (v != 0) | |||
| v->listeners.call (&ValueTree::Listener::valueTreeChildRemoved, tree, child); | |||
| } | |||
| } | |||
| void ValueTree::SharedObject::sendChildRemovedMessage (ValueTree child) | |||
| { | |||
| ValueTree tree (this); | |||
| ValueTree::SharedObject* t = this; | |||
| while (t != 0) | |||
| { | |||
| t->sendChildRemovedMessage (tree, child); | |||
| t = t->parent; | |||
| } | |||
| } | |||
| void ValueTree::SharedObject::sendChildOrderChangedMessage (ValueTree& tree) | |||
| { | |||
| for (int i = valueTreesWithListeners.size(); --i >= 0;) | |||
| { | |||
| ValueTree* const v = valueTreesWithListeners[i]; | |||
| if (v != 0) | |||
| v->listeners.call (&ValueTree::Listener::valueTreeChildOrderChanged, tree); | |||
| } | |||
| } | |||
| void ValueTree::SharedObject::sendChildOrderChangedMessage() | |||
| { | |||
| ValueTree tree (this); | |||
| ValueTree::SharedObject* t = this; | |||
| while (t != 0) | |||
| { | |||
| t->sendChildOrderChangedMessage (tree); | |||
| t = t->parent; | |||
| } | |||
| } | |||
| @@ -434,7 +478,7 @@ void ValueTree::SharedObject::addChild (SharedObject* child, int index, UndoMana | |||
| { | |||
| children.insert (index, child); | |||
| child->parent = this; | |||
| sendChildChangeMessage(); | |||
| sendChildAddedMessage (ValueTree (child)); | |||
| child->sendParentChangeMessage(); | |||
| } | |||
| else | |||
| @@ -464,7 +508,7 @@ void ValueTree::SharedObject::removeChild (const int childIndex, UndoManager* co | |||
| { | |||
| children.remove (childIndex); | |||
| child->parent = 0; | |||
| sendChildChangeMessage(); | |||
| sendChildRemovedMessage (ValueTree (child)); | |||
| child->sendParentChangeMessage(); | |||
| } | |||
| else | |||
| @@ -491,7 +535,7 @@ void ValueTree::SharedObject::moveChild (int currentIndex, int newIndex, UndoMan | |||
| if (undoManager == 0) | |||
| { | |||
| children.move (currentIndex, newIndex); | |||
| sendChildChangeMessage(); | |||
| sendChildOrderChangedMessage(); | |||
| } | |||
| else | |||
| { | |||
| @@ -510,16 +554,19 @@ void ValueTree::SharedObject::reorderChildren (const ReferenceCountedArray <Shar | |||
| if (undoManager == 0) | |||
| { | |||
| children = newOrder; | |||
| sendChildChangeMessage(); | |||
| sendChildOrderChangedMessage(); | |||
| } | |||
| else | |||
| { | |||
| for (int i = 0; i < children.size(); ++i) | |||
| { | |||
| if (children.getUnchecked(i) != newOrder.getUnchecked(i)) | |||
| const SharedObjectPtr child (newOrder.getUnchecked(i)); | |||
| if (children.getUnchecked(i) != child) | |||
| { | |||
| jassert (children.contains (newOrder.getUnchecked(i))); | |||
| moveChild (children.indexOf (newOrder.getUnchecked(i)), i, undoManager); | |||
| const int oldIndex = children.indexOf (child); | |||
| jassert (oldIndex >= 0); | |||
| moveChild (oldIndex, i, undoManager); | |||
| } | |||
| } | |||
| } | |||
| @@ -719,8 +766,10 @@ public: | |||
| sendChangeMessage (false); | |||
| } | |||
| void valueTreeChildrenChanged (ValueTree&) {} | |||
| void valueTreeParentChanged (ValueTree&) {} | |||
| void valueTreeChildAdded (ValueTree&, ValueTree&) {} | |||
| void valueTreeChildRemoved (ValueTree&, ValueTree&) {} | |||
| void valueTreeChildOrderChanged (ValueTree&) {} | |||
| void valueTreeParentChanged (ValueTree&) {} | |||
| private: | |||
| ValueTree tree; | |||
| @@ -368,16 +368,34 @@ public: | |||
| virtual void valueTreePropertyChanged (ValueTree& treeWhosePropertyHasChanged, | |||
| const Identifier& property) = 0; | |||
| /** This method is called when a child sub-tree is added or removed. | |||
| /** This method is called when a child sub-tree is added. | |||
| The tree parameter indicates the tree whose child was added or removed. | |||
| Note that when you register a listener to a tree, it will receive this callback for | |||
| child changes in both that tree and any of its children, (recursively, at any depth). | |||
| If your tree has sub-trees but you only want to know about changes to the top level tree, | |||
| just check the parentTree parameter to make sure it's the one that you're interested in. | |||
| */ | |||
| virtual void valueTreeChildAdded (ValueTree& parentTree, | |||
| ValueTree& childWhichHasBeenAdded) = 0; | |||
| /** This method is called when a child sub-tree is removed. | |||
| Note that when you register a listener to a tree, it will receive this callback for | |||
| child changes in that tree, and also in any of its children, (recursively, at any depth). | |||
| child changes in both that tree and any of its children, (recursively, at any depth). | |||
| If your tree has sub-trees but you only want to know about changes to the top level tree, | |||
| simply check the tree parameter in this callback to make sure it's the tree you're interested in. | |||
| just check the parentTree parameter to make sure it's the one that you're interested in. | |||
| */ | |||
| virtual void valueTreeChildRemoved (ValueTree& parentTree, | |||
| ValueTree& childWhichHasBeenRemoved) = 0; | |||
| /** This method is called when a tree's children have been re-shuffled. | |||
| Note that when you register a listener to a tree, it will receive this callback for | |||
| child changes in both that tree and any of its children, (recursively, at any depth). | |||
| If your tree has sub-trees but you only want to know about changes to the top level tree, | |||
| just check the parameter to make sure it's the tree that you're interested in. | |||
| */ | |||
| virtual void valueTreeChildrenChanged (ValueTree& treeWhoseChildHasChanged) = 0; | |||
| virtual void valueTreeChildOrderChanged (ValueTree& parentTreeWhoseChildrenHaveMoved) = 0; | |||
| /** This method is called when a tree has been added or removed from a parent node. | |||
| @@ -470,8 +488,12 @@ private: | |||
| void sendPropertyChangeMessage (const Identifier& property); | |||
| void sendPropertyChangeMessage (ValueTree& tree, const Identifier& property); | |||
| void sendChildChangeMessage(); | |||
| void sendChildChangeMessage (ValueTree& tree); | |||
| void sendChildAddedMessage (ValueTree& parent, ValueTree& child); | |||
| void sendChildAddedMessage (ValueTree child); | |||
| void sendChildRemovedMessage (ValueTree& parent, ValueTree& child); | |||
| void sendChildRemovedMessage (ValueTree child); | |||
| void sendChildOrderChangedMessage (ValueTree& parent); | |||
| void sendChildOrderChangedMessage(); | |||
| void sendParentChangeMessage(); | |||
| const var& getProperty (const Identifier& name) const; | |||
| const var getProperty (const Identifier& name, const var& defaultReturnValue) const; | |||
| @@ -33,7 +33,7 @@ | |||
| */ | |||
| #define JUCE_MAJOR_VERSION 1 | |||
| #define JUCE_MINOR_VERSION 53 | |||
| #define JUCE_BUILDNUMBER 21 | |||
| #define JUCE_BUILDNUMBER 23 | |||
| /** Current Juce version number. | |||
| @@ -180,6 +180,7 @@ void DrawableButton::buttonStateChanged() | |||
| if (currentImage != 0) | |||
| { | |||
| currentImage->setInterceptsMouseClicks (false, false); | |||
| addAndMakeVisible (currentImage); | |||
| DrawableButton::resized(); | |||
| } | |||
| @@ -2621,5 +2621,9 @@ void TextEditor::coalesceSimilarSections() | |||
| } | |||
| } | |||
| void TextEditor::Listener::textEditorTextChanged (TextEditor&) {} | |||
| void TextEditor::Listener::textEditorReturnKeyPressed (TextEditor&) {} | |||
| void TextEditor::Listener::textEditorEscapeKeyPressed (TextEditor&) {} | |||
| void TextEditor::Listener::textEditorFocusLost (TextEditor&) {} | |||
| END_JUCE_NAMESPACE | |||
| @@ -313,16 +313,16 @@ public: | |||
| virtual ~Listener() {} | |||
| /** Called when the user changes the text in some way. */ | |||
| virtual void textEditorTextChanged (TextEditor& editor) = 0; | |||
| virtual void textEditorTextChanged (TextEditor& editor); | |||
| /** Called when the user presses the return key. */ | |||
| virtual void textEditorReturnKeyPressed (TextEditor& editor) = 0; | |||
| virtual void textEditorReturnKeyPressed (TextEditor& editor); | |||
| /** Called when the user presses the escape key. */ | |||
| virtual void textEditorEscapeKeyPressed (TextEditor& editor) = 0; | |||
| virtual void textEditorEscapeKeyPressed (TextEditor& editor); | |||
| /** Called when the text editor loses focus. */ | |||
| virtual void textEditorFocusLost (TextEditor& editor) = 0; | |||
| virtual void textEditorFocusLost (TextEditor& editor); | |||
| }; | |||
| /** Registers a listener to be told when things happen to the text. | |||
| @@ -201,7 +201,17 @@ void ComponentBuilder::valueTreePropertyChanged (ValueTree& tree, const Identifi | |||
| ComponentBuilderHelpers::updateComponent (*this, tree); | |||
| } | |||
| void ComponentBuilder::valueTreeChildrenChanged (ValueTree& tree) | |||
| void ComponentBuilder::valueTreeChildAdded (ValueTree& tree, ValueTree&) | |||
| { | |||
| ComponentBuilderHelpers::updateComponent (*this, tree); | |||
| } | |||
| void ComponentBuilder::valueTreeChildRemoved (ValueTree& tree, ValueTree&) | |||
| { | |||
| ComponentBuilderHelpers::updateComponent (*this, tree); | |||
| } | |||
| void ComponentBuilder::valueTreeChildOrderChanged (ValueTree& tree) | |||
| { | |||
| ComponentBuilderHelpers::updateComponent (*this, tree); | |||
| } | |||
| @@ -229,7 +229,11 @@ public: | |||
| /** @internal */ | |||
| void valueTreePropertyChanged (ValueTree& treeWhosePropertyHasChanged, const Identifier& property); | |||
| /** @internal */ | |||
| void valueTreeChildrenChanged (ValueTree& treeWhoseChildHasChanged); | |||
| void valueTreeChildAdded (ValueTree& parentTree, ValueTree& childWhichHasBeenAdded); | |||
| /** @internal */ | |||
| void valueTreeChildRemoved (ValueTree& parentTree, ValueTree& childWhichHasBeenRemoved); | |||
| /** @internal */ | |||
| void valueTreeChildOrderChanged (ValueTree& parentTree); | |||
| /** @internal */ | |||
| void valueTreeParentChanged (ValueTree& treeWhoseParentHasChanged); | |||
| @@ -135,17 +135,21 @@ class PopupMenu::ItemComponent : public Component | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| ItemComponent (const PopupMenu::Item& itemInfo_, int standardItemHeight) | |||
| ItemComponent (const PopupMenu::Item& itemInfo_, int standardItemHeight, Component* const parent) | |||
| : itemInfo (itemInfo_), | |||
| isHighlighted (false) | |||
| { | |||
| if (itemInfo.customComp != 0) | |||
| addAndMakeVisible (itemInfo.customComp); | |||
| parent->addAndMakeVisible (this); | |||
| int itemW = 80; | |||
| int itemH = 16; | |||
| getIdealSize (itemW, itemH, standardItemHeight); | |||
| setSize (itemW, jlimit (2, 600, itemH)); | |||
| addMouseListener (parent, false); | |||
| } | |||
| ~ItemComponent() | |||
| @@ -277,12 +281,7 @@ public: | |||
| setOpaque (getLookAndFeel().findColour (PopupMenu::backgroundColourId).isOpaque() || ! Desktop::canUseSemiTransparentWindows()); | |||
| for (int i = 0; i < menu.items.size(); ++i) | |||
| { | |||
| PopupMenu::ItemComponent* const itemComp = new PopupMenu::ItemComponent (*menu.items.getUnchecked(i), standardItemHeight); | |||
| items.add (itemComp); | |||
| addAndMakeVisible (itemComp); | |||
| itemComp->addMouseListener (this, false); | |||
| } | |||
| items.add (new PopupMenu::ItemComponent (*menu.items.getUnchecked(i), standardItemHeight, this)); | |||
| calculateWindowPos (target, alignToRectangle); | |||
| setTopLeftPosition (windowPos.getX(), windowPos.getY()); | |||
| @@ -198,6 +198,12 @@ const Rectangle<float> DrawableShape::getDrawableBounds() const | |||
| bool DrawableShape::hitTest (int x, int y) | |||
| { | |||
| bool allowsClicksOnThisComponent, allowsClicksOnChildComponents; | |||
| getInterceptsMouseClicks (allowsClicksOnThisComponent, allowsClicksOnChildComponents); | |||
| if (! allowsClicksOnThisComponent) | |||
| return false; | |||
| const float globalX = (float) (x - originRelativeToComponent.getX()); | |||
| const float globalY = (float) (y - originRelativeToComponent.getY()); | |||
| @@ -233,6 +233,9 @@ | |||
| #ifndef __JUCE_CHARACTERFUNCTIONS_JUCEHEADER__ | |||
| #include "text/juce_CharacterFunctions.h" | |||
| #endif | |||
| #ifndef __JUCE_CHARPOINTER_ASCII_JUCEHEADER__ | |||
| #include "text/juce_CharPointer_ASCII.h" | |||
| #endif | |||
| #ifndef __JUCE_CHARPOINTER_UTF16_JUCEHEADER__ | |||
| #include "text/juce_CharPointer_UTF16.h" | |||
| #endif | |||
| @@ -92,7 +92,7 @@ namespace FileHelpers | |||
| FSRef ref; | |||
| LSItemInfoRecord info; | |||
| return FSPathMakeRefWithOptions ((const UInt8*) path.toUTF8(), kFSPathMakeRefDoNotFollowLeafSymlink, &ref, 0) == noErr | |||
| return FSPathMakeRefWithOptions ((const UInt8*) path.toUTF8().getAddress(), kFSPathMakeRefDoNotFollowLeafSymlink, &ref, 0) == noErr | |||
| && LSCopyItemInfoForRef (&ref, kLSRequestBasicFlagsOnly, &info) == noErr | |||
| && (info.flags & kLSItemInfoIsInvisible) != 0; | |||
| #endif | |||
| @@ -35,7 +35,7 @@ void SystemClipboard::copyTextToClipboard (const String& text) | |||
| { | |||
| if (EmptyClipboard() != 0) | |||
| { | |||
| const int bytesNeeded = CharPointer_UTF16::getBytesRequiredFor (text.getCharPointer()); | |||
| const int bytesNeeded = CharPointer_UTF16::getBytesRequiredFor (text.getCharPointer()) + 4; | |||
| if (bytesNeeded > 0) | |||
| { | |||
| @@ -0,0 +1,382 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||
| Copyright 2004-10 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_CHARPOINTER_ASCII_JUCEHEADER__ | |||
| #define __JUCE_CHARPOINTER_ASCII_JUCEHEADER__ | |||
| //============================================================================== | |||
| /** | |||
| Wraps a pointer to a null-terminated ASCII character string, and provides | |||
| various methods to operate on the data. | |||
| A valid ASCII string is assumed to not contain any characters above 127. | |||
| @see CharPointer_UTF8, CharPointer_UTF16, CharPointer_UTF32 | |||
| */ | |||
| class CharPointer_ASCII | |||
| { | |||
| public: | |||
| typedef char CharType; | |||
| inline explicit CharPointer_ASCII (const CharType* const rawPointer) throw() | |||
| : data (const_cast <CharType*> (rawPointer)) | |||
| { | |||
| } | |||
| inline CharPointer_ASCII (const CharPointer_ASCII& other) throw() | |||
| : data (other.data) | |||
| { | |||
| } | |||
| inline CharPointer_ASCII& operator= (const CharPointer_ASCII& other) throw() | |||
| { | |||
| data = other.data; | |||
| return *this; | |||
| } | |||
| inline CharPointer_ASCII& operator= (const CharType* text) throw() | |||
| { | |||
| data = const_cast <CharType*> (text); | |||
| return *this; | |||
| } | |||
| /** This is a pointer comparison, it doesn't compare the actual text. */ | |||
| inline bool operator== (const CharPointer_ASCII& other) const throw() | |||
| { | |||
| return data == other.data; | |||
| } | |||
| /** This is a pointer comparison, it doesn't compare the actual text. */ | |||
| inline bool operator!= (const CharPointer_ASCII& other) const throw() | |||
| { | |||
| return data == other.data; | |||
| } | |||
| /** Returns the address that this pointer is pointing to. */ | |||
| inline CharType* getAddress() const throw() { return data; } | |||
| /** Returns the address that this pointer is pointing to. */ | |||
| inline operator const CharType*() const throw() { return data; } | |||
| /** Returns true if this pointer is pointing to a null character. */ | |||
| inline bool isEmpty() const throw() { return *data == 0; } | |||
| /** Returns the unicode character that this pointer is pointing to. */ | |||
| inline juce_wchar operator*() const throw() { return *data; } | |||
| /** Moves this pointer along to the next character in the string. */ | |||
| inline CharPointer_ASCII& operator++() throw() | |||
| { | |||
| ++data; | |||
| return *this; | |||
| } | |||
| /** Moves this pointer to the previous character in the string. */ | |||
| inline CharPointer_ASCII& operator--() throw() | |||
| { | |||
| --data; | |||
| return *this; | |||
| } | |||
| /** Returns the character that this pointer is currently pointing to, and then | |||
| advances the pointer to point to the next character. */ | |||
| inline juce_wchar getAndAdvance() throw() { return *data++; } | |||
| /** Moves this pointer along to the next character in the string. */ | |||
| CharPointer_ASCII operator++ (int) throw() | |||
| { | |||
| CharPointer_ASCII temp (*this); | |||
| ++data; | |||
| return temp; | |||
| } | |||
| /** Moves this pointer forwards by the specified number of characters. */ | |||
| inline void operator+= (const int numToSkip) throw() | |||
| { | |||
| data += numToSkip; | |||
| } | |||
| inline void operator-= (const int numToSkip) throw() | |||
| { | |||
| data -= numToSkip; | |||
| } | |||
| /** Returns the character at a given character index from the start of the string. */ | |||
| inline juce_wchar operator[] (const int characterIndex) const throw() | |||
| { | |||
| return (juce_wchar) (unsigned char) data [characterIndex]; | |||
| } | |||
| /** Returns a pointer which is moved forwards from this one by the specified number of characters. */ | |||
| CharPointer_ASCII operator+ (const int numToSkip) const throw() | |||
| { | |||
| return CharPointer_ASCII (data + numToSkip); | |||
| } | |||
| /** Returns a pointer which is moved backwards from this one by the specified number of characters. */ | |||
| CharPointer_ASCII operator- (const int numToSkip) const throw() | |||
| { | |||
| return CharPointer_ASCII (data - numToSkip); | |||
| } | |||
| /** Writes a unicode character to this string, and advances this pointer to point to the next position. */ | |||
| inline void write (const juce_wchar charToWrite) throw() | |||
| { | |||
| *data++ = (char) charToWrite; | |||
| } | |||
| inline void replaceChar (const juce_wchar newChar) throw() | |||
| { | |||
| *data = (char) newChar; | |||
| } | |||
| /** Writes a null character to this string (leaving the pointer's position unchanged). */ | |||
| inline void writeNull() const throw() | |||
| { | |||
| *data = 0; | |||
| } | |||
| /** Returns the number of characters in this string. */ | |||
| size_t length() const throw() | |||
| { | |||
| return (size_t) strlen (data); | |||
| } | |||
| /** Returns the number of characters in this string, or the given value, whichever is lower. */ | |||
| size_t lengthUpTo (const size_t maxCharsToCount) const throw() | |||
| { | |||
| return CharacterFunctions::lengthUpTo (*this, maxCharsToCount); | |||
| } | |||
| /** Returns the number of bytes that are used to represent this string. | |||
| This includes the terminating null character. | |||
| */ | |||
| size_t sizeInBytes() const throw() | |||
| { | |||
| return length() + 1; | |||
| } | |||
| /** Returns the number of bytes that would be needed to represent the given | |||
| unicode character in this encoding format. | |||
| */ | |||
| static inline size_t getBytesRequiredFor (const juce_wchar) throw() | |||
| { | |||
| return 1; | |||
| } | |||
| /** Returns the number of bytes that would be needed to represent the given | |||
| string in this encoding format. | |||
| The value returned does NOT include the terminating null character. | |||
| */ | |||
| template <class CharPointer> | |||
| static size_t getBytesRequiredFor (const CharPointer& text) throw() | |||
| { | |||
| return text.length(); | |||
| } | |||
| /** Returns a pointer to the null character that terminates this string. */ | |||
| CharPointer_ASCII findTerminatingNull() const throw() | |||
| { | |||
| return CharPointer_ASCII (data + length()); | |||
| } | |||
| /** Copies a source string to this pointer, advancing this pointer as it goes. */ | |||
| template <typename CharPointer> | |||
| void writeAll (const CharPointer& src) throw() | |||
| { | |||
| CharacterFunctions::copyAll (*this, src); | |||
| } | |||
| /** Copies a source string to this pointer, advancing this pointer as it goes. */ | |||
| void writeAll (const CharPointer_ASCII& src) throw() | |||
| { | |||
| strcpy (data, src.data); | |||
| } | |||
| /** Copies a source string to this pointer, advancing this pointer as it goes. | |||
| The maxDestBytes parameter specifies the maximum number of bytes that can be written | |||
| to the destination buffer before stopping. | |||
| */ | |||
| template <typename CharPointer> | |||
| int writeWithDestByteLimit (const CharPointer& src, const int maxDestBytes) throw() | |||
| { | |||
| return CharacterFunctions::copyWithDestByteLimit (*this, src, maxDestBytes); | |||
| } | |||
| /** Copies a source string to this pointer, advancing this pointer as it goes. | |||
| The maxChars parameter specifies the maximum number of characters that can be | |||
| written to the destination buffer before stopping (including the terminating null). | |||
| */ | |||
| template <typename CharPointer> | |||
| void writeWithCharLimit (const CharPointer& src, const int maxChars) throw() | |||
| { | |||
| CharacterFunctions::copyWithCharLimit (*this, src, maxChars); | |||
| } | |||
| /** Compares this string with another one. */ | |||
| template <typename CharPointer> | |||
| int compare (const CharPointer& other) const throw() | |||
| { | |||
| return CharacterFunctions::compare (*this, other); | |||
| } | |||
| /** Compares this string with another one. */ | |||
| int compare (const CharPointer_ASCII& other) const throw() | |||
| { | |||
| return strcmp (data, other.data); | |||
| } | |||
| /** Compares this string with another one, up to a specified number of characters. */ | |||
| template <typename CharPointer> | |||
| int compareUpTo (const CharPointer& other, const int maxChars) const throw() | |||
| { | |||
| return CharacterFunctions::compareUpTo (*this, other, maxChars); | |||
| } | |||
| /** Compares this string with another one, up to a specified number of characters. */ | |||
| int compareUpTo (const CharPointer_ASCII& other, const int maxChars) const throw() | |||
| { | |||
| return strncmp (data, other.data, (size_t) maxChars); | |||
| } | |||
| /** Compares this string with another one. */ | |||
| template <typename CharPointer> | |||
| int compareIgnoreCase (const CharPointer& other) const | |||
| { | |||
| return CharacterFunctions::compareIgnoreCase (*this, other); | |||
| } | |||
| int compareIgnoreCase (const CharPointer_ASCII& other) const | |||
| { | |||
| #if JUCE_WINDOWS | |||
| return stricmp (data, other.data); | |||
| #else | |||
| return strcasecmp (data, other.data); | |||
| #endif | |||
| } | |||
| /** Compares this string with another one, up to a specified number of characters. */ | |||
| template <typename CharPointer> | |||
| int compareIgnoreCaseUpTo (const CharPointer& other, const int maxChars) const throw() | |||
| { | |||
| return CharacterFunctions::compareIgnoreCaseUpTo (*this, other, maxChars); | |||
| } | |||
| /** Returns the character index of a substring, or -1 if it isn't found. */ | |||
| template <typename CharPointer> | |||
| int indexOf (const CharPointer& stringToFind) const throw() | |||
| { | |||
| return CharacterFunctions::indexOf (*this, stringToFind); | |||
| } | |||
| /** Returns the character index of a unicode character, or -1 if it isn't found. */ | |||
| int indexOf (const juce_wchar charToFind) const throw() | |||
| { | |||
| int i = 0; | |||
| while (data[i] != 0) | |||
| { | |||
| if (data[i] == (char) charToFind) | |||
| return i; | |||
| ++i; | |||
| } | |||
| return -1; | |||
| } | |||
| /** Returns the character index of a unicode character, or -1 if it isn't found. */ | |||
| int indexOf (const juce_wchar charToFind, const bool ignoreCase) const throw() | |||
| { | |||
| return ignoreCase ? CharacterFunctions::indexOfCharIgnoreCase (*this, charToFind) | |||
| : CharacterFunctions::indexOfChar (*this, charToFind); | |||
| } | |||
| /** Returns true if the first character of this string is whitespace. */ | |||
| bool isWhitespace() const { return CharacterFunctions::isWhitespace (*data) != 0; } | |||
| /** Returns true if the first character of this string is a digit. */ | |||
| bool isDigit() const { return CharacterFunctions::isDigit (*data) != 0; } | |||
| /** Returns true if the first character of this string is a letter. */ | |||
| bool isLetter() const { return CharacterFunctions::isLetter (*data) != 0; } | |||
| /** Returns true if the first character of this string is a letter or digit. */ | |||
| bool isLetterOrDigit() const { return CharacterFunctions::isLetterOrDigit (*data) != 0; } | |||
| /** Returns true if the first character of this string is upper-case. */ | |||
| bool isUpperCase() const { return CharacterFunctions::isUpperCase (*data) != 0; } | |||
| /** Returns true if the first character of this string is lower-case. */ | |||
| bool isLowerCase() const { return CharacterFunctions::isLowerCase (*data) != 0; } | |||
| /** Returns an upper-case version of the first character of this string. */ | |||
| juce_wchar toUpperCase() const throw() { return CharacterFunctions::toUpperCase (*data); } | |||
| /** Returns a lower-case version of the first character of this string. */ | |||
| juce_wchar toLowerCase() const throw() { return CharacterFunctions::toLowerCase (*data); } | |||
| /** Parses this string as a 32-bit integer. */ | |||
| int getIntValue32() const throw() { return atoi (data); } | |||
| /** Parses this string as a 64-bit integer. */ | |||
| int64 getIntValue64() const throw() | |||
| { | |||
| #if JUCE_LINUX || JUCE_ANDROID | |||
| return atoll (data); | |||
| #elif JUCE_WINDOWS | |||
| return _atoi64 (data); | |||
| #else | |||
| return CharacterFunctions::getIntValue <int64, CharPointer_ASCII> (*this); | |||
| #endif | |||
| } | |||
| /** Parses this string as a floating point double. */ | |||
| double getDoubleValue() const throw() { return CharacterFunctions::getDoubleValue (*this); } | |||
| /** Returns the first non-whitespace character in the string. */ | |||
| CharPointer_ASCII findEndOfWhitespace() const throw() { return CharacterFunctions::findEndOfWhitespace (*this); } | |||
| /** Returns true if the given unicode character can be represented in this encoding. */ | |||
| static bool canRepresent (juce_wchar character) throw() | |||
| { | |||
| return ((unsigned int) character) < (unsigned int) 128; | |||
| } | |||
| /** Returns true if this data contains a valid string in this encoding. */ | |||
| static bool isValidString (const CharType* dataToTest, int maxBytesToRead) | |||
| { | |||
| while (--maxBytesToRead >= 0) | |||
| { | |||
| if (*dataToTest <= 0) | |||
| return *dataToTest == 0; | |||
| ++dataToTest; | |||
| } | |||
| return true; | |||
| } | |||
| private: | |||
| CharType* data; | |||
| }; | |||
| #endif // __JUCE_CHARPOINTER_ASCII_JUCEHEADER__ | |||
| @@ -395,6 +395,43 @@ public: | |||
| /** Returns the first non-whitespace character in the string. */ | |||
| CharPointer_UTF16 findEndOfWhitespace() const throw() { return CharacterFunctions::findEndOfWhitespace (*this); } | |||
| /** Returns true if the given unicode character can be represented in this encoding. */ | |||
| static bool canRepresent (juce_wchar character) throw() | |||
| { | |||
| return ((unsigned int) character) < (unsigned int) 0x10ffff | |||
| && (((unsigned int) character) < 0xd800 || ((unsigned int) character) > 0xdfff); | |||
| } | |||
| /** Returns true if this data contains a valid string in this encoding. */ | |||
| static bool isValidString (const CharType* dataToTest, int maxBytesToRead) | |||
| { | |||
| maxBytesToRead /= sizeof (CharType); | |||
| while (--maxBytesToRead >= 0 && *dataToTest != 0) | |||
| { | |||
| const uint32 n = (uint32) (uint16) *dataToTest++; | |||
| if (n >= 0xd800) | |||
| { | |||
| if (n > 0x10ffff) | |||
| return false; | |||
| if (n <= 0xdfff) | |||
| { | |||
| if (n > 0xdc00) | |||
| return false; | |||
| const uint32 nextChar = (uint32) (uint16) *dataToTest++; | |||
| if (nextChar < 0xdc00 || nextChar > 0xdfff) | |||
| return false; | |||
| } | |||
| } | |||
| } | |||
| return true; | |||
| } | |||
| /** These values are the byte-order-mark (BOM) values for a UTF-16 stream. */ | |||
| enum | |||
| { | |||
| @@ -106,7 +106,7 @@ public: | |||
| CharPointer_UTF32 operator++ (int) throw() | |||
| { | |||
| CharPointer_UTF32 temp (*this); | |||
| ++*this; | |||
| ++data; | |||
| return temp; | |||
| } | |||
| @@ -341,6 +341,25 @@ public: | |||
| /** Returns the first non-whitespace character in the string. */ | |||
| CharPointer_UTF32 findEndOfWhitespace() const throw() { return CharacterFunctions::findEndOfWhitespace (*this); } | |||
| /** Returns true if the given unicode character can be represented in this encoding. */ | |||
| static bool canRepresent (juce_wchar character) throw() | |||
| { | |||
| return ((unsigned int) character) < (unsigned int) 0x10ffff; | |||
| } | |||
| /** Returns true if this data contains a valid string in this encoding. */ | |||
| static bool isValidString (const CharType* dataToTest, int maxBytesToRead) | |||
| { | |||
| maxBytesToRead /= sizeof (CharType); | |||
| while (--maxBytesToRead >= 0 && *dataToTest != 0) | |||
| if (! canRepresent (*dataToTest++)) | |||
| return false; | |||
| return true; | |||
| } | |||
| /** Atomically swaps this pointer for a new value, returning the previous value. */ | |||
| CharPointer_UTF32 atomicSwap (const CharPointer_UTF32& newValue) | |||
| { | |||
| return CharPointer_UTF32 (reinterpret_cast <Atomic<CharType*>&> (data).exchange (newValue.data)); | |||
| @@ -88,9 +88,9 @@ public: | |||
| if (byte >= 0) | |||
| return byte; | |||
| juce_wchar n = byte; | |||
| juce_wchar mask = 0x7f; | |||
| juce_wchar bit = 0x40; | |||
| uint32 n = (uint32) (uint8) byte; | |||
| uint32 mask = 0x7f; | |||
| uint32 bit = 0x40; | |||
| size_t numExtraValues = 0; | |||
| while ((n & bit) != 0 && bit > 0x10) | |||
| @@ -113,7 +113,7 @@ public: | |||
| n |= (nextByte & 0x3f); | |||
| } | |||
| return n; | |||
| return (juce_wchar) n; | |||
| } | |||
| /** Moves this pointer along to the next character in the string. */ | |||
| @@ -473,6 +473,51 @@ public: | |||
| /** Returns the first non-whitespace character in the string. */ | |||
| CharPointer_UTF8 findEndOfWhitespace() const throw() { return CharacterFunctions::findEndOfWhitespace (*this); } | |||
| /** Returns true if the given unicode character can be represented in this encoding. */ | |||
| static bool canRepresent (juce_wchar character) throw() | |||
| { | |||
| return ((unsigned int) character) < (unsigned int) 0x10ffff; | |||
| } | |||
| /** Returns true if this data contains a valid string in this encoding. */ | |||
| static bool isValidString (const CharType* dataToTest, int maxBytesToRead) | |||
| { | |||
| while (--maxBytesToRead >= 0 && *dataToTest != 0) | |||
| { | |||
| const char byte = *dataToTest; | |||
| if (byte < 0) | |||
| { | |||
| uint32 n = (uint32) (uint8) byte; | |||
| uint32 mask = 0x7f; | |||
| uint32 bit = 0x40; | |||
| int numExtraValues = 0; | |||
| while ((n & bit) != 0) | |||
| { | |||
| if (bit <= 0x10) | |||
| return false; | |||
| mask >>= 1; | |||
| ++numExtraValues; | |||
| bit >>= 1; | |||
| } | |||
| n &= mask; | |||
| while (--numExtraValues >= 0) | |||
| { | |||
| const uint32 nextByte = (uint32) (uint8) *dataToTest++; | |||
| if ((nextByte & 0xc0) != 0x80) | |||
| return false; | |||
| } | |||
| } | |||
| } | |||
| return true; | |||
| } | |||
| /** These values are the byte-order-mark (BOM) values for a UTF-8 stream. */ | |||
| enum | |||
| { | |||
| @@ -40,6 +40,7 @@ | |||
| BEGIN_JUCE_NAMESPACE | |||
| #include "juce_String.h" | |||
| #include "../memory/juce_HeapBlock.h" | |||
| //============================================================================== | |||
| juce_wchar CharacterFunctions::toUpperCase (const juce_wchar character) throw() | |||
| @@ -250,8 +250,41 @@ String::String (const String& stringToCopy, const size_t charsToAllocate) | |||
| } | |||
| String::String (const char* const t) | |||
| : text (StringHolder::createFromCharPointer (CharPointer_UTF8 (t))) | |||
| : text (StringHolder::createFromCharPointer (CharPointer_ASCII (t))) | |||
| { | |||
| /* If you get an assertion here, then you're trying to create a string from 8-bit data | |||
| that contains values greater than 127. These can NOT be correctly converted to unicode | |||
| because there's no way for the String class to know what encoding was used to | |||
| create them. The source data could be UTF-8, ASCII or one of many local code-pages. | |||
| To get around this problem, you must be more explicit when you pass an ambiguous 8-bit | |||
| string to the String class - so for example if your source data is actually UTF-8, | |||
| you'd call String (CharPointer_UTF8 ("my utf8 string..")), and it would be able to | |||
| correctly convert the multi-byte characters to unicode. It's *highly* recommended that | |||
| you use UTF-8 with escape characters in your source code to represent extended characters, | |||
| because there's no other way to represent these strings in a way that isn't dependent on | |||
| the compiler, source code editor and platform. | |||
| */ | |||
| jassert (CharPointer_ASCII::isValidString (t, std::numeric_limits<int>::max())); | |||
| } | |||
| String::String (const char* const t, const size_t maxChars) | |||
| : text (StringHolder::createFromCharPointer (CharPointer_ASCII (t), maxChars)) | |||
| { | |||
| /* If you get an assertion here, then you're trying to create a string from 8-bit data | |||
| that contains values greater than 127. These can NOT be correctly converted to unicode | |||
| because there's no way for the String class to know what encoding was used to | |||
| create them. The source data could be UTF-8, ASCII or one of many local code-pages. | |||
| To get around this problem, you must be more explicit when you pass an ambiguous 8-bit | |||
| string to the String class - so for example if your source data is actually UTF-8, | |||
| you'd call String (CharPointer_UTF8 ("my utf8 string..")), and it would be able to | |||
| correctly convert the multi-byte characters to unicode. It's *highly* recommended that | |||
| you use UTF-8 with escape characters in your source code to represent extended characters, | |||
| because there's no other way to represent these strings in a way that isn't dependent on | |||
| the compiler, source code editor and platform. | |||
| */ | |||
| jassert (CharPointer_ASCII::isValidString (t, (int) maxChars)); | |||
| } | |||
| String::String (const juce_wchar* const t) | |||
| @@ -259,6 +292,11 @@ String::String (const juce_wchar* const t) | |||
| { | |||
| } | |||
| String::String (const juce_wchar* const t, const size_t maxChars) | |||
| : text (StringHolder::createFromCharPointer (CharPointer_UTF32 (t), maxChars)) | |||
| { | |||
| } | |||
| String::String (const CharPointer_UTF8& t) | |||
| : text (StringHolder::createFromCharPointer (t)) | |||
| { | |||
| @@ -279,6 +317,11 @@ String::String (const CharPointer_UTF32& t, const size_t maxChars) | |||
| { | |||
| } | |||
| String::String (const CharPointer_ASCII& t) | |||
| : text (StringHolder::createFromCharPointer (t)) | |||
| { | |||
| } | |||
| #if JUCE_WINDOWS | |||
| String::String (const wchar_t* const t) | |||
| : text (StringHolder::createFromCharPointer (CharPointer_UTF16 (t))) | |||
| @@ -291,16 +334,6 @@ String::String (const wchar_t* const t, size_t maxChars) | |||
| } | |||
| #endif | |||
| String::String (const char* const t, const size_t maxChars) | |||
| : text (StringHolder::createFromCharPointer (CharPointer_UTF8 (t), maxChars)) | |||
| { | |||
| } | |||
| String::String (const juce_wchar* const t, const size_t maxChars) | |||
| : text (StringHolder::createFromCharPointer (CharPointer_UTF32 (t), maxChars)) | |||
| { | |||
| } | |||
| const String String::charToString (const juce_wchar character) | |||
| { | |||
| String result (Preallocation (1)); | |||
| @@ -679,7 +712,7 @@ String& String::operator+= (const juce_wchar ch) | |||
| } | |||
| #if JUCE_WINDOWS | |||
| String& String::operator+= (wchar_t ch) | |||
| String& String::operator+= (const wchar_t ch) | |||
| { | |||
| return operator+= ((juce_wchar) ch); | |||
| } | |||
| @@ -37,6 +37,7 @@ | |||
| #include "juce_CharPointer_UTF8.h" | |||
| #include "juce_CharPointer_UTF16.h" | |||
| #include "juce_CharPointer_UTF32.h" | |||
| #include "juce_CharPointer_ASCII.h" | |||
| #if JUCE_MSVC | |||
| #pragma warning (pop) | |||
| @@ -60,7 +61,6 @@ class JUCE_API String | |||
| public: | |||
| //============================================================================== | |||
| /** Creates an empty string. | |||
| @see empty | |||
| */ | |||
| String() throw(); | |||
| @@ -68,15 +68,36 @@ public: | |||
| /** Creates a copy of another string. */ | |||
| String (const String& other) throw(); | |||
| /** Creates a string from a zero-terminated text string. | |||
| The string is assumed to be stored in the default system encoding. | |||
| /** Creates a string from a zero-terminated ascii text string. | |||
| The string passed-in must not contain any characters with a value above 127, because | |||
| these can't be converted to unicode without knowing the original encoding that was | |||
| used to create the string. If you attempt to pass-in values above 127, you'll get an | |||
| assertion. | |||
| To create strings with extended characters from UTF-8, you should explicitly call | |||
| String (CharPointer_UTF8 ("my utf8 string..")). It's *highly* recommended that you | |||
| use UTF-8 with escape characters in your source code to represent extended characters, | |||
| because there's no other way to represent unicode strings in a way that isn't dependent | |||
| on the compiler, source code editor and platform. | |||
| */ | |||
| String (const char* text); | |||
| /** Creates a string from an string of characters. | |||
| /** Creates a string from a string of 8-bit ascii characters. | |||
| This will use up the the first maxChars characters of the string (or | |||
| less if the string is actually shorter) | |||
| The string passed-in must not contain any characters with a value above 127, because | |||
| these can't be converted to unicode without knowing the original encoding that was | |||
| used to create the string. If you attempt to pass-in values above 127, you'll get an | |||
| assertion. | |||
| To create strings with extended characters from UTF-8, you should explicitly call | |||
| String (CharPointer_UTF8 ("my utf8 string..")). It's *highly* recommended that you | |||
| use UTF-8 with escape characters in your source code to represent extended characters, | |||
| because there's no other way to represent unicode strings in a way that isn't dependent | |||
| on the compiler, source code editor and platform. | |||
| This will use up the the first maxChars characters of the string (or less if the string | |||
| is actually shorter). | |||
| */ | |||
| String (const char* text, size_t maxChars); | |||
| @@ -102,6 +123,9 @@ public: | |||
| /** Creates a string from a UTF-32 character string */ | |||
| String (const CharPointer_UTF32& text, size_t maxChars); | |||
| /** Creates a string from an ASCII character string */ | |||
| String (const CharPointer_ASCII& text); | |||
| #if JUCE_WINDOWS | |||
| /** Creates a string from a UTF-16 character string */ | |||
| String (const wchar_t* text); | |||
| @@ -124,7 +124,7 @@ XmlElement* XmlDocument::getDocumentElement (const bool onlyReadOuterDocumentEle | |||
| } | |||
| } | |||
| input = static_cast <const juce_wchar*> (textToParse); | |||
| input = textToParse.getCharPointer(); | |||
| lastError = String::empty; | |||
| errorOccurred = false; | |||
| outOfData = false; | |||
| @@ -235,7 +235,7 @@ void XmlDocument::skipHeader() | |||
| return; | |||
| input += docTypeIndex + 9; | |||
| const CharPointer_UTF32 docType (input); | |||
| const String::CharPointerType docType (input); | |||
| int n = 1; | |||
| @@ -324,7 +324,7 @@ void XmlDocument::readQuotedString (String& result) | |||
| else | |||
| { | |||
| --input; | |||
| const CharPointer_UTF32 start (input); | |||
| const String::CharPointerType start (input); | |||
| for (;;) | |||
| { | |||
| @@ -332,14 +332,14 @@ void XmlDocument::readQuotedString (String& result) | |||
| if (character == quote) | |||
| { | |||
| result.append (start.getAddress(), (int) (input.getAddress() - start.getAddress())); | |||
| result.appendCharPointer (start, (int) (input.getAddress() - start.getAddress())); | |||
| ++input; | |||
| return; | |||
| } | |||
| else if (character == '&') | |||
| { | |||
| result.append (start.getAddress(), (int) (input.getAddress() - start.getAddress())); | |||
| result.appendCharPointer (start, (int) (input.getAddress() - start.getAddress())); | |||
| break; | |||
| } | |||
| else if (character == 0) | |||
| @@ -419,7 +419,7 @@ XmlElement* XmlDocument::readNextElement (const bool alsoParseSubElements) | |||
| if (attNameLen > 0) | |||
| { | |||
| const CharPointer_UTF32 attNameStart (input); | |||
| const String::CharPointerType attNameStart (input); | |||
| input += attNameLen; | |||
| skipNextWhiteSpace(); | |||
| @@ -462,7 +462,7 @@ void XmlDocument::readChildElements (XmlElement* parent) | |||
| for (;;) | |||
| { | |||
| const CharPointer_UTF32 preWhitespaceInput (input); | |||
| const String::CharPointerType preWhitespaceInput (input); | |||
| skipNextWhiteSpace(); | |||
| if (outOfData) | |||
| @@ -493,7 +493,7 @@ void XmlDocument::readChildElements (XmlElement* parent) | |||
| && input[8] == '[') | |||
| { | |||
| input += 9; | |||
| const CharPointer_UTF32 inputStart (input); | |||
| const String::CharPointerType inputStart (input); | |||
| int len = 0; | |||
| @@ -556,10 +556,10 @@ void XmlDocument::readChildElements (XmlElement* parent) | |||
| if (entity.startsWithChar ('<') && entity [1] != 0) | |||
| { | |||
| const CharPointer_UTF32 oldInput (input); | |||
| const String::CharPointerType oldInput (input); | |||
| const bool oldOutOfData = outOfData; | |||
| input = static_cast <const juce_wchar*> (entity); | |||
| input = entity.getCharPointer(); | |||
| outOfData = false; | |||
| for (;;) | |||
| @@ -582,7 +582,7 @@ void XmlDocument::readChildElements (XmlElement* parent) | |||
| } | |||
| else | |||
| { | |||
| const CharPointer_UTF32 start (input); | |||
| const String::CharPointerType start (input); | |||
| int len = 0; | |||
| for (;;) | |||
| @@ -701,7 +701,7 @@ void XmlDocument::readEntity (String& result) | |||
| } | |||
| else | |||
| { | |||
| const CharPointer_UTF32 entityNameStart (input); | |||
| const String::CharPointerType entityNameStart (input); | |||
| const int closingSemiColon = input.indexOf ((juce_wchar) ';'); | |||
| if (closingSemiColon < 0) | |||
| @@ -153,7 +153,7 @@ public: | |||
| //============================================================================== | |||
| private: | |||
| String originalText; | |||
| CharPointer_UTF32 input; | |||
| String::CharPointerType input; | |||
| bool outOfData, errorOccurred; | |||
| String lastError, dtdText; | |||