Browse Source

Merge branch 'master' of github.com:julianstorer/JUCE

pull/4/head
falkTX 10 years ago
parent
commit
873eb9c593
20 changed files with 656 additions and 36 deletions
  1. +14
    -1
      examples/Demo/Source/Demos/WavefrontObjParser.h
  2. +14
    -1
      examples/OpenGLAppExample/Source/Resources/WavefrontObjParser.h
  3. +4
    -0
      extras/Introjucer/JuceLibraryCode/AppConfig.h
  4. +3
    -0
      extras/Introjucer/Source/Project Saving/jucer_ProjectExport_Make.h
  5. +1
    -0
      extras/Introjucer/Source/Project Saving/jucer_ProjectExport_XCode.h
  6. +3
    -1
      modules/juce_audio_plugin_client/AAX/juce_AAX_Wrapper.cpp
  7. +7
    -2
      modules/juce_audio_plugin_client/utility/juce_PluginHostType.h
  8. +0
    -1
      modules/juce_audio_processors/processors/juce_AudioProcessorGraph.cpp
  9. +7
    -0
      modules/juce_core/juce_core.cpp
  10. +11
    -0
      modules/juce_core/juce_core.h
  11. +472
    -0
      modules/juce_core/native/juce_curl_Network.cpp
  12. +70
    -12
      modules/juce_core/native/juce_linux_Network.cpp
  13. +5
    -1
      modules/juce_graphics/fonts/juce_Font.h
  14. +2
    -2
      modules/juce_gui_basics/components/juce_Component.h
  15. +7
    -6
      modules/juce_gui_basics/keyboard/juce_TextEditorKeyMapper.h
  16. +6
    -0
      modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V2.cpp
  17. +15
    -0
      modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V2.h
  18. +3
    -0
      modules/juce_gui_basics/widgets/juce_TableListBox.h
  19. +11
    -9
      modules/juce_gui_basics/windows/juce_AlertWindow.cpp
  20. +1
    -0
      modules/juce_gui_basics/windows/juce_AlertWindow.h

+ 14
- 1
examples/Demo/Source/Demos/WavefrontObjParser.h View File

@@ -101,7 +101,20 @@ private:
struct TripleIndex
{
TripleIndex() noexcept : vertexIndex (-1), textureIndex (-1), normalIndex (-1) {}
bool operator< (const TripleIndex& other) const noexcept { return vertexIndex < other.vertexIndex; }
bool operator< (const TripleIndex& other) const noexcept
{
if (this == &other)
return false;
if (vertexIndex != other.vertexIndex)
return vertexIndex < other.vertexIndex;
if (textureIndex != other.textureIndex)
return textureIndex < other.textureIndex;
return normalIndex < other.normalIndex;
}
int vertexIndex, textureIndex, normalIndex;
};


+ 14
- 1
examples/OpenGLAppExample/Source/Resources/WavefrontObjParser.h View File

@@ -101,7 +101,20 @@ private:
struct TripleIndex
{
TripleIndex() noexcept : vertexIndex (-1), textureIndex (-1), normalIndex (-1) {}
bool operator< (const TripleIndex& other) const noexcept { return vertexIndex < other.vertexIndex; }
bool operator< (const TripleIndex& other) const noexcept
{
if (this == &other)
return false;
if (vertexIndex != other.vertexIndex)
return vertexIndex < other.vertexIndex;
if (textureIndex != other.textureIndex)
return textureIndex < other.textureIndex;
return normalIndex < other.normalIndex;
}
int vertexIndex, textureIndex, normalIndex;
};


+ 4
- 0
extras/Introjucer/JuceLibraryCode/AppConfig.h View File

@@ -58,6 +58,10 @@
//#define JUCE_INCLUDE_ZLIB_CODE
#endif
#ifndef JUCE_USE_CURL
//#define JUCE_USE_CURL
#endif
//==============================================================================
// juce_graphics flags:


+ 3
- 0
extras/Introjucer/Source/Project Saving/jucer_ProjectExport_Make.h View File

