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