Clean up pointer use:

* Use unique_ptr for Actions instead of manual memory management
 * Use unique_ptr in KeywordDatabase
 * Use unique_ptr instead of shared_ptr for file formats
 * Don't pass shared_ptr to Reader/Writer, use references instead
Also
 * Switch to C++17 so we can use map::try_emplace
This commit is contained in:
Twan van Laarhoven
2020-04-25 21:30:05 +02:00
parent 708b4389a0
commit 64ea1d7322
57 changed files with 363 additions and 385 deletions
+1 -1
View File
@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.13)
project(magicseteditor) project(magicseteditor)
set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True) set(CMAKE_CXX_STANDARD_REQUIRED True)
find_package(wxWidgets 3 REQUIRED COMPONENTS core base net html) find_package(wxWidgets 3 REQUIRED COMPONENTS core base net html)
+15 -6
View File
@@ -97,6 +97,7 @@ ControlPointMoveAction::ControlPointMoveAction(const set<ControlPointP>& points)
FOR_EACH(p, points) { FOR_EACH(p, points) {
oldValues.push_back(p->pos); oldValues.push_back(p->pos);
} }
perform(false);
} }
String ControlPointMoveAction::getName(bool to_undo) const { String ControlPointMoveAction::getName(bool to_undo) const {
@@ -104,12 +105,15 @@ String ControlPointMoveAction::getName(bool to_undo) const {
} }
void ControlPointMoveAction::perform(bool to_undo) { void ControlPointMoveAction::perform(bool to_undo) {
if (to_undo != done) return;
done = !to_undo;
FOR_EACH_2(p,points, op,oldValues) { FOR_EACH_2(p,points, op,oldValues) {
swap(p->pos, op); swap(p->pos, op);
} }
} }
void ControlPointMoveAction::move (const Vector2D& deltaDelta) { void ControlPointMoveAction::move(const Vector2D& deltaDelta) {
assert(done);
delta += deltaDelta; delta += deltaDelta;
// Move each point by delta, possibly constrained // Move each point by delta, possibly constrained
set<ControlPointP>::const_iterator it = points.begin(); set<ControlPointP>::const_iterator it = points.begin();
@@ -128,18 +132,23 @@ HandleMoveAction::HandleMoveAction(const SelectedHandle& handle)
, old_other (handle.getOther()) , old_other (handle.getOther())
, constrain(false) , constrain(false)
, snap(0) , snap(0)
{} {
perform(false);
}
String HandleMoveAction::getName(bool to_undo) const { String HandleMoveAction::getName(bool to_undo) const {
return _ACTION_("move handle"); return _ACTION_("move handle");
} }
void HandleMoveAction::perform(bool to_undo) { void HandleMoveAction::perform(bool to_undo) {
if (to_undo != done) return;
done = !to_undo;
swap(old_handle, handle.getHandle()); swap(old_handle, handle.getHandle());
swap(old_other, handle.getOther()); swap(old_other, handle.getOther());
} }
void HandleMoveAction::move(const Vector2D& deltaDelta) { void HandleMoveAction::move(const Vector2D& deltaDelta) {
assert(done);
delta += deltaDelta; delta += deltaDelta;
handle.getHandle() = constrain_snap_vector_offset(handle.point->pos, old_handle + delta, constrain, snap); handle.getHandle() = constrain_snap_vector_offset(handle.point->pos, old_handle + delta, constrain, snap);
handle.getOther() = old_other; handle.getOther() = old_other;
@@ -246,7 +255,7 @@ void CurveDragAction::move(const Vector2D& delta, double t) {
ControlPointAddAction::ControlPointAddAction(const SymbolShapeP& shape, UInt insert_after, double t) ControlPointAddAction::ControlPointAddAction(const SymbolShapeP& shape, UInt insert_after, double t)
: shape(shape) : shape(shape)
, new_point(new ControlPoint()) , new_point(make_shared<ControlPoint>())
, insert_after(insert_after) , insert_after(insert_after)
, point1(shape->getPoint(insert_after)) , point1(shape->getPoint(insert_after))
, point2(shape->getPoint(insert_after + 1)) , point2(shape->getPoint(insert_after + 1))
@@ -419,13 +428,13 @@ void ControlPointRemoveAction::perform(bool to_undo) {
} }
Action* control_point_remove_action(const SymbolShapeP& shape, const set<ControlPointP>& to_delete) { unique_ptr<Action> control_point_remove_action(const SymbolShapeP& shape, const set<ControlPointP>& to_delete) {
if (shape->points.size() - to_delete.size() < 2) { if (shape->points.size() - to_delete.size() < 2) {
// TODO : remove part? // TODO : remove part?
//make_intrusive<ControlPointRemoveAllAction>(part); //make_intrusive<ControlPointRemoveAllAction>(part);
return 0; // no action return unique_ptr<Action>(); // no action
} else { } else {
return new ControlPointRemoveAction(shape, to_delete); return make_unique<ControlPointRemoveAction>(shape, to_delete);
} }
} }
+11 -3
View File
@@ -40,10 +40,18 @@ Vector2D constrain_snap_vector_offset(const Vector2D& off1, const Vector2D& d, b
/** Takes the closest snap */ /** Takes the closest snap */
Vector2D constrain_snap_vector_offset(const Vector2D& off1, const Vector2D& off2, const Vector2D& d, bool constrain, int steps); Vector2D constrain_snap_vector_offset(const Vector2D& off1, const Vector2D& off2, const Vector2D& d, bool constrain, int steps);
// ----------------------------------------------------------------------------- : Base class
/// An action that by itself doesn't do anything, but can later be extended after it is performed
class ExtendableAction : public Action {
protected:
bool done = false;
};
// ----------------------------------------------------------------------------- : Move control point // ----------------------------------------------------------------------------- : Move control point
/// Moving a control point in a symbol /// Moving a control point in a symbol
class ControlPointMoveAction : public Action { class ControlPointMoveAction : public ExtendableAction {
public: public:
ControlPointMoveAction(const set<ControlPointP>& points); ControlPointMoveAction(const set<ControlPointP>& points);
@@ -65,7 +73,7 @@ class ControlPointMoveAction : public Action {
// ----------------------------------------------------------------------------- : Move handle // ----------------------------------------------------------------------------- : Move handle
/// Moving a handle(before/after) of a control point in a symbol /// Moving a handle(before/after) of a control point in a symbol
class HandleMoveAction : public Action { class HandleMoveAction : public ExtendableAction {
public: public:
HandleMoveAction(const SelectedHandle& handle); HandleMoveAction(const SelectedHandle& handle);
@@ -169,7 +177,7 @@ class ControlPointAddAction : public Action {
/// Action that removes any number of points from a symbol shape /// Action that removes any number of points from a symbol shape
/// TODO: If less then 3 points are left removes the entire shape? /// TODO: If less then 3 points are left removes the entire shape?
Action* control_point_remove_action(const SymbolShapeP& shape, const set<ControlPointP>& to_delete); unique_ptr<Action> control_point_remove_action(const SymbolShapeP& shape, const set<ControlPointP>& to_delete);
+24 -14
View File
@@ -81,14 +81,24 @@ class SimpleValueAction : public ValueAction {
typename T::ValueType new_value; typename T::ValueType new_value;
}; };
ValueAction* value_action(const ChoiceValueP& value, const Defaultable<String>& new_value) { return new SimpleValueAction<ChoiceValue, true> (value, new_value); } unique_ptr<ValueAction> value_action(const ChoiceValueP& value, const Defaultable<String>& new_value) {
ValueAction* value_action(const ColorValueP& value, const Defaultable<Color>& new_value) { return new SimpleValueAction<ColorValue, true> (value, new_value); } return make_unique<SimpleValueAction<ChoiceValue, true>>(value, new_value);
ValueAction* value_action(const ImageValueP& value, const FileName& new_value) { return new SimpleValueAction<ImageValue, false>(value, new_value); } }
ValueAction* value_action(const SymbolValueP& value, const FileName& new_value) { return new SimpleValueAction<SymbolValue, false>(value, new_value); } unique_ptr<ValueAction> value_action(const ColorValueP& value, const Defaultable<Color>& new_value) {
ValueAction* value_action(const PackageChoiceValueP& value, const String& new_value) { return new SimpleValueAction<PackageChoiceValue, false>(value, new_value); } return make_unique<SimpleValueAction<ColorValue, true>>(value, new_value);
ValueAction* value_action(const MultipleChoiceValueP& value, const Defaultable<String>& new_value, const String& last_change) { }
unique_ptr<ValueAction> value_action(const ImageValueP& value, const FileName& new_value) {
return make_unique<SimpleValueAction<ImageValue, false>>(value, new_value);
}
unique_ptr<ValueAction> value_action(const SymbolValueP& value, const FileName& new_value) {
return make_unique<SimpleValueAction<SymbolValue, false>>(value, new_value);
}
unique_ptr<ValueAction> value_action(const PackageChoiceValueP& value, const String& new_value) {
return make_unique<SimpleValueAction<PackageChoiceValue, false>>(value, new_value);
}
unique_ptr<ValueAction> value_action(const MultipleChoiceValueP& value, const Defaultable<String>& new_value, const String& last_change) {
MultipleChoiceValue::ValueType v = { new_value, last_change }; MultipleChoiceValue::ValueType v = { new_value, last_change };
return new SimpleValueAction<MultipleChoiceValue, false>(value, v); return make_unique<SimpleValueAction<MultipleChoiceValue, false>>(value, v);
} }
@@ -133,7 +143,7 @@ TextValue& TextValueAction::value() const {
} }
TextValueAction* toggle_format_action(const TextValueP& value, const String& tag, size_t start_i, size_t end_i, size_t start, size_t end, const String& action_name) { unique_ptr<TextValueAction> toggle_format_action(const TextValueP& value, const String& tag, size_t start_i, size_t end_i, size_t start, size_t end, const String& action_name) {
if (start > end) { if (start > end) {
swap(start, end); swap(start, end);
swap(start_i, end_i); swap(start_i, end_i);
@@ -165,11 +175,11 @@ TextValueAction* toggle_format_action(const TextValueP& value, const String& tag
if (value->value() == new_value) { if (value->value() == new_value) {
return nullptr; // no changes return nullptr; // no changes
} else { } else {
return new TextValueAction(value, start, end, end, new_value, action_name); return make_unique<TextValueAction>(value, start, end, end, new_value, action_name);
} }
} }
TextValueAction* typing_action(const TextValueP& value, size_t start_i, size_t end_i, size_t start, size_t end, const String& replacement, const String& action_name) { unique_ptr<TextValueAction> typing_action(const TextValueP& value, size_t start_i, size_t end_i, size_t start, size_t end, const String& replacement, const String& action_name) {
bool reverse = start > end; bool reverse = start > end;
if (reverse) { if (reverse) {
swap(start, end); swap(start, end);
@@ -181,9 +191,9 @@ TextValueAction* typing_action(const TextValueP& value, size_t start_i, size_t e
return nullptr; return nullptr;
} else { } else {
if (reverse) { if (reverse) {
return new TextValueAction(value, end, start, start+untag(replacement).size(), new_value, action_name); return make_unique<TextValueAction>(value, end, start, start+untag(replacement).size(), new_value, action_name);
} else { } else {
return new TextValueAction(value, start, end, start+untag(replacement).size(), new_value, action_name); return make_unique<TextValueAction>(value, start, end, start+untag(replacement).size(), new_value, action_name);
} }
} }
} }
@@ -248,9 +258,9 @@ ValueActionPerformer::ValueActionPerformer(const ValueP& value, Card* card, cons
{} {}
ValueActionPerformer::~ValueActionPerformer() {} ValueActionPerformer::~ValueActionPerformer() {}
void ValueActionPerformer::addAction(ValueAction* action) { void ValueActionPerformer::addAction(unique_ptr<ValueAction>&& action) {
action->isOnCard(card); action->isOnCard(card);
set->actions.addAction(action); set->actions.addAction(move(action));
} }
Package& ValueActionPerformer::getLocalPackage() { Package& ValueActionPerformer::getLocalPackage() {
+9 -9
View File
@@ -55,12 +55,12 @@ class ValueAction : public Action {
// ----------------------------------------------------------------------------- : Simple // ----------------------------------------------------------------------------- : Simple
/// Action that updates a Value to a new value /// Action that updates a Value to a new value
ValueAction* value_action(const ChoiceValueP& value, const Defaultable<String>& new_value); unique_ptr<ValueAction> value_action(const ChoiceValueP& value, const Defaultable<String>& new_value);
ValueAction* value_action(const MultipleChoiceValueP& value, const Defaultable<String>& new_value, const String& last_change); unique_ptr<ValueAction> value_action(const MultipleChoiceValueP& value, const Defaultable<String>& new_value, const String& last_change);
ValueAction* value_action(const ColorValueP& value, const Defaultable<Color>& new_value); unique_ptr<ValueAction> value_action(const ColorValueP& value, const Defaultable<Color>& new_value);
ValueAction* value_action(const ImageValueP& value, const FileName& new_value); unique_ptr<ValueAction> value_action(const ImageValueP& value, const FileName& new_value);
ValueAction* value_action(const SymbolValueP& value, const FileName& new_value); unique_ptr<ValueAction> value_action(const SymbolValueP& value, const FileName& new_value);
ValueAction* value_action(const PackageChoiceValueP& value, const String& new_value); unique_ptr<ValueAction> value_action(const PackageChoiceValueP& value, const String& new_value);
// ----------------------------------------------------------------------------- : Text // ----------------------------------------------------------------------------- : Text
@@ -86,11 +86,11 @@ class TextValueAction : public ValueAction {
}; };
/// Action for toggling some formating tag on or off in some range /// Action for toggling some formating tag on or off in some range
TextValueAction* toggle_format_action(const TextValueP& value, const String& tag, size_t start_i, size_t end_i, size_t start, size_t end, const String& action_name); unique_ptr<TextValueAction> toggle_format_action(const TextValueP& value, const String& tag, size_t start_i, size_t end_i, size_t start, size_t end, const String& action_name);
/// Typing in a TextValue, replace the selection [start...end) with replacement /// Typing in a TextValue, replace the selection [start...end) with replacement
/** start and end are cursor positions, start_i and end_i are indices*/ /** start and end are cursor positions, start_i and end_i are indices*/
TextValueAction* typing_action(const TextValueP& value, size_t start_i, size_t end_i, size_t start, size_t end, const String& replacement, const String& action_name); unique_ptr<TextValueAction> typing_action(const TextValueP& value, size_t start_i, size_t end_i, size_t start, size_t end, const String& replacement, const String& action_name);
// ----------------------------------------------------------------------------- : Reminder text // ----------------------------------------------------------------------------- : Reminder text
@@ -169,7 +169,7 @@ class ValueActionPerformer {
ValueActionPerformer(const ValueP& value, Card* card, const SetP& set); ValueActionPerformer(const ValueP& value, Card* card, const SetP& set);
~ValueActionPerformer(); ~ValueActionPerformer();
/// Perform an action. The performer takes ownerwhip of the action. /// Perform an action. The performer takes ownerwhip of the action.
void addAction(ValueAction* action); void addAction(unique_ptr<ValueAction>&& action);
const ValueP value; ///< The value const ValueP value; ///< The value
Package& getLocalPackage(); Package& getLocalPackage();
+1 -1
View File
@@ -47,6 +47,6 @@ void AddCardsScript::perform(Set& set) {
// Add to set // Add to set
if (!cards.empty()) { if (!cards.empty()) {
// TODO: change the name of the action somehow // TODO: change the name of the action somehow
set.actions.addAction(new AddCardAction(ADD, set, cards)); set.actions.addAction(make_unique<AddCardAction>(ADD, set, cards));
} }
} }
+5 -5
View File
@@ -284,11 +284,11 @@ inline String type_name(const Value&) {
return _(NAME); \ return _(NAME); \
} }
#define DECLARE_STYLE_TYPE(Type) \ #define DECLARE_STYLE_TYPE(Type) \
DECLARE_REFLECTION(); public: \ DECLARE_REFLECTION(); public: \
DECLARE_HAS_FIELD(Type) \ DECLARE_HAS_FIELD(Type) \
virtual StyleP clone() const; \ virtual StyleP clone() const; \
virtual ValueViewerP makeViewer(DataViewer& parent, const StyleP& thisP); \ virtual ValueViewerP makeViewer(DataViewer& parent, const StyleP& thisP); \
virtual ValueViewerP makeEditor(DataEditor& parent, const StyleP& thisP) virtual ValueViewerP makeEditor(DataEditor& parent, const StyleP& thisP)
#define DECLARE_VALUE_TYPE(Type,ValueType_) \ #define DECLARE_VALUE_TYPE(Type,ValueType_) \
+1 -1
View File
@@ -190,7 +190,7 @@ void ChoiceStyle::initImage() {
// CALL 0 // CALL 0
// PUSH_CONST nil // PUSH_CONST nil
// OR_ELSE // OR_ELSE
ScriptCustomCollectionP lookup(new ScriptCustomCollection()); ScriptCustomCollectionP lookup = make_intrusive<ScriptCustomCollection>();
FOR_EACH(ci, choice_images) { FOR_EACH(ci, choice_images) {
lookup->key_value[uncanonical_name_form(ci.first)] = lookup->key_value[uncanonical_name_form(ci.first)] =
lookup->key_value[ci.first] = ci.second.getValidScriptP(); lookup->key_value[ci.first] = ci.second.getValidScriptP();
+1 -1
View File
@@ -301,7 +301,7 @@ void ApprDistroDatabase::removeSet(const String& code) {
// TODO ? // TODO ?
} }
void ApprDistroDatabase::doRead(InputStream& in) { void ApprDistroDatabase::doRead(wxInputStream& in) {
wxTextInputStream tin(in); wxTextInputStream tin(in);
ApprDistro* last = 0; ApprDistro* last = 0;
while (!in.Eof()) { while (!in.Eof()) {
+3 -3
View File
@@ -23,16 +23,16 @@
/// Serialize an object to a string, clipboard_package will be set to the given package. /// Serialize an object to a string, clipboard_package will be set to the given package.
template <typename T> template <typename T>
String serialize_for_clipboard(Package& package, T& object) { String serialize_for_clipboard(Package& package, T& object) {
shared_ptr<wxStringOutputStream> stream( new wxStringOutputStream ); wxStringOutputStream stream;
Writer writer(stream, file_version_clipboard); Writer writer(stream, file_version_clipboard);
WITH_DYNAMIC_ARG(clipboard_package, &package); WITH_DYNAMIC_ARG(clipboard_package, &package);
writer.handle(object); writer.handle(object);
return stream->GetString(); return stream.GetString();
} }
template <typename T> template <typename T>
void deserialize_from_clipboard(T& object, Package& package, const String& data) { void deserialize_from_clipboard(T& object, Package& package, const String& data) {
shared_ptr<wxStringInputStream> stream( new wxStringInputStream(data) ); wxStringInputStream stream = {data};
Reader reader(stream, nullptr, _("clipboard")); Reader reader(stream, nullptr, _("clipboard"));
WITH_DYNAMIC_ARG(clipboard_package, &package); WITH_DYNAMIC_ARG(clipboard_package, &package);
reader.handle_greedy(object); reader.handle_greedy(object);
+7 -15
View File
@@ -21,14 +21,6 @@
#include <wx/zipstrm.h> #include <wx/zipstrm.h>
#include <wx/stdpaths.h> #include <wx/stdpaths.h>
DECLARE_TYPEOF_COLLECTION(String);
DECLARE_TYPEOF_COLLECTION(PackagedP);
DECLARE_TYPEOF_COLLECTION(PackageDependencyP);
DECLARE_TYPEOF_COLLECTION(PackageDescriptionP);
DECLARE_TYPEOF_COLLECTION(InstallablePackageP);
DECLARE_POINTER_TYPE(wxFileInputStream);
DECLARE_POINTER_TYPE(wxZipInputStream);
// Don't do this check for now, because we can't bless packages // Don't do this check for now, because we can't bless packages
#define USE_MODIFIED_CHECK 0 #define USE_MODIFIED_CHECK 0
@@ -50,8 +42,8 @@ void Installer::validate(Version file_app_version) {
// TODO: support absolute icon names // TODO: support absolute icon names
try{ try{
String filename = p->name + _("/") + p->icon_url; String filename = p->name + _("/") + p->icon_url;
InputStreamP img = openIn(p->name + _("/") + p->icon_url); auto img_stream = openIn(p->name + _("/") + p->icon_url);
image_load_file(p->icon, *img); image_load_file(p->icon, *img_stream);
} catch (...) { } catch (...) {
// ignore errors, it's just an image // ignore errors, it's just an image
p->icon_url.clear(); p->icon_url.clear();
@@ -195,9 +187,9 @@ void Installer::addPackage(Packaged& package) {
const FileInfos& file_infos = package.getFileInfos(); const FileInfos& file_infos = package.getFileInfos();
for (FileInfos::const_iterator it = file_infos.begin() ; it != file_infos.end() ; ++it) { for (FileInfos::const_iterator it = file_infos.begin() ; it != file_infos.end() ; ++it) {
String file = it->first; String file = it->first;
InputStreamP is = package.openIn(file); auto in_stream = package.openIn(file);
OutputStreamP os = openOut(name + _("/") + file); auto out_stream = openOut(name + _("/") + file);
os->Write(*is); out_stream->Write(*in_stream);
} }
} }
@@ -235,8 +227,8 @@ PackageDescription::PackageDescription(const Packaged& package)
} }
} }
// icon // icon
InputStreamP file = const_cast<Packaged&>(package).openIconFile(); auto file_stream = const_cast<Packaged&>(package).openIconFile();
if (file) image_load_file(icon, *file); if (file_stream) image_load_file(icon, *file_stream);
} }
IMPLEMENT_REFLECTION_NO_SCRIPT(PackageDescription) { IMPLEMENT_REFLECTION_NO_SCRIPT(PackageDescription) {
+27 -34
View File
@@ -256,13 +256,13 @@ class KeywordTrie {
KeywordTrie(); KeywordTrie();
~KeywordTrie(); ~KeywordTrie();
map<Char, KeywordTrie*> children; ///< children after a given character (owned) map<wxUniChar, unique_ptr<KeywordTrie>> children; ///< children after a given character
KeywordTrie* on_any_star; ///< children on /.*/ (owned or this) KeywordTrie* on_any_star; ///< children on /.*/ (owned or this)
vector<const Keyword*> finished; ///< keywordss that end in this node vector<const Keyword*> finished; ///< keywords that end in this node
/// Insert nodes representing the given character /// Insert nodes representing the given character
/** return the node where the evaluation will be after matching the character */ /** return the node where the evaluation will be after matching the character */
KeywordTrie* insert(Char match); KeywordTrie* insert(wxUniChar match);
/// Insert nodes representing the given string /// Insert nodes representing the given string
/** return the node where the evaluation will be after matching the string */ /** return the node where the evaluation will be after matching the string */
KeywordTrie* insert(const String& match); KeywordTrie* insert(const String& match);
@@ -276,32 +276,28 @@ class KeywordTrie {
KeywordTrie::KeywordTrie() KeywordTrie::KeywordTrie()
: on_any_star(nullptr) : on_any_star(nullptr)
{} {}
KeywordTrie::~KeywordTrie() { KeywordTrie::~KeywordTrie() {
FOR_EACH(c, children) {
delete c.second;
}
if (on_any_star != this) delete on_any_star; if (on_any_star != this) delete on_any_star;
} }
KeywordTrie* KeywordTrie::insert(Char c) { KeywordTrie* KeywordTrie::insert(wxUniChar c) {
#if USE_CASE_INSENSITIVE_KEYWORDS #if USE_CASE_INSENSITIVE_KEYWORDS
c = toLower(c); // case insensitive matching c = toLower(c); // case insensitive matching
#endif #endif
KeywordTrie*& child = children[c]; unique_ptr<KeywordTrie>& child = children[c];
if (!child) child = new KeywordTrie; if (!child) child.reset(new KeywordTrie);
return child; return child.get();
} }
KeywordTrie* KeywordTrie::insert(const String& match) { KeywordTrie* KeywordTrie::insert(const String& match) {
KeywordTrie* cur = this; KeywordTrie* cur = this;
FOR_EACH_CONST(c, match) { for (wxUniChar c : match) {
cur = cur->insert(static_cast<Char>(c)); cur = cur->insert(c);
} }
return cur; return cur;
} }
KeywordTrie* KeywordTrie::insertAnyStar() { KeywordTrie* KeywordTrie::insertAnyStar() {
if (!on_any_star) on_any_star = new KeywordTrie; if (!on_any_star) on_any_star = new KeywordTrie();
on_any_star->on_any_star = on_any_star; // circular reference to itself on_any_star->on_any_star = on_any_star; // circular reference to itself
return on_any_star; return on_any_star;
} }
@@ -314,14 +310,11 @@ IMPLEMENT_DYNAMIC_ARG(KeywordUsageStatistics*, keyword_usage_statistics, nullptr
KeywordDatabase::KeywordDatabase() KeywordDatabase::KeywordDatabase()
: root(nullptr) : root(nullptr)
{} {}
// Note: has to be here because in the header KeywordTrie is not defined
KeywordDatabase::~KeywordDatabase() { KeywordDatabase::~KeywordDatabase() {}
clear();
}
void KeywordDatabase::clear() { void KeywordDatabase::clear() {
delete root; root.reset();
root = nullptr;
} }
void KeywordDatabase::add(const vector<KeywordP>& kws) { void KeywordDatabase::add(const vector<KeywordP>& kws) {
@@ -334,8 +327,8 @@ void KeywordDatabase::add(const Keyword& kw) {
if (kw.match.empty() || !kw.valid) return; // can't handle empty keywords if (kw.match.empty() || !kw.valid) return; // can't handle empty keywords
// Create root // Create root
if (!root) { if (!root) {
root = new KeywordTrie; root = make_unique<KeywordTrie>();
root->on_any_star = root; root->on_any_star = root.get();
} }
KeywordTrie* cur = root->insertAnyStar(); KeywordTrie* cur = root->insertAnyStar();
// Add to trie // Add to trie
@@ -384,7 +377,7 @@ void KeywordDatabase::prepare_parameters(const vector<KeywordParamP>& ps, const
// ----------------------------------------------------------------------------- : KeywordDatabase : matching // ----------------------------------------------------------------------------- : KeywordDatabase : matching
// transitive closure of a state, follow all on_any_star links // transitive closure of a state, follow all on_any_star links
void closure(vector<KeywordTrie*>& state) { void closure(vector<const KeywordTrie*>& state) {
for (size_t j = 0 ; j < state.size() ; ++j) { for (size_t j = 0 ; j < state.size() ; ++j) {
if (state[j]->on_any_star && state[j]->on_any_star != state[j]) { if (state[j]->on_any_star && state[j]->on_any_star != state[j]) {
state.push_back(state[j]->on_any_star); state.push_back(state[j]->on_any_star);
@@ -393,10 +386,10 @@ void closure(vector<KeywordTrie*>& state) {
} }
#ifdef _DEBUG #ifdef _DEBUG
void dump(int i, KeywordTrie* t) { void dump(int i, const KeywordTrie* t) {
FOR_EACH(c, t->children) { FOR_EACH(c, t->children) {
wxLogDebug(String(i,_(' ')) + c.first + _(" ") + String::Format(_("%p"),c.second)); wxLogDebug(String(i,_(' ')) + c.first + _(" ") + String::Format(_("%p"),c.second.get()));
dump(i+2, c.second); dump(i+2, c.second.get());
} }
if (t->on_any_star) { if (t->on_any_star) {
wxLogDebug(String(i,_(' ')) + _(".*") + _(" ") + String::Format(_("%p"),t->on_any_star)); wxLogDebug(String(i,_(' ')) + _(".*") + _(" ") + String::Format(_("%p"),t->on_any_star));
@@ -438,10 +431,10 @@ String KeywordDatabase::expand(const String& text,
// Find keywords // Find keywords
while (!tagged.empty()) { while (!tagged.empty()) {
vector<KeywordTrie*> current; // current location(s) in the trie vector<const KeywordTrie*> current; // current location(s) in the trie
vector<KeywordTrie*> next; // location(s) after this step vector<const KeywordTrie*> next; // location(s) after this step
set<const Keyword*> used; // keywords already investigated set<const Keyword*> used; // keywords already investigated
current.push_back(root); current.push_back(root.get());
closure(current); closure(current);
// is the keyword expanded? From <kw-?> tag // is the keyword expanded? From <kw-?> tag
// Possible values are: // Possible values are:
@@ -453,7 +446,7 @@ String KeywordDatabase::expand(const String& text,
char expand_type = default_expand_type; char expand_type = default_expand_type;
for (size_t i = 0 ; i < tagged.size() ;) { for (size_t i = 0 ; i < tagged.size() ;) {
Char c = tagged.GetChar(i); wxUniChar c = tagged.GetChar(i);
// tag? // tag?
if (c == _('<')) { if (c == _('<')) {
if (is_substr(tagged, i, _("<kw-")) && i + 4 < tagged.size()) { if (is_substr(tagged, i, _("<kw-")) && i + 4 < tagged.size()) {
@@ -476,9 +469,9 @@ String KeywordDatabase::expand(const String& text,
} }
// find 'next' trie node set matching c // find 'next' trie node set matching c
FOR_EACH(kt, current) { FOR_EACH(kt, current) {
map<Char,KeywordTrie*>::const_iterator it = kt->children.find(c); auto it = kt->children.find(c);
if (it != kt->children.end()) { if (it != kt->children.end()) {
next.push_back(it->second); next.push_back(it->second.get());
} }
// TODO: on any star first or last? // TODO: on any star first or last?
if (kt->on_any_star) { if (kt->on_any_star) {
+3 -3
View File
@@ -140,7 +140,7 @@ DECLARE_DYNAMIC_ARG(KeywordUsageStatistics*, keyword_usage_statistics);
* The database should be rebuild. * The database should be rebuild.
*/ */
class KeywordDatabase { class KeywordDatabase {
public: public:
KeywordDatabase(); KeywordDatabase();
~KeywordDatabase(); ~KeywordDatabase();
@@ -165,8 +165,8 @@ class KeywordDatabase {
*/ */
String expand(const String& text, const ScriptValueP& match_condition, const ScriptValueP& expand_default, const ScriptValueP& combine_script, Context& ctx) const; String expand(const String& text, const ScriptValueP& match_condition, const ScriptValueP& expand_default, const ScriptValueP& combine_script, Context& ctx) const;
private: private:
KeywordTrie* root; ///< Data structure for finding keywords unique_ptr<KeywordTrie> root; ///< Data structure for finding keywords
/// (try to) expand a single keyword /// (try to) expand a single keyword
/** If the keyword matches: /** If the keyword matches:
+2 -1
View File
@@ -223,7 +223,8 @@ void Set::reflect_cards<Writer> (Writer& tag) {
// writeFile won't quite work because we'd need // writeFile won't quite work because we'd need
// include file: card: filename // include file: card: filename
// to do that // to do that
Writer writer(openOut(full_name), app_version); auto stream = openOut(full_name);
Writer writer(*stream, app_version);
writer.handle(_("card"), card); writer.handle(_("card"), card);
referenceFile(full_name); referenceFile(full_name);
REFLECT_N("include_file", full_name); REFLECT_N("include_file", full_name);
+4 -3
View File
@@ -295,14 +295,15 @@ void Settings::read() {
String filename = settingsFile(); String filename = settingsFile();
if (wxFileExists(filename)) { if (wxFileExists(filename)) {
// settings file not existing is not an error // settings file not existing is not an error
shared_ptr<wxFileInputStream> file = make_shared<wxFileInputStream>(filename); wxFileInputStream file(filename);
if (!file->Ok()) return; // failure is not an error if (!file.Ok()) return; // failure is not an error
Reader reader(file, nullptr, filename); Reader reader(file, nullptr, filename);
reader.handle_greedy(*this); reader.handle_greedy(*this);
} }
} }
void Settings::write() { void Settings::write() {
Writer writer(make_shared<wxFileOutputStream>(settingsFile()), app_version); wxFileOutputStream file(settingsFile());
Writer writer(file, app_version);
writer.handle(*this); writer.handle(*this);
} }
+8 -12
View File
@@ -321,8 +321,8 @@ bool CropImage::operator == (const GeneratedImage& that) const {
/** out is scaled some scaling, this is the return value */ /** out is scaled some scaling, this is the return value */
UInt gaussian_blur(Byte* in, UInt* out, int w, int h, double radius) { UInt gaussian_blur(Byte* in, UInt* out, int w, int h, double radius) {
// blur horizontally // blur horizontally
UInt* blur_x = new UInt[w*h]; // scaled by total_x, so in [0..255*total_x] auto blur_x = make_unique<UInt[]>(w*h); // scaled by total_x, so in [0..255*total_x]
memset(blur_x, 0, w*h*sizeof(UInt)); memset(blur_x.get(), 0, w*h*sizeof(UInt));
UInt total_x = 0; UInt total_x = 0;
{ {
double sigma = radius * w; double sigma = radius * w;
@@ -363,7 +363,6 @@ UInt gaussian_blur(Byte* in, UInt* out, int w, int h, double radius) {
} }
} }
} }
delete[] blur_x;
return total_x * total_y; return total_x * total_y;
} }
@@ -377,8 +376,8 @@ Image DropShadowImage::generate(const Options& opt) const {
int w = img.GetWidth(), h = img.GetHeight(); int w = img.GetWidth(), h = img.GetHeight();
Byte* alpha = img.GetAlpha(); Byte* alpha = img.GetAlpha();
// blur // blur
UInt* shadow = new UInt[w*h]; auto shadow = make_unique<UInt[]>(w*h);
UInt total = 255 * gaussian_blur(alpha, shadow, w, h, shadow_blur_radius); UInt total = 255 * gaussian_blur(alpha, shadow.get(), w, h, shadow_blur_radius);
// combine // combine
Byte* data = img.GetData(); Byte* data = img.GetData();
int dw = int(w * offset_x), dh = int(h * offset_y); int dw = int(w * offset_x), dh = int(h * offset_y);
@@ -398,9 +397,6 @@ Image DropShadowImage::generate(const Options& opt) const {
alpha[p] = a + shad; alpha[p] = a + shad;
} }
} }
//memset(data,0,3*w*h);
// cleanup
delete[] shadow;
return img; return img;
} }
bool DropShadowImage::operator == (const GeneratedImage& that) const { bool DropShadowImage::operator == (const GeneratedImage& that) const {
@@ -417,9 +413,9 @@ Image PackagedImage::generate(const Options& opt) const {
// TODO : use opt.width and opt.height? // TODO : use opt.width and opt.height?
// open file from package // open file from package
if (!opt.package) throw ScriptError(_("Can only load images in a context where an image is expected")); if (!opt.package) throw ScriptError(_("Can only load images in a context where an image is expected"));
InputStreamP file = opt.package->openIn(filename); auto file_stream = opt.package->openIn(filename);
Image img; Image img;
if (image_load_file(img, *file)) { if (image_load_file(img, *file_stream)) {
if (img.HasMask()) img.InitAlpha(); // we can't handle masks if (img.HasMask()) img.InitAlpha(); // we can't handle masks
return img; return img;
} else { } else {
@@ -494,8 +490,8 @@ Image ImageValueToImage::generate(const Options& opt) const {
if (!opt.local_package) throw ScriptError(_("Can only load images in a context where an image is expected")); if (!opt.local_package) throw ScriptError(_("Can only load images in a context where an image is expected"));
Image image; Image image;
if (!filename.empty()) { if (!filename.empty()) {
InputStreamP image_file = opt.local_package->openIn(filename); auto image_file_stream = opt.local_package->openIn(filename);
image_load_file(image, *image_file); image_load_file(image, *image_file_stream);
} }
if (!image.Ok()) { if (!image.Ok()) {
image = Image(max(1,opt.width), max(1,opt.height)); image = Image(max(1,opt.width), max(1,opt.height));
+2 -2
View File
@@ -58,8 +58,8 @@ bool DataEditor::viewerIsCurrent(const ValueViewer* viewer) const {
} }
void DataEditor::addAction(Action* action) { void DataEditor::addAction(unique_ptr<Action> action) {
set->actions.addAction(action); set->actions.addAction(move(action));
} }
// ----------------------------------------------------------------------------- : Selection // ----------------------------------------------------------------------------- : Selection
+1 -1
View File
@@ -27,7 +27,7 @@ class DataEditor : public CardViewer {
virtual DrawWhat drawWhat(const ValueViewer*) const; virtual DrawWhat drawWhat(const ValueViewer*) const;
virtual bool viewerIsCurrent(const ValueViewer*) const; virtual bool viewerIsCurrent(const ValueViewer*) const;
virtual void addAction(Action* action); virtual void addAction(unique_ptr<Action> action);
inline SetP getSetForActions() { return set; } inline SetP getSetForActions() { return set; }
// --------------------------------------------------- : Selection // --------------------------------------------------- : Selection
+3 -3
View File
@@ -179,7 +179,7 @@ bool CardListBase::doPaste() {
ok = data.getCards(set, new_cards); ok = data.getCards(set, new_cards);
if (!ok) return false; if (!ok) return false;
// add card to set // add card to set
set->actions.addAction(new AddCardAction(ADD, *set, new_cards)); set->actions.addAction(make_unique<AddCardAction>(ADD, *set, new_cards));
return true; return true;
} }
bool CardListBase::doDelete() { bool CardListBase::doDelete() {
@@ -188,7 +188,7 @@ bool CardListBase::doDelete() {
getSelection(cards_to_delete); getSelection(cards_to_delete);
if (cards_to_delete.empty()) return false; if (cards_to_delete.empty()) return false;
// delete cards // delete cards
set->actions.addAction(new AddCardAction(REMOVE, *set, cards_to_delete)); set->actions.addAction(make_unique<AddCardAction>(REMOVE, *set, cards_to_delete));
return true; return true;
} }
@@ -378,7 +378,7 @@ void CardListBase::onDrag(wxMouseEvent& ev) {
findSelectedItemPos(); findSelectedItemPos();
if (item != selected_item_pos) { if (item != selected_item_pos) {
// move card in the set // move card in the set
set->actions.addAction(new ReorderCardsAction(*set, item, selected_item_pos)); set->actions.addAction(make_unique<ReorderCardsAction>(*set, item, selected_item_pos));
} }
ev.Skip(false); ev.Skip(false);
} }
+2 -2
View File
@@ -132,14 +132,14 @@ bool KeywordList::doPaste() {
// add keyword to set // add keyword to set
KeywordP keyword = data.getKeyword(set); KeywordP keyword = data.getKeyword(set);
if (keyword) { if (keyword) {
set->actions.addAction(new AddKeywordAction(ADD, *set, keyword)); set->actions.addAction(make_unique<AddKeywordAction>(ADD, *set, keyword));
return true; return true;
} else { } else {
return false; return false;
} }
} }
bool KeywordList::doDelete() { bool KeywordList::doDelete() {
set->actions.addAction(new AddKeywordAction(REMOVE, *set, getKeyword())); set->actions.addAction(make_unique<AddKeywordAction>(REMOVE, *set, getKeyword()));
return true; return true;
} }
+1 -1
View File
@@ -73,7 +73,7 @@ void PackageList::showData(const String& pattern) {
FOR_EACH(p, matching) { FOR_EACH(p, matching) {
// open image // open image
PROFILER(_("load package image")); PROFILER(_("load package image"));
InputStreamP stream = p->openIconFile(); auto stream = p->openIconFile();
Image img; Image img;
Bitmap bmp; Bitmap bmp;
if (stream && image_load_file(img, *stream)) { if (stream && image_load_file(img, *stream)) {
+4 -5
View File
@@ -82,15 +82,14 @@ bool DownloadableInstallerList::download() {
wxThread::ExitCode DownloadableInstallerList::Thread::Entry() { wxThread::ExitCode DownloadableInstallerList::Thread::Entry() {
// open url // open url
wxURL url(settings.installer_list_url); wxURL url(settings.installer_list_url);
wxInputStream* isP = url.GetInputStream(); unique_ptr<wxInputStream> stream(url.GetInputStream());
if (!isP) { if (!stream) {
wxMutexLocker l(downloadable_installers.lock); wxMutexLocker l(downloadable_installers.lock);
downloadable_installers.status = DONE; downloadable_installers.status = DONE;
return 0; return 0;
} }
InputStreamP is(isP);
// Read installer list // Read installer list
Reader reader(is, nullptr, _("installers"), true); Reader reader(*stream, nullptr, _("installers"), true);
vector<DownloadableInstallerP> installers; vector<DownloadableInstallerP> installers;
reader.handle(_("installers"),installers); reader.handle(_("installers"),installers);
// done // done
@@ -344,7 +343,7 @@ void PackagesWindow::onOk(wxCommandEvent& ev) {
} }
// download installer // download installer
wxURL url(ip->installer->installer_url); wxURL url(ip->installer->installer_url);
wxInputStream* is = url.GetInputStream(); unique_ptr<wxInputStream> is(url.GetInputStream());
if (!is) { if (!is) {
throw Error(_ERROR_2_("can't download installer", ip->description->name, ip->installer->installer_url)); throw Error(_ERROR_2_("can't download installer", ip->description->name, ip->installer->installer_url));
} }
+1 -1
View File
@@ -325,7 +325,7 @@ void CardsPanel::onCommand(int id) {
if (card_list->canSelectNext()) card_list->selectNext(); if (card_list->canSelectNext()) card_list->selectNext();
break; break;
case ID_CARD_ADD: case ID_CARD_ADD:
set->actions.addAction(new AddCardAction(*set)); set->actions.addAction(make_unique<AddCardAction>(*set));
break; break;
case ID_CARD_REMOVE: case ID_CARD_REMOVE:
card_list->doDelete(); card_list->doDelete();
+2 -2
View File
@@ -180,7 +180,7 @@ void KeywordsPanel::onCommand(int id) {
list->selectNext(); list->selectNext();
break; break;
case ID_KEYWORD_ADD: case ID_KEYWORD_ADD:
set->actions.addAction(new AddKeywordAction(*set)); set->actions.addAction(make_unique<AddKeywordAction>(*set));
break; break;
case ID_KEYWORD_REMOVE: case ID_KEYWORD_REMOVE:
if (list->canDelete()) { if (list->canDelete()) {
@@ -370,7 +370,7 @@ void KeywordsPanel::onModeChange(wxCommandEvent& ev) {
if (!list->getKeyword()) return; if (!list->getKeyword()) return;
int sel = mode->GetSelection(); int sel = mode->GetSelection();
if (sel >= 0 && (size_t)sel < set->game->keyword_modes.size()) { if (sel >= 0 && (size_t)sel < set->game->keyword_modes.size()) {
set->actions.addAction(new ChangeKeywordModeAction(*list->getKeyword(), set->game->keyword_modes[sel]->name)); set->actions.addAction(make_unique<ChangeKeywordModeAction>(*list->getKeyword(), set->game->keyword_modes[sel]->name));
} }
} }
+3 -3
View File
@@ -528,7 +528,7 @@ void RandomPackPanel::onCommand(int id) {
case ID_CUSTOM_PACK: { case ID_CUSTOM_PACK: {
CustomPackDialog dlg(this, set, PackTypeP(), false); CustomPackDialog dlg(this, set, PackTypeP(), false);
if (dlg.ShowModal() == wxID_OK) { if (dlg.ShowModal() == wxID_OK) {
set->actions.addAction( new AddPackAction(ADD,*set,dlg.get()) ); set->actions.addAction(make_unique<AddPackAction>(ADD,*set,dlg.get()));
} }
break; break;
} }
@@ -544,12 +544,12 @@ void RandomPackPanel::onPackTypeClick(wxCommandEvent& ev) {
// update pack // update pack
for (size_t i = 0 ; i < set->pack_types.size() ; ++i) { for (size_t i = 0 ; i < set->pack_types.size() ; ++i) {
if (set->pack_types[i] == pick.pack) { if (set->pack_types[i] == pick.pack) {
set->actions.addAction( new ChangePackAction(*set,i,dlg.get()) ); set->actions.addAction(make_unique<ChangePackAction>(*set,i,dlg.get()));
} }
} }
} else { } else {
// delete pack // delete pack
set->actions.addAction( new AddPackAction(REMOVE,*set,pick.pack) ); set->actions.addAction(make_unique<AddPackAction>(REMOVE,*set,pick.pack));
} }
} }
break; break;
+1 -1
View File
@@ -238,7 +238,7 @@ void StatDimensionList::drawItem(DC& dc, int x, int y, size_t item) {
StatsDimension& dim = *dimensions.at(item - show_empty); StatsDimension& dim = *dimensions.at(item - show_empty);
// draw icon // draw icon
if (!dim.icon_filename.empty() && !dim.icon.Ok()) { if (!dim.icon_filename.empty() && !dim.icon.Ok()) {
InputStreamP file = game->openIn(dim.icon_filename); auto file = game->openIn(dim.icon_filename);
Image img(*file); Image img(*file);
if (img.HasMask()) img.InitAlpha(); // we can't handle masks if (img.HasMask()) img.InitAlpha(); // we can't handle masks
Image resampled(21, 21); Image resampled(21, 21);
+3 -3
View File
@@ -171,18 +171,18 @@ void StylePanel::onStyleSelect(wxCommandEvent&) {
// select no special style when selecting the same style as the set default // select no special style when selecting the same style as the set default
stylesheet = StyleSheetP(); stylesheet = StyleSheetP();
} }
set->actions.addAction(new ChangeCardStyleAction(card, stylesheet)); set->actions.addAction(make_unique<ChangeCardStyleAction>(card, stylesheet));
Layout(); Layout();
} }
} }
void StylePanel::onUseForAll(wxCommandEvent&) { void StylePanel::onUseForAll(wxCommandEvent&) {
set->actions.addAction(new ChangeSetStyleAction(*set, card)); set->actions.addAction(make_unique<ChangeSetStyleAction>(*set, card));
Layout(); Layout();
} }
void StylePanel::onUseCustom(wxCommandEvent&) { void StylePanel::onUseCustom(wxCommandEvent&) {
set->actions.addAction(new ChangeCardHasStylingAction(*set, card)); set->actions.addAction(make_unique<ChangeCardHasStylingAction>(*set, card));
} }
BEGIN_EVENT_TABLE(StylePanel, wxPanel) BEGIN_EVENT_TABLE(StylePanel, wxPanel)
+1 -1
View File
@@ -100,7 +100,7 @@ void SymbolBasicShapeEditor::onLeftDown (const Vector2D& pos, wxMouseEvent& ev
void SymbolBasicShapeEditor::onLeftUp (const Vector2D& pos, wxMouseEvent& ev) { void SymbolBasicShapeEditor::onLeftUp (const Vector2D& pos, wxMouseEvent& ev) {
if (drawing && shape) { if (drawing && shape) {
// Finalize the shape // Finalize the shape
addAction(new AddSymbolPartAction(*getSymbol(), shape)); addAction(make_unique<AddSymbolPartAction>(*getSymbol(), shape));
// Select the part // Select the part
control.selectPart(shape); control.selectPart(shape);
// no need to clean up, this editor is replaced // no need to clean up, this editor is replaced
+2 -2
View File
@@ -16,6 +16,6 @@ void SymbolEditorBase::SetStatusText(const String& text) {
control.parent->SetStatusText(text); control.parent->SetStatusText(text);
} }
void SymbolEditorBase::addAction(Action* action, bool allow_merge) { void SymbolEditorBase::addAction(unique_ptr<Action> action, bool allow_merge) {
getSymbol()->actions.addAction(action, allow_merge); getSymbol()->actions.addAction(move(action), allow_merge);
} }
+1 -1
View File
@@ -30,7 +30,7 @@ class SymbolEditorBase : public IntrusivePtrVirtualBase {
inline SymbolP getSymbol() { return control.getSymbol(); } inline SymbolP getSymbol() { return control.getSymbol(); }
/// Perform an action /// Perform an action
void addAction(Action* action, bool allow_merge = true); void addAction(unique_ptr<Action> action, bool allow_merge = true);
void SetStatusText(const String& text); void SetStatusText(const String& text);
+5 -5
View File
@@ -166,9 +166,9 @@ void SymbolPartList::onLeftUp(wxMouseEvent& ev) {
if (par != drop_parent && par->parts.size() == 1 && !par->isSymbolSymmetry()) { if (par != drop_parent && par->parts.size() == 1 && !par->isSymbolSymmetry()) {
// this leaves a group without elements, remove it // this leaves a group without elements, remove it
findParent(*par, par, drag_position); // parent of the group findParent(*par, par, drag_position); // parent of the group
symbol->actions.addAction(new UngroupReorderSymbolPartsAction(*par, drag_position, *drop_parent, drop_position)); symbol->actions.addAction(make_unique<UngroupReorderSymbolPartsAction>(*par, drag_position, *drop_parent, drop_position));
} else { } else {
symbol->actions.addAction(new ReorderSymbolPartsAction(*par, drag_position, *drop_parent, drop_position)); symbol->actions.addAction(make_unique<ReorderSymbolPartsAction>(*par, drag_position, *drop_parent, drop_position));
} }
} else { } else {
Refresh(false); Refresh(false);
@@ -257,14 +257,14 @@ void SymbolPartList::onChar(wxKeyEvent& ev) {
if (cursor > 0 && cursor <= typing_in->name.size()) { if (cursor > 0 && cursor <= typing_in->name.size()) {
String new_name = typing_in->name; String new_name = typing_in->name;
new_name.erase(cursor - 1, 1); new_name.erase(cursor - 1, 1);
symbol->actions.addAction(new SymbolPartNameAction(typing_in, new_name, cursor, cursor - 1)); symbol->actions.addAction(make_unique<SymbolPartNameAction>(typing_in, new_name, cursor, cursor - 1));
} }
break; break;
case WXK_DELETE: case WXK_DELETE:
if (cursor < typing_in->name.size()) { if (cursor < typing_in->name.size()) {
String new_name = typing_in->name; String new_name = typing_in->name;
new_name.erase(cursor, 1); new_name.erase(cursor, 1);
symbol->actions.addAction(new SymbolPartNameAction(typing_in, new_name, cursor, cursor)); symbol->actions.addAction(make_unique<SymbolPartNameAction>(typing_in, new_name, cursor, cursor));
} }
break; break;
default: default:
@@ -281,7 +281,7 @@ void SymbolPartList::onChar(wxKeyEvent& ev) {
#endif #endif
String new_name = typing_in->name; String new_name = typing_in->name;
new_name.insert(cursor, 1, key); new_name.insert(cursor, 1, key);
symbol->actions.addAction(new SymbolPartNameAction(typing_in, new_name, cursor, cursor + 1)); symbol->actions.addAction(make_unique<SymbolPartNameAction>(typing_in, new_name, cursor, cursor + 1));
} }
} }
} }
+22 -18
View File
@@ -253,10 +253,11 @@ void SymbolPointEditor::onLeftDClick(const Vector2D& pos, wxMouseEvent& ev) {
findHoveredItem(pos, false); findHoveredItem(pos, false);
if (hovering == SELECTED_NEW_POINT) { if (hovering == SELECTED_NEW_POINT) {
// Add point // Add point
ControlPointAddAction* act = new ControlPointAddAction(part, hover_line_1_idx, hover_line_t); auto act = make_unique<ControlPointAddAction>(part, hover_line_1_idx, hover_line_t);
addAction(act); ControlPointP new_point = act->getNewPoint();
addAction(move(act));
// select the new point // select the new point
selectPoint(act->getNewPoint(), false); selectPoint(new_point, false);
selection = SELECTED_POINTS; selection = SELECTED_POINTS;
} else if (hovering == SELECTED_HANDLE && hover_handle.handle == HANDLE_MAIN) { } else if (hovering == SELECTED_HANDLE && hover_handle.handle == HANDLE_MAIN) {
// Delete point // Delete point
@@ -287,8 +288,9 @@ void SymbolPointEditor::onMouseDrag(const Vector2D& from, const Vector2D& to, wx
// Drag the curve // Drag the curve
if (controlPointMoveAction) controlPointMoveAction = 0; if (controlPointMoveAction) controlPointMoveAction = 0;
if (!curveDragAction) { if (!curveDragAction) {
curveDragAction = new CurveDragAction(selected_line1, selected_line2); auto action = make_unique<CurveDragAction>(selected_line1, selected_line2);
addAction(curveDragAction); curveDragAction = action.get();
addAction(std::move(action));
} }
curveDragAction->move(delta, selected_line_t); curveDragAction->move(delta, selected_line_t);
control.Refresh(false); control.Refresh(false);
@@ -297,8 +299,9 @@ void SymbolPointEditor::onMouseDrag(const Vector2D& from, const Vector2D& to, wx
if (curveDragAction) curveDragAction = 0; if (curveDragAction) curveDragAction = 0;
if (!controlPointMoveAction) { if (!controlPointMoveAction) {
// create action we can add this movement to // create action we can add this movement to
controlPointMoveAction = new ControlPointMoveAction(selected_points); auto action = make_unique<ControlPointMoveAction>(selected_points);
addAction(controlPointMoveAction); controlPointMoveAction = action.get();
addAction(std::move(action));
} }
controlPointMoveAction->constrain = ev.ControlDown(); // ctrl constrains controlPointMoveAction->constrain = ev.ControlDown(); // ctrl constrains
controlPointMoveAction->snap = snap(ev); controlPointMoveAction->snap = snap(ev);
@@ -308,8 +311,9 @@ void SymbolPointEditor::onMouseDrag(const Vector2D& from, const Vector2D& to, wx
} else if (selection == SELECTED_HANDLE) { } else if (selection == SELECTED_HANDLE) {
// Move the selected handle // Move the selected handle
if (!handleMoveAction) { if (!handleMoveAction) {
handleMoveAction = new HandleMoveAction(selected_handle); auto action = make_unique<HandleMoveAction>(selected_handle);
addAction(handleMoveAction); handleMoveAction = action.get();
addAction(std::move(action));
} }
handleMoveAction->constrain = ev.ControlDown(); // ctrl constrains handleMoveAction->constrain = ev.ControlDown(); // ctrl constrains
handleMoveAction->snap = snap(ev); handleMoveAction->snap = snap(ev);
@@ -353,6 +357,7 @@ void SymbolPointEditor::onChar(wxKeyEvent& ev) {
if (ev.GetKeyCode() == WXK_DELETE) { if (ev.GetKeyCode() == WXK_DELETE) {
deleteSelection(); deleteSelection();
} else { } else {
resetActions();
// move selection using arrow keys // move selection using arrow keys
double step = 1.0 / settings.symbol_grid_size; double step = 1.0 / settings.symbol_grid_size;
Vector2D delta; Vector2D delta;
@@ -367,19 +372,18 @@ void SymbolPointEditor::onChar(wxKeyEvent& ev) {
// what to move // what to move
if (selection == SELECTED_POINTS || selection == SELECTED_LINE) { if (selection == SELECTED_POINTS || selection == SELECTED_LINE) {
// Move all selected points // Move all selected points
controlPointMoveAction = new ControlPointMoveAction(selected_points); auto action = make_unique<ControlPointMoveAction>(selected_points);
addAction(controlPointMoveAction); action->move(delta);
controlPointMoveAction->move(delta); addAction(std::move(action));
new_point += delta; new_point += delta;
control.Refresh(false); control.Refresh(false);
} else if (selection == SELECTED_HANDLE) { } else if (selection == SELECTED_HANDLE) {
// Move the selected handle // Move the selected handle
handleMoveAction = new HandleMoveAction(selected_handle); auto action = make_unique<HandleMoveAction>(selected_handle);
addAction(handleMoveAction); action->move(delta);
handleMoveAction->move(delta); addAction(std::move(action));
control.Refresh(false); control.Refresh(false);
} }
resetActions();
} }
} }
@@ -477,12 +481,12 @@ void SymbolPointEditor::onChangeSegment(SegmentMode mode) {
assert(selected_line1); assert(selected_line1);
assert(selected_line2); assert(selected_line2);
if (selected_line1->segment_after == mode) return; if (selected_line1->segment_after == mode) return;
addAction(new SegmentModeAction(selected_line1, selected_line2, mode)); addAction(make_unique<SegmentModeAction>(selected_line1, selected_line2, mode));
control.Refresh(false); control.Refresh(false);
} }
void SymbolPointEditor::onChangeLock(LockMode mode) { void SymbolPointEditor::onChangeLock(LockMode mode) {
addAction(new LockModeAction(*selected_points.begin(), mode)); addAction(make_unique<LockModeAction>(*selected_points.begin(), mode));
control.Refresh(false); control.Refresh(false);
} }
+18 -14
View File
@@ -173,22 +173,22 @@ void SymbolSelectEditor::onUpdateUI(wxUpdateUIEvent& ev) {
void SymbolSelectEditor::onCommand(int id) { void SymbolSelectEditor::onCommand(int id) {
if (id >= ID_SYMBOL_COMBINE && id < ID_SYMBOL_COMBINE_MAX) { if (id >= ID_SYMBOL_COMBINE && id < ID_SYMBOL_COMBINE_MAX) {
// change combine mode // change combine mode
addAction(new CombiningModeAction( addAction(make_unique<CombiningModeAction>(
control.selected_parts.get(), control.selected_parts.get(),
static_cast<SymbolShapeCombine>(id - ID_SYMBOL_COMBINE) static_cast<SymbolShapeCombine>(id - ID_SYMBOL_COMBINE)
)); ));
control.Refresh(false); control.Refresh(false);
} else if (id == ID_EDIT_DUPLICATE && !isEditing()) { } else if (id == ID_EDIT_DUPLICATE && !isEditing()) {
// duplicate selection, not when dragging // duplicate selection, not when dragging
addAction(new DuplicateSymbolPartsAction(*getSymbol(), control.selected_parts.get())); addAction(make_unique<DuplicateSymbolPartsAction>(*getSymbol(), control.selected_parts.get()));
control.Refresh(false); control.Refresh(false);
} else if (id == ID_EDIT_GROUP && !isEditing()) { } else if (id == ID_EDIT_GROUP && !isEditing()) {
// group selection, not when dragging // group selection, not when dragging
addAction(new GroupSymbolPartsAction(*getSymbol(), control.selected_parts.get(), make_intrusive<SymbolGroup>())); addAction(make_unique<GroupSymbolPartsAction>(*getSymbol(), control.selected_parts.get(), make_intrusive<SymbolGroup>()));
control.Refresh(false); control.Refresh(false);
} else if (id == ID_EDIT_UNGROUP && !isEditing()) { } else if (id == ID_EDIT_UNGROUP && !isEditing()) {
// ungroup selection, not when dragging // ungroup selection, not when dragging
addAction(new UngroupSymbolPartsAction(*getSymbol(), control.selected_parts.get())); addAction(make_unique<UngroupSymbolPartsAction>(*getSymbol(), control.selected_parts.get()));
control.Refresh(false); control.Refresh(false);
} }
} }
@@ -312,24 +312,28 @@ void SymbolSelectEditor::onMouseDrag (const Vector2D& from, const Vector2D& to,
if (rotate) { if (rotate) {
if (scaleX == 0 || scaleY == 0) { if (scaleX == 0 || scaleY == 0) {
// shear, center/fixed point on the opposite side // shear, center/fixed point on the opposite side
shearAction = new SymbolPartShearAction(control.selected_parts.get(), bounds.corner(-scaleX, -scaleY)); auto action = make_unique<SymbolPartShearAction>(control.selected_parts.get(), bounds.corner(-scaleX, -scaleY));
addAction(shearAction); shearAction = action.get();
addAction(std::move(action));
} else { } else {
// rotate // rotate
rotateAction = new SymbolPartRotateAction(control.selected_parts.get(), center); auto action = make_unique<SymbolPartRotateAction>(control.selected_parts.get(), center);
addAction(rotateAction); rotateAction = action.get();
addAction(std::move(action));
startAngle = angleTo(to); startAngle = angleTo(to);
} }
} else { } else {
// we are on a handle; start scaling // we are on a handle; start scaling
scaleAction = new SymbolPartScaleAction(control.selected_parts.get(), scaleX, scaleY); auto action = make_unique<SymbolPartScaleAction>(control.selected_parts.get(), scaleX, scaleY);
addAction(scaleAction); scaleAction = action.get();
addAction(std::move(action));
} }
} else { } else {
// move // move
click_mode = CLICK_MOVE; click_mode = CLICK_MOVE;
moveAction = new SymbolPartMoveAction(control.selected_parts.get()); auto action = make_unique<SymbolPartMoveAction>(control.selected_parts.get());
addAction(moveAction); moveAction = action.get();
addAction(std::move(action));
} }
} }
@@ -399,7 +403,7 @@ void SymbolSelectEditor::onKeyChange (wxKeyEvent& ev) {
void SymbolSelectEditor::onChar(wxKeyEvent& ev) { void SymbolSelectEditor::onChar(wxKeyEvent& ev) {
if (ev.GetKeyCode() == WXK_DELETE) { if (ev.GetKeyCode() == WXK_DELETE) {
// delete selected parts // delete selected parts
addAction(new RemoveSymbolPartsAction(*getSymbol(), control.selected_parts.get())); addAction(make_unique<RemoveSymbolPartsAction>(*getSymbol(), control.selected_parts.get()));
if (control.selected_parts.selected(highlightPart)) highlightPart = SymbolPartP(); // deleted it if (control.selected_parts.selected(highlightPart)) highlightPart = SymbolPartP(); // deleted it
control.selected_parts.clear(); control.selected_parts.clear();
resetActions(); resetActions();
@@ -416,7 +420,7 @@ void SymbolSelectEditor::onChar(wxKeyEvent& ev) {
ev.Skip(); ev.Skip();
return; return;
} }
addAction(new SymbolPartMoveAction(control.selected_parts.get(), delta)); addAction(make_unique<SymbolPartMoveAction>(control.selected_parts.get(), delta));
} }
} }
+7 -6
View File
@@ -107,13 +107,13 @@ void SymbolSymmetryEditor::onCommand(int id) {
if (id >= ID_SYMMETRY && id < ID_SYMMETRY_MAX) { if (id >= ID_SYMMETRY && id < ID_SYMMETRY_MAX) {
SymbolSymmetryType kind = id == ID_SYMMETRY_ROTATION ? SYMMETRY_ROTATION : SYMMETRY_REFLECTION; SymbolSymmetryType kind = id == ID_SYMMETRY_ROTATION ? SYMMETRY_ROTATION : SYMMETRY_REFLECTION;
if (symmetry && symmetry->kind != kind) { if (symmetry && symmetry->kind != kind) {
addAction(new SymmetryTypeAction(*symmetry, kind)); addAction(make_unique<SymmetryTypeAction>(*symmetry, kind));
control.Refresh(false); control.Refresh(false);
} }
resetActions(); resetActions();
} else if (id == ID_COPIES) { } else if (id == ID_COPIES) {
if (symmetry && symmetry->copies != copies->GetValue()) { if (symmetry && symmetry->copies != copies->GetValue()) {
addAction(new SymmetryCopiesAction(*symmetry, copies->GetValue())); addAction(make_unique<SymmetryCopiesAction>(*symmetry, copies->GetValue()));
control.Refresh(false); control.Refresh(false);
} }
resetActions(); resetActions();
@@ -124,11 +124,11 @@ void SymbolSymmetryEditor::onCommand(int id) {
symmetry->center = Vector2D(0.5,0.5); symmetry->center = Vector2D(0.5,0.5);
symmetry->handle = Vector2D(0.2,0); symmetry->handle = Vector2D(0.2,0);
symmetry->name = symmetry->expectedName(); symmetry->name = symmetry->expectedName();
addAction(new GroupSymbolPartsAction(*getSymbol(), control.selected_parts.get(), symmetry)); addAction(make_unique<GroupSymbolPartsAction>(*getSymbol(), control.selected_parts.get(), symmetry));
control.selected_parts.select(symmetry); control.selected_parts.select(symmetry);
control.Refresh(false); control.Refresh(false);
} else if (id == ID_REMOVE_SYMMETRY) { } else if (id == ID_REMOVE_SYMMETRY) {
addAction(new UngroupSymbolPartsAction(*getSymbol(), control.selected_parts.get())); addAction(make_unique<UngroupSymbolPartsAction>(*getSymbol(), control.selected_parts.get()));
symmetry = SymbolSymmetryP(); symmetry = SymbolSymmetryP();
control.Refresh(false); control.Refresh(false);
} }
@@ -155,10 +155,11 @@ void SymbolSymmetryEditor::onMouseDrag (const Vector2D& from, const Vector2D& t
// Resize the object // Resize the object
if (selection == SELECTION_NONE) return; if (selection == SELECTION_NONE) return;
if (!symmetryMoveAction) { if (!symmetryMoveAction) {
symmetryMoveAction = new SymmetryMoveAction(*symmetry, selection == SELECTION_HANDLE); auto action = make_unique<SymmetryMoveAction>(*symmetry, selection == SELECTION_HANDLE);
symmetryMoveAction = action.get();
symmetryMoveAction->constrain = ev.ControlDown(); symmetryMoveAction->constrain = ev.ControlDown();
symmetryMoveAction->snap = ev.ShiftDown() != settings.symbol_grid_snap ? settings.symbol_grid_size : 0; symmetryMoveAction->snap = ev.ShiftDown() != settings.symbol_grid_snap ? settings.symbol_grid_size : 0;
addAction(symmetryMoveAction); addAction(std::move(action));
} }
symmetryMoveAction->move(to - from); symmetryMoveAction->move(to - from);
control.Refresh(false); control.Refresh(false);
+8 -4
View File
@@ -36,7 +36,8 @@ SymbolWindow::SymbolWindow(Window* parent, const String& filename)
: performer(nullptr) : performer(nullptr)
{ {
// open file // open file
Reader reader(make_shared<wxFileInputStream>(filename), nullptr, filename); wxFileInputStream stream(filename);
Reader reader(stream, nullptr, filename);
SymbolP symbol; SymbolP symbol;
reader.handle_greedy(symbol); reader.handle_greedy(symbol);
init(parent, symbol); init(parent, symbol);
@@ -217,7 +218,8 @@ void SymbolWindow::onFileOpen(wxCommandEvent& ev) {
String ext = n.GetExt(); String ext = n.GetExt();
SymbolP symbol; SymbolP symbol;
if (ext.Lower() == _("mse-symbol")) { if (ext.Lower() == _("mse-symbol")) {
Reader reader(make_shared<wxFileInputStream>(name), nullptr, name); wxFileInputStream stream(name);
Reader reader(stream, nullptr, name);
reader.handle_greedy(symbol); reader.handle_greedy(symbol);
} else { } else {
wxBusyCursor busy; wxBusyCursor busy;
@@ -240,7 +242,8 @@ void SymbolWindow::onFileSaveAs(wxCommandEvent& ev) {
String name = wxFileSelector(_("Save symbol"),settings.default_set_dir,_(""),_(""),_("Symbol files (*.mse-symbol)|*.mse-symbol"),wxFD_SAVE, this); String name = wxFileSelector(_("Save symbol"),settings.default_set_dir,_(""),_(""),_("Symbol files (*.mse-symbol)|*.mse-symbol"),wxFD_SAVE, this);
if (!name.empty()) { if (!name.empty()) {
settings.default_set_dir = wxPathOnly(name); settings.default_set_dir = wxPathOnly(name);
Writer writer(make_shared<wxFileOutputStream>(name), file_version_symbol); wxFileOutputStream stream(name);
Writer writer(stream, file_version_symbol);
writer.handle(control->getSymbol()); writer.handle(control->getSymbol());
} }
} }
@@ -250,7 +253,8 @@ void SymbolWindow::onFileStore(wxCommandEvent& ev) {
SymbolValueP value = static_pointer_cast<SymbolValue>(performer->value); SymbolValueP value = static_pointer_cast<SymbolValue>(performer->value);
Package& package = performer->getLocalPackage(); Package& package = performer->getLocalPackage();
FileName new_filename = package.newFileName(value->field().name,_(".mse-symbol")); // a new unique name in the package FileName new_filename = package.newFileName(value->field().name,_(".mse-symbol")); // a new unique name in the package
Writer writer(package.openOut(new_filename), file_version_symbol); auto stream = package.openOut(new_filename);
Writer writer(*stream, file_version_symbol);
writer.handle(control->getSymbol()); writer.handle(control->getSymbol());
performer->addAction(value_action(value, new_filename)); performer->addAction(value_action(value, new_filename));
} }
+2 -3
View File
@@ -107,13 +107,12 @@ class CheckUpdateThread : public wxThread {
String& the_url = settings.updates_url; String& the_url = settings.updates_url;
#endif #endif
wxURL url(the_url); wxURL url(the_url);
wxInputStream* isP = url.GetInputStream(); unique_ptr<wxInputStream> isP(url.GetInputStream());
if (!isP) return; // failed to get data if (!isP) return; // failed to get data
InputStreamP is(isP);
// Read version data // Read version data
// ignore errors for forwards compatability // ignore errors for forwards compatability
VersionDataP version_data; VersionDataP version_data;
Reader reader(is, nullptr, _("updates"), true); Reader reader(*isP, nullptr, _("updates"), true);
reader.handle(version_data); reader.handle(version_data);
// has the updates url changed? // has the updates url changed?
if (!version_data->new_updates_url.empty()) { if (!version_data->new_updates_url.empty()) {
+2 -2
View File
@@ -12,9 +12,9 @@
// ----------------------------------------------------------------------------- : ValueEditor // ----------------------------------------------------------------------------- : ValueEditor
void ValueEditor::addAction(ValueAction* a) { void ValueEditor::addAction(unique_ptr<ValueAction> a) {
if (a) { if (a) {
a->isOnCard(editor().getCard().get()); a->isOnCard(editor().getCard().get());
editor().addAction(a); editor().addAction(move(a));
} }
} }
+1 -1
View File
@@ -130,7 +130,7 @@ class ValueEditor {
virtual DataEditor& editor() const = 0; virtual DataEditor& editor() const = 0;
/// Perform an action /// Perform an action
void addAction(ValueAction* a); void addAction(unique_ptr<ValueAction> a);
}; };
// ----------------------------------------------------------------------------- : Utility // ----------------------------------------------------------------------------- : Utility
+1 -1
View File
@@ -65,7 +65,7 @@ bool ImageValueEditor::canPaste() const {
bool ImageValueEditor::doCopy() { bool ImageValueEditor::doCopy() {
// load image // load image
InputStreamP image_file = getLocalPackage().openIn(value().filename); auto image_file = getLocalPackage().openIn(value().filename);
Image image; Image image;
if (!image_load_file(image, *image_file)) return false; if (!image_load_file(image, *image_file)) return false;
// set data // set data
+3 -3
View File
@@ -856,7 +856,7 @@ void TextValueEditor::doFormat(int type) {
break; break;
} }
case ID_FORMAT_REMINDER: { case ID_FORMAT_REMINDER: {
addAction(new TextToggleReminderAction(valueP(), selection_start_i)); addAction(make_unique<TextToggleReminderAction>(valueP(), selection_start_i));
break; break;
} }
} }
@@ -983,7 +983,7 @@ void TextValueEditor::replaceSelection(const String& replacement, const String&
fixSelection(); fixSelection();
// execute the action before adding it to the stack, // execute the action before adding it to the stack,
// because we want to run scripts before action listeners see the action // because we want to run scripts before action listeners see the action
TextValueAction* action = typing_action(valueP(), selection_start_i, selection_end_i, select_on_undo ? selection_start : selection_end, selection_end, replacement, name); auto action = typing_action(valueP(), selection_start_i, selection_end_i, select_on_undo ? selection_start : selection_end, selection_end, replacement, name);
if (!action) { if (!action) {
// nothing changes, but move the selection anyway // nothing changes, but move the selection anyway
moveSelection(TYPE_CURSOR, selection_end); moveSelection(TYPE_CURSOR, selection_end);
@@ -994,7 +994,7 @@ void TextValueEditor::replaceSelection(const String& replacement, const String&
size_t expected_cursor = min(selection_start, selection_end) + untag_for_cursor(replacement).size(); size_t expected_cursor = min(selection_start, selection_end) + untag_for_cursor(replacement).size();
// perform the action // perform the action
// NOTE: this calls our onAction, invalidating the text viewer and moving the selection around the new text // NOTE: this calls our onAction, invalidating the text viewer and moving the selection around the new text
addAction(action); addAction(std::move(action));
// move cursor // move cursor
{ {
String real_value = untag_for_cursor(value().value()); String real_value = untag_for_cursor(value().value());
+1 -1
View File
@@ -32,7 +32,7 @@ void ImageValueViewer::draw(RotatedDC& dc) {
// load from file // load from file
if (!value().filename.empty()) { if (!value().filename.empty()) {
try { try {
InputStreamP image_file = getLocalPackage().openIn(value().filename); auto image_file = getLocalPackage().openIn(value().filename);
if (image_load_file(image, *image_file)) { if (image_load_file(image, *image_file)) {
image.Rescale(w, h); image.Rescale(w, h);
} }
+1 -1
View File
@@ -37,7 +37,7 @@ void PackageChoiceValueViewer::initItems() {
i.package_name = p->relativeFilename(); i.package_name = p->relativeFilename();
i.name = capitalize_sentence(p->short_name); i.name = capitalize_sentence(p->short_name);
Image image; Image image;
InputStreamP stream = p->openIconFile(); auto stream = p->openIconFile();
if (stream && image_load_file(image, *stream)) { if (stream && image_load_file(image, *stream)) {
i.image = Bitmap(resample(image, 16,16)); i.image = Bitmap(resample(image, 16,16));
} }
+1 -1
View File
@@ -378,7 +378,7 @@ SCRIPT_FUNCTION(copy_file) {
String out_path = get_export_full_path(out_name); String out_path = get_export_full_path(out_name);
// copy // copy
ExportInfo& ei = *export_info(); ExportInfo& ei = *export_info();
InputStreamP in = ei.export_template->openIn(input); auto in = ei.export_template->openIn(input);
wxFileOutputStream out(out_path); wxFileOutputStream out(out_path);
if (!out.Ok()) throw Error(_("Unable to open file '") + out_path + _("' for output")); if (!out.Ok()) throw Error(_("Unable to open file '") + out_path + _("' for output"));
out.Write(*in); out.Write(*in);
+3 -3
View File
@@ -213,9 +213,9 @@ void TokenIterator::readToken() {
// read the entire file, and start at the beginning of it // read the entire file, and start at the beginning of it
pos = 0; pos = 0;
filename = include_file; filename = include_file;
InputStreamP is = package_manager.openFileFromPackage(package, include_file); auto stream = package_manager.openFileFromPackage(package, include_file);
eat_utf8_bom(*is); eat_utf8_bom(*stream);
input = read_utf8_line(*is, true); input = read_utf8_line(*stream, true);
} else if (isAlpha(c) || isUnicodeAlpha(c) || c == _('_') || (isDigit(c) && !buffer.empty() && buffer.back() == _("."))) { } else if (isAlpha(c) || isUnicodeAlpha(c) || c == _('_') || (isDigit(c) && !buffer.empty() && buffer.back() == _("."))) {
// name, or a number after a . token, as in array.0 // name, or a number after a . token, as in array.0
size_t start = pos - 1; size_t start = pos - 1;
+17 -37
View File
@@ -21,57 +21,37 @@
#include <data/action/keyword.hpp> #include <data/action/keyword.hpp>
#include <util/error.hpp> #include <util/error.hpp>
typedef map<const StyleSheet*,Context*> Contexts;
DECLARE_TYPEOF(Contexts);
DECLARE_TYPEOF_COLLECTION(CardP);
DECLARE_TYPEOF_COLLECTION(FieldP);
DECLARE_TYPEOF_COLLECTION(Dependency);
DECLARE_TYPEOF_NO_REV(IndexMap<FieldP COMMA StyleP>);
DECLARE_TYPEOF_NO_REV(IndexMap<FieldP COMMA ValueP>);
//#define LOG_UPDATES
// ----------------------------------------------------------------------------- : SetScriptContext : initialization // ----------------------------------------------------------------------------- : SetScriptContext : initialization
SetScriptContext::SetScriptContext(Set& set) SetScriptContext::SetScriptContext(Set& set)
: set(set) : set(set)
{} {}
SetScriptContext::~SetScriptContext() {
// destroy contexts
FOR_EACH(sc, contexts) {
delete sc.second;
}
}
Context& SetScriptContext::getContext(const StyleSheetP& stylesheet) { Context& SetScriptContext::getContext(const StyleSheetP& stylesheet) {
Contexts::iterator it = contexts.find(stylesheet.get()); auto it = contexts.try_emplace(stylesheet.get());
if (it != contexts.end()) { Context& ctx = it.first->second;
return *it->second; // we already have a context if (it.second) {
} else { // we created a new context
// create a new context
Context* ctx = new Context();
contexts.insert(make_pair(stylesheet.get(), ctx));
// variables // variables
// NOTE: do not use a smart pointer for the pointer to the set, because the set owns this // NOTE: do not use a smart pointer for the pointer to the set, because the set owns this
// which would lead to a reference cycle. // which would lead to a reference cycle.
init_script_functions(*ctx); init_script_functions(ctx);
ctx->setVariable(SCRIPT_VAR_set, make_intrusive<ScriptObject<Set*>>(&set)); ctx.setVariable(SCRIPT_VAR_set, make_intrusive<ScriptObject<Set*>>(&set));
ctx->setVariable(SCRIPT_VAR_game, to_script(set.game)); ctx.setVariable(SCRIPT_VAR_game, to_script(set.game));
ctx->setVariable(SCRIPT_VAR_stylesheet, to_script(stylesheet)); ctx.setVariable(SCRIPT_VAR_stylesheet, to_script(stylesheet));
ctx->setVariable(SCRIPT_VAR_card_style, to_script(&stylesheet->card_style)); ctx.setVariable(SCRIPT_VAR_card_style, to_script(&stylesheet->card_style));
ctx->setVariable(SCRIPT_VAR_card, set.cards.empty() ? script_nil : to_script(set.cards.front())); // dummy value ctx.setVariable(SCRIPT_VAR_card, set.cards.empty() ? script_nil : to_script(set.cards.front())); // dummy value
ctx->setVariable(SCRIPT_VAR_styling, to_script(&set.stylingDataFor(*stylesheet))); ctx.setVariable(SCRIPT_VAR_styling, to_script(&set.stylingDataFor(*stylesheet)));
try { try {
// perform init scripts, don't use a scope, variables stay bound in the context // perform init scripts, don't use a scope, variables stay bound in the context
set.game ->init_script.invoke(*ctx, false); set.game ->init_script.invoke(ctx, false);
stylesheet->init_script.invoke(*ctx, false); stylesheet->init_script.invoke(ctx, false);
} catch (const Error& e) { } catch (const Error& e) {
handle_error(e); handle_error(e);
} }
onInit(stylesheet, ctx); onInit(stylesheet, ctx);
return *ctx;
} }
return ctx;
} }
Context& SetScriptContext::getContext(const CardP& card) { Context& SetScriptContext::getContext(const CardP& card) {
StyleSheetP stylesheet = set.stylesheetForP(card); StyleSheetP stylesheet = set.stylesheetForP(card);
@@ -100,13 +80,13 @@ SetScriptManager::~SetScriptManager() {
set.actions.removeListener(this); set.actions.removeListener(this);
} }
void SetScriptManager::onInit(const StyleSheetP& stylesheet, Context* ctx) { void SetScriptManager::onInit(const StyleSheetP& stylesheet, Context& ctx) {
assert(wxThread::IsMain()); assert(wxThread::IsMain());
// initialize dependencies // initialize dependencies
try { try {
// find script dependencies // find script dependencies
initDependencies(*ctx, *set.game); initDependencies(ctx, *set.game);
initDependencies(*ctx, *stylesheet); initDependencies(ctx, *stylesheet);
} catch (const Error& e) { } catch (const Error& e) {
handle_error(e); handle_error(e);
} }
+6 -7
View File
@@ -28,21 +28,20 @@ DECLARE_POINTER_TYPE(Style);
/// Manager of the script context for a set /// Manager of the script context for a set
class SetScriptContext { class SetScriptContext {
public: public:
SetScriptContext(Set& set); SetScriptContext(Set& set);
virtual ~SetScriptContext();
/// Get a context to use for the set, for a given stylesheet /// Get a context to use for the set, for a given stylesheet
Context& getContext(const StyleSheetP&); Context& getContext(const StyleSheetP&);
/// Get a context to use for the set, for a given card /// Get a context to use for the set, for a given card
Context& getContext(const CardP&); Context& getContext(const CardP&);
protected: protected:
Set& set; ///< Set for which we are managing scripts Set& set; ///< Set for which we are managing scripts
map<const StyleSheet*,Context*> contexts; ///< Context for evaluating scripts that use a given stylesheet map<const StyleSheet*,Context> contexts; ///< Context for evaluating scripts that use a given stylesheet
/// Called when a new context for a stylesheet is initialized /// Called when a new context for a stylesheet is initialized
virtual void onInit(const StyleSheetP& stylesheet, Context* ctx) {} virtual void onInit(const StyleSheetP& stylesheet, Context& ctx) {}
}; };
@@ -73,7 +72,7 @@ class SetScriptManager : public SetScriptContext, public ActionListener {
void updateAll(); void updateAll();
private: private:
virtual void onInit(const StyleSheetP& stylesheet, Context* ctx); void onInit(const StyleSheetP& stylesheet, Context& ctx) override;
void initDependencies(Context&, Game&); void initDependencies(Context&, Game&);
void initDependencies(Context&, StyleSheet&); void initDependencies(Context&, StyleSheet&);
+13 -20
View File
@@ -21,29 +21,22 @@ ActionStack::ActionStack()
, last_was_add(false) , last_was_add(false)
{} {}
ActionStack::~ActionStack() { void ActionStack::addAction(unique_ptr<Action> action, bool allow_merge) {
// we own the actions, delete them
FOR_EACH(a, undo_actions) delete a;
FOR_EACH(a, redo_actions) delete a;
}
void ActionStack::addAction(Action* action, bool allow_merge) {
if (!action) return; // no action if (!action) return; // no action
action->perform(false); // TODO: delete action if perform throws action->perform(false); // TODO: delete action if perform throws
tellListeners(*action, false); tellListeners(*action, false);
// clear redo list // clear redo list
if (!redo_actions.empty()) allow_merge = false; // don't merge after undo if (!redo_actions.empty()) allow_merge = false; // don't merge after undo
FOR_EACH(a, redo_actions) delete a;
redo_actions.clear(); redo_actions.clear();
// try to merge? // try to merge?
if (allow_merge && !undo_actions.empty() && if (allow_merge && !undo_actions.empty() &&
last_was_add && // never merge with something that was redone once already last_was_add && // never merge with something that was redone once already
undo_actions.back() != save_point && // never merge with the save point undo_actions.back().get() != save_point && // never merge with the save point
undo_actions.back()->merge(*action) // merged with top undo action undo_actions.back()->merge(*action) // merged with top undo action
) { ) {
delete action; // don't add
} else { } else {
undo_actions.push_back(action); undo_actions.push_back(move(action));
} }
last_was_add = true; last_was_add = true;
} }
@@ -51,23 +44,23 @@ void ActionStack::addAction(Action* action, bool allow_merge) {
void ActionStack::undo() { void ActionStack::undo() {
assert(canUndo()); assert(canUndo());
if (!canUndo()) return; if (!canUndo()) return;
Action* action = undo_actions.back(); unique_ptr<Action> action = move(undo_actions.back());
undo_actions.pop_back();
action->perform(true); action->perform(true);
tellListeners(*action, true); tellListeners(*action, true);
// move to redo stack // move to redo stack
undo_actions.pop_back(); redo_actions.emplace_back(move(action));
redo_actions.push_back(action);
last_was_add = false; last_was_add = false;
} }
void ActionStack::redo() { void ActionStack::redo() {
assert(canRedo()); assert(canRedo());
if (!canRedo()) return; if (!canRedo()) return;
Action* action = redo_actions.back(); unique_ptr<Action> action = move(redo_actions.back());
redo_actions.pop_back();
action->perform(false); action->perform(false);
tellListeners(*action, false); tellListeners(*action, false);
// move to undo stack // move to undo stack
redo_actions.pop_back(); undo_actions.emplace_back(move(action));
undo_actions.push_back(action);
last_was_add = false; last_was_add = false;
} }
@@ -95,13 +88,13 @@ String ActionStack::redoName() const {
bool ActionStack::atSavePoint() const { bool ActionStack::atSavePoint() const {
return (undo_actions.empty() && save_point == nullptr) return (undo_actions.empty() && save_point == nullptr)
|| (undo_actions.back() == save_point); || (undo_actions.back().get() == save_point);
} }
void ActionStack::setSavePoint() { void ActionStack::setSavePoint() {
if (undo_actions.empty()) { if (undo_actions.empty()) {
save_point = nullptr; save_point = nullptr;
} else { } else {
save_point = undo_actions.back(); save_point = undo_actions.back().get();
} }
} }
+4 -7
View File
@@ -64,14 +64,13 @@ class ActionListener {
class ActionStack { class ActionStack {
public: public:
ActionStack(); ActionStack();
~ActionStack();
/// Add an action to the stack, and perform that action. /// Add an action to the stack, and perform that action.
/** Tells all listeners about the action. /** Tells all listeners about the action.
* The ActionStack takes ownership of the action. * The ActionStack takes ownership of the action.
* If allow_merge == true then we attempt to merge this action with previous ones * If allow_merge == true then we attempt to merge this action with previous ones
*/ */
void addAction(Action* action, bool allow_merge = true); void addAction(unique_ptr<Action> action, bool allow_merge = true);
/// Undoes the last action that was (re)done /// Undoes the last action that was (re)done
/** @pre canUndo() */ /** @pre canUndo() */
@@ -107,13 +106,11 @@ class ActionStack {
private: private:
/// Actions to be undone. /// Actions to be undone.
/** Owns the action objects! */ vector<unique_ptr<Action>> undo_actions;
vector<Action*> undo_actions;
/// Actions to be redone /// Actions to be redone
/** Owns the action objects! */ vector<unique_ptr<Action>> redo_actions;
vector<Action*> redo_actions;
/// Point at which the file was saved, corresponds to the top of the undo stack at that point /// Point at which the file was saved, corresponds to the top of the undo stack at that point
Action* save_point; const Action* save_point;
/// Was the last thing the user did addAction? (as opposed to undo/redo) /// Was the last thing the user did addAction? (as opposed to undo/redo)
bool last_was_add; bool last_was_add;
/// Objects that are listening to actions /// Objects that are listening to actions
+2 -1
View File
@@ -25,7 +25,8 @@ IndexMap<Key,Value>& DelayedIndexMaps<Key,Value>::get(const String& name, const
item->read_data.init(init_with); item->read_data.init(init_with);
} else if (!item->unread_data.empty()) { // not read, read now } else if (!item->unread_data.empty()) { // not read, read now
item->read_data.init(init_with); item->read_data.init(init_with);
Reader reader(make_shared<wxStringInputStream>(item->unread_data), nullptr, _("delayed data for ") + name); wxStringInputStream input(item->unread_data);
Reader reader(input, nullptr, _("delayed data for ") + name);
reader.handle_greedy(item->read_data); reader.handle_greedy(item->read_data);
item->unread_data.clear(); item->unread_data.clear();
} }
+44 -44
View File
@@ -26,13 +26,10 @@ IMPLEMENT_DYNAMIC_ARG(Package*, writing_package, nullptr);
IMPLEMENT_DYNAMIC_ARG(Package*, clipboard_package, nullptr); IMPLEMENT_DYNAMIC_ARG(Package*, clipboard_package, nullptr);
Package::Package() Package::Package()
: fileStream(nullptr) : zipStream (nullptr)
, zipStream (nullptr)
{} {}
Package::~Package() { Package::~Package() {
delete zipStream;
delete fileStream;
// remove any remaining temporary files // remove any remaining temporary files
FOR_EACH(f, files) { FOR_EACH(f, files) {
if (f.second.wasWritten()) { if (f.second.wasWritten()) {
@@ -91,8 +88,7 @@ void Package::open(const String& n, bool fast) {
void Package::reopen() { void Package::reopen() {
if (wxDirExists(filename)) { if (wxDirExists(filename)) {
// make sure we have no zip open // make sure we have no zip open
delete zipStream; zipStream = nullptr; zipStream.reset();
delete fileStream; fileStream = nullptr;
} else { } else {
// reopen only needed for zipfile // reopen only needed for zipfile
openZipfile(); openZipfile();
@@ -154,40 +150,45 @@ void Package::clearKeepFlag() {
// ----------------------------------------------------------------------------- : Package : inside // ----------------------------------------------------------------------------- : Package : inside
class FileInputStream_aux {
protected:
wxFileInputStream file_stream;
inline FileInputStream_aux(const String& filename)
: file_stream(filename)
{}
};
/// Class that is a wxZipInputStream over a wxFileInput stream /// Class that is a wxZipInputStream over a wxFileInput stream
/** Note that wxFileInputStream is also a base class, because it must be constructed first /** Note that wxFileInputStream is also a base class, because it must be constructed first
*/ */
class ZipFileInputStream : private wxFileInputStream, public wxZipInputStream { class ZipFileInputStream : private FileInputStream_aux, public wxZipInputStream {
public: public:
ZipFileInputStream(const String& filename)
: FileInputStream_aux(filename)
, wxZipInputStream(file_stream)
{}
ZipFileInputStream(const String& filename, wxZipEntry* entry) ZipFileInputStream(const String& filename, wxZipEntry* entry)
: wxFileInputStream(filename) : FileInputStream_aux(filename)
, wxZipInputStream(static_cast<wxFileInputStream&>(*this)) , wxZipInputStream(file_stream)
{ {
OpenEntry(*entry); OpenEntry(*entry);
} }
}; };
class BufferedFileInputStream_aux {
protected:
wxFileInputStream file_stream;
inline BufferedFileInputStream_aux(const String& filename)
: file_stream(filename)
{}
};
/// A buffered version of wxFileInputStream /// A buffered version of wxFileInputStream
/** 2007-08-24: /** 2007-08-24:
* According to profiling this gives a significant speedup * According to profiling this gives a significant speedup
* Bringing the avarage run time of read_utf8_line from 186k to 54k (in cpu time units) * Bringing the avarage run time of read_utf8_line from 186k to 54k (in cpu time units)
*/ */
class BufferedFileInputStream : private BufferedFileInputStream_aux, public wxBufferedInputStream { class BufferedFileInputStream : private FileInputStream_aux, public wxBufferedInputStream {
public: public:
inline BufferedFileInputStream(const String& filename) inline BufferedFileInputStream(const String& filename)
: BufferedFileInputStream_aux(filename) : FileInputStream_aux(filename)
, wxBufferedInputStream(file_stream) , wxBufferedInputStream(file_stream)
{} {}
}; };
InputStreamP Package::openIn(const String& file) { unique_ptr<wxInputStream> Package::openIn(const String& file) {
if (!file.empty() && file.GetChar(0) == _('/')) { if (!file.empty() && file.GetChar(0) == _('/')) {
// absolute path, open file from another package // absolute path, open file from another package
Packaged* p = dynamic_cast<Packaged*>(this); Packaged* p = dynamic_cast<Packaged*>(this);
@@ -200,16 +201,16 @@ InputStreamP Package::openIn(const String& file) {
throw PackageError(_ERROR_2_("file not found package like", file, filename)); throw PackageError(_ERROR_2_("file not found package like", file, filename));
} }
} }
InputStreamP stream; unique_ptr<wxInputStream> stream;
if (it != files.end() && it->second.wasWritten()) { if (it != files.end() && it->second.wasWritten()) {
// written to this file, open the temp file // written to this file, open the temp file
stream = make_shared<BufferedFileInputStream>(it->second.tempName); stream = make_unique<BufferedFileInputStream>(it->second.tempName);
} else if (wxFileExists(filename+_("/")+file)) { } else if (wxFileExists(filename+_("/")+file)) {
// a file in directory package // a file in directory package
stream = make_shared<BufferedFileInputStream>(filename+_("/")+file); stream = make_unique<BufferedFileInputStream>(filename+_("/")+file);
} else if (wxFileExists(filename) && it != files.end() && it->second.zipEntry) { } else if (wxFileExists(filename) && it != files.end() && it->second.zipEntry) {
// a file in a zip archive // a file in a zip archive
stream = static_pointer_cast<wxZipInputStream>(make_shared<ZipFileInputStream>(filename, it->second.zipEntry)); stream = make_unique<ZipFileInputStream>(filename, it->second.zipEntry);
} else { } else {
// shouldn't happen, packaged changed by someone else since opening it // shouldn't happen, packaged changed by someone else since opening it
throw FileNotFoundError(file, filename); throw FileNotFoundError(file, filename);
@@ -221,8 +222,8 @@ InputStreamP Package::openIn(const String& file) {
} }
} }
OutputStreamP Package::openOut(const String& file) { unique_ptr<wxOutputStream> Package::openOut(const String& file) {
return make_shared<wxFileOutputStream>(nameOut(file)); return make_unique<wxFileOutputStream>(nameOut(file));
} }
String Package::nameOut(const String& file) { String Package::nameOut(const String& file) {
@@ -292,13 +293,13 @@ String Package::absoluteName(const String& file) {
} }
} }
// Open a file that is in some package // Open a file that is in some package
InputStreamP Package::openAbsoluteFile(const String& name) { unique_ptr<wxInputStream> Package::openAbsoluteFile(const String& name) {
size_t pos = name.find_first_of(_('\1')); size_t pos = name.find_first_of(_('\1'));
if (pos == String::npos) { if (pos == String::npos) {
// temp or dir file // temp or dir file
shared_ptr<wxFileInputStream> f = make_shared<wxFileInputStream>(name); auto stream = make_unique<wxFileInputStream>(name);
if (!f->IsOk()) throw FileNotFoundError(_("<unknown>"), name); if (!stream->IsOk()) throw FileNotFoundError(_("<unknown>"), name);
return f; return stream;
} else { } else {
// packaged file, always in zip format // packaged file, always in zip format
Package p; Package p;
@@ -355,12 +356,9 @@ void Package::openSubdir(const String& name) {
void Package::openZipfile() { void Package::openZipfile() {
// close old streams // close old streams
delete fileStream; fileStream = nullptr; zipStream.reset();
delete zipStream; zipStream = nullptr;
// open streams // open streams
fileStream = new wxFileInputStream(filename); zipStream = make_unique<ZipFileInputStream>(filename);
if (!fileStream->IsOk()) throw PackageError(_ERROR_1_("package not found", filename));
zipStream = new wxZipInputStream(*fileStream);
if (!zipStream->IsOk()) throw PackageError(_ERROR_1_("package not found", filename)); if (!zipStream->IsOk()) throw PackageError(_ERROR_1_("package not found", filename));
// read zip entries // read zip entries
loadZipStream(); loadZipStream();
@@ -421,14 +419,13 @@ void Package::saveToZipfile(const String& saveAs, bool remove_unused, bool is_co
} else { } else {
// changed file, or the old package was not a zipfile // changed file, or the old package was not a zipfile
newZip->PutNextEntry(f.first); newZip->PutNextEntry(f.first);
InputStreamP temp = openIn(f.first); auto temp_stream = openIn(f.first);
newZip->Write(*temp); newZip->Write(*temp_stream);
} }
} }
// close the old file // close the old file
if (!is_copy) { if (!is_copy) {
delete zipStream; zipStream = nullptr; zipStream.reset();
delete fileStream; fileStream = nullptr;
} }
} catch (Error e) { } catch (Error e) {
// when things go wrong delete the temp file // when things go wrong delete the temp file
@@ -503,11 +500,11 @@ Packaged::Packaged()
, fully_loaded(true) , fully_loaded(true)
{} {}
InputStreamP Packaged::openIconFile() { unique_ptr<wxInputStream> Packaged::openIconFile() {
if (!icon_filename.empty()) { if (!icon_filename.empty()) {
return openIn(icon_filename); return openIn(icon_filename);
} else { } else {
return InputStreamP(); return unique_ptr<wxInputStream>();
} }
} }
@@ -526,7 +523,8 @@ void Packaged::open(const String& package, bool just_header) {
PROFILER(just_header ? _("open package header") : _("open package fully")); PROFILER(just_header ? _("open package header") : _("open package fully"));
if (just_header) { if (just_header) {
// Read just the header (the part common to all Packageds) // Read just the header (the part common to all Packageds)
Reader reader(openIn(typeName()), this, absoluteFilename() + _("/") + typeName(), true); auto stream = openIn(typeName());
Reader reader(*stream, this, absoluteFilename() + _("/") + typeName(), true);
try { try {
JustAsPackageProxy proxy(this); JustAsPackageProxy proxy(this);
reader.handle_greedy(proxy); reader.handle_greedy(proxy);
@@ -538,9 +536,11 @@ void Packaged::open(const String& package, bool just_header) {
loadFully(); loadFully();
} }
} }
void Packaged::loadFully() { void Packaged::loadFully() {
if (fully_loaded) return; if (fully_loaded) return;
Reader reader(openIn(typeName()), this, absoluteFilename() + _("/") + typeName()); auto stream = openIn(typeName());
Reader reader(*stream, this, absoluteFilename() + _("/") + typeName());
try { try {
reader.handle_greedy(*this); reader.handle_greedy(*this);
validate(reader.file_app_version); validate(reader.file_app_version);
+11 -12
View File
@@ -100,11 +100,11 @@ class Package : public IntrusivePtrVirtualBase {
// --------------------------------------------------- : Managing the inside of the package // --------------------------------------------------- : Managing the inside of the package
/// Open an input stream for a file in the package. /// Open an input stream for a file in the package.
InputStreamP openIn(const String& file); unique_ptr<wxInputStream> openIn(const String& file);
/// Open an output stream for a file in the package. /// Open an output stream for a file in the package.
/// (changes are only committed with save()) /// (changes are only committed with save())
OutputStreamP openOut(const String& file); unique_ptr<wxOutputStream> openOut(const String& file);
/// Get a filename that can be written to to modfify a file in the package /// Get a filename that can be written to to modfify a file in the package
/// (changes are only committed with save()) /// (changes are only committed with save())
@@ -125,7 +125,7 @@ class Package : public IntrusivePtrVirtualBase {
String absoluteName(const String& file); String absoluteName(const String& file);
/// Open a file given an absolute filename /// Open a file given an absolute filename
static InputStreamP openAbsoluteFile(const String& name); static unique_ptr<wxInputStream> openAbsoluteFile(const String& name);
// --------------------------------------------------- : Managing the inside of the package : Reader/writer // --------------------------------------------------- : Managing the inside of the package : Reader/writer
@@ -141,7 +141,8 @@ class Package : public IntrusivePtrVirtualBase {
template <typename T> template <typename T>
void writeFile(const String& file, const T& obj, Version file_version) { void writeFile(const String& file, const T& obj, Version file_version) {
Writer writer(openOut(file), file_version); auto stream = openOut(file);
Writer writer(*stream, file_version);
writer.handle(obj); writer.handle(obj);
} }
@@ -182,10 +183,8 @@ class Package : public IntrusivePtrVirtualBase {
private: private:
/// All files in the package /// All files in the package
FileInfos files; FileInfos files;
/// Filestream for reading zip files /// Filestream/zipstream for reading zip files
wxFileInputStream* fileStream; unique_ptr<wxZipInputStream> zipStream;
/// Filestream for reading zip files
wxZipInputStream* zipStream;
void loadZipStream(); void loadZipStream();
void openDirectory(bool fast = false); void openDirectory(bool fast = false);
@@ -229,7 +228,7 @@ class Packaged : public Package {
int position_hint; ///< A hint for the package list int position_hint; ///< A hint for the package list
/// Get an input stream for the package icon, if there is any /// Get an input stream for the package icon, if there is any
InputStreamP openIconFile(); unique_ptr<wxInputStream> openIconFile();
/// Open a package, and read the data /// Open a package, and read the data
/** if just_header is true, then the package is not fully parsed. /** if just_header is true, then the package is not fully parsed.
@@ -289,9 +288,9 @@ intrusive_ptr<T> open_package(const String& filename) {
// This is here because it uses dynamic_cast and must be to a complete type. // This is here because it uses dynamic_cast and must be to a complete type.
template <typename T> template <typename T>
inline void Package::readFile(const String& file, T& obj) inline void Package::readFile(const String& file, T& obj) {
{ auto stream = openIn(file);
Reader reader(openIn(file), dynamic_cast<Packaged*>(this), absoluteFilename() + _("/") + file); Reader reader(*stream, dynamic_cast<Packaged*>(this), absoluteFilename() + _("/") + file);
try { try {
reader.handle_greedy(obj); reader.handle_greedy(obj);
} catch (const ParseError& err) { } catch (const ParseError& err) {
+10 -9
View File
@@ -99,7 +99,7 @@ void PackageManager::findMatching(const String& pattern, vector<PackagedP>& out)
} }
} }
InputStreamP PackageManager::openFileFromPackage(Packaged*& package, const String& name) { unique_ptr<wxInputStream> PackageManager::openFileFromPackage(Packaged*& package, const String& name) {
if (!name.empty() && name.GetChar(0) == _('/')) { if (!name.empty() && name.GetChar(0) == _('/')) {
// absolute name; break name // absolute name; break name
size_t start = name.find_first_not_of(_("/\\"), 1); // allow "//package/name" from incorrect scripts size_t start = name.find_first_not_of(_("/\\"), 1); // allow "//package/name" from incorrect scripts
@@ -339,16 +339,17 @@ void PackageDirectory::loadDatabase() {
String filename = databaseFile(); String filename = databaseFile();
if (wxFileExists(filename)) { if (wxFileExists(filename)) {
// packages file not existing is not an error // packages file not existing is not an error
shared_ptr<wxFileInputStream> file = make_shared<wxFileInputStream>(filename); wxFileInputStream file_stream = {filename};
if (!file->Ok()) return; // failure is not an error if (!file_stream.Ok()) return; // failure is not an error
Reader reader(file, nullptr, filename); Reader reader(file_stream, nullptr, filename);
reader.handle_greedy(*this); reader.handle_greedy(*this);
sort(packages.begin(), packages.end(), compare_name); sort(packages.begin(), packages.end(), compare_name);
} }
} }
void PackageDirectory::saveDatabase() { void PackageDirectory::saveDatabase() {
Writer writer(make_shared<wxFileOutputStream>(databaseFile()), app_version); wxFileOutputStream stream(databaseFile());
Writer writer(stream, app_version);
writer.handle(*this); writer.handle(*this);
} }
String PackageDirectory::databaseFile() { String PackageDirectory::databaseFile() {
@@ -391,13 +392,13 @@ bool PackageDirectory::actual_install(const InstallablePackage& package, const S
String local_file = install_dir + file.substr(name.length()); String local_file = install_dir + file.substr(name.length());
create_parent_dirs(local_file); create_parent_dirs(local_file);
// copy file // copy file
InputStreamP is = installer.openIn(file); auto in_stream = installer.openIn(file);
wxFileOutputStream os (local_file); wxFileOutputStream out_stream(local_file);
if (!os.IsOk()) { if (!out_stream.IsOk()) {
int act = wxMessageBox(_ERROR_1_("cannot create file", file), _TITLE_("cannot create file"), wxICON_ERROR | wxYES_NO); int act = wxMessageBox(_ERROR_1_("cannot create file", file), _TITLE_("cannot create file"), wxICON_ERROR | wxYES_NO);
if (act == wxNO) return false; if (act == wxNO) return false;
} }
os.Write(*is); out_stream.Write(*in_stream);
} }
// update package database // update package database
// TODO: bless the package? // TODO: bless the package?
+1 -1
View File
@@ -148,7 +148,7 @@ class PackageManager {
* this is to force people to fill in the dependencies * this is to force people to fill in the dependencies
* Afterwards, package will be set to the package the file is opened from * Afterwards, package will be set to the package the file is opened from
*/ */
InputStreamP openFileFromPackage(Packaged*& package, const String& name); unique_ptr<wxInputStream> openFileFromPackage(Packaged*& package, const String& name);
/// Get a filename to open from a package /// Get a filename to open from a package
/** WARNING: this is a bit of a hack, since not all package types support names in this way. /** WARNING: this is a bit of a hack, since not all package types support names in this way.
+15 -28
View File
@@ -21,33 +21,20 @@ IMPLEMENT_DYNAMIC_ARG(ReaderPragmaHandler,reader_pragma_handler,nullptr);
// ----------------------------------------------------------------------------- : Reader // ----------------------------------------------------------------------------- : Reader
Reader::Reader(const InputStreamP& input, Packaged* package, const String& filename, bool ignore_invalid) Reader::Reader(wxInputStream& input, Packaged* package, const String& filename, bool ignore_invalid)
: indent(0), expected_indent(0), state(OUTSIDE) : indent(0), expected_indent(0), state(OUTSIDE)
, ignore_invalid(ignore_invalid) , ignore_invalid(ignore_invalid)
, filename(filename), package(package), line_number(0), previous_line_number(0) , filename(filename), package(package), line_number(0), previous_line_number(0)
, input(input) , input(input)
{ {
assert(input); assert(input.IsOk());
assert(input->IsOk()); eat_utf8_bom(input);
eat_utf8_bom(*input);
moveNext(); moveNext();
handleAppVersion(); handleAppVersion();
} }
Reader::Reader(Reader* parent, Packaged* pkg, const String& filename, bool ignore_invalid) unique_ptr<wxInputStream> Reader::openIncludedFile() {
: indent(0), expected_indent(0), state(OUTSIDE) return package_manager.openFileFromPackage(package, value);
, ignore_invalid(ignore_invalid)
, filename(filename), package(pkg), line_number(0), previous_line_number(0)
, input(package_manager.openFileFromPackage(package, filename))
{
assert(input);
eat_utf8_bom(*input);
moveNext();
// in an included file, use the app version of the parent if we have none
handleAppVersion();
if (file_app_version == 0) {
file_app_version = parent->file_app_version;
}
} }
void Reader::addAlias(Version end_version, const Char* a, const Char* b) { void Reader::addAlias(Version end_version, const Char* a, const Char* b) {
@@ -125,11 +112,11 @@ void Reader::moveNext() {
key.clear(); key.clear();
indent = -1; // if no line is read it never has the expected indentation indent = -1; // if no line is read it never has the expected indentation
// repeat until we have a good line // repeat until we have a good line
while (key.empty() && !input->Eof()) { while (key.empty() && !input.Eof()) {
readLine(); readLine();
} }
// did we reach the end of the file? // did we reach the end of the file?
if (key.empty() && input->Eof()) { if (key.empty() && input.Eof()) {
line_number += 1; line_number += 1;
indent = -1; indent = -1;
} }
@@ -216,7 +203,7 @@ void Reader::readLine(bool in_string) {
line_number += 1; line_number += 1;
// We have to do our own line reading, because wxTextInputStream is insane // We have to do our own line reading, because wxTextInputStream is insane
try { try {
line = read_utf8_line(*input); line = read_utf8_line(input);
} catch (const ParseError& e) { } catch (const ParseError& e) {
throw ParseError(e.what() + String(_(" on line ")) << line_number); throw ParseError(e.what() + String(_(" on line ")) << line_number);
} }
@@ -304,7 +291,7 @@ const String& Reader::getValue() {
// read all lines that are indented enough // read all lines that are indented enough
readLine(true); readLine(true);
previous_line_number = line_number; previous_line_number = line_number;
while (indent >= expected_indent && !input->Eof()) { while (indent >= expected_indent && !input.Eof()) {
previous_value.resize(previous_value.size() + pending_newlines, _('\n')); previous_value.resize(previous_value.size() + pending_newlines, _('\n'));
pending_newlines = 0; pending_newlines = 0;
previous_value += line.substr(expected_indent); // strip expected indent previous_value += line.substr(expected_indent); // strip expected indent
@@ -312,15 +299,15 @@ const String& Reader::getValue() {
readLine(true); readLine(true);
pending_newlines++; pending_newlines++;
// skip empty lines that are not indented enough // skip empty lines that are not indented enough
} while(trim(line).empty() && indent < expected_indent && !input->Eof()); } while(trim(line).empty() && indent < expected_indent && !input.Eof());
} }
// moveNext(), but without the initial readLine() // moveNext(), but without the initial readLine()
state = HANDLED; state = HANDLED;
while (key.empty() && !input->Eof()) { while (key.empty() && !input.Eof()) {
readLine(); readLine();
} }
// did we reach the end of the file? // did we reach the end of the file?
if (key.empty() && input->Eof()) { if (key.empty() && input.Eof()) {
line_number += 1; line_number += 1;
indent = -1; indent = -1;
} }
@@ -400,9 +387,9 @@ template <> void Reader::handle(FileName& f) {
// copy file into current package // copy file into current package
try { try {
String packaged_name = clipboard_package()->newFileName(_("image"),_("")); // a new unique name in the package, assume it's an image String packaged_name = clipboard_package()->newFileName(_("image"),_("")); // a new unique name in the package, assume it's an image
OutputStreamP out = clipboard_package()->openOut(packaged_name); auto out_stream = clipboard_package()->openOut(packaged_name);
InputStreamP in = Package::openAbsoluteFile(str); auto in_stream = Package::openAbsoluteFile(str);
out->Write(*in); // copy out_stream->Write(*in_stream); // copy
f.assign(packaged_name); f.assign(packaged_name);
} catch (Error const&) { } catch (Error const&) {
// ignore errors // ignore errors
+12 -9
View File
@@ -20,9 +20,6 @@ class Packaged;
// ----------------------------------------------------------------------------- : Reader // ----------------------------------------------------------------------------- : Reader
typedef wxInputStream InputStream;
typedef shared_ptr<wxInputStream> InputStreamP;
/// The Reader can be used for reading (deserializing) objects /// The Reader can be used for reading (deserializing) objects
/** This class makes use of the reflection functionality, in effect /** This class makes use of the reflection functionality, in effect
* an object tells the Reader what fields it would like to read. * an object tells the Reader what fields it would like to read.
@@ -37,12 +34,12 @@ class Reader {
/** Used for "include file" keys. /** Used for "include file" keys.
* package can be nullptr * package can be nullptr
*/ */
Reader(Reader* parent, Packaged* package, const String& filename, bool ignore_invalid = false); //Reader(Reader* parent, Packaged* package, const String& filename, bool ignore_invalid = false);
public: public:
/// Construct a reader that reads from the given input stream /// Construct a reader that reads from the given input stream
/** filename is used only for error messages /** filename is used only for error messages
*/ */
Reader(const InputStreamP& input, Packaged* package = nullptr, const String& filename = wxEmptyString, bool ignore_invalid = false); Reader(wxInputStream& input, Packaged* package = nullptr, const String& filename = wxEmptyString, bool ignore_invalid = false);
~Reader() { showWarnings(); } ~Reader() { showWarnings(); }
@@ -119,7 +116,7 @@ class Reader {
// --------------------------------------------------- : Data // --------------------------------------------------- : Data
/// App version this file was made with /// App version this file was made with
Version file_app_version; Version file_app_version;
private: private:
/// The line we read /// The line we read
String line; String line;
/// The key and value of the last line we read /// The key and value of the last line we read
@@ -156,7 +153,7 @@ class Reader {
/// Line number of the previous_line /// Line number of the previous_line
int previous_line_number; int previous_line_number;
/// Input stream we are reading from /// Input stream we are reading from
InputStreamP input; wxInputStream& input;
/// Accumulated warning messages /// Accumulated warning messages
String warnings; String warnings;
@@ -182,14 +179,20 @@ class Reader {
template <typename T> template <typename T>
void unknownKey(T& v) { void unknownKey(T& v) {
if (key == _("include_file")) { if (key == _("include_file")) {
Reader reader(this, package, value, ignore_invalid); auto stream = openIncludedFile();
reader.handle_greedy(v); Reader sub_reader(*stream, package, value, ignore_invalid);
if (sub_reader.file_app_version == 0) {
// in an included file, use the app version of the parent if there is none
sub_reader.file_app_version = file_app_version;
}
sub_reader.handle_greedy(v);
moveNext(); moveNext();
} else { } else {
unknownKey(); unknownKey();
} }
} }
void unknownKey(); void unknownKey();
unique_ptr<wxInputStream> openIncludedFile();
}; };
// ----------------------------------------------------------------------------- : Container types // ----------------------------------------------------------------------------- : Container types
+2 -2
View File
@@ -17,10 +17,10 @@ using boost::tribool;
// ----------------------------------------------------------------------------- : Writer // ----------------------------------------------------------------------------- : Writer
Writer::Writer(const OutputStreamP& output, Version file_app_version) Writer::Writer(OutputStream& output, Version file_app_version)
: indentation(0) : indentation(0)
, output(output) , output(output)
, stream(*output, wxEOL_UNIX, wxMBConvUTF8()) , stream(output, wxEOL_UNIX, wxMBConvUTF8())
{ {
stream.WriteString(BYTE_ORDER_MARK); stream.WriteString(BYTE_ORDER_MARK);
handle(_("mse_version"), file_app_version); handle(_("mse_version"), file_app_version);
+2 -5
View File
@@ -19,14 +19,11 @@ DECLARE_POINTER_TYPE(StyleSheet);
// ----------------------------------------------------------------------------- : Writer // ----------------------------------------------------------------------------- : Writer
typedef wxOutputStream OutputStream;
typedef shared_ptr<wxOutputStream> OutputStreamP;
/// The Writer can be used for writing (serializing) objects /// The Writer can be used for writing (serializing) objects
class Writer { class Writer {
public: public:
/// Construct a writer that writes to the given output stream /// Construct a writer that writes to the given output stream
Writer(const OutputStreamP& output, Version file_app_version); Writer(OutputStream& output, Version file_app_version);
/// Tell the reflection code we are not reading /// Tell the reflection code we are not reading
inline bool reading() const { return false; } inline bool reading() const { return false; }
@@ -81,7 +78,7 @@ class Writer {
vector<const Char*> pending_opened; vector<const Char*> pending_opened;
/// Output stream we are writing to /// Output stream we are writing to
OutputStreamP output; OutputStream& output;
/// Text stream wrapping the output stream /// Text stream wrapping the output stream
wxTextOutputStream stream; wxTextOutputStream stream;