summarylogtreecommitdiffstats
diff options
context:
space:
mode:
authorEthan Kerrick2021-09-27 02:23:36 -0400
committerEthan Kerrick2021-09-27 02:23:36 -0400
commitaefb91461252e6e84b1bfd3e948e3261216c6e44 (patch)
tree79d7b54e5238bbb4b36d1c2625c4738ee4638062
parent56018b99d9f5edae98ec503bffd6e268db323857 (diff)
downloadaur-aefb91461252e6e84b1bfd3e948e3261216c6e44.tar.gz
bumped version to 2.1.2, upgrade to new build system, fix for compiler error, and addition of .desktop file
-rw-r--r--.SRCINFO28
-rw-r--r--MagicSetEditor.desktop28
-rw-r--r--PKGBUILD47
-rw-r--r--compilefix.patch1671
-rw-r--r--magicseteditor.install2
5 files changed, 1737 insertions, 39 deletions
diff --git a/.SRCINFO b/.SRCINFO
index 8194d1eb986e..6a8ff79e1b16 100644
--- a/.SRCINFO
+++ b/.SRCINFO
@@ -1,30 +1,26 @@
-# Generated by mksrcinfo v8
-# Sun Jun 3 00:46:51 UTC 2018
pkgbase = magicseteditor
pkgdesc = A program to help create Magic: the Gathering cards and sets. Comes with no game support.
- pkgver = 2.0.0
- pkgrel = 14
- url = http://magicseteditor.sourceforge.net
+ pkgver = 2.1.2
+ pkgrel = 1
+ url = https://github.com/twanvl/MagicSetEditor2
install = magicseteditor.install
arch = i686
arch = x86_64
license = GPL
makedepends = boost
makedepends = unzip
- makedepends = pkg-config
- makedepends = svn
+ makedepends = cmake
depends = hunspell
depends = libjpeg
- depends = wxgtk2.8
+ depends = wxgtk3
depends = boost-libs
- provides = magicseteditor=2.0.0
- conflicts = magicseteditor-bin
- conflicts = magicseteditor-svn
- conflicts = mse2
- conflicts = magicseteditor-xyz-mod
+ provides = magicseteditor=2.1.2
options = !strip
- source = mse-2.0.0::svn+https://svn.code.sf.net/p/magicseteditor/code/tags/releases/mse-2.0.0
- md5sums = SKIP
+ source = https://github.com/twanvl/MagicSetEditor2/archive/refs/tags/v2.1.2.tar.gz
+ source = compilefix.patch
+ source = MagicSetEditor.desktop
+ md5sums = 10a4d10e326f05c32a3e8f7be1842562
+ md5sums = 650a9afc5faa3d7749267608e1fe17c7
+ md5sums = fdcacb8841ebdbccd6b443e35276d497
pkgname = magicseteditor
-
diff --git a/MagicSetEditor.desktop b/MagicSetEditor.desktop
new file mode 100644
index 000000000000..f2a46ccf6e41
--- /dev/null
+++ b/MagicSetEditor.desktop
@@ -0,0 +1,28 @@
+[Desktop Entry]
+
+# The type as listed above
+Type=Application
+
+# The version of the desktop entry specification to which this file complies
+Version=1.0
+
+# The name of the application
+Name=MagicSetEditor
+
+# A comment which can/will be used as a tooltip
+Comment=a tool used to make custom cards
+
+# The path to the folder in which the executable is run
+Path=/usr/bin/
+
+# The executable of the application, possibly with arguments.
+Exec=magicseteditor
+
+# The name of the icon that will be used to display this entry
+Icon=MagicSetEditor
+
+# Describes whether this application needs to be run in a terminal or not
+Terminal=false
+
+# Describes the categories in which this entry should be shown
+Categories=Graphics
diff --git a/PKGBUILD b/PKGBUILD
index 22ada464a8ae..4dd5707c01a8 100644
--- a/PKGBUILD
+++ b/PKGBUILD
@@ -1,41 +1,44 @@
# Contributor: Sapphira Armageddos <shadowkyogre.public+aur@gmail.com>
pkgname=magicseteditor
-pkgver=2.0.0
-pkgrel=14
+pkgver=2.1.2
+pkgrel=1
pkgdesc="A program to help create Magic: the Gathering cards and sets. Comes with no game support."
arch=('i686' 'x86_64')
-url="http://magicseteditor.sourceforge.net"
+url="https://github.com/twanvl/MagicSetEditor2"
license=('GPL')
-depends=('hunspell' 'libjpeg' 'wxgtk2.8' 'boost-libs')
-makedepends=('boost' 'unzip' 'pkg-config' 'svn')
+depends=('hunspell' 'libjpeg' 'wxgtk3' 'boost-libs')
+makedepends=('boost' 'unzip' 'cmake')
provides=("magicseteditor=${pkgver}")
-conflicts=('magicseteditor-bin' 'magicseteditor-svn' 'mse2' 'magicseteditor-xyz-mod')
-source=("mse-${pkgver}::svn+https://svn.code.sf.net/p/magicseteditor/code/tags/releases/mse-${pkgver}")
+source=("https://github.com/twanvl/MagicSetEditor2/archive/refs/tags/v${pkgver}.tar.gz" "compilefix.patch" "MagicSetEditor.desktop")
install=$pkgname.install
options=(!strip)
-md5sums=(SKIP)
+md5sums=('10a4d10e326f05c32a3e8f7be1842562' '650a9afc5faa3d7749267608e1fe17c7' 'fdcacb8841ebdbccd6b443e35276d497')
-build() {
- cd "$srcdir/mse-${pkgver}"
- ./configure --prefix=/usr --with-wx-config=/usr/bin/wx-config-2.8
- #sed -e 's|^\(AM_LDFLAGS = .*\),--as-needed|\1,-Bsymbolic-functions|' -i Makefile
- make LIBS="-lboost_system $(pkg-config --libs hunspell) $(wx-config-2.8 --libs)" \
- CPPFLAGS="-std=c++98 -I/usr/include/hunspell -fpermissive" || return 1
+prepare()
+{
+patch -p0 < ./compilefix.patch
+}
+build()
+{
+cmake -B build -S "MagicSetEditor2-${pkgver}" -DwxWidgets_CONFIG_EXECUTABLE:FILEPATH="/usr/bin/wx-config-gtk3" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX='/usr'
+make -C build
}
package()
{
- cd "$srcdir/mse-${pkgver}"
- make DESTDIR=$pkgdir install || return 1
+ mkdir -p $pkgdir/usr/share/applications
+ cp MagicSetEditor.desktop $pkgdir/usr/share/applications
+ cd "$srcdir/build"
+ mv magicseteditor ../MagicSetEditor2-2.1.2
+ cd "$srcdir/MagicSetEditor2-${pkgver}"
+ mkdir -p $pkgdir/usr/bin
+ cp magicseteditor $pkgdir/usr/bin/
mkdir -p $pkgdir/usr/share/magicseteditor/{resource,data}
cp -r ./data/*.mse-locale $pkgdir/usr/share/magicseteditor/data
- cp -r ./src/resource/common/* $pkgdir/usr/share/magicseteditor/resource
- cp -r ./src/resource/msw/other/* $pkgdir/usr/share/magicseteditor/resource
- cp -r ./src/resource/msw/{cursor,icon,tool} $pkgdir/usr/share/magicseteditor/resource
- rm -rf $pkgdir/usr/share/magicseteditor/resource/{cursor,icon,tool}/.svn
- rm -rf $pkgdir/usr/share/magicseteditor/data/.svn
- rm -rf $pkgdir/usr/share/magicseteditor/data/*/.svn
+ cp -r ./resource/* $pkgdir/usr/share/magicseteditor/resource
+ mkdir -p $pkgdir/usr/share/pixmaps
+ cp ./resource/installer_program.png $pkgdir/usr/share/pixmaps/MagicSetEditor.png
}
# vim:set ts=2 sw=2 et:
diff --git a/compilefix.patch b/compilefix.patch
new file mode 100644
index 000000000000..fbb4f83c0fd5
--- /dev/null
+++ b/compilefix.patch
@@ -0,0 +1,1671 @@
+diff -ruN MagicSetEditor2-2.1.2/CHANGES.md MagicSetEditor2/CHANGES.md
+--- MagicSetEditor2-2.1.2/CHANGES.md 2020-09-27 20:12:17.000000000 -0400
++++ MagicSetEditor2/CHANGES.md 2021-09-26 12:56:49.109632360 -0400
+@@ -4,6 +4,12 @@
+ HEAD: new items added as changes are made
+ ------------------------------------------------------------------------------
+
++Features:
++ * You can now check/uncheck all selected cards in the export window (#93)
++
++Template features:
++ * Localization of game/stylesheet/symbol_font names is now done in those templates, instead of via the program-wide locale file. (#100)
++
+ ------------------------------------------------------------------------------
+ version 2.1.2, 2020-09-28
+ ------------------------------------------------------------------------------
+diff -ruN MagicSetEditor2-2.1.2/doc/type/field.txt MagicSetEditor2/doc/type/field.txt
+--- MagicSetEditor2-2.1.2/doc/type/field.txt 2020-09-27 20:12:17.000000000 -0400
++++ MagicSetEditor2/doc/type/field.txt 2021-09-26 12:56:49.122965694 -0400
+@@ -27,7 +27,7 @@
+ * @color@
+ * @info@
+ | @name@ [[type:string]] ''required'' Name of the field.
+-| @description@ [[type:string]] @""@ Description of the field, shown in the status bar when the mouse is over the field.
++| @description@ [[type:localized string]] @""@ Description of the field, shown in the status bar when the mouse is over the field.
+ | @icon@ [[type:filename]] Filename of an icon for this field, used for automatically generated [[type:statistics category]]s.
+ | @editable@ [[type:boolean]] @true@ Can values of this field be edited?
+ | @save value@ [[type:boolean]] @true@ Should values of this field be saved to files? Should be disabled for values that are generated by scripts.
+@@ -38,7 +38,7 @@
+ | @card list width@ [[type:int]] @100@ Width of the card list column in pixels.
+ | @card list visible@ [[type:boolean]] @false@ Should this field be shown in the card list by default?
+ | @card list allow@ [[type:boolean]] @true@ Should this field be allowed in the card list at all?
+-| @card list name@ [[type:string]] field name Alternate name to use for the card list, for example an abbreviation.
++| @card list name@ [[type:localized string]] field name Alternate name to use for the card list, for example an abbreviation.
+ | @card list alignment@ [[type:alignment]] @left@ Alignment of the card list column.
+ | @sort script@ [[type:script]] Alternate way to sort the card list when using this column to sort the list.
+
+diff -ruN MagicSetEditor2-2.1.2/doc/type/insert_symbol_menu.txt MagicSetEditor2/doc/type/insert_symbol_menu.txt
+--- MagicSetEditor2-2.1.2/doc/type/insert_symbol_menu.txt 2020-09-27 20:12:17.000000000 -0400
++++ MagicSetEditor2/doc/type/insert_symbol_menu.txt 2021-09-26 12:56:49.122965694 -0400
+@@ -14,18 +14,19 @@
+ * @line@, a separating line.
+ * @submenu@, a submenu.
+ | @name@ [[type:string]] ''required'' Name of this menu item, corresponding to the code to insert.
++| @label@ [[type:localized string]] name Label to show in the menu.
++| @prompt@ [[type:localized string]] Prompt to use for the pop up box with @custom@ type
+ | @items@ [[type:list]] of [[type:insert symbol menu|submenu items]] Items in the submenu, when items are present the @type@ is set to @"submenu"@.
+
+-In the user interface the items are shown as @"menu item {name}"@, the [[type:locale]] should be used to give a beter label.
+-
+-For custom items the dialog will be titled @"title {name}"@ and have message text @"message {name}"@, again this should be changed in the locale.
++For custom items the dialog will be titled with the @label@ and have message text @prompt@.
+
+ --Examples--
+ A menu for magic mana symbols (simplified). Containing all types of items.
+ >insert symbol menu:
+ > item:
+ > type: custom
+-> name: colorless
++> name: Generic
++> prompt: How much generic mana?
+ > item:
+ > type: line
+ > item: W
+@@ -34,6 +35,9 @@
+ > item: R
+ > item: G
+ > item:
++> label: Complex
++> name: cplx
++> item:
+ > type: line
+ > item:
+ > name: hybrid
+diff -ruN MagicSetEditor2-2.1.2/doc/type/locale.txt MagicSetEditor2/doc/type/locale.txt
+--- MagicSetEditor2-2.1.2/doc/type/locale.txt 2020-09-27 20:12:17.000000000 -0400
++++ MagicSetEditor2/doc/type/locale.txt 2021-09-26 12:56:49.126299027 -0400
+@@ -35,12 +35,15 @@
+ | @error@ [[type:map]] of [[type:string]]s Error messages.
+ | @type@ [[type:map]] of [[type:string]]s Types of objects for error messages.
+ | @game@ [[type:map]] of [[type:map]] of [[type:string]]s
++ Deprecated since MSE 2.1.3, use @localized_...@ instead.<br/>
+ Translations for specific [[type:game]]s.<br/>
+ Field names and field descriptions are looked up in the locale, if they are found the translation is used, otherwise the value from the game file.<br/>
+ Extra keys not present in the English locale can be added here.
+ | @stylesheet@ [[type:map]] of [[type:map]] of [[type:string]]s
++ Deprecated since MSE 2.1.3, use @localized_...@ instead.<br/>
+ Translations for specific [[type:stylesheet]]s.
+ | @symbol font@ [[type:map]] of [[type:map]] of [[type:string]]s
++ Deprecated since MSE 2.1.3, use @localized_...@ instead.<br/>
+ Translations for specific [[type:symbol font]]s, in particular the "insert symbol" menu.
+
+ Some of the items can contain placeholders for other values, for example:
+diff -ruN MagicSetEditor2-2.1.2/doc/type/localized_string.txt MagicSetEditor2/doc/type/localized_string.txt
+--- MagicSetEditor2-2.1.2/doc/type/localized_string.txt 1969-12-31 19:00:00.000000000 -0500
++++ MagicSetEditor2/doc/type/localized_string.txt 2021-09-26 12:56:49.126299027 -0400
+@@ -0,0 +1,14 @@
++Localized strings
++
++A 'localized string' is a [[type:map]] of [[type::string]]s, indexed by locale name.
++It is used to translate games and stylesheets to other user interface languages.
++
++Localized strings can be given with a @localized@ prefix on the property name.
++For example, a field has a @description@ which is a [[type::string]], and a @localized_description@ for localized variants. So
++
++>field:
++> name: cost
++> description: How much this card costs
++> localized description:
++> en_US: How much this card costs
++> nl_NL: Hoeveel deze kaart kost
+diff -ruN MagicSetEditor2-2.1.2/doc/type/statistics_category.txt MagicSetEditor2/doc/type/statistics_category.txt
+--- MagicSetEditor2-2.1.2/doc/type/statistics_category.txt 2020-09-27 20:12:17.000000000 -0400
++++ MagicSetEditor2/doc/type/statistics_category.txt 2021-09-26 12:56:49.126299027 -0400
+@@ -12,7 +12,7 @@
+ --Properties--
+ ! Property Type Default Description
+ | @name@ [[type:string]] ''required'' Name of this category.
+-| @description@ [[type:string]] @""@ A description of the category, currently not used.
++| @description@ [[type:localized string]] @""@ A description of the category, currently not used.
+ | @position hint@ [[type:string]] @0@ Hint for ordering category, lower numbers are at the top of the list.
+ | @icon@ [[type:filename]] Filename of an icon for this category, the image should be 21x21 pixels.
+ | @type@ [[type:graph type]] @"bar"@ Type of graph to use.
+diff -ruN MagicSetEditor2-2.1.2/doc/type/statistics_dimension.txt MagicSetEditor2/doc/type/statistics_dimension.txt
+--- MagicSetEditor2-2.1.2/doc/type/statistics_dimension.txt 2020-09-27 20:12:17.000000000 -0400
++++ MagicSetEditor2/doc/type/statistics_dimension.txt 2021-09-26 12:56:49.126299027 -0400
+@@ -13,7 +13,7 @@
+ --Properties--
+ ! Property Type Default Description
+ | @name@ [[type:string]] ''required'' Name of this dimension, used as an axis label and a label for automatically generated categories.
+-| @description@ [[type:string]] @""@ A description of the dimension, currently not used.
++| @description@ [[type:localized string]] @""@ A description of the dimension, currently not used.
+ | @position hint@ [[type:string]] @0@ Hint for ordering dimensions.
+ | @icon@ [[type:filename]] Filename of an icon for this dimension.
+ | @script@ [[type:script]] ''required'' Script that generates a value for each card in the set.
+diff -ruN MagicSetEditor2-2.1.2/.git/config MagicSetEditor2/.git/config
+--- MagicSetEditor2-2.1.2/.git/config 1969-12-31 19:00:00.000000000 -0500
++++ MagicSetEditor2/.git/config 2021-09-26 12:56:49.102965694 -0400
+@@ -0,0 +1,13 @@
++[core]
++ repositoryformatversion = 0
++ filemode = true
++ bare = false
++ logallrefupdates = true
++[submodule]
++ active = .
++[remote "origin"]
++ url = https://github.com/twanvl/MagicSetEditor2
++ fetch = +refs/heads/*:refs/remotes/origin/*
++[branch "master"]
++ remote = origin
++ merge = refs/heads/master
+diff -ruN MagicSetEditor2-2.1.2/.git/description MagicSetEditor2/.git/description
+--- MagicSetEditor2-2.1.2/.git/description 1969-12-31 19:00:00.000000000 -0500
++++ MagicSetEditor2/.git/description 2021-09-26 12:56:33.186298359 -0400
+@@ -0,0 +1 @@
++Unnamed repository; edit this file 'description' to name the repository.
+diff -ruN MagicSetEditor2-2.1.2/.git/HEAD MagicSetEditor2/.git/HEAD
+--- MagicSetEditor2-2.1.2/.git/HEAD 1969-12-31 19:00:00.000000000 -0500
++++ MagicSetEditor2/.git/HEAD 2021-09-26 12:56:49.099632359 -0400
+@@ -0,0 +1 @@
++ref: refs/heads/master
+diff -ruN MagicSetEditor2-2.1.2/.git/hooks/applypatch-msg.sample MagicSetEditor2/.git/hooks/applypatch-msg.sample
+--- MagicSetEditor2-2.1.2/.git/hooks/applypatch-msg.sample 1969-12-31 19:00:00.000000000 -0500
++++ MagicSetEditor2/.git/hooks/applypatch-msg.sample 2021-09-26 12:56:33.189631693 -0400
+@@ -0,0 +1,15 @@
++#!/bin/sh
++#
++# An example hook script to check the commit log message taken by
++# applypatch from an e-mail message.
++#
++# The hook should exit with non-zero status after issuing an
++# appropriate message if it wants to stop the commit. The hook is
++# allowed to edit the commit message file.
++#
++# To enable this hook, rename this file to "applypatch-msg".
++
++. git-sh-setup
++commitmsg="$(git rev-parse --git-path hooks/commit-msg)"
++test -x "$commitmsg" && exec "$commitmsg" ${1+"$@"}
++:
+diff -ruN MagicSetEditor2-2.1.2/.git/hooks/commit-msg.sample MagicSetEditor2/.git/hooks/commit-msg.sample
+--- MagicSetEditor2-2.1.2/.git/hooks/commit-msg.sample 1969-12-31 19:00:00.000000000 -0500
++++ MagicSetEditor2/.git/hooks/commit-msg.sample 2021-09-26 12:56:33.186298359 -0400
+@@ -0,0 +1,24 @@
++#!/bin/sh
++#
++# An example hook script to check the commit log message.
++# Called by "git commit" with one argument, the name of the file
++# that has the commit message. The hook should exit with non-zero
++# status after issuing an appropriate message if it wants to stop the
++# commit. The hook is allowed to edit the commit message file.
++#
++# To enable this hook, rename this file to "commit-msg".
++
++# Uncomment the below to add a Signed-off-by line to the message.
++# Doing this in a hook is a bad idea in general, but the prepare-commit-msg
++# hook is more suited to it.
++#
++# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
++# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
++
++# This example catches duplicate Signed-off-by lines.
++
++test "" = "$(grep '^Signed-off-by: ' "$1" |
++ sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || {
++ echo >&2 Duplicate Signed-off-by lines.
++ exit 1
++}
+diff -ruN MagicSetEditor2-2.1.2/.git/hooks/fsmonitor-watchman.sample MagicSetEditor2/.git/hooks/fsmonitor-watchman.sample
+--- MagicSetEditor2-2.1.2/.git/hooks/fsmonitor-watchman.sample 1969-12-31 19:00:00.000000000 -0500
++++ MagicSetEditor2/.git/hooks/fsmonitor-watchman.sample 2021-09-26 12:56:33.186298359 -0400
+@@ -0,0 +1,173 @@
++#!/usr/bin/perl
++
++use strict;
++use warnings;
++use IPC::Open2;
++
++# An example hook script to integrate Watchman
++# (https://facebook.github.io/watchman/) with git to speed up detecting
++# new and modified files.
++#
++# The hook is passed a version (currently 2) and last update token
++# formatted as a string and outputs to stdout a new update token and
++# all files that have been modified since the update token. Paths must
++# be relative to the root of the working tree and separated by a single NUL.
++#
++# To enable this hook, rename this file to "query-watchman" and set
++# 'git config core.fsmonitor .git/hooks/query-watchman'
++#
++my ($version, $last_update_token) = @ARGV;
++
++# Uncomment for debugging
++# print STDERR "$0 $version $last_update_token\n";
++
++# Check the hook interface version
++if ($version ne 2) {
++ die "Unsupported query-fsmonitor hook version '$version'.\n" .
++ "Falling back to scanning...\n";
++}
++
++my $git_work_tree = get_working_dir();
++
++my $retry = 1;
++
++my $json_pkg;
++eval {
++ require JSON::XS;
++ $json_pkg = "JSON::XS";
++ 1;
++} or do {
++ require JSON::PP;
++ $json_pkg = "JSON::PP";
++};
++
++launch_watchman();
++
++sub launch_watchman {
++ my $o = watchman_query();
++ if (is_work_tree_watched($o)) {
++ output_result($o->{clock}, @{$o->{files}});
++ }
++}
++
++sub output_result {
++ my ($clockid, @files) = @_;
++
++ # Uncomment for debugging watchman output
++ # open (my $fh, ">", ".git/watchman-output.out");
++ # binmode $fh, ":utf8";
++ # print $fh "$clockid\n@files\n";
++ # close $fh;
++
++ binmode STDOUT, ":utf8";
++ print $clockid;
++ print "\0";
++ local $, = "\0";
++ print @files;
++}
++
++sub watchman_clock {
++ my $response = qx/watchman clock "$git_work_tree"/;
++ die "Failed to get clock id on '$git_work_tree'.\n" .
++ "Falling back to scanning...\n" if $? != 0;
++
++ return $json_pkg->new->utf8->decode($response);
++}
++
++sub watchman_query {
++ my $pid = open2(\*CHLD_OUT, \*CHLD_IN, 'watchman -j --no-pretty')
++ or die "open2() failed: $!\n" .
++ "Falling back to scanning...\n";
++
++ # In the query expression below we're asking for names of files that
++ # changed since $last_update_token but not from the .git folder.
++ #
++ # To accomplish this, we're using the "since" generator to use the
++ # recency index to select candidate nodes and "fields" to limit the
++ # output to file names only. Then we're using the "expression" term to
++ # further constrain the results.
++ if (substr($last_update_token, 0, 1) eq "c") {
++ $last_update_token = "\"$last_update_token\"";
++ }
++ my $query = <<" END";
++ ["query", "$git_work_tree", {
++ "since": $last_update_token,
++ "fields": ["name"],
++ "expression": ["not", ["dirname", ".git"]]
++ }]
++ END
++
++ # Uncomment for debugging the watchman query
++ # open (my $fh, ">", ".git/watchman-query.json");
++ # print $fh $query;
++ # close $fh;
++
++ print CHLD_IN $query;
++ close CHLD_IN;
++ my $response = do {local $/; <CHLD_OUT>};
++
++ # Uncomment for debugging the watch response
++ # open ($fh, ">", ".git/watchman-response.json");
++ # print $fh $response;
++ # close $fh;
++
++ die "Watchman: command returned no output.\n" .
++ "Falling back to scanning...\n" if $response eq "";
++ die "Watchman: command returned invalid output: $response\n" .
++ "Falling back to scanning...\n" unless $response =~ /^\{/;
++
++ return $json_pkg->new->utf8->decode($response);
++}
++
++sub is_work_tree_watched {
++ my ($output) = @_;
++ my $error = $output->{error};
++ if ($retry > 0 and $error and $error =~ m/unable to resolve root .* directory (.*) is not watched/) {
++ $retry--;
++ my $response = qx/watchman watch "$git_work_tree"/;
++ die "Failed to make watchman watch '$git_work_tree'.\n" .
++ "Falling back to scanning...\n" if $? != 0;
++ $output = $json_pkg->new->utf8->decode($response);
++ $error = $output->{error};
++ die "Watchman: $error.\n" .
++ "Falling back to scanning...\n" if $error;
++
++ # Uncomment for debugging watchman output
++ # open (my $fh, ">", ".git/watchman-output.out");
++ # close $fh;
++
++ # Watchman will always return all files on the first query so
++ # return the fast "everything is dirty" flag to git and do the
++ # Watchman query just to get it over with now so we won't pay
++ # the cost in git to look up each individual file.
++ my $o = watchman_clock();
++ $error = $output->{error};
++
++ die "Watchman: $error.\n" .
++ "Falling back to scanning...\n" if $error;
++
++ output_result($o->{clock}, ("/"));
++ $last_update_token = $o->{clock};
++
++ eval { launch_watchman() };
++ return 0;
++ }
++
++ die "Watchman: $error.\n" .
++ "Falling back to scanning...\n" if $error;
++
++ return 1;
++}
++
++sub get_working_dir {
++ my $working_dir;
++ if ($^O =~ 'msys' || $^O =~ 'cygwin') {
++ $working_dir = Win32::GetCwd();
++ $working_dir =~ tr/\\/\//;
++ } else {
++ require Cwd;
++ $working_dir = Cwd::cwd();
++ }
++
++ return $working_dir;
++}
+diff -ruN MagicSetEditor2-2.1.2/.git/hooks/post-update.sample MagicSetEditor2/.git/hooks/post-update.sample
+--- MagicSetEditor2-2.1.2/.git/hooks/post-update.sample 1969-12-31 19:00:00.000000000 -0500
++++ MagicSetEditor2/.git/hooks/post-update.sample 2021-09-26 12:56:33.189631693 -0400
+@@ -0,0 +1,8 @@
++#!/bin/sh
++#
++# An example hook script to prepare a packed repository for use over
++# dumb transports.
++#
++# To enable this hook, rename this file to "post-update".
++
++exec git update-server-info
+diff -ruN MagicSetEditor2-2.1.2/.git/hooks/pre-applypatch.sample MagicSetEditor2/.git/hooks/pre-applypatch.sample
+--- MagicSetEditor2-2.1.2/.git/hooks/pre-applypatch.sample 1969-12-31 19:00:00.000000000 -0500
++++ MagicSetEditor2/.git/hooks/pre-applypatch.sample 2021-09-26 12:56:33.186298359 -0400
+@@ -0,0 +1,14 @@
++#!/bin/sh
++#
++# An example hook script to verify what is about to be committed
++# by applypatch from an e-mail message.
++#
++# The hook should exit with non-zero status after issuing an
++# appropriate message if it wants to stop the commit.
++#
++# To enable this hook, rename this file to "pre-applypatch".
++
++. git-sh-setup
++precommit="$(git rev-parse --git-path hooks/pre-commit)"
++test -x "$precommit" && exec "$precommit" ${1+"$@"}
++:
+diff -ruN MagicSetEditor2-2.1.2/.git/hooks/pre-commit.sample MagicSetEditor2/.git/hooks/pre-commit.sample
+--- MagicSetEditor2-2.1.2/.git/hooks/pre-commit.sample 1969-12-31 19:00:00.000000000 -0500
++++ MagicSetEditor2/.git/hooks/pre-commit.sample 2021-09-26 12:56:33.186298359 -0400
+@@ -0,0 +1,49 @@
++#!/bin/sh
++#
++# An example hook script to verify what is about to be committed.
++# Called by "git commit" with no arguments. The hook should
++# exit with non-zero status after issuing an appropriate message if
++# it wants to stop the commit.
++#
++# To enable this hook, rename this file to "pre-commit".
++
++if git rev-parse --verify HEAD >/dev/null 2>&1
++then
++ against=HEAD
++else
++ # Initial commit: diff against an empty tree object
++ against=$(git hash-object -t tree /dev/null)
++fi
++
++# If you want to allow non-ASCII filenames set this variable to true.
++allownonascii=$(git config --type=bool hooks.allownonascii)
++
++# Redirect output to stderr.
++exec 1>&2
++
++# Cross platform projects tend to avoid non-ASCII filenames; prevent
++# them from being added to the repository. We exploit the fact that the
++# printable range starts at the space character and ends with tilde.
++if [ "$allownonascii" != "true" ] &&
++ # Note that the use of brackets around a tr range is ok here, (it's
++ # even required, for portability to Solaris 10's /usr/bin/tr), since
++ # the square bracket bytes happen to fall in the designated range.
++ test $(git diff --cached --name-only --diff-filter=A -z $against |
++ LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0
++then
++ cat <<\EOF
++Error: Attempt to add a non-ASCII file name.
++
++This can cause problems if you want to work with people on other platforms.
++
++To be portable it is advisable to rename the file.
++
++If you know what you are doing you can disable this check using:
++
++ git config hooks.allownonascii true
++EOF
++ exit 1
++fi
++
++# If there are whitespace errors, print the offending file names and fail.
++exec git diff-index --check --cached $against --
+diff -ruN MagicSetEditor2-2.1.2/.git/hooks/pre-merge-commit.sample MagicSetEditor2/.git/hooks/pre-merge-commit.sample
+--- MagicSetEditor2-2.1.2/.git/hooks/pre-merge-commit.sample 1969-12-31 19:00:00.000000000 -0500
++++ MagicSetEditor2/.git/hooks/pre-merge-commit.sample 2021-09-26 12:56:33.189631693 -0400
+@@ -0,0 +1,13 @@
++#!/bin/sh
++#
++# An example hook script to verify what is about to be committed.
++# Called by "git merge" with no arguments. The hook should
++# exit with non-zero status after issuing an appropriate message to
++# stderr if it wants to stop the merge commit.
++#
++# To enable this hook, rename this file to "pre-merge-commit".
++
++. git-sh-setup
++test -x "$GIT_DIR/hooks/pre-commit" &&
++ exec "$GIT_DIR/hooks/pre-commit"
++:
+diff -ruN MagicSetEditor2-2.1.2/.git/hooks/prepare-commit-msg.sample MagicSetEditor2/.git/hooks/prepare-commit-msg.sample
+--- MagicSetEditor2-2.1.2/.git/hooks/prepare-commit-msg.sample 1969-12-31 19:00:00.000000000 -0500
++++ MagicSetEditor2/.git/hooks/prepare-commit-msg.sample 2021-09-26 12:56:33.189631693 -0400
+@@ -0,0 +1,42 @@
++#!/bin/sh
++#
++# An example hook script to prepare the commit log message.
++# Called by "git commit" with the name of the file that has the
++# commit message, followed by the description of the commit
++# message's source. The hook's purpose is to edit the commit
++# message file. If the hook fails with a non-zero status,
++# the commit is aborted.
++#
++# To enable this hook, rename this file to "prepare-commit-msg".
++
++# This hook includes three examples. The first one removes the
++# "# Please enter the commit message..." help message.
++#
++# The second includes the output of "git diff --name-status -r"
++# into the message, just before the "git status" output. It is
++# commented because it doesn't cope with --amend or with squashed
++# commits.
++#
++# The third example adds a Signed-off-by line to the message, that can
++# still be edited. This is rarely a good idea.
++
++COMMIT_MSG_FILE=$1
++COMMIT_SOURCE=$2
++SHA1=$3
++
++/usr/bin/perl -i.bak -ne 'print unless(m/^. Please enter the commit message/..m/^#$/)' "$COMMIT_MSG_FILE"
++
++# case "$COMMIT_SOURCE,$SHA1" in
++# ,|template,)
++# /usr/bin/perl -i.bak -pe '
++# print "\n" . `git diff --cached --name-status -r`
++# if /^#/ && $first++ == 0' "$COMMIT_MSG_FILE" ;;
++# *) ;;
++# esac
++
++# SOB=$(git var GIT_COMMITTER_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
++# git interpret-trailers --in-place --trailer "$SOB" "$COMMIT_MSG_FILE"
++# if test -z "$COMMIT_SOURCE"
++# then
++# /usr/bin/perl -i.bak -pe 'print "\n" if !$first_line++' "$COMMIT_MSG_FILE"
++# fi
+diff -ruN MagicSetEditor2-2.1.2/.git/hooks/pre-push.sample MagicSetEditor2/.git/hooks/pre-push.sample
+--- MagicSetEditor2-2.1.2/.git/hooks/pre-push.sample 1969-12-31 19:00:00.000000000 -0500
++++ MagicSetEditor2/.git/hooks/pre-push.sample 2021-09-26 12:56:33.186298359 -0400
+@@ -0,0 +1,53 @@
++#!/bin/sh
++
++# An example hook script to verify what is about to be pushed. Called by "git
++# push" after it has checked the remote status, but before anything has been
++# pushed. If this script exits with a non-zero status nothing will be pushed.
++#
++# This hook is called with the following parameters:
++#
++# $1 -- Name of the remote to which the push is being done
++# $2 -- URL to which the push is being done
++#
++# If pushing without using a named remote those arguments will be equal.
++#
++# Information about the commits which are being pushed is supplied as lines to
++# the standard input in the form:
++#
++# <local ref> <local oid> <remote ref> <remote oid>
++#
++# This sample shows how to prevent push of commits where the log message starts
++# with "WIP" (work in progress).
++
++remote="$1"
++url="$2"
++
++zero=$(git hash-object --stdin </dev/null | tr '[0-9a-f]' '0')
++
++while read local_ref local_oid remote_ref remote_oid
++do
++ if test "$local_oid" = "$zero"
++ then
++ # Handle delete
++ :
++ else
++ if test "$remote_oid" = "$zero"
++ then
++ # New branch, examine all commits
++ range="$local_oid"
++ else
++ # Update to existing branch, examine new commits
++ range="$remote_oid..$local_oid"
++ fi
++
++ # Check for WIP commit
++ commit=$(git rev-list -n 1 --grep '^WIP' "$range")
++ if test -n "$commit"
++ then
++ echo >&2 "Found WIP commit in $local_ref, not pushing"
++ exit 1
++ fi
++ fi
++done
++
++exit 0
+diff -ruN MagicSetEditor2-2.1.2/.git/hooks/pre-rebase.sample MagicSetEditor2/.git/hooks/pre-rebase.sample
+--- MagicSetEditor2-2.1.2/.git/hooks/pre-rebase.sample 1969-12-31 19:00:00.000000000 -0500
++++ MagicSetEditor2/.git/hooks/pre-rebase.sample 2021-09-26 12:56:33.186298359 -0400
+@@ -0,0 +1,169 @@
++#!/bin/sh
++#
++# Copyright (c) 2006, 2008 Junio C Hamano
++#
++# The "pre-rebase" hook is run just before "git rebase" starts doing
++# its job, and can prevent the command from running by exiting with
++# non-zero status.
++#
++# The hook is called with the following parameters:
++#
++# $1 -- the upstream the series was forked from.
++# $2 -- the branch being rebased (or empty when rebasing the current branch).
++#
++# This sample shows how to prevent topic branches that are already
++# merged to 'next' branch from getting rebased, because allowing it
++# would result in rebasing already published history.
++
++publish=next
++basebranch="$1"
++if test "$#" = 2
++then
++ topic="refs/heads/$2"
++else
++ topic=`git symbolic-ref HEAD` ||
++ exit 0 ;# we do not interrupt rebasing detached HEAD
++fi
++
++case "$topic" in
++refs/heads/??/*)
++ ;;
++*)
++ exit 0 ;# we do not interrupt others.
++ ;;
++esac
++
++# Now we are dealing with a topic branch being rebased
++# on top of master. Is it OK to rebase it?
++
++# Does the topic really exist?
++git show-ref -q "$topic" || {
++ echo >&2 "No such branch $topic"
++ exit 1
++}
++
++# Is topic fully merged to master?
++not_in_master=`git rev-list --pretty=oneline ^master "$topic"`
++if test -z "$not_in_master"
++then
++ echo >&2 "$topic is fully merged to master; better remove it."
++ exit 1 ;# we could allow it, but there is no point.
++fi
++
++# Is topic ever merged to next? If so you should not be rebasing it.
++only_next_1=`git rev-list ^master "^$topic" ${publish} | sort`
++only_next_2=`git rev-list ^master ${publish} | sort`
++if test "$only_next_1" = "$only_next_2"
++then
++ not_in_topic=`git rev-list "^$topic" master`
++ if test -z "$not_in_topic"
++ then
++ echo >&2 "$topic is already up to date with master"
++ exit 1 ;# we could allow it, but there is no point.
++ else
++ exit 0
++ fi
++else
++ not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"`
++ /usr/bin/perl -e '
++ my $topic = $ARGV[0];
++ my $msg = "* $topic has commits already merged to public branch:\n";
++ my (%not_in_next) = map {
++ /^([0-9a-f]+) /;
++ ($1 => 1);
++ } split(/\n/, $ARGV[1]);
++ for my $elem (map {
++ /^([0-9a-f]+) (.*)$/;
++ [$1 => $2];
++ } split(/\n/, $ARGV[2])) {
++ if (!exists $not_in_next{$elem->[0]}) {
++ if ($msg) {
++ print STDERR $msg;
++ undef $msg;
++ }
++ print STDERR " $elem->[1]\n";
++ }
++ }
++ ' "$topic" "$not_in_next" "$not_in_master"
++ exit 1
++fi
++
++<<\DOC_END
++
++This sample hook safeguards topic branches that have been
++published from being rewound.
++
++The workflow assumed here is:
++
++ * Once a topic branch forks from "master", "master" is never
++ merged into it again (either directly or indirectly).
++
++ * Once a topic branch is fully cooked and merged into "master",
++ it is deleted. If you need to build on top of it to correct
++ earlier mistakes, a new topic branch is created by forking at
++ the tip of the "master". This is not strictly necessary, but
++ it makes it easier to keep your history simple.
++
++ * Whenever you need to test or publish your changes to topic
++ branches, merge them into "next" branch.
++
++The script, being an example, hardcodes the publish branch name
++to be "next", but it is trivial to make it configurable via
++$GIT_DIR/config mechanism.
++
++With this workflow, you would want to know:
++
++(1) ... if a topic branch has ever been merged to "next". Young
++ topic branches can have stupid mistakes you would rather
++ clean up before publishing, and things that have not been
++ merged into other branches can be easily rebased without
++ affecting other people. But once it is published, you would
++ not want to rewind it.
++
++(2) ... if a topic branch has been fully merged to "master".
++ Then you can delete it. More importantly, you should not
++ build on top of it -- other people may already want to
++ change things related to the topic as patches against your
++ "master", so if you need further changes, it is better to
++ fork the topic (perhaps with the same name) afresh from the
++ tip of "master".
++
++Let's look at this example:
++
++ o---o---o---o---o---o---o---o---o---o "next"
++ / / / /
++ / a---a---b A / /
++ / / / /
++ / / c---c---c---c B /
++ / / / \ /
++ / / / b---b C \ /
++ / / / / \ /
++ ---o---o---o---o---o---o---o---o---o---o---o "master"
++
++
++A, B and C are topic branches.
++
++ * A has one fix since it was merged up to "next".
++
++ * B has finished. It has been fully merged up to "master" and "next",
++ and is ready to be deleted.
++
++ * C has not merged to "next" at all.
++
++We would want to allow C to be rebased, refuse A, and encourage
++B to be deleted.
++
++To compute (1):
++
++ git rev-list ^master ^topic next
++ git rev-list ^master next
++
++ if these match, topic has not merged in next at all.
++
++To compute (2):
++
++ git rev-list master..topic
++
++ if this is empty, it is fully merged to "master".
++
++DOC_END
+diff -ruN MagicSetEditor2-2.1.2/.git/hooks/pre-receive.sample MagicSetEditor2/.git/hooks/pre-receive.sample
+--- MagicSetEditor2-2.1.2/.git/hooks/pre-receive.sample 1969-12-31 19:00:00.000000000 -0500
++++ MagicSetEditor2/.git/hooks/pre-receive.sample 2021-09-26 12:56:33.186298359 -0400
+@@ -0,0 +1,24 @@
++#!/bin/sh
++#
++# An example hook script to make use of push options.
++# The example simply echoes all push options that start with 'echoback='
++# and rejects all pushes when the "reject" push option is used.
++#
++# To enable this hook, rename this file to "pre-receive".
++
++if test -n "$GIT_PUSH_OPTION_COUNT"
++then
++ i=0
++ while test "$i" -lt "$GIT_PUSH_OPTION_COUNT"
++ do
++ eval "value=\$GIT_PUSH_OPTION_$i"
++ case "$value" in
++ echoback=*)
++ echo "echo from the pre-receive-hook: ${value#*=}" >&2
++ ;;
++ reject)
++ exit 1
++ esac
++ i=$((i + 1))
++ done
++fi
+diff -ruN MagicSetEditor2-2.1.2/.git/hooks/push-to-checkout.sample MagicSetEditor2/.git/hooks/push-to-checkout.sample
+--- MagicSetEditor2-2.1.2/.git/hooks/push-to-checkout.sample 1969-12-31 19:00:00.000000000 -0500
++++ MagicSetEditor2/.git/hooks/push-to-checkout.sample 2021-09-26 12:56:33.189631693 -0400
+@@ -0,0 +1,78 @@
++#!/bin/sh
++
++# An example hook script to update a checked-out tree on a git push.
++#
++# This hook is invoked by git-receive-pack(1) when it reacts to git
++# push and updates reference(s) in its repository, and when the push
++# tries to update the branch that is currently checked out and the
++# receive.denyCurrentBranch configuration variable is set to
++# updateInstead.
++#
++# By default, such a push is refused if the working tree and the index
++# of the remote repository has any difference from the currently
++# checked out commit; when both the working tree and the index match
++# the current commit, they are updated to match the newly pushed tip
++# of the branch. This hook is to be used to override the default
++# behaviour; however the code below reimplements the default behaviour
++# as a starting point for convenient modification.
++#
++# The hook receives the commit with which the tip of the current
++# branch is going to be updated:
++commit=$1
++
++# It can exit with a non-zero status to refuse the push (when it does
++# so, it must not modify the index or the working tree).
++die () {
++ echo >&2 "$*"
++ exit 1
++}
++
++# Or it can make any necessary changes to the working tree and to the
++# index to bring them to the desired state when the tip of the current
++# branch is updated to the new commit, and exit with a zero status.
++#
++# For example, the hook can simply run git read-tree -u -m HEAD "$1"
++# in order to emulate git fetch that is run in the reverse direction
++# with git push, as the two-tree form of git read-tree -u -m is
++# essentially the same as git switch or git checkout that switches
++# branches while keeping the local changes in the working tree that do
++# not interfere with the difference between the branches.
++
++# The below is a more-or-less exact translation to shell of the C code
++# for the default behaviour for git's push-to-checkout hook defined in
++# the push_to_deploy() function in builtin/receive-pack.c.
++#
++# Note that the hook will be executed from the repository directory,
++# not from the working tree, so if you want to perform operations on
++# the working tree, you will have to adapt your code accordingly, e.g.
++# by adding "cd .." or using relative paths.
++
++if ! git update-index -q --ignore-submodules --refresh
++then
++ die "Up-to-date check failed"
++fi
++
++if ! git diff-files --quiet --ignore-submodules --
++then
++ die "Working directory has unstaged changes"
++fi
++
++# This is a rough translation of:
++#
++# head_has_history() ? "HEAD" : EMPTY_TREE_SHA1_HEX
++if git cat-file -e HEAD 2>/dev/null
++then
++ head=HEAD
++else
++ head=$(git hash-object -t tree --stdin </dev/null)
++fi
++
++if ! git diff-index --quiet --cached --ignore-submodules $head --
++then
++ die "Working directory has staged changes"
++fi
++
++if ! git read-tree -u -m "$commit"
++then
++ die "Could not update working tree to new HEAD"
++fi
+diff -ruN MagicSetEditor2-2.1.2/.git/hooks/update.sample MagicSetEditor2/.git/hooks/update.sample
+--- MagicSetEditor2-2.1.2/.git/hooks/update.sample 1969-12-31 19:00:00.000000000 -0500
++++ MagicSetEditor2/.git/hooks/update.sample 2021-09-26 12:56:33.189631693 -0400
+@@ -0,0 +1,128 @@
++#!/bin/sh
++#
++# An example hook script to block unannotated tags from entering.
++# Called by "git receive-pack" with arguments: refname sha1-old sha1-new
++#
++# To enable this hook, rename this file to "update".
++#
++# Config
++# ------
++# hooks.allowunannotated
++# This boolean sets whether unannotated tags will be allowed into the
++# repository. By default they won't be.
++# hooks.allowdeletetag
++# This boolean sets whether deleting tags will be allowed in the
++# repository. By default they won't be.
++# hooks.allowmodifytag
++# This boolean sets whether a tag may be modified after creation. By default
++# it won't be.
++# hooks.allowdeletebranch
++# This boolean sets whether deleting branches will be allowed in the
++# repository. By default they won't be.
++# hooks.denycreatebranch
++# This boolean sets whether remotely creating branches will be denied
++# in the repository. By default this is allowed.
++#
++
++# --- Command line
++refname="$1"
++oldrev="$2"
++newrev="$3"
++
++# --- Safety check
++if [ -z "$GIT_DIR" ]; then
++ echo "Don't run this script from the command line." >&2
++ echo " (if you want, you could supply GIT_DIR then run" >&2
++ echo " $0 <ref> <oldrev> <newrev>)" >&2
++ exit 1
++fi
++
++if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then
++ echo "usage: $0 <ref> <oldrev> <newrev>" >&2
++ exit 1
++fi
++
++# --- Config
++allowunannotated=$(git config --type=bool hooks.allowunannotated)
++allowdeletebranch=$(git config --type=bool hooks.allowdeletebranch)
++denycreatebranch=$(git config --type=bool hooks.denycreatebranch)
++allowdeletetag=$(git config --type=bool hooks.allowdeletetag)
++allowmodifytag=$(git config --type=bool hooks.allowmodifytag)
++
++# check for no description
++projectdesc=$(sed -e '1q' "$GIT_DIR/description")
++case "$projectdesc" in
++"Unnamed repository"* | "")
++ echo "*** Project description file hasn't been set" >&2
++ exit 1
++ ;;
++esac
++
++# --- Check types
++# if $newrev is 0000...0000, it's a commit to delete a ref.
++zero=$(git hash-object --stdin </dev/null | tr '[0-9a-f]' '0')
++if [ "$newrev" = "$zero" ]; then
++ newrev_type=delete
++else
++ newrev_type=$(git cat-file -t $newrev)
++fi
++
++case "$refname","$newrev_type" in
++ refs/tags/*,commit)
++ # un-annotated tag
++ short_refname=${refname##refs/tags/}
++ if [ "$allowunannotated" != "true" ]; then
++ echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2
++ echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2
++ exit 1
++ fi
++ ;;
++ refs/tags/*,delete)
++ # delete tag
++ if [ "$allowdeletetag" != "true" ]; then
++ echo "*** Deleting a tag is not allowed in this repository" >&2
++ exit 1
++ fi
++ ;;
++ refs/tags/*,tag)
++ # annotated tag
++ if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1
++ then
++ echo "*** Tag '$refname' already exists." >&2
++ echo "*** Modifying a tag is not allowed in this repository." >&2
++ exit 1
++ fi
++ ;;
++ refs/heads/*,commit)
++ # branch
++ if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then
++ echo "*** Creating a branch is not allowed in this repository" >&2
++ exit 1
++ fi
++ ;;
++ refs/heads/*,delete)
++ # delete branch
++ if [ "$allowdeletebranch" != "true" ]; then
++ echo "*** Deleting a branch is not allowed in this repository" >&2
++ exit 1
++ fi
++ ;;
++ refs/remotes/*,commit)
++ # tracking branch
++ ;;
++ refs/remotes/*,delete)
++ # delete tracking branch
++ if [ "$allowdeletebranch" != "true" ]; then
++ echo "*** Deleting a tracking branch is not allowed in this repository" >&2
++ exit 1
++ fi
++ ;;
++ *)
++ # Anything else (is there anything else?)
++ echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2
++ exit 1
++ ;;
++esac
++
++# --- Finished
++exit 0
+Binary files MagicSetEditor2-2.1.2/.git/index and MagicSetEditor2/.git/index differ
+diff -ruN MagicSetEditor2-2.1.2/.git/info/exclude MagicSetEditor2/.git/info/exclude
+--- MagicSetEditor2-2.1.2/.git/info/exclude 1969-12-31 19:00:00.000000000 -0500
++++ MagicSetEditor2/.git/info/exclude 2021-09-26 12:56:33.186298359 -0400
+@@ -0,0 +1,6 @@
++# git ls-files --others --exclude-from=.git/info/exclude
++# Lines that start with '#' are comments.
++# For a project mostly in C, the following would be a good set of
++# exclude patterns (uncomment them if you want to use them):
++# *.[oa]
++# *~
+diff -ruN MagicSetEditor2-2.1.2/.git/logs/HEAD MagicSetEditor2/.git/logs/HEAD
+--- MagicSetEditor2-2.1.2/.git/logs/HEAD 1969-12-31 19:00:00.000000000 -0500
++++ MagicSetEditor2/.git/logs/HEAD 2021-09-26 12:56:49.099632359 -0400
+@@ -0,0 +1 @@
++0000000000000000000000000000000000000000 f9d9356d51f28210ccf0c0dda508502f222e1def Ethan Kerrick <kerrickethan@gmail.com> 1632675409 -0400 clone: from https://github.com/twanvl/MagicSetEditor2
+diff -ruN MagicSetEditor2-2.1.2/.git/logs/refs/heads/master MagicSetEditor2/.git/logs/refs/heads/master
+--- MagicSetEditor2-2.1.2/.git/logs/refs/heads/master 1969-12-31 19:00:00.000000000 -0500
++++ MagicSetEditor2/.git/logs/refs/heads/master 2021-09-26 12:56:49.099632359 -0400
+@@ -0,0 +1 @@
++0000000000000000000000000000000000000000 f9d9356d51f28210ccf0c0dda508502f222e1def Ethan Kerrick <kerrickethan@gmail.com> 1632675409 -0400 clone: from https://github.com/twanvl/MagicSetEditor2
+diff -ruN MagicSetEditor2-2.1.2/.git/logs/refs/remotes/origin/HEAD MagicSetEditor2/.git/logs/refs/remotes/origin/HEAD
+--- MagicSetEditor2-2.1.2/.git/logs/refs/remotes/origin/HEAD 1969-12-31 19:00:00.000000000 -0500
++++ MagicSetEditor2/.git/logs/refs/remotes/origin/HEAD 2021-09-26 12:56:49.099632359 -0400
+@@ -0,0 +1 @@
++0000000000000000000000000000000000000000 f9d9356d51f28210ccf0c0dda508502f222e1def Ethan Kerrick <kerrickethan@gmail.com> 1632675409 -0400 clone: from https://github.com/twanvl/MagicSetEditor2
+Binary files MagicSetEditor2-2.1.2/.git/objects/pack/pack-7c9224ebd96d37c231a471c68dcc7bc0af836971.idx and MagicSetEditor2/.git/objects/pack/pack-7c9224ebd96d37c231a471c68dcc7bc0af836971.idx differ
+Binary files MagicSetEditor2-2.1.2/.git/objects/pack/pack-7c9224ebd96d37c231a471c68dcc7bc0af836971.pack and MagicSetEditor2/.git/objects/pack/pack-7c9224ebd96d37c231a471c68dcc7bc0af836971.pack differ
+diff -ruN MagicSetEditor2-2.1.2/.git/packed-refs MagicSetEditor2/.git/packed-refs
+--- MagicSetEditor2-2.1.2/.git/packed-refs 1969-12-31 19:00:00.000000000 -0500
++++ MagicSetEditor2/.git/packed-refs 2021-09-26 12:56:49.099632359 -0400
+@@ -0,0 +1,14 @@
++# pack-refs with: peeled fully-peeled sorted
++f9d9356d51f28210ccf0c0dda508502f222e1def refs/remotes/origin/master
++a8b7699ac3057493f9b178092b21fbdb7dc696c9 refs/tags/v2.0.2-rc1
++e005d47d563f5bd1b34184c0e887a4c2f150d31d refs/tags/v2.0.2-rc2
++9562103f7e073cd357148d0d46a3bbd3d8726360 refs/tags/v2.0.2-rc3
++2b7bd252e4404dd7c7e8a13439f005c4333e2519 refs/tags/v2.0.2-rc4
++a0f077e3b654438658b60895e9471e418451c0a4 refs/tags/v2.0.2-rc5
++641acff92a60b5fedec5ae63372b352d9bfba439 refs/tags/v2.0.2-rc6
++6a299dfe4109fb2f0d2db0f50b31138f764af9f1 refs/tags/v2.0.2-rc7
++a90348a71038c97a428e07d3d3fc0cb5bf2090ae refs/tags/v2.0.2-rc8
++31baa909d8a4c9872c249323dcfa7e15ca8c9b79 refs/tags/v2.0.2-rc9
++f5fb23da4d872dd3ca48f257b867ba35364c35ad refs/tags/v2.1.0
++0fc9480586d8e7be20fbb7d89b86569cadc13b23 refs/tags/v2.1.1
++2ae1598d5832977c7a2daf54f27c42a04553ac8f refs/tags/v2.1.2
+diff -ruN MagicSetEditor2-2.1.2/.git/refs/heads/master MagicSetEditor2/.git/refs/heads/master
+--- MagicSetEditor2-2.1.2/.git/refs/heads/master 1969-12-31 19:00:00.000000000 -0500
++++ MagicSetEditor2/.git/refs/heads/master 2021-09-26 12:56:49.099632359 -0400
+@@ -0,0 +1 @@
++f9d9356d51f28210ccf0c0dda508502f222e1def
+diff -ruN MagicSetEditor2-2.1.2/.git/refs/remotes/origin/HEAD MagicSetEditor2/.git/refs/remotes/origin/HEAD
+--- MagicSetEditor2-2.1.2/.git/refs/remotes/origin/HEAD 1969-12-31 19:00:00.000000000 -0500
++++ MagicSetEditor2/.git/refs/remotes/origin/HEAD 2021-09-26 12:56:49.099632359 -0400
+@@ -0,0 +1 @@
++ref: refs/remotes/origin/master
+diff -ruN MagicSetEditor2-2.1.2/src/data/field/information.cpp MagicSetEditor2/src/data/field/information.cpp
+--- MagicSetEditor2-2.1.2/src/data/field/information.cpp 2020-09-27 20:12:17.000000000 -0400
++++ MagicSetEditor2/src/data/field/information.cpp 2021-09-26 12:56:49.139632361 -0400
+@@ -64,7 +64,7 @@
+ return value;
+ }
+ bool InfoValue::update(Context& ctx) {
+- if (value.empty()) value = field().caption;
++ if (value.empty()) value = field().caption.get();
+ bool change = field().script.invokeOn(ctx, value);
+ Value::update(ctx);
+ return change;
+diff -ruN MagicSetEditor2-2.1.2/src/data/field.cpp MagicSetEditor2/src/data/field.cpp
+--- MagicSetEditor2-2.1.2/src/data/field.cpp 2020-09-27 20:12:17.000000000 -0400
++++ MagicSetEditor2/src/data/field.cpp 2021-09-26 12:56:49.136299028 -0400
+@@ -47,8 +47,8 @@
+ REFLECT(type);
+ }
+ REFLECT(name);
+- REFLECT(caption);
+- REFLECT(description);
++ REFLECT_LOCALIZED(caption);
++ REFLECT_LOCALIZED(description);
+ REFLECT_N("icon", icon_filename);
+ REFLECT(editable);
+ REFLECT(save_value);
+@@ -59,15 +59,15 @@
+ REFLECT(card_list_width);
+ REFLECT(card_list_visible);
+ REFLECT(card_list_allow);
+- REFLECT(card_list_name);
++ REFLECT_LOCALIZED(card_list_name);
+ REFLECT(sort_script);
+ REFLECT_N("card_list_alignment", card_list_align);
+ }
+
+ void Field::after_reading(Version ver) {
+ name = canonical_name_form(name);
+- if(caption.empty()) caption = name_to_caption(name);
+- if(card_list_name.empty()) card_list_name = capitalize(caption);
++ if(caption.default_.empty()) caption.default_ = name_to_caption(name);
++ if(card_list_name.default_.empty()) card_list_name.default_ = capitalize(caption.default_);
+ }
+
+ template <>
+diff -ruN MagicSetEditor2-2.1.2/src/data/field.hpp MagicSetEditor2/src/data/field.hpp
+--- MagicSetEditor2-2.1.2/src/data/field.hpp 2020-09-27 20:12:17.000000000 -0400
++++ MagicSetEditor2/src/data/field.hpp 2021-09-26 12:56:49.136299028 -0400
+@@ -13,6 +13,7 @@
+ #include <util/alignment.hpp>
+ #include <util/age.hpp>
+ #include <util/rotation.hpp>
++#include <data/localized_string.hpp>
+ #include <script/scriptable.hpp>
+ #include <script/dependency.hpp>
+ #include <script/image.hpp>
+@@ -43,8 +44,8 @@
+
+ size_t index; ///< Used by IndexMap
+ String name; ///< Name of the field, for refering to it from scripts and files
+- String caption; ///< Caption for NativeLookEditor
+- String description; ///< Description, used in status bar
++ LocalizedString caption; ///< Caption for NativeLookEditor
++ LocalizedString description;///< Description, used in status bar
+ String icon_filename; ///< Filename for an icon (for list of fields)
+ bool editable; ///< Can values of this field be edited?
+ bool save_value; ///< Should values of this field be written to files? Can be false for script generated fields.
+@@ -55,7 +56,7 @@
+ UInt card_list_width; ///< Width of the card list column (pixels).
+ bool card_list_visible;///< Is this field shown in the card list?
+ bool card_list_allow; ///< Is this field allowed to appear in the card list?
+- String card_list_name; ///< Alternate name to use in card list.
++ LocalizedString card_list_name; ///< Name to use in card list.
+ Alignment card_list_align; ///< Alignment of the card list colummn.
+ OptionalScript sort_script; ///< The script to use when sorting this, if not the value.
+ Dependencies dependent_scripts; ///< Scripts that depend on values of this field
+diff -ruN MagicSetEditor2-2.1.2/src/data/locale.cpp MagicSetEditor2/src/data/locale.cpp
+--- MagicSetEditor2-2.1.2/src/data/locale.cpp 2020-09-27 20:12:17.000000000 -0400
++++ MagicSetEditor2/src/data/locale.cpp 2021-09-26 12:56:49.142965695 -0400
+@@ -8,6 +8,7 @@
+
+ #include <util/prec.hpp>
+ #include <data/locale.hpp>
++#include <data/localized_string.hpp>
+ #include <data/game.hpp>
+ #include <data/stylesheet.hpp>
+ #include <data/symbol_font.hpp>
+@@ -118,3 +119,23 @@
+ }
+ return loc->tr(subcat, key, def);
+ }
++
++// ----------------------------------------------------------------------------- : LocalizedString
++
++String const& LocalizedString::get(String const& locale) const {
++ auto it = translations.find(locale);
++ if (it != translations.end()) {
++ return it->second;
++ } else {
++ return default_;
++ }
++}
++
++String const& LocalizedString::get(Locale const& locale) const {
++ return get(locale.name());
++}
++
++String const& LocalizedString::get() const {
++ if (translations.empty()) return default_;
++ return get(the_locale->name());
++}
+diff -ruN MagicSetEditor2-2.1.2/src/data/localized_string.hpp MagicSetEditor2/src/data/localized_string.hpp
+--- MagicSetEditor2-2.1.2/src/data/localized_string.hpp 1969-12-31 19:00:00.000000000 -0500
++++ MagicSetEditor2/src/data/localized_string.hpp 2021-09-26 12:56:49.142965695 -0400
+@@ -0,0 +1,37 @@
++//+----------------------------------------------------------------------------+
++//| Description: Magic Set Editor - Program to make Magic (tm) cards |
++//| Copyright: (C) Twan van Laarhoven and the other MSE developers |
++//| License: GNU General Public License 2 or later (see file COPYING) |
++//+----------------------------------------------------------------------------+
++
++#pragma once
++
++// ----------------------------------------------------------------------------- : Includes
++
++#include <util/prec.hpp>
++
++class Locale;
++
++// ----------------------------------------------------------------------------- : LocalizedString
++
++/// Translations of a text in a template
++class LocalizedString {
++public:
++ String default_; //< Value in all other locales
++ unordered_map<String, String> translations;
++
++ /// Translate
++ String const& get(Locale const& locale) const;
++ String const& get(String const& locale) const;
++ String const& get() const;
++
++ bool empty() const { return default_.empty(); }
++};
++
++#define REFLECT_LOCALIZED_N(name, var) \
++ do { \
++ handler.handle(name, var.default_); \
++ handler.handle(_("localized_") name, var.translations); \
++ } while (0)
++
++#define REFLECT_LOCALIZED(var) REFLECT_LOCALIZED_N(_(#var), var)
+diff -ruN MagicSetEditor2-2.1.2/src/data/statistics.cpp MagicSetEditor2/src/data/statistics.cpp
+--- MagicSetEditor2-2.1.2/src/data/statistics.cpp 2020-09-27 20:12:17.000000000 -0400
++++ MagicSetEditor2/src/data/statistics.cpp 2021-09-26 12:56:49.142965695 -0400
+@@ -64,7 +64,7 @@
+ IMPLEMENT_REFLECTION_NO_GET_MEMBER(StatsDimension) {
+ if (!automatic) {
+ REFLECT(name);
+- REFLECT(description);
++ REFLECT_LOCALIZED(description);
+ REFLECT(position_hint);
+ REFLECT_N("icon", icon_filename);
+ REFLECT(script);
+@@ -98,7 +98,7 @@
+ IMPLEMENT_REFLECTION_NO_GET_MEMBER(StatsCategory) {
+ if (!automatic) {
+ REFLECT(name);
+- REFLECT(description);
++ REFLECT_LOCALIZED(description);
+ REFLECT(position_hint);
+ REFLECT_N("icon", icon_filename);
+ REFLECT(type);
+diff -ruN MagicSetEditor2-2.1.2/src/data/statistics.hpp MagicSetEditor2/src/data/statistics.hpp
+--- MagicSetEditor2-2.1.2/src/data/statistics.hpp 2020-09-27 20:12:17.000000000 -0400
++++ MagicSetEditor2/src/data/statistics.hpp 2021-09-26 12:56:49.142965695 -0400
+@@ -11,6 +11,7 @@
+ #include <util/prec.hpp>
+ #include <util/reflect.hpp>
+ #include <data/graph_type.hpp>
++#include <data/localized_string.hpp>
+ #include <script/scriptable.hpp>
+
+ class Field;
+@@ -28,7 +29,7 @@
+
+ const bool automatic; ///< Based on a card field?
+ String name; ///< Name of this dimension
+- String description; ///< Description, used in status bar
++ LocalizedString description; ///< Description, used in status bar
+ int position_hint; ///< Hint for the ordering
+ String icon_filename; ///< Icon for lists
+ Bitmap icon; ///< The loaded icon (optional of course)
+@@ -52,15 +53,15 @@
+ StatsCategory();
+ StatsCategory(const StatsDimensionP&);
+
+- const bool automatic; ///< Automatically generated?
+- String name; ///< Name/label
+- String description; ///< Description, used in status bar
+- int position_hint; ///< Hint for the ordering
+- String icon_filename; ///< Icon for lists
+- Bitmap icon; ///< The loaded icon (optional of course)
+- vector<String> dimension_names;///< Names of the dimensions to use
+- vector<StatsDimensionP> dimensions; ///< Actual dimensions
+- GraphType type; ///< Type of graph to use
++ const bool automatic; ///< Automatically generated?
++ String name; ///< Name/label
++ LocalizedString description; ///< Description, used in status bar
++ int position_hint; ///< Hint for the ordering
++ String icon_filename; ///< Icon for lists
++ Bitmap icon; ///< The loaded icon (optional of course)
++ vector<String> dimension_names; ///< Names of the dimensions to use
++ vector<StatsDimensionP> dimensions; ///< Actual dimensions
++ GraphType type; ///< Type of graph to use
+
+ /// Initialize dimensions from dimension_names
+ void find_dimensions(const vector<StatsDimensionP>& available);
+diff -ruN MagicSetEditor2-2.1.2/src/data/symbol_font.cpp MagicSetEditor2/src/data/symbol_font.cpp
+--- MagicSetEditor2-2.1.2/src/data/symbol_font.cpp 2020-09-27 20:12:17.000000000 -0400
++++ MagicSetEditor2/src/data/symbol_font.cpp 2021-09-26 12:56:49.146299028 -0400
+@@ -52,8 +52,8 @@
+ REFLECT_N("vertical_space", spacing.height);
+ WITH_DYNAMIC_ARG(symbol_font_for_reading, this);
+ REFLECT(symbols);
+- REFLECT(scale_text);
+- REFLECT(insert_symbol_menu);
++ REFLECT(scale_text);
++ REFLECT(insert_symbol_menu);
+ }
+
+ // ----------------------------------------------------------------------------- : SymbolInFont
+@@ -460,11 +460,11 @@
+ } else if (id == 0 && type == Type::CODE) {
+ return name;
+ } else if (id == 0 && type == Type::CUSTOM) {
+- String caption = tr(font, _("title"), name, capitalize_sentence);
+- String message = tr(font, _("message"), name, capitalize_sentence);
+- return wxGetTextFromUser(message, caption);
++ String title = this->label.get();
++ title.Replace(_("&"), _("")); // remove underlines
++ return wxGetTextFromUser(prompt.get(), title);
+ }
+- return wxEmptyString;
++ return String();
+ }
+
+ wxMenu* InsertSymbolMenu::makeMenu(int id, SymbolFont& font) const {
+@@ -478,17 +478,18 @@
+ }
+ return nullptr;
+ }
++
+ wxMenuItem* InsertSymbolMenu::makeMenuItem(wxMenu* parent, int first_id, SymbolFont& font) const {
+- wxString menu_name = tr(font, _("menu_item"), name, capitalize);
++ String label = this->label.get();
+ // ensure that there is not actually an accelerator string,
+- menu_name.Replace(_("\t "),_("\t"));
++ label.Replace(_("\t "), _("\t"));
+ #ifdef __WXMSW__
+- menu_name.Replace(_("\t"),_("\t ")); // by prepending " "
++ label.Replace(_("\t"), _("\t ")); // by prepending " "
+ #else
+- menu_name.Replace(_("\t"),_(" ")); // by simply dropping the \t
++ label.Replace(_("\t"), _(" ")); // by simply dropping the \t
+ #endif
+ if (type == Type::SUBMENU) {
+- wxMenuItem* item = new wxMenuItem(parent, wxID_ANY, menu_name,
++ wxMenuItem* item = new wxMenuItem(parent, wxID_ANY, label,
+ wxEmptyString, wxITEM_NORMAL,
+ makeMenu(first_id, font));
+ item->SetBitmap(wxNullBitmap);
+@@ -497,7 +498,7 @@
+ wxMenuItem* item = new wxMenuItem(parent, wxID_SEPARATOR);
+ return item;
+ } else {
+- wxMenuItem* item = new wxMenuItem(parent, first_id, menu_name);
++ wxMenuItem* item = new wxMenuItem(parent, first_id, label);
+ // Generate bitmap for use on this item
+ SymbolInFont* symbol = nullptr;
+ if (type == Type::CUSTOM) {
+@@ -527,24 +528,24 @@
+ VALUE_N("submenu", InsertSymbolMenu::Type::SUBMENU);
+ }
+
+-IMPLEMENT_REFLECTION_NO_GET_MEMBER(InsertSymbolMenu) {
++IMPLEMENT_REFLECTION(InsertSymbolMenu) {
+ REFLECT_IF_READING_SINGLE_VALUE_AND(items.empty()) {
+ REFLECT_NAMELESS(name);
+ } else {
+ // complex values are groups
+ REFLECT(type);
+ REFLECT(name);
++ REFLECT_LOCALIZED(label);
++ REFLECT_LOCALIZED(prompt);
+ REFLECT(items);
+ if (Handler::isReading && !items.empty()) type = Type::SUBMENU;
+ }
+ }
+-template <> void GetDefaultMember::handle(const InsertSymbolMenu& m) {
+- handle(m.name);
+-}
+-template <> void GetMember::handle(const InsertSymbolMenu& m) {
+- handle(_("type"), m.type);
+- handle(_("name"), m.name);
+- handle(_("items"), m.items);
++
++void after_reading(InsertSymbolMenu& m, Version ver) {
++ assert(symbol_font_for_reading());
++ if (m.label.empty()) m.label.default_ = tr(*symbol_font_for_reading(), _("menu_item"), m.name, capitalize);
++ if (m.prompt.empty()) m.prompt.default_ = tr(*symbol_font_for_reading(), _("message"), m.name, capitalize_sentence);
+ }
+
+ // ----------------------------------------------------------------------------- : SymbolFontRef
+diff -ruN MagicSetEditor2-2.1.2/src/data/symbol_font.hpp MagicSetEditor2/src/data/symbol_font.hpp
+--- MagicSetEditor2-2.1.2/src/data/symbol_font.hpp 2020-09-27 20:12:17.000000000 -0400
++++ MagicSetEditor2/src/data/symbol_font.hpp 2021-09-26 12:56:49.146299028 -0400
+@@ -11,6 +11,7 @@
+ #include <util/prec.hpp>
+ #include <util/alignment.hpp>
+ #include <util/io/package.hpp>
++#include <data/localized_string.hpp>
+ #include <data/font.hpp>
+ #include <wx/regex.h>
+
+@@ -124,6 +125,8 @@
+ };
+ Type type;
+ String name;
++ LocalizedString label; // text of menu item
++ LocalizedString prompt; // prompt for dialog box if type == CUSTOM
+ vector<InsertSymbolMenuP> items;
+
+ /// Number of ids used (recursive)
+@@ -139,6 +142,8 @@
+ DECLARE_REFLECTION();
+ };
+
++void after_reading(InsertSymbolMenu&, Version ver);
++
+ // ----------------------------------------------------------------------------- : SymbolFontRef
+
+ /// A reference to an actual symbol font
+diff -ruN MagicSetEditor2-2.1.2/src/gui/control/card_editor.cpp MagicSetEditor2/src/gui/control/card_editor.cpp
+--- MagicSetEditor2-2.1.2/src/gui/control/card_editor.cpp 2020-09-27 20:12:17.000000000 -0400
++++ MagicSetEditor2/src/gui/control/card_editor.cpp 2021-09-26 12:56:49.149632362 -0400
+@@ -355,7 +355,7 @@
+ // set status text
+ wxFrame* frame = dynamic_cast<wxFrame*>( wxGetTopLevelParent(this) );
+ if (frame) {
+- frame->SetStatusText(hovered_viewer ? hovered_viewer->getField()->description : String());
++ frame->SetStatusText(hovered_viewer ? hovered_viewer->getField()->description.get() : String());
+ }
+ }
+ }
+diff -ruN MagicSetEditor2-2.1.2/src/gui/control/card_list_column_select.cpp MagicSetEditor2/src/gui/control/card_list_column_select.cpp
+--- MagicSetEditor2-2.1.2/src/gui/control/card_list_column_select.cpp 2020-09-27 20:12:17.000000000 -0400
++++ MagicSetEditor2/src/gui/control/card_list_column_select.cpp 2021-09-26 12:56:49.149632362 -0400
+@@ -67,7 +67,7 @@
+ // Init items
+ Color window_color = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
+ FOR_EACH(c, columns) {
+- list->Append(tr(*game, c.field->card_list_name, identity));
++ list->Append(c.field->card_list_name.get());
+ // check
+ int i = list->GetCount() - 1;
+ list->Check(i, c.settings.visible);
+@@ -80,7 +80,7 @@
+
+ void CardListColumnSelectDialog::refreshItem(int i) {
+ list->Check (i, columns[i].settings.visible);
+- list->SetString(i, tr(*game, columns[i].field->card_list_name, identity) );
++ list->SetString(i, columns[i].field->card_list_name.get());
+ }
+
+ // ----------------------------------------------------------------------------- : Events
+diff -ruN MagicSetEditor2-2.1.2/src/gui/control/card_list.cpp MagicSetEditor2/src/gui/control/card_list.cpp
+--- MagicSetEditor2-2.1.2/src/gui/control/card_list.cpp 2020-09-27 20:12:17.000000000 -0400
++++ MagicSetEditor2/src/gui/control/card_list.cpp 2021-09-26 12:56:49.149632362 -0400
+@@ -225,9 +225,7 @@
+ if (f.second->card_list_align & ALIGN_RIGHT) align = wxLIST_FORMAT_RIGHT;
+ else if (f.second->card_list_align & ALIGN_CENTER) align = wxLIST_FORMAT_CENTRE;
+ else align = wxLIST_FORMAT_LEFT;
+- InsertColumn((long)column_fields.size(),
+- tr(*set->game, f.second->card_list_name, identity),
+- align, cs.width);
++ InsertColumn((long)column_fields.size(), f.second->card_list_name.get(), align, cs.width);
+ column_fields.push_back(f.second);
+ }
+ // determine sort settings
+diff -ruN MagicSetEditor2-2.1.2/src/gui/control/native_look_editor.cpp MagicSetEditor2/src/gui/control/native_look_editor.cpp
+--- MagicSetEditor2-2.1.2/src/gui/control/native_look_editor.cpp 2020-09-27 20:12:17.000000000 -0400
++++ MagicSetEditor2/src/gui/control/native_look_editor.cpp 2021-09-26 12:56:49.152965695 -0400
+@@ -39,9 +39,7 @@
+ // draw label
+ dc.SetFont(*wxNORMAL_FONT);
+ dc.SetTextForeground(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNTEXT));
+- // TODO : tr using stylesheet or using game?
+- dc.DrawText(tr(getStylePackage(), v.getField()->caption, identity),
+- RealPoint(margin_left - v.bounding_box.x, 1));
++ dc.DrawText(v.getField()->caption.get(), RealPoint(margin_left - v.bounding_box.x, 1));
+ }
+ // draw viewer
+ v.draw(dc);
+@@ -64,8 +62,7 @@
+ // width of the label string
+ int w;
+ Style& s = *v->getStyle();
+- String text = tr(getStylePackage(), s.fieldP->caption, identity);
+- dc.GetTextExtent(text,&w,nullptr);
++ dc.GetTextExtent(s.fieldP->caption.get(), &w, nullptr);
+ label_width = max(label_width, w + label_margin);
+ }
+ }
+diff -ruN MagicSetEditor2-2.1.2/src/gui/control/select_card_list.cpp MagicSetEditor2/src/gui/control/select_card_list.cpp
+--- MagicSetEditor2-2.1.2/src/gui/control/select_card_list.cpp 2020-09-27 20:12:17.000000000 -0400
++++ MagicSetEditor2/src/gui/control/select_card_list.cpp 2021-09-26 12:56:49.152965695 -0400
+@@ -74,6 +74,17 @@
+ }
+ }
+
++void SelectCardList::toggleSelected(bool select) {
++ for (long i = GetFirstSelected(); i != -1; i = GetNextSelected(i)) {
++ if (select) {
++ selected.insert(getCard(i));
++ } else {
++ selected.erase(getCard(i));
++ }
++ RefreshItem(i);
++ }
++}
++
+ void SelectCardList::onKeyDown(wxKeyEvent& ev) {
+ if (selected_item_pos == -1 || !selected_item) {
+ // no selection
+@@ -82,18 +93,15 @@
+ }
+ switch (ev.GetKeyCode()) {
+ case WXK_SPACE: {
+- toggle(getCard());
+- RefreshItem(selected_item_pos);
++ toggleSelected(!isSelected(getCard()));
+ break;
+ }
+ case WXK_NUMPAD_ADD: case '+': {
+- selected.insert(getCard());
+- RefreshItem(selected_item_pos);
++ toggleSelected(true);
+ break;
+ }
+ case WXK_NUMPAD_SUBTRACT: case '-': {
+- selected.erase(getCard());
+- RefreshItem(selected_item_pos);
++ toggleSelected(false);
+ break;
+ }
+ default:
+@@ -106,8 +114,14 @@
+ long item = HitTest(wxPoint(ev.GetX(), ev.GetY()), flags);
+ if (flags == wxLIST_HITTEST_ONITEMICON) {
+ // only clicking the icon toggles
+- toggle(getCard(item));
+- RefreshItem(item);
++ if (IsSelected(item)) {
++ // if multiple items are selected in the view (regardless of checkbox status), check/uncheck them all
++ toggleSelected(!isSelected(getCard(item)));
++ return; // don't change selection
++ } else {
++ toggle(getCard(item));
++ RefreshItem(item);
++ }
+ }
+ ev.Skip();
+ }
+diff -ruN MagicSetEditor2-2.1.2/src/gui/control/select_card_list.hpp MagicSetEditor2/src/gui/control/select_card_list.hpp
+--- MagicSetEditor2-2.1.2/src/gui/control/select_card_list.hpp 2020-09-27 20:12:17.000000000 -0400
++++ MagicSetEditor2/src/gui/control/select_card_list.hpp 2021-09-26 12:56:49.152965695 -0400
+@@ -37,8 +37,9 @@
+ DECLARE_EVENT_TABLE();
+
+ std::set<CardP> selected; ///< which cards are selected?
+-
++
+ void toggle(const CardP& card);
++ void toggleSelected(bool select);
+
+ void onKeyDown(wxKeyEvent&);
+ void onLeftDown(wxMouseEvent&);
+diff -ruN MagicSetEditor2-2.1.2/src/script/to_value.hpp MagicSetEditor2/src/script/to_value.hpp
+--- MagicSetEditor2-2.1.2/src/script/to_value.hpp 2020-09-27 20:12:17.000000000 -0400
++++ MagicSetEditor2/src/script/to_value.hpp 2021-09-26 12:56:49.169632362 -0400
+@@ -145,9 +145,9 @@
+
+ // ----------------------------------------------------------------------------- : Collections : maps
+
+-template <typename V>
+-ScriptValueP get_member(const map<String,V>& m, const String& name) {
+- typename map<String,V>::const_iterator it = m.find(name);
++template <typename Container>
++ScriptValueP get_member(const Container& m, const String& name) {
++ auto it = m.find(name);
+ if (it != m.end()) {
+ return to_script(it->second);
+ } else {
+@@ -403,6 +403,10 @@
+ return make_intrusive<ScriptMap<map<K,V>>>(v);
+ }
+ template <typename K, typename V>
++inline ScriptValueP to_script(const unordered_map<K,V>* v) {
++ return make_intrusive<ScriptMap<unordered_map<K,V>>>(v);
++}
++template <typename K, typename V>
+ inline ScriptValueP to_script(const IndexMap<K,V>* v) {
+ return make_intrusive<ScriptMap<IndexMap<K,V>>>(v);
+ }
+diff -ruN MagicSetEditor2-2.1.2/src/util/io/get_member.hpp MagicSetEditor2/src/util/io/get_member.hpp
+--- MagicSetEditor2-2.1.2/src/util/io/get_member.hpp 2020-09-27 20:12:17.000000000 -0400
++++ MagicSetEditor2/src/util/io/get_member.hpp 2021-09-26 12:56:49.172965696 -0400
+@@ -56,6 +56,7 @@
+ template <typename T> void handle(const Scriptable<T>& );
+ template <typename T> void handle(const vector<T>& c) { value = to_script(&c); }
+ template <typename K, typename V> void handle(const map<K,V>& c) { value = to_script(&c); }
++ template <typename K, typename V> void handle(const unordered_map<K,V>& c) { value = to_script(&c); }
+ template <typename K, typename V> void handle(const IndexMap<K,V>& c) { value = to_script(&c); }
+ template <typename K, typename V> void handle(const DelayedIndexMaps<K,V>&) {}
+ template <typename K, typename V> void handle(const DelayedIndexMapsData<K,V>& c);
+diff -ruN MagicSetEditor2-2.1.2/src/util/locale.hpp MagicSetEditor2/src/util/locale.hpp
+--- MagicSetEditor2-2.1.2/src/util/locale.hpp 2020-09-27 20:12:17.000000000 -0400
++++ MagicSetEditor2/src/util/locale.hpp 2021-09-26 12:56:49.172965696 -0400
+@@ -49,9 +49,11 @@
+ String tr(LocaleCategory cat, const String& key, DefaultLocaleFun def = warn_and_identity);
+
+ /// Translate 'key' in the for a Package using the current locale
++[[deprecated]]
+ String tr(const Package&, const String& key, DefaultLocaleFun def);
+
+ /// Translate 'key' in the for a Package using the current locale
++[[deprecated]]
+ String tr(const Package&, const String& subcat, const String& key, DefaultLocaleFun def);
+
+ /// A localized string for menus
+diff -ruN MagicSetEditor2-2.1.2/src/util/prec.hpp MagicSetEditor2/src/util/prec.hpp
+--- MagicSetEditor2-2.1.2/src/util/prec.hpp 2020-09-27 20:12:17.000000000 -0400
++++ MagicSetEditor2/src/util/prec.hpp 2021-09-26 12:56:49.172965696 -0400
+@@ -40,6 +40,7 @@
+ #include <vector>
+ #include <map>
+ #include <set>
++#include <unordered_map>
+ using namespace std;
+
+ #undef RGB
+diff -ruN MagicSetEditor2-2.1.2/src/util/regex.hpp MagicSetEditor2/src/util/regex.hpp
+--- MagicSetEditor2-2.1.2/src/util/regex.hpp 2020-09-27 20:12:17.000000000 -0400
++++ MagicSetEditor2/src/util/regex.hpp 2021-09-26 12:56:49.172965696 -0400
+@@ -31,23 +31,18 @@
+ // ----------------------------------------------------------------------------- : Boost implementation
+
+ #if USE_BOOST_REGEX
+- // needed for boost::regex
+- inline std::size_t hash_value(wxUniChar const& x) {
+- boost::hash<int> hasher;
+- return hasher(static_cast<int>(x));
+- }
+- /*
+- // fix: boost regex doesn't like that wxUniChar can't be constructed from an int
+- namespace boost {
+- namespace BOOST_REGEX_DETAIL_NS {
+- inline bool can_start(wxUniChar c, const unsigned char* map, unsigned char mask) {
+- return can_start(c.GetValue(), map, mask);
+- }
+- inline bool can_start(wxUniCharRef c, const unsigned char* map, unsigned char mask) {
+- return can_start(c.GetValue(), map, mask);
+- }
++ // needed for boost::regex to compute hash values of unicode chars
++ #if BOOST_VERSION < 107600
++ inline std::size_t hash_value(wxUniChar const& x) {
++ boost::hash<int> hasher;
++ return hasher(static_cast<int>(x));
+ }
+- }*/
++ #else
++ // boost > 1.76 uses its own hash function that needs operator +
++ inline int operator + (wxUniChar x, unsigned int y) {
++ return static_cast<int>(x) + y;
++ }
++ #endif
+
+ /// Our own regular expression wrapper
+ /** Suppors both boost::regex and wxRegEx.
+diff -ruN MagicSetEditor2-2.1.2/src/util/string.hpp MagicSetEditor2/src/util/string.hpp
+--- MagicSetEditor2-2.1.2/src/util/string.hpp 2020-09-27 20:12:17.000000000 -0400
++++ MagicSetEditor2/src/util/string.hpp 2021-09-26 12:56:49.176299029 -0400
+@@ -33,6 +33,17 @@
+ #endif
+ }
+
++#if wxVERSION_NUMBER < 3100
++// wxWidgets 3.1.0 added this specialization
++namespace std {
++ template<> struct hash<String> {
++ size_t operator()(String const& s) const {
++ return std::hash<std::wstring>()(s.ToStdWstring());
++ }
++ };
++}
++#endif
++
+ // ----------------------------------------------------------------------------- : Unicode
+
+ /// u if UNICODE is defined, a otherwise
diff --git a/magicseteditor.install b/magicseteditor.install
index bd80c6245e13..bdcd26f735c5 100644
--- a/magicseteditor.install
+++ b/magicseteditor.install
@@ -3,7 +3,7 @@ post_install()
cat <<-EndOfMessage
The fonts required for this package can't be put on the AUR due to licensing issues.
In order to get them, download the binary release here:
-http://downloads.sourceforge.net/magicseteditor/mse-linux32-2011-02-05-full.tar.gz
+https://github.com/MagicSetEditorPacks/Basic-M15-Magic-Pack/archive/refs/heads/main.zip
Copy the fonts into your /usr/share/fonts/TTF folder or wrap them up
with some fancy PKGBUILD of your own.