@@ -184,6 +184,9 @@ private:
for (int i = 0; i < linuxLibs.size(); ++i)
out << " -l" << linuxLibs[i];
if (getProject().isConfigFlagEnabled ("JUCE_USE_CURL"))
out << " -lcurl";
StringArray libraries;
libraries.addTokens (getExternalLibrariesString(), ";", "\"'");
libraries.removeEmptyStrings();


+ 1
- 0
extras/Introjucer/Source/Project Saving/jucer_ProjectExport_XCode.h View File

@@ -654,6 +654,7 @@ private:
static const char* kDefaultiOSOrientationStrings[] =
{
"UIInterfaceOrientationPortrait",
"UIInterfaceOrientationPortraitUpsideDown",
"UIInterfaceOrientationLandscapeLeft",
"UIInterfaceOrientationLandscapeRight",
nullptr


+ 3
- 1
modules/juce_audio_plugin_client/AAX/juce_AAX_Wrapper.cpp View File

@@ -918,9 +918,11 @@ struct AAXClasses
for (int parameterIndex = 0; parameterIndex < numParameters; ++parameterIndex)
{
AAX_CString paramName (audioProcessor.getParameterName (parameterIndex, 31).toRawUTF8());
AAX_IParameter* parameter
= new AAX_CParameter<float> (IndexAsParamID (parameterIndex),
audioProcessor.getParameterName (parameterIndex, 31).toRawUTF8(),
paramName,
audioProcessor.getParameterDefaultValue (parameterIndex),
AAX_CLinearTaperDelegate<float, 0>(),
AAX_CNumberDisplayDelegate<float, 3>(),


+ 7
- 2
modules/juce_audio_plugin_client/utility/juce_PluginHostType.h View File

@@ -47,6 +47,7 @@ public:
CakewalkSonarGeneric,
DigidesignProTools,
DigitalPerformer,
FinalCut,
FruityLoops,
MagixSamplitude,
MergingPyramix,
@@ -72,8 +73,8 @@ public:
StudioOne,
Tracktion3,
TracktionGeneric,
WaveBurner,
VBVSTScanner
VBVSTScanner,
WaveBurner
};
HostType type;
@@ -87,6 +88,7 @@ public:
bool isCubase7orLater() const noexcept { return isCubase() && ! (type == SteinbergCubase4 || type == SteinbergCubase5 || type == SteinbergCubase6); }
bool isCubaseBridged() const noexcept { return type == SteinbergCubase5Bridged; }
bool isLogic() const noexcept { return type == AppleLogic; }
bool isFinalCut() const noexcept { return type == FinalCut; }
bool isFruityLoops() const noexcept { return type == FruityLoops; }
bool isNuendo() const noexcept { return type == SteinbergNuendo3 || type == SteinbergNuendo4 || type == SteinbergNuendo5 || type == SteinbergNuendoGeneric; }
bool isPremiere() const noexcept { return type == AdobePremierePro; }
@@ -120,6 +122,7 @@ public:
case CakewalkSonarGeneric: return "Cakewalk Sonar";
case DigidesignProTools: return "ProTools";
case DigitalPerformer: return "DigitalPerformer";
case FinalCut: return "Final Cut";
case FruityLoops: return "FruityLoops";
case MagixSamplitude: return "Magix Samplitude";
case MergingPyramix: return "Pyramix";
@@ -167,6 +170,8 @@ private:
const String hostFilename (File (hostPath).getFileName());
#if JUCE_MAC
if (hostPath.containsIgnoreCase ("Final Cut Pro.app")) return FinalCut;
if (hostPath.containsIgnoreCase ("Final Cut Pro Trial.app")) return FinalCut;
if (hostPath.containsIgnoreCase ("Live 6.")) return AbletonLive6;
if (hostPath.containsIgnoreCase ("Live 7.")) return AbletonLive7;
if (hostPath.containsIgnoreCase ("Live 8.")) return AbletonLive8;


+ 0
- 1
modules/juce_audio_processors/processors/juce_AudioProcessorGraph.cpp View File

@@ -977,7 +977,6 @@ bool AudioProcessorGraph::removeNode (const uint32 nodeId)
{
if (nodes.getUnchecked(i)->nodeId == nodeId)
{
nodes.getUnchecked(i)->setParentGraph (nullptr);
nodes.remove (i);
triggerAsyncUpdate();


+ 7
- 0
modules/juce_core/juce_core.cpp View File

@@ -82,6 +82,10 @@
#if JUCE_LINUX
#include <langinfo.h>
#include <ifaddrs.h>
#if JUCE_USE_CURL
#include <curl/curl.h>
#endif
#endif
#include <pwd.h>
@@ -210,6 +214,9 @@ namespace juce
#include "native/juce_linux_CommonFile.cpp"
#include "native/juce_linux_Files.cpp"
#include "native/juce_linux_Network.cpp"
#if JUCE_USE_CURL
#include "native/juce_curl_Network.cpp"
#endif
#include "native/juce_linux_SystemStats.cpp"
#include "native/juce_linux_Threads.cpp"


+ 11
- 0
modules/juce_core/juce_core.h View File

@@ -126,6 +126,17 @@
#define JUCE_ZLIB_INCLUDE_PATH <zlib.h>
#endif
/** Config: JUCE_USE_CURL
Enables http/https support via libcurl (Linux only). Enabling this will add an additional
run-time dynmic dependency to libcurl.
If you disable this then https/ssl support will not be available on linux.
*/
#ifndef JUCE_USE_CURL
#define JUCE_USE_CURL 0
#endif
/* Config: JUCE_CATCH_UNHANDLED_EXCEPTIONS
If enabled, this will add some exception-catching code to forward unhandled exceptions
to your JUCEApplicationBase::unhandledException() callback.


+ 472
- 0
modules/juce_core/native/juce_curl_Network.cpp View File

@@ -0,0 +1,472 @@
/*
==============================================================================
This file is part of the juce_core module of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission to use, copy, modify, and/or distribute this software for any purpose with
or without fee is hereby granted, provided that the above copyright notice and this
permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
------------------------------------------------------------------------------
NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
All other JUCE modules are covered by a dual GPL/commercial license, so if you are
using any other modules, be sure to check that you also comply with their license.
For more details, visit www.juce.com
==============================================================================
*/
class WebInputStream : public InputStream
{
public:
WebInputStream (const String& address, bool isPost, const MemoryBlock& postData,
URL::OpenStreamProgressCallback* progressCallback, void* progressCallbackContext,
const String& headers, int timeOutMs, StringPairArray* responseHeaders,
const int maxRedirects)
: multi (nullptr), curl (nullptr), headerList (nullptr), lastError (CURLE_OK),
contentLength (-1), streamPos (0),
finished (false), skipBytes (0),
postBuffer (nullptr), postPosition (0)
{
statusCode = -1;
if (init() && setOptions (address, timeOutMs, (responseHeaders != nullptr),
maxRedirects, headers, isPost, postData.getSize()))
{
connect (responseHeaders, isPost, postData, progressCallback, progressCallbackContext);
}
else
{
cleanup();
}
}
~WebInputStream()
{
cleanup();
}
//==============================================================================
// Input Stream overrides
bool isError() const { return curl == nullptr || lastError != CURLE_OK; }
bool isExhausted() override { return (isError() || finished) && curlBuffer.getSize() == 0; }
int64 getPosition() override { return streamPos; }
int64 getTotalLength() override { return contentLength; }
int read (void* buffer, int bytesToRead) override
{
return readOrSkip (buffer, bytesToRead, false);
}
bool setPosition (int64 wantedPos) override
{
const int amountToSkip = static_cast<int> (wantedPos - getPosition());
if (amountToSkip < 0)
return false;
if (amountToSkip == 0)
return true;
const int actuallySkipped = readOrSkip (nullptr, amountToSkip, true);
return actuallySkipped == amountToSkip;
}
//==============================================================================
int statusCode;
private:
//==============================================================================
bool init()
{
multi = curl_multi_init();
if (multi != nullptr)
{
curl = curl_easy_init();
if (curl != nullptr)
if (curl_multi_add_handle (multi, curl) == CURLM_OK)
return true;
}
cleanup();
return false;
}
void cleanup()
{
if (curl != nullptr)
{
curl_multi_remove_handle (multi, curl);
if (headerList != nullptr)
{
curl_slist_free_all (headerList);
headerList = nullptr;
}
curl_easy_cleanup (curl);
curl = nullptr;
}
if (multi != nullptr)
{
curl_multi_cleanup (multi);
multi = nullptr;
}
}
//==============================================================================
bool setOptions (const String& address, int timeOutMs, bool wantsHeaders,
const int maxRedirects, const String& headers,
bool isPost, size_t postSize)
{
if (curl_easy_setopt (curl, CURLOPT_URL, address.toRawUTF8()) == CURLE_OK
&& curl_easy_setopt (curl, CURLOPT_WRITEDATA, this) == CURLE_OK
&& curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, StaticCurlWrite) == CURLE_OK
&& curl_easy_setopt (curl, CURLOPT_MAXREDIRS, static_cast<long> (maxRedirects)) == CURLE_OK)
{
if (isPost)
{
if (curl_easy_setopt (curl, CURLOPT_READDATA, this) != CURLE_OK
|| curl_easy_setopt (curl, CURLOPT_READFUNCTION, StaticCurlRead) != CURLE_OK)
return false;
if (curl_easy_setopt (curl, CURLOPT_POST, 1) != CURLE_OK
|| curl_easy_setopt (curl, CURLOPT_POSTFIELDSIZE_LARGE, static_cast<curl_off_t> (postSize)) != CURLE_OK)
return false;
}
// do we want to parse the headers
if (wantsHeaders)
{
if (curl_easy_setopt (curl, CURLOPT_HEADERDATA, this) != CURLE_OK
|| curl_easy_setopt (curl, CURLOPT_HEADERFUNCTION, StaticCurlHeader) != CURLE_OK)
return false;
}
if (headers.isNotEmpty())
{
const StringArray headerLines = StringArray::fromLines (headers);
// fromLines will always return at least one line if the string is not empty
jassert (headerLines.size() > 0);
headerList = curl_slist_append (headerList, headerLines [0].toRawUTF8());
for (int i = 1; (i < headerLines.size() && headerList != nullptr); ++i)
headerList = curl_slist_append (headerList, headerLines [i].toRawUTF8());
if (headerList == nullptr)
return false;
if (curl_easy_setopt (curl, CURLOPT_HTTPHEADER, headerList) != CURLE_OK)
return false;
}
if (timeOutMs > 0)
{
long timeOutSecs = static_cast<long> (ceil (static_cast<double> (timeOutMs) / 1000.0));
if (curl_easy_setopt (curl, CURLOPT_CONNECTTIMEOUT, timeOutSecs) != CURLE_OK)
return false;
}
return true;
}
return false;
}
void connect (StringPairArray* responseHeaders, bool isPost, const MemoryBlock& postData,
URL::OpenStreamProgressCallback* progressCallback, void* progressCallbackContext)
{
if (isPost)
postBuffer = &postData;
size_t lastPos = static_cast<size_t> (-1);
// step until either: 1) there is an error 2) the transaction is complete
// or 3) data is in the in buffer
while ((! finished) && curlBuffer.getSize() == 0 && curl != nullptr)
{
singleStep();
// call callbacks if this is a post request
if (isPost && progressCallback != nullptr && lastPos != postPosition)
{
lastPos = postPosition;
if (! progressCallback (progressCallbackContext,
static_cast<int> (lastPos),
static_cast<int> (postData.getSize())))
{
// user has decided to abort the transaction
cleanup();
return;
}
}
}
long responseCode;
if (curl_easy_getinfo (curl, CURLINFO_RESPONSE_CODE, &responseCode) == CURLE_OK)
statusCode = static_cast<int> (responseCode);
// parse headers
if (responseHeaders != nullptr)
parseHttpHeaders (*responseHeaders);
// get content length size
double curlLength;
if (curl_easy_getinfo (curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &curlLength) == CURLE_OK)
contentLength = static_cast<int64> (curlLength);
}
void finish()
{
if (curl == nullptr)
return;
for (;;)
{
int cnt = 0;
if (CURLMsg* msg = curl_multi_info_read (multi, &cnt))
{
if (msg->msg == CURLMSG_DONE && msg->easy_handle == curl)
{
lastError = msg->data.result; // this is the error that stopped our process from continuing
break;
}
}
else
{
break;
}
}
finished = true;
}
//==============================================================================
void singleStep()
{
if (curl == nullptr || lastError != CURLE_OK)
return;
fd_set fdread, fdwrite, fdexcep;
int maxfd = -1;
long curl_timeo;
if ((lastError = (int) curl_multi_timeout (multi, &curl_timeo)) != CURLM_OK)
return;
// why 980? see http://curl.haxx.se/libcurl/c/curl_multi_timeout.html
if (curl_timeo < 0)
curl_timeo = 980;
struct timeval tv;
tv.tv_sec = curl_timeo / 1000;
tv.tv_usec = (curl_timeo % 1000) * 1000;
FD_ZERO (&fdread);
FD_ZERO (&fdwrite);
FD_ZERO (&fdexcep);
if ((lastError = (int) curl_multi_fdset (multi, &fdread, &fdwrite, &fdexcep, &maxfd)) != CURLM_OK)
return;
if (maxfd != -1)
{
if (select (maxfd + 1, &fdread, &fdwrite, &fdexcep, &tv) < 0)
{
lastError = -1;
return;
}
}
else
{
// if curl does not return any sockets for to wait on, then the doc says to wait 100 ms
Thread::sleep (100);
}
int still_running = 0;
int curlRet;
while ((curlRet = (int) curl_multi_perform (multi, &still_running)) == CURLM_CALL_MULTI_PERFORM)
{}
if ((lastError = curlRet) != CURLM_OK)
return;
if (still_running <= 0)
finish();
}
int readOrSkip (void* buffer, int bytesToRead, bool skip)
{
if (bytesToRead <= 0)
return 0;
size_t pos = 0;
size_t len = static_cast<size_t> (bytesToRead);
while (len > 0)
{
size_t bufferBytes = curlBuffer.getSize();
bool removeSection = true;
if (bufferBytes == 0)
{
// do not call curl again if we are finished
if (finished || curl == nullptr)
return static_cast<int> (pos);
skipBytes = skip ? len : 0;
singleStep();
// update the amount that was read/skipped from curl
bufferBytes = skip ? len - skipBytes : curlBuffer.getSize();
removeSection = ! skip;
}
// can we copy data from the internal buffer?
if (bufferBytes > 0)
{
size_t max = jmin (len, bufferBytes);
if (! skip)
memcpy (addBytesToPointer (buffer, pos), curlBuffer.getData(), max);
pos += max;
streamPos += static_cast<int64> (max);
len -= max;
if (removeSection)
curlBuffer.removeSection (0, max);
}
}
return static_cast<int> (pos);
}
//==============================================================================
void parseHttpHeaders (StringPairArray& responseHeaders)
{
StringArray headerLines = StringArray::fromLines (curlHeaders);
// ignore the first line as this is the status line
for (int i = 1; i < headerLines.size(); ++i)
{
const String& headersEntry = headerLines[i];
if (headersEntry.isNotEmpty())
{
const String key (headersEntry.upToFirstOccurrenceOf (": ", false, false));
const String value (headersEntry.fromFirstOccurrenceOf (": ", false, false));
const String previousValue (responseHeaders [key]);
responseHeaders.set (key, previousValue.isEmpty() ? value : (previousValue + "," + value));
}
}
}
//==============================================================================
// CURL callbacks
size_t curlWriteCallback (char* ptr, size_t size, size_t nmemb)
{
if (curl == nullptr || lastError != CURLE_OK)
return 0;
const size_t len = size * nmemb;
// skip bytes if necessary
size_t max = jmin (skipBytes, len);
skipBytes -= max;
if (len > max)
curlBuffer.append (ptr + max, len - max);
return len;
}
size_t curlReadCallback (char* ptr, size_t size, size_t nmemb)
{
if (curl == nullptr || postBuffer == nullptr || lastError != CURLE_OK)
return 0;
const size_t len = size * nmemb;
size_t max = jmin (postBuffer->getSize() - postPosition, len);
memcpy (ptr, (char*)postBuffer->getData() + postPosition, max);
postPosition += max;
return max;
}
size_t curlHeaderCallback (char* ptr, size_t size, size_t nmemb)
{
if (curl == nullptr || lastError != CURLE_OK)
return 0;
size_t len = size * nmemb;
curlHeaders += String (ptr, len);
return len;
}
//==============================================================================
// Static method wrappers
static size_t StaticCurlWrite (char* ptr, size_t size, size_t nmemb, void* userdata)
{
WebInputStream* wi = reinterpret_cast<WebInputStream*> (userdata);
return wi->curlWriteCallback (ptr, size, nmemb);
}
static size_t StaticCurlRead (char* ptr, size_t size, size_t nmemb, void* userdata)
{
WebInputStream* wi = reinterpret_cast<WebInputStream*> (userdata);
return wi->curlReadCallback (ptr, size, nmemb);
}
static size_t StaticCurlHeader (char* ptr, size_t size, size_t nmemb, void* userdata)
{
WebInputStream* wi = reinterpret_cast<WebInputStream*> (userdata);
return wi->curlHeaderCallback (ptr, size, nmemb);
}
private:
CURLM* multi;
CURL* curl;
struct curl_slist* headerList;
int lastError;
//==============================================================================
// internal buffers and buffer positions
int64 contentLength, streamPos;
MemoryBlock curlBuffer;
String curlHeaders;
bool finished;
size_t skipBytes;
//==============================================================================
// Http POST variables
const MemoryBlock* postBuffer;
size_t postPosition;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WebInputStream)
};

+ 70
- 12
modules/juce_core/native/juce_linux_Network.cpp View File

@@ -67,8 +67,8 @@ bool JUCE_CALLTYPE Process::openEmailWithAttachments (const String& /* targetEma
return false;
}
//==============================================================================
#if ! JUCE_USE_CURL
class WebInputStream : public InputStream
{
public:
@@ -77,8 +77,9 @@ public:
const String& headers_, int timeOutMs_, StringPairArray* responseHeaders,
const int maxRedirects)
: statusCode (0), socketHandle (-1), levelsOfRedirection (0),
address (address_), headers (headers_), postData (postData_), position (0),
finished (false), isPost (isPost_), timeOutMs (timeOutMs_), numRedirectsToFollow (maxRedirects)
address (address_), headers (headers_), postData (postData_), contentLength (-1), position (0),
finished (false), isPost (isPost_), timeOutMs (timeOutMs_), numRedirectsToFollow (maxRedirects),
chunkEnd (0), isChunked (false), readingChunk (false)
{
statusCode = createConnection (progressCallback, progressCallbackContext, numRedirectsToFollow);
@@ -104,18 +105,63 @@ public:
bool isError() const { return socketHandle < 0; }
bool isExhausted() override { return finished; }
int64 getPosition() override { return position; }
int64 getTotalLength() override
{
//xxx to do
return -1;
}
int64 getTotalLength() override { return contentLength; }
int read (void* buffer, int bytesToRead) override
{
if (finished || isError())
return 0;
if (isChunked && ! readingChunk)
{
if (position >= chunkEnd)
{
const ScopedValueSetter<bool> setter (readingChunk, true, false);
MemoryOutputStream chunkLengthBuffer;
char c = 0;
if (chunkEnd > 0)
{
if (read (&c, 1) != 1 || c != '\r'
|| read (&c, 1) != 1 || c != '\n')
{
finished = true;
return 0;
}
}
while (chunkLengthBuffer.getDataSize() < 512 && ! (finished || isError()))
{
if (read (&c, 1) != 1)
{
finished = true;
return 0;
}
if (c == '\r')
continue;
if (c == '\n')
break;
chunkLengthBuffer.writeByte (c);
}
const int64 chunkSize = chunkLengthBuffer.toString().trimStart().getHexValue64();
if (chunkSize == 0)
{
finished = true;
return 0;
}
chunkEnd += chunkSize;
}
if (bytesToRead > chunkEnd - position)
bytesToRead = chunkEnd - position;
}
fd_set readbits;
FD_ZERO (&readbits);
FD_SET (socketHandle, &readbits);
@@ -131,7 +177,9 @@ public:
if (bytesRead == 0)
finished = true;
position += bytesRead;
if (! readingChunk)
position += bytesRead;
return bytesRead;
}
@@ -165,11 +213,13 @@ private:
StringArray headerLines;
String address, headers;
MemoryBlock postData;
int64 position;
int64 contentLength, position;
bool finished;
const bool isPost;
const int timeOutMs;
const int numRedirectsToFollow;
int64 chunkEnd;
bool isChunked, readingChunk;
void closeSocket (bool resetLevelsOfRedirection = true)
{
@@ -298,6 +348,13 @@ private:
return createConnection (progressCallback, progressCallbackContext, numRedirects);
}
String contentLengthString (findHeaderItem (headerLines, "Content-Length:"));
if (contentLengthString.isNotEmpty())
contentLength = contentLengthString.getLargeIntValue();
isChunked = (findHeaderItem (headerLines, "Transfer-Encoding:") == "chunked");
return status;
}
@@ -345,7 +402,7 @@ private:
static void writeHost (MemoryOutputStream& dest, const bool isPost,
const String& path, const String& host, int port)
{
dest << (isPost ? "POST " : "GET ") << path << " HTTP/1.0\r\nHost: " << host;
dest << (isPost ? "POST " : "GET ") << path << " HTTP/1.1\r\nHost: " << host;
/* HTTP spec 14.23 says that the port number must be included in the header if it is not 80 */
if (port != 80)
@@ -455,3 +512,4 @@ private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WebInputStream)
};
#endif

+ 5
- 1
modules/juce_graphics/fonts/juce_Font.h View File

@@ -279,8 +279,12 @@ public:
//==============================================================================
/** Makes the font bold or non-bold. */
void setBold (bool shouldBeBold);
/** Returns a copy of this font with the bold attribute set. */
/** Returns a copy of this font with the bold attribute set.
If the font does not have a bold version, this will return the default font.
*/
Font boldened() const;
/** Returns true if the font is bold. */
bool isBold() const noexcept;


+ 2
- 2
modules/juce_gui_basics/components/juce_Component.h View File

@@ -443,7 +443,7 @@ public:
/** Changes the component's position and size.
The coordinates are relative to the top-left of the component's parent, or relative
to the origin of the screen is the component is on the desktop.
to the origin of the screen if the component is on the desktop.
If this method changes the component's top-left position, it will make a synchronous
call to moved(). If it changes the size, it will also make a call to resized().
@@ -459,7 +459,7 @@ public:
/** Changes the component's position and size.
The coordinates are relative to the top-left of the component's parent, or relative
to the origin of the screen is the component is on the desktop.
to the origin of the screen if the component is on the desktop.
If this method changes the component's top-left position, it will make a synchronous
call to moved(). If it changes the size, it will also make a call to resized().


+ 7
- 6
modules/juce_gui_basics/keyboard/juce_TextEditorKeyMapper.h View File

@@ -85,12 +85,6 @@ struct TextEditorKeyMapper
if (key.isKeyCode (KeyPress::pageDownKey)) return target.pageDown (isShiftDown);
}
if (numCtrlAltCommandKeys < 2)
{
if (key.isKeyCode (KeyPress::backspaceKey)) return target.deleteBackwards (ctrlOrAltDown);
if (key.isKeyCode (KeyPress::deleteKey)) return target.deleteForwards (ctrlOrAltDown);
}
if (key == KeyPress ('c', ModifierKeys::commandModifier, 0)
|| key == KeyPress (KeyPress::insertKey, ModifierKeys::ctrlModifier, 0))
return target.copyToClipboard();
@@ -103,6 +97,13 @@ struct TextEditorKeyMapper
|| key == KeyPress (KeyPress::insertKey, ModifierKeys::shiftModifier, 0))
return target.pasteFromClipboard();
// NB: checking for delete must happen after the earlier check for shift + delete
if (numCtrlAltCommandKeys < 2)
{
if (key.isKeyCode (KeyPress::backspaceKey)) return target.deleteBackwards (ctrlOrAltDown);
if (key.isKeyCode (KeyPress::deleteKey)) return target.deleteForwards (ctrlOrAltDown);
}
if (key == KeyPress ('a', ModifierKeys::commandModifier, 0))
return target.selectAll();


+ 6
- 0
modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V2.cpp View File

@@ -490,6 +490,12 @@ int LookAndFeel_V2::getAlertWindowButtonHeight()
return 28;
}
Font LookAndFeel_V2::getAlertWindowTitleFont()
{
Font messageFont = getAlertWindowMessageFont();
return messageFont.withHeight (messageFont.getHeight() * 1.1f).boldened();
}
Font LookAndFeel_V2::getAlertWindowMessageFont()
{
return Font (15.0f);


+ 15
- 0
modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V2.h View File

@@ -67,7 +67,22 @@ public:
void drawAlertBox (Graphics&, AlertWindow&, const Rectangle<int>& textArea, TextLayout&) override;
int getAlertBoxWindowFlags() override;
int getAlertWindowButtonHeight() override;
/** Override this function to supply a custom font for the alert window title.
This default implementation will use a boldened and slightly larger version
of the alert window message font.
@see getAlertWindowMessageFont.
*/
Font getAlertWindowTitleFont() override;
/** Override this function to supply a custom font for the alert window message.
This default implementation will use the default font with height set to 15.0f.
@see getAlertWindowTitleFont
*/
Font getAlertWindowMessageFont() override;
Font getAlertWindowFont() override;
//==============================================================================


+ 3
- 0
modules/juce_gui_basics/widgets/juce_TableListBox.h View File

@@ -56,6 +56,9 @@ public:
The graphics context has its origin at the row's top-left, and your method
should fill the area specified by the width and height parameters.
Note that the rowNumber value may be greater than the number of rows in your
list, so be careful that you don't assume it's less than getNumRows().
*/
virtual void paintRowBackground (Graphics&,
int rowNumber,


+ 11
- 9
modules/juce_gui_basics/windows/juce_AlertWindow.cpp View File

@@ -343,22 +343,24 @@ void AlertWindow::updateLayout (const bool onlyIncreaseSize)
const int titleH = 24;
const int iconWidth = 80;
const Font font (getLookAndFeel().getAlertWindowMessageFont());
LookAndFeel& lookAndFeel = getLookAndFeel();
const int wid = jmax (font.getStringWidth (text),
font.getStringWidth (getName()));
const Font messageFont (lookAndFeel.getAlertWindowMessageFont());
const int sw = (int) std::sqrt (font.getHeight() * wid);
const int wid = jmax (messageFont.getStringWidth (text),
messageFont.getStringWidth (getName()));
const int sw = (int) std::sqrt (messageFont.getHeight() * wid);
int w = jmin (300 + sw * 2, (int) (getParentWidth() * 0.7f));
const int edgeGap = 10;
const int labelHeight = 18;
int iconSpace = 0;
AttributedString attributedText;
attributedText.append (getName(), font.withHeight (font.getHeight() * 1.1f).boldened());
attributedText.append (getName(), lookAndFeel.getAlertWindowTitleFont());
if (text.isNotEmpty())
attributedText.append ("\n\n" + text, font);
attributedText.append ("\n\n" + text, messageFont);
attributedText.setColour (findColour (textColourId));
@@ -383,18 +385,18 @@ void AlertWindow::updateLayout (const bool onlyIncreaseSize)
int buttonW = 40;
for (int i = 0; i < buttons.size(); ++i)
buttonW += 16 + buttons.getUnchecked(i)->getWidth();
buttonW += 16 + buttons.getUnchecked (i)->getWidth();
w = jmax (buttonW, w);
h += (textBoxes.size() + comboBoxes.size() + progressBars.size()) * 50;
if (buttons.size() > 0)
h += 20 + buttons.getUnchecked(0)->getHeight();
h += 20 + buttons.getUnchecked (0)->getHeight();
for (int i = customComps.size(); --i >= 0;)
{
Component* c = customComps.getUnchecked(i);
Component* c = customComps.getUnchecked (i);
w = jmax (w, (c->getWidth() * 100) / 80);
h += 10 + c->getHeight();


+ 1
- 0
modules/juce_gui_basics/windows/juce_AlertWindow.h View File

@@ -437,6 +437,7 @@ public:
virtual int getAlertWindowButtonHeight() = 0;
virtual Font getAlertWindowTitleFont() = 0;
virtual Font getAlertWindowMessageFont() = 0;
virtual Font getAlertWindowFont() = 0;
};


Loading…
Cancel
Save