Commit 31cc9a52 authored by twanvl's avatar twanvl

The 'Big Whine' patch:

 Any use of a file from another package without a declared dependency will give a warning;

Also added some more _LOCALE_123_ macros so we need less format_string calls
parent 5d797fa6
...@@ -622,14 +622,24 @@ error: ...@@ -622,14 +622,24 @@ error:
You should leave a bug report on http://magicseteditor.sourceforge.net/ You should leave a bug report on http://magicseteditor.sourceforge.net/
# File related # File related
file not found: File not found: '%s' in package '%s' file not found: File not found: '%s' in package '%s'
file not found package like:
File not found: '%s' in package '%s'
If you are trying to open a file from another package, use "/package/filename"
file parse error: file parse error:
Error while parsing file: '%s' Error while parsing file: '%s'
%s %s
package not found: Package not found: '%s' package not found: Package not found: '%s'
package out of date: The package '%s' (version %s) is out of date, version %s is required. package out of date: The package '%s' (version %s) is out of date, version %s is required.
package too new: The package '%s' (version %s) is not compatible with version %s, required by '%s'
unable to open output file: Error while saving, unable to open output file unable to open output file: Error while saving, unable to open output file
unable to store file: Error while saving, unable to store file unable to store file: Error while saving, unable to store file
dependency not given:
The package '%s' uses files from the package '%s', but it does not list a dependency.
To resolve this, add:
depends on:
package: %s
version: %s
# Script stuff # Script stuff
has no member: %s has no member '%s' has no member: %s has no member '%s'
......
...@@ -15,7 +15,7 @@ card dpi: 150 ...@@ -15,7 +15,7 @@ card dpi: 150
init script: init script:
# Load scripts for image box # Load scripts for image box
include file: magic-default-image.mse-include/scripts include file: /magic-default-image.mse-include/scripts
# Should hybrids have a grey name? # Should hybrids have a grey name?
mask_hybrid_with_land := { styling.grey_hybrid_name } mask_hybrid_with_land := { styling.grey_hybrid_name }
......
...@@ -33,7 +33,7 @@ card dpi: 150 ...@@ -33,7 +33,7 @@ card dpi: 150
init script: init script:
# Load blend scripts for hybrids/multicolors # Load blend scripts for hybrids/multicolors
include file: magic-default-image.mse-include/scripts include file: /magic-default-image.mse-include/scripts
# We have no land templates # We have no land templates
land_template := { "c{type}.jpg" } land_template := { "c{type}.jpg" }
...@@ -305,7 +305,7 @@ card style: ...@@ -305,7 +305,7 @@ card style:
z index: 1 z index: 1
render style: image render style: image
alignment: middle center alignment: middle center
include file: magic-watermarks.mse-include/watermarks include file: /magic-watermarks.mse-include/watermarks
text 2: text 2:
left: 33 left: 33
top : 65 top : 65
...@@ -348,7 +348,7 @@ card style: ...@@ -348,7 +348,7 @@ card style:
render style: image render style: image
alignment: middle center alignment: middle center
angle: 180 angle: 180
include file: magic-watermarks.mse-include/watermarks include file: /magic-watermarks.mse-include/watermarks
############################# PT ############################# PT
power: power:
......
...@@ -279,7 +279,7 @@ card style: ...@@ -279,7 +279,7 @@ card style:
z index: 1 z index: 1
render style: image render style: image
alignment: middle center alignment: middle center
include file: magic-watermarks.mse-include/watermarks include file: /magic-watermarks.mse-include/watermarks
############################# PT ############################# PT
power: power:
......
...@@ -250,7 +250,7 @@ card style: ...@@ -250,7 +250,7 @@ card style:
z index: 1 z index: 1
render style: image render style: image
alignment: middle center alignment: middle center
include file: magic-watermarks.mse-include/watermarks include file: /magic-watermarks.mse-include/watermarks
############################# PT ############################# PT
power: power:
......
...@@ -378,7 +378,7 @@ card style: ...@@ -378,7 +378,7 @@ card style:
z index: 1 z index: 1
render style: image render style: image
alignment: middle center alignment: middle center
include file: magic-watermarks.mse-include/watermarks include file: /magic-watermarks.mse-include/watermarks
watermark 2: watermark 2:
left: 349.45 left: 349.45
top : 240 top : 240
...@@ -387,7 +387,7 @@ card style: ...@@ -387,7 +387,7 @@ card style:
z index: 1 z index: 1
render style: image render style: image
alignment: middle center alignment: middle center
include file: magic-watermarks.mse-include/watermarks include file: /magic-watermarks.mse-include/watermarks
############################# PT ############################# PT
power: power:
......
...@@ -263,7 +263,7 @@ card style: ...@@ -263,7 +263,7 @@ card style:
render style: image render style: image
alignment: middle center alignment: middle center
visible: { card.rule_text != "" and card.flavor_text != "" } visible: { card.rule_text != "" and card.flavor_text != "" }
include file: magic-watermarks.mse-include/watermarks include file: /magic-watermarks.mse-include/watermarks
############################# PT ############################# PT
power: power:
......
...@@ -253,7 +253,7 @@ card style: ...@@ -253,7 +253,7 @@ card style:
width: { 300 - max(18,card_style.rarity.content_width) } width: { 300 - max(18,card_style.rarity.content_width) }
height: 28 height: 28
alignment: middle shrink-overflow alignment: middle shrink-overflow
z index: 1 z index: 2
padding top: 2 padding top: 2
font: font:
name: Matrix name: Matrix
......
...@@ -398,7 +398,7 @@ card style: ...@@ -398,7 +398,7 @@ card style:
z index: 2 z index: 2
render style: image render style: image
alignment: middle center alignment: middle center
include file: magic-watermarks.mse-include/watermarks include file: /magic-watermarks.mse-include/watermarks
############################# PT ############################# PT
pt: pt:
......
...@@ -18,7 +18,7 @@ card dpi: 150 ...@@ -18,7 +18,7 @@ card dpi: 150
init script: init script:
# Load scripts for image box # Load scripts for image box
include file: magic-default-image.mse-include/scripts include file: /magic-default-image.mse-include/scripts
# Should hybrids have a grey name? # Should hybrids have a grey name?
mask_hybrid_with_land := { false } mask_hybrid_with_land := { false }
...@@ -332,7 +332,7 @@ card style: ...@@ -332,7 +332,7 @@ card style:
z index: 1 z index: 1
render style: image render style: image
alignment: middle center alignment: middle center
include file: magic-watermarks.mse-include/watermarks include file: /magic-watermarks.mse-include/watermarks
watermark 2: watermark 2:
left: 151 left: 151
top : 378 top : 378
...@@ -342,7 +342,7 @@ card style: ...@@ -342,7 +342,7 @@ card style:
z index: 1 z index: 1
render style: image render style: image
alignment: middle center alignment: middle center
include file: magic-watermarks.mse-include/watermarks include file: /magic-watermarks.mse-include/watermarks
############################# PT ############################# PT
pt: pt:
......
...@@ -18,7 +18,7 @@ card dpi: 150 ...@@ -18,7 +18,7 @@ card dpi: 150
init script: init script:
# Load scripts for image box # Load scripts for image box
include file: magic-default-image.mse-include/scripts include file: /magic-default-image.mse-include/scripts
# Should hybrids have a grey name? # Should hybrids have a grey name?
mask_hybrid_with_land := { styling.grey_hybrid_name } mask_hybrid_with_land := { styling.grey_hybrid_name }
...@@ -270,7 +270,7 @@ card style: ...@@ -270,7 +270,7 @@ card style:
z index: 1 z index: 1
render style: image render style: image
alignment: middle center alignment: middle center
include file: magic-watermarks.mse-include/watermarks include file: /magic-watermarks.mse-include/watermarks
############################# Loyalty ############################# Loyalty
loyalty: loyalty:
......
...@@ -14,7 +14,7 @@ card dpi: 150 ...@@ -14,7 +14,7 @@ card dpi: 150
init script: init script:
# Load scripts for image box # Load scripts for image box
include file: magic-default-image.mse-include/scripts include file: /magic-default-image.mse-include/scripts
# Should hybrids have a grey name? # Should hybrids have a grey name?
mask_hybrid_with_land := { styling.grey_hybrid_name } mask_hybrid_with_land := { styling.grey_hybrid_name }
...@@ -229,7 +229,7 @@ card style: ...@@ -229,7 +229,7 @@ card style:
z index: 1 z index: 1
render style: image render style: image
alignment: middle center alignment: middle center
include file: magic-watermarks.mse-include/watermarks include file: /magic-watermarks.mse-include/watermarks
############################# PT ############################# PT
pt: pt:
......
...@@ -17,7 +17,7 @@ card dpi: 150 ...@@ -17,7 +17,7 @@ card dpi: 150
init script: init script:
# Load scripts for image box # Load scripts for image box
include file: magic-default-image.mse-include/scripts include file: /magic-default-image.mse-include/scripts
# Should hybrids have a grey name? # Should hybrids have a grey name?
mask_hybrid_with_land := { styling.grey_hybrid_name } mask_hybrid_with_land := { styling.grey_hybrid_name }
...@@ -365,7 +365,7 @@ card style: ...@@ -365,7 +365,7 @@ card style:
z index: 1 z index: 1
render style: image render style: image
alignment: middle center alignment: middle center
include file: magic-watermarks.mse-include/watermarks include file: /magic-watermarks.mse-include/watermarks
watermark 2: watermark 2:
left: 338 left: 338
top : 228 top : 228
...@@ -374,7 +374,7 @@ card style: ...@@ -374,7 +374,7 @@ card style:
z index: 1 z index: 1
render style: image render style: image
alignment: middle center alignment: middle center
include file: magic-watermarks.mse-include/watermarks include file: /magic-watermarks.mse-include/watermarks
############################# PT ############################# PT
pt: pt:
......
...@@ -17,7 +17,7 @@ card dpi: 150 ...@@ -17,7 +17,7 @@ card dpi: 150
init script: init script:
# Load scripts for default images # Load scripts for default images
include file: magic-default-image.mse-include/scripts include file: /magic-default-image.mse-include/scripts
# What should the textbox look like? # What should the textbox look like?
text_shape := { text_shape := {
......
...@@ -21,7 +21,7 @@ card dpi: 150 ...@@ -21,7 +21,7 @@ card dpi: 150
init script: init script:
# Load scripts for image box # Load scripts for image box
include file: magic-default-image.mse-include/scripts include file: /magic-default-image.mse-include/scripts
# Should hybrids have a grey name? # Should hybrids have a grey name?
mask_hybrid_with_land := { styling.grey_hybrid_name } mask_hybrid_with_land := { styling.grey_hybrid_name }
...@@ -224,7 +224,7 @@ card style: ...@@ -224,7 +224,7 @@ card style:
type: type:
left: 35 left: 35
top : 299 top : 298
width: { 308 - max(22,card_style.rarity.content_width) } width: { 308 - max(22,card_style.rarity.content_width) }
height: 20 height: 20
alignment: top shrink-overflow alignment: top shrink-overflow
...@@ -305,7 +305,7 @@ card style: ...@@ -305,7 +305,7 @@ card style:
z index: 1 z index: 1
render style: image render style: image
alignment: middle center alignment: middle center
include file: magic-watermarks.mse-include/watermarks include file: /magic-watermarks.mse-include/watermarks
############################# PT ############################# PT
pt: pt:
......
...@@ -426,7 +426,7 @@ card style: ...@@ -426,7 +426,7 @@ card style:
z index: 1 z index: 1
render style: image render style: image
alignment: middle center alignment: middle center
include file: magic-watermarks.mse-include/watermarks include file: /magic-watermarks.mse-include/watermarks
watermark 2: watermark 2:
left: 338 left: 338
top : 228 top : 228
...@@ -435,7 +435,7 @@ card style: ...@@ -435,7 +435,7 @@ card style:
z index: 1 z index: 1
render style: image render style: image
alignment: middle center alignment: middle center
include file: magic-watermarks.mse-include/watermarks include file: /magic-watermarks.mse-include/watermarks
############################# PT ############################# PT
pt: pt:
......
...@@ -315,7 +315,7 @@ card style: ...@@ -315,7 +315,7 @@ card style:
z index: 1 z index: 1
render style: image render style: image
alignment: middle center alignment: middle center
include file: magic-watermarks.mse-include/watermarks include file: /magic-watermarks.mse-include/watermarks
############################# PT ############################# PT
pt: pt:
......
...@@ -266,7 +266,7 @@ card style: ...@@ -266,7 +266,7 @@ card style:
z index: 1 z index: 1
render style: image render style: image
alignment: middle center alignment: middle center
include file: magic-watermarks.mse-include/watermarks include file: /magic-watermarks.mse-include/watermarks
############################# PT ############################# PT
pt: pt:
......
...@@ -173,10 +173,10 @@ init script: ...@@ -173,10 +173,10 @@ init script:
# The code consists of 4 parts: # The code consists of 4 parts:
# normal/token, color, shifted, split # normal/token, color, shifted, split
sort_index := { sort_index := {
(if contains(card.shape, match:"token") then "T" else "N") + # Tokens come last (if contains(card.shape, match:"token") then "T" else " ") + # Tokens come last
color_of_card() + color_of_card() +
(if contains(card.shape, match:"shifted") then "S" else "N") + # planeshifted cards come after normal ones (if contains(card.shape, match:"shifted") then "S" else " ") + # planeshifted cards come after normal ones
(if contains(card.shape, match:"split") then "S" else "N") + # split cards come after normal ones (if contains(card.shape, match:"split") then "S" else " ") + # split cards come after normal ones
":" ":"
} }
is_multicolor := { chosen(choice: "multicolor") and input != "artifact, multicolor" } is_multicolor := { chosen(choice: "multicolor") and input != "artifact, multicolor" }
...@@ -221,7 +221,7 @@ init script: ...@@ -221,7 +221,7 @@ init script:
} }
rarity_sort := { rarity_sort := {
if set.sort_special_rarity == "with the rest" or card.rarity != "special" then "A" else "Z" if set.sort_special_rarity == "with the rest" or card.rarity != "special" then " " else "S"
} }
set_filter := { set_filter := {
if set.sort_special_rarity != "separate numbering" then nil if set.sort_special_rarity != "separate numbering" then nil
...@@ -825,7 +825,7 @@ card field: ...@@ -825,7 +825,7 @@ card field:
name: watermark name: watermark
icon: stats/watermark.png icon: stats/watermark.png
position hint: 200 position hint: 200
include file: magic-watermarks.mse-include/watermark-names include file: /magic-watermarks.mse-include/watermark-names
description: A watermark for below the textbox, this can be a big mana symbol used on basic lands, or a guild symbol description: A watermark for below the textbox, this can be a big mana symbol used on basic lands, or a guild symbol
############################# Loyalty ############################# Loyalty
...@@ -1052,7 +1052,7 @@ card field: ...@@ -1052,7 +1052,7 @@ card field:
card field: card field:
type: choice type: choice
name: watermark 2 name: watermark 2
include file: magic-watermarks.mse-include/watermark-names include file: /magic-watermarks.mse-include/watermark-names
icon: stats/watermark.png icon: stats/watermark.png
show statistics: false show statistics: false
description: A watermark for below the textbox, this can be a big mana symbol used on basic lands, a special symbol, or a guild symbol description: A watermark for below the textbox, this can be a big mana symbol used on basic lands, a special symbol, or a guild symbol
......
...@@ -30,7 +30,7 @@ However some keys, like @mse version@ and @type@ must come first because they in ...@@ -30,7 +30,7 @@ However some keys, like @mse version@ and @type@ must come first because they in
A heirachical file can contain a reference to another file: A heirachical file can contain a reference to another file:
>>>include file: <em>filename</em> >>>include file: <em>filename</em>
Where filename must be an absolute [[type:filename]]. Where filename must be an absolute or relative [[type:filename]].
That file is included literally into the current one; except for indentation, the included file never escapes from the level the 'include file' line is on. That file is included literally into the current one; except for indentation, the included file never escapes from the level the 'include file' line is on.
......
...@@ -15,7 +15,7 @@ If @alpha@ is 1 the image stays the same, if @alpha@ is 0 the image becomes comp ...@@ -15,7 +15,7 @@ If @alpha@ is 1 the image stays the same, if @alpha@ is 0 the image becomes comp
--Examples-- --Examples--
> set_alpha("image1.png", alpha: 0.5) == [[Image]] > set_alpha("image1.png", alpha: 0.5) == [[Image]]
>>> set_mask(<img src="image1.png" alt='"image1.png"' style="border:1px solid black;vertical-align:middle;margin:1px;" />, alpha: 0.5) == <img src="image_set_alpha.png" alt='"image_set_alpha.png"' style="border:1px solid black;vertical-align:middle;margin:1px;" /> >>> set_alpha(<img src="image1.png" alt='"image1.png"' style="border:1px solid black;vertical-align:middle;margin:1px;" />, alpha: 0.5) == <img src="image_set_alpha.png" alt='"image_set_alpha.png"' style="border:1px solid black;vertical-align:middle;margin:1px;" />
--See also-- --See also--
| [[fun:set_mask]] Set the transparancy mask of an image. | [[fun:set_mask]] Set the transparancy mask of an image.
...@@ -8,3 +8,13 @@ There are two types of filenames, relative and absolute: ...@@ -8,3 +8,13 @@ There are two types of filenames, relative and absolute:
| <tt>/package/path/to/file</tt> An absolute filename includes the name of the package. This is a package somewhere in the MSE data directory. | <tt>/package/path/to/file</tt> An absolute filename includes the name of the package. This is a package somewhere in the MSE data directory.
Don't forget the double quotes (@""@) in scripts. Don't forget the double quotes (@""@) in scripts.
--Dependencies--
When using an absolute filename to refer to a file from another [[file:package]],
the [[type:dependency]] on that package must be declared.
For example,
>include file: /common.mse-include/something
Will give a warning message, unless the file also lists
>depends on:
> package: common.mse-include
> version: 2007-01-01
...@@ -70,7 +70,7 @@ void KeywordReminderTextValue::store() { ...@@ -70,7 +70,7 @@ void KeywordReminderTextValue::store() {
String new_value = untag(value); String new_value = untag(value);
// Try to parse the script // Try to parse the script
vector<ScriptParseError> parse_errors; vector<ScriptParseError> parse_errors;
ScriptP new_script = parse(new_value, true, parse_errors); ScriptP new_script = parse(new_value, nullptr, true, parse_errors);
if (parse_errors.empty()) { if (parse_errors.empty()) {
// parsed okay, assign // parsed okay, assign
errors.clear(); errors.clear();
......
...@@ -356,7 +356,7 @@ AddSymbolPartAction::AddSymbolPartAction(Symbol& symbol, const SymbolPartP& part ...@@ -356,7 +356,7 @@ AddSymbolPartAction::AddSymbolPartAction(Symbol& symbol, const SymbolPartP& part
{} {}
String AddSymbolPartAction::getName(bool to_undo) const { String AddSymbolPartAction::getName(bool to_undo) const {
return format_string(_ACTION_("add part"), part->name); return _ACTION_1_("add part", part->name);
} }
void AddSymbolPartAction::perform(bool to_undo) { void AddSymbolPartAction::perform(bool to_undo) {
...@@ -395,7 +395,7 @@ void RemoveSymbolPartsAction::check(SymbolGroup& group, const set<SymbolPartP>& ...@@ -395,7 +395,7 @@ void RemoveSymbolPartsAction::check(SymbolGroup& group, const set<SymbolPartP>&
} }
String RemoveSymbolPartsAction::getName(bool to_undo) const { String RemoveSymbolPartsAction::getName(bool to_undo) const {
return format_string(_ACTION_("remove parts"), removals.size() == 1 ? _TYPE_("shape") : _TYPE_("shapes")); return _ACTION_1_("remove parts", removals.size() == 1 ? _TYPE_("shape") : _TYPE_("shapes"));
} }
void RemoveSymbolPartsAction::perform(bool to_undo) { void RemoveSymbolPartsAction::perform(bool to_undo) {
...@@ -433,7 +433,7 @@ DuplicateSymbolPartsAction::DuplicateSymbolPartsAction(Symbol& symbol, const set ...@@ -433,7 +433,7 @@ DuplicateSymbolPartsAction::DuplicateSymbolPartsAction(Symbol& symbol, const set
} }
String DuplicateSymbolPartsAction::getName(bool to_undo) const { String DuplicateSymbolPartsAction::getName(bool to_undo) const {
return format_string(_ACTION_("duplicate"), duplications.size() == 1 ? _TYPE_("shape") : _TYPE_("shapes")); return _ACTION_1_("duplicate", duplications.size() == 1 ? _TYPE_("shape") : _TYPE_("shapes"));
} }
void DuplicateSymbolPartsAction::perform(bool to_undo) { void DuplicateSymbolPartsAction::perform(bool to_undo) {
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
// ----------------------------------------------------------------------------- : ValueAction // ----------------------------------------------------------------------------- : ValueAction
String ValueAction::getName(bool to_undo) const { String ValueAction::getName(bool to_undo) const {
return format_string(_ACTION_("change"), valueP->fieldP->name); return _ACTION_1_("change", valueP->fieldP->name);
} }
// ----------------------------------------------------------------------------- : Simple // ----------------------------------------------------------------------------- : Simple
......
...@@ -31,7 +31,7 @@ String serialize_for_clipboard(Package& package, T& object) { ...@@ -31,7 +31,7 @@ String serialize_for_clipboard(Package& package, T& object) {
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) ); shared_ptr<wxStringInputStream> stream( new wxStringInputStream(data) );
Reader reader(stream, _("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);
} }
......
...@@ -42,12 +42,12 @@ void Installer::installFrom(const String& filename, bool message_on_success, boo ...@@ -42,12 +42,12 @@ void Installer::installFrom(const String& filename, bool message_on_success, boo
i.open(filename); i.open(filename);
try { try {
i.install(local); i.install(local);
} } catch (const Error& e) {
catch (Error& e) {
handle_error(e); handle_error(e);
return; return;
} }
if (message_on_success) { if (message_on_success) {
//wxMessageBox(_ERROR_2_("successful install", i.name(), String() << i.packaged.size(),
wxMessageBox(String::Format(_("'%s' successfully installed %d package%s."), i.name().c_str(), i.packages.size(), i.packages.size() == 1 ? _("") : _("s")), wxMessageBox(String::Format(_("'%s' successfully installed %d package%s."), i.name().c_str(), i.packages.size(), i.packages.size() == 1 ? _("") : _("s")),
_("Magic Set Editor"), wxOK | wxICON_INFORMATION); _("Magic Set Editor"), wxOK | wxICON_INFORMATION);
} }
...@@ -65,15 +65,17 @@ struct dependency_check : public unary_function<bool, PackagedP> { ...@@ -65,15 +65,17 @@ struct dependency_check : public unary_function<bool, PackagedP> {
void Installer::install(bool local) { void Installer::install(bool local) {
// Destination directory // Destination directory
String install_dir = local ? ::packages.getLocalDataDir() : ::packages.getGlobalDataDir(); String install_dir = local ? ::packages.getLocalDataDir() : ::packages.getGlobalDataDir();
if (!wxDirExists(install_dir)) if (!wxDirExists(install_dir)) {
wxMkdir(install_dir, 0755); wxMkdir(install_dir, 0755);
}
// All the packages we're installing. // All the packages we're installing.
vector<PackagedP> new_packages; vector<PackagedP> new_packages;
FOR_EACH(p, packages) { FOR_EACH(p, packages) {
if (wxDirExists(install_dir + _("/") + p) || wxFileExists(install_dir + _("/") + p)) if (wxDirExists(install_dir + _("/") + p) || wxFileExists(install_dir + _("/") + p)) {
throw PackageError(_("Package ") + p + _(" is already installed. Overwriting currently not supported.")); throw PackageError(_("Package ") + p + _(" is already installed. Overwriting currently not supported."));
}
PackagedP pack; PackagedP pack;
wxString fn(wxFileName(p).GetExt()); wxString fn(wxFileName(p).GetExt());
if (fn == _("mse-game")) pack = new_intrusive<Game>(); if (fn == _("mse-game")) pack = new_intrusive<Game>();
...@@ -90,7 +92,6 @@ void Installer::install(bool local) { ...@@ -90,7 +92,6 @@ void Installer::install(bool local) {
new_packages.push_back(pack); new_packages.push_back(pack);
} }
// Check dependencies for each and every package. // Check dependencies for each and every package.
FOR_EACH(p, new_packages) { FOR_EACH(p, new_packages) {
FOR_EACH(d, p->dependencies) { FOR_EACH(d, p->dependencies) {
...@@ -100,28 +101,31 @@ void Installer::install(bool local) { ...@@ -100,28 +101,31 @@ void Installer::install(bool local) {
} }
} }
} }
const FileInfos& file_infos = getFileInfos(); const FileInfos& file_infos = 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;
wxFileName fn(file); wxFileName fn(file);
wxArrayString dirs = fn.GetDirs(); wxArrayString dirs = fn.GetDirs();
if (fn.IsDir() || !dirs.GetCount() || find(packages.begin(), packages.end(), dirs[0]) == packages.end()) if (fn.IsDir() || !dirs.GetCount() || find(packages.begin(), packages.end(), dirs[0]) == packages.end()) {
continue; continue;
}
String current_dir = install_dir; String current_dir = install_dir;
for (size_t j = 0; j < dirs.GetCount(); ++j) { for (size_t j = 0; j < dirs.GetCount(); ++j) {
current_dir += _("/") + dirs[j]; current_dir += _("/") + dirs[j];
if (!wxDirExists(current_dir) && !wxMkdir(current_dir, 0755)) if (!wxDirExists(current_dir) && !wxMkdir(current_dir, 0755)) {
throw PackageError(_("Cannot create folder ") + current_dir + _(" for install. Warning: some packages may have been installed anyway, and some may only be partially installed.")); throw PackageError(_("Cannot create folder ") + current_dir + _(" for install. Warning: some packages may have been installed anyway, and some may only be partially installed."));
}
} }
InputStreamP is = openIn(file); InputStreamP is = openIn(file);
wxFileOutputStream os (install_dir + _("/") + file); wxFileOutputStream os (install_dir + _("/") + file);
if (!os.IsOk()) if (!os.IsOk()) {
throw PackageError(_("Cannot create file ") + install_dir + _("/") + file + _(" for install. Warning: some packages may have been installed anyway, and some may only be partially installed.")); throw PackageError(_("Cannot create file ") + install_dir + _("/") + file + _(" for install. Warning: some packages may have been installed anyway, and some may only be partially installed."));
}
os.Write(*is); os.Write(*is);
} }
} }
......
...@@ -206,7 +206,7 @@ DECLARE_TYPEOF(map<String COMMA KeyValidator>); ...@@ -206,7 +206,7 @@ DECLARE_TYPEOF(map<String COMMA KeyValidator>);
void Locale::validate(Version ver) { void Locale::validate(Version ver) {
// load locale validator // load locale validator
LocaleValidator v; LocaleValidator v;
Reader r(load_resource_text(_("expected_locale_keys")), _("expected_locale_keys")); Reader r(load_resource_text(_("expected_locale_keys")), nullptr, _("expected_locale_keys"));
r.handle_greedy(v); r.handle_greedy(v);
// validate // validate
String errors; String errors;
......
...@@ -248,7 +248,7 @@ void Settings::read() { ...@@ -248,7 +248,7 @@ void Settings::read() {
// settings file not existing is not an error // settings file not existing is not an error
shared_ptr<wxFileInputStream> file = new_shared1<wxFileInputStream>(filename); shared_ptr<wxFileInputStream> file = new_shared1<wxFileInputStream>(filename);
if (!file->Ok()) return; // failure is not an error if (!file->Ok()) return; // failure is not an error
Reader reader(file, filename); Reader reader(file, nullptr, filename);
reader.handle_greedy(*this); reader.handle_greedy(*this);
} }
} }
......
...@@ -66,7 +66,7 @@ void ImagesExportWindow::onOk(wxCommandEvent&) { ...@@ -66,7 +66,7 @@ void ImagesExportWindow::onOk(wxCommandEvent&) {
else if (sel == 2) gs.images_export_conflicts = CONFLICT_NUMBER; else if (sel == 2) gs.images_export_conflicts = CONFLICT_NUMBER;
else gs.images_export_conflicts = CONFLICT_NUMBER_OVERWRITE; else gs.images_export_conflicts = CONFLICT_NUMBER_OVERWRITE;
// Script // Script
ScriptP filename_script = parse(gs.images_export_filename, true); ScriptP filename_script = parse(gs.images_export_filename, nullptr, true);
// Select filename // Select filename
String name = wxFileSelector(_TITLE_("export images"),_(""), _LABEL_("filename is ignored"),_(""), String name = wxFileSelector(_TITLE_("export images"),_(""), _LABEL_("filename is ignored"),_(""),
_LABEL_("filename is ignored")+_("|*"), wxSAVE, this); _LABEL_("filename is ignored")+_("|*"), wxSAVE, this);
......
...@@ -35,7 +35,7 @@ DECLARE_POINTER_TYPE(PageLayout); ...@@ -35,7 +35,7 @@ DECLARE_POINTER_TYPE(PageLayout);
*/ */
class TextBufferDC : public wxMemoryDC { class TextBufferDC : public wxMemoryDC {
public: public:
TextBufferDC(int width, int height); TextBufferDC(int width, int height, bool buffer_text);
virtual void DoDrawText(const String& str, int x, int y); virtual void DoDrawText(const String& str, int x, int y);
virtual void DoDrawRotatedText(const String& str, int x, int y, double angle); virtual void DoDrawRotatedText(const String& str, int x, int y, double angle);
...@@ -62,24 +62,34 @@ class TextBufferDC : public wxMemoryDC { ...@@ -62,24 +62,34 @@ class TextBufferDC : public wxMemoryDC {
private: private:
vector<TextDrawP> text; vector<TextDrawP> text;
Bitmap buffer; Bitmap buffer;
bool buffer_text; ///< buffering text?
}; };
TextBufferDC::TextBufferDC(int width, int height) TextBufferDC::TextBufferDC(int width, int height, bool buffer_text)
: buffer(width, height, 32) : buffer(width, height, 32)
, buffer_text(buffer_text)
{ {
SelectObject(buffer); SelectObject(buffer);
// initialize to white // initialize to white
clearDC(*this,*wxWHITE_BRUSH); clearDC(*this,*wxWHITE_BRUSH);
} }
void TextBufferDC::DoDrawText(const String& str, int x, int y) { void TextBufferDC::DoDrawText(const String& str, int x, int y) {
double usx,usy; if (buffer_text) {
GetUserScale(&usx, &usy); double usx,usy;
text.push_back( new_intrusive7<TextDraw>(GetFont(), GetTextForeground(), usx, usy, x, y, str) ); GetUserScale(&usx, &usy);
text.push_back( new_intrusive7<TextDraw>(GetFont(), GetTextForeground(), usx, usy, x, y, str) );
} else {
wxMemoryDC::DoDrawText(str,x,y);
}
} }
void TextBufferDC::DoDrawRotatedText(const String& str, int x, int y, double angle) { void TextBufferDC::DoDrawRotatedText(const String& str, int x, int y, double angle) {
double usx,usy; if (buffer_text) {
GetUserScale(&usx, &usy); double usx,usy;
text.push_back( new_intrusive8<TextDraw>(GetFont(), GetTextForeground(), usx, usy, x, y, str, angle) ); GetUserScale(&usx, &usy);
text.push_back( new_intrusive8<TextDraw>(GetFont(), GetTextForeground(), usx, usy, x, y, str, angle) );
} else {
wxMemoryDC::DoDrawRotatedText(str,x,y,angle);
}
} }
DECLARE_TYPEOF_COLLECTION(TextBufferDC::TextDrawP); DECLARE_TYPEOF_COLLECTION(TextBufferDC::TextDrawP);
...@@ -219,13 +229,16 @@ void CardsPrintout::drawCard(DC& dc, const CardP& card, int card_nr) { ...@@ -219,13 +229,16 @@ void CardsPrintout::drawCard(DC& dc, const CardP& card, int card_nr) {
// create buffers // create buffers
int w = stylesheet.card_width, h = stylesheet.card_height; // in pixels int w = stylesheet.card_width, h = stylesheet.card_height; // in pixels
if (rotation == 90) swap(w,h); if (rotation == 90) swap(w,h);
TextBufferDC bufferDC(w,h); // Draw using text buffer
RotatedDC rdc(bufferDC, rotation, RealRect(0,0,w,h), 1.0, QUALITY_SUB_PIXEL); //TextBufferDC bufferDC(w,h,true);
//RotatedDC rdc(bufferDC, rotation, RealRect(0,0,w,h), 1.0, QUALITY_SUB_PIXEL);
TextBufferDC bufferDC(w*4,h*4,false);
RotatedDC rdc(bufferDC, rotation, RealRect(0,0,w*4,h*4), 4.0, QUALITY_AA);
// render card to dc // render card to dc
viewer.setCard(card); viewer.setCard(card);
viewer.draw(rdc, *wxWHITE); viewer.draw(rdc, *wxWHITE);
// render buffer to device // render buffer to device
double px_per_mm = stylesheet.card_dpi / 25.4; double px_per_mm = 4 * stylesheet.card_dpi / 25.4;
dc.SetUserScale(scale_x / px_per_mm, scale_y / px_per_mm); dc.SetUserScale(scale_x / px_per_mm, scale_y / px_per_mm);
dc.SetDeviceOrigin(scale_x * pos.x, scale_y * pos.y); dc.SetDeviceOrigin(scale_x * pos.x, scale_y * pos.y);
bufferDC.drawToDevice(dc, 0, 0); // adjust for scaling bufferDC.drawToDevice(dc, 0, 0); // adjust for scaling
......
...@@ -188,7 +188,7 @@ void CardsPanel::onUpdateUI(wxUpdateUIEvent& ev) { ...@@ -188,7 +188,7 @@ void CardsPanel::onUpdateUI(wxUpdateUIEvent& ev) {
ev.Enable(menu); ev.Enable(menu);
if (insertSymbolMenu->GetSubMenu() != menu || (menu && menu->GetParent() != menuFormat)) { if (insertSymbolMenu->GetSubMenu() != menu || (menu && menu->GetParent() != menuFormat)) {
// re-add the menu // re-add the menu
menuFormat->Remove(insertSymbolMenu); menuFormat->Remove(ID_INSERT_SYMBOL);
insertSymbolMenu->SetSubMenu(menu); insertSymbolMenu->SetSubMenu(menu);
menuFormat->Append(insertSymbolMenu); menuFormat->Append(insertSymbolMenu);
} }
......
...@@ -250,7 +250,7 @@ void KeywordsPanel::doPaste() { CUT_COPY_PASTE(doPaste, return (void), ! ...@@ -250,7 +250,7 @@ void KeywordsPanel::doPaste() { CUT_COPY_PASTE(doPaste, return (void), !
void KeywordsPanel::onChangeSet() { void KeywordsPanel::onChangeSet() {
list->setSet(set); list->setSet(set);
// warning label (depends on game name) // warning label (depends on game name)
fixedL->SetLabel(format_string(_LABEL_("standard keyword"), set->game->short_name)); fixedL->SetLabel(_LABEL_1_("standard keyword", set->game->short_name));
// init text controls // init text controls
keyword ->setSet(set); keyword ->setSet(set);
keyword ->getStyle().font.size = 16; keyword ->getStyle().font.size = 16;
......
...@@ -286,7 +286,7 @@ void SetWindow::updateTitle() { ...@@ -286,7 +286,7 @@ void SetWindow::updateTitle() {
if (identification.empty()) identification = set->name(); if (identification.empty()) identification = set->name();
if (identification.empty()) identification = _TITLE_("untitled"); if (identification.empty()) identification = _TITLE_("untitled");
set->short_name = identification; set->short_name = identification;
SetTitle(format_string(_TITLE_("%s - magic set editor"),identification)); SetTitle(_TITLE_1_("%s - magic set editor",identification));
} }
} }
...@@ -335,7 +335,7 @@ void SetWindow::onClose(wxCloseEvent& ev) { ...@@ -335,7 +335,7 @@ void SetWindow::onClose(wxCloseEvent& ev) {
bool SetWindow::askSaveAndContinue() { bool SetWindow::askSaveAndContinue() {
if (set->actions.atSavePoint()) return true; if (set->actions.atSavePoint()) return true;
// todo : if more then one window has the set selected it's ok to proceed // todo : if more then one window has the set selected it's ok to proceed
int save = wxMessageBox(format_string(_LABEL_("save changes"), set->short_name), _TITLE_("save changes"), wxYES_NO | wxCANCEL | wxICON_EXCLAMATION); int save = wxMessageBox(_LABEL_1_("save changes", set->short_name), _TITLE_("save changes"), wxYES_NO | wxCANCEL | wxICON_EXCLAMATION);
if (save == wxYES) { if (save == wxYES) {
// save the set // save the set
try { try {
......
...@@ -29,7 +29,7 @@ SymbolWindow::SymbolWindow(Window* parent) { ...@@ -29,7 +29,7 @@ SymbolWindow::SymbolWindow(Window* parent) {
SymbolWindow::SymbolWindow(Window* parent, const String& filename) { SymbolWindow::SymbolWindow(Window* parent, const String& filename) {
// open file // open file
Reader reader(new_shared1<wxFileInputStream>(filename), filename); Reader reader(new_shared1<wxFileInputStream>(filename), nullptr, filename);
SymbolP symbol; SymbolP symbol;
reader.handle_greedy(symbol); reader.handle_greedy(symbol);
init(parent, symbol); init(parent, symbol);
...@@ -204,7 +204,7 @@ void SymbolWindow::onFileOpen(wxCommandEvent& ev) { ...@@ -204,7 +204,7 @@ 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(new_shared1<wxFileInputStream>(name), name); Reader reader(new_shared1<wxFileInputStream>(name), nullptr, name);
reader.handle_greedy(symbol); reader.handle_greedy(symbol);
} else { } else {
wxBusyCursor busy; wxBusyCursor busy;
......
...@@ -297,8 +297,7 @@ void DropDownWordList::select(size_t item) { ...@@ -297,8 +297,7 @@ void DropDownWordList::select(size_t item) {
tve.selection_start_i = pos->start; tve.selection_start_i = pos->start;
tve.selection_end_i = pos->end; tve.selection_end_i = pos->end;
tve.fixSelection(TYPE_INDEX); tve.fixSelection(TYPE_INDEX);
tve.replaceSelection(escape(new_value), tve.replaceSelection(escape(new_value), _ACTION_1_("change", tve.field().name));
format_string(_ACTION_("change"), tve.field().name));
// stay open? // stay open?
if (IsShown()) selection(); // update 'enabled' if (IsShown()) selection(); // update 'enabled'
} }
......
...@@ -102,9 +102,10 @@ int MSE::OnRun() { ...@@ -102,9 +102,10 @@ int MSE::OnRun() {
InstallType type = settings.install_type; InstallType type = settings.install_type;
if (argc > 2) { if (argc > 2) {
String arg = argv[2]; String arg = argv[2];
if (arg.Mid(0,2) == _("--")) if (starts_with(argv[2], _("--"))) {
parse_enum(arg.Mid(2), type); parse_enum(String(argv[2]).substr(2), type);
} }
}
Installer::installFrom(argv[1], true, isInstallLocal(type)); Installer::installFrom(argv[1], true, isInstallLocal(type));
return EXIT_SUCCESS; return EXIT_SUCCESS;
} else if (arg == _("--symbol-editor")) { } else if (arg == _("--symbol-editor")) {
......
# This file contains the keys expected to be in MSE locales # This file contains the keys expected to be in MSE locales
# It was automatically generated by tools/locale/locale.pl # It was automatically generated by tools/locale/locale.pl
# Generated on Fri Sep 21 14:19:24 2007 # Generated on Mon Sep 24 22:07:59 2007
action: action:
add control point: 0 add control point: 0
...@@ -82,9 +82,11 @@ error: ...@@ -82,9 +82,11 @@ error:
checking updates: 0 checking updates: 0
checking updates failed: 0 checking updates failed: 0
coordinates for blending overlap: 0 coordinates for blending overlap: 0
dependency not given: 4
dimension not found: 1 dimension not found: 1
expected key: 1 expected key: 1
file not found: 2 file not found: 2
file not found package like: 2
file parse error: 2 file parse error: 2
has no member: 2 has no member: 2
has no member value: 2 has no member value: 2
...@@ -99,7 +101,9 @@ error: ...@@ -99,7 +101,9 @@ error:
no updates: 0 no updates: 0
package not found: 1 package not found: 1
package out of date: 3 package out of date: 3
package too new: 4
stylesheet and set refer to different game: 0 stylesheet and set refer to different game: 0
successful install: optional, 2
unable to open output file: 0 unable to open output file: 0
unable to store file: 0 unable to store file: 0
unrecognized value: 1 unrecognized value: 1
......
...@@ -57,7 +57,7 @@ enum OpenBrace ...@@ -57,7 +57,7 @@ enum OpenBrace
/** Also stores errors found when tokenizing or parsing */ /** Also stores errors found when tokenizing or parsing */
class TokenIterator { class TokenIterator {
public: public:
TokenIterator(const String& str, bool string_mode, vector<ScriptParseError>& errors); TokenIterator(const String& str, Packaged* package, bool string_mode, vector<ScriptParseError>& errors);
/// Peek at the next token, doesn't move to the one after that /// Peek at the next token, doesn't move to the one after that
/** Can peek further forward by using higher values of offset. /** Can peek further forward by using higher values of offset.
...@@ -75,6 +75,7 @@ class TokenIterator { ...@@ -75,6 +75,7 @@ class TokenIterator {
String input; String input;
size_t pos; size_t pos;
String filename; ///< Filename of include files, "" for the main input String filename; ///< Filename of include files, "" for the main input
Packaged* package; ///< Package the input is from
vector<Token> buffer; ///< buffer of unread tokens, front() = current vector<Token> buffer; ///< buffer of unread tokens, front() = current
stack<OpenBrace> open_braces; ///< braces/quotes we entered from script mode stack<OpenBrace> open_braces; ///< braces/quotes we entered from script mode
bool newline; ///< Did we just pass a newline? bool newline; ///< Did we just pass a newline?
...@@ -83,6 +84,7 @@ class TokenIterator { ...@@ -83,6 +84,7 @@ class TokenIterator {
String input; String input;
size_t pos; size_t pos;
String filename; String filename;
Package* package;
}; };
stack<MoreInput> more; ///< Read tokens from here when we are done with the current input stack<MoreInput> more; ///< Read tokens from here when we are done with the current input
...@@ -115,9 +117,10 @@ bool isLongOper(const String& s) { return s==_(":=") || s==_("==") || s==_("!=") ...@@ -115,9 +117,10 @@ bool isLongOper(const String& s) { return s==_(":=") || s==_("==") || s==_("!=")
// ----------------------------------------------------------------------------- : Tokenizing // ----------------------------------------------------------------------------- : Tokenizing
TokenIterator::TokenIterator(const String& str, bool string_mode, vector<ScriptParseError>& errors) TokenIterator::TokenIterator(const String& str, Packaged* package, bool string_mode, vector<ScriptParseError>& errors)
: input(str) : input(str)
, pos(0) , pos(0)
, package(package)
, newline(false) , newline(false)
, errors(errors) , errors(errors)
{ {
...@@ -183,12 +186,12 @@ void TokenIterator::readToken() { ...@@ -183,12 +186,12 @@ void TokenIterator::readToken() {
if (eol == String::npos) eol = input.size(); if (eol == String::npos) eol = input.size();
String include_file = trim(input.substr(pos, eol - pos)); String include_file = trim(input.substr(pos, eol - pos));
// store the current input for later retrieval // store the current input for later retrieval
MoreInput m = {input, eol, filename}; MoreInput m = {input, eol, filename, package};
more.push(m); more.push(m);
// 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 = packages.openFileFromPackage(include_file); InputStreamP is = packages.openFileFromPackage(package, include_file);
input = read_utf8_line(*is, true, true); input = read_utf8_line(*is, true, true);
} else if (isAlpha(c) || c == _('_')) { } else if (isAlpha(c) || c == _('_')) {
// name // name
...@@ -345,10 +348,10 @@ void parseExpr(TokenIterator& input, Script& script, Precedence min_prec); ...@@ -345,10 +348,10 @@ void parseExpr(TokenIterator& input, Script& script, Precedence min_prec);
void parseOper(TokenIterator& input, Script& script, Precedence min_prec, InstructionType close_with = I_NOP, int close_with_data = 0); void parseOper(TokenIterator& input, Script& script, Precedence min_prec, InstructionType close_with = I_NOP, int close_with_data = 0);
ScriptP parse(const String& s, bool string_mode, vector<ScriptParseError>& errors_out) { ScriptP parse(const String& s, Packaged* package, bool string_mode, vector<ScriptParseError>& errors_out) {
errors_out.clear(); errors_out.clear();
// parse // parse
TokenIterator input(s, string_mode, errors_out); TokenIterator input(s, package, string_mode, errors_out);
ScriptP script(new Script); ScriptP script(new Script);
parseOper(input, *script, PREC_ALL, I_RET); parseOper(input, *script, PREC_ALL, I_RET);
Token eof = input.read(); Token eof = input.read();
...@@ -363,9 +366,9 @@ ScriptP parse(const String& s, bool string_mode, vector<ScriptParseError>& error ...@@ -363,9 +366,9 @@ ScriptP parse(const String& s, bool string_mode, vector<ScriptParseError>& error
} }
} }
ScriptP parse(const String& s, bool string_mode) { ScriptP parse(const String& s, Packaged* package, bool string_mode) {
vector<ScriptParseError> errors; vector<ScriptParseError> errors;
ScriptP script = parse(s, string_mode, errors); ScriptP script = parse(s, package, string_mode, errors);
if (!errors.empty()) { if (!errors.empty()) {
throw ScriptParseErrors(errors); throw ScriptParseErrors(errors);
} }
......
...@@ -13,6 +13,8 @@ ...@@ -13,6 +13,8 @@
#include <util/error.hpp> #include <util/error.hpp>
#include <script/script.hpp> #include <script/script.hpp>
class Packaged;
// ----------------------------------------------------------------------------- : Parser // ----------------------------------------------------------------------------- : Parser
/// Parse a String to a Script /// Parse a String to a Script
...@@ -21,8 +23,10 @@ ...@@ -21,8 +23,10 @@
* *
* Errors are stored in the output vector. * Errors are stored in the output vector.
* If there are errors, the result is a null pointer * If there are errors, the result is a null pointer
*
* The package is for loading included files, it may be null
*/ */
ScriptP parse(const String& s, bool string_mode, vector<ScriptParseError>& errors_out); ScriptP parse(const String& s, Packaged* package, bool string_mode, vector<ScriptParseError>& errors_out);
/// Parse a String to a Script /// Parse a String to a Script
/** If string_mode then s is interpreted as a string, /** If string_mode then s is interpreted as a string,
...@@ -30,7 +34,7 @@ ScriptP parse(const String& s, bool string_mode, vector<ScriptParseError>& error ...@@ -30,7 +34,7 @@ ScriptP parse(const String& s, bool string_mode, vector<ScriptParseError>& error
* *
* If an error is encountered, an exception is thrown. * If an error is encountered, an exception is thrown.
*/ */
ScriptP parse(const String& s, bool string_mode = false); ScriptP parse(const String& s, Packaged* package = nullptr, bool string_mode = false);
// ----------------------------------------------------------------------------- : EOF // ----------------------------------------------------------------------------- : EOF
#endif #endif
...@@ -46,7 +46,7 @@ ScriptValueP OptionalScript::invoke(Context& ctx, bool open_scope) const { ...@@ -46,7 +46,7 @@ ScriptValueP OptionalScript::invoke(Context& ctx, bool open_scope) const {
void OptionalScript::parse(Reader& reader, bool string_mode) { void OptionalScript::parse(Reader& reader, bool string_mode) {
vector<ScriptParseError> errors; vector<ScriptParseError> errors;
script = ::parse(unparsed, string_mode, errors); script = ::parse(unparsed, reader.getPackage(), string_mode, errors);
// show parse errors as warnings // show parse errors as warnings
String include_warnings; String include_warnings;
for (size_t i = 0 ; i < errors.size() ; ++i) { for (size_t i = 0 ; i < errors.size() ; ++i) {
...@@ -104,7 +104,7 @@ const String& StringScript::get() const { ...@@ -104,7 +104,7 @@ const String& StringScript::get() const {
void StringScript::set(const String& s) { void StringScript::set(const String& s) {
unparsed = s; unparsed = s;
script = ::parse(unparsed, true); script = ::parse(unparsed, nullptr, true);
} }
template <> void Reader::handle(StringScript& os) { template <> void Reader::handle(StringScript& os) {
......
...@@ -112,7 +112,7 @@ class ScriptCollection : public ScriptValue { ...@@ -112,7 +112,7 @@ class ScriptCollection : public ScriptValue {
public: public:
inline ScriptCollection(const Collection* v) : value(v) {} inline ScriptCollection(const Collection* v) : value(v) {}
virtual ScriptType type() const { return SCRIPT_COLLECTION; } virtual ScriptType type() const { return SCRIPT_COLLECTION; }
virtual String typeName() const { return format_string(_TYPE_("collection of"), type_name(*value->begin())); } virtual String typeName() const { return _TYPE_1_("collection of", type_name(*value->begin())); }
virtual ScriptValueP getMember(const String& name) const { virtual ScriptValueP getMember(const String& name) const {
long index; long index;
if (name.ToLong(&index) && index >= 0 && (size_t)index < value->size()) { if (name.ToLong(&index) && index >= 0 && (size_t)index < value->size()) {
...@@ -160,7 +160,7 @@ class ScriptMap : public ScriptValue { ...@@ -160,7 +160,7 @@ class ScriptMap : public ScriptValue {
public: public:
inline ScriptMap(const Collection* v) : value(v) {} inline ScriptMap(const Collection* v) : value(v) {}
virtual ScriptType type() const { return SCRIPT_COLLECTION; } virtual ScriptType type() const { return SCRIPT_COLLECTION; }
virtual String typeName() const { return format_string(_TYPE_("collection of"), type_name(value->begin())); } virtual String typeName() const { return _TYPE_1_("collection of", type_name(value->begin())); }
virtual ScriptValueP getMember(const String& name) const { virtual ScriptValueP getMember(const String& name) const {
return get_member(*value, name); return get_member(*value, name);
} }
......
...@@ -25,7 +25,7 @@ IndexMap<Key,Value>& DelayedIndexMaps<Key,Value>::get(const String& name, const ...@@ -25,7 +25,7 @@ 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(new_shared1<wxStringInputStream>(item->unread_data), _("delayed data for ") + name); Reader reader(new_shared1<wxStringInputStream>(item->unread_data), 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();
} }
......
...@@ -178,10 +178,15 @@ class BufferedFileInputStream : private BufferedFileInputStream_aux, public wxBu ...@@ -178,10 +178,15 @@ class BufferedFileInputStream : private BufferedFileInputStream_aux, public wxBu
InputStreamP Package::openIn(const String& file) { InputStreamP 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
return packages.openFileFromPackage(file); Packaged* p = dynamic_cast<Packaged*>(this);
return packages.openFileFromPackage(p, file);
} }
FileInfos::iterator it = files.find(toStandardName(file)); FileInfos::iterator it = files.find(toStandardName(file));
if (it == files.end()) { if (it == files.end()) {
// does it look like a relative filename?
if (filename.find(_(".mse-")) != String::npos) {
throw PackageError(_ERROR_2_("file not found package like", file, filename));
}
throw FileNotFoundError(file, filename); throw FileNotFoundError(file, filename);
} }
InputStreamP stream; InputStreamP stream;
...@@ -442,6 +447,7 @@ IMPLEMENT_REFLECTION(Packaged) { ...@@ -442,6 +447,7 @@ IMPLEMENT_REFLECTION(Packaged) {
REFLECT_N("icon", icon_filename); REFLECT_N("icon", icon_filename);
REFLECT_NO_SCRIPT(position_hint); REFLECT_NO_SCRIPT(position_hint);
REFLECT(version); REFLECT(version);
REFLECT(compatible_version);
REFLECT_NO_SCRIPT_N("depends ons", dependencies); // hack for singular_form REFLECT_NO_SCRIPT_N("depends ons", dependencies); // hack for singular_form
} }
...@@ -472,7 +478,7 @@ void Packaged::open(const String& package, bool just_header) { ...@@ -472,7 +478,7 @@ void Packaged::open(const String& package, bool just_header) {
fully_loaded = false; fully_loaded = false;
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()), absoluteFilename() + _("/") + typeName(), true); Reader reader(openIn(typeName()), this, absoluteFilename() + _("/") + typeName(), true);
try { try {
JustAsPackageProxy proxy(this); JustAsPackageProxy proxy(this);
reader.handle_greedy(proxy); reader.handle_greedy(proxy);
...@@ -487,7 +493,7 @@ void Packaged::open(const String& package, bool just_header) { ...@@ -487,7 +493,7 @@ void Packaged::open(const String& package, bool just_header) {
void Packaged::loadFully() { void Packaged::loadFully() {
if (fully_loaded) return; if (fully_loaded) return;
fully_loaded = true; fully_loaded = true;
Reader reader(openIn(typeName()), absoluteFilename() + _("/") + typeName()); Reader reader(openIn(typeName()), this, absoluteFilename() + _("/") + typeName());
try { try {
reader.handle_greedy(*this); reader.handle_greedy(*this);
validate(reader.file_app_version); validate(reader.file_app_version);
...@@ -518,6 +524,24 @@ void Packaged::validate(Version) { ...@@ -518,6 +524,24 @@ void Packaged::validate(Version) {
} }
} }
void Packaged::requireDependency(Packaged* package) {
if (package == this) return; // dependency on self
String n = package->relativeFilename();
FOR_EACH(dep, dependencies) {
if (dep->package == n) {
if (package->version < dep->version) {
handle_warning(_ERROR_3_("package out of date", n, package->version.toString(), dep->version.toString()), false);
} else if (package->compatible_version > dep->version) {
handle_warning(_ERROR_4_("package too new", n, package->version.toString(), dep->version.toString(), relativeFilename()), false);
} else {
return; // ok
}
}
}
// dependency not found
handle_warning(_ERROR_4_("dependency not given", name(), package->relativeFilename(), package->relativeFilename(), package->version.toString()), false);
}
// ----------------------------------------------------------------------------- : IncludePackage // ----------------------------------------------------------------------------- : IncludePackage
String IncludePackage::typeName() const { return _("include"); } String IncludePackage::typeName() const { return _("include"); }
......
...@@ -117,7 +117,7 @@ class Package : public IntrusivePtrVirtualBase { ...@@ -117,7 +117,7 @@ class Package : public IntrusivePtrVirtualBase {
template <typename T> template <typename T>
void readFile(const String& file, T& obj) { void readFile(const String& file, T& obj) {
Reader reader(openIn(file), absoluteFilename() + _("/") + file); Reader reader(openIn(file), dynamic_cast<Packaged*>(this), absoluteFilename() + _("/") + file);
try { try {
reader.handle_greedy(obj); reader.handle_greedy(obj);
} catch (const ParseError& err) { } catch (const ParseError& err) {
...@@ -196,12 +196,13 @@ class Packaged : public Package { ...@@ -196,12 +196,13 @@ class Packaged : public Package {
Packaged(); Packaged();
virtual ~Packaged() {} virtual ~Packaged() {}
Version version; ///< Version number of this package Version version; ///< Version number of this package
String short_name; ///< Short name of this package Version compatible_version; ///< Earliest version number this package is compatible with
String full_name; ///< Name of this package, for menus etc. String short_name; ///< Short name of this package
String icon_filename; ///< Filename of icon to use in package lists String full_name; ///< Name of this package, for menus etc.
String icon_filename; ///< Filename of icon to use in package lists
vector<PackageDependencyP> dependencies; ///< Dependencies of this package vector<PackageDependencyP> dependencies; ///< Dependencies of this 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(); InputStreamP openIconFile();
...@@ -215,6 +216,10 @@ class Packaged : public Package { ...@@ -215,6 +216,10 @@ class Packaged : public Package {
void save(); void save();
void saveAs(const String& package, bool remove_unused = true); void saveAs(const String& package, bool remove_unused = true);
/// Check if this package lists a dependency on the given package
/** This is done to force people to fill in the dependencies */
void requireDependency(Packaged* package);
protected: protected:
/// filename of the data file, and extension of the package file /// filename of the data file, and extension of the package file
virtual String typeName() const = 0; virtual String typeName() const = 0;
......
...@@ -101,17 +101,24 @@ void PackageManager::findMatching(const String& pattern, vector<PackagedP>& out) ...@@ -101,17 +101,24 @@ void PackageManager::findMatching(const String& pattern, vector<PackagedP>& out)
} }
} }
InputStreamP PackageManager::openFileFromPackage(const String& name) { InputStreamP PackageManager::openFileFromPackage(Packaged*& package, const String& name) {
// we don't want an absolute path (for security reasons) if (!name.empty() && name.GetChar(0) == _('/')) {
String n; // absolute name; break name
if (!name.empty() && name.GetChar(0) == _('/')) n = name.substr(1); size_t pos = name.find_first_of(_("/\\"), 1);
else n = name; if (pos != String::npos) {
// break // open package
size_t pos = n.find_first_of(_("/\\")); PackagedP p = openAny(name.substr(1, pos-1));
if (pos == String::npos) throw FileNotFoundError(n, _("No package name specified, use 'package/filename'")); if (package) {
// open package and file package->requireDependency(p.get());
PackagedP p = openAny(n.substr(0, pos)); }
return p->openIn(n.substr(pos+1)); package = p.get();
return p->openIn(name.substr(pos + 1));
}
} else if (package) {
// relative name
return package->openIn(name);
}
throw FileNotFoundError(name, _("No package name specified, use '/package/filename'"));
} }
bool PackageManager::checkDependency(const PackageDependency& dep, bool report_errors) { bool PackageManager::checkDependency(const PackageDependency& dep, bool report_errors) {
......
...@@ -66,12 +66,18 @@ class PackageManager { ...@@ -66,12 +66,18 @@ class PackageManager {
/** Only reads the package headers */ /** Only reads the package headers */
void findMatching(const String& pattern, vector<PackagedP>& out); void findMatching(const String& pattern, vector<PackagedP>& out);
/// Open a file from a package, with a name encoded as "package/file" /// Open a file from a package, with a name encoded as "/package/file"
InputStreamP openFileFromPackage(const String& name); /** If 'package' is set then:
* - tries to open a relative file from the package if the name is "file"
* - verifies a dependency from that package if an absolute filename is used
* this is to force people to fill in the dependencies
* Afterwards, package will be set to the package the file is opened from
*/
InputStreamP openFileFromPackage(Packaged*& package, const String& name);
/// Check if the given dependency is currently installed /// Check if the given dependency is currently installed
bool checkDependency(const PackageDependency& dep, bool report_errors = false); bool checkDependency(const PackageDependency& dep, bool report_errors = true);
inline String getGlobalDataDir() const { return global_data_directory; } inline String getGlobalDataDir() const { return global_data_directory; }
inline String getLocalDataDir() const { return local_data_directory; } inline String getLocalDataDir() const { return local_data_directory; }
......
...@@ -14,9 +14,9 @@ ...@@ -14,9 +14,9 @@
// ----------------------------------------------------------------------------- : Reader // ----------------------------------------------------------------------------- : Reader
Reader::Reader(const InputStreamP& input, const String& filename, bool ignore_invalid) Reader::Reader(const InputStreamP& input, Packaged* package, const String& filename, bool ignore_invalid)
: indent(0), expected_indent(0), state(OUTSIDE) : indent(0), expected_indent(0), state(OUTSIDE)
, filename(filename), line_number(0), previous_line_number(0) , package(package), filename(filename), line_number(0), previous_line_number(0)
, ignore_invalid(ignore_invalid) , ignore_invalid(ignore_invalid)
, input(input) , input(input)
{ {
...@@ -24,12 +24,12 @@ Reader::Reader(const InputStreamP& input, const String& filename, bool ignore_in ...@@ -24,12 +24,12 @@ Reader::Reader(const InputStreamP& input, const String& filename, bool ignore_in
handleAppVersion(); handleAppVersion();
} }
Reader::Reader(const String& filename) Reader::Reader(Packaged* pkg, const String& filename)
: indent(0), expected_indent(0), state(OUTSIDE) : indent(0), expected_indent(0), state(OUTSIDE)
, filename(filename), line_number(0), previous_line_number(0) , package(pkg), filename(filename), line_number(0), previous_line_number(0)
, ignore_invalid(false) , ignore_invalid(false)
, input(packages.openFileFromPackage(filename))
{ {
input = packages.openFileFromPackage(package, filename);
moveNext(); moveNext();
handleAppVersion(); handleAppVersion();
} }
......
...@@ -16,6 +16,7 @@ template <typename T> class Defaultable; ...@@ -16,6 +16,7 @@ template <typename T> class Defaultable;
template <typename T> class Scriptable; template <typename T> class Scriptable;
DECLARE_POINTER_TYPE(Game); DECLARE_POINTER_TYPE(Game);
DECLARE_POINTER_TYPE(StyleSheet); DECLARE_POINTER_TYPE(StyleSheet);
class Packaged;
// ----------------------------------------------------------------------------- : Reader // ----------------------------------------------------------------------------- : Reader
...@@ -35,11 +36,13 @@ class Reader { ...@@ -35,11 +36,13 @@ class Reader {
/// 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, const String& filename = wxEmptyString, bool ignore_invalid = false); Reader(const InputStreamP& input, Packaged* package = nullptr, const String& filename = wxEmptyString, bool ignore_invalid = false);
/// Construct a reader that reads a file in a package /// Construct a reader that reads a file in a package
/** Used for "include file" keys. */ /** Used for "include file" keys.
Reader(const String& filename); * package can be nullptr
*/
Reader(Packaged* package, const String& filename);
~Reader() { showWarnings(); } ~Reader() { showWarnings(); }
...@@ -108,6 +111,9 @@ class Reader { ...@@ -108,6 +111,9 @@ class Reader {
/// Indicate that the last value from getValue() was not handled, allowing it to be handled again /// Indicate that the last value from getValue() was not handled, allowing it to be handled again
void unhandle(); void unhandle();
/// The package being read from
inline Packaged* getPackage() const { return package; }
// --------------------------------------------------- : Data // --------------------------------------------------- : Data
/// App version this file was made with /// App version this file was made with
Version file_app_version; Version file_app_version;
...@@ -141,6 +147,8 @@ class Reader { ...@@ -141,6 +147,8 @@ class Reader {
/// Filename for error messages /// Filename for error messages
String filename; String filename;
/// Package this file is from, if any
Packaged* package;
/// Line number of the current line for error messages /// Line number of the current line for error messages
int line_number; int line_number;
/// Line number of the previous_line /// Line number of the previous_line
...@@ -172,7 +180,7 @@ class Reader { ...@@ -172,7 +180,7 @@ 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(value); Reader reader(package, value);
reader.handle_greedy(v); reader.handle_greedy(v);
moveNext(); moveNext();
} else { } else {
......
...@@ -98,12 +98,23 @@ String tr(const SymbolFont&, const String& key, const String& def); ...@@ -98,12 +98,23 @@ String tr(const SymbolFont&, const String& key, const String& def);
/// A localized string for button text, with 1 argument (printf style) /// A localized string for button text, with 1 argument (printf style)
#define _BUTTON_1_(s,a) format_string(_BUTTON_(s), a) #define _BUTTON_1_(s,a) format_string(_BUTTON_(s), a)
/// A localized string for window titles, with 1 argument (printf style)
#define _TITLE_1_(s,a) format_string(_TITLE_(s), a)
/// A localized string for type names in scripts, with 1 argument (printf style)
#define _TYPE_1_(s,a) format_string(_TYPE_(s), a)
/// A localized string for action names, with 1 argument (printf style)
#define _ACTION_1_(s,a) format_string(_ACTION_(s), a)
/// A localized string for error messages, with 1 argument (printf style) /// A localized string for error messages, with 1 argument (printf style)
#define _ERROR_1_(s,a) format_string(_ERROR_(s), a) #define _ERROR_1_(s,a) format_string(_ERROR_(s), a)
/// A localized string for error messages, with 2 argument (printf style) /// A localized string for error messages, with 2 argument (printf style)
#define _ERROR_2_(s,a,b) format_string(_ERROR_(s), a, b) #define _ERROR_2_(s,a,b) format_string(_ERROR_(s), a, b)
/// A localized string for error messages, with 3 argument (printf style) /// A localized string for error messages, with 3 argument (printf style)
#define _ERROR_3_(s,a,b,c) format_string(_ERROR_(s), a, b, c) #define _ERROR_3_(s,a,b,c) format_string(_ERROR_(s), a, b, c)
/// A localized string for error messages, with 4 argument (printf style)
#define _ERROR_4_(s,a,b,c,d) format_string(_ERROR_(s), a, b, c, d)
/// Format a string /// Format a string
/** Equivalent to sprintf / String::Format, but allows strings to be passed as arguments (gcc) /** Equivalent to sprintf / String::Format, but allows strings to be passed as arguments (gcc)
...@@ -124,6 +135,9 @@ inline String format_string(const String& format, const String& a0, const String ...@@ -124,6 +135,9 @@ inline String format_string(const String& format, const String& a0, const String
inline String format_string(const String& format, const String& a0, const String& a1, const String& a2) { inline String format_string(const String& format, const String& a0, const String& a1, const String& a2) {
return String::Format(format, a0.c_str(), a1.c_str(), a2.c_str()); return String::Format(format, a0.c_str(), a1.c_str(), a2.c_str());
} }
inline String format_string(const String& format, const String& a0, const String& a1, const String& a2, const String& a3) {
return String::Format(format, a0.c_str(), a1.c_str(), a2.c_str(), a3.c_str());
}
// ----------------------------------------------------------------------------- : EOF // ----------------------------------------------------------------------------- : EOF
#endif #endif
...@@ -17,10 +17,12 @@ $built_in_functions = array( ...@@ -17,10 +17,12 @@ $built_in_functions = array(
'sort_text' =>'', 'sort_rule' => 'sort_text', 'sort_text' =>'', 'sort_rule' => 'sort_text',
'contains' =>'', 'contains' =>'',
'match' =>'', 'match_rule' => 'match', 'match' =>'', 'match_rule' => 'match',
'trim' =>'',
'regex_escape' =>'', 'regex_escape' =>'',
// tags // tags
'tag_contents' =>'', 'tag_contents_rule'=>'tag_contents', 'tag_contents' =>'', 'tag_contents_rule'=>'tag_contents',
'remove_tag' =>'', 'tag_remove_rule' =>'remove_tag', 'remove_tag' =>'', 'tag_remove_rule' =>'remove_tag',
'remove_tags' =>'',
// lists // lists
'postion' =>'', 'postion' =>'',
'length' =>'', 'length' =>'',
...@@ -39,8 +41,8 @@ $built_in_functions = array( ...@@ -39,8 +41,8 @@ $built_in_functions = array(
'english_singular' =>'english_plural', 'english_singular' =>'english_plural',
'process_english_hints' =>'', 'process_english_hints' =>'',
// fields and values // fields and values
'forward_editor' =>'', 'forward_editor' =>'combined_editor',
'combined_editor' =>'combined_editor', 'combined_editor' =>'',
'primary_choice' =>'', 'primary_choice' =>'',
'chosen' =>'', 'chosen' =>'',
'require_choice' =>'', 'require_choice' =>'',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment