| @@ -40,7 +40,7 @@ static int CALLBACK wfontEnum2 (ENUMLOGFONTEXW* lpelfe, | |||
| int type, | |||
| LPARAM lParam) | |||
| { | |||
| if (lpelfe != 0 && type == TRUETYPE_FONTTYPE) | |||
| if (lpelfe != 0 && (type & RASTER_FONTTYPE) == 0) | |||
| { | |||
| const String fontName (lpelfe->elfLogFont.lfFaceName); | |||
| @@ -55,8 +55,7 @@ static int CALLBACK wfontEnum1 (ENUMLOGFONTEXW* lpelfe, | |||
| int type, | |||
| LPARAM lParam) | |||
| { | |||
| if (lpelfe != 0 | |||
| && ((type & (DEVICE_FONTTYPE | RASTER_FONTTYPE)) == 0)) | |||
| if (lpelfe != 0 && (type & RASTER_FONTTYPE) == 0) | |||
| { | |||
| LOGFONTW lf; | |||
| zerostruct (lf); | |||
| @@ -55,7 +55,7 @@ | |||
| //============================================================================== | |||
| #define juceFilterObjectPropertyID 0x1a45ffe9 | |||
| static VoidArray activePlugins; | |||
| static VoidArray activePlugins, activeUIs; | |||
| static const short channelConfigs[][2] = { JucePlugin_PreferredChannelConfigurations }; | |||
| static const int numChannelConfigs = numElementsInArray (channelConfigs); | |||
| @@ -108,7 +108,7 @@ public: | |||
| channels (0), | |||
| prepared (false) | |||
| { | |||
| if (activePlugins.size() == 0) | |||
| if (activePlugins.size() + activeUIs.size() == 0) | |||
| { | |||
| #if BUILD_AU_CARBON_UI | |||
| NSApplicationLoad(); | |||
| @@ -143,7 +143,7 @@ public: | |||
| jassert (activePlugins.contains (this)); | |||
| activePlugins.removeValue (this); | |||
| if (activePlugins.size() == 0) | |||
| if (activePlugins.size() + activeUIs.size() == 0) | |||
| shutdownJuce_GUI(); | |||
| } | |||
| @@ -993,6 +993,8 @@ public: | |||
| [self setHidden: NO]; | |||
| [self setPostsFrameChangedNotifications: YES]; | |||
| activeUIs.add (self); | |||
| editorComp->addToDesktop (0, (void*) self); | |||
| editorComp->setVisible (true); | |||
| @@ -1005,10 +1007,19 @@ public: | |||
| // is trying to delete our plugin.. | |||
| jassert (Component::getCurrentlyModalComponent() == 0); | |||
| if (editorComp != 0 && editorComp->getChildComponent(0) != 0) | |||
| filter->editorBeingDeleted ((AudioProcessorEditor*) editorComp->getChildComponent(0)); | |||
| if (editorComp != 0 && editorComp->isValidComponent()) | |||
| { | |||
| if (editorComp->getChildComponent(0) != 0) | |||
| if (activePlugins.contains ((void*) filter)) // plugin may have been deleted before the UI | |||
| filter->editorBeingDeleted ((AudioProcessorEditor*) editorComp->getChildComponent(0)); | |||
| deleteAndZero (editorComp); | |||
| } | |||
| deleteAndZero (editorComp); | |||
| jassert (activeUIs.contains (self)); | |||
| activeUIs.removeValue (self); | |||
| if (activePlugins.size() + activeUIs.size() == 0) | |||
| shutdownJuce_GUI(); | |||
| [super dealloc]; | |||
| } | |||
| @@ -221,9 +221,13 @@ class SharedMessageThread : public Thread | |||
| { | |||
| public: | |||
| SharedMessageThread() | |||
| : Thread (T("VstMessageThread")) | |||
| : Thread (T("VstMessageThread")), | |||
| initialised (false) | |||
| { | |||
| startThread (7); | |||
| while (! initialised) | |||
| sleep (1); | |||
| } | |||
| ~SharedMessageThread() | |||
| @@ -241,6 +245,9 @@ public: | |||
| const Thread::ThreadID originalThreadId = messageManager->getCurrentMessageThread(); | |||
| messageManager->setCurrentMessageThread (Thread::getCurrentThreadId()); | |||
| initialiseJuce_GUI(); | |||
| initialised = true; | |||
| while ((! threadShouldExit()) && messageManager->runDispatchLoopUntil (250)) | |||
| { | |||
| } | |||
| @@ -249,8 +256,12 @@ public: | |||
| } | |||
| juce_DeclareSingleton (SharedMessageThread, false) | |||
| private: | |||
| bool initialised; | |||
| }; | |||
| juce_ImplementSingleton (SharedMessageThread) | |||
| #endif | |||
| @@ -446,6 +457,7 @@ public: | |||
| { | |||
| if (editorComp == 0) | |||
| { | |||
| const MessageManagerLock mmLock; | |||
| AudioProcessorEditor* const ed = filter->createEditorIfNeeded(); | |||
| if (ed != 0) | |||
| @@ -462,6 +474,7 @@ public: | |||
| void close() | |||
| { | |||
| const MessageManagerLock mmLock; | |||
| jassert (! recursionCheck); | |||
| stopTimer(); | |||
| @@ -1179,6 +1192,7 @@ public: | |||
| if (canDeleteLaterIfModal) | |||
| { | |||
| shouldDeleteEditor = true; | |||
| recursionCheck = false; | |||
| return; | |||
| } | |||
| } | |||
| @@ -1219,6 +1233,7 @@ public: | |||
| } | |||
| else if (opCode == effEditOpen) | |||
| { | |||
| const MessageManagerLock mmLock; | |||
| jassert (! recursionCheck); | |||
| deleteEditor (true); | |||
| @@ -1253,11 +1268,13 @@ public: | |||
| } | |||
| else if (opCode == effEditClose) | |||
| { | |||
| const MessageManagerLock mmLock; | |||
| deleteEditor (true); | |||
| return 0; | |||
| } | |||
| else if (opCode == effEditGetRect) | |||
| { | |||
| const MessageManagerLock mmLock; | |||
| createEditorComp(); | |||
| if (editorComp != 0) | |||
| @@ -1490,7 +1507,6 @@ extern "C" __attribute__ ((visibility("default"))) AEffect* main_macho (audioMas | |||
| extern "C" AEffect* VSTPluginMain (audioMasterCallback audioMaster) | |||
| { | |||
| initialiseJuce_GUI(); | |||
| SharedMessageThread::getInstance(); | |||
| return pluginEntryPoint (audioMaster); | |||
| @@ -447,7 +447,7 @@ public: | |||
| { | |||
| return [[v className] isEqualToString: @"WebNetscapePluginDocumentView"] | |||
| || [[v className] isEqualToString: @"WebPluginDocumentView"] | |||
| || [[v className] isEqualToString: @"ChildView"]; | |||
| || ([[v className] isEqualToString: @"ChildView"] && ([v frame].origin.x != 0 && [v frame].origin.y != 0)); | |||
| } | |||
| void setWindow (NPWindow* window) | |||
| @@ -7965,6 +7965,73 @@ bool URL::isWellFormed() const | |||
| return url.isNotEmpty(); | |||
| } | |||
| static int findStartOfDomain (const String& url) | |||
| { | |||
| int i = 0; | |||
| while (CharacterFunctions::isLetterOrDigit (url[i]) | |||
| || CharacterFunctions::indexOfChar (T("+-."), url[i], false) >= 0) | |||
| ++i; | |||
| return url[i] == T(':') ? i + 1 : 0; | |||
| } | |||
| const String URL::getDomain() const | |||
| { | |||
| int start = findStartOfDomain (url); | |||
| while (url[start] == T('/')) | |||
| ++start; | |||
| const int end1 = url.indexOfChar (start, T('/')); | |||
| const int end2 = url.indexOfChar (start, T(':')); | |||
| const int end = (end1 < 0 || end2 < 0) ? jmax (end1, end2) | |||
| : jmin (end1, end2); | |||
| return url.substring (start, end); | |||
| } | |||
| const String URL::getSubPath() const | |||
| { | |||
| int start = findStartOfDomain (url); | |||
| while (url[start] == T('/')) | |||
| ++start; | |||
| const int startOfPath = url.indexOfChar (start, T('/')) + 1; | |||
| return startOfPath <= 0 ? String::empty | |||
| : url.substring (startOfPath); | |||
| } | |||
| const String URL::getScheme() const | |||
| { | |||
| return url.substring (0, findStartOfDomain (url) - 1); | |||
| } | |||
| const URL URL::withNewSubPath (const String& newPath) const | |||
| { | |||
| int start = findStartOfDomain (url); | |||
| while (url[start] == T('/')) | |||
| ++start; | |||
| const int startOfPath = url.indexOfChar (start, T('/')) + 1; | |||
| URL u (*this); | |||
| if (startOfPath > 0) | |||
| u.url = url.substring (0, startOfPath); | |||
| if (! u.url.endsWithChar (T('/'))) | |||
| u.url << '/'; | |||
| if (newPath.startsWithChar (T('/'))) | |||
| u.url << newPath.substring (1); | |||
| else | |||
| u.url << newPath; | |||
| return u; | |||
| } | |||
| bool URL::isProbablyAWebsiteURL (const String& possibleURL) | |||
| { | |||
| if (possibleURL.startsWithIgnoreCase (T("http:")) | |||
| @@ -52504,7 +52571,7 @@ public: | |||
| if (buttonUnderMouse != newItem) | |||
| { | |||
| if (buttonUnderMouse != 0) | |||
| if (buttonUnderMouse != 0 && containsItem (buttonUnderMouse)) | |||
| { | |||
| const Rectangle r (buttonUnderMouse->getItemPosition (false)); | |||
| repaint (0, r.getY(), r.getX(), buttonUnderMouse->getItemHeight()); | |||
| @@ -52588,6 +52655,15 @@ private: | |||
| item->setSelected ((! cmd) || (! item->isSelected()), ! cmd); | |||
| } | |||
| } | |||
| bool containsItem (TreeViewItem* const item) const | |||
| { | |||
| for (int i = rowComponentItems.size(); --i >= 0;) | |||
| if ((TreeViewItem*) rowComponentItems.getUnchecked (i) == item) | |||
| return true; | |||
| return false; | |||
| } | |||
| }; | |||
| class TreeViewport : public Viewport | |||
| @@ -61074,10 +61150,15 @@ void LookAndFeel::drawButtonBackground (Graphics& g, | |||
| button.isConnectedOnBottom()); | |||
| } | |||
| const Font LookAndFeel::getFontForTextButton (TextButton& button) | |||
| { | |||
| return button.getFont(); | |||
| } | |||
| void LookAndFeel::drawButtonText (Graphics& g, TextButton& button, | |||
| bool /*isMouseOverButton*/, bool /*isButtonDown*/) | |||
| { | |||
| g.setFont (button.getFont()); | |||
| g.setFont (getFontForTextButton (button)); | |||
| g.setColour (button.findColour (TextButton::textColourId) | |||
| .withMultipliedAlpha (button.isEnabled() ? 1.0f : 0.5f)); | |||
| @@ -70772,7 +70853,8 @@ MagnifierComponent::MagnifierComponent (Component* const content_, | |||
| : content (content_), | |||
| scaleFactor (0.0), | |||
| peer (0), | |||
| deleteContent (deleteContentCompWhenNoLongerNeeded) | |||
| deleteContent (deleteContentCompWhenNoLongerNeeded), | |||
| quality (Graphics::lowResamplingQuality) | |||
| { | |||
| holderComp = new PeerHolderComp (this); | |||
| setScaleFactor (1.0); | |||
| @@ -70844,7 +70926,7 @@ void MagnifierComponent::paint (Graphics& g) | |||
| g2.reduceClipRegion (srcX, srcY, srcW, srcH); | |||
| holderComp->paintEntireComponent (g2); | |||
| g.setImageResamplingQuality (Graphics::lowResamplingQuality); | |||
| g.setImageResamplingQuality (quality); | |||
| g.drawImage (&temp, | |||
| 0, 0, (int) (w * scaleFactor), (int) (h * scaleFactor), | |||
| 0, 0, w, h, | |||
| @@ -72256,6 +72338,9 @@ AlertWindow::AlertWindow (const String& title, | |||
| } | |||
| } | |||
| if (JUCEApplication::getInstance() == 0) | |||
| setAlwaysOnTop (true); // for a plugin, make it always-on-top because the host windows are often top-level | |||
| lookAndFeelChanged(); | |||
| constrainer.setMinimumOnscreenAmounts (0x10000, 0x10000, 0x10000, 0x10000); | |||
| @@ -76602,6 +76687,7 @@ void EdgeTable::addEdgePoint (const int x, const int y, const int winding) throw | |||
| if (n >= maxEdgesPerLine) | |||
| { | |||
| remapTableForNumEdges (maxEdgesPerLine + juce_edgeTableDefaultEdgesPerLine); | |||
| jassert (n < maxEdgesPerLine); | |||
| lineStart = table + lineStrideElements * y; | |||
| } | |||
| @@ -80551,11 +80637,9 @@ const AffineTransform RectanglePlacement::getTransformToFit (float x, float y, | |||
| const float scaleY = dh / h; | |||
| if ((flags & stretchToFit) != 0) | |||
| { | |||
| return AffineTransform::translation (-x, -y) | |||
| .scaled (scaleX, scaleY) | |||
| .translated (dx - x, dy - y); | |||
| } | |||
| .translated (dx, dy); | |||
| float scale = (flags & fillDestination) != 0 ? jmax (scaleX, scaleY) | |||
| : jmin (scaleX, scaleY); | |||
| @@ -246621,7 +246705,7 @@ static int CALLBACK wfontEnum2 (ENUMLOGFONTEXW* lpelfe, | |||
| int type, | |||
| LPARAM lParam) | |||
| { | |||
| if (lpelfe != 0 && type == TRUETYPE_FONTTYPE) | |||
| if (lpelfe != 0 && (type & RASTER_FONTTYPE) == 0) | |||
| { | |||
| const String fontName (lpelfe->elfLogFont.lfFaceName); | |||
| @@ -246636,8 +246720,7 @@ static int CALLBACK wfontEnum1 (ENUMLOGFONTEXW* lpelfe, | |||
| int type, | |||
| LPARAM lParam) | |||
| { | |||
| if (lpelfe != 0 | |||
| && ((type & (DEVICE_FONTTYPE | RASTER_FONTTYPE)) == 0)) | |||
| if (lpelfe != 0 && (type & RASTER_FONTTYPE) == 0) | |||
| { | |||
| LOGFONTW lf; | |||
| zerostruct (lf); | |||
| @@ -12593,6 +12593,32 @@ public: | |||
| /** True if it seems to be valid. */ | |||
| bool isWellFormed() const; | |||
| /** Returns just the domain part of the URL. | |||
| E.g. for "http://www.xyz.com/foobar", this will return "www.xyz.com". | |||
| */ | |||
| const String getDomain() const; | |||
| /** Returns the path part of the URL. | |||
| E.g. for "http://www.xyz.com/foo/bar?x=1", this will return "foo/bar". | |||
| */ | |||
| const String getSubPath() const; | |||
| /** Returns the scheme of the URL. | |||
| E.g. for "http://www.xyz.com/foobar", this will return "http". (It won't | |||
| include the colon). | |||
| */ | |||
| const String getScheme() const; | |||
| /** Returns a new version of this URL that uses a different sub-path. | |||
| E.g. if the URL is "http://www.xyz.com/foo?x=1" and you call this with | |||
| "bar", it'll return "http://www.xyz.com/bar?x=1". | |||
| */ | |||
| const URL withNewSubPath (const String& newPath) const; | |||
| /** Returns a copy of this URL, with a GET parameter added to the end. | |||
| Any control characters in the value will be encoded. | |||
| @@ -52446,6 +52472,10 @@ public: | |||
| /** Returns the current zoom factor. */ | |||
| double getScaleFactor() const throw() { return scaleFactor; } | |||
| /** Changes the quality setting used to rescale the graphics. | |||
| */ | |||
| void setResamplingQuality (Graphics::ResamplingQuality newQuality); | |||
| juce_UseDebuggingNewOperator | |||
| /** @internal */ | |||
| @@ -52457,6 +52487,7 @@ private: | |||
| double scaleFactor; | |||
| ComponentPeer* peer; | |||
| bool deleteContent; | |||
| Graphics::ResamplingQuality quality; | |||
| void paint (Graphics& g); | |||
| void mouseDown (const MouseEvent& e); | |||
| @@ -53803,6 +53834,8 @@ public: | |||
| bool isMouseOverButton, | |||
| bool isButtonDown); | |||
| virtual const Font getFontForTextButton (TextButton& button); | |||
| /** Draws the text for a TextButton. */ | |||
| virtual void drawButtonText (Graphics& g, | |||
| TextButton& button, | |||
| @@ -278,7 +278,7 @@ public: | |||
| if (buttonUnderMouse != newItem) | |||
| { | |||
| if (buttonUnderMouse != 0) | |||
| if (buttonUnderMouse != 0 && containsItem (buttonUnderMouse)) | |||
| { | |||
| const Rectangle r (buttonUnderMouse->getItemPosition (false)); | |||
| repaint (0, r.getY(), r.getX(), buttonUnderMouse->getItemHeight()); | |||
| @@ -363,6 +363,15 @@ private: | |||
| item->setSelected ((! cmd) || (! item->isSelected()), ! cmd); | |||
| } | |||
| } | |||
| bool containsItem (TreeViewItem* const item) const | |||
| { | |||
| for (int i = rowComponentItems.size(); --i >= 0;) | |||
| if ((TreeViewItem*) rowComponentItems.getUnchecked (i) == item) | |||
| return true; | |||
| return false; | |||
| } | |||
| }; | |||
| //============================================================================== | |||
| @@ -365,10 +365,15 @@ void LookAndFeel::drawButtonBackground (Graphics& g, | |||
| button.isConnectedOnBottom()); | |||
| } | |||
| const Font LookAndFeel::getFontForTextButton (TextButton& button) | |||
| { | |||
| return button.getFont(); | |||
| } | |||
| void LookAndFeel::drawButtonText (Graphics& g, TextButton& button, | |||
| bool /*isMouseOverButton*/, bool /*isButtonDown*/) | |||
| { | |||
| g.setFont (button.getFont()); | |||
| g.setFont (getFontForTextButton (button)); | |||
| g.setColour (button.findColour (TextButton::textColourId) | |||
| .withMultipliedAlpha (button.isEnabled() ? 1.0f : 0.5f)); | |||
| @@ -153,6 +153,8 @@ public: | |||
| bool isMouseOverButton, | |||
| bool isButtonDown); | |||
| virtual const Font getFontForTextButton (TextButton& button); | |||
| /** Draws the text for a TextButton. */ | |||
| virtual void drawButtonText (Graphics& g, | |||
| TextButton& button, | |||
| @@ -200,7 +200,8 @@ MagnifierComponent::MagnifierComponent (Component* const content_, | |||
| : content (content_), | |||
| scaleFactor (0.0), | |||
| peer (0), | |||
| deleteContent (deleteContentCompWhenNoLongerNeeded) | |||
| deleteContent (deleteContentCompWhenNoLongerNeeded), | |||
| quality (Graphics::lowResamplingQuality) | |||
| { | |||
| holderComp = new PeerHolderComp (this); | |||
| setScaleFactor (1.0); | |||
| @@ -272,7 +273,7 @@ void MagnifierComponent::paint (Graphics& g) | |||
| g2.reduceClipRegion (srcX, srcY, srcW, srcH); | |||
| holderComp->paintEntireComponent (g2); | |||
| g.setImageResamplingQuality (Graphics::lowResamplingQuality); | |||
| g.setImageResamplingQuality (quality); | |||
| g.drawImage (&temp, | |||
| 0, 0, (int) (w * scaleFactor), (int) (h * scaleFactor), | |||
| 0, 0, w, h, | |||
| @@ -89,6 +89,9 @@ public: | |||
| /** Returns the current zoom factor. */ | |||
| double getScaleFactor() const throw() { return scaleFactor; } | |||
| /** Changes the quality setting used to rescale the graphics. | |||
| */ | |||
| void setResamplingQuality (Graphics::ResamplingQuality newQuality); | |||
| //============================================================================== | |||
| juce_UseDebuggingNewOperator | |||
| @@ -102,6 +105,7 @@ private: | |||
| double scaleFactor; | |||
| ComponentPeer* peer; | |||
| bool deleteContent; | |||
| Graphics::ResamplingQuality quality; | |||
| //============================================================================== | |||
| void paint (Graphics& g); | |||
| @@ -41,6 +41,7 @@ BEGIN_JUCE_NAMESPACE | |||
| #include "../juce_Desktop.h" | |||
| #include "../../../../juce_core/text/juce_LocalisedStrings.h" | |||
| #include "../../../events/juce_MessageManager.h" | |||
| #include "../../../application/juce_Application.h" | |||
| static const int titleH = 24; | |||
| static const int iconWidth = 80; | |||
| @@ -112,6 +113,9 @@ AlertWindow::AlertWindow (const String& title, | |||
| } | |||
| } | |||
| if (JUCEApplication::getInstance() == 0) | |||
| setAlwaysOnTop (true); // for a plugin, make it always-on-top because the host windows are often top-level | |||
| lookAndFeelChanged(); | |||
| constrainer.setMinimumOnscreenAmounts (0x10000, 0x10000, 0x10000, 0x10000); | |||
| @@ -135,6 +135,7 @@ void EdgeTable::addEdgePoint (const int x, const int y, const int winding) throw | |||
| if (n >= maxEdgesPerLine) | |||
| { | |||
| remapTableForNumEdges (maxEdgesPerLine + juce_edgeTableDefaultEdgesPerLine); | |||
| jassert (n < maxEdgesPerLine); | |||
| lineStart = table + lineStrideElements * y; | |||
| } | |||
| @@ -105,11 +105,9 @@ const AffineTransform RectanglePlacement::getTransformToFit (float x, float y, | |||
| const float scaleY = dh / h; | |||
| if ((flags & stretchToFit) != 0) | |||
| { | |||
| return AffineTransform::translation (-x, -y) | |||
| .scaled (scaleX, scaleY) | |||
| .translated (dx - x, dy - y); | |||
| } | |||
| .translated (dx, dy); | |||
| float scale = (flags & fillDestination) != 0 ? jmax (scaleX, scaleY) | |||
| : jmin (scaleX, scaleY); | |||
| @@ -133,6 +133,73 @@ bool URL::isWellFormed() const | |||
| return url.isNotEmpty(); | |||
| } | |||
| static int findStartOfDomain (const String& url) | |||
| { | |||
| int i = 0; | |||
| while (CharacterFunctions::isLetterOrDigit (url[i]) | |||
| || CharacterFunctions::indexOfChar (T("+-."), url[i], false) >= 0) | |||
| ++i; | |||
| return url[i] == T(':') ? i + 1 : 0; | |||
| } | |||
| const String URL::getDomain() const | |||
| { | |||
| int start = findStartOfDomain (url); | |||
| while (url[start] == T('/')) | |||
| ++start; | |||
| const int end1 = url.indexOfChar (start, T('/')); | |||
| const int end2 = url.indexOfChar (start, T(':')); | |||
| const int end = (end1 < 0 || end2 < 0) ? jmax (end1, end2) | |||
| : jmin (end1, end2); | |||
| return url.substring (start, end); | |||
| } | |||
| const String URL::getSubPath() const | |||
| { | |||
| int start = findStartOfDomain (url); | |||
| while (url[start] == T('/')) | |||
| ++start; | |||
| const int startOfPath = url.indexOfChar (start, T('/')) + 1; | |||
| return startOfPath <= 0 ? String::empty | |||
| : url.substring (startOfPath); | |||
| } | |||
| const String URL::getScheme() const | |||
| { | |||
| return url.substring (0, findStartOfDomain (url) - 1); | |||
| } | |||
| const URL URL::withNewSubPath (const String& newPath) const | |||
| { | |||
| int start = findStartOfDomain (url); | |||
| while (url[start] == T('/')) | |||
| ++start; | |||
| const int startOfPath = url.indexOfChar (start, T('/')) + 1; | |||
| URL u (*this); | |||
| if (startOfPath > 0) | |||
| u.url = url.substring (0, startOfPath); | |||
| if (! u.url.endsWithChar (T('/'))) | |||
| u.url << '/'; | |||
| if (newPath.startsWithChar (T('/'))) | |||
| u.url << newPath.substring (1); | |||
| else | |||
| u.url << newPath; | |||
| return u; | |||
| } | |||
| //============================================================================== | |||
| bool URL::isProbablyAWebsiteURL (const String& possibleURL) | |||
| { | |||
| @@ -75,6 +75,32 @@ public: | |||
| /** True if it seems to be valid. */ | |||
| bool isWellFormed() const; | |||
| /** Returns just the domain part of the URL. | |||
| E.g. for "http://www.xyz.com/foobar", this will return "www.xyz.com". | |||
| */ | |||
| const String getDomain() const; | |||
| /** Returns the path part of the URL. | |||
| E.g. for "http://www.xyz.com/foo/bar?x=1", this will return "foo/bar". | |||
| */ | |||
| const String getSubPath() const; | |||
| /** Returns the scheme of the URL. | |||
| E.g. for "http://www.xyz.com/foobar", this will return "http". (It won't | |||
| include the colon). | |||
| */ | |||
| const String getScheme() const; | |||
| /** Returns a new version of this URL that uses a different sub-path. | |||
| E.g. if the URL is "http://www.xyz.com/foo?x=1" and you call this with | |||
| "bar", it'll return "http://www.xyz.com/bar?x=1". | |||
| */ | |||
| const URL withNewSubPath (const String& newPath) const; | |||
| //============================================================================== | |||
| /** Returns a copy of this URL, with a GET parameter added to the end. | |||