|
|
|
@@ -42655,14 +42655,15 @@ void Label::setText (const String& newText, |
|
|
|
if (text != newText) |
|
|
|
{ |
|
|
|
text = newText; |
|
|
|
|
|
|
|
if (broadcastChangeMessage) |
|
|
|
triggerAsyncUpdate(); |
|
|
|
|
|
|
|
repaint(); |
|
|
|
|
|
|
|
if (ownerComponent != 0 && ! deletionWatcher->hasBeenDeleted()) |
|
|
|
{ |
|
|
|
componentMovedOrResized (*ownerComponent, true, true); |
|
|
|
|
|
|
|
if (broadcastChangeMessage) |
|
|
|
callChangeListeners(); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@@ -42793,8 +42794,6 @@ bool Label::updateFromTextEditorContents() |
|
|
|
if (text != newText) |
|
|
|
{ |
|
|
|
text = newText; |
|
|
|
|
|
|
|
triggerAsyncUpdate(); |
|
|
|
repaint(); |
|
|
|
|
|
|
|
if (ownerComponent != 0 && ! deletionWatcher->hasBeenDeleted()) |
|
|
|
@@ -42820,6 +42819,9 @@ void Label::hideEditor (const bool discardCurrentEditorContents) |
|
|
|
textWasEdited(); |
|
|
|
|
|
|
|
exitModalState (0); |
|
|
|
|
|
|
|
if (changed && isValidComponent()) |
|
|
|
callChangeListeners(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@@ -42904,6 +42906,15 @@ void Label::colourChanged() |
|
|
|
repaint(); |
|
|
|
} |
|
|
|
|
|
|
|
void Label::setMinimumHorizontalScale (const float newScale) |
|
|
|
{ |
|
|
|
if (minimumHorizontalScale != newScale) |
|
|
|
{ |
|
|
|
minimumHorizontalScale = newScale; |
|
|
|
repaint(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// We'll use a custom focus traverser here to make sure focus goes from the |
|
|
|
// text editor to another component rather than back to the label itself. |
|
|
|
class LabelKeyboardFocusTraverser : public KeyboardFocusTraverser |
|
|
|
@@ -42941,7 +42952,7 @@ void Label::removeListener (LabelListener* const listener) throw() |
|
|
|
listeners.removeValue (listener); |
|
|
|
} |
|
|
|
|
|
|
|
void Label::handleAsyncUpdate() |
|
|
|
void Label::callChangeListeners() |
|
|
|
{ |
|
|
|
for (int i = listeners.size(); --i >= 0;) |
|
|
|
{ |
|
|
|
@@ -42977,7 +42988,12 @@ void Label::textEditorReturnKeyPressed (TextEditor& ed) |
|
|
|
hideEditor (true); |
|
|
|
|
|
|
|
if (changed) |
|
|
|
{ |
|
|
|
textWasEdited(); |
|
|
|
|
|
|
|
if (isValidComponent()) |
|
|
|
callChangeListeners(); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@@ -48808,7 +48824,7 @@ bool TextEditor::keyPressed (const KeyPress& key) |
|
|
|
bool TextEditor::keyStateChanged() |
|
|
|
{ |
|
|
|
// (overridden to avoid forwarding key events to the parent) |
|
|
|
return true; |
|
|
|
return ! ModifierKeys::getCurrentModifiers().isCommandDown(); |
|
|
|
} |
|
|
|
|
|
|
|
const int baseMenuItemID = 0x7fff0000; |
|
|
|
@@ -59362,7 +59378,7 @@ void LookAndFeel::drawProgressBar (Graphics& g, ProgressBar& progressBar, |
|
|
|
|
|
|
|
Path p; |
|
|
|
|
|
|
|
for (float x = (float) (-stripeWidth - position); x < width + stripeWidth; x += stripeWidth) |
|
|
|
for (float x = (float) (- position); x < width + stripeWidth; x += stripeWidth) |
|
|
|
p.addQuadrilateral (x, 0.0f, |
|
|
|
x + stripeWidth * 0.5f, 0.0f, |
|
|
|
x, (float) height, |
|
|
|
@@ -240129,6 +240145,26 @@ int juce_seekInInternetFile (void* handle, int newPosition) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
int juce_getInternetFileContentLength (void* handle) |
|
|
|
{ |
|
|
|
DWORD result = 0; |
|
|
|
const ConnectionAndRequestStruct* const crs = (const ConnectionAndRequestStruct*) handle; |
|
|
|
|
|
|
|
if (crs != 0) |
|
|
|
{ |
|
|
|
DWORD index = 0; |
|
|
|
DWORD size = sizeof (result); |
|
|
|
|
|
|
|
HttpQueryInfo (crs->request, |
|
|
|
HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, |
|
|
|
&result, |
|
|
|
&size, |
|
|
|
&index); |
|
|
|
} |
|
|
|
|
|
|
|
return (int) result; |
|
|
|
} |
|
|
|
|
|
|
|
void juce_closeInternetFile (void* handle) |
|
|
|
{ |
|
|
|
if (handle != 0) |
|
|
|
@@ -249910,7 +249946,8 @@ public: |
|
|
|
|
|
|
|
JUCE_TRY |
|
|
|
{ |
|
|
|
close(); |
|
|
|
// are there are devices that need to be closed before showing their control panel? |
|
|
|
// close(); |
|
|
|
insideControlPanelModalLoop = true; |
|
|
|
|
|
|
|
const uint32 started = Time::getMillisecondCounter(); |
|
|
|
@@ -254066,330 +254103,330 @@ bool PlatformUtilities::launchEmailWithAttachments (const String& targetEmailAdd |
|
|
|
/** A HTTP input stream that uses sockets. |
|
|
|
*/ |
|
|
|
class JUCE_HTTPSocketStream |
|
|
|
{ |
|
|
|
public: |
|
|
|
{ |
|
|
|
public: |
|
|
|
|
|
|
|
JUCE_HTTPSocketStream() |
|
|
|
JUCE_HTTPSocketStream() |
|
|
|
: readPosition (0), |
|
|
|
socketHandle (-1), |
|
|
|
levelsOfRedirection (0), |
|
|
|
timeoutSeconds (15) |
|
|
|
{ |
|
|
|
} |
|
|
|
socketHandle (-1), |
|
|
|
levelsOfRedirection (0), |
|
|
|
timeoutSeconds (15) |
|
|
|
{ |
|
|
|
} |
|
|
|
|
|
|
|
~JUCE_HTTPSocketStream() |
|
|
|
{ |
|
|
|
closeSocket(); |
|
|
|
} |
|
|
|
~JUCE_HTTPSocketStream() |
|
|
|
{ |
|
|
|
closeSocket(); |
|
|
|
} |
|
|
|
|
|
|
|
bool open (const String& url, |
|
|
|
const String& headers, |
|
|
|
const MemoryBlock& postData, |
|
|
|
const bool isPost, |
|
|
|
URL::OpenStreamProgressCallback* callback, |
|
|
|
void* callbackContext, |
|
|
|
int timeOutMs) |
|
|
|
{ |
|
|
|
closeSocket(); |
|
|
|
bool open (const String& url, |
|
|
|
const String& headers, |
|
|
|
const MemoryBlock& postData, |
|
|
|
const bool isPost, |
|
|
|
URL::OpenStreamProgressCallback* callback, |
|
|
|
void* callbackContext, |
|
|
|
int timeOutMs) |
|
|
|
{ |
|
|
|
closeSocket(); |
|
|
|
|
|
|
|
uint32 timeOutTime = Time::getMillisecondCounter(); |
|
|
|
uint32 timeOutTime = Time::getMillisecondCounter(); |
|
|
|
|
|
|
|
if (timeOutMs == 0) |
|
|
|
timeOutTime += 60000; |
|
|
|
else if (timeOutMs < 0) |
|
|
|
timeOutTime = 0xffffffff; |
|
|
|
else |
|
|
|
timeOutTime += timeOutMs; |
|
|
|
if (timeOutMs == 0) |
|
|
|
timeOutTime += 60000; |
|
|
|
else if (timeOutMs < 0) |
|
|
|
timeOutTime = 0xffffffff; |
|
|
|
else |
|
|
|
timeOutTime += timeOutMs; |
|
|
|
|
|
|
|
String hostName, hostPath; |
|
|
|
int hostPort; |
|
|
|
String hostName, hostPath; |
|
|
|
int hostPort; |
|
|
|
|
|
|
|
if (! decomposeURL (url, hostName, hostPath, hostPort)) |
|
|
|
return false; |
|
|
|
if (! decomposeURL (url, hostName, hostPath, hostPort)) |
|
|
|
return false; |
|
|
|
|
|
|
|
const struct hostent* host = 0; |
|
|
|
int port = 0; |
|
|
|
const struct hostent* host = 0; |
|
|
|
int port = 0; |
|
|
|
|
|
|
|
String proxyName, proxyPath; |
|
|
|
int proxyPort = 0; |
|
|
|
String proxyName, proxyPath; |
|
|
|
int proxyPort = 0; |
|
|
|
|
|
|
|
String proxyURL (getenv ("http_proxy")); |
|
|
|
if (proxyURL.startsWithIgnoreCase (T("http://"))) |
|
|
|
{ |
|
|
|
if (! decomposeURL (proxyURL, proxyName, proxyPath, proxyPort)) |
|
|
|
return false; |
|
|
|
String proxyURL (getenv ("http_proxy")); |
|
|
|
if (proxyURL.startsWithIgnoreCase (T("http://"))) |
|
|
|
{ |
|
|
|
if (! decomposeURL (proxyURL, proxyName, proxyPath, proxyPort)) |
|
|
|
return false; |
|
|
|
|
|
|
|
host = gethostbyname ((const char*) proxyName.toUTF8()); |
|
|
|
port = proxyPort; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
host = gethostbyname ((const char*) hostName.toUTF8()); |
|
|
|
port = hostPort; |
|
|
|
} |
|
|
|
host = gethostbyname ((const char*) proxyName.toUTF8()); |
|
|
|
port = proxyPort; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
host = gethostbyname ((const char*) hostName.toUTF8()); |
|
|
|
port = hostPort; |
|
|
|
} |
|
|
|
|
|
|
|
if (host == 0) |
|
|
|
return false; |
|
|
|
if (host == 0) |
|
|
|
return false; |
|
|
|
|
|
|
|
struct sockaddr_in address; |
|
|
|
zerostruct (address); |
|
|
|
memcpy ((void*) &address.sin_addr, (const void*) host->h_addr, host->h_length); |
|
|
|
address.sin_family = host->h_addrtype; |
|
|
|
address.sin_port = htons (port); |
|
|
|
struct sockaddr_in address; |
|
|
|
zerostruct (address); |
|
|
|
memcpy ((void*) &address.sin_addr, (const void*) host->h_addr, host->h_length); |
|
|
|
address.sin_family = host->h_addrtype; |
|
|
|
address.sin_port = htons (port); |
|
|
|
|
|
|
|
socketHandle = socket (host->h_addrtype, SOCK_STREAM, 0); |
|
|
|
socketHandle = socket (host->h_addrtype, SOCK_STREAM, 0); |
|
|
|
|
|
|
|
if (socketHandle == -1) |
|
|
|
return false; |
|
|
|
if (socketHandle == -1) |
|
|
|
return false; |
|
|
|
|
|
|
|
int receiveBufferSize = 16384; |
|
|
|
setsockopt (socketHandle, SOL_SOCKET, SO_RCVBUF, (char*) &receiveBufferSize, sizeof (receiveBufferSize)); |
|
|
|
setsockopt (socketHandle, SOL_SOCKET, SO_KEEPALIVE, 0, 0); |
|
|
|
int receiveBufferSize = 16384; |
|
|
|
setsockopt (socketHandle, SOL_SOCKET, SO_RCVBUF, (char*) &receiveBufferSize, sizeof (receiveBufferSize)); |
|
|
|
setsockopt (socketHandle, SOL_SOCKET, SO_KEEPALIVE, 0, 0); |
|
|
|
|
|
|
|
#if JUCE_MAC |
|
|
|
setsockopt (socketHandle, SOL_SOCKET, SO_NOSIGPIPE, 0, 0); |
|
|
|
setsockopt (socketHandle, SOL_SOCKET, SO_NOSIGPIPE, 0, 0); |
|
|
|
#endif |
|
|
|
|
|
|
|
if (connect (socketHandle, (struct sockaddr*) &address, sizeof (address)) == -1) |
|
|
|
if (connect (socketHandle, (struct sockaddr*) &address, sizeof (address)) == -1) |
|
|
|
{ |
|
|
|
closeSocket(); |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
const MemoryBlock requestHeader (createRequestHeader (hostName, hostPort, |
|
|
|
proxyName, proxyPort, |
|
|
|
hostPath, url, |
|
|
|
headers, postData, |
|
|
|
isPost)); |
|
|
|
int totalHeaderSent = 0; |
|
|
|
|
|
|
|
while (totalHeaderSent < requestHeader.getSize()) |
|
|
|
{ |
|
|
|
if (Time::getMillisecondCounter() > timeOutTime) |
|
|
|
{ |
|
|
|
closeSocket(); |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
const MemoryBlock requestHeader (createRequestHeader (hostName, hostPort, |
|
|
|
proxyName, proxyPort, |
|
|
|
hostPath, url, |
|
|
|
headers, postData, |
|
|
|
isPost)); |
|
|
|
int totalHeaderSent = 0; |
|
|
|
const int numToSend = jmin (1024, requestHeader.getSize() - totalHeaderSent); |
|
|
|
|
|
|
|
while (totalHeaderSent < requestHeader.getSize()) |
|
|
|
if (send (socketHandle, |
|
|
|
((const char*) requestHeader.getData()) + totalHeaderSent, |
|
|
|
numToSend, 0) |
|
|
|
!= numToSend) |
|
|
|
{ |
|
|
|
if (Time::getMillisecondCounter() > timeOutTime) |
|
|
|
{ |
|
|
|
closeSocket(); |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
const int numToSend = jmin (1024, requestHeader.getSize() - totalHeaderSent); |
|
|
|
|
|
|
|
if (send (socketHandle, |
|
|
|
((const char*) requestHeader.getData()) + totalHeaderSent, |
|
|
|
numToSend, 0) |
|
|
|
!= numToSend) |
|
|
|
{ |
|
|
|
closeSocket(); |
|
|
|
return false; |
|
|
|
} |
|
|
|
closeSocket(); |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
totalHeaderSent += numToSend; |
|
|
|
totalHeaderSent += numToSend; |
|
|
|
|
|
|
|
if (callback != 0 && ! callback (callbackContext, totalHeaderSent, requestHeader.getSize())) |
|
|
|
{ |
|
|
|
closeSocket(); |
|
|
|
return false; |
|
|
|
} |
|
|
|
if (callback != 0 && ! callback (callbackContext, totalHeaderSent, requestHeader.getSize())) |
|
|
|
{ |
|
|
|
closeSocket(); |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
const String responseHeader (readResponse (timeOutTime)); |
|
|
|
const String responseHeader (readResponse (timeOutTime)); |
|
|
|
|
|
|
|
if (responseHeader.isNotEmpty()) |
|
|
|
{ |
|
|
|
//DBG (responseHeader); |
|
|
|
if (responseHeader.isNotEmpty()) |
|
|
|
{ |
|
|
|
//DBG (responseHeader); |
|
|
|
|
|
|
|
StringArray lines; |
|
|
|
lines.addLines (responseHeader); |
|
|
|
StringArray lines; |
|
|
|
lines.addLines (responseHeader); |
|
|
|
|
|
|
|
// NB - using charToString() here instead of just T(" "), because that was |
|
|
|
// causing a mysterious gcc internal compiler error... |
|
|
|
const int statusCode = responseHeader.fromFirstOccurrenceOf (String::charToString (T(' ')), false, false) |
|
|
|
.substring (0, 3) |
|
|
|
.getIntValue(); |
|
|
|
// NB - using charToString() here instead of just T(" "), because that was |
|
|
|
// causing a mysterious gcc internal compiler error... |
|
|
|
const int statusCode = responseHeader.fromFirstOccurrenceOf (String::charToString (T(' ')), false, false) |
|
|
|
.substring (0, 3) |
|
|
|
.getIntValue(); |
|
|
|
|
|
|
|
//int contentLength = findHeaderItem (lines, T("Content-Length:")).getIntValue(); |
|
|
|
//bool isChunked = findHeaderItem (lines, T("Transfer-Encoding:")).equalsIgnoreCase ("chunked"); |
|
|
|
//int contentLength = findHeaderItem (lines, T("Content-Length:")).getIntValue(); |
|
|
|
//bool isChunked = findHeaderItem (lines, T("Transfer-Encoding:")).equalsIgnoreCase ("chunked"); |
|
|
|
|
|
|
|
String location (findHeaderItem (lines, T("Location:"))); |
|
|
|
String location (findHeaderItem (lines, T("Location:"))); |
|
|
|
|
|
|
|
if (statusCode >= 300 && statusCode < 400 |
|
|
|
&& location.isNotEmpty()) |
|
|
|
{ |
|
|
|
if (! location.startsWithIgnoreCase (T("http://"))) |
|
|
|
location = T("http://") + location; |
|
|
|
if (statusCode >= 300 && statusCode < 400 |
|
|
|
&& location.isNotEmpty()) |
|
|
|
{ |
|
|
|
if (! location.startsWithIgnoreCase (T("http://"))) |
|
|
|
location = T("http://") + location; |
|
|
|
|
|
|
|
if (levelsOfRedirection++ < 3) |
|
|
|
return open (location, headers, postData, isPost, callback, callbackContext, timeOutMs); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
levelsOfRedirection = 0; |
|
|
|
return true; |
|
|
|
} |
|
|
|
if (levelsOfRedirection++ < 3) |
|
|
|
return open (location, headers, postData, isPost, callback, callbackContext, timeOutMs); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
levelsOfRedirection = 0; |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
closeSocket(); |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
int read (void* buffer, int bytesToRead) |
|
|
|
{ |
|
|
|
fd_set readbits; |
|
|
|
FD_ZERO (&readbits); |
|
|
|
FD_SET (socketHandle, &readbits); |
|
|
|
|
|
|
|
struct timeval tv; |
|
|
|
tv.tv_sec = timeoutSeconds; |
|
|
|
tv.tv_usec = 0; |
|
|
|
|
|
|
|
if (select (socketHandle + 1, &readbits, 0, 0, &tv) <= 0) |
|
|
|
return 0; // (timeout) |
|
|
|
closeSocket(); |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
const int bytesRead = jmax (0, recv (socketHandle, buffer, bytesToRead, MSG_WAITALL)); |
|
|
|
readPosition += bytesRead; |
|
|
|
return bytesRead; |
|
|
|
} |
|
|
|
int read (void* buffer, int bytesToRead) |
|
|
|
{ |
|
|
|
fd_set readbits; |
|
|
|
FD_ZERO (&readbits); |
|
|
|
FD_SET (socketHandle, &readbits); |
|
|
|
|
|
|
|
int readPosition; |
|
|
|
struct timeval tv; |
|
|
|
tv.tv_sec = timeoutSeconds; |
|
|
|
tv.tv_usec = 0; |
|
|
|
|
|
|
|
juce_UseDebuggingNewOperator |
|
|
|
if (select (socketHandle + 1, &readbits, 0, 0, &tv) <= 0) |
|
|
|
return 0; // (timeout) |
|
|
|
|
|
|
|
private: |
|
|
|
int socketHandle, levelsOfRedirection; |
|
|
|
const int timeoutSeconds; |
|
|
|
const int bytesRead = jmax (0, recv (socketHandle, buffer, bytesToRead, MSG_WAITALL)); |
|
|
|
readPosition += bytesRead; |
|
|
|
return bytesRead; |
|
|
|
} |
|
|
|
|
|
|
|
void closeSocket() |
|
|
|
{ |
|
|
|
if (socketHandle >= 0) |
|
|
|
close (socketHandle); |
|
|
|
int readPosition; |
|
|
|
|
|
|
|
socketHandle = -1; |
|
|
|
} |
|
|
|
juce_UseDebuggingNewOperator |
|
|
|
|
|
|
|
const MemoryBlock createRequestHeader (const String& hostName, |
|
|
|
const int hostPort, |
|
|
|
const String& proxyName, |
|
|
|
const int proxyPort, |
|
|
|
const String& hostPath, |
|
|
|
const String& originalURL, |
|
|
|
const String& headers, |
|
|
|
const MemoryBlock& postData, |
|
|
|
const bool isPost) |
|
|
|
{ |
|
|
|
String header (isPost ? "POST " : "GET "); |
|
|
|
private: |
|
|
|
int socketHandle, levelsOfRedirection; |
|
|
|
const int timeoutSeconds; |
|
|
|
|
|
|
|
if (proxyName.isEmpty()) |
|
|
|
{ |
|
|
|
header << hostPath << " HTTP/1.0\r\nHost: " |
|
|
|
<< hostName << ':' << hostPort; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
header << originalURL << " HTTP/1.0\r\nHost: " |
|
|
|
<< proxyName << ':' << proxyPort; |
|
|
|
} |
|
|
|
void closeSocket() |
|
|
|
{ |
|
|
|
if (socketHandle >= 0) |
|
|
|
close (socketHandle); |
|
|
|
|
|
|
|
header << "\r\nUser-Agent: JUCE/" |
|
|
|
<< JUCE_MAJOR_VERSION << '.' << JUCE_MINOR_VERSION |
|
|
|
<< "\r\nConnection: Close\r\nContent-Length: " |
|
|
|
<< postData.getSize() << "\r\n" |
|
|
|
<< headers << "\r\n"; |
|
|
|
socketHandle = -1; |
|
|
|
} |
|
|
|
|
|
|
|
MemoryBlock mb; |
|
|
|
mb.append (header.toUTF8(), (int) strlen (header.toUTF8())); |
|
|
|
mb.append (postData.getData(), postData.getSize()); |
|
|
|
const MemoryBlock createRequestHeader (const String& hostName, |
|
|
|
const int hostPort, |
|
|
|
const String& proxyName, |
|
|
|
const int proxyPort, |
|
|
|
const String& hostPath, |
|
|
|
const String& originalURL, |
|
|
|
const String& headers, |
|
|
|
const MemoryBlock& postData, |
|
|
|
const bool isPost) |
|
|
|
{ |
|
|
|
String header (isPost ? "POST " : "GET "); |
|
|
|
|
|
|
|
return mb; |
|
|
|
if (proxyName.isEmpty()) |
|
|
|
{ |
|
|
|
header << hostPath << " HTTP/1.0\r\nHost: " |
|
|
|
<< hostName << ':' << hostPort; |
|
|
|
} |
|
|
|
|
|
|
|
const String readResponse (const uint32 timeOutTime) |
|
|
|
else |
|
|
|
{ |
|
|
|
int bytesRead = 0, numConsecutiveLFs = 0; |
|
|
|
MemoryBlock buffer (1024, true); |
|
|
|
header << originalURL << " HTTP/1.0\r\nHost: " |
|
|
|
<< proxyName << ':' << proxyPort; |
|
|
|
} |
|
|
|
|
|
|
|
while (numConsecutiveLFs < 2 && bytesRead < 32768 |
|
|
|
&& Time::getMillisecondCounter() <= timeOutTime) |
|
|
|
{ |
|
|
|
fd_set readbits; |
|
|
|
FD_ZERO (&readbits); |
|
|
|
FD_SET (socketHandle, &readbits); |
|
|
|
header << "\r\nUser-Agent: JUCE/" |
|
|
|
<< JUCE_MAJOR_VERSION << '.' << JUCE_MINOR_VERSION |
|
|
|
<< "\r\nConnection: Close\r\nContent-Length: " |
|
|
|
<< postData.getSize() << "\r\n" |
|
|
|
<< headers << "\r\n"; |
|
|
|
|
|
|
|
struct timeval tv; |
|
|
|
tv.tv_sec = timeoutSeconds; |
|
|
|
tv.tv_usec = 0; |
|
|
|
MemoryBlock mb; |
|
|
|
mb.append (header.toUTF8(), (int) strlen (header.toUTF8())); |
|
|
|
mb.append (postData.getData(), postData.getSize()); |
|
|
|
|
|
|
|
if (select (socketHandle + 1, &readbits, 0, 0, &tv) <= 0) |
|
|
|
return String::empty; // (timeout) |
|
|
|
return mb; |
|
|
|
} |
|
|
|
|
|
|
|
buffer.ensureSize (bytesRead + 8, true); |
|
|
|
char* const dest = (char*) buffer.getData() + bytesRead; |
|
|
|
const String readResponse (const uint32 timeOutTime) |
|
|
|
{ |
|
|
|
int bytesRead = 0, numConsecutiveLFs = 0; |
|
|
|
MemoryBlock buffer (1024, true); |
|
|
|
|
|
|
|
if (recv (socketHandle, dest, 1, 0) == -1) |
|
|
|
return String::empty; |
|
|
|
while (numConsecutiveLFs < 2 && bytesRead < 32768 |
|
|
|
&& Time::getMillisecondCounter() <= timeOutTime) |
|
|
|
{ |
|
|
|
fd_set readbits; |
|
|
|
FD_ZERO (&readbits); |
|
|
|
FD_SET (socketHandle, &readbits); |
|
|
|
|
|
|
|
const char lastByte = *dest; |
|
|
|
++bytesRead; |
|
|
|
struct timeval tv; |
|
|
|
tv.tv_sec = timeoutSeconds; |
|
|
|
tv.tv_usec = 0; |
|
|
|
|
|
|
|
if (lastByte == '\n') |
|
|
|
++numConsecutiveLFs; |
|
|
|
else if (lastByte != '\r') |
|
|
|
numConsecutiveLFs = 0; |
|
|
|
} |
|
|
|
if (select (socketHandle + 1, &readbits, 0, 0, &tv) <= 0) |
|
|
|
return String::empty; // (timeout) |
|
|
|
|
|
|
|
const String header (String::fromUTF8 ((const uint8*) buffer.getData())); |
|
|
|
buffer.ensureSize (bytesRead + 8, true); |
|
|
|
char* const dest = (char*) buffer.getData() + bytesRead; |
|
|
|
|
|
|
|
if (header.startsWithIgnoreCase (T("HTTP/"))) |
|
|
|
return header.trimEnd(); |
|
|
|
if (recv (socketHandle, dest, 1, 0) == -1) |
|
|
|
return String::empty; |
|
|
|
|
|
|
|
return String::empty; |
|
|
|
const char lastByte = *dest; |
|
|
|
++bytesRead; |
|
|
|
|
|
|
|
if (lastByte == '\n') |
|
|
|
++numConsecutiveLFs; |
|
|
|
else if (lastByte != '\r') |
|
|
|
numConsecutiveLFs = 0; |
|
|
|
} |
|
|
|
|
|
|
|
static bool decomposeURL (const String& url, |
|
|
|
String& host, String& path, int& port) |
|
|
|
{ |
|
|
|
if (! url.startsWithIgnoreCase (T("http://"))) |
|
|
|
return false; |
|
|
|
const String header (String::fromUTF8 ((const uint8*) buffer.getData())); |
|
|
|
|
|
|
|
const int nextSlash = url.indexOfChar (7, '/'); |
|
|
|
int nextColon = url.indexOfChar (7, ':'); |
|
|
|
if (nextColon > nextSlash && nextSlash > 0) |
|
|
|
nextColon = -1; |
|
|
|
if (header.startsWithIgnoreCase (T("HTTP/"))) |
|
|
|
return header.trimEnd(); |
|
|
|
|
|
|
|
if (nextColon >= 0) |
|
|
|
{ |
|
|
|
host = url.substring (7, nextColon); |
|
|
|
return String::empty; |
|
|
|
} |
|
|
|
|
|
|
|
if (nextSlash >= 0) |
|
|
|
port = url.substring (nextColon + 1, nextSlash).getIntValue(); |
|
|
|
else |
|
|
|
port = url.substring (nextColon + 1).getIntValue(); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
port = 80; |
|
|
|
static bool decomposeURL (const String& url, |
|
|
|
String& host, String& path, int& port) |
|
|
|
{ |
|
|
|
if (! url.startsWithIgnoreCase (T("http://"))) |
|
|
|
return false; |
|
|
|
|
|
|
|
if (nextSlash >= 0) |
|
|
|
host = url.substring (7, nextSlash); |
|
|
|
else |
|
|
|
host = url.substring (7); |
|
|
|
} |
|
|
|
const int nextSlash = url.indexOfChar (7, '/'); |
|
|
|
int nextColon = url.indexOfChar (7, ':'); |
|
|
|
if (nextColon > nextSlash && nextSlash > 0) |
|
|
|
nextColon = -1; |
|
|
|
|
|
|
|
if (nextColon >= 0) |
|
|
|
{ |
|
|
|
host = url.substring (7, nextColon); |
|
|
|
|
|
|
|
if (nextSlash >= 0) |
|
|
|
path = url.substring (nextSlash); |
|
|
|
port = url.substring (nextColon + 1, nextSlash).getIntValue(); |
|
|
|
else |
|
|
|
path = T("/"); |
|
|
|
|
|
|
|
return true; |
|
|
|
port = url.substring (nextColon + 1).getIntValue(); |
|
|
|
} |
|
|
|
|
|
|
|
static const String findHeaderItem (const StringArray& lines, const String& itemName) |
|
|
|
else |
|
|
|
{ |
|
|
|
for (int i = 0; i < lines.size(); ++i) |
|
|
|
if (lines[i].startsWithIgnoreCase (itemName)) |
|
|
|
return lines[i].substring (itemName.length()).trim(); |
|
|
|
port = 80; |
|
|
|
|
|
|
|
return String::empty; |
|
|
|
if (nextSlash >= 0) |
|
|
|
host = url.substring (7, nextSlash); |
|
|
|
else |
|
|
|
host = url.substring (7); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
if (nextSlash >= 0) |
|
|
|
path = url.substring (nextSlash); |
|
|
|
else |
|
|
|
path = T("/"); |
|
|
|
|
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
static const String findHeaderItem (const StringArray& lines, const String& itemName) |
|
|
|
{ |
|
|
|
for (int i = 0; i < lines.size(); ++i) |
|
|
|
if (lines[i].startsWithIgnoreCase (itemName)) |
|
|
|
return lines[i].substring (itemName.length()).trim(); |
|
|
|
|
|
|
|
return String::empty; |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
bool juce_isOnLine() |
|
|
|
{ |
|
|
|
@@ -254432,6 +254469,19 @@ int juce_readFromInternetFile (void* handle, void* buffer, int bytesToRead) |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
int juce_getInternetFileContentLength (void* handle) |
|
|
|
{ |
|
|
|
JUCE_HTTPSocketStream* const s = (JUCE_HTTPSocketStream*) handle; |
|
|
|
|
|
|
|
if (s != 0) |
|
|
|
{ |
|
|
|
//xxx todo |
|
|
|
jassertfalse |
|
|
|
} |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
int juce_seekInInternetFile (void* handle, int newPosition) |
|
|
|
{ |
|
|
|
JUCE_HTTPSocketStream* const s = (JUCE_HTTPSocketStream*) handle; |
|
|
|
@@ -262777,6 +262827,19 @@ int juce_readFromInternetFile (void* handle, void* buffer, int bytesToRead) |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
int juce_getInternetFileContentLength (void* handle) |
|
|
|
{ |
|
|
|
JuceURLConnection* const s = (JuceURLConnection*) handle; |
|
|
|
|
|
|
|
if (s != 0) |
|
|
|
{ |
|
|
|
//xxx todo |
|
|
|
jassertfalse |
|
|
|
} |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
int juce_seekInInternetFile (void* handle, int newPosition) |
|
|
|
{ |
|
|
|
JuceURLConnection* const s = (JuceURLConnection*) handle; |
|
|
|
@@ -265111,6 +265174,9 @@ bool NSViewComponentPeer::handleKeyEvent (NSEvent* ev, bool isKeyDown) |
|
|
|
juce_wchar textCharacter = unicode[0]; |
|
|
|
unicode = unicode.substring (1); |
|
|
|
|
|
|
|
if (([ev modifierFlags] & NSCommandKeyMask) != 0) |
|
|
|
textCharacter = 0; |
|
|
|
|
|
|
|
used = handleKeyUpOrDown() || used; |
|
|
|
used = handleKeyPress (keyCode, textCharacter) || used; |
|
|
|
} |
|
|
|
@@ -265127,6 +265193,45 @@ bool NSViewComponentPeer::handleKeyEvent (NSEvent* ev, bool isKeyDown) |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
bool NSViewComponentPeer::redirectKeyDown (NSEvent* ev) |
|
|
|
{ |
|
|
|
updateKeysDown (ev, true); |
|
|
|
bool used = handleKeyEvent (ev, true); |
|
|
|
|
|
|
|
if (([ev modifierFlags] & NSCommandKeyMask) != 0) |
|
|
|
{ |
|
|
|
// for command keys, the key-up event is thrown away, so simulate one.. |
|
|
|
updateKeysDown (ev, false); |
|
|
|
used = (isValidPeer (this) && handleKeyEvent (ev, false)) || used; |
|
|
|
} |
|
|
|
|
|
|
|
return used; |
|
|
|
} |
|
|
|
|
|
|
|
bool NSViewComponentPeer::redirectKeyUp (NSEvent* ev) |
|
|
|
{ |
|
|
|
updateKeysDown (ev, false); |
|
|
|
return handleKeyEvent (ev, false); |
|
|
|
} |
|
|
|
|
|
|
|
void NSViewComponentPeer::redirectModKeyChange (NSEvent* ev) |
|
|
|
{ |
|
|
|
updateModifiers (ev); |
|
|
|
handleModifierKeysChange(); |
|
|
|
} |
|
|
|
|
|
|
|
#if MACOS_10_4_OR_EARLIER |
|
|
|
bool NSViewComponentPeer::redirectPerformKeyEquivalent (NSEvent* ev) |
|
|
|
{ |
|
|
|
if ([ev type] == NSKeyDown) |
|
|
|
return redirectKeyDown (ev); |
|
|
|
else if ([ev type] == NSKeyUp) |
|
|
|
return redirectKeyUp (ev); |
|
|
|
|
|
|
|
return false; |
|
|
|
} |
|
|
|
#endif |
|
|
|
|
|
|
|
void NSViewComponentPeer::redirectMouseDown (NSEvent* ev) |
|
|
|
{ |
|
|
|
updateModifiers (ev); |
|
|
|
@@ -265194,45 +265299,6 @@ void NSViewComponentPeer::redirectMouseWheel (NSEvent* ev) |
|
|
|
getMouseTime (ev)); |
|
|
|
} |
|
|
|
|
|
|
|
bool NSViewComponentPeer::redirectKeyDown (NSEvent* ev) |
|
|
|
{ |
|
|
|
updateKeysDown (ev, true); |
|
|
|
bool used = handleKeyEvent (ev, true); |
|
|
|
|
|
|
|
if (([ev modifierFlags] & NSCommandKeyMask) != 0) |
|
|
|
{ |
|
|
|
// for command keys, the key-up event is thrown away, so simulate one.. |
|
|
|
updateKeysDown (ev, false); |
|
|
|
used = (isValidPeer (this) && handleKeyEvent (ev, false)) || used; |
|
|
|
} |
|
|
|
|
|
|
|
return used; |
|
|
|
} |
|
|
|
|
|
|
|
bool NSViewComponentPeer::redirectKeyUp (NSEvent* ev) |
|
|
|
{ |
|
|
|
updateKeysDown (ev, false); |
|
|
|
return handleKeyEvent (ev, false); |
|
|
|
} |
|
|
|
|
|
|
|
void NSViewComponentPeer::redirectModKeyChange (NSEvent* ev) |
|
|
|
{ |
|
|
|
updateModifiers (ev); |
|
|
|
handleModifierKeysChange(); |
|
|
|
} |
|
|
|
|
|
|
|
#if MACOS_10_4_OR_EARLIER |
|
|
|
bool NSViewComponentPeer::redirectPerformKeyEquivalent (NSEvent* ev) |
|
|
|
{ |
|
|
|
updateKeysDown (ev, true); |
|
|
|
const bool used1 = isValidPeer (this) && handleKeyEvent (ev, true); |
|
|
|
updateKeysDown (ev, false); |
|
|
|
const bool used2 = isValidPeer (this) && handleKeyEvent (ev, false); |
|
|
|
|
|
|
|
return used1 || used2; |
|
|
|
} |
|
|
|
#endif |
|
|
|
|
|
|
|
BOOL NSViewComponentPeer::sendDragCallback (int type, id <NSDraggingInfo> sender) |
|
|
|
{ |
|
|
|
NSString* bestType |
|
|
|
@@ -265442,17 +265508,17 @@ static NSImage* juceImageToNSImage (const Image& image) |
|
|
|
lineStride, pixelStride); |
|
|
|
|
|
|
|
NSBitmapImageRep* rep = [[NSBitmapImageRep alloc] |
|
|
|
initWithBitmapDataPlanes: NULL |
|
|
|
pixelsWide: image.getWidth() |
|
|
|
pixelsHigh: image.getHeight() |
|
|
|
bitsPerSample: 8 |
|
|
|
samplesPerPixel: image.hasAlphaChannel() ? 4 : 3 |
|
|
|
hasAlpha: image.hasAlphaChannel() |
|
|
|
isPlanar: NO |
|
|
|
colorSpaceName: NSCalibratedRGBColorSpace |
|
|
|
initWithBitmapDataPlanes: NULL |
|
|
|
pixelsWide: image.getWidth() |
|
|
|
pixelsHigh: image.getHeight() |
|
|
|
bitsPerSample: 8 |
|
|
|
samplesPerPixel: image.hasAlphaChannel() ? 4 : 3 |
|
|
|
hasAlpha: image.hasAlphaChannel() |
|
|
|
isPlanar: NO |
|
|
|
colorSpaceName: NSCalibratedRGBColorSpace |
|
|
|
bitmapFormat: (NSBitmapFormat) 0 |
|
|
|
bytesPerRow: lineStride |
|
|
|
bitsPerPixel: pixelStride * 8]; |
|
|
|
bytesPerRow: lineStride |
|
|
|
bitsPerPixel: pixelStride * 8]; |
|
|
|
|
|
|
|
unsigned char* newData = [rep bitmapData]; |
|
|
|
memcpy (newData, pixels, lineStride * image.getHeight()); |
|
|
|
@@ -266484,59 +266550,59 @@ MenuBarModel* MenuBarModel::getMacMainMenu() throw() |
|
|
|
|
|
|
|
static NSMenu* createStandardAppMenu (NSMenu* menu, const String& appName) |
|
|
|
{ |
|
|
|
NSMenuItem* item; |
|
|
|
NSMenuItem* item; |
|
|
|
|
|
|
|
// xxx should allow the 'about' and 'preferences' items to be turned on programatically... |
|
|
|
/* item = [menu addItemWithTitle: juceStringToNS ("About " + appName)] |
|
|
|
action: @selector(orderFrontStandardAboutPanel:) keyEquivalent: @""]; |
|
|
|
[item setTarget: NSApp]; |
|
|
|
[menu addItem: [NSMenuItem separatorItem]]; |
|
|
|
action: @selector(orderFrontStandardAboutPanel:) keyEquivalent: @""]; |
|
|
|
[item setTarget: NSApp]; |
|
|
|
[menu addItem: [NSMenuItem separatorItem]]; |
|
|
|
*/ |
|
|
|
|
|
|
|
/* item = [menu addItemWithTitle: NSLocalizedString (@"Preferences...", nil) |
|
|
|
action: nil keyEquivalent: @","]; |
|
|
|
[menu addItem: [NSMenuItem separatorItem]]; |
|
|
|
action: nil keyEquivalent: @","]; |
|
|
|
[menu addItem: [NSMenuItem separatorItem]]; |
|
|
|
*/ |
|
|
|
|
|
|
|
// Services... |
|
|
|
item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString (@"Services", nil) |
|
|
|
action: nil keyEquivalent: @""]; |
|
|
|
[menu addItem: item]; |
|
|
|
[menu addItem: item]; |
|
|
|
[item release]; |
|
|
|
NSMenu* servicesMenu = [[NSMenu alloc] initWithTitle: @"Services"]; |
|
|
|
[menu setSubmenu: servicesMenu forItem: item]; |
|
|
|
[NSApp setServicesMenu: servicesMenu]; |
|
|
|
[servicesMenu release]; |
|
|
|
[menu addItem: [NSMenuItem separatorItem]]; |
|
|
|
NSMenu* servicesMenu = [[NSMenu alloc] initWithTitle: @"Services"]; |
|
|
|
[menu setSubmenu: servicesMenu forItem: item]; |
|
|
|
[NSApp setServicesMenu: servicesMenu]; |
|
|
|
[servicesMenu release]; |
|
|
|
[menu addItem: [NSMenuItem separatorItem]]; |
|
|
|
|
|
|
|
// Hide + Show stuff... |
|
|
|
item = [[NSMenuItem alloc] initWithTitle: juceStringToNS ("Hide " + appName) |
|
|
|
action: @selector (hide:) keyEquivalent: @"h"]; |
|
|
|
[item setTarget: NSApp]; |
|
|
|
[menu addItem: item]; |
|
|
|
[item setTarget: NSApp]; |
|
|
|
[menu addItem: item]; |
|
|
|
[item release]; |
|
|
|
|
|
|
|
item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString (@"Hide Others", nil) |
|
|
|
action: @selector (hideOtherApplications:) keyEquivalent: @"h"]; |
|
|
|
[item setKeyEquivalentModifierMask: NSCommandKeyMask | NSAlternateKeyMask]; |
|
|
|
[item setTarget: NSApp]; |
|
|
|
[menu addItem: item]; |
|
|
|
[item setKeyEquivalentModifierMask: NSCommandKeyMask | NSAlternateKeyMask]; |
|
|
|
[item setTarget: NSApp]; |
|
|
|
[menu addItem: item]; |
|
|
|
[item release]; |
|
|
|
|
|
|
|
item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString (@"Show All", nil) |
|
|
|
action: @selector (unhideAllApplications:) keyEquivalent: @""]; |
|
|
|
[item setTarget: NSApp]; |
|
|
|
[menu addItem: item]; |
|
|
|
[item setTarget: NSApp]; |
|
|
|
[menu addItem: item]; |
|
|
|
[item release]; |
|
|
|
|
|
|
|
[menu addItem: [NSMenuItem separatorItem]]; |
|
|
|
[menu addItem: [NSMenuItem separatorItem]]; |
|
|
|
|
|
|
|
// Quit item.... |
|
|
|
item = [[NSMenuItem alloc] initWithTitle: juceStringToNS ("Quit " + appName) |
|
|
|
action: @selector (terminate:) keyEquivalent: @"q"]; |
|
|
|
|
|
|
|
[item setTarget: NSApp]; |
|
|
|
[menu addItem: item]; |
|
|
|
[item setTarget: NSApp]; |
|
|
|
[menu addItem: item]; |
|
|
|
[item release]; |
|
|
|
|
|
|
|
return menu; |
|
|
|
|