[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
gEDA-cvs: branch: master updated (rel_0.1.1-7-g59c3a9a)
The branch, master has been updated
via 59c3a9a59f4ddfa893edf18b5aa7df552b8af356 (commit)
via 649f9471386c378c0dc8145cc5a7cc1c3dbae515 (commit)
via d0e352691a5a330ccef662013875ebdfbfbea0a9 (commit)
via 1e35cf9eb5bd654f58e5b461ff073042204a8880 (commit)
from 5911561361be6e21d586d4f2dcbe901d6278d702 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
=========
Summary
=========
.gitignore | 4 +
Makefile.am | 17 +-
configure.ac | 50 ++-
data/.gitignore | 4 +
data/Makefile.am | 51 ++
data/geda-xgsch2pcb.desktop.in | 10 +
data/xgsch2pcb-48.png | Bin 0 -> 3323 bytes
data/xgsch2pcb.svg | 1097 ++++++++++++++++++++++++++++
icon-theme-installer | 181 +++++
lib/xgsch2pcb/assistant.py | 4 -
lib/xgsch2pcb/config.py.in | 2 +-
lib/xgsch2pcb/gui.py | 5 +-
lib/xgsch2pcb/new_project_gui.py | 4 +-
lib/xgsch2pcb/pcbmanager.py | 4 +-
po/.gitignore | 15 +
po/POTFILES.in | 4 +
po/POTFILES.skip | 1 +
po/geda-xgsch2pcb.pot | 306 ++++++++
tools/intltool-extract.in | 861 ++++++++++++++++++++++
tools/intltool-merge.in | 1451 ++++++++++++++++++++++++++++++++++++++
tools/intltool-update.in | 1164 ++++++++++++++++++++++++++++++
xgsch2pcb.in | 3 +-
22 files changed, 5219 insertions(+), 19 deletions(-)
create mode 100644 data/.gitignore
create mode 100644 data/Makefile.am
create mode 100644 data/geda-xgsch2pcb.desktop.in
create mode 100644 data/xgsch2pcb-48.png
create mode 100644 data/xgsch2pcb.svg
create mode 100755 icon-theme-installer
create mode 100644 po/.gitignore
create mode 100644 po/ChangeLog
create mode 100644 po/LINGUAS
create mode 100644 po/POTFILES.in
create mode 100644 po/POTFILES.skip
create mode 100644 po/geda-xgsch2pcb.pot
create mode 100644 tools/intltool-extract.in
create mode 100644 tools/intltool-merge.in
create mode 100644 tools/intltool-update.in
=================
Commit Messages
=================
commit 59c3a9a59f4ddfa893edf18b5aa7df552b8af356
Author: Peter Clifton <pcjc2@xxxxxxxxx>
Date: Sun Nov 11 05:31:29 2007 +0000
Add .desktop file and icon to install
Packaged builds for .deb, .rpm etc.. should build with the new configure
option --disable-desktop-database-update, or delete the cache files placed
into the build directory. The icon cache files should also be deleted
before installing.
:100644 100644 6017506... c04b581... M Makefile.am
:000000 100644 0000000... d128920... A data/.gitignore
:000000 100644 0000000... a409120... A data/Makefile.am
:000000 100644 0000000... 49f5507... A data/geda-xgsch2pcb.desktop.in
:000000 100644 0000000... 0baf93c... A data/xgsch2pcb-48.png
:000000 100644 0000000... a7d9c6e... A data/xgsch2pcb.svg
:000000 100755 0000000... 8cc0e79... A icon-theme-installer
:100644 100644 27e4765... d33fbcf... M po/POTFILES.in
:100644 100644 1eb2be7... 09ac4d1... M po/geda-xgsch2pcb.pot
commit 649f9471386c378c0dc8145cc5a7cc1c3dbae515
Author: Peter Clifton <pcjc2@xxxxxxxxx>
Date: Sun Nov 11 05:30:40 2007 +0000
Add build infrastructure for translations and fix gettext invocation
A translation template is found at "po/geda-xgsch2pcb.pot", and can
be update by executing "make update-po" in the "po" directory.
:100644 100644 d2a59cd... 00a9e71... M .gitignore
:100644 100644 9506b6b... 6017506... M Makefile.am
:100644 100644 fce9bf9... 6ad1d47... M configure.ac
:100644 100644 8c78337... 1cdc776... M lib/xgsch2pcb/assistant.py
:100644 100644 9612965... 2f55f92... M lib/xgsch2pcb/config.py.in
:100644 100644 95be683... ae7414e... M lib/xgsch2pcb/gui.py
:100644 100644 66a670e... 8e07b26... M lib/xgsch2pcb/new_project_gui.py
:100644 100644 0303b49... 99d76b0... M lib/xgsch2pcb/pcbmanager.py
:000000 100644 0000000... 2ab8637... A po/.gitignore
:000000 100644 0000000... e69de29... A po/ChangeLog
:000000 100644 0000000... e69de29... A po/LINGUAS
:000000 100644 0000000... 27e4765... A po/POTFILES.in
:000000 100644 0000000... 236e168... A po/POTFILES.skip
:000000 100644 0000000... 1eb2be7... A po/geda-xgsch2pcb.pot
:000000 100644 0000000... 7b83435... A tools/intltool-extract.in
:000000 100644 0000000... e5671d7... A tools/intltool-merge.in
:000000 100644 0000000... bffd10f... A tools/intltool-update.in
:100644 100644 2c2d0bf... 406378c... M xgsch2pcb.in
commit d0e352691a5a330ccef662013875ebdfbfbea0a9
Author: Peter Clifton <pcjc2@xxxxxxxxx>
Date: Sun Nov 11 05:29:23 2007 +0000
Add .gitignore entry for generated toplevel config.py
:100644 100644 8aabc23... d2a59cd... M .gitignore
commit 1e35cf9eb5bd654f58e5b461ff073042204a8880
Author: Peter Clifton <pcjc2@xxxxxxxxx>
Date: Sun Nov 11 04:34:21 2007 +0000
Fix the "here documents" in the configure script to a non bashism
Fix FTBFS on non bash shells, such as "dash" which is default in Ubuntu.
:100644 100644 db228d9... fce9bf9... M configure.ac
=========
Changes
=========
commit 59c3a9a59f4ddfa893edf18b5aa7df552b8af356
Author: Peter Clifton <pcjc2@xxxxxxxxx>
Date: Sun Nov 11 05:31:29 2007 +0000
Add .desktop file and icon to install
Packaged builds for .deb, .rpm etc.. should build with the new configure
option --disable-desktop-database-update, or delete the cache files placed
into the build directory. The icon cache files should also be deleted
before installing.
diff --git a/Makefile.am b/Makefile.am
index 6017506..c04b581 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -18,7 +18,7 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
-SUBDIRS = po
+SUBDIRS = po data
bin_SCRIPTS = xgsch2pcb
@@ -40,7 +40,7 @@ INTLTOOL_FILES = tools/intltool-extract.in \
tools/intltool-update.in
EXTRA_DIST = xgsch2pcb.in lib/xgsch2pcb/config.py.in \
- $(INTLTOOL_FILES)
+ $(INTLTOOL_FILES) icon-theme-installer
CLEANFILES = xgsch2pcb config.py
DISTCLEANFILES = intltool-extract \
intltool-merge \
@@ -65,4 +65,4 @@ xgsch2pcb: xgsch2pcb.in Makefile
$(do_subst) < $(srcdir)/xgsch2pcb.in > $@
chmod +x xgsch2pcb
-
+DISTCHECK_CONFIGURE_FLAGS = --disable-update-desktop-database
diff --git a/data/.gitignore b/data/.gitignore
new file mode 100644
index 0000000..d128920
--- /dev/null
+++ b/data/.gitignore
@@ -0,0 +1,4 @@
+geda-xgsch2pcb.desktop
+Makefile
+Makefile.in
+*~
diff --git a/data/Makefile.am b/data/Makefile.am
new file mode 100644
index 0000000..a409120
--- /dev/null
+++ b/data/Makefile.am
@@ -0,0 +1,51 @@
+theme=hicolor
+themedir=$(datadir)/icons/$(theme)
+
+app_icon = xgsch2pcb
+
+app_icon_files = \
+ $(app_icon:%=%-48.png) \
+ $(app_icon:%=%.svg)
+# $(app_icon:%=%-16.png)
+# $(app_icon:%=%-22.png)
+# $(app_icon:%=%-24.png)
+# $(app_icon:%=%-32.png)
+#
+theme_icons = \
+ $(app_icon_files:%=apps,%)
+
+
+desktopdir=$(datadir)/applications
+desktop_in_files = geda-xgsch2pcb.desktop.in
+desktop_DATA = $(desktop_in_files:.desktop.in=.desktop)
+
+@INTLTOOL_DESKTOP_RULE@
+
+install_icon_exec = \
+ $(top_srcdir)/icon-theme-installer \
+ -t $(theme) \
+ -s $(srcdir) \
+ -d "x$(DESTDIR)" \
+ -b $(themedir) \
+ -m "$(mkinstalldirs)" \
+ -x "$(INSTALL_DATA)"
+
+install-data-local:
+ $(install_icon_exec) -i $(theme_icons)
+
+
+install-data-hook:
+if ENABLE_UPDATE_DESKTOP_DATABASE
+ $(UPDATE_DESKTOP_DATABASE) "$(DESTDIR)$(desktopdir)"
+endif
+
+uninstall-hook:
+if ENABLE_UPDATE_DESKTOP_DATABASE
+ $(UPDATE_DESKTOP_DATABASE) "$(DESTDIR)$(desktopdir)"
+endif
+ $(install_icon_exec) -u $(theme_icons)
+
+MAINTAINERCLEANFILES = *.log core FILE *~ Makefile.in
+DISTCLEANFILES = $(desktop_DATA)
+EXTRA_DIST = $(app_icon_files) \
+ $(desktop_in_files) $(desktop_DATA)
diff --git a/data/geda-xgsch2pcb.desktop.in b/data/geda-xgsch2pcb.desktop.in
new file mode 100644
index 0000000..49f5507
--- /dev/null
+++ b/data/geda-xgsch2pcb.desktop.in
@@ -0,0 +1,10 @@
+[Desktop Entry]
+Version=1.0
+Encoding=UTF-8
+GenericName=xgsch2pcb
+_Name=gEDA Schematic -> PCB Project
+_Comment=Create and edit electronics projects with xgsch2pcb
+Type=Application
+Exec=xgsch2pcb
+Icon=xgsch2pcb
+Categories=Engineering;Electronics
diff --git a/data/xgsch2pcb-48.png b/data/xgsch2pcb-48.png
new file mode 100644
index 0000000..0baf93c
Binary files /dev/null and b/data/xgsch2pcb-48.png differ
diff --git a/data/xgsch2pcb.svg b/data/xgsch2pcb.svg
new file mode 100644
index 0000000..a7d9c6e
--- /dev/null
+++ b/data/xgsch2pcb.svg
@@ -0,0 +1,1097 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="48"
+ height="48"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.45.1"
+ version="1.0"
+ sodipodi:docbase="/home/pcjc2/gedawork/tomazicons"
+ sodipodi:docname="xgsch2pcb.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ inkscape:export-filename="/home/pcjc2/gedawork/tomazicons/xgsch2pcb.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <defs
+ id="defs4">
+ <linearGradient
+ id="linearGradient6572">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop6574" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="1"
+ id="stop6576" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4700"
+ inkscape:collect="always">
+ <stop
+ id="stop4702"
+ offset="0"
+ style="stop-color:#2e3436;stop-opacity:1" />
+ <stop
+ id="stop4704"
+ offset="1"
+ style="stop-color:#888a85;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient4682">
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="0"
+ id="stop4684" />
+ <stop
+ style="stop-color:white;stop-opacity:0;"
+ offset="1"
+ id="stop4686" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3415">
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="0"
+ id="stop3417" />
+ <stop
+ id="stop3423"
+ offset="0.5"
+ style="stop-color:black;stop-opacity:1;" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop3419" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3399">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop3401" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop3403" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient2919">
+ <stop
+ style="stop-color:#d3d7cf;stop-opacity:1;"
+ offset="0"
+ id="stop2921" />
+ <stop
+ style="stop-color:#d3d7cf;stop-opacity:0;"
+ offset="1"
+ id="stop2923" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4700"
+ id="linearGradient6520"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(122.86105,13.397466)"
+ x1="5.6568546"
+ y1="53.320892"
+ x2="4"
+ y2="16.003418" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3399"
+ id="radialGradient6522"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,2.166667,0,-46.08333)"
+ cx="6"
+ cy="39.5"
+ fx="6"
+ fy="39.5"
+ r="3" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3399"
+ id="radialGradient6524"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,2.166667,-45,-125.0833)"
+ cx="6"
+ cy="39.5"
+ fx="6"
+ fy="39.5"
+ r="3" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3415"
+ id="linearGradient6526"
+ gradientUnits="userSpaceOnUse"
+ x1="18"
+ y1="46"
+ x2="18"
+ y2="32.999397" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2919"
+ id="linearGradient6528"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.489708,120.86105,-9.1547942)"
+ x1="11.949747"
+ y1="40.664974"
+ x2="94.364037"
+ y2="47.897068" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4682"
+ id="linearGradient6530"
+ gradientUnits="userSpaceOnUse"
+ x1="6.7928934"
+ y1="32.963203"
+ x2="7.9215727"
+ y2="54.448856" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6572"
+ id="linearGradient6582"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(77.752564,16.900603)"
+ x1="83.607964"
+ y1="28.76277"
+ x2="69.426666"
+ y2="19.390785" />
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask6578">
+ <rect
+ style="fill:url(#linearGradient6582);fill-opacity:1;stroke:none;stroke-width:31.20000076;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect6580"
+ width="42.556099"
+ height="39.572861"
+ x="131.75256"
+ y="15.32774" />
+ </mask>
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#afafaf"
+ borderopacity="1"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="10.113465"
+ inkscape:cx="23.518046"
+ inkscape:cy="21.614126"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ width="48px"
+ height="48px"
+ gridspacingx="0.5px"
+ gridspacingy="0.5px"
+ inkscape:showpageshadow="true"
+ borderlayer="true"
+ gridempspacing="2"
+ inkscape:window-width="1033"
+ inkscape:window-height="797"
+ inkscape:window-x="162"
+ inkscape:window-y="137"
+ showgrid="true"
+ showborder="true"
+ showguides="true"
+ inkscape:guide-bbox="true"
+ inkscape:grid-points="true"
+ inkscape:grid-bbox="false"
+ inkscape:object-paths="false"
+ gridtolerance="28.3" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:creator>
+ <cc:Agent>
+ <dc:title>Lapo Calamandrei</dc:title>
+ </cc:Agent>
+ </dc:creator>
+ <cc:license
+ rdf:resource="http://creativecommons.org/licenses/GPL/2.0/" />
+ <dc:title>Text editor</dc:title>
+ </cc:Work>
+ <cc:License
+ rdf:about="http://creativecommons.org/licenses/GPL/2.0/">
+ <cc:permits
+ rdf:resource="http://web.resource.org/cc/Reproduction" />
+ <cc:permits
+ rdf:resource="http://web.resource.org/cc/Distribution" />
+ <cc:requires
+ rdf:resource="http://web.resource.org/cc/Notice" />
+ <cc:permits
+ rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
+ <cc:requires
+ rdf:resource="http://web.resource.org/cc/ShareAlike" />
+ <cc:requires
+ rdf:resource="http://web.resource.org/cc/SourceCode" />
+ </cc:License>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Livello 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-70.308665,-15.420814)">
+ <g
+ id="g4691"
+ inkscape:label="base"
+ style="display:inline"
+ transform="translate(206.42951,99.974912)" />
+ <g
+ id="layer6"
+ inkscape:label="Shadow"
+ transform="translate(175.11105,9.7452988)" />
+ <g
+ id="layer5"
+ inkscape:label="Text"
+ style="display:inline"
+ transform="translate(175.11105,9.7452988)" />
+ <g
+ id="g4626">
+ <g
+ transform="translate(0.2055256,2.987116)"
+ id="g2404">
+ <g
+ id="g6764"
+ transform="translate(56.960042,-0.5)"
+ style="opacity:1">
+ <g
+ clip-path="none"
+ mask="none"
+ transform="translate(-108.69993,0.5467708)"
+ id="g6382">
+ <path
+ style="fill:#4e9a06;fill-opacity:1;stroke:url(#linearGradient6520);stroke-width:0.99999952;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 131.12882,23.920814 L 159.59326,23.920814 C 160.5726,23.920814 161.29005,24.673489 161.36103,25.688581 L 163.29853,53.397466 L 163.36105,56.897466 L 127.36105,56.897466 L 127.36105,53.397466 L 129.36105,25.688581 C 129.43112,24.71773 130.14947,23.920814 131.12882,23.920814 z "
+ id="path2997"
+ sodipodi:nodetypes="cczcccczc" />
+ <g
+ id="g5565"
+ transform="translate(129.54855,-32.641686)">
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5567"
+ d="M 10,73 L 10,73"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5569"
+ d="M 13,73 L 13,73"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5571"
+ d="M 16,73 L 16,73"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5573"
+ d="M 19,73 L 19,73"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5575"
+ d="M 10,70 L 10,70"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5577"
+ d="M 13,70 L 13,70"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5579"
+ d="M 16,70 L 16,70"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5581"
+ d="M 19,70 L 19,70"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5583"
+ d="M 10,67 L 10,67"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5585"
+ d="M 13,67 L 13,67"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5587"
+ d="M 16,67 L 16,67"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5589"
+ d="M 19,67 L 19,67"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5591"
+ d="M 10,64 L 10,64"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5593"
+ d="M 13,64 L 13,64"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5595"
+ d="M 16,64 L 16,64"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5597"
+ d="M 19,64 L 19,64"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5599"
+ d="M 22,73 L 22,73"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5601"
+ d="M 25,73 L 25,73"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5603"
+ d="M 28,73 L 28,73"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5605"
+ d="M 31,73 L 31,73"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5607"
+ d="M 22,70 L 22,70"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5609"
+ d="M 25,70 L 25,70"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5611"
+ d="M 28,70 L 28,70"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5613"
+ d="M 31,70 L 31,70"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5615"
+ d="M 22,67 L 22,67"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5617"
+ d="M 25,67 L 25,67"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5619"
+ d="M 28,67 L 28,67"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5621"
+ d="M 31,67 L 31,67"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5623"
+ d="M 22,64 L 22,64"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5625"
+ d="M 25,64 L 25,64"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5627"
+ d="M 28,64 L 28,64"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5629"
+ d="M 31,64 L 31,64"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5631"
+ d="M 10,61 L 10,61"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5633"
+ d="M 13,61 L 13,61"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5635"
+ d="M 16,61 L 16,61"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5637"
+ d="M 19,61 L 19,61"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5639"
+ d="M 10,58 L 10,58"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5641"
+ d="M 13,58 L 13,58"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5643"
+ d="M 16,58 L 16,58"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5645"
+ d="M 19,58 L 19,58"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5647"
+ d="M 22,61 L 22,61"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5649"
+ d="M 25,61 L 25,61"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5651"
+ d="M 28,61 L 28,61"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5653"
+ d="M 31,61 L 31,61"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5655"
+ d="M 22,58 L 22,58"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5657"
+ d="M 25,58 L 25,58"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5659"
+ d="M 28,58 L 28,58"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5661"
+ d="M 10,85 L 10,85"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5663"
+ d="M 13,85 L 13,85"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5665"
+ d="M 16,85 L 16,85"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5667"
+ d="M 19,85 L 19,85"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5669"
+ d="M 10,82 L 10,82"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5671"
+ d="M 13,82 L 13,82"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5673"
+ d="M 16,82 L 16,82"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5675"
+ d="M 19,82 L 19,82"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5677"
+ d="M 10,79 L 10,79"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5679"
+ d="M 13,79 L 13,79"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5681"
+ d="M 16,79 L 16,79"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5683"
+ d="M 19,79 L 19,79"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5685"
+ d="M 10,76 L 10,76"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5687"
+ d="M 13,76 L 13,76"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5689"
+ d="M 16,76 L 16,76"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5691"
+ d="M 19,76 L 19,76"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5693"
+ d="M 22,85 L 22,85"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5695"
+ d="M 25,85 L 25,85"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5697"
+ d="M 28,85 L 28,85"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5699"
+ d="M 31,85 L 31,85"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5701"
+ d="M 22,82 L 22,82"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5703"
+ d="M 25,82 L 25,82"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5705"
+ d="M 28,82 L 28,82"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5707"
+ d="M 31,82 L 31,82"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5709"
+ d="M 22,79 L 22,79"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5711"
+ d="M 25,79 L 25,79"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5713"
+ d="M 28,79 L 28,79"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5715"
+ d="M 31,79 L 31,79"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5717"
+ d="M 22,76 L 22,76"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5719"
+ d="M 25,76 L 25,76"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5721"
+ d="M 28,76 L 28,76"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5723"
+ d="M 31,76 L 31,76"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5725"
+ d="M 4,73 L 4,73"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5727"
+ d="M 7,73 L 7,73"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5729"
+ d="M 4,70 L 4,70"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5731"
+ d="M 7,70 L 7,70"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5733"
+ d="M 4,67 L 4,67"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5735"
+ d="M 7,67 L 7,67"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5737"
+ d="M 4,64 L 4,64"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5739"
+ d="M 7,64 L 7,64"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5741"
+ d="M 4,61 L 4,61"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5743"
+ d="M 7,61 L 7,61"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5745"
+ d="M 4,58 L 4,58"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5747"
+ d="M 7,58 L 7,58"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5749"
+ d="M 4,85 L 4,85"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5751"
+ d="M 7,85 L 7,85"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5753"
+ d="M 4,82 L 4,82"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5755"
+ d="M 7,82 L 7,82"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5757"
+ d="M 4,79 L 4,79"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5759"
+ d="M 7,79 L 7,79"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5761"
+ d="M 4,76 L 4,76"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5763"
+ d="M 7,76 L 7,76"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5765"
+ d="M 1,73 L 1,73"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5767"
+ d="M 1,70 L 1,70"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5769"
+ d="M 1,67 L 1,67"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5771"
+ d="M 1,64 L 1,64"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5773"
+ d="M 1,61 L 1,61"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5775"
+ d="M 1,85 L 1,85"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5777"
+ d="M 1,82 L 1,82"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5779"
+ d="M 1,79 L 1,79"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path5781"
+ d="M 1,76 L 1,76"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#316400;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ </g>
+ <g
+ id="g2999"
+ transform="matrix(1.0416677,0,0,0.4579337,121.92355,37.809093)"
+ style="opacity:0.4">
+ <rect
+ y="33"
+ x="3"
+ height="13"
+ width="3"
+ id="rect3001"
+ style="opacity:1;fill:url(#radialGradient6522);fill-opacity:1;stroke:none;stroke-width:1.00199997;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1" />
+ <rect
+ transform="scale(-1,-1)"
+ y="-46"
+ x="-42"
+ height="13"
+ width="3"
+ id="rect3003"
+ style="opacity:1;fill:url(#radialGradient6524);fill-opacity:1;stroke:none;stroke-width:1.00199997;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1" />
+ <rect
+ y="33"
+ x="6"
+ height="13"
+ width="33"
+ id="rect3005"
+ style="opacity:1;fill:url(#linearGradient6526);fill-opacity:1;stroke:none;stroke-width:1.00199997;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1" />
+ </g>
+ <rect
+ style="fill:url(#linearGradient6528);fill-opacity:1;stroke:none;stroke-width:1.00199997;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1"
+ id="rect3009"
+ width="35"
+ height="3.0103984"
+ x="127.86104"
+ y="53.397465" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#c17d11;stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 127.36105,56.897466 L 163.36105,56.897466"
+ id="path3013"
+ sodipodi:nodetypes="cc" />
+ <g
+ mask="none"
+ id="g5792"
+ transform="matrix(1,0,9.7841434e-2,1,159.38974,100.11879)">
+ <path
+ style="color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#5fc500;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:block;overflow:visible"
+ d="M -7.911735,-72.09947 L -4.2637154,-72.144203 L -0.98581343,-68.498826 L -1.726049,-61.118607"
+ id="path2828"
+ sodipodi:nodetypes="ccc" />
+ <path
+ style="color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#5fc500;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:block;overflow:visible"
+ d="M 1.1923678,-61.154394 L 2.0806498,-70.010656 L 0.1139084,-72.197882"
+ id="path2830" />
+ <path
+ style="color:#000000;fill:#4e9a06;fill-opacity:1;fill-rule:nonzero;stroke:#5fc500;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:block;overflow:visible"
+ d="M 4.1107838,-61.19018 L 5.1471128,-71.522486 L 4.4915318,-72.251562"
+ id="path2832" />
+ <path
+ style="color:#000000;fill:#4e9a06;fill-opacity:1;fill-rule:nonzero;stroke:#5fc500;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:block;overflow:visible"
+ d="M 7.0291988,-61.225967 L 8.1395518,-72.296295"
+ id="path2890" />
+ <path
+ style="color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#5fc500;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:block;overflow:visible"
+ d="M -2.5403079,-53.000368 L -2.8364022,-50.04828 L -5.2472848,-47.807374 L -10.354512,-47.744748"
+ id="path2910" />
+ <path
+ style="color:#000000;fill:#4e9a06;fill-opacity:1;fill-rule:nonzero;stroke:#5fc500;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:block;overflow:visible"
+ d="M 0.3781084,-53.036154 L -0.1400566,-47.87"
+ id="path2912" />
+ <path
+ sodipodi:nodetypes="cccc"
+ style="color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#5fc500;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:block;overflow:visible"
+ d="M 3.2965248,-53.07194 L 3.0004298,-50.119853 L 4.9671708,-47.932626 L 7.3302275,-47.744747"
+ id="path2914" />
+ <path
+ sodipodi:nodetypes="cc"
+ style="color:#000000;fill:#4e9a06;fill-opacity:1;fill-rule:nonzero;stroke:#5fc500;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:block;overflow:visible"
+ d="M 6.2149398,-53.107727 L 7.5260988,-51.649575"
+ id="path2916" />
+ <path
+ style="color:#000000;fill:#5fc500;fill-opacity:1;fill-rule:nonzero;stroke:#5fc500;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:block;overflow:visible"
+ d="M -8.1338058,-69.885404 L -5.2153901,-69.92119 L -3.248649,-67.733963 L -4.8771671,-51.497483 L -6.484422,-50.003547 L -10.132442,-49.958814 L -8.1338058,-69.885404 z "
+ id="path2918"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ sodipodi:nodetypes="cccccccccccc"
+ id="rect2920"
+ d="M 7.5370152,-63.943032 L -1.6810415,-63.829998 C -3.0397431,-63.813338 -4.2603778,-62.695321 -4.3959852,-61.343303 L -5.2629909,-52.699175 C -5.3985985,-51.347154 -4.3995076,-50.256359 -3.0408059,-50.27302 L 7.0748311,-50.244747 M 7.1726725,-51.244747 L -2.9410067,-51.268027 C -3.76135,-51.257968 -4.3449419,-51.895127 -4.2630661,-52.711436 L -3.3960604,-61.355564 C -3.3141848,-62.171872 -2.601184,-62.824931 -1.7808407,-62.834991 L 7.437216,-62.948025"
+ style="color:#000000;fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;marker:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:block;overflow:visible" />
+ <path
+ id="path2894"
+ d="M -1.726049,-61.118607 L -1.8740961,-59.642563"
+ style="color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#babdb6;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:block;overflow:visible" />
+ <path
+ id="path2896"
+ d="M 1.1923678,-61.154394 L 1.0443198,-59.67835"
+ style="color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#babdb6;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:block;overflow:visible" />
+ <path
+ id="path2898"
+ d="M 4.1107838,-61.19018 L 3.9627358,-59.714137"
+ style="color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#babdb6;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:block;overflow:visible" />
+ <path
+ id="path2900"
+ d="M 7.0291988,-61.225967 L 6.8811508,-59.749923"
+ style="color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#babdb6;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:block;overflow:visible" />
+ <path
+ id="path2902"
+ d="M 6.3629868,-54.58377 L 6.2149398,-53.107727"
+ style="color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#babdb6;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:block;overflow:visible" />
+ <path
+ id="path2904"
+ d="M 3.4445718,-54.547983 L 3.2965248,-53.07194"
+ style="color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#babdb6;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:block;overflow:visible" />
+ <path
+ id="path2906"
+ d="M 0.5261554,-54.512197 L 0.3781084,-53.036154"
+ style="color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#babdb6;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:block;overflow:visible" />
+ <path
+ id="path2908"
+ d="M -2.3922609,-54.476411 L -2.5403079,-53.000368"
+ style="color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#babdb6;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:block;overflow:visible" />
+ </g>
+ <path
+ sodipodi:type="inkscape:offset"
+ inkscape:radius="-0.9722718"
+ inkscape:original="M 8.28125 10.53125 C 7.301907 10.53125 6.570075 11.310399 6.5 12.28125 L 4.5 40 L 4.5 43.5 L 40.5 43.5 L 40.4375 40 L 38.5 12.28125 C 38.429021 11.266158 37.698095 10.53125 36.71875 10.53125 L 8.28125 10.53125 z "
+ style="fill:none;fill-opacity:1;stroke:url(#linearGradient6530);stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="path3011"
+ d="M 8.28125,11.5 C 7.8175892,11.5 7.5065211,11.820452 7.46875,12.34375 L 5.46875,40 L 5.46875,40.0625 L 5.46875,42.53125 L 39.5,42.53125 L 39.46875,40.0625 L 39.46875,40.03125 L 37.53125,12.34375 C 37.490391,11.75941 37.211695,11.5 36.71875,11.5 L 8.28125,11.5 z "
+ transform="translate(122.86105,13.397466)" />
+ </g>
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path6752"
+ d="M 21.933665,25.983314 L 19.933665,53.983314 L 37.433665,53.983314 L 35.933665,25.483314 L 21.933665,25.983314 z "
+ style="fill:#ffffff;fill-opacity:0.72463768;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ transform="translate(70.308665,15.420814)"
+ id="path6762"
+ d="M -33,38 L -34.559844,11"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" />
+ <g
+ transform="matrix(1,0,-6.1460228e-2,1,-42.299782,-19.079186)"
+ id="g6711">
+ <g
+ transform="translate(-1.254175,29.723237)"
+ id="g6673">
+ <path
+ sodipodi:nodetypes="cc"
+ id="path6675"
+ d="M 74.856803,34.945737 L 70.00418,34.945737"
+ style="color:#000000;fill:#4e9a06;fill-opacity:0.75;fill-rule:evenodd;stroke:#204a87;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path6677"
+ d="M 74.856803,30.988845 L 74.856803,38.902628"
+ style="color:#000000;fill:#4e9a06;fill-opacity:0.75;fill-rule:evenodd;stroke:#4e9a06;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path6679"
+ d="M 78.900656,38.902628 L 78.900656,41.276763"
+ style="color:#000000;fill:#4e9a06;fill-opacity:0.75;fill-rule:evenodd;stroke:#204a87;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path6681"
+ d="M 78.900656,38.902628 L 74.856803,36.528493"
+ style="color:#000000;fill:#4e9a06;fill-opacity:0.75;fill-rule:evenodd;stroke:#4e9a06;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path6683"
+ d="M 80.518197,41.276763 L 77.283114,41.276763"
+ style="color:#000000;fill:#4e9a06;fill-opacity:0.75;fill-rule:evenodd;stroke:#4e9a06;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path6685"
+ d="M 78.900656,30.988845 L 78.900656,26.240574"
+ style="color:#000000;fill:#4e9a06;fill-opacity:0.75;fill-rule:evenodd;stroke:#204a87;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path6687"
+ d="M 78.900656,30.988845 L 74.856803,33.36298"
+ style="color:#000000;fill:#4e9a06;fill-opacity:0.75;fill-rule:evenodd;stroke:#4e9a06;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path6689"
+ d="M 78.900656,18.326791 L 78.900656,20.700926"
+ style="color:#000000;fill:#4e9a06;fill-opacity:0.75;fill-rule:evenodd;stroke:#204a87;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path6691"
+ d="M 79.709426,26.240574 L 78.091886,26.240574 L 78.091886,20.700926 L 79.709426,20.700926 L 79.709426,26.240574"
+ style="color:#000000;fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#4e9a06;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path6693"
+ d="M 78.900656,28.614709 L 85.37082,28.614709"
+ style="color:#000000;fill:#4e9a06;fill-opacity:0.75;fill-rule:evenodd;stroke:#204a87;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path6695"
+ d="M 70.00418,21.492304 L 74.048033,21.492304"
+ style="color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#888a85;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path6697"
+ d="M 70.00418,23.075061 L 74.048033,23.075061"
+ style="color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#888a85;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path6699"
+ d="M 81.326967,34.154358 L 85.37082,34.154358"
+ style="color:#000000;fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#888a85;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path6701"
+ d="M 81.326967,35.737115 L 85.37082,35.737115"
+ style="color:#000000;fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#888a85;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path6703"
+ d="M 78.900656,38.902628 L 77.13147,36.676876 L 76.221604,38.605861 L 78.900656,38.902628 z "
+ style="color:#000000;fill:#4e9a06;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+ </g>
+ <path
+ transform="translate(-13.425451,28.5)"
+ d="M 83 36 A 1 1 0 1 1 81,36 A 1 1 0 1 1 83 36 z"
+ sodipodi:ry="1"
+ sodipodi:rx="1"
+ sodipodi:cy="36"
+ sodipodi:cx="82"
+ id="path6705"
+ style="fill:#a40000;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ sodipodi:type="arc" />
+ <path
+ transform="translate(2.250005,22.206252)"
+ d="M 83 36 A 1 1 0 1 1 81,36 A 1 1 0 1 1 83 36 z"
+ sodipodi:ry="1"
+ sodipodi:rx="1"
+ sodipodi:cy="36"
+ sodipodi:cx="82"
+ id="path6707"
+ style="fill:#a40000;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ sodipodi:type="arc" />
+ <path
+ transform="translate(-4.40813,11.985281)"
+ d="M 83 36 A 1 1 0 1 1 81,36 A 1 1 0 1 1 83 36 z"
+ sodipodi:ry="1"
+ sodipodi:rx="1"
+ sodipodi:cy="36"
+ sodipodi:cx="82"
+ id="path6709"
+ style="fill:#a40000;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ sodipodi:type="arc" />
+ </g>
+ </g>
+ </g>
+ <g
+ id="g5303"
+ transform="matrix(0.896386,0,0,0.9891442,9.2126594,-25.95452)"
+ style="fill:#cc0000;fill-opacity:1;stroke:#ffe9e9;stroke-opacity:1">
+ <path
+ sodipodi:nodetypes="ccccccccczc"
+ d="M 99.394682,56.308139 L 97.1635,57.319114 L 103.29925,60.352039 L 103.85448,54.314097 L 103.85705,54.286189 L 101.62586,55.297164 C 95.490118,47.209365 91.832211,48.748499 91.21875,48.90625 C 88.764906,49.537252 85.465477,52.919866 83.833209,57.549302 L 86.007592,58.330089 C 87.554913,53.941579 90.435785,51.69236 92.143342,51.253264 C 93.850899,50.814168 96.605705,52.26424 99.394682,56.308139 z "
+ style="fill:#cc0000;fill-opacity:1;fill-rule:evenodd;stroke:#ffe9e9;stroke-width:1.06199551;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1"
+ id="path5305" />
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/icon-theme-installer b/icon-theme-installer
new file mode 100755
index 0000000..8cc0e79
--- /dev/null
+++ b/icon-theme-installer
@@ -0,0 +1,181 @@
+#!/bin/bash
+
+# icon-theme-installer
+# Copyright (C) 2006 Novell, Inc.
+# Written by Aaron Bockover <abock@xxxxxxxxx>
+# Licensed under the MIT/X11 license
+#
+# Modified by Peter Clifton to allow icons with numerals in the filename
+#
+# This script is meant to be invoked from within a Makefile/Makefile.am
+# in the install-data-local and uninstall-data sections. It handles the
+# task of properly installing icons into the icon theme. It requires a
+# few arguments to set up its environment, and a list of files to be
+# installed. The format of the file list is critical:
+#
+# <category>,<local-src-file-name>
+#
+# apps,music-player-banshee.svg
+# apps,music-player-banshee-16.png
+# apps,music-player-banshee-22.png
+#
+# <category> is the icon theme category, for instance, apps, devices,
+# actions, emblems...
+#
+# <local-src-file-name> must have a basename in the form of:
+#
+# proper-theme-name[-<SIZE>].<EXTENSION>
+#
+# Where <SIZE> should be either nothing, which will default to scalable
+# or \-[0-9]{2}, which will expand to <SIZE>x<SIZE>. For example:
+#
+# music-player-banshee-16.png
+#
+# The <SIZE> here is -16 and will expand to 16x16 per the icon theme spec
+#
+# What follows is an example Makefile.am for icon theme installation:
+#
+# ---------------
+# theme=hicolor
+# themedir=$(datadir)/icons/$(theme)
+# theme_icons = \
+# apps,music-player-banshee.svg \
+# apps,music-player-banshee-16.png \
+# apps,music-player-banshee-22.png \
+# apps,music-player-banshee-24.png \
+# apps,music-player-banshee-32.png
+#
+# install_icon_exec = $(top_srcdir)/build/icon-theme-installer -t $(theme) -s $(srcdir) -d "x$(DESTDIR)" -b $(themedir) -m "$(mkinstalldirs)" -x "$(INSTALL_DATA)"
+# install-data-local:
+# $(install_icon_exec) -i $(theme_icons)
+#
+# uninstall-hook:
+# $(install_icon_exec) -u $(theme_icons)
+#
+# MAINTAINERCLEANFILES = Makefile.in
+# EXTRA_DIST = $(wildcard *.svg *.png)
+# ---------------
+#
+# Arguments to this program:
+#
+# -i : Install
+# -u : Uninstall
+# -t <theme> : Theme name (hicolor)
+# -b <dir> : Theme installation dest directory [x$(DESTDIR)] - Always prefix
+# this argument with x; it will be stripped but will act as a
+# placeholder for zero $DESTDIRs (only set by packagers)
+# -d <dir> : Theme installation directory [$(hicolordir)]
+# -s <dir> : Source directory [$(srcdir)]
+# -m <exec> : Command to exec for directory creation [$(mkinstalldirs)]
+# -x <exec> : Command to exec for single file installation [$(INSTALL_DATA)]
+# <remainging> : All remainging should be category,filename pairs
+
+while getopts "iut:b:d:s:m:x:" flag; do
+ case "$flag" in
+ i) INSTALL=yes ;;
+ u) UNINSTALL=yes ;;
+ t) THEME_NAME=$OPTARG ;;
+ d) INSTALL_DEST_DIR=${OPTARG##x} ;;
+ b) INSTALL_BASE_DIR=$OPTARG ;;
+ s) SRC_DIR=$OPTARG ;;
+ m) MKINSTALLDIRS_EXEC=$OPTARG ;;
+ x) INSTALL_DATA_EXEC=$OPTARG ;;
+ esac
+done
+
+shift $(($OPTIND - 1))
+
+if test "x$INSTALL" = "xyes" -a "x$UNINSTALL" = "xyes"; then
+ echo "Cannot pass both -i and -u"
+ exit 1
+elif test "x$INSTALL" = "x" -a "x$UNINSTALL" = "x"; then
+ echo "Must path either -i or -u"
+ exit 1
+fi
+
+if test -z "$THEME_NAME"; then
+ echo "Theme name required (-t hicolor)"
+ exit 1
+fi
+
+if test -z "$INSTALL_BASE_DIR"; then
+ echo "Base theme directory required [-d \$(hicolordir)]"
+ exit 1
+fi
+
+if test ! -x $(echo "$MKINSTALLDIRS_EXEC" | cut -f1 -d' '); then
+ echo "Cannot find '$MKINSTALLDIRS_EXEC'; You probably want to pass -m \$(mkinstalldirs)"
+ exit 1
+fi
+
+if test ! -x $(echo "$INSTALL_DATA_EXEC" | cut -f1 -d' '); then
+ echo "Cannot find '$INSTALL_DATA_EXEC'; You probably want to pass -x \$(INSTALL_DATA)"
+ exit 1
+fi
+
+if test -z "$SRC_DIR"; then
+ SRC_DIR=.
+fi
+
+for icon in $@; do
+ size=$(echo $icon | sed -n "s/.*-\([0-9]*\).*/\1/p")
+ category=$(echo $icon | cut -d, -f1)
+ build_name=$(echo $icon | cut -d, -f2)
+ install_name=$(echo $build_name | sed "s/-[0-9]\+//g")
+ install_name=$(basename $install_name)
+
+ if test -z $size; then
+ size=scalable;
+ else
+ size=${size}x${size};
+ fi
+
+ install_dir=${INSTALL_DEST_DIR}${INSTALL_BASE_DIR}/$size/$category
+ install_path=$install_dir/$install_name
+
+ if test "x$INSTALL" = "xyes"; then
+ echo "Installing $size $install_name into $THEME_NAME icon theme"
+
+ $($MKINSTALLDIRS_EXEC $install_dir) || {
+ echo "Failed to create directory $install_dir"
+ exit 1
+ }
+
+ $($INSTALL_DATA_EXEC $SRC_DIR/$build_name $install_path) || {
+ echo "Failed to install $SRC_DIR/$build_name into $install_path"
+ exit 1
+ }
+
+ if test ! -e $install_path; then
+ echo "Failed to install $SRC_DIR/$build_name into $install_path"
+ exit 1
+ fi
+ else
+ if test -e $install_path; then
+ echo "Removing $size $install_name from $THEME_NAME icon theme"
+
+ rm $install_path || {
+ echo "Failed to remove $install_path"
+ exit 1
+ }
+ fi
+ fi
+done
+
+if test "x$INSTALL" = "xyes"; then
+ gtk_update_icon_cache_bin="$((which gtk-update-icon-cache || echo /opt/gnome/bin/gtk-update-icon-cache)2>/dev/null)"
+ gtk_update_icon_cache="$gtk_update_icon_cache_bin -f -t $INSTALL_BASE_DIR"
+
+ if test -z "$INSTALL_DEST_DIR"; then
+ if test -x $gtk_update_icon_cache_bin; then
+ echo "Updating GTK icon cache"
+ $gtk_update_icon_cache
+ else
+ echo "*** Icon cache not updated. Could not execute $gtk_update_icon_cache_bin"
+ fi
+ else
+ echo "*** Icon cache not updated. After install, run this:"
+ echo "*** $gtk_update_icon_cache"
+ fi
+fi
+
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 27e4765..d33fbcf 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -1,3 +1,4 @@
lib/xgsch2pcb/gui.py
lib/xgsch2pcb/new_project_gui.py
lib/xgsch2pcb/pcbmanager.py
+data/geda-xgsch2pcb.desktop.in
diff --git a/po/geda-xgsch2pcb.pot b/po/geda-xgsch2pcb.pot
index 1eb2be7..09ac4d1 100644
--- a/po/geda-xgsch2pcb.pot
+++ b/po/geda-xgsch2pcb.pot
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2007-11-10 23:41+0000\n"
+"POT-Creation-Date: 2007-11-10 23:44+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@xxxxxx>\n"
@@ -296,3 +296,11 @@ msgstr ""
#: ../lib/xgsch2pcb/pcbmanager.py:313
msgid "********DONE UPDATING********"
msgstr ""
+
+#: ../data/geda-xgsch2pcb.desktop.in.h:1
+msgid "Schematic -> PCB Project"
+msgstr ""
+
+#: ../data/geda-xgsch2pcb.desktop.in.h:2
+msgid "gEDA xgschp2cb project manager"
+msgstr ""
commit 649f9471386c378c0dc8145cc5a7cc1c3dbae515
Author: Peter Clifton <pcjc2@xxxxxxxxx>
Date: Sun Nov 11 05:30:40 2007 +0000
Add build infrastructure for translations and fix gettext invocation
A translation template is found at "po/geda-xgsch2pcb.pot", and can
be update by executing "make update-po" in the "po" directory.
diff --git a/.gitignore b/.gitignore
index d2a59cd..00a9e71 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,3 +7,6 @@ configure
config.log
config.status
config.py
+intltool-extract
+intltool-merge
+intltool-update
diff --git a/Makefile.am b/Makefile.am
index 9506b6b..6017506 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -18,6 +18,8 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+SUBDIRS = po
+
bin_SCRIPTS = xgsch2pcb
pkglib_PYTHON = lib/xgsch2pcb/pcbmanager.py \
@@ -32,9 +34,18 @@ nodist_pkglib_PYTHON = config.py
dist_noinst_SCRIPTS = tools/pygettext.py \
tools/msgfmt.py
-
-EXTRA_DIST = xgsch2pcb.in lib/xgsch2pcb/config.py.in
+
+INTLTOOL_FILES = tools/intltool-extract.in \
+ tools/intltool-merge.in \
+ tools/intltool-update.in
+
+EXTRA_DIST = xgsch2pcb.in lib/xgsch2pcb/config.py.in \
+ $(INTLTOOL_FILES)
CLEANFILES = xgsch2pcb config.py
+DISTCLEANFILES = intltool-extract \
+ intltool-merge \
+ intltool-update \
+ po/.intltool-merge-cache
templatesdir = @templatesdir@
diff --git a/configure.ac b/configure.ac
index fce9bf9..6ad1d47 100644
--- a/configure.ac
+++ b/configure.ac
@@ -36,7 +36,7 @@ GTK_WANTVERSION=2.8
# Checks for programs.
AC_PROG_INSTALL
AM_PATH_PYTHON($PYTHON_WANTVERSION)
-
+IT_PROG_INTLTOOL(0.35.0)
AC_DEFUN([AC_PYTHON_MODULE],[
AC_MSG_CHECKING([for python module $1])
@@ -52,6 +52,39 @@ AC_DEFUN([AC_PYTHON_MODULE],[
])
+############################################################################
+# Update desktop database utility start
+#
+
+AC_ARG_ENABLE(update-desktop-database,
+ AC_HELP_STRING([--disable-update-dektop-database],
+ [do not update desktop file database after installation]),,
+ enable_update_desktop_database=yes)
+
+AM_CONDITIONAL(ENABLE_UPDATE_DESKTOP_DATABASE,
+ test x$enable_update_desktop_database = xyes)
+
+if test x$enable_update_desktop_database = xyes ; then
+ AC_PATH_PROG(UPDATE_DESKTOP_DATABASE, [update-desktop-database], no)
+ if test $UPDATE_DESKTOP_DATABASE = no; then
+ AC_MSG_ERROR([Cannot find update-desktop-database, make sure it is installed and in your PATH, or configure with --disable-update-desktop-database])
+ fi
+fi
+
+#
+# Update mime database utility end
+############################################################################
+
+# Set USE_NLS
+AM_NLS
+
+# Find GMSGFMT
+AC_PATH_PROG(GMSGFMT, msgfmt)
+
+# Set package name for translations
+GETTEXT_PACKAGE=$PACKAGE
+AC_SUBST(GETTEXT_PACKAGE)
+
##########################################################################
# Command line flags start
#
@@ -138,6 +171,9 @@ if test $interpval == 'no'; then
AC_MSG_ERROR([Your system must support the shell bang syntax]);
fi
-AC_CONFIG_FILES([Makefile])
+AC_CONFIG_FILES([Makefile
+ data/Makefile
+ po/Makefile.in
+ po/Makefile])
AC_OUTPUT
diff --git a/lib/xgsch2pcb/assistant.py b/lib/xgsch2pcb/assistant.py
index 8c78337..1cdc776 100644
--- a/lib/xgsch2pcb/assistant.py
+++ b/lib/xgsch2pcb/assistant.py
@@ -22,10 +22,6 @@
import gtk, gtk.gdk, pango, gobject
-import gettext
-t = gettext.translation('xgsch2pcb', fallback=True)
-_ = t.ugettext
-
ASSISTANT_PAGE_CONTENT = 0
ASSISTANT_PAGE_INTRO = 1
diff --git a/lib/xgsch2pcb/config.py.in b/lib/xgsch2pcb/config.py.in
index 9612965..2f55f92 100644
--- a/lib/xgsch2pcb/config.py.in
+++ b/lib/xgsch2pcb/config.py.in
@@ -24,4 +24,4 @@ VERSION="@VERSION@"
prefix="@prefix@"
pkglibdir="@pkglibdir@"
templatesdir="@templatesdir@"
-
+localedir="@prefix@/share/locale"
diff --git a/lib/xgsch2pcb/gui.py b/lib/xgsch2pcb/gui.py
index 95be683..ae7414e 100644
--- a/lib/xgsch2pcb/gui.py
+++ b/lib/xgsch2pcb/gui.py
@@ -21,13 +21,14 @@ import gtk, gtk.gdk, gobject, os, sys, commands, shutil
from stat import *
from subprocess import *
+import config
+
# i18n
import gettext
-t = gettext.translation('xgsch2pcb', fallback=True)
+t = gettext.translation(config.PACKAGE, config.localedir, fallback=True)
_ = t.ugettext
# xgsch2pcb-specific modules
-import config
from funcs import *
from gsch2pcbproject import Gsch2PCBProject
from pcbmanager import PCBManager
diff --git a/lib/xgsch2pcb/new_project_gui.py b/lib/xgsch2pcb/new_project_gui.py
index 66a670e..8e07b26 100644
--- a/lib/xgsch2pcb/new_project_gui.py
+++ b/lib/xgsch2pcb/new_project_gui.py
@@ -20,8 +20,10 @@
import gtk, gtk.gdk, gobject
+import config
+
import gettext
-t = gettext.translation('xgsch2pcb', fallback=True)
+t = gettext.translation(config.PACKAGE, config.localedir, fallback=True)
_ = t.ugettext
# xgsch2pcb-specific modules
diff --git a/lib/xgsch2pcb/pcbmanager.py b/lib/xgsch2pcb/pcbmanager.py
index 0303b49..99d76b0 100644
--- a/lib/xgsch2pcb/pcbmanager.py
+++ b/lib/xgsch2pcb/pcbmanager.py
@@ -23,9 +23,11 @@ from __future__ import generators
import commands, shutil, re, gobject, os, sys, time
import dbus, dbus.glib, dbus.service
+import config
+
# i18n
import gettext
-t = gettext.translation('xgsch2pcb', fallback=True)
+t = gettext.translation(config.PACKAGE, config.localedir, fallback=True)
_ = t.ugettext
# xgsch2pcb-specific modules
diff --git a/po/.gitignore b/po/.gitignore
new file mode 100644
index 0000000..2ab8637
--- /dev/null
+++ b/po/.gitignore
@@ -0,0 +1,15 @@
+Makefile
+Makefile.in
+Makefile.in.in
+POTFILES
+*.gmo
+*.gmo
+*.sed
+*.header
+*.sin
+Rules-quot
+Makevars.template
+stamp-po
+stamp-it
+.intltool-merge-cache
+*~
diff --git a/po/ChangeLog b/po/ChangeLog
new file mode 100644
index 0000000..e69de29
diff --git a/po/LINGUAS b/po/LINGUAS
new file mode 100644
index 0000000..e69de29
diff --git a/po/POTFILES.in b/po/POTFILES.in
new file mode 100644
index 0000000..27e4765
--- /dev/null
+++ b/po/POTFILES.in
@@ -0,0 +1,3 @@
+lib/xgsch2pcb/gui.py
+lib/xgsch2pcb/new_project_gui.py
+lib/xgsch2pcb/pcbmanager.py
diff --git a/po/POTFILES.skip b/po/POTFILES.skip
new file mode 100644
index 0000000..236e168
--- /dev/null
+++ b/po/POTFILES.skip
@@ -0,0 +1 @@
+tools/pygettext.py
diff --git a/po/geda-xgsch2pcb.pot b/po/geda-xgsch2pcb.pot
new file mode 100644
index 0000000..1eb2be7
--- /dev/null
+++ b/po/geda-xgsch2pcb.pot
@@ -0,0 +1,298 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2007-11-10 23:41+0000\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@xxxxxx>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Page editing widgets
+#. --------------------
+#: ../lib/xgsch2pcb/gui.py:75
+msgid "Schematic pages"
+msgstr ""
+
+#. Buttons to run gschem/gattrib
+#: ../lib/xgsch2pcb/gui.py:115
+msgid "Edit schematic"
+msgstr ""
+
+#: ../lib/xgsch2pcb/gui.py:127
+msgid "Edit attributes"
+msgstr ""
+
+#. Layout editing widgets
+#. ----------------------
+#: ../lib/xgsch2pcb/gui.py:142
+msgid "Layout"
+msgstr ""
+
+#: ../lib/xgsch2pcb/gui.py:154
+msgid "Edit layout"
+msgstr ""
+
+#: ../lib/xgsch2pcb/gui.py:159 ../lib/xgsch2pcb/gui.py:428
+msgid "Update layout"
+msgstr ""
+
+#: ../lib/xgsch2pcb/gui.py:181
+msgid "xgsch2pcb"
+msgstr ""
+
+#: ../lib/xgsch2pcb/gui.py:182
+msgid "a GUI for gsch2pcb"
+msgstr ""
+
+#: ../lib/xgsch2pcb/gui.py:302
+msgid ""
+"You must select either an existing schematic file or enter a filename for a "
+"new file."
+msgstr ""
+
+#: ../lib/xgsch2pcb/gui.py:317
+msgid ""
+"<span weight=\"bold\" size=\"larger\">Selected file is outside the project "
+"directory\n"
+"Add anyway?</span>\n"
+"\n"
+"Projects are best kept in self contained directories. Ensure that you don't "
+"move or delete any external files, or the project will be incomplete."
+msgstr ""
+
+#: ../lib/xgsch2pcb/gui.py:326
+msgid "_Add anyway"
+msgstr ""
+
+#: ../lib/xgsch2pcb/gui.py:352
+#, python-format
+msgid ""
+"<span weight=\"bold\" size=\"larger\">Could not create schematic</span>\n"
+"\n"
+"Error %i: %s"
+msgstr ""
+
+#: ../lib/xgsch2pcb/gui.py:365
+msgid "<span weight=\"bold\" size=\"larger\">Could not create schematic</span>"
+msgstr ""
+
+#: ../lib/xgsch2pcb/gui.py:407
+#, python-format
+msgid "Could not locate tool: %s"
+msgstr ""
+
+#: ../lib/xgsch2pcb/gui.py:426
+msgid ""
+"Your schematic has changed.\n"
+"\n"
+"Would you like to update your PCB layout?"
+msgstr ""
+
+#: ../lib/xgsch2pcb/gui.py:427
+msgid "Leave layout unchanged"
+msgstr ""
+
+#: ../lib/xgsch2pcb/gui.py:466
+msgid "creating a new project"
+msgstr ""
+
+#: ../lib/xgsch2pcb/gui.py:476
+msgid "opening a new project"
+msgstr ""
+
+#: ../lib/xgsch2pcb/gui.py:485
+msgid "Open Project..."
+msgstr ""
+
+#: ../lib/xgsch2pcb/gui.py:518
+msgid "closing the project"
+msgstr ""
+
+#: ../lib/xgsch2pcb/gui.py:543
+msgid " [modified]"
+msgstr ""
+
+#: ../lib/xgsch2pcb/gui.py:591
+msgid "exiting"
+msgstr ""
+
+#: ../lib/xgsch2pcb/gui.py:631
+#, python-format
+msgid ""
+"<span weight=\"bold\" size=\"larger\">Problem initialising</span>\n"
+"%s"
+msgstr ""
+
+#: ../lib/xgsch2pcb/gui.py:668 ../lib/xgsch2pcb/gui.py:698
+#, python-format
+msgid ""
+"<span weight=\"bold\" size=\"larger\">Layout editor still open</span>\n"
+"\n"
+"Close the layout editor before %s."
+msgstr ""
+
+#: ../lib/xgsch2pcb/gui.py:671 ../lib/xgsch2pcb/gui.py:701
+msgid ""
+"<span weight=\"bold\" size=\"larger\">Layout editor still open</span>\n"
+"\n"
+"Close the layout editor first."
+msgstr ""
+
+#: ../lib/xgsch2pcb/gui.py:726
+#, python-format
+msgid ""
+"<span weight=\"bold\" size=\"larger\">Save the changes to project \"%s\" "
+"before closing?</span>\n"
+"\n"
+"Any changes made since the last save will be lost."
+msgstr ""
+
+#: ../lib/xgsch2pcb/gui.py:731
+msgid "Close _without Saving"
+msgstr ""
+
+#: ../lib/xgsch2pcb/gui.py:758
+msgid "Elements missing from layout"
+msgstr ""
+
+#: ../lib/xgsch2pcb/gui.py:759
+msgid ""
+"The footprints for the following elements were not found.\n"
+"Please check the 'footprint' attribute for these elements:\n"
+msgstr ""
+
+#: ../lib/xgsch2pcb/gui.py:787
+msgid "Add schematic page..."
+msgstr ""
+
+#. Two radio buttons allow you to select whether to use an
+#. existing file or create a new file
+#: ../lib/xgsch2pcb/gui.py:810
+msgid "From file:"
+msgstr ""
+
+#: ../lib/xgsch2pcb/gui.py:820
+msgid "Create new:"
+msgstr ""
+
+#. File chooser button to select and existing file. Currently
+#. limited to local files 'cos gsch2pcb can't handle remote
+#. files.
+#: ../lib/xgsch2pcb/gui.py:833
+msgid "Select schematic page..."
+msgstr ""
+
+#: ../lib/xgsch2pcb/gui.py:900
+msgid "New project..."
+msgstr ""
+
+#: ../lib/xgsch2pcb/gui.py:933
+#, python-format
+msgid ""
+"<span weight=\"bold\" size=\"larger\">A project named \"%s\" already exists. "
+"Do you want to replace it?</span>\n"
+"\n"
+"The project already exists in directory \"%s\". Replacing it will overwrite "
+"its contents."
+msgstr ""
+
+#: ../lib/xgsch2pcb/gui.py:943
+msgid "_Replace"
+msgstr ""
+
+#: ../lib/xgsch2pcb/new_project_gui.py:69
+#, python-format
+msgid ""
+"<span weight=\"bold\" size=\"larger\">Could not create project</span>\n"
+"\n"
+"Error %i: %s"
+msgstr ""
+
+#: ../lib/xgsch2pcb/new_project_gui.py:81
+msgid "<span weight=\"bold\" size=\"larger\">Could not create project</span>"
+msgstr ""
+
+#: ../lib/xgsch2pcb/new_project_gui.py:150
+msgid "<b>Choose project template</b>"
+msgstr ""
+
+#: ../lib/xgsch2pcb/new_project_gui.py:161
+msgid "Blank"
+msgstr ""
+
+#: ../lib/xgsch2pcb/new_project_gui.py:163
+msgid "From template:"
+msgstr ""
+
+#: ../lib/xgsch2pcb/new_project_gui.py:174
+msgid "(No templates found)"
+msgstr ""
+
+#: ../lib/xgsch2pcb/new_project_gui.py:204
+#: ../lib/xgsch2pcb/new_project_gui.py:263
+#: ../lib/xgsch2pcb/new_project_gui.py:335
+msgid "Create new project"
+msgstr ""
+
+#: ../lib/xgsch2pcb/new_project_gui.py:225
+msgid "<b>Choose project filename</b>"
+msgstr ""
+
+#. TODO: Remove magic numbers
+#. TODO: Remove magic numbers
+#: ../lib/xgsch2pcb/new_project_gui.py:240
+msgid "Project name:"
+msgstr ""
+
+#: ../lib/xgsch2pcb/new_project_gui.py:245
+msgid "Location:"
+msgstr ""
+
+#: ../lib/xgsch2pcb/new_project_gui.py:253
+msgid "Select project location..."
+msgstr ""
+
+#: ../lib/xgsch2pcb/new_project_gui.py:282
+msgid "<b>Project summary</b>"
+msgstr ""
+
+#: ../lib/xgsch2pcb/new_project_gui.py:294
+msgid "<b>New files to be created:</b>"
+msgstr ""
+
+#: ../lib/xgsch2pcb/new_project_gui.py:308
+msgid "<b>The following files would be overwritten:</b>"
+msgstr ""
+
+#: ../lib/xgsch2pcb/new_project_gui.py:325
+msgid "Confirm overwrite"
+msgstr ""
+
+#: ../lib/xgsch2pcb/pcbmanager.py:72
+msgid ""
+"\n"
+"Couldn't find 'pcb' executable"
+msgstr ""
+
+#: ../lib/xgsch2pcb/pcbmanager.py:75
+msgid ""
+"\n"
+"Couldn't find 'gsch2pcb' executable"
+msgstr ""
+
+#: ../lib/xgsch2pcb/pcbmanager.py:213
+msgid "********START UPDATING********"
+msgstr ""
+
+#: ../lib/xgsch2pcb/pcbmanager.py:313
+msgid "********DONE UPDATING********"
+msgstr ""
diff --git a/tools/intltool-extract.in b/tools/intltool-extract.in
new file mode 100644
index 0000000..7b83435
--- /dev/null
+++ b/tools/intltool-extract.in
@@ -0,0 +1,861 @@
+#!@INTLTOOL_PERL@ -w
+# -*- Mode: perl; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+
+#
+# The Intltool Message Extractor
+#
+# Copyright (C) 2000-2001, 2003 Free Software Foundation.
+#
+# Intltool is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# Intltool is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+#
+# Authors: Kenneth Christiansen <kenneth@xxxxxxx>
+# Darin Adler <darin@xxxxxxxxxxxxx>
+#
+
+## Release information
+my $PROGRAM = "intltool-extract";
+my $PACKAGE = "intltool";
+my $VERSION = "0.36.2";
+
+## Loaded modules
+use strict;
+use File::Basename;
+use Getopt::Long;
+
+## Scalars used by the option stuff
+my $TYPE_ARG = "0";
+my $LOCAL_ARG = "0";
+my $HELP_ARG = "0";
+my $VERSION_ARG = "0";
+my $UPDATE_ARG = "0";
+my $QUIET_ARG = "0";
+my $SRCDIR_ARG = ".";
+
+my $FILE;
+my $OUTFILE;
+
+my $gettext_type = "";
+my $input;
+my %messages = ();
+my %loc = ();
+my %count = ();
+my %comments = ();
+my $strcount = 0;
+
+my $XMLCOMMENT = "";
+
+## Use this instead of \w for XML files to handle more possible characters.
+my $w = "[-A-Za-z0-9._:]";
+
+## Always print first
+$| = 1;
+
+## Handle options
+GetOptions (
+ "type=s" => \$TYPE_ARG,
+ "local|l" => \$LOCAL_ARG,
+ "help|h" => \$HELP_ARG,
+ "version|v" => \$VERSION_ARG,
+ "update" => \$UPDATE_ARG,
+ "quiet|q" => \$QUIET_ARG,
+ "srcdir=s" => \$SRCDIR_ARG,
+ ) or &error;
+
+&split_on_argument;
+
+
+## Check for options.
+## This section will check for the different options.
+
+sub split_on_argument {
+
+ if ($VERSION_ARG) {
+ &version;
+
+ } elsif ($HELP_ARG) {
+ &help;
+
+ } elsif ($LOCAL_ARG) {
+ &place_local;
+ &extract;
+
+ } elsif ($UPDATE_ARG) {
+ &place_normal;
+ &extract;
+
+ } elsif (@ARGV > 0) {
+ &place_normal;
+ &message;
+ &extract;
+
+ } else {
+ &help;
+
+ }
+}
+
+sub place_normal {
+ $FILE = $ARGV[0];
+ $OUTFILE = "$FILE.h";
+
+ my $dirname = dirname ($OUTFILE);
+ if (! -d "$dirname" && $dirname ne "") {
+ system ("mkdir -p $dirname");
+ }
+}
+
+sub place_local {
+ $FILE = $ARGV[0];
+ $OUTFILE = fileparse($FILE, ());
+ if (!-e "tmp/") {
+ system("mkdir tmp/");
+ }
+ $OUTFILE = "./tmp/$OUTFILE.h"
+}
+
+sub determine_type {
+ if ($TYPE_ARG =~ /^gettext\/(.*)/) {
+ $gettext_type=$1
+ }
+}
+
+## Sub for printing release information
+sub version{
+ print <<_EOF_;
+${PROGRAM} (${PACKAGE}) $VERSION
+Copyright (C) 2000, 2003 Free Software Foundation, Inc.
+Written by Kenneth Christiansen, 2000.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+_EOF_
+ exit;
+}
+
+## Sub for printing usage information
+sub help {
+ print <<_EOF_;
+Usage: ${PROGRAM} [OPTION]... [FILENAME]
+Generates a header file from an XML source file.
+
+It grabs all strings between <_translatable_node> and its end tag in
+XML files. Read manpage (man ${PROGRAM}) for more info.
+
+ --type=TYPE Specify the file type of FILENAME. Currently supports:
+ "gettext/glade", "gettext/ini", "gettext/keys"
+ "gettext/rfc822deb", "gettext/schemas",
+ "gettext/scheme", "gettext/xml", "gettext/quoted"
+ -l, --local Writes output into current working directory
+ (conflicts with --update)
+ --update Writes output into the same directory the source file
+ reside (conflicts with --local)
+ --srcdir Root of the source tree
+ -v, --version Output version information and exit
+ -h, --help Display this help and exit
+ -q, --quiet Quiet mode
+
+Report bugs to http://bugzilla.gnome.org/ (product name "$PACKAGE")
+or send email to <xml-i18n-tools\@gnome.org>.
+_EOF_
+ exit;
+}
+
+## Sub for printing error messages
+sub error{
+ print STDERR "Try `${PROGRAM} --help' for more information.\n";
+ exit;
+}
+
+sub message {
+ print "Generating C format header file for translation.\n" unless $QUIET_ARG;
+}
+
+sub extract {
+ &determine_type;
+
+ &convert;
+
+ open OUT, ">$OUTFILE";
+ binmode (OUT) if $^O eq 'MSWin32';
+ &msg_write;
+ close OUT;
+
+ print "Wrote $OUTFILE\n" unless $QUIET_ARG;
+}
+
+sub convert {
+
+ ## Reading the file
+ {
+ local (*IN);
+ local $/; #slurp mode
+ open (IN, "<$SRCDIR_ARG/$FILE") || die "can't open $SRCDIR_ARG/$FILE: $!";
+ $input = <IN>;
+ }
+
+ &type_ini if $gettext_type eq "ini";
+ &type_keys if $gettext_type eq "keys";
+ &type_xml if $gettext_type eq "xml";
+ &type_glade if $gettext_type eq "glade";
+ &type_scheme if $gettext_type eq "scheme";
+ &type_schemas if $gettext_type eq "schemas";
+ &type_rfc822deb if $gettext_type eq "rfc822deb";
+ &type_quoted if $gettext_type eq "quoted";
+}
+
+sub entity_decode_minimal
+{
+ local ($_) = @_;
+
+ s/'/'/g; # '
+ s/"/"/g; # "
+ s/&/&/g;
+
+ return $_;
+}
+
+sub entity_decode
+{
+ local ($_) = @_;
+
+ s/'/'/g; # '
+ s/"/"/g; # "
+ s/</</g;
+ s/>/>/g;
+ s/&/&/g;
+
+ return $_;
+}
+
+sub escape_char
+{
+ return '\"' if $_ eq '"';
+ return '\n' if $_ eq "\n";
+ return '\\\\' if $_ eq '\\';
+
+ return $_;
+}
+
+sub escape
+{
+ my ($string) = @_;
+ return join "", map &escape_char, split //, $string;
+}
+
+sub type_ini {
+ ### For generic translatable desktop files ###
+ while ($input =~ /^(#(.+)\n)?^_.*=(.*)$/mg) {
+ if (defined($2)) {
+ $comments{$3} = $2;
+ }
+ $messages{$3} = [];
+ }
+}
+
+sub type_keys {
+ ### For generic translatable mime/keys files ###
+ while ($input =~ /^\s*_\w+=(.*)$/mg) {
+ $messages{$1} = [];
+ }
+}
+
+sub type_xml {
+ ### For generic translatable XML files ###
+ my $tree = readXml($input);
+ parseTree(0, $tree);
+}
+
+sub print_var {
+ my $var = shift;
+ my $vartype = ref $var;
+
+ if ($vartype =~ /ARRAY/) {
+ my @arr = @{$var};
+ print "[ ";
+ foreach my $el (@arr) {
+ print_var($el);
+ print ", ";
+ }
+ print "] ";
+ } elsif ($vartype =~ /HASH/) {
+ my %hash = %{$var};
+ print "{ ";
+ foreach my $key (keys %hash) {
+ print "$key => ";
+ print_var($hash{$key});
+ print ", ";
+ }
+ print "} ";
+ } else {
+ print $var;
+ }
+}
+
+# Same syntax as getAttributeString in intltool-merge.in.in, similar logic (look for ## differences comment)
+sub getAttributeString
+{
+ my $sub = shift;
+ my $do_translate = shift || 1;
+ my $language = shift || "";
+ my $translate = shift;
+ my $result = "";
+ foreach my $e (reverse(sort(keys %{ $sub }))) {
+ my $key = $e;
+ my $string = $sub->{$e};
+ my $quote = '"';
+
+ $string =~ s/^[\s]+//;
+ $string =~ s/[\s]+$//;
+
+ if ($string =~ /^'.*'$/)
+ {
+ $quote = "'";
+ }
+ $string =~ s/^['"]//g;
+ $string =~ s/['"]$//g;
+
+ ## differences from intltool-merge.in.in
+ if ($key =~ /^_/) {
+ $comments{entity_decode($string)} = $XMLCOMMENT if $XMLCOMMENT;
+ $messages{entity_decode($string)} = [];
+ $$translate = 2;
+ }
+ ## differences end here from intltool-merge.in.in
+ $result .= " $key=$quote$string$quote";
+ }
+ return $result;
+}
+
+# Verbatim copy from intltool-merge.in.in
+sub getXMLstring
+{
+ my $ref = shift;
+ my $spacepreserve = shift || 0;
+ my @list = @{ $ref };
+ my $result = "";
+
+ my $count = scalar(@list);
+ my $attrs = $list[0];
+ my $index = 1;
+
+ $spacepreserve = 1 if ((exists $attrs->{"xml:space"}) && ($attrs->{"xml:space"} =~ /^["']?preserve["']?$/));
+ $spacepreserve = 0 if ((exists $attrs->{"xml:space"}) && ($attrs->{"xml:space"} =~ /^["']?default["']?$/));
+
+ while ($index < $count) {
+ my $type = $list[$index];
+ my $content = $list[$index+1];
+ if (! $type ) {
+ # We've got CDATA
+ if ($content) {
+ # lets strip the whitespace here, and *ONLY* here
+ $content =~ s/\s+/ /gs if (!$spacepreserve);
+ $result .= $content;
+ }
+ } elsif ( "$type" ne "1" ) {
+ # We've got another element
+ $result .= "<$type";
+ $result .= getAttributeString(@{$content}[0], 0); # no nested translatable elements
+ if ($content) {
+ my $subresult = getXMLstring($content, $spacepreserve);
+ if ($subresult) {
+ $result .= ">".$subresult . "</$type>";
+ } else {
+ $result .= "/>";
+ }
+ } else {
+ $result .= "/>";
+ }
+ }
+ $index += 2;
+ }
+ return $result;
+}
+
+# Verbatim copy from intltool-merge.in.in, except for MULTIPLE_OUTPUT handling removed
+# Translate list of nodes if necessary
+sub translate_subnodes
+{
+ my $fh = shift;
+ my $content = shift;
+ my $language = shift || "";
+ my $singlelang = shift || 0;
+ my $spacepreserve = shift || 0;
+
+ my @nodes = @{ $content };
+
+ my $count = scalar(@nodes);
+ my $index = 0;
+ while ($index < $count) {
+ my $type = $nodes[$index];
+ my $rest = $nodes[$index+1];
+ traverse($fh, $type, $rest, $language, $spacepreserve);
+ $index += 2;
+ }
+}
+
+# Based on traverse() in intltool-merge.in.in
+sub traverse
+{
+ my $fh = shift; # unused, to allow us to sync code between -merge and -extract
+ my $nodename = shift;
+ my $content = shift;
+ my $language = shift || "";
+ my $spacepreserve = shift || 0;
+
+ if ($nodename && "$nodename" eq "1") {
+ $XMLCOMMENT = $content;
+ } elsif ($nodename) {
+ # element
+ my @all = @{ $content };
+ my $attrs = shift @all;
+ my $translate = 0;
+ my $outattr = getAttributeString($attrs, 1, $language, \$translate);
+
+ if ($nodename =~ /^_/) {
+ $translate = 1;
+ $nodename =~ s/^_//;
+ }
+ my $lookup = '';
+
+ $spacepreserve = 0 if ((exists $attrs->{"xml:space"}) && ($attrs->{"xml:space"} =~ /^["']?default["']?$/));
+ $spacepreserve = 1 if ((exists $attrs->{"xml:space"}) && ($attrs->{"xml:space"} =~ /^["']?preserve["']?$/));
+
+ if ($translate) {
+ $lookup = getXMLstring($content, $spacepreserve);
+ if (!$spacepreserve) {
+ $lookup =~ s/^\s+//s;
+ $lookup =~ s/\s+$//s;
+ }
+
+ if ($lookup && $translate != 2) {
+ $comments{$lookup} = $XMLCOMMENT if $XMLCOMMENT;
+ $messages{$lookup} = [];
+ } elsif ($translate == 2) {
+ translate_subnodes($fh, \@all, $language, 1, $spacepreserve);
+ }
+ } else {
+ $XMLCOMMENT = "";
+ my $count = scalar(@all);
+ if ($count > 0) {
+ my $index = 0;
+ while ($index < $count) {
+ my $type = $all[$index];
+ my $rest = $all[$index+1];
+ traverse($fh, $type, $rest, $language, $spacepreserve);
+ $index += 2;
+ }
+ }
+ }
+ $XMLCOMMENT = "";
+ }
+}
+
+
+# Verbatim copy from intltool-merge.in.in, $fh for compatibility
+sub parseTree
+{
+ my $fh = shift;
+ my $ref = shift;
+ my $language = shift || "";
+
+ my $name = shift @{ $ref };
+ my $cont = shift @{ $ref };
+
+ while (!$name || "$name" eq "1") {
+ $name = shift @{ $ref };
+ $cont = shift @{ $ref };
+ }
+
+ my $spacepreserve = 0;
+ my $attrs = @{$cont}[0];
+ $spacepreserve = 1 if ((exists $attrs->{"xml:space"}) && ($attrs->{"xml:space"} =~ /^["']?preserve["']?$/));
+
+ traverse($fh, $name, $cont, $language, $spacepreserve);
+}
+
+# Verbatim copy from intltool-merge.in.in
+sub intltool_tree_comment
+{
+ my $expat = shift;
+ my $data = $expat->original_string();
+ my $clist = $expat->{Curlist};
+ my $pos = $#$clist;
+
+ $data =~ s/^<!--//s;
+ $data =~ s/-->$//s;
+ push @$clist, 1 => $data;
+}
+
+# Verbatim copy from intltool-merge.in.in
+sub intltool_tree_cdatastart
+{
+ my $expat = shift;
+ my $clist = $expat->{Curlist};
+ my $pos = $#$clist;
+
+ push @$clist, 0 => $expat->original_string();
+}
+
+# Verbatim copy from intltool-merge.in.in
+sub intltool_tree_cdataend
+{
+ my $expat = shift;
+ my $clist = $expat->{Curlist};
+ my $pos = $#$clist;
+
+ $clist->[$pos] .= $expat->original_string();
+}
+
+# Verbatim copy from intltool-merge.in.in
+sub intltool_tree_char
+{
+ my $expat = shift;
+ my $text = shift;
+ my $clist = $expat->{Curlist};
+ my $pos = $#$clist;
+
+ # Use original_string so that we retain escaped entities
+ # in CDATA sections.
+ #
+ if ($pos > 0 and $clist->[$pos - 1] eq '0') {
+ $clist->[$pos] .= $expat->original_string();
+ } else {
+ push @$clist, 0 => $expat->original_string();
+ }
+}
+
+# Verbatim copy from intltool-merge.in.in
+sub intltool_tree_start
+{
+ my $expat = shift;
+ my $tag = shift;
+ my @origlist = ();
+
+ # Use original_string so that we retain escaped entities
+ # in attribute values. We must convert the string to an
+ # @origlist array to conform to the structure of the Tree
+ # Style.
+ #
+ my @original_array = split /\x/, $expat->original_string();
+ my $source = $expat->original_string();
+
+ # Remove leading tag.
+ #
+ $source =~ s|^\s*<\s*(\S+)||s;
+
+ # Grab attribute key/value pairs and push onto @origlist array.
+ #
+ while ($source)
+ {
+ if ($source =~ /^\s*([\w:-]+)\s*[=]\s*["]/)
+ {
+ $source =~ s|^\s*([\w:-]+)\s*[=]\s*["]([^"]*)["]||s;
+ push @origlist, $1;
+ push @origlist, '"' . $2 . '"';
+ }
+ elsif ($source =~ /^\s*([\w:-]+)\s*[=]\s*[']/)
+ {
+ $source =~ s|^\s*([\w:-]+)\s*[=]\s*[']([^']*)[']||s;
+ push @origlist, $1;
+ push @origlist, "'" . $2 . "'";
+ }
+ else
+ {
+ last;
+ }
+ }
+
+ my $ol = [ { @origlist } ];
+
+ push @{ $expat->{Lists} }, $expat->{Curlist};
+ push @{ $expat->{Curlist} }, $tag => $ol;
+ $expat->{Curlist} = $ol;
+}
+
+# Copied from intltool-merge.in.in and added comment handler.
+sub readXml
+{
+ my $xmldoc = shift || return;
+ my $ret = eval 'require XML::Parser';
+ if(!$ret) {
+ die "You must have XML::Parser installed to run $0\n\n";
+ }
+ my $xp = new XML::Parser(Style => 'Tree');
+ $xp->setHandlers(Char => \&intltool_tree_char);
+ $xp->setHandlers(Start => \&intltool_tree_start);
+ $xp->setHandlers(CdataStart => \&intltool_tree_cdatastart);
+ $xp->setHandlers(CdataEnd => \&intltool_tree_cdataend);
+
+ ## differences from intltool-merge.in.in
+ $xp->setHandlers(Comment => \&intltool_tree_comment);
+ ## differences end here from intltool-merge.in.in
+
+ my $tree = $xp->parse($xmldoc);
+ #print_var($tree);
+
+# <foo><!-- comment --><head id="a">Hello <em>there</em></head><bar>Howdy<ref/></bar>do</foo>
+# would be:
+# [foo, [{}, 1, "comment", head, [{id => "a"}, 0, "Hello ", em, [{}, 0, "there"]], bar,
+# [{}, 0, "Howdy", ref, [{}]], 0, "do" ] ]
+
+ return $tree;
+}
+
+sub type_schemas {
+ ### For schemas XML files ###
+
+ # FIXME: We should handle escaped < (less than)
+ while ($input =~ /
+ <locale\ name="C">\s*
+ (<default>\s*(?:<!--([^>]*?)-->\s*)?(.*?)\s*<\/default>\s*)?
+ (<short>\s*(?:<!--([^>]*?)-->\s*)?(.*?)\s*<\/short>\s*)?
+ (<long>\s*(?:<!--([^>]*?)-->\s*)?(.*?)\s*<\/long>\s*)?
+ <\/locale>
+ /sgx) {
+ my @totranslate = ($3,$6,$9);
+ my @eachcomment = ($2,$5,$8);
+ foreach (@totranslate) {
+ my $currentcomment = shift @eachcomment;
+ next if !$_;
+ s/\s+/ /g;
+ $messages{entity_decode_minimal($_)} = [];
+ $comments{entity_decode_minimal($_)} = $currentcomment if (defined($currentcomment));
+ }
+ }
+}
+
+sub type_rfc822deb {
+ ### For rfc822-style Debian configuration files ###
+
+ my $lineno = 1;
+ my $type = '';
+ while ($input =~ /\G(.*?)(^|\n)(_+)([^:]+):[ \t]*(.*?)(?=\n\S|$)/sg)
+ {
+ my ($pre, $newline, $underscore, $tag, $text) = ($1, $2, $3, $4, $5);
+ while ($pre =~ m/\n/g)
+ {
+ $lineno ++;
+ }
+ $lineno += length($newline);
+ my @str_list = rfc822deb_split(length($underscore), $text);
+ for my $str (@str_list)
+ {
+ $strcount++;
+ $messages{$str} = [];
+ $loc{$str} = $lineno;
+ $count{$str} = $strcount;
+ my $usercomment = '';
+ while($pre =~ s/(^|\n)#([^\n]*)$//s)
+ {
+ $usercomment = "\n" . $2 . $usercomment;
+ }
+ $comments{$str} = $tag . $usercomment;
+ }
+ $lineno += ($text =~ s/\n//g);
+ }
+}
+
+sub rfc822deb_split {
+ # Debian defines a special way to deal with rfc822-style files:
+ # when a value contain newlines, it consists of
+ # 1. a short form (first line)
+ # 2. a long description, all lines begin with a space,
+ # and paragraphs are separated by a single dot on a line
+ # This routine returns an array of all paragraphs, and reformat
+ # them.
+ # When first argument is 2, the string is a comma separated list of
+ # values.
+ my $type = shift;
+ my $text = shift;
+ $text =~ s/^[ \t]//mg;
+ return (split(/, */, $text, 0)) if $type ne 1;
+ return ($text) if $text !~ /\n/;
+
+ $text =~ s/([^\n]*)\n//;
+ my @list = ($1);
+ my $str = '';
+ for my $line (split (/\n/, $text))
+ {
+ chomp $line;
+ if ($line =~ /^\.\s*$/)
+ {
+ # New paragraph
+ $str =~ s/\s*$//;
+ push(@list, $str);
+ $str = '';
+ }
+ elsif ($line =~ /^\s/)
+ {
+ # Line which must not be reformatted
+ $str .= "\n" if length ($str) && $str !~ /\n$/;
+ $line =~ s/\s+$//;
+ $str .= $line."\n";
+ }
+ else
+ {
+ # Continuation line, remove newline
+ $str .= " " if length ($str) && $str !~ /\n$/;
+ $str .= $line;
+ }
+ }
+ $str =~ s/\s*$//;
+ push(@list, $str) if length ($str);
+ return @list;
+}
+
+sub type_quoted {
+ while ($input =~ /\"(([^\"]|\\\")*[^\\\"])\"/g) {
+ my $message = $1;
+ my $before = $`;
+ $message =~ s/\\\"/\"/g;
+ $before =~ s/[^\n]//g;
+ $messages{$message} = [];
+ $loc{$message} = length ($before) + 2;
+ }
+}
+
+sub type_glade {
+ ### For translatable Glade XML files ###
+
+ my $tags = "label|title|text|format|copyright|comments|preview_text|tooltip|message";
+
+ while ($input =~ /<($tags)>([^<]+)<\/($tags)>/sg) {
+ # Glade sometimes uses tags that normally mark translatable things for
+ # little bits of non-translatable content. We work around this by not
+ # translating strings that only includes something like label4 or window1.
+ $messages{entity_decode($2)} = [] unless $2 =~ /^(window|label|dialog)[0-9]+$/;
+ }
+
+ while ($input =~ /<items>(..[^<]*)<\/items>/sg) {
+ for my $item (split (/\n/, $1)) {
+ $messages{entity_decode($item)} = [];
+ }
+ }
+
+ ## handle new glade files
+ while ($input =~ /<(property|atkproperty)\s+[^>]*translatable\s*=\s*"yes"(?:\s+[^>]*comments\s*=\s*"([^"]*)")?[^>]*>([^<]+)<\/\1>/sg) {
+ $messages{entity_decode($3)} = [] unless $3 =~ /^(window|label)[0-9]+$/;
+ if (defined($2) and !($3 =~ /^(window|label)[0-9]+$/)) {
+ $comments{entity_decode($3)} = entity_decode($2) ;
+ }
+ }
+ while ($input =~ /<atkaction\s+action_name="([^>]*)"\s+description="([^>]+)"\/>/sg) {
+ $messages{entity_decode_minimal($2)} = [];
+ }
+}
+
+sub type_scheme {
+ my ($line, $i, $state, $str, $trcomment, $char);
+ for $line (split(/\n/, $input)) {
+ $i = 0;
+ $state = 0; # 0 - nothing, 1 - string, 2 - translatable string
+ while ($i < length($line)) {
+ if (substr($line,$i,1) eq "\"") {
+ if ($state == 2) {
+ $comments{$str} = $trcomment if ($trcomment);
+ $messages{$str} = [];
+ $str = '';
+ $state = 0; $trcomment = "";
+ } elsif ($state == 1) {
+ $str = '';
+ $state = 0; $trcomment = "";
+ } else {
+ $state = 1;
+ $str = '';
+ if ($i>0 && substr($line,$i-1,1) eq '_') {
+ $state = 2;
+ }
+ }
+ } elsif (!$state) {
+ if (substr($line,$i,1) eq ";") {
+ $trcomment = substr($line,$i+1);
+ $trcomment =~ s/^;*\s*//;
+ $i = length($line);
+ } elsif ($trcomment && substr($line,$i,1) !~ /\s|\(|\)|_/) {
+ $trcomment = "";
+ }
+ } else {
+ if (substr($line,$i,1) eq "\\") {
+ $char = substr($line,$i+1,1);
+ if ($char ne "\"" && $char ne "\\") {
+ $str = $str . "\\";
+ }
+ $i++;
+ }
+ $str = $str . substr($line,$i,1);
+ }
+ $i++;
+ }
+ }
+}
+
+sub msg_write {
+ my @msgids;
+ if (%count)
+ {
+ @msgids = sort { $count{$a} <=> $count{$b} } keys %count;
+ }
+ else
+ {
+ @msgids = sort keys %messages;
+ }
+ for my $message (@msgids)
+ {
+ my $offsetlines = 1;
+ $offsetlines++ if $message =~ /%/;
+ if (defined ($comments{$message}))
+ {
+ while ($comments{$message} =~ m/\n/g)
+ {
+ $offsetlines++;
+ }
+ }
+ print OUT "# ".($loc{$message} - $offsetlines). " \"$FILE\"\n"
+ if defined $loc{$message};
+ print OUT "/* ".$comments{$message}." */\n"
+ if defined $comments{$message};
+ print OUT "/* xgettext:no-c-format */\n" if $message =~ /%/;
+
+ my @lines = split (/\n/, $message, -1);
+ for (my $n = 0; $n < @lines; $n++)
+ {
+ if ($n == 0)
+ {
+ print OUT "char *s = N_(\"";
+ }
+ else
+ {
+ print OUT " \"";
+ }
+
+ print OUT escape($lines[$n]);
+
+ if ($n < @lines - 1)
+ {
+ print OUT "\\n\"\n";
+ }
+ else
+ {
+ print OUT "\");\n";
+ }
+ }
+ }
+}
+
diff --git a/tools/intltool-merge.in b/tools/intltool-merge.in
new file mode 100644
index 0000000..e5671d7
--- /dev/null
+++ b/tools/intltool-merge.in
@@ -0,0 +1,1451 @@
+#!@INTLTOOL_PERL@ -w
+# -*- Mode: perl; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+
+#
+# The Intltool Message Merger
+#
+# Copyright (C) 2000, 2003 Free Software Foundation.
+# Copyright (C) 2000, 2001 Eazel, Inc
+#
+# Intltool is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# version 2 published by the Free Software Foundation.
+#
+# Intltool is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+#
+# Authors: Maciej Stachowiak <mjs@xxxxxxxxxxxxxx>
+# Kenneth Christiansen <kenneth@xxxxxxx>
+# Darin Adler <darin@xxxxxxxxxxxxx>
+#
+# Proper XML UTF-8'ification written by Cyrille Chepelov <chepelov@xxxxxxxxxx>
+#
+
+## Release information
+my $PROGRAM = "intltool-merge";
+my $PACKAGE = "intltool";
+my $VERSION = "0.36.2";
+
+## Loaded modules
+use strict;
+use Getopt::Long;
+use Text::Wrap;
+use File::Basename;
+
+my $must_end_tag = -1;
+my $last_depth = -1;
+my $translation_depth = -1;
+my @tag_stack = ();
+my @entered_tag = ();
+my @translation_strings = ();
+my $leading_space = "";
+
+## Scalars used by the option stuff
+my $HELP_ARG = 0;
+my $VERSION_ARG = 0;
+my $BA_STYLE_ARG = 0;
+my $XML_STYLE_ARG = 0;
+my $KEYS_STYLE_ARG = 0;
+my $DESKTOP_STYLE_ARG = 0;
+my $SCHEMAS_STYLE_ARG = 0;
+my $RFC822DEB_STYLE_ARG = 0;
+my $QUOTED_STYLE_ARG = 0;
+my $QUIET_ARG = 0;
+my $PASS_THROUGH_ARG = 0;
+my $UTF8_ARG = 0;
+my $MULTIPLE_OUTPUT = 0;
+my $cache_file;
+
+## Handle options
+GetOptions
+(
+ "help" => \$HELP_ARG,
+ "version" => \$VERSION_ARG,
+ "quiet|q" => \$QUIET_ARG,
+ "oaf-style|o" => \$BA_STYLE_ARG, ## for compatibility
+ "ba-style|b" => \$BA_STYLE_ARG,
+ "xml-style|x" => \$XML_STYLE_ARG,
+ "keys-style|k" => \$KEYS_STYLE_ARG,
+ "desktop-style|d" => \$DESKTOP_STYLE_ARG,
+ "schemas-style|s" => \$SCHEMAS_STYLE_ARG,
+ "rfc822deb-style|r" => \$RFC822DEB_STYLE_ARG,
+ "quoted-style" => \$QUOTED_STYLE_ARG,
+ "pass-through|p" => \$PASS_THROUGH_ARG,
+ "utf8|u" => \$UTF8_ARG,
+ "multiple-output|m" => \$MULTIPLE_OUTPUT,
+ "cache|c=s" => \$cache_file
+ ) or &error;
+
+my $PO_DIR;
+my $FILE;
+my $OUTFILE;
+
+my %po_files_by_lang = ();
+my %translations = ();
+my $iconv = $ENV{"ICONV"} || "iconv";
+my $devnull = ($^O eq 'MSWin32' ? 'NUL:' : '/dev/null');
+
+sub isProgramInPath
+{
+ my ($file) = @_;
+ # If either a file exists, or when run it returns 0 exit status
+ return 1 if ((-x $file) or (system("$file -l >$devnull") == 0));
+ return 0;
+}
+
+if (! isProgramInPath ("$iconv"))
+{
+ print STDERR " *** iconv is not found on this system!\n".
+ " *** Without it, intltool-merge can not convert encodings.\n";
+ exit;
+}
+
+# Use this instead of \w for XML files to handle more possible characters.
+my $w = "[-A-Za-z0-9._:]";
+
+# XML quoted string contents
+my $q = "[^\\\"]*";
+
+## Check for options.
+
+if ($VERSION_ARG)
+{
+ &print_version;
+}
+elsif ($HELP_ARG)
+{
+ &print_help;
+}
+elsif ($BA_STYLE_ARG && @ARGV > 2)
+{
+ &utf8_sanity_check;
+ &preparation;
+ &print_message;
+ &ba_merge_translations;
+ &finalize;
+}
+elsif ($XML_STYLE_ARG && @ARGV > 2)
+{
+ &utf8_sanity_check;
+ &preparation;
+ &print_message;
+ &xml_merge_output;
+ &finalize;
+}
+elsif ($KEYS_STYLE_ARG && @ARGV > 2)
+{
+ &utf8_sanity_check;
+ &preparation;
+ &print_message;
+ &keys_merge_translations;
+ &finalize;
+}
+elsif ($DESKTOP_STYLE_ARG && @ARGV > 2)
+{
+ &utf8_sanity_check;
+ &preparation;
+ &print_message;
+ &desktop_merge_translations;
+ &finalize;
+}
+elsif ($SCHEMAS_STYLE_ARG && @ARGV > 2)
+{
+ &utf8_sanity_check;
+ &preparation;
+ &print_message;
+ &schemas_merge_translations;
+ &finalize;
+}
+elsif ($RFC822DEB_STYLE_ARG && @ARGV > 2)
+{
+ &preparation;
+ &print_message;
+ &rfc822deb_merge_translations;
+ &finalize;
+}
+elsif ($QUOTED_STYLE_ARG && @ARGV > 2)
+{
+ &utf8_sanity_check;
+ &preparation;
+ &print_message;
+ "ed_merge_translations;
+ &finalize;
+}
+else
+{
+ &print_help;
+}
+
+exit;
+
+## Sub for printing release information
+sub print_version
+{
+ print <<_EOF_;
+${PROGRAM} (${PACKAGE}) ${VERSION}
+Written by Maciej Stachowiak, Darin Adler and Kenneth Christiansen.
+
+Copyright (C) 2000-2003 Free Software Foundation, Inc.
+Copyright (C) 2000-2001 Eazel, Inc.
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+_EOF_
+ exit;
+}
+
+## Sub for printing usage information
+sub print_help
+{
+ print <<_EOF_;
+Usage: ${PROGRAM} [OPTION]... PO_DIRECTORY FILENAME OUTPUT_FILE
+Generates an output file that includes some localized attributes from an
+untranslated source file.
+
+Mandatory options: (exactly one must be specified)
+ -b, --ba-style includes translations in the bonobo-activation style
+ -d, --desktop-style includes translations in the desktop style
+ -k, --keys-style includes translations in the keys style
+ -s, --schemas-style includes translations in the schemas style
+ -r, --rfc822deb-style includes translations in the RFC822 style
+ --quoted-style includes translations in the quoted string style
+ -x, --xml-style includes translations in the standard xml style
+
+Other options:
+ -u, --utf8 convert all strings to UTF-8 before merging
+ (default for everything except RFC822 style)
+ -p, --pass-through deprecated, does nothing and issues a warning
+ -m, --multiple-output output one localized file per locale, instead of
+ a single file containing all localized elements
+ -c, --cache=FILE specify cache file name
+ (usually \$top_builddir/po/.intltool-merge-cache)
+ -q, --quiet suppress most messages
+ --help display this help and exit
+ --version output version information and exit
+
+Report bugs to http://bugzilla.gnome.org/ (product name "$PACKAGE")
+or send email to <xml-i18n-tools\@gnome.org>.
+_EOF_
+ exit;
+}
+
+
+## Sub for printing error messages
+sub print_error
+{
+ print STDERR "Try `${PROGRAM} --help' for more information.\n";
+ exit;
+}
+
+
+sub print_message
+{
+ print "Merging translations into $OUTFILE.\n" unless $QUIET_ARG;
+}
+
+
+sub preparation
+{
+ $PO_DIR = $ARGV[0];
+ $FILE = $ARGV[1];
+ $OUTFILE = $ARGV[2];
+
+ &gather_po_files;
+ &get_translation_database;
+}
+
+# General-purpose code for looking up translations in .po files
+
+sub po_file2lang
+{
+ my ($tmp) = @_;
+ $tmp =~ s/^.*\/(.*)\.po$/$1/;
+ return $tmp;
+}
+
+sub gather_po_files
+{
+ if (my $linguas = $ENV{"LINGUAS"})
+ {
+ for my $lang (split / /, $linguas) {
+ my $po_file = $PO_DIR . "/" . $lang . ".po";
+ if (-e $po_file) {
+ $po_files_by_lang{$lang} = $po_file;
+ }
+ }
+ }
+ else
+ {
+ if (open LINGUAS_FILE, "$PO_DIR/LINGUAS")
+ {
+ while (<LINGUAS_FILE>)
+ {
+ next if /^#/;
+
+ if (/([-a-zA-Z_@.]+)\n/)
+ {
+ my $lang = $1;
+
+ my $po_file = $PO_DIR . "/" . $lang . ".po";
+ if (-e $po_file) {
+ $po_files_by_lang{$lang} = $po_file;
+ }
+ }
+ }
+
+ close LINGUAS_FILE;
+ }
+ else
+ {
+ for my $po_file (glob "$PO_DIR/*.po") {
+ $po_files_by_lang{po_file2lang($po_file)} = $po_file;
+ }
+ }
+ }
+}
+
+sub get_local_charset
+{
+ my ($encoding) = @_;
+ my $alias_file = $ENV{"G_CHARSET_ALIAS"} || "@INTLTOOL_LIBDIR@/charset.alias";
+
+ # seek character encoding aliases in charset.alias (glib)
+
+ if (open CHARSET_ALIAS, $alias_file)
+ {
+ while (<CHARSET_ALIAS>)
+ {
+ next if /^\#/;
+ return $1 if (/^\s*([-._a-zA-Z0-9]+)\s+$encoding\b/i)
+ }
+
+ close CHARSET_ALIAS;
+ }
+
+ # if not found, return input string
+
+ return $encoding;
+}
+
+sub get_po_encoding
+{
+ my ($in_po_file) = @_;
+ my $encoding = "";
+
+ open IN_PO_FILE, $in_po_file or die;
+ while (<IN_PO_FILE>)
+ {
+ ## example: "Content-Type: text/plain; charset=ISO-8859-1\n"
+ if (/Content-Type\:.*charset=([-a-zA-Z0-9]+)\\n/)
+ {
+ $encoding = $1;
+ last;
+ }
+ }
+ close IN_PO_FILE;
+
+ if (!$encoding)
+ {
+ print STDERR "Warning: no encoding found in $in_po_file. Assuming ISO-8859-1\n" unless $QUIET_ARG;
+ $encoding = "ISO-8859-1";
+ }
+
+ system ("$iconv -f $encoding -t UTF-8 <$devnull 2>$devnull");
+ if ($?) {
+ $encoding = get_local_charset($encoding);
+ }
+
+ return $encoding
+}
+
+sub utf8_sanity_check
+{
+ print STDERR "Warning: option --pass-through has been removed.\n" if $PASS_THROUGH_ARG;
+ $UTF8_ARG = 1;
+}
+
+sub get_translation_database
+{
+ if ($cache_file) {
+ &get_cached_translation_database;
+ } else {
+ &create_translation_database;
+ }
+}
+
+sub get_newest_po_age
+{
+ my $newest_age;
+
+ foreach my $file (values %po_files_by_lang)
+ {
+ my $file_age = -M $file;
+ $newest_age = $file_age if !$newest_age || $file_age < $newest_age;
+ }
+
+ $newest_age = 0 if !$newest_age;
+
+ return $newest_age;
+}
+
+sub create_cache
+{
+ print "Generating and caching the translation database\n" unless $QUIET_ARG;
+
+ &create_translation_database;
+
+ open CACHE, ">$cache_file" || die;
+ print CACHE join "\x01", %translations;
+ close CACHE;
+}
+
+sub load_cache
+{
+ print "Found cached translation database\n" unless $QUIET_ARG;
+
+ my $contents;
+ open CACHE, "<$cache_file" || die;
+ {
+ local $/;
+ $contents = <CACHE>;
+ }
+ close CACHE;
+ %translations = split "\x01", $contents;
+}
+
+sub get_cached_translation_database
+{
+ my $cache_file_age = -M $cache_file;
+ if (defined $cache_file_age)
+ {
+ if ($cache_file_age <= &get_newest_po_age)
+ {
+ &load_cache;
+ return;
+ }
+ print "Found too-old cached translation database\n" unless $QUIET_ARG;
+ }
+
+ &create_cache;
+}
+
+sub create_translation_database
+{
+ for my $lang (keys %po_files_by_lang)
+ {
+ my $po_file = $po_files_by_lang{$lang};
+
+ if ($UTF8_ARG)
+ {
+ my $encoding = get_po_encoding ($po_file);
+
+ if (lc $encoding eq "utf-8")
+ {
+ open PO_FILE, "<$po_file";
+ }
+ else
+ {
+ print "NOTICE: $po_file is not in UTF-8 but $encoding, converting...\n" unless $QUIET_ARG;;
+
+ open PO_FILE, "$iconv -f $encoding -t UTF-8 $po_file|";
+ }
+ }
+ else
+ {
+ open PO_FILE, "<$po_file";
+ }
+
+ my $nextfuzzy = 0;
+ my $inmsgid = 0;
+ my $inmsgstr = 0;
+ my $msgid = "";
+ my $msgstr = "";
+
+ while (<PO_FILE>)
+ {
+ $nextfuzzy = 1 if /^#, fuzzy/;
+
+ if (/^msgid "((\\.|[^\\]+)*)"/ )
+ {
+ $translations{$lang, $msgid} = $msgstr if $inmsgstr && $msgid && $msgstr;
+ $msgid = "";
+ $msgstr = "";
+
+ if ($nextfuzzy) {
+ $inmsgid = 0;
+ } else {
+ $msgid = unescape_po_string($1);
+ $inmsgid = 1;
+ }
+ $inmsgstr = 0;
+ $nextfuzzy = 0;
+ }
+
+ if (/^msgstr "((\\.|[^\\]+)*)"/)
+ {
+ $msgstr = unescape_po_string($1);
+ $inmsgstr = 1;
+ $inmsgid = 0;
+ }
+
+ if (/^"((\\.|[^\\]+)*)"/)
+ {
+ $msgid .= unescape_po_string($1) if $inmsgid;
+ $msgstr .= unescape_po_string($1) if $inmsgstr;
+ }
+ }
+ $translations{$lang, $msgid} = $msgstr if $inmsgstr && $msgid && $msgstr;
+ }
+}
+
+sub finalize
+{
+}
+
+sub unescape_one_sequence
+{
+ my ($sequence) = @_;
+
+ return "\\" if $sequence eq "\\\\";
+ return "\"" if $sequence eq "\\\"";
+ return "\n" if $sequence eq "\\n";
+ return "\r" if $sequence eq "\\r";
+ return "\t" if $sequence eq "\\t";
+ return "\b" if $sequence eq "\\b";
+ return "\f" if $sequence eq "\\f";
+ return "\a" if $sequence eq "\\a";
+ return chr(11) if $sequence eq "\\v"; # vertical tab, see ascii(7)
+
+ return chr(hex($1)) if ($sequence =~ /\\x([0-9a-fA-F]{2})/);
+ return chr(oct($1)) if ($sequence =~ /\\([0-7]{3})/);
+
+ # FIXME: Is \0 supported as well? Kenneth and Rodney don't want it, see bug #48489
+
+ return $sequence;
+}
+
+sub unescape_po_string
+{
+ my ($string) = @_;
+
+ $string =~ s/(\\x[0-9a-fA-F]{2}|\\[0-7]{3}|\\.)/unescape_one_sequence($1)/eg;
+
+ return $string;
+}
+
+sub entity_decode
+{
+ local ($_) = @_;
+
+ s/'/'/g; # '
+ s/"/"/g; # "
+ s/</</g;
+ s/>/>/g;
+ s/&/&/g;
+
+ return $_;
+}
+
+# entity_encode: (string)
+#
+# Encode the given string to XML format (encode '<' etc).
+
+sub entity_encode
+{
+ my ($pre_encoded) = @_;
+
+ my @list_of_chars = unpack ('C*', $pre_encoded);
+
+ # with UTF-8 we only encode minimalistic
+ return join ('', map (&entity_encode_int_minimalist, @list_of_chars));
+}
+
+sub entity_encode_int_minimalist
+{
+ return """ if $_ == 34;
+ return "&" if $_ == 38;
+ return "'" if $_ == 39;
+ return "<" if $_ == 60;
+ return chr $_;
+}
+
+sub entity_encoded_translation
+{
+ my ($lang, $string) = @_;
+
+ my $translation = $translations{$lang, $string};
+ return $string if !$translation;
+ return entity_encode ($translation);
+}
+
+## XML (bonobo-activation specific) merge code
+
+sub ba_merge_translations
+{
+ my $source;
+
+ {
+ local $/; # slurp mode
+ open INPUT, "<$FILE" or die "can't open $FILE: $!";
+ $source = <INPUT>;
+ close INPUT;
+ }
+
+ open OUTPUT, ">$OUTFILE" or die "can't open $OUTFILE: $!";
+ # Binmode so that selftest works ok if using a native Win32 Perl...
+ binmode (OUTPUT) if $^O eq 'MSWin32';
+
+ while ($source =~ s|^(.*?)([ \t]*<\s*$w+\s+($w+\s*=\s*"$q"\s*)+/?>)([ \t]*\n)?||s)
+ {
+ print OUTPUT $1;
+
+ my $node = $2 . "\n";
+
+ my @strings = ();
+ $_ = $node;
+ while (s/(\s)_($w+\s*=\s*"($q)")/$1$2/s) {
+ push @strings, entity_decode($3);
+ }
+ print OUTPUT;
+
+ my %langs;
+ for my $string (@strings)
+ {
+ for my $lang (keys %po_files_by_lang)
+ {
+ $langs{$lang} = 1 if $translations{$lang, $string};
+ }
+ }
+
+ for my $lang (sort keys %langs)
+ {
+ $_ = $node;
+ s/(\sname\s*=\s*)"($q)"/$1"$2-$lang"/s;
+ s/(\s)_($w+\s*=\s*")($q)"/$1 . $2 . entity_encoded_translation($lang, $3) . '"'/seg;
+ print OUTPUT;
+ }
+ }
+
+ print OUTPUT $source;
+
+ close OUTPUT;
+}
+
+
+## XML (non-bonobo-activation) merge code
+
+
+# Process tag attributes
+# Only parameter is a HASH containing attributes -> values mapping
+sub getAttributeString
+{
+ my $sub = shift;
+ my $do_translate = shift || 0;
+ my $language = shift || "";
+ my $result = "";
+ my $translate = shift;
+ foreach my $e (reverse(sort(keys %{ $sub }))) {
+ my $key = $e;
+ my $string = $sub->{$e};
+ my $quote = '"';
+
+ $string =~ s/^[\s]+//;
+ $string =~ s/[\s]+$//;
+
+ if ($string =~ /^'.*'$/)
+ {
+ $quote = "'";
+ }
+ $string =~ s/^['"]//g;
+ $string =~ s/['"]$//g;
+
+ if ($do_translate && $key =~ /^_/) {
+ $key =~ s|^_||g;
+ if ($language) {
+ # Handle translation
+ my $decode_string = entity_decode($string);
+ my $translation = $translations{$language, $decode_string};
+ if ($translation) {
+ $translation = entity_encode($translation);
+ $string = $translation;
+ }
+ $$translate = 2;
+ } else {
+ $$translate = 2 if ($translate && (!$$translate)); # watch not to "overwrite" $translate
+ }
+ }
+
+ $result .= " $key=$quote$string$quote";
+ }
+ return $result;
+}
+
+# Returns a translatable string from XML node, it works on contents of every node in XML::Parser tree
+sub getXMLstring
+{
+ my $ref = shift;
+ my $spacepreserve = shift || 0;
+ my @list = @{ $ref };
+ my $result = "";
+
+ my $count = scalar(@list);
+ my $attrs = $list[0];
+ my $index = 1;
+
+ $spacepreserve = 1 if ((exists $attrs->{"xml:space"}) && ($attrs->{"xml:space"} =~ /^["']?preserve["']?$/));
+ $spacepreserve = 0 if ((exists $attrs->{"xml:space"}) && ($attrs->{"xml:space"} =~ /^["']?default["']?$/));
+
+ while ($index < $count) {
+ my $type = $list[$index];
+ my $content = $list[$index+1];
+ if (! $type ) {
+ # We've got CDATA
+ if ($content) {
+ # lets strip the whitespace here, and *ONLY* here
+ $content =~ s/\s+/ /gs if (!$spacepreserve);
+ $result .= $content;
+ }
+ } elsif ( "$type" ne "1" ) {
+ # We've got another element
+ $result .= "<$type";
+ $result .= getAttributeString(@{$content}[0], 0); # no nested translatable elements
+ if ($content) {
+ my $subresult = getXMLstring($content, $spacepreserve);
+ if ($subresult) {
+ $result .= ">".$subresult . "</$type>";
+ } else {
+ $result .= "/>";
+ }
+ } else {
+ $result .= "/>";
+ }
+ }
+ $index += 2;
+ }
+ return $result;
+}
+
+# Translate list of nodes if necessary
+sub translate_subnodes
+{
+ my $fh = shift;
+ my $content = shift;
+ my $language = shift || "";
+ my $singlelang = shift || 0;
+ my $spacepreserve = shift || 0;
+
+ my @nodes = @{ $content };
+
+ my $count = scalar(@nodes);
+ my $index = 0;
+ while ($index < $count) {
+ my $type = $nodes[$index];
+ my $rest = $nodes[$index+1];
+ if ($singlelang) {
+ my $oldMO = $MULTIPLE_OUTPUT;
+ $MULTIPLE_OUTPUT = 1;
+ traverse($fh, $type, $rest, $language, $spacepreserve);
+ $MULTIPLE_OUTPUT = $oldMO;
+ } else {
+ traverse($fh, $type, $rest, $language, $spacepreserve);
+ }
+ $index += 2;
+ }
+}
+
+sub isWellFormedXmlFragment
+{
+ my $ret = eval 'require XML::Parser';
+ if(!$ret) {
+ die "You must have XML::Parser installed to run $0\n\n";
+ }
+
+ my $fragment = shift;
+ return 0 if (!$fragment);
+
+ $fragment = "<root>$fragment</root>";
+ my $xp = new XML::Parser(Style => 'Tree');
+ my $tree = 0;
+ eval { $tree = $xp->parse($fragment); };
+ return $tree;
+}
+
+sub traverse
+{
+ my $fh = shift;
+ my $nodename = shift;
+ my $content = shift;
+ my $language = shift || "";
+ my $spacepreserve = shift || 0;
+
+ if (!$nodename) {
+ if ($content =~ /^[\s]*$/) {
+ $leading_space .= $content;
+ }
+ print $fh $content;
+ } else {
+ # element
+ my @all = @{ $content };
+ my $attrs = shift @all;
+ my $translate = 0;
+ my $outattr = getAttributeString($attrs, 1, $language, \$translate);
+
+ if ($nodename =~ /^_/) {
+ $translate = 1;
+ $nodename =~ s/^_//;
+ }
+ my $lookup = '';
+
+ $spacepreserve = 0 if ((exists $attrs->{"xml:space"}) && ($attrs->{"xml:space"} =~ /^["']?default["']?$/));
+ $spacepreserve = 1 if ((exists $attrs->{"xml:space"}) && ($attrs->{"xml:space"} =~ /^["']?preserve["']?$/));
+
+ print $fh "<$nodename", $outattr;
+ if ($translate) {
+ $lookup = getXMLstring($content, $spacepreserve);
+ if (!$spacepreserve) {
+ $lookup =~ s/^\s+//s;
+ $lookup =~ s/\s+$//s;
+ }
+
+ if ($lookup || $translate == 2) {
+ my $translation = $translations{$language, $lookup} if isWellFormedXmlFragment($translations{$language, $lookup});
+ if ($MULTIPLE_OUTPUT && ($translation || $translate == 2)) {
+ $translation = $lookup if (!$translation);
+ print $fh " xml:lang=\"", $language, "\"" if $language;
+ print $fh ">";
+ if ($translate == 2) {
+ translate_subnodes($fh, \@all, $language, 1, $spacepreserve);
+ } else {
+ print $fh $translation;
+ }
+ print $fh "</$nodename>";
+
+ return; # this means there will be no same translation with xml:lang="$language"...
+ # if we want them both, just remove this "return"
+ } else {
+ print $fh ">";
+ if ($translate == 2) {
+ translate_subnodes($fh, \@all, $language, 1, $spacepreserve);
+ } else {
+ print $fh $lookup;
+ }
+ print $fh "</$nodename>";
+ }
+ } else {
+ print $fh "/>";
+ }
+
+ for my $lang (sort keys %po_files_by_lang) {
+ if ($MULTIPLE_OUTPUT && $lang ne "$language") {
+ next;
+ }
+ if ($lang) {
+ # Handle translation
+ #
+ my $translate = 0;
+ my $localattrs = getAttributeString($attrs, 1, $lang, \$translate);
+ my $translation = $translations{$lang, $lookup} if isWellFormedXmlFragment($translations{$lang, $lookup});
+ if ($translate && !$translation) {
+ $translation = $lookup;
+ }
+
+ if ($translation || $translate) {
+ print $fh "\n";
+ $leading_space =~ s/.*\n//g;
+ print $fh $leading_space;
+ print $fh "<", $nodename, " xml:lang=\"", $lang, "\"", $localattrs, ">";
+ if ($translate == 2) {
+ translate_subnodes($fh, \@all, $lang, 1, $spacepreserve);
+ } else {
+ print $fh $translation;
+ }
+ print $fh "</$nodename>";
+ }
+ }
+ }
+
+ } else {
+ my $count = scalar(@all);
+ if ($count > 0) {
+ print $fh ">";
+ my $index = 0;
+ while ($index < $count) {
+ my $type = $all[$index];
+ my $rest = $all[$index+1];
+ traverse($fh, $type, $rest, $language, $spacepreserve);
+ $index += 2;
+ }
+ print $fh "</$nodename>";
+ } else {
+ print $fh "/>";
+ }
+ }
+ }
+}
+
+sub intltool_tree_comment
+{
+ my $expat = shift;
+ my $data = shift;
+ my $clist = $expat->{Curlist};
+ my $pos = $#$clist;
+
+ push @$clist, 1 => $data;
+}
+
+sub intltool_tree_cdatastart
+{
+ my $expat = shift;
+ my $clist = $expat->{Curlist};
+ my $pos = $#$clist;
+
+ push @$clist, 0 => $expat->original_string();
+}
+
+sub intltool_tree_cdataend
+{
+ my $expat = shift;
+ my $clist = $expat->{Curlist};
+ my $pos = $#$clist;
+
+ $clist->[$pos] .= $expat->original_string();
+}
+
+sub intltool_tree_char
+{
+ my $expat = shift;
+ my $text = shift;
+ my $clist = $expat->{Curlist};
+ my $pos = $#$clist;
+
+ # Use original_string so that we retain escaped entities
+ # in CDATA sections.
+ #
+ if ($pos > 0 and $clist->[$pos - 1] eq '0') {
+ $clist->[$pos] .= $expat->original_string();
+ } else {
+ push @$clist, 0 => $expat->original_string();
+ }
+}
+
+sub intltool_tree_start
+{
+ my $expat = shift;
+ my $tag = shift;
+ my @origlist = ();
+
+ # Use original_string so that we retain escaped entities
+ # in attribute values. We must convert the string to an
+ # @origlist array to conform to the structure of the Tree
+ # Style.
+ #
+ my @original_array = split /\x/, $expat->original_string();
+ my $source = $expat->original_string();
+
+ # Remove leading tag.
+ #
+ $source =~ s|^\s*<\s*(\S+)||s;
+
+ # Grab attribute key/value pairs and push onto @origlist array.
+ #
+ while ($source)
+ {
+ if ($source =~ /^\s*([\w:-]+)\s*[=]\s*["]/)
+ {
+ $source =~ s|^\s*([\w:-]+)\s*[=]\s*["]([^"]*)["]||s;
+ push @origlist, $1;
+ push @origlist, '"' . $2 . '"';
+ }
+ elsif ($source =~ /^\s*([\w:-]+)\s*[=]\s*[']/)
+ {
+ $source =~ s|^\s*([\w:-]+)\s*[=]\s*[']([^']*)[']||s;
+ push @origlist, $1;
+ push @origlist, "'" . $2 . "'";
+ }
+ else
+ {
+ last;
+ }
+ }
+
+ my $ol = [ { @origlist } ];
+
+ push @{ $expat->{Lists} }, $expat->{Curlist};
+ push @{ $expat->{Curlist} }, $tag => $ol;
+ $expat->{Curlist} = $ol;
+}
+
+sub readXml
+{
+ my $filename = shift || return;
+ if(!-f $filename) {
+ die "ERROR Cannot find filename: $filename\n";
+ }
+
+ my $ret = eval 'require XML::Parser';
+ if(!$ret) {
+ die "You must have XML::Parser installed to run $0\n\n";
+ }
+ my $xp = new XML::Parser(Style => 'Tree');
+ $xp->setHandlers(Char => \&intltool_tree_char);
+ $xp->setHandlers(Start => \&intltool_tree_start);
+ $xp->setHandlers(CdataStart => \&intltool_tree_cdatastart);
+ $xp->setHandlers(CdataEnd => \&intltool_tree_cdataend);
+ my $tree = $xp->parsefile($filename);
+
+# <foo><head id="a">Hello <em>there</em></head><bar>Howdy<ref/></bar>do</foo>
+# would be:
+# [foo, [{}, head, [{id => "a"}, 0, "Hello ", em, [{}, 0, "there"]], bar, [{},
+# 0, "Howdy", ref, [{}]], 0, "do" ] ]
+
+ return $tree;
+}
+
+sub print_header
+{
+ my $infile = shift;
+ my $fh = shift;
+ my $source;
+
+ if(!-f $infile) {
+ die "ERROR Cannot find filename: $infile\n";
+ }
+
+ print $fh qq{<?xml version="1.0" encoding="UTF-8"?>\n};
+ {
+ local $/;
+ open DOCINPUT, "<${FILE}" or die;
+ $source = <DOCINPUT>;
+ close DOCINPUT;
+ }
+ if ($source =~ /(<!DOCTYPE.*\[.*\]\s*>)/s)
+ {
+ print $fh "$1\n";
+ }
+ elsif ($source =~ /(<!DOCTYPE[^>]*>)/s)
+ {
+ print $fh "$1\n";
+ }
+}
+
+sub parseTree
+{
+ my $fh = shift;
+ my $ref = shift;
+ my $language = shift || "";
+
+ my $name = shift @{ $ref };
+ my $cont = shift @{ $ref };
+
+ while (!$name || "$name" eq "1") {
+ $name = shift @{ $ref };
+ $cont = shift @{ $ref };
+ }
+
+ my $spacepreserve = 0;
+ my $attrs = @{$cont}[0];
+ $spacepreserve = 1 if ((exists $attrs->{"xml:space"}) && ($attrs->{"xml:space"} =~ /^["']?preserve["']?$/));
+
+ traverse($fh, $name, $cont, $language, $spacepreserve);
+}
+
+sub xml_merge_output
+{
+ my $source;
+
+ if ($MULTIPLE_OUTPUT) {
+ for my $lang (sort keys %po_files_by_lang) {
+ if ( ! -d $lang ) {
+ mkdir $lang or -d $lang or die "Cannot create subdirectory $lang: $!\n";
+ }
+ open OUTPUT, ">$lang/$OUTFILE" or die "Cannot open $lang/$OUTFILE: $!\n";
+ binmode (OUTPUT) if $^O eq 'MSWin32';
+ my $tree = readXml($FILE);
+ print_header($FILE, \*OUTPUT);
+ parseTree(\*OUTPUT, $tree, $lang);
+ close OUTPUT;
+ print "CREATED $lang/$OUTFILE\n" unless $QUIET_ARG;
+ }
+ }
+ open OUTPUT, ">$OUTFILE" or die "Cannot open $OUTFILE: $!\n";
+ binmode (OUTPUT) if $^O eq 'MSWin32';
+ my $tree = readXml($FILE);
+ print_header($FILE, \*OUTPUT);
+ parseTree(\*OUTPUT, $tree);
+ close OUTPUT;
+ print "CREATED $OUTFILE\n" unless $QUIET_ARG;
+}
+
+sub keys_merge_translations
+{
+ open INPUT, "<${FILE}" or die;
+ open OUTPUT, ">${OUTFILE}" or die;
+ binmode (OUTPUT) if $^O eq 'MSWin32';
+
+ while (<INPUT>)
+ {
+ if (s/^(\s*)_(\w+=(.*))/$1$2/)
+ {
+ my $string = $3;
+
+ print OUTPUT;
+
+ my $non_translated_line = $_;
+
+ for my $lang (sort keys %po_files_by_lang)
+ {
+ my $translation = $translations{$lang, $string};
+ next if !$translation;
+
+ $_ = $non_translated_line;
+ s/(\w+)=.*/[$lang]$1=$translation/;
+ print OUTPUT;
+ }
+ }
+ else
+ {
+ print OUTPUT;
+ }
+ }
+
+ close OUTPUT;
+ close INPUT;
+}
+
+sub desktop_merge_translations
+{
+ open INPUT, "<${FILE}" or die;
+ open OUTPUT, ">${OUTFILE}" or die;
+ binmode (OUTPUT) if $^O eq 'MSWin32';
+
+ while (<INPUT>)
+ {
+ if (s/^(\s*)_(\w+=(.*))/$1$2/)
+ {
+ my $string = $3;
+
+ print OUTPUT;
+
+ my $non_translated_line = $_;
+
+ for my $lang (sort keys %po_files_by_lang)
+ {
+ my $translation = $translations{$lang, $string};
+ next if !$translation;
+
+ $_ = $non_translated_line;
+ s/(\w+)=.*/${1}[$lang]=$translation/;
+ print OUTPUT;
+ }
+ }
+ else
+ {
+ print OUTPUT;
+ }
+ }
+
+ close OUTPUT;
+ close INPUT;
+}
+
+sub schemas_merge_translations
+{
+ my $source;
+
+ {
+ local $/; # slurp mode
+ open INPUT, "<$FILE" or die "can't open $FILE: $!";
+ $source = <INPUT>;
+ close INPUT;
+ }
+
+ open OUTPUT, ">$OUTFILE" or die;
+ binmode (OUTPUT) if $^O eq 'MSWin32';
+
+ # FIXME: support attribute translations
+
+ # Empty nodes never need translation, so unmark all of them.
+ # For example, <_foo/> is just replaced by <foo/>.
+ $source =~ s|<\s*_($w+)\s*/>|<$1/>|g;
+
+ while ($source =~ s/
+ (.*?)
+ (\s+)(<locale\ name="C">(\s*)
+ (<default>\s*(?:<!--[^>]*?-->\s*)?(.*?)\s*<\/default>)?(\s*)
+ (<short>\s*(?:<!--[^>]*?-->\s*)?(.*?)\s*<\/short>)?(\s*)
+ (<long>\s*(?:<!--[^>]*?-->\s*)?(.*?)\s*<\/long>)?(\s*)
+ <\/locale>)
+ //sx)
+ {
+ print OUTPUT $1;
+
+ my $locale_start_spaces = $2 ? $2 : '';
+ my $default_spaces = $4 ? $4 : '';
+ my $short_spaces = $7 ? $7 : '';
+ my $long_spaces = $10 ? $10 : '';
+ my $locale_end_spaces = $13 ? $13 : '';
+ my $c_default_block = $3 ? $3 : '';
+ my $default_string = $6 ? $6 : '';
+ my $short_string = $9 ? $9 : '';
+ my $long_string = $12 ? $12 : '';
+
+ print OUTPUT "$locale_start_spaces$c_default_block";
+
+ $default_string =~ s/\s+/ /g;
+ $default_string = entity_decode($default_string);
+ $short_string =~ s/\s+/ /g;
+ $short_string = entity_decode($short_string);
+ $long_string =~ s/\s+/ /g;
+ $long_string = entity_decode($long_string);
+
+ for my $lang (sort keys %po_files_by_lang)
+ {
+ my $default_translation = $translations{$lang, $default_string};
+ my $short_translation = $translations{$lang, $short_string};
+ my $long_translation = $translations{$lang, $long_string};
+
+ next if (!$default_translation && !$short_translation &&
+ !$long_translation);
+
+ print OUTPUT "\n$locale_start_spaces<locale name=\"$lang\">";
+
+ print OUTPUT "$default_spaces";
+
+ if ($default_translation)
+ {
+ $default_translation = entity_encode($default_translation);
+ print OUTPUT "<default>$default_translation</default>";
+ }
+
+ print OUTPUT "$short_spaces";
+
+ if ($short_translation)
+ {
+ $short_translation = entity_encode($short_translation);
+ print OUTPUT "<short>$short_translation</short>";
+ }
+
+ print OUTPUT "$long_spaces";
+
+ if ($long_translation)
+ {
+ $long_translation = entity_encode($long_translation);
+ print OUTPUT "<long>$long_translation</long>";
+ }
+
+ print OUTPUT "$locale_end_spaces</locale>";
+ }
+ }
+
+ print OUTPUT $source;
+
+ close OUTPUT;
+}
+
+sub rfc822deb_merge_translations
+{
+ my %encodings = ();
+ for my $lang (keys %po_files_by_lang) {
+ $encodings{$lang} = ($UTF8_ARG ? 'UTF-8' : get_po_encoding($po_files_by_lang{$lang}));
+ }
+
+ my $source;
+
+ $Text::Wrap::huge = 'overflow';
+ $Text::Wrap::break = qr/\n|\s(?=\S)/;
+
+ {
+ local $/; # slurp mode
+ open INPUT, "<$FILE" or die "can't open $FILE: $!";
+ $source = <INPUT>;
+ close INPUT;
+ }
+
+ open OUTPUT, ">${OUTFILE}" or die;
+ binmode (OUTPUT) if $^O eq 'MSWin32';
+
+ while ($source =~ /(^|\n+)(_*)([^:\s]+)(:[ \t]*)(.*?)(?=\n[\S\n]|$)/sg)
+ {
+ my $sep = $1;
+ my $non_translated_line = $3.$4;
+ my $string = $5;
+ my $underscore = length($2);
+ next if $underscore eq 0 && $non_translated_line =~ /^#/;
+ # Remove [] dummy strings
+ my $stripped = $string;
+ $stripped =~ s/\[\s[^\[\]]*\],/,/g if $underscore eq 2;
+ $stripped =~ s/\[\s[^\[\]]*\]$//;
+ $non_translated_line .= $stripped;
+
+ print OUTPUT $sep.$non_translated_line;
+
+ if ($underscore)
+ {
+ my @str_list = rfc822deb_split($underscore, $string);
+
+ for my $lang (sort keys %po_files_by_lang)
+ {
+ my $is_translated = 1;
+ my $str_translated = '';
+ my $first = 1;
+
+ for my $str (@str_list)
+ {
+ my $translation = $translations{$lang, $str};
+
+ if (!$translation)
+ {
+ $is_translated = 0;
+ last;
+ }
+
+ # $translation may also contain [] dummy
+ # strings, mostly to indicate an empty string
+ $translation =~ s/\[\s[^\[\]]*\]$//;
+
+ if ($first)
+ {
+ if ($underscore eq 2)
+ {
+ $str_translated .= $translation;
+ }
+ else
+ {
+ $str_translated .=
+ Text::Tabs::expand($translation) .
+ "\n";
+ }
+ }
+ else
+ {
+ if ($underscore eq 2)
+ {
+ $str_translated .= ', ' . $translation;
+ }
+ else
+ {
+ $str_translated .= Text::Tabs::expand(
+ Text::Wrap::wrap(' ', ' ', $translation)) .
+ "\n .\n";
+ }
+ }
+ $first = 0;
+
+ # To fix some problems with Text::Wrap::wrap
+ $str_translated =~ s/(\n )+\n/\n .\n/g;
+ }
+ next unless $is_translated;
+
+ $str_translated =~ s/\n \.\n$//;
+ $str_translated =~ s/\s+$//;
+
+ $_ = $non_translated_line;
+ s/^(\w+):\s*.*/$sep${1}-$lang.$encodings{$lang}: $str_translated/s;
+ print OUTPUT;
+ }
+ }
+ }
+ print OUTPUT "\n";
+
+ close OUTPUT;
+ close INPUT;
+}
+
+sub rfc822deb_split
+{
+ # Debian defines a special way to deal with rfc822-style files:
+ # when a value contain newlines, it consists of
+ # 1. a short form (first line)
+ # 2. a long description, all lines begin with a space,
+ # and paragraphs are separated by a single dot on a line
+ # This routine returns an array of all paragraphs, and reformat
+ # them.
+ # When first argument is 2, the string is a comma separated list of
+ # values.
+ my $type = shift;
+ my $text = shift;
+ $text =~ s/^[ \t]//mg;
+ return (split(/, */, $text, 0)) if $type ne 1;
+ return ($text) if $text !~ /\n/;
+
+ $text =~ s/([^\n]*)\n//;
+ my @list = ($1);
+ my $str = '';
+
+ for my $line (split (/\n/, $text))
+ {
+ chomp $line;
+ if ($line =~ /^\.\s*$/)
+ {
+ # New paragraph
+ $str =~ s/\s*$//;
+ push(@list, $str);
+ $str = '';
+ }
+ elsif ($line =~ /^\s/)
+ {
+ # Line which must not be reformatted
+ $str .= "\n" if length ($str) && $str !~ /\n$/;
+ $line =~ s/\s+$//;
+ $str .= $line."\n";
+ }
+ else
+ {
+ # Continuation line, remove newline
+ $str .= " " if length ($str) && $str !~ /\n$/;
+ $str .= $line;
+ }
+ }
+
+ $str =~ s/\s*$//;
+ push(@list, $str) if length ($str);
+
+ return @list;
+}
+
+sub quoted_translation
+{
+ my ($lang, $string) = @_;
+
+ $string =~ s/\\\"/\"/g;
+
+ my $translation = $translations{$lang, $string};
+ $translation = $string if !$translation;
+
+ $translation =~ s/\"/\\\"/g;
+ return $translation
+}
+
+sub quoted_merge_translations
+{
+ if (!$MULTIPLE_OUTPUT) {
+ print "Quoted only supports Multiple Output.\n";
+ exit(1);
+ }
+
+ for my $lang (sort keys %po_files_by_lang) {
+ if ( ! -d $lang ) {
+ mkdir $lang or -d $lang or die "Cannot create subdirectory $lang: $!\n";
+ }
+ open INPUT, "<${FILE}" or die;
+ open OUTPUT, ">$lang/$OUTFILE" or die "Cannot open $lang/$OUTFILE: $!\n";
+ binmode (OUTPUT) if $^O eq 'MSWin32';
+ while (<INPUT>)
+ {
+ s/\"(([^\"]|\\\")*[^\\\"])\"/"\"" . "ed_translation($lang, $1) . "\""/ge;
+ print OUTPUT;
+ }
+ close OUTPUT;
+ close INPUT;
+ }
+}
diff --git a/tools/intltool-update.in b/tools/intltool-update.in
new file mode 100644
index 0000000..bffd10f
--- /dev/null
+++ b/tools/intltool-update.in
@@ -0,0 +1,1164 @@
+#!@INTLTOOL_PERL@ -w
+# -*- Mode: perl; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+
+#
+# The Intltool Message Updater
+#
+# Copyright (C) 2000-2003 Free Software Foundation.
+#
+# Intltool is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# version 2 published by the Free Software Foundation.
+#
+# Intltool is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+#
+# Authors: Kenneth Christiansen <kenneth@xxxxxxx>
+# Maciej Stachowiak
+# Darin Adler <darin@xxxxxxxxxxxxx>
+
+## Release information
+my $PROGRAM = "intltool-update";
+my $VERSION = "0.36.2";
+my $PACKAGE = "intltool";
+
+## Loaded modules
+use strict;
+use Getopt::Long;
+use Cwd;
+use File::Copy;
+use File::Find;
+
+## Scalars used by the option stuff
+my $HELP_ARG = 0;
+my $VERSION_ARG = 0;
+my $DIST_ARG = 0;
+my $POT_ARG = 0;
+my $HEADERS_ARG = 0;
+my $MAINTAIN_ARG = 0;
+my $REPORT_ARG = 0;
+my $VERBOSE = 0;
+my $GETTEXT_PACKAGE = "";
+my $OUTPUT_FILE = "";
+
+my @languages;
+my %varhash = ();
+my %po_files_by_lang = ();
+
+# Regular expressions to categorize file types.
+# FIXME: Please check if the following is correct
+
+my $xml_support =
+"xml(?:\\.in)*|". # http://www.w3.org/XML/ (Note: .in is not required)
+"ui|". # Bonobo specific - User Interface desc. files
+"lang|". # ?
+"glade2?(?:\\.in)*|". # Glade specific - User Interface desc. files (Note: .in is not required)
+"scm(?:\\.in)*|". # ? (Note: .in is not required)
+"oaf(?:\\.in)+|". # DEPRECATED: Replaces by Bonobo .server files
+"etspec|". # ?
+"server(?:\\.in)+|". # Bonobo specific
+"sheet(?:\\.in)+|". # ?
+"schemas(?:\\.in)+|". # GConf specific
+"pong(?:\\.in)+|". # DEPRECATED: PONG is not used [by GNOME] any longer.
+"kbd(?:\\.in)+|". # GOK specific.
+"policy(?:\\.in)+"; # PolicyKit files
+
+my $ini_support =
+"icon(?:\\.in)+|". # http://www.freedesktop.org/Standards/icon-theme-spec
+"desktop(?:\\.in)+|". # http://www.freedesktop.org/Standards/menu-spec
+"caves(?:\\.in)+|". # GNOME Games specific
+"directory(?:\\.in)+|". # http://www.freedesktop.org/Standards/menu-spec
+"soundlist(?:\\.in)+|". # GNOME specific
+"keys(?:\\.in)+|". # GNOME Mime database specific
+"theme(?:\\.in)+|". # http://www.freedesktop.org/Standards/icon-theme-spec
+"service(?:\\.in)+"; # DBus specific
+
+my $buildin_gettext_support =
+"c|y|cs|cc|cpp|c\\+\\+|h|hh|gob|py";
+
+## Always flush buffer when printing
+$| = 1;
+
+## Sometimes the source tree will be rooted somewhere else.
+my $SRCDIR = $ENV{"srcdir"} || ".";
+my $POTFILES_in;
+
+$POTFILES_in = "<$SRCDIR/POTFILES.in";
+
+my $devnull = ($^O eq 'MSWin32' ? 'NUL:' : '/dev/null');
+
+## Handle options
+GetOptions
+(
+ "help" => \$HELP_ARG,
+ "version" => \$VERSION_ARG,
+ "dist|d" => \$DIST_ARG,
+ "pot|p" => \$POT_ARG,
+ "headers|s" => \$HEADERS_ARG,
+ "maintain|m" => \$MAINTAIN_ARG,
+ "report|r" => \$REPORT_ARG,
+ "verbose|x" => \$VERBOSE,
+ "gettext-package|g=s" => \$GETTEXT_PACKAGE,
+ "output-file|o=s" => \$OUTPUT_FILE,
+ ) or &Console_WriteError_InvalidOption;
+
+&Console_Write_IntltoolHelp if $HELP_ARG;
+&Console_Write_IntltoolVersion if $VERSION_ARG;
+
+my $arg_count = ($DIST_ARG > 0)
+ + ($POT_ARG > 0)
+ + ($HEADERS_ARG > 0)
+ + ($MAINTAIN_ARG > 0)
+ + ($REPORT_ARG > 0);
+
+&Console_Write_IntltoolHelp if $arg_count > 1;
+
+my $PKGNAME = FindPackageName ();
+
+# --version and --help don't require a module name
+my $MODULE = $GETTEXT_PACKAGE || $PKGNAME || "unknown";
+
+if ($POT_ARG)
+{
+ &GenerateHeaders;
+ &GeneratePOTemplate;
+}
+elsif ($HEADERS_ARG)
+{
+ &GenerateHeaders;
+}
+elsif ($MAINTAIN_ARG)
+{
+ &FindLeftoutFiles;
+}
+elsif ($REPORT_ARG)
+{
+ &GenerateHeaders;
+ &GeneratePOTemplate;
+ &Console_Write_CoverageReport;
+}
+elsif ((defined $ARGV[0]) && $ARGV[0] =~ /^[a-z]/)
+{
+ my $lang = $ARGV[0];
+
+ ## Report error if the language file supplied
+ ## to the command line is non-existent
+ &Console_WriteError_NotExisting("$SRCDIR/$lang.po")
+ if ! -s "$SRCDIR/$lang.po";
+
+ if (!$DIST_ARG)
+ {
+ print "Working, please wait..." if $VERBOSE;
+ &GenerateHeaders;
+ &GeneratePOTemplate;
+ }
+ &POFile_Update ($lang, $OUTPUT_FILE);
+ &Console_Write_TranslationStatus ($lang, $OUTPUT_FILE);
+}
+else
+{
+ &Console_Write_IntltoolHelp;
+}
+
+exit;
+
+#########
+
+sub Console_Write_IntltoolVersion
+{
+ print <<_EOF_;
+${PROGRAM} (${PACKAGE}) $VERSION
+Written by Kenneth Christiansen, Maciej Stachowiak, and Darin Adler.
+
+Copyright (C) 2000-2003 Free Software Foundation, Inc.
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+_EOF_
+ exit;
+}
+
+sub Console_Write_IntltoolHelp
+{
+ print <<_EOF_;
+Usage: ${PROGRAM} [OPTION]... LANGCODE
+Updates PO template files and merge them with the translations.
+
+Mode of operation (only one is allowed):
+ -p, --pot generate the PO template only
+ -s, --headers generate the header files in POTFILES.in
+ -m, --maintain search for left out files from POTFILES.in
+ -r, --report display a status report for the module
+ -d, --dist merge LANGCODE.po with existing PO template
+
+Extra options:
+ -g, --gettext-package=NAME override PO template name, useful with --pot
+ -o, --output-file=FILE write merged translation to FILE
+ -x, --verbose display lots of feedback
+ --help display this help and exit
+ --version output version information and exit
+
+Examples of use:
+${PROGRAM} --pot just create a new PO template
+${PROGRAM} xy create new PO template and merge xy.po with it
+
+Report bugs to http://bugzilla.gnome.org/ (product name "$PACKAGE")
+or send email to <xml-i18n-tools\@gnome.org>.
+_EOF_
+ exit;
+}
+
+sub echo_n
+{
+ my $str = shift;
+ my $ret = `echo "$str"`;
+
+ $ret =~ s/\n$//; # do we need the "s" flag?
+
+ return $ret;
+}
+
+sub POFile_DetermineType ($)
+{
+ my $type = $_;
+ my $gettext_type;
+
+ my $xml_regex = "(?:" . $xml_support . ")";
+ my $ini_regex = "(?:" . $ini_support . ")";
+ my $buildin_regex = "(?:" . $buildin_gettext_support . ")";
+
+ if ($type =~ /\[type: gettext\/([^\]].*)]/)
+ {
+ $gettext_type=$1;
+ }
+ elsif ($type =~ /schemas(\.in)+$/)
+ {
+ $gettext_type="schemas";
+ }
+ elsif ($type =~ /glade2?(\.in)*$/)
+ {
+ $gettext_type="glade";
+ }
+ elsif ($type =~ /scm(\.in)*$/)
+ {
+ $gettext_type="scheme";
+ }
+ elsif ($type =~ /keys(\.in)+$/)
+ {
+ $gettext_type="keys";
+ }
+
+ # bucket types
+
+ elsif ($type =~ /$xml_regex$/)
+ {
+ $gettext_type="xml";
+ }
+ elsif ($type =~ /$ini_regex$/)
+ {
+ $gettext_type="ini";
+ }
+ elsif ($type =~ /$buildin_regex$/)
+ {
+ $gettext_type="buildin";
+ }
+ else
+ {
+ $gettext_type="unknown";
+ }
+
+ return "gettext\/$gettext_type";
+}
+
+sub TextFile_DetermineEncoding ($)
+{
+ my $gettext_code="ASCII"; # All files are ASCII by default
+ my $filetype=`file $_ | cut -d ' ' -f 2`;
+
+ if ($? eq "0")
+ {
+ if ($filetype =~ /^(ISO|UTF)/)
+ {
+ chomp ($gettext_code = $filetype);
+ }
+ elsif ($filetype =~ /^XML/)
+ {
+ $gettext_code="UTF-8"; # We asume that .glade and other .xml files are UTF-8
+ }
+ }
+
+ return $gettext_code;
+}
+
+sub isNotValidMissing
+{
+ my ($file) = @_;
+
+ return if $file =~ /^\{arch\}\/.*$/;
+ return if $file =~ /^$varhash{"PACKAGE"}-$varhash{"VERSION"}\/.*$/;
+}
+
+sub FindLeftoutFiles
+{
+ my (@buf_i18n_plain,
+ @buf_i18n_xml,
+ @buf_i18n_xml_unmarked,
+ @buf_i18n_ini,
+ @buf_potfiles,
+ @buf_potfiles_ignore,
+ @buf_allfiles,
+ @buf_allfiles_sorted,
+ @buf_potfiles_sorted,
+ @buf_potfiles_ignore_sorted
+ );
+
+ ## Search and find all translatable files
+ find sub {
+ push @buf_i18n_plain, "$File::Find::name" if /\.($buildin_gettext_support)$/;
+ push @buf_i18n_xml, "$File::Find::name" if /\.($xml_support)$/;
+ push @buf_i18n_ini, "$File::Find::name" if /\.($ini_support)$/;
+ push @buf_i18n_xml_unmarked, "$File::Find::name" if /\.(schemas(\.in)+)$/;
+ }, "..";
+ find sub {
+ push @buf_i18n_plain, "$File::Find::name" if /\.($buildin_gettext_support)$/;
+ push @buf_i18n_xml, "$File::Find::name" if /\.($xml_support)$/;
+ push @buf_i18n_ini, "$File::Find::name" if /\.($ini_support)$/;
+ push @buf_i18n_xml_unmarked, "$File::Find::name" if /\.(schemas(\.in)+)$/;
+ }, "$SRCDIR/..";
+
+ open POTFILES, $POTFILES_in or die "$PROGRAM: there's no POTFILES.in!\n";
+ @buf_potfiles = grep !/^(#|\s*$)/, <POTFILES>;
+ close POTFILES;
+
+ foreach (@buf_potfiles) {
+ s/^\[.*]\s*//;
+ }
+
+ print "Searching for missing translatable files...\n" if $VERBOSE;
+
+ ## Check if we should ignore some found files, when
+ ## comparing with POTFILES.in
+ foreach my $ignore ("POTFILES.skip", "POTFILES.ignore")
+ {
+ (-s "$SRCDIR/$ignore") or next;
+
+ if ("$ignore" eq "POTFILES.ignore")
+ {
+ print "The usage of POTFILES.ignore is deprecated. Please consider moving the\n".
+ "content of this file to POTFILES.skip.\n";
+ }
+
+ print "Found $ignore: Ignoring files...\n" if $VERBOSE;
+ open FILE, "<$SRCDIR/$ignore" or die "ERROR: Failed to open $SRCDIR/$ignore!\n";
+
+ while (<FILE>)
+ {
+ push @buf_potfiles_ignore, $_ unless /^(#|\s*$)/;
+ }
+ close FILE;
+
+ @buf_potfiles_ignore_sorted = sort (@buf_potfiles_ignore);
+ }
+
+ foreach my $file (@buf_i18n_plain)
+ {
+ my $in_comment = 0;
+ my $in_macro = 0;
+
+ open FILE, "<$file";
+ while (<FILE>)
+ {
+ # Handle continued multi-line comment.
+ if ($in_comment)
+ {
+ next unless s-.*\*/--;
+ $in_comment = 0;
+ }
+
+ # Handle continued macro.
+ if ($in_macro)
+ {
+ $in_macro = 0 unless /\\$/;
+ next;
+ }
+
+ # Handle start of macro (or any preprocessor directive).
+ if (/^\s*\#/)
+ {
+ $in_macro = 1 if /^([^\\]|\\.)*\\$/;
+ next;
+ }
+
+ # Handle comments and quoted text.
+ while (m-(/\*|//|\'|\")-) # \' and \" keep emacs perl mode happy
+ {
+ my $match = $1;
+ if ($match eq "/*")
+ {
+ if (!s-/\*.*?\*/--)
+ {
+ s-/\*.*--;
+ $in_comment = 1;
+ }
+ }
+ elsif ($match eq "//")
+ {
+ s-//.*--;
+ }
+ else # ' or "
+ {
+ if (!s-$match([^\\]|\\.)*?$match-QUOTEDTEXT-)
+ {
+ warn "mismatched quotes at line $. in $file\n";
+ s-$match.*--;
+ }
+ }
+ }
+
+ if (/\w\.GetString *\(QUOTEDTEXT/)
+ {
+ if (defined isNotValidMissing (unpack("x3 A*", $file))) {
+ ## Remove the first 3 chars and add newline
+ push @buf_allfiles, unpack("x3 A*", $file) . "\n";
+ }
+ last;
+ }
+
+ ## N_ Q_ and _ are the three macros defined in gi8n.h
+ if (/[NQ]?_ *\(QUOTEDTEXT/)
+ {
+ if (defined isNotValidMissing (unpack("x3 A*", $file))) {
+ ## Remove the first 3 chars and add newline
+ push @buf_allfiles, unpack("x3 A*", $file) . "\n";
+ }
+ last;
+ }
+ }
+ close FILE;
+ }
+
+ foreach my $file (@buf_i18n_xml)
+ {
+ open FILE, "<$file";
+
+ while (<FILE>)
+ {
+ # FIXME: share the pattern matching code with intltool-extract
+ if (/\s_[-A-Za-z0-9._:]+\s*=\s*\"([^"]+)\"/ || /<_[^>]+>/ || /translatable=\"yes\"/)
+ {
+ if (defined isNotValidMissing (unpack("x3 A*", $file))) {
+ push @buf_allfiles, unpack("x3 A*", $file) . "\n";
+ }
+ last;
+ }
+ }
+ close FILE;
+ }
+
+ foreach my $file (@buf_i18n_ini)
+ {
+ open FILE, "<$file";
+ while (<FILE>)
+ {
+ if (/_(.*)=/)
+ {
+ if (defined isNotValidMissing (unpack("x3 A*", $file))) {
+ push @buf_allfiles, unpack("x3 A*", $file) . "\n";
+ }
+ last;
+ }
+ }
+ close FILE;
+ }
+
+ foreach my $file (@buf_i18n_xml_unmarked)
+ {
+ if (defined isNotValidMissing (unpack("x3 A*", $file))) {
+ push @buf_allfiles, unpack("x3 A*", $file) . "\n";
+ }
+ }
+
+
+ @buf_allfiles_sorted = sort (@buf_allfiles);
+ @buf_potfiles_sorted = sort (@buf_potfiles);
+
+ my %in2;
+ foreach (@buf_potfiles_sorted)
+ {
+ s#^$SRCDIR/../##;
+ s#^$SRCDIR/##;
+ $in2{$_} = 1;
+ }
+
+ foreach (@buf_potfiles_ignore_sorted)
+ {
+ s#^$SRCDIR/../##;
+ s#^$SRCDIR/##;
+ $in2{$_} = 1;
+ }
+
+ my @result;
+
+ foreach (@buf_allfiles_sorted)
+ {
+ my $dummy = $_;
+ my $srcdir = $SRCDIR;
+
+ $srcdir =~ s#^../##;
+ $dummy =~ s#^$srcdir/../##;
+ $dummy =~ s#^$srcdir/##;
+ $dummy =~ s#_build/##;
+ if (!exists($in2{$dummy}))
+ {
+ push @result, $dummy
+ }
+ }
+
+ my @buf_potfiles_notexist;
+
+ foreach (@buf_potfiles_sorted)
+ {
+ chomp (my $dummy = $_);
+ if ("$dummy" ne "" and !(-f "$SRCDIR/../$dummy" or -f "../$dummy"))
+ {
+ push @buf_potfiles_notexist, $_;
+ }
+ }
+
+ ## Save file with information about the files missing
+ ## if any, and give information about this procedure.
+ if (@result + @buf_potfiles_notexist > 0)
+ {
+ if (@result)
+ {
+ print "\n" if $VERBOSE;
+ unlink "missing";
+ open OUT, ">missing";
+ print OUT @result;
+ close OUT;
+ warn "\e[1mThe following files contain translations and are currently not in use. Please\e[0m\n".
+ "\e[1mconsider adding these to the POTFILES.in file, located in the po/ directory.\e[0m\n\n";
+ print STDERR @result, "\n";
+ warn "If some of these files are left out on purpose then please add them to\n".
+ "POTFILES.skip instead of POTFILES.in. A file \e[1m'missing'\e[0m containing this list\n".
+ "of left out files has been written in the current directory.\n";
+ }
+ if (@buf_potfiles_notexist)
+ {
+ unlink "notexist";
+ open OUT, ">notexist";
+ print OUT @buf_potfiles_notexist;
+ close OUT;
+ warn "\n" if ($VERBOSE or @result);
+ warn "\e[1mThe following files do not exist anymore:\e[0m\n\n";
+ warn @buf_potfiles_notexist, "\n";
+ warn "Please remove them from POTFILES.in. A file \e[1m'notexist'\e[0m\n".
+ "containing this list of absent files has been written in the current directory.\n";
+ }
+ }
+
+ ## If there is nothing to complain about, notify the user
+ else {
+ print "\nAll files containing translations are present in POTFILES.in.\n" if $VERBOSE;
+ }
+}
+
+sub Console_WriteError_InvalidOption
+{
+ ## Handle invalid arguments
+ print STDERR "Try `${PROGRAM} --help' for more information.\n";
+ exit 1;
+}
+
+sub isProgramInPath
+{
+ my ($file) = @_;
+ # If either a file exists, or when run it returns 0 exit status
+ return 1 if ((-x $file) or (system("$file --version >$devnull") == 0));
+ return 0;
+}
+
+sub isGNUGettextTool
+{
+ my ($file) = @_;
+ # Check that we are using GNU gettext tools
+ if (isProgramInPath ($file))
+ {
+ my $version = `$file --version`;
+ return 1 if ($version =~ m/.*\(GNU .*\).*/);
+ }
+ return 0;
+}
+
+sub GenerateHeaders
+{
+ my $EXTRACT = $ENV{"INTLTOOL_EXTRACT"} || "intltool-extract";
+
+ ## Generate the .h header files, so we can allow glade and
+ ## xml translation support
+ if (! isProgramInPath ("$EXTRACT"))
+ {
+ print STDERR "\n *** The intltool-extract script wasn't found!"
+ ."\n *** Without it, intltool-update can not generate files.\n";
+ exit;
+ }
+ else
+ {
+ open (FILE, $POTFILES_in) or die "$PROGRAM: POTFILES.in not found.\n";
+
+ while (<FILE>)
+ {
+ chomp;
+ next if /^\[\s*encoding/;
+
+ ## Find xml files in POTFILES.in and generate the
+ ## files with help from the extract script
+
+ my $gettext_type= &POFile_DetermineType ($1);
+
+ if (/\.($xml_support|$ini_support)$/ || /^\[/)
+ {
+ s/^\[[^\[].*]\s*//;
+
+ my $filename = "../$_";
+
+ if ($VERBOSE)
+ {
+ system ($EXTRACT, "--update", "--srcdir=$SRCDIR",
+ "--type=$gettext_type", $filename);
+ }
+ else
+ {
+ system ($EXTRACT, "--update", "--type=$gettext_type",
+ "--srcdir=$SRCDIR", "--quiet", $filename);
+ }
+ }
+ }
+ close FILE;
+ }
+}
+
+#
+# Generate .pot file from POTFILES.in
+#
+sub GeneratePOTemplate
+{
+ my $XGETTEXT = $ENV{"XGETTEXT"} || "xgettext";
+ my $XGETTEXT_ARGS = $ENV{"XGETTEXT_ARGS"} || '';
+ chomp $XGETTEXT;
+
+ if (! isGNUGettextTool ("$XGETTEXT"))
+ {
+ print STDERR " *** GNU xgettext is not found on this system!\n".
+ " *** Without it, intltool-update can not extract strings.\n";
+ exit;
+ }
+
+ print "Building $MODULE.pot...\n" if $VERBOSE;
+
+ open INFILE, $POTFILES_in;
+ unlink "POTFILES.in.temp";
+ open OUTFILE, ">POTFILES.in.temp" or die("Cannot open POTFILES.in.temp for writing");
+
+ my $gettext_support_nonascii = 0;
+
+ # checks for GNU gettext >= 0.12
+ my $dummy = `$XGETTEXT --version --from-code=UTF-8 >$devnull 2>$devnull`;
+ if ($? == 0)
+ {
+ $gettext_support_nonascii = 1;
+ }
+ else
+ {
+ # urge everybody to upgrade gettext
+ print STDERR "WARNING: This version of gettext does not support extracting non-ASCII\n".
+ " strings. That means you should install a version of gettext\n".
+ " that supports non-ASCII strings (such as GNU gettext >= 0.12),\n".
+ " or have to let non-ASCII strings untranslated. (If there is any)\n";
+ }
+
+ my $encoding = "ASCII";
+ my $forced_gettext_code;
+ my @temp_headers;
+ my $encoding_problem_is_reported = 0;
+
+ while (<INFILE>)
+ {
+ next if (/^#/ or /^\s*$/);
+
+ chomp;
+
+ my $gettext_code;
+
+ if (/^\[\s*encoding:\s*(.*)\s*\]/)
+ {
+ $forced_gettext_code=$1;
+ }
+ elsif (/\.($xml_support|$ini_support)$/ || /^\[/)
+ {
+ s/^\[.*]\s*//;
+ print OUTFILE "../$_.h\n";
+ push @temp_headers, "../$_.h";
+ $gettext_code = &TextFile_DetermineEncoding ("../$_.h") if ($gettext_support_nonascii and not defined $forced_gettext_code);
+ }
+ else
+ {
+ print OUTFILE "$SRCDIR/../$_\n";
+ $gettext_code = &TextFile_DetermineEncoding ("$SRCDIR/../$_") if ($gettext_support_nonascii and not defined $forced_gettext_code);
+ }
+
+ next if (! $gettext_support_nonascii);
+
+ if (defined $forced_gettext_code)
+ {
+ $encoding=$forced_gettext_code;
+ }
+ elsif (defined $gettext_code and "$encoding" ne "$gettext_code")
+ {
+ if ($encoding eq "ASCII")
+ {
+ $encoding=$gettext_code;
+ }
+ elsif ($gettext_code ne "ASCII")
+ {
+ # Only report once because the message is quite long
+ if (! $encoding_problem_is_reported)
+ {
+ print STDERR "WARNING: You should use the same file encoding for all your project files,\n".
+ " but $PROGRAM thinks that most of the source files are in\n".
+ " $encoding encoding, while \"$_\" is (likely) in\n".
+ " $gettext_code encoding. If you are sure that all translatable strings\n".
+ " are in same encoding (say UTF-8), please \e[1m*prepend*\e[0m the following\n".
+ " line to POTFILES.in:\n\n".
+ " [encoding: UTF-8]\n\n".
+ " and make sure that configure.in/ac checks for $PACKAGE >= 0.27 .\n".
+ "(such warning message will only be reported once.)\n";
+ $encoding_problem_is_reported = 1;
+ }
+ }
+ }
+ }
+
+ close OUTFILE;
+ close INFILE;
+
+ unlink "$MODULE.pot";
+ my @xgettext_argument=("$XGETTEXT",
+ "--add-comments",
+ "--directory\=.",
+ "--default-domain\=$MODULE",
+ "--flag\=g_strdup_printf:1:c-format",
+ "--flag\=g_string_printf:2:c-format",
+ "--flag\=g_string_append_printf:2:c-format",
+ "--flag\=g_error_new:3:c-format",
+ "--flag\=g_set_error:4:c-format",
+ "--flag\=g_markup_printf_escaped:1:c-format",
+ "--flag\=g_log:3:c-format",
+ "--flag\=g_print:1:c-format",
+ "--flag\=g_printerr:1:c-format",
+ "--flag\=g_printf:1:c-format",
+ "--flag\=g_fprintf:2:c-format",
+ "--flag\=g_sprintf:2:c-format",
+ "--flag\=g_snprintf:3:c-format",
+ "--flag\=g_scanner_error:2:c-format",
+ "--flag\=g_scanner_warn:2:c-format",
+ "--output\=$MODULE\.pot",
+ "--files-from\=\.\/POTFILES\.in\.temp");
+ my $XGETTEXT_KEYWORDS = &FindPOTKeywords;
+ push @xgettext_argument, $XGETTEXT_KEYWORDS;
+ my $MSGID_BUGS_ADDRESS = &FindMakevarsBugAddress;
+ push @xgettext_argument, "--msgid-bugs-address\=$MSGID_BUGS_ADDRESS" if $MSGID_BUGS_ADDRESS;
+ push @xgettext_argument, "--from-code\=$encoding" if ($gettext_support_nonascii);
+ push @xgettext_argument, $XGETTEXT_ARGS if $XGETTEXT_ARGS;
+ my $xgettext_command = join ' ', @xgettext_argument;
+
+ # intercept xgettext error message
+ print "Running $xgettext_command\n" if $VERBOSE;
+ my $xgettext_error_msg = `$xgettext_command 2>\&1`;
+ my $command_failed = $?;
+
+ unlink "POTFILES.in.temp";
+
+ print "Removing generated header (.h) files..." if $VERBOSE;
+ unlink foreach (@temp_headers);
+ print "done.\n" if $VERBOSE;
+
+ if (! $command_failed)
+ {
+ if (! -e "$MODULE.pot")
+ {
+ print "None of the files in POTFILES.in contain strings marked for translation.\n" if $VERBOSE;
+ }
+ else
+ {
+ print "Wrote $MODULE.pot\n" if $VERBOSE;
+ }
+ }
+ else
+ {
+ if ($xgettext_error_msg =~ /--from-code/)
+ {
+ # replace non-ASCII error message with a more useful one.
+ print STDERR "ERROR: xgettext failed to generate PO template file because there is non-ASCII\n".
+ " string marked for translation. Please make sure that all strings marked\n".
+ " for translation are in uniform encoding (say UTF-8), then \e[1m*prepend*\e[0m the\n".
+ " following line to POTFILES.in and rerun $PROGRAM:\n\n".
+ " [encoding: UTF-8]\n\n";
+ }
+ else
+ {
+ print STDERR "$xgettext_error_msg";
+ if (-e "$MODULE.pot")
+ {
+ # is this possible?
+ print STDERR "ERROR: xgettext failed but still managed to generate PO template file.\n".
+ " Please consult error message above if there is any.\n";
+ }
+ else
+ {
+ print STDERR "ERROR: xgettext failed to generate PO template file. Please consult\n".
+ " error message above if there is any.\n";
+ }
+ }
+ exit (1);
+ }
+}
+
+sub POFile_Update
+{
+ -f "$MODULE.pot" or die "$PROGRAM: $MODULE.pot does not exist.\n";
+
+ my $MSGMERGE = $ENV{"MSGMERGE"} || "msgmerge";
+ my ($lang, $outfile) = @_;
+
+ if (! isGNUGettextTool ("$MSGMERGE"))
+ {
+ print STDERR " *** GNU msgmerge is not found on this system!\n".
+ " *** Without it, intltool-update can not extract strings.\n";
+ exit;
+ }
+
+ print "Merging $SRCDIR/$lang.po with $MODULE.pot..." if $VERBOSE;
+
+ my $infile = "$SRCDIR/$lang.po";
+ $outfile = "$SRCDIR/$lang.po" if ($outfile eq "");
+
+ # I think msgmerge won't overwrite old file if merge is not successful
+ system ("$MSGMERGE", "-o", $outfile, $infile, "$MODULE.pot");
+}
+
+sub Console_WriteError_NotExisting
+{
+ my ($file) = @_;
+
+ ## Report error if supplied language file is non-existing
+ print STDERR "$PROGRAM: $file does not exist!\n";
+ print STDERR "Try '$PROGRAM --help' for more information.\n";
+ exit;
+}
+
+sub GatherPOFiles
+{
+ my @po_files = glob ("./*.po");
+
+ @languages = map (&POFile_GetLanguage, @po_files);
+
+ foreach my $lang (@languages)
+ {
+ $po_files_by_lang{$lang} = shift (@po_files);
+ }
+}
+
+sub POFile_GetLanguage ($)
+{
+ s/^(.*\/)?(.+)\.po$/$2/;
+ return $_;
+}
+
+sub Console_Write_TranslationStatus
+{
+ my ($lang, $output_file) = @_;
+ my $MSGFMT = $ENV{"MSGFMT"} || "msgfmt";
+
+ if (! isGNUGettextTool ("$MSGFMT"))
+ {
+ print STDERR " *** GNU msgfmt is not found on this system!\n".
+ " *** Without it, intltool-update can not extract strings.\n";
+ exit;
+ }
+
+ $output_file = "$SRCDIR/$lang.po" if ($output_file eq "");
+
+ system ("$MSGFMT", "-o", "$devnull", "--verbose", $output_file);
+}
+
+sub Console_Write_CoverageReport
+{
+ my $MSGFMT = $ENV{"MSGFMT"} || "msgfmt";
+
+ if (! isGNUGettextTool ("$MSGFMT"))
+ {
+ print STDERR " *** GNU msgfmt is not found on this system!\n".
+ " *** Without it, intltool-update can not extract strings.\n";
+ exit;
+ }
+
+ &GatherPOFiles;
+
+ foreach my $lang (@languages)
+ {
+ print STDERR "$lang: ";
+ &POFile_Update ($lang, "");
+ }
+
+ print STDERR "\n\n * Current translation support in $MODULE \n\n";
+
+ foreach my $lang (@languages)
+ {
+ print STDERR "$lang: ";
+ system ("$MSGFMT", "-o", "$devnull", "--verbose", "$SRCDIR/$lang.po");
+ }
+}
+
+sub SubstituteVariable
+{
+ my ($str) = @_;
+
+ # always need to rewind file whenever it has been accessed
+ seek (CONF, 0, 0);
+
+ # cache each variable. varhash is global to we can add
+ # variables elsewhere.
+ while (<CONF>)
+ {
+ if (/^(\w+)=(.*)$/)
+ {
+ ($varhash{$1} = $2) =~ s/^["'](.*)["']$/$1/;
+ }
+ }
+
+ if ($str =~ /^(.*)\${?([A-Z_]+)}?(.*)$/)
+ {
+ my $rest = $3;
+ my $untouched = $1;
+ my $sub = "";
+ # Ignore recursive definitions of variables
+ $sub = $varhash{$2} if defined $varhash{$2} and $varhash{$2} !~ /\${?$2}?/;
+
+ return SubstituteVariable ("$untouched$sub$rest");
+ }
+
+ # We're using Perl backticks ` and "echo -n" here in order to
+ # expand any shell escapes (such as backticks themselves) in every variable
+ return echo_n ($str);
+}
+
+sub CONF_Handle_Open
+{
+ my $base_dirname = getcwd();
+ $base_dirname =~ s@.*/@@;
+
+ my ($conf_in, $src_dir);
+
+ if ($base_dirname =~ /^po(-.+)?$/)
+ {
+ if (-f "Makevars")
+ {
+ my $makefile_source;
+
+ local (*IN);
+ open (IN, "<Makevars") || die "can't open Makevars: $!";
+
+ while (<IN>)
+ {
+ if (/^top_builddir[ \t]*=/)
+ {
+ $src_dir = $_;
+ $src_dir =~ s/^top_builddir[ \t]*=[ \t]*([^ \t\n\r]*)/$1/;
+
+ chomp $src_dir;
+ if (-f "$src_dir" . "/configure.ac") {
+ $conf_in = "$src_dir" . "/configure.ac" . "\n";
+ } else {
+ $conf_in = "$src_dir" . "/configure.in" . "\n";
+ }
+ last;
+ }
+ }
+ close IN;
+
+ $conf_in || die "Cannot find top_builddir in Makevars.";
+ }
+ elsif (-f "$SRCDIR/../configure.ac")
+ {
+ $conf_in = "$SRCDIR/../configure.ac";
+ }
+ elsif (-f "$SRCDIR/../configure.in")
+ {
+ $conf_in = "$SRCDIR/../configure.in";
+ }
+ else
+ {
+ my $makefile_source;
+
+ local (*IN);
+ open (IN, "<Makefile") || return;
+
+ while (<IN>)
+ {
+ if (/^top_srcdir[ \t]*=/)
+ {
+ $src_dir = $_;
+ $src_dir =~ s/^top_srcdir[ \t]*=[ \t]*([^ \t\n\r]*)/$1/;
+
+ chomp $src_dir;
+ $conf_in = "$src_dir" . "/configure.in" . "\n";
+
+ last;
+ }
+ }
+ close IN;
+
+ $conf_in || die "Cannot find top_srcdir in Makefile.";
+ }
+
+ open (CONF, "<$conf_in");
+ }
+ else
+ {
+ print STDERR "$PROGRAM: Unable to proceed.\n" .
+ "Make sure to run this script inside the po directory.\n";
+ exit;
+ }
+}
+
+sub FindPackageName
+{
+ my $version;
+ my $domain = &FindMakevarsDomain;
+ my $name = $domain || "untitled";
+
+ &CONF_Handle_Open;
+
+ my $conf_source; {
+ local (*IN);
+ open (IN, "<&CONF") || return $name;
+ seek (IN, 0, 0);
+ local $/; # slurp mode
+ $conf_source = <IN>;
+ close IN;
+ }
+
+ # priority for getting package name:
+ # 1. GETTEXT_PACKAGE
+ # 2. first argument of AC_INIT (with >= 2 arguments)
+ # 3. first argument of AM_INIT_AUTOMAKE (with >= 2 argument)
+
+ # /^AM_INIT_AUTOMAKE\([\s\[]*([^,\)\s\]]+)/m
+ # the \s makes this not work, why?
+ if ($conf_source =~ /^AM_INIT_AUTOMAKE\(([^,\)]+),([^,\)]+)/m)
+ {
+ ($name, $version) = ($1, $2);
+ $name =~ s/[\[\]\s]//g;
+ $version =~ s/[\[\]\s]//g;
+ $varhash{"PACKAGE_NAME"} = $name if (not $name =~ /\${?AC_PACKAGE_NAME}?/);
+ $varhash{"PACKAGE"} = $name if (not $name =~ /\${?PACKAGE}?/);
+ $varhash{"PACKAGE_VERSION"} = $version if (not $name =~ /\${?AC_PACKAGE_VERSION}?/);
+ $varhash{"VERSION"} = $version if (not $name =~ /\${?VERSION}?/);
+ }
+
+ if ($conf_source =~ /^AC_INIT\(([^,\)]+),([^,\)]+)/m)
+ {
+ ($name, $version) = ($1, $2);
+ $name =~ s/[\[\]\s]//g;
+ $version =~ s/[\[\]\s]//g;
+ $varhash{"PACKAGE_NAME"} = $name if (not $name =~ /\${?AC_PACKAGE_NAME}?/);
+ $varhash{"PACKAGE"} = $name if (not $name =~ /\${?PACKAGE}?/);
+ $varhash{"PACKAGE_VERSION"} = $version if (not $name =~ /\${?AC_PACKAGE_VERSION}?/);
+ $varhash{"VERSION"} = $version if (not $name =~ /\${?VERSION}?/);
+ }
+
+ # \s makes this not work, why?
+ $name = $1 if $conf_source =~ /^GETTEXT_PACKAGE=\[?([^\n\]]+)/m;
+
+ # m4 macros AC_PACKAGE_NAME, AC_PACKAGE_VERSION etc. have same value
+ # as corresponding $PACKAGE_NAME, $PACKAGE_VERSION etc. shell variables.
+ $name =~ s/\bAC_PACKAGE_/\$PACKAGE_/g;
+
+ $name = $domain if $domain;
+
+ $name = SubstituteVariable ($name);
+ $name =~ s/^["'](.*)["']$/$1/;
+
+ return $name if $name;
+}
+
+
+sub FindPOTKeywords
+{
+
+ my $keywords = "--keyword\=\_ --keyword\=N\_ --keyword\=U\_ --keyword\=Q\_";
+ my $varname = "XGETTEXT_OPTIONS";
+ my $make_source; {
+ local (*IN);
+ open (IN, "<Makevars") || (open(IN, "<Makefile.in.in") && ($varname = "XGETTEXT_KEYWORDS")) || return $keywords;
+ seek (IN, 0, 0);
+ local $/; # slurp mode
+ $make_source = <IN>;
+ close IN;
+ }
+
+ $keywords = $1 if $make_source =~ /^$varname[ ]*=\[?([^\n\]]+)/m;
+
+ return $keywords;
+}
+
+sub FindMakevarsDomain
+{
+
+ my $domain = "";
+ my $makevars_source; {
+ local (*IN);
+ open (IN, "<Makevars") || return $domain;
+ seek (IN, 0, 0);
+ local $/; # slurp mode
+ $makevars_source = <IN>;
+ close IN;
+ }
+
+ $domain = $1 if $makevars_source =~ /^DOMAIN[ ]*=\[?([^\n\]\$]+)/m;
+ $domain =~ s/^\s+//;
+ $domain =~ s/\s+$//;
+
+ return $domain;
+}
+
+sub FindMakevarsBugAddress
+{
+
+ my $address = "";
+ my $makevars_source; {
+ local (*IN);
+ open (IN, "<Makevars") || return undef;
+ seek (IN, 0, 0);
+ local $/; # slurp mode
+ $makevars_source = <IN>;
+ close IN;
+ }
+
+ $address = $1 if $makevars_source =~ /^MSGID_BUGS_ADDRESS[ ]*=\[?([^\n\]\$]+)/m;
+ $address =~ s/^\s+//;
+ $address =~ s/\s+$//;
+
+ return $address;
+}
diff --git a/xgsch2pcb.in b/xgsch2pcb.in
index 2c2d0bf..406378c 100644
--- a/xgsch2pcb.in
+++ b/xgsch2pcb.in
@@ -27,6 +27,7 @@ import sys, gtk, os.path
# xgsch2pcb needs to know its installation prefix in order to find its files
prefix = '@prefix@'
pkglibdir = '@pkglibdir@'
+localedir = '@prefix@/share/locale'
libpath = os.path.abspath(pkglibdir)
if libpath not in sys.path:
@@ -35,7 +36,7 @@ if libpath not in sys.path:
# Check i18n
import gettext
try:
- t = gettext.translation('xgsch2pcb')
+ t = gettext.translation('@PACKAGE@', localedir)
except IOError:
print 'Warning: Failed to load gettext translations'
commit d0e352691a5a330ccef662013875ebdfbfbea0a9
Author: Peter Clifton <pcjc2@xxxxxxxxx>
Date: Sun Nov 11 05:29:23 2007 +0000
Add .gitignore entry for generated toplevel config.py
diff --git a/.gitignore b/.gitignore
index 8aabc23..d2a59cd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,3 +6,4 @@ autom4te.cache
configure
config.log
config.status
+config.py
commit 1e35cf9eb5bd654f58e5b461ff073042204a8880
Author: Peter Clifton <pcjc2@xxxxxxxxx>
Date: Sun Nov 11 04:34:21 2007 +0000
Fix the "here documents" in the configure script to a non bashism
Fix FTBFS on non bash shells, such as "dash" which is default in Ubuntu.
diff --git a/configure.ac b/configure.ac
index db228d9..fce9bf9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -72,10 +72,11 @@ AC_SUBST(templatesdir)
AC_PYTHON_MODULE(pygtk, t)
AC_MSG_CHECKING(for pygtk 2.0)
-cat > conftest.py <<< ['
+cat > conftest.py <<[EOF
import pygtk
pygtk.require("2.0")
-']
+EOF]
+
if $PYTHON conftest.py > /dev/null 2>&1; then
AC_MSG_RESULT(yes)
else
@@ -88,7 +89,7 @@ for module in gobject gtk gtk.gdk; do
done
AC_MSG_CHECKING(for gtk+ >= $GTK_WANTVERSION)
-cat > conftest.py <<< ['
+cat > conftest.py <<[EOF
import sys
try:
import gtk
@@ -105,7 +106,8 @@ try:
except:
sys.exit(1)
sys.exit(0)
-']
+EOF]
+
GTK_VERSION=`$PYTHON conftest.py $GTK_WANTVERSION 2> /dev/null`
haveversion=$?
AC_MSG_RESULT($GTK_VERSION)
_______________________________________________
geda-cvs mailing list
geda-cvs@xxxxxxxxxxxxxx
http://www.seul.org/cgi-bin/mailman/listinfo/geda-cvs