diff --git a/build/macosx/Juce.xcodeproj/project.pbxproj b/build/macosx/Juce.xcodeproj/project.pbxproj index be9bea98e0..65cf2694cd 100644 --- a/build/macosx/Juce.xcodeproj/project.pbxproj +++ b/build/macosx/Juce.xcodeproj/project.pbxproj @@ -105,7 +105,6 @@ 84816EAA10809DCB008FEC33 /* juce_ComponentMovementWatcher.h in Headers */ = {isa = PBXBuildFile; fileRef = 84F1EAA910403709006A1807 /* juce_ComponentMovementWatcher.h */; }; 84816EAB10809DCB008FEC33 /* juce_ComponentPeer.h in Headers */ = {isa = PBXBuildFile; fileRef = 84F1EB0A10403709006A1807 /* juce_ComponentPeer.h */; }; 84816EAC10809DCB008FEC33 /* juce_CriticalSection.h in Headers */ = {isa = PBXBuildFile; fileRef = 84F1E9D9104036D6006A1807 /* juce_CriticalSection.h */; }; - 84816EAD10809DCB008FEC33 /* juce_DataConversions.h in Headers */ = {isa = PBXBuildFile; fileRef = 84F1E90410403681006A1807 /* juce_DataConversions.h */; }; 84816EAE10809DCB008FEC33 /* juce_DeletedAtShutdown.h in Headers */ = {isa = PBXBuildFile; fileRef = 84F1E92C1040369C006A1807 /* juce_DeletedAtShutdown.h */; }; 84816EAF10809DCB008FEC33 /* juce_Desktop.h in Headers */ = {isa = PBXBuildFile; fileRef = 84F1EA4C10403708006A1807 /* juce_Desktop.h */; }; 84816EB010809DCB008FEC33 /* juce_DialogWindow.h in Headers */ = {isa = PBXBuildFile; fileRef = 84F1EB0C10403709006A1807 /* juce_DialogWindow.h */; }; @@ -617,6 +616,7 @@ 8481730F10832513008FEC33 /* juce_TargetPlatform.h in Headers */ = {isa = PBXBuildFile; fileRef = 8481730E10832513008FEC33 /* juce_TargetPlatform.h */; }; 84842F9510F6559300490977 /* juce_Value.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84BA603E10F2017A001D9D70 /* juce_Value.cpp */; }; 84842F9610F6559400490977 /* juce_Value.h in Headers */ = {isa = PBXBuildFile; fileRef = 84BA603F10F2017A001D9D70 /* juce_Value.h */; }; + 848432C310F933B800490977 /* juce_ByteOrder.h in Headers */ = {isa = PBXBuildFile; fileRef = 848432C210F933B800490977 /* juce_ByteOrder.h */; }; 8484E9A5103C958A008B7C6C /* juce_mac_NativeCode.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8484E9A4103C958A008B7C6C /* juce_mac_NativeCode.mm */; }; 8484E9BE103C9595008B7C6C /* juce_mac_AppleRemote.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8484E9A6103C9595008B7C6C /* juce_mac_AppleRemote.mm */; }; 8484E9BF103C9595008B7C6C /* juce_mac_AudioCDBurner.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8484E9A7103C9595008B7C6C /* juce_mac_AudioCDBurner.mm */; }; @@ -814,7 +814,6 @@ 84F1E91A10403681006A1807 /* juce_Initialisation.h in Headers */ = {isa = PBXBuildFile; fileRef = 84F1E90110403681006A1807 /* juce_Initialisation.h */; }; 84F1E91B10403681006A1807 /* juce_FileLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = 84F1E90210403681006A1807 /* juce_FileLogger.h */; }; 84F1E91C10403681006A1807 /* juce_FileLogger.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84F1E90310403681006A1807 /* juce_FileLogger.cpp */; }; - 84F1E91D10403681006A1807 /* juce_DataConversions.h in Headers */ = {isa = PBXBuildFile; fileRef = 84F1E90410403681006A1807 /* juce_DataConversions.h */; }; 84F1E91E10403681006A1807 /* juce_Atomic.h in Headers */ = {isa = PBXBuildFile; fileRef = 84F1E90510403681006A1807 /* juce_Atomic.h */; }; 84F1E91F10403681006A1807 /* juce_Uuid.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84F1E90610403681006A1807 /* juce_Uuid.cpp */; }; 84F1E92010403681006A1807 /* juce_Uuid.h in Headers */ = {isa = PBXBuildFile; fileRef = 84F1E90710403681006A1807 /* juce_Uuid.h */; }; @@ -1232,6 +1231,7 @@ 84816E5410809D07008FEC33 /* juce_iphone_MiscUtilities.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = juce_iphone_MiscUtilities.mm; sourceTree = ""; }; 84816E5610809D07008FEC33 /* juce_iphone_UIViewComponentPeer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = juce_iphone_UIViewComponentPeer.mm; sourceTree = ""; }; 8481730E10832513008FEC33 /* juce_TargetPlatform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = juce_TargetPlatform.h; sourceTree = ""; }; + 848432C210F933B800490977 /* juce_ByteOrder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = juce_ByteOrder.h; sourceTree = ""; }; 8484E9A4103C958A008B7C6C /* juce_mac_NativeCode.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = juce_mac_NativeCode.mm; path = ../../src/native/juce_mac_NativeCode.mm; sourceTree = SOURCE_ROOT; }; 8484E9A6103C9595008B7C6C /* juce_mac_AppleRemote.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = juce_mac_AppleRemote.mm; path = ../../src/native/mac/juce_mac_AppleRemote.mm; sourceTree = SOURCE_ROOT; }; 8484E9A7103C9595008B7C6C /* juce_mac_AudioCDBurner.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = juce_mac_AudioCDBurner.mm; path = ../../src/native/mac/juce_mac_AudioCDBurner.mm; sourceTree = SOURCE_ROOT; }; @@ -1425,7 +1425,6 @@ 84F1E90110403681006A1807 /* juce_Initialisation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = juce_Initialisation.h; path = ../../src/core/juce_Initialisation.h; sourceTree = SOURCE_ROOT; }; 84F1E90210403681006A1807 /* juce_FileLogger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = juce_FileLogger.h; path = ../../src/core/juce_FileLogger.h; sourceTree = SOURCE_ROOT; }; 84F1E90310403681006A1807 /* juce_FileLogger.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = juce_FileLogger.cpp; path = ../../src/core/juce_FileLogger.cpp; sourceTree = SOURCE_ROOT; }; - 84F1E90410403681006A1807 /* juce_DataConversions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = juce_DataConversions.h; path = ../../src/core/juce_DataConversions.h; sourceTree = SOURCE_ROOT; }; 84F1E90510403681006A1807 /* juce_Atomic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = juce_Atomic.h; path = ../../src/core/juce_Atomic.h; sourceTree = SOURCE_ROOT; }; 84F1E90610403681006A1807 /* juce_Uuid.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = juce_Uuid.cpp; path = ../../src/core/juce_Uuid.cpp; sourceTree = SOURCE_ROOT; }; 84F1E90710403681006A1807 /* juce_Uuid.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = juce_Uuid.h; path = ../../src/core/juce_Uuid.h; sourceTree = SOURCE_ROOT; }; @@ -2197,32 +2196,32 @@ 84F1E8F210403681006A1807 /* core */ = { isa = PBXGroup; children = ( - 84F1E8F310403681006A1807 /* juce_Time.h */, - 84F1E8F410403681006A1807 /* juce_Time.cpp */, - 84F1E8F510403681006A1807 /* juce_SystemStats.cpp */, - 84F1E8F610403681006A1807 /* juce_SystemStats.h */, - 84F1E8F710403681006A1807 /* juce_Singleton.h */, - 84F1E8F810403681006A1807 /* juce_RelativeTime.cpp */, - 84F1E8F910403681006A1807 /* juce_RelativeTime.h */, - 84F1E8FA10403681006A1807 /* juce_PlatformDefs.h */, - 84F1E8FB10403681006A1807 /* juce_Random.cpp */, - 84F1E8FC10403681006A1807 /* juce_Random.h */, + 84F1E90510403681006A1807 /* juce_Atomic.h */, + 848432C210F933B800490977 /* juce_ByteOrder.h */, + 84F1E90310403681006A1807 /* juce_FileLogger.cpp */, + 84F1E90210403681006A1807 /* juce_FileLogger.h */, + 84F1E90110403681006A1807 /* juce_Initialisation.h */, + 84F1E90010403681006A1807 /* juce_Logger.cpp */, + 84F1E8FF10403681006A1807 /* juce_Logger.h */, 84F1E8FD10403681006A1807 /* juce_MathsFunctions.h */, 84F1E8FE10403681006A1807 /* juce_Memory.h */, - 84F1E8FF10403681006A1807 /* juce_Logger.h */, - 84F1E90010403681006A1807 /* juce_Logger.cpp */, - 84F1E90110403681006A1807 /* juce_Initialisation.h */, - 84F1E90210403681006A1807 /* juce_FileLogger.h */, - 84F1E90310403681006A1807 /* juce_FileLogger.cpp */, - 84F1E90410403681006A1807 /* juce_DataConversions.h */, - 84F1E90510403681006A1807 /* juce_Atomic.h */, - 84F1E90610403681006A1807 /* juce_Uuid.cpp */, - 84F1E90710403681006A1807 /* juce_Uuid.h */, 84F1E90810403681006A1807 /* juce_PerformanceCounter.cpp */, 84F1E90910403681006A1807 /* juce_PerformanceCounter.h */, + 84F1E8FA10403681006A1807 /* juce_PlatformDefs.h */, 84F1E90A10403681006A1807 /* juce_PlatformUtilities.h */, + 84F1E8FB10403681006A1807 /* juce_Random.cpp */, + 84F1E8FC10403681006A1807 /* juce_Random.h */, + 84F1E8F810403681006A1807 /* juce_RelativeTime.cpp */, + 84F1E8F910403681006A1807 /* juce_RelativeTime.h */, + 84F1E8F710403681006A1807 /* juce_Singleton.h */, + 84F1E8F510403681006A1807 /* juce_SystemStats.cpp */, + 84F1E8F610403681006A1807 /* juce_SystemStats.h */, 84F1E90B10403681006A1807 /* juce_StandardHeader.h */, 8481730E10832513008FEC33 /* juce_TargetPlatform.h */, + 84F1E8F410403681006A1807 /* juce_Time.cpp */, + 84F1E8F310403681006A1807 /* juce_Time.h */, + 84F1E90610403681006A1807 /* juce_Uuid.cpp */, + 84F1E90710403681006A1807 /* juce_Uuid.h */, ); name = core; path = ../../src/core; @@ -2983,7 +2982,6 @@ 84816EAA10809DCB008FEC33 /* juce_ComponentMovementWatcher.h in Headers */, 84816EAB10809DCB008FEC33 /* juce_ComponentPeer.h in Headers */, 84816EAC10809DCB008FEC33 /* juce_CriticalSection.h in Headers */, - 84816EAD10809DCB008FEC33 /* juce_DataConversions.h in Headers */, 84816EAE10809DCB008FEC33 /* juce_DeletedAtShutdown.h in Headers */, 84816EAF10809DCB008FEC33 /* juce_Desktop.h in Headers */, 84816EB010809DCB008FEC33 /* juce_DialogWindow.h in Headers */, @@ -3324,7 +3322,6 @@ 84F1E91810403681006A1807 /* juce_Logger.h in Headers */, 84F1E91A10403681006A1807 /* juce_Initialisation.h in Headers */, 84F1E91B10403681006A1807 /* juce_FileLogger.h in Headers */, - 84F1E91D10403681006A1807 /* juce_DataConversions.h in Headers */, 84F1E91E10403681006A1807 /* juce_Atomic.h in Headers */, 84F1E92010403681006A1807 /* juce_Uuid.h in Headers */, 84F1E92210403681006A1807 /* juce_PerformanceCounter.h in Headers */, @@ -3552,6 +3549,7 @@ 84DEDD9F10EE496500909D01 /* juce_HeapBlock.h in Headers */, 84AF3FE810EF9FF30035D74F /* juce_ScopedPointer.h in Headers */, 84BA604110F2017A001D9D70 /* juce_Value.h in Headers */, + 848432C310F933B800490977 /* juce_ByteOrder.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/build/win32/vc8/JUCE.vcproj b/build/win32/vc8/JUCE.vcproj index ab982dcc58..b05a0b490d 100644 --- a/build/win32/vc8/JUCE.vcproj +++ b/build/win32/vc8/JUCE.vcproj @@ -962,7 +962,7 @@ > getParentWidth()) - dx = -fabsf (dx); - - if (y < 0) - dy = fabsf (dy); - - if (y > getParentHeight()) - dy = -fabsf (dy); - - setTopLeftPosition ((int) x, (int) y); - } - - bool hitTest (int x, int y) - { - return false; - } -}; - -//============================================================================== -class DragOntoDesktopDemoComp : public Component -{ - Component* parent; - ComponentDragger dragger; - -public: - DragOntoDesktopDemoComp (Component* p) - : parent (p) - { - // show off semi-transparency if it's supported by the current OS. - setOpaque (! Desktop::canUseSemiTransparentWindows()); - - for (int i = 3; --i >= 0;) - addAndMakeVisible (new BouncingBallComponent()); - } - - ~DragOntoDesktopDemoComp() - { - deleteAllChildren(); - } - - void mouseDown (const MouseEvent& e) - { - dragger.startDraggingComponent (this, 0); - } - - void mouseDrag (const MouseEvent& e) - { - if (! parent->isValidComponent()) - { - delete this; - } - else - { - MouseEvent e2 (e.getEventRelativeTo (parent)); - - // if the mouse is inside the parent component, we'll make that the - // parent - otherwise, we'll put this comp on the desktop. - if (e2.x >= 0 && e2.y >= 0 && e2.x < parent->getWidth() && e2.y < parent->getHeight()) - { - // re-add this component to a parent component, which will - // remove it from the desktop.. - parent->addChildComponent (this); - } - else - { - // add the component to the desktop, which will remove it - // from its current parent component.. - addToDesktop (ComponentPeer::windowIsTemporary); - } - - dragger.dragComponent (this, e); - } - } - - void paint (Graphics& g) - { - if (isOpaque()) - g.fillAll (Colours::white); - else - g.fillAll (Colours::blue.withAlpha (0.2f)); - - String desc (T("drag this box onto the desktop to show how the same component can move from being lightweight to being a separate window")); - - g.setFont (15.0f); - g.setColour (Colours::black); - g.drawFittedText (desc, 4, 0, getWidth() - 8, getHeight(), Justification::horizontallyJustified, 5); - - g.drawRect (0, 0, getWidth(), getHeight()); - } -}; - -//============================================================================== -class CustomMenuComponent : public PopupMenuCustomComponent, - public Timer -{ - int blobX, blobY; - -public: - CustomMenuComponent() - : blobX (0), - blobY (0) - { - // set off a timer to move a blob around on this component every - // 300 milliseconds - see the timerCallback() method. - startTimer (300); - } - - ~CustomMenuComponent() - { - } - - void getIdealSize (int& idealWidth, - int& idealHeight) - { - // tells the menu how big we'd like to be.. - idealWidth = 200; - idealHeight = 60; - } - - void paint (Graphics& g) - { - g.fillAll (Colours::yellow.withAlpha (0.3f)); - - g.setColour (Colours::pink); - g.fillEllipse ((float) blobX, (float) blobY, 30.0f, 40.0f); - - g.setFont (14.0f, Font::italic); - g.setColour (Colours::black); - - g.drawFittedText (T("this is a customised menu item (also demonstrating the Timer class)..."), - 4, 0, getWidth() - 8, getHeight(), - Justification::centred, 3); - } - - void timerCallback() - { - blobX = Random::getSystemRandom().nextInt (getWidth()); - blobY = Random::getSystemRandom().nextInt (getHeight()); - repaint(); - } -}; - -//============================================================================== -/** To demonstrate how sliders can have custom snapping applied to their values, - this simple class snaps the value to 50 if it comes near. -*/ -class SnappingSlider : public Slider -{ -public: - SnappingSlider (const String& name) - : Slider (name) - { - } - - double snapValue (double attemptedValue, const bool userIsDragging) - { - if (! userIsDragging) - return attemptedValue; // if they're entering the value in the text-box, don't mess with it. - - if (attemptedValue > 40 && attemptedValue < 60) - return 50.0; - else - return attemptedValue; - } -}; - -/** A TextButton that pops up a colour chooser to change its colours. */ -class ColourChangeButton : public TextButton, - public ChangeListener -{ -public: - ColourChangeButton() - : TextButton (T("click to change colour...")) - { - setSize (10, 24); - changeWidthToFitText(); - } - - ~ColourChangeButton() - { - } - - void clicked() - { - // create two colour selector components for our background and - // text colour.. - ColourSelector colourSelector1; - colourSelector1.setName (T("background")); - colourSelector1.setCurrentColour (findColour (TextButton::buttonColourId)); - colourSelector1.addChangeListener (this); - - ColourSelector colourSelector2; - colourSelector2.setName (T("text")); - colourSelector2.setCurrentColour (findColour (TextButton::textColourOffId)); - colourSelector2.addChangeListener (this); - - // and add the selectors as custom menu items to a PopupMenu, putting - // them in two different sub-menus.. - PopupMenu m, sub1, sub2; - - sub1.addCustomItem (1234, &colourSelector1, 300, 300, false); - m.addSubMenu (T("background colour"), sub1); - - sub2.addCustomItem (1234, &colourSelector2, 300, 300, false); - m.addSubMenu (T("text colour"), sub2); - - // and show the menu (modally).. - m.showAt (this); - } - - void changeListenerCallback (void* source) - { - ColourSelector* cs = (ColourSelector*) source; - - if (cs->getName() == T("text")) - setColour (TextButton::textColourOffId, cs->getCurrentColour()); - else - setColour (TextButton::buttonColourId, cs->getCurrentColour()); - } -}; - -//============================================================================== -// just a component that deletes all its children, to use for the tabbed pages to avoid -// memory leaks when they're deleted -class DemoPageComp : public Component -{ -public: - DemoPageComp() - { - } - - ~DemoPageComp() - { - deleteAllChildren(); - } -}; - -//============================================================================== -static Component* createSlidersPage() -{ - DemoPageComp* page = new DemoPageComp(); - - const int numSliders = 11; - Slider* sliders [numSliders]; - - int i; - for (i = 0; i < numSliders; ++i) - { - if (i == 2) - page->addAndMakeVisible (sliders[i] = new SnappingSlider (T("slider"))); - else - page->addAndMakeVisible (sliders[i] = new Slider (T("slider"))); - - sliders[i]->setRange (0.0, 100.0, 0.1); - sliders[i]->setPopupMenuEnabled (true); - sliders[i]->setValue (Random::getSystemRandom().nextDouble() * 100.0, false, false); - } - - sliders[0]->setSliderStyle (Slider::LinearVertical); - sliders[0]->setTextBoxStyle (Slider::TextBoxBelow, false, 100, 20); - sliders[0]->setBounds (10, 25, 70, 200); - sliders[0]->setDoubleClickReturnValue (true, 50.0); // double-clicking this slider will set it to 50.0 - sliders[0]->setTextValueSuffix (T(" units")); - - sliders[1]->setSliderStyle (Slider::LinearVertical); - sliders[1]->setVelocityBasedMode (true); - sliders[1]->setSkewFactor (0.5); - sliders[1]->setTextBoxStyle (Slider::TextBoxAbove, true, 100, 20); - sliders[1]->setBounds (85, 25, 70, 200); - sliders[1]->setTextValueSuffix (T(" rels")); - - sliders[2]->setSliderStyle (Slider::LinearHorizontal); - sliders[2]->setTextBoxStyle (Slider::TextBoxLeft, false, 80, 20); - sliders[2]->setBounds (180, 35, 150, 20); - - sliders[3]->setSliderStyle (Slider::LinearHorizontal); - sliders[3]->setTextBoxStyle (Slider::NoTextBox, false, 0, 0); - sliders[3]->setBounds (180, 65, 150, 20); - sliders[3]->setPopupDisplayEnabled (true, page); - sliders[3]->setTextValueSuffix (T(" nuns required to change a lightbulb")); - - sliders[4]->setSliderStyle (Slider::IncDecButtons); - sliders[4]->setTextBoxStyle (Slider::TextBoxLeft, false, 50, 20); - sliders[4]->setBounds (180, 105, 100, 20); - sliders[4]->setIncDecButtonsMode (Slider::incDecButtonsDraggable_Vertical); - - sliders[5]->setSliderStyle (Slider::Rotary); - sliders[5]->setRotaryParameters (float_Pi * 1.2f, float_Pi * 2.8f, false); - sliders[5]->setTextBoxStyle (Slider::TextBoxRight, false, 70, 20); - sliders[5]->setBounds (190, 145, 120, 40); - sliders[5]->setTextValueSuffix (T(" mm")); - - sliders[6]->setSliderStyle (Slider::LinearBar); - sliders[6]->setBounds (180, 195, 100, 30); - sliders[6]->setTextValueSuffix (T(" gallons")); - - sliders[7]->setSliderStyle (Slider::TwoValueHorizontal); - sliders[7]->setBounds (360, 20, 160, 40); - - sliders[8]->setSliderStyle (Slider::TwoValueVertical); - sliders[8]->setBounds (360, 110, 40, 160); - - sliders[9]->setSliderStyle (Slider::ThreeValueHorizontal); - sliders[9]->setBounds (360, 70, 160, 40); - - sliders[10]->setSliderStyle (Slider::ThreeValueVertical); - sliders[10]->setBounds (440, 110, 40, 160); - - for (i = 7; i <= 10; ++i) - { - sliders[i]->setTextBoxStyle (Slider::NoTextBox, false, 0, 0); - sliders[i]->setPopupDisplayEnabled (true, page); - } - - /* Here, we'll create a Value object, and tell a bunch of our sliders to use it as their - value source. By telling them all to share the same Value, they'll stay in sync with - each other. - - We could also optionally keep a copy of this Value elsewhere, and by changing it, - cause all the sliders to automatically update. - */ - Value sharedValue; - sharedValue = Random::getSystemRandom().nextDouble() * 100; - for (i = 0; i < 7; ++i) - sliders[i]->getValueObject().referTo (sharedValue); - - // ..and now we'll do the same for all our min/max slider values.. - Value sharedValueMin, sharedValueMax; - sharedValueMin = Random::getSystemRandom().nextDouble() * 60.0; - sharedValueMax = Random::getSystemRandom().nextDouble() * 60.0 + 40.0; - for (i = 7; i <= 10; ++i) - { - sliders[i]->getMinValueObject().referTo (sharedValueMin); - sliders[i]->getMaxValueObject().referTo (sharedValueMax); - } - - // Create a description label... - Label* label = new Label (T("hint"), T("Try right-clicking on a slider for an options menu. \n\nAlso, holding down CTRL while dragging will turn on a slider's velocity-sensitive mode")); - label->setBounds (20, 245, 350, 150); - page->addAndMakeVisible (label); - - return page; -} - -//============================================================================== -static Component* createRadioButtonPage() -{ - DemoPageComp* page = new DemoPageComp(); - - GroupComponent* group = new GroupComponent (T("group"), T("radio buttons")); - group->setBounds (20, 20, 220, 140); - page->addAndMakeVisible (group); - - int i; - for (i = 0; i < 4; ++i) - { - ToggleButton* tb = new ToggleButton (T("radio button #") + String (i + 1)); - page->addAndMakeVisible (tb); - tb->setRadioGroupId (1234); - tb->setBounds (45, 46 + i * 22, 180, 22); - tb->setTooltip (T("a set of mutually-exclusive radio buttons")); - - if (i == 0) - tb->setToggleState (true, false); - } - - for (i = 0; i < 4; ++i) - { - DrawablePath normal, over; - - Path p; - p.addStar (0.0f, 0.0f, i + 5, 20.0f, 50.0f, -0.2f); - normal.setPath (p); - normal.setFill (Colours::lightblue); - normal.setStrokeFill (Colours::black); - normal.setStrokeThickness (4.0f); - - over.setPath (p); - over.setFill (Colours::blue); - over.setStrokeFill (Colours::black); - over.setStrokeThickness (4.0f); - - DrawableButton* db = new DrawableButton (String (i + 5) + T(" points"), DrawableButton::ImageAboveTextLabel); - db->setImages (&normal, &over, 0); - - page->addAndMakeVisible (db); - db->setClickingTogglesState (true); - db->setRadioGroupId (23456); - - const int buttonSize = 50; - db->setBounds (25 + i * buttonSize, 180, buttonSize, buttonSize); - - if (i == 0) - db->setToggleState (true, false); - } - - for (i = 0; i < 4; ++i) - { - TextButton* tb = new TextButton (T("button ") + String (i + 1)); - - page->addAndMakeVisible (tb); - tb->setClickingTogglesState (true); - tb->setRadioGroupId (34567); - tb->setColour (TextButton::buttonColourId, Colours::white); - tb->setColour (TextButton::buttonOnColourId, Colours::blueviolet.brighter()); - - tb->setBounds (20 + i * 55, 260, 55, 24); - tb->setConnectedEdges (((i != 0) ? Button::ConnectedOnLeft : 0) - | ((i != 3) ? Button::ConnectedOnRight : 0)); - - if (i == 0) - tb->setToggleState (true, false); - } - - return page; -} - -//============================================================================== -class ButtonsPage : public Component, - public ButtonListener -{ -public: - ButtonsPage (ButtonListener* buttonListener) - { - //============================================================================== - // create some drawables to use for our drawable buttons... - DrawablePath normal, over; - - Path p; - p.addStar (0.0f, 0.0f, 5, 20.0f, 50.0f, 0.2f); - normal.setPath (p); - normal.setFill (Colours::red); - - p.clear(); - p.addStar (0.0f, 0.0f, 7, 30.0f, 50.0f, 0.0f); - over.setPath (p); - over.setFill (Colours::pink); - over.setStrokeFill (Colours::black); - over.setStrokeThickness (5.0f); - - DrawableImage down; - down.setImage (ImageCache::getFromMemory (BinaryData::juce_png, BinaryData::juce_pngSize), true); - down.setOverlayColour (Colours::black.withAlpha (0.3f)); - - //============================================================================== - // create an image-above-text button from these drawables.. - DrawableButton* db = new DrawableButton (T("Button 1"), DrawableButton::ImageAboveTextLabel); - db->setImages (&normal, &over, &down); - - addAndMakeVisible (db); - db->setBounds (10, 30, 80, 80); - db->setTooltip (T("this is a DrawableButton with a label")); - - //============================================================================== - // create an image-only button from these drawables.. - db = new DrawableButton (T("Button 2"), DrawableButton::ImageFitted); - db->setImages (&normal, &over, &down); - db->setClickingTogglesState (true); - - addAndMakeVisible (db); - db->setBounds (90, 30, 80, 80); - db->setTooltip (T("this is an image-only DrawableButton")); - db->addButtonListener (buttonListener); - - //============================================================================== - // create an image-on-button-shape button from the same drawables.. - db = new DrawableButton (T("Button 3"), DrawableButton::ImageOnButtonBackground); - db->setImages (&normal, 0, 0); - - addAndMakeVisible (db); - db->setBounds (200, 30, 110, 25); - db->setTooltip (T("this is a DrawableButton on a standard button background")); - - //============================================================================== - db = new DrawableButton (T("Button 4"), DrawableButton::ImageOnButtonBackground); - db->setImages (&normal, &over, &down); - db->setClickingTogglesState (true); - db->setBackgroundColours (Colours::white, Colours::yellow); - - addAndMakeVisible (db); - db->setBounds (200, 70, 50, 50); - db->setTooltip (T("this is a DrawableButton on a standard button background")); - db->addButtonListener (buttonListener); - - //============================================================================== - HyperlinkButton* hyperlink - = new HyperlinkButton (T("this is a HyperlinkButton"), - URL (T("http://www.rawmaterialsoftware.com/juce"))); - - hyperlink->setBounds (10, 130, 200, 24); - addAndMakeVisible (hyperlink); - - //============================================================================== - ImageButton* imageButton = new ImageButton (T("imagebutton")); - addAndMakeVisible (imageButton); - - Image* juceImage = ImageCache::getFromMemory (BinaryData::juce_png, BinaryData::juce_pngSize); - ImageCache::incReferenceCount (juceImage); - ImageCache::incReferenceCount (juceImage); - - imageButton->setImages (true, true, true, - juceImage, 0.7f, Colours::transparentBlack, - juceImage, 1.0f, Colours::transparentBlack, - juceImage, 1.0f, Colours::pink.withAlpha (0.8f), - 0.5f); - - imageButton->setTopLeftPosition (10, 160); - imageButton->setTooltip (T("image button - showing alpha-channel hit-testing and colour overlay when clicked")); - - //============================================================================== - ColourChangeButton* colourChangeButton = new ColourChangeButton(); - addAndMakeVisible (colourChangeButton); - colourChangeButton->setTopLeftPosition (350, 30); - - //============================================================================== - animateButton = new TextButton (T("click to animate...")); - addAndMakeVisible (animateButton); - animateButton->changeWidthToFitText (24); - animateButton->setTopLeftPosition (350, 70); - animateButton->addButtonListener (this); - } - - ~ButtonsPage() - { - deleteAllChildren(); - } - - void buttonClicked (Button*) - { - for (int i = getNumChildComponents(); --i >= 0;) - { - if (getChildComponent (i) != animateButton) - { - animator.animateComponent (getChildComponent (i), - Rectangle (Random::getSystemRandom().nextInt (getWidth() / 2), - Random::getSystemRandom().nextInt (getHeight() / 2), - 60 + Random::getSystemRandom().nextInt (getWidth() / 3), - 16 + Random::getSystemRandom().nextInt (getHeight() / 6)), - 500 + Random::getSystemRandom().nextInt (2000), - Random::getSystemRandom().nextDouble(), - Random::getSystemRandom().nextDouble()); - } - } - } - -private: - TextButton* animateButton; - ComponentAnimator animator; -}; - - -//============================================================================== -static Component* createMiscPage() -{ - DemoPageComp* page = new DemoPageComp(); - - TextEditor* textEditor = new TextEditor(); - page->addAndMakeVisible (textEditor); - textEditor->setBounds (10, 25, 200, 24); - textEditor->setText (T("single-line text box")); - - textEditor = new TextEditor (T("password"), (tchar) 0x2022); - page->addAndMakeVisible (textEditor); - textEditor->setBounds (10, 55, 200, 24); - textEditor->setText (T("password")); - - //============================================================================== - ComboBox* comboBox = new ComboBox (T("combo")); - page->addAndMakeVisible (comboBox); - comboBox->setBounds (300, 25, 200, 24); - comboBox->setEditableText (true); - comboBox->setJustificationType (Justification::centred); - - int i; - for (i = 1; i < 100; ++i) - comboBox->addItem (T("combo box item ") + String (i), i); - - comboBox->setSelectedId (1); - - DragOntoDesktopDemoComp* d = new DragOntoDesktopDemoComp (page); - page->addAndMakeVisible (d); - d->setBounds (20, 100, 200, 80); - - return page; -} - -//============================================================================== -class ToolbarDemoComp : public Component, - public SliderListener, - public ButtonListener -{ -public: - ToolbarDemoComp (ApplicationCommandManager* commandManager) - { - // Create and add the toolbar... - addAndMakeVisible (toolbar = new Toolbar()); - - // And use our item factory to add a set of default icons to it... - toolbar->addDefaultItems (factory); - - // Now we'll just create the other sliders and buttons on the demo page, which adjust - // the toolbar's properties... - Label* info = new Label (String::empty, - "As well as showing off toolbars, this demo illustrates how to store " - "a set of SVG files in a Zip file, embed that in your application, and read " - "them back in at runtime.\n\nThe icon images here are taken from the open-source " - "Tango icon project."); - - addAndMakeVisible (info); - info->setJustificationType (Justification::topLeft); - info->setBounds (80, 80, 450, 100); - info->setInterceptsMouseClicks (false, false); - - addAndMakeVisible (depthSlider = new Slider (T("toolbar depth:"))); - depthSlider->setRange (10.0, 200.0, 1.0); - depthSlider->setValue (50, false); - depthSlider->setSliderStyle (Slider::LinearHorizontal); - depthSlider->setTextBoxStyle (Slider::TextBoxLeft, false, 80, 20); - depthSlider->addListener (this); - depthSlider->setBounds (80, 210, 300, 22); - (new Label (depthSlider->getName(), depthSlider->getName()))->attachToComponent (depthSlider, false); - - addAndMakeVisible (orientationButton = new TextButton (T("vertical/horizontal"))); - orientationButton->addButtonListener (this); - orientationButton->changeWidthToFitText (22); - orientationButton->setTopLeftPosition (depthSlider->getX(), depthSlider->getBottom() + 20); - - addAndMakeVisible (customiseButton = new TextButton (T("customise..."))); - customiseButton->addButtonListener (this); - customiseButton->changeWidthToFitText (22); - customiseButton->setTopLeftPosition (orientationButton->getRight() + 20, orientationButton->getY()); - } - - ~ToolbarDemoComp() - { - deleteAllChildren(); - } - - void resized() - { - if (toolbar->isVertical()) - toolbar->setBounds (0, 0, (int) depthSlider->getValue(), getHeight()); - else - toolbar->setBounds (0, 0, getWidth(), (int) depthSlider->getValue()); - } - - void sliderValueChanged (Slider* slider) - { - resized(); - } - - void buttonClicked (Button* button) - { - if (button == orientationButton) - { - toolbar->setVertical (! toolbar->isVertical()); - resized(); - } - else if (button == customiseButton) - { - toolbar->showCustomisationDialog (factory); - } - } - -private: - Toolbar* toolbar; - Slider* depthSlider; - TextButton* orientationButton; - TextButton* customiseButton; - - //============================================================================== - class DemoToolbarItemFactory : public ToolbarItemFactory - { - public: - DemoToolbarItemFactory() {} - ~DemoToolbarItemFactory() {} - - //============================================================================== - // Each type of item a toolbar can contain must be given a unique ID. These - // are the ones we'll use in this demo. - enum DemoToolbarItemIds - { - doc_new = 1, - doc_open = 2, - doc_save = 3, - doc_saveAs = 4, - edit_copy = 5, - edit_cut = 6, - edit_paste = 7, - juceLogoButton = 8, - customComboBox = 9 - }; - - void getAllToolbarItemIds (Array & ids) - { - // This returns the complete list of all item IDs that are allowed to - // go in our toolbar. Any items you might want to add must be listed here. The - // order in which they are listed will be used by the toolbar customisation panel. - - ids.add (doc_new); - ids.add (doc_open); - ids.add (doc_save); - ids.add (doc_saveAs); - ids.add (edit_copy); - ids.add (edit_cut); - ids.add (edit_paste); - ids.add (juceLogoButton); - ids.add (customComboBox); - - // If you're going to use separators, then they must also be added explicitly - // to the list. - ids.add (separatorBarId); - ids.add (spacerId); - ids.add (flexibleSpacerId); - } - - void getDefaultItemSet (Array & ids) - { - // This returns an ordered list of the set of items that make up a - // toolbar's default set. Not all items need to be on this list, and - // items can appear multiple times (e.g. the separators used here). - ids.add (doc_new); - ids.add (doc_open); - ids.add (doc_save); - ids.add (doc_saveAs); - ids.add (spacerId); - ids.add (separatorBarId); - ids.add (edit_copy); - ids.add (edit_cut); - ids.add (edit_paste); - ids.add (separatorBarId); - ids.add (flexibleSpacerId); - ids.add (customComboBox); - ids.add (flexibleSpacerId); - ids.add (separatorBarId); - ids.add (juceLogoButton); - } - - ToolbarItemComponent* createItem (const int itemId) - { - switch (itemId) - { - case doc_new: - return createButtonFromZipFileSVG (itemId, T("new"), T("document-new.svg")); - - case doc_open: - return createButtonFromZipFileSVG (itemId, T("open"), T("document-open.svg")); - - case doc_save: - return createButtonFromZipFileSVG (itemId, T("save"), T("document-save.svg")); - - case doc_saveAs: - return createButtonFromZipFileSVG (itemId, T("save as"), T("document-save-as.svg")); - - case edit_copy: - return createButtonFromZipFileSVG (itemId, T("copy"), T("edit-copy.svg")); - - case edit_cut: - return createButtonFromZipFileSVG (itemId, T("cut"), T("edit-cut.svg")); - - case edit_paste: - return createButtonFromZipFileSVG (itemId, T("paste"), T("edit-paste.svg")); - - case juceLogoButton: - return new ToolbarButton (itemId, T("juce!"), Drawable::createFromImageData (BinaryData::juce_png, BinaryData::juce_pngSize), 0); - - case customComboBox: - return new CustomToolbarComboBox (itemId); - - default: - break; - } - - return 0; - } - - private: - StringArray iconNames; - OwnedArray iconsFromZipFile; - - // This is a little utility to create a button with one of the SVG images in - // our embedded ZIP file "icons.zip" - ToolbarButton* createButtonFromZipFileSVG (const int itemId, const String& text, const String& filename) - { - if (iconsFromZipFile.size() == 0) - { - // If we've not already done so, load all the images from the zip file.. - MemoryInputStream iconsFileStream (BinaryData::icons_zip, BinaryData::icons_zipSize, false); - ZipFile icons (&iconsFileStream, false); - - for (int i = 0; i < icons.getNumEntries(); ++i) - { - InputStream* svgFileStream = icons.createStreamForEntry (i); - - if (svgFileStream != 0) - { - iconNames.add (icons.getEntry(i)->filename); - iconsFromZipFile.add (Drawable::createFromImageDataStream (*svgFileStream)); - - delete svgFileStream; - } - } - } - - Drawable* image = iconsFromZipFile [iconNames.indexOf (filename)]->createCopy(); - return new ToolbarButton (itemId, text, image, 0); - - return 0; - } - - // Demonstrates how to put a custom component into a toolbar - this one contains - // a ComboBox. - class CustomToolbarComboBox : public ToolbarItemComponent - { - public: - CustomToolbarComboBox (const int toolbarItemId) - : ToolbarItemComponent (toolbarItemId, T("Custom Toolbar Item"), false) - { - addAndMakeVisible (comboBox = new ComboBox (T("demo toolbar combo box"))); - - for (int i = 1; i < 20; ++i) - comboBox->addItem (T("Toolbar ComboBox item ") + String (i), i); - - comboBox->setSelectedId (1); - comboBox->setEditableText (true); - } - - ~CustomToolbarComboBox() - { - delete comboBox; - } - - bool getToolbarItemSizes (int toolbarDepth, - bool isToolbarVertical, - int& preferredSize, int& minSize, int& maxSize) - { - if (isToolbarVertical) - return false; - - preferredSize = 250; - minSize = 80; - maxSize = 300; - return true; - } - - void paintButtonArea (Graphics&, int, int, bool, bool) - { - } - - void contentAreaChanged (const Rectangle& contentArea) - { - comboBox->setSize (contentArea.getWidth() - 2, - jmin (contentArea.getHeight() - 2, 22)); - - comboBox->setCentrePosition (contentArea.getCentreX(), contentArea.getCentreY()); - } - - private: - ComboBox* comboBox; - }; - }; - - DemoToolbarItemFactory factory; -}; - -//============================================================================== -class DemoTabbedComponent : public TabbedComponent, - public ButtonListener -{ -public: - DemoTabbedComponent (ApplicationCommandManager* commandManager) - : TabbedComponent (TabbedButtonBar::TabsAtTop) - { - addTab (T("sliders"), getRandomBrightColour(), createSlidersPage(), true); - addTab (T("toolbars"), getRandomBrightColour(), new ToolbarDemoComp (commandManager), true); - addTab (T("buttons"), getRandomBrightColour(), new ButtonsPage (this), true); - addTab (T("radio buttons"), getRandomBrightColour(), createRadioButtonPage(), true); - addTab (T("misc widgets"), getRandomBrightColour(), createMiscPage(), true); - } - - ~DemoTabbedComponent() - { - } - - void buttonClicked (Button* button) - { - BubbleMessageComponent* bmc = new BubbleMessageComponent(); - - if (Desktop::canUseSemiTransparentWindows()) - { - bmc->setAlwaysOnTop (true); - bmc->addToDesktop (0); - } - else - { - addChildComponent (bmc); - } - - bmc->showAt (button, T("This is a demo of the BubbleMessageComponent, which lets you pop up a message pointing at a component or somewhere on the screen.\n\nThe message bubbles will disappear after a timeout period, or when the mouse is clicked."), - 2000, true, true); - } - - static const Colour getRandomBrightColour() - { - return Colour (Random::getSystemRandom().nextFloat(), 0.1f, 0.97f, 1.0f); - } -}; - - -//============================================================================== -class DemoBackgroundThread : public ThreadWithProgressWindow -{ -public: - DemoBackgroundThread() - : ThreadWithProgressWindow (T("busy doing some important things..."), - true, - true) - { - setStatusMessage (T("Getting ready...")); - } - - ~DemoBackgroundThread() - { - } - - void run() - { - setProgress (-1.0); // setting a value beyond the range 0 -> 1 will show a spinning bar.. - setStatusMessage (T("Preparing to do some stuff...")); - wait (2000); - - const int thingsToDo = 10; - - for (int i = 0; i < thingsToDo; ++i) - { - // must check this as often as possible, because this is - // how we know if the user's pressed 'cancel' - if (threadShouldExit()) - return; - - // this will update the progress bar on the dialog box - setProgress (i / (double) thingsToDo); - - setStatusMessage (String (thingsToDo - i) + T(" things left to do...")); - - wait (500); - } - - setProgress (-1.0); // setting a value beyond the range 0 -> 1 will show a spinning bar.. - setStatusMessage (T("Finishing off the last few bits and pieces!")); - wait (2000); - } -}; - -//============================================================================== -/** A DialogWindow containing a ColourSelector component */ -class ColourSelectorDialogWindow : public DialogWindow -{ -public: - ColourSelectorDialogWindow() - : DialogWindow (T("Colour selector demo"), - Colours::lightgrey, - true) - { - setContentComponent (new ColourSelector()); - centreWithSize (400, 400); - setResizable (true, true); - } - - ~ColourSelectorDialogWindow() - { - } - - void closeButtonPressed() - { - // we expect this component to be run within a modal loop, so when the close - // button is clicked, we can make it invisible to cause the loop to exit and the - // calling code will delete this object. - setVisible (false); - } -}; - -#if JUCE_MAC - -//============================================================================== -/** This pops open a dialog box and waits for you to press keys on your Apple Remote, - which it describes in the box. -*/ -class AppleRemoteTestWindow : public AlertWindow, - public AppleRemoteDevice -{ -public: - AppleRemoteTestWindow() - : AlertWindow ("Apple Remote Control Test!", - "If you've got an Apple Remote, press some buttons now...", - AlertWindow::NoIcon) - { - addButton (T("done"), 0); - - // (To open the device in non-exclusive mode, pass 'false' in here).. - if (! start (true)) - setMessage ("Couldn't open the remote control device!"); - } - - ~AppleRemoteTestWindow() - { - stop(); - } - - void buttonPressed (const ButtonType buttonId, const bool isDown) - { - String desc; - - switch (buttonId) - { - case menuButton: - desc = "menu button (short)"; - break; - case playButton: - desc = "play button"; - break; - case plusButton: - desc = "plus button"; - break; - case minusButton: - desc = "minus button"; - break; - case rightButton: - desc = "right button (short)"; - break; - case leftButton: - desc = "left button (short)"; - break; - case rightButton_Long: - desc = "right button (long)"; - break; - case leftButton_Long: - desc = "left button (long)"; - break; - case menuButton_Long: - desc = "menu button (long)"; - break; - case playButtonSleepMode: - desc = "play (sleep mode)"; - break; - case switched: - desc = "remote switched"; - break; - } - - if (isDown) - desc << " -- [down]"; - else - desc << " -- [up]"; - - setMessage (desc); - } -}; - -#endif - -//============================================================================== -const int numGroups = 4; - -class WidgetsDemo : public Component, - public ButtonListener -{ - TextButton* menuButton; - ToggleButton* enableButton; - - DemoTabbedComponent* tabs; - -public: - //============================================================================== - WidgetsDemo (ApplicationCommandManager* commandManager) - { - setName (T("Widgets")); - - addAndMakeVisible (tabs = new DemoTabbedComponent (commandManager)); - - //============================================================================== - menuButton = new TextButton (T("click for a popup menu.."), - T("click for a demo of the different types of item you can put into a popup menu...")); - - addAndMakeVisible (menuButton); - menuButton->setBounds (10, 10, 200, 24); - menuButton->addButtonListener (this); - menuButton->setTriggeredOnMouseDown (true); // because this button pops up a menu, this lets us - // hold down the button and drag straight onto the menu - - //============================================================================== - enableButton = new ToggleButton (T("enable/disable components")); - addAndMakeVisible (enableButton); - enableButton->setBounds (230, 10, 180, 24); - enableButton->setTooltip (T("toggle button")); - enableButton->setToggleState (true, false); - enableButton->addButtonListener (this); - } - - ~WidgetsDemo() - { - deleteAllChildren(); - } - - void resized() - { - tabs->setBounds (10, 40, getWidth() - 20, getHeight() - 50); - } - - //============================================================================== - void buttonClicked (Button* button) - { - if (button == enableButton) - { - const bool enabled = enableButton->getToggleState(); - - menuButton->setEnabled (enabled); - tabs->setEnabled (enabled); - } - else if (button == menuButton) - { - PopupMenu m; - m.addItem (1, T("Normal item")); - m.addItem (2, T("Disabled item"), false); - m.addItem (3, T("Ticked item"), true, true); - m.addColouredItem (4, T("Coloured item"), Colours::green); - m.addSeparator(); - m.addCustomItem (5, new CustomMenuComponent()); - - m.addSeparator(); - - PopupMenu tabsMenu; - tabsMenu.addItem (1001, T("Show tabs at the top"), true, tabs->getOrientation() == TabbedButtonBar::TabsAtTop); - tabsMenu.addItem (1002, T("Show tabs at the bottom"), true, tabs->getOrientation() == TabbedButtonBar::TabsAtBottom); - tabsMenu.addItem (1003, T("Show tabs at the left"), true, tabs->getOrientation() == TabbedButtonBar::TabsAtLeft); - tabsMenu.addItem (1004, T("Show tabs at the right"), true, tabs->getOrientation() == TabbedButtonBar::TabsAtRight); - m.addSubMenu (T("Tab position"), tabsMenu); - - m.addSeparator(); - - PopupMenu dialogMenu; - dialogMenu.addItem (100, T("Show a plain alert-window...")); - dialogMenu.addItem (101, T("Show an alert-window with a 'warning' icon...")); - dialogMenu.addItem (102, T("Show an alert-window with an 'info' icon...")); - dialogMenu.addItem (103, T("Show an alert-window with a 'question' icon...")); - - dialogMenu.addSeparator(); - - dialogMenu.addItem (110, T("Show an ok/cancel alert-window...")); - - dialogMenu.addSeparator(); - - dialogMenu.addItem (111, T("Show an alert-window with some extra components...")); - - dialogMenu.addSeparator(); - - dialogMenu.addItem (112, T("Show a ThreadWithProgressWindow demo...")); - - m.addSubMenu (T("AlertWindow demonstrations"), dialogMenu); - - m.addSeparator(); - - m.addItem (120, T("Show a colour selector demo...")); - m.addSeparator(); - -#if JUCE_MAC - m.addItem (140, T("Run the Apple Remote Control test...")); - m.addSeparator(); -#endif - - PopupMenu nativeFileChoosers; - nativeFileChoosers.addItem (121, T("'Load' file browser...")); - nativeFileChoosers.addItem (124, T("'Load' file browser with an image file preview...")); - nativeFileChoosers.addItem (122, T("'Save' file browser...")); - nativeFileChoosers.addItem (123, T("'Choose directory' file browser...")); - - PopupMenu juceFileChoosers; - juceFileChoosers.addItem (131, T("'Load' file browser...")); - juceFileChoosers.addItem (134, T("'Load' file browser with an image file preview...")); - juceFileChoosers.addItem (132, T("'Save' file browser...")); - juceFileChoosers.addItem (133, T("'Choose directory' file browser...")); - - PopupMenu fileChoosers; - fileChoosers.addSubMenu (T("Operating system dialogs"), nativeFileChoosers); - fileChoosers.addSubMenu (T("Juce dialogs"), juceFileChoosers); - - m.addSubMenu (T("File chooser dialogs"), fileChoosers); - - int result = m.showAt (menuButton); - - if (result != 0) - { - // user chose something from the menu.. - - if (result >= 100 && result < 105) - { - AlertWindow::AlertIconType icon = AlertWindow::NoIcon; - - if (result == 101) - icon = AlertWindow::WarningIcon; - else if (result == 102) - icon = AlertWindow::InfoIcon; - else if (result == 103) - icon = AlertWindow::QuestionIcon; - - AlertWindow::showMessageBox (icon, - T("This is an AlertWindow"), - T("And this is the AlertWindow's message. Blah blah blah blah blah blah blah blah blah blah blah blah blah."), - T("ok")); - } - else if (result == 110) - { - bool userPickedOk - = AlertWindow::showOkCancelBox (AlertWindow::QuestionIcon, - T("This is an ok/cancel AlertWindow"), - T("And this is the AlertWindow's message. Blah blah blah blah blah blah blah blah blah blah blah blah blah.")); - - (void) userPickedOk; // (just avoids a compiler warning about unused variables) - } - else if (result == 111) - { - AlertWindow w (T("AlertWindow demo.."), - T("This AlertWindow has a couple of extra components added to show how to add drop-down lists and text entry boxes."), - AlertWindow::QuestionIcon); - - w.addTextEditor (T("text"), T("enter some text here"), T("text field:")); - - StringArray options; - options.add (T("option 1")); - options.add (T("option 2")); - options.add (T("option 3")); - options.add (T("option 4")); - w.addComboBox (T("option"), options, T("some options")); - - w.addButton (T("ok"), 1, KeyPress (KeyPress::returnKey, 0, 0)); - w.addButton (T("cancel"), 0, KeyPress (KeyPress::escapeKey, 0, 0)); - - if (w.runModalLoop() != 0) // is they picked 'ok' - { - // this is the item they chose in the drop-down list.. - const int optionIndexChosen = w.getComboBoxComponent (T("option"))->getSelectedItemIndex(); - (void) optionIndexChosen; // (just avoids a compiler warning about unused variables) - - - // this is the text they entered.. - String text = w.getTextEditorContents (T("text")); - - } - } - else if (result == 112) - { - DemoBackgroundThread demoThread; - - if (demoThread.runThread()) - { - // thread finished normally.. - AlertWindow::showMessageBox (AlertWindow::WarningIcon, - T("Progress window"), - T("Thread finished ok!")); - } - else - { - // user pressed the cancel button.. - AlertWindow::showMessageBox (AlertWindow::WarningIcon, - T("Progress window"), - T("You pressed cancel!")); - } - - } - else if (result == 120) - { - ColourSelectorDialogWindow colourDialog; - - // this will run an event loop until the dialog's closeButtonPressed() - // method causes the loop to exit. - colourDialog.runModalLoop(); - } - else if (result == 140) - { -#if JUCE_MAC - AppleRemoteTestWindow test; - test.runModalLoop(); -#endif - } - else if (result >= 121 && result < 139) - { - const bool useNativeVersion = result < 130; - if (result > 130) - result -= 10; - - if (result == 121) - { - FileChooser fc (T("Choose a file to open..."), - File::getCurrentWorkingDirectory(), - T("*"), - useNativeVersion); - - if (fc.browseForFileToOpen()) - { - File chosenFile = fc.getResult(); - - AlertWindow::showMessageBox (AlertWindow::InfoIcon, - T("File Chooser..."), - T("You picked: ") + chosenFile.getFullPathName()); - } - } - else if (result == 124) - { - ImagePreviewComponent imagePreview; - imagePreview.setSize (200, 200); - - FileChooser fc (T("Choose an image to open..."), - File::getCurrentWorkingDirectory(), - T("*.jpg;*.jpeg;*.png;*.gif"), - useNativeVersion); - - if (fc.browseForFileToOpen (&imagePreview)) - { - File chosenFile = fc.getResult(); - - AlertWindow::showMessageBox (AlertWindow::InfoIcon, - T("File Chooser..."), - T("You picked: ") + chosenFile.getFullPathName()); - } - } - else if (result == 122) - { - FileChooser fc (T("Choose a file to save..."), - File::getCurrentWorkingDirectory(), - T("*"), - useNativeVersion); - - if (fc.browseForFileToSave (true)) - { - File chosenFile = fc.getResult(); - - AlertWindow::showMessageBox (AlertWindow::InfoIcon, - T("File Chooser..."), - T("You picked: ") + chosenFile.getFullPathName()); - } - } - else if (result == 123) - { - FileChooser fc (T("Choose a directory..."), - File::getCurrentWorkingDirectory(), - T("*"), - useNativeVersion); - - if (fc.browseForDirectory()) - { - File chosenDirectory = fc.getResult(); - - AlertWindow::showMessageBox (AlertWindow::InfoIcon, - T("File Chooser..."), - T("You picked: ") + chosenDirectory.getFullPathName()); - } - } - } - else if (result == 1001) - { - tabs->setOrientation (TabbedButtonBar::TabsAtTop); - } - else if (result == 1002) - { - tabs->setOrientation (TabbedButtonBar::TabsAtBottom); - } - else if (result == 1003) - { - tabs->setOrientation (TabbedButtonBar::TabsAtLeft); - } - else if (result == 1004) - { - tabs->setOrientation (TabbedButtonBar::TabsAtRight); - } - } - } - } -}; - - -//============================================================================== -Component* createWidgetsDemo (ApplicationCommandManager* commandManager) -{ - return new WidgetsDemo (commandManager); -} +/* + ============================================================================== + + This file is part of the JUCE library - "Jules' Utility Class Extensions" + Copyright 2004-9 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. + + ============================================================================== +*/ + +#include "../jucedemo_headers.h" + + +//============================================================================== +class BouncingBallComponent : public Component, + public Timer +{ + Colour colour; + float x, y, dx, dy; + +public: + BouncingBallComponent() + { + x = Random::getSystemRandom().nextFloat() * 100.0f; + y = Random::getSystemRandom().nextFloat() * 100.0f; + + dx = Random::getSystemRandom().nextFloat() * 8.0f - 4.0f; + dy = Random::getSystemRandom().nextFloat() * 8.0f - 4.0f; + + colour = Colour (Random::getSystemRandom().nextInt()) + .withAlpha (0.5f) + .withBrightness (0.7f); + + int size = 10 + Random::getSystemRandom().nextInt (30); + setSize (size, size); + + startTimer (60); + } + + ~BouncingBallComponent() + { + } + + void paint (Graphics& g) + { + g.setColour (colour); + g.fillEllipse (x - getX(), y - getY(), getWidth() - 2.0f, getHeight() - 2.0f); + } + + void timerCallback() + { + x += dx; + y += dy; + + if (x < 0) + dx = fabsf (dx); + + if (x > getParentWidth()) + dx = -fabsf (dx); + + if (y < 0) + dy = fabsf (dy); + + if (y > getParentHeight()) + dy = -fabsf (dy); + + setTopLeftPosition ((int) x, (int) y); + } + + bool hitTest (int x, int y) + { + return false; + } +}; + +//============================================================================== +class DragOntoDesktopDemoComp : public Component +{ + Component* parent; + ComponentDragger dragger; + +public: + DragOntoDesktopDemoComp (Component* p) + : parent (p) + { + // show off semi-transparency if it's supported by the current OS. + setOpaque (! Desktop::canUseSemiTransparentWindows()); + + for (int i = 3; --i >= 0;) + addAndMakeVisible (new BouncingBallComponent()); + } + + ~DragOntoDesktopDemoComp() + { + deleteAllChildren(); + } + + void mouseDown (const MouseEvent& e) + { + dragger.startDraggingComponent (this, 0); + } + + void mouseDrag (const MouseEvent& e) + { + if (! parent->isValidComponent()) + { + delete this; + } + else + { + MouseEvent e2 (e.getEventRelativeTo (parent)); + + // if the mouse is inside the parent component, we'll make that the + // parent - otherwise, we'll put this comp on the desktop. + if (e2.x >= 0 && e2.y >= 0 && e2.x < parent->getWidth() && e2.y < parent->getHeight()) + { + // re-add this component to a parent component, which will + // remove it from the desktop.. + parent->addChildComponent (this); + } + else + { + // add the component to the desktop, which will remove it + // from its current parent component.. + addToDesktop (ComponentPeer::windowIsTemporary); + } + + dragger.dragComponent (this, e); + } + } + + void paint (Graphics& g) + { + if (isOpaque()) + g.fillAll (Colours::white); + else + g.fillAll (Colours::blue.withAlpha (0.2f)); + + String desc (T("drag this box onto the desktop to show how the same component can move from being lightweight to being a separate window")); + + g.setFont (15.0f); + g.setColour (Colours::black); + g.drawFittedText (desc, 4, 0, getWidth() - 8, getHeight(), Justification::horizontallyJustified, 5); + + g.drawRect (0, 0, getWidth(), getHeight()); + } +}; + +//============================================================================== +class CustomMenuComponent : public PopupMenuCustomComponent, + public Timer +{ + int blobX, blobY; + +public: + CustomMenuComponent() + : blobX (0), + blobY (0) + { + // set off a timer to move a blob around on this component every + // 300 milliseconds - see the timerCallback() method. + startTimer (300); + } + + ~CustomMenuComponent() + { + } + + void getIdealSize (int& idealWidth, + int& idealHeight) + { + // tells the menu how big we'd like to be.. + idealWidth = 200; + idealHeight = 60; + } + + void paint (Graphics& g) + { + g.fillAll (Colours::yellow.withAlpha (0.3f)); + + g.setColour (Colours::pink); + g.fillEllipse ((float) blobX, (float) blobY, 30.0f, 40.0f); + + g.setFont (14.0f, Font::italic); + g.setColour (Colours::black); + + g.drawFittedText (T("this is a customised menu item (also demonstrating the Timer class)..."), + 4, 0, getWidth() - 8, getHeight(), + Justification::centred, 3); + } + + void timerCallback() + { + blobX = Random::getSystemRandom().nextInt (getWidth()); + blobY = Random::getSystemRandom().nextInt (getHeight()); + repaint(); + } +}; + +//============================================================================== +/** To demonstrate how sliders can have custom snapping applied to their values, + this simple class snaps the value to 50 if it comes near. +*/ +class SnappingSlider : public Slider +{ +public: + SnappingSlider (const String& name) + : Slider (name) + { + } + + double snapValue (double attemptedValue, const bool userIsDragging) + { + if (! userIsDragging) + return attemptedValue; // if they're entering the value in the text-box, don't mess with it. + + if (attemptedValue > 40 && attemptedValue < 60) + return 50.0; + else + return attemptedValue; + } +}; + +/** A TextButton that pops up a colour chooser to change its colours. */ +class ColourChangeButton : public TextButton, + public ChangeListener +{ +public: + ColourChangeButton() + : TextButton (T("click to change colour...")) + { + setSize (10, 24); + changeWidthToFitText(); + } + + ~ColourChangeButton() + { + } + + void clicked() + { + // create two colour selector components for our background and + // text colour.. + ColourSelector colourSelector1; + colourSelector1.setName (T("background")); + colourSelector1.setCurrentColour (findColour (TextButton::buttonColourId)); + colourSelector1.addChangeListener (this); + + ColourSelector colourSelector2; + colourSelector2.setName (T("text")); + colourSelector2.setCurrentColour (findColour (TextButton::textColourOffId)); + colourSelector2.addChangeListener (this); + + // and add the selectors as custom menu items to a PopupMenu, putting + // them in two different sub-menus.. + PopupMenu m, sub1, sub2; + + sub1.addCustomItem (1234, &colourSelector1, 300, 300, false); + m.addSubMenu (T("background colour"), sub1); + + sub2.addCustomItem (1234, &colourSelector2, 300, 300, false); + m.addSubMenu (T("text colour"), sub2); + + // and show the menu (modally).. + m.showAt (this); + } + + void changeListenerCallback (void* source) + { + ColourSelector* cs = (ColourSelector*) source; + + if (cs->getName() == T("text")) + setColour (TextButton::textColourOffId, cs->getCurrentColour()); + else + setColour (TextButton::buttonColourId, cs->getCurrentColour()); + } +}; + +//============================================================================== +// just a component that deletes all its children, to use for the tabbed pages to avoid +// memory leaks when they're deleted +class DemoPageComp : public Component +{ +public: + DemoPageComp() + { + } + + ~DemoPageComp() + { + deleteAllChildren(); + } +}; + +//============================================================================== +static Component* createSlidersPage() +{ + DemoPageComp* page = new DemoPageComp(); + + const int numSliders = 11; + Slider* sliders [numSliders]; + + int i; + for (i = 0; i < numSliders; ++i) + { + if (i == 2) + page->addAndMakeVisible (sliders[i] = new SnappingSlider (T("slider"))); + else + page->addAndMakeVisible (sliders[i] = new Slider (T("slider"))); + + sliders[i]->setRange (0.0, 100.0, 0.1); + sliders[i]->setPopupMenuEnabled (true); + sliders[i]->setValue (Random::getSystemRandom().nextDouble() * 100.0, false, false); + } + + sliders[0]->setSliderStyle (Slider::LinearVertical); + sliders[0]->setTextBoxStyle (Slider::TextBoxBelow, false, 100, 20); + sliders[0]->setBounds (10, 25, 70, 200); + sliders[0]->setDoubleClickReturnValue (true, 50.0); // double-clicking this slider will set it to 50.0 + sliders[0]->setTextValueSuffix (T(" units")); + + sliders[1]->setSliderStyle (Slider::LinearVertical); + sliders[1]->setVelocityBasedMode (true); + sliders[1]->setSkewFactor (0.5); + sliders[1]->setTextBoxStyle (Slider::TextBoxAbove, true, 100, 20); + sliders[1]->setBounds (85, 25, 70, 200); + sliders[1]->setTextValueSuffix (T(" rels")); + + sliders[2]->setSliderStyle (Slider::LinearHorizontal); + sliders[2]->setTextBoxStyle (Slider::TextBoxLeft, false, 80, 20); + sliders[2]->setBounds (180, 35, 150, 20); + + sliders[3]->setSliderStyle (Slider::LinearHorizontal); + sliders[3]->setTextBoxStyle (Slider::NoTextBox, false, 0, 0); + sliders[3]->setBounds (180, 65, 150, 20); + sliders[3]->setPopupDisplayEnabled (true, page); + sliders[3]->setTextValueSuffix (T(" nuns required to change a lightbulb")); + + sliders[4]->setSliderStyle (Slider::IncDecButtons); + sliders[4]->setTextBoxStyle (Slider::TextBoxLeft, false, 50, 20); + sliders[4]->setBounds (180, 105, 100, 20); + sliders[4]->setIncDecButtonsMode (Slider::incDecButtonsDraggable_Vertical); + + sliders[5]->setSliderStyle (Slider::Rotary); + sliders[5]->setRotaryParameters (float_Pi * 1.2f, float_Pi * 2.8f, false); + sliders[5]->setTextBoxStyle (Slider::TextBoxRight, false, 70, 20); + sliders[5]->setBounds (190, 145, 120, 40); + sliders[5]->setTextValueSuffix (T(" mm")); + + sliders[6]->setSliderStyle (Slider::LinearBar); + sliders[6]->setBounds (180, 195, 100, 30); + sliders[6]->setTextValueSuffix (T(" gallons")); + + sliders[7]->setSliderStyle (Slider::TwoValueHorizontal); + sliders[7]->setBounds (360, 20, 160, 40); + + sliders[8]->setSliderStyle (Slider::TwoValueVertical); + sliders[8]->setBounds (360, 110, 40, 160); + + sliders[9]->setSliderStyle (Slider::ThreeValueHorizontal); + sliders[9]->setBounds (360, 70, 160, 40); + + sliders[10]->setSliderStyle (Slider::ThreeValueVertical); + sliders[10]->setBounds (440, 110, 40, 160); + + for (i = 7; i <= 10; ++i) + { + sliders[i]->setTextBoxStyle (Slider::NoTextBox, false, 0, 0); + sliders[i]->setPopupDisplayEnabled (true, page); + } + + /* Here, we'll create a Value object, and tell a bunch of our sliders to use it as their + value source. By telling them all to share the same Value, they'll stay in sync with + each other. + + We could also optionally keep a copy of this Value elsewhere, and by changing it, + cause all the sliders to automatically update. + */ + Value sharedValue; + sharedValue = Random::getSystemRandom().nextDouble() * 100; + for (i = 0; i < 7; ++i) + sliders[i]->getValueObject().referTo (sharedValue); + + // ..and now we'll do the same for all our min/max slider values.. + Value sharedValueMin, sharedValueMax; + sharedValueMin = Random::getSystemRandom().nextDouble() * 40.0; + sharedValueMax = Random::getSystemRandom().nextDouble() * 40.0 + 60.0; + + for (i = 7; i <= 10; ++i) + { + sliders[i]->getMaxValueObject().referTo (sharedValueMax); + sliders[i]->getMinValueObject().referTo (sharedValueMin); + } + + // Create a description label... + Label* label = new Label (T("hint"), T("Try right-clicking on a slider for an options menu. \n\nAlso, holding down CTRL while dragging will turn on a slider's velocity-sensitive mode")); + label->setBounds (20, 245, 350, 150); + page->addAndMakeVisible (label); + + return page; +} + +//============================================================================== +static Component* createRadioButtonPage() +{ + DemoPageComp* page = new DemoPageComp(); + + GroupComponent* group = new GroupComponent (T("group"), T("radio buttons")); + group->setBounds (20, 20, 220, 140); + page->addAndMakeVisible (group); + + int i; + for (i = 0; i < 4; ++i) + { + ToggleButton* tb = new ToggleButton (T("radio button #") + String (i + 1)); + page->addAndMakeVisible (tb); + tb->setRadioGroupId (1234); + tb->setBounds (45, 46 + i * 22, 180, 22); + tb->setTooltip (T("a set of mutually-exclusive radio buttons")); + + if (i == 0) + tb->setToggleState (true, false); + } + + for (i = 0; i < 4; ++i) + { + DrawablePath normal, over; + + Path p; + p.addStar (0.0f, 0.0f, i + 5, 20.0f, 50.0f, -0.2f); + normal.setPath (p); + normal.setFill (Colours::lightblue); + normal.setStrokeFill (Colours::black); + normal.setStrokeThickness (4.0f); + + over.setPath (p); + over.setFill (Colours::blue); + over.setStrokeFill (Colours::black); + over.setStrokeThickness (4.0f); + + DrawableButton* db = new DrawableButton (String (i + 5) + T(" points"), DrawableButton::ImageAboveTextLabel); + db->setImages (&normal, &over, 0); + + page->addAndMakeVisible (db); + db->setClickingTogglesState (true); + db->setRadioGroupId (23456); + + const int buttonSize = 50; + db->setBounds (25 + i * buttonSize, 180, buttonSize, buttonSize); + + if (i == 0) + db->setToggleState (true, false); + } + + for (i = 0; i < 4; ++i) + { + TextButton* tb = new TextButton (T("button ") + String (i + 1)); + + page->addAndMakeVisible (tb); + tb->setClickingTogglesState (true); + tb->setRadioGroupId (34567); + tb->setColour (TextButton::buttonColourId, Colours::white); + tb->setColour (TextButton::buttonOnColourId, Colours::blueviolet.brighter()); + + tb->setBounds (20 + i * 55, 260, 55, 24); + tb->setConnectedEdges (((i != 0) ? Button::ConnectedOnLeft : 0) + | ((i != 3) ? Button::ConnectedOnRight : 0)); + + if (i == 0) + tb->setToggleState (true, false); + } + + return page; +} + +//============================================================================== +class ButtonsPage : public Component, + public ButtonListener +{ +public: + ButtonsPage (ButtonListener* buttonListener) + { + //============================================================================== + // create some drawables to use for our drawable buttons... + DrawablePath normal, over; + + Path p; + p.addStar (0.0f, 0.0f, 5, 20.0f, 50.0f, 0.2f); + normal.setPath (p); + normal.setFill (Colours::red); + + p.clear(); + p.addStar (0.0f, 0.0f, 7, 30.0f, 50.0f, 0.0f); + over.setPath (p); + over.setFill (Colours::pink); + over.setStrokeFill (Colours::black); + over.setStrokeThickness (5.0f); + + DrawableImage down; + down.setImage (ImageCache::getFromMemory (BinaryData::juce_png, BinaryData::juce_pngSize), true); + down.setOverlayColour (Colours::black.withAlpha (0.3f)); + + //============================================================================== + // create an image-above-text button from these drawables.. + DrawableButton* db = new DrawableButton (T("Button 1"), DrawableButton::ImageAboveTextLabel); + db->setImages (&normal, &over, &down); + + addAndMakeVisible (db); + db->setBounds (10, 30, 80, 80); + db->setTooltip (T("this is a DrawableButton with a label")); + + //============================================================================== + // create an image-only button from these drawables.. + db = new DrawableButton (T("Button 2"), DrawableButton::ImageFitted); + db->setImages (&normal, &over, &down); + db->setClickingTogglesState (true); + + addAndMakeVisible (db); + db->setBounds (90, 30, 80, 80); + db->setTooltip (T("this is an image-only DrawableButton")); + db->addButtonListener (buttonListener); + + //============================================================================== + // create an image-on-button-shape button from the same drawables.. + db = new DrawableButton (T("Button 3"), DrawableButton::ImageOnButtonBackground); + db->setImages (&normal, 0, 0); + + addAndMakeVisible (db); + db->setBounds (200, 30, 110, 25); + db->setTooltip (T("this is a DrawableButton on a standard button background")); + + //============================================================================== + db = new DrawableButton (T("Button 4"), DrawableButton::ImageOnButtonBackground); + db->setImages (&normal, &over, &down); + db->setClickingTogglesState (true); + db->setBackgroundColours (Colours::white, Colours::yellow); + + addAndMakeVisible (db); + db->setBounds (200, 70, 50, 50); + db->setTooltip (T("this is a DrawableButton on a standard button background")); + db->addButtonListener (buttonListener); + + //============================================================================== + HyperlinkButton* hyperlink + = new HyperlinkButton (T("this is a HyperlinkButton"), + URL (T("http://www.rawmaterialsoftware.com/juce"))); + + hyperlink->setBounds (10, 130, 200, 24); + addAndMakeVisible (hyperlink); + + //============================================================================== + ImageButton* imageButton = new ImageButton (T("imagebutton")); + addAndMakeVisible (imageButton); + + Image* juceImage = ImageCache::getFromMemory (BinaryData::juce_png, BinaryData::juce_pngSize); + ImageCache::incReferenceCount (juceImage); + ImageCache::incReferenceCount (juceImage); + + imageButton->setImages (true, true, true, + juceImage, 0.7f, Colours::transparentBlack, + juceImage, 1.0f, Colours::transparentBlack, + juceImage, 1.0f, Colours::pink.withAlpha (0.8f), + 0.5f); + + imageButton->setTopLeftPosition (10, 160); + imageButton->setTooltip (T("image button - showing alpha-channel hit-testing and colour overlay when clicked")); + + //============================================================================== + ColourChangeButton* colourChangeButton = new ColourChangeButton(); + addAndMakeVisible (colourChangeButton); + colourChangeButton->setTopLeftPosition (350, 30); + + //============================================================================== + animateButton = new TextButton (T("click to animate...")); + addAndMakeVisible (animateButton); + animateButton->changeWidthToFitText (24); + animateButton->setTopLeftPosition (350, 70); + animateButton->addButtonListener (this); + } + + ~ButtonsPage() + { + deleteAllChildren(); + } + + void buttonClicked (Button*) + { + for (int i = getNumChildComponents(); --i >= 0;) + { + if (getChildComponent (i) != animateButton) + { + animator.animateComponent (getChildComponent (i), + Rectangle (Random::getSystemRandom().nextInt (getWidth() / 2), + Random::getSystemRandom().nextInt (getHeight() / 2), + 60 + Random::getSystemRandom().nextInt (getWidth() / 3), + 16 + Random::getSystemRandom().nextInt (getHeight() / 6)), + 500 + Random::getSystemRandom().nextInt (2000), + Random::getSystemRandom().nextDouble(), + Random::getSystemRandom().nextDouble()); + } + } + } + +private: + TextButton* animateButton; + ComponentAnimator animator; +}; + + +//============================================================================== +static Component* createMiscPage() +{ + DemoPageComp* page = new DemoPageComp(); + + TextEditor* textEditor1 = new TextEditor(); + page->addAndMakeVisible (textEditor1); + textEditor1->setBounds (10, 25, 200, 24); + textEditor1->setText (T("single-line text box")); + + TextEditor* textEditor2 = new TextEditor (T("password"), (tchar) 0x2022); + page->addAndMakeVisible (textEditor2); + textEditor2->setBounds (10, 55, 200, 24); + textEditor2->setText (T("password")); + + //============================================================================== + ComboBox* comboBox = new ComboBox (T("combo")); + page->addAndMakeVisible (comboBox); + comboBox->setBounds (300, 25, 200, 24); + comboBox->setEditableText (true); + comboBox->setJustificationType (Justification::centred); + + int i; + for (i = 1; i < 100; ++i) + comboBox->addItem (T("combo box item ") + String (i), i); + + comboBox->setSelectedId (1); + + DragOntoDesktopDemoComp* d = new DragOntoDesktopDemoComp (page); + page->addAndMakeVisible (d); + d->setBounds (20, 100, 200, 80); + + return page; +} + +//============================================================================== +class ToolbarDemoComp : public Component, + public SliderListener, + public ButtonListener +{ +public: + ToolbarDemoComp (ApplicationCommandManager* commandManager) + { + // Create and add the toolbar... + addAndMakeVisible (toolbar = new Toolbar()); + + // And use our item factory to add a set of default icons to it... + toolbar->addDefaultItems (factory); + + // Now we'll just create the other sliders and buttons on the demo page, which adjust + // the toolbar's properties... + Label* info = new Label (String::empty, + "As well as showing off toolbars, this demo illustrates how to store " + "a set of SVG files in a Zip file, embed that in your application, and read " + "them back in at runtime.\n\nThe icon images here are taken from the open-source " + "Tango icon project."); + + addAndMakeVisible (info); + info->setJustificationType (Justification::topLeft); + info->setBounds (80, 80, 450, 100); + info->setInterceptsMouseClicks (false, false); + + addAndMakeVisible (depthSlider = new Slider (T("toolbar depth:"))); + depthSlider->setRange (10.0, 200.0, 1.0); + depthSlider->setValue (50, false); + depthSlider->setSliderStyle (Slider::LinearHorizontal); + depthSlider->setTextBoxStyle (Slider::TextBoxLeft, false, 80, 20); + depthSlider->addListener (this); + depthSlider->setBounds (80, 210, 300, 22); + (new Label (depthSlider->getName(), depthSlider->getName()))->attachToComponent (depthSlider, false); + + addAndMakeVisible (orientationButton = new TextButton (T("vertical/horizontal"))); + orientationButton->addButtonListener (this); + orientationButton->changeWidthToFitText (22); + orientationButton->setTopLeftPosition (depthSlider->getX(), depthSlider->getBottom() + 20); + + addAndMakeVisible (customiseButton = new TextButton (T("customise..."))); + customiseButton->addButtonListener (this); + customiseButton->changeWidthToFitText (22); + customiseButton->setTopLeftPosition (orientationButton->getRight() + 20, orientationButton->getY()); + } + + ~ToolbarDemoComp() + { + deleteAllChildren(); + } + + void resized() + { + if (toolbar->isVertical()) + toolbar->setBounds (0, 0, (int) depthSlider->getValue(), getHeight()); + else + toolbar->setBounds (0, 0, getWidth(), (int) depthSlider->getValue()); + } + + void sliderValueChanged (Slider* slider) + { + resized(); + } + + void buttonClicked (Button* button) + { + if (button == orientationButton) + { + toolbar->setVertical (! toolbar->isVertical()); + resized(); + } + else if (button == customiseButton) + { + toolbar->showCustomisationDialog (factory); + } + } + +private: + Toolbar* toolbar; + Slider* depthSlider; + TextButton* orientationButton; + TextButton* customiseButton; + + //============================================================================== + class DemoToolbarItemFactory : public ToolbarItemFactory + { + public: + DemoToolbarItemFactory() {} + ~DemoToolbarItemFactory() {} + + //============================================================================== + // Each type of item a toolbar can contain must be given a unique ID. These + // are the ones we'll use in this demo. + enum DemoToolbarItemIds + { + doc_new = 1, + doc_open = 2, + doc_save = 3, + doc_saveAs = 4, + edit_copy = 5, + edit_cut = 6, + edit_paste = 7, + juceLogoButton = 8, + customComboBox = 9 + }; + + void getAllToolbarItemIds (Array & ids) + { + // This returns the complete list of all item IDs that are allowed to + // go in our toolbar. Any items you might want to add must be listed here. The + // order in which they are listed will be used by the toolbar customisation panel. + + ids.add (doc_new); + ids.add (doc_open); + ids.add (doc_save); + ids.add (doc_saveAs); + ids.add (edit_copy); + ids.add (edit_cut); + ids.add (edit_paste); + ids.add (juceLogoButton); + ids.add (customComboBox); + + // If you're going to use separators, then they must also be added explicitly + // to the list. + ids.add (separatorBarId); + ids.add (spacerId); + ids.add (flexibleSpacerId); + } + + void getDefaultItemSet (Array & ids) + { + // This returns an ordered list of the set of items that make up a + // toolbar's default set. Not all items need to be on this list, and + // items can appear multiple times (e.g. the separators used here). + ids.add (doc_new); + ids.add (doc_open); + ids.add (doc_save); + ids.add (doc_saveAs); + ids.add (spacerId); + ids.add (separatorBarId); + ids.add (edit_copy); + ids.add (edit_cut); + ids.add (edit_paste); + ids.add (separatorBarId); + ids.add (flexibleSpacerId); + ids.add (customComboBox); + ids.add (flexibleSpacerId); + ids.add (separatorBarId); + ids.add (juceLogoButton); + } + + ToolbarItemComponent* createItem (const int itemId) + { + switch (itemId) + { + case doc_new: + return createButtonFromZipFileSVG (itemId, T("new"), T("document-new.svg")); + + case doc_open: + return createButtonFromZipFileSVG (itemId, T("open"), T("document-open.svg")); + + case doc_save: + return createButtonFromZipFileSVG (itemId, T("save"), T("document-save.svg")); + + case doc_saveAs: + return createButtonFromZipFileSVG (itemId, T("save as"), T("document-save-as.svg")); + + case edit_copy: + return createButtonFromZipFileSVG (itemId, T("copy"), T("edit-copy.svg")); + + case edit_cut: + return createButtonFromZipFileSVG (itemId, T("cut"), T("edit-cut.svg")); + + case edit_paste: + return createButtonFromZipFileSVG (itemId, T("paste"), T("edit-paste.svg")); + + case juceLogoButton: + return new ToolbarButton (itemId, T("juce!"), Drawable::createFromImageData (BinaryData::juce_png, BinaryData::juce_pngSize), 0); + + case customComboBox: + return new CustomToolbarComboBox (itemId); + + default: + break; + } + + return 0; + } + + private: + StringArray iconNames; + OwnedArray iconsFromZipFile; + + // This is a little utility to create a button with one of the SVG images in + // our embedded ZIP file "icons.zip" + ToolbarButton* createButtonFromZipFileSVG (const int itemId, const String& text, const String& filename) + { + if (iconsFromZipFile.size() == 0) + { + // If we've not already done so, load all the images from the zip file.. + MemoryInputStream iconsFileStream (BinaryData::icons_zip, BinaryData::icons_zipSize, false); + ZipFile icons (&iconsFileStream, false); + + for (int i = 0; i < icons.getNumEntries(); ++i) + { + InputStream* svgFileStream = icons.createStreamForEntry (i); + + if (svgFileStream != 0) + { + iconNames.add (icons.getEntry(i)->filename); + iconsFromZipFile.add (Drawable::createFromImageDataStream (*svgFileStream)); + + delete svgFileStream; + } + } + } + + Drawable* image = iconsFromZipFile [iconNames.indexOf (filename)]->createCopy(); + return new ToolbarButton (itemId, text, image, 0); + + return 0; + } + + // Demonstrates how to put a custom component into a toolbar - this one contains + // a ComboBox. + class CustomToolbarComboBox : public ToolbarItemComponent + { + public: + CustomToolbarComboBox (const int toolbarItemId) + : ToolbarItemComponent (toolbarItemId, T("Custom Toolbar Item"), false) + { + addAndMakeVisible (comboBox = new ComboBox (T("demo toolbar combo box"))); + + for (int i = 1; i < 20; ++i) + comboBox->addItem (T("Toolbar ComboBox item ") + String (i), i); + + comboBox->setSelectedId (1); + comboBox->setEditableText (true); + } + + ~CustomToolbarComboBox() + { + delete comboBox; + } + + bool getToolbarItemSizes (int toolbarDepth, + bool isToolbarVertical, + int& preferredSize, int& minSize, int& maxSize) + { + if (isToolbarVertical) + return false; + + preferredSize = 250; + minSize = 80; + maxSize = 300; + return true; + } + + void paintButtonArea (Graphics&, int, int, bool, bool) + { + } + + void contentAreaChanged (const Rectangle& contentArea) + { + comboBox->setSize (contentArea.getWidth() - 2, + jmin (contentArea.getHeight() - 2, 22)); + + comboBox->setCentrePosition (contentArea.getCentreX(), contentArea.getCentreY()); + } + + private: + ComboBox* comboBox; + }; + }; + + DemoToolbarItemFactory factory; +}; + +//============================================================================== +class DemoTabbedComponent : public TabbedComponent, + public ButtonListener +{ +public: + DemoTabbedComponent (ApplicationCommandManager* commandManager) + : TabbedComponent (TabbedButtonBar::TabsAtTop) + { + addTab (T("sliders"), getRandomBrightColour(), createSlidersPage(), true); + addTab (T("toolbars"), getRandomBrightColour(), new ToolbarDemoComp (commandManager), true); + addTab (T("buttons"), getRandomBrightColour(), new ButtonsPage (this), true); + addTab (T("radio buttons"), getRandomBrightColour(), createRadioButtonPage(), true); + addTab (T("misc widgets"), getRandomBrightColour(), createMiscPage(), true); + } + + ~DemoTabbedComponent() + { + } + + void buttonClicked (Button* button) + { + BubbleMessageComponent* bmc = new BubbleMessageComponent(); + + if (Desktop::canUseSemiTransparentWindows()) + { + bmc->setAlwaysOnTop (true); + bmc->addToDesktop (0); + } + else + { + addChildComponent (bmc); + } + + bmc->showAt (button, T("This is a demo of the BubbleMessageComponent, which lets you pop up a message pointing at a component or somewhere on the screen.\n\nThe message bubbles will disappear after a timeout period, or when the mouse is clicked."), + 2000, true, true); + } + + static const Colour getRandomBrightColour() + { + return Colour (Random::getSystemRandom().nextFloat(), 0.1f, 0.97f, 1.0f); + } +}; + + +//============================================================================== +class DemoBackgroundThread : public ThreadWithProgressWindow +{ +public: + DemoBackgroundThread() + : ThreadWithProgressWindow (T("busy doing some important things..."), + true, + true) + { + setStatusMessage (T("Getting ready...")); + } + + ~DemoBackgroundThread() + { + } + + void run() + { + setProgress (-1.0); // setting a value beyond the range 0 -> 1 will show a spinning bar.. + setStatusMessage (T("Preparing to do some stuff...")); + wait (2000); + + const int thingsToDo = 10; + + for (int i = 0; i < thingsToDo; ++i) + { + // must check this as often as possible, because this is + // how we know if the user's pressed 'cancel' + if (threadShouldExit()) + return; + + // this will update the progress bar on the dialog box + setProgress (i / (double) thingsToDo); + + setStatusMessage (String (thingsToDo - i) + T(" things left to do...")); + + wait (500); + } + + setProgress (-1.0); // setting a value beyond the range 0 -> 1 will show a spinning bar.. + setStatusMessage (T("Finishing off the last few bits and pieces!")); + wait (2000); + } +}; + +//============================================================================== +/** A DialogWindow containing a ColourSelector component */ +class ColourSelectorDialogWindow : public DialogWindow +{ +public: + ColourSelectorDialogWindow() + : DialogWindow (T("Colour selector demo"), + Colours::lightgrey, + true) + { + setContentComponent (new ColourSelector()); + centreWithSize (400, 400); + setResizable (true, true); + } + + ~ColourSelectorDialogWindow() + { + } + + void closeButtonPressed() + { + // we expect this component to be run within a modal loop, so when the close + // button is clicked, we can make it invisible to cause the loop to exit and the + // calling code will delete this object. + setVisible (false); + } +}; + +#if JUCE_MAC + +//============================================================================== +/** This pops open a dialog box and waits for you to press keys on your Apple Remote, + which it describes in the box. +*/ +class AppleRemoteTestWindow : public AlertWindow, + public AppleRemoteDevice +{ +public: + AppleRemoteTestWindow() + : AlertWindow ("Apple Remote Control Test!", + "If you've got an Apple Remote, press some buttons now...", + AlertWindow::NoIcon) + { + addButton (T("done"), 0); + + // (To open the device in non-exclusive mode, pass 'false' in here).. + if (! start (true)) + setMessage ("Couldn't open the remote control device!"); + } + + ~AppleRemoteTestWindow() + { + stop(); + } + + void buttonPressed (const ButtonType buttonId, const bool isDown) + { + String desc; + + switch (buttonId) + { + case menuButton: + desc = "menu button (short)"; + break; + case playButton: + desc = "play button"; + break; + case plusButton: + desc = "plus button"; + break; + case minusButton: + desc = "minus button"; + break; + case rightButton: + desc = "right button (short)"; + break; + case leftButton: + desc = "left button (short)"; + break; + case rightButton_Long: + desc = "right button (long)"; + break; + case leftButton_Long: + desc = "left button (long)"; + break; + case menuButton_Long: + desc = "menu button (long)"; + break; + case playButtonSleepMode: + desc = "play (sleep mode)"; + break; + case switched: + desc = "remote switched"; + break; + } + + if (isDown) + desc << " -- [down]"; + else + desc << " -- [up]"; + + setMessage (desc); + } +}; + +#endif + +//============================================================================== +const int numGroups = 4; + +class WidgetsDemo : public Component, + public ButtonListener +{ + TextButton* menuButton; + ToggleButton* enableButton; + + DemoTabbedComponent* tabs; + +public: + //============================================================================== + WidgetsDemo (ApplicationCommandManager* commandManager) + { + setName (T("Widgets")); + + addAndMakeVisible (tabs = new DemoTabbedComponent (commandManager)); + + //============================================================================== + menuButton = new TextButton (T("click for a popup menu.."), + T("click for a demo of the different types of item you can put into a popup menu...")); + + addAndMakeVisible (menuButton); + menuButton->setBounds (10, 10, 200, 24); + menuButton->addButtonListener (this); + menuButton->setTriggeredOnMouseDown (true); // because this button pops up a menu, this lets us + // hold down the button and drag straight onto the menu + + //============================================================================== + enableButton = new ToggleButton (T("enable/disable components")); + addAndMakeVisible (enableButton); + enableButton->setBounds (230, 10, 180, 24); + enableButton->setTooltip (T("toggle button")); + enableButton->setToggleState (true, false); + enableButton->addButtonListener (this); + } + + ~WidgetsDemo() + { + deleteAllChildren(); + } + + void resized() + { + tabs->setBounds (10, 40, getWidth() - 20, getHeight() - 50); + } + + //============================================================================== + void buttonClicked (Button* button) + { + if (button == enableButton) + { + const bool enabled = enableButton->getToggleState(); + + menuButton->setEnabled (enabled); + tabs->setEnabled (enabled); + } + else if (button == menuButton) + { + PopupMenu m; + m.addItem (1, T("Normal item")); + m.addItem (2, T("Disabled item"), false); + m.addItem (3, T("Ticked item"), true, true); + m.addColouredItem (4, T("Coloured item"), Colours::green); + m.addSeparator(); + m.addCustomItem (5, new CustomMenuComponent()); + + m.addSeparator(); + + PopupMenu tabsMenu; + tabsMenu.addItem (1001, T("Show tabs at the top"), true, tabs->getOrientation() == TabbedButtonBar::TabsAtTop); + tabsMenu.addItem (1002, T("Show tabs at the bottom"), true, tabs->getOrientation() == TabbedButtonBar::TabsAtBottom); + tabsMenu.addItem (1003, T("Show tabs at the left"), true, tabs->getOrientation() == TabbedButtonBar::TabsAtLeft); + tabsMenu.addItem (1004, T("Show tabs at the right"), true, tabs->getOrientation() == TabbedButtonBar::TabsAtRight); + m.addSubMenu (T("Tab position"), tabsMenu); + + m.addSeparator(); + + PopupMenu dialogMenu; + dialogMenu.addItem (100, T("Show a plain alert-window...")); + dialogMenu.addItem (101, T("Show an alert-window with a 'warning' icon...")); + dialogMenu.addItem (102, T("Show an alert-window with an 'info' icon...")); + dialogMenu.addItem (103, T("Show an alert-window with a 'question' icon...")); + + dialogMenu.addSeparator(); + + dialogMenu.addItem (110, T("Show an ok/cancel alert-window...")); + + dialogMenu.addSeparator(); + + dialogMenu.addItem (111, T("Show an alert-window with some extra components...")); + + dialogMenu.addSeparator(); + + dialogMenu.addItem (112, T("Show a ThreadWithProgressWindow demo...")); + + m.addSubMenu (T("AlertWindow demonstrations"), dialogMenu); + + m.addSeparator(); + + m.addItem (120, T("Show a colour selector demo...")); + m.addSeparator(); + +#if JUCE_MAC + m.addItem (140, T("Run the Apple Remote Control test...")); + m.addSeparator(); +#endif + + PopupMenu nativeFileChoosers; + nativeFileChoosers.addItem (121, T("'Load' file browser...")); + nativeFileChoosers.addItem (124, T("'Load' file browser with an image file preview...")); + nativeFileChoosers.addItem (122, T("'Save' file browser...")); + nativeFileChoosers.addItem (123, T("'Choose directory' file browser...")); + + PopupMenu juceFileChoosers; + juceFileChoosers.addItem (131, T("'Load' file browser...")); + juceFileChoosers.addItem (134, T("'Load' file browser with an image file preview...")); + juceFileChoosers.addItem (132, T("'Save' file browser...")); + juceFileChoosers.addItem (133, T("'Choose directory' file browser...")); + + PopupMenu fileChoosers; + fileChoosers.addSubMenu (T("Operating system dialogs"), nativeFileChoosers); + fileChoosers.addSubMenu (T("Juce dialogs"), juceFileChoosers); + + m.addSubMenu (T("File chooser dialogs"), fileChoosers); + + int result = m.showAt (menuButton); + + if (result != 0) + { + // user chose something from the menu.. + + if (result >= 100 && result < 105) + { + AlertWindow::AlertIconType icon = AlertWindow::NoIcon; + + if (result == 101) + icon = AlertWindow::WarningIcon; + else if (result == 102) + icon = AlertWindow::InfoIcon; + else if (result == 103) + icon = AlertWindow::QuestionIcon; + + AlertWindow::showMessageBox (icon, + T("This is an AlertWindow"), + T("And this is the AlertWindow's message. Blah blah blah blah blah blah blah blah blah blah blah blah blah."), + T("ok")); + } + else if (result == 110) + { + bool userPickedOk + = AlertWindow::showOkCancelBox (AlertWindow::QuestionIcon, + T("This is an ok/cancel AlertWindow"), + T("And this is the AlertWindow's message. Blah blah blah blah blah blah blah blah blah blah blah blah blah.")); + + (void) userPickedOk; // (just avoids a compiler warning about unused variables) + } + else if (result == 111) + { + AlertWindow w (T("AlertWindow demo.."), + T("This AlertWindow has a couple of extra components added to show how to add drop-down lists and text entry boxes."), + AlertWindow::QuestionIcon); + + w.addTextEditor (T("text"), T("enter some text here"), T("text field:")); + + StringArray options; + options.add (T("option 1")); + options.add (T("option 2")); + options.add (T("option 3")); + options.add (T("option 4")); + w.addComboBox (T("option"), options, T("some options")); + + w.addButton (T("ok"), 1, KeyPress (KeyPress::returnKey, 0, 0)); + w.addButton (T("cancel"), 0, KeyPress (KeyPress::escapeKey, 0, 0)); + + if (w.runModalLoop() != 0) // is they picked 'ok' + { + // this is the item they chose in the drop-down list.. + const int optionIndexChosen = w.getComboBoxComponent (T("option"))->getSelectedItemIndex(); + (void) optionIndexChosen; // (just avoids a compiler warning about unused variables) + + + // this is the text they entered.. + String text = w.getTextEditorContents (T("text")); + + } + } + else if (result == 112) + { + DemoBackgroundThread demoThread; + + if (demoThread.runThread()) + { + // thread finished normally.. + AlertWindow::showMessageBox (AlertWindow::WarningIcon, + T("Progress window"), + T("Thread finished ok!")); + } + else + { + // user pressed the cancel button.. + AlertWindow::showMessageBox (AlertWindow::WarningIcon, + T("Progress window"), + T("You pressed cancel!")); + } + + } + else if (result == 120) + { + ColourSelectorDialogWindow colourDialog; + + // this will run an event loop until the dialog's closeButtonPressed() + // method causes the loop to exit. + colourDialog.runModalLoop(); + } + else if (result == 140) + { +#if JUCE_MAC + AppleRemoteTestWindow test; + test.runModalLoop(); +#endif + } + else if (result >= 121 && result < 139) + { + const bool useNativeVersion = result < 130; + if (result > 130) + result -= 10; + + if (result == 121) + { + FileChooser fc (T("Choose a file to open..."), + File::getCurrentWorkingDirectory(), + T("*"), + useNativeVersion); + + if (fc.browseForFileToOpen()) + { + File chosenFile = fc.getResult(); + + AlertWindow::showMessageBox (AlertWindow::InfoIcon, + T("File Chooser..."), + T("You picked: ") + chosenFile.getFullPathName()); + } + } + else if (result == 124) + { + ImagePreviewComponent imagePreview; + imagePreview.setSize (200, 200); + + FileChooser fc (T("Choose an image to open..."), + File::getCurrentWorkingDirectory(), + T("*.jpg;*.jpeg;*.png;*.gif"), + useNativeVersion); + + if (fc.browseForFileToOpen (&imagePreview)) + { + File chosenFile = fc.getResult(); + + AlertWindow::showMessageBox (AlertWindow::InfoIcon, + T("File Chooser..."), + T("You picked: ") + chosenFile.getFullPathName()); + } + } + else if (result == 122) + { + FileChooser fc (T("Choose a file to save..."), + File::getCurrentWorkingDirectory(), + T("*"), + useNativeVersion); + + if (fc.browseForFileToSave (true)) + { + File chosenFile = fc.getResult(); + + AlertWindow::showMessageBox (AlertWindow::InfoIcon, + T("File Chooser..."), + T("You picked: ") + chosenFile.getFullPathName()); + } + } + else if (result == 123) + { + FileChooser fc (T("Choose a directory..."), + File::getCurrentWorkingDirectory(), + T("*"), + useNativeVersion); + + if (fc.browseForDirectory()) + { + File chosenDirectory = fc.getResult(); + + AlertWindow::showMessageBox (AlertWindow::InfoIcon, + T("File Chooser..."), + T("You picked: ") + chosenDirectory.getFullPathName()); + } + } + } + else if (result == 1001) + { + tabs->setOrientation (TabbedButtonBar::TabsAtTop); + } + else if (result == 1002) + { + tabs->setOrientation (TabbedButtonBar::TabsAtBottom); + } + else if (result == 1003) + { + tabs->setOrientation (TabbedButtonBar::TabsAtLeft); + } + else if (result == 1004) + { + tabs->setOrientation (TabbedButtonBar::TabsAtRight); + } + } + } + } +}; + + +//============================================================================== +Component* createWidgetsDemo (ApplicationCommandManager* commandManager) +{ + return new WidgetsDemo (commandManager); +} diff --git a/juce_amalgamated.cpp b/juce_amalgamated.cpp index 7747d118c4..558a283a79 100644 --- a/juce_amalgamated.cpp +++ b/juce_amalgamated.cpp @@ -1236,13 +1236,11 @@ void Random::setSeed (const int64 newSeed) throw() void Random::setSeedRandomly() { - Random r1 (Time::getMillisecondCounter()); - Random r2 (Time::getHighResolutionTicks()); - Random r3 (Time::getHighResolutionTicksPerSecond()); - Random r4 (Time::currentTimeMillis()); - - setSeed (nextInt64() ^ r1.nextInt64() ^ r2.nextInt64() - ^ r3.nextInt64() ^ r4.nextInt64()); + seed ^= (int64) (pointer_sized_int) this; + seed ^= nextInt64() ^ Time::getMillisecondCounter(); + seed ^= nextInt64() ^ Time::getHighResolutionTicks(); + seed ^= nextInt64() ^ Time::getHighResolutionTicksPerSecond(); + seed ^= nextInt64() ^ Time::currentTimeMillis(); } int Random::nextInt() throw() @@ -1576,12 +1574,13 @@ void JUCE_PUBLIC_FUNCTION initialiseJuce_NonGUI() // Some simple test code to keep an eye on things and make sure these functions // work ok on all platforms. Let me know if any of these assertions fail! int n = 1; - atomicIncrement (n); - jassert (atomicIncrementAndReturn (n) == 3); - atomicDecrement (n); - jassert (atomicDecrementAndReturn (n) == 1); + Atomic::increment (n); + jassert (Atomic::incrementAndReturn (n) == 3); + Atomic::decrement (n); + jassert (Atomic::decrementAndReturn (n) == 1); - jassert (swapByteOrder ((uint32) 0x11223344) == 0x44332211); + jassert (ByteOrder::swap ((uint16) 0x1122) == 0x2211); + jassert (ByteOrder::swap ((uint32) 0x11223344) == 0x44332211); // quick test to make sure the run-time lib doesn't crash on freeing a null-pointer. SystemStats* nullPointer = 0; @@ -2011,28 +2010,20 @@ const String Time::toString (const bool includeDate, const String Time::formatted (const tchar* const format) const throw() { - tchar buffer[80]; + String buffer; + int bufferSize = 128; + buffer.preallocateStorage (bufferSize); struct tm t; millisToLocal (millisSinceEpoch, t); - if (CharacterFunctions::ftime (buffer, 79, format, &t) <= 0) + while (CharacterFunctions::ftime ((tchar*) (const tchar*) buffer, bufferSize, format, &t) <= 0) { - int bufferSize = 128; - - for (;;) - { - MemoryBlock mb (bufferSize * sizeof (tchar)); - tchar* const b = (tchar*) mb.getData(); - - if (CharacterFunctions::ftime (b, bufferSize, format, &t) > 0) - return String (b); - - bufferSize += 128; - } + bufferSize += 128; + buffer.preallocateStorage (bufferSize); } - return String (buffer); + return buffer; } int Time::getYear() const throw() @@ -3766,21 +3757,55 @@ const var& var::operator= (const var& valueToCopy) throw() { if (this != &valueToCopy) { - if (type == stringType) - delete value.stringValue; + if (type == valueToCopy.type) + { + switch (type) + { + case voidType: + break; + + case intType: + case boolType: + case doubleType: + value = valueToCopy.value; + break; - DynamicObject* const oldObject = getObject(); + case stringType: + *(value.stringValue) = *(valueToCopy.value.stringValue); + break; + + case objectType: + if (valueToCopy.value.objectValue != 0) + valueToCopy.value.objectValue->incReferenceCount(); - type = valueToCopy.type; - value = valueToCopy.value; + if (value.objectValue != 0) + value.objectValue->decReferenceCount(); - if (type == stringType) - value.stringValue = new String (*(value.stringValue)); - else if (type == objectType && value.objectValue != 0) - value.objectValue->incReferenceCount(); + value.objectValue = valueToCopy.value.objectValue; + break; - if (oldObject != 0) - oldObject->decReferenceCount(); + default: + jassertfalse; + break; + } + } + else + { + releaseValue(); + type = valueToCopy.type; + + if (type == stringType) + { + value.stringValue = new String (*(valueToCopy.value.stringValue)); + } + else + { + value = valueToCopy.value; + + if (type == objectType && value.objectValue != 0) + value.objectValue->incReferenceCount(); + } + } } return *this; @@ -4627,7 +4652,7 @@ MD5::MD5 (const String& text) // force the string into integer-sized unicode characters, to try to make it // get the same results on all platforms + compilers. uint32 unicodeChar = (uint32) t[i]; - swapIfBigEndian (unicodeChar); + ByteOrder::swapIfBigEndian (unicodeChar); context.processBlock ((const uint8*) &unicodeChar, sizeof (unicodeChar)); @@ -4731,7 +4756,7 @@ static void encode (uint8* const output, uint32* const o = (uint32*) output; for (int i = 0; i < (numBytes >> 2); ++i) - o[i] = swapIfBigEndian (input [i]); + o[i] = ByteOrder::swapIfBigEndian (input [i]); } static void decode (uint32* const output, @@ -4739,7 +4764,7 @@ static void decode (uint32* const output, const int numBytes) { for (int i = 0; i < (numBytes >> 2); ++i) - output[i] = littleEndianInt ((const char*) input + (i << 2)); + output[i] = ByteOrder::littleEndianInt ((const char*) input + (i << 2)); } void MD5::ProcessContext::finish (uint8* const result) @@ -5298,7 +5323,7 @@ short InputStream::readShort() char temp [2]; if (read (temp, 2) == 2) - return (short) littleEndianShort (temp); + return (short) ByteOrder::littleEndianShort (temp); else return 0; } @@ -5308,7 +5333,7 @@ short InputStream::readShortBigEndian() char temp [2]; if (read (temp, 2) == 2) - return (short) bigEndianShort (temp); + return (short) ByteOrder::bigEndianShort (temp); else return 0; } @@ -5318,7 +5343,7 @@ int InputStream::readInt() char temp [4]; if (read (temp, 4) == 4) - return (int) littleEndianInt (temp); + return (int) ByteOrder::littleEndianInt (temp); else return 0; } @@ -5328,7 +5353,7 @@ int InputStream::readIntBigEndian() char temp [4]; if (read (temp, 4) == 4) - return (int) bigEndianInt (temp); + return (int) ByteOrder::bigEndianInt (temp); else return 0; } @@ -5351,7 +5376,7 @@ int InputStream::readCompressedInt() if (read (bytes, numBytes) != numBytes) return 0; - const int num = (int) littleEndianInt (bytes); + const int num = (int) ByteOrder::littleEndianInt (bytes); return (sizeByte >> 7) ? -num : num; } @@ -5360,7 +5385,7 @@ int64 InputStream::readInt64() char temp [8]; if (read (temp, 8) == 8) - return (int64) swapIfBigEndian (*(uint64*) temp); + return (int64) ByteOrder::swapIfBigEndian (*(uint64*) temp); else return 0; } @@ -5370,7 +5395,7 @@ int64 InputStream::readInt64BigEndian() char temp [8]; if (read (temp, 8) == 8) - return (int64) swapIfLittleEndian (*(uint64*) temp); + return (int64) ByteOrder::swapIfLittleEndian (*(uint64*) temp); else return 0; } @@ -5579,25 +5604,25 @@ void OutputStream::writeByte (char byte) void OutputStream::writeShort (short value) { - const unsigned short v = swapIfBigEndian ((unsigned short) value); + const unsigned short v = ByteOrder::swapIfBigEndian ((unsigned short) value); write (&v, 2); } void OutputStream::writeShortBigEndian (short value) { - const unsigned short v = swapIfLittleEndian ((unsigned short) value); + const unsigned short v = ByteOrder::swapIfLittleEndian ((unsigned short) value); write (&v, 2); } void OutputStream::writeInt (int value) { - const unsigned int v = swapIfBigEndian ((unsigned int) value); + const unsigned int v = ByteOrder::swapIfBigEndian ((unsigned int) value); write (&v, 4); } void OutputStream::writeIntBigEndian (int value) { - const unsigned int v = swapIfLittleEndian ((unsigned int) value); + const unsigned int v = ByteOrder::swapIfLittleEndian ((unsigned int) value); write (&v, 4); } @@ -5625,13 +5650,13 @@ void OutputStream::writeCompressedInt (int value) void OutputStream::writeInt64 (int64 value) { - const uint64 v = swapIfBigEndian ((uint64) value); + const uint64 v = ByteOrder::swapIfBigEndian ((uint64) value); write (&v, 8); } void OutputStream::writeInt64BigEndian (int64 value) { - const uint64 v = swapIfLittleEndian ((uint64) value); + const uint64 v = ByteOrder::swapIfLittleEndian ((uint64) value); write (&v, 8); } @@ -9253,10 +9278,10 @@ public: if (inputStream != 0 && inputStream->setPosition (zei.streamOffset) && inputStream->read (buffer, 30) == 30 - && littleEndianInt (buffer) == 0x04034b50) + && ByteOrder::littleEndianInt (buffer) == 0x04034b50) { - headerSize = 30 + littleEndianShort (buffer + 26) - + littleEndianShort (buffer + 28); + headerSize = 30 + ByteOrder::littleEndianShort (buffer + 26) + + ByteOrder::littleEndianShort (buffer + 28); } } @@ -9480,7 +9505,7 @@ void ZipFile::init() const char* const buffer = ((const char*) headerData.getData()) + pos; - const int fileNameLen = littleEndianShort (buffer + 28); + const int fileNameLen = ByteOrder::littleEndianShort (buffer + 28); if (pos + 46 + fileNameLen > size) break; @@ -9488,8 +9513,8 @@ void ZipFile::init() ZipEntryInfo* const zei = new ZipEntryInfo(); zei->entry.filename = String::fromUTF8 ((const uint8*) buffer + 46, fileNameLen); - const int time = littleEndianShort (buffer + 12); - const int date = littleEndianShort (buffer + 14); + const int time = ByteOrder::littleEndianShort (buffer + 12); + const int date = ByteOrder::littleEndianShort (buffer + 14); const int year = 1980 + (date >> 9); const int month = ((date >> 5) & 15) - 1; @@ -9500,16 +9525,16 @@ void ZipFile::init() zei->entry.fileTime = Time (year, month, day, hours, minutes, seconds); - zei->compressed = littleEndianShort (buffer + 10) != 0; - zei->compressedSize = littleEndianInt (buffer + 20); - zei->entry.uncompressedSize = littleEndianInt (buffer + 24); + zei->compressed = ByteOrder::littleEndianShort (buffer + 10) != 0; + zei->compressedSize = ByteOrder::littleEndianInt (buffer + 20); + zei->entry.uncompressedSize = ByteOrder::littleEndianInt (buffer + 24); - zei->streamOffset = littleEndianInt (buffer + 42); + zei->streamOffset = ByteOrder::littleEndianInt (buffer + 42); entries.add (zei); pos += 46 + fileNameLen - + littleEndianShort (buffer + 30) - + littleEndianShort (buffer + 32); + + ByteOrder::littleEndianShort (buffer + 30) + + ByteOrder::littleEndianShort (buffer + 32); } } } @@ -9538,13 +9563,13 @@ int ZipFile::findEndOfZipEntryTable (InputStream* input) for (int i = 0; i < 22; ++i) { - if (littleEndianInt (buffer + i) == 0x06054b50) + if (ByteOrder::littleEndianInt (buffer + i) == 0x06054b50) { in.setPosition (pos + i); in.read (buffer, 22); - numEntries = littleEndianShort (buffer + 10); + numEntries = ByteOrder::littleEndianShort (buffer + 10); - return littleEndianInt (buffer + 16); + return ByteOrder::littleEndianInt (buffer + 16); } } } @@ -10504,7 +10529,7 @@ void juce_initialiseStrings() void String::deleteInternal() throw() { - if (atomicDecrementAndReturn (text->refCount) == 0) + if (Atomic::decrementAndReturn (text->refCount) == 0) juce_free (text); } @@ -10551,7 +10576,7 @@ void String::appendInternal (const tchar* const newText, InternalRefCountedStringHolder* const old = text; text = newTextHolder; - if (atomicDecrementAndReturn (old->refCount) == 0) + if (Atomic::decrementAndReturn (old->refCount) == 0) juce_free (old); } else @@ -10591,7 +10616,7 @@ void String::dupeInternalIfMultiplyReferenced() throw() text = newTextHolder; - if (atomicDecrementAndReturn (old->refCount) == 0) + if (Atomic::decrementAndReturn (old->refCount) == 0) juce_free (old); } } @@ -10606,7 +10631,7 @@ String::String() throw() String::String (const String& other) throw() : text (other.text) { - atomicIncrement (text->refCount); + Atomic::increment (text->refCount); } String::String (const int numChars, @@ -10904,7 +10929,7 @@ String::~String() throw() { emptyString.refCount = safeEmptyStringRefCount; - if (atomicDecrementAndReturn (text->refCount) == 0) + if (Atomic::decrementAndReturn (text->refCount) == 0) juce_free (text); } @@ -11064,9 +11089,9 @@ const String& String::operator= (const String& other) throw() { if (this != &other) { - atomicIncrement (other.text->refCount); + Atomic::increment (other.text->refCount); - if (atomicDecrementAndReturn (text->refCount) == 0) + if (Atomic::decrementAndReturn (text->refCount) == 0) juce_free (text); text = other.text; @@ -12507,12 +12532,12 @@ const String String::createStringFromData (const void* const data_, if (bigEndian) { for (int i = 0; i < numChars; ++i) - dst[i] = (tchar) swapIfLittleEndian (src[i]); + dst[i] = (tchar) ByteOrder::swapIfLittleEndian (src[i]); } else { for (int i = 0; i < numChars; ++i) - dst[i] = (tchar) swapIfBigEndian (src[i]); + dst[i] = (tchar) ByteOrder::swapIfBigEndian (src[i]); } dst [numChars] = 0; @@ -12695,6 +12720,28 @@ const String String::fromUTF8 (const uint8* const buffer, int bufferSizeBytes) t return result; } +String::Concatenator::Concatenator (String& stringToAppendTo) + : result (stringToAppendTo), + nextIndex (stringToAppendTo.length()) +{ +} + +String::Concatenator::~Concatenator() +{ +} + +void String::Concatenator::append (const String& s) +{ + const int len = s.length(); + + if (len > 0) + { + result.preallocateStorage (nextIndex + len); + s.copyToBuffer (const_cast ((const tchar*) result) + nextIndex, len); + nextIndex += len; + } +} + END_JUCE_NAMESPACE /********* End of inlined file: juce_String.cpp *********/ @@ -13346,18 +13393,6 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE -static bool isXmlIdentifierChar_Slow (const tchar c) throw() -{ - return CharacterFunctions::isLetterOrDigit (c) - || c == T('_') - || c == T('-') - || c == T(':') - || c == T('.'); -} - -#define isXmlIdentifierChar(c) \ - ((c > 0 && c <= 127) ? identifierLookupTable [(int) c] : isXmlIdentifierChar_Slow (c)) - XmlDocument::XmlDocument (const String& documentText) throw() : originalText (documentText), ignoreEmptyTextElements (true) @@ -13383,6 +13418,21 @@ void XmlDocument::setEmptyTextElementsIgnored (const bool shouldBeIgnored) throw ignoreEmptyTextElements = shouldBeIgnored; } +bool XmlDocument::isXmlIdentifierCharSlow (const tchar c) throw() +{ + return CharacterFunctions::isLetterOrDigit (c) + || c == T('_') + || c == T('-') + || c == T(':') + || c == T('.'); +} + +inline bool XmlDocument::isXmlIdentifierChar (const tchar c) const throw() +{ + return (c > 0 && c <= 127) ? identifierLookupTable [(int) c] + : isXmlIdentifierCharSlow (c); +} + XmlElement* XmlDocument::getDocumentElement (const bool onlyReadOuterDocumentElement) { String textToParse (originalText); @@ -13420,7 +13470,7 @@ XmlElement* XmlDocument::getDocumentElement (const bool onlyReadOuterDocumentEle needToLoadDTD = true; for (int i = 0; i < 128; ++i) - identifierLookupTable[i] = isXmlIdentifierChar_Slow ((tchar) i); + identifierLookupTable[i] = isXmlIdentifierCharSlow ((tchar) i); if (textToParse.isEmpty()) { @@ -15301,12 +15351,13 @@ void XmlElement::setText (const String& newText) throw() const String XmlElement::getAllSubText() const throw() { String result; + String::Concatenator concatenator (result); const XmlElement* child = firstChildElement; while (child != 0) { if (child->isTextElement()) - result += child->getText(); + concatenator.append (child->getText()); child = child->nextElement; } @@ -18220,8 +18271,8 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE -static const int propFileMagicNumber = ((int) littleEndianInt ("PROP")); -static const int propFileMagicNumberCompressed = ((int) littleEndianInt ("CPRP")); +static const int propFileMagicNumber = ((int) ByteOrder::littleEndianInt ("PROP")); +static const int propFileMagicNumberCompressed = ((int) ByteOrder::littleEndianInt ("CPRP")); static const tchar* const propertyFileXmlTag = T("PROPERTIES"); static const tchar* const propertyTagName = T("VALUE"); @@ -19109,10 +19160,7 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE -#undef chunkName -#define chunkName(a) (int)littleEndianInt(a) - -#define aiffFormatName TRANS("AIFF file") +static const char* const aiffFormatName = "AIFF file"; static const tchar* const aiffExtensions[] = { T(".aiff"), T(".aif"), 0 }; class AiffAudioFormatReader : public AudioFormatReader @@ -19123,7 +19171,7 @@ public: bool littleEndian; AiffAudioFormatReader (InputStream* in) - : AudioFormatReader (in, aiffFormatName) + : AudioFormatReader (in, TRANS (aiffFormatName)) { if (input->readInt() == chunkName ("FORM")) { @@ -19169,9 +19217,9 @@ public: || (byte0 == 0x40 && sampleRateBytes[1] > 0x1C)) break; - unsigned int sampRate = bigEndianInt ((char*) sampleRateBytes + 2); - sampRate >>= (16414 - bigEndianShort ((char*) sampleRateBytes)); - sampleRate = (int)sampRate; + unsigned int sampRate = ByteOrder::bigEndianInt ((char*) sampleRateBytes + 2); + sampRate >>= (16414 - ByteOrder::bigEndianShort ((char*) sampleRateBytes)); + sampleRate = (int) sampRate; if (length <= 18) { @@ -19273,7 +19321,7 @@ public: { for (int i = numThisTime; --i >= 0;) { - *right++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16; + *right++ = (int) ByteOrder::swapIfBigEndian ((unsigned short) *src++) << 16; ++src; } } @@ -19282,15 +19330,15 @@ public: for (int i = numThisTime; --i >= 0;) { ++src; - *left++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16; + *left++ = (int) ByteOrder::swapIfBigEndian ((unsigned short) *src++) << 16; } } else { for (int i = numThisTime; --i >= 0;) { - *left++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16; - *right++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16; + *left++ = (int) ByteOrder::swapIfBigEndian ((unsigned short) *src++) << 16; + *right++ = (int) ByteOrder::swapIfBigEndian ((unsigned short) *src++) << 16; } } } @@ -19298,7 +19346,7 @@ public: { for (int i = numThisTime; --i >= 0;) { - *left++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16; + *left++ = (int) ByteOrder::swapIfBigEndian ((unsigned short) *src++) << 16; } } } @@ -19312,7 +19360,7 @@ public: { for (int i = numThisTime; --i >= 0;) { - *right++ = bigEndianShort (src) << 16; + *right++ = ByteOrder::bigEndianShort (src) << 16; src += 4; } } @@ -19321,7 +19369,7 @@ public: for (int i = numThisTime; --i >= 0;) { src += 2; - *left++ = bigEndianShort (src) << 16; + *left++ = ByteOrder::bigEndianShort (src) << 16; src += 2; } } @@ -19329,9 +19377,9 @@ public: { for (int i = numThisTime; --i >= 0;) { - *left++ = bigEndianShort (src) << 16; + *left++ = ByteOrder::bigEndianShort (src) << 16; src += 2; - *right++ = bigEndianShort (src) << 16; + *right++ = ByteOrder::bigEndianShort (src) << 16; src += 2; } } @@ -19340,7 +19388,7 @@ public: { for (int i = numThisTime; --i >= 0;) { - *left++ = bigEndianShort (src) << 16; + *left++ = ByteOrder::bigEndianShort (src) << 16; src += 2; } } @@ -19358,7 +19406,7 @@ public: { for (int i = numThisTime; --i >= 0;) { - *right++ = littleEndian24Bit (src) << 8; + *right++ = ByteOrder::littleEndian24Bit (src) << 8; src += 6; } } @@ -19367,7 +19415,7 @@ public: for (int i = numThisTime; --i >= 0;) { src += 3; - *left++ = littleEndian24Bit (src) << 8; + *left++ = ByteOrder::littleEndian24Bit (src) << 8; src += 3; } } @@ -19375,9 +19423,9 @@ public: { for (int i = numThisTime; --i >= 0;) { - *left++ = littleEndian24Bit (src) << 8; + *left++ = ByteOrder::littleEndian24Bit (src) << 8; src += 3; - *right++ = littleEndian24Bit (src) << 8; + *right++ = ByteOrder::littleEndian24Bit (src) << 8; src += 3; } } @@ -19386,7 +19434,7 @@ public: { for (int i = numThisTime; --i >= 0;) { - *left++ = littleEndian24Bit (src) << 8; + *left++ = ByteOrder::littleEndian24Bit (src) << 8; src += 3; } } @@ -19399,7 +19447,7 @@ public: { for (int i = numThisTime; --i >= 0;) { - *right++ = bigEndian24Bit (src) << 8; + *right++ = ByteOrder::bigEndian24Bit (src) << 8; src += 6; } } @@ -19408,7 +19456,7 @@ public: for (int i = numThisTime; --i >= 0;) { src += 3; - *left++ = bigEndian24Bit (src) << 8; + *left++ = ByteOrder::bigEndian24Bit (src) << 8; src += 3; } } @@ -19416,9 +19464,9 @@ public: { for (int i = numThisTime; --i >= 0;) { - *left++ = bigEndian24Bit (src) << 8; + *left++ = ByteOrder::bigEndian24Bit (src) << 8; src += 3; - *right++ = bigEndian24Bit (src) << 8; + *right++ = ByteOrder::bigEndian24Bit (src) << 8; src += 3; } } @@ -19427,7 +19475,7 @@ public: { for (int i = numThisTime; --i >= 0;) { - *left++ = bigEndian24Bit (src) << 8; + *left++ = ByteOrder::bigEndian24Bit (src) << 8; src += 3; } } @@ -19448,14 +19496,14 @@ public: for (int i = numThisTime; --i >= 0;) { ++src; - *r++ = swapIfBigEndian (*src++); + *r++ = ByteOrder::swapIfBigEndian (*src++); } } else if (r == 0) { for (int i = numThisTime; --i >= 0;) { - *l++ = swapIfBigEndian (*src++); + *l++ = ByteOrder::swapIfBigEndian (*src++); ++src; } } @@ -19463,8 +19511,8 @@ public: { for (int i = numThisTime; --i >= 0;) { - *l++ = swapIfBigEndian (*src++); - *r++ = swapIfBigEndian (*src++); + *l++ = ByteOrder::swapIfBigEndian (*src++); + *r++ = ByteOrder::swapIfBigEndian (*src++); } } } @@ -19472,7 +19520,7 @@ public: { for (int i = numThisTime; --i >= 0;) { - *l++ = swapIfBigEndian (*src++); + *l++ = ByteOrder::swapIfBigEndian (*src++); } } } @@ -19485,14 +19533,14 @@ public: for (int i = numThisTime; --i >= 0;) { ++src; - *r++ = swapIfLittleEndian (*src++); + *r++ = ByteOrder::swapIfLittleEndian (*src++); } } else if (r == 0) { for (int i = numThisTime; --i >= 0;) { - *l++ = swapIfLittleEndian (*src++); + *l++ = ByteOrder::swapIfLittleEndian (*src++); ++src; } } @@ -19500,8 +19548,8 @@ public: { for (int i = numThisTime; --i >= 0;) { - *l++ = swapIfLittleEndian (*src++); - *r++ = swapIfLittleEndian (*src++); + *l++ = ByteOrder::swapIfLittleEndian (*src++); + *r++ = ByteOrder::swapIfLittleEndian (*src++); } } } @@ -19509,7 +19557,7 @@ public: { for (int i = numThisTime; --i >= 0;) { - *l++ = swapIfLittleEndian (*src++); + *l++ = ByteOrder::swapIfLittleEndian (*src++); } } } @@ -19577,6 +19625,8 @@ public: private: AiffAudioFormatReader (const AiffAudioFormatReader&); const AiffAudioFormatReader& operator= (const AiffAudioFormatReader&); + + static inline int chunkName (const char* const name) { return (int) ByteOrder::littleEndianInt (name); } }; class AiffAudioFormatWriter : public AudioFormatWriter @@ -19586,6 +19636,8 @@ class AiffAudioFormatWriter : public AudioFormatWriter int64 headerPosition; bool writeFailed; + static inline int chunkName (const char* const name) { return (int) ByteOrder::littleEndianInt (name); } + AiffAudioFormatWriter (const AiffAudioFormatWriter&); const AiffAudioFormatWriter& operator= (const AiffAudioFormatWriter&); @@ -19670,7 +19722,7 @@ public: const unsigned int chans, const int bits) : AudioFormatWriter (out, - aiffFormatName, + TRANS (aiffFormatName), sampleRate_, chans, bits), @@ -19712,15 +19764,15 @@ public: { for (int i = numSamples; --i >= 0;) { - *b++ = (short) swapIfLittleEndian ((unsigned short) (*left++ >> 16)); - *b++ = (short) swapIfLittleEndian ((unsigned short) (*right++ >> 16)); + *b++ = (short) ByteOrder::swapIfLittleEndian ((uint16) (*left++ >> 16)); + *b++ = (short) ByteOrder::swapIfLittleEndian ((uint16) (*right++ >> 16)); } } else { for (int i = numSamples; --i >= 0;) { - *b++ = (short) swapIfLittleEndian ((unsigned short) (*left++ >> 16)); + *b++ = (short) ByteOrder::swapIfLittleEndian ((uint16) (*left++ >> 16)); } } } @@ -19732,9 +19784,9 @@ public: { for (int i = numSamples; --i >= 0;) { - bigEndian24BitToChars (*left++ >> 8, b); + ByteOrder::bigEndian24BitToChars (*left++ >> 8, b); b += 3; - bigEndian24BitToChars (*right++ >> 8, b); + ByteOrder::bigEndian24BitToChars (*right++ >> 8, b); b += 3; } } @@ -19742,34 +19794,34 @@ public: { for (int i = numSamples; --i >= 0;) { - bigEndian24BitToChars (*left++ >> 8, b); + ByteOrder::bigEndian24BitToChars (*left++ >> 8, b); b += 3; } } } else if (bitsPerSample == 32) { - unsigned int* b = (unsigned int*) buffer; + uint32* b = (uint32*) buffer; if (numChannels > 1) { for (int i = numSamples; --i >= 0;) { - *b++ = swapIfLittleEndian ((unsigned int) *left++); - *b++ = swapIfLittleEndian ((unsigned int) *right++); + *b++ = ByteOrder::swapIfLittleEndian ((uint32) *left++); + *b++ = ByteOrder::swapIfLittleEndian ((uint32) *right++); } } else { for (int i = numSamples; --i >= 0;) { - *b++ = swapIfLittleEndian ((unsigned int) *left++); + *b++ = ByteOrder::swapIfLittleEndian ((uint32) *left++); } } } else if (bitsPerSample == 8) { - char* b = (char*)buffer; + char* b = (char*) buffer; if (numChannels > 1) { @@ -19811,7 +19863,7 @@ public: }; AiffAudioFormat::AiffAudioFormat() - : AudioFormat (aiffFormatName, (const tchar**) aiffExtensions) + : AudioFormat (TRANS (aiffFormatName), (const tchar**) aiffExtensions) { } @@ -20902,8 +20954,8 @@ struct AudioThumbnailDataFormat }; #if JUCE_BIG_ENDIAN - static void swap (int& n) { n = (int) swapByteOrder ((uint32) n); } - static void swap (int64& n) { n = (int64) swapByteOrder ((uint64) n); } + static void swap (int& n) { n = (int) ByteOrder::swap ((uint32) n); } + static void swap (int64& n) { n = (int64) ByteOrder::swap ((uint64) n); } #endif static void swapEndiannessIfNeeded (AudioThumbnailDataFormat* const d) @@ -21527,14 +21579,14 @@ BEGIN_JUCE_NAMESPACE bool juce_OpenQuickTimeMovieFromStream (InputStream* input, Movie& movie, Handle& dataHandle); -#define quickTimeFormatName TRANS("QuickTime file") +static const char* const quickTimeFormatName = "QuickTime file"; static const tchar* const quickTimeExtensions[] = { T(".mov"), T(".mp3"), T(".mp4"), 0 }; class QTAudioReader : public AudioFormatReader { public: QTAudioReader (InputStream* const input_, const int trackNum_) - : AudioFormatReader (input_, quickTimeFormatName), + : AudioFormatReader (input_, TRANS (quickTimeFormatName)), ok (false), movie (0), trackNum (trackNum_), @@ -21796,7 +21848,7 @@ private: }; QuickTimeAudioFormat::QuickTimeAudioFormat() - : AudioFormat (quickTimeFormatName, (const tchar**) quickTimeExtensions) + : AudioFormat (TRANS (quickTimeFormatName), (const tchar**) quickTimeExtensions) { } @@ -21858,7 +21910,7 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE -#define wavFormatName TRANS("WAV file") +static const char* const wavFormatName = "WAV file"; static const tchar* const wavExtensions[] = { T(".wav"), T(".bwf"), 0 }; const tchar* const WavAudioFormat::bwavDescription = T("bwav description"); @@ -21920,8 +21972,8 @@ struct BWAVChunk values.set (WavAudioFormat::bwavOriginationDate, String::fromUTF8 (originationDate, 10)); values.set (WavAudioFormat::bwavOriginationTime, String::fromUTF8 (originationTime, 8)); - const uint32 timeLow = swapIfBigEndian (timeRefLow); - const uint32 timeHigh = swapIfBigEndian (timeRefHigh); + const uint32 timeLow = ByteOrder::swapIfBigEndian (timeRefLow); + const uint32 timeHigh = ByteOrder::swapIfBigEndian (timeRefHigh); const int64 time = (((int64)timeHigh) << 32) + timeLow; values.set (WavAudioFormat::bwavTimeReference, String (time)); @@ -21945,8 +21997,8 @@ struct BWAVChunk values [WavAudioFormat::bwavOriginationTime].copyToUTF8 (b->originationTime, 9); const int64 time = values [WavAudioFormat::bwavTimeReference].getLargeIntValue(); - b->timeRefLow = swapIfBigEndian ((uint32) (time & 0xffffffff)); - b->timeRefHigh = swapIfBigEndian ((uint32) (time >> 32)); + b->timeRefLow = ByteOrder::swapIfBigEndian ((uint32) (time & 0xffffffff)); + b->timeRefHigh = ByteOrder::swapIfBigEndian ((uint32) (time >> 32)); values [WavAudioFormat::bwavCodingHistory].copyToUTF8 (b->codingHistory); @@ -21990,27 +22042,27 @@ struct SMPLChunk void copyTo (StringPairArray& values, const int totalSize) const { - values.set (T("Manufacturer"), String (swapIfBigEndian (manufacturer))); - values.set (T("Product"), String (swapIfBigEndian (product))); - values.set (T("SamplePeriod"), String (swapIfBigEndian (samplePeriod))); - values.set (T("MidiUnityNote"), String (swapIfBigEndian (midiUnityNote))); - values.set (T("MidiPitchFraction"), String (swapIfBigEndian (midiPitchFraction))); - values.set (T("SmpteFormat"), String (swapIfBigEndian (smpteFormat))); - values.set (T("SmpteOffset"), String (swapIfBigEndian (smpteOffset))); - values.set (T("NumSampleLoops"), String (swapIfBigEndian (numSampleLoops))); - values.set (T("SamplerData"), String (swapIfBigEndian (samplerData))); + values.set (T("Manufacturer"), String (ByteOrder::swapIfBigEndian (manufacturer))); + values.set (T("Product"), String (ByteOrder::swapIfBigEndian (product))); + values.set (T("SamplePeriod"), String (ByteOrder::swapIfBigEndian (samplePeriod))); + values.set (T("MidiUnityNote"), String (ByteOrder::swapIfBigEndian (midiUnityNote))); + values.set (T("MidiPitchFraction"), String (ByteOrder::swapIfBigEndian (midiPitchFraction))); + values.set (T("SmpteFormat"), String (ByteOrder::swapIfBigEndian (smpteFormat))); + values.set (T("SmpteOffset"), String (ByteOrder::swapIfBigEndian (smpteOffset))); + values.set (T("NumSampleLoops"), String (ByteOrder::swapIfBigEndian (numSampleLoops))); + values.set (T("SamplerData"), String (ByteOrder::swapIfBigEndian (samplerData))); for (uint32 i = 0; i < numSampleLoops; ++i) { if ((uint8*) (loops + (i + 1)) > ((uint8*) this) + totalSize) break; - values.set (String::formatted (T("Loop%dIdentifier"), i), String (swapIfBigEndian (loops[i].identifier))); - values.set (String::formatted (T("Loop%dType"), i), String (swapIfBigEndian (loops[i].type))); - values.set (String::formatted (T("Loop%dStart"), i), String (swapIfBigEndian (loops[i].start))); - values.set (String::formatted (T("Loop%dEnd"), i), String (swapIfBigEndian (loops[i].end))); - values.set (String::formatted (T("Loop%dFraction"), i), String (swapIfBigEndian (loops[i].fraction))); - values.set (String::formatted (T("Loop%dPlayCount"), i), String (swapIfBigEndian (loops[i].playCount))); + values.set (String::formatted (T("Loop%dIdentifier"), i), String (ByteOrder::swapIfBigEndian (loops[i].identifier))); + values.set (String::formatted (T("Loop%dType"), i), String (ByteOrder::swapIfBigEndian (loops[i].type))); + values.set (String::formatted (T("Loop%dStart"), i), String (ByteOrder::swapIfBigEndian (loops[i].start))); + values.set (String::formatted (T("Loop%dEnd"), i), String (ByteOrder::swapIfBigEndian (loops[i].end))); + values.set (String::formatted (T("Loop%dFraction"), i), String (ByteOrder::swapIfBigEndian (loops[i].fraction))); + values.set (String::formatted (T("Loop%dPlayCount"), i), String (ByteOrder::swapIfBigEndian (loops[i].playCount))); } } } PACKED; @@ -22021,14 +22073,13 @@ struct SMPLChunk #undef PACKED -#undef chunkName -#define chunkName(a) ((int) littleEndianInt(a)) - class WavAudioFormatReader : public AudioFormatReader { int bytesPerFrame; int64 dataChunkStart, dataLength; + static inline int chunkName (const char* const name) { return (int) ByteOrder::littleEndianInt (name); } + WavAudioFormatReader (const WavAudioFormatReader&); const WavAudioFormatReader& operator= (const WavAudioFormatReader&); @@ -22036,7 +22087,7 @@ public: int64 bwavChunkStart, bwavSize; WavAudioFormatReader (InputStream* const in) - : AudioFormatReader (in, wavFormatName), + : AudioFormatReader (in, TRANS (wavFormatName)), dataLength (0), bwavChunkStart (0), bwavSize (0) @@ -22167,14 +22218,14 @@ public: for (int i = numThisTime; --i >= 0;) { ++src; - *right++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16; + *right++ = (int) ByteOrder::swapIfBigEndian ((unsigned short) *src++) << 16; } } else if (right == 0) { for (int i = numThisTime; --i >= 0;) { - *left++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16; + *left++ = (int) ByteOrder::swapIfBigEndian ((unsigned short) *src++) << 16; ++src; } } @@ -22182,8 +22233,8 @@ public: { for (int i = numThisTime; --i >= 0;) { - *left++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16; - *right++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16; + *left++ = (int) ByteOrder::swapIfBigEndian ((unsigned short) *src++) << 16; + *right++ = (int) ByteOrder::swapIfBigEndian ((unsigned short) *src++) << 16; } } } @@ -22191,7 +22242,7 @@ public: { for (int i = numThisTime; --i >= 0;) { - *left++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16; + *left++ = (int) ByteOrder::swapIfBigEndian ((unsigned short) *src++) << 16; } } } @@ -22206,7 +22257,7 @@ public: for (int i = numThisTime; --i >= 0;) { src += 3; - *right++ = littleEndian24Bit (src) << 8; + *right++ = ByteOrder::littleEndian24Bit (src) << 8; src += 3; } } @@ -22214,7 +22265,7 @@ public: { for (int i = numThisTime; --i >= 0;) { - *left++ = littleEndian24Bit (src) << 8; + *left++ = ByteOrder::littleEndian24Bit (src) << 8; src += 6; } } @@ -22222,9 +22273,9 @@ public: { for (int i = 0; i < numThisTime; ++i) { - *left++ = littleEndian24Bit (src) << 8; + *left++ = ByteOrder::littleEndian24Bit (src) << 8; src += 3; - *right++ = littleEndian24Bit (src) << 8; + *right++ = ByteOrder::littleEndian24Bit (src) << 8; src += 3; } } @@ -22233,7 +22284,7 @@ public: { for (int i = 0; i < numThisTime; ++i) { - *left++ = littleEndian24Bit (src) << 8; + *left++ = ByteOrder::littleEndian24Bit (src) << 8; src += 3; } } @@ -22251,14 +22302,14 @@ public: for (int i = numThisTime; --i >= 0;) { ++src; - *r++ = swapIfBigEndian (*src++); + *r++ = ByteOrder::swapIfBigEndian (*src++); } } else if (r == 0) { for (int i = numThisTime; --i >= 0;) { - *l++ = swapIfBigEndian (*src++); + *l++ = ByteOrder::swapIfBigEndian (*src++); ++src; } } @@ -22266,8 +22317,8 @@ public: { for (int i = numThisTime; --i >= 0;) { - *l++ = swapIfBigEndian (*src++); - *r++ = swapIfBigEndian (*src++); + *l++ = ByteOrder::swapIfBigEndian (*src++); + *r++ = ByteOrder::swapIfBigEndian (*src++); } } } @@ -22275,7 +22326,7 @@ public: { for (int i = numThisTime; --i >= 0;) { - *l++ = swapIfBigEndian (*src++); + *l++ = ByteOrder::swapIfBigEndian (*src++); } } @@ -22347,6 +22398,8 @@ class WavAudioFormatWriter : public AudioFormatWriter int64 headerPosition; bool writeFailed; + static inline int chunkName (const char* const name) { return (int) ByteOrder::littleEndianInt (name); } + WavAudioFormatWriter (const WavAudioFormatWriter&); const WavAudioFormatWriter& operator= (const WavAudioFormatWriter&); @@ -22396,7 +22449,7 @@ public: const int bits, const StringPairArray& metadataValues) : AudioFormatWriter (out, - wavFormatName, + TRANS (wavFormatName), sampleRate_, numChannels_, bits), @@ -22438,15 +22491,15 @@ public: { for (int i = numSamples; --i >= 0;) { - *b++ = (short) swapIfBigEndian ((unsigned short) (*left++ >> 16)); - *b++ = (short) swapIfBigEndian ((unsigned short) (*right++ >> 16)); + *b++ = (short) ByteOrder::swapIfBigEndian ((unsigned short) (*left++ >> 16)); + *b++ = (short) ByteOrder::swapIfBigEndian ((unsigned short) (*right++ >> 16)); } } else { for (int i = numSamples; --i >= 0;) { - *b++ = (short) swapIfBigEndian ((unsigned short) (*left++ >> 16)); + *b++ = (short) ByteOrder::swapIfBigEndian ((unsigned short) (*left++ >> 16)); } } } @@ -22458,9 +22511,9 @@ public: { for (int i = numSamples; --i >= 0;) { - littleEndian24BitToChars ((*left++) >> 8, b); + ByteOrder::littleEndian24BitToChars ((*left++) >> 8, b); b += 3; - littleEndian24BitToChars ((*right++) >> 8, b); + ByteOrder::littleEndian24BitToChars ((*right++) >> 8, b); b += 3; } } @@ -22468,7 +22521,7 @@ public: { for (int i = numSamples; --i >= 0;) { - littleEndian24BitToChars ((*left++) >> 8, b); + ByteOrder::littleEndian24BitToChars ((*left++) >> 8, b); b += 3; } } @@ -22481,15 +22534,15 @@ public: { for (int i = numSamples; --i >= 0;) { - *b++ = swapIfBigEndian ((unsigned int) *left++); - *b++ = swapIfBigEndian ((unsigned int) *right++); + *b++ = ByteOrder::swapIfBigEndian ((unsigned int) *left++); + *b++ = ByteOrder::swapIfBigEndian ((unsigned int) *right++); } } else { for (int i = numSamples; --i >= 0;) { - *b++ = swapIfBigEndian ((unsigned int) *left++); + *b++ = ByteOrder::swapIfBigEndian ((unsigned int) *left++); } } } @@ -22537,7 +22590,7 @@ public: }; WavAudioFormat::WavAudioFormat() - : AudioFormat (wavFormatName, (const tchar**) wavExtensions) + : AudioFormat (TRANS (wavFormatName), (const tchar**) wavExtensions) { } @@ -25345,7 +25398,7 @@ void AudioDataConverters::convertFloatToInt16LE (const float* source, void* dest { for (int i = 0; i < numSamples; ++i) { - *(uint16*)intData = swapIfBigEndian ((uint16) (short) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); + *(uint16*)intData = ByteOrder::swapIfBigEndian ((uint16) (short) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); intData += destBytesPerSample; } } @@ -25356,7 +25409,7 @@ void AudioDataConverters::convertFloatToInt16LE (const float* source, void* dest for (int i = numSamples; --i >= 0;) { intData -= destBytesPerSample; - *(uint16*)intData = swapIfBigEndian ((uint16) (short) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); + *(uint16*)intData = ByteOrder::swapIfBigEndian ((uint16) (short) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); } } } @@ -25370,7 +25423,7 @@ void AudioDataConverters::convertFloatToInt16BE (const float* source, void* dest { for (int i = 0; i < numSamples; ++i) { - *(uint16*)intData = swapIfLittleEndian ((uint16) (short) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); + *(uint16*) intData = ByteOrder::swapIfLittleEndian ((uint16) (short) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); intData += destBytesPerSample; } } @@ -25381,7 +25434,7 @@ void AudioDataConverters::convertFloatToInt16BE (const float* source, void* dest for (int i = numSamples; --i >= 0;) { intData -= destBytesPerSample; - *(uint16*)intData = swapIfLittleEndian ((uint16) (short) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); + *(uint16*)intData = ByteOrder::swapIfLittleEndian ((uint16) (short) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); } } } @@ -25395,7 +25448,7 @@ void AudioDataConverters::convertFloatToInt24LE (const float* source, void* dest { for (int i = 0; i < numSamples; ++i) { - littleEndian24BitToChars ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i])), intData); + ByteOrder::littleEndian24BitToChars ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i])), intData); intData += destBytesPerSample; } } @@ -25406,7 +25459,7 @@ void AudioDataConverters::convertFloatToInt24LE (const float* source, void* dest for (int i = numSamples; --i >= 0;) { intData -= destBytesPerSample; - littleEndian24BitToChars ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i])), intData); + ByteOrder::littleEndian24BitToChars ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i])), intData); } } } @@ -25420,7 +25473,7 @@ void AudioDataConverters::convertFloatToInt24BE (const float* source, void* dest { for (int i = 0; i < numSamples; ++i) { - bigEndian24BitToChars ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i])), intData); + ByteOrder::bigEndian24BitToChars ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i])), intData); intData += destBytesPerSample; } } @@ -25431,7 +25484,7 @@ void AudioDataConverters::convertFloatToInt24BE (const float* source, void* dest for (int i = numSamples; --i >= 0;) { intData -= destBytesPerSample; - bigEndian24BitToChars ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i])), intData); + ByteOrder::bigEndian24BitToChars ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i])), intData); } } } @@ -25445,7 +25498,7 @@ void AudioDataConverters::convertFloatToInt32LE (const float* source, void* dest { for (int i = 0; i < numSamples; ++i) { - *(uint32*)intData = swapIfBigEndian ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); + *(uint32*)intData = ByteOrder::swapIfBigEndian ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); intData += destBytesPerSample; } } @@ -25456,7 +25509,7 @@ void AudioDataConverters::convertFloatToInt32LE (const float* source, void* dest for (int i = numSamples; --i >= 0;) { intData -= destBytesPerSample; - *(uint32*)intData = swapIfBigEndian ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); + *(uint32*)intData = ByteOrder::swapIfBigEndian ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); } } } @@ -25470,7 +25523,7 @@ void AudioDataConverters::convertFloatToInt32BE (const float* source, void* dest { for (int i = 0; i < numSamples; ++i) { - *(uint32*)intData = swapIfLittleEndian ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); + *(uint32*)intData = ByteOrder::swapIfLittleEndian ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); intData += destBytesPerSample; } } @@ -25481,7 +25534,7 @@ void AudioDataConverters::convertFloatToInt32BE (const float* source, void* dest for (int i = numSamples; --i >= 0;) { intData -= destBytesPerSample; - *(uint32*)intData = swapIfLittleEndian ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); + *(uint32*)intData = ByteOrder::swapIfLittleEndian ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); } } } @@ -25494,10 +25547,10 @@ void AudioDataConverters::convertFloatToFloat32LE (const float* source, void* de for (int i = 0; i < numSamples; ++i) { - *(float*)d = source[i]; + *(float*) d = source[i]; #if JUCE_BIG_ENDIAN - *(uint32*)d = swapByteOrder (*(uint32*)d); + *(uint32*) d = ByteOrder::swap (*(uint32*) d); #endif d += destBytesPerSample; @@ -25512,10 +25565,10 @@ void AudioDataConverters::convertFloatToFloat32BE (const float* source, void* de for (int i = 0; i < numSamples; ++i) { - *(float*)d = source[i]; + *(float*) d = source[i]; #if JUCE_LITTLE_ENDIAN - *(uint32*)d = swapByteOrder (*(uint32*)d); + *(uint32*) d = ByteOrder::swap (*(uint32*) d); #endif d += destBytesPerSample; @@ -25531,7 +25584,7 @@ void AudioDataConverters::convertInt16LEToFloat (const void* const source, float { for (int i = 0; i < numSamples; ++i) { - dest[i] = scale * (short) swapIfBigEndian (*(uint16*)intData); + dest[i] = scale * (short) ByteOrder::swapIfBigEndian (*(uint16*)intData); intData += srcBytesPerSample; } } @@ -25542,7 +25595,7 @@ void AudioDataConverters::convertInt16LEToFloat (const void* const source, float for (int i = numSamples; --i >= 0;) { intData -= srcBytesPerSample; - dest[i] = scale * (short) swapIfBigEndian (*(uint16*)intData); + dest[i] = scale * (short) ByteOrder::swapIfBigEndian (*(uint16*)intData); } } } @@ -25556,7 +25609,7 @@ void AudioDataConverters::convertInt16BEToFloat (const void* const source, float { for (int i = 0; i < numSamples; ++i) { - dest[i] = scale * (short) swapIfLittleEndian (*(uint16*)intData); + dest[i] = scale * (short) ByteOrder::swapIfLittleEndian (*(uint16*)intData); intData += srcBytesPerSample; } } @@ -25567,7 +25620,7 @@ void AudioDataConverters::convertInt16BEToFloat (const void* const source, float for (int i = numSamples; --i >= 0;) { intData -= srcBytesPerSample; - dest[i] = scale * (short) swapIfLittleEndian (*(uint16*)intData); + dest[i] = scale * (short) ByteOrder::swapIfLittleEndian (*(uint16*)intData); } } } @@ -25581,7 +25634,7 @@ void AudioDataConverters::convertInt24LEToFloat (const void* const source, float { for (int i = 0; i < numSamples; ++i) { - dest[i] = scale * (short) littleEndian24Bit (intData); + dest[i] = scale * (short) ByteOrder::littleEndian24Bit (intData); intData += srcBytesPerSample; } } @@ -25592,7 +25645,7 @@ void AudioDataConverters::convertInt24LEToFloat (const void* const source, float for (int i = numSamples; --i >= 0;) { intData -= srcBytesPerSample; - dest[i] = scale * (short) littleEndian24Bit (intData); + dest[i] = scale * (short) ByteOrder::littleEndian24Bit (intData); } } } @@ -25606,7 +25659,7 @@ void AudioDataConverters::convertInt24BEToFloat (const void* const source, float { for (int i = 0; i < numSamples; ++i) { - dest[i] = scale * (short) bigEndian24Bit (intData); + dest[i] = scale * (short) ByteOrder::bigEndian24Bit (intData); intData += srcBytesPerSample; } } @@ -25617,7 +25670,7 @@ void AudioDataConverters::convertInt24BEToFloat (const void* const source, float for (int i = numSamples; --i >= 0;) { intData -= srcBytesPerSample; - dest[i] = scale * (short) bigEndian24Bit (intData); + dest[i] = scale * (short) ByteOrder::bigEndian24Bit (intData); } } } @@ -25631,7 +25684,7 @@ void AudioDataConverters::convertInt32LEToFloat (const void* const source, float { for (int i = 0; i < numSamples; ++i) { - dest[i] = scale * (int) swapIfBigEndian (*(uint32*) intData); + dest[i] = scale * (int) ByteOrder::swapIfBigEndian (*(uint32*) intData); intData += srcBytesPerSample; } } @@ -25642,7 +25695,7 @@ void AudioDataConverters::convertInt32LEToFloat (const void* const source, float for (int i = numSamples; --i >= 0;) { intData -= srcBytesPerSample; - dest[i] = scale * (int) swapIfBigEndian (*(uint32*) intData); + dest[i] = scale * (int) ByteOrder::swapIfBigEndian (*(uint32*) intData); } } } @@ -25656,7 +25709,7 @@ void AudioDataConverters::convertInt32BEToFloat (const void* const source, float { for (int i = 0; i < numSamples; ++i) { - dest[i] = scale * (int) (swapIfLittleEndian (*(uint32*) intData)); + dest[i] = scale * (int) ByteOrder::swapIfLittleEndian (*(uint32*) intData); intData += srcBytesPerSample; } } @@ -25667,7 +25720,7 @@ void AudioDataConverters::convertInt32BEToFloat (const void* const source, float for (int i = numSamples; --i >= 0;) { intData -= srcBytesPerSample; - dest[i] = scale * (int) (swapIfLittleEndian (*(uint32*) intData)); + dest[i] = scale * (int) ByteOrder::swapIfLittleEndian (*(uint32*) intData); } } } @@ -25682,7 +25735,7 @@ void AudioDataConverters::convertFloat32LEToFloat (const void* const source, flo #if JUCE_BIG_ENDIAN uint32* const d = (uint32*) (dest + i); - *d = swapByteOrder (*d); + *d = ByteOrder::swap (*d); #endif s += srcBytesPerSample; @@ -25699,7 +25752,7 @@ void AudioDataConverters::convertFloat32BEToFloat (const void* const source, flo #if JUCE_LITTLE_ENDIAN uint32* const d = (uint32*) (dest + i); - *d = swapByteOrder (*d); + *d = ByteOrder::swap (*d); #endif s += srcBytesPerSample; @@ -27111,21 +27164,21 @@ static bool parseMidiHeader (const char* &data, short& fileType, short& numberOfTracks) { - unsigned int ch = (int) bigEndianInt (data); + unsigned int ch = (int) ByteOrder::bigEndianInt (data); data += 4; - if (ch != bigEndianInt ("MThd")) + if (ch != ByteOrder::bigEndianInt ("MThd")) { bool ok = false; - if (ch == bigEndianInt ("RIFF")) + if (ch == ByteOrder::bigEndianInt ("RIFF")) { for (int i = 0; i < 8; ++i) { - ch = bigEndianInt (data); + ch = ByteOrder::bigEndianInt (data); data += 4; - if (ch == bigEndianInt ("MThd")) + if (ch == ByteOrder::bigEndianInt ("MThd")) { ok = true; break; @@ -27137,13 +27190,13 @@ static bool parseMidiHeader (const char* &data, return false; } - unsigned int bytesRemaining = bigEndianInt (data); + unsigned int bytesRemaining = ByteOrder::bigEndianInt (data); data += 4; - fileType = (short)bigEndianShort (data); + fileType = (short) ByteOrder::bigEndianShort (data); data += 2; - numberOfTracks = (short)bigEndianShort (data); + numberOfTracks = (short) ByteOrder::bigEndianShort (data); data += 2; - timeFormat = (short)bigEndianShort (data); + timeFormat = (short) ByteOrder::bigEndianShort (data); data += 2; bytesRemaining -= 6; data += bytesRemaining; @@ -27173,9 +27226,9 @@ bool MidiFile::readFrom (InputStream& sourceStream) while (size > 0 && track < expectedTracks) { - const int chunkType = (int)bigEndianInt (d); + const int chunkType = (int) ByteOrder::bigEndianInt (d); d += 4; - const int chunkSize = (int)bigEndianInt (d); + const int chunkSize = (int) ByteOrder::bigEndianInt (d); d += 4; if (chunkSize <= 0) @@ -27184,7 +27237,7 @@ bool MidiFile::readFrom (InputStream& sourceStream) if (size < 0) return false; - if (chunkType == (int)bigEndianInt ("MTrk")) + if (chunkType == (int) ByteOrder::bigEndianInt ("MTrk")) { readNextTrack (d, chunkSize); } @@ -27369,10 +27422,10 @@ static void writeVariableLengthInt (OutputStream& out, unsigned int v) bool MidiFile::writeTo (OutputStream& out) { - out.writeIntBigEndian ((int) bigEndianInt ("MThd")); + out.writeIntBigEndian ((int) ByteOrder::bigEndianInt ("MThd")); out.writeIntBigEndian (6); out.writeShortBigEndian (1); // type - out.writeShortBigEndian (tracks.size()); + out.writeShortBigEndian ((short) tracks.size()); out.writeShortBigEndian (timeFormat); for (int i = 0; i < tracks.size(); ++i) @@ -27424,7 +27477,7 @@ void MidiFile::writeTrack (OutputStream& mainOut, out.write (m.getRawData(), m.getRawDataSize()); - mainOut.writeIntBigEndian ((int)bigEndianInt ("MTrk")); + mainOut.writeIntBigEndian ((int) ByteOrder::bigEndianInt ("MTrk")); mainOut.writeIntBigEndian (out.getDataSize()); mainOut.write (out.getData(), out.getDataSize()); } @@ -31929,20 +31982,26 @@ struct fxProgramSet char chunk[8]; // variable }; -#ifdef JUCE_LITTLE_ENDIAN - static long vst_swap (const long x) throw() { return (long) swapByteOrder ((uint32) x); } +static long vst_swap (const long x) throw() +{ + #ifdef JUCE_LITTLE_ENDIAN + return (long) ByteOrder::swap ((uint32) x); + #else + return x; + #endif +} - static float vst_swapFloat (const float x) throw() - { - union { uint32 asInt; float asFloat; } n; - n.asFloat = x; - n.asInt = swapByteOrder (n.asInt); - return n.asFloat; - } -#else - #define vst_swap(x) (x) - #define vst_swapFloat(x) (x) -#endif +static float vst_swapFloat (const float x) throw() +{ + #ifdef JUCE_LITTLE_ENDIAN + union { uint32 asInt; float asFloat; } n; + n.asFloat = x; + n.asInt = ByteOrder::swap (n.asInt); + return n.asFloat; + #else + return x; + #endif +} typedef AEffect* (*MainCall) (audioMasterCallback); @@ -34953,8 +35012,8 @@ void AudioProcessor::copyXmlToBinary (const XmlElement& xml, destData.setSize (stringLength + 10); char* const d = (char*) destData.getData(); - *(uint32*) d = swapIfBigEndian ((const uint32) magicXmlNumber); - *(uint32*) (d + 4) = swapIfBigEndian ((const uint32) stringLength); + *(uint32*) d = ByteOrder::swapIfBigEndian ((const uint32) magicXmlNumber); + *(uint32*) (d + 4) = ByteOrder::swapIfBigEndian ((const uint32) stringLength); xmlString.copyToBuffer (d + 8, stringLength); } @@ -34963,9 +35022,9 @@ XmlElement* AudioProcessor::getXmlFromBinary (const void* data, const int sizeInBytes) { if (sizeInBytes > 8 - && littleEndianInt ((const char*) data) == magicXmlNumber) + && ByteOrder::littleEndianInt ((const char*) data) == magicXmlNumber) { - const uint32 stringLength = littleEndianInt (((const char*) data) + 4); + const uint32 stringLength = ByteOrder::littleEndianInt (((const char*) data) + 4); if (stringLength > 0) { @@ -37580,8 +37639,8 @@ const String InterprocessConnection::getConnectedHostName() const bool InterprocessConnection::sendMessage (const MemoryBlock& message) { uint32 messageHeader[2]; - messageHeader [0] = swapIfBigEndian (magicMessageHeader); - messageHeader [1] = swapIfBigEndian ((uint32) message.getSize()); + messageHeader [0] = ByteOrder::swapIfBigEndian (magicMessageHeader); + messageHeader [1] = ByteOrder::swapIfBigEndian ((uint32) message.getSize()); MemoryBlock messageData (sizeof (messageHeader) + message.getSize()); messageData.copyFrom (messageHeader, 0, sizeof (messageHeader)); @@ -37696,9 +37755,9 @@ bool InterprocessConnection::readNextMessageInt() : pipe->read (messageHeader, sizeof (messageHeader), pipeReceiveMessageTimeout); if (bytes == sizeof (messageHeader) - && swapIfBigEndian (messageHeader[0]) == magicMessageHeader) + && ByteOrder::swapIfBigEndian (messageHeader[0]) == magicMessageHeader) { - const int bytesInMessage = (int) swapIfBigEndian (messageHeader[1]); + const int bytesInMessage = (int) ByteOrder::swapIfBigEndian (messageHeader[1]); if (bytesInMessage > 0 && bytesInMessage < maximumMessageSize) { @@ -42691,7 +42750,7 @@ Button::Button (const String& name) commandID (0), connectedEdgeFlags (0), buttonState (buttonNormal), - isOn (false), + lastToggleState (false), clickTogglesState (false), needsToRelease (false), needsRepainting (false), @@ -42700,10 +42759,13 @@ Button::Button (const String& name) generateTooltip (false) { setWantsKeyboardFocus (true); + isOn.addListener (this); } Button::~Button() { + isOn.removeListener (this); + if (commandManagerToUse != 0) commandManagerToUse->removeListener (this); @@ -42738,10 +42800,12 @@ const String Button::getTooltip() { const String key (keyPresses.getReference(i).getTextDescription()); + tt << " ["; + if (key.length() == 1) - tt << " [" << TRANS("shortcut") << ": '" << key << "']"; + tt << TRANS("shortcut") << ": '" << key << "']"; else - tt << " [" << key << ']'; + tt << key << ']'; } return tt; @@ -42762,17 +42826,18 @@ void Button::setConnectedEdges (const int connectedEdgeFlags_) throw() void Button::setToggleState (const bool shouldBeOn, const bool sendChangeNotification) { - if (shouldBeOn != isOn) + if (shouldBeOn != lastToggleState) { const ComponentDeletionWatcher deletionWatcher (this); isOn = shouldBeOn; + lastToggleState = shouldBeOn; repaint(); if (sendChangeNotification) sendClickMessage (ModifierKeys()); - if ((! deletionWatcher.hasBeenDeleted()) && isOn) + if ((! deletionWatcher.hasBeenDeleted()) && getToggleState()) turnOffOtherButtonsInGroup (sendChangeNotification); } } @@ -42793,13 +42858,19 @@ bool Button::getClickingTogglesState() const throw() return clickTogglesState; } +void Button::valueChanged (Value& value) +{ + if (value.refersToSameSourceAs (isOn)) + setToggleState (isOn.getValue(), true); +} + void Button::setRadioGroupId (const int newGroupId) { if (radioGroupId != newGroupId) { radioGroupId = newGroupId; - if (isOn) + if (getToggleState()) turnOffOtherButtonsInGroup (true); } } @@ -42931,7 +43002,7 @@ void Button::triggerClick() void Button::internalClickCallback (const ModifierKeys& modifiers) { if (clickTogglesState) - setToggleState ((radioGroupId != 0) || ! isOn, false); + setToggleState ((radioGroupId != 0) || ! getToggleState(), false); sendClickMessage (modifiers); } @@ -44579,7 +44650,7 @@ const String CodeDocument::getTextBetween (const Position& start, const Position String result; result.preallocateStorage (end.getPosition() - start.getPosition() + 4); - tchar* dest = (tchar*) (const tchar*) result; + String::Concatenator concatenator (result); const int maxLine = jmin (lines.size() - 1, endLine); @@ -44591,26 +44662,19 @@ const String CodeDocument::getTextBetween (const Position& start, const Position if (i == startLine) { const int index = start.getIndexInLine(); - len -= index; - line->line.substring (index).copyToBuffer (dest, len); - dest += len; + concatenator.append (line->line.substring (index, len)); } else if (i == endLine) { len = end.getIndexInLine(); - line->line.copyToBuffer (dest, len); - dest += len; + concatenator.append (line->line.substring (0, len)); } else { - line->line.copyToBuffer (dest, len); - dest += len; + concatenator.append (line->line); } } - // check we preallocated enough space.. - jassert ((dest - (const tchar*) result) <= end.getPosition() - start.getPosition()); - return result; } @@ -49204,9 +49268,9 @@ void Slider::valueChanged (Value& value) setValue (currentValue.getValue(), false, false); } else if (value.refersToSameSourceAs (valueMin)) - setMinValue (valueMin.getValue(), false, false); + setMinValue (valueMin.getValue(), false, false, true); else if (value.refersToSameSourceAs (valueMax)) - setMaxValue (valueMax.getValue(), false, false); + setMaxValue (valueMax.getValue(), false, false, true); } double Slider::getValue() const @@ -49243,7 +49307,7 @@ void Slider::setValue (double newValue, valueBox->hideEditor (true); lastCurrentValue = newValue; - currentValue = var (newValue); + currentValue = newValue; updateText(); repaint(); @@ -49293,10 +49357,10 @@ void Slider::setMinValue (double newValue, const bool sendUpdateMessage, const b } else { - if (allowNudgingOfOtherValues && newValue > (double) currentValue.getValue()) + if (allowNudgingOfOtherValues && newValue > lastCurrentValue) setValue (newValue, sendUpdateMessage, sendMessageSynchronously); - newValue = jmin ((double) currentValue.getValue(), newValue); + newValue = jmin (lastCurrentValue, newValue); } if (lastValueMin != newValue) @@ -49333,10 +49397,10 @@ void Slider::setMaxValue (double newValue, const bool sendUpdateMessage, const b } else { - if (allowNudgingOfOtherValues && newValue < (double) currentValue.getValue()) + if (allowNudgingOfOtherValues && newValue < lastCurrentValue) setValue (newValue, sendUpdateMessage, sendMessageSynchronously); - newValue = jmax ((double) currentValue.getValue(), newValue); + newValue = jmax (lastCurrentValue, newValue); } if (lastValueMax != newValue) @@ -49566,7 +49630,7 @@ void Slider::paint (Graphics& g) { if (style == Rotary || style == RotaryHorizontalDrag || style == RotaryVerticalDrag) { - const float sliderPos = (float) valueToProportionOfLength (currentValue.getValue()); + const float sliderPos = (float) valueToProportionOfLength (lastCurrentValue); jassert (sliderPos >= 0 && sliderPos <= 1.0f); getLookAndFeel().drawRotarySlider (g, @@ -49585,9 +49649,9 @@ void Slider::paint (Graphics& g) sliderRect.getY(), sliderRect.getWidth(), sliderRect.getHeight(), - getLinearSliderPos (currentValue.getValue()), - getLinearSliderPos (valueMin.getValue()), - getLinearSliderPos (valueMax.getValue()), + getLinearSliderPos (lastCurrentValue), + getLinearSliderPos (lastValueMin), + getLinearSliderPos (lastValueMax), style, *this); } @@ -51632,10 +51696,10 @@ struct TextAtom float width; uint16 numChars; - bool isWhitespace() const throw() { return CharacterFunctions::isWhitespace (atomText[0]); } - bool isNewLine() const throw() { return atomText[0] == T('\r') || atomText[0] == T('\n'); } + bool isWhitespace() const { return CharacterFunctions::isWhitespace (atomText[0]); } + bool isNewLine() const { return atomText[0] == T('\r') || atomText[0] == T('\n'); } - const String getText (const tchar passwordCharacter) const throw() + const String getText (const tchar passwordCharacter) const { if (passwordCharacter == 0) return atomText; @@ -51644,7 +51708,7 @@ struct TextAtom atomText.length()); } - const String getTrimmedText (const tchar passwordCharacter) const throw() + const String getTrimmedText (const tchar passwordCharacter) const { if (passwordCharacter == 0) return atomText.substring (0, numChars); @@ -51663,7 +51727,7 @@ public: UniformTextSection (const String& text, const Font& font_, const Colour& colour_, - const tchar passwordCharacter) throw() + const tchar passwordCharacter) : font (font_), colour (colour_), atoms (64) @@ -51671,7 +51735,7 @@ public: initialiseAtoms (text, passwordCharacter); } - UniformTextSection (const UniformTextSection& other) throw() + UniformTextSection (const UniformTextSection& other) : font (other.font), colour (other.colour), atoms (64) @@ -51680,12 +51744,12 @@ public: atoms.add (new TextAtom (*(const TextAtom*) other.atoms.getUnchecked(i))); } - ~UniformTextSection() throw() + ~UniformTextSection() { // (no need to delete the atoms, as they're explicitly deleted by the caller) } - void clear() throw() + void clear() { for (int i = atoms.size(); --i >= 0;) delete getAtom(i); @@ -51693,17 +51757,17 @@ public: atoms.clear(); } - int getNumAtoms() const throw() + int getNumAtoms() const { return atoms.size(); } - TextAtom* getAtom (const int index) const throw() + TextAtom* getAtom (const int index) const { return (TextAtom*) atoms.getUnchecked (index); } - void append (const UniformTextSection& other, const tchar passwordCharacter) throw() + void append (const UniformTextSection& other, const tchar passwordCharacter) { if (other.atoms.size() > 0) { @@ -51736,7 +51800,7 @@ public: } UniformTextSection* split (const int indexToBreakAt, - const tchar passwordCharacter) throw() + const tchar passwordCharacter) { UniformTextSection* const section2 = new UniformTextSection (String::empty, font, colour, @@ -51790,96 +51854,50 @@ public: return section2; } - const String getAllText() const throw() + void appendAllText (String::Concatenator& concatenator) const { - String s; - s.preallocateStorage (getTotalLength()); - - tchar* endOfString = (tchar*) &(s[0]); - for (int i = 0; i < atoms.size(); ++i) - { - const TextAtom* const atom = getAtom(i); - - memcpy (endOfString, &(atom->atomText[0]), atom->numChars * sizeof (tchar)); - endOfString += atom->numChars; - } - - *endOfString = 0; - - jassert ((endOfString - (tchar*) &(s[0])) <= getTotalLength()); - return s; + concatenator.append (getAtom(i)->atomText); } - const String getTextSubstring (const int startCharacter, - const int endCharacter) const throw() - { - int index = 0; - int totalLen = 0; - int i; - - for (i = 0; i < atoms.size(); ++i) - { - const TextAtom* const atom = getAtom (i); - const int nextIndex = index + atom->numChars; - - if (startCharacter < nextIndex) - { - if (endCharacter <= index) - break; - - const int start = jmax (0, startCharacter - index); - const int end = jmin (endCharacter - index, atom->numChars); - jassert (end >= start); - - totalLen += end - start; - } - - index = nextIndex; - } - - String s; - s.preallocateStorage (totalLen + 1); - tchar* psz = (tchar*) (const tchar*) s; - - index = 0; - - for (i = 0; i < atoms.size(); ++i) - { - const TextAtom* const atom = getAtom (i); - const int nextIndex = index + atom->numChars; - - if (startCharacter < nextIndex) - { - if (endCharacter <= index) - break; + void appendSubstring (String::Concatenator& concatenator, + const int startCharacter, + const int endCharacter) const + { + int index = 0; + for (int i = 0; i < atoms.size(); ++i) + { + const TextAtom* const atom = getAtom (i); + const int nextIndex = index + atom->numChars; - const int start = jmax (0, startCharacter - index); - const int len = jmin (endCharacter - index, atom->numChars) - start; + if (startCharacter < nextIndex) + { + if (endCharacter <= index) + break; - memcpy (psz, ((const tchar*) atom->atomText) + start, len * sizeof (tchar)); - psz += len; - *psz = 0; - } + const int start = jmax (0, startCharacter - index); + const int end = jmin (endCharacter - index, atom->numChars); - index = nextIndex; - } + if (start < end) + concatenator.append (atom->atomText.substring (start, end)); + } - return s; + index = nextIndex; + } } - int getTotalLength() const throw() + int getTotalLength() const { - int c = 0; + int total = 0; for (int i = atoms.size(); --i >= 0;) - c += getAtom(i)->numChars; + total += getAtom(i)->numChars; - return c; + return total; } void setFont (const Font& newFont, - const tchar passwordCharacter) throw() + const tchar passwordCharacter) { if (font != newFont) { @@ -51902,7 +51920,7 @@ private: VoidArray atoms; void initialiseAtoms (const String& textToParse, - const tchar passwordCharacter) throw() + const tchar passwordCharacter) { int i = 0; const int len = textToParse.length(); @@ -51967,7 +51985,7 @@ public: TextEditorIterator (const VoidArray& sections_, const float wordWrapWidth_, - const tchar passwordCharacter_) throw() + const tchar passwordCharacter_) : indexInText (0), lineY (0), lineHeight (0), @@ -51993,7 +52011,7 @@ public: } } - TextEditorIterator (const TextEditorIterator& other) throw() + TextEditorIterator (const TextEditorIterator& other) : indexInText (other.indexInText), lineY (other.lineY), lineHeight (other.lineHeight), @@ -52011,11 +52029,11 @@ public: { } - ~TextEditorIterator() throw() + ~TextEditorIterator() { } - bool next() throw() + bool next() { if (atom == &tempAtom) { @@ -52160,7 +52178,7 @@ public: return true; } - void beginNewLine() throw() + void beginNewLine() { atomX = 0; lineY += lineHeight; @@ -52211,7 +52229,7 @@ public: } } - void draw (Graphics& g, const UniformTextSection*& lastSection) const throw() + void draw (Graphics& g, const UniformTextSection*& lastSection) const { if (passwordCharacter != 0 || ! atom->isWhitespace()) { @@ -52235,7 +52253,7 @@ public: void drawSelection (Graphics& g, const int selectionStart, - const int selectionEnd) const throw() + const int selectionEnd) const { const int startX = roundFloatToInt (indexToX (selectionStart)); const int endX = roundFloatToInt (indexToX (selectionEnd)); @@ -52249,7 +52267,7 @@ public: void drawSelectedText (Graphics& g, const int selectionStart, const int selectionEnd, - const Colour& selectedTextColour) const throw() + const Colour& selectedTextColour) const { if (passwordCharacter != 0 || ! atom->isWhitespace()) { @@ -52284,7 +52302,7 @@ public: } } - float indexToX (const int indexToFind) const throw() + float indexToX (const int indexToFind) const { if (indexToFind <= indexInText) return atomX; @@ -52303,7 +52321,7 @@ public: return jmin (atomRight, g.getGlyph (indexToFind - indexInText).getLeft()); } - int xToIndex (const float xToFind) const throw() + int xToIndex (const float xToFind) const { if (xToFind <= atomX || atom->isNewLine()) return indexInText; @@ -52324,7 +52342,7 @@ public: return indexInText + j; } - bool getCharPosition (const int index, float& cx, float& cy, float& lineHeight_) throw() + bool getCharPosition (const int index, float& cx, float& cy, float& lineHeight_) { while (next()) { @@ -52360,7 +52378,7 @@ private: const TextEditorIterator& operator= (const TextEditorIterator&); - void moveToEndOfLastAtom() throw() + void moveToEndOfLastAtom() { if (atom != 0) { @@ -52374,7 +52392,7 @@ private: } } - bool shouldWrap (const float x) const throw() + bool shouldWrap (const float x) const { return (x - 0.0001f) >= wordWrapWidth; } @@ -52398,7 +52416,7 @@ public: const Font& font_, const Colour& colour_, const int oldCaretPos_, - const int newCaretPos_) throw() + const int newCaretPos_) : owner (owner_), text (text_), insertIndex (insertIndex_), @@ -52446,7 +52464,7 @@ public: const int endIndex_, const int oldCaretPos_, const int newCaretPos_, - const VoidArray& removedSections_) throw() + const VoidArray& removedSections_) : owner (owner_), startIndex (startIndex_), endIndex (endIndex_), @@ -52494,38 +52512,47 @@ public: }; class TextHolderComponent : public Component, - public Timer + public Timer, + public Value::Listener { - TextEditor* const owner; + TextEditor& owner; TextHolderComponent (const TextHolderComponent&); const TextHolderComponent& operator= (const TextHolderComponent&); public: - TextHolderComponent (TextEditor* const owner_) + TextHolderComponent (TextEditor& owner_) : owner (owner_) { setWantsKeyboardFocus (false); setInterceptsMouseClicks (false, true); + + owner.getTextValue().addListener (this); } ~TextHolderComponent() { + owner.getTextValue().removeListener (this); } void paint (Graphics& g) { - owner->drawContent (g); + owner.drawContent (g); } void timerCallback() { - owner->timerCallbackInt(); + owner.timerCallbackInt(); } const MouseCursor getMouseCursor() { - return owner->getMouseCursor(); + return owner.getMouseCursor(); + } + + void valueChanged (Value&) + { + owner.textWasChangedByValue(); } }; @@ -52584,6 +52611,7 @@ TextEditor::TextEditor (const String& name, keepCursorOnScreen (true), tabKeyUsed (false), menuActive (false), + valueTextNeedsUpdating (false), cursorX (0), cursorY (0), cursorHeight (0), @@ -52604,7 +52632,7 @@ TextEditor::TextEditor (const String& name, setOpaque (true); addAndMakeVisible (viewport = new TextEditorViewport (this)); - viewport->setViewedComponent (textHolder = new TextHolderComponent (this)); + viewport->setViewedComponent (textHolder = new TextHolderComponent (*this)); viewport->setWantsKeyboardFocus (false); viewport->setScrollBarsShown (false, false); @@ -52616,9 +52644,10 @@ TextEditor::~TextEditor() { clearInternal (0); viewport = 0; + textHolder = 0; } -void TextEditor::newTransaction() throw() +void TextEditor::newTransaction() { lastTransactionTime = Time::getApproximateMillisecondCounter(); undoManager.beginNewTransaction(); @@ -52652,12 +52681,12 @@ void TextEditor::setMultiLine (const bool shouldBeMultiLine, scrollToMakeSureCursorIsVisible(); } -bool TextEditor::isMultiLine() const throw() +bool TextEditor::isMultiLine() const { return multiline; } -void TextEditor::setScrollbarsShown (bool enabled) throw() +void TextEditor::setScrollbarsShown (bool enabled) { scrollbarVisible = enabled; @@ -52672,7 +52701,7 @@ void TextEditor::setReadOnly (const bool shouldBeReadOnly) enablementChanged(); } -bool TextEditor::isReadOnly() const throw() +bool TextEditor::isReadOnly() const { return readOnly || ! isEnabled(); } @@ -52682,27 +52711,27 @@ void TextEditor::setReturnKeyStartsNewLine (const bool shouldStartNewLine) returnKeyStartsNewLine = shouldStartNewLine; } -void TextEditor::setTabKeyUsedAsCharacter (const bool shouldTabKeyBeUsed) throw() +void TextEditor::setTabKeyUsedAsCharacter (const bool shouldTabKeyBeUsed) { tabKeyUsed = shouldTabKeyBeUsed; } -void TextEditor::setPopupMenuEnabled (const bool b) throw() +void TextEditor::setPopupMenuEnabled (const bool b) { popupMenuEnabled = b; } -void TextEditor::setSelectAllWhenFocused (const bool b) throw() +void TextEditor::setSelectAllWhenFocused (const bool b) { selectAllTextWhenFocused = b; } -const Font TextEditor::getFont() const throw() +const Font TextEditor::getFont() const { return currentFont; } -void TextEditor::setFont (const Font& newFont) throw() +void TextEditor::setFont (const Font& newFont) { currentFont = newFont; scrollToMakeSureCursorIsVisible(); @@ -52733,7 +52762,7 @@ void TextEditor::colourChanged() repaint(); } -void TextEditor::setCaretVisible (const bool shouldCaretBeVisible) throw() +void TextEditor::setCaretVisible (const bool shouldCaretBeVisible) { caretVisible = shouldCaretBeVisible; @@ -52745,19 +52774,19 @@ void TextEditor::setCaretVisible (const bool shouldCaretBeVisible) throw() } void TextEditor::setInputRestrictions (const int maxLen, - const String& chars) throw() + const String& chars) { maxTextLength = jmax (0, maxLen); allowedCharacters = chars; } -void TextEditor::setTextToShowWhenEmpty (const String& text, const Colour& colourToUse) throw() +void TextEditor::setTextToShowWhenEmpty (const String& text, const Colour& colourToUse) { textToShowWhenEmpty = text; colourForTextWhenEmpty = colourToUse; } -void TextEditor::setPasswordCharacter (const tchar newPasswordCharacter) throw() +void TextEditor::setPasswordCharacter (const tchar newPasswordCharacter) { if (passwordCharacter != newPasswordCharacter) { @@ -52817,10 +52846,33 @@ void TextEditor::setText (const String& newText, undoManager.clearUndoHistory(); } -void TextEditor::textChanged() throw() +Value& TextEditor::getTextValue() +{ + if (valueTextNeedsUpdating) + { + valueTextNeedsUpdating = false; + textValue = getText(); + } + + return textValue; +} + +void TextEditor::textWasChangedByValue() +{ + if (textValue.getValueSource().getReferenceCount() > 1) + setText (textValue.getValue()); +} + +void TextEditor::textChanged() { updateTextHolderSize(); postCommandMessage (textChangeMessageId); + + if (textValue.getValueSource().getReferenceCount() > 1) + { + valueTextNeedsUpdating = false; + textValue = getText(); + } } void TextEditor::returnPressed() @@ -52833,7 +52885,7 @@ void TextEditor::escapePressed() postCommandMessage (escapeKeyMessageId); } -void TextEditor::addListener (TextEditorListener* const newListener) throw() +void TextEditor::addListener (TextEditorListener* const newListener) { jassert (newListener != 0) @@ -52841,7 +52893,7 @@ void TextEditor::addListener (TextEditorListener* const newListener) throw() listeners.add (newListener); } -void TextEditor::removeListener (TextEditorListener* const listenerToRemove) throw() +void TextEditor::removeListener (TextEditorListener* const listenerToRemove) { listeners.removeValue (listenerToRemove); } @@ -52912,7 +52964,7 @@ void TextEditor::repaintText (int textStartIndex, int textEndIndex) } } -void TextEditor::moveCaret (int newCaretPos) throw() +void TextEditor::moveCaret (int newCaretPos) { if (newCaretPos < 0) newCaretPos = 0; @@ -52930,18 +52982,18 @@ void TextEditor::moveCaret (int newCaretPos) throw() } } -void TextEditor::setCaretPosition (const int newIndex) throw() +void TextEditor::setCaretPosition (const int newIndex) { moveCursorTo (newIndex, false); } -int TextEditor::getCaretPosition() const throw() +int TextEditor::getCaretPosition() const { return caretPosition; } void TextEditor::scrollEditorToPositionCaret (const int desiredCaretX, - const int desiredCaretY) throw() + const int desiredCaretY) { updateCaretPosition(); @@ -52983,7 +53035,7 @@ void TextEditor::scrollEditorToPositionCaret (const int desiredCaretX, viewport->setViewPosition (vx, vy); } -const Rectangle TextEditor::getCaretRectangle() throw() +const Rectangle TextEditor::getCaretRectangle() { updateCaretPosition(); @@ -52992,13 +53044,13 @@ const Rectangle TextEditor::getCaretRectangle() throw() 1, roundFloatToInt (cursorHeight)); } -float TextEditor::getWordWrapWidth() const throw() +float TextEditor::getWordWrapWidth() const { return (wordWrap) ? (float) (viewport->getMaximumVisibleWidth() - leftIndent - leftIndent / 2) : 1.0e10f; } -void TextEditor::updateTextHolderSize() throw() +void TextEditor::updateTextHolderSize() { const float wordWrapWidth = getWordWrapWidth(); @@ -53019,46 +53071,46 @@ void TextEditor::updateTextHolderSize() throw() } } -int TextEditor::getTextWidth() const throw() +int TextEditor::getTextWidth() const { return textHolder->getWidth(); } -int TextEditor::getTextHeight() const throw() +int TextEditor::getTextHeight() const { return textHolder->getHeight(); } void TextEditor::setIndents (const int newLeftIndent, - const int newTopIndent) throw() + const int newTopIndent) { leftIndent = newLeftIndent; topIndent = newTopIndent; } -void TextEditor::setBorder (const BorderSize& border) throw() +void TextEditor::setBorder (const BorderSize& border) { borderSize = border; resized(); } -const BorderSize TextEditor::getBorder() const throw() +const BorderSize TextEditor::getBorder() const { return borderSize; } -void TextEditor::setScrollToShowCursor (const bool shouldScrollToShowCursor) throw() +void TextEditor::setScrollToShowCursor (const bool shouldScrollToShowCursor) { keepCursorOnScreen = shouldScrollToShowCursor; } -void TextEditor::updateCaretPosition() throw() +void TextEditor::updateCaretPosition() { cursorHeight = currentFont.getHeight(); // (in case the text is empty and the call below doesn't set this value) getCharPosition (caretPosition, cursorX, cursorY, cursorHeight); } -void TextEditor::scrollToMakeSureCursorIsVisible() throw() +void TextEditor::scrollToMakeSureCursorIsVisible() { updateCaretPosition(); @@ -53104,7 +53156,7 @@ void TextEditor::scrollToMakeSureCursorIsVisible() throw() } void TextEditor::moveCursorTo (const int newPosition, - const bool isSelecting) throw() + const bool isSelecting) { if (isSelecting) { @@ -53162,7 +53214,7 @@ void TextEditor::moveCursorTo (const int newPosition, } int TextEditor::getTextIndexAt (const int x, - const int y) throw() + const int y) { return indexAtPosition ((float) (x + viewport->getViewPositionX() - leftIndent), (float) (y + viewport->getViewPositionY() - topIndent)); @@ -53199,7 +53251,7 @@ void TextEditor::insertTextAtCursor (String newText) textChanged(); } -void TextEditor::setHighlightedRegion (int startPos, int numChars) throw() +void TextEditor::setHighlightedRegion (int startPos, int numChars) { moveCursorTo (startPos, false); moveCursorTo (startPos + numChars, true); @@ -53791,7 +53843,7 @@ void TextEditor::enablementChanged() repaint(); } -void TextEditor::clearInternal (UndoManager* const um) throw() +void TextEditor::clearInternal (UndoManager* const um) { remove (0, getTotalNumChars(), um, caretPosition); } @@ -53801,7 +53853,7 @@ void TextEditor::insert (const String& text, const Font& font, const Colour& colour, UndoManager* const um, - const int caretPositionToMoveTo) throw() + const int caretPositionToMoveTo) { if (text.isNotEmpty()) { @@ -53853,6 +53905,7 @@ void TextEditor::insert (const String& text, coalesceSimilarSections(); totalNumChars = -1; + valueTextNeedsUpdating = true; moveCursorTo (caretPositionToMoveTo, false); @@ -53862,7 +53915,7 @@ void TextEditor::insert (const String& text, } void TextEditor::reinsert (const int insertIndex, - const VoidArray& sectionsToInsert) throw() + const VoidArray& sectionsToInsert) { int index = 0; int nextIndex = 0; @@ -53899,12 +53952,13 @@ void TextEditor::reinsert (const int insertIndex, coalesceSimilarSections(); totalNumChars = -1; + valueTextNeedsUpdating = true; } void TextEditor::remove (const int startIndex, int endIndex, UndoManager* const um, - const int caretPositionToMoveTo) throw() + const int caretPositionToMoveTo) { if (endIndex > startIndex) { @@ -53988,6 +54042,7 @@ void TextEditor::remove (const int startIndex, coalesceSimilarSections(); totalNumChars = -1; + valueTextNeedsUpdating = true; moveCursorTo (caretPositionToMoveTo, false); @@ -53996,48 +54051,56 @@ void TextEditor::remove (const int startIndex, } } -const String TextEditor::getText() const throw() +const String TextEditor::getText() const { String t; + t.preallocateStorage (getTotalNumChars()); + String::Concatenator concatenator (t); for (int i = 0; i < sections.size(); ++i) - t += ((const UniformTextSection*) sections.getUnchecked(i))->getAllText(); + ((const UniformTextSection*) sections.getUnchecked(i))->appendAllText (concatenator); return t; } -const String TextEditor::getTextSubstring (const int startCharacter, const int endCharacter) const throw() +const String TextEditor::getTextSubstring (const int startCharacter, const int endCharacter) const { String t; - int index = 0; - for (int i = 0; i < sections.size(); ++i) + if (endCharacter > startCharacter) { - const UniformTextSection* const s = (const UniformTextSection*) sections.getUnchecked(i); - const int nextIndex = index + s->getTotalLength(); + t.preallocateStorage (jmin (getTotalNumChars(), endCharacter - startCharacter)); + String::Concatenator concatenator (t); + int index = 0; - if (startCharacter < nextIndex) + for (int i = 0; i < sections.size(); ++i) { - if (endCharacter <= index) - break; + const UniformTextSection* const s = (const UniformTextSection*) sections.getUnchecked(i); + const int nextIndex = index + s->getTotalLength(); - const int start = jmax (index, startCharacter); - t += s->getTextSubstring (start - index, endCharacter - index); - } + if (startCharacter < nextIndex) + { + if (endCharacter <= index) + break; - index = nextIndex; + s->appendSubstring (concatenator, + startCharacter - index, + endCharacter - index); + } + + index = nextIndex; + } } return t; } -const String TextEditor::getHighlightedText() const throw() +const String TextEditor::getHighlightedText() const { - return getTextSubstring (getHighlightedRegionStart(), - getHighlightedRegionStart() + getHighlightedRegionLength()); + return getTextSubstring (selectionStart, selectionEnd); } -int TextEditor::getTotalNumChars() throw() +int TextEditor::getTotalNumChars() const { if (totalNumChars < 0) { @@ -54050,19 +54113,12 @@ int TextEditor::getTotalNumChars() throw() return totalNumChars; } -bool TextEditor::isEmpty() const throw() +bool TextEditor::isEmpty() const { - if (totalNumChars != 0) - { - for (int i = sections.size(); --i >= 0;) - if (((const UniformTextSection*) sections.getUnchecked(i))->getTotalLength() > 0) - return false; - } - - return true; + return getTotalNumChars() == 0; } -void TextEditor::getCharPosition (const int index, float& cx, float& cy, float& lineHeight) const throw() +void TextEditor::getCharPosition (const int index, float& cx, float& cy, float& lineHeight) const { const float wordWrapWidth = getWordWrapWidth(); @@ -54079,7 +54135,7 @@ void TextEditor::getCharPosition (const int index, float& cx, float& cy, float& } } -int TextEditor::indexAtPosition (const float x, const float y) throw() +int TextEditor::indexAtPosition (const float x, const float y) { const float wordWrapWidth = getWordWrapWidth(); @@ -54106,13 +54162,13 @@ int TextEditor::indexAtPosition (const float x, const float y) throw() return getTotalNumChars(); } -static int getCharacterCategory (const tchar character) throw() +static int getCharacterCategory (const tchar character) { return CharacterFunctions::isLetterOrDigit (character) ? 2 : (CharacterFunctions::isWhitespace (character) ? 0 : 1); } -int TextEditor::findWordBreakAfter (const int position) const throw() +int TextEditor::findWordBreakAfter (const int position) const { const String t (getTextSubstring (position, position + 512)); const int totalLength = t.length(); @@ -54132,7 +54188,7 @@ int TextEditor::findWordBreakAfter (const int position) const throw() return position + i; } -int TextEditor::findWordBreakBefore (const int position) const throw() +int TextEditor::findWordBreakBefore (const int position) const { if (position <= 0) return 0; @@ -54158,7 +54214,7 @@ int TextEditor::findWordBreakBefore (const int position) const throw() } void TextEditor::splitSection (const int sectionIndex, - const int charToSplitAt) throw() + const int charToSplitAt) { jassert (sections[sectionIndex] != 0); @@ -54167,7 +54223,7 @@ void TextEditor::splitSection (const int sectionIndex, ->split (charToSplitAt, passwordCharacter)); } -void TextEditor::coalesceSimilarSections() throw() +void TextEditor::coalesceSimilarSections() { for (int i = 0; i < sections.size() - 1; ++i) { @@ -56410,9 +56466,12 @@ TreeViewItem* TreeViewContentComponent::findItemAt (int y, Rectangle& itemPositi return 0; } -#define opennessDefault 0 -#define opennessClosed 1 -#define opennessOpen 2 +enum TreeViewOpenness +{ + opennessDefault = 0, + opennessClosed = 1, + opennessOpen = 2 +}; TreeViewItem::TreeViewItem() : ownerView (0), @@ -64322,9 +64381,9 @@ LookAndFeel::LookAndFeel() jassert (Colours::white == Colour (0xffffffff)); // set up the standard set of colours.. - #define textButtonColour 0xffbbbbff - #define textHighlightColour 0x401111ee - #define standardOutlineColour 0xb2808080 + const int textButtonColour = 0xffbbbbff; + const int textHighlightColour = 0x401111ee; + const int standardOutlineColour = 0xb2808080; static const int standardColours[] = { @@ -75687,17 +75746,10 @@ static const int iconWidth = 80; class AlertWindowTextEditor : public TextEditor { public: - #if JUCE_LINUX - #define PASSWORD_CHAR 0x2022 - #else - #define PASSWORD_CHAR 0x25cf - #endif + static const tchar passwordChar; - AlertWindowTextEditor (const String& name, - const bool isPasswordBox) - : TextEditor (name, - isPasswordBox ? (const tchar) PASSWORD_CHAR - : (const tchar) 0) + AlertWindowTextEditor (const String& name, const bool isPasswordBox) + : TextEditor (name, isPasswordBox ? passwordChar : 0) { setSelectAllWhenFocused (true); } @@ -75723,6 +75775,12 @@ private: const AlertWindowTextEditor& operator= (const AlertWindowTextEditor&); }; +#if JUCE_LINUX +const tchar AlertWindowTextEditor::passwordChar = 0x2022; +#else +const tchar AlertWindowTextEditor::passwordChar = 0x25cf; +#endif + AlertWindow::AlertWindow (const String& title, const String& message, AlertIconType iconType, @@ -86053,8 +86111,6 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE -#define SHOULD_WRAP(x, wrapwidth) (((x) - 0.0001f) >= (wrapwidth)) - PositionedGlyph::PositionedGlyph() { } @@ -86324,7 +86380,7 @@ void GlyphArrangement::addJustifiedText (const Font& font, { lastWordBreakIndex = i + 1; } - else if (SHOULD_WRAP (pg->getRight(), lineMaxX)) + else if (pg->getRight() - 0.0001f >= lineMaxX) { if (lastWordBreakIndex >= 0) i = lastWordBreakIndex; @@ -92870,8 +92926,8 @@ private: int processExtension (int type, int& transparent); int readLZWByte (bool initialise, int input_code_size); int getCode (int code_size, bool initialise); - bool readImage (int width, int height, - int interlace, int transparent); + bool readImage (int width, int height, int interlace, int transparent); + static inline int makeWord (const uint8 a, const uint8 b) { return (b << 8) | a; } GIFLoader (const GIFLoader&); const GIFLoader& operator= (const GIFLoader&); @@ -93064,11 +93120,6 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE -static inline int makeWord (const unsigned char a, const unsigned char b) -{ - return (b << 8) | a; -} - GIFLoader::GIFLoader (InputStream& in) : image (0), input (in), @@ -125475,7 +125526,7 @@ BEGIN_JUCE_NAMESPACE using namespace FlacNamespace; -#define flacFormatName TRANS("FLAC file") +static const char* const flacFormatName = "FLAC file"; static const tchar* const flacExtensions[] = { T(".flac"), 0 }; class FlacReader : public AudioFormatReader @@ -125488,7 +125539,7 @@ class FlacReader : public AudioFormatReader public: FlacReader (InputStream* const in) - : AudioFormatReader (in, flacFormatName), + : AudioFormatReader (in, TRANS (flacFormatName)), reservoir (2, 0), reservoirStart (0), samplesInReservoir (0), @@ -125704,7 +125755,7 @@ public: const double sampleRate_, const int numChannels_, const int bitsPerSample_) - : AudioFormatWriter (out, flacFormatName, + : AudioFormatWriter (out, TRANS (flacFormatName), sampleRate_, numChannels_, bitsPerSample_) @@ -125861,7 +125912,7 @@ public: }; FlacAudioFormat::FlacAudioFormat() - : AudioFormat (flacFormatName, (const tchar**) flacExtensions) + : AudioFormat (TRANS (flacFormatName), (const tchar**) flacExtensions) { } @@ -184509,7 +184560,7 @@ BEGIN_JUCE_NAMESPACE using namespace OggVorbisNamespace; -#define oggFormatName TRANS("Ogg-Vorbis file") +static const char* const oggFormatName = "Ogg-Vorbis file"; static const tchar* const oggExtensions[] = { T(".ogg"), 0 }; class OggReader : public AudioFormatReader @@ -184522,7 +184573,7 @@ class OggReader : public AudioFormatReader public: OggReader (InputStream* const inp) - : AudioFormatReader (inp, oggFormatName), + : AudioFormatReader (inp, TRANS (oggFormatName)), reservoir (2, 4096), reservoirStart (0), samplesInReservoir (0) @@ -184683,7 +184734,7 @@ public: const int numChannels, const int bitsPerSample, const int qualityIndex) - : AudioFormatWriter (out, oggFormatName, + : AudioFormatWriter (out, TRANS (oggFormatName), sampleRate, numChannels, bitsPerSample) @@ -184809,7 +184860,7 @@ public: }; OggVorbisAudioFormat::OggVorbisAudioFormat() - : AudioFormat (oggFormatName, (const tchar**) oggExtensions) + : AudioFormat (TRANS (oggFormatName), (const tchar**) oggExtensions) { } @@ -208393,7 +208444,7 @@ Image* juce_loadJPEGImageFromStream (InputStream& in) return image; } -static const int bufferSize = 512; +static const int jpegBufferSize = 512; struct JuceJpegDest : public jpeg_destination_mgr { @@ -208409,7 +208460,7 @@ static void jpegWriteTerminate (j_compress_ptr cinfo) { JuceJpegDest* const dest = (JuceJpegDest*) cinfo->dest; - const int numToWrite = bufferSize - dest->free_in_buffer; + const int numToWrite = jpegBufferSize - dest->free_in_buffer; dest->output->write (dest->buffer, numToWrite); } @@ -208417,10 +208468,10 @@ static boolean jpegWriteFlush (j_compress_ptr cinfo) { JuceJpegDest* const dest = (JuceJpegDest*) cinfo->dest; - const int numToWrite = bufferSize; + const int numToWrite = jpegBufferSize; dest->next_output_byte = (JOCTET*) dest->buffer; - dest->free_in_buffer = bufferSize; + dest->free_in_buffer = jpegBufferSize; return dest->output->write (dest->buffer, numToWrite); } @@ -208448,10 +208499,10 @@ bool juce_writeJPEGImageToStream (const Image& image, jpegCompStruct.dest = &dest; dest.output = &out; - HeapBlock tempBuffer (bufferSize); + HeapBlock tempBuffer (jpegBufferSize); dest.buffer = (char*) tempBuffer; dest.next_output_byte = (JOCTET*) dest.buffer; - dest.free_in_buffer = bufferSize; + dest.free_in_buffer = jpegBufferSize; dest.init_destination = jpegWriteInit; dest.empty_output_buffer = jpegWriteFlush; dest.term_destination = jpegWriteTerminate; @@ -234279,20 +234330,6 @@ static double hiResTicksScaleFactor; #pragma intrinsic (__cpuid) #pragma intrinsic (__rdtsc) -/*static unsigned int getCPUIDWord (int* familyModel = 0, int* extFeatures = 0) throw() -{ - int info [4]; - __cpuid (info, 1); - - if (familyModel != 0) - *familyModel = info [0]; - - if (extFeatures != 0) - *extFeatures = info[1]; - - return info[3]; -}*/ - const String SystemStats::getCpuVendor() throw() { int info [4]; @@ -234310,50 +234347,6 @@ const String SystemStats::getCpuVendor() throw() // CPU info functions using old fashioned inline asm... -/*static juce_noinline unsigned int getCPUIDWord (int* familyModel = 0, int* extFeatures = 0) -{ - unsigned int cpu = 0; - unsigned int ext = 0; - unsigned int family = 0; - - #if JUCE_GCC - unsigned int dummy = 0; - #endif - - #ifndef __MINGW32__ - __try - #endif - { - #if JUCE_GCC - __asm__ ("cpuid" : "=a" (family), "=b" (ext), "=c" (dummy),"=d" (cpu) : "a" (1)); - #else - __asm - { - mov eax, 1 - cpuid - mov cpu, edx - mov family, eax - mov ext, ebx - } - - #endif - } - #ifndef __MINGW32__ - __except (EXCEPTION_EXECUTE_HANDLER) - { - return 0; - } - #endif - - if (familyModel != 0) - *familyModel = family; - - if (extFeatures != 0) - *extFeatures = ext; - - return cpu; -}*/ - static void juce_getCpuVendor (char* const v) { int vendor[4]; @@ -234913,7 +234906,7 @@ void Process::setPriority (ProcessPriority prior) } } -bool JUCE_API JUCE_CALLTYPE juce_isRunningUnderDebugger() +bool JUCE_PUBLIC_FUNCTION juce_isRunningUnderDebugger() { return IsDebuggerPresent() != FALSE; } @@ -236149,7 +236142,7 @@ static int getMACAddressViaGetAdaptersInfo (int64* addresses, int maxNum, const mac = (mac << 8) | adapter->Address[i]; if (littleEndian) - mac = (int64) swapByteOrder ((uint64) mac); + mac = (int64) ByteOrder::swap ((uint64) mac); if (numFound < maxNum && mac != 0) addresses [numFound++] = mac; @@ -246688,7 +246681,7 @@ private: { while (--numSamples >= 0) { - *dest++ = (float) (g * (short) littleEndianShort (src)); + *dest++ = (float) (g * (short) ByteOrder::littleEndianShort (src)); src += srcStrideBytes; } } @@ -246696,7 +246689,7 @@ private: { while (--numSamples >= 0) { - *dest++ = (float) (g * (short) bigEndianShort (src)); + *dest++ = (float) (g * (short) ByteOrder::bigEndianShort (src)); src += srcStrideBytes; } } @@ -246714,7 +246707,7 @@ private: { while (--numSamples >= 0) { - *(uint16*) dest = swapIfBigEndian ((uint16) (short) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * *src++))); + *(uint16*) dest = ByteOrder::swapIfBigEndian ((uint16) (short) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * *src++))); dest += dstStrideBytes; } } @@ -246722,7 +246715,7 @@ private: { while (--numSamples >= 0) { - *(uint16*) dest = swapIfLittleEndian ((uint16) (short) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * *src++))); + *(uint16*) dest = ByteOrder::swapIfLittleEndian ((uint16) (short) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * *src++))); dest += dstStrideBytes; } } @@ -246740,7 +246733,7 @@ private: { while (--numSamples >= 0) { - *dest++ = (float) (g * littleEndian24Bit (src)); + *dest++ = (float) (g * ByteOrder::littleEndian24Bit (src)); src += srcStrideBytes; } } @@ -246748,7 +246741,7 @@ private: { while (--numSamples >= 0) { - *dest++ = (float) (g * bigEndian24Bit (src)); + *dest++ = (float) (g * ByteOrder::bigEndian24Bit (src)); src += srcStrideBytes; } } @@ -246766,7 +246759,7 @@ private: { while (--numSamples >= 0) { - littleEndian24BitToChars ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * *src++)), dest); + ByteOrder::littleEndian24BitToChars ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * *src++)), dest); dest += dstStrideBytes; } } @@ -246774,7 +246767,7 @@ private: { while (--numSamples >= 0) { - bigEndian24BitToChars ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * *src++)), dest); + ByteOrder::bigEndian24BitToChars ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * *src++)), dest); dest += dstStrideBytes; } } @@ -246792,7 +246785,7 @@ private: { while (--numSamples >= 0) { - *dest++ = (float) (g * (int) littleEndianInt (src)); + *dest++ = (float) (g * (int) ByteOrder::littleEndianInt (src)); src += srcStrideBytes; } } @@ -246800,7 +246793,7 @@ private: { while (--numSamples >= 0) { - *dest++ = (float) (g * (int) bigEndianInt (src)); + *dest++ = (float) (g * (int) ByteOrder::bigEndianInt (src)); src += srcStrideBytes; } } @@ -246818,7 +246811,7 @@ private: { while (--numSamples >= 0) { - *(uint32*) dest = swapIfBigEndian ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * *src++))); + *(uint32*) dest = ByteOrder::swap ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * *src++))); dest += dstStrideBytes; } } @@ -246826,7 +246819,7 @@ private: { while (--numSamples >= 0) { - *(uint32*) dest = swapIfLittleEndian ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * *src++))); + *(uint32*) dest = ByteOrder::swap ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * *src++))); dest += dstStrideBytes; } } @@ -251566,7 +251559,7 @@ void juce_findFileClose (void* handle) bool juce_launchFile (const String& fileName, const String& parameters) { - String cmdString (fileName); + String cmdString (fileName.replace (T(" "), T("\\ "),false)); cmdString << " " << parameters; if (URL::isProbablyAWebsiteURL (fileName) @@ -252253,31 +252246,6 @@ int juce_seekInInternetFile (void* handle, int newPosition) // compiled on its own). #if JUCE_INCLUDED_FILE -/*static juce_noinline unsigned int getCPUIDWord (int* familyModel, int* extFeatures) throw() -{ - unsigned int cpu = 0; - unsigned int ext = 0; - unsigned int family = 0; - unsigned int dummy = 0; - -#if JUCE_64BIT - __asm__ ("cpuid" - : "=a" (family), "=b" (ext), "=c" (dummy), "=d" (cpu) : "a" (1)); - -#else - __asm__ ("push %%ebx; cpuid; mov %%ebx, %%edi; pop %%ebx" - : "=a" (family), "=D" (ext), "=c" (dummy), "=d" (cpu) : "a" (1)); -#endif - - if (familyModel != 0) - *familyModel = family; - - if (extFeatures != 0) - *extFeatures = ext; - - return cpu; -}*/ - void Logger::outputDebugString (const String& text) throw() { fputs (text.toUTF8(), stdout); @@ -252641,7 +252609,7 @@ void Process::terminate() exit (0); } -bool JUCE_CALLTYPE juce_isRunningUnderDebugger() +bool JUCE_PUBLIC_FUNCTION juce_isRunningUnderDebugger() { static char testResult = 0; @@ -261591,7 +261559,7 @@ void Logger::outputDebugPrintf (const tchar* format, ...) throw() outputDebugString (text); } -bool JUCE_CALLTYPE juce_isRunningUnderDebugger() +bool JUCE_PUBLIC_FUNCTION juce_isRunningUnderDebugger() { static char testResult = 0; diff --git a/juce_amalgamated.h b/juce_amalgamated.h index 1fbff6ad0c..4317801c86 100644 --- a/juce_amalgamated.h +++ b/juce_amalgamated.h @@ -743,7 +743,7 @@ // Now include some basics that are needed by most of the Juce classes... BEGIN_JUCE_NAMESPACE -extern bool JUCE_API JUCE_CALLTYPE juce_isRunningUnderDebugger(); +extern bool JUCE_PUBLIC_FUNCTION juce_isRunningUnderDebugger(); #if JUCE_LOG_ASSERTIONS extern void JUCE_API juce_LogAssertion (const char* filename, const int lineNum) throw(); @@ -903,7 +903,7 @@ extern bool JUCE_API JUCE_CALLTYPE juce_isRunningUnderDebugger(); #endif #if JUCE_MSVC - /** This is a compiler-indenpendent way of declaring a variable as being thread-local. + /** This is a compiler-independent way of declaring a variable as being thread-local. E.g. @code @@ -1070,7 +1070,7 @@ inline double jmin (const double a, const double b, const double c, const double and upperLimit (inclusive) @see jlimit0To, jmin, jmax */ -template +template inline Type jlimit (const Type lowerLimit, const Type upperLimit, const Type valueToConstrain) throw() @@ -1084,8 +1084,8 @@ inline Type jlimit (const Type lowerLimit, /** Handy function to swap two values over. */ -template -inline void swapVariables (Type& variable1, Type& variable2) throw() +template +inline void swapVariables (Type& variable1, Type& variable2) { const Type tempVal = variable1; variable1 = variable2; @@ -1105,25 +1105,33 @@ inline void swapVariables (Type& variable1, Type& variable2) throw() // Some useful maths functions that aren't always present with all compilers and build settings. -#if JUCE_WINDOWS || defined (DOXYGEN) - /** Using juce_hypot and juce_hypotf is easier than dealing with all the different - versions of these functions of various platforms and compilers. */ - forcedinline double juce_hypot (double a, double b) { return _hypot (a, b); } - - /** Using juce_hypot and juce_hypotf is easier than dealing with all the different - versions of these functions of various platforms and compilers. */ - forcedinline float juce_hypotf (float a, float b) { return (float) _hypot (a, b); } -#else - /** Using juce_hypot and juce_hypotf is easier than dealing with all the different - versions of these functions of various platforms and compilers. */ - forcedinline double juce_hypot (double a, double b) { return hypot (a, b); } +/** Using juce_hypot and juce_hypotf is easier than dealing with all the different + versions of these functions of various platforms and compilers. */ +inline double juce_hypot (double a, double b) +{ + #if JUCE_WINDOWS + return _hypot (a, b); + #else + return hypot (a, b); + #endif +} - /** Using juce_hypot and juce_hypotf is easier than dealing with all the different - versions of these functions of various platforms and compilers. */ - forcedinline float juce_hypotf (float a, float b) { return hypotf (a, b); } -#endif +/** Using juce_hypot and juce_hypotf is easier than dealing with all the different + versions of these functions of various platforms and compilers. */ +inline float juce_hypotf (float a, float b) +{ + #if JUCE_WINDOWS + return (float) _hypot (a, b); + #else + return hypotf (a, b); + #endif +} -inline int64 abs64 (const int64 n) throw() { return (n >= 0) ? n : -n; } +/** 64-bit abs function. */ +inline int64 abs64 (const int64 n) +{ + return (n >= 0) ? n : -n; +} /** A predefined value for Pi, at double-precision. @@ -1137,146 +1145,19 @@ const double double_Pi = 3.1415926535897932384626433832795; */ const float float_Pi = 3.14159265358979323846f; -/** The isfinite() method seems to vary greatly between platforms, so this is a - platform-independent macro for it. +/** The isfinite() method seems to vary between platforms, so this is a + platform-independent function for it. */ -#if JUCE_LINUX || JUCE_MAC || JUCE_IPHONE - #define juce_isfinite(v) std::isfinite(v) -#elif JUCE_WINDOWS && ! defined (isfinite) - #define juce_isfinite(v) _finite(v) -#else - #define juce_isfinite(v) isfinite(v) -#endif - -#endif // __JUCE_MATHSFUNCTIONS_JUCEHEADER__ -/********* End of inlined file: juce_MathsFunctions.h *********/ - -/********* Start of inlined file: juce_DataConversions.h *********/ -#ifndef __JUCE_DATACONVERSIONS_JUCEHEADER__ -#define __JUCE_DATACONVERSIONS_JUCEHEADER__ - -#if JUCE_USE_INTRINSICS - #pragma intrinsic (_byteswap_ulong) -#endif - -// Endianness conversions.. - -#if JUCE_IPHONE -// a gcc compiler error seems to mean that these functions only work properly -// on the iPhone if they are declared static.. -static forcedinline uint32 swapByteOrder (uint32 n) throw(); -static inline uint16 swapByteOrder (const uint16 n) throw(); -static inline uint64 swapByteOrder (const uint64 value) throw(); -#endif - -/** Swaps the byte-order in an integer from little to big-endianness or vice-versa. */ -forcedinline uint32 swapByteOrder (uint32 n) throw() -{ -#if JUCE_MAC || JUCE_IPHONE - // Mac version - return OSSwapInt32 (n); -#elif JUCE_GCC - // Inpenetrable GCC version.. - asm("bswap %%eax" : "=a"(n) : "a"(n)); - return n; -#elif JUCE_USE_INTRINSICS - // Win32 intrinsics version.. - return _byteswap_ulong (n); -#else - // Win32 version.. - __asm { - mov eax, n - bswap eax - mov n, eax - } - return n; -#endif -} - -/** Swaps the byte-order of a 16-bit short. */ -inline uint16 swapByteOrder (const uint16 n) throw() +template +inline bool juce_isfinite (FloatingPointType value) { -#if JUCE_USE_INTRINSICSxxx // agh - the MS compiler has an internal error when you try to use this intrinsic! - // Win32 intrinsics version.. - return (uint16) _byteswap_ushort (n); -#else - return (uint16) ((n << 8) | (n >> 8)); -#endif -} - -inline uint64 swapByteOrder (const uint64 value) throw() -{ -#if JUCE_MAC || JUCE_IPHONE - return OSSwapInt64 (value); -#elif JUCE_USE_INTRINSICS - return _byteswap_uint64 (value); -#else - return (((int64) swapByteOrder ((uint32) value)) << 32) - | swapByteOrder ((uint32) (value >> 32)); -#endif + #if JUCE_WINDOWS + return _finite (value); + #else + return std::isfinite (value); + #endif } -#if JUCE_LITTLE_ENDIAN - /** Swaps the byte order of a 16-bit int if the CPU is big-endian */ - inline uint16 swapIfBigEndian (const uint16 v) throw() { return v; } - /** Swaps the byte order of a 32-bit int if the CPU is big-endian */ - inline uint32 swapIfBigEndian (const uint32 v) throw() { return v; } - /** Swaps the byte order of a 64-bit int if the CPU is big-endian */ - inline uint64 swapIfBigEndian (const uint64 v) throw() { return v; } - - /** Swaps the byte order of a 16-bit int if the CPU is little-endian */ - inline uint16 swapIfLittleEndian (const uint16 v) throw() { return swapByteOrder (v); } - /** Swaps the byte order of a 32-bit int if the CPU is little-endian */ - inline uint32 swapIfLittleEndian (const uint32 v) throw() { return swapByteOrder (v); } - /** Swaps the byte order of a 64-bit int if the CPU is little-endian */ - inline uint64 swapIfLittleEndian (const uint64 v) throw() { return swapByteOrder (v); } - - /** Turns 4 bytes into a little-endian integer. */ - inline uint32 littleEndianInt (const char* const bytes) throw() { return *(uint32*) bytes; } - /** Turns 2 bytes into a little-endian integer. */ - inline uint16 littleEndianShort (const char* const bytes) throw() { return *(uint16*) bytes; } - - /** Turns 4 bytes into a big-endian integer. */ - inline uint32 bigEndianInt (const char* const bytes) throw() { return swapByteOrder (*(uint32*) bytes); } - /** Turns 2 bytes into a big-endian integer. */ - inline uint16 bigEndianShort (const char* const bytes) throw() { return swapByteOrder (*(uint16*) bytes); } - -#else - /** Swaps the byte order of a 16-bit int if the CPU is big-endian */ - inline uint16 swapIfBigEndian (const uint16 v) throw() { return swapByteOrder (v); } - /** Swaps the byte order of a 32-bit int if the CPU is big-endian */ - inline uint32 swapIfBigEndian (const uint32 v) throw() { return swapByteOrder (v); } - /** Swaps the byte order of a 64-bit int if the CPU is big-endian */ - inline uint64 swapIfBigEndian (const uint64 v) throw() { return swapByteOrder (v); } - - /** Swaps the byte order of a 16-bit int if the CPU is little-endian */ - inline uint16 swapIfLittleEndian (const uint16 v) throw() { return v; } - /** Swaps the byte order of a 32-bit int if the CPU is little-endian */ - inline uint32 swapIfLittleEndian (const uint32 v) throw() { return v; } - /** Swaps the byte order of a 64-bit int if the CPU is little-endian */ - inline uint64 swapIfLittleEndian (const uint64 v) throw() { return v; } - - /** Turns 4 bytes into a little-endian integer. */ - inline uint32 littleEndianInt (const char* const bytes) throw() { return swapByteOrder (*(uint32*) bytes); } - /** Turns 2 bytes into a little-endian integer. */ - inline uint16 littleEndianShort (const char* const bytes) throw() { return swapByteOrder (*(uint16*) bytes); } - - /** Turns 4 bytes into a big-endian integer. */ - inline uint32 bigEndianInt (const char* const bytes) throw() { return *(uint32*) bytes; } - /** Turns 2 bytes into a big-endian integer. */ - inline uint16 bigEndianShort (const char* const bytes) throw() { return *(uint16*) bytes; } -#endif - -/** Converts 3 little-endian bytes into a signed 24-bit value (which is sign-extended to 32 bits). */ -inline int littleEndian24Bit (const char* const bytes) throw() { return (((int) bytes[2]) << 16) | (((uint32) (uint8) bytes[1]) << 8) | ((uint32) (uint8) bytes[0]); } -/** Converts 3 big-endian bytes into a signed 24-bit value (which is sign-extended to 32 bits). */ -inline int bigEndian24Bit (const char* const bytes) throw() { return (((int) bytes[0]) << 16) | (((uint32) (uint8) bytes[1]) << 8) | ((uint32) (uint8) bytes[2]); } - -/** Copies a 24-bit number to 3 little-endian bytes. */ -inline void littleEndian24BitToChars (const int value, char* const destBytes) throw() { destBytes[0] = (char)(value & 0xff); destBytes[1] = (char)((value >> 8) & 0xff); destBytes[2] = (char)((value >> 16) & 0xff); } -/** Copies a 24-bit number to 3 big-endian bytes. */ -inline void bigEndian24BitToChars (const int value, char* const destBytes) throw() { destBytes[0] = (char)((value >> 16) & 0xff); destBytes[1] = (char)((value >> 8) & 0xff); destBytes[2] = (char)(value & 0xff); } - /** Fast floating-point-to-integer conversion. This is faster than using the normal c++ cast to convert a double to an int, and @@ -1293,11 +1174,11 @@ inline int roundDoubleToInt (const double value) throw() union { int asInt[2]; double asDouble; } n; n.asDouble = value + 6755399441055744.0; -#if JUCE_BIG_ENDIAN - return n.asInt [1]; -#else - return n.asInt [0]; -#endif + #if JUCE_BIG_ENDIAN + return n.asInt [1]; + #else + return n.asInt [0]; + #endif } /** Fast floating-point-to-integer conversion. @@ -1325,15 +1206,158 @@ inline int roundFloatToInt (const float value) throw() union { int asInt[2]; double asDouble; } n; n.asDouble = value + 6755399441055744.0; -#if JUCE_BIG_ENDIAN - return n.asInt [1]; + #if JUCE_BIG_ENDIAN + return n.asInt [1]; + #else + return n.asInt [0]; + #endif +} + +#endif // __JUCE_MATHSFUNCTIONS_JUCEHEADER__ +/********* End of inlined file: juce_MathsFunctions.h *********/ + +/********* Start of inlined file: juce_ByteOrder.h *********/ +#ifndef __JUCE_BYTEORDER_JUCEHEADER__ +#define __JUCE_BYTEORDER_JUCEHEADER__ + +/** Contains static methods for converting the byte order between different + endiannesses. +*/ +class JUCE_API ByteOrder +{ +public: + + /** Swaps the upper and lower bytes of a 16-bit integer. */ + static uint16 swap (uint16 value); + + /** Reverses the order of the 4 bytes in a 32-bit integer. */ + static uint32 swap (uint32 value); + + /** Reverses the order of the 8 bytes in a 64-bit integer. */ + static uint64 swap (uint64 value); + + /** Swaps the byte order of a 16-bit int if the CPU is big-endian */ + static uint16 swapIfBigEndian (const uint16 value); + + /** Swaps the byte order of a 32-bit int if the CPU is big-endian */ + static uint32 swapIfBigEndian (const uint32 value); + + /** Swaps the byte order of a 64-bit int if the CPU is big-endian */ + static uint64 swapIfBigEndian (const uint64 value); + + /** Swaps the byte order of a 16-bit int if the CPU is little-endian */ + static uint16 swapIfLittleEndian (const uint16 value); + + /** Swaps the byte order of a 32-bit int if the CPU is little-endian */ + static uint32 swapIfLittleEndian (const uint32 value); + + /** Swaps the byte order of a 64-bit int if the CPU is little-endian */ + static uint64 swapIfLittleEndian (const uint64 value); + + /** Turns 4 bytes into a little-endian integer. */ + static uint32 littleEndianInt (const char* const bytes); + + /** Turns 2 bytes into a little-endian integer. */ + static uint16 littleEndianShort (const char* const bytes); + + /** Turns 4 bytes into a big-endian integer. */ + static uint32 bigEndianInt (const char* const bytes); + + /** Turns 2 bytes into a big-endian integer. */ + static uint16 bigEndianShort (const char* const bytes); + + /** Converts 3 little-endian bytes into a signed 24-bit value (which is sign-extended to 32 bits). */ + static int littleEndian24Bit (const char* const bytes); + + /** Converts 3 big-endian bytes into a signed 24-bit value (which is sign-extended to 32 bits). */ + static int bigEndian24Bit (const char* const bytes); + + /** Copies a 24-bit number to 3 little-endian bytes. */ + static void littleEndian24BitToChars (const int value, char* const destBytes); + + /** Copies a 24-bit number to 3 big-endian bytes. */ + static void bigEndian24BitToChars (const int value, char* const destBytes); + + /** Returns true if the current CPU is big-endian. */ + static bool isBigEndian(); +}; + +#if JUCE_USE_INTRINSICS + #pragma intrinsic (_byteswap_ulong) +#endif + +inline uint16 ByteOrder::swap (uint16 n) +{ +#if JUCE_USE_INTRINSICSxxx // agh - the MS compiler has an internal error when you try to use this intrinsic! + return (uint16) _byteswap_ushort (n); #else - return n.asInt [0]; + return (uint16) ((n << 8) | (n >> 8)); #endif } -#endif // __JUCE_DATACONVERSIONS_JUCEHEADER__ -/********* End of inlined file: juce_DataConversions.h *********/ +inline uint32 ByteOrder::swap (uint32 n) +{ +#if JUCE_MAC || JUCE_IPHONE + return OSSwapInt32 (n); +#elif JUCE_GCC + asm("bswap %%eax" : "=a"(n) : "a"(n)); + return n; +#elif JUCE_USE_INTRINSICS + return _byteswap_ulong (n); +#else + __asm { + mov eax, n + bswap eax + mov n, eax + } + return n; +#endif +} + +inline uint64 ByteOrder::swap (uint64 value) +{ +#if JUCE_MAC || JUCE_IPHONE + return OSSwapInt64 (value); +#elif JUCE_USE_INTRINSICS + return _byteswap_uint64 (value); +#else + return (((int64) swap ((uint32) value)) << 32) | swap ((uint32) (value >> 32)); +#endif +} + +#if JUCE_LITTLE_ENDIAN + inline uint16 ByteOrder::swapIfBigEndian (const uint16 v) { return v; } + inline uint32 ByteOrder::swapIfBigEndian (const uint32 v) { return v; } + inline uint64 ByteOrder::swapIfBigEndian (const uint64 v) { return v; } + inline uint16 ByteOrder::swapIfLittleEndian (const uint16 v) { return swap (v); } + inline uint32 ByteOrder::swapIfLittleEndian (const uint32 v) { return swap (v); } + inline uint64 ByteOrder::swapIfLittleEndian (const uint64 v) { return swap (v); } + inline uint32 ByteOrder::littleEndianInt (const char* const bytes) { return *(uint32*) bytes; } + inline uint16 ByteOrder::littleEndianShort (const char* const bytes) { return *(uint16*) bytes; } + inline uint32 ByteOrder::bigEndianInt (const char* const bytes) { return swap (*(uint32*) bytes); } + inline uint16 ByteOrder::bigEndianShort (const char* const bytes) { return swap (*(uint16*) bytes); } + inline bool ByteOrder::isBigEndian() { return false; } +#else + inline uint16 ByteOrder::swapIfBigEndian (const uint16 v) { return swap (v); } + inline uint32 ByteOrder::swapIfBigEndian (const uint32 v) { return swap (v); } + inline uint64 ByteOrder::swapIfBigEndian (const uint64 v) { return swap (v); } + inline uint16 ByteOrder::swapIfLittleEndian (const uint16 v) { return v; } + inline uint32 ByteOrder::swapIfLittleEndian (const uint32 v) { return v; } + inline uint64 ByteOrder::swapIfLittleEndian (const uint64 v) { return v; } + inline uint32 ByteOrder::littleEndianInt (const char* const bytes) { return swap (*(uint32*) bytes); } + inline uint16 ByteOrder::littleEndianShort (const char* const bytes) { return swap (*(uint16*) bytes); } + inline uint32 ByteOrder::bigEndianInt (const char* const bytes) { return *(uint32*) bytes; } + inline uint16 ByteOrder::bigEndianShort (const char* const bytes) { return *(uint16*) bytes; } + inline bool ByteOrder::isBigEndian() { return true; } +#endif + +inline int ByteOrder::littleEndian24Bit (const char* const bytes) { return (((int) bytes[2]) << 16) | (((uint32) (uint8) bytes[1]) << 8) | ((uint32) (uint8) bytes[0]); } +inline int ByteOrder::bigEndian24Bit (const char* const bytes) { return (((int) bytes[0]) << 16) | (((uint32) (uint8) bytes[1]) << 8) | ((uint32) (uint8) bytes[2]); } +inline void ByteOrder::littleEndian24BitToChars (const int value, char* const destBytes) { destBytes[0] = (char)(value & 0xff); destBytes[1] = (char)((value >> 8) & 0xff); destBytes[2] = (char)((value >> 16) & 0xff); } +inline void ByteOrder::bigEndian24BitToChars (const int value, char* const destBytes) { destBytes[0] = (char)((value >> 16) & 0xff); destBytes[1] = (char)((value >> 8) & 0xff); destBytes[2] = (char)(value & 0xff); } + +#endif // __JUCE_BYTEORDER_JUCEHEADER__ +/********* End of inlined file: juce_ByteOrder.h *********/ /********* Start of inlined file: juce_Logger.h *********/ #ifndef __JUCE_LOGGER_JUCEHEADER__ @@ -2508,6 +2532,31 @@ public: */ void preallocateStorage (const int numCharsNeeded) throw(); + /** A helper class to improve performance when concatenating many large strings + together. + + Because appending one string to another involves measuring the length of + both strings, repeatedly doing this for many long strings will become + an exponentially slow operation. This class uses some internal state to + avoid that, so that each append operation only needs to measure the length + of the appended string. + */ + class JUCE_API Concatenator + { + public: + Concatenator (String& stringToAppendTo); + ~Concatenator(); + + void append (const String& s); + + private: + String& result; + int nextIndex; + + Concatenator (const Concatenator&); + const Concatenator& operator= (const Concatenator&); + }; + juce_UseDebuggingNewOperator // (adds debugging info to find leaked objects) private: @@ -2723,7 +2772,7 @@ public: elements = newElements; } - else if (elements != 0) + else { delete[] elements; elements = 0; @@ -4308,12 +4357,14 @@ public: Obviously there's no bounds-checking here, as this object is just a dumb pointer and has no idea of the size it currently has allocated. */ - inline ElementType& operator[] (const pointer_sized_int index) const { return data [index]; } + template + inline ElementType& operator[] (IndexType index) const { return data [index]; } /** Returns a pointer to a data element at an offset from the start of the array. This is the same as doing pointer arithmetic on the raw pointer itself. */ - inline ElementType* operator+ (const pointer_sized_int index) const { return data + index; } + template + inline ElementType* operator+ (IndexType index) const { return data + index; } /** Returns a reference to the raw data pointer. Beware that the pointer returned here will become invalid as soon as you call @@ -4954,7 +5005,7 @@ private: can use the release() method. */ template -class ScopedPointer +class JUCE_API ScopedPointer { public: @@ -4997,7 +5048,7 @@ public: */ const ScopedPointer& operator= (ScopedPointer& objectToTransferFrom) { - if (this != &objectToTransferFrom) + if (this != objectToTransferFrom.getAddress()) { // Two ScopedPointers should never be able to refer to the same object - if // this happens, you must have done something dodgy! @@ -5080,6 +5131,9 @@ public: private: ObjectType* object; + + // (Required as an alternative to the overloaded & operator). + ScopedPointer* getAddress() { return this; } }; #endif // __JUCE_SCOPEDPOINTER_JUCEHEADER__ @@ -9016,182 +9070,175 @@ private: #ifndef __JUCE_ATOMIC_JUCEHEADER__ #define __JUCE_ATOMIC_JUCEHEADER__ -// Atomic increment/decrement operations.. +/** Contains static functions for thread-safe atomic operations. +*/ +class JUCE_API Atomic +{ +public: + /** Increments an integer in a thread-safe way. */ + static void increment (int& variable); -#if (JUCE_MAC || JUCE_IPHONE) && ! DOXYGEN + /** Increments an integer in a thread-safe way and returns its new value. */ + static int incrementAndReturn (int& variable); - #include - static forcedinline void atomicIncrement (int& variable) throw() { OSAtomicIncrement32 ((int32_t*) &variable); } - static forcedinline int atomicIncrementAndReturn (int& variable) throw() { return OSAtomicIncrement32 ((int32_t*) &variable); } - static forcedinline void atomicDecrement (int& variable) throw() { OSAtomicDecrement32 ((int32_t*) &variable); } - static forcedinline int atomicDecrementAndReturn (int& variable) throw() { return OSAtomicDecrement32 ((int32_t*) &variable); } + /** Decrements an integer in a thread-safe way. */ + static void decrement (int& variable); -#elif JUCE_GCC + /** Decrements an integer in a thread-safe way and returns its new value. */ + static int decrementAndReturn (int& variable); +}; - #if JUCE_USE_GCC_ATOMIC_INTRINSICS - forcedinline void atomicIncrement (int& variable) throw() { __sync_add_and_fetch (&variable, 1); } - forcedinline int atomicIncrementAndReturn (int& variable) throw() { return __sync_add_and_fetch (&variable, 1); } - forcedinline void atomicDecrement (int& variable) throw() { __sync_add_and_fetch (&variable, -1); } - forcedinline int atomicDecrementAndReturn (int& variable) throw() { return __sync_add_and_fetch (&variable, -1); } - #else +#if (JUCE_MAC || JUCE_IPHONE) // Mac and iPhone... - /** Increments an integer in a thread-safe way. */ - forcedinline void atomicIncrement (int& variable) throw() - { - __asm__ __volatile__ ( - #if JUCE_64BIT - "lock incl (%%rax)" - : - : "a" (&variable) - : "cc", "memory"); - #else - "lock incl %0" - : "=m" (variable) - : "m" (variable)); - #endif - } +#include +inline void Atomic::increment (int& variable) { OSAtomicIncrement32 ((int32_t*) &variable); } +inline int Atomic::incrementAndReturn (int& variable) { return OSAtomicIncrement32 ((int32_t*) &variable); } +inline void Atomic::decrement (int& variable) { OSAtomicDecrement32 ((int32_t*) &variable); } +inline int Atomic::decrementAndReturn (int& variable) { return OSAtomicDecrement32 ((int32_t*) &variable); } - /** Increments an integer in a thread-safe way and returns the incremented value. */ - forcedinline int atomicIncrementAndReturn (int& variable) throw() - { - int result; +#elif JUCE_GCC - __asm__ __volatile__ ( - #if JUCE_64BIT - "lock xaddl %%ebx, (%%rax) \n\ - incl %%ebx" - : "=b" (result) - : "a" (&variable), "b" (1) - : "cc", "memory"); - #else - "lock xaddl %%eax, (%%ecx) \n\ - incl %%eax" - : "=a" (result) - : "c" (&variable), "a" (1) - : "memory"); - #endif +#if JUCE_USE_GCC_ATOMIC_INTRINSICS // Linux with intrinsics... - return result; - } +inline void Atomic::increment (int& variable) { __sync_add_and_fetch (&variable, 1); } +inline int Atomic::incrementAndReturn (int& variable) { return __sync_add_and_fetch (&variable, 1); } +inline void Atomic::decrement (int& variable) { __sync_add_and_fetch (&variable, -1); } +inline int Atomic::decrementAndReturn (int& variable) { return __sync_add_and_fetch (&variable, -1); } - /** Decrememts an integer in a thread-safe way. */ - forcedinline void atomicDecrement (int& variable) throw() - { - __asm__ __volatile__ ( - #if JUCE_64BIT - "lock decl (%%rax)" - : - : "a" (&variable) - : "cc", "memory"); - #else - "lock decl %0" - : "=m" (variable) - : "m" (variable)); - #endif - } +#else // Linux without intrinsics... - /** Decrememts an integer in a thread-safe way and returns the incremented value. */ - forcedinline int atomicDecrementAndReturn (int& variable) throw() - { - int result; +inline void Atomic::increment (int& variable) +{ + __asm__ __volatile__ ( + #if JUCE_64BIT + "lock incl (%%rax)" + : + : "a" (&variable) + : "cc", "memory"); + #else + "lock incl %0" + : "=m" (variable) + : "m" (variable)); + #endif +} - __asm__ __volatile__ ( - #if JUCE_64BIT - "lock xaddl %%ebx, (%%rax) \n\ - decl %%ebx" - : "=b" (result) - : "a" (&variable), "b" (-1) - : "cc", "memory"); - #else - "lock xaddl %%eax, (%%ecx) \n\ - decl %%eax" - : "=a" (result) - : "c" (&variable), "a" (-1) - : "memory"); - #endif - return result; - } - #endif +inline int Atomic::incrementAndReturn (int& variable) +{ + int result; -#elif JUCE_USE_INTRINSICS + __asm__ __volatile__ ( + #if JUCE_64BIT + "lock xaddl %%ebx, (%%rax) \n\ + incl %%ebx" + : "=b" (result) + : "a" (&variable), "b" (1) + : "cc", "memory"); + #else + "lock xaddl %%eax, (%%ecx) \n\ + incl %%eax" + : "=a" (result) + : "c" (&variable), "a" (1) + : "memory"); + #endif - #pragma intrinsic (_InterlockedIncrement) - #pragma intrinsic (_InterlockedDecrement) + return result; +} - /** Increments an integer in a thread-safe way. */ - forcedinline void __fastcall atomicIncrement (int& variable) throw() - { - _InterlockedIncrement (reinterpret_cast (&variable)); - } +inline void Atomic::decrement (int& variable) +{ + __asm__ __volatile__ ( + #if JUCE_64BIT + "lock decl (%%rax)" + : + : "a" (&variable) + : "cc", "memory"); + #else + "lock decl %0" + : "=m" (variable) + : "m" (variable)); + #endif +} - /** Increments an integer in a thread-safe way and returns the incremented value. */ - forcedinline int __fastcall atomicIncrementAndReturn (int& variable) throw() - { - return _InterlockedIncrement (reinterpret_cast (&variable)); - } +inline int Atomic::decrementAndReturn (int& variable) +{ + int result; - /** Decrememts an integer in a thread-safe way. */ - forcedinline void __fastcall atomicDecrement (int& variable) throw() - { - _InterlockedDecrement (reinterpret_cast (&variable)); - } + __asm__ __volatile__ ( + #if JUCE_64BIT + "lock xaddl %%ebx, (%%rax) \n\ + decl %%ebx" + : "=b" (result) + : "a" (&variable), "b" (-1) + : "cc", "memory"); + #else + "lock xaddl %%eax, (%%ecx) \n\ + decl %%eax" + : "=a" (result) + : "c" (&variable), "a" (-1) + : "memory"); + #endif + return result; +} +#endif - /** Decrememts an integer in a thread-safe way and returns the incremented value. */ - forcedinline int __fastcall atomicDecrementAndReturn (int& variable) throw() - { - return _InterlockedDecrement (reinterpret_cast (&variable)); - } -#else +#elif JUCE_USE_INTRINSICS // Windows with intrinsics... - /** Increments an integer in a thread-safe way. */ - forcedinline void __fastcall atomicIncrement (int& variable) throw() - { - __asm { - mov ecx, dword ptr [variable] - lock inc dword ptr [ecx] - } - } +#pragma intrinsic (_InterlockedIncrement) +#pragma intrinsic (_InterlockedDecrement) - /** Increments an integer in a thread-safe way and returns the incremented value. */ - forcedinline int __fastcall atomicIncrementAndReturn (int& variable) throw() - { - int result; +inline void Atomic::increment (int& variable) { _InterlockedIncrement (reinterpret_cast (&variable)); } +inline int Atomic::incrementAndReturn (int& variable) { return _InterlockedIncrement (reinterpret_cast (&variable)); } +inline void Atomic::decrement (int& variable) { _InterlockedDecrement (reinterpret_cast (&variable)); } +inline int Atomic::decrementAndReturn (int& variable) { return _InterlockedDecrement (reinterpret_cast (&variable)); } - __asm { - mov ecx, dword ptr [variable] - mov eax, 1 - lock xadd dword ptr [ecx], eax - inc eax - mov result, eax - } +#else // Windows without intrinsics... - return result; +inline void Atomic::increment (int& variable) +{ + __asm { + mov ecx, dword ptr [variable] + lock inc dword ptr [ecx] } +} - /** Decrememts an integer in a thread-safe way. */ - forcedinline void __fastcall atomicDecrement (int& variable) throw() - { - __asm { - mov ecx, dword ptr [variable] - lock dec dword ptr [ecx] - } +inline int Atomic::incrementAndReturn (int& variable) +{ + int result; + + __asm { + mov ecx, dword ptr [variable] + mov eax, 1 + lock xadd dword ptr [ecx], eax + inc eax + mov result, eax } - /** Decrememts an integer in a thread-safe way and returns the incremented value. */ - forcedinline int __fastcall atomicDecrementAndReturn (int& variable) throw() - { - int result; + return result; +} - __asm { - mov ecx, dword ptr [variable] - mov eax, -1 - lock xadd dword ptr [ecx], eax - dec eax - mov result, eax - } +inline void Atomic::decrement (int& variable) +{ + __asm { + mov ecx, dword ptr [variable] + lock dec dword ptr [ecx] + } +} - return result; +inline int Atomic::decrementAndReturn (int& variable) +{ + int result; + + __asm { + mov ecx, dword ptr [variable] + mov eax, -1 + lock xadd dword ptr [ecx], eax + dec eax + mov result, eax } + + return result; +} + #endif #endif // __JUCE_ATOMIC_JUCEHEADER__ @@ -9235,7 +9282,7 @@ public: */ inline void incReferenceCount() throw() { - atomicIncrement (refCounts); + Atomic::increment (refCounts); jassert (refCounts > 0); } @@ -9248,7 +9295,7 @@ public: { jassert (refCounts > 0); - if (atomicDecrementAndReturn (refCounts) == 0) + if (Atomic::decrementAndReturn (refCounts) == 0) delete this; } @@ -11607,20 +11654,29 @@ public: */ const Value& operator= (const var& newValue); - /** Makes this object refer to the same underlying value as another one. + /** Makes this object refer to the same underlying ValueSource as another one. + + Once this object has been connected to another one, changing either one + will update the other. + Existing listeners will still be registered after you call this method, and + they'll continue to receive messages when the new value changes. */ void referTo (const Value& valueToReferTo); - /** + /** Returns true if this value and the other one are references to the same value. */ bool refersToSameSourceAs (const Value& other) const; - /** + /** Compares two values. + This is a compare-by-value comparison, so is effectively the same as + saying (this->getValue() == other.getValue()). */ bool operator== (const Value& other) const; - /** + /** Compares two values. + This is a compare-by-value comparison, so is effectively the same as + saying (this->getValue() != other.getValue()). */ bool operator!= (const Value& other) const; @@ -11701,6 +11757,8 @@ public: /** @internal */ explicit Value (ValueSource* const valueSource); + /** @internal */ + ValueSource& getValueSource() { return *value; } juce_UseDebuggingNewOperator @@ -12668,7 +12726,7 @@ typedef Array VoidArray; #ifndef __JUCE_ATOMIC_JUCEHEADER__ #endif -#ifndef __JUCE_DATACONVERSIONS_JUCEHEADER__ +#ifndef __JUCE_BYTEORDER_JUCEHEADER__ #endif #ifndef __JUCE_FILELOGGER_JUCEHEADER__ @@ -15898,6 +15956,8 @@ private: int findNextTokenLength() throw(); void readQuotedString (String& result) throw(); void readEntity (String& result) throw(); + static bool isXmlIdentifierCharSlow (const tchar c) throw(); + bool isXmlIdentifierChar (const tchar c) const throw(); const String getFileContents (const String& filename) const; const String expandEntity (const String& entity); @@ -31870,6 +31930,7 @@ public: class JUCE_API Button : public Component, public SettableTooltipClient, public ApplicationCommandManagerListener, + public Value::Listener, private KeyListener { protected: @@ -31938,7 +31999,15 @@ public: @see setToggleState */ - bool getToggleState() const throw() { return isOn; } + bool getToggleState() const throw() { return isOn.getValue(); } + + /** Returns the Value object that represents the botton's toggle state. + You can use this Value object to connect the button's state to external values or setters, + either by taking a copy of the Value, or by using Value::referTo() to make it point to + your own Value object. + @see getToggleState, Value + */ + Value& getToggleStateValue() { return isOn; } /** This tells the button to automatically flip the toggle state when the button is clicked. @@ -32238,6 +32307,8 @@ protected: void applicationCommandInvoked (const ApplicationCommandTarget::InvocationInfo&); /** @internal */ void applicationCommandListChanged(); + /** @internal */ + void valueChanged (Value& value); private: @@ -32254,7 +32325,8 @@ private: int radioGroupId, commandID, connectedEdgeFlags; ButtonState buttonState; - bool isOn : 1; + Value isOn; + bool lastToggleState : 1; bool clickTogglesState : 1; bool needsToRelease : 1; bool needsRepainting : 1; @@ -33268,7 +33340,7 @@ public: /** Returns true if the editor is in multi-line mode. */ - bool isMultiLine() const throw(); + bool isMultiLine() const; /** Changes the behaviour of the return key. @@ -33283,7 +33355,7 @@ public: See setReturnKeyStartsNewLine() for more info. */ - bool getReturnKeyStartsNewLine() const throw() { return returnKeyStartsNewLine; } + bool getReturnKeyStartsNewLine() const { return returnKeyStartsNewLine; } /** Indicates whether the tab key should be accepted and used to input a tab character, or whether it gets ignored. @@ -33291,12 +33363,12 @@ public: By default the tab key is ignored, so that it can be used to switch keyboard focus between components. */ - void setTabKeyUsedAsCharacter (const bool shouldTabKeyBeUsed) throw(); + void setTabKeyUsedAsCharacter (const bool shouldTabKeyBeUsed); /** Returns true if the tab key is being used for input. @see setTabKeyUsedAsCharacter */ - bool isTabKeyUsedAsCharacter() const throw() { return tabKeyUsed; } + bool isTabKeyUsedAsCharacter() const { return tabKeyUsed; } /** Changes the editor to read-only mode. @@ -33311,7 +33383,7 @@ public: /** Returns true if the editor is in read-only mode. */ - bool isReadOnly() const throw(); + bool isReadOnly() const; /** Makes the caret visible or invisible. @@ -33319,12 +33391,12 @@ public: @see setCaretColour, setCaretPosition */ - void setCaretVisible (const bool shouldBeVisible) throw(); + void setCaretVisible (const bool shouldBeVisible); /** Returns true if the caret is enabled. @see setCaretVisible */ - bool isCaretVisible() const throw() { return caretVisible; } + bool isCaretVisible() const { return caretVisible; } /** Enables/disables a vertical scrollbar. @@ -33334,12 +33406,12 @@ public: By default the scrollbar is enabled. */ - void setScrollbarsShown (bool shouldBeEnabled) throw(); + void setScrollbarsShown (bool shouldBeEnabled); /** Returns true if scrollbars are enabled. @see setScrollbarsShown */ - bool areScrollbarsShown() const throw() { return scrollbarVisible; } + bool areScrollbarsShown() const { return scrollbarVisible; } /** Changes the password character used to disguise the text. @@ -33350,12 +33422,12 @@ public: for a black splodge (not all fonts include this, though), or 0x2022, which is a bullet (probably the best choice for linux). */ - void setPasswordCharacter (const tchar passwordCharacter) throw(); + void setPasswordCharacter (const tchar passwordCharacter); /** Returns the current password character. @see setPasswordCharacter l */ - tchar getPasswordCharacter() const throw() { return passwordCharacter; } + tchar getPasswordCharacter() const { return passwordCharacter; } /** Allows a right-click menu to appear for the editor. @@ -33364,16 +33436,16 @@ l */ If enabled, right-clicking (or command-clicking on the Mac) will pop up a menu of options such as cut/copy/paste, undo/redo, etc. */ - void setPopupMenuEnabled (const bool menuEnabled) throw(); + void setPopupMenuEnabled (const bool menuEnabled); /** Returns true if the right-click menu is enabled. @see setPopupMenuEnabled */ - bool isPopupMenuEnabled() const throw() { return popupMenuEnabled; } + bool isPopupMenuEnabled() const { return popupMenuEnabled; } /** Returns true if a popup-menu is currently being displayed. */ - bool isPopupMenuCurrentlyActive() const throw() { return menuActive; } + bool isPopupMenuCurrentlyActive() const { return menuActive; } /** A set of colour IDs to use to change the colour of various aspects of the editor. @@ -33418,7 +33490,7 @@ l */ @see applyFontToAllText */ - void setFont (const Font& newFont) throw(); + void setFont (const Font& newFont); /** Applies a font to all the text in the editor. @@ -33432,7 +33504,7 @@ l */ @see setFont */ - const Font getFont() const throw(); + const Font getFont() const; /** If set to true, focusing on the editor will highlight all its text. @@ -33441,7 +33513,7 @@ l */ This is useful for boxes where you expect the user to re-enter all the text when they focus on the component, rather than editing what's already there. */ - void setSelectAllWhenFocused (const bool b) throw(); + void setSelectAllWhenFocused (const bool b); /** Sets limits on the characters that can be entered. @@ -33451,7 +33523,7 @@ l */ this string are allowed to be entered into the editor. */ void setInputRestrictions (const int maxTextLength, - const String& allowedCharacters = String::empty) throw(); + const String& allowedCharacters = String::empty); /** When the text editor is empty, it can be set to display a message. @@ -33459,7 +33531,7 @@ l */ string is only displayed, it's not taken to actually be the contents of the editor. */ - void setTextToShowWhenEmpty (const String& text, const Colour& colourToUse) throw(); + void setTextToShowWhenEmpty (const String& text, const Colour& colourToUse); /** Changes the size of the scrollbars that are used. @@ -33477,25 +33549,25 @@ l */ @see removeListener */ - void addListener (TextEditorListener* const newListener) throw(); + void addListener (TextEditorListener* const newListener); /** Deregisters a listener. @see addListener */ - void removeListener (TextEditorListener* const listenerToRemove) throw(); + void removeListener (TextEditorListener* const listenerToRemove); /** Returns the entire contents of the editor. */ - const String getText() const throw(); + const String getText() const; /** Returns a section of the contents of the editor. */ - const String getTextSubstring (const int startCharacter, const int endCharacter) const throw(); + const String getTextSubstring (const int startCharacter, const int endCharacter) const; /** Returns true if there are no characters in the editor. This is more efficient than calling getText().isEmpty(). */ - bool isEmpty() const throw(); + bool isEmpty() const; /** Sets the entire content of the editor. @@ -33512,6 +33584,14 @@ l */ void setText (const String& newText, const bool sendTextChangeMessage = true); + /** Returns a Value object that can be used to get or set the text. + + Bear in mind that this operate quite slowly if your text box contains large + amounts of text, as it needs to dynamically build the string that's involved. It's + best used for small text boxes. + */ + Value& getTextValue(); + /** Inserts some text at the current cursor position. If a section of the text is highlighted, it will be replaced by @@ -33549,13 +33629,13 @@ l */ @see getCaretPosition */ - void setCaretPosition (const int newIndex) throw(); + void setCaretPosition (const int newIndex); /** Returns the current index of the caret. @see setCaretPosition */ - int getCaretPosition() const throw(); + int getCaretPosition() const; /** Attempts to scroll the text editor so that the caret ends up at a specified position. @@ -33569,19 +33649,19 @@ l */ will go as far as it can in that direction. */ void scrollEditorToPositionCaret (const int desiredCaretX, - const int desiredCaretY) throw(); + const int desiredCaretY); /** Get the graphical position of the caret. The rectangle returned is relative to the component's top-left corner. @see scrollEditorToPositionCaret */ - const Rectangle getCaretRectangle() throw(); + const Rectangle getCaretRectangle(); /** Selects a section of the text. */ void setHighlightedRegion (int startIndex, - int numberOfCharactersToHighlight) throw(); + int numberOfCharactersToHighlight); /** Returns the first character that is selected. @@ -33590,68 +33670,68 @@ l */ @see setHighlightedRegion, getHighlightedRegionLength */ - int getHighlightedRegionStart() const throw() { return selectionStart; } + int getHighlightedRegionStart() const { return selectionStart; } /** Returns the number of characters that are selected. @see setHighlightedRegion, getHighlightedRegionStart */ - int getHighlightedRegionLength() const throw() { return jmax (0, selectionEnd - selectionStart); } + int getHighlightedRegionLength() const { return jmax (0, selectionEnd - selectionStart); } /** Returns the section of text that is currently selected. */ - const String getHighlightedText() const throw(); + const String getHighlightedText() const; /** Finds the index of the character at a given position. The co-ordinates are relative to the component's top-left. */ - int getTextIndexAt (const int x, const int y) throw(); + int getTextIndexAt (const int x, const int y); /** Counts the number of characters in the text. This is quicker than getting the text as a string if you just need to know the length. */ - int getTotalNumChars() throw(); + int getTotalNumChars() const; /** Returns the total width of the text, as it is currently laid-out. This may be larger than the size of the TextEditor, and can change when the TextEditor is resized or the text changes. */ - int getTextWidth() const throw(); + int getTextWidth() const; /** Returns the maximum height of the text, as it is currently laid-out. This may be larger than the size of the TextEditor, and can change when the TextEditor is resized or the text changes. */ - int getTextHeight() const throw(); + int getTextHeight() const; /** Changes the size of the gap at the top and left-edge of the editor. By default there's a gap of 4 pixels. */ - void setIndents (const int newLeftIndent, const int newTopIndent) throw(); + void setIndents (const int newLeftIndent, const int newTopIndent); /** Changes the size of border left around the edge of the component. @see getBorder */ - void setBorder (const BorderSize& border) throw(); + void setBorder (const BorderSize& border); /** Returns the size of border around the edge of the component. @see setBorder */ - const BorderSize getBorder() const throw(); + const BorderSize getBorder() const; /** Used to disable the auto-scrolling which keeps the cursor visible. If true (the default), the editor will scroll when the cursor moves offscreen. If set to false, it won't. */ - void setScrollToShowCursor (const bool shouldScrollToShowCursor) throw(); + void setScrollToShowCursor (const bool shouldScrollToShowCursor); /** @internal */ void paint (Graphics& g); @@ -33724,20 +33804,20 @@ protected: virtual void performPopupMenuAction (const int menuItemID); /** Scrolls the minimum distance needed to get the caret into view. */ - void scrollToMakeSureCursorIsVisible() throw(); + void scrollToMakeSureCursorIsVisible(); /** @internal */ - void moveCaret (int newCaretPos) throw(); + void moveCaret (int newCaretPos); /** @internal */ - void moveCursorTo (const int newPosition, const bool isSelecting) throw(); + void moveCursorTo (const int newPosition, const bool isSelecting); /** Used internally to dispatch a text-change message. */ - void textChanged() throw(); + void textChanged(); /** Begins a new transaction in the UndoManager. */ - void newTransaction() throw(); + void newTransaction(); /** Used internally to trigger an undo or redo. */ void doUndoRedo (const bool isRedo); @@ -33770,6 +33850,7 @@ private: bool keepCursorOnScreen : 1; bool tabKeyUsed : 1; bool menuActive : 1; + bool valueTextNeedsUpdating : 1; UndoManager undoManager; float cursorX, cursorY, cursorHeight; @@ -33778,11 +33859,13 @@ private: int leftIndent, topIndent; unsigned int lastTransactionTime; Font currentFont; - int totalNumChars, caretPosition; + mutable int totalNumChars; + int caretPosition; VoidArray sections; String textToShowWhenEmpty; Colour colourForTextWhenEmpty; tchar passwordCharacter; + Value textValue; enum { @@ -33797,43 +33880,45 @@ private: friend class TextEditorInsertAction; friend class TextEditorRemoveAction; - void coalesceSimilarSections() throw(); - void splitSection (const int sectionIndex, const int charToSplitAt) throw(); + void coalesceSimilarSections(); + void splitSection (const int sectionIndex, const int charToSplitAt); - void clearInternal (UndoManager* const um) throw(); + void clearInternal (UndoManager* const um); void insert (const String& text, const int insertIndex, const Font& font, const Colour& colour, UndoManager* const um, - const int caretPositionToMoveTo) throw(); + const int caretPositionToMoveTo); void reinsert (const int insertIndex, - const VoidArray& sections) throw(); + const VoidArray& sections); void remove (const int startIndex, int endIndex, UndoManager* const um, - const int caretPositionToMoveTo) throw(); + const int caretPositionToMoveTo); void getCharPosition (const int index, float& x, float& y, - float& lineHeight) const throw(); + float& lineHeight) const; + + void updateCaretPosition(); - void updateCaretPosition() throw(); + void textWasChangedByValue(); int indexAtPosition (const float x, - const float y) throw(); + const float y); - int findWordBreakAfter (const int position) const throw(); - int findWordBreakBefore (const int position) const throw(); + int findWordBreakAfter (const int position) const; + int findWordBreakBefore (const int position) const; friend class TextHolderComponent; friend class TextEditorViewport; void drawContent (Graphics& g); - void updateTextHolderSize() throw(); - float getWordWrapWidth() const throw(); + void updateTextHolderSize(); + float getWordWrapWidth() const; void timerCallbackInt(); void repaintCaret(); void repaintText (int textStartIndex, int textEndIndex); diff --git a/src/audio/audio_file_formats/juce_AiffAudioFormat.cpp b/src/audio/audio_file_formats/juce_AiffAudioFormat.cpp index 26dfe7a7d4..c1951d49b7 100644 --- a/src/audio/audio_file_formats/juce_AiffAudioFormat.cpp +++ b/src/audio/audio_file_formats/juce_AiffAudioFormat.cpp @@ -32,12 +32,8 @@ BEGIN_JUCE_NAMESPACE #include "../../core/juce_PlatformUtilities.h" #include "../../text/juce_LocalisedStrings.h" - -#undef chunkName -#define chunkName(a) (int)littleEndianInt(a) - //============================================================================== -#define aiffFormatName TRANS("AIFF file") +static const char* const aiffFormatName = "AIFF file"; static const tchar* const aiffExtensions[] = { T(".aiff"), T(".aif"), 0 }; @@ -51,7 +47,7 @@ public: //============================================================================== AiffAudioFormatReader (InputStream* in) - : AudioFormatReader (in, aiffFormatName) + : AudioFormatReader (in, TRANS (aiffFormatName)) { if (input->readInt() == chunkName ("FORM")) { @@ -97,9 +93,9 @@ public: || (byte0 == 0x40 && sampleRateBytes[1] > 0x1C)) break; - unsigned int sampRate = bigEndianInt ((char*) sampleRateBytes + 2); - sampRate >>= (16414 - bigEndianShort ((char*) sampleRateBytes)); - sampleRate = (int)sampRate; + unsigned int sampRate = ByteOrder::bigEndianInt ((char*) sampleRateBytes + 2); + sampRate >>= (16414 - ByteOrder::bigEndianShort ((char*) sampleRateBytes)); + sampleRate = (int) sampRate; if (length <= 18) { @@ -202,7 +198,7 @@ public: { for (int i = numThisTime; --i >= 0;) { - *right++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16; + *right++ = (int) ByteOrder::swapIfBigEndian ((unsigned short) *src++) << 16; ++src; } } @@ -211,15 +207,15 @@ public: for (int i = numThisTime; --i >= 0;) { ++src; - *left++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16; + *left++ = (int) ByteOrder::swapIfBigEndian ((unsigned short) *src++) << 16; } } else { for (int i = numThisTime; --i >= 0;) { - *left++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16; - *right++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16; + *left++ = (int) ByteOrder::swapIfBigEndian ((unsigned short) *src++) << 16; + *right++ = (int) ByteOrder::swapIfBigEndian ((unsigned short) *src++) << 16; } } } @@ -227,7 +223,7 @@ public: { for (int i = numThisTime; --i >= 0;) { - *left++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16; + *left++ = (int) ByteOrder::swapIfBigEndian ((unsigned short) *src++) << 16; } } } @@ -241,7 +237,7 @@ public: { for (int i = numThisTime; --i >= 0;) { - *right++ = bigEndianShort (src) << 16; + *right++ = ByteOrder::bigEndianShort (src) << 16; src += 4; } } @@ -250,7 +246,7 @@ public: for (int i = numThisTime; --i >= 0;) { src += 2; - *left++ = bigEndianShort (src) << 16; + *left++ = ByteOrder::bigEndianShort (src) << 16; src += 2; } } @@ -258,9 +254,9 @@ public: { for (int i = numThisTime; --i >= 0;) { - *left++ = bigEndianShort (src) << 16; + *left++ = ByteOrder::bigEndianShort (src) << 16; src += 2; - *right++ = bigEndianShort (src) << 16; + *right++ = ByteOrder::bigEndianShort (src) << 16; src += 2; } } @@ -269,7 +265,7 @@ public: { for (int i = numThisTime; --i >= 0;) { - *left++ = bigEndianShort (src) << 16; + *left++ = ByteOrder::bigEndianShort (src) << 16; src += 2; } } @@ -287,7 +283,7 @@ public: { for (int i = numThisTime; --i >= 0;) { - *right++ = littleEndian24Bit (src) << 8; + *right++ = ByteOrder::littleEndian24Bit (src) << 8; src += 6; } } @@ -296,7 +292,7 @@ public: for (int i = numThisTime; --i >= 0;) { src += 3; - *left++ = littleEndian24Bit (src) << 8; + *left++ = ByteOrder::littleEndian24Bit (src) << 8; src += 3; } } @@ -304,9 +300,9 @@ public: { for (int i = numThisTime; --i >= 0;) { - *left++ = littleEndian24Bit (src) << 8; + *left++ = ByteOrder::littleEndian24Bit (src) << 8; src += 3; - *right++ = littleEndian24Bit (src) << 8; + *right++ = ByteOrder::littleEndian24Bit (src) << 8; src += 3; } } @@ -315,7 +311,7 @@ public: { for (int i = numThisTime; --i >= 0;) { - *left++ = littleEndian24Bit (src) << 8; + *left++ = ByteOrder::littleEndian24Bit (src) << 8; src += 3; } } @@ -328,7 +324,7 @@ public: { for (int i = numThisTime; --i >= 0;) { - *right++ = bigEndian24Bit (src) << 8; + *right++ = ByteOrder::bigEndian24Bit (src) << 8; src += 6; } } @@ -337,7 +333,7 @@ public: for (int i = numThisTime; --i >= 0;) { src += 3; - *left++ = bigEndian24Bit (src) << 8; + *left++ = ByteOrder::bigEndian24Bit (src) << 8; src += 3; } } @@ -345,9 +341,9 @@ public: { for (int i = numThisTime; --i >= 0;) { - *left++ = bigEndian24Bit (src) << 8; + *left++ = ByteOrder::bigEndian24Bit (src) << 8; src += 3; - *right++ = bigEndian24Bit (src) << 8; + *right++ = ByteOrder::bigEndian24Bit (src) << 8; src += 3; } } @@ -356,7 +352,7 @@ public: { for (int i = numThisTime; --i >= 0;) { - *left++ = bigEndian24Bit (src) << 8; + *left++ = ByteOrder::bigEndian24Bit (src) << 8; src += 3; } } @@ -377,14 +373,14 @@ public: for (int i = numThisTime; --i >= 0;) { ++src; - *r++ = swapIfBigEndian (*src++); + *r++ = ByteOrder::swapIfBigEndian (*src++); } } else if (r == 0) { for (int i = numThisTime; --i >= 0;) { - *l++ = swapIfBigEndian (*src++); + *l++ = ByteOrder::swapIfBigEndian (*src++); ++src; } } @@ -392,8 +388,8 @@ public: { for (int i = numThisTime; --i >= 0;) { - *l++ = swapIfBigEndian (*src++); - *r++ = swapIfBigEndian (*src++); + *l++ = ByteOrder::swapIfBigEndian (*src++); + *r++ = ByteOrder::swapIfBigEndian (*src++); } } } @@ -401,7 +397,7 @@ public: { for (int i = numThisTime; --i >= 0;) { - *l++ = swapIfBigEndian (*src++); + *l++ = ByteOrder::swapIfBigEndian (*src++); } } } @@ -414,14 +410,14 @@ public: for (int i = numThisTime; --i >= 0;) { ++src; - *r++ = swapIfLittleEndian (*src++); + *r++ = ByteOrder::swapIfLittleEndian (*src++); } } else if (r == 0) { for (int i = numThisTime; --i >= 0;) { - *l++ = swapIfLittleEndian (*src++); + *l++ = ByteOrder::swapIfLittleEndian (*src++); ++src; } } @@ -429,8 +425,8 @@ public: { for (int i = numThisTime; --i >= 0;) { - *l++ = swapIfLittleEndian (*src++); - *r++ = swapIfLittleEndian (*src++); + *l++ = ByteOrder::swapIfLittleEndian (*src++); + *r++ = ByteOrder::swapIfLittleEndian (*src++); } } } @@ -438,7 +434,7 @@ public: { for (int i = numThisTime; --i >= 0;) { - *l++ = swapIfLittleEndian (*src++); + *l++ = ByteOrder::swapIfLittleEndian (*src++); } } } @@ -506,6 +502,8 @@ public: private: AiffAudioFormatReader (const AiffAudioFormatReader&); const AiffAudioFormatReader& operator= (const AiffAudioFormatReader&); + + static inline int chunkName (const char* const name) { return (int) ByteOrder::littleEndianInt (name); } }; //============================================================================== @@ -516,6 +514,8 @@ class AiffAudioFormatWriter : public AudioFormatWriter int64 headerPosition; bool writeFailed; + static inline int chunkName (const char* const name) { return (int) ByteOrder::littleEndianInt (name); } + AiffAudioFormatWriter (const AiffAudioFormatWriter&); const AiffAudioFormatWriter& operator= (const AiffAudioFormatWriter&); @@ -600,7 +600,7 @@ public: const unsigned int chans, const int bits) : AudioFormatWriter (out, - aiffFormatName, + TRANS (aiffFormatName), sampleRate_, chans, bits), @@ -643,15 +643,15 @@ public: { for (int i = numSamples; --i >= 0;) { - *b++ = (short) swapIfLittleEndian ((unsigned short) (*left++ >> 16)); - *b++ = (short) swapIfLittleEndian ((unsigned short) (*right++ >> 16)); + *b++ = (short) ByteOrder::swapIfLittleEndian ((uint16) (*left++ >> 16)); + *b++ = (short) ByteOrder::swapIfLittleEndian ((uint16) (*right++ >> 16)); } } else { for (int i = numSamples; --i >= 0;) { - *b++ = (short) swapIfLittleEndian ((unsigned short) (*left++ >> 16)); + *b++ = (short) ByteOrder::swapIfLittleEndian ((uint16) (*left++ >> 16)); } } } @@ -663,9 +663,9 @@ public: { for (int i = numSamples; --i >= 0;) { - bigEndian24BitToChars (*left++ >> 8, b); + ByteOrder::bigEndian24BitToChars (*left++ >> 8, b); b += 3; - bigEndian24BitToChars (*right++ >> 8, b); + ByteOrder::bigEndian24BitToChars (*right++ >> 8, b); b += 3; } } @@ -673,34 +673,34 @@ public: { for (int i = numSamples; --i >= 0;) { - bigEndian24BitToChars (*left++ >> 8, b); + ByteOrder::bigEndian24BitToChars (*left++ >> 8, b); b += 3; } } } else if (bitsPerSample == 32) { - unsigned int* b = (unsigned int*) buffer; + uint32* b = (uint32*) buffer; if (numChannels > 1) { for (int i = numSamples; --i >= 0;) { - *b++ = swapIfLittleEndian ((unsigned int) *left++); - *b++ = swapIfLittleEndian ((unsigned int) *right++); + *b++ = ByteOrder::swapIfLittleEndian ((uint32) *left++); + *b++ = ByteOrder::swapIfLittleEndian ((uint32) *right++); } } else { for (int i = numSamples; --i >= 0;) { - *b++ = swapIfLittleEndian ((unsigned int) *left++); + *b++ = ByteOrder::swapIfLittleEndian ((uint32) *left++); } } } else if (bitsPerSample == 8) { - char* b = (char*)buffer; + char* b = (char*) buffer; if (numChannels > 1) { @@ -743,7 +743,7 @@ public: //============================================================================== AiffAudioFormat::AiffAudioFormat() - : AudioFormat (aiffFormatName, (const tchar**) aiffExtensions) + : AudioFormat (TRANS (aiffFormatName), (const tchar**) aiffExtensions) { } diff --git a/src/audio/audio_file_formats/juce_AudioThumbnail.cpp b/src/audio/audio_file_formats/juce_AudioThumbnail.cpp index db8c51ae3e..e384b74d9d 100644 --- a/src/audio/audio_file_formats/juce_AudioThumbnail.cpp +++ b/src/audio/audio_file_formats/juce_AudioThumbnail.cpp @@ -48,8 +48,8 @@ struct AudioThumbnailDataFormat }; #if JUCE_BIG_ENDIAN - static void swap (int& n) { n = (int) swapByteOrder ((uint32) n); } - static void swap (int64& n) { n = (int64) swapByteOrder ((uint64) n); } + static void swap (int& n) { n = (int) ByteOrder::swap ((uint32) n); } + static void swap (int64& n) { n = (int64) ByteOrder::swap ((uint64) n); } #endif static void swapEndiannessIfNeeded (AudioThumbnailDataFormat* const d) diff --git a/src/audio/audio_file_formats/juce_FlacAudioFormat.cpp b/src/audio/audio_file_formats/juce_FlacAudioFormat.cpp index 08bd64ff3c..a207c2381b 100644 --- a/src/audio/audio_file_formats/juce_FlacAudioFormat.cpp +++ b/src/audio/audio_file_formats/juce_FlacAudioFormat.cpp @@ -82,7 +82,7 @@ BEGIN_JUCE_NAMESPACE using namespace FlacNamespace; //============================================================================== -#define flacFormatName TRANS("FLAC file") +static const char* const flacFormatName = "FLAC file"; static const tchar* const flacExtensions[] = { T(".flac"), 0 }; @@ -97,7 +97,7 @@ class FlacReader : public AudioFormatReader public: //============================================================================== FlacReader (InputStream* const in) - : AudioFormatReader (in, flacFormatName), + : AudioFormatReader (in, TRANS (flacFormatName)), reservoir (2, 0), reservoirStart (0), samplesInReservoir (0), @@ -317,7 +317,7 @@ public: const double sampleRate_, const int numChannels_, const int bitsPerSample_) - : AudioFormatWriter (out, flacFormatName, + : AudioFormatWriter (out, TRANS (flacFormatName), sampleRate_, numChannels_, bitsPerSample_) @@ -478,7 +478,7 @@ public: //============================================================================== FlacAudioFormat::FlacAudioFormat() - : AudioFormat (flacFormatName, (const tchar**) flacExtensions) + : AudioFormat (TRANS (flacFormatName), (const tchar**) flacExtensions) { } diff --git a/src/audio/audio_file_formats/juce_OggVorbisAudioFormat.cpp b/src/audio/audio_file_formats/juce_OggVorbisAudioFormat.cpp index 68caab5d19..49790d43d0 100644 --- a/src/audio/audio_file_formats/juce_OggVorbisAudioFormat.cpp +++ b/src/audio/audio_file_formats/juce_OggVorbisAudioFormat.cpp @@ -83,7 +83,7 @@ BEGIN_JUCE_NAMESPACE using namespace OggVorbisNamespace; //============================================================================== -#define oggFormatName TRANS("Ogg-Vorbis file") +static const char* const oggFormatName = "Ogg-Vorbis file"; static const tchar* const oggExtensions[] = { T(".ogg"), 0 }; @@ -98,7 +98,7 @@ class OggReader : public AudioFormatReader public: //============================================================================== OggReader (InputStream* const inp) - : AudioFormatReader (inp, oggFormatName), + : AudioFormatReader (inp, TRANS (oggFormatName)), reservoir (2, 4096), reservoirStart (0), samplesInReservoir (0) @@ -263,7 +263,7 @@ public: const int numChannels, const int bitsPerSample, const int qualityIndex) - : AudioFormatWriter (out, oggFormatName, + : AudioFormatWriter (out, TRANS (oggFormatName), sampleRate, numChannels, bitsPerSample) @@ -392,7 +392,7 @@ public: //============================================================================== OggVorbisAudioFormat::OggVorbisAudioFormat() - : AudioFormat (oggFormatName, (const tchar**) oggExtensions) + : AudioFormat (TRANS (oggFormatName), (const tchar**) oggExtensions) { } diff --git a/src/audio/audio_file_formats/juce_QuickTimeAudioFormat.cpp b/src/audio/audio_file_formats/juce_QuickTimeAudioFormat.cpp index d31889bac7..595c3fc835 100644 --- a/src/audio/audio_file_formats/juce_QuickTimeAudioFormat.cpp +++ b/src/audio/audio_file_formats/juce_QuickTimeAudioFormat.cpp @@ -68,7 +68,7 @@ BEGIN_JUCE_NAMESPACE bool juce_OpenQuickTimeMovieFromStream (InputStream* input, Movie& movie, Handle& dataHandle); -#define quickTimeFormatName TRANS("QuickTime file") +static const char* const quickTimeFormatName = "QuickTime file"; static const tchar* const quickTimeExtensions[] = { T(".mov"), T(".mp3"), T(".mp4"), 0 }; //============================================================================== @@ -76,7 +76,7 @@ class QTAudioReader : public AudioFormatReader { public: QTAudioReader (InputStream* const input_, const int trackNum_) - : AudioFormatReader (input_, quickTimeFormatName), + : AudioFormatReader (input_, TRANS (quickTimeFormatName)), ok (false), movie (0), trackNum (trackNum_), @@ -341,7 +341,7 @@ private: //============================================================================== QuickTimeAudioFormat::QuickTimeAudioFormat() - : AudioFormat (quickTimeFormatName, (const tchar**) quickTimeExtensions) + : AudioFormat (TRANS (quickTimeFormatName), (const tchar**) quickTimeExtensions) { } diff --git a/src/audio/audio_file_formats/juce_WavAudioFormat.cpp b/src/audio/audio_file_formats/juce_WavAudioFormat.cpp index d593197123..4190567e25 100644 --- a/src/audio/audio_file_formats/juce_WavAudioFormat.cpp +++ b/src/audio/audio_file_formats/juce_WavAudioFormat.cpp @@ -35,7 +35,7 @@ BEGIN_JUCE_NAMESPACE //============================================================================== -#define wavFormatName TRANS("WAV file") +static const char* const wavFormatName = "WAV file"; static const tchar* const wavExtensions[] = { T(".wav"), T(".bwf"), 0 }; @@ -101,8 +101,8 @@ struct BWAVChunk values.set (WavAudioFormat::bwavOriginationDate, String::fromUTF8 (originationDate, 10)); values.set (WavAudioFormat::bwavOriginationTime, String::fromUTF8 (originationTime, 8)); - const uint32 timeLow = swapIfBigEndian (timeRefLow); - const uint32 timeHigh = swapIfBigEndian (timeRefHigh); + const uint32 timeLow = ByteOrder::swapIfBigEndian (timeRefLow); + const uint32 timeHigh = ByteOrder::swapIfBigEndian (timeRefHigh); const int64 time = (((int64)timeHigh) << 32) + timeLow; values.set (WavAudioFormat::bwavTimeReference, String (time)); @@ -126,8 +126,8 @@ struct BWAVChunk values [WavAudioFormat::bwavOriginationTime].copyToUTF8 (b->originationTime, 9); const int64 time = values [WavAudioFormat::bwavTimeReference].getLargeIntValue(); - b->timeRefLow = swapIfBigEndian ((uint32) (time & 0xffffffff)); - b->timeRefHigh = swapIfBigEndian ((uint32) (time >> 32)); + b->timeRefLow = ByteOrder::swapIfBigEndian ((uint32) (time & 0xffffffff)); + b->timeRefHigh = ByteOrder::swapIfBigEndian ((uint32) (time >> 32)); values [WavAudioFormat::bwavCodingHistory].copyToUTF8 (b->codingHistory); @@ -173,27 +173,27 @@ struct SMPLChunk void copyTo (StringPairArray& values, const int totalSize) const { - values.set (T("Manufacturer"), String (swapIfBigEndian (manufacturer))); - values.set (T("Product"), String (swapIfBigEndian (product))); - values.set (T("SamplePeriod"), String (swapIfBigEndian (samplePeriod))); - values.set (T("MidiUnityNote"), String (swapIfBigEndian (midiUnityNote))); - values.set (T("MidiPitchFraction"), String (swapIfBigEndian (midiPitchFraction))); - values.set (T("SmpteFormat"), String (swapIfBigEndian (smpteFormat))); - values.set (T("SmpteOffset"), String (swapIfBigEndian (smpteOffset))); - values.set (T("NumSampleLoops"), String (swapIfBigEndian (numSampleLoops))); - values.set (T("SamplerData"), String (swapIfBigEndian (samplerData))); + values.set (T("Manufacturer"), String (ByteOrder::swapIfBigEndian (manufacturer))); + values.set (T("Product"), String (ByteOrder::swapIfBigEndian (product))); + values.set (T("SamplePeriod"), String (ByteOrder::swapIfBigEndian (samplePeriod))); + values.set (T("MidiUnityNote"), String (ByteOrder::swapIfBigEndian (midiUnityNote))); + values.set (T("MidiPitchFraction"), String (ByteOrder::swapIfBigEndian (midiPitchFraction))); + values.set (T("SmpteFormat"), String (ByteOrder::swapIfBigEndian (smpteFormat))); + values.set (T("SmpteOffset"), String (ByteOrder::swapIfBigEndian (smpteOffset))); + values.set (T("NumSampleLoops"), String (ByteOrder::swapIfBigEndian (numSampleLoops))); + values.set (T("SamplerData"), String (ByteOrder::swapIfBigEndian (samplerData))); for (uint32 i = 0; i < numSampleLoops; ++i) { if ((uint8*) (loops + (i + 1)) > ((uint8*) this) + totalSize) break; - values.set (String::formatted (T("Loop%dIdentifier"), i), String (swapIfBigEndian (loops[i].identifier))); - values.set (String::formatted (T("Loop%dType"), i), String (swapIfBigEndian (loops[i].type))); - values.set (String::formatted (T("Loop%dStart"), i), String (swapIfBigEndian (loops[i].start))); - values.set (String::formatted (T("Loop%dEnd"), i), String (swapIfBigEndian (loops[i].end))); - values.set (String::formatted (T("Loop%dFraction"), i), String (swapIfBigEndian (loops[i].fraction))); - values.set (String::formatted (T("Loop%dPlayCount"), i), String (swapIfBigEndian (loops[i].playCount))); + values.set (String::formatted (T("Loop%dIdentifier"), i), String (ByteOrder::swapIfBigEndian (loops[i].identifier))); + values.set (String::formatted (T("Loop%dType"), i), String (ByteOrder::swapIfBigEndian (loops[i].type))); + values.set (String::formatted (T("Loop%dStart"), i), String (ByteOrder::swapIfBigEndian (loops[i].start))); + values.set (String::formatted (T("Loop%dEnd"), i), String (ByteOrder::swapIfBigEndian (loops[i].end))); + values.set (String::formatted (T("Loop%dFraction"), i), String (ByteOrder::swapIfBigEndian (loops[i].fraction))); + values.set (String::formatted (T("Loop%dPlayCount"), i), String (ByteOrder::swapIfBigEndian (loops[i].playCount))); } } } PACKED; @@ -204,8 +204,6 @@ struct SMPLChunk #undef PACKED -#undef chunkName -#define chunkName(a) ((int) littleEndianInt(a)) //============================================================================== class WavAudioFormatReader : public AudioFormatReader @@ -213,6 +211,8 @@ class WavAudioFormatReader : public AudioFormatReader int bytesPerFrame; int64 dataChunkStart, dataLength; + static inline int chunkName (const char* const name) { return (int) ByteOrder::littleEndianInt (name); } + WavAudioFormatReader (const WavAudioFormatReader&); const WavAudioFormatReader& operator= (const WavAudioFormatReader&); @@ -221,7 +221,7 @@ public: //============================================================================== WavAudioFormatReader (InputStream* const in) - : AudioFormatReader (in, wavFormatName), + : AudioFormatReader (in, TRANS (wavFormatName)), dataLength (0), bwavChunkStart (0), bwavSize (0) @@ -353,14 +353,14 @@ public: for (int i = numThisTime; --i >= 0;) { ++src; - *right++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16; + *right++ = (int) ByteOrder::swapIfBigEndian ((unsigned short) *src++) << 16; } } else if (right == 0) { for (int i = numThisTime; --i >= 0;) { - *left++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16; + *left++ = (int) ByteOrder::swapIfBigEndian ((unsigned short) *src++) << 16; ++src; } } @@ -368,8 +368,8 @@ public: { for (int i = numThisTime; --i >= 0;) { - *left++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16; - *right++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16; + *left++ = (int) ByteOrder::swapIfBigEndian ((unsigned short) *src++) << 16; + *right++ = (int) ByteOrder::swapIfBigEndian ((unsigned short) *src++) << 16; } } } @@ -377,7 +377,7 @@ public: { for (int i = numThisTime; --i >= 0;) { - *left++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16; + *left++ = (int) ByteOrder::swapIfBigEndian ((unsigned short) *src++) << 16; } } } @@ -392,7 +392,7 @@ public: for (int i = numThisTime; --i >= 0;) { src += 3; - *right++ = littleEndian24Bit (src) << 8; + *right++ = ByteOrder::littleEndian24Bit (src) << 8; src += 3; } } @@ -400,7 +400,7 @@ public: { for (int i = numThisTime; --i >= 0;) { - *left++ = littleEndian24Bit (src) << 8; + *left++ = ByteOrder::littleEndian24Bit (src) << 8; src += 6; } } @@ -408,9 +408,9 @@ public: { for (int i = 0; i < numThisTime; ++i) { - *left++ = littleEndian24Bit (src) << 8; + *left++ = ByteOrder::littleEndian24Bit (src) << 8; src += 3; - *right++ = littleEndian24Bit (src) << 8; + *right++ = ByteOrder::littleEndian24Bit (src) << 8; src += 3; } } @@ -419,7 +419,7 @@ public: { for (int i = 0; i < numThisTime; ++i) { - *left++ = littleEndian24Bit (src) << 8; + *left++ = ByteOrder::littleEndian24Bit (src) << 8; src += 3; } } @@ -437,14 +437,14 @@ public: for (int i = numThisTime; --i >= 0;) { ++src; - *r++ = swapIfBigEndian (*src++); + *r++ = ByteOrder::swapIfBigEndian (*src++); } } else if (r == 0) { for (int i = numThisTime; --i >= 0;) { - *l++ = swapIfBigEndian (*src++); + *l++ = ByteOrder::swapIfBigEndian (*src++); ++src; } } @@ -452,8 +452,8 @@ public: { for (int i = numThisTime; --i >= 0;) { - *l++ = swapIfBigEndian (*src++); - *r++ = swapIfBigEndian (*src++); + *l++ = ByteOrder::swapIfBigEndian (*src++); + *r++ = ByteOrder::swapIfBigEndian (*src++); } } } @@ -461,7 +461,7 @@ public: { for (int i = numThisTime; --i >= 0;) { - *l++ = swapIfBigEndian (*src++); + *l++ = ByteOrder::swapIfBigEndian (*src++); } } @@ -534,6 +534,8 @@ class WavAudioFormatWriter : public AudioFormatWriter int64 headerPosition; bool writeFailed; + static inline int chunkName (const char* const name) { return (int) ByteOrder::littleEndianInt (name); } + WavAudioFormatWriter (const WavAudioFormatWriter&); const WavAudioFormatWriter& operator= (const WavAudioFormatWriter&); @@ -583,7 +585,7 @@ public: const int bits, const StringPairArray& metadataValues) : AudioFormatWriter (out, - wavFormatName, + TRANS (wavFormatName), sampleRate_, numChannels_, bits), @@ -626,15 +628,15 @@ public: { for (int i = numSamples; --i >= 0;) { - *b++ = (short) swapIfBigEndian ((unsigned short) (*left++ >> 16)); - *b++ = (short) swapIfBigEndian ((unsigned short) (*right++ >> 16)); + *b++ = (short) ByteOrder::swapIfBigEndian ((unsigned short) (*left++ >> 16)); + *b++ = (short) ByteOrder::swapIfBigEndian ((unsigned short) (*right++ >> 16)); } } else { for (int i = numSamples; --i >= 0;) { - *b++ = (short) swapIfBigEndian ((unsigned short) (*left++ >> 16)); + *b++ = (short) ByteOrder::swapIfBigEndian ((unsigned short) (*left++ >> 16)); } } } @@ -646,9 +648,9 @@ public: { for (int i = numSamples; --i >= 0;) { - littleEndian24BitToChars ((*left++) >> 8, b); + ByteOrder::littleEndian24BitToChars ((*left++) >> 8, b); b += 3; - littleEndian24BitToChars ((*right++) >> 8, b); + ByteOrder::littleEndian24BitToChars ((*right++) >> 8, b); b += 3; } } @@ -656,7 +658,7 @@ public: { for (int i = numSamples; --i >= 0;) { - littleEndian24BitToChars ((*left++) >> 8, b); + ByteOrder::littleEndian24BitToChars ((*left++) >> 8, b); b += 3; } } @@ -669,15 +671,15 @@ public: { for (int i = numSamples; --i >= 0;) { - *b++ = swapIfBigEndian ((unsigned int) *left++); - *b++ = swapIfBigEndian ((unsigned int) *right++); + *b++ = ByteOrder::swapIfBigEndian ((unsigned int) *left++); + *b++ = ByteOrder::swapIfBigEndian ((unsigned int) *right++); } } else { for (int i = numSamples; --i >= 0;) { - *b++ = swapIfBigEndian ((unsigned int) *left++); + *b++ = ByteOrder::swapIfBigEndian ((unsigned int) *left++); } } } @@ -726,7 +728,7 @@ public: //============================================================================== WavAudioFormat::WavAudioFormat() - : AudioFormat (wavFormatName, (const tchar**) wavExtensions) + : AudioFormat (TRANS (wavFormatName), (const tchar**) wavExtensions) { } diff --git a/src/audio/dsp/juce_AudioDataConverters.cpp b/src/audio/dsp/juce_AudioDataConverters.cpp index d564ece51a..1c91727dd1 100644 --- a/src/audio/dsp/juce_AudioDataConverters.cpp +++ b/src/audio/dsp/juce_AudioDataConverters.cpp @@ -40,7 +40,7 @@ void AudioDataConverters::convertFloatToInt16LE (const float* source, void* dest { for (int i = 0; i < numSamples; ++i) { - *(uint16*)intData = swapIfBigEndian ((uint16) (short) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); + *(uint16*)intData = ByteOrder::swapIfBigEndian ((uint16) (short) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); intData += destBytesPerSample; } } @@ -51,7 +51,7 @@ void AudioDataConverters::convertFloatToInt16LE (const float* source, void* dest for (int i = numSamples; --i >= 0;) { intData -= destBytesPerSample; - *(uint16*)intData = swapIfBigEndian ((uint16) (short) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); + *(uint16*)intData = ByteOrder::swapIfBigEndian ((uint16) (short) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); } } } @@ -65,7 +65,7 @@ void AudioDataConverters::convertFloatToInt16BE (const float* source, void* dest { for (int i = 0; i < numSamples; ++i) { - *(uint16*)intData = swapIfLittleEndian ((uint16) (short) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); + *(uint16*) intData = ByteOrder::swapIfLittleEndian ((uint16) (short) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); intData += destBytesPerSample; } } @@ -76,7 +76,7 @@ void AudioDataConverters::convertFloatToInt16BE (const float* source, void* dest for (int i = numSamples; --i >= 0;) { intData -= destBytesPerSample; - *(uint16*)intData = swapIfLittleEndian ((uint16) (short) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); + *(uint16*)intData = ByteOrder::swapIfLittleEndian ((uint16) (short) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); } } } @@ -90,7 +90,7 @@ void AudioDataConverters::convertFloatToInt24LE (const float* source, void* dest { for (int i = 0; i < numSamples; ++i) { - littleEndian24BitToChars ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i])), intData); + ByteOrder::littleEndian24BitToChars ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i])), intData); intData += destBytesPerSample; } } @@ -101,7 +101,7 @@ void AudioDataConverters::convertFloatToInt24LE (const float* source, void* dest for (int i = numSamples; --i >= 0;) { intData -= destBytesPerSample; - littleEndian24BitToChars ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i])), intData); + ByteOrder::littleEndian24BitToChars ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i])), intData); } } } @@ -115,7 +115,7 @@ void AudioDataConverters::convertFloatToInt24BE (const float* source, void* dest { for (int i = 0; i < numSamples; ++i) { - bigEndian24BitToChars ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i])), intData); + ByteOrder::bigEndian24BitToChars ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i])), intData); intData += destBytesPerSample; } } @@ -126,7 +126,7 @@ void AudioDataConverters::convertFloatToInt24BE (const float* source, void* dest for (int i = numSamples; --i >= 0;) { intData -= destBytesPerSample; - bigEndian24BitToChars ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i])), intData); + ByteOrder::bigEndian24BitToChars ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i])), intData); } } } @@ -140,7 +140,7 @@ void AudioDataConverters::convertFloatToInt32LE (const float* source, void* dest { for (int i = 0; i < numSamples; ++i) { - *(uint32*)intData = swapIfBigEndian ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); + *(uint32*)intData = ByteOrder::swapIfBigEndian ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); intData += destBytesPerSample; } } @@ -151,7 +151,7 @@ void AudioDataConverters::convertFloatToInt32LE (const float* source, void* dest for (int i = numSamples; --i >= 0;) { intData -= destBytesPerSample; - *(uint32*)intData = swapIfBigEndian ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); + *(uint32*)intData = ByteOrder::swapIfBigEndian ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); } } } @@ -165,7 +165,7 @@ void AudioDataConverters::convertFloatToInt32BE (const float* source, void* dest { for (int i = 0; i < numSamples; ++i) { - *(uint32*)intData = swapIfLittleEndian ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); + *(uint32*)intData = ByteOrder::swapIfLittleEndian ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); intData += destBytesPerSample; } } @@ -176,7 +176,7 @@ void AudioDataConverters::convertFloatToInt32BE (const float* source, void* dest for (int i = numSamples; --i >= 0;) { intData -= destBytesPerSample; - *(uint32*)intData = swapIfLittleEndian ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); + *(uint32*)intData = ByteOrder::swapIfLittleEndian ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); } } } @@ -189,10 +189,10 @@ void AudioDataConverters::convertFloatToFloat32LE (const float* source, void* de for (int i = 0; i < numSamples; ++i) { - *(float*)d = source[i]; + *(float*) d = source[i]; #if JUCE_BIG_ENDIAN - *(uint32*)d = swapByteOrder (*(uint32*)d); + *(uint32*) d = ByteOrder::swap (*(uint32*) d); #endif d += destBytesPerSample; @@ -207,10 +207,10 @@ void AudioDataConverters::convertFloatToFloat32BE (const float* source, void* de for (int i = 0; i < numSamples; ++i) { - *(float*)d = source[i]; + *(float*) d = source[i]; #if JUCE_LITTLE_ENDIAN - *(uint32*)d = swapByteOrder (*(uint32*)d); + *(uint32*) d = ByteOrder::swap (*(uint32*) d); #endif d += destBytesPerSample; @@ -227,7 +227,7 @@ void AudioDataConverters::convertInt16LEToFloat (const void* const source, float { for (int i = 0; i < numSamples; ++i) { - dest[i] = scale * (short) swapIfBigEndian (*(uint16*)intData); + dest[i] = scale * (short) ByteOrder::swapIfBigEndian (*(uint16*)intData); intData += srcBytesPerSample; } } @@ -238,7 +238,7 @@ void AudioDataConverters::convertInt16LEToFloat (const void* const source, float for (int i = numSamples; --i >= 0;) { intData -= srcBytesPerSample; - dest[i] = scale * (short) swapIfBigEndian (*(uint16*)intData); + dest[i] = scale * (short) ByteOrder::swapIfBigEndian (*(uint16*)intData); } } } @@ -252,7 +252,7 @@ void AudioDataConverters::convertInt16BEToFloat (const void* const source, float { for (int i = 0; i < numSamples; ++i) { - dest[i] = scale * (short) swapIfLittleEndian (*(uint16*)intData); + dest[i] = scale * (short) ByteOrder::swapIfLittleEndian (*(uint16*)intData); intData += srcBytesPerSample; } } @@ -263,7 +263,7 @@ void AudioDataConverters::convertInt16BEToFloat (const void* const source, float for (int i = numSamples; --i >= 0;) { intData -= srcBytesPerSample; - dest[i] = scale * (short) swapIfLittleEndian (*(uint16*)intData); + dest[i] = scale * (short) ByteOrder::swapIfLittleEndian (*(uint16*)intData); } } } @@ -277,7 +277,7 @@ void AudioDataConverters::convertInt24LEToFloat (const void* const source, float { for (int i = 0; i < numSamples; ++i) { - dest[i] = scale * (short) littleEndian24Bit (intData); + dest[i] = scale * (short) ByteOrder::littleEndian24Bit (intData); intData += srcBytesPerSample; } } @@ -288,7 +288,7 @@ void AudioDataConverters::convertInt24LEToFloat (const void* const source, float for (int i = numSamples; --i >= 0;) { intData -= srcBytesPerSample; - dest[i] = scale * (short) littleEndian24Bit (intData); + dest[i] = scale * (short) ByteOrder::littleEndian24Bit (intData); } } } @@ -302,7 +302,7 @@ void AudioDataConverters::convertInt24BEToFloat (const void* const source, float { for (int i = 0; i < numSamples; ++i) { - dest[i] = scale * (short) bigEndian24Bit (intData); + dest[i] = scale * (short) ByteOrder::bigEndian24Bit (intData); intData += srcBytesPerSample; } } @@ -313,7 +313,7 @@ void AudioDataConverters::convertInt24BEToFloat (const void* const source, float for (int i = numSamples; --i >= 0;) { intData -= srcBytesPerSample; - dest[i] = scale * (short) bigEndian24Bit (intData); + dest[i] = scale * (short) ByteOrder::bigEndian24Bit (intData); } } } @@ -327,7 +327,7 @@ void AudioDataConverters::convertInt32LEToFloat (const void* const source, float { for (int i = 0; i < numSamples; ++i) { - dest[i] = scale * (int) swapIfBigEndian (*(uint32*) intData); + dest[i] = scale * (int) ByteOrder::swapIfBigEndian (*(uint32*) intData); intData += srcBytesPerSample; } } @@ -338,7 +338,7 @@ void AudioDataConverters::convertInt32LEToFloat (const void* const source, float for (int i = numSamples; --i >= 0;) { intData -= srcBytesPerSample; - dest[i] = scale * (int) swapIfBigEndian (*(uint32*) intData); + dest[i] = scale * (int) ByteOrder::swapIfBigEndian (*(uint32*) intData); } } } @@ -352,7 +352,7 @@ void AudioDataConverters::convertInt32BEToFloat (const void* const source, float { for (int i = 0; i < numSamples; ++i) { - dest[i] = scale * (int) (swapIfLittleEndian (*(uint32*) intData)); + dest[i] = scale * (int) ByteOrder::swapIfLittleEndian (*(uint32*) intData); intData += srcBytesPerSample; } } @@ -363,7 +363,7 @@ void AudioDataConverters::convertInt32BEToFloat (const void* const source, float for (int i = numSamples; --i >= 0;) { intData -= srcBytesPerSample; - dest[i] = scale * (int) (swapIfLittleEndian (*(uint32*) intData)); + dest[i] = scale * (int) ByteOrder::swapIfLittleEndian (*(uint32*) intData); } } } @@ -378,7 +378,7 @@ void AudioDataConverters::convertFloat32LEToFloat (const void* const source, flo #if JUCE_BIG_ENDIAN uint32* const d = (uint32*) (dest + i); - *d = swapByteOrder (*d); + *d = ByteOrder::swap (*d); #endif s += srcBytesPerSample; @@ -395,7 +395,7 @@ void AudioDataConverters::convertFloat32BEToFloat (const void* const source, flo #if JUCE_LITTLE_ENDIAN uint32* const d = (uint32*) (dest + i); - *d = swapByteOrder (*d); + *d = ByteOrder::swap (*d); #endif s += srcBytesPerSample; diff --git a/src/audio/midi/juce_MidiFile.cpp b/src/audio/midi/juce_MidiFile.cpp index 0142ba56a3..ec0a33c1f1 100644 --- a/src/audio/midi/juce_MidiFile.cpp +++ b/src/audio/midi/juce_MidiFile.cpp @@ -140,21 +140,21 @@ static bool parseMidiHeader (const char* &data, short& fileType, short& numberOfTracks) { - unsigned int ch = (int) bigEndianInt (data); + unsigned int ch = (int) ByteOrder::bigEndianInt (data); data += 4; - if (ch != bigEndianInt ("MThd")) + if (ch != ByteOrder::bigEndianInt ("MThd")) { bool ok = false; - if (ch == bigEndianInt ("RIFF")) + if (ch == ByteOrder::bigEndianInt ("RIFF")) { for (int i = 0; i < 8; ++i) { - ch = bigEndianInt (data); + ch = ByteOrder::bigEndianInt (data); data += 4; - if (ch == bigEndianInt ("MThd")) + if (ch == ByteOrder::bigEndianInt ("MThd")) { ok = true; break; @@ -166,13 +166,13 @@ static bool parseMidiHeader (const char* &data, return false; } - unsigned int bytesRemaining = bigEndianInt (data); + unsigned int bytesRemaining = ByteOrder::bigEndianInt (data); data += 4; - fileType = (short)bigEndianShort (data); + fileType = (short) ByteOrder::bigEndianShort (data); data += 2; - numberOfTracks = (short)bigEndianShort (data); + numberOfTracks = (short) ByteOrder::bigEndianShort (data); data += 2; - timeFormat = (short)bigEndianShort (data); + timeFormat = (short) ByteOrder::bigEndianShort (data); data += 2; bytesRemaining -= 6; data += bytesRemaining; @@ -202,9 +202,9 @@ bool MidiFile::readFrom (InputStream& sourceStream) while (size > 0 && track < expectedTracks) { - const int chunkType = (int)bigEndianInt (d); + const int chunkType = (int) ByteOrder::bigEndianInt (d); d += 4; - const int chunkSize = (int)bigEndianInt (d); + const int chunkSize = (int) ByteOrder::bigEndianInt (d); d += 4; if (chunkSize <= 0) @@ -213,7 +213,7 @@ bool MidiFile::readFrom (InputStream& sourceStream) if (size < 0) return false; - if (chunkType == (int)bigEndianInt ("MTrk")) + if (chunkType == (int) ByteOrder::bigEndianInt ("MTrk")) { readNextTrack (d, chunkSize); } @@ -400,10 +400,10 @@ static void writeVariableLengthInt (OutputStream& out, unsigned int v) bool MidiFile::writeTo (OutputStream& out) { - out.writeIntBigEndian ((int) bigEndianInt ("MThd")); + out.writeIntBigEndian ((int) ByteOrder::bigEndianInt ("MThd")); out.writeIntBigEndian (6); out.writeShortBigEndian (1); // type - out.writeShortBigEndian (tracks.size()); + out.writeShortBigEndian ((short) tracks.size()); out.writeShortBigEndian (timeFormat); for (int i = 0; i < tracks.size(); ++i) @@ -457,7 +457,7 @@ void MidiFile::writeTrack (OutputStream& mainOut, out.write (m.getRawData(), m.getRawDataSize()); - mainOut.writeIntBigEndian ((int)bigEndianInt ("MTrk")); + mainOut.writeIntBigEndian ((int) ByteOrder::bigEndianInt ("MTrk")); mainOut.writeIntBigEndian (out.getDataSize()); mainOut.write (out.getData(), out.getDataSize()); } diff --git a/src/audio/plugins/formats/juce_VSTPluginFormat.cpp b/src/audio/plugins/formats/juce_VSTPluginFormat.cpp index 9de4c10149..ef529e3fae 100644 --- a/src/audio/plugins/formats/juce_VSTPluginFormat.cpp +++ b/src/audio/plugins/formats/juce_VSTPluginFormat.cpp @@ -177,20 +177,26 @@ struct fxProgramSet }; -#ifdef JUCE_LITTLE_ENDIAN - static long vst_swap (const long x) throw() { return (long) swapByteOrder ((uint32) x); } - - static float vst_swapFloat (const float x) throw() - { - union { uint32 asInt; float asFloat; } n; - n.asFloat = x; - n.asInt = swapByteOrder (n.asInt); - return n.asFloat; - } -#else - #define vst_swap(x) (x) - #define vst_swapFloat(x) (x) -#endif +static long vst_swap (const long x) throw() +{ + #ifdef JUCE_LITTLE_ENDIAN + return (long) ByteOrder::swap ((uint32) x); + #else + return x; + #endif +} + +static float vst_swapFloat (const float x) throw() +{ + #ifdef JUCE_LITTLE_ENDIAN + union { uint32 asInt; float asFloat; } n; + n.asFloat = x; + n.asInt = ByteOrder::swap (n.asInt); + return n.asFloat; + #else + return x; + #endif +} //============================================================================== typedef AEffect* (*MainCall) (audioMasterCallback); diff --git a/src/audio/processors/juce_AudioProcessor.cpp b/src/audio/processors/juce_AudioProcessor.cpp index 6daa9655d9..1aea0c333d 100644 --- a/src/audio/processors/juce_AudioProcessor.cpp +++ b/src/audio/processors/juce_AudioProcessor.cpp @@ -255,8 +255,8 @@ void AudioProcessor::copyXmlToBinary (const XmlElement& xml, destData.setSize (stringLength + 10); char* const d = (char*) destData.getData(); - *(uint32*) d = swapIfBigEndian ((const uint32) magicXmlNumber); - *(uint32*) (d + 4) = swapIfBigEndian ((const uint32) stringLength); + *(uint32*) d = ByteOrder::swapIfBigEndian ((const uint32) magicXmlNumber); + *(uint32*) (d + 4) = ByteOrder::swapIfBigEndian ((const uint32) stringLength); xmlString.copyToBuffer (d + 8, stringLength); } @@ -265,9 +265,9 @@ XmlElement* AudioProcessor::getXmlFromBinary (const void* data, const int sizeInBytes) { if (sizeInBytes > 8 - && littleEndianInt ((const char*) data) == magicXmlNumber) + && ByteOrder::littleEndianInt ((const char*) data) == magicXmlNumber) { - const uint32 stringLength = littleEndianInt (((const char*) data) + 4); + const uint32 stringLength = ByteOrder::littleEndianInt (((const char*) data) + 4); if (stringLength > 0) { diff --git a/src/containers/juce_ArrayAllocationBase.h b/src/containers/juce_ArrayAllocationBase.h index c3034309fc..131cc2ed37 100644 --- a/src/containers/juce_ArrayAllocationBase.h +++ b/src/containers/juce_ArrayAllocationBase.h @@ -93,7 +93,7 @@ public: elements = newElements; } - else if (elements != 0) + else { delete[] elements; elements = 0; diff --git a/src/containers/juce_HeapBlock.h b/src/containers/juce_HeapBlock.h index cc42a34e86..e8d0626b27 100644 --- a/src/containers/juce_HeapBlock.h +++ b/src/containers/juce_HeapBlock.h @@ -131,12 +131,14 @@ public: Obviously there's no bounds-checking here, as this object is just a dumb pointer and has no idea of the size it currently has allocated. */ - inline ElementType& operator[] (const pointer_sized_int index) const { return data [index]; } + template + inline ElementType& operator[] (IndexType index) const { return data [index]; } /** Returns a pointer to a data element at an offset from the start of the array. This is the same as doing pointer arithmetic on the raw pointer itself. */ - inline ElementType* operator+ (const pointer_sized_int index) const { return data + index; } + template + inline ElementType* operator+ (IndexType index) const { return data + index; } /** Returns a reference to the raw data pointer. Beware that the pointer returned here will become invalid as soon as you call diff --git a/src/containers/juce_ReferenceCountedObject.h b/src/containers/juce_ReferenceCountedObject.h index 6adef6d768..6590a253d0 100644 --- a/src/containers/juce_ReferenceCountedObject.h +++ b/src/containers/juce_ReferenceCountedObject.h @@ -68,7 +68,7 @@ public: */ inline void incReferenceCount() throw() { - atomicIncrement (refCounts); + Atomic::increment (refCounts); jassert (refCounts > 0); } @@ -81,7 +81,7 @@ public: { jassert (refCounts > 0); - if (atomicDecrementAndReturn (refCounts) == 0) + if (Atomic::decrementAndReturn (refCounts) == 0) delete this; } diff --git a/src/containers/juce_ScopedPointer.h b/src/containers/juce_ScopedPointer.h index 8b808e899d..1664c8aed5 100644 --- a/src/containers/juce_ScopedPointer.h +++ b/src/containers/juce_ScopedPointer.h @@ -45,7 +45,7 @@ can use the release() method. */ template -class ScopedPointer +class JUCE_API ScopedPointer { public: //============================================================================== @@ -88,7 +88,7 @@ public: */ const ScopedPointer& operator= (ScopedPointer& objectToTransferFrom) { - if (this != &objectToTransferFrom) + if (this != objectToTransferFrom.getAddress()) { // Two ScopedPointers should never be able to refer to the same object - if // this happens, you must have done something dodgy! @@ -175,6 +175,9 @@ public: private: //============================================================================== ObjectType* object; + + // (Required as an alternative to the overloaded & operator). + ScopedPointer* getAddress() { return this; } }; diff --git a/src/containers/juce_Value.h b/src/containers/juce_Value.h index c4faad78b2..dad4b2cf7e 100644 --- a/src/containers/juce_Value.h +++ b/src/containers/juce_Value.h @@ -94,21 +94,29 @@ public: */ const Value& operator= (const var& newValue); - /** Makes this object refer to the same underlying value as another one. + /** Makes this object refer to the same underlying ValueSource as another one. + Once this object has been connected to another one, changing either one + will update the other. + Existing listeners will still be registered after you call this method, and + they'll continue to receive messages when the new value changes. */ void referTo (const Value& valueToReferTo); - /** + /** Returns true if this value and the other one are references to the same value. */ bool refersToSameSourceAs (const Value& other) const; - /** + /** Compares two values. + This is a compare-by-value comparison, so is effectively the same as + saying (this->getValue() == other.getValue()). */ bool operator== (const Value& other) const; - /** + /** Compares two values. + This is a compare-by-value comparison, so is effectively the same as + saying (this->getValue() != other.getValue()). */ bool operator!= (const Value& other) const; @@ -195,6 +203,8 @@ public: //============================================================================== /** @internal */ explicit Value (ValueSource* const valueSource); + /** @internal */ + ValueSource& getValueSource() { return *value; } juce_UseDebuggingNewOperator diff --git a/src/containers/juce_Variant.cpp b/src/containers/juce_Variant.cpp index ac2ca73231..235392fc9f 100644 --- a/src/containers/juce_Variant.cpp +++ b/src/containers/juce_Variant.cpp @@ -117,21 +117,55 @@ const var& var::operator= (const var& valueToCopy) throw() { if (this != &valueToCopy) { - if (type == stringType) - delete value.stringValue; + if (type == valueToCopy.type) + { + switch (type) + { + case voidType: + break; + + case intType: + case boolType: + case doubleType: + value = valueToCopy.value; + break; + + case stringType: + *(value.stringValue) = *(valueToCopy.value.stringValue); + break; - DynamicObject* const oldObject = getObject(); + case objectType: + if (valueToCopy.value.objectValue != 0) + valueToCopy.value.objectValue->incReferenceCount(); - type = valueToCopy.type; - value = valueToCopy.value; + if (value.objectValue != 0) + value.objectValue->decReferenceCount(); + + value.objectValue = valueToCopy.value.objectValue; + break; + + default: + jassertfalse; + break; + } + } + else + { + releaseValue(); + type = valueToCopy.type; - if (type == stringType) - value.stringValue = new String (*(value.stringValue)); - else if (type == objectType && value.objectValue != 0) - value.objectValue->incReferenceCount(); + if (type == stringType) + { + value.stringValue = new String (*(valueToCopy.value.stringValue)); + } + else + { + value = valueToCopy.value; - if (oldObject != 0) - oldObject->decReferenceCount(); + if (type == objectType && value.objectValue != 0) + value.objectValue->incReferenceCount(); + } + } } return *this; diff --git a/src/core/juce_Atomic.h b/src/core/juce_Atomic.h index 3659642f68..51d9d9e585 100644 --- a/src/core/juce_Atomic.h +++ b/src/core/juce_Atomic.h @@ -26,186 +26,183 @@ #ifndef __JUCE_ATOMIC_JUCEHEADER__ #define __JUCE_ATOMIC_JUCEHEADER__ + //============================================================================== -// Atomic increment/decrement operations.. +/** Contains static functions for thread-safe atomic operations. +*/ +class JUCE_API Atomic +{ +public: + /** Increments an integer in a thread-safe way. */ + static void increment (int& variable); + + /** Increments an integer in a thread-safe way and returns its new value. */ + static int incrementAndReturn (int& variable); + + /** Decrements an integer in a thread-safe way. */ + static void decrement (int& variable); + + /** Decrements an integer in a thread-safe way and returns its new value. */ + static int decrementAndReturn (int& variable); +}; //============================================================================== -#if (JUCE_MAC || JUCE_IPHONE) && ! DOXYGEN +#if (JUCE_MAC || JUCE_IPHONE) // Mac and iPhone... - //============================================================================== - #include - static forcedinline void atomicIncrement (int& variable) throw() { OSAtomicIncrement32 ((int32_t*) &variable); } - static forcedinline int atomicIncrementAndReturn (int& variable) throw() { return OSAtomicIncrement32 ((int32_t*) &variable); } - static forcedinline void atomicDecrement (int& variable) throw() { OSAtomicDecrement32 ((int32_t*) &variable); } - static forcedinline int atomicDecrementAndReturn (int& variable) throw() { return OSAtomicDecrement32 ((int32_t*) &variable); } +#include +inline void Atomic::increment (int& variable) { OSAtomicIncrement32 ((int32_t*) &variable); } +inline int Atomic::incrementAndReturn (int& variable) { return OSAtomicIncrement32 ((int32_t*) &variable); } +inline void Atomic::decrement (int& variable) { OSAtomicDecrement32 ((int32_t*) &variable); } +inline int Atomic::decrementAndReturn (int& variable) { return OSAtomicDecrement32 ((int32_t*) &variable); } #elif JUCE_GCC - //============================================================================== - #if JUCE_USE_GCC_ATOMIC_INTRINSICS - forcedinline void atomicIncrement (int& variable) throw() { __sync_add_and_fetch (&variable, 1); } - forcedinline int atomicIncrementAndReturn (int& variable) throw() { return __sync_add_and_fetch (&variable, 1); } - forcedinline void atomicDecrement (int& variable) throw() { __sync_add_and_fetch (&variable, -1); } - forcedinline int atomicDecrementAndReturn (int& variable) throw() { return __sync_add_and_fetch (&variable, -1); } - #else - //============================================================================== - /** Increments an integer in a thread-safe way. */ - forcedinline void atomicIncrement (int& variable) throw() - { - __asm__ __volatile__ ( - #if JUCE_64BIT - "lock incl (%%rax)" - : - : "a" (&variable) - : "cc", "memory"); - #else - "lock incl %0" - : "=m" (variable) - : "m" (variable)); - #endif - } - /** Increments an integer in a thread-safe way and returns the incremented value. */ - forcedinline int atomicIncrementAndReturn (int& variable) throw() - { - int result; - - __asm__ __volatile__ ( - #if JUCE_64BIT - "lock xaddl %%ebx, (%%rax) \n\ - incl %%ebx" - : "=b" (result) - : "a" (&variable), "b" (1) - : "cc", "memory"); - #else - "lock xaddl %%eax, (%%ecx) \n\ - incl %%eax" - : "=a" (result) - : "c" (&variable), "a" (1) - : "memory"); - #endif - - return result; - } +//============================================================================== +#if JUCE_USE_GCC_ATOMIC_INTRINSICS // Linux with intrinsics... - /** Decrememts an integer in a thread-safe way. */ - forcedinline void atomicDecrement (int& variable) throw() - { - __asm__ __volatile__ ( - #if JUCE_64BIT - "lock decl (%%rax)" - : - : "a" (&variable) - : "cc", "memory"); - #else - "lock decl %0" - : "=m" (variable) - : "m" (variable)); - #endif - } +inline void Atomic::increment (int& variable) { __sync_add_and_fetch (&variable, 1); } +inline int Atomic::incrementAndReturn (int& variable) { return __sync_add_and_fetch (&variable, 1); } +inline void Atomic::decrement (int& variable) { __sync_add_and_fetch (&variable, -1); } +inline int Atomic::decrementAndReturn (int& variable) { return __sync_add_and_fetch (&variable, -1); } - /** Decrememts an integer in a thread-safe way and returns the incremented value. */ - forcedinline int atomicDecrementAndReturn (int& variable) throw() - { - int result; - - __asm__ __volatile__ ( - #if JUCE_64BIT - "lock xaddl %%ebx, (%%rax) \n\ - decl %%ebx" - : "=b" (result) - : "a" (&variable), "b" (-1) - : "cc", "memory"); - #else - "lock xaddl %%eax, (%%ecx) \n\ - decl %%eax" - : "=a" (result) - : "c" (&variable), "a" (-1) - : "memory"); - #endif - return result; - } - #endif +//============================================================================== +#else // Linux without intrinsics... + +inline void Atomic::increment (int& variable) +{ + __asm__ __volatile__ ( + #if JUCE_64BIT + "lock incl (%%rax)" + : + : "a" (&variable) + : "cc", "memory"); + #else + "lock incl %0" + : "=m" (variable) + : "m" (variable)); + #endif +} + +inline int Atomic::incrementAndReturn (int& variable) +{ + int result; + + __asm__ __volatile__ ( + #if JUCE_64BIT + "lock xaddl %%ebx, (%%rax) \n\ + incl %%ebx" + : "=b" (result) + : "a" (&variable), "b" (1) + : "cc", "memory"); + #else + "lock xaddl %%eax, (%%ecx) \n\ + incl %%eax" + : "=a" (result) + : "c" (&variable), "a" (1) + : "memory"); + #endif + + return result; +} + +inline void Atomic::decrement (int& variable) +{ + __asm__ __volatile__ ( + #if JUCE_64BIT + "lock decl (%%rax)" + : + : "a" (&variable) + : "cc", "memory"); + #else + "lock decl %0" + : "=m" (variable) + : "m" (variable)); + #endif +} + +inline int Atomic::decrementAndReturn (int& variable) +{ + int result; + + __asm__ __volatile__ ( + #if JUCE_64BIT + "lock xaddl %%ebx, (%%rax) \n\ + decl %%ebx" + : "=b" (result) + : "a" (&variable), "b" (-1) + : "cc", "memory"); + #else + "lock xaddl %%eax, (%%ecx) \n\ + decl %%eax" + : "=a" (result) + : "c" (&variable), "a" (-1) + : "memory"); + #endif + return result; +} +#endif -#elif JUCE_USE_INTRINSICS - //============================================================================== - #pragma intrinsic (_InterlockedIncrement) - #pragma intrinsic (_InterlockedDecrement) +//============================================================================== +#elif JUCE_USE_INTRINSICS // Windows with intrinsics... - /** Increments an integer in a thread-safe way. */ - forcedinline void __fastcall atomicIncrement (int& variable) throw() - { - _InterlockedIncrement (reinterpret_cast (&variable)); - } +#pragma intrinsic (_InterlockedIncrement) +#pragma intrinsic (_InterlockedDecrement) - /** Increments an integer in a thread-safe way and returns the incremented value. */ - forcedinline int __fastcall atomicIncrementAndReturn (int& variable) throw() - { - return _InterlockedIncrement (reinterpret_cast (&variable)); - } +inline void Atomic::increment (int& variable) { _InterlockedIncrement (reinterpret_cast (&variable)); } +inline int Atomic::incrementAndReturn (int& variable) { return _InterlockedIncrement (reinterpret_cast (&variable)); } +inline void Atomic::decrement (int& variable) { _InterlockedDecrement (reinterpret_cast (&variable)); } +inline int Atomic::decrementAndReturn (int& variable) { return _InterlockedDecrement (reinterpret_cast (&variable)); } - /** Decrememts an integer in a thread-safe way. */ - forcedinline void __fastcall atomicDecrement (int& variable) throw() - { - _InterlockedDecrement (reinterpret_cast (&variable)); - } +//============================================================================== +#else // Windows without intrinsics... - /** Decrememts an integer in a thread-safe way and returns the incremented value. */ - forcedinline int __fastcall atomicDecrementAndReturn (int& variable) throw() - { - return _InterlockedDecrement (reinterpret_cast (&variable)); +inline void Atomic::increment (int& variable) +{ + __asm { + mov ecx, dword ptr [variable] + lock inc dword ptr [ecx] } -#else - //============================================================================== - /** Increments an integer in a thread-safe way. */ - forcedinline void __fastcall atomicIncrement (int& variable) throw() - { - __asm { - mov ecx, dword ptr [variable] - lock inc dword ptr [ecx] - } +} + +inline int Atomic::incrementAndReturn (int& variable) +{ + int result; + + __asm { + mov ecx, dword ptr [variable] + mov eax, 1 + lock xadd dword ptr [ecx], eax + inc eax + mov result, eax } - /** Increments an integer in a thread-safe way and returns the incremented value. */ - forcedinline int __fastcall atomicIncrementAndReturn (int& variable) throw() - { - int result; - - __asm { - mov ecx, dword ptr [variable] - mov eax, 1 - lock xadd dword ptr [ecx], eax - inc eax - mov result, eax - } + return result; +} - return result; +inline void Atomic::decrement (int& variable) +{ + __asm { + mov ecx, dword ptr [variable] + lock dec dword ptr [ecx] } - - /** Decrememts an integer in a thread-safe way. */ - forcedinline void __fastcall atomicDecrement (int& variable) throw() - { - __asm { - mov ecx, dword ptr [variable] - lock dec dword ptr [ecx] - } +} + +inline int Atomic::decrementAndReturn (int& variable) +{ + int result; + + __asm { + mov ecx, dword ptr [variable] + mov eax, -1 + lock xadd dword ptr [ecx], eax + dec eax + mov result, eax } - /** Decrememts an integer in a thread-safe way and returns the incremented value. */ - forcedinline int __fastcall atomicDecrementAndReturn (int& variable) throw() - { - int result; - - __asm { - mov ecx, dword ptr [variable] - mov eax, -1 - lock xadd dword ptr [ecx], eax - dec eax - mov result, eax - } + return result; +} - return result; - } #endif #endif // __JUCE_ATOMIC_JUCEHEADER__ diff --git a/src/core/juce_ByteOrder.h b/src/core/juce_ByteOrder.h new file mode 100644 index 0000000000..c379de8528 --- /dev/null +++ b/src/core/juce_ByteOrder.h @@ -0,0 +1,174 @@ +/* + ============================================================================== + + This file is part of the JUCE library - "Jules' Utility Class Extensions" + Copyright 2004-9 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 __JUCE_BYTEORDER_JUCEHEADER__ +#define __JUCE_BYTEORDER_JUCEHEADER__ + + +//============================================================================== +/** Contains static methods for converting the byte order between different + endiannesses. +*/ +class JUCE_API ByteOrder +{ +public: + //============================================================================== + /** Swaps the upper and lower bytes of a 16-bit integer. */ + static uint16 swap (uint16 value); + + /** Reverses the order of the 4 bytes in a 32-bit integer. */ + static uint32 swap (uint32 value); + + /** Reverses the order of the 8 bytes in a 64-bit integer. */ + static uint64 swap (uint64 value); + + //============================================================================== + /** Swaps the byte order of a 16-bit int if the CPU is big-endian */ + static uint16 swapIfBigEndian (const uint16 value); + + /** Swaps the byte order of a 32-bit int if the CPU is big-endian */ + static uint32 swapIfBigEndian (const uint32 value); + + /** Swaps the byte order of a 64-bit int if the CPU is big-endian */ + static uint64 swapIfBigEndian (const uint64 value); + + /** Swaps the byte order of a 16-bit int if the CPU is little-endian */ + static uint16 swapIfLittleEndian (const uint16 value); + + /** Swaps the byte order of a 32-bit int if the CPU is little-endian */ + static uint32 swapIfLittleEndian (const uint32 value); + + /** Swaps the byte order of a 64-bit int if the CPU is little-endian */ + static uint64 swapIfLittleEndian (const uint64 value); + + //============================================================================== + /** Turns 4 bytes into a little-endian integer. */ + static uint32 littleEndianInt (const char* const bytes); + + /** Turns 2 bytes into a little-endian integer. */ + static uint16 littleEndianShort (const char* const bytes); + + /** Turns 4 bytes into a big-endian integer. */ + static uint32 bigEndianInt (const char* const bytes); + + /** Turns 2 bytes into a big-endian integer. */ + static uint16 bigEndianShort (const char* const bytes); + + //============================================================================== + /** Converts 3 little-endian bytes into a signed 24-bit value (which is sign-extended to 32 bits). */ + static int littleEndian24Bit (const char* const bytes); + + /** Converts 3 big-endian bytes into a signed 24-bit value (which is sign-extended to 32 bits). */ + static int bigEndian24Bit (const char* const bytes); + + /** Copies a 24-bit number to 3 little-endian bytes. */ + static void littleEndian24BitToChars (const int value, char* const destBytes); + + /** Copies a 24-bit number to 3 big-endian bytes. */ + static void bigEndian24BitToChars (const int value, char* const destBytes); + + //============================================================================== + /** Returns true if the current CPU is big-endian. */ + static bool isBigEndian(); +}; + + +//============================================================================== +#if JUCE_USE_INTRINSICS + #pragma intrinsic (_byteswap_ulong) +#endif + +inline uint16 ByteOrder::swap (uint16 n) +{ +#if JUCE_USE_INTRINSICSxxx // agh - the MS compiler has an internal error when you try to use this intrinsic! + return (uint16) _byteswap_ushort (n); +#else + return (uint16) ((n << 8) | (n >> 8)); +#endif +} + +inline uint32 ByteOrder::swap (uint32 n) +{ +#if JUCE_MAC || JUCE_IPHONE + return OSSwapInt32 (n); +#elif JUCE_GCC + asm("bswap %%eax" : "=a"(n) : "a"(n)); + return n; +#elif JUCE_USE_INTRINSICS + return _byteswap_ulong (n); +#else + __asm { + mov eax, n + bswap eax + mov n, eax + } + return n; +#endif +} + +inline uint64 ByteOrder::swap (uint64 value) +{ +#if JUCE_MAC || JUCE_IPHONE + return OSSwapInt64 (value); +#elif JUCE_USE_INTRINSICS + return _byteswap_uint64 (value); +#else + return (((int64) swap ((uint32) value)) << 32) | swap ((uint32) (value >> 32)); +#endif +} + +#if JUCE_LITTLE_ENDIAN + inline uint16 ByteOrder::swapIfBigEndian (const uint16 v) { return v; } + inline uint32 ByteOrder::swapIfBigEndian (const uint32 v) { return v; } + inline uint64 ByteOrder::swapIfBigEndian (const uint64 v) { return v; } + inline uint16 ByteOrder::swapIfLittleEndian (const uint16 v) { return swap (v); } + inline uint32 ByteOrder::swapIfLittleEndian (const uint32 v) { return swap (v); } + inline uint64 ByteOrder::swapIfLittleEndian (const uint64 v) { return swap (v); } + inline uint32 ByteOrder::littleEndianInt (const char* const bytes) { return *(uint32*) bytes; } + inline uint16 ByteOrder::littleEndianShort (const char* const bytes) { return *(uint16*) bytes; } + inline uint32 ByteOrder::bigEndianInt (const char* const bytes) { return swap (*(uint32*) bytes); } + inline uint16 ByteOrder::bigEndianShort (const char* const bytes) { return swap (*(uint16*) bytes); } + inline bool ByteOrder::isBigEndian() { return false; } +#else + inline uint16 ByteOrder::swapIfBigEndian (const uint16 v) { return swap (v); } + inline uint32 ByteOrder::swapIfBigEndian (const uint32 v) { return swap (v); } + inline uint64 ByteOrder::swapIfBigEndian (const uint64 v) { return swap (v); } + inline uint16 ByteOrder::swapIfLittleEndian (const uint16 v) { return v; } + inline uint32 ByteOrder::swapIfLittleEndian (const uint32 v) { return v; } + inline uint64 ByteOrder::swapIfLittleEndian (const uint64 v) { return v; } + inline uint32 ByteOrder::littleEndianInt (const char* const bytes) { return swap (*(uint32*) bytes); } + inline uint16 ByteOrder::littleEndianShort (const char* const bytes) { return swap (*(uint16*) bytes); } + inline uint32 ByteOrder::bigEndianInt (const char* const bytes) { return *(uint32*) bytes; } + inline uint16 ByteOrder::bigEndianShort (const char* const bytes) { return *(uint16*) bytes; } + inline bool ByteOrder::isBigEndian() { return true; } +#endif + +inline int ByteOrder::littleEndian24Bit (const char* const bytes) { return (((int) bytes[2]) << 16) | (((uint32) (uint8) bytes[1]) << 8) | ((uint32) (uint8) bytes[0]); } +inline int ByteOrder::bigEndian24Bit (const char* const bytes) { return (((int) bytes[0]) << 16) | (((uint32) (uint8) bytes[1]) << 8) | ((uint32) (uint8) bytes[2]); } +inline void ByteOrder::littleEndian24BitToChars (const int value, char* const destBytes) { destBytes[0] = (char)(value & 0xff); destBytes[1] = (char)((value >> 8) & 0xff); destBytes[2] = (char)((value >> 16) & 0xff); } +inline void ByteOrder::bigEndian24BitToChars (const int value, char* const destBytes) { destBytes[0] = (char)((value >> 16) & 0xff); destBytes[1] = (char)((value >> 8) & 0xff); destBytes[2] = (char)(value & 0xff); } + + +#endif // __JUCE_BYTEORDER_JUCEHEADER__ diff --git a/src/core/juce_DataConversions.h b/src/core/juce_DataConversions.h deleted file mode 100644 index ec1835506f..0000000000 --- a/src/core/juce_DataConversions.h +++ /dev/null @@ -1,210 +0,0 @@ -/* - ============================================================================== - - This file is part of the JUCE library - "Jules' Utility Class Extensions" - Copyright 2004-9 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 __JUCE_DATACONVERSIONS_JUCEHEADER__ -#define __JUCE_DATACONVERSIONS_JUCEHEADER__ - -#if JUCE_USE_INTRINSICS - #pragma intrinsic (_byteswap_ulong) -#endif - -//============================================================================== -// Endianness conversions.. - -#if JUCE_IPHONE -// a gcc compiler error seems to mean that these functions only work properly -// on the iPhone if they are declared static.. -static forcedinline uint32 swapByteOrder (uint32 n) throw(); -static inline uint16 swapByteOrder (const uint16 n) throw(); -static inline uint64 swapByteOrder (const uint64 value) throw(); -#endif - -/** Swaps the byte-order in an integer from little to big-endianness or vice-versa. */ -forcedinline uint32 swapByteOrder (uint32 n) throw() -{ -#if JUCE_MAC || JUCE_IPHONE - // Mac version - return OSSwapInt32 (n); -#elif JUCE_GCC - // Inpenetrable GCC version.. - asm("bswap %%eax" : "=a"(n) : "a"(n)); - return n; -#elif JUCE_USE_INTRINSICS - // Win32 intrinsics version.. - return _byteswap_ulong (n); -#else - // Win32 version.. - __asm { - mov eax, n - bswap eax - mov n, eax - } - return n; -#endif -} - -/** Swaps the byte-order of a 16-bit short. */ -inline uint16 swapByteOrder (const uint16 n) throw() -{ -#if JUCE_USE_INTRINSICSxxx // agh - the MS compiler has an internal error when you try to use this intrinsic! - // Win32 intrinsics version.. - return (uint16) _byteswap_ushort (n); -#else - return (uint16) ((n << 8) | (n >> 8)); -#endif -} - -inline uint64 swapByteOrder (const uint64 value) throw() -{ -#if JUCE_MAC || JUCE_IPHONE - return OSSwapInt64 (value); -#elif JUCE_USE_INTRINSICS - return _byteswap_uint64 (value); -#else - return (((int64) swapByteOrder ((uint32) value)) << 32) - | swapByteOrder ((uint32) (value >> 32)); -#endif -} - -#if JUCE_LITTLE_ENDIAN - /** Swaps the byte order of a 16-bit int if the CPU is big-endian */ - inline uint16 swapIfBigEndian (const uint16 v) throw() { return v; } - /** Swaps the byte order of a 32-bit int if the CPU is big-endian */ - inline uint32 swapIfBigEndian (const uint32 v) throw() { return v; } - /** Swaps the byte order of a 64-bit int if the CPU is big-endian */ - inline uint64 swapIfBigEndian (const uint64 v) throw() { return v; } - - /** Swaps the byte order of a 16-bit int if the CPU is little-endian */ - inline uint16 swapIfLittleEndian (const uint16 v) throw() { return swapByteOrder (v); } - /** Swaps the byte order of a 32-bit int if the CPU is little-endian */ - inline uint32 swapIfLittleEndian (const uint32 v) throw() { return swapByteOrder (v); } - /** Swaps the byte order of a 64-bit int if the CPU is little-endian */ - inline uint64 swapIfLittleEndian (const uint64 v) throw() { return swapByteOrder (v); } - - /** Turns 4 bytes into a little-endian integer. */ - inline uint32 littleEndianInt (const char* const bytes) throw() { return *(uint32*) bytes; } - /** Turns 2 bytes into a little-endian integer. */ - inline uint16 littleEndianShort (const char* const bytes) throw() { return *(uint16*) bytes; } - - /** Turns 4 bytes into a big-endian integer. */ - inline uint32 bigEndianInt (const char* const bytes) throw() { return swapByteOrder (*(uint32*) bytes); } - /** Turns 2 bytes into a big-endian integer. */ - inline uint16 bigEndianShort (const char* const bytes) throw() { return swapByteOrder (*(uint16*) bytes); } - -#else - /** Swaps the byte order of a 16-bit int if the CPU is big-endian */ - inline uint16 swapIfBigEndian (const uint16 v) throw() { return swapByteOrder (v); } - /** Swaps the byte order of a 32-bit int if the CPU is big-endian */ - inline uint32 swapIfBigEndian (const uint32 v) throw() { return swapByteOrder (v); } - /** Swaps the byte order of a 64-bit int if the CPU is big-endian */ - inline uint64 swapIfBigEndian (const uint64 v) throw() { return swapByteOrder (v); } - - /** Swaps the byte order of a 16-bit int if the CPU is little-endian */ - inline uint16 swapIfLittleEndian (const uint16 v) throw() { return v; } - /** Swaps the byte order of a 32-bit int if the CPU is little-endian */ - inline uint32 swapIfLittleEndian (const uint32 v) throw() { return v; } - /** Swaps the byte order of a 64-bit int if the CPU is little-endian */ - inline uint64 swapIfLittleEndian (const uint64 v) throw() { return v; } - - /** Turns 4 bytes into a little-endian integer. */ - inline uint32 littleEndianInt (const char* const bytes) throw() { return swapByteOrder (*(uint32*) bytes); } - /** Turns 2 bytes into a little-endian integer. */ - inline uint16 littleEndianShort (const char* const bytes) throw() { return swapByteOrder (*(uint16*) bytes); } - - /** Turns 4 bytes into a big-endian integer. */ - inline uint32 bigEndianInt (const char* const bytes) throw() { return *(uint32*) bytes; } - /** Turns 2 bytes into a big-endian integer. */ - inline uint16 bigEndianShort (const char* const bytes) throw() { return *(uint16*) bytes; } -#endif - -/** Converts 3 little-endian bytes into a signed 24-bit value (which is sign-extended to 32 bits). */ -inline int littleEndian24Bit (const char* const bytes) throw() { return (((int) bytes[2]) << 16) | (((uint32) (uint8) bytes[1]) << 8) | ((uint32) (uint8) bytes[0]); } -/** Converts 3 big-endian bytes into a signed 24-bit value (which is sign-extended to 32 bits). */ -inline int bigEndian24Bit (const char* const bytes) throw() { return (((int) bytes[0]) << 16) | (((uint32) (uint8) bytes[1]) << 8) | ((uint32) (uint8) bytes[2]); } - -/** Copies a 24-bit number to 3 little-endian bytes. */ -inline void littleEndian24BitToChars (const int value, char* const destBytes) throw() { destBytes[0] = (char)(value & 0xff); destBytes[1] = (char)((value >> 8) & 0xff); destBytes[2] = (char)((value >> 16) & 0xff); } -/** Copies a 24-bit number to 3 big-endian bytes. */ -inline void bigEndian24BitToChars (const int value, char* const destBytes) throw() { destBytes[0] = (char)((value >> 16) & 0xff); destBytes[1] = (char)((value >> 8) & 0xff); destBytes[2] = (char)(value & 0xff); } - - -//============================================================================== -/** Fast floating-point-to-integer conversion. - - This is faster than using the normal c++ cast to convert a double to an int, and - it will round the value to the nearest integer, rather than rounding it down - like the normal cast does. - - Note that this routine gets its speed at the expense of some accuracy, and when - rounding values whose floating point component is exactly 0.5, odd numbers and - even numbers will be rounded up or down differently. For a more accurate conversion, - see roundDoubleToIntAccurate(). -*/ -inline int roundDoubleToInt (const double value) throw() -{ - union { int asInt[2]; double asDouble; } n; - n.asDouble = value + 6755399441055744.0; - -#if JUCE_BIG_ENDIAN - return n.asInt [1]; -#else - return n.asInt [0]; -#endif -} - -/** Fast floating-point-to-integer conversion. - - This is a slightly slower and slightly more accurate version of roundDoubleToInt(). It works - fine for values above zero, but negative numbers are rounded the wrong way. -*/ -inline int roundDoubleToIntAccurate (const double value) throw() -{ - return roundDoubleToInt (value + 1.5e-8); -} - -/** Fast floating-point-to-integer conversion. - - This is faster than using the normal c++ cast to convert a float to an int, and - it will round the value to the nearest integer, rather than rounding it down - like the normal cast does. - - Note that this routine gets its speed at the expense of some accuracy, and when - rounding values whose floating point component is exactly 0.5, odd numbers and - even numbers will be rounded up or down differently. -*/ -inline int roundFloatToInt (const float value) throw() -{ - union { int asInt[2]; double asDouble; } n; - n.asDouble = value + 6755399441055744.0; - -#if JUCE_BIG_ENDIAN - return n.asInt [1]; -#else - return n.asInt [0]; -#endif -} - - -#endif // __JUCE_DATACONVERSIONS_JUCEHEADER__ diff --git a/src/core/juce_MathsFunctions.h b/src/core/juce_MathsFunctions.h index 5c7e738c8a..67985e443f 100644 --- a/src/core/juce_MathsFunctions.h +++ b/src/core/juce_MathsFunctions.h @@ -170,7 +170,7 @@ inline double jmin (const double a, const double b, const double c, const double and upperLimit (inclusive) @see jlimit0To, jmin, jmax */ -template +template inline Type jlimit (const Type lowerLimit, const Type upperLimit, const Type valueToConstrain) throw() @@ -185,8 +185,8 @@ inline Type jlimit (const Type lowerLimit, //============================================================================== /** Handy function to swap two values over. */ -template -inline void swapVariables (Type& variable1, Type& variable2) throw() +template +inline void swapVariables (Type& variable1, Type& variable2) { const Type tempVal = variable1; variable1 = variable2; @@ -207,25 +207,33 @@ inline void swapVariables (Type& variable1, Type& variable2) throw() //============================================================================== // Some useful maths functions that aren't always present with all compilers and build settings. -#if JUCE_WINDOWS || defined (DOXYGEN) - /** Using juce_hypot and juce_hypotf is easier than dealing with all the different - versions of these functions of various platforms and compilers. */ - forcedinline double juce_hypot (double a, double b) { return _hypot (a, b); } - - /** Using juce_hypot and juce_hypotf is easier than dealing with all the different - versions of these functions of various platforms and compilers. */ - forcedinline float juce_hypotf (float a, float b) { return (float) _hypot (a, b); } -#else - /** Using juce_hypot and juce_hypotf is easier than dealing with all the different - versions of these functions of various platforms and compilers. */ - forcedinline double juce_hypot (double a, double b) { return hypot (a, b); } +/** Using juce_hypot and juce_hypotf is easier than dealing with all the different + versions of these functions of various platforms and compilers. */ +inline double juce_hypot (double a, double b) +{ + #if JUCE_WINDOWS + return _hypot (a, b); + #else + return hypot (a, b); + #endif +} - /** Using juce_hypot and juce_hypotf is easier than dealing with all the different - versions of these functions of various platforms and compilers. */ - forcedinline float juce_hypotf (float a, float b) { return hypotf (a, b); } -#endif +/** Using juce_hypot and juce_hypotf is easier than dealing with all the different + versions of these functions of various platforms and compilers. */ +inline float juce_hypotf (float a, float b) +{ + #if JUCE_WINDOWS + return (float) _hypot (a, b); + #else + return hypotf (a, b); + #endif +} -inline int64 abs64 (const int64 n) throw() { return (n >= 0) ? n : -n; } +/** 64-bit abs function. */ +inline int64 abs64 (const int64 n) +{ + return (n >= 0) ? n : -n; +} //============================================================================== @@ -243,17 +251,74 @@ const float float_Pi = 3.14159265358979323846f; //============================================================================== -/** The isfinite() method seems to vary greatly between platforms, so this is a - platform-independent macro for it. +/** The isfinite() method seems to vary between platforms, so this is a + platform-independent function for it. */ -#if JUCE_LINUX || JUCE_MAC || JUCE_IPHONE - #define juce_isfinite(v) std::isfinite(v) -#elif JUCE_WINDOWS && ! defined (isfinite) - #define juce_isfinite(v) _finite(v) -#else - #define juce_isfinite(v) isfinite(v) -#endif +template +inline bool juce_isfinite (FloatingPointType value) +{ + #if JUCE_WINDOWS + return _finite (value); + #else + return std::isfinite (value); + #endif +} + +//============================================================================== +/** Fast floating-point-to-integer conversion. + This is faster than using the normal c++ cast to convert a double to an int, and + it will round the value to the nearest integer, rather than rounding it down + like the normal cast does. + + Note that this routine gets its speed at the expense of some accuracy, and when + rounding values whose floating point component is exactly 0.5, odd numbers and + even numbers will be rounded up or down differently. For a more accurate conversion, + see roundDoubleToIntAccurate(). +*/ +inline int roundDoubleToInt (const double value) throw() +{ + union { int asInt[2]; double asDouble; } n; + n.asDouble = value + 6755399441055744.0; + + #if JUCE_BIG_ENDIAN + return n.asInt [1]; + #else + return n.asInt [0]; + #endif +} + +/** Fast floating-point-to-integer conversion. + + This is a slightly slower and slightly more accurate version of roundDoubleToInt(). It works + fine for values above zero, but negative numbers are rounded the wrong way. +*/ +inline int roundDoubleToIntAccurate (const double value) throw() +{ + return roundDoubleToInt (value + 1.5e-8); +} + +/** Fast floating-point-to-integer conversion. + + This is faster than using the normal c++ cast to convert a float to an int, and + it will round the value to the nearest integer, rather than rounding it down + like the normal cast does. + + Note that this routine gets its speed at the expense of some accuracy, and when + rounding values whose floating point component is exactly 0.5, odd numbers and + even numbers will be rounded up or down differently. +*/ +inline int roundFloatToInt (const float value) throw() +{ + union { int asInt[2]; double asDouble; } n; + n.asDouble = value + 6755399441055744.0; + + #if JUCE_BIG_ENDIAN + return n.asInt [1]; + #else + return n.asInt [0]; + #endif +} //============================================================================== diff --git a/src/core/juce_Memory.h b/src/core/juce_Memory.h index 80beee2bd7..8297c05b2a 100644 --- a/src/core/juce_Memory.h +++ b/src/core/juce_Memory.h @@ -180,7 +180,7 @@ //============================================================================== #if JUCE_MSVC - /** This is a compiler-indenpendent way of declaring a variable as being thread-local. + /** This is a compiler-independent way of declaring a variable as being thread-local. E.g. @code diff --git a/src/core/juce_Random.cpp b/src/core/juce_Random.cpp index 8a3df9976f..97e65643d1 100644 --- a/src/core/juce_Random.cpp +++ b/src/core/juce_Random.cpp @@ -48,13 +48,11 @@ void Random::setSeed (const int64 newSeed) throw() void Random::setSeedRandomly() { - Random r1 (Time::getMillisecondCounter()); - Random r2 (Time::getHighResolutionTicks()); - Random r3 (Time::getHighResolutionTicksPerSecond()); - Random r4 (Time::currentTimeMillis()); - - setSeed (nextInt64() ^ r1.nextInt64() ^ r2.nextInt64() - ^ r3.nextInt64() ^ r4.nextInt64()); + seed ^= (int64) (pointer_sized_int) this; + seed ^= nextInt64() ^ Time::getMillisecondCounter(); + seed ^= nextInt64() ^ Time::getHighResolutionTicks(); + seed ^= nextInt64() ^ Time::getHighResolutionTicksPerSecond(); + seed ^= nextInt64() ^ Time::currentTimeMillis(); } //============================================================================== diff --git a/src/core/juce_StandardHeader.h b/src/core/juce_StandardHeader.h index b13c4a86a5..cdfee0bf1d 100644 --- a/src/core/juce_StandardHeader.h +++ b/src/core/juce_StandardHeader.h @@ -128,7 +128,7 @@ // Now include some basics that are needed by most of the Juce classes... BEGIN_JUCE_NAMESPACE -extern bool JUCE_API JUCE_CALLTYPE juce_isRunningUnderDebugger(); +extern bool JUCE_PUBLIC_FUNCTION juce_isRunningUnderDebugger(); #if JUCE_LOG_ASSERTIONS extern void JUCE_API juce_LogAssertion (const char* filename, const int lineNum) throw(); @@ -136,7 +136,7 @@ extern bool JUCE_API JUCE_CALLTYPE juce_isRunningUnderDebugger(); #include "juce_Memory.h" #include "juce_MathsFunctions.h" -#include "juce_DataConversions.h" +#include "juce_ByteOrder.h" #include "juce_Logger.h" END_JUCE_NAMESPACE diff --git a/src/core/juce_SystemStats.cpp b/src/core/juce_SystemStats.cpp index b91703a358..c187a1ea0a 100644 --- a/src/core/juce_SystemStats.cpp +++ b/src/core/juce_SystemStats.cpp @@ -63,12 +63,13 @@ void JUCE_PUBLIC_FUNCTION initialiseJuce_NonGUI() // Some simple test code to keep an eye on things and make sure these functions // work ok on all platforms. Let me know if any of these assertions fail! int n = 1; - atomicIncrement (n); - jassert (atomicIncrementAndReturn (n) == 3); - atomicDecrement (n); - jassert (atomicDecrementAndReturn (n) == 1); + Atomic::increment (n); + jassert (Atomic::incrementAndReturn (n) == 3); + Atomic::decrement (n); + jassert (Atomic::decrementAndReturn (n) == 1); - jassert (swapByteOrder ((uint32) 0x11223344) == 0x44332211); + jassert (ByteOrder::swap ((uint16) 0x1122) == 0x2211); + jassert (ByteOrder::swap ((uint32) 0x11223344) == 0x44332211); // quick test to make sure the run-time lib doesn't crash on freeing a null-pointer. SystemStats* nullPointer = 0; diff --git a/src/core/juce_Time.cpp b/src/core/juce_Time.cpp index ee57f62f1b..23e9c84921 100644 --- a/src/core/juce_Time.cpp +++ b/src/core/juce_Time.cpp @@ -335,28 +335,20 @@ const String Time::toString (const bool includeDate, const String Time::formatted (const tchar* const format) const throw() { - tchar buffer[80]; + String buffer; + int bufferSize = 128; + buffer.preallocateStorage (bufferSize); struct tm t; millisToLocal (millisSinceEpoch, t); - if (CharacterFunctions::ftime (buffer, 79, format, &t) <= 0) + while (CharacterFunctions::ftime ((tchar*) (const tchar*) buffer, bufferSize, format, &t) <= 0) { - int bufferSize = 128; - - for (;;) - { - MemoryBlock mb (bufferSize * sizeof (tchar)); - tchar* const b = (tchar*) mb.getData(); - - if (CharacterFunctions::ftime (b, bufferSize, format, &t) > 0) - return String (b); - - bufferSize += 128; - } + bufferSize += 128; + buffer.preallocateStorage (bufferSize); } - return String (buffer); + return buffer; } //============================================================================== diff --git a/src/cryptography/juce_MD5.cpp b/src/cryptography/juce_MD5.cpp index 64327770a7..8844497109 100644 --- a/src/cryptography/juce_MD5.cpp +++ b/src/cryptography/juce_MD5.cpp @@ -77,7 +77,7 @@ MD5::MD5 (const String& text) // force the string into integer-sized unicode characters, to try to make it // get the same results on all platforms + compilers. uint32 unicodeChar = (uint32) t[i]; - swapIfBigEndian (unicodeChar); + ByteOrder::swapIfBigEndian (unicodeChar); context.processBlock ((const uint8*) &unicodeChar, sizeof (unicodeChar)); @@ -183,7 +183,7 @@ static void encode (uint8* const output, uint32* const o = (uint32*) output; for (int i = 0; i < (numBytes >> 2); ++i) - o[i] = swapIfBigEndian (input [i]); + o[i] = ByteOrder::swapIfBigEndian (input [i]); } static void decode (uint32* const output, @@ -191,7 +191,7 @@ static void decode (uint32* const output, const int numBytes) { for (int i = 0; i < (numBytes >> 2); ++i) - output[i] = littleEndianInt ((const char*) input + (i << 2)); + output[i] = ByteOrder::littleEndianInt ((const char*) input + (i << 2)); } //============================================================================== diff --git a/src/events/juce_InterprocessConnection.cpp b/src/events/juce_InterprocessConnection.cpp index 37620b8d55..5dc12e09d8 100644 --- a/src/events/juce_InterprocessConnection.cpp +++ b/src/events/juce_InterprocessConnection.cpp @@ -161,8 +161,8 @@ const String InterprocessConnection::getConnectedHostName() const bool InterprocessConnection::sendMessage (const MemoryBlock& message) { uint32 messageHeader[2]; - messageHeader [0] = swapIfBigEndian (magicMessageHeader); - messageHeader [1] = swapIfBigEndian ((uint32) message.getSize()); + messageHeader [0] = ByteOrder::swapIfBigEndian (magicMessageHeader); + messageHeader [1] = ByteOrder::swapIfBigEndian ((uint32) message.getSize()); MemoryBlock messageData (sizeof (messageHeader) + message.getSize()); messageData.copyFrom (messageHeader, 0, sizeof (messageHeader)); @@ -279,9 +279,9 @@ bool InterprocessConnection::readNextMessageInt() : pipe->read (messageHeader, sizeof (messageHeader), pipeReceiveMessageTimeout); if (bytes == sizeof (messageHeader) - && swapIfBigEndian (messageHeader[0]) == magicMessageHeader) + && ByteOrder::swapIfBigEndian (messageHeader[0]) == magicMessageHeader) { - const int bytesInMessage = (int) swapIfBigEndian (messageHeader[1]); + const int bytesInMessage = (int) ByteOrder::swapIfBigEndian (messageHeader[1]); if (bytesInMessage > 0 && bytesInMessage < maximumMessageSize) { diff --git a/src/gui/components/buttons/juce_Button.cpp b/src/gui/components/buttons/juce_Button.cpp index e8a5dd5904..2ee2d9b276 100644 --- a/src/gui/components/buttons/juce_Button.cpp +++ b/src/gui/components/buttons/juce_Button.cpp @@ -50,7 +50,7 @@ Button::Button (const String& name) commandID (0), connectedEdgeFlags (0), buttonState (buttonNormal), - isOn (false), + lastToggleState (false), clickTogglesState (false), needsToRelease (false), needsRepainting (false), @@ -59,10 +59,13 @@ Button::Button (const String& name) generateTooltip (false) { setWantsKeyboardFocus (true); + isOn.addListener (this); } Button::~Button() { + isOn.removeListener (this); + if (commandManagerToUse != 0) commandManagerToUse->removeListener (this); @@ -98,10 +101,12 @@ const String Button::getTooltip() { const String key (keyPresses.getReference(i).getTextDescription()); + tt << " ["; + if (key.length() == 1) - tt << " [" << TRANS("shortcut") << ": '" << key << "']"; + tt << TRANS("shortcut") << ": '" << key << "']"; else - tt << " [" << key << ']'; + tt << key << ']'; } return tt; @@ -123,17 +128,18 @@ void Button::setConnectedEdges (const int connectedEdgeFlags_) throw() void Button::setToggleState (const bool shouldBeOn, const bool sendChangeNotification) { - if (shouldBeOn != isOn) + if (shouldBeOn != lastToggleState) { const ComponentDeletionWatcher deletionWatcher (this); isOn = shouldBeOn; + lastToggleState = shouldBeOn; repaint(); if (sendChangeNotification) sendClickMessage (ModifierKeys()); - if ((! deletionWatcher.hasBeenDeleted()) && isOn) + if ((! deletionWatcher.hasBeenDeleted()) && getToggleState()) turnOffOtherButtonsInGroup (sendChangeNotification); } } @@ -154,13 +160,19 @@ bool Button::getClickingTogglesState() const throw() return clickTogglesState; } +void Button::valueChanged (Value& value) +{ + if (value.refersToSameSourceAs (isOn)) + setToggleState (isOn.getValue(), true); +} + void Button::setRadioGroupId (const int newGroupId) { if (radioGroupId != newGroupId) { radioGroupId = newGroupId; - if (isOn) + if (getToggleState()) turnOffOtherButtonsInGroup (true); } } @@ -294,7 +306,7 @@ void Button::triggerClick() void Button::internalClickCallback (const ModifierKeys& modifiers) { if (clickTogglesState) - setToggleState ((radioGroupId != 0) || ! isOn, false); + setToggleState ((radioGroupId != 0) || ! getToggleState(), false); sendClickMessage (modifiers); } diff --git a/src/gui/components/buttons/juce_Button.h b/src/gui/components/buttons/juce_Button.h index cf55559d49..ca537960b2 100644 --- a/src/gui/components/buttons/juce_Button.h +++ b/src/gui/components/buttons/juce_Button.h @@ -30,6 +30,7 @@ #include "../keyboard/juce_KeyListener.h" #include "../../../application/juce_ApplicationCommandManager.h" #include "../../../containers/juce_SortedSet.h" +#include "../../../containers/juce_Value.h" #include "../windows/juce_TooltipWindow.h" #include "../../../events/juce_Timer.h" class Button; @@ -68,6 +69,7 @@ public: class JUCE_API Button : public Component, public SettableTooltipClient, public ApplicationCommandManagerListener, + public Value::Listener, private KeyListener { protected: @@ -139,7 +141,15 @@ public: @see setToggleState */ - bool getToggleState() const throw() { return isOn; } + bool getToggleState() const throw() { return isOn.getValue(); } + + /** Returns the Value object that represents the botton's toggle state. + You can use this Value object to connect the button's state to external values or setters, + either by taking a copy of the Value, or by using Value::referTo() to make it point to + your own Value object. + @see getToggleState, Value + */ + Value& getToggleStateValue() { return isOn; } /** This tells the button to automatically flip the toggle state when the button is clicked. @@ -454,7 +464,8 @@ protected: void applicationCommandInvoked (const ApplicationCommandTarget::InvocationInfo&); /** @internal */ void applicationCommandListChanged(); - + /** @internal */ + void valueChanged (Value& value); private: //============================================================================== @@ -471,7 +482,8 @@ private: int radioGroupId, commandID, connectedEdgeFlags; ButtonState buttonState; - bool isOn : 1; + Value isOn; + bool lastToggleState : 1; bool clickTogglesState : 1; bool needsToRelease : 1; bool needsRepainting : 1; diff --git a/src/gui/components/code_editor/juce_CodeDocument.cpp b/src/gui/components/code_editor/juce_CodeDocument.cpp index 11f4669f2b..3d3d892952 100644 --- a/src/gui/components/code_editor/juce_CodeDocument.cpp +++ b/src/gui/components/code_editor/juce_CodeDocument.cpp @@ -470,7 +470,7 @@ const String CodeDocument::getTextBetween (const Position& start, const Position String result; result.preallocateStorage (end.getPosition() - start.getPosition() + 4); - tchar* dest = (tchar*) (const tchar*) result; + String::Concatenator concatenator (result); const int maxLine = jmin (lines.size() - 1, endLine); @@ -482,26 +482,19 @@ const String CodeDocument::getTextBetween (const Position& start, const Position if (i == startLine) { const int index = start.getIndexInLine(); - len -= index; - line->line.substring (index).copyToBuffer (dest, len); - dest += len; + concatenator.append (line->line.substring (index, len)); } else if (i == endLine) { len = end.getIndexInLine(); - line->line.copyToBuffer (dest, len); - dest += len; + concatenator.append (line->line.substring (0, len)); } else { - line->line.copyToBuffer (dest, len); - dest += len; + concatenator.append (line->line); } } - // check we preallocated enough space.. - jassert ((dest - (const tchar*) result) <= end.getPosition() - start.getPosition()); - return result; } diff --git a/src/gui/components/controls/juce_Slider.cpp b/src/gui/components/controls/juce_Slider.cpp index 5c35cdf507..494f028e90 100644 --- a/src/gui/components/controls/juce_Slider.cpp +++ b/src/gui/components/controls/juce_Slider.cpp @@ -457,9 +457,9 @@ void Slider::valueChanged (Value& value) setValue (currentValue.getValue(), false, false); } else if (value.refersToSameSourceAs (valueMin)) - setMinValue (valueMin.getValue(), false, false); + setMinValue (valueMin.getValue(), false, false, true); else if (value.refersToSameSourceAs (valueMax)) - setMaxValue (valueMax.getValue(), false, false); + setMaxValue (valueMax.getValue(), false, false, true); } double Slider::getValue() const @@ -496,7 +496,7 @@ void Slider::setValue (double newValue, valueBox->hideEditor (true); lastCurrentValue = newValue; - currentValue = var (newValue); + currentValue = newValue; updateText(); repaint(); @@ -546,10 +546,10 @@ void Slider::setMinValue (double newValue, const bool sendUpdateMessage, const b } else { - if (allowNudgingOfOtherValues && newValue > (double) currentValue.getValue()) + if (allowNudgingOfOtherValues && newValue > lastCurrentValue) setValue (newValue, sendUpdateMessage, sendMessageSynchronously); - newValue = jmin ((double) currentValue.getValue(), newValue); + newValue = jmin (lastCurrentValue, newValue); } if (lastValueMin != newValue) @@ -586,10 +586,10 @@ void Slider::setMaxValue (double newValue, const bool sendUpdateMessage, const b } else { - if (allowNudgingOfOtherValues && newValue < (double) currentValue.getValue()) + if (allowNudgingOfOtherValues && newValue < lastCurrentValue) setValue (newValue, sendUpdateMessage, sendMessageSynchronously); - newValue = jmax ((double) currentValue.getValue(), newValue); + newValue = jmax (lastCurrentValue, newValue); } if (lastValueMax != newValue) @@ -824,7 +824,7 @@ void Slider::paint (Graphics& g) { if (style == Rotary || style == RotaryHorizontalDrag || style == RotaryVerticalDrag) { - const float sliderPos = (float) valueToProportionOfLength (currentValue.getValue()); + const float sliderPos = (float) valueToProportionOfLength (lastCurrentValue); jassert (sliderPos >= 0 && sliderPos <= 1.0f); getLookAndFeel().drawRotarySlider (g, @@ -843,9 +843,9 @@ void Slider::paint (Graphics& g) sliderRect.getY(), sliderRect.getWidth(), sliderRect.getHeight(), - getLinearSliderPos (currentValue.getValue()), - getLinearSliderPos (valueMin.getValue()), - getLinearSliderPos (valueMax.getValue()), + getLinearSliderPos (lastCurrentValue), + getLinearSliderPos (lastValueMin), + getLinearSliderPos (lastValueMax), style, *this); } diff --git a/src/gui/components/controls/juce_TextEditor.cpp b/src/gui/components/controls/juce_TextEditor.cpp index 02815476f7..3611d2103d 100644 --- a/src/gui/components/controls/juce_TextEditor.cpp +++ b/src/gui/components/controls/juce_TextEditor.cpp @@ -45,10 +45,10 @@ struct TextAtom uint16 numChars; //============================================================================== - bool isWhitespace() const throw() { return CharacterFunctions::isWhitespace (atomText[0]); } - bool isNewLine() const throw() { return atomText[0] == T('\r') || atomText[0] == T('\n'); } + bool isWhitespace() const { return CharacterFunctions::isWhitespace (atomText[0]); } + bool isNewLine() const { return atomText[0] == T('\r') || atomText[0] == T('\n'); } - const String getText (const tchar passwordCharacter) const throw() + const String getText (const tchar passwordCharacter) const { if (passwordCharacter == 0) return atomText; @@ -57,7 +57,7 @@ struct TextAtom atomText.length()); } - const String getTrimmedText (const tchar passwordCharacter) const throw() + const String getTrimmedText (const tchar passwordCharacter) const { if (passwordCharacter == 0) return atomText.substring (0, numChars); @@ -77,7 +77,7 @@ public: UniformTextSection (const String& text, const Font& font_, const Colour& colour_, - const tchar passwordCharacter) throw() + const tchar passwordCharacter) : font (font_), colour (colour_), atoms (64) @@ -85,7 +85,7 @@ public: initialiseAtoms (text, passwordCharacter); } - UniformTextSection (const UniformTextSection& other) throw() + UniformTextSection (const UniformTextSection& other) : font (other.font), colour (other.colour), atoms (64) @@ -94,12 +94,12 @@ public: atoms.add (new TextAtom (*(const TextAtom*) other.atoms.getUnchecked(i))); } - ~UniformTextSection() throw() + ~UniformTextSection() { // (no need to delete the atoms, as they're explicitly deleted by the caller) } - void clear() throw() + void clear() { for (int i = atoms.size(); --i >= 0;) delete getAtom(i); @@ -107,17 +107,17 @@ public: atoms.clear(); } - int getNumAtoms() const throw() + int getNumAtoms() const { return atoms.size(); } - TextAtom* getAtom (const int index) const throw() + TextAtom* getAtom (const int index) const { return (TextAtom*) atoms.getUnchecked (index); } - void append (const UniformTextSection& other, const tchar passwordCharacter) throw() + void append (const UniformTextSection& other, const tchar passwordCharacter) { if (other.atoms.size() > 0) { @@ -150,7 +150,7 @@ public: } UniformTextSection* split (const int indexToBreakAt, - const tchar passwordCharacter) throw() + const tchar passwordCharacter) { UniformTextSection* const section2 = new UniformTextSection (String::empty, font, colour, @@ -204,96 +204,50 @@ public: return section2; } - const String getAllText() const throw() + void appendAllText (String::Concatenator& concatenator) const { - String s; - s.preallocateStorage (getTotalLength()); - - tchar* endOfString = (tchar*) &(s[0]); - for (int i = 0; i < atoms.size(); ++i) - { - const TextAtom* const atom = getAtom(i); - - memcpy (endOfString, &(atom->atomText[0]), atom->numChars * sizeof (tchar)); - endOfString += atom->numChars; - } - - *endOfString = 0; - - jassert ((endOfString - (tchar*) &(s[0])) <= getTotalLength()); - return s; + concatenator.append (getAtom(i)->atomText); } - const String getTextSubstring (const int startCharacter, - const int endCharacter) const throw() - { - int index = 0; - int totalLen = 0; - int i; - - for (i = 0; i < atoms.size(); ++i) - { - const TextAtom* const atom = getAtom (i); - const int nextIndex = index + atom->numChars; - - if (startCharacter < nextIndex) - { - if (endCharacter <= index) - break; - - const int start = jmax (0, startCharacter - index); - const int end = jmin (endCharacter - index, atom->numChars); - jassert (end >= start); - - totalLen += end - start; - } - - index = nextIndex; - } - - String s; - s.preallocateStorage (totalLen + 1); - tchar* psz = (tchar*) (const tchar*) s; - - index = 0; - - for (i = 0; i < atoms.size(); ++i) - { - const TextAtom* const atom = getAtom (i); - const int nextIndex = index + atom->numChars; - - if (startCharacter < nextIndex) - { - if (endCharacter <= index) - break; + void appendSubstring (String::Concatenator& concatenator, + const int startCharacter, + const int endCharacter) const + { + int index = 0; + for (int i = 0; i < atoms.size(); ++i) + { + const TextAtom* const atom = getAtom (i); + const int nextIndex = index + atom->numChars; - const int start = jmax (0, startCharacter - index); - const int len = jmin (endCharacter - index, atom->numChars) - start; + if (startCharacter < nextIndex) + { + if (endCharacter <= index) + break; - memcpy (psz, ((const tchar*) atom->atomText) + start, len * sizeof (tchar)); - psz += len; - *psz = 0; - } + const int start = jmax (0, startCharacter - index); + const int end = jmin (endCharacter - index, atom->numChars); - index = nextIndex; - } + if (start < end) + concatenator.append (atom->atomText.substring (start, end)); + } - return s; + index = nextIndex; + } } - int getTotalLength() const throw() + int getTotalLength() const { - int c = 0; + int total = 0; for (int i = atoms.size(); --i >= 0;) - c += getAtom(i)->numChars; + total += getAtom(i)->numChars; - return c; + return total; } void setFont (const Font& newFont, - const tchar passwordCharacter) throw() + const tchar passwordCharacter) { if (font != newFont) { @@ -318,7 +272,7 @@ private: //============================================================================== void initialiseAtoms (const String& textToParse, - const tchar passwordCharacter) throw() + const tchar passwordCharacter) { int i = 0; const int len = textToParse.length(); @@ -384,7 +338,7 @@ public: //============================================================================== TextEditorIterator (const VoidArray& sections_, const float wordWrapWidth_, - const tchar passwordCharacter_) throw() + const tchar passwordCharacter_) : indexInText (0), lineY (0), lineHeight (0), @@ -410,7 +364,7 @@ public: } } - TextEditorIterator (const TextEditorIterator& other) throw() + TextEditorIterator (const TextEditorIterator& other) : indexInText (other.indexInText), lineY (other.lineY), lineHeight (other.lineHeight), @@ -428,12 +382,12 @@ public: { } - ~TextEditorIterator() throw() + ~TextEditorIterator() { } //============================================================================== - bool next() throw() + bool next() { if (atom == &tempAtom) { @@ -578,7 +532,7 @@ public: return true; } - void beginNewLine() throw() + void beginNewLine() { atomX = 0; lineY += lineHeight; @@ -630,7 +584,7 @@ public: } //============================================================================== - void draw (Graphics& g, const UniformTextSection*& lastSection) const throw() + void draw (Graphics& g, const UniformTextSection*& lastSection) const { if (passwordCharacter != 0 || ! atom->isWhitespace()) { @@ -654,7 +608,7 @@ public: void drawSelection (Graphics& g, const int selectionStart, - const int selectionEnd) const throw() + const int selectionEnd) const { const int startX = roundFloatToInt (indexToX (selectionStart)); const int endX = roundFloatToInt (indexToX (selectionEnd)); @@ -668,7 +622,7 @@ public: void drawSelectedText (Graphics& g, const int selectionStart, const int selectionEnd, - const Colour& selectedTextColour) const throw() + const Colour& selectedTextColour) const { if (passwordCharacter != 0 || ! atom->isWhitespace()) { @@ -704,7 +658,7 @@ public: } //============================================================================== - float indexToX (const int indexToFind) const throw() + float indexToX (const int indexToFind) const { if (indexToFind <= indexInText) return atomX; @@ -723,7 +677,7 @@ public: return jmin (atomRight, g.getGlyph (indexToFind - indexInText).getLeft()); } - int xToIndex (const float xToFind) const throw() + int xToIndex (const float xToFind) const { if (xToFind <= atomX || atom->isNewLine()) return indexInText; @@ -745,7 +699,7 @@ public: } //============================================================================== - bool getCharPosition (const int index, float& cx, float& cy, float& lineHeight_) throw() + bool getCharPosition (const int index, float& cx, float& cy, float& lineHeight_) { while (next()) { @@ -782,7 +736,7 @@ private: const TextEditorIterator& operator= (const TextEditorIterator&); - void moveToEndOfLastAtom() throw() + void moveToEndOfLastAtom() { if (atom != 0) { @@ -796,7 +750,7 @@ private: } } - bool shouldWrap (const float x) const throw() + bool shouldWrap (const float x) const { return (x - 0.0001f) >= wordWrapWidth; } @@ -822,7 +776,7 @@ public: const Font& font_, const Colour& colour_, const int oldCaretPos_, - const int newCaretPos_) throw() + const int newCaretPos_) : owner (owner_), text (text_), insertIndex (insertIndex_), @@ -871,7 +825,7 @@ public: const int endIndex_, const int oldCaretPos_, const int newCaretPos_, - const VoidArray& removedSections_) throw() + const VoidArray& removedSections_) : owner (owner_), startIndex (startIndex_), endIndex (endIndex_), @@ -920,38 +874,47 @@ public: //============================================================================== class TextHolderComponent : public Component, - public Timer + public Timer, + public Value::Listener { - TextEditor* const owner; + TextEditor& owner; TextHolderComponent (const TextHolderComponent&); const TextHolderComponent& operator= (const TextHolderComponent&); public: - TextHolderComponent (TextEditor* const owner_) + TextHolderComponent (TextEditor& owner_) : owner (owner_) { setWantsKeyboardFocus (false); setInterceptsMouseClicks (false, true); + + owner.getTextValue().addListener (this); } ~TextHolderComponent() { + owner.getTextValue().removeListener (this); } void paint (Graphics& g) { - owner->drawContent (g); + owner.drawContent (g); } void timerCallback() { - owner->timerCallbackInt(); + owner.timerCallbackInt(); } const MouseCursor getMouseCursor() { - return owner->getMouseCursor(); + return owner.getMouseCursor(); + } + + void valueChanged (Value&) + { + owner.textWasChangedByValue(); } }; @@ -1014,6 +977,7 @@ TextEditor::TextEditor (const String& name, keepCursorOnScreen (true), tabKeyUsed (false), menuActive (false), + valueTextNeedsUpdating (false), cursorX (0), cursorY (0), cursorHeight (0), @@ -1034,7 +998,7 @@ TextEditor::TextEditor (const String& name, setOpaque (true); addAndMakeVisible (viewport = new TextEditorViewport (this)); - viewport->setViewedComponent (textHolder = new TextHolderComponent (this)); + viewport->setViewedComponent (textHolder = new TextHolderComponent (*this)); viewport->setWantsKeyboardFocus (false); viewport->setScrollBarsShown (false, false); @@ -1046,10 +1010,11 @@ TextEditor::~TextEditor() { clearInternal (0); viewport = 0; + textHolder = 0; } //============================================================================== -void TextEditor::newTransaction() throw() +void TextEditor::newTransaction() { lastTransactionTime = Time::getApproximateMillisecondCounter(); undoManager.beginNewTransaction(); @@ -1084,12 +1049,12 @@ void TextEditor::setMultiLine (const bool shouldBeMultiLine, scrollToMakeSureCursorIsVisible(); } -bool TextEditor::isMultiLine() const throw() +bool TextEditor::isMultiLine() const { return multiline; } -void TextEditor::setScrollbarsShown (bool enabled) throw() +void TextEditor::setScrollbarsShown (bool enabled) { scrollbarVisible = enabled; @@ -1104,7 +1069,7 @@ void TextEditor::setReadOnly (const bool shouldBeReadOnly) enablementChanged(); } -bool TextEditor::isReadOnly() const throw() +bool TextEditor::isReadOnly() const { return readOnly || ! isEnabled(); } @@ -1114,28 +1079,28 @@ void TextEditor::setReturnKeyStartsNewLine (const bool shouldStartNewLine) returnKeyStartsNewLine = shouldStartNewLine; } -void TextEditor::setTabKeyUsedAsCharacter (const bool shouldTabKeyBeUsed) throw() +void TextEditor::setTabKeyUsedAsCharacter (const bool shouldTabKeyBeUsed) { tabKeyUsed = shouldTabKeyBeUsed; } -void TextEditor::setPopupMenuEnabled (const bool b) throw() +void TextEditor::setPopupMenuEnabled (const bool b) { popupMenuEnabled = b; } -void TextEditor::setSelectAllWhenFocused (const bool b) throw() +void TextEditor::setSelectAllWhenFocused (const bool b) { selectAllTextWhenFocused = b; } //============================================================================== -const Font TextEditor::getFont() const throw() +const Font TextEditor::getFont() const { return currentFont; } -void TextEditor::setFont (const Font& newFont) throw() +void TextEditor::setFont (const Font& newFont) { currentFont = newFont; scrollToMakeSureCursorIsVisible(); @@ -1166,7 +1131,7 @@ void TextEditor::colourChanged() repaint(); } -void TextEditor::setCaretVisible (const bool shouldCaretBeVisible) throw() +void TextEditor::setCaretVisible (const bool shouldCaretBeVisible) { caretVisible = shouldCaretBeVisible; @@ -1178,19 +1143,19 @@ void TextEditor::setCaretVisible (const bool shouldCaretBeVisible) throw() } void TextEditor::setInputRestrictions (const int maxLen, - const String& chars) throw() + const String& chars) { maxTextLength = jmax (0, maxLen); allowedCharacters = chars; } -void TextEditor::setTextToShowWhenEmpty (const String& text, const Colour& colourToUse) throw() +void TextEditor::setTextToShowWhenEmpty (const String& text, const Colour& colourToUse) { textToShowWhenEmpty = text; colourForTextWhenEmpty = colourToUse; } -void TextEditor::setPasswordCharacter (const tchar newPasswordCharacter) throw() +void TextEditor::setPasswordCharacter (const tchar newPasswordCharacter) { if (passwordCharacter != newPasswordCharacter) { @@ -1252,10 +1217,34 @@ void TextEditor::setText (const String& newText, } //============================================================================== -void TextEditor::textChanged() throw() +Value& TextEditor::getTextValue() +{ + if (valueTextNeedsUpdating) + { + valueTextNeedsUpdating = false; + textValue = getText(); + } + + return textValue; +} + +void TextEditor::textWasChangedByValue() +{ + if (textValue.getValueSource().getReferenceCount() > 1) + setText (textValue.getValue()); +} + +//============================================================================== +void TextEditor::textChanged() { updateTextHolderSize(); postCommandMessage (textChangeMessageId); + + if (textValue.getValueSource().getReferenceCount() > 1) + { + valueTextNeedsUpdating = false; + textValue = getText(); + } } void TextEditor::returnPressed() @@ -1268,7 +1257,7 @@ void TextEditor::escapePressed() postCommandMessage (escapeKeyMessageId); } -void TextEditor::addListener (TextEditorListener* const newListener) throw() +void TextEditor::addListener (TextEditorListener* const newListener) { jassert (newListener != 0) @@ -1276,7 +1265,7 @@ void TextEditor::addListener (TextEditorListener* const newListener) throw() listeners.add (newListener); } -void TextEditor::removeListener (TextEditorListener* const listenerToRemove) throw() +void TextEditor::removeListener (TextEditorListener* const listenerToRemove) { listeners.removeValue (listenerToRemove); } @@ -1349,7 +1338,7 @@ void TextEditor::repaintText (int textStartIndex, int textEndIndex) } //============================================================================== -void TextEditor::moveCaret (int newCaretPos) throw() +void TextEditor::moveCaret (int newCaretPos) { if (newCaretPos < 0) newCaretPos = 0; @@ -1367,18 +1356,18 @@ void TextEditor::moveCaret (int newCaretPos) throw() } } -void TextEditor::setCaretPosition (const int newIndex) throw() +void TextEditor::setCaretPosition (const int newIndex) { moveCursorTo (newIndex, false); } -int TextEditor::getCaretPosition() const throw() +int TextEditor::getCaretPosition() const { return caretPosition; } void TextEditor::scrollEditorToPositionCaret (const int desiredCaretX, - const int desiredCaretY) throw() + const int desiredCaretY) { updateCaretPosition(); @@ -1420,7 +1409,7 @@ void TextEditor::scrollEditorToPositionCaret (const int desiredCaretX, viewport->setViewPosition (vx, vy); } -const Rectangle TextEditor::getCaretRectangle() throw() +const Rectangle TextEditor::getCaretRectangle() { updateCaretPosition(); @@ -1430,13 +1419,13 @@ const Rectangle TextEditor::getCaretRectangle() throw() } //============================================================================== -float TextEditor::getWordWrapWidth() const throw() +float TextEditor::getWordWrapWidth() const { return (wordWrap) ? (float) (viewport->getMaximumVisibleWidth() - leftIndent - leftIndent / 2) : 1.0e10f; } -void TextEditor::updateTextHolderSize() throw() +void TextEditor::updateTextHolderSize() { const float wordWrapWidth = getWordWrapWidth(); @@ -1457,46 +1446,46 @@ void TextEditor::updateTextHolderSize() throw() } } -int TextEditor::getTextWidth() const throw() +int TextEditor::getTextWidth() const { return textHolder->getWidth(); } -int TextEditor::getTextHeight() const throw() +int TextEditor::getTextHeight() const { return textHolder->getHeight(); } void TextEditor::setIndents (const int newLeftIndent, - const int newTopIndent) throw() + const int newTopIndent) { leftIndent = newLeftIndent; topIndent = newTopIndent; } -void TextEditor::setBorder (const BorderSize& border) throw() +void TextEditor::setBorder (const BorderSize& border) { borderSize = border; resized(); } -const BorderSize TextEditor::getBorder() const throw() +const BorderSize TextEditor::getBorder() const { return borderSize; } -void TextEditor::setScrollToShowCursor (const bool shouldScrollToShowCursor) throw() +void TextEditor::setScrollToShowCursor (const bool shouldScrollToShowCursor) { keepCursorOnScreen = shouldScrollToShowCursor; } -void TextEditor::updateCaretPosition() throw() +void TextEditor::updateCaretPosition() { cursorHeight = currentFont.getHeight(); // (in case the text is empty and the call below doesn't set this value) getCharPosition (caretPosition, cursorX, cursorY, cursorHeight); } -void TextEditor::scrollToMakeSureCursorIsVisible() throw() +void TextEditor::scrollToMakeSureCursorIsVisible() { updateCaretPosition(); @@ -1542,7 +1531,7 @@ void TextEditor::scrollToMakeSureCursorIsVisible() throw() } void TextEditor::moveCursorTo (const int newPosition, - const bool isSelecting) throw() + const bool isSelecting) { if (isSelecting) { @@ -1600,7 +1589,7 @@ void TextEditor::moveCursorTo (const int newPosition, } int TextEditor::getTextIndexAt (const int x, - const int y) throw() + const int y) { return indexAtPosition ((float) (x + viewport->getViewPositionX() - leftIndent), (float) (y + viewport->getViewPositionY() - topIndent)); @@ -1637,7 +1626,7 @@ void TextEditor::insertTextAtCursor (String newText) textChanged(); } -void TextEditor::setHighlightedRegion (int startPos, int numChars) throw() +void TextEditor::setHighlightedRegion (int startPos, int numChars) { moveCursorTo (startPos, false); moveCursorTo (startPos + numChars, true); @@ -2237,7 +2226,7 @@ void TextEditor::enablementChanged() } //============================================================================== -void TextEditor::clearInternal (UndoManager* const um) throw() +void TextEditor::clearInternal (UndoManager* const um) { remove (0, getTotalNumChars(), um, caretPosition); } @@ -2247,7 +2236,7 @@ void TextEditor::insert (const String& text, const Font& font, const Colour& colour, UndoManager* const um, - const int caretPositionToMoveTo) throw() + const int caretPositionToMoveTo) { if (text.isNotEmpty()) { @@ -2299,6 +2288,7 @@ void TextEditor::insert (const String& text, coalesceSimilarSections(); totalNumChars = -1; + valueTextNeedsUpdating = true; moveCursorTo (caretPositionToMoveTo, false); @@ -2308,7 +2298,7 @@ void TextEditor::insert (const String& text, } void TextEditor::reinsert (const int insertIndex, - const VoidArray& sectionsToInsert) throw() + const VoidArray& sectionsToInsert) { int index = 0; int nextIndex = 0; @@ -2345,12 +2335,13 @@ void TextEditor::reinsert (const int insertIndex, coalesceSimilarSections(); totalNumChars = -1; + valueTextNeedsUpdating = true; } void TextEditor::remove (const int startIndex, int endIndex, UndoManager* const um, - const int caretPositionToMoveTo) throw() + const int caretPositionToMoveTo) { if (endIndex > startIndex) { @@ -2434,6 +2425,7 @@ void TextEditor::remove (const int startIndex, coalesceSimilarSections(); totalNumChars = -1; + valueTextNeedsUpdating = true; moveCursorTo (caretPositionToMoveTo, false); @@ -2443,48 +2435,56 @@ void TextEditor::remove (const int startIndex, } //============================================================================== -const String TextEditor::getText() const throw() +const String TextEditor::getText() const { String t; + t.preallocateStorage (getTotalNumChars()); + String::Concatenator concatenator (t); for (int i = 0; i < sections.size(); ++i) - t += ((const UniformTextSection*) sections.getUnchecked(i))->getAllText(); + ((const UniformTextSection*) sections.getUnchecked(i))->appendAllText (concatenator); return t; } -const String TextEditor::getTextSubstring (const int startCharacter, const int endCharacter) const throw() +const String TextEditor::getTextSubstring (const int startCharacter, const int endCharacter) const { String t; - int index = 0; - for (int i = 0; i < sections.size(); ++i) + if (endCharacter > startCharacter) { - const UniformTextSection* const s = (const UniformTextSection*) sections.getUnchecked(i); - const int nextIndex = index + s->getTotalLength(); + t.preallocateStorage (jmin (getTotalNumChars(), endCharacter - startCharacter)); + String::Concatenator concatenator (t); + int index = 0; - if (startCharacter < nextIndex) + for (int i = 0; i < sections.size(); ++i) { - if (endCharacter <= index) - break; + const UniformTextSection* const s = (const UniformTextSection*) sections.getUnchecked(i); + const int nextIndex = index + s->getTotalLength(); - const int start = jmax (index, startCharacter); - t += s->getTextSubstring (start - index, endCharacter - index); - } + if (startCharacter < nextIndex) + { + if (endCharacter <= index) + break; - index = nextIndex; + s->appendSubstring (concatenator, + startCharacter - index, + endCharacter - index); + } + + index = nextIndex; + } } return t; } -const String TextEditor::getHighlightedText() const throw() +const String TextEditor::getHighlightedText() const { - return getTextSubstring (getHighlightedRegionStart(), - getHighlightedRegionStart() + getHighlightedRegionLength()); + return getTextSubstring (selectionStart, selectionEnd); } -int TextEditor::getTotalNumChars() throw() +int TextEditor::getTotalNumChars() const { if (totalNumChars < 0) { @@ -2497,19 +2497,12 @@ int TextEditor::getTotalNumChars() throw() return totalNumChars; } -bool TextEditor::isEmpty() const throw() +bool TextEditor::isEmpty() const { - if (totalNumChars != 0) - { - for (int i = sections.size(); --i >= 0;) - if (((const UniformTextSection*) sections.getUnchecked(i))->getTotalLength() > 0) - return false; - } - - return true; + return getTotalNumChars() == 0; } -void TextEditor::getCharPosition (const int index, float& cx, float& cy, float& lineHeight) const throw() +void TextEditor::getCharPosition (const int index, float& cx, float& cy, float& lineHeight) const { const float wordWrapWidth = getWordWrapWidth(); @@ -2526,7 +2519,7 @@ void TextEditor::getCharPosition (const int index, float& cx, float& cy, float& } } -int TextEditor::indexAtPosition (const float x, const float y) throw() +int TextEditor::indexAtPosition (const float x, const float y) { const float wordWrapWidth = getWordWrapWidth(); @@ -2554,13 +2547,13 @@ int TextEditor::indexAtPosition (const float x, const float y) throw() } //============================================================================== -static int getCharacterCategory (const tchar character) throw() +static int getCharacterCategory (const tchar character) { return CharacterFunctions::isLetterOrDigit (character) ? 2 : (CharacterFunctions::isWhitespace (character) ? 0 : 1); } -int TextEditor::findWordBreakAfter (const int position) const throw() +int TextEditor::findWordBreakAfter (const int position) const { const String t (getTextSubstring (position, position + 512)); const int totalLength = t.length(); @@ -2580,7 +2573,7 @@ int TextEditor::findWordBreakAfter (const int position) const throw() return position + i; } -int TextEditor::findWordBreakBefore (const int position) const throw() +int TextEditor::findWordBreakBefore (const int position) const { if (position <= 0) return 0; @@ -2608,7 +2601,7 @@ int TextEditor::findWordBreakBefore (const int position) const throw() //============================================================================== void TextEditor::splitSection (const int sectionIndex, - const int charToSplitAt) throw() + const int charToSplitAt) { jassert (sections[sectionIndex] != 0); @@ -2617,7 +2610,7 @@ void TextEditor::splitSection (const int sectionIndex, ->split (charToSplitAt, passwordCharacter)); } -void TextEditor::coalesceSimilarSections() throw() +void TextEditor::coalesceSimilarSections() { for (int i = 0; i < sections.size() - 1; ++i) { diff --git a/src/gui/components/controls/juce_TextEditor.h b/src/gui/components/controls/juce_TextEditor.h index 1508d3f465..acec66ef7a 100644 --- a/src/gui/components/controls/juce_TextEditor.h +++ b/src/gui/components/controls/juce_TextEditor.h @@ -31,6 +31,7 @@ #include "../../../utilities/juce_UndoManager.h" #include "../layout/juce_Viewport.h" #include "../menus/juce_PopupMenu.h" +#include "../../../containers/juce_Value.h" class TextEditor; class TextHolderComponent; @@ -108,7 +109,7 @@ public: /** Returns true if the editor is in multi-line mode. */ - bool isMultiLine() const throw(); + bool isMultiLine() const; //============================================================================== /** Changes the behaviour of the return key. @@ -124,7 +125,7 @@ public: See setReturnKeyStartsNewLine() for more info. */ - bool getReturnKeyStartsNewLine() const throw() { return returnKeyStartsNewLine; } + bool getReturnKeyStartsNewLine() const { return returnKeyStartsNewLine; } /** Indicates whether the tab key should be accepted and used to input a tab character, or whether it gets ignored. @@ -132,12 +133,12 @@ public: By default the tab key is ignored, so that it can be used to switch keyboard focus between components. */ - void setTabKeyUsedAsCharacter (const bool shouldTabKeyBeUsed) throw(); + void setTabKeyUsedAsCharacter (const bool shouldTabKeyBeUsed); /** Returns true if the tab key is being used for input. @see setTabKeyUsedAsCharacter */ - bool isTabKeyUsedAsCharacter() const throw() { return tabKeyUsed; } + bool isTabKeyUsedAsCharacter() const { return tabKeyUsed; } //============================================================================== /** Changes the editor to read-only mode. @@ -153,7 +154,7 @@ public: /** Returns true if the editor is in read-only mode. */ - bool isReadOnly() const throw(); + bool isReadOnly() const; //============================================================================== /** Makes the caret visible or invisible. @@ -162,12 +163,12 @@ public: @see setCaretColour, setCaretPosition */ - void setCaretVisible (const bool shouldBeVisible) throw(); + void setCaretVisible (const bool shouldBeVisible); /** Returns true if the caret is enabled. @see setCaretVisible */ - bool isCaretVisible() const throw() { return caretVisible; } + bool isCaretVisible() const { return caretVisible; } //============================================================================== /** Enables/disables a vertical scrollbar. @@ -178,12 +179,12 @@ public: By default the scrollbar is enabled. */ - void setScrollbarsShown (bool shouldBeEnabled) throw(); + void setScrollbarsShown (bool shouldBeEnabled); /** Returns true if scrollbars are enabled. @see setScrollbarsShown */ - bool areScrollbarsShown() const throw() { return scrollbarVisible; } + bool areScrollbarsShown() const { return scrollbarVisible; } /** Changes the password character used to disguise the text. @@ -195,12 +196,12 @@ public: for a black splodge (not all fonts include this, though), or 0x2022, which is a bullet (probably the best choice for linux). */ - void setPasswordCharacter (const tchar passwordCharacter) throw(); + void setPasswordCharacter (const tchar passwordCharacter); /** Returns the current password character. @see setPasswordCharacter l */ - tchar getPasswordCharacter() const throw() { return passwordCharacter; } + tchar getPasswordCharacter() const { return passwordCharacter; } //============================================================================== @@ -211,16 +212,16 @@ l */ If enabled, right-clicking (or command-clicking on the Mac) will pop up a menu of options such as cut/copy/paste, undo/redo, etc. */ - void setPopupMenuEnabled (const bool menuEnabled) throw(); + void setPopupMenuEnabled (const bool menuEnabled); /** Returns true if the right-click menu is enabled. @see setPopupMenuEnabled */ - bool isPopupMenuEnabled() const throw() { return popupMenuEnabled; } + bool isPopupMenuEnabled() const { return popupMenuEnabled; } /** Returns true if a popup-menu is currently being displayed. */ - bool isPopupMenuCurrentlyActive() const throw() { return menuActive; } + bool isPopupMenuCurrentlyActive() const { return menuActive; } //============================================================================== /** A set of colour IDs to use to change the colour of various aspects of the editor. @@ -267,7 +268,7 @@ l */ @see applyFontToAllText */ - void setFont (const Font& newFont) throw(); + void setFont (const Font& newFont); /** Applies a font to all the text in the editor. @@ -281,7 +282,7 @@ l */ @see setFont */ - const Font getFont() const throw(); + const Font getFont() const; //============================================================================== /** If set to true, focusing on the editor will highlight all its text. @@ -291,7 +292,7 @@ l */ This is useful for boxes where you expect the user to re-enter all the text when they focus on the component, rather than editing what's already there. */ - void setSelectAllWhenFocused (const bool b) throw(); + void setSelectAllWhenFocused (const bool b); /** Sets limits on the characters that can be entered. @@ -301,7 +302,7 @@ l */ this string are allowed to be entered into the editor. */ void setInputRestrictions (const int maxTextLength, - const String& allowedCharacters = String::empty) throw(); + const String& allowedCharacters = String::empty); /** When the text editor is empty, it can be set to display a message. @@ -309,7 +310,7 @@ l */ string is only displayed, it's not taken to actually be the contents of the editor. */ - void setTextToShowWhenEmpty (const String& text, const Colour& colourToUse) throw(); + void setTextToShowWhenEmpty (const String& text, const Colour& colourToUse); //============================================================================== /** Changes the size of the scrollbars that are used. @@ -329,26 +330,26 @@ l */ @see removeListener */ - void addListener (TextEditorListener* const newListener) throw(); + void addListener (TextEditorListener* const newListener); /** Deregisters a listener. @see addListener */ - void removeListener (TextEditorListener* const listenerToRemove) throw(); + void removeListener (TextEditorListener* const listenerToRemove); //============================================================================== /** Returns the entire contents of the editor. */ - const String getText() const throw(); + const String getText() const; /** Returns a section of the contents of the editor. */ - const String getTextSubstring (const int startCharacter, const int endCharacter) const throw(); + const String getTextSubstring (const int startCharacter, const int endCharacter) const; /** Returns true if there are no characters in the editor. This is more efficient than calling getText().isEmpty(). */ - bool isEmpty() const throw(); + bool isEmpty() const; /** Sets the entire content of the editor. @@ -365,6 +366,14 @@ l */ void setText (const String& newText, const bool sendTextChangeMessage = true); + /** Returns a Value object that can be used to get or set the text. + + Bear in mind that this operate quite slowly if your text box contains large + amounts of text, as it needs to dynamically build the string that's involved. It's + best used for small text boxes. + */ + Value& getTextValue(); + /** Inserts some text at the current cursor position. If a section of the text is highlighted, it will be replaced by @@ -403,13 +412,13 @@ l */ @see getCaretPosition */ - void setCaretPosition (const int newIndex) throw(); + void setCaretPosition (const int newIndex); /** Returns the current index of the caret. @see setCaretPosition */ - int getCaretPosition() const throw(); + int getCaretPosition() const; /** Attempts to scroll the text editor so that the caret ends up at a specified position. @@ -423,19 +432,19 @@ l */ will go as far as it can in that direction. */ void scrollEditorToPositionCaret (const int desiredCaretX, - const int desiredCaretY) throw(); + const int desiredCaretY); /** Get the graphical position of the caret. The rectangle returned is relative to the component's top-left corner. @see scrollEditorToPositionCaret */ - const Rectangle getCaretRectangle() throw(); + const Rectangle getCaretRectangle(); /** Selects a section of the text. */ void setHighlightedRegion (int startIndex, - int numberOfCharactersToHighlight) throw(); + int numberOfCharactersToHighlight); /** Returns the first character that is selected. @@ -444,68 +453,68 @@ l */ @see setHighlightedRegion, getHighlightedRegionLength */ - int getHighlightedRegionStart() const throw() { return selectionStart; } + int getHighlightedRegionStart() const { return selectionStart; } /** Returns the number of characters that are selected. @see setHighlightedRegion, getHighlightedRegionStart */ - int getHighlightedRegionLength() const throw() { return jmax (0, selectionEnd - selectionStart); } + int getHighlightedRegionLength() const { return jmax (0, selectionEnd - selectionStart); } /** Returns the section of text that is currently selected. */ - const String getHighlightedText() const throw(); + const String getHighlightedText() const; /** Finds the index of the character at a given position. The co-ordinates are relative to the component's top-left. */ - int getTextIndexAt (const int x, const int y) throw(); + int getTextIndexAt (const int x, const int y); /** Counts the number of characters in the text. This is quicker than getting the text as a string if you just need to know the length. */ - int getTotalNumChars() throw(); + int getTotalNumChars() const; /** Returns the total width of the text, as it is currently laid-out. This may be larger than the size of the TextEditor, and can change when the TextEditor is resized or the text changes. */ - int getTextWidth() const throw(); + int getTextWidth() const; /** Returns the maximum height of the text, as it is currently laid-out. This may be larger than the size of the TextEditor, and can change when the TextEditor is resized or the text changes. */ - int getTextHeight() const throw(); + int getTextHeight() const; /** Changes the size of the gap at the top and left-edge of the editor. By default there's a gap of 4 pixels. */ - void setIndents (const int newLeftIndent, const int newTopIndent) throw(); + void setIndents (const int newLeftIndent, const int newTopIndent); /** Changes the size of border left around the edge of the component. @see getBorder */ - void setBorder (const BorderSize& border) throw(); + void setBorder (const BorderSize& border); /** Returns the size of border around the edge of the component. @see setBorder */ - const BorderSize getBorder() const throw(); + const BorderSize getBorder() const; /** Used to disable the auto-scrolling which keeps the cursor visible. If true (the default), the editor will scroll when the cursor moves offscreen. If set to false, it won't. */ - void setScrollToShowCursor (const bool shouldScrollToShowCursor) throw(); + void setScrollToShowCursor (const bool shouldScrollToShowCursor); //============================================================================== /** @internal */ @@ -580,20 +589,20 @@ protected: //============================================================================== /** Scrolls the minimum distance needed to get the caret into view. */ - void scrollToMakeSureCursorIsVisible() throw(); + void scrollToMakeSureCursorIsVisible(); /** @internal */ - void moveCaret (int newCaretPos) throw(); + void moveCaret (int newCaretPos); /** @internal */ - void moveCursorTo (const int newPosition, const bool isSelecting) throw(); + void moveCursorTo (const int newPosition, const bool isSelecting); /** Used internally to dispatch a text-change message. */ - void textChanged() throw(); + void textChanged(); /** Begins a new transaction in the UndoManager. */ - void newTransaction() throw(); + void newTransaction(); /** Used internally to trigger an undo or redo. */ void doUndoRedo (const bool isRedo); @@ -626,6 +635,7 @@ private: bool keepCursorOnScreen : 1; bool tabKeyUsed : 1; bool menuActive : 1; + bool valueTextNeedsUpdating : 1; UndoManager undoManager; float cursorX, cursorY, cursorHeight; @@ -634,11 +644,13 @@ private: int leftIndent, topIndent; unsigned int lastTransactionTime; Font currentFont; - int totalNumChars, caretPosition; + mutable int totalNumChars; + int caretPosition; VoidArray sections; String textToShowWhenEmpty; Colour colourForTextWhenEmpty; tchar passwordCharacter; + Value textValue; enum { @@ -653,43 +665,45 @@ private: friend class TextEditorInsertAction; friend class TextEditorRemoveAction; - void coalesceSimilarSections() throw(); - void splitSection (const int sectionIndex, const int charToSplitAt) throw(); + void coalesceSimilarSections(); + void splitSection (const int sectionIndex, const int charToSplitAt); - void clearInternal (UndoManager* const um) throw(); + void clearInternal (UndoManager* const um); void insert (const String& text, const int insertIndex, const Font& font, const Colour& colour, UndoManager* const um, - const int caretPositionToMoveTo) throw(); + const int caretPositionToMoveTo); void reinsert (const int insertIndex, - const VoidArray& sections) throw(); + const VoidArray& sections); void remove (const int startIndex, int endIndex, UndoManager* const um, - const int caretPositionToMoveTo) throw(); + const int caretPositionToMoveTo); void getCharPosition (const int index, float& x, float& y, - float& lineHeight) const throw(); + float& lineHeight) const; + + void updateCaretPosition(); - void updateCaretPosition() throw(); + void textWasChangedByValue(); int indexAtPosition (const float x, - const float y) throw(); + const float y); - int findWordBreakAfter (const int position) const throw(); - int findWordBreakBefore (const int position) const throw(); + int findWordBreakAfter (const int position) const; + int findWordBreakBefore (const int position) const; friend class TextHolderComponent; friend class TextEditorViewport; void drawContent (Graphics& g); - void updateTextHolderSize() throw(); - float getWordWrapWidth() const throw(); + void updateTextHolderSize(); + float getWordWrapWidth() const; void timerCallbackInt(); void repaintCaret(); void repaintText (int textStartIndex, int textEndIndex); diff --git a/src/gui/components/controls/juce_TreeView.cpp b/src/gui/components/controls/juce_TreeView.cpp index 49354691a8..af6a32916a 100644 --- a/src/gui/components/controls/juce_TreeView.cpp +++ b/src/gui/components/controls/juce_TreeView.cpp @@ -1076,9 +1076,12 @@ TreeViewItem* TreeViewContentComponent::findItemAt (int y, Rectangle& itemPositi } //============================================================================== -#define opennessDefault 0 -#define opennessClosed 1 -#define opennessOpen 2 +enum TreeViewOpenness +{ + opennessDefault = 0, + opennessClosed = 1, + opennessOpen = 2 +}; TreeViewItem::TreeViewItem() : ownerView (0), diff --git a/src/gui/components/lookandfeel/juce_LookAndFeel.cpp b/src/gui/components/lookandfeel/juce_LookAndFeel.cpp index eea832efc5..edd8fa34ec 100644 --- a/src/gui/components/lookandfeel/juce_LookAndFeel.cpp +++ b/src/gui/components/lookandfeel/juce_LookAndFeel.cpp @@ -106,9 +106,9 @@ LookAndFeel::LookAndFeel() jassert (Colours::white == Colour (0xffffffff)); // set up the standard set of colours.. - #define textButtonColour 0xffbbbbff - #define textHighlightColour 0x401111ee - #define standardOutlineColour 0xb2808080 + const int textButtonColour = 0xffbbbbff; + const int textHighlightColour = 0x401111ee; + const int standardOutlineColour = 0xb2808080; static const int standardColours[] = { diff --git a/src/gui/components/windows/juce_AlertWindow.cpp b/src/gui/components/windows/juce_AlertWindow.cpp index 1e91dea01b..45ed3fcb54 100644 --- a/src/gui/components/windows/juce_AlertWindow.cpp +++ b/src/gui/components/windows/juce_AlertWindow.cpp @@ -46,17 +46,10 @@ static const int iconWidth = 80; class AlertWindowTextEditor : public TextEditor { public: - #if JUCE_LINUX - #define PASSWORD_CHAR 0x2022 - #else - #define PASSWORD_CHAR 0x25cf - #endif - - AlertWindowTextEditor (const String& name, - const bool isPasswordBox) - : TextEditor (name, - isPasswordBox ? (const tchar) PASSWORD_CHAR - : (const tchar) 0) + static const tchar passwordChar; + + AlertWindowTextEditor (const String& name, const bool isPasswordBox) + : TextEditor (name, isPasswordBox ? passwordChar : 0) { setSelectAllWhenFocused (true); } @@ -82,6 +75,11 @@ private: const AlertWindowTextEditor& operator= (const AlertWindowTextEditor&); }; +#if JUCE_LINUX +const tchar AlertWindowTextEditor::passwordChar = 0x2022; +#else +const tchar AlertWindowTextEditor::passwordChar = 0x25cf; +#endif //============================================================================== AlertWindow::AlertWindow (const String& title, diff --git a/src/gui/graphics/fonts/juce_GlyphArrangement.cpp b/src/gui/graphics/fonts/juce_GlyphArrangement.cpp index 551d4f8a25..48b59e789e 100644 --- a/src/gui/graphics/fonts/juce_GlyphArrangement.cpp +++ b/src/gui/graphics/fonts/juce_GlyphArrangement.cpp @@ -32,8 +32,6 @@ BEGIN_JUCE_NAMESPACE #include "../imaging/juce_Image.h" #include "../../../utilities/juce_DeletedAtShutdown.h" -#define SHOULD_WRAP(x, wrapwidth) (((x) - 0.0001f) >= (wrapwidth)) - //============================================================================== PositionedGlyph::PositionedGlyph() @@ -310,7 +308,7 @@ void GlyphArrangement::addJustifiedText (const Font& font, { lastWordBreakIndex = i + 1; } - else if (SHOULD_WRAP (pg->getRight(), lineMaxX)) + else if (pg->getRight() - 0.0001f >= lineMaxX) { if (lastWordBreakIndex >= 0) i = lastWordBreakIndex; diff --git a/src/gui/graphics/imaging/image_file_formats/juce_GIFLoader.cpp b/src/gui/graphics/imaging/image_file_formats/juce_GIFLoader.cpp index af5e2ddcb4..053b22d1a9 100644 --- a/src/gui/graphics/imaging/image_file_formats/juce_GIFLoader.cpp +++ b/src/gui/graphics/imaging/image_file_formats/juce_GIFLoader.cpp @@ -33,11 +33,6 @@ BEGIN_JUCE_NAMESPACE //============================================================================== -static inline int makeWord (const unsigned char a, const unsigned char b) -{ - return (b << 8) | a; -} - GIFLoader::GIFLoader (InputStream& in) : image (0), input (in), diff --git a/src/gui/graphics/imaging/image_file_formats/juce_GIFLoader.h b/src/gui/graphics/imaging/image_file_formats/juce_GIFLoader.h index 3bc27a8d60..44415b70c2 100644 --- a/src/gui/graphics/imaging/image_file_formats/juce_GIFLoader.h +++ b/src/gui/graphics/imaging/image_file_formats/juce_GIFLoader.h @@ -69,8 +69,8 @@ private: int processExtension (int type, int& transparent); int readLZWByte (bool initialise, int input_code_size); int getCode (int code_size, bool initialise); - bool readImage (int width, int height, - int interlace, int transparent); + bool readImage (int width, int height, int interlace, int transparent); + static inline int makeWord (const uint8 a, const uint8 b) { return (b << 8) | a; } GIFLoader (const GIFLoader&); const GIFLoader& operator= (const GIFLoader&); diff --git a/src/gui/graphics/imaging/image_file_formats/juce_JPEGLoader.cpp b/src/gui/graphics/imaging/image_file_formats/juce_JPEGLoader.cpp index dbacb1b30f..cddf977561 100644 --- a/src/gui/graphics/imaging/image_file_formats/juce_JPEGLoader.cpp +++ b/src/gui/graphics/imaging/image_file_formats/juce_JPEGLoader.cpp @@ -270,7 +270,7 @@ Image* juce_loadJPEGImageFromStream (InputStream& in) //============================================================================== -static const int bufferSize = 512; +static const int jpegBufferSize = 512; struct JuceJpegDest : public jpeg_destination_mgr { @@ -286,7 +286,7 @@ static void jpegWriteTerminate (j_compress_ptr cinfo) { JuceJpegDest* const dest = (JuceJpegDest*) cinfo->dest; - const int numToWrite = bufferSize - dest->free_in_buffer; + const int numToWrite = jpegBufferSize - dest->free_in_buffer; dest->output->write (dest->buffer, numToWrite); } @@ -294,10 +294,10 @@ static boolean jpegWriteFlush (j_compress_ptr cinfo) { JuceJpegDest* const dest = (JuceJpegDest*) cinfo->dest; - const int numToWrite = bufferSize; + const int numToWrite = jpegBufferSize; dest->next_output_byte = (JOCTET*) dest->buffer; - dest->free_in_buffer = bufferSize; + dest->free_in_buffer = jpegBufferSize; return dest->output->write (dest->buffer, numToWrite); } @@ -326,10 +326,10 @@ bool juce_writeJPEGImageToStream (const Image& image, jpegCompStruct.dest = &dest; dest.output = &out; - HeapBlock tempBuffer (bufferSize); + HeapBlock tempBuffer (jpegBufferSize); dest.buffer = (char*) tempBuffer; dest.next_output_byte = (JOCTET*) dest.buffer; - dest.free_in_buffer = bufferSize; + dest.free_in_buffer = jpegBufferSize; dest.init_destination = jpegWriteInit; dest.empty_output_buffer = jpegWriteFlush; dest.term_destination = jpegWriteTerminate; diff --git a/src/io/files/juce_ZipFile.cpp b/src/io/files/juce_ZipFile.cpp index 0e47d5bdbb..9ee617a37b 100644 --- a/src/io/files/juce_ZipFile.cpp +++ b/src/io/files/juce_ZipFile.cpp @@ -77,10 +77,10 @@ public: if (inputStream != 0 && inputStream->setPosition (zei.streamOffset) && inputStream->read (buffer, 30) == 30 - && littleEndianInt (buffer) == 0x04034b50) + && ByteOrder::littleEndianInt (buffer) == 0x04034b50) { - headerSize = 30 + littleEndianShort (buffer + 26) - + littleEndianShort (buffer + 28); + headerSize = 30 + ByteOrder::littleEndianShort (buffer + 26) + + ByteOrder::littleEndianShort (buffer + 28); } } @@ -309,7 +309,7 @@ void ZipFile::init() const char* const buffer = ((const char*) headerData.getData()) + pos; - const int fileNameLen = littleEndianShort (buffer + 28); + const int fileNameLen = ByteOrder::littleEndianShort (buffer + 28); if (pos + 46 + fileNameLen > size) break; @@ -317,8 +317,8 @@ void ZipFile::init() ZipEntryInfo* const zei = new ZipEntryInfo(); zei->entry.filename = String::fromUTF8 ((const uint8*) buffer + 46, fileNameLen); - const int time = littleEndianShort (buffer + 12); - const int date = littleEndianShort (buffer + 14); + const int time = ByteOrder::littleEndianShort (buffer + 12); + const int date = ByteOrder::littleEndianShort (buffer + 14); const int year = 1980 + (date >> 9); const int month = ((date >> 5) & 15) - 1; @@ -329,16 +329,16 @@ void ZipFile::init() zei->entry.fileTime = Time (year, month, day, hours, minutes, seconds); - zei->compressed = littleEndianShort (buffer + 10) != 0; - zei->compressedSize = littleEndianInt (buffer + 20); - zei->entry.uncompressedSize = littleEndianInt (buffer + 24); + zei->compressed = ByteOrder::littleEndianShort (buffer + 10) != 0; + zei->compressedSize = ByteOrder::littleEndianInt (buffer + 20); + zei->entry.uncompressedSize = ByteOrder::littleEndianInt (buffer + 24); - zei->streamOffset = littleEndianInt (buffer + 42); + zei->streamOffset = ByteOrder::littleEndianInt (buffer + 42); entries.add (zei); pos += 46 + fileNameLen - + littleEndianShort (buffer + 30) - + littleEndianShort (buffer + 32); + + ByteOrder::littleEndianShort (buffer + 30) + + ByteOrder::littleEndianShort (buffer + 32); } } } @@ -367,13 +367,13 @@ int ZipFile::findEndOfZipEntryTable (InputStream* input) for (int i = 0; i < 22; ++i) { - if (littleEndianInt (buffer + i) == 0x06054b50) + if (ByteOrder::littleEndianInt (buffer + i) == 0x06054b50) { in.setPosition (pos + i); in.read (buffer, 22); - numEntries = littleEndianShort (buffer + 10); + numEntries = ByteOrder::littleEndianShort (buffer + 10); - return littleEndianInt (buffer + 16); + return ByteOrder::littleEndianInt (buffer + 16); } } } diff --git a/src/io/streams/juce_InputStream.cpp b/src/io/streams/juce_InputStream.cpp index 5b2dca6f70..87a743b6e2 100644 --- a/src/io/streams/juce_InputStream.cpp +++ b/src/io/streams/juce_InputStream.cpp @@ -49,7 +49,7 @@ short InputStream::readShort() char temp [2]; if (read (temp, 2) == 2) - return (short) littleEndianShort (temp); + return (short) ByteOrder::littleEndianShort (temp); else return 0; } @@ -59,7 +59,7 @@ short InputStream::readShortBigEndian() char temp [2]; if (read (temp, 2) == 2) - return (short) bigEndianShort (temp); + return (short) ByteOrder::bigEndianShort (temp); else return 0; } @@ -69,7 +69,7 @@ int InputStream::readInt() char temp [4]; if (read (temp, 4) == 4) - return (int) littleEndianInt (temp); + return (int) ByteOrder::littleEndianInt (temp); else return 0; } @@ -79,7 +79,7 @@ int InputStream::readIntBigEndian() char temp [4]; if (read (temp, 4) == 4) - return (int) bigEndianInt (temp); + return (int) ByteOrder::bigEndianInt (temp); else return 0; } @@ -102,7 +102,7 @@ int InputStream::readCompressedInt() if (read (bytes, numBytes) != numBytes) return 0; - const int num = (int) littleEndianInt (bytes); + const int num = (int) ByteOrder::littleEndianInt (bytes); return (sizeByte >> 7) ? -num : num; } @@ -111,7 +111,7 @@ int64 InputStream::readInt64() char temp [8]; if (read (temp, 8) == 8) - return (int64) swapIfBigEndian (*(uint64*) temp); + return (int64) ByteOrder::swapIfBigEndian (*(uint64*) temp); else return 0; } @@ -121,7 +121,7 @@ int64 InputStream::readInt64BigEndian() char temp [8]; if (read (temp, 8) == 8) - return (int64) swapIfLittleEndian (*(uint64*) temp); + return (int64) ByteOrder::swapIfLittleEndian (*(uint64*) temp); else return 0; } diff --git a/src/io/streams/juce_OutputStream.cpp b/src/io/streams/juce_OutputStream.cpp index 1140d527a9..fd019fc7c3 100644 --- a/src/io/streams/juce_OutputStream.cpp +++ b/src/io/streams/juce_OutputStream.cpp @@ -83,25 +83,25 @@ void OutputStream::writeByte (char byte) void OutputStream::writeShort (short value) { - const unsigned short v = swapIfBigEndian ((unsigned short) value); + const unsigned short v = ByteOrder::swapIfBigEndian ((unsigned short) value); write (&v, 2); } void OutputStream::writeShortBigEndian (short value) { - const unsigned short v = swapIfLittleEndian ((unsigned short) value); + const unsigned short v = ByteOrder::swapIfLittleEndian ((unsigned short) value); write (&v, 2); } void OutputStream::writeInt (int value) { - const unsigned int v = swapIfBigEndian ((unsigned int) value); + const unsigned int v = ByteOrder::swapIfBigEndian ((unsigned int) value); write (&v, 4); } void OutputStream::writeIntBigEndian (int value) { - const unsigned int v = swapIfLittleEndian ((unsigned int) value); + const unsigned int v = ByteOrder::swapIfLittleEndian ((unsigned int) value); write (&v, 4); } @@ -129,13 +129,13 @@ void OutputStream::writeCompressedInt (int value) void OutputStream::writeInt64 (int64 value) { - const uint64 v = swapIfBigEndian ((uint64) value); + const uint64 v = ByteOrder::swapIfBigEndian ((uint64) value); write (&v, 8); } void OutputStream::writeInt64BigEndian (int64 value) { - const uint64 v = swapIfLittleEndian ((uint64) value); + const uint64 v = ByteOrder::swapIfLittleEndian ((uint64) value); write (&v, 8); } diff --git a/src/juce_core_includes.h b/src/juce_core_includes.h index 8616afe5c2..bd5d7610a3 100644 --- a/src/juce_core_includes.h +++ b/src/juce_core_includes.h @@ -80,8 +80,8 @@ #ifndef __JUCE_ATOMIC_JUCEHEADER__ #include "core/juce_Atomic.h" #endif -#ifndef __JUCE_DATACONVERSIONS_JUCEHEADER__ - #include "core/juce_DataConversions.h" +#ifndef __JUCE_BYTEORDER_JUCEHEADER__ + #include "core/juce_ByteOrder.h" #endif #ifndef __JUCE_FILELOGGER_JUCEHEADER__ #include "core/juce_FileLogger.h" diff --git a/src/native/linux/juce_linux_Files.cpp b/src/native/linux/juce_linux_Files.cpp index 925f09312e..f2914a0c83 100644 --- a/src/native/linux/juce_linux_Files.cpp +++ b/src/native/linux/juce_linux_Files.cpp @@ -413,7 +413,7 @@ void juce_findFileClose (void* handle) bool juce_launchFile (const String& fileName, const String& parameters) { - String cmdString (fileName); + String cmdString (fileName.replace (T(" "), T("\\ "),false)); cmdString << " " << parameters; if (URL::isProbablyAWebsiteURL (fileName) diff --git a/src/native/linux/juce_linux_SystemStats.cpp b/src/native/linux/juce_linux_SystemStats.cpp index c4498ba155..977d191c4a 100644 --- a/src/native/linux/juce_linux_SystemStats.cpp +++ b/src/native/linux/juce_linux_SystemStats.cpp @@ -28,32 +28,6 @@ #if JUCE_INCLUDED_FILE -//============================================================================== -/*static juce_noinline unsigned int getCPUIDWord (int* familyModel, int* extFeatures) throw() -{ - unsigned int cpu = 0; - unsigned int ext = 0; - unsigned int family = 0; - unsigned int dummy = 0; - -#if JUCE_64BIT - __asm__ ("cpuid" - : "=a" (family), "=b" (ext), "=c" (dummy), "=d" (cpu) : "a" (1)); - -#else - __asm__ ("push %%ebx; cpuid; mov %%ebx, %%edi; pop %%ebx" - : "=a" (family), "=D" (ext), "=c" (dummy), "=d" (cpu) : "a" (1)); -#endif - - if (familyModel != 0) - *familyModel = family; - - if (extFeatures != 0) - *extFeatures = ext; - - return cpu; -}*/ - //============================================================================== void Logger::outputDebugString (const String& text) throw() { diff --git a/src/native/linux/juce_linux_Threads.cpp b/src/native/linux/juce_linux_Threads.cpp index 31cb2a487d..df365d6a3e 100644 --- a/src/native/linux/juce_linux_Threads.cpp +++ b/src/native/linux/juce_linux_Threads.cpp @@ -188,7 +188,7 @@ void Process::terminate() exit (0); } -bool JUCE_CALLTYPE juce_isRunningUnderDebugger() +bool JUCE_PUBLIC_FUNCTION juce_isRunningUnderDebugger() { static char testResult = 0; diff --git a/src/native/mac/juce_mac_Debugging.mm b/src/native/mac/juce_mac_Debugging.mm index cb15246d8a..92de817482 100644 --- a/src/native/mac/juce_mac_Debugging.mm +++ b/src/native/mac/juce_mac_Debugging.mm @@ -43,7 +43,7 @@ void Logger::outputDebugPrintf (const tchar* format, ...) throw() outputDebugString (text); } -bool JUCE_CALLTYPE juce_isRunningUnderDebugger() +bool JUCE_PUBLIC_FUNCTION juce_isRunningUnderDebugger() { static char testResult = 0; diff --git a/src/native/windows/juce_win32_ASIO.cpp b/src/native/windows/juce_win32_ASIO.cpp index 3328ef850e..659a01bd89 100644 --- a/src/native/windows/juce_win32_ASIO.cpp +++ b/src/native/windows/juce_win32_ASIO.cpp @@ -1466,7 +1466,7 @@ private: { while (--numSamples >= 0) { - *dest++ = (float) (g * (short) littleEndianShort (src)); + *dest++ = (float) (g * (short) ByteOrder::littleEndianShort (src)); src += srcStrideBytes; } } @@ -1474,7 +1474,7 @@ private: { while (--numSamples >= 0) { - *dest++ = (float) (g * (short) bigEndianShort (src)); + *dest++ = (float) (g * (short) ByteOrder::bigEndianShort (src)); src += srcStrideBytes; } } @@ -1492,7 +1492,7 @@ private: { while (--numSamples >= 0) { - *(uint16*) dest = swapIfBigEndian ((uint16) (short) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * *src++))); + *(uint16*) dest = ByteOrder::swapIfBigEndian ((uint16) (short) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * *src++))); dest += dstStrideBytes; } } @@ -1500,7 +1500,7 @@ private: { while (--numSamples >= 0) { - *(uint16*) dest = swapIfLittleEndian ((uint16) (short) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * *src++))); + *(uint16*) dest = ByteOrder::swapIfLittleEndian ((uint16) (short) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * *src++))); dest += dstStrideBytes; } } @@ -1518,7 +1518,7 @@ private: { while (--numSamples >= 0) { - *dest++ = (float) (g * littleEndian24Bit (src)); + *dest++ = (float) (g * ByteOrder::littleEndian24Bit (src)); src += srcStrideBytes; } } @@ -1526,7 +1526,7 @@ private: { while (--numSamples >= 0) { - *dest++ = (float) (g * bigEndian24Bit (src)); + *dest++ = (float) (g * ByteOrder::bigEndian24Bit (src)); src += srcStrideBytes; } } @@ -1544,7 +1544,7 @@ private: { while (--numSamples >= 0) { - littleEndian24BitToChars ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * *src++)), dest); + ByteOrder::littleEndian24BitToChars ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * *src++)), dest); dest += dstStrideBytes; } } @@ -1552,7 +1552,7 @@ private: { while (--numSamples >= 0) { - bigEndian24BitToChars ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * *src++)), dest); + ByteOrder::bigEndian24BitToChars ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * *src++)), dest); dest += dstStrideBytes; } } @@ -1570,7 +1570,7 @@ private: { while (--numSamples >= 0) { - *dest++ = (float) (g * (int) littleEndianInt (src)); + *dest++ = (float) (g * (int) ByteOrder::littleEndianInt (src)); src += srcStrideBytes; } } @@ -1578,7 +1578,7 @@ private: { while (--numSamples >= 0) { - *dest++ = (float) (g * (int) bigEndianInt (src)); + *dest++ = (float) (g * (int) ByteOrder::bigEndianInt (src)); src += srcStrideBytes; } } @@ -1596,7 +1596,7 @@ private: { while (--numSamples >= 0) { - *(uint32*) dest = swapIfBigEndian ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * *src++))); + *(uint32*) dest = ByteOrder::swap ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * *src++))); dest += dstStrideBytes; } } @@ -1604,7 +1604,7 @@ private: { while (--numSamples >= 0) { - *(uint32*) dest = swapIfLittleEndian ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * *src++))); + *(uint32*) dest = ByteOrder::swap ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * *src++))); dest += dstStrideBytes; } } diff --git a/src/native/windows/juce_win32_Network.cpp b/src/native/windows/juce_win32_Network.cpp index 72ecbf1bdd..b671c0b1bd 100644 --- a/src/native/windows/juce_win32_Network.cpp +++ b/src/native/windows/juce_win32_Network.cpp @@ -276,7 +276,7 @@ static int getMACAddressViaGetAdaptersInfo (int64* addresses, int maxNum, const mac = (mac << 8) | adapter->Address[i]; if (littleEndian) - mac = (int64) swapByteOrder ((uint64) mac); + mac = (int64) ByteOrder::swap ((uint64) mac); if (numFound < maxNum && mac != 0) addresses [numFound++] = mac; diff --git a/src/native/windows/juce_win32_SystemStats.cpp b/src/native/windows/juce_win32_SystemStats.cpp index 7c51f81cfc..ff4bea5ce0 100644 --- a/src/native/windows/juce_win32_SystemStats.cpp +++ b/src/native/windows/juce_win32_SystemStats.cpp @@ -59,20 +59,6 @@ static double hiResTicksScaleFactor; #pragma intrinsic (__cpuid) #pragma intrinsic (__rdtsc) -/*static unsigned int getCPUIDWord (int* familyModel = 0, int* extFeatures = 0) throw() -{ - int info [4]; - __cpuid (info, 1); - - if (familyModel != 0) - *familyModel = info [0]; - - if (extFeatures != 0) - *extFeatures = info[1]; - - return info[3]; -}*/ - const String SystemStats::getCpuVendor() throw() { int info [4]; @@ -91,50 +77,6 @@ const String SystemStats::getCpuVendor() throw() //============================================================================== // CPU info functions using old fashioned inline asm... -/*static juce_noinline unsigned int getCPUIDWord (int* familyModel = 0, int* extFeatures = 0) -{ - unsigned int cpu = 0; - unsigned int ext = 0; - unsigned int family = 0; - - #if JUCE_GCC - unsigned int dummy = 0; - #endif - - #ifndef __MINGW32__ - __try - #endif - { - #if JUCE_GCC - __asm__ ("cpuid" : "=a" (family), "=b" (ext), "=c" (dummy),"=d" (cpu) : "a" (1)); - #else - __asm - { - mov eax, 1 - cpuid - mov cpu, edx - mov family, eax - mov ext, ebx - } - - #endif - } - #ifndef __MINGW32__ - __except (EXCEPTION_EXECUTE_HANDLER) - { - return 0; - } - #endif - - if (familyModel != 0) - *familyModel = family; - - if (extFeatures != 0) - *extFeatures = ext; - - return cpu; -}*/ - static void juce_getCpuVendor (char* const v) { int vendor[4]; diff --git a/src/native/windows/juce_win32_Threads.cpp b/src/native/windows/juce_win32_Threads.cpp index 66eff18e7a..fbb787437c 100644 --- a/src/native/windows/juce_win32_Threads.cpp +++ b/src/native/windows/juce_win32_Threads.cpp @@ -277,7 +277,7 @@ void Process::setPriority (ProcessPriority prior) } } -bool JUCE_API JUCE_CALLTYPE juce_isRunningUnderDebugger() +bool JUCE_PUBLIC_FUNCTION juce_isRunningUnderDebugger() { return IsDebuggerPresent() != FALSE; } diff --git a/src/text/juce_String.cpp b/src/text/juce_String.cpp index a41b8cf453..67883c6798 100644 --- a/src/text/juce_String.cpp +++ b/src/text/juce_String.cpp @@ -58,7 +58,7 @@ void juce_initialiseStrings() //============================================================================== void String::deleteInternal() throw() { - if (atomicDecrementAndReturn (text->refCount) == 0) + if (Atomic::decrementAndReturn (text->refCount) == 0) juce_free (text); } @@ -105,7 +105,7 @@ void String::appendInternal (const tchar* const newText, InternalRefCountedStringHolder* const old = text; text = newTextHolder; - if (atomicDecrementAndReturn (old->refCount) == 0) + if (Atomic::decrementAndReturn (old->refCount) == 0) juce_free (old); } else @@ -145,7 +145,7 @@ void String::dupeInternalIfMultiplyReferenced() throw() text = newTextHolder; - if (atomicDecrementAndReturn (old->refCount) == 0) + if (Atomic::decrementAndReturn (old->refCount) == 0) juce_free (old); } } @@ -163,7 +163,7 @@ String::String() throw() String::String (const String& other) throw() : text (other.text) { - atomicIncrement (text->refCount); + Atomic::increment (text->refCount); } String::String (const int numChars, @@ -461,7 +461,7 @@ String::~String() throw() { emptyString.refCount = safeEmptyStringRefCount; - if (atomicDecrementAndReturn (text->refCount) == 0) + if (Atomic::decrementAndReturn (text->refCount) == 0) juce_free (text); } @@ -625,9 +625,9 @@ const String& String::operator= (const String& other) throw() { if (this != &other) { - atomicIncrement (other.text->refCount); + Atomic::increment (other.text->refCount); - if (atomicDecrementAndReturn (text->refCount) == 0) + if (Atomic::decrementAndReturn (text->refCount) == 0) juce_free (text); text = other.text; @@ -2087,12 +2087,12 @@ const String String::createStringFromData (const void* const data_, if (bigEndian) { for (int i = 0; i < numChars; ++i) - dst[i] = (tchar) swapIfLittleEndian (src[i]); + dst[i] = (tchar) ByteOrder::swapIfLittleEndian (src[i]); } else { for (int i = 0; i < numChars; ++i) - dst[i] = (tchar) swapIfBigEndian (src[i]); + dst[i] = (tchar) ByteOrder::swapIfBigEndian (src[i]); } dst [numChars] = 0; @@ -2276,5 +2276,28 @@ const String String::fromUTF8 (const uint8* const buffer, int bufferSizeBytes) t return result; } +//============================================================================== +String::Concatenator::Concatenator (String& stringToAppendTo) + : result (stringToAppendTo), + nextIndex (stringToAppendTo.length()) +{ +} + +String::Concatenator::~Concatenator() +{ +} + +void String::Concatenator::append (const String& s) +{ + const int len = s.length(); + + if (len > 0) + { + result.preallocateStorage (nextIndex + len); + s.copyToBuffer (const_cast ((const tchar*) result) + nextIndex, len); + nextIndex += len; + } +} + END_JUCE_NAMESPACE diff --git a/src/text/juce_String.h b/src/text/juce_String.h index 8246264640..488cb0427d 100644 --- a/src/text/juce_String.h +++ b/src/text/juce_String.h @@ -1067,6 +1067,31 @@ public: */ void preallocateStorage (const int numCharsNeeded) throw(); + //============================================================================== + /** A helper class to improve performance when concatenating many large strings + together. + + Because appending one string to another involves measuring the length of + both strings, repeatedly doing this for many long strings will become + an exponentially slow operation. This class uses some internal state to + avoid that, so that each append operation only needs to measure the length + of the appended string. + */ + class JUCE_API Concatenator + { + public: + Concatenator (String& stringToAppendTo); + ~Concatenator(); + + void append (const String& s); + + private: + String& result; + int nextIndex; + + Concatenator (const Concatenator&); + const Concatenator& operator= (const Concatenator&); + }; //============================================================================== juce_UseDebuggingNewOperator // (adds debugging info to find leaked objects) diff --git a/src/text/juce_XmlDocument.cpp b/src/text/juce_XmlDocument.cpp index 8cb8548cbb..294a88f51e 100644 --- a/src/text/juce_XmlDocument.cpp +++ b/src/text/juce_XmlDocument.cpp @@ -31,20 +31,6 @@ BEGIN_JUCE_NAMESPACE #include "../io/streams/juce_FileInputSource.h" -//============================================================================== -static bool isXmlIdentifierChar_Slow (const tchar c) throw() -{ - return CharacterFunctions::isLetterOrDigit (c) - || c == T('_') - || c == T('-') - || c == T(':') - || c == T('.'); -} - -#define isXmlIdentifierChar(c) \ - ((c > 0 && c <= 127) ? identifierLookupTable [(int) c] : isXmlIdentifierChar_Slow (c)) - - //============================================================================== XmlDocument::XmlDocument (const String& documentText) throw() : originalText (documentText), @@ -71,6 +57,21 @@ void XmlDocument::setEmptyTextElementsIgnored (const bool shouldBeIgnored) throw ignoreEmptyTextElements = shouldBeIgnored; } +bool XmlDocument::isXmlIdentifierCharSlow (const tchar c) throw() +{ + return CharacterFunctions::isLetterOrDigit (c) + || c == T('_') + || c == T('-') + || c == T(':') + || c == T('.'); +} + +inline bool XmlDocument::isXmlIdentifierChar (const tchar c) const throw() +{ + return (c > 0 && c <= 127) ? identifierLookupTable [(int) c] + : isXmlIdentifierCharSlow (c); +} + XmlElement* XmlDocument::getDocumentElement (const bool onlyReadOuterDocumentElement) { String textToParse (originalText); @@ -108,7 +109,7 @@ XmlElement* XmlDocument::getDocumentElement (const bool onlyReadOuterDocumentEle needToLoadDTD = true; for (int i = 0; i < 128; ++i) - identifierLookupTable[i] = isXmlIdentifierChar_Slow ((tchar) i); + identifierLookupTable[i] = isXmlIdentifierCharSlow ((tchar) i); if (textToParse.isEmpty()) { diff --git a/src/text/juce_XmlDocument.h b/src/text/juce_XmlDocument.h index 1fc629f636..108f104a17 100644 --- a/src/text/juce_XmlDocument.h +++ b/src/text/juce_XmlDocument.h @@ -148,6 +148,8 @@ private: int findNextTokenLength() throw(); void readQuotedString (String& result) throw(); void readEntity (String& result) throw(); + static bool isXmlIdentifierCharSlow (const tchar c) throw(); + bool isXmlIdentifierChar (const tchar c) const throw(); const String getFileContents (const String& filename) const; const String expandEntity (const String& entity); diff --git a/src/text/juce_XmlElement.cpp b/src/text/juce_XmlElement.cpp index 7b54972966..65c90012fa 100644 --- a/src/text/juce_XmlElement.cpp +++ b/src/text/juce_XmlElement.cpp @@ -1130,12 +1130,13 @@ void XmlElement::setText (const String& newText) throw() const String XmlElement::getAllSubText() const throw() { String result; + String::Concatenator concatenator (result); const XmlElement* child = firstChildElement; while (child != 0) { if (child->isTextElement()) - result += child->getText(); + concatenator.append (child->getText()); child = child->nextElement; } diff --git a/src/utilities/juce_PropertiesFile.cpp b/src/utilities/juce_PropertiesFile.cpp index be43579904..bd4a840f2b 100644 --- a/src/utilities/juce_PropertiesFile.cpp +++ b/src/utilities/juce_PropertiesFile.cpp @@ -40,8 +40,8 @@ BEGIN_JUCE_NAMESPACE //============================================================================== -static const int propFileMagicNumber = ((int) littleEndianInt ("PROP")); -static const int propFileMagicNumberCompressed = ((int) littleEndianInt ("CPRP")); +static const int propFileMagicNumber = ((int) ByteOrder::littleEndianInt ("PROP")); +static const int propFileMagicNumberCompressed = ((int) ByteOrder::littleEndianInt ("CPRP")); static const tchar* const propertyFileXmlTag = T("PROPERTIES"); static const tchar* const propertyTagName = T("VALUE");