| @@ -86,6 +86,7 @@ | |||
| F2F98DA41146390D05A44EAD = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = jucer_ProjectContentComponent.h; path = ../../Source/Project/jucer_ProjectContentComponent.h; sourceTree = SOURCE_ROOT; }; | |||
| 296E0498784BF03FA18B164B = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = jucer_ProjectExporter.cpp; path = ../../Source/Project/jucer_ProjectExporter.cpp; sourceTree = SOURCE_ROOT; }; | |||
| 5DE419991013E7C0F203E99F = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = jucer_ProjectExporter.h; path = ../../Source/Project/jucer_ProjectExporter.h; sourceTree = SOURCE_ROOT; }; | |||
| AB9EE4734D894FBF1CF62C5F = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = jucer_ProjectExport_Android.h; path = ../../Source/Project/jucer_ProjectExport_Android.h; sourceTree = SOURCE_ROOT; }; | |||
| 889715B0152919B2EAA1F5F9 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = jucer_ProjectExport_Make.h; path = ../../Source/Project/jucer_ProjectExport_Make.h; sourceTree = SOURCE_ROOT; }; | |||
| 907F302BB89308CDB2C5FD0E = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = jucer_ProjectExport_MSVC.h; path = ../../Source/Project/jucer_ProjectExport_MSVC.h; sourceTree = SOURCE_ROOT; }; | |||
| D250274734D729D2E0389A20 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = jucer_ProjectExport_XCode.h; path = ../../Source/Project/jucer_ProjectExport_XCode.h; sourceTree = SOURCE_ROOT; }; | |||
| @@ -165,6 +166,7 @@ | |||
| F2F98DA41146390D05A44EAD, | |||
| 296E0498784BF03FA18B164B, | |||
| 5DE419991013E7C0F203E99F, | |||
| AB9EE4734D894FBF1CF62C5F, | |||
| 889715B0152919B2EAA1F5F9, | |||
| 907F302BB89308CDB2C5FD0E, | |||
| D250274734D729D2E0389A20, | |||
| @@ -162,6 +162,7 @@ | |||
| <File RelativePath="..\..\Source\Project\jucer_ProjectContentComponent.h"/> | |||
| <File RelativePath="..\..\Source\Project\jucer_ProjectExporter.cpp"/> | |||
| <File RelativePath="..\..\Source\Project\jucer_ProjectExporter.h"/> | |||
| <File RelativePath="..\..\Source\Project\jucer_ProjectExport_Android.h"/> | |||
| <File RelativePath="..\..\Source\Project\jucer_ProjectExport_Make.h"/> | |||
| <File RelativePath="..\..\Source\Project\jucer_ProjectExport_MSVC.h"/> | |||
| <File RelativePath="..\..\Source\Project\jucer_ProjectExport_XCode.h"/> | |||
| @@ -162,6 +162,7 @@ | |||
| <File RelativePath="..\..\Source\Project\jucer_ProjectContentComponent.h"/> | |||
| <File RelativePath="..\..\Source\Project\jucer_ProjectExporter.cpp"/> | |||
| <File RelativePath="..\..\Source\Project\jucer_ProjectExporter.h"/> | |||
| <File RelativePath="..\..\Source\Project\jucer_ProjectExport_Android.h"/> | |||
| <File RelativePath="..\..\Source\Project\jucer_ProjectExport_Make.h"/> | |||
| <File RelativePath="..\..\Source\Project\jucer_ProjectExport_MSVC.h"/> | |||
| <File RelativePath="..\..\Source\Project\jucer_ProjectExport_XCode.h"/> | |||
| @@ -167,6 +167,7 @@ | |||
| <ClInclude Include="..\..\Source\Project\jucer_Project.h"/> | |||
| <ClInclude Include="..\..\Source\Project\jucer_ProjectContentComponent.h"/> | |||
| <ClInclude Include="..\..\Source\Project\jucer_ProjectExporter.h"/> | |||
| <ClInclude Include="..\..\Source\Project\jucer_ProjectExport_Android.h"/> | |||
| <ClInclude Include="..\..\Source\Project\jucer_ProjectExport_Make.h"/> | |||
| <ClInclude Include="..\..\Source\Project\jucer_ProjectExport_MSVC.h"/> | |||
| <ClInclude Include="..\..\Source\Project\jucer_ProjectExport_XCode.h"/> | |||
| @@ -183,6 +183,9 @@ | |||
| <ClInclude Include="..\..\Source\Project\jucer_ProjectExporter.h"> | |||
| <Filter>The Jucer\Project</Filter> | |||
| </ClInclude> | |||
| <ClInclude Include="..\..\Source\Project\jucer_ProjectExport_Android.h"> | |||
| <Filter>The Jucer\Project</Filter> | |||
| </ClInclude> | |||
| <ClInclude Include="..\..\Source\Project\jucer_ProjectExport_Make.h"> | |||
| <Filter>The Jucer\Project</Filter> | |||
| </ClInclude> | |||
| @@ -90,6 +90,8 @@ | |||
| file="Source/Project/jucer_ProjectExporter.cpp"/> | |||
| <FILE id="KFY4Re5" name="jucer_ProjectExporter.h" compile="0" resource="0" | |||
| file="Source/Project/jucer_ProjectExporter.h"/> | |||
| <FILE id="N0uQAr" name="jucer_ProjectExport_Android.h" compile="0" | |||
| resource="0" file="Source/Project/jucer_ProjectExport_Android.h"/> | |||
| <FILE id="b8ouh7s" name="jucer_ProjectExport_Make.h" compile="0" resource="0" | |||
| file="Source/Project/jucer_ProjectExport_Make.h"/> | |||
| <FILE id="lbo8KcG" name="jucer_ProjectExport_MSVC.h" compile="0" resource="0" | |||
| @@ -448,6 +448,43 @@ const Image Project::getSmallIcon() | |||
| return Image(); | |||
| } | |||
| const Image Project::getBestIconForSize (int size, bool returnNullIfNothingBigEnough) | |||
| { | |||
| Image im; | |||
| const Image im1 (getSmallIcon()); | |||
| const Image im2 (getBigIcon()); | |||
| if (im1.isValid() && im2.isValid()) | |||
| { | |||
| if (im1.getWidth() >= size && im2.getWidth() >= size) | |||
| im = im1.getWidth() < im2.getWidth() ? im1 : im2; | |||
| else if (im1.getWidth() >= size) | |||
| im = im1; | |||
| else if (im2.getWidth() >= size) | |||
| im = im2; | |||
| else | |||
| return Image(); | |||
| } | |||
| else | |||
| { | |||
| im = im1.isValid() ? im1 : im2; | |||
| } | |||
| if (size == im.getWidth() && size == im.getHeight()) | |||
| return im; | |||
| if (returnNullIfNothingBigEnough && im.getWidth() < size && im.getHeight() < size) | |||
| return Image::null; | |||
| Image newIm (Image::ARGB, size, size, true); | |||
| Graphics g (newIm); | |||
| g.drawImageWithin (im, 0, 0, size, size, | |||
| RectanglePlacement::centred | RectanglePlacement::onlyReduceInSize, false); | |||
| return newIm; | |||
| } | |||
| const StringPairArray Project::getPreprocessorDefs() const | |||
| { | |||
| return parsePreprocessorDefs (getProjectPreprocessorDefs().toString()); | |||
| @@ -109,6 +109,7 @@ public: | |||
| Value getSmallIconImageItemID() const { return getProjectValue ("smallIcon"); } | |||
| const Image getBigIcon(); | |||
| const Image getSmallIcon(); | |||
| const Image getBestIconForSize (int size, bool returnNullIfNothingBigEnough); | |||
| Value shouldBuildVST() const { return getProjectValue ("buildVST"); } | |||
| Value shouldBuildRTAS() const { return getProjectValue ("buildRTAS"); } | |||
| @@ -0,0 +1,374 @@ | |||
| /* | |||
| ============================================================================== | |||
| 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 __JUCER_PROJECTEXPORT_ANDROID_JUCEHEADER__ | |||
| #define __JUCER_PROJECTEXPORT_ANDROID_JUCEHEADER__ | |||
| #include "jucer_ProjectExporter.h" | |||
| //============================================================================== | |||
| class AndroidProjectExporter : public ProjectExporter | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| static const char* getNameAndroid() { return "Android Project"; } | |||
| static const char* getValueTreeTypeName() { return "ANDROID"; } | |||
| static AndroidProjectExporter* createForSettings (Project& project, const ValueTree& settings) | |||
| { | |||
| if (settings.hasType (getValueTreeTypeName())) | |||
| return new AndroidProjectExporter (project, settings); | |||
| return 0; | |||
| } | |||
| //============================================================================== | |||
| AndroidProjectExporter (Project& project_, const ValueTree& settings_) | |||
| : ProjectExporter (project_, settings_) | |||
| { | |||
| name = getNameAndroid(); | |||
| if (getTargetLocation().toString().isEmpty()) | |||
| getTargetLocation() = getDefaultBuildsRootFolder() + "Android"; | |||
| if (getSDKPath().toString().isEmpty()) | |||
| getSDKPath() = "${user.home}/SDKs/android-sdk-mac_86"; | |||
| if (getNDKPath().toString().isEmpty()) | |||
| getNDKPath() = "${user.home}/SDKs/android-ndk-r4-crystax"; | |||
| } | |||
| //============================================================================== | |||
| bool isDefaultFormatForCurrentOS() | |||
| { | |||
| #if JUCE_ANDROID | |||
| return true; | |||
| #else | |||
| return false; | |||
| #endif | |||
| } | |||
| bool isPossibleForCurrentProject() { return project.isGUIApplication(); } | |||
| bool usesMMFiles() const { return false; } | |||
| void launchProject() | |||
| { | |||
| } | |||
| void createPropertyEditors (Array <PropertyComponent*>& props) | |||
| { | |||
| ProjectExporter::createPropertyEditors (props); | |||
| props.add (new TextPropertyComponent (getSDKPath(), "Android SDK Path", 1024, false)); | |||
| props.getLast()->setTooltip ("The path to the Android SDK folder on the target build machine"); | |||
| props.add (new TextPropertyComponent (getNDKPath(), "Android NDK Path", 1024, false)); | |||
| props.getLast()->setTooltip ("The path to the Android NDK folder on the target build machine"); | |||
| } | |||
| Value getSDKPath() const { return getSetting (Ids::androidSDKPath); } | |||
| Value getNDKPath() const { return getSetting (Ids::androidNDKPath); } | |||
| //============================================================================== | |||
| void create() | |||
| { | |||
| const File target (getTargetFolder()); | |||
| const File jniFolder (target.getChildFile ("jni")); | |||
| createDirectoryOrThrow (target.getChildFile ("src/com")); | |||
| createDirectoryOrThrow (jniFolder); | |||
| createDirectoryOrThrow (target.getChildFile ("res/drawable-hdpi")); | |||
| createDirectoryOrThrow (target.getChildFile ("res/drawable-mdpi")); | |||
| createDirectoryOrThrow (target.getChildFile ("res/drawable-ldpi")); | |||
| createDirectoryOrThrow (target.getChildFile ("res/values")); | |||
| createDirectoryOrThrow (target.getChildFile ("libs")); | |||
| createDirectoryOrThrow (target.getChildFile ("bin")); | |||
| { | |||
| ScopedPointer<XmlElement> manifest (createManifestXML()); | |||
| writeXmlOrThrow (*manifest, target.getChildFile ("AndroidManifest.xml"), "utf-8", 100); | |||
| } | |||
| writeJNIMakefile (jniFolder.getChildFile ("Android.mk")); | |||
| { | |||
| ScopedPointer<XmlElement> antBuildXml (createAntBuildXML()); | |||
| writeXmlOrThrow (*antBuildXml, target.getChildFile ("build.xml"), "UTF-8", 100); | |||
| } | |||
| writeBuildPropertiesFile (target.getChildFile ("build.properties")); | |||
| writeDefaultPropertiesFile (target.getChildFile ("default.properties")); | |||
| writeLocalPropertiesFile (target.getChildFile ("local.properties")); | |||
| writeIcon (target.getChildFile ("res/drawable-hdpi/icon.png"), 72); | |||
| writeIcon (target.getChildFile ("res/drawable-mdpi/icon.png"), 48); | |||
| writeIcon (target.getChildFile ("res/drawable-ldpi/icon.png"), 36); | |||
| writeStringsFile (target.getChildFile ("res/values/strings.xml")); | |||
| } | |||
| private: | |||
| //============================================================================== | |||
| XmlElement* createManifestXML() | |||
| { | |||
| XmlElement* manifest = new XmlElement ("manifest"); | |||
| manifest->setAttribute ("xmlns:android", "http://schemas.android.com/apk/res/android"); | |||
| manifest->setAttribute ("android:versionCode", "1"); | |||
| manifest->setAttribute ("android:versionName", "1.0"); | |||
| manifest->setAttribute ("package", "com.juce"); | |||
| XmlElement* screens = manifest->createNewChildElement ("supports-screens"); | |||
| screens->setAttribute ("android:smallScreens", "true"); | |||
| screens->setAttribute ("android:normalScreens", "true"); | |||
| screens->setAttribute ("android:largeScreens", "true"); | |||
| screens->setAttribute ("android:xlargeScreens", "true"); | |||
| screens->setAttribute ("android:anyDensity", "true"); | |||
| XmlElement* app = manifest->createNewChildElement ("application"); | |||
| app->setAttribute ("android:label", "@string/app_name"); | |||
| app->setAttribute ("android:icon", "@drawable/icon"); | |||
| XmlElement* act = app->createNewChildElement ("activity"); | |||
| act->setAttribute ("android:name", "JuceAppActivity"); | |||
| act->setAttribute ("android:label", "@string/app_name"); | |||
| XmlElement* intent = act->createNewChildElement ("intent-filter"); | |||
| intent->createNewChildElement ("action")->setAttribute ("android:name", "android.intent.action.MAIN"); | |||
| intent->createNewChildElement ("category")->setAttribute ("android:name", "android.intent.category.LAUNCHER"); | |||
| return manifest; | |||
| } | |||
| //============================================================================== | |||
| void findAllFilesToCompile (const Project::Item& projectItem, Array<RelativePath>& results) | |||
| { | |||
| if (projectItem.isGroup()) | |||
| { | |||
| for (int i = 0; i < projectItem.getNumChildren(); ++i) | |||
| findAllFilesToCompile (projectItem.getChild(i), results); | |||
| } | |||
| else | |||
| { | |||
| if (projectItem.shouldBeCompiled()) | |||
| results.add (RelativePath (projectItem.getFile(), getTargetFolder(), RelativePath::buildTargetFolder)); | |||
| } | |||
| } | |||
| void writeJNIMakefile (const File& file) | |||
| { | |||
| Array<RelativePath> files; | |||
| findAllFilesToCompile (project.getMainGroup(), files); | |||
| for (int i = 0; i < juceWrapperFiles.size(); ++i) | |||
| if (shouldFileBeCompiledByDefault (juceWrapperFiles.getReference(i))) | |||
| files.add (juceWrapperFiles.getReference(i)); | |||
| MemoryOutputStream mo; | |||
| writeJNIMakefile (mo, files); | |||
| overwriteFileIfDifferentOrThrow (file, mo); | |||
| } | |||
| void writeJNIMakefile (OutputStream& out, const Array<RelativePath>& files) | |||
| { | |||
| out << "# Automatically generated makefile, created by the Jucer" << newLine | |||
| << "# Don't edit this file! Your changes will be overwritten when you re-save the Jucer project!" << newLine | |||
| << newLine | |||
| << "LOCAL_PATH := $(call my-dir)" << newLine | |||
| << newLine | |||
| << "include $(CLEAR_VARS)" << newLine | |||
| << newLine | |||
| << "LOCAL_CPP_EXTENSION := cpp" << newLine | |||
| << "LOCAL_MODULE := juce_jni" << newLine | |||
| << "LOCAL_SRC_FILES := \\" << newLine; | |||
| for (int i = 0; i < files.size(); ++i) | |||
| out << " ../" << escapeSpaces (files.getReference(i).toUnixStyle()) << "\\" << newLine; | |||
| out << newLine | |||
| << "ifeq ($(CONFIG),Debug)" << newLine | |||
| << " LOCAL_CFLAGS +=" << createPreprocessorDefs (true) << newLine | |||
| << "else" << newLine | |||
| << " LOCAL_CFLAGS +=" << createPreprocessorDefs (false) << newLine | |||
| << "endif" << newLine | |||
| << newLine | |||
| << "include $(BUILD_SHARED_LIBRARY)" << newLine; | |||
| } | |||
| const String createPreprocessorDefs (bool forDebug) | |||
| { | |||
| StringPairArray defines; | |||
| defines.set ("JUCE_ANDROID", "1"); | |||
| if (forDebug) | |||
| { | |||
| defines.set ("DEBUG", "1"); | |||
| defines.set ("_DEBUG", "1"); | |||
| } | |||
| else | |||
| { | |||
| defines.set ("NDEBUG", "1"); | |||
| } | |||
| for (int i = 0; i < project.getNumConfigurations(); ++i) | |||
| { | |||
| Project::BuildConfiguration config (project.getConfiguration(i)); | |||
| if (config.isDebug() == forDebug) | |||
| { | |||
| defines = mergePreprocessorDefs (defines, getAllPreprocessorDefs (config)); | |||
| break; | |||
| } | |||
| } | |||
| return createGCCPreprocessorFlags (defines); | |||
| } | |||
| //============================================================================== | |||
| XmlElement* createAntBuildXML() | |||
| { | |||
| XmlElement* proj = new XmlElement ("project"); | |||
| proj->setAttribute ("name", project.getProjectName().toString()); | |||
| proj->setAttribute ("default", "help"); | |||
| proj->createNewChildElement ("property")->setAttribute ("file", "local.properties"); | |||
| proj->createNewChildElement ("property")->setAttribute ("file", "build.properties"); | |||
| proj->createNewChildElement ("property")->setAttribute ("file", "default.properties"); | |||
| XmlElement* path = proj->createNewChildElement ("path"); | |||
| path->setAttribute ("id", "android.antlibs"); | |||
| path->createNewChildElement ("pathelement")->setAttribute ("path", "${sdk.dir}/tools/lib/anttasks.jar"); | |||
| path->createNewChildElement ("pathelement")->setAttribute ("path", "${sdk.dir}/tools/lib/sdklib.jar"); | |||
| path->createNewChildElement ("pathelement")->setAttribute ("path", "${sdk.dir}/tools/lib/androidprefs.jar"); | |||
| XmlElement* taskdef = proj->createNewChildElement ("taskdef"); | |||
| taskdef->setAttribute ("name", "setup"); | |||
| taskdef->setAttribute ("classname", "com.android.ant.SetupTask"); | |||
| taskdef->setAttribute ("classpathref", "android.antlibs"); | |||
| addNDKBuildStep (proj, "clean", "clean"); | |||
| //addLinkStep (proj, "${basedir}/" + rebaseFromProjectFolderToBuildTarget (RelativePath()).toUnixStyle() + "/", "jni/app"); | |||
| addLinkStep (proj, "${basedir}/" + getJucePathFromTargetFolder().toUnixStyle() + "/src/native/android/java/", "src/com/juce"); | |||
| addNDKBuildStep (proj, "debug", "CONFIG=Debug"); | |||
| addNDKBuildStep (proj, "release", "CONFIG=Release"); | |||
| proj->createNewChildElement ("setup"); | |||
| return proj; | |||
| } | |||
| static void addNDKBuildStep (XmlElement* project, const String& type, const String& arg) | |||
| { | |||
| XmlElement* target = project->createNewChildElement ("target"); | |||
| target->setAttribute ("name", type); | |||
| XmlElement* executable = target->createNewChildElement ("exec"); | |||
| executable->setAttribute ("executable", "${ndk.dir}/ndk-build"); | |||
| executable->setAttribute ("dir", "${basedir}"); | |||
| executable->setAttribute ("failonerror", "true"); | |||
| executable->createNewChildElement ("arg")->setAttribute ("value", arg); | |||
| } | |||
| static void addLinkStep (XmlElement* project, const String& from, const String& to) | |||
| { | |||
| XmlElement* executable = project->createNewChildElement ("exec"); | |||
| executable->setAttribute ("executable", "ln"); | |||
| executable->setAttribute ("dir", "${basedir}"); | |||
| executable->setAttribute ("failonerror", "false"); | |||
| executable->createNewChildElement ("arg")->setAttribute ("value", "-s"); | |||
| executable->createNewChildElement ("arg")->setAttribute ("value", from); | |||
| executable->createNewChildElement ("arg")->setAttribute ("value", to); | |||
| } | |||
| void writeBuildPropertiesFile (const File& file) | |||
| { | |||
| MemoryOutputStream mo; | |||
| mo << "# This file is used to override default values used by the Ant build system." << newLine; | |||
| overwriteFileIfDifferentOrThrow (file, mo); | |||
| } | |||
| void writeDefaultPropertiesFile (const File& file) | |||
| { | |||
| MemoryOutputStream mo; | |||
| mo << "# This file is used to override default values used by the Ant build system." << newLine | |||
| << "# It is automatically generated - DO NOT EDIT IT or your changes will be lost!." << newLine | |||
| << newLine | |||
| << "target=android-9" | |||
| << newLine; | |||
| overwriteFileIfDifferentOrThrow (file, mo); | |||
| } | |||
| void writeLocalPropertiesFile (const File& file) | |||
| { | |||
| MemoryOutputStream mo; | |||
| mo << "# This file is used to override default values used by the Ant build system." << newLine | |||
| << "# It is automatically generated by the Jucer - DO NOT EDIT IT or your changes will be lost!." << newLine | |||
| << newLine | |||
| << "sdk.dir=" << escapeSpaces (replacePreprocessorDefs (getAllPreprocessorDefs(), getSDKPath().toString())) << newLine | |||
| << "ndk.dir=" << escapeSpaces (replacePreprocessorDefs (getAllPreprocessorDefs(), getNDKPath().toString())) << newLine | |||
| << newLine; | |||
| overwriteFileIfDifferentOrThrow (file, mo); | |||
| } | |||
| void writeIcon (const File& file, int size) | |||
| { | |||
| Image im (project.getBestIconForSize (size, false)); | |||
| if (im.isValid()) | |||
| { | |||
| PNGImageFormat png; | |||
| MemoryOutputStream mo; | |||
| if (! png.writeImageToStream (im, mo)) | |||
| throw SaveError ("Can't generate Android icon file"); | |||
| overwriteFileIfDifferentOrThrow (file, mo); | |||
| } | |||
| } | |||
| void writeStringsFile (const File& file) | |||
| { | |||
| XmlElement strings ("resources"); | |||
| XmlElement* name = strings.createNewChildElement ("string"); | |||
| name->setAttribute ("name", "app_name"); | |||
| name->addTextElement (project.getProjectName().toString()); | |||
| writeXmlOrThrow (strings, file, "utf-8", 100); | |||
| } | |||
| //============================================================================== | |||
| JUCE_DECLARE_NON_COPYABLE (AndroidProjectExporter); | |||
| }; | |||
| #endif // __JUCER_PROJECTEXPORT_ANDROID_JUCEHEADER__ | |||
| @@ -377,59 +377,23 @@ protected: | |||
| out << dataBlock; | |||
| } | |||
| static const Image getBestIconImage (const Image& im1, const Image& im2, int size) | |||
| { | |||
| Image im; | |||
| if (im1.isValid() && im2.isValid()) | |||
| { | |||
| if (im1.getWidth() >= size && im2.getWidth() >= size) | |||
| im = im1.getWidth() < im2.getWidth() ? im1 : im2; | |||
| else if (im1.getWidth() >= size) | |||
| im = im1; | |||
| else if (im2.getWidth() >= size) | |||
| im = im2; | |||
| else | |||
| return Image(); | |||
| } | |||
| else | |||
| { | |||
| im = im1.isValid() ? im1 : im2; | |||
| } | |||
| if (size == im.getWidth() && size == im.getHeight()) | |||
| return im; | |||
| if (im.getWidth() < size && im.getHeight() < size) | |||
| return Image(); | |||
| Image newIm (Image::ARGB, size, size, true); | |||
| Graphics g (newIm); | |||
| g.drawImageWithin (im, 0, 0, size, size, | |||
| RectanglePlacement::centred | RectanglePlacement::onlyReduceInSize, false); | |||
| return newIm; | |||
| } | |||
| bool createIconFile() | |||
| { | |||
| Array<Image> images; | |||
| const Image smallIcon (project.getSmallIcon()); | |||
| const Image bigIcon (project.getBigIcon()); | |||
| Image im (getBestIconImage (smallIcon, bigIcon, 16)); | |||
| Image im (project.getBestIconForSize (16, true)); | |||
| if (im.isValid()) | |||
| images.add (im); | |||
| im = getBestIconImage (smallIcon, bigIcon, 32); | |||
| im = project.getBestIconForSize (32, true); | |||
| if (im.isValid()) | |||
| images.add (im); | |||
| im = getBestIconImage (smallIcon, bigIcon, 48); | |||
| im = project.getBestIconForSize (48, true); | |||
| if (im.isValid()) | |||
| images.add (im); | |||
| im = getBestIconImage (smallIcon, bigIcon, 128); | |||
| im = project.getBestIconForSize (128, true); | |||
| if (im.isValid()) | |||
| images.add (im); | |||
| @@ -485,7 +449,7 @@ public: | |||
| } | |||
| //============================================================================== | |||
| const String create() | |||
| void create() | |||
| { | |||
| createIconFile(); | |||
| @@ -498,23 +462,15 @@ public: | |||
| { | |||
| XmlElement projectXml ("VisualStudioProject"); | |||
| fillInProjectXml (projectXml); | |||
| MemoryOutputStream mo; | |||
| projectXml.writeToStream (mo, String::empty, false, true, "UTF-8", 10); | |||
| if (! FileHelpers::overwriteFileWithNewDataIfDifferent (getVCProjFile(), mo)) | |||
| return "Can't write to the VC project file: " + getVCProjFile().getFullPathName(); | |||
| writeXmlOrThrow (projectXml, getVCProjFile(), "UTF-8", 10); | |||
| } | |||
| { | |||
| MemoryOutputStream mo; | |||
| writeSolutionFile (mo, getSolutionVersionString(), getVCProjFile()); | |||
| if (! FileHelpers::overwriteFileWithNewDataIfDifferent (getSLNFile(), mo)) | |||
| return "Can't write to the VC solution file: " + getSLNFile().getFullPathName(); | |||
| overwriteFileIfDifferentOrThrow (getSLNFile(), mo); | |||
| } | |||
| return String::empty; | |||
| } | |||
| protected: | |||
| @@ -873,25 +829,19 @@ public: | |||
| } | |||
| //============================================================================== | |||
| const String create() | |||
| void create() | |||
| { | |||
| { | |||
| MemoryOutputStream mo; | |||
| writeProject (mo); | |||
| if (! FileHelpers::overwriteFileWithNewDataIfDifferent (getDSPFile(), mo)) | |||
| return "Can't write to the VC project file: " + getDSPFile().getFullPathName(); | |||
| overwriteFileIfDifferentOrThrow (getDSPFile(), mo); | |||
| } | |||
| { | |||
| MemoryOutputStream mo; | |||
| writeDSWFile (mo); | |||
| if (! FileHelpers::overwriteFileWithNewDataIfDifferent (getDSWFile(), mo)) | |||
| return "Can't write to the VC solution file: " + getDSWFile().getFullPathName(); | |||
| overwriteFileIfDifferentOrThrow (getDSWFile(), mo); | |||
| } | |||
| return String::empty; | |||
| } | |||
| private: | |||
| @@ -1140,41 +1090,28 @@ public: | |||
| } | |||
| //============================================================================== | |||
| const String create() | |||
| void create() | |||
| { | |||
| createIconFile(); | |||
| { | |||
| XmlElement projectXml ("Project"); | |||
| fillInProjectXml (projectXml); | |||
| MemoryOutputStream mo; | |||
| projectXml.writeToStream (mo, String::empty, false, true, "utf-8", 100); | |||
| if (! FileHelpers::overwriteFileWithNewDataIfDifferent (getVCProjFile(), mo)) | |||
| return "Can't write to the VC project file: " + getVCProjFile().getFullPathName(); | |||
| writeXmlOrThrow (projectXml, getVCProjFile(), "utf-8", 100); | |||
| } | |||
| { | |||
| XmlElement filtersXml ("Project"); | |||
| fillInFiltersXml (filtersXml); | |||
| MemoryOutputStream mo; | |||
| filtersXml.writeToStream (mo, String::empty, false, true, "utf-8", 100); | |||
| if (! FileHelpers::overwriteFileWithNewDataIfDifferent (getVCProjFiltersFile(), mo)) | |||
| return "Can't write to the VC project file: " + getVCProjFiltersFile().getFullPathName(); | |||
| writeXmlOrThrow (filtersXml, getVCProjFiltersFile(), "utf-8", 100); | |||
| } | |||
| { | |||
| MemoryOutputStream mo; | |||
| writeSolutionFile (mo, "11.00", getVCProjFile()); | |||
| if (! FileHelpers::overwriteFileWithNewDataIfDifferent (getSLNFile(), mo)) | |||
| return "Can't write to the VC solution file: " + getSLNFile().getFullPathName(); | |||
| overwriteFileIfDifferentOrThrow (getSLNFile(), mo); | |||
| } | |||
| return String::empty; | |||
| } | |||
| protected: | |||
| @@ -83,7 +83,7 @@ public: | |||
| } | |||
| //============================================================================== | |||
| const String create() | |||
| void create() | |||
| { | |||
| Array<RelativePath> files; | |||
| findAllFilesToCompile (project.getMainGroup(), files); | |||
| @@ -99,11 +99,7 @@ public: | |||
| MemoryOutputStream mo; | |||
| writeMakefile (mo, files); | |||
| const File makefile (getTargetFolder().getChildFile ("Makefile")); | |||
| if (! FileHelpers::overwriteFileWithNewDataIfDifferent (makefile, mo)) | |||
| return "Can't write to the Makefile: " + makefile.getFullPathName(); | |||
| return String::empty; | |||
| overwriteFileIfDifferentOrThrow (getTargetFolder().getChildFile ("Makefile"), mo); | |||
| } | |||
| private: | |||
| @@ -137,17 +133,7 @@ private: | |||
| defines.set ("NDEBUG", "1"); | |||
| } | |||
| defines = mergePreprocessorDefs (defines, getAllPreprocessorDefs (config)); | |||
| for (int i = 0; i < defines.size(); ++i) | |||
| { | |||
| String def (defines.getAllKeys()[i]); | |||
| const String value (defines.getAllValues()[i]); | |||
| if (value.isNotEmpty()) | |||
| def << "=" << value; | |||
| out << " -D " << def.quoted(); | |||
| } | |||
| out << createGCCPreprocessorFlags (mergePreprocessorDefs (defines, getAllPreprocessorDefs (config))); | |||
| } | |||
| void writeHeaderPathFlags (OutputStream& out, const Project::BuildConfiguration& config) | |||
| @@ -334,11 +320,6 @@ private: | |||
| out << "-include $(OBJECTS:%.o=%.d)" << newLine; | |||
| } | |||
| static const String escapeSpaces (const String& s) | |||
| { | |||
| return s.replace (" ", "\\ "); | |||
| } | |||
| const String getObjectFileFor (const RelativePath& file) const | |||
| { | |||
| return file.getFileNameWithoutExtension() | |||
| @@ -106,16 +106,14 @@ public: | |||
| } | |||
| //============================================================================== | |||
| const String create() | |||
| void create() | |||
| { | |||
| infoPlistFile = getTargetFolder().getChildFile ("Info.plist"); | |||
| if (! createIconFile()) | |||
| return "Can't write the icon file"; | |||
| createIconFile(); | |||
| File projectBundle (getProjectBundle()); | |||
| if (! projectBundle.createDirectory()) | |||
| return "Can't write to the target directory"; | |||
| createDirectoryOrThrow (projectBundle); | |||
| createObjects(); | |||
| @@ -124,15 +122,10 @@ public: | |||
| { | |||
| MemoryOutputStream mo; | |||
| writeProjectFile (mo); | |||
| if (! FileHelpers::overwriteFileWithNewDataIfDifferent (projectFile, mo)) | |||
| return "Can't write to file: " + projectFile.getFullPathName(); | |||
| overwriteFileIfDifferentOrThrow (projectFile, mo); | |||
| } | |||
| if (! writeInfoPlistFile()) | |||
| return "Can't write the Info.plist file"; | |||
| return String::empty; | |||
| writeInfoPlistFile(); | |||
| } | |||
| private: | |||
| @@ -303,7 +296,7 @@ private: | |||
| out << data; | |||
| } | |||
| bool createIconFile() | |||
| void createIconFile() | |||
| { | |||
| Array<Image> images; | |||
| @@ -315,20 +308,20 @@ private: | |||
| if (smallIcon.isValid()) | |||
| images.add (smallIcon); | |||
| if (images.size() == 0) | |||
| return true; | |||
| MemoryOutputStream mo; | |||
| writeIcnsFile (images, mo); | |||
| if (images.size() > 0) | |||
| { | |||
| MemoryOutputStream mo; | |||
| writeIcnsFile (images, mo); | |||
| iconFile = getTargetFolder().getChildFile ("Icon.icns"); | |||
| return FileHelpers::overwriteFileWithNewDataIfDifferent (iconFile, mo); | |||
| iconFile = getTargetFolder().getChildFile ("Icon.icns"); | |||
| overwriteFileIfDifferentOrThrow (iconFile, mo); | |||
| } | |||
| } | |||
| bool writeInfoPlistFile() | |||
| void writeInfoPlistFile() | |||
| { | |||
| if (! hasPList()) | |||
| return true; | |||
| return; | |||
| XmlElement plist ("plist"); | |||
| XmlElement* dict = plist.createNewChildElement ("dict"); | |||
| @@ -353,7 +346,7 @@ private: | |||
| addPlistDictionaryKey (dict, "CFBundleVersion", project.getVersion().toString()); | |||
| StringArray documentExtensions; | |||
| documentExtensions.addTokens (replacePreprocessorDefs (project.getPreprocessorDefs(), getSetting ("documentExtensions").toString()), | |||
| documentExtensions.addTokens (replacePreprocessorDefs (getAllPreprocessorDefs(), getSetting ("documentExtensions").toString()), | |||
| ",", String::empty); | |||
| documentExtensions.trim(); | |||
| documentExtensions.removeEmptyStrings (true); | |||
| @@ -380,7 +373,7 @@ private: | |||
| MemoryOutputStream mo; | |||
| plist.writeToStream (mo, "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">"); | |||
| return FileHelpers::overwriteFileWithNewDataIfDifferent (infoPlistFile, mo); | |||
| overwriteFileIfDifferentOrThrow (infoPlistFile, mo); | |||
| } | |||
| const StringArray getHeaderSearchPaths (const Project::BuildConfiguration& config) | |||
| @@ -27,6 +27,7 @@ | |||
| #include "jucer_ProjectExport_Make.h" | |||
| #include "jucer_ProjectExport_MSVC.h" | |||
| #include "jucer_ProjectExport_XCode.h" | |||
| #include "jucer_ProjectExport_Android.h" | |||
| //============================================================================== | |||
| @@ -55,6 +56,7 @@ const StringArray ProjectExporter::getExporterNames() | |||
| s.add (MSVCProjectExporterVC2008::getName()); | |||
| s.add (MSVCProjectExporterVC2010::getName()); | |||
| s.add (MakefileProjectExporter::getNameLinux()); | |||
| //s.add (AndroidProjectExporter::getNameAndroid()); | |||
| return s; | |||
| } | |||
| @@ -71,6 +73,7 @@ ProjectExporter* ProjectExporter::createNewExporter (Project& project, const int | |||
| case 4: exp = new MSVCProjectExporterVC2008 (project, ValueTree (MSVCProjectExporterVC2008::getValueTreeTypeName())); break; | |||
| case 5: exp = new MSVCProjectExporterVC2010 (project, ValueTree (MSVCProjectExporterVC2010::getValueTreeTypeName())); break; | |||
| case 6: exp = new MakefileProjectExporter (project, ValueTree (MakefileProjectExporter::getValueTreeTypeName())); break; | |||
| case 7: exp = new AndroidProjectExporter (project, ValueTree (AndroidProjectExporter::getValueTreeTypeName())); break; | |||
| default: jassertfalse; return 0; | |||
| } | |||
| @@ -93,6 +96,7 @@ ProjectExporter* ProjectExporter::createExporter (Project& project, const ValueT | |||
| if (exp == 0) exp = MSVCProjectExporterVC2010::createForSettings (project, settings); | |||
| if (exp == 0) exp = XCodeProjectExporter::createForSettings (project, settings); | |||
| if (exp == 0) exp = MakefileProjectExporter::createForSettings (project, settings); | |||
| if (exp == 0) exp = AndroidProjectExporter::createForSettings (project, settings); | |||
| jassert (exp != 0); | |||
| return exp; | |||
| @@ -208,6 +212,14 @@ const StringPairArray ProjectExporter::getAllPreprocessorDefs (const Project::Bu | |||
| return defs; | |||
| } | |||
| const StringPairArray ProjectExporter::getAllPreprocessorDefs() const | |||
| { | |||
| StringPairArray defs (mergePreprocessorDefs (project.getPreprocessorDefs(), | |||
| parsePreprocessorDefs (getExporterPreprocessorDefs().toString()))); | |||
| defs.set (getExporterIdentifierMacro(), "1"); | |||
| return defs; | |||
| } | |||
| const String ProjectExporter::replacePreprocessorTokens (const Project::BuildConfiguration& config, const String& sourceString) const | |||
| { | |||
| return replacePreprocessorDefs (getAllPreprocessorDefs (config), sourceString); | |||
| @@ -53,7 +53,7 @@ public: | |||
| virtual bool usesMMFiles() const = 0; | |||
| virtual void createPropertyEditors (Array <PropertyComponent*>& props); | |||
| virtual void launchProject() = 0; | |||
| virtual const String create() = 0; | |||
| virtual void create() = 0; // may throw a SaveError | |||
| virtual bool shouldFileBeCompiledByDefault (const RelativePath& path) const; | |||
| //============================================================================== | |||
| @@ -78,7 +78,11 @@ public: | |||
| Value getExtraLinkerFlags() const { return getSetting (Ids::extraLinkerFlags); } | |||
| Value getExporterPreprocessorDefs() const { return getSetting (Ids::extraDefs); } | |||
| const StringPairArray getAllPreprocessorDefs (const Project::BuildConfiguration& config) const; // includes inherited ones.. | |||
| // includes exporter, project + config defs | |||
| const StringPairArray getAllPreprocessorDefs (const Project::BuildConfiguration& config) const; | |||
| // includes exporter + project defs.. | |||
| const StringPairArray getAllPreprocessorDefs() const; | |||
| const String replacePreprocessorTokens (const Project::BuildConfiguration& config, | |||
| const String& sourceString) const; | |||
| @@ -95,6 +99,20 @@ public: | |||
| Array<RelativePath> juceWrapperFiles; | |||
| RelativePath juceWrapperFolder; | |||
| // An exception that can be thrown by the create() method. | |||
| class SaveError | |||
| { | |||
| public: | |||
| SaveError (const String& error) : message (error) | |||
| {} | |||
| SaveError (const File& fileThatFailedToWrite) | |||
| : message ("Can't write to the file: " + fileThatFailedToWrite.getFullPathName()) | |||
| {} | |||
| String message; | |||
| }; | |||
| protected: | |||
| //============================================================================== | |||
| Project& project; | |||
| @@ -103,7 +121,7 @@ protected: | |||
| const RelativePath getJucePathFromTargetFolder() const; | |||
| const String getDefaultBuildsRootFolder() const { return "Builds/"; } | |||
| static const String getDefaultBuildsRootFolder() { return "Builds/"; } | |||
| const Array<RelativePath> getVSTFilesRequired() const; | |||
| @@ -118,6 +136,26 @@ protected: | |||
| const RelativePath rebaseFromProjectFolderToBuildTarget (const RelativePath& path) const; | |||
| //============================================================================== | |||
| static void overwriteFileIfDifferentOrThrow (const File& file, const MemoryOutputStream& newData) | |||
| { | |||
| if (! FileHelpers::overwriteFileWithNewDataIfDifferent (file, newData)) | |||
| throw SaveError (file); | |||
| } | |||
| static void createDirectoryOrThrow (const File& dirToCreate) | |||
| { | |||
| if (! dirToCreate.createDirectory()) | |||
| throw SaveError ("Can't create folder: " + dirToCreate.getFullPathName()); | |||
| } | |||
| static void writeXmlOrThrow (const XmlElement& xml, const File& file, const String& encoding, int maxCharsPerLine) | |||
| { | |||
| MemoryOutputStream mo; | |||
| xml.writeToStream (mo, String::empty, false, true, encoding, maxCharsPerLine); | |||
| overwriteFileIfDifferentOrThrow (file, mo); | |||
| } | |||
| private: | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ProjectExporter); | |||
| }; | |||
| @@ -515,10 +515,14 @@ private: | |||
| if (project.isAudioPlugin()) | |||
| exporter->juceWrapperFiles.add (RelativePath (pluginCharacteristicsFile, targetFolder, RelativePath::buildTargetFolder)); | |||
| String error = exporter->create(); | |||
| if (error.isNotEmpty()) | |||
| errors.add (error); | |||
| try | |||
| { | |||
| exporter->create(); | |||
| } | |||
| catch (ProjectExporter::SaveError& error) | |||
| { | |||
| errors.add (error.message); | |||
| } | |||
| } | |||
| else | |||
| { | |||
| @@ -77,46 +77,45 @@ const String createGUID (const String& seed) | |||
| return guid; | |||
| } | |||
| //============================================================================== | |||
| static void skipWhitespace (const String& s, int& i) | |||
| const String escapeSpaces (const String& s) | |||
| { | |||
| while (CharacterFunctions::isWhitespace (s[i])) | |||
| ++i; | |||
| return s.replace (" ", "\\ "); | |||
| } | |||
| const StringPairArray parsePreprocessorDefs (const String& s) | |||
| //============================================================================== | |||
| const StringPairArray parsePreprocessorDefs (const String& text) | |||
| { | |||
| StringPairArray result; | |||
| int i = 0; | |||
| String::CharPointerType s (text.getCharPointer()); | |||
| while (s[i] != 0) | |||
| while (! s.isEmpty()) | |||
| { | |||
| String token, value; | |||
| skipWhitespace (s, i); | |||
| s = s.findEndOfWhitespace(); | |||
| while (s[i] != 0 && s[i] != '=' && ! CharacterFunctions::isWhitespace (s[i])) | |||
| token << s[i++]; | |||
| while ((! s.isEmpty()) && *s != '=' && ! s.isWhitespace()) | |||
| token << s.getAndAdvance(); | |||
| skipWhitespace (s, i); | |||
| s = s.findEndOfWhitespace(); | |||
| if (s[i] == '=') | |||
| if (*s == '=') | |||
| { | |||
| ++i; | |||
| ++s; | |||
| skipWhitespace (s, i); | |||
| s = s.findEndOfWhitespace(); | |||
| while (s[i] != 0 && ! CharacterFunctions::isWhitespace (s[i])) | |||
| while ((! s.isEmpty()) && ! s.isWhitespace()) | |||
| { | |||
| if (s[i] == ',') | |||
| if (*s == ',') | |||
| { | |||
| ++i; | |||
| ++s; | |||
| break; | |||
| } | |||
| if (s[i] == '\\' && (s[i + 1] == ' ' || s[i + 1] == ',')) | |||
| ++i; | |||
| if (*s == '\\' && (s[1] == ' ' || s[1] == ',')) | |||
| ++s; | |||
| value << s[i++]; | |||
| value << s.getAndAdvance(); | |||
| } | |||
| } | |||
| @@ -135,6 +134,23 @@ const StringPairArray mergePreprocessorDefs (StringPairArray inheritedDefs, cons | |||
| return inheritedDefs; | |||
| } | |||
| const String createGCCPreprocessorFlags (const StringPairArray& defs) | |||
| { | |||
| String s; | |||
| for (int i = 0; i < defs.size(); ++i) | |||
| { | |||
| String def (defs.getAllKeys()[i]); | |||
| const String value (defs.getAllValues()[i]); | |||
| if (value.isNotEmpty()) | |||
| def << "=" << value; | |||
| s += " -D " + def.quoted(); | |||
| } | |||
| return s; | |||
| } | |||
| const String replacePreprocessorDefs (const StringPairArray& definitions, String sourceString) | |||
| { | |||
| for (int i = 0; i < definitions.size(); ++i) | |||
| @@ -33,8 +33,11 @@ const String hexString8Digits (int value); | |||
| const String createAlphaNumericUID(); | |||
| const String createGUID (const String& seed); // Turns a seed into a windows GUID | |||
| const String escapeSpaces (const String& text); // replaces spaces with blackslash-space | |||
| const StringPairArray parsePreprocessorDefs (const String& defs); | |||
| const StringPairArray mergePreprocessorDefs (StringPairArray inheritedDefs, const StringPairArray& overridingDefs); | |||
| const String createGCCPreprocessorFlags (const StringPairArray& defs); | |||
| const String replacePreprocessorDefs (const StringPairArray& definitions, String sourceString); | |||
| //============================================================================== | |||
| @@ -113,6 +113,8 @@ namespace Ids | |||
| DECLARE_ID (memberName); | |||
| DECLARE_ID (focusOrder); | |||
| DECLARE_ID (hidden); | |||
| DECLARE_ID (androidSDKPath); | |||
| DECLARE_ID (androidNDKPath); | |||
| const Identifier class_ ("class"); | |||
| const Identifier id_ ("id"); | |||
| @@ -776,6 +776,7 @@ protected: | |||
| #include <net/if.h> | |||
| #include <sys/sysinfo.h> | |||
| #include <sys/file.h> | |||
| #include <sys/prctl.h> | |||
| #include <signal.h> | |||
| /* Got a build error here? You'll need to install the freetype library... | |||
| @@ -2202,6 +2203,16 @@ JUCE_API void JUCE_CALLTYPE initialiseJuce_NonGUI() | |||
| static_jassert (sizeof (uint32) == 4); | |||
| static_jassert (sizeof (int64) == 8); | |||
| static_jassert (sizeof (uint64) == 8); | |||
| #if JUCE_NATIVE_WCHAR_IS_UTF8 | |||
| static_jassert (sizeof (wchar_t) == 1); | |||
| #elif JUCE_NATIVE_WCHAR_IS_UTF16 | |||
| static_jassert (sizeof (wchar_t) == 2); | |||
| #elif JUCE_NATIVE_WCHAR_IS_UTF32 | |||
| static_jassert (sizeof (wchar_t) == 4); | |||
| #else | |||
| #error "native wchar_t size is unknown" | |||
| #endif | |||
| } | |||
| JUCE_API void JUCE_CALLTYPE shutdownJuce_NonGUI() | |||
| @@ -11142,14 +11153,14 @@ int CharacterFunctions::ftime (char* const dest, const int maxChars, const char* | |||
| int CharacterFunctions::ftime (juce_wchar* const dest, const int maxChars, const juce_wchar* const format, const struct tm* const tm) throw() | |||
| { | |||
| #if JUCE_NATIVE_WCHAR_IS_NOT_UTF32 | |||
| #if JUCE_NATIVE_WCHAR_IS_UTF32 && ! JUCE_ANDROID | |||
| return (int) wcsftime (dest, maxChars, format, tm); | |||
| #else | |||
| HeapBlock <char> tempDest; | |||
| tempDest.calloc (maxChars + 2); | |||
| int result = ftime (tempDest.getData(), maxChars, String (format).toUTF8(), tm); | |||
| CharPointer_UTF32 (dest).writeAll (CharPointer_UTF8 (tempDest.getData())); | |||
| return result; | |||
| #else | |||
| return (int) wcsftime (dest, maxChars, format, tm); | |||
| #endif | |||
| } | |||
| @@ -11334,6 +11345,14 @@ BEGIN_JUCE_NAMESPACE | |||
| #error "JUCE_STRINGS_ARE_UNICODE is deprecated! All strings are now unicode by default." | |||
| #endif | |||
| #if JUCE_NATIVE_WCHAR_IS_UTF8 | |||
| typedef CharPointer_UTF8 CharPointer_wchar_t; | |||
| #elif JUCE_NATIVE_WCHAR_IS_UTF16 | |||
| typedef CharPointer_UTF16 CharPointer_wchar_t; | |||
| #else | |||
| typedef CharPointer_UTF32 CharPointer_wchar_t; | |||
| #endif | |||
| NewLine newLine; | |||
| class StringHolder | |||
| @@ -11550,7 +11569,7 @@ String::String (const char* const t) | |||
| 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())); | |||
| jassert (t == 0 || CharPointer_ASCII::isValidString (t, std::numeric_limits<int>::max())); | |||
| } | |||
| String::String (const char* const t, const size_t maxChars) | |||
| @@ -11569,7 +11588,7 @@ String::String (const char* const t, const size_t maxChars) | |||
| 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)); | |||
| jassert (t == 0 || CharPointer_ASCII::isValidString (t, (int) maxChars)); | |||
| } | |||
| String::String (const juce_wchar* const t) | |||
| @@ -11607,14 +11626,16 @@ String::String (const CharPointer_ASCII& t) | |||
| { | |||
| } | |||
| #if JUCE_WINDOWS | |||
| #if ! JUCE_NATIVE_WCHAR_IS_UTF32 | |||
| String::String (const wchar_t* const t) | |||
| : text (StringHolder::createFromCharPointer (CharPointer_UTF16 (t))) | |||
| : text (StringHolder::createFromCharPointer | |||
| (CharPointer_wchar_t (reinterpret_cast <const CharPointer_wchar_t::CharType*> (t)))) | |||
| { | |||
| } | |||
| String::String (const wchar_t* const t, size_t maxChars) | |||
| : text (StringHolder::createFromCharPointer (CharPointer_UTF16 (t), maxChars)) | |||
| : text (StringHolder::createFromCharPointer | |||
| (CharPointer_wchar_t (reinterpret_cast <const CharPointer_wchar_t::CharType*> (t)), maxChars)) | |||
| { | |||
| } | |||
| #endif | |||
| @@ -11997,7 +12018,7 @@ String& String::operator+= (const juce_wchar ch) | |||
| return operator+= (static_cast <const juce_wchar*> (asString)); | |||
| } | |||
| #if JUCE_WINDOWS | |||
| #if ! JUCE_NATIVE_WCHAR_IS_UTF32 | |||
| String& String::operator+= (const wchar_t ch) | |||
| { | |||
| return operator+= ((juce_wchar) ch); | |||
| @@ -12065,7 +12086,7 @@ JUCE_API const String JUCE_CALLTYPE operator+ (String string1, const juce_wchar | |||
| return string1 += string2; | |||
| } | |||
| #if JUCE_WINDOWS | |||
| #if ! JUCE_NATIVE_WCHAR_IS_UTF32 | |||
| JUCE_API const String JUCE_CALLTYPE operator+ (String string1, wchar_t string2) | |||
| { | |||
| return string1 += string2; | |||
| @@ -12073,7 +12094,7 @@ JUCE_API const String JUCE_CALLTYPE operator+ (String string1, wchar_t string2) | |||
| JUCE_API const String JUCE_CALLTYPE operator+ (String string1, const wchar_t* string2) | |||
| { | |||
| string1.appendCharPointer (CharPointer_UTF16 (string2)); | |||
| string1.appendCharPointer (CharPointer_wchar_t (reinterpret_cast <const CharPointer_wchar_t::CharType*> (string2))); | |||
| return string1; | |||
| } | |||
| @@ -13383,9 +13404,7 @@ const String String::fromUTF8 (const char* const buffer, int bufferSizeBytes) | |||
| const char* String::toCString() const | |||
| { | |||
| #if JUCE_NATIVE_WCHAR_IS_NOT_UTF32 | |||
| return toUTF8(); | |||
| #else | |||
| #if JUCE_NATIVE_WCHAR_IS_UTF32 && ! JUCE_ANDROID | |||
| if (isEmpty()) | |||
| return reinterpret_cast <const char*> (text.getAddress()); | |||
| @@ -13394,29 +13413,31 @@ const char* String::toCString() const | |||
| wcstombs (extraSpace, text, len); | |||
| extraSpace [len] = 0; | |||
| return extraSpace; | |||
| #else | |||
| return toUTF8(); | |||
| #endif | |||
| } | |||
| int String::getNumBytesAsCString() const throw() | |||
| { | |||
| #if JUCE_NATIVE_WCHAR_IS_NOT_UTF32 | |||
| return getNumBytesAsUTF8(); | |||
| #else | |||
| #if JUCE_NATIVE_WCHAR_IS_UTF32 && ! JUCE_ANDROID | |||
| return (int) wcstombs (0, text, 0); | |||
| #else | |||
| return getNumBytesAsUTF8(); | |||
| #endif | |||
| } | |||
| int String::copyToCString (char* destBuffer, const int maxBufferSizeBytes) const throw() | |||
| { | |||
| #if JUCE_NATIVE_WCHAR_IS_NOT_UTF32 | |||
| return copyToUTF8 (destBuffer, maxBufferSizeBytes); | |||
| #else | |||
| #if JUCE_NATIVE_WCHAR_IS_UTF32 && ! JUCE_ANDROID | |||
| const int numBytes = (int) wcstombs (destBuffer, text, maxBufferSizeBytes); | |||
| if (destBuffer != 0 && numBytes >= 0) | |||
| destBuffer [numBytes] = 0; | |||
| return numBytes; | |||
| #else | |||
| return copyToUTF8 (destBuffer, maxBufferSizeBytes); | |||
| #endif | |||
| } | |||
| @@ -253997,8 +254018,13 @@ void Thread::killThread() | |||
| } | |||
| } | |||
| void Thread::setCurrentThreadName (const String& /*name*/) | |||
| void Thread::setCurrentThreadName (const String& name) | |||
| { | |||
| #if JUCE_MAC | |||
| pthread_setname_np (name.toUTF8()); | |||
| #elif JUCE_LINUX | |||
| prctl (PR_SET_NAME, name.toUTF8().getAddress(), 0, 0, 0); | |||
| #endif | |||
| } | |||
| bool Thread::setThreadPriority (void* handle, int priority) | |||
| @@ -263904,8 +263930,13 @@ void Thread::killThread() | |||
| } | |||
| } | |||
| void Thread::setCurrentThreadName (const String& /*name*/) | |||
| void Thread::setCurrentThreadName (const String& name) | |||
| { | |||
| #if JUCE_MAC | |||
| pthread_setname_np (name.toUTF8()); | |||
| #elif JUCE_LINUX | |||
| prctl (PR_SET_NAME, name.toUTF8().getAddress(), 0, 0, 0); | |||
| #endif | |||
| } | |||
| bool Thread::setThreadPriority (void* handle, int priority) | |||
| @@ -267538,6 +267569,8 @@ END_JUCE_NAMESPACE | |||
| - (bool) makeActive; | |||
| - (void) makeInactive; | |||
| - (void) reshape; | |||
| - (void) rightMouseDown: (NSEvent*) ev; | |||
| - (void) rightMouseUp: (NSEvent*) ev; | |||
| @end | |||
| @implementation ThreadSafeNSOpenGLView | |||
| @@ -267606,6 +267639,16 @@ END_JUCE_NAMESPACE | |||
| needsUpdate = true; | |||
| } | |||
| - (void) rightMouseDown: (NSEvent*) ev | |||
| { | |||
| [[self superview] rightMouseDown: ev]; | |||
| } | |||
| - (void) rightMouseUp: (NSEvent*) ev | |||
| { | |||
| [[self superview] rightMouseUp: ev]; | |||
| } | |||
| @end | |||
| BEGIN_JUCE_NAMESPACE | |||
| @@ -273176,6 +273219,8 @@ END_JUCE_NAMESPACE | |||
| - (bool) makeActive; | |||
| - (void) makeInactive; | |||
| - (void) reshape; | |||
| - (void) rightMouseDown: (NSEvent*) ev; | |||
| - (void) rightMouseUp: (NSEvent*) ev; | |||
| @end | |||
| @implementation ThreadSafeNSOpenGLView | |||
| @@ -273244,6 +273289,16 @@ END_JUCE_NAMESPACE | |||
| needsUpdate = true; | |||
| } | |||
| - (void) rightMouseDown: (NSEvent*) ev | |||
| { | |||
| [[self superview] rightMouseDown: ev]; | |||
| } | |||
| - (void) rightMouseUp: (NSEvent*) ev | |||
| { | |||
| [[self superview] rightMouseUp: ev]; | |||
| } | |||
| @end | |||
| BEGIN_JUCE_NAMESPACE | |||
| @@ -278567,7 +278622,6 @@ public: | |||
| inline operator jobject() const throw() { return obj; } | |||
| inline jobject get() const throw() { return obj; } | |||
| inline JNIEnv* getEnv() const throw() { return env; } | |||
| #define DECLARE_CALL_TYPE_METHOD(returnType, typeName) \ | |||
| @@ -278601,6 +278655,7 @@ public: | |||
| } | |||
| private: | |||
| JNIEnv* env; | |||
| jobject obj; | |||
| @@ -279595,8 +279650,13 @@ void Thread::killThread() | |||
| } | |||
| } | |||
| void Thread::setCurrentThreadName (const String& /*name*/) | |||
| void Thread::setCurrentThreadName (const String& name) | |||
| { | |||
| #if JUCE_MAC | |||
| pthread_setname_np (name.toUTF8()); | |||
| #elif JUCE_LINUX | |||
| prctl (PR_SET_NAME, name.toUTF8().getAddress(), 0, 0, 0); | |||
| #endif | |||
| } | |||
| bool Thread::setThreadPriority (void* handle, int priority) | |||
| @@ -73,7 +73,7 @@ namespace JuceDummyNamespace {} | |||
| */ | |||
| #define JUCE_MAJOR_VERSION 1 | |||
| #define JUCE_MINOR_VERSION 53 | |||
| #define JUCE_BUILDNUMBER 25 | |||
| #define JUCE_BUILDNUMBER 26 | |||
| /** Current Juce version number. | |||
| @@ -1636,25 +1636,35 @@ inline void ByteOrder::bigEndian24BitToChars (const int value, char* const destB | |||
| #ifndef __JUCE_CHARACTERFUNCTIONS_JUCEHEADER__ | |||
| #define __JUCE_CHARACTERFUNCTIONS_JUCEHEADER__ | |||
| #if JUCE_ANDROID && ! DOXYGEN | |||
| typedef uint32 juce_wchar; | |||
| #define JUCE_T(stringLiteral) CharPointer_UTF8 (stringLiteral) | |||
| #define JUCE_NATIVE_WCHAR_IS_NOT_UTF32 1 | |||
| #elif JUCE_WINDOWS && ! DOXYGEN | |||
| typedef uint32 juce_wchar; | |||
| #define JUCE_T(stringLiteral) L##stringLiteral | |||
| #define JUCE_NATIVE_WCHAR_IS_NOT_UTF32 1 | |||
| #if JUCE_WINDOWS && ! DOXYGEN | |||
| #define JUCE_NATIVE_WCHAR_IS_UTF8 0 | |||
| #define JUCE_NATIVE_WCHAR_IS_UTF16 1 | |||
| #define JUCE_NATIVE_WCHAR_IS_UTF32 0 | |||
| #else | |||
| /** A platform-independent unicode character type. */ | |||
| typedef wchar_t juce_wchar; | |||
| #define JUCE_T(stringLiteral) (L##stringLiteral) | |||
| /** This macro will be set to 1 if the compiler's native wchar_t is an 8-bit type. */ | |||
| #define JUCE_NATIVE_WCHAR_IS_UTF8 0 | |||
| /** This macro will be set to 1 if the compiler's native wchar_t is a 16-bit type. */ | |||
| #define JUCE_NATIVE_WCHAR_IS_UTF16 0 | |||
| /** This macro will be set to 1 if the compiler's native wchar_t is a 32-bit type. */ | |||
| #define JUCE_NATIVE_WCHAR_IS_UTF32 1 | |||
| #endif | |||
| #if JUCE_NATIVE_WCHAR_IS_UTF32 || DOXYGEN | |||
| /** A platform-independent 32-bit unicode character type. */ | |||
| typedef wchar_t juce_wchar; | |||
| #else | |||
| typedef uint32 juce_wchar; | |||
| #endif | |||
| /** This macro is deprecated, but preserved for compatibility with old code.*/ | |||
| #define JUCE_T(stringLiteral) (L##stringLiteral) | |||
| #if ! JUCE_DONT_DEFINE_MACROS | |||
| /** The 'T' macro allows a literal string to be compiled as unicode. | |||
| /** The 'T' macro is an alternative for using the "L" prefix in front of a string literal. | |||
| If you write your string literals in the form T("xyz"), it will be compiled as L"xyz" | |||
| or "xyz", depending on which representation is best for the String class to work with. | |||
| This macro is deprectated, but kept here for compatibility with old code. The best (i.e. | |||
| most portable) way to encode your string literals is just as standard 8-bit strings, but | |||
| using escaped utf-8 character codes for extended characters. | |||
| Because the 'T' symbol is occasionally used inside 3rd-party library headers which you | |||
| may need to include after juce.h, you can use the juce_withoutMacros.h file (in | |||
| @@ -2332,7 +2342,7 @@ inline Type Atomic<Type>::operator+= (const Type amountToAdd) throw() | |||
| for (;;) | |||
| { | |||
| const Type oldValue (value); | |||
| const Type newValue (oldValue + amountToAdd); | |||
| const Type newValue (castFrom32Bit (castTo32Bit (oldValue) + castTo32Bit (amountToAdd))); | |||
| if (compareAndSetBool (newValue, oldValue)) | |||
| return newValue; | |||
| } | |||
| @@ -2357,7 +2367,7 @@ inline Type Atomic<Type>::operator++() throw() | |||
| return sizeof (Type) == 4 ? (Type) juce_InterlockedIncrement ((volatile long*) &value) | |||
| : (Type) juce_InterlockedIncrement64 ((volatile __int64*) &value); | |||
| #elif JUCE_ANDROID | |||
| return (Type) __atomic_inc (&value); | |||
| return (Type) __atomic_inc ((volatile int*) &value); | |||
| #elif JUCE_ATOMICS_GCC | |||
| return (Type) __sync_add_and_fetch (&value, 1); | |||
| #endif | |||
| @@ -2373,7 +2383,7 @@ inline Type Atomic<Type>::operator--() throw() | |||
| return sizeof (Type) == 4 ? (Type) juce_InterlockedDecrement ((volatile long*) &value) | |||
| : (Type) juce_InterlockedDecrement64 ((volatile __int64*) &value); | |||
| #elif JUCE_ANDROID | |||
| return (Type) __atomic_dec (&value); | |||
| return (Type) __atomic_dec ((volatile int*) &value); | |||
| #elif JUCE_ATOMICS_GCC | |||
| return (Type) __sync_add_and_fetch (&value, -1); | |||
| #endif | |||
| @@ -2961,7 +2971,7 @@ private: | |||
| class CharPointer_UTF16 | |||
| { | |||
| public: | |||
| #if JUCE_WINDOWS && ! DOXYGEN | |||
| #if JUCE_NATIVE_WCHAR_IS_UTF16 | |||
| typedef wchar_t CharType; | |||
| #else | |||
| typedef int16 CharType; | |||
| @@ -3519,13 +3529,13 @@ public: | |||
| /** Returns the number of characters in this string. */ | |||
| size_t length() const throw() | |||
| { | |||
| #if JUCE_NATIVE_WCHAR_IS_NOT_UTF32 | |||
| #if JUCE_NATIVE_WCHAR_IS_UTF32 && ! JUCE_ANDROID | |||
| return wcslen (data); | |||
| #else | |||
| size_t n = 0; | |||
| while (data[n] != 0) | |||
| ++n; | |||
| return n; | |||
| #else | |||
| return wcslen (data); | |||
| #endif | |||
| } | |||
| @@ -3613,7 +3623,7 @@ public: | |||
| return CharacterFunctions::compare (*this, other); | |||
| } | |||
| #if ! JUCE_NATIVE_WCHAR_IS_NOT_UTF32 | |||
| #if JUCE_NATIVE_WCHAR_IS_UTF32 && ! JUCE_ANDROID | |||
| /** Compares this string with another one. */ | |||
| int compare (const CharPointer_UTF32& other) const throw() | |||
| { | |||
| @@ -4175,7 +4185,7 @@ public: | |||
| /** Creates a string from an ASCII character string */ | |||
| String (const CharPointer_ASCII& text); | |||
| #if JUCE_WINDOWS | |||
| #if ! JUCE_NATIVE_WCHAR_IS_UTF32 | |||
| /** Creates a string from a UTF-16 character string */ | |||
| String (const wchar_t* text); | |||
| @@ -4221,7 +4231,7 @@ public: | |||
| String& operator+= (char characterToAppend); | |||
| /** Appends a character at the end of this string. */ | |||
| String& operator+= (juce_wchar characterToAppend); | |||
| #if JUCE_WINDOWS | |||
| #if ! JUCE_NATIVE_WCHAR_IS_UTF32 | |||
| /** Appends a character at the end of this string. */ | |||
| String& operator+= (wchar_t characterToAppend); | |||
| /** Appends another string at the end of this one. */ | |||
| @@ -5242,7 +5252,7 @@ JUCE_API const String JUCE_CALLTYPE operator+ (String string1, const juce_wchar | |||
| JUCE_API const String JUCE_CALLTYPE operator+ (String string1, char characterToAppend); | |||
| /** Concatenates two strings. */ | |||
| JUCE_API const String JUCE_CALLTYPE operator+ (String string1, juce_wchar characterToAppend); | |||
| #if JUCE_WINDOWS | |||
| #if ! JUCE_NATIVE_WCHAR_IS_UTF32 | |||
| /** Concatenates two strings. */ | |||
| JUCE_API const String JUCE_CALLTYPE operator+ (String string1, wchar_t characterToAppend); | |||
| /** Concatenates two strings. */ | |||
| @@ -12535,7 +12545,8 @@ public: | |||
| /** Sets the text in a text element. | |||
| Note that this is only a valid call if this element is a text element. If it's | |||
| not, then no action will be performed. | |||
| not, then no action will be performed. If you're trying to add text inside a normal | |||
| element, you probably want to use addTextElement() instead. | |||
| */ | |||
| void setText (const String& newText); | |||
| @@ -35101,7 +35112,8 @@ protected: | |||
| typedef AudioData::Pointer <DestSampleType, DestEndianness, AudioData::Interleaved, AudioData::NonConst> DestType; | |||
| typedef AudioData::Pointer <SourceSampleType, AudioData::NativeEndian, AudioData::NonInterleaved, AudioData::Const> SourceType; | |||
| static void write (void* destData, int numDestChannels, const int** source, int numSamples) throw() | |||
| static void write (void* destData, int numDestChannels, const int** source, | |||
| int numSamples, const int sourceOffset = 0) throw() | |||
| { | |||
| for (int i = 0; i < numDestChannels; ++i) | |||
| { | |||
| @@ -35109,7 +35121,7 @@ protected: | |||
| if (*source != 0) | |||
| { | |||
| dest.convertSamples (SourceType (*source), numSamples); | |||
| dest.convertSamples (SourceType (*source + sourceOffset), numSamples); | |||
| ++source; | |||
| } | |||
| else | |||
| @@ -224,7 +224,8 @@ protected: | |||
| typedef AudioData::Pointer <DestSampleType, DestEndianness, AudioData::Interleaved, AudioData::NonConst> DestType; | |||
| typedef AudioData::Pointer <SourceSampleType, AudioData::NativeEndian, AudioData::NonInterleaved, AudioData::Const> SourceType; | |||
| static void write (void* destData, int numDestChannels, const int** source, int numSamples) throw() | |||
| static void write (void* destData, int numDestChannels, const int** source, | |||
| int numSamples, const int sourceOffset = 0) throw() | |||
| { | |||
| for (int i = 0; i < numDestChannels; ++i) | |||
| { | |||
| @@ -232,7 +233,7 @@ protected: | |||
| if (*source != 0) | |||
| { | |||
| dest.convertSamples (SourceType (*source), numSamples); | |||
| dest.convertSamples (SourceType (*source + sourceOffset), numSamples); | |||
| ++source; | |||
| } | |||
| else | |||
| @@ -78,6 +78,16 @@ JUCE_API void JUCE_CALLTYPE initialiseJuce_NonGUI() | |||
| static_jassert (sizeof (uint32) == 4); | |||
| static_jassert (sizeof (int64) == 8); | |||
| static_jassert (sizeof (uint64) == 8); | |||
| #if JUCE_NATIVE_WCHAR_IS_UTF8 | |||
| static_jassert (sizeof (wchar_t) == 1); | |||
| #elif JUCE_NATIVE_WCHAR_IS_UTF16 | |||
| static_jassert (sizeof (wchar_t) == 2); | |||
| #elif JUCE_NATIVE_WCHAR_IS_UTF32 | |||
| static_jassert (sizeof (wchar_t) == 4); | |||
| #else | |||
| #error "native wchar_t size is unknown" | |||
| #endif | |||
| } | |||
| JUCE_API void JUCE_CALLTYPE shutdownJuce_NonGUI() | |||
| @@ -33,7 +33,7 @@ | |||
| */ | |||
| #define JUCE_MAJOR_VERSION 1 | |||
| #define JUCE_MINOR_VERSION 53 | |||
| #define JUCE_BUILDNUMBER 25 | |||
| #define JUCE_BUILDNUMBER 26 | |||
| /** Current Juce version number. | |||
| @@ -280,7 +280,7 @@ inline Type Atomic<Type>::operator+= (const Type amountToAdd) throw() | |||
| for (;;) | |||
| { | |||
| const Type oldValue (value); | |||
| const Type newValue (oldValue + amountToAdd); | |||
| const Type newValue (castFrom32Bit (castTo32Bit (oldValue) + castTo32Bit (amountToAdd))); | |||
| if (compareAndSetBool (newValue, oldValue)) | |||
| return newValue; | |||
| } | |||
| @@ -305,7 +305,7 @@ inline Type Atomic<Type>::operator++() throw() | |||
| return sizeof (Type) == 4 ? (Type) juce_InterlockedIncrement ((volatile long*) &value) | |||
| : (Type) juce_InterlockedIncrement64 ((volatile __int64*) &value); | |||
| #elif JUCE_ANDROID | |||
| return (Type) __atomic_inc (&value); | |||
| return (Type) __atomic_inc ((volatile int*) &value); | |||
| #elif JUCE_ATOMICS_GCC | |||
| return (Type) __sync_add_and_fetch (&value, 1); | |||
| #endif | |||
| @@ -321,7 +321,7 @@ inline Type Atomic<Type>::operator--() throw() | |||
| return sizeof (Type) == 4 ? (Type) juce_InterlockedDecrement ((volatile long*) &value) | |||
| : (Type) juce_InterlockedDecrement64 ((volatile __int64*) &value); | |||
| #elif JUCE_ANDROID | |||
| return (Type) __atomic_dec (&value); | |||
| return (Type) __atomic_dec ((volatile int*) &value); | |||
| #elif JUCE_ATOMICS_GCC | |||
| return (Type) __sync_add_and_fetch (&value, -1); | |||
| #endif | |||
| @@ -166,11 +166,12 @@ public: | |||
| } | |||
| } | |||
| //============================================================================== | |||
| inline operator jobject() const throw() { return obj; } | |||
| inline jobject get() const throw() { return obj; } | |||
| inline JNIEnv* getEnv() const throw() { return env; } | |||
| //============================================================================== | |||
| #define DECLARE_CALL_TYPE_METHOD(returnType, typeName) \ | |||
| returnType call##typeName##Method (jmethodID methodID, ... ) \ | |||
| { \ | |||
| @@ -202,6 +203,7 @@ public: | |||
| } | |||
| private: | |||
| //============================================================================== | |||
| JNIEnv* env; | |||
| jobject obj; | |||
| @@ -742,8 +742,13 @@ void Thread::killThread() | |||
| } | |||
| } | |||
| void Thread::setCurrentThreadName (const String& /*name*/) | |||
| void Thread::setCurrentThreadName (const String& name) | |||
| { | |||
| #if JUCE_MAC | |||
| pthread_setname_np (name.toUTF8()); | |||
| #elif JUCE_LINUX | |||
| prctl (PR_SET_NAME, name.toUTF8().getAddress(), 0, 0, 0); | |||
| #endif | |||
| } | |||
| bool Thread::setThreadPriority (void* handle, int priority) | |||
| @@ -56,6 +56,7 @@ | |||
| #include <net/if.h> | |||
| #include <sys/sysinfo.h> | |||
| #include <sys/file.h> | |||
| #include <sys/prctl.h> | |||
| #include <signal.h> | |||
| /* Got a build error here? You'll need to install the freetype library... | |||
| @@ -44,6 +44,8 @@ END_JUCE_NAMESPACE | |||
| - (bool) makeActive; | |||
| - (void) makeInactive; | |||
| - (void) reshape; | |||
| - (void) rightMouseDown: (NSEvent*) ev; | |||
| - (void) rightMouseUp: (NSEvent*) ev; | |||
| @end | |||
| @implementation ThreadSafeNSOpenGLView | |||
| @@ -112,6 +114,16 @@ END_JUCE_NAMESPACE | |||
| needsUpdate = true; | |||
| } | |||
| - (void) rightMouseDown: (NSEvent*) ev | |||
| { | |||
| [[self superview] rightMouseDown: ev]; | |||
| } | |||
| - (void) rightMouseUp: (NSEvent*) ev | |||
| { | |||
| [[self superview] rightMouseUp: ev]; | |||
| } | |||
| @end | |||
| BEGIN_JUCE_NAMESPACE | |||
| @@ -36,7 +36,7 @@ | |||
| class CharPointer_UTF16 | |||
| { | |||
| public: | |||
| #if JUCE_WINDOWS && ! DOXYGEN | |||
| #if JUCE_NATIVE_WCHAR_IS_UTF16 | |||
| typedef wchar_t CharType; | |||
| #else | |||
| typedef int16 CharType; | |||
| @@ -159,13 +159,13 @@ public: | |||
| /** Returns the number of characters in this string. */ | |||
| size_t length() const throw() | |||
| { | |||
| #if JUCE_NATIVE_WCHAR_IS_NOT_UTF32 | |||
| #if JUCE_NATIVE_WCHAR_IS_UTF32 && ! JUCE_ANDROID | |||
| return wcslen (data); | |||
| #else | |||
| size_t n = 0; | |||
| while (data[n] != 0) | |||
| ++n; | |||
| return n; | |||
| #else | |||
| return wcslen (data); | |||
| #endif | |||
| } | |||
| @@ -253,7 +253,7 @@ public: | |||
| return CharacterFunctions::compare (*this, other); | |||
| } | |||
| #if ! JUCE_NATIVE_WCHAR_IS_NOT_UTF32 | |||
| #if JUCE_NATIVE_WCHAR_IS_UTF32 && ! JUCE_ANDROID | |||
| /** Compares this string with another one. */ | |||
| int compare (const CharPointer_UTF32& other) const throw() | |||
| { | |||
| @@ -139,14 +139,14 @@ int CharacterFunctions::ftime (char* const dest, const int maxChars, const char* | |||
| int CharacterFunctions::ftime (juce_wchar* const dest, const int maxChars, const juce_wchar* const format, const struct tm* const tm) throw() | |||
| { | |||
| #if JUCE_NATIVE_WCHAR_IS_NOT_UTF32 | |||
| #if JUCE_NATIVE_WCHAR_IS_UTF32 && ! JUCE_ANDROID | |||
| return (int) wcsftime (dest, maxChars, format, tm); | |||
| #else | |||
| HeapBlock <char> tempDest; | |||
| tempDest.calloc (maxChars + 2); | |||
| int result = ftime (tempDest.getData(), maxChars, String (format).toUTF8(), tm); | |||
| CharPointer_UTF32 (dest).writeAll (CharPointer_UTF8 (tempDest.getData())); | |||
| return result; | |||
| #else | |||
| return (int) wcsftime (dest, maxChars, format, tm); | |||
| #endif | |||
| } | |||
| @@ -28,25 +28,35 @@ | |||
| //============================================================================== | |||
| #if JUCE_ANDROID && ! DOXYGEN | |||
| typedef uint32 juce_wchar; | |||
| #define JUCE_T(stringLiteral) CharPointer_UTF8 (stringLiteral) | |||
| #define JUCE_NATIVE_WCHAR_IS_NOT_UTF32 1 | |||
| #elif JUCE_WINDOWS && ! DOXYGEN | |||
| typedef uint32 juce_wchar; | |||
| #define JUCE_T(stringLiteral) L##stringLiteral | |||
| #define JUCE_NATIVE_WCHAR_IS_NOT_UTF32 1 | |||
| #if JUCE_WINDOWS && ! DOXYGEN | |||
| #define JUCE_NATIVE_WCHAR_IS_UTF8 0 | |||
| #define JUCE_NATIVE_WCHAR_IS_UTF16 1 | |||
| #define JUCE_NATIVE_WCHAR_IS_UTF32 0 | |||
| #else | |||
| /** A platform-independent unicode character type. */ | |||
| typedef wchar_t juce_wchar; | |||
| #define JUCE_T(stringLiteral) (L##stringLiteral) | |||
| /** This macro will be set to 1 if the compiler's native wchar_t is an 8-bit type. */ | |||
| #define JUCE_NATIVE_WCHAR_IS_UTF8 0 | |||
| /** This macro will be set to 1 if the compiler's native wchar_t is a 16-bit type. */ | |||
| #define JUCE_NATIVE_WCHAR_IS_UTF16 0 | |||
| /** This macro will be set to 1 if the compiler's native wchar_t is a 32-bit type. */ | |||
| #define JUCE_NATIVE_WCHAR_IS_UTF32 1 | |||
| #endif | |||
| #if JUCE_NATIVE_WCHAR_IS_UTF32 || DOXYGEN | |||
| /** A platform-independent 32-bit unicode character type. */ | |||
| typedef wchar_t juce_wchar; | |||
| #else | |||
| typedef uint32 juce_wchar; | |||
| #endif | |||
| /** This macro is deprecated, but preserved for compatibility with old code.*/ | |||
| #define JUCE_T(stringLiteral) (L##stringLiteral) | |||
| #if ! JUCE_DONT_DEFINE_MACROS | |||
| /** The 'T' macro allows a literal string to be compiled as unicode. | |||
| /** The 'T' macro is an alternative for using the "L" prefix in front of a string literal. | |||
| If you write your string literals in the form T("xyz"), it will be compiled as L"xyz" | |||
| or "xyz", depending on which representation is best for the String class to work with. | |||
| This macro is deprectated, but kept here for compatibility with old code. The best (i.e. | |||
| most portable) way to encode your string literals is just as standard 8-bit strings, but | |||
| using escaped utf-8 character codes for extended characters. | |||
| Because the 'T' symbol is occasionally used inside 3rd-party library headers which you | |||
| may need to include after juce.h, you can use the juce_withoutMacros.h file (in | |||
| @@ -42,6 +42,14 @@ BEGIN_JUCE_NAMESPACE | |||
| #error "JUCE_STRINGS_ARE_UNICODE is deprecated! All strings are now unicode by default." | |||
| #endif | |||
| #if JUCE_NATIVE_WCHAR_IS_UTF8 | |||
| typedef CharPointer_UTF8 CharPointer_wchar_t; | |||
| #elif JUCE_NATIVE_WCHAR_IS_UTF16 | |||
| typedef CharPointer_UTF16 CharPointer_wchar_t; | |||
| #else | |||
| typedef CharPointer_UTF32 CharPointer_wchar_t; | |||
| #endif | |||
| NewLine newLine; | |||
| //============================================================================== | |||
| @@ -265,7 +273,7 @@ String::String (const char* const t) | |||
| 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())); | |||
| jassert (t == 0 || CharPointer_ASCII::isValidString (t, std::numeric_limits<int>::max())); | |||
| } | |||
| String::String (const char* const t, const size_t maxChars) | |||
| @@ -284,7 +292,7 @@ String::String (const char* const t, const size_t maxChars) | |||
| 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)); | |||
| jassert (t == 0 || CharPointer_ASCII::isValidString (t, (int) maxChars)); | |||
| } | |||
| String::String (const juce_wchar* const t) | |||
| @@ -322,14 +330,16 @@ String::String (const CharPointer_ASCII& t) | |||
| { | |||
| } | |||
| #if JUCE_WINDOWS | |||
| #if ! JUCE_NATIVE_WCHAR_IS_UTF32 | |||
| String::String (const wchar_t* const t) | |||
| : text (StringHolder::createFromCharPointer (CharPointer_UTF16 (t))) | |||
| : text (StringHolder::createFromCharPointer | |||
| (CharPointer_wchar_t (reinterpret_cast <const CharPointer_wchar_t::CharType*> (t)))) | |||
| { | |||
| } | |||
| String::String (const wchar_t* const t, size_t maxChars) | |||
| : text (StringHolder::createFromCharPointer (CharPointer_UTF16 (t), maxChars)) | |||
| : text (StringHolder::createFromCharPointer | |||
| (CharPointer_wchar_t (reinterpret_cast <const CharPointer_wchar_t::CharType*> (t)), maxChars)) | |||
| { | |||
| } | |||
| #endif | |||
| @@ -717,7 +727,7 @@ String& String::operator+= (const juce_wchar ch) | |||
| return operator+= (static_cast <const juce_wchar*> (asString)); | |||
| } | |||
| #if JUCE_WINDOWS | |||
| #if ! JUCE_NATIVE_WCHAR_IS_UTF32 | |||
| String& String::operator+= (const wchar_t ch) | |||
| { | |||
| return operator+= ((juce_wchar) ch); | |||
| @@ -786,7 +796,7 @@ JUCE_API const String JUCE_CALLTYPE operator+ (String string1, const juce_wchar | |||
| return string1 += string2; | |||
| } | |||
| #if JUCE_WINDOWS | |||
| #if ! JUCE_NATIVE_WCHAR_IS_UTF32 | |||
| JUCE_API const String JUCE_CALLTYPE operator+ (String string1, wchar_t string2) | |||
| { | |||
| return string1 += string2; | |||
| @@ -794,7 +804,7 @@ JUCE_API const String JUCE_CALLTYPE operator+ (String string1, wchar_t string2) | |||
| JUCE_API const String JUCE_CALLTYPE operator+ (String string1, const wchar_t* string2) | |||
| { | |||
| string1.appendCharPointer (CharPointer_UTF16 (string2)); | |||
| string1.appendCharPointer (CharPointer_wchar_t (reinterpret_cast <const CharPointer_wchar_t::CharType*> (string2))); | |||
| return string1; | |||
| } | |||
| @@ -2117,9 +2127,7 @@ const String String::fromUTF8 (const char* const buffer, int bufferSizeBytes) | |||
| //============================================================================== | |||
| const char* String::toCString() const | |||
| { | |||
| #if JUCE_NATIVE_WCHAR_IS_NOT_UTF32 | |||
| return toUTF8(); | |||
| #else | |||
| #if JUCE_NATIVE_WCHAR_IS_UTF32 && ! JUCE_ANDROID | |||
| if (isEmpty()) | |||
| return reinterpret_cast <const char*> (text.getAddress()); | |||
| @@ -2128,29 +2136,31 @@ const char* String::toCString() const | |||
| wcstombs (extraSpace, text, len); | |||
| extraSpace [len] = 0; | |||
| return extraSpace; | |||
| #else | |||
| return toUTF8(); | |||
| #endif | |||
| } | |||
| int String::getNumBytesAsCString() const throw() | |||
| { | |||
| #if JUCE_NATIVE_WCHAR_IS_NOT_UTF32 | |||
| return getNumBytesAsUTF8(); | |||
| #else | |||
| #if JUCE_NATIVE_WCHAR_IS_UTF32 && ! JUCE_ANDROID | |||
| return (int) wcstombs (0, text, 0); | |||
| #else | |||
| return getNumBytesAsUTF8(); | |||
| #endif | |||
| } | |||
| int String::copyToCString (char* destBuffer, const int maxBufferSizeBytes) const throw() | |||
| { | |||
| #if JUCE_NATIVE_WCHAR_IS_NOT_UTF32 | |||
| return copyToUTF8 (destBuffer, maxBufferSizeBytes); | |||
| #else | |||
| #if JUCE_NATIVE_WCHAR_IS_UTF32 && ! JUCE_ANDROID | |||
| const int numBytes = (int) wcstombs (destBuffer, text, maxBufferSizeBytes); | |||
| if (destBuffer != 0 && numBytes >= 0) | |||
| destBuffer [numBytes] = 0; | |||
| return numBytes; | |||
| #else | |||
| return copyToUTF8 (destBuffer, maxBufferSizeBytes); | |||
| #endif | |||
| } | |||
| @@ -126,7 +126,7 @@ public: | |||
| /** Creates a string from an ASCII character string */ | |||
| String (const CharPointer_ASCII& text); | |||
| #if JUCE_WINDOWS | |||
| #if ! JUCE_NATIVE_WCHAR_IS_UTF32 | |||
| /** Creates a string from a UTF-16 character string */ | |||
| String (const wchar_t* text); | |||
| @@ -175,7 +175,7 @@ public: | |||
| String& operator+= (char characterToAppend); | |||
| /** Appends a character at the end of this string. */ | |||
| String& operator+= (juce_wchar characterToAppend); | |||
| #if JUCE_WINDOWS | |||
| #if ! JUCE_NATIVE_WCHAR_IS_UTF32 | |||
| /** Appends a character at the end of this string. */ | |||
| String& operator+= (wchar_t characterToAppend); | |||
| /** Appends another string at the end of this one. */ | |||
| @@ -1219,7 +1219,7 @@ JUCE_API const String JUCE_CALLTYPE operator+ (String string1, const juce_wchar | |||
| JUCE_API const String JUCE_CALLTYPE operator+ (String string1, char characterToAppend); | |||
| /** Concatenates two strings. */ | |||
| JUCE_API const String JUCE_CALLTYPE operator+ (String string1, juce_wchar characterToAppend); | |||
| #if JUCE_WINDOWS | |||
| #if ! JUCE_NATIVE_WCHAR_IS_UTF32 | |||
| /** Concatenates two strings. */ | |||
| JUCE_API const String JUCE_CALLTYPE operator+ (String string1, wchar_t characterToAppend); | |||
| /** Concatenates two strings. */ | |||
| @@ -638,7 +638,8 @@ public: | |||
| /** Sets the text in a text element. | |||
| Note that this is only a valid call if this element is a text element. If it's | |||
| not, then no action will be performed. | |||
| not, then no action will be performed. If you're trying to add text inside a normal | |||
| element, you probably want to use addTextElement() instead. | |||
| */ | |||
| void setText (const String& newText); | |||