diff --git a/extras/Jucer (experimental)/Builds/MacOSX/The Jucer.xcodeproj/project.pbxproj b/extras/Jucer (experimental)/Builds/MacOSX/The Jucer.xcodeproj/project.pbxproj
index 9341922d87..0526b0516d 100644
--- a/extras/Jucer (experimental)/Builds/MacOSX/The Jucer.xcodeproj/project.pbxproj
+++ b/extras/Jucer (experimental)/Builds/MacOSX/The Jucer.xcodeproj/project.pbxproj
@@ -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,
diff --git a/extras/Jucer (experimental)/Builds/VisualStudio2005/The Jucer.vcproj b/extras/Jucer (experimental)/Builds/VisualStudio2005/The Jucer.vcproj
index b81b006292..4c768a4e60 100644
--- a/extras/Jucer (experimental)/Builds/VisualStudio2005/The Jucer.vcproj
+++ b/extras/Jucer (experimental)/Builds/VisualStudio2005/The Jucer.vcproj
@@ -162,6 +162,7 @@
+
diff --git a/extras/Jucer (experimental)/Builds/VisualStudio2008/The Jucer.vcproj b/extras/Jucer (experimental)/Builds/VisualStudio2008/The Jucer.vcproj
index dfcfa551f9..6c95751d08 100644
--- a/extras/Jucer (experimental)/Builds/VisualStudio2008/The Jucer.vcproj
+++ b/extras/Jucer (experimental)/Builds/VisualStudio2008/The Jucer.vcproj
@@ -162,6 +162,7 @@
+
diff --git a/extras/Jucer (experimental)/Builds/VisualStudio2010/The Jucer.vcxproj b/extras/Jucer (experimental)/Builds/VisualStudio2010/The Jucer.vcxproj
index 6971cec82c..9ca167f9a5 100644
--- a/extras/Jucer (experimental)/Builds/VisualStudio2010/The Jucer.vcxproj
+++ b/extras/Jucer (experimental)/Builds/VisualStudio2010/The Jucer.vcxproj
@@ -167,6 +167,7 @@
+
diff --git a/extras/Jucer (experimental)/Builds/VisualStudio2010/The Jucer.vcxproj.filters b/extras/Jucer (experimental)/Builds/VisualStudio2010/The Jucer.vcxproj.filters
index e077948cb6..19e09167bc 100644
--- a/extras/Jucer (experimental)/Builds/VisualStudio2010/The Jucer.vcxproj.filters
+++ b/extras/Jucer (experimental)/Builds/VisualStudio2010/The Jucer.vcxproj.filters
@@ -183,6 +183,9 @@
The Jucer\Project
+
+ The Jucer\Project
+
The Jucer\Project
diff --git a/extras/Jucer (experimental)/Jucer.jucer b/extras/Jucer (experimental)/Jucer.jucer
index b9e039f2d9..588b158e16 100644
--- a/extras/Jucer (experimental)/Jucer.jucer
+++ b/extras/Jucer (experimental)/Jucer.jucer
@@ -90,6 +90,8 @@
file="Source/Project/jucer_ProjectExporter.cpp"/>
+
= 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());
diff --git a/extras/Jucer (experimental)/Source/Project/jucer_Project.h b/extras/Jucer (experimental)/Source/Project/jucer_Project.h
index a171df4f95..8859cf2e17 100644
--- a/extras/Jucer (experimental)/Source/Project/jucer_Project.h
+++ b/extras/Jucer (experimental)/Source/Project/jucer_Project.h
@@ -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"); }
diff --git a/extras/Jucer (experimental)/Source/Project/jucer_ProjectExport_Android.h b/extras/Jucer (experimental)/Source/Project/jucer_ProjectExport_Android.h
new file mode 100644
index 0000000000..05cb736eea
--- /dev/null
+++ b/extras/Jucer (experimental)/Source/Project/jucer_ProjectExport_Android.h
@@ -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 & 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 manifest (createManifestXML());
+ writeXmlOrThrow (*manifest, target.getChildFile ("AndroidManifest.xml"), "utf-8", 100);
+ }
+
+ writeJNIMakefile (jniFolder.getChildFile ("Android.mk"));
+
+ {
+ ScopedPointer 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& 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 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& 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__
diff --git a/extras/Jucer (experimental)/Source/Project/jucer_ProjectExport_MSVC.h b/extras/Jucer (experimental)/Source/Project/jucer_ProjectExport_MSVC.h
index 169acdc843..cc5e54e292 100644
--- a/extras/Jucer (experimental)/Source/Project/jucer_ProjectExport_MSVC.h
+++ b/extras/Jucer (experimental)/Source/Project/jucer_ProjectExport_MSVC.h
@@ -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 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:
diff --git a/extras/Jucer (experimental)/Source/Project/jucer_ProjectExport_Make.h b/extras/Jucer (experimental)/Source/Project/jucer_ProjectExport_Make.h
index 582f74fc5c..790b43bf09 100644
--- a/extras/Jucer (experimental)/Source/Project/jucer_ProjectExport_Make.h
+++ b/extras/Jucer (experimental)/Source/Project/jucer_ProjectExport_Make.h
@@ -83,7 +83,7 @@ public:
}
//==============================================================================
- const String create()
+ void create()
{
Array 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()
diff --git a/extras/Jucer (experimental)/Source/Project/jucer_ProjectExport_XCode.h b/extras/Jucer (experimental)/Source/Project/jucer_ProjectExport_XCode.h
index 430b49581b..1d8bb91c7c 100644
--- a/extras/Jucer (experimental)/Source/Project/jucer_ProjectExport_XCode.h
+++ b/extras/Jucer (experimental)/Source/Project/jucer_ProjectExport_XCode.h
@@ -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 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, "");
- return FileHelpers::overwriteFileWithNewDataIfDifferent (infoPlistFile, mo);
+ overwriteFileIfDifferentOrThrow (infoPlistFile, mo);
}
const StringArray getHeaderSearchPaths (const Project::BuildConfiguration& config)
diff --git a/extras/Jucer (experimental)/Source/Project/jucer_ProjectExporter.cpp b/extras/Jucer (experimental)/Source/Project/jucer_ProjectExporter.cpp
index 0798663e07..ec07044633 100644
--- a/extras/Jucer (experimental)/Source/Project/jucer_ProjectExporter.cpp
+++ b/extras/Jucer (experimental)/Source/Project/jucer_ProjectExporter.cpp
@@ -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);
diff --git a/extras/Jucer (experimental)/Source/Project/jucer_ProjectExporter.h b/extras/Jucer (experimental)/Source/Project/jucer_ProjectExporter.h
index 914ad97e9f..18aa40b4da 100644
--- a/extras/Jucer (experimental)/Source/Project/jucer_ProjectExporter.h
+++ b/extras/Jucer (experimental)/Source/Project/jucer_ProjectExporter.h
@@ -53,7 +53,7 @@ public:
virtual bool usesMMFiles() const = 0;
virtual void createPropertyEditors (Array & 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 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 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);
};
diff --git a/extras/Jucer (experimental)/Source/Project/jucer_ProjectSaver.h b/extras/Jucer (experimental)/Source/Project/jucer_ProjectSaver.h
index 2148a7edc1..0fde6082e9 100644
--- a/extras/Jucer (experimental)/Source/Project/jucer_ProjectSaver.h
+++ b/extras/Jucer (experimental)/Source/Project/jucer_ProjectSaver.h
@@ -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
{
diff --git a/extras/Jucer (experimental)/Source/Utility/jucer_MiscUtilities.cpp b/extras/Jucer (experimental)/Source/Utility/jucer_MiscUtilities.cpp
index c9cfbd0e02..70833cbd04 100644
--- a/extras/Jucer (experimental)/Source/Utility/jucer_MiscUtilities.cpp
+++ b/extras/Jucer (experimental)/Source/Utility/jucer_MiscUtilities.cpp
@@ -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)
diff --git a/extras/Jucer (experimental)/Source/Utility/jucer_MiscUtilities.h b/extras/Jucer (experimental)/Source/Utility/jucer_MiscUtilities.h
index 9fb70e2afb..437b7096f3 100644
--- a/extras/Jucer (experimental)/Source/Utility/jucer_MiscUtilities.h
+++ b/extras/Jucer (experimental)/Source/Utility/jucer_MiscUtilities.h
@@ -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);
//==============================================================================
diff --git a/extras/Jucer (experimental)/Source/Utility/jucer_PresetIDs.h b/extras/Jucer (experimental)/Source/Utility/jucer_PresetIDs.h
index 8976eac34c..29ad3db4c1 100644
--- a/extras/Jucer (experimental)/Source/Utility/jucer_PresetIDs.h
+++ b/extras/Jucer (experimental)/Source/Utility/jucer_PresetIDs.h
@@ -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");
diff --git a/juce_amalgamated.cpp b/juce_amalgamated.cpp
index dcbc262c37..b13f4fb855 100644
--- a/juce_amalgamated.cpp
+++ b/juce_amalgamated.cpp
@@ -776,6 +776,7 @@ protected:
#include
#include
#include
+#include
#include
/* 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 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::max()));
+ jassert (t == 0 || CharPointer_ASCII::isValidString (t, std::numeric_limits::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 (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 (t)), maxChars))
{
}
#endif
@@ -11997,7 +12018,7 @@ String& String::operator+= (const juce_wchar ch)
return operator+= (static_cast (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 (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 (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)
diff --git a/juce_amalgamated.h b/juce_amalgamated.h
index 131e5a5bd4..eb63af9d46 100644
--- a/juce_amalgamated.h
+++ b/juce_amalgamated.h
@@ -73,7 +73,7 @@ namespace JuceDummyNamespace {}
*/
#define JUCE_MAJOR_VERSION 1
#define JUCE_MINOR_VERSION 53
-#define JUCE_BUILDNUMBER 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::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::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::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 DestType;
typedef AudioData::Pointer 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
diff --git a/src/audio/audio_file_formats/juce_AudioFormatWriter.h b/src/audio/audio_file_formats/juce_AudioFormatWriter.h
index f9c5555343..87dc6184db 100644
--- a/src/audio/audio_file_formats/juce_AudioFormatWriter.h
+++ b/src/audio/audio_file_formats/juce_AudioFormatWriter.h
@@ -224,7 +224,8 @@ protected:
typedef AudioData::Pointer DestType;
typedef AudioData::Pointer 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
diff --git a/src/core/juce_Initialisation.cpp b/src/core/juce_Initialisation.cpp
index 93c574ea50..0ff27436f1 100644
--- a/src/core/juce_Initialisation.cpp
+++ b/src/core/juce_Initialisation.cpp
@@ -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()
diff --git a/src/core/juce_StandardHeader.h b/src/core/juce_StandardHeader.h
index 7a43ba3425..99a2f24be4 100644
--- a/src/core/juce_StandardHeader.h
+++ b/src/core/juce_StandardHeader.h
@@ -33,7 +33,7 @@
*/
#define JUCE_MAJOR_VERSION 1
#define JUCE_MINOR_VERSION 53
-#define JUCE_BUILDNUMBER 25
+#define JUCE_BUILDNUMBER 26
/** Current Juce version number.
diff --git a/src/memory/juce_Atomic.h b/src/memory/juce_Atomic.h
index cb5b0969f6..db0f47c4f6 100644
--- a/src/memory/juce_Atomic.h
+++ b/src/memory/juce_Atomic.h
@@ -280,7 +280,7 @@ inline Type Atomic::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::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::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
diff --git a/src/native/android/juce_android_NativeCode.cpp b/src/native/android/juce_android_NativeCode.cpp
index d1964809ea..2274cf79b4 100644
--- a/src/native/android/juce_android_NativeCode.cpp
+++ b/src/native/android/juce_android_NativeCode.cpp
@@ -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;
diff --git a/src/native/common/juce_posix_SharedCode.h b/src/native/common/juce_posix_SharedCode.h
index 5823fce07a..caf6a0f24d 100644
--- a/src/native/common/juce_posix_SharedCode.h
+++ b/src/native/common/juce_posix_SharedCode.h
@@ -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)
diff --git a/src/native/linux/juce_linux_NativeIncludes.h b/src/native/linux/juce_linux_NativeIncludes.h
index 1d0e38ec76..abb4745a13 100644
--- a/src/native/linux/juce_linux_NativeIncludes.h
+++ b/src/native/linux/juce_linux_NativeIncludes.h
@@ -56,6 +56,7 @@
#include
#include
#include
+#include
#include
/* Got a build error here? You'll need to install the freetype library...
diff --git a/src/native/mac/juce_mac_OpenGLComponent.mm b/src/native/mac/juce_mac_OpenGLComponent.mm
index 848a4dbc9d..f5d9069f7a 100644
--- a/src/native/mac/juce_mac_OpenGLComponent.mm
+++ b/src/native/mac/juce_mac_OpenGLComponent.mm
@@ -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
diff --git a/src/text/juce_CharPointer_UTF16.h b/src/text/juce_CharPointer_UTF16.h
index fbba22c72f..3b82c2cb64 100644
--- a/src/text/juce_CharPointer_UTF16.h
+++ b/src/text/juce_CharPointer_UTF16.h
@@ -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;
diff --git a/src/text/juce_CharPointer_UTF32.h b/src/text/juce_CharPointer_UTF32.h
index a6872e89a7..ca02c277a2 100644
--- a/src/text/juce_CharPointer_UTF32.h
+++ b/src/text/juce_CharPointer_UTF32.h
@@ -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()
{
diff --git a/src/text/juce_CharacterFunctions.cpp b/src/text/juce_CharacterFunctions.cpp
index cdab05eea4..1ff37c63b7 100644
--- a/src/text/juce_CharacterFunctions.cpp
+++ b/src/text/juce_CharacterFunctions.cpp
@@ -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 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
}
diff --git a/src/text/juce_CharacterFunctions.h b/src/text/juce_CharacterFunctions.h
index f456520234..f713fc12e4 100644
--- a/src/text/juce_CharacterFunctions.h
+++ b/src/text/juce_CharacterFunctions.h
@@ -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
diff --git a/src/text/juce_String.cpp b/src/text/juce_String.cpp
index b06bf11984..7d637dbf98 100644
--- a/src/text/juce_String.cpp
+++ b/src/text/juce_String.cpp
@@ -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::max()));
+ jassert (t == 0 || CharPointer_ASCII::isValidString (t, std::numeric_limits::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 (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 (t)), maxChars))
{
}
#endif
@@ -717,7 +727,7 @@ String& String::operator+= (const juce_wchar ch)
return operator+= (static_cast (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 (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 (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
}
diff --git a/src/text/juce_String.h b/src/text/juce_String.h
index 00a06ac02f..61d41fc989 100644
--- a/src/text/juce_String.h
+++ b/src/text/juce_String.h
@@ -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. */
diff --git a/src/text/juce_XmlElement.h b/src/text/juce_XmlElement.h
index 9081f68c26..9aa35b744e 100644
--- a/src/text/juce_XmlElement.h
+++ b/src/text/juce_XmlElement.h
@@ -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);