| @@ -33,6 +33,88 @@ | |||
| // compiled on its own). | |||
| #if JUCE_INCLUDED_FILE && JUCE_OPENGL | |||
| END_JUCE_NAMESPACE | |||
| //============================================================================== | |||
| @interface ThreadSafeNSOpenGLView : NSOpenGLView | |||
| { | |||
| CriticalSection* contextLock; | |||
| bool needsUpdate; | |||
| } | |||
| - (id) initWithFrame: (NSRect) frameRect pixelFormat: (NSOpenGLPixelFormat*) format; | |||
| - (bool) makeActive; | |||
| - (void) makeInactive; | |||
| - (void) reshape; | |||
| @end | |||
| @implementation ThreadSafeNSOpenGLView | |||
| - (id) initWithFrame: (NSRect) frameRect | |||
| pixelFormat: (NSOpenGLPixelFormat*) format | |||
| { | |||
| contextLock = new CriticalSection(); | |||
| self = [super initWithFrame: frameRect pixelFormat: format]; | |||
| if (self != nil) | |||
| [[NSNotificationCenter defaultCenter] addObserver: self | |||
| selector: @selector (_surfaceNeedsUpdate:) | |||
| name: NSViewGlobalFrameDidChangeNotification | |||
| object: self]; | |||
| return self; | |||
| } | |||
| - (void) dealloc | |||
| { | |||
| [[NSNotificationCenter defaultCenter] removeObserver: self]; | |||
| delete contextLock; | |||
| [super dealloc]; | |||
| } | |||
| - (bool) makeActive | |||
| { | |||
| const ScopedLock sl (*contextLock); | |||
| if ([self openGLContext] == 0) | |||
| return false; | |||
| [[self openGLContext] makeCurrentContext]; | |||
| if (needsUpdate) | |||
| { | |||
| [super update]; | |||
| needsUpdate = false; | |||
| } | |||
| return true; | |||
| } | |||
| - (void) makeInactive | |||
| { | |||
| const ScopedLock sl (*contextLock); | |||
| [NSOpenGLContext clearCurrentContext]; | |||
| } | |||
| - (void) _surfaceNeedsUpdate: (NSNotification*) notification | |||
| { | |||
| const ScopedLock sl (*contextLock); | |||
| needsUpdate = true; | |||
| } | |||
| - (void) update | |||
| { | |||
| const ScopedLock sl (*contextLock); | |||
| needsUpdate = true; | |||
| } | |||
| - (void) reshape | |||
| { | |||
| const ScopedLock sl (*contextLock); | |||
| needsUpdate = true; | |||
| } | |||
| @end | |||
| BEGIN_JUCE_NAMESPACE | |||
| //============================================================================== | |||
| class WindowedGLContext : public OpenGLContext | |||
| @@ -50,6 +132,7 @@ public: | |||
| int n = 0; | |||
| attribs[n++] = NSOpenGLPFADoubleBuffer; | |||
| attribs[n++] = NSOpenGLPFAAccelerated; | |||
| attribs[n++] = NSOpenGLPFAMPSafe; // NSOpenGLPFAAccelerated, NSOpenGLPFAMultiScreen, NSOpenGLPFASingleRenderer | |||
| attribs[n++] = NSOpenGLPFAColorSize; | |||
| attribs[n++] = (NSOpenGLPixelFormatAttribute) jmax (pixelFormat.redBits, | |||
| pixelFormat.greenBits, | |||
| @@ -67,7 +150,6 @@ public: | |||
| pixelFormat.accumulationBufferAlphaBits); | |||
| // xxx not sure how to do fullSceneAntiAliasingNumSamples.. | |||
| attribs[n++] = NSOpenGLPFASampleBuffers; | |||
| attribs[n++] = (NSOpenGLPixelFormatAttribute) 1; | |||
| attribs[n++] = NSOpenGLPFAClosestPolicy; | |||
| @@ -77,21 +159,13 @@ public: | |||
| NSOpenGLPixelFormat* format | |||
| = [[NSOpenGLPixelFormat alloc] initWithAttributes: attribs]; | |||
| NSOpenGLView* view | |||
| = [[NSOpenGLView alloc] initWithFrame: NSMakeRect (0, 0, 100.0f, 100.0f) | |||
| pixelFormat: format]; | |||
| if (sharedContext != 0) | |||
| { | |||
| renderContext = [[NSOpenGLContext alloc] initWithFormat: format | |||
| shareContext: sharedContext]; | |||
| [view setOpenGLContext: renderContext]; | |||
| [renderContext setView: view]; | |||
| } | |||
| else | |||
| { | |||
| renderContext = [view openGLContext]; | |||
| } | |||
| view = [[ThreadSafeNSOpenGLView alloc] initWithFrame: NSMakeRect (0, 0, 100.0f, 100.0f) | |||
| pixelFormat: format]; | |||
| renderContext = [[[NSOpenGLContext alloc] initWithFormat: format | |||
| shareContext: sharedContext] autorelease]; | |||
| [view setOpenGLContext: renderContext]; | |||
| [renderContext setView: view]; | |||
| [format release]; | |||
| @@ -108,15 +182,13 @@ public: | |||
| bool makeActive() const throw() | |||
| { | |||
| jassert (renderContext != 0); | |||
| [renderContext makeCurrentContext]; | |||
| return renderContext != 0; | |||
| [view makeActive]; | |||
| return isActive(); | |||
| } | |||
| bool makeInactive() const throw() | |||
| { | |||
| if (! isActive()) | |||
| [NSOpenGLContext clearCurrentContext]; | |||
| [view makeInactive]; | |||
| return true; | |||
| } | |||
| @@ -134,7 +206,6 @@ public: | |||
| void swapBuffers() | |||
| { | |||
| glFlush(); | |||
| [renderContext flushBuffer]; | |||
| } | |||
| @@ -173,6 +244,7 @@ public: | |||
| juce_UseDebuggingNewOperator | |||
| NSOpenGLContext* renderContext; | |||
| ThreadSafeNSOpenGLView* view; | |||
| private: | |||
| OpenGLPixelFormat pixelFormat; | |||
| @@ -2033,9 +2033,18 @@ private: | |||
| return 0; | |||
| case WM_QUIT: | |||
| JUCEApplication::quit(); | |||
| if (JUCEApplication::getInstance() != 0) | |||
| JUCEApplication::getInstance()->systemRequestedQuit(); | |||
| return 0; | |||
| case WM_QUERYENDSESSION: | |||
| if (JUCEApplication::getInstance() != 0) | |||
| { | |||
| JUCEApplication::getInstance()->systemRequestedQuit(); | |||
| return MessageManager::getInstance()->hasStopMessageBeenSent(); | |||
| } | |||
| return TRUE; | |||
| //============================================================================== | |||
| case WM_TRAYNOTIFY: | |||
| if (component->isCurrentlyBlockedByAnotherModalComponent()) | |||
| @@ -69,12 +69,26 @@ | |||
| #include "public.sdk/source/vst2.x/aeffeditor.h" | |||
| #include "public.sdk/source/vst2.x/audioeffectx.cpp" | |||
| #include "public.sdk/source/vst2.x/audioeffect.cpp" | |||
| #if JUCE_LINUX | |||
| #define __cdecl | |||
| #endif | |||
| #if ! VST_2_4_EXTENSIONS | |||
| #error // You're probably trying to include the wrong VSTSDK version - make sure your include path matches the JUCE_USE_VSTSDK_2_4 flag | |||
| #endif | |||
| #else | |||
| // VSTSDK V2.3 includes.. | |||
| #include "source/common/audioeffectx.h" | |||
| #include "source/common/AEffEditor.hpp" | |||
| #include "source/common/audioeffectx.cpp" | |||
| #include "source/common/AudioEffect.cpp" | |||
| #if (! VST_2_3_EXTENSIONS) || VST_2_4_EXTENSIONS | |||
| #error // You're probably trying to include the wrong VSTSDK version - make sure your include path matches the JUCE_USE_VSTSDK_2_4 flag | |||
| #endif | |||
| typedef long VstInt32; | |||
| typedef long VstIntPtr; | |||
| enum Vst2StringConstants | |||
| @@ -966,7 +980,13 @@ public: | |||
| bool setSpeakerArrangement (VstSpeakerArrangement* pluginInput, | |||
| VstSpeakerArrangement* pluginOutput) | |||
| { | |||
| // if this method isn't implemented, nuendo4 + cubase4 crash when you've got multiple channels.. | |||
| if (numInChans != pluginInput->numChannels | |||
| || numOutChans != pluginOutput->numChannels) | |||
| { | |||
| setNumInputs (pluginInput->numChannels); | |||
| setNumOutputs (pluginOutput->numChannels); | |||
| ioChanged(); | |||
| } | |||
| numInChans = pluginInput->numChannels; | |||
| numOutChans = pluginOutput->numChannels; | |||
| @@ -8029,8 +8029,12 @@ int BufferedInputStream::read (void* destBuffer, int maxBytesToRead) | |||
| destBuffer = (void*) (((char*) destBuffer) + bytesAvailable); | |||
| } | |||
| const int64 oldLastReadPos = lastReadPos; | |||
| ensureBuffered(); | |||
| if (oldLastReadPos == lastReadPos) | |||
| break; // if ensureBuffered() failed to read any more data, bail out | |||
| if (isExhausted()) | |||
| break; | |||
| } | |||
| @@ -9749,6 +9753,11 @@ void LocalisedStrings::loadFromText (const String& fileContents) throw() | |||
| } | |||
| } | |||
| void LocalisedStrings::setIgnoresCase (const bool shouldIgnoreCase) throw() | |||
| { | |||
| translations.setIgnoresCase (shouldIgnoreCase); | |||
| } | |||
| static CriticalSection currentMappingsLock; | |||
| static LocalisedStrings* currentMappings = 0; | |||
| @@ -12592,6 +12601,11 @@ void StringPairArray::remove (const int index) throw() | |||
| values.remove (index); | |||
| } | |||
| void StringPairArray::setIgnoresCase (const bool shouldIgnoreCase) throw() | |||
| { | |||
| ignoreCase = shouldIgnoreCase; | |||
| } | |||
| void StringPairArray::minimiseStorageOverheads() throw() | |||
| { | |||
| keys.minimiseStorageOverheads(); | |||
| @@ -22363,7 +22377,7 @@ const String AudioDeviceManager::setAudioDeviceSetup (const AudioDeviceSetup& ne | |||
| const String newOutputDeviceName (numOutputChansNeeded == 0 ? String::empty : newSetup.outputDeviceName); | |||
| if (currentSetup.inputDeviceName != newInputDeviceName | |||
| || currentSetup.inputDeviceName != newOutputDeviceName | |||
| || currentSetup.outputDeviceName != newOutputDeviceName | |||
| || currentAudioDevice == 0) | |||
| { | |||
| deleteCurrentDevice(); | |||
| @@ -22813,12 +22827,18 @@ void AudioDeviceManager::setDefaultMidiOutput (const String& deviceName) | |||
| { | |||
| if (defaultMidiOutputName != deviceName) | |||
| { | |||
| if (currentCallback != 0 && currentAudioDevice != 0) | |||
| currentCallback->audioDeviceStopped(); | |||
| deleteAndZero (defaultMidiOutput); | |||
| defaultMidiOutputName = deviceName; | |||
| if (deviceName.isNotEmpty()) | |||
| defaultMidiOutput = MidiOutput::openDevice (MidiOutput::getDevices().indexOf (deviceName)); | |||
| if (currentCallback != 0 && currentAudioDevice != 0) | |||
| currentCallback->audioDeviceAboutToStart (currentAudioDevice); | |||
| updateXml(); | |||
| sendChangeMessage (this); | |||
| } | |||
| @@ -71675,6 +71695,11 @@ void AlertWindow::lookAndFeelChanged() | |||
| setDropShadowEnabled ((flags & ComponentPeer::windowHasDropShadow) != 0); | |||
| } | |||
| int AlertWindow::getDesktopWindowStyleFlags() const | |||
| { | |||
| return getLookAndFeel().getAlertBoxWindowFlags(); | |||
| } | |||
| struct AlertWindowInfo | |||
| { | |||
| String title, message, button1, button2, button3; | |||
| @@ -76036,7 +76061,7 @@ void Graphics::strokePath (const Path& path, | |||
| const PathStrokeType& strokeType, | |||
| const AffineTransform& transform) const throw() | |||
| { | |||
| if (! state->colour.isTransparent()) | |||
| if ((! state->colour.isTransparent()) || state->brush != 0) | |||
| { | |||
| Path stroke; | |||
| strokeType.createStrokedPath (stroke, path, transform); | |||
| @@ -244183,9 +244208,18 @@ private: | |||
| return 0; | |||
| case WM_QUIT: | |||
| JUCEApplication::quit(); | |||
| if (JUCEApplication::getInstance() != 0) | |||
| JUCEApplication::getInstance()->systemRequestedQuit(); | |||
| return 0; | |||
| case WM_QUERYENDSESSION: | |||
| if (JUCEApplication::getInstance() != 0) | |||
| { | |||
| JUCEApplication::getInstance()->systemRequestedQuit(); | |||
| return MessageManager::getInstance()->hasStopMessageBeenSent(); | |||
| } | |||
| return TRUE; | |||
| case WM_TRAYNOTIFY: | |||
| if (component->isCurrentlyBlockedByAnotherModalComponent()) | |||
| { | |||
| @@ -267842,6 +267876,88 @@ void AppleRemoteDevice::handleCallbackInternal() | |||
| // compiled on its own). | |||
| #if JUCE_INCLUDED_FILE && JUCE_OPENGL | |||
| END_JUCE_NAMESPACE | |||
| @interface ThreadSafeNSOpenGLView : NSOpenGLView | |||
| { | |||
| CriticalSection* contextLock; | |||
| bool needsUpdate; | |||
| } | |||
| - (id) initWithFrame: (NSRect) frameRect pixelFormat: (NSOpenGLPixelFormat*) format; | |||
| - (bool) makeActive; | |||
| - (void) makeInactive; | |||
| - (void) reshape; | |||
| @end | |||
| @implementation ThreadSafeNSOpenGLView | |||
| - (id) initWithFrame: (NSRect) frameRect | |||
| pixelFormat: (NSOpenGLPixelFormat*) format | |||
| { | |||
| contextLock = new CriticalSection(); | |||
| self = [super initWithFrame: frameRect pixelFormat: format]; | |||
| if (self != nil) | |||
| [[NSNotificationCenter defaultCenter] addObserver: self | |||
| selector: @selector (_surfaceNeedsUpdate:) | |||
| name: NSViewGlobalFrameDidChangeNotification | |||
| object: self]; | |||
| return self; | |||
| } | |||
| - (void) dealloc | |||
| { | |||
| [[NSNotificationCenter defaultCenter] removeObserver: self]; | |||
| delete contextLock; | |||
| [super dealloc]; | |||
| } | |||
| - (bool) makeActive | |||
| { | |||
| const ScopedLock sl (*contextLock); | |||
| if ([self openGLContext] == 0) | |||
| return false; | |||
| [[self openGLContext] makeCurrentContext]; | |||
| if (needsUpdate) | |||
| { | |||
| [super update]; | |||
| needsUpdate = false; | |||
| } | |||
| return true; | |||
| } | |||
| - (void) makeInactive | |||
| { | |||
| const ScopedLock sl (*contextLock); | |||
| [NSOpenGLContext clearCurrentContext]; | |||
| } | |||
| - (void) _surfaceNeedsUpdate: (NSNotification*) notification | |||
| { | |||
| const ScopedLock sl (*contextLock); | |||
| needsUpdate = true; | |||
| } | |||
| - (void) update | |||
| { | |||
| const ScopedLock sl (*contextLock); | |||
| needsUpdate = true; | |||
| } | |||
| - (void) reshape | |||
| { | |||
| const ScopedLock sl (*contextLock); | |||
| needsUpdate = true; | |||
| } | |||
| @end | |||
| BEGIN_JUCE_NAMESPACE | |||
| class WindowedGLContext : public OpenGLContext | |||
| { | |||
| public: | |||
| @@ -267857,6 +267973,7 @@ public: | |||
| int n = 0; | |||
| attribs[n++] = NSOpenGLPFADoubleBuffer; | |||
| attribs[n++] = NSOpenGLPFAAccelerated; | |||
| attribs[n++] = NSOpenGLPFAMPSafe; // NSOpenGLPFAAccelerated, NSOpenGLPFAMultiScreen, NSOpenGLPFASingleRenderer | |||
| attribs[n++] = NSOpenGLPFAColorSize; | |||
| attribs[n++] = (NSOpenGLPixelFormatAttribute) jmax (pixelFormat.redBits, | |||
| pixelFormat.greenBits, | |||
| @@ -267874,7 +267991,6 @@ public: | |||
| pixelFormat.accumulationBufferAlphaBits); | |||
| // xxx not sure how to do fullSceneAntiAliasingNumSamples.. | |||
| attribs[n++] = NSOpenGLPFASampleBuffers; | |||
| attribs[n++] = (NSOpenGLPixelFormatAttribute) 1; | |||
| attribs[n++] = NSOpenGLPFAClosestPolicy; | |||
| @@ -267884,21 +268000,13 @@ public: | |||
| NSOpenGLPixelFormat* format | |||
| = [[NSOpenGLPixelFormat alloc] initWithAttributes: attribs]; | |||
| NSOpenGLView* view | |||
| = [[NSOpenGLView alloc] initWithFrame: NSMakeRect (0, 0, 100.0f, 100.0f) | |||
| pixelFormat: format]; | |||
| view = [[ThreadSafeNSOpenGLView alloc] initWithFrame: NSMakeRect (0, 0, 100.0f, 100.0f) | |||
| pixelFormat: format]; | |||
| if (sharedContext != 0) | |||
| { | |||
| renderContext = [[NSOpenGLContext alloc] initWithFormat: format | |||
| shareContext: sharedContext]; | |||
| [view setOpenGLContext: renderContext]; | |||
| [renderContext setView: view]; | |||
| } | |||
| else | |||
| { | |||
| renderContext = [view openGLContext]; | |||
| } | |||
| renderContext = [[[NSOpenGLContext alloc] initWithFormat: format | |||
| shareContext: sharedContext] autorelease]; | |||
| [view setOpenGLContext: renderContext]; | |||
| [renderContext setView: view]; | |||
| [format release]; | |||
| @@ -267915,15 +268023,13 @@ public: | |||
| bool makeActive() const throw() | |||
| { | |||
| jassert (renderContext != 0); | |||
| [renderContext makeCurrentContext]; | |||
| return renderContext != 0; | |||
| [view makeActive]; | |||
| return isActive(); | |||
| } | |||
| bool makeInactive() const throw() | |||
| { | |||
| if (! isActive()) | |||
| [NSOpenGLContext clearCurrentContext]; | |||
| [view makeInactive]; | |||
| return true; | |||
| } | |||
| @@ -267941,7 +268047,6 @@ public: | |||
| void swapBuffers() | |||
| { | |||
| glFlush(); | |||
| [renderContext flushBuffer]; | |||
| } | |||
| @@ -267979,6 +268084,7 @@ public: | |||
| juce_UseDebuggingNewOperator | |||
| NSOpenGLContext* renderContext; | |||
| ThreadSafeNSOpenGLView* view; | |||
| private: | |||
| OpenGLPixelFormat pixelFormat; | |||
| @@ -2783,6 +2783,7 @@ protected: | |||
| numAllocated (0), | |||
| granularity (granularity_) | |||
| { | |||
| jassert (granularity > 0); | |||
| } | |||
| /** Destructor. */ | |||
| @@ -8102,6 +8103,10 @@ public: | |||
| */ | |||
| void remove (const int index) throw(); | |||
| /** Indicates whether to use a case-insensitive search when looking up a key string. | |||
| */ | |||
| void setIgnoresCase (const bool shouldIgnoreCase) throw(); | |||
| /** Reduces the amount of storage being used by the array. | |||
| Arrays typically allocate slightly more storage than they need, and after | |||
| @@ -11214,23 +11219,26 @@ public: | |||
| { | |||
| jassert (numValuesToRemove >= 0); | |||
| if (numValuesToRemove != 0 | |||
| if (numValuesToRemove >= 0 | |||
| && firstValue < values.getLast()) | |||
| { | |||
| const bool onAtStart = contains (firstValue - 1); | |||
| Type lastValue = firstValue + numValuesToRemove; | |||
| if (lastValue < firstValue) // possible if the signed arithmetic wraps around | |||
| lastValue = values.getLast(); | |||
| const Type lastValue = firstValue + jmin (numValuesToRemove, values.getLast() - firstValue); | |||
| const bool onAtEnd = contains (lastValue); | |||
| for (int i = values.size(); --i >= 0;) | |||
| { | |||
| if (values.getUnchecked(i) >= firstValue | |||
| && values.getUnchecked(i) <= lastValue) | |||
| if (values.getUnchecked(i) <= lastValue) | |||
| { | |||
| values.remove (i); | |||
| while (values.getUnchecked(i) >= firstValue) | |||
| { | |||
| values.remove (i); | |||
| if (--i < 0) | |||
| break; | |||
| } | |||
| break; | |||
| } | |||
| } | |||
| @@ -13693,6 +13701,11 @@ public: | |||
| */ | |||
| const StringArray getCountryCodes() const throw() { return countryCodes; } | |||
| /** Indicates whether to use a case-insensitive search when looking up a string. | |||
| This defaults to true. | |||
| */ | |||
| void setIgnoresCase (const bool shouldIgnoreCase) throw(); | |||
| juce_UseDebuggingNewOperator | |||
| private: | |||
| @@ -50713,6 +50726,8 @@ protected: | |||
| void lookAndFeelChanged(); | |||
| /** @internal */ | |||
| void userTriedToCloseWindow(); | |||
| /** @internal */ | |||
| int getDesktopWindowStyleFlags() const; | |||
| private: | |||
| String text; | |||
| @@ -379,7 +379,7 @@ const String AudioDeviceManager::setAudioDeviceSetup (const AudioDeviceSetup& ne | |||
| const String newOutputDeviceName (numOutputChansNeeded == 0 ? String::empty : newSetup.outputDeviceName); | |||
| if (currentSetup.inputDeviceName != newInputDeviceName | |||
| || currentSetup.inputDeviceName != newOutputDeviceName | |||
| || currentSetup.outputDeviceName != newOutputDeviceName | |||
| || currentAudioDevice == 0) | |||
| { | |||
| deleteCurrentDevice(); | |||
| @@ -832,12 +832,18 @@ void AudioDeviceManager::setDefaultMidiOutput (const String& deviceName) | |||
| { | |||
| if (defaultMidiOutputName != deviceName) | |||
| { | |||
| if (currentCallback != 0 && currentAudioDevice != 0) | |||
| currentCallback->audioDeviceStopped(); | |||
| deleteAndZero (defaultMidiOutput); | |||
| defaultMidiOutputName = deviceName; | |||
| if (deviceName.isNotEmpty()) | |||
| defaultMidiOutput = MidiOutput::openDevice (MidiOutput::getDevices().indexOf (deviceName)); | |||
| if (currentCallback != 0 && currentAudioDevice != 0) | |||
| currentCallback->audioDeviceAboutToStart (currentAudioDevice); | |||
| updateXml(); | |||
| sendChangeMessage (this); | |||
| } | |||
| @@ -591,6 +591,11 @@ void AlertWindow::lookAndFeelChanged() | |||
| setDropShadowEnabled ((flags & ComponentPeer::windowHasDropShadow) != 0); | |||
| } | |||
| int AlertWindow::getDesktopWindowStyleFlags() const | |||
| { | |||
| return getLookAndFeel().getAlertBoxWindowFlags(); | |||
| } | |||
| //============================================================================== | |||
| struct AlertWindowInfo | |||
| { | |||
| @@ -339,6 +339,8 @@ protected: | |||
| void lookAndFeelChanged(); | |||
| /** @internal */ | |||
| void userTriedToCloseWindow(); | |||
| /** @internal */ | |||
| int getDesktopWindowStyleFlags() const; | |||
| private: | |||
| String text; | |||
| @@ -429,7 +429,7 @@ void Graphics::strokePath (const Path& path, | |||
| const PathStrokeType& strokeType, | |||
| const AffineTransform& transform) const throw() | |||
| { | |||
| if (! state->colour.isTransparent()) | |||
| if ((! state->colour.isTransparent()) || state->brush != 0) | |||
| { | |||
| Path stroke; | |||
| strokeType.createStrokedPath (stroke, path, transform); | |||
| @@ -65,6 +65,7 @@ protected: | |||
| numAllocated (0), | |||
| granularity (granularity_) | |||
| { | |||
| jassert (granularity > 0); | |||
| } | |||
| /** Destructor. */ | |||
| @@ -225,23 +225,26 @@ public: | |||
| { | |||
| jassert (numValuesToRemove >= 0); | |||
| if (numValuesToRemove != 0 | |||
| if (numValuesToRemove >= 0 | |||
| && firstValue < values.getLast()) | |||
| { | |||
| const bool onAtStart = contains (firstValue - 1); | |||
| Type lastValue = firstValue + numValuesToRemove; | |||
| if (lastValue < firstValue) // possible if the signed arithmetic wraps around | |||
| lastValue = values.getLast(); | |||
| const Type lastValue = firstValue + jmin (numValuesToRemove, values.getLast() - firstValue); | |||
| const bool onAtEnd = contains (lastValue); | |||
| for (int i = values.size(); --i >= 0;) | |||
| { | |||
| if (values.getUnchecked(i) >= firstValue | |||
| && values.getUnchecked(i) <= lastValue) | |||
| if (values.getUnchecked(i) <= lastValue) | |||
| { | |||
| values.remove (i); | |||
| while (values.getUnchecked(i) >= firstValue) | |||
| { | |||
| values.remove (i); | |||
| if (--i < 0) | |||
| break; | |||
| } | |||
| break; | |||
| } | |||
| } | |||
| @@ -153,8 +153,12 @@ int BufferedInputStream::read (void* destBuffer, int maxBytesToRead) | |||
| destBuffer = (void*) (((char*) destBuffer) + bytesAvailable); | |||
| } | |||
| const int64 oldLastReadPos = lastReadPos; | |||
| ensureBuffered(); | |||
| if (oldLastReadPos == lastReadPos) | |||
| break; // if ensureBuffered() failed to read any more data, bail out | |||
| if (isExhausted()) | |||
| break; | |||
| } | |||
| @@ -124,6 +124,11 @@ void LocalisedStrings::loadFromText (const String& fileContents) throw() | |||
| } | |||
| } | |||
| void LocalisedStrings::setIgnoresCase (const bool shouldIgnoreCase) throw() | |||
| { | |||
| translations.setIgnoresCase (shouldIgnoreCase); | |||
| } | |||
| //============================================================================== | |||
| static CriticalSection currentMappingsLock; | |||
| static LocalisedStrings* currentMappings = 0; | |||
| @@ -181,6 +181,13 @@ public: | |||
| */ | |||
| const StringArray getCountryCodes() const throw() { return countryCodes; } | |||
| //============================================================================== | |||
| /** Indicates whether to use a case-insensitive search when looking up a string. | |||
| This defaults to true. | |||
| */ | |||
| void setIgnoresCase (const bool shouldIgnoreCase) throw(); | |||
| //============================================================================== | |||
| juce_UseDebuggingNewOperator | |||
| @@ -130,6 +130,11 @@ void StringPairArray::remove (const int index) throw() | |||
| values.remove (index); | |||
| } | |||
| void StringPairArray::setIgnoresCase (const bool shouldIgnoreCase) throw() | |||
| { | |||
| ignoreCase = shouldIgnoreCase; | |||
| } | |||
| void StringPairArray::minimiseStorageOverheads() throw() | |||
| { | |||
| keys.minimiseStorageOverheads(); | |||
| @@ -138,6 +138,11 @@ public: | |||
| */ | |||
| void remove (const int index) throw(); | |||
| //============================================================================== | |||
| /** Indicates whether to use a case-insensitive search when looking up a key string. | |||
| */ | |||
| void setIgnoresCase (const bool shouldIgnoreCase) throw(); | |||
| //============================================================================== | |||
| /** Reduces the amount of storage being used by the array. | |||