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:
You should leave a bug report on http://magicseteditor.sourceforge.net/
# 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:
Error while parsing file: '%s'
%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 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 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
has no member: %s has no member '%s'
......
......@@ -15,7 +15,7 @@ card dpi: 150
init script:
# 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?
mask_hybrid_with_land := { styling.grey_hybrid_name }
......
......@@ -33,7 +33,7 @@ card dpi: 150
init script:
# 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
land_template := { "c{type}.jpg" }
......@@ -305,7 +305,7 @@ card style:
z index: 1
render style: image
alignment: middle center
include file: magic-watermarks.mse-include/watermarks
include file: /magic-watermarks.mse-include/watermarks
text 2:
left: 33
top : 65
......@@ -348,7 +348,7 @@ card style:
render style: image
alignment: middle center
angle: 180
include file: magic-watermarks.mse-include/watermarks
include file: /magic-watermarks.mse-include/watermarks
############################# PT
power:
......
......@@ -279,7 +279,7 @@ card style:
z index: 1
render style: image
alignment: middle center
include file: magic-watermarks.mse-include/watermarks
include file: /magic-watermarks.mse-include/watermarks
############################# PT
power:
......
......@@ -250,7 +250,7 @@ card style:
z index: 1
render style: image
alignment: middle center
include file: magic-watermarks.mse-include/watermarks
include file: /magic-watermarks.mse-include/watermarks
############################# PT
power:
......
......@@ -378,7 +378,7 @@ card style:
z index: 1
render style: image
alignment: middle center
include file: magic-watermarks.mse-include/watermarks
include file: /magic-watermarks.mse-include/watermarks
watermark 2:
left: 349.45
top : 240
......@@ -387,7 +387,7 @@ card style:
z index: 1
render style: image
alignment: middle center
include file: magic-watermarks.mse-include/watermarks
include file: /magic-watermarks.mse-include/watermarks
############################# PT
power:
......
......@@ -263,7 +263,7 @@ card style:
render style: image
alignment: middle center
visible: { card.rule_text != "" and card.flavor_text != "" }
include file: magic-watermarks.mse-include/watermarks
include file: /magic-watermarks.mse-include/watermarks
############################# PT
power:
......
......@@ -253,7 +253,7 @@ card style:
width: { 300 - max(18,card_style.rarity.content_width) }
height: 28
alignment: middle shrink-overflow
z index: 1
z index: 2
padding top: 2
font:
name: Matrix
......
......@@ -398,7 +398,7 @@ card style:
z index: 2
render style: image
alignment: middle center
include file: magic-watermarks.mse-include/watermarks
include file: /magic-watermarks.mse-include/watermarks
############################# PT
pt:
......
......@@ -18,7 +18,7 @@ card dpi: 150
init script:
# 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?
mask_hybrid_with_land := { false }
......@@ -332,7 +332,7 @@ card style:
z index: 1
render style: image
alignment: middle center
include file: magic-watermarks.mse-include/watermarks
include file: /magic-watermarks.mse-include/watermarks
watermark 2:
left: 151
top : 378
......@@ -342,7 +342,7 @@ card style:
z index: 1
render style: image
alignment: middle center
include file: magic-watermarks.mse-include/watermarks
include file: /magic-watermarks.mse-include/watermarks
############################# PT
pt:
......
......@@ -18,7 +18,7 @@ card dpi: 150
init script:
# 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?
mask_hybrid_with_land := { styling.grey_hybrid_name }
......@@ -270,7 +270,7 @@ card style:
z index: 1
render style: image
alignment: middle center
include file: magic-watermarks.mse-include/watermarks
include file: /magic-watermarks.mse-include/watermarks
############################# Loyalty
loyalty:
......
......@@ -14,7 +14,7 @@ card dpi: 150
init script:
# 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?
mask_hybrid_with_land := { styling.grey_hybrid_name }
......@@ -229,7 +229,7 @@ card style:
z index: 1
render style: image
alignment: middle center
include file: magic-watermarks.mse-include/watermarks
include file: /magic-watermarks.mse-include/watermarks
############################# PT
pt:
......
......@@ -17,7 +17,7 @@ card dpi: 150
init script:
# 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?
mask_hybrid_with_land := { styling.grey_hybrid_name }
......@@ -365,7 +365,7 @@ card style:
z index: 1
render style: image
alignment: middle center
include file: magic-watermarks.mse-include/watermarks
include file: /magic-watermarks.mse-include/watermarks
watermark 2:
left: 338
top : 228
......@@ -374,7 +374,7 @@ card style:
z index: 1
render style: image
alignment: middle center
include file: magic-watermarks.mse-include/watermarks
include file: /magic-watermarks.mse-include/watermarks
############################# PT
pt:
......
......@@ -17,7 +17,7 @@ card dpi: 150
init script:
# 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?
text_shape := {
......
......@@ -21,7 +21,7 @@ card dpi: 150
init script:
# 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?
mask_hybrid_with_land := { styling.grey_hybrid_name }
......@@ -224,7 +224,7 @@ card style:
type:
left: 35
top : 299
top : 298
width: { 308 - max(22,card_style.rarity.content_width) }
height: 20
alignment: top shrink-overflow
......@@ -305,7 +305,7 @@ card style:
z index: 1
render style: image
alignment: middle center
include file: magic-watermarks.mse-include/watermarks
include file: /magic-watermarks.mse-include/watermarks
############################# PT
pt:
......
......@@ -426,7 +426,7 @@ card style:
z index: 1
render style: image
alignment: middle center
include file: magic-watermarks.mse-include/watermarks
include file: /magic-watermarks.mse-include/watermarks
watermark 2:
left: 338
top : 228
......@@ -435,7 +435,7 @@ card style:
z index: 1
render style: image
alignment: middle center
include file: magic-watermarks.mse-include/watermarks
include file: /magic-watermarks.mse-include/watermarks
############################# PT
pt:
......
......@@ -315,7 +315,7 @@ card style:
z index: 1
render style: image
alignment: middle center
include file: magic-watermarks.mse-include/watermarks
include file: /magic-watermarks.mse-include/watermarks
############################# PT
pt:
......
......@@ -266,7 +266,7 @@ card style:
z index: 1
render style: image
alignment: middle center
include file: magic-watermarks.mse-include/watermarks
include file: /magic-watermarks.mse-include/watermarks
############################# PT
pt:
......
......@@ -173,10 +173,10 @@ init script:
# The code consists of 4 parts:
# normal/token, color, shifted, split
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() +
(if contains(card.shape, match:"shifted") then "S" else "N") + # 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:"shifted") then "S" else " ") + # planeshifted 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" }
......@@ -221,7 +221,7 @@ init script:
}
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 := {
if set.sort_special_rarity != "separate numbering" then nil
......@@ -825,7 +825,7 @@ card field:
name: watermark
icon: stats/watermark.png
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
############################# Loyalty
......@@ -1052,7 +1052,7 @@ card field:
card field:
type: choice
name: watermark 2
include file: magic-watermarks.mse-include/watermark-names
include file: /magic-watermarks.mse-include/watermark-names
icon: stats/watermark.png
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
......
......@@ -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:
>>>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.
......
......@@ -15,7 +15,7 @@ If @alpha@ is 1 the image stays the same, if @alpha@ is 0 the image becomes comp
--Examples--
> 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--
| [[fun:set_mask]] Set the transparancy mask of an image.
......@@ -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.
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() {
String new_value = untag(value);
// Try to parse the script
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()) {
// parsed okay, assign
errors.clear();
......
......@@ -356,7 +356,7 @@ AddSymbolPartAction::AddSymbolPartAction(Symbol& symbol, const SymbolPartP& part
{}
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) {
......@@ -395,7 +395,7 @@ void RemoveSymbolPartsAction::check(SymbolGroup& group, const set<SymbolPartP>&
}
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) {
......@@ -433,7 +433,7 @@ DuplicateSymbolPartsAction::DuplicateSymbolPartsAction(Symbol& symbol, const set
}
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) {
......
......@@ -19,7 +19,7 @@
// ----------------------------------------------------------------------------- : ValueAction
String ValueAction::getName(bool to_undo) const {
return format_string(_ACTION_("change"), valueP->fieldP->name);
return _ACTION_1_("change", valueP->fieldP->name);
}
// ----------------------------------------------------------------------------- : Simple
......
......@@ -31,7 +31,7 @@ String serialize_for_clipboard(Package& package, T& object) {
template <typename T>
void deserialize_from_clipboard(T& object, Package& package, const String& data) {
shared_ptr<wxStringInputStream> stream( new wxStringInputStream(data) );
Reader reader(stream, _("clipboard"));
Reader reader(stream, nullptr, _("clipboard"));
WITH_DYNAMIC_ARG(clipboard_package, &package);
reader.handle_greedy(object);
}
......
......@@ -42,12 +42,12 @@ void Installer::installFrom(const String& filename, bool message_on_success, boo
i.open(filename);
try {
i.install(local);
}
catch (Error& e) {
} catch (const Error& e) {
handle_error(e);
return;
}
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")),
_("Magic Set Editor"), wxOK | wxICON_INFORMATION);
}
......@@ -65,15 +65,17 @@ struct dependency_check : public unary_function<bool, PackagedP> {
void Installer::install(bool local) {
// Destination directory
String install_dir = local ? ::packages.getLocalDataDir() : ::packages.getGlobalDataDir();
if (!wxDirExists(install_dir))
if (!wxDirExists(install_dir)) {
wxMkdir(install_dir, 0755);
}
// All the packages we're installing.
vector<PackagedP> new_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."));
}
PackagedP pack;
wxString fn(wxFileName(p).GetExt());
if (fn == _("mse-game")) pack = new_intrusive<Game>();
......@@ -90,7 +92,6 @@ void Installer::install(bool local) {
new_packages.push_back(pack);
}
// Check dependencies for each and every package.
FOR_EACH(p, new_packages) {
FOR_EACH(d, p->dependencies) {
......@@ -100,28 +101,31 @@ void Installer::install(bool local) {
}
}
}
const FileInfos& file_infos = getFileInfos();
for (FileInfos::const_iterator it = file_infos.begin() ; it != file_infos.end() ; ++it) {
String file = it->first;
wxFileName fn(file);
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;
}
String current_dir = install_dir;
for (size_t j = 0; j < dirs.GetCount(); ++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."));
}
}
InputStreamP is = openIn(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."));
}
os.Write(*is);
}
}
......
......@@ -206,7 +206,7 @@ DECLARE_TYPEOF(map<String COMMA KeyValidator>);
void Locale::validate(Version ver) {
// load locale validator
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);
// validate
String errors;
......
......@@ -248,7 +248,7 @@ void Settings::read() {
// settings file not existing is not an error
shared_ptr<wxFileInputStream> file = new_shared1<wxFileInputStream>(filename);
if (!file->Ok()) return; // failure is not an error
Reader reader(file, filename);
Reader reader(file, nullptr, filename);
reader.handle_greedy(*this);
}
}
......
......@@ -66,7 +66,7 @@ void ImagesExportWindow::onOk(wxCommandEvent&) {
else if (sel == 2) gs.images_export_conflicts = CONFLICT_NUMBER;
else gs.images_export_conflicts = CONFLICT_NUMBER_OVERWRITE;
// Script
ScriptP filename_script = parse(gs.images_export_filename, true);
ScriptP filename_script = parse(gs.images_export_filename, nullptr, true);
// Select filename
String name = wxFileSelector(_TITLE_("export images"),_(""), _LABEL_("filename is ignored"),_(""),
_LABEL_("filename is ignored")+_("|*"), wxSAVE, this);
......
......@@ -35,7 +35,7 @@ DECLARE_POINTER_TYPE(PageLayout);
*/
class TextBufferDC : public wxMemoryDC {
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 DoDrawRotatedText(const String& str, int x, int y, double angle);
......@@ -62,24 +62,34 @@ class TextBufferDC : public wxMemoryDC {
private:
vector<TextDrawP> text;
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_text(buffer_text)
{
SelectObject(buffer);
// initialize to white
clearDC(*this,*wxWHITE_BRUSH);
}
void TextBufferDC::DoDrawText(const String& str, int x, int y) {
double usx,usy;
GetUserScale(&usx, &usy);
text.push_back( new_intrusive7<TextDraw>(GetFont(), GetTextForeground(), usx, usy, x, y, str) );
if (buffer_text) {
double usx,usy;
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) {
double usx,usy;
GetUserScale(&usx, &usy);
text.push_back( new_intrusive8<TextDraw>(GetFont(), GetTextForeground(), usx, usy, x, y, str, angle) );
if (buffer_text) {
double usx,usy;
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);
......@@ -219,13 +229,16 @@ void CardsPrintout::drawCard(DC& dc, const CardP& card, int card_nr) {
// create buffers
int w = stylesheet.card_width, h = stylesheet.card_height; // in pixels
if (rotation == 90) swap(w,h);
TextBufferDC bufferDC(w,h);
RotatedDC rdc(bufferDC, rotation, RealRect(0,0,w,h), 1.0, QUALITY_SUB_PIXEL);
// Draw using text buffer
//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
viewer.setCard(card);
viewer.draw(rdc, *wxWHITE);
// 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.SetDeviceOrigin(scale_x * pos.x, scale_y * pos.y);
bufferDC.drawToDevice(dc, 0, 0); // adjust for scaling
......
......@@ -188,7 +188,7 @@ void CardsPanel::onUpdateUI(wxUpdateUIEvent& ev) {
ev.Enable(menu);
if (insertSymbolMenu->GetSubMenu() != menu || (menu && menu->GetParent() != menuFormat)) {
// re-add the menu
menuFormat->Remove(insertSymbolMenu);
menuFormat->Remove(ID_INSERT_SYMBOL);
insertSymbolMenu->SetSubMenu(menu);
menuFormat->Append(insertSymbolMenu);
}
......
......@@ -250,7 +250,7 @@ void KeywordsPanel::doPaste() { CUT_COPY_PASTE(doPaste, return (void), !
void KeywordsPanel::onChangeSet() {
list->setSet(set);
// 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
keyword ->setSet(set);
keyword ->getStyle().font.size = 16;
......
......@@ -286,7 +286,7 @@ void SetWindow::updateTitle() {
if (identification.empty()) identification = set->name();
if (identification.empty()) identification = _TITLE_("untitled");
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) {
bool SetWindow::askSaveAndContinue() {
if (set->actions.atSavePoint()) return true;
// 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) {
// save the set
try {
......
......@@ -29,7 +29,7 @@ SymbolWindow::SymbolWindow(Window* parent) {
SymbolWindow::SymbolWindow(Window* parent, const String& filename) {
// open file
Reader reader(new_shared1<wxFileInputStream>(filename), filename);
Reader reader(new_shared1<wxFileInputStream>(filename), nullptr, filename);
SymbolP symbol;
reader.handle_greedy(symbol);
init(parent, symbol);
......@@ -204,7 +204,7 @@ void SymbolWindow::onFileOpen(wxCommandEvent& ev) {
String ext = n.GetExt();
SymbolP 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);
} else {
wxBusyCursor busy;
......
......@@ -297,8 +297,7 @@ void DropDownWordList::select(size_t item) {
tve.selection_start_i = pos->start;
tve.selection_end_i = pos->end;
tve.fixSelection(TYPE_INDEX);
tve.replaceSelection(escape(new_value),
format_string(_ACTION_("change"), tve.field().name));
tve.replaceSelection(escape(new_value), _ACTION_1_("change", tve.field().name));
// stay open?
if (IsShown()) selection(); // update 'enabled'
}
......
......@@ -102,9 +102,10 @@ int MSE::OnRun() {
InstallType type = settings.install_type;
if (argc > 2) {
String arg = argv[2];
if (arg.Mid(0,2) == _("--"))
parse_enum(arg.Mid(2), type);
if (starts_with(argv[2], _("--"))) {
parse_enum(String(argv[2]).substr(2), type);
}
}
Installer::installFrom(argv[1], true, isInstallLocal(type));
return EXIT_SUCCESS;
} else if (arg == _("--symbol-editor")) {
......
# This file contains the keys expected to be in MSE locales
# 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:
add control point: 0
......@@ -82,9 +82,11 @@ error:
checking updates: 0
checking updates failed: 0
coordinates for blending overlap: 0
dependency not given: 4
dimension not found: 1
expected key: 1
file not found: 2
file not found package like: 2
file parse error: 2
has no member: 2
has no member value: 2
......@@ -99,7 +101,9 @@ error:
no updates: 0
package not found: 1
package out of date: 3
package too new: 4
stylesheet and set refer to different game: 0
successful install: optional, 2
unable to open output file: 0
unable to store file: 0
unrecognized value: 1
......
......@@ -57,7 +57,7 @@ enum OpenBrace
/** Also stores errors found when tokenizing or parsing */
class TokenIterator {
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
/** Can peek further forward by using higher values of offset.
......@@ -75,6 +75,7 @@ class TokenIterator {
String input;
size_t pos;
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
stack<OpenBrace> open_braces; ///< braces/quotes we entered from script mode
bool newline; ///< Did we just pass a newline?
......@@ -83,6 +84,7 @@ class TokenIterator {
String input;
size_t pos;
String filename;
Package* package;
};
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==_("!=")
// ----------------------------------------------------------------------------- : 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)
, pos(0)
, package(package)
, newline(false)
, errors(errors)
{
......@@ -183,12 +186,12 @@ void TokenIterator::readToken() {
if (eol == String::npos) eol = input.size();
String include_file = trim(input.substr(pos, eol - pos));
// store the current input for later retrieval
MoreInput m = {input, eol, filename};
MoreInput m = {input, eol, filename, package};
more.push(m);
// read the entire file, and start at the beginning of it
pos = 0;
filename = include_file;
InputStreamP is = packages.openFileFromPackage(include_file);
InputStreamP is = packages.openFileFromPackage(package, include_file);
input = read_utf8_line(*is, true, true);
} else if (isAlpha(c) || c == _('_')) {
// name
......@@ -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);
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();
// parse
TokenIterator input(s, string_mode, errors_out);
TokenIterator input(s, package, string_mode, errors_out);
ScriptP script(new Script);
parseOper(input, *script, PREC_ALL, I_RET);
Token eof = input.read();
......@@ -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;
ScriptP script = parse(s, string_mode, errors);
ScriptP script = parse(s, package, string_mode, errors);
if (!errors.empty()) {
throw ScriptParseErrors(errors);
}
......
......@@ -13,6 +13,8 @@
#include <util/error.hpp>
#include <script/script.hpp>
class Packaged;
// ----------------------------------------------------------------------------- : Parser
/// Parse a String to a Script
......@@ -21,8 +23,10 @@
*
* Errors are stored in the output vector.
* 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
/** 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
*
* 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
#endif
......@@ -46,7 +46,7 @@ ScriptValueP OptionalScript::invoke(Context& ctx, bool open_scope) const {
void OptionalScript::parse(Reader& reader, bool string_mode) {
vector<ScriptParseError> errors;
script = ::parse(unparsed, string_mode, errors);
script = ::parse(unparsed, reader.getPackage(), string_mode, errors);
// show parse errors as warnings
String include_warnings;
for (size_t i = 0 ; i < errors.size() ; ++i) {
......@@ -104,7 +104,7 @@ const String& StringScript::get() const {
void StringScript::set(const String& s) {
unparsed = s;
script = ::parse(unparsed, true);
script = ::parse(unparsed, nullptr, true);
}
template <> void Reader::handle(StringScript& os) {
......
......@@ -112,7 +112,7 @@ class ScriptCollection : public ScriptValue {
public:
inline ScriptCollection(const Collection* v) : value(v) {}
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 {
long index;
if (name.ToLong(&index) && index >= 0 && (size_t)index < value->size()) {
......@@ -160,7 +160,7 @@ class ScriptMap : public ScriptValue {
public:
inline ScriptMap(const Collection* v) : value(v) {}
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 {
return get_member(*value, name);
}
......
......@@ -25,7 +25,7 @@ IndexMap<Key,Value>& DelayedIndexMaps<Key,Value>::get(const String& name, const
item->read_data.init(init_with);
} else if (!item->unread_data.empty()) { // not read, read now
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);
item->unread_data.clear();
}
......
......@@ -178,10 +178,15 @@ class BufferedFileInputStream : private BufferedFileInputStream_aux, public wxBu
InputStreamP Package::openIn(const String& file) {
if (!file.empty() && file.GetChar(0) == _('/')) {
// 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));
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);
}
InputStreamP stream;
......@@ -442,6 +447,7 @@ IMPLEMENT_REFLECTION(Packaged) {
REFLECT_N("icon", icon_filename);
REFLECT_NO_SCRIPT(position_hint);
REFLECT(version);
REFLECT(compatible_version);
REFLECT_NO_SCRIPT_N("depends ons", dependencies); // hack for singular_form
}
......@@ -472,7 +478,7 @@ void Packaged::open(const String& package, bool just_header) {
fully_loaded = false;
if (just_header) {
// 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 {
JustAsPackageProxy proxy(this);
reader.handle_greedy(proxy);
......@@ -487,7 +493,7 @@ void Packaged::open(const String& package, bool just_header) {
void Packaged::loadFully() {
if (fully_loaded) return;
fully_loaded = true;
Reader reader(openIn(typeName()), absoluteFilename() + _("/") + typeName());
Reader reader(openIn(typeName()), this, absoluteFilename() + _("/") + typeName());
try {
reader.handle_greedy(*this);
validate(reader.file_app_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
String IncludePackage::typeName() const { return _("include"); }
......
......@@ -117,7 +117,7 @@ class Package : public IntrusivePtrVirtualBase {
template <typename T>
void readFile(const String& file, T& obj) {
Reader reader(openIn(file), absoluteFilename() + _("/") + file);
Reader reader(openIn(file), dynamic_cast<Packaged*>(this), absoluteFilename() + _("/") + file);
try {
reader.handle_greedy(obj);
} catch (const ParseError& err) {
......@@ -196,12 +196,13 @@ class Packaged : public Package {
Packaged();
virtual ~Packaged() {}
Version version; ///< Version number of this package
String short_name; ///< Short name of this package
String full_name; ///< Name of this package, for menus etc.
String icon_filename; ///< Filename of icon to use in package lists
Version version; ///< Version number of this package
Version compatible_version; ///< Earliest version number this package is compatible with
String short_name; ///< Short name of this package
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
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
InputStreamP openIconFile();
......@@ -215,6 +216,10 @@ class Packaged : public Package {
void save();
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:
/// filename of the data file, and extension of the package file
virtual String typeName() const = 0;
......
......@@ -101,17 +101,24 @@ void PackageManager::findMatching(const String& pattern, vector<PackagedP>& out)
}
}
InputStreamP PackageManager::openFileFromPackage(const String& name) {
// we don't want an absolute path (for security reasons)
String n;
if (!name.empty() && name.GetChar(0) == _('/')) n = name.substr(1);
else n = name;
// break
size_t pos = n.find_first_of(_("/\\"));
if (pos == String::npos) throw FileNotFoundError(n, _("No package name specified, use 'package/filename'"));
// open package and file
PackagedP p = openAny(n.substr(0, pos));
return p->openIn(n.substr(pos+1));
InputStreamP PackageManager::openFileFromPackage(Packaged*& package, const String& name) {
if (!name.empty() && name.GetChar(0) == _('/')) {
// absolute name; break name
size_t pos = name.find_first_of(_("/\\"), 1);
if (pos != String::npos) {
// open package
PackagedP p = openAny(name.substr(1, pos-1));
if (package) {
package->requireDependency(p.get());
}
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) {
......
......@@ -66,12 +66,18 @@ class PackageManager {
/** Only reads the package headers */
void findMatching(const String& pattern, vector<PackagedP>& out);
/// Open a file from a package, with a name encoded as "package/file"
InputStreamP openFileFromPackage(const String& name);
/// Open a file from a package, with a name encoded as "/package/file"
/** 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
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 getLocalDataDir() const { return local_data_directory; }
......
......@@ -14,9 +14,9 @@
// ----------------------------------------------------------------------------- : 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)
, filename(filename), line_number(0), previous_line_number(0)
, package(package), filename(filename), line_number(0), previous_line_number(0)
, ignore_invalid(ignore_invalid)
, input(input)
{
......@@ -24,12 +24,12 @@ Reader::Reader(const InputStreamP& input, const String& filename, bool ignore_in
handleAppVersion();
}
Reader::Reader(const String& filename)
Reader::Reader(Packaged* pkg, const String& filename)
: 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)
, input(packages.openFileFromPackage(filename))
{
input = packages.openFileFromPackage(package, filename);
moveNext();
handleAppVersion();
}
......
......@@ -16,6 +16,7 @@ template <typename T> class Defaultable;
template <typename T> class Scriptable;
DECLARE_POINTER_TYPE(Game);
DECLARE_POINTER_TYPE(StyleSheet);
class Packaged;
// ----------------------------------------------------------------------------- : Reader
......@@ -35,11 +36,13 @@ class Reader {
/// Construct a reader that reads from the given input stream
/** 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
/** Used for "include file" keys. */
Reader(const String& filename);
/** Used for "include file" keys.
* package can be nullptr
*/
Reader(Packaged* package, const String& filename);
~Reader() { showWarnings(); }
......@@ -108,6 +111,9 @@ class Reader {
/// Indicate that the last value from getValue() was not handled, allowing it to be handled again
void unhandle();
/// The package being read from
inline Packaged* getPackage() const { return package; }
// --------------------------------------------------- : Data
/// App version this file was made with
Version file_app_version;
......@@ -141,6 +147,8 @@ class Reader {
/// Filename for error messages
String filename;
/// Package this file is from, if any
Packaged* package;
/// Line number of the current line for error messages
int line_number;
/// Line number of the previous_line
......@@ -172,7 +180,7 @@ class Reader {
template <typename T>
void unknownKey(T& v) {
if (key == _("include file")) {
Reader reader(value);
Reader reader(package, value);
reader.handle_greedy(v);
moveNext();
} else {
......
......@@ -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)
#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)
#define _ERROR_1_(s,a) format_string(_ERROR_(s), a)
/// A localized string for error messages, with 2 argument (printf style)
#define _ERROR_2_(s,a,b) format_string(_ERROR_(s), a, b)
/// 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)
/// 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
/** 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
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());
}
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
#endif
......@@ -17,10 +17,12 @@ $built_in_functions = array(
'sort_text' =>'', 'sort_rule' => 'sort_text',
'contains' =>'',
'match' =>'', 'match_rule' => 'match',
'trim' =>'',
'regex_escape' =>'',
// tags
'tag_contents' =>'', 'tag_contents_rule'=>'tag_contents',
'remove_tag' =>'', 'tag_remove_rule' =>'remove_tag',
'remove_tags' =>'',
// lists
'postion' =>'',
'length' =>'',
......@@ -39,8 +41,8 @@ $built_in_functions = array(
'english_singular' =>'english_plural',
'process_english_hints' =>'',
// fields and values
'forward_editor' =>'',
'combined_editor' =>'combined_editor',
'forward_editor' =>'combined_editor',
'combined_editor' =>'',
'primary_choice' =>'',
'chosen' =>'',
'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