diff --git a/extras/Jucer (experimental)/Builds/MacOSX/The Jucer.xcodeproj/project.pbxproj b/extras/Jucer (experimental)/Builds/MacOSX/The Jucer.xcodeproj/project.pbxproj
index 406084abb4..496b9e545c 100644
--- a/extras/Jucer (experimental)/Builds/MacOSX/The Jucer.xcodeproj/project.pbxproj
+++ b/extras/Jucer (experimental)/Builds/MacOSX/The Jucer.xcodeproj/project.pbxproj
@@ -105,6 +105,7 @@
F9EAFD5BC3E676BC59B326E0 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = jucer_DrawableObjectComponent.h; path = "../../Source/ui/Drawable Editor/jucer_DrawableObjectComponent.h"; sourceTree = SOURCE_ROOT; };
654C1B62A2BE1FBB28BEAE72 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = jucer_DrawableTreeviewItem.h; path = "../../Source/ui/Drawable Editor/jucer_DrawableTreeviewItem.h"; sourceTree = SOURCE_ROOT; };
E6BB0D9B515B50E418D98B9C = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = jucer_CommandIDs.h; path = ../../Source/ui/jucer_CommandIDs.h; sourceTree = SOURCE_ROOT; };
+ 95A4E72FC64A7338CB259DF7 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = jucer_CoordinatePropertyComponent.h; path = ../../Source/ui/jucer_CoordinatePropertyComponent.h; sourceTree = SOURCE_ROOT; };
3B2C45064E85B3B631D4F921 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = jucer_DocumentEditorComponent.cpp; path = ../../Source/ui/jucer_DocumentEditorComponent.cpp; sourceTree = SOURCE_ROOT; };
156F72179BBFCD0D9804C266 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = jucer_DocumentEditorComponent.h; path = ../../Source/ui/jucer_DocumentEditorComponent.h; sourceTree = SOURCE_ROOT; };
8F731296532276CBF2B6190D = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = jucer_GroupInformationComponent.cpp; path = ../../Source/ui/jucer_GroupInformationComponent.cpp; sourceTree = SOURCE_ROOT; };
@@ -209,6 +210,7 @@
3A0BE83502CB509D623C2C07,
E6053BD673F80E900DDA3593,
E6BB0D9B515B50E418D98B9C,
+ 95A4E72FC64A7338CB259DF7,
3B2C45064E85B3B631D4F921,
156F72179BBFCD0D9804C266,
8F731296532276CBF2B6190D,
diff --git a/extras/Jucer (experimental)/Builds/VisualStudio2005/The Jucer.vcproj b/extras/Jucer (experimental)/Builds/VisualStudio2005/The Jucer.vcproj
index fef4486a97..e95c9cbdee 100644
--- a/extras/Jucer (experimental)/Builds/VisualStudio2005/The Jucer.vcproj
+++ b/extras/Jucer (experimental)/Builds/VisualStudio2005/The Jucer.vcproj
@@ -185,6 +185,7 @@
+
diff --git a/extras/Jucer (experimental)/Builds/VisualStudio2008/The Jucer.vcproj b/extras/Jucer (experimental)/Builds/VisualStudio2008/The Jucer.vcproj
index 1d1c6f7bfd..16e97f17c0 100644
--- a/extras/Jucer (experimental)/Builds/VisualStudio2008/The Jucer.vcproj
+++ b/extras/Jucer (experimental)/Builds/VisualStudio2008/The Jucer.vcproj
@@ -185,6 +185,7 @@
+
diff --git a/extras/Jucer (experimental)/Jucer.jucer b/extras/Jucer (experimental)/Jucer.jucer
index be9986fa81..bae1deadc4 100644
--- a/extras/Jucer (experimental)/Jucer.jucer
+++ b/extras/Jucer (experimental)/Jucer.jucer
@@ -123,6 +123,8 @@
+
setEditable (true, true, false);
- label->setColour (Label::backgroundColourId, Colours::white);
- label->setColour (Label::outlineColourId, findColour (ComboBox::outlineColourId));
- label->getTextValue().referTo (textValue);
-
- addAndMakeVisible (proportionButton = new TextButton ("%"));
- proportionButton->addButtonListener (this);
-
- addAndMakeVisible (anchorButton1 = new TextButton (String::empty));
- anchorButton1->setConnectedEdges (Button::ConnectedOnLeft | Button::ConnectedOnTop | Button::ConnectedOnRight | Button::ConnectedOnBottom);
- anchorButton1->setTriggeredOnMouseDown (true);
- anchorButton1->addButtonListener (this);
-
- addAndMakeVisible (anchorButton2 = new TextButton (String::empty));
- anchorButton2->setConnectedEdges (Button::ConnectedOnLeft | Button::ConnectedOnTop | Button::ConnectedOnRight | Button::ConnectedOnBottom);
- anchorButton2->setTriggeredOnMouseDown (true);
- anchorButton2->addButtonListener (this);
-
- coordValue.addListener (this);
- valueChanged (coordValue);
- }
-
- ~CoordinateEditor()
- {
- coordValue.removeListener (this);
- deleteAllChildren();
- }
-
- void resized()
- {
- const Rectangle r (getLookAndFeel().getPropertyComponentContentPosition (*this));
-
- label->setBounds (r.getX(), r.getY(), r.getWidth() / 2, r.getHeight() / 2);
- proportionButton->setBounds (r.getX() + r.getWidth() / 2, r.getY(),
- r.getWidth() / 2, r.getHeight() / 2);
-
- if (anchorButton2->isVisible())
- {
- anchorButton1->setBounds (r.getX(), r.getY() + r.getHeight() / 2, r.getWidth() / 2, r.getHeight() / 2);
- anchorButton2->setBounds (r.getX() + r.getWidth() / 2, r.getY() + r.getHeight() / 2, r.getWidth() / 2, r.getHeight() / 2);
- }
- else
- {
- anchorButton1->setBounds (r.getX(), r.getY() + r.getHeight() / 2, r.getWidth(), r.getHeight() / 2);
- }
- }
-
- void refresh() {}
-
- void buttonClicked (Button* button)
- {
- Coordinate coord (getCoordinate());
-
- if (button == proportionButton)
- {
- coord.toggleProportionality (document);
- coordValue = coord.toString();
- }
- else if (button == anchorButton1)
- {
- const String marker (pickMarker (anchorButton1, coord.getAnchor1(), true));
-
- if (marker.isNotEmpty())
- {
- coord.changeAnchor1 (marker, document);
- coordValue = coord.toString();
- }
- }
- else if (button == anchorButton2)
- {
- const String marker (pickMarker (anchorButton2, coord.getAnchor2(), false));
-
- if (marker.isNotEmpty())
- {
- coord.changeAnchor2 (marker, document);
- coordValue = coord.toString();
- }
- }
- }
-
- void valueChanged (Value&)
- {
- Coordinate coord (getCoordinate());
-
- anchorButton1->setButtonText (coord.getAnchor1());
-
- anchorButton2->setVisible (coord.isProportional());
- anchorButton2->setButtonText (coord.getAnchor2());
- resized();
- }
-
- const Coordinate getCoordinate() const
- {
- return Coordinate (coordValue.toString(), isHorizontal);
- }
-
- virtual const String pickMarker (TextButton* button, const String& currentMarker, bool isAnchor1) = 0;
-
-protected:
- ComponentDocument& document;
- Value coordValue, textValue;
- Label* label;
- TextButton* proportionButton;
- TextButton* anchorButton1;
- TextButton* anchorButton2;
- bool isHorizontal;
-
- //==============================================================================
- class CoordEditableValueSource : public Value::ValueSource,
- public Value::Listener
- {
- public:
- CoordEditableValueSource (const Value& sourceValue_, bool isHorizontal_)
- : sourceValue (sourceValue_), isHorizontal (isHorizontal_)
- {
- sourceValue.addListener (this);
- }
-
- ~CoordEditableValueSource() {}
-
- const var getValue() const
- {
- Coordinate coord (sourceValue.toString(), isHorizontal);
-
- if (coord.isProportional())
- return String (coord.getEditableValue()) + "%";
-
- return coord.getEditableValue();
- }
-
- void setValue (const var& newValue)
- {
- Coordinate coord (sourceValue.toString(), isHorizontal);
- coord.setEditableValue ((double) newValue);
-
- const String newVal (coord.toString());
- if (sourceValue != newVal)
- sourceValue = newVal;
- }
-
- void valueChanged (Value&)
- {
- sendChangeMessage (true);
- }
-
- //==============================================================================
- juce_UseDebuggingNewOperator
-
- protected:
- Value sourceValue;
- bool isHorizontal;
-
- CoordEditableValueSource (const CoordEditableValueSource&);
- const CoordEditableValueSource& operator= (const CoordEditableValueSource&);
- };
-};
-
-
-//==============================================================================
-class ComponentBoundsEditor : public CoordinateEditor
+class ComponentBoundsEditor : public CoordinatePropertyComponent
{
public:
enum Type
@@ -213,9 +40,9 @@ public:
//==============================================================================
ComponentBoundsEditor (ComponentDocument& document_, const String& name, Type type_,
const ValueTree& compState_, const Value& coordValue_)
- : CoordinateEditor (document_, name,
- Value (new BoundsCoordValueSource (coordValue_, type_)),
- type_ == left || type_ == right),
+ : CoordinatePropertyComponent (document_, name,
+ Value (new CoordExtractor (coordValue_, type_)),
+ type_ == left || type_ == right),
type (type_),
compState (compState_)
{
@@ -226,17 +53,17 @@ public:
}
//==============================================================================
- class BoundsCoordValueSource : public Value::ValueSource,
- public Value::Listener
+ class CoordExtractor : public Value::ValueSource,
+ public Value::Listener
{
public:
- BoundsCoordValueSource (const Value& sourceValue_, Type type_)
+ CoordExtractor (const Value& sourceValue_, Type type_)
: sourceValue (sourceValue_), type (type_)
{
sourceValue.addListener (this);
}
- ~BoundsCoordValueSource() {}
+ ~CoordExtractor() {}
const var getValue() const
{
@@ -286,8 +113,8 @@ public:
return getCoordForType (type, r);
}
- BoundsCoordValueSource (const BoundsCoordValueSource&);
- const BoundsCoordValueSource& operator= (const BoundsCoordValueSource&);
+ CoordExtractor (const CoordExtractor&);
+ const CoordExtractor& operator= (const CoordExtractor&);
};
const String pickMarker (TextButton* button, const String& currentMarker, bool isAnchor1)
@@ -295,7 +122,7 @@ public:
Coordinate coord (getCoordinate());
PopupMenu m;
- document.getComponentMarkerMenuItems (compState, getTypeName(), coord, m, isAnchor1);
+ document.addComponentMarkerMenuItems (compState, getTypeName(), coord, m, isAnchor1);
const int r = m.showAt (button);
diff --git a/extras/Jucer (experimental)/Source/model/jucer_ComponentDocument.cpp b/extras/Jucer (experimental)/Source/model/jucer_ComponentDocument.cpp
index 560b95bf1f..377d500672 100644
--- a/extras/Jucer (experimental)/Source/model/jucer_ComponentDocument.cpp
+++ b/extras/Jucer (experimental)/Source/model/jucer_ComponentDocument.cpp
@@ -25,6 +25,7 @@
#include "jucer_ComponentDocument.h"
#include "Component Types/jucer_ComponentTypeManager.h"
+#include "../ui/jucer_CoordinatePropertyComponent.h"
//==============================================================================
@@ -355,38 +356,37 @@ bool ComponentDocument::setCoordsFor (ValueTree& state, const RectangleCoordinat
return true;
}
-void ComponentDocument::addMarkerMenuItem (int i, Coordinate& coord, const String& name, PopupMenu& menu, bool isAnchor1,
- const ValueTree& componentState, const String& coordName)
+void ComponentDocument::addMarkerMenuItem (int i, const Coordinate& coord, const String& name, PopupMenu& menu,
+ bool isAnchor1, const String& fullCoordName)
{
- const String componentName (componentState [memberNameProperty].toString());
Coordinate requestedCoord (findMarker (name, coord.isHorizontal()));
- const String fullCoordName (componentName + "." + coordName);
menu.addItem (i, name,
! (name == fullCoordName || requestedCoord.referencesIndirectly (fullCoordName, *this)),
name == (isAnchor1 ? coord.getAnchor1() : coord.getAnchor2()));
}
-void ComponentDocument::getComponentMarkerMenuItems (const ValueTree& componentState, const String& coordName,
+void ComponentDocument::addComponentMarkerMenuItems (const ValueTree& componentState, const String& coordName,
Coordinate& coord, PopupMenu& menu, bool isAnchor1)
{
const String componentName (componentState [memberNameProperty].toString());
+ const String fullCoordName (componentName + "." + coordName);
if (coord.isHorizontal())
{
- addMarkerMenuItem (1, coord, Coordinate::parentLeftMarkerName, menu, isAnchor1, componentState, coordName);
- addMarkerMenuItem (2, coord, Coordinate::parentRightMarkerName, menu, isAnchor1, componentState, coordName);
+ addMarkerMenuItem (1, coord, Coordinate::parentLeftMarkerName, menu, isAnchor1, fullCoordName);
+ addMarkerMenuItem (2, coord, Coordinate::parentRightMarkerName, menu, isAnchor1, fullCoordName);
menu.addSeparator();
- addMarkerMenuItem (3, coord, componentName + ".left", menu, isAnchor1, componentState, coordName);
- addMarkerMenuItem (4, coord, componentName + ".right", menu, isAnchor1, componentState, coordName);
+ addMarkerMenuItem (3, coord, componentName + ".left", menu, isAnchor1, fullCoordName);
+ addMarkerMenuItem (4, coord, componentName + ".right", menu, isAnchor1, fullCoordName);
}
else
{
- addMarkerMenuItem (1, coord, Coordinate::parentTopMarkerName, menu, isAnchor1, componentState, coordName);
- addMarkerMenuItem (2, coord, Coordinate::parentBottomMarkerName, menu, isAnchor1, componentState, coordName);
+ addMarkerMenuItem (1, coord, Coordinate::parentTopMarkerName, menu, isAnchor1, fullCoordName);
+ addMarkerMenuItem (2, coord, Coordinate::parentBottomMarkerName, menu, isAnchor1, fullCoordName);
menu.addSeparator();
- addMarkerMenuItem (3, coord, componentName + ".top", menu, isAnchor1, componentState, coordName);
- addMarkerMenuItem (4, coord, componentName + ".bottom", menu, isAnchor1, componentState, coordName);
+ addMarkerMenuItem (3, coord, componentName + ".top", menu, isAnchor1, fullCoordName);
+ addMarkerMenuItem (4, coord, componentName + ".bottom", menu, isAnchor1, fullCoordName);
}
menu.addSeparator();
@@ -394,7 +394,7 @@ void ComponentDocument::getComponentMarkerMenuItems (const ValueTree& componentS
int i;
for (i = 0; i < markerList.size(); ++i)
- addMarkerMenuItem (100 + i, coord, markerList.getName (markerList.getMarker (i)), menu, isAnchor1, componentState, coordName);
+ addMarkerMenuItem (100 + i, coord, markerList.getName (markerList.getMarker (i)), menu, isAnchor1, fullCoordName);
menu.addSeparator();
for (i = 0; i < getNumComponents(); ++i)
@@ -405,13 +405,13 @@ void ComponentDocument::getComponentMarkerMenuItems (const ValueTree& componentS
{
if (coord.isHorizontal())
{
- addMarkerMenuItem (10000 + i * 4, coord, compName + ".left", menu, isAnchor1, componentState, coordName);
- addMarkerMenuItem (10001 + i * 4, coord, compName + ".right", menu, isAnchor1, componentState, coordName);
+ addMarkerMenuItem (10000 + i * 4, coord, compName + ".left", menu, isAnchor1, fullCoordName);
+ addMarkerMenuItem (10001 + i * 4, coord, compName + ".right", menu, isAnchor1, fullCoordName);
}
else
{
- addMarkerMenuItem (10002 + i * 4, coord, compName + ".top", menu, isAnchor1, componentState, coordName);
- addMarkerMenuItem (10003 + i * 4, coord, compName + ".bottom", menu, isAnchor1, componentState, coordName);
+ addMarkerMenuItem (10002 + i * 4, coord, compName + ".top", menu, isAnchor1, fullCoordName);
+ addMarkerMenuItem (10003 + i * 4, coord, compName + ".bottom", menu, isAnchor1, fullCoordName);
}
}
}
@@ -600,9 +600,84 @@ const Coordinate ComponentDocument::MarkerList::findMarker (const String& name,
return Coordinate (isX);
}
+void ComponentDocument::MarkerList::addMarkerMenuItems (const ValueTree& markerState, const Coordinate& coord, PopupMenu& menu, bool isAnchor1)
+{
+ const String fullCoordName (getName (markerState));
+
+ if (coord.isHorizontal())
+ {
+ document.addMarkerMenuItem (1, coord, Coordinate::parentLeftMarkerName, menu, isAnchor1, fullCoordName);
+ document.addMarkerMenuItem (2, coord, Coordinate::parentRightMarkerName, menu, isAnchor1, fullCoordName);
+ }
+ else
+ {
+ document.addMarkerMenuItem (1, coord, Coordinate::parentTopMarkerName, menu, isAnchor1, fullCoordName);
+ document.addMarkerMenuItem (2, coord, Coordinate::parentBottomMarkerName, menu, isAnchor1, fullCoordName);
+ }
+
+ menu.addSeparator();
+ const MarkerList& markerList = document.getMarkerList (coord.isHorizontal());
+
+ for (int i = 0; i < markerList.size(); ++i)
+ document.addMarkerMenuItem (100 + i, coord, markerList.getName (markerList.getMarker (i)), menu, isAnchor1, fullCoordName);
+}
+
+const String ComponentDocument::MarkerList::getChosenMarkerMenuItem (const Coordinate& coord, int i) const
+{
+ if (i == 1) return coord.isHorizontal() ? Coordinate::parentLeftMarkerName : Coordinate::parentTopMarkerName;
+ if (i == 2) return coord.isHorizontal() ? Coordinate::parentRightMarkerName : Coordinate::parentBottomMarkerName;
+
+ const MarkerList& markerList = document.getMarkerList (coord.isHorizontal());
+
+ if (i >= 100 && i < 10000)
+ return markerList.getName (markerList.getMarker (i - 100));
+
+ jassertfalse;
+ return String::empty;
+}
+
+//==============================================================================
+class MarkerPositionComponent : public CoordinatePropertyComponent
+{
+public:
+ //==============================================================================
+ MarkerPositionComponent (ComponentDocument& document_, const String& name, const ValueTree& markerState_,
+ const Value& coordValue_, bool isHorizontal_)
+ : CoordinatePropertyComponent (document_, name, coordValue_, isHorizontal_),
+ markerState (markerState_)
+ {
+ }
+
+ ~MarkerPositionComponent()
+ {
+ }
+
+ const String pickMarker (TextButton* button, const String& currentMarker, bool isAnchor1)
+ {
+ Coordinate coord (getCoordinate());
+
+ PopupMenu m;
+ document.getMarkerList (coord.isHorizontal())
+ .addMarkerMenuItems (markerState, coord, m, isAnchor1);
+
+ const int r = m.showAt (button);
+
+ if (r > 0)
+ return document.getMarkerList (coord.isHorizontal()).getChosenMarkerMenuItem (coord, r);
+
+ return String::empty;
+ }
+
+private:
+ ValueTree markerState;
+};
+
void ComponentDocument::MarkerList::createMarkerProperties (Array & props, ValueTree& marker)
{
props.add (new TextPropertyComponent (getNameAsValue (marker), "Marker Name", 256, false));
+ props.add (new MarkerPositionComponent (document, "Position", marker,
+ marker.getPropertyAsValue (markerPosProperty, document.getUndoManager()),
+ contains (marker)));
}
bool ComponentDocument::MarkerList::createProperties (Array & props, const String& itemId)
diff --git a/extras/Jucer (experimental)/Source/model/jucer_ComponentDocument.h b/extras/Jucer (experimental)/Source/model/jucer_ComponentDocument.h
index 0077f98933..9af0d4213f 100644
--- a/extras/Jucer (experimental)/Source/model/jucer_ComponentDocument.h
+++ b/extras/Jucer (experimental)/Source/model/jucer_ComponentDocument.h
@@ -74,7 +74,7 @@ public:
// for Coordinate::MarkerResolver:
const Coordinate findMarker (const String& name, bool isHorizontal) const;
- void getComponentMarkerMenuItems (const ValueTree& componentState, const String& coordName,
+ void addComponentMarkerMenuItems (const ValueTree& componentState, const String& coordName,
Coordinate& coord, PopupMenu& menu, bool isAnchor1);
const String getChosenMarkerMenuItem (const ValueTree& componentState, Coordinate& coord, int itemId) const;
@@ -105,6 +105,9 @@ public:
bool createProperties (Array & props, const String& itemId);
void createMarkerProperties (Array & props, ValueTree& marker);
+ void addMarkerMenuItems (const ValueTree& markerState, const Coordinate& coord, PopupMenu& menu, bool isAnchor1);
+ const String getChosenMarkerMenuItem (const Coordinate& coord, int itemId) const;
+
private:
ComponentDocument& document;
ValueTree group;
@@ -159,8 +162,8 @@ private:
void checkRootObject();
void createSubTreeIfNotThere (const String& name);
ValueTree getComponentGroup() const;
- void addMarkerMenuItem (int i, Coordinate& coord, const String& name, PopupMenu& menu, bool isAnchor1,
- const ValueTree& componentState, const String& coordName);
+ void addMarkerMenuItem (int i, const Coordinate& coord, const String& name, PopupMenu& menu,
+ bool isAnchor1, const String& fullCoordName);
Value getRootValueUndoable (const var::identifier& name) const { return root.getPropertyAsValue (name, getUndoManager()); }
Value getRootValueNonUndoable (const var::identifier& name) const { return root.getPropertyAsValue (name, 0); }
diff --git a/extras/Jucer (experimental)/Source/ui/jucer_CoordinatePropertyComponent.h b/extras/Jucer (experimental)/Source/ui/jucer_CoordinatePropertyComponent.h
new file mode 100644
index 0000000000..ddeab9da2b
--- /dev/null
+++ b/extras/Jucer (experimental)/Source/ui/jucer_CoordinatePropertyComponent.h
@@ -0,0 +1,205 @@
+/*
+ ==============================================================================
+
+ 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 __JUCER_COORDINATEPROPERTYCOMPONENT_H_1128AA3D__
+#define __JUCER_COORDINATEPROPERTYCOMPONENT_H_1128AA3D__
+
+
+//==============================================================================
+class CoordinatePropertyComponent : public PropertyComponent,
+ public ButtonListener,
+ public Value::Listener
+{
+public:
+ //==============================================================================
+ CoordinatePropertyComponent (ComponentDocument& document_, const String& name,
+ const Value& coordValue_, bool isHorizontal_)
+ : PropertyComponent (name, 40), document (document_),
+ coordValue (coordValue_),
+ textValue (Value (new CoordEditableValueSource (coordValue_, isHorizontal_))),
+ isHorizontal (isHorizontal_)
+ {
+ addAndMakeVisible (label = new Label (String::empty, String::empty));
+
+ label->setEditable (true, true, false);
+ label->setColour (Label::backgroundColourId, Colours::white);
+ label->setColour (Label::outlineColourId, findColour (ComboBox::outlineColourId));
+ label->getTextValue().referTo (textValue);
+
+ addAndMakeVisible (proportionButton = new TextButton ("%"));
+ proportionButton->addButtonListener (this);
+
+ addAndMakeVisible (anchorButton1 = new TextButton (String::empty));
+ anchorButton1->setConnectedEdges (Button::ConnectedOnLeft | Button::ConnectedOnTop | Button::ConnectedOnRight | Button::ConnectedOnBottom);
+ anchorButton1->setTriggeredOnMouseDown (true);
+ anchorButton1->addButtonListener (this);
+
+ addAndMakeVisible (anchorButton2 = new TextButton (String::empty));
+ anchorButton2->setConnectedEdges (Button::ConnectedOnLeft | Button::ConnectedOnTop | Button::ConnectedOnRight | Button::ConnectedOnBottom);
+ anchorButton2->setTriggeredOnMouseDown (true);
+ anchorButton2->addButtonListener (this);
+
+ coordValue.addListener (this);
+ valueChanged (coordValue);
+ }
+
+ ~CoordinatePropertyComponent()
+ {
+ coordValue.removeListener (this);
+ deleteAllChildren();
+ }
+
+ void resized()
+ {
+ const Rectangle r (getLookAndFeel().getPropertyComponentContentPosition (*this));
+
+ label->setBounds (r.getX(), r.getY(), r.getWidth() / 2, r.getHeight() / 2);
+ proportionButton->setBounds (r.getX() + r.getWidth() / 2, r.getY(),
+ r.getWidth() / 2, r.getHeight() / 2);
+
+ if (anchorButton2->isVisible())
+ {
+ anchorButton1->setBounds (r.getX(), r.getY() + r.getHeight() / 2, r.getWidth() / 2, r.getHeight() / 2);
+ anchorButton2->setBounds (r.getX() + r.getWidth() / 2, r.getY() + r.getHeight() / 2, r.getWidth() / 2, r.getHeight() / 2);
+ }
+ else
+ {
+ anchorButton1->setBounds (r.getX(), r.getY() + r.getHeight() / 2, r.getWidth(), r.getHeight() / 2);
+ }
+ }
+
+ void refresh() {}
+
+ void buttonClicked (Button* button)
+ {
+ Coordinate coord (getCoordinate());
+
+ if (button == proportionButton)
+ {
+ coord.toggleProportionality (document);
+ coordValue = coord.toString();
+ }
+ else if (button == anchorButton1)
+ {
+ const String marker (pickMarker (anchorButton1, coord.getAnchor1(), true));
+
+ if (marker.isNotEmpty())
+ {
+ coord.changeAnchor1 (marker, document);
+ coordValue = coord.toString();
+ }
+ }
+ else if (button == anchorButton2)
+ {
+ const String marker (pickMarker (anchorButton2, coord.getAnchor2(), false));
+
+ if (marker.isNotEmpty())
+ {
+ coord.changeAnchor2 (marker, document);
+ coordValue = coord.toString();
+ }
+ }
+ }
+
+ void valueChanged (Value&)
+ {
+ Coordinate coord (getCoordinate());
+
+ anchorButton1->setButtonText (coord.getAnchor1());
+
+ anchorButton2->setVisible (coord.isProportional());
+ anchorButton2->setButtonText (coord.getAnchor2());
+ resized();
+ }
+
+ const Coordinate getCoordinate() const
+ {
+ return Coordinate (coordValue.toString(), isHorizontal);
+ }
+
+ virtual const String pickMarker (TextButton* button, const String& currentMarker, bool isAnchor1) = 0;
+
+protected:
+ ComponentDocument& document;
+ Value coordValue, textValue;
+ Label* label;
+ TextButton* proportionButton;
+ TextButton* anchorButton1;
+ TextButton* anchorButton2;
+ bool isHorizontal;
+
+ //==============================================================================
+ class CoordEditableValueSource : public Value::ValueSource,
+ public Value::Listener
+ {
+ public:
+ CoordEditableValueSource (const Value& sourceValue_, bool isHorizontal_)
+ : sourceValue (sourceValue_), isHorizontal (isHorizontal_)
+ {
+ sourceValue.addListener (this);
+ }
+
+ ~CoordEditableValueSource() {}
+
+ const var getValue() const
+ {
+ Coordinate coord (sourceValue.toString(), isHorizontal);
+
+ if (coord.isProportional())
+ return String (coord.getEditableValue()) + "%";
+
+ return coord.getEditableValue();
+ }
+
+ void setValue (const var& newValue)
+ {
+ Coordinate coord (sourceValue.toString(), isHorizontal);
+ coord.setEditableValue ((double) newValue);
+
+ const String newVal (coord.toString());
+ if (sourceValue != newVal)
+ sourceValue = newVal;
+ }
+
+ void valueChanged (Value&)
+ {
+ sendChangeMessage (true);
+ }
+
+ //==============================================================================
+ juce_UseDebuggingNewOperator
+
+ protected:
+ Value sourceValue;
+ bool isHorizontal;
+
+ CoordEditableValueSource (const CoordEditableValueSource&);
+ const CoordEditableValueSource& operator= (const CoordEditableValueSource&);
+ };
+};
+
+
+
+#endif // __JUCER_COORDINATEPROPERTYCOMPONENT_H_1128AA3D__
diff --git a/juce_Config.h b/juce_Config.h
index a2f8ad1d1a..13794ca42a 100644
--- a/juce_Config.h
+++ b/juce_Config.h
@@ -45,7 +45,7 @@
it to be true or false.
*/
#ifndef JUCE_FORCE_DEBUG
- #define JUCE_FORCE_DEBUG 0
+ //#define JUCE_FORCE_DEBUG 0
#endif
//=============================================================================
diff --git a/juce_amalgamated.cpp b/juce_amalgamated.cpp
index 328c712ad6..38f574497e 100644
--- a/juce_amalgamated.cpp
+++ b/juce_amalgamated.cpp
@@ -168,7 +168,7 @@
#endif
#ifndef JUCE_FORCE_DEBUG
- #define JUCE_FORCE_DEBUG 0
+ //#define JUCE_FORCE_DEBUG 0
#endif
#ifndef JUCE_LOG_ASSERTIONS
@@ -1892,7 +1892,7 @@ const String Time::toString (const bool includeDate,
return result.trimEnd();
}
-const String Time::formatted (const juce_wchar* const format) const throw()
+const String Time::formatted (const String& format) const throw()
{
String buffer;
int bufferSize = 128;
@@ -5464,77 +5464,21 @@ END_JUCE_NAMESPACE
/*** Start of inlined file: juce_DirectoryIterator.cpp ***/
BEGIN_JUCE_NAMESPACE
-void* juce_findFileStart (const String& directory, const String& wildCard, String& firstResultFile,
- bool* isDirectory, bool* isHidden, int64* fileSize,
- Time* modTime, Time* creationTime, bool* isReadOnly);
-bool juce_findFileNext (void* handle, String& resultFile,
- bool* isDirectory, bool* isHidden, int64* fileSize,
- Time* modTime, Time* creationTime, bool* isReadOnly);
-void juce_findFileClose (void* handle);
-
DirectoryIterator::DirectoryIterator (const File& directory,
- bool isRecursive,
- const String& wc,
+ bool isRecursive_,
+ const String& wildCard_,
const int whatToLookFor_)
- : wildCard (wc),
+ : fileFinder (directory, isRecursive ? "*" : wildCard_),
+ wildCard (wildCard_),
+ path (File::addTrailingSeparator (directory.getFullPathName())),
index (-1),
- whatToLookFor (whatToLookFor_)
+ totalNumFiles (-1),
+ whatToLookFor (whatToLookFor_),
+ isRecursive (isRecursive_)
{
// you have to specify the type of files you're looking for!
jassert ((whatToLookFor_ & (File::findFiles | File::findDirectories)) != 0);
jassert (whatToLookFor_ > 0 && whatToLookFor_ <= 7);
-
- String path (directory.getFullPathName());
- if (! path.endsWithChar (File::separator))
- path += File::separator;
-
- String filename;
- bool isDirectory, isHidden;
-
- void* const handle = juce_findFileStart (path,
- isRecursive ? "*" : wc,
- filename, &isDirectory, &isHidden, 0, 0, 0, 0);
-
- if (handle != 0)
- {
- do
- {
- if (! filename.containsOnly ("."))
- {
- bool addToList = false;
-
- if (isDirectory)
- {
- if (isRecursive
- && ((whatToLookFor_ & File::ignoreHiddenFiles) == 0
- || ! isHidden))
- {
- dirsFound.add (File (path + filename, 0));
- }
-
- addToList = (whatToLookFor_ & File::findDirectories) != 0;
- }
- else
- {
- addToList = (whatToLookFor_ & File::findFiles) != 0;
- }
-
- // if it's recursive, we're not relying on the OS iterator
- // to do the wildcard match, so do it now..
- if (isRecursive && addToList)
- addToList = filename.matchesWildcard (wc, true);
-
- if (addToList && (whatToLookFor_ & File::ignoreHiddenFiles) != 0)
- addToList = ! isHidden;
-
- if (addToList)
- filesFound.add (File (path + filename, 0));
- }
-
- } while (juce_findFileNext (handle, filename, &isDirectory, &isHidden, 0, 0, 0, 0));
-
- juce_findFileClose (handle);
- }
}
DirectoryIterator::~DirectoryIterator()
@@ -5542,28 +5486,67 @@ DirectoryIterator::~DirectoryIterator()
}
bool DirectoryIterator::next()
+{
+ return next (0, 0, 0, 0, 0, 0);
+}
+
+bool DirectoryIterator::next (bool* const isDirResult, bool* const isHiddenResult, int64* const fileSize,
+ Time* const modTime, Time* const creationTime, bool* const isReadOnly)
{
if (subIterator != 0)
{
- if (subIterator->next())
+ if (subIterator->next (isDirResult, isHiddenResult, fileSize, modTime, creationTime, isReadOnly))
return true;
subIterator = 0;
}
- if (index >= filesFound.size() + dirsFound.size() - 1)
- return false;
-
- ++index;
-
- if (index >= filesFound.size())
+ String filename;
+ bool isDirectory, isHidden;
+ while (fileFinder.next (filename, &isDirectory, &isHidden, fileSize, modTime, creationTime, isReadOnly))
{
- subIterator = new DirectoryIterator (dirsFound.getReference (index - filesFound.size()),
- true, wildCard, whatToLookFor);
- return next();
+ ++index;
+
+ if (! filename.containsOnly ("."))
+ {
+ const File fileFound (path + filename, 0);
+ bool matches = false;
+
+ if (isDirectory)
+ {
+ if (isRecursive && ((whatToLookFor & File::ignoreHiddenFiles) == 0 || ! isHidden))
+ subIterator = new DirectoryIterator (fileFound, true, wildCard, whatToLookFor);
+
+ matches = (whatToLookFor & File::findDirectories) != 0;
+ }
+ else
+ {
+ matches = (whatToLookFor & File::findFiles) != 0;
+ }
+
+ // if recursive, we're not relying on the OS iterator to do the wildcard match, so do it now..
+ if (matches && isRecursive)
+ matches = filename.matchesWildcard (wildCard, ! File::areFileNamesCaseSensitive());
+
+ if (matches && (whatToLookFor & File::ignoreHiddenFiles) != 0)
+ matches = ! isHidden;
+
+ if (matches)
+ {
+ currentFile = fileFound;
+ if (isHiddenResult != 0) *isHiddenResult = isHidden;
+ if (isDirResult != 0) *isDirResult = isDirectory;
+
+ return true;
+ }
+ else if (subIterator != 0)
+ {
+ return next();
+ }
+ }
}
- return true;
+ return false;
}
const File DirectoryIterator::getFile() const
@@ -5571,22 +5554,21 @@ const File DirectoryIterator::getFile() const
if (subIterator != 0)
return subIterator->getFile();
- return filesFound [index];
+ return currentFile;
}
float DirectoryIterator::getEstimatedProgress() const
{
- if (filesFound.size() + dirsFound.size() == 0)
- {
- return 0.0f;
- }
- else
- {
- const float detailedIndex = (subIterator != 0) ? index + subIterator->getEstimatedProgress()
- : (float) index;
+ if (totalNumFiles < 0)
+ totalNumFiles = File (path).getNumberOfChildFiles (File::findFilesAndDirectories);
- return detailedIndex / (filesFound.size() + dirsFound.size());
- }
+ if (totalNumFiles <= 0)
+ return 0.0f;
+
+ const float detailedIndex = (subIterator != 0) ? index + subIterator->getEstimatedProgress()
+ : (float) index;
+
+ return detailedIndex / totalNumFiles;
}
END_JUCE_NAMESPACE
@@ -5594,165 +5576,20 @@ END_JUCE_NAMESPACE
/*** Start of inlined file: juce_File.cpp ***/
-#ifdef _MSC_VER
- #pragma warning (disable: 4514)
- #pragma warning (push)
-#endif
-
#if ! JUCE_WINDOWS
#include
#endif
BEGIN_JUCE_NAMESPACE
-#ifdef _MSC_VER
- #pragma warning (pop)
-#endif
-
-void* juce_fileOpen (const String& path, bool forWriting);
-void juce_fileClose (void* handle);
-int juce_fileWrite (void* handle, const void* buffer, int size);
-int64 juce_fileGetPosition (void* handle);
-int64 juce_fileSetPosition (void* handle, int64 pos);
-void juce_fileFlush (void* handle);
-
-bool juce_fileExists (const String& fileName, const bool dontCountDirectories);
-bool juce_isDirectory (const String& fileName);
-int64 juce_getFileSize (const String& fileName);
bool juce_canWriteToFile (const String& fileName);
bool juce_setFileReadOnly (const String& fileName, bool isReadOnly);
-
void juce_getFileTimes (const String& fileName, int64& modificationTime, int64& accessTime, int64& creationTime);
bool juce_setFileTimes (const String& fileName, int64 modificationTime, int64 accessTime, int64 creationTime);
-
-bool juce_deleteFile (const String& fileName);
bool juce_copyFile (const String& source, const String& dest);
bool juce_moveFile (const String& source, const String& dest);
-
-// this must also create all paths involved in the directory.
-void juce_createDirectory (const String& fileName);
-
bool juce_launchFile (const String& fileName, const String& parameters);
-const StringArray juce_getFileSystemRoots();
-const String juce_getVolumeLabel (const String& filenameOnVolume, int& volumeSerialNumber);
-
-// starts a directory search operation with a wildcard, returning a handle for
-// use in calls to juce_findFileNext.
-// juce_firstResultFile gets the name of the file (not the whole pathname) and
-// the other pointers, if non-null, are set based on the properties of the file.
-void* juce_findFileStart (const String& directory, const String& wildCard, String& firstResultFile,
- bool* isDirectory, bool* isHidden, int64* fileSize, Time* modTime,
- Time* creationTime, bool* isReadOnly);
-
-// returns false when no more files are found
-bool juce_findFileNext (void* handle, String& resultFile,
- bool* isDirectory, bool* isHidden, int64* fileSize,
- Time* modTime, Time* creationTime, bool* isReadOnly);
-
-void juce_findFileClose (void* handle);
-
-static const String juce_addTrailingSeparator (const String& path)
-{
- return path.endsWithChar (File::separator) ? path
- : path + File::separator;
-}
-
-static const String parseAbsolutePath (String path)
-{
- if (path.isEmpty())
- return String::empty;
-
-#if JUCE_WINDOWS
- // Windows..
- path = path.replaceCharacter ('/', '\\');
-
- if (path.startsWithChar (File::separator))
- {
- if (path[1] != File::separator)
- {
- /* When you supply a raw string to the File object constructor, it must be an absolute path.
- If you're trying to parse a string that may be either a relative path or an absolute path,
- you MUST provide a context against which the partial path can be evaluated - you can do
- this by simply using File::getChildFile() instead of the File constructor. E.g. saying
- "File::getCurrentWorkingDirectory().getChildFile (myUnknownPath)" would return an absolute
- path if that's what was supplied, or would evaluate a partial path relative to the CWD.
- */
- jassertfalse
-
- path = File::getCurrentWorkingDirectory().getFullPathName().substring (0, 2) + path;
- }
- }
- else if (path.indexOfChar (':') < 0)
- {
- if (path.isEmpty())
- return String::empty;
-
- /* When you supply a raw string to the File object constructor, it must be an absolute path.
- If you're trying to parse a string that may be either a relative path or an absolute path,
- you MUST provide a context against which the partial path can be evaluated - you can do
- this by simply using File::getChildFile() instead of the File constructor. E.g. saying
- "File::getCurrentWorkingDirectory().getChildFile (myUnknownPath)" would return an absolute
- path if that's what was supplied, or would evaluate a partial path relative to the CWD.
- */
- jassertfalse
-
- return File::getCurrentWorkingDirectory().getChildFile (path).getFullPathName();
- }
-#else
- // Mac or Linux..
- path = path.replaceCharacter ('\\', '/');
-
- if (path.startsWithChar ('~'))
- {
- const char* homeDir = 0;
-
- if (path[1] == File::separator || path[1] == 0)
- {
- // expand a name of the form "~/abc"
- path = File::getSpecialLocation (File::userHomeDirectory).getFullPathName()
- + path.substring (1);
- }
- else
- {
- // expand a name of type "~dave/abc"
- const String userName (path.substring (1).upToFirstOccurrenceOf ("/", false, false));
-
- struct passwd* const pw = getpwnam (userName.toUTF8());
- if (pw != 0)
- {
- String home (homeDir);
-
- if (home.endsWithChar (File::separator))
- home [home.length() - 1] = 0;
-
- path = String (pw->pw_dir)
- + path.substring (userName.length());
- }
- }
- }
- else if (! path.startsWithChar (File::separator))
- {
- /* When you supply a raw string to the File object constructor, it must be an absolute path.
- If you're trying to parse a string that may be either a relative path or an absolute path,
- you MUST provide a context against which the partial path can be evaluated - you can do
- this by simply using File::getChildFile() instead of the File constructor. E.g. saying
- "File::getCurrentWorkingDirectory().getChildFile (myUnknownPath)" would return an absolute
- path if that's what was supplied, or would evaluate a partial path relative to the CWD.
- */
- jassert (path.startsWith ("./") || path.startsWith ("../")); // (assume that a path "./xyz" is deliberately intended to be relative to the CWD)
-
- return File::getCurrentWorkingDirectory().getChildFile (path).getFullPathName();
- }
-#endif
-
- int len = path.length();
- while (--len > 0 && path [len] == File::separator)
- path [len] = 0;
-
- return path;
-}
-
const File File::nonexistent;
File::File (const String& fullPathName)
@@ -5787,6 +5624,90 @@ File& File::operator= (const File& other)
return *this;
}
+const String File::parseAbsolutePath (const String& p)
+{
+ if (p.isEmpty())
+ return String::empty;
+
+#if JUCE_WINDOWS
+ // Windows..
+ String path (p.replaceCharacter ('/', '\\'));
+
+ if (path.startsWithChar (File::separator))
+ {
+ if (path[1] != File::separator)
+ {
+ /* When you supply a raw string to the File object constructor, it must be an absolute path.
+ If you're trying to parse a string that may be either a relative path or an absolute path,
+ you MUST provide a context against which the partial path can be evaluated - you can do
+ this by simply using File::getChildFile() instead of the File constructor. E.g. saying
+ "File::getCurrentWorkingDirectory().getChildFile (myUnknownPath)" would return an absolute
+ path if that's what was supplied, or would evaluate a partial path relative to the CWD.
+ */
+ jassertfalse
+
+ path = File::getCurrentWorkingDirectory().getFullPathName().substring (0, 2) + path;
+ }
+ }
+ else if (! path.containsChar (':'))
+ {
+ /* When you supply a raw string to the File object constructor, it must be an absolute path.
+ If you're trying to parse a string that may be either a relative path or an absolute path,
+ you MUST provide a context against which the partial path can be evaluated - you can do
+ this by simply using File::getChildFile() instead of the File constructor. E.g. saying
+ "File::getCurrentWorkingDirectory().getChildFile (myUnknownPath)" would return an absolute
+ path if that's what was supplied, or would evaluate a partial path relative to the CWD.
+ */
+ jassertfalse
+
+ return File::getCurrentWorkingDirectory().getChildFile (path).getFullPathName();
+ }
+#else
+ // Mac or Linux..
+ String path (p.replaceCharacter ('\\', '/'));
+
+ if (path.startsWithChar ('~'))
+ {
+ if (path[1] == File::separator || path[1] == 0)
+ {
+ // expand a name of the form "~/abc"
+ path = File::getSpecialLocation (File::userHomeDirectory).getFullPathName()
+ + path.substring (1);
+ }
+ else
+ {
+ // expand a name of type "~dave/abc"
+ const String userName (path.substring (1).upToFirstOccurrenceOf ("/", false, false));
+
+ struct passwd* const pw = getpwnam (userName.toUTF8());
+ if (pw != 0)
+ path = addTrailingSeparator (pw->pw_dir) + path.fromFirstOccurrenceOf ("/", false, false);
+ }
+ }
+ else if (! path.startsWithChar (File::separator))
+ {
+ /* When you supply a raw string to the File object constructor, it must be an absolute path.
+ If you're trying to parse a string that may be either a relative path or an absolute path,
+ you MUST provide a context against which the partial path can be evaluated - you can do
+ this by simply using File::getChildFile() instead of the File constructor. E.g. saying
+ "File::getCurrentWorkingDirectory().getChildFile (myUnknownPath)" would return an absolute
+ path if that's what was supplied, or would evaluate a partial path relative to the CWD.
+ */
+ jassert (path.startsWith ("./") || path.startsWith ("../")); // (assume that a path "./xyz" is deliberately intended to be relative to the CWD)
+
+ return File::getCurrentWorkingDirectory().getChildFile (path).getFullPathName();
+ }
+#endif
+
+ return path.trimCharactersAtEnd (separatorString);
+}
+
+const String File::addTrailingSeparator (const String& path)
+{
+ return path.endsWithChar (File::separator) ? path
+ : path + File::separator;
+}
+
#if JUCE_LINUX
#define NAMES_ARE_CASE_SENSITIVE 1
#endif
@@ -5802,7 +5723,6 @@ bool File::areFileNamesCaseSensitive()
bool File::operator== (const File& other) const
{
- // case-insensitive on Windows, but not on linux.
#if NAMES_ARE_CASE_SENSITIVE
return fullPath == other.fullPath;
#else
@@ -5815,19 +5735,22 @@ bool File::operator!= (const File& other) const
return ! operator== (other);
}
-bool File::exists() const
+bool File::operator< (const File& other) const
{
- return juce_fileExists (fullPath, false);
+#if NAMES_ARE_CASE_SENSITIVE
+ return fullPath < other.fullPath;
+#else
+ return fullPath.compareIgnoreCase (other.fullPath) < 0;
+#endif
}
-bool File::existsAsFile() const
+bool File::operator> (const File& other) const
{
- return juce_fileExists (fullPath, true);
-}
-
-bool File::isDirectory() const
-{
- return juce_isDirectory (fullPath);
+#if NAMES_ARE_CASE_SENSITIVE
+ return fullPath > other.fullPath;
+#else
+ return fullPath.compareIgnoreCase (other.fullPath) > 0;
+#endif
}
bool File::hasWriteAccess() const
@@ -5865,12 +5788,6 @@ bool File::setReadOnly (const bool shouldBeReadOnly,
return juce_setFileReadOnly (fullPath, shouldBeReadOnly) && worked;
}
-bool File::deleteFile() const
-{
- return (! exists())
- || juce_deleteFile (fullPath);
-}
-
bool File::deleteRecursively() const
{
bool worked = true;
@@ -6062,7 +5979,7 @@ const File File::getChildFile (String relativePath) const
}
}
- return File (juce_addTrailingSeparator (path) + relativePath);
+ return File (addTrailingSeparator (path) + relativePath);
}
}
@@ -6071,11 +5988,6 @@ const File File::getSiblingFile (const String& fileName) const
return getParentDirectory().getChildFile (fileName);
}
-int64 File::getSize() const
-{
- return juce_getFileSize (fullPath);
-}
-
const String File::descriptionOfSizeInBytes (const int64 bytes)
{
if (bytes == 1)
@@ -6102,22 +6014,19 @@ const String File::descriptionOfSizeInBytes (const int64 bytes)
bool File::create() const
{
- if (! exists())
+ if (exists())
+ return true;
+
{
const File parentDir (getParentDirectory());
if (parentDir == *this || ! parentDir.createDirectory())
return false;
- void* const fh = juce_fileOpen (fullPath, true);
-
- if (fh == 0)
- return false;
-
- juce_fileClose (fh);
+ FileOutputStream fo (*this, 8);
}
- return true;
+ return exists();
}
bool File::createDirectory() const
@@ -6129,13 +6038,7 @@ bool File::createDirectory() const
if (parentDir == *this || ! parentDir.createDirectory())
return false;
- String dir (fullPath);
-
- while (dir.endsWithChar (separator))
- dir [dir.length() - 1] = 0;
-
- juce_createDirectory (dir);
-
+ createDirectoryInternal (fullPath.trimCharactersAtEnd (separatorString));
return isDirectory();
}
@@ -6196,14 +6099,11 @@ const String File::loadFileAsString() const
return in.readEntireStreamAsString();
}
-static inline bool fileTypeMatches (const int whatToLookFor,
- const bool isDir,
- const bool isHidden)
+bool File::fileTypeMatches (const int whatToLookFor, const bool isDir, const bool isHidden)
{
- return (whatToLookFor & (isDir ? File::findDirectories
- : File::findFiles)) != 0
- && ((! isHidden)
- || (whatToLookFor & File::ignoreHiddenFiles) == 0);
+ return (whatToLookFor & (isDir ? findDirectories
+ : findFiles)) != 0
+ && ((! isHidden) || (whatToLookFor & File::ignoreHiddenFiles) == 0);
}
int File::findChildFiles (Array& results,
@@ -6216,50 +6116,32 @@ int File::findChildFiles (Array& results,
int total = 0;
- // find child files or directories in this directory first..
if (isDirectory())
{
- const String path (juce_addTrailingSeparator (fullPath));
-
- String filename;
+ // find child files or directories in this directory first..
+ String path (addTrailingSeparator (fullPath)), filename;
bool itemIsDirectory, itemIsHidden;
- void* const handle = juce_findFileStart (path, wildCardPattern, filename,
- &itemIsDirectory, &itemIsHidden,
- 0, 0, 0, 0);
+ DirectoryIterator::NativeIterator i (path, wildCardPattern);
- if (handle != 0)
+ while (i.next (filename, &itemIsDirectory, &itemIsHidden, 0, 0, 0, 0))
{
- do
+ if (! filename.containsOnly ("."))
{
- if (fileTypeMatches (whatToLookFor, itemIsDirectory, itemIsHidden)
- && ! filename.containsOnly ("."))
+ const File fileFound (path + filename, 0);
+
+ if (fileTypeMatches (whatToLookFor, itemIsDirectory, itemIsHidden))
{
- results.add (File (path + filename, 0));
+ results.add (fileFound);
++total;
}
- } while (juce_findFileNext (handle, filename, &itemIsDirectory, &itemIsHidden, 0, 0, 0, 0));
-
- juce_findFileClose (handle);
- }
- }
- else
- {
- // trying to search for files inside a non-directory?
- //jassertfalse
- }
-
- // and recurse down if required.
- if (searchRecursively)
- {
- Array subDirectories;
- findChildFiles (subDirectories, File::findDirectories, false);
-
- for (int i = 0; i < subDirectories.size(); ++i)
- {
- total += subDirectories.getReference(i).findChildFiles (results, whatToLookFor,
- true, wildCardPattern);
+ if (searchRecursively && itemIsDirectory
+ && fileTypeMatches (whatToLookFor | findDirectories, true, itemIsHidden))
+ {
+ total += fileFound.findChildFiles (results, whatToLookFor, true, wildCardPattern);
+ }
+ }
}
}
@@ -6279,24 +6161,12 @@ int File::getNumberOfChildFiles (const int whatToLookFor,
String filename;
bool itemIsDirectory, itemIsHidden;
- void* const handle = juce_findFileStart (fullPath, wildCardPattern, filename,
- &itemIsDirectory, &itemIsHidden,
- 0, 0, 0, 0);
+ DirectoryIterator::NativeIterator i (*this, wildCardPattern);
- if (handle != 0)
- {
- do
- {
- if (fileTypeMatches (whatToLookFor, itemIsDirectory, itemIsHidden)
- && ! filename.containsOnly ("."))
- {
- ++count;
- }
-
- } while (juce_findFileNext (handle, filename, &itemIsDirectory, &itemIsHidden, 0, 0, 0, 0));
-
- juce_findFileClose (handle);
- }
+ while (i.next (filename, &itemIsDirectory, &itemIsHidden, 0, 0, 0, 0))
+ if (fileTypeMatches (whatToLookFor, itemIsDirectory, itemIsHidden)
+ && ! filename.containsOnly ("."))
+ ++count;
}
else
{
@@ -6309,33 +6179,19 @@ int File::getNumberOfChildFiles (const int whatToLookFor,
bool File::containsSubDirectories() const
{
- bool result = false;
-
if (isDirectory())
{
String filename;
- bool itemIsDirectory, itemIsHidden;
- void* const handle = juce_findFileStart (juce_addTrailingSeparator (fullPath),
- "*", filename,
- &itemIsDirectory, &itemIsHidden, 0, 0, 0, 0);
+ bool itemIsDirectory;
- if (handle != 0)
- {
- do
- {
- if (itemIsDirectory)
- {
- result = true;
- break;
- }
+ DirectoryIterator::NativeIterator i (*this, "*");
- } while (juce_findFileNext (handle, filename, &itemIsDirectory, &itemIsHidden, 0, 0, 0, 0));
-
- juce_findFileClose (handle);
- }
+ while (i.next (filename, &itemIsDirectory, 0, 0, 0, 0, 0))
+ if (itemIsDirectory)
+ return true;
}
- return result;
+ return false;
}
const File File::getNonexistentChildFile (const String& prefix_,
@@ -6585,8 +6441,8 @@ const String File::getRelativePathFrom (const File& dir) const
thisPath [len] = 0;
}
- String dirPath (juce_addTrailingSeparator ((dir.existsAsFile()) ? dir.getParentDirectory().getFullPathName()
- : dir.fullPath));
+ String dirPath (addTrailingSeparator (dir.existsAsFile() ? dir.getParentDirectory().getFullPathName()
+ : dir.fullPath));
const int len = jmin (thisPath.length(), dirPath.length());
int commonBitLength = 0;
@@ -6636,28 +6492,6 @@ const String File::getRelativePathFrom (const File& dir) const
return thisPath;
}
-void File::findFileSystemRoots (Array& destArray)
-{
- const StringArray roots (juce_getFileSystemRoots());
-
- for (int i = 0; i < roots.size(); ++i)
- destArray.add (File (roots[i]));
-}
-
-const String File::getVolumeLabel() const
-{
- int serialNum;
- return juce_getVolumeLabel (fullPath, serialNum);
-}
-
-int File::getVolumeSerialNumber() const
-{
- int serialNum;
- juce_getVolumeLabel (fullPath, serialNum);
-
- return serialNum;
-}
-
const File File::createTempFile (const String& fileNameEnding)
{
const File tempFile (getSpecialLocation (tempDirectory)
@@ -6677,7 +6511,7 @@ END_JUCE_NAMESPACE
/*** Start of inlined file: juce_FileInputStream.cpp ***/
BEGIN_JUCE_NAMESPACE
-void* juce_fileOpen (const String& path, bool forWriting);
+void* juce_fileOpen (const File& file, bool forWriting);
void juce_fileClose (void* handle);
int juce_fileRead (void* handle, void* buffer, int size);
int64 juce_fileSetPosition (void* handle, int64 pos);
@@ -6689,7 +6523,7 @@ FileInputStream::FileInputStream (const File& f)
{
totalSize = f.getSize();
- fileHandle = juce_fileOpen (f.getFullPathName(), false);
+ fileHandle = juce_fileOpen (f, false);
}
FileInputStream::~FileInputStream()
@@ -6747,11 +6581,9 @@ END_JUCE_NAMESPACE
/*** Start of inlined file: juce_FileOutputStream.cpp ***/
BEGIN_JUCE_NAMESPACE
-void* juce_fileOpen (const String& path, bool forWriting);
+void* juce_fileOpen (const File& file, bool forWriting);
void juce_fileClose (void* handle);
int juce_fileWrite (void* handle, const void* buffer, int size);
-void juce_fileFlush (void* handle);
-int64 juce_fileGetPosition (void* handle);
int64 juce_fileSetPosition (void* handle, int64 pos);
FileOutputStream::FileOutputStream (const File& f,
@@ -6760,11 +6592,11 @@ FileOutputStream::FileOutputStream (const File& f,
bufferSize (bufferSize_),
bytesInBuffer (0)
{
- fileHandle = juce_fileOpen (f.getFullPathName(), true);
+ fileHandle = juce_fileOpen (f, true);
if (fileHandle != 0)
{
- currentPosition = juce_fileGetPosition (fileHandle);
+ currentPosition = getPositionInternal();
if (currentPosition < 0)
{
@@ -6808,7 +6640,7 @@ void FileOutputStream::flush()
bytesInBuffer = 0;
}
- juce_fileFlush (fileHandle);
+ flushInternal();
}
bool FileOutputStream::write (const void* const src, const int numBytes)
@@ -11634,10 +11466,7 @@ const String String::trimCharactersAtStart (const String& charactersToTrim) cons
while (charactersToTrim.containsChar (*t))
++t;
- if (t == text)
- return *this;
-
- return String (t);
+ return t == text ? *this : String (t);
}
const String String::trimCharactersAtEnd (const String& charactersToTrim) const
@@ -11645,12 +11474,17 @@ const String String::trimCharactersAtEnd (const String& charactersToTrim) const
if (isEmpty())
return empty;
- const juce_wchar* endT = text + (length() - 1);
+ const int len = length();
+ const juce_wchar* endT = text + (len - 1);
+ int numToRemove = 0;
- while (endT >= text && charactersToTrim.containsChar (*endT))
+ while (numToRemove < len && charactersToTrim.containsChar (*endT))
+ {
+ ++numToRemove;
--endT;
+ }
- return String (text, (int) (++endT - text));
+ return numToRemove > 0 ? String (text, len - numToRemove) : *this;
}
const String String::retainCharacters (const String& charactersToRetain) const
@@ -12699,10 +12533,10 @@ void StringArray::appendNumbersToDuplicates (const bool ignoreCase,
const juce_wchar* postNumberString)
{
if (preNumberString == 0)
- preNumberString = T(" (");
+ preNumberString = L" (";
if (postNumberString == 0)
- postNumberString = T(")");
+ postNumberString = L")";
for (int i = 0; i < size() - 1; ++i)
{
@@ -13591,9 +13425,7 @@ const String XmlDocument::expandExternalEntity (const String& entity)
{
if (dtdText.isNotEmpty())
{
- while (dtdText.endsWithChar ('>'))
- dtdText = dtdText.dropLastCharacters (1);
-
+ dtdText = dtdText.trimCharactersAtEnd (">");
tokenisedDTD.addTokens (dtdText, true);
if (tokenisedDTD [tokenisedDTD.size() - 2].equalsIgnoreCase ("system")
@@ -13645,12 +13477,7 @@ const String XmlDocument::expandExternalEntity (const String& entity)
{
if (tokenisedDTD[i - 1].equalsIgnoreCase ("'))
- ent = ent.dropLastCharacters (1);
-
- ent = ent.trim().unquoted();
+ String ent (tokenisedDTD [i + 1].trimCharactersAtEnd (">").trim().unquoted());
// check for sub-entities..
int ampersand = ent.indexOfChar ('&');
@@ -13693,24 +13520,12 @@ const String XmlDocument::getParameterEntity (const String& entity)
if (tokenisedDTD [i - 1] == "%"
&& tokenisedDTD [i - 2].equalsIgnoreCase ("'))
- ent = ent.dropLastCharacters (1);
+ const String ent (tokenisedDTD [i + 1].trimCharactersAtEnd (">"));
if (ent.equalsIgnoreCase ("system"))
- {
- String filename (tokenisedDTD [i + 2]);
-
- while (filename.endsWithChar ('>'))
- filename = filename.dropLastCharacters (1);
-
- return getFileContents (filename);
- }
+ return getFileContents (tokenisedDTD [i + 2].trimCharactersAtEnd (">"));
else
- {
return ent.trim().unquoted();
- }
}
}
}
@@ -14726,7 +14541,7 @@ bool XmlElement::isTextElement() const throw()
return tagName.isEmpty();
}
-static const juce_wchar* const juce_xmltextContentAttributeName = T("text");
+static const juce_wchar* const juce_xmltextContentAttributeName = L"text";
const String XmlElement::getText() const throw()
{
@@ -21400,8 +21215,8 @@ const StringPairArray WavAudioFormat::createBWAVMetadata (const String& descript
m.set (bwavDescription, description);
m.set (bwavOriginator, originator);
m.set (bwavOriginatorRef, originatorRef);
- m.set (bwavOriginationDate, date.formatted (T("%Y-%m-%d")));
- m.set (bwavOriginationTime, date.formatted (T("%H:%M:%S")));
+ m.set (bwavOriginationDate, date.formatted ("%Y-%m-%d"));
+ m.set (bwavOriginationTime, date.formatted ("%H:%M:%S"));
m.set (bwavTimeReference, String (timeReferenceSamples));
m.set (bwavCodingHistory, codingHistory);
@@ -56342,21 +56157,11 @@ END_JUCE_NAMESPACE
/*** Start of inlined file: juce_DirectoryContentsList.cpp ***/
BEGIN_JUCE_NAMESPACE
-void* juce_findFileStart (const String& directory, const String& wildCard, String& firstResultFile,
- bool* isDirectory, bool* isHidden, int64* fileSize, Time* modTime,
- Time* creationTime, bool* isReadOnly);
-bool juce_findFileNext (void* handle, String& resultFile,
- bool* isDirectory, bool* isHidden, int64* fileSize,
- Time* modTime, Time* creationTime, bool* isReadOnly);
-void juce_findFileClose (void* handle);
-
DirectoryContentsList::DirectoryContentsList (const FileFilter* const fileFilter_,
TimeSliceThread& thread_)
: fileFilter (fileFilter_),
thread (thread_),
- includeDirectories (false),
- includeFiles (false),
- ignoreHiddenFiles (true),
+ fileTypeFlags (File::ignoreHiddenFiles | File::findFiles),
fileFindHandle (0),
shouldStop (true)
{
@@ -56369,7 +56174,13 @@ DirectoryContentsList::~DirectoryContentsList()
void DirectoryContentsList::setIgnoresHiddenFiles (const bool shouldIgnoreHiddenFiles)
{
- ignoreHiddenFiles = shouldIgnoreHiddenFiles;
+ setTypeFlags (shouldIgnoreHiddenFiles ? (fileTypeFlags | File::ignoreHiddenFiles)
+ : (fileTypeFlags & ~File::ignoreHiddenFiles));
+}
+
+bool DirectoryContentsList::ignoresHiddenFiles() const
+{
+ return (fileTypeFlags & File::ignoreHiddenFiles) != 0;
}
const File& DirectoryContentsList::getDirectory() const
@@ -56378,19 +56189,32 @@ const File& DirectoryContentsList::getDirectory() const
}
void DirectoryContentsList::setDirectory (const File& directory,
- const bool includeDirectories_,
- const bool includeFiles_)
+ const bool includeDirectories,
+ const bool includeFiles)
{
- if (directory != root
- || includeDirectories != includeDirectories_
- || includeFiles != includeFiles_)
+ jassert (includeDirectories || includeFiles); // you have to speciify at least one of these!
+
+ if (directory != root)
{
clear();
-
root = directory;
- includeDirectories = includeDirectories_;
- includeFiles = includeFiles_;
+ // (this forces a refresh when setTypeFlags() is called, rather than triggering two refreshes)
+ fileTypeFlags &= ~(File::findDirectories | File::findFiles);
+ }
+
+ int newFlags = fileTypeFlags;
+ if (includeDirectories) newFlags |= File::findDirectories; else newFlags &= ~File::findDirectories;
+ if (includeFiles) newFlags |= File::findFiles; else newFlags &= ~File::findFiles;
+
+ setTypeFlags (newFlags);
+}
+
+void DirectoryContentsList::setTypeFlags (const int newFlags)
+{
+ if (fileTypeFlags != newFlags)
+ {
+ fileTypeFlags = newFlags;
refresh();
}
}
@@ -56400,11 +56224,7 @@ void DirectoryContentsList::clear()
shouldStop = true;
thread.removeTimeSliceClient (this);
- if (fileFindHandle != 0)
- {
- juce_findFileClose (fileFindHandle);
- fileFindHandle = 0;
- }
+ fileFindHandle = 0;
if (files.size() > 0)
{
@@ -56419,36 +56239,8 @@ void DirectoryContentsList::refresh()
if (root.isDirectory())
{
- String fileFound;
- bool fileFoundIsDir, isHidden, isReadOnly;
- int64 fileSize;
- Time modTime, creationTime;
-
- String path (root.getFullPathName());
- if (! path.endsWithChar (File::separator))
- path += File::separator;
-
- jassert (fileFindHandle == 0);
-
- fileFindHandle = juce_findFileStart (path, "*", fileFound,
- &fileFoundIsDir,
- &isHidden,
- &fileSize,
- &modTime,
- &creationTime,
- &isReadOnly);
-
- if (fileFindHandle != 0 && fileFound.isNotEmpty())
- {
- if (addFile (fileFound, fileFoundIsDir, isHidden,
- fileSize, modTime, creationTime, isReadOnly))
- {
- changed();
- }
- }
-
+ fileFindHandle = new DirectoryIterator (root, false, "*", fileTypeFlags);
shouldStop = false;
-
thread.addTimeSliceClient (this);
}
}
@@ -56523,20 +56315,15 @@ bool DirectoryContentsList::checkNextFile (bool& hasChanged)
{
if (fileFindHandle != 0)
{
- String fileFound;
bool fileFoundIsDir, isHidden, isReadOnly;
int64 fileSize;
Time modTime, creationTime;
- if (juce_findFileNext (fileFindHandle, fileFound,
- &fileFoundIsDir, &isHidden,
- &fileSize,
- &modTime,
- &creationTime,
- &isReadOnly))
+ if (fileFindHandle->next (&fileFoundIsDir, &isHidden, &fileSize,
+ &modTime, &creationTime, &isReadOnly))
{
- if (addFile (fileFound, fileFoundIsDir, isHidden, fileSize,
- modTime, creationTime, isReadOnly))
+ if (addFile (fileFindHandle->getFile(), fileFoundIsDir,
+ fileSize, modTime, creationTime, isReadOnly))
{
hasChanged = true;
}
@@ -56545,7 +56332,6 @@ bool DirectoryContentsList::checkNextFile (bool& hasChanged)
}
else
{
- juce_findFileClose (fileFindHandle);
fileFindHandle = 0;
}
}
@@ -56564,29 +56350,20 @@ int DirectoryContentsList::compareElements (const DirectoryContentsList::FileInf
return first->filename.compareIgnoreCase (second->filename);
}
-bool DirectoryContentsList::addFile (const String& filename,
+bool DirectoryContentsList::addFile (const File& file,
const bool isDir,
- const bool isHidden,
const int64 fileSize,
const Time& modTime,
const Time& creationTime,
const bool isReadOnly)
{
- if (filename == ".."
- || filename == "."
- || (ignoreHiddenFiles && isHidden))
- return false;
-
- const File file (root.getChildFile (filename));
-
- if (((isDir && includeDirectories) || ((! isDir) && includeFiles))
- && (fileFilter == 0
- || ((! isDir) && fileFilter->isFileSuitable (file))
- || (isDir && fileFilter->isDirectorySuitable (file))))
+ if (fileFilter == 0
+ || ((! isDir) && fileFilter->isFileSuitable (file))
+ || (isDir && fileFilter->isDirectorySuitable (file)))
{
ScopedPointer info (new FileInfo());
- info->filename = filename;
+ info->filename = file.getFileName();
info->fileSize = fileSize;
info->modificationTime = modTime;
info->creationTime = creationTime;
@@ -56803,7 +56580,7 @@ void FileBrowserComponent::setRoot (const File& newRootDirectory)
String path (newRootDirectory.getFullPathName());
if (path.isEmpty())
- path += File::separator;
+ path = File::separatorString;
StringArray rootNames, rootPaths;
getRoots (rootNames, rootPaths);
@@ -56831,7 +56608,7 @@ void FileBrowserComponent::setRoot (const File& newRootDirectory)
String currentRootName (currentRoot.getFullPathName());
if (currentRootName.isEmpty())
- currentRootName += File::separator;
+ currentRootName = File::separatorString;
currentPathBox->setText (currentRootName, true);
@@ -57527,7 +57304,7 @@ public:
{
newFile = root.getChildFile (fileInfo->filename);
newFileSize = File::descriptionOfSizeInBytes (fileInfo->fileSize);
- newModTime = fileInfo->modificationTime.formatted (T("%d %b '%y %H:%M"));
+ newModTime = fileInfo->modificationTime.formatted ("%d %b '%y %H:%M");
}
if (newFile != file
@@ -58147,7 +57924,7 @@ public:
&& parentContentsList_->getFileInfo (indexInContentsList_, fileInfo))
{
fileSize = File::descriptionOfSizeInBytes (fileInfo.fileSize);
- modTime = fileInfo.modificationTime.formatted (T("%d %b '%y %H:%M"));
+ modTime = fileInfo.modificationTime.formatted ("%d %b '%y %H:%M");
isDirectory = fileInfo.isDirectory;
}
else
@@ -212038,22 +211815,24 @@ void InterProcessLock::exit()
#define INVALID_FILE_ATTRIBUTES ((DWORD) -1)
#endif
-const juce_wchar File::separator = '\\';
-const juce_wchar* File::separatorString = T("\\");
+const juce_wchar File::separator = '\\';
+const String File::separatorString ("\\");
-bool juce_fileExists (const String& fileName, const bool dontCountDirectories)
+bool File::exists() const
{
- if (fileName.isEmpty())
- return false;
-
- const DWORD attr = GetFileAttributes (fileName);
- return dontCountDirectories ? ((attr & FILE_ATTRIBUTE_DIRECTORY) == 0)
- : (attr != INVALID_FILE_ATTRIBUTES);
+ return fullPath.isNotEmpty()
+ && GetFileAttributes (fullPath) != INVALID_FILE_ATTRIBUTES;
}
-bool juce_isDirectory (const String& fileName)
+bool File::existsAsFile() const
{
- const DWORD attr = GetFileAttributes (fileName);
+ return fullPath.isNotEmpty()
+ && (GetFileAttributes (fullPath) & FILE_ATTRIBUTE_DIRECTORY) == 0;
+}
+
+bool File::isDirectory() const
+{
+ const DWORD attr = GetFileAttributes (fullPath);
return ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) && (attr != INVALID_FILE_ATTRIBUTES);
}
@@ -212086,12 +211865,14 @@ bool File::isHidden() const
return (GetFileAttributes (getFullPathName()) & FILE_ATTRIBUTE_HIDDEN) != 0;
}
-bool juce_deleteFile (const String& fileName)
+bool File::deleteFile() const
{
- if (juce_isDirectory (fileName))
- return RemoveDirectory (fileName) != 0;
-
- return DeleteFile (fileName) != 0;
+ if (! exists())
+ return true;
+ else if (isDirectory())
+ return RemoveDirectory (fullPath) != 0;
+ else
+ return DeleteFile (fullPath) != 0;
}
bool File::moveToTrash() const
@@ -212125,20 +211906,19 @@ bool juce_copyFile (const String& source, const String& dest)
return CopyFile (source, dest, false) != 0;
}
-void juce_createDirectory (const String& fileName)
+void File::createDirectoryInternal (const String& fileName) const
{
- if (! juce_fileExists (fileName, true))
- CreateDirectory (fileName, 0);
+ CreateDirectory (fileName, 0);
}
// return 0 if not possible
-void* juce_fileOpen (const String& fileName, bool forWriting)
+void* juce_fileOpen (const File& file, bool forWriting)
{
HANDLE h;
if (forWriting)
{
- h = CreateFile (fileName, GENERIC_WRITE, FILE_SHARE_READ, 0,
+ h = CreateFile (file.getFullPathName(), GENERIC_WRITE, FILE_SHARE_READ, 0,
OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
if (h != INVALID_HANDLE_VALUE)
@@ -212148,7 +211928,7 @@ void* juce_fileOpen (const String& fileName, bool forWriting)
}
else
{
- h = CreateFile (fileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0,
+ h = CreateFile (file.getFullPathName(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, 0);
if (h == INVALID_HANDLE_VALUE)
@@ -212185,24 +211965,28 @@ int64 juce_fileSetPosition (void* handle, int64 pos)
return li.QuadPart;
}
-int64 juce_fileGetPosition (void* handle)
+int64 FileOutputStream::getPositionInternal() const
{
+ if (fileHandle == 0)
+ return -1;
+
LARGE_INTEGER li;
li.QuadPart = 0;
- li.LowPart = SetFilePointer ((HANDLE) handle, 0, &li.HighPart, FILE_CURRENT); // (returns -1 if it fails)
+ li.LowPart = SetFilePointer ((HANDLE) fileHandle, 0, &li.HighPart, FILE_CURRENT); // (returns -1 if it fails)
return jmax ((int64) 0, li.QuadPart);
}
-void juce_fileFlush (void* handle)
+void FileOutputStream::flushInternal()
{
- FlushFileBuffers ((HANDLE) handle);
+ if (fileHandle != 0)
+ FlushFileBuffers ((HANDLE) fileHandle);
}
-int64 juce_getFileSize (const String& fileName)
+int64 File::getSize() const
{
WIN32_FILE_ATTRIBUTE_DATA attributes;
- if (GetFileAttributesEx (fileName, GetFileExInfoStandard, &attributes))
+ if (GetFileAttributesEx (fullPath, GetFileExInfoStandard, &attributes))
return (((int64) attributes.nFileSizeHigh) << 32) | attributes.nFileSizeLow;
return 0;
@@ -212265,8 +212049,7 @@ bool juce_setFileTimes (const String& fileName,
return ok;
}
-// return '\0' separated list of strings
-const StringArray juce_getFileSystemRoots()
+void File::findFileSystemRoots (Array& destArray)
{
TCHAR buffer [2048];
buffer[0] = 0;
@@ -212285,7 +212068,9 @@ const StringArray juce_getFileSystemRoots()
}
roots.sort (true);
- return roots;
+
+ for (int i = 0; i < roots.size(); ++i)
+ destArray.add (roots [i]);
}
static const String getDriveFromPath (const String& path)
@@ -212296,21 +212081,26 @@ static const String getDriveFromPath (const String& path)
return path;
}
-const String juce_getVolumeLabel (const String& filenameOnVolume,
- int& volumeSerialNumber)
+const String File::getVolumeLabel() const
+{
+ TCHAR dest[64];
+ if (! GetVolumeInformation (getDriveFromPath (getFullPathName()), dest,
+ numElementsInArray (dest), 0, 0, 0, 0, 0))
+ dest[0] = 0;
+
+ return dest;
+}
+
+int File::getVolumeSerialNumber() const
{
TCHAR dest[64];
DWORD serialNum;
- if (! GetVolumeInformation (getDriveFromPath (filenameOnVolume), dest,
+ if (! GetVolumeInformation (getDriveFromPath (getFullPathName()), dest,
numElementsInArray (dest), &serialNum, 0, 0, 0, 0))
- {
- dest[0] = 0;
- serialNum = 0;
- }
+ return 0;
- volumeSerialNumber = serialNum;
- return dest;
+ return (int) serialNum;
}
static int64 getDiskSpaceInfo (const String& path, const bool total)
@@ -212494,78 +212284,76 @@ const File File::getLinkedTarget() const
return result;
}
-template
-static void getFindFileInfo (FindDataType& findData,
- String& filename, bool* const isDir, bool* const isHidden,
- int64* const fileSize, Time* const modTime, Time* const creationTime,
- bool* const isReadOnly)
+class DirectoryIterator::NativeIterator::Pimpl
{
- filename = findData.cFileName;
-
- if (isDir != 0)
- *isDir = ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0);
-
- if (isHidden != 0)
- *isHidden = ((findData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) != 0);
-
- if (fileSize != 0)
- *fileSize = findData.nFileSizeLow + (((int64) findData.nFileSizeHigh) << 32);
-
- if (modTime != 0)
- *modTime = fileTimeToTime (&findData.ftLastWriteTime);
-
- if (creationTime != 0)
- *creationTime = fileTimeToTime (&findData.ftCreationTime);
-
- if (isReadOnly != 0)
- *isReadOnly = ((findData.dwFileAttributes & FILE_ATTRIBUTE_READONLY) != 0);
-}
-
-void* juce_findFileStart (const String& directory, const String& wildCard, String& firstResult,
- bool* isDir, bool* isHidden, int64* fileSize,
- Time* modTime, Time* creationTime, bool* isReadOnly)
-{
- String wc (directory);
-
- if (! wc.endsWithChar (File::separator))
- wc += File::separator;
-
- wc += wildCard;
-
- WIN32_FIND_DATA findData;
- HANDLE h = FindFirstFile (wc, &findData);
-
- if (h != INVALID_HANDLE_VALUE)
+public:
+ Pimpl (const File& directory, const String& wildCard)
+ : directoryWithWildCard (File::addTrailingSeparator (directory.getFullPathName()) + wildCard),
+ handle (INVALID_HANDLE_VALUE)
{
- getFindFileInfo (findData, firstResult, isDir, isHidden, fileSize,
- modTime, creationTime, isReadOnly);
- return h;
}
- firstResult = String::empty;
- return 0;
-}
-
-bool juce_findFileNext (void* handle, String& resultFile,
- bool* isDir, bool* isHidden, int64* fileSize,
- Time* modTime, Time* creationTime, bool* isReadOnly)
-{
- WIN32_FIND_DATA findData;
-
- if (handle != 0 && FindNextFile ((HANDLE) handle, &findData) != 0)
+ ~Pimpl()
{
- getFindFileInfo (findData, resultFile, isDir, isHidden, fileSize,
- modTime, creationTime, isReadOnly);
+ if (handle != INVALID_HANDLE_VALUE)
+ FindClose (handle);
+ }
+
+ bool next (String& filenameFound,
+ bool* const isDir, bool* const isHidden, int64* const fileSize,
+ Time* const modTime, Time* const creationTime, bool* const isReadOnly)
+ {
+ WIN32_FIND_DATA findData;
+
+ if (handle == INVALID_HANDLE_VALUE)
+ {
+ handle = FindFirstFile (directoryWithWildCard, &findData);
+
+ if (handle == INVALID_HANDLE_VALUE)
+ return false;
+ }
+ else
+ {
+ if (FindNextFile (handle, &findData) == 0)
+ return false;
+ }
+
+ filenameFound = findData.cFileName;
+
+ if (isDir != 0) *isDir = ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0);
+ if (isHidden != 0) *isHidden = ((findData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) != 0);
+ if (fileSize != 0) *fileSize = findData.nFileSizeLow + (((int64) findData.nFileSizeHigh) << 32);
+ if (modTime != 0) *modTime = fileTimeToTime (&findData.ftLastWriteTime);
+ if (creationTime != 0) *creationTime = fileTimeToTime (&findData.ftCreationTime);
+ if (isReadOnly != 0) *isReadOnly = ((findData.dwFileAttributes & FILE_ATTRIBUTE_READONLY) != 0);
+
return true;
}
- resultFile = String::empty;
- return false;
+ juce_UseDebuggingNewOperator
+
+private:
+ const String directoryWithWildCard;
+ HANDLE handle;
+
+ Pimpl (const Pimpl&);
+ Pimpl& operator= (const Pimpl&);
+};
+
+DirectoryIterator::NativeIterator::NativeIterator (const File& directory, const String& wildCard)
+ : pimpl (new DirectoryIterator::NativeIterator::Pimpl (directory, wildCard))
+{
}
-void juce_findFileClose (void* handle)
+DirectoryIterator::NativeIterator::~NativeIterator()
{
- FindClose (handle);
+}
+
+bool DirectoryIterator::NativeIterator::next (String& filenameFound,
+ bool* const isDir, bool* const isHidden, int64* const fileSize,
+ Time* const modTime, Time* const creationTime, bool* const isReadOnly)
+{
+ return pimpl->next (filenameFound, isDir, isHidden, fileSize, modTime, creationTime, isReadOnly);
}
bool juce_launchFile (const String& fileName, const String& parameters)
@@ -227843,7 +227631,7 @@ void JUCE_CALLTYPE Thread::sleep (int millisecs)
}
const juce_wchar File::separator = '/';
-const juce_wchar* File::separatorString = L"/";
+const String File::separatorString ("/");
const File File::getCurrentWorkingDirectory()
{
@@ -227868,47 +227656,35 @@ bool File::setAsCurrentWorkingDirectory() const
return chdir (getFullPathName().toUTF8()) == 0;
}
-bool juce_copyFile (const String& s, const String& d);
-
static bool juce_stat (const String& fileName, struct stat& info)
{
return fileName.isNotEmpty()
&& (stat (fileName.toUTF8(), &info) == 0);
}
-bool juce_isDirectory (const String& fileName)
+bool File::isDirectory() const
{
struct stat info;
- return fileName.isEmpty()
- || (juce_stat (fileName, info)
- && ((info.st_mode & S_IFDIR) != 0));
+ return fullPath.isEmpty()
+ || (juce_stat (fullPath, info) && ((info.st_mode & S_IFDIR) != 0));
}
-bool juce_fileExists (const String& fileName, const bool dontCountDirectories)
+bool File::exists() const
{
- if (fileName.isEmpty())
- return false;
-
- const char* const fileNameUTF8 = fileName.toUTF8();
- bool exists = access (fileNameUTF8, F_OK) == 0;
-
- if (exists && dontCountDirectories)
- {
- struct stat info;
- const int res = stat (fileNameUTF8, &info);
-
- if (res == 0 && (info.st_mode & S_IFDIR) != 0)
- exists = false;
- }
-
- return exists;
+ return fullPath.isNotEmpty()
+ && access (fullPath.toUTF8(), F_OK) == 0;
}
-int64 juce_getFileSize (const String& fileName)
+bool File::existsAsFile() const
+{
+ return exists() && ! isDirectory();
+}
+
+int64 File::getSize() const
{
struct stat info;
- return juce_stat (fileName, info) ? info.st_size : 0;
+ return juce_stat (fullPath, info) ? info.st_size : 0;
}
bool juce_canWriteToFile (const String& fileName)
@@ -227916,14 +227692,36 @@ bool juce_canWriteToFile (const String& fileName)
return access (fileName.toUTF8(), W_OK) == 0;
}
-bool juce_deleteFile (const String& fileName)
+bool juce_setFileReadOnly (const String& fileName, bool isReadOnly)
{
- if (juce_isDirectory (fileName))
- return rmdir (fileName.toUTF8()) == 0;
+ struct stat info;
+ const int res = stat (fileName.toUTF8(), &info);
+ if (res != 0)
+ return false;
+
+ info.st_mode &= 0777; // Just permissions
+
+ if (isReadOnly)
+ info.st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
else
- return remove (fileName.toUTF8()) == 0;
+ // Give everybody write permission?
+ info.st_mode |= S_IWUSR | S_IWGRP | S_IWOTH;
+
+ return chmod (fileName.toUTF8(), info.st_mode) == 0;
}
+bool File::deleteFile() const
+{
+ if (! exists())
+ return true;
+ else if (isDirectory())
+ return rmdir (fullPath.toUTF8()) == 0;
+ else
+ return remove (fullPath.toUTF8()) == 0;
+}
+
+bool juce_copyFile (const String& s, const String& d);
+
bool juce_moveFile (const String& source, const String& dest)
{
if (rename (source.toUTF8(), dest.toUTF8()) == 0)
@@ -227932,29 +227730,29 @@ bool juce_moveFile (const String& source, const String& dest)
if (juce_canWriteToFile (source)
&& juce_copyFile (source, dest))
{
- if (juce_deleteFile (source))
+ if (File (source).deleteFile())
return true;
- juce_deleteFile (dest);
+ File (dest).deleteFile();
}
return false;
}
-void juce_createDirectory (const String& fileName)
+void File::createDirectoryInternal (const String& fileName) const
{
mkdir (fileName.toUTF8(), 0777);
}
-void* juce_fileOpen (const String& fileName, bool forWriting)
+void* juce_fileOpen (const File& file, bool forWriting)
{
int flags = O_RDONLY;
if (forWriting)
{
- if (juce_fileExists (fileName, false))
+ if (file.exists())
{
- const int f = open (fileName.toUTF8(), O_RDWR, 00644);
+ const int f = open (file.getFullPathName().toUTF8(), O_RDWR, 00644);
if (f != -1)
lseek (f, 0, SEEK_END);
@@ -227967,7 +227765,7 @@ void* juce_fileOpen (const String& fileName, bool forWriting)
}
}
- return (void*) open (fileName.toUTF8(), flags, 00644);
+ return (void*) open (file.getFullPathName().toUTF8(), flags, 00644);
}
void juce_fileClose (void* handle)
@@ -228000,18 +227798,18 @@ int64 juce_fileSetPosition (void* handle, int64 pos)
return -1;
}
-int64 juce_fileGetPosition (void* handle)
+int64 FileOutputStream::getPositionInternal() const
{
- if (handle != 0)
- return lseek ((int) (pointer_sized_int) handle, 0, SEEK_CUR);
+ if (fileHandle != 0)
+ return lseek ((int) (pointer_sized_int) fileHandle, 0, SEEK_CUR);
return -1;
}
-void juce_fileFlush (void* handle)
+void FileOutputStream::flushInternal()
{
- if (handle != 0)
- fsync ((int) (pointer_sized_int) handle);
+ if (fileHandle != 0)
+ fsync ((int) (pointer_sized_int) fileHandle);
}
const File juce_getExecutableFile()
@@ -228022,10 +227820,8 @@ const File juce_getExecutableFile()
}
// if this file doesn't exist, find a parent of it that does..
-static bool doStatFS (const File* file, struct statfs& result)
+static bool juce_doStatFS (File f, struct statfs& result)
{
- File f (*file);
-
for (int i = 5; --i >= 0;)
{
if (f.exists())
@@ -228040,7 +227836,7 @@ static bool doStatFS (const File* file, struct statfs& result)
int64 File::getBytesFreeOnVolume() const
{
struct statfs buf;
- if (doStatFS (this, buf))
+ if (juce_doStatFS (*this, buf))
return (int64) buf.f_bsize * (int64) buf.f_bavail; // Note: this returns space available to non-super user
return 0;
@@ -228049,17 +227845,14 @@ int64 File::getBytesFreeOnVolume() const
int64 File::getVolumeTotalSize() const
{
struct statfs buf;
- if (doStatFS (this, buf))
+ if (juce_doStatFS (*this, buf))
return (int64) buf.f_bsize * (int64) buf.f_blocks;
return 0;
}
-const String juce_getVolumeLabel (const String& filenameOnVolume,
- int& volumeSerialNumber)
+const String File::getVolumeLabel() const
{
- volumeSerialNumber = 0;
-
#if JUCE_MAC
struct VolAttrBuf
{
@@ -228073,16 +227866,13 @@ const String juce_getVolumeLabel (const String& filenameOnVolume,
attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
attrList.volattr = ATTR_VOL_INFO | ATTR_VOL_NAME;
- File f (filenameOnVolume);
+ File f (*this);
for (;;)
{
- if (getattrlist (f.getFullPathName().toUTF8(),
- &attrList, &attrBuf, sizeof(attrBuf), 0) == 0)
- {
+ if (getattrlist (f.getFullPathName().toUTF8(), &attrList, &attrBuf, sizeof (attrBuf), 0) == 0)
return String::fromUTF8 (((const char*) &attrBuf.mountPointRef) + attrBuf.mountPointRef.attr_dataoffset,
(int) attrBuf.mountPointRef.attr_length);
- }
const File parent (f.getParentDirectory());
@@ -228096,6 +227886,11 @@ const String juce_getVolumeLabel (const String& filenameOnVolume,
return String::empty;
}
+int File::getVolumeSerialNumber() const
+{
+ return 0; // xxx
+}
+
void juce_runSystemCommand (const String& command)
{
int result = system (command.toUTF8());
@@ -228267,24 +228062,6 @@ bool juce_setFileTimes (const String& fileName,
return utime (fileName.toUTF8(), ×) == 0;
}
-bool juce_setFileReadOnly (const String& fileName, bool isReadOnly)
-{
- struct stat info;
- const int res = stat (fileName.toUTF8(), &info);
- if (res != 0)
- return false;
-
- info.st_mode &= 0777; // Just permissions
-
- if( isReadOnly )
- info.st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
- else
- // Give everybody write permission?
- info.st_mode |= S_IWUSR | S_IWGRP | S_IWOTH;
-
- return chmod (fileName.toUTF8(), info.st_mode) == 0;
-}
-
bool juce_copyFile (const String& s, const String& d)
{
const File source (s), dest (d);
@@ -228316,11 +228093,9 @@ bool juce_copyFile (const String& s, const String& d)
return ok;
}
-const StringArray juce_getFileSystemRoots()
+void File::findFileSystemRoots (Array& destArray)
{
- StringArray s;
- s.add ("/");
- return s;
+ destArray.add (File ("/"));
}
bool File::isOnCDRomDrive() const
@@ -228472,42 +228247,54 @@ bool File::moveToTrash() const
getFileExtension()));
}
-struct FindFileStruct
+class DirectoryIterator::NativeIterator::Pimpl
{
- String parentDir, wildCard;
- DIR* dir;
-
- bool getNextMatch (String& result, bool* const isDir, bool* const isHidden, int64* const fileSize,
- Time* const modTime, Time* const creationTime, bool* const isReadOnly)
+public:
+ Pimpl (const File& directory, const String& wildCard_)
+ : parentDir (File::addTrailingSeparator (directory.getFullPathName())),
+ wildCard (wildCard_),
+ dir (opendir (directory.getFullPathName().toUTF8()))
{
- const char* const wildcardUTF8 = wildCard.toUTF8();
+ if (wildCard == "*.*")
+ wildCard = "*";
+
+ wildcardUTF8 = wildCard.toUTF8();
+ }
+
+ ~Pimpl()
+ {
+ if (dir != 0)
+ closedir (dir);
+ }
+
+ bool next (String& filenameFound,
+ bool* const isDir, bool* const isHidden, int64* const fileSize,
+ Time* const modTime, Time* const creationTime, bool* const isReadOnly)
+ {
+ if (dir == 0)
+ return false;
for (;;)
{
struct dirent* const de = readdir (dir);
if (de == 0)
- break;
+ return false;
if (fnmatch (wildcardUTF8, de->d_name, FNM_CASEFOLD) == 0)
{
- result = String::fromUTF8 (de->d_name);
+ filenameFound = String::fromUTF8 (de->d_name);
- const String path (parentDir + result);
+ const String path (parentDir + filenameFound);
if (isDir != 0 || fileSize != 0)
{
struct stat info;
const bool statOk = (stat (path.toUTF8(), &info) == 0);
- if (isDir != 0)
- *isDir = path.isEmpty() || (statOk && ((info.st_mode & S_IFDIR) != 0));
-
- if (isHidden != 0)
- *isHidden = (de->d_name[0] == '.');
-
- if (fileSize != 0)
- *fileSize = statOk ? info.st_size : 0;
+ if (isDir != 0) *isDir = path.isEmpty() || (statOk && ((info.st_mode & S_IFDIR) != 0));
+ if (isHidden != 0) *isHidden = (de->d_name[0] == '.');
+ if (fileSize != 0) *fileSize = statOk ? info.st_size : 0;
}
if (modTime != 0 || creationTime != 0)
@@ -228515,11 +228302,8 @@ struct FindFileStruct
int64 m, a, c;
juce_getFileTimes (path, m, a, c);
- if (modTime != 0)
- *modTime = m;
-
- if (creationTime != 0)
- *creationTime = c;
+ if (modTime != 0) *modTime = m;
+ if (creationTime != 0) *creationTime = c;
}
if (isReadOnly != 0)
@@ -228528,69 +228312,31 @@ struct FindFileStruct
return true;
}
}
-
- return false;
}
+
+private:
+ String parentDir, wildCard;
+ const char* wildcardUTF8;
+ DIR* dir;
+
+ Pimpl (const Pimpl&);
+ Pimpl& operator= (const Pimpl&);
};
-// returns 0 on failure
-void* juce_findFileStart (const String& directory, const String& wildCard, String& firstResultFile,
- bool* isDir, bool* isHidden, int64* fileSize, Time* modTime,
- Time* creationTime, bool* isReadOnly)
+DirectoryIterator::NativeIterator::NativeIterator (const File& directory, const String& wildCard)
+ : pimpl (new DirectoryIterator::NativeIterator::Pimpl (directory, wildCard))
{
- DIR* d = opendir (directory.toUTF8());
-
- if (d != 0)
- {
- FindFileStruct* ff = new FindFileStruct();
- ff->parentDir = directory;
-
- if (!ff->parentDir.endsWithChar (File::separator))
- ff->parentDir += File::separator;
-
- ff->wildCard = wildCard;
- if (wildCard == "*.*")
- ff->wildCard = "*";
-
- ff->dir = d;
-
- if (ff->getNextMatch (firstResultFile, isDir, isHidden, fileSize, modTime, creationTime, isReadOnly))
- {
- return ff;
- }
- else
- {
- firstResultFile = String::empty;
- isDir = false;
- isHidden = false;
- closedir (d);
- delete ff;
- }
- }
-
- return 0;
}
-bool juce_findFileNext (void* handle, String& resultFile,
- bool* isDir, bool* isHidden, int64* fileSize, Time* modTime, Time* creationTime, bool* isReadOnly)
+DirectoryIterator::NativeIterator::~NativeIterator()
{
- FindFileStruct* const ff = (FindFileStruct*) handle;
-
- if (ff != 0)
- return ff->getNextMatch (resultFile, isDir, isHidden, fileSize, modTime, creationTime, isReadOnly);
-
- return false;
}
-void juce_findFileClose (void* handle)
+bool DirectoryIterator::NativeIterator::next (String& filenameFound,
+ bool* const isDir, bool* const isHidden, int64* const fileSize,
+ Time* const modTime, Time* const creationTime, bool* const isReadOnly)
{
- FindFileStruct* const ff = (FindFileStruct*) handle;
-
- if (ff != 0)
- {
- closedir (ff->dir);
- delete ff;
- }
+ return pimpl->next (filenameFound, isDir, isHidden, fileSize, modTime, creationTime, isReadOnly);
}
bool juce_launchFile (const String& fileName,
@@ -237902,7 +237648,7 @@ void JUCE_CALLTYPE Thread::sleep (int millisecs)
}
const juce_wchar File::separator = '/';
-const juce_wchar* File::separatorString = L"/";
+const String File::separatorString ("/");
const File File::getCurrentWorkingDirectory()
{
@@ -237927,47 +237673,35 @@ bool File::setAsCurrentWorkingDirectory() const
return chdir (getFullPathName().toUTF8()) == 0;
}
-bool juce_copyFile (const String& s, const String& d);
-
static bool juce_stat (const String& fileName, struct stat& info)
{
return fileName.isNotEmpty()
&& (stat (fileName.toUTF8(), &info) == 0);
}
-bool juce_isDirectory (const String& fileName)
+bool File::isDirectory() const
{
struct stat info;
- return fileName.isEmpty()
- || (juce_stat (fileName, info)
- && ((info.st_mode & S_IFDIR) != 0));
+ return fullPath.isEmpty()
+ || (juce_stat (fullPath, info) && ((info.st_mode & S_IFDIR) != 0));
}
-bool juce_fileExists (const String& fileName, const bool dontCountDirectories)
+bool File::exists() const
{
- if (fileName.isEmpty())
- return false;
-
- const char* const fileNameUTF8 = fileName.toUTF8();
- bool exists = access (fileNameUTF8, F_OK) == 0;
-
- if (exists && dontCountDirectories)
- {
- struct stat info;
- const int res = stat (fileNameUTF8, &info);
-
- if (res == 0 && (info.st_mode & S_IFDIR) != 0)
- exists = false;
- }
-
- return exists;
+ return fullPath.isNotEmpty()
+ && access (fullPath.toUTF8(), F_OK) == 0;
}
-int64 juce_getFileSize (const String& fileName)
+bool File::existsAsFile() const
+{
+ return exists() && ! isDirectory();
+}
+
+int64 File::getSize() const
{
struct stat info;
- return juce_stat (fileName, info) ? info.st_size : 0;
+ return juce_stat (fullPath, info) ? info.st_size : 0;
}
bool juce_canWriteToFile (const String& fileName)
@@ -237975,14 +237709,36 @@ bool juce_canWriteToFile (const String& fileName)
return access (fileName.toUTF8(), W_OK) == 0;
}
-bool juce_deleteFile (const String& fileName)
+bool juce_setFileReadOnly (const String& fileName, bool isReadOnly)
{
- if (juce_isDirectory (fileName))
- return rmdir (fileName.toUTF8()) == 0;
+ struct stat info;
+ const int res = stat (fileName.toUTF8(), &info);
+ if (res != 0)
+ return false;
+
+ info.st_mode &= 0777; // Just permissions
+
+ if (isReadOnly)
+ info.st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
else
- return remove (fileName.toUTF8()) == 0;
+ // Give everybody write permission?
+ info.st_mode |= S_IWUSR | S_IWGRP | S_IWOTH;
+
+ return chmod (fileName.toUTF8(), info.st_mode) == 0;
}
+bool File::deleteFile() const
+{
+ if (! exists())
+ return true;
+ else if (isDirectory())
+ return rmdir (fullPath.toUTF8()) == 0;
+ else
+ return remove (fullPath.toUTF8()) == 0;
+}
+
+bool juce_copyFile (const String& s, const String& d);
+
bool juce_moveFile (const String& source, const String& dest)
{
if (rename (source.toUTF8(), dest.toUTF8()) == 0)
@@ -237991,29 +237747,29 @@ bool juce_moveFile (const String& source, const String& dest)
if (juce_canWriteToFile (source)
&& juce_copyFile (source, dest))
{
- if (juce_deleteFile (source))
+ if (File (source).deleteFile())
return true;
- juce_deleteFile (dest);
+ File (dest).deleteFile();
}
return false;
}
-void juce_createDirectory (const String& fileName)
+void File::createDirectoryInternal (const String& fileName) const
{
mkdir (fileName.toUTF8(), 0777);
}
-void* juce_fileOpen (const String& fileName, bool forWriting)
+void* juce_fileOpen (const File& file, bool forWriting)
{
int flags = O_RDONLY;
if (forWriting)
{
- if (juce_fileExists (fileName, false))
+ if (file.exists())
{
- const int f = open (fileName.toUTF8(), O_RDWR, 00644);
+ const int f = open (file.getFullPathName().toUTF8(), O_RDWR, 00644);
if (f != -1)
lseek (f, 0, SEEK_END);
@@ -238026,7 +237782,7 @@ void* juce_fileOpen (const String& fileName, bool forWriting)
}
}
- return (void*) open (fileName.toUTF8(), flags, 00644);
+ return (void*) open (file.getFullPathName().toUTF8(), flags, 00644);
}
void juce_fileClose (void* handle)
@@ -238059,18 +237815,18 @@ int64 juce_fileSetPosition (void* handle, int64 pos)
return -1;
}
-int64 juce_fileGetPosition (void* handle)
+int64 FileOutputStream::getPositionInternal() const
{
- if (handle != 0)
- return lseek ((int) (pointer_sized_int) handle, 0, SEEK_CUR);
+ if (fileHandle != 0)
+ return lseek ((int) (pointer_sized_int) fileHandle, 0, SEEK_CUR);
return -1;
}
-void juce_fileFlush (void* handle)
+void FileOutputStream::flushInternal()
{
- if (handle != 0)
- fsync ((int) (pointer_sized_int) handle);
+ if (fileHandle != 0)
+ fsync ((int) (pointer_sized_int) fileHandle);
}
const File juce_getExecutableFile()
@@ -238081,10 +237837,8 @@ const File juce_getExecutableFile()
}
// if this file doesn't exist, find a parent of it that does..
-static bool doStatFS (const File* file, struct statfs& result)
+static bool juce_doStatFS (File f, struct statfs& result)
{
- File f (*file);
-
for (int i = 5; --i >= 0;)
{
if (f.exists())
@@ -238099,7 +237853,7 @@ static bool doStatFS (const File* file, struct statfs& result)
int64 File::getBytesFreeOnVolume() const
{
struct statfs buf;
- if (doStatFS (this, buf))
+ if (juce_doStatFS (*this, buf))
return (int64) buf.f_bsize * (int64) buf.f_bavail; // Note: this returns space available to non-super user
return 0;
@@ -238108,17 +237862,14 @@ int64 File::getBytesFreeOnVolume() const
int64 File::getVolumeTotalSize() const
{
struct statfs buf;
- if (doStatFS (this, buf))
+ if (juce_doStatFS (*this, buf))
return (int64) buf.f_bsize * (int64) buf.f_blocks;
return 0;
}
-const String juce_getVolumeLabel (const String& filenameOnVolume,
- int& volumeSerialNumber)
+const String File::getVolumeLabel() const
{
- volumeSerialNumber = 0;
-
#if JUCE_MAC
struct VolAttrBuf
{
@@ -238132,16 +237883,13 @@ const String juce_getVolumeLabel (const String& filenameOnVolume,
attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
attrList.volattr = ATTR_VOL_INFO | ATTR_VOL_NAME;
- File f (filenameOnVolume);
+ File f (*this);
for (;;)
{
- if (getattrlist (f.getFullPathName().toUTF8(),
- &attrList, &attrBuf, sizeof(attrBuf), 0) == 0)
- {
+ if (getattrlist (f.getFullPathName().toUTF8(), &attrList, &attrBuf, sizeof (attrBuf), 0) == 0)
return String::fromUTF8 (((const char*) &attrBuf.mountPointRef) + attrBuf.mountPointRef.attr_dataoffset,
(int) attrBuf.mountPointRef.attr_length);
- }
const File parent (f.getParentDirectory());
@@ -238155,6 +237903,11 @@ const String juce_getVolumeLabel (const String& filenameOnVolume,
return String::empty;
}
+int File::getVolumeSerialNumber() const
+{
+ return 0; // xxx
+}
+
void juce_runSystemCommand (const String& command)
{
int result = system (command.toUTF8());
@@ -238321,24 +238074,6 @@ bool juce_setFileTimes (const String& fileName,
return utime (fileName.toUTF8(), ×) == 0;
}
-bool juce_setFileReadOnly (const String& fileName, bool isReadOnly)
-{
- struct stat info;
- const int res = stat (fileName.toUTF8(), &info);
- if (res != 0)
- return false;
-
- info.st_mode &= 0777; // Just permissions
-
- if (isReadOnly)
- info.st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
- else
- // Give everybody write permission?
- info.st_mode |= S_IWUSR | S_IWGRP | S_IWOTH;
-
- return chmod (fileName.toUTF8(), info.st_mode) == 0;
-}
-
bool juce_copyFile (const String& src, const String& dst)
{
const ScopedAutoReleasePool pool;
@@ -238356,18 +238091,16 @@ bool juce_copyFile (const String& src, const String& dst)
#endif
}
-const StringArray juce_getFileSystemRoots()
+void File::findFileSystemRoots (Array& destArray)
{
- StringArray s;
- s.add ("/");
- return s;
+ destArray.add (File ("/"));
}
-static bool isFileOnDriveType (const File* const f, const char** types)
+static bool isFileOnDriveType (const File& f, const char** types)
{
struct statfs buf;
- if (doStatFS (f, buf))
+ if (juce_doStatFS (f, buf))
{
const String type (buf.f_fstypename);
@@ -238383,14 +238116,14 @@ bool File::isOnCDRomDrive() const
{
static const char* const cdTypes[] = { "cd9660", "cdfs", "cddafs", "udf", 0 };
- return isFileOnDriveType (this, (const char**) cdTypes);
+ return isFileOnDriveType (*this, (const char**) cdTypes);
}
bool File::isOnHardDisk() const
{
static const char* const nonHDTypes[] = { "nfs", "smbfs", "ramfs", 0 };
- return ! (isOnCDRomDrive() || isFileOnDriveType (this, (const char**) nonHDTypes));
+ return ! (isOnCDRomDrive() || isFileOnDriveType (*this, (const char**) nonHDTypes));
}
bool File::isOnRemovableDrive() const
@@ -238575,98 +238308,95 @@ bool File::moveToTrash() const
#endif
}
-struct FindFileStruct
+class DirectoryIterator::NativeIterator::Pimpl
{
- NSDirectoryEnumerator* enumerator;
+public:
+ Pimpl (const File& directory, const String& wildCard_)
+ : parentDir (File::addTrailingSeparator (directory.getFullPathName())),
+ wildCard (wildCard_),
+ enumerator (0)
+ {
+ ScopedAutoReleasePool pool;
+
+ enumerator = [[[NSFileManager defaultManager] enumeratorAtPath: juceStringToNS (directory.getFullPathName())] retain];
+
+ wildcardUTF8 = wildCard.toUTF8();
+ }
+
+ ~Pimpl()
+ {
+ [enumerator release];
+ }
+
+ bool next (String& filenameFound,
+ bool* const isDir, bool* const isHidden, int64* const fileSize,
+ Time* const modTime, Time* const creationTime, bool* const isReadOnly)
+ {
+ ScopedAutoReleasePool pool;
+
+ for (;;)
+ {
+ NSString* file;
+ if (enumerator == 0 || (file = [enumerator nextObject]) == 0)
+ return false;
+
+ [enumerator skipDescendents];
+ filenameFound = nsStringToJuce (file);
+
+ if (fnmatch (wildcardUTF8, filenameFound.toUTF8(), FNM_CASEFOLD) != 0)
+ continue;
+
+ const String path (parentDir + filenameFound);
+
+ if (isDir != 0 || fileSize != 0)
+ {
+ struct stat info;
+ const bool statOk = juce_stat (path, info);
+
+ if (isDir != 0) *isDir = statOk && ((info.st_mode & S_IFDIR) != 0);
+ if (isHidden != 0) *isHidden = juce_isHiddenFile (path);
+ if (fileSize != 0) *fileSize = statOk ? info.st_size : 0;
+ }
+
+ if (modTime != 0 || creationTime != 0)
+ {
+ int64 m, a, c;
+ juce_getFileTimes (path, m, a, c);
+
+ if (modTime != 0) *modTime = m;
+ if (creationTime != 0) *creationTime = c;
+ }
+
+ if (isReadOnly != 0)
+ *isReadOnly = ! juce_canWriteToFile (path);
+
+ return true;
+ }
+ }
+
+private:
String parentDir, wildCard;
+ const char* wildcardUTF8;
+ NSDirectoryEnumerator* enumerator;
+
+ Pimpl (const Pimpl&);
+ Pimpl& operator= (const Pimpl&);
};
-bool juce_findFileNext (void* handle, String& resultFile,
- bool* isDir, bool* isHidden, int64* fileSize, Time* modTime, Time* creationTime, bool* isReadOnly)
+DirectoryIterator::NativeIterator::NativeIterator (const File& directory, const String& wildCard)
+ : pimpl (new DirectoryIterator::NativeIterator::Pimpl (directory, wildCard))
{
- ScopedAutoReleasePool pool;
- FindFileStruct* ff = (FindFileStruct*) handle;
- NSString* file;
- const char* const wildcardUTF8 = ff->wildCard.toUTF8();
-
- for (;;)
- {
- if (ff == 0 || (file = [ff->enumerator nextObject]) == 0)
- return false;
-
- [ff->enumerator skipDescendents];
- resultFile = nsStringToJuce (file);
-
- if (fnmatch (wildcardUTF8, resultFile.toUTF8(), FNM_CASEFOLD) != 0)
- continue;
-
- const String path (ff->parentDir + resultFile);
-
- if (isDir != 0 || fileSize != 0)
- {
- struct stat info;
- const bool statOk = juce_stat (path, info);
-
- if (isDir != 0)
- *isDir = statOk && ((info.st_mode & S_IFDIR) != 0);
-
- if (isHidden != 0)
- *isHidden = juce_isHiddenFile (path);
-
- if (fileSize != 0)
- *fileSize = statOk ? info.st_size : 0;
- }
-
- if (modTime != 0 || creationTime != 0)
- {
- int64 m, a, c;
- juce_getFileTimes (path, m, a, c);
-
- if (modTime != 0)
- *modTime = m;
-
- if (creationTime != 0)
- *creationTime = c;
- }
-
- if (isReadOnly != 0)
- *isReadOnly = ! juce_canWriteToFile (path);
-
- return true;
- }
}
-void* juce_findFileStart (const String& directory, const String& wildCard, String& firstResultFile,
- bool* isDir, bool* isHidden, int64* fileSize, Time* modTime,
- Time* creationTime, bool* isReadOnly)
+DirectoryIterator::NativeIterator::~NativeIterator()
{
- ScopedAutoReleasePool pool;
- NSDirectoryEnumerator* e = [[NSFileManager defaultManager] enumeratorAtPath: juceStringToNS (directory)];
-
- if (e != 0)
- {
- ScopedPointer ff (new FindFileStruct());
- ff->enumerator = [e retain];
- ff->parentDir = directory;
- ff->wildCard = wildCard;
-
- if (! ff->parentDir.endsWithChar (File::separator))
- ff->parentDir += File::separator;
-
- if (juce_findFileNext (ff, firstResultFile, isDir, isHidden, fileSize, modTime, creationTime, isReadOnly))
- return ff.release();
-
- [e release];
- }
-
- return 0;
}
-void juce_findFileClose (void* handle)
+bool DirectoryIterator::NativeIterator::next (String& filenameFound,
+ bool* const isDir, bool* const isHidden, int64* const fileSize,
+ Time* const modTime, Time* const creationTime, bool* const isReadOnly)
{
- ScopedAutoReleasePool pool;
- ScopedPointer ff ((FindFileStruct*) handle);
- [ff->enumerator release];
+ return pimpl->next (filenameFound, isDir, isHidden, fileSize, modTime, creationTime, isReadOnly);
}
bool juce_launchExecutable (const String& pathAndArguments)
diff --git a/juce_amalgamated.h b/juce_amalgamated.h
index 2dd3f1ba30..d8d86f59cf 100644
--- a/juce_amalgamated.h
+++ b/juce_amalgamated.h
@@ -42,8 +42,8 @@
#define __JUCE_STANDARDHEADER_JUCEHEADER__
#define JUCE_MAJOR_VERSION 1
-#define JUCE_MINOR_VERSION 51
-#define JUCE_BUILDNUMBER 16
+#define JUCE_MINOR_VERSION 52
+#define JUCE_BUILDNUMBER 0
#define JUCE_VERSION ((JUCE_MAJOR_VERSION << 16) + (JUCE_MINOR_VERSION << 8) + JUCE_BUILDNUMBER)
@@ -189,7 +189,7 @@
#endif
#ifndef JUCE_FORCE_DEBUG
- #define JUCE_FORCE_DEBUG 0
+ //#define JUCE_FORCE_DEBUG 0
#endif
#ifndef JUCE_LOG_ASSERTIONS
@@ -4256,7 +4256,7 @@ public:
bool includeSeconds = true,
bool use24HourClock = false) const throw();
- const String formatted (const juce_wchar* format) const throw();
+ const String formatted (const String& format) const throw();
const Time operator+ (const RelativeTime& delta) const throw() { return Time (millisSinceEpoch + delta.inMilliseconds()); }
@@ -4379,6 +4379,8 @@ public:
bool operator== (const File& otherFile) const;
bool operator!= (const File& otherFile) const;
+ bool operator< (const File& otherFile) const;
+ bool operator> (const File& otherFile) const;
bool hasWriteAccess() const;
@@ -4516,7 +4518,7 @@ public:
static const juce_wchar separator;
- static const juce_wchar* separatorString;
+ static const String separatorString;
static const String createLegalFileName (const String& fileNameToFix);
@@ -4528,6 +4530,8 @@ public:
static const File createFileWithoutCheckingPath (const String& path);
+ static const String addTrailingSeparator (const String& path);
+
juce_UseDebuggingNewOperator
private:
@@ -4538,6 +4542,10 @@ private:
friend class DirectoryIterator;
File (const String&, int);
const String getPathUpToLastSlash() const;
+
+ void createDirectoryInternal (const String& fileName) const;
+ static const String parseAbsolutePath (const String& path);
+ static bool fileTypeMatches (int whatToLookFor, bool isDir, bool isHidden);
};
#endif // __JUCE_FILE_JUCEHEADER__
@@ -7744,6 +7752,9 @@ public:
bool next();
+ bool next (bool* isDirectory, bool* isHidden, int64* fileSize,
+ Time* modTime, Time* creationTime, bool* isReadOnly);
+
const File getFile() const;
float getEstimatedProgress() const;
@@ -7751,12 +7762,39 @@ public:
juce_UseDebuggingNewOperator
private:
- Array filesFound;
- Array dirsFound;
- String wildCard;
+ friend class File;
+
+ class NativeIterator
+ {
+ public:
+ NativeIterator (const File& directory, const String& wildCard);
+ ~NativeIterator();
+
+ bool next (String& filenameFound,
+ bool* isDirectory, bool* isHidden, int64* fileSize,
+ Time* modTime, Time* creationTime, bool* isReadOnly);
+
+ juce_UseDebuggingNewOperator
+
+ private:
+ class Pimpl;
+ friend class DirectoryIterator;
+ friend class ScopedPointer;
+ ScopedPointer pimpl;
+
+ NativeIterator (const NativeIterator&);
+ NativeIterator& operator= (const NativeIterator&);
+ };
+
+ friend class ScopedPointer;
+ NativeIterator fileFinder;
+ String wildCard, path;
int index;
+ mutable int totalNumFiles;
const int whatToLookFor;
+ const bool isRecursive;
ScopedPointer subIterator;
+ File currentFile;
DirectoryIterator (const DirectoryIterator&);
DirectoryIterator& operator= (const DirectoryIterator&);
@@ -7842,6 +7880,9 @@ private:
int bufferSize, bytesInBuffer;
HeapBlock buffer;
+ void flushInternal();
+ int64 getPositionInternal() const;
+
FileOutputStream (const FileOutputStream&);
FileOutputStream& operator= (const FileOutputStream&);
};
@@ -22342,7 +22383,7 @@ public:
void setIgnoresHiddenFiles (bool shouldIgnoreHiddenFiles);
- bool ignoresHiddenFiles() const { return ignoreHiddenFiles; }
+ bool ignoresHiddenFiles() const;
struct FileInfo
{
@@ -22379,19 +22420,20 @@ private:
File root;
const FileFilter* fileFilter;
TimeSliceThread& thread;
- bool includeDirectories, includeFiles, ignoreHiddenFiles;
+ int fileTypeFlags;
CriticalSection fileListLock;
OwnedArray files;
- void* volatile fileFindHandle;
+ ScopedPointer fileFindHandle;
bool volatile shouldStop;
void changed();
bool checkNextFile (bool& hasChanged);
- bool addFile (const String& filename, bool isDir, bool isHidden,
+ bool addFile (const File& file, bool isDir,
const int64 fileSize, const Time& modTime,
const Time& creationTime, bool isReadOnly);
+ void setTypeFlags (int newFlags);
DirectoryContentsList (const DirectoryContentsList&);
DirectoryContentsList& operator= (const DirectoryContentsList&);
diff --git a/src/audio/audio_file_formats/juce_WavAudioFormat.cpp b/src/audio/audio_file_formats/juce_WavAudioFormat.cpp
index c8c7e07cd8..0573f6a008 100644
--- a/src/audio/audio_file_formats/juce_WavAudioFormat.cpp
+++ b/src/audio/audio_file_formats/juce_WavAudioFormat.cpp
@@ -60,8 +60,8 @@ const StringPairArray WavAudioFormat::createBWAVMetadata (const String& descript
m.set (bwavDescription, description);
m.set (bwavOriginator, originator);
m.set (bwavOriginatorRef, originatorRef);
- m.set (bwavOriginationDate, date.formatted (T("%Y-%m-%d")));
- m.set (bwavOriginationTime, date.formatted (T("%H:%M:%S")));
+ m.set (bwavOriginationDate, date.formatted ("%Y-%m-%d"));
+ m.set (bwavOriginationTime, date.formatted ("%H:%M:%S"));
m.set (bwavTimeReference, String (timeReferenceSamples));
m.set (bwavCodingHistory, codingHistory);
diff --git a/src/core/juce_StandardHeader.h b/src/core/juce_StandardHeader.h
index 3d6c95c90e..7108010022 100644
--- a/src/core/juce_StandardHeader.h
+++ b/src/core/juce_StandardHeader.h
@@ -32,8 +32,8 @@
See also SystemStats::getJUCEVersion() for a string version.
*/
#define JUCE_MAJOR_VERSION 1
-#define JUCE_MINOR_VERSION 51
-#define JUCE_BUILDNUMBER 16
+#define JUCE_MINOR_VERSION 52
+#define JUCE_BUILDNUMBER 0
/** Current Juce version number.
diff --git a/src/core/juce_Time.cpp b/src/core/juce_Time.cpp
index e636d4de7a..e0145c9c7b 100644
--- a/src/core/juce_Time.cpp
+++ b/src/core/juce_Time.cpp
@@ -341,7 +341,7 @@ const String Time::toString (const bool includeDate,
return result.trimEnd();
}
-const String Time::formatted (const juce_wchar* const format) const throw()
+const String Time::formatted (const String& format) const throw()
{
String buffer;
int bufferSize = 128;
diff --git a/src/core/juce_Time.h b/src/core/juce_Time.h
index 0d7f951bea..98b95bfd28 100644
--- a/src/core/juce_Time.h
+++ b/src/core/juce_Time.h
@@ -245,7 +245,7 @@ public:
@see toString
*/
- const String formatted (const juce_wchar* format) const throw();
+ const String formatted (const String& format) const throw();
//==============================================================================
/** Adds a RelativeTime to this time and returns the result. */
diff --git a/src/gui/components/filebrowser/juce_DirectoryContentsList.cpp b/src/gui/components/filebrowser/juce_DirectoryContentsList.cpp
index a9587510cc..83c467b66e 100644
--- a/src/gui/components/filebrowser/juce_DirectoryContentsList.cpp
+++ b/src/gui/components/filebrowser/juce_DirectoryContentsList.cpp
@@ -30,23 +30,13 @@ BEGIN_JUCE_NAMESPACE
#include "juce_DirectoryContentsList.h"
#include "../../graphics/imaging/juce_ImageCache.h"
-void* juce_findFileStart (const String& directory, const String& wildCard, String& firstResultFile,
- bool* isDirectory, bool* isHidden, int64* fileSize, Time* modTime,
- Time* creationTime, bool* isReadOnly);
-bool juce_findFileNext (void* handle, String& resultFile,
- bool* isDirectory, bool* isHidden, int64* fileSize,
- Time* modTime, Time* creationTime, bool* isReadOnly);
-void juce_findFileClose (void* handle);
-
//==============================================================================
DirectoryContentsList::DirectoryContentsList (const FileFilter* const fileFilter_,
TimeSliceThread& thread_)
: fileFilter (fileFilter_),
thread (thread_),
- includeDirectories (false),
- includeFiles (false),
- ignoreHiddenFiles (true),
+ fileTypeFlags (File::ignoreHiddenFiles | File::findFiles),
fileFindHandle (0),
shouldStop (true)
{
@@ -59,7 +49,13 @@ DirectoryContentsList::~DirectoryContentsList()
void DirectoryContentsList::setIgnoresHiddenFiles (const bool shouldIgnoreHiddenFiles)
{
- ignoreHiddenFiles = shouldIgnoreHiddenFiles;
+ setTypeFlags (shouldIgnoreHiddenFiles ? (fileTypeFlags | File::ignoreHiddenFiles)
+ : (fileTypeFlags & ~File::ignoreHiddenFiles));
+}
+
+bool DirectoryContentsList::ignoresHiddenFiles() const
+{
+ return (fileTypeFlags & File::ignoreHiddenFiles) != 0;
}
//==============================================================================
@@ -69,19 +65,32 @@ const File& DirectoryContentsList::getDirectory() const
}
void DirectoryContentsList::setDirectory (const File& directory,
- const bool includeDirectories_,
- const bool includeFiles_)
+ const bool includeDirectories,
+ const bool includeFiles)
{
- if (directory != root
- || includeDirectories != includeDirectories_
- || includeFiles != includeFiles_)
+ jassert (includeDirectories || includeFiles); // you have to speciify at least one of these!
+
+ if (directory != root)
{
clear();
-
root = directory;
- includeDirectories = includeDirectories_;
- includeFiles = includeFiles_;
+ // (this forces a refresh when setTypeFlags() is called, rather than triggering two refreshes)
+ fileTypeFlags &= ~(File::findDirectories | File::findFiles);
+ }
+
+ int newFlags = fileTypeFlags;
+ if (includeDirectories) newFlags |= File::findDirectories; else newFlags &= ~File::findDirectories;
+ if (includeFiles) newFlags |= File::findFiles; else newFlags &= ~File::findFiles;
+
+ setTypeFlags (newFlags);
+}
+
+void DirectoryContentsList::setTypeFlags (const int newFlags)
+{
+ if (fileTypeFlags != newFlags)
+ {
+ fileTypeFlags = newFlags;
refresh();
}
}
@@ -91,11 +100,7 @@ void DirectoryContentsList::clear()
shouldStop = true;
thread.removeTimeSliceClient (this);
- if (fileFindHandle != 0)
- {
- juce_findFileClose (fileFindHandle);
- fileFindHandle = 0;
- }
+ fileFindHandle = 0;
if (files.size() > 0)
{
@@ -110,36 +115,8 @@ void DirectoryContentsList::refresh()
if (root.isDirectory())
{
- String fileFound;
- bool fileFoundIsDir, isHidden, isReadOnly;
- int64 fileSize;
- Time modTime, creationTime;
-
- String path (root.getFullPathName());
- if (! path.endsWithChar (File::separator))
- path += File::separator;
-
- jassert (fileFindHandle == 0);
-
- fileFindHandle = juce_findFileStart (path, "*", fileFound,
- &fileFoundIsDir,
- &isHidden,
- &fileSize,
- &modTime,
- &creationTime,
- &isReadOnly);
-
- if (fileFindHandle != 0 && fileFound.isNotEmpty())
- {
- if (addFile (fileFound, fileFoundIsDir, isHidden,
- fileSize, modTime, creationTime, isReadOnly))
- {
- changed();
- }
- }
-
+ fileFindHandle = new DirectoryIterator (root, false, "*", fileTypeFlags);
shouldStop = false;
-
thread.addTimeSliceClient (this);
}
}
@@ -216,20 +193,15 @@ bool DirectoryContentsList::checkNextFile (bool& hasChanged)
{
if (fileFindHandle != 0)
{
- String fileFound;
bool fileFoundIsDir, isHidden, isReadOnly;
int64 fileSize;
Time modTime, creationTime;
- if (juce_findFileNext (fileFindHandle, fileFound,
- &fileFoundIsDir, &isHidden,
- &fileSize,
- &modTime,
- &creationTime,
- &isReadOnly))
+ if (fileFindHandle->next (&fileFoundIsDir, &isHidden, &fileSize,
+ &modTime, &creationTime, &isReadOnly))
{
- if (addFile (fileFound, fileFoundIsDir, isHidden, fileSize,
- modTime, creationTime, isReadOnly))
+ if (addFile (fileFindHandle->getFile(), fileFoundIsDir,
+ fileSize, modTime, creationTime, isReadOnly))
{
hasChanged = true;
}
@@ -238,7 +210,6 @@ bool DirectoryContentsList::checkNextFile (bool& hasChanged)
}
else
{
- juce_findFileClose (fileFindHandle);
fileFindHandle = 0;
}
}
@@ -257,29 +228,20 @@ int DirectoryContentsList::compareElements (const DirectoryContentsList::FileInf
return first->filename.compareIgnoreCase (second->filename);
}
-bool DirectoryContentsList::addFile (const String& filename,
+bool DirectoryContentsList::addFile (const File& file,
const bool isDir,
- const bool isHidden,
const int64 fileSize,
const Time& modTime,
const Time& creationTime,
const bool isReadOnly)
{
- if (filename == ".."
- || filename == "."
- || (ignoreHiddenFiles && isHidden))
- return false;
-
- const File file (root.getChildFile (filename));
-
- if (((isDir && includeDirectories) || ((! isDir) && includeFiles))
- && (fileFilter == 0
- || ((! isDir) && fileFilter->isFileSuitable (file))
- || (isDir && fileFilter->isDirectorySuitable (file))))
+ if (fileFilter == 0
+ || ((! isDir) && fileFilter->isFileSuitable (file))
+ || (isDir && fileFilter->isDirectorySuitable (file)))
{
ScopedPointer info (new FileInfo());
- info->filename = filename;
+ info->filename = file.getFileName();
info->fileSize = fileSize;
info->modificationTime = modTime;
info->creationTime = creationTime;
diff --git a/src/gui/components/filebrowser/juce_DirectoryContentsList.h b/src/gui/components/filebrowser/juce_DirectoryContentsList.h
index b31903c547..0dd4f56b44 100644
--- a/src/gui/components/filebrowser/juce_DirectoryContentsList.h
+++ b/src/gui/components/filebrowser/juce_DirectoryContentsList.h
@@ -30,6 +30,7 @@
#include "../../../events/juce_ChangeBroadcaster.h"
#include "../../../threads/juce_TimeSliceThread.h"
#include "../../graphics/imaging/juce_Image.h"
+#include "../../../io/files/juce_DirectoryIterator.h"
//==============================================================================
@@ -104,7 +105,7 @@ public:
/** Returns true if hidden files are ignored.
@see setIgnoresHiddenFiles
*/
- bool ignoresHiddenFiles() const { return ignoreHiddenFiles; }
+ bool ignoresHiddenFiles() const;
//==============================================================================
/** Contains cached information about one of the files in a DirectoryContentsList.
@@ -197,19 +198,20 @@ private:
File root;
const FileFilter* fileFilter;
TimeSliceThread& thread;
- bool includeDirectories, includeFiles, ignoreHiddenFiles;
+ int fileTypeFlags;
CriticalSection fileListLock;
OwnedArray files;
- void* volatile fileFindHandle;
+ ScopedPointer fileFindHandle;
bool volatile shouldStop;
void changed();
bool checkNextFile (bool& hasChanged);
- bool addFile (const String& filename, bool isDir, bool isHidden,
+ bool addFile (const File& file, bool isDir,
const int64 fileSize, const Time& modTime,
const Time& creationTime, bool isReadOnly);
+ void setTypeFlags (int newFlags);
DirectoryContentsList (const DirectoryContentsList&);
DirectoryContentsList& operator= (const DirectoryContentsList&);
diff --git a/src/gui/components/filebrowser/juce_FileBrowserComponent.cpp b/src/gui/components/filebrowser/juce_FileBrowserComponent.cpp
index 4e31eed64a..b264ebc209 100644
--- a/src/gui/components/filebrowser/juce_FileBrowserComponent.cpp
+++ b/src/gui/components/filebrowser/juce_FileBrowserComponent.cpp
@@ -231,7 +231,7 @@ void FileBrowserComponent::setRoot (const File& newRootDirectory)
String path (newRootDirectory.getFullPathName());
if (path.isEmpty())
- path += File::separator;
+ path = File::separatorString;
StringArray rootNames, rootPaths;
getRoots (rootNames, rootPaths);
@@ -259,7 +259,7 @@ void FileBrowserComponent::setRoot (const File& newRootDirectory)
String currentRootName (currentRoot.getFullPathName());
if (currentRootName.isEmpty())
- currentRootName += File::separator;
+ currentRootName = File::separatorString;
currentPathBox->setText (currentRootName, true);
diff --git a/src/gui/components/filebrowser/juce_FileListComponent.cpp b/src/gui/components/filebrowser/juce_FileListComponent.cpp
index da9641c8c1..84c91d7eb4 100644
--- a/src/gui/components/filebrowser/juce_FileListComponent.cpp
+++ b/src/gui/components/filebrowser/juce_FileListComponent.cpp
@@ -142,7 +142,7 @@ public:
{
newFile = root.getChildFile (fileInfo->filename);
newFileSize = File::descriptionOfSizeInBytes (fileInfo->fileSize);
- newModTime = fileInfo->modificationTime.formatted (T("%d %b '%y %H:%M"));
+ newModTime = fileInfo->modificationTime.formatted ("%d %b '%y %H:%M");
}
if (newFile != file
diff --git a/src/gui/components/filebrowser/juce_FileTreeComponent.cpp b/src/gui/components/filebrowser/juce_FileTreeComponent.cpp
index b0949d789a..8a2ba0ea09 100644
--- a/src/gui/components/filebrowser/juce_FileTreeComponent.cpp
+++ b/src/gui/components/filebrowser/juce_FileTreeComponent.cpp
@@ -63,7 +63,7 @@ public:
&& parentContentsList_->getFileInfo (indexInContentsList_, fileInfo))
{
fileSize = File::descriptionOfSizeInBytes (fileInfo.fileSize);
- modTime = fileInfo.modificationTime.formatted (T("%d %b '%y %H:%M"));
+ modTime = fileInfo.modificationTime.formatted ("%d %b '%y %H:%M");
isDirectory = fileInfo.isDirectory;
}
else
diff --git a/src/io/files/juce_DirectoryIterator.cpp b/src/io/files/juce_DirectoryIterator.cpp
index f8ca3e11b4..1e97850ce1 100644
--- a/src/io/files/juce_DirectoryIterator.cpp
+++ b/src/io/files/juce_DirectoryIterator.cpp
@@ -30,79 +30,23 @@ BEGIN_JUCE_NAMESPACE
#include "juce_DirectoryIterator.h"
-void* juce_findFileStart (const String& directory, const String& wildCard, String& firstResultFile,
- bool* isDirectory, bool* isHidden, int64* fileSize,
- Time* modTime, Time* creationTime, bool* isReadOnly);
-bool juce_findFileNext (void* handle, String& resultFile,
- bool* isDirectory, bool* isHidden, int64* fileSize,
- Time* modTime, Time* creationTime, bool* isReadOnly);
-void juce_findFileClose (void* handle);
-
//==============================================================================
DirectoryIterator::DirectoryIterator (const File& directory,
- bool isRecursive,
- const String& wc,
+ bool isRecursive_,
+ const String& wildCard_,
const int whatToLookFor_)
- : wildCard (wc),
+ : fileFinder (directory, isRecursive ? "*" : wildCard_),
+ wildCard (wildCard_),
+ path (File::addTrailingSeparator (directory.getFullPathName())),
index (-1),
- whatToLookFor (whatToLookFor_)
+ totalNumFiles (-1),
+ whatToLookFor (whatToLookFor_),
+ isRecursive (isRecursive_)
{
// you have to specify the type of files you're looking for!
jassert ((whatToLookFor_ & (File::findFiles | File::findDirectories)) != 0);
jassert (whatToLookFor_ > 0 && whatToLookFor_ <= 7);
-
- String path (directory.getFullPathName());
- if (! path.endsWithChar (File::separator))
- path += File::separator;
-
- String filename;
- bool isDirectory, isHidden;
-
- void* const handle = juce_findFileStart (path,
- isRecursive ? "*" : wc,
- filename, &isDirectory, &isHidden, 0, 0, 0, 0);
-
- if (handle != 0)
- {
- do
- {
- if (! filename.containsOnly ("."))
- {
- bool addToList = false;
-
- if (isDirectory)
- {
- if (isRecursive
- && ((whatToLookFor_ & File::ignoreHiddenFiles) == 0
- || ! isHidden))
- {
- dirsFound.add (File (path + filename, 0));
- }
-
- addToList = (whatToLookFor_ & File::findDirectories) != 0;
- }
- else
- {
- addToList = (whatToLookFor_ & File::findFiles) != 0;
- }
-
- // if it's recursive, we're not relying on the OS iterator
- // to do the wildcard match, so do it now..
- if (isRecursive && addToList)
- addToList = filename.matchesWildcard (wc, true);
-
- if (addToList && (whatToLookFor_ & File::ignoreHiddenFiles) != 0)
- addToList = ! isHidden;
-
- if (addToList)
- filesFound.add (File (path + filename, 0));
- }
-
- } while (juce_findFileNext (handle, filename, &isDirectory, &isHidden, 0, 0, 0, 0));
-
- juce_findFileClose (handle);
- }
}
DirectoryIterator::~DirectoryIterator()
@@ -110,28 +54,67 @@ DirectoryIterator::~DirectoryIterator()
}
bool DirectoryIterator::next()
+{
+ return next (0, 0, 0, 0, 0, 0);
+}
+
+bool DirectoryIterator::next (bool* const isDirResult, bool* const isHiddenResult, int64* const fileSize,
+ Time* const modTime, Time* const creationTime, bool* const isReadOnly)
{
if (subIterator != 0)
{
- if (subIterator->next())
+ if (subIterator->next (isDirResult, isHiddenResult, fileSize, modTime, creationTime, isReadOnly))
return true;
subIterator = 0;
}
- if (index >= filesFound.size() + dirsFound.size() - 1)
- return false;
-
- ++index;
-
- if (index >= filesFound.size())
+ String filename;
+ bool isDirectory, isHidden;
+ while (fileFinder.next (filename, &isDirectory, &isHidden, fileSize, modTime, creationTime, isReadOnly))
{
- subIterator = new DirectoryIterator (dirsFound.getReference (index - filesFound.size()),
- true, wildCard, whatToLookFor);
- return next();
+ ++index;
+
+ if (! filename.containsOnly ("."))
+ {
+ const File fileFound (path + filename, 0);
+ bool matches = false;
+
+ if (isDirectory)
+ {
+ if (isRecursive && ((whatToLookFor & File::ignoreHiddenFiles) == 0 || ! isHidden))
+ subIterator = new DirectoryIterator (fileFound, true, wildCard, whatToLookFor);
+
+ matches = (whatToLookFor & File::findDirectories) != 0;
+ }
+ else
+ {
+ matches = (whatToLookFor & File::findFiles) != 0;
+ }
+
+ // if recursive, we're not relying on the OS iterator to do the wildcard match, so do it now..
+ if (matches && isRecursive)
+ matches = filename.matchesWildcard (wildCard, ! File::areFileNamesCaseSensitive());
+
+ if (matches && (whatToLookFor & File::ignoreHiddenFiles) != 0)
+ matches = ! isHidden;
+
+ if (matches)
+ {
+ currentFile = fileFound;
+ if (isHiddenResult != 0) *isHiddenResult = isHidden;
+ if (isDirResult != 0) *isDirResult = isDirectory;
+
+ return true;
+ }
+ else if (subIterator != 0)
+ {
+ return next();
+ }
+ }
}
- return true;
+ return false;
}
const File DirectoryIterator::getFile() const
@@ -139,22 +122,21 @@ const File DirectoryIterator::getFile() const
if (subIterator != 0)
return subIterator->getFile();
- return filesFound [index];
+ return currentFile;
}
float DirectoryIterator::getEstimatedProgress() const
{
- if (filesFound.size() + dirsFound.size() == 0)
- {
- return 0.0f;
- }
- else
- {
- const float detailedIndex = (subIterator != 0) ? index + subIterator->getEstimatedProgress()
- : (float) index;
+ if (totalNumFiles < 0)
+ totalNumFiles = File (path).getNumberOfChildFiles (File::findFilesAndDirectories);
- return detailedIndex / (filesFound.size() + dirsFound.size());
- }
+ if (totalNumFiles <= 0)
+ return 0.0f;
+
+ const float detailedIndex = (subIterator != 0) ? index + subIterator->getEstimatedProgress()
+ : (float) index;
+
+ return detailedIndex / totalNumFiles;
}
END_JUCE_NAMESPACE
diff --git a/src/io/files/juce_DirectoryIterator.h b/src/io/files/juce_DirectoryIterator.h
index 354f3947d1..fcea05271e 100644
--- a/src/io/files/juce_DirectoryIterator.h
+++ b/src/io/files/juce_DirectoryIterator.h
@@ -76,13 +76,28 @@ public:
/** Destructor. */
~DirectoryIterator();
- /** Call this to move the iterator along to the next file.
+ /** Moves the iterator along to the next file.
@returns true if a file was found (you can then use getFile() to see what it was) - or
false if there are no more matching files.
*/
bool next();
+ /** Moves the iterator along to the next file, and returns various properties of that file.
+
+ If you need to find out details about the file, it's more efficient to call this method than
+ to call the normal next() method and then find out the details afterwards.
+
+ All the parameters are optional, so pass null pointers for any items that you're not
+ interested in.
+
+ @returns true if a file was found (you can then use getFile() to see what it was) - or
+ false if there are no more matching files. If it returns false, then none of the
+ parameters will be filled-in.
+ */
+ bool next (bool* isDirectory, bool* isHidden, int64* fileSize,
+ Time* modTime, Time* creationTime, bool* isReadOnly);
+
/** Returns the file that the iterator is currently pointing at.
The result of this call is only valid after a call to next() has returned true.
@@ -96,17 +111,44 @@ public:
*/
float getEstimatedProgress() const;
-
//==============================================================================
juce_UseDebuggingNewOperator
private:
- Array filesFound;
- Array dirsFound;
- String wildCard;
+ friend class File;
+
+ //==============================================================================
+ class NativeIterator
+ {
+ public:
+ NativeIterator (const File& directory, const String& wildCard);
+ ~NativeIterator();
+
+ bool next (String& filenameFound,
+ bool* isDirectory, bool* isHidden, int64* fileSize,
+ Time* modTime, Time* creationTime, bool* isReadOnly);
+
+ juce_UseDebuggingNewOperator
+
+ private:
+ class Pimpl;
+ friend class DirectoryIterator;
+ friend class ScopedPointer;
+ ScopedPointer pimpl;
+
+ NativeIterator (const NativeIterator&);
+ NativeIterator& operator= (const NativeIterator&);
+ };
+
+ friend class ScopedPointer;
+ NativeIterator fileFinder;
+ String wildCard, path;
int index;
+ mutable int totalNumFiles;
const int whatToLookFor;
+ const bool isRecursive;
ScopedPointer subIterator;
+ File currentFile;
DirectoryIterator (const DirectoryIterator&);
DirectoryIterator& operator= (const DirectoryIterator&);
diff --git a/src/io/files/juce_File.cpp b/src/io/files/juce_File.cpp
index 1e4cab13e5..46b27beb73 100644
--- a/src/io/files/juce_File.cpp
+++ b/src/io/files/juce_File.cpp
@@ -23,11 +23,6 @@
==============================================================================
*/
-#ifdef _MSC_VER
- #pragma warning (disable: 4514)
- #pragma warning (push)
-#endif
-
#include "../../core/juce_StandardHeader.h"
#if ! JUCE_WINDOWS
@@ -36,170 +31,28 @@
BEGIN_JUCE_NAMESPACE
-
#include "juce_File.h"
#include "juce_FileInputStream.h"
+#include "juce_DirectoryIterator.h"
#include "juce_TemporaryFile.h"
#include "../../core/juce_SystemStats.h"
#include "../../core/juce_Random.h"
#include "../../containers/juce_ScopedPointer.h"
-#ifdef _MSC_VER
- #pragma warning (pop)
-#endif
//==============================================================================
-void* juce_fileOpen (const String& path, bool forWriting);
-void juce_fileClose (void* handle);
-int juce_fileWrite (void* handle, const void* buffer, int size);
-int64 juce_fileGetPosition (void* handle);
-int64 juce_fileSetPosition (void* handle, int64 pos);
-void juce_fileFlush (void* handle);
-
-bool juce_fileExists (const String& fileName, const bool dontCountDirectories);
-bool juce_isDirectory (const String& fileName);
-int64 juce_getFileSize (const String& fileName);
bool juce_canWriteToFile (const String& fileName);
bool juce_setFileReadOnly (const String& fileName, bool isReadOnly);
-
void juce_getFileTimes (const String& fileName, int64& modificationTime, int64& accessTime, int64& creationTime);
bool juce_setFileTimes (const String& fileName, int64 modificationTime, int64 accessTime, int64 creationTime);
-
-bool juce_deleteFile (const String& fileName);
bool juce_copyFile (const String& source, const String& dest);
bool juce_moveFile (const String& source, const String& dest);
-
-// this must also create all paths involved in the directory.
-void juce_createDirectory (const String& fileName);
-
bool juce_launchFile (const String& fileName, const String& parameters);
-const StringArray juce_getFileSystemRoots();
-const String juce_getVolumeLabel (const String& filenameOnVolume, int& volumeSerialNumber);
-
-// starts a directory search operation with a wildcard, returning a handle for
-// use in calls to juce_findFileNext.
-// juce_firstResultFile gets the name of the file (not the whole pathname) and
-// the other pointers, if non-null, are set based on the properties of the file.
-void* juce_findFileStart (const String& directory, const String& wildCard, String& firstResultFile,
- bool* isDirectory, bool* isHidden, int64* fileSize, Time* modTime,
- Time* creationTime, bool* isReadOnly);
-
-// returns false when no more files are found
-bool juce_findFileNext (void* handle, String& resultFile,
- bool* isDirectory, bool* isHidden, int64* fileSize,
- Time* modTime, Time* creationTime, bool* isReadOnly);
-
-void juce_findFileClose (void* handle);
-
-//==============================================================================
-static const String juce_addTrailingSeparator (const String& path)
-{
- return path.endsWithChar (File::separator) ? path
- : path + File::separator;
-}
-
-//==============================================================================
-static const String parseAbsolutePath (String path)
-{
- if (path.isEmpty())
- return String::empty;
-
-#if JUCE_WINDOWS
- // Windows..
- path = path.replaceCharacter ('/', '\\');
-
- if (path.startsWithChar (File::separator))
- {
- if (path[1] != File::separator)
- {
- /* When you supply a raw string to the File object constructor, it must be an absolute path.
- If you're trying to parse a string that may be either a relative path or an absolute path,
- you MUST provide a context against which the partial path can be evaluated - you can do
- this by simply using File::getChildFile() instead of the File constructor. E.g. saying
- "File::getCurrentWorkingDirectory().getChildFile (myUnknownPath)" would return an absolute
- path if that's what was supplied, or would evaluate a partial path relative to the CWD.
- */
- jassertfalse
-
- path = File::getCurrentWorkingDirectory().getFullPathName().substring (0, 2) + path;
- }
- }
- else if (path.indexOfChar (':') < 0)
- {
- if (path.isEmpty())
- return String::empty;
-
- /* When you supply a raw string to the File object constructor, it must be an absolute path.
- If you're trying to parse a string that may be either a relative path or an absolute path,
- you MUST provide a context against which the partial path can be evaluated - you can do
- this by simply using File::getChildFile() instead of the File constructor. E.g. saying
- "File::getCurrentWorkingDirectory().getChildFile (myUnknownPath)" would return an absolute
- path if that's what was supplied, or would evaluate a partial path relative to the CWD.
- */
- jassertfalse
-
- return File::getCurrentWorkingDirectory().getChildFile (path).getFullPathName();
- }
-#else
- // Mac or Linux..
- path = path.replaceCharacter ('\\', '/');
-
- if (path.startsWithChar ('~'))
- {
- const char* homeDir = 0;
-
- if (path[1] == File::separator || path[1] == 0)
- {
- // expand a name of the form "~/abc"
- path = File::getSpecialLocation (File::userHomeDirectory).getFullPathName()
- + path.substring (1);
- }
- else
- {
- // expand a name of type "~dave/abc"
- const String userName (path.substring (1).upToFirstOccurrenceOf ("/", false, false));
-
- struct passwd* const pw = getpwnam (userName.toUTF8());
- if (pw != 0)
- {
- String home (homeDir);
-
- if (home.endsWithChar (File::separator))
- home [home.length() - 1] = 0;
-
- path = String (pw->pw_dir)
- + path.substring (userName.length());
- }
- }
- }
- else if (! path.startsWithChar (File::separator))
- {
- /* When you supply a raw string to the File object constructor, it must be an absolute path.
- If you're trying to parse a string that may be either a relative path or an absolute path,
- you MUST provide a context against which the partial path can be evaluated - you can do
- this by simply using File::getChildFile() instead of the File constructor. E.g. saying
- "File::getCurrentWorkingDirectory().getChildFile (myUnknownPath)" would return an absolute
- path if that's what was supplied, or would evaluate a partial path relative to the CWD.
- */
- jassert (path.startsWith ("./") || path.startsWith ("../")); // (assume that a path "./xyz" is deliberately intended to be relative to the CWD)
-
- return File::getCurrentWorkingDirectory().getChildFile (path).getFullPathName();
- }
-#endif
-
- int len = path.length();
- while (--len > 0 && path [len] == File::separator)
- path [len] = 0;
-
- return path;
-}
-
//==============================================================================
const File File::nonexistent;
-
//==============================================================================
File::File (const String& fullPathName)
: fullPath (parseAbsolutePath (fullPathName))
@@ -233,6 +86,91 @@ File& File::operator= (const File& other)
return *this;
}
+//==============================================================================
+const String File::parseAbsolutePath (const String& p)
+{
+ if (p.isEmpty())
+ return String::empty;
+
+#if JUCE_WINDOWS
+ // Windows..
+ String path (p.replaceCharacter ('/', '\\'));
+
+ if (path.startsWithChar (File::separator))
+ {
+ if (path[1] != File::separator)
+ {
+ /* When you supply a raw string to the File object constructor, it must be an absolute path.
+ If you're trying to parse a string that may be either a relative path or an absolute path,
+ you MUST provide a context against which the partial path can be evaluated - you can do
+ this by simply using File::getChildFile() instead of the File constructor. E.g. saying
+ "File::getCurrentWorkingDirectory().getChildFile (myUnknownPath)" would return an absolute
+ path if that's what was supplied, or would evaluate a partial path relative to the CWD.
+ */
+ jassertfalse
+
+ path = File::getCurrentWorkingDirectory().getFullPathName().substring (0, 2) + path;
+ }
+ }
+ else if (! path.containsChar (':'))
+ {
+ /* When you supply a raw string to the File object constructor, it must be an absolute path.
+ If you're trying to parse a string that may be either a relative path or an absolute path,
+ you MUST provide a context against which the partial path can be evaluated - you can do
+ this by simply using File::getChildFile() instead of the File constructor. E.g. saying
+ "File::getCurrentWorkingDirectory().getChildFile (myUnknownPath)" would return an absolute
+ path if that's what was supplied, or would evaluate a partial path relative to the CWD.
+ */
+ jassertfalse
+
+ return File::getCurrentWorkingDirectory().getChildFile (path).getFullPathName();
+ }
+#else
+ // Mac or Linux..
+ String path (p.replaceCharacter ('\\', '/'));
+
+ if (path.startsWithChar ('~'))
+ {
+ if (path[1] == File::separator || path[1] == 0)
+ {
+ // expand a name of the form "~/abc"
+ path = File::getSpecialLocation (File::userHomeDirectory).getFullPathName()
+ + path.substring (1);
+ }
+ else
+ {
+ // expand a name of type "~dave/abc"
+ const String userName (path.substring (1).upToFirstOccurrenceOf ("/", false, false));
+
+ struct passwd* const pw = getpwnam (userName.toUTF8());
+ if (pw != 0)
+ path = addTrailingSeparator (pw->pw_dir) + path.fromFirstOccurrenceOf ("/", false, false);
+ }
+ }
+ else if (! path.startsWithChar (File::separator))
+ {
+ /* When you supply a raw string to the File object constructor, it must be an absolute path.
+ If you're trying to parse a string that may be either a relative path or an absolute path,
+ you MUST provide a context against which the partial path can be evaluated - you can do
+ this by simply using File::getChildFile() instead of the File constructor. E.g. saying
+ "File::getCurrentWorkingDirectory().getChildFile (myUnknownPath)" would return an absolute
+ path if that's what was supplied, or would evaluate a partial path relative to the CWD.
+ */
+ jassert (path.startsWith ("./") || path.startsWith ("../")); // (assume that a path "./xyz" is deliberately intended to be relative to the CWD)
+
+ return File::getCurrentWorkingDirectory().getChildFile (path).getFullPathName();
+ }
+#endif
+
+ return path.trimCharactersAtEnd (separatorString);
+}
+
+const String File::addTrailingSeparator (const String& path)
+{
+ return path.endsWithChar (File::separator) ? path
+ : path + File::separator;
+}
+
//==============================================================================
#if JUCE_LINUX
#define NAMES_ARE_CASE_SENSITIVE 1
@@ -249,7 +187,6 @@ bool File::areFileNamesCaseSensitive()
bool File::operator== (const File& other) const
{
- // case-insensitive on Windows, but not on linux.
#if NAMES_ARE_CASE_SENSITIVE
return fullPath == other.fullPath;
#else
@@ -262,22 +199,25 @@ bool File::operator!= (const File& other) const
return ! operator== (other);
}
+bool File::operator< (const File& other) const
+{
+#if NAMES_ARE_CASE_SENSITIVE
+ return fullPath < other.fullPath;
+#else
+ return fullPath.compareIgnoreCase (other.fullPath) < 0;
+#endif
+}
+
+bool File::operator> (const File& other) const
+{
+#if NAMES_ARE_CASE_SENSITIVE
+ return fullPath > other.fullPath;
+#else
+ return fullPath.compareIgnoreCase (other.fullPath) > 0;
+#endif
+}
+
//==============================================================================
-bool File::exists() const
-{
- return juce_fileExists (fullPath, false);
-}
-
-bool File::existsAsFile() const
-{
- return juce_fileExists (fullPath, true);
-}
-
-bool File::isDirectory() const
-{
- return juce_isDirectory (fullPath);
-}
-
bool File::hasWriteAccess() const
{
if (exists())
@@ -313,12 +253,6 @@ bool File::setReadOnly (const bool shouldBeReadOnly,
return juce_setFileReadOnly (fullPath, shouldBeReadOnly) && worked;
}
-bool File::deleteFile() const
-{
- return (! exists())
- || juce_deleteFile (fullPath);
-}
-
bool File::deleteRecursively() const
{
bool worked = true;
@@ -513,7 +447,7 @@ const File File::getChildFile (String relativePath) const
}
}
- return File (juce_addTrailingSeparator (path) + relativePath);
+ return File (addTrailingSeparator (path) + relativePath);
}
}
@@ -523,11 +457,6 @@ const File File::getSiblingFile (const String& fileName) const
}
//==============================================================================
-int64 File::getSize() const
-{
- return juce_getFileSize (fullPath);
-}
-
const String File::descriptionOfSizeInBytes (const int64 bytes)
{
if (bytes == 1)
@@ -555,22 +484,19 @@ const String File::descriptionOfSizeInBytes (const int64 bytes)
//==============================================================================
bool File::create() const
{
- if (! exists())
+ if (exists())
+ return true;
+
{
const File parentDir (getParentDirectory());
if (parentDir == *this || ! parentDir.createDirectory())
return false;
- void* const fh = juce_fileOpen (fullPath, true);
-
- if (fh == 0)
- return false;
-
- juce_fileClose (fh);
+ FileOutputStream fo (*this, 8);
}
- return true;
+ return exists();
}
bool File::createDirectory() const
@@ -582,13 +508,7 @@ bool File::createDirectory() const
if (parentDir == *this || ! parentDir.createDirectory())
return false;
- String dir (fullPath);
-
- while (dir.endsWithChar (separator))
- dir [dir.length() - 1] = 0;
-
- juce_createDirectory (dir);
-
+ createDirectoryInternal (fullPath.trimCharactersAtEnd (separatorString));
return isDirectory();
}
@@ -652,14 +572,11 @@ const String File::loadFileAsString() const
}
//==============================================================================
-static inline bool fileTypeMatches (const int whatToLookFor,
- const bool isDir,
- const bool isHidden)
+bool File::fileTypeMatches (const int whatToLookFor, const bool isDir, const bool isHidden)
{
- return (whatToLookFor & (isDir ? File::findDirectories
- : File::findFiles)) != 0
- && ((! isHidden)
- || (whatToLookFor & File::ignoreHiddenFiles) == 0);
+ return (whatToLookFor & (isDir ? findDirectories
+ : findFiles)) != 0
+ && ((! isHidden) || (whatToLookFor & File::ignoreHiddenFiles) == 0);
}
int File::findChildFiles (Array& results,
@@ -672,50 +589,32 @@ int File::findChildFiles (Array& results,
int total = 0;
- // find child files or directories in this directory first..
if (isDirectory())
{
- const String path (juce_addTrailingSeparator (fullPath));
-
- String filename;
+ // find child files or directories in this directory first..
+ String path (addTrailingSeparator (fullPath)), filename;
bool itemIsDirectory, itemIsHidden;
- void* const handle = juce_findFileStart (path, wildCardPattern, filename,
- &itemIsDirectory, &itemIsHidden,
- 0, 0, 0, 0);
+ DirectoryIterator::NativeIterator i (path, wildCardPattern);
- if (handle != 0)
+ while (i.next (filename, &itemIsDirectory, &itemIsHidden, 0, 0, 0, 0))
{
- do
+ if (! filename.containsOnly ("."))
{
- if (fileTypeMatches (whatToLookFor, itemIsDirectory, itemIsHidden)
- && ! filename.containsOnly ("."))
+ const File fileFound (path + filename, 0);
+
+ if (fileTypeMatches (whatToLookFor, itemIsDirectory, itemIsHidden))
{
- results.add (File (path + filename, 0));
+ results.add (fileFound);
++total;
}
- } while (juce_findFileNext (handle, filename, &itemIsDirectory, &itemIsHidden, 0, 0, 0, 0));
-
- juce_findFileClose (handle);
- }
- }
- else
- {
- // trying to search for files inside a non-directory?
- //jassertfalse
- }
-
- // and recurse down if required.
- if (searchRecursively)
- {
- Array subDirectories;
- findChildFiles (subDirectories, File::findDirectories, false);
-
- for (int i = 0; i < subDirectories.size(); ++i)
- {
- total += subDirectories.getReference(i).findChildFiles (results, whatToLookFor,
- true, wildCardPattern);
+ if (searchRecursively && itemIsDirectory
+ && fileTypeMatches (whatToLookFor | findDirectories, true, itemIsHidden))
+ {
+ total += fileFound.findChildFiles (results, whatToLookFor, true, wildCardPattern);
+ }
+ }
}
}
@@ -735,24 +634,12 @@ int File::getNumberOfChildFiles (const int whatToLookFor,
String filename;
bool itemIsDirectory, itemIsHidden;
- void* const handle = juce_findFileStart (fullPath, wildCardPattern, filename,
- &itemIsDirectory, &itemIsHidden,
- 0, 0, 0, 0);
+ DirectoryIterator::NativeIterator i (*this, wildCardPattern);
- if (handle != 0)
- {
- do
- {
- if (fileTypeMatches (whatToLookFor, itemIsDirectory, itemIsHidden)
- && ! filename.containsOnly ("."))
- {
- ++count;
- }
-
- } while (juce_findFileNext (handle, filename, &itemIsDirectory, &itemIsHidden, 0, 0, 0, 0));
-
- juce_findFileClose (handle);
- }
+ while (i.next (filename, &itemIsDirectory, &itemIsHidden, 0, 0, 0, 0))
+ if (fileTypeMatches (whatToLookFor, itemIsDirectory, itemIsHidden)
+ && ! filename.containsOnly ("."))
+ ++count;
}
else
{
@@ -765,33 +652,19 @@ int File::getNumberOfChildFiles (const int whatToLookFor,
bool File::containsSubDirectories() const
{
- bool result = false;
-
if (isDirectory())
{
String filename;
- bool itemIsDirectory, itemIsHidden;
- void* const handle = juce_findFileStart (juce_addTrailingSeparator (fullPath),
- "*", filename,
- &itemIsDirectory, &itemIsHidden, 0, 0, 0, 0);
+ bool itemIsDirectory;
- if (handle != 0)
- {
- do
- {
- if (itemIsDirectory)
- {
- result = true;
- break;
- }
+ DirectoryIterator::NativeIterator i (*this, "*");
- } while (juce_findFileNext (handle, filename, &itemIsDirectory, &itemIsHidden, 0, 0, 0, 0));
-
- juce_findFileClose (handle);
- }
+ while (i.next (filename, &itemIsDirectory, 0, 0, 0, 0, 0))
+ if (itemIsDirectory)
+ return true;
}
- return result;
+ return false;
}
//==============================================================================
@@ -1048,8 +921,8 @@ const String File::getRelativePathFrom (const File& dir) const
thisPath [len] = 0;
}
- String dirPath (juce_addTrailingSeparator ((dir.existsAsFile()) ? dir.getParentDirectory().getFullPathName()
- : dir.fullPath));
+ String dirPath (addTrailingSeparator (dir.existsAsFile() ? dir.getParentDirectory().getFullPathName()
+ : dir.fullPath));
const int len = jmin (thisPath.length(), dirPath.length());
int commonBitLength = 0;
@@ -1099,29 +972,6 @@ const String File::getRelativePathFrom (const File& dir) const
return thisPath;
}
-//==============================================================================
-void File::findFileSystemRoots (Array& destArray)
-{
- const StringArray roots (juce_getFileSystemRoots());
-
- for (int i = 0; i < roots.size(); ++i)
- destArray.add (File (roots[i]));
-}
-
-const String File::getVolumeLabel() const
-{
- int serialNum;
- return juce_getVolumeLabel (fullPath, serialNum);
-}
-
-int File::getVolumeSerialNumber() const
-{
- int serialNum;
- juce_getVolumeLabel (fullPath, serialNum);
-
- return serialNum;
-}
-
//==============================================================================
const File File::createTempFile (const String& fileNameEnding)
{
diff --git a/src/io/files/juce_File.h b/src/io/files/juce_File.h
index 15cf7d0b8e..4b55bf9822 100644
--- a/src/io/files/juce_File.h
+++ b/src/io/files/juce_File.h
@@ -30,6 +30,7 @@
#include "../../core/juce_Time.h"
#include "../../text/juce_StringArray.h"
#include "../../containers/juce_MemoryBlock.h"
+#include "../../containers/juce_ScopedPointer.h"
class FileInputStream;
class FileOutputStream;
@@ -320,6 +321,10 @@ public:
bool operator== (const File& otherFile) const;
/** Compares the pathnames for two files. */
bool operator!= (const File& otherFile) const;
+ /** Compares the pathnames for two files. */
+ bool operator< (const File& otherFile) const;
+ /** Compares the pathnames for two files. */
+ bool operator> (const File& otherFile) const;
//==============================================================================
/** Checks whether a file can be created or written to.
@@ -864,7 +869,7 @@ public:
On Windows, this will be '\', on Mac/Linux, it'll be '/'
*/
- static const juce_wchar* separatorString;
+ static const String separatorString;
//==============================================================================
/** Removes illegal characters from a filename.
@@ -903,6 +908,9 @@ public:
*/
static const File createFileWithoutCheckingPath (const String& path);
+ /** Adds a separator character to the end of a path if it doesn't already have one. */
+ static const String addTrailingSeparator (const String& path);
+
//==============================================================================
juce_UseDebuggingNewOperator
@@ -914,6 +922,10 @@ private:
friend class DirectoryIterator;
File (const String&, int);
const String getPathUpToLastSlash() const;
+
+ void createDirectoryInternal (const String& fileName) const;
+ static const String parseAbsolutePath (const String& path);
+ static bool fileTypeMatches (int whatToLookFor, bool isDir, bool isHidden);
};
#endif // __JUCE_FILE_JUCEHEADER__
diff --git a/src/io/files/juce_FileInputStream.cpp b/src/io/files/juce_FileInputStream.cpp
index 8996280026..4556f6ea14 100644
--- a/src/io/files/juce_FileInputStream.cpp
+++ b/src/io/files/juce_FileInputStream.cpp
@@ -31,7 +31,7 @@ BEGIN_JUCE_NAMESPACE
//==============================================================================
-void* juce_fileOpen (const String& path, bool forWriting);
+void* juce_fileOpen (const File& file, bool forWriting);
void juce_fileClose (void* handle);
int juce_fileRead (void* handle, void* buffer, int size);
int64 juce_fileSetPosition (void* handle, int64 pos);
@@ -45,7 +45,7 @@ FileInputStream::FileInputStream (const File& f)
{
totalSize = f.getSize();
- fileHandle = juce_fileOpen (f.getFullPathName(), false);
+ fileHandle = juce_fileOpen (f, false);
}
FileInputStream::~FileInputStream()
diff --git a/src/io/files/juce_FileOutputStream.cpp b/src/io/files/juce_FileOutputStream.cpp
index 11fe08ce14..39e1931837 100644
--- a/src/io/files/juce_FileOutputStream.cpp
+++ b/src/io/files/juce_FileOutputStream.cpp
@@ -29,11 +29,9 @@ BEGIN_JUCE_NAMESPACE
#include "juce_FileOutputStream.h"
-void* juce_fileOpen (const String& path, bool forWriting);
+void* juce_fileOpen (const File& file, bool forWriting);
void juce_fileClose (void* handle);
int juce_fileWrite (void* handle, const void* buffer, int size);
-void juce_fileFlush (void* handle);
-int64 juce_fileGetPosition (void* handle);
int64 juce_fileSetPosition (void* handle, int64 pos);
@@ -44,11 +42,11 @@ FileOutputStream::FileOutputStream (const File& f,
bufferSize (bufferSize_),
bytesInBuffer (0)
{
- fileHandle = juce_fileOpen (f.getFullPathName(), true);
+ fileHandle = juce_fileOpen (f, true);
if (fileHandle != 0)
{
- currentPosition = juce_fileGetPosition (fileHandle);
+ currentPosition = getPositionInternal();
if (currentPosition < 0)
{
@@ -92,7 +90,7 @@ void FileOutputStream::flush()
bytesInBuffer = 0;
}
- juce_fileFlush (fileHandle);
+ flushInternal();
}
bool FileOutputStream::write (const void* const src, const int numBytes)
diff --git a/src/io/files/juce_FileOutputStream.h b/src/io/files/juce_FileOutputStream.h
index 67ac2d1b7b..e15dd4bf5b 100644
--- a/src/io/files/juce_FileOutputStream.h
+++ b/src/io/files/juce_FileOutputStream.h
@@ -88,6 +88,9 @@ private:
int bufferSize, bytesInBuffer;
HeapBlock buffer;
+ void flushInternal();
+ int64 getPositionInternal() const;
+
FileOutputStream (const FileOutputStream&);
FileOutputStream& operator= (const FileOutputStream&);
};
diff --git a/src/native/common/juce_posix_SharedCode.h b/src/native/common/juce_posix_SharedCode.h
index 7d39c754dc..a641439309 100644
--- a/src/native/common/juce_posix_SharedCode.h
+++ b/src/native/common/juce_posix_SharedCode.h
@@ -188,7 +188,7 @@ void JUCE_CALLTYPE Thread::sleep (int millisecs)
//==============================================================================
const juce_wchar File::separator = '/';
-const juce_wchar* File::separatorString = L"/";
+const String File::separatorString ("/");
//==============================================================================
const File File::getCurrentWorkingDirectory()
@@ -215,47 +215,35 @@ bool File::setAsCurrentWorkingDirectory() const
}
//==============================================================================
-bool juce_copyFile (const String& s, const String& d);
-
static bool juce_stat (const String& fileName, struct stat& info)
{
return fileName.isNotEmpty()
&& (stat (fileName.toUTF8(), &info) == 0);
}
-bool juce_isDirectory (const String& fileName)
+bool File::isDirectory() const
{
struct stat info;
- return fileName.isEmpty()
- || (juce_stat (fileName, info)
- && ((info.st_mode & S_IFDIR) != 0));
+ return fullPath.isEmpty()
+ || (juce_stat (fullPath, info) && ((info.st_mode & S_IFDIR) != 0));
}
-bool juce_fileExists (const String& fileName, const bool dontCountDirectories)
+bool File::exists() const
{
- if (fileName.isEmpty())
- return false;
-
- const char* const fileNameUTF8 = fileName.toUTF8();
- bool exists = access (fileNameUTF8, F_OK) == 0;
-
- if (exists && dontCountDirectories)
- {
- struct stat info;
- const int res = stat (fileNameUTF8, &info);
-
- if (res == 0 && (info.st_mode & S_IFDIR) != 0)
- exists = false;
- }
-
- return exists;
+ return fullPath.isNotEmpty()
+ && access (fullPath.toUTF8(), F_OK) == 0;
}
-int64 juce_getFileSize (const String& fileName)
+bool File::existsAsFile() const
+{
+ return exists() && ! isDirectory();
+}
+
+int64 File::getSize() const
{
struct stat info;
- return juce_stat (fileName, info) ? info.st_size : 0;
+ return juce_stat (fullPath, info) ? info.st_size : 0;
}
//==============================================================================
@@ -264,14 +252,36 @@ bool juce_canWriteToFile (const String& fileName)
return access (fileName.toUTF8(), W_OK) == 0;
}
-bool juce_deleteFile (const String& fileName)
+bool juce_setFileReadOnly (const String& fileName, bool isReadOnly)
{
- if (juce_isDirectory (fileName))
- return rmdir (fileName.toUTF8()) == 0;
+ struct stat info;
+ const int res = stat (fileName.toUTF8(), &info);
+ if (res != 0)
+ return false;
+
+ info.st_mode &= 0777; // Just permissions
+
+ if (isReadOnly)
+ info.st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
else
- return remove (fileName.toUTF8()) == 0;
+ // Give everybody write permission?
+ info.st_mode |= S_IWUSR | S_IWGRP | S_IWOTH;
+
+ return chmod (fileName.toUTF8(), info.st_mode) == 0;
}
+bool File::deleteFile() const
+{
+ if (! exists())
+ return true;
+ else if (isDirectory())
+ return rmdir (fullPath.toUTF8()) == 0;
+ else
+ return remove (fullPath.toUTF8()) == 0;
+}
+
+bool juce_copyFile (const String& s, const String& d);
+
bool juce_moveFile (const String& source, const String& dest)
{
if (rename (source.toUTF8(), dest.toUTF8()) == 0)
@@ -280,29 +290,29 @@ bool juce_moveFile (const String& source, const String& dest)
if (juce_canWriteToFile (source)
&& juce_copyFile (source, dest))
{
- if (juce_deleteFile (source))
+ if (File (source).deleteFile())
return true;
- juce_deleteFile (dest);
+ File (dest).deleteFile();
}
return false;
}
-void juce_createDirectory (const String& fileName)
+void File::createDirectoryInternal (const String& fileName) const
{
mkdir (fileName.toUTF8(), 0777);
}
-void* juce_fileOpen (const String& fileName, bool forWriting)
+void* juce_fileOpen (const File& file, bool forWriting)
{
int flags = O_RDONLY;
if (forWriting)
{
- if (juce_fileExists (fileName, false))
+ if (file.exists())
{
- const int f = open (fileName.toUTF8(), O_RDWR, 00644);
+ const int f = open (file.getFullPathName().toUTF8(), O_RDWR, 00644);
if (f != -1)
lseek (f, 0, SEEK_END);
@@ -315,7 +325,7 @@ void* juce_fileOpen (const String& fileName, bool forWriting)
}
}
- return (void*) open (fileName.toUTF8(), flags, 00644);
+ return (void*) open (file.getFullPathName().toUTF8(), flags, 00644);
}
void juce_fileClose (void* handle)
@@ -348,18 +358,18 @@ int64 juce_fileSetPosition (void* handle, int64 pos)
return -1;
}
-int64 juce_fileGetPosition (void* handle)
+int64 FileOutputStream::getPositionInternal() const
{
- if (handle != 0)
- return lseek ((int) (pointer_sized_int) handle, 0, SEEK_CUR);
+ if (fileHandle != 0)
+ return lseek ((int) (pointer_sized_int) fileHandle, 0, SEEK_CUR);
return -1;
}
-void juce_fileFlush (void* handle)
+void FileOutputStream::flushInternal()
{
- if (handle != 0)
- fsync ((int) (pointer_sized_int) handle);
+ if (fileHandle != 0)
+ fsync ((int) (pointer_sized_int) fileHandle);
}
const File juce_getExecutableFile()
@@ -371,10 +381,8 @@ const File juce_getExecutableFile()
//==============================================================================
// if this file doesn't exist, find a parent of it that does..
-static bool doStatFS (const File* file, struct statfs& result)
+static bool juce_doStatFS (File f, struct statfs& result)
{
- File f (*file);
-
for (int i = 5; --i >= 0;)
{
if (f.exists())
@@ -389,7 +397,7 @@ static bool doStatFS (const File* file, struct statfs& result)
int64 File::getBytesFreeOnVolume() const
{
struct statfs buf;
- if (doStatFS (this, buf))
+ if (juce_doStatFS (*this, buf))
return (int64) buf.f_bsize * (int64) buf.f_bavail; // Note: this returns space available to non-super user
return 0;
@@ -398,17 +406,14 @@ int64 File::getBytesFreeOnVolume() const
int64 File::getVolumeTotalSize() const
{
struct statfs buf;
- if (doStatFS (this, buf))
+ if (juce_doStatFS (*this, buf))
return (int64) buf.f_bsize * (int64) buf.f_blocks;
return 0;
}
-const String juce_getVolumeLabel (const String& filenameOnVolume,
- int& volumeSerialNumber)
+const String File::getVolumeLabel() const
{
- volumeSerialNumber = 0;
-
#if JUCE_MAC
struct VolAttrBuf
{
@@ -422,16 +427,13 @@ const String juce_getVolumeLabel (const String& filenameOnVolume,
attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
attrList.volattr = ATTR_VOL_INFO | ATTR_VOL_NAME;
- File f (filenameOnVolume);
+ File f (*this);
for (;;)
{
- if (getattrlist (f.getFullPathName().toUTF8(),
- &attrList, &attrBuf, sizeof(attrBuf), 0) == 0)
- {
+ if (getattrlist (f.getFullPathName().toUTF8(), &attrList, &attrBuf, sizeof (attrBuf), 0) == 0)
return String::fromUTF8 (((const char*) &attrBuf.mountPointRef) + attrBuf.mountPointRef.attr_dataoffset,
(int) attrBuf.mountPointRef.attr_length);
- }
const File parent (f.getParentDirectory());
@@ -445,6 +447,10 @@ const String juce_getVolumeLabel (const String& filenameOnVolume,
return String::empty;
}
+int File::getVolumeSerialNumber() const
+{
+ return 0; // xxx
+}
//==============================================================================
void juce_runSystemCommand (const String& command)
diff --git a/src/native/juce_mac_NativeCode.mm b/src/native/juce_mac_NativeCode.mm
index 65faebf679..4c072a0896 100644
--- a/src/native/juce_mac_NativeCode.mm
+++ b/src/native/juce_mac_NativeCode.mm
@@ -46,7 +46,9 @@ BEGIN_JUCE_NAMESPACE
#include "../threads/juce_Thread.h"
#include "../threads/juce_InterProcessLock.h"
#include "../io/files/juce_FileInputStream.h"
+#include "../io/files/juce_FileOutputStream.h"
#include "../io/files/juce_NamedPipe.h"
+#include "../io/files/juce_DirectoryIterator.h"
#include "../io/network/juce_URL.h"
#include "../io/streams/juce_MemoryInputStream.h"
#include "../core/juce_PlatformUtilities.h"
diff --git a/src/native/juce_win32_NativeCode.cpp b/src/native/juce_win32_NativeCode.cpp
index 58358c033f..474ce1bd37 100644
--- a/src/native/juce_win32_NativeCode.cpp
+++ b/src/native/juce_win32_NativeCode.cpp
@@ -47,7 +47,9 @@ BEGIN_JUCE_NAMESPACE
#include "../threads/juce_Thread.h"
#include "../threads/juce_InterProcessLock.h"
#include "../io/files/juce_FileInputStream.h"
+#include "../io/files/juce_FileOutputStream.h"
#include "../io/files/juce_NamedPipe.h"
+#include "../io/files/juce_DirectoryIterator.h"
#include "../io/network/juce_URL.h"
#include "../core/juce_PlatformUtilities.h"
#include "../text/juce_LocalisedStrings.h"
diff --git a/src/native/linux/juce_linux_Files.cpp b/src/native/linux/juce_linux_Files.cpp
index 1d56528e4f..1a15b74ebe 100644
--- a/src/native/linux/juce_linux_Files.cpp
+++ b/src/native/linux/juce_linux_Files.cpp
@@ -64,24 +64,6 @@ bool juce_setFileTimes (const String& fileName,
return utime (fileName.toUTF8(), ×) == 0;
}
-bool juce_setFileReadOnly (const String& fileName, bool isReadOnly)
-{
- struct stat info;
- const int res = stat (fileName.toUTF8(), &info);
- if (res != 0)
- return false;
-
- info.st_mode &= 0777; // Just permissions
-
- if( isReadOnly )
- info.st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
- else
- // Give everybody write permission?
- info.st_mode |= S_IWUSR | S_IWGRP | S_IWOTH;
-
- return chmod (fileName.toUTF8(), info.st_mode) == 0;
-}
-
bool juce_copyFile (const String& s, const String& d)
{
const File source (s), dest (d);
@@ -113,11 +95,9 @@ bool juce_copyFile (const String& s, const String& d)
return ok;
}
-const StringArray juce_getFileSystemRoots()
+void File::findFileSystemRoots (Array& destArray)
{
- StringArray s;
- s.add ("/");
- return s;
+ destArray.add (File ("/"));
}
//==============================================================================
@@ -275,42 +255,54 @@ bool File::moveToTrash() const
}
//==============================================================================
-struct FindFileStruct
+class DirectoryIterator::NativeIterator::Pimpl
{
- String parentDir, wildCard;
- DIR* dir;
-
- bool getNextMatch (String& result, bool* const isDir, bool* const isHidden, int64* const fileSize,
- Time* const modTime, Time* const creationTime, bool* const isReadOnly)
+public:
+ Pimpl (const File& directory, const String& wildCard_)
+ : parentDir (File::addTrailingSeparator (directory.getFullPathName())),
+ wildCard (wildCard_),
+ dir (opendir (directory.getFullPathName().toUTF8()))
{
- const char* const wildcardUTF8 = wildCard.toUTF8();
+ if (wildCard == "*.*")
+ wildCard = "*";
+
+ wildcardUTF8 = wildCard.toUTF8();
+ }
+
+ ~Pimpl()
+ {
+ if (dir != 0)
+ closedir (dir);
+ }
+
+ bool next (String& filenameFound,
+ bool* const isDir, bool* const isHidden, int64* const fileSize,
+ Time* const modTime, Time* const creationTime, bool* const isReadOnly)
+ {
+ if (dir == 0)
+ return false;
for (;;)
{
struct dirent* const de = readdir (dir);
if (de == 0)
- break;
+ return false;
if (fnmatch (wildcardUTF8, de->d_name, FNM_CASEFOLD) == 0)
{
- result = String::fromUTF8 (de->d_name);
+ filenameFound = String::fromUTF8 (de->d_name);
- const String path (parentDir + result);
+ const String path (parentDir + filenameFound);
if (isDir != 0 || fileSize != 0)
{
struct stat info;
const bool statOk = (stat (path.toUTF8(), &info) == 0);
- if (isDir != 0)
- *isDir = path.isEmpty() || (statOk && ((info.st_mode & S_IFDIR) != 0));
-
- if (isHidden != 0)
- *isHidden = (de->d_name[0] == '.');
-
- if (fileSize != 0)
- *fileSize = statOk ? info.st_size : 0;
+ if (isDir != 0) *isDir = path.isEmpty() || (statOk && ((info.st_mode & S_IFDIR) != 0));
+ if (isHidden != 0) *isHidden = (de->d_name[0] == '.');
+ if (fileSize != 0) *fileSize = statOk ? info.st_size : 0;
}
if (modTime != 0 || creationTime != 0)
@@ -318,11 +310,8 @@ struct FindFileStruct
int64 m, a, c;
juce_getFileTimes (path, m, a, c);
- if (modTime != 0)
- *modTime = m;
-
- if (creationTime != 0)
- *creationTime = c;
+ if (modTime != 0) *modTime = m;
+ if (creationTime != 0) *creationTime = c;
}
if (isReadOnly != 0)
@@ -331,71 +320,35 @@ struct FindFileStruct
return true;
}
}
-
- return false;
}
+
+private:
+ String parentDir, wildCard;
+ const char* wildcardUTF8;
+ DIR* dir;
+
+ Pimpl (const Pimpl&);
+ Pimpl& operator= (const Pimpl&);
};
-// returns 0 on failure
-void* juce_findFileStart (const String& directory, const String& wildCard, String& firstResultFile,
- bool* isDir, bool* isHidden, int64* fileSize, Time* modTime,
- Time* creationTime, bool* isReadOnly)
+DirectoryIterator::NativeIterator::NativeIterator (const File& directory, const String& wildCard)
+ : pimpl (new DirectoryIterator::NativeIterator::Pimpl (directory, wildCard))
{
- DIR* d = opendir (directory.toUTF8());
-
- if (d != 0)
- {
- FindFileStruct* ff = new FindFileStruct();
- ff->parentDir = directory;
-
- if (!ff->parentDir.endsWithChar (File::separator))
- ff->parentDir += File::separator;
-
- ff->wildCard = wildCard;
- if (wildCard == "*.*")
- ff->wildCard = "*";
-
- ff->dir = d;
-
- if (ff->getNextMatch (firstResultFile, isDir, isHidden, fileSize, modTime, creationTime, isReadOnly))
- {
- return ff;
- }
- else
- {
- firstResultFile = String::empty;
- isDir = false;
- isHidden = false;
- closedir (d);
- delete ff;
- }
- }
-
- return 0;
}
-bool juce_findFileNext (void* handle, String& resultFile,
- bool* isDir, bool* isHidden, int64* fileSize, Time* modTime, Time* creationTime, bool* isReadOnly)
+DirectoryIterator::NativeIterator::~NativeIterator()
{
- FindFileStruct* const ff = (FindFileStruct*) handle;
-
- if (ff != 0)
- return ff->getNextMatch (resultFile, isDir, isHidden, fileSize, modTime, creationTime, isReadOnly);
-
- return false;
}
-void juce_findFileClose (void* handle)
+bool DirectoryIterator::NativeIterator::next (String& filenameFound,
+ bool* const isDir, bool* const isHidden, int64* const fileSize,
+ Time* const modTime, Time* const creationTime, bool* const isReadOnly)
{
- FindFileStruct* const ff = (FindFileStruct*) handle;
-
- if (ff != 0)
- {
- closedir (ff->dir);
- delete ff;
- }
+ return pimpl->next (filenameFound, isDir, isHidden, fileSize, modTime, creationTime, isReadOnly);
}
+
+//==============================================================================
bool juce_launchFile (const String& fileName,
const String& parameters)
{
diff --git a/src/native/mac/juce_mac_Files.mm b/src/native/mac/juce_mac_Files.mm
index 9772bb1ff0..50010f1104 100644
--- a/src/native/mac/juce_mac_Files.mm
+++ b/src/native/mac/juce_mac_Files.mm
@@ -64,24 +64,6 @@ bool juce_setFileTimes (const String& fileName,
return utime (fileName.toUTF8(), ×) == 0;
}
-bool juce_setFileReadOnly (const String& fileName, bool isReadOnly)
-{
- struct stat info;
- const int res = stat (fileName.toUTF8(), &info);
- if (res != 0)
- return false;
-
- info.st_mode &= 0777; // Just permissions
-
- if (isReadOnly)
- info.st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
- else
- // Give everybody write permission?
- info.st_mode |= S_IWUSR | S_IWGRP | S_IWOTH;
-
- return chmod (fileName.toUTF8(), info.st_mode) == 0;
-}
-
bool juce_copyFile (const String& src, const String& dst)
{
const ScopedAutoReleasePool pool;
@@ -99,19 +81,18 @@ bool juce_copyFile (const String& src, const String& dst)
#endif
}
-const StringArray juce_getFileSystemRoots()
+void File::findFileSystemRoots (Array& destArray)
{
- StringArray s;
- s.add ("/");
- return s;
+ destArray.add (File ("/"));
}
+
//==============================================================================
-static bool isFileOnDriveType (const File* const f, const char** types)
+static bool isFileOnDriveType (const File& f, const char** types)
{
struct statfs buf;
- if (doStatFS (f, buf))
+ if (juce_doStatFS (f, buf))
{
const String type (buf.f_fstypename);
@@ -127,14 +108,14 @@ bool File::isOnCDRomDrive() const
{
static const char* const cdTypes[] = { "cd9660", "cdfs", "cddafs", "udf", 0 };
- return isFileOnDriveType (this, (const char**) cdTypes);
+ return isFileOnDriveType (*this, (const char**) cdTypes);
}
bool File::isOnHardDisk() const
{
static const char* const nonHDTypes[] = { "nfs", "smbfs", "ramfs", 0 };
- return ! (isOnCDRomDrive() || isFileOnDriveType (this, (const char**) nonHDTypes));
+ return ! (isOnCDRomDrive() || isFileOnDriveType (*this, (const char**) nonHDTypes));
}
bool File::isOnRemovableDrive() const
@@ -324,100 +305,98 @@ bool File::moveToTrash() const
}
//==============================================================================
-struct FindFileStruct
+class DirectoryIterator::NativeIterator::Pimpl
{
- NSDirectoryEnumerator* enumerator;
+public:
+ Pimpl (const File& directory, const String& wildCard_)
+ : parentDir (File::addTrailingSeparator (directory.getFullPathName())),
+ wildCard (wildCard_),
+ enumerator (0)
+ {
+ ScopedAutoReleasePool pool;
+
+ enumerator = [[[NSFileManager defaultManager] enumeratorAtPath: juceStringToNS (directory.getFullPathName())] retain];
+
+ wildcardUTF8 = wildCard.toUTF8();
+ }
+
+ ~Pimpl()
+ {
+ [enumerator release];
+ }
+
+ bool next (String& filenameFound,
+ bool* const isDir, bool* const isHidden, int64* const fileSize,
+ Time* const modTime, Time* const creationTime, bool* const isReadOnly)
+ {
+ ScopedAutoReleasePool pool;
+
+ for (;;)
+ {
+ NSString* file;
+ if (enumerator == 0 || (file = [enumerator nextObject]) == 0)
+ return false;
+
+ [enumerator skipDescendents];
+ filenameFound = nsStringToJuce (file);
+
+ if (fnmatch (wildcardUTF8, filenameFound.toUTF8(), FNM_CASEFOLD) != 0)
+ continue;
+
+ const String path (parentDir + filenameFound);
+
+ if (isDir != 0 || fileSize != 0)
+ {
+ struct stat info;
+ const bool statOk = juce_stat (path, info);
+
+ if (isDir != 0) *isDir = statOk && ((info.st_mode & S_IFDIR) != 0);
+ if (isHidden != 0) *isHidden = juce_isHiddenFile (path);
+ if (fileSize != 0) *fileSize = statOk ? info.st_size : 0;
+ }
+
+ if (modTime != 0 || creationTime != 0)
+ {
+ int64 m, a, c;
+ juce_getFileTimes (path, m, a, c);
+
+ if (modTime != 0) *modTime = m;
+ if (creationTime != 0) *creationTime = c;
+ }
+
+ if (isReadOnly != 0)
+ *isReadOnly = ! juce_canWriteToFile (path);
+
+ return true;
+ }
+ }
+
+private:
String parentDir, wildCard;
+ const char* wildcardUTF8;
+ NSDirectoryEnumerator* enumerator;
+
+ Pimpl (const Pimpl&);
+ Pimpl& operator= (const Pimpl&);
};
-bool juce_findFileNext (void* handle, String& resultFile,
- bool* isDir, bool* isHidden, int64* fileSize, Time* modTime, Time* creationTime, bool* isReadOnly)
+DirectoryIterator::NativeIterator::NativeIterator (const File& directory, const String& wildCard)
+ : pimpl (new DirectoryIterator::NativeIterator::Pimpl (directory, wildCard))
{
- ScopedAutoReleasePool pool;
- FindFileStruct* ff = (FindFileStruct*) handle;
- NSString* file;
- const char* const wildcardUTF8 = ff->wildCard.toUTF8();
-
- for (;;)
- {
- if (ff == 0 || (file = [ff->enumerator nextObject]) == 0)
- return false;
-
- [ff->enumerator skipDescendents];
- resultFile = nsStringToJuce (file);
-
- if (fnmatch (wildcardUTF8, resultFile.toUTF8(), FNM_CASEFOLD) != 0)
- continue;
-
- const String path (ff->parentDir + resultFile);
-
- if (isDir != 0 || fileSize != 0)
- {
- struct stat info;
- const bool statOk = juce_stat (path, info);
-
- if (isDir != 0)
- *isDir = statOk && ((info.st_mode & S_IFDIR) != 0);
-
- if (isHidden != 0)
- *isHidden = juce_isHiddenFile (path);
-
- if (fileSize != 0)
- *fileSize = statOk ? info.st_size : 0;
- }
-
- if (modTime != 0 || creationTime != 0)
- {
- int64 m, a, c;
- juce_getFileTimes (path, m, a, c);
-
- if (modTime != 0)
- *modTime = m;
-
- if (creationTime != 0)
- *creationTime = c;
- }
-
- if (isReadOnly != 0)
- *isReadOnly = ! juce_canWriteToFile (path);
-
- return true;
- }
}
-void* juce_findFileStart (const String& directory, const String& wildCard, String& firstResultFile,
- bool* isDir, bool* isHidden, int64* fileSize, Time* modTime,
- Time* creationTime, bool* isReadOnly)
+DirectoryIterator::NativeIterator::~NativeIterator()
{
- ScopedAutoReleasePool pool;
- NSDirectoryEnumerator* e = [[NSFileManager defaultManager] enumeratorAtPath: juceStringToNS (directory)];
-
- if (e != 0)
- {
- ScopedPointer ff (new FindFileStruct());
- ff->enumerator = [e retain];
- ff->parentDir = directory;
- ff->wildCard = wildCard;
-
- if (! ff->parentDir.endsWithChar (File::separator))
- ff->parentDir += File::separator;
-
- if (juce_findFileNext (ff, firstResultFile, isDir, isHidden, fileSize, modTime, creationTime, isReadOnly))
- return ff.release();
-
- [e release];
- }
-
- return 0;
}
-void juce_findFileClose (void* handle)
+bool DirectoryIterator::NativeIterator::next (String& filenameFound,
+ bool* const isDir, bool* const isHidden, int64* const fileSize,
+ Time* const modTime, Time* const creationTime, bool* const isReadOnly)
{
- ScopedAutoReleasePool pool;
- ScopedPointer ff ((FindFileStruct*) handle);
- [ff->enumerator release];
+ return pimpl->next (filenameFound, isDir, isHidden, fileSize, modTime, creationTime, isReadOnly);
}
+
//==============================================================================
bool juce_launchExecutable (const String& pathAndArguments)
{
diff --git a/src/native/windows/juce_win32_Files.cpp b/src/native/windows/juce_win32_Files.cpp
index 98af5d5378..02fa7bbc2b 100644
--- a/src/native/windows/juce_win32_Files.cpp
+++ b/src/native/windows/juce_win32_Files.cpp
@@ -42,24 +42,26 @@
#endif
//==============================================================================
-const juce_wchar File::separator = '\\';
-const juce_wchar* File::separatorString = T("\\");
+const juce_wchar File::separator = '\\';
+const String File::separatorString ("\\");
//==============================================================================
-bool juce_fileExists (const String& fileName, const bool dontCountDirectories)
+bool File::exists() const
{
- if (fileName.isEmpty())
- return false;
-
- const DWORD attr = GetFileAttributes (fileName);
- return dontCountDirectories ? ((attr & FILE_ATTRIBUTE_DIRECTORY) == 0)
- : (attr != INVALID_FILE_ATTRIBUTES);
+ return fullPath.isNotEmpty()
+ && GetFileAttributes (fullPath) != INVALID_FILE_ATTRIBUTES;
}
-bool juce_isDirectory (const String& fileName)
+bool File::existsAsFile() const
{
- const DWORD attr = GetFileAttributes (fileName);
+ return fullPath.isNotEmpty()
+ && (GetFileAttributes (fullPath) & FILE_ATTRIBUTE_DIRECTORY) == 0;
+}
+
+bool File::isDirectory() const
+{
+ const DWORD attr = GetFileAttributes (fullPath);
return ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) && (attr != INVALID_FILE_ATTRIBUTES);
}
@@ -93,12 +95,14 @@ bool File::isHidden() const
}
//==============================================================================
-bool juce_deleteFile (const String& fileName)
+bool File::deleteFile() const
{
- if (juce_isDirectory (fileName))
- return RemoveDirectory (fileName) != 0;
-
- return DeleteFile (fileName) != 0;
+ if (! exists())
+ return true;
+ else if (isDirectory())
+ return RemoveDirectory (fullPath) != 0;
+ else
+ return DeleteFile (fullPath) != 0;
}
bool File::moveToTrash() const
@@ -132,21 +136,20 @@ bool juce_copyFile (const String& source, const String& dest)
return CopyFile (source, dest, false) != 0;
}
-void juce_createDirectory (const String& fileName)
+void File::createDirectoryInternal (const String& fileName) const
{
- if (! juce_fileExists (fileName, true))
- CreateDirectory (fileName, 0);
+ CreateDirectory (fileName, 0);
}
//==============================================================================
// return 0 if not possible
-void* juce_fileOpen (const String& fileName, bool forWriting)
+void* juce_fileOpen (const File& file, bool forWriting)
{
HANDLE h;
if (forWriting)
{
- h = CreateFile (fileName, GENERIC_WRITE, FILE_SHARE_READ, 0,
+ h = CreateFile (file.getFullPathName(), GENERIC_WRITE, FILE_SHARE_READ, 0,
OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
if (h != INVALID_HANDLE_VALUE)
@@ -156,7 +159,7 @@ void* juce_fileOpen (const String& fileName, bool forWriting)
}
else
{
- h = CreateFile (fileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0,
+ h = CreateFile (file.getFullPathName(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, 0);
if (h == INVALID_HANDLE_VALUE)
@@ -194,24 +197,28 @@ int64 juce_fileSetPosition (void* handle, int64 pos)
return li.QuadPart;
}
-int64 juce_fileGetPosition (void* handle)
+int64 FileOutputStream::getPositionInternal() const
{
+ if (fileHandle == 0)
+ return -1;
+
LARGE_INTEGER li;
li.QuadPart = 0;
- li.LowPart = SetFilePointer ((HANDLE) handle, 0, &li.HighPart, FILE_CURRENT); // (returns -1 if it fails)
+ li.LowPart = SetFilePointer ((HANDLE) fileHandle, 0, &li.HighPart, FILE_CURRENT); // (returns -1 if it fails)
return jmax ((int64) 0, li.QuadPart);
}
-void juce_fileFlush (void* handle)
+void FileOutputStream::flushInternal()
{
- FlushFileBuffers ((HANDLE) handle);
+ if (fileHandle != 0)
+ FlushFileBuffers ((HANDLE) fileHandle);
}
-int64 juce_getFileSize (const String& fileName)
+int64 File::getSize() const
{
WIN32_FILE_ATTRIBUTE_DATA attributes;
- if (GetFileAttributesEx (fileName, GetFileExInfoStandard, &attributes))
+ if (GetFileAttributesEx (fullPath, GetFileExInfoStandard, &attributes))
return (((int64) attributes.nFileSizeHigh) << 32) | attributes.nFileSizeLow;
return 0;
@@ -276,8 +283,7 @@ bool juce_setFileTimes (const String& fileName,
}
//==============================================================================
-// return '\0' separated list of strings
-const StringArray juce_getFileSystemRoots()
+void File::findFileSystemRoots (Array& destArray)
{
TCHAR buffer [2048];
buffer[0] = 0;
@@ -296,7 +302,9 @@ const StringArray juce_getFileSystemRoots()
}
roots.sort (true);
- return roots;
+
+ for (int i = 0; i < roots.size(); ++i)
+ destArray.add (roots [i]);
}
//==============================================================================
@@ -308,21 +316,26 @@ static const String getDriveFromPath (const String& path)
return path;
}
-const String juce_getVolumeLabel (const String& filenameOnVolume,
- int& volumeSerialNumber)
+const String File::getVolumeLabel() const
+{
+ TCHAR dest[64];
+ if (! GetVolumeInformation (getDriveFromPath (getFullPathName()), dest,
+ numElementsInArray (dest), 0, 0, 0, 0, 0))
+ dest[0] = 0;
+
+ return dest;
+}
+
+int File::getVolumeSerialNumber() const
{
TCHAR dest[64];
DWORD serialNum;
- if (! GetVolumeInformation (getDriveFromPath (filenameOnVolume), dest,
+ if (! GetVolumeInformation (getDriveFromPath (getFullPathName()), dest,
numElementsInArray (dest), &serialNum, 0, 0, 0, 0))
- {
- dest[0] = 0;
- serialNum = 0;
- }
+ return 0;
- volumeSerialNumber = serialNum;
- return dest;
+ return (int) serialNum;
}
static int64 getDiskSpaceInfo (const String& path, const bool total)
@@ -513,80 +526,79 @@ const File File::getLinkedTarget() const
//==============================================================================
-template
-static void getFindFileInfo (FindDataType& findData,
- String& filename, bool* const isDir, bool* const isHidden,
- int64* const fileSize, Time* const modTime, Time* const creationTime,
- bool* const isReadOnly)
+class DirectoryIterator::NativeIterator::Pimpl
{
- filename = findData.cFileName;
-
- if (isDir != 0)
- *isDir = ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0);
-
- if (isHidden != 0)
- *isHidden = ((findData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) != 0);
-
- if (fileSize != 0)
- *fileSize = findData.nFileSizeLow + (((int64) findData.nFileSizeHigh) << 32);
-
- if (modTime != 0)
- *modTime = fileTimeToTime (&findData.ftLastWriteTime);
-
- if (creationTime != 0)
- *creationTime = fileTimeToTime (&findData.ftCreationTime);
-
- if (isReadOnly != 0)
- *isReadOnly = ((findData.dwFileAttributes & FILE_ATTRIBUTE_READONLY) != 0);
-}
-
-void* juce_findFileStart (const String& directory, const String& wildCard, String& firstResult,
- bool* isDir, bool* isHidden, int64* fileSize,
- Time* modTime, Time* creationTime, bool* isReadOnly)
-{
- String wc (directory);
-
- if (! wc.endsWithChar (File::separator))
- wc += File::separator;
-
- wc += wildCard;
-
- WIN32_FIND_DATA findData;
- HANDLE h = FindFirstFile (wc, &findData);
-
- if (h != INVALID_HANDLE_VALUE)
+public:
+ Pimpl (const File& directory, const String& wildCard)
+ : directoryWithWildCard (File::addTrailingSeparator (directory.getFullPathName()) + wildCard),
+ handle (INVALID_HANDLE_VALUE)
{
- getFindFileInfo (findData, firstResult, isDir, isHidden, fileSize,
- modTime, creationTime, isReadOnly);
- return h;
}
- firstResult = String::empty;
- return 0;
-}
-
-bool juce_findFileNext (void* handle, String& resultFile,
- bool* isDir, bool* isHidden, int64* fileSize,
- Time* modTime, Time* creationTime, bool* isReadOnly)
-{
- WIN32_FIND_DATA findData;
-
- if (handle != 0 && FindNextFile ((HANDLE) handle, &findData) != 0)
+ ~Pimpl()
{
- getFindFileInfo (findData, resultFile, isDir, isHidden, fileSize,
- modTime, creationTime, isReadOnly);
+ if (handle != INVALID_HANDLE_VALUE)
+ FindClose (handle);
+ }
+
+ bool next (String& filenameFound,
+ bool* const isDir, bool* const isHidden, int64* const fileSize,
+ Time* const modTime, Time* const creationTime, bool* const isReadOnly)
+ {
+ WIN32_FIND_DATA findData;
+
+ if (handle == INVALID_HANDLE_VALUE)
+ {
+ handle = FindFirstFile (directoryWithWildCard, &findData);
+
+ if (handle == INVALID_HANDLE_VALUE)
+ return false;
+ }
+ else
+ {
+ if (FindNextFile (handle, &findData) == 0)
+ return false;
+ }
+
+ filenameFound = findData.cFileName;
+
+ if (isDir != 0) *isDir = ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0);
+ if (isHidden != 0) *isHidden = ((findData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) != 0);
+ if (fileSize != 0) *fileSize = findData.nFileSizeLow + (((int64) findData.nFileSizeHigh) << 32);
+ if (modTime != 0) *modTime = fileTimeToTime (&findData.ftLastWriteTime);
+ if (creationTime != 0) *creationTime = fileTimeToTime (&findData.ftCreationTime);
+ if (isReadOnly != 0) *isReadOnly = ((findData.dwFileAttributes & FILE_ATTRIBUTE_READONLY) != 0);
+
return true;
}
- resultFile = String::empty;
- return false;
+ juce_UseDebuggingNewOperator
+
+private:
+ const String directoryWithWildCard;
+ HANDLE handle;
+
+ Pimpl (const Pimpl&);
+ Pimpl& operator= (const Pimpl&);
+};
+
+DirectoryIterator::NativeIterator::NativeIterator (const File& directory, const String& wildCard)
+ : pimpl (new DirectoryIterator::NativeIterator::Pimpl (directory, wildCard))
+{
}
-void juce_findFileClose (void* handle)
+DirectoryIterator::NativeIterator::~NativeIterator()
{
- FindClose (handle);
}
+bool DirectoryIterator::NativeIterator::next (String& filenameFound,
+ bool* const isDir, bool* const isHidden, int64* const fileSize,
+ Time* const modTime, Time* const creationTime, bool* const isReadOnly)
+{
+ return pimpl->next (filenameFound, isDir, isHidden, fileSize, modTime, creationTime, isReadOnly);
+}
+
+
//==============================================================================
bool juce_launchFile (const String& fileName, const String& parameters)
{
diff --git a/src/text/juce_String.cpp b/src/text/juce_String.cpp
index 088c314109..3e20c49e76 100644
--- a/src/text/juce_String.cpp
+++ b/src/text/juce_String.cpp
@@ -1542,10 +1542,7 @@ const String String::trimCharactersAtStart (const String& charactersToTrim) cons
while (charactersToTrim.containsChar (*t))
++t;
- if (t == text)
- return *this;
-
- return String (t);
+ return t == text ? *this : String (t);
}
const String String::trimCharactersAtEnd (const String& charactersToTrim) const
@@ -1553,12 +1550,17 @@ const String String::trimCharactersAtEnd (const String& charactersToTrim) const
if (isEmpty())
return empty;
- const juce_wchar* endT = text + (length() - 1);
+ const int len = length();
+ const juce_wchar* endT = text + (len - 1);
+ int numToRemove = 0;
- while (endT >= text && charactersToTrim.containsChar (*endT))
+ while (numToRemove < len && charactersToTrim.containsChar (*endT))
+ {
+ ++numToRemove;
--endT;
+ }
- return String (text, (int) (++endT - text));
+ return numToRemove > 0 ? String (text, len - numToRemove) : *this;
}
//==============================================================================
diff --git a/src/text/juce_StringArray.cpp b/src/text/juce_StringArray.cpp
index 2b88bba2d6..c27a6f5995 100644
--- a/src/text/juce_StringArray.cpp
+++ b/src/text/juce_StringArray.cpp
@@ -461,10 +461,10 @@ void StringArray::appendNumbersToDuplicates (const bool ignoreCase,
const juce_wchar* postNumberString)
{
if (preNumberString == 0)
- preNumberString = T(" (");
+ preNumberString = L" (";
if (postNumberString == 0)
- postNumberString = T(")");
+ postNumberString = L")";
for (int i = 0; i < size() - 1; ++i)
{
diff --git a/src/text/juce_XmlDocument.cpp b/src/text/juce_XmlDocument.cpp
index 40f4ef4a03..f2f71604b9 100644
--- a/src/text/juce_XmlDocument.cpp
+++ b/src/text/juce_XmlDocument.cpp
@@ -759,9 +759,7 @@ const String XmlDocument::expandExternalEntity (const String& entity)
{
if (dtdText.isNotEmpty())
{
- while (dtdText.endsWithChar ('>'))
- dtdText = dtdText.dropLastCharacters (1);
-
+ dtdText = dtdText.trimCharactersAtEnd (">");
tokenisedDTD.addTokens (dtdText, true);
if (tokenisedDTD [tokenisedDTD.size() - 2].equalsIgnoreCase ("system")
@@ -813,12 +811,7 @@ const String XmlDocument::expandExternalEntity (const String& entity)
{
if (tokenisedDTD[i - 1].equalsIgnoreCase ("'))
- ent = ent.dropLastCharacters (1);
-
- ent = ent.trim().unquoted();
+ String ent (tokenisedDTD [i + 1].trimCharactersAtEnd (">").trim().unquoted());
// check for sub-entities..
int ampersand = ent.indexOfChar ('&');
@@ -861,24 +854,12 @@ const String XmlDocument::getParameterEntity (const String& entity)
if (tokenisedDTD [i - 1] == "%"
&& tokenisedDTD [i - 2].equalsIgnoreCase ("'))
- ent = ent.dropLastCharacters (1);
+ const String ent (tokenisedDTD [i + 1].trimCharactersAtEnd (">"));
if (ent.equalsIgnoreCase ("system"))
- {
- String filename (tokenisedDTD [i + 2]);
-
- while (filename.endsWithChar ('>'))
- filename = filename.dropLastCharacters (1);
-
- return getFileContents (filename);
- }
+ return getFileContents (tokenisedDTD [i + 2].trimCharactersAtEnd (">"));
else
- {
return ent.trim().unquoted();
- }
}
}
}
diff --git a/src/text/juce_XmlElement.cpp b/src/text/juce_XmlElement.cpp
index 6b36cb3dd9..87bed1d850 100644
--- a/src/text/juce_XmlElement.cpp
+++ b/src/text/juce_XmlElement.cpp
@@ -1078,7 +1078,7 @@ bool XmlElement::isTextElement() const throw()
return tagName.isEmpty();
}
-static const juce_wchar* const juce_xmltextContentAttributeName = T("text");
+static const juce_wchar* const juce_xmltextContentAttributeName = L"text";
const String XmlElement::getText() const throw()
{