From 3167306af4c5138ba2ec48886e8ba1a539502b8c Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Mon, 1 Aug 2011 15:10:17 +1000 Subject: [PATCH 001/112] Start preparing for version 7.2 In this version, hopefully, internationalisation and multibyte strings will be handled correctly. --- NEWS | 6 ++++++ configure.ac | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index fdc32a6..596936b 100644 --- a/NEWS +++ b/NEWS @@ -15,6 +15,12 @@ consult the Subversion repository for "trader" on The ZAP Group web server at http://www.zap.org.au/services/svn/. +Version 7.2 (not yet released) +------------------------------ + +@@@ To be written. Internationalisation, multibyte strings + + Version 7.1 (29th July, 2011) ----------------------------- diff --git a/configure.ac b/configure.ac index c343cfd..2509b88 100644 --- a/configure.ac +++ b/configure.ac @@ -26,7 +26,7 @@ dnl You should have received a copy of the GNU General Public License dnl along with this program. If not, see http://www.gnu.org/licenses/. -AC_INIT([Star Traders], [7.1], [J.Zaitseff@zap.org.au], [trader], [http://www.zap.org.au/software/trader/]) +AC_INIT([Star Traders], [7.2], [J.Zaitseff@zap.org.au], [trader], [http://www.zap.org.au/software/trader/]) AC_DEFINE([PACKAGE_AUTHOR], ["John Zaitseff"], [Package author]) AC_PREREQ([2.67]) From 378b7e64b075c5ec262f99b5a6f042bc7de16f74 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Mon, 1 Aug 2011 18:17:02 +1000 Subject: [PATCH 002/112] Add preliminary support for GNU gettext internationalisation --- .gitignore | 4 + Makefile.am | 2 +- build-aux/bootstrap | 2 +- configure.ac | 4 + m4/.gitignore | 24 +++ m4/gnulib-cache.m4 | 4 +- po/Makefile.in.in | 444 +++++++++++++++++++++++++++++++++++++++++ po/Makevars | 49 +++++ po/POTFILES.in | 26 +++ po/Rules-quot | 47 +++++ po/boldquot.sed | 10 + po/en@boldquot.header | 25 +++ po/en@quot.header | 22 ++ po/insert-header.sin | 23 +++ po/quot.sed | 6 + po/remove-potcdate.sin | 19 ++ src/Makefile.am | 1 + src/system.h | 8 + src/trader.c | 4 + 19 files changed, 721 insertions(+), 3 deletions(-) create mode 100644 po/Makefile.in.in create mode 100644 po/Makevars create mode 100644 po/POTFILES.in create mode 100644 po/Rules-quot create mode 100644 po/boldquot.sed create mode 100644 po/en@boldquot.header create mode 100644 po/en@quot.header create mode 100644 po/insert-header.sin create mode 100644 po/quot.sed create mode 100644 po/remove-potcdate.sin diff --git a/.gitignore b/.gitignore index 4f60249..0247e11 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ Makefile.in /stamp-h1 /build-aux/config.guess +/build-aux/config.rpath /build-aux/config.sub /build-aux/depcomp /build-aux/install-sh @@ -24,4 +25,7 @@ Makefile.in /build-aux/snippet/warn-on-use.h /build-aux/snippet/_Noreturn.h +/po/POTFILES +/po/remove-potcdate.sed + /src/trader diff --git a/Makefile.am b/Makefile.am index 369910e..7413364 100644 --- a/Makefile.am +++ b/Makefile.am @@ -31,7 +31,7 @@ ACLOCAL_AMFLAGS = -I m4 # Subdirectories to recurse into -SUBDIRS = lib src doc m4 +SUBDIRS = lib src doc po m4 # Additional files to distribute EXTRA_DIST = build-aux/bootstrap diff --git a/build-aux/bootstrap b/build-aux/bootstrap index cf465f9..c90790c 100755 --- a/build-aux/bootstrap +++ b/build-aux/bootstrap @@ -6,4 +6,4 @@ set -e gnulib-tool --update -autoreconf --install --verbose +env AUTOPOINT=true autoreconf --install --verbose diff --git a/configure.ac b/configure.ac index 2509b88..77fa26c 100644 --- a/configure.ac +++ b/configure.ac @@ -57,11 +57,15 @@ AS_IF([test "x$ax_cv_curses" != xyes || test "x$ax_cv_curses_color" != xyes], [ AC_MSG_ERROR([requires an X/Open-compatible Curses library with colour]) ]) +AM_GNU_GETTEXT([external]) +AM_GNU_GETTEXT_VERSION([0.18.1]) + AC_CONFIG_FILES([ Makefile lib/Makefile src/Makefile doc/Makefile + po/Makefile.in m4/Makefile ]) AC_OUTPUT diff --git a/m4/.gitignore b/m4/.gitignore index 1bf3aef..8c17497 100644 --- a/m4/.gitignore +++ b/m4/.gitignore @@ -2,6 +2,7 @@ alloca.m4 asm-underscore.m4 assert.m4 +codeset.m4 config-h.m4 ctype.m4 errno_h.m4 @@ -9,36 +10,56 @@ exponentd.m4 exponentf.m4 exponentl.m4 extensions.m4 +fcntl-o.m4 float_h.m4 fpieee.m4 fprintf-posix.m4 frexp.m4 frexpl.m4 getopt.m4 +gettext.m4 gettimeofday.m4 +glibc21.m4 +glibc2.m4 gnulib-common.m4 gnulib-comp.m4 gnulib-tool.m4 +iconv.m4 include_next.m4 +intdiv0.m4 +intldir.m4 +intl.m4 +intlmacosx.m4 +intmax.m4 intmax_t.m4 +inttypes-pri.m4 inttypes_h.m4 isnand.m4 isnanf.m4 isnanl.m4 largefile.m4 +lcmessage.m4 ldexpl.m4 +lib-ld.m4 +lib-link.m4 +lib-prefix.m4 locale_h.m4 +lock.m4 longlong.m4 malloc.m4 math_h.m4 memchr.m4 mmap-anon.m4 multiarch.m4 +nls.m4 nocrash.m4 +po.m4 printf.m4 printf-frexp.m4 printf-frexpl.m4 +printf-posix.m4 printf-posix-rpl.m4 +progtest.m4 signbit.m4 size_max.m4 snprintf.m4 @@ -57,10 +78,13 @@ strncat.m4 strstr.m4 sys_stat_h.m4 sys_time_h.m4 +threadlib.m4 time_h.m4 +uintmax_t.m4 unistd_h.m4 vasnprintf.m4 vfprintf-posix.m4 +visibility.m4 vsnprintf.m4 vsnprintf-posix.m4 warn-on-use.m4 diff --git a/m4/gnulib-cache.m4 b/m4/gnulib-cache.m4 index 7eb8d0d..b0b1044 100644 --- a/m4/gnulib-cache.m4 +++ b/m4/gnulib-cache.m4 @@ -15,7 +15,7 @@ # Specification in the form of a command-line invocation: -# gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --no-conditional-dependencies --no-libtool --macro-prefix=gl assert config-h ctype fprintf-posix getopt-gnu gettimeofday locale printf-posix snprintf-posix stat stdarg stdbool stdio strdup-posix string strncat strstr sys_stat sys_time unistd vfprintf-posix vsnprintf-posix +# gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --no-conditional-dependencies --no-libtool --macro-prefix=gl assert config-h ctype fprintf-posix getopt-gnu gettext gettext-h gettimeofday locale printf-posix snprintf-posix stat stdarg stdbool stdio strdup-posix string strncat strstr sys_stat sys_time unistd vfprintf-posix vsnprintf-posix # Specification in the form of a few gnulib-tool.m4 macro invocations: gl_LOCAL_DIR([]) @@ -25,6 +25,8 @@ gl_MODULES([ ctype fprintf-posix getopt-gnu + gettext + gettext-h gettimeofday locale printf-posix diff --git a/po/Makefile.in.in b/po/Makefile.in.in new file mode 100644 index 0000000..83d8838 --- /dev/null +++ b/po/Makefile.in.in @@ -0,0 +1,444 @@ +# Makefile for PO directory in any package using GNU gettext. +# Copyright (C) 1995-1997, 2000-2007, 2009-2010 by Ulrich Drepper +# +# This file can be copied and used freely without restrictions. It can +# be used in projects which are not available under the GNU General Public +# License but which still want to provide support for the GNU gettext +# functionality. +# Please note that the actual code of GNU gettext is covered by the GNU +# General Public License and is *not* in the public domain. +# +# Origin: gettext-0.18 +GETTEXT_MACRO_VERSION = 0.18 + +PACKAGE = @PACKAGE@ +VERSION = @VERSION@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ + +SHELL = /bin/sh +@SET_MAKE@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ + +prefix = @prefix@ +exec_prefix = @exec_prefix@ +datarootdir = @datarootdir@ +datadir = @datadir@ +localedir = @localedir@ +gettextsrcdir = $(datadir)/gettext/po + +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ + +# We use $(mkdir_p). +# In automake <= 1.9.x, $(mkdir_p) is defined either as "mkdir -p --" or as +# "$(mkinstalldirs)" or as "$(install_sh) -d". For these automake versions, +# @install_sh@ does not start with $(SHELL), so we add it. +# In automake >= 1.10, @mkdir_p@ is derived from ${MKDIR_P}, which is defined +# either as "/path/to/mkdir -p" or ".../install-sh -c -d". For these automake +# versions, $(mkinstalldirs) and $(install_sh) are unused. +mkinstalldirs = $(SHELL) @install_sh@ -d +install_sh = $(SHELL) @install_sh@ +MKDIR_P = @MKDIR_P@ +mkdir_p = @mkdir_p@ + +GMSGFMT_ = @GMSGFMT@ +GMSGFMT_no = @GMSGFMT@ +GMSGFMT_yes = @GMSGFMT_015@ +GMSGFMT = $(GMSGFMT_$(USE_MSGCTXT)) +MSGFMT_ = @MSGFMT@ +MSGFMT_no = @MSGFMT@ +MSGFMT_yes = @MSGFMT_015@ +MSGFMT = $(MSGFMT_$(USE_MSGCTXT)) +XGETTEXT_ = @XGETTEXT@ +XGETTEXT_no = @XGETTEXT@ +XGETTEXT_yes = @XGETTEXT_015@ +XGETTEXT = $(XGETTEXT_$(USE_MSGCTXT)) +MSGMERGE = msgmerge +MSGMERGE_UPDATE = @MSGMERGE@ --update +MSGINIT = msginit +MSGCONV = msgconv +MSGFILTER = msgfilter + +POFILES = @POFILES@ +GMOFILES = @GMOFILES@ +UPDATEPOFILES = @UPDATEPOFILES@ +DUMMYPOFILES = @DUMMYPOFILES@ +DISTFILES.common = Makefile.in.in remove-potcdate.sin \ +$(DISTFILES.common.extra1) $(DISTFILES.common.extra2) $(DISTFILES.common.extra3) +DISTFILES = $(DISTFILES.common) Makevars POTFILES.in \ +$(POFILES) $(GMOFILES) \ +$(DISTFILES.extra1) $(DISTFILES.extra2) $(DISTFILES.extra3) + +POTFILES = \ + +CATALOGS = @CATALOGS@ + +# Makevars gets inserted here. (Don't remove this line!) + +.SUFFIXES: +.SUFFIXES: .po .gmo .mo .sed .sin .nop .po-create .po-update + +.po.mo: + @echo "$(MSGFMT) -c -o $@ $<"; \ + $(MSGFMT) -c -o t-$@ $< && mv t-$@ $@ + +.po.gmo: + @lang=`echo $* | sed -e 's,.*/,,'`; \ + test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ + echo "$${cdcmd}rm -f $${lang}.gmo && $(GMSGFMT) -c --statistics --verbose -o $${lang}.gmo $${lang}.po"; \ + cd $(srcdir) && rm -f $${lang}.gmo && $(GMSGFMT) -c --statistics --verbose -o t-$${lang}.gmo $${lang}.po && mv t-$${lang}.gmo $${lang}.gmo + +.sin.sed: + sed -e '/^#/d' $< > t-$@ + mv t-$@ $@ + + +all: check-macro-version all-@USE_NLS@ + +all-yes: stamp-po +all-no: + +# Ensure that the gettext macros and this Makefile.in.in are in sync. +check-macro-version: + @test "$(GETTEXT_MACRO_VERSION)" = "@GETTEXT_MACRO_VERSION@" \ + || { echo "*** error: gettext infrastructure mismatch: using a Makefile.in.in from gettext version $(GETTEXT_MACRO_VERSION) but the autoconf macros are from gettext version @GETTEXT_MACRO_VERSION@" 1>&2; \ + exit 1; \ + } + +# $(srcdir)/$(DOMAIN).pot is only created when needed. When xgettext finds no +# internationalized messages, no $(srcdir)/$(DOMAIN).pot is created (because +# we don't want to bother translators with empty POT files). We assume that +# LINGUAS is empty in this case, i.e. $(POFILES) and $(GMOFILES) are empty. +# In this case, stamp-po is a nop (i.e. a phony target). + +# stamp-po is a timestamp denoting the last time at which the CATALOGS have +# been loosely updated. Its purpose is that when a developer or translator +# checks out the package via CVS, and the $(DOMAIN).pot file is not in CVS, +# "make" will update the $(DOMAIN).pot and the $(CATALOGS), but subsequent +# invocations of "make" will do nothing. This timestamp would not be necessary +# if updating the $(CATALOGS) would always touch them; however, the rule for +# $(POFILES) has been designed to not touch files that don't need to be +# changed. +stamp-po: $(srcdir)/$(DOMAIN).pot + test ! -f $(srcdir)/$(DOMAIN).pot || \ + test -z "$(GMOFILES)" || $(MAKE) $(GMOFILES) + @test ! -f $(srcdir)/$(DOMAIN).pot || { \ + echo "touch stamp-po" && \ + echo timestamp > stamp-poT && \ + mv stamp-poT stamp-po; \ + } + +# Note: Target 'all' must not depend on target '$(DOMAIN).pot-update', +# otherwise packages like GCC can not be built if only parts of the source +# have been downloaded. + +# This target rebuilds $(DOMAIN).pot; it is an expensive operation. +# Note that $(DOMAIN).pot is not touched if it doesn't need to be changed. +$(DOMAIN).pot-update: $(POTFILES) $(srcdir)/POTFILES.in remove-potcdate.sed + if LC_ALL=C grep 'GNU @PACKAGE@' $(top_srcdir)/* 2>/dev/null | grep -v 'libtool:' >/dev/null; then \ + package_gnu='GNU '; \ + else \ + package_gnu=''; \ + fi; \ + if test -n '$(MSGID_BUGS_ADDRESS)' || test '$(PACKAGE_BUGREPORT)' = '@'PACKAGE_BUGREPORT'@'; then \ + msgid_bugs_address='$(MSGID_BUGS_ADDRESS)'; \ + else \ + msgid_bugs_address='$(PACKAGE_BUGREPORT)'; \ + fi; \ + case `$(XGETTEXT) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \ + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-5] | 0.1[0-5].* | 0.16 | 0.16.[0-1]*) \ + $(XGETTEXT) --default-domain=$(DOMAIN) --directory=$(top_srcdir) \ + --add-comments=TRANSLATORS: $(XGETTEXT_OPTIONS) @XGETTEXT_EXTRA_OPTIONS@ \ + --files-from=$(srcdir)/POTFILES.in \ + --copyright-holder='$(COPYRIGHT_HOLDER)' \ + --msgid-bugs-address="$$msgid_bugs_address" \ + ;; \ + *) \ + $(XGETTEXT) --default-domain=$(DOMAIN) --directory=$(top_srcdir) \ + --add-comments=TRANSLATORS: $(XGETTEXT_OPTIONS) @XGETTEXT_EXTRA_OPTIONS@ \ + --files-from=$(srcdir)/POTFILES.in \ + --copyright-holder='$(COPYRIGHT_HOLDER)' \ + --package-name="$${package_gnu}@PACKAGE@" \ + --package-version='@VERSION@' \ + --msgid-bugs-address="$$msgid_bugs_address" \ + ;; \ + esac + test ! -f $(DOMAIN).po || { \ + if test -f $(srcdir)/$(DOMAIN).pot; then \ + sed -f remove-potcdate.sed < $(srcdir)/$(DOMAIN).pot > $(DOMAIN).1po && \ + sed -f remove-potcdate.sed < $(DOMAIN).po > $(DOMAIN).2po && \ + if cmp $(DOMAIN).1po $(DOMAIN).2po >/dev/null 2>&1; then \ + rm -f $(DOMAIN).1po $(DOMAIN).2po $(DOMAIN).po; \ + else \ + rm -f $(DOMAIN).1po $(DOMAIN).2po $(srcdir)/$(DOMAIN).pot && \ + mv $(DOMAIN).po $(srcdir)/$(DOMAIN).pot; \ + fi; \ + else \ + mv $(DOMAIN).po $(srcdir)/$(DOMAIN).pot; \ + fi; \ + } + +# This rule has no dependencies: we don't need to update $(DOMAIN).pot at +# every "make" invocation, only create it when it is missing. +# Only "make $(DOMAIN).pot-update" or "make dist" will force an update. +$(srcdir)/$(DOMAIN).pot: + $(MAKE) $(DOMAIN).pot-update + +# This target rebuilds a PO file if $(DOMAIN).pot has changed. +# Note that a PO file is not touched if it doesn't need to be changed. +$(POFILES): $(srcdir)/$(DOMAIN).pot + @lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \ + if test -f "$(srcdir)/$${lang}.po"; then \ + test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ + echo "$${cdcmd}$(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) --lang=$${lang} $${lang}.po $(DOMAIN).pot"; \ + cd $(srcdir) \ + && { case `$(MSGMERGE_UPDATE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \ + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-7] | 0.1[0-7].*) \ + $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \ + *) \ + $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) --lang=$${lang} $${lang}.po $(DOMAIN).pot;; \ + esac; \ + }; \ + else \ + $(MAKE) $${lang}.po-create; \ + fi + + +install: install-exec install-data +install-exec: +install-data: install-data-@USE_NLS@ + if test "$(PACKAGE)" = "gettext-tools"; then \ + $(mkdir_p) $(DESTDIR)$(gettextsrcdir); \ + for file in $(DISTFILES.common) Makevars.template; do \ + $(INSTALL_DATA) $(srcdir)/$$file \ + $(DESTDIR)$(gettextsrcdir)/$$file; \ + done; \ + for file in Makevars; do \ + rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \ + done; \ + else \ + : ; \ + fi +install-data-no: all +install-data-yes: all + @catalogs='$(CATALOGS)'; \ + for cat in $$catalogs; do \ + cat=`basename $$cat`; \ + lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \ + dir=$(localedir)/$$lang/LC_MESSAGES; \ + $(mkdir_p) $(DESTDIR)$$dir; \ + if test -r $$cat; then realcat=$$cat; else realcat=$(srcdir)/$$cat; fi; \ + $(INSTALL_DATA) $$realcat $(DESTDIR)$$dir/$(DOMAIN).mo; \ + echo "installing $$realcat as $(DESTDIR)$$dir/$(DOMAIN).mo"; \ + for lc in '' $(EXTRA_LOCALE_CATEGORIES); do \ + if test -n "$$lc"; then \ + if (cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc 2>/dev/null) | grep ' -> ' >/dev/null; then \ + link=`cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc | sed -e 's/^.* -> //'`; \ + mv $(DESTDIR)$(localedir)/$$lang/$$lc $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ + mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ + (cd $(DESTDIR)$(localedir)/$$lang/$$lc.old && \ + for file in *; do \ + if test -f $$file; then \ + ln -s ../$$link/$$file $(DESTDIR)$(localedir)/$$lang/$$lc/$$file; \ + fi; \ + done); \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ + else \ + if test -d $(DESTDIR)$(localedir)/$$lang/$$lc; then \ + :; \ + else \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc; \ + mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ + fi; \ + fi; \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \ + ln -s ../LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo 2>/dev/null || \ + ln $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo 2>/dev/null || \ + cp -p $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \ + echo "installing $$realcat link as $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo"; \ + fi; \ + done; \ + done + +install-strip: install + +installdirs: installdirs-exec installdirs-data +installdirs-exec: +installdirs-data: installdirs-data-@USE_NLS@ + if test "$(PACKAGE)" = "gettext-tools"; then \ + $(mkdir_p) $(DESTDIR)$(gettextsrcdir); \ + else \ + : ; \ + fi +installdirs-data-no: +installdirs-data-yes: + @catalogs='$(CATALOGS)'; \ + for cat in $$catalogs; do \ + cat=`basename $$cat`; \ + lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \ + dir=$(localedir)/$$lang/LC_MESSAGES; \ + $(mkdir_p) $(DESTDIR)$$dir; \ + for lc in '' $(EXTRA_LOCALE_CATEGORIES); do \ + if test -n "$$lc"; then \ + if (cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc 2>/dev/null) | grep ' -> ' >/dev/null; then \ + link=`cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc | sed -e 's/^.* -> //'`; \ + mv $(DESTDIR)$(localedir)/$$lang/$$lc $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ + mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ + (cd $(DESTDIR)$(localedir)/$$lang/$$lc.old && \ + for file in *; do \ + if test -f $$file; then \ + ln -s ../$$link/$$file $(DESTDIR)$(localedir)/$$lang/$$lc/$$file; \ + fi; \ + done); \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ + else \ + if test -d $(DESTDIR)$(localedir)/$$lang/$$lc; then \ + :; \ + else \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc; \ + mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ + fi; \ + fi; \ + fi; \ + done; \ + done + +# Define this as empty until I found a useful application. +installcheck: + +uninstall: uninstall-exec uninstall-data +uninstall-exec: +uninstall-data: uninstall-data-@USE_NLS@ + if test "$(PACKAGE)" = "gettext-tools"; then \ + for file in $(DISTFILES.common) Makevars.template; do \ + rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \ + done; \ + else \ + : ; \ + fi +uninstall-data-no: +uninstall-data-yes: + catalogs='$(CATALOGS)'; \ + for cat in $$catalogs; do \ + cat=`basename $$cat`; \ + lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \ + for lc in LC_MESSAGES $(EXTRA_LOCALE_CATEGORIES); do \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \ + done; \ + done + +check: all + +info dvi ps pdf html tags TAGS ctags CTAGS ID: + +mostlyclean: + rm -f remove-potcdate.sed + rm -f stamp-poT + rm -f core core.* $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.new.po + rm -fr *.o + +clean: mostlyclean + +distclean: clean + rm -f Makefile Makefile.in POTFILES *.mo + +maintainer-clean: distclean + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + rm -f stamp-po $(GMOFILES) + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) +dist distdir: + $(MAKE) update-po + @$(MAKE) dist2 +# This is a separate target because 'update-po' must be executed before. +dist2: stamp-po $(DISTFILES) + dists="$(DISTFILES)"; \ + if test "$(PACKAGE)" = "gettext-tools"; then \ + dists="$$dists Makevars.template"; \ + fi; \ + if test -f $(srcdir)/$(DOMAIN).pot; then \ + dists="$$dists $(DOMAIN).pot stamp-po"; \ + fi; \ + if test -f $(srcdir)/ChangeLog; then \ + dists="$$dists ChangeLog"; \ + fi; \ + for i in 0 1 2 3 4 5 6 7 8 9; do \ + if test -f $(srcdir)/ChangeLog.$$i; then \ + dists="$$dists ChangeLog.$$i"; \ + fi; \ + done; \ + if test -f $(srcdir)/LINGUAS; then dists="$$dists LINGUAS"; fi; \ + for file in $$dists; do \ + if test -f $$file; then \ + cp -p $$file $(distdir) || exit 1; \ + else \ + cp -p $(srcdir)/$$file $(distdir) || exit 1; \ + fi; \ + done + +update-po: Makefile + $(MAKE) $(DOMAIN).pot-update + test -z "$(UPDATEPOFILES)" || $(MAKE) $(UPDATEPOFILES) + $(MAKE) update-gmo + +# General rule for creating PO files. + +.nop.po-create: + @lang=`echo $@ | sed -e 's/\.po-create$$//'`; \ + echo "File $$lang.po does not exist. If you are a translator, you can create it through 'msginit'." 1>&2; \ + exit 1 + +# General rule for updating PO files. + +.nop.po-update: + @lang=`echo $@ | sed -e 's/\.po-update$$//'`; \ + if test "$(PACKAGE)" = "gettext-tools"; then PATH=`pwd`/../src:$$PATH; fi; \ + tmpdir=`pwd`; \ + echo "$$lang:"; \ + test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ + echo "$${cdcmd}$(MSGMERGE) $(MSGMERGE_OPTIONS) --lang=$$lang $$lang.po $(DOMAIN).pot -o $$lang.new.po"; \ + cd $(srcdir); \ + if { case `$(MSGMERGE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \ + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-7] | 0.1[0-7].*) \ + $(MSGMERGE) $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \ + *) \ + $(MSGMERGE) $(MSGMERGE_OPTIONS) --lang=$$lang -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \ + esac; \ + }; then \ + if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \ + rm -f $$tmpdir/$$lang.new.po; \ + else \ + if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \ + :; \ + else \ + echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \ + exit 1; \ + fi; \ + fi; \ + else \ + echo "msgmerge for $$lang.po failed!" 1>&2; \ + rm -f $$tmpdir/$$lang.new.po; \ + fi + +$(DUMMYPOFILES): + +update-gmo: Makefile $(GMOFILES) + @: + +# Recreate Makefile by invoking config.status. Explicitly invoke the shell, +# because execution permission bits may not work on the current file system. +# Use @SHELL@, which is the shell determined by autoconf for the use by its +# scripts, not $(SHELL) which is hardwired to /bin/sh and may be deficient. +Makefile: Makefile.in.in Makevars $(top_builddir)/config.status @POMAKEFILEDEPS@ + cd $(top_builddir) \ + && @SHELL@ ./config.status $(subdir)/$@.in po-directories + +force: + +# Tell versions [3.59,3.63) of GNU make not to export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/po/Makevars b/po/Makevars new file mode 100644 index 0000000..12376cf --- /dev/null +++ b/po/Makevars @@ -0,0 +1,49 @@ +######################################################################### +# # +# Star Traders: A Game of Interstellar Trading # +# Copyright (C) 1990-2011, John Zaitseff # +# # +######################################################################### + +# Author: John Zaitseff +# $Id$ +# +# This file, po/Makevars, contains variables that are substituted into +# po/Makefile for use with GNU gettext. +# +# +# This program 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 3 of the License, or (at your +# option) any later version. +# +# This program 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, see http://www.gnu.org/licenses/. + + +# The message domain is the same as the package name +DOMAIN = $(PACKAGE) + +# These two variables depend on the location of this directory +subdir = po +top_builddir = .. + +# These options get passed to xgettext +XGETTEXT_OPTIONS = --keyword=_ --keyword=N_ + +# Copyright holder that gets inserted into the header of the +# $(DOMAIN).pot file. +COPYRIGHT_HOLDER = John Zaitseff + +# E-mail address or URL used by translators to report bugs in the +# untranslated (original) strings +MSGID_BUGS_ADDRESS = J.Zaitseff@zap.org.au + +# List of locale categories, beyond LC_MESSAGES, for which the message +# catalogs shall be used. It is usually empty. +EXTRA_LOCALE_CATEGORIES = diff --git a/po/POTFILES.in b/po/POTFILES.in new file mode 100644 index 0000000..c541778 --- /dev/null +++ b/po/POTFILES.in @@ -0,0 +1,26 @@ +######################################################################### +# # +# Star Traders: A Game of Interstellar Trading # +# Copyright (C) 1990-2011, John Zaitseff # +# # +######################################################################### + +# Author: John Zaitseff +# $Id$ +# +# This file, po/POTFILES.in, contains a list of source files which +# contain translatable strings. +# +# +# This program 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 3 of the License, or (at your +# option) any later version. +# +# This program 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, see http://www.gnu.org/licenses/. diff --git a/po/Rules-quot b/po/Rules-quot new file mode 100644 index 0000000..af52487 --- /dev/null +++ b/po/Rules-quot @@ -0,0 +1,47 @@ +# Special Makefile rules for English message catalogs with quotation marks. + +DISTFILES.common.extra1 = quot.sed boldquot.sed en@quot.header en@boldquot.header insert-header.sin Rules-quot + +.SUFFIXES: .insert-header .po-update-en + +en@quot.po-create: + $(MAKE) en@quot.po-update +en@boldquot.po-create: + $(MAKE) en@boldquot.po-update + +en@quot.po-update: en@quot.po-update-en +en@boldquot.po-update: en@boldquot.po-update-en + +.insert-header.po-update-en: + @lang=`echo $@ | sed -e 's/\.po-update-en$$//'`; \ + if test "$(PACKAGE)" = "gettext"; then PATH=`pwd`/../src:$$PATH; GETTEXTLIBDIR=`cd $(top_srcdir)/src && pwd`; export GETTEXTLIBDIR; fi; \ + tmpdir=`pwd`; \ + echo "$$lang:"; \ + ll=`echo $$lang | sed -e 's/@.*//'`; \ + LC_ALL=C; export LC_ALL; \ + cd $(srcdir); \ + if $(MSGINIT) -i $(DOMAIN).pot --no-translator -l $$lang -o - 2>/dev/null | sed -f $$tmpdir/$$lang.insert-header | $(MSGCONV) -t UTF-8 | $(MSGFILTER) sed -f `echo $$lang | sed -e 's/.*@//'`.sed 2>/dev/null > $$tmpdir/$$lang.new.po; then \ + if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \ + rm -f $$tmpdir/$$lang.new.po; \ + else \ + if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \ + :; \ + else \ + echo "creation of $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \ + exit 1; \ + fi; \ + fi; \ + else \ + echo "creation of $$lang.po failed!" 1>&2; \ + rm -f $$tmpdir/$$lang.new.po; \ + fi + +en@quot.insert-header: insert-header.sin + sed -e '/^#/d' -e 's/HEADER/en@quot.header/g' $(srcdir)/insert-header.sin > en@quot.insert-header + +en@boldquot.insert-header: insert-header.sin + sed -e '/^#/d' -e 's/HEADER/en@boldquot.header/g' $(srcdir)/insert-header.sin > en@boldquot.insert-header + +mostlyclean: mostlyclean-quot +mostlyclean-quot: + rm -f *.insert-header diff --git a/po/boldquot.sed b/po/boldquot.sed new file mode 100644 index 0000000..4b937aa --- /dev/null +++ b/po/boldquot.sed @@ -0,0 +1,10 @@ +s/"\([^"]*\)"/“\1”/g +s/`\([^`']*\)'/‘\1’/g +s/ '\([^`']*\)' / ‘\1’ /g +s/ '\([^`']*\)'$/ ‘\1’/g +s/^'\([^`']*\)' /‘\1’ /g +s/“”/""/g +s/“/“/g +s/”/”/g +s/‘/‘/g +s/’/’/g diff --git a/po/en@boldquot.header b/po/en@boldquot.header new file mode 100644 index 0000000..fedb6a0 --- /dev/null +++ b/po/en@boldquot.header @@ -0,0 +1,25 @@ +# All this catalog "translates" are quotation characters. +# The msgids must be ASCII and therefore cannot contain real quotation +# characters, only substitutes like grave accent (0x60), apostrophe (0x27) +# and double quote (0x22). These substitutes look strange; see +# http://www.cl.cam.ac.uk/~mgk25/ucs/quotes.html +# +# This catalog translates grave accent (0x60) and apostrophe (0x27) to +# left single quotation mark (U+2018) and right single quotation mark (U+2019). +# It also translates pairs of apostrophe (0x27) to +# left single quotation mark (U+2018) and right single quotation mark (U+2019) +# and pairs of quotation mark (0x22) to +# left double quotation mark (U+201C) and right double quotation mark (U+201D). +# +# When output to an UTF-8 terminal, the quotation characters appear perfectly. +# When output to an ISO-8859-1 terminal, the single quotation marks are +# transliterated to apostrophes (by iconv in glibc 2.2 or newer) or to +# grave/acute accent (by libiconv), and the double quotation marks are +# transliterated to 0x22. +# When output to an ASCII terminal, the single quotation marks are +# transliterated to apostrophes, and the double quotation marks are +# transliterated to 0x22. +# +# This catalog furthermore displays the text between the quotation marks in +# bold face, assuming the VT100/XTerm escape sequences. +# diff --git a/po/en@quot.header b/po/en@quot.header new file mode 100644 index 0000000..a9647fc --- /dev/null +++ b/po/en@quot.header @@ -0,0 +1,22 @@ +# All this catalog "translates" are quotation characters. +# The msgids must be ASCII and therefore cannot contain real quotation +# characters, only substitutes like grave accent (0x60), apostrophe (0x27) +# and double quote (0x22). These substitutes look strange; see +# http://www.cl.cam.ac.uk/~mgk25/ucs/quotes.html +# +# This catalog translates grave accent (0x60) and apostrophe (0x27) to +# left single quotation mark (U+2018) and right single quotation mark (U+2019). +# It also translates pairs of apostrophe (0x27) to +# left single quotation mark (U+2018) and right single quotation mark (U+2019) +# and pairs of quotation mark (0x22) to +# left double quotation mark (U+201C) and right double quotation mark (U+201D). +# +# When output to an UTF-8 terminal, the quotation characters appear perfectly. +# When output to an ISO-8859-1 terminal, the single quotation marks are +# transliterated to apostrophes (by iconv in glibc 2.2 or newer) or to +# grave/acute accent (by libiconv), and the double quotation marks are +# transliterated to 0x22. +# When output to an ASCII terminal, the single quotation marks are +# transliterated to apostrophes, and the double quotation marks are +# transliterated to 0x22. +# diff --git a/po/insert-header.sin b/po/insert-header.sin new file mode 100644 index 0000000..b26de01 --- /dev/null +++ b/po/insert-header.sin @@ -0,0 +1,23 @@ +# Sed script that inserts the file called HEADER before the header entry. +# +# At each occurrence of a line starting with "msgid ", we execute the following +# commands. At the first occurrence, insert the file. At the following +# occurrences, do nothing. The distinction between the first and the following +# occurrences is achieved by looking at the hold space. +/^msgid /{ +x +# Test if the hold space is empty. +s/m/m/ +ta +# Yes it was empty. First occurrence. Read the file. +r HEADER +# Output the file's contents by reading the next line. But don't lose the +# current line while doing this. +g +N +bb +:a +# The hold space was nonempty. Following occurrences. Do nothing. +x +:b +} diff --git a/po/quot.sed b/po/quot.sed new file mode 100644 index 0000000..0122c46 --- /dev/null +++ b/po/quot.sed @@ -0,0 +1,6 @@ +s/"\([^"]*\)"/“\1”/g +s/`\([^`']*\)'/‘\1’/g +s/ '\([^`']*\)' / ‘\1’ /g +s/ '\([^`']*\)'$/ ‘\1’/g +s/^'\([^`']*\)' /‘\1’ /g +s/“”/""/g diff --git a/po/remove-potcdate.sin b/po/remove-potcdate.sin new file mode 100644 index 0000000..2436c49 --- /dev/null +++ b/po/remove-potcdate.sin @@ -0,0 +1,19 @@ +# Sed script that remove the POT-Creation-Date line in the header entry +# from a POT file. +# +# The distinction between the first and the following occurrences of the +# pattern is achieved by looking at the hold space. +/^"POT-Creation-Date: .*"$/{ +x +# Test if the hold space is empty. +s/P/P/ +ta +# Yes it was empty. First occurrence. Remove the line. +g +d +bb +:a +# The hold space was nonempty. Following occurrences. Do nothing. +x +:b +} diff --git a/src/Makefile.am b/src/Makefile.am index 13a2b16..afac912 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -43,5 +43,6 @@ trader_SOURCES = \ AM_CPPFLAGS = -I$(top_builddir)/lib -I$(top_srcdir)/lib trader_LDADD = @LIBINTL@ @CURSES_LIB@ $(top_builddir)/lib/libgnu.a +DEFS = -DLOCALEDIR=\"$(localedir)\" @DEFS@ EXTRA_DIST = README diff --git a/src/system.h b/src/system.h index 7d0a80b..3456ad3 100644 --- a/src/system.h +++ b/src/system.h @@ -74,6 +74,14 @@ #include +// Internationalisation using GNU gettext + +#include "gettext.h" // This handles ENABLE_NLS correctly + +#define _(string) gettext(string) +#define N_(string) gettext_noop(string) + + // X/Open-compatible Curses library #if defined(HAVE_NCURSESW_CURSES_H) diff --git a/src/trader.c b/src/trader.c index d22c1a0..062ca80 100644 --- a/src/trader.c +++ b/src/trader.c @@ -155,6 +155,10 @@ int main (int argc, char *argv[]) "(check LANG, LC_ALL and LANGUAGE in environment)"); } + // Use correct message catalogs for the locale + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + // Process command line arguments process_cmdline(argc, argv); From 686b3b0e0ef959672b1ba77b39822a24c2fdb222 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Mon, 1 Aug 2011 18:59:11 +1000 Subject: [PATCH 003/112] Rearrange order of linked libraries; move definition of LOCALEDIR --- src/Makefile.am | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index afac912..692d7f6 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -41,8 +41,8 @@ trader_SOURCES = \ utils.c utils.h \ system.h -AM_CPPFLAGS = -I$(top_builddir)/lib -I$(top_srcdir)/lib -trader_LDADD = @LIBINTL@ @CURSES_LIB@ $(top_builddir)/lib/libgnu.a -DEFS = -DLOCALEDIR=\"$(localedir)\" @DEFS@ +trader_CPPFLAGS = -I$(top_builddir)/lib -I$(top_srcdir)/lib \ + -DLOCALEDIR=\"$(localedir)\" +trader_LDADD = @CURSES_LIB@ $(top_builddir)/lib/libgnu.a @LIBINTL@ EXTRA_DIST = README From 36b1a132549c0bd34e99367dcbcd7780b7c7b11b Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Mon, 1 Aug 2011 18:59:54 +1000 Subject: [PATCH 004/112] Add languages currently enabled; add source files to internationalise --- po/LINGUAS | 29 +++++++++++++++++++++++++++++ po/POTFILES.in | 16 ++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 po/LINGUAS diff --git a/po/LINGUAS b/po/LINGUAS new file mode 100644 index 0000000..14fe9e1 --- /dev/null +++ b/po/LINGUAS @@ -0,0 +1,29 @@ +######################################################################### +# # +# Star Traders: A Game of Interstellar Trading # +# Copyright (C) 1990-2011, John Zaitseff # +# # +######################################################################### + +# Author: John Zaitseff +# $Id$ +# +# This file, po/LINGUAS, contains a list of the available languages in +# the po directory. +# +# +# This program 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 3 of the License, or (at your +# option) any later version. +# +# This program 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, see http://www.gnu.org/licenses/. + + +en@quot diff --git a/po/POTFILES.in b/po/POTFILES.in index c541778..e227a2c 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -24,3 +24,19 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see http://www.gnu.org/licenses/. + + +# Source files from Star Traders +src/trader.c +src/globals.c +src/game.c +src/move.c +src/exch.c +src/fileio.c +src/help.c +src/intf.c +src/utils.c + + +# Source files from the Gnulib GNU Portability Library +lib/getopt.c From 9251ca046361cc26e33e74b5953fd8811c143825 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Mon, 1 Aug 2011 19:30:19 +1000 Subject: [PATCH 005/112] First pass at adding _() and N_() to allow string translation --- src/fileio.c | 28 ++++++++++++++-------------- src/game.c | 4 ++-- src/globals.c | 34 +++++++++++++++++----------------- src/intf.c | 2 +- src/trader.c | 36 ++++++++++++++++++------------------ src/utils.c | 8 ++++---- 6 files changed, 56 insertions(+), 56 deletions(-) diff --git a/src/fileio.c b/src/fileio.c index a9917a6..94e9677 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -52,15 +52,15 @@ static const unsigned char game_file_crypt_key[] = { #define load_game_scanf(_fmt, _var, _cond) \ do { \ if (fgets(buf, BUFSIZE, file) == NULL) { \ - err_exit("%s: missing field on line %d", filename, lineno); \ + err_exit(_("%s: missing field on line %d"), filename, lineno); \ } \ if (sscanf(unscramble(crypt_key, buf, BUFSIZE), _fmt "\n", \ &(_var)) != 1) { \ - err_exit("%s: illegal field on line %d: `%s'", \ + err_exit(_("%s: illegal field on line %d: `%s'"), \ filename, lineno, buf); \ } \ if (! (_cond)) { \ - err_exit("%s: illegal value on line %d: `%s'", \ + err_exit(_("%s: illegal value on line %d: `%s'"), \ filename, lineno, buf); \ } \ lineno++; \ @@ -87,10 +87,10 @@ static const unsigned char game_file_crypt_key[] = { int len; \ \ if (fgets(buf, BUFSIZE, file) == NULL) { \ - err_exit("%s: missing field on line %d", filename, lineno); \ + err_exit(_("%s: missing field on line %d"), filename, lineno); \ } \ if (strlen(unscramble(crypt_key, buf, BUFSIZE)) == 0) { \ - err_exit("%s: illegal value on line %d", filename, lineno); \ + err_exit(_("%s: illegal value on line %d"), filename, lineno); \ } \ lineno++; \ \ @@ -205,16 +205,16 @@ bool load_game (int num) // Read the game file header if (fgets(buf, BUFSIZE, file) == NULL) { - err_exit("%s: missing header in game file", filename); + err_exit(_("%s: missing header in game file"), filename); } if (strcmp(buf, GAME_FILE_HEADER "\n") != 0) { - err_exit("%s: not a valid game file", filename); + err_exit(_("%s: not a valid game file"), filename); } if (fgets(buf, BUFSIZE, file) == NULL) { - err_exit("%s: missing subheader in game file", filename); + err_exit(_("%s: missing subheader in game file"), filename); } if (strcmp(buf, GAME_FILE_API_VERSION "\n") != 0) { - err_exit("%s: saved under a different version of Star Traders", + err_exit(_("%s: saved under a different version of Star Traders"), filename); } @@ -222,7 +222,7 @@ bool load_game (int num) // Read in the game file encryption key if (fscanf(file, "%i\n", &crypt_key) != 1) { - err_exit("%s: illegal or missing field on line %d", filename, lineno); + err_exit(_("%s: illegal or missing field on line %d"), filename, lineno); } lineno++; @@ -251,7 +251,7 @@ bool load_game (int num) // Read in company data for (i = 0; i < MAX_COMPANIES; i++) { - company[i].name = company_name[i]; + company[i].name = strdup(gettext(company_name[i])); load_game_read_double(company[i].share_price, company[i].share_price >= 0.0); load_game_read_double(company[i].share_return, true); load_game_read_long(company[i].stock_issued, company[i].stock_issued >= 0); @@ -262,10 +262,10 @@ bool load_game (int num) // Read in galaxy map for (int x = 0; x < MAX_X; x++) { if (fgets(buf, BUFSIZE, file) == NULL) { - err_exit("%s: missing field on line %d", filename, lineno); + err_exit(_("%s: missing field on line %d"), filename, lineno); } if (strlen(unscramble(crypt_key, buf, BUFSIZE)) != MAX_Y + 1) { - err_exit("%s: illegal field on line %d", filename, lineno); + err_exit(_("%s: illegal field on line %d"), filename, lineno); } for (int y = 0; y < MAX_Y; y++) { @@ -274,7 +274,7 @@ bool load_game (int num) || (c >= MAP_A && c <= MAP_LAST)) { galaxy_map[x][y] = (map_val_t) c; } else { - err_exit("%s: illegal value on line %d", filename, lineno); + err_exit(_("%s: illegal value on line %d"), filename, lineno); } } diff --git a/src/game.c b/src/game.c index 719ca64..3e13573 100644 --- a/src/game.c +++ b/src/game.c @@ -178,7 +178,7 @@ void init_game (void) // Initialise company data for (i = 0; i < MAX_COMPANIES; i++) { - company[i].name = company_name[i]; + company[i].name = strdup(gettext(company_name[i])); company[i].share_price = 0.0; company[i].share_return = INITIAL_RETURN; company[i].stock_issued = 0; @@ -552,7 +552,7 @@ void end_game (void) for (i = 0; i < number_players; i++) { l_strfmon(buf, BUFSIZE, "%!18n", player[i].sort_value); mvwprintw(curwin, i + 7, 2, "%5s %-*.*s %18s ", - ordinal[i + 1], w, w, player[i].name, buf); + gettext(ordinal[i + 1]), w, w, player[i].name, buf); } wait_for_key(curwin, getmaxy(curwin) - 2, attr_waitforkey); diff --git a/src/globals.c b/src/globals.c index 1d452b7..4a61865 100644 --- a/src/globals.c +++ b/src/globals.c @@ -37,28 +37,28 @@ // Company names const char *company_name[MAX_COMPANIES] = { - "Altair Starways", - "Betelgeuse, Ltd", - "Capella Freight Co", - "Denebola Shippers", - "Eridani Expediters", - "Fornax Express", - "Gemeni Inc", - "Hercules and Co" + N_("Altair Starways"), + N_("Betelgeuse, Ltd"), + N_("Capella Freight Co"), + N_("Denebola Shippers"), + N_("Eridani Expediters"), + N_("Fornax Express"), + N_("Gemeni Inc"), + N_("Hercules and Co") }; // Ordinal strings const char *ordinal[MAX_PLAYERS + 1] = { - "0th", - "1st", - "2nd", - "3rd", - "4th", - "5th", - "6th", - "7th", - "8th" + N_("0th"), + N_("1st"), + N_("2nd"), + N_("3rd"), + N_("4th"), + N_("5th"), + N_("6th"), + N_("7th"), + N_("8th") }; diff --git a/src/intf.c b/src/intf.c index 9033437..6f03ad5 100644 --- a/src/intf.c +++ b/src/intf.c @@ -129,7 +129,7 @@ void init_screen (void) initscr(); if (COLS < MIN_COLS || LINES < MIN_LINES) { - err_exit("terminal size is too small (%d x %d required)", + err_exit(_("terminal size is too small (%d x %d required)"), MIN_COLS, MIN_LINES); } diff --git a/src/trader.c b/src/trader.c index 062ca80..9ff175e 100644 --- a/src/trader.c +++ b/src/trader.c @@ -232,7 +232,7 @@ void process_cmdline (int argc, char *argv[]) option_max_turn = strtol(optarg, &p, 10); if (option_max_turn < MIN_MAX_TURN || p == NULL || *p != '\0') { - fprintf(stderr, "%s: invalid value for --max-turn: `%s'\n", + fprintf(stderr, _("%s: invalid value for --max-turn: `%s'\n"), program_name(), optarg); show_usage(EXIT_FAILURE); } @@ -248,7 +248,7 @@ void process_cmdline (int argc, char *argv[]) if (optind < argc && argv[optind] != NULL) { if (*argv[optind] == '-') { - fprintf(stderr, "%s: invalid operand `%s'\n", program_name(), + fprintf(stderr, _("%s: invalid operand `%s'\n"), program_name(), argv[optind]); show_usage(EXIT_FAILURE); } @@ -257,7 +257,7 @@ void process_cmdline (int argc, char *argv[]) && *argv[optind] >= '1' && *argv[optind] <= '9') { game_num = *argv[optind] - '0'; } else { - fprintf(stderr, "%s: invalid game number `%s'\n", + fprintf(stderr, _("%s: invalid game number `%s'\n"), program_name(), argv[optind]); show_usage(EXIT_FAILURE); } @@ -266,7 +266,7 @@ void process_cmdline (int argc, char *argv[]) } if (optind < argc && argv[optind] != NULL) { - fprintf(stderr, "%s: extra operand `%s'\n", program_name(), + fprintf(stderr, _("%s: extra operand `%s'\n"), program_name(), argv[optind]); show_usage(EXIT_FAILURE); } @@ -278,7 +278,7 @@ void process_cmdline (int argc, char *argv[]) void show_version (void) { - printf("\ + printf(_("\ " PACKAGE_NAME " (%s) %s\n\ Copyright (C) %s, John Zaitseff.\n\ \n\ @@ -290,7 +290,7 @@ This program is free software that is distributed under the terms of the\n\ GNU General Public License, version 3 or later. You are welcome to\n\ modify and/or distribute it under certain conditions. This program has\n\ NO WARRANTY, to the extent permitted by law; see the License for details.\n\ -", program_name(), PACKAGE_VERSION, "1990-2011"); +"), program_name(), PACKAGE_VERSION, "1990-2011"); exit(EXIT_SUCCESS); } @@ -305,35 +305,35 @@ void show_usage (int status) if (status != EXIT_SUCCESS) { - fprintf(stderr, "%s: Try `%s --help' for more information.\n", + fprintf(stderr, _("%s: Try `%s --help' for more information.\n"), pn, pn); } else { - printf("Usage: %s [OPTION ...] [GAME]\n", pn); - printf("\ + printf(_("Usage: %s [OPTION ...] [GAME]\n"), pn); + printf(_("\ Play Star Traders, a simple game of interstellar trading.\n\n\ -"); - printf("\ +")); + printf(_("\ Options:\n\ -V, --version output version information and exit\n\ -h, --help display this help and exit\n\ --no-color don't use colour for displaying text\n\ --max-turn=NUM set the number of turns to NUM\n\n\ -"); - printf("\ +")); + printf(_("\ If GAME is specified as a number between 1 and 9, load and continue\n\ playing that game. If GAME is not specified, start a new game.\n\n\ -"); +")); #ifdef PACKAGE_AUTHOR - printf("Report bugs to %s <%s>.\n", PACKAGE_AUTHOR, PACKAGE_BUGREPORT); + printf(_("Report bugs to %s <%s>.\n"), PACKAGE_AUTHOR, PACKAGE_BUGREPORT); #else - printf("Report bugs to <%s>.\n", PACKAGE_BUGREPORT); + printf(_("Report bugs to <%s>.\n"), PACKAGE_BUGREPORT); #endif #ifdef PACKAGE_PACKAGER_BUG_REPORTS - printf("Report %s bugs to <%s>.\n", PACKAGE_PACKAGER, PACKAGE_PACKAGER_BUG_REPORTS); + printf(_("Report %s bugs to <%s>.\n"), PACKAGE_PACKAGER, PACKAGE_PACKAGER_BUG_REPORTS); #endif #ifdef PACKAGE_URL - printf(PACKAGE_NAME " home page: <%s>.\n", PACKAGE_URL); + printf(_(PACKAGE_NAME " home page: <%s>.\n"), PACKAGE_URL); #endif } diff --git a/src/utils.c b/src/utils.c index ce13f0e..32f4df0 100644 --- a/src/utils.c +++ b/src/utils.c @@ -206,7 +206,7 @@ void err_exit (const char *restrict format, ...) end_screen(); - fprintf(stderr, "%s: ", program_name()); + fprintf(stderr, _("%s: "), program_name()); va_start(args, format); vfprintf(stderr, format, args); va_end(args); @@ -227,12 +227,12 @@ void errno_exit (const char *restrict format, ...) end_screen(); - fprintf(stderr, "%s: ", program_name()); + fprintf(stderr, _("%s: "), program_name()); if (format != NULL) { va_start(args, format); vfprintf(stderr, format, args); va_end(args); - fputs(": ", stderr); + fputs(_(": "), stderr); } fprintf(stderr, "%s\n", strerror(saved_errno)); @@ -245,7 +245,7 @@ void errno_exit (const char *restrict format, ...) void err_exit_nomem (void) { - err_exit("out of memory"); + err_exit(_("out of memory")); } From 1ee27fda20ae673449c0f562379820d54736cb99 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Mon, 1 Aug 2011 19:43:55 +1000 Subject: [PATCH 006/112] Minor modifications to allow the first pass to compile! --- src/globals.c | 1 + src/trader.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/globals.c b/src/globals.c index 4a61865..3deab67 100644 --- a/src/globals.c +++ b/src/globals.c @@ -28,6 +28,7 @@ */ +#include "system.h" #include "globals.h" diff --git a/src/trader.c b/src/trader.c index 9ff175e..a7d7ab2 100644 --- a/src/trader.c +++ b/src/trader.c @@ -279,7 +279,7 @@ void process_cmdline (int argc, char *argv[]) void show_version (void) { printf(_("\ -" PACKAGE_NAME " (%s) %s\n\ +Star Traders (%s) %s\n\ Copyright (C) %s, John Zaitseff.\n\ \n\ Star Traders is a simple game of interstellar trading, where the object\n\ From c7e1f6096f7cb8bcb4e84b627b2f30b0bc99721c Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Mon, 1 Aug 2011 19:49:16 +1000 Subject: [PATCH 007/112] Replace PACKAGE_NAME with "Star Traders" The gettext utilities don't like C macros in gettext() invocations, so replace each occurrence of PACKAGE_NAME with "Star Traders". --- src/intf.c | 2 +- src/trader.c | 2 +- src/trader.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/intf.c b/src/intf.c index 6f03ad5..6214570 100644 --- a/src/intf.c +++ b/src/intf.c @@ -234,7 +234,7 @@ void init_screen (void) addch(attr_game_title | ' '); } - center(stdscr, 0, attr_game_title, PACKAGE_NAME); + center(stdscr, 0, attr_game_title, "Star Traders"); attrset(attr_root_window); refresh(); diff --git a/src/trader.c b/src/trader.c index a7d7ab2..5b1bbd8 100644 --- a/src/trader.c +++ b/src/trader.c @@ -333,7 +333,7 @@ playing that game. If GAME is not specified, start a new game.\n\n\ printf(_("Report %s bugs to <%s>.\n"), PACKAGE_PACKAGER, PACKAGE_PACKAGER_BUG_REPORTS); #endif #ifdef PACKAGE_URL - printf(_(PACKAGE_NAME " home page: <%s>.\n"), PACKAGE_URL); + printf(_("Star Traders home page: <%s>.\n"), PACKAGE_URL); #endif } diff --git a/src/trader.h b/src/trader.h index 90e6d81..3fd27d3 100644 --- a/src/trader.h +++ b/src/trader.h @@ -52,7 +52,7 @@ * Global definitions * ************************************************************************/ -#define GAME_FILE_HEADER PACKAGE_NAME " Saved Game" +#define GAME_FILE_HEADER "Star Traders Saved Game" #define GAME_FILE_API_VERSION "7.0" // For game loads and saves #define GAME_FILE_SENTINEL 42 // End of game file sentinel From ee6e48fd456ef75f32b239ac2f84d6cd3af8feb7 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Mon, 1 Aug 2011 20:35:16 +1000 Subject: [PATCH 008/112] Add a README file to the po directory --- po/README | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 po/README diff --git a/po/README b/po/README new file mode 100644 index 0000000..7930c42 --- /dev/null +++ b/po/README @@ -0,0 +1,9 @@ +************************************************************************** +* * +* Star Traders: A Game of Interstellar Trading * +* Copyright (C) 1990-2011, John Zaitseff * +* * +************************************************************************** + +This directory, po, contains translations for text strings used in Star +Traders. The GNU Gettext project is used for this purpose. From 601678313df758cda0526fe70bc8118767cb4a39 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Mon, 1 Aug 2011 20:52:40 +1000 Subject: [PATCH 009/112] As much as I don't like it, change the help string to American spelling --- src/trader.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/trader.c b/src/trader.c index 5b1bbd8..b47dda6 100644 --- a/src/trader.c +++ b/src/trader.c @@ -316,7 +316,7 @@ Play Star Traders, a simple game of interstellar trading.\n\n\ Options:\n\ -V, --version output version information and exit\n\ -h, --help display this help and exit\n\ - --no-color don't use colour for displaying text\n\ + --no-color don't use color for displaying text\n\ --max-turn=NUM set the number of turns to NUM\n\n\ ")); printf(_("\ From 1e7c6c098a298ad08810580a7db67f85e624aec4 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Mon, 8 Aug 2011 10:21:24 +1000 Subject: [PATCH 010/112] Add checks for the C.UTF-8 (C.utf8) locale for adding a currency symbol --- src/utils.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/utils.c b/src/utils.c index 32f4df0..9c2ecd1 100644 --- a/src/utils.c +++ b/src/utils.c @@ -320,8 +320,10 @@ void init_locale (void) /* Are we in the POSIX locale? This test may not be portable as the string returned by setlocale() is supposed to be opaque. */ add_currency_symbol = false; - if (strcmp(current_mon_locale, "POSIX") == 0 - || strcmp(current_mon_locale, "C") == 0) { + if ( strcmp(current_mon_locale, "POSIX") == 0 + || strcmp(current_mon_locale, "C") == 0 + || strcmp(current_mon_locale, "C.UTF-8") == 0 + || strcmp(current_mon_locale, "C.utf8") == 0) { add_currency_symbol = true; lconvinfo.currency_symbol = MOD_POSIX_CURRENCY_SYMBOL; From 32ed55a0cd8f46126c1d757455ba46a21800812e Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Mon, 8 Aug 2011 11:15:44 +1000 Subject: [PATCH 011/112] Convert strings to UTF-8 if possible during file save and load --- .gitignore | 2 + configure.ac | 6 +- lib/.gitignore | 34 +++++++++ m4/.gitignore | 5 ++ m4/gnulib-cache.m4 | 4 +- src/Makefile.am | 2 +- src/fileio.c | 182 +++++++++++++++++++++++++++++++++++++++++---- src/system.h | 10 +++ src/trader.h | 8 +- 9 files changed, 233 insertions(+), 20 deletions(-) diff --git a/.gitignore b/.gitignore index 0247e11..2f1337e 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ Makefile.in /configure /stamp-h1 +/build-aux/compile /build-aux/config.guess /build-aux/config.rpath /build-aux/config.sub @@ -22,6 +23,7 @@ Makefile.in /build-aux/snippet/arg-nonnull.h /build-aux/snippet/c++defs.h +/build-aux/snippet/unused-parameter.h /build-aux/snippet/warn-on-use.h /build-aux/snippet/_Noreturn.h diff --git a/configure.ac b/configure.ac index 77fa26c..c65dafc 100644 --- a/configure.ac +++ b/configure.ac @@ -50,6 +50,9 @@ AX_C___ATTRIBUTE__ AC_TYPE_SIZE_T AC_TYPE_SSIZE_T +AM_GNU_GETTEXT([external]) +AM_GNU_GETTEXT_VERSION([0.18.1]) + gl_INIT AX_WITH_CURSES @@ -57,9 +60,6 @@ AS_IF([test "x$ax_cv_curses" != xyes || test "x$ax_cv_curses_color" != xyes], [ AC_MSG_ERROR([requires an X/Open-compatible Curses library with colour]) ]) -AM_GNU_GETTEXT([external]) -AM_GNU_GETTEXT_VERSION([0.18.1]) - AC_CONFIG_FILES([ Makefile lib/Makefile diff --git a/lib/.gitignore b/lib/.gitignore index 58e90ee..723eb71 100644 --- a/lib/.gitignore +++ b/lib/.gitignore @@ -2,6 +2,11 @@ Makefile.am alloca.in.h asnprintf.c ctype.in.h +c-ctype.c +c-ctype.h +c-strcase.h +c-strcasecmp.c +c-strncasecmp.c dosname.h errno.in.h float.c @@ -19,6 +24,15 @@ getopt1.c getopt_int.h gettext.h gettimeofday.c +iconv.c +iconv.in.h +iconv_close.c +iconv_open-aix.gperf +iconv_open-hpux.gperf +iconv_open-irix.gperf +iconv_open-osf.gperf +iconv_open-solaris.gperf +iconv_open.c isnan.c isnand.c isnand-nolibm.h @@ -26,6 +40,7 @@ isnanf.c isnanf-nolibm.h isnanl.c isnanl-nolibm.h +langinfo.in.h locale.in.h malloc.c math.in.h @@ -54,6 +69,8 @@ stdio.in.h stdio-impl.h stdlib.in.h strdup.c +striconv.c +striconv.h string.in.h strncat.c strstr.c @@ -62,6 +79,8 @@ sys_stat.in.h sys_time.in.h time.in.h unistd.in.h +unistr.in.h +unitypes.in.h vasnprintf.c vasnprintf.h verify.h @@ -75,6 +94,13 @@ arg-nonnull.h c++defs.h ctype.h getopt.h +iconv.h +iconv_open-aix.h +iconv_open-hpux.h +iconv_open-irix.h +iconv_open-osf.h +iconv_open-solaris.h +langinfo.h locale.h math.h stdio.h @@ -83,5 +109,13 @@ string.h sys time.h unistd.h +unistr.h +unitypes.h +unused-parameter.h warn-on-use.h wchar.h + +unistr/.dirstamp +unistr/u8-mbtoucr.c +unistr/u8-uctomb-aux.c +unistr/u8-uctomb.c diff --git a/m4/.gitignore b/m4/.gitignore index 8c17497..76961e1 100644 --- a/m4/.gitignore +++ b/m4/.gitignore @@ -25,7 +25,10 @@ gnulib-common.m4 gnulib-comp.m4 gnulib-tool.m4 iconv.m4 +iconv_h.m4 +iconv_open.m4 include_next.m4 +inline.m4 intdiv0.m4 intldir.m4 intl.m4 @@ -37,12 +40,14 @@ inttypes_h.m4 isnand.m4 isnanf.m4 isnanl.m4 +langinfo_h.m4 largefile.m4 lcmessage.m4 ldexpl.m4 lib-ld.m4 lib-link.m4 lib-prefix.m4 +libunistring-base.m4 locale_h.m4 lock.m4 longlong.m4 diff --git a/m4/gnulib-cache.m4 b/m4/gnulib-cache.m4 index b0b1044..da62d61 100644 --- a/m4/gnulib-cache.m4 +++ b/m4/gnulib-cache.m4 @@ -15,7 +15,7 @@ # Specification in the form of a command-line invocation: -# gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --no-conditional-dependencies --no-libtool --macro-prefix=gl assert config-h ctype fprintf-posix getopt-gnu gettext gettext-h gettimeofday locale printf-posix snprintf-posix stat stdarg stdbool stdio strdup-posix string strncat strstr sys_stat sys_time unistd vfprintf-posix vsnprintf-posix +# gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --no-conditional-dependencies --no-libtool --macro-prefix=gl assert config-h ctype fprintf-posix getopt-gnu gettext gettext-h gettimeofday langinfo locale printf-posix snprintf-posix stat stdarg stdbool stdio strdup-posix striconv string strncat strstr sys_stat sys_time unistd vfprintf-posix vsnprintf-posix # Specification in the form of a few gnulib-tool.m4 macro invocations: gl_LOCAL_DIR([]) @@ -28,6 +28,7 @@ gl_MODULES([ gettext gettext-h gettimeofday + langinfo locale printf-posix snprintf-posix @@ -36,6 +37,7 @@ gl_MODULES([ stdbool stdio strdup-posix + striconv string strncat strstr diff --git a/src/Makefile.am b/src/Makefile.am index 692d7f6..57feebf 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -43,6 +43,6 @@ trader_SOURCES = \ trader_CPPFLAGS = -I$(top_builddir)/lib -I$(top_srcdir)/lib \ -DLOCALEDIR=\"$(localedir)\" -trader_LDADD = @CURSES_LIB@ $(top_builddir)/lib/libgnu.a @LIBINTL@ +trader_LDADD = @CURSES_LIB@ @LIBICONV@ $(top_builddir)/lib/libgnu.a @LIBINTL@ EXTRA_DIST = README diff --git a/src/fileio.c b/src/fileio.c index 94e9677..6721854 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -52,7 +52,8 @@ static const unsigned char game_file_crypt_key[] = { #define load_game_scanf(_fmt, _var, _cond) \ do { \ if (fgets(buf, BUFSIZE, file) == NULL) { \ - err_exit(_("%s: missing field on line %d"), filename, lineno); \ + err_exit(_("%s: missing field on line %d"), \ + filename, lineno); \ } \ if (sscanf(unscramble(crypt_key, buf, BUFSIZE), _fmt "\n", \ &(_var)) != 1) { \ @@ -81,32 +82,76 @@ static const unsigned char game_file_crypt_key[] = { (_var) = b; \ } while (0) -#define load_game_read_string(_var) \ +#ifdef USE_UTF8_GAME_FILE +# define load_game_read_string(_var) \ do { \ char *s; \ int len; \ \ if (fgets(buf, BUFSIZE, file) == NULL) { \ - err_exit(_("%s: missing field on line %d"), filename, lineno); \ + err_exit(_("%s: missing field on line %d"), \ + filename, lineno); \ } \ if (strlen(unscramble(crypt_key, buf, BUFSIZE)) == 0) { \ - err_exit(_("%s: illegal value on line %d"), filename, lineno); \ + err_exit(_("%s: illegal value on line %d"), \ + filename, lineno); \ } \ - lineno++; \ - \ - s = malloc(strlen(buf) + 1); \ - if (s == NULL) { \ - err_exit_nomem(); \ + if (need_icd) { \ + s = str_cd_iconv(buf, icd); \ + if (s == NULL) { \ + if (errno == EILSEQ) { \ + err_exit(_("%s: illegal characters on line %d"), \ + filename, lineno); \ + } else { \ + errno_exit("str_cd_iconv()"); \ + } \ + } \ + } else { \ + s = malloc(strlen(buf) + 1); \ + if (s == NULL) { \ + err_exit_nomem(); \ + } \ + strcpy(s, buf); \ } \ \ - strcpy(s, buf); \ len = strlen(s); \ if (len > 0 && s[len - 1] == '\n') { \ s[len - 1] = '\0'; \ } \ \ + lineno++; \ (_var) = s; \ } while (0) +#else // ! USE_UTF8_GAME_FILE +# define load_game_read_string(_var) \ + do { \ + char *s; \ + int len; \ + \ + if (fgets(buf, BUFSIZE, file) == NULL) { \ + err_exit(_("%s: missing field on line %d"), \ + filename, lineno); \ + } \ + if (strlen(unscramble(crypt_key, buf, BUFSIZE)) == 0) { \ + err_exit(_("%s: illegal value on line %d"), \ + filename, lineno); \ + } \ + \ + s = malloc(strlen(buf) + 1); \ + if (s == NULL) { \ + err_exit_nomem(); \ + } \ + strcpy(s, buf); \ + \ + len = strlen(s); \ + if (len > 0 && s[len - 1] == '\n') { \ + s[len - 1] = '\0'; \ + } \ + \ + lineno++; \ + (_var) = s; \ + } while (0) +#endif // ! USE_UTF8_GAME_FILE // Macros used in save_game() @@ -126,8 +171,30 @@ static const unsigned char game_file_crypt_key[] = { save_game_printf("%2.20e", _var) #define save_game_write_bool(_var) \ save_game_printf("%d", (int) _var) -#define save_game_write_string(_var) \ + +#ifdef USE_UTF8_GAME_FILE +# define save_game_write_string(_var) \ + do { \ + if (need_icd) { \ + char *s = str_cd_iconv(_var, icd); \ + if (s == NULL) { \ + if (errno == EILSEQ) { \ + err_exit(_("%s: could not convert string"), \ + filename); \ + } else { \ + errno_exit("str_cd_iconv()"); \ + } \ + } \ + save_game_printf("%s", s); \ + free(s); \ + } else { \ + save_game_printf("%s", _var); \ + } \ + } while (0) +#else // ! USE_UTF8_GAME_FILE +# define save_game_write_string(_var) \ save_game_printf("%s", _var) +#endif // ! USE_UTF8_GAME_FILE /************************************************************************ @@ -144,12 +211,18 @@ bool load_game (int num) { char *buf, *filename; FILE *file; + char *codeset, *codeset_nl; int saved_errno, lineno; char *prev_locale; int crypt_key; int n, i, j; +#ifdef USE_UTF8_GAME_FILE + iconv_t icd; + bool need_icd; +#endif + assert(num >= 1 && num <= 9); @@ -196,6 +269,39 @@ bool load_game (int num) return false; } +#ifdef USE_UTF8_GAME_FILE + // Make sure all strings are read in UTF-8 format for consistency + codeset = nl_langinfo(CODESET); + if (codeset == NULL) { + errno_exit("nl_langinfo(CODESET)"); + } + need_icd = (strcmp(codeset, GAME_FILE_CHARSET) != 0); + if (need_icd) { + icd = iconv_open(codeset, GAME_FILE_CHARSET); + if (icd == (iconv_t) -1) { + errno_exit("iconv_open()"); + } + } else { + icd = (iconv_t) -1; + } + codeset_nl = strdup(GAME_FILE_CHARSET "\n"); + if (codeset_nl == NULL) { + err_exit_nomem(); + } +#else // ! USE_UTF8_GAME_FILE + // Make sure all strings are read in the correct codeset + codeset = nl_langinfo(CODESET); + if (codeset == NULL) { + errno_exit("nl_langinfo(CODESET)"); + } + codeset_nl = malloc(strlen(codeset) + 2); + if (codeset_nl == NULL) { + err_exit_nomem(); + } + strcpy(codeset_nl, codeset); + strcat(codeset_nl, "\n"); +#endif // ! USE_UTF8_GAME_FILE + // Change the formatting of numbers to the POSIX locale for consistency prev_locale = strdup(setlocale(LC_NUMERIC, NULL)); if (prev_locale == NULL) { @@ -217,8 +323,15 @@ bool load_game (int num) err_exit(_("%s: saved under a different version of Star Traders"), filename); } + if (fgets(buf, BUFSIZE, file) == NULL) { + err_exit(_("%s: missing subheader in game file"), filename); + } + if (strcmp(buf, codeset_nl) != 0) { + err_exit(_("%s: saved under an incompatible character encoding"), + filename); + } - lineno = 3; + lineno = 4; // Read in the game file encryption key if (fscanf(file, "%i\n", &crypt_key) != 1) { @@ -291,9 +404,16 @@ bool load_game (int num) // Change the formatting of numbers back to the user-supplied locale setlocale(LC_NUMERIC, prev_locale); +#ifdef USE_UTF8_GAME_FILE + if (need_icd) { + iconv_close(icd); + } +#endif + free(buf); free(filename); free(prev_locale); + free(codeset_nl); return true; } @@ -306,12 +426,18 @@ bool save_game (int num) const char *data_dir; char *buf, *filename; FILE *file; + char *codeset; int saved_errno; char *prev_locale; struct stat statbuf; int crypt_key; int i, j, x, y; +#ifdef USE_UTF8_GAME_FILE + iconv_t icd; + bool need_icd; +#endif + assert(num >= 1 && num <= 9); @@ -375,6 +501,30 @@ bool save_game (int num) return false; } +#ifdef USE_UTF8_GAME_FILE + // Make sure all strings are output in UTF-8 format for consistency + codeset = nl_langinfo(CODESET); + if (codeset == NULL) { + errno_exit("nl_langinfo(CODESET)"); + } + need_icd = (strcmp(codeset, GAME_FILE_CHARSET) != 0); + if (need_icd) { + icd = iconv_open(codeset, GAME_FILE_CHARSET); + if (icd == (iconv_t) -1) { + errno_exit("iconv_open()"); + } + } else { + icd = (iconv_t) -1; + } + codeset = GAME_FILE_CHARSET; // Now contains output codeset +#else // ! USE_UTF8_GAME_FILE + // Make sure all strings are output in the correct codeset + codeset = nl_langinfo(CODESET); + if (codeset == NULL) { + errno_exit("nl_langinfo(CODESET)"); + } +#endif // ! USE_UTF8_GAME_FILE + // Change the formatting of numbers to the POSIX locale for consistency prev_locale = strdup(setlocale(LC_NUMERIC, NULL)); if (prev_locale == NULL) { @@ -384,7 +534,7 @@ bool save_game (int num) // Write out the game file header and encryption key fprintf(file, "%s\n" "%s\n", GAME_FILE_HEADER, GAME_FILE_API_VERSION); - fprintf(file, "%d\n", crypt_key); + fprintf(file, "%s\n" "%d\n", codeset, crypt_key); // Write out various game variables save_game_write_int(MAX_X); @@ -443,6 +593,12 @@ bool save_game (int num) // Change the formatting of numbers back to the user-supplied locale setlocale(LC_NUMERIC, prev_locale); +#ifdef USE_UTF8_GAME_FILE + if (need_icd) { + iconv_close(icd); + } +#endif + free(buf); free(filename); free(prev_locale); diff --git a/src/system.h b/src/system.h index 3456ad3..6b03183 100644 --- a/src/system.h +++ b/src/system.h @@ -67,6 +67,7 @@ #include #include #include +#include // Headers defined by the GNU C Library @@ -82,6 +83,15 @@ #define N_(string) gettext_noop(string) +// Character set conversion for game files + +#undef USE_UTF8_GAME_FILE +#ifdef HAVE_ICONV +# define USE_UTF8_GAME_FILE 1 +# include "striconv.h" +#endif + + // X/Open-compatible Curses library #if defined(HAVE_NCURSESW_CURSES_H) diff --git a/src/trader.h b/src/trader.h index 3fd27d3..1cc785b 100644 --- a/src/trader.h +++ b/src/trader.h @@ -53,8 +53,12 @@ ************************************************************************/ #define GAME_FILE_HEADER "Star Traders Saved Game" -#define GAME_FILE_API_VERSION "7.0" // For game loads and saves -#define GAME_FILE_SENTINEL 42 // End of game file sentinel +#define GAME_FILE_API_VERSION "File API 7.2" // For game loads and saves +#define GAME_FILE_SENTINEL 42 // End of game file sentinel + +#ifdef USE_UTF8_GAME_FILE +# define GAME_FILE_CHARSET "UTF-8" // For strings in game file +#endif #define BUFSIZE 1024 // For various string buffers From 2401bea19c3122d8a8fc01fab009523287d7b064 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Mon, 8 Aug 2011 12:33:25 +1000 Subject: [PATCH 012/112] Document the need for GPerf, and the --disable-nls configure option --- INSTALL | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/INSTALL b/INSTALL index 7853dee..12ccce3 100644 --- a/INSTALL +++ b/INSTALL @@ -39,6 +39,9 @@ and installation: 4. Development libraries and header files for all of the above. On many systems, these files are part of XXX-dev packages. +5. The GNU Perfect Hash Function Generator, gperf. This utility program + is required for parts of the GNU Portability Library. + Installation ============ @@ -58,6 +61,7 @@ manual: This version of the configure script understands the following additional command line options: + --disable-nls Do not use Native Language Support --disable-assert Turn off all debugging assert() statements --with-ncurses Force the use of NCurses over the system's Curses library From 91eb4d65d8ab4c73ae62c4ae32de73617f321fcc Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Mon, 8 Aug 2011 12:33:49 +1000 Subject: [PATCH 013/112] Add some TODO notes to NEWS --- NEWS | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 596936b..af59af1 100644 --- a/NEWS +++ b/NEWS @@ -18,7 +18,8 @@ at http://www.zap.org.au/services/svn/. Version 7.2 (not yet released) ------------------------------ -@@@ To be written. Internationalisation, multibyte strings +@@@ To be written. Internationalisation, multibyte strings, terminal +resizing, signals, game file in UTF-8 Version 7.1 (29th July, 2011) From bbdae69de4079c36350b0798e92937529c70dd48 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Mon, 8 Aug 2011 20:47:52 +1000 Subject: [PATCH 014/112] Add a signal handler for SIGINT and SIGTERM Add a signal handler for SIGINT and SIGTERM, as well as sprinklings of checks to abort_game. Although Ncurses DOES define handlers for SIGINT and SIGTERM, they do not always seem to work correctly under many operating systems. --- .gitignore | 2 +- lib/.gitignore | 21 +++++++++++------- m4/.gitignore | 15 +++++++------ m4/gnulib-cache.m4 | 4 +++- src/exch.c | 15 +++++++++++++ src/game.c | 42 ++++++++++++++++++++++++++++++------ src/globals.c | 3 ++- src/globals.h | 4 +++- src/help.c | 6 ++++++ src/intf.c | 53 +++++++++++++++++++++++++++++++++++++++++++--- src/intf.h | 11 +++++----- src/move.c | 52 ++++++++++++++++++++++++++++++++++++++++++--- src/system.h | 1 + src/trader.c | 2 +- 14 files changed, 195 insertions(+), 36 deletions(-) diff --git a/.gitignore b/.gitignore index 2f1337e..d10ac52 100644 --- a/.gitignore +++ b/.gitignore @@ -21,11 +21,11 @@ Makefile.in /build-aux/install-sh /build-aux/missing +/build-aux/snippet/_Noreturn.h /build-aux/snippet/arg-nonnull.h /build-aux/snippet/c++defs.h /build-aux/snippet/unused-parameter.h /build-aux/snippet/warn-on-use.h -/build-aux/snippet/_Noreturn.h /po/POTFILES /po/remove-potcdate.sed diff --git a/lib/.gitignore b/lib/.gitignore index 723eb71..40cf3ec 100644 --- a/lib/.gitignore +++ b/lib/.gitignore @@ -1,17 +1,17 @@ Makefile.am alloca.in.h asnprintf.c -ctype.in.h c-ctype.c c-ctype.h c-strcase.h c-strcasecmp.c c-strncasecmp.c +ctype.in.h dosname.h errno.in.h +float+.h float.c float.in.h -float+.h fprintf.c fpucw.h frexp.c @@ -34,19 +34,18 @@ iconv_open-osf.gperf iconv_open-solaris.gperf iconv_open.c isnan.c -isnand.c isnand-nolibm.h -isnanf.c +isnand.c isnanf-nolibm.h -isnanl.c +isnanf.c isnanl-nolibm.h +isnanl.c langinfo.in.h locale.in.h malloc.c math.in.h memchr.c memchr.valgrind -printf.c printf-args.c printf-args.h printf-frexp.c @@ -55,9 +54,14 @@ printf-frexpl.c printf-frexpl.h printf-parse.c printf-parse.h +printf.c +sig-handler.h +sigaction.c +signal.in.h signbitd.c signbitf.c signbitl.c +sigprocmask.c size_max.h snprintf.c stat.c @@ -65,16 +69,16 @@ stdarg.in.h stdbool.in.h stddef.in.h stdint.in.h -stdio.in.h stdio-impl.h +stdio.in.h stdlib.in.h +str-two-way.h strdup.c striconv.c striconv.h string.in.h strncat.c strstr.c -str-two-way.h sys_stat.in.h sys_time.in.h time.in.h @@ -103,6 +107,7 @@ iconv_open-solaris.h langinfo.h locale.h math.h +signal.h stdio.h stdlib.h string.h diff --git a/m4/.gitignore b/m4/.gitignore index 76961e1..d9056c6 100644 --- a/m4/.gitignore +++ b/m4/.gitignore @@ -19,8 +19,8 @@ frexpl.m4 getopt.m4 gettext.m4 gettimeofday.m4 -glibc21.m4 glibc2.m4 +glibc21.m4 gnulib-common.m4 gnulib-comp.m4 gnulib-tool.m4 @@ -30,8 +30,8 @@ iconv_open.m4 include_next.m4 inline.m4 intdiv0.m4 -intldir.m4 intl.m4 +intldir.m4 intlmacosx.m4 intmax.m4 intmax_t.m4 @@ -59,16 +59,19 @@ multiarch.m4 nls.m4 nocrash.m4 po.m4 -printf.m4 printf-frexp.m4 printf-frexpl.m4 -printf-posix.m4 printf-posix-rpl.m4 +printf-posix.m4 +printf.m4 progtest.m4 +sigaction.m4 +signal_h.m4 +signalblocking.m4 signbit.m4 size_max.m4 -snprintf.m4 snprintf-posix.m4 +snprintf.m4 stat.m4 stdarg.m4 stdbool.m4 @@ -90,8 +93,8 @@ unistd_h.m4 vasnprintf.m4 vfprintf-posix.m4 visibility.m4 -vsnprintf.m4 vsnprintf-posix.m4 +vsnprintf.m4 warn-on-use.m4 wchar_h.m4 wchar_t.m4 diff --git a/m4/gnulib-cache.m4 b/m4/gnulib-cache.m4 index da62d61..94ec404 100644 --- a/m4/gnulib-cache.m4 +++ b/m4/gnulib-cache.m4 @@ -15,7 +15,7 @@ # Specification in the form of a command-line invocation: -# gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --no-conditional-dependencies --no-libtool --macro-prefix=gl assert config-h ctype fprintf-posix getopt-gnu gettext gettext-h gettimeofday langinfo locale printf-posix snprintf-posix stat stdarg stdbool stdio strdup-posix striconv string strncat strstr sys_stat sys_time unistd vfprintf-posix vsnprintf-posix +# gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --no-conditional-dependencies --no-libtool --macro-prefix=gl assert config-h ctype fprintf-posix getopt-gnu gettext gettext-h gettimeofday langinfo locale printf-posix sigaction signal snprintf-posix stat stdarg stdbool stdio strdup-posix striconv string strncat strstr sys_stat sys_time unistd vfprintf-posix vsnprintf-posix # Specification in the form of a few gnulib-tool.m4 macro invocations: gl_LOCAL_DIR([]) @@ -31,6 +31,8 @@ gl_MODULES([ langinfo locale printf-posix + sigaction + signal snprintf-posix stat stdarg diff --git a/src/exch.c b/src/exch.c index 9535ff5..d426608 100644 --- a/src/exch.c +++ b/src/exch.c @@ -211,6 +211,9 @@ void exchange_stock (void) break; default: + if (abort_game) + return; + beep(); } } @@ -256,6 +259,9 @@ void visit_bank (void) char *buf; + if (abort_game) + return; + buf = malloc(BUFSIZE); if (buf == NULL) { err_exit_nomem(); @@ -328,6 +334,9 @@ void visit_bank (void) break; default: + if (abort_game) + return; + beep(); } } @@ -482,6 +491,9 @@ void trade_shares (int num, bool *bid_used) char *buf; + if (abort_game) + return; + assert(num >= 0 && num < MAX_COMPANIES); assert(company[num].on_map); @@ -581,6 +593,9 @@ void trade_shares (int num, bool *bid_used) break; default: + if (abort_game) + return; + beep(); } } diff --git a/src/game.c b/src/game.c index 3e13573..18a6837 100644 --- a/src/game.c +++ b/src/game.c @@ -126,6 +126,9 @@ void init_game (void) while (number_players == 0) { int choice = ask_number_players(); + if (abort_game) + return; + if (choice == ERR) { abort_game = true; return; @@ -133,6 +136,9 @@ void init_game (void) } else if (choice == 0) { choice = ask_game_number(); + if (abort_game) + return; + if (choice != ERR) { game_num = choice; @@ -162,6 +168,9 @@ void init_game (void) ask_player_names(); + if (abort_game) + return; + deltxwin(); // "Number of players" window txrefresh(); @@ -221,7 +230,6 @@ void init_game (void) } quit_selected = false; - abort_game = false; } @@ -277,6 +285,9 @@ static int ask_number_players (void) break; default: + if (abort_game) + return ERR; + beep(); } } @@ -333,6 +344,9 @@ int ask_game_number (void) break; default: + if (abort_game) + return ERR; + beep(); } } @@ -348,6 +362,9 @@ int ask_game_number (void) void ask_player_names (void) { + if (abort_game) + return; + if (number_players == 1) { // Ask for the player's name @@ -362,6 +379,9 @@ void ask_player_names (void) while (true) { int ret = gettxstr(curwin, &player[0].name, NULL, false, 2, x, w, attr_input_field); + if (abort_game) + return; + if (ret == OK && strlen(player[0].name) != 0) { break; } else { @@ -371,7 +391,7 @@ void ask_player_names (void) newtxwin(5, 44, 6, WCENTER, true, attr_normal_window); mvwaddstr(curwin, 2, 2, "Do you need any instructions?"); - if (answer_yesno(curwin, attr_keycode)) { + if (answer_yesno(curwin, attr_keycode) == true) { show_help(); } @@ -432,6 +452,9 @@ void ask_player_names (void) break; case ERR: + if (abort_game) + return; + beep(); break; @@ -468,7 +491,7 @@ void ask_player_names (void) newtxwin(5, 50, 6, WCENTER, true, attr_normal_window); mvwaddstr(curwin, 2, 2, "Does any player need instructions?"); - if (answer_yesno(curwin, attr_keycode)) { + if (answer_yesno(curwin, attr_keycode) == true) { show_help(); } } @@ -487,10 +510,8 @@ void end_game (void) char *buf; - if (abort_game) { - // init_game() was cancelled by user + if (abort_game) return; - } buf = malloc(BUFSIZE); if (buf == NULL) { @@ -510,6 +531,9 @@ void end_game (void) show_status(i); } + if (abort_game) + return; + if (number_players == 1) { l_strfmon(buf, BUFSIZE, "%1n", total_value(0)); @@ -571,6 +595,9 @@ void show_map (bool closewin) int n, x, y; + if (abort_game) + return; + newtxwin(MAX_Y + 4, WIN_COLS, 1, WCENTER, true, attr_map_window); // Draw various borders @@ -670,6 +697,9 @@ void show_status (int num) int i, line; + if (abort_game) + return; + assert(num >= 0 && num < number_players); newtxwin(MAX_COMPANIES + 15, WIN_COLS, 1, WCENTER, true, diff --git a/src/globals.c b/src/globals.c index 3deab67..af8e74e 100644 --- a/src/globals.c +++ b/src/globals.c @@ -84,12 +84,13 @@ bool game_loaded = false; // True if game was loaded from disk int game_num = 0; // Game number (1-9) bool quit_selected = false; // Is a player trying to quit the game? -bool abort_game = false; // Abort game without declaring winner? bool option_no_color = false; // True if --no-color was specified bool option_dont_encrypt = false; // True if --dont-encrypt was specified int option_max_turn = 0; // Max. turns if --max-turn was specified +volatile sig_atomic_t abort_game = false; // Abort game as quickly as possible? + /***********************************************************************/ // End of file diff --git a/src/globals.h b/src/globals.h index db19be3..135a717 100644 --- a/src/globals.h +++ b/src/globals.h @@ -33,6 +33,7 @@ #include +#include /************************************************************************ @@ -195,11 +196,12 @@ extern bool game_loaded; // True if game was loaded from disk extern int game_num; // Game number (1-9) extern bool quit_selected; // Is a player trying to quit the game? -extern bool abort_game; // Abort game without declaring winner? extern bool option_no_color; // True if --no-color was specified extern bool option_dont_encrypt; // True if --dont-encrypt was specified extern int option_max_turn; // Max. turns if --max-turn was specified +extern volatile sig_atomic_t abort_game; // Abort game as quickly as possible? + #endif /* included_GLOBALS_H */ diff --git a/src/help.c b/src/help.c index 4f9a520..938848c 100644 --- a/src/help.c +++ b/src/help.c @@ -162,6 +162,9 @@ void show_help (void) bool done = false; + if (abort_game) + return; + // Count how many pages appear in the help text for (numpages = 0; help_text[numpages] != NULL; numpages++) ; @@ -356,6 +359,9 @@ void show_help (void) break; default: + if (abort_game) + return; + curpage++; done = (curpage == numpages); } diff --git a/src/intf.c b/src/intf.c index 6214570..0ef038b 100644 --- a/src/intf.c +++ b/src/intf.c @@ -101,6 +101,7 @@ txwin_t *firstwin = NULL; // First (bottom-most) txwin structure Parameters: dest - Destination buffer of size BUFSIZE src - Source buffer of size BUFSIZE isfloat - True if src contains a floating point number + Returns: (nothing) This helper function copies the string in src to dest, performing certain fixups along the way. In particular, thousands separators are @@ -114,6 +115,17 @@ static void txinput_fixup (char *restrict dest, char *restrict src, bool isfloat); +/* + Function: sigterm_handler - Handle program termination signals + Parameters: sig - Signal number + Returns: (nothing) + + This function handles termination signals (like SIGINT and SIGTERM) by + setting the global variable abort_game to true. +*/ +static void sigterm_handler (int sig); + + /************************************************************************ * Basic text input/output function definitions * ************************************************************************/ @@ -126,6 +138,22 @@ static void txinput_fixup (char *restrict dest, char *restrict src, void init_screen (void) { + struct sigaction sa; + + + // Initialise signal handlers + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sa.sa_handler = sigterm_handler; + + if (sigaction(SIGINT, &sa, NULL) == -1) { + errno_exit("sigaction(SIGINT)"); + } + if (sigaction(SIGTERM, &sa, NULL) == -1) { + errno_exit("sigaction(SIGTERM)"); + } + + // Initialise the screen initscr(); if (COLS < MIN_COLS || LINES < MIN_LINES) { @@ -259,6 +287,21 @@ void end_screen (void) } +/***********************************************************************/ +// sigterm_handler: Handle program termination signals + +void sigterm_handler (int sig) +{ + /* Note that sigterm_handler() simply sets a volatile variable + instead of directly terminating, as functions like endwin() and + end_screen() are NOT reentrant. A side-effect of doing this, + however, is that the main program needs to have abort_game checks + scattered all over it. */ + + abort_game = true; +} + + /***********************************************************************/ // newtxwin: Create a new window, inserted into window stack @@ -642,8 +685,10 @@ int gettxline (WINDOW *win, char *buf, int bufsize, bool *restrict modified, key = wgetch(win); if (key == ERR) { - // Do nothing on ERR - ; + if (abort_game) { + ret = ERR; + done = true; + } } else if ((key == KEY_DEFAULTVAL1 || key == KEY_DEFAULTVAL2) && defaultval != NULL && len == 0) { // Initialise buffer with the default value @@ -1447,7 +1492,7 @@ int gettxlong (WINDOW *win, long int *restrict result, long int min, /***********************************************************************/ // answer_yesno: Wait for a Yes/No answer -bool answer_yesno (WINDOW *win, chtype attr_keys) +int answer_yesno (WINDOW *win, chtype attr_keys) { int key; bool done; @@ -1474,6 +1519,8 @@ bool answer_yesno (WINDOW *win, chtype attr_keys) if (key == 'Y' || key == 'N') { done = true; + } else if (abort_game) { + return ERR; } else { beep(); } diff --git a/src/intf.h b/src/intf.h index 6301c2a..2887925 100644 --- a/src/intf.h +++ b/src/intf.h @@ -534,16 +534,17 @@ extern int gettxlong (WINDOW *win, long int *restrict result, long int min, Function: answer_yesno - Wait for a Yes/No answer Parameters: win - Window to use (should be curwin) attr_keys - Window rendition to use for key choices - Returns: bool - True if Yes was selected, false if No + Returns: int - 1 if Yes was selected, 0 if No, ERR if error This function prompts the user by printing " [Y/N] " using appropriate character renditions ("Y" and "N" in attr_keys, the rest in the current rendition), then waits for the user to press either "Y" (for Yes) or - "N" (for No) on the keyboard, then prints the answer using A_BOLD. - True is returned if "Y" was selected, false if "N". Note that the - cursor becomes invisible after calling this function. + "N" (for No) on the keyboard, then prints the answer using A_BOLD. If + "Y" was selected, 1 is returned, if "N", 0 is returned. ERR is + returned if abort_game becomes true. Note that the cursor becomes + invisible after calling this function. */ -extern bool answer_yesno (WINDOW *win, chtype attr_keys); +extern int answer_yesno (WINDOW *win, chtype attr_keys); /* diff --git a/src/move.c b/src/move.c index 3db159b..8d41845 100644 --- a/src/move.c +++ b/src/move.c @@ -159,6 +159,9 @@ void select_moves (void) bool unique; + if (abort_game) + return; + // How many empty spaces are there in the galaxy map? count = 0; for (x = 0; x < MAX_X; x++) { @@ -318,6 +321,9 @@ selection_t get_move (void) break; default: + if (abort_game) + return SEL_QUIT; + beep(); } } @@ -335,10 +341,13 @@ selection_t get_move (void) // Ask the player to confirm their choice mvwaddstr(curwin, 2, 22, "Are you sure?"); - if (! answer_yesno(curwin, attr_keycode)) { + if (answer_yesno(curwin, attr_keycode) != true) { selection = SEL_NONE; } + if (abort_game) + return SEL_QUIT; + // Save the game if required if (selection == SEL_SAVE) { bool saved = false; @@ -397,6 +406,9 @@ selection_t get_move (void) break; default: + if (abort_game) + return SEL_QUIT; + beep(); } } @@ -444,12 +456,13 @@ selection_t get_move (void) void process_move (selection_t selection) { + if (abort_game) + return; + if (selection == SEL_QUIT) { // The players want to end the game quit_selected = true; - } - if (quit_selected || abort_game) { deltxwin(); // "Select move" window deltxwin(); // Galaxy map window txrefresh(); @@ -495,6 +508,9 @@ void process_move (selection_t selection) assign_vals(x, y, left, right, up, down); } + if (abort_game) + return; + if (IS_MAP_COMPANY(left) && IS_MAP_COMPANY(up) && left != up) { galaxy_map[x][y] = left; @@ -502,6 +518,9 @@ void process_move (selection_t selection) assign_vals(x, y, left, right, up, down); } + if (abort_game) + return; + if (IS_MAP_COMPANY(left) && IS_MAP_COMPANY(down) && left != down) { galaxy_map[x][y] = left; @@ -509,6 +528,9 @@ void process_move (selection_t selection) assign_vals(x, y, left, right, up, down); } + if (abort_game) + return; + if (IS_MAP_COMPANY(right) && IS_MAP_COMPANY(up) && right != up) { galaxy_map[x][y] = right; @@ -516,6 +538,9 @@ void process_move (selection_t selection) assign_vals(x, y, left, right, up, down); } + if (abort_game) + return; + if (IS_MAP_COMPANY(right) && IS_MAP_COMPANY(down) && right != down) { galaxy_map[x][y] = right; @@ -523,6 +548,9 @@ void process_move (selection_t selection) assign_vals(x, y, left, right, up, down); } + if (abort_game) + return; + if (IS_MAP_COMPANY(up) && IS_MAP_COMPANY(down) && up != down) { galaxy_map[x][y] = up; @@ -531,6 +559,9 @@ void process_move (selection_t selection) } } + if (abort_game) + return; + // See if an existing company can be expanded nearby = (IS_MAP_COMPANY(left) ? left : (IS_MAP_COMPANY(right) ? right : @@ -596,6 +627,9 @@ void next_player (void) bool all_out; + if (abort_game) + return; + all_out = true; for (i = 0; i < number_players; i++) { if (player[i].in_game) { @@ -636,6 +670,9 @@ void bankrupt_player (bool forced) int i; + if (abort_game) + return; + /* It would be nice if we had functions that would do word-wrapping for us automatically! */ @@ -790,6 +827,9 @@ void merge_companies (map_val_t a, map_val_t b) char *buf; + if (abort_game) + return; + buf = malloc(BUFSIZE); if (buf == NULL) { err_exit_nomem(); @@ -952,6 +992,9 @@ void adjust_values (void) int which; + if (abort_game) + return; + // Declare a company bankrupt! if (randf() > (1.0 - COMPANY_BANKRUPTCY)) { which = randi(MAX_COMPANIES); @@ -1085,6 +1128,9 @@ void adjust_values (void) interest_rate /= randf() + INTEREST_RATE_DIVIDER; } + if (abort_game) + return; + // Calculate current player's debt player[current_player].debt *= interest_rate + 1.0; diff --git a/src/system.h b/src/system.h index 6b03183..1e6fb58 100644 --- a/src/system.h +++ b/src/system.h @@ -64,6 +64,7 @@ // Headers defined by X/Open Single Unix Specification v4 #include +#include #include #include #include diff --git a/src/trader.c b/src/trader.c index b47dda6..8ccc6e8 100644 --- a/src/trader.c +++ b/src/trader.c @@ -180,7 +180,7 @@ int main (int argc, char *argv[]) // Finish up... end_program(); - return EXIT_SUCCESS; + return abort_game ? EXIT_FAILURE : EXIT_SUCCESS; } From 4d133cf6629f3dcc4ba9aa81fa3a09a6f546feb5 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Tue, 9 Aug 2011 12:27:56 +1000 Subject: [PATCH 015/112] Rework the definition of USE_UTF8_GAME_FILE a little --- src/system.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/system.h b/src/system.h index 1e6fb58..7ea4458 100644 --- a/src/system.h +++ b/src/system.h @@ -86,10 +86,11 @@ // Character set conversion for game files -#undef USE_UTF8_GAME_FILE #ifdef HAVE_ICONV # define USE_UTF8_GAME_FILE 1 # include "striconv.h" +#else +# undef USE_UTF8_GAME_FILE #endif From 8a2bc51f28c38db511fad5c41d267ab5cf28f9eb Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Tue, 9 Aug 2011 13:06:21 +1000 Subject: [PATCH 016/112] Rearrange function prototypes to match the order in the source file --- src/intf.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/intf.c b/src/intf.c index 0ef038b..a1ccad7 100644 --- a/src/intf.c +++ b/src/intf.c @@ -96,6 +96,17 @@ txwin_t *firstwin = NULL; // First (bottom-most) txwin structure * Module-specific function prototypes * ************************************************************************/ +/* + Function: sigterm_handler - Handle program termination signals + Parameters: sig - Signal number + Returns: (nothing) + + This function handles termination signals (like SIGINT and SIGTERM) by + setting the global variable abort_game to true. +*/ +static void sigterm_handler (int sig); + + /* Function: txinput_fixup - Copy strings with fixup Parameters: dest - Destination buffer of size BUFSIZE @@ -115,17 +126,6 @@ static void txinput_fixup (char *restrict dest, char *restrict src, bool isfloat); -/* - Function: sigterm_handler - Handle program termination signals - Parameters: sig - Signal number - Returns: (nothing) - - This function handles termination signals (like SIGINT and SIGTERM) by - setting the global variable abort_game to true. -*/ -static void sigterm_handler (int sig); - - /************************************************************************ * Basic text input/output function definitions * ************************************************************************/ From 5f995f1d3631f7ac9f2bc011db94a2c70067491d Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Tue, 9 Aug 2011 13:11:22 +1000 Subject: [PATCH 017/112] Move the initialisation of the game title into its own function --- src/intf.c | 44 ++++++++++++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/src/intf.c b/src/intf.c index a1ccad7..a486ab5 100644 --- a/src/intf.c +++ b/src/intf.c @@ -96,6 +96,17 @@ txwin_t *firstwin = NULL; // First (bottom-most) txwin structure * Module-specific function prototypes * ************************************************************************/ +/* + Function: init_title - Draw the main window title + Parameters: (none) + Returns: (nothing) + + This function draws the main window game title, "Star Traders", and + clears the rest of the screen. +*/ +static void init_title (void); + + /* Function: sigterm_handler - Handle program termination signals Parameters: sig - Signal number @@ -254,18 +265,7 @@ void init_screen (void) attr_error_waitforkey = A_REVERSE; } - bkgd(attr_root_window); - clear(); - - move(0, 0); - for (int i = 0; i < COLS; i++) { - addch(attr_game_title | ' '); - } - - center(stdscr, 0, attr_game_title, "Star Traders"); - - attrset(attr_root_window); - refresh(); + init_title(); } @@ -287,6 +287,26 @@ void end_screen (void) } +/***********************************************************************/ +// init_title: Draw the main window title + +void init_title (void) +{ + bkgd(attr_root_window); + clear(); + + move(0, 0); + for (int i = 0; i < COLS; i++) { + addch(attr_game_title | ' '); + } + + center(stdscr, 0, attr_game_title, "Star Traders"); + + attrset(attr_root_window); + refresh(); +} + + /***********************************************************************/ // sigterm_handler: Handle program termination signals From 040e1a5ad6e31a4064f81fdd297f3ec894d16ea6 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Tue, 9 Aug 2011 23:20:56 +1000 Subject: [PATCH 018/112] Rework the signal handler Rework the signal handler to be somewhat more unsafe, but conceptually cleaner, in operation. It now ends the use of Curses, then reraises the signal. Remove almost all references to abort_game. --- src/exch.c | 15 --------------- src/game.c | 42 ++++++----------------------------------- src/globals.c | 3 +-- src/globals.h | 4 +--- src/help.c | 6 ------ src/intf.c | 43 +++++++++++++++++++++++++++--------------- src/intf.h | 11 +++++------ src/move.c | 52 +++------------------------------------------------ src/trader.c | 2 +- 9 files changed, 45 insertions(+), 133 deletions(-) diff --git a/src/exch.c b/src/exch.c index d426608..9535ff5 100644 --- a/src/exch.c +++ b/src/exch.c @@ -211,9 +211,6 @@ void exchange_stock (void) break; default: - if (abort_game) - return; - beep(); } } @@ -259,9 +256,6 @@ void visit_bank (void) char *buf; - if (abort_game) - return; - buf = malloc(BUFSIZE); if (buf == NULL) { err_exit_nomem(); @@ -334,9 +328,6 @@ void visit_bank (void) break; default: - if (abort_game) - return; - beep(); } } @@ -491,9 +482,6 @@ void trade_shares (int num, bool *bid_used) char *buf; - if (abort_game) - return; - assert(num >= 0 && num < MAX_COMPANIES); assert(company[num].on_map); @@ -593,9 +581,6 @@ void trade_shares (int num, bool *bid_used) break; default: - if (abort_game) - return; - beep(); } } diff --git a/src/game.c b/src/game.c index 18a6837..3e13573 100644 --- a/src/game.c +++ b/src/game.c @@ -126,9 +126,6 @@ void init_game (void) while (number_players == 0) { int choice = ask_number_players(); - if (abort_game) - return; - if (choice == ERR) { abort_game = true; return; @@ -136,9 +133,6 @@ void init_game (void) } else if (choice == 0) { choice = ask_game_number(); - if (abort_game) - return; - if (choice != ERR) { game_num = choice; @@ -168,9 +162,6 @@ void init_game (void) ask_player_names(); - if (abort_game) - return; - deltxwin(); // "Number of players" window txrefresh(); @@ -230,6 +221,7 @@ void init_game (void) } quit_selected = false; + abort_game = false; } @@ -285,9 +277,6 @@ static int ask_number_players (void) break; default: - if (abort_game) - return ERR; - beep(); } } @@ -344,9 +333,6 @@ int ask_game_number (void) break; default: - if (abort_game) - return ERR; - beep(); } } @@ -362,9 +348,6 @@ int ask_game_number (void) void ask_player_names (void) { - if (abort_game) - return; - if (number_players == 1) { // Ask for the player's name @@ -379,9 +362,6 @@ void ask_player_names (void) while (true) { int ret = gettxstr(curwin, &player[0].name, NULL, false, 2, x, w, attr_input_field); - if (abort_game) - return; - if (ret == OK && strlen(player[0].name) != 0) { break; } else { @@ -391,7 +371,7 @@ void ask_player_names (void) newtxwin(5, 44, 6, WCENTER, true, attr_normal_window); mvwaddstr(curwin, 2, 2, "Do you need any instructions?"); - if (answer_yesno(curwin, attr_keycode) == true) { + if (answer_yesno(curwin, attr_keycode)) { show_help(); } @@ -452,9 +432,6 @@ void ask_player_names (void) break; case ERR: - if (abort_game) - return; - beep(); break; @@ -491,7 +468,7 @@ void ask_player_names (void) newtxwin(5, 50, 6, WCENTER, true, attr_normal_window); mvwaddstr(curwin, 2, 2, "Does any player need instructions?"); - if (answer_yesno(curwin, attr_keycode) == true) { + if (answer_yesno(curwin, attr_keycode)) { show_help(); } } @@ -510,8 +487,10 @@ void end_game (void) char *buf; - if (abort_game) + if (abort_game) { + // init_game() was cancelled by user return; + } buf = malloc(BUFSIZE); if (buf == NULL) { @@ -531,9 +510,6 @@ void end_game (void) show_status(i); } - if (abort_game) - return; - if (number_players == 1) { l_strfmon(buf, BUFSIZE, "%1n", total_value(0)); @@ -595,9 +571,6 @@ void show_map (bool closewin) int n, x, y; - if (abort_game) - return; - newtxwin(MAX_Y + 4, WIN_COLS, 1, WCENTER, true, attr_map_window); // Draw various borders @@ -697,9 +670,6 @@ void show_status (int num) int i, line; - if (abort_game) - return; - assert(num >= 0 && num < number_players); newtxwin(MAX_COMPANIES + 15, WIN_COLS, 1, WCENTER, true, diff --git a/src/globals.c b/src/globals.c index af8e74e..3deab67 100644 --- a/src/globals.c +++ b/src/globals.c @@ -84,13 +84,12 @@ bool game_loaded = false; // True if game was loaded from disk int game_num = 0; // Game number (1-9) bool quit_selected = false; // Is a player trying to quit the game? +bool abort_game = false; // Abort game without declaring winner? bool option_no_color = false; // True if --no-color was specified bool option_dont_encrypt = false; // True if --dont-encrypt was specified int option_max_turn = 0; // Max. turns if --max-turn was specified -volatile sig_atomic_t abort_game = false; // Abort game as quickly as possible? - /***********************************************************************/ // End of file diff --git a/src/globals.h b/src/globals.h index 135a717..db19be3 100644 --- a/src/globals.h +++ b/src/globals.h @@ -33,7 +33,6 @@ #include -#include /************************************************************************ @@ -196,12 +195,11 @@ extern bool game_loaded; // True if game was loaded from disk extern int game_num; // Game number (1-9) extern bool quit_selected; // Is a player trying to quit the game? +extern bool abort_game; // Abort game without declaring winner? extern bool option_no_color; // True if --no-color was specified extern bool option_dont_encrypt; // True if --dont-encrypt was specified extern int option_max_turn; // Max. turns if --max-turn was specified -extern volatile sig_atomic_t abort_game; // Abort game as quickly as possible? - #endif /* included_GLOBALS_H */ diff --git a/src/help.c b/src/help.c index 938848c..4f9a520 100644 --- a/src/help.c +++ b/src/help.c @@ -162,9 +162,6 @@ void show_help (void) bool done = false; - if (abort_game) - return; - // Count how many pages appear in the help text for (numpages = 0; help_text[numpages] != NULL; numpages++) ; @@ -359,9 +356,6 @@ void show_help (void) break; default: - if (abort_game) - return; - curpage++; done = (curpage == numpages); } diff --git a/src/intf.c b/src/intf.c index a486ab5..461587c 100644 --- a/src/intf.c +++ b/src/intf.c @@ -112,8 +112,9 @@ static void init_title (void); Parameters: sig - Signal number Returns: (nothing) - This function handles termination signals (like SIGINT and SIGTERM) by - setting the global variable abort_game to true. + This function handles termination signals (like SIGINT, SIGTERM and + SIGQUIT) by clearing the screen, uninstalling itself and reraising the + signal. */ static void sigterm_handler (int sig); @@ -163,6 +164,9 @@ void init_screen (void) if (sigaction(SIGTERM, &sa, NULL) == -1) { errno_exit("sigaction(SIGTERM)"); } + if (sigaction(SIGQUIT, &sa, NULL) == -1) { + errno_exit("sigaction(SIGQUIT)"); + } // Initialise the screen initscr(); @@ -312,13 +316,26 @@ void init_title (void) void sigterm_handler (int sig) { - /* Note that sigterm_handler() simply sets a volatile variable - instead of directly terminating, as functions like endwin() and - end_screen() are NOT reentrant. A side-effect of doing this, - however, is that the main program needs to have abort_game checks - scattered all over it. */ + struct sigaction sa; - abort_game = true; + + /* The following Curses functions are NOT async-signal-safe (ie, are + not reentrant) as they may well call malloc() or free(). However, + it does allow us to terminate with the correct signal without + having convoluted code in the main program. */ + + curs_set(CURS_ON); + clear(); + refresh(); + endwin(); + + // Reraise the same signal, using the system-default handler + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sa.sa_handler = SIG_DFL; + + sigaction(sig, &sa, NULL); + raise(sig); } @@ -705,10 +722,8 @@ int gettxline (WINDOW *win, char *buf, int bufsize, bool *restrict modified, key = wgetch(win); if (key == ERR) { - if (abort_game) { - ret = ERR; - done = true; - } + // Do nothing on ERR + ; } else if ((key == KEY_DEFAULTVAL1 || key == KEY_DEFAULTVAL2) && defaultval != NULL && len == 0) { // Initialise buffer with the default value @@ -1512,7 +1527,7 @@ int gettxlong (WINDOW *win, long int *restrict result, long int min, /***********************************************************************/ // answer_yesno: Wait for a Yes/No answer -int answer_yesno (WINDOW *win, chtype attr_keys) +bool answer_yesno (WINDOW *win, chtype attr_keys) { int key; bool done; @@ -1539,8 +1554,6 @@ int answer_yesno (WINDOW *win, chtype attr_keys) if (key == 'Y' || key == 'N') { done = true; - } else if (abort_game) { - return ERR; } else { beep(); } diff --git a/src/intf.h b/src/intf.h index 2887925..6301c2a 100644 --- a/src/intf.h +++ b/src/intf.h @@ -534,17 +534,16 @@ extern int gettxlong (WINDOW *win, long int *restrict result, long int min, Function: answer_yesno - Wait for a Yes/No answer Parameters: win - Window to use (should be curwin) attr_keys - Window rendition to use for key choices - Returns: int - 1 if Yes was selected, 0 if No, ERR if error + Returns: bool - True if Yes was selected, false if No This function prompts the user by printing " [Y/N] " using appropriate character renditions ("Y" and "N" in attr_keys, the rest in the current rendition), then waits for the user to press either "Y" (for Yes) or - "N" (for No) on the keyboard, then prints the answer using A_BOLD. If - "Y" was selected, 1 is returned, if "N", 0 is returned. ERR is - returned if abort_game becomes true. Note that the cursor becomes - invisible after calling this function. + "N" (for No) on the keyboard, then prints the answer using A_BOLD. + True is returned if "Y" was selected, false if "N". Note that the + cursor becomes invisible after calling this function. */ -extern int answer_yesno (WINDOW *win, chtype attr_keys); +extern bool answer_yesno (WINDOW *win, chtype attr_keys); /* diff --git a/src/move.c b/src/move.c index 8d41845..3db159b 100644 --- a/src/move.c +++ b/src/move.c @@ -159,9 +159,6 @@ void select_moves (void) bool unique; - if (abort_game) - return; - // How many empty spaces are there in the galaxy map? count = 0; for (x = 0; x < MAX_X; x++) { @@ -321,9 +318,6 @@ selection_t get_move (void) break; default: - if (abort_game) - return SEL_QUIT; - beep(); } } @@ -341,13 +335,10 @@ selection_t get_move (void) // Ask the player to confirm their choice mvwaddstr(curwin, 2, 22, "Are you sure?"); - if (answer_yesno(curwin, attr_keycode) != true) { + if (! answer_yesno(curwin, attr_keycode)) { selection = SEL_NONE; } - if (abort_game) - return SEL_QUIT; - // Save the game if required if (selection == SEL_SAVE) { bool saved = false; @@ -406,9 +397,6 @@ selection_t get_move (void) break; default: - if (abort_game) - return SEL_QUIT; - beep(); } } @@ -456,13 +444,12 @@ selection_t get_move (void) void process_move (selection_t selection) { - if (abort_game) - return; - if (selection == SEL_QUIT) { // The players want to end the game quit_selected = true; + } + if (quit_selected || abort_game) { deltxwin(); // "Select move" window deltxwin(); // Galaxy map window txrefresh(); @@ -508,9 +495,6 @@ void process_move (selection_t selection) assign_vals(x, y, left, right, up, down); } - if (abort_game) - return; - if (IS_MAP_COMPANY(left) && IS_MAP_COMPANY(up) && left != up) { galaxy_map[x][y] = left; @@ -518,9 +502,6 @@ void process_move (selection_t selection) assign_vals(x, y, left, right, up, down); } - if (abort_game) - return; - if (IS_MAP_COMPANY(left) && IS_MAP_COMPANY(down) && left != down) { galaxy_map[x][y] = left; @@ -528,9 +509,6 @@ void process_move (selection_t selection) assign_vals(x, y, left, right, up, down); } - if (abort_game) - return; - if (IS_MAP_COMPANY(right) && IS_MAP_COMPANY(up) && right != up) { galaxy_map[x][y] = right; @@ -538,9 +516,6 @@ void process_move (selection_t selection) assign_vals(x, y, left, right, up, down); } - if (abort_game) - return; - if (IS_MAP_COMPANY(right) && IS_MAP_COMPANY(down) && right != down) { galaxy_map[x][y] = right; @@ -548,9 +523,6 @@ void process_move (selection_t selection) assign_vals(x, y, left, right, up, down); } - if (abort_game) - return; - if (IS_MAP_COMPANY(up) && IS_MAP_COMPANY(down) && up != down) { galaxy_map[x][y] = up; @@ -559,9 +531,6 @@ void process_move (selection_t selection) } } - if (abort_game) - return; - // See if an existing company can be expanded nearby = (IS_MAP_COMPANY(left) ? left : (IS_MAP_COMPANY(right) ? right : @@ -627,9 +596,6 @@ void next_player (void) bool all_out; - if (abort_game) - return; - all_out = true; for (i = 0; i < number_players; i++) { if (player[i].in_game) { @@ -670,9 +636,6 @@ void bankrupt_player (bool forced) int i; - if (abort_game) - return; - /* It would be nice if we had functions that would do word-wrapping for us automatically! */ @@ -827,9 +790,6 @@ void merge_companies (map_val_t a, map_val_t b) char *buf; - if (abort_game) - return; - buf = malloc(BUFSIZE); if (buf == NULL) { err_exit_nomem(); @@ -992,9 +952,6 @@ void adjust_values (void) int which; - if (abort_game) - return; - // Declare a company bankrupt! if (randf() > (1.0 - COMPANY_BANKRUPTCY)) { which = randi(MAX_COMPANIES); @@ -1128,9 +1085,6 @@ void adjust_values (void) interest_rate /= randf() + INTEREST_RATE_DIVIDER; } - if (abort_game) - return; - // Calculate current player's debt player[current_player].debt *= interest_rate + 1.0; diff --git a/src/trader.c b/src/trader.c index 8ccc6e8..b47dda6 100644 --- a/src/trader.c +++ b/src/trader.c @@ -180,7 +180,7 @@ int main (int argc, char *argv[]) // Finish up... end_program(); - return abort_game ? EXIT_FAILURE : EXIT_SUCCESS; + return EXIT_SUCCESS; } From 738ffcd69a7950105dec6f80250842db56d266f7 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Wed, 10 Aug 2011 00:30:38 +1000 Subject: [PATCH 019/112] Block SIGINT, SIGTERM and SIGQUIT when in the signal handler --- src/intf.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/intf.c b/src/intf.c index 461587c..45ad32a 100644 --- a/src/intf.c +++ b/src/intf.c @@ -154,9 +154,12 @@ void init_screen (void) // Initialise signal handlers - sigemptyset(&sa.sa_mask); - sa.sa_flags = 0; sa.sa_handler = sigterm_handler; + sa.sa_flags = 0; + sigemptyset(&sa.sa_mask); + sigaddset(&sa.sa_mask, SIGINT); + sigaddset(&sa.sa_mask, SIGTERM); + sigaddset(&sa.sa_mask, SIGQUIT); if (sigaction(SIGINT, &sa, NULL) == -1) { errno_exit("sigaction(SIGINT)"); @@ -330,9 +333,9 @@ void sigterm_handler (int sig) endwin(); // Reraise the same signal, using the system-default handler - sigemptyset(&sa.sa_mask); - sa.sa_flags = 0; sa.sa_handler = SIG_DFL; + sa.sa_flags = 0; + sigemptyset(&sa.sa_mask); sigaction(sig, &sa, NULL); raise(sig); From 39844688945ac06f0dad1024b5925bfc3bfe8507 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Wed, 10 Aug 2011 01:27:11 +1000 Subject: [PATCH 020/112] Handle KEY_RESIZE events (where defined) in a simple manner Unfortunately, the implementation of Curses (even Ncurses) requires that to truely handle resizing, one must destroy and recreate every window (and, of course, repaint it)--a lot of work that is not done at this time. --- src/intf.c | 112 +++++++++++++++++++++++++++++++++++++++++++++++------ src/intf.h | 30 ++++++-------- 2 files changed, 113 insertions(+), 29 deletions(-) diff --git a/src/intf.c b/src/intf.c index 45ad32a..38d8248 100644 --- a/src/intf.c +++ b/src/intf.c @@ -119,6 +119,19 @@ static void init_title (void); static void sigterm_handler (int sig); +/* + Function: txresize - Handle a terminal resize event + Parameters: (none) + Returns: (nothing) + + This function handles a SIGWINCH (terminal window size changed) event + by refreshing Curses windows as appropriate. +*/ +#ifdef HANDLE_RESIZE_EVENTS +static void txresize (void); +#endif + + /* Function: txinput_fixup - Copy strings with fixup Parameters: dest - Destination buffer of size BUFSIZE @@ -464,6 +477,26 @@ int txrefresh (void) } +/***********************************************************************/ +// txresize: Handle a terminal resize event + +#ifdef HANDLE_RESIZE_EVENTS + +void txresize (void) +{ + /* The current implementation cannot resize windows per se: a given + window would have to be destroyed and recreated in the new + location, then redrawn, most likely via a call-back function. + We just redraw the game title, refresh all windows and hope for + the best! */ + + init_title(); + txrefresh(); +} + +#endif // HANDLE_RESIZE_EVENTS + + /***********************************************************************/ // attrpr: Print a string with a particular character rendition @@ -654,11 +687,34 @@ int center3 (WINDOW *win, int y, chtype attr1, chtype attr3, chtype attr2, int gettxchar (WINDOW *win) { + int key; + bool done; + + keypad(win, true); meta(win, true); wtimeout(win, -1); - return wgetch(win); + done = false; + while (! done) { + key = wgetch(win); + switch (key) { + case ERR: + beep(); + break; + +#ifdef HANDLE_RESIZE_EVENTS + case KEY_RESIZE: + txresize(); + break; +#endif // HANDLE_RESIZE_EVENTS + + default: + done = true; + } + } + + return key; } @@ -1265,11 +1321,11 @@ int gettxline (WINDOW *win, char *buf, int bufsize, bool *restrict modified, // Miscellaneous keys and events +#ifdef HANDLE_RESIZE_EVENTS case KEY_RESIZE: - case KEY_EVENT: - ret = key; - done = true; + txresize(); break; +#endif // HANDLE_RESIZE_EVENTS default: beep(); @@ -1279,11 +1335,11 @@ int gettxline (WINDOW *win, char *buf, int bufsize, bool *restrict modified, wtimeout(win, -1); break; +#ifdef HANDLE_RESIZE_EVENTS case KEY_RESIZE: - case KEY_EVENT: - ret = key; - done = true; + txresize(); break; +#endif // HANDLE_RESIZE_EVENTS default: beep(); @@ -1553,11 +1609,24 @@ bool answer_yesno (WINDOW *win, chtype attr_keys) done = false; while (! done) { - key = toupper(wgetch(win)); + key = wgetch(win); - if (key == 'Y' || key == 'N') { + switch (key) { + case 'Y': + case 'y': + case 'N': + case 'n': + key = toupper(key); done = true; - } else { + break; + +#ifdef HANDLE_RESIZE_EVENTS + case KEY_RESIZE: + txresize(); + break; +#endif // HANDLE_RESIZE_EVENTS + + default: beep(); } } @@ -1584,6 +1653,10 @@ bool answer_yesno (WINDOW *win, chtype attr_keys) void wait_for_key (WINDOW *win, int y, chtype attr) { + int key; + bool done; + + keypad(win, true); meta(win, true); wtimeout(win, -1); @@ -1591,7 +1664,24 @@ void wait_for_key (WINDOW *win, int y, chtype attr) center(win, y, attr, "[ Press to continue ] "); wrefresh(win); - (void) wgetch(win); + done = false; + while (! done) { + key = wgetch(win); + switch (key) { + case ERR: + beep(); + break; + +#ifdef HANDLE_RESIZE_EVENTS + case KEY_RESIZE: + txresize(); + break; +#endif // HANDLE_RESIZE_EVENTS + + default: + done = true; + } + } } diff --git a/src/intf.h b/src/intf.h index 6301c2a..e60957e 100644 --- a/src/intf.h +++ b/src/intf.h @@ -43,20 +43,27 @@ /* This version of Star Traders only utilises WIN_COLS x WIN_LINES of a terminal screen; this terminal must be at least MIN_COLS x MIN_LINES in - size; the newtxwin() function automatically places a new window in the - centre-top of the terminal screen. The program does not yet handle - terminal resizing events. + size. The newtxwin() function automatically places a new window in the + centre-top of the terminal screen. */ #define MIN_LINES 24 // Minimum number of lines in terminal #define MIN_COLS 80 // Minimum number of columns in terminal -#define WIN_LINES MIN_LINES // Number of lines in main window -#define WIN_COLS MIN_COLS // Number of columns in main window +#define WIN_LINES MIN_LINES // Number of lines used in main window +#define WIN_COLS MIN_COLS // Number of columns used in main window #define WCENTER -1 // Centre the new window +// Check if resizing events are supported +#ifdef KEY_RESIZE +# define HANDLE_RESIZE_EVENTS 1 +#else +# undef HANDLE_RESIZE_EVENTS +#endif + + // Visibility of the cursor in Curses (for curs_set()) typedef enum curs_type { CURS_INVISIBLE = 0, @@ -77,8 +84,6 @@ typedef enum curs_type { #define KEY_CTRL(x) ((x) - 0100) // ASCII control character -#define KEY_ILLEGAL 077777 // No key should ever return this! - // Keycodes for inserting the default value in input routines #define KEY_DEFAULTVAL1 '=' #define KEY_DEFAULTVAL2 ';' @@ -91,17 +96,6 @@ typedef enum curs_type { # define KEY_CRIGHT 01052 // CTRL + Right Arrow #endif -// Keycodes only defined by NCurses -#ifndef KEY_RESIZE -# define KEY_RESIZE KEY_ILLEGAL -#endif -#ifndef KEY_EVENT -# define KEY_EVENT KEY_ILLEGAL -#endif -#ifndef KEY_MOUSE -# define KEY_MOUSE KEY_ILLEGAL -#endif - // Timeout value (in ms) for Meta-X-style keyboard input #ifdef NCURSES_VERSION # define META_TIMEOUT ESCDELAY From 2612eddf3dae6248a65535cbe7f4bc6f088a64a5 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Fri, 12 Aug 2011 14:28:15 +1000 Subject: [PATCH 021/112] Add functions prepstr(), pr_left(), pr_center() and pr_right() These functions allow multiple lines to be printed left-aligned, centered or right-aligned, with automatic line-wrapping where needed. --- src/intf.c | 697 ++++++++++++++++++++++++++++++++++++++++++++++++++++- src/intf.h | 126 ++++++++++ 2 files changed, 822 insertions(+), 1 deletion(-) diff --git a/src/intf.c b/src/intf.c index 38d8248..ade44c7 100644 --- a/src/intf.c +++ b/src/intf.c @@ -42,6 +42,29 @@ typedef struct txwin { } txwin_t; +// Declarations for argument processing in prepstr() + +#define MAXFMTARGS 8 // Maximum number of positional arguments + +enum argument_type { + TYPE_NONE, // No type yet assigned + TYPE_INT, // int + TYPE_LONGINT, // long int + TYPE_DOUBLE, // double + TYPE_STRING // const char * +}; + +struct argument { + enum argument_type a_type; + union a { + int a_int; + long int a_longint; + double a_double; + const char *a_string; + } a; +}; + + /************************************************************************ * Global variable definitions * ************************************************************************/ @@ -132,6 +155,40 @@ static void txresize (void); #endif +/* + Function: prepstr_addch - Add a character to the prepstr buffer + Parameters: chbuf - Pointer to chtype pointer in which to store string + chbufsize - Pointer to number of chtype elements in chbuf + attr - Character rendition to use + maxlines - Maximum number of screen lines to use + maxwidth - Maximum width of each line, in chars + line - Pointer to current line number + width - Pointer to current line width + lastspc - Pointer to const char * pointer to last space + widthspc - Pointer to width just before last space + widthbuf - Pointer to buffer to store widths of each line + widthbufsize - Number of int elements in widthbuf + str - Pointer to const char * pointer to string + Returns: int - -1 on error (with errno set), 0 otherwise + + This helper function adds the character **str to **chbuf, using attr as + the character rendition (attributes), incrementing both *str and *chbuf + and decrementing *chbufsize. If a string is too long for the current + line, a previous space in the current line is converted to a new line + (if possible), else a new line is inserted into the current location + (if not on the last line). *line, *width, *lastspc, *widthspc and + widthbuf[] are all updated appropriately. +*/ +static int prepstr_addch (chtype *restrict *restrict chbuf, + int *restrict chbufsize, chtype attr, + int maxlines, int maxwidth, int *restrict line, + int *restrict width, + chtype *restrict *restrict lastspc, + int *restrict widthspc, int *restrict widthbuf, + int widthbufsize, + const char *restrict *restrict str); + + /* Function: txinput_fixup - Copy strings with fixup Parameters: dest - Destination buffer of size BUFSIZE @@ -155,7 +212,8 @@ static void txinput_fixup (char *restrict dest, char *restrict src, * Basic text input/output function definitions * ************************************************************************/ -// These functions are documented in the file "intf.h" +/* These functions are documented either in the file "intf.h" or in the + comments above. */ /***********************************************************************/ @@ -497,6 +555,643 @@ void txresize (void) #endif // HANDLE_RESIZE_EVENTS +/***********************************************************************/ +// prepstr_addch: Add a character to the prepstr buffer + +int prepstr_addch (chtype *restrict *restrict chbuf, int *restrict chbufsize, + chtype attr, int maxlines, int maxwidth, + int *restrict line, int *restrict width, + chtype *restrict *restrict lastspc, int *restrict widthspc, + int *restrict widthbuf, int widthbufsize, + const char *restrict *restrict str) +{ + if (*line < 0) { + // First character in buffer: start line 0 + *line = 0; + } + + if (**str == '\n') { + // Start a new line + + if (*line < maxlines - 1) { + *(*chbuf)++ = '\n'; + (*chbufsize)--; + } + + widthbuf[*line] = *width; + *width = 0; + + *lastspc = NULL; + *widthspc = 0; + + (*line)++; + (*str)++; + } else if (*width == maxwidth) { + // Current line is now too long + + if (! isspace(**str) && *lastspc != NULL && *line < maxlines - 1) { + // Break on the last space in this line + **lastspc = '\n'; + + widthbuf[*line] = *widthspc; + *width -= *widthspc + 1; + + *lastspc = NULL; + *widthspc = 0; + + (*line)++; + } else { + // Insert a new-line character (if not on last line) + if (*line < maxlines - 1) { + *(*chbuf)++ = '\n'; + (*chbufsize)--; + } + + widthbuf[*line] = *width; + *width = 0; + + *lastspc = NULL; + *widthspc = 0; + + (*line)++; + + // Skip any following spaces + while (isspace(**str)) { + if (*(*str)++ == '\n') { + break; + } + } + } + } else { + // Insert an ordinary character into the output string + + if (isspace(**str)) { + *lastspc = *chbuf; + *widthspc = *width; + } + + *(*chbuf)++ = (unsigned char) **str | attr; + (*chbufsize)--; + (*width)++; + (*str)++; + } + + return 0; +} + + +/***********************************************************************/ +// prepstr: Prepare a string for printing to screen + +int prepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, + chtype attr_alt1, chtype attr_alt2, int maxlines, int maxwidth, + int *restrict widthbuf, int widthbufsize, + const char *restrict format, ...) +{ + struct argument format_arg[MAXFMTARGS]; + int num_format_args, arg_num; + const char *orig_format; + va_list args; + int line, width; + chtype *lastspc; + int widthspc; + chtype curattr; + int saved_errno; + + + assert(chbuf != NULL); + assert(chbufsize > 0); + assert(maxlines > 0); + assert(maxwidth > 0); + assert(widthbuf != NULL); + assert(widthbufsize >= maxlines); + assert(format != NULL); + + /* Do a preliminary scan through the format parameter to determine + the types of each positional argument (conversion specifier). If + we did not support "%m$"-style specifiers, this would not be + necessary. */ + + orig_format = format; + memset(format_arg, 0, sizeof(format_arg)); + num_format_args = 0; + arg_num = 0; + va_start(args, format); + + while (*format != '\0') { + switch (*format++) { + case '^': + // Switch to a different character rendition + if (*format == '\0') { + goto error_inval; + } else { + format++; + } + break; + + case '%': + // Process a conversion specifier + if (*format == '\0') { + goto error_inval; + } else if (*format == '%') { + format++; + } else { + enum argument_type arg_type = TYPE_NONE; + bool inspec = true; + bool flag_posn = false; + bool flag_long = false; + int count = 0; + + while (inspec && *format != '\0') { + char c = *format++; + switch (c) { + case '0': + // Zero flag, or part of numeric count + if (count == 0) + goto error_inval; + + count *= 10; + break; + + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + // Part of some numeric count + count = count * 10 + (c - '0'); + break; + + case '$': + // Fixed-position argument + if (flag_posn || count == 0) + goto error_inval; + + if (count > MAXFMTARGS) { + errno = E2BIG; + goto error; + } + + flag_posn = true; + arg_num = count - 1; + count = 0; + break; + + case '\'': + // Use locale-specific thousands separator + break; + + case 'l': + // Long length modifier + if (flag_long) + goto error_inval; + + flag_long = true; + break; + + case 'd': + // Insert an integer (int or long int) + arg_type = flag_long ? TYPE_LONGINT : TYPE_INT; + goto handlefmt; + + case 'N': + // Insert a monetary amount (double) + if (flag_long) + goto error_inval; + + arg_type = TYPE_DOUBLE; + goto handlefmt; + + case 's': + // Insert a string (const char *) + if (flag_long) + goto error_inval; + + arg_type = TYPE_STRING; + + handlefmt: + if (arg_num >= MAXFMTARGS) { + errno = E2BIG; + goto error; + } + + if (format_arg[arg_num].a_type == TYPE_NONE) { + format_arg[arg_num].a_type = arg_type; + } else if (format_arg[arg_num].a_type != arg_type) { + goto error_inval; + } + + arg_num++; + num_format_args = MAX(num_format_args, arg_num); + + inspec = false; + break; + + default: + goto error_inval; + } + } + if (inspec) + goto error_inval; + } + break; + + default: + // Process an ordinary character: do nothing for now + ; + } + } + + for (int i = 0; i < num_format_args; i++) { + switch (format_arg[i].a_type) { + case TYPE_INT: + format_arg[i].a.a_int = va_arg(args, int); + break; + + case TYPE_LONGINT: + format_arg[i].a.a_longint = va_arg(args, long int); + break; + + case TYPE_DOUBLE: + format_arg[i].a.a_double = va_arg(args, double); + break; + + case TYPE_STRING: + format_arg[i].a.a_string = va_arg(args, const char *); + break; + + default: + /* Cannot allow unused arguments, as we have no way of + knowing how much space they take (cf. int vs. long long + int). */ + goto error_inval; + } + } + + // Actually process the format parameter string + + format = orig_format; + arg_num = 0; + + curattr = attr_norm; + line = -1; // Current line number (0 = first) + width = 0; // Width of the current line + lastspc = NULL; // Pointer to last space in line + widthspc = 0; // Width of line before last space + + while (*format != '\0' && chbufsize > 1 && line < maxlines) { + switch (*format) { + case '^': + // Switch to a different character rendition + if (*++format == '\0') { + goto error_inval; + } else { + switch (*format) { + case '^': + if (prepstr_addch(&chbuf, &chbufsize, curattr, maxlines, + maxwidth, &line, &width, &lastspc, + &widthspc, widthbuf, widthbufsize, + &format) < 0) { + goto error; + } + break; + + case '{': + curattr = attr_alt1; + format++; + break; + + case '[': + curattr = attr_alt2; + format++; + break; + + case '}': + case ']': + curattr = attr_norm; + format++; + break; + + default: + goto error_inval; + } + } + break; + + case '%': + // Process a conversion specifier + if (*++format == '\0') { + goto error_inval; + } else if (*format == '%') { + if (prepstr_addch(&chbuf, &chbufsize, curattr, maxlines, + maxwidth, &line, &width, &lastspc, &widthspc, + widthbuf, widthbufsize, &format) < 0) { + goto error; + } + } else { + bool inspec = true; + bool flag_posn = false; + bool flag_long = false; + bool flag_thou = false; + int count = 0; + const char *str; + + char *buf = malloc(BUFSIZE); + if (buf == NULL) + err_exit_nomem(); + + while (inspec && *format != '\0') { + char c = *format++; + switch (c) { + case '0': + // Zero flag, or part of numeric count + if (count == 0) { + // Zero flag is not supported + free(buf); + goto error_inval; + } + + count *= 10; + break; + + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + // Part of some numeric count + count = count * 10 + (c - '0'); + break; + + case '$': + // Fixed-position argument + if (flag_posn || count == 0) { + free(buf); + goto error_inval; + } + + if (count > MAXFMTARGS) { + free(buf); + errno = E2BIG; + goto error; + } + + flag_posn = true; + arg_num = count - 1; + count = 0; + break; + + case '\'': + // Use locale-specific thousands separator + if (flag_thou) { + free(buf); + goto error_inval; + } + + flag_thou = true; + break; + + case 'l': + // Long length modifier + if (flag_long) { + free(buf); + goto error_inval; + } + + flag_long = true; + break; + + case 'd': + // Insert an integer (int or long int) into the output + if (count != 0) { + free(buf); + goto error_inval; + } + + if (arg_num >= MAXFMTARGS) { + free(buf); + errno = E2BIG; + goto error; + } + + if (flag_long) { + if (snprintf(buf, BUFSIZE, flag_thou ? "%'ld" : "%ld", + format_arg[arg_num].a.a_longint) < 0) { + saved_errno = errno; + free(buf); + errno = saved_errno; + goto error; + } + } else { + if (snprintf(buf, BUFSIZE, flag_thou ? "%'d" : "%d", + format_arg[arg_num].a.a_int) < 0) { + saved_errno = errno; + free(buf); + errno = saved_errno; + goto error; + } + } + + str = buf; + goto insertstr; + + case 'N': + // Insert a monetary amount (double) into the output + if (count != 0 || flag_thou || flag_long) { + free(buf); + goto error_inval; + } + + if (arg_num >= MAXFMTARGS) { + free(buf); + errno = E2BIG; + goto error; + } + + if (l_strfmon(buf, BUFSIZE, "%n", + format_arg[arg_num].a.a_double) < 0) { + saved_errno = errno; + free(buf); + errno = saved_errno; + goto error; + } + + str = buf; + goto insertstr; + + case 's': + // Insert a string (const char *) into the output + if (count != 0 || flag_thou || flag_long) { + free(buf); + goto error_inval; + } + + if (arg_num >= MAXFMTARGS) { + free(buf); + errno = E2BIG; + goto error; + } + + str = format_arg[arg_num].a.a_string; + + if (str == NULL) { + str = "(null)"; // As per GNU printf() + } + + insertstr: + // Insert the string pointed to by str + while (*str != '\0' && chbufsize > 1 && line < maxlines) { + if (prepstr_addch(&chbuf, &chbufsize, curattr, + maxlines, maxwidth, &line, &width, + &lastspc, &widthspc, widthbuf, + widthbufsize, &str) < 0) { + saved_errno = errno; + free(buf); + errno = saved_errno; + goto error; + } + } + + arg_num++; + inspec = false; + break; + + default: + free(buf); + goto error_inval; + } + } + free(buf); + if (inspec) + goto error_inval; + } + break; + + default: + // Process an ordinary character (including new-line) + if (prepstr_addch(&chbuf, &chbufsize, curattr, maxlines, maxwidth, + &line, &width, &lastspc, &widthspc, widthbuf, + widthbufsize, &format) < 0) { + goto error; + } + } + } + + *chbuf = 0; // Terminating NUL byte + + if (line >= 0 && line < maxlines) { + widthbuf[line] = width; + } else if (line >= maxlines) { + line = maxlines - 1; + } + + va_end(args); + return line + 1; + +error_inval: + errno = EINVAL; + +error: + va_end(args); + return -1; +} + + +/***********************************************************************/ +// pr_left: Print strings in chbuf left-aligned + +int pr_left (WINDOW *win, int y, int x, const chtype *restrict chbuf, + int lines, const int *restrict widthbuf) +{ + assert(win != NULL); + assert(chbuf != NULL); + assert(lines > 0); + assert(widthbuf != NULL); + + wmove(win, y, x); + for ( ; *chbuf != '\0'; chbuf++) { + if (*chbuf == '\n') { + wmove(win, getcury(win) + 1, x); + } else { + waddch(win, *chbuf); + } + } + + return OK; +} + + +/***********************************************************************/ +// pr_center: Print strings in chbuf centered in window + +int pr_center (WINDOW *win, int y, int offset, const chtype *restrict chbuf, + int lines, const int *restrict widthbuf) +{ + int ln = 0; + + + assert(win != NULL); + assert(chbuf != NULL); + assert(lines > 0); + assert(widthbuf != NULL); + + wmove(win, y, (getmaxx(win) - widthbuf[ln]) / 2 + offset); + for ( ; *chbuf != '\0'; chbuf++) { + if (*chbuf == '\n') { + if (ln++ >= lines) { + return ERR; + } else { + wmove(win, getcury(win) + 1, + (getmaxx(win) - widthbuf[ln]) / 2 + offset); + } + } else { + waddch(win, *chbuf); + } + } + + return OK; +} + + +/***********************************************************************/ +// pr_right: Print strings in chbuf right-aligned + +int pr_right (WINDOW *win, int y, int x, const chtype *restrict chbuf, + int lines, const int *restrict widthbuf) +{ + int ln = 0; + + + assert(win != NULL); + assert(chbuf != NULL); + assert(lines > 0); + assert(widthbuf != NULL); + + wmove(win, y, x - widthbuf[ln]); + for ( ; *chbuf != '\0'; chbuf++) { + if (*chbuf == '\n') { + if (ln++ >= lines) { + return ERR; + } else { + wmove(win, getcury(win) + 1, x - widthbuf[ln]); + } + } else { + waddch(win, *chbuf); + } + } + + return OK; +} + + /***********************************************************************/ // attrpr: Print a string with a particular character rendition diff --git a/src/intf.h b/src/intf.h index e60957e..3910c76 100644 --- a/src/intf.h +++ b/src/intf.h @@ -254,6 +254,132 @@ extern int delalltxwin (void); extern int txrefresh (void); +/* + Function: prepstr - Prepare a string for printing to screen + Parameters: chbuf - Pointer to chtype buffer in which to store string + chbufsize - Number of chtype elements in chbuf + attr_norm - Normal character rendition to use + attr_alt1 - First alternate character rendition to use + attr_alt2 - Second alternate character rendition to use + maxlines - Maximum number of screen lines to use + maxwidth - Maximum width of each line, in chars + widthbuf - Pointer to buffer to store widths of each line + widthbufsize - Number of int elements in widthbuf + format - Format string as described below + ... - Arguments for the format string + Returns: int - Number of lines actually used, or -1 on error + + This function converts the format string and following arguments into + chbuf, a chtype buffer that can be used for calls to pr_left(), + pr_center() and pr_right(). At most maxlines lines are used, each with + a maximum width of maxwidth. The actual widths of each resulting line + are stored in widthbuf (which must not be NULL). If maxlines is + greater than 1, lines are wrapped as needed. + + The format string is similar to but more limited than printf(). In + particular, the following conversion specifiers are understood: + + %% - Print the ASCII percent sign (ASCII code U+0025) + + %s - Insert the next parameter as a string + %d - Insert the next parameter as an integer (type int) + %'d - Insert as an int, using the locale's thousands separator + %ld - Insert the next parameter as a long int + %'ld - Insert as a long int, using the locale's thousands separator + %N - Insert the next parameter as a double, using the locale's + national currency format (extension to printf()) + + Instead of using "%" to convert the next parameter, "%m$" can be used + to indicate fixed parameter m (where m is an integer from 1 to 8). For + example, "%4$s" inserts the fourth parameter after "format" as a string + into chbuf. As with printf(), using "%m$" together with ordinary "%" + forms is undefined. If "%m$" is used, no parameter m can be skipped. + + Note that no other flag, field width, precision or length modifier + characters are recognised: if needed, these should be formatted FIRST + with snprintf(), then inserted using %s as appropriate. + + In addition to the conversion specifiers, the following character + rendition flags are understood, where the "^" character is a literal + ASCII circumflex accent: + + ^^ - Print the circumflex accent (ASCII code U+005E) + ^{ - Switch to using attr_alt1 character rendition (alternate mode 1) + ^} - Switch to using attr_norm character rendition + ^[ - Switch to using attr_alt2 character rendition (alternate mode 2) + ^] - Switch to using attr_norm character rendition + + Characters other than these are inserted as literals, except that '\n' + will force the start of a new line. By default, attr_norm is used as + the character rendition (attributes). + + This function returns the actual number of lines used (from 0 to + maxlines), or -1 on error (with errno set to EINVAL for an invalid + format conversion specifier or argument). +*/ +extern int prepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, + chtype attr_alt1, chtype attr_alt2, int maxlines, + int maxwidth, int *restrict widthbuf, int widthbufsize, + const char *restrict format, ...); + + +/* + Function: pr_left - Print strings in chbuf left-aligned + Parameters: win - Window to use (should be curwin) + y - Line on which to print first string + x - Starting column number for each line + chbuf - chtype buffer as returned from prepstr() + lines - Number of lines in chbuf (as returned from prepstr()) + widthbuf - Widths of each line (as returned from prepstr()) + Returns: int - Error code OK + + This function takes the strings in the chtype array chbuf and prints + them left-aligned in the window win. Note that wrefresh() is NOT + called. +*/ +extern int pr_left (WINDOW *win, int y, int x, const chtype *restrict chbuf, + int lines, const int *restrict widthbuf); + + +/* + Function: pr_center - Print strings in chbuf centered in window + Parameters: win - Window to use (should be curwin) + y - Line on which to print first string + offset - Column offset to add to position for each line + chbuf - chtype buffer as returned from prepstr() + lines - Number of lines in chbuf (as returned from prepstr()) + widthbuf - Widths of each line (as returned from prepstr()) + Returns: int - ERR if more lines in chbuf[] than lines, else OK + + This function takes the strings in the chtype array chbuf and prints + them centered in the window win, offset by the parameter offset. Note + that wrefresh() is NOT called. ERR is returned if there are more lines + in chbuf[] than are passed in the parameter lines. +*/ +extern int pr_center (WINDOW *win, int y, int offset, + const chtype *restrict chbuf, int lines, + const int *restrict widthbuf); + + +/* + Function: pr_right - Print strings in chbuf right-aligned + Parameters: win - Window to use (should be curwin) + y - Line on which to print first string + x - Ending column number for each line + chbuf - chtype buffer as returned from prepstr() + lines - Number of lines in chbuf (as returned from prepstr()) + widthbuf - Widths of each line (as returned from prepstr()) + Returns: int - ERR if more lines in chbuf[] than lines, else OK + + This function takes the strings in the chtype array chbuf and prints + them right-aligned in the window win, with each line ending at column + x. Note that wrefresh() is NOT called. ERR is returned if there are + more lines in chbuf[] than are passed in the parameter lines. +*/ +extern int pr_right (WINDOW *win, int y, int x, const chtype *restrict chbuf, + int lines, const int *restrict widthbuf); + + /* Function: attrpr - Print a string with a particular character rendition Parameters: win - Window to use (should be curwin) From 4e7699f1920a9c8f0ed43d6e4b3b6730a4165b47 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Fri, 12 Aug 2011 15:10:05 +1000 Subject: [PATCH 022/112] Add vprepstr() with a va_list argument: for the future txdlgbox() --- src/intf.c | 157 +++++++++++++++++++++++++++++++++-------------------- src/intf.h | 26 +++++++++ 2 files changed, 125 insertions(+), 58 deletions(-) diff --git a/src/intf.c b/src/intf.c index ade44c7..6682ff5 100644 --- a/src/intf.c +++ b/src/intf.c @@ -555,6 +555,27 @@ void txresize (void) #endif // HANDLE_RESIZE_EVENTS +/***********************************************************************/ +// prepstr: Prepare a string for printing to screen + +int prepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, + chtype attr_alt1, chtype attr_alt2, int maxlines, int maxwidth, + int *restrict widthbuf, int widthbufsize, + const char *restrict format, ...) +{ + va_list args; + int lines; + + + va_start(args, format); + lines = vprepstr(chbuf, chbufsize, attr_norm, attr_alt1, attr_alt2, + maxlines, maxwidth, widthbuf, widthbufsize, format, + args); + va_end(args); + return lines; +} + + /***********************************************************************/ // prepstr_addch: Add a character to the prepstr buffer @@ -641,17 +662,16 @@ int prepstr_addch (chtype *restrict *restrict chbuf, int *restrict chbufsize, /***********************************************************************/ -// prepstr: Prepare a string for printing to screen +// vprepstr: Prepare a string for printing to screen -int prepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, - chtype attr_alt1, chtype attr_alt2, int maxlines, int maxwidth, - int *restrict widthbuf, int widthbufsize, - const char *restrict format, ...) +int vprepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, + chtype attr_alt1, chtype attr_alt2, int maxlines, int maxwidth, + int *restrict widthbuf, int widthbufsize, + const char *restrict format, va_list args) { struct argument format_arg[MAXFMTARGS]; int num_format_args, arg_num; const char *orig_format; - va_list args; int line, width; chtype *lastspc; int widthspc; @@ -676,14 +696,14 @@ int prepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, memset(format_arg, 0, sizeof(format_arg)); num_format_args = 0; arg_num = 0; - va_start(args, format); while (*format != '\0') { switch (*format++) { case '^': // Switch to a different character rendition if (*format == '\0') { - goto error_inval; + errno = EINVAL; + return -1; } else { format++; } @@ -692,7 +712,8 @@ int prepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, case '%': // Process a conversion specifier if (*format == '\0') { - goto error_inval; + errno = EINVAL; + return -1; } else if (*format == '%') { format++; } else { @@ -707,8 +728,10 @@ int prepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, switch (c) { case '0': // Zero flag, or part of numeric count - if (count == 0) - goto error_inval; + if (count == 0) { + errno = EINVAL; + return -1; + } count *= 10; break; @@ -728,12 +751,14 @@ int prepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, case '$': // Fixed-position argument - if (flag_posn || count == 0) - goto error_inval; + if (flag_posn || count == 0) { + errno = EINVAL; + return -1; + } if (count > MAXFMTARGS) { errno = E2BIG; - goto error; + return -1; } flag_posn = true; @@ -747,8 +772,10 @@ int prepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, case 'l': // Long length modifier - if (flag_long) - goto error_inval; + if (flag_long) { + errno = EINVAL; + return -1; + } flag_long = true; break; @@ -760,29 +787,34 @@ int prepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, case 'N': // Insert a monetary amount (double) - if (flag_long) - goto error_inval; + if (flag_long) { + errno = EINVAL; + return -1; + } arg_type = TYPE_DOUBLE; goto handlefmt; case 's': // Insert a string (const char *) - if (flag_long) - goto error_inval; + if (flag_long) { + errno = EINVAL; + return -1; + } arg_type = TYPE_STRING; handlefmt: if (arg_num >= MAXFMTARGS) { errno = E2BIG; - goto error; + return -1; } if (format_arg[arg_num].a_type == TYPE_NONE) { format_arg[arg_num].a_type = arg_type; } else if (format_arg[arg_num].a_type != arg_type) { - goto error_inval; + errno = EINVAL; + return -1; } arg_num++; @@ -792,11 +824,14 @@ int prepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, break; default: - goto error_inval; + errno = EINVAL; + return -1; } } - if (inspec) - goto error_inval; + if (inspec) { + errno = EINVAL; + return -1; + } } break; @@ -828,7 +863,8 @@ int prepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, /* Cannot allow unused arguments, as we have no way of knowing how much space they take (cf. int vs. long long int). */ - goto error_inval; + errno = EINVAL; + return -1; } } @@ -848,7 +884,8 @@ int prepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, case '^': // Switch to a different character rendition if (*++format == '\0') { - goto error_inval; + errno = EINVAL; + return -1; } else { switch (*format) { case '^': @@ -856,7 +893,7 @@ int prepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, maxwidth, &line, &width, &lastspc, &widthspc, widthbuf, widthbufsize, &format) < 0) { - goto error; + return -1; } break; @@ -877,7 +914,8 @@ int prepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, break; default: - goto error_inval; + errno = EINVAL; + return -1; } } break; @@ -885,12 +923,13 @@ int prepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, case '%': // Process a conversion specifier if (*++format == '\0') { - goto error_inval; + errno = EINVAL; + return -1; } else if (*format == '%') { if (prepstr_addch(&chbuf, &chbufsize, curattr, maxlines, maxwidth, &line, &width, &lastspc, &widthspc, widthbuf, widthbufsize, &format) < 0) { - goto error; + return -1; } } else { bool inspec = true; @@ -912,7 +951,8 @@ int prepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, if (count == 0) { // Zero flag is not supported free(buf); - goto error_inval; + errno = EINVAL; + return -1; } count *= 10; @@ -935,13 +975,14 @@ int prepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, // Fixed-position argument if (flag_posn || count == 0) { free(buf); - goto error_inval; + errno = EINVAL; + return -1; } if (count > MAXFMTARGS) { free(buf); errno = E2BIG; - goto error; + return -1; } flag_posn = true; @@ -953,7 +994,8 @@ int prepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, // Use locale-specific thousands separator if (flag_thou) { free(buf); - goto error_inval; + errno = EINVAL; + return -1; } flag_thou = true; @@ -963,7 +1005,8 @@ int prepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, // Long length modifier if (flag_long) { free(buf); - goto error_inval; + errno = EINVAL; + return -1; } flag_long = true; @@ -973,13 +1016,14 @@ int prepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, // Insert an integer (int or long int) into the output if (count != 0) { free(buf); - goto error_inval; + errno = EINVAL; + return -1; } if (arg_num >= MAXFMTARGS) { free(buf); errno = E2BIG; - goto error; + return -1; } if (flag_long) { @@ -988,7 +1032,7 @@ int prepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, saved_errno = errno; free(buf); errno = saved_errno; - goto error; + return -1; } } else { if (snprintf(buf, BUFSIZE, flag_thou ? "%'d" : "%d", @@ -996,7 +1040,7 @@ int prepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, saved_errno = errno; free(buf); errno = saved_errno; - goto error; + return -1; } } @@ -1007,13 +1051,14 @@ int prepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, // Insert a monetary amount (double) into the output if (count != 0 || flag_thou || flag_long) { free(buf); - goto error_inval; + errno = EINVAL; + return -1; } if (arg_num >= MAXFMTARGS) { free(buf); errno = E2BIG; - goto error; + return -1; } if (l_strfmon(buf, BUFSIZE, "%n", @@ -1021,7 +1066,7 @@ int prepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, saved_errno = errno; free(buf); errno = saved_errno; - goto error; + return -1; } str = buf; @@ -1031,13 +1076,14 @@ int prepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, // Insert a string (const char *) into the output if (count != 0 || flag_thou || flag_long) { free(buf); - goto error_inval; + errno = EINVAL; + return -1; } if (arg_num >= MAXFMTARGS) { free(buf); errno = E2BIG; - goto error; + return -1; } str = format_arg[arg_num].a.a_string; @@ -1056,7 +1102,7 @@ int prepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, saved_errno = errno; free(buf); errno = saved_errno; - goto error; + return -1; } } @@ -1066,12 +1112,15 @@ int prepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, default: free(buf); - goto error_inval; + errno = EINVAL; + return -1; } } free(buf); - if (inspec) - goto error_inval; + if (inspec) { + errno = EINVAL; + return -1; + } } break; @@ -1080,7 +1129,7 @@ int prepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, if (prepstr_addch(&chbuf, &chbufsize, curattr, maxlines, maxwidth, &line, &width, &lastspc, &widthspc, widthbuf, widthbufsize, &format) < 0) { - goto error; + return -1; } } } @@ -1093,15 +1142,7 @@ int prepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, line = maxlines - 1; } - va_end(args); return line + 1; - -error_inval: - errno = EINVAL; - -error: - va_end(args); - return -1; } diff --git a/src/intf.h b/src/intf.h index 3910c76..d447ec9 100644 --- a/src/intf.h +++ b/src/intf.h @@ -323,6 +323,32 @@ extern int prepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, const char *restrict format, ...); +/* + Function: vprepstr - Prepare a string for printing to screen + Parameters: chbuf - Pointer to chtype buffer in which to store string + chbufsize - Number of chtype elements in chbuf + attr_norm - Normal character rendition to use + attr_alt1 - First alternate character rendition to use + attr_alt2 - Second alternate character rendition to use + maxlines - Maximum number of screen lines to use + maxwidth - Maximum width of each line, in chars + widthbuf - Pointer to buffer to store widths of each line + widthbufsize - Number of int elements in widthbuf + format - Format string as described for prepstr() + args - Variable argument list + Returns: int - Number of lines actually used, or -1 on error + + This function is exactly the same as prepstr(), except that it is + called with a va_list parameter args instead of a variable number of + arguments. Note that va_end() is NOT called on args, and that args is + undefined after this function. +*/ +extern int vprepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, + chtype attr_alt1, chtype attr_alt2, int maxlines, + int maxwidth, int *restrict widthbuf, int widthbufsize, + const char *restrict format, va_list args); + + /* Function: pr_left - Print strings in chbuf left-aligned Parameters: win - Window to use (should be curwin) From 6594ff3daae7891ae05a1f52e0706f00d2e602e8 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Fri, 12 Aug 2011 16:02:01 +1000 Subject: [PATCH 023/112] Add the function txdlgbox() to display a dialog box --- src/intf.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++- src/intf.h | 36 +++++++++++++++++++++++--- 2 files changed, 107 insertions(+), 4 deletions(-) diff --git a/src/intf.c b/src/intf.c index 6682ff5..8560bb3 100644 --- a/src/intf.c +++ b/src/intf.c @@ -555,6 +555,78 @@ void txresize (void) #endif // HANDLE_RESIZE_EVENTS +/***********************************************************************/ +// txdlgbox: Display a dialog box and wait for any key + +int txdlgbox (int maxlines, int ncols, int begin_y, int begin_x, + chtype bkgd_attr, chtype title_attr, chtype norm_attr, + chtype alt1_attr, chtype alt2_attr, chtype keywait_attr, + const char *restrict boxtitle, const char *restrict format, ...) +{ + bool usetitle = (boxtitle != NULL); + + chtype *chbuf; + int *widthbuf; + int lines; + va_list args; + + + assert(maxlines > 0); + + chbuf = malloc(BUFSIZE * sizeof(chtype)); + if (chbuf == NULL) { + err_exit_nomem(); + } + + widthbuf = malloc(maxlines * sizeof(int)); + if (widthbuf == NULL) { + err_exit_nomem(); + } + + va_start(args, format); + lines = vprepstr(chbuf, BUFSIZE, norm_attr, alt1_attr, alt2_attr, maxlines, + ncols - 4, widthbuf, maxlines, format, args); + va_end(args); + + if (lines < 0) { + errno_exit("txdlgbox: `%s'", format); + } + + newtxwin(usetitle ? lines + 6 : lines + 5, ncols, begin_y, begin_x, + true, bkgd_attr); + + if (usetitle) { + chtype *titlebuf; + int titlewidth; + int titlelines; + + titlebuf = malloc(BUFSIZE * sizeof(chtype)); + if (titlebuf == NULL) { + err_exit_nomem(); + } + + titlelines = prepstr(titlebuf, BUFSIZE, title_attr, bkgd_attr, + norm_attr, 1, ncols - 4, &titlewidth, 1, + "%s", boxtitle); + if (titlelines < 0) { + errno_exit("txdlgbox: `%s'", boxtitle); + } + + pr_center(curwin, 1, 0, titlebuf, titlelines, &titlewidth); + + free(titlebuf); + } + + pr_center(curwin, usetitle ? 3 : 2, 0, chbuf, lines, widthbuf); + wait_for_key(curwin, getmaxy(curwin) - 2, keywait_attr); + deltxwin(); + + free(widthbuf); + free(chbuf); + return OK; +} + + /***********************************************************************/ // prepstr: Prepare a string for printing to screen @@ -940,8 +1012,9 @@ int vprepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, const char *str; char *buf = malloc(BUFSIZE); - if (buf == NULL) + if (buf == NULL) { err_exit_nomem(); + } while (inspec && *format != '\0') { char c = *format++; diff --git a/src/intf.h b/src/intf.h index d447ec9..d0701df 100644 --- a/src/intf.h +++ b/src/intf.h @@ -185,10 +185,10 @@ extern void end_screen (void); Function: newtxwin - Create a new window, inserted into window stack Parameters: nlines - Number of lines in new window ncols - Number of columns in new window - begin_y - Starting line number (0 to LINES-1) - begin_x - Starting column number (0 to COLS-1) + begin_y - Starting line number (0 to LINES-1) or WCENTER + begin_x - Starting column number (0 to COLS-1) or WCENTER dofill - True to draw background and box frame - bkgd_attr - Background attribute + bkgd_attr - Background character rendition Returns: WINDOW * - Pointer to new window This function creates a window using the Curses newwin() function and @@ -254,6 +254,36 @@ extern int delalltxwin (void); extern int txrefresh (void); +/* + Function: txdlgbox - Display a dialog box and wait for any key + Parameters: maxlines - Maximum number of lines of text in window + ncols - Number of columns in dialog box window + begin_y - Starting line number (0 to LINES-1) or WCENTER + begin_x - Starting column number (0 to COLS-1) or WCENTER + bkgd_attr - Background character rendition + title_attr - Character rendition to use for dialog box title + norm_attr - Normal character rendition in box + alt1_attr - Alternate character rendition 1 (highlight) + alt2_attr - Alternate character rendition 2 (more highlighted) + keywait_attr - "Press any key" character rendition + boxtitle - Dialog box title (may be NULL) + format - Dialog box text, as passed to prepstr() + ... - Dialog box text format parameters + Returns: int - OK is always returned + + This function creates a dialog box window using newtxwin(), displays + boxtitle centered on the first line (if boxtitle is not NULL), displays + format (and associated parameters) centered using prepstr(), then waits + for the user to press any key before closing the dialog box window. + Note that txrefresh() is NOT called once the window is closed. +*/ +extern int txdlgbox (int maxlines, int ncols, int begin_y, int begin_x, + chtype bkgd_attr, chtype title_attr, chtype norm_attr, + chtype alt1_attr, chtype alt2_attr, chtype keywait_attr, + const char *restrict boxtitle, + const char *restrict format, ...); + + /* Function: prepstr - Prepare a string for printing to screen Parameters: chbuf - Pointer to chtype buffer in which to store string From b27af385376df6f2fd612720ccf3a1beb41f9657 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Fri, 12 Aug 2011 16:09:38 +1000 Subject: [PATCH 024/112] Minimise flickering when resizing the console window --- src/intf.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/intf.c b/src/intf.c index 8560bb3..f120ace 100644 --- a/src/intf.c +++ b/src/intf.c @@ -125,7 +125,7 @@ txwin_t *firstwin = NULL; // First (bottom-most) txwin structure Returns: (nothing) This function draws the main window game title, "Star Traders", and - clears the rest of the screen. + clears the rest of the screen. It does NOT call wrefresh(). */ static void init_title (void); @@ -344,6 +344,7 @@ void init_screen (void) } init_title(); + refresh(); } @@ -379,9 +380,7 @@ void init_title (void) } center(stdscr, 0, attr_game_title, "Star Traders"); - attrset(attr_root_window); - refresh(); } From 15f06bdc79e57d660f0a4600b5f57a3f16d31c5c Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Fri, 12 Aug 2011 16:32:32 +1000 Subject: [PATCH 025/112] Move some functions from center() to pr_center() --- src/intf.c | 45 ++++++++++++++++++++++++++++++++++++++++----- src/intf.h | 8 ++++---- 2 files changed, 44 insertions(+), 9 deletions(-) diff --git a/src/intf.c b/src/intf.c index f120ace..8dab9fc 100644 --- a/src/intf.c +++ b/src/intf.c @@ -371,6 +371,11 @@ void end_screen (void) void init_title (void) { + chtype *chbuf; + int width; + int lines; + + bkgd(attr_root_window); clear(); @@ -379,8 +384,20 @@ void init_title (void) addch(attr_game_title | ' '); } - center(stdscr, 0, attr_game_title, "Star Traders"); + chbuf = malloc(BUFSIZE * sizeof(chtype)); + if (chbuf == NULL) { + err_exit_nomem(); + } + + lines = prepstr(chbuf, BUFSIZE, attr_game_title, 0, 0, 1, COLS, + &width, 1, "%s", _("Star Traders")); + if (lines < 0) { + errno_exit("init_title"); + } + + pr_center(stdscr, 0, 0, chbuf, lines, &width); attrset(attr_root_window); + free(chbuf); } @@ -588,7 +605,7 @@ int txdlgbox (int maxlines, int ncols, int begin_y, int begin_x, va_end(args); if (lines < 0) { - errno_exit("txdlgbox: `%s'", format); + errno_exit(_("txdlgbox: `%s'"), format); } newtxwin(usetitle ? lines + 6 : lines + 5, ncols, begin_y, begin_x, @@ -608,7 +625,7 @@ int txdlgbox (int maxlines, int ncols, int begin_y, int begin_x, norm_attr, 1, ncols - 4, &titlewidth, 1, "%s", boxtitle); if (titlelines < 0) { - errno_exit("txdlgbox: `%s'", boxtitle); + errno_exit(_("txdlgbox: `%s'"), boxtitle); } pr_center(curwin, 1, 0, titlebuf, titlelines, &titlewidth); @@ -1243,7 +1260,7 @@ int pr_left (WINDOW *win, int y, int x, const chtype *restrict chbuf, /***********************************************************************/ -// pr_center: Print strings in chbuf centered in window +// pr_center: Print strings in chbuf centred in window int pr_center (WINDOW *win, int y, int offset, const chtype *restrict chbuf, int lines, const int *restrict widthbuf) @@ -2461,15 +2478,31 @@ bool answer_yesno (WINDOW *win, chtype attr_keys) void wait_for_key (WINDOW *win, int y, chtype attr) { + chtype *chbuf; + int width; + int lines; + int key; bool done; + keypad(win, true); meta(win, true); wtimeout(win, -1); - center(win, y, attr, "[ Press to continue ] "); + chbuf = malloc(BUFSIZE * sizeof(chtype)); + if (chbuf == NULL) { + err_exit_nomem(); + } + + lines = prepstr(chbuf, BUFSIZE, attr, 0, 0, 1, getmaxx(win) - 4, + &width, 1, _("[ Press to continue ] ")); + if (lines < 0) { + errno_exit("wait_for_key"); + } + + pr_center(win, y, 0, chbuf, lines, &width); wrefresh(win); done = false; @@ -2490,6 +2523,8 @@ void wait_for_key (WINDOW *win, int y, chtype attr) done = true; } } + + free(chbuf); } diff --git a/src/intf.h b/src/intf.h index d0701df..4e2069f 100644 --- a/src/intf.h +++ b/src/intf.h @@ -272,8 +272,8 @@ extern int txrefresh (void); Returns: int - OK is always returned This function creates a dialog box window using newtxwin(), displays - boxtitle centered on the first line (if boxtitle is not NULL), displays - format (and associated parameters) centered using prepstr(), then waits + boxtitle centred on the first line (if boxtitle is not NULL), displays + format (and associated parameters) centred using prepstr(), then waits for the user to press any key before closing the dialog box window. Note that txrefresh() is NOT called once the window is closed. */ @@ -398,7 +398,7 @@ extern int pr_left (WINDOW *win, int y, int x, const chtype *restrict chbuf, /* - Function: pr_center - Print strings in chbuf centered in window + Function: pr_center - Print strings in chbuf centred in window Parameters: win - Window to use (should be curwin) y - Line on which to print first string offset - Column offset to add to position for each line @@ -408,7 +408,7 @@ extern int pr_left (WINDOW *win, int y, int x, const chtype *restrict chbuf, Returns: int - ERR if more lines in chbuf[] than lines, else OK This function takes the strings in the chtype array chbuf and prints - them centered in the window win, offset by the parameter offset. Note + them centred in the window win, offset by the parameter offset. Note that wrefresh() is NOT called. ERR is returned if there are more lines in chbuf[] than are passed in the parameter lines. */ From 184c07d19d4b7b723acf1fcb4e7b92bcebdaa056 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Fri, 12 Aug 2011 16:35:13 +1000 Subject: [PATCH 026/112] Add a comment about multibyte character handling in prepstr() --- src/intf.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/intf.h b/src/intf.h index 4e2069f..fa2176c 100644 --- a/src/intf.h +++ b/src/intf.h @@ -343,6 +343,10 @@ extern int txdlgbox (int maxlines, int ncols, int begin_y, int begin_x, will force the start of a new line. By default, attr_norm is used as the character rendition (attributes). + Please note that this function does NOT handle multibyte characters + correctly: widths may be incorrect (byte count, not actual width) and + multibyte characters may be split over two lines. + This function returns the actual number of lines used (from 0 to maxlines), or -1 on error (with errno set to EINVAL for an invalid format conversion specifier or argument). From 7d9bf097b9f77514fe8a2cd002d5c15ea38737fa Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Fri, 12 Aug 2011 18:24:35 +1000 Subject: [PATCH 027/112] Replace discrete calls to newtxwin() etc. with calls to txdlgbox() --- src/exch.c | 106 ++++++++++++++----------------------------- src/fileio.c | 64 ++++++++++---------------- src/game.c | 39 ++++++---------- src/intf.h | 2 + src/move.c | 125 +++++++++++++-------------------------------------- 5 files changed, 104 insertions(+), 232 deletions(-) diff --git a/src/exch.c b/src/exch.c index 9535ff5..c623e95 100644 --- a/src/exch.c +++ b/src/exch.c @@ -338,15 +338,10 @@ void visit_bank (void) case '1': // Borrow money from the Bank if (credit_limit == 0.0) { - newtxwin(7, 50, 8, WCENTER, true, attr_error_window); - - center(curwin, 1, attr_error_title, " Insufficient Credit Limit "); - center(curwin, 3, attr_error_highlight, - "The Bank will not lend you any more money"); - - wait_for_key(curwin, 5, attr_error_waitforkey); - deltxwin(); - + txdlgbox(MAX_DLG_LINES, 50, 8, WCENTER, attr_error_window, + attr_error_title, attr_error_highlight, 0, 0, + attr_error_waitforkey, " Insufficient Credit Limit ", + "The Bank will not lend you any more money."); } else { int x, y, n; int ret; @@ -390,25 +385,15 @@ void visit_bank (void) case '2': // Repay a debt if (player[current_player].debt == 0.0) { - newtxwin(7, 50, 8, WCENTER, true, attr_error_window); - - center(curwin, 1, attr_error_title, " No Debt "); - center(curwin, 3, attr_error_highlight, - "You have no debt to repay"); - - wait_for_key(curwin, 5, attr_error_waitforkey); - deltxwin(); - + txdlgbox(MAX_DLG_LINES, 50, 8, WCENTER, attr_error_window, + attr_error_title, attr_error_highlight, 0, 0, + attr_error_waitforkey, " No Debt ", + "You have no debt to repay."); } else if (player[current_player].cash == 0.0) { - newtxwin(7, 60, 8, WCENTER, true, attr_error_window); - - center(curwin, 1, attr_error_title, " No Cash "); - center(curwin, 3, attr_error_highlight, - "You have no cash with which to repay the debt!"); - - wait_for_key(curwin, 5, attr_error_waitforkey); - deltxwin(); - + txdlgbox(MAX_DLG_LINES, 50, 8, WCENTER, attr_error_window, + attr_error_title, attr_error_highlight, 0, 0, + attr_error_waitforkey, " No Cash ", + "You have no cash with which to repay the debt!"); } else { int x, y, n; int ret; @@ -593,25 +578,15 @@ void trade_shares (int num, bool *bid_used) maxshares = player[current_player].cash / company[num].share_price; if (company[num].max_stock - company[num].stock_issued == 0) { - newtxwin(7, 50, 8, WCENTER, true, attr_error_window); - - center(curwin, 1, attr_error_title, " No Shares Available "); - center(curwin, 3, attr_error_highlight, - "No more shares are available for purchase"); - - wait_for_key(curwin, 5, attr_error_waitforkey); - deltxwin(); - + txdlgbox(MAX_DLG_LINES, 50, 8, WCENTER, attr_error_window, + attr_error_title, attr_error_highlight, 0, 0, + attr_error_waitforkey, " No Shares Available ", + "No more shares are available for purchase."); } else if (maxshares <= 0) { - newtxwin(7, 50, 8, WCENTER, true, attr_error_window); - - center(curwin, 1, attr_error_title, " Insufficient Cash "); - center(curwin, 3, attr_error_highlight, - "Not enough cash to purchase shares"); - - wait_for_key(curwin, 5, attr_error_waitforkey); - deltxwin(); - + txdlgbox(MAX_DLG_LINES, 50, 8, WCENTER, attr_error_window, + attr_error_title, attr_error_highlight, 0, 0, + attr_error_waitforkey, " Insufficient Cash ", + "Not enough cash to purchase shares."); } else { maxshares = MIN(maxshares, company[num].max_stock - company[num].stock_issued); @@ -641,15 +616,10 @@ void trade_shares (int num, bool *bid_used) // Sell stock back to company maxshares = player[current_player].stock_owned[num]; if (maxshares == 0) { - newtxwin(7, 50, 8, WCENTER, true, attr_error_window); - - center(curwin, 1, attr_error_title, " No Shares "); - center(curwin, 3, attr_error_highlight, - "You do not have any shares to sell"); - - wait_for_key(curwin, 5, attr_error_waitforkey); - deltxwin(); - + txdlgbox(MAX_DLG_LINES, 50, 8, WCENTER, attr_error_window, + attr_error_title, attr_error_highlight, 0, 0, + attr_error_waitforkey, " No Shares ", + "You do not have any shares to sell."); } else { wbkgd(curwin, attr_normal_window); werase(curwin); @@ -683,25 +653,17 @@ void trade_shares (int num, bool *bid_used) *bid_used = true; if (maxshares == 0) { - newtxwin(8, 50, 8, WCENTER, true, attr_error_window); - - center(curwin, 1, attr_error_title, " No Shares Issued "); - center(curwin, 3, attr_error_highlight, "%s", company[num].name); - center(curwin, 4, attr_error_highlight, - "has refused to issue more shares"); - - wait_for_key(curwin, 6, attr_error_waitforkey); - deltxwin(); + txdlgbox(MAX_DLG_LINES, 50, 8, WCENTER, attr_error_window, + attr_error_title, attr_error_highlight, 0, 0, + attr_error_waitforkey, " No Shares Issued ", + "%s has refused\nto issue more shares.", + company[num].name); } else { - newtxwin(8, 50, 8, WCENTER, true, attr_normal_window); - - center(curwin, 1, attr_title, " Shares Issued "); - center(curwin, 3, attr_highlight, "%s", company[num].name); - center(curwin, 4, attr_highlight, "has issued %'ld more shares", - maxshares); - - wait_for_key(curwin, 6, attr_waitforkey); - deltxwin(); + txdlgbox(MAX_DLG_LINES, 50, 8, WCENTER, attr_normal_window, + attr_title, attr_normal, attr_highlight, 0, + attr_waitforkey, " Shares Issued ", + "%s has issued\n^{%'ld^} more shares.", + company[num].name, maxshares); } break; diff --git a/src/fileio.c b/src/fileio.c index 6721854..bcf41b6 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -240,28 +240,19 @@ bool load_game (int num) if (errno == ENOENT) { // File not found - newtxwin(7, 40, 9, WCENTER, true, attr_error_window); - - center(curwin, 1, attr_error_title, " Game Not Found "); - center(curwin, 3, attr_error_highlight, - "Game %d has not been saved to disk", num); - - wait_for_key(curwin, 5, attr_error_waitforkey); - deltxwin(); + txdlgbox(MAX_DLG_LINES, 50, 9, WCENTER, attr_error_window, + attr_error_title, attr_error_highlight, 0, 0, + attr_error_waitforkey, " Game Not Found ", + "Game %d has not been saved to disk.", num); } else { // Some other file error saved_errno = errno; - - newtxwin(9, 70, 9, WCENTER, true, attr_error_window); - - center(curwin, 1, attr_error_title, " Game Not Loaded "); - center(curwin, 3, attr_error_highlight, - "Game %d could not be loaded from disk", num); - center(curwin, 5, attr_error_normal, "File %s: %s", filename, - strerror(saved_errno)); - - wait_for_key(curwin, 7, attr_error_waitforkey); - deltxwin(); + txdlgbox(MAX_DLG_LINES, 60, 9, WCENTER, attr_error_window, + attr_error_title, attr_error_highlight, + attr_error_normal, 0, attr_error_waitforkey, + " Game Not Loaded ", + "Game %d could not be loaded from disk.\n\n" + "^{File %s: %s^}", num, filename, strerror(saved_errno)); } free(buf); @@ -459,17 +450,13 @@ bool save_game (int num) ; // Do nothing: directory already exists } else { // Data directory could not be created - - newtxwin(9, 70, 7, WCENTER, true, attr_error_window); - - center(curwin, 1, attr_error_title, " Game Not Saved "); - center(curwin, 3, attr_error_highlight, - "Game %d could not be saved to disk", num); - center(curwin, 5, attr_error_normal, "Directory %s: %s", - data_dir, strerror(saved_errno)); - - wait_for_key(curwin, 7, attr_error_waitforkey); - deltxwin(); + txdlgbox(MAX_DLG_LINES, 60, 7, WCENTER, attr_error_window, + attr_error_title, attr_error_highlight, + attr_error_normal, 0, attr_error_waitforkey, + " Game Not Saved ", + "Game %d could not be saved to disk.\n\n" + "^{Directory %s: %s^}", num, data_dir, + strerror(saved_errno)); free(buf); return false; @@ -484,17 +471,12 @@ bool save_game (int num) if (file == NULL) { // File could not be opened for writing saved_errno = errno; - - newtxwin(9, 70, 7, WCENTER, true, attr_error_window); - - center(curwin, 1, attr_error_title, " Game Not Saved "); - center(curwin, 3, attr_error_highlight, - "Game %d could not be saved to disk", num); - center(curwin, 5, attr_error_normal, "File %s: %s", filename, - strerror(saved_errno)); - - wait_for_key(curwin, 7, attr_error_waitforkey); - deltxwin(); + txdlgbox(MAX_DLG_LINES, 60, 7, WCENTER, attr_error_window, + attr_error_title, attr_error_highlight, + attr_error_normal, 0, attr_error_waitforkey, + " Game Not Saved ", + "Game %d could not be saved to disk.\n\n" + "^{File %s: %s^}", num, filename, strerror(saved_errno)); free(buf); free(filename); diff --git a/src/game.c b/src/game.c index 3e13573..a56d1c4 100644 --- a/src/game.c +++ b/src/game.c @@ -207,14 +207,11 @@ void init_game (void) first_player = randi(number_players); current_player = first_player; - newtxwin(7, 50, 8, WCENTER, true, attr_normal_window); - - center(curwin, 2, attr_normal, "The first player to go is"); - center(curwin, 3, attr_highlight, "%s", - player[first_player].name); - - wait_for_key(curwin, 5, attr_waitforkey); - deltxwin(); + txdlgbox(MAX_DLG_LINES, 50, 8, WCENTER, attr_normal_window, + attr_title, attr_normal, attr_highlight, 0, + attr_waitforkey, " First Player ", + "The first player to go is ^{%s^}.", + player[first_player].name); txrefresh(); } } @@ -497,30 +494,20 @@ void end_game (void) err_exit_nomem(); } - newtxwin(7, 40, 9, WCENTER, true, attr_error_window); - - center(curwin, 1, attr_error_title, " Game Over "); - center(curwin, 3, attr_error_highlight, "The game is over after %d turns", - turn_number - 1); - - wait_for_key(curwin, 5, attr_error_waitforkey); - deltxwin(); + txdlgbox(MAX_DLG_LINES, 50, 9, WCENTER, attr_error_window, + attr_error_title, attr_error_highlight, 0, 0, + attr_error_waitforkey, " Game Over ", + "The game is over after %d turns.", turn_number - 1); for (i = 0; i < number_players; i++) { show_status(i); } if (number_players == 1) { - l_strfmon(buf, BUFSIZE, "%1n", total_value(0)); - - newtxwin(9, 60, 8, WCENTER, true, attr_normal_window); - - center(curwin, 1, attr_title, " Total Value "); - center2(curwin, 4, attr_normal, attr_highlight, - "Your total value was ", "%s", buf); - - wait_for_key(curwin, 7, attr_waitforkey); - deltxwin(); + txdlgbox(MAX_DLG_LINES, 60, 8, WCENTER, attr_normal_window, + attr_title, attr_normal, attr_highlight, 0, attr_waitforkey, + " Total Value ", "Your total value was ^{%N^}.", + total_value(0)); } else { // Sort players on the basis of total value for (i = 0; i < number_players; i++) { diff --git a/src/intf.h b/src/intf.h index fa2176c..1809355 100644 --- a/src/intf.h +++ b/src/intf.h @@ -55,6 +55,8 @@ #define WCENTER -1 // Centre the new window +#define MAX_DLG_LINES 10 // Default maximum lines in dialog box + // Check if resizing events are supported #ifdef KEY_RESIZE diff --git a/src/move.c b/src/move.c index 3db159b..49f3aa9 100644 --- a/src/move.c +++ b/src/move.c @@ -632,58 +632,23 @@ void next_player (void) void bankrupt_player (bool forced) { - bool longname; - int i; - - - /* It would be nice if we had functions that would do word-wrapping - for us automatically! */ - - longname = (strlen(player[current_player].name) > 20); if (forced) { - newtxwin(longname ? 9 : 8, 54, 7, WCENTER, true, attr_error_window); + txdlgbox(MAX_DLG_LINES, 50, 7, WCENTER, attr_error_window, + attr_error_title, attr_error_highlight, 0, 0, + attr_error_waitforkey, " Bankruptcy Court ", + "%s has been declared bankrupt by the Interstellar Trading Bank.", + player[current_player].name); } else { - newtxwin(longname ? 8 : 7, 50, 7, WCENTER, true, attr_error_window); + txdlgbox(MAX_DLG_LINES, 50, 7, WCENTER, attr_error_window, + attr_error_title, attr_error_highlight, 0, 0, + attr_error_waitforkey, " Bankruptcy Court ", + "%s has declared bankruptcy.", player[current_player].name); } - - center(curwin, 1, attr_error_title, " Bankruptcy Court "); - - if (forced) { - if (longname) { - center(curwin, 3, attr_error_highlight, "%s", - player[current_player].name); - center(curwin, 4, attr_error_highlight, - "has been declared bankrupt by the"); - center(curwin, 5, attr_error_highlight, - "Interstellar Trading Bank"); - } else { - center(curwin, 3, attr_error_highlight, - "%s has been declared bankrupt", - player[current_player].name); - center(curwin, 4, attr_error_highlight, - "by the Interstellar Trading Bank"); - } - } else { - if (longname) { - center(curwin, 3, attr_error_highlight, "%s", - player[current_player].name); - center(curwin, 4, attr_error_highlight, - "has declared bankruptcy"); - } else { - center(curwin, 3, attr_error_highlight, - "%s has declared bankruptcy", - player[current_player].name); - } - } - - wait_for_key(curwin, getmaxy(curwin) - 2, attr_error_waitforkey); - - deltxwin(); txrefresh(); // Confiscate all assets belonging to player player[current_player].in_game = false; - for (i = 0; i < MAX_COMPANIES; i++) { + for (int i = 0; i < MAX_COMPANIES; i++) { company[i].stock_issued -= player[current_player].stock_owned[i]; player[current_player].stock_owned[i] = 0; } @@ -692,7 +657,7 @@ void bankrupt_player (bool forced) // Is anyone still left in the game? bool all_out = true; - for (i = 0; i < number_players; i++) { + for (int i = 0; i < number_players; i++) { if (player[i].in_game) { all_out = false; break; @@ -742,16 +707,10 @@ void try_start_new_company (int x, int y) } else { // Create the new company - newtxwin(8, 50, 7, WCENTER, true, attr_normal_window); - - center(curwin, 1, attr_title, " New Company "); - center(curwin, 3, attr_normal, "A new company has been formed!"); - center2(curwin, 4, attr_normal, attr_highlight, "Its name is ", - "%s", company[i].name); - - wait_for_key(curwin, 6, attr_waitforkey); - - deltxwin(); + txdlgbox(MAX_DLG_LINES, 50, 7, WCENTER, attr_normal_window, + attr_title, attr_normal, attr_highlight, 0, attr_waitforkey, + " New Company ", "A new company has been formed!\n" + "Its name is ^{%s^}.", company[i].name); txrefresh(); galaxy_map[x][y] = COMPANY_TO_MAP(i); @@ -958,19 +917,15 @@ void adjust_values (void) if (company[which].on_map) { if (randf() < ALL_ASSETS_TAKEN) { - newtxwin(10, 60, 6, WCENTER, true, attr_error_window); - - center(curwin, 1, attr_error_title, " Bankruptcy Court "); - center(curwin, 3, attr_error_highlight, "%s has been declared", - company[which].name); - center(curwin, 4, attr_error_highlight, - "bankrupt by the Interstellar Trading Bank."); - - center(curwin, 6, attr_error_window, - "All assets have been taken to repay outstanding loans."); - - wait_for_key(curwin, 8, attr_error_waitforkey); - deltxwin(); + txdlgbox(MAX_DLG_LINES, 60, 6, WCENTER, attr_error_window, + attr_error_title, attr_error_highlight, + attr_error_normal, 0, attr_error_waitforkey, + " Bankruptcy Court ", + "%s has been declared bankrupt " + "by the Interstellar Trading Bank.\n\n" + "^{All assets have been taken " + "to repay outstanding loans.^}", + company[which].name); txrefresh(); } else { @@ -1090,31 +1045,15 @@ void adjust_values (void) // Check if a player's debt is too large if (total_value(current_player) <= -MAX_OVERDRAFT) { - double impounded; - char *buf; + double impounded = MIN(player[current_player].cash, + player[current_player].debt); - buf = malloc(BUFSIZE); - if (buf == NULL) { - err_exit_nomem(); - } - - impounded = MIN(player[current_player].cash, - player[current_player].debt); - - newtxwin(8, 60, 7, WCENTER, true, attr_error_window); - center(curwin, 1, attr_error_title, " Interstellar Trading Bank "); - - l_strfmon(buf, BUFSIZE, "%1n", player[current_player].debt); - center(curwin, 3, attr_error_highlight, - "Your debt has amounted to %s", buf); - - l_strfmon(buf, BUFSIZE, "%1n", impounded); - center3(curwin, 4, attr_error_normal, attr_error_normal, - attr_error_highlight, "The Bank has impounded ", - " from your cash", "%s", buf); - - wait_for_key(curwin, 6, attr_error_waitforkey); - deltxwin(); + txdlgbox(MAX_DLG_LINES, 60, 7, WCENTER, attr_error_window, + attr_error_title, attr_error_highlight, attr_error_normal, + 0, attr_error_waitforkey, " Interstellar Trading Bank ", + "Your debt has amounted to %N!\n" + "^{The Bank has impounded ^}%N^{ from your cash.^}", + player[current_player].debt, impounded); txrefresh(); player[current_player].cash -= impounded; From 06b66716cf5e11bb9e046c66092f926a6fabe9ee Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Sat, 13 Aug 2011 07:59:20 +1000 Subject: [PATCH 028/112] Add the function chbufdup() to duplicate a chtype array --- src/intf.c | 26 ++++++++++++++++++++++++++ src/intf.h | 14 ++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/src/intf.c b/src/intf.c index 8dab9fc..238c756 100644 --- a/src/intf.c +++ b/src/intf.c @@ -1235,6 +1235,32 @@ int vprepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, } +/***********************************************************************/ +// chbufdup: Duplicate a chtype buffer + +chtype *chbufdup (const chtype *restrict chbuf, int chbufsize) +{ + const chtype *p; + int len; + chtype *ret; + + + // Determine chbuf length, including ending NUL + for (len = 1, p = chbuf; *p != '\0' && len <= chbufsize; p++, len++) + ; + + ret = malloc(len * sizeof(chtype)); + if (ret == NULL) { + err_exit_nomem(); + } + + memcpy(ret, chbuf, len * sizeof(chtype)); + ret[len - 1] = '\0'; // Terminating NUL, just in case not present + + return ret; +} + + /***********************************************************************/ // pr_left: Print strings in chbuf left-aligned diff --git a/src/intf.h b/src/intf.h index 1809355..8d594d0 100644 --- a/src/intf.h +++ b/src/intf.h @@ -385,6 +385,20 @@ extern int vprepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, const char *restrict format, va_list args); +/* + Function: chbufdup - Duplicate a chtype buffer + Parameters: chbuf - Buffer to duplicate + chbufsize - Number of chtype elements in chbuf + Returns: chtype * - Pointer to new duplicated buffer + + This function returns a new buffer of type chtype * that contains a + copy of the string in chbuf. No errors are returned: if sufficient + memory is not available, the program terminates with an "Out of memory" + message. +*/ +extern chtype *chbufdup (const chtype *restrict chbuf, int chbufsize); + + /* Function: pr_left - Print strings in chbuf left-aligned Parameters: win - Window to use (should be curwin) From c50b8a464937b0bac1533ddce3c9c2223d0afedc Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Sat, 13 Aug 2011 08:17:30 +1000 Subject: [PATCH 029/112] Move error handling into vprepstr(), to save doing it over and over --- src/intf.c | 142 +++++++++++++++++++---------------------------------- src/intf.h | 7 ++- 2 files changed, 54 insertions(+), 95 deletions(-) diff --git a/src/intf.c b/src/intf.c index 238c756..d0ef68c 100644 --- a/src/intf.c +++ b/src/intf.c @@ -390,10 +390,7 @@ void init_title (void) } lines = prepstr(chbuf, BUFSIZE, attr_game_title, 0, 0, 1, COLS, - &width, 1, "%s", _("Star Traders")); - if (lines < 0) { - errno_exit("init_title"); - } + &width, 1, _("Star Traders")); pr_center(stdscr, 0, 0, chbuf, lines, &width); attrset(attr_root_window); @@ -604,10 +601,6 @@ int txdlgbox (int maxlines, int ncols, int begin_y, int begin_x, ncols - 4, widthbuf, maxlines, format, args); va_end(args); - if (lines < 0) { - errno_exit(_("txdlgbox: `%s'"), format); - } - newtxwin(usetitle ? lines + 6 : lines + 5, ncols, begin_y, begin_x, true, bkgd_attr); @@ -621,15 +614,9 @@ int txdlgbox (int maxlines, int ncols, int begin_y, int begin_x, err_exit_nomem(); } - titlelines = prepstr(titlebuf, BUFSIZE, title_attr, bkgd_attr, - norm_attr, 1, ncols - 4, &titlewidth, 1, - "%s", boxtitle); - if (titlelines < 0) { - errno_exit(_("txdlgbox: `%s'"), boxtitle); - } - + titlelines = prepstr(titlebuf, BUFSIZE, title_attr, 0, 0, 1, + ncols - 4, &titlewidth, 1, boxtitle); pr_center(curwin, 1, 0, titlebuf, titlelines, &titlewidth); - free(titlebuf); } @@ -790,8 +777,7 @@ int vprepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, case '^': // Switch to a different character rendition if (*format == '\0') { - errno = EINVAL; - return -1; + goto error_inval; } else { format++; } @@ -800,8 +786,7 @@ int vprepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, case '%': // Process a conversion specifier if (*format == '\0') { - errno = EINVAL; - return -1; + goto error_inval; } else if (*format == '%') { format++; } else { @@ -816,10 +801,8 @@ int vprepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, switch (c) { case '0': // Zero flag, or part of numeric count - if (count == 0) { - errno = EINVAL; - return -1; - } + if (count == 0) + goto error_inval; count *= 10; break; @@ -839,14 +822,12 @@ int vprepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, case '$': // Fixed-position argument - if (flag_posn || count == 0) { - errno = EINVAL; - return -1; - } + if (flag_posn || count == 0) + goto error_inval; if (count > MAXFMTARGS) { errno = E2BIG; - return -1; + goto error; } flag_posn = true; @@ -860,10 +841,8 @@ int vprepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, case 'l': // Long length modifier - if (flag_long) { - errno = EINVAL; - return -1; - } + if (flag_long) + goto error_inval; flag_long = true; break; @@ -875,34 +854,29 @@ int vprepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, case 'N': // Insert a monetary amount (double) - if (flag_long) { - errno = EINVAL; - return -1; - } + if (flag_long) + goto error_inval; arg_type = TYPE_DOUBLE; goto handlefmt; case 's': // Insert a string (const char *) - if (flag_long) { - errno = EINVAL; - return -1; - } + if (flag_long) + goto error_inval; arg_type = TYPE_STRING; handlefmt: if (arg_num >= MAXFMTARGS) { errno = E2BIG; - return -1; + goto error; } if (format_arg[arg_num].a_type == TYPE_NONE) { format_arg[arg_num].a_type = arg_type; } else if (format_arg[arg_num].a_type != arg_type) { - errno = EINVAL; - return -1; + goto error_inval; } arg_num++; @@ -912,13 +886,11 @@ int vprepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, break; default: - errno = EINVAL; - return -1; + goto error_inval; } } if (inspec) { - errno = EINVAL; - return -1; + goto error_inval; } } break; @@ -951,8 +923,7 @@ int vprepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, /* Cannot allow unused arguments, as we have no way of knowing how much space they take (cf. int vs. long long int). */ - errno = EINVAL; - return -1; + goto error_inval; } } @@ -972,8 +943,7 @@ int vprepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, case '^': // Switch to a different character rendition if (*++format == '\0') { - errno = EINVAL; - return -1; + goto error_inval; } else { switch (*format) { case '^': @@ -981,7 +951,7 @@ int vprepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, maxwidth, &line, &width, &lastspc, &widthspc, widthbuf, widthbufsize, &format) < 0) { - return -1; + goto error; } break; @@ -1002,8 +972,7 @@ int vprepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, break; default: - errno = EINVAL; - return -1; + goto error_inval; } } break; @@ -1011,13 +980,12 @@ int vprepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, case '%': // Process a conversion specifier if (*++format == '\0') { - errno = EINVAL; - return -1; + goto error_inval; } else if (*format == '%') { if (prepstr_addch(&chbuf, &chbufsize, curattr, maxlines, maxwidth, &line, &width, &lastspc, &widthspc, widthbuf, widthbufsize, &format) < 0) { - return -1; + goto error; } } else { bool inspec = true; @@ -1040,8 +1008,7 @@ int vprepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, if (count == 0) { // Zero flag is not supported free(buf); - errno = EINVAL; - return -1; + goto error_inval; } count *= 10; @@ -1064,14 +1031,13 @@ int vprepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, // Fixed-position argument if (flag_posn || count == 0) { free(buf); - errno = EINVAL; - return -1; + goto error_inval; } if (count > MAXFMTARGS) { free(buf); errno = E2BIG; - return -1; + goto error; } flag_posn = true; @@ -1083,8 +1049,7 @@ int vprepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, // Use locale-specific thousands separator if (flag_thou) { free(buf); - errno = EINVAL; - return -1; + goto error_inval; } flag_thou = true; @@ -1094,8 +1059,7 @@ int vprepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, // Long length modifier if (flag_long) { free(buf); - errno = EINVAL; - return -1; + goto error_inval; } flag_long = true; @@ -1105,14 +1069,13 @@ int vprepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, // Insert an integer (int or long int) into the output if (count != 0) { free(buf); - errno = EINVAL; - return -1; + goto error_inval; } if (arg_num >= MAXFMTARGS) { free(buf); errno = E2BIG; - return -1; + goto error; } if (flag_long) { @@ -1121,7 +1084,7 @@ int vprepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, saved_errno = errno; free(buf); errno = saved_errno; - return -1; + goto error; } } else { if (snprintf(buf, BUFSIZE, flag_thou ? "%'d" : "%d", @@ -1129,7 +1092,7 @@ int vprepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, saved_errno = errno; free(buf); errno = saved_errno; - return -1; + goto error; } } @@ -1140,14 +1103,13 @@ int vprepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, // Insert a monetary amount (double) into the output if (count != 0 || flag_thou || flag_long) { free(buf); - errno = EINVAL; - return -1; + goto error_inval; } if (arg_num >= MAXFMTARGS) { free(buf); errno = E2BIG; - return -1; + goto error; } if (l_strfmon(buf, BUFSIZE, "%n", @@ -1155,7 +1117,7 @@ int vprepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, saved_errno = errno; free(buf); errno = saved_errno; - return -1; + goto error; } str = buf; @@ -1165,14 +1127,13 @@ int vprepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, // Insert a string (const char *) into the output if (count != 0 || flag_thou || flag_long) { free(buf); - errno = EINVAL; - return -1; + goto error_inval; } if (arg_num >= MAXFMTARGS) { free(buf); errno = E2BIG; - return -1; + goto error; } str = format_arg[arg_num].a.a_string; @@ -1191,7 +1152,7 @@ int vprepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, saved_errno = errno; free(buf); errno = saved_errno; - return -1; + goto error; } } @@ -1201,14 +1162,12 @@ int vprepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, default: free(buf); - errno = EINVAL; - return -1; + goto error_inval; } } free(buf); if (inspec) { - errno = EINVAL; - return -1; + goto error_inval; } } break; @@ -1218,7 +1177,7 @@ int vprepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, if (prepstr_addch(&chbuf, &chbufsize, curattr, maxlines, maxwidth, &line, &width, &lastspc, &widthspc, widthbuf, widthbufsize, &format) < 0) { - return -1; + goto error; } } } @@ -1232,6 +1191,13 @@ int vprepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, } return line + 1; + + +error_inval: + errno = EINVAL; + +error: + errno_exit(_("prepstr: `%s'"), orig_format); } @@ -2507,12 +2473,10 @@ void wait_for_key (WINDOW *win, int y, chtype attr) chtype *chbuf; int width; int lines; - int key; bool done; - keypad(win, true); meta(win, true); wtimeout(win, -1); @@ -2524,10 +2488,6 @@ void wait_for_key (WINDOW *win, int y, chtype attr) lines = prepstr(chbuf, BUFSIZE, attr, 0, 0, 1, getmaxx(win) - 4, &width, 1, _("[ Press to continue ] ")); - if (lines < 0) { - errno_exit("wait_for_key"); - } - pr_center(win, y, 0, chbuf, lines, &width); wrefresh(win); diff --git a/src/intf.h b/src/intf.h index 8d594d0..d5ef379 100644 --- a/src/intf.h +++ b/src/intf.h @@ -299,7 +299,7 @@ extern int txdlgbox (int maxlines, int ncols, int begin_y, int begin_x, widthbufsize - Number of int elements in widthbuf format - Format string as described below ... - Arguments for the format string - Returns: int - Number of lines actually used, or -1 on error + Returns: int - Number of lines actually used This function converts the format string and following arguments into chbuf, a chtype buffer that can be used for calls to pr_left(), @@ -350,8 +350,7 @@ extern int txdlgbox (int maxlines, int ncols, int begin_y, int begin_x, multibyte characters may be split over two lines. This function returns the actual number of lines used (from 0 to - maxlines), or -1 on error (with errno set to EINVAL for an invalid - format conversion specifier or argument). + maxlines). If an error is detected, the application terminates. */ extern int prepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, chtype attr_alt1, chtype attr_alt2, int maxlines, @@ -372,7 +371,7 @@ extern int prepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, widthbufsize - Number of int elements in widthbuf format - Format string as described for prepstr() args - Variable argument list - Returns: int - Number of lines actually used, or -1 on error + Returns: int - Number of lines actually used This function is exactly the same as prepstr(), except that it is called with a va_list parameter args instead of a variable number of From 5bb48fe35fcbd2f06492b46869279312159b11c7 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Sat, 13 Aug 2011 08:50:34 +1000 Subject: [PATCH 030/112] Add wrapper functions xmalloc() and xstrdup() to do error handling --- src/exch.c | 15 ++------ src/fileio.c | 44 +++++------------------ src/game.c | 18 +++------- src/intf.c | 99 ++++++++++++---------------------------------------- src/move.c | 14 ++------ src/utils.c | 79 ++++++++++++++++++++++++++++++----------- src/utils.h | 28 +++++++++++++++ 7 files changed, 127 insertions(+), 170 deletions(-) diff --git a/src/exch.c b/src/exch.c index c623e95..5666742 100644 --- a/src/exch.c +++ b/src/exch.c @@ -108,10 +108,7 @@ void exchange_stock (void) if (all_off_map) { center(curwin, 8, attr_normal, "No companies on the map"); } else { - char *buf = malloc(BUFSIZE); - if (buf == NULL) { - err_exit_nomem(); - } + char *buf = xmalloc(BUFSIZE); // Handle the locale's currency symbol snprintf(buf, BUFSIZE, "share (%s)", lconvinfo.currency_symbol); @@ -256,10 +253,7 @@ void visit_bank (void) char *buf; - buf = malloc(BUFSIZE); - if (buf == NULL) { - err_exit_nomem(); - } + buf = xmalloc(BUFSIZE); credit_limit = (total_value(current_player) - player[current_player].debt) * CREDIT_LIMIT_RATE; @@ -470,10 +464,7 @@ void trade_shares (int num, bool *bid_used) assert(num >= 0 && num < MAX_COMPANIES); assert(company[num].on_map); - buf = malloc(BUFSIZE); - if (buf == NULL) { - err_exit_nomem(); - } + buf = xmalloc(BUFSIZE); ownership = (company[num].stock_issued == 0) ? 0.0 : ((double) player[current_player].stock_owned[num] diff --git a/src/fileio.c b/src/fileio.c index bcf41b6..297a4ee 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -107,11 +107,7 @@ static const unsigned char game_file_crypt_key[] = { } \ } \ } else { \ - s = malloc(strlen(buf) + 1); \ - if (s == NULL) { \ - err_exit_nomem(); \ - } \ - strcpy(s, buf); \ + s = xstrdup(buf); \ } \ \ len = strlen(s); \ @@ -137,11 +133,7 @@ static const unsigned char game_file_crypt_key[] = { filename, lineno); \ } \ \ - s = malloc(strlen(buf) + 1); \ - if (s == NULL) { \ - err_exit_nomem(); \ - } \ - strcpy(s, buf); \ + s = xstrdup(buf); \ \ len = strlen(s); \ if (len > 0 && s[len - 1] == '\n') { \ @@ -226,10 +218,7 @@ bool load_game (int num) assert(num >= 1 && num <= 9); - buf = malloc(BUFSIZE); - if (buf == NULL) { - err_exit_nomem(); - } + buf = xmalloc(BUFSIZE); filename = game_filename(num); assert(filename != NULL); @@ -275,29 +264,20 @@ bool load_game (int num) } else { icd = (iconv_t) -1; } - codeset_nl = strdup(GAME_FILE_CHARSET "\n"); - if (codeset_nl == NULL) { - err_exit_nomem(); - } + codeset_nl = xstrdup(GAME_FILE_CHARSET "\n"); #else // ! USE_UTF8_GAME_FILE // Make sure all strings are read in the correct codeset codeset = nl_langinfo(CODESET); if (codeset == NULL) { errno_exit("nl_langinfo(CODESET)"); } - codeset_nl = malloc(strlen(codeset) + 2); - if (codeset_nl == NULL) { - err_exit_nomem(); - } + codeset_nl = xmalloc(strlen(codeset) + 2); strcpy(codeset_nl, codeset); strcat(codeset_nl, "\n"); #endif // ! USE_UTF8_GAME_FILE // Change the formatting of numbers to the POSIX locale for consistency - prev_locale = strdup(setlocale(LC_NUMERIC, NULL)); - if (prev_locale == NULL) { - err_exit_nomem(); - } + prev_locale = xstrdup(setlocale(LC_NUMERIC, NULL)); setlocale(LC_NUMERIC, "C"); // Read the game file header @@ -355,7 +335,7 @@ bool load_game (int num) // Read in company data for (i = 0; i < MAX_COMPANIES; i++) { - company[i].name = strdup(gettext(company_name[i])); + company[i].name = xstrdup(gettext(company_name[i])); load_game_read_double(company[i].share_price, company[i].share_price >= 0.0); load_game_read_double(company[i].share_return, true); load_game_read_long(company[i].stock_issued, company[i].stock_issued >= 0); @@ -432,10 +412,7 @@ bool save_game (int num) assert(num >= 1 && num <= 9); - buf = malloc(BUFSIZE); - if (buf == NULL) { - err_exit_nomem(); - } + buf = xmalloc(BUFSIZE); crypt_key = option_dont_encrypt ? 0 : game_file_crypt_key[randi(GAME_FILE_CRYPT_KEY_SIZE)]; @@ -508,10 +485,7 @@ bool save_game (int num) #endif // ! USE_UTF8_GAME_FILE // Change the formatting of numbers to the POSIX locale for consistency - prev_locale = strdup(setlocale(LC_NUMERIC, NULL)); - if (prev_locale == NULL) { - err_exit_nomem(); - } + prev_locale = xstrdup(setlocale(LC_NUMERIC, NULL)); setlocale(LC_NUMERIC, "C"); // Write out the game file header and encryption key diff --git a/src/game.c b/src/game.c index a56d1c4..41d06f7 100644 --- a/src/game.c +++ b/src/game.c @@ -178,7 +178,7 @@ void init_game (void) // Initialise company data for (i = 0; i < MAX_COMPANIES; i++) { - company[i].name = strdup(gettext(company_name[i])); + company[i].name = xstrdup(gettext(company_name[i])); company[i].share_price = 0.0; company[i].share_return = INITIAL_RETURN; company[i].stock_issued = 0; @@ -489,10 +489,7 @@ void end_game (void) return; } - buf = malloc(BUFSIZE); - if (buf == NULL) { - err_exit_nomem(); - } + buf = xmalloc(BUFSIZE); txdlgbox(MAX_DLG_LINES, 50, 9, WCENTER, attr_error_window, attr_error_title, attr_error_highlight, 0, 0, @@ -577,11 +574,7 @@ void show_map (bool closewin) if (turn_number != max_turn) { const char *initial = "Turn: "; - - char *buf = malloc(BUFSIZE); - if (buf == NULL) { - err_exit_nomem(); - } + char *buf = xmalloc(BUFSIZE); int len1 = strlen(initial); int len2 = snprintf(buf, BUFSIZE, "%d", turn_number); @@ -671,10 +664,7 @@ void show_status (int num) center(curwin, 11, attr_blink, "* * * B A N K R U P T * * *"); } else { - char *buf = malloc(BUFSIZE); - if (buf == NULL) { - err_exit_nomem(); - } + char *buf = xmalloc(BUFSIZE); // Check to see if any companies are on the map bool none = true; diff --git a/src/intf.c b/src/intf.c index d0ef68c..b3e4493 100644 --- a/src/intf.c +++ b/src/intf.c @@ -384,14 +384,9 @@ void init_title (void) addch(attr_game_title | ' '); } - chbuf = malloc(BUFSIZE * sizeof(chtype)); - if (chbuf == NULL) { - err_exit_nomem(); - } - + chbuf = xmalloc(BUFSIZE * sizeof(chtype)); lines = prepstr(chbuf, BUFSIZE, attr_game_title, 0, 0, 1, COLS, &width, 1, _("Star Traders")); - pr_center(stdscr, 0, 0, chbuf, lines, &width); attrset(attr_root_window); free(chbuf); @@ -451,13 +446,9 @@ WINDOW *newtxwin (int nlines, int ncols, int begin_y, int begin_x, err_exit_nomem(); } - nw = malloc(sizeof(txwin_t)); - if (nw == NULL) { - err_exit_nomem(); - } - // Insert the new window into the txwin stack + nw = xmalloc(sizeof(txwin_t)); nw->win = win; nw->next = NULL; nw->prev = topwin; @@ -586,15 +577,8 @@ int txdlgbox (int maxlines, int ncols, int begin_y, int begin_x, assert(maxlines > 0); - chbuf = malloc(BUFSIZE * sizeof(chtype)); - if (chbuf == NULL) { - err_exit_nomem(); - } - - widthbuf = malloc(maxlines * sizeof(int)); - if (widthbuf == NULL) { - err_exit_nomem(); - } + chbuf = xmalloc(BUFSIZE * sizeof(chtype)); + widthbuf = xmalloc(maxlines * sizeof(int)); va_start(args, format); lines = vprepstr(chbuf, BUFSIZE, norm_attr, alt1_attr, alt2_attr, maxlines, @@ -605,15 +589,10 @@ int txdlgbox (int maxlines, int ncols, int begin_y, int begin_x, true, bkgd_attr); if (usetitle) { - chtype *titlebuf; + chtype *titlebuf = xmalloc(BUFSIZE * sizeof(chtype)); int titlewidth; int titlelines; - titlebuf = malloc(BUFSIZE * sizeof(chtype)); - if (titlebuf == NULL) { - err_exit_nomem(); - } - titlelines = prepstr(titlebuf, BUFSIZE, title_attr, 0, 0, 1, ncols - 4, &titlewidth, 1, boxtitle); pr_center(curwin, 1, 0, titlebuf, titlelines, &titlewidth); @@ -995,10 +974,7 @@ int vprepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, int count = 0; const char *str; - char *buf = malloc(BUFSIZE); - if (buf == NULL) { - err_exit_nomem(); - } + char *buf = xmalloc(BUFSIZE); while (inspec && *format != '\0') { char c = *format++; @@ -1215,11 +1191,7 @@ chtype *chbufdup (const chtype *restrict chbuf, int chbufsize) for (len = 1, p = chbuf; *p != '\0' && len <= chbufsize; p++, len++) ; - ret = malloc(len * sizeof(chtype)); - if (ret == NULL) { - err_exit_nomem(); - } - + ret = xmalloc(len * sizeof(chtype)); memcpy(ret, chbuf, len * sizeof(chtype)); ret[len - 1] = '\0'; // Terminating NUL, just in case not present @@ -1358,10 +1330,7 @@ int center (WINDOW *win, int y, chtype attr, const char *restrict format, ...) assert(win != NULL); assert(format != NULL); - buf = malloc(BUFSIZE); - if (buf == NULL) { - err_exit_nomem(); - } + buf = xmalloc(BUFSIZE); chtype oldattr = getattrs(win); chtype oldbkgd = getbkgd(win); @@ -1406,10 +1375,7 @@ int center2 (WINDOW *win, int y, chtype attr1, chtype attr2, assert(initial != NULL); assert(format != NULL); - buf = malloc(BUFSIZE); - if (buf == NULL) { - err_exit_nomem(); - } + buf = xmalloc(BUFSIZE); chtype oldattr = getattrs(win); chtype oldbkgd = getbkgd(win); @@ -1460,10 +1426,7 @@ int center3 (WINDOW *win, int y, chtype attr1, chtype attr3, chtype attr2, assert(final != NULL); assert(format != NULL); - buf = malloc(BUFSIZE); - if (buf == NULL) { - err_exit_nomem(); - } + buf = xmalloc(BUFSIZE); chtype oldattr = getattrs(win); chtype oldbkgd = getbkgd(win); @@ -2191,11 +2154,7 @@ int gettxstr (WINDOW *win, char **bufptr, bool *restrict modified, // Allocate the result buffer if needed if (*bufptr == NULL) { - *bufptr = malloc(BUFSIZE); - if (*bufptr == NULL) { - err_exit_nomem(); - } - + *bufptr = xmalloc(BUFSIZE); **bufptr = '\0'; } @@ -2275,16 +2234,11 @@ int gettxdouble (WINDOW *win, double *restrict result, double min, assert(result != NULL); assert(min <= max); - buf = malloc(BUFSIZE); - bufcopy = malloc(BUFSIZE); - allowed = malloc(BUFSIZE); - emptystr = malloc(BUFSIZE); - defaultstr = malloc(BUFSIZE); - - if (buf == NULL || bufcopy == NULL || allowed == NULL - || emptystr == NULL || defaultstr == NULL) { - err_exit_nomem(); - } + buf = xmalloc(BUFSIZE); + bufcopy = xmalloc(BUFSIZE); + allowed = xmalloc(BUFSIZE); + emptystr = xmalloc(BUFSIZE); + defaultstr = xmalloc(BUFSIZE); *buf = '\0'; @@ -2348,16 +2302,11 @@ int gettxlong (WINDOW *win, long int *restrict result, long int min, assert(result != NULL); assert(min <= max); - buf = malloc(BUFSIZE); - bufcopy = malloc(BUFSIZE); - allowed = malloc(BUFSIZE); - emptystr = malloc(BUFSIZE); - defaultstr = malloc(BUFSIZE); - - if (buf == NULL || bufcopy == NULL || allowed == NULL - || emptystr == NULL || defaultstr == NULL) { - err_exit_nomem(); - } + buf = xmalloc(BUFSIZE); + bufcopy = xmalloc(BUFSIZE); + allowed = xmalloc(BUFSIZE); + emptystr = xmalloc(BUFSIZE); + defaultstr = xmalloc(BUFSIZE); *buf = '\0'; @@ -2481,11 +2430,7 @@ void wait_for_key (WINDOW *win, int y, chtype attr) meta(win, true); wtimeout(win, -1); - chbuf = malloc(BUFSIZE * sizeof(chtype)); - if (chbuf == NULL) { - err_exit_nomem(); - } - + chbuf = xmalloc(BUFSIZE * sizeof(chtype)); lines = prepstr(chbuf, BUFSIZE, attr, 0, 0, 1, getmaxx(win) - 4, &width, 1, _("[ Press to continue ] ")); pr_center(win, y, 0, chbuf, lines, &width); diff --git a/src/move.c b/src/move.c index 49f3aa9..98fc17e 100644 --- a/src/move.c +++ b/src/move.c @@ -746,14 +746,9 @@ void merge_companies (map_val_t a, map_val_t b) long int old_stock, new_stock, total_new; int x, y, i, line; double bonus; - char *buf; + char *buf = xmalloc(BUFSIZE); - buf = malloc(BUFSIZE); - if (buf == NULL) { - err_exit_nomem(); - } - if (val_aa < val_bb) { // Make sure aa is the dominant company map_val_t t; @@ -930,12 +925,7 @@ void adjust_values (void) } else { double rate = randf(); - char *buf; - - buf = malloc(BUFSIZE); - if (buf == NULL) { - err_exit_nomem(); - } + char *buf = xmalloc(BUFSIZE); for (i = 0; i < number_players; i++) { if (player[i].in_game) { diff --git a/src/utils.c b/src/utils.c index 9c2ecd1..d106c72 100644 --- a/src/utils.c +++ b/src/utils.c @@ -114,7 +114,7 @@ const char *home_directory (void) char *home = getenv("HOME"); if (home != NULL && *home != '\0') { - home_directory_str = strdup(home); + home_directory_str = xstrdup(home); } } @@ -136,13 +136,12 @@ const char *data_directory (void) const char *home = home_directory(); if (name != NULL && home != NULL) { - char *p = malloc(strlen(home) + strlen(name) + 3); - if (p != NULL) { - strcpy(p, home); - strcat(p, "/."); - strcat(p, name); - data_directory_str = p; - } + char *p = xmalloc(strlen(home) + strlen(name) + 3); + + strcpy(p, home); + strcat(p, "/."); + strcat(p, name); + data_directory_str = p; } } @@ -170,20 +169,13 @@ char *game_filename (int gamenum) snprintf(buf, GAME_FILENAME_BUFSIZE, GAME_FILENAME_PROTO, gamenum); if (dd == NULL) { - char *p = malloc(strlen(buf) + 1); - - if (p != NULL) { - strcpy(p, buf); - } - return p; + return xstrdup(buf); } else { - char *p = malloc(strlen(dd) + strlen(buf) + 2); + char *p = xmalloc(strlen(dd) + strlen(buf) + 2); - if (p != NULL) { - strcpy(p, dd); - strcat(p, "/"); - strcat(p, buf); - } + strcpy(p, dd); + strcat(p, "/"); + strcat(p, buf); return p; } } @@ -439,5 +431,52 @@ char *unscramble (int key, char *restrict buf, int bufsize) } +/************************************************************************ +* Miscellaneous function definitions * +************************************************************************/ + +// These functions are documented in the file "utils.h" + + +/***********************************************************************/ +// xmalloc: Allocate a new block of memory, with checking + +void *xmalloc (size_t size) +{ + void *p; + + + if (size < 1) + size = 1; + + p = malloc(size); + if (p == NULL) { + err_exit_nomem(); + } + + return p; +} + + +/***********************************************************************/ +// xstrdup: Duplicate a string, with checking + +char *xstrdup (const char *str) +{ + char *s; + + + if (str == NULL) + str = ""; + + s = strdup(str); + if (s == NULL) { + err_exit_nomem(); + } + + return s; +} + + /***********************************************************************/ // End of file diff --git a/src/utils.h b/src/utils.h index 70f717a..4c9aabe 100644 --- a/src/utils.h +++ b/src/utils.h @@ -300,4 +300,32 @@ extern char *scramble (int key, char *restrict buf, int bufsize); extern char *unscramble (int key, char *restrict buf, int bufsize); +/************************************************************************ +* Miscellaneous function prototypes * +************************************************************************/ + +/* + Function: xmalloc - Allocate a new block of memory, with checking + Parameters: size - Size of new block of memory in bytes + Returns: void * - Pointer to new block of memory + + This wrapper function allocates a new block of memory by calling + malloc(), then checks if a NULL pointer has been returned. If so, the + program terminates with an "Out of memory" error. +*/ +extern void *xmalloc (size_t size); + + +/* + Function: xstrdup - Duplicate a string, with checking + Parameters: str - String to duplicate + Returns: char * - Pointer to new string, allocated with malloc() + + This wrapper function duplicates a string by calling strdup(), then + checks if a NULL pointer has been returned. If so, the program + terminates with an "Out of memory" error. +*/ +extern char *xstrdup (const char *str); + + #endif /* included_UTILS_H */ From 746155078b7ccc66ad3216ac36fbdb3f34da0ec4 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Mon, 15 Aug 2011 10:08:44 +1000 Subject: [PATCH 031/112] Continue to move text output to the new interfaces --- src/game.c | 182 +++++++++++++++++++++++++++++++---------------------- src/help.c | 53 ++++++++++++++-- src/intf.c | 8 +-- src/intf.h | 18 +++--- src/move.c | 51 +++++++++------ 5 files changed, 196 insertions(+), 116 deletions(-) diff --git a/src/game.c b/src/game.c index 41d06f7..8c8b085 100644 --- a/src/game.c +++ b/src/game.c @@ -110,14 +110,21 @@ void init_game (void) { // Try to load an old game, if possible if (game_num != 0) { - newtxwin(5, 30, 6, WCENTER, true, attr_status_window); - center(curwin, 2, attr_status_window, "Loading game %d... ", game_num); + chtype *chbuf = xmalloc(BUFSIZE * sizeof(chtype)); + int lines, width; + + lines = prepstr(chbuf, BUFSIZE, attr_status_window, 0, 0, 1, + WIN_COLS - 7, &width, 1, + "Loading game %d... ", game_num); + newtxwin(5, width + 5, 6, WCENTER, true, attr_status_window); + pr_center(curwin, 2, 0, chbuf, 1, &width); wrefresh(curwin); game_loaded = load_game(game_num); deltxwin(); txrefresh(); + free(chbuf); } // Initialise game data, if not already loaded @@ -134,18 +141,25 @@ void init_game (void) choice = ask_game_number(); if (choice != ERR) { + // Try to load the game, if possible + + chtype *chbuf = xmalloc(BUFSIZE * sizeof(chtype)); + int lines, width; + game_num = choice; - // Try to load the game, if possible - newtxwin(5, 30, 9, WCENTER, true, attr_status_window); - center(curwin, 2, attr_status_window, - "Loading game %d... ", game_num); + lines = prepstr(chbuf, BUFSIZE, attr_status_window, + 0, 0, 1, WIN_COLS - 7, &width, 1, + "Loading game %d... ", game_num); + newtxwin(5, width + 5, 9, WCENTER, true, attr_status_window); + pr_center(curwin, 2, 0, chbuf, 1, &width); wrefresh(curwin); game_loaded = load_game(game_num); deltxwin(); txrefresh(); + free(chbuf); } deltxwin(); // "Enter game number" window @@ -227,22 +241,24 @@ void init_game (void) static int ask_number_players (void) { + chtype *chbuf; + int lines, maxwidth; + int widthbuf[2]; int key, ret; bool done; - // Ask for the number of players - newtxwin(5, 62, 3, WCENTER, true, attr_normal_window); + chbuf = xmalloc(BUFSIZE * sizeof(chtype)); + lines = prepstr(chbuf, BUFSIZE, attr_normal, attr_keycode, 0, + sizeof(widthbuf) / sizeof(widthbuf[0]), WIN_COLS - 7, + widthbuf, sizeof(widthbuf) / sizeof(widthbuf[0]), + "Enter number of players [^{1^}-^{%d^}] " + "or ^{^} to continue a game: ", MAX_PLAYERS); + maxwidth = MAX(widthbuf[0], widthbuf[1]) + 5; - mvwaddstr(curwin, 2, 2, "Enter number of players "); - waddstr(curwin, "["); - attrpr(curwin, attr_keycode, "1"); - waddstr(curwin, "-"); - attrpr(curwin, attr_keycode, "%d", MAX_PLAYERS); - waddstr(curwin, "]"); - waddstr(curwin, " or "); - attrpr(curwin, attr_keycode, ""); - waddstr(curwin, " to continue a game: "); + newtxwin(lines + 4, maxwidth, 3, WCENTER, true, attr_normal_window); + pr_left(curwin, 2, 2, chbuf, lines, widthbuf); + free(chbuf); curs_set(CURS_ON); wrefresh(curwin); @@ -289,22 +305,24 @@ static int ask_number_players (void) int ask_game_number (void) { + chtype *chbuf; + int lines, maxwidth; + int widthbuf[2]; int key, ret; bool done; - // Ask which game to load - newtxwin(5, 54, 6, WCENTER, true, attr_normal_window); + chbuf = xmalloc(BUFSIZE * sizeof(chtype)); + lines = prepstr(chbuf, BUFSIZE, attr_normal, attr_keycode, 0, + sizeof(widthbuf) / sizeof(widthbuf[0]), WIN_COLS - 7, + widthbuf, sizeof(widthbuf) / sizeof(widthbuf[0]), + "Enter game number [^{1^}-^{9^}] " + "or ^{^} to cancel: "); + maxwidth = MAX(widthbuf[0], widthbuf[1]) + 5; - mvwaddstr(curwin, 2, 2, "Enter game number "); - waddstr(curwin, "["); - attrpr(curwin, attr_keycode, "1"); - waddstr(curwin, "-"); - attrpr(curwin, attr_keycode, "9"); - waddstr(curwin, "]"); - waddstr(curwin, " or "); - attrpr(curwin, attr_keycode, ""); - waddstr(curwin, " to cancel: "); + newtxwin(lines + 4, maxwidth, 6, WCENTER, true, attr_normal_window); + pr_left(curwin, 2, 2, chbuf, lines, widthbuf); + free(chbuf); curs_set(CURS_ON); wrefresh(curwin); @@ -349,7 +367,6 @@ void ask_player_names (void) // Ask for the player's name newtxwin(5, WIN_COLS - 4, 9, WCENTER, true, attr_normal_window); - mvwaddstr(curwin, 2, 2, "Please enter your name: "); int x = getcurx(curwin); @@ -366,23 +383,35 @@ void ask_player_names (void) } } - newtxwin(5, 44, 6, WCENTER, true, attr_normal_window); - mvwaddstr(curwin, 2, 2, "Do you need any instructions?"); - if (answer_yesno(curwin, attr_keycode)) { + chtype *chbuf = xmalloc(BUFSIZE * sizeof(chtype)); + int lines, width; + + lines = prepstr(chbuf, BUFSIZE, attr_normal, attr_keycode, 0, + 1, WIN_COLS - YESNO_COLS - 6, &width, 1, + "Do you need any instructions? [^{Y^}/^{N^}] "); + newtxwin(5, width + YESNO_COLS + 4, 6, WCENTER, true, + attr_normal_window); + pr_left(curwin, 2, 2, chbuf, lines, &width); + free(chbuf); + if (answer_yesno(curwin)) { show_help(); } } else { // Ask for all of the player names + chtype *chbuf = xmalloc(BUFSIZE * sizeof(chtype)); + int lines, width; + bool entered[MAX_PLAYERS]; bool done, modified; int cur, len, i; newtxwin(number_players + 5, WIN_COLS - 4, 9, WCENTER, true, attr_normal_window); - - center(curwin, 1, attr_title, " Enter Player Names "); + lines = prepstr(chbuf, BUFSIZE, attr_title, 0, 0, 1, WIN_COLS - 8, + &width, 1, " Enter Player Names "); + pr_center(curwin, 1, 0, chbuf, lines, &width); for (i = 0; i < number_players; i++) { player[i].name = NULL; @@ -463,11 +492,17 @@ void ask_player_names (void) } } - newtxwin(5, 50, 6, WCENTER, true, attr_normal_window); - mvwaddstr(curwin, 2, 2, "Does any player need instructions?"); - if (answer_yesno(curwin, attr_keycode)) { + lines = prepstr(chbuf, BUFSIZE, attr_normal, attr_keycode, 0, + 1, WIN_COLS - YESNO_COLS - 6, &width, 1, + "Does any player need instructions? [^{Y^}/^{N^}] "); + newtxwin(5, width + YESNO_COLS + 4, 6, WCENTER, true, + attr_normal_window); + pr_left(curwin, 2, 2, chbuf, lines, &width); + if (answer_yesno(curwin)) { show_help(); } + + free(chbuf); } deltxwin(); // "Need instructions?" window @@ -552,48 +587,30 @@ void end_game (void) void show_map (bool closewin) { - int n, x, y; + chtype *chbuf = xmalloc(BUFSIZE * sizeof(chtype)); + int lines, width; + int x, y; newtxwin(MAX_Y + 4, WIN_COLS, 1, WCENTER, true, attr_map_window); - // Draw various borders + // Draw various borders and highlights mvwaddch(curwin, 2, 0, ACS_LTEE); whline(curwin, ACS_HLINE, getmaxx(curwin) - 2); mvwaddch(curwin, 2, getmaxx(curwin) - 1, ACS_RTEE); + mvwhline(curwin, 1, 2, ' ' | attr_mapwin_title, getmaxx(curwin) - 4); // Display current player and turn number - wattrset(curwin, attr_mapwin_title); - mvwaddstr(curwin, 1, 2, " "); - waddstr(curwin, "Player: "); - n = getmaxx(curwin) - getcurx(curwin) - 4; - wattrset(curwin, attr_mapwin_highlight); - wprintw(curwin, "%-*.*s", n, n, player[current_player].name); - wattrset(curwin, attr_mapwin_title); - waddstr(curwin, " "); + lines = prepstr(chbuf, BUFSIZE, attr_mapwin_title, attr_mapwin_highlight, + 0, 1, WIN_COLS - 4, &width, 1, " Player: ^{%s^} ", + player[current_player].name); + pr_left(curwin, 1, 2, chbuf, lines, &width); - if (turn_number != max_turn) { - const char *initial = "Turn: "; - char *buf = xmalloc(BUFSIZE); - - int len1 = strlen(initial); - int len2 = snprintf(buf, BUFSIZE, "%d", turn_number); - - mvwaddstr(curwin, 1, getmaxx(curwin) - (len1 + len2) - 6, " "); - waddstr(curwin, initial); - attrpr(curwin, attr_mapwin_highlight, "%s", buf); - waddstr(curwin, " "); - - free(buf); - - } else { - const char *buf = "*** Last Turn ***"; - int len = strlen(buf); - - mvwaddstr(curwin, 1, getmaxx(curwin) - len - 6, " "); - attrpr(curwin, attr_mapwin_blink, "%s", buf); - waddstr(curwin, " "); - } + lines = prepstr(chbuf, BUFSIZE, attr_mapwin_title, attr_mapwin_highlight, + attr_mapwin_blink, 1, WIN_COLS / 2, &width, 1, + (turn_number != max_turn) ? " Turn: ^{%d^} " : + " ^[*** Last Turn ***^] ", turn_number); + pr_right(curwin, 1, WIN_COLS - 2, chbuf, lines, &width); wattrset(curwin, attr_map_window); @@ -638,6 +655,8 @@ void show_map (bool closewin) deltxwin(); // Galaxy map window txrefresh(); } + + free(chbuf); } @@ -646,6 +665,8 @@ void show_map (bool closewin) void show_status (int num) { + chtype *chbuf; + int lines, width; double val; int i, line; @@ -655,13 +676,22 @@ void show_status (int num) newtxwin(MAX_COMPANIES + 15, WIN_COLS, 1, WCENTER, true, attr_normal_window); - center(curwin, 1, attr_title, " Stock Portfolio "); - center2(curwin, 2, attr_normal, attr_highlight, "Player: ", "%s", - player[num].name); + chbuf = xmalloc(BUFSIZE * sizeof(chtype)); + lines = prepstr(chbuf, BUFSIZE, attr_title, 0, 0, 1, WIN_COLS - 4, + &width, 1, " Stock Portfolio "); + pr_center(curwin, 1, 0, chbuf, lines, &width); + + lines = prepstr(chbuf, BUFSIZE, attr_normal, attr_highlight, 0, 1, + WIN_COLS - 4, &width, 1, "Player: ^{%s^}", + player[num].name); + pr_center(curwin, 2, 0, chbuf, lines, &width); val = total_value(num); if (val == 0.0) { - center(curwin, 11, attr_blink, "* * * B A N K R U P T * * *"); + lines = prepstr(chbuf, BUFSIZE, attr_normal, attr_highlight, + attr_blink, 1, WIN_COLS - 4, &width, 1, + "^[* * * B A N K R U P T * * *^]"); + pr_center(curwin, 11, 0, chbuf, lines, &width); } else { char *buf = xmalloc(BUFSIZE); @@ -676,7 +706,10 @@ void show_status (int num) } if (none) { - center(curwin, 8, attr_normal, "No companies on the map"); + lines = prepstr(chbuf, BUFSIZE, attr_normal, attr_highlight, 0, + 1, WIN_COLS - 4, &width, 1, + "No companies on the map"); + pr_center(curwin, 8, 0, chbuf, lines, &width); } else { // Handle the locale's currency symbol snprintf(buf, BUFSIZE, "share (%s)", lconvinfo.currency_symbol); @@ -726,6 +759,7 @@ void show_status (int num) wait_for_key(curwin, getmaxy(curwin) - 2, attr_waitforkey); deltxwin(); txrefresh(); + free(chbuf); } diff --git a/src/help.c b/src/help.c index 4f9a520..dd78cf5 100644 --- a/src/help.c +++ b/src/help.c @@ -157,17 +157,45 @@ static const char *help_text[] = { void show_help (void) { + chtype *chbuf = xmalloc(BUFSIZE * sizeof(chtype)); + int lines, width; + int curpage = 0; int numpages; bool done = false; + chtype *ch_title; // Title string + chtype *ch_contfirst; // "Continue", first page + chtype *ch_contnext; // "Continue", following pages + int w_title, ln_title; + int w_contfirst, ln_contfirst; + int w_contnext, ln_contnext; + // Count how many pages appear in the help text for (numpages = 0; help_text[numpages] != NULL; numpages++) ; - if (numpages == 0) + if (numpages == 0) { + free(chbuf); return; + } + + // Prepare fixed-text strings + ln_title = prepstr(chbuf, BUFSIZE, attr_title, 0, 0, 1, WIN_COLS - 4, + &w_title, 1, " How to Play "); + ch_title = chbufdup(chbuf, BUFSIZE); + + ln_contfirst = prepstr(chbuf, BUFSIZE, attr_waitforkey, 0, 0, 1, + WIN_COLS - 4, &w_contfirst, 1, + "[ Press to continue ] "); + ch_contfirst = chbufdup(chbuf, BUFSIZE); + + ln_contnext = prepstr(chbuf, BUFSIZE, attr_waitforkey, 0, 0, 1, + WIN_COLS - 4, &w_contnext, 1, + "[ Press to continue or " + " for the previous page ] "); + ch_contnext = chbufdup(chbuf, BUFSIZE); newtxwin(WIN_LINES - 1, WIN_COLS, 1, WCENTER, false, 0); @@ -177,8 +205,12 @@ void show_help (void) werase(curwin); wbkgd(curwin, attr_normal_window); box(curwin, 0, 0); - center(curwin, 1, attr_title, " How to Play "); - center(curwin, 2, attr_normal, "Page %d of %d", curpage + 1, numpages); + pr_center(curwin, 1, 0, ch_title, ln_title, &w_title); + + lines = prepstr(chbuf, BUFSIZE, attr_normal, attr_highlight, 0, 1, + WIN_COLS - 4, &width, 1, "Page %d of %d", + curpage + 1, numpages); + pr_center(curwin, 2, 0, chbuf, lines, &width); wmove(curwin, 4, 2); // Process the help text string @@ -323,9 +355,13 @@ void show_help (void) s++; } - center(curwin, 21, attr_waitforkey, (curpage == 0) ? - "[ Press to continue ] " : - "[ Press to continue or for the previous page ] "); + if (curpage == 0) { + pr_center(curwin, getmaxy(curwin) - 2, 0, ch_contfirst, + ln_contfirst, &w_contfirst); + } else { + pr_center(curwin, getmaxy(curwin) - 2, 0, ch_contnext, + ln_contnext, &w_contnext); + } wrefresh(curwin); @@ -363,4 +399,9 @@ void show_help (void) deltxwin(); txrefresh(); + + free(ch_title); + free(ch_contfirst); + free(ch_contnext); + free(chbuf); } diff --git a/src/intf.c b/src/intf.c index b3e4493..3d08ab0 100644 --- a/src/intf.c +++ b/src/intf.c @@ -2352,7 +2352,7 @@ int gettxlong (WINDOW *win, long int *restrict result, long int min, /***********************************************************************/ // answer_yesno: Wait for a Yes/No answer -bool answer_yesno (WINDOW *win, chtype attr_keys) +bool answer_yesno (WINDOW *win) { int key; bool done; @@ -2365,12 +2365,6 @@ bool answer_yesno (WINDOW *win, chtype attr_keys) meta(win, true); wtimeout(win, -1); - waddstr(curwin, " ["); - attrpr(curwin, attr_keys, "Y"); - waddstr(curwin, "/"); - attrpr(curwin, attr_keys, "N"); - waddstr(curwin, "] "); - curs_set(CURS_ON); done = false; diff --git a/src/intf.h b/src/intf.h index d5ef379..a06c394 100644 --- a/src/intf.h +++ b/src/intf.h @@ -53,9 +53,10 @@ #define WIN_LINES MIN_LINES // Number of lines used in main window #define WIN_COLS MIN_COLS // Number of columns used in main window -#define WCENTER -1 // Centre the new window +#define WCENTER -1 // Centre the new window -#define MAX_DLG_LINES 10 // Default maximum lines in dialog box +#define MAX_DLG_LINES 10 // Default maximum lines of text in dialog box +#define YESNO_COLS 4 // Space to allow for "Yes" or "No" response // Check if resizing events are supported @@ -728,17 +729,14 @@ extern int gettxlong (WINDOW *win, long int *restrict result, long int min, /* Function: answer_yesno - Wait for a Yes/No answer Parameters: win - Window to use (should be curwin) - attr_keys - Window rendition to use for key choices Returns: bool - True if Yes was selected, false if No - This function prompts the user by printing " [Y/N] " using appropriate - character renditions ("Y" and "N" in attr_keys, the rest in the current - rendition), then waits for the user to press either "Y" (for Yes) or - "N" (for No) on the keyboard, then prints the answer using A_BOLD. - True is returned if "Y" was selected, false if "N". Note that the - cursor becomes invisible after calling this function. + This function waits for the user to press either "Y" (for Yes) or "N" + (for No) on the keyboard, then prints the answer using A_BOLD. True is + returned if "Y" was selected, false if "N". Note that the cursor + becomes invisible after calling this function. */ -extern bool answer_yesno (WINDOW *win, chtype attr_keys); +extern bool answer_yesno (WINDOW *win); /* diff --git a/src/move.c b/src/move.c index 98fc17e..fcba6ef 100644 --- a/src/move.c +++ b/src/move.c @@ -207,7 +207,6 @@ void select_moves (void) selection_t get_move (void) { - int i, x, y; selection_t selection = SEL_NONE; @@ -219,7 +218,7 @@ selection_t get_move (void) show_map(false); // Display current move choices on the galaxy map - for (i = 0; i < NUMBER_MOVES; i++) { + for (int i = 0; i < NUMBER_MOVES; i++) { mvwaddch(curwin, game_move[i].y + 3, game_move[i].x * 2 + 2, MOVE_TO_KEY(i) | attr_map_choice); } @@ -324,18 +323,20 @@ selection_t get_move (void) } // Clear the menu choices (but not the prompt!) - wattrset(curwin, attr_normal); - for (y = 2; y < 4; y++) { - wmove(curwin, y, 2); - for (x = 2; x < getmaxx(curwin) - 2; x++) { - waddch(curwin, ' ' | attr_normal); - } - } - wrefresh(curwin); + mvwhline(curwin, 2, 2, ' ' | attr_normal, getmaxx(curwin) - 4); + mvwhline(curwin, 3, 2, ' ' | attr_normal, getmaxx(curwin) - 4); // Ask the player to confirm their choice - mvwaddstr(curwin, 2, 22, "Are you sure?"); - if (! answer_yesno(curwin, attr_keycode)) { + wattrset(curwin, attr_normal); + mvwaddstr(curwin, 2, 22, "Are you sure? "); + waddstr(curwin, "["); + attrpr(curwin, attr_keycode, "Y"); + waddstr(curwin, "/"); + attrpr(curwin, attr_keycode, "N"); + waddstr(curwin, "] "); + wrefresh(curwin); + + if (! answer_yesno(curwin)) { selection = SEL_NONE; } @@ -345,15 +346,21 @@ selection_t get_move (void) if (game_loaded) { // Save the game to the same game number - newtxwin(5, 30, 7, WCENTER, true, attr_status_window); - center(curwin, 2, attr_status_window, - "Saving game %d... ", game_num); + chtype *chbuf = xmalloc(BUFSIZE * sizeof(chtype)); + int lines, width; + + lines = prepstr(chbuf, BUFSIZE, attr_status_window, 0, 0, 1, + WIN_COLS - 7, &width, 1, + "Saving game %d... ", game_num); + newtxwin(5, width + 5, 7, WCENTER, true, attr_status_window); + pr_center(curwin, 2, 0, chbuf, 1, &width); wrefresh(curwin); saved = save_game(game_num); deltxwin(); txrefresh(); + free(chbuf); } if (! saved) { @@ -405,18 +412,24 @@ selection_t get_move (void) curs_set(CURS_OFF); if (key != KEY_CANCEL) { + // Try to save the game, if possible + chtype *chbuf = xmalloc(BUFSIZE * sizeof(chtype)); + int lines, width; + game_num = key - '0'; - // Try to save the game, if possible - newtxwin(5, 30, 7, WCENTER, true, attr_status_window); - center(curwin, 2, attr_status_window, - "Saving game %d... ", game_num); + lines = prepstr(chbuf, BUFSIZE, attr_status_window, + 0, 0, 1, WIN_COLS - 7, &width, 1, + "Saving game %d... ", game_num); + newtxwin(5, width + 5, 7, WCENTER, true, attr_status_window); + pr_center(curwin, 2, 0, chbuf, 1, &width); wrefresh(curwin); saved = save_game(game_num); deltxwin(); txrefresh(); + free(chbuf); } deltxwin(); // "Enter game number" window From 3ad62688da04862edf507f169559cc35718333bc Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Mon, 15 Aug 2011 15:53:56 +1000 Subject: [PATCH 032/112] Do parse of format string in prepstr_parse(); add the "%c" specifier --- src/intf.c | 476 ++++++++++++++++++++++++++++------------------------- src/intf.h | 6 +- 2 files changed, 254 insertions(+), 228 deletions(-) diff --git a/src/intf.c b/src/intf.c index 3d08ab0..53a6909 100644 --- a/src/intf.c +++ b/src/intf.c @@ -48,6 +48,7 @@ typedef struct txwin { enum argument_type { TYPE_NONE, // No type yet assigned + TYPE_CHAR, // char TYPE_INT, // int TYPE_LONGINT, // long int TYPE_DOUBLE, // double @@ -57,6 +58,7 @@ enum argument_type { struct argument { enum argument_type a_type; union a { + char a_char; int a_int; long int a_longint; double a_double; @@ -65,6 +67,18 @@ struct argument { }; +#define MAXFMTSPECS 16 // Maximum number of conversion specifiers + +struct convspec { + int len; // Length of conversion specifier, 0 = unused + int arg_num; // Which variable argument to use + char spec; // Conversion specifier: c d N s + bool flag_group; // Flag "'" (thousands grouping) + bool flag_nosym; // Flag "!" (omit currency symbol) + bool flag_long; // Length modifier "l" (long) +}; + + /************************************************************************ * Global variable definitions * ************************************************************************/ @@ -189,6 +203,23 @@ static int prepstr_addch (chtype *restrict *restrict chbuf, const char *restrict *restrict str); +/* + Function: prepstr_parse - Parse the format string for prepstr() + Parameters: format - Format string as described for prepstr() + format_arg - Pointer to variable arguments array + format_spec - Pointer to conversion specifiers array + args - Variable argument list passed to prepstr() + Returns: int - 0 if OK, -1 if error (with errno set) + + This helper function parses the format string passed to prepstr(), + setting the format_arg and format_spec arrays appropriately. +*/ +static int prepstr_parse (const char *restrict format, + struct argument *restrict format_arg, + struct convspec *restrict format_spec, + va_list args); + + /* Function: txinput_fixup - Copy strings with fixup Parameters: dest - Destination buffer of size BUFSIZE @@ -716,48 +747,29 @@ int prepstr_addch (chtype *restrict *restrict chbuf, int *restrict chbufsize, /***********************************************************************/ -// vprepstr: Prepare a string for printing to screen +// prepstr_parse: Parse the format string for prepstr() -int vprepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, - chtype attr_alt1, chtype attr_alt2, int maxlines, int maxwidth, - int *restrict widthbuf, int widthbufsize, - const char *restrict format, va_list args) +int prepstr_parse (const char *restrict format, + struct argument *restrict format_arg, + struct convspec *restrict format_spec, va_list args) { - struct argument format_arg[MAXFMTARGS]; - int num_format_args, arg_num; - const char *orig_format; - int line, width; - chtype *lastspc; - int widthspc; - chtype curattr; - int saved_errno; + int num_args = 0; // 0 .. MAXFMTARGS + int arg_num = 0; // Current index into format_arg[] + int specs_left = MAXFMTSPECS; // MAXFMTSPECS .. 0 (counting down) - assert(chbuf != NULL); - assert(chbufsize > 0); - assert(maxlines > 0); - assert(maxwidth > 0); - assert(widthbuf != NULL); - assert(widthbufsize >= maxlines); - assert(format != NULL); - - /* Do a preliminary scan through the format parameter to determine - the types of each positional argument (conversion specifier). If - we did not support "%m$"-style specifiers, this would not be - necessary. */ - - orig_format = format; - memset(format_arg, 0, sizeof(format_arg)); - num_format_args = 0; - arg_num = 0; + memset(format_arg, 0, MAXFMTARGS * sizeof(format_arg[0])); + memset(format_spec, 0, MAXFMTSPECS * sizeof(format_spec[0])); while (*format != '\0') { switch (*format++) { case '^': // Switch to a different character rendition if (*format == '\0') { - goto error_inval; + errno = EINVAL; + return -1; } else { + // Ignore next character for now format++; } break; @@ -765,14 +777,17 @@ int vprepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, case '%': // Process a conversion specifier if (*format == '\0') { - goto error_inval; + errno = EINVAL; + return -1; } else if (*format == '%') { + // Ignore "%%" specifier format++; } else { - enum argument_type arg_type = TYPE_NONE; + const char *start = format; + enum argument_type arg_type; bool inspec = true; - bool flag_posn = false; - bool flag_long = false; + bool flag_posn = false; // Have we already seen "$"? + bool flag_other = false; // Have we seen something else? int count = 0; while (inspec && *format != '\0') { @@ -780,8 +795,11 @@ int vprepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, switch (c) { case '0': // Zero flag, or part of numeric count - if (count == 0) - goto error_inval; + if (count == 0) { + // Zero flag is NOT supported + errno = EINVAL; + return -1; + } count *= 10; break; @@ -801,12 +819,14 @@ int vprepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, case '$': // Fixed-position argument - if (flag_posn || count == 0) - goto error_inval; + if (flag_posn || flag_other || count == 0) { + errno = EINVAL; + return -1; + } if (count > MAXFMTARGS) { errno = E2BIG; - goto error; + return -1; } flag_posn = true; @@ -815,61 +835,116 @@ int vprepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, break; case '\'': - // Use locale-specific thousands separator + // Use locale-specific thousands group separator + if (format_spec->flag_group) { + errno = EINVAL; + return -1; + } + + format_spec->flag_group = true; + flag_other = true; + break; + + case '!': + // Omit the locale-specific currency symbol + if (format_spec->flag_nosym) { + errno = EINVAL; + return -1; + } + + format_spec->flag_nosym = true; + flag_other = true; break; case 'l': // Long length modifier - if (flag_long) - goto error_inval; + if (format_spec->flag_long) { + // "ll" is NOT supported + errno = EINVAL; + return -1; + } - flag_long = true; + format_spec->flag_long = true; + flag_other = true; break; + case 'c': + // Insert a character (char) + if (format_spec->flag_group || format_spec->flag_nosym + || format_spec->flag_long || count != 0) { + errno = EINVAL; + return -1; + } + + arg_type = TYPE_CHAR; + goto handlefmt; + case 'd': // Insert an integer (int or long int) - arg_type = flag_long ? TYPE_LONGINT : TYPE_INT; + if (count != 0) { + errno = EINVAL; + return -1; + } + + arg_type = format_spec->flag_long ? + TYPE_LONGINT : TYPE_INT; goto handlefmt; case 'N': // Insert a monetary amount (double) - if (flag_long) - goto error_inval; + if (format_spec->flag_group || format_spec->flag_long + || count != 0) { + errno = EINVAL; + return -1; + } arg_type = TYPE_DOUBLE; goto handlefmt; case 's': // Insert a string (const char *) - if (flag_long) - goto error_inval; + if (format_spec->flag_group || format_spec->flag_nosym + || format_spec->flag_long || count != 0) { + errno = EINVAL; + return -1; + } arg_type = TYPE_STRING; handlefmt: - if (arg_num >= MAXFMTARGS) { + if (arg_num >= MAXFMTARGS || specs_left == 0) { errno = E2BIG; - goto error; + return -1; } if (format_arg[arg_num].a_type == TYPE_NONE) { format_arg[arg_num].a_type = arg_type; } else if (format_arg[arg_num].a_type != arg_type) { - goto error_inval; + errno = EINVAL; + return -1; } + format_spec->len = format - start; + format_spec->arg_num = arg_num; + format_spec->spec = c; + arg_num++; - num_format_args = MAX(num_format_args, arg_num); + num_args = MAX(num_args, arg_num); + + format_spec++; + specs_left--; inspec = false; break; default: - goto error_inval; + errno = EINVAL; + return -1; } } if (inspec) { - goto error_inval; + errno = EINVAL; + return -1; } } break; @@ -880,36 +955,73 @@ int vprepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, } } - for (int i = 0; i < num_format_args; i++) { - switch (format_arg[i].a_type) { + for (int i = 0; i < num_args; format_arg++, i++) { + switch (format_arg->a_type) { + case TYPE_CHAR: + format_arg->a.a_char = (char) va_arg(args, int); + break; + case TYPE_INT: - format_arg[i].a.a_int = va_arg(args, int); + format_arg->a.a_int = va_arg(args, int); break; case TYPE_LONGINT: - format_arg[i].a.a_longint = va_arg(args, long int); + format_arg->a.a_longint = va_arg(args, long int); break; case TYPE_DOUBLE: - format_arg[i].a.a_double = va_arg(args, double); + format_arg->a.a_double = va_arg(args, double); break; case TYPE_STRING: - format_arg[i].a.a_string = va_arg(args, const char *); + format_arg->a.a_string = va_arg(args, const char *); break; default: /* Cannot allow unused arguments, as we have no way of knowing how much space they take (cf. int vs. long long int). */ - goto error_inval; + errno = EINVAL; + return -1; } } - // Actually process the format parameter string + return 0; +} - format = orig_format; - arg_num = 0; + +/***********************************************************************/ +// vprepstr: Prepare a string for printing to screen + +int vprepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, + chtype attr_alt1, chtype attr_alt2, int maxlines, int maxwidth, + int *restrict widthbuf, int widthbufsize, + const char *restrict format, va_list args) +{ + const char *orig_format = format; + struct argument format_arg[MAXFMTARGS]; + struct convspec format_spec[MAXFMTSPECS]; + struct convspec *spec; + int line, width; + chtype *lastspc; + int widthspc; + chtype curattr; + int saved_errno; + + + assert(chbuf != NULL); + assert(chbufsize > 0); + assert(maxlines > 0); + assert(maxwidth > 0); + assert(widthbuf != NULL); + assert(widthbufsize >= maxlines); + assert(format != NULL); + + if (prepstr_parse(format, format_arg, format_spec, args) < 0) { + goto error; + } + + spec = format_spec; curattr = attr_norm; line = -1; // Current line number (0 = first) @@ -967,184 +1079,94 @@ int vprepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, goto error; } } else { - bool inspec = true; - bool flag_posn = false; - bool flag_long = false; - bool flag_thou = false; - int count = 0; - const char *str; + assert(spec->len != 0); + const char *str; char *buf = xmalloc(BUFSIZE); - while (inspec && *format != '\0') { - char c = *format++; - switch (c) { - case '0': - // Zero flag, or part of numeric count - if (count == 0) { - // Zero flag is not supported - free(buf); - goto error_inval; - } + switch (spec->spec) { + case 'c': + // Insert a character (char) into the output + if (snprintf(buf, BUFSIZE, "%c", + format_arg[spec->arg_num].a.a_char) < 0) { + saved_errno = errno; + free(buf); + errno = saved_errno; + goto error; + } - count *= 10; - break; + str = buf; + goto insertstr; - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - // Part of some numeric count - count = count * 10 + (c - '0'); - break; - - case '$': - // Fixed-position argument - if (flag_posn || count == 0) { - free(buf); - goto error_inval; - } - - if (count > MAXFMTARGS) { - free(buf); - errno = E2BIG; - goto error; - } - - flag_posn = true; - arg_num = count - 1; - count = 0; - break; - - case '\'': - // Use locale-specific thousands separator - if (flag_thou) { - free(buf); - goto error_inval; - } - - flag_thou = true; - break; - - case 'l': - // Long length modifier - if (flag_long) { - free(buf); - goto error_inval; - } - - flag_long = true; - break; - - case 'd': - // Insert an integer (int or long int) into the output - if (count != 0) { - free(buf); - goto error_inval; - } - - if (arg_num >= MAXFMTARGS) { - free(buf); - errno = E2BIG; - goto error; - } - - if (flag_long) { - if (snprintf(buf, BUFSIZE, flag_thou ? "%'ld" : "%ld", - format_arg[arg_num].a.a_longint) < 0) { - saved_errno = errno; - free(buf); - errno = saved_errno; - goto error; - } - } else { - if (snprintf(buf, BUFSIZE, flag_thou ? "%'d" : "%d", - format_arg[arg_num].a.a_int) < 0) { - saved_errno = errno; - free(buf); - errno = saved_errno; - goto error; - } - } - - str = buf; - goto insertstr; - - case 'N': - // Insert a monetary amount (double) into the output - if (count != 0 || flag_thou || flag_long) { - free(buf); - goto error_inval; - } - - if (arg_num >= MAXFMTARGS) { - free(buf); - errno = E2BIG; - goto error; - } - - if (l_strfmon(buf, BUFSIZE, "%n", - format_arg[arg_num].a.a_double) < 0) { + case 'd': + // Insert an integer (int or long int) into the output + if (spec->flag_long) { + if (snprintf(buf, BUFSIZE, spec->flag_group ? + "%'ld" : "%ld", + format_arg[spec->arg_num].a.a_longint) < 0) { saved_errno = errno; free(buf); errno = saved_errno; goto error; } - - str = buf; - goto insertstr; - - case 's': - // Insert a string (const char *) into the output - if (count != 0 || flag_thou || flag_long) { + } else { + if (snprintf(buf, BUFSIZE, spec->flag_group ? + "%'d" : "%d", + format_arg[spec->arg_num].a.a_int) < 0) { + saved_errno = errno; free(buf); - goto error_inval; - } - - if (arg_num >= MAXFMTARGS) { - free(buf); - errno = E2BIG; + errno = saved_errno; goto error; } - - str = format_arg[arg_num].a.a_string; - - if (str == NULL) { - str = "(null)"; // As per GNU printf() - } - - insertstr: - // Insert the string pointed to by str - while (*str != '\0' && chbufsize > 1 && line < maxlines) { - if (prepstr_addch(&chbuf, &chbufsize, curattr, - maxlines, maxwidth, &line, &width, - &lastspc, &widthspc, widthbuf, - widthbufsize, &str) < 0) { - saved_errno = errno; - free(buf); - errno = saved_errno; - goto error; - } - } - - arg_num++; - inspec = false; - break; - - default: - free(buf); - goto error_inval; } + + str = buf; + goto insertstr; + + case 'N': + // Insert a monetary amount (double) into the output + if (l_strfmon(buf, BUFSIZE, spec->flag_nosym ? "%!n" : "%n", + format_arg[spec->arg_num].a.a_double) < 0) { + saved_errno = errno; + free(buf); + errno = saved_errno; + goto error; + } + + str = buf; + goto insertstr; + + case 's': + // Insert a string (const char *) into the output + str = format_arg[spec->arg_num].a.a_string; + + if (str == NULL) { + str = "(null)"; // As per GNU printf() + } + + insertstr: + // Insert the string pointed to by str + while (*str != '\0' && chbufsize > 1 && line < maxlines) { + if (prepstr_addch(&chbuf, &chbufsize, curattr, + maxlines, maxwidth, &line, &width, + &lastspc, &widthspc, widthbuf, + widthbufsize, &str) < 0) { + saved_errno = errno; + free(buf); + errno = saved_errno; + goto error; + } + } + + format += spec->len; + spec++; + break; + + default: + assert(spec->spec); } + free(buf); - if (inspec) { - goto error_inval; - } } break; diff --git a/src/intf.h b/src/intf.h index a06c394..4aa9b8e 100644 --- a/src/intf.h +++ b/src/intf.h @@ -314,13 +314,17 @@ extern int txdlgbox (int maxlines, int ncols, int begin_y, int begin_x, %% - Print the ASCII percent sign (ASCII code U+0025) - %s - Insert the next parameter as a string + %c - Insert the next parameter as a character (type char) + %s - Insert the next parameter as a string (type char *) %d - Insert the next parameter as an integer (type int) %'d - Insert as an int, using the locale's thousands separator %ld - Insert the next parameter as a long int %'ld - Insert as a long int, using the locale's thousands separator %N - Insert the next parameter as a double, using the locale's national currency format (extension to printf()) + %!N - Insert the next parameter as a double, using the locale's + national currency format without the actual currency symbol + (extension to printf()) Instead of using "%" to convert the next parameter, "%m$" can be used to indicate fixed parameter m (where m is an integer from 1 to 8). For From 0c319738a80a135c9eba8ef4990aa19b1f7c057a Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Mon, 15 Aug 2011 17:07:00 +1000 Subject: [PATCH 033/112] Continue to move code to prepstr() and friends --- src/game.c | 6 ++- src/move.c | 129 ++++++++++++++++++++++++++--------------------------- 2 files changed, 68 insertions(+), 67 deletions(-) diff --git a/src/game.c b/src/game.c index 8c8b085..7d1cc4e 100644 --- a/src/game.c +++ b/src/game.c @@ -254,7 +254,8 @@ static int ask_number_players (void) widthbuf, sizeof(widthbuf) / sizeof(widthbuf[0]), "Enter number of players [^{1^}-^{%d^}] " "or ^{^} to continue a game: ", MAX_PLAYERS); - maxwidth = MAX(widthbuf[0], widthbuf[1]) + 5; + assert(lines == 1 || lines == 2); + maxwidth = ((lines == 1) ? widthbuf[0] : MAX(widthbuf[0], widthbuf[1])) + 5; newtxwin(lines + 4, maxwidth, 3, WCENTER, true, attr_normal_window); pr_left(curwin, 2, 2, chbuf, lines, widthbuf); @@ -318,7 +319,8 @@ int ask_game_number (void) widthbuf, sizeof(widthbuf) / sizeof(widthbuf[0]), "Enter game number [^{1^}-^{9^}] " "or ^{^} to cancel: "); - maxwidth = MAX(widthbuf[0], widthbuf[1]) + 5; + assert(lines == 1 || lines == 2); + maxwidth = ((lines == 1) ? widthbuf[0] : MAX(widthbuf[0], widthbuf[1])) + 5; newtxwin(lines + 4, maxwidth, 6, WCENTER, true, attr_normal_window); pr_left(curwin, 2, 2, chbuf, lines, widthbuf); diff --git a/src/move.c b/src/move.c index fcba6ef..15faadb 100644 --- a/src/move.c +++ b/src/move.c @@ -208,6 +208,8 @@ void select_moves (void) selection_t get_move (void) { selection_t selection = SEL_NONE; + chtype *chbuf = xmalloc(BUFSIZE * sizeof(chtype)); + int lines, width; if (quit_selected || abort_game) { @@ -231,34 +233,31 @@ selection_t get_move (void) werase(curwin); box(curwin, 0, 0); - wmove(curwin, 2, 2); - attrpr(curwin, attr_keycode, "<1>"); - waddstr(curwin, " Display stock portfolio"); + lines = prepstr(chbuf, BUFSIZE, attr_normal, attr_keycode, 0, + 1, getmaxx(curwin) / 2 - 4, &width, 1, + "^{<1>^} Display stock portfolio"); + pr_left(curwin, 2, 2, chbuf, lines, &width); - wmove(curwin, 3, 2); - attrpr(curwin, attr_keycode, "<2>"); - waddstr(curwin, " Declare bankruptcy"); + lines = prepstr(chbuf, BUFSIZE, attr_normal, attr_keycode, 0, + 1, getmaxx(curwin) / 2 - 4, &width, 1, + "^{<2>^} Declare bankruptcy"); + pr_left(curwin, 3, 2, chbuf, lines, &width); - wmove(curwin, 2, 42); - attrpr(curwin, attr_keycode, "<3>"); - waddstr(curwin, " Save and end the game"); + lines = prepstr(chbuf, BUFSIZE, attr_normal, attr_keycode, 0, + 1, getmaxx(curwin) / 2 - 4, &width, 1, + "^{<3>^} Save and end the game"); + pr_left(curwin, 2, getmaxx(curwin) / 2, chbuf, lines, &width); - wmove(curwin, 3, 42); - attrpr(curwin, attr_keycode, ""); - waddstr(curwin, " Quit the game"); + lines = prepstr(chbuf, BUFSIZE, attr_normal, attr_keycode, 0, + 1, getmaxx(curwin) / 2 - 4, &width, 1, + "^{^} Quit the game"); + pr_left(curwin, 3, getmaxx(curwin) / 2, chbuf, lines, &width); - mvwaddstr(curwin, 1, 9, "Select move "); - waddstr(curwin, "["); - attrpr(curwin, attr_choice, "%c", MOVE_TO_KEY(0)); - waddstr(curwin, "-"); - attrpr(curwin, attr_choice, "%c", MOVE_TO_KEY(NUMBER_MOVES - 1)); - waddstr(curwin, "/"); - attrpr(curwin, attr_keycode, "1"); - waddstr(curwin, "-"); - attrpr(curwin, attr_keycode, "3"); - waddstr(curwin, "/"); - attrpr(curwin, attr_keycode, ""); - waddstr(curwin, "]: "); + lines = prepstr(chbuf, BUFSIZE, attr_normal, attr_keycode, attr_choice, + 1, getmaxx(curwin) / 2 - 4, &width, 1, + "Select move [^[%c^]-^[%c^]/^{1^}-^{3^}/^{^}]: ", + MOVE_TO_KEY(0), MOVE_TO_KEY(NUMBER_MOVES - 1)); + pr_right(curwin, 1, getmaxx(curwin) / 2, chbuf, lines, &width); curs_set(CURS_ON); wrefresh(curwin); @@ -271,8 +270,10 @@ selection_t get_move (void) selection = KEY_TO_MOVE(key); curs_set(CURS_OFF); - waddstr(curwin, "Move "); - attrpr(curwin, attr_choice, "%c", key); + lines = prepstr(chbuf, BUFSIZE, attr_normal, attr_choice, 0, + 1, getmaxx(curwin) / 2 - 4, &width, 1, + "Move ^{%c^}", key); + pr_left(curwin, 1, getmaxx(curwin) / 2, chbuf, lines, &width); } else { switch (key) { case '1': @@ -285,20 +286,22 @@ selection_t get_move (void) selection = SEL_BANKRUPT; curs_set(CURS_OFF); - wattron(curwin, A_BOLD); - waddstr(curwin, "<2>"); - wattroff(curwin, A_BOLD); - waddstr(curwin, " (Declare bankruptcy)"); + lines = prepstr(chbuf, BUFSIZE, attr_normal, + attr_normal | A_BOLD, 0, 1, + getmaxx(curwin) / 2 - 4, &width, 1, + "^{<2>^} (Declare bankruptcy)"); + pr_left(curwin, 1, getmaxx(curwin) / 2, chbuf, lines, &width); break; case '3': selection = SEL_SAVE; curs_set(CURS_OFF); - wattron(curwin, A_BOLD); - waddstr(curwin, "<3>"); - wattroff(curwin, A_BOLD); - waddstr(curwin, " (Save and end the game)"); + lines = prepstr(chbuf, BUFSIZE, attr_normal, + attr_normal | A_BOLD, 0, 1, + getmaxx(curwin) / 2 - 4, &width, 1, + "^{<3>^} (Save and end the game)"); + pr_left(curwin, 1, getmaxx(curwin) / 2, chbuf, lines, &width); break; case KEY_ESC: @@ -310,10 +313,11 @@ selection_t get_move (void) selection = SEL_QUIT; curs_set(CURS_OFF); - wattron(curwin, A_BOLD); - waddstr(curwin, ""); - wattroff(curwin, A_BOLD); - waddstr(curwin, " (Quit the game)"); + lines = prepstr(chbuf, BUFSIZE, attr_normal, + attr_normal | A_BOLD, 0, 1, + getmaxx(curwin) / 2 - 4, &width, 1, + "^{^} (Quit the game)"); + pr_left(curwin, 1, getmaxx(curwin) / 2, chbuf, lines, &width); break; default: @@ -327,13 +331,10 @@ selection_t get_move (void) mvwhline(curwin, 3, 2, ' ' | attr_normal, getmaxx(curwin) - 4); // Ask the player to confirm their choice - wattrset(curwin, attr_normal); - mvwaddstr(curwin, 2, 22, "Are you sure? "); - waddstr(curwin, "["); - attrpr(curwin, attr_keycode, "Y"); - waddstr(curwin, "/"); - attrpr(curwin, attr_keycode, "N"); - waddstr(curwin, "] "); + lines = prepstr(chbuf, BUFSIZE, attr_normal, attr_keycode, 0, + 1, getmaxx(curwin) / 2 - 4, &width, 1, + "Are you sure? [^{Y^}/^{N^}] "); + pr_right(curwin, 2, getmaxx(curwin) / 2, chbuf, lines, &width); wrefresh(curwin); if (! answer_yesno(curwin)) { @@ -346,9 +347,6 @@ selection_t get_move (void) if (game_loaded) { // Save the game to the same game number - chtype *chbuf = xmalloc(BUFSIZE * sizeof(chtype)); - int lines, width; - lines = prepstr(chbuf, BUFSIZE, attr_status_window, 0, 0, 1, WIN_COLS - 7, &width, 1, "Saving game %d... ", game_num); @@ -360,26 +358,30 @@ selection_t get_move (void) deltxwin(); txrefresh(); - free(chbuf); } if (! saved) { + // Ask which game to save + int key; bool done; + int widthbuf[2]; + int maxwidth; - // Ask which game to save - newtxwin(6, 54, 8, WCENTER, true, attr_normal_window); - center(curwin, 1, attr_title, " Save Game "); - mvwaddstr(curwin, 3, 2, "Enter game number "); - waddstr(curwin, "["); - attrpr(curwin, attr_keycode, "1"); - waddstr(curwin, "-"); - attrpr(curwin, attr_keycode, "9"); - waddstr(curwin, "]"); - waddstr(curwin, " or "); - attrpr(curwin, attr_keycode, ""); - waddstr(curwin, " to cancel: "); + lines = prepstr(chbuf, BUFSIZE, attr_normal, attr_keycode, 0, + sizeof(widthbuf) / sizeof(widthbuf[0]), + WIN_COLS - 7, widthbuf, + sizeof(widthbuf) / sizeof(widthbuf[0]), + "Enter game number [^{1^}-^{9^}] " + "or ^{^} to cancel: "); + assert(lines == 1 || lines == 2); + maxwidth = ((lines == 1) ? widthbuf[0] : + MAX(widthbuf[0], widthbuf[1])) + 5; + + newtxwin(lines + 4, maxwidth, 8, WCENTER, true, + attr_normal_window); + pr_left(curwin, 2, 2, chbuf, lines, widthbuf); curs_set(CURS_ON); wrefresh(curwin); @@ -413,9 +415,6 @@ selection_t get_move (void) if (key != KEY_CANCEL) { // Try to save the game, if possible - chtype *chbuf = xmalloc(BUFSIZE * sizeof(chtype)); - int lines, width; - game_num = key - '0'; lines = prepstr(chbuf, BUFSIZE, attr_status_window, @@ -429,7 +428,6 @@ selection_t get_move (void) deltxwin(); txrefresh(); - free(chbuf); } deltxwin(); // "Enter game number" window @@ -448,6 +446,7 @@ selection_t get_move (void) } } + free(chbuf); return selection; } From 907a995b988e12f6f5b406b9a29940bfe335d0a1 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Mon, 15 Aug 2011 19:12:26 +1000 Subject: [PATCH 034/112] Refactor function names; "old_" functions will be removed Rename prepstr, vprepstr, chbufdup, center, center2, center3 and attrpr to mkchstr, vmkchstr, chstrdup, old_center, old_center2, old_center3 and old_attrpr respectively. --- src/exch.c | 74 ++++++++++++++++++++++++++-------------------------- src/game.c | 42 +++++++++++++++--------------- src/help.c | 14 +++++----- src/intf.c | 76 +++++++++++++++++++++++++++--------------------------- src/intf.h | 60 +++++++++++++++++++++--------------------- src/move.c | 50 +++++++++++++++++------------------ 6 files changed, 158 insertions(+), 158 deletions(-) diff --git a/src/exch.c b/src/exch.c index 5666742..5c50a46 100644 --- a/src/exch.c +++ b/src/exch.c @@ -93,8 +93,8 @@ void exchange_stock (void) werase(curwin); box(curwin, 0, 0); - center(curwin, 1, attr_title, " Interstellar Stock Exchange "); - center2(curwin, 2, attr_normal, attr_highlight, "Player: ", "%s", + old_center(curwin, 1, attr_title, " Interstellar Stock Exchange "); + old_center2(curwin, 2, attr_normal, attr_highlight, "Player: ", "%s", player[current_player].name); all_off_map = true; @@ -106,7 +106,7 @@ void exchange_stock (void) } if (all_off_map) { - center(curwin, 8, attr_normal, "No companies on the map"); + old_center(curwin, 8, attr_normal, "No companies on the map"); } else { char *buf = xmalloc(BUFSIZE); @@ -142,28 +142,28 @@ void exchange_stock (void) newtxwin(6, WIN_COLS, 18, WCENTER, true, attr_normal_window); wmove(curwin, 3, 2); - attrpr(curwin, attr_keycode, "<1>"); + old_attrpr(curwin, attr_keycode, "<1>"); waddstr(curwin, " Display stock portfolio"); wmove(curwin, 4, 2); - attrpr(curwin, attr_keycode, "<2>"); + old_attrpr(curwin, attr_keycode, "<2>"); waddstr(curwin, " Display galaxy map"); wmove(curwin, 3, 40); - attrpr(curwin, attr_keycode, "<3>"); + old_attrpr(curwin, attr_keycode, "<3>"); waddstr(curwin, " Visit the Trading Bank"); wmove(curwin, 4, 40); - attrpr(curwin, attr_keycode, "<4>"); + old_attrpr(curwin, attr_keycode, "<4>"); waddstr(curwin, " Exit the Stock Exchange"); mvwaddstr(curwin, 1, 18, "Enter selection "); waddstr(curwin, "["); - attrpr(curwin, attr_highlight, "Company letter"); + old_attrpr(curwin, attr_highlight, "Company letter"); waddstr(curwin, "/"); - attrpr(curwin, attr_keycode, "1"); + old_attrpr(curwin, attr_keycode, "1"); waddstr(curwin, "-"); - attrpr(curwin, attr_keycode, "4"); + old_attrpr(curwin, attr_keycode, "4"); waddstr(curwin, "]: "); curs_set(CURS_ON); @@ -264,21 +264,21 @@ void visit_bank (void) // Show the informational part of the Bank newtxwin(10, WIN_COLS - 4, 5, WCENTER, true, attr_normal_window); - center(curwin, 1, attr_title, " Interstellar Trading Bank "); + old_center(curwin, 1, attr_title, " Interstellar Trading Bank "); l_strfmon(buf, BUFSIZE, "%18n", player[current_player].cash); - center2(curwin, 3, attr_normal, attr_highlight, "Current cash: ", + old_center2(curwin, 3, attr_normal, attr_highlight, "Current cash: ", " %s ", buf); l_strfmon(buf, BUFSIZE, "%18n", player[current_player].debt); - center2(curwin, 4, attr_normal, attr_highlight, "Current debt: ", + old_center2(curwin, 4, attr_normal, attr_highlight, "Current debt: ", " %s ", buf); - center2(curwin, 5, attr_normal, attr_highlight, "Interest rate: ", + old_center2(curwin, 5, attr_normal, attr_highlight, "Interest rate: ", " %17.2f%% ", interest_rate * 100.0); l_strfmon(buf, BUFSIZE, "%18n", credit_limit); - center2(curwin, 7, attr_highlight, attr_title, "Credit limit: ", + old_center2(curwin, 7, attr_highlight, attr_title, "Credit limit: ", " %s ", buf); wrefresh(curwin); @@ -286,15 +286,15 @@ void visit_bank (void) // Show menu of choices for the player newtxwin(7, WIN_COLS - 4, 15, WCENTER, true, attr_normal_window); - center2(curwin, 3, attr_keycode, attr_normal, "<1>", " Borrow money "); - center2(curwin, 4, attr_keycode, attr_normal, "<2>", " Repay debt "); - center2(curwin, 5, attr_keycode, attr_normal, "<3>", " Exit from the Bank"); + old_center2(curwin, 3, attr_keycode, attr_normal, "<1>", " Borrow money "); + old_center2(curwin, 4, attr_keycode, attr_normal, "<2>", " Repay debt "); + old_center2(curwin, 5, attr_keycode, attr_normal, "<3>", " Exit from the Bank"); mvwaddstr(curwin, 1, 24, "Enter selection "); waddstr(curwin, "["); - attrpr(curwin, attr_keycode, "1"); + old_attrpr(curwin, attr_keycode, "1"); waddstr(curwin, "-"); - attrpr(curwin, attr_keycode, "3"); + old_attrpr(curwin, attr_keycode, "3"); waddstr(curwin, "]: "); curs_set(CURS_ON); @@ -473,35 +473,35 @@ void trade_shares (int num, bool *bid_used) // Show the informational part of the trade window newtxwin(9, WIN_COLS - 4, 5, WCENTER, true, attr_normal_window); - center(curwin, 1, attr_title, " Stock Transaction in %s ", + old_center(curwin, 1, attr_title, " Stock Transaction in %s ", company[num].name); mvwaddstr(curwin, 3, 2, "Shares issued: "); - attrpr(curwin, attr_highlight, "%'12ld", company[num].stock_issued); + old_attrpr(curwin, attr_highlight, "%'12ld", company[num].stock_issued); mvwaddstr(curwin, 4, 2, "Shares left: "); - attrpr(curwin, attr_highlight, "%'12ld", + old_attrpr(curwin, attr_highlight, "%'12ld", company[num].max_stock - company[num].stock_issued); mvwaddstr(curwin, 5, 2, "Price per share: "); l_strfmon(buf, BUFSIZE, "%12n", company[num].share_price); - attrpr(curwin, attr_highlight, "%12s", buf); + old_attrpr(curwin, attr_highlight, "%12s", buf); mvwaddstr(curwin, 6, 2, "Return: "); - attrpr(curwin, attr_highlight, "%11.2f%%", + old_attrpr(curwin, attr_highlight, "%11.2f%%", company[num].share_return * 100.0); mvwaddstr(curwin, 3, 38, "Current holdings: "); - attrpr(curwin, attr_highlight, " %'16ld ", + old_attrpr(curwin, attr_highlight, " %'16ld ", player[current_player].stock_owned[num]); mvwaddstr(curwin, 4, 38, "Percentage owned: "); - attrpr(curwin, attr_highlight, " %'15.2f%% ", ownership * 100.0); + old_attrpr(curwin, attr_highlight, " %'15.2f%% ", ownership * 100.0); wmove(curwin, 6, 38); - attrpr(curwin, attr_highlight, "Current cash: "); + old_attrpr(curwin, attr_highlight, "Current cash: "); l_strfmon(buf, BUFSIZE, "%16n", player[current_player].cash); - attrpr(curwin, attr_title, " %16s ", buf); + old_attrpr(curwin, attr_title, " %16s ", buf); wrefresh(curwin); @@ -509,26 +509,26 @@ void trade_shares (int num, bool *bid_used) newtxwin(7, WIN_COLS - 4, 14, WCENTER, true, attr_normal_window); wmove(curwin, 3, 2); - attrpr(curwin, attr_keycode, "<1>"); + old_attrpr(curwin, attr_keycode, "<1>"); waddstr(curwin, " Buy stock from company"); wmove(curwin, 4, 2); - attrpr(curwin, attr_keycode, "<2>"); + old_attrpr(curwin, attr_keycode, "<2>"); waddstr(curwin, " Sell stock back to company"); wmove(curwin, 3, 38); - attrpr(curwin, attr_keycode, "<3>"); + old_attrpr(curwin, attr_keycode, "<3>"); waddstr(curwin, " Bid company to issue more shares"); wmove(curwin, 4, 38); - attrpr(curwin, attr_keycode, "<4>"); + old_attrpr(curwin, attr_keycode, "<4>"); waddstr(curwin, " Exit to the Stock Exchange"); mvwaddstr(curwin, 1, 24, "Enter selection "); waddstr(curwin, "["); - attrpr(curwin, attr_keycode, "1"); + old_attrpr(curwin, attr_keycode, "1"); waddstr(curwin, "-"); - attrpr(curwin, attr_keycode, "4"); + old_attrpr(curwin, attr_keycode, "4"); waddstr(curwin, "]: "); curs_set(CURS_ON); @@ -586,7 +586,7 @@ void trade_shares (int num, bool *bid_used) werase(curwin); box(curwin, 0, 0); - center3(curwin, 2, attr_normal, attr_normal, attr_highlight, + old_center3(curwin, 2, attr_normal, attr_normal, attr_highlight, "You can purchase up to ", " shares.", "%'ld", maxshares); mvwprintw(curwin, 4, 10, "How many shares do you wish to purchase? "); @@ -616,7 +616,7 @@ void trade_shares (int num, bool *bid_used) werase(curwin); box(curwin, 0, 0); - center3(curwin, 2, attr_normal, attr_normal, attr_highlight, + old_center3(curwin, 2, attr_normal, attr_normal, attr_highlight, "You can sell up to ", " shares.", "%'ld", maxshares); mvwprintw(curwin, 4, 10, "How many shares do you wish to sell? "); diff --git a/src/game.c b/src/game.c index 7d1cc4e..93844aa 100644 --- a/src/game.c +++ b/src/game.c @@ -113,7 +113,7 @@ void init_game (void) chtype *chbuf = xmalloc(BUFSIZE * sizeof(chtype)); int lines, width; - lines = prepstr(chbuf, BUFSIZE, attr_status_window, 0, 0, 1, + lines = mkchstr(chbuf, BUFSIZE, attr_status_window, 0, 0, 1, WIN_COLS - 7, &width, 1, "Loading game %d... ", game_num); newtxwin(5, width + 5, 6, WCENTER, true, attr_status_window); @@ -148,7 +148,7 @@ void init_game (void) game_num = choice; - lines = prepstr(chbuf, BUFSIZE, attr_status_window, + lines = mkchstr(chbuf, BUFSIZE, attr_status_window, 0, 0, 1, WIN_COLS - 7, &width, 1, "Loading game %d... ", game_num); newtxwin(5, width + 5, 9, WCENTER, true, attr_status_window); @@ -249,7 +249,7 @@ static int ask_number_players (void) chbuf = xmalloc(BUFSIZE * sizeof(chtype)); - lines = prepstr(chbuf, BUFSIZE, attr_normal, attr_keycode, 0, + lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_keycode, 0, sizeof(widthbuf) / sizeof(widthbuf[0]), WIN_COLS - 7, widthbuf, sizeof(widthbuf) / sizeof(widthbuf[0]), "Enter number of players [^{1^}-^{%d^}] " @@ -314,7 +314,7 @@ int ask_game_number (void) chbuf = xmalloc(BUFSIZE * sizeof(chtype)); - lines = prepstr(chbuf, BUFSIZE, attr_normal, attr_keycode, 0, + lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_keycode, 0, sizeof(widthbuf) / sizeof(widthbuf[0]), WIN_COLS - 7, widthbuf, sizeof(widthbuf) / sizeof(widthbuf[0]), "Enter game number [^{1^}-^{9^}] " @@ -388,7 +388,7 @@ void ask_player_names (void) chtype *chbuf = xmalloc(BUFSIZE * sizeof(chtype)); int lines, width; - lines = prepstr(chbuf, BUFSIZE, attr_normal, attr_keycode, 0, + lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_keycode, 0, 1, WIN_COLS - YESNO_COLS - 6, &width, 1, "Do you need any instructions? [^{Y^}/^{N^}] "); newtxwin(5, width + YESNO_COLS + 4, 6, WCENTER, true, @@ -411,7 +411,7 @@ void ask_player_names (void) newtxwin(number_players + 5, WIN_COLS - 4, 9, WCENTER, true, attr_normal_window); - lines = prepstr(chbuf, BUFSIZE, attr_title, 0, 0, 1, WIN_COLS - 8, + lines = mkchstr(chbuf, BUFSIZE, attr_title, 0, 0, 1, WIN_COLS - 8, &width, 1, " Enter Player Names "); pr_center(curwin, 1, 0, chbuf, lines, &width); @@ -494,7 +494,7 @@ void ask_player_names (void) } } - lines = prepstr(chbuf, BUFSIZE, attr_normal, attr_keycode, 0, + lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_keycode, 0, 1, WIN_COLS - YESNO_COLS - 6, &width, 1, "Does any player need instructions? [^{Y^}/^{N^}] "); newtxwin(5, width + YESNO_COLS + 4, 6, WCENTER, true, @@ -552,15 +552,15 @@ void end_game (void) newtxwin(number_players + 10, WIN_COLS - 4, 3, WCENTER, true, attr_normal_window); - center(curwin, 1, attr_title, " Game Winner "); - center2(curwin, 3, attr_normal, attr_highlight, "The winner is ", + old_center(curwin, 1, attr_title, " Game Winner "); + old_center2(curwin, 3, attr_normal, attr_highlight, "The winner is ", "%s", player[0].name); if (player[0].sort_value == 0.0) { - center2(curwin, 4, attr_normal, attr_blink, "who is ", + old_center2(curwin, 4, attr_normal, attr_blink, "who is ", "*** BANKRUPT ***"); } else { l_strfmon(buf, BUFSIZE, "%1n", player[0].sort_value); - center2(curwin, 4, attr_normal, attr_highlight, + old_center2(curwin, 4, attr_normal, attr_highlight, "with a value of ", "%s", buf); } @@ -603,12 +603,12 @@ void show_map (bool closewin) mvwhline(curwin, 1, 2, ' ' | attr_mapwin_title, getmaxx(curwin) - 4); // Display current player and turn number - lines = prepstr(chbuf, BUFSIZE, attr_mapwin_title, attr_mapwin_highlight, + lines = mkchstr(chbuf, BUFSIZE, attr_mapwin_title, attr_mapwin_highlight, 0, 1, WIN_COLS - 4, &width, 1, " Player: ^{%s^} ", player[current_player].name); pr_left(curwin, 1, 2, chbuf, lines, &width); - lines = prepstr(chbuf, BUFSIZE, attr_mapwin_title, attr_mapwin_highlight, + lines = mkchstr(chbuf, BUFSIZE, attr_mapwin_title, attr_mapwin_highlight, attr_mapwin_blink, 1, WIN_COLS / 2, &width, 1, (turn_number != max_turn) ? " Turn: ^{%d^} " : " ^[*** Last Turn ***^] ", turn_number); @@ -679,18 +679,18 @@ void show_status (int num) attr_normal_window); chbuf = xmalloc(BUFSIZE * sizeof(chtype)); - lines = prepstr(chbuf, BUFSIZE, attr_title, 0, 0, 1, WIN_COLS - 4, + lines = mkchstr(chbuf, BUFSIZE, attr_title, 0, 0, 1, WIN_COLS - 4, &width, 1, " Stock Portfolio "); pr_center(curwin, 1, 0, chbuf, lines, &width); - lines = prepstr(chbuf, BUFSIZE, attr_normal, attr_highlight, 0, 1, + lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_highlight, 0, 1, WIN_COLS - 4, &width, 1, "Player: ^{%s^}", player[num].name); pr_center(curwin, 2, 0, chbuf, lines, &width); val = total_value(num); if (val == 0.0) { - lines = prepstr(chbuf, BUFSIZE, attr_normal, attr_highlight, + lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_highlight, attr_blink, 1, WIN_COLS - 4, &width, 1, "^[* * * B A N K R U P T * * *^]"); pr_center(curwin, 11, 0, chbuf, lines, &width); @@ -708,7 +708,7 @@ void show_status (int num) } if (none) { - lines = prepstr(chbuf, BUFSIZE, attr_normal, attr_highlight, 0, + lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_highlight, 0, 1, WIN_COLS - 4, &width, 1, "No companies on the map"); pr_center(curwin, 8, 0, chbuf, lines, &width); @@ -741,18 +741,18 @@ void show_status (int num) line = 15; l_strfmon(buf, BUFSIZE, "%18n", player[num].cash); - center2(curwin, line++, attr_normal, attr_highlight, "Current cash: ", + old_center2(curwin, line++, attr_normal, attr_highlight, "Current cash: ", " %s ", buf); if (player[num].debt != 0.0) { l_strfmon(buf, BUFSIZE, "%18n", player[num].debt); - center2(curwin, line++, attr_normal, attr_highlight, + old_center2(curwin, line++, attr_normal, attr_highlight, "Current debt: ", " %s ", buf); - center2(curwin, line++, attr_normal, attr_highlight, + old_center2(curwin, line++, attr_normal, attr_highlight, "Interest rate: ", " %17.2f%% ", interest_rate * 100.0); } l_strfmon(buf, BUFSIZE, "%18n", val); - center2(curwin, line + 1, attr_highlight, attr_title, + old_center2(curwin, line + 1, attr_highlight, attr_title, "Total value: ", " %s ", buf); free(buf); diff --git a/src/help.c b/src/help.c index dd78cf5..2dad035 100644 --- a/src/help.c +++ b/src/help.c @@ -182,20 +182,20 @@ void show_help (void) } // Prepare fixed-text strings - ln_title = prepstr(chbuf, BUFSIZE, attr_title, 0, 0, 1, WIN_COLS - 4, + ln_title = mkchstr(chbuf, BUFSIZE, attr_title, 0, 0, 1, WIN_COLS - 4, &w_title, 1, " How to Play "); - ch_title = chbufdup(chbuf, BUFSIZE); + ch_title = chstrdup(chbuf, BUFSIZE); - ln_contfirst = prepstr(chbuf, BUFSIZE, attr_waitforkey, 0, 0, 1, + ln_contfirst = mkchstr(chbuf, BUFSIZE, attr_waitforkey, 0, 0, 1, WIN_COLS - 4, &w_contfirst, 1, "[ Press to continue ] "); - ch_contfirst = chbufdup(chbuf, BUFSIZE); + ch_contfirst = chstrdup(chbuf, BUFSIZE); - ln_contnext = prepstr(chbuf, BUFSIZE, attr_waitforkey, 0, 0, 1, + ln_contnext = mkchstr(chbuf, BUFSIZE, attr_waitforkey, 0, 0, 1, WIN_COLS - 4, &w_contnext, 1, "[ Press to continue or " " for the previous page ] "); - ch_contnext = chbufdup(chbuf, BUFSIZE); + ch_contnext = chstrdup(chbuf, BUFSIZE); newtxwin(WIN_LINES - 1, WIN_COLS, 1, WCENTER, false, 0); @@ -207,7 +207,7 @@ void show_help (void) box(curwin, 0, 0); pr_center(curwin, 1, 0, ch_title, ln_title, &w_title); - lines = prepstr(chbuf, BUFSIZE, attr_normal, attr_highlight, 0, 1, + lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_highlight, 0, 1, WIN_COLS - 4, &width, 1, "Page %d of %d", curpage + 1, numpages); pr_center(curwin, 2, 0, chbuf, lines, &width); diff --git a/src/intf.c b/src/intf.c index 53a6909..8a26435 100644 --- a/src/intf.c +++ b/src/intf.c @@ -42,7 +42,7 @@ typedef struct txwin { } txwin_t; -// Declarations for argument processing in prepstr() +// Declarations for argument processing in mkchstr() #define MAXFMTARGS 8 // Maximum number of positional arguments @@ -170,7 +170,7 @@ static void txresize (void); /* - Function: prepstr_addch - Add a character to the prepstr buffer + Function: mkchstr_addch - Add a character to the mkchstr buffer Parameters: chbuf - Pointer to chtype pointer in which to store string chbufsize - Pointer to number of chtype elements in chbuf attr - Character rendition to use @@ -193,7 +193,7 @@ static void txresize (void); (if not on the last line). *line, *width, *lastspc, *widthspc and widthbuf[] are all updated appropriately. */ -static int prepstr_addch (chtype *restrict *restrict chbuf, +static int mkchstr_addch (chtype *restrict *restrict chbuf, int *restrict chbufsize, chtype attr, int maxlines, int maxwidth, int *restrict line, int *restrict width, @@ -204,17 +204,17 @@ static int prepstr_addch (chtype *restrict *restrict chbuf, /* - Function: prepstr_parse - Parse the format string for prepstr() - Parameters: format - Format string as described for prepstr() + Function: mkchstr_parse - Parse the format string for mkchstr() + Parameters: format - Format string as described for mkchstr() format_arg - Pointer to variable arguments array format_spec - Pointer to conversion specifiers array - args - Variable argument list passed to prepstr() + args - Variable argument list passed to mkchstr() Returns: int - 0 if OK, -1 if error (with errno set) - This helper function parses the format string passed to prepstr(), + This helper function parses the format string passed to mkchstr(), setting the format_arg and format_spec arrays appropriately. */ -static int prepstr_parse (const char *restrict format, +static int mkchstr_parse (const char *restrict format, struct argument *restrict format_arg, struct convspec *restrict format_spec, va_list args); @@ -416,7 +416,7 @@ void init_title (void) } chbuf = xmalloc(BUFSIZE * sizeof(chtype)); - lines = prepstr(chbuf, BUFSIZE, attr_game_title, 0, 0, 1, COLS, + lines = mkchstr(chbuf, BUFSIZE, attr_game_title, 0, 0, 1, COLS, &width, 1, _("Star Traders")); pr_center(stdscr, 0, 0, chbuf, lines, &width); attrset(attr_root_window); @@ -612,7 +612,7 @@ int txdlgbox (int maxlines, int ncols, int begin_y, int begin_x, widthbuf = xmalloc(maxlines * sizeof(int)); va_start(args, format); - lines = vprepstr(chbuf, BUFSIZE, norm_attr, alt1_attr, alt2_attr, maxlines, + lines = vmkchstr(chbuf, BUFSIZE, norm_attr, alt1_attr, alt2_attr, maxlines, ncols - 4, widthbuf, maxlines, format, args); va_end(args); @@ -624,7 +624,7 @@ int txdlgbox (int maxlines, int ncols, int begin_y, int begin_x, int titlewidth; int titlelines; - titlelines = prepstr(titlebuf, BUFSIZE, title_attr, 0, 0, 1, + titlelines = mkchstr(titlebuf, BUFSIZE, title_attr, 0, 0, 1, ncols - 4, &titlewidth, 1, boxtitle); pr_center(curwin, 1, 0, titlebuf, titlelines, &titlewidth); free(titlebuf); @@ -641,9 +641,9 @@ int txdlgbox (int maxlines, int ncols, int begin_y, int begin_x, /***********************************************************************/ -// prepstr: Prepare a string for printing to screen +// mkchstr: Prepare a string for printing to screen -int prepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, +int mkchstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, chtype attr_alt1, chtype attr_alt2, int maxlines, int maxwidth, int *restrict widthbuf, int widthbufsize, const char *restrict format, ...) @@ -653,7 +653,7 @@ int prepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, va_start(args, format); - lines = vprepstr(chbuf, chbufsize, attr_norm, attr_alt1, attr_alt2, + lines = vmkchstr(chbuf, chbufsize, attr_norm, attr_alt1, attr_alt2, maxlines, maxwidth, widthbuf, widthbufsize, format, args); va_end(args); @@ -662,9 +662,9 @@ int prepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, /***********************************************************************/ -// prepstr_addch: Add a character to the prepstr buffer +// mkchstr_addch: Add a character to the mkchstr buffer -int prepstr_addch (chtype *restrict *restrict chbuf, int *restrict chbufsize, +int mkchstr_addch (chtype *restrict *restrict chbuf, int *restrict chbufsize, chtype attr, int maxlines, int maxwidth, int *restrict line, int *restrict width, chtype *restrict *restrict lastspc, int *restrict widthspc, @@ -747,9 +747,9 @@ int prepstr_addch (chtype *restrict *restrict chbuf, int *restrict chbufsize, /***********************************************************************/ -// prepstr_parse: Parse the format string for prepstr() +// mkchstr_parse: Parse the format string for mkchstr() -int prepstr_parse (const char *restrict format, +int mkchstr_parse (const char *restrict format, struct argument *restrict format_arg, struct convspec *restrict format_spec, va_list args) { @@ -991,9 +991,9 @@ int prepstr_parse (const char *restrict format, /***********************************************************************/ -// vprepstr: Prepare a string for printing to screen +// vmkchstr: Prepare a string for printing to screen -int vprepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, +int vmkchstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, chtype attr_alt1, chtype attr_alt2, int maxlines, int maxwidth, int *restrict widthbuf, int widthbufsize, const char *restrict format, va_list args) @@ -1017,7 +1017,7 @@ int vprepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, assert(widthbufsize >= maxlines); assert(format != NULL); - if (prepstr_parse(format, format_arg, format_spec, args) < 0) { + if (mkchstr_parse(format, format_arg, format_spec, args) < 0) { goto error; } @@ -1038,7 +1038,7 @@ int vprepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, } else { switch (*format) { case '^': - if (prepstr_addch(&chbuf, &chbufsize, curattr, maxlines, + if (mkchstr_addch(&chbuf, &chbufsize, curattr, maxlines, maxwidth, &line, &width, &lastspc, &widthspc, widthbuf, widthbufsize, &format) < 0) { @@ -1073,7 +1073,7 @@ int vprepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, if (*++format == '\0') { goto error_inval; } else if (*format == '%') { - if (prepstr_addch(&chbuf, &chbufsize, curattr, maxlines, + if (mkchstr_addch(&chbuf, &chbufsize, curattr, maxlines, maxwidth, &line, &width, &lastspc, &widthspc, widthbuf, widthbufsize, &format) < 0) { goto error; @@ -1147,7 +1147,7 @@ int vprepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, insertstr: // Insert the string pointed to by str while (*str != '\0' && chbufsize > 1 && line < maxlines) { - if (prepstr_addch(&chbuf, &chbufsize, curattr, + if (mkchstr_addch(&chbuf, &chbufsize, curattr, maxlines, maxwidth, &line, &width, &lastspc, &widthspc, widthbuf, widthbufsize, &str) < 0) { @@ -1172,7 +1172,7 @@ int vprepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, default: // Process an ordinary character (including new-line) - if (prepstr_addch(&chbuf, &chbufsize, curattr, maxlines, maxwidth, + if (mkchstr_addch(&chbuf, &chbufsize, curattr, maxlines, maxwidth, &line, &width, &lastspc, &widthspc, widthbuf, widthbufsize, &format) < 0) { goto error; @@ -1195,14 +1195,14 @@ error_inval: errno = EINVAL; error: - errno_exit(_("prepstr: `%s'"), orig_format); + errno_exit(_("mkchstr: `%s'"), orig_format); } /***********************************************************************/ -// chbufdup: Duplicate a chtype buffer +// chstrdup: Duplicate a chtype buffer -chtype *chbufdup (const chtype *restrict chbuf, int chbufsize) +chtype *chstrdup (const chtype *restrict chbuf, int chbufsize) { const chtype *p; int len; @@ -1309,9 +1309,9 @@ int pr_right (WINDOW *win, int y, int x, const chtype *restrict chbuf, /***********************************************************************/ -// attrpr: Print a string with a particular character rendition +// old_attrpr: Print a string with a particular character rendition -int attrpr (WINDOW *win, chtype attr, const char *restrict format, ...) +int old_attrpr (WINDOW *win, chtype attr, const char *restrict format, ...) { va_list args; int ret; @@ -1340,9 +1340,9 @@ int attrpr (WINDOW *win, chtype attr, const char *restrict format, ...) /***********************************************************************/ -// center: Centre a string in a given window +// old_center: Centre a string in a given window -int center (WINDOW *win, int y, chtype attr, const char *restrict format, ...) +int old_center (WINDOW *win, int y, chtype attr, const char *restrict format, ...) { va_list args; int ret, len, x; @@ -1357,7 +1357,7 @@ int center (WINDOW *win, int y, chtype attr, const char *restrict format, ...) chtype oldattr = getattrs(win); chtype oldbkgd = getbkgd(win); - // Order is important: see attrpr() + // Order is important: see old_attrpr() wbkgdset(win, (oldbkgd & A_COLOR) | A_NORMAL); wattrset(win, attr); @@ -1383,9 +1383,9 @@ int center (WINDOW *win, int y, chtype attr, const char *restrict format, ...) /***********************************************************************/ -// center2: Centre two strings in a given window +// old_center2: Centre two strings in a given window -int center2 (WINDOW *win, int y, chtype attr1, chtype attr2, +int old_center2 (WINDOW *win, int y, chtype attr1, chtype attr2, const char *initial, const char *restrict format, ...) { va_list args; @@ -1431,9 +1431,9 @@ int center2 (WINDOW *win, int y, chtype attr1, chtype attr2, /***********************************************************************/ -// center3: Centre three strings in a given window +// old_center3: Centre three strings in a given window -int center3 (WINDOW *win, int y, chtype attr1, chtype attr3, chtype attr2, +int old_center3 (WINDOW *win, int y, chtype attr1, chtype attr3, chtype attr2, const char *initial, const char *final, const char *restrict format, ...) { @@ -2447,7 +2447,7 @@ void wait_for_key (WINDOW *win, int y, chtype attr) wtimeout(win, -1); chbuf = xmalloc(BUFSIZE * sizeof(chtype)); - lines = prepstr(chbuf, BUFSIZE, attr, 0, 0, 1, getmaxx(win) - 4, + lines = mkchstr(chbuf, BUFSIZE, attr, 0, 0, 1, getmaxx(win) - 4, &width, 1, _("[ Press to continue ] ")); pr_center(win, y, 0, chbuf, lines, &width); wrefresh(win); diff --git a/src/intf.h b/src/intf.h index 4aa9b8e..622c85f 100644 --- a/src/intf.h +++ b/src/intf.h @@ -288,7 +288,7 @@ extern int txdlgbox (int maxlines, int ncols, int begin_y, int begin_x, /* - Function: prepstr - Prepare a string for printing to screen + Function: mkchstr - Prepare a string for printing to screen Parameters: chbuf - Pointer to chtype buffer in which to store string chbufsize - Number of chtype elements in chbuf attr_norm - Normal character rendition to use @@ -357,14 +357,14 @@ extern int txdlgbox (int maxlines, int ncols, int begin_y, int begin_x, This function returns the actual number of lines used (from 0 to maxlines). If an error is detected, the application terminates. */ -extern int prepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, +extern int mkchstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, chtype attr_alt1, chtype attr_alt2, int maxlines, int maxwidth, int *restrict widthbuf, int widthbufsize, const char *restrict format, ...); /* - Function: vprepstr - Prepare a string for printing to screen + Function: vmkchstr - Prepare a string for printing to screen Parameters: chbuf - Pointer to chtype buffer in which to store string chbufsize - Number of chtype elements in chbuf attr_norm - Normal character rendition to use @@ -374,33 +374,33 @@ extern int prepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, maxwidth - Maximum width of each line, in chars widthbuf - Pointer to buffer to store widths of each line widthbufsize - Number of int elements in widthbuf - format - Format string as described for prepstr() + format - Format string as described for mkchstr() args - Variable argument list Returns: int - Number of lines actually used - This function is exactly the same as prepstr(), except that it is + This function is exactly the same as mkchstr(), except that it is called with a va_list parameter args instead of a variable number of arguments. Note that va_end() is NOT called on args, and that args is undefined after this function. */ -extern int vprepstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, +extern int vmkchstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, chtype attr_alt1, chtype attr_alt2, int maxlines, int maxwidth, int *restrict widthbuf, int widthbufsize, const char *restrict format, va_list args); /* - Function: chbufdup - Duplicate a chtype buffer - Parameters: chbuf - Buffer to duplicate - chbufsize - Number of chtype elements in chbuf - Returns: chtype * - Pointer to new duplicated buffer + Function: chstrdup - Duplicate a chtype string + Parameters: chstr - String to duplicate + chstrsize - Maximum number of chtype elements in chstr + Returns: chtype * - Pointer to new (duplicated) string - This function returns a new buffer of type chtype * that contains a - copy of the string in chbuf. No errors are returned: if sufficient + This function returns a new string of type chtype * that contains a + copy of the string in chstr. No errors are returned: if sufficient memory is not available, the program terminates with an "Out of memory" message. */ -extern chtype *chbufdup (const chtype *restrict chbuf, int chbufsize); +extern chtype *chstrdup (const chtype *restrict chstr, int chstrsize); /* @@ -408,9 +408,9 @@ extern chtype *chbufdup (const chtype *restrict chbuf, int chbufsize); Parameters: win - Window to use (should be curwin) y - Line on which to print first string x - Starting column number for each line - chbuf - chtype buffer as returned from prepstr() - lines - Number of lines in chbuf (as returned from prepstr()) - widthbuf - Widths of each line (as returned from prepstr()) + chbuf - chtype buffer as returned from mkchstr() + lines - Number of lines in chbuf (as returned from mkchstr()) + widthbuf - Widths of each line (as returned from mkchstr()) Returns: int - Error code OK This function takes the strings in the chtype array chbuf and prints @@ -426,9 +426,9 @@ extern int pr_left (WINDOW *win, int y, int x, const chtype *restrict chbuf, Parameters: win - Window to use (should be curwin) y - Line on which to print first string offset - Column offset to add to position for each line - chbuf - chtype buffer as returned from prepstr() - lines - Number of lines in chbuf (as returned from prepstr()) - widthbuf - Widths of each line (as returned from prepstr()) + chbuf - chtype buffer as returned from mkchstr() + lines - Number of lines in chbuf (as returned from mkchstr()) + widthbuf - Widths of each line (as returned from mkchstr()) Returns: int - ERR if more lines in chbuf[] than lines, else OK This function takes the strings in the chtype array chbuf and prints @@ -446,9 +446,9 @@ extern int pr_center (WINDOW *win, int y, int offset, Parameters: win - Window to use (should be curwin) y - Line on which to print first string x - Ending column number for each line - chbuf - chtype buffer as returned from prepstr() - lines - Number of lines in chbuf (as returned from prepstr()) - widthbuf - Widths of each line (as returned from prepstr()) + chbuf - chtype buffer as returned from mkchstr() + lines - Number of lines in chbuf (as returned from mkchstr()) + widthbuf - Widths of each line (as returned from mkchstr()) Returns: int - ERR if more lines in chbuf[] than lines, else OK This function takes the strings in the chtype array chbuf and prints @@ -461,7 +461,7 @@ extern int pr_right (WINDOW *win, int y, int x, const chtype *restrict chbuf, /* - Function: attrpr - Print a string with a particular character rendition + Function: old_attrpr - Print a string with a particular character rendition Parameters: win - Window to use (should be curwin) attr - Character rendition to use for the string format - printf()-like format string @@ -473,12 +473,12 @@ extern int pr_right (WINDOW *win, int y, int x, const chtype *restrict chbuf, rendition. The return code is as returned from wprintw(). Note that wrefresh() is NOT called. */ -extern int attrpr (WINDOW *win, chtype attr, const char *restrict format, ...) +extern int old_attrpr (WINDOW *win, chtype attr, const char *restrict format, ...) __attribute__((format (printf, 3, 4))); /* - Function: center - Centre a string in a given window + Function: old_center - Centre a string in a given window Parameters: win - Window to use (should be curwin) y - Line on which to centre the string attr - Character rendition to use for the string @@ -495,13 +495,13 @@ extern int attrpr (WINDOW *win, chtype attr, const char *restrict format, ...) handle multibyte strings correctly: strlen() is used to determine the printing width of the string. */ -extern int center (WINDOW *win, int y, chtype attr, +extern int old_center (WINDOW *win, int y, chtype attr, const char *restrict format, ...) __attribute__((format (printf, 4, 5))); /* - Function: center2 - Centre two strings in a given window + Function: old_center2 - Centre two strings in a given window Parameters: win - Window to use (should be curwin) y - Line on which to centre the strings attr1 - Character rendition to use for initial string @@ -521,13 +521,13 @@ extern int center (WINDOW *win, int y, chtype attr, As with center(), the current implementation does NOT handle multibyte strings correctly. */ -extern int center2 (WINDOW *win, int y, chtype attr1, chtype attr2, +extern int old_center2 (WINDOW *win, int y, chtype attr1, chtype attr2, const char *initial, const char *restrict format, ...) __attribute__((format (printf, 6, 7))); /* - Function: center3 - Centre three strings in a given window + Function: old_center3 - Centre three strings in a given window Parameters: win - Window to use (should be curwin) y - Line on which to centre the strings attr1 - Character rendition to use for initial string @@ -552,7 +552,7 @@ extern int center2 (WINDOW *win, int y, chtype attr1, chtype attr2, strings correctly. */ -extern int center3 (WINDOW *win, int y, chtype attr1, chtype attr3, +extern int old_center3 (WINDOW *win, int y, chtype attr1, chtype attr3, chtype attr2, const char *initial, const char *final, const char *restrict format, ...) __attribute__((format (printf, 8, 9))); diff --git a/src/move.c b/src/move.c index 15faadb..f6e97f1 100644 --- a/src/move.c +++ b/src/move.c @@ -233,27 +233,27 @@ selection_t get_move (void) werase(curwin); box(curwin, 0, 0); - lines = prepstr(chbuf, BUFSIZE, attr_normal, attr_keycode, 0, + lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_keycode, 0, 1, getmaxx(curwin) / 2 - 4, &width, 1, "^{<1>^} Display stock portfolio"); pr_left(curwin, 2, 2, chbuf, lines, &width); - lines = prepstr(chbuf, BUFSIZE, attr_normal, attr_keycode, 0, + lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_keycode, 0, 1, getmaxx(curwin) / 2 - 4, &width, 1, "^{<2>^} Declare bankruptcy"); pr_left(curwin, 3, 2, chbuf, lines, &width); - lines = prepstr(chbuf, BUFSIZE, attr_normal, attr_keycode, 0, + lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_keycode, 0, 1, getmaxx(curwin) / 2 - 4, &width, 1, "^{<3>^} Save and end the game"); pr_left(curwin, 2, getmaxx(curwin) / 2, chbuf, lines, &width); - lines = prepstr(chbuf, BUFSIZE, attr_normal, attr_keycode, 0, + lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_keycode, 0, 1, getmaxx(curwin) / 2 - 4, &width, 1, "^{^} Quit the game"); pr_left(curwin, 3, getmaxx(curwin) / 2, chbuf, lines, &width); - lines = prepstr(chbuf, BUFSIZE, attr_normal, attr_keycode, attr_choice, + lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_keycode, attr_choice, 1, getmaxx(curwin) / 2 - 4, &width, 1, "Select move [^[%c^]-^[%c^]/^{1^}-^{3^}/^{^}]: ", MOVE_TO_KEY(0), MOVE_TO_KEY(NUMBER_MOVES - 1)); @@ -270,7 +270,7 @@ selection_t get_move (void) selection = KEY_TO_MOVE(key); curs_set(CURS_OFF); - lines = prepstr(chbuf, BUFSIZE, attr_normal, attr_choice, 0, + lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_choice, 0, 1, getmaxx(curwin) / 2 - 4, &width, 1, "Move ^{%c^}", key); pr_left(curwin, 1, getmaxx(curwin) / 2, chbuf, lines, &width); @@ -286,7 +286,7 @@ selection_t get_move (void) selection = SEL_BANKRUPT; curs_set(CURS_OFF); - lines = prepstr(chbuf, BUFSIZE, attr_normal, + lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_normal | A_BOLD, 0, 1, getmaxx(curwin) / 2 - 4, &width, 1, "^{<2>^} (Declare bankruptcy)"); @@ -297,7 +297,7 @@ selection_t get_move (void) selection = SEL_SAVE; curs_set(CURS_OFF); - lines = prepstr(chbuf, BUFSIZE, attr_normal, + lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_normal | A_BOLD, 0, 1, getmaxx(curwin) / 2 - 4, &width, 1, "^{<3>^} (Save and end the game)"); @@ -313,7 +313,7 @@ selection_t get_move (void) selection = SEL_QUIT; curs_set(CURS_OFF); - lines = prepstr(chbuf, BUFSIZE, attr_normal, + lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_normal | A_BOLD, 0, 1, getmaxx(curwin) / 2 - 4, &width, 1, "^{^} (Quit the game)"); @@ -331,7 +331,7 @@ selection_t get_move (void) mvwhline(curwin, 3, 2, ' ' | attr_normal, getmaxx(curwin) - 4); // Ask the player to confirm their choice - lines = prepstr(chbuf, BUFSIZE, attr_normal, attr_keycode, 0, + lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_keycode, 0, 1, getmaxx(curwin) / 2 - 4, &width, 1, "Are you sure? [^{Y^}/^{N^}] "); pr_right(curwin, 2, getmaxx(curwin) / 2, chbuf, lines, &width); @@ -347,7 +347,7 @@ selection_t get_move (void) if (game_loaded) { // Save the game to the same game number - lines = prepstr(chbuf, BUFSIZE, attr_status_window, 0, 0, 1, + lines = mkchstr(chbuf, BUFSIZE, attr_status_window, 0, 0, 1, WIN_COLS - 7, &width, 1, "Saving game %d... ", game_num); newtxwin(5, width + 5, 7, WCENTER, true, attr_status_window); @@ -369,7 +369,7 @@ selection_t get_move (void) int maxwidth; - lines = prepstr(chbuf, BUFSIZE, attr_normal, attr_keycode, 0, + lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_keycode, 0, sizeof(widthbuf) / sizeof(widthbuf[0]), WIN_COLS - 7, widthbuf, sizeof(widthbuf) / sizeof(widthbuf[0]), @@ -417,7 +417,7 @@ selection_t get_move (void) // Try to save the game, if possible game_num = key - '0'; - lines = prepstr(chbuf, BUFSIZE, attr_status_window, + lines = mkchstr(chbuf, BUFSIZE, attr_status_window, 0, 0, 1, WIN_COLS - 7, &width, 1, "Saving game %d... ", game_num); newtxwin(5, width + 5, 7, WCENTER, true, attr_status_window); @@ -775,15 +775,15 @@ void merge_companies (map_val_t a, map_val_t b) newtxwin(number_players + 14, WIN_COLS - 4, 9 - number_players, WCENTER, true, attr_normal_window); - center(curwin, 1, attr_title, " Company Merger "); - center3(curwin, 3, attr_highlight, attr_highlight, attr_normal, + old_center(curwin, 1, attr_title, " Company Merger "); + old_center3(curwin, 3, attr_highlight, attr_highlight, attr_normal, company[bb].name, company[aa].name, " has just merged into "); - center(curwin, 5, attr_normal, "Please note the following transactions:"); + old_center(curwin, 5, attr_normal, "Please note the following transactions:"); - center2(curwin, 7, attr_normal, attr_highlight, " Old stock: ", + old_center2(curwin, 7, attr_normal, attr_highlight, " Old stock: ", "%-20s", company[bb].name); - center2(curwin, 8, attr_normal, attr_highlight, " New stock: ", + old_center2(curwin, 8, attr_normal, attr_highlight, " New stock: ", "%-20s", company[aa].name); // Handle the locale's currency symbol @@ -947,25 +947,25 @@ void adjust_values (void) newtxwin(14, 60, 4, WCENTER, true, attr_error_window); - center(curwin, 1, attr_error_title, " Bankruptcy Court "); - center(curwin, 3, attr_error_highlight, "%s has been declared", + old_center(curwin, 1, attr_error_title, " Bankruptcy Court "); + old_center(curwin, 3, attr_error_highlight, "%s has been declared", company[which].name); - center(curwin, 4, attr_error_highlight, + old_center(curwin, 4, attr_error_highlight, "bankrupt by the Interstellar Trading Bank."); - center2(curwin, 6, attr_error_normal, attr_error_highlight, + old_center2(curwin, 6, attr_error_normal, attr_error_highlight, "The Bank has agreed to pay stock holders ", "%4.2f%%", rate * 100.0); - center(curwin, 7, attr_error_normal, + old_center(curwin, 7, attr_error_normal, "of the share value on each share owned."); l_strfmon(buf, BUFSIZE, "%12n", company[which].share_price); - center2(curwin, 9, attr_error_normal, attr_error_highlight, + old_center2(curwin, 9, attr_error_normal, attr_error_highlight, "Old share value: ", "%s", buf); l_strfmon(buf, BUFSIZE, "%12n", company[which].share_price * rate); - center2(curwin, 10, attr_error_normal, attr_error_highlight, + old_center2(curwin, 10, attr_error_normal, attr_error_highlight, "Amount paid per share: ", "%s", buf); wait_for_key(curwin, 12, attr_error_waitforkey); From a6c362d2e8c87e88e5748717a476505fe9aa65bc Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Mon, 15 Aug 2011 19:46:26 +1000 Subject: [PATCH 035/112] Rename pr_left, pr_center and pr_right to leftch, centerch and rightch --- src/game.c | 26 +++++++++---------- src/help.c | 12 ++++----- src/intf.c | 58 +++++++++++++++++++++--------------------- src/intf.h | 74 +++++++++++++++++++++++++++--------------------------- src/move.c | 26 +++++++++---------- 5 files changed, 98 insertions(+), 98 deletions(-) diff --git a/src/game.c b/src/game.c index 93844aa..f76b093 100644 --- a/src/game.c +++ b/src/game.c @@ -117,7 +117,7 @@ void init_game (void) WIN_COLS - 7, &width, 1, "Loading game %d... ", game_num); newtxwin(5, width + 5, 6, WCENTER, true, attr_status_window); - pr_center(curwin, 2, 0, chbuf, 1, &width); + centerch(curwin, 2, 0, chbuf, 1, &width); wrefresh(curwin); game_loaded = load_game(game_num); @@ -152,7 +152,7 @@ void init_game (void) 0, 0, 1, WIN_COLS - 7, &width, 1, "Loading game %d... ", game_num); newtxwin(5, width + 5, 9, WCENTER, true, attr_status_window); - pr_center(curwin, 2, 0, chbuf, 1, &width); + centerch(curwin, 2, 0, chbuf, 1, &width); wrefresh(curwin); game_loaded = load_game(game_num); @@ -258,7 +258,7 @@ static int ask_number_players (void) maxwidth = ((lines == 1) ? widthbuf[0] : MAX(widthbuf[0], widthbuf[1])) + 5; newtxwin(lines + 4, maxwidth, 3, WCENTER, true, attr_normal_window); - pr_left(curwin, 2, 2, chbuf, lines, widthbuf); + leftch(curwin, 2, 2, chbuf, lines, widthbuf); free(chbuf); curs_set(CURS_ON); @@ -323,7 +323,7 @@ int ask_game_number (void) maxwidth = ((lines == 1) ? widthbuf[0] : MAX(widthbuf[0], widthbuf[1])) + 5; newtxwin(lines + 4, maxwidth, 6, WCENTER, true, attr_normal_window); - pr_left(curwin, 2, 2, chbuf, lines, widthbuf); + leftch(curwin, 2, 2, chbuf, lines, widthbuf); free(chbuf); curs_set(CURS_ON); @@ -393,7 +393,7 @@ void ask_player_names (void) "Do you need any instructions? [^{Y^}/^{N^}] "); newtxwin(5, width + YESNO_COLS + 4, 6, WCENTER, true, attr_normal_window); - pr_left(curwin, 2, 2, chbuf, lines, &width); + leftch(curwin, 2, 2, chbuf, lines, &width); free(chbuf); if (answer_yesno(curwin)) { show_help(); @@ -413,7 +413,7 @@ void ask_player_names (void) true, attr_normal_window); lines = mkchstr(chbuf, BUFSIZE, attr_title, 0, 0, 1, WIN_COLS - 8, &width, 1, " Enter Player Names "); - pr_center(curwin, 1, 0, chbuf, lines, &width); + centerch(curwin, 1, 0, chbuf, lines, &width); for (i = 0; i < number_players; i++) { player[i].name = NULL; @@ -499,7 +499,7 @@ void ask_player_names (void) "Does any player need instructions? [^{Y^}/^{N^}] "); newtxwin(5, width + YESNO_COLS + 4, 6, WCENTER, true, attr_normal_window); - pr_left(curwin, 2, 2, chbuf, lines, &width); + leftch(curwin, 2, 2, chbuf, lines, &width); if (answer_yesno(curwin)) { show_help(); } @@ -606,13 +606,13 @@ void show_map (bool closewin) lines = mkchstr(chbuf, BUFSIZE, attr_mapwin_title, attr_mapwin_highlight, 0, 1, WIN_COLS - 4, &width, 1, " Player: ^{%s^} ", player[current_player].name); - pr_left(curwin, 1, 2, chbuf, lines, &width); + leftch(curwin, 1, 2, chbuf, lines, &width); lines = mkchstr(chbuf, BUFSIZE, attr_mapwin_title, attr_mapwin_highlight, attr_mapwin_blink, 1, WIN_COLS / 2, &width, 1, (turn_number != max_turn) ? " Turn: ^{%d^} " : " ^[*** Last Turn ***^] ", turn_number); - pr_right(curwin, 1, WIN_COLS - 2, chbuf, lines, &width); + rightch(curwin, 1, WIN_COLS - 2, chbuf, lines, &width); wattrset(curwin, attr_map_window); @@ -681,19 +681,19 @@ void show_status (int num) chbuf = xmalloc(BUFSIZE * sizeof(chtype)); lines = mkchstr(chbuf, BUFSIZE, attr_title, 0, 0, 1, WIN_COLS - 4, &width, 1, " Stock Portfolio "); - pr_center(curwin, 1, 0, chbuf, lines, &width); + centerch(curwin, 1, 0, chbuf, lines, &width); lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_highlight, 0, 1, WIN_COLS - 4, &width, 1, "Player: ^{%s^}", player[num].name); - pr_center(curwin, 2, 0, chbuf, lines, &width); + centerch(curwin, 2, 0, chbuf, lines, &width); val = total_value(num); if (val == 0.0) { lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_highlight, attr_blink, 1, WIN_COLS - 4, &width, 1, "^[* * * B A N K R U P T * * *^]"); - pr_center(curwin, 11, 0, chbuf, lines, &width); + centerch(curwin, 11, 0, chbuf, lines, &width); } else { char *buf = xmalloc(BUFSIZE); @@ -711,7 +711,7 @@ void show_status (int num) lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_highlight, 0, 1, WIN_COLS - 4, &width, 1, "No companies on the map"); - pr_center(curwin, 8, 0, chbuf, lines, &width); + centerch(curwin, 8, 0, chbuf, lines, &width); } else { // Handle the locale's currency symbol snprintf(buf, BUFSIZE, "share (%s)", lconvinfo.currency_symbol); diff --git a/src/help.c b/src/help.c index 2dad035..4f9184f 100644 --- a/src/help.c +++ b/src/help.c @@ -205,12 +205,12 @@ void show_help (void) werase(curwin); wbkgd(curwin, attr_normal_window); box(curwin, 0, 0); - pr_center(curwin, 1, 0, ch_title, ln_title, &w_title); + centerch(curwin, 1, 0, ch_title, ln_title, &w_title); lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_highlight, 0, 1, WIN_COLS - 4, &width, 1, "Page %d of %d", curpage + 1, numpages); - pr_center(curwin, 2, 0, chbuf, lines, &width); + centerch(curwin, 2, 0, chbuf, lines, &width); wmove(curwin, 4, 2); // Process the help text string @@ -356,11 +356,11 @@ void show_help (void) } if (curpage == 0) { - pr_center(curwin, getmaxy(curwin) - 2, 0, ch_contfirst, - ln_contfirst, &w_contfirst); + centerch(curwin, getmaxy(curwin) - 2, 0, ch_contfirst, + ln_contfirst, &w_contfirst); } else { - pr_center(curwin, getmaxy(curwin) - 2, 0, ch_contnext, - ln_contnext, &w_contnext); + centerch(curwin, getmaxy(curwin) - 2, 0, ch_contnext, + ln_contnext, &w_contnext); } wrefresh(curwin); diff --git a/src/intf.c b/src/intf.c index 8a26435..e416456 100644 --- a/src/intf.c +++ b/src/intf.c @@ -418,7 +418,7 @@ void init_title (void) chbuf = xmalloc(BUFSIZE * sizeof(chtype)); lines = mkchstr(chbuf, BUFSIZE, attr_game_title, 0, 0, 1, COLS, &width, 1, _("Star Traders")); - pr_center(stdscr, 0, 0, chbuf, lines, &width); + centerch(stdscr, 0, 0, chbuf, lines, &width); attrset(attr_root_window); free(chbuf); } @@ -626,11 +626,11 @@ int txdlgbox (int maxlines, int ncols, int begin_y, int begin_x, titlelines = mkchstr(titlebuf, BUFSIZE, title_attr, 0, 0, 1, ncols - 4, &titlewidth, 1, boxtitle); - pr_center(curwin, 1, 0, titlebuf, titlelines, &titlewidth); + centerch(curwin, 1, 0, titlebuf, titlelines, &titlewidth); free(titlebuf); } - pr_center(curwin, usetitle ? 3 : 2, 0, chbuf, lines, widthbuf); + centerch(curwin, usetitle ? 3 : 2, 0, chbuf, lines, widthbuf); wait_for_key(curwin, getmaxy(curwin) - 2, keywait_attr); deltxwin(); @@ -1202,19 +1202,19 @@ error: /***********************************************************************/ // chstrdup: Duplicate a chtype buffer -chtype *chstrdup (const chtype *restrict chbuf, int chbufsize) +chtype *chstrdup (const chtype *restrict chstr, int chstrsize) { const chtype *p; int len; chtype *ret; - // Determine chbuf length, including ending NUL - for (len = 1, p = chbuf; *p != '\0' && len <= chbufsize; p++, len++) + // Determine chstr length, including ending NUL + for (len = 1, p = chstr; *p != '\0' && len <= chstrsize; p++, len++) ; ret = xmalloc(len * sizeof(chtype)); - memcpy(ret, chbuf, len * sizeof(chtype)); + memcpy(ret, chstr, len * sizeof(chtype)); ret[len - 1] = '\0'; // Terminating NUL, just in case not present return ret; @@ -1222,22 +1222,22 @@ chtype *chstrdup (const chtype *restrict chbuf, int chbufsize) /***********************************************************************/ -// pr_left: Print strings in chbuf left-aligned +// leftch: Print strings in chstr left-aligned -int pr_left (WINDOW *win, int y, int x, const chtype *restrict chbuf, - int lines, const int *restrict widthbuf) +int leftch (WINDOW *win, int y, int x, const chtype *restrict chstr, + int lines, const int *restrict widthbuf) { assert(win != NULL); - assert(chbuf != NULL); + assert(chstr != NULL); assert(lines > 0); assert(widthbuf != NULL); wmove(win, y, x); - for ( ; *chbuf != '\0'; chbuf++) { - if (*chbuf == '\n') { + for ( ; *chstr != '\0'; chstr++) { + if (*chstr == '\n') { wmove(win, getcury(win) + 1, x); } else { - waddch(win, *chbuf); + waddch(win, *chstr); } } @@ -1246,22 +1246,22 @@ int pr_left (WINDOW *win, int y, int x, const chtype *restrict chbuf, /***********************************************************************/ -// pr_center: Print strings in chbuf centred in window +// centerch: Print strings in chstr centred in window -int pr_center (WINDOW *win, int y, int offset, const chtype *restrict chbuf, - int lines, const int *restrict widthbuf) +int centerch (WINDOW *win, int y, int offset, const chtype *restrict chstr, + int lines, const int *restrict widthbuf) { int ln = 0; assert(win != NULL); - assert(chbuf != NULL); + assert(chstr != NULL); assert(lines > 0); assert(widthbuf != NULL); wmove(win, y, (getmaxx(win) - widthbuf[ln]) / 2 + offset); - for ( ; *chbuf != '\0'; chbuf++) { - if (*chbuf == '\n') { + for ( ; *chstr != '\0'; chstr++) { + if (*chstr == '\n') { if (ln++ >= lines) { return ERR; } else { @@ -1269,7 +1269,7 @@ int pr_center (WINDOW *win, int y, int offset, const chtype *restrict chbuf, (getmaxx(win) - widthbuf[ln]) / 2 + offset); } } else { - waddch(win, *chbuf); + waddch(win, *chstr); } } @@ -1278,29 +1278,29 @@ int pr_center (WINDOW *win, int y, int offset, const chtype *restrict chbuf, /***********************************************************************/ -// pr_right: Print strings in chbuf right-aligned +// rightch: Print strings in chstr right-aligned -int pr_right (WINDOW *win, int y, int x, const chtype *restrict chbuf, - int lines, const int *restrict widthbuf) +int rightch (WINDOW *win, int y, int x, const chtype *restrict chstr, + int lines, const int *restrict widthbuf) { int ln = 0; assert(win != NULL); - assert(chbuf != NULL); + assert(chstr != NULL); assert(lines > 0); assert(widthbuf != NULL); wmove(win, y, x - widthbuf[ln]); - for ( ; *chbuf != '\0'; chbuf++) { - if (*chbuf == '\n') { + for ( ; *chstr != '\0'; chstr++) { + if (*chstr == '\n') { if (ln++ >= lines) { return ERR; } else { wmove(win, getcury(win) + 1, x - widthbuf[ln]); } } else { - waddch(win, *chbuf); + waddch(win, *chstr); } } @@ -2449,7 +2449,7 @@ void wait_for_key (WINDOW *win, int y, chtype attr) chbuf = xmalloc(BUFSIZE * sizeof(chtype)); lines = mkchstr(chbuf, BUFSIZE, attr, 0, 0, 1, getmaxx(win) - 4, &width, 1, _("[ Press to continue ] ")); - pr_center(win, y, 0, chbuf, lines, &width); + centerch(win, y, 0, chbuf, lines, &width); wrefresh(win); done = false; diff --git a/src/intf.h b/src/intf.h index 622c85f..2e74e24 100644 --- a/src/intf.h +++ b/src/intf.h @@ -303,14 +303,14 @@ extern int txdlgbox (int maxlines, int ncols, int begin_y, int begin_x, Returns: int - Number of lines actually used This function converts the format string and following arguments into - chbuf, a chtype buffer that can be used for calls to pr_left(), - pr_center() and pr_right(). At most maxlines lines are used, each with - a maximum width of maxwidth. The actual widths of each resulting line - are stored in widthbuf (which must not be NULL). If maxlines is - greater than 1, lines are wrapped as needed. + chbuf, a chtype buffer that can be used for calls to leftch(), centerch() + and rightch(). At most maxlines lines are used, each with a maximum + width of maxwidth. The actual widths of each resulting line are stored + in widthbuf (which must not be NULL). If maxlines is greater than 1, + lines are wrapped as needed. The format string is similar to but more limited than printf(). In - particular, the following conversion specifiers are understood: + particular, only the following conversion specifiers are understood: %% - Print the ASCII percent sign (ASCII code U+0025) @@ -404,60 +404,60 @@ extern chtype *chstrdup (const chtype *restrict chstr, int chstrsize); /* - Function: pr_left - Print strings in chbuf left-aligned + Function: leftch - Print strings in chstr left-aligned Parameters: win - Window to use (should be curwin) y - Line on which to print first string x - Starting column number for each line - chbuf - chtype buffer as returned from mkchstr() - lines - Number of lines in chbuf (as returned from mkchstr()) - widthbuf - Widths of each line (as returned from mkchstr()) + chstr - chtype string as returned from mkchstr() + lines - Number of lines in chstr as returned from mkchstr() + widthbuf - Widths of each line as returned from mkchstr() Returns: int - Error code OK - This function takes the strings in the chtype array chbuf and prints + This function takes the strings in the chtype array chstr and prints them left-aligned in the window win. Note that wrefresh() is NOT called. */ -extern int pr_left (WINDOW *win, int y, int x, const chtype *restrict chbuf, - int lines, const int *restrict widthbuf); +extern int leftch (WINDOW *win, int y, int x, const chtype *restrict chstr, + int lines, const int *restrict widthbuf); /* - Function: pr_center - Print strings in chbuf centred in window - Parameters: win - Window to use (should be curwin) - y - Line on which to print first string - offset - Column offset to add to position for each line - chbuf - chtype buffer as returned from mkchstr() - lines - Number of lines in chbuf (as returned from mkchstr()) - widthbuf - Widths of each line (as returned from mkchstr()) - Returns: int - ERR if more lines in chbuf[] than lines, else OK + Function: centerch - Print strings in chstr centred in window + Parameters: win - Window to use (should be curwin) + y - Line on which to print first string + offset - Column offset to add to position for each line + chstr - chtype string as returned from mkchstr() + lines - Number of lines in chstr as returned from mkchstr() + widthbuf - Widths of each line as returned from mkchstr() + Returns: int - ERR if more lines in chstr[] than lines, else OK - This function takes the strings in the chtype array chbuf and prints + This function takes the strings in the chtype array chstr and prints them centred in the window win, offset by the parameter offset. Note that wrefresh() is NOT called. ERR is returned if there are more lines - in chbuf[] than are passed in the parameter lines. + in chstr[] than are passed in the parameter lines. */ -extern int pr_center (WINDOW *win, int y, int offset, - const chtype *restrict chbuf, int lines, - const int *restrict widthbuf); +extern int centerch (WINDOW *win, int y, int offset, + const chtype *restrict chstr, int lines, + const int *restrict widthbuf); /* - Function: pr_right - Print strings in chbuf right-aligned + Function: rightch - Print strings in chstr right-aligned Parameters: win - Window to use (should be curwin) y - Line on which to print first string x - Ending column number for each line - chbuf - chtype buffer as returned from mkchstr() - lines - Number of lines in chbuf (as returned from mkchstr()) - widthbuf - Widths of each line (as returned from mkchstr()) - Returns: int - ERR if more lines in chbuf[] than lines, else OK + chstr - chtype string as returned from mkchstr() + lines - Number of lines in chstr as returned from mkchstr() + widthbuf - Widths of each line as returned from mkchstr() + Returns: int - ERR if more lines in chstr[] than lines, else OK - This function takes the strings in the chtype array chbuf and prints - them right-aligned in the window win, with each line ending at column - x. Note that wrefresh() is NOT called. ERR is returned if there are - more lines in chbuf[] than are passed in the parameter lines. + This function takes the strings in the chtype array chstr and prints + them right-aligned in the window win, with each line ending just before + column x. Note that wrefresh() is NOT called. ERR is returned if + there are more lines in chstr[] than are passed in the parameter lines. */ -extern int pr_right (WINDOW *win, int y, int x, const chtype *restrict chbuf, - int lines, const int *restrict widthbuf); +extern int rightch (WINDOW *win, int y, int x, const chtype *restrict chstr, + int lines, const int *restrict widthbuf); /* diff --git a/src/move.c b/src/move.c index f6e97f1..17c86f9 100644 --- a/src/move.c +++ b/src/move.c @@ -236,28 +236,28 @@ selection_t get_move (void) lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_keycode, 0, 1, getmaxx(curwin) / 2 - 4, &width, 1, "^{<1>^} Display stock portfolio"); - pr_left(curwin, 2, 2, chbuf, lines, &width); + leftch(curwin, 2, 2, chbuf, lines, &width); lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_keycode, 0, 1, getmaxx(curwin) / 2 - 4, &width, 1, "^{<2>^} Declare bankruptcy"); - pr_left(curwin, 3, 2, chbuf, lines, &width); + leftch(curwin, 3, 2, chbuf, lines, &width); lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_keycode, 0, 1, getmaxx(curwin) / 2 - 4, &width, 1, "^{<3>^} Save and end the game"); - pr_left(curwin, 2, getmaxx(curwin) / 2, chbuf, lines, &width); + leftch(curwin, 2, getmaxx(curwin) / 2, chbuf, lines, &width); lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_keycode, 0, 1, getmaxx(curwin) / 2 - 4, &width, 1, "^{^} Quit the game"); - pr_left(curwin, 3, getmaxx(curwin) / 2, chbuf, lines, &width); + leftch(curwin, 3, getmaxx(curwin) / 2, chbuf, lines, &width); lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_keycode, attr_choice, 1, getmaxx(curwin) / 2 - 4, &width, 1, "Select move [^[%c^]-^[%c^]/^{1^}-^{3^}/^{^}]: ", MOVE_TO_KEY(0), MOVE_TO_KEY(NUMBER_MOVES - 1)); - pr_right(curwin, 1, getmaxx(curwin) / 2, chbuf, lines, &width); + rightch(curwin, 1, getmaxx(curwin) / 2, chbuf, lines, &width); curs_set(CURS_ON); wrefresh(curwin); @@ -273,7 +273,7 @@ selection_t get_move (void) lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_choice, 0, 1, getmaxx(curwin) / 2 - 4, &width, 1, "Move ^{%c^}", key); - pr_left(curwin, 1, getmaxx(curwin) / 2, chbuf, lines, &width); + leftch(curwin, 1, getmaxx(curwin) / 2, chbuf, lines, &width); } else { switch (key) { case '1': @@ -290,7 +290,7 @@ selection_t get_move (void) attr_normal | A_BOLD, 0, 1, getmaxx(curwin) / 2 - 4, &width, 1, "^{<2>^} (Declare bankruptcy)"); - pr_left(curwin, 1, getmaxx(curwin) / 2, chbuf, lines, &width); + leftch(curwin, 1, getmaxx(curwin) / 2, chbuf, lines, &width); break; case '3': @@ -301,7 +301,7 @@ selection_t get_move (void) attr_normal | A_BOLD, 0, 1, getmaxx(curwin) / 2 - 4, &width, 1, "^{<3>^} (Save and end the game)"); - pr_left(curwin, 1, getmaxx(curwin) / 2, chbuf, lines, &width); + leftch(curwin, 1, getmaxx(curwin) / 2, chbuf, lines, &width); break; case KEY_ESC: @@ -317,7 +317,7 @@ selection_t get_move (void) attr_normal | A_BOLD, 0, 1, getmaxx(curwin) / 2 - 4, &width, 1, "^{^} (Quit the game)"); - pr_left(curwin, 1, getmaxx(curwin) / 2, chbuf, lines, &width); + leftch(curwin, 1, getmaxx(curwin) / 2, chbuf, lines, &width); break; default: @@ -334,7 +334,7 @@ selection_t get_move (void) lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_keycode, 0, 1, getmaxx(curwin) / 2 - 4, &width, 1, "Are you sure? [^{Y^}/^{N^}] "); - pr_right(curwin, 2, getmaxx(curwin) / 2, chbuf, lines, &width); + rightch(curwin, 2, getmaxx(curwin) / 2, chbuf, lines, &width); wrefresh(curwin); if (! answer_yesno(curwin)) { @@ -351,7 +351,7 @@ selection_t get_move (void) WIN_COLS - 7, &width, 1, "Saving game %d... ", game_num); newtxwin(5, width + 5, 7, WCENTER, true, attr_status_window); - pr_center(curwin, 2, 0, chbuf, 1, &width); + centerch(curwin, 2, 0, chbuf, 1, &width); wrefresh(curwin); saved = save_game(game_num); @@ -381,7 +381,7 @@ selection_t get_move (void) newtxwin(lines + 4, maxwidth, 8, WCENTER, true, attr_normal_window); - pr_left(curwin, 2, 2, chbuf, lines, widthbuf); + leftch(curwin, 2, 2, chbuf, lines, widthbuf); curs_set(CURS_ON); wrefresh(curwin); @@ -421,7 +421,7 @@ selection_t get_move (void) 0, 0, 1, WIN_COLS - 7, &width, 1, "Saving game %d... ", game_num); newtxwin(5, width + 5, 7, WCENTER, true, attr_status_window); - pr_center(curwin, 2, 0, chbuf, 1, &width); + centerch(curwin, 2, 0, chbuf, 1, &width); wrefresh(curwin); saved = save_game(game_num); From 665605d1448bd25f298b2f6ce6555b85da0fa96e Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Mon, 15 Aug 2011 21:04:07 +1000 Subject: [PATCH 036/112] Add convenience functions left(), center() and right() --- src/game.c | 109 +++++++++++++++++------------------------------- src/help.c | 55 ++++--------------------- src/intf.c | 119 +++++++++++++++++++++++++++++++++++++---------------- src/intf.h | 65 ++++++++++++++++++++++++++++- src/move.c | 98 +++++++++++++++++-------------------------- 5 files changed, 231 insertions(+), 215 deletions(-) diff --git a/src/game.c b/src/game.c index f76b093..c3dde3d 100644 --- a/src/game.c +++ b/src/game.c @@ -111,11 +111,10 @@ void init_game (void) // Try to load an old game, if possible if (game_num != 0) { chtype *chbuf = xmalloc(BUFSIZE * sizeof(chtype)); - int lines, width; + int width; - lines = mkchstr(chbuf, BUFSIZE, attr_status_window, 0, 0, 1, - WIN_COLS - 7, &width, 1, - "Loading game %d... ", game_num); + mkchstr(chbuf, BUFSIZE, attr_status_window, 0, 0, 1, WIN_COLS - 7, + &width, 1, "Loading game %d... ", game_num); newtxwin(5, width + 5, 6, WCENTER, true, attr_status_window); centerch(curwin, 2, 0, chbuf, 1, &width); wrefresh(curwin); @@ -144,13 +143,13 @@ void init_game (void) // Try to load the game, if possible chtype *chbuf = xmalloc(BUFSIZE * sizeof(chtype)); - int lines, width; + int width; game_num = choice; - lines = mkchstr(chbuf, BUFSIZE, attr_status_window, - 0, 0, 1, WIN_COLS - 7, &width, 1, - "Loading game %d... ", game_num); + mkchstr(chbuf, BUFSIZE, attr_status_window, 0, 0, 1, + WIN_COLS - 7, &width, 1, + "Loading game %d... ", game_num); newtxwin(5, width + 5, 9, WCENTER, true, attr_status_window); centerch(curwin, 2, 0, chbuf, 1, &width); wrefresh(curwin); @@ -249,10 +248,8 @@ static int ask_number_players (void) chbuf = xmalloc(BUFSIZE * sizeof(chtype)); - lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_keycode, 0, - sizeof(widthbuf) / sizeof(widthbuf[0]), WIN_COLS - 7, - widthbuf, sizeof(widthbuf) / sizeof(widthbuf[0]), - "Enter number of players [^{1^}-^{%d^}] " + lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_keycode, 0, 2, WIN_COLS + - 7, widthbuf, 2, "Enter number of players [^{1^}-^{%d^}] " "or ^{^} to continue a game: ", MAX_PLAYERS); assert(lines == 1 || lines == 2); maxwidth = ((lines == 1) ? widthbuf[0] : MAX(widthbuf[0], widthbuf[1])) + 5; @@ -314,10 +311,8 @@ int ask_game_number (void) chbuf = xmalloc(BUFSIZE * sizeof(chtype)); - lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_keycode, 0, - sizeof(widthbuf) / sizeof(widthbuf[0]), WIN_COLS - 7, - widthbuf, sizeof(widthbuf) / sizeof(widthbuf[0]), - "Enter game number [^{1^}-^{9^}] " + lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_keycode, 0, 2, WIN_COLS + - 7, widthbuf, 2, "Enter game number [^{1^}-^{9^}] " "or ^{^} to cancel: "); assert(lines == 1 || lines == 2); maxwidth = ((lines == 1) ? widthbuf[0] : MAX(widthbuf[0], widthbuf[1])) + 5; @@ -365,11 +360,15 @@ int ask_game_number (void) void ask_player_names (void) { + chtype *chbuf = xmalloc(BUFSIZE * sizeof(chtype)); + int width; + + if (number_players == 1) { // Ask for the player's name newtxwin(5, WIN_COLS - 4, 9, WCENTER, true, attr_normal_window); - mvwaddstr(curwin, 2, 2, "Please enter your name: "); + left(curwin, 2, 2, attr_normal, 0, 0, "Please enter your name: "); int x = getcurx(curwin); int w = getmaxx(curwin) - x - 2; @@ -385,16 +384,13 @@ void ask_player_names (void) } } - chtype *chbuf = xmalloc(BUFSIZE * sizeof(chtype)); - int lines, width; - - lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_keycode, 0, - 1, WIN_COLS - YESNO_COLS - 6, &width, 1, - "Do you need any instructions? [^{Y^}/^{N^}] "); + mkchstr(chbuf, BUFSIZE, attr_normal, attr_keycode, 0, 1, + WIN_COLS - YESNO_COLS - 6, &width, 1, + "Do you need any instructions? [^{Y^}/^{N^}] "); newtxwin(5, width + YESNO_COLS + 4, 6, WCENTER, true, attr_normal_window); - leftch(curwin, 2, 2, chbuf, lines, &width); - free(chbuf); + leftch(curwin, 2, 2, chbuf, 1, &width); + if (answer_yesno(curwin)) { show_help(); } @@ -402,23 +398,18 @@ void ask_player_names (void) } else { // Ask for all of the player names - chtype *chbuf = xmalloc(BUFSIZE * sizeof(chtype)); - int lines, width; - bool entered[MAX_PLAYERS]; bool done, modified; int cur, len, i; newtxwin(number_players + 5, WIN_COLS - 4, 9, WCENTER, true, attr_normal_window); - lines = mkchstr(chbuf, BUFSIZE, attr_title, 0, 0, 1, WIN_COLS - 8, - &width, 1, " Enter Player Names "); - centerch(curwin, 1, 0, chbuf, lines, &width); + center(curwin, 1, 0, attr_title, 0, 0, " Enter Player Names "); for (i = 0; i < number_players; i++) { player[i].name = NULL; entered[i] = false; - mvwprintw(curwin, i + 3, 2, "Player %d:", i + 1); + left(curwin, i + 3, 2, attr_normal, 0, 0, "Player %d:", i + 1); } int x = getcurx(curwin) + 1; @@ -494,21 +485,21 @@ void ask_player_names (void) } } - lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_keycode, 0, - 1, WIN_COLS - YESNO_COLS - 6, &width, 1, - "Does any player need instructions? [^{Y^}/^{N^}] "); + mkchstr(chbuf, BUFSIZE, attr_normal, attr_keycode, 0, 1, + WIN_COLS - YESNO_COLS - 6, &width, 1, + "Does any player need instructions? [^{Y^}/^{N^}] "); newtxwin(5, width + YESNO_COLS + 4, 6, WCENTER, true, attr_normal_window); - leftch(curwin, 2, 2, chbuf, lines, &width); + leftch(curwin, 2, 2, chbuf, 1, &width); + if (answer_yesno(curwin)) { show_help(); } - - free(chbuf); } deltxwin(); // "Need instructions?" window deltxwin(); // "Enter player names" window + free(chbuf); } @@ -589,8 +580,6 @@ void end_game (void) void show_map (bool closewin) { - chtype *chbuf = xmalloc(BUFSIZE * sizeof(chtype)); - int lines, width; int x, y; @@ -603,16 +592,11 @@ void show_map (bool closewin) mvwhline(curwin, 1, 2, ' ' | attr_mapwin_title, getmaxx(curwin) - 4); // Display current player and turn number - lines = mkchstr(chbuf, BUFSIZE, attr_mapwin_title, attr_mapwin_highlight, - 0, 1, WIN_COLS - 4, &width, 1, " Player: ^{%s^} ", - player[current_player].name); - leftch(curwin, 1, 2, chbuf, lines, &width); - - lines = mkchstr(chbuf, BUFSIZE, attr_mapwin_title, attr_mapwin_highlight, - attr_mapwin_blink, 1, WIN_COLS / 2, &width, 1, - (turn_number != max_turn) ? " Turn: ^{%d^} " : - " ^[*** Last Turn ***^] ", turn_number); - rightch(curwin, 1, WIN_COLS - 2, chbuf, lines, &width); + left(curwin, 1, 2, attr_mapwin_title, attr_mapwin_highlight, 0, + " Player: ^{%s^} ", player[current_player].name); + right(curwin, 1, getmaxx(curwin) - 2, attr_mapwin_title, + attr_mapwin_highlight, attr_mapwin_blink, (turn_number != max_turn) ? + " Turn: ^{%d^} " : " ^[*** Last Turn ***^] ", turn_number); wattrset(curwin, attr_map_window); @@ -657,8 +641,6 @@ void show_map (bool closewin) deltxwin(); // Galaxy map window txrefresh(); } - - free(chbuf); } @@ -667,8 +649,6 @@ void show_map (bool closewin) void show_status (int num) { - chtype *chbuf; - int lines, width; double val; int i, line; @@ -677,24 +657,14 @@ void show_status (int num) newtxwin(MAX_COMPANIES + 15, WIN_COLS, 1, WCENTER, true, attr_normal_window); - - chbuf = xmalloc(BUFSIZE * sizeof(chtype)); - lines = mkchstr(chbuf, BUFSIZE, attr_title, 0, 0, 1, WIN_COLS - 4, - &width, 1, " Stock Portfolio "); - centerch(curwin, 1, 0, chbuf, lines, &width); - - lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_highlight, 0, 1, - WIN_COLS - 4, &width, 1, "Player: ^{%s^}", + center(curwin, 1, 0, attr_title, 0, 0, " Stock Portfolio "); + center(curwin, 2, 0, attr_normal, attr_highlight, 0, "Player: ^{%s^}", player[num].name); - centerch(curwin, 2, 0, chbuf, lines, &width); val = total_value(num); if (val == 0.0) { - lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_highlight, - attr_blink, 1, WIN_COLS - 4, &width, 1, + center(curwin, 11, 0, attr_normal, attr_highlight, attr_blink, "^[* * * B A N K R U P T * * *^]"); - centerch(curwin, 11, 0, chbuf, lines, &width); - } else { char *buf = xmalloc(BUFSIZE); @@ -708,10 +678,8 @@ void show_status (int num) } if (none) { - lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_highlight, 0, - 1, WIN_COLS - 4, &width, 1, + center(curwin, 8, 0, attr_normal, attr_highlight, 0, "No companies on the map"); - centerch(curwin, 8, 0, chbuf, lines, &width); } else { // Handle the locale's currency symbol snprintf(buf, BUFSIZE, "share (%s)", lconvinfo.currency_symbol); @@ -761,7 +729,6 @@ void show_status (int num) wait_for_key(curwin, getmaxy(curwin) - 2, attr_waitforkey); deltxwin(); txrefresh(); - free(chbuf); } diff --git a/src/help.c b/src/help.c index 4f9184f..ac02394 100644 --- a/src/help.c +++ b/src/help.c @@ -157,45 +157,17 @@ static const char *help_text[] = { void show_help (void) { - chtype *chbuf = xmalloc(BUFSIZE * sizeof(chtype)); - int lines, width; - int curpage = 0; int numpages; bool done = false; - chtype *ch_title; // Title string - chtype *ch_contfirst; // "Continue", first page - chtype *ch_contnext; // "Continue", following pages - int w_title, ln_title; - int w_contfirst, ln_contfirst; - int w_contnext, ln_contnext; - // Count how many pages appear in the help text for (numpages = 0; help_text[numpages] != NULL; numpages++) ; - if (numpages == 0) { - free(chbuf); + if (numpages == 0) return; - } - - // Prepare fixed-text strings - ln_title = mkchstr(chbuf, BUFSIZE, attr_title, 0, 0, 1, WIN_COLS - 4, - &w_title, 1, " How to Play "); - ch_title = chstrdup(chbuf, BUFSIZE); - - ln_contfirst = mkchstr(chbuf, BUFSIZE, attr_waitforkey, 0, 0, 1, - WIN_COLS - 4, &w_contfirst, 1, - "[ Press to continue ] "); - ch_contfirst = chstrdup(chbuf, BUFSIZE); - - ln_contnext = mkchstr(chbuf, BUFSIZE, attr_waitforkey, 0, 0, 1, - WIN_COLS - 4, &w_contnext, 1, - "[ Press to continue or " - " for the previous page ] "); - ch_contnext = chstrdup(chbuf, BUFSIZE); newtxwin(WIN_LINES - 1, WIN_COLS, 1, WCENTER, false, 0); @@ -205,12 +177,10 @@ void show_help (void) werase(curwin); wbkgd(curwin, attr_normal_window); box(curwin, 0, 0); - centerch(curwin, 1, 0, ch_title, ln_title, &w_title); - lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_highlight, 0, 1, - WIN_COLS - 4, &width, 1, "Page %d of %d", - curpage + 1, numpages); - centerch(curwin, 2, 0, chbuf, lines, &width); + center(curwin, 1, 0, attr_title, 0, 0, " How to Play "); + center(curwin, 2, 0, attr_normal, attr_highlight, 0, + "Page %d of %d", curpage + 1, numpages); wmove(curwin, 4, 2); // Process the help text string @@ -355,14 +325,10 @@ void show_help (void) s++; } - if (curpage == 0) { - centerch(curwin, getmaxy(curwin) - 2, 0, ch_contfirst, - ln_contfirst, &w_contfirst); - } else { - centerch(curwin, getmaxy(curwin) - 2, 0, ch_contnext, - ln_contnext, &w_contnext); - } - + center(curwin, getmaxy(curwin) - 2, 0, attr_waitforkey, 0, 0, + (curpage == 0) ? "[ Press to continue ] " : + "[ Press to continue or " + "for the previous page ] "); wrefresh(curwin); int key = gettxchar(curwin); @@ -399,9 +365,4 @@ void show_help (void) deltxwin(); txrefresh(); - - free(ch_title); - free(ch_contfirst); - free(ch_contnext); - free(chbuf); } diff --git a/src/intf.c b/src/intf.c index e416456..4f3e1e1 100644 --- a/src/intf.c +++ b/src/intf.c @@ -402,25 +402,12 @@ void end_screen (void) void init_title (void) { - chtype *chbuf; - int width; - int lines; - - bkgd(attr_root_window); + attrset(attr_root_window); clear(); - move(0, 0); - for (int i = 0; i < COLS; i++) { - addch(attr_game_title | ' '); - } - - chbuf = xmalloc(BUFSIZE * sizeof(chtype)); - lines = mkchstr(chbuf, BUFSIZE, attr_game_title, 0, 0, 1, COLS, - &width, 1, _("Star Traders")); - centerch(stdscr, 0, 0, chbuf, lines, &width); - attrset(attr_root_window); - free(chbuf); + mvwhline(stdscr, 0, 0, ' ' | attr_game_title, COLS); + center(stdscr, 0, 0, attr_game_title, 0, 0, _("Star Traders")); } @@ -620,14 +607,7 @@ int txdlgbox (int maxlines, int ncols, int begin_y, int begin_x, true, bkgd_attr); if (usetitle) { - chtype *titlebuf = xmalloc(BUFSIZE * sizeof(chtype)); - int titlewidth; - int titlelines; - - titlelines = mkchstr(titlebuf, BUFSIZE, title_attr, 0, 0, 1, - ncols - 4, &titlewidth, 1, boxtitle); - centerch(curwin, 1, 0, titlebuf, titlelines, &titlewidth); - free(titlebuf); + center(curwin, 1, 0, title_attr, 0, 0, boxtitle); } centerch(curwin, usetitle ? 3 : 2, 0, chbuf, lines, widthbuf); @@ -654,8 +634,7 @@ int mkchstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, va_start(args, format); lines = vmkchstr(chbuf, chbufsize, attr_norm, attr_alt1, attr_alt2, - maxlines, maxwidth, widthbuf, widthbufsize, format, - args); + maxlines, maxwidth, widthbuf, widthbufsize, format, args); va_end(args); return lines; } @@ -1308,6 +1287,84 @@ int rightch (WINDOW *win, int y, int x, const chtype *restrict chstr, } +/***********************************************************************/ +// left: Print strings left-aligned + +int left (WINDOW *win, int y, int x, chtype attr_norm, chtype attr_alt1, + chtype attr_alt2, const char *restrict format, ...) +{ + va_list args; + chtype *chbuf = xmalloc(BUFSIZE * sizeof(chtype)); + int widthbuf[MAX_DLG_LINES]; + int lines; + int ret; + + + va_start(args, format); + lines = vmkchstr(chbuf, BUFSIZE, attr_norm, attr_alt1, attr_alt2, + MAX_DLG_LINES, getmaxx(win) - x - 2, widthbuf, + MAX_DLG_LINES, format, args); + ret = leftch(win, y, x, chbuf, lines, widthbuf); + assert(ret == OK); + va_end(args); + + free(chbuf); + return ret; +} + + +/***********************************************************************/ +// center: Print strings centred in window + +int center (WINDOW *win, int y, int offset, chtype attr_norm, chtype attr_alt1, + chtype attr_alt2, const char *restrict format, ...) +{ + va_list args; + chtype *chbuf = xmalloc(BUFSIZE * sizeof(chtype)); + int widthbuf[MAX_DLG_LINES]; + int lines; + int ret; + + + va_start(args, format); + lines = vmkchstr(chbuf, BUFSIZE, attr_norm, attr_alt1, attr_alt2, + MAX_DLG_LINES, getmaxx(win) - 4, widthbuf, + MAX_DLG_LINES, format, args); + ret = centerch(win, y, offset, chbuf, lines, widthbuf); + assert(ret == OK); + va_end(args); + + free(chbuf); + return ret; +} + + +/***********************************************************************/ +// right: Print strings right-aligned + +int right (WINDOW *win, int y, int x, chtype attr_norm, chtype attr_alt1, + chtype attr_alt2, const char *restrict format, ...) +{ + va_list args; + chtype *chbuf = xmalloc(BUFSIZE * sizeof(chtype)); + int widthbuf[MAX_DLG_LINES]; + int lines; + int ret; + + + va_start(args, format); + lines = vmkchstr(chbuf, BUFSIZE, attr_norm, attr_alt1, attr_alt2, + MAX_DLG_LINES, x - 2, widthbuf, MAX_DLG_LINES, + format, args); + ret = rightch(win, y, x, chbuf, lines, widthbuf); + assert(ret == OK); + va_end(args); + + free(chbuf); + return ret; +} + + /***********************************************************************/ // old_attrpr: Print a string with a particular character rendition @@ -2435,9 +2492,6 @@ bool answer_yesno (WINDOW *win) void wait_for_key (WINDOW *win, int y, chtype attr) { - chtype *chbuf; - int width; - int lines; int key; bool done; @@ -2446,10 +2500,7 @@ void wait_for_key (WINDOW *win, int y, chtype attr) meta(win, true); wtimeout(win, -1); - chbuf = xmalloc(BUFSIZE * sizeof(chtype)); - lines = mkchstr(chbuf, BUFSIZE, attr, 0, 0, 1, getmaxx(win) - 4, - &width, 1, _("[ Press to continue ] ")); - centerch(win, y, 0, chbuf, lines, &width); + center(curwin, y, 0, attr, 0, 0, _("[ Press to continue ] ")); wrefresh(win); done = false; @@ -2470,8 +2521,6 @@ void wait_for_key (WINDOW *win, int y, chtype attr) done = true; } } - - free(chbuf); } diff --git a/src/intf.h b/src/intf.h index 2e74e24..4541bc4 100644 --- a/src/intf.h +++ b/src/intf.h @@ -411,7 +411,7 @@ extern chtype *chstrdup (const chtype *restrict chstr, int chstrsize); chstr - chtype string as returned from mkchstr() lines - Number of lines in chstr as returned from mkchstr() widthbuf - Widths of each line as returned from mkchstr() - Returns: int - Error code OK + Returns: int - Always returns OK This function takes the strings in the chtype array chstr and prints them left-aligned in the window win. Note that wrefresh() is NOT @@ -460,6 +460,69 @@ extern int rightch (WINDOW *win, int y, int x, const chtype *restrict chstr, int lines, const int *restrict widthbuf); +/* + Function: left - Print strings left-aligned + Parameters: win - Window to use (should be curwin) + y - Line on which to print first string + x - Starting column number for each line + attr_norm - Normal character rendition to use + attr_alt1 - First alternate character rendition to use + attr_alt2 - Second alternate character rendition to use + format - Format string as described for mkchstr() + ... - Arguments for the format string + Returns: int - Always returns OK + + This shortcut function prepares a chtype string using mkchstr(), then + prints the string using leftch(). At most MAX_DLG_LINES are printed, + with the maximum width being that of the window win - x - 2 (the "2" is + for the right-hand border). +*/ +extern int left (WINDOW *win, int y, int x, chtype attr_norm, chtype attr_alt1, + chtype attr_alt2, const char *restrict format, ...); + + +/* + Function: center - Print strings centred in window + Parameters: win - Window to use (should be curwin) + y - Line on which to print first string + offset - Column offset to add to position for each line + attr_norm - Normal character rendition to use + attr_alt1 - First alternate character rendition to use + attr_alt2 - Second alternate character rendition to use + format - Format string as described for mkchstr() + ... - Arguments for the format string + Returns: int - Always returns OK + + This shortcut function prepares a chtype string using mkchstr(), then + prints the string using centerch(). At most MAX_DLG_LINES are printed, + with the maximum width being that of the window win - 4 (for borders). +*/ +extern int center (WINDOW *win, int y, int offset, chtype attr_norm, + chtype attr_alt1, chtype attr_alt2, + const char *restrict format, ...); + + +/* + Function: right - Print strings right-aligned + Parameters: win - Window to use (should be curwin) + y - Line on which to print first string + x - Ending column number for each line + attr_norm - Normal character rendition to use + attr_alt1 - First alternate character rendition to use + attr_alt2 - Second alternate character rendition to use + format - Format string as described for mkchstr() + ... - Arguments for the format string + Returns: int - Always returns OK + + This shortcut function prepares a chtype string using mkchstr(), then + prints the string using rightch(). At most MAX_DLG_LINES are printed, + with the maximum width being that of x - 2 (the "2" is for the + left-hand border). +*/ +extern int right (WINDOW *win, int y, int x, chtype attr_norm, chtype attr_alt1, + chtype attr_alt2, const char *restrict format, ...); + + /* Function: old_attrpr - Print a string with a particular character rendition Parameters: win - Window to use (should be curwin) diff --git a/src/move.c b/src/move.c index 17c86f9..a727593 100644 --- a/src/move.c +++ b/src/move.c @@ -208,8 +208,6 @@ void select_moves (void) selection_t get_move (void) { selection_t selection = SEL_NONE; - chtype *chbuf = xmalloc(BUFSIZE * sizeof(chtype)); - int lines, width; if (quit_selected || abort_game) { @@ -233,31 +231,19 @@ selection_t get_move (void) werase(curwin); box(curwin, 0, 0); - lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_keycode, 0, - 1, getmaxx(curwin) / 2 - 4, &width, 1, - "^{<1>^} Display stock portfolio"); - leftch(curwin, 2, 2, chbuf, lines, &width); + left(curwin, 2, 2, attr_normal, attr_keycode, 0, + "^{<1>^} Display stock portfolio"); + left(curwin, 3, 2, attr_normal, attr_keycode, 0, + "^{<2>^} Declare bankruptcy"); + left(curwin, 2, getmaxx(curwin) / 2, attr_normal, attr_keycode, 0, + "^{<3>^} Save and end the game"); + left(curwin, 3, getmaxx(curwin) / 2, attr_normal, attr_keycode, 0, + "^{^} Quit the game"); - lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_keycode, 0, - 1, getmaxx(curwin) / 2 - 4, &width, 1, - "^{<2>^} Declare bankruptcy"); - leftch(curwin, 3, 2, chbuf, lines, &width); - - lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_keycode, 0, - 1, getmaxx(curwin) / 2 - 4, &width, 1, - "^{<3>^} Save and end the game"); - leftch(curwin, 2, getmaxx(curwin) / 2, chbuf, lines, &width); - - lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_keycode, 0, - 1, getmaxx(curwin) / 2 - 4, &width, 1, - "^{^} Quit the game"); - leftch(curwin, 3, getmaxx(curwin) / 2, chbuf, lines, &width); - - lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_keycode, attr_choice, - 1, getmaxx(curwin) / 2 - 4, &width, 1, - "Select move [^[%c^]-^[%c^]/^{1^}-^{3^}/^{^}]: ", - MOVE_TO_KEY(0), MOVE_TO_KEY(NUMBER_MOVES - 1)); - rightch(curwin, 1, getmaxx(curwin) / 2, chbuf, lines, &width); + right(curwin, 1, getmaxx(curwin) / 2, attr_normal, attr_keycode, + attr_choice, "Select move " + "[^[%c^]-^[%c^]/^{1^}-^{3^}/^{^}]: ", + MOVE_TO_KEY(0), MOVE_TO_KEY(NUMBER_MOVES - 1)); curs_set(CURS_ON); wrefresh(curwin); @@ -270,10 +256,8 @@ selection_t get_move (void) selection = KEY_TO_MOVE(key); curs_set(CURS_OFF); - lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_choice, 0, - 1, getmaxx(curwin) / 2 - 4, &width, 1, - "Move ^{%c^}", key); - leftch(curwin, 1, getmaxx(curwin) / 2, chbuf, lines, &width); + left(curwin, 1, getmaxx(curwin) / 2, attr_normal, attr_choice, + 0, "Move ^{%c^}", key); } else { switch (key) { case '1': @@ -286,22 +270,18 @@ selection_t get_move (void) selection = SEL_BANKRUPT; curs_set(CURS_OFF); - lines = mkchstr(chbuf, BUFSIZE, attr_normal, - attr_normal | A_BOLD, 0, 1, - getmaxx(curwin) / 2 - 4, &width, 1, - "^{<2>^} (Declare bankruptcy)"); - leftch(curwin, 1, getmaxx(curwin) / 2, chbuf, lines, &width); + left(curwin, 1, getmaxx(curwin) / 2, attr_normal, + attr_normal | A_BOLD, 0, + "^{<2>^} (Declare bankruptcy)"); break; case '3': selection = SEL_SAVE; curs_set(CURS_OFF); - lines = mkchstr(chbuf, BUFSIZE, attr_normal, - attr_normal | A_BOLD, 0, 1, - getmaxx(curwin) / 2 - 4, &width, 1, - "^{<3>^} (Save and end the game)"); - leftch(curwin, 1, getmaxx(curwin) / 2, chbuf, lines, &width); + left(curwin, 1, getmaxx(curwin) / 2, attr_normal, + attr_normal | A_BOLD, 0, + "^{<3>^} (Save and end the game)"); break; case KEY_ESC: @@ -313,11 +293,9 @@ selection_t get_move (void) selection = SEL_QUIT; curs_set(CURS_OFF); - lines = mkchstr(chbuf, BUFSIZE, attr_normal, - attr_normal | A_BOLD, 0, 1, - getmaxx(curwin) / 2 - 4, &width, 1, - "^{^} (Quit the game)"); - leftch(curwin, 1, getmaxx(curwin) / 2, chbuf, lines, &width); + left(curwin, 1, getmaxx(curwin) / 2, attr_normal, + attr_normal | A_BOLD, 0, + "^{^} (Quit the game)"); break; default: @@ -331,10 +309,8 @@ selection_t get_move (void) mvwhline(curwin, 3, 2, ' ' | attr_normal, getmaxx(curwin) - 4); // Ask the player to confirm their choice - lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_keycode, 0, - 1, getmaxx(curwin) / 2 - 4, &width, 1, - "Are you sure? [^{Y^}/^{N^}] "); - rightch(curwin, 2, getmaxx(curwin) / 2, chbuf, lines, &width); + right(curwin, 2, getmaxx(curwin) / 2, attr_normal, attr_keycode, 0, + "Are you sure? [^{Y^}/^{N^}] "); wrefresh(curwin); if (! answer_yesno(curwin)) { @@ -343,13 +319,15 @@ selection_t get_move (void) // Save the game if required if (selection == SEL_SAVE) { + chtype *chbuf = xmalloc(BUFSIZE * sizeof(chtype)); + int width; + bool saved = false; if (game_loaded) { // Save the game to the same game number - lines = mkchstr(chbuf, BUFSIZE, attr_status_window, 0, 0, 1, - WIN_COLS - 7, &width, 1, - "Saving game %d... ", game_num); + mkchstr(chbuf, BUFSIZE, attr_status_window, 0, 0, 1, WIN_COLS + - 7, &width, 1, "Saving game %d... ", game_num); newtxwin(5, width + 5, 7, WCENTER, true, attr_status_window); centerch(curwin, 2, 0, chbuf, 1, &width); wrefresh(curwin); @@ -366,13 +344,10 @@ selection_t get_move (void) int key; bool done; int widthbuf[2]; - int maxwidth; - + int lines, maxwidth; lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_keycode, 0, - sizeof(widthbuf) / sizeof(widthbuf[0]), - WIN_COLS - 7, widthbuf, - sizeof(widthbuf) / sizeof(widthbuf[0]), + 2, WIN_COLS - 7, widthbuf, 2, "Enter game number [^{1^}-^{9^}] " "or ^{^} to cancel: "); assert(lines == 1 || lines == 2); @@ -417,9 +392,9 @@ selection_t get_move (void) // Try to save the game, if possible game_num = key - '0'; - lines = mkchstr(chbuf, BUFSIZE, attr_status_window, - 0, 0, 1, WIN_COLS - 7, &width, 1, - "Saving game %d... ", game_num); + mkchstr(chbuf, BUFSIZE, attr_status_window, 0, 0, 1, + WIN_COLS - 7, &width, 1, + "Saving game %d... ", game_num); newtxwin(5, width + 5, 7, WCENTER, true, attr_status_window); centerch(curwin, 2, 0, chbuf, 1, &width); wrefresh(curwin); @@ -443,10 +418,11 @@ selection_t get_move (void) selection = SEL_NONE; } + + free(chbuf); } } - free(chbuf); return selection; } From 22677c0d89c80d428ee4058f2644cc825a07cf73 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Mon, 15 Aug 2011 23:12:10 +1000 Subject: [PATCH 037/112] Handle floating-point numbers in mkchstr(), with optional precision --- src/intf.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++------ src/intf.h | 12 ++++++---- 2 files changed, 68 insertions(+), 12 deletions(-) diff --git a/src/intf.c b/src/intf.c index 4f3e1e1..010c01e 100644 --- a/src/intf.c +++ b/src/intf.c @@ -70,11 +70,13 @@ struct argument { #define MAXFMTSPECS 16 // Maximum number of conversion specifiers struct convspec { - int len; // Length of conversion specifier, 0 = unused + char spec; // Conversion specifier: c d f N s int arg_num; // Which variable argument to use - char spec; // Conversion specifier: c d N s + int len; // Length of conversion specifier, 0 = unused + int precision; // Precision value bool flag_group; // Flag "'" (thousands grouping) bool flag_nosym; // Flag "!" (omit currency symbol) + bool flag_prec; // Flag "." (precision) bool flag_long; // Length modifier "l" (long) }; @@ -835,6 +837,17 @@ int mkchstr_parse (const char *restrict format, flag_other = true; break; + case '.': + // Precision flag + if (format_spec->flag_prec || count != 0) { + errno = EINVAL; + return -1; + } + + format_spec->flag_prec = true; + flag_other = true; + break; + case 'l': // Long length modifier if (format_spec->flag_long) { @@ -850,7 +863,8 @@ int mkchstr_parse (const char *restrict format, case 'c': // Insert a character (char) if (format_spec->flag_group || format_spec->flag_nosym - || format_spec->flag_long || count != 0) { + || format_spec->flag_prec || format_spec->flag_long + || count != 0) { errno = EINVAL; return -1; } @@ -860,7 +874,8 @@ int mkchstr_parse (const char *restrict format, case 'd': // Insert an integer (int or long int) - if (count != 0) { + if (format_spec->flag_nosym || format_spec->flag_prec + || count != 0) { errno = EINVAL; return -1; } @@ -869,10 +884,23 @@ int mkchstr_parse (const char *restrict format, TYPE_LONGINT : TYPE_INT; goto handlefmt; + case 'f': + // Insert a floating-point number (double) + if (format_spec->flag_nosym || format_spec->flag_long || + (! format_spec->flag_prec && count != 0)) { + errno = EINVAL; + return -1; + } + + format_spec->precision = count; + + arg_type = TYPE_DOUBLE; + goto handlefmt; + case 'N': // Insert a monetary amount (double) - if (format_spec->flag_group || format_spec->flag_long - || count != 0) { + if (format_spec->flag_group || format_spec->flag_prec + || format_spec->flag_long || count != 0) { errno = EINVAL; return -1; } @@ -883,7 +911,8 @@ int mkchstr_parse (const char *restrict format, case 's': // Insert a string (const char *) if (format_spec->flag_group || format_spec->flag_nosym - || format_spec->flag_long || count != 0) { + || format_spec->flag_prec || format_spec->flag_long + || count != 0) { errno = EINVAL; return -1; } @@ -1102,6 +1131,31 @@ int vmkchstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, str = buf; goto insertstr; + case 'f': + // Insert a floating-point number (double) into the output + if (spec->flag_prec) { + if (snprintf(buf, BUFSIZE, spec->flag_group ? + "%'.*f" : "%.*f", spec->precision, + format_arg[spec->arg_num].a.a_double) < 0) { + saved_errno = errno; + free(buf); + errno = saved_errno; + goto error; + } + } else { + if (snprintf(buf, BUFSIZE, spec->flag_group ? + "%'f" : "%f", + format_arg[spec->arg_num].a.a_double) < 0) { + saved_errno = errno; + free(buf); + errno = saved_errno; + goto error; + } + } + + str = buf; + goto insertstr; + case 'N': // Insert a monetary amount (double) into the output if (l_strfmon(buf, BUFSIZE, spec->flag_nosym ? "%!n" : "%n", diff --git a/src/intf.h b/src/intf.h index 4541bc4..46f86dc 100644 --- a/src/intf.h +++ b/src/intf.h @@ -317,14 +317,16 @@ extern int txdlgbox (int maxlines, int ncols, int begin_y, int begin_x, %c - Insert the next parameter as a character (type char) %s - Insert the next parameter as a string (type char *) %d - Insert the next parameter as an integer (type int) - %'d - Insert as an int, using the locale's thousands separator + %'d - As above, using the locale's thousands group separator %ld - Insert the next parameter as a long int - %'ld - Insert as a long int, using the locale's thousands separator + %'ld - As above, using the locale's thousands group separator + %f - Insert the next parameter as a floating point number (double) + %.mf - As above, with precision "m" (a positive integer > 0) + %'.mf - As above, using the locale's thousands group separator %N - Insert the next parameter as a double, using the locale's national currency format (extension to printf()) - %!N - Insert the next parameter as a double, using the locale's - national currency format without the actual currency symbol - (extension to printf()) + %!N - As above, using the locale's national currency format without + the actual currency symbol (extension to printf()) Instead of using "%" to convert the next parameter, "%m$" can be used to indicate fixed parameter m (where m is an integer from 1 to 8). For From 82647cf6915487b6d4d1c562be0c29735fdaf5b5 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Mon, 15 Aug 2011 23:54:44 +1000 Subject: [PATCH 038/112] Move to the new left/center/right functions; add maxlines parameter --- src/game.c | 175 +++++++++++++++++++++++++++++++---------------------- src/help.c | 6 +- src/intf.c | 63 +++++++++++-------- src/intf.h | 33 ++++++---- src/move.c | 20 +++--- 5 files changed, 177 insertions(+), 120 deletions(-) diff --git a/src/game.c b/src/game.c index c3dde3d..52628ef 100644 --- a/src/game.c +++ b/src/game.c @@ -368,7 +368,7 @@ void ask_player_names (void) // Ask for the player's name newtxwin(5, WIN_COLS - 4, 9, WCENTER, true, attr_normal_window); - left(curwin, 2, 2, attr_normal, 0, 0, "Please enter your name: "); + left(curwin, 2, 2, attr_normal, 0, 0, 1, "Please enter your name: "); int x = getcurx(curwin); int w = getmaxx(curwin) - x - 2; @@ -404,12 +404,12 @@ void ask_player_names (void) newtxwin(number_players + 5, WIN_COLS - 4, 9, WCENTER, true, attr_normal_window); - center(curwin, 1, 0, attr_title, 0, 0, " Enter Player Names "); + center(curwin, 1, 0, attr_title, 0, 0, 1, " Enter Player Names "); for (i = 0; i < number_players; i++) { player[i].name = NULL; entered[i] = false; - left(curwin, i + 3, 2, attr_normal, 0, 0, "Player %d:", i + 1); + left(curwin, i + 3, 2, attr_normal, 0, 0, 1, "Player %d:", i + 1); } int x = getcurx(curwin) + 1; @@ -508,8 +508,9 @@ void ask_player_names (void) void end_game (void) { - int i; - char *buf; + chtype *chbuf; + int lines; + int widthbuf[5]; if (abort_game) { @@ -517,14 +518,14 @@ void end_game (void) return; } - buf = xmalloc(BUFSIZE); + chbuf = xmalloc(BUFSIZE * sizeof(chtype)); txdlgbox(MAX_DLG_LINES, 50, 9, WCENTER, attr_error_window, attr_error_title, attr_error_highlight, 0, 0, attr_error_waitforkey, " Game Over ", "The game is over after %d turns.", turn_number - 1); - for (i = 0; i < number_players; i++) { + for (int i = 0; i < number_players; i++) { show_status(i); } @@ -535,43 +536,45 @@ void end_game (void) total_value(0)); } else { // Sort players on the basis of total value - for (i = 0; i < number_players; i++) { + for (int i = 0; i < number_players; i++) { player[i].sort_value = total_value(i); } qsort(player, number_players, sizeof(player_info_t), cmp_player); - newtxwin(number_players + 10, WIN_COLS - 4, 3, WCENTER, + lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_highlight, attr_blink, + 5, WIN_COLS - 8, widthbuf, 5, (player[0].sort_value == 0) ? + "The winner is ^{%s^}\n" + "who is ^[*** BANKRUPT ***^]" : + "The winner is ^{%s^}\n" + "with a value of ^{%N^}.", player[0].name, + player[0].sort_value); + + newtxwin(number_players + lines + 8, WIN_COLS - 4, 3, WCENTER, true, attr_normal_window); + center(curwin, 1, 0, attr_title, 0, 0, 1, " Game Winner "); + centerch(curwin, 3, 0, chbuf, lines, widthbuf); - old_center(curwin, 1, attr_title, " Game Winner "); - old_center2(curwin, 3, attr_normal, attr_highlight, "The winner is ", - "%s", player[0].name); - if (player[0].sort_value == 0.0) { - old_center2(curwin, 4, attr_normal, attr_blink, "who is ", - "*** BANKRUPT ***"); - } else { - l_strfmon(buf, BUFSIZE, "%1n", player[0].sort_value); - old_center2(curwin, 4, attr_normal, attr_highlight, - "with a value of ", "%s", buf); - } + mvwhline(curwin, lines + 4, 2, ' ' | attr_subtitle, + getmaxx(curwin) - 4); + left(curwin, lines + 4, ORDINAL_COLS + 4, attr_subtitle, 0, 0, 1, + "Player"); + right(curwin, lines + 4, getmaxx(curwin) - 4, attr_subtitle, 0, 0, 1, + "Total Value (%s)", lconvinfo.currency_symbol); - int w = getmaxx(curwin) - 33; - wattrset(curwin, attr_subtitle); - snprintf(buf, BUFSIZE, "Total Value (%s)", lconvinfo.currency_symbol); - mvwprintw(curwin, 6, 2, "%5s %-*.*s %18s ", "", w, w, "Player", buf); - wattrset(curwin, attr_normal); - - for (i = 0; i < number_players; i++) { - l_strfmon(buf, BUFSIZE, "%!18n", player[i].sort_value); - mvwprintw(curwin, i + 7, 2, "%5s %-*.*s %18s ", - gettext(ordinal[i + 1]), w, w, player[i].name, buf); + for (int i = 0; i < number_players; i++) { + right(curwin, i + lines + 5, ORDINAL_COLS + 2, attr_normal, 0, 0, + 1, gettext(ordinal[i + 1])); + left(curwin, i + lines + 5, ORDINAL_COLS + 4, attr_normal, 0, 0, + 1, "%s", player[i].name); + right(curwin, i + lines + 5, getmaxx(curwin) - 2, attr_normal, 0, + 0, 1, " %!N ", player[i].sort_value); } wait_for_key(curwin, getmaxy(curwin) - 2, attr_waitforkey); deltxwin(); } - free(buf); + free(chbuf); } @@ -592,13 +595,12 @@ void show_map (bool closewin) mvwhline(curwin, 1, 2, ' ' | attr_mapwin_title, getmaxx(curwin) - 4); // Display current player and turn number - left(curwin, 1, 2, attr_mapwin_title, attr_mapwin_highlight, 0, + left(curwin, 1, 2, attr_mapwin_title, attr_mapwin_highlight, 0, 1, " Player: ^{%s^} ", player[current_player].name); right(curwin, 1, getmaxx(curwin) - 2, attr_mapwin_title, - attr_mapwin_highlight, attr_mapwin_blink, (turn_number != max_turn) ? - " Turn: ^{%d^} " : " ^[*** Last Turn ***^] ", turn_number); - - wattrset(curwin, attr_map_window); + attr_mapwin_highlight, attr_mapwin_blink, 1, + (turn_number != max_turn) ? " Turn: ^{%d^} " : + " ^[*** Last Turn ***^] ", turn_number); // Display the actual map for (y = 0; y < MAX_Y; y++) { @@ -657,17 +659,15 @@ void show_status (int num) newtxwin(MAX_COMPANIES + 15, WIN_COLS, 1, WCENTER, true, attr_normal_window); - center(curwin, 1, 0, attr_title, 0, 0, " Stock Portfolio "); - center(curwin, 2, 0, attr_normal, attr_highlight, 0, "Player: ^{%s^}", + center(curwin, 1, 0, attr_title, 0, 0, 1, " Stock Portfolio "); + center(curwin, 2, 0, attr_normal, attr_highlight, 0, 1, "Player: ^{%s^}", player[num].name); val = total_value(num); if (val == 0.0) { - center(curwin, 11, 0, attr_normal, attr_highlight, attr_blink, + center(curwin, 11, 0, attr_normal, attr_highlight, attr_blink, 1, "^[* * * B A N K R U P T * * *^]"); } else { - char *buf = xmalloc(BUFSIZE); - // Check to see if any companies are on the map bool none = true; for (i = 0; i < MAX_COMPANIES; i++) { @@ -678,52 +678,83 @@ void show_status (int num) } if (none) { - center(curwin, 8, 0, attr_normal, attr_highlight, 0, + center(curwin, 8, 0, attr_normal, attr_highlight, 0, 1, "No companies on the map"); } else { - // Handle the locale's currency symbol - snprintf(buf, BUFSIZE, "share (%s)", lconvinfo.currency_symbol); + mvwhline(curwin, 4, 2, ' ' | attr_subtitle, getmaxx(curwin) - 4); + mvwhline(curwin, 5, 2, ' ' | attr_subtitle, getmaxx(curwin) - 4); - wattrset(curwin, attr_subtitle); - mvwprintw(curwin, 4, 2, " %-22s %12s %10s %10s %10s ", - "", "Price per", "", "Holdings", "Company"); - mvwprintw(curwin, 5, 2, " %-22s %12s %10s %10s %10s ", - "Company", buf, "Return (%)", "(shares)", "owner (%)"); - wattrset(curwin, attr_normal); + left(curwin, 4, 4, attr_subtitle, 0, 0, 2, "\nCompany"); + right(curwin, 4, getmaxx(curwin) - 4, attr_subtitle, 0, 0, 2, + "Ownership\n(%%)"); + right(curwin, 4, getmaxx(curwin) - 6 - OWNERSHIP_COLS, + attr_subtitle, 0, 0, 2, "Holdings\n(shares)"); + right(curwin, 4, getmaxx(curwin) - 8 - OWNERSHIP_COLS + - STOCK_OWNED_COLS, attr_subtitle, 0, 0, 2, + "\nReturn (%%)"); + right(curwin, 4, getmaxx(curwin) - 10 - OWNERSHIP_COLS + - STOCK_OWNED_COLS - SHARE_RETURN_COLS, attr_subtitle, 0, 0, + 2, "Price per\nshare (%s)", lconvinfo.currency_symbol); for (line = 6, i = 0; i < MAX_COMPANIES; i++) { if (company[i].on_map) { - l_strfmon(buf, BUFSIZE, "%!12n", company[i].share_price); - mvwprintw(curwin, line, 2, - " %-22s %10s %10.2f %'10ld %10.2f ", - company[i].name, buf, - company[i].share_return * 100.0, - player[num].stock_owned[i], - (company[i].stock_issued == 0) ? 0.0 : - ((double) player[num].stock_owned[i] * 100.0) - / company[i].stock_issued); + left(curwin, line, 4, attr_normal, 0, 0, 1, "%s", + company[i].name); + + right(curwin, line, getmaxx(curwin) - 2, attr_normal, 0, 0, + 1, "%.2f ", (company[i].stock_issued == 0) ? 0.0 : + ((double) player[num].stock_owned[i] * 100.0) + / company[i].stock_issued); + right(curwin, line, getmaxx(curwin) - 4 - OWNERSHIP_COLS, + attr_normal, 0, 0, 1, "%'ld ", + player[num].stock_owned[i]); + right(curwin, line, getmaxx(curwin) - 6 - OWNERSHIP_COLS + - STOCK_OWNED_COLS, attr_normal, 0, 0, 1, "%.2f ", + company[i].share_return * 100.0); + right(curwin, line, getmaxx(curwin) - 8 - OWNERSHIP_COLS + - STOCK_OWNED_COLS - SHARE_RETURN_COLS, attr_normal, + 0, 0, 1, " %!N ", company[i].share_price); + line++; } } } - line = 15; - l_strfmon(buf, BUFSIZE, "%18n", player[num].cash); - old_center2(curwin, line++, attr_normal, attr_highlight, "Current cash: ", - " %s ", buf); + line = MAX_COMPANIES + 7; + + chtype *chbuf = xmalloc(BUFSIZE * sizeof(chtype)); + int width, x; + + mkchstr(chbuf, BUFSIZE, attr_highlight, 0, 0, 1, getmaxx(curwin) / 2, + &width, 1, "Total value: "); + x = (getmaxx(curwin) + width - (TOTAL_VALUE_COLS + 2)) / 2; + + right(curwin, line, x, attr_normal, attr_highlight, 0, 1, + "Current cash: "); + right(curwin, line, x + TOTAL_VALUE_COLS + 2, attr_normal, + attr_highlight, 0, 1, " ^{%N^} ", player[num].cash); + line++; + if (player[num].debt != 0.0) { - l_strfmon(buf, BUFSIZE, "%18n", player[num].debt); - old_center2(curwin, line++, attr_normal, attr_highlight, - "Current debt: ", " %s ", buf); - old_center2(curwin, line++, attr_normal, attr_highlight, - "Interest rate: ", " %17.2f%% ", interest_rate * 100.0); + right(curwin, line, x, attr_normal, attr_highlight, 0, 1, + "Current debt: "); + right(curwin, line, x + TOTAL_VALUE_COLS + 2, attr_normal, + attr_highlight, 0, 1, " ^{%N^} ", player[num].debt); + line++; + + right(curwin, line, x, attr_normal, attr_highlight, 0, 1, + "Interest rate: "); + right(curwin, line, x + TOTAL_VALUE_COLS + 2, attr_normal, + attr_highlight, 0, 1, " ^{%.2f%%^} ", interest_rate * 100.0); + line++; } - l_strfmon(buf, BUFSIZE, "%18n", val); - old_center2(curwin, line + 1, attr_highlight, attr_title, - "Total value: ", " %s ", buf); + rightch(curwin, line + 1, x, chbuf, 1, &width); + whline(curwin, ' ' | attr_title, TOTAL_VALUE_COLS + 2); + right(curwin, line + 1, x + TOTAL_VALUE_COLS + 2, attr_title, 0, 0, 1, + " %N ", val); - free(buf); + free(chbuf); } wait_for_key(curwin, getmaxy(curwin) - 2, attr_waitforkey); diff --git a/src/help.c b/src/help.c index ac02394..5875708 100644 --- a/src/help.c +++ b/src/help.c @@ -178,8 +178,8 @@ void show_help (void) wbkgd(curwin, attr_normal_window); box(curwin, 0, 0); - center(curwin, 1, 0, attr_title, 0, 0, " How to Play "); - center(curwin, 2, 0, attr_normal, attr_highlight, 0, + center(curwin, 1, 0, attr_title, 0, 0, 1, " How to Play "); + center(curwin, 2, 0, attr_normal, attr_highlight, 0, 1, "Page %d of %d", curpage + 1, numpages); wmove(curwin, 4, 2); @@ -325,7 +325,7 @@ void show_help (void) s++; } - center(curwin, getmaxy(curwin) - 2, 0, attr_waitforkey, 0, 0, + center(curwin, getmaxy(curwin) - 2, 0, attr_waitforkey, 0, 0, 1, (curpage == 0) ? "[ Press to continue ] " : "[ Press to continue or " "for the previous page ] "); diff --git a/src/intf.c b/src/intf.c index 010c01e..6896fa2 100644 --- a/src/intf.c +++ b/src/intf.c @@ -409,7 +409,7 @@ void init_title (void) clear(); mvwhline(stdscr, 0, 0, ' ' | attr_game_title, COLS); - center(stdscr, 0, 0, attr_game_title, 0, 0, _("Star Traders")); + center(stdscr, 0, 0, attr_game_title, 0, 0, 1, _("Star Traders")); } @@ -609,7 +609,7 @@ int txdlgbox (int maxlines, int ncols, int begin_y, int begin_x, true, bkgd_attr); if (usetitle) { - center(curwin, 1, 0, title_attr, 0, 0, boxtitle); + center(curwin, 1, 0, title_attr, 0, 0, 1, boxtitle); } centerch(curwin, usetitle ? 3 : 2, 0, chbuf, lines, widthbuf); @@ -1345,25 +1345,30 @@ int rightch (WINDOW *win, int y, int x, const chtype *restrict chstr, // left: Print strings left-aligned int left (WINDOW *win, int y, int x, chtype attr_norm, chtype attr_alt1, - chtype attr_alt2, const char *restrict format, ...) + chtype attr_alt2, int maxlines, const char *restrict format, ...) { va_list args; - chtype *chbuf = xmalloc(BUFSIZE * sizeof(chtype)); - int widthbuf[MAX_DLG_LINES]; + chtype *chbuf; + int *widthbuf; int lines; int ret; + assert(maxlines > 0); + + chbuf = xmalloc(BUFSIZE * sizeof(chtype)); + widthbuf = xmalloc(maxlines * sizeof(int)); + va_start(args, format); - lines = vmkchstr(chbuf, BUFSIZE, attr_norm, attr_alt1, attr_alt2, - MAX_DLG_LINES, getmaxx(win) - x - 2, widthbuf, - MAX_DLG_LINES, format, args); + lines = vmkchstr(chbuf, BUFSIZE, attr_norm, attr_alt1, attr_alt2, maxlines, + getmaxx(win) - x - 2, widthbuf, maxlines, format, args); ret = leftch(win, y, x, chbuf, lines, widthbuf); assert(ret == OK); va_end(args); + free(widthbuf); free(chbuf); - return ret; + return lines; } @@ -1371,25 +1376,30 @@ int left (WINDOW *win, int y, int x, chtype attr_norm, chtype attr_alt1, // center: Print strings centred in window int center (WINDOW *win, int y, int offset, chtype attr_norm, chtype attr_alt1, - chtype attr_alt2, const char *restrict format, ...) + chtype attr_alt2, int maxlines, const char *restrict format, ...) { va_list args; - chtype *chbuf = xmalloc(BUFSIZE * sizeof(chtype)); - int widthbuf[MAX_DLG_LINES]; + chtype *chbuf; + int *widthbuf; int lines; int ret; + assert(maxlines > 0); + + chbuf = xmalloc(BUFSIZE * sizeof(chtype)); + widthbuf = xmalloc(maxlines * sizeof(int)); + va_start(args, format); - lines = vmkchstr(chbuf, BUFSIZE, attr_norm, attr_alt1, attr_alt2, - MAX_DLG_LINES, getmaxx(win) - 4, widthbuf, - MAX_DLG_LINES, format, args); + lines = vmkchstr(chbuf, BUFSIZE, attr_norm, attr_alt1, attr_alt2, maxlines, + getmaxx(win) - 4, widthbuf, maxlines, format, args); ret = centerch(win, y, offset, chbuf, lines, widthbuf); assert(ret == OK); va_end(args); + free(widthbuf); free(chbuf); - return ret; + return lines; } @@ -1397,25 +1407,30 @@ int center (WINDOW *win, int y, int offset, chtype attr_norm, chtype attr_alt1, // right: Print strings right-aligned int right (WINDOW *win, int y, int x, chtype attr_norm, chtype attr_alt1, - chtype attr_alt2, const char *restrict format, ...) + chtype attr_alt2, int maxlines, const char *restrict format, ...) { va_list args; - chtype *chbuf = xmalloc(BUFSIZE * sizeof(chtype)); - int widthbuf[MAX_DLG_LINES]; + chtype *chbuf; + int *widthbuf; int lines; int ret; + assert(maxlines > 0); + + chbuf = xmalloc(BUFSIZE * sizeof(chtype)); + widthbuf = xmalloc(maxlines * sizeof(int)); + va_start(args, format); - lines = vmkchstr(chbuf, BUFSIZE, attr_norm, attr_alt1, attr_alt2, - MAX_DLG_LINES, x - 2, widthbuf, MAX_DLG_LINES, - format, args); + lines = vmkchstr(chbuf, BUFSIZE, attr_norm, attr_alt1, attr_alt2, maxlines, + x - 2, widthbuf, maxlines, format, args); ret = rightch(win, y, x, chbuf, lines, widthbuf); assert(ret == OK); va_end(args); + free(widthbuf); free(chbuf); - return ret; + return lines; } @@ -2554,7 +2569,7 @@ void wait_for_key (WINDOW *win, int y, chtype attr) meta(win, true); wtimeout(win, -1); - center(curwin, y, 0, attr, 0, 0, _("[ Press to continue ] ")); + center(curwin, y, 0, attr, 0, 0, 1, _("[ Press to continue ] ")); wrefresh(win); done = false; diff --git a/src/intf.h b/src/intf.h index 46f86dc..5601ab3 100644 --- a/src/intf.h +++ b/src/intf.h @@ -50,13 +50,19 @@ #define MIN_LINES 24 // Minimum number of lines in terminal #define MIN_COLS 80 // Minimum number of columns in terminal -#define WIN_LINES MIN_LINES // Number of lines used in main window -#define WIN_COLS MIN_COLS // Number of columns used in main window +#define WIN_LINES MIN_LINES // Number of lines used in main window +#define WIN_COLS MIN_COLS // Number of columns used in main window -#define WCENTER -1 // Centre the new window +#define WCENTER -1 // Centre the new window -#define MAX_DLG_LINES 10 // Default maximum lines of text in dialog box -#define YESNO_COLS 4 // Space to allow for "Yes" or "No" response +#define MAX_DLG_LINES 10 // Default maximum lines of text in dialog box +#define YESNO_COLS 4 // Space to allow for "Yes" or "No" response +#define ORDINAL_COLS 5 // Space for ordinals (1st, 2nd, etc) +#define TOTAL_VALUE_COLS 18 // Space for total value (monetary) +#define SHARE_PRICE_COLS 12 // Space for "Price per share" +#define SHARE_RETURN_COLS 10 // Space for "Return per share" +#define STOCK_OWNED_COLS 10 // Space for "Holdings (shares)" +#define OWNERSHIP_COLS 10 // Space for "Company ownership (%)" // Check if resizing events are supported @@ -470,9 +476,10 @@ extern int rightch (WINDOW *win, int y, int x, const chtype *restrict chstr, attr_norm - Normal character rendition to use attr_alt1 - First alternate character rendition to use attr_alt2 - Second alternate character rendition to use + maxlines - Maximum number of screen lines to use format - Format string as described for mkchstr() ... - Arguments for the format string - Returns: int - Always returns OK + Returns: int - Number of lines actually used This shortcut function prepares a chtype string using mkchstr(), then prints the string using leftch(). At most MAX_DLG_LINES are printed, @@ -480,7 +487,8 @@ extern int rightch (WINDOW *win, int y, int x, const chtype *restrict chstr, for the right-hand border). */ extern int left (WINDOW *win, int y, int x, chtype attr_norm, chtype attr_alt1, - chtype attr_alt2, const char *restrict format, ...); + chtype attr_alt2, int maxlines, const char *restrict format, + ...); /* @@ -491,16 +499,17 @@ extern int left (WINDOW *win, int y, int x, chtype attr_norm, chtype attr_alt1, attr_norm - Normal character rendition to use attr_alt1 - First alternate character rendition to use attr_alt2 - Second alternate character rendition to use + maxlines - Maximum number of screen lines to use format - Format string as described for mkchstr() ... - Arguments for the format string - Returns: int - Always returns OK + Returns: int - Number of lines actually used This shortcut function prepares a chtype string using mkchstr(), then prints the string using centerch(). At most MAX_DLG_LINES are printed, with the maximum width being that of the window win - 4 (for borders). */ extern int center (WINDOW *win, int y, int offset, chtype attr_norm, - chtype attr_alt1, chtype attr_alt2, + chtype attr_alt1, chtype attr_alt2, int maxlines, const char *restrict format, ...); @@ -512,9 +521,10 @@ extern int center (WINDOW *win, int y, int offset, chtype attr_norm, attr_norm - Normal character rendition to use attr_alt1 - First alternate character rendition to use attr_alt2 - Second alternate character rendition to use + maxlines - Maximum number of screen lines to use format - Format string as described for mkchstr() ... - Arguments for the format string - Returns: int - Always returns OK + Returns: int - Number of lines actually used This shortcut function prepares a chtype string using mkchstr(), then prints the string using rightch(). At most MAX_DLG_LINES are printed, @@ -522,7 +532,8 @@ extern int center (WINDOW *win, int y, int offset, chtype attr_norm, left-hand border). */ extern int right (WINDOW *win, int y, int x, chtype attr_norm, chtype attr_alt1, - chtype attr_alt2, const char *restrict format, ...); + chtype attr_alt2, int maxlines, const char *restrict format, + ...); /* diff --git a/src/move.c b/src/move.c index a727593..c7e926e 100644 --- a/src/move.c +++ b/src/move.c @@ -231,17 +231,17 @@ selection_t get_move (void) werase(curwin); box(curwin, 0, 0); - left(curwin, 2, 2, attr_normal, attr_keycode, 0, + left(curwin, 2, 2, attr_normal, attr_keycode, 0, 1, "^{<1>^} Display stock portfolio"); - left(curwin, 3, 2, attr_normal, attr_keycode, 0, + left(curwin, 3, 2, attr_normal, attr_keycode, 0, 1, "^{<2>^} Declare bankruptcy"); - left(curwin, 2, getmaxx(curwin) / 2, attr_normal, attr_keycode, 0, + left(curwin, 2, getmaxx(curwin) / 2, attr_normal, attr_keycode, 0, 1, "^{<3>^} Save and end the game"); - left(curwin, 3, getmaxx(curwin) / 2, attr_normal, attr_keycode, 0, + left(curwin, 3, getmaxx(curwin) / 2, attr_normal, attr_keycode, 0, 1, "^{^} Quit the game"); right(curwin, 1, getmaxx(curwin) / 2, attr_normal, attr_keycode, - attr_choice, "Select move " + attr_choice, 1, "Select move " "[^[%c^]-^[%c^]/^{1^}-^{3^}/^{^}]: ", MOVE_TO_KEY(0), MOVE_TO_KEY(NUMBER_MOVES - 1)); @@ -257,7 +257,7 @@ selection_t get_move (void) curs_set(CURS_OFF); left(curwin, 1, getmaxx(curwin) / 2, attr_normal, attr_choice, - 0, "Move ^{%c^}", key); + 0, 1, "Move ^{%c^}", key); } else { switch (key) { case '1': @@ -271,7 +271,7 @@ selection_t get_move (void) curs_set(CURS_OFF); left(curwin, 1, getmaxx(curwin) / 2, attr_normal, - attr_normal | A_BOLD, 0, + attr_normal | A_BOLD, 0, 1, "^{<2>^} (Declare bankruptcy)"); break; @@ -280,7 +280,7 @@ selection_t get_move (void) curs_set(CURS_OFF); left(curwin, 1, getmaxx(curwin) / 2, attr_normal, - attr_normal | A_BOLD, 0, + attr_normal | A_BOLD, 0, 1, "^{<3>^} (Save and end the game)"); break; @@ -294,7 +294,7 @@ selection_t get_move (void) curs_set(CURS_OFF); left(curwin, 1, getmaxx(curwin) / 2, attr_normal, - attr_normal | A_BOLD, 0, + attr_normal | A_BOLD, 0, 1, "^{^} (Quit the game)"); break; @@ -309,7 +309,7 @@ selection_t get_move (void) mvwhline(curwin, 3, 2, ' ' | attr_normal, getmaxx(curwin) - 4); // Ask the player to confirm their choice - right(curwin, 2, getmaxx(curwin) / 2, attr_normal, attr_keycode, 0, + right(curwin, 2, getmaxx(curwin) / 2, attr_normal, attr_keycode, 0, 1, "Are you sure? [^{Y^}/^{N^}] "); wrefresh(curwin); From 135842b87d8e3eda3af6ea61b29c92bd03a7f321 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Tue, 16 Aug 2011 16:25:28 +1000 Subject: [PATCH 039/112] Bug fix for non-colour mode If the background has A_REVERSE, then A_NORMAL will have no effect. For that reason, specify A_NORMAL as the default background after creating a new window. --- src/intf.c | 8 +++++++- src/intf.h | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/intf.c b/src/intf.c index 6896fa2..db3021f 100644 --- a/src/intf.c +++ b/src/intf.c @@ -86,6 +86,7 @@ struct convspec { ************************************************************************/ WINDOW *curwin = NULL; // Top-most (current) window +bool use_color = true; // True to use colour // Character renditions (attributes) used by Star Traders @@ -293,7 +294,8 @@ void init_screen (void) raw(); // Initialise all character renditions used in the game - if (! option_no_color && has_colors()) { + use_color = ! option_no_color && has_colors(); + if (use_color) { start_color(); init_pair(1, COLOR_BLACK, COLOR_WHITE); @@ -491,6 +493,10 @@ WINDOW *newtxwin (int nlines, int ncols, int begin_y, int begin_x, box(win, 0, 0); } + if (! use_color) { + wbkgdset(win, A_NORMAL); + } + return win; } diff --git a/src/intf.h b/src/intf.h index 5601ab3..f975dcf 100644 --- a/src/intf.h +++ b/src/intf.h @@ -118,6 +118,7 @@ typedef enum curs_type { ************************************************************************/ extern WINDOW *curwin; // Top-most (current) window +extern bool use_color; // True to use colour // Character renditions (attributes) used by Star Traders From cf3093361496be10cb1e88d2fdc2e536332ed131 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Tue, 16 Aug 2011 18:48:56 +1000 Subject: [PATCH 040/112] Continue to rewrite the interface code to use the new interfaces --- src/exch.c | 349 ++++++++++++++++++++++++++++------------------------- src/game.c | 45 ++++--- src/help.c | 2 +- src/intf.h | 11 ++ src/move.c | 157 +++++++++++++++--------- 5 files changed, 318 insertions(+), 246 deletions(-) diff --git a/src/exch.c b/src/exch.c index 5c50a46..24b5096 100644 --- a/src/exch.c +++ b/src/exch.c @@ -76,7 +76,7 @@ void exchange_stock (void) selection_t selection = SEL_NONE; bool bid_used = false; bool all_off_map; - int i, line; + int w, i, line; if (quit_selected || abort_game || ! player[current_player].in_game) { @@ -84,18 +84,20 @@ void exchange_stock (void) } newtxwin(17, WIN_COLS, 1, WCENTER, false, 0); + w = getmaxx(curwin); while (selection != SEL_EXIT) { selection = SEL_NONE; // Display (or refresh) the Stock Exchange window - wbkgd(curwin, attr_normal_window); + wbkgdset(curwin, attr_normal_window); werase(curwin); box(curwin, 0, 0); - old_center(curwin, 1, attr_title, " Interstellar Stock Exchange "); - old_center2(curwin, 2, attr_normal, attr_highlight, "Player: ", "%s", - player[current_player].name); + center(curwin, 1, 0, attr_title, 0, 0, 1, + " Interstellar Stock Exchange "); + center(curwin, 2, 0, attr_normal, attr_highlight, 0, 1, + "Player: ^{%s^}", player[current_player].name); all_off_map = true; for (i = 0; i < MAX_COMPANIES; i++) { @@ -106,34 +108,44 @@ void exchange_stock (void) } if (all_off_map) { - old_center(curwin, 8, attr_normal, "No companies on the map"); + center(curwin, 8, 0, attr_normal, attr_highlight, 0, 1, + "No companies on the map"); } else { - char *buf = xmalloc(BUFSIZE); + mvwhline(curwin, 4, 2, ' ' | attr_subtitle, w - 4); + mvwhline(curwin, 5, 2, ' ' | attr_subtitle, w - 4); - // Handle the locale's currency symbol - snprintf(buf, BUFSIZE, "share (%s)", lconvinfo.currency_symbol); - - wattrset(curwin, attr_subtitle); - mvwprintw(curwin, 4, 2, " %-22s %12s %10s %10s %10s ", - "", "Price per", "", "Shares", "Shares"); - mvwprintw(curwin, 5, 2, " %-22s %12s %10s %10s %10s ", - "Company", buf, "Return (%)", "issued", "left"); - wattrset(curwin, attr_normal); + left(curwin, 4, 4, attr_subtitle, 0, 0, 2, "\nCompany"); + right(curwin, 4, w - 4, attr_subtitle, 0, 0, 2, "Shares\nleft"); + right(curwin, 4, w - 6 - STOCK_LEFT_COLS, attr_subtitle, 0, 0, + 2, "Shares\nissued"); + right(curwin, 4, w - 8 - STOCK_LEFT_COLS - STOCK_ISSUED_COLS, + attr_subtitle, 0, 0, 2, "Return\n(%%)"); + right(curwin, 4, w - 10 - STOCK_LEFT_COLS - STOCK_ISSUED_COLS + - SHARE_RETURN_COLS, attr_subtitle, 0, 0, 2, + "Price per\nshare (%s)", lconvinfo.currency_symbol); for (line = 6, i = 0; i < MAX_COMPANIES; i++) { if (company[i].on_map) { mvwaddch(curwin, line, 2, PRINTABLE_MAP_VAL(COMPANY_TO_MAP(i)) | attr_choice); - l_strfmon(buf, BUFSIZE, "%!12n", company[i].share_price); - mvwprintw(curwin, line, 4, "%-22s %12s %10.2f %'10ld %'10ld ", - company[i].name, buf, company[i].share_return - * 100.0, company[i].stock_issued, - company[i].max_stock - company[i].stock_issued); + + left(curwin, line, 4, attr_normal, 0, 0, 1, "%s", + company[i].name); + + right(curwin, line, w - 2, attr_normal, 0, 0, 1, "%'ld ", + company[i].max_stock - company[i].stock_issued); + right(curwin, line, w - 4 - STOCK_LEFT_COLS, attr_normal, + 0, 0, 1, "%'ld ", company[i].stock_issued); + right(curwin, line, w - 6 - STOCK_LEFT_COLS + - STOCK_ISSUED_COLS, attr_normal, 0, 0, 1, "%.2f ", + company[i].share_return * 100.0); + right(curwin, line, w - 8 - STOCK_LEFT_COLS + - STOCK_ISSUED_COLS - SHARE_RETURN_COLS, attr_normal, + 0, 0, 1, " %!N ", company[i].share_price); + line++; } } - - free(buf); } wrefresh(curwin); @@ -141,30 +153,17 @@ void exchange_stock (void) // Show menu of choices for the player newtxwin(6, WIN_COLS, 18, WCENTER, true, attr_normal_window); - wmove(curwin, 3, 2); - old_attrpr(curwin, attr_keycode, "<1>"); - waddstr(curwin, " Display stock portfolio"); + left(curwin, 3, 2, attr_normal, attr_keycode, 0, 1, + "^{<1>^} Display stock portfolio"); + left(curwin, 4, 2, attr_normal, attr_keycode, 0, 1, + "^{<2>^} Display galaxy map"); + left(curwin, 3, getmaxx(curwin) / 2, attr_normal, attr_keycode, 0, 1, + "^{<3>^} Visit the Trading Bank"); + left(curwin, 4, getmaxx(curwin) / 2, attr_normal, attr_keycode, 0, 1, + "^{<4>^} Exit the Stock Exchange"); - wmove(curwin, 4, 2); - old_attrpr(curwin, attr_keycode, "<2>"); - waddstr(curwin, " Display galaxy map"); - - wmove(curwin, 3, 40); - old_attrpr(curwin, attr_keycode, "<3>"); - waddstr(curwin, " Visit the Trading Bank"); - - wmove(curwin, 4, 40); - old_attrpr(curwin, attr_keycode, "<4>"); - waddstr(curwin, " Exit the Stock Exchange"); - - mvwaddstr(curwin, 1, 18, "Enter selection "); - waddstr(curwin, "["); - old_attrpr(curwin, attr_highlight, "Company letter"); - waddstr(curwin, "/"); - old_attrpr(curwin, attr_keycode, "1"); - waddstr(curwin, "-"); - old_attrpr(curwin, attr_keycode, "4"); - waddstr(curwin, "]: "); + center(curwin, 1, -1, attr_normal, attr_keycode, attr_highlight, 1, + "Enter selection [^[Company letter^]/^{1^}-^{4^}]: "); curs_set(CURS_ON); wrefresh(curwin); @@ -250,10 +249,10 @@ void visit_bank (void) double val, max; int key; bool done; - char *buf; + chtype *chbuf = xmalloc(BUFSIZE * sizeof(chtype)); + int x, width; - buf = xmalloc(BUFSIZE); credit_limit = (total_value(current_player) - player[current_player].debt) * CREDIT_LIMIT_RATE; @@ -264,38 +263,43 @@ void visit_bank (void) // Show the informational part of the Bank newtxwin(10, WIN_COLS - 4, 5, WCENTER, true, attr_normal_window); - old_center(curwin, 1, attr_title, " Interstellar Trading Bank "); + center(curwin, 1, 0, attr_title, 0, 0, 1, " Interstellar Trading Bank "); - l_strfmon(buf, BUFSIZE, "%18n", player[current_player].cash); - old_center2(curwin, 3, attr_normal, attr_highlight, "Current cash: ", - " %s ", buf); + mkchstr(chbuf, BUFSIZE, attr_normal, 0, 0, 1, getmaxx(curwin) - 4, &width, + 1, "Current cash: "); + x = (getmaxx(curwin) + width - (BANK_VALUE_COLS + 2)) / 2; - l_strfmon(buf, BUFSIZE, "%18n", player[current_player].debt); - old_center2(curwin, 4, attr_normal, attr_highlight, "Current debt: ", - " %s ", buf); + rightch(curwin, 3, x, chbuf, 1, &width); + right(curwin, 3, x + BANK_VALUE_COLS + 2, attr_normal, attr_highlight, 0, + 1, " ^{%N^} ", player[current_player].cash); - old_center2(curwin, 5, attr_normal, attr_highlight, "Interest rate: ", - " %17.2f%% ", interest_rate * 100.0); + right(curwin, 4, x, attr_normal, 0, 0, 1, "Current debt: "); + right(curwin, 4, x + BANK_VALUE_COLS + 2, attr_normal, attr_highlight, 0, + 1, " ^{%N^} ", player[current_player].debt); - l_strfmon(buf, BUFSIZE, "%18n", credit_limit); - old_center2(curwin, 7, attr_highlight, attr_title, "Credit limit: ", - " %s ", buf); + right(curwin, 5, x, attr_normal, 0, 0, 1, "Interest rate: "); + right(curwin, 5, x + BANK_VALUE_COLS + 2, attr_normal, attr_highlight, 0, + 1, " ^{%.2f%%^} ", interest_rate * 100.0); + + right(curwin, 7, x, attr_highlight, 0, 0, 1, "Credit limit: "); + whline(curwin, ' ' | attr_title, BANK_VALUE_COLS + 2); + right(curwin, 7, x + BANK_VALUE_COLS + 2, attr_title, 0, 0, 1, + " %N ", credit_limit); wrefresh(curwin); // Show menu of choices for the player newtxwin(7, WIN_COLS - 4, 15, WCENTER, true, attr_normal_window); - old_center2(curwin, 3, attr_keycode, attr_normal, "<1>", " Borrow money "); - old_center2(curwin, 4, attr_keycode, attr_normal, "<2>", " Repay debt "); - old_center2(curwin, 5, attr_keycode, attr_normal, "<3>", " Exit from the Bank"); + center(curwin, 3, 0, attr_normal, attr_keycode, 0, 1, + "^{<1>^} Borrow money "); + center(curwin, 4, 0, attr_normal, attr_keycode, 0, 1, + "^{<2>^} Repay debt "); + center(curwin, 5, 0, attr_normal, attr_keycode, 0, 1, + "^{<3>^} Exit from the Bank"); - mvwaddstr(curwin, 1, 24, "Enter selection "); - waddstr(curwin, "["); - old_attrpr(curwin, attr_keycode, "1"); - waddstr(curwin, "-"); - old_attrpr(curwin, attr_keycode, "3"); - waddstr(curwin, "]: "); + center(curwin, 1, 0, attr_normal, attr_keycode, 0, 1, + "Enter selection [^{1^}-^{3^}]: "); curs_set(CURS_ON); wrefresh(curwin); @@ -337,42 +341,48 @@ void visit_bank (void) attr_error_waitforkey, " Insufficient Credit Limit ", "The Bank will not lend you any more money."); } else { - int x, y, n; - int ret; + chtype *chbuf_cursym; + int width_cursym; + int n, ret; - wbkgd(curwin, attr_normal_window); + wbkgdset(curwin, attr_normal_window); werase(curwin); box(curwin, 0, 0); - mvwprintw(curwin, 3, 10, "How much do you wish to borrow? "); + n = (lconvinfo.p_sep_by_space == 1) ? 1 : 0; + + mkchstr(chbuf, BUFSIZE, attr_normal, attr_normal | A_BOLD, 0, 1, + getmaxx(curwin) / 2, &width_cursym, 1, "^{%s^}", + lconvinfo.currency_symbol); + chbuf_cursym = chstrdup(chbuf, BUFSIZE); + + mkchstr(chbuf, BUFSIZE, attr_normal, 0, 0, 1, getmaxx(curwin) + - BANK_INPUT_COLS - width_cursym - 6, &width, 1, + "How much do you wish to borrow? "); + x = (getmaxx(curwin) + width - BANK_INPUT_COLS - width_cursym + - n) / 2; + rightch(curwin, 3, x, chbuf, 1, &width); // Show the currency symbol before or after the input field - wattron(curwin, A_BOLD); if (lconvinfo.p_cs_precedes == 1) { - wprintw(curwin, "%s%s", lconvinfo.currency_symbol, - (lconvinfo.p_sep_by_space == 1) ? " " : ""); - n = 10; + leftch(curwin, 3, x, chbuf_cursym, 1, &width_cursym); + x += width_cursym + n; } else { - getyx(curwin, y, x); - n = strlen(lconvinfo.currency_symbol) + 10 - + (lconvinfo.p_sep_by_space == 1); - mvwprintw(curwin, y, getmaxx(curwin) - n, "%s%s", - (lconvinfo.p_sep_by_space == 1) ? " " : "", - lconvinfo.currency_symbol); - wmove(curwin, y, x); + leftch(curwin, 3, x + BANK_INPUT_COLS + n, chbuf_cursym, 1, + &width_cursym); } - wattroff(curwin, A_BOLD); - x = getcurx(curwin); ret = gettxdouble(curwin, &val, 0.0, credit_limit + ROUNDING_AMOUNT, - 0.0, credit_limit, 3, x, getmaxx(curwin) - x - n, + 0.0, credit_limit, 3, x, BANK_INPUT_COLS, attr_input_field); if (ret == OK && val > ROUNDING_AMOUNT) { player[current_player].cash += val; player[current_player].debt += val * (interest_rate + 1.0); } + + free(chbuf_cursym); } break; @@ -389,39 +399,42 @@ void visit_bank (void) attr_error_waitforkey, " No Cash ", "You have no cash with which to repay the debt!"); } else { - int x, y, n; - int ret; + chtype *chbuf_cursym; + int width_cursym; + int n, ret; - wbkgd(curwin, attr_normal_window); + wbkgdset(curwin, attr_normal_window); werase(curwin); box(curwin, 0, 0); - mvwprintw(curwin, 3, 10, "How much do you wish to repay? "); + n = (lconvinfo.p_sep_by_space == 1) ? 1 : 0; + + mkchstr(chbuf, BUFSIZE, attr_normal, attr_normal | A_BOLD, 0, 1, + getmaxx(curwin) / 2, &width_cursym, 1, "^{%s^}", + lconvinfo.currency_symbol); + chbuf_cursym = chstrdup(chbuf, BUFSIZE); + + mkchstr(chbuf, BUFSIZE, attr_normal, 0, 0, 1, getmaxx(curwin) + - BANK_INPUT_COLS - width_cursym - 6, &width, 1, + "How much do you wish to repay? "); + x = (getmaxx(curwin) + width - BANK_INPUT_COLS - width_cursym + - n) / 2; + rightch(curwin, 3, x, chbuf, 1, &width); // Show the currency symbol before or after the input field - wattron(curwin, A_BOLD); if (lconvinfo.p_cs_precedes == 1) { - wprintw(curwin, "%s%s", lconvinfo.currency_symbol, - (lconvinfo.p_sep_by_space == 1) ? " " : ""); - n = 10; + leftch(curwin, 3, x, chbuf_cursym, 1, &width_cursym); + x += width_cursym + n; } else { - getyx(curwin, y, x); - n = strlen(lconvinfo.currency_symbol) + 10 - + (lconvinfo.p_sep_by_space == 1); - mvwprintw(curwin, y, getmaxx(curwin) - n, "%s%s", - (lconvinfo.p_sep_by_space == 1) ? " " : "", - lconvinfo.currency_symbol); - wmove(curwin, y, x); + leftch(curwin, 3, x + BANK_INPUT_COLS + n, chbuf_cursym, 1, + &width_cursym); } - wattroff(curwin, A_BOLD); - x = getcurx(curwin); max = MIN(player[current_player].cash, player[current_player].debt); ret = gettxdouble(curwin, &val, 0.0, max + ROUNDING_AMOUNT, 0.0, - max, 3, x, getmaxx(curwin) - x - n, - attr_input_field); + max, 3, x, BANK_INPUT_COLS, attr_input_field); if (ret == OK) { player[current_player].cash -= val; @@ -434,6 +447,8 @@ void visit_bank (void) player[current_player].debt = 0.0; } } + + free(chbuf_cursym); } break; @@ -445,7 +460,7 @@ void visit_bank (void) deltxwin(); // Trading Bank window txrefresh(); - free(buf); + free(chbuf); } @@ -455,16 +470,17 @@ void visit_bank (void) void trade_shares (int num, bool *bid_used) { bool done; - int key, ret, x; + int key, ret, w, x; long int maxshares, val; double ownership; - char *buf; + chtype *chbuf; + int width; assert(num >= 0 && num < MAX_COMPANIES); assert(company[num].on_map); - buf = xmalloc(BUFSIZE); + chbuf = xmalloc(BUFSIZE * sizeof(chtype)); ownership = (company[num].stock_issued == 0) ? 0.0 : ((double) player[current_player].stock_owned[num] @@ -472,64 +488,58 @@ void trade_shares (int num, bool *bid_used) // Show the informational part of the trade window newtxwin(9, WIN_COLS - 4, 5, WCENTER, true, attr_normal_window); + w = getmaxx(curwin); - old_center(curwin, 1, attr_title, " Stock Transaction in %s ", + center(curwin, 1, 0, attr_title, 0, 0, 1, " Stock Transaction in %s ", company[num].name); - mvwaddstr(curwin, 3, 2, "Shares issued: "); - old_attrpr(curwin, attr_highlight, "%'12ld", company[num].stock_issued); + mkchstr(chbuf, BUFSIZE, attr_normal, 0, 0, 1, w / 2, &width, 1, + "Shares issued: "); + leftch(curwin, 3, 2, chbuf, 1, &width); + right(curwin, 3, width + SHARE_PRICE_COLS + 2, attr_normal, attr_highlight, + 0, 1, "^{%'ld^}", company[num].stock_issued); - mvwaddstr(curwin, 4, 2, "Shares left: "); - old_attrpr(curwin, attr_highlight, "%'12ld", - company[num].max_stock - company[num].stock_issued); + left(curwin, 4, 2, attr_normal, 0, 0, 1, "Shares left: "); + right(curwin, 4, width + SHARE_PRICE_COLS + 2, attr_normal, attr_highlight, + 0, 1, "^{%'ld^}", company[num].max_stock - company[num].stock_issued); - mvwaddstr(curwin, 5, 2, "Price per share: "); - l_strfmon(buf, BUFSIZE, "%12n", company[num].share_price); - old_attrpr(curwin, attr_highlight, "%12s", buf); + left(curwin, 5, 2, attr_normal, 0, 0, 1, "Price per share: "); + right(curwin, 5, width + SHARE_PRICE_COLS + 2, attr_normal, attr_highlight, + 0, 1, "^{%N^}", company[num].share_price); - mvwaddstr(curwin, 6, 2, "Return: "); - old_attrpr(curwin, attr_highlight, "%11.2f%%", - company[num].share_return * 100.0); + left(curwin, 6, 2, attr_normal, 0, 0, 1, "Return: "); + right(curwin, 6, width + SHARE_PRICE_COLS + 2, attr_normal, attr_highlight, + 0, 1, "^{%.2f%%^}", company[num].share_return * 100.0); - mvwaddstr(curwin, 3, 38, "Current holdings: "); - old_attrpr(curwin, attr_highlight, " %'16ld ", - player[current_player].stock_owned[num]); + left(curwin, 3, w / 2, attr_normal, 0, 0, 1, "Current holdings: "); + right(curwin, 3, w - 2, attr_normal, attr_highlight, 0, 1, " ^{%'ld^} ", + player[current_player].stock_owned[num]); - mvwaddstr(curwin, 4, 38, "Percentage owned: "); - old_attrpr(curwin, attr_highlight, " %'15.2f%% ", ownership * 100.0); + left(curwin, 4, w / 2, attr_normal, 0, 0, 1, "Percentage owned: "); + right(curwin, 4, w - 2, attr_normal, attr_highlight, 0, 1, " ^{%.2f%%^} ", + ownership * 100.0); - wmove(curwin, 6, 38); - old_attrpr(curwin, attr_highlight, "Current cash: "); - l_strfmon(buf, BUFSIZE, "%16n", player[current_player].cash); - old_attrpr(curwin, attr_title, " %16s ", buf); + left(curwin, 6, w / 2, attr_highlight, 0, 0, 1, "Current cash: "); + whline(curwin, ' ' | attr_title, TRADE_VALUE_COLS + 2); + right(curwin, 6, w - 2, attr_title, 0, 0, 1, " %N ", + player[current_player].cash); wrefresh(curwin); // Show menu of choices for the player newtxwin(7, WIN_COLS - 4, 14, WCENTER, true, attr_normal_window); - wmove(curwin, 3, 2); - old_attrpr(curwin, attr_keycode, "<1>"); - waddstr(curwin, " Buy stock from company"); + left(curwin, 3, 2, attr_normal, attr_keycode, 0, 1, + "^{<1>^} Buy stock from company"); + left(curwin, 4, 2, attr_normal, attr_keycode, 0, 1, + "^{<2>^} Sell stock back to company"); + left(curwin, 3, getmaxx(curwin) / 2, attr_normal, attr_keycode, 0, 1, + "^{<3>^} Bid company to issue more shares"); + left(curwin, 4, getmaxx(curwin) / 2, attr_normal, attr_keycode, 0, 1, + "^{<4>^} Exit to the Stock Exchange"); - wmove(curwin, 4, 2); - old_attrpr(curwin, attr_keycode, "<2>"); - waddstr(curwin, " Sell stock back to company"); - - wmove(curwin, 3, 38); - old_attrpr(curwin, attr_keycode, "<3>"); - waddstr(curwin, " Bid company to issue more shares"); - - wmove(curwin, 4, 38); - old_attrpr(curwin, attr_keycode, "<4>"); - waddstr(curwin, " Exit to the Stock Exchange"); - - mvwaddstr(curwin, 1, 24, "Enter selection "); - waddstr(curwin, "["); - old_attrpr(curwin, attr_keycode, "1"); - waddstr(curwin, "-"); - old_attrpr(curwin, attr_keycode, "4"); - waddstr(curwin, "]: "); + center(curwin, 1, 0, attr_normal, attr_keycode, 0, 1, + "Enter selection [^{1^}-^{4^}]: "); curs_set(CURS_ON); wrefresh(curwin); @@ -577,23 +587,27 @@ void trade_shares (int num, bool *bid_used) txdlgbox(MAX_DLG_LINES, 50, 8, WCENTER, attr_error_window, attr_error_title, attr_error_highlight, 0, 0, attr_error_waitforkey, " Insufficient Cash ", - "Not enough cash to purchase shares."); + "You do not have enough cash\n" + "to purchase additional shares."); } else { maxshares = MIN(maxshares, company[num].max_stock - company[num].stock_issued); - wbkgd(curwin, attr_normal_window); + wbkgdset(curwin, attr_normal_window); werase(curwin); box(curwin, 0, 0); - old_center3(curwin, 2, attr_normal, attr_normal, attr_highlight, - "You can purchase up to ", " shares.", "%'ld", maxshares); + center(curwin, 2, 0, attr_normal, attr_highlight, 0, 1, + "You can purchase up to ^{%'ld^} shares.", maxshares); - mvwprintw(curwin, 4, 10, "How many shares do you wish to purchase? "); - x = getcurx(curwin); + mkchstr(chbuf, BUFSIZE, attr_normal, 0, 0, 1, getmaxx(curwin) + - TRADE_INPUT_COLS - 4, &width, 1, + "How many shares do you wish to purchase? "); + x = (getmaxx(curwin) + width - TRADE_INPUT_COLS) / 2; + rightch(curwin, 4, x, chbuf, 1, &width); ret = gettxlong(curwin, &val, 0, maxshares, 0, maxshares, 4, x, - getmaxx(curwin) - x - 10, attr_input_field); + TRADE_INPUT_COLS, attr_input_field); if (ret == OK) { player[current_player].cash -= val * company[num].share_price; @@ -612,18 +626,21 @@ void trade_shares (int num, bool *bid_used) attr_error_waitforkey, " No Shares ", "You do not have any shares to sell."); } else { - wbkgd(curwin, attr_normal_window); + wbkgdset(curwin, attr_normal_window); werase(curwin); box(curwin, 0, 0); - old_center3(curwin, 2, attr_normal, attr_normal, attr_highlight, - "You can sell up to ", " shares.", "%'ld", maxshares); + center(curwin, 2, 0, attr_normal, attr_highlight, 0, 1, + "You can sell up to ^{%'ld^} shares.", maxshares); - mvwprintw(curwin, 4, 10, "How many shares do you wish to sell? "); - x = getcurx(curwin); + mkchstr(chbuf, BUFSIZE, attr_normal, 0, 0, 1, getmaxx(curwin) + - TRADE_INPUT_COLS - 4, &width, 1, + "How many shares do you wish to sell? "); + x = (getmaxx(curwin) + width - TRADE_INPUT_COLS) / 2; + rightch(curwin, 4, x, chbuf, 1, &width); ret = gettxlong(curwin, &val, 0, maxshares, 0, maxshares, 4, x, - getmaxx(curwin) - x - 10, attr_input_field); + TRADE_INPUT_COLS, attr_input_field); if (ret == OK) { company[num].stock_issued -= val; @@ -666,7 +683,7 @@ void trade_shares (int num, bool *bid_used) deltxwin(); // Stock Transaction window txrefresh(); - free(buf); + free(chbuf); } diff --git a/src/game.c b/src/game.c index 52628ef..43500b0 100644 --- a/src/game.c +++ b/src/game.c @@ -652,7 +652,7 @@ void show_map (bool closewin) void show_status (int num) { double val; - int i, line; + int w, i, line; assert(num >= 0 && num < number_players); @@ -668,6 +668,8 @@ void show_status (int num) center(curwin, 11, 0, attr_normal, attr_highlight, attr_blink, 1, "^[* * * B A N K R U P T * * *^]"); } else { + w = getmaxx(curwin); + // Check to see if any companies are on the map bool none = true; for (i = 0; i < MAX_COMPANIES; i++) { @@ -681,37 +683,34 @@ void show_status (int num) center(curwin, 8, 0, attr_normal, attr_highlight, 0, 1, "No companies on the map"); } else { - mvwhline(curwin, 4, 2, ' ' | attr_subtitle, getmaxx(curwin) - 4); - mvwhline(curwin, 5, 2, ' ' | attr_subtitle, getmaxx(curwin) - 4); + mvwhline(curwin, 4, 2, ' ' | attr_subtitle, w - 4); + mvwhline(curwin, 5, 2, ' ' | attr_subtitle, w - 4); left(curwin, 4, 4, attr_subtitle, 0, 0, 2, "\nCompany"); - right(curwin, 4, getmaxx(curwin) - 4, attr_subtitle, 0, 0, 2, - "Ownership\n(%%)"); - right(curwin, 4, getmaxx(curwin) - 6 - OWNERSHIP_COLS, - attr_subtitle, 0, 0, 2, "Holdings\n(shares)"); - right(curwin, 4, getmaxx(curwin) - 8 - OWNERSHIP_COLS - - STOCK_OWNED_COLS, attr_subtitle, 0, 0, 2, - "\nReturn (%%)"); - right(curwin, 4, getmaxx(curwin) - 10 - OWNERSHIP_COLS - - STOCK_OWNED_COLS - SHARE_RETURN_COLS, attr_subtitle, 0, 0, - 2, "Price per\nshare (%s)", lconvinfo.currency_symbol); + right(curwin, 4, w - 4, attr_subtitle, 0, 0, 2, "Ownership\n(%%)"); + right(curwin, 4, w - 6 - OWNERSHIP_COLS, attr_subtitle, 0, 0, + 2, "Holdings\n(shares)"); + right(curwin, 4, w - 8 - OWNERSHIP_COLS - STOCK_OWNED_COLS, + attr_subtitle, 0, 0, 2, "Return\n(%%)"); + right(curwin, 4, w - 10 - OWNERSHIP_COLS - STOCK_OWNED_COLS + - SHARE_RETURN_COLS, attr_subtitle, 0, 0, 2, + "Price per\nshare (%s)", lconvinfo.currency_symbol); for (line = 6, i = 0; i < MAX_COMPANIES; i++) { if (company[i].on_map) { left(curwin, line, 4, attr_normal, 0, 0, 1, "%s", company[i].name); - right(curwin, line, getmaxx(curwin) - 2, attr_normal, 0, 0, - 1, "%.2f ", (company[i].stock_issued == 0) ? 0.0 : + right(curwin, line, w - 2, attr_normal, 0, 0, 1, "%.2f ", + (company[i].stock_issued == 0) ? 0.0 : ((double) player[num].stock_owned[i] * 100.0) / company[i].stock_issued); - right(curwin, line, getmaxx(curwin) - 4 - OWNERSHIP_COLS, - attr_normal, 0, 0, 1, "%'ld ", - player[num].stock_owned[i]); - right(curwin, line, getmaxx(curwin) - 6 - OWNERSHIP_COLS + right(curwin, line, w - 4 - OWNERSHIP_COLS, attr_normal, + 0, 0, 1, "%'ld ", player[num].stock_owned[i]); + right(curwin, line, w - 6 - OWNERSHIP_COLS - STOCK_OWNED_COLS, attr_normal, 0, 0, 1, "%.2f ", company[i].share_return * 100.0); - right(curwin, line, getmaxx(curwin) - 8 - OWNERSHIP_COLS + right(curwin, line, w - 8 - OWNERSHIP_COLS - STOCK_OWNED_COLS - SHARE_RETURN_COLS, attr_normal, 0, 0, 1, " %!N ", company[i].share_price); @@ -725,9 +724,9 @@ void show_status (int num) chtype *chbuf = xmalloc(BUFSIZE * sizeof(chtype)); int width, x; - mkchstr(chbuf, BUFSIZE, attr_highlight, 0, 0, 1, getmaxx(curwin) / 2, - &width, 1, "Total value: "); - x = (getmaxx(curwin) + width - (TOTAL_VALUE_COLS + 2)) / 2; + mkchstr(chbuf, BUFSIZE, attr_highlight, 0, 0, 1, w / 2, &width, 1, + "Total value: "); + x = (w + width - (TOTAL_VALUE_COLS + 2)) / 2; right(curwin, line, x, attr_normal, attr_highlight, 0, 1, "Current cash: "); diff --git a/src/help.c b/src/help.c index 5875708..fa2a51b 100644 --- a/src/help.c +++ b/src/help.c @@ -174,8 +174,8 @@ void show_help (void) while (! done) { // Display a page of instructions + wbkgdset(curwin, attr_normal_window); werase(curwin); - wbkgd(curwin, attr_normal_window); box(curwin, 0, 0); center(curwin, 1, 0, attr_title, 0, 0, 1, " How to Play "); diff --git a/src/intf.h b/src/intf.h index f975dcf..8d0e0cf 100644 --- a/src/intf.h +++ b/src/intf.h @@ -56,6 +56,7 @@ #define WCENTER -1 // Centre the new window #define MAX_DLG_LINES 10 // Default maximum lines of text in dialog box + #define YESNO_COLS 4 // Space to allow for "Yes" or "No" response #define ORDINAL_COLS 5 // Space for ordinals (1st, 2nd, etc) #define TOTAL_VALUE_COLS 18 // Space for total value (monetary) @@ -63,6 +64,16 @@ #define SHARE_RETURN_COLS 10 // Space for "Return per share" #define STOCK_OWNED_COLS 10 // Space for "Holdings (shares)" #define OWNERSHIP_COLS 10 // Space for "Company ownership (%)" +#define STOCK_ISSUED_COLS 10 // Space for "Shares issued" +#define STOCK_LEFT_COLS 10 // Space for "Shares left" +#define BANK_VALUE_COLS 18 // Space for amounts in bank window +#define BANK_INPUT_COLS 16 // Space for input text box in bank +#define TRADE_VALUE_COLS 16 // Space for amounts in trade window +#define TRADE_INPUT_COLS 10 // Space for input text box in trade window +#define MERGE_BONUS_COLS 12 // Space for "Bonus" (company merger) +#define MERGE_OLD_STOCK_COLS 8 // Space for "Old stocks" (company merger) +#define MERGE_NEW_STOCK_COLS 8 // Space for "New stocks" (company merger) +#define MERGE_TOTAL_STOCK_COLS 8 // Space for "Total stocks" (company merger) // Check if resizing events are supported diff --git a/src/move.c b/src/move.c index c7e926e..c1eb629 100644 --- a/src/move.c +++ b/src/move.c @@ -227,7 +227,7 @@ selection_t get_move (void) // Show menu of choices for the player newtxwin(5, WIN_COLS, 19, WCENTER, false, 0); while (selection == SEL_NONE) { - wbkgd(curwin, attr_normal_window); + wbkgdset(curwin, attr_normal_window); werase(curwin); box(curwin, 0, 0); @@ -731,10 +731,13 @@ void merge_companies (map_val_t a, map_val_t b) double val_bb = company[bb].share_price * company[bb].stock_issued * company[bb].share_return; - long int old_stock, new_stock, total_new; - int x, y, i, line; double bonus; - char *buf = xmalloc(BUFSIZE); + long int old_stock, new_stock, total_new; + chtype *chbuf = xmalloc(BUFSIZE * sizeof(chtype)); + int lines, width, widthbuf[4]; + chtype *chbuf_aa, *chbuf_bb; + int width_aa, width_bb; + int x, y, w, i, ln; if (val_aa < val_bb) { @@ -748,31 +751,49 @@ void merge_companies (map_val_t a, map_val_t b) // Display information about the merger - newtxwin(number_players + 14, WIN_COLS - 4, 9 - number_players, - WCENTER, true, attr_normal_window); + lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_highlight, 0, 4, WIN_COLS + - 8, widthbuf, 4, "^{%s^} has just merged into ^{%s^}.\n" + "Please note the following transactions:\n", + company[bb].name, company[aa].name); - old_center(curwin, 1, attr_title, " Company Merger "); - old_center3(curwin, 3, attr_highlight, attr_highlight, attr_normal, - company[bb].name, company[aa].name, " has just merged into "); + newtxwin(number_players + lines + 10, WIN_COLS - 4, lines + 6 + - number_players, WCENTER, true, attr_normal_window); + center(curwin, 1, 0, attr_title, 0, 0, 1, " Company Merger "); + centerch(curwin, 3, 0, chbuf, lines, widthbuf); - old_center(curwin, 5, attr_normal, "Please note the following transactions:"); + mkchstr(chbuf, BUFSIZE, attr_highlight, 0, 0, 1, getmaxx(curwin) / 2, + &width_aa, 1, "%s", company[aa].name); + chbuf_aa = chstrdup(chbuf, BUFSIZE); - old_center2(curwin, 7, attr_normal, attr_highlight, " Old stock: ", - "%-20s", company[bb].name); - old_center2(curwin, 8, attr_normal, attr_highlight, " New stock: ", - "%-20s", company[aa].name); + mkchstr(chbuf, BUFSIZE, attr_highlight, 0, 0, 1, getmaxx(curwin) / 2, + &width_bb, 1, "%s", company[bb].name); + chbuf_bb = chstrdup(chbuf, BUFSIZE); - // Handle the locale's currency symbol - snprintf(buf, BUFSIZE, "Bonus (%s)", lconvinfo.currency_symbol); + mkchstr(chbuf, BUFSIZE, attr_normal, 0, 0, 1, getmaxx(curwin) / 2, &width, + 1, "Old stock: "); - int w = getmaxx(curwin) - 52; - wattrset(curwin, attr_subtitle); - mvwprintw(curwin, 10, 2, " %-*.*s %8s %8s %8s %12s ", w, w, - "Player", "Old", "New", "Total", buf); - wattrset(curwin, attr_normal); + w = getmaxx(curwin); + x = (w + width - MAX(width_aa, width_bb)) / 2; + + rightch(curwin, lines + 3, x, chbuf, 1, &width); + leftch(curwin, lines + 3, x, chbuf_bb, 1, &width_bb); + + right(curwin, lines + 4, x, attr_normal, 0, 0, 1, "New Stock: "); + leftch(curwin, lines + 4, x, chbuf_aa, 1, &width_aa); + + mvwhline(curwin, lines + 6, 2, ' ' | attr_subtitle, w - 4); + left(curwin, lines + 6, 4, attr_subtitle, 0, 0, 1, "Player"); + right(curwin, lines + 6, w - 4, attr_subtitle, 0, 0, 1, + "Bonus (%s)", lconvinfo.currency_symbol); + right(curwin, lines + 6, w - 6 - MERGE_BONUS_COLS, attr_subtitle, 0, 0, + 1, "Total"); + right(curwin, lines + 6, w - 8 - MERGE_BONUS_COLS - MERGE_TOTAL_STOCK_COLS, + attr_subtitle, 0, 0, 1, "New"); + right(curwin, lines + 6, w - 10 - MERGE_BONUS_COLS - MERGE_TOTAL_STOCK_COLS + - MERGE_NEW_STOCK_COLS, attr_subtitle, 0, 0, 1, "Old"); total_new = 0; - for (line = 11, i = 0; i < number_players; i++) { + for (ln = lines + 7, i = 0; i < number_players; i++) { if (player[i].in_game) { // Calculate new stock and any bonus old_stock = player[i].stock_owned[bb]; @@ -787,11 +808,22 @@ void merge_companies (map_val_t a, map_val_t b) player[i].stock_owned[bb] = 0; player[i].cash += bonus; - l_strfmon(buf, BUFSIZE, "%!12n", bonus); - mvwprintw(curwin, line, 2, " %-*.*s %'8ld %'8ld %'8ld %12s ", - w, w, player[i].name, old_stock, new_stock, - player[i].stock_owned[aa], buf); - line++; + mkchstr(chbuf, BUFSIZE, attr_normal, 0, 0, 1, w - 12 + - MERGE_BONUS_COLS - MERGE_TOTAL_STOCK_COLS + - MERGE_NEW_STOCK_COLS - MERGE_OLD_STOCK_COLS, + &width, 1, "%s", player[i].name); + leftch(curwin, ln, 4, chbuf, 1, &width); + + right(curwin, ln, w - 4, attr_normal, 0, 0, 1, "%!N", bonus); + right(curwin, ln, w - 6 - MERGE_BONUS_COLS, attr_normal, 0, 0, 1, + "%'ld", player[i].stock_owned[aa]); + right(curwin, ln, w - 8 - MERGE_BONUS_COLS - MERGE_TOTAL_STOCK_COLS, + attr_normal, 0, 0, 1, "%'ld", new_stock); + right(curwin, ln, w - 10 - MERGE_BONUS_COLS - MERGE_TOTAL_STOCK_COLS + - MERGE_NEW_STOCK_COLS, attr_normal, 0, 0, 1, "%'ld", + old_stock); + + ln++; } } @@ -818,7 +850,9 @@ void merge_companies (map_val_t a, map_val_t b) deltxwin(); // "Company merger" window txrefresh(); - free(buf); + free(chbuf_bb); + free(chbuf_aa); + free(chbuf); } @@ -890,7 +924,6 @@ void inc_share_price (int num, double inc) void adjust_values (void) { - int i, x, y; int which; @@ -913,45 +946,57 @@ void adjust_values (void) } else { double rate = randf(); - char *buf = xmalloc(BUFSIZE); - for (i = 0; i < number_players; i++) { + chtype *chbuf = xmalloc(BUFSIZE * sizeof(chtype)); + chtype *chbuf_amt; + int w, x, lines, width, width_amt, widthbuf[6]; + + for (int i = 0; i < number_players; i++) { if (player[i].in_game) { player[i].cash += player[i].stock_owned[which] * rate; } } - newtxwin(14, 60, 4, WCENTER, true, attr_error_window); + lines = mkchstr(chbuf, BUFSIZE, attr_error_highlight, + attr_error_normal, 0, 6, 60 - 4, widthbuf, 6, + "%s has been declared bankrupt by the " + "Interstellar Trading Bank.\n\n" + "^{The Bank has agreed to pay stock holders ^}" + "%.2f%%^{ of the share value on each share " + "owned.^}", company[which].name, rate * 100.0); - old_center(curwin, 1, attr_error_title, " Bankruptcy Court "); - old_center(curwin, 3, attr_error_highlight, "%s has been declared", - company[which].name); - old_center(curwin, 4, attr_error_highlight, - "bankrupt by the Interstellar Trading Bank."); + newtxwin(9 + lines, 60, 4, WCENTER, true, attr_error_window); + w = getmaxx(curwin); - old_center2(curwin, 6, attr_error_normal, attr_error_highlight, - "The Bank has agreed to pay stock holders ", - "%4.2f%%", rate * 100.0); - old_center(curwin, 7, attr_error_normal, - "of the share value on each share owned."); + center(curwin, 1, 0, attr_error_title, 0, 0, 1, + " Bankruptcy Court "); + centerch(curwin, 3, 0, chbuf, lines, widthbuf); - l_strfmon(buf, BUFSIZE, "%12n", company[which].share_price); - old_center2(curwin, 9, attr_error_normal, attr_error_highlight, - "Old share value: ", "%s", buf); + mkchstr(chbuf, BUFSIZE, attr_error_highlight, 0, 0, 1, w / 2, + &width_amt, 1, "%N", company[which].share_price); + chbuf_amt = chstrdup(chbuf, BUFSIZE); - l_strfmon(buf, BUFSIZE, "%12n", company[which].share_price - * rate); - old_center2(curwin, 10, attr_error_normal, attr_error_highlight, - "Amount paid per share: ", "%s", buf); + mkchstr(chbuf, BUFSIZE, attr_error_normal, 0, 0, 1, w / 2, + &width, 1, "Amount paid per share: "); + x = (w + width - width_amt) / 2; - wait_for_key(curwin, 12, attr_error_waitforkey); + right(curwin, lines + 4, x, attr_error_normal, 0, 0, 1, + "Old share value: "); + leftch(curwin, lines + 4, x, chbuf_amt, 1, &width_amt); + + rightch(curwin, lines + 5, x, chbuf, 1, &width); + left(curwin, lines + 5, x, attr_error_highlight, 0, 0, 1, + "%N", company[which].share_price * rate); + + wait_for_key(curwin, getmaxy(curwin) - 2, attr_error_waitforkey); deltxwin(); txrefresh(); - free(buf); + free(chbuf_amt); + free(chbuf); } - for (i = 0; i < number_players; i++) { + for (int i = 0; i < number_players; i++) { player[i].stock_owned[which] = 0; } @@ -961,8 +1006,8 @@ void adjust_values (void) company[which].max_stock = 0; company[which].on_map = false; - for (x = 0; x < MAX_X; x++) { - for (y = 0; y < MAX_Y; y++) { + for (int x = 0; x < MAX_X; x++) { + for (int y = 0; y < MAX_Y; y++) { if (galaxy_map[x][y] == COMPANY_TO_MAP((unsigned int) which)) { galaxy_map[x][y] = MAP_EMPTY; } @@ -980,7 +1025,7 @@ void adjust_values (void) } // Make sure that a company's return is not too large - for (i = 0; i < MAX_COMPANIES; i++) { + for (int i = 0; i < MAX_COMPANIES; i++) { if (company[i].on_map && company[i].share_return > MAX_COMPANY_RETURN) { company[i].share_return /= randf() + RETURN_DIVIDER; } @@ -1000,7 +1045,7 @@ void adjust_values (void) } // Give the current player the companies' dividends - for (i = 0; i < MAX_COMPANIES; i++) { + for (int i = 0; i < MAX_COMPANIES; i++) { if (company[i].on_map && company[i].stock_issued != 0) { player[current_player].cash += player[current_player].stock_owned[i] * company[i].share_price * company[i].share_return From de6a4e3e667dcd8cd3e5e3e8bfa873a375826860 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Tue, 16 Aug 2011 18:51:56 +1000 Subject: [PATCH 041/112] Remove obsolete old_attrpr, old_center, old_center2 and old_center3 --- src/intf.c | 176 ----------------------------------------------------- src/intf.h | 98 ----------------------------- 2 files changed, 274 deletions(-) diff --git a/src/intf.c b/src/intf.c index db3021f..96bd95b 100644 --- a/src/intf.c +++ b/src/intf.c @@ -1440,182 +1440,6 @@ int right (WINDOW *win, int y, int x, chtype attr_norm, chtype attr_alt1, } -/***********************************************************************/ -// old_attrpr: Print a string with a particular character rendition - -int old_attrpr (WINDOW *win, chtype attr, const char *restrict format, ...) -{ - va_list args; - int ret; - - - assert(win != NULL); - assert(format != NULL); - - chtype oldattr = getattrs(win); - chtype oldbkgd = getbkgd(win); - - /* Note that wattrset() will override parts of wbkgdset() and vice - versa: don't swap the order of these two lines! */ - wbkgdset(win, (oldbkgd & A_COLOR) | A_NORMAL); - wattrset(win, attr); - - va_start(args, format); - ret = vw_printw(win, format, args); - va_end(args); - - wbkgdset(win, oldbkgd); - wattrset(win, oldattr); - - return ret; -} - - -/***********************************************************************/ -// old_center: Centre a string in a given window - -int old_center (WINDOW *win, int y, chtype attr, const char *restrict format, ...) -{ - va_list args; - int ret, len, x; - char *buf; - - - assert(win != NULL); - assert(format != NULL); - - buf = xmalloc(BUFSIZE); - - chtype oldattr = getattrs(win); - chtype oldbkgd = getbkgd(win); - - // Order is important: see old_attrpr() - wbkgdset(win, (oldbkgd & A_COLOR) | A_NORMAL); - wattrset(win, attr); - - va_start(args, format); - len = vsnprintf(buf, BUFSIZE, format, args); - va_end(args); - - if (len < 0) { - ret = ERR; - } else if (len == 0) { - ret = OK; - } else { - x = (getmaxx(win) - len) / 2; - ret = mvwprintw(win, y, MAX(x, 2), "%1.*s", getmaxx(win) - 4, buf); - } - - wbkgdset(win, oldbkgd); - wattrset(win, oldattr); - - free(buf); - return ret; -} - - -/***********************************************************************/ -// old_center2: Centre two strings in a given window - -int old_center2 (WINDOW *win, int y, chtype attr1, chtype attr2, - const char *initial, const char *restrict format, ...) -{ - va_list args; - int ret, len1, len2, x; - char *buf; - - - assert(win != NULL); - assert(initial != NULL); - assert(format != NULL); - - buf = xmalloc(BUFSIZE); - - chtype oldattr = getattrs(win); - chtype oldbkgd = getbkgd(win); - - wbkgdset(win, (oldbkgd & A_COLOR) | A_NORMAL); - - len1 = strlen(initial); - - va_start(args, format); - len2 = vsnprintf(buf, BUFSIZE, format, args); - va_end(args); - - if (len2 < 0) { - ret = ERR; - } else if (len1 + len2 == 0) { - ret = OK; - } else { - x = (getmaxx(win) - (len1 + len2)) / 2; - wattrset(win, attr1); - mvwprintw(win, y, MAX(x, 2), "%s", initial); - wattrset(win, attr2); - ret = wprintw(win, "%1.*s", getmaxx(win) - len1 - 4, buf); - } - - wbkgdset(win, oldbkgd); - wattrset(win, oldattr); - - free(buf); - return ret; -} - - -/***********************************************************************/ -// old_center3: Centre three strings in a given window - -int old_center3 (WINDOW *win, int y, chtype attr1, chtype attr3, chtype attr2, - const char *initial, const char *final, - const char *restrict format, ...) -{ - va_list args; - int len1, len2, len3; - int ret, x; - char *buf; - - - assert(win != NULL); - assert(initial != NULL); - assert(final != NULL); - assert(format != NULL); - - buf = xmalloc(BUFSIZE); - - chtype oldattr = getattrs(win); - chtype oldbkgd = getbkgd(win); - - wbkgdset(win, (oldbkgd & A_COLOR) | A_NORMAL); - - len1 = strlen(initial); - len3 = strlen(final); - - va_start(args, format); - len2 = vsnprintf(buf, BUFSIZE, format, args); - va_end(args); - - if (len2 < 0) { - ret = ERR; - } else if (len1 + len2 + len3 == 0) { - ret = OK; - } else { - x = (getmaxx(win) - (len1 + len2 + len3)) / 2; - wattrset(win, attr1); - mvwprintw(win, y, MAX(x, 2), "%s", initial); - wattrset(win, attr2); - ret = wprintw(win, "%1.*s", getmaxx(win) - len1 - len3 - 4, buf); - wattrset(win, attr3); - wprintw(win, "%s", final); - } - - wbkgdset(win, oldbkgd); - wattrset(win, oldattr); - - free(buf); - return ret; -} - - /***********************************************************************/ // gettxchar: Read a character from the keyboard diff --git a/src/intf.h b/src/intf.h index 8d0e0cf..00128d7 100644 --- a/src/intf.h +++ b/src/intf.h @@ -548,104 +548,6 @@ extern int right (WINDOW *win, int y, int x, chtype attr_norm, chtype attr_alt1, ...); -/* - Function: old_attrpr - Print a string with a particular character rendition - Parameters: win - Window to use (should be curwin) - attr - Character rendition to use for the string - format - printf()-like format string - ... - printf()-like arguments - Returns: int - Return code from wprintw(): OK or ERR - - This function sets the character rendition (attributes) to attr, prints - the string using wprintw(), then restores the previous character - rendition. The return code is as returned from wprintw(). Note that - wrefresh() is NOT called. -*/ -extern int old_attrpr (WINDOW *win, chtype attr, const char *restrict format, ...) - __attribute__((format (printf, 3, 4))); - - -/* - Function: old_center - Centre a string in a given window - Parameters: win - Window to use (should be curwin) - y - Line on which to centre the string - attr - Character rendition to use for the string - format - printf()-like format string - ... - printf()-like arguments - Returns: int - Return code from wprintw(): OK or ERR - - This function prints a string formatted with wprintw() in the centre of - line y in the window win, using the character rendition (attributes) in - attr. If the string is too long to fit the window, it is truncated. - Please note that wrefresh() is NOT called. - - At the current time, the implementation of this function does NOT - handle multibyte strings correctly: strlen() is used to determine the - printing width of the string. -*/ -extern int old_center (WINDOW *win, int y, chtype attr, - const char *restrict format, ...) - __attribute__((format (printf, 4, 5))); - - -/* - Function: old_center2 - Centre two strings in a given window - Parameters: win - Window to use (should be curwin) - y - Line on which to centre the strings - attr1 - Character rendition to use for initial string - attr2 - Character rendition to use for main string - initial - Initial string (no printf() formatting) - format - printf()-like format string for main string - ... - printf()-like arguments - Returns: int - Return code from wprintw(): OK or ERR - - This function prints two strings side-by-side on line y in the centre - of window win. The first (initial) string is printed with character - rendition (attributes) attr1 using waddstr(). The second (main) string - uses wprintw(format, ...) with rendition attr2. If the main string is - too long to fit in the window alongside the initial string, the main - string is truncated to fit. Please note that wrefresh() is NOT called. - - As with center(), the current implementation does NOT handle multibyte - strings correctly. -*/ -extern int old_center2 (WINDOW *win, int y, chtype attr1, chtype attr2, - const char *initial, const char *restrict format, ...) - __attribute__((format (printf, 6, 7))); - - -/* - Function: old_center3 - Centre three strings in a given window - Parameters: win - Window to use (should be curwin) - y - Line on which to centre the strings - attr1 - Character rendition to use for initial string - attr3 - Character rendition to use for final string - attr2 - Character rendition to use for main string - initial - Initial string (no printf() formatting) - final - Final string (no printf() formatting) - format - printf()-like format string for main string - ... - printf()-like arguments - Returns: int - Return code from wprintw(): OK or ERR - - This function prints three strings side-by-side on line y in the centre - of window win. The first (initial) string is printed with character - rendition (attributes) attr1 using waddstr(). The second (main) string - uses wprintw(format, ...) with rendition attr2. The third (final) - string is then printed with rendition attr3 using waddstr(). If the - strings are too long to fit the window width, the main (centre) string - is truncated. Please note that wrefresh() is NOT called. Also note - the order of rendition values: 1, 3, 2, NOT 1, 2, 3! - - As with center(), the current implementation does NOT handle multibyte - strings correctly. -*/ - -extern int old_center3 (WINDOW *win, int y, chtype attr1, chtype attr3, - chtype attr2, const char *initial, const char *final, - const char *restrict format, ...) - __attribute__((format (printf, 8, 9))); - - /* Function: gettxchar - Read a character from the keyboard Parameters: win - Window to use (should be curwin) From d20cc2b5ec5f0c2927ce411ba0e5b3cecf886947 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Tue, 16 Aug 2011 20:45:47 +1000 Subject: [PATCH 042/112] Use chstr-style output functions in gettxline() --- src/intf.c | 41 ++++++++++++++++++----------------------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/src/intf.c b/src/intf.c index 96bd95b..0b374fd 100644 --- a/src/intf.c +++ b/src/intf.c @@ -1484,9 +1484,12 @@ int gettxline (WINDOW *win, char *buf, int bufsize, bool *restrict modified, const char *allowed, bool stripspc, int y, int x, int width, chtype attr) { - int len, pos, cpos, nb, ret; + int len, pos, cpos, ret; bool done, redraw, mod; int key, key2; + chtype oldattr; + chtype *chbuf; + int chbufwidth; assert(win != NULL); @@ -1494,17 +1497,13 @@ int gettxline (WINDOW *win, char *buf, int bufsize, bool *restrict modified, assert(bufsize > 2); assert(width > 1); + chbuf = xmalloc(BUFSIZE * sizeof(chtype)); + keypad(win, true); meta(win, true); wtimeout(win, -1); - chtype oldattr = getattrs(win); - chtype oldbkgd = getbkgd(win); - - /* Note that wattrset() will override parts of wbkgdset() and vice - versa: don't swap the order of these two lines! */ - wbkgdset(win, (oldbkgd & A_COLOR) | A_NORMAL); - wattrset(win, attr & ~A_CHARTEXT); + oldattr = getattrs(win); curs_set(CURS_ON); len = strlen(buf); @@ -1522,16 +1521,11 @@ int gettxline (WINDOW *win, char *buf, int bufsize, bool *restrict modified, Blanks at the end of the input area are replaced with "attr", which may contain a '_' for non-colour mode. */ - mvwprintw(win, y, x, "%-*.*s", width, width, buf + pos - cpos); - - // nb = number of blanks - nb = (len - (pos - cpos) > width) ? 0 : width - (len - (pos - cpos)); - wmove(win, y, x + width - nb); - - chtype ch = ((attr & A_CHARTEXT) == 0) ? attr | ' ' : attr; - for (int i = 0; i < nb; i++) { - waddch(win, ch); - } + mvwhline(win, y, x, ((attr & A_CHARTEXT) == 0) ? + ' ' | attr : attr, width); + mkchstr(chbuf, BUFSIZE, attr & ~A_CHARTEXT, 0, 0, 1, width, + &chbufwidth, 1, "%s", buf + pos - cpos); + leftch(win, y, x, chbuf, 1, &chbufwidth); wmove(win, y, x + cpos); wrefresh(win); @@ -2107,16 +2101,17 @@ int gettxline (WINDOW *win, char *buf, int bufsize, bool *restrict modified, curs_set(CURS_OFF); - wattrset(win, oldattr | A_BOLD); - mvwprintw(win, y, x, "%-*.*s", width, width, buf); - - wbkgdset(win, oldbkgd); - wattrset(win, oldattr); + mvwhline(win, y, x, ' ' | oldattr, width); + mkchstr(chbuf, BUFSIZE, oldattr | A_BOLD, 0, 0, 1, width, + &chbufwidth, 1, "%s", buf); + leftch(win, y, x, chbuf, 1, &chbufwidth); wrefresh(win); if (modified != NULL) { *modified = mod; } + + free(chbuf); return ret; } From bf76fa312c71a79a8ca9fd6a89ad6fe3a71cc677 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Tue, 16 Aug 2011 20:55:42 +1000 Subject: [PATCH 043/112] Assume MOD_POSIX_CURRENCY_SYMBOL contains only ASCII characters The GNU library now has "C.UTF-8" as a locale (which is NOT a single-byte locale!), but we assume the currency symbol in MOD_POSIX_CURRENCY_SYMBOL contains only ASCII characters. --- src/utils.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/utils.c b/src/utils.c index d106c72..20c2e2c 100644 --- a/src/utils.c +++ b/src/utils.c @@ -345,9 +345,9 @@ ssize_t l_strfmon (char *restrict s, size_t maxsize, if (strstr(format, "!") == NULL) { /* Insert lconvinfo.currency_symbol to s. - NB: add_currecy_symbol == true assumes POSIX locale: - single-byte strings are in effect, so strlen(), etc, work - correctly. */ + NB: add_currecy_symbol == true assumes a POSIX locale and + that MOD_POSIX_CURRENCY_SYMBOL contains only ASCII-safe + characters that work with strlen(), etc. */ const char *sym = lconvinfo.currency_symbol; int symlen = strlen(sym); char *p; From 6c1c272780de8a643e14415e85a4eb773a8fdbe4 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Tue, 16 Aug 2011 21:03:41 +1000 Subject: [PATCH 044/112] Place all output strings within gettext invocations --- src/exch.c | 125 ++++++++++++++--------------- src/fileio.c | 23 +++--- src/game.c | 138 ++++++++++++++++---------------- src/help.c | 216 ++++++++++++++++++++++++++------------------------- src/intf.c | 4 +- src/move.c | 104 +++++++++++++------------ 6 files changed, 312 insertions(+), 298 deletions(-) diff --git a/src/exch.c b/src/exch.c index 24b5096..f6a50d3 100644 --- a/src/exch.c +++ b/src/exch.c @@ -95,9 +95,9 @@ void exchange_stock (void) box(curwin, 0, 0); center(curwin, 1, 0, attr_title, 0, 0, 1, - " Interstellar Stock Exchange "); + _(" Interstellar Stock Exchange ")); center(curwin, 2, 0, attr_normal, attr_highlight, 0, 1, - "Player: ^{%s^}", player[current_player].name); + _("Player: ^{%s^}"), player[current_player].name); all_off_map = true; for (i = 0; i < MAX_COMPANIES; i++) { @@ -109,20 +109,20 @@ void exchange_stock (void) if (all_off_map) { center(curwin, 8, 0, attr_normal, attr_highlight, 0, 1, - "No companies on the map"); + _("No companies on the map")); } else { mvwhline(curwin, 4, 2, ' ' | attr_subtitle, w - 4); mvwhline(curwin, 5, 2, ' ' | attr_subtitle, w - 4); - left(curwin, 4, 4, attr_subtitle, 0, 0, 2, "\nCompany"); - right(curwin, 4, w - 4, attr_subtitle, 0, 0, 2, "Shares\nleft"); + left(curwin, 4, 4, attr_subtitle, 0, 0, 2, _("\nCompany")); + right(curwin, 4, w - 4, attr_subtitle, 0, 0, 2, _("Shares\nleft")); right(curwin, 4, w - 6 - STOCK_LEFT_COLS, attr_subtitle, 0, 0, - 2, "Shares\nissued"); + 2, _("Shares\nissued")); right(curwin, 4, w - 8 - STOCK_LEFT_COLS - STOCK_ISSUED_COLS, - attr_subtitle, 0, 0, 2, "Return\n(%%)"); + attr_subtitle, 0, 0, 2, _("Return\n(%%)")); right(curwin, 4, w - 10 - STOCK_LEFT_COLS - STOCK_ISSUED_COLS - SHARE_RETURN_COLS, attr_subtitle, 0, 0, 2, - "Price per\nshare (%s)", lconvinfo.currency_symbol); + _("Price per\nshare (%s)"), lconvinfo.currency_symbol); for (line = 6, i = 0; i < MAX_COMPANIES; i++) { if (company[i].on_map) { @@ -154,16 +154,16 @@ void exchange_stock (void) newtxwin(6, WIN_COLS, 18, WCENTER, true, attr_normal_window); left(curwin, 3, 2, attr_normal, attr_keycode, 0, 1, - "^{<1>^} Display stock portfolio"); + _("^{<1>^} Display stock portfolio")); left(curwin, 4, 2, attr_normal, attr_keycode, 0, 1, - "^{<2>^} Display galaxy map"); + _("^{<2>^} Display galaxy map")); left(curwin, 3, getmaxx(curwin) / 2, attr_normal, attr_keycode, 0, 1, - "^{<3>^} Visit the Trading Bank"); + _("^{<3>^} Visit the Trading Bank")); left(curwin, 4, getmaxx(curwin) / 2, attr_normal, attr_keycode, 0, 1, - "^{<4>^} Exit the Stock Exchange"); + _("^{<4>^} Exit the Stock Exchange")); center(curwin, 1, -1, attr_normal, attr_keycode, attr_highlight, 1, - "Enter selection [^[Company letter^]/^{1^}-^{4^}]: "); + _("Enter selection [^[Company letter^]/^{1^}-^{4^}]: ")); curs_set(CURS_ON); wrefresh(curwin); @@ -263,25 +263,26 @@ void visit_bank (void) // Show the informational part of the Bank newtxwin(10, WIN_COLS - 4, 5, WCENTER, true, attr_normal_window); - center(curwin, 1, 0, attr_title, 0, 0, 1, " Interstellar Trading Bank "); + center(curwin, 1, 0, attr_title, 0, 0, 1, + _(" Interstellar Trading Bank ")); mkchstr(chbuf, BUFSIZE, attr_normal, 0, 0, 1, getmaxx(curwin) - 4, &width, - 1, "Current cash: "); + 1, _("Current cash: ")); x = (getmaxx(curwin) + width - (BANK_VALUE_COLS + 2)) / 2; rightch(curwin, 3, x, chbuf, 1, &width); right(curwin, 3, x + BANK_VALUE_COLS + 2, attr_normal, attr_highlight, 0, 1, " ^{%N^} ", player[current_player].cash); - right(curwin, 4, x, attr_normal, 0, 0, 1, "Current debt: "); + right(curwin, 4, x, attr_normal, 0, 0, 1, _("Current debt: ")); right(curwin, 4, x + BANK_VALUE_COLS + 2, attr_normal, attr_highlight, 0, 1, " ^{%N^} ", player[current_player].debt); - right(curwin, 5, x, attr_normal, 0, 0, 1, "Interest rate: "); + right(curwin, 5, x, attr_normal, 0, 0, 1, _("Interest rate: ")); right(curwin, 5, x + BANK_VALUE_COLS + 2, attr_normal, attr_highlight, 0, 1, " ^{%.2f%%^} ", interest_rate * 100.0); - right(curwin, 7, x, attr_highlight, 0, 0, 1, "Credit limit: "); + right(curwin, 7, x, attr_highlight, 0, 0, 1, _("Credit limit: ")); whline(curwin, ' ' | attr_title, BANK_VALUE_COLS + 2); right(curwin, 7, x + BANK_VALUE_COLS + 2, attr_title, 0, 0, 1, " %N ", credit_limit); @@ -292,14 +293,14 @@ void visit_bank (void) newtxwin(7, WIN_COLS - 4, 15, WCENTER, true, attr_normal_window); center(curwin, 3, 0, attr_normal, attr_keycode, 0, 1, - "^{<1>^} Borrow money "); + _("^{<1>^} Borrow money ")); center(curwin, 4, 0, attr_normal, attr_keycode, 0, 1, - "^{<2>^} Repay debt "); + _("^{<2>^} Repay debt ")); center(curwin, 5, 0, attr_normal, attr_keycode, 0, 1, - "^{<3>^} Exit from the Bank"); + _("^{<3>^} Exit from the Bank")); center(curwin, 1, 0, attr_normal, attr_keycode, 0, 1, - "Enter selection [^{1^}-^{3^}]: "); + _("Enter selection [^{1^}-^{3^}]: ")); curs_set(CURS_ON); wrefresh(curwin); @@ -338,8 +339,8 @@ void visit_bank (void) if (credit_limit == 0.0) { txdlgbox(MAX_DLG_LINES, 50, 8, WCENTER, attr_error_window, attr_error_title, attr_error_highlight, 0, 0, - attr_error_waitforkey, " Insufficient Credit Limit ", - "The Bank will not lend you any more money."); + attr_error_waitforkey, _(" Insufficient Credit Limit "), + _("The Bank will not lend you any more money.")); } else { chtype *chbuf_cursym; int width_cursym; @@ -359,7 +360,7 @@ void visit_bank (void) mkchstr(chbuf, BUFSIZE, attr_normal, 0, 0, 1, getmaxx(curwin) - BANK_INPUT_COLS - width_cursym - 6, &width, 1, - "How much do you wish to borrow? "); + _("How much do you wish to borrow? ")); x = (getmaxx(curwin) + width - BANK_INPUT_COLS - width_cursym - n) / 2; rightch(curwin, 3, x, chbuf, 1, &width); @@ -391,13 +392,13 @@ void visit_bank (void) if (player[current_player].debt == 0.0) { txdlgbox(MAX_DLG_LINES, 50, 8, WCENTER, attr_error_window, attr_error_title, attr_error_highlight, 0, 0, - attr_error_waitforkey, " No Debt ", - "You have no debt to repay."); + attr_error_waitforkey, _(" No Debt "), + _("You have no debt to repay.")); } else if (player[current_player].cash == 0.0) { txdlgbox(MAX_DLG_LINES, 50, 8, WCENTER, attr_error_window, attr_error_title, attr_error_highlight, 0, 0, - attr_error_waitforkey, " No Cash ", - "You have no cash with which to repay the debt!"); + attr_error_waitforkey, _(" No Cash "), + _("You have no cash with which to repay the debt!")); } else { chtype *chbuf_cursym; int width_cursym; @@ -417,7 +418,7 @@ void visit_bank (void) mkchstr(chbuf, BUFSIZE, attr_normal, 0, 0, 1, getmaxx(curwin) - BANK_INPUT_COLS - width_cursym - 6, &width, 1, - "How much do you wish to repay? "); + _("How much do you wish to repay? ")); x = (getmaxx(curwin) + width - BANK_INPUT_COLS - width_cursym - n) / 2; rightch(curwin, 3, x, chbuf, 1, &width); @@ -490,36 +491,36 @@ void trade_shares (int num, bool *bid_used) newtxwin(9, WIN_COLS - 4, 5, WCENTER, true, attr_normal_window); w = getmaxx(curwin); - center(curwin, 1, 0, attr_title, 0, 0, 1, " Stock Transaction in %s ", + center(curwin, 1, 0, attr_title, 0, 0, 1, _(" Stock Transaction in %s "), company[num].name); mkchstr(chbuf, BUFSIZE, attr_normal, 0, 0, 1, w / 2, &width, 1, - "Shares issued: "); + _("Shares issued: ")); leftch(curwin, 3, 2, chbuf, 1, &width); right(curwin, 3, width + SHARE_PRICE_COLS + 2, attr_normal, attr_highlight, 0, 1, "^{%'ld^}", company[num].stock_issued); - left(curwin, 4, 2, attr_normal, 0, 0, 1, "Shares left: "); + left(curwin, 4, 2, attr_normal, 0, 0, 1, _("Shares left: ")); right(curwin, 4, width + SHARE_PRICE_COLS + 2, attr_normal, attr_highlight, 0, 1, "^{%'ld^}", company[num].max_stock - company[num].stock_issued); - left(curwin, 5, 2, attr_normal, 0, 0, 1, "Price per share: "); + left(curwin, 5, 2, attr_normal, 0, 0, 1, _("Price per share: ")); right(curwin, 5, width + SHARE_PRICE_COLS + 2, attr_normal, attr_highlight, 0, 1, "^{%N^}", company[num].share_price); - left(curwin, 6, 2, attr_normal, 0, 0, 1, "Return: "); + left(curwin, 6, 2, attr_normal, 0, 0, 1, _("Return: ")); right(curwin, 6, width + SHARE_PRICE_COLS + 2, attr_normal, attr_highlight, 0, 1, "^{%.2f%%^}", company[num].share_return * 100.0); - left(curwin, 3, w / 2, attr_normal, 0, 0, 1, "Current holdings: "); + left(curwin, 3, w / 2, attr_normal, 0, 0, 1, _("Current holdings: ")); right(curwin, 3, w - 2, attr_normal, attr_highlight, 0, 1, " ^{%'ld^} ", player[current_player].stock_owned[num]); - left(curwin, 4, w / 2, attr_normal, 0, 0, 1, "Percentage owned: "); + left(curwin, 4, w / 2, attr_normal, 0, 0, 1, _("Percentage owned: ")); right(curwin, 4, w - 2, attr_normal, attr_highlight, 0, 1, " ^{%.2f%%^} ", ownership * 100.0); - left(curwin, 6, w / 2, attr_highlight, 0, 0, 1, "Current cash: "); + left(curwin, 6, w / 2, attr_highlight, 0, 0, 1, _("Current cash: ")); whline(curwin, ' ' | attr_title, TRADE_VALUE_COLS + 2); right(curwin, 6, w - 2, attr_title, 0, 0, 1, " %N ", player[current_player].cash); @@ -530,16 +531,16 @@ void trade_shares (int num, bool *bid_used) newtxwin(7, WIN_COLS - 4, 14, WCENTER, true, attr_normal_window); left(curwin, 3, 2, attr_normal, attr_keycode, 0, 1, - "^{<1>^} Buy stock from company"); + _("^{<1>^} Buy stock from company")); left(curwin, 4, 2, attr_normal, attr_keycode, 0, 1, - "^{<2>^} Sell stock back to company"); + _("^{<2>^} Sell stock back to company")); left(curwin, 3, getmaxx(curwin) / 2, attr_normal, attr_keycode, 0, 1, - "^{<3>^} Bid company to issue more shares"); + _("^{<3>^} Bid company to issue more shares")); left(curwin, 4, getmaxx(curwin) / 2, attr_normal, attr_keycode, 0, 1, - "^{<4>^} Exit to the Stock Exchange"); + _("^{<4>^} Exit to the Stock Exchange")); center(curwin, 1, 0, attr_normal, attr_keycode, 0, 1, - "Enter selection [^{1^}-^{4^}]: "); + _("Enter selection [^{1^}-^{4^}]: ")); curs_set(CURS_ON); wrefresh(curwin); @@ -581,14 +582,14 @@ void trade_shares (int num, bool *bid_used) if (company[num].max_stock - company[num].stock_issued == 0) { txdlgbox(MAX_DLG_LINES, 50, 8, WCENTER, attr_error_window, attr_error_title, attr_error_highlight, 0, 0, - attr_error_waitforkey, " No Shares Available ", - "No more shares are available for purchase."); + attr_error_waitforkey, _(" No Shares Available "), + _("No more shares are available for purchase.")); } else if (maxshares <= 0) { txdlgbox(MAX_DLG_LINES, 50, 8, WCENTER, attr_error_window, attr_error_title, attr_error_highlight, 0, 0, - attr_error_waitforkey, " Insufficient Cash ", - "You do not have enough cash\n" - "to purchase additional shares."); + attr_error_waitforkey, _(" Insufficient Cash "), + _("You do not have enough cash\n" + "to purchase additional shares.")); } else { maxshares = MIN(maxshares, company[num].max_stock - company[num].stock_issued); @@ -598,11 +599,11 @@ void trade_shares (int num, bool *bid_used) box(curwin, 0, 0); center(curwin, 2, 0, attr_normal, attr_highlight, 0, 1, - "You can purchase up to ^{%'ld^} shares.", maxshares); + _("You can purchase up to ^{%'ld^} shares."), maxshares); - mkchstr(chbuf, BUFSIZE, attr_normal, 0, 0, 1, getmaxx(curwin) - - TRADE_INPUT_COLS - 4, &width, 1, - "How many shares do you wish to purchase? "); + mkchstr(chbuf, BUFSIZE, attr_normal, 0, 0, 1, + getmaxx(curwin) - TRADE_INPUT_COLS - 4, &width, 1, + _("How many shares do you wish to purchase? ")); x = (getmaxx(curwin) + width - TRADE_INPUT_COLS) / 2; rightch(curwin, 4, x, chbuf, 1, &width); @@ -623,19 +624,19 @@ void trade_shares (int num, bool *bid_used) if (maxshares == 0) { txdlgbox(MAX_DLG_LINES, 50, 8, WCENTER, attr_error_window, attr_error_title, attr_error_highlight, 0, 0, - attr_error_waitforkey, " No Shares ", - "You do not have any shares to sell."); + attr_error_waitforkey, _(" No Shares "), + _("You do not have any shares to sell.")); } else { wbkgdset(curwin, attr_normal_window); werase(curwin); box(curwin, 0, 0); center(curwin, 2, 0, attr_normal, attr_highlight, 0, 1, - "You can sell up to ^{%'ld^} shares.", maxshares); + _("You can sell up to ^{%'ld^} shares."), maxshares); - mkchstr(chbuf, BUFSIZE, attr_normal, 0, 0, 1, getmaxx(curwin) - - TRADE_INPUT_COLS - 4, &width, 1, - "How many shares do you wish to sell? "); + mkchstr(chbuf, BUFSIZE, attr_normal, 0, 0, 1, + getmaxx(curwin) - TRADE_INPUT_COLS - 4, &width, 1, + _("How many shares do you wish to sell? ")); x = (getmaxx(curwin) + width - TRADE_INPUT_COLS) / 2; rightch(curwin, 4, x, chbuf, 1, &width); @@ -663,14 +664,14 @@ void trade_shares (int num, bool *bid_used) if (maxshares == 0) { txdlgbox(MAX_DLG_LINES, 50, 8, WCENTER, attr_error_window, attr_error_title, attr_error_highlight, 0, 0, - attr_error_waitforkey, " No Shares Issued ", - "%s has refused\nto issue more shares.", + attr_error_waitforkey, _(" No Shares Issued "), + _("%s has refused\nto issue more shares."), company[num].name); } else { txdlgbox(MAX_DLG_LINES, 50, 8, WCENTER, attr_normal_window, attr_title, attr_normal, attr_highlight, 0, - attr_waitforkey, " Shares Issued ", - "%s has issued\n^{%'ld^} more shares.", + attr_waitforkey, _(" Shares Issued "), + _("%s has issued\n^{%'ld^} more shares."), company[num].name, maxshares); } break; diff --git a/src/fileio.c b/src/fileio.c index 297a4ee..60dfe04 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -231,17 +231,18 @@ bool load_game (int num) // File not found txdlgbox(MAX_DLG_LINES, 50, 9, WCENTER, attr_error_window, attr_error_title, attr_error_highlight, 0, 0, - attr_error_waitforkey, " Game Not Found ", - "Game %d has not been saved to disk.", num); + attr_error_waitforkey, _(" Game Not Found "), + _("Game %d has not been saved to disk."), num); } else { // Some other file error saved_errno = errno; txdlgbox(MAX_DLG_LINES, 60, 9, WCENTER, attr_error_window, attr_error_title, attr_error_highlight, attr_error_normal, 0, attr_error_waitforkey, - " Game Not Loaded ", - "Game %d could not be loaded from disk.\n\n" - "^{File %s: %s^}", num, filename, strerror(saved_errno)); + _(" Game Not Loaded "), + _("Game %d could not be loaded from disk.\n\n" + "^{File %s: %s^}"), num, filename, + strerror(saved_errno)); } free(buf); @@ -430,9 +431,9 @@ bool save_game (int num) txdlgbox(MAX_DLG_LINES, 60, 7, WCENTER, attr_error_window, attr_error_title, attr_error_highlight, attr_error_normal, 0, attr_error_waitforkey, - " Game Not Saved ", - "Game %d could not be saved to disk.\n\n" - "^{Directory %s: %s^}", num, data_dir, + _(" Game Not Saved "), + _("Game %d could not be saved to disk.\n\n" + "^{Directory %s: %s^}"), num, data_dir, strerror(saved_errno)); free(buf); @@ -451,9 +452,9 @@ bool save_game (int num) txdlgbox(MAX_DLG_LINES, 60, 7, WCENTER, attr_error_window, attr_error_title, attr_error_highlight, attr_error_normal, 0, attr_error_waitforkey, - " Game Not Saved ", - "Game %d could not be saved to disk.\n\n" - "^{File %s: %s^}", num, filename, strerror(saved_errno)); + _(" Game Not Saved "), + _("Game %d could not be saved to disk.\n\n" + "^{File %s: %s^}"), num, filename, strerror(saved_errno)); free(buf); free(filename); diff --git a/src/game.c b/src/game.c index 43500b0..4d3099a 100644 --- a/src/game.c +++ b/src/game.c @@ -114,7 +114,7 @@ void init_game (void) int width; mkchstr(chbuf, BUFSIZE, attr_status_window, 0, 0, 1, WIN_COLS - 7, - &width, 1, "Loading game %d... ", game_num); + &width, 1, _("Loading game %d... "), game_num); newtxwin(5, width + 5, 6, WCENTER, true, attr_status_window); centerch(curwin, 2, 0, chbuf, 1, &width); wrefresh(curwin); @@ -149,7 +149,7 @@ void init_game (void) mkchstr(chbuf, BUFSIZE, attr_status_window, 0, 0, 1, WIN_COLS - 7, &width, 1, - "Loading game %d... ", game_num); + _("Loading game %d... "), game_num); newtxwin(5, width + 5, 9, WCENTER, true, attr_status_window); centerch(curwin, 2, 0, chbuf, 1, &width); wrefresh(curwin); @@ -171,26 +171,24 @@ void init_game (void) } if (! game_loaded) { - int i, j, x, y; - ask_player_names(); deltxwin(); // "Number of players" window txrefresh(); // Initialise player data (other than names) - for (i = 0; i < number_players; i++) { + for (int i = 0; i < number_players; i++) { player[i].cash = INITIAL_CASH; player[i].debt = 0.0; player[i].in_game = true; - for (j = 0; j < MAX_COMPANIES; j++) { + for (int j = 0; j < MAX_COMPANIES; j++) { player[i].stock_owned[j] = 0; } } // Initialise company data - for (i = 0; i < MAX_COMPANIES; i++) { + for (int i = 0; i < MAX_COMPANIES; i++) { company[i].name = xstrdup(gettext(company_name[i])); company[i].share_price = 0.0; company[i].share_return = INITIAL_RETURN; @@ -200,8 +198,8 @@ void init_game (void) } // Initialise galaxy map - for (x = 0; x < MAX_X; x++) { - for (y = 0; y < MAX_Y; y++) { + for (int x = 0; x < MAX_X; x++) { + for (int y = 0; y < MAX_Y; y++) { galaxy_map[x][y] = (randf() < STAR_RATIO) ? MAP_STAR : MAP_EMPTY; } @@ -222,8 +220,8 @@ void init_game (void) txdlgbox(MAX_DLG_LINES, 50, 8, WCENTER, attr_normal_window, attr_title, attr_normal, attr_highlight, 0, - attr_waitforkey, " First Player ", - "The first player to go is ^{%s^}.", + attr_waitforkey, _(" First Player "), + _("The first player to go is ^{%s^}."), player[first_player].name); txrefresh(); } @@ -248,11 +246,12 @@ static int ask_number_players (void) chbuf = xmalloc(BUFSIZE * sizeof(chtype)); - lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_keycode, 0, 2, WIN_COLS - - 7, widthbuf, 2, "Enter number of players [^{1^}-^{%d^}] " - "or ^{^} to continue a game: ", MAX_PLAYERS); + lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_keycode, 0, 2, + WIN_COLS - 7, widthbuf, 2, + _("Enter number of players [^{1^}-^{%d^}] " + "or ^{^} to continue a game: "), MAX_PLAYERS); assert(lines == 1 || lines == 2); - maxwidth = ((lines == 1) ? widthbuf[0] : MAX(widthbuf[0], widthbuf[1])) + 5; + maxwidth = (lines == 1 ? widthbuf[0] : MAX(widthbuf[0], widthbuf[1])) + 5; newtxwin(lines + 4, maxwidth, 3, WCENTER, true, attr_normal_window); leftch(curwin, 2, 2, chbuf, lines, widthbuf); @@ -311,11 +310,12 @@ int ask_game_number (void) chbuf = xmalloc(BUFSIZE * sizeof(chtype)); - lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_keycode, 0, 2, WIN_COLS - - 7, widthbuf, 2, "Enter game number [^{1^}-^{9^}] " - "or ^{^} to cancel: "); + lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_keycode, 0, 2, + WIN_COLS - 7, widthbuf, 2, + _("Enter game number [^{1^}-^{9^}] " + "or ^{^} to cancel: ")); assert(lines == 1 || lines == 2); - maxwidth = ((lines == 1) ? widthbuf[0] : MAX(widthbuf[0], widthbuf[1])) + 5; + maxwidth = (lines == 1 ? widthbuf[0] : MAX(widthbuf[0], widthbuf[1])) + 5; newtxwin(lines + 4, maxwidth, 6, WCENTER, true, attr_normal_window); leftch(curwin, 2, 2, chbuf, lines, widthbuf); @@ -368,7 +368,7 @@ void ask_player_names (void) // Ask for the player's name newtxwin(5, WIN_COLS - 4, 9, WCENTER, true, attr_normal_window); - left(curwin, 2, 2, attr_normal, 0, 0, 1, "Please enter your name: "); + left(curwin, 2, 2, attr_normal, 0, 0, 1, _("Please enter your name: ")); int x = getcurx(curwin); int w = getmaxx(curwin) - x - 2; @@ -386,7 +386,7 @@ void ask_player_names (void) mkchstr(chbuf, BUFSIZE, attr_normal, attr_keycode, 0, 1, WIN_COLS - YESNO_COLS - 6, &width, 1, - "Do you need any instructions? [^{Y^}/^{N^}] "); + _("Do you need any instructions? [^{Y^}/^{N^}] ")); newtxwin(5, width + YESNO_COLS + 4, 6, WCENTER, true, attr_normal_window); leftch(curwin, 2, 2, chbuf, 1, &width); @@ -404,12 +404,13 @@ void ask_player_names (void) newtxwin(number_players + 5, WIN_COLS - 4, 9, WCENTER, true, attr_normal_window); - center(curwin, 1, 0, attr_title, 0, 0, 1, " Enter Player Names "); + center(curwin, 1, 0, attr_title, 0, 0, 1, _(" Enter Player Names ")); for (i = 0; i < number_players; i++) { player[i].name = NULL; entered[i] = false; - left(curwin, i + 3, 2, attr_normal, 0, 0, 1, "Player %d:", i + 1); + left(curwin, i + 3, 2, attr_normal, 0, 0, 1, + _("Player %d:"), i + 1); } int x = getcurx(curwin) + 1; @@ -487,7 +488,7 @@ void ask_player_names (void) mkchstr(chbuf, BUFSIZE, attr_normal, attr_keycode, 0, 1, WIN_COLS - YESNO_COLS - 6, &width, 1, - "Does any player need instructions? [^{Y^}/^{N^}] "); + _("Does any player need instructions? [^{Y^}/^{N^}] ")); newtxwin(5, width + YESNO_COLS + 4, 6, WCENTER, true, attr_normal_window); leftch(curwin, 2, 2, chbuf, 1, &width); @@ -509,8 +510,7 @@ void ask_player_names (void) void end_game (void) { chtype *chbuf; - int lines; - int widthbuf[5]; + int lines, widthbuf[5]; if (abort_game) { @@ -522,8 +522,8 @@ void end_game (void) txdlgbox(MAX_DLG_LINES, 50, 9, WCENTER, attr_error_window, attr_error_title, attr_error_highlight, 0, 0, - attr_error_waitforkey, " Game Over ", - "The game is over after %d turns.", turn_number - 1); + attr_error_waitforkey, _(" Game Over "), + _("The game is over after %d turns."), turn_number - 1); for (int i = 0; i < number_players; i++) { show_status(i); @@ -532,7 +532,7 @@ void end_game (void) if (number_players == 1) { txdlgbox(MAX_DLG_LINES, 60, 8, WCENTER, attr_normal_window, attr_title, attr_normal, attr_highlight, 0, attr_waitforkey, - " Total Value ", "Your total value was ^{%N^}.", + _(" Total Value "), _("Your total value was ^{%N^}."), total_value(0)); } else { // Sort players on the basis of total value @@ -541,33 +541,35 @@ void end_game (void) } qsort(player, number_players, sizeof(player_info_t), cmp_player); - lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_highlight, attr_blink, - 5, WIN_COLS - 8, widthbuf, 5, (player[0].sort_value == 0) ? - "The winner is ^{%s^}\n" - "who is ^[*** BANKRUPT ***^]" : - "The winner is ^{%s^}\n" - "with a value of ^{%N^}.", player[0].name, - player[0].sort_value); + lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_highlight, + attr_blink, 5, WIN_COLS - 8, widthbuf, 5, + (player[0].sort_value == 0) ? + _("The winner is ^{%s^}\n" + "who is ^[*** BANKRUPT ***^]") : + _("The winner is ^{%s^}\n" + "with a value of ^{%N^}."), + player[0].name, player[0].sort_value); newtxwin(number_players + lines + 8, WIN_COLS - 4, 3, WCENTER, true, attr_normal_window); - center(curwin, 1, 0, attr_title, 0, 0, 1, " Game Winner "); + center(curwin, 1, 0, attr_title, 0, 0, 1, _(" Game Winner ")); centerch(curwin, 3, 0, chbuf, lines, widthbuf); - mvwhline(curwin, lines + 4, 2, ' ' | attr_subtitle, - getmaxx(curwin) - 4); + int w = getmaxx(curwin); + + mvwhline(curwin, lines + 4, 2, ' ' | attr_subtitle, w - 4); left(curwin, lines + 4, ORDINAL_COLS + 4, attr_subtitle, 0, 0, 1, - "Player"); - right(curwin, lines + 4, getmaxx(curwin) - 4, attr_subtitle, 0, 0, 1, - "Total Value (%s)", lconvinfo.currency_symbol); + _("Player")); + right(curwin, lines + 4, w - 4, attr_subtitle, 0, 0, 1, + _("Total Value (%s)"), lconvinfo.currency_symbol); for (int i = 0; i < number_players; i++) { right(curwin, i + lines + 5, ORDINAL_COLS + 2, attr_normal, 0, 0, 1, gettext(ordinal[i + 1])); left(curwin, i + lines + 5, ORDINAL_COLS + 4, attr_normal, 0, 0, 1, "%s", player[i].name); - right(curwin, i + lines + 5, getmaxx(curwin) - 2, attr_normal, 0, - 0, 1, " %!N ", player[i].sort_value); + right(curwin, i + lines + 5, w - 2, attr_normal, 0, 0, + 1, " %!N ", player[i].sort_value); } wait_for_key(curwin, getmaxy(curwin) - 2, attr_waitforkey); @@ -583,9 +585,6 @@ void end_game (void) void show_map (bool closewin) { - int x, y; - - newtxwin(MAX_Y + 4, WIN_COLS, 1, WCENTER, true, attr_map_window); // Draw various borders and highlights @@ -596,16 +595,16 @@ void show_map (bool closewin) // Display current player and turn number left(curwin, 1, 2, attr_mapwin_title, attr_mapwin_highlight, 0, 1, - " Player: ^{%s^} ", player[current_player].name); + _(" Player: ^{%s^} "), player[current_player].name); right(curwin, 1, getmaxx(curwin) - 2, attr_mapwin_title, attr_mapwin_highlight, attr_mapwin_blink, 1, - (turn_number != max_turn) ? " Turn: ^{%d^} " : - " ^[*** Last Turn ***^] ", turn_number); + (turn_number != max_turn) ? _(" Turn: ^{%d^} ") : + _(" ^[*** Last Turn ***^] "), turn_number); // Display the actual map - for (y = 0; y < MAX_Y; y++) { + for (int y = 0; y < MAX_Y; y++) { wmove(curwin, y + 3, 2); - for (x = 0; x < MAX_X; x++) { + for (int x = 0; x < MAX_X; x++) { map_val_t m = galaxy_map[x][y]; switch (m) { @@ -659,14 +658,14 @@ void show_status (int num) newtxwin(MAX_COMPANIES + 15, WIN_COLS, 1, WCENTER, true, attr_normal_window); - center(curwin, 1, 0, attr_title, 0, 0, 1, " Stock Portfolio "); - center(curwin, 2, 0, attr_normal, attr_highlight, 0, 1, "Player: ^{%s^}", - player[num].name); + center(curwin, 1, 0, attr_title, 0, 0, 1, _(" Stock Portfolio ")); + center(curwin, 2, 0, attr_normal, attr_highlight, 0, 1, + _("Player: ^{%s^}"), player[num].name); val = total_value(num); if (val == 0.0) { center(curwin, 11, 0, attr_normal, attr_highlight, attr_blink, 1, - "^[* * * B A N K R U P T * * *^]"); + _("^[* * * B A N K R U P T * * *^]")); } else { w = getmaxx(curwin); @@ -681,20 +680,22 @@ void show_status (int num) if (none) { center(curwin, 8, 0, attr_normal, attr_highlight, 0, 1, - "No companies on the map"); + _("No companies on the map")); } else { mvwhline(curwin, 4, 2, ' ' | attr_subtitle, w - 4); mvwhline(curwin, 5, 2, ' ' | attr_subtitle, w - 4); - left(curwin, 4, 4, attr_subtitle, 0, 0, 2, "\nCompany"); - right(curwin, 4, w - 4, attr_subtitle, 0, 0, 2, "Ownership\n(%%)"); - right(curwin, 4, w - 6 - OWNERSHIP_COLS, attr_subtitle, 0, 0, - 2, "Holdings\n(shares)"); + left(curwin, 4, 4, attr_subtitle, 0, 0, 2, + _("\nCompany")); + right(curwin, 4, w - 4, attr_subtitle, 0, 0, 2, + _("Ownership\n(%%)")); + right(curwin, 4, w - 6 - OWNERSHIP_COLS, attr_subtitle, 0, 0, 2, + _("Holdings\n(shares)")); right(curwin, 4, w - 8 - OWNERSHIP_COLS - STOCK_OWNED_COLS, - attr_subtitle, 0, 0, 2, "Return\n(%%)"); + attr_subtitle, 0, 0, 2, _("Return\n(%%)")); right(curwin, 4, w - 10 - OWNERSHIP_COLS - STOCK_OWNED_COLS - SHARE_RETURN_COLS, attr_subtitle, 0, 0, 2, - "Price per\nshare (%s)", lconvinfo.currency_symbol); + _("Price per\nshare (%s)"), lconvinfo.currency_symbol); for (line = 6, i = 0; i < MAX_COMPANIES; i++) { if (company[i].on_map) { @@ -725,24 +726,24 @@ void show_status (int num) int width, x; mkchstr(chbuf, BUFSIZE, attr_highlight, 0, 0, 1, w / 2, &width, 1, - "Total value: "); + _("Total value: ")); x = (w + width - (TOTAL_VALUE_COLS + 2)) / 2; right(curwin, line, x, attr_normal, attr_highlight, 0, 1, - "Current cash: "); + _("Current cash: ")); right(curwin, line, x + TOTAL_VALUE_COLS + 2, attr_normal, attr_highlight, 0, 1, " ^{%N^} ", player[num].cash); line++; if (player[num].debt != 0.0) { right(curwin, line, x, attr_normal, attr_highlight, 0, 1, - "Current debt: "); + _("Current debt: ")); right(curwin, line, x + TOTAL_VALUE_COLS + 2, attr_normal, attr_highlight, 0, 1, " ^{%N^} ", player[num].debt); line++; right(curwin, line, x, attr_normal, attr_highlight, 0, 1, - "Interest rate: "); + _("Interest rate: ")); right(curwin, line, x + TOTAL_VALUE_COLS + 2, attr_normal, attr_highlight, 0, 1, " ^{%.2f%%^} ", interest_rate * 100.0); line++; @@ -768,13 +769,12 @@ void show_status (int num) double total_value (int num) { double val; - int i; assert(num >= 0 && num < number_players); val = player[num].cash - player[num].debt; - for (i = 0; i < MAX_COMPANIES; i++) { + for (int i = 0; i < MAX_COMPANIES; i++) { if (company[i].on_map) { val += player[num].stock_owned[i] * company[i].share_price; } diff --git a/src/help.c b/src/help.c index fa2a51b..57baea5 100644 --- a/src/help.c +++ b/src/help.c @@ -36,110 +36,116 @@ ************************************************************************/ static const char *help_text[] = { - "^BStar Traders^N is a simple game of interstellar trading. The object of the\n" - "game is to amass the greatest amount of wealth possible. This is done by\n" - "creating interstellar shipping lanes, expanding them and buying shares in\n" - "the companies controlling them. Shares appreciate in value as company\n" - "operations expand. In addition, the return on each share (as a percentage)\n" - "also changes. Players may also borrow from the Interstellar Trading Bank to\n" - "finance additional purchases on the Stock Exchange.\n" - "\n" - "The map of the galaxy is represented by a ^B~x^N x ^B~y^N grid. A typical section\n" - "of it may be:\n" - "\n" - " ^e . . ^s*^e . . . ^s*^e ^s*^e . ^N\n" - " ^e . . . . . . . . . ^N ^e . ^N represents ^Bempty space^N,\n" - " ^e . ^s*^e . . . . . . . ^N ^s * ^N represents a ^Bstar^N.\n" - " ^e . . . . . . . ^s*^e . ^N\n" - " ^e . . . . ^s*^e . . . . ^N\n" - , + N_("" + "^BStar Traders^N is a simple game of interstellar trading. The object of the\n" + "game is to amass the greatest amount of wealth possible. This is done by\n" + "creating interstellar shipping lanes, expanding them and buying shares in\n" + "the companies controlling them. Shares appreciate in value as company\n" + "operations expand. In addition, the return on each share (as a percentage)\n" + "also changes. Players may also borrow from the Interstellar Trading Bank to\n" + "finance additional purchases on the Stock Exchange.\n" + "\n" + "The map of the galaxy is represented by a ^B~x^N x ^B~y^N grid. A typical section\n" + "of it may be:\n" + "\n" + " ^e . . ^s*^e . . . ^s*^e ^s*^e . ^N\n" + " ^e . . . . . . . . . ^N ^e . ^N represents ^Bempty space^N,\n" + " ^e . ^s*^e . . . . . . . ^N ^s * ^N represents a ^Bstar^N.\n" + " ^e . . . . . . . ^s*^e . ^N\n" + " ^e . . . . ^s*^e . . . . ^N\n" + ""), - "The computer selects ^B~m^N moves (labeled ^k~1^N to ^k~M^N) at random, and places these\n" - "on the map. To select any of the highlighted positions, press that letter.\n" - "As an example, some of the moves on the map may be:\n" - "\n" - "\n" - " ^e ^k~1^e . ^s*^e . . . ^s*^e ^s*^e . ^N\n" - " ^e . . . ^k~3^e . . . . . ^N\n" - " ^e . ^s*^e . . . . ^k~5^e . . ^N Moves ^k~1^N to ^k~5^N shown.\n" - " ^e . ^k~2^e . . ^k~4^e . . ^s*^e . ^N\n" - " ^e . . . . ^s*^e . . . . ^N\n" - "\n" - "\n" - "Selecting a position that is ^Bnot^N next to a star (such as moves ^k~1^N, ^k~3^N or ^k~5^N)\n" - "will set up an ^Boutpost^N, not belonging to any company. Thus, if move ^k~3^N was\n" - "selected on the above map, a ^o + ^N would be placed at that position.\n" - , + N_("" + "The computer selects ^B~m^N moves (labeled ^k~1^N to ^k~M^N) at random, and places these\n" + "on the map. To select any of the highlighted positions, press that letter.\n" + "As an example, some of the moves on the map may be:\n" + "\n" + "\n" + " ^e ^k~1^e . ^s*^e . . . ^s*^e ^s*^e . ^N\n" + " ^e . . . ^k~3^e . . . . . ^N\n" + " ^e . ^s*^e . . . . ^k~5^e . . ^N Moves ^k~1^N to ^k~5^N shown.\n" + " ^e . ^k~2^e . . ^k~4^e . . ^s*^e . ^N\n" + " ^e . . . . ^s*^e . . . . ^N\n" + "\n" + "\n" + "Selecting a position that is ^Bnot^N next to a star (such as moves ^k~1^N, ^k~3^N or ^k~5^N)\n" + "will set up an ^Boutpost^N, not belonging to any company. Thus, if move ^k~3^N was\n" + "selected on the above map, a ^o + ^N would be placed at that position.\n" + ""), - "If, on the other hand, a position next to a star (or another outpost) is\n" - "selected, a ^Bcompany^N would be formed and its first letter would appear on the\n" - "map. As a reward for creating the company, you are granted the first five\n" - "shares. Up to ^B~c^N companies can be created in this way.\n" - "\n" - "If a position next to an existing company is selected, the company would\n" - "expand its operations by one square. This increases the cost of its shares\n" - "and hence your return. Thus, if the map was as shown below, selecting ^k~6^N\n" - "or ^k~8^N increases Company ^B~B^N's shipping lane:\n" - "\n" - " ^e ^k~1^e . ^s*^e . . . ^s*^e ^s*^e . ^N\n" - " ^e . . . ^o+^e . . ^k~6^e . . ^N\n" - " ^e . ^s*^e . . . . ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~6^N or ^k~8^N increases Company ^B~B^N.\n" - " ^e . ^k~2^e . . ^k~4^e . . ^s*^e ^c~B^e ^N\n" - " ^e . . . . ^s*^e . . . ^k~8^e ^N\n" - , + N_("" + "If, on the other hand, a position next to a star (or another outpost) is\n" + "selected, a ^Bcompany^N would be formed and its first letter would appear on the\n" + "map. As a reward for creating the company, you are granted the first five\n" + "shares. Up to ^B~c^N companies can be created in this way.\n" + "\n" + "If a position next to an existing company is selected, the company would\n" + "expand its operations by one square. This increases the cost of its shares\n" + "and hence your return. Thus, if the map was as shown below, selecting ^k~6^N\n" + "or ^k~8^N increases Company ^B~B^N's shipping lane:\n" + "\n" + " ^e ^k~1^e . ^s*^e . . . ^s*^e ^s*^e . ^N\n" + " ^e . . . ^o+^e . . ^k~6^e . . ^N\n" + " ^e . ^s*^e . . . . ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~6^N or ^k~8^N increases Company ^B~B^N.\n" + " ^e . ^k~2^e . . ^k~4^e . . ^s*^e ^c~B^e ^N\n" + " ^e . . . . ^s*^e . . . ^k~8^e ^N\n" + ""), - "Selecting positions next to stars increases the value of your stock by about\n" - "five times as much as an extension not next to a star. Thus move ^k~6^N should\n" - "be preferred to move ^k~8^N.\n" - "\n" - " ^e ^c~C^e . ^s*^e . . . ^s*^e ^s*^e . ^N\n" - " ^e ^k~1^e ^o+^e . ^o+^e . . ^k~6^e . . ^N\n" - " ^e . ^s*^e . . . . ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~6^N is preferred to ^k~8^N.\n" - " ^e . ^k~2^e . . ^k~4^e . . ^s*^e ^c~B^e ^N\n" - " ^e . . . . ^s*^e . . . ^k~8^e ^N\n" - "\n" - "You can also expand any company by selecting positions next to outposts.\n" - "Such outposts will be swallowed up by that company. Thus, move ^k~1^N will\n" - "extend Company ^BC^N by ^Btwo^N squares. As a bonus, outposts next to stars are\n" - "more valuable: the company's share price will increase by a greater amount\n" - "than it would for outposts not next to stars.\n" - , + N_("" + "Selecting positions next to stars increases the value of your stock by about\n" + "five times as much as an extension not next to a star. Thus move ^k~6^N should\n" + "be preferred to move ^k~8^N.\n" + "\n" + " ^e ^c~C^e . ^s*^e . . . ^s*^e ^s*^e . ^N\n" + " ^e ^k~1^e ^o+^e . ^o+^e . . ^k~6^e . . ^N\n" + " ^e . ^s*^e . . . . ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~6^N is preferred to ^k~8^N.\n" + " ^e . ^k~2^e . . ^k~4^e . . ^s*^e ^c~B^e ^N\n" + " ^e . . . . ^s*^e . . . ^k~8^e ^N\n" + "\n" + "You can also expand any company by selecting positions next to outposts.\n" + "Such outposts will be swallowed up by that company. Thus, move ^k~1^N will\n" + "extend Company ^BC^N by ^Btwo^N squares. As a bonus, outposts next to stars are\n" + "more valuable: the company's share price will increase by a greater amount\n" + "than it would for outposts not next to stars.\n" + ""), - "If two companies are separated on the map by only one square, then they can\n" - "be ^Bmerged^N into one company by selecting that position (if available). For\n" - "example, on the map below, companies ^B~A^N and ^B~B^N can be merged by selecting ^k~5^N.\n" - "When this occurs, the company with the greater assets value takes over the\n" - "other one. Here, Company ^B~B^N might take over Company ^B~A^N. Company ^B~A^N ceases to\n" - "exist, although it may reappear as an entirely new company at a later stage.\n" - "\n" - " ^e ^k~1^e . ^s*^e . . . ^s*^e ^s*^e . ^N\n" - " ^e . . . ^c~A^e ^c~A^e ^k~5^e ^c~B^e . . ^N\n" - " ^e . ^s*^e . . ^c~A^e . ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~5^N merges companies ^B~A^N and ^B~B^N.\n" - " ^e . ^k~2^e . . . . . ^s*^e ^c~B^e ^N\n" - " ^e . . . . ^s*^e . ^o+^e . . ^N\n" - "\n" - "When companies merge, players are granted shares in the dominant company\n" - "proportional to the amount owned in the old company. As well, a cash bonus\n" - "is also paid, proportional to the percentage of the old company owned.\n" - , + N_("" + "If two companies are separated on the map by only one square, then they can\n" + "be ^Bmerged^N into one company by selecting that position (if available). For\n" + "example, on the map below, companies ^B~A^N and ^B~B^N can be merged by selecting ^k~5^N.\n" + "When this occurs, the company with the greater assets value takes over the\n" + "other one. Here, Company ^B~B^N might take over Company ^B~A^N. Company ^B~A^N ceases to\n" + "exist, although it may reappear as an entirely new company at a later stage.\n" + "\n" + " ^e ^k~1^e . ^s*^e . . . ^s*^e ^s*^e . ^N\n" + " ^e . . . ^c~A^e ^c~A^e ^k~5^e ^c~B^e . . ^N\n" + " ^e . ^s*^e . . ^c~A^e . ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~5^N merges companies ^B~A^N and ^B~B^N.\n" + " ^e . ^k~2^e . . . . . ^s*^e ^c~B^e ^N\n" + " ^e . . . . ^s*^e . ^o+^e . . ^N\n" + "\n" + "When companies merge, players are granted shares in the dominant company\n" + "proportional to the amount owned in the old company. As well, a cash bonus\n" + "is also paid, proportional to the percentage of the old company owned.\n" + ""), - "Once you select your move, you enter the ^BInterstellar Stock Exchange^N. Here\n" - "you can purchase shares, sell them, borrow from the Trading Bank or repay\n" - "some of your debt (if applicable). Note that each company issues a limited\n" - "number of shares --- you cannot go on buying for ever! You can, however,\n" - "bid for more shares to be issued. You have a better chance of succeeding if\n" - "you own a larger proportion of the company.\n" - "\n" - "The game usually ends after ^B~t^N turns. However, you can end the game sooner\n" - "by pressing ^K^N when asked to select a move. As well, individual\n" - "players can declare themselves bankrupt at any time. If your debt is large\n" - "enough, the Bank may do this for you! If you do not complete your game in\n" - "the time you have available, you may save the game and continue it later.\n" - "\n" - "\n" - "The ^Bwinner of the game^N is the person with the greatest net worth (total\n" - "value of cash, stock and debt). ^HGood luck^N and may the best person win!\n" - , + N_("" + "Once you select your move, you enter the ^BInterstellar Stock Exchange^N. Here\n" + "you can purchase shares, sell them, borrow from the Trading Bank or repay\n" + "some of your debt (if applicable). Note that each company issues a limited\n" + "number of shares --- you cannot go on buying for ever! You can, however,\n" + "bid for more shares to be issued. You have a better chance of succeeding if\n" + "you own a larger proportion of the company.\n" + "\n" + "The game usually ends after ^B~t^N turns. However, you can end the game sooner\n" + "by pressing ^K^N when asked to select a move. As well, individual\n" + "players can declare themselves bankrupt at any time. If your debt is large\n" + "enough, the Bank may do this for you! If you do not complete your game in\n" + "the time you have available, you may save the game and continue it later.\n" + "\n" + "\n" + "The ^Bwinner of the game^N is the person with the greatest net worth (total\n" + "value of cash, stock and debt). ^HGood luck^N and may the best person win!\n" + ""), NULL }; @@ -178,14 +184,14 @@ void show_help (void) werase(curwin); box(curwin, 0, 0); - center(curwin, 1, 0, attr_title, 0, 0, 1, " How to Play "); + center(curwin, 1, 0, attr_title, 0, 0, 1, _(" How to Play ")); center(curwin, 2, 0, attr_normal, attr_highlight, 0, 1, - "Page %d of %d", curpage + 1, numpages); + _("Page %d of %d"), curpage + 1, numpages); wmove(curwin, 4, 2); // Process the help text string - const char *s = help_text[curpage]; + const char *s = gettext(help_text[curpage]); int curattr = attr_normal; while (*s != '\0') { @@ -326,9 +332,9 @@ void show_help (void) } center(curwin, getmaxy(curwin) - 2, 0, attr_waitforkey, 0, 0, 1, - (curpage == 0) ? "[ Press to continue ] " : - "[ Press to continue or " - "for the previous page ] "); + (curpage == 0) ? _("[ Press to continue ] ") : + _("[ Press to continue or " + "for the previous page ] ")); wrefresh(curwin); int key = gettxchar(curwin); diff --git a/src/intf.c b/src/intf.c index 0b374fd..2b9d7f5 100644 --- a/src/intf.c +++ b/src/intf.c @@ -2368,9 +2368,9 @@ bool answer_yesno (WINDOW *win) wattron(win, A_BOLD); if (key == 'Y') { - waddstr(win, "Yes"); + waddstr(win, _("Yes")); } else { - waddstr(win, "No"); + waddstr(win, _("No")); } wbkgdset(win, oldbkgd); diff --git a/src/move.c b/src/move.c index c1eb629..a502675 100644 --- a/src/move.c +++ b/src/move.c @@ -232,17 +232,17 @@ selection_t get_move (void) box(curwin, 0, 0); left(curwin, 2, 2, attr_normal, attr_keycode, 0, 1, - "^{<1>^} Display stock portfolio"); + _("^{<1>^} Display stock portfolio")); left(curwin, 3, 2, attr_normal, attr_keycode, 0, 1, - "^{<2>^} Declare bankruptcy"); + _("^{<2>^} Declare bankruptcy")); left(curwin, 2, getmaxx(curwin) / 2, attr_normal, attr_keycode, 0, 1, - "^{<3>^} Save and end the game"); + _("^{<3>^} Save and end the game")); left(curwin, 3, getmaxx(curwin) / 2, attr_normal, attr_keycode, 0, 1, - "^{^} Quit the game"); + _("^{^} Quit the game")); right(curwin, 1, getmaxx(curwin) / 2, attr_normal, attr_keycode, - attr_choice, 1, "Select move " - "[^[%c^]-^[%c^]/^{1^}-^{3^}/^{^}]: ", + attr_choice, 1, + _("Select move [^[%c^]-^[%c^]/^{1^}-^{3^}/^{^}]: "), MOVE_TO_KEY(0), MOVE_TO_KEY(NUMBER_MOVES - 1)); curs_set(CURS_ON); @@ -257,7 +257,7 @@ selection_t get_move (void) curs_set(CURS_OFF); left(curwin, 1, getmaxx(curwin) / 2, attr_normal, attr_choice, - 0, 1, "Move ^{%c^}", key); + 0, 1, _("Move ^{%c^}"), key); } else { switch (key) { case '1': @@ -272,7 +272,7 @@ selection_t get_move (void) curs_set(CURS_OFF); left(curwin, 1, getmaxx(curwin) / 2, attr_normal, attr_normal | A_BOLD, 0, 1, - "^{<2>^} (Declare bankruptcy)"); + _("^{<2>^} (Declare bankruptcy)")); break; case '3': @@ -281,7 +281,7 @@ selection_t get_move (void) curs_set(CURS_OFF); left(curwin, 1, getmaxx(curwin) / 2, attr_normal, attr_normal | A_BOLD, 0, 1, - "^{<3>^} (Save and end the game)"); + _("^{<3>^} (Save and end the game)")); break; case KEY_ESC: @@ -295,7 +295,7 @@ selection_t get_move (void) curs_set(CURS_OFF); left(curwin, 1, getmaxx(curwin) / 2, attr_normal, attr_normal | A_BOLD, 0, 1, - "^{^} (Quit the game)"); + _("^{^} (Quit the game)")); break; default: @@ -310,7 +310,7 @@ selection_t get_move (void) // Ask the player to confirm their choice right(curwin, 2, getmaxx(curwin) / 2, attr_normal, attr_keycode, 0, 1, - "Are you sure? [^{Y^}/^{N^}] "); + _("Are you sure? [^{Y^}/^{N^}] ")); wrefresh(curwin); if (! answer_yesno(curwin)) { @@ -327,7 +327,7 @@ selection_t get_move (void) if (game_loaded) { // Save the game to the same game number mkchstr(chbuf, BUFSIZE, attr_status_window, 0, 0, 1, WIN_COLS - - 7, &width, 1, "Saving game %d... ", game_num); + - 7, &width, 1, _("Saving game %d... "), game_num); newtxwin(5, width + 5, 7, WCENTER, true, attr_status_window); centerch(curwin, 2, 0, chbuf, 1, &width); wrefresh(curwin); @@ -348,8 +348,8 @@ selection_t get_move (void) lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_keycode, 0, 2, WIN_COLS - 7, widthbuf, 2, - "Enter game number [^{1^}-^{9^}] " - "or ^{^} to cancel: "); + _("Enter game number [^{1^}-^{9^}] " + "or ^{^} to cancel: ")); assert(lines == 1 || lines == 2); maxwidth = ((lines == 1) ? widthbuf[0] : MAX(widthbuf[0], widthbuf[1])) + 5; @@ -394,8 +394,9 @@ selection_t get_move (void) mkchstr(chbuf, BUFSIZE, attr_status_window, 0, 0, 1, WIN_COLS - 7, &width, 1, - "Saving game %d... ", game_num); - newtxwin(5, width + 5, 7, WCENTER, true, attr_status_window); + _("Saving game %d... "), game_num); + newtxwin(5, width + 5, 7, WCENTER, true, + attr_status_window); centerch(curwin, 2, 0, chbuf, 1, &width); wrefresh(curwin); @@ -623,14 +624,16 @@ void bankrupt_player (bool forced) if (forced) { txdlgbox(MAX_DLG_LINES, 50, 7, WCENTER, attr_error_window, attr_error_title, attr_error_highlight, 0, 0, - attr_error_waitforkey, " Bankruptcy Court ", - "%s has been declared bankrupt by the Interstellar Trading Bank.", + attr_error_waitforkey, _(" Bankruptcy Court "), + _("%s has been declared bankrupt " + "by the Interstellar Trading Bank."), player[current_player].name); } else { txdlgbox(MAX_DLG_LINES, 50, 7, WCENTER, attr_error_window, attr_error_title, attr_error_highlight, 0, 0, - attr_error_waitforkey, " Bankruptcy Court ", - "%s has declared bankruptcy.", player[current_player].name); + attr_error_waitforkey, _(" Bankruptcy Court "), + _("%s has declared bankruptcy."), + player[current_player].name); } txrefresh(); @@ -697,8 +700,9 @@ void try_start_new_company (int x, int y) txdlgbox(MAX_DLG_LINES, 50, 7, WCENTER, attr_normal_window, attr_title, attr_normal, attr_highlight, 0, attr_waitforkey, - " New Company ", "A new company has been formed!\n" - "Its name is ^{%s^}.", company[i].name); + _(" New Company "), + _("A new company has been formed!\nIts name is ^{%s^}."), + company[i].name); txrefresh(); galaxy_map[x][y] = COMPANY_TO_MAP(i); @@ -751,14 +755,15 @@ void merge_companies (map_val_t a, map_val_t b) // Display information about the merger - lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_highlight, 0, 4, WIN_COLS - - 8, widthbuf, 4, "^{%s^} has just merged into ^{%s^}.\n" - "Please note the following transactions:\n", + lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_highlight, 0, 4, + WIN_COLS - 8, widthbuf, 4, + _("^{%s^} has just merged into ^{%s^}.\n" + "Please note the following transactions:\n"), company[bb].name, company[aa].name); newtxwin(number_players + lines + 10, WIN_COLS - 4, lines + 6 - number_players, WCENTER, true, attr_normal_window); - center(curwin, 1, 0, attr_title, 0, 0, 1, " Company Merger "); + center(curwin, 1, 0, attr_title, 0, 0, 1, _(" Company Merger ")); centerch(curwin, 3, 0, chbuf, lines, widthbuf); mkchstr(chbuf, BUFSIZE, attr_highlight, 0, 0, 1, getmaxx(curwin) / 2, @@ -770,7 +775,7 @@ void merge_companies (map_val_t a, map_val_t b) chbuf_bb = chstrdup(chbuf, BUFSIZE); mkchstr(chbuf, BUFSIZE, attr_normal, 0, 0, 1, getmaxx(curwin) / 2, &width, - 1, "Old stock: "); + 1, _("Old stock: ")); w = getmaxx(curwin); x = (w + width - MAX(width_aa, width_bb)) / 2; @@ -778,19 +783,19 @@ void merge_companies (map_val_t a, map_val_t b) rightch(curwin, lines + 3, x, chbuf, 1, &width); leftch(curwin, lines + 3, x, chbuf_bb, 1, &width_bb); - right(curwin, lines + 4, x, attr_normal, 0, 0, 1, "New Stock: "); + right(curwin, lines + 4, x, attr_normal, 0, 0, 1, _("New Stock: ")); leftch(curwin, lines + 4, x, chbuf_aa, 1, &width_aa); mvwhline(curwin, lines + 6, 2, ' ' | attr_subtitle, w - 4); - left(curwin, lines + 6, 4, attr_subtitle, 0, 0, 1, "Player"); + left(curwin, lines + 6, 4, attr_subtitle, 0, 0, 1, _("Player")); right(curwin, lines + 6, w - 4, attr_subtitle, 0, 0, 1, - "Bonus (%s)", lconvinfo.currency_symbol); + _("Bonus (%s)"), lconvinfo.currency_symbol); right(curwin, lines + 6, w - 6 - MERGE_BONUS_COLS, attr_subtitle, 0, 0, - 1, "Total"); + 1, _("Total")); right(curwin, lines + 6, w - 8 - MERGE_BONUS_COLS - MERGE_TOTAL_STOCK_COLS, - attr_subtitle, 0, 0, 1, "New"); + attr_subtitle, 0, 0, 1, _("New")); right(curwin, lines + 6, w - 10 - MERGE_BONUS_COLS - MERGE_TOTAL_STOCK_COLS - - MERGE_NEW_STOCK_COLS, attr_subtitle, 0, 0, 1, "Old"); + - MERGE_NEW_STOCK_COLS, attr_subtitle, 0, 0, 1, _("Old")); total_new = 0; for (ln = lines + 7, i = 0; i < number_players; i++) { @@ -936,11 +941,11 @@ void adjust_values (void) txdlgbox(MAX_DLG_LINES, 60, 6, WCENTER, attr_error_window, attr_error_title, attr_error_highlight, attr_error_normal, 0, attr_error_waitforkey, - " Bankruptcy Court ", - "%s has been declared bankrupt " - "by the Interstellar Trading Bank.\n\n" - "^{All assets have been taken " - "to repay outstanding loans.^}", + _(" Bankruptcy Court "), + _("%s has been declared bankrupt " + "by the Interstellar Trading Bank.\n\n" + "^{All assets have been taken " + "to repay outstanding loans.^}"), company[which].name); txrefresh(); @@ -959,17 +964,18 @@ void adjust_values (void) lines = mkchstr(chbuf, BUFSIZE, attr_error_highlight, attr_error_normal, 0, 6, 60 - 4, widthbuf, 6, - "%s has been declared bankrupt by the " - "Interstellar Trading Bank.\n\n" - "^{The Bank has agreed to pay stock holders ^}" - "%.2f%%^{ of the share value on each share " - "owned.^}", company[which].name, rate * 100.0); + _("%s has been declared bankrupt by the " + "Interstellar Trading Bank.\n\n" + "^{The Bank has agreed to pay stock holders ^}" + "%.2f%%^{ of the share value on each share " + "owned.^}"), + company[which].name, rate * 100.0); newtxwin(9 + lines, 60, 4, WCENTER, true, attr_error_window); w = getmaxx(curwin); center(curwin, 1, 0, attr_error_title, 0, 0, 1, - " Bankruptcy Court "); + _(" Bankruptcy Court ")); centerch(curwin, 3, 0, chbuf, lines, widthbuf); mkchstr(chbuf, BUFSIZE, attr_error_highlight, 0, 0, 1, w / 2, @@ -977,11 +983,11 @@ void adjust_values (void) chbuf_amt = chstrdup(chbuf, BUFSIZE); mkchstr(chbuf, BUFSIZE, attr_error_normal, 0, 0, 1, w / 2, - &width, 1, "Amount paid per share: "); + &width, 1, _("Amount paid per share: ")); x = (w + width - width_amt) / 2; right(curwin, lines + 4, x, attr_error_normal, 0, 0, 1, - "Old share value: "); + _("Old share value: ")); leftch(curwin, lines + 4, x, chbuf_amt, 1, &width_amt); rightch(curwin, lines + 5, x, chbuf, 1, &width); @@ -1073,9 +1079,9 @@ void adjust_values (void) txdlgbox(MAX_DLG_LINES, 60, 7, WCENTER, attr_error_window, attr_error_title, attr_error_highlight, attr_error_normal, - 0, attr_error_waitforkey, " Interstellar Trading Bank ", - "Your debt has amounted to %N!\n" - "^{The Bank has impounded ^}%N^{ from your cash.^}", + 0, attr_error_waitforkey, _(" Interstellar Trading Bank "), + _("Your debt has amounted to %N!\n" + "^{The Bank has impounded ^}%N^{ from your cash.^}"), player[current_player].debt, impounded); txrefresh(); From 0aa74d1f46a9ac7b44004823627b8cb1e9f6032b Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Tue, 16 Aug 2011 21:14:56 +1000 Subject: [PATCH 045/112] Add a space to the "Player %d: " string for consistency --- src/game.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game.c b/src/game.c index 4d3099a..f9853f5 100644 --- a/src/game.c +++ b/src/game.c @@ -410,10 +410,10 @@ void ask_player_names (void) player[i].name = NULL; entered[i] = false; left(curwin, i + 3, 2, attr_normal, 0, 0, 1, - _("Player %d:"), i + 1); + _("Player %d: "), i + 1); } - int x = getcurx(curwin) + 1; + int x = getcurx(curwin); int w = getmaxx(curwin) - x - 2; cur = 0; From 4fecbe6e9d7603a0e44eb34a1e8c9e4bc1103349 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Wed, 17 Aug 2011 09:40:36 +1000 Subject: [PATCH 046/112] Ignore TAGS files --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index d10ac52..1219d12 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ .deps/ Makefile Makefile.in +TAGS /aclocal.m4 /autom4te.cache From d953154e5dfa82b74ada65e25773b6771f302b2d Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Wed, 17 Aug 2011 10:04:57 +1000 Subject: [PATCH 047/112] Mark up strings with xgettext:c-format comments where appropriate --- src/game.c | 5 ++++- src/move.c | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/game.c b/src/game.c index f9853f5..738fa38 100644 --- a/src/game.c +++ b/src/game.c @@ -532,7 +532,9 @@ void end_game (void) if (number_players == 1) { txdlgbox(MAX_DLG_LINES, 60, 8, WCENTER, attr_normal_window, attr_title, attr_normal, attr_highlight, 0, attr_waitforkey, - _(" Total Value "), _("Your total value was ^{%N^}."), + _(" Total Value "), + /* xgettext:c-format */ + _("Your total value was ^{%N^}."), total_value(0)); } else { // Sort players on the basis of total value @@ -546,6 +548,7 @@ void end_game (void) (player[0].sort_value == 0) ? _("The winner is ^{%s^}\n" "who is ^[*** BANKRUPT ***^]") : + /* xgettext:c-format */ _("The winner is ^{%s^}\n" "with a value of ^{%N^}."), player[0].name, player[0].sort_value); diff --git a/src/move.c b/src/move.c index a502675..fe1ae42 100644 --- a/src/move.c +++ b/src/move.c @@ -1080,6 +1080,7 @@ void adjust_values (void) txdlgbox(MAX_DLG_LINES, 60, 7, WCENTER, attr_error_window, attr_error_title, attr_error_highlight, attr_error_normal, 0, attr_error_waitforkey, _(" Interstellar Trading Bank "), + /* xgettext:c-format */ _("Your debt has amounted to %N!\n" "^{The Bank has impounded ^}%N^{ from your cash.^}"), player[current_player].debt, impounded); From 9b115993540d4e1def5d7604acbd37ddc8410eb5 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Wed, 17 Aug 2011 12:21:18 +1000 Subject: [PATCH 048/112] Add some translator comments with the correct pronunciation of my name --- src/trader.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/trader.c b/src/trader.c index b47dda6..3eb23ce 100644 --- a/src/trader.c +++ b/src/trader.c @@ -278,6 +278,9 @@ void process_cmdline (int argc, char *argv[]) void show_version (void) { + /* TRANSLATORS: "John Zaitseff" [IPA d͡ʒɒn ˈzaɪ̯t͡səf] is the proper + name of the author. The IPA pronunciation in this comment is in + UTF-8 encoding. */ printf(_("\ Star Traders (%s) %s\n\ Copyright (C) %s, John Zaitseff.\n\ @@ -325,8 +328,19 @@ playing that game. If GAME is not specified, start a new game.\n\n\ ")); #ifdef PACKAGE_AUTHOR + /* TRANSLATORS: The first %s is the proper name of the package + author, John Zaitseff [IPA d͡ʒɒn ˈzaɪ̯t͡səf]; the second %s is + the e-mail address for reporting bugs. Please add ANOTHER + line with the (translated) text "Report translation bugs to +
\n", with ADDRESS replaced with either an e-mail + address or web URL for reporting bugs in your translation. */ printf(_("Report bugs to %s <%s>.\n"), PACKAGE_AUTHOR, PACKAGE_BUGREPORT); #else + /* TRANSLATORS: The %s is the e-mail address for reporting bugs. + As with the previous string, please add ANOTHER line with the + (translated) text "Report translation bugs to
\n", + with ADDRESS replaced with either an e-mail address or web URL + for reporting bugs in your translation. */ printf(_("Report bugs to <%s>.\n"), PACKAGE_BUGREPORT); #endif #ifdef PACKAGE_PACKAGER_BUG_REPORTS From 197de2804fbce042d05e2057f0d0c4c4b03e6ff8 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Wed, 17 Aug 2011 13:18:41 +1000 Subject: [PATCH 049/112] Add calls to ngettext() where appropriate --- src/exch.c | 13 +++++++++---- src/game.c | 4 +++- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/exch.c b/src/exch.c index f6a50d3..fe6b266 100644 --- a/src/exch.c +++ b/src/exch.c @@ -599,7 +599,9 @@ void trade_shares (int num, bool *bid_used) box(curwin, 0, 0); center(curwin, 2, 0, attr_normal, attr_highlight, 0, 1, - _("You can purchase up to ^{%'ld^} shares."), maxshares); + ngettext("You can purchase ^{one^} share.", + "You can purchase up to ^{%'ld^} shares.", + maxshares), maxshares); mkchstr(chbuf, BUFSIZE, attr_normal, 0, 0, 1, getmaxx(curwin) - TRADE_INPUT_COLS - 4, &width, 1, @@ -632,7 +634,9 @@ void trade_shares (int num, bool *bid_used) box(curwin, 0, 0); center(curwin, 2, 0, attr_normal, attr_highlight, 0, 1, - _("You can sell up to ^{%'ld^} shares."), maxshares); + ngettext("You can sell ^{one^} share.", + "You can sell up to ^{%'ld^} shares.", + maxshares), maxshares); mkchstr(chbuf, BUFSIZE, attr_normal, 0, 0, 1, getmaxx(curwin) - TRADE_INPUT_COLS - 4, &width, 1, @@ -671,8 +675,9 @@ void trade_shares (int num, bool *bid_used) txdlgbox(MAX_DLG_LINES, 50, 8, WCENTER, attr_normal_window, attr_title, attr_normal, attr_highlight, 0, attr_waitforkey, _(" Shares Issued "), - _("%s has issued\n^{%'ld^} more shares."), - company[num].name, maxshares); + ngettext("%s has issued\none more share.", + "%s has issued\n^{%'ld^} more shares.", + maxshares), company[num].name, maxshares); } break; diff --git a/src/game.c b/src/game.c index 738fa38..3f17f99 100644 --- a/src/game.c +++ b/src/game.c @@ -523,7 +523,9 @@ void end_game (void) txdlgbox(MAX_DLG_LINES, 50, 9, WCENTER, attr_error_window, attr_error_title, attr_error_highlight, 0, 0, attr_error_waitforkey, _(" Game Over "), - _("The game is over after %d turns."), turn_number - 1); + ngettext("The game is over after one turn.", + "The game is over after %d turns.", + turn_number - 1), turn_number - 1); for (int i = 0; i < number_players; i++) { show_status(i); From 5f069b983d629e867a8129b41f297809739de7a8 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Wed, 17 Aug 2011 13:19:57 +1000 Subject: [PATCH 050/112] Inform xgettext(1) that files are in UTF-8 format and may be wide --- po/Makevars | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/po/Makevars b/po/Makevars index 12376cf..8ef2d06 100644 --- a/po/Makevars +++ b/po/Makevars @@ -34,7 +34,7 @@ subdir = po top_builddir = .. # These options get passed to xgettext -XGETTEXT_OPTIONS = --keyword=_ --keyword=N_ +XGETTEXT_OPTIONS = --from-code=UTF-8 --keyword=_ --keyword=N_ --width=132 # Copyright holder that gets inserted into the header of the # $(DOMAIN).pot file. From 5f5c512e459961a295ccea37897a1076c300f494 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Wed, 17 Aug 2011 13:26:11 +1000 Subject: [PATCH 051/112] Highlight the word "one" --- src/exch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/exch.c b/src/exch.c index fe6b266..d50811e 100644 --- a/src/exch.c +++ b/src/exch.c @@ -675,7 +675,7 @@ void trade_shares (int num, bool *bid_used) txdlgbox(MAX_DLG_LINES, 50, 8, WCENTER, attr_normal_window, attr_title, attr_normal, attr_highlight, 0, attr_waitforkey, _(" Shares Issued "), - ngettext("%s has issued\none more share.", + ngettext("%s has issued\n^{one^} more share.", "%s has issued\n^{%'ld^} more shares.", maxshares), company[num].name, maxshares); } From 25d586f7753475a8259bb3f5b6e9deb3b22d5a00 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Wed, 17 Aug 2011 13:26:55 +1000 Subject: [PATCH 052/112] Add some translator comments regarding company names and ordinals --- src/globals.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/globals.c b/src/globals.c index 3deab67..7c7269b 100644 --- a/src/globals.c +++ b/src/globals.c @@ -38,6 +38,10 @@ // Company names const char *company_name[MAX_COMPANIES] = { + /* TRANSLATORS: The eight company names do NOT have to be literal + translations of the English names. In fact, if possible, the + names should start with successive letters of your alphabet (in + English, "A" to "H"). */ N_("Altair Starways"), N_("Betelgeuse, Ltd"), N_("Capella Freight Co"), @@ -51,7 +55,12 @@ const char *company_name[MAX_COMPANIES] = { // Ordinal strings const char *ordinal[MAX_PLAYERS + 1] = { - N_("0th"), + "", + /* TRANSLATORS: The ordinal strings "1st" to "8th" are used in the + Game Winner dialog box at the end of the game. If ordinals depend + on the gender of the player, it may be simpler to list cardinal + numbers instead (eg, "No. 1"). Up to five characters are allowed + (see ORDINAL_COLS in src/intf.h). */ N_("1st"), N_("2nd"), N_("3rd"), From b674c05d56fca6ec69a76f2f288b61cf9e871bc9 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Wed, 17 Aug 2011 19:13:05 +1000 Subject: [PATCH 053/112] Add many comments for translators; use pgettext() where appropriate --- src/exch.c | 112 +++++++++++++++++++++++++++++++++++++++++--------- src/game.c | 66 +++++++++++++++++++++++------ src/globals.c | 3 +- src/intf.c | 7 +++- src/move.c | 73 ++++++++++++++++++++++++++------ src/trader.c | 6 ++- 6 files changed, 218 insertions(+), 49 deletions(-) diff --git a/src/exch.c b/src/exch.c index d50811e..b9f0392 100644 --- a/src/exch.c +++ b/src/exch.c @@ -114,15 +114,41 @@ void exchange_stock (void) mvwhline(curwin, 4, 2, ' ' | attr_subtitle, w - 4); mvwhline(curwin, 5, 2, ' ' | attr_subtitle, w - 4); - left(curwin, 4, 4, attr_subtitle, 0, 0, 2, _("\nCompany")); - right(curwin, 4, w - 4, attr_subtitle, 0, 0, 2, _("Shares\nleft")); - right(curwin, 4, w - 6 - STOCK_LEFT_COLS, attr_subtitle, 0, 0, - 2, _("Shares\nissued")); + left(curwin, 4, 4, attr_subtitle, 0, 0, 2, + /* TRANSLATORS: "Company" is a two-line column label in + a table containing a list of companies. */ + pgettext("subtitle", "\nCompany")); + right(curwin, 4, w - 4, attr_subtitle, 0, 0, 2, + /* TRANSLATORS: "Shares left" is a two-line column + label in a table containing the number of shares + left to be purchased in any given company. The + maximum column width is 10 characters (see + STOCK_LEFT_COLS in src/intf.h). */ + pgettext("subtitle", "Shares\nleft")); + right(curwin, 4, w - 6 - STOCK_LEFT_COLS, attr_subtitle, 0, 0, 2, + /* TRANSLATORS: "Shares issued" is a two-line column + label in a table containing the number of shares + already sold (ie, bought by all players) in any + given company. The maximum column width is 10 + characters (see STOCK_ISSUED_COLS in src/intf.h). */ + pgettext("subtitle", "Shares\nissued")); right(curwin, 4, w - 8 - STOCK_LEFT_COLS - STOCK_ISSUED_COLS, - attr_subtitle, 0, 0, 2, _("Return\n(%%)")); + attr_subtitle, 0, 0, 2, + /* TRANSLATORS: "Return" is a two-line column label in + a table containing the share return as a percentage + in any given company. The maximum column width is + 10 characters (see SHARE_RETURN_COLS in src/intf.h). */ + pgettext("subtitle", "Return\n(%%)")); right(curwin, 4, w - 10 - STOCK_LEFT_COLS - STOCK_ISSUED_COLS - SHARE_RETURN_COLS, attr_subtitle, 0, 0, 2, - _("Price per\nshare (%s)"), lconvinfo.currency_symbol); + /* TRANSLATORS: "Price per share" is a two-line column + label in a table containing the price per share in + any given company. %s is the currency symbol in the + current locale. The maximum column width is 12 + characters INCLUDING the currency symbol (see + SHARE_PRICE_COLS in src/intf.h). */ + pgettext("subtitle", "Price per\nshare (%s)"), + lconvinfo.currency_symbol); for (line = 6, i = 0; i < MAX_COMPANIES; i++) { if (company[i].on_map) { @@ -267,22 +293,34 @@ void visit_bank (void) _(" Interstellar Trading Bank ")); mkchstr(chbuf, BUFSIZE, attr_normal, 0, 0, 1, getmaxx(curwin) - 4, &width, - 1, _("Current cash: ")); + 1, pgettext("label", "Current cash: ")); x = (getmaxx(curwin) + width - (BANK_VALUE_COLS + 2)) / 2; rightch(curwin, 3, x, chbuf, 1, &width); right(curwin, 3, x + BANK_VALUE_COLS + 2, attr_normal, attr_highlight, 0, 1, " ^{%N^} ", player[current_player].cash); - right(curwin, 4, x, attr_normal, 0, 0, 1, _("Current debt: ")); + right(curwin, 4, x, attr_normal, 0, 0, 1, + pgettext("label", "Current debt: ")); right(curwin, 4, x + BANK_VALUE_COLS + 2, attr_normal, attr_highlight, 0, 1, " ^{%N^} ", player[current_player].debt); - right(curwin, 5, x, attr_normal, 0, 0, 1, _("Interest rate: ")); + right(curwin, 5, x, attr_normal, 0, 0, 1, + pgettext("label", "Interest rate: ")); right(curwin, 5, x + BANK_VALUE_COLS + 2, attr_normal, attr_highlight, 0, 1, " ^{%.2f%%^} ", interest_rate * 100.0); - right(curwin, 7, x, attr_highlight, 0, 0, 1, _("Credit limit: ")); + right(curwin, 7, x, attr_highlight, 0, 0, 1, + /* TRANSLATORS: The "Total value", "Current cash", "Current + debt", "Interest rate" and "Credit limit" labels MUST all be + the same length (ie, right-padded with spaces as needed) and + must have at least one trailing space so that the display + routines work correctly. The maximum length of each label + is 36 characters. + + Note that some of these labels are used for both the Player + Status window and the Trading Bank window. */ + pgettext("label", "Credit limit: ")); whline(curwin, ' ' | attr_title, BANK_VALUE_COLS + 2); right(curwin, 7, x + BANK_VALUE_COLS + 2, attr_title, 0, 0, 1, " %N ", credit_limit); @@ -293,6 +331,10 @@ void visit_bank (void) newtxwin(7, WIN_COLS - 4, 15, WCENTER, true, attr_normal_window); center(curwin, 3, 0, attr_normal, attr_keycode, 0, 1, + /* TRANSLATORS: The "Borrow money", "Repay debt" and "Exit + from the Bank" menu options must all be the same length + (ie, padded with trailing spaces as required). The maximum + length is 72 characters. */ _("^{<1>^} Borrow money ")); center(curwin, 4, 0, attr_normal, attr_keycode, 0, 1, _("^{<2>^} Repay debt ")); @@ -491,36 +533,66 @@ void trade_shares (int num, bool *bid_used) newtxwin(9, WIN_COLS - 4, 5, WCENTER, true, attr_normal_window); w = getmaxx(curwin); - center(curwin, 1, 0, attr_title, 0, 0, 1, _(" Stock Transaction in %s "), - company[num].name); + center(curwin, 1, 0, attr_title, 0, 0, 1, + /* TRANSLATORS: %s represents the company name. */ + _(" Stock Transaction in %s "), company[num].name); mkchstr(chbuf, BUFSIZE, attr_normal, 0, 0, 1, w / 2, &width, 1, - _("Shares issued: ")); + /* TRANSLATORS: "Shares issued" represents the number of + shares already sold by the company to all players. + + Note that the labels "Shares issued", "Shares left", + "Price per share" and "Return" must all be the same length + and must have at least one trailing space for the output + routines to work correctly. The maximum length of each + label is 22 characters. */ + pgettext("label|Stock A", "Shares issued: ")); leftch(curwin, 3, 2, chbuf, 1, &width); right(curwin, 3, width + SHARE_PRICE_COLS + 2, attr_normal, attr_highlight, 0, 1, "^{%'ld^}", company[num].stock_issued); - left(curwin, 4, 2, attr_normal, 0, 0, 1, _("Shares left: ")); + left(curwin, 4, 2, attr_normal, 0, 0, 1, + /* TRANSLATORS: "Shares left" is the number of shares that are + left to be purchased in the current company. */ + pgettext("label|Stock A", "Shares left: ")); right(curwin, 4, width + SHARE_PRICE_COLS + 2, attr_normal, attr_highlight, 0, 1, "^{%'ld^}", company[num].max_stock - company[num].stock_issued); - left(curwin, 5, 2, attr_normal, 0, 0, 1, _("Price per share: ")); + left(curwin, 5, 2, attr_normal, 0, 0, 1, + /* TRANSLATORS: "Price per share" is the cost of each share in + the current company. */ + pgettext("label|Stock A", "Price per share: ")); right(curwin, 5, width + SHARE_PRICE_COLS + 2, attr_normal, attr_highlight, 0, 1, "^{%N^}", company[num].share_price); - left(curwin, 6, 2, attr_normal, 0, 0, 1, _("Return: ")); + left(curwin, 6, 2, attr_normal, 0, 0, 1, + /* TRANSLATORS: "Return" is the share return as a percentage. */ + pgettext("label|Stock A", "Return: ")); right(curwin, 6, width + SHARE_PRICE_COLS + 2, attr_normal, attr_highlight, 0, 1, "^{%.2f%%^}", company[num].share_return * 100.0); - left(curwin, 3, w / 2, attr_normal, 0, 0, 1, _("Current holdings: ")); + left(curwin, 3, w / 2, attr_normal, 0, 0, 1, + /* TRANSLATORS: "Current holdings" is the number of shares the + current player owns in this particular company. + + Note that the labels "Current holdings", "Percentage owned" + and "Current cash" MUST all be the same length and contain at + least one trailing space for the display routines to work + correctly. The maximum length of each label is 18 + characters. */ + pgettext("label|Stock B", "Current holdings: ")); right(curwin, 3, w - 2, attr_normal, attr_highlight, 0, 1, " ^{%'ld^} ", player[current_player].stock_owned[num]); - left(curwin, 4, w / 2, attr_normal, 0, 0, 1, _("Percentage owned: ")); + left(curwin, 4, w / 2, attr_normal, 0, 0, 1, + /* TRANSLATORS: "Percentage owned" is the current player's + percentage ownership in this particular company. */ + pgettext("label|Stock B", "Percentage owned: ")); right(curwin, 4, w - 2, attr_normal, attr_highlight, 0, 1, " ^{%.2f%%^} ", ownership * 100.0); - left(curwin, 6, w / 2, attr_highlight, 0, 0, 1, _("Current cash: ")); + left(curwin, 6, w / 2, attr_highlight, 0, 0, 1, + pgettext("label|Stock B", "Current cash: ")); whline(curwin, ' ' | attr_title, TRADE_VALUE_COLS + 2); right(curwin, 6, w - 2, attr_title, 0, 0, 1, " %N ", player[current_player].cash); @@ -669,12 +741,14 @@ void trade_shares (int num, bool *bid_used) txdlgbox(MAX_DLG_LINES, 50, 8, WCENTER, attr_error_window, attr_error_title, attr_error_highlight, 0, 0, attr_error_waitforkey, _(" No Shares Issued "), + /* TRANSLATORS: %s represents the company name. */ _("%s has refused\nto issue more shares."), company[num].name); } else { txdlgbox(MAX_DLG_LINES, 50, 8, WCENTER, attr_normal_window, attr_title, attr_normal, attr_highlight, 0, attr_waitforkey, _(" Shares Issued "), + /* TRANSLATORS: %s represents the company name. */ ngettext("%s has issued\n^{one^} more share.", "%s has issued\n^{%'ld^} more shares.", maxshares), company[num].name, maxshares); diff --git a/src/game.c b/src/game.c index 3f17f99..881eb7f 100644 --- a/src/game.c +++ b/src/game.c @@ -410,6 +410,7 @@ void ask_player_names (void) player[i].name = NULL; entered[i] = false; left(curwin, i + 3, 2, attr_normal, 0, 0, 1, + /* xgettext:c-format, range: 1..8 */ _("Player %d: "), i + 1); } @@ -564,9 +565,15 @@ void end_game (void) mvwhline(curwin, lines + 4, 2, ' ' | attr_subtitle, w - 4); left(curwin, lines + 4, ORDINAL_COLS + 4, attr_subtitle, 0, 0, 1, - _("Player")); + /* TRANSLATORS: "Player" is used as a column title in a + table containing all player names. */ + pgettext("subtitle", "Player")); right(curwin, lines + 4, w - 4, attr_subtitle, 0, 0, 1, - _("Total Value (%s)"), lconvinfo.currency_symbol); + /* TRANSLATORS: "Total Value" refers to the total worth + (shares, cash and debt) of any given player. %s is the + currency symbol of the current locale. */ + pgettext("subtitle", "Total Value (%s)"), + lconvinfo.currency_symbol); for (int i = 0; i < number_players; i++) { right(curwin, i + lines + 5, ORDINAL_COLS + 2, attr_normal, 0, 0, @@ -599,8 +606,8 @@ void show_map (bool closewin) mvwhline(curwin, 1, 2, ' ' | attr_mapwin_title, getmaxx(curwin) - 4); // Display current player and turn number - left(curwin, 1, 2, attr_mapwin_title, attr_mapwin_highlight, 0, 1, - _(" Player: ^{%s^} "), player[current_player].name); + left(curwin, 1, 4, attr_mapwin_title, attr_mapwin_highlight, 0, 1, + _("Player: ^{%s^}"), player[current_player].name); right(curwin, 1, getmaxx(curwin) - 2, attr_mapwin_title, attr_mapwin_highlight, attr_mapwin_blink, 1, (turn_number != max_turn) ? _(" Turn: ^{%d^} ") : @@ -691,16 +698,40 @@ void show_status (int num) mvwhline(curwin, 5, 2, ' ' | attr_subtitle, w - 4); left(curwin, 4, 4, attr_subtitle, 0, 0, 2, - _("\nCompany")); + /* TRANSLATORS: "Company" is a two-line column label in + a table containing a list of companies. */ + pgettext("subtitle", "\nCompany")); right(curwin, 4, w - 4, attr_subtitle, 0, 0, 2, - _("Ownership\n(%%)")); + /* TRANSLATORS: "Ownership" is a two-line column label + in a table containing the current player's + percentage ownership in any given company. The + maximum column width is 10 characters (see + OWNERSHIP_COLS in src/intf.h). */ + pgettext("subtitle", "Ownership\n(%%)")); right(curwin, 4, w - 6 - OWNERSHIP_COLS, attr_subtitle, 0, 0, 2, - _("Holdings\n(shares)")); + /* TRANSLATORS: "Holdings" is a two-line column label + in a table containing the number of shares the + current player owns in any given company. The + maximum column width is 10 characters (see + STOCK_OWNED_COLS in src/intf.h). */ + pgettext("subtitle", "Holdings\n(shares)")); right(curwin, 4, w - 8 - OWNERSHIP_COLS - STOCK_OWNED_COLS, - attr_subtitle, 0, 0, 2, _("Return\n(%%)")); + attr_subtitle, 0, 0, 2, + /* TRANSLATORS: "Return" is a two-line column label in + a table containing the share return as a percentage + in any given company. The maximum column width is + 10 characters (see SHARE_RETURN_COLS in src/intf.h). */ + pgettext("subtitle", "Return\n(%%)")); right(curwin, 4, w - 10 - OWNERSHIP_COLS - STOCK_OWNED_COLS - SHARE_RETURN_COLS, attr_subtitle, 0, 0, 2, - _("Price per\nshare (%s)"), lconvinfo.currency_symbol); + /* TRANSLATORS: "Price per share" is a two-line column + label in a table containing the price per share in + any given company. %s is the currency symbol in the + current locale. The maximum column width is 12 + characters INCLUDING the currency symbol (see + SHARE_PRICE_COLS in src/intf.h). */ + pgettext("subtitle", "Price per\nshare (%s)"), + lconvinfo.currency_symbol); for (line = 6, i = 0; i < MAX_COMPANIES; i++) { if (company[i].on_map) { @@ -731,24 +762,33 @@ void show_status (int num) int width, x; mkchstr(chbuf, BUFSIZE, attr_highlight, 0, 0, 1, w / 2, &width, 1, - _("Total value: ")); + /* TRANSLATORS: The "Total value", "Current cash", + "Current debt" and "Interest rate" labels MUST all be + the same length (ie, right-padded with spaces as + needed) and must have at least one trailing space so + that the display routines work correctly. The maximum + length of each label is 36 characters. + + Note that some of these labels are used for both the + Player Status window and the Trading Bank window. */ + pgettext("label", "Total value: ")); x = (w + width - (TOTAL_VALUE_COLS + 2)) / 2; right(curwin, line, x, attr_normal, attr_highlight, 0, 1, - _("Current cash: ")); + pgettext("label", "Current cash: ")); right(curwin, line, x + TOTAL_VALUE_COLS + 2, attr_normal, attr_highlight, 0, 1, " ^{%N^} ", player[num].cash); line++; if (player[num].debt != 0.0) { right(curwin, line, x, attr_normal, attr_highlight, 0, 1, - _("Current debt: ")); + pgettext("label", "Current debt: ")); right(curwin, line, x + TOTAL_VALUE_COLS + 2, attr_normal, attr_highlight, 0, 1, " ^{%N^} ", player[num].debt); line++; right(curwin, line, x, attr_normal, attr_highlight, 0, 1, - _("Interest rate: ")); + pgettext("label", "Interest rate: ")); right(curwin, line, x + TOTAL_VALUE_COLS + 2, attr_normal, attr_highlight, 0, 1, " ^{%.2f%%^} ", interest_rate * 100.0); line++; diff --git a/src/globals.c b/src/globals.c index 7c7269b..b61a9f7 100644 --- a/src/globals.c +++ b/src/globals.c @@ -41,7 +41,8 @@ const char *company_name[MAX_COMPANIES] = { /* TRANSLATORS: The eight company names do NOT have to be literal translations of the English names. In fact, if possible, the names should start with successive letters of your alphabet (in - English, "A" to "H"). */ + English, "A" to "H"). No company name should be more than 24 + characters (column positions, to be precise) long. */ N_("Altair Starways"), N_("Betelgeuse, Ltd"), N_("Capella Freight Co"), diff --git a/src/intf.c b/src/intf.c index 2b9d7f5..7546068 100644 --- a/src/intf.c +++ b/src/intf.c @@ -2368,9 +2368,12 @@ bool answer_yesno (WINDOW *win) wattron(win, A_BOLD); if (key == 'Y') { - waddstr(win, _("Yes")); + /* TRANSLATORS: The strings "Yes" and "No" are printed as a + response to user input in answer to questions like "Are you + sure? [Y/N] " */ + waddstr(win, pgettext("answer", "Yes")); } else { - waddstr(win, _("No")); + waddstr(win, pgettext("answer", "No")); } wbkgdset(win, oldbkgd); diff --git a/src/move.c b/src/move.c index fe1ae42..14bab95 100644 --- a/src/move.c +++ b/src/move.c @@ -257,7 +257,11 @@ selection_t get_move (void) curs_set(CURS_OFF); left(curwin, 1, getmaxx(curwin) / 2, attr_normal, attr_choice, - 0, 1, _("Move ^{%c^}"), key); + 0, 1, + /* TRANSLATORS: "Move" refers to the choice of moves + made by the current player (out of a selection of + 20 moves). */ + _("Move ^{%c^}"), key); } else { switch (key) { case '1': @@ -774,8 +778,16 @@ void merge_companies (map_val_t a, map_val_t b) &width_bb, 1, "%s", company[bb].name); chbuf_bb = chstrdup(chbuf, BUFSIZE); - mkchstr(chbuf, BUFSIZE, attr_normal, 0, 0, 1, getmaxx(curwin) / 2, &width, - 1, _("Old stock: ")); + mkchstr(chbuf, BUFSIZE, attr_normal, 0, 0, 1, getmaxx(curwin) / 2, + &width, 1, + /* TRANSLATORS: "Old stock" refers to the company that has + just ceased existence due to a merger. + + Note that the "Old stock" and "New stock" labels MUST be + the same length and must contain a trailing space for the + display routines to work correctly. The maximum length of + each label is 36 characters. */ + pgettext("label", "Old stock: ")); w = getmaxx(curwin); x = (w + width - MAX(width_aa, width_bb)) / 2; @@ -783,19 +795,43 @@ void merge_companies (map_val_t a, map_val_t b) rightch(curwin, lines + 3, x, chbuf, 1, &width); leftch(curwin, lines + 3, x, chbuf_bb, 1, &width_bb); - right(curwin, lines + 4, x, attr_normal, 0, 0, 1, _("New Stock: ")); + right(curwin, lines + 4, x, attr_normal, 0, 0, 1, + /* TRANSLATORS: "New stock" refers to the company that has + absorbed another due to a merger. */ + pgettext("label", "New Stock: ")); leftch(curwin, lines + 4, x, chbuf_aa, 1, &width_aa); mvwhline(curwin, lines + 6, 2, ' ' | attr_subtitle, w - 4); - left(curwin, lines + 6, 4, attr_subtitle, 0, 0, 1, _("Player")); + left(curwin, lines + 6, 4, attr_subtitle, 0, 0, 1, + /* TRANSLATORS: "Player" is used as a column title in a + table containing all player names. */ + pgettext("subtitle", "Player")); right(curwin, lines + 6, w - 4, attr_subtitle, 0, 0, 1, - _("Bonus (%s)"), lconvinfo.currency_symbol); - right(curwin, lines + 6, w - 6 - MERGE_BONUS_COLS, attr_subtitle, 0, 0, - 1, _("Total")); + /* TRANSLATORS: "Bonus" refers to the bonus cash amount paid to + each player after two companies merge. %s is the currency + symbol in the current locale. The maximum column width is + 12 characters INCLUDING the currency symbol (see + MERGE_BONUS_COLS in src/intf.h). */ + pgettext("subtitle", "Bonus (%s)"), + lconvinfo.currency_symbol); + right(curwin, lines + 6, w - 6 - MERGE_BONUS_COLS, attr_subtitle, 0, 0, 1, + /* TRANSLATORS: "Total" refers to the total number of shares in + the new company after a merger. The maximum column width is + 8 characters (see MERGE_TOTAL_STOCK_COLS in src/intf.h). */ + pgettext("subtitle", "Total")); right(curwin, lines + 6, w - 8 - MERGE_BONUS_COLS - MERGE_TOTAL_STOCK_COLS, - attr_subtitle, 0, 0, 1, _("New")); + attr_subtitle, 0, 0, 1, + /* TRANSLATORS: "New" refers to how many (new) shares each + player receives in the surviving company after a merger. + The maximum column width is 8 characters (see + MERGE_NEW_STOCK_COLS in src/intf.h). */ + pgettext("subtitle", "New")); right(curwin, lines + 6, w - 10 - MERGE_BONUS_COLS - MERGE_TOTAL_STOCK_COLS - - MERGE_NEW_STOCK_COLS, attr_subtitle, 0, 0, 1, _("Old")); + - MERGE_NEW_STOCK_COLS, attr_subtitle, 0, 0, 1, + /* TRANSLATORS: "Old" refers to how many shares each player had + in the company ceasing existence. The maximum column width + is 8 characters (see MERGE_OLD_STOCK_COLS in src/intf.h). */ + pgettext("subtitle", "Old")); total_new = 0; for (ln = lines + 7, i = 0; i < number_players; i++) { @@ -983,11 +1019,24 @@ void adjust_values (void) chbuf_amt = chstrdup(chbuf, BUFSIZE); mkchstr(chbuf, BUFSIZE, attr_error_normal, 0, 0, 1, w / 2, - &width, 1, _("Amount paid per share: ")); + &width, 1, + /* TRANSLATORS: The label "Amount paid per share" + refers to payment made by the Interstellar + Trading Bank to each player upon company + bankruptcy. This label MUST be the same + length as "Old share value" and MUST have at + least one trailing space for the display + routines to work correctly. The maximum + length is 28 characters. */ + pgettext("label", "Amount paid per share: ")); x = (w + width - width_amt) / 2; right(curwin, lines + 4, x, attr_error_normal, 0, 0, 1, - _("Old share value: ")); + /* TRANSLATORS: "Old share value" refers to the + share price of a company before it was forced + into bankruptcy by the Bank. This label must be + the same width as "Amount paid per share". */ + pgettext("label", "Old share value: ")); leftch(curwin, lines + 4, x, chbuf_amt, 1, &width_amt); rightch(curwin, lines + 5, x, chbuf, 1, &width); diff --git a/src/trader.c b/src/trader.c index 3eb23ce..459f008 100644 --- a/src/trader.c +++ b/src/trader.c @@ -336,14 +336,16 @@ playing that game. If GAME is not specified, start a new game.\n\n\ address or web URL for reporting bugs in your translation. */ printf(_("Report bugs to %s <%s>.\n"), PACKAGE_AUTHOR, PACKAGE_BUGREPORT); #else - /* TRANSLATORS: The %s is the e-mail address for reporting bugs. - As with the previous string, please add ANOTHER line with the + /* TRANSLATORS: %s is the e-mail address for reporting bugs. As + with the previous string, please add ANOTHER line with the (translated) text "Report translation bugs to
\n", with ADDRESS replaced with either an e-mail address or web URL for reporting bugs in your translation. */ printf(_("Report bugs to <%s>.\n"), PACKAGE_BUGREPORT); #endif #ifdef PACKAGE_PACKAGER_BUG_REPORTS + /* TRANSLATORS: The first %s is for packagers and may be + something like "Debian". */ printf(_("Report %s bugs to <%s>.\n"), PACKAGE_PACKAGER, PACKAGE_PACKAGER_BUG_REPORTS); #endif #ifdef PACKAGE_URL From c2a3c5ac8f3f59d98447cb6fb36e3eced263d630 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Wed, 17 Aug 2011 19:48:39 +1000 Subject: [PATCH 054/112] Require Gettext 0.18.1; regularise usage of Ncurses; update version --- INSTALL | 28 +++++++++++++++++----------- src/intf.h | 2 +- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/INSTALL b/INSTALL index 12ccce3..11b96e5 100644 --- a/INSTALL +++ b/INSTALL @@ -34,12 +34,18 @@ and installation: In actual fact, Star Traders uses the GNU Portability Library, so many older systems may also work without modification. -3. A working X/Open Curses-compatible library, such as NCurses. +3. A working X/Open Curses-compatible library, such as Ncurses. Ncurses + is preferred over system-native libraries, if present. -4. Development libraries and header files for all of the above. On many +4. The GNU Gettext library, version 0.18.1 or later, to allow the game to + use languages other than English; this is also called Native Language + Support. If you do not have this library (and do not wish to install + it), you may pass "--disable-nls" to the configure script. + +5. Development libraries and header files for all of the above. On many systems, these files are part of XXX-dev packages. -5. The GNU Perfect Hash Function Generator, gperf. This utility program +6. The GNU Perfect Hash Function Generator, gperf. This utility program is required for parts of the GNU Portability Library. @@ -63,13 +69,13 @@ command line options: --disable-nls Do not use Native Language Support --disable-assert Turn off all debugging assert() statements - --with-ncurses Force the use of NCurses over the system's Curses + --with-ncurses Force the use of Ncurses over the system's Curses library - --with-ncursesw Force the use of the NCursesW library with wide- + --with-ncursesw Force the use of the NcursesW library with wide- character support - --without-ncursesw Don't use the NCursesW library with wide-character + --without-ncursesw Don't use the NcursesW library with wide-character support - --without-ncurses Don't use the NCurses library: use the system's + --without-ncurses Don't use the Ncurses library: use the system's normal Curses library By default, configure uses "/usr/local" as the top-level (prefix) install @@ -94,12 +100,12 @@ You can also run configure in a separate build-only directory tree. This feature requires GNU Make and allows you to keep the source code tree from being modified by the compilation process. To use this option, create a separate build directory, then run configure. For example, if you placed -the Star Traders source code tree in $HOME/src/trader-7.0, you could run +the Star Traders source code tree in $HOME/src/trader-7.2, you could run something like: - mkdir /tmp/trader-build-7.0 - cd /tmp/trader-build-7.0 - $HOME/src/trader-7.0/configure + mkdir /tmp/trader-build-7.2 + cd /tmp/trader-build-7.2 + $HOME/src/trader-7.2/configure Once again, the Autoconf manual describes these options (and many others): diff --git a/src/intf.h b/src/intf.h index 00128d7..89c5791 100644 --- a/src/intf.h +++ b/src/intf.h @@ -108,7 +108,7 @@ typedef enum curs_type { #define KEY_DEFAULTVAL1 '=' #define KEY_DEFAULTVAL2 ';' -// Control-arrow key combinations, as returned by NCurses +// Control-arrow key combinations, as returned by Ncurses #ifndef KEY_CDOWN # define KEY_CDOWN 01007 // CTRL + Down Arrow # define KEY_CUP 01060 // CTRL + Up Arrow From 1c4cac2ba1d8ddb96250888377aeef049860bb55 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Wed, 17 Aug 2011 21:41:38 +1000 Subject: [PATCH 055/112] Add a detailed explanation of the help text markup format --- src/help.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++---- src/intf.c | 6 ++++- 2 files changed, 78 insertions(+), 6 deletions(-) diff --git a/src/help.c b/src/help.c index 57baea5..26e0c50 100644 --- a/src/help.c +++ b/src/help.c @@ -36,6 +36,55 @@ ************************************************************************/ static const char *help_text[] = { + + /* + TRANSLATORS: The help text for Star Traders is marked up using a + custom mark-up format NOT used anywhere else in the source code. + + Each string is a single page of text that is displayed in an area 76 + columns wide by 16 lines high. Ideally, each line within the string + should be (manually) space-justified or centred; each line is + separated by "\n". If a string starts with "@" as the very first + character, that string (and all strings following) are ignored: this + allows a variable number of help text pages (from one to twelve). + + The ASCII circumflex accent character "^" switches to a different + character rendition (also called attributes), depending on the + character following the "^": + + ^^ - Print the circumflex accent (ASCII code U+005E) + ^N - Switch to using the normal character rendition + ^B - Switch to using the bold character rendition + ^B - Switch to using the highlight character rendition + ^K - Switch to using the keycode character rendition (such as used for "") + ^e - Switch to using the character rendition used for empty space + ^o - Switch to using the character rendition used for outposts + ^s - Switch to using the character rendition used for stars + ^c - Switch to using the character rendition used for companies + ^k - Switch to using the character rendition used for keyboard choices on the galaxy map + + The help text parsing routines also understand the following "value + escapes" introduced by the ASCII tilde character "~": + + ~~ - Print the tilde character (ASCII code U+007E) [*] + ~x - Print the width of the galaxy map (MAX_X) [**] + ~y - Print the height of the galaxy map (MAX_Y) [**] + ~m - Print the number of moves available (NUMBER_MOVES) [**] + ~c - Print the maximum number of companies that can be formed (MAX_COMPANIES) [*] + ~t - Prints the default number of turns in the game (DEFAULT_MAX_TURN) [**] + ~1 to ~9 - Print the keycode for the N-th choice of move, appropriately localised [*] + ~M - Print the keycode for the last choice of move [*] + ~A to ~H - Print the character used to represent the company on the galaxy map, appropriately localised [*] + + [*] Takes one character space in the output + [**] Takes two character spaces in the output + + Note that the tilde value escapes do NOT change the current character + rendition: a circumflex accent escape is needed for that. For + example, to display the first choice of move as it would be shown on + the galaxy map, use something like "^k~1^N" (a six-character sequence + that would translate to just one character in the output text). + */ N_("" "^BStar Traders^N is a simple game of interstellar trading. The object of the\n" "game is to amass the greatest amount of wealth possible. This is done by\n" @@ -147,6 +196,15 @@ static const char *help_text[] = { "value of cash, stock and debt). ^HGood luck^N and may the best person win!\n" ""), +#ifdef ENABLE_NLS + N_("@ Help text, page 7"), + N_("@ Help text, page 8"), + N_("@ Help text, page 9"), + N_("@ Help text, page 10"), + N_("@ Help text, page 11"), + N_("@ Help text, page 12"), +#endif + NULL }; @@ -164,13 +222,17 @@ static const char *help_text[] = { void show_help (void) { int curpage = 0; - int numpages; + int numpages = 0; bool done = false; - // Count how many pages appear in the help text - for (numpages = 0; help_text[numpages] != NULL; numpages++) - ; + // Count how many pages appear in the (translated) help text + while (help_text[numpages] != NULL) { + const char *s = gettext(help_text[numpages]); + if (s == NULL || *s == '\0' || *s == '@') + break; + numpages++; + } if (numpages == 0) return; @@ -202,7 +264,7 @@ void show_help (void) break; case '^': - // Set the current attribute + // Switch to a different character rendition switch (*++s) { case '^': waddch(curwin, *s | curattr); @@ -333,6 +395,12 @@ void show_help (void) center(curwin, getmaxy(curwin) - 2, 0, attr_waitforkey, 0, 0, 1, (curpage == 0) ? _("[ Press to continue ] ") : + /* TRANSLATORS: The specific use of and + is not essential: you can use , + , , or instead of + , and almost any other key instead of + (other than , , , , + or <\>). */ _("[ Press to continue or " "for the previous page ] ")); wrefresh(curwin); diff --git a/src/intf.c b/src/intf.c index 7546068..abf9387 100644 --- a/src/intf.c +++ b/src/intf.c @@ -2397,7 +2397,11 @@ void wait_for_key (WINDOW *win, int y, chtype attr) meta(win, true); wtimeout(win, -1); - center(curwin, y, 0, attr, 0, 0, 1, _("[ Press to continue ] ")); + center(curwin, y, 0, attr, 0, 0, 1, + /* TRANSLATORS: The reason the user is not asked "Press any + key to continue" is historical: many, many people used to + ask "where is the key?" :-) */ + _("[ Press to continue ] ")); wrefresh(win); done = false; From 75503ab10324ba56a00fd0d0522ff2f6d8c082e9 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Wed, 17 Aug 2011 22:07:31 +1000 Subject: [PATCH 056/112] Parameterise answer_yesno() so that the input keycodes can be localised --- src/intf.c | 46 +++++++++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/src/intf.c b/src/intf.c index abf9387..bc7feb6 100644 --- a/src/intf.c +++ b/src/intf.c @@ -2327,39 +2327,47 @@ int gettxlong (WINDOW *win, long int *restrict result, long int min, bool answer_yesno (WINDOW *win) { - int key; - bool done; + static char *keys_yes; + static char *keys_no; + + bool ret; chtype oldattr = getattrs(win); chtype oldbkgd = getbkgd(win); + if (keys_yes == NULL) { + /* TRANSLATORS: The strings with msgctxt "input|Yes" and + "input|No" contain the keycodes used to determine whether a + user is answering "Yes" or "No" in response to some question. + Both upper and lower-case versions should be present. */ + keys_yes = xstrdup(pgettext("input|Yes", "Yy")); + keys_no = xstrdup(pgettext("input|No", "Nn")); + } + + keypad(win, true); meta(win, true); wtimeout(win, -1); curs_set(CURS_ON); - done = false; - while (! done) { - key = wgetch(win); + while (true) { + int key = wgetch(win); - switch (key) { - case 'Y': - case 'y': - case 'N': - case 'n': - key = toupper(key); - done = true; + if (strchr(keys_yes, key) != NULL) { + ret = true; break; - + } else if (strchr(keys_no, key) != NULL) { + ret = false; + break; + } else #ifdef HANDLE_RESIZE_EVENTS - case KEY_RESIZE: + if (key == KEY_RESIZE) { txresize(); - break; + } else #endif // HANDLE_RESIZE_EVENTS - - default: + { beep(); } } @@ -2367,7 +2375,7 @@ bool answer_yesno (WINDOW *win) curs_set(CURS_OFF); wattron(win, A_BOLD); - if (key == 'Y') { + if (ret) { /* TRANSLATORS: The strings "Yes" and "No" are printed as a response to user input in answer to questions like "Are you sure? [Y/N] " */ @@ -2380,7 +2388,7 @@ bool answer_yesno (WINDOW *win) wattrset(win, oldattr); wrefresh(win); - return (key == 'Y'); + return ret; } From e87c6ce9b341e370e8e1b585305949f8eb257031 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Wed, 17 Aug 2011 22:27:51 +1000 Subject: [PATCH 057/112] Allow input keycodes in ask_number_players() to be localised --- src/game.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/src/game.c b/src/game.c index 881eb7f..7c4fbc2 100644 --- a/src/game.c +++ b/src/game.c @@ -238,6 +238,7 @@ void init_game (void) static int ask_number_players (void) { + char *keys_contgame; chtype *chbuf; int lines, maxwidth; int widthbuf[2]; @@ -248,6 +249,9 @@ static int ask_number_players (void) chbuf = xmalloc(BUFSIZE * sizeof(chtype)); lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_keycode, 0, 2, WIN_COLS - 7, widthbuf, 2, + /* TRANSLATORS: The keycode should be modified to + match that (or those) specified with msgctxt + "input|ContinueGame". */ _("Enter number of players [^{1^}-^{%d^}] " "or ^{^} to continue a game: "), MAX_PLAYERS); assert(lines == 1 || lines == 2); @@ -260,14 +264,25 @@ static int ask_number_players (void) curs_set(CURS_ON); wrefresh(curwin); + /* TRANSLATORS: This string specifies the keycodes used to continue a + game; these must NOT contain any numeric digit from 1 to 9. The + first character (keyboard input code) is used to print the user's + response if one of those keys is pressed. Both upper and + lower-case versions should be present. */ + keys_contgame = xstrdup(pgettext("input|ContinueGame", "Cc")); + done = false; while (! done) { - key = toupper(gettxchar(curwin)); + key = gettxchar(curwin); if (key >= '1' && key <= MAX_PLAYERS + '0') { wechochar(curwin, key | A_BOLD); ret = key - '0'; done = true; + } else if (strchr(keys_contgame, key) != NULL) { + wechochar(curwin, ((unsigned char) *keys_contgame) | A_BOLD); + ret = 0; + done = true; } else { switch (key) { case KEY_ESC: @@ -280,12 +295,6 @@ static int ask_number_players (void) done = true; break; - case 'C': - wechochar(curwin, key | A_BOLD); - ret = 0; - done = true; - break; - default: beep(); } @@ -293,6 +302,7 @@ static int ask_number_players (void) } curs_set(CURS_OFF); + free(keys_contgame); return ret; } From a024ad83e7f03ab48a01acd17daa7d7ae5230d2f Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Thu, 18 Aug 2011 09:10:38 +1000 Subject: [PATCH 058/112] Update help text company letter; clarify tilde escapes in general --- src/help.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/help.c b/src/help.c index 26e0c50..404f5c2 100644 --- a/src/help.c +++ b/src/help.c @@ -64,7 +64,8 @@ static const char *help_text[] = { ^k - Switch to using the character rendition used for keyboard choices on the galaxy map The help text parsing routines also understand the following "value - escapes" introduced by the ASCII tilde character "~": + escapes" introduced by the ASCII tilde character "~"; these act like + "%" conversion specifiers in printf(): ~~ - Print the tilde character (ASCII code U+007E) [*] ~x - Print the width of the galaxy map (MAX_X) [**] @@ -153,7 +154,7 @@ static const char *help_text[] = { "\n" "You can also expand any company by selecting positions next to outposts.\n" "Such outposts will be swallowed up by that company. Thus, move ^k~1^N will\n" - "extend Company ^BC^N by ^Btwo^N squares. As a bonus, outposts next to stars are\n" + "extend Company ^B~C^N by ^Btwo^N squares. As a bonus, outposts next to stars are\n" "more valuable: the company's share price will increase by a greater amount\n" "than it would for outposts not next to stars.\n" ""), From 6ef7c7b6da192bebd7db78d8919c43f21e2903a1 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Thu, 18 Aug 2011 12:10:33 +1000 Subject: [PATCH 059/112] Allow localisation of company letters and map moves (choices) --- src/exch.c | 28 +++++++++--- src/game.c | 54 +++++++++++++++++++++--- src/globals.c | 51 ++++++++++++++++++++++ src/globals.h | 31 ++++++++++---- src/help.c | 115 +++++++++++++++++++++++++++++--------------------- src/help.h | 5 ++- src/intf.c | 14 +++--- src/move.c | 42 ++++++++++++------ 8 files changed, 251 insertions(+), 89 deletions(-) diff --git a/src/exch.c b/src/exch.c index b9f0392..c5c5552 100644 --- a/src/exch.c +++ b/src/exch.c @@ -196,15 +196,29 @@ void exchange_stock (void) // Get the actual selection made by the player while (selection == SEL_NONE) { - int key = toupper(gettxchar(curwin)); + bool found; - if (IS_COMPANY_KEY(key)) { - if (company[KEY_TO_COMPANY(key)].on_map) { - selection = KEY_TO_COMPANY(key); - } else { - beep(); + int key = gettxchar(curwin); + + if (isupper(*keycode_company)) { + key = toupper(key); + } else if (islower(*keycode_company)) { + key = tolower(key); + } + + for (i = 0, found = false; keycode_company[i] != '\0'; i++) { + if (keycode_company[i] == key) { + found = true; + if (company[i].on_map) { + selection = i; + } else { + beep(); + } + break; } - } else { + } + + if (! found) { switch (key) { case '1': curs_set(CURS_OFF); diff --git a/src/game.c b/src/game.c index 7c4fbc2..db0cd29 100644 --- a/src/game.c +++ b/src/game.c @@ -108,6 +108,48 @@ static int cmp_player (const void *a, const void *b); void init_game (void) { + /* Initialise strings used for keycode input and map representations. + + Each string must have an ASCII vertical line (U+007C) in the + correct position, followed by context information (such as + "input|Company" and "output|MapVals"). This is done to overcome a + limitation of gettext_noop() and N_() that does NOT allow context + IDs. This vertical line is replaced by a NUL character to + terminate the resulting string. The vertical line MAY appear in + other positions; if so, it is handled correctly. */ + + keycode_company = xstrdup(gettext(default_keycode_company)); + if (strlen(keycode_company) < MAX_COMPANIES + 1 + || keycode_company[MAX_COMPANIES] != '|') { + err_exit(_("keycode string for companies has incorrect format: `%s'"), + keycode_company); + } + keycode_company[MAX_COMPANIES] = '\0'; + + keycode_game_move = xstrdup(gettext(default_keycode_game_move)); + if (strlen(keycode_game_move) < NUMBER_MOVES + 1 + || keycode_game_move[NUMBER_MOVES] != '|') { + err_exit(_("keycode string for game moves has incorrect format: `%s'"), + keycode_game_move); + } + keycode_game_move[NUMBER_MOVES] = '\0'; + + printable_map_val = xstrdup(gettext(default_printable_map_val)); + if (strlen(printable_map_val) < MAX_COMPANIES + 4 + || printable_map_val[MAX_COMPANIES + 3] != '|') { + err_exit(_("output string for companies has incorrect format: `%s'"), + printable_map_val); + } + printable_map_val[MAX_COMPANIES + 3] = '\0'; + + printable_game_move = xstrdup(gettext(default_printable_game_move)); + if (strlen(printable_game_move) < NUMBER_MOVES + 1 + || printable_game_move[NUMBER_MOVES] != '|') { + err_exit(_("output string for game moves has incorrect format: `%s'"), + printable_game_move); + } + printable_game_move[NUMBER_MOVES] = '\0'; + // Try to load an old game, if possible if (game_num != 0) { chtype *chbuf = xmalloc(BUFSIZE * sizeof(chtype)); @@ -238,7 +280,7 @@ void init_game (void) static int ask_number_players (void) { - char *keys_contgame; + char *keycode_contgame; chtype *chbuf; int lines, maxwidth; int widthbuf[2]; @@ -269,7 +311,7 @@ static int ask_number_players (void) first character (keyboard input code) is used to print the user's response if one of those keys is pressed. Both upper and lower-case versions should be present. */ - keys_contgame = xstrdup(pgettext("input|ContinueGame", "Cc")); + keycode_contgame = xstrdup(pgettext("input|ContinueGame", "Cc")); done = false; while (! done) { @@ -279,8 +321,8 @@ static int ask_number_players (void) wechochar(curwin, key | A_BOLD); ret = key - '0'; done = true; - } else if (strchr(keys_contgame, key) != NULL) { - wechochar(curwin, ((unsigned char) *keys_contgame) | A_BOLD); + } else if (strchr(keycode_contgame, key) != NULL) { + wechochar(curwin, ((unsigned char) *keycode_contgame) | A_BOLD); ret = 0; done = true; } else { @@ -302,7 +344,7 @@ static int ask_number_players (void) } curs_set(CURS_OFF); - free(keys_contgame); + free(keycode_contgame); return ret; } @@ -687,6 +729,8 @@ void show_status (int num) val = total_value(num); if (val == 0.0) { center(curwin, 11, 0, attr_normal, attr_highlight, attr_blink, 1, + /* TRANSLATORS: The current player is bankrupt (has no + shares or cash, ie, whose total value is zero) */ _("^[* * * B A N K R U P T * * *^]")); } else { w = getmaxx(curwin); diff --git a/src/globals.c b/src/globals.c index b61a9f7..9a0e602 100644 --- a/src/globals.c +++ b/src/globals.c @@ -54,6 +54,52 @@ const char *company_name[MAX_COMPANIES] = { }; +// Default keycodes (keyboard input characters) for each company +const char *default_keycode_company = + /* TRANSLATORS: This string specifies the keycodes (keyboard input + codes) used to enter the Stock Transaction window for each + company. There must be exactly eight characters, one for each + company in order, before the ASCII vertical line "|"; these must + be EITHER all in upper-case or all in lower-case. If at all + possible, these should be successive letters in your alphabet (in + English, "A" to "H"). Do NOT use digits or control characters. + Do not change or translate anything after the vertical line. */ + N_("ABCDEFGH|input|Companies"); + + +// Default keycodes (keyboard input characters) for each move +const char *default_keycode_game_move = + /* TRANSLATORS: This string specifies the keycodes used to select a + game move. There must be exactly 20 characters, one for each + move, before the ASCII vertical line "|"; these must be EITHER all + in upper-case or all in lower-case. If at all possible, these + should be successive letters in your alphabet. Do NOT use digits + or control characters. Do not change or translate anything after + the vertical line. */ + N_("ABCDEFGHIJKLMNOPQRST|input|GameMoves"); + + +// Default printable output representations for each map element +const char *default_printable_map_val = + /* TRANSLATORS: This string is used to display the galaxy map to + screen. There must be exactly 11 characters before the ASCII + vertical line. The first ("." in English) is used for empty + space, the second ("+") for outposts, the third ("*") for stars, + the remaining for the eight companies. Do not change or translate + anything after the vertical line. */ + N_(".+*ABCDEFGH|output|MapVals"); + + +// Default printable output representations for each move +const char *default_printable_game_move = + /* TRANSLATORS: This string is used to display the game moves + (choices). There must be exactly 20 characters before the ASCII + vertical line. The first character corresponds to the first + character in the "input|GameMoves" string, and so on. Do not + change or translate anything after the vertical line. */ + N_("abcdefghijklmnopqrst|output|GameMoves"); + + // Ordinal strings const char *ordinal[MAX_PLAYERS + 1] = { "", @@ -82,6 +128,11 @@ player_info_t player[MAX_PLAYERS]; // Array of players map_val_t galaxy_map[MAX_X][MAX_Y]; // Map of the galaxy move_rec_t game_move[NUMBER_MOVES]; // Current moves +char *keycode_company; // Keycodes for each company +char *keycode_game_move; // Keycodes for each game move +char *printable_map_val; // Printable output for each map value +char *printable_game_move; // Printable output for each game move + int max_turn; // Max. number of turns in game int turn_number; // Current turn (1 to max_turn) int number_players; // Number of players diff --git a/src/globals.h b/src/globals.h index db19be3..b6d393f 100644 --- a/src/globals.h +++ b/src/globals.h @@ -130,11 +130,11 @@ typedef enum map_val { #define MAP_TO_COMPANY(m) ((m) - MAP_A) #define IS_MAP_COMPANY(m) ((m) >= MAP_A && (m) <= MAP_LAST) -#define PRINTABLE_MAP_VAL(m) ((char) (m)) - -#define COMPANY_TO_KEY(i) ((i) + 'A') -#define KEY_TO_COMPANY(k) ((k) - 'A') -#define IS_COMPANY_KEY(k) ((k) >= 'A' && (k) < COMPANY_TO_KEY(MAX_COMPANIES)) +#define PRINTABLE_MAP_VAL(m) \ + (((m) == MAP_EMPTY) ? printable_map_val[0] : \ + (((m) == MAP_OUTPOST) ? printable_map_val[1] : \ + (((m) == MAP_STAR) ? printable_map_val[2] : \ + printable_map_val[(m) - MAP_A + 3]))) // Information about a move @@ -143,9 +143,7 @@ typedef struct move_rec { int y; } move_rec_t; -#define MOVE_TO_KEY(m) ((m) + 'a') -#define KEY_TO_MOVE(k) ((k) - 'a') -#define IS_MOVE_KEY(k) ((k) >= 'a' && (k) < MOVE_TO_KEY(NUMBER_MOVES)) +#define PRINTABLE_GAME_MOVE(m) (printable_game_move[m]) // Player moves / selection values @@ -170,6 +168,18 @@ typedef enum selection { // Company names extern const char *company_name[MAX_COMPANIES]; +// Default keycodes (keyboard input characters) for each company +extern const char *default_keycode_company; + +// Default keycodes (keyboard input characters) for each move +extern const char *default_keycode_game_move; + +// Default printable output representations for each map element +extern const char *default_printable_map_val; + +// Default printable output representations for each move +extern const char *default_printable_game_move; + // Ordinal strings extern const char *ordinal[MAX_PLAYERS + 1]; @@ -183,6 +193,11 @@ extern player_info_t player[MAX_PLAYERS]; // Array of players extern map_val_t galaxy_map[MAX_X][MAX_Y]; // Map of the galaxy extern move_rec_t game_move[NUMBER_MOVES]; // Current moves +extern char *keycode_company; // Keycodes for each company +extern char *keycode_game_move; // Keycodes for each game move +extern char *printable_map_val; // Printable output for each map value +extern char *printable_game_move; // Printable output for each game move + extern int max_turn; // Max. number of turns in game extern int turn_number; // Current turn (1 to max_turn) extern int number_players; // Number of players diff --git a/src/help.c b/src/help.c index 404f5c2..e95ae21 100644 --- a/src/help.c +++ b/src/help.c @@ -44,9 +44,10 @@ static const char *help_text[] = { Each string is a single page of text that is displayed in an area 76 columns wide by 16 lines high. Ideally, each line within the string should be (manually) space-justified or centred; each line is - separated by "\n". If a string starts with "@" as the very first - character, that string (and all strings following) are ignored: this - allows a variable number of help text pages (from one to twelve). + separated by "\n". TAB characters and other control codes must NOT + be used. If a string starts with "@" as the very first character, + that string (and all strings following) are ignored: this allows a + variable number of help text pages (from one to twelve). The ASCII circumflex accent character "^" switches to a different character rendition (also called attributes), depending on the @@ -73,18 +74,23 @@ static const char *help_text[] = { ~m - Print the number of moves available (NUMBER_MOVES) [**] ~c - Print the maximum number of companies that can be formed (MAX_COMPANIES) [*] ~t - Prints the default number of turns in the game (DEFAULT_MAX_TURN) [**] - ~1 to ~9 - Print the keycode for the N-th choice of move, appropriately localised [*] + ~1 to ~9 - Print the keycode for the N-th choice of move [*] ~M - Print the keycode for the last choice of move [*] - ~A to ~H - Print the character used to represent the company on the galaxy map, appropriately localised [*] + ~A to ~H - Print the character used to represent the company on the galaxy map [*] + ~. - Print the character used to represent empty space on the map [*] + ~+ - Print the character used to represent outposts on the map [*] + ~* - Print the character used to represent stars on the map [*] [*] Takes one character space in the output [**] Takes two character spaces in the output - Note that the tilde value escapes do NOT change the current character - rendition: a circumflex accent escape is needed for that. For - example, to display the first choice of move as it would be shown on - the galaxy map, use something like "^k~1^N" (a six-character sequence - that would translate to just one character in the output text). + Note that all keycodes and map representation characters use locale- + specific characters. Note also that the tilde value escapes do NOT + change the current character rendition: a circumflex accent escape is + needed for that. For example, to display the first choice of move as + it would be shown on the galaxy map, use something like "^k~1^N" (a + six-character sequence that would translate to just one character in + the output text). */ N_("" "^BStar Traders^N is a simple game of interstellar trading. The object of the\n" @@ -98,47 +104,47 @@ static const char *help_text[] = { "The map of the galaxy is represented by a ^B~x^N x ^B~y^N grid. A typical section\n" "of it may be:\n" "\n" - " ^e . . ^s*^e . . . ^s*^e ^s*^e . ^N\n" - " ^e . . . . . . . . . ^N ^e . ^N represents ^Bempty space^N,\n" - " ^e . ^s*^e . . . . . . . ^N ^s * ^N represents a ^Bstar^N.\n" - " ^e . . . . . . . ^s*^e . ^N\n" - " ^e . . . . ^s*^e . . . . ^N\n" + " ^e ~. ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" + " ^e ~. ~. ~. ~. ~. ~. ~. ~. ~. ^N ^e ~. ^N represents ^Bempty space^N,\n" + " ^e ~. ^s~*^e ~. ~. ~. ~. ~. ~. ~. ^N ^s ~* ^N represents a ^Bstar^N.\n" + " ^e ~. ~. ~. ~. ~. ~. ~. ^s~*^e ~. ^N\n" + " ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ~. ^N\n" ""), N_("" "The computer selects ^B~m^N moves (labeled ^k~1^N to ^k~M^N) at random, and places these\n" "on the map. To select any of the highlighted positions, press that letter.\n" - "As an example, some of the moves on the map may be:\n" + "For example, some of the moves on the map may be:\n" "\n" "\n" - " ^e ^k~1^e . ^s*^e . . . ^s*^e ^s*^e . ^N\n" - " ^e . . . ^k~3^e . . . . . ^N\n" - " ^e . ^s*^e . . . . ^k~5^e . . ^N Moves ^k~1^N to ^k~5^N shown.\n" - " ^e . ^k~2^e . . ^k~4^e . . ^s*^e . ^N\n" - " ^e . . . . ^s*^e . . . . ^N\n" + " ^e ^k~1^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" + " ^e ~. ~. ~. ^k~3^e ~. ~. ~. ~. ~. ^N\n" + " ^e ~. ^s~*^e ~. ~. ~. ~. ^k~5^e ~. ~. ^N Moves ^k~1^N to ^k~5^N shown.\n" + " ^e ~. ^k~2^e ~. ~. ^k~4^e ~. ~. ^s~*^e ~. ^N\n" + " ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ~. ^N\n" "\n" "\n" "Selecting a position that is ^Bnot^N next to a star (such as moves ^k~1^N, ^k~3^N or ^k~5^N)\n" - "will set up an ^Boutpost^N, not belonging to any company. Thus, if move ^k~3^N was\n" - "selected on the above map, a ^o + ^N would be placed at that position.\n" + "will set up an ^Boutpost^N, not belonging to any company. Thus, if move ^k~3^N is\n" + "selected on the above map, a ^o ~+ ^N would be placed at that position.\n" ""), N_("" "If, on the other hand, a position next to a star (or another outpost) is\n" - "selected, a ^Bcompany^N would be formed and its first letter would appear on the\n" - "map. As a reward for creating the company, you are granted the first five\n" - "shares. Up to ^B~c^N companies can be created in this way.\n" + "selected, a ^Bcompany^N would be formed and its letter would appear on the map.\n" + "As a reward for creating the company, you are granted the first five shares.\n" + "Up to ^B~c^N companies can be created in this way.\n" "\n" "If a position next to an existing company is selected, the company would\n" "expand its operations by one square. This increases the cost of its shares\n" "and hence your return. Thus, if the map was as shown below, selecting ^k~6^N\n" "or ^k~8^N increases Company ^B~B^N's shipping lane:\n" "\n" - " ^e ^k~1^e . ^s*^e . . . ^s*^e ^s*^e . ^N\n" - " ^e . . . ^o+^e . . ^k~6^e . . ^N\n" - " ^e . ^s*^e . . . . ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~6^N or ^k~8^N increases Company ^B~B^N.\n" - " ^e . ^k~2^e . . ^k~4^e . . ^s*^e ^c~B^e ^N\n" - " ^e . . . . ^s*^e . . . ^k~8^e ^N\n" + " ^e ^k~1^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" + " ^e ~. ~. ~. ^o~+^e ~. ~. ^k~6^e ~. ~. ^N\n" + " ^e ~. ^s~*^e ~. ~. ~. ~. ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~6^N or ^k~8^N increases Company ^B~B^N.\n" + " ^e ~. ^k~2^e ~. ~. ^k~4^e ~. ~. ^s~*^e ^c~B^e ^N\n" + " ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ^k~8^e ^N\n" ""), N_("" @@ -146,13 +152,13 @@ static const char *help_text[] = { "five times as much as an extension not next to a star. Thus move ^k~6^N should\n" "be preferred to move ^k~8^N.\n" "\n" - " ^e ^c~C^e . ^s*^e . . . ^s*^e ^s*^e . ^N\n" - " ^e ^k~1^e ^o+^e . ^o+^e . . ^k~6^e . . ^N\n" - " ^e . ^s*^e . . . . ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~6^N is preferred to ^k~8^N.\n" - " ^e . ^k~2^e . . ^k~4^e . . ^s*^e ^c~B^e ^N\n" - " ^e . . . . ^s*^e . . . ^k~8^e ^N\n" + " ^e ^c~C^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" + " ^e ^k~1^e ^o~+^e ~. ^o~+^e ~. ~. ^k~6^e ~. ~. ^N\n" + " ^e ~. ^s~*^e ~. ~. ~. ~. ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~6^N is preferred to ^k~8^N.\n" + " ^e ~. ^k~2^e ~. ~. ^k~4^e ~. ~. ^s~*^e ^c~B^e ^N\n" + " ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ^k~8^e ^N\n" "\n" - "You can also expand any company by selecting positions next to outposts.\n" + "You may also expand any company by selecting positions next to outposts.\n" "Such outposts will be swallowed up by that company. Thus, move ^k~1^N will\n" "extend Company ^B~C^N by ^Btwo^N squares. As a bonus, outposts next to stars are\n" "more valuable: the company's share price will increase by a greater amount\n" @@ -167,11 +173,11 @@ static const char *help_text[] = { "other one. Here, Company ^B~B^N might take over Company ^B~A^N. Company ^B~A^N ceases to\n" "exist, although it may reappear as an entirely new company at a later stage.\n" "\n" - " ^e ^k~1^e . ^s*^e . . . ^s*^e ^s*^e . ^N\n" - " ^e . . . ^c~A^e ^c~A^e ^k~5^e ^c~B^e . . ^N\n" - " ^e . ^s*^e . . ^c~A^e . ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~5^N merges companies ^B~A^N and ^B~B^N.\n" - " ^e . ^k~2^e . . . . . ^s*^e ^c~B^e ^N\n" - " ^e . . . . ^s*^e . ^o+^e . . ^N\n" + " ^e ^k~1^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" + " ^e ~. ~. ~. ^c~A^e ^c~A^e ^k~5^e ^c~B^e ~. ~. ^N\n" + " ^e ~. ^s~*^e ~. ~. ^c~A^e ~. ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~5^N merges companies ^B~A^N and ^B~B^N.\n" + " ^e ~. ^k~2^e ~. ~. ~. ~. ~. ^s~*^e ^c~B^e ^N\n" + " ^e ~. ~. ~. ~. ^s~*^e ~. ^o~+^e ~. ~. ^N\n" "\n" "When companies merge, players are granted shares in the dominant company\n" "proportional to the amount owned in the old company. As well, a cash bonus\n" @@ -180,13 +186,13 @@ static const char *help_text[] = { N_("" "Once you select your move, you enter the ^BInterstellar Stock Exchange^N. Here\n" - "you can purchase shares, sell them, borrow from the Trading Bank or repay\n" + "you may purchase shares, sell them, borrow from the Trading Bank or repay\n" "some of your debt (if applicable). Note that each company issues a limited\n" - "number of shares --- you cannot go on buying for ever! You can, however,\n" + "number of shares --- you cannot go on buying for ever! You may, however,\n" "bid for more shares to be issued. You have a better chance of succeeding if\n" "you own a larger proportion of the company.\n" "\n" - "The game usually ends after ^B~t^N turns. However, you can end the game sooner\n" + "The game usually ends after ^B~t^N turns. However, you may end the game sooner\n" "by pressing ^K^N when asked to select a move. As well, individual\n" "players can declare themselves bankrupt at any time. If your debt is large\n" "enough, the Bank may do this for you! If you do not complete your game in\n" @@ -359,12 +365,27 @@ void show_help (void) case '8': case '9': // N-th choice of move, as a key press - wprintw(curwin, "%c", MOVE_TO_KEY(*s - '1')); + wprintw(curwin, "%c", PRINTABLE_GAME_MOVE(*s - '1')); break; case 'M': // Last choice of move, as a key press - wprintw(curwin, "%c", MOVE_TO_KEY(NUMBER_MOVES - 1)); + wprintw(curwin, "%c", PRINTABLE_GAME_MOVE(NUMBER_MOVES - 1)); + break; + + case '.': + // Map representation of empty space + wprintw(curwin, "%c", PRINTABLE_MAP_VAL(MAP_EMPTY)); + break; + + case '+': + // Map representation of an outpost + wprintw(curwin, "%c", PRINTABLE_MAP_VAL(MAP_OUTPOST)); + break; + + case '*': + // Map representation of a star + wprintw(curwin, "%c", PRINTABLE_MAP_VAL(MAP_STAR)); break; case 'A': diff --git a/src/help.h b/src/help.h index fa27634..ddb5998 100644 --- a/src/help.h +++ b/src/help.h @@ -42,8 +42,9 @@ Returns: (nothing) This function displays instructions on how to play Star Traders in a - Curses window. It does not depend on any global game variable. On - exit, the previous screen is restored and refreshed. + Curses window. It does not depend on any global game variables other + than printable_map_val[] and printable_game_move[]. On exit, the + previous screen is restored and refreshed. */ extern void show_help (void); diff --git a/src/intf.c b/src/intf.c index bc7feb6..03cf18f 100644 --- a/src/intf.c +++ b/src/intf.c @@ -2327,8 +2327,8 @@ int gettxlong (WINDOW *win, long int *restrict result, long int min, bool answer_yesno (WINDOW *win) { - static char *keys_yes; - static char *keys_no; + static char *keycode_yes; + static char *keycode_no; bool ret; @@ -2336,13 +2336,13 @@ bool answer_yesno (WINDOW *win) chtype oldbkgd = getbkgd(win); - if (keys_yes == NULL) { + if (keycode_yes == NULL) { /* TRANSLATORS: The strings with msgctxt "input|Yes" and "input|No" contain the keycodes used to determine whether a user is answering "Yes" or "No" in response to some question. Both upper and lower-case versions should be present. */ - keys_yes = xstrdup(pgettext("input|Yes", "Yy")); - keys_no = xstrdup(pgettext("input|No", "Nn")); + keycode_yes = xstrdup(pgettext("input|Yes", "Yy")); + keycode_no = xstrdup(pgettext("input|No", "Nn")); } @@ -2355,10 +2355,10 @@ bool answer_yesno (WINDOW *win) while (true) { int key = wgetch(win); - if (strchr(keys_yes, key) != NULL) { + if (strchr(keycode_yes, key) != NULL) { ret = true; break; - } else if (strchr(keys_no, key) != NULL) { + } else if (strchr(keycode_no, key) != NULL) { ret = false; break; } else diff --git a/src/move.c b/src/move.c index 14bab95..14fb280 100644 --- a/src/move.c +++ b/src/move.c @@ -220,7 +220,7 @@ selection_t get_move (void) // Display current move choices on the galaxy map for (int i = 0; i < NUMBER_MOVES; i++) { mvwaddch(curwin, game_move[i].y + 3, game_move[i].x * 2 + 2, - MOVE_TO_KEY(i) | attr_map_choice); + PRINTABLE_GAME_MOVE(i) | attr_map_choice); } wrefresh(curwin); @@ -243,26 +243,42 @@ selection_t get_move (void) right(curwin, 1, getmaxx(curwin) / 2, attr_normal, attr_keycode, attr_choice, 1, _("Select move [^[%c^]-^[%c^]/^{1^}-^{3^}/^{^}]: "), - MOVE_TO_KEY(0), MOVE_TO_KEY(NUMBER_MOVES - 1)); + PRINTABLE_GAME_MOVE(0), PRINTABLE_GAME_MOVE(NUMBER_MOVES - 1)); curs_set(CURS_ON); wrefresh(curwin); // Get the actual selection made by the player while (selection == SEL_NONE) { - int key = tolower(gettxchar(curwin)); + int i; + bool found; - if (IS_MOVE_KEY(key)) { - selection = KEY_TO_MOVE(key); + int key = gettxchar(curwin); - curs_set(CURS_OFF); - left(curwin, 1, getmaxx(curwin) / 2, attr_normal, attr_choice, - 0, 1, - /* TRANSLATORS: "Move" refers to the choice of moves - made by the current player (out of a selection of - 20 moves). */ - _("Move ^{%c^}"), key); - } else { + if (isupper(*keycode_game_move)) { + key = toupper(key); + } else if (islower(*keycode_game_move)) { + key = tolower(key); + } + + for (i = 0, found = false; keycode_game_move[i] != '\0'; i++) { + if (keycode_game_move[i] == key) { + found = true; + selection = i; + + curs_set(CURS_OFF); + left(curwin, 1, getmaxx(curwin) / 2, attr_normal, + attr_choice, 0, 1, + /* TRANSLATORS: "Move" refers to the choice of + moves made by the current player (out of a + selection of 20 moves). */ + _("Move ^{%c^}"), PRINTABLE_GAME_MOVE(i)); + + break; + } + } + + if (! found) { switch (key) { case '1': curs_set(CURS_OFF); From ef3e06ed36c8c26d175312f2b3a873dac56129e5 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Thu, 18 Aug 2011 12:53:23 +1000 Subject: [PATCH 060/112] Add the wchar and wctype-h modules from the GNU Portability Library --- lib/.gitignore | 2 ++ m4/.gitignore | 1 + m4/gnulib-cache.m4 | 4 +++- src/system.h | 2 ++ 4 files changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/.gitignore b/lib/.gitignore index 40cf3ec..3230f5b 100644 --- a/lib/.gitignore +++ b/lib/.gitignore @@ -91,6 +91,7 @@ verify.h vfprintf.c vsnprintf.c wchar.in.h +wctype.in.h xsize.h alloca.h @@ -119,6 +120,7 @@ unitypes.h unused-parameter.h warn-on-use.h wchar.h +wctype.h unistr/.dirstamp unistr/u8-mbtoucr.c diff --git a/m4/.gitignore b/m4/.gitignore index d9056c6..60c8caa 100644 --- a/m4/.gitignore +++ b/m4/.gitignore @@ -98,5 +98,6 @@ vsnprintf.m4 warn-on-use.m4 wchar_h.m4 wchar_t.m4 +wctype_h.m4 wint_t.m4 xsize.m4 diff --git a/m4/gnulib-cache.m4 b/m4/gnulib-cache.m4 index 94ec404..4608fa9 100644 --- a/m4/gnulib-cache.m4 +++ b/m4/gnulib-cache.m4 @@ -15,7 +15,7 @@ # Specification in the form of a command-line invocation: -# gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --no-conditional-dependencies --no-libtool --macro-prefix=gl assert config-h ctype fprintf-posix getopt-gnu gettext gettext-h gettimeofday langinfo locale printf-posix sigaction signal snprintf-posix stat stdarg stdbool stdio strdup-posix striconv string strncat strstr sys_stat sys_time unistd vfprintf-posix vsnprintf-posix +# gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --no-conditional-dependencies --no-libtool --macro-prefix=gl assert config-h ctype fprintf-posix getopt-gnu gettext gettext-h gettimeofday langinfo locale printf-posix sigaction signal snprintf-posix stat stdarg stdbool stdio strdup-posix striconv string strncat strstr sys_stat sys_time unistd vfprintf-posix vsnprintf-posix wchar wctype-h # Specification in the form of a few gnulib-tool.m4 macro invocations: gl_LOCAL_DIR([]) @@ -48,6 +48,8 @@ gl_MODULES([ unistd vfprintf-posix vsnprintf-posix + wchar + wctype-h ]) gl_AVOID([]) gl_SOURCE_BASE([lib]) diff --git a/src/system.h b/src/system.h index 7ea4458..4b1732a 100644 --- a/src/system.h +++ b/src/system.h @@ -59,6 +59,8 @@ #include #include #include +#include +#include // Headers defined by X/Open Single Unix Specification v4 From bee30b73436d5f73c9ef3e79a270ee805af8cb48 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Thu, 18 Aug 2011 12:56:21 +1000 Subject: [PATCH 061/112] Ignore additional files in the po subdirectory Yes, trader.pot should be ignored: it is autogenerated from the source code. --- .gitignore | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.gitignore b/.gitignore index 1219d12..8f5607d 100644 --- a/.gitignore +++ b/.gitignore @@ -29,6 +29,12 @@ TAGS /build-aux/snippet/warn-on-use.h /po/POTFILES +/po/en@quot.gmo +/po/en@quot.insert-header +/po/en@quot.po +/po/messages.mo /po/remove-potcdate.sed +/po/stamp-po +/po/trader.pot /src/trader From 4d6f1478e6264468107ae705e510afe283e88298 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Thu, 18 Aug 2011 14:53:03 +1000 Subject: [PATCH 062/112] Remove the superfluous argument to chstrdup() This argument is not required: we KNOW that we have initialised chtype arrays with an ending NUL! --- src/exch.c | 4 ++-- src/intf.c | 4 ++-- src/intf.h | 3 +-- src/move.c | 6 +++--- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/exch.c b/src/exch.c index c5c5552..19ff2d0 100644 --- a/src/exch.c +++ b/src/exch.c @@ -412,7 +412,7 @@ void visit_bank (void) mkchstr(chbuf, BUFSIZE, attr_normal, attr_normal | A_BOLD, 0, 1, getmaxx(curwin) / 2, &width_cursym, 1, "^{%s^}", lconvinfo.currency_symbol); - chbuf_cursym = chstrdup(chbuf, BUFSIZE); + chbuf_cursym = chstrdup(chbuf); mkchstr(chbuf, BUFSIZE, attr_normal, 0, 0, 1, getmaxx(curwin) - BANK_INPUT_COLS - width_cursym - 6, &width, 1, @@ -470,7 +470,7 @@ void visit_bank (void) mkchstr(chbuf, BUFSIZE, attr_normal, attr_normal | A_BOLD, 0, 1, getmaxx(curwin) / 2, &width_cursym, 1, "^{%s^}", lconvinfo.currency_symbol); - chbuf_cursym = chstrdup(chbuf, BUFSIZE); + chbuf_cursym = chstrdup(chbuf); mkchstr(chbuf, BUFSIZE, attr_normal, 0, 0, 1, getmaxx(curwin) - BANK_INPUT_COLS - width_cursym - 6, &width, 1, diff --git a/src/intf.c b/src/intf.c index 03cf18f..94b1aa1 100644 --- a/src/intf.c +++ b/src/intf.c @@ -1241,7 +1241,7 @@ error: /***********************************************************************/ // chstrdup: Duplicate a chtype buffer -chtype *chstrdup (const chtype *restrict chstr, int chstrsize) +chtype *chstrdup (const chtype *restrict chstr) { const chtype *p; int len; @@ -1249,7 +1249,7 @@ chtype *chstrdup (const chtype *restrict chstr, int chstrsize) // Determine chstr length, including ending NUL - for (len = 1, p = chstr; *p != '\0' && len <= chstrsize; p++, len++) + for (len = 1, p = chstr; *p != '\0'; p++, len++) ; ret = xmalloc(len * sizeof(chtype)); diff --git a/src/intf.h b/src/intf.h index 89c5791..ee53f33 100644 --- a/src/intf.h +++ b/src/intf.h @@ -412,7 +412,6 @@ extern int vmkchstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, /* Function: chstrdup - Duplicate a chtype string Parameters: chstr - String to duplicate - chstrsize - Maximum number of chtype elements in chstr Returns: chtype * - Pointer to new (duplicated) string This function returns a new string of type chtype * that contains a @@ -420,7 +419,7 @@ extern int vmkchstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, memory is not available, the program terminates with an "Out of memory" message. */ -extern chtype *chstrdup (const chtype *restrict chstr, int chstrsize); +extern chtype *chstrdup (const chtype *restrict chstr); /* diff --git a/src/move.c b/src/move.c index 14fb280..353d73c 100644 --- a/src/move.c +++ b/src/move.c @@ -788,11 +788,11 @@ void merge_companies (map_val_t a, map_val_t b) mkchstr(chbuf, BUFSIZE, attr_highlight, 0, 0, 1, getmaxx(curwin) / 2, &width_aa, 1, "%s", company[aa].name); - chbuf_aa = chstrdup(chbuf, BUFSIZE); + chbuf_aa = chstrdup(chbuf); mkchstr(chbuf, BUFSIZE, attr_highlight, 0, 0, 1, getmaxx(curwin) / 2, &width_bb, 1, "%s", company[bb].name); - chbuf_bb = chstrdup(chbuf, BUFSIZE); + chbuf_bb = chstrdup(chbuf); mkchstr(chbuf, BUFSIZE, attr_normal, 0, 0, 1, getmaxx(curwin) / 2, &width, 1, @@ -1032,7 +1032,7 @@ void adjust_values (void) mkchstr(chbuf, BUFSIZE, attr_error_highlight, 0, 0, 1, w / 2, &width_amt, 1, "%N", company[which].share_price); - chbuf_amt = chstrdup(chbuf, BUFSIZE); + chbuf_amt = chstrdup(chbuf); mkchstr(chbuf, BUFSIZE, attr_error_normal, 0, 0, 1, w / 2, &width, 1, From 3a6f33d2a18bb8bb70d64c7ff39fa793d4a8d6d1 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Thu, 18 Aug 2011 15:05:55 +1000 Subject: [PATCH 063/112] Update some minor comments about character encodings --- src/utils.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/utils.c b/src/utils.c index 20c2e2c..4629c8b 100644 --- a/src/utils.c +++ b/src/utils.c @@ -77,6 +77,9 @@ static bool add_currency_symbol = false; // Do we need to add "$"? void init_program_name (char *argv[]) { + /* This implementation assumes a POSIX environment with an ASCII-safe + character encoding (such as ASCII or UTF-8). */ + if (argv == NULL || argv[0] == NULL || *argv[0] == '\0') { program_name_str = PACKAGE; } else { @@ -129,7 +132,8 @@ const char *data_directory (void) { /* This implementation assumes a POSIX environment by using "/" as the directory separator. It also assumes a dot-starting directory - name is permissible (again, true on POSIX systems) */ + name is permissible (again, true on POSIX systems) and that the + character encoding is ASCII-safe. */ if (data_directory_str == NULL) { const char *name = program_name(); @@ -154,8 +158,8 @@ const char *data_directory (void) char *game_filename (int gamenum) { - /* This implementation assumes a POSIX environment by using "/" as - the directory separator */ + /* This implementation assumes a POSIX environment and an ASCII-safe + character encoding. */ char buf[GAME_FILENAME_BUFSIZE]; // Buffer for part of filename const char *dd; // Data directory @@ -335,7 +339,8 @@ ssize_t l_strfmon (char *restrict s, size_t maxsize, /* The current implementation assumes MOD_POSIX_P_CS_PRECEDES is 1 (currency symbol precedes value) and that MOD_POSIX_P_SEP_BY_SPACE is 0 (no space separates currency symbol and value). It does, - however, handle currency symbols of length > 1 */ + however, handle currency symbols of length > 1. */ + assert(MOD_POSIX_P_CS_PRECEDES == 1); assert(MOD_POSIX_P_SEP_BY_SPACE == 0); @@ -346,8 +351,8 @@ ssize_t l_strfmon (char *restrict s, size_t maxsize, /* Insert lconvinfo.currency_symbol to s. NB: add_currecy_symbol == true assumes a POSIX locale and - that MOD_POSIX_CURRENCY_SYMBOL contains only ASCII-safe - characters that work with strlen(), etc. */ + that the character encoding is ASCII-safe (such as by + being ASCII itself, or UTF-8). */ const char *sym = lconvinfo.currency_symbol; int symlen = strlen(sym); char *p; From 87f09a6fda7cd62ec1b562cd1cd24f53f6639c68 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Fri, 19 Aug 2011 13:11:43 +1000 Subject: [PATCH 064/112] Add the Gnulib modules mbrtowc, mbsrtowcs, wcrtomb and wcsrtombs --- lib/.gitignore | 17 +++++++++++++++++ m4/.gitignore | 11 +++++++++++ m4/gnulib-cache.m4 | 6 +++++- 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/lib/.gitignore b/lib/.gitignore index 3230f5b..d6f599c 100644 --- a/lib/.gitignore +++ b/lib/.gitignore @@ -6,6 +6,7 @@ c-ctype.h c-strcase.h c-strcasecmp.c c-strncasecmp.c +config.charset ctype.in.h dosname.h errno.in.h @@ -41,9 +42,16 @@ isnanf.c isnanl-nolibm.h isnanl.c langinfo.in.h +localcharset.c +localcharset.h locale.in.h malloc.c math.in.h +mbrtowc.c +mbsinit.c +mbsrtowcs-impl.h +mbsrtowcs-state.c +mbsrtowcs.c memchr.c memchr.valgrind printf-args.c @@ -55,6 +63,8 @@ printf-frexpl.h printf-parse.c printf-parse.h printf.c +ref-add.sin +ref-del.sin sig-handler.h sigaction.c signal.in.h @@ -74,10 +84,13 @@ stdio.in.h stdlib.in.h str-two-way.h strdup.c +streq.h striconv.c striconv.h string.in.h strncat.c +strnlen1.c +strnlen1.h strstr.c sys_stat.in.h sys_time.in.h @@ -91,6 +104,10 @@ verify.h vfprintf.c vsnprintf.c wchar.in.h +wcrtomb.c +wcsrtombs-impl.h +wcsrtombs-state.c +wcsrtombs.c wctype.in.h xsize.h diff --git a/m4/.gitignore b/m4/.gitignore index 60c8caa..d371b13 100644 --- a/m4/.gitignore +++ b/m4/.gitignore @@ -4,6 +4,7 @@ asm-underscore.m4 assert.m4 codeset.m4 config-h.m4 +configmake.m4 ctype.m4 errno_h.m4 exponentd.m4 @@ -48,11 +49,19 @@ lib-ld.m4 lib-link.m4 lib-prefix.m4 libunistring-base.m4 +localcharset.m4 +locale-fr.m4 +locale-ja.m4 +locale-zh.m4 locale_h.m4 lock.m4 longlong.m4 malloc.m4 math_h.m4 +mbrtowc.m4 +mbsinit.m4 +mbsrtowcs.m4 +mbstate_t.m4 memchr.m4 mmap-anon.m4 multiarch.m4 @@ -98,6 +107,8 @@ vsnprintf.m4 warn-on-use.m4 wchar_h.m4 wchar_t.m4 +wcrtomb.m4 +wcsrtombs.m4 wctype_h.m4 wint_t.m4 xsize.m4 diff --git a/m4/gnulib-cache.m4 b/m4/gnulib-cache.m4 index 4608fa9..2d5a2b0 100644 --- a/m4/gnulib-cache.m4 +++ b/m4/gnulib-cache.m4 @@ -15,7 +15,7 @@ # Specification in the form of a command-line invocation: -# gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --no-conditional-dependencies --no-libtool --macro-prefix=gl assert config-h ctype fprintf-posix getopt-gnu gettext gettext-h gettimeofday langinfo locale printf-posix sigaction signal snprintf-posix stat stdarg stdbool stdio strdup-posix striconv string strncat strstr sys_stat sys_time unistd vfprintf-posix vsnprintf-posix wchar wctype-h +# gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --no-conditional-dependencies --no-libtool --macro-prefix=gl assert config-h ctype fprintf-posix getopt-gnu gettext gettext-h gettimeofday langinfo locale mbrtowc mbsrtowcs printf-posix sigaction signal snprintf-posix stat stdarg stdbool stdio strdup-posix striconv string strncat strstr sys_stat sys_time unistd vfprintf-posix vsnprintf-posix wchar wcrtomb wcsrtombs wctype-h # Specification in the form of a few gnulib-tool.m4 macro invocations: gl_LOCAL_DIR([]) @@ -30,6 +30,8 @@ gl_MODULES([ gettimeofday langinfo locale + mbrtowc + mbsrtowcs printf-posix sigaction signal @@ -49,6 +51,8 @@ gl_MODULES([ vfprintf-posix vsnprintf-posix wchar + wcrtomb + wcsrtombs wctype-h ]) gl_AVOID([]) From 75b5c986c0e7ea2496473a012b6d5bf29cc21e5a Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Fri, 19 Aug 2011 13:22:16 +1000 Subject: [PATCH 065/112] Add the module wcwidth from the GNU Portability Library --- lib/.gitignore | 5 +++++ m4/.gitignore | 1 + m4/gnulib-cache.m4 | 3 ++- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/.gitignore b/lib/.gitignore index d6f599c..41ca201 100644 --- a/lib/.gitignore +++ b/lib/.gitignore @@ -98,6 +98,7 @@ time.in.h unistd.in.h unistr.in.h unitypes.in.h +uniwidth.in.h vasnprintf.c vasnprintf.h verify.h @@ -109,6 +110,7 @@ wcsrtombs-impl.h wcsrtombs-state.c wcsrtombs.c wctype.in.h +wcwidth.c xsize.h alloca.h @@ -143,3 +145,6 @@ unistr/.dirstamp unistr/u8-mbtoucr.c unistr/u8-uctomb-aux.c unistr/u8-uctomb.c + +uniwidth/cjk.h +uniwidth/width.c diff --git a/m4/.gitignore b/m4/.gitignore index d371b13..751f4c1 100644 --- a/m4/.gitignore +++ b/m4/.gitignore @@ -110,5 +110,6 @@ wchar_t.m4 wcrtomb.m4 wcsrtombs.m4 wctype_h.m4 +wcwidth.m4 wint_t.m4 xsize.m4 diff --git a/m4/gnulib-cache.m4 b/m4/gnulib-cache.m4 index 2d5a2b0..828e456 100644 --- a/m4/gnulib-cache.m4 +++ b/m4/gnulib-cache.m4 @@ -15,7 +15,7 @@ # Specification in the form of a command-line invocation: -# gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --no-conditional-dependencies --no-libtool --macro-prefix=gl assert config-h ctype fprintf-posix getopt-gnu gettext gettext-h gettimeofday langinfo locale mbrtowc mbsrtowcs printf-posix sigaction signal snprintf-posix stat stdarg stdbool stdio strdup-posix striconv string strncat strstr sys_stat sys_time unistd vfprintf-posix vsnprintf-posix wchar wcrtomb wcsrtombs wctype-h +# gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --no-conditional-dependencies --no-libtool --macro-prefix=gl assert config-h ctype fprintf-posix getopt-gnu gettext gettext-h gettimeofday langinfo locale mbrtowc mbsrtowcs printf-posix sigaction signal snprintf-posix stat stdarg stdbool stdio strdup-posix striconv string strncat strstr sys_stat sys_time unistd vfprintf-posix vsnprintf-posix wchar wcrtomb wcsrtombs wctype-h wcwidth # Specification in the form of a few gnulib-tool.m4 macro invocations: gl_LOCAL_DIR([]) @@ -54,6 +54,7 @@ gl_MODULES([ wcrtomb wcsrtombs wctype-h + wcwidth ]) gl_AVOID([]) gl_SOURCE_BASE([lib]) From 03e33a64658ff4903f306b5c5300be8d047a9fd5 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Fri, 19 Aug 2011 13:31:07 +1000 Subject: [PATCH 066/112] Update the list of (auto-generated) files to ignore --- lib/.gitignore | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/.gitignore b/lib/.gitignore index 41ca201..83edd45 100644 --- a/lib/.gitignore +++ b/lib/.gitignore @@ -116,6 +116,8 @@ xsize.h alloca.h arg-nonnull.h c++defs.h +charset.alias +configmake.h ctype.h getopt.h iconv.h @@ -127,15 +129,18 @@ iconv_open-solaris.h langinfo.h locale.h math.h +ref-add.sed +ref-del.sed signal.h stdio.h stdlib.h string.h -sys +sys/ time.h unistd.h unistr.h unitypes.h +uniwidth.h unused-parameter.h warn-on-use.h wchar.h @@ -146,5 +151,6 @@ unistr/u8-mbtoucr.c unistr/u8-uctomb-aux.c unistr/u8-uctomb.c +uniwidth/.dirstamp uniwidth/cjk.h uniwidth/width.c From 74031a0415d974a4c0656d0dff580a54f9fe3188 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Fri, 19 Aug 2011 14:26:30 +1000 Subject: [PATCH 067/112] Add yet another module from the GNU Portability Library: btowc --- lib/.gitignore | 3 +++ m4/.gitignore | 2 ++ m4/gnulib-cache.m4 | 3 ++- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/.gitignore b/lib/.gitignore index 83edd45..a34ed72 100644 --- a/lib/.gitignore +++ b/lib/.gitignore @@ -1,6 +1,7 @@ Makefile.am alloca.in.h asnprintf.c +btowc.c c-ctype.c c-ctype.h c-strcase.h @@ -52,6 +53,8 @@ mbsinit.c mbsrtowcs-impl.h mbsrtowcs-state.c mbsrtowcs.c +mbtowc-impl.h +mbtowc.c memchr.c memchr.valgrind printf-args.c diff --git a/m4/.gitignore b/m4/.gitignore index 751f4c1..86d99a2 100644 --- a/m4/.gitignore +++ b/m4/.gitignore @@ -2,6 +2,7 @@ alloca.m4 asm-underscore.m4 assert.m4 +btowc.m4 codeset.m4 config-h.m4 configmake.m4 @@ -62,6 +63,7 @@ mbrtowc.m4 mbsinit.m4 mbsrtowcs.m4 mbstate_t.m4 +mbtowc.m4 memchr.m4 mmap-anon.m4 multiarch.m4 diff --git a/m4/gnulib-cache.m4 b/m4/gnulib-cache.m4 index 828e456..66f7648 100644 --- a/m4/gnulib-cache.m4 +++ b/m4/gnulib-cache.m4 @@ -15,12 +15,13 @@ # Specification in the form of a command-line invocation: -# gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --no-conditional-dependencies --no-libtool --macro-prefix=gl assert config-h ctype fprintf-posix getopt-gnu gettext gettext-h gettimeofday langinfo locale mbrtowc mbsrtowcs printf-posix sigaction signal snprintf-posix stat stdarg stdbool stdio strdup-posix striconv string strncat strstr sys_stat sys_time unistd vfprintf-posix vsnprintf-posix wchar wcrtomb wcsrtombs wctype-h wcwidth +# gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --no-conditional-dependencies --no-libtool --macro-prefix=gl assert btowc config-h ctype fprintf-posix getopt-gnu gettext gettext-h gettimeofday langinfo locale mbrtowc mbsrtowcs printf-posix sigaction signal snprintf-posix stat stdarg stdbool stdio strdup-posix striconv string strncat strstr sys_stat sys_time unistd vfprintf-posix vsnprintf-posix wchar wcrtomb wcsrtombs wctype-h wcwidth # Specification in the form of a few gnulib-tool.m4 macro invocations: gl_LOCAL_DIR([]) gl_MODULES([ assert + btowc config-h ctype fprintf-posix From 8a7dfcaf990b665a5a1e7f1648dfe494e4f8cc39 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Fri, 19 Aug 2011 16:52:27 +1000 Subject: [PATCH 068/112] Handle multibyte characters correctly in mkchstr() Internal processing is now done in terms of wide characters (type wchar_t). --- src/intf.c | 568 ++++++++++++++++++++++++++++++++++++----------------- src/intf.h | 25 ++- 2 files changed, 395 insertions(+), 198 deletions(-) diff --git a/src/intf.c b/src/intf.c index 94b1aa1..8ad6588 100644 --- a/src/intf.c +++ b/src/intf.c @@ -44,25 +44,31 @@ typedef struct txwin { // Declarations for argument processing in mkchstr() +#define EILSEQ_REPL '?' // Illegal byte sequence replacement character + #define MAXFMTARGS 8 // Maximum number of positional arguments enum argument_type { TYPE_NONE, // No type yet assigned TYPE_CHAR, // char + TYPE_WCHAR, // wchar_t TYPE_INT, // int TYPE_LONGINT, // long int TYPE_DOUBLE, // double - TYPE_STRING // const char * + TYPE_STRING, // const char * + TYPE_WSTRING // const wchar_t * }; struct argument { enum argument_type a_type; union a { char a_char; + wchar_t a_wchar; int a_int; long int a_longint; double a_double; const char *a_string; + const wchar_t *a_wstring; } a; }; @@ -70,9 +76,9 @@ struct argument { #define MAXFMTSPECS 16 // Maximum number of conversion specifiers struct convspec { - char spec; // Conversion specifier: c d f N s + wchar_t spec; // Conversion specifier: c d f N s int arg_num; // Which variable argument to use - int len; // Length of conversion specifier, 0 = unused + ptrdiff_t len; // Length of conversion specifier, 0 = unused int precision; // Precision value bool flag_group; // Flag "'" (thousands grouping) bool flag_nosym; // Flag "!" (omit currency symbol) @@ -173,37 +179,39 @@ static void txresize (void); /* - Function: mkchstr_addch - Add a character to the mkchstr buffer - Parameters: chbuf - Pointer to chtype pointer in which to store string - chbufsize - Pointer to number of chtype elements in chbuf - attr - Character rendition to use - maxlines - Maximum number of screen lines to use - maxwidth - Maximum width of each line, in chars - line - Pointer to current line number - width - Pointer to current line width - lastspc - Pointer to const char * pointer to last space - widthspc - Pointer to width just before last space - widthbuf - Pointer to buffer to store widths of each line - widthbufsize - Number of int elements in widthbuf - str - Pointer to const char * pointer to string - Returns: int - -1 on error (with errno set), 0 otherwise + Function: mkchstr_add - Add one character to the mkchstr() buffers + Parameters: outbuf - Pointer to wchar_t pointer in which to store char + attrbuf - Pointer to chtype pointer in which to store attr + count - Pointer to number of wchar_t elements left in outbuf + attr - Character rendition to use + maxlines - Maximum number of screen lines to use + maxwidth - Maximum width of each line, in column positions + line - Pointer to current line number + width - Pointer to current line width + lastspc - Pointer to wchar_t * pointer to last space + spcattr - Pointer to corresponding place in attrbuf + widthspc - Pointer to width just before last space + widthbuf - Pointer to buffer to store widths of each line + widthbufsize - Number of int elements in widthbuf + str - Pointer to const wchar_t * pointer to string + Returns: int - -1 on error (with errno set), 0 otherwise - This helper function adds the character **str to **chbuf, using attr as - the character rendition (attributes), incrementing both *str and *chbuf - and decrementing *chbufsize. If a string is too long for the current - line, a previous space in the current line is converted to a new line - (if possible), else a new line is inserted into the current location - (if not on the last line). *line, *width, *lastspc, *widthspc and - widthbuf[] are all updated appropriately. + This helper function adds one wide character from **str to **outbuf, + and the character rendition attr to **attrbuf, incrementing *str and + *outbuf and decrementing *count. If a string is too long for the + current line, a previous space in the current line is converted to a + new line (if possible), else a new line is inserted into the current + location (if not on the last line). *line, *width, *lastspc, *widthspc + and widthbuf[] are all updated appropriately. */ -static int mkchstr_addch (chtype *restrict *restrict chbuf, - int *restrict chbufsize, chtype attr, - int maxlines, int maxwidth, int *restrict line, - int *restrict width, - chtype *restrict *restrict lastspc, - int *restrict widthspc, int *restrict widthbuf, - int widthbufsize, - const char *restrict *restrict str); +static int mkchstr_add (wchar_t *restrict *restrict outbuf, + chtype *restrict *restrict attrbuf, + int *restrict count, chtype attr, int maxlines, + int maxwidth, int *restrict line, int *restrict width, + wchar_t *restrict *restrict lastspc, + chtype *restrict *restrict spcattr, + int *restrict widthspc, int *restrict widthbuf, + int widthbufsize, const wchar_t *restrict *restrict str); /* @@ -217,12 +225,27 @@ static int mkchstr_addch (chtype *restrict *restrict chbuf, This helper function parses the format string passed to mkchstr(), setting the format_arg and format_spec arrays appropriately. */ -static int mkchstr_parse (const char *restrict format, +static int mkchstr_parse (const wchar_t *restrict format, struct argument *restrict format_arg, struct convspec *restrict format_spec, va_list args); +/* + Function: mkchstr_conv - Convert (wcbuf, attrbuf) to chbuf + Parameters: chbuf - Pointer to chtype buffer in which to store string + chbufsize - Number of chtype elements in chbuf + wcbuf - Wide-character string from which to convert + attrbuf - Associated character rendition array + Returns: (nothing) + + This helper function converts the wide-character string in wcbuf and + the array of character renditions in attrbuf to a chtype * string. +*/ +static void mkchstr_conv (chtype *restrict chbuf, int chbufsize, + wchar_t *restrict wcbuf, chtype *restrict attrbuf); + + /* Function: txinput_fixup - Copy strings with fixup Parameters: dest - Destination buffer of size BUFSIZE @@ -649,15 +672,19 @@ int mkchstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, /***********************************************************************/ -// mkchstr_addch: Add a character to the mkchstr buffer +// mkchstr_add: Add a character to the mkchstr buffer -int mkchstr_addch (chtype *restrict *restrict chbuf, int *restrict chbufsize, - chtype attr, int maxlines, int maxwidth, - int *restrict line, int *restrict width, - chtype *restrict *restrict lastspc, int *restrict widthspc, - int *restrict widthbuf, int widthbufsize, - const char *restrict *restrict str) +int mkchstr_add (wchar_t *restrict *restrict outbuf, + chtype *restrict *restrict attrbuf, int *restrict count, + chtype attr, int maxlines, int maxwidth, int *restrict line, + int *restrict width, wchar_t *restrict *restrict lastspc, + chtype *restrict *restrict spcattr, int *restrict widthspc, + int *restrict widthbuf, int widthbufsize, + const wchar_t *restrict *restrict str) { + int w, wspc; + + if (*line < 0) { // First character in buffer: start line 0 *line = 0; @@ -667,66 +694,87 @@ int mkchstr_addch (chtype *restrict *restrict chbuf, int *restrict chbufsize, // Start a new line if (*line < maxlines - 1) { - *(*chbuf)++ = '\n'; - (*chbufsize)--; + *(*outbuf)++ = '\n'; + *(*attrbuf)++ = 0; + (*count)--; } widthbuf[*line] = *width; *width = 0; *lastspc = NULL; + *spcattr = NULL; *widthspc = 0; (*line)++; (*str)++; - } else if (*width == maxwidth) { - // Current line is now too long + } else { + w = wcwidth(**str); + if (w < 0) { + // We don't support control or non-printable characters + errno = EILSEQ; + return -1; + } - if (! isspace(**str) && *lastspc != NULL && *line < maxlines - 1) { - // Break on the last space in this line - **lastspc = '\n'; + if (*width + w > maxwidth) { + // Current line would be too long to fit in **str - widthbuf[*line] = *widthspc; - *width -= *widthspc + 1; + if (! iswspace(**str) && *lastspc != NULL && *line < maxlines - 1) { + // Break on the last space in this line + wspc = wcwidth(**lastspc); - *lastspc = NULL; - *widthspc = 0; + **lastspc = '\n'; + **spcattr = 0; - (*line)++; - } else { - // Insert a new-line character (if not on last line) - if (*line < maxlines - 1) { - *(*chbuf)++ = '\n'; - (*chbufsize)--; - } + widthbuf[*line] = *widthspc; + *width -= *widthspc + wspc; - widthbuf[*line] = *width; - *width = 0; + *lastspc = NULL; + *spcattr = NULL; + *widthspc = 0; - *lastspc = NULL; - *widthspc = 0; + (*line)++; + } else { + // Insert a new-line character (if not on last line) + if (*line < maxlines - 1) { + *(*outbuf)++ = '\n'; + *(*attrbuf)++ = 0; + (*count)--; + } - (*line)++; + widthbuf[*line] = *width; + *width = 0; - // Skip any following spaces - while (isspace(**str)) { - if (*(*str)++ == '\n') { - break; + *lastspc = NULL; + *spcattr = NULL; + *widthspc = 0; + + (*line)++; + + /* Skip any following spaces. This assumes that no-one + will ever have combining diacritical marks following a + (line-breaking) space! */ + while (iswspace(**str)) { + if (*(*str)++ == '\n') { + break; + } } } - } - } else { - // Insert an ordinary character into the output string + } else { + // Insert an ordinary character into the output buffer - if (isspace(**str)) { - *lastspc = *chbuf; - *widthspc = *width; - } + if (iswspace(**str)) { + *lastspc = *outbuf; + *spcattr = *attrbuf; + *widthspc = *width; + } - *(*chbuf)++ = (unsigned char) **str | attr; - (*chbufsize)--; - (*width)++; - (*str)++; + *(*outbuf)++ = **str; + *(*attrbuf)++ = attr; + (*count)--; + *width += w; + (*str)++; + } } return 0; @@ -736,7 +784,7 @@ int mkchstr_addch (chtype *restrict *restrict chbuf, int *restrict chbufsize, /***********************************************************************/ // mkchstr_parse: Parse the format string for mkchstr() -int mkchstr_parse (const char *restrict format, +int mkchstr_parse (const wchar_t *restrict format, struct argument *restrict format_arg, struct convspec *restrict format_spec, va_list args) { @@ -770,7 +818,7 @@ int mkchstr_parse (const char *restrict format, // Ignore "%%" specifier format++; } else { - const char *start = format; + const wchar_t *start = format; enum argument_type arg_type; bool inspec = true; bool flag_posn = false; // Have we already seen "$"? @@ -778,8 +826,8 @@ int mkchstr_parse (const char *restrict format, int count = 0; while (inspec && *format != '\0') { - char c = *format++; - switch (c) { + wchar_t wc = *format++; + switch (wc) { case '0': // Zero flag, or part of numeric count if (count == 0) { @@ -801,7 +849,7 @@ int mkchstr_parse (const char *restrict format, case '8': case '9': // Part of some numeric count - count = count * 10 + (c - '0'); + count = count * 10 + (wc - '0'); break; case '$': @@ -867,15 +915,15 @@ int mkchstr_parse (const char *restrict format, break; case 'c': - // Insert a character (char) + // Insert a character (char or wchar_t) if (format_spec->flag_group || format_spec->flag_nosym - || format_spec->flag_prec || format_spec->flag_long - || count != 0) { + || format_spec->flag_prec || count != 0) { errno = EINVAL; return -1; } - arg_type = TYPE_CHAR; + arg_type = format_spec->flag_long ? + TYPE_WCHAR : TYPE_CHAR; goto handlefmt; case 'd': @@ -915,15 +963,15 @@ int mkchstr_parse (const char *restrict format, goto handlefmt; case 's': - // Insert a string (const char *) + // Insert a string (const char * or const wchar_t *) if (format_spec->flag_group || format_spec->flag_nosym - || format_spec->flag_prec || format_spec->flag_long - || count != 0) { + || format_spec->flag_prec || count != 0) { errno = EINVAL; return -1; } - arg_type = TYPE_STRING; + arg_type = format_spec->flag_long ? + TYPE_WSTRING : TYPE_STRING; handlefmt: if (arg_num >= MAXFMTARGS || specs_left == 0) { @@ -940,7 +988,7 @@ int mkchstr_parse (const char *restrict format, format_spec->len = format - start; format_spec->arg_num = arg_num; - format_spec->spec = c; + format_spec->spec = wc; arg_num++; num_args = MAX(num_args, arg_num); @@ -975,6 +1023,10 @@ int mkchstr_parse (const char *restrict format, format_arg->a.a_char = (char) va_arg(args, int); break; + case TYPE_WCHAR: + format_arg->a.a_wchar = va_arg(args, wchar_t); + break; + case TYPE_INT: format_arg->a.a_int = va_arg(args, int); break; @@ -991,6 +1043,10 @@ int mkchstr_parse (const char *restrict format, format_arg->a.a_string = va_arg(args, const char *); break; + case TYPE_WSTRING: + format_arg->a.a_wstring = va_arg(args, const wchar_t *); + break; + default: /* Cannot allow unused arguments, as we have no way of knowing how much space they take (cf. int vs. long long @@ -1004,6 +1060,77 @@ int mkchstr_parse (const char *restrict format, } +/***********************************************************************/ +// mkchstr_conv: Convert (wcbuf, attrbuf) to chbuf + +void mkchstr_conv (chtype *restrict chbuf, int chbufsize, + wchar_t *restrict wcbuf, chtype *restrict attrbuf) +{ + char *convbuf = xmalloc(chbufsize); + mbstate_t mbstate; + wchar_t *wp; + char *p; + bool done; + size_t n; + + + /* Perform a preliminary conversion to weed out any problems with + EILSEQ and insufficient buffer space. */ + while (true) { + memset(&mbstate, 0, sizeof(mbstate)); + wp = wcbuf; + if (wcsrtombs(convbuf, (const wchar_t **) &wp, chbufsize, &mbstate) + == (size_t) -1) { + if (errno == EILSEQ) { + /* Replace problematic wide characters with a known-good + (ASCII) one. This is better than terminating! */ + *wp = EILSEQ_REPL; + } else { + errno_exit("mkchstr_conv: `%ls'", wcbuf); + } + } else if (wp != NULL) { + // convbuf is too small: truncate wcbuf if possible + if (wp == wcbuf) { + errno = E2BIG; + errno_exit("mkchstr_conv: `%ls'", wcbuf); + } else { + *(wp - 1) = '\0'; + } + } else { + // wcbuf CAN fit into convbuf when converted + break; + } + } + + // Convert for real, combining each multibyte character with attrbuf + memset(&mbstate, 0, sizeof(mbstate)); + done = false; + while (! done) { + // Yes, we want to convert a wide NUL, too! + if ((n = wcrtomb(convbuf, *wcbuf, &mbstate)) == (size_t) -1) { + errno_exit("mkchstr_conv: `%ls'", wcbuf); + } + + for (p = convbuf; n > 0; n--, p++, chbuf++) { + if (*p == '\0' || *p == '\n') { + /* This code assumes '\n' can never appear in a multibyte + string except as a control character---which is true + of all multibyte encodings (I believe!) */ + *chbuf = (unsigned char) *p; + } else { + *chbuf = (unsigned char) *p | *attrbuf; + } + } + + done = (*wcbuf == '\0'); + wcbuf++; + attrbuf++; + } + + free(convbuf); +} + + /***********************************************************************/ // vmkchstr: Prepare a string for printing to screen @@ -1012,12 +1139,20 @@ int vmkchstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, int *restrict widthbuf, int widthbufsize, const char *restrict format, va_list args) { - const char *orig_format = format; struct argument format_arg[MAXFMTARGS]; struct convspec format_spec[MAXFMTSPECS]; struct convspec *spec; - int line, width; - chtype *lastspc; + const wchar_t *wcformat; + wchar_t *orig_wcformat; + mbstate_t mbstate; + + wchar_t *outbuf, *orig_outbuf; + chtype *attrbuf, *orig_attrbuf; + wchar_t *fmtbuf; + + int count, line, width; + wchar_t *lastspc; + chtype *spcattr; int widthspc; chtype curattr; int saved_errno; @@ -1025,55 +1160,78 @@ int vmkchstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, assert(chbuf != NULL); assert(chbufsize > 0); + assert(chbufsize <= BUFSIZE); assert(maxlines > 0); assert(maxwidth > 0); assert(widthbuf != NULL); assert(widthbufsize >= maxlines); assert(format != NULL); - if (mkchstr_parse(format, format_arg, format_spec, args) < 0) { + outbuf = orig_outbuf = xmalloc(BUFSIZE * sizeof(wchar_t)); + attrbuf = orig_attrbuf = xmalloc(BUFSIZE * sizeof(chtype)); + wcformat = orig_wcformat = xmalloc(chbufsize * sizeof(wchar_t)); + fmtbuf = xmalloc(BUFSIZE * sizeof(wchar_t)); + + // Convert format to a wide-character string + { + memset(&mbstate, 0, sizeof(mbstate)); + const char *p = format; + if (mbsrtowcs(orig_wcformat, &p, BUFSIZE, &mbstate) == (size_t) -1) { + goto error; + } else if (p != NULL) { + errno = E2BIG; + goto error; + } + } + + if (mkchstr_parse(wcformat, format_arg, format_spec, args) < 0) { goto error; } + // Construct the (outbuf, attrbuf) pair of arrays + spec = format_spec; curattr = attr_norm; + count = BUFSIZE; // Space left in outbuf line = -1; // Current line number (0 = first) width = 0; // Width of the current line + lastspc = NULL; // Pointer to last space in line + spcattr = NULL; // Equivalent in attrbuf widthspc = 0; // Width of line before last space - while (*format != '\0' && chbufsize > 1 && line < maxlines) { - switch (*format) { + while (*wcformat != '\0' && count > 1 && line < maxlines) { + switch (*wcformat) { case '^': // Switch to a different character rendition - if (*++format == '\0') { + if (*++wcformat == '\0') { goto error_inval; } else { - switch (*format) { + switch (*wcformat) { case '^': - if (mkchstr_addch(&chbuf, &chbufsize, curattr, maxlines, - maxwidth, &line, &width, &lastspc, - &widthspc, widthbuf, widthbufsize, - &format) < 0) { + if (mkchstr_add(&outbuf, &attrbuf, &count, curattr, + maxlines, maxwidth, &line, &width, + &lastspc, &spcattr, &widthspc, widthbuf, + widthbufsize, &wcformat) < 0) { goto error; } break; case '{': curattr = attr_alt1; - format++; + wcformat++; break; case '[': curattr = attr_alt2; - format++; + wcformat++; break; case '}': case ']': curattr = attr_norm; - format++; + wcformat++; break; default: @@ -1084,142 +1242,167 @@ int vmkchstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, case '%': // Process a conversion specifier - if (*++format == '\0') { + if (*++wcformat == '\0') { goto error_inval; - } else if (*format == '%') { - if (mkchstr_addch(&chbuf, &chbufsize, curattr, maxlines, - maxwidth, &line, &width, &lastspc, &widthspc, - widthbuf, widthbufsize, &format) < 0) { + } else if (*wcformat == '%') { + if (mkchstr_add(&outbuf, &attrbuf, &count, curattr, maxlines, + maxwidth, &line, &width, &lastspc, &spcattr, + &widthspc, widthbuf, widthbufsize, &wcformat) + < 0) { goto error; } } else { assert(spec->len != 0); - - const char *str; - char *buf = xmalloc(BUFSIZE); + const wchar_t *str; + wint_t wc; switch (spec->spec) { case 'c': - // Insert a character (char) into the output - if (snprintf(buf, BUFSIZE, "%c", - format_arg[spec->arg_num].a.a_char) < 0) { - saved_errno = errno; - free(buf); - errno = saved_errno; + // Insert a character (char or wchar_t) into the output + if (spec->flag_long) { + wc = format_arg[spec->arg_num].a.a_wchar; + } else { + wc = btowc(format_arg[spec->arg_num].a.a_char); + } + + if (wc == '\0' || wc == WEOF) { + errno = EILSEQ; goto error; } - str = buf; + fmtbuf[0] = wc; + fmtbuf[1] = '\0'; + + str = fmtbuf; goto insertstr; case 'd': // Insert an integer (int or long int) into the output if (spec->flag_long) { - if (snprintf(buf, BUFSIZE, spec->flag_group ? - "%'ld" : "%ld", - format_arg[spec->arg_num].a.a_longint) < 0) { - saved_errno = errno; - free(buf); - errno = saved_errno; + if (swprintf(fmtbuf, BUFSIZE, spec->flag_group ? + L"%'ld" : L"%ld", + format_arg[spec->arg_num].a.a_longint) < 0) goto error; - } } else { - if (snprintf(buf, BUFSIZE, spec->flag_group ? - "%'d" : "%d", - format_arg[spec->arg_num].a.a_int) < 0) { - saved_errno = errno; - free(buf); - errno = saved_errno; + if (swprintf(fmtbuf, BUFSIZE, spec->flag_group ? + L"%'d" : L"%d", + format_arg[spec->arg_num].a.a_int) < 0) goto error; - } } - str = buf; + str = fmtbuf; goto insertstr; case 'f': // Insert a floating-point number (double) into the output if (spec->flag_prec) { - if (snprintf(buf, BUFSIZE, spec->flag_group ? - "%'.*f" : "%.*f", spec->precision, - format_arg[spec->arg_num].a.a_double) < 0) { - saved_errno = errno; - free(buf); - errno = saved_errno; + if (swprintf(fmtbuf, BUFSIZE, spec->flag_group ? + L"%'.*f" : L"%.*f", spec->precision, + format_arg[spec->arg_num].a.a_double) < 0) goto error; - } } else { - if (snprintf(buf, BUFSIZE, spec->flag_group ? - "%'f" : "%f", - format_arg[spec->arg_num].a.a_double) < 0) { - saved_errno = errno; - free(buf); - errno = saved_errno; + if (swprintf(fmtbuf, BUFSIZE, spec->flag_group ? + L"%'f" : L"%f", + format_arg[spec->arg_num].a.a_double) < 0) goto error; - } } - str = buf; + str = fmtbuf; goto insertstr; case 'N': // Insert a monetary amount (double) into the output - if (l_strfmon(buf, BUFSIZE, spec->flag_nosym ? "%!n" : "%n", - format_arg[spec->arg_num].a.a_double) < 0) { - saved_errno = errno; - free(buf); - errno = saved_errno; - goto error; - } + { + /* strfmon() is not available in a wide-char + version, so we need a multibyte char buffer */ + char *buf = xmalloc(BUFSIZE); + const char *p = buf; - str = buf; - goto insertstr; - - case 's': - // Insert a string (const char *) into the output - str = format_arg[spec->arg_num].a.a_string; - - if (str == NULL) { - str = "(null)"; // As per GNU printf() - } - - insertstr: - // Insert the string pointed to by str - while (*str != '\0' && chbufsize > 1 && line < maxlines) { - if (mkchstr_addch(&chbuf, &chbufsize, curattr, - maxlines, maxwidth, &line, &width, - &lastspc, &widthspc, widthbuf, - widthbufsize, &str) < 0) { + if (l_strfmon(buf, BUFSIZE, spec->flag_nosym ? "%!n" : "%n", + format_arg[spec->arg_num].a.a_double) < 0) { saved_errno = errno; free(buf); errno = saved_errno; goto error; } + + memset(&mbstate, 0, sizeof(mbstate)); + if (mbsrtowcs(fmtbuf, &p, BUFSIZE, &mbstate) + == (size_t) -1) { + saved_errno = errno; + free(buf); + errno = saved_errno; + goto error; + } else if (p != NULL) { + free(buf); + errno = E2BIG; + goto error; + } + + free(buf); } - format += spec->len; + str = fmtbuf; + goto insertstr; + + case 's': + // Insert a string (const char * or const wchar_t *) + if (spec->flag_long) { + str = format_arg[spec->arg_num].a.a_wstring; + } else { + const char *p = format_arg[spec->arg_num].a.a_string; + if (p == NULL) { + str = NULL; + } else { + memset(&mbstate, 0, sizeof(mbstate)); + if (mbsrtowcs(fmtbuf, &p, BUFSIZE, &mbstate) + == (size_t) -1) { + goto error; + } else if (p != NULL) { + errno = E2BIG; + goto error; + } + str = fmtbuf; + } + } + + if (str == NULL) { + str = L"(null)"; // As per GNU printf() + } + + insertstr: + // Insert the string pointed to by str + while (*str != '\0' && count > 1 && line < maxlines) { + if (mkchstr_add(&outbuf, &attrbuf, &count, curattr, + maxlines, maxwidth, &line, &width, + &lastspc, &spcattr, &widthspc, + widthbuf, widthbufsize, &str) < 0) { + goto error; + } + } + + wcformat += spec->len; spec++; break; default: assert(spec->spec); } - - free(buf); } break; default: // Process an ordinary character (including new-line) - if (mkchstr_addch(&chbuf, &chbufsize, curattr, maxlines, maxwidth, - &line, &width, &lastspc, &widthspc, widthbuf, - widthbufsize, &format) < 0) { + if (mkchstr_add(&outbuf, &attrbuf, &count, curattr, maxlines, + maxwidth, &line, &width, &lastspc, &spcattr, + &widthspc, widthbuf, widthbufsize, &wcformat) < 0) { goto error; } } } - *chbuf = 0; // Terminating NUL byte + *outbuf = '\0'; // Terminating NUL character + *attrbuf = 0; if (line >= 0 && line < maxlines) { widthbuf[line] = width; @@ -1227,6 +1410,14 @@ int vmkchstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, line = maxlines - 1; } + // Convert the (outbuf, attrbuf) pair of arrays to chbuf + mkchstr_conv(chbuf, chbufsize, orig_outbuf, orig_attrbuf); + + free(fmtbuf); + free(orig_wcformat); + free(orig_attrbuf); + free(orig_outbuf); + return line + 1; @@ -1234,7 +1425,14 @@ error_inval: errno = EINVAL; error: - errno_exit(_("mkchstr: `%s'"), orig_format); + saved_errno = errno; + free(fmtbuf); + free(orig_wcformat); + free(orig_attrbuf); + free(orig_outbuf); + errno = saved_errno; + + errno_exit(_("mkchstr: `%s'"), format); } diff --git a/src/intf.h b/src/intf.h index ee53f33..9fcb017 100644 --- a/src/intf.h +++ b/src/intf.h @@ -43,8 +43,7 @@ /* This version of Star Traders only utilises WIN_COLS x WIN_LINES of a terminal screen; this terminal must be at least MIN_COLS x MIN_LINES in - size. The newtxwin() function automatically places a new window in the - centre-top of the terminal screen. + size. Windows are placed in the centre-top of the terminal screen. */ #define MIN_LINES 24 // Minimum number of lines in terminal @@ -57,6 +56,7 @@ #define MAX_DLG_LINES 10 // Default maximum lines of text in dialog box +// Space (number of terminal columns) to allow for various fields #define YESNO_COLS 4 // Space to allow for "Yes" or "No" response #define ORDINAL_COLS 5 // Space for ordinals (1st, 2nd, etc) #define TOTAL_VALUE_COLS 18 // Space for total value (monetary) @@ -288,13 +288,13 @@ extern int txrefresh (void); alt2_attr - Alternate character rendition 2 (more highlighted) keywait_attr - "Press any key" character rendition boxtitle - Dialog box title (may be NULL) - format - Dialog box text, as passed to prepstr() + format - Dialog box text, as passed to mkchstr() ... - Dialog box text format parameters Returns: int - OK is always returned This function creates a dialog box window using newtxwin(), displays boxtitle centred on the first line (if boxtitle is not NULL), displays - format (and associated parameters) centred using prepstr(), then waits + format (and associated parameters) centred using mkchstr(), then waits for the user to press any key before closing the dialog box window. Note that txrefresh() is NOT called once the window is closed. */ @@ -330,10 +330,12 @@ extern int txdlgbox (int maxlines, int ncols, int begin_y, int begin_x, The format string is similar to but more limited than printf(). In particular, only the following conversion specifiers are understood: - %% - Print the ASCII percent sign (ASCII code U+0025) + %% - Insert the ASCII percent sign (ASCII code U+0025) %c - Insert the next parameter as a character (type char) + %lc - Insert the next parameter as a wide char (type wchar_t) %s - Insert the next parameter as a string (type char *) + %ls - Insert the next parameter as a wide string (type wchar_t *) %d - Insert the next parameter as an integer (type int) %'d - As above, using the locale's thousands group separator %ld - Insert the next parameter as a long int @@ -360,19 +362,16 @@ extern int txdlgbox (int maxlines, int ncols, int begin_y, int begin_x, rendition flags are understood, where the "^" character is a literal ASCII circumflex accent: - ^^ - Print the circumflex accent (ASCII code U+005E) + ^^ - Insert the circumflex accent (ASCII code U+005E) ^{ - Switch to using attr_alt1 character rendition (alternate mode 1) ^} - Switch to using attr_norm character rendition ^[ - Switch to using attr_alt2 character rendition (alternate mode 2) ^] - Switch to using attr_norm character rendition - Characters other than these are inserted as literals, except that '\n' - will force the start of a new line. By default, attr_norm is used as - the character rendition (attributes). - - Please note that this function does NOT handle multibyte characters - correctly: widths may be incorrect (byte count, not actual width) and - multibyte characters may be split over two lines. + Printable characters other than these are inserted as literals. The + character '\n' will force the start of a new line; no other control (or + non-printable) characters are allowed. By default, attr_norm is used + as the character rendition (attributes). This function returns the actual number of lines used (from 0 to maxlines). If an error is detected, the application terminates. From aeaf08a8a4fc9b782e90c0350b785ecd2971a3f9 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Fri, 19 Aug 2011 17:14:00 +1000 Subject: [PATCH 069/112] Possible bug fix: test for "C" locale when return string is opaque On some systems the return string from setlocale() may be opaque, so we need to explicitly set the locale to "C", then test the return value from that. --- src/utils.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/utils.c b/src/utils.c index 4629c8b..e698ad3 100644 --- a/src/utils.c +++ b/src/utils.c @@ -61,7 +61,6 @@ static char *program_name_str = NULL; // Canonical program name static char *home_directory_str = NULL; // Full pathname to home static char *data_directory_str = NULL; // Writable data dir pathname -static char *current_mon_locale; // As returned by setlocale() static bool add_currency_symbol = false; // Do we need to add "$"? @@ -302,24 +301,26 @@ extern int randi (int limit) void init_locale (void) { + char *cur, *cloc; struct lconv *lc; - current_mon_locale = setlocale(LC_MONETARY, NULL); + cur = xstrdup(setlocale(LC_MONETARY, NULL)); lc = localeconv(); - - assert(current_mon_locale != NULL); assert(lc != NULL); lconvinfo = *lc; - /* Are we in the POSIX locale? This test may not be portable as the - string returned by setlocale() is supposed to be opaque. */ add_currency_symbol = false; - if ( strcmp(current_mon_locale, "POSIX") == 0 - || strcmp(current_mon_locale, "C") == 0 - || strcmp(current_mon_locale, "C.UTF-8") == 0 - || strcmp(current_mon_locale, "C.utf8") == 0) { + + /* Are we in the POSIX locale? The string returned by setlocale() is + supposed to be opaque, but in practise is not. To be on the safe + side, we explicitly set the locale to "C", then test the returned + value of that, too. */ + cloc = setlocale(LC_MONETARY, "C"); + if ( strcmp(cur, cloc) == 0 + || strcmp(cur, "POSIX") == 0 || strcmp(cur, "C") == 0 + || strcmp(cur, "C.UTF-8") == 0 || strcmp(cur, "C.utf8") == 0) { add_currency_symbol = true; lconvinfo.currency_symbol = MOD_POSIX_CURRENCY_SYMBOL; @@ -327,6 +328,9 @@ void init_locale (void) lconvinfo.p_cs_precedes = MOD_POSIX_P_CS_PRECEDES; lconvinfo.p_sep_by_space = MOD_POSIX_P_SEP_BY_SPACE; } + + setlocale(LC_MONETARY, cur); + free(cur); } From 6fb62460cad8a39e33380f3e737c49f8d9cde430 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Fri, 19 Aug 2011 17:20:41 +1000 Subject: [PATCH 070/112] Add some asserts to newtxwin(), just to be on the safe side --- src/intf.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/intf.c b/src/intf.c index 8ad6588..27bef6b 100644 --- a/src/intf.c +++ b/src/intf.c @@ -484,6 +484,11 @@ WINDOW *newtxwin (int nlines, int ncols, int begin_y, int begin_x, begin_x = (ncols == 0) ? 0 : (COLS - ncols) / 2; } + assert(nlines > 0); + assert(ncols > 0); + assert(begin_y >= 0); + assert(begin_x >= 0); + // Create the new window win = newwin(nlines, ncols, begin_y, begin_x); From a49c50b4fda65eb4576cf2a03315f4a62b320501 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Fri, 19 Aug 2011 17:24:28 +1000 Subject: [PATCH 071/112] Allow mkchstr_conv error strings to be localised --- src/intf.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/intf.c b/src/intf.c index 27bef6b..03a66ad 100644 --- a/src/intf.c +++ b/src/intf.c @@ -1091,13 +1091,13 @@ void mkchstr_conv (chtype *restrict chbuf, int chbufsize, (ASCII) one. This is better than terminating! */ *wp = EILSEQ_REPL; } else { - errno_exit("mkchstr_conv: `%ls'", wcbuf); + errno_exit(_("mkchstr_conv: `%ls'"), wcbuf); } } else if (wp != NULL) { // convbuf is too small: truncate wcbuf if possible if (wp == wcbuf) { errno = E2BIG; - errno_exit("mkchstr_conv: `%ls'", wcbuf); + errno_exit(_("mkchstr_conv: `%ls'"), wcbuf); } else { *(wp - 1) = '\0'; } @@ -1113,7 +1113,7 @@ void mkchstr_conv (chtype *restrict chbuf, int chbufsize, while (! done) { // Yes, we want to convert a wide NUL, too! if ((n = wcrtomb(convbuf, *wcbuf, &mbstate)) == (size_t) -1) { - errno_exit("mkchstr_conv: `%ls'", wcbuf); + errno_exit(_("mkchstr_conv: `%ls'"), wcbuf); } for (p = convbuf; n > 0; n--, p++, chbuf++) { From 02fd0178076eaa878f5017ba8cfbb0d4ba3993e0 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Fri, 19 Aug 2011 17:34:41 +1000 Subject: [PATCH 072/112] Make the errno_exit() string a little more regular This is to match all other such strings in the program. --- src/fileio.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/fileio.c b/src/fileio.c index 60dfe04..15d2df4 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -103,7 +103,7 @@ static const unsigned char game_file_crypt_key[] = { err_exit(_("%s: illegal characters on line %d"), \ filename, lineno); \ } else { \ - errno_exit("str_cd_iconv()"); \ + errno_exit("str_cd_iconv"); \ } \ } \ } else { \ @@ -174,7 +174,7 @@ static const unsigned char game_file_crypt_key[] = { err_exit(_("%s: could not convert string"), \ filename); \ } else { \ - errno_exit("str_cd_iconv()"); \ + errno_exit("str_cd_iconv"); \ } \ } \ save_game_printf("%s", s); \ @@ -260,7 +260,7 @@ bool load_game (int num) if (need_icd) { icd = iconv_open(codeset, GAME_FILE_CHARSET); if (icd == (iconv_t) -1) { - errno_exit("iconv_open()"); + errno_exit("iconv_open"); } } else { icd = (iconv_t) -1; @@ -471,7 +471,7 @@ bool save_game (int num) if (need_icd) { icd = iconv_open(codeset, GAME_FILE_CHARSET); if (icd == (iconv_t) -1) { - errno_exit("iconv_open()"); + errno_exit("iconv_open"); } } else { icd = (iconv_t) -1; From 336611559ba8c67be677e861773a4ccb44390d4f Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Sat, 20 Aug 2011 10:40:07 +1000 Subject: [PATCH 073/112] Add the error-checking function xwcsdup() --- lib/.gitignore | 4 ++++ m4/.gitignore | 2 ++ m4/gnulib-cache.m4 | 3 ++- src/intf.c | 2 -- src/utils.c | 20 ++++++++++++++++++++ src/utils.h | 15 +++++++++++++++ 6 files changed, 43 insertions(+), 3 deletions(-) diff --git a/lib/.gitignore b/lib/.gitignore index a34ed72..c2b6dae 100644 --- a/lib/.gitignore +++ b/lib/.gitignore @@ -109,11 +109,15 @@ vfprintf.c vsnprintf.c wchar.in.h wcrtomb.c +wcsdup-impl.h +wcsdup.c wcsrtombs-impl.h wcsrtombs-state.c wcsrtombs.c wctype.in.h wcwidth.c +wmemcpy-impl.h +wmemcpy.c xsize.h alloca.h diff --git a/m4/.gitignore b/m4/.gitignore index 86d99a2..1ad61a1 100644 --- a/m4/.gitignore +++ b/m4/.gitignore @@ -110,8 +110,10 @@ warn-on-use.m4 wchar_h.m4 wchar_t.m4 wcrtomb.m4 +wcsdup.m4 wcsrtombs.m4 wctype_h.m4 wcwidth.m4 wint_t.m4 +wmemcpy.m4 xsize.m4 diff --git a/m4/gnulib-cache.m4 b/m4/gnulib-cache.m4 index 66f7648..b6e250d 100644 --- a/m4/gnulib-cache.m4 +++ b/m4/gnulib-cache.m4 @@ -15,7 +15,7 @@ # Specification in the form of a command-line invocation: -# gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --no-conditional-dependencies --no-libtool --macro-prefix=gl assert btowc config-h ctype fprintf-posix getopt-gnu gettext gettext-h gettimeofday langinfo locale mbrtowc mbsrtowcs printf-posix sigaction signal snprintf-posix stat stdarg stdbool stdio strdup-posix striconv string strncat strstr sys_stat sys_time unistd vfprintf-posix vsnprintf-posix wchar wcrtomb wcsrtombs wctype-h wcwidth +# gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --no-conditional-dependencies --no-libtool --macro-prefix=gl assert btowc config-h ctype fprintf-posix getopt-gnu gettext gettext-h gettimeofday langinfo locale mbrtowc mbsrtowcs printf-posix sigaction signal snprintf-posix stat stdarg stdbool stdio strdup-posix striconv string strncat strstr sys_stat sys_time unistd vfprintf-posix vsnprintf-posix wchar wcrtomb wcsdup wcsrtombs wctype-h wcwidth # Specification in the form of a few gnulib-tool.m4 macro invocations: gl_LOCAL_DIR([]) @@ -53,6 +53,7 @@ gl_MODULES([ vsnprintf-posix wchar wcrtomb + wcsdup wcsrtombs wctype-h wcwidth diff --git a/src/intf.c b/src/intf.c index 03a66ad..09b6501 100644 --- a/src/intf.c +++ b/src/intf.c @@ -44,8 +44,6 @@ typedef struct txwin { // Declarations for argument processing in mkchstr() -#define EILSEQ_REPL '?' // Illegal byte sequence replacement character - #define MAXFMTARGS 8 // Maximum number of positional arguments enum argument_type { diff --git a/src/utils.c b/src/utils.c index e698ad3..7b0adac 100644 --- a/src/utils.c +++ b/src/utils.c @@ -487,5 +487,25 @@ char *xstrdup (const char *str) } +/***********************************************************************/ +// xwcsdup: Duplicate a wide-character string, with checking + +wchar_t *xwcsdup (const wchar_t *str) +{ + wchar_t *s; + + + if (str == NULL) + str = L""; + + s = wcsdup(str); + if (s == NULL) { + err_exit_nomem(); + } + + return s; +} + + /***********************************************************************/ // End of file diff --git a/src/utils.h b/src/utils.h index 4c9aabe..88699ba 100644 --- a/src/utils.h +++ b/src/utils.h @@ -42,6 +42,9 @@ #define MAX(a, b) ((a) > (b) ? (a) : (b)) +#define EILSEQ_REPL '?' // Illegal character sequence replacement + + /************************************************************************ * Global variable declarations * ************************************************************************/ @@ -328,4 +331,16 @@ extern void *xmalloc (size_t size); extern char *xstrdup (const char *str); +/* + Function: xwcsdup - Duplicate a wide-character string, with checking + Parameters: str - String to duplicate + Returns: wchar_t * - Pointer to new string, allocated with malloc() + + This wrapper function duplicates a string by calling wcsdup(), then + checks if a NULL pointer has been returned. If so, the program + terminates with an "Out of memory" error. +*/ +extern wchar_t *xwcsdup (const wchar_t *str); + + #endif /* included_UTILS_H */ From 7b544bbd35fc5eb9cdab2235006fd09e9f94cc03 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Sat, 20 Aug 2011 13:03:40 +1000 Subject: [PATCH 074/112] Add the functions xwcrtomb() and xmbstowcs() The xwcrtomb() and xmbstowcs() functions replace illegal characters with EILSEQ_REPL ('?'). Adjust other functions, particularly mkchstr() and friends, to suit. --- src/intf.c | 114 +++++++++++++++------------------------------------ src/system.h | 1 + src/utils.c | 76 ++++++++++++++++++++++++++++++++++ src/utils.h | 33 +++++++++++++++ 4 files changed, 143 insertions(+), 81 deletions(-) diff --git a/src/intf.c b/src/intf.c index 09b6501..46cc3e8 100644 --- a/src/intf.c +++ b/src/intf.c @@ -1069,68 +1069,51 @@ int mkchstr_parse (const wchar_t *restrict format, void mkchstr_conv (chtype *restrict chbuf, int chbufsize, wchar_t *restrict wcbuf, chtype *restrict attrbuf) { - char *convbuf = xmalloc(chbufsize); - mbstate_t mbstate; - wchar_t *wp; + char convbuf[MB_LEN_MAX + 1]; + char endbuf[MB_LEN_MAX]; + mbstate_t mbstate, mbcopy; + size_t endsize, n; char *p; bool done; - size_t n; - /* Perform a preliminary conversion to weed out any problems with - EILSEQ and insufficient buffer space. */ - while (true) { - memset(&mbstate, 0, sizeof(mbstate)); - wp = wcbuf; - if (wcsrtombs(convbuf, (const wchar_t **) &wp, chbufsize, &mbstate) - == (size_t) -1) { - if (errno == EILSEQ) { - /* Replace problematic wide characters with a known-good - (ASCII) one. This is better than terminating! */ - *wp = EILSEQ_REPL; - } else { - errno_exit(_("mkchstr_conv: `%ls'"), wcbuf); - } - } else if (wp != NULL) { - // convbuf is too small: truncate wcbuf if possible - if (wp == wcbuf) { - errno = E2BIG; - errno_exit(_("mkchstr_conv: `%ls'"), wcbuf); - } else { - *(wp - 1) = '\0'; - } - } else { - // wcbuf CAN fit into convbuf when converted - break; - } - } - - // Convert for real, combining each multibyte character with attrbuf memset(&mbstate, 0, sizeof(mbstate)); done = false; while (! done) { - // Yes, we want to convert a wide NUL, too! - if ((n = wcrtomb(convbuf, *wcbuf, &mbstate)) == (size_t) -1) { - errno_exit(_("mkchstr_conv: `%ls'"), wcbuf); + // Make sure we always have enough space for ending shift sequence + memcpy(&mbcopy, &mbstate, sizeof(mbstate)); + endsize = wcrtomb(endbuf, '\0', &mbcopy); + if (endsize == (size_t) -1) { + errno_exit(_("mkchstr_conv: NUL")); } - for (p = convbuf; n > 0; n--, p++, chbuf++) { - if (*p == '\0' || *p == '\n') { - /* This code assumes '\n' can never appear in a multibyte - string except as a control character---which is true - of all multibyte encodings (I believe!) */ - *chbuf = (unsigned char) *p; - } else { - *chbuf = (unsigned char) *p | *attrbuf; + // Yes, we want to convert a wide NUL, too! + n = xwcrtomb(convbuf, *wcbuf, &mbstate); + + if (chbufsize > endsize + n) { + for (p = convbuf; n > 0; n--, p++, chbuf++, chbufsize--) { + if (*p == '\0' || *p == '\n') { + /* This code assumes '\n' can never appear in a + multibyte string except as a control character--- + which is true of all multibyte encodings (I + believe!) */ + *chbuf = (unsigned char) *p; + } else { + *chbuf = (unsigned char) *p | *attrbuf; + } } + } else { + // Not enough space for *wcbuf, so terminate chbuf early + for (p = endbuf; endsize > 0; endsize--, p++, chbuf++) { + *chbuf = (unsigned char) *p; + } + break; } done = (*wcbuf == '\0'); wcbuf++; attrbuf++; } - - free(convbuf); } @@ -1147,7 +1130,6 @@ int vmkchstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, struct convspec *spec; const wchar_t *wcformat; wchar_t *orig_wcformat; - mbstate_t mbstate; wchar_t *outbuf, *orig_outbuf; chtype *attrbuf, *orig_attrbuf; @@ -1176,16 +1158,7 @@ int vmkchstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, fmtbuf = xmalloc(BUFSIZE * sizeof(wchar_t)); // Convert format to a wide-character string - { - memset(&mbstate, 0, sizeof(mbstate)); - const char *p = format; - if (mbsrtowcs(orig_wcformat, &p, BUFSIZE, &mbstate) == (size_t) -1) { - goto error; - } else if (p != NULL) { - errno = E2BIG; - goto error; - } - } + xmbstowcs(orig_wcformat, format, BUFSIZE); if (mkchstr_parse(wcformat, format_arg, format_spec, args) < 0) { goto error; @@ -1269,8 +1242,7 @@ int vmkchstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, } if (wc == '\0' || wc == WEOF) { - errno = EILSEQ; - goto error; + wc = EILSEQ_REPL; } fmtbuf[0] = wc; @@ -1319,7 +1291,6 @@ int vmkchstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, /* strfmon() is not available in a wide-char version, so we need a multibyte char buffer */ char *buf = xmalloc(BUFSIZE); - const char *p = buf; if (l_strfmon(buf, BUFSIZE, spec->flag_nosym ? "%!n" : "%n", format_arg[spec->arg_num].a.a_double) < 0) { @@ -1329,19 +1300,7 @@ int vmkchstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, goto error; } - memset(&mbstate, 0, sizeof(mbstate)); - if (mbsrtowcs(fmtbuf, &p, BUFSIZE, &mbstate) - == (size_t) -1) { - saved_errno = errno; - free(buf); - errno = saved_errno; - goto error; - } else if (p != NULL) { - free(buf); - errno = E2BIG; - goto error; - } - + xmbstowcs(fmtbuf, buf, BUFSIZE); free(buf); } @@ -1357,14 +1316,7 @@ int vmkchstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, if (p == NULL) { str = NULL; } else { - memset(&mbstate, 0, sizeof(mbstate)); - if (mbsrtowcs(fmtbuf, &p, BUFSIZE, &mbstate) - == (size_t) -1) { - goto error; - } else if (p != NULL) { - errno = E2BIG; - goto error; - } + xmbstowcs(fmtbuf, p, BUFSIZE); str = fmtbuf; } } diff --git a/src/system.h b/src/system.h index 4b1732a..c9342a7 100644 --- a/src/system.h +++ b/src/system.h @@ -55,6 +55,7 @@ #include #include #include +#include #include #include #include diff --git a/src/utils.c b/src/utils.c index 7b0adac..3d9cfd5 100644 --- a/src/utils.c +++ b/src/utils.c @@ -507,5 +507,81 @@ wchar_t *xwcsdup (const wchar_t *str) } +/***********************************************************************/ +// xmbstowcs: Convert a multibyte string to a wide-character string + +size_t xmbstowcs (wchar_t *restrict dest, const char *restrict src, size_t len) +{ + assert(dest != NULL); + assert(len > 0); + + char *s = xstrdup(src); + size_t n; + + while (true) { + mbstate_t mbstate; + char *p = s; + + memset(&mbstate, 0, sizeof(mbstate)); + if ((n = mbsrtowcs(dest, (const char **) &p, len, &mbstate)) + == (size_t) -1) { + if (errno == EILSEQ) { + // Illegal sequence detected: replace it and try again + *p = EILSEQ_REPL; + } else { + errno_exit(_("xmbstowcs: `%s'"), src); + } + } else if (p != NULL) { + // Multibyte string was too long: truncate dest + dest[len - 1] = '\0'; + n--; + break; + } else { + break; + } + } + + free(s); + return n; +} + + +/***********************************************************************/ +// xwcrtomb: Convert a wide character to a multibyte sequence + +size_t xwcrtomb (char *restrict dest, wchar_t wc, mbstate_t *restrict mbstate) +{ + mbstate_t mbcopy; + size_t n; + + + assert(dest != NULL); + assert(mbstate != NULL); + + memcpy(&mbcopy, mbstate, sizeof(mbcopy)); + + if ((n = wcrtomb(dest, wc, &mbcopy)) == (size_t) -1) { + if (errno == EILSEQ) { + /* wc cannot be represented in current locale. + + Note that the shift state in mbcopy is now undefined. + Hence, restore the original, try to store an ending shift + sequence, then EILSEQ_REPL. */ + memcpy(&mbcopy, mbstate, sizeof(mbcopy)); + if ((n = wcrtomb(dest, '\0', &mbcopy)) == (size_t) -1) { + errno_exit(_("xwcrtomb: NUL")); + } + dest[n] = EILSEQ_REPL; + dest[n++] = '\0'; + } else { + errno_exit(_("xwcrtomb: `%lc'"), wc); + } + } + + memcpy(mbstate, &mbcopy, sizeof(mbcopy)); + return n; +} + + /***********************************************************************/ // End of file diff --git a/src/utils.h b/src/utils.h index 88699ba..6d0079f 100644 --- a/src/utils.h +++ b/src/utils.h @@ -343,4 +343,37 @@ extern char *xstrdup (const char *str); extern wchar_t *xwcsdup (const wchar_t *str); +/* + Function: xmbstowcs - Convert a multibyte string to a wide-character string + Parameters: dest - Location of wide-string buffer + src - String to convert + len - Size of dest, in multiples of wchar_t + Returns: size_t - Number of characters placed in dest (excluding NUL) + + This wrapper function converts a multibyte string to a wide-character + one by calling mbrtowc() continually until the whole string is + converted. If any illegal sequences are present, they are converted to + the EILSEQ_REPL character. If the destination buffer is too small, the + string is truncated. +*/ +extern size_t xmbstowcs (wchar_t *restrict dest, const char *restrict src, + size_t len); + + +/* + Function: xwcrtomb - Convert a wide character to a multibyte sequence + Parameters: dest - Location of multibyte buffer (size >= MB_CUR_MAX + 1) + wc - Character to convert + mbstate - Pointer to current multibyte shift state + Returns: size_t - Number of characters placed in dest + + This wrapper function converts the wide character in wc (which may be + NUL) by calling wcrtomb(). If wc cannot be represented in the current + locale, EILSEQ_REPL is used instead (with any characters needed to move + to an initial shift state prior to EILSEQ_REPL). +*/ +extern size_t xwcrtomb (char *restrict dest, wchar_t wc, + mbstate_t *restrict mbstate); + + #endif /* included_UTILS_H */ From 4d145813ff1ad2449c86b9976d69379505e4884d Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Sat, 20 Aug 2011 13:27:26 +1000 Subject: [PATCH 075/112] Make the show_help() function multibyte-aware All text in the show_help() function is now processed as wide characters. --- src/help.c | 227 +++++++++++++++++++++++++++++++++------------------ src/trader.h | 1 + 2 files changed, 147 insertions(+), 81 deletions(-) diff --git a/src/help.c b/src/help.c index e95ae21..23be6a6 100644 --- a/src/help.c +++ b/src/help.c @@ -35,19 +35,24 @@ * Help text definition * ************************************************************************/ -static const char *help_text[] = { +#define HELP_TEXT_PAGES 10 + +static const char *help_text[HELP_TEXT_PAGES] = { /* TRANSLATORS: The help text for Star Traders is marked up using a custom mark-up format NOT used anywhere else in the source code. Each string is a single page of text that is displayed in an area 76 - columns wide by 16 lines high. Ideally, each line within the string - should be (manually) space-justified or centred; each line is - separated by "\n". TAB characters and other control codes must NOT - be used. If a string starts with "@" as the very first character, - that string (and all strings following) are ignored: this allows a - variable number of help text pages (from one to twelve). + columns wide by 16 lines high. Each line is delimited by "\n". NO + word-wrapping is performed: you must place the "\n" characters in the + appropriate place. Ideally, each line within the string should be + also (manually) space-justified or centred. TAB characters and other + control codes must NOT be used. If a string starts with "@" as the + very first character, that string is ignored (as are all strings + following): this allows a variable number of help text pages (from + one to ten). Multibyte strings are handled correctly (even those + requiring shift sequences!). The ASCII circumflex accent character "^" switches to a different character rendition (also called attributes), depending on the @@ -74,23 +79,26 @@ static const char *help_text[] = { ~m - Print the number of moves available (NUMBER_MOVES) [**] ~c - Print the maximum number of companies that can be formed (MAX_COMPANIES) [*] ~t - Prints the default number of turns in the game (DEFAULT_MAX_TURN) [**] - ~1 to ~9 - Print the keycode for the N-th choice of move [*] - ~M - Print the keycode for the last choice of move [*] - ~A to ~H - Print the character used to represent the company on the galaxy map [*] - ~. - Print the character used to represent empty space on the map [*] - ~+ - Print the character used to represent outposts on the map [*] - ~* - Print the character used to represent stars on the map [*] + ~1 to ~9 - Print the keycode for the N-th choice of move [***] + ~M - Print the keycode for the last choice of move [***] + ~A to ~H - Print the character used to represent the company on the galaxy map [***] + ~. - Print the character used to represent empty space on the map [***] + ~+ - Print the character used to represent outposts on the map [***] + ~* - Print the character used to represent stars on the map [***] - [*] Takes one character space in the output - [**] Takes two character spaces in the output + [*] Takes one character space (column space) in the output + [**] Takes two column spaces in the output + [***] Takes one or two column spaces in the output, depending on the + appropriate strings in the current PO file. Note that all keycodes and map representation characters use locale- - specific characters. Note also that the tilde value escapes do NOT - change the current character rendition: a circumflex accent escape is - needed for that. For example, to display the first choice of move as - it would be shown on the galaxy map, use something like "^k~1^N" (a - six-character sequence that would translate to just one character in - the output text). + specific characters; double-width characters ARE supported. Note + also that the tilde value escapes do NOT change the current character + rendition: a circumflex accent escape is needed for that. For + example, to display the first choice of move as it would be shown on + the galaxy map, use something like "^k~1^N" (a six-character sequence + that would translate to just one character (or maybe two) in the + output text). */ N_("" "^BStar Traders^N is a simple game of interstellar trading. The object of the\n" @@ -201,18 +209,14 @@ static const char *help_text[] = { "\n" "The ^Bwinner of the game^N is the person with the greatest net worth (total\n" "value of cash, stock and debt). ^HGood luck^N and may the best person win!\n" - ""), + "") #ifdef ENABLE_NLS - N_("@ Help text, page 7"), - N_("@ Help text, page 8"), - N_("@ Help text, page 9"), - N_("@ Help text, page 10"), - N_("@ Help text, page 11"), - N_("@ Help text, page 12"), + , N_("@ Help text, page 7") + , N_("@ Help text, page 8") + , N_("@ Help text, page 9") + , N_("@ Help text, page 10") #endif - - NULL }; @@ -228,21 +232,31 @@ static const char *help_text[] = { void show_help (void) { + wchar_t *wchelp_text[HELP_TEXT_PAGES]; + wchar_t *wcbuf = xmalloc(BIGBUFSIZE * sizeof(wchar_t)); + chtype *outbuf = xmalloc(BIGBUFSIZE * sizeof(chtype)); + int curpage = 0; int numpages = 0; bool done = false; // Count how many pages appear in the (translated) help text - while (help_text[numpages] != NULL) { + while (numpages < HELP_TEXT_PAGES) { const char *s = gettext(help_text[numpages]); if (s == NULL || *s == '\0' || *s == '@') break; + + xmbstowcs(wcbuf, s, BIGBUFSIZE); + wchelp_text[numpages] = xwcsdup(wcbuf); numpages++; } - if (numpages == 0) + if (numpages == 0) { + free(outbuf); + free(wcbuf); return; + } newtxwin(WIN_LINES - 1, WIN_COLS, 1, WCENTER, false, 0); @@ -260,100 +274,108 @@ void show_help (void) // Process the help text string - const char *s = gettext(help_text[curpage]); + const wchar_t *htxt = wchelp_text[curpage]; + char convbuf[MB_LEN_MAX + 1]; + char *cp; + mbstate_t mbstate; + chtype *outp; + wchar_t c; + size_t i, n; + + int count = BIGBUFSIZE; + int maxchar = MB_CUR_MAX; int curattr = attr_normal; - while (*s != '\0') { - switch (*s) { + memset(&mbstate, 0, sizeof(mbstate)); + outp = outbuf; + + while (*htxt != '\0' && count > maxchar * 2) { + switch (*htxt) { case '\n': - // Start a new line, suitably indented - wmove(curwin, getcury(curwin) + 1, 2); + // Start a new line + *outp++ = '\n'; + count--; break; case '^': // Switch to a different character rendition - switch (*++s) { + switch (*++htxt) { case '^': - waddch(curwin, *s | curattr); - break; + wcbuf[0] = *htxt; + wcbuf[1] = '\0'; + goto addwcbuf; case 'N': curattr = attr_normal; - wattrset(curwin, curattr); break; case 'B': curattr = attr_normal | A_BOLD; - wattrset(curwin, curattr); break; case 'H': curattr = attr_highlight; - wattrset(curwin, curattr); break; case 'K': curattr = attr_keycode; - wattrset(curwin, curattr); break; case 'e': curattr = attr_map_empty; - wattrset(curwin, curattr); break; case 'o': curattr = attr_map_outpost; - wattrset(curwin, curattr); break; case 's': curattr = attr_map_star; - wattrset(curwin, curattr); break; case 'c': curattr = attr_map_company; - wattrset(curwin, curattr); break; case 'k': curattr = attr_map_choice; - wattrset(curwin, curattr); break; default: - waddch(curwin, '^' | curattr); - waddch(curwin, *s | curattr); + wcbuf[0] = '^'; + wcbuf[1] = *htxt; + wcbuf[2] = '\0'; + goto addwcbuf; } break; case '~': // Print a global constant - switch (*++s) { + switch (*++htxt) { case '~': - waddch(curwin, *s | curattr); - break; + wcbuf[0] = *htxt; + wcbuf[1] = '\0'; + goto addwcbuf; case 'x': - wprintw(curwin, "%2d", MAX_X); - break; + swprintf(wcbuf, BIGBUFSIZE, L"%2d", MAX_X); + goto addwcbuf; case 'y': - wprintw(curwin, "%2d", MAX_Y); - break; + swprintf(wcbuf, BIGBUFSIZE, L"%2d", MAX_Y); + goto addwcbuf; case 'm': - wprintw(curwin, "%2d", NUMBER_MOVES); - break; + swprintf(wcbuf, BIGBUFSIZE, L"%2d", NUMBER_MOVES); + goto addwcbuf; case 'c': - wprintw(curwin, "%d", MAX_COMPANIES); - break; + swprintf(wcbuf, BIGBUFSIZE, L"%d", MAX_COMPANIES); + goto addwcbuf; case 't': - wprintw(curwin, "%2d", DEFAULT_MAX_TURN); - break; + swprintf(wcbuf, BIGBUFSIZE, L"%2d", DEFAULT_MAX_TURN); + goto addwcbuf; case '1': case '2': @@ -365,28 +387,38 @@ void show_help (void) case '8': case '9': // N-th choice of move, as a key press - wprintw(curwin, "%c", PRINTABLE_GAME_MOVE(*s - '1')); - break; + c = btowc(PRINTABLE_GAME_MOVE(*htxt - L'1')); + wcbuf[0] = (c == WEOF) ? EILSEQ_REPL : c; + wcbuf[1] = '\0'; + goto addwcbuf; case 'M': // Last choice of move, as a key press - wprintw(curwin, "%c", PRINTABLE_GAME_MOVE(NUMBER_MOVES - 1)); - break; + c = btowc(PRINTABLE_GAME_MOVE(NUMBER_MOVES - 1)); + wcbuf[0] = (c == WEOF) ? EILSEQ_REPL : c; + wcbuf[1] = '\0'; + goto addwcbuf; case '.': // Map representation of empty space - wprintw(curwin, "%c", PRINTABLE_MAP_VAL(MAP_EMPTY)); - break; + c = btowc(PRINTABLE_MAP_VAL(MAP_EMPTY)); + wcbuf[0] = (c == WEOF) ? EILSEQ_REPL : c; + wcbuf[1] = '\0'; + goto addwcbuf; case '+': // Map representation of an outpost - wprintw(curwin, "%c", PRINTABLE_MAP_VAL(MAP_OUTPOST)); - break; + c = btowc(PRINTABLE_MAP_VAL(MAP_OUTPOST)); + wcbuf[0] = (c == WEOF) ? EILSEQ_REPL : c; + wcbuf[1] = '\0'; + goto addwcbuf; case '*': // Map representation of a star - wprintw(curwin, "%c", PRINTABLE_MAP_VAL(MAP_STAR)); - break; + c = btowc(PRINTABLE_MAP_VAL(MAP_STAR)); + wcbuf[0] = (c == WEOF) ? EILSEQ_REPL : c; + wcbuf[1] = '\0'; + goto addwcbuf; case 'A': case 'B': @@ -397,22 +429,49 @@ void show_help (void) case 'G': case 'H': // Map representation of company - wprintw(curwin, "%c", - PRINTABLE_MAP_VAL(COMPANY_TO_MAP(*s - 'A'))); - break; + c = btowc(PRINTABLE_MAP_VAL(COMPANY_TO_MAP(*htxt - L'A'))); + wcbuf[0] = (c == WEOF) ? EILSEQ_REPL : c; + wcbuf[1] = '\0'; + goto addwcbuf; default: - waddch(curwin, '~' | curattr); - waddch(curwin, *s | curattr); + wcbuf[0] = '~'; + wcbuf[1] = *htxt; + goto addwcbuf; } break; default: // Print the character - waddch(curwin, *s | curattr); + wcbuf[0] = *htxt; + wcbuf[1] = '\0'; + + addwcbuf: + for (wchar_t *p = wcbuf; *p != '\0' && count > maxchar * 2; p++) { + n = xwcrtomb(convbuf, *p, &mbstate); + for (i = 0, cp = convbuf; i < n; i++, cp++, outp++, count--) { + *outp = (unsigned char) *cp | curattr; + } + } } - s++; + htxt++; + } + + // Add the terminating NUL (possibly with a preceding shift sequence) + n = xwcrtomb(convbuf, '\0', &mbstate); + for (i = 0, cp = convbuf; i < n; i++, cp++, outp++, count--) { + *outp = (unsigned char) *cp; + } + assert(count >= 0); + + // Display the formatted text in outbuf + for (outp = outbuf; *outp != '\0'; outp++) { + if (*outp == '\n') { + wmove(curwin, getcury(curwin) + 1, 2); + } else { + waddch(curwin, *outp); + } } center(curwin, getmaxy(curwin) - 2, 0, attr_waitforkey, 0, 0, 1, @@ -461,4 +520,10 @@ void show_help (void) deltxwin(); txrefresh(); + + for (curpage = 0; curpage < numpages; curpage++) { + free(wchelp_text[curpage]); + } + free(outbuf); + free(wcbuf); } diff --git a/src/trader.h b/src/trader.h index 1cc785b..0c61045 100644 --- a/src/trader.h +++ b/src/trader.h @@ -61,6 +61,7 @@ #endif #define BUFSIZE 1024 // For various string buffers +#define BIGBUFSIZE 2048 // For buffers known to be larger #endif /* included_TRADER_H */ From c90265ec28a23ad643ec19a3459335da26b75950 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Sat, 20 Aug 2011 13:30:31 +1000 Subject: [PATCH 076/112] Replace "---" with "--": it looks better in text mode --- src/help.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/help.c b/src/help.c index 23be6a6..5c82752 100644 --- a/src/help.c +++ b/src/help.c @@ -196,9 +196,9 @@ static const char *help_text[HELP_TEXT_PAGES] = { "Once you select your move, you enter the ^BInterstellar Stock Exchange^N. Here\n" "you may purchase shares, sell them, borrow from the Trading Bank or repay\n" "some of your debt (if applicable). Note that each company issues a limited\n" - "number of shares --- you cannot go on buying for ever! You may, however,\n" - "bid for more shares to be issued. You have a better chance of succeeding if\n" - "you own a larger proportion of the company.\n" + "number of shares -- you cannot go on buying for ever! You may, however, bid\n" + "for more shares to be issued. You have a better chance of succeeding if you\n" + "own a larger proportion of the company.\n" "\n" "The game usually ends after ^B~t^N turns. However, you may end the game sooner\n" "by pressing ^K^N when asked to select a move. As well, individual\n" From bc8dc76f00c119da59432f34e7ae2628119a9d88 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Sat, 20 Aug 2011 13:34:28 +1000 Subject: [PATCH 077/112] Minor white-space formatting change: indent by 8 characters, not 7 --- src/help.c | 210 ++++++++++++++++++++++++++--------------------------- 1 file changed, 105 insertions(+), 105 deletions(-) diff --git a/src/help.c b/src/help.c index 5c82752..f8a8451 100644 --- a/src/help.c +++ b/src/help.c @@ -100,116 +100,116 @@ static const char *help_text[HELP_TEXT_PAGES] = { that would translate to just one character (or maybe two) in the output text). */ - N_("" - "^BStar Traders^N is a simple game of interstellar trading. The object of the\n" - "game is to amass the greatest amount of wealth possible. This is done by\n" - "creating interstellar shipping lanes, expanding them and buying shares in\n" - "the companies controlling them. Shares appreciate in value as company\n" - "operations expand. In addition, the return on each share (as a percentage)\n" - "also changes. Players may also borrow from the Interstellar Trading Bank to\n" - "finance additional purchases on the Stock Exchange.\n" - "\n" - "The map of the galaxy is represented by a ^B~x^N x ^B~y^N grid. A typical section\n" - "of it may be:\n" - "\n" - " ^e ~. ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" - " ^e ~. ~. ~. ~. ~. ~. ~. ~. ~. ^N ^e ~. ^N represents ^Bempty space^N,\n" - " ^e ~. ^s~*^e ~. ~. ~. ~. ~. ~. ~. ^N ^s ~* ^N represents a ^Bstar^N.\n" - " ^e ~. ~. ~. ~. ~. ~. ~. ^s~*^e ~. ^N\n" - " ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ~. ^N\n" - ""), + N_( "" + "^BStar Traders^N is a simple game of interstellar trading. The object of the\n" + "game is to amass the greatest amount of wealth possible. This is done by\n" + "creating interstellar shipping lanes, expanding them and buying shares in\n" + "the companies controlling them. Shares appreciate in value as company\n" + "operations expand. In addition, the return on each share (as a percentage)\n" + "also changes. Players may also borrow from the Interstellar Trading Bank to\n" + "finance additional purchases on the Stock Exchange.\n" + "\n" + "The map of the galaxy is represented by a ^B~x^N x ^B~y^N grid. A typical section\n" + "of it may be:\n" + "\n" + " ^e ~. ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" + " ^e ~. ~. ~. ~. ~. ~. ~. ~. ~. ^N ^e ~. ^N represents ^Bempty space^N,\n" + " ^e ~. ^s~*^e ~. ~. ~. ~. ~. ~. ~. ^N ^s ~* ^N represents a ^Bstar^N.\n" + " ^e ~. ~. ~. ~. ~. ~. ~. ^s~*^e ~. ^N\n" + " ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ~. ^N\n" + ""), - N_("" - "The computer selects ^B~m^N moves (labeled ^k~1^N to ^k~M^N) at random, and places these\n" - "on the map. To select any of the highlighted positions, press that letter.\n" - "For example, some of the moves on the map may be:\n" - "\n" - "\n" - " ^e ^k~1^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" - " ^e ~. ~. ~. ^k~3^e ~. ~. ~. ~. ~. ^N\n" - " ^e ~. ^s~*^e ~. ~. ~. ~. ^k~5^e ~. ~. ^N Moves ^k~1^N to ^k~5^N shown.\n" - " ^e ~. ^k~2^e ~. ~. ^k~4^e ~. ~. ^s~*^e ~. ^N\n" - " ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ~. ^N\n" - "\n" - "\n" - "Selecting a position that is ^Bnot^N next to a star (such as moves ^k~1^N, ^k~3^N or ^k~5^N)\n" - "will set up an ^Boutpost^N, not belonging to any company. Thus, if move ^k~3^N is\n" - "selected on the above map, a ^o ~+ ^N would be placed at that position.\n" - ""), + N_( "" + "The computer selects ^B~m^N moves (labeled ^k~1^N to ^k~M^N) at random, and places these\n" + "on the map. To select any of the highlighted positions, press that letter.\n" + "For example, some of the moves on the map may be:\n" + "\n" + "\n" + " ^e ^k~1^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" + " ^e ~. ~. ~. ^k~3^e ~. ~. ~. ~. ~. ^N\n" + " ^e ~. ^s~*^e ~. ~. ~. ~. ^k~5^e ~. ~. ^N Moves ^k~1^N to ^k~5^N shown.\n" + " ^e ~. ^k~2^e ~. ~. ^k~4^e ~. ~. ^s~*^e ~. ^N\n" + " ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ~. ^N\n" + "\n" + "\n" + "Selecting a position that is ^Bnot^N next to a star (such as moves ^k~1^N, ^k~3^N or ^k~5^N)\n" + "will set up an ^Boutpost^N, not belonging to any company. Thus, if move ^k~3^N is\n" + "selected on the above map, a ^o ~+ ^N would be placed at that position.\n" + ""), - N_("" - "If, on the other hand, a position next to a star (or another outpost) is\n" - "selected, a ^Bcompany^N would be formed and its letter would appear on the map.\n" - "As a reward for creating the company, you are granted the first five shares.\n" - "Up to ^B~c^N companies can be created in this way.\n" - "\n" - "If a position next to an existing company is selected, the company would\n" - "expand its operations by one square. This increases the cost of its shares\n" - "and hence your return. Thus, if the map was as shown below, selecting ^k~6^N\n" - "or ^k~8^N increases Company ^B~B^N's shipping lane:\n" - "\n" - " ^e ^k~1^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" - " ^e ~. ~. ~. ^o~+^e ~. ~. ^k~6^e ~. ~. ^N\n" - " ^e ~. ^s~*^e ~. ~. ~. ~. ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~6^N or ^k~8^N increases Company ^B~B^N.\n" - " ^e ~. ^k~2^e ~. ~. ^k~4^e ~. ~. ^s~*^e ^c~B^e ^N\n" - " ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ^k~8^e ^N\n" - ""), + N_( "" + "If, on the other hand, a position next to a star (or another outpost) is\n" + "selected, a ^Bcompany^N would be formed and its letter would appear on the map.\n" + "As a reward for creating the company, you are granted the first five shares.\n" + "Up to ^B~c^N companies can be created in this way.\n" + "\n" + "If a position next to an existing company is selected, the company would\n" + "expand its operations by one square. This increases the cost of its shares\n" + "and hence your return. Thus, if the map was as shown below, selecting ^k~6^N\n" + "or ^k~8^N increases Company ^B~B^N's shipping lane:\n" + "\n" + " ^e ^k~1^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" + " ^e ~. ~. ~. ^o~+^e ~. ~. ^k~6^e ~. ~. ^N\n" + " ^e ~. ^s~*^e ~. ~. ~. ~. ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~6^N or ^k~8^N increases Company ^B~B^N.\n" + " ^e ~. ^k~2^e ~. ~. ^k~4^e ~. ~. ^s~*^e ^c~B^e ^N\n" + " ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ^k~8^e ^N\n" + ""), - N_("" - "Selecting positions next to stars increases the value of your stock by about\n" - "five times as much as an extension not next to a star. Thus move ^k~6^N should\n" - "be preferred to move ^k~8^N.\n" - "\n" - " ^e ^c~C^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" - " ^e ^k~1^e ^o~+^e ~. ^o~+^e ~. ~. ^k~6^e ~. ~. ^N\n" - " ^e ~. ^s~*^e ~. ~. ~. ~. ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~6^N is preferred to ^k~8^N.\n" - " ^e ~. ^k~2^e ~. ~. ^k~4^e ~. ~. ^s~*^e ^c~B^e ^N\n" - " ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ^k~8^e ^N\n" - "\n" - "You may also expand any company by selecting positions next to outposts.\n" - "Such outposts will be swallowed up by that company. Thus, move ^k~1^N will\n" - "extend Company ^B~C^N by ^Btwo^N squares. As a bonus, outposts next to stars are\n" - "more valuable: the company's share price will increase by a greater amount\n" - "than it would for outposts not next to stars.\n" - ""), + N_( "" + "Selecting positions next to stars increases the value of your stock by about\n" + "five times as much as an extension not next to a star. Thus move ^k~6^N should\n" + "be preferred to move ^k~8^N.\n" + "\n" + " ^e ^c~C^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" + " ^e ^k~1^e ^o~+^e ~. ^o~+^e ~. ~. ^k~6^e ~. ~. ^N\n" + " ^e ~. ^s~*^e ~. ~. ~. ~. ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~6^N is preferred to ^k~8^N.\n" + " ^e ~. ^k~2^e ~. ~. ^k~4^e ~. ~. ^s~*^e ^c~B^e ^N\n" + " ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ^k~8^e ^N\n" + "\n" + "You may also expand any company by selecting positions next to outposts.\n" + "Such outposts will be swallowed up by that company. Thus, move ^k~1^N will\n" + "extend Company ^B~C^N by ^Btwo^N squares. As a bonus, outposts next to stars are\n" + "more valuable: the company's share price will increase by a greater amount\n" + "than it would for outposts not next to stars.\n" + ""), - N_("" - "If two companies are separated on the map by only one square, then they can\n" - "be ^Bmerged^N into one company by selecting that position (if available). For\n" - "example, on the map below, companies ^B~A^N and ^B~B^N can be merged by selecting ^k~5^N.\n" - "When this occurs, the company with the greater assets value takes over the\n" - "other one. Here, Company ^B~B^N might take over Company ^B~A^N. Company ^B~A^N ceases to\n" - "exist, although it may reappear as an entirely new company at a later stage.\n" - "\n" - " ^e ^k~1^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" - " ^e ~. ~. ~. ^c~A^e ^c~A^e ^k~5^e ^c~B^e ~. ~. ^N\n" - " ^e ~. ^s~*^e ~. ~. ^c~A^e ~. ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~5^N merges companies ^B~A^N and ^B~B^N.\n" - " ^e ~. ^k~2^e ~. ~. ~. ~. ~. ^s~*^e ^c~B^e ^N\n" - " ^e ~. ~. ~. ~. ^s~*^e ~. ^o~+^e ~. ~. ^N\n" - "\n" - "When companies merge, players are granted shares in the dominant company\n" - "proportional to the amount owned in the old company. As well, a cash bonus\n" - "is also paid, proportional to the percentage of the old company owned.\n" - ""), + N_( "" + "If two companies are separated on the map by only one square, then they can\n" + "be ^Bmerged^N into one company by selecting that position (if available). For\n" + "example, on the map below, companies ^B~A^N and ^B~B^N can be merged by selecting ^k~5^N.\n" + "When this occurs, the company with the greater assets value takes over the\n" + "other one. Here, Company ^B~B^N might take over Company ^B~A^N. Company ^B~A^N ceases to\n" + "exist, although it may reappear as an entirely new company at a later stage.\n" + "\n" + " ^e ^k~1^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" + " ^e ~. ~. ~. ^c~A^e ^c~A^e ^k~5^e ^c~B^e ~. ~. ^N\n" + " ^e ~. ^s~*^e ~. ~. ^c~A^e ~. ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~5^N merges companies ^B~A^N and ^B~B^N.\n" + " ^e ~. ^k~2^e ~. ~. ~. ~. ~. ^s~*^e ^c~B^e ^N\n" + " ^e ~. ~. ~. ~. ^s~*^e ~. ^o~+^e ~. ~. ^N\n" + "\n" + "When companies merge, players are granted shares in the dominant company\n" + "proportional to the amount owned in the old company. As well, a cash bonus\n" + "is also paid, proportional to the percentage of the old company owned.\n" + ""), - N_("" - "Once you select your move, you enter the ^BInterstellar Stock Exchange^N. Here\n" - "you may purchase shares, sell them, borrow from the Trading Bank or repay\n" - "some of your debt (if applicable). Note that each company issues a limited\n" - "number of shares -- you cannot go on buying for ever! You may, however, bid\n" - "for more shares to be issued. You have a better chance of succeeding if you\n" - "own a larger proportion of the company.\n" - "\n" - "The game usually ends after ^B~t^N turns. However, you may end the game sooner\n" - "by pressing ^K^N when asked to select a move. As well, individual\n" - "players can declare themselves bankrupt at any time. If your debt is large\n" - "enough, the Bank may do this for you! If you do not complete your game in\n" - "the time you have available, you may save the game and continue it later.\n" - "\n" - "\n" - "The ^Bwinner of the game^N is the person with the greatest net worth (total\n" - "value of cash, stock and debt). ^HGood luck^N and may the best person win!\n" - "") + N_( "" + "Once you select your move, you enter the ^BInterstellar Stock Exchange^N. Here\n" + "you may purchase shares, sell them, borrow from the Trading Bank or repay\n" + "some of your debt (if applicable). Note that each company issues a limited\n" + "number of shares -- you cannot go on buying for ever! You may, however, bid\n" + "for more shares to be issued. You have a better chance of succeeding if you\n" + "own a larger proportion of the company.\n" + "\n" + "The game usually ends after ^B~t^N turns. However, you may end the game sooner\n" + "by pressing ^K^N when asked to select a move. As well, individual\n" + "players can declare themselves bankrupt at any time. If your debt is large\n" + "enough, the Bank may do this for you! If you do not complete your game in\n" + "the time you have available, you may save the game and continue it later.\n" + "\n" + "\n" + "The ^Bwinner of the game^N is the person with the greatest net worth (total\n" + "value of cash, stock and debt). ^HGood luck^N and may the best person win!\n" + "") #ifdef ENABLE_NLS , N_("@ Help text, page 7") From b5b211313e58c42d92a9c66b63193ba5a827bdff Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Sat, 20 Aug 2011 15:17:09 +1000 Subject: [PATCH 078/112] Move chstrdup() to utils.c and rename it to xchstrdup() The new name is for consistency with other XXXdup() functions used in this program. --- src/exch.c | 4 ++-- src/intf.c | 22 ---------------------- src/intf.h | 13 ------------- src/move.c | 6 +++--- src/utils.c | 22 ++++++++++++++++++++++ src/utils.h | 13 +++++++++++++ 6 files changed, 40 insertions(+), 40 deletions(-) diff --git a/src/exch.c b/src/exch.c index 19ff2d0..caf814d 100644 --- a/src/exch.c +++ b/src/exch.c @@ -412,7 +412,7 @@ void visit_bank (void) mkchstr(chbuf, BUFSIZE, attr_normal, attr_normal | A_BOLD, 0, 1, getmaxx(curwin) / 2, &width_cursym, 1, "^{%s^}", lconvinfo.currency_symbol); - chbuf_cursym = chstrdup(chbuf); + chbuf_cursym = xchstrdup(chbuf); mkchstr(chbuf, BUFSIZE, attr_normal, 0, 0, 1, getmaxx(curwin) - BANK_INPUT_COLS - width_cursym - 6, &width, 1, @@ -470,7 +470,7 @@ void visit_bank (void) mkchstr(chbuf, BUFSIZE, attr_normal, attr_normal | A_BOLD, 0, 1, getmaxx(curwin) / 2, &width_cursym, 1, "^{%s^}", lconvinfo.currency_symbol); - chbuf_cursym = chstrdup(chbuf); + chbuf_cursym = xchstrdup(chbuf); mkchstr(chbuf, BUFSIZE, attr_normal, 0, 0, 1, getmaxx(curwin) - BANK_INPUT_COLS - width_cursym - 6, &width, 1, diff --git a/src/intf.c b/src/intf.c index 46cc3e8..cab54de 100644 --- a/src/intf.c +++ b/src/intf.c @@ -1391,28 +1391,6 @@ error: } -/***********************************************************************/ -// chstrdup: Duplicate a chtype buffer - -chtype *chstrdup (const chtype *restrict chstr) -{ - const chtype *p; - int len; - chtype *ret; - - - // Determine chstr length, including ending NUL - for (len = 1, p = chstr; *p != '\0'; p++, len++) - ; - - ret = xmalloc(len * sizeof(chtype)); - memcpy(ret, chstr, len * sizeof(chtype)); - ret[len - 1] = '\0'; // Terminating NUL, just in case not present - - return ret; -} - - /***********************************************************************/ // leftch: Print strings in chstr left-aligned diff --git a/src/intf.h b/src/intf.h index 9fcb017..8a27e0c 100644 --- a/src/intf.h +++ b/src/intf.h @@ -408,19 +408,6 @@ extern int vmkchstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, const char *restrict format, va_list args); -/* - Function: chstrdup - Duplicate a chtype string - Parameters: chstr - String to duplicate - Returns: chtype * - Pointer to new (duplicated) string - - This function returns a new string of type chtype * that contains a - copy of the string in chstr. No errors are returned: if sufficient - memory is not available, the program terminates with an "Out of memory" - message. -*/ -extern chtype *chstrdup (const chtype *restrict chstr); - - /* Function: leftch - Print strings in chstr left-aligned Parameters: win - Window to use (should be curwin) diff --git a/src/move.c b/src/move.c index 353d73c..8382773 100644 --- a/src/move.c +++ b/src/move.c @@ -788,11 +788,11 @@ void merge_companies (map_val_t a, map_val_t b) mkchstr(chbuf, BUFSIZE, attr_highlight, 0, 0, 1, getmaxx(curwin) / 2, &width_aa, 1, "%s", company[aa].name); - chbuf_aa = chstrdup(chbuf); + chbuf_aa = xchstrdup(chbuf); mkchstr(chbuf, BUFSIZE, attr_highlight, 0, 0, 1, getmaxx(curwin) / 2, &width_bb, 1, "%s", company[bb].name); - chbuf_bb = chstrdup(chbuf); + chbuf_bb = xchstrdup(chbuf); mkchstr(chbuf, BUFSIZE, attr_normal, 0, 0, 1, getmaxx(curwin) / 2, &width, 1, @@ -1032,7 +1032,7 @@ void adjust_values (void) mkchstr(chbuf, BUFSIZE, attr_error_highlight, 0, 0, 1, w / 2, &width_amt, 1, "%N", company[which].share_price); - chbuf_amt = chstrdup(chbuf); + chbuf_amt = xchstrdup(chbuf); mkchstr(chbuf, BUFSIZE, attr_error_normal, 0, 0, 1, w / 2, &width, 1, diff --git a/src/utils.c b/src/utils.c index 3d9cfd5..c2a1dfd 100644 --- a/src/utils.c +++ b/src/utils.c @@ -487,6 +487,28 @@ char *xstrdup (const char *str) } +/***********************************************************************/ +// chstrdup: Duplicate a chtype buffer + +chtype *xchstrdup (const chtype *restrict chstr) +{ + const chtype *p; + int len; + chtype *ret; + + + // Determine chstr length, including ending NUL + for (len = 1, p = chstr; *p != '\0'; p++, len++) + ; + + ret = xmalloc(len * sizeof(chtype)); + memcpy(ret, chstr, len * sizeof(chtype)); + ret[len - 1] = '\0'; // Terminating NUL, just in case not present + + return ret; +} + + /***********************************************************************/ // xwcsdup: Duplicate a wide-character string, with checking diff --git a/src/utils.h b/src/utils.h index 6d0079f..7f7ada8 100644 --- a/src/utils.h +++ b/src/utils.h @@ -331,6 +331,19 @@ extern void *xmalloc (size_t size); extern char *xstrdup (const char *str); +/* + Function: xchstrdup - Duplicate a chtype string + Parameters: chstr - String to duplicate + Returns: chtype * - Pointer to new (duplicated) string + + This function returns a new string of type chtype * that contains a + copy of the string in chstr. No errors are returned: if sufficient + memory is not available, the program terminates with an "Out of memory" + message. +*/ +extern chtype *xchstrdup (const chtype *restrict chstr); + + /* Function: xwcsdup - Duplicate a wide-character string, with checking Parameters: str - String to duplicate From 0a8e05f4d4e183ca2d343eccb2a26341320c3ce6 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Sat, 20 Aug 2011 15:24:27 +1000 Subject: [PATCH 079/112] Rearrange the order of the internal mkchstr_XXX functions --- src/intf.c | 254 ++++++++++++++++++++++++++--------------------------- 1 file changed, 127 insertions(+), 127 deletions(-) diff --git a/src/intf.c b/src/intf.c index cab54de..fec3f46 100644 --- a/src/intf.c +++ b/src/intf.c @@ -176,6 +176,23 @@ static void txresize (void); #endif +/* + Function: mkchstr_parse - Parse the format string for mkchstr() + Parameters: format - Format string as described for mkchstr() + format_arg - Pointer to variable arguments array + format_spec - Pointer to conversion specifiers array + args - Variable argument list passed to mkchstr() + Returns: int - 0 if OK, -1 if error (with errno set) + + This helper function parses the format string passed to mkchstr(), + setting the format_arg and format_spec arrays appropriately. +*/ +static int mkchstr_parse (const wchar_t *restrict format, + struct argument *restrict format_arg, + struct convspec *restrict format_spec, + va_list args); + + /* Function: mkchstr_add - Add one character to the mkchstr() buffers Parameters: outbuf - Pointer to wchar_t pointer in which to store char @@ -212,23 +229,6 @@ static int mkchstr_add (wchar_t *restrict *restrict outbuf, int widthbufsize, const wchar_t *restrict *restrict str); -/* - Function: mkchstr_parse - Parse the format string for mkchstr() - Parameters: format - Format string as described for mkchstr() - format_arg - Pointer to variable arguments array - format_spec - Pointer to conversion specifiers array - args - Variable argument list passed to mkchstr() - Returns: int - 0 if OK, -1 if error (with errno set) - - This helper function parses the format string passed to mkchstr(), - setting the format_arg and format_spec arrays appropriately. -*/ -static int mkchstr_parse (const wchar_t *restrict format, - struct argument *restrict format_arg, - struct convspec *restrict format_spec, - va_list args); - - /* Function: mkchstr_conv - Convert (wcbuf, attrbuf) to chbuf Parameters: chbuf - Pointer to chtype buffer in which to store string @@ -674,116 +674,6 @@ int mkchstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, } -/***********************************************************************/ -// mkchstr_add: Add a character to the mkchstr buffer - -int mkchstr_add (wchar_t *restrict *restrict outbuf, - chtype *restrict *restrict attrbuf, int *restrict count, - chtype attr, int maxlines, int maxwidth, int *restrict line, - int *restrict width, wchar_t *restrict *restrict lastspc, - chtype *restrict *restrict spcattr, int *restrict widthspc, - int *restrict widthbuf, int widthbufsize, - const wchar_t *restrict *restrict str) -{ - int w, wspc; - - - if (*line < 0) { - // First character in buffer: start line 0 - *line = 0; - } - - if (**str == '\n') { - // Start a new line - - if (*line < maxlines - 1) { - *(*outbuf)++ = '\n'; - *(*attrbuf)++ = 0; - (*count)--; - } - - widthbuf[*line] = *width; - *width = 0; - - *lastspc = NULL; - *spcattr = NULL; - *widthspc = 0; - - (*line)++; - (*str)++; - } else { - w = wcwidth(**str); - if (w < 0) { - // We don't support control or non-printable characters - errno = EILSEQ; - return -1; - } - - if (*width + w > maxwidth) { - // Current line would be too long to fit in **str - - if (! iswspace(**str) && *lastspc != NULL && *line < maxlines - 1) { - // Break on the last space in this line - wspc = wcwidth(**lastspc); - - **lastspc = '\n'; - **spcattr = 0; - - widthbuf[*line] = *widthspc; - *width -= *widthspc + wspc; - - *lastspc = NULL; - *spcattr = NULL; - *widthspc = 0; - - (*line)++; - } else { - // Insert a new-line character (if not on last line) - if (*line < maxlines - 1) { - *(*outbuf)++ = '\n'; - *(*attrbuf)++ = 0; - (*count)--; - } - - widthbuf[*line] = *width; - *width = 0; - - *lastspc = NULL; - *spcattr = NULL; - *widthspc = 0; - - (*line)++; - - /* Skip any following spaces. This assumes that no-one - will ever have combining diacritical marks following a - (line-breaking) space! */ - while (iswspace(**str)) { - if (*(*str)++ == '\n') { - break; - } - } - } - } else { - // Insert an ordinary character into the output buffer - - if (iswspace(**str)) { - *lastspc = *outbuf; - *spcattr = *attrbuf; - *widthspc = *width; - } - - *(*outbuf)++ = **str; - *(*attrbuf)++ = attr; - (*count)--; - *width += w; - (*str)++; - } - } - - return 0; -} - - /***********************************************************************/ // mkchstr_parse: Parse the format string for mkchstr() @@ -1063,6 +953,116 @@ int mkchstr_parse (const wchar_t *restrict format, } +/***********************************************************************/ +// mkchstr_add: Add a character to the mkchstr buffer + +int mkchstr_add (wchar_t *restrict *restrict outbuf, + chtype *restrict *restrict attrbuf, int *restrict count, + chtype attr, int maxlines, int maxwidth, int *restrict line, + int *restrict width, wchar_t *restrict *restrict lastspc, + chtype *restrict *restrict spcattr, int *restrict widthspc, + int *restrict widthbuf, int widthbufsize, + const wchar_t *restrict *restrict str) +{ + int w, wspc; + + + if (*line < 0) { + // First character in buffer: start line 0 + *line = 0; + } + + if (**str == '\n') { + // Start a new line + + if (*line < maxlines - 1) { + *(*outbuf)++ = '\n'; + *(*attrbuf)++ = 0; + (*count)--; + } + + widthbuf[*line] = *width; + *width = 0; + + *lastspc = NULL; + *spcattr = NULL; + *widthspc = 0; + + (*line)++; + (*str)++; + } else { + w = wcwidth(**str); + if (w < 0) { + // We don't support control or non-printable characters + errno = EILSEQ; + return -1; + } + + if (*width + w > maxwidth) { + // Current line would be too long to fit in **str + + if (! iswspace(**str) && *lastspc != NULL && *line < maxlines - 1) { + // Break on the last space in this line + wspc = wcwidth(**lastspc); + + **lastspc = '\n'; + **spcattr = 0; + + widthbuf[*line] = *widthspc; + *width -= *widthspc + wspc; + + *lastspc = NULL; + *spcattr = NULL; + *widthspc = 0; + + (*line)++; + } else { + // Insert a new-line character (if not on last line) + if (*line < maxlines - 1) { + *(*outbuf)++ = '\n'; + *(*attrbuf)++ = 0; + (*count)--; + } + + widthbuf[*line] = *width; + *width = 0; + + *lastspc = NULL; + *spcattr = NULL; + *widthspc = 0; + + (*line)++; + + /* Skip any following spaces. This assumes that no-one + will ever have combining diacritical marks following a + (line-breaking) space! */ + while (iswspace(**str)) { + if (*(*str)++ == '\n') { + break; + } + } + } + } else { + // Insert an ordinary character into the output buffer + + if (iswspace(**str)) { + *lastspc = *outbuf; + *spcattr = *attrbuf; + *widthspc = *width; + } + + *(*outbuf)++ = **str; + *(*attrbuf)++ = attr; + (*count)--; + *width += w; + (*str)++; + } + } + + return 0; +} + + /***********************************************************************/ // mkchstr_conv: Convert (wcbuf, attrbuf) to chbuf From 4b8d2529a84af73f09791b5d371c04b902d95783 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Sat, 20 Aug 2011 15:27:22 +1000 Subject: [PATCH 080/112] Replace '0' with L'0', just in case --- src/intf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/intf.c b/src/intf.c index fec3f46..333c74a 100644 --- a/src/intf.c +++ b/src/intf.c @@ -742,7 +742,7 @@ int mkchstr_parse (const wchar_t *restrict format, case '8': case '9': // Part of some numeric count - count = count * 10 + (wc - '0'); + count = count * 10 + (wc - L'0'); break; case '$': From a4cc805a65e630804cc6f6ee360739f78ae6aab4 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Sat, 20 Aug 2011 15:38:26 +1000 Subject: [PATCH 081/112] Use wchar_t in answer_yesno() Calls to wgetch(win) do not use wchar_t for the moment. --- src/intf.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/intf.c b/src/intf.c index 333c74a..daec6f1 100644 --- a/src/intf.c +++ b/src/intf.c @@ -2458,8 +2458,8 @@ int gettxlong (WINDOW *win, long int *restrict result, long int min, bool answer_yesno (WINDOW *win) { - static char *keycode_yes; - static char *keycode_no; + static wchar_t *keycode_yes; + static wchar_t *keycode_no; bool ret; @@ -2468,12 +2468,18 @@ bool answer_yesno (WINDOW *win) if (keycode_yes == NULL) { + wchar_t *buf = xmalloc(BUFSIZE * sizeof(wchar_t)); + /* TRANSLATORS: The strings with msgctxt "input|Yes" and "input|No" contain the keycodes used to determine whether a user is answering "Yes" or "No" in response to some question. Both upper and lower-case versions should be present. */ - keycode_yes = xstrdup(pgettext("input|Yes", "Yy")); - keycode_no = xstrdup(pgettext("input|No", "Nn")); + xmbstowcs(buf, pgettext("input|Yes", "Yy"), BUFSIZE); + keycode_yes = xwcsdup(buf); + xmbstowcs(buf, pgettext("input|No", "Nn"), BUFSIZE); + keycode_no = xwcsdup(buf); + + free(buf); } @@ -2486,10 +2492,10 @@ bool answer_yesno (WINDOW *win) while (true) { int key = wgetch(win); - if (strchr(keycode_yes, key) != NULL) { + if (wcschr(keycode_yes, key) != NULL) { ret = true; break; - } else if (strchr(keycode_no, key) != NULL) { + } else if (wcschr(keycode_no, key) != NULL) { ret = false; break; } else From cf944c58f6300999a4af06537e0f69b4319f1b89 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Sat, 20 Aug 2011 15:49:19 +1000 Subject: [PATCH 082/112] Minor fix: we don't use mbrtowc() in our program --- src/utils.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils.h b/src/utils.h index 7f7ada8..49a5c3f 100644 --- a/src/utils.h +++ b/src/utils.h @@ -364,7 +364,7 @@ extern wchar_t *xwcsdup (const wchar_t *str); Returns: size_t - Number of characters placed in dest (excluding NUL) This wrapper function converts a multibyte string to a wide-character - one by calling mbrtowc() continually until the whole string is + one by calling mbsrtowcs() continually until the whole string is converted. If any illegal sequences are present, they are converted to the EILSEQ_REPL character. If the destination buffer is too small, the string is truncated. From 150bcf10c2ddea6c91d3d0684ac50c90a369fb67 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Sat, 20 Aug 2011 16:27:11 +1000 Subject: [PATCH 083/112] Try loading UTF-8 strings with transliteration, if at all possible Also fix a bug in save_game(): the iconv_open() parameters were the wrong way around! --- src/fileio.c | 14 +++++++++++--- src/trader.h | 1 + 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/fileio.c b/src/fileio.c index 15d2df4..1224695 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -258,9 +258,17 @@ bool load_game (int num) } need_icd = (strcmp(codeset, GAME_FILE_CHARSET) != 0); if (need_icd) { - icd = iconv_open(codeset, GAME_FILE_CHARSET); + // Try using the GNU libiconv "//TRANSLIT" option + strcpy(buf, codeset); + strcat(buf, GAME_FILE_TRANSLIT); + + icd = iconv_open(buf, GAME_FILE_CHARSET); if (icd == (iconv_t) -1) { - errno_exit("iconv_open"); + // Try iconv_open() without "//TRANSLIT" + icd = iconv_open(codeset, GAME_FILE_CHARSET); + if (icd == (iconv_t) -1) { + errno_exit("iconv_open"); + } } } else { icd = (iconv_t) -1; @@ -469,7 +477,7 @@ bool save_game (int num) } need_icd = (strcmp(codeset, GAME_FILE_CHARSET) != 0); if (need_icd) { - icd = iconv_open(codeset, GAME_FILE_CHARSET); + icd = iconv_open(GAME_FILE_CHARSET, codeset); if (icd == (iconv_t) -1) { errno_exit("iconv_open"); } diff --git a/src/trader.h b/src/trader.h index 0c61045..0ae2f4c 100644 --- a/src/trader.h +++ b/src/trader.h @@ -58,6 +58,7 @@ #ifdef USE_UTF8_GAME_FILE # define GAME_FILE_CHARSET "UTF-8" // For strings in game file +# define GAME_FILE_TRANSLIT "//TRANSLIT" // Transliterate (GNU libiconv) #endif #define BUFSIZE 1024 // For various string buffers From 07e9d30a668775b66b6f6c59494514e83b9350b3 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Mon, 22 Aug 2011 09:34:07 +1000 Subject: [PATCH 084/112] Add the module wctob from the GNU Portability Library --- lib/.gitignore | 3 +++ m4/.gitignore | 2 ++ m4/gnulib-cache.m4 | 3 ++- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/.gitignore b/lib/.gitignore index c2b6dae..69ee50e 100644 --- a/lib/.gitignore +++ b/lib/.gitignore @@ -114,6 +114,9 @@ wcsdup.c wcsrtombs-impl.h wcsrtombs-state.c wcsrtombs.c +wctob.c +wctomb-impl.h +wctomb.c wctype.in.h wcwidth.c wmemcpy-impl.h diff --git a/m4/.gitignore b/m4/.gitignore index 1ad61a1..2afe33d 100644 --- a/m4/.gitignore +++ b/m4/.gitignore @@ -112,6 +112,8 @@ wchar_t.m4 wcrtomb.m4 wcsdup.m4 wcsrtombs.m4 +wctob.m4 +wctomb.m4 wctype_h.m4 wcwidth.m4 wint_t.m4 diff --git a/m4/gnulib-cache.m4 b/m4/gnulib-cache.m4 index b6e250d..6bd0fcf 100644 --- a/m4/gnulib-cache.m4 +++ b/m4/gnulib-cache.m4 @@ -15,7 +15,7 @@ # Specification in the form of a command-line invocation: -# gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --no-conditional-dependencies --no-libtool --macro-prefix=gl assert btowc config-h ctype fprintf-posix getopt-gnu gettext gettext-h gettimeofday langinfo locale mbrtowc mbsrtowcs printf-posix sigaction signal snprintf-posix stat stdarg stdbool stdio strdup-posix striconv string strncat strstr sys_stat sys_time unistd vfprintf-posix vsnprintf-posix wchar wcrtomb wcsdup wcsrtombs wctype-h wcwidth +# gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --no-conditional-dependencies --no-libtool --macro-prefix=gl assert btowc config-h ctype fprintf-posix getopt-gnu gettext gettext-h gettimeofday langinfo locale mbrtowc mbsrtowcs printf-posix sigaction signal snprintf-posix stat stdarg stdbool stdio strdup-posix striconv string strncat strstr sys_stat sys_time unistd vfprintf-posix vsnprintf-posix wchar wcrtomb wcsdup wcsrtombs wctob wctype-h wcwidth # Specification in the form of a few gnulib-tool.m4 macro invocations: gl_LOCAL_DIR([]) @@ -55,6 +55,7 @@ gl_MODULES([ wcrtomb wcsdup wcsrtombs + wctob wctype-h wcwidth ]) From 3a4b014e64158edff47067ff99a302012e38b6d0 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Mon, 22 Aug 2011 13:42:29 +1000 Subject: [PATCH 085/112] Add the module wcswidth from the GNU Portability Library --- lib/.gitignore | 2 ++ m4/.gitignore | 1 + m4/gnulib-cache.m4 | 3 ++- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/.gitignore b/lib/.gitignore index 69ee50e..692d9bb 100644 --- a/lib/.gitignore +++ b/lib/.gitignore @@ -114,6 +114,8 @@ wcsdup.c wcsrtombs-impl.h wcsrtombs-state.c wcsrtombs.c +wcswidth-impl.h +wcswidth.c wctob.c wctomb-impl.h wctomb.c diff --git a/m4/.gitignore b/m4/.gitignore index 2afe33d..6cd5941 100644 --- a/m4/.gitignore +++ b/m4/.gitignore @@ -112,6 +112,7 @@ wchar_t.m4 wcrtomb.m4 wcsdup.m4 wcsrtombs.m4 +wcswidth.m4 wctob.m4 wctomb.m4 wctype_h.m4 diff --git a/m4/gnulib-cache.m4 b/m4/gnulib-cache.m4 index 6bd0fcf..d6b55ea 100644 --- a/m4/gnulib-cache.m4 +++ b/m4/gnulib-cache.m4 @@ -15,7 +15,7 @@ # Specification in the form of a command-line invocation: -# gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --no-conditional-dependencies --no-libtool --macro-prefix=gl assert btowc config-h ctype fprintf-posix getopt-gnu gettext gettext-h gettimeofday langinfo locale mbrtowc mbsrtowcs printf-posix sigaction signal snprintf-posix stat stdarg stdbool stdio strdup-posix striconv string strncat strstr sys_stat sys_time unistd vfprintf-posix vsnprintf-posix wchar wcrtomb wcsdup wcsrtombs wctob wctype-h wcwidth +# gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --no-conditional-dependencies --no-libtool --macro-prefix=gl assert btowc config-h ctype fprintf-posix getopt-gnu gettext gettext-h gettimeofday langinfo locale mbrtowc mbsrtowcs printf-posix sigaction signal snprintf-posix stat stdarg stdbool stdio strdup-posix striconv string strncat strstr sys_stat sys_time unistd vfprintf-posix vsnprintf-posix wchar wcrtomb wcsdup wcsrtombs wcswidth wctob wctype-h wcwidth # Specification in the form of a few gnulib-tool.m4 macro invocations: gl_LOCAL_DIR([]) @@ -55,6 +55,7 @@ gl_MODULES([ wcrtomb wcsdup wcsrtombs + wcswidth wctob wctype-h wcwidth From b951b2189465c4bef4963685a2bdcf19271f74f3 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Thu, 25 Aug 2011 12:26:15 +1000 Subject: [PATCH 086/112] Add global (wide-character) currency and numeric variables Add the variables decimal_point, thousands_sep, currency_symbol, mon_decimal_point and mon_thousands_sep, with code to initialise them. --- src/utils.c | 33 +++++++++++++++++++++++++++++++-- src/utils.h | 19 ++++++++++++++----- 2 files changed, 45 insertions(+), 7 deletions(-) diff --git a/src/utils.c b/src/utils.c index c2a1dfd..8c3e890 100644 --- a/src/utils.c +++ b/src/utils.c @@ -38,6 +38,13 @@ // Global copy, suitably modified, of localeconv() information struct lconv lconvinfo; +// localeconv() information, converted to wide strings +wchar_t *decimal_point; // Locale's radix character +wchar_t *thousands_sep; // Locale's thousands separator +wchar_t *currency_symbol; // Local currency symbol +wchar_t *mon_decimal_point; // Local monetary radix character +wchar_t *mon_thousands_sep; // Local monetary thousands separator + /************************************************************************ * Module-specific constants and variable definitions * @@ -303,6 +310,7 @@ void init_locale (void) { char *cur, *cloc; struct lconv *lc; + wchar_t *buf; cur = xstrdup(setlocale(LC_MONETARY, NULL)); @@ -329,6 +337,27 @@ void init_locale (void) lconvinfo.p_sep_by_space = MOD_POSIX_P_SEP_BY_SPACE; } + // Convert localeconv() information to wide strings + + buf = xmalloc(BUFSIZE * sizeof(wchar_t)); + + xmbstowcs(buf, lconvinfo.decimal_point, BUFSIZE); + decimal_point = xwcsdup(buf); + + xmbstowcs(buf, lconvinfo.thousands_sep, BUFSIZE); + thousands_sep = xwcsdup(buf); + + xmbstowcs(buf, lconvinfo.currency_symbol, BUFSIZE); + currency_symbol = xwcsdup(buf); + + xmbstowcs(buf, lconvinfo.mon_decimal_point, BUFSIZE); + mon_decimal_point = xwcsdup(buf); + + xmbstowcs(buf, lconvinfo.mon_thousands_sep, BUFSIZE); + mon_thousands_sep = xwcsdup(buf); + + free(buf); + setlocale(LC_MONETARY, cur); free(cur); } @@ -555,7 +584,7 @@ size_t xmbstowcs (wchar_t *restrict dest, const char *restrict src, size_t len) } } else if (p != NULL) { // Multibyte string was too long: truncate dest - dest[len - 1] = '\0'; + dest[len - 1] = L'\0'; n--; break; } else { @@ -590,7 +619,7 @@ size_t xwcrtomb (char *restrict dest, wchar_t wc, mbstate_t *restrict mbstate) Hence, restore the original, try to store an ending shift sequence, then EILSEQ_REPL. */ memcpy(&mbcopy, mbstate, sizeof(mbcopy)); - if ((n = wcrtomb(dest, '\0', &mbcopy)) == (size_t) -1) { + if ((n = wcrtomb(dest, L'\0', &mbcopy)) == (size_t) -1) { errno_exit(_("xwcrtomb: NUL")); } dest[n] = EILSEQ_REPL; diff --git a/src/utils.h b/src/utils.h index 49a5c3f..a30a108 100644 --- a/src/utils.h +++ b/src/utils.h @@ -43,6 +43,7 @@ #define EILSEQ_REPL '?' // Illegal character sequence replacement +#define EILSEQ_REPL_WC L'?' // ... wide character version /************************************************************************ @@ -52,6 +53,13 @@ // Global copy, suitably modified, of localeconv() information extern struct lconv lconvinfo; +// localeconv() information, converted to wide strings +extern wchar_t *decimal_point; // Locale's radix character +extern wchar_t *thousands_sep; // Locale's thousands separator +extern wchar_t *currency_symbol; // Local currency symbol +extern wchar_t *mon_decimal_point; // Local monetary radix character +extern wchar_t *mon_thousands_sep; // Local monetary thousands separator + /************************************************************************ * Initialisation and environment function prototypes * @@ -229,11 +237,12 @@ extern int randi (int limit); Parameters: (none) Returns: (nothing) - This function initialises the global variable lconvinfo with values - suitable for this program. In particular, if the POSIX or C locale is - in effect, the currency_symbol and frac_digits members are updated to - be something reasonable. This function must be called before using - localeconf_info. + This function initialises the global variable lconvinfo, as well as + decimal_point, thousands_sep, currency_symbol, mon_decimal_point and + mon_thousands_sep, with values suitable for this program. In + particular, if the POSIX or C locale is in effect, the currency_symbol + and frac_digits members of lconvinfo are updated to be something + reasonable. This function must be called before using localeconf_info. */ extern void init_locale (void); From 20473ae409a44770ce29049cbd73ab0031c5110f Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Thu, 25 Aug 2011 13:19:31 +1000 Subject: [PATCH 087/112] Use wide-character functions for input routines and most strings Convert all input routines, and most internal strings, to use wide-character functions. All extended characters are supported, including those having column widths of zero (eg, combining characters), one (eg, normal Western characters) and two (eg, many East Asian characters). This was quite a major undertaking! --- src/exch.c | 224 +++++---- src/fileio.c | 72 ++- src/game.c | 165 +++---- src/globals.c | 10 +- src/globals.h | 31 +- src/help.c | 80 ++-- src/intf.c | 1212 ++++++++++++++++++++++++++++++++----------------- src/intf.h | 109 +++-- src/move.c | 163 ++++--- 9 files changed, 1261 insertions(+), 805 deletions(-) diff --git a/src/exch.c b/src/exch.c index caf814d..71f51dc 100644 --- a/src/exch.c +++ b/src/exch.c @@ -97,7 +97,7 @@ void exchange_stock (void) center(curwin, 1, 0, attr_title, 0, 0, 1, _(" Interstellar Stock Exchange ")); center(curwin, 2, 0, attr_normal, attr_highlight, 0, 1, - _("Player: ^{%s^}"), player[current_player].name); + _("Player: ^{%ls^}"), player[current_player].name); all_off_map = true; for (i = 0; i < MAX_COMPANIES; i++) { @@ -143,19 +143,19 @@ void exchange_stock (void) - SHARE_RETURN_COLS, attr_subtitle, 0, 0, 2, /* TRANSLATORS: "Price per share" is a two-line column label in a table containing the price per share in - any given company. %s is the currency symbol in the - current locale. The maximum column width is 12 + any given company. %ls is the currency symbol in + the current locale. The maximum column width is 12 characters INCLUDING the currency symbol (see SHARE_PRICE_COLS in src/intf.h). */ - pgettext("subtitle", "Price per\nshare (%s)"), - lconvinfo.currency_symbol); + pgettext("subtitle", "Price per\nshare (%ls)"), + currency_symbol); for (line = 6, i = 0; i < MAX_COMPANIES; i++) { if (company[i].on_map) { mvwaddch(curwin, line, 2, PRINTABLE_MAP_VAL(COMPANY_TO_MAP(i)) | attr_choice); - left(curwin, line, 4, attr_normal, 0, 0, 1, "%s", + left(curwin, line, 4, attr_normal, 0, 0, 1, "%ls", company[i].name); right(curwin, line, w - 2, attr_normal, 0, 0, 1, "%'ld ", @@ -196,48 +196,61 @@ void exchange_stock (void) // Get the actual selection made by the player while (selection == SEL_NONE) { - bool found; + wint_t key; - int key = gettxchar(curwin); + if (gettxchar(curwin, &key) == OK) { + // Ordinary wide character + bool found; - if (isupper(*keycode_company)) { - key = toupper(key); - } else if (islower(*keycode_company)) { - key = tolower(key); - } + if (iswupper(*keycode_company)) { + key = towupper(key); + } else if (iswlower(*keycode_company)) { + key = towlower(key); + } - for (i = 0, found = false; keycode_company[i] != '\0'; i++) { - if (keycode_company[i] == key) { - found = true; - if (company[i].on_map) { - selection = i; - } else { + for (i = 0, found = false; keycode_company[i] != '\0'; i++) { + if (keycode_company[i] == key) { + found = true; + if (company[i].on_map) { + selection = i; + } else { + beep(); + } + break; + } + } + + if (! found) { + switch (key) { + case '1': + curs_set(CURS_OFF); + show_status(current_player); + curs_set(CURS_ON); + break; + + case '2': + curs_set(CURS_OFF); + show_map(true); + curs_set(CURS_ON); + break; + + case '3': + selection = SEL_BANK; + break; + + case '4': + case ' ': + selection = SEL_EXIT; + break; + + default: beep(); } - break; } - } - - if (! found) { + } else { + // Function or control key switch (key) { - case '1': - curs_set(CURS_OFF); - show_status(current_player); - curs_set(CURS_ON); - break; - - case '2': - curs_set(CURS_OFF); - show_map(true); - curs_set(CURS_ON); - break; - - case '3': - selection = SEL_BANK; - break; - - case '4': - case ' ': + case KEY_ESC: case KEY_CANCEL: case KEY_EXIT: case KEY_CTRL('C'): @@ -287,7 +300,7 @@ void visit_bank (void) { double credit_limit; double val, max; - int key; + wint_t key; bool done; chtype *chbuf = xmalloc(BUFSIZE * sizeof(chtype)); @@ -363,27 +376,41 @@ void visit_bank (void) done = false; while (! done) { - key = gettxchar(curwin); + if (gettxchar(curwin, &key) == OK) { + // Ordinary wide character + switch (key) { + case '1': + case '2': + case '3': + left(curwin, getcury(curwin), getcurx(curwin), A_BOLD, + 0, 0, 1, "%lc", key); + wrefresh(curwin); - switch (key) { - case '1': - case '2': - case '3': - wechochar(curwin, key | A_BOLD); - done = true; - break; + done = true; + break; - case ' ': - case KEY_CANCEL: - case KEY_EXIT: - case KEY_CTRL('C'): - case KEY_CTRL('G'): - case KEY_CTRL('\\'): - done = true; - break; + case ' ': + done = true; + break; - default: - beep(); + default: + beep(); + } + } else { + // Function or control key + switch (key) { + case KEY_ESC: + case KEY_CANCEL: + case KEY_EXIT: + case KEY_CTRL('C'): + case KEY_CTRL('G'): + case KEY_CTRL('\\'): + done = true; + break; + + default: + beep(); + } } } @@ -410,8 +437,8 @@ void visit_bank (void) n = (lconvinfo.p_sep_by_space == 1) ? 1 : 0; mkchstr(chbuf, BUFSIZE, attr_normal, attr_normal | A_BOLD, 0, 1, - getmaxx(curwin) / 2, &width_cursym, 1, "^{%s^}", - lconvinfo.currency_symbol); + getmaxx(curwin) / 2, &width_cursym, 1, "^{%ls^}", + currency_symbol); chbuf_cursym = xchstrdup(chbuf); mkchstr(chbuf, BUFSIZE, attr_normal, 0, 0, 1, getmaxx(curwin) @@ -468,8 +495,8 @@ void visit_bank (void) n = (lconvinfo.p_sep_by_space == 1) ? 1 : 0; mkchstr(chbuf, BUFSIZE, attr_normal, attr_normal | A_BOLD, 0, 1, - getmaxx(curwin) / 2, &width_cursym, 1, "^{%s^}", - lconvinfo.currency_symbol); + getmaxx(curwin) / 2, &width_cursym, 1, "^{%ls^}", + currency_symbol); chbuf_cursym = xchstrdup(chbuf); mkchstr(chbuf, BUFSIZE, attr_normal, 0, 0, 1, getmaxx(curwin) @@ -527,11 +554,12 @@ void visit_bank (void) void trade_shares (int num, bool *bid_used) { bool done; - int key, ret, w, x; + int ret, w, x; long int maxshares, val; double ownership; chtype *chbuf; int width; + wint_t key; assert(num >= 0 && num < MAX_COMPANIES); @@ -548,8 +576,8 @@ void trade_shares (int num, bool *bid_used) w = getmaxx(curwin); center(curwin, 1, 0, attr_title, 0, 0, 1, - /* TRANSLATORS: %s represents the company name. */ - _(" Stock Transaction in %s "), company[num].name); + /* TRANSLATORS: %ls represents the company name. */ + _(" Stock Transaction in %ls "), company[num].name); mkchstr(chbuf, BUFSIZE, attr_normal, 0, 0, 1, w / 2, &width, 1, /* TRANSLATORS: "Shares issued" represents the number of @@ -633,28 +661,42 @@ void trade_shares (int num, bool *bid_used) done = false; while (! done) { - key = gettxchar(curwin); + if (gettxchar(curwin, &key) == OK) { + // Ordinary wide character + switch (key) { + case '1': + case '2': + case '3': + case '4': + left(curwin, getcury(curwin), getcurx(curwin), A_BOLD, + 0, 0, 1, "%lc", key); + wrefresh(curwin); - switch (key) { - case '1': - case '2': - case '3': - case '4': - wechochar(curwin, key | A_BOLD); - done = true; - break; + done = true; + break; - case ' ': - case KEY_CANCEL: - case KEY_EXIT: - case KEY_CTRL('C'): - case KEY_CTRL('G'): - case KEY_CTRL('\\'): - done = true; - break; + case ' ': + done = true; + break; - default: - beep(); + default: + beep(); + } + } else { + // Function or control key + switch (key) { + case KEY_ESC: + case KEY_CANCEL: + case KEY_EXIT: + case KEY_CTRL('C'): + case KEY_CTRL('G'): + case KEY_CTRL('\\'): + done = true; + break; + + default: + beep(); + } } } @@ -755,16 +797,16 @@ void trade_shares (int num, bool *bid_used) txdlgbox(MAX_DLG_LINES, 50, 8, WCENTER, attr_error_window, attr_error_title, attr_error_highlight, 0, 0, attr_error_waitforkey, _(" No Shares Issued "), - /* TRANSLATORS: %s represents the company name. */ - _("%s has refused\nto issue more shares."), + /* TRANSLATORS: %ls represents the company name. */ + _("%ls has refused\nto issue more shares."), company[num].name); } else { txdlgbox(MAX_DLG_LINES, 50, 8, WCENTER, attr_normal_window, attr_title, attr_normal, attr_highlight, 0, attr_waitforkey, _(" Shares Issued "), - /* TRANSLATORS: %s represents the company name. */ - ngettext("%s has issued\n^{one^} more share.", - "%s has issued\n^{%'ld^} more shares.", + /* TRANSLATORS: %ls represents the company name. */ + ngettext("%ls has issued\n^{one^} more share.", + "%ls has issued\n^{%'ld^} more shares.", maxshares), company[num].name, maxshares); } break; diff --git a/src/fileio.c b/src/fileio.c index 1224695..9b75432 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -83,7 +83,7 @@ static const unsigned char game_file_crypt_key[] = { } while (0) #ifdef USE_UTF8_GAME_FILE -# define load_game_read_string(_var) \ +# define load_game_read_string(_var, _var_utf8) \ do { \ char *s; \ int len; \ @@ -115,11 +115,14 @@ static const unsigned char game_file_crypt_key[] = { s[len - 1] = '\0'; \ } \ \ + xmbstowcs(wcbuf, s, BUFSIZE); \ + (_var) = xwcsdup(wcbuf); \ + (_var_utf8) = s; \ + \ lineno++; \ - (_var) = s; \ } while (0) #else // ! USE_UTF8_GAME_FILE -# define load_game_read_string(_var) \ +# define load_game_read_string(_var, _var_utf8) \ do { \ char *s; \ int len; \ @@ -140,8 +143,11 @@ static const unsigned char game_file_crypt_key[] = { s[len - 1] = '\0'; \ } \ \ + xmbstowcs(wcbuf, s, BUFSIZE); \ + (_var) = xwcsdup(wcbuf); \ + (_var_utf8) = s; \ + \ lineno++; \ - (_var) = s; \ } while (0) #endif // ! USE_UTF8_GAME_FILE @@ -165,27 +171,38 @@ static const unsigned char game_file_crypt_key[] = { save_game_printf("%d", (int) _var) #ifdef USE_UTF8_GAME_FILE -# define save_game_write_string(_var) \ +# define save_game_write_string(_var, _var_utf8) \ do { \ - if (need_icd) { \ - char *s = str_cd_iconv(_var, icd); \ - if (s == NULL) { \ - if (errno == EILSEQ) { \ - err_exit(_("%s: could not convert string"), \ - filename); \ - } else { \ - errno_exit("str_cd_iconv"); \ - } \ - } \ - save_game_printf("%s", s); \ - free(s); \ + if ((_var_utf8) != NULL) { \ + save_game_printf("%s", _var_utf8); \ } else { \ - save_game_printf("%s", _var); \ + if (need_icd) { \ + snprintf(buf, BUFSIZE, "%ls", _var); \ + char *s = str_cd_iconv(buf, icd); \ + if (s == NULL) { \ + if (errno == EILSEQ) { \ + err_exit(_("%s: could not convert string"), \ + filename); \ + } else { \ + errno_exit("str_cd_iconv"); \ + } \ + } \ + save_game_printf("%s", s); \ + free(s); \ + } else { \ + save_game_printf("%ls", _var); \ + } \ } \ } while (0) #else // ! USE_UTF8_GAME_FILE -# define save_game_write_string(_var) \ - save_game_printf("%s", _var) +# define save_game_write_string(_var, _var_utf8) \ + do { \ + if ((_var_utf8) != NULL) { \ + save_game_printf("%s", _var_utf8); \ + } else { \ + save_game_printf("%ls", _var); \ + } \ + } while (0) #endif // ! USE_UTF8_GAME_FILE @@ -201,12 +218,15 @@ static const unsigned char game_file_crypt_key[] = { bool load_game (int num) { - char *buf, *filename; + char *filename; FILE *file; char *codeset, *codeset_nl; int saved_errno, lineno; char *prev_locale; + char *buf; + wchar_t *wcbuf; + int crypt_key; int n, i, j; @@ -219,6 +239,7 @@ bool load_game (int num) assert(num >= 1 && num <= 9); buf = xmalloc(BUFSIZE); + wcbuf = xmalloc(BUFSIZE * sizeof(wchar_t)); filename = game_filename(num); assert(filename != NULL); @@ -246,6 +267,7 @@ bool load_game (int num) } free(buf); + free(wcbuf); free(filename); return false; } @@ -332,7 +354,7 @@ bool load_game (int num) // Read in player data for (i = 0; i < number_players; i++) { - load_game_read_string(player[i].name); + load_game_read_string(player[i].name, player[i].name_utf8); load_game_read_double(player[i].cash, player[i].cash >= 0.0); load_game_read_double(player[i].debt, player[i].debt >= 0.0); load_game_read_bool(player[i].in_game); @@ -344,7 +366,8 @@ bool load_game (int num) // Read in company data for (i = 0; i < MAX_COMPANIES; i++) { - company[i].name = xstrdup(gettext(company_name[i])); + xmbstowcs(wcbuf, gettext(company_name[i]), BUFSIZE); + company[i].name = xwcsdup(wcbuf); load_game_read_double(company[i].share_price, company[i].share_price >= 0.0); load_game_read_double(company[i].share_return, true); load_game_read_long(company[i].stock_issued, company[i].stock_issued >= 0); @@ -391,6 +414,7 @@ bool load_game (int num) #endif free(buf); + free(wcbuf); free(filename); free(prev_locale); free(codeset_nl); @@ -514,7 +538,7 @@ bool save_game (int num) // Write out player data for (i = 0; i < number_players; i++) { - save_game_write_string(player[i].name); + save_game_write_string(player[i].name, player[i].name_utf8); save_game_write_double(player[i].cash); save_game_write_double(player[i].debt); save_game_write_bool(player[i].in_game); diff --git a/src/game.c b/src/game.c index db0cd29..46f236d 100644 --- a/src/game.c +++ b/src/game.c @@ -108,48 +108,6 @@ static int cmp_player (const void *a, const void *b); void init_game (void) { - /* Initialise strings used for keycode input and map representations. - - Each string must have an ASCII vertical line (U+007C) in the - correct position, followed by context information (such as - "input|Company" and "output|MapVals"). This is done to overcome a - limitation of gettext_noop() and N_() that does NOT allow context - IDs. This vertical line is replaced by a NUL character to - terminate the resulting string. The vertical line MAY appear in - other positions; if so, it is handled correctly. */ - - keycode_company = xstrdup(gettext(default_keycode_company)); - if (strlen(keycode_company) < MAX_COMPANIES + 1 - || keycode_company[MAX_COMPANIES] != '|') { - err_exit(_("keycode string for companies has incorrect format: `%s'"), - keycode_company); - } - keycode_company[MAX_COMPANIES] = '\0'; - - keycode_game_move = xstrdup(gettext(default_keycode_game_move)); - if (strlen(keycode_game_move) < NUMBER_MOVES + 1 - || keycode_game_move[NUMBER_MOVES] != '|') { - err_exit(_("keycode string for game moves has incorrect format: `%s'"), - keycode_game_move); - } - keycode_game_move[NUMBER_MOVES] = '\0'; - - printable_map_val = xstrdup(gettext(default_printable_map_val)); - if (strlen(printable_map_val) < MAX_COMPANIES + 4 - || printable_map_val[MAX_COMPANIES + 3] != '|') { - err_exit(_("output string for companies has incorrect format: `%s'"), - printable_map_val); - } - printable_map_val[MAX_COMPANIES + 3] = '\0'; - - printable_game_move = xstrdup(gettext(default_printable_game_move)); - if (strlen(printable_game_move) < NUMBER_MOVES + 1 - || printable_game_move[NUMBER_MOVES] != '|') { - err_exit(_("output string for game moves has incorrect format: `%s'"), - printable_game_move); - } - printable_game_move[NUMBER_MOVES] = '\0'; - // Try to load an old game, if possible if (game_num != 0) { chtype *chbuf = xmalloc(BUFSIZE * sizeof(chtype)); @@ -213,6 +171,8 @@ void init_game (void) } if (! game_loaded) { + wchar_t *buf = xmalloc(BUFSIZE * sizeof(wchar_t)); + ask_player_names(); deltxwin(); // "Number of players" window @@ -231,7 +191,8 @@ void init_game (void) // Initialise company data for (int i = 0; i < MAX_COMPANIES; i++) { - company[i].name = xstrdup(gettext(company_name[i])); + xmbstowcs(buf, gettext(company_name[i]), BUFSIZE); + company[i].name = xwcsdup(buf); company[i].share_price = 0.0; company[i].share_return = INITIAL_RETURN; company[i].stock_issued = 0; @@ -263,10 +224,12 @@ void init_game (void) txdlgbox(MAX_DLG_LINES, 50, 8, WCENTER, attr_normal_window, attr_title, attr_normal, attr_highlight, 0, attr_waitforkey, _(" First Player "), - _("The first player to go is ^{%s^}."), + _("The first player to go is ^{%ls^}."), player[first_player].name); txrefresh(); } + + free(buf); } } @@ -280,15 +243,14 @@ void init_game (void) static int ask_number_players (void) { - char *keycode_contgame; - chtype *chbuf; + wchar_t *keycode_contgame = xmalloc(BUFSIZE * sizeof(wchar_t)); + chtype *chbuf = xmalloc(BUFSIZE * sizeof(chtype)); int lines, maxwidth; int widthbuf[2]; - int key, ret; + int ret; bool done; - chbuf = xmalloc(BUFSIZE * sizeof(chtype)); lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_keycode, 0, 2, WIN_COLS - 7, widthbuf, 2, /* TRANSLATORS: The keycode should be modified to @@ -311,21 +273,33 @@ static int ask_number_players (void) first character (keyboard input code) is used to print the user's response if one of those keys is pressed. Both upper and lower-case versions should be present. */ - keycode_contgame = xstrdup(pgettext("input|ContinueGame", "Cc")); + xmbstowcs(keycode_contgame, pgettext("input|ContinueGame", "Cc"), BUFSIZE); done = false; while (! done) { - key = gettxchar(curwin); + wint_t key; - if (key >= '1' && key <= MAX_PLAYERS + '0') { - wechochar(curwin, key | A_BOLD); - ret = key - '0'; - done = true; - } else if (strchr(keycode_contgame, key) != NULL) { - wechochar(curwin, ((unsigned char) *keycode_contgame) | A_BOLD); - ret = 0; - done = true; + if (gettxchar(curwin, &key) == OK) { + // Ordinary wide character + if (key >= '1' && key <= MAX_PLAYERS + '0') { + left(curwin, getcury(curwin), getcurx(curwin), A_BOLD, + 0, 0, 1, "%lc", key); + wrefresh(curwin); + + ret = key - '0'; + done = true; + } else if (wcschr(keycode_contgame, key) != NULL) { + left(curwin, getcury(curwin), getcurx(curwin), A_BOLD, + 0, 0, 1, "%lc", *keycode_contgame); + wrefresh(curwin); + + ret = 0; + done = true; + } else { + beep(); + } } else { + // Function or control key switch (key) { case KEY_ESC: case KEY_CANCEL: @@ -357,7 +331,7 @@ int ask_game_number (void) chtype *chbuf; int lines, maxwidth; int widthbuf[2]; - int key, ret; + int ret; bool done; @@ -378,13 +352,22 @@ int ask_game_number (void) done = false; while (! done) { - key = gettxchar(curwin); + wint_t key; - if (key >= '1' && key <= '9') { - wechochar(curwin, key | A_BOLD); - ret = key - '0'; - done = true; + if (gettxchar(curwin, &key) == OK) { + // Ordinary wide character + if (key >= '1' && key <= '9') { + left(curwin, getcury(curwin), getcurx(curwin), A_BOLD, + 0, 0, 1, "%lc", key); + wrefresh(curwin); + + ret = key - '0'; + done = true; + } else { + beep(); + } } else { + // Function or control key switch (key) { case KEY_ESC: case KEY_CANCEL: @@ -426,10 +409,11 @@ void ask_player_names (void) int w = getmaxx(curwin) - x - 2; player[0].name = NULL; + player[0].name_utf8 = NULL; while (true) { int ret = gettxstr(curwin, &player[0].name, NULL, false, 2, x, w, attr_input_field); - if (ret == OK && strlen(player[0].name) != 0) { + if (ret == OK && wcslen(player[0].name) != 0) { break; } else { beep(); @@ -460,6 +444,7 @@ void ask_player_names (void) for (i = 0; i < number_players; i++) { player[i].name = NULL; + player[i].name_utf8 = NULL; entered[i] = false; left(curwin, i + 3, 2, attr_normal, 0, 0, 1, /* xgettext:c-format, range: 1..8 */ @@ -478,7 +463,7 @@ void ask_player_names (void) switch (ret) { case OK: // Make sure name is not an empty string - len = strlen(player[cur].name); + len = wcslen(player[cur].name); entered[cur] = (len != 0); if (len == 0) { beep(); @@ -487,7 +472,7 @@ void ask_player_names (void) // Make sure name has not been entered already for (i = 0; i < number_players; i++) { if (i != cur && player[i].name != NULL - && strcmp(player[i].name, player[cur].name) == 0) { + && wcscmp(player[i].name, player[cur].name) == 0) { entered[cur] = false; beep(); break; @@ -601,10 +586,10 @@ void end_game (void) lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_highlight, attr_blink, 5, WIN_COLS - 8, widthbuf, 5, (player[0].sort_value == 0) ? - _("The winner is ^{%s^}\n" + _("The winner is ^{%ls^}\n" "who is ^[*** BANKRUPT ***^]") : /* xgettext:c-format */ - _("The winner is ^{%s^}\n" + _("The winner is ^{%ls^}\n" "with a value of ^{%N^}."), player[0].name, player[0].sort_value); @@ -622,16 +607,15 @@ void end_game (void) pgettext("subtitle", "Player")); right(curwin, lines + 4, w - 4, attr_subtitle, 0, 0, 1, /* TRANSLATORS: "Total Value" refers to the total worth - (shares, cash and debt) of any given player. %s is the + (shares, cash and debt) of any given player. %ls is the currency symbol of the current locale. */ - pgettext("subtitle", "Total Value (%s)"), - lconvinfo.currency_symbol); + pgettext("subtitle", "Total Value (%ls)"), currency_symbol); for (int i = 0; i < number_players; i++) { right(curwin, i + lines + 5, ORDINAL_COLS + 2, attr_normal, 0, 0, 1, gettext(ordinal[i + 1])); left(curwin, i + lines + 5, ORDINAL_COLS + 4, attr_normal, 0, 0, - 1, "%s", player[i].name); + 1, "%ls", player[i].name); right(curwin, i + lines + 5, w - 2, attr_normal, 0, 0, 1, " %!N ", player[i].sort_value); } @@ -659,7 +643,7 @@ void show_map (bool closewin) // Display current player and turn number left(curwin, 1, 4, attr_mapwin_title, attr_mapwin_highlight, 0, 1, - _("Player: ^{%s^}"), player[current_player].name); + _("Player: ^{%ls^}"), player[current_player].name); right(curwin, 1, getmaxx(curwin) - 2, attr_mapwin_title, attr_mapwin_highlight, attr_mapwin_blink, 1, (turn_number != max_turn) ? _(" Turn: ^{%d^} ") : @@ -669,26 +653,11 @@ void show_map (bool closewin) for (int y = 0; y < MAX_Y; y++) { wmove(curwin, y + 3, 2); for (int x = 0; x < MAX_X; x++) { - map_val_t m = galaxy_map[x][y]; + chtype *mapstr = CHTYPE_MAP_VAL(galaxy_map[x][y]); - switch (m) { - case MAP_EMPTY: - waddch(curwin, PRINTABLE_MAP_VAL(m) | attr_map_empty); - break; - - case MAP_OUTPOST: - waddch(curwin, PRINTABLE_MAP_VAL(m) | attr_map_outpost); - break; - - case MAP_STAR: - waddch(curwin, PRINTABLE_MAP_VAL(m) | attr_map_star); - break; - - default: - waddch(curwin, PRINTABLE_MAP_VAL(m) | attr_map_company); - break; + while (*mapstr != '\0') { + waddch(curwin, *mapstr++); } - waddch(curwin, ' ' | attr_map_empty); } } @@ -724,7 +693,7 @@ void show_status (int num) attr_normal_window); center(curwin, 1, 0, attr_title, 0, 0, 1, _(" Stock Portfolio ")); center(curwin, 2, 0, attr_normal, attr_highlight, 0, 1, - _("Player: ^{%s^}"), player[num].name); + _("Player: ^{%ls^}"), player[num].name); val = total_value(num); if (val == 0.0) { @@ -780,16 +749,16 @@ void show_status (int num) - SHARE_RETURN_COLS, attr_subtitle, 0, 0, 2, /* TRANSLATORS: "Price per share" is a two-line column label in a table containing the price per share in - any given company. %s is the currency symbol in the - current locale. The maximum column width is 12 + any given company. %ls is the currency symbol in + the current locale. The maximum column width is 12 characters INCLUDING the currency symbol (see SHARE_PRICE_COLS in src/intf.h). */ - pgettext("subtitle", "Price per\nshare (%s)"), - lconvinfo.currency_symbol); + pgettext("subtitle", "Price per\nshare (%ls)"), + currency_symbol); for (line = 6, i = 0; i < MAX_COMPANIES; i++) { if (company[i].on_map) { - left(curwin, line, 4, attr_normal, 0, 0, 1, "%s", + left(curwin, line, 4, attr_normal, 0, 0, 1, "%ls", company[i].name); right(curwin, line, w - 2, attr_normal, 0, 0, 1, "%.2f ", diff --git a/src/globals.c b/src/globals.c index 9a0e602..f8fc0c9 100644 --- a/src/globals.c +++ b/src/globals.c @@ -128,10 +128,12 @@ player_info_t player[MAX_PLAYERS]; // Array of players map_val_t galaxy_map[MAX_X][MAX_Y]; // Map of the galaxy move_rec_t game_move[NUMBER_MOVES]; // Current moves -char *keycode_company; // Keycodes for each company -char *keycode_game_move; // Keycodes for each game move -char *printable_map_val; // Printable output for each map value -char *printable_game_move; // Printable output for each game move +wchar_t *keycode_company; // Keycodes for each company +wchar_t *keycode_game_move; // Keycodes for each game move +wchar_t *printable_map_val; // Printable output for each map value +wchar_t *printable_game_move; // Printable output for each game move +chtype *chtype_map_val[MAX_COMPANIES + 3]; // as chtype strings +chtype *chtype_game_move[NUMBER_MOVES]; // as chtype strings int max_turn; // Max. number of turns in game int turn_number; // Current turn (1 to max_turn) diff --git a/src/globals.h b/src/globals.h index b6d393f..e5f562c 100644 --- a/src/globals.h +++ b/src/globals.h @@ -32,7 +32,7 @@ #define included_GLOBALS_H 1 -#include +#include /************************************************************************ @@ -97,7 +97,7 @@ // Information about each company typedef struct company_info { - const char *name; // Company name + wchar_t *name; // Company name double share_price; // Share price double share_return; // Return per share long int stock_issued; // Total stock sold to players @@ -108,7 +108,8 @@ typedef struct company_info { // Information about each player typedef struct player_info { - char *name; // Player name + wchar_t *name; // Player name + char *name_utf8; // Player name (in UTF-8, for load/save) double cash; // Cash available double debt; // Amount of debt long int stock_owned[MAX_COMPANIES]; // How much stock is owned @@ -130,11 +131,14 @@ typedef enum map_val { #define MAP_TO_COMPANY(m) ((m) - MAP_A) #define IS_MAP_COMPANY(m) ((m) >= MAP_A && (m) <= MAP_LAST) -#define PRINTABLE_MAP_VAL(m) \ - (((m) == MAP_EMPTY) ? printable_map_val[0] : \ - (((m) == MAP_OUTPOST) ? printable_map_val[1] : \ - (((m) == MAP_STAR) ? printable_map_val[2] : \ - printable_map_val[(m) - MAP_A + 3]))) +#define MAP_TO_INDEX(m) \ + (((m) == MAP_EMPTY) ? 0 : \ + (((m) == MAP_OUTPOST) ? 1 : \ + (((m) == MAP_STAR) ? 2 : \ + ((m) - MAP_A + 3)))) + +#define PRINTABLE_MAP_VAL(m) printable_map_val[MAP_TO_INDEX(m)] +#define CHTYPE_MAP_VAL(m) chtype_map_val[MAP_TO_INDEX(m)] // Information about a move @@ -144,6 +148,7 @@ typedef struct move_rec { } move_rec_t; #define PRINTABLE_GAME_MOVE(m) (printable_game_move[m]) +#define CHTYPE_GAME_MOVE(m) (chtype_game_move[m]) // Player moves / selection values @@ -193,10 +198,12 @@ extern player_info_t player[MAX_PLAYERS]; // Array of players extern map_val_t galaxy_map[MAX_X][MAX_Y]; // Map of the galaxy extern move_rec_t game_move[NUMBER_MOVES]; // Current moves -extern char *keycode_company; // Keycodes for each company -extern char *keycode_game_move; // Keycodes for each game move -extern char *printable_map_val; // Printable output for each map value -extern char *printable_game_move; // Printable output for each game move +extern wchar_t *keycode_company; // Keycodes for each company +extern wchar_t *keycode_game_move; // Keycodes for each game move +extern wchar_t *printable_map_val; // Printable output for each map value +extern wchar_t *printable_game_move; // Printable output for each game move +extern chtype *chtype_map_val[MAX_COMPANIES + 3]; // as chtype strings +extern chtype *chtype_game_move[NUMBER_MOVES]; // as chtype strings extern int max_turn; // Max. number of turns in game extern int turn_number; // Current turn (1 to max_turn) diff --git a/src/help.c b/src/help.c index f8a8451..8893d97 100644 --- a/src/help.c +++ b/src/help.c @@ -279,7 +279,6 @@ void show_help (void) char *cp; mbstate_t mbstate; chtype *outp; - wchar_t c; size_t i, n; int count = BIGBUFSIZE; @@ -387,36 +386,31 @@ void show_help (void) case '8': case '9': // N-th choice of move, as a key press - c = btowc(PRINTABLE_GAME_MOVE(*htxt - L'1')); - wcbuf[0] = (c == WEOF) ? EILSEQ_REPL : c; + wcbuf[0] = PRINTABLE_GAME_MOVE(*htxt - L'1'); wcbuf[1] = '\0'; goto addwcbuf; case 'M': // Last choice of move, as a key press - c = btowc(PRINTABLE_GAME_MOVE(NUMBER_MOVES - 1)); - wcbuf[0] = (c == WEOF) ? EILSEQ_REPL : c; + wcbuf[0] = PRINTABLE_GAME_MOVE(NUMBER_MOVES - 1); wcbuf[1] = '\0'; goto addwcbuf; case '.': // Map representation of empty space - c = btowc(PRINTABLE_MAP_VAL(MAP_EMPTY)); - wcbuf[0] = (c == WEOF) ? EILSEQ_REPL : c; + wcbuf[0] = PRINTABLE_MAP_VAL(MAP_EMPTY); wcbuf[1] = '\0'; goto addwcbuf; case '+': // Map representation of an outpost - c = btowc(PRINTABLE_MAP_VAL(MAP_OUTPOST)); - wcbuf[0] = (c == WEOF) ? EILSEQ_REPL : c; + wcbuf[0] = PRINTABLE_MAP_VAL(MAP_OUTPOST); wcbuf[1] = '\0'; goto addwcbuf; case '*': // Map representation of a star - c = btowc(PRINTABLE_MAP_VAL(MAP_STAR)); - wcbuf[0] = (c == WEOF) ? EILSEQ_REPL : c; + wcbuf[0] = PRINTABLE_MAP_VAL(MAP_STAR); wcbuf[1] = '\0'; goto addwcbuf; @@ -429,8 +423,8 @@ void show_help (void) case 'G': case 'H': // Map representation of company - c = btowc(PRINTABLE_MAP_VAL(COMPANY_TO_MAP(*htxt - L'A'))); - wcbuf[0] = (c == WEOF) ? EILSEQ_REPL : c; + assert((*htxt - L'A') < MAX_COMPANIES); + wcbuf[0] = PRINTABLE_MAP_VAL(COMPANY_TO_MAP(*htxt - L'A')); wcbuf[1] = '\0'; goto addwcbuf; @@ -486,35 +480,41 @@ void show_help (void) "for the previous page ] ")); wrefresh(curwin); - int key = gettxchar(curwin); - - switch (key) { - case KEY_BS: - case KEY_BACKSPACE: - case KEY_DEL: - case KEY_PPAGE: - case KEY_UP: - case KEY_LEFT: - case KEY_BTAB: - if (curpage == 0) { - beep(); - } else { - curpage--; - } - break; - - case KEY_ESC: - case KEY_CANCEL: - case KEY_EXIT: - case KEY_CTRL('C'): - case KEY_CTRL('G'): - case KEY_CTRL('\\'): - done = true; - break; - - default: + wint_t key; + if (gettxchar(curwin, &key) == OK) { + // Ordinary wide character curpage++; done = (curpage == numpages); + } else { + // Function or control character + switch (key) { + case KEY_BS: + case KEY_BACKSPACE: + case KEY_DEL: + case KEY_PPAGE: + case KEY_UP: + case KEY_LEFT: + case KEY_BTAB: + if (curpage == 0) { + beep(); + } else { + curpage--; + } + break; + + case KEY_ESC: + case KEY_CANCEL: + case KEY_EXIT: + case KEY_CTRL('C'): + case KEY_CTRL('G'): + case KEY_CTRL('\\'): + done = true; + break; + + default: + curpage++; + done = (curpage == numpages); + } } } diff --git a/src/intf.c b/src/intf.c index daec6f1..1ef3b0b 100644 --- a/src/intf.c +++ b/src/intf.c @@ -32,7 +32,7 @@ /************************************************************************ -* Module-specific constants and type declarations * +* Module-specific constants, type declarations and macros * ************************************************************************/ typedef struct txwin { @@ -42,6 +42,57 @@ typedef struct txwin { } txwin_t; +// Initialisation macros used in init_screen() + +#define __stringify(s) #s + +#define init_game_str(_var, _default, _checkpos) \ + do { \ + char *s = gettext(_default); \ + if (xmbstowcs(buf, s, BUFSIZE) < (_checkpos) + 1 \ + || buf[_checkpos] != '|') { \ + err_exit(_("%s: string has incorrect format: `%s'"), \ + __stringify(_var), s); \ + } \ + (_var) = xwcsdup(buf); \ + (_var)[_checkpos] = '\0'; \ + } while (0) + +#define init_game_chstr(_chvar, _var, _attr, _err) \ + do { \ + chtype *p = chbuf; \ + wchar_t c; \ + int w, n; \ + mbstate_t mbstate; \ + \ + c = (_var); \ + if ((w = wcwidth(c)) < 1) { \ + err_exit(_("%s: character has illegal width: `%lc'"), \ + __stringify(_err), c); \ + } \ + \ + memset(&mbstate, 0, sizeof(mbstate)); \ + n = xwcrtomb(convbuf, c, &mbstate); \ + for (int i = 0; i < n; i++) { \ + *p++ = (unsigned char) convbuf[i] | (_attr); \ + } \ + \ + if (w == 1) { \ + n = xwcrtomb(convbuf, ' ', &mbstate); \ + for (int i = 0; i < n; i++) { \ + *p++ = (unsigned char) convbuf[i] | attr_map_empty; \ + } \ + } \ + \ + n = xwcrtomb(convbuf, '\0', &mbstate); \ + for (int i = 0; i < n; i++) { \ + *p++ = (unsigned char) convbuf[i]; \ + } \ + \ + (_chvar) = xchstrdup(chbuf); \ + } while (0) + + // Declarations for argument processing in mkchstr() #define MAXFMTARGS 8 // Maximum number of positional arguments @@ -244,6 +295,72 @@ static void mkchstr_conv (chtype *restrict chbuf, int chbufsize, wchar_t *restrict wcbuf, chtype *restrict attrbuf); +/* + Function: getwch - Get a wide character from the keyboard + Parameters: win - Window to use (should be curwin) + wch - Pointer to wide character result + Returns: int - OK, KEY_CODE_YES or ERR + + This internal function waits for a complete wide character to be typed + on the keyboard. OK is returned if wch contains an ordinary wide + character, KEY_CODE_YES if a function key or control key, or ERR on + error. + + This function is either a wrapper (with modifications) for wget_wch() + from Curses, or an implementation of that function using wgetch(). +*/ +static int getwch (WINDOW *win, wint_t *wch); + + +/* + Function: cpos_endl - Adjust cpos and st for printing the ending part of buf + Parameters: buf - Pointer to current editing buffer + cpos - Pointer to current cursor position (result) + st - Pointer to current starting offset for buf[] (result) + clen - Current column width of entire string + width - Width of editing field in column spaces + len - Length of string being edited (wchar_t elements) + Returns: (nothing) + + This helper function adjusts *cpos and *st so that the cursor is placed + at the end of the current editing buffer buf[]. +*/ +static void cpos_endl (wchar_t *restrict buf, int *restrict cpos, + int *restrict st, int clen, int width, int len); + + +/* + Function: cpos_decr - Adjust cpos and st: scroll to the left by w columns + Parameters: buf - Pointer to current editing buffer + cpos - Pointer to current cursor position (result) + st - Pointer to current starting offset for buf[] (result) + w - Number of columns to scroll left + width - Width of editing field in column spaces + Returns: (nothing) + + This helper function adjusts *cpos and *st so that the cursor is moved + to the left by w column positions. +*/ +static void cpos_decr (wchar_t *restrict buf, int *restrict cpos, + int *restrict st, int w, int width); + + +/* + Function: cpos_incr - Adjust cpos and st: scroll to the right by w columns + Parameters: buf - Pointer to current editing buffer + cpos - Pointer to current cursor position (result) + st - Pointer to current starting offset for buf[] (result) + w - Number of columns to scroll right + width - Width of editing field in column spaces + Returns: (nothing) + + This helper function adjusts *cpos and *st so that the cursor is moved + to the right by w column positions. +*/ +static void cpos_incr (wchar_t *restrict buf, int *restrict cpos, + int *restrict st, int w, int width); + + /* Function: txinput_fixup - Copy strings with fixup Parameters: dest - Destination buffer of size BUFSIZE @@ -259,7 +376,7 @@ static void mkchstr_conv (chtype *restrict chbuf, int chbufsize, This function is used by gettxdouble() and gettxlong() to share some common code. */ -static void txinput_fixup (char *restrict dest, char *restrict src, +static void txinput_fixup (wchar_t *restrict dest, wchar_t *restrict src, bool isfloat); @@ -401,6 +518,51 @@ void init_screen (void) init_title(); refresh(); + + /* Initialise strings used for keycode input and map representations. + + Each string must have an ASCII vertical line (U+007C) in the + correct position, followed by context information (such as + "input|Company" and "output|MapVals"). This is done to overcome a + limitation of gettext_noop() and N_() that does NOT allow context + IDs. This vertical line is replaced by a NUL character to + terminate the resulting string. The vertical line MAY appear in + other positions; if so, it is handled correctly. */ + + wchar_t *buf = xmalloc(BUFSIZE * sizeof(wchar_t)); + char convbuf[MB_LEN_MAX + 1]; + chtype chbuf[MB_LEN_MAX * 3 + 1]; + + init_game_str(keycode_company, default_keycode_company, MAX_COMPANIES); + init_game_str(keycode_game_move, default_keycode_game_move, NUMBER_MOVES); + + init_game_str(printable_map_val, default_printable_map_val, MAX_COMPANIES + 3); + init_game_str(printable_game_move, default_printable_game_move, NUMBER_MOVES); + + /* To save time later, convert each output character to its own + chtype string, with appropriate attributes. */ + + init_game_chstr(chtype_map_val[MAP_TO_INDEX(MAP_EMPTY)], + printable_map_val[MAP_TO_INDEX(MAP_EMPTY)], + attr_map_empty, MAP_EMPTY); + init_game_chstr(chtype_map_val[MAP_TO_INDEX(MAP_OUTPOST)], + printable_map_val[MAP_TO_INDEX(MAP_OUTPOST)], + attr_map_outpost, MAP_OUTPOST); + init_game_chstr(chtype_map_val[MAP_TO_INDEX(MAP_STAR)], + printable_map_val[MAP_TO_INDEX(MAP_STAR)], + attr_map_star, MAP_STAR); + for (int i = 0; i < MAX_COMPANIES; i++) { + init_game_chstr(chtype_map_val[MAP_TO_INDEX(COMPANY_TO_MAP(i))], + printable_map_val[MAP_TO_INDEX(COMPANY_TO_MAP(i))], + attr_map_company, COMPANY_TO_MAP(i)); + } + + for (int i = 0; i < NUMBER_MOVES; i++) { + init_game_chstr(chtype_game_move[i], printable_game_move[i], + attr_map_choice, printable_game_move[i]); + } + + free(buf); } @@ -1242,7 +1404,7 @@ int vmkchstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, } if (wc == '\0' || wc == WEOF) { - wc = EILSEQ_REPL; + wc = EILSEQ_REPL_WC; } fmtbuf[0] = wc; @@ -1322,7 +1484,7 @@ int vmkchstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, } if (str == NULL) { - str = L"(null)"; // As per GNU printf() + str = L"(NULL)"; // As per GNU printf() } insertstr: @@ -1571,53 +1733,185 @@ int right (WINDOW *win, int y, int x, chtype attr_norm, chtype attr_alt1, } +/***********************************************************************/ +// getwch: Get a wide character from the keyboard + +/* There are two implementations of getwch(): one used if enhanced Curses + is present (with wide-character functions), the other if only + single-byte functions are available. */ + +#if defined(HAVE_CURSES_ENHANCED) || defined(HAVE_NCURSESW) + +int getwch (WINDOW *win, wint_t *wch) +{ + int ret = wget_wch(win, wch); + + if (ret == OK) { + char c = wctob(*wch); + if ((c >= 0 && c < ' ') || c == 0x7F) { + /* Make control characters (and DEL) appear to be similar to + function keys. This assumes the KEY_xxx definitions do + not overlap, which is true of all Curses implementations + (due to the same codes being returned by getch()). We do + not use iswcntrl() as certain additional Unicode + characters are also control characters (eg, U+2028) */ + ret = KEY_CODE_YES; + } + } + + return ret; +} + +#else // !defined(HAVE_CURSES_ENHANCED) && !defined(HAVE_NCURSESW) + +int getwch (WINDOW *win, wint_t *wch) +{ +#error "Single-byte version of getwch() not yet implemented" +"Single-byte version of getwch() not yet implemented" +} + +#endif // !defined(HAVE_CURSES_ENHANCED) && !defined(HAVE_NCURSESW) + + /***********************************************************************/ // gettxchar: Read a character from the keyboard -int gettxchar (WINDOW *win) +int gettxchar (WINDOW *win, wint_t *wch) { - int key; - bool done; + int ret; + assert(win != NULL); + assert(wch != NULL); + keypad(win, true); meta(win, true); wtimeout(win, -1); - done = false; - while (! done) { - key = wgetch(win); - switch (key) { - case ERR: - beep(); + while (true) { + ret = getwch(win, wch); + if (ret == OK) { break; + } else if (ret == KEY_CODE_YES) { #ifdef HANDLE_RESIZE_EVENTS - case KEY_RESIZE: - txresize(); + if (*wch == KEY_RESIZE) { + txresize(); + } else { + break; + } +#else // ! HANDLE_RESIZE_EVENTS break; -#endif // HANDLE_RESIZE_EVENTS +#endif // ! HANDLE_RESIZE_EVENTS - default: - done = true; + } else { + // ret == ERR + beep(); } } - return key; + return ret; } /***********************************************************************/ -// gettxline: Read a line from the keyboard (low-level) +// cpos_endl: Adjust cpos and st for printing the ending part of buf -int gettxline (WINDOW *win, char *buf, int bufsize, bool *restrict modified, - bool multifield, const char *emptyval, const char *defaultval, - const char *allowed, bool stripspc, int y, int x, int width, - chtype attr) +void cpos_endl (wchar_t *restrict buf, int *restrict cpos, int *restrict st, + int clen, int width, int len) +{ + *cpos = MIN(clen, width - 1); + + if (clen <= width - 1) { + // Whole string can be displayed + *st = 0; + } else { + // String too long: figure out offset from which to print (value of st) + int i = width - 1; + *st = len; + while (i > 0) { + i -= wcwidth(buf[--(*st)]); + } + if (i < 0) { + /* Don't truncate a double-width character if the second half + would appear in the first column position. */ + i += wcwidth(buf[(*st)++]); + while (wcwidth(buf[*st]) == 0) { + // Skip over zero-width characters (mostly combining ones) + (*st)++; + } + *cpos -= i; + } + } + + assert(*st >= 0); +} + + +/***********************************************************************/ +// cpos_decr: Adjust cpos and st: scroll to the left by w columns + +void cpos_decr (wchar_t *restrict buf, int *restrict cpos, int *restrict st, + int w, int width) +{ + if (*cpos > 0) { + // Cursor position is not yet in first column + *cpos -= w; + } else if (*st > 0) { + (*st)--; + if (w == 0) { + /* Make sure zero-width characters (esp. combining ones) do + not appear without the associated base character */ + w = wcwidth(buf[*st]); + while (*st > 0 && w == 0) { + w = wcwidth(buf[--(*st)]); + } + *cpos = w; + } + } +} + + +/***********************************************************************/ +// cpos_incr: Adjust cpos and st: scroll to the right by w columns + +void cpos_incr (wchar_t *restrict buf, int *restrict cpos, int *restrict st, + int w, int width) +{ + if (*cpos + w <= width - 1) { + // Cursor position is not yet in second-last column + *cpos += w; + } else { + int i = 0; + while (i < w) { + i += wcwidth(buf[(*st)++]); + } + while (wcwidth(buf[*st]) == 0) { + // Skip over zero-width characters (mainly combining ones) + (*st)++; + } + if (i > w) { + // Take double-width characters into account + *cpos -= i - w; + } + } +} + + +/***********************************************************************/ +// gettxline: Read a line of input from the keyboard (low-level) + +int gettxline (WINDOW *win, wchar_t *restrict buf, int bufsize, + bool *restrict modified, bool multifield, + const wchar_t *emptyval, const wchar_t *defaultval, + const wchar_t *allowed, bool stripspc, int y, int x, + int width, chtype attr) { - int len, pos, cpos, ret; bool done, redraw, mod; - int key, key2; + int len, pos, st; + int clen, cpos; + int rcode, ret; + wint_t key; chtype oldattr; chtype *chbuf; int chbufwidth; @@ -1626,7 +1920,7 @@ int gettxline (WINDOW *win, char *buf, int bufsize, bool *restrict modified, assert(win != NULL); assert(buf != NULL); assert(bufsize > 2); - assert(width > 1); + assert(width > 2); chbuf = xmalloc(BUFSIZE * sizeof(chtype)); @@ -1637,9 +1931,17 @@ int gettxline (WINDOW *win, char *buf, int bufsize, bool *restrict modified, oldattr = getattrs(win); curs_set(CURS_ON); - len = strlen(buf); - pos = len; // pos (string position) is from 0 to len - cpos = MIN(len, width - 1); // cpos (cursor position) is from 0 to width-1 + len = wcslen(buf); // len is number of wide chars in buf + pos = len; // pos (string position): 0 to len + clen = wcswidth(buf, bufsize); // clen is number of column positions + + if (clen < 0) { + err_exit("gettxline: illegal character in string: `%ls'", buf); + } + + // Find the point from which buf should be displayed to screen + cpos_endl(buf, &cpos, &st, clen, width, len); + redraw = true; done = false; mod = false; @@ -1647,55 +1949,73 @@ int gettxline (WINDOW *win, char *buf, int bufsize, bool *restrict modified, while (! done) { if (redraw) { - /* - Redisplay the visible part of the current input string. - Blanks at the end of the input area are replaced with - "attr", which may contain a '_' for non-colour mode. - */ + /* Redisplay the visible part of the current input string. + Blanks at the end of the input area are replaced with + "attr", which may contain a '_' for non-colour mode. */ mvwhline(win, y, x, ((attr & A_CHARTEXT) == 0) ? ' ' | attr : attr, width); mkchstr(chbuf, BUFSIZE, attr & ~A_CHARTEXT, 0, 0, 1, width, - &chbufwidth, 1, "%s", buf + pos - cpos); + &chbufwidth, 1, "%ls", buf + st); leftch(win, y, x, chbuf, 1, &chbufwidth); wmove(win, y, x + cpos); wrefresh(win); } - key = wgetch(win); - if (key == ERR) { - // Do nothing on ERR - ; - } else if ((key == KEY_DEFAULTVAL1 || key == KEY_DEFAULTVAL2) - && defaultval != NULL && len == 0) { - // Initialise buffer with the default value + rcode = getwch(win, &key); - strncpy(buf, defaultval, bufsize - 1); - buf[bufsize - 1] = '\0'; + if (rcode == OK) { + // Ordinary wide character - len = strlen(buf); - pos = len; - cpos = MIN(len, width - 1); - mod = true; - redraw = true; - } else if (key < 0400 && ! iscntrl(key)) { - if (len >= bufsize - 1 - || (allowed != NULL && strchr(allowed, key) == NULL)) { - beep(); - } else { - // Process ordinary key press: insert it into the string + if ((key == CHAR_DEFVAL1 || key == CHAR_DEFVAL2) + && defaultval != NULL && len == 0) { + // Initialise buffer with the default value - memmove(buf + pos + 1, buf + pos, len - pos + 1); - buf[pos] = (char) key; - len++; - pos++; - if (cpos < width - 1) { - cpos++; + wcsncpy(buf, defaultval, bufsize - 1); + buf[bufsize - 1] = L'\0'; + + len = wcslen(buf); + pos = len; + clen = wcswidth(buf, bufsize); + + if (clen == -1) { + err_exit("gettxline: illegal character in string: `%ls'", + buf); } + + cpos_endl(buf, &cpos, &st, clen, width, len); + mod = true; redraw = true; + + } else if (len >= bufsize - 1 + || (allowed != NULL && wcschr(allowed, key) == NULL)) { + beep(); + + } else { + // Process an ordinary character: insert it into the string + int w = wcwidth(key); + + if (w < 0) { + // Non-printing character + beep(); + + } else { + wmemmove(buf + pos + 1, buf + pos, len - pos + 1); + buf[pos] = (wchar_t) key; + len++; + pos++; + + clen += w; + cpos_incr(buf, &cpos, &st, w, width); + + mod = true; + redraw = true; + } } - } else { + + } else if (rcode == KEY_CODE_YES) { + // Function or control key switch (key) { // Terminating keys @@ -1706,30 +2026,30 @@ int gettxline (WINDOW *win, char *buf, int bufsize, bool *restrict modified, // Finish entering the string if (stripspc) { - // Strip leading spaces int i; - for (i = 0; i < len && isspace(buf[i]); i++) + // Strip leading spaces + for (i = 0; i < len && iswspace(buf[i]); i++) ; if (i > 0) { - memmove(buf, buf + i, len - i + 1); + wmemmove(buf, buf + i, len - i + 1); len -= i; mod = true; } // Strip trailing spaces - for (i = len; i > 0 && isspace(buf[i - 1]); i--) + for (i = len; i > 0 && iswspace(buf[i - 1]); i--) ; if (i < len) { - buf[i] = '\0'; + buf[i] = L'\0'; len = i; mod = true; } } if (emptyval != NULL && len == 0) { - strncpy(buf, emptyval, bufsize - 1); - buf[bufsize - 1] = '\0'; + wcsncpy(buf, emptyval, bufsize - 1); + buf[bufsize - 1] = L'\0'; mod = true; } @@ -1739,8 +2059,8 @@ int gettxline (WINDOW *win, char *buf, int bufsize, bool *restrict modified, case KEY_CANCEL: case KEY_EXIT: - case KEY_CTRL('G'): case KEY_CTRL('C'): + case KEY_CTRL('G'): case KEY_CTRL('\\'): // Cancel entering the string ret = ERR; @@ -1780,9 +2100,7 @@ int gettxline (WINDOW *win, char *buf, int bufsize, bool *restrict modified, beep(); } else { pos--; - if (cpos > 0) { - cpos--; - } + cpos_decr(buf, &cpos, &st, wcwidth(buf[pos]), width); redraw = true; } break; @@ -1794,9 +2112,7 @@ int gettxline (WINDOW *win, char *buf, int bufsize, bool *restrict modified, beep(); } else { pos++; - if (cpos < width - 1) { - cpos++; - } + cpos_incr(buf, &cpos, &st, wcwidth(buf[pos - 1]), width); redraw = true; } break; @@ -1806,6 +2122,7 @@ int gettxline (WINDOW *win, char *buf, int bufsize, bool *restrict modified, // Move cursor to start of string pos = 0; cpos = 0; + st = 0; redraw = true; break; @@ -1813,40 +2130,39 @@ int gettxline (WINDOW *win, char *buf, int bufsize, bool *restrict modified, case KEY_CTRL('E'): // Move cursor to end of string pos = len; - cpos = MIN(pos, width - 1); + cpos_endl(buf, &cpos, &st, clen, width, len); redraw = true; break; case KEY_CLEFT: // Move cursor to start of current or previous word - while (pos > 0 && ! isalnum(buf[pos - 1])) { + while (pos > 0 && ! iswalnum(buf[pos - 1])) { pos--; - if (cpos > 0) { - cpos--; - } + cpos_decr(buf, &cpos, &st, wcwidth(buf[pos]), width); } - while (pos > 0 && isalnum(buf[pos - 1])) { + while (pos > 0 && (iswalnum(buf[pos - 1]) + || (pos > 1 && wcwidth(buf[pos - 1]) == 0 + && iswalnum(buf[pos - 2])))) { + /* Treat zero-width characters preceded by an + alphanumeric character as alphanumeric. */ pos--; - if (cpos > 0) { - cpos--; - } + cpos_decr(buf, &cpos, &st, wcwidth(buf[pos]), width); } redraw = true; break; case KEY_CRIGHT: // Move cursor to end of current or next word - while (pos < len && ! isalnum(buf[pos])) { + while (pos < len && ! iswalnum(buf[pos])) { pos++; - if (cpos < width - 1) { - cpos++; - } + cpos_incr(buf, &cpos, &st, wcwidth(buf[pos - 1]), width); } - while (pos < len && isalnum(buf[pos])) { + while (pos < len + && (iswalnum(buf[pos]) || wcwidth(buf[pos]) == 0)) { + /* Treat zero-width characters following an + alphanumeric character as alphanumeric. */ pos++; - if (cpos < width - 1) { - cpos++; - } + cpos_incr(buf, &cpos, &st, wcwidth(buf[pos - 1]), width); } redraw = true; break; @@ -1860,12 +2176,12 @@ int gettxline (WINDOW *win, char *buf, int bufsize, bool *restrict modified, if (pos == 0) { beep(); } else { - memmove(buf + pos - 1, buf + pos, len - pos + 1); + int w = wcwidth(buf[pos - 1]); + wmemmove(buf + pos - 1, buf + pos, len - pos + 1); len--; pos--; - if (cpos > 0) { - cpos--; - } + clen -= w; + cpos_decr(buf, &cpos, &st, w, width); mod = true; redraw = true; } @@ -1877,9 +2193,11 @@ int gettxline (WINDOW *win, char *buf, int bufsize, bool *restrict modified, if (pos == len) { beep(); } else { - memmove(buf + pos, buf + pos + 1, len - pos); + int w = wcwidth(buf[pos]); + wmemmove(buf + pos, buf + pos + 1, len - pos); len--; - // pos and cpos stay the same + clen -= w; + // pos, cpos and st stay the same mod = true; redraw = true; } @@ -1887,10 +2205,12 @@ int gettxline (WINDOW *win, char *buf, int bufsize, bool *restrict modified, case KEY_CLEAR: // Delete the entire line - strcpy(buf, ""); + wcscpy(buf, L""); len = 0; pos = 0; + clen = 0; cpos = 0; + st = 0; mod = true; redraw = true; break; @@ -1900,10 +2220,17 @@ int gettxline (WINDOW *win, char *buf, int bufsize, bool *restrict modified, if (pos == 0) { beep(); } else { - memmove(buf, buf + pos, len - pos + 1); + int i, ww; + for (i = 0, ww = 0; i < pos; i++) { + ww += wcwidth(buf[i]); + } + + wmemmove(buf, buf + pos, len - pos + 1); len -= pos; pos = 0; + clen -= ww; cpos = 0; + st = 0; mod = true; redraw = true; } @@ -1914,9 +2241,15 @@ int gettxline (WINDOW *win, char *buf, int bufsize, bool *restrict modified, if (pos == len) { beep(); } else { - buf[pos] = '\0'; + int i, ww; + for (i = pos, ww = 0; i < len; i++) { + ww += wcwidth(buf[i]); + } + + buf[pos] = L'\0'; len = pos; - // pos and cpos stay the same + clen -= ww; + // pos, cpos and st stay the same mod = true; redraw = true; } @@ -1927,28 +2260,28 @@ int gettxline (WINDOW *win, char *buf, int bufsize, bool *restrict modified, if (pos == 0) { beep(); } else { - /* - Note the use of isspace() instead of isalnum(): - this makes ^W follow GNU Bash standards, which - behaves differently from Meta-DEL. - */ + /* Note the use of iswspace() instead of iswalnum(): + this makes ^W follow GNU Bash standards, which + behaves differently from Meta-DEL. */ int i = pos; - while (i > 0 && isspace(buf[i - 1])) { + int ww = 0; + while (i > 0 && iswspace(buf[i - 1])) { i--; - if (cpos > 0) { - cpos--; - } + int w = wcwidth(buf[i]); + ww += w; + cpos_decr(buf, &cpos, &st, w, width); } - while (i > 0 && ! isspace(buf[i - 1])) { + while (i > 0 && ! iswspace(buf[i - 1])) { i--; - if (cpos > 0) { - cpos--; - } + int w = wcwidth(buf[i]); + ww += w; + cpos_decr(buf, &cpos, &st, w, width); } - memmove(buf + i, buf + pos, len - pos + 1); + wmemmove(buf + i, buf + pos, len - pos + 1); len -= pos - i; pos = i; + clen -= ww; mod = true; redraw = true; } @@ -1961,20 +2294,21 @@ int gettxline (WINDOW *win, char *buf, int bufsize, bool *restrict modified, if (pos == 0 || len <= 1) { beep(); } else if (pos == len) { - char c = buf[pos - 1]; + wchar_t c = buf[pos - 1]; buf[pos - 1] = buf[pos - 2]; buf[pos - 2] = c; mod = true; redraw = true; } else { - char c = buf[pos]; + wchar_t c = buf[pos]; + int w = wcwidth(c); + buf[pos] = buf[pos - 1]; buf[pos - 1] = c; pos++; - if (cpos < width - 1) { - cpos++; - } + cpos_incr(buf, &cpos, &st, w, width); + mod = true; redraw = true; } @@ -1983,64 +2317,226 @@ int gettxline (WINDOW *win, char *buf, int bufsize, bool *restrict modified, case KEY_ESC: // Handle Meta-X-style and other function key presses wtimeout(win, META_TIMEOUT); - key2 = wgetch(win); + rcode = getwch(win, &key); + + if (rcode == OK) { + // Ordinary wide character - if (key2 == ERR) { - // by itself: cancel entering the string - ret = ERR; - done = true; - } else if (key2 == 'O' || key2 == '[') { // Swallow any unknown VT100-style function keys - key2 = wgetch(win); - while (key2 != ERR && isascii(key2) - && strchr("0123456789;", key2) != NULL - && strchr("~ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz", key2) - == NULL) { - key2 = wgetch(win); + if (key == L'O' || key == L'[') { + rcode = getwch(win, &key); + while (rcode == OK + && wcschr(L"0123456789;", key) != NULL + && wcschr(L"~ABCDEFGHIJKLMNOPQRSTUVWXYZ" + L"abcdefghijklmnopqrstuvwxyz", key) + == NULL) { + rcode = getwch(win, &key); + } + beep(); + + } else { + // Handle Meta-X-style keypress + switch (key) { + + // Cursor movement keys + + case L'B': + case L'b': + // Move cursor to start of current or previous word + while (pos > 0 && ! iswalnum(buf[pos - 1])) { + pos--; + cpos_decr(buf, &cpos, &st, wcwidth(buf[pos]), + width); + } + while (pos > 0 && (iswalnum(buf[pos - 1]) + || (pos > 1 + && wcwidth(buf[pos - 1]) == 0 + && iswalnum(buf[pos - 2])))) { + /* Treat zero-width characters preceded by an + alphanumeric character as alphanumeric. */ + pos--; + cpos_decr(buf, &cpos, &st, wcwidth(buf[pos]), + width); + } + redraw = true; + break; + + case L'F': + case L'f': + // Move cursor to end of current or next word + while (pos < len && ! iswalnum(buf[pos])) { + pos++; + cpos_incr(buf, &cpos, &st, + wcwidth(buf[pos - 1]), width); + } + while (pos < len + && (iswalnum(buf[pos]) + || wcwidth(buf[pos]) == 0)) { + /* Treat zero-width characters following an + alphanumeric character as alphanumeric. */ + pos++; + cpos_incr(buf, &cpos, &st, + wcwidth(buf[pos - 1]), width); + } + redraw = true; + break; + + // Deletion keys + + case L'D': + case L'd': + // Delete the next word + { + int i = pos; + int ww = 0; + while (i < len && ! iswalnum(buf[i])) { + i++; + ww += wcwidth(buf[i - 1]); + } + while (i < len + && (iswalnum(buf[i]) + || wcwidth(buf[pos]) == 0)) { + /* Treat zero-width characters + following an alphanumeric + character as alphanumeric. */ + i++; + ww += wcwidth(buf[i - 1]); + } + + wmemmove(buf + pos, buf + i, len - i + 1); + len -= (i - pos); + clen -= ww; + // pos, cpos and st stay the same + mod = true; + redraw = true; + } + break; + + case L'\\': + case L' ': + // Delete all surrounding spaces; if key == ' ', + // also insert one space + { + int i = pos; + int ww = 0; + while (pos > 0 && iswspace(buf[pos - 1])) { + pos--; + int w = wcwidth(buf[pos]); + ww += w; + cpos_decr(buf, &cpos, &st, w, width); + } + while (i < len && iswspace(buf[i])) { + i++; + ww += wcwidth(buf[i - 1]); + } + + wmemmove(buf + pos, buf + i, len - i + 1); + len -= (i - pos); + clen -= ww; + + if (key == L' ') { + if (len >= bufsize - 1 || (allowed != NULL + && wcschr(allowed, key) == NULL)) { + beep(); + } else { + wchar_t c = L' '; + wmemmove(buf + pos + 1, buf + pos, + len - pos + 1); + buf[pos] = c; + len++; + pos++; + + int w = wcwidth(c); + clen += w; + cpos_incr(buf, &cpos, &st, w, width); + } + } + + mod = true; + redraw = true; + } + break; + + // Transformation keys + + case L'U': + case L'u': + // Convert word (from cursor onwards) to upper case + while (pos < len && ! iswalnum(buf[pos])) { + pos++; + cpos_incr(buf, &cpos, &st, + wcwidth(buf[pos - 1]), width); + } + while (pos < len + && (iswalnum(buf[pos]) + || wcwidth(buf[pos]) == 0)) { + buf[pos] = towupper(buf[pos]); + pos++; + cpos_incr(buf, &cpos, &st, + wcwidth(buf[pos - 1]), width); + } + mod = true; + redraw = true; + break; + + case L'L': + case L'l': + // Convert word (from cursor onwards) to lower case + while (pos < len && ! iswalnum(buf[pos])) { + pos++; + cpos_incr(buf, &cpos, &st, + wcwidth(buf[pos - 1]), width); + } + while (pos < len + && (iswalnum(buf[pos]) + || wcwidth(buf[pos]) == 0)) { + buf[pos] = towlower(buf[pos]); + pos++; + cpos_incr(buf, &cpos, &st, + wcwidth(buf[pos - 1]), width); + } + mod = true; + redraw = true; + break; + + case L'C': + case L'c': + // Convert current letter to upper case, + // following letters to lower case + { + bool first = true; + while (pos < len && ! iswalnum(buf[pos])) { + pos++; + cpos_incr(buf, &cpos, &st, + wcwidth(buf[pos - 1]), width); + } + while (pos < len + && (iswalnum(buf[pos]) + || wcwidth(buf[pos]) == 0)) { + if (first) { + buf[pos] = towupper(buf[pos]); + first = false; + } else { + buf[pos] = towlower(buf[pos]); + } + pos++; + cpos_incr(buf, &cpos, &st, + wcwidth(buf[pos - 1]), width); + } + mod = true; + redraw = true; + } + break; + + default: + beep(); + } } - beep(); - } else { - // Handle Meta-X-style keypress - switch (key2) { - // Cursor movement keys + } else if (rcode == KEY_CODE_YES) { + // Function or control key (with preceding Meta key) - case 'B': - case 'b': - // Move cursor to start of current or previous word - while (pos > 0 && ! isalnum(buf[pos - 1])) { - pos--; - if (cpos > 0) { - cpos--; - } - } - while (pos > 0 && isalnum(buf[pos - 1])) { - pos--; - if (cpos > 0) { - cpos--; - } - } - redraw = true; - break; - - case 'F': - case 'f': - // Move cursor to end of current or next word - while (pos < len && ! isalnum(buf[pos])) { - pos++; - if (cpos < width - 1) { - cpos++; - } - } - while (pos < len && isalnum(buf[pos])) { - pos++; - if (cpos < width - 1) { - cpos++; - } - } - redraw = true; - break; + switch (key) { // Deletion keys @@ -2049,154 +2545,30 @@ int gettxline (WINDOW *win, char *buf, int bufsize, bool *restrict modified, case KEY_DEL: // Delete the previous word (different from ^W) { + int ww = 0; int i = pos; - while (i > 0 && ! isalnum(buf[i - 1])) { + while (i > 0 && ! iswalnum(buf[i - 1])) { i--; - if (cpos > 0) { - cpos--; - } + int w = wcwidth(buf[i]); + ww += w; + cpos_decr(buf, &cpos, &st, w, width); } - while (i > 0 && isalnum(buf[i - 1])) { + while (i > 0 + && (iswalnum(buf[i - 1]) + || (i > 1 && wcwidth(buf[i - 1]) == 0 + && iswalnum(buf[i - 2])))) { + /* Treat zero-width characters preceded by an + alphanumeric character as alphanumeric. */ i--; - if (cpos > 0) { - cpos--; - } + int w = wcwidth(buf[i]); + ww += w; + cpos_decr(buf, &cpos, &st, w, width); } - memmove(buf + i, buf + pos, len - pos + 1); + wmemmove(buf + i, buf + pos, len - pos + 1); len -= (pos - i); pos = i; - mod = true; - redraw = true; - } - break; - - case 'D': - case 'd': - // Delete the next word - { - int i = pos; - while (i < len && ! isalnum(buf[i])) { - i++; - } - while (i < len && isalnum(buf[i])) { - i++; - } - - memmove(buf + pos, buf + i, len - i + 1); - len -= (i - pos); - // pos and cpos stay the same - mod = true; - redraw = true; - } - break; - - case '\\': - case ' ': - // Delete all surrounding spaces; if key2 == ' ', - // also insert one space - { - int i = pos; - while (pos > 0 && isspace(buf[pos - 1])) { - pos--; - if (cpos > 0) { - cpos--; - } - } - while (i < len && isspace(buf[i])) { - i++; - } - - memmove(buf + pos, buf + i, len - i + 1); - len -= (i - pos); - - if (key2 == ' ') { - if (len >= bufsize - 1 || (allowed != NULL - && strchr(allowed, key) == NULL)) { - beep(); - } else { - memmove(buf + pos + 1, buf + pos, - len - pos + 1); - buf[pos] = ' '; - len++; - pos++; - if (cpos < width - 1) { - cpos++; - } - } - } - - mod = true; - redraw = true; - } - break; - - // Transformation keys - - case 'U': - case 'u': - // Convert word (from cursor onwards) to upper case - while (pos < len && ! isalnum(buf[pos])) { - pos++; - if (cpos < width - 1) { - cpos++; - } - } - while (pos < len && isalnum(buf[pos])) { - buf[pos] = toupper(buf[pos]); - pos++; - if (cpos < width - 1) { - cpos++; - } - } - mod = true; - redraw = true; - break; - - case 'L': - case 'l': - // Convert word (from cursor onwards) to lower case - while (pos < len && ! isalnum(buf[pos])) { - pos++; - if (cpos < width - 1) { - cpos++; - } - } - while (pos < len && isalnum(buf[pos])) { - buf[pos] = tolower(buf[pos]); - pos++; - if (cpos < width - 1) { - cpos++; - } - } - mod = true; - redraw = true; - break; - - case 'C': - case 'c': - // Convert current letter to upper case, following - // letters to lower case - { - bool first = true; - while (pos < len && ! isalnum(buf[pos])) { - pos++; - if (cpos < width - 1) { - cpos++; - } - } - while (pos < len && isalnum(buf[pos])) { - if (first) { - buf[pos] = toupper(buf[pos]); - first = false; - } else { - buf[pos] = tolower(buf[pos]); - } - pos++; - if (cpos < width - 1) { - cpos++; - } - } + clen -= ww; mod = true; redraw = true; } @@ -2213,6 +2585,12 @@ int gettxline (WINDOW *win, char *buf, int bufsize, bool *restrict modified, default: beep(); } + + } else { + /* rcode == ERR (timeout): by itself, so cancel + entering the string. */ + ret = ERR; + done = true; } wtimeout(win, -1); @@ -2227,6 +2605,9 @@ int gettxline (WINDOW *win, char *buf, int bufsize, bool *restrict modified, default: beep(); } + } else { + // rcode == ERR: Do nothing + ; } } @@ -2234,7 +2615,7 @@ int gettxline (WINDOW *win, char *buf, int bufsize, bool *restrict modified, mvwhline(win, y, x, ' ' | oldattr, width); mkchstr(chbuf, BUFSIZE, oldattr | A_BOLD, 0, 0, 1, width, - &chbufwidth, 1, "%s", buf); + &chbufwidth, 1, "%ls", buf); leftch(win, y, x, chbuf, 1, &chbufwidth); wrefresh(win); @@ -2250,19 +2631,20 @@ int gettxline (WINDOW *win, char *buf, int bufsize, bool *restrict modified, /***********************************************************************/ // gettxstr: Read a string from the keyboard -int gettxstr (WINDOW *win, char **bufptr, bool *restrict modified, - bool multifield, int y, int x, int width, chtype attr) +int gettxstr (WINDOW *win, wchar_t *restrict *restrict bufptr, + bool *restrict modified, bool multifield, int y, int x, + int width, chtype attr) { assert(bufptr != NULL); // Allocate the result buffer if needed if (*bufptr == NULL) { - *bufptr = xmalloc(BUFSIZE); + *bufptr = xmalloc(BUFSIZE * sizeof(wchar_t)); **bufptr = '\0'; } - return gettxline(win, *bufptr, BUFSIZE, modified, multifield, "", "", + return gettxline(win, *bufptr, BUFSIZE, modified, multifield, L"", L"", NULL, true, y, x, width, attr); } @@ -2270,33 +2652,32 @@ int gettxstr (WINDOW *win, char **bufptr, bool *restrict modified, /***********************************************************************/ // txinput_fixup: Copy strings with fixup -void txinput_fixup (char *restrict dest, char *restrict src, bool isfloat) +void txinput_fixup (wchar_t *restrict dest, wchar_t *restrict src, bool isfloat) { - struct lconv *lc = &lconvinfo; - char *p; - - assert(src != NULL); assert(dest != NULL); - strncpy(dest, src, BUFSIZE - 1); + wcsncpy(dest, src, BUFSIZE - 1); dest[BUFSIZE - 1] = '\0'; // Replace mon_decimal_point with decimal_point if these are different if (isfloat) { - if (strcmp(lc->mon_decimal_point, "") != 0 - && strcmp(lc->decimal_point, "") != 0 - && strcmp(lc->mon_decimal_point, lc->decimal_point) != 0) { - while ((p = strstr(dest, lc->mon_decimal_point)) != NULL) { - char *pn; - int len1 = strlen(lc->mon_decimal_point); - int len2 = strlen(lc->decimal_point); + if (*mon_decimal_point != L'\0' && *decimal_point != L'\0' + && wcscmp(mon_decimal_point, decimal_point) != 0) { - // Make space for lc->decimal_point, if needed - memmove(p + len2, p + len1, strlen(p) - (len2 - len1) + 1); + int len_dp = wcslen(decimal_point); + int len_mdp = wcslen(mon_decimal_point); + wchar_t *p; - // Copy lc->decimal_point over p WITHOUT copying ending NUL - for (pn = lc->decimal_point; *pn != '\0'; pn++, p++) { + while ((p = wcsstr(dest, mon_decimal_point)) != NULL) { + // Make space for decimal_point, if needed + if (len_mdp != len_dp) { + wmemmove(p + len_dp, p + len_mdp, + wcslen(p) - (len_dp - len_mdp) + 1); + } + + // Copy decimal_point over p WITHOUT copying ending NUL + for (wchar_t *pn = decimal_point; *pn != L'\0'; pn++, p++) { *p = *pn; } } @@ -2304,16 +2685,20 @@ void txinput_fixup (char *restrict dest, char *restrict src, bool isfloat) } // Remove thousands separators if required - if (strcmp(lc->thousands_sep, "") != 0) { - while ((p = strstr(dest, lc->thousands_sep)) != NULL) { - int len = strlen(lc->thousands_sep); - memmove(p, p + len, strlen(p) - len + 1); + if (*thousands_sep != L'\0') { + int len = wcslen(thousands_sep); + wchar_t *p; + + while ((p = wcsstr(dest, thousands_sep)) != NULL) { + wmemmove(p, p + len, wcslen(p) - len + 1); } } - if (strcmp(lc->mon_thousands_sep, "") != 0) { - while ((p = strstr(dest, lc->mon_thousands_sep)) != NULL) { - int len = strlen(lc->thousands_sep); - memmove(p, p + len, strlen(p) - len + 1); + if (*mon_thousands_sep != L'\0') { + int len = wcslen(mon_thousands_sep); + wchar_t *p; + + while ((p = wcsstr(dest, mon_thousands_sep)) != NULL) { + wmemmove(p, p + len, wcslen(p) - len + 1); } } } @@ -2328,8 +2713,8 @@ int gettxdouble (WINDOW *win, double *restrict result, double min, { struct lconv *lc = &lconvinfo; - char *buf, *bufcopy; - char *allowed, *emptystr, *defaultstr; + wchar_t *buf, *bufcopy; + wchar_t *allowed, *emptystr, *defaultstr; double val; bool done; int ret; @@ -2338,22 +2723,22 @@ int gettxdouble (WINDOW *win, double *restrict result, double min, assert(result != NULL); assert(min <= max); - buf = xmalloc(BUFSIZE); - bufcopy = xmalloc(BUFSIZE); - allowed = xmalloc(BUFSIZE); - emptystr = xmalloc(BUFSIZE); - defaultstr = xmalloc(BUFSIZE); + buf = xmalloc(BUFSIZE * sizeof(wchar_t)); + bufcopy = xmalloc(BUFSIZE * sizeof(wchar_t)); + allowed = xmalloc(BUFSIZE * sizeof(wchar_t)); + emptystr = xmalloc(BUFSIZE * sizeof(wchar_t)); + defaultstr = xmalloc(BUFSIZE * sizeof(wchar_t)); - *buf = '\0'; + *buf = L'\0'; - strcpy(allowed, "0123456789+-Ee"); - strncat(allowed, lc->decimal_point, BUFSIZE - strlen(allowed) - 1); - strncat(allowed, lc->thousands_sep, BUFSIZE - strlen(allowed) - 1); - strncat(allowed, lc->mon_decimal_point, BUFSIZE - strlen(allowed) - 1); - strncat(allowed, lc->mon_thousands_sep, BUFSIZE - strlen(allowed) - 1); + wcscpy(allowed, L"0123456789+-Ee"); + wcsncat(allowed, decimal_point, BUFSIZE - wcslen(allowed) - 1); + wcsncat(allowed, thousands_sep, BUFSIZE - wcslen(allowed) - 1); + wcsncat(allowed, mon_decimal_point, BUFSIZE - wcslen(allowed) - 1); + wcsncat(allowed, mon_thousands_sep, BUFSIZE - wcslen(allowed) - 1); - snprintf(emptystr, BUFSIZE, "%'1.*f", lc->frac_digits, emptyval); - snprintf(defaultstr, BUFSIZE, "%'1.*f", lc->frac_digits, defaultval); + swprintf(emptystr, BUFSIZE, L"%'1.*f", lc->frac_digits, emptyval); + swprintf(defaultstr, BUFSIZE, L"%'1.*f", lc->frac_digits, defaultval); done = false; while (! done) { @@ -2361,12 +2746,12 @@ int gettxdouble (WINDOW *win, double *restrict result, double min, allowed, true, y, x, width, attr); if (ret == OK) { - char *p; + wchar_t *p; txinput_fixup(bufcopy, buf, true); - val = strtod(bufcopy, &p); + val = wcstod(bufcopy, &p); - if (*p == '\0' && val >= min && val <= max) { + if (*p == L'\0' && val >= min && val <= max) { *result = val; done = true; } else { @@ -2394,10 +2779,8 @@ int gettxlong (WINDOW *win, long int *restrict result, long int min, long int max, long int emptyval, long int defaultval, int y, int x, int width, chtype attr) { - struct lconv *lc = &lconvinfo; - - char *buf, *bufcopy; - char *allowed, *emptystr, *defaultstr; + wchar_t *buf, *bufcopy; + wchar_t *allowed, *emptystr, *defaultstr; long int val; bool done; int ret; @@ -2406,20 +2789,20 @@ int gettxlong (WINDOW *win, long int *restrict result, long int min, assert(result != NULL); assert(min <= max); - buf = xmalloc(BUFSIZE); - bufcopy = xmalloc(BUFSIZE); - allowed = xmalloc(BUFSIZE); - emptystr = xmalloc(BUFSIZE); - defaultstr = xmalloc(BUFSIZE); + buf = xmalloc(BUFSIZE * sizeof(wchar_t)); + bufcopy = xmalloc(BUFSIZE * sizeof(wchar_t)); + allowed = xmalloc(BUFSIZE * sizeof(wchar_t)); + emptystr = xmalloc(BUFSIZE * sizeof(wchar_t)); + defaultstr = xmalloc(BUFSIZE * sizeof(wchar_t)); - *buf = '\0'; + *buf = L'\0'; - strcpy(allowed, "0123456789+-"); - strncat(allowed, lc->thousands_sep, BUFSIZE - strlen(allowed) - 1); - strncat(allowed, lc->mon_thousands_sep, BUFSIZE - strlen(allowed) - 1); + wcscpy(allowed, L"0123456789+-"); + wcsncat(allowed, thousands_sep, BUFSIZE - wcslen(allowed) - 1); + wcsncat(allowed, mon_thousands_sep, BUFSIZE - wcslen(allowed) - 1); - snprintf(emptystr, BUFSIZE, "%'1ld", emptyval); - snprintf(defaultstr, BUFSIZE, "%'1ld", defaultval); + swprintf(emptystr, BUFSIZE, L"%'1ld", emptyval); + swprintf(defaultstr, BUFSIZE, L"%'1ld", defaultval); done = false; while (! done) { @@ -2427,12 +2810,12 @@ int gettxlong (WINDOW *win, long int *restrict result, long int min, allowed, true, y, x, width, attr); if (ret == OK) { - char *p; + wchar_t *p; txinput_fixup(bufcopy, buf, false); - val = strtol(bufcopy, &p, 10); + val = wcstol(bufcopy, &p, 10); - if (*p == '\0' && val >= min && val <= max) { + if (*p == L'\0' && val >= min && val <= max) { *result = val; done = true; } else { @@ -2490,21 +2873,32 @@ bool answer_yesno (WINDOW *win) curs_set(CURS_ON); while (true) { - int key = wgetch(win); + wint_t key; + int r = getwch(win, &key); + + if (r == OK) { + if (wcschr(keycode_yes, key) != NULL) { + ret = true; + break; + } else if (wcschr(keycode_no, key) != NULL) { + ret = false; + break; + } else { + beep(); + } + } else if (r == KEY_CODE_YES) { - if (wcschr(keycode_yes, key) != NULL) { - ret = true; - break; - } else if (wcschr(keycode_no, key) != NULL) { - ret = false; - break; - } else #ifdef HANDLE_RESIZE_EVENTS - if (key == KEY_RESIZE) { - txresize(); - } else -#endif // HANDLE_RESIZE_EVENTS - { + if (key == KEY_RESIZE) { + txresize(); + } else { + beep(); + } +#else // ! HANDLE_RESIZE_EVENTS + beep(); +#endif // ! HANDLE_RESIZE_EVENTS + + } else { beep(); } } @@ -2534,8 +2928,8 @@ bool answer_yesno (WINDOW *win) void wait_for_key (WINDOW *win, int y, chtype attr) { - int key; - bool done; + wint_t key; + int r; keypad(win, true); @@ -2549,22 +2943,24 @@ void wait_for_key (WINDOW *win, int y, chtype attr) _("[ Press to continue ] ")); wrefresh(win); - done = false; - while (! done) { - key = wgetch(win); - switch (key) { - case ERR: - beep(); + while (true) { + r = getwch(win, &key); + if (r == OK) { break; + } else if (r == KEY_CODE_YES) { #ifdef HANDLE_RESIZE_EVENTS - case KEY_RESIZE: - txresize(); + if (key == KEY_RESIZE) { + txresize(); + } else { + break; + } +#else // ! HANDLE_RESIZE_EVENTS break; -#endif // HANDLE_RESIZE_EVENTS +#endif // ! HANDLE_RESIZE_EVENTS - default: - done = true; + } else { + beep(); } } } diff --git a/src/intf.h b/src/intf.h index 8a27e0c..c22eeb3 100644 --- a/src/intf.h +++ b/src/intf.h @@ -105,8 +105,8 @@ typedef enum curs_type { #define KEY_CTRL(x) ((x) - 0100) // ASCII control character // Keycodes for inserting the default value in input routines -#define KEY_DEFAULTVAL1 '=' -#define KEY_DEFAULTVAL2 ';' +#define CHAR_DEFVAL1 '=' +#define CHAR_DEFVAL2 ';' // Control-arrow key combinations, as returned by Ncurses #ifndef KEY_CDOWN @@ -116,6 +116,11 @@ typedef enum curs_type { # define KEY_CRIGHT 01052 // CTRL + Right Arrow #endif +// Function-key result, for Curses that do not define it +#ifndef KEY_CODE_YES +# define KEY_CODE_YES 0400 +#endif + // Timeout value (in ms) for Meta-X-style keyboard input #ifdef NCURSES_VERSION # define META_TIMEOUT ESCDELAY @@ -321,7 +326,7 @@ extern int txdlgbox (int maxlines, int ncols, int begin_y, int begin_x, Returns: int - Number of lines actually used This function converts the format string and following arguments into - chbuf, a chtype buffer that can be used for calls to leftch(), centerch() + chbuf, a chtype string that can be used for calls to leftch(), centerch() and rightch(). At most maxlines lines are used, each with a maximum width of maxwidth. The actual widths of each resulting line are stored in widthbuf (which must not be NULL). If maxlines is greater than 1, @@ -534,26 +539,26 @@ extern int right (WINDOW *win, int y, int x, chtype attr_norm, chtype attr_alt1, /* - Function: gettxchar - Read a character from the keyboard + Function: gettxchar - Read a wide character from the keyboard Parameters: win - Window to use (should be curwin) - Returns: int - The keyboard character + wch - Pointer to keyboard wide character + Returns: int - OK or KEY_CODE_YES - This function reads a single character from the keyboard. The key is - NOT echoed to the terminal display, nor is the cursor visibility - affected. - - This implementation does not handle multibyte characters correctly: - each part of the multibyte character most likely appears as a separate - keyboard press. + This function waits until the user presses a key on the keyboard, then + reads that key as a single wide character. If it is a function key or + a control key, it is stored in wch and KEY_CODE_YES is returned. + Otherwise, it is an ordinary key: it is also stored in wch and OK is + returned. ERR is never returned. The key is NOT echoed to the + terminal display, nor is the cursor visibility affected. */ -extern int gettxchar (WINDOW *win); +extern int gettxchar (WINDOW *win, wint_t *wch); /* - Function: gettxline - Read a line from the keyboard (low-level) + Function: gettxline - Read a line of input from the keyboard (low-level) Parameters: win - Window to use (should be curwin) buf - Pointer to preallocated buffer - bufsize - Size of buffer in bytes + bufsize - Size of buffer (number of wchar_t elements) modified - Pointer to modified status (result) multifield - Allow , etc, to exit this function emptyval - String used if input line is empty @@ -561,14 +566,14 @@ extern int gettxchar (WINDOW *win); allowed - Characters allowed in the input line stripspc - True to strip leading/trailing spaces y, x - Start of the input field (line, column) - width - Width of the input field + width - Width of the input field (column spaces) attr - Character rendition to use for input field Returns: int - Status code: OK, ERR or KEY_ keycode - This low-level function draws an input field width characters long + This low-level function shows an input field width column spaces long using attr as the character rendition, then reads a line of input from the keyboard and places it into the preallocated buffer buf[] of size - bufsize. On entry, buf[] must contain a valid C string; this string is + bufsize. On entry, buf[] must contain a valid string; this string is used as the initial contents of the input field. On exit, buf[] contains the final string as edited or input by the user. This string is printed in place of the input field using the original character @@ -580,13 +585,13 @@ extern int gettxchar (WINDOW *win); empty string is entered, the string pointed to by emptyval (if not NULL) is stored in buf[]. - If CANCEL, EXIT, ESC, ^C, ^\ or ^G is pressed, ERR is returned. In + If ESC, CANCEL, EXIT, ^C, ^G or ^\ is pressed, ERR is returned. In this case, buf[] contains the string as left by the user: emptyval is NOT used, nor are leading and trailing spaces stripped. If multifield is true, the UP and DOWN arrow keys, as well as TAB, - Shift-TAB, ^P (Previous) and ^N (Next) return KEY_UP or KEY_DOWN as - appropriate. As with CANCEL etc., emptyval is NOT used, nor are + Shift-TAB, ^P (Previous) and ^N (Next) return either KEY_UP or KEY_DOWN + as appropriate. As with ESC etc., emptyval is NOT used, nor are leading and trailing spaces stripped. In all of these cases, the boolean variable *modified (if modified is @@ -594,7 +599,7 @@ extern int gettxchar (WINDOW *win); way (including if the user made any changed, spaces were stripped or if emptyval was copied into buf[]). - If KEY_DEFAULTVAL1 or KEY_DEFAULTVAL2 is pressed when the input line is + If either KEY_DEFVAL1 or KEY_DEFVAL2 is pressed when the input line is empty, the string pointed to by defaultval (if not NULL) is placed in the buffer as if typed by the user. Editing is NOT terminated in this case. @@ -607,17 +612,12 @@ extern int gettxchar (WINDOW *win); Note that the character rendition (attributes) in attr may contain a printing character. For example, A_BOLD | '_' is a valid rendition that causes the input field to be a series of "_" characters in bold. - - This implementation does not handle multibyte characters correctly: - each part of the multibyte character most likely appears as a separate - keyboard press and is handled as a separate character, causing the - cursor position to be incorrect. In addition, allowed is compared on a - byte-by-byte basis, not character-by-character. + Note also that the cursor becomes invisible after calling this function. */ -extern int gettxline (WINDOW *win, char *buf, int bufsize, +extern int gettxline (WINDOW *win, wchar_t *restrict buf, int bufsize, bool *restrict modified, bool multifield, - const char *emptyval, const char *defaultval, - const char *allowed, bool stripspc, int y, int x, + const wchar_t *emptyval, const wchar_t *defaultval, + const wchar_t *allowed, bool stripspc, int y, int x, int width, chtype attr); @@ -633,18 +633,19 @@ extern int gettxline (WINDOW *win, char *buf, int bufsize, Returns: int - Status code: OK, ERR or KEY_ keycode This function calls gettxline() to allow the user to enter a string via - the keyboard. On entry, bufptr must be the address of a char * pointer - variable; that pointer (*bufptr) must either be NULL or contain the - address of a buffer previously allocated with gettxstr(). If *bufptr - is NULL, a buffer of BUFSIZE is automatically allocated using malloc(); - this buffer is used to store and return the input line. + the keyboard. On entry, bufptr must be the address of a wchar_t * + pointer variable; that pointer (*bufptr) must either be NULL or contain + the address of a buffer previously allocated with gettxstr(). If + *bufptr is NULL, a buffer of BUFSIZE is automatically allocated using + malloc(); this buffer is used to store and return the input line. Apart from bufptr, all parameters are as used for gettxline(). The gettxline() parameters emptyval and defaultval are passed as "", allowed is NULL and stripspc is true. */ -extern int gettxstr (WINDOW *win, char **bufptr, bool *restrict modified, - bool multifield, int y, int x, int width, chtype attr); +extern int gettxstr (WINDOW *win, wchar_t *restrict *restrict bufptr, + bool *restrict modified, bool multifield, + int y, int x, int width, chtype attr); /* @@ -656,7 +657,7 @@ extern int gettxstr (WINDOW *win, char **bufptr, bool *restrict modified, emptyval - Value to use for empty input defaultval - Value to use for default input y, x - Start of the input field (line, column) - width - Width of the input field + width - Width of the input field (column spaces) attr - Character rendition to use for input field Returns: int - Status code: OK, ERR or KEY_ keycode @@ -668,12 +669,11 @@ extern int gettxstr (WINDOW *win, char **bufptr, bool *restrict modified, result from gettxline() is passed back to the caller. Note that the low-level function gettxline() is called with multifield set to false. - This function is locale-aware, although multibyte strings are not - handled correctly. In particular, the default value is formatted using - strfmon() and uses the locale monetary default decimal places - (frac_digits). In addition, the user is allowed to use the locale's - radix character (decimal point) and the thousands separator, as well as - the monetary versions of these. + This function is locale-aware. In particular, the default value is + formatted using strfmon() and uses the locale monetary default decimal + places (frac_digits). In addition, the user is allowed to use the + locale's radix character (decimal point) and the thousands separator, + as well as the monetary versions of these. */ extern int gettxdouble (WINDOW *win, double *restrict result, double min, double max, double emptyval, double defaultval, @@ -696,9 +696,9 @@ extern int gettxdouble (WINDOW *win, double *restrict result, double min, This function behaves almost exactly like gettxdouble(), except that only integer numbers are allowed to be entered. - This function is locale-aware, although multibyte strings are not - handled correctly. In particular, the user is allowed to use the - locale's thousands separator and the monetary thousands separator. + This function is locale-aware. In particular, the user is allowed to + use the locale's thousands separator and the monetary thousands + separator. */ extern int gettxlong (WINDOW *win, long int *restrict result, long int min, long int max, long int emptyval, long int defaultval, @@ -710,10 +710,11 @@ extern int gettxlong (WINDOW *win, long int *restrict result, long int min, Parameters: win - Window to use (should be curwin) Returns: bool - True if Yes was selected, false if No - This function waits for the user to press either "Y" (for Yes) or "N" - (for No) on the keyboard, then prints the answer using A_BOLD. True is - returned if "Y" was selected, false if "N". Note that the cursor - becomes invisible after calling this function. + This function waits for the user to press either the locale-specific + equivalent of "Y" (for Yes) or "N" (for No) on the keyboard, then + prints the answer using A_BOLD. True is returned if "Y" was selected, + false if "N". Note that the cursor becomes invisible after calling + this function. */ extern bool answer_yesno (WINDOW *win); @@ -730,10 +731,6 @@ extern bool answer_yesno (WINDOW *win); The reason the user is not asked "Press any key to continue" is historical: many, many people used to ask "where is the key?" :-) - - The current implementation does not handle multibyte characters - correctly: only the first byte of the character is consumed, with - further bytes left in the keyboard queue. */ extern void wait_for_key (WINDOW *win, int y, chtype attr); diff --git a/src/move.c b/src/move.c index 8382773..81ee522 100644 --- a/src/move.c +++ b/src/move.c @@ -219,8 +219,8 @@ selection_t get_move (void) // Display current move choices on the galaxy map for (int i = 0; i < NUMBER_MOVES; i++) { - mvwaddch(curwin, game_move[i].y + 3, game_move[i].x * 2 + 2, - PRINTABLE_GAME_MOVE(i) | attr_map_choice); + mvwaddchstr(curwin, game_move[i].y + 3, game_move[i].x * 2 + 2, + CHTYPE_GAME_MOVE(i)); } wrefresh(curwin); @@ -242,7 +242,7 @@ selection_t get_move (void) right(curwin, 1, getmaxx(curwin) / 2, attr_normal, attr_keycode, attr_choice, 1, - _("Select move [^[%c^]-^[%c^]/^{1^}-^{3^}/^{^}]: "), + _("Select move [^[%lc^]-^[%lc^]/^{1^}-^{3^}/^{^}]: "), PRINTABLE_GAME_MOVE(0), PRINTABLE_GAME_MOVE(NUMBER_MOVES - 1)); curs_set(CURS_ON); @@ -250,60 +250,69 @@ selection_t get_move (void) // Get the actual selection made by the player while (selection == SEL_NONE) { - int i; - bool found; + wint_t key; - int key = gettxchar(curwin); + if (gettxchar(curwin, &key) == OK) { + // Ordinary wide character + int i; + bool found; - if (isupper(*keycode_game_move)) { - key = toupper(key); - } else if (islower(*keycode_game_move)) { - key = tolower(key); - } - - for (i = 0, found = false; keycode_game_move[i] != '\0'; i++) { - if (keycode_game_move[i] == key) { - found = true; - selection = i; - - curs_set(CURS_OFF); - left(curwin, 1, getmaxx(curwin) / 2, attr_normal, - attr_choice, 0, 1, - /* TRANSLATORS: "Move" refers to the choice of - moves made by the current player (out of a - selection of 20 moves). */ - _("Move ^{%c^}"), PRINTABLE_GAME_MOVE(i)); - - break; + if (iswupper(*keycode_game_move)) { + key = towupper(key); + } else if (iswlower(*keycode_game_move)) { + key = towlower(key); } - } - if (! found) { + for (i = 0, found = false; keycode_game_move[i] != '\0'; i++) { + if (keycode_game_move[i] == key) { + found = true; + selection = i; + + curs_set(CURS_OFF); + left(curwin, 1, getmaxx(curwin) / 2, attr_normal, + attr_choice, 0, 1, + /* TRANSLATORS: "Move" refers to the choice of + moves made by the current player (out of a + selection of 20 moves). */ + _("Move ^{%lc^}"), PRINTABLE_GAME_MOVE(i)); + + break; + } + } + + if (! found) { + switch (key) { + case '1': + curs_set(CURS_OFF); + show_status(current_player); + curs_set(CURS_ON); + break; + + case '2': + selection = SEL_BANKRUPT; + + curs_set(CURS_OFF); + left(curwin, 1, getmaxx(curwin) / 2, attr_normal, + attr_normal | A_BOLD, 0, 1, + _("^{<2>^} (Declare bankruptcy)")); + break; + + case '3': + selection = SEL_SAVE; + + curs_set(CURS_OFF); + left(curwin, 1, getmaxx(curwin) / 2, attr_normal, + attr_normal | A_BOLD, 0, 1, + _("^{<3>^} (Save and end the game)")); + break; + + default: + beep(); + } + } + } else { + // Function or control key switch (key) { - case '1': - curs_set(CURS_OFF); - show_status(current_player); - curs_set(CURS_ON); - break; - - case '2': - selection = SEL_BANKRUPT; - - curs_set(CURS_OFF); - left(curwin, 1, getmaxx(curwin) / 2, attr_normal, - attr_normal | A_BOLD, 0, 1, - _("^{<2>^} (Declare bankruptcy)")); - break; - - case '3': - selection = SEL_SAVE; - - curs_set(CURS_OFF); - left(curwin, 1, getmaxx(curwin) / 2, attr_normal, - attr_normal | A_BOLD, 0, 1, - _("^{<3>^} (Save and end the game)")); - break; - case KEY_ESC: case KEY_CANCEL: case KEY_EXIT: @@ -361,10 +370,10 @@ selection_t get_move (void) if (! saved) { // Ask which game to save - int key; bool done; int widthbuf[2]; int lines, maxwidth; + int choice; lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_keycode, 0, 2, WIN_COLS - 7, widthbuf, 2, @@ -383,12 +392,22 @@ selection_t get_move (void) done = false; while (! done) { - key = gettxchar(curwin); + wint_t key; - if (key >= '1' && key <= '9') { - wechochar(curwin, key | A_BOLD); - done = true; + if (gettxchar(curwin, &key) == OK) { + // Ordinary wide character + if (key >= '1' && key <= '9') { + left(curwin, getcury(curwin), getcurx(curwin), + A_BOLD, 0, 0, 1, "%lc", key); + wrefresh(curwin); + + choice = key - '0'; + done = true; + } else { + beep(); + } } else { + // Function or control key switch (key) { case KEY_ESC: case KEY_CANCEL: @@ -396,7 +415,7 @@ selection_t get_move (void) case KEY_CTRL('C'): case KEY_CTRL('G'): case KEY_CTRL('\\'): - key = KEY_CANCEL; + choice = ERR; done = true; break; @@ -408,9 +427,10 @@ selection_t get_move (void) curs_set(CURS_OFF); - if (key != KEY_CANCEL) { + if (choice != ERR) { // Try to save the game, if possible - game_num = key - '0'; + + game_num = choice; mkchstr(chbuf, BUFSIZE, attr_status_window, 0, 0, 1, WIN_COLS - 7, &width, 1, @@ -645,14 +665,14 @@ void bankrupt_player (bool forced) txdlgbox(MAX_DLG_LINES, 50, 7, WCENTER, attr_error_window, attr_error_title, attr_error_highlight, 0, 0, attr_error_waitforkey, _(" Bankruptcy Court "), - _("%s has been declared bankrupt " + _("%ls has been declared bankrupt " "by the Interstellar Trading Bank."), player[current_player].name); } else { txdlgbox(MAX_DLG_LINES, 50, 7, WCENTER, attr_error_window, attr_error_title, attr_error_highlight, 0, 0, attr_error_waitforkey, _(" Bankruptcy Court "), - _("%s has declared bankruptcy."), + _("%ls has declared bankruptcy."), player[current_player].name); } txrefresh(); @@ -721,7 +741,7 @@ void try_start_new_company (int x, int y) txdlgbox(MAX_DLG_LINES, 50, 7, WCENTER, attr_normal_window, attr_title, attr_normal, attr_highlight, 0, attr_waitforkey, _(" New Company "), - _("A new company has been formed!\nIts name is ^{%s^}."), + _("A new company has been formed!\nIts name is ^{%ls^}."), company[i].name); txrefresh(); @@ -777,7 +797,7 @@ void merge_companies (map_val_t a, map_val_t b) lines = mkchstr(chbuf, BUFSIZE, attr_normal, attr_highlight, 0, 4, WIN_COLS - 8, widthbuf, 4, - _("^{%s^} has just merged into ^{%s^}.\n" + _("^{%ls^} has just merged into ^{%ls^}.\n" "Please note the following transactions:\n"), company[bb].name, company[aa].name); @@ -787,11 +807,11 @@ void merge_companies (map_val_t a, map_val_t b) centerch(curwin, 3, 0, chbuf, lines, widthbuf); mkchstr(chbuf, BUFSIZE, attr_highlight, 0, 0, 1, getmaxx(curwin) / 2, - &width_aa, 1, "%s", company[aa].name); + &width_aa, 1, "%ls", company[aa].name); chbuf_aa = xchstrdup(chbuf); mkchstr(chbuf, BUFSIZE, attr_highlight, 0, 0, 1, getmaxx(curwin) / 2, - &width_bb, 1, "%s", company[bb].name); + &width_bb, 1, "%ls", company[bb].name); chbuf_bb = xchstrdup(chbuf); mkchstr(chbuf, BUFSIZE, attr_normal, 0, 0, 1, getmaxx(curwin) / 2, @@ -824,12 +844,11 @@ void merge_companies (map_val_t a, map_val_t b) pgettext("subtitle", "Player")); right(curwin, lines + 6, w - 4, attr_subtitle, 0, 0, 1, /* TRANSLATORS: "Bonus" refers to the bonus cash amount paid to - each player after two companies merge. %s is the currency + each player after two companies merge. %ls is the currency symbol in the current locale. The maximum column width is 12 characters INCLUDING the currency symbol (see MERGE_BONUS_COLS in src/intf.h). */ - pgettext("subtitle", "Bonus (%s)"), - lconvinfo.currency_symbol); + pgettext("subtitle", "Bonus (%ls)"), currency_symbol); right(curwin, lines + 6, w - 6 - MERGE_BONUS_COLS, attr_subtitle, 0, 0, 1, /* TRANSLATORS: "Total" refers to the total number of shares in the new company after a merger. The maximum column width is @@ -868,7 +887,7 @@ void merge_companies (map_val_t a, map_val_t b) mkchstr(chbuf, BUFSIZE, attr_normal, 0, 0, 1, w - 12 - MERGE_BONUS_COLS - MERGE_TOTAL_STOCK_COLS - MERGE_NEW_STOCK_COLS - MERGE_OLD_STOCK_COLS, - &width, 1, "%s", player[i].name); + &width, 1, "%ls", player[i].name); leftch(curwin, ln, 4, chbuf, 1, &width); right(curwin, ln, w - 4, attr_normal, 0, 0, 1, "%!N", bonus); @@ -994,7 +1013,7 @@ void adjust_values (void) attr_error_title, attr_error_highlight, attr_error_normal, 0, attr_error_waitforkey, _(" Bankruptcy Court "), - _("%s has been declared bankrupt " + _("%ls has been declared bankrupt " "by the Interstellar Trading Bank.\n\n" "^{All assets have been taken " "to repay outstanding loans.^}"), @@ -1016,7 +1035,7 @@ void adjust_values (void) lines = mkchstr(chbuf, BUFSIZE, attr_error_highlight, attr_error_normal, 0, 6, 60 - 4, widthbuf, 6, - _("%s has been declared bankrupt by the " + _("%ls has been declared bankrupt by the " "Interstellar Trading Bank.\n\n" "^{The Bank has agreed to pay stock holders ^}" "%.2f%%^{ of the share value on each share " From 485a867b998f8523e501e63ee90a5b6b07c38804 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Thu, 25 Aug 2011 14:09:48 +1000 Subject: [PATCH 088/112] Remove superfluous #include directives --- src/globals.h | 3 --- src/intf.h | 3 --- 2 files changed, 6 deletions(-) diff --git a/src/globals.h b/src/globals.h index e5f562c..53dc727 100644 --- a/src/globals.h +++ b/src/globals.h @@ -32,9 +32,6 @@ #define included_GLOBALS_H 1 -#include - - /************************************************************************ * Game constants * ************************************************************************/ diff --git a/src/intf.h b/src/intf.h index c22eeb3..f829a42 100644 --- a/src/intf.h +++ b/src/intf.h @@ -33,9 +33,6 @@ #define included_INTF_H 1 -#include "system.h" - - /************************************************************************ * Constants and type declarations * ************************************************************************/ From 4733e98e7f02cdf16fd1794c4529adc083d6a80f Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Thu, 25 Aug 2011 14:26:25 +1000 Subject: [PATCH 089/112] Change program_name() to be a global variable We're using global variables all over the place, in any case... --- src/trader.c | 21 +++++++++------------ src/utils.c | 44 ++++++++++++++++---------------------------- src/utils.h | 28 +++++++++------------------- 3 files changed, 34 insertions(+), 59 deletions(-) diff --git a/src/trader.c b/src/trader.c index 459f008..3d3c227 100644 --- a/src/trader.c +++ b/src/trader.c @@ -147,7 +147,7 @@ static void end_program (void); int main (int argc, char *argv[]) { // Strip off leading pathname components from program name - init_program_name(argv); + init_program_name(argv[0]); // Initialise the locale if (setlocale(LC_ALL, "") == NULL) { @@ -233,7 +233,7 @@ void process_cmdline (int argc, char *argv[]) if (option_max_turn < MIN_MAX_TURN || p == NULL || *p != '\0') { fprintf(stderr, _("%s: invalid value for --max-turn: `%s'\n"), - program_name(), optarg); + program_name, optarg); show_usage(EXIT_FAILURE); } } @@ -248,7 +248,7 @@ void process_cmdline (int argc, char *argv[]) if (optind < argc && argv[optind] != NULL) { if (*argv[optind] == '-') { - fprintf(stderr, _("%s: invalid operand `%s'\n"), program_name(), + fprintf(stderr, _("%s: invalid operand `%s'\n"), program_name, argv[optind]); show_usage(EXIT_FAILURE); } @@ -258,7 +258,7 @@ void process_cmdline (int argc, char *argv[]) game_num = *argv[optind] - '0'; } else { fprintf(stderr, _("%s: invalid game number `%s'\n"), - program_name(), argv[optind]); + program_name, argv[optind]); show_usage(EXIT_FAILURE); } @@ -266,8 +266,8 @@ void process_cmdline (int argc, char *argv[]) } if (optind < argc && argv[optind] != NULL) { - fprintf(stderr, _("%s: extra operand `%s'\n"), program_name(), - argv[optind]); + fprintf(stderr, _("%s: extra operand `%s'\n"), + program_name, argv[optind]); show_usage(EXIT_FAILURE); } } @@ -293,7 +293,7 @@ This program is free software that is distributed under the terms of the\n\ GNU General Public License, version 3 or later. You are welcome to\n\ modify and/or distribute it under certain conditions. This program has\n\ NO WARRANTY, to the extent permitted by law; see the License for details.\n\ -"), program_name(), PACKAGE_VERSION, "1990-2011"); +"), program_name, PACKAGE_VERSION, "1990-2011"); exit(EXIT_SUCCESS); } @@ -304,14 +304,11 @@ NO WARRANTY, to the extent permitted by law; see the License for details.\n\ void show_usage (int status) { - const char *pn = program_name(); - - if (status != EXIT_SUCCESS) { fprintf(stderr, _("%s: Try `%s --help' for more information.\n"), - pn, pn); + program_name, program_name); } else { - printf(_("Usage: %s [OPTION ...] [GAME]\n"), pn); + printf(_("Usage: %s [OPTION ...] [GAME]\n"), program_name); printf(_("\ Play Star Traders, a simple game of interstellar trading.\n\n\ ")); diff --git a/src/utils.c b/src/utils.c index 8c3e890..1558b73 100644 --- a/src/utils.c +++ b/src/utils.c @@ -35,6 +35,9 @@ * Global variable definitions * ************************************************************************/ +const char *program_name = NULL; // Canonical program name + + // Global copy, suitably modified, of localeconv() information struct lconv lconvinfo; @@ -64,7 +67,6 @@ wchar_t *mon_thousands_sep; // Local monetary thousands separator * Module-specific variables * ************************************************************************/ -static char *program_name_str = NULL; // Canonical program name static char *home_directory_str = NULL; // Full pathname to home static char *data_directory_str = NULL; // Writable data dir pathname @@ -79,40 +81,27 @@ static bool add_currency_symbol = false; // Do we need to add "$"? /***********************************************************************/ -// init_program_name: Make the program name "canonical" +// init_program_name: Make the program name canonical -void init_program_name (char *argv[]) +void init_program_name (char *argv0) { /* This implementation assumes a POSIX environment with an ASCII-safe character encoding (such as ASCII or UTF-8). */ - if (argv == NULL || argv[0] == NULL || *argv[0] == '\0') { - program_name_str = PACKAGE; + if (argv0 == NULL || *argv0 == '\0') { + program_name = PACKAGE; } else { - char *p = strrchr(argv[0], '/'); + char *p = strrchr(argv0, '/'); if (p != NULL && *++p != '\0') { - argv[0] = p; + program_name = xstrdup(p); + } else { + program_name = xstrdup(argv0); } - - program_name_str = argv[0]; } } -/***********************************************************************/ -// program_name: Return the canonical program name - -const char *program_name (void) -{ - if (program_name_str == NULL) { - init_program_name(NULL); - } - - return program_name_str; -} - - /***********************************************************************/ // home_directory: Return home directory pathname @@ -142,15 +131,14 @@ const char *data_directory (void) character encoding is ASCII-safe. */ if (data_directory_str == NULL) { - const char *name = program_name(); const char *home = home_directory(); - if (name != NULL && home != NULL) { - char *p = xmalloc(strlen(home) + strlen(name) + 3); + if (program_name != NULL && home != NULL) { + char *p = xmalloc(strlen(home) + strlen(program_name) + 3); strcpy(p, home); strcat(p, "/."); - strcat(p, name); + strcat(p, program_name); data_directory_str = p; } } @@ -208,7 +196,7 @@ void err_exit (const char *restrict format, ...) end_screen(); - fprintf(stderr, _("%s: "), program_name()); + fprintf(stderr, _("%s: "), program_name); va_start(args, format); vfprintf(stderr, format, args); va_end(args); @@ -229,7 +217,7 @@ void errno_exit (const char *restrict format, ...) end_screen(); - fprintf(stderr, _("%s: "), program_name()); + fprintf(stderr, _("%s: "), program_name); if (format != NULL) { va_start(args, format); vfprintf(stderr, format, args); diff --git a/src/utils.h b/src/utils.h index a30a108..adfcc8c 100644 --- a/src/utils.h +++ b/src/utils.h @@ -50,6 +50,9 @@ * Global variable declarations * ************************************************************************/ +extern const char *program_name; // Canonical program name + + // Global copy, suitably modified, of localeconv() information extern struct lconv lconvinfo; @@ -66,29 +69,16 @@ extern wchar_t *mon_thousands_sep; // Local monetary thousands separator ************************************************************************/ /* - Function: init_program_name - Make the program name "canonical" - Parameters: argv - Same as passed to main() + Function: init_program_name - Make the program name canonical + Parameters: argv0 - Same as passed to main() Returns: (nothing) - This function modifies the argv[0] pointer to eliminate any leading + This function modifies the argv0 pointer to eliminate any leading pathname (directory) components from the program name, leaving just the basename of the program. It also saves a copy that can be accessed via - the program_name() function. + the program_name global variable. */ -extern void init_program_name (char *argv[]); - - -/* - Function: program_name - Return the canonical program name - Parameters: (none) - Returns: const char * - Pointer to program name - - This function returns the canonical program name (the program name as - invoked on the command line, without any leading pathname components). - NULL should never be returned; however, init_program_name() SHOULD be - called before using this function. -*/ -extern const char *program_name (void); +extern void init_program_name (char *argv0); /* @@ -111,7 +101,7 @@ extern const char *home_directory (void); This function returns the full pathname to a potentially-writable subdirectory within the user's home directory. Essentially, this - function returns home_directory() + "/." + program_name(). Note that + function returns home_directory() + "/." + program_name. Note that this path is NOT created by this function, nor is the writability of this path checked. NULL is returned if this path cannot be determined. */ From 10815a2803f4907fc80bab0a7ef52ed4e63d51e7 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Thu, 25 Aug 2011 14:48:31 +1000 Subject: [PATCH 090/112] Move some global variables to intf.c and intf.h Move the keycode_company, printable_map_val, chtype_map_val, keycode_game_move, printable_game_move and chtype_game_move global variables to intf.c and intf.h. --- src/globals.c | 19 ++++++------------- src/globals.h | 19 ------------------- src/intf.c | 13 +++++++++++++ src/intf.h | 30 ++++++++++++++++++++++++++++++ 4 files changed, 49 insertions(+), 32 deletions(-) diff --git a/src/globals.c b/src/globals.c index f8fc0c9..bc251a5 100644 --- a/src/globals.c +++ b/src/globals.c @@ -41,8 +41,8 @@ const char *company_name[MAX_COMPANIES] = { /* TRANSLATORS: The eight company names do NOT have to be literal translations of the English names. In fact, if possible, the names should start with successive letters of your alphabet (in - English, "A" to "H"). No company name should be more than 24 - characters (column positions, to be precise) long. */ + English, for example, "A" to "H"). No company name should be more + than 24 characters (column positions, to be precise) long. */ N_("Altair Starways"), N_("Betelgeuse, Ltd"), N_("Capella Freight Co"), @@ -93,10 +93,10 @@ const char *default_printable_map_val = // Default printable output representations for each move const char *default_printable_game_move = /* TRANSLATORS: This string is used to display the game moves - (choices). There must be exactly 20 characters before the ASCII - vertical line. The first character corresponds to the first - character in the "input|GameMoves" string, and so on. Do not - change or translate anything after the vertical line. */ + (choices). There must be exactly 20 characters (NUMBER_MOVES) + before the ASCII vertical line. The first character corresponds + to the first character in the "input|GameMoves" string, and so on. + Do not change or translate anything after the vertical line. */ N_("abcdefghijklmnopqrst|output|GameMoves"); @@ -128,13 +128,6 @@ player_info_t player[MAX_PLAYERS]; // Array of players map_val_t galaxy_map[MAX_X][MAX_Y]; // Map of the galaxy move_rec_t game_move[NUMBER_MOVES]; // Current moves -wchar_t *keycode_company; // Keycodes for each company -wchar_t *keycode_game_move; // Keycodes for each game move -wchar_t *printable_map_val; // Printable output for each map value -wchar_t *printable_game_move; // Printable output for each game move -chtype *chtype_map_val[MAX_COMPANIES + 3]; // as chtype strings -chtype *chtype_game_move[NUMBER_MOVES]; // as chtype strings - int max_turn; // Max. number of turns in game int turn_number; // Current turn (1 to max_turn) int number_players; // Number of players diff --git a/src/globals.h b/src/globals.h index 53dc727..9d0c626 100644 --- a/src/globals.h +++ b/src/globals.h @@ -128,15 +128,6 @@ typedef enum map_val { #define MAP_TO_COMPANY(m) ((m) - MAP_A) #define IS_MAP_COMPANY(m) ((m) >= MAP_A && (m) <= MAP_LAST) -#define MAP_TO_INDEX(m) \ - (((m) == MAP_EMPTY) ? 0 : \ - (((m) == MAP_OUTPOST) ? 1 : \ - (((m) == MAP_STAR) ? 2 : \ - ((m) - MAP_A + 3)))) - -#define PRINTABLE_MAP_VAL(m) printable_map_val[MAP_TO_INDEX(m)] -#define CHTYPE_MAP_VAL(m) chtype_map_val[MAP_TO_INDEX(m)] - // Information about a move typedef struct move_rec { @@ -144,9 +135,6 @@ typedef struct move_rec { int y; } move_rec_t; -#define PRINTABLE_GAME_MOVE(m) (printable_game_move[m]) -#define CHTYPE_GAME_MOVE(m) (chtype_game_move[m]) - // Player moves / selection values typedef enum selection { @@ -195,13 +183,6 @@ extern player_info_t player[MAX_PLAYERS]; // Array of players extern map_val_t galaxy_map[MAX_X][MAX_Y]; // Map of the galaxy extern move_rec_t game_move[NUMBER_MOVES]; // Current moves -extern wchar_t *keycode_company; // Keycodes for each company -extern wchar_t *keycode_game_move; // Keycodes for each game move -extern wchar_t *printable_map_val; // Printable output for each map value -extern wchar_t *printable_game_move; // Printable output for each game move -extern chtype *chtype_map_val[MAX_COMPANIES + 3]; // as chtype strings -extern chtype *chtype_game_move[NUMBER_MOVES]; // as chtype strings - extern int max_turn; // Max. number of turns in game extern int turn_number; // Current turn (1 to max_turn) extern int number_players; // Number of players diff --git a/src/intf.c b/src/intf.c index 1ef3b0b..bbbc74d 100644 --- a/src/intf.c +++ b/src/intf.c @@ -179,6 +179,19 @@ chtype attr_error_highlight; // Error window highlighted string chtype attr_error_waitforkey; // "Press any key", error window +/************************************************************************ +* Game printing global variable definitions * +************************************************************************/ + +wchar_t *keycode_company; // Keycodes for each company +wchar_t *printable_map_val; // Printable output for each map value +chtype *chtype_map_val[MAX_COMPANIES + 3]; // as chtype strings + +wchar_t *keycode_game_move; // Keycodes for each game move +wchar_t *printable_game_move; // Printable output for each game move +chtype *chtype_game_move[NUMBER_MOVES]; // as chtype strings + + /************************************************************************ * Module-specific variables * ************************************************************************/ diff --git a/src/intf.h b/src/intf.h index f829a42..ede44af 100644 --- a/src/intf.h +++ b/src/intf.h @@ -169,6 +169,36 @@ extern chtype attr_error_highlight; // Error window highlighted string extern chtype attr_error_waitforkey; // "Press any key", error window +/************************************************************************ +* Game printing macros and global variable declarations * +************************************************************************/ + +// Macros and variables for printing the galaxy map + +#define MAP_TO_INDEX(m) \ + (((m) == MAP_EMPTY) ? 0 : \ + (((m) == MAP_OUTPOST) ? 1 : \ + (((m) == MAP_STAR) ? 2 : \ + ((m) - MAP_A + 3)))) + +#define PRINTABLE_MAP_VAL(m) printable_map_val[MAP_TO_INDEX(m)] +#define CHTYPE_MAP_VAL(m) chtype_map_val[MAP_TO_INDEX(m)] + +extern wchar_t *keycode_company; // Keycodes for each company +extern wchar_t *printable_map_val; // Printable output for each map value +extern chtype *chtype_map_val[MAX_COMPANIES + 3]; // as chtype strings + + +// Macros and variables for printing the current game moves + +#define PRINTABLE_GAME_MOVE(m) (printable_game_move[m]) +#define CHTYPE_GAME_MOVE(m) (chtype_game_move[m]) + +extern wchar_t *keycode_game_move; // Keycodes for each game move +extern wchar_t *printable_game_move; // Printable output for each game move +extern chtype *chtype_game_move[NUMBER_MOVES]; // as chtype strings + + /************************************************************************ * Basic text input/output function prototypes * ************************************************************************/ From 61411e3416a1c1447c85c8901ae1149ab30a1ef9 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Thu, 25 Aug 2011 14:49:51 +1000 Subject: [PATCH 091/112] Rearrange the order of constants, type declarations and macros --- src/intf.c | 112 ++++++++++++++++++++++++++--------------------------- 1 file changed, 56 insertions(+), 56 deletions(-) diff --git a/src/intf.c b/src/intf.c index bbbc74d..ededde7 100644 --- a/src/intf.c +++ b/src/intf.c @@ -31,6 +31,62 @@ #include "trader.h" +/************************************************************************ +* Global variable definitions * +************************************************************************/ + +WINDOW *curwin = NULL; // Top-most (current) window +bool use_color = true; // True to use colour + + +// Character renditions (attributes) used by Star Traders + +chtype attr_root_window; // Root window (behind all others) +chtype attr_game_title; // One-line game title at top + +chtype attr_normal_window; // Normal window background +chtype attr_title; // Normal window title +chtype attr_subtitle; // Normal window subtitle +chtype attr_normal; // Normal window text +chtype attr_highlight; // Normal window highlighted string +chtype attr_blink; // Blinking text in normal window +chtype attr_keycode; // Make keycodes like <1> stand out +chtype attr_choice; // Make map/company choices stand out +chtype attr_input_field; // Background for input text field +chtype attr_waitforkey; // "Press any key", normal window + +chtype attr_map_window; // Map window background +chtype attr_mapwin_title; // Map window title (player name, turn) +chtype attr_mapwin_highlight; // Map window title highlight +chtype attr_mapwin_blink; // Map window title blinking text +chtype attr_map_empty; // On map, empty space +chtype attr_map_outpost; // On map, outpost +chtype attr_map_star; // On map, star +chtype attr_map_company; // On map, company +chtype attr_map_choice; // On map, a choice of moves + +chtype attr_status_window; // Status window background + +chtype attr_error_window; // Error message window background +chtype attr_error_title; // Error window title +chtype attr_error_normal; // Error window ordinary text +chtype attr_error_highlight; // Error window highlighted string +chtype attr_error_waitforkey; // "Press any key", error window + + +/************************************************************************ +* Game printing global variable definitions * +************************************************************************/ + +wchar_t *keycode_company; // Keycodes for each company +wchar_t *printable_map_val; // Printable output for each map value +chtype *chtype_map_val[MAX_COMPANIES + 3]; // as chtype strings + +wchar_t *keycode_game_move; // Keycodes for each game move +wchar_t *printable_game_move; // Printable output for each game move +chtype *chtype_game_move[NUMBER_MOVES]; // as chtype strings + + /************************************************************************ * Module-specific constants, type declarations and macros * ************************************************************************/ @@ -136,62 +192,6 @@ struct convspec { }; -/************************************************************************ -* Global variable definitions * -************************************************************************/ - -WINDOW *curwin = NULL; // Top-most (current) window -bool use_color = true; // True to use colour - - -// Character renditions (attributes) used by Star Traders - -chtype attr_root_window; // Root window (behind all others) -chtype attr_game_title; // One-line game title at top - -chtype attr_normal_window; // Normal window background -chtype attr_title; // Normal window title -chtype attr_subtitle; // Normal window subtitle -chtype attr_normal; // Normal window text -chtype attr_highlight; // Normal window highlighted string -chtype attr_blink; // Blinking text in normal window -chtype attr_keycode; // Make keycodes like <1> stand out -chtype attr_choice; // Make map/company choices stand out -chtype attr_input_field; // Background for input text field -chtype attr_waitforkey; // "Press any key", normal window - -chtype attr_map_window; // Map window background -chtype attr_mapwin_title; // Map window title (player name, turn) -chtype attr_mapwin_highlight; // Map window title highlight -chtype attr_mapwin_blink; // Map window title blinking text -chtype attr_map_empty; // On map, empty space -chtype attr_map_outpost; // On map, outpost -chtype attr_map_star; // On map, star -chtype attr_map_company; // On map, company -chtype attr_map_choice; // On map, a choice of moves - -chtype attr_status_window; // Status window background - -chtype attr_error_window; // Error message window background -chtype attr_error_title; // Error window title -chtype attr_error_normal; // Error window ordinary text -chtype attr_error_highlight; // Error window highlighted string -chtype attr_error_waitforkey; // "Press any key", error window - - -/************************************************************************ -* Game printing global variable definitions * -************************************************************************/ - -wchar_t *keycode_company; // Keycodes for each company -wchar_t *printable_map_val; // Printable output for each map value -chtype *chtype_map_val[MAX_COMPANIES + 3]; // as chtype strings - -wchar_t *keycode_game_move; // Keycodes for each game move -wchar_t *printable_game_move; // Printable output for each game move -chtype *chtype_game_move[NUMBER_MOVES]; // as chtype strings - - /************************************************************************ * Module-specific variables * ************************************************************************/ From 1c2518a78b977c927a713560f68fd48f648ac453 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Thu, 25 Aug 2011 21:34:41 +1000 Subject: [PATCH 092/112] Minor clean-up: replace character constants with wide-char versions Wide-char character constants is not strictly needed for most (all?) modern C compilers, as ASCII maps to wchar_t directly (as long as __STDC_ISO_10646__ is defined). However, it doesn't hurt to be pedantic! --- src/exch.c | 40 ++++---- src/game.c | 13 ++- src/help.c | 115 +++++++++++----------- src/intf.c | 263 ++++++++++++++++++++++++++------------------------- src/intf.h | 6 +- src/move.c | 26 ++--- src/trader.c | 4 +- src/utils.c | 18 ++-- src/utils.h | 8 +- 9 files changed, 249 insertions(+), 244 deletions(-) diff --git a/src/exch.c b/src/exch.c index 71f51dc..3d4d43b 100644 --- a/src/exch.c +++ b/src/exch.c @@ -208,7 +208,7 @@ void exchange_stock (void) key = towlower(key); } - for (i = 0, found = false; keycode_company[i] != '\0'; i++) { + for (i = 0, found = false; keycode_company[i] != L'\0'; i++) { if (keycode_company[i] == key) { found = true; if (company[i].on_map) { @@ -222,24 +222,24 @@ void exchange_stock (void) if (! found) { switch (key) { - case '1': + case L'1': curs_set(CURS_OFF); show_status(current_player); curs_set(CURS_ON); break; - case '2': + case L'2': curs_set(CURS_OFF); show_map(true); curs_set(CURS_ON); break; - case '3': + case L'3': selection = SEL_BANK; break; - case '4': - case ' ': + case L'4': + case L' ': selection = SEL_EXIT; break; @@ -379,9 +379,9 @@ void visit_bank (void) if (gettxchar(curwin, &key) == OK) { // Ordinary wide character switch (key) { - case '1': - case '2': - case '3': + case L'1': + case L'2': + case L'3': left(curwin, getcury(curwin), getcurx(curwin), A_BOLD, 0, 0, 1, "%lc", key); wrefresh(curwin); @@ -389,7 +389,7 @@ void visit_bank (void) done = true; break; - case ' ': + case L' ': done = true; break; @@ -417,7 +417,7 @@ void visit_bank (void) curs_set(CURS_OFF); switch (key) { - case '1': + case L'1': // Borrow money from the Bank if (credit_limit == 0.0) { txdlgbox(MAX_DLG_LINES, 50, 8, WCENTER, attr_error_window, @@ -470,7 +470,7 @@ void visit_bank (void) } break; - case '2': + case L'2': // Repay a debt if (player[current_player].debt == 0.0) { txdlgbox(MAX_DLG_LINES, 50, 8, WCENTER, attr_error_window, @@ -664,10 +664,10 @@ void trade_shares (int num, bool *bid_used) if (gettxchar(curwin, &key) == OK) { // Ordinary wide character switch (key) { - case '1': - case '2': - case '3': - case '4': + case L'1': + case L'2': + case L'3': + case L'4': left(curwin, getcury(curwin), getcurx(curwin), A_BOLD, 0, 0, 1, "%lc", key); wrefresh(curwin); @@ -675,7 +675,7 @@ void trade_shares (int num, bool *bid_used) done = true; break; - case ' ': + case L' ': done = true; break; @@ -703,7 +703,7 @@ void trade_shares (int num, bool *bid_used) curs_set(CURS_OFF); switch (key) { - case '1': + case L'1': // Buy stock in company maxshares = player[current_player].cash / company[num].share_price; @@ -748,7 +748,7 @@ void trade_shares (int num, bool *bid_used) } break; - case '2': + case L'2': // Sell stock back to company maxshares = player[current_player].stock_owned[num]; if (maxshares == 0) { @@ -783,7 +783,7 @@ void trade_shares (int num, bool *bid_used) } break; - case '3': + case L'3': // Bid company to issue more shares maxshares = 0; if (! *bid_used && randf() < ownership && randf() < BID_CHANCE) { diff --git a/src/game.c b/src/game.c index 46f236d..3ee99bf 100644 --- a/src/game.c +++ b/src/game.c @@ -281,12 +281,12 @@ static int ask_number_players (void) if (gettxchar(curwin, &key) == OK) { // Ordinary wide character - if (key >= '1' && key <= MAX_PLAYERS + '0') { + if (key >= L'1' && key <= MAX_PLAYERS + L'0') { left(curwin, getcury(curwin), getcurx(curwin), A_BOLD, 0, 0, 1, "%lc", key); wrefresh(curwin); - ret = key - '0'; + ret = key - L'0'; done = true; } else if (wcschr(keycode_contgame, key) != NULL) { left(curwin, getcury(curwin), getcurx(curwin), A_BOLD, @@ -356,12 +356,12 @@ int ask_game_number (void) if (gettxchar(curwin, &key) == OK) { // Ordinary wide character - if (key >= '1' && key <= '9') { + if (key >= L'1' && key <= L'9') { left(curwin, getcury(curwin), getcurx(curwin), A_BOLD, 0, 0, 1, "%lc", key); wrefresh(curwin); - ret = key - '0'; + ret = key - L'0'; done = true; } else { beep(); @@ -574,8 +574,7 @@ void end_game (void) attr_title, attr_normal, attr_highlight, 0, attr_waitforkey, _(" Total Value "), /* xgettext:c-format */ - _("Your total value was ^{%N^}."), - total_value(0)); + _("Your total value was ^{%N^}."), total_value(0)); } else { // Sort players on the basis of total value for (int i = 0; i < number_players; i++) { @@ -655,7 +654,7 @@ void show_map (bool closewin) for (int x = 0; x < MAX_X; x++) { chtype *mapstr = CHTYPE_MAP_VAL(galaxy_map[x][y]); - while (*mapstr != '\0') { + while (*mapstr != 0) { waddch(curwin, *mapstr++); } } diff --git a/src/help.c b/src/help.c index 8893d97..e803441 100644 --- a/src/help.c +++ b/src/help.c @@ -61,7 +61,7 @@ static const char *help_text[HELP_TEXT_PAGES] = { ^^ - Print the circumflex accent (ASCII code U+005E) ^N - Switch to using the normal character rendition ^B - Switch to using the bold character rendition - ^B - Switch to using the highlight character rendition + ^H - Switch to using the highlight character rendition ^K - Switch to using the keycode character rendition (such as used for "") ^e - Switch to using the character rendition used for empty space ^o - Switch to using the character rendition used for outposts @@ -288,149 +288,150 @@ void show_help (void) memset(&mbstate, 0, sizeof(mbstate)); outp = outbuf; - while (*htxt != '\0' && count > maxchar * 2) { + while (*htxt != L'\0' && count > maxchar * 2) { switch (*htxt) { - case '\n': + case L'\n': // Start a new line *outp++ = '\n'; count--; break; - case '^': + case L'^': // Switch to a different character rendition switch (*++htxt) { - case '^': + case L'^': wcbuf[0] = *htxt; - wcbuf[1] = '\0'; + wcbuf[1] = L'\0'; goto addwcbuf; - case 'N': + case L'N': curattr = attr_normal; break; - case 'B': + case L'B': curattr = attr_normal | A_BOLD; break; - case 'H': + case L'H': curattr = attr_highlight; break; - case 'K': + case L'K': curattr = attr_keycode; break; - case 'e': + case L'e': curattr = attr_map_empty; break; - case 'o': + case L'o': curattr = attr_map_outpost; break; - case 's': + case L's': curattr = attr_map_star; break; - case 'c': + case L'c': curattr = attr_map_company; break; - case 'k': + case L'k': curattr = attr_map_choice; break; default: - wcbuf[0] = '^'; + wcbuf[0] = L'^'; wcbuf[1] = *htxt; - wcbuf[2] = '\0'; + wcbuf[2] = L'\0'; goto addwcbuf; } break; - case '~': + case L'~': // Print a global constant switch (*++htxt) { - case '~': + case L'~': wcbuf[0] = *htxt; - wcbuf[1] = '\0'; + wcbuf[1] = L'\0'; goto addwcbuf; - case 'x': + case L'x': swprintf(wcbuf, BIGBUFSIZE, L"%2d", MAX_X); goto addwcbuf; - case 'y': + case L'y': swprintf(wcbuf, BIGBUFSIZE, L"%2d", MAX_Y); goto addwcbuf; - case 'm': + case L'm': swprintf(wcbuf, BIGBUFSIZE, L"%2d", NUMBER_MOVES); goto addwcbuf; - case 'c': + case L'c': swprintf(wcbuf, BIGBUFSIZE, L"%d", MAX_COMPANIES); goto addwcbuf; - case 't': + case L't': swprintf(wcbuf, BIGBUFSIZE, L"%2d", DEFAULT_MAX_TURN); goto addwcbuf; - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': + case L'1': + case L'2': + case L'3': + case L'4': + case L'5': + case L'6': + case L'7': + case L'8': + case L'9': // N-th choice of move, as a key press wcbuf[0] = PRINTABLE_GAME_MOVE(*htxt - L'1'); - wcbuf[1] = '\0'; + wcbuf[1] = L'\0'; goto addwcbuf; - case 'M': + case L'M': // Last choice of move, as a key press wcbuf[0] = PRINTABLE_GAME_MOVE(NUMBER_MOVES - 1); - wcbuf[1] = '\0'; + wcbuf[1] = L'\0'; goto addwcbuf; - case '.': + case L'.': // Map representation of empty space wcbuf[0] = PRINTABLE_MAP_VAL(MAP_EMPTY); - wcbuf[1] = '\0'; + wcbuf[1] = L'\0'; goto addwcbuf; - case '+': + case L'+': // Map representation of an outpost wcbuf[0] = PRINTABLE_MAP_VAL(MAP_OUTPOST); - wcbuf[1] = '\0'; + wcbuf[1] = L'\0'; goto addwcbuf; - case '*': + case L'*': // Map representation of a star wcbuf[0] = PRINTABLE_MAP_VAL(MAP_STAR); - wcbuf[1] = '\0'; + wcbuf[1] = L'\0'; goto addwcbuf; - case 'A': - case 'B': - case 'C': - case 'D': - case 'E': - case 'F': - case 'G': - case 'H': + case L'A': + case L'B': + case L'C': + case L'D': + case L'E': + case L'F': + case L'G': + case L'H': // Map representation of company assert((*htxt - L'A') < MAX_COMPANIES); wcbuf[0] = PRINTABLE_MAP_VAL(COMPANY_TO_MAP(*htxt - L'A')); - wcbuf[1] = '\0'; + wcbuf[1] = L'\0'; goto addwcbuf; default: - wcbuf[0] = '~'; + wcbuf[0] = L'~'; wcbuf[1] = *htxt; + wcbuf[2] = L'\0'; goto addwcbuf; } break; @@ -438,10 +439,10 @@ void show_help (void) default: // Print the character wcbuf[0] = *htxt; - wcbuf[1] = '\0'; + wcbuf[1] = L'\0'; addwcbuf: - for (wchar_t *p = wcbuf; *p != '\0' && count > maxchar * 2; p++) { + for (wchar_t *p = wcbuf; *p != L'\0' && count > maxchar * 2; p++) { n = xwcrtomb(convbuf, *p, &mbstate); for (i = 0, cp = convbuf; i < n; i++, cp++, outp++, count--) { *outp = (unsigned char) *cp | curattr; @@ -453,14 +454,14 @@ void show_help (void) } // Add the terminating NUL (possibly with a preceding shift sequence) - n = xwcrtomb(convbuf, '\0', &mbstate); + n = xwcrtomb(convbuf, L'\0', &mbstate); for (i = 0, cp = convbuf; i < n; i++, cp++, outp++, count--) { *outp = (unsigned char) *cp; } assert(count >= 0); // Display the formatted text in outbuf - for (outp = outbuf; *outp != '\0'; outp++) { + for (outp = outbuf; *outp != 0; outp++) { if (*outp == '\n') { wmove(curwin, getcury(curwin) + 1, 2); } else { diff --git a/src/intf.c b/src/intf.c index ededde7..bd50c97 100644 --- a/src/intf.c +++ b/src/intf.c @@ -111,7 +111,7 @@ typedef struct txwin { __stringify(_var), s); \ } \ (_var) = xwcsdup(buf); \ - (_var)[_checkpos] = '\0'; \ + (_var)[_checkpos] = L'\0'; \ } while (0) #define init_game_chstr(_chvar, _var, _attr, _err) \ @@ -134,13 +134,13 @@ typedef struct txwin { } \ \ if (w == 1) { \ - n = xwcrtomb(convbuf, ' ', &mbstate); \ + n = xwcrtomb(convbuf, L' ', &mbstate); \ for (int i = 0; i < n; i++) { \ *p++ = (unsigned char) convbuf[i] | attr_map_empty; \ } \ } \ \ - n = xwcrtomb(convbuf, '\0', &mbstate); \ + n = xwcrtomb(convbuf, L'\0', &mbstate); \ for (int i = 0; i < n; i++) { \ *p++ = (unsigned char) convbuf[i]; \ } \ @@ -326,52 +326,52 @@ static int getwch (WINDOW *win, wint_t *wch); /* - Function: cpos_endl - Adjust cpos and st for printing the ending part of buf - Parameters: buf - Pointer to current editing buffer - cpos - Pointer to current cursor position (result) - st - Pointer to current starting offset for buf[] (result) - clen - Current column width of entire string - width - Width of editing field in column spaces - len - Length of string being edited (wchar_t elements) + Function: cpos_end - Adjust cpos and st for printing the ending part of buf + Parameters: buf - Pointer to current editing buffer + cpos - Pointer to current cursor position (result) + st - Pointer to current starting offset for buf[] (result) + clen - Current column width of entire string + width - Width of editing field in column spaces + len - Length of string being edited (wchar_t elements) Returns: (nothing) This helper function adjusts *cpos and *st so that the cursor is placed at the end of the current editing buffer buf[]. */ -static void cpos_endl (wchar_t *restrict buf, int *restrict cpos, - int *restrict st, int clen, int width, int len); +static void cpos_end (const wchar_t *restrict buf, int *restrict cpos, + int *restrict st, int clen, int width, int len); /* - Function: cpos_decr - Adjust cpos and st: scroll to the left by w columns - Parameters: buf - Pointer to current editing buffer - cpos - Pointer to current cursor position (result) - st - Pointer to current starting offset for buf[] (result) - w - Number of columns to scroll left - width - Width of editing field in column spaces + Function: cpos_dec - Adjust cpos and st: scroll to the left by w columns + Parameters: buf - Pointer to current editing buffer + cpos - Pointer to current cursor position (result) + st - Pointer to current starting offset for buf[] (result) + w - Number of columns to scroll left + width - Width of editing field in column spaces Returns: (nothing) This helper function adjusts *cpos and *st so that the cursor is moved to the left by w column positions. */ -static void cpos_decr (wchar_t *restrict buf, int *restrict cpos, - int *restrict st, int w, int width); +static void cpos_dec (const wchar_t *restrict buf, int *restrict cpos, + int *restrict st, int w, int width); /* - Function: cpos_incr - Adjust cpos and st: scroll to the right by w columns - Parameters: buf - Pointer to current editing buffer - cpos - Pointer to current cursor position (result) - st - Pointer to current starting offset for buf[] (result) - w - Number of columns to scroll right - width - Width of editing field in column spaces + Function: cpos_inc - Adjust cpos and st: scroll to the right by w columns + Parameters: buf - Pointer to current editing buffer + cpos - Pointer to current cursor position (result) + st - Pointer to current starting offset for buf[] (result) + w - Number of columns to scroll right + width - Width of editing field in column spaces Returns: (nothing) This helper function adjusts *cpos and *st so that the cursor is moved to the right by w column positions. */ -static void cpos_incr (wchar_t *restrict buf, int *restrict cpos, - int *restrict st, int w, int width); +static void cpos_inc (const wchar_t *restrict buf, int *restrict cpos, + int *restrict st, int w, int width); /* @@ -389,7 +389,7 @@ static void cpos_incr (wchar_t *restrict buf, int *restrict cpos, This function is used by gettxdouble() and gettxlong() to share some common code. */ -static void txinput_fixup (wchar_t *restrict dest, wchar_t *restrict src, +static void txinput_fixup (wchar_t *restrict dest, const wchar_t *restrict src, bool isfloat); @@ -864,11 +864,11 @@ int mkchstr_parse (const wchar_t *restrict format, memset(format_arg, 0, MAXFMTARGS * sizeof(format_arg[0])); memset(format_spec, 0, MAXFMTSPECS * sizeof(format_spec[0])); - while (*format != '\0') { + while (*format != L'\0') { switch (*format++) { - case '^': + case L'^': // Switch to a different character rendition - if (*format == '\0') { + if (*format == L'\0') { errno = EINVAL; return -1; } else { @@ -877,13 +877,13 @@ int mkchstr_parse (const wchar_t *restrict format, } break; - case '%': + case L'%': // Process a conversion specifier - if (*format == '\0') { + if (*format == L'\0') { errno = EINVAL; return -1; - } else if (*format == '%') { - // Ignore "%%" specifier + } else if (*format == L'%') { + // Ignore "%%" specifier for now format++; } else { const wchar_t *start = format; @@ -893,10 +893,10 @@ int mkchstr_parse (const wchar_t *restrict format, bool flag_other = false; // Have we seen something else? int count = 0; - while (inspec && *format != '\0') { - wchar_t wc = *format++; - switch (wc) { - case '0': + while (inspec && *format != L'\0') { + wchar_t c = *format++; + switch (c) { + case L'0': // Zero flag, or part of numeric count if (count == 0) { // Zero flag is NOT supported @@ -907,20 +907,20 @@ int mkchstr_parse (const wchar_t *restrict format, count *= 10; break; - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': + case L'1': + case L'2': + case L'3': + case L'4': + case L'5': + case L'6': + case L'7': + case L'8': + case L'9': // Part of some numeric count - count = count * 10 + (wc - L'0'); + count = count * 10 + (c - L'0'); break; - case '$': + case L'$': // Fixed-position argument if (flag_posn || flag_other || count == 0) { errno = EINVAL; @@ -937,7 +937,7 @@ int mkchstr_parse (const wchar_t *restrict format, count = 0; break; - case '\'': + case L'\'': // Use locale-specific thousands group separator if (format_spec->flag_group) { errno = EINVAL; @@ -948,7 +948,7 @@ int mkchstr_parse (const wchar_t *restrict format, flag_other = true; break; - case '!': + case L'!': // Omit the locale-specific currency symbol if (format_spec->flag_nosym) { errno = EINVAL; @@ -959,7 +959,7 @@ int mkchstr_parse (const wchar_t *restrict format, flag_other = true; break; - case '.': + case L'.': // Precision flag if (format_spec->flag_prec || count != 0) { errno = EINVAL; @@ -970,7 +970,7 @@ int mkchstr_parse (const wchar_t *restrict format, flag_other = true; break; - case 'l': + case L'l': // Long length modifier if (format_spec->flag_long) { // "ll" is NOT supported @@ -982,7 +982,7 @@ int mkchstr_parse (const wchar_t *restrict format, flag_other = true; break; - case 'c': + case L'c': // Insert a character (char or wchar_t) if (format_spec->flag_group || format_spec->flag_nosym || format_spec->flag_prec || count != 0) { @@ -994,7 +994,7 @@ int mkchstr_parse (const wchar_t *restrict format, TYPE_WCHAR : TYPE_CHAR; goto handlefmt; - case 'd': + case L'd': // Insert an integer (int or long int) if (format_spec->flag_nosym || format_spec->flag_prec || count != 0) { @@ -1006,7 +1006,7 @@ int mkchstr_parse (const wchar_t *restrict format, TYPE_LONGINT : TYPE_INT; goto handlefmt; - case 'f': + case L'f': // Insert a floating-point number (double) if (format_spec->flag_nosym || format_spec->flag_long || (! format_spec->flag_prec && count != 0)) { @@ -1019,7 +1019,7 @@ int mkchstr_parse (const wchar_t *restrict format, arg_type = TYPE_DOUBLE; goto handlefmt; - case 'N': + case L'N': // Insert a monetary amount (double) if (format_spec->flag_group || format_spec->flag_prec || format_spec->flag_long || count != 0) { @@ -1030,7 +1030,7 @@ int mkchstr_parse (const wchar_t *restrict format, arg_type = TYPE_DOUBLE; goto handlefmt; - case 's': + case L's': // Insert a string (const char * or const wchar_t *) if (format_spec->flag_group || format_spec->flag_nosym || format_spec->flag_prec || count != 0) { @@ -1056,7 +1056,7 @@ int mkchstr_parse (const wchar_t *restrict format, format_spec->len = format - start; format_spec->arg_num = arg_num; - format_spec->spec = wc; + format_spec->spec = c; arg_num++; num_args = MAX(num_args, arg_num); @@ -1147,11 +1147,11 @@ int mkchstr_add (wchar_t *restrict *restrict outbuf, *line = 0; } - if (**str == '\n') { + if (**str == L'\n') { // Start a new line if (*line < maxlines - 1) { - *(*outbuf)++ = '\n'; + *(*outbuf)++ = L'\n'; *(*attrbuf)++ = 0; (*count)--; } @@ -1180,7 +1180,7 @@ int mkchstr_add (wchar_t *restrict *restrict outbuf, // Break on the last space in this line wspc = wcwidth(**lastspc); - **lastspc = '\n'; + **lastspc = L'\n'; **spcattr = 0; widthbuf[*line] = *widthspc; @@ -1194,7 +1194,7 @@ int mkchstr_add (wchar_t *restrict *restrict outbuf, } else { // Insert a new-line character (if not on last line) if (*line < maxlines - 1) { - *(*outbuf)++ = '\n'; + *(*outbuf)++ = L'\n'; *(*attrbuf)++ = 0; (*count)--; } @@ -1212,7 +1212,7 @@ int mkchstr_add (wchar_t *restrict *restrict outbuf, will ever have combining diacritical marks following a (line-breaking) space! */ while (iswspace(**str)) { - if (*(*str)++ == '\n') { + if (*(*str)++ == L'\n') { break; } } @@ -1257,7 +1257,7 @@ void mkchstr_conv (chtype *restrict chbuf, int chbufsize, while (! done) { // Make sure we always have enough space for ending shift sequence memcpy(&mbcopy, &mbstate, sizeof(mbstate)); - endsize = wcrtomb(endbuf, '\0', &mbcopy); + endsize = wcrtomb(endbuf, L'\0', &mbcopy); if (endsize == (size_t) -1) { errno_exit(_("mkchstr_conv: NUL")); } @@ -1285,7 +1285,7 @@ void mkchstr_conv (chtype *restrict chbuf, int chbufsize, break; } - done = (*wcbuf == '\0'); + done = (*wcbuf == L'\0'); wcbuf++; attrbuf++; } @@ -1352,15 +1352,15 @@ int vmkchstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, spcattr = NULL; // Equivalent in attrbuf widthspc = 0; // Width of line before last space - while (*wcformat != '\0' && count > 1 && line < maxlines) { + while (*wcformat != L'\0' && count > 1 && line < maxlines) { switch (*wcformat) { - case '^': + case L'^': // Switch to a different character rendition - if (*++wcformat == '\0') { + if (*++wcformat == L'\0') { goto error_inval; } else { switch (*wcformat) { - case '^': + case L'^': if (mkchstr_add(&outbuf, &attrbuf, &count, curattr, maxlines, maxwidth, &line, &width, &lastspc, &spcattr, &widthspc, widthbuf, @@ -1369,18 +1369,18 @@ int vmkchstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, } break; - case '{': + case L'{': curattr = attr_alt1; wcformat++; break; - case '[': + case L'[': curattr = attr_alt2; wcformat++; break; - case '}': - case ']': + case L'}': + case L']': curattr = attr_norm; wcformat++; break; @@ -1391,11 +1391,11 @@ int vmkchstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, } break; - case '%': + case L'%': // Process a conversion specifier - if (*++wcformat == '\0') { + if (*++wcformat == L'\0') { goto error_inval; - } else if (*wcformat == '%') { + } else if (*wcformat == L'%') { if (mkchstr_add(&outbuf, &attrbuf, &count, curattr, maxlines, maxwidth, &line, &width, &lastspc, &spcattr, &widthspc, widthbuf, widthbufsize, &wcformat) @@ -1408,7 +1408,7 @@ int vmkchstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, wint_t wc; switch (spec->spec) { - case 'c': + case L'c': // Insert a character (char or wchar_t) into the output if (spec->flag_long) { wc = format_arg[spec->arg_num].a.a_wchar; @@ -1416,17 +1416,17 @@ int vmkchstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, wc = btowc(format_arg[spec->arg_num].a.a_char); } - if (wc == '\0' || wc == WEOF) { + if (wc == L'\0' || wc == WEOF) { wc = EILSEQ_REPL_WC; } fmtbuf[0] = wc; - fmtbuf[1] = '\0'; + fmtbuf[1] = L'\0'; str = fmtbuf; goto insertstr; - case 'd': + case L'd': // Insert an integer (int or long int) into the output if (spec->flag_long) { if (swprintf(fmtbuf, BUFSIZE, spec->flag_group ? @@ -1443,7 +1443,7 @@ int vmkchstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, str = fmtbuf; goto insertstr; - case 'f': + case L'f': // Insert a floating-point number (double) into the output if (spec->flag_prec) { if (swprintf(fmtbuf, BUFSIZE, spec->flag_group ? @@ -1460,7 +1460,7 @@ int vmkchstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, str = fmtbuf; goto insertstr; - case 'N': + case L'N': // Insert a monetary amount (double) into the output { /* strfmon() is not available in a wide-char @@ -1482,7 +1482,7 @@ int vmkchstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, str = fmtbuf; goto insertstr; - case 's': + case L's': // Insert a string (const char * or const wchar_t *) if (spec->flag_long) { str = format_arg[spec->arg_num].a.a_wstring; @@ -1502,7 +1502,7 @@ int vmkchstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, insertstr: // Insert the string pointed to by str - while (*str != '\0' && count > 1 && line < maxlines) { + while (*str != L'\0' && count > 1 && line < maxlines) { if (mkchstr_add(&outbuf, &attrbuf, &count, curattr, maxlines, maxwidth, &line, &width, &lastspc, &spcattr, &widthspc, @@ -1531,7 +1531,7 @@ int vmkchstr (chtype *restrict chbuf, int chbufsize, chtype attr_norm, } } - *outbuf = '\0'; // Terminating NUL character + *outbuf = L'\0'; // Terminating NUL character *attrbuf = 0; if (line >= 0 && line < maxlines) { @@ -1578,7 +1578,7 @@ int leftch (WINDOW *win, int y, int x, const chtype *restrict chstr, assert(widthbuf != NULL); wmove(win, y, x); - for ( ; *chstr != '\0'; chstr++) { + for ( ; *chstr != 0; chstr++) { if (*chstr == '\n') { wmove(win, getcury(win) + 1, x); } else { @@ -1605,7 +1605,7 @@ int centerch (WINDOW *win, int y, int offset, const chtype *restrict chstr, assert(widthbuf != NULL); wmove(win, y, (getmaxx(win) - widthbuf[ln]) / 2 + offset); - for ( ; *chstr != '\0'; chstr++) { + for ( ; *chstr != 0; chstr++) { if (*chstr == '\n') { if (ln++ >= lines) { return ERR; @@ -1637,7 +1637,7 @@ int rightch (WINDOW *win, int y, int x, const chtype *restrict chstr, assert(widthbuf != NULL); wmove(win, y, x - widthbuf[ln]); - for ( ; *chstr != '\0'; chstr++) { + for ( ; *chstr != 0; chstr++) { if (*chstr == '\n') { if (ln++ >= lines) { return ERR; @@ -1828,10 +1828,10 @@ int gettxchar (WINDOW *win, wint_t *wch) /***********************************************************************/ -// cpos_endl: Adjust cpos and st for printing the ending part of buf +// cpos_end: Adjust cpos and st for printing the ending part of buf -void cpos_endl (wchar_t *restrict buf, int *restrict cpos, int *restrict st, - int clen, int width, int len) +void cpos_end (const wchar_t *restrict buf, int *restrict cpos, + int *restrict st, int clen, int width, int len) { *cpos = MIN(clen, width - 1); @@ -1862,10 +1862,10 @@ void cpos_endl (wchar_t *restrict buf, int *restrict cpos, int *restrict st, /***********************************************************************/ -// cpos_decr: Adjust cpos and st: scroll to the left by w columns +// cpos_dec: Adjust cpos and st: scroll to the left by w columns -void cpos_decr (wchar_t *restrict buf, int *restrict cpos, int *restrict st, - int w, int width) +void cpos_dec (const wchar_t *restrict buf, int *restrict cpos, + int *restrict st, int w, int width) { if (*cpos > 0) { // Cursor position is not yet in first column @@ -1886,10 +1886,10 @@ void cpos_decr (wchar_t *restrict buf, int *restrict cpos, int *restrict st, /***********************************************************************/ -// cpos_incr: Adjust cpos and st: scroll to the right by w columns +// cpos_inc: Adjust cpos and st: scroll to the right by w columns -void cpos_incr (wchar_t *restrict buf, int *restrict cpos, int *restrict st, - int w, int width) +void cpos_inc (const wchar_t *restrict buf, int *restrict cpos, + int *restrict st, int w, int width) { if (*cpos + w <= width - 1) { // Cursor position is not yet in second-last column @@ -1953,7 +1953,7 @@ int gettxline (WINDOW *win, wchar_t *restrict buf, int bufsize, } // Find the point from which buf should be displayed to screen - cpos_endl(buf, &cpos, &st, clen, width, len); + cpos_end(buf, &cpos, &st, clen, width, len); redraw = true; done = false; @@ -1996,7 +1996,7 @@ int gettxline (WINDOW *win, wchar_t *restrict buf, int bufsize, buf); } - cpos_endl(buf, &cpos, &st, clen, width, len); + cpos_end(buf, &cpos, &st, clen, width, len); mod = true; redraw = true; @@ -2020,7 +2020,7 @@ int gettxline (WINDOW *win, wchar_t *restrict buf, int bufsize, pos++; clen += w; - cpos_incr(buf, &cpos, &st, w, width); + cpos_inc(buf, &cpos, &st, w, width); mod = true; redraw = true; @@ -2113,7 +2113,7 @@ int gettxline (WINDOW *win, wchar_t *restrict buf, int bufsize, beep(); } else { pos--; - cpos_decr(buf, &cpos, &st, wcwidth(buf[pos]), width); + cpos_dec(buf, &cpos, &st, wcwidth(buf[pos]), width); redraw = true; } break; @@ -2125,7 +2125,7 @@ int gettxline (WINDOW *win, wchar_t *restrict buf, int bufsize, beep(); } else { pos++; - cpos_incr(buf, &cpos, &st, wcwidth(buf[pos - 1]), width); + cpos_inc(buf, &cpos, &st, wcwidth(buf[pos - 1]), width); redraw = true; } break; @@ -2143,7 +2143,7 @@ int gettxline (WINDOW *win, wchar_t *restrict buf, int bufsize, case KEY_CTRL('E'): // Move cursor to end of string pos = len; - cpos_endl(buf, &cpos, &st, clen, width, len); + cpos_end(buf, &cpos, &st, clen, width, len); redraw = true; break; @@ -2151,7 +2151,7 @@ int gettxline (WINDOW *win, wchar_t *restrict buf, int bufsize, // Move cursor to start of current or previous word while (pos > 0 && ! iswalnum(buf[pos - 1])) { pos--; - cpos_decr(buf, &cpos, &st, wcwidth(buf[pos]), width); + cpos_dec(buf, &cpos, &st, wcwidth(buf[pos]), width); } while (pos > 0 && (iswalnum(buf[pos - 1]) || (pos > 1 && wcwidth(buf[pos - 1]) == 0 @@ -2159,7 +2159,7 @@ int gettxline (WINDOW *win, wchar_t *restrict buf, int bufsize, /* Treat zero-width characters preceded by an alphanumeric character as alphanumeric. */ pos--; - cpos_decr(buf, &cpos, &st, wcwidth(buf[pos]), width); + cpos_dec(buf, &cpos, &st, wcwidth(buf[pos]), width); } redraw = true; break; @@ -2168,14 +2168,14 @@ int gettxline (WINDOW *win, wchar_t *restrict buf, int bufsize, // Move cursor to end of current or next word while (pos < len && ! iswalnum(buf[pos])) { pos++; - cpos_incr(buf, &cpos, &st, wcwidth(buf[pos - 1]), width); + cpos_inc(buf, &cpos, &st, wcwidth(buf[pos - 1]), width); } while (pos < len && (iswalnum(buf[pos]) || wcwidth(buf[pos]) == 0)) { /* Treat zero-width characters following an alphanumeric character as alphanumeric. */ pos++; - cpos_incr(buf, &cpos, &st, wcwidth(buf[pos - 1]), width); + cpos_inc(buf, &cpos, &st, wcwidth(buf[pos - 1]), width); } redraw = true; break; @@ -2194,7 +2194,7 @@ int gettxline (WINDOW *win, wchar_t *restrict buf, int bufsize, len--; pos--; clen -= w; - cpos_decr(buf, &cpos, &st, w, width); + cpos_dec(buf, &cpos, &st, w, width); mod = true; redraw = true; } @@ -2282,13 +2282,13 @@ int gettxline (WINDOW *win, wchar_t *restrict buf, int bufsize, i--; int w = wcwidth(buf[i]); ww += w; - cpos_decr(buf, &cpos, &st, w, width); + cpos_dec(buf, &cpos, &st, w, width); } while (i > 0 && ! iswspace(buf[i - 1])) { i--; int w = wcwidth(buf[i]); ww += w; - cpos_decr(buf, &cpos, &st, w, width); + cpos_dec(buf, &cpos, &st, w, width); } wmemmove(buf + i, buf + pos, len - pos + 1); @@ -2320,7 +2320,7 @@ int gettxline (WINDOW *win, wchar_t *restrict buf, int bufsize, buf[pos - 1] = c; pos++; - cpos_incr(buf, &cpos, &st, w, width); + cpos_inc(buf, &cpos, &st, w, width); mod = true; redraw = true; @@ -2358,7 +2358,7 @@ int gettxline (WINDOW *win, wchar_t *restrict buf, int bufsize, // Move cursor to start of current or previous word while (pos > 0 && ! iswalnum(buf[pos - 1])) { pos--; - cpos_decr(buf, &cpos, &st, wcwidth(buf[pos]), + cpos_dec(buf, &cpos, &st, wcwidth(buf[pos]), width); } while (pos > 0 && (iswalnum(buf[pos - 1]) @@ -2368,7 +2368,7 @@ int gettxline (WINDOW *win, wchar_t *restrict buf, int bufsize, /* Treat zero-width characters preceded by an alphanumeric character as alphanumeric. */ pos--; - cpos_decr(buf, &cpos, &st, wcwidth(buf[pos]), + cpos_dec(buf, &cpos, &st, wcwidth(buf[pos]), width); } redraw = true; @@ -2379,7 +2379,7 @@ int gettxline (WINDOW *win, wchar_t *restrict buf, int bufsize, // Move cursor to end of current or next word while (pos < len && ! iswalnum(buf[pos])) { pos++; - cpos_incr(buf, &cpos, &st, + cpos_inc(buf, &cpos, &st, wcwidth(buf[pos - 1]), width); } while (pos < len @@ -2388,7 +2388,7 @@ int gettxline (WINDOW *win, wchar_t *restrict buf, int bufsize, /* Treat zero-width characters following an alphanumeric character as alphanumeric. */ pos++; - cpos_incr(buf, &cpos, &st, + cpos_inc(buf, &cpos, &st, wcwidth(buf[pos - 1]), width); } redraw = true; @@ -2436,7 +2436,7 @@ int gettxline (WINDOW *win, wchar_t *restrict buf, int bufsize, pos--; int w = wcwidth(buf[pos]); ww += w; - cpos_decr(buf, &cpos, &st, w, width); + cpos_dec(buf, &cpos, &st, w, width); } while (i < len && iswspace(buf[i])) { i++; @@ -2461,7 +2461,7 @@ int gettxline (WINDOW *win, wchar_t *restrict buf, int bufsize, int w = wcwidth(c); clen += w; - cpos_incr(buf, &cpos, &st, w, width); + cpos_inc(buf, &cpos, &st, w, width); } } @@ -2477,7 +2477,7 @@ int gettxline (WINDOW *win, wchar_t *restrict buf, int bufsize, // Convert word (from cursor onwards) to upper case while (pos < len && ! iswalnum(buf[pos])) { pos++; - cpos_incr(buf, &cpos, &st, + cpos_inc(buf, &cpos, &st, wcwidth(buf[pos - 1]), width); } while (pos < len @@ -2485,7 +2485,7 @@ int gettxline (WINDOW *win, wchar_t *restrict buf, int bufsize, || wcwidth(buf[pos]) == 0)) { buf[pos] = towupper(buf[pos]); pos++; - cpos_incr(buf, &cpos, &st, + cpos_inc(buf, &cpos, &st, wcwidth(buf[pos - 1]), width); } mod = true; @@ -2497,7 +2497,7 @@ int gettxline (WINDOW *win, wchar_t *restrict buf, int bufsize, // Convert word (from cursor onwards) to lower case while (pos < len && ! iswalnum(buf[pos])) { pos++; - cpos_incr(buf, &cpos, &st, + cpos_inc(buf, &cpos, &st, wcwidth(buf[pos - 1]), width); } while (pos < len @@ -2505,7 +2505,7 @@ int gettxline (WINDOW *win, wchar_t *restrict buf, int bufsize, || wcwidth(buf[pos]) == 0)) { buf[pos] = towlower(buf[pos]); pos++; - cpos_incr(buf, &cpos, &st, + cpos_inc(buf, &cpos, &st, wcwidth(buf[pos - 1]), width); } mod = true; @@ -2520,7 +2520,7 @@ int gettxline (WINDOW *win, wchar_t *restrict buf, int bufsize, bool first = true; while (pos < len && ! iswalnum(buf[pos])) { pos++; - cpos_incr(buf, &cpos, &st, + cpos_inc(buf, &cpos, &st, wcwidth(buf[pos - 1]), width); } while (pos < len @@ -2533,7 +2533,7 @@ int gettxline (WINDOW *win, wchar_t *restrict buf, int bufsize, buf[pos] = towlower(buf[pos]); } pos++; - cpos_incr(buf, &cpos, &st, + cpos_inc(buf, &cpos, &st, wcwidth(buf[pos - 1]), width); } mod = true; @@ -2564,7 +2564,7 @@ int gettxline (WINDOW *win, wchar_t *restrict buf, int bufsize, i--; int w = wcwidth(buf[i]); ww += w; - cpos_decr(buf, &cpos, &st, w, width); + cpos_dec(buf, &cpos, &st, w, width); } while (i > 0 && (iswalnum(buf[i - 1]) @@ -2575,7 +2575,7 @@ int gettxline (WINDOW *win, wchar_t *restrict buf, int bufsize, i--; int w = wcwidth(buf[i]); ww += w; - cpos_decr(buf, &cpos, &st, w, width); + cpos_dec(buf, &cpos, &st, w, width); } wmemmove(buf + i, buf + pos, len - pos + 1); @@ -2654,7 +2654,7 @@ int gettxstr (WINDOW *win, wchar_t *restrict *restrict bufptr, // Allocate the result buffer if needed if (*bufptr == NULL) { *bufptr = xmalloc(BUFSIZE * sizeof(wchar_t)); - **bufptr = '\0'; + **bufptr = L'\0'; } return gettxline(win, *bufptr, BUFSIZE, modified, multifield, L"", L"", @@ -2665,13 +2665,14 @@ int gettxstr (WINDOW *win, wchar_t *restrict *restrict bufptr, /***********************************************************************/ // txinput_fixup: Copy strings with fixup -void txinput_fixup (wchar_t *restrict dest, wchar_t *restrict src, bool isfloat) +void txinput_fixup (wchar_t *restrict dest, const wchar_t *restrict src, + bool isfloat) { assert(src != NULL); assert(dest != NULL); wcsncpy(dest, src, BUFSIZE - 1); - dest[BUFSIZE - 1] = '\0'; + dest[BUFSIZE - 1] = L'\0'; // Replace mon_decimal_point with decimal_point if these are different if (isfloat) { diff --git a/src/intf.h b/src/intf.h index ede44af..ebdb70d 100644 --- a/src/intf.h +++ b/src/intf.h @@ -597,7 +597,7 @@ extern int gettxchar (WINDOW *win, wint_t *wch); attr - Character rendition to use for input field Returns: int - Status code: OK, ERR or KEY_ keycode - This low-level function shows an input field width column spaces long + This low-level function shows an input field width column-spaces long using attr as the character rendition, then reads a line of input from the keyboard and places it into the preallocated buffer buf[] of size bufsize. On entry, buf[] must contain a valid string; this string is @@ -633,7 +633,7 @@ extern int gettxchar (WINDOW *win, wint_t *wch); If allowed is not NULL, only characters in that string are allowed to be entered into the input line. For example, if allowed points to - "0123456789abcdefABCDEF", only those characters would be allowed (in + L"0123456789abcdefABCDEF", only those characters would be allowed (in this instance, allowing the user to type in a hexadecimal number). Note that the character rendition (attributes) in attr may contain a @@ -667,7 +667,7 @@ extern int gettxline (WINDOW *win, wchar_t *restrict buf, int bufsize, malloc(); this buffer is used to store and return the input line. Apart from bufptr, all parameters are as used for gettxline(). The - gettxline() parameters emptyval and defaultval are passed as "", + gettxline() parameters emptyval and defaultval are passed as L"", allowed is NULL and stripspc is true. */ extern int gettxstr (WINDOW *win, wchar_t *restrict *restrict bufptr, diff --git a/src/move.c b/src/move.c index 81ee522..5e5271a 100644 --- a/src/move.c +++ b/src/move.c @@ -263,7 +263,7 @@ selection_t get_move (void) key = towlower(key); } - for (i = 0, found = false; keycode_game_move[i] != '\0'; i++) { + for (i = 0, found = false; keycode_game_move[i] != L'\0'; i++) { if (keycode_game_move[i] == key) { found = true; selection = i; @@ -282,13 +282,13 @@ selection_t get_move (void) if (! found) { switch (key) { - case '1': + case L'1': curs_set(CURS_OFF); show_status(current_player); curs_set(CURS_ON); break; - case '2': + case L'2': selection = SEL_BANKRUPT; curs_set(CURS_OFF); @@ -297,7 +297,7 @@ selection_t get_move (void) _("^{<2>^} (Declare bankruptcy)")); break; - case '3': + case L'3': selection = SEL_SAVE; curs_set(CURS_OFF); @@ -396,12 +396,12 @@ selection_t get_move (void) if (gettxchar(curwin, &key) == OK) { // Ordinary wide character - if (key >= '1' && key <= '9') { + if (key >= L'1' && key <= L'9') { left(curwin, getcury(curwin), getcurx(curwin), A_BOLD, 0, 0, 1, "%lc", key); wrefresh(curwin); - choice = key - '0'; + choice = key - L'0'; done = true; } else { beep(); @@ -504,13 +504,13 @@ void process_move (selection_t selection) assign_vals(x, y, left, right, up, down); - if (left == MAP_EMPTY && right == MAP_EMPTY && - up == MAP_EMPTY && down == MAP_EMPTY) { + if ( left == MAP_EMPTY && right == MAP_EMPTY + && up == MAP_EMPTY && down == MAP_EMPTY) { // The position is out in the middle of nowhere... galaxy_map[x][y] = MAP_OUTPOST; - } else if (! IS_MAP_COMPANY(left) && ! IS_MAP_COMPANY(right) - && ! IS_MAP_COMPANY(up) && ! IS_MAP_COMPANY(down)) { + } else if ( ! IS_MAP_COMPANY(left) && ! IS_MAP_COMPANY(right) + && ! IS_MAP_COMPANY(up) && ! IS_MAP_COMPANY(down)) { // See if a company can be established try_start_new_company(x, y); @@ -770,6 +770,9 @@ void merge_companies (map_val_t a, map_val_t b) int aa = MAP_TO_COMPANY(a); int bb = MAP_TO_COMPANY(b); + assert(aa >= 0 && aa < MAX_COMPANIES); + assert(bb >= 0 && bb < MAX_COMPANIES); + double val_aa = company[aa].share_price * company[aa].stock_issued * company[aa].share_return; double val_bb = company[bb].share_price * company[bb].stock_issued * @@ -1137,7 +1140,8 @@ void adjust_values (void) // Give the current player the companies' dividends for (int i = 0; i < MAX_COMPANIES; i++) { if (company[i].on_map && company[i].stock_issued != 0) { - player[current_player].cash += player[current_player].stock_owned[i] + player[current_player].cash += + player[current_player].stock_owned[i] * company[i].share_price * company[i].share_return + ((double) player[current_player].stock_owned[i] / company[i].stock_issued) * company[i].share_price diff --git a/src/trader.c b/src/trader.c index 3d3c227..96b85a8 100644 --- a/src/trader.c +++ b/src/trader.c @@ -248,8 +248,8 @@ void process_cmdline (int argc, char *argv[]) if (optind < argc && argv[optind] != NULL) { if (*argv[optind] == '-') { - fprintf(stderr, _("%s: invalid operand `%s'\n"), program_name, - argv[optind]); + fprintf(stderr, _("%s: invalid operand `%s'\n"), + program_name, argv[optind]); show_usage(EXIT_FAILURE); } diff --git a/src/utils.c b/src/utils.c index 1558b73..39abf31 100644 --- a/src/utils.c +++ b/src/utils.c @@ -83,7 +83,7 @@ static bool add_currency_symbol = false; // Do we need to add "$"? /***********************************************************************/ // init_program_name: Make the program name canonical -void init_program_name (char *argv0) +void init_program_name (const char *argv0) { /* This implementation assumes a POSIX environment with an ASCII-safe character encoding (such as ASCII or UTF-8). */ @@ -109,7 +109,7 @@ const char *home_directory (void) { if (home_directory_str == NULL) { // Use the HOME environment variable where possible - char *home = getenv("HOME"); + const char *home = getenv("HOME"); if (home != NULL && *home != '\0') { home_directory_str = xstrdup(home); @@ -354,7 +354,7 @@ void init_locale (void) /***********************************************************************/ // l_strfmon: Convert monetary value to a string -ssize_t l_strfmon (char *restrict s, size_t maxsize, +ssize_t l_strfmon (char *restrict buf, size_t maxsize, const char *restrict format, double val) { /* The current implementation assumes MOD_POSIX_P_CS_PRECEDES is 1 @@ -365,7 +365,7 @@ ssize_t l_strfmon (char *restrict s, size_t maxsize, assert(MOD_POSIX_P_CS_PRECEDES == 1); assert(MOD_POSIX_P_SEP_BY_SPACE == 0); - ssize_t ret = strfmon(s, maxsize, format, val); + ssize_t ret = strfmon(buf, maxsize, format, val); if (ret > 0 && add_currency_symbol) { if (strstr(format, "!") == NULL) { @@ -382,7 +382,7 @@ ssize_t l_strfmon (char *restrict s, size_t maxsize, assert(maxsize > (unsigned int) symlen); // Count number of leading spaces - for (p = s, spc = 0; *p == ' '; p++, spc++) + for (p = buf, spc = 0; *p == ' '; p++, spc++) ; if (symlen <= spc) { @@ -394,12 +394,12 @@ ssize_t l_strfmon (char *restrict s, size_t maxsize, } else { // Make space for currency symbol, then copy it - memmove(s + symlen - spc, s, maxsize - (symlen - spc)); - s[maxsize - 1] = '\0'; + memmove(buf + symlen - spc, buf, maxsize - (symlen - spc)); + buf[maxsize - 1] = '\0'; - for ( ; *sym != '\0'; sym++, s++) { + for ( ; *sym != '\0'; sym++, buf++) { // Make sure terminating NUL character is NOT copied! - *s = *sym; + *buf = *sym; } ret = MIN((unsigned int) ret + symlen - spc, maxsize - 1); diff --git a/src/utils.h b/src/utils.h index adfcc8c..1174edf 100644 --- a/src/utils.h +++ b/src/utils.h @@ -70,7 +70,7 @@ extern wchar_t *mon_thousands_sep; // Local monetary thousands separator /* Function: init_program_name - Make the program name canonical - Parameters: argv0 - Same as passed to main() + Parameters: argv0 - Same as passed to main() as argv[0] Returns: (nothing) This function modifies the argv0 pointer to eliminate any leading @@ -78,7 +78,7 @@ extern wchar_t *mon_thousands_sep; // Local monetary thousands separator basename of the program. It also saves a copy that can be accessed via the program_name global variable. */ -extern void init_program_name (char *argv0); +extern void init_program_name (const char *argv0); /* @@ -239,7 +239,7 @@ extern void init_locale (void); /* Function: l_strfmon - Convert monetary value to a string - Parameters: s - Buffer to receive result + Parameters: buf - Buffer to receive result maxsize - Maximum size of buffer format - strfmon() format to use val - Monetary value to convert @@ -251,7 +251,7 @@ extern void init_locale (void); function overcomes the limitation that the POSIX locale does not define anything for localeconv()->currency_symbol. */ -extern ssize_t l_strfmon (char *restrict s, size_t maxsize, +extern ssize_t l_strfmon (char *restrict buf, size_t maxsize, const char *restrict format, double val); From 167bcd82f5e6d69112c8d3044e617e09a164a82c Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Thu, 25 Aug 2011 21:45:22 +1000 Subject: [PATCH 093/112] Remove the unused header file --- src/system.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/system.h b/src/system.h index c9342a7..b7f5143 100644 --- a/src/system.h +++ b/src/system.h @@ -57,7 +57,6 @@ #include #include #include -#include #include #include #include From dfab785ba7fa5cb558d4c510844d5b80a040394b Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Thu, 25 Aug 2011 21:55:10 +1000 Subject: [PATCH 094/112] Add a couple more places where the character constant is a wide char --- src/intf.c | 2 +- src/intf.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/intf.c b/src/intf.c index bd50c97..003e0aa 100644 --- a/src/intf.c +++ b/src/intf.c @@ -106,7 +106,7 @@ typedef struct txwin { do { \ char *s = gettext(_default); \ if (xmbstowcs(buf, s, BUFSIZE) < (_checkpos) + 1 \ - || buf[_checkpos] != '|') { \ + || buf[_checkpos] != L'|') { \ err_exit(_("%s: string has incorrect format: `%s'"), \ __stringify(_var), s); \ } \ diff --git a/src/intf.h b/src/intf.h index ebdb70d..8c45177 100644 --- a/src/intf.h +++ b/src/intf.h @@ -102,8 +102,8 @@ typedef enum curs_type { #define KEY_CTRL(x) ((x) - 0100) // ASCII control character // Keycodes for inserting the default value in input routines -#define CHAR_DEFVAL1 '=' -#define CHAR_DEFVAL2 ';' +#define CHAR_DEFVAL1 L'=' +#define CHAR_DEFVAL2 L';' // Control-arrow key combinations, as returned by Ncurses #ifndef KEY_CDOWN From cb67513bb9f87c18386d229bdf842a3d43f646cd Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Thu, 25 Aug 2011 22:15:12 +1000 Subject: [PATCH 095/112] Correct a minor bug in cursor decrement (cpos_dec) --- src/intf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/intf.c b/src/intf.c index 003e0aa..f5f6914 100644 --- a/src/intf.c +++ b/src/intf.c @@ -1867,7 +1867,7 @@ void cpos_end (const wchar_t *restrict buf, int *restrict cpos, void cpos_dec (const wchar_t *restrict buf, int *restrict cpos, int *restrict st, int w, int width) { - if (*cpos > 0) { + if (*cpos - w >= 0) { // Cursor position is not yet in first column *cpos -= w; } else if (*st > 0) { From 4c99f9a57f309b2b25290bfbaa302ece3ffdcb63 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Fri, 26 Aug 2011 03:22:25 +1000 Subject: [PATCH 096/112] More (slight) code clean-ups --- src/intf.c | 83 +++++++++++++++++++++++++----------------------------- 1 file changed, 39 insertions(+), 44 deletions(-) diff --git a/src/intf.c b/src/intf.c index f5f6914..9bc6131 100644 --- a/src/intf.c +++ b/src/intf.c @@ -1949,10 +1949,12 @@ int gettxline (WINDOW *win, wchar_t *restrict buf, int bufsize, clen = wcswidth(buf, bufsize); // clen is number of column positions if (clen < 0) { - err_exit("gettxline: illegal character in string: `%ls'", buf); + err_exit(_("gettxline: illegal character in string: `%ls'"), buf); } - // Find the point from which buf should be displayed to screen + /* Find the point from which buf should be displayed to screen. cpos + is the cursor position (0 to width-1), st is the offset in buf[] + from which to start printing the string on the screen. */ cpos_end(buf, &cpos, &st, clen, width, len); redraw = true; @@ -1992,7 +1994,7 @@ int gettxline (WINDOW *win, wchar_t *restrict buf, int bufsize, clen = wcswidth(buf, bufsize); if (clen == -1) { - err_exit("gettxline: illegal character in string: `%ls'", + err_exit(_("gettxline: illegal character in string: `%ls'"), buf); } @@ -2154,8 +2156,8 @@ int gettxline (WINDOW *win, wchar_t *restrict buf, int bufsize, cpos_dec(buf, &cpos, &st, wcwidth(buf[pos]), width); } while (pos > 0 && (iswalnum(buf[pos - 1]) - || (pos > 1 && wcwidth(buf[pos - 1]) == 0 - && iswalnum(buf[pos - 2])))) { + || (pos > 1 && wcwidth(buf[pos - 1]) == 0 + && iswalnum(buf[pos - 2])))) { /* Treat zero-width characters preceded by an alphanumeric character as alphanumeric. */ pos--; @@ -2310,18 +2312,18 @@ int gettxline (WINDOW *win, wchar_t *restrict buf, int bufsize, wchar_t c = buf[pos - 1]; buf[pos - 1] = buf[pos - 2]; buf[pos - 2] = c; + + // pos, cpos and st stay the same mod = true; redraw = true; } else { wchar_t c = buf[pos]; int w = wcwidth(c); - buf[pos] = buf[pos - 1]; buf[pos - 1] = c; pos++; cpos_inc(buf, &cpos, &st, w, width); - mod = true; redraw = true; } @@ -2359,17 +2361,16 @@ int gettxline (WINDOW *win, wchar_t *restrict buf, int bufsize, while (pos > 0 && ! iswalnum(buf[pos - 1])) { pos--; cpos_dec(buf, &cpos, &st, wcwidth(buf[pos]), - width); + width); } while (pos > 0 && (iswalnum(buf[pos - 1]) - || (pos > 1 - && wcwidth(buf[pos - 1]) == 0 - && iswalnum(buf[pos - 2])))) { + || (pos > 1 && wcwidth(buf[pos - 1]) == 0 + && iswalnum(buf[pos - 2])))) { /* Treat zero-width characters preceded by an alphanumeric character as alphanumeric. */ pos--; cpos_dec(buf, &cpos, &st, wcwidth(buf[pos]), - width); + width); } redraw = true; break; @@ -2380,16 +2381,15 @@ int gettxline (WINDOW *win, wchar_t *restrict buf, int bufsize, while (pos < len && ! iswalnum(buf[pos])) { pos++; cpos_inc(buf, &cpos, &st, - wcwidth(buf[pos - 1]), width); + wcwidth(buf[pos - 1]), width); } - while (pos < len - && (iswalnum(buf[pos]) - || wcwidth(buf[pos]) == 0)) { + while (pos < len && (iswalnum(buf[pos]) + || wcwidth(buf[pos]) == 0)) { /* Treat zero-width characters following an alphanumeric character as alphanumeric. */ pos++; cpos_inc(buf, &cpos, &st, - wcwidth(buf[pos - 1]), width); + wcwidth(buf[pos - 1]), width); } redraw = true; break; @@ -2406,12 +2406,11 @@ int gettxline (WINDOW *win, wchar_t *restrict buf, int bufsize, i++; ww += wcwidth(buf[i - 1]); } - while (i < len - && (iswalnum(buf[i]) - || wcwidth(buf[pos]) == 0)) { - /* Treat zero-width characters - following an alphanumeric - character as alphanumeric. */ + while (i < len && (iswalnum(buf[i]) + || wcwidth(buf[pos]) == 0)) { + /* Treat zero-width characters following + an alphanumeric character as + alphanumeric. */ i++; ww += wcwidth(buf[i - 1]); } @@ -2427,7 +2426,7 @@ int gettxline (WINDOW *win, wchar_t *restrict buf, int bufsize, case L'\\': case L' ': - // Delete all surrounding spaces; if key == ' ', + // Delete all surrounding spaces; if key == L' ', // also insert one space { int i = pos; @@ -2478,15 +2477,14 @@ int gettxline (WINDOW *win, wchar_t *restrict buf, int bufsize, while (pos < len && ! iswalnum(buf[pos])) { pos++; cpos_inc(buf, &cpos, &st, - wcwidth(buf[pos - 1]), width); + wcwidth(buf[pos - 1]), width); } - while (pos < len - && (iswalnum(buf[pos]) - || wcwidth(buf[pos]) == 0)) { + while (pos < len && (iswalnum(buf[pos]) + || wcwidth(buf[pos]) == 0)) { buf[pos] = towupper(buf[pos]); pos++; cpos_inc(buf, &cpos, &st, - wcwidth(buf[pos - 1]), width); + wcwidth(buf[pos - 1]), width); } mod = true; redraw = true; @@ -2498,15 +2496,14 @@ int gettxline (WINDOW *win, wchar_t *restrict buf, int bufsize, while (pos < len && ! iswalnum(buf[pos])) { pos++; cpos_inc(buf, &cpos, &st, - wcwidth(buf[pos - 1]), width); + wcwidth(buf[pos - 1]), width); } - while (pos < len - && (iswalnum(buf[pos]) - || wcwidth(buf[pos]) == 0)) { + while (pos < len && (iswalnum(buf[pos]) + || wcwidth(buf[pos]) == 0)) { buf[pos] = towlower(buf[pos]); pos++; cpos_inc(buf, &cpos, &st, - wcwidth(buf[pos - 1]), width); + wcwidth(buf[pos - 1]), width); } mod = true; redraw = true; @@ -2517,15 +2514,14 @@ int gettxline (WINDOW *win, wchar_t *restrict buf, int bufsize, // Convert current letter to upper case, // following letters to lower case { - bool first = true; while (pos < len && ! iswalnum(buf[pos])) { pos++; cpos_inc(buf, &cpos, &st, - wcwidth(buf[pos - 1]), width); + wcwidth(buf[pos - 1]), width); } - while (pos < len - && (iswalnum(buf[pos]) - || wcwidth(buf[pos]) == 0)) { + bool first = true; + while (pos < len && (iswalnum(buf[pos]) + || wcwidth(buf[pos]) == 0)) { if (first) { buf[pos] = towupper(buf[pos]); first = false; @@ -2534,7 +2530,7 @@ int gettxline (WINDOW *win, wchar_t *restrict buf, int bufsize, } pos++; cpos_inc(buf, &cpos, &st, - wcwidth(buf[pos - 1]), width); + wcwidth(buf[pos - 1]), width); } mod = true; redraw = true; @@ -2566,10 +2562,9 @@ int gettxline (WINDOW *win, wchar_t *restrict buf, int bufsize, ww += w; cpos_dec(buf, &cpos, &st, w, width); } - while (i > 0 - && (iswalnum(buf[i - 1]) - || (i > 1 && wcwidth(buf[i - 1]) == 0 - && iswalnum(buf[i - 2])))) { + while (i > 0 && (iswalnum(buf[i - 1]) + || (i > 1 && wcwidth(buf[i - 1]) == 0 + && iswalnum(buf[i - 2])))) { /* Treat zero-width characters preceded by an alphanumeric character as alphanumeric. */ i--; From dffb4c59fe394db26e77c6609b52ec4b4dc37d03 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Fri, 26 Aug 2011 04:51:44 +1000 Subject: [PATCH 097/112] Implement the single-byte equivalent of getwch() This implementation assembles a wide character from a stream of multibyte-forming bytes. --- src/intf.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++---- src/intf.h | 2 +- 2 files changed, 77 insertions(+), 7 deletions(-) diff --git a/src/intf.c b/src/intf.c index 9bc6131..eb76e57 100644 --- a/src/intf.c +++ b/src/intf.c @@ -322,7 +322,7 @@ static void mkchstr_conv (chtype *restrict chbuf, int chbufsize, This function is either a wrapper (with modifications) for wget_wch() from Curses, or an implementation of that function using wgetch(). */ -static int getwch (WINDOW *win, wint_t *wch); +static int getwch (WINDOW *win, wint_t *restrict wch); /* @@ -1755,7 +1755,7 @@ int right (WINDOW *win, int y, int x, chtype attr_norm, chtype attr_alt1, #if defined(HAVE_CURSES_ENHANCED) || defined(HAVE_NCURSESW) -int getwch (WINDOW *win, wint_t *wch) +int getwch (WINDOW *win, wint_t *restrict wch) { int ret = wget_wch(win, wch); @@ -1768,6 +1768,7 @@ int getwch (WINDOW *win, wint_t *wch) (due to the same codes being returned by getch()). We do not use iswcntrl() as certain additional Unicode characters are also control characters (eg, U+2028) */ + *wch = (unsigned char) c; ret = KEY_CODE_YES; } } @@ -1777,10 +1778,79 @@ int getwch (WINDOW *win, wint_t *wch) #else // !defined(HAVE_CURSES_ENHANCED) && !defined(HAVE_NCURSESW) -int getwch (WINDOW *win, wint_t *wch) +int getwch (WINDOW *win, wint_t *restrict wch) { -#error "Single-byte version of getwch() not yet implemented" -"Single-byte version of getwch() not yet implemented" + static mbstate_t *mbstate; // Current shift state + + char buf[MB_LEN_MAX * 8]; // Allow space for redundant shifts + mbstate_t mbcopy; + int len, ret; + wchar_t val = 0; + + + if (mbstate == NULL) { + mbstate = xmalloc(sizeof(mbstate_t)); + memset(mbstate, 0, sizeof(mbstate_t)); + } + + len = 0; + while (true) { + ret = wgetch(win); + if (ret == ERR) { + break; + } else if (ret >= 0400) { + // Assume any non-ASCII result is a function key + if (len > 0) { + // Function key is interrupting an incomplete multibyte char! + ungetch(ret); + ret = ERR; + } else { + val = ret; + ret = KEY_CODE_YES; + } + break; + } else if (len >= sizeof(buf) - 1) { + // Too many characters + ungetch(ret); + ret = ERR; + break; + } else { + buf[len++] = ret; + + // Do we have a complete multibyte keypress? + memcpy(&mbcopy, mbstate, sizeof(mbstate_t)); + size_t n = mbrtowc(&val, buf, len, &mbcopy); + if (n == (size_t) -1) { + // Invalid character + ungetch(ret); + ret = ERR; + break; + } else if (n == (size_t) -2) { + // Incomplete sequence: wait for more bytes to come + ; + } else { + // A valid multibyte sequence + memcpy(mbstate, &mbcopy, sizeof(mbstate_t)); + + char c = wctob(val); + if ((c >= 0 && c < ' ') || c == 0x7F) { + /* Make control characters (and DEL) appear to be + similar to function keys. */ + val = (unsigned char) c; + ret = KEY_CODE_YES; + } else { + // An ordinary key + ret = OK; + } + break; + } + } + } + + if (wch != NULL) { + *wch = val; + } + return ret; } #endif // !defined(HAVE_CURSES_ENHANCED) && !defined(HAVE_NCURSESW) @@ -1789,7 +1859,7 @@ int getwch (WINDOW *win, wint_t *wch) /***********************************************************************/ // gettxchar: Read a character from the keyboard -int gettxchar (WINDOW *win, wint_t *wch) +int gettxchar (WINDOW *win, wint_t *restrict wch) { int ret; diff --git a/src/intf.h b/src/intf.h index 8c45177..322ded0 100644 --- a/src/intf.h +++ b/src/intf.h @@ -578,7 +578,7 @@ extern int right (WINDOW *win, int y, int x, chtype attr_norm, chtype attr_alt1, returned. ERR is never returned. The key is NOT echoed to the terminal display, nor is the cursor visibility affected. */ -extern int gettxchar (WINDOW *win, wint_t *wch); +extern int gettxchar (WINDOW *win, wint_t *restrict wch); /* From 3a68213e80e80d07f10c5d1f6fa6878104907b87 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Fri, 26 Aug 2011 06:33:40 +1000 Subject: [PATCH 098/112] Remove all unnecessary Gnulib modules In particular, the various printf-posix modules are not needed as %ls and the ' flag (thousands separator) is supported on all modern platforms (it is needed on Cygwin 1.5.x, for example, but the 1.5.x series do not support swprintf() anyway). Similarly, OpenBSD 3.8 (released November 2005) is not supported: it does not have . A number of modules (locale, string, unistd, wchar) are only required for NetBSD 5.0 (c. 2009: quite recent). We try to support MacOS X 10.5 (October 2007), but it may require GNU libiconv. --- lib/.gitignore | 69 ---------------------------------------------- m4/.gitignore | 42 ---------------------------- m4/gnulib-cache.m4 | 18 +----------- 3 files changed, 1 insertion(+), 128 deletions(-) diff --git a/lib/.gitignore b/lib/.gitignore index 692d9bb..e2586b1 100644 --- a/lib/.gitignore +++ b/lib/.gitignore @@ -1,6 +1,4 @@ Makefile.am -alloca.in.h -asnprintf.c btowc.c c-ctype.c c-ctype.h @@ -8,18 +6,6 @@ c-strcase.h c-strcasecmp.c c-strncasecmp.c config.charset -ctype.in.h -dosname.h -errno.in.h -float+.h -float.c -float.in.h -fprintf.c -fpucw.h -frexp.c -frexpl.c -fseterr.c -fseterr.h getopt.c getopt.in.h getopt1.c @@ -35,19 +21,9 @@ iconv_open-irix.gperf iconv_open-osf.gperf iconv_open-solaris.gperf iconv_open.c -isnan.c -isnand-nolibm.h -isnand.c -isnanf-nolibm.h -isnanf.c -isnanl-nolibm.h -isnanl.c -langinfo.in.h localcharset.c localcharset.h locale.in.h -malloc.c -math.in.h mbrtowc.c mbsinit.c mbsrtowcs-impl.h @@ -57,41 +33,18 @@ mbtowc-impl.h mbtowc.c memchr.c memchr.valgrind -printf-args.c -printf-args.h -printf-frexp.c -printf-frexp.h -printf-frexpl.c -printf-frexpl.h -printf-parse.c -printf-parse.h -printf.c ref-add.sin ref-del.sin -sig-handler.h -sigaction.c -signal.in.h -signbitd.c -signbitf.c -signbitl.c -sigprocmask.c -size_max.h -snprintf.c -stat.c -stdarg.in.h stdbool.in.h stddef.in.h stdint.in.h -stdio-impl.h stdio.in.h stdlib.in.h str-two-way.h -strdup.c streq.h striconv.c striconv.h string.in.h -strncat.c strnlen1.c strnlen1.h strstr.c @@ -101,36 +54,22 @@ time.in.h unistd.in.h unistr.in.h unitypes.in.h -uniwidth.in.h -vasnprintf.c -vasnprintf.h verify.h -vfprintf.c -vsnprintf.c wchar.in.h wcrtomb.c wcsdup-impl.h wcsdup.c -wcsrtombs-impl.h -wcsrtombs-state.c -wcsrtombs.c -wcswidth-impl.h -wcswidth.c wctob.c wctomb-impl.h wctomb.c wctype.in.h -wcwidth.c wmemcpy-impl.h wmemcpy.c -xsize.h -alloca.h arg-nonnull.h c++defs.h charset.alias configmake.h -ctype.h getopt.h iconv.h iconv_open-aix.h @@ -138,12 +77,9 @@ iconv_open-hpux.h iconv_open-irix.h iconv_open-osf.h iconv_open-solaris.h -langinfo.h locale.h -math.h ref-add.sed ref-del.sed -signal.h stdio.h stdlib.h string.h @@ -152,7 +88,6 @@ time.h unistd.h unistr.h unitypes.h -uniwidth.h unused-parameter.h warn-on-use.h wchar.h @@ -162,7 +97,3 @@ unistr/.dirstamp unistr/u8-mbtoucr.c unistr/u8-uctomb-aux.c unistr/u8-uctomb.c - -uniwidth/.dirstamp -uniwidth/cjk.h -uniwidth/width.c diff --git a/m4/.gitignore b/m4/.gitignore index 6cd5941..a26f228 100644 --- a/m4/.gitignore +++ b/m4/.gitignore @@ -1,23 +1,11 @@ 00gnulib.m4 -alloca.m4 -asm-underscore.m4 assert.m4 btowc.m4 codeset.m4 config-h.m4 configmake.m4 -ctype.m4 -errno_h.m4 -exponentd.m4 -exponentf.m4 -exponentl.m4 extensions.m4 fcntl-o.m4 -float_h.m4 -fpieee.m4 -fprintf-posix.m4 -frexp.m4 -frexpl.m4 getopt.m4 gettext.m4 gettimeofday.m4 @@ -36,16 +24,9 @@ intl.m4 intldir.m4 intlmacosx.m4 intmax.m4 -intmax_t.m4 inttypes-pri.m4 inttypes_h.m4 -isnand.m4 -isnanf.m4 -isnanl.m4 -langinfo_h.m4 -largefile.m4 lcmessage.m4 -ldexpl.m4 lib-ld.m4 lib-link.m4 lib-prefix.m4 @@ -57,8 +38,6 @@ locale-zh.m4 locale_h.m4 lock.m4 longlong.m4 -malloc.m4 -math_h.m4 mbrtowc.m4 mbsinit.m4 mbsrtowcs.m4 @@ -70,30 +49,16 @@ multiarch.m4 nls.m4 nocrash.m4 po.m4 -printf-frexp.m4 -printf-frexpl.m4 -printf-posix-rpl.m4 printf-posix.m4 -printf.m4 progtest.m4 -sigaction.m4 -signal_h.m4 -signalblocking.m4 -signbit.m4 size_max.m4 -snprintf-posix.m4 -snprintf.m4 -stat.m4 -stdarg.m4 stdbool.m4 stddef_h.m4 stdint.m4 stdint_h.m4 stdio_h.m4 stdlib_h.m4 -strdup.m4 string_h.m4 -strncat.m4 strstr.m4 sys_stat_h.m4 sys_time_h.m4 @@ -101,22 +66,15 @@ threadlib.m4 time_h.m4 uintmax_t.m4 unistd_h.m4 -vasnprintf.m4 -vfprintf-posix.m4 visibility.m4 -vsnprintf-posix.m4 -vsnprintf.m4 warn-on-use.m4 wchar_h.m4 wchar_t.m4 wcrtomb.m4 wcsdup.m4 -wcsrtombs.m4 -wcswidth.m4 wctob.m4 wctomb.m4 wctype_h.m4 -wcwidth.m4 wint_t.m4 wmemcpy.m4 xsize.m4 diff --git a/m4/gnulib-cache.m4 b/m4/gnulib-cache.m4 index d6b55ea..00ce11e 100644 --- a/m4/gnulib-cache.m4 +++ b/m4/gnulib-cache.m4 @@ -15,7 +15,7 @@ # Specification in the form of a command-line invocation: -# gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --no-conditional-dependencies --no-libtool --macro-prefix=gl assert btowc config-h ctype fprintf-posix getopt-gnu gettext gettext-h gettimeofday langinfo locale mbrtowc mbsrtowcs printf-posix sigaction signal snprintf-posix stat stdarg stdbool stdio strdup-posix striconv string strncat strstr sys_stat sys_time unistd vfprintf-posix vsnprintf-posix wchar wcrtomb wcsdup wcsrtombs wcswidth wctob wctype-h wcwidth +# gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --no-conditional-dependencies --no-libtool --macro-prefix=gl assert btowc config-h getopt-gnu gettext gettext-h gettimeofday locale mbrtowc mbsrtowcs stdbool stdio striconv string strstr sys_stat sys_time unistd wchar wcrtomb wcsdup wctob wctype-h # Specification in the form of a few gnulib-tool.m4 macro invocations: gl_LOCAL_DIR([]) @@ -23,42 +23,26 @@ gl_MODULES([ assert btowc config-h - ctype - fprintf-posix getopt-gnu gettext gettext-h gettimeofday - langinfo locale mbrtowc mbsrtowcs - printf-posix - sigaction - signal - snprintf-posix - stat - stdarg stdbool stdio - strdup-posix striconv string - strncat strstr sys_stat sys_time unistd - vfprintf-posix - vsnprintf-posix wchar wcrtomb wcsdup - wcsrtombs - wcswidth wctob wctype-h - wcwidth ]) gl_AVOID([]) gl_SOURCE_BASE([lib]) From 3b8aaf193e3ea18d748eb92f9ffed3f3a896c1f8 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Sun, 28 Aug 2011 14:11:29 +1000 Subject: [PATCH 099/112] Don't suggest /tmp for building: it may not be large enough --- INSTALL | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/INSTALL b/INSTALL index 11b96e5..a9baeea 100644 --- a/INSTALL +++ b/INSTALL @@ -103,8 +103,8 @@ separate build directory, then run configure. For example, if you placed the Star Traders source code tree in $HOME/src/trader-7.2, you could run something like: - mkdir /tmp/trader-build-7.2 - cd /tmp/trader-build-7.2 + mkdir $HOME/build/trader-build-7.2 + cd $HOME/build/trader-build-7.2 $HOME/src/trader-7.2/configure Once again, the Autoconf manual describes these options (and many others): From 0ec87f8b3488741f167a812b6bdca46b9ff6741d Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Sun, 28 Aug 2011 14:40:39 +1000 Subject: [PATCH 100/112] Multibyte locales require a wide-character version of Curses --- INSTALL | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/INSTALL b/INSTALL index a9baeea..5308e8e 100644 --- a/INSTALL +++ b/INSTALL @@ -35,7 +35,9 @@ and installation: older systems may also work without modification. 3. A working X/Open Curses-compatible library, such as Ncurses. Ncurses - is preferred over system-native libraries, if present. + is preferred over system-native libraries, if present. Locales with + multibyte character sequences (such as UTF-8) require a wide-character + version of Curses, such as NcursesW, to work correctly. 4. The GNU Gettext library, version 0.18.1 or later, to allow the game to use languages other than English; this is also called Native Language From 868013e5a5c3b719d06f6b0746a8facf1b8ce09d Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Sun, 28 Aug 2011 16:10:46 +1000 Subject: [PATCH 101/112] Add translations for en_AU, en_GB and en_US In particular, replace quotes with Unicode variants and change spelling appropriately. --- .gitignore | 2 +- po/LINGUAS | 3 + po/en_AU.po | 1662 +++++++++++++++++++++++++++++++++++++++++++++++++++ po/en_GB.po | 1662 +++++++++++++++++++++++++++++++++++++++++++++++++++ po/en_US.po | 1662 +++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 4990 insertions(+), 1 deletion(-) create mode 100644 po/en_AU.po create mode 100644 po/en_GB.po create mode 100644 po/en_US.po diff --git a/.gitignore b/.gitignore index 8f5607d..9656886 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ *.o *.a +*.gmo .deps/ Makefile Makefile.in @@ -29,7 +30,6 @@ TAGS /build-aux/snippet/warn-on-use.h /po/POTFILES -/po/en@quot.gmo /po/en@quot.insert-header /po/en@quot.po /po/messages.mo diff --git a/po/LINGUAS b/po/LINGUAS index 14fe9e1..27c00af 100644 --- a/po/LINGUAS +++ b/po/LINGUAS @@ -27,3 +27,6 @@ en@quot +en_AU +en_GB +en_US diff --git a/po/en_AU.po b/po/en_AU.po new file mode 100644 index 0000000..e4251ef --- /dev/null +++ b/po/en_AU.po @@ -0,0 +1,1662 @@ +# ************************************************************************* +# * * +# * English (Australian) Translations for Star Traders * +# * Copyright (C) 1990-2011, John Zaitseff * +# * * +# ************************************************************************* +# +# This file is distributed under the same licence as Star Traders. +# +# Contributors: +# John Zaitseff , 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: trader 7.2\n" +"Report-Msgid-Bugs-To: J.Zaitseff@zap.org.au\n" +"POT-Creation-Date: 2011-08-28 14:55+1000\n" +"PO-Revision-Date: 2011-08-28 16:00+1000\n" +"Last-Translator: John Zaitseff \n" +"Language-Team: English (Australian)\n" +"Language: en_AU\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: src/trader.c:235 +#, c-format +msgid "%s: invalid value for --max-turn: `%s'\n" +msgstr "%s: invalid value for --max-turn: ‘%s’\n" + +#: src/trader.c:251 +#, c-format +msgid "%s: invalid operand `%s'\n" +msgstr "%s: invalid operand ‘%s’\n" + +#: src/trader.c:260 +#, c-format +msgid "%s: invalid game number `%s'\n" +msgstr "%s: invalid game number ‘%s’\n" + +#: src/trader.c:269 +#, c-format +msgid "%s: extra operand `%s'\n" +msgstr "%s: extra operand ‘%s’\n" + +#. TRANSLATORS: "John Zaitseff" [IPA d͡ʒɒn ˈzaɪ̯t͡səf] is the proper +#. name of the author. The IPA pronunciation in this comment is in +#. UTF-8 encoding. +#: src/trader.c:284 +#, c-format +msgid "" +"Star Traders (%s) %s\n" +"Copyright (C) %s, John Zaitseff.\n" +"\n" +"Star Traders is a simple game of interstellar trading, where the object\n" +"of the game is to create companies, buy and sell shares, borrow and repay\n" +"money, in order to become the wealthiest player (the winner).\n" +"\n" +"This program is free software that is distributed under the terms of the\n" +"GNU General Public License, version 3 or later. You are welcome to\n" +"modify and/or distribute it under certain conditions. This program has\n" +"NO WARRANTY, to the extent permitted by law; see the License for details.\n" +msgstr "" +"Star Traders (%s) %s\n" +"Copyright (C) %s, John Zaitseff.\n" +"\n" +"Star Traders is a simple game of interstellar trading, where the object\n" +"of the game is to create companies, buy and sell shares, borrow and repay\n" +"money, in order to become the wealthiest player (the winner).\n" +"\n" +"This program is free software that is distributed under the terms of the\n" +"GNU General Public License, version 3 or later. You are welcome to\n" +"modify and/or distribute it under certain conditions. This program has\n" +"NO WARRANTY, to the extent permitted by law; see the License for details.\n" + +#: src/trader.c:308 +#, c-format +msgid "%s: Try `%s --help' for more information.\n" +msgstr "%s: Try ‘%s --help’ for more information.\n" + +#: src/trader.c:311 +#, c-format +msgid "Usage: %s [OPTION ...] [GAME]\n" +msgstr "Usage: %s [OPTION ...] [GAME]\n" + +#: src/trader.c:312 +#, c-format +msgid "" +"Play Star Traders, a simple game of interstellar trading.\n" +"\n" +msgstr "" +"Play Star Traders, a simple game of interstellar trading.\n" +"\n" + +#: src/trader.c:315 +#, c-format +msgid "" +"Options:\n" +" -V, --version output version information and exit\n" +" -h, --help display this help and exit\n" +" --no-color don't use color for displaying text\n" +" --max-turn=NUM set the number of turns to NUM\n" +"\n" +msgstr "" +"Options:\n" +" -V, --version output version information and exit\n" +" -h, --help display this help and exit\n" +" --no-colour don’t use colour for displaying text\n" +" --max-turn=NUM set the number of turns to NUM\n" +"\n" + +#: src/trader.c:322 +#, c-format +msgid "" +"If GAME is specified as a number between 1 and 9, load and continue\n" +"playing that game. If GAME is not specified, start a new game.\n" +"\n" +msgstr "" +"If GAME is specified as a number between 1 and 9, load and continue\n" +"playing that game. If GAME is not specified, start a new game.\n" +"\n" + +#. TRANSLATORS: The first %s is the proper name of the package +#. author, John Zaitseff [IPA d͡ʒɒn ˈzaɪ̯t͡səf]; the second %s is +#. the e-mail address for reporting bugs. Please add ANOTHER +#. line with the (translated) text "Report translation bugs to +#.
\n", with ADDRESS replaced with either an e-mail +#. address or web URL for reporting bugs in your translation. +#: src/trader.c:334 +#, c-format +msgid "Report bugs to %s <%s>.\n" +msgstr "Report bugs to %s <%s>.\n" + +#. TRANSLATORS: %s is the e-mail address for reporting bugs. As +#. with the previous string, please add ANOTHER line with the +#. (translated) text "Report translation bugs to
\n", +#. with ADDRESS replaced with either an e-mail address or web URL +#. for reporting bugs in your translation. +#: src/trader.c:341 +#, c-format +msgid "Report bugs to <%s>.\n" +msgstr "Report bugs to <%s>.\n" + +#. TRANSLATORS: The first %s is for packagers and may be +#. something like "Debian". +#: src/trader.c:346 +#, c-format +msgid "Report %s bugs to <%s>.\n" +msgstr "Report %s bugs to <%s>.\n" + +#: src/trader.c:349 +#, c-format +msgid "Star Traders home page: <%s>.\n" +msgstr "Star Traders home page: <%s>.\n" + +#. TRANSLATORS: The eight company names do NOT have to be literal +#. translations of the English names. In fact, if possible, the +#. names should start with successive letters of your alphabet (in +#. English, for example, "A" to "H"). No company name should be more +#. than 24 characters (column positions, to be precise) long. +#: src/globals.c:46 +msgid "Altair Starways" +msgstr "Altair Starways" + +#: src/globals.c:47 +msgid "Betelgeuse, Ltd" +msgstr "Betelgeuse, Ltd" + +#: src/globals.c:48 +msgid "Capella Freight Co" +msgstr "Capella Freight Co" + +#: src/globals.c:49 +msgid "Denebola Shippers" +msgstr "Denebola Shippers" + +#: src/globals.c:50 +msgid "Eridani Expediters" +msgstr "Eridani Expediters" + +#: src/globals.c:51 +msgid "Fornax Express" +msgstr "Fornax Express" + +#: src/globals.c:52 +msgid "Gemeni Inc" +msgstr "Gemeni Inc" + +#: src/globals.c:53 +msgid "Hercules and Co" +msgstr "Hercules and Co" + +#. TRANSLATORS: This string specifies the keycodes (keyboard input +#. codes) used to enter the Stock Transaction window for each +#. company. There must be exactly eight characters, one for each +#. company in order, before the ASCII vertical line "|"; these must +#. be EITHER all in upper-case or all in lower-case. If at all +#. possible, these should be successive letters in your alphabet (in +#. English, "A" to "H"). Do NOT use digits or control characters. +#. Do not change or translate anything after the vertical line. +#: src/globals.c:67 +msgid "ABCDEFGH|input|Companies" +msgstr "ABCDEFGH|input|Companies" + +#. TRANSLATORS: This string specifies the keycodes used to select a +#. game move. There must be exactly 20 characters, one for each +#. move, before the ASCII vertical line "|"; these must be EITHER all +#. in upper-case or all in lower-case. If at all possible, these +#. should be successive letters in your alphabet. Do NOT use digits +#. or control characters. Do not change or translate anything after +#. the vertical line. +#: src/globals.c:79 +msgid "ABCDEFGHIJKLMNOPQRST|input|GameMoves" +msgstr "ABCDEFGHIJKLMNOPQRST|input|GameMoves" + +#. TRANSLATORS: This string is used to display the galaxy map to +#. screen. There must be exactly 11 characters before the ASCII +#. vertical line. The first ("." in English) is used for empty +#. space, the second ("+") for outposts, the third ("*") for stars, +#. the remaining for the eight companies. Do not change or translate +#. anything after the vertical line. +#: src/globals.c:90 +msgid ".+*ABCDEFGH|output|MapVals" +msgstr ".+*ABCDEFGH|output|MapVals" + +#. TRANSLATORS: This string is used to display the game moves +#. (choices). There must be exactly 20 characters (NUMBER_MOVES) +#. before the ASCII vertical line. The first character corresponds +#. to the first character in the "input|GameMoves" string, and so on. +#. Do not change or translate anything after the vertical line. +#: src/globals.c:100 +msgid "abcdefghijklmnopqrst|output|GameMoves" +msgstr "abcdefghijklmnopqrst|output|GameMoves" + +#. TRANSLATORS: The ordinal strings "1st" to "8th" are used in the +#. Game Winner dialog box at the end of the game. If ordinals depend +#. on the gender of the player, it may be simpler to list cardinal +#. numbers instead (eg, "No. 1"). Up to five characters are allowed +#. (see ORDINAL_COLS in src/intf.h). +#: src/globals.c:111 +msgid "1st" +msgstr "1st" + +#: src/globals.c:112 +msgid "2nd" +msgstr "2nd" + +#: src/globals.c:113 +msgid "3rd" +msgstr "3rd" + +#: src/globals.c:114 +msgid "4th" +msgstr "4th" + +#: src/globals.c:115 +msgid "5th" +msgstr "5th" + +#: src/globals.c:116 +msgid "6th" +msgstr "6th" + +#: src/globals.c:117 +msgid "7th" +msgstr "7th" + +#: src/globals.c:118 +msgid "8th" +msgstr "8th" + +#: src/game.c:117 src/game.c:152 +#, c-format +msgid "Loading game %d... " +msgstr "Loading game %d... " + +#: src/game.c:226 +msgid " First Player " +msgstr " First Player " + +#: src/game.c:227 +#, c-format +msgid "The first player to go is ^{%ls^}." +msgstr "The first player to go is ^{%ls^}." + +#. TRANSLATORS: The keycode should be modified to +#. match that (or those) specified with msgctxt +#. "input|ContinueGame". +#: src/game.c:259 +#, c-format +msgid "Enter number of players [^{1^}-^{%d^}] or ^{^} to continue a game: " +msgstr "Enter number of players [^{1^}-^{%d^}] or ^{^} to continue a game: " + +#. TRANSLATORS: This string specifies the keycodes used to continue a +#. game; these must NOT contain any numeric digit from 1 to 9. The +#. first character (keyboard input code) is used to print the user's +#. response if one of those keys is pressed. Both upper and +#. lower-case versions should be present. +#: src/game.c:276 +msgctxt "input|ContinueGame" +msgid "Cc" +msgstr "Cc" + +#: src/game.c:341 src/move.c:380 +msgid "Enter game number [^{1^}-^{9^}] or ^{^} to cancel: " +msgstr "Enter game number [^{1^}-^{9^}] or ^{^} to cancel: " + +#: src/game.c:406 +msgid "Please enter your name: " +msgstr "Please enter your name: " + +#: src/game.c:425 +msgid "Do you need any instructions? [^{Y^}/^{N^}] " +msgstr "Do you need any instructions? [^{Y^}/^{N^}] " + +#: src/game.c:443 +msgid " Enter Player Names " +msgstr " Enter Player Names " + +#: src/game.c:451 +#, c-format, range: 1..8 +msgid "Player %d: " +msgstr "Player %d: " + +#: src/game.c:529 +msgid "Does any player need instructions? [^{Y^}/^{N^}] " +msgstr "Does any player need instructions? [^{Y^}/^{N^}] " + +#: src/game.c:563 +msgid " Game Over " +msgstr " Game Over " + +#: src/game.c:564 +#, c-format +msgid "The game is over after one turn." +msgid_plural "The game is over after %d turns." +msgstr[0] "The game is over after one turn." +msgstr[1] "The game is over after %d turns." + +#: src/game.c:575 +msgid " Total Value " +msgstr " Total Value " + +#: src/game.c:577 +#, c-format +msgid "Your total value was ^{%N^}." +msgstr "Your total value was ^{%N^}." + +#: src/game.c:588 +#, c-format +msgid "" +"The winner is ^{%ls^}\n" +"who is ^[*** BANKRUPT ***^]" +msgstr "" +"The winner is ^{%ls^}\n" +"who is ^[*** BANKRUPT ***^]" + +#: src/game.c:591 +#, c-format +msgid "" +"The winner is ^{%ls^}\n" +"with a value of ^{%N^}." +msgstr "" +"The winner is ^{%ls^}\n" +"with a value of ^{%N^}." + +#: src/game.c:597 +msgid " Game Winner " +msgstr " Game Winner " + +#. TRANSLATORS: "Player" is used as a column title in a +#. table containing all player names. +#: src/game.c:606 src/move.c:847 +msgctxt "subtitle" +msgid "Player" +msgstr "Player" + +#. TRANSLATORS: "Total Value" refers to the total worth +#. (shares, cash and debt) of any given player. %ls is the +#. currency symbol of the current locale. +#: src/game.c:611 +#, c-format +msgctxt "subtitle" +msgid "Total Value (%ls)" +msgstr "Total Value (%ls)" + +#: src/game.c:645 src/game.c:695 src/exch.c:100 +#, c-format +msgid "Player: ^{%ls^}" +msgstr "Player: ^{%ls^}" + +#: src/game.c:648 +#, c-format +msgid " Turn: ^{%d^} " +msgstr " Turn: ^{%d^} " + +#: src/game.c:649 +msgid " ^[*** Last Turn ***^] " +msgstr " ^[*** Last Turn ***^] " + +#: src/game.c:693 +msgid " Stock Portfolio " +msgstr " Stock Portfolio " + +#. TRANSLATORS: The current player is bankrupt (has no +#. shares or cash, ie, whose total value is zero) +#: src/game.c:702 +msgid "^[* * * B A N K R U P T * * *^]" +msgstr "^[* * * B A N K R U P T * * *^]" + +#: src/game.c:717 src/exch.c:112 +msgid "No companies on the map" +msgstr "No companies on the map" + +#. TRANSLATORS: "Company" is a two-line column label in +#. a table containing a list of companies. +#: src/game.c:725 src/exch.c:120 +msgctxt "subtitle" +msgid "" +"\n" +"Company" +msgstr "" +"\n" +"Company" + +#. TRANSLATORS: "Ownership" is a two-line column label +#. in a table containing the current player's +#. percentage ownership in any given company. The +#. maximum column width is 10 characters (see +#. OWNERSHIP_COLS in src/intf.h). +#: src/game.c:732 +#, c-format +msgctxt "subtitle" +msgid "" +"Ownership\n" +"(%%)" +msgstr "" +"Ownership\n" +"(%%)" + +#. TRANSLATORS: "Holdings" is a two-line column label +#. in a table containing the number of shares the +#. current player owns in any given company. The +#. maximum column width is 10 characters (see +#. STOCK_OWNED_COLS in src/intf.h). +#: src/game.c:739 +msgctxt "subtitle" +msgid "" +"Holdings\n" +"(shares)" +msgstr "" +"Holdings\n" +"(shares)" + +#. TRANSLATORS: "Return" is a two-line column label in +#. a table containing the share return as a percentage +#. in any given company. The maximum column width is +#. 10 characters (see SHARE_RETURN_COLS in src/intf.h). +#: src/game.c:746 src/exch.c:141 +#, c-format +msgctxt "subtitle" +msgid "" +"Return\n" +"(%%)" +msgstr "" +"Return\n" +"(%%)" + +#. TRANSLATORS: "Price per share" is a two-line column +#. label in a table containing the price per share in +#. any given company. %ls is the currency symbol in +#. the current locale. The maximum column width is 12 +#. characters INCLUDING the currency symbol (see +#. SHARE_PRICE_COLS in src/intf.h). +#: src/game.c:755 src/exch.c:150 +#, c-format +msgctxt "subtitle" +msgid "" +"Price per\n" +"share (%ls)" +msgstr "" +"Price per\n" +"share (%ls)" + +#. TRANSLATORS: The "Total value", "Current cash", +#. "Current debt" and "Interest rate" labels MUST all be +#. the same length (ie, right-padded with spaces as +#. needed) and must have at least one trailing space so +#. that the display routines work correctly. The maximum +#. length of each label is 36 characters. +#. +#. Note that some of these labels are used for both the +#. Player Status window and the Trading Bank window. +#: src/game.c:796 +msgctxt "label" +msgid "Total value: " +msgstr "Total value: " + +#: src/game.c:800 src/exch.c:323 +msgctxt "label" +msgid "Current cash: " +msgstr "Current cash: " + +#: src/game.c:807 src/exch.c:331 +msgctxt "label" +msgid "Current debt: " +msgstr "Current debt: " + +#: src/game.c:813 src/exch.c:336 +msgctxt "label" +msgid "Interest rate: " +msgstr "Interest rate: " + +#: src/move.c:235 src/exch.c:183 +msgid "^{<1>^} Display stock portfolio" +msgstr "^{<1>^} Display stock portfolio" + +#: src/move.c:237 +msgid "^{<2>^} Declare bankruptcy" +msgstr "^{<2>^} Declare bankruptcy" + +#: src/move.c:239 +msgid "^{<3>^} Save and end the game" +msgstr "^{<3>^} Save and end the game" + +#: src/move.c:241 +msgid "^{^} Quit the game" +msgstr "^{^} Quit the game" + +#: src/move.c:245 +#, c-format +msgid "Select move [^[%lc^]-^[%lc^]/^{1^}-^{3^}/^{^}]: " +msgstr "Select move [^[%lc^]-^[%lc^]/^{1^}-^{3^}/^{^}]: " + +#. TRANSLATORS: "Move" refers to the choice of +#. moves made by the current player (out of a +#. selection of 20 moves). +#: src/move.c:277 +#, c-format +msgid "Move ^{%lc^}" +msgstr "Move ^{%lc^}" + +#: src/move.c:297 +msgid "^{<2>^} (Declare bankruptcy)" +msgstr "^{<2>^} (Declare bankruptcy)" + +#: src/move.c:306 +msgid "^{<3>^} (Save and end the game)" +msgstr "^{<3>^} (Save and end the game)" + +#: src/move.c:327 +msgid "^{^} (Quit the game)" +msgstr "^{^} (Quit the game)" + +#: src/move.c:342 +msgid "Are you sure? [^{Y^}/^{N^}] " +msgstr "Are you sure? [^{Y^}/^{N^}] " + +#: src/move.c:359 src/move.c:437 +#, c-format +msgid "Saving game %d... " +msgstr "Saving game %d... " + +#: src/move.c:667 src/move.c:674 src/move.c:1018 src/move.c:1052 +msgid " Bankruptcy Court " +msgstr " Bankruptcy Court " + +#: src/move.c:668 +#, c-format +msgid "%ls has been declared bankrupt by the Interstellar Trading Bank." +msgstr "%ls has been declared bankrupt by the Interstellar Trading Bank." + +#: src/move.c:675 +#, c-format +msgid "%ls has declared bankruptcy." +msgstr "%ls has declared bankruptcy." + +#: src/move.c:743 +msgid " New Company " +msgstr " New Company " + +#: src/move.c:744 +#, c-format +msgid "" +"A new company has been formed!\n" +"Its name is ^{%ls^}." +msgstr "" +"A new company has been formed!\n" +"Its name is ^{%ls^}." + +#: src/move.c:803 +#, c-format +msgid "" +"^{%ls^} has just merged into ^{%ls^}.\n" +"Please note the following transactions:\n" +msgstr "" +"^{%ls^} has just merged into ^{%ls^}.\n" +"Please note the following transactions:\n" + +#: src/move.c:809 +msgid " Company Merger " +msgstr " Company Merger " + +#. TRANSLATORS: "Old stock" refers to the company that has +#. just ceased existence due to a merger. +#. +#. Note that the "Old stock" and "New stock" labels MUST be +#. the same length and must contain a trailing space for the +#. display routines to work correctly. The maximum length of +#. each label is 36 characters. +#: src/move.c:829 +msgctxt "label" +msgid "Old stock: " +msgstr "Old stock: " + +#. TRANSLATORS: "New stock" refers to the company that has +#. absorbed another due to a merger. +#: src/move.c:840 +msgctxt "label" +msgid "New Stock: " +msgstr "New Stock: " + +#. TRANSLATORS: "Bonus" refers to the bonus cash amount paid to +#. each player after two companies merge. %ls is the currency +#. symbol in the current locale. The maximum column width is +#. 12 characters INCLUDING the currency symbol (see +#. MERGE_BONUS_COLS in src/intf.h). +#: src/move.c:854 +#, c-format +msgctxt "subtitle" +msgid "Bonus (%ls)" +msgstr "Bonus (%ls)" + +#. TRANSLATORS: "Total" refers to the total number of shares in +#. the new company after a merger. The maximum column width is +#. 8 characters (see MERGE_TOTAL_STOCK_COLS in src/intf.h). +#: src/move.c:859 +msgctxt "subtitle" +msgid "Total" +msgstr "Total" + +#. TRANSLATORS: "New" refers to how many (new) shares each +#. player receives in the surviving company after a merger. +#. The maximum column width is 8 characters (see +#. MERGE_NEW_STOCK_COLS in src/intf.h). +#: src/move.c:866 +msgctxt "subtitle" +msgid "New" +msgstr "New" + +#. TRANSLATORS: "Old" refers to how many shares each player had +#. in the company ceasing existence. The maximum column width +#. is 8 characters (see MERGE_OLD_STOCK_COLS in src/intf.h). +#: src/move.c:872 +msgctxt "subtitle" +msgid "Old" +msgstr "Old" + +#: src/move.c:1019 +#, c-format +msgid "" +"%ls has been declared bankrupt by the Interstellar Trading Bank.\n" +"\n" +"^{All assets have been taken to repay outstanding loans.^}" +msgstr "" +"%ls has been declared bankrupt by the Interstellar Trading Bank.\n" +"\n" +"^{All assets have been taken to repay outstanding loans.^}" + +#: src/move.c:1041 +#, c-format +msgid "" +"%ls has been declared bankrupt by the Interstellar Trading Bank.\n" +"\n" +"^{The Bank has agreed to pay stock holders ^}%.2f%%^{ of the share value on " +"each share owned.^}" +msgstr "" +"%ls has been declared bankrupt by the Interstellar Trading Bank.\n" +"\n" +"^{The Bank has agreed to pay stock holders ^}%.2f%%^{ of the share value on " +"each share owned.^}" + +#. TRANSLATORS: The label "Amount paid per share" +#. refers to payment made by the Interstellar +#. Trading Bank to each player upon company +#. bankruptcy. This label MUST be the same +#. length as "Old share value" and MUST have at +#. least one trailing space for the display +#. routines to work correctly. The maximum +#. length is 28 characters. +#: src/move.c:1069 +msgctxt "label" +msgid "Amount paid per share: " +msgstr "Amount paid per share: " + +#. TRANSLATORS: "Old share value" refers to the +#. share price of a company before it was forced +#. into bankruptcy by the Bank. This label must be +#. the same width as "Amount paid per share". +#: src/move.c:1077 +msgctxt "label" +msgid "Old share value: " +msgstr "Old share value: " + +#: src/move.c:1170 src/exch.c:320 +msgid " Interstellar Trading Bank " +msgstr " Interstellar Trading Bank " + +#: src/move.c:1172 +#, c-format +msgid "" +"Your debt has amounted to %N!\n" +"^{The Bank has impounded ^}%N^{ from your cash.^}" +msgstr "" +"Your debt has amounted to %N!\n" +"^{The Bank has impounded ^}%N^{ from your cash.^}" + +#: src/exch.c:98 +msgid " Interstellar Stock Exchange " +msgstr " Interstellar Stock Exchange " + +#. TRANSLATORS: "Shares left" is a two-line column +#. label in a table containing the number of shares +#. left to be purchased in any given company. The +#. maximum column width is 10 characters (see +#. STOCK_LEFT_COLS in src/intf.h). +#: src/exch.c:127 +msgctxt "subtitle" +msgid "" +"Shares\n" +"left" +msgstr "" +"Shares\n" +"left" + +#. TRANSLATORS: "Shares issued" is a two-line column +#. label in a table containing the number of shares +#. already sold (ie, bought by all players) in any +#. given company. The maximum column width is 10 +#. characters (see STOCK_ISSUED_COLS in src/intf.h). +#: src/exch.c:134 +msgctxt "subtitle" +msgid "" +"Shares\n" +"issued" +msgstr "" +"Shares\n" +"issued" + +#: src/exch.c:185 +msgid "^{<2>^} Display galaxy map" +msgstr "^{<2>^} Display galaxy map" + +#: src/exch.c:187 +msgid "^{<3>^} Visit the Trading Bank" +msgstr "^{<3>^} Visit the Trading Bank" + +#: src/exch.c:189 +msgid "^{<4>^} Exit the Stock Exchange" +msgstr "^{<4>^} Exit the Stock Exchange" + +#: src/exch.c:192 +msgid "Enter selection [^[Company letter^]/^{1^}-^{4^}]: " +msgstr "Enter selection [^[Company letter^]/^{1^}-^{4^}]: " + +#. TRANSLATORS: The "Total value", "Current cash", "Current +#. debt", "Interest rate" and "Credit limit" labels MUST all be +#. the same length (ie, right-padded with spaces as needed) and +#. must have at least one trailing space so that the display +#. routines work correctly. The maximum length of each label +#. is 36 characters. +#. +#. Note that some of these labels are used for both the Player +#. Status window and the Trading Bank window. +#: src/exch.c:350 +msgctxt "label" +msgid "Credit limit: " +msgstr "Credit limit: " + +#. TRANSLATORS: The "Borrow money", "Repay debt" and "Exit +#. from the Bank" menu options must all be the same length +#. (ie, padded with trailing spaces as required). The maximum +#. length is 72 characters. +#: src/exch.c:365 +msgid "^{<1>^} Borrow money " +msgstr "^{<1>^} Borrow money " + +#: src/exch.c:367 +msgid "^{<2>^} Repay debt " +msgstr "^{<2>^} Repay debt " + +#: src/exch.c:369 +msgid "^{<3>^} Exit from the Bank" +msgstr "^{<3>^} Exit from the Bank" + +#: src/exch.c:372 +msgid "Enter selection [^{1^}-^{3^}]: " +msgstr "Enter selection [^{1^}-^{3^}]: " + +#: src/exch.c:425 +msgid " Insufficient Credit Limit " +msgstr " Insufficient Credit Limit " + +#: src/exch.c:426 +msgid "The Bank will not lend you any more money." +msgstr "The Bank will not lend you any more money." + +#: src/exch.c:446 +msgid "How much do you wish to borrow? " +msgstr "How much do you wish to borrow? " + +#: src/exch.c:478 +msgid " No Debt " +msgstr " No Debt " + +#: src/exch.c:479 +msgid "You have no debt to repay." +msgstr "You have no debt to repay." + +#: src/exch.c:483 +msgid " No Cash " +msgstr " No Cash " + +#: src/exch.c:484 +msgid "You have no cash with which to repay the debt!" +msgstr "You have no cash with which to repay the debt!" + +#: src/exch.c:504 +msgid "How much do you wish to repay? " +msgstr "How much do you wish to repay? " + +#. TRANSLATORS: %ls represents the company name. +#: src/exch.c:580 +#, c-format +msgid " Stock Transaction in %ls " +msgstr " Stock Transaction in %ls " + +#. TRANSLATORS: "Shares issued" represents the number of +#. shares already sold by the company to all players. +#. +#. Note that the labels "Shares issued", "Shares left", +#. "Price per share" and "Return" must all be the same length +#. and must have at least one trailing space for the output +#. routines to work correctly. The maximum length of each +#. label is 22 characters. +#: src/exch.c:591 +msgctxt "label|Stock A" +msgid "Shares issued: " +msgstr "Shares issued: " + +#. TRANSLATORS: "Shares left" is the number of shares that are +#. left to be purchased in the current company. +#: src/exch.c:599 +msgctxt "label|Stock A" +msgid "Shares left: " +msgstr "Shares left: " + +#. TRANSLATORS: "Price per share" is the cost of each share in +#. the current company. +#: src/exch.c:606 +msgctxt "label|Stock A" +msgid "Price per share: " +msgstr "Price per share: " + +#. TRANSLATORS: "Return" is the share return as a percentage. +#: src/exch.c:612 +msgctxt "label|Stock A" +msgid "Return: " +msgstr "Return: " + +#. TRANSLATORS: "Current holdings" is the number of shares the +#. current player owns in this particular company. +#. +#. Note that the labels "Current holdings", "Percentage owned" +#. and "Current cash" MUST all be the same length and contain at +#. least one trailing space for the display routines to work +#. correctly. The maximum length of each label is 18 +#. characters. +#: src/exch.c:625 +msgctxt "label|Stock B" +msgid "Current holdings: " +msgstr "Current holdings: " + +#. TRANSLATORS: "Percentage owned" is the current player's +#. percentage ownership in this particular company. +#: src/exch.c:632 +msgctxt "label|Stock B" +msgid "Percentage owned: " +msgstr "Percentage owned: " + +#: src/exch.c:637 +msgctxt "label|Stock B" +msgid "Current cash: " +msgstr "Current cash: " + +#: src/exch.c:648 +msgid "^{<1>^} Buy stock from company" +msgstr "^{<1>^} Buy stock from company" + +#: src/exch.c:650 +msgid "^{<2>^} Sell stock back to company" +msgstr "^{<2>^} Sell stock back to company" + +#: src/exch.c:652 +msgid "^{<3>^} Bid company to issue more shares" +msgstr "^{<3>^} Bid company to issue more shares" + +#: src/exch.c:654 +msgid "^{<4>^} Exit to the Stock Exchange" +msgstr "^{<4>^} Exit to the Stock Exchange" + +#: src/exch.c:657 +msgid "Enter selection [^{1^}-^{4^}]: " +msgstr "Enter selection [^{1^}-^{4^}]: " + +#: src/exch.c:713 +msgid " No Shares Available " +msgstr " No Shares Available " + +#: src/exch.c:714 +msgid "No more shares are available for purchase." +msgstr "No more shares are available for purchase." + +#: src/exch.c:718 +msgid " Insufficient Cash " +msgstr " Insufficient Cash " + +#: src/exch.c:719 +msgid "" +"You do not have enough cash\n" +"to purchase additional shares." +msgstr "" +"You do not have enough cash\n" +"to purchase additional shares." + +#: src/exch.c:730 +#, c-format +msgid "You can purchase ^{one^} share." +msgid_plural "You can purchase up to ^{%'ld^} shares." +msgstr[0] "You can purchase ^{one^} share." +msgstr[1] "You can purchase up to ^{%'ld^} shares." + +#: src/exch.c:736 +msgid "How many shares do you wish to purchase? " +msgstr "How many shares do you wish to purchase? " + +#: src/exch.c:757 +msgid " No Shares " +msgstr " No Shares " + +#: src/exch.c:758 +msgid "You do not have any shares to sell." +msgstr "You do not have any shares to sell." + +#: src/exch.c:765 +#, c-format +msgid "You can sell ^{one^} share." +msgid_plural "You can sell up to ^{%'ld^} shares." +msgstr[0] "You can sell ^{one^} share." +msgstr[1] "You can sell up to ^{%'ld^} shares." + +#: src/exch.c:771 +msgid "How many shares do you wish to sell? " +msgstr "How many shares do you wish to sell? " + +#: src/exch.c:799 +msgid " No Shares Issued " +msgstr " No Shares Issued " + +#. TRANSLATORS: %ls represents the company name. +#: src/exch.c:801 +#, c-format +msgid "" +"%ls has refused\n" +"to issue more shares." +msgstr "" +"%ls has refused\n" +"to issue more shares." + +#: src/exch.c:806 +msgid " Shares Issued " +msgstr " Shares Issued " + +#. TRANSLATORS: %ls represents the company name. +#: src/exch.c:808 +#, c-format +msgid "" +"%ls has issued\n" +"^{one^} more share." +msgid_plural "" +"%ls has issued\n" +"^{%'ld^} more shares." +msgstr[0] "" +"%ls has issued\n" +"^{one^} more share." +msgstr[1] "" +"%ls has issued\n" +"^{%'ld^} more shares." + +#: src/fileio.c:55 src/fileio.c:92 src/fileio.c:131 src/fileio.c:381 +#, c-format +msgid "%s: missing field on line %d" +msgstr "%s: missing field on line %d" + +#: src/fileio.c:60 +#, c-format +msgid "%s: illegal field on line %d: `%s'" +msgstr "%s: illegal field on line %d: ‘%s’" + +#: src/fileio.c:64 +#, c-format +msgid "%s: illegal value on line %d: `%s'" +msgstr "%s: illegal value on line %d: ‘%s’" + +#: src/fileio.c:96 src/fileio.c:135 src/fileio.c:393 +#, c-format +msgid "%s: illegal value on line %d" +msgstr "%s: illegal value on line %d" + +#: src/fileio.c:103 +#, c-format +msgid "%s: illegal characters on line %d" +msgstr "%s: illegal characters on line %d" + +#: src/fileio.c:184 +#, c-format +msgid "%s: could not convert string" +msgstr "%s: could not convert string" + +#: src/fileio.c:255 +msgid " Game Not Found " +msgstr " Game Not Found " + +#: src/fileio.c:256 +#, c-format +msgid "Game %d has not been saved to disk." +msgstr "Game %d has not been saved to disk." + +#: src/fileio.c:263 +msgid " Game Not Loaded " +msgstr " Game Not Loaded " + +#: src/fileio.c:264 +#, c-format +msgid "" +"Game %d could not be loaded from disk.\n" +"\n" +"^{File %s: %s^}" +msgstr "" +"Game %d could not be loaded from disk.\n" +"\n" +"^{File %s: %s^}" + +#: src/fileio.c:316 +#, c-format +msgid "%s: missing header in game file" +msgstr "%s: missing header in game file" + +#: src/fileio.c:319 +#, c-format +msgid "%s: not a valid game file" +msgstr "%s: not a valid game file" + +#: src/fileio.c:322 src/fileio.c:329 +#, c-format +msgid "%s: missing subheader in game file" +msgstr "%s: missing subheader in game file" + +#: src/fileio.c:325 +#, c-format +msgid "%s: saved under a different version of Star Traders" +msgstr "%s: saved under a different version of Star Traders" + +#: src/fileio.c:332 +#, c-format +msgid "%s: saved under an incompatible character encoding" +msgstr "%s: saved under an incompatible character encoding" + +#: src/fileio.c:340 +#, c-format +msgid "%s: illegal or missing field on line %d" +msgstr "%s: illegal or missing field on line %d" + +#: src/fileio.c:384 +#, c-format +msgid "%s: illegal field on line %d" +msgstr "%s: illegal field on line %d" + +#: src/fileio.c:466 src/fileio.c:487 +msgid " Game Not Saved " +msgstr " Game Not Saved " + +#: src/fileio.c:467 +#, c-format +msgid "" +"Game %d could not be saved to disk.\n" +"\n" +"^{Directory %s: %s^}" +msgstr "" +"Game %d could not be saved to disk.\n" +"\n" +"^{Directory %s: %s^}" + +#: src/fileio.c:488 +#, c-format +msgid "" +"Game %d could not be saved to disk.\n" +"\n" +"^{File %s: %s^}" +msgstr "" +"Game %d could not be saved to disk.\n" +"\n" +"^{File %s: %s^}" + +#. TRANSLATORS: The help text for Star Traders is marked up using a +#. custom mark-up format NOT used anywhere else in the source code. +#. +#. Each string is a single page of text that is displayed in an area 76 +#. columns wide by 16 lines high. Each line is delimited by "\n". NO +#. word-wrapping is performed: you must place the "\n" characters in the +#. appropriate place. Ideally, each line within the string should be +#. also (manually) space-justified or centred. TAB characters and other +#. control codes must NOT be used. If a string starts with "@" as the +#. very first character, that string is ignored (as are all strings +#. following): this allows a variable number of help text pages (from +#. one to ten). Multibyte strings are handled correctly (even those +#. requiring shift sequences!). +#. +#. The ASCII circumflex accent character "^" switches to a different +#. character rendition (also called attributes), depending on the +#. character following the "^": +#. +#. ^^ - Print the circumflex accent (ASCII code U+005E) +#. ^N - Switch to using the normal character rendition +#. ^B - Switch to using the bold character rendition +#. ^H - Switch to using the highlight character rendition +#. ^K - Switch to using the keycode character rendition (such as used for "") +#. ^e - Switch to using the character rendition used for empty space +#. ^o - Switch to using the character rendition used for outposts +#. ^s - Switch to using the character rendition used for stars +#. ^c - Switch to using the character rendition used for companies +#. ^k - Switch to using the character rendition used for keyboard choices on the galaxy map +#. +#. The help text parsing routines also understand the following "value +#. escapes" introduced by the ASCII tilde character "~"; these act like +#. "%" conversion specifiers in printf(): +#. +#. ~~ - Print the tilde character (ASCII code U+007E) [*] +#. ~x - Print the width of the galaxy map (MAX_X) [**] +#. ~y - Print the height of the galaxy map (MAX_Y) [**] +#. ~m - Print the number of moves available (NUMBER_MOVES) [**] +#. ~c - Print the maximum number of companies that can be formed (MAX_COMPANIES) [*] +#. ~t - Prints the default number of turns in the game (DEFAULT_MAX_TURN) [**] +#. ~1 to ~9 - Print the keycode for the N-th choice of move [***] +#. ~M - Print the keycode for the last choice of move [***] +#. ~A to ~H - Print the character used to represent the company on the galaxy map [***] +#. ~. - Print the character used to represent empty space on the map [***] +#. ~+ - Print the character used to represent outposts on the map [***] +#. ~* - Print the character used to represent stars on the map [***] +#. +#. [*] Takes one character space (column space) in the output +#. [**] Takes two column spaces in the output +#. [***] Takes one or two column spaces in the output, depending on the +#. appropriate strings in the current PO file. +#. +#. Note that all keycodes and map representation characters use locale- +#. specific characters; double-width characters ARE supported. Note +#. also that the tilde value escapes do NOT change the current character +#. rendition: a circumflex accent escape is needed for that. For +#. example, to display the first choice of move as it would be shown on +#. the galaxy map, use something like "^k~1^N" (a six-character sequence +#. that would translate to just one character (or maybe two) in the +#. output text). +#. +#: src/help.c:103 +msgid "" +"^BStar Traders^N is a simple game of interstellar trading. The object of " +"the\n" +"game is to amass the greatest amount of wealth possible. This is done " +"by\n" +"creating interstellar shipping lanes, expanding them and buying shares " +"in\n" +"the companies controlling them. Shares appreciate in value as " +"company\n" +"operations expand. In addition, the return on each share (as a " +"percentage)\n" +"also changes. Players may also borrow from the Interstellar Trading Bank " +"to\n" +"finance additional purchases on the Stock Exchange.\n" +"\n" +"The map of the galaxy is represented by a ^B~x^N x ^B~y^N grid. A typical " +"section\n" +"of it may be:\n" +"\n" +" ^e ~. ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" +" ^e ~. ~. ~. ~. ~. ~. ~. ~. ~. ^N ^e ~. ^N represents ^Bempty " +"space^N,\n" +" ^e ~. ^s~*^e ~. ~. ~. ~. ~. ~. ~. ^N ^s ~* ^N represents a " +"^Bstar^N.\n" +" ^e ~. ~. ~. ~. ~. ~. ~. ^s~*^e ~. ^N\n" +" ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ~. ^N\n" +msgstr "" +"^BStar Traders^N is a simple game of interstellar trading. The object of " +"the\n" +"game is to amass the greatest amount of wealth possible. This is done " +"by\n" +"creating interstellar shipping lanes, expanding them and buying shares " +"in\n" +"the companies controlling them. Shares appreciate in value as " +"company\n" +"operations expand. In addition, the return on each share (as a " +"percentage)\n" +"also changes. Players may also borrow from the Interstellar Trading Bank " +"to\n" +"finance additional purchases on the Stock Exchange.\n" +"\n" +"The map of the galaxy is represented by a ^B~x^N x ^B~y^N grid. A typical " +"section\n" +"of it may be:\n" +"\n" +" ^e ~. ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" +" ^e ~. ~. ~. ~. ~. ~. ~. ~. ~. ^N ^e ~. ^N represents ^Bempty " +"space^N,\n" +" ^e ~. ^s~*^e ~. ~. ~. ~. ~. ~. ~. ^N ^s ~* ^N represents a " +"^Bstar^N.\n" +" ^e ~. ~. ~. ~. ~. ~. ~. ^s~*^e ~. ^N\n" +" ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ~. ^N\n" + +#: src/help.c:122 +msgid "" +"The computer selects ^B~m^N moves (labeled ^k~1^N to ^k~M^N) at random, " +"and places these\n" +"on the map. To select any of the highlighted positions, press that " +"letter.\n" +"For example, some of the moves on the map may be:\n" +"\n" +"\n" +" ^e ^k~1^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" +" ^e ~. ~. ~. ^k~3^e ~. ~. ~. ~. ~. ^N\n" +" ^e ~. ^s~*^e ~. ~. ~. ~. ^k~5^e ~. ~. ^N Moves ^k~1^N to " +"^k~5^N shown.\n" +" ^e ~. ^k~2^e ~. ~. ^k~4^e ~. ~. ^s~*^e ~. ^N\n" +" ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ~. ^N\n" +"\n" +"\n" +"Selecting a position that is ^Bnot^N next to a star (such as moves " +"^k~1^N, ^k~3^N or ^k~5^N)\n" +"will set up an ^Boutpost^N, not belonging to any company. Thus, if move " +"^k~3^N is\n" +"selected on the above map, a ^o ~+ ^N would be placed at that position.\n" +msgstr "" +"The computer selects ^B~m^N moves (labelled ^k~1^N to ^k~M^N) at random, " +"and places these\n" +"on the map. To select any of the highlighted positions, press that " +"letter.\n" +"For example, some of the moves on the map may be:\n" +"\n" +"\n" +" ^e ^k~1^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" +" ^e ~. ~. ~. ^k~3^e ~. ~. ~. ~. ~. ^N\n" +" ^e ~. ^s~*^e ~. ~. ~. ~. ^k~5^e ~. ~. ^N Moves ^k~1^N to " +"^k~5^N shown.\n" +" ^e ~. ^k~2^e ~. ~. ^k~4^e ~. ~. ^s~*^e ~. ^N\n" +" ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ~. ^N\n" +"\n" +"\n" +"Selecting a position that is ^Bnot^N next to a star (such as moves " +"^k~1^N, ^k~3^N or ^k~5^N)\n" +"will set up an ^Boutpost^N, not belonging to any company. Thus, if move " +"^k~3^N is\n" +"selected on the above map, a ^o ~+ ^N would be placed at that position.\n" + +#: src/help.c:140 +msgid "" +"If, on the other hand, a position next to a star (or another outpost) " +"is\n" +"selected, a ^Bcompany^N would be formed and its letter would appear on the " +"map.\n" +"As a reward for creating the company, you are granted the first five " +"shares.\n" +"Up to ^B~c^N companies can be created in this way.\n" +"\n" +"If a position next to an existing company is selected, the company " +"would\n" +"expand its operations by one square. This increases the cost of its " +"shares\n" +"and hence your return. Thus, if the map was as shown below, selecting " +"^k~6^N\n" +"or ^k~8^N increases Company ^B~B^N's shipping lane:\n" +"\n" +" ^e ^k~1^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" +" ^e ~. ~. ~. ^o~+^e ~. ~. ^k~6^e ~. ~. ^N\n" +" ^e ~. ^s~*^e ~. ~. ~. ~. ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~6^N " +"or ^k~8^N increases Company ^B~B^N.\n" +" ^e ~. ^k~2^e ~. ~. ^k~4^e ~. ~. ^s~*^e ^c~B^e ^N\n" +" ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ^k~8^e ^N\n" +msgstr "" +"If, on the other hand, a position next to a star (or another outpost) " +"is\n" +"selected, a ^Bcompany^N would be formed and its letter would appear on the " +"map.\n" +"As a reward for creating the company, you are granted the first five " +"shares.\n" +"Up to ^B~c^N companies can be created in this way.\n" +"\n" +"If a position next to an existing company is selected, the company " +"would\n" +"expand its operations by one square. This increases the cost of its " +"shares\n" +"and hence your return. Thus, if the map was as shown below, selecting " +"^k~6^N\n" +"or ^k~8^N increases Company ^B~B^N’s shipping lane:\n" +"\n" +" ^e ^k~1^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" +" ^e ~. ~. ~. ^o~+^e ~. ~. ^k~6^e ~. ~. ^N\n" +" ^e ~. ^s~*^e ~. ~. ~. ~. ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~6^N " +"or ^k~8^N increases Company ^B~B^N.\n" +" ^e ~. ^k~2^e ~. ~. ^k~4^e ~. ~. ^s~*^e ^c~B^e ^N\n" +" ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ^k~8^e ^N\n" + +#: src/help.c:158 +msgid "" +"Selecting positions next to stars increases the value of your stock by " +"about\n" +"five times as much as an extension not next to a star. Thus move ^k~6^N " +"should\n" +"be preferred to move ^k~8^N.\n" +"\n" +" ^e ^c~C^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" +" ^e ^k~1^e ^o~+^e ~. ^o~+^e ~. ~. ^k~6^e ~. ~. ^N\n" +" ^e ~. ^s~*^e ~. ~. ~. ~. ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~6^N " +"is preferred to ^k~8^N.\n" +" ^e ~. ^k~2^e ~. ~. ^k~4^e ~. ~. ^s~*^e ^c~B^e ^N\n" +" ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ^k~8^e ^N\n" +"\n" +"You may also expand any company by selecting positions next to " +"outposts.\n" +"Such outposts will be swallowed up by that company. Thus, move ^k~1^N " +"will\n" +"extend Company ^B~C^N by ^Btwo^N squares. As a bonus, outposts next to " +"stars are\n" +"more valuable: the company's share price will increase by a greater " +"amount\n" +"than it would for outposts not next to stars.\n" +msgstr "" +"Selecting positions next to stars increases the value of your stock by " +"about\n" +"five times as much as an extension not next to a star. Thus move ^k~6^N " +"should\n" +"be preferred to move ^k~8^N.\n" +"\n" +" ^e ^c~C^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" +" ^e ^k~1^e ^o~+^e ~. ^o~+^e ~. ~. ^k~6^e ~. ~. ^N\n" +" ^e ~. ^s~*^e ~. ~. ~. ~. ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~6^N " +"is preferred to ^k~8^N.\n" +" ^e ~. ^k~2^e ~. ~. ^k~4^e ~. ~. ^s~*^e ^c~B^e ^N\n" +" ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ^k~8^e ^N\n" +"\n" +"You may also expand any company by selecting positions next to " +"outposts.\n" +"Such outposts will be swallowed up by that company. Thus, move ^k~1^N " +"will\n" +"extend Company ^B~C^N by ^Btwo^N squares. As a bonus, outposts next to " +"stars are\n" +"more valuable: the company’s share price will increase by a greater " +"amount\n" +"than it would for outposts not next to stars.\n" + +#: src/help.c:176 +msgid "" +"If two companies are separated on the map by only one square, then they " +"can\n" +"be ^Bmerged^N into one company by selecting that position (if available). " +"For\n" +"example, on the map below, companies ^B~A^N and ^B~B^N can be merged by " +"selecting ^k~5^N.\n" +"When this occurs, the company with the greater assets value takes over " +"the\n" +"other one. Here, Company ^B~B^N might take over Company ^B~A^N. Company " +"^B~A^N ceases to\n" +"exist, although it may reappear as an entirely new company at a later " +"stage.\n" +"\n" +" ^e ^k~1^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" +" ^e ~. ~. ~. ^c~A^e ^c~A^e ^k~5^e ^c~B^e ~. ~. ^N\n" +" ^e ~. ^s~*^e ~. ~. ^c~A^e ~. ^c~B^e ^c~B^e ^c~B^e ^N Move " +"^k~5^N merges companies ^B~A^N and ^B~B^N.\n" +" ^e ~. ^k~2^e ~. ~. ~. ~. ~. ^s~*^e ^c~B^e ^N\n" +" ^e ~. ~. ~. ~. ^s~*^e ~. ^o~+^e ~. ~. ^N\n" +"\n" +"When companies merge, players are granted shares in the dominant " +"company\n" +"proportional to the amount owned in the old company. As well, a cash " +"bonus\n" +"is also paid, proportional to the percentage of the old company owned.\n" +msgstr "" +"If two companies are separated on the map by only one square, then they " +"can\n" +"be ^Bmerged^N into one company by selecting that position (if available). " +"For\n" +"example, on the map below, companies ^B~A^N and ^B~B^N can be merged by " +"selecting ^k~5^N.\n" +"When this occurs, the company with the greater assets value takes over " +"the\n" +"other one. Here, Company ^B~B^N might take over Company ^B~A^N. Company " +"^B~A^N ceases to\n" +"exist, although it may reappear as an entirely new company at a later " +"stage.\n" +"\n" +" ^e ^k~1^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" +" ^e ~. ~. ~. ^c~A^e ^c~A^e ^k~5^e ^c~B^e ~. ~. ^N\n" +" ^e ~. ^s~*^e ~. ~. ^c~A^e ~. ^c~B^e ^c~B^e ^c~B^e ^N Move " +"^k~5^N merges companies ^B~A^N and ^B~B^N.\n" +" ^e ~. ^k~2^e ~. ~. ~. ~. ~. ^s~*^e ^c~B^e ^N\n" +" ^e ~. ~. ~. ~. ^s~*^e ~. ^o~+^e ~. ~. ^N\n" +"\n" +"When companies merge, players are granted shares in the dominant " +"company\n" +"proportional to the amount owned in the old company. As well, a cash " +"bonus\n" +"is also paid, proportional to the percentage of the old company owned.\n" + +#: src/help.c:195 +msgid "" +"Once you select your move, you enter the ^BInterstellar Stock Exchange^N. " +"Here\n" +"you may purchase shares, sell them, borrow from the Trading Bank or " +"repay\n" +"some of your debt (if applicable). Note that each company issues a " +"limited\n" +"number of shares -- you cannot go on buying for ever! You may, however, " +"bid\n" +"for more shares to be issued. You have a better chance of succeeding if " +"you\n" +"own a larger proportion of the company.\n" +"\n" +"The game usually ends after ^B~t^N turns. However, you may end the game " +"sooner\n" +"by pressing ^K^N when asked to select a move. As well, " +"individual\n" +"players can declare themselves bankrupt at any time. If your debt is " +"large\n" +"enough, the Bank may do this for you! If you do not complete your game " +"in\n" +"the time you have available, you may save the game and continue it later.\n" +"\n" +"\n" +"The ^Bwinner of the game^N is the person with the greatest net worth " +"(total\n" +"value of cash, stock and debt). ^HGood luck^N and may the best person win!\n" +msgstr "" +"Once you select your move, you enter the ^BInterstellar Stock Exchange^N. " +"Here\n" +"you may purchase shares, sell them, borrow from the Trading Bank or " +"repay\n" +"some of your debt (if applicable). Note that each company issues a " +"limited\n" +"number of shares -- you cannot go on buying for ever! You may, however, " +"bid\n" +"for more shares to be issued. You have a better chance of succeeding if " +"you\n" +"own a larger proportion of the company.\n" +"\n" +"The game usually ends after ^B~t^N turns. However, you may end the game " +"sooner\n" +"by pressing ^K^N when asked to select a move. As well, " +"individual\n" +"players can declare themselves bankrupt at any time. If your debt is " +"large\n" +"enough, the Bank may do this for you! If you do not complete your game " +"in\n" +"the time you have available, you may save the game and continue it later.\n" +"\n" +"\n" +"The ^Bwinner of the game^N is the person with the greatest net worth " +"(total\n" +"value of cash, stock and debt). ^HGood luck^N and may the best person win!\n" + +#: src/help.c:215 +msgid "@ Help text, page 7" +msgstr "@ Help text, page 7" + +#: src/help.c:216 +msgid "@ Help text, page 8" +msgstr "@ Help text, page 8" + +#: src/help.c:217 +msgid "@ Help text, page 9" +msgstr "@ Help text, page 9" + +#: src/help.c:218 +msgid "@ Help text, page 10" +msgstr "@ Help text, page 10" + +#: src/help.c:270 +msgid " How to Play " +msgstr " How to Play " + +#: src/help.c:272 +#, c-format +msgid "Page %d of %d" +msgstr "Page %d of %d" + +#. TRANSLATORS: The reason the user is not asked "Press any +#. key to continue" is historical: many, many people used to +#. ask "where is the key?" :-) +#: src/help.c:473 src/intf.c:3022 +msgid "[ Press to continue ] " +msgstr "[ Press to continue ] " + +#. TRANSLATORS: The specific use of and +#. is not essential: you can use , +#. , , or instead of +#. , and almost any other key instead of +#. (other than , , , , +#. or <\>). +#: src/help.c:480 +msgid "[ Press to continue or for the previous page ] " +msgstr "[ Press to continue or for the previous page ] " + +#: src/intf.c:110 +#, c-format +msgid "%s: string has incorrect format: `%s'" +msgstr "%s: string has incorrect format: ‘%s’" + +#: src/intf.c:126 +#, c-format +msgid "%s: character has illegal width: `%lc'" +msgstr "%s: character has illegal width: ‘%lc’" + +#: src/intf.c:434 +#, c-format +msgid "terminal size is too small (%d x %d required)" +msgstr "terminal size is too small (%d x %d required)" + +#: src/intf.c:610 +msgid "Star Traders" +msgstr "Star Traders" + +#: src/intf.c:1262 +msgid "mkchstr_conv: NUL" +msgstr "mkchstr_conv: NUL" + +#: src/intf.c:1565 +#, c-format +msgid "mkchstr: `%s'" +msgstr "mkchstr: ‘%s’" + +#: src/intf.c:2022 src/intf.c:2067 +#, c-format +msgid "gettxline: illegal character in string: `%ls'" +msgstr "gettxline: illegal character in string: ‘%ls’" + +#. TRANSLATORS: The strings with msgctxt "input|Yes" and +#. "input|No" contain the keycodes used to determine whether a +#. user is answering "Yes" or "No" in response to some question. +#. Both upper and lower-case versions should be present. +#: src/intf.c:2939 +msgctxt "input|Yes" +msgid "Yy" +msgstr "Yy" + +#: src/intf.c:2941 +msgctxt "input|No" +msgid "Nn" +msgstr "Nn" + +#. TRANSLATORS: The strings "Yes" and "No" are printed as a +#. response to user input in answer to questions like "Are you +#. sure? [Y/N] " +#: src/intf.c:2992 +msgctxt "answer" +msgid "Yes" +msgstr "Yes" + +#: src/intf.c:2994 +msgctxt "answer" +msgid "No" +msgstr "No" + +#: src/utils.c:199 src/utils.c:220 +#, c-format +msgid "%s: " +msgstr "%s: " + +#: src/utils.c:225 +msgid ": " +msgstr ": " + +#: src/utils.c:238 +msgid "out of memory" +msgstr "out of memory" + +#: src/utils.c:571 +#, c-format +msgid "xmbstowcs: `%s'" +msgstr "xmbstowcs: ‘%s’" + +#: src/utils.c:611 +msgid "xwcrtomb: NUL" +msgstr "xwcrtomb: NUL" + +#: src/utils.c:616 +#, c-format +msgid "xwcrtomb: `%lc'" +msgstr "xwcrtomb: ‘%lc’" + +#: lib/getopt.c:547 lib/getopt.c:576 +#, c-format +msgid "%s: option '%s' is ambiguous; possibilities:" +msgstr "%s: option ‘%s’ is ambiguous; possibilities:" + +#: lib/getopt.c:624 lib/getopt.c:628 +#, c-format +msgid "%s: option '--%s' doesn't allow an argument\n" +msgstr "%s: option ‘--%s’ doesn’t allow an argument\n" + +#: lib/getopt.c:637 lib/getopt.c:642 +#, c-format +msgid "%s: option '%c%s' doesn't allow an argument\n" +msgstr "%s: option ‘%c%s’ doesn’t allow an argument\n" + +#: lib/getopt.c:685 lib/getopt.c:704 +#, c-format +msgid "%s: option '--%s' requires an argument\n" +msgstr "%s: option ‘--%s’ requires an argument\n" + +#: lib/getopt.c:742 lib/getopt.c:745 +#, c-format +msgid "%s: unrecognized option '--%s'\n" +msgstr "%s: unrecognized option ‘--%s’\n" + +#: lib/getopt.c:753 lib/getopt.c:756 +#, c-format +msgid "%s: unrecognized option '%c%s'\n" +msgstr "%s: unrecognized option ‘%c%s’\n" + +#: lib/getopt.c:805 lib/getopt.c:808 +#, c-format +msgid "%s: invalid option -- '%c'\n" +msgstr "%s: invalid option -- ‘%c’\n" + +#: lib/getopt.c:861 lib/getopt.c:878 lib/getopt.c:1088 lib/getopt.c:1106 +#, c-format +msgid "%s: option requires an argument -- '%c'\n" +msgstr "%s: option requires an argument -- ‘%c’\n" + +#: lib/getopt.c:934 lib/getopt.c:950 +#, c-format +msgid "%s: option '-W %s' is ambiguous\n" +msgstr "%s: option ‘-W %s’ is ambiguous\n" + +#: lib/getopt.c:974 lib/getopt.c:992 +#, c-format +msgid "%s: option '-W %s' doesn't allow an argument\n" +msgstr "%s: option ‘-W %s’ doesn’t allow an argument\n" + +#: lib/getopt.c:1013 lib/getopt.c:1031 +#, c-format +msgid "%s: option '-W %s' requires an argument\n" +msgstr "%s: option ‘-W %s’ requires an argument\n" diff --git a/po/en_GB.po b/po/en_GB.po new file mode 100644 index 0000000..c9fdcd7 --- /dev/null +++ b/po/en_GB.po @@ -0,0 +1,1662 @@ +# ************************************************************************* +# * * +# * English (British) Translations for Star Traders * +# * Copyright (C) 1990-2011, John Zaitseff * +# * * +# ************************************************************************* +# +# This file is distributed under the same licence as Star Traders. +# +# Contributors: +# John Zaitseff , 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: trader 7.2\n" +"Report-Msgid-Bugs-To: J.Zaitseff@zap.org.au\n" +"POT-Creation-Date: 2011-08-28 14:55+1000\n" +"PO-Revision-Date: 2011-08-28 15:59+1000\n" +"Last-Translator: John Zaitseff \n" +"Language-Team: English (British)\n" +"Language: en_GB\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: src/trader.c:235 +#, c-format +msgid "%s: invalid value for --max-turn: `%s'\n" +msgstr "%s: invalid value for --max-turn: ‘%s’\n" + +#: src/trader.c:251 +#, c-format +msgid "%s: invalid operand `%s'\n" +msgstr "%s: invalid operand ‘%s’\n" + +#: src/trader.c:260 +#, c-format +msgid "%s: invalid game number `%s'\n" +msgstr "%s: invalid game number ‘%s’\n" + +#: src/trader.c:269 +#, c-format +msgid "%s: extra operand `%s'\n" +msgstr "%s: extra operand ‘%s’\n" + +#. TRANSLATORS: "John Zaitseff" [IPA d͡ʒɒn ˈzaɪ̯t͡səf] is the proper +#. name of the author. The IPA pronunciation in this comment is in +#. UTF-8 encoding. +#: src/trader.c:284 +#, c-format +msgid "" +"Star Traders (%s) %s\n" +"Copyright (C) %s, John Zaitseff.\n" +"\n" +"Star Traders is a simple game of interstellar trading, where the object\n" +"of the game is to create companies, buy and sell shares, borrow and repay\n" +"money, in order to become the wealthiest player (the winner).\n" +"\n" +"This program is free software that is distributed under the terms of the\n" +"GNU General Public License, version 3 or later. You are welcome to\n" +"modify and/or distribute it under certain conditions. This program has\n" +"NO WARRANTY, to the extent permitted by law; see the License for details.\n" +msgstr "" +"Star Traders (%s) %s\n" +"Copyright (C) %s, John Zaitseff.\n" +"\n" +"Star Traders is a simple game of interstellar trading, where the object\n" +"of the game is to create companies, buy and sell shares, borrow and repay\n" +"money, in order to become the wealthiest player (the winner).\n" +"\n" +"This program is free software that is distributed under the terms of the\n" +"GNU General Public License, version 3 or later. You are welcome to\n" +"modify and/or distribute it under certain conditions. This program has\n" +"NO WARRANTY, to the extent permitted by law; see the License for details.\n" + +#: src/trader.c:308 +#, c-format +msgid "%s: Try `%s --help' for more information.\n" +msgstr "%s: Try ‘%s --help’ for more information.\n" + +#: src/trader.c:311 +#, c-format +msgid "Usage: %s [OPTION ...] [GAME]\n" +msgstr "Usage: %s [OPTION ...] [GAME]\n" + +#: src/trader.c:312 +#, c-format +msgid "" +"Play Star Traders, a simple game of interstellar trading.\n" +"\n" +msgstr "" +"Play Star Traders, a simple game of interstellar trading.\n" +"\n" + +#: src/trader.c:315 +#, c-format +msgid "" +"Options:\n" +" -V, --version output version information and exit\n" +" -h, --help display this help and exit\n" +" --no-color don't use color for displaying text\n" +" --max-turn=NUM set the number of turns to NUM\n" +"\n" +msgstr "" +"Options:\n" +" -V, --version output version information and exit\n" +" -h, --help display this help and exit\n" +" --no-colour don’t use colour for displaying text\n" +" --max-turn=NUM set the number of turns to NUM\n" +"\n" + +#: src/trader.c:322 +#, c-format +msgid "" +"If GAME is specified as a number between 1 and 9, load and continue\n" +"playing that game. If GAME is not specified, start a new game.\n" +"\n" +msgstr "" +"If GAME is specified as a number between 1 and 9, load and continue\n" +"playing that game. If GAME is not specified, start a new game.\n" +"\n" + +#. TRANSLATORS: The first %s is the proper name of the package +#. author, John Zaitseff [IPA d͡ʒɒn ˈzaɪ̯t͡səf]; the second %s is +#. the e-mail address for reporting bugs. Please add ANOTHER +#. line with the (translated) text "Report translation bugs to +#.
\n", with ADDRESS replaced with either an e-mail +#. address or web URL for reporting bugs in your translation. +#: src/trader.c:334 +#, c-format +msgid "Report bugs to %s <%s>.\n" +msgstr "Report bugs to %s <%s>.\n" + +#. TRANSLATORS: %s is the e-mail address for reporting bugs. As +#. with the previous string, please add ANOTHER line with the +#. (translated) text "Report translation bugs to
\n", +#. with ADDRESS replaced with either an e-mail address or web URL +#. for reporting bugs in your translation. +#: src/trader.c:341 +#, c-format +msgid "Report bugs to <%s>.\n" +msgstr "Report bugs to <%s>.\n" + +#. TRANSLATORS: The first %s is for packagers and may be +#. something like "Debian". +#: src/trader.c:346 +#, c-format +msgid "Report %s bugs to <%s>.\n" +msgstr "Report %s bugs to <%s>.\n" + +#: src/trader.c:349 +#, c-format +msgid "Star Traders home page: <%s>.\n" +msgstr "Star Traders home page: <%s>.\n" + +#. TRANSLATORS: The eight company names do NOT have to be literal +#. translations of the English names. In fact, if possible, the +#. names should start with successive letters of your alphabet (in +#. English, for example, "A" to "H"). No company name should be more +#. than 24 characters (column positions, to be precise) long. +#: src/globals.c:46 +msgid "Altair Starways" +msgstr "Altair Starways" + +#: src/globals.c:47 +msgid "Betelgeuse, Ltd" +msgstr "Betelgeuse, Ltd" + +#: src/globals.c:48 +msgid "Capella Freight Co" +msgstr "Capella Freight Co" + +#: src/globals.c:49 +msgid "Denebola Shippers" +msgstr "Denebola Shippers" + +#: src/globals.c:50 +msgid "Eridani Expediters" +msgstr "Eridani Expediters" + +#: src/globals.c:51 +msgid "Fornax Express" +msgstr "Fornax Express" + +#: src/globals.c:52 +msgid "Gemeni Inc" +msgstr "Gemeni Inc" + +#: src/globals.c:53 +msgid "Hercules and Co" +msgstr "Hercules and Co" + +#. TRANSLATORS: This string specifies the keycodes (keyboard input +#. codes) used to enter the Stock Transaction window for each +#. company. There must be exactly eight characters, one for each +#. company in order, before the ASCII vertical line "|"; these must +#. be EITHER all in upper-case or all in lower-case. If at all +#. possible, these should be successive letters in your alphabet (in +#. English, "A" to "H"). Do NOT use digits or control characters. +#. Do not change or translate anything after the vertical line. +#: src/globals.c:67 +msgid "ABCDEFGH|input|Companies" +msgstr "ABCDEFGH|input|Companies" + +#. TRANSLATORS: This string specifies the keycodes used to select a +#. game move. There must be exactly 20 characters, one for each +#. move, before the ASCII vertical line "|"; these must be EITHER all +#. in upper-case or all in lower-case. If at all possible, these +#. should be successive letters in your alphabet. Do NOT use digits +#. or control characters. Do not change or translate anything after +#. the vertical line. +#: src/globals.c:79 +msgid "ABCDEFGHIJKLMNOPQRST|input|GameMoves" +msgstr "ABCDEFGHIJKLMNOPQRST|input|GameMoves" + +#. TRANSLATORS: This string is used to display the galaxy map to +#. screen. There must be exactly 11 characters before the ASCII +#. vertical line. The first ("." in English) is used for empty +#. space, the second ("+") for outposts, the third ("*") for stars, +#. the remaining for the eight companies. Do not change or translate +#. anything after the vertical line. +#: src/globals.c:90 +msgid ".+*ABCDEFGH|output|MapVals" +msgstr ".+*ABCDEFGH|output|MapVals" + +#. TRANSLATORS: This string is used to display the game moves +#. (choices). There must be exactly 20 characters (NUMBER_MOVES) +#. before the ASCII vertical line. The first character corresponds +#. to the first character in the "input|GameMoves" string, and so on. +#. Do not change or translate anything after the vertical line. +#: src/globals.c:100 +msgid "abcdefghijklmnopqrst|output|GameMoves" +msgstr "abcdefghijklmnopqrst|output|GameMoves" + +#. TRANSLATORS: The ordinal strings "1st" to "8th" are used in the +#. Game Winner dialog box at the end of the game. If ordinals depend +#. on the gender of the player, it may be simpler to list cardinal +#. numbers instead (eg, "No. 1"). Up to five characters are allowed +#. (see ORDINAL_COLS in src/intf.h). +#: src/globals.c:111 +msgid "1st" +msgstr "1st" + +#: src/globals.c:112 +msgid "2nd" +msgstr "2nd" + +#: src/globals.c:113 +msgid "3rd" +msgstr "3rd" + +#: src/globals.c:114 +msgid "4th" +msgstr "4th" + +#: src/globals.c:115 +msgid "5th" +msgstr "5th" + +#: src/globals.c:116 +msgid "6th" +msgstr "6th" + +#: src/globals.c:117 +msgid "7th" +msgstr "7th" + +#: src/globals.c:118 +msgid "8th" +msgstr "8th" + +#: src/game.c:117 src/game.c:152 +#, c-format +msgid "Loading game %d... " +msgstr "Loading game %d... " + +#: src/game.c:226 +msgid " First Player " +msgstr " First Player " + +#: src/game.c:227 +#, c-format +msgid "The first player to go is ^{%ls^}." +msgstr "The first player to go is ^{%ls^}." + +#. TRANSLATORS: The keycode should be modified to +#. match that (or those) specified with msgctxt +#. "input|ContinueGame". +#: src/game.c:259 +#, c-format +msgid "Enter number of players [^{1^}-^{%d^}] or ^{^} to continue a game: " +msgstr "Enter number of players [^{1^}-^{%d^}] or ^{^} to continue a game: " + +#. TRANSLATORS: This string specifies the keycodes used to continue a +#. game; these must NOT contain any numeric digit from 1 to 9. The +#. first character (keyboard input code) is used to print the user's +#. response if one of those keys is pressed. Both upper and +#. lower-case versions should be present. +#: src/game.c:276 +msgctxt "input|ContinueGame" +msgid "Cc" +msgstr "Cc" + +#: src/game.c:341 src/move.c:380 +msgid "Enter game number [^{1^}-^{9^}] or ^{^} to cancel: " +msgstr "Enter game number [^{1^}-^{9^}] or ^{^} to cancel: " + +#: src/game.c:406 +msgid "Please enter your name: " +msgstr "Please enter your name: " + +#: src/game.c:425 +msgid "Do you need any instructions? [^{Y^}/^{N^}] " +msgstr "Do you need any instructions? [^{Y^}/^{N^}] " + +#: src/game.c:443 +msgid " Enter Player Names " +msgstr " Enter Player Names " + +#: src/game.c:451 +#, c-format, range: 1..8 +msgid "Player %d: " +msgstr "Player %d: " + +#: src/game.c:529 +msgid "Does any player need instructions? [^{Y^}/^{N^}] " +msgstr "Does any player need instructions? [^{Y^}/^{N^}] " + +#: src/game.c:563 +msgid " Game Over " +msgstr " Game Over " + +#: src/game.c:564 +#, c-format +msgid "The game is over after one turn." +msgid_plural "The game is over after %d turns." +msgstr[0] "The game is over after one turn." +msgstr[1] "The game is over after %d turns." + +#: src/game.c:575 +msgid " Total Value " +msgstr " Total Value " + +#: src/game.c:577 +#, c-format +msgid "Your total value was ^{%N^}." +msgstr "Your total value was ^{%N^}." + +#: src/game.c:588 +#, c-format +msgid "" +"The winner is ^{%ls^}\n" +"who is ^[*** BANKRUPT ***^]" +msgstr "" +"The winner is ^{%ls^}\n" +"who is ^[*** BANKRUPT ***^]" + +#: src/game.c:591 +#, c-format +msgid "" +"The winner is ^{%ls^}\n" +"with a value of ^{%N^}." +msgstr "" +"The winner is ^{%ls^}\n" +"with a value of ^{%N^}." + +#: src/game.c:597 +msgid " Game Winner " +msgstr " Game Winner " + +#. TRANSLATORS: "Player" is used as a column title in a +#. table containing all player names. +#: src/game.c:606 src/move.c:847 +msgctxt "subtitle" +msgid "Player" +msgstr "Player" + +#. TRANSLATORS: "Total Value" refers to the total worth +#. (shares, cash and debt) of any given player. %ls is the +#. currency symbol of the current locale. +#: src/game.c:611 +#, c-format +msgctxt "subtitle" +msgid "Total Value (%ls)" +msgstr "Total Value (%ls)" + +#: src/game.c:645 src/game.c:695 src/exch.c:100 +#, c-format +msgid "Player: ^{%ls^}" +msgstr "Player: ^{%ls^}" + +#: src/game.c:648 +#, c-format +msgid " Turn: ^{%d^} " +msgstr " Turn: ^{%d^} " + +#: src/game.c:649 +msgid " ^[*** Last Turn ***^] " +msgstr " ^[*** Last Turn ***^] " + +#: src/game.c:693 +msgid " Stock Portfolio " +msgstr " Stock Portfolio " + +#. TRANSLATORS: The current player is bankrupt (has no +#. shares or cash, ie, whose total value is zero) +#: src/game.c:702 +msgid "^[* * * B A N K R U P T * * *^]" +msgstr "^[* * * B A N K R U P T * * *^]" + +#: src/game.c:717 src/exch.c:112 +msgid "No companies on the map" +msgstr "No companies on the map" + +#. TRANSLATORS: "Company" is a two-line column label in +#. a table containing a list of companies. +#: src/game.c:725 src/exch.c:120 +msgctxt "subtitle" +msgid "" +"\n" +"Company" +msgstr "" +"\n" +"Company" + +#. TRANSLATORS: "Ownership" is a two-line column label +#. in a table containing the current player's +#. percentage ownership in any given company. The +#. maximum column width is 10 characters (see +#. OWNERSHIP_COLS in src/intf.h). +#: src/game.c:732 +#, c-format +msgctxt "subtitle" +msgid "" +"Ownership\n" +"(%%)" +msgstr "" +"Ownership\n" +"(%%)" + +#. TRANSLATORS: "Holdings" is a two-line column label +#. in a table containing the number of shares the +#. current player owns in any given company. The +#. maximum column width is 10 characters (see +#. STOCK_OWNED_COLS in src/intf.h). +#: src/game.c:739 +msgctxt "subtitle" +msgid "" +"Holdings\n" +"(shares)" +msgstr "" +"Holdings\n" +"(shares)" + +#. TRANSLATORS: "Return" is a two-line column label in +#. a table containing the share return as a percentage +#. in any given company. The maximum column width is +#. 10 characters (see SHARE_RETURN_COLS in src/intf.h). +#: src/game.c:746 src/exch.c:141 +#, c-format +msgctxt "subtitle" +msgid "" +"Return\n" +"(%%)" +msgstr "" +"Return\n" +"(%%)" + +#. TRANSLATORS: "Price per share" is a two-line column +#. label in a table containing the price per share in +#. any given company. %ls is the currency symbol in +#. the current locale. The maximum column width is 12 +#. characters INCLUDING the currency symbol (see +#. SHARE_PRICE_COLS in src/intf.h). +#: src/game.c:755 src/exch.c:150 +#, c-format +msgctxt "subtitle" +msgid "" +"Price per\n" +"share (%ls)" +msgstr "" +"Price per\n" +"share (%ls)" + +#. TRANSLATORS: The "Total value", "Current cash", +#. "Current debt" and "Interest rate" labels MUST all be +#. the same length (ie, right-padded with spaces as +#. needed) and must have at least one trailing space so +#. that the display routines work correctly. The maximum +#. length of each label is 36 characters. +#. +#. Note that some of these labels are used for both the +#. Player Status window and the Trading Bank window. +#: src/game.c:796 +msgctxt "label" +msgid "Total value: " +msgstr "Total value: " + +#: src/game.c:800 src/exch.c:323 +msgctxt "label" +msgid "Current cash: " +msgstr "Current cash: " + +#: src/game.c:807 src/exch.c:331 +msgctxt "label" +msgid "Current debt: " +msgstr "Current debt: " + +#: src/game.c:813 src/exch.c:336 +msgctxt "label" +msgid "Interest rate: " +msgstr "Interest rate: " + +#: src/move.c:235 src/exch.c:183 +msgid "^{<1>^} Display stock portfolio" +msgstr "^{<1>^} Display stock portfolio" + +#: src/move.c:237 +msgid "^{<2>^} Declare bankruptcy" +msgstr "^{<2>^} Declare bankruptcy" + +#: src/move.c:239 +msgid "^{<3>^} Save and end the game" +msgstr "^{<3>^} Save and end the game" + +#: src/move.c:241 +msgid "^{^} Quit the game" +msgstr "^{^} Quit the game" + +#: src/move.c:245 +#, c-format +msgid "Select move [^[%lc^]-^[%lc^]/^{1^}-^{3^}/^{^}]: " +msgstr "Select move [^[%lc^]-^[%lc^]/^{1^}-^{3^}/^{^}]: " + +#. TRANSLATORS: "Move" refers to the choice of +#. moves made by the current player (out of a +#. selection of 20 moves). +#: src/move.c:277 +#, c-format +msgid "Move ^{%lc^}" +msgstr "Move ^{%lc^}" + +#: src/move.c:297 +msgid "^{<2>^} (Declare bankruptcy)" +msgstr "^{<2>^} (Declare bankruptcy)" + +#: src/move.c:306 +msgid "^{<3>^} (Save and end the game)" +msgstr "^{<3>^} (Save and end the game)" + +#: src/move.c:327 +msgid "^{^} (Quit the game)" +msgstr "^{^} (Quit the game)" + +#: src/move.c:342 +msgid "Are you sure? [^{Y^}/^{N^}] " +msgstr "Are you sure? [^{Y^}/^{N^}] " + +#: src/move.c:359 src/move.c:437 +#, c-format +msgid "Saving game %d... " +msgstr "Saving game %d... " + +#: src/move.c:667 src/move.c:674 src/move.c:1018 src/move.c:1052 +msgid " Bankruptcy Court " +msgstr " Bankruptcy Court " + +#: src/move.c:668 +#, c-format +msgid "%ls has been declared bankrupt by the Interstellar Trading Bank." +msgstr "%ls has been declared bankrupt by the Interstellar Trading Bank." + +#: src/move.c:675 +#, c-format +msgid "%ls has declared bankruptcy." +msgstr "%ls has declared bankruptcy." + +#: src/move.c:743 +msgid " New Company " +msgstr " New Company " + +#: src/move.c:744 +#, c-format +msgid "" +"A new company has been formed!\n" +"Its name is ^{%ls^}." +msgstr "" +"A new company has been formed!\n" +"Its name is ^{%ls^}." + +#: src/move.c:803 +#, c-format +msgid "" +"^{%ls^} has just merged into ^{%ls^}.\n" +"Please note the following transactions:\n" +msgstr "" +"^{%ls^} has just merged into ^{%ls^}.\n" +"Please note the following transactions:\n" + +#: src/move.c:809 +msgid " Company Merger " +msgstr " Company Merger " + +#. TRANSLATORS: "Old stock" refers to the company that has +#. just ceased existence due to a merger. +#. +#. Note that the "Old stock" and "New stock" labels MUST be +#. the same length and must contain a trailing space for the +#. display routines to work correctly. The maximum length of +#. each label is 36 characters. +#: src/move.c:829 +msgctxt "label" +msgid "Old stock: " +msgstr "Old stock: " + +#. TRANSLATORS: "New stock" refers to the company that has +#. absorbed another due to a merger. +#: src/move.c:840 +msgctxt "label" +msgid "New Stock: " +msgstr "New Stock: " + +#. TRANSLATORS: "Bonus" refers to the bonus cash amount paid to +#. each player after two companies merge. %ls is the currency +#. symbol in the current locale. The maximum column width is +#. 12 characters INCLUDING the currency symbol (see +#. MERGE_BONUS_COLS in src/intf.h). +#: src/move.c:854 +#, c-format +msgctxt "subtitle" +msgid "Bonus (%ls)" +msgstr "Bonus (%ls)" + +#. TRANSLATORS: "Total" refers to the total number of shares in +#. the new company after a merger. The maximum column width is +#. 8 characters (see MERGE_TOTAL_STOCK_COLS in src/intf.h). +#: src/move.c:859 +msgctxt "subtitle" +msgid "Total" +msgstr "Total" + +#. TRANSLATORS: "New" refers to how many (new) shares each +#. player receives in the surviving company after a merger. +#. The maximum column width is 8 characters (see +#. MERGE_NEW_STOCK_COLS in src/intf.h). +#: src/move.c:866 +msgctxt "subtitle" +msgid "New" +msgstr "New" + +#. TRANSLATORS: "Old" refers to how many shares each player had +#. in the company ceasing existence. The maximum column width +#. is 8 characters (see MERGE_OLD_STOCK_COLS in src/intf.h). +#: src/move.c:872 +msgctxt "subtitle" +msgid "Old" +msgstr "Old" + +#: src/move.c:1019 +#, c-format +msgid "" +"%ls has been declared bankrupt by the Interstellar Trading Bank.\n" +"\n" +"^{All assets have been taken to repay outstanding loans.^}" +msgstr "" +"%ls has been declared bankrupt by the Interstellar Trading Bank.\n" +"\n" +"^{All assets have been taken to repay outstanding loans.^}" + +#: src/move.c:1041 +#, c-format +msgid "" +"%ls has been declared bankrupt by the Interstellar Trading Bank.\n" +"\n" +"^{The Bank has agreed to pay stock holders ^}%.2f%%^{ of the share value on " +"each share owned.^}" +msgstr "" +"%ls has been declared bankrupt by the Interstellar Trading Bank.\n" +"\n" +"^{The Bank has agreed to pay stock holders ^}%.2f%%^{ of the share value on " +"each share owned.^}" + +#. TRANSLATORS: The label "Amount paid per share" +#. refers to payment made by the Interstellar +#. Trading Bank to each player upon company +#. bankruptcy. This label MUST be the same +#. length as "Old share value" and MUST have at +#. least one trailing space for the display +#. routines to work correctly. The maximum +#. length is 28 characters. +#: src/move.c:1069 +msgctxt "label" +msgid "Amount paid per share: " +msgstr "Amount paid per share: " + +#. TRANSLATORS: "Old share value" refers to the +#. share price of a company before it was forced +#. into bankruptcy by the Bank. This label must be +#. the same width as "Amount paid per share". +#: src/move.c:1077 +msgctxt "label" +msgid "Old share value: " +msgstr "Old share value: " + +#: src/move.c:1170 src/exch.c:320 +msgid " Interstellar Trading Bank " +msgstr " Interstellar Trading Bank " + +#: src/move.c:1172 +#, c-format +msgid "" +"Your debt has amounted to %N!\n" +"^{The Bank has impounded ^}%N^{ from your cash.^}" +msgstr "" +"Your debt has amounted to %N!\n" +"^{The Bank has impounded ^}%N^{ from your cash.^}" + +#: src/exch.c:98 +msgid " Interstellar Stock Exchange " +msgstr " Interstellar Stock Exchange " + +#. TRANSLATORS: "Shares left" is a two-line column +#. label in a table containing the number of shares +#. left to be purchased in any given company. The +#. maximum column width is 10 characters (see +#. STOCK_LEFT_COLS in src/intf.h). +#: src/exch.c:127 +msgctxt "subtitle" +msgid "" +"Shares\n" +"left" +msgstr "" +"Shares\n" +"left" + +#. TRANSLATORS: "Shares issued" is a two-line column +#. label in a table containing the number of shares +#. already sold (ie, bought by all players) in any +#. given company. The maximum column width is 10 +#. characters (see STOCK_ISSUED_COLS in src/intf.h). +#: src/exch.c:134 +msgctxt "subtitle" +msgid "" +"Shares\n" +"issued" +msgstr "" +"Shares\n" +"issued" + +#: src/exch.c:185 +msgid "^{<2>^} Display galaxy map" +msgstr "^{<2>^} Display galaxy map" + +#: src/exch.c:187 +msgid "^{<3>^} Visit the Trading Bank" +msgstr "^{<3>^} Visit the Trading Bank" + +#: src/exch.c:189 +msgid "^{<4>^} Exit the Stock Exchange" +msgstr "^{<4>^} Exit the Stock Exchange" + +#: src/exch.c:192 +msgid "Enter selection [^[Company letter^]/^{1^}-^{4^}]: " +msgstr "Enter selection [^[Company letter^]/^{1^}-^{4^}]: " + +#. TRANSLATORS: The "Total value", "Current cash", "Current +#. debt", "Interest rate" and "Credit limit" labels MUST all be +#. the same length (ie, right-padded with spaces as needed) and +#. must have at least one trailing space so that the display +#. routines work correctly. The maximum length of each label +#. is 36 characters. +#. +#. Note that some of these labels are used for both the Player +#. Status window and the Trading Bank window. +#: src/exch.c:350 +msgctxt "label" +msgid "Credit limit: " +msgstr "Credit limit: " + +#. TRANSLATORS: The "Borrow money", "Repay debt" and "Exit +#. from the Bank" menu options must all be the same length +#. (ie, padded with trailing spaces as required). The maximum +#. length is 72 characters. +#: src/exch.c:365 +msgid "^{<1>^} Borrow money " +msgstr "^{<1>^} Borrow money " + +#: src/exch.c:367 +msgid "^{<2>^} Repay debt " +msgstr "^{<2>^} Repay debt " + +#: src/exch.c:369 +msgid "^{<3>^} Exit from the Bank" +msgstr "^{<3>^} Exit from the Bank" + +#: src/exch.c:372 +msgid "Enter selection [^{1^}-^{3^}]: " +msgstr "Enter selection [^{1^}-^{3^}]: " + +#: src/exch.c:425 +msgid " Insufficient Credit Limit " +msgstr " Insufficient Credit Limit " + +#: src/exch.c:426 +msgid "The Bank will not lend you any more money." +msgstr "The Bank will not lend you any more money." + +#: src/exch.c:446 +msgid "How much do you wish to borrow? " +msgstr "How much do you wish to borrow? " + +#: src/exch.c:478 +msgid " No Debt " +msgstr " No Debt " + +#: src/exch.c:479 +msgid "You have no debt to repay." +msgstr "You have no debt to repay." + +#: src/exch.c:483 +msgid " No Cash " +msgstr " No Cash " + +#: src/exch.c:484 +msgid "You have no cash with which to repay the debt!" +msgstr "You have no cash with which to repay the debt!" + +#: src/exch.c:504 +msgid "How much do you wish to repay? " +msgstr "How much do you wish to repay? " + +#. TRANSLATORS: %ls represents the company name. +#: src/exch.c:580 +#, c-format +msgid " Stock Transaction in %ls " +msgstr " Stock Transaction in %ls " + +#. TRANSLATORS: "Shares issued" represents the number of +#. shares already sold by the company to all players. +#. +#. Note that the labels "Shares issued", "Shares left", +#. "Price per share" and "Return" must all be the same length +#. and must have at least one trailing space for the output +#. routines to work correctly. The maximum length of each +#. label is 22 characters. +#: src/exch.c:591 +msgctxt "label|Stock A" +msgid "Shares issued: " +msgstr "Shares issued: " + +#. TRANSLATORS: "Shares left" is the number of shares that are +#. left to be purchased in the current company. +#: src/exch.c:599 +msgctxt "label|Stock A" +msgid "Shares left: " +msgstr "Shares left: " + +#. TRANSLATORS: "Price per share" is the cost of each share in +#. the current company. +#: src/exch.c:606 +msgctxt "label|Stock A" +msgid "Price per share: " +msgstr "Price per share: " + +#. TRANSLATORS: "Return" is the share return as a percentage. +#: src/exch.c:612 +msgctxt "label|Stock A" +msgid "Return: " +msgstr "Return: " + +#. TRANSLATORS: "Current holdings" is the number of shares the +#. current player owns in this particular company. +#. +#. Note that the labels "Current holdings", "Percentage owned" +#. and "Current cash" MUST all be the same length and contain at +#. least one trailing space for the display routines to work +#. correctly. The maximum length of each label is 18 +#. characters. +#: src/exch.c:625 +msgctxt "label|Stock B" +msgid "Current holdings: " +msgstr "Current holdings: " + +#. TRANSLATORS: "Percentage owned" is the current player's +#. percentage ownership in this particular company. +#: src/exch.c:632 +msgctxt "label|Stock B" +msgid "Percentage owned: " +msgstr "Percentage owned: " + +#: src/exch.c:637 +msgctxt "label|Stock B" +msgid "Current cash: " +msgstr "Current cash: " + +#: src/exch.c:648 +msgid "^{<1>^} Buy stock from company" +msgstr "^{<1>^} Buy stock from company" + +#: src/exch.c:650 +msgid "^{<2>^} Sell stock back to company" +msgstr "^{<2>^} Sell stock back to company" + +#: src/exch.c:652 +msgid "^{<3>^} Bid company to issue more shares" +msgstr "^{<3>^} Bid company to issue more shares" + +#: src/exch.c:654 +msgid "^{<4>^} Exit to the Stock Exchange" +msgstr "^{<4>^} Exit to the Stock Exchange" + +#: src/exch.c:657 +msgid "Enter selection [^{1^}-^{4^}]: " +msgstr "Enter selection [^{1^}-^{4^}]: " + +#: src/exch.c:713 +msgid " No Shares Available " +msgstr " No Shares Available " + +#: src/exch.c:714 +msgid "No more shares are available for purchase." +msgstr "No more shares are available for purchase." + +#: src/exch.c:718 +msgid " Insufficient Cash " +msgstr " Insufficient Cash " + +#: src/exch.c:719 +msgid "" +"You do not have enough cash\n" +"to purchase additional shares." +msgstr "" +"You do not have enough cash\n" +"to purchase additional shares." + +#: src/exch.c:730 +#, c-format +msgid "You can purchase ^{one^} share." +msgid_plural "You can purchase up to ^{%'ld^} shares." +msgstr[0] "You can purchase ^{one^} share." +msgstr[1] "You can purchase up to ^{%'ld^} shares." + +#: src/exch.c:736 +msgid "How many shares do you wish to purchase? " +msgstr "How many shares do you wish to purchase? " + +#: src/exch.c:757 +msgid " No Shares " +msgstr " No Shares " + +#: src/exch.c:758 +msgid "You do not have any shares to sell." +msgstr "You do not have any shares to sell." + +#: src/exch.c:765 +#, c-format +msgid "You can sell ^{one^} share." +msgid_plural "You can sell up to ^{%'ld^} shares." +msgstr[0] "You can sell ^{one^} share." +msgstr[1] "You can sell up to ^{%'ld^} shares." + +#: src/exch.c:771 +msgid "How many shares do you wish to sell? " +msgstr "How many shares do you wish to sell? " + +#: src/exch.c:799 +msgid " No Shares Issued " +msgstr " No Shares Issued " + +#. TRANSLATORS: %ls represents the company name. +#: src/exch.c:801 +#, c-format +msgid "" +"%ls has refused\n" +"to issue more shares." +msgstr "" +"%ls has refused\n" +"to issue more shares." + +#: src/exch.c:806 +msgid " Shares Issued " +msgstr " Shares Issued " + +#. TRANSLATORS: %ls represents the company name. +#: src/exch.c:808 +#, c-format +msgid "" +"%ls has issued\n" +"^{one^} more share." +msgid_plural "" +"%ls has issued\n" +"^{%'ld^} more shares." +msgstr[0] "" +"%ls has issued\n" +"^{one^} more share." +msgstr[1] "" +"%ls has issued\n" +"^{%'ld^} more shares." + +#: src/fileio.c:55 src/fileio.c:92 src/fileio.c:131 src/fileio.c:381 +#, c-format +msgid "%s: missing field on line %d" +msgstr "%s: missing field on line %d" + +#: src/fileio.c:60 +#, c-format +msgid "%s: illegal field on line %d: `%s'" +msgstr "%s: illegal field on line %d: ‘%s’" + +#: src/fileio.c:64 +#, c-format +msgid "%s: illegal value on line %d: `%s'" +msgstr "%s: illegal value on line %d: ‘%s’" + +#: src/fileio.c:96 src/fileio.c:135 src/fileio.c:393 +#, c-format +msgid "%s: illegal value on line %d" +msgstr "%s: illegal value on line %d" + +#: src/fileio.c:103 +#, c-format +msgid "%s: illegal characters on line %d" +msgstr "%s: illegal characters on line %d" + +#: src/fileio.c:184 +#, c-format +msgid "%s: could not convert string" +msgstr "%s: could not convert string" + +#: src/fileio.c:255 +msgid " Game Not Found " +msgstr " Game Not Found " + +#: src/fileio.c:256 +#, c-format +msgid "Game %d has not been saved to disk." +msgstr "Game %d has not been saved to disk." + +#: src/fileio.c:263 +msgid " Game Not Loaded " +msgstr " Game Not Loaded " + +#: src/fileio.c:264 +#, c-format +msgid "" +"Game %d could not be loaded from disk.\n" +"\n" +"^{File %s: %s^}" +msgstr "" +"Game %d could not be loaded from disk.\n" +"\n" +"^{File %s: %s^}" + +#: src/fileio.c:316 +#, c-format +msgid "%s: missing header in game file" +msgstr "%s: missing header in game file" + +#: src/fileio.c:319 +#, c-format +msgid "%s: not a valid game file" +msgstr "%s: not a valid game file" + +#: src/fileio.c:322 src/fileio.c:329 +#, c-format +msgid "%s: missing subheader in game file" +msgstr "%s: missing subheader in game file" + +#: src/fileio.c:325 +#, c-format +msgid "%s: saved under a different version of Star Traders" +msgstr "%s: saved under a different version of Star Traders" + +#: src/fileio.c:332 +#, c-format +msgid "%s: saved under an incompatible character encoding" +msgstr "%s: saved under an incompatible character encoding" + +#: src/fileio.c:340 +#, c-format +msgid "%s: illegal or missing field on line %d" +msgstr "%s: illegal or missing field on line %d" + +#: src/fileio.c:384 +#, c-format +msgid "%s: illegal field on line %d" +msgstr "%s: illegal field on line %d" + +#: src/fileio.c:466 src/fileio.c:487 +msgid " Game Not Saved " +msgstr " Game Not Saved " + +#: src/fileio.c:467 +#, c-format +msgid "" +"Game %d could not be saved to disk.\n" +"\n" +"^{Directory %s: %s^}" +msgstr "" +"Game %d could not be saved to disk.\n" +"\n" +"^{Directory %s: %s^}" + +#: src/fileio.c:488 +#, c-format +msgid "" +"Game %d could not be saved to disk.\n" +"\n" +"^{File %s: %s^}" +msgstr "" +"Game %d could not be saved to disk.\n" +"\n" +"^{File %s: %s^}" + +#. TRANSLATORS: The help text for Star Traders is marked up using a +#. custom mark-up format NOT used anywhere else in the source code. +#. +#. Each string is a single page of text that is displayed in an area 76 +#. columns wide by 16 lines high. Each line is delimited by "\n". NO +#. word-wrapping is performed: you must place the "\n" characters in the +#. appropriate place. Ideally, each line within the string should be +#. also (manually) space-justified or centred. TAB characters and other +#. control codes must NOT be used. If a string starts with "@" as the +#. very first character, that string is ignored (as are all strings +#. following): this allows a variable number of help text pages (from +#. one to ten). Multibyte strings are handled correctly (even those +#. requiring shift sequences!). +#. +#. The ASCII circumflex accent character "^" switches to a different +#. character rendition (also called attributes), depending on the +#. character following the "^": +#. +#. ^^ - Print the circumflex accent (ASCII code U+005E) +#. ^N - Switch to using the normal character rendition +#. ^B - Switch to using the bold character rendition +#. ^H - Switch to using the highlight character rendition +#. ^K - Switch to using the keycode character rendition (such as used for "") +#. ^e - Switch to using the character rendition used for empty space +#. ^o - Switch to using the character rendition used for outposts +#. ^s - Switch to using the character rendition used for stars +#. ^c - Switch to using the character rendition used for companies +#. ^k - Switch to using the character rendition used for keyboard choices on the galaxy map +#. +#. The help text parsing routines also understand the following "value +#. escapes" introduced by the ASCII tilde character "~"; these act like +#. "%" conversion specifiers in printf(): +#. +#. ~~ - Print the tilde character (ASCII code U+007E) [*] +#. ~x - Print the width of the galaxy map (MAX_X) [**] +#. ~y - Print the height of the galaxy map (MAX_Y) [**] +#. ~m - Print the number of moves available (NUMBER_MOVES) [**] +#. ~c - Print the maximum number of companies that can be formed (MAX_COMPANIES) [*] +#. ~t - Prints the default number of turns in the game (DEFAULT_MAX_TURN) [**] +#. ~1 to ~9 - Print the keycode for the N-th choice of move [***] +#. ~M - Print the keycode for the last choice of move [***] +#. ~A to ~H - Print the character used to represent the company on the galaxy map [***] +#. ~. - Print the character used to represent empty space on the map [***] +#. ~+ - Print the character used to represent outposts on the map [***] +#. ~* - Print the character used to represent stars on the map [***] +#. +#. [*] Takes one character space (column space) in the output +#. [**] Takes two column spaces in the output +#. [***] Takes one or two column spaces in the output, depending on the +#. appropriate strings in the current PO file. +#. +#. Note that all keycodes and map representation characters use locale- +#. specific characters; double-width characters ARE supported. Note +#. also that the tilde value escapes do NOT change the current character +#. rendition: a circumflex accent escape is needed for that. For +#. example, to display the first choice of move as it would be shown on +#. the galaxy map, use something like "^k~1^N" (a six-character sequence +#. that would translate to just one character (or maybe two) in the +#. output text). +#. +#: src/help.c:103 +msgid "" +"^BStar Traders^N is a simple game of interstellar trading. The object of " +"the\n" +"game is to amass the greatest amount of wealth possible. This is done " +"by\n" +"creating interstellar shipping lanes, expanding them and buying shares " +"in\n" +"the companies controlling them. Shares appreciate in value as " +"company\n" +"operations expand. In addition, the return on each share (as a " +"percentage)\n" +"also changes. Players may also borrow from the Interstellar Trading Bank " +"to\n" +"finance additional purchases on the Stock Exchange.\n" +"\n" +"The map of the galaxy is represented by a ^B~x^N x ^B~y^N grid. A typical " +"section\n" +"of it may be:\n" +"\n" +" ^e ~. ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" +" ^e ~. ~. ~. ~. ~. ~. ~. ~. ~. ^N ^e ~. ^N represents ^Bempty " +"space^N,\n" +" ^e ~. ^s~*^e ~. ~. ~. ~. ~. ~. ~. ^N ^s ~* ^N represents a " +"^Bstar^N.\n" +" ^e ~. ~. ~. ~. ~. ~. ~. ^s~*^e ~. ^N\n" +" ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ~. ^N\n" +msgstr "" +"^BStar Traders^N is a simple game of interstellar trading. The object of " +"the\n" +"game is to amass the greatest amount of wealth possible. This is done " +"by\n" +"creating interstellar shipping lanes, expanding them and buying shares " +"in\n" +"the companies controlling them. Shares appreciate in value as " +"company\n" +"operations expand. In addition, the return on each share (as a " +"percentage)\n" +"also changes. Players may also borrow from the Interstellar Trading Bank " +"to\n" +"finance additional purchases on the Stock Exchange.\n" +"\n" +"The map of the galaxy is represented by a ^B~x^N x ^B~y^N grid. A typical " +"section\n" +"of it may be:\n" +"\n" +" ^e ~. ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" +" ^e ~. ~. ~. ~. ~. ~. ~. ~. ~. ^N ^e ~. ^N represents ^Bempty " +"space^N,\n" +" ^e ~. ^s~*^e ~. ~. ~. ~. ~. ~. ~. ^N ^s ~* ^N represents a " +"^Bstar^N.\n" +" ^e ~. ~. ~. ~. ~. ~. ~. ^s~*^e ~. ^N\n" +" ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ~. ^N\n" + +#: src/help.c:122 +msgid "" +"The computer selects ^B~m^N moves (labeled ^k~1^N to ^k~M^N) at random, " +"and places these\n" +"on the map. To select any of the highlighted positions, press that " +"letter.\n" +"For example, some of the moves on the map may be:\n" +"\n" +"\n" +" ^e ^k~1^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" +" ^e ~. ~. ~. ^k~3^e ~. ~. ~. ~. ~. ^N\n" +" ^e ~. ^s~*^e ~. ~. ~. ~. ^k~5^e ~. ~. ^N Moves ^k~1^N to " +"^k~5^N shown.\n" +" ^e ~. ^k~2^e ~. ~. ^k~4^e ~. ~. ^s~*^e ~. ^N\n" +" ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ~. ^N\n" +"\n" +"\n" +"Selecting a position that is ^Bnot^N next to a star (such as moves " +"^k~1^N, ^k~3^N or ^k~5^N)\n" +"will set up an ^Boutpost^N, not belonging to any company. Thus, if move " +"^k~3^N is\n" +"selected on the above map, a ^o ~+ ^N would be placed at that position.\n" +msgstr "" +"The computer selects ^B~m^N moves (labelled ^k~1^N to ^k~M^N) at random, " +"and places these\n" +"on the map. To select any of the highlighted positions, press that " +"letter.\n" +"For example, some of the moves on the map may be:\n" +"\n" +"\n" +" ^e ^k~1^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" +" ^e ~. ~. ~. ^k~3^e ~. ~. ~. ~. ~. ^N\n" +" ^e ~. ^s~*^e ~. ~. ~. ~. ^k~5^e ~. ~. ^N Moves ^k~1^N to " +"^k~5^N shown.\n" +" ^e ~. ^k~2^e ~. ~. ^k~4^e ~. ~. ^s~*^e ~. ^N\n" +" ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ~. ^N\n" +"\n" +"\n" +"Selecting a position that is ^Bnot^N next to a star (such as moves " +"^k~1^N, ^k~3^N or ^k~5^N)\n" +"will set up an ^Boutpost^N, not belonging to any company. Thus, if move " +"^k~3^N is\n" +"selected on the above map, a ^o ~+ ^N would be placed at that position.\n" + +#: src/help.c:140 +msgid "" +"If, on the other hand, a position next to a star (or another outpost) " +"is\n" +"selected, a ^Bcompany^N would be formed and its letter would appear on the " +"map.\n" +"As a reward for creating the company, you are granted the first five " +"shares.\n" +"Up to ^B~c^N companies can be created in this way.\n" +"\n" +"If a position next to an existing company is selected, the company " +"would\n" +"expand its operations by one square. This increases the cost of its " +"shares\n" +"and hence your return. Thus, if the map was as shown below, selecting " +"^k~6^N\n" +"or ^k~8^N increases Company ^B~B^N's shipping lane:\n" +"\n" +" ^e ^k~1^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" +" ^e ~. ~. ~. ^o~+^e ~. ~. ^k~6^e ~. ~. ^N\n" +" ^e ~. ^s~*^e ~. ~. ~. ~. ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~6^N " +"or ^k~8^N increases Company ^B~B^N.\n" +" ^e ~. ^k~2^e ~. ~. ^k~4^e ~. ~. ^s~*^e ^c~B^e ^N\n" +" ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ^k~8^e ^N\n" +msgstr "" +"If, on the other hand, a position next to a star (or another outpost) " +"is\n" +"selected, a ^Bcompany^N would be formed and its letter would appear on the " +"map.\n" +"As a reward for creating the company, you are granted the first five " +"shares.\n" +"Up to ^B~c^N companies can be created in this way.\n" +"\n" +"If a position next to an existing company is selected, the company " +"would\n" +"expand its operations by one square. This increases the cost of its " +"shares\n" +"and hence your return. Thus, if the map was as shown below, selecting " +"^k~6^N\n" +"or ^k~8^N increases Company ^B~B^N’s shipping lane:\n" +"\n" +" ^e ^k~1^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" +" ^e ~. ~. ~. ^o~+^e ~. ~. ^k~6^e ~. ~. ^N\n" +" ^e ~. ^s~*^e ~. ~. ~. ~. ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~6^N " +"or ^k~8^N increases Company ^B~B^N.\n" +" ^e ~. ^k~2^e ~. ~. ^k~4^e ~. ~. ^s~*^e ^c~B^e ^N\n" +" ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ^k~8^e ^N\n" + +#: src/help.c:158 +msgid "" +"Selecting positions next to stars increases the value of your stock by " +"about\n" +"five times as much as an extension not next to a star. Thus move ^k~6^N " +"should\n" +"be preferred to move ^k~8^N.\n" +"\n" +" ^e ^c~C^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" +" ^e ^k~1^e ^o~+^e ~. ^o~+^e ~. ~. ^k~6^e ~. ~. ^N\n" +" ^e ~. ^s~*^e ~. ~. ~. ~. ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~6^N " +"is preferred to ^k~8^N.\n" +" ^e ~. ^k~2^e ~. ~. ^k~4^e ~. ~. ^s~*^e ^c~B^e ^N\n" +" ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ^k~8^e ^N\n" +"\n" +"You may also expand any company by selecting positions next to " +"outposts.\n" +"Such outposts will be swallowed up by that company. Thus, move ^k~1^N " +"will\n" +"extend Company ^B~C^N by ^Btwo^N squares. As a bonus, outposts next to " +"stars are\n" +"more valuable: the company's share price will increase by a greater " +"amount\n" +"than it would for outposts not next to stars.\n" +msgstr "" +"Selecting positions next to stars increases the value of your stock by " +"about\n" +"five times as much as an extension not next to a star. Thus move ^k~6^N " +"should\n" +"be preferred to move ^k~8^N.\n" +"\n" +" ^e ^c~C^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" +" ^e ^k~1^e ^o~+^e ~. ^o~+^e ~. ~. ^k~6^e ~. ~. ^N\n" +" ^e ~. ^s~*^e ~. ~. ~. ~. ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~6^N " +"is preferred to ^k~8^N.\n" +" ^e ~. ^k~2^e ~. ~. ^k~4^e ~. ~. ^s~*^e ^c~B^e ^N\n" +" ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ^k~8^e ^N\n" +"\n" +"You may also expand any company by selecting positions next to " +"outposts.\n" +"Such outposts will be swallowed up by that company. Thus, move ^k~1^N " +"will\n" +"extend Company ^B~C^N by ^Btwo^N squares. As a bonus, outposts next to " +"stars are\n" +"more valuable: the company’s share price will increase by a greater " +"amount\n" +"than it would for outposts not next to stars.\n" + +#: src/help.c:176 +msgid "" +"If two companies are separated on the map by only one square, then they " +"can\n" +"be ^Bmerged^N into one company by selecting that position (if available). " +"For\n" +"example, on the map below, companies ^B~A^N and ^B~B^N can be merged by " +"selecting ^k~5^N.\n" +"When this occurs, the company with the greater assets value takes over " +"the\n" +"other one. Here, Company ^B~B^N might take over Company ^B~A^N. Company " +"^B~A^N ceases to\n" +"exist, although it may reappear as an entirely new company at a later " +"stage.\n" +"\n" +" ^e ^k~1^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" +" ^e ~. ~. ~. ^c~A^e ^c~A^e ^k~5^e ^c~B^e ~. ~. ^N\n" +" ^e ~. ^s~*^e ~. ~. ^c~A^e ~. ^c~B^e ^c~B^e ^c~B^e ^N Move " +"^k~5^N merges companies ^B~A^N and ^B~B^N.\n" +" ^e ~. ^k~2^e ~. ~. ~. ~. ~. ^s~*^e ^c~B^e ^N\n" +" ^e ~. ~. ~. ~. ^s~*^e ~. ^o~+^e ~. ~. ^N\n" +"\n" +"When companies merge, players are granted shares in the dominant " +"company\n" +"proportional to the amount owned in the old company. As well, a cash " +"bonus\n" +"is also paid, proportional to the percentage of the old company owned.\n" +msgstr "" +"If two companies are separated on the map by only one square, then they " +"can\n" +"be ^Bmerged^N into one company by selecting that position (if available). " +"For\n" +"example, on the map below, companies ^B~A^N and ^B~B^N can be merged by " +"selecting ^k~5^N.\n" +"When this occurs, the company with the greater assets value takes over " +"the\n" +"other one. Here, Company ^B~B^N might take over Company ^B~A^N. Company " +"^B~A^N ceases to\n" +"exist, although it may reappear as an entirely new company at a later " +"stage.\n" +"\n" +" ^e ^k~1^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" +" ^e ~. ~. ~. ^c~A^e ^c~A^e ^k~5^e ^c~B^e ~. ~. ^N\n" +" ^e ~. ^s~*^e ~. ~. ^c~A^e ~. ^c~B^e ^c~B^e ^c~B^e ^N Move " +"^k~5^N merges companies ^B~A^N and ^B~B^N.\n" +" ^e ~. ^k~2^e ~. ~. ~. ~. ~. ^s~*^e ^c~B^e ^N\n" +" ^e ~. ~. ~. ~. ^s~*^e ~. ^o~+^e ~. ~. ^N\n" +"\n" +"When companies merge, players are granted shares in the dominant " +"company\n" +"proportional to the amount owned in the old company. As well, a cash " +"bonus\n" +"is also paid, proportional to the percentage of the old company owned.\n" + +#: src/help.c:195 +msgid "" +"Once you select your move, you enter the ^BInterstellar Stock Exchange^N. " +"Here\n" +"you may purchase shares, sell them, borrow from the Trading Bank or " +"repay\n" +"some of your debt (if applicable). Note that each company issues a " +"limited\n" +"number of shares -- you cannot go on buying for ever! You may, however, " +"bid\n" +"for more shares to be issued. You have a better chance of succeeding if " +"you\n" +"own a larger proportion of the company.\n" +"\n" +"The game usually ends after ^B~t^N turns. However, you may end the game " +"sooner\n" +"by pressing ^K^N when asked to select a move. As well, " +"individual\n" +"players can declare themselves bankrupt at any time. If your debt is " +"large\n" +"enough, the Bank may do this for you! If you do not complete your game " +"in\n" +"the time you have available, you may save the game and continue it later.\n" +"\n" +"\n" +"The ^Bwinner of the game^N is the person with the greatest net worth " +"(total\n" +"value of cash, stock and debt). ^HGood luck^N and may the best person win!\n" +msgstr "" +"Once you select your move, you enter the ^BInterstellar Stock Exchange^N. " +"Here\n" +"you may purchase shares, sell them, borrow from the Trading Bank or " +"repay\n" +"some of your debt (if applicable). Note that each company issues a " +"limited\n" +"number of shares -- you cannot go on buying for ever! You may, however, " +"bid\n" +"for more shares to be issued. You have a better chance of succeeding if " +"you\n" +"own a larger proportion of the company.\n" +"\n" +"The game usually ends after ^B~t^N turns. However, you may end the game " +"sooner\n" +"by pressing ^K^N when asked to select a move. As well, " +"individual\n" +"players can declare themselves bankrupt at any time. If your debt is " +"large\n" +"enough, the Bank may do this for you! If you do not complete your game " +"in\n" +"the time you have available, you may save the game and continue it later.\n" +"\n" +"\n" +"The ^Bwinner of the game^N is the person with the greatest net worth " +"(total\n" +"value of cash, stock and debt). ^HGood luck^N and may the best person win!\n" + +#: src/help.c:215 +msgid "@ Help text, page 7" +msgstr "@ Help text, page 7" + +#: src/help.c:216 +msgid "@ Help text, page 8" +msgstr "@ Help text, page 8" + +#: src/help.c:217 +msgid "@ Help text, page 9" +msgstr "@ Help text, page 9" + +#: src/help.c:218 +msgid "@ Help text, page 10" +msgstr "@ Help text, page 10" + +#: src/help.c:270 +msgid " How to Play " +msgstr " How to Play " + +#: src/help.c:272 +#, c-format +msgid "Page %d of %d" +msgstr "Page %d of %d" + +#. TRANSLATORS: The reason the user is not asked "Press any +#. key to continue" is historical: many, many people used to +#. ask "where is the key?" :-) +#: src/help.c:473 src/intf.c:3022 +msgid "[ Press to continue ] " +msgstr "[ Press to continue ] " + +#. TRANSLATORS: The specific use of and +#. is not essential: you can use , +#. , , or instead of +#. , and almost any other key instead of +#. (other than , , , , +#. or <\>). +#: src/help.c:480 +msgid "[ Press to continue or for the previous page ] " +msgstr "[ Press to continue or for the previous page ] " + +#: src/intf.c:110 +#, c-format +msgid "%s: string has incorrect format: `%s'" +msgstr "%s: string has incorrect format: ‘%s’" + +#: src/intf.c:126 +#, c-format +msgid "%s: character has illegal width: `%lc'" +msgstr "%s: character has illegal width: ‘%lc’" + +#: src/intf.c:434 +#, c-format +msgid "terminal size is too small (%d x %d required)" +msgstr "terminal size is too small (%d x %d required)" + +#: src/intf.c:610 +msgid "Star Traders" +msgstr "Star Traders" + +#: src/intf.c:1262 +msgid "mkchstr_conv: NUL" +msgstr "mkchstr_conv: NUL" + +#: src/intf.c:1565 +#, c-format +msgid "mkchstr: `%s'" +msgstr "mkchstr: ‘%s’" + +#: src/intf.c:2022 src/intf.c:2067 +#, c-format +msgid "gettxline: illegal character in string: `%ls'" +msgstr "gettxline: illegal character in string: ‘%ls’" + +#. TRANSLATORS: The strings with msgctxt "input|Yes" and +#. "input|No" contain the keycodes used to determine whether a +#. user is answering "Yes" or "No" in response to some question. +#. Both upper and lower-case versions should be present. +#: src/intf.c:2939 +msgctxt "input|Yes" +msgid "Yy" +msgstr "Yy" + +#: src/intf.c:2941 +msgctxt "input|No" +msgid "Nn" +msgstr "Nn" + +#. TRANSLATORS: The strings "Yes" and "No" are printed as a +#. response to user input in answer to questions like "Are you +#. sure? [Y/N] " +#: src/intf.c:2992 +msgctxt "answer" +msgid "Yes" +msgstr "Yes" + +#: src/intf.c:2994 +msgctxt "answer" +msgid "No" +msgstr "No" + +#: src/utils.c:199 src/utils.c:220 +#, c-format +msgid "%s: " +msgstr "%s: " + +#: src/utils.c:225 +msgid ": " +msgstr ": " + +#: src/utils.c:238 +msgid "out of memory" +msgstr "out of memory" + +#: src/utils.c:571 +#, c-format +msgid "xmbstowcs: `%s'" +msgstr "xmbstowcs: ‘%s’" + +#: src/utils.c:611 +msgid "xwcrtomb: NUL" +msgstr "xwcrtomb: NUL" + +#: src/utils.c:616 +#, c-format +msgid "xwcrtomb: `%lc'" +msgstr "xwcrtomb: ‘%lc’" + +#: lib/getopt.c:547 lib/getopt.c:576 +#, c-format +msgid "%s: option '%s' is ambiguous; possibilities:" +msgstr "%s: option ‘%s’ is ambiguous; possibilities:" + +#: lib/getopt.c:624 lib/getopt.c:628 +#, c-format +msgid "%s: option '--%s' doesn't allow an argument\n" +msgstr "%s: option ‘--%s’ doesn’t allow an argument\n" + +#: lib/getopt.c:637 lib/getopt.c:642 +#, c-format +msgid "%s: option '%c%s' doesn't allow an argument\n" +msgstr "%s: option ‘%c%s’ doesn’t allow an argument\n" + +#: lib/getopt.c:685 lib/getopt.c:704 +#, c-format +msgid "%s: option '--%s' requires an argument\n" +msgstr "%s: option ‘--%s’ requires an argument\n" + +#: lib/getopt.c:742 lib/getopt.c:745 +#, c-format +msgid "%s: unrecognized option '--%s'\n" +msgstr "%s: unrecognized option ‘--%s’\n" + +#: lib/getopt.c:753 lib/getopt.c:756 +#, c-format +msgid "%s: unrecognized option '%c%s'\n" +msgstr "%s: unrecognized option ‘%c%s’\n" + +#: lib/getopt.c:805 lib/getopt.c:808 +#, c-format +msgid "%s: invalid option -- '%c'\n" +msgstr "%s: invalid option -- ‘%c’\n" + +#: lib/getopt.c:861 lib/getopt.c:878 lib/getopt.c:1088 lib/getopt.c:1106 +#, c-format +msgid "%s: option requires an argument -- '%c'\n" +msgstr "%s: option requires an argument -- ‘%c’\n" + +#: lib/getopt.c:934 lib/getopt.c:950 +#, c-format +msgid "%s: option '-W %s' is ambiguous\n" +msgstr "%s: option ‘-W %s’ is ambiguous\n" + +#: lib/getopt.c:974 lib/getopt.c:992 +#, c-format +msgid "%s: option '-W %s' doesn't allow an argument\n" +msgstr "%s: option ‘-W %s’ doesn’t allow an argument\n" + +#: lib/getopt.c:1013 lib/getopt.c:1031 +#, c-format +msgid "%s: option '-W %s' requires an argument\n" +msgstr "%s: option ‘-W %s’ requires an argument\n" diff --git a/po/en_US.po b/po/en_US.po new file mode 100644 index 0000000..663c00e --- /dev/null +++ b/po/en_US.po @@ -0,0 +1,1662 @@ +# ************************************************************************* +# * * +# * English (US) Translations for Star Traders * +# * Copyright (C) 1990-2011, John Zaitseff * +# * * +# ************************************************************************* +# +# This file is distributed under the same licence as Star Traders. +# +# Contributors: +# John Zaitseff , 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: trader 7.2\n" +"Report-Msgid-Bugs-To: J.Zaitseff@zap.org.au\n" +"POT-Creation-Date: 2011-08-28 14:55+1000\n" +"PO-Revision-Date: 2011-08-28 15:59+1000\n" +"Last-Translator: John Zaitseff \n" +"Language-Team: English\n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: src/trader.c:235 +#, c-format +msgid "%s: invalid value for --max-turn: `%s'\n" +msgstr "%s: invalid value for --max-turn: ‘%s’\n" + +#: src/trader.c:251 +#, c-format +msgid "%s: invalid operand `%s'\n" +msgstr "%s: invalid operand ‘%s’\n" + +#: src/trader.c:260 +#, c-format +msgid "%s: invalid game number `%s'\n" +msgstr "%s: invalid game number ‘%s’\n" + +#: src/trader.c:269 +#, c-format +msgid "%s: extra operand `%s'\n" +msgstr "%s: extra operand ‘%s’\n" + +#. TRANSLATORS: "John Zaitseff" [IPA d͡ʒɒn ˈzaɪ̯t͡səf] is the proper +#. name of the author. The IPA pronunciation in this comment is in +#. UTF-8 encoding. +#: src/trader.c:284 +#, c-format +msgid "" +"Star Traders (%s) %s\n" +"Copyright (C) %s, John Zaitseff.\n" +"\n" +"Star Traders is a simple game of interstellar trading, where the object\n" +"of the game is to create companies, buy and sell shares, borrow and repay\n" +"money, in order to become the wealthiest player (the winner).\n" +"\n" +"This program is free software that is distributed under the terms of the\n" +"GNU General Public License, version 3 or later. You are welcome to\n" +"modify and/or distribute it under certain conditions. This program has\n" +"NO WARRANTY, to the extent permitted by law; see the License for details.\n" +msgstr "" +"Star Traders (%s) %s\n" +"Copyright (C) %s, John Zaitseff.\n" +"\n" +"Star Traders is a simple game of interstellar trading, where the object\n" +"of the game is to create companies, buy and sell shares, borrow and repay\n" +"money, in order to become the wealthiest player (the winner).\n" +"\n" +"This program is free software that is distributed under the terms of the\n" +"GNU General Public License, version 3 or later. You are welcome to\n" +"modify and/or distribute it under certain conditions. This program has\n" +"NO WARRANTY, to the extent permitted by law; see the License for details.\n" + +#: src/trader.c:308 +#, c-format +msgid "%s: Try `%s --help' for more information.\n" +msgstr "%s: Try ‘%s --help’ for more information.\n" + +#: src/trader.c:311 +#, c-format +msgid "Usage: %s [OPTION ...] [GAME]\n" +msgstr "Usage: %s [OPTION ...] [GAME]\n" + +#: src/trader.c:312 +#, c-format +msgid "" +"Play Star Traders, a simple game of interstellar trading.\n" +"\n" +msgstr "" +"Play Star Traders, a simple game of interstellar trading.\n" +"\n" + +#: src/trader.c:315 +#, c-format +msgid "" +"Options:\n" +" -V, --version output version information and exit\n" +" -h, --help display this help and exit\n" +" --no-color don't use color for displaying text\n" +" --max-turn=NUM set the number of turns to NUM\n" +"\n" +msgstr "" +"Options:\n" +" -V, --version output version information and exit\n" +" -h, --help display this help and exit\n" +" --no-color don’t use color for displaying text\n" +" --max-turn=NUM set the number of turns to NUM\n" +"\n" + +#: src/trader.c:322 +#, c-format +msgid "" +"If GAME is specified as a number between 1 and 9, load and continue\n" +"playing that game. If GAME is not specified, start a new game.\n" +"\n" +msgstr "" +"If GAME is specified as a number between 1 and 9, load and continue\n" +"playing that game. If GAME is not specified, start a new game.\n" +"\n" + +#. TRANSLATORS: The first %s is the proper name of the package +#. author, John Zaitseff [IPA d͡ʒɒn ˈzaɪ̯t͡səf]; the second %s is +#. the e-mail address for reporting bugs. Please add ANOTHER +#. line with the (translated) text "Report translation bugs to +#.
\n", with ADDRESS replaced with either an e-mail +#. address or web URL for reporting bugs in your translation. +#: src/trader.c:334 +#, c-format +msgid "Report bugs to %s <%s>.\n" +msgstr "Report bugs to %s <%s>.\n" + +#. TRANSLATORS: %s is the e-mail address for reporting bugs. As +#. with the previous string, please add ANOTHER line with the +#. (translated) text "Report translation bugs to
\n", +#. with ADDRESS replaced with either an e-mail address or web URL +#. for reporting bugs in your translation. +#: src/trader.c:341 +#, c-format +msgid "Report bugs to <%s>.\n" +msgstr "Report bugs to <%s>.\n" + +#. TRANSLATORS: The first %s is for packagers and may be +#. something like "Debian". +#: src/trader.c:346 +#, c-format +msgid "Report %s bugs to <%s>.\n" +msgstr "Report %s bugs to <%s>.\n" + +#: src/trader.c:349 +#, c-format +msgid "Star Traders home page: <%s>.\n" +msgstr "Star Traders home page: <%s>.\n" + +#. TRANSLATORS: The eight company names do NOT have to be literal +#. translations of the English names. In fact, if possible, the +#. names should start with successive letters of your alphabet (in +#. English, for example, "A" to "H"). No company name should be more +#. than 24 characters (column positions, to be precise) long. +#: src/globals.c:46 +msgid "Altair Starways" +msgstr "Altair Starways" + +#: src/globals.c:47 +msgid "Betelgeuse, Ltd" +msgstr "Betelgeuse, Ltd" + +#: src/globals.c:48 +msgid "Capella Freight Co" +msgstr "Capella Freight Co" + +#: src/globals.c:49 +msgid "Denebola Shippers" +msgstr "Denebola Shippers" + +#: src/globals.c:50 +msgid "Eridani Expediters" +msgstr "Eridani Expediters" + +#: src/globals.c:51 +msgid "Fornax Express" +msgstr "Fornax Express" + +#: src/globals.c:52 +msgid "Gemeni Inc" +msgstr "Gemeni Inc" + +#: src/globals.c:53 +msgid "Hercules and Co" +msgstr "Hercules and Co" + +#. TRANSLATORS: This string specifies the keycodes (keyboard input +#. codes) used to enter the Stock Transaction window for each +#. company. There must be exactly eight characters, one for each +#. company in order, before the ASCII vertical line "|"; these must +#. be EITHER all in upper-case or all in lower-case. If at all +#. possible, these should be successive letters in your alphabet (in +#. English, "A" to "H"). Do NOT use digits or control characters. +#. Do not change or translate anything after the vertical line. +#: src/globals.c:67 +msgid "ABCDEFGH|input|Companies" +msgstr "ABCDEFGH|input|Companies" + +#. TRANSLATORS: This string specifies the keycodes used to select a +#. game move. There must be exactly 20 characters, one for each +#. move, before the ASCII vertical line "|"; these must be EITHER all +#. in upper-case or all in lower-case. If at all possible, these +#. should be successive letters in your alphabet. Do NOT use digits +#. or control characters. Do not change or translate anything after +#. the vertical line. +#: src/globals.c:79 +msgid "ABCDEFGHIJKLMNOPQRST|input|GameMoves" +msgstr "ABCDEFGHIJKLMNOPQRST|input|GameMoves" + +#. TRANSLATORS: This string is used to display the galaxy map to +#. screen. There must be exactly 11 characters before the ASCII +#. vertical line. The first ("." in English) is used for empty +#. space, the second ("+") for outposts, the third ("*") for stars, +#. the remaining for the eight companies. Do not change or translate +#. anything after the vertical line. +#: src/globals.c:90 +msgid ".+*ABCDEFGH|output|MapVals" +msgstr ".+*ABCDEFGH|output|MapVals" + +#. TRANSLATORS: This string is used to display the game moves +#. (choices). There must be exactly 20 characters (NUMBER_MOVES) +#. before the ASCII vertical line. The first character corresponds +#. to the first character in the "input|GameMoves" string, and so on. +#. Do not change or translate anything after the vertical line. +#: src/globals.c:100 +msgid "abcdefghijklmnopqrst|output|GameMoves" +msgstr "abcdefghijklmnopqrst|output|GameMoves" + +#. TRANSLATORS: The ordinal strings "1st" to "8th" are used in the +#. Game Winner dialog box at the end of the game. If ordinals depend +#. on the gender of the player, it may be simpler to list cardinal +#. numbers instead (eg, "No. 1"). Up to five characters are allowed +#. (see ORDINAL_COLS in src/intf.h). +#: src/globals.c:111 +msgid "1st" +msgstr "1st" + +#: src/globals.c:112 +msgid "2nd" +msgstr "2nd" + +#: src/globals.c:113 +msgid "3rd" +msgstr "3rd" + +#: src/globals.c:114 +msgid "4th" +msgstr "4th" + +#: src/globals.c:115 +msgid "5th" +msgstr "5th" + +#: src/globals.c:116 +msgid "6th" +msgstr "6th" + +#: src/globals.c:117 +msgid "7th" +msgstr "7th" + +#: src/globals.c:118 +msgid "8th" +msgstr "8th" + +#: src/game.c:117 src/game.c:152 +#, c-format +msgid "Loading game %d... " +msgstr "Loading game %d... " + +#: src/game.c:226 +msgid " First Player " +msgstr " First Player " + +#: src/game.c:227 +#, c-format +msgid "The first player to go is ^{%ls^}." +msgstr "The first player to go is ^{%ls^}." + +#. TRANSLATORS: The keycode should be modified to +#. match that (or those) specified with msgctxt +#. "input|ContinueGame". +#: src/game.c:259 +#, c-format +msgid "Enter number of players [^{1^}-^{%d^}] or ^{^} to continue a game: " +msgstr "Enter number of players [^{1^}-^{%d^}] or ^{^} to continue a game: " + +#. TRANSLATORS: This string specifies the keycodes used to continue a +#. game; these must NOT contain any numeric digit from 1 to 9. The +#. first character (keyboard input code) is used to print the user's +#. response if one of those keys is pressed. Both upper and +#. lower-case versions should be present. +#: src/game.c:276 +msgctxt "input|ContinueGame" +msgid "Cc" +msgstr "Cc" + +#: src/game.c:341 src/move.c:380 +msgid "Enter game number [^{1^}-^{9^}] or ^{^} to cancel: " +msgstr "Enter game number [^{1^}-^{9^}] or ^{^} to cancel: " + +#: src/game.c:406 +msgid "Please enter your name: " +msgstr "Please enter your name: " + +#: src/game.c:425 +msgid "Do you need any instructions? [^{Y^}/^{N^}] " +msgstr "Do you need any instructions? [^{Y^}/^{N^}] " + +#: src/game.c:443 +msgid " Enter Player Names " +msgstr " Enter Player Names " + +#: src/game.c:451 +#, c-format, range: 1..8 +msgid "Player %d: " +msgstr "Player %d: " + +#: src/game.c:529 +msgid "Does any player need instructions? [^{Y^}/^{N^}] " +msgstr "Does any player need instructions? [^{Y^}/^{N^}] " + +#: src/game.c:563 +msgid " Game Over " +msgstr " Game Over " + +#: src/game.c:564 +#, c-format +msgid "The game is over after one turn." +msgid_plural "The game is over after %d turns." +msgstr[0] "The game is over after one turn." +msgstr[1] "The game is over after %d turns." + +#: src/game.c:575 +msgid " Total Value " +msgstr " Total Value " + +#: src/game.c:577 +#, c-format +msgid "Your total value was ^{%N^}." +msgstr "Your total value was ^{%N^}." + +#: src/game.c:588 +#, c-format +msgid "" +"The winner is ^{%ls^}\n" +"who is ^[*** BANKRUPT ***^]" +msgstr "" +"The winner is ^{%ls^}\n" +"who is ^[*** BANKRUPT ***^]" + +#: src/game.c:591 +#, c-format +msgid "" +"The winner is ^{%ls^}\n" +"with a value of ^{%N^}." +msgstr "" +"The winner is ^{%ls^}\n" +"with a value of ^{%N^}." + +#: src/game.c:597 +msgid " Game Winner " +msgstr " Game Winner " + +#. TRANSLATORS: "Player" is used as a column title in a +#. table containing all player names. +#: src/game.c:606 src/move.c:847 +msgctxt "subtitle" +msgid "Player" +msgstr "Player" + +#. TRANSLATORS: "Total Value" refers to the total worth +#. (shares, cash and debt) of any given player. %ls is the +#. currency symbol of the current locale. +#: src/game.c:611 +#, c-format +msgctxt "subtitle" +msgid "Total Value (%ls)" +msgstr "Total Value (%ls)" + +#: src/game.c:645 src/game.c:695 src/exch.c:100 +#, c-format +msgid "Player: ^{%ls^}" +msgstr "Player: ^{%ls^}" + +#: src/game.c:648 +#, c-format +msgid " Turn: ^{%d^} " +msgstr " Turn: ^{%d^} " + +#: src/game.c:649 +msgid " ^[*** Last Turn ***^] " +msgstr " ^[*** Last Turn ***^] " + +#: src/game.c:693 +msgid " Stock Portfolio " +msgstr " Stock Portfolio " + +#. TRANSLATORS: The current player is bankrupt (has no +#. shares or cash, ie, whose total value is zero) +#: src/game.c:702 +msgid "^[* * * B A N K R U P T * * *^]" +msgstr "^[* * * B A N K R U P T * * *^]" + +#: src/game.c:717 src/exch.c:112 +msgid "No companies on the map" +msgstr "No companies on the map" + +#. TRANSLATORS: "Company" is a two-line column label in +#. a table containing a list of companies. +#: src/game.c:725 src/exch.c:120 +msgctxt "subtitle" +msgid "" +"\n" +"Company" +msgstr "" +"\n" +"Company" + +#. TRANSLATORS: "Ownership" is a two-line column label +#. in a table containing the current player's +#. percentage ownership in any given company. The +#. maximum column width is 10 characters (see +#. OWNERSHIP_COLS in src/intf.h). +#: src/game.c:732 +#, c-format +msgctxt "subtitle" +msgid "" +"Ownership\n" +"(%%)" +msgstr "" +"Ownership\n" +"(%%)" + +#. TRANSLATORS: "Holdings" is a two-line column label +#. in a table containing the number of shares the +#. current player owns in any given company. The +#. maximum column width is 10 characters (see +#. STOCK_OWNED_COLS in src/intf.h). +#: src/game.c:739 +msgctxt "subtitle" +msgid "" +"Holdings\n" +"(shares)" +msgstr "" +"Holdings\n" +"(shares)" + +#. TRANSLATORS: "Return" is a two-line column label in +#. a table containing the share return as a percentage +#. in any given company. The maximum column width is +#. 10 characters (see SHARE_RETURN_COLS in src/intf.h). +#: src/game.c:746 src/exch.c:141 +#, c-format +msgctxt "subtitle" +msgid "" +"Return\n" +"(%%)" +msgstr "" +"Return\n" +"(%%)" + +#. TRANSLATORS: "Price per share" is a two-line column +#. label in a table containing the price per share in +#. any given company. %ls is the currency symbol in +#. the current locale. The maximum column width is 12 +#. characters INCLUDING the currency symbol (see +#. SHARE_PRICE_COLS in src/intf.h). +#: src/game.c:755 src/exch.c:150 +#, c-format +msgctxt "subtitle" +msgid "" +"Price per\n" +"share (%ls)" +msgstr "" +"Price per\n" +"share (%ls)" + +#. TRANSLATORS: The "Total value", "Current cash", +#. "Current debt" and "Interest rate" labels MUST all be +#. the same length (ie, right-padded with spaces as +#. needed) and must have at least one trailing space so +#. that the display routines work correctly. The maximum +#. length of each label is 36 characters. +#. +#. Note that some of these labels are used for both the +#. Player Status window and the Trading Bank window. +#: src/game.c:796 +msgctxt "label" +msgid "Total value: " +msgstr "Total value: " + +#: src/game.c:800 src/exch.c:323 +msgctxt "label" +msgid "Current cash: " +msgstr "Current cash: " + +#: src/game.c:807 src/exch.c:331 +msgctxt "label" +msgid "Current debt: " +msgstr "Current debt: " + +#: src/game.c:813 src/exch.c:336 +msgctxt "label" +msgid "Interest rate: " +msgstr "Interest rate: " + +#: src/move.c:235 src/exch.c:183 +msgid "^{<1>^} Display stock portfolio" +msgstr "^{<1>^} Display stock portfolio" + +#: src/move.c:237 +msgid "^{<2>^} Declare bankruptcy" +msgstr "^{<2>^} Declare bankruptcy" + +#: src/move.c:239 +msgid "^{<3>^} Save and end the game" +msgstr "^{<3>^} Save and end the game" + +#: src/move.c:241 +msgid "^{^} Quit the game" +msgstr "^{^} Quit the game" + +#: src/move.c:245 +#, c-format +msgid "Select move [^[%lc^]-^[%lc^]/^{1^}-^{3^}/^{^}]: " +msgstr "Select move [^[%lc^]-^[%lc^]/^{1^}-^{3^}/^{^}]: " + +#. TRANSLATORS: "Move" refers to the choice of +#. moves made by the current player (out of a +#. selection of 20 moves). +#: src/move.c:277 +#, c-format +msgid "Move ^{%lc^}" +msgstr "Move ^{%lc^}" + +#: src/move.c:297 +msgid "^{<2>^} (Declare bankruptcy)" +msgstr "^{<2>^} (Declare bankruptcy)" + +#: src/move.c:306 +msgid "^{<3>^} (Save and end the game)" +msgstr "^{<3>^} (Save and end the game)" + +#: src/move.c:327 +msgid "^{^} (Quit the game)" +msgstr "^{^} (Quit the game)" + +#: src/move.c:342 +msgid "Are you sure? [^{Y^}/^{N^}] " +msgstr "Are you sure? [^{Y^}/^{N^}] " + +#: src/move.c:359 src/move.c:437 +#, c-format +msgid "Saving game %d... " +msgstr "Saving game %d... " + +#: src/move.c:667 src/move.c:674 src/move.c:1018 src/move.c:1052 +msgid " Bankruptcy Court " +msgstr " Bankruptcy Court " + +#: src/move.c:668 +#, c-format +msgid "%ls has been declared bankrupt by the Interstellar Trading Bank." +msgstr "%ls has been declared bankrupt by the Interstellar Trading Bank." + +#: src/move.c:675 +#, c-format +msgid "%ls has declared bankruptcy." +msgstr "%ls has declared bankruptcy." + +#: src/move.c:743 +msgid " New Company " +msgstr " New Company " + +#: src/move.c:744 +#, c-format +msgid "" +"A new company has been formed!\n" +"Its name is ^{%ls^}." +msgstr "" +"A new company has been formed!\n" +"Its name is ^{%ls^}." + +#: src/move.c:803 +#, c-format +msgid "" +"^{%ls^} has just merged into ^{%ls^}.\n" +"Please note the following transactions:\n" +msgstr "" +"^{%ls^} has just merged into ^{%ls^}.\n" +"Please note the following transactions:\n" + +#: src/move.c:809 +msgid " Company Merger " +msgstr " Company Merger " + +#. TRANSLATORS: "Old stock" refers to the company that has +#. just ceased existence due to a merger. +#. +#. Note that the "Old stock" and "New stock" labels MUST be +#. the same length and must contain a trailing space for the +#. display routines to work correctly. The maximum length of +#. each label is 36 characters. +#: src/move.c:829 +msgctxt "label" +msgid "Old stock: " +msgstr "Old stock: " + +#. TRANSLATORS: "New stock" refers to the company that has +#. absorbed another due to a merger. +#: src/move.c:840 +msgctxt "label" +msgid "New Stock: " +msgstr "New Stock: " + +#. TRANSLATORS: "Bonus" refers to the bonus cash amount paid to +#. each player after two companies merge. %ls is the currency +#. symbol in the current locale. The maximum column width is +#. 12 characters INCLUDING the currency symbol (see +#. MERGE_BONUS_COLS in src/intf.h). +#: src/move.c:854 +#, c-format +msgctxt "subtitle" +msgid "Bonus (%ls)" +msgstr "Bonus (%ls)" + +#. TRANSLATORS: "Total" refers to the total number of shares in +#. the new company after a merger. The maximum column width is +#. 8 characters (see MERGE_TOTAL_STOCK_COLS in src/intf.h). +#: src/move.c:859 +msgctxt "subtitle" +msgid "Total" +msgstr "Total" + +#. TRANSLATORS: "New" refers to how many (new) shares each +#. player receives in the surviving company after a merger. +#. The maximum column width is 8 characters (see +#. MERGE_NEW_STOCK_COLS in src/intf.h). +#: src/move.c:866 +msgctxt "subtitle" +msgid "New" +msgstr "New" + +#. TRANSLATORS: "Old" refers to how many shares each player had +#. in the company ceasing existence. The maximum column width +#. is 8 characters (see MERGE_OLD_STOCK_COLS in src/intf.h). +#: src/move.c:872 +msgctxt "subtitle" +msgid "Old" +msgstr "Old" + +#: src/move.c:1019 +#, c-format +msgid "" +"%ls has been declared bankrupt by the Interstellar Trading Bank.\n" +"\n" +"^{All assets have been taken to repay outstanding loans.^}" +msgstr "" +"%ls has been declared bankrupt by the Interstellar Trading Bank.\n" +"\n" +"^{All assets have been taken to repay outstanding loans.^}" + +#: src/move.c:1041 +#, c-format +msgid "" +"%ls has been declared bankrupt by the Interstellar Trading Bank.\n" +"\n" +"^{The Bank has agreed to pay stock holders ^}%.2f%%^{ of the share value on " +"each share owned.^}" +msgstr "" +"%ls has been declared bankrupt by the Interstellar Trading Bank.\n" +"\n" +"^{The Bank has agreed to pay stock holders ^}%.2f%%^{ of the share value on " +"each share owned.^}" + +#. TRANSLATORS: The label "Amount paid per share" +#. refers to payment made by the Interstellar +#. Trading Bank to each player upon company +#. bankruptcy. This label MUST be the same +#. length as "Old share value" and MUST have at +#. least one trailing space for the display +#. routines to work correctly. The maximum +#. length is 28 characters. +#: src/move.c:1069 +msgctxt "label" +msgid "Amount paid per share: " +msgstr "Amount paid per share: " + +#. TRANSLATORS: "Old share value" refers to the +#. share price of a company before it was forced +#. into bankruptcy by the Bank. This label must be +#. the same width as "Amount paid per share". +#: src/move.c:1077 +msgctxt "label" +msgid "Old share value: " +msgstr "Old share value: " + +#: src/move.c:1170 src/exch.c:320 +msgid " Interstellar Trading Bank " +msgstr " Interstellar Trading Bank " + +#: src/move.c:1172 +#, c-format +msgid "" +"Your debt has amounted to %N!\n" +"^{The Bank has impounded ^}%N^{ from your cash.^}" +msgstr "" +"Your debt has amounted to %N!\n" +"^{The Bank has impounded ^}%N^{ from your cash.^}" + +#: src/exch.c:98 +msgid " Interstellar Stock Exchange " +msgstr " Interstellar Stock Exchange " + +#. TRANSLATORS: "Shares left" is a two-line column +#. label in a table containing the number of shares +#. left to be purchased in any given company. The +#. maximum column width is 10 characters (see +#. STOCK_LEFT_COLS in src/intf.h). +#: src/exch.c:127 +msgctxt "subtitle" +msgid "" +"Shares\n" +"left" +msgstr "" +"Shares\n" +"left" + +#. TRANSLATORS: "Shares issued" is a two-line column +#. label in a table containing the number of shares +#. already sold (ie, bought by all players) in any +#. given company. The maximum column width is 10 +#. characters (see STOCK_ISSUED_COLS in src/intf.h). +#: src/exch.c:134 +msgctxt "subtitle" +msgid "" +"Shares\n" +"issued" +msgstr "" +"Shares\n" +"issued" + +#: src/exch.c:185 +msgid "^{<2>^} Display galaxy map" +msgstr "^{<2>^} Display galaxy map" + +#: src/exch.c:187 +msgid "^{<3>^} Visit the Trading Bank" +msgstr "^{<3>^} Visit the Trading Bank" + +#: src/exch.c:189 +msgid "^{<4>^} Exit the Stock Exchange" +msgstr "^{<4>^} Exit the Stock Exchange" + +#: src/exch.c:192 +msgid "Enter selection [^[Company letter^]/^{1^}-^{4^}]: " +msgstr "Enter selection [^[Company letter^]/^{1^}-^{4^}]: " + +#. TRANSLATORS: The "Total value", "Current cash", "Current +#. debt", "Interest rate" and "Credit limit" labels MUST all be +#. the same length (ie, right-padded with spaces as needed) and +#. must have at least one trailing space so that the display +#. routines work correctly. The maximum length of each label +#. is 36 characters. +#. +#. Note that some of these labels are used for both the Player +#. Status window and the Trading Bank window. +#: src/exch.c:350 +msgctxt "label" +msgid "Credit limit: " +msgstr "Credit limit: " + +#. TRANSLATORS: The "Borrow money", "Repay debt" and "Exit +#. from the Bank" menu options must all be the same length +#. (ie, padded with trailing spaces as required). The maximum +#. length is 72 characters. +#: src/exch.c:365 +msgid "^{<1>^} Borrow money " +msgstr "^{<1>^} Borrow money " + +#: src/exch.c:367 +msgid "^{<2>^} Repay debt " +msgstr "^{<2>^} Repay debt " + +#: src/exch.c:369 +msgid "^{<3>^} Exit from the Bank" +msgstr "^{<3>^} Exit from the Bank" + +#: src/exch.c:372 +msgid "Enter selection [^{1^}-^{3^}]: " +msgstr "Enter selection [^{1^}-^{3^}]: " + +#: src/exch.c:425 +msgid " Insufficient Credit Limit " +msgstr " Insufficient Credit Limit " + +#: src/exch.c:426 +msgid "The Bank will not lend you any more money." +msgstr "The Bank will not lend you any more money." + +#: src/exch.c:446 +msgid "How much do you wish to borrow? " +msgstr "How much do you wish to borrow? " + +#: src/exch.c:478 +msgid " No Debt " +msgstr " No Debt " + +#: src/exch.c:479 +msgid "You have no debt to repay." +msgstr "You have no debt to repay." + +#: src/exch.c:483 +msgid " No Cash " +msgstr " No Cash " + +#: src/exch.c:484 +msgid "You have no cash with which to repay the debt!" +msgstr "You have no cash with which to repay the debt!" + +#: src/exch.c:504 +msgid "How much do you wish to repay? " +msgstr "How much do you wish to repay? " + +#. TRANSLATORS: %ls represents the company name. +#: src/exch.c:580 +#, c-format +msgid " Stock Transaction in %ls " +msgstr " Stock Transaction in %ls " + +#. TRANSLATORS: "Shares issued" represents the number of +#. shares already sold by the company to all players. +#. +#. Note that the labels "Shares issued", "Shares left", +#. "Price per share" and "Return" must all be the same length +#. and must have at least one trailing space for the output +#. routines to work correctly. The maximum length of each +#. label is 22 characters. +#: src/exch.c:591 +msgctxt "label|Stock A" +msgid "Shares issued: " +msgstr "Shares issued: " + +#. TRANSLATORS: "Shares left" is the number of shares that are +#. left to be purchased in the current company. +#: src/exch.c:599 +msgctxt "label|Stock A" +msgid "Shares left: " +msgstr "Shares left: " + +#. TRANSLATORS: "Price per share" is the cost of each share in +#. the current company. +#: src/exch.c:606 +msgctxt "label|Stock A" +msgid "Price per share: " +msgstr "Price per share: " + +#. TRANSLATORS: "Return" is the share return as a percentage. +#: src/exch.c:612 +msgctxt "label|Stock A" +msgid "Return: " +msgstr "Return: " + +#. TRANSLATORS: "Current holdings" is the number of shares the +#. current player owns in this particular company. +#. +#. Note that the labels "Current holdings", "Percentage owned" +#. and "Current cash" MUST all be the same length and contain at +#. least one trailing space for the display routines to work +#. correctly. The maximum length of each label is 18 +#. characters. +#: src/exch.c:625 +msgctxt "label|Stock B" +msgid "Current holdings: " +msgstr "Current holdings: " + +#. TRANSLATORS: "Percentage owned" is the current player's +#. percentage ownership in this particular company. +#: src/exch.c:632 +msgctxt "label|Stock B" +msgid "Percentage owned: " +msgstr "Percentage owned: " + +#: src/exch.c:637 +msgctxt "label|Stock B" +msgid "Current cash: " +msgstr "Current cash: " + +#: src/exch.c:648 +msgid "^{<1>^} Buy stock from company" +msgstr "^{<1>^} Buy stock from company" + +#: src/exch.c:650 +msgid "^{<2>^} Sell stock back to company" +msgstr "^{<2>^} Sell stock back to company" + +#: src/exch.c:652 +msgid "^{<3>^} Bid company to issue more shares" +msgstr "^{<3>^} Bid company to issue more shares" + +#: src/exch.c:654 +msgid "^{<4>^} Exit to the Stock Exchange" +msgstr "^{<4>^} Exit to the Stock Exchange" + +#: src/exch.c:657 +msgid "Enter selection [^{1^}-^{4^}]: " +msgstr "Enter selection [^{1^}-^{4^}]: " + +#: src/exch.c:713 +msgid " No Shares Available " +msgstr " No Shares Available " + +#: src/exch.c:714 +msgid "No more shares are available for purchase." +msgstr "No more shares are available for purchase." + +#: src/exch.c:718 +msgid " Insufficient Cash " +msgstr " Insufficient Cash " + +#: src/exch.c:719 +msgid "" +"You do not have enough cash\n" +"to purchase additional shares." +msgstr "" +"You do not have enough cash\n" +"to purchase additional shares." + +#: src/exch.c:730 +#, c-format +msgid "You can purchase ^{one^} share." +msgid_plural "You can purchase up to ^{%'ld^} shares." +msgstr[0] "You can purchase ^{one^} share." +msgstr[1] "You can purchase up to ^{%'ld^} shares." + +#: src/exch.c:736 +msgid "How many shares do you wish to purchase? " +msgstr "How many shares do you wish to purchase? " + +#: src/exch.c:757 +msgid " No Shares " +msgstr " No Shares " + +#: src/exch.c:758 +msgid "You do not have any shares to sell." +msgstr "You do not have any shares to sell." + +#: src/exch.c:765 +#, c-format +msgid "You can sell ^{one^} share." +msgid_plural "You can sell up to ^{%'ld^} shares." +msgstr[0] "You can sell ^{one^} share." +msgstr[1] "You can sell up to ^{%'ld^} shares." + +#: src/exch.c:771 +msgid "How many shares do you wish to sell? " +msgstr "How many shares do you wish to sell? " + +#: src/exch.c:799 +msgid " No Shares Issued " +msgstr " No Shares Issued " + +#. TRANSLATORS: %ls represents the company name. +#: src/exch.c:801 +#, c-format +msgid "" +"%ls has refused\n" +"to issue more shares." +msgstr "" +"%ls has refused\n" +"to issue more shares." + +#: src/exch.c:806 +msgid " Shares Issued " +msgstr " Shares Issued " + +#. TRANSLATORS: %ls represents the company name. +#: src/exch.c:808 +#, c-format +msgid "" +"%ls has issued\n" +"^{one^} more share." +msgid_plural "" +"%ls has issued\n" +"^{%'ld^} more shares." +msgstr[0] "" +"%ls has issued\n" +"^{one^} more share." +msgstr[1] "" +"%ls has issued\n" +"^{%'ld^} more shares." + +#: src/fileio.c:55 src/fileio.c:92 src/fileio.c:131 src/fileio.c:381 +#, c-format +msgid "%s: missing field on line %d" +msgstr "%s: missing field on line %d" + +#: src/fileio.c:60 +#, c-format +msgid "%s: illegal field on line %d: `%s'" +msgstr "%s: illegal field on line %d: ‘%s’" + +#: src/fileio.c:64 +#, c-format +msgid "%s: illegal value on line %d: `%s'" +msgstr "%s: illegal value on line %d: ‘%s’" + +#: src/fileio.c:96 src/fileio.c:135 src/fileio.c:393 +#, c-format +msgid "%s: illegal value on line %d" +msgstr "%s: illegal value on line %d" + +#: src/fileio.c:103 +#, c-format +msgid "%s: illegal characters on line %d" +msgstr "%s: illegal characters on line %d" + +#: src/fileio.c:184 +#, c-format +msgid "%s: could not convert string" +msgstr "%s: could not convert string" + +#: src/fileio.c:255 +msgid " Game Not Found " +msgstr " Game Not Found " + +#: src/fileio.c:256 +#, c-format +msgid "Game %d has not been saved to disk." +msgstr "Game %d has not been saved to disk." + +#: src/fileio.c:263 +msgid " Game Not Loaded " +msgstr " Game Not Loaded " + +#: src/fileio.c:264 +#, c-format +msgid "" +"Game %d could not be loaded from disk.\n" +"\n" +"^{File %s: %s^}" +msgstr "" +"Game %d could not be loaded from disk.\n" +"\n" +"^{File %s: %s^}" + +#: src/fileio.c:316 +#, c-format +msgid "%s: missing header in game file" +msgstr "%s: missing header in game file" + +#: src/fileio.c:319 +#, c-format +msgid "%s: not a valid game file" +msgstr "%s: not a valid game file" + +#: src/fileio.c:322 src/fileio.c:329 +#, c-format +msgid "%s: missing subheader in game file" +msgstr "%s: missing subheader in game file" + +#: src/fileio.c:325 +#, c-format +msgid "%s: saved under a different version of Star Traders" +msgstr "%s: saved under a different version of Star Traders" + +#: src/fileio.c:332 +#, c-format +msgid "%s: saved under an incompatible character encoding" +msgstr "%s: saved under an incompatible character encoding" + +#: src/fileio.c:340 +#, c-format +msgid "%s: illegal or missing field on line %d" +msgstr "%s: illegal or missing field on line %d" + +#: src/fileio.c:384 +#, c-format +msgid "%s: illegal field on line %d" +msgstr "%s: illegal field on line %d" + +#: src/fileio.c:466 src/fileio.c:487 +msgid " Game Not Saved " +msgstr " Game Not Saved " + +#: src/fileio.c:467 +#, c-format +msgid "" +"Game %d could not be saved to disk.\n" +"\n" +"^{Directory %s: %s^}" +msgstr "" +"Game %d could not be saved to disk.\n" +"\n" +"^{Directory %s: %s^}" + +#: src/fileio.c:488 +#, c-format +msgid "" +"Game %d could not be saved to disk.\n" +"\n" +"^{File %s: %s^}" +msgstr "" +"Game %d could not be saved to disk.\n" +"\n" +"^{File %s: %s^}" + +#. TRANSLATORS: The help text for Star Traders is marked up using a +#. custom mark-up format NOT used anywhere else in the source code. +#. +#. Each string is a single page of text that is displayed in an area 76 +#. columns wide by 16 lines high. Each line is delimited by "\n". NO +#. word-wrapping is performed: you must place the "\n" characters in the +#. appropriate place. Ideally, each line within the string should be +#. also (manually) space-justified or centred. TAB characters and other +#. control codes must NOT be used. If a string starts with "@" as the +#. very first character, that string is ignored (as are all strings +#. following): this allows a variable number of help text pages (from +#. one to ten). Multibyte strings are handled correctly (even those +#. requiring shift sequences!). +#. +#. The ASCII circumflex accent character "^" switches to a different +#. character rendition (also called attributes), depending on the +#. character following the "^": +#. +#. ^^ - Print the circumflex accent (ASCII code U+005E) +#. ^N - Switch to using the normal character rendition +#. ^B - Switch to using the bold character rendition +#. ^H - Switch to using the highlight character rendition +#. ^K - Switch to using the keycode character rendition (such as used for "") +#. ^e - Switch to using the character rendition used for empty space +#. ^o - Switch to using the character rendition used for outposts +#. ^s - Switch to using the character rendition used for stars +#. ^c - Switch to using the character rendition used for companies +#. ^k - Switch to using the character rendition used for keyboard choices on the galaxy map +#. +#. The help text parsing routines also understand the following "value +#. escapes" introduced by the ASCII tilde character "~"; these act like +#. "%" conversion specifiers in printf(): +#. +#. ~~ - Print the tilde character (ASCII code U+007E) [*] +#. ~x - Print the width of the galaxy map (MAX_X) [**] +#. ~y - Print the height of the galaxy map (MAX_Y) [**] +#. ~m - Print the number of moves available (NUMBER_MOVES) [**] +#. ~c - Print the maximum number of companies that can be formed (MAX_COMPANIES) [*] +#. ~t - Prints the default number of turns in the game (DEFAULT_MAX_TURN) [**] +#. ~1 to ~9 - Print the keycode for the N-th choice of move [***] +#. ~M - Print the keycode for the last choice of move [***] +#. ~A to ~H - Print the character used to represent the company on the galaxy map [***] +#. ~. - Print the character used to represent empty space on the map [***] +#. ~+ - Print the character used to represent outposts on the map [***] +#. ~* - Print the character used to represent stars on the map [***] +#. +#. [*] Takes one character space (column space) in the output +#. [**] Takes two column spaces in the output +#. [***] Takes one or two column spaces in the output, depending on the +#. appropriate strings in the current PO file. +#. +#. Note that all keycodes and map representation characters use locale- +#. specific characters; double-width characters ARE supported. Note +#. also that the tilde value escapes do NOT change the current character +#. rendition: a circumflex accent escape is needed for that. For +#. example, to display the first choice of move as it would be shown on +#. the galaxy map, use something like "^k~1^N" (a six-character sequence +#. that would translate to just one character (or maybe two) in the +#. output text). +#. +#: src/help.c:103 +msgid "" +"^BStar Traders^N is a simple game of interstellar trading. The object of " +"the\n" +"game is to amass the greatest amount of wealth possible. This is done " +"by\n" +"creating interstellar shipping lanes, expanding them and buying shares " +"in\n" +"the companies controlling them. Shares appreciate in value as " +"company\n" +"operations expand. In addition, the return on each share (as a " +"percentage)\n" +"also changes. Players may also borrow from the Interstellar Trading Bank " +"to\n" +"finance additional purchases on the Stock Exchange.\n" +"\n" +"The map of the galaxy is represented by a ^B~x^N x ^B~y^N grid. A typical " +"section\n" +"of it may be:\n" +"\n" +" ^e ~. ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" +" ^e ~. ~. ~. ~. ~. ~. ~. ~. ~. ^N ^e ~. ^N represents ^Bempty " +"space^N,\n" +" ^e ~. ^s~*^e ~. ~. ~. ~. ~. ~. ~. ^N ^s ~* ^N represents a " +"^Bstar^N.\n" +" ^e ~. ~. ~. ~. ~. ~. ~. ^s~*^e ~. ^N\n" +" ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ~. ^N\n" +msgstr "" +"^BStar Traders^N is a simple game of interstellar trading. The object of " +"the\n" +"game is to amass the greatest amount of wealth possible. This is done " +"by\n" +"creating interstellar shipping lanes, expanding them and buying shares " +"in\n" +"the companies controlling them. Shares appreciate in value as " +"company\n" +"operations expand. In addition, the return on each share (as a " +"percentage)\n" +"also changes. Players may also borrow from the Interstellar Trading Bank " +"to\n" +"finance additional purchases on the Stock Exchange.\n" +"\n" +"The map of the galaxy is represented by a ^B~x^N x ^B~y^N grid. A typical " +"section\n" +"of it may be:\n" +"\n" +" ^e ~. ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" +" ^e ~. ~. ~. ~. ~. ~. ~. ~. ~. ^N ^e ~. ^N represents ^Bempty " +"space^N,\n" +" ^e ~. ^s~*^e ~. ~. ~. ~. ~. ~. ~. ^N ^s ~* ^N represents a " +"^Bstar^N.\n" +" ^e ~. ~. ~. ~. ~. ~. ~. ^s~*^e ~. ^N\n" +" ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ~. ^N\n" + +#: src/help.c:122 +msgid "" +"The computer selects ^B~m^N moves (labeled ^k~1^N to ^k~M^N) at random, " +"and places these\n" +"on the map. To select any of the highlighted positions, press that " +"letter.\n" +"For example, some of the moves on the map may be:\n" +"\n" +"\n" +" ^e ^k~1^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" +" ^e ~. ~. ~. ^k~3^e ~. ~. ~. ~. ~. ^N\n" +" ^e ~. ^s~*^e ~. ~. ~. ~. ^k~5^e ~. ~. ^N Moves ^k~1^N to " +"^k~5^N shown.\n" +" ^e ~. ^k~2^e ~. ~. ^k~4^e ~. ~. ^s~*^e ~. ^N\n" +" ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ~. ^N\n" +"\n" +"\n" +"Selecting a position that is ^Bnot^N next to a star (such as moves " +"^k~1^N, ^k~3^N or ^k~5^N)\n" +"will set up an ^Boutpost^N, not belonging to any company. Thus, if move " +"^k~3^N is\n" +"selected on the above map, a ^o ~+ ^N would be placed at that position.\n" +msgstr "" +"The computer selects ^B~m^N moves (labeled ^k~1^N to ^k~M^N) at random, " +"and places these\n" +"on the map. To select any of the highlighted positions, press that " +"letter.\n" +"For example, some of the moves on the map may be:\n" +"\n" +"\n" +" ^e ^k~1^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" +" ^e ~. ~. ~. ^k~3^e ~. ~. ~. ~. ~. ^N\n" +" ^e ~. ^s~*^e ~. ~. ~. ~. ^k~5^e ~. ~. ^N Moves ^k~1^N to " +"^k~5^N shown.\n" +" ^e ~. ^k~2^e ~. ~. ^k~4^e ~. ~. ^s~*^e ~. ^N\n" +" ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ~. ^N\n" +"\n" +"\n" +"Selecting a position that is ^Bnot^N next to a star (such as moves " +"^k~1^N, ^k~3^N or ^k~5^N)\n" +"will set up an ^Boutpost^N, not belonging to any company. Thus, if move " +"^k~3^N is\n" +"selected on the above map, a ^o ~+ ^N would be placed at that position.\n" + +#: src/help.c:140 +msgid "" +"If, on the other hand, a position next to a star (or another outpost) " +"is\n" +"selected, a ^Bcompany^N would be formed and its letter would appear on the " +"map.\n" +"As a reward for creating the company, you are granted the first five " +"shares.\n" +"Up to ^B~c^N companies can be created in this way.\n" +"\n" +"If a position next to an existing company is selected, the company " +"would\n" +"expand its operations by one square. This increases the cost of its " +"shares\n" +"and hence your return. Thus, if the map was as shown below, selecting " +"^k~6^N\n" +"or ^k~8^N increases Company ^B~B^N's shipping lane:\n" +"\n" +" ^e ^k~1^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" +" ^e ~. ~. ~. ^o~+^e ~. ~. ^k~6^e ~. ~. ^N\n" +" ^e ~. ^s~*^e ~. ~. ~. ~. ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~6^N " +"or ^k~8^N increases Company ^B~B^N.\n" +" ^e ~. ^k~2^e ~. ~. ^k~4^e ~. ~. ^s~*^e ^c~B^e ^N\n" +" ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ^k~8^e ^N\n" +msgstr "" +"If, on the other hand, a position next to a star (or another outpost) " +"is\n" +"selected, a ^Bcompany^N would be formed and its letter would appear on the " +"map.\n" +"As a reward for creating the company, you are granted the first five " +"shares.\n" +"Up to ^B~c^N companies can be created in this way.\n" +"\n" +"If a position next to an existing company is selected, the company " +"would\n" +"expand its operations by one square. This increases the cost of its " +"shares\n" +"and hence your return. Thus, if the map was as shown below, selecting " +"^k~6^N\n" +"or ^k~8^N increases Company ^B~B^N’s shipping lane:\n" +"\n" +" ^e ^k~1^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" +" ^e ~. ~. ~. ^o~+^e ~. ~. ^k~6^e ~. ~. ^N\n" +" ^e ~. ^s~*^e ~. ~. ~. ~. ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~6^N " +"or ^k~8^N increases Company ^B~B^N.\n" +" ^e ~. ^k~2^e ~. ~. ^k~4^e ~. ~. ^s~*^e ^c~B^e ^N\n" +" ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ^k~8^e ^N\n" + +#: src/help.c:158 +msgid "" +"Selecting positions next to stars increases the value of your stock by " +"about\n" +"five times as much as an extension not next to a star. Thus move ^k~6^N " +"should\n" +"be preferred to move ^k~8^N.\n" +"\n" +" ^e ^c~C^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" +" ^e ^k~1^e ^o~+^e ~. ^o~+^e ~. ~. ^k~6^e ~. ~. ^N\n" +" ^e ~. ^s~*^e ~. ~. ~. ~. ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~6^N " +"is preferred to ^k~8^N.\n" +" ^e ~. ^k~2^e ~. ~. ^k~4^e ~. ~. ^s~*^e ^c~B^e ^N\n" +" ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ^k~8^e ^N\n" +"\n" +"You may also expand any company by selecting positions next to " +"outposts.\n" +"Such outposts will be swallowed up by that company. Thus, move ^k~1^N " +"will\n" +"extend Company ^B~C^N by ^Btwo^N squares. As a bonus, outposts next to " +"stars are\n" +"more valuable: the company's share price will increase by a greater " +"amount\n" +"than it would for outposts not next to stars.\n" +msgstr "" +"Selecting positions next to stars increases the value of your stock by " +"about\n" +"five times as much as an extension not next to a star. Thus move ^k~6^N " +"should\n" +"be preferred to move ^k~8^N.\n" +"\n" +" ^e ^c~C^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" +" ^e ^k~1^e ^o~+^e ~. ^o~+^e ~. ~. ^k~6^e ~. ~. ^N\n" +" ^e ~. ^s~*^e ~. ~. ~. ~. ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~6^N " +"is preferred to ^k~8^N.\n" +" ^e ~. ^k~2^e ~. ~. ^k~4^e ~. ~. ^s~*^e ^c~B^e ^N\n" +" ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ^k~8^e ^N\n" +"\n" +"You may also expand any company by selecting positions next to " +"outposts.\n" +"Such outposts will be swallowed up by that company. Thus, move ^k~1^N " +"will\n" +"extend Company ^B~C^N by ^Btwo^N squares. As a bonus, outposts next to " +"stars are\n" +"more valuable: the company’s share price will increase by a greater " +"amount\n" +"than it would for outposts not next to stars.\n" + +#: src/help.c:176 +msgid "" +"If two companies are separated on the map by only one square, then they " +"can\n" +"be ^Bmerged^N into one company by selecting that position (if available). " +"For\n" +"example, on the map below, companies ^B~A^N and ^B~B^N can be merged by " +"selecting ^k~5^N.\n" +"When this occurs, the company with the greater assets value takes over " +"the\n" +"other one. Here, Company ^B~B^N might take over Company ^B~A^N. Company " +"^B~A^N ceases to\n" +"exist, although it may reappear as an entirely new company at a later " +"stage.\n" +"\n" +" ^e ^k~1^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" +" ^e ~. ~. ~. ^c~A^e ^c~A^e ^k~5^e ^c~B^e ~. ~. ^N\n" +" ^e ~. ^s~*^e ~. ~. ^c~A^e ~. ^c~B^e ^c~B^e ^c~B^e ^N Move " +"^k~5^N merges companies ^B~A^N and ^B~B^N.\n" +" ^e ~. ^k~2^e ~. ~. ~. ~. ~. ^s~*^e ^c~B^e ^N\n" +" ^e ~. ~. ~. ~. ^s~*^e ~. ^o~+^e ~. ~. ^N\n" +"\n" +"When companies merge, players are granted shares in the dominant " +"company\n" +"proportional to the amount owned in the old company. As well, a cash " +"bonus\n" +"is also paid, proportional to the percentage of the old company owned.\n" +msgstr "" +"If two companies are separated on the map by only one square, then they " +"can\n" +"be ^Bmerged^N into one company by selecting that position (if available). " +"For\n" +"example, on the map below, companies ^B~A^N and ^B~B^N can be merged by " +"selecting ^k~5^N.\n" +"When this occurs, the company with the greater assets value takes over " +"the\n" +"other one. Here, Company ^B~B^N might take over Company ^B~A^N. Company " +"^B~A^N ceases to\n" +"exist, although it may reappear as an entirely new company at a later " +"stage.\n" +"\n" +" ^e ^k~1^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" +" ^e ~. ~. ~. ^c~A^e ^c~A^e ^k~5^e ^c~B^e ~. ~. ^N\n" +" ^e ~. ^s~*^e ~. ~. ^c~A^e ~. ^c~B^e ^c~B^e ^c~B^e ^N Move " +"^k~5^N merges companies ^B~A^N and ^B~B^N.\n" +" ^e ~. ^k~2^e ~. ~. ~. ~. ~. ^s~*^e ^c~B^e ^N\n" +" ^e ~. ~. ~. ~. ^s~*^e ~. ^o~+^e ~. ~. ^N\n" +"\n" +"When companies merge, players are granted shares in the dominant " +"company\n" +"proportional to the amount owned in the old company. As well, a cash " +"bonus\n" +"is also paid, proportional to the percentage of the old company owned.\n" + +#: src/help.c:195 +msgid "" +"Once you select your move, you enter the ^BInterstellar Stock Exchange^N. " +"Here\n" +"you may purchase shares, sell them, borrow from the Trading Bank or " +"repay\n" +"some of your debt (if applicable). Note that each company issues a " +"limited\n" +"number of shares -- you cannot go on buying for ever! You may, however, " +"bid\n" +"for more shares to be issued. You have a better chance of succeeding if " +"you\n" +"own a larger proportion of the company.\n" +"\n" +"The game usually ends after ^B~t^N turns. However, you may end the game " +"sooner\n" +"by pressing ^K^N when asked to select a move. As well, " +"individual\n" +"players can declare themselves bankrupt at any time. If your debt is " +"large\n" +"enough, the Bank may do this for you! If you do not complete your game " +"in\n" +"the time you have available, you may save the game and continue it later.\n" +"\n" +"\n" +"The ^Bwinner of the game^N is the person with the greatest net worth " +"(total\n" +"value of cash, stock and debt). ^HGood luck^N and may the best person win!\n" +msgstr "" +"Once you select your move, you enter the ^BInterstellar Stock Exchange^N. " +"Here\n" +"you may purchase shares, sell them, borrow from the Trading Bank or " +"repay\n" +"some of your debt (if applicable). Note that each company issues a " +"limited\n" +"number of shares -- you cannot go on buying for ever! You may, however, " +"bid\n" +"for more shares to be issued. You have a better chance of succeeding if " +"you\n" +"own a larger proportion of the company.\n" +"\n" +"The game usually ends after ^B~t^N turns. However, you may end the game " +"sooner\n" +"by pressing ^K^N when asked to select a move. As well, " +"individual\n" +"players can declare themselves bankrupt at any time. If your debt is " +"large\n" +"enough, the Bank may do this for you! If you do not complete your game " +"in\n" +"the time you have available, you may save the game and continue it later.\n" +"\n" +"\n" +"The ^Bwinner of the game^N is the person with the greatest net worth " +"(total\n" +"value of cash, stock and debt). ^HGood luck^N and may the best person win!\n" + +#: src/help.c:215 +msgid "@ Help text, page 7" +msgstr "@ Help text, page 7" + +#: src/help.c:216 +msgid "@ Help text, page 8" +msgstr "@ Help text, page 8" + +#: src/help.c:217 +msgid "@ Help text, page 9" +msgstr "@ Help text, page 9" + +#: src/help.c:218 +msgid "@ Help text, page 10" +msgstr "@ Help text, page 10" + +#: src/help.c:270 +msgid " How to Play " +msgstr " How to Play " + +#: src/help.c:272 +#, c-format +msgid "Page %d of %d" +msgstr "Page %d of %d" + +#. TRANSLATORS: The reason the user is not asked "Press any +#. key to continue" is historical: many, many people used to +#. ask "where is the key?" :-) +#: src/help.c:473 src/intf.c:3022 +msgid "[ Press to continue ] " +msgstr "[ Press to continue ] " + +#. TRANSLATORS: The specific use of and +#. is not essential: you can use , +#. , , or instead of +#. , and almost any other key instead of +#. (other than , , , , +#. or <\>). +#: src/help.c:480 +msgid "[ Press to continue or for the previous page ] " +msgstr "[ Press to continue or for the previous page ] " + +#: src/intf.c:110 +#, c-format +msgid "%s: string has incorrect format: `%s'" +msgstr "%s: string has incorrect format: ‘%s’" + +#: src/intf.c:126 +#, c-format +msgid "%s: character has illegal width: `%lc'" +msgstr "%s: character has illegal width: ‘%lc’" + +#: src/intf.c:434 +#, c-format +msgid "terminal size is too small (%d x %d required)" +msgstr "terminal size is too small (%d x %d required)" + +#: src/intf.c:610 +msgid "Star Traders" +msgstr "Star Traders" + +#: src/intf.c:1262 +msgid "mkchstr_conv: NUL" +msgstr "mkchstr_conv: NUL" + +#: src/intf.c:1565 +#, c-format +msgid "mkchstr: `%s'" +msgstr "mkchstr: ‘%s’" + +#: src/intf.c:2022 src/intf.c:2067 +#, c-format +msgid "gettxline: illegal character in string: `%ls'" +msgstr "gettxline: illegal character in string: ‘%ls’" + +#. TRANSLATORS: The strings with msgctxt "input|Yes" and +#. "input|No" contain the keycodes used to determine whether a +#. user is answering "Yes" or "No" in response to some question. +#. Both upper and lower-case versions should be present. +#: src/intf.c:2939 +msgctxt "input|Yes" +msgid "Yy" +msgstr "Yy" + +#: src/intf.c:2941 +msgctxt "input|No" +msgid "Nn" +msgstr "Nn" + +#. TRANSLATORS: The strings "Yes" and "No" are printed as a +#. response to user input in answer to questions like "Are you +#. sure? [Y/N] " +#: src/intf.c:2992 +msgctxt "answer" +msgid "Yes" +msgstr "Yes" + +#: src/intf.c:2994 +msgctxt "answer" +msgid "No" +msgstr "No" + +#: src/utils.c:199 src/utils.c:220 +#, c-format +msgid "%s: " +msgstr "%s: " + +#: src/utils.c:225 +msgid ": " +msgstr ": " + +#: src/utils.c:238 +msgid "out of memory" +msgstr "out of memory" + +#: src/utils.c:571 +#, c-format +msgid "xmbstowcs: `%s'" +msgstr "xmbstowcs: ‘%s’" + +#: src/utils.c:611 +msgid "xwcrtomb: NUL" +msgstr "xwcrtomb: NUL" + +#: src/utils.c:616 +#, c-format +msgid "xwcrtomb: `%lc'" +msgstr "xwcrtomb: ‘%lc’" + +#: lib/getopt.c:547 lib/getopt.c:576 +#, c-format +msgid "%s: option '%s' is ambiguous; possibilities:" +msgstr "%s: option ‘%s’ is ambiguous; possibilities:" + +#: lib/getopt.c:624 lib/getopt.c:628 +#, c-format +msgid "%s: option '--%s' doesn't allow an argument\n" +msgstr "%s: option ‘--%s’ doesn’t allow an argument\n" + +#: lib/getopt.c:637 lib/getopt.c:642 +#, c-format +msgid "%s: option '%c%s' doesn't allow an argument\n" +msgstr "%s: option ‘%c%s’ doesn’t allow an argument\n" + +#: lib/getopt.c:685 lib/getopt.c:704 +#, c-format +msgid "%s: option '--%s' requires an argument\n" +msgstr "%s: option ‘--%s’ requires an argument\n" + +#: lib/getopt.c:742 lib/getopt.c:745 +#, c-format +msgid "%s: unrecognized option '--%s'\n" +msgstr "%s: unrecognized option ‘--%s’\n" + +#: lib/getopt.c:753 lib/getopt.c:756 +#, c-format +msgid "%s: unrecognized option '%c%s'\n" +msgstr "%s: unrecognized option ‘%c%s’\n" + +#: lib/getopt.c:805 lib/getopt.c:808 +#, c-format +msgid "%s: invalid option -- '%c'\n" +msgstr "%s: invalid option -- ‘%c’\n" + +#: lib/getopt.c:861 lib/getopt.c:878 lib/getopt.c:1088 lib/getopt.c:1106 +#, c-format +msgid "%s: option requires an argument -- '%c'\n" +msgstr "%s: option requires an argument -- ‘%c’\n" + +#: lib/getopt.c:934 lib/getopt.c:950 +#, c-format +msgid "%s: option '-W %s' is ambiguous\n" +msgstr "%s: option ‘-W %s’ is ambiguous\n" + +#: lib/getopt.c:974 lib/getopt.c:992 +#, c-format +msgid "%s: option '-W %s' doesn't allow an argument\n" +msgstr "%s: option ‘-W %s’ doesn’t allow an argument\n" + +#: lib/getopt.c:1013 lib/getopt.c:1031 +#, c-format +msgid "%s: option '-W %s' requires an argument\n" +msgstr "%s: option ‘-W %s’ requires an argument\n" From 39ac89e1cdb9708011d84a1223b38b5bc7d173fb Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Sun, 28 Aug 2011 16:59:59 +1000 Subject: [PATCH 102/112] Remove unwanted word-wrapping from the Star Traders help text --- po/en_AU.po | 284 ++++++++++++++++++---------------------------------- po/en_GB.po | 284 ++++++++++++++++++---------------------------------- po/en_US.po | 284 ++++++++++++++++++---------------------------------- 3 files changed, 285 insertions(+), 567 deletions(-) diff --git a/po/en_AU.po b/po/en_AU.po index e4251ef..74995d9 100644 --- a/po/en_AU.po +++ b/po/en_AU.po @@ -15,7 +15,7 @@ msgstr "" "Project-Id-Version: trader 7.2\n" "Report-Msgid-Bugs-To: J.Zaitseff@zap.org.au\n" "POT-Creation-Date: 2011-08-28 14:55+1000\n" -"PO-Revision-Date: 2011-08-28 16:00+1000\n" +"PO-Revision-Date: 2011-08-28 16:50+1000\n" "Last-Translator: John Zaitseff \n" "Language-Team: English (Australian)\n" "Language: en_AU\n" @@ -1175,306 +1175,212 @@ msgstr "" #. #: src/help.c:103 msgid "" -"^BStar Traders^N is a simple game of interstellar trading. The object of " -"the\n" -"game is to amass the greatest amount of wealth possible. This is done " -"by\n" -"creating interstellar shipping lanes, expanding them and buying shares " -"in\n" -"the companies controlling them. Shares appreciate in value as " -"company\n" -"operations expand. In addition, the return on each share (as a " -"percentage)\n" -"also changes. Players may also borrow from the Interstellar Trading Bank " -"to\n" +"^BStar Traders^N is a simple game of interstellar trading. The object of the\n" +"game is to amass the greatest amount of wealth possible. This is done by\n" +"creating interstellar shipping lanes, expanding them and buying shares in\n" +"the companies controlling them. Shares appreciate in value as company\n" +"operations expand. In addition, the return on each share (as a percentage)\n" +"also changes. Players may also borrow from the Interstellar Trading Bank to\n" "finance additional purchases on the Stock Exchange.\n" "\n" -"The map of the galaxy is represented by a ^B~x^N x ^B~y^N grid. A typical " -"section\n" +"The map of the galaxy is represented by a ^B~x^N x ^B~y^N grid. A typical section\n" "of it may be:\n" "\n" " ^e ~. ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" -" ^e ~. ~. ~. ~. ~. ~. ~. ~. ~. ^N ^e ~. ^N represents ^Bempty " -"space^N,\n" -" ^e ~. ^s~*^e ~. ~. ~. ~. ~. ~. ~. ^N ^s ~* ^N represents a " -"^Bstar^N.\n" +" ^e ~. ~. ~. ~. ~. ~. ~. ~. ~. ^N ^e ~. ^N represents ^Bempty space^N,\n" +" ^e ~. ^s~*^e ~. ~. ~. ~. ~. ~. ~. ^N ^s ~* ^N represents a ^Bstar^N.\n" " ^e ~. ~. ~. ~. ~. ~. ~. ^s~*^e ~. ^N\n" " ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ~. ^N\n" msgstr "" -"^BStar Traders^N is a simple game of interstellar trading. The object of " -"the\n" -"game is to amass the greatest amount of wealth possible. This is done " -"by\n" -"creating interstellar shipping lanes, expanding them and buying shares " -"in\n" -"the companies controlling them. Shares appreciate in value as " -"company\n" -"operations expand. In addition, the return on each share (as a " -"percentage)\n" -"also changes. Players may also borrow from the Interstellar Trading Bank " -"to\n" +"^BStar Traders^N is a simple game of interstellar trading. The object of the\n" +"game is to amass the greatest amount of wealth possible. This is done by\n" +"creating interstellar shipping lanes, expanding them and buying shares in\n" +"the companies controlling them. Shares appreciate in value as company\n" +"operations expand. In addition, the return on each share (as a percentage)\n" +"also changes. Players may also borrow from the Interstellar Trading Bank to\n" "finance additional purchases on the Stock Exchange.\n" "\n" -"The map of the galaxy is represented by a ^B~x^N x ^B~y^N grid. A typical " -"section\n" +"The map of the galaxy is represented by a ^B~x^N x ^B~y^N grid. A typical section\n" "of it may be:\n" "\n" " ^e ~. ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" -" ^e ~. ~. ~. ~. ~. ~. ~. ~. ~. ^N ^e ~. ^N represents ^Bempty " -"space^N,\n" -" ^e ~. ^s~*^e ~. ~. ~. ~. ~. ~. ~. ^N ^s ~* ^N represents a " -"^Bstar^N.\n" +" ^e ~. ~. ~. ~. ~. ~. ~. ~. ~. ^N ^e ~. ^N represents ^Bempty space^N,\n" +" ^e ~. ^s~*^e ~. ~. ~. ~. ~. ~. ~. ^N ^s ~* ^N represents a ^Bstar^N.\n" " ^e ~. ~. ~. ~. ~. ~. ~. ^s~*^e ~. ^N\n" " ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ~. ^N\n" #: src/help.c:122 msgid "" -"The computer selects ^B~m^N moves (labeled ^k~1^N to ^k~M^N) at random, " -"and places these\n" -"on the map. To select any of the highlighted positions, press that " -"letter.\n" +"The computer selects ^B~m^N moves (labeled ^k~1^N to ^k~M^N) at random, and places these\n" +"on the map. To select any of the highlighted positions, press that letter.\n" "For example, some of the moves on the map may be:\n" "\n" "\n" " ^e ^k~1^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" " ^e ~. ~. ~. ^k~3^e ~. ~. ~. ~. ~. ^N\n" -" ^e ~. ^s~*^e ~. ~. ~. ~. ^k~5^e ~. ~. ^N Moves ^k~1^N to " -"^k~5^N shown.\n" +" ^e ~. ^s~*^e ~. ~. ~. ~. ^k~5^e ~. ~. ^N Moves ^k~1^N to ^k~5^N shown.\n" " ^e ~. ^k~2^e ~. ~. ^k~4^e ~. ~. ^s~*^e ~. ^N\n" " ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ~. ^N\n" "\n" "\n" -"Selecting a position that is ^Bnot^N next to a star (such as moves " -"^k~1^N, ^k~3^N or ^k~5^N)\n" -"will set up an ^Boutpost^N, not belonging to any company. Thus, if move " -"^k~3^N is\n" +"Selecting a position that is ^Bnot^N next to a star (such as moves ^k~1^N, ^k~3^N or ^k~5^N)\n" +"will set up an ^Boutpost^N, not belonging to any company. Thus, if move ^k~3^N is\n" "selected on the above map, a ^o ~+ ^N would be placed at that position.\n" msgstr "" -"The computer selects ^B~m^N moves (labelled ^k~1^N to ^k~M^N) at random, " -"and places these\n" -"on the map. To select any of the highlighted positions, press that " -"letter.\n" +"The computer selects ^B~m^N moves (labelled ^k~1^N to ^k~M^N) at random, and places these\n" +"on the map. To select any of the highlighted positions, press that letter.\n" "For example, some of the moves on the map may be:\n" "\n" "\n" " ^e ^k~1^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" " ^e ~. ~. ~. ^k~3^e ~. ~. ~. ~. ~. ^N\n" -" ^e ~. ^s~*^e ~. ~. ~. ~. ^k~5^e ~. ~. ^N Moves ^k~1^N to " -"^k~5^N shown.\n" +" ^e ~. ^s~*^e ~. ~. ~. ~. ^k~5^e ~. ~. ^N Moves ^k~1^N to ^k~5^N shown.\n" " ^e ~. ^k~2^e ~. ~. ^k~4^e ~. ~. ^s~*^e ~. ^N\n" " ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ~. ^N\n" "\n" "\n" -"Selecting a position that is ^Bnot^N next to a star (such as moves " -"^k~1^N, ^k~3^N or ^k~5^N)\n" -"will set up an ^Boutpost^N, not belonging to any company. Thus, if move " -"^k~3^N is\n" +"Selecting a position that is ^Bnot^N next to a star (such as moves ^k~1^N, ^k~3^N or ^k~5^N)\n" +"will set up an ^Boutpost^N, not belonging to any company. Thus, if move ^k~3^N is\n" "selected on the above map, a ^o ~+ ^N would be placed at that position.\n" #: src/help.c:140 msgid "" -"If, on the other hand, a position next to a star (or another outpost) " -"is\n" -"selected, a ^Bcompany^N would be formed and its letter would appear on the " -"map.\n" -"As a reward for creating the company, you are granted the first five " -"shares.\n" +"If, on the other hand, a position next to a star (or another outpost) is\n" +"selected, a ^Bcompany^N would be formed and its letter would appear on the map.\n" +"As a reward for creating the company, you are granted the first five shares.\n" "Up to ^B~c^N companies can be created in this way.\n" "\n" -"If a position next to an existing company is selected, the company " -"would\n" -"expand its operations by one square. This increases the cost of its " -"shares\n" -"and hence your return. Thus, if the map was as shown below, selecting " -"^k~6^N\n" +"If a position next to an existing company is selected, the company would\n" +"expand its operations by one square. This increases the cost of its shares\n" +"and hence your return. Thus, if the map was as shown below, selecting ^k~6^N\n" "or ^k~8^N increases Company ^B~B^N's shipping lane:\n" "\n" " ^e ^k~1^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" " ^e ~. ~. ~. ^o~+^e ~. ~. ^k~6^e ~. ~. ^N\n" -" ^e ~. ^s~*^e ~. ~. ~. ~. ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~6^N " -"or ^k~8^N increases Company ^B~B^N.\n" +" ^e ~. ^s~*^e ~. ~. ~. ~. ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~6^N or ^k~8^N increases Company ^B~B^N.\n" " ^e ~. ^k~2^e ~. ~. ^k~4^e ~. ~. ^s~*^e ^c~B^e ^N\n" " ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ^k~8^e ^N\n" msgstr "" -"If, on the other hand, a position next to a star (or another outpost) " -"is\n" -"selected, a ^Bcompany^N would be formed and its letter would appear on the " -"map.\n" -"As a reward for creating the company, you are granted the first five " -"shares.\n" +"If, on the other hand, a position next to a star (or another outpost) is\n" +"selected, a ^Bcompany^N would be formed and its letter would appear on the map.\n" +"As a reward for creating the company, you are granted the first five shares.\n" "Up to ^B~c^N companies can be created in this way.\n" "\n" -"If a position next to an existing company is selected, the company " -"would\n" -"expand its operations by one square. This increases the cost of its " -"shares\n" -"and hence your return. Thus, if the map was as shown below, selecting " -"^k~6^N\n" +"If a position next to an existing company is selected, the company would\n" +"expand its operations by one square. This increases the cost of its shares\n" +"and hence your return. Thus, if the map was as shown below, selecting ^k~6^N\n" "or ^k~8^N increases Company ^B~B^N’s shipping lane:\n" "\n" " ^e ^k~1^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" " ^e ~. ~. ~. ^o~+^e ~. ~. ^k~6^e ~. ~. ^N\n" -" ^e ~. ^s~*^e ~. ~. ~. ~. ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~6^N " -"or ^k~8^N increases Company ^B~B^N.\n" +" ^e ~. ^s~*^e ~. ~. ~. ~. ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~6^N or ^k~8^N increases Company ^B~B^N.\n" " ^e ~. ^k~2^e ~. ~. ^k~4^e ~. ~. ^s~*^e ^c~B^e ^N\n" " ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ^k~8^e ^N\n" #: src/help.c:158 msgid "" -"Selecting positions next to stars increases the value of your stock by " -"about\n" -"five times as much as an extension not next to a star. Thus move ^k~6^N " -"should\n" +"Selecting positions next to stars increases the value of your stock by about\n" +"five times as much as an extension not next to a star. Thus move ^k~6^N should\n" "be preferred to move ^k~8^N.\n" "\n" " ^e ^c~C^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" " ^e ^k~1^e ^o~+^e ~. ^o~+^e ~. ~. ^k~6^e ~. ~. ^N\n" -" ^e ~. ^s~*^e ~. ~. ~. ~. ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~6^N " -"is preferred to ^k~8^N.\n" +" ^e ~. ^s~*^e ~. ~. ~. ~. ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~6^N is preferred to ^k~8^N.\n" " ^e ~. ^k~2^e ~. ~. ^k~4^e ~. ~. ^s~*^e ^c~B^e ^N\n" " ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ^k~8^e ^N\n" "\n" -"You may also expand any company by selecting positions next to " -"outposts.\n" -"Such outposts will be swallowed up by that company. Thus, move ^k~1^N " -"will\n" -"extend Company ^B~C^N by ^Btwo^N squares. As a bonus, outposts next to " -"stars are\n" -"more valuable: the company's share price will increase by a greater " -"amount\n" +"You may also expand any company by selecting positions next to outposts.\n" +"Such outposts will be swallowed up by that company. Thus, move ^k~1^N will\n" +"extend Company ^B~C^N by ^Btwo^N squares. As a bonus, outposts next to stars are\n" +"more valuable: the company's share price will increase by a greater amount\n" "than it would for outposts not next to stars.\n" msgstr "" -"Selecting positions next to stars increases the value of your stock by " -"about\n" -"five times as much as an extension not next to a star. Thus move ^k~6^N " -"should\n" +"Selecting positions next to stars increases the value of your stock by about\n" +"five times as much as an extension not next to a star. Thus move ^k~6^N should\n" "be preferred to move ^k~8^N.\n" "\n" " ^e ^c~C^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" " ^e ^k~1^e ^o~+^e ~. ^o~+^e ~. ~. ^k~6^e ~. ~. ^N\n" -" ^e ~. ^s~*^e ~. ~. ~. ~. ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~6^N " -"is preferred to ^k~8^N.\n" +" ^e ~. ^s~*^e ~. ~. ~. ~. ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~6^N is preferred to ^k~8^N.\n" " ^e ~. ^k~2^e ~. ~. ^k~4^e ~. ~. ^s~*^e ^c~B^e ^N\n" " ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ^k~8^e ^N\n" "\n" -"You may also expand any company by selecting positions next to " -"outposts.\n" -"Such outposts will be swallowed up by that company. Thus, move ^k~1^N " -"will\n" -"extend Company ^B~C^N by ^Btwo^N squares. As a bonus, outposts next to " -"stars are\n" -"more valuable: the company’s share price will increase by a greater " -"amount\n" +"You may also expand any company by selecting positions next to outposts.\n" +"Such outposts will be swallowed up by that company. Thus, move ^k~1^N will\n" +"extend Company ^B~C^N by ^Btwo^N squares. As a bonus, outposts next to stars are\n" +"more valuable: the company’s share price will increase by a greater amount\n" "than it would for outposts not next to stars.\n" #: src/help.c:176 msgid "" -"If two companies are separated on the map by only one square, then they " -"can\n" -"be ^Bmerged^N into one company by selecting that position (if available). " -"For\n" -"example, on the map below, companies ^B~A^N and ^B~B^N can be merged by " -"selecting ^k~5^N.\n" -"When this occurs, the company with the greater assets value takes over " -"the\n" -"other one. Here, Company ^B~B^N might take over Company ^B~A^N. Company " -"^B~A^N ceases to\n" -"exist, although it may reappear as an entirely new company at a later " -"stage.\n" +"If two companies are separated on the map by only one square, then they can\n" +"be ^Bmerged^N into one company by selecting that position (if available). For\n" +"example, on the map below, companies ^B~A^N and ^B~B^N can be merged by selecting ^k~5^N.\n" +"When this occurs, the company with the greater assets value takes over the\n" +"other one. Here, Company ^B~B^N might take over Company ^B~A^N. Company ^B~A^N ceases to\n" +"exist, although it may reappear as an entirely new company at a later stage.\n" "\n" " ^e ^k~1^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" " ^e ~. ~. ~. ^c~A^e ^c~A^e ^k~5^e ^c~B^e ~. ~. ^N\n" -" ^e ~. ^s~*^e ~. ~. ^c~A^e ~. ^c~B^e ^c~B^e ^c~B^e ^N Move " -"^k~5^N merges companies ^B~A^N and ^B~B^N.\n" +" ^e ~. ^s~*^e ~. ~. ^c~A^e ~. ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~5^N merges companies ^B~A^N and ^B~B^N.\n" " ^e ~. ^k~2^e ~. ~. ~. ~. ~. ^s~*^e ^c~B^e ^N\n" " ^e ~. ~. ~. ~. ^s~*^e ~. ^o~+^e ~. ~. ^N\n" "\n" -"When companies merge, players are granted shares in the dominant " -"company\n" -"proportional to the amount owned in the old company. As well, a cash " -"bonus\n" +"When companies merge, players are granted shares in the dominant company\n" +"proportional to the amount owned in the old company. As well, a cash bonus\n" "is also paid, proportional to the percentage of the old company owned.\n" msgstr "" -"If two companies are separated on the map by only one square, then they " -"can\n" -"be ^Bmerged^N into one company by selecting that position (if available). " -"For\n" -"example, on the map below, companies ^B~A^N and ^B~B^N can be merged by " -"selecting ^k~5^N.\n" -"When this occurs, the company with the greater assets value takes over " -"the\n" -"other one. Here, Company ^B~B^N might take over Company ^B~A^N. Company " -"^B~A^N ceases to\n" -"exist, although it may reappear as an entirely new company at a later " -"stage.\n" +"If two companies are separated on the map by only one square, then they can\n" +"be ^Bmerged^N into one company by selecting that position (if available). For\n" +"example, on the map below, companies ^B~A^N and ^B~B^N can be merged by selecting ^k~5^N.\n" +"When this occurs, the company with the greater assets value takes over the\n" +"other one. Here, Company ^B~B^N might take over Company ^B~A^N. Company ^B~A^N ceases to\n" +"exist, although it may reappear as an entirely new company at a later stage.\n" "\n" " ^e ^k~1^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" " ^e ~. ~. ~. ^c~A^e ^c~A^e ^k~5^e ^c~B^e ~. ~. ^N\n" -" ^e ~. ^s~*^e ~. ~. ^c~A^e ~. ^c~B^e ^c~B^e ^c~B^e ^N Move " -"^k~5^N merges companies ^B~A^N and ^B~B^N.\n" +" ^e ~. ^s~*^e ~. ~. ^c~A^e ~. ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~5^N merges companies ^B~A^N and ^B~B^N.\n" " ^e ~. ^k~2^e ~. ~. ~. ~. ~. ^s~*^e ^c~B^e ^N\n" " ^e ~. ~. ~. ~. ^s~*^e ~. ^o~+^e ~. ~. ^N\n" "\n" -"When companies merge, players are granted shares in the dominant " -"company\n" -"proportional to the amount owned in the old company. As well, a cash " -"bonus\n" +"When companies merge, players are granted shares in the dominant company\n" +"proportional to the amount owned in the old company. As well, a cash bonus\n" "is also paid, proportional to the percentage of the old company owned.\n" #: src/help.c:195 msgid "" -"Once you select your move, you enter the ^BInterstellar Stock Exchange^N. " -"Here\n" -"you may purchase shares, sell them, borrow from the Trading Bank or " -"repay\n" -"some of your debt (if applicable). Note that each company issues a " -"limited\n" -"number of shares -- you cannot go on buying for ever! You may, however, " -"bid\n" -"for more shares to be issued. You have a better chance of succeeding if " -"you\n" +"Once you select your move, you enter the ^BInterstellar Stock Exchange^N. Here\n" +"you may purchase shares, sell them, borrow from the Trading Bank or repay\n" +"some of your debt (if applicable). Note that each company issues a limited\n" +"number of shares -- you cannot go on buying for ever! You may, however, bid\n" +"for more shares to be issued. You have a better chance of succeeding if you\n" "own a larger proportion of the company.\n" "\n" -"The game usually ends after ^B~t^N turns. However, you may end the game " -"sooner\n" -"by pressing ^K^N when asked to select a move. As well, " -"individual\n" -"players can declare themselves bankrupt at any time. If your debt is " -"large\n" -"enough, the Bank may do this for you! If you do not complete your game " -"in\n" +"The game usually ends after ^B~t^N turns. However, you may end the game sooner\n" +"by pressing ^K^N when asked to select a move. As well, individual\n" +"players can declare themselves bankrupt at any time. If your debt is large\n" +"enough, the Bank may do this for you! If you do not complete your game in\n" "the time you have available, you may save the game and continue it later.\n" "\n" "\n" -"The ^Bwinner of the game^N is the person with the greatest net worth " -"(total\n" +"The ^Bwinner of the game^N is the person with the greatest net worth (total\n" "value of cash, stock and debt). ^HGood luck^N and may the best person win!\n" msgstr "" -"Once you select your move, you enter the ^BInterstellar Stock Exchange^N. " -"Here\n" -"you may purchase shares, sell them, borrow from the Trading Bank or " -"repay\n" -"some of your debt (if applicable). Note that each company issues a " -"limited\n" -"number of shares -- you cannot go on buying for ever! You may, however, " -"bid\n" -"for more shares to be issued. You have a better chance of succeeding if " -"you\n" +"Once you select your move, you enter the ^BInterstellar Stock Exchange^N. Here\n" +"you may purchase shares, sell them, borrow from the Trading Bank or repay\n" +"some of your debt (if applicable). Note that each company issues a limited\n" +"number of shares -- you cannot go on buying for ever! You may, however, bid\n" +"for more shares to be issued. You have a better chance of succeeding if you\n" "own a larger proportion of the company.\n" "\n" -"The game usually ends after ^B~t^N turns. However, you may end the game " -"sooner\n" -"by pressing ^K^N when asked to select a move. As well, " -"individual\n" -"players can declare themselves bankrupt at any time. If your debt is " -"large\n" -"enough, the Bank may do this for you! If you do not complete your game " -"in\n" +"The game usually ends after ^B~t^N turns. However, you may end the game sooner\n" +"by pressing ^K^N when asked to select a move. As well, individual\n" +"players can declare themselves bankrupt at any time. If your debt is large\n" +"enough, the Bank may do this for you! If you do not complete your game in\n" "the time you have available, you may save the game and continue it later.\n" "\n" "\n" -"The ^Bwinner of the game^N is the person with the greatest net worth " -"(total\n" +"The ^Bwinner of the game^N is the person with the greatest net worth (total\n" "value of cash, stock and debt). ^HGood luck^N and may the best person win!\n" #: src/help.c:215 diff --git a/po/en_GB.po b/po/en_GB.po index c9fdcd7..5bb813e 100644 --- a/po/en_GB.po +++ b/po/en_GB.po @@ -15,7 +15,7 @@ msgstr "" "Project-Id-Version: trader 7.2\n" "Report-Msgid-Bugs-To: J.Zaitseff@zap.org.au\n" "POT-Creation-Date: 2011-08-28 14:55+1000\n" -"PO-Revision-Date: 2011-08-28 15:59+1000\n" +"PO-Revision-Date: 2011-08-28 16:50+1000\n" "Last-Translator: John Zaitseff \n" "Language-Team: English (British)\n" "Language: en_GB\n" @@ -1175,306 +1175,212 @@ msgstr "" #. #: src/help.c:103 msgid "" -"^BStar Traders^N is a simple game of interstellar trading. The object of " -"the\n" -"game is to amass the greatest amount of wealth possible. This is done " -"by\n" -"creating interstellar shipping lanes, expanding them and buying shares " -"in\n" -"the companies controlling them. Shares appreciate in value as " -"company\n" -"operations expand. In addition, the return on each share (as a " -"percentage)\n" -"also changes. Players may also borrow from the Interstellar Trading Bank " -"to\n" +"^BStar Traders^N is a simple game of interstellar trading. The object of the\n" +"game is to amass the greatest amount of wealth possible. This is done by\n" +"creating interstellar shipping lanes, expanding them and buying shares in\n" +"the companies controlling them. Shares appreciate in value as company\n" +"operations expand. In addition, the return on each share (as a percentage)\n" +"also changes. Players may also borrow from the Interstellar Trading Bank to\n" "finance additional purchases on the Stock Exchange.\n" "\n" -"The map of the galaxy is represented by a ^B~x^N x ^B~y^N grid. A typical " -"section\n" +"The map of the galaxy is represented by a ^B~x^N x ^B~y^N grid. A typical section\n" "of it may be:\n" "\n" " ^e ~. ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" -" ^e ~. ~. ~. ~. ~. ~. ~. ~. ~. ^N ^e ~. ^N represents ^Bempty " -"space^N,\n" -" ^e ~. ^s~*^e ~. ~. ~. ~. ~. ~. ~. ^N ^s ~* ^N represents a " -"^Bstar^N.\n" +" ^e ~. ~. ~. ~. ~. ~. ~. ~. ~. ^N ^e ~. ^N represents ^Bempty space^N,\n" +" ^e ~. ^s~*^e ~. ~. ~. ~. ~. ~. ~. ^N ^s ~* ^N represents a ^Bstar^N.\n" " ^e ~. ~. ~. ~. ~. ~. ~. ^s~*^e ~. ^N\n" " ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ~. ^N\n" msgstr "" -"^BStar Traders^N is a simple game of interstellar trading. The object of " -"the\n" -"game is to amass the greatest amount of wealth possible. This is done " -"by\n" -"creating interstellar shipping lanes, expanding them and buying shares " -"in\n" -"the companies controlling them. Shares appreciate in value as " -"company\n" -"operations expand. In addition, the return on each share (as a " -"percentage)\n" -"also changes. Players may also borrow from the Interstellar Trading Bank " -"to\n" +"^BStar Traders^N is a simple game of interstellar trading. The object of the\n" +"game is to amass the greatest amount of wealth possible. This is done by\n" +"creating interstellar shipping lanes, expanding them and buying shares in\n" +"the companies controlling them. Shares appreciate in value as company\n" +"operations expand. In addition, the return on each share (as a percentage)\n" +"also changes. Players may also borrow from the Interstellar Trading Bank to\n" "finance additional purchases on the Stock Exchange.\n" "\n" -"The map of the galaxy is represented by a ^B~x^N x ^B~y^N grid. A typical " -"section\n" +"The map of the galaxy is represented by a ^B~x^N x ^B~y^N grid. A typical section\n" "of it may be:\n" "\n" " ^e ~. ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" -" ^e ~. ~. ~. ~. ~. ~. ~. ~. ~. ^N ^e ~. ^N represents ^Bempty " -"space^N,\n" -" ^e ~. ^s~*^e ~. ~. ~. ~. ~. ~. ~. ^N ^s ~* ^N represents a " -"^Bstar^N.\n" +" ^e ~. ~. ~. ~. ~. ~. ~. ~. ~. ^N ^e ~. ^N represents ^Bempty space^N,\n" +" ^e ~. ^s~*^e ~. ~. ~. ~. ~. ~. ~. ^N ^s ~* ^N represents a ^Bstar^N.\n" " ^e ~. ~. ~. ~. ~. ~. ~. ^s~*^e ~. ^N\n" " ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ~. ^N\n" #: src/help.c:122 msgid "" -"The computer selects ^B~m^N moves (labeled ^k~1^N to ^k~M^N) at random, " -"and places these\n" -"on the map. To select any of the highlighted positions, press that " -"letter.\n" +"The computer selects ^B~m^N moves (labeled ^k~1^N to ^k~M^N) at random, and places these\n" +"on the map. To select any of the highlighted positions, press that letter.\n" "For example, some of the moves on the map may be:\n" "\n" "\n" " ^e ^k~1^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" " ^e ~. ~. ~. ^k~3^e ~. ~. ~. ~. ~. ^N\n" -" ^e ~. ^s~*^e ~. ~. ~. ~. ^k~5^e ~. ~. ^N Moves ^k~1^N to " -"^k~5^N shown.\n" +" ^e ~. ^s~*^e ~. ~. ~. ~. ^k~5^e ~. ~. ^N Moves ^k~1^N to ^k~5^N shown.\n" " ^e ~. ^k~2^e ~. ~. ^k~4^e ~. ~. ^s~*^e ~. ^N\n" " ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ~. ^N\n" "\n" "\n" -"Selecting a position that is ^Bnot^N next to a star (such as moves " -"^k~1^N, ^k~3^N or ^k~5^N)\n" -"will set up an ^Boutpost^N, not belonging to any company. Thus, if move " -"^k~3^N is\n" +"Selecting a position that is ^Bnot^N next to a star (such as moves ^k~1^N, ^k~3^N or ^k~5^N)\n" +"will set up an ^Boutpost^N, not belonging to any company. Thus, if move ^k~3^N is\n" "selected on the above map, a ^o ~+ ^N would be placed at that position.\n" msgstr "" -"The computer selects ^B~m^N moves (labelled ^k~1^N to ^k~M^N) at random, " -"and places these\n" -"on the map. To select any of the highlighted positions, press that " -"letter.\n" +"The computer selects ^B~m^N moves (labelled ^k~1^N to ^k~M^N) at random, and places these\n" +"on the map. To select any of the highlighted positions, press that letter.\n" "For example, some of the moves on the map may be:\n" "\n" "\n" " ^e ^k~1^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" " ^e ~. ~. ~. ^k~3^e ~. ~. ~. ~. ~. ^N\n" -" ^e ~. ^s~*^e ~. ~. ~. ~. ^k~5^e ~. ~. ^N Moves ^k~1^N to " -"^k~5^N shown.\n" +" ^e ~. ^s~*^e ~. ~. ~. ~. ^k~5^e ~. ~. ^N Moves ^k~1^N to ^k~5^N shown.\n" " ^e ~. ^k~2^e ~. ~. ^k~4^e ~. ~. ^s~*^e ~. ^N\n" " ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ~. ^N\n" "\n" "\n" -"Selecting a position that is ^Bnot^N next to a star (such as moves " -"^k~1^N, ^k~3^N or ^k~5^N)\n" -"will set up an ^Boutpost^N, not belonging to any company. Thus, if move " -"^k~3^N is\n" +"Selecting a position that is ^Bnot^N next to a star (such as moves ^k~1^N, ^k~3^N or ^k~5^N)\n" +"will set up an ^Boutpost^N, not belonging to any company. Thus, if move ^k~3^N is\n" "selected on the above map, a ^o ~+ ^N would be placed at that position.\n" #: src/help.c:140 msgid "" -"If, on the other hand, a position next to a star (or another outpost) " -"is\n" -"selected, a ^Bcompany^N would be formed and its letter would appear on the " -"map.\n" -"As a reward for creating the company, you are granted the first five " -"shares.\n" +"If, on the other hand, a position next to a star (or another outpost) is\n" +"selected, a ^Bcompany^N would be formed and its letter would appear on the map.\n" +"As a reward for creating the company, you are granted the first five shares.\n" "Up to ^B~c^N companies can be created in this way.\n" "\n" -"If a position next to an existing company is selected, the company " -"would\n" -"expand its operations by one square. This increases the cost of its " -"shares\n" -"and hence your return. Thus, if the map was as shown below, selecting " -"^k~6^N\n" +"If a position next to an existing company is selected, the company would\n" +"expand its operations by one square. This increases the cost of its shares\n" +"and hence your return. Thus, if the map was as shown below, selecting ^k~6^N\n" "or ^k~8^N increases Company ^B~B^N's shipping lane:\n" "\n" " ^e ^k~1^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" " ^e ~. ~. ~. ^o~+^e ~. ~. ^k~6^e ~. ~. ^N\n" -" ^e ~. ^s~*^e ~. ~. ~. ~. ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~6^N " -"or ^k~8^N increases Company ^B~B^N.\n" +" ^e ~. ^s~*^e ~. ~. ~. ~. ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~6^N or ^k~8^N increases Company ^B~B^N.\n" " ^e ~. ^k~2^e ~. ~. ^k~4^e ~. ~. ^s~*^e ^c~B^e ^N\n" " ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ^k~8^e ^N\n" msgstr "" -"If, on the other hand, a position next to a star (or another outpost) " -"is\n" -"selected, a ^Bcompany^N would be formed and its letter would appear on the " -"map.\n" -"As a reward for creating the company, you are granted the first five " -"shares.\n" +"If, on the other hand, a position next to a star (or another outpost) is\n" +"selected, a ^Bcompany^N would be formed and its letter would appear on the map.\n" +"As a reward for creating the company, you are granted the first five shares.\n" "Up to ^B~c^N companies can be created in this way.\n" "\n" -"If a position next to an existing company is selected, the company " -"would\n" -"expand its operations by one square. This increases the cost of its " -"shares\n" -"and hence your return. Thus, if the map was as shown below, selecting " -"^k~6^N\n" +"If a position next to an existing company is selected, the company would\n" +"expand its operations by one square. This increases the cost of its shares\n" +"and hence your return. Thus, if the map was as shown below, selecting ^k~6^N\n" "or ^k~8^N increases Company ^B~B^N’s shipping lane:\n" "\n" " ^e ^k~1^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" " ^e ~. ~. ~. ^o~+^e ~. ~. ^k~6^e ~. ~. ^N\n" -" ^e ~. ^s~*^e ~. ~. ~. ~. ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~6^N " -"or ^k~8^N increases Company ^B~B^N.\n" +" ^e ~. ^s~*^e ~. ~. ~. ~. ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~6^N or ^k~8^N increases Company ^B~B^N.\n" " ^e ~. ^k~2^e ~. ~. ^k~4^e ~. ~. ^s~*^e ^c~B^e ^N\n" " ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ^k~8^e ^N\n" #: src/help.c:158 msgid "" -"Selecting positions next to stars increases the value of your stock by " -"about\n" -"five times as much as an extension not next to a star. Thus move ^k~6^N " -"should\n" +"Selecting positions next to stars increases the value of your stock by about\n" +"five times as much as an extension not next to a star. Thus move ^k~6^N should\n" "be preferred to move ^k~8^N.\n" "\n" " ^e ^c~C^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" " ^e ^k~1^e ^o~+^e ~. ^o~+^e ~. ~. ^k~6^e ~. ~. ^N\n" -" ^e ~. ^s~*^e ~. ~. ~. ~. ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~6^N " -"is preferred to ^k~8^N.\n" +" ^e ~. ^s~*^e ~. ~. ~. ~. ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~6^N is preferred to ^k~8^N.\n" " ^e ~. ^k~2^e ~. ~. ^k~4^e ~. ~. ^s~*^e ^c~B^e ^N\n" " ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ^k~8^e ^N\n" "\n" -"You may also expand any company by selecting positions next to " -"outposts.\n" -"Such outposts will be swallowed up by that company. Thus, move ^k~1^N " -"will\n" -"extend Company ^B~C^N by ^Btwo^N squares. As a bonus, outposts next to " -"stars are\n" -"more valuable: the company's share price will increase by a greater " -"amount\n" +"You may also expand any company by selecting positions next to outposts.\n" +"Such outposts will be swallowed up by that company. Thus, move ^k~1^N will\n" +"extend Company ^B~C^N by ^Btwo^N squares. As a bonus, outposts next to stars are\n" +"more valuable: the company's share price will increase by a greater amount\n" "than it would for outposts not next to stars.\n" msgstr "" -"Selecting positions next to stars increases the value of your stock by " -"about\n" -"five times as much as an extension not next to a star. Thus move ^k~6^N " -"should\n" +"Selecting positions next to stars increases the value of your stock by about\n" +"five times as much as an extension not next to a star. Thus move ^k~6^N should\n" "be preferred to move ^k~8^N.\n" "\n" " ^e ^c~C^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" " ^e ^k~1^e ^o~+^e ~. ^o~+^e ~. ~. ^k~6^e ~. ~. ^N\n" -" ^e ~. ^s~*^e ~. ~. ~. ~. ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~6^N " -"is preferred to ^k~8^N.\n" +" ^e ~. ^s~*^e ~. ~. ~. ~. ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~6^N is preferred to ^k~8^N.\n" " ^e ~. ^k~2^e ~. ~. ^k~4^e ~. ~. ^s~*^e ^c~B^e ^N\n" " ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ^k~8^e ^N\n" "\n" -"You may also expand any company by selecting positions next to " -"outposts.\n" -"Such outposts will be swallowed up by that company. Thus, move ^k~1^N " -"will\n" -"extend Company ^B~C^N by ^Btwo^N squares. As a bonus, outposts next to " -"stars are\n" -"more valuable: the company’s share price will increase by a greater " -"amount\n" +"You may also expand any company by selecting positions next to outposts.\n" +"Such outposts will be swallowed up by that company. Thus, move ^k~1^N will\n" +"extend Company ^B~C^N by ^Btwo^N squares. As a bonus, outposts next to stars are\n" +"more valuable: the company’s share price will increase by a greater amount\n" "than it would for outposts not next to stars.\n" #: src/help.c:176 msgid "" -"If two companies are separated on the map by only one square, then they " -"can\n" -"be ^Bmerged^N into one company by selecting that position (if available). " -"For\n" -"example, on the map below, companies ^B~A^N and ^B~B^N can be merged by " -"selecting ^k~5^N.\n" -"When this occurs, the company with the greater assets value takes over " -"the\n" -"other one. Here, Company ^B~B^N might take over Company ^B~A^N. Company " -"^B~A^N ceases to\n" -"exist, although it may reappear as an entirely new company at a later " -"stage.\n" +"If two companies are separated on the map by only one square, then they can\n" +"be ^Bmerged^N into one company by selecting that position (if available). For\n" +"example, on the map below, companies ^B~A^N and ^B~B^N can be merged by selecting ^k~5^N.\n" +"When this occurs, the company with the greater assets value takes over the\n" +"other one. Here, Company ^B~B^N might take over Company ^B~A^N. Company ^B~A^N ceases to\n" +"exist, although it may reappear as an entirely new company at a later stage.\n" "\n" " ^e ^k~1^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" " ^e ~. ~. ~. ^c~A^e ^c~A^e ^k~5^e ^c~B^e ~. ~. ^N\n" -" ^e ~. ^s~*^e ~. ~. ^c~A^e ~. ^c~B^e ^c~B^e ^c~B^e ^N Move " -"^k~5^N merges companies ^B~A^N and ^B~B^N.\n" +" ^e ~. ^s~*^e ~. ~. ^c~A^e ~. ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~5^N merges companies ^B~A^N and ^B~B^N.\n" " ^e ~. ^k~2^e ~. ~. ~. ~. ~. ^s~*^e ^c~B^e ^N\n" " ^e ~. ~. ~. ~. ^s~*^e ~. ^o~+^e ~. ~. ^N\n" "\n" -"When companies merge, players are granted shares in the dominant " -"company\n" -"proportional to the amount owned in the old company. As well, a cash " -"bonus\n" +"When companies merge, players are granted shares in the dominant company\n" +"proportional to the amount owned in the old company. As well, a cash bonus\n" "is also paid, proportional to the percentage of the old company owned.\n" msgstr "" -"If two companies are separated on the map by only one square, then they " -"can\n" -"be ^Bmerged^N into one company by selecting that position (if available). " -"For\n" -"example, on the map below, companies ^B~A^N and ^B~B^N can be merged by " -"selecting ^k~5^N.\n" -"When this occurs, the company with the greater assets value takes over " -"the\n" -"other one. Here, Company ^B~B^N might take over Company ^B~A^N. Company " -"^B~A^N ceases to\n" -"exist, although it may reappear as an entirely new company at a later " -"stage.\n" +"If two companies are separated on the map by only one square, then they can\n" +"be ^Bmerged^N into one company by selecting that position (if available). For\n" +"example, on the map below, companies ^B~A^N and ^B~B^N can be merged by selecting ^k~5^N.\n" +"When this occurs, the company with the greater assets value takes over the\n" +"other one. Here, Company ^B~B^N might take over Company ^B~A^N. Company ^B~A^N ceases to\n" +"exist, although it may reappear as an entirely new company at a later stage.\n" "\n" " ^e ^k~1^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" " ^e ~. ~. ~. ^c~A^e ^c~A^e ^k~5^e ^c~B^e ~. ~. ^N\n" -" ^e ~. ^s~*^e ~. ~. ^c~A^e ~. ^c~B^e ^c~B^e ^c~B^e ^N Move " -"^k~5^N merges companies ^B~A^N and ^B~B^N.\n" +" ^e ~. ^s~*^e ~. ~. ^c~A^e ~. ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~5^N merges companies ^B~A^N and ^B~B^N.\n" " ^e ~. ^k~2^e ~. ~. ~. ~. ~. ^s~*^e ^c~B^e ^N\n" " ^e ~. ~. ~. ~. ^s~*^e ~. ^o~+^e ~. ~. ^N\n" "\n" -"When companies merge, players are granted shares in the dominant " -"company\n" -"proportional to the amount owned in the old company. As well, a cash " -"bonus\n" +"When companies merge, players are granted shares in the dominant company\n" +"proportional to the amount owned in the old company. As well, a cash bonus\n" "is also paid, proportional to the percentage of the old company owned.\n" #: src/help.c:195 msgid "" -"Once you select your move, you enter the ^BInterstellar Stock Exchange^N. " -"Here\n" -"you may purchase shares, sell them, borrow from the Trading Bank or " -"repay\n" -"some of your debt (if applicable). Note that each company issues a " -"limited\n" -"number of shares -- you cannot go on buying for ever! You may, however, " -"bid\n" -"for more shares to be issued. You have a better chance of succeeding if " -"you\n" +"Once you select your move, you enter the ^BInterstellar Stock Exchange^N. Here\n" +"you may purchase shares, sell them, borrow from the Trading Bank or repay\n" +"some of your debt (if applicable). Note that each company issues a limited\n" +"number of shares -- you cannot go on buying for ever! You may, however, bid\n" +"for more shares to be issued. You have a better chance of succeeding if you\n" "own a larger proportion of the company.\n" "\n" -"The game usually ends after ^B~t^N turns. However, you may end the game " -"sooner\n" -"by pressing ^K^N when asked to select a move. As well, " -"individual\n" -"players can declare themselves bankrupt at any time. If your debt is " -"large\n" -"enough, the Bank may do this for you! If you do not complete your game " -"in\n" +"The game usually ends after ^B~t^N turns. However, you may end the game sooner\n" +"by pressing ^K^N when asked to select a move. As well, individual\n" +"players can declare themselves bankrupt at any time. If your debt is large\n" +"enough, the Bank may do this for you! If you do not complete your game in\n" "the time you have available, you may save the game and continue it later.\n" "\n" "\n" -"The ^Bwinner of the game^N is the person with the greatest net worth " -"(total\n" +"The ^Bwinner of the game^N is the person with the greatest net worth (total\n" "value of cash, stock and debt). ^HGood luck^N and may the best person win!\n" msgstr "" -"Once you select your move, you enter the ^BInterstellar Stock Exchange^N. " -"Here\n" -"you may purchase shares, sell them, borrow from the Trading Bank or " -"repay\n" -"some of your debt (if applicable). Note that each company issues a " -"limited\n" -"number of shares -- you cannot go on buying for ever! You may, however, " -"bid\n" -"for more shares to be issued. You have a better chance of succeeding if " -"you\n" +"Once you select your move, you enter the ^BInterstellar Stock Exchange^N. Here\n" +"you may purchase shares, sell them, borrow from the Trading Bank or repay\n" +"some of your debt (if applicable). Note that each company issues a limited\n" +"number of shares -- you cannot go on buying for ever! You may, however, bid\n" +"for more shares to be issued. You have a better chance of succeeding if you\n" "own a larger proportion of the company.\n" "\n" -"The game usually ends after ^B~t^N turns. However, you may end the game " -"sooner\n" -"by pressing ^K^N when asked to select a move. As well, " -"individual\n" -"players can declare themselves bankrupt at any time. If your debt is " -"large\n" -"enough, the Bank may do this for you! If you do not complete your game " -"in\n" +"The game usually ends after ^B~t^N turns. However, you may end the game sooner\n" +"by pressing ^K^N when asked to select a move. As well, individual\n" +"players can declare themselves bankrupt at any time. If your debt is large\n" +"enough, the Bank may do this for you! If you do not complete your game in\n" "the time you have available, you may save the game and continue it later.\n" "\n" "\n" -"The ^Bwinner of the game^N is the person with the greatest net worth " -"(total\n" +"The ^Bwinner of the game^N is the person with the greatest net worth (total\n" "value of cash, stock and debt). ^HGood luck^N and may the best person win!\n" #: src/help.c:215 diff --git a/po/en_US.po b/po/en_US.po index 663c00e..24d0eaf 100644 --- a/po/en_US.po +++ b/po/en_US.po @@ -15,7 +15,7 @@ msgstr "" "Project-Id-Version: trader 7.2\n" "Report-Msgid-Bugs-To: J.Zaitseff@zap.org.au\n" "POT-Creation-Date: 2011-08-28 14:55+1000\n" -"PO-Revision-Date: 2011-08-28 15:59+1000\n" +"PO-Revision-Date: 2011-08-28 16:50+1000\n" "Last-Translator: John Zaitseff \n" "Language-Team: English\n" "Language: en_US\n" @@ -1175,306 +1175,212 @@ msgstr "" #. #: src/help.c:103 msgid "" -"^BStar Traders^N is a simple game of interstellar trading. The object of " -"the\n" -"game is to amass the greatest amount of wealth possible. This is done " -"by\n" -"creating interstellar shipping lanes, expanding them and buying shares " -"in\n" -"the companies controlling them. Shares appreciate in value as " -"company\n" -"operations expand. In addition, the return on each share (as a " -"percentage)\n" -"also changes. Players may also borrow from the Interstellar Trading Bank " -"to\n" +"^BStar Traders^N is a simple game of interstellar trading. The object of the\n" +"game is to amass the greatest amount of wealth possible. This is done by\n" +"creating interstellar shipping lanes, expanding them and buying shares in\n" +"the companies controlling them. Shares appreciate in value as company\n" +"operations expand. In addition, the return on each share (as a percentage)\n" +"also changes. Players may also borrow from the Interstellar Trading Bank to\n" "finance additional purchases on the Stock Exchange.\n" "\n" -"The map of the galaxy is represented by a ^B~x^N x ^B~y^N grid. A typical " -"section\n" +"The map of the galaxy is represented by a ^B~x^N x ^B~y^N grid. A typical section\n" "of it may be:\n" "\n" " ^e ~. ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" -" ^e ~. ~. ~. ~. ~. ~. ~. ~. ~. ^N ^e ~. ^N represents ^Bempty " -"space^N,\n" -" ^e ~. ^s~*^e ~. ~. ~. ~. ~. ~. ~. ^N ^s ~* ^N represents a " -"^Bstar^N.\n" +" ^e ~. ~. ~. ~. ~. ~. ~. ~. ~. ^N ^e ~. ^N represents ^Bempty space^N,\n" +" ^e ~. ^s~*^e ~. ~. ~. ~. ~. ~. ~. ^N ^s ~* ^N represents a ^Bstar^N.\n" " ^e ~. ~. ~. ~. ~. ~. ~. ^s~*^e ~. ^N\n" " ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ~. ^N\n" msgstr "" -"^BStar Traders^N is a simple game of interstellar trading. The object of " -"the\n" -"game is to amass the greatest amount of wealth possible. This is done " -"by\n" -"creating interstellar shipping lanes, expanding them and buying shares " -"in\n" -"the companies controlling them. Shares appreciate in value as " -"company\n" -"operations expand. In addition, the return on each share (as a " -"percentage)\n" -"also changes. Players may also borrow from the Interstellar Trading Bank " -"to\n" +"^BStar Traders^N is a simple game of interstellar trading. The object of the\n" +"game is to amass the greatest amount of wealth possible. This is done by\n" +"creating interstellar shipping lanes, expanding them and buying shares in\n" +"the companies controlling them. Shares appreciate in value as company\n" +"operations expand. In addition, the return on each share (as a percentage)\n" +"also changes. Players may also borrow from the Interstellar Trading Bank to\n" "finance additional purchases on the Stock Exchange.\n" "\n" -"The map of the galaxy is represented by a ^B~x^N x ^B~y^N grid. A typical " -"section\n" +"The map of the galaxy is represented by a ^B~x^N x ^B~y^N grid. A typical section\n" "of it may be:\n" "\n" " ^e ~. ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" -" ^e ~. ~. ~. ~. ~. ~. ~. ~. ~. ^N ^e ~. ^N represents ^Bempty " -"space^N,\n" -" ^e ~. ^s~*^e ~. ~. ~. ~. ~. ~. ~. ^N ^s ~* ^N represents a " -"^Bstar^N.\n" +" ^e ~. ~. ~. ~. ~. ~. ~. ~. ~. ^N ^e ~. ^N represents ^Bempty space^N,\n" +" ^e ~. ^s~*^e ~. ~. ~. ~. ~. ~. ~. ^N ^s ~* ^N represents a ^Bstar^N.\n" " ^e ~. ~. ~. ~. ~. ~. ~. ^s~*^e ~. ^N\n" " ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ~. ^N\n" #: src/help.c:122 msgid "" -"The computer selects ^B~m^N moves (labeled ^k~1^N to ^k~M^N) at random, " -"and places these\n" -"on the map. To select any of the highlighted positions, press that " -"letter.\n" +"The computer selects ^B~m^N moves (labeled ^k~1^N to ^k~M^N) at random, and places these\n" +"on the map. To select any of the highlighted positions, press that letter.\n" "For example, some of the moves on the map may be:\n" "\n" "\n" " ^e ^k~1^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" " ^e ~. ~. ~. ^k~3^e ~. ~. ~. ~. ~. ^N\n" -" ^e ~. ^s~*^e ~. ~. ~. ~. ^k~5^e ~. ~. ^N Moves ^k~1^N to " -"^k~5^N shown.\n" +" ^e ~. ^s~*^e ~. ~. ~. ~. ^k~5^e ~. ~. ^N Moves ^k~1^N to ^k~5^N shown.\n" " ^e ~. ^k~2^e ~. ~. ^k~4^e ~. ~. ^s~*^e ~. ^N\n" " ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ~. ^N\n" "\n" "\n" -"Selecting a position that is ^Bnot^N next to a star (such as moves " -"^k~1^N, ^k~3^N or ^k~5^N)\n" -"will set up an ^Boutpost^N, not belonging to any company. Thus, if move " -"^k~3^N is\n" +"Selecting a position that is ^Bnot^N next to a star (such as moves ^k~1^N, ^k~3^N or ^k~5^N)\n" +"will set up an ^Boutpost^N, not belonging to any company. Thus, if move ^k~3^N is\n" "selected on the above map, a ^o ~+ ^N would be placed at that position.\n" msgstr "" -"The computer selects ^B~m^N moves (labeled ^k~1^N to ^k~M^N) at random, " -"and places these\n" -"on the map. To select any of the highlighted positions, press that " -"letter.\n" +"The computer selects ^B~m^N moves (labeled ^k~1^N to ^k~M^N) at random, and places these\n" +"on the map. To select any of the highlighted positions, press that letter.\n" "For example, some of the moves on the map may be:\n" "\n" "\n" " ^e ^k~1^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" " ^e ~. ~. ~. ^k~3^e ~. ~. ~. ~. ~. ^N\n" -" ^e ~. ^s~*^e ~. ~. ~. ~. ^k~5^e ~. ~. ^N Moves ^k~1^N to " -"^k~5^N shown.\n" +" ^e ~. ^s~*^e ~. ~. ~. ~. ^k~5^e ~. ~. ^N Moves ^k~1^N to ^k~5^N shown.\n" " ^e ~. ^k~2^e ~. ~. ^k~4^e ~. ~. ^s~*^e ~. ^N\n" " ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ~. ^N\n" "\n" "\n" -"Selecting a position that is ^Bnot^N next to a star (such as moves " -"^k~1^N, ^k~3^N or ^k~5^N)\n" -"will set up an ^Boutpost^N, not belonging to any company. Thus, if move " -"^k~3^N is\n" +"Selecting a position that is ^Bnot^N next to a star (such as moves ^k~1^N, ^k~3^N or ^k~5^N)\n" +"will set up an ^Boutpost^N, not belonging to any company. Thus, if move ^k~3^N is\n" "selected on the above map, a ^o ~+ ^N would be placed at that position.\n" #: src/help.c:140 msgid "" -"If, on the other hand, a position next to a star (or another outpost) " -"is\n" -"selected, a ^Bcompany^N would be formed and its letter would appear on the " -"map.\n" -"As a reward for creating the company, you are granted the first five " -"shares.\n" +"If, on the other hand, a position next to a star (or another outpost) is\n" +"selected, a ^Bcompany^N would be formed and its letter would appear on the map.\n" +"As a reward for creating the company, you are granted the first five shares.\n" "Up to ^B~c^N companies can be created in this way.\n" "\n" -"If a position next to an existing company is selected, the company " -"would\n" -"expand its operations by one square. This increases the cost of its " -"shares\n" -"and hence your return. Thus, if the map was as shown below, selecting " -"^k~6^N\n" +"If a position next to an existing company is selected, the company would\n" +"expand its operations by one square. This increases the cost of its shares\n" +"and hence your return. Thus, if the map was as shown below, selecting ^k~6^N\n" "or ^k~8^N increases Company ^B~B^N's shipping lane:\n" "\n" " ^e ^k~1^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" " ^e ~. ~. ~. ^o~+^e ~. ~. ^k~6^e ~. ~. ^N\n" -" ^e ~. ^s~*^e ~. ~. ~. ~. ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~6^N " -"or ^k~8^N increases Company ^B~B^N.\n" +" ^e ~. ^s~*^e ~. ~. ~. ~. ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~6^N or ^k~8^N increases Company ^B~B^N.\n" " ^e ~. ^k~2^e ~. ~. ^k~4^e ~. ~. ^s~*^e ^c~B^e ^N\n" " ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ^k~8^e ^N\n" msgstr "" -"If, on the other hand, a position next to a star (or another outpost) " -"is\n" -"selected, a ^Bcompany^N would be formed and its letter would appear on the " -"map.\n" -"As a reward for creating the company, you are granted the first five " -"shares.\n" +"If, on the other hand, a position next to a star (or another outpost) is\n" +"selected, a ^Bcompany^N would be formed and its letter would appear on the map.\n" +"As a reward for creating the company, you are granted the first five shares.\n" "Up to ^B~c^N companies can be created in this way.\n" "\n" -"If a position next to an existing company is selected, the company " -"would\n" -"expand its operations by one square. This increases the cost of its " -"shares\n" -"and hence your return. Thus, if the map was as shown below, selecting " -"^k~6^N\n" +"If a position next to an existing company is selected, the company would\n" +"expand its operations by one square. This increases the cost of its shares\n" +"and hence your return. Thus, if the map was as shown below, selecting ^k~6^N\n" "or ^k~8^N increases Company ^B~B^N’s shipping lane:\n" "\n" " ^e ^k~1^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" " ^e ~. ~. ~. ^o~+^e ~. ~. ^k~6^e ~. ~. ^N\n" -" ^e ~. ^s~*^e ~. ~. ~. ~. ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~6^N " -"or ^k~8^N increases Company ^B~B^N.\n" +" ^e ~. ^s~*^e ~. ~. ~. ~. ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~6^N or ^k~8^N increases Company ^B~B^N.\n" " ^e ~. ^k~2^e ~. ~. ^k~4^e ~. ~. ^s~*^e ^c~B^e ^N\n" " ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ^k~8^e ^N\n" #: src/help.c:158 msgid "" -"Selecting positions next to stars increases the value of your stock by " -"about\n" -"five times as much as an extension not next to a star. Thus move ^k~6^N " -"should\n" +"Selecting positions next to stars increases the value of your stock by about\n" +"five times as much as an extension not next to a star. Thus move ^k~6^N should\n" "be preferred to move ^k~8^N.\n" "\n" " ^e ^c~C^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" " ^e ^k~1^e ^o~+^e ~. ^o~+^e ~. ~. ^k~6^e ~. ~. ^N\n" -" ^e ~. ^s~*^e ~. ~. ~. ~. ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~6^N " -"is preferred to ^k~8^N.\n" +" ^e ~. ^s~*^e ~. ~. ~. ~. ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~6^N is preferred to ^k~8^N.\n" " ^e ~. ^k~2^e ~. ~. ^k~4^e ~. ~. ^s~*^e ^c~B^e ^N\n" " ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ^k~8^e ^N\n" "\n" -"You may also expand any company by selecting positions next to " -"outposts.\n" -"Such outposts will be swallowed up by that company. Thus, move ^k~1^N " -"will\n" -"extend Company ^B~C^N by ^Btwo^N squares. As a bonus, outposts next to " -"stars are\n" -"more valuable: the company's share price will increase by a greater " -"amount\n" +"You may also expand any company by selecting positions next to outposts.\n" +"Such outposts will be swallowed up by that company. Thus, move ^k~1^N will\n" +"extend Company ^B~C^N by ^Btwo^N squares. As a bonus, outposts next to stars are\n" +"more valuable: the company's share price will increase by a greater amount\n" "than it would for outposts not next to stars.\n" msgstr "" -"Selecting positions next to stars increases the value of your stock by " -"about\n" -"five times as much as an extension not next to a star. Thus move ^k~6^N " -"should\n" +"Selecting positions next to stars increases the value of your stock by about\n" +"five times as much as an extension not next to a star. Thus move ^k~6^N should\n" "be preferred to move ^k~8^N.\n" "\n" " ^e ^c~C^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" " ^e ^k~1^e ^o~+^e ~. ^o~+^e ~. ~. ^k~6^e ~. ~. ^N\n" -" ^e ~. ^s~*^e ~. ~. ~. ~. ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~6^N " -"is preferred to ^k~8^N.\n" +" ^e ~. ^s~*^e ~. ~. ~. ~. ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~6^N is preferred to ^k~8^N.\n" " ^e ~. ^k~2^e ~. ~. ^k~4^e ~. ~. ^s~*^e ^c~B^e ^N\n" " ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ^k~8^e ^N\n" "\n" -"You may also expand any company by selecting positions next to " -"outposts.\n" -"Such outposts will be swallowed up by that company. Thus, move ^k~1^N " -"will\n" -"extend Company ^B~C^N by ^Btwo^N squares. As a bonus, outposts next to " -"stars are\n" -"more valuable: the company’s share price will increase by a greater " -"amount\n" +"You may also expand any company by selecting positions next to outposts.\n" +"Such outposts will be swallowed up by that company. Thus, move ^k~1^N will\n" +"extend Company ^B~C^N by ^Btwo^N squares. As a bonus, outposts next to stars are\n" +"more valuable: the company’s share price will increase by a greater amount\n" "than it would for outposts not next to stars.\n" #: src/help.c:176 msgid "" -"If two companies are separated on the map by only one square, then they " -"can\n" -"be ^Bmerged^N into one company by selecting that position (if available). " -"For\n" -"example, on the map below, companies ^B~A^N and ^B~B^N can be merged by " -"selecting ^k~5^N.\n" -"When this occurs, the company with the greater assets value takes over " -"the\n" -"other one. Here, Company ^B~B^N might take over Company ^B~A^N. Company " -"^B~A^N ceases to\n" -"exist, although it may reappear as an entirely new company at a later " -"stage.\n" +"If two companies are separated on the map by only one square, then they can\n" +"be ^Bmerged^N into one company by selecting that position (if available). For\n" +"example, on the map below, companies ^B~A^N and ^B~B^N can be merged by selecting ^k~5^N.\n" +"When this occurs, the company with the greater assets value takes over the\n" +"other one. Here, Company ^B~B^N might take over Company ^B~A^N. Company ^B~A^N ceases to\n" +"exist, although it may reappear as an entirely new company at a later stage.\n" "\n" " ^e ^k~1^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" " ^e ~. ~. ~. ^c~A^e ^c~A^e ^k~5^e ^c~B^e ~. ~. ^N\n" -" ^e ~. ^s~*^e ~. ~. ^c~A^e ~. ^c~B^e ^c~B^e ^c~B^e ^N Move " -"^k~5^N merges companies ^B~A^N and ^B~B^N.\n" +" ^e ~. ^s~*^e ~. ~. ^c~A^e ~. ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~5^N merges companies ^B~A^N and ^B~B^N.\n" " ^e ~. ^k~2^e ~. ~. ~. ~. ~. ^s~*^e ^c~B^e ^N\n" " ^e ~. ~. ~. ~. ^s~*^e ~. ^o~+^e ~. ~. ^N\n" "\n" -"When companies merge, players are granted shares in the dominant " -"company\n" -"proportional to the amount owned in the old company. As well, a cash " -"bonus\n" +"When companies merge, players are granted shares in the dominant company\n" +"proportional to the amount owned in the old company. As well, a cash bonus\n" "is also paid, proportional to the percentage of the old company owned.\n" msgstr "" -"If two companies are separated on the map by only one square, then they " -"can\n" -"be ^Bmerged^N into one company by selecting that position (if available). " -"For\n" -"example, on the map below, companies ^B~A^N and ^B~B^N can be merged by " -"selecting ^k~5^N.\n" -"When this occurs, the company with the greater assets value takes over " -"the\n" -"other one. Here, Company ^B~B^N might take over Company ^B~A^N. Company " -"^B~A^N ceases to\n" -"exist, although it may reappear as an entirely new company at a later " -"stage.\n" +"If two companies are separated on the map by only one square, then they can\n" +"be ^Bmerged^N into one company by selecting that position (if available). For\n" +"example, on the map below, companies ^B~A^N and ^B~B^N can be merged by selecting ^k~5^N.\n" +"When this occurs, the company with the greater assets value takes over the\n" +"other one. Here, Company ^B~B^N might take over Company ^B~A^N. Company ^B~A^N ceases to\n" +"exist, although it may reappear as an entirely new company at a later stage.\n" "\n" " ^e ^k~1^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" " ^e ~. ~. ~. ^c~A^e ^c~A^e ^k~5^e ^c~B^e ~. ~. ^N\n" -" ^e ~. ^s~*^e ~. ~. ^c~A^e ~. ^c~B^e ^c~B^e ^c~B^e ^N Move " -"^k~5^N merges companies ^B~A^N and ^B~B^N.\n" +" ^e ~. ^s~*^e ~. ~. ^c~A^e ~. ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~5^N merges companies ^B~A^N and ^B~B^N.\n" " ^e ~. ^k~2^e ~. ~. ~. ~. ~. ^s~*^e ^c~B^e ^N\n" " ^e ~. ~. ~. ~. ^s~*^e ~. ^o~+^e ~. ~. ^N\n" "\n" -"When companies merge, players are granted shares in the dominant " -"company\n" -"proportional to the amount owned in the old company. As well, a cash " -"bonus\n" +"When companies merge, players are granted shares in the dominant company\n" +"proportional to the amount owned in the old company. As well, a cash bonus\n" "is also paid, proportional to the percentage of the old company owned.\n" #: src/help.c:195 msgid "" -"Once you select your move, you enter the ^BInterstellar Stock Exchange^N. " -"Here\n" -"you may purchase shares, sell them, borrow from the Trading Bank or " -"repay\n" -"some of your debt (if applicable). Note that each company issues a " -"limited\n" -"number of shares -- you cannot go on buying for ever! You may, however, " -"bid\n" -"for more shares to be issued. You have a better chance of succeeding if " -"you\n" +"Once you select your move, you enter the ^BInterstellar Stock Exchange^N. Here\n" +"you may purchase shares, sell them, borrow from the Trading Bank or repay\n" +"some of your debt (if applicable). Note that each company issues a limited\n" +"number of shares -- you cannot go on buying for ever! You may, however, bid\n" +"for more shares to be issued. You have a better chance of succeeding if you\n" "own a larger proportion of the company.\n" "\n" -"The game usually ends after ^B~t^N turns. However, you may end the game " -"sooner\n" -"by pressing ^K^N when asked to select a move. As well, " -"individual\n" -"players can declare themselves bankrupt at any time. If your debt is " -"large\n" -"enough, the Bank may do this for you! If you do not complete your game " -"in\n" +"The game usually ends after ^B~t^N turns. However, you may end the game sooner\n" +"by pressing ^K^N when asked to select a move. As well, individual\n" +"players can declare themselves bankrupt at any time. If your debt is large\n" +"enough, the Bank may do this for you! If you do not complete your game in\n" "the time you have available, you may save the game and continue it later.\n" "\n" "\n" -"The ^Bwinner of the game^N is the person with the greatest net worth " -"(total\n" +"The ^Bwinner of the game^N is the person with the greatest net worth (total\n" "value of cash, stock and debt). ^HGood luck^N and may the best person win!\n" msgstr "" -"Once you select your move, you enter the ^BInterstellar Stock Exchange^N. " -"Here\n" -"you may purchase shares, sell them, borrow from the Trading Bank or " -"repay\n" -"some of your debt (if applicable). Note that each company issues a " -"limited\n" -"number of shares -- you cannot go on buying for ever! You may, however, " -"bid\n" -"for more shares to be issued. You have a better chance of succeeding if " -"you\n" +"Once you select your move, you enter the ^BInterstellar Stock Exchange^N. Here\n" +"you may purchase shares, sell them, borrow from the Trading Bank or repay\n" +"some of your debt (if applicable). Note that each company issues a limited\n" +"number of shares -- you cannot go on buying for ever! You may, however, bid\n" +"for more shares to be issued. You have a better chance of succeeding if you\n" "own a larger proportion of the company.\n" "\n" -"The game usually ends after ^B~t^N turns. However, you may end the game " -"sooner\n" -"by pressing ^K^N when asked to select a move. As well, " -"individual\n" -"players can declare themselves bankrupt at any time. If your debt is " -"large\n" -"enough, the Bank may do this for you! If you do not complete your game " -"in\n" +"The game usually ends after ^B~t^N turns. However, you may end the game sooner\n" +"by pressing ^K^N when asked to select a move. As well, individual\n" +"players can declare themselves bankrupt at any time. If your debt is large\n" +"enough, the Bank may do this for you! If you do not complete your game in\n" "the time you have available, you may save the game and continue it later.\n" "\n" "\n" -"The ^Bwinner of the game^N is the person with the greatest net worth " -"(total\n" +"The ^Bwinner of the game^N is the person with the greatest net worth (total\n" "value of cash, stock and debt). ^HGood luck^N and may the best person win!\n" #: src/help.c:215 From a9dfde342a4f65d985bf5896a3f0c14c48859300 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Sun, 28 Aug 2011 17:06:03 +1000 Subject: [PATCH 103/112] Correct the spelling of "-ize" vs. "-ise" --- po/en_AU.po | 6 +++--- po/en_GB.po | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/po/en_AU.po b/po/en_AU.po index 74995d9..dfb8fb9 100644 --- a/po/en_AU.po +++ b/po/en_AU.po @@ -15,7 +15,7 @@ msgstr "" "Project-Id-Version: trader 7.2\n" "Report-Msgid-Bugs-To: J.Zaitseff@zap.org.au\n" "POT-Creation-Date: 2011-08-28 14:55+1000\n" -"PO-Revision-Date: 2011-08-28 16:50+1000\n" +"PO-Revision-Date: 2011-08-28 17:03+1000\n" "Last-Translator: John Zaitseff \n" "Language-Team: English (Australian)\n" "Language: en_AU\n" @@ -1535,12 +1535,12 @@ msgstr "%s: option ‘--%s’ requires an argument\n" #: lib/getopt.c:742 lib/getopt.c:745 #, c-format msgid "%s: unrecognized option '--%s'\n" -msgstr "%s: unrecognized option ‘--%s’\n" +msgstr "%s: unrecognised option ‘--%s’\n" #: lib/getopt.c:753 lib/getopt.c:756 #, c-format msgid "%s: unrecognized option '%c%s'\n" -msgstr "%s: unrecognized option ‘%c%s’\n" +msgstr "%s: unrecognised option ‘%c%s’\n" #: lib/getopt.c:805 lib/getopt.c:808 #, c-format diff --git a/po/en_GB.po b/po/en_GB.po index 5bb813e..d056eb0 100644 --- a/po/en_GB.po +++ b/po/en_GB.po @@ -15,7 +15,7 @@ msgstr "" "Project-Id-Version: trader 7.2\n" "Report-Msgid-Bugs-To: J.Zaitseff@zap.org.au\n" "POT-Creation-Date: 2011-08-28 14:55+1000\n" -"PO-Revision-Date: 2011-08-28 16:50+1000\n" +"PO-Revision-Date: 2011-08-28 17:03+1000\n" "Last-Translator: John Zaitseff \n" "Language-Team: English (British)\n" "Language: en_GB\n" @@ -1535,12 +1535,12 @@ msgstr "%s: option ‘--%s’ requires an argument\n" #: lib/getopt.c:742 lib/getopt.c:745 #, c-format msgid "%s: unrecognized option '--%s'\n" -msgstr "%s: unrecognized option ‘--%s’\n" +msgstr "%s: unrecognised option ‘--%s’\n" #: lib/getopt.c:753 lib/getopt.c:756 #, c-format msgid "%s: unrecognized option '%c%s'\n" -msgstr "%s: unrecognized option ‘%c%s’\n" +msgstr "%s: unrecognised option ‘%c%s’\n" #: lib/getopt.c:805 lib/getopt.c:808 #, c-format From 2c57284edf2f0651a777cadb9784d224a8915d9b Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Sun, 28 Aug 2011 17:06:53 +1000 Subject: [PATCH 104/112] Add the English (Canadian) translation of Star Traders Hopefully, this has the correct spelling. Corrections welcome! --- po/LINGUAS | 1 + po/en_CA.po | 1568 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1569 insertions(+) create mode 100644 po/en_CA.po diff --git a/po/LINGUAS b/po/LINGUAS index 27c00af..6a642e9 100644 --- a/po/LINGUAS +++ b/po/LINGUAS @@ -28,5 +28,6 @@ en@quot en_AU +en_CA en_GB en_US diff --git a/po/en_CA.po b/po/en_CA.po new file mode 100644 index 0000000..5b702ce --- /dev/null +++ b/po/en_CA.po @@ -0,0 +1,1568 @@ +# ************************************************************************* +# * * +# * English (Canadian) Translations for Star Traders * +# * Copyright (C) 1990-2011, John Zaitseff * +# * * +# ************************************************************************* +# +# This file is distributed under the same licence as Star Traders. +# +# Contributors: +# John Zaitseff , 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: trader 7.2\n" +"Report-Msgid-Bugs-To: J.Zaitseff@zap.org.au\n" +"POT-Creation-Date: 2011-08-28 14:55+1000\n" +"PO-Revision-Date: 2011-08-28 17:01+1000\n" +"Last-Translator: John Zaitseff \n" +"Language-Team: English (Canadian)\n" +"Language: en_CA\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: src/trader.c:235 +#, c-format +msgid "%s: invalid value for --max-turn: `%s'\n" +msgstr "%s: invalid value for --max-turn: ‘%s’\n" + +#: src/trader.c:251 +#, c-format +msgid "%s: invalid operand `%s'\n" +msgstr "%s: invalid operand ‘%s’\n" + +#: src/trader.c:260 +#, c-format +msgid "%s: invalid game number `%s'\n" +msgstr "%s: invalid game number ‘%s’\n" + +#: src/trader.c:269 +#, c-format +msgid "%s: extra operand `%s'\n" +msgstr "%s: extra operand ‘%s’\n" + +#. TRANSLATORS: "John Zaitseff" [IPA d͡ʒɒn ˈzaɪ̯t͡səf] is the proper +#. name of the author. The IPA pronunciation in this comment is in +#. UTF-8 encoding. +#: src/trader.c:284 +#, c-format +msgid "" +"Star Traders (%s) %s\n" +"Copyright (C) %s, John Zaitseff.\n" +"\n" +"Star Traders is a simple game of interstellar trading, where the object\n" +"of the game is to create companies, buy and sell shares, borrow and repay\n" +"money, in order to become the wealthiest player (the winner).\n" +"\n" +"This program is free software that is distributed under the terms of the\n" +"GNU General Public License, version 3 or later. You are welcome to\n" +"modify and/or distribute it under certain conditions. This program has\n" +"NO WARRANTY, to the extent permitted by law; see the License for details.\n" +msgstr "" +"Star Traders (%s) %s\n" +"Copyright (C) %s, John Zaitseff.\n" +"\n" +"Star Traders is a simple game of interstellar trading, where the object\n" +"of the game is to create companies, buy and sell shares, borrow and repay\n" +"money, in order to become the wealthiest player (the winner).\n" +"\n" +"This program is free software that is distributed under the terms of the\n" +"GNU General Public License, version 3 or later. You are welcome to\n" +"modify and/or distribute it under certain conditions. This program has\n" +"NO WARRANTY, to the extent permitted by law; see the License for details.\n" + +#: src/trader.c:308 +#, c-format +msgid "%s: Try `%s --help' for more information.\n" +msgstr "%s: Try ‘%s --help’ for more information.\n" + +#: src/trader.c:311 +#, c-format +msgid "Usage: %s [OPTION ...] [GAME]\n" +msgstr "Usage: %s [OPTION ...] [GAME]\n" + +#: src/trader.c:312 +#, c-format +msgid "" +"Play Star Traders, a simple game of interstellar trading.\n" +"\n" +msgstr "" +"Play Star Traders, a simple game of interstellar trading.\n" +"\n" + +#: src/trader.c:315 +#, c-format +msgid "" +"Options:\n" +" -V, --version output version information and exit\n" +" -h, --help display this help and exit\n" +" --no-color don't use color for displaying text\n" +" --max-turn=NUM set the number of turns to NUM\n" +"\n" +msgstr "" +"Options:\n" +" -V, --version output version information and exit\n" +" -h, --help display this help and exit\n" +" --no-colour don’t use colour for displaying text\n" +" --max-turn=NUM set the number of turns to NUM\n" +"\n" + +#: src/trader.c:322 +#, c-format +msgid "" +"If GAME is specified as a number between 1 and 9, load and continue\n" +"playing that game. If GAME is not specified, start a new game.\n" +"\n" +msgstr "" +"If GAME is specified as a number between 1 and 9, load and continue\n" +"playing that game. If GAME is not specified, start a new game.\n" +"\n" + +#. TRANSLATORS: The first %s is the proper name of the package +#. author, John Zaitseff [IPA d͡ʒɒn ˈzaɪ̯t͡səf]; the second %s is +#. the e-mail address for reporting bugs. Please add ANOTHER +#. line with the (translated) text "Report translation bugs to +#.
\n", with ADDRESS replaced with either an e-mail +#. address or web URL for reporting bugs in your translation. +#: src/trader.c:334 +#, c-format +msgid "Report bugs to %s <%s>.\n" +msgstr "Report bugs to %s <%s>.\n" + +#. TRANSLATORS: %s is the e-mail address for reporting bugs. As +#. with the previous string, please add ANOTHER line with the +#. (translated) text "Report translation bugs to
\n", +#. with ADDRESS replaced with either an e-mail address or web URL +#. for reporting bugs in your translation. +#: src/trader.c:341 +#, c-format +msgid "Report bugs to <%s>.\n" +msgstr "Report bugs to <%s>.\n" + +#. TRANSLATORS: The first %s is for packagers and may be +#. something like "Debian". +#: src/trader.c:346 +#, c-format +msgid "Report %s bugs to <%s>.\n" +msgstr "Report %s bugs to <%s>.\n" + +#: src/trader.c:349 +#, c-format +msgid "Star Traders home page: <%s>.\n" +msgstr "Star Traders home page: <%s>.\n" + +#. TRANSLATORS: The eight company names do NOT have to be literal +#. translations of the English names. In fact, if possible, the +#. names should start with successive letters of your alphabet (in +#. English, for example, "A" to "H"). No company name should be more +#. than 24 characters (column positions, to be precise) long. +#: src/globals.c:46 +msgid "Altair Starways" +msgstr "Altair Starways" + +#: src/globals.c:47 +msgid "Betelgeuse, Ltd" +msgstr "Betelgeuse, Ltd" + +#: src/globals.c:48 +msgid "Capella Freight Co" +msgstr "Capella Freight Co" + +#: src/globals.c:49 +msgid "Denebola Shippers" +msgstr "Denebola Shippers" + +#: src/globals.c:50 +msgid "Eridani Expediters" +msgstr "Eridani Expediters" + +#: src/globals.c:51 +msgid "Fornax Express" +msgstr "Fornax Express" + +#: src/globals.c:52 +msgid "Gemeni Inc" +msgstr "Gemeni Inc" + +#: src/globals.c:53 +msgid "Hercules and Co" +msgstr "Hercules and Co" + +#. TRANSLATORS: This string specifies the keycodes (keyboard input +#. codes) used to enter the Stock Transaction window for each +#. company. There must be exactly eight characters, one for each +#. company in order, before the ASCII vertical line "|"; these must +#. be EITHER all in upper-case or all in lower-case. If at all +#. possible, these should be successive letters in your alphabet (in +#. English, "A" to "H"). Do NOT use digits or control characters. +#. Do not change or translate anything after the vertical line. +#: src/globals.c:67 +msgid "ABCDEFGH|input|Companies" +msgstr "ABCDEFGH|input|Companies" + +#. TRANSLATORS: This string specifies the keycodes used to select a +#. game move. There must be exactly 20 characters, one for each +#. move, before the ASCII vertical line "|"; these must be EITHER all +#. in upper-case or all in lower-case. If at all possible, these +#. should be successive letters in your alphabet. Do NOT use digits +#. or control characters. Do not change or translate anything after +#. the vertical line. +#: src/globals.c:79 +msgid "ABCDEFGHIJKLMNOPQRST|input|GameMoves" +msgstr "ABCDEFGHIJKLMNOPQRST|input|GameMoves" + +#. TRANSLATORS: This string is used to display the galaxy map to +#. screen. There must be exactly 11 characters before the ASCII +#. vertical line. The first ("." in English) is used for empty +#. space, the second ("+") for outposts, the third ("*") for stars, +#. the remaining for the eight companies. Do not change or translate +#. anything after the vertical line. +#: src/globals.c:90 +msgid ".+*ABCDEFGH|output|MapVals" +msgstr ".+*ABCDEFGH|output|MapVals" + +#. TRANSLATORS: This string is used to display the game moves +#. (choices). There must be exactly 20 characters (NUMBER_MOVES) +#. before the ASCII vertical line. The first character corresponds +#. to the first character in the "input|GameMoves" string, and so on. +#. Do not change or translate anything after the vertical line. +#: src/globals.c:100 +msgid "abcdefghijklmnopqrst|output|GameMoves" +msgstr "abcdefghijklmnopqrst|output|GameMoves" + +#. TRANSLATORS: The ordinal strings "1st" to "8th" are used in the +#. Game Winner dialog box at the end of the game. If ordinals depend +#. on the gender of the player, it may be simpler to list cardinal +#. numbers instead (eg, "No. 1"). Up to five characters are allowed +#. (see ORDINAL_COLS in src/intf.h). +#: src/globals.c:111 +msgid "1st" +msgstr "1st" + +#: src/globals.c:112 +msgid "2nd" +msgstr "2nd" + +#: src/globals.c:113 +msgid "3rd" +msgstr "3rd" + +#: src/globals.c:114 +msgid "4th" +msgstr "4th" + +#: src/globals.c:115 +msgid "5th" +msgstr "5th" + +#: src/globals.c:116 +msgid "6th" +msgstr "6th" + +#: src/globals.c:117 +msgid "7th" +msgstr "7th" + +#: src/globals.c:118 +msgid "8th" +msgstr "8th" + +#: src/game.c:117 src/game.c:152 +#, c-format +msgid "Loading game %d... " +msgstr "Loading game %d... " + +#: src/game.c:226 +msgid " First Player " +msgstr " First Player " + +#: src/game.c:227 +#, c-format +msgid "The first player to go is ^{%ls^}." +msgstr "The first player to go is ^{%ls^}." + +#. TRANSLATORS: The keycode should be modified to +#. match that (or those) specified with msgctxt +#. "input|ContinueGame". +#: src/game.c:259 +#, c-format +msgid "Enter number of players [^{1^}-^{%d^}] or ^{^} to continue a game: " +msgstr "Enter number of players [^{1^}-^{%d^}] or ^{^} to continue a game: " + +#. TRANSLATORS: This string specifies the keycodes used to continue a +#. game; these must NOT contain any numeric digit from 1 to 9. The +#. first character (keyboard input code) is used to print the user's +#. response if one of those keys is pressed. Both upper and +#. lower-case versions should be present. +#: src/game.c:276 +msgctxt "input|ContinueGame" +msgid "Cc" +msgstr "Cc" + +#: src/game.c:341 src/move.c:380 +msgid "Enter game number [^{1^}-^{9^}] or ^{^} to cancel: " +msgstr "Enter game number [^{1^}-^{9^}] or ^{^} to cancel: " + +#: src/game.c:406 +msgid "Please enter your name: " +msgstr "Please enter your name: " + +#: src/game.c:425 +msgid "Do you need any instructions? [^{Y^}/^{N^}] " +msgstr "Do you need any instructions? [^{Y^}/^{N^}] " + +#: src/game.c:443 +msgid " Enter Player Names " +msgstr " Enter Player Names " + +#: src/game.c:451 +#, c-format, range: 1..8 +msgid "Player %d: " +msgstr "Player %d: " + +#: src/game.c:529 +msgid "Does any player need instructions? [^{Y^}/^{N^}] " +msgstr "Does any player need instructions? [^{Y^}/^{N^}] " + +#: src/game.c:563 +msgid " Game Over " +msgstr " Game Over " + +#: src/game.c:564 +#, c-format +msgid "The game is over after one turn." +msgid_plural "The game is over after %d turns." +msgstr[0] "The game is over after one turn." +msgstr[1] "The game is over after %d turns." + +#: src/game.c:575 +msgid " Total Value " +msgstr " Total Value " + +#: src/game.c:577 +#, c-format +msgid "Your total value was ^{%N^}." +msgstr "Your total value was ^{%N^}." + +#: src/game.c:588 +#, c-format +msgid "" +"The winner is ^{%ls^}\n" +"who is ^[*** BANKRUPT ***^]" +msgstr "" +"The winner is ^{%ls^}\n" +"who is ^[*** BANKRUPT ***^]" + +#: src/game.c:591 +#, c-format +msgid "" +"The winner is ^{%ls^}\n" +"with a value of ^{%N^}." +msgstr "" +"The winner is ^{%ls^}\n" +"with a value of ^{%N^}." + +#: src/game.c:597 +msgid " Game Winner " +msgstr " Game Winner " + +#. TRANSLATORS: "Player" is used as a column title in a +#. table containing all player names. +#: src/game.c:606 src/move.c:847 +msgctxt "subtitle" +msgid "Player" +msgstr "Player" + +#. TRANSLATORS: "Total Value" refers to the total worth +#. (shares, cash and debt) of any given player. %ls is the +#. currency symbol of the current locale. +#: src/game.c:611 +#, c-format +msgctxt "subtitle" +msgid "Total Value (%ls)" +msgstr "Total Value (%ls)" + +#: src/game.c:645 src/game.c:695 src/exch.c:100 +#, c-format +msgid "Player: ^{%ls^}" +msgstr "Player: ^{%ls^}" + +#: src/game.c:648 +#, c-format +msgid " Turn: ^{%d^} " +msgstr " Turn: ^{%d^} " + +#: src/game.c:649 +msgid " ^[*** Last Turn ***^] " +msgstr " ^[*** Last Turn ***^] " + +#: src/game.c:693 +msgid " Stock Portfolio " +msgstr " Stock Portfolio " + +#. TRANSLATORS: The current player is bankrupt (has no +#. shares or cash, ie, whose total value is zero) +#: src/game.c:702 +msgid "^[* * * B A N K R U P T * * *^]" +msgstr "^[* * * B A N K R U P T * * *^]" + +#: src/game.c:717 src/exch.c:112 +msgid "No companies on the map" +msgstr "No companies on the map" + +#. TRANSLATORS: "Company" is a two-line column label in +#. a table containing a list of companies. +#: src/game.c:725 src/exch.c:120 +msgctxt "subtitle" +msgid "" +"\n" +"Company" +msgstr "" +"\n" +"Company" + +#. TRANSLATORS: "Ownership" is a two-line column label +#. in a table containing the current player's +#. percentage ownership in any given company. The +#. maximum column width is 10 characters (see +#. OWNERSHIP_COLS in src/intf.h). +#: src/game.c:732 +#, c-format +msgctxt "subtitle" +msgid "" +"Ownership\n" +"(%%)" +msgstr "" +"Ownership\n" +"(%%)" + +#. TRANSLATORS: "Holdings" is a two-line column label +#. in a table containing the number of shares the +#. current player owns in any given company. The +#. maximum column width is 10 characters (see +#. STOCK_OWNED_COLS in src/intf.h). +#: src/game.c:739 +msgctxt "subtitle" +msgid "" +"Holdings\n" +"(shares)" +msgstr "" +"Holdings\n" +"(shares)" + +#. TRANSLATORS: "Return" is a two-line column label in +#. a table containing the share return as a percentage +#. in any given company. The maximum column width is +#. 10 characters (see SHARE_RETURN_COLS in src/intf.h). +#: src/game.c:746 src/exch.c:141 +#, c-format +msgctxt "subtitle" +msgid "" +"Return\n" +"(%%)" +msgstr "" +"Return\n" +"(%%)" + +#. TRANSLATORS: "Price per share" is a two-line column +#. label in a table containing the price per share in +#. any given company. %ls is the currency symbol in +#. the current locale. The maximum column width is 12 +#. characters INCLUDING the currency symbol (see +#. SHARE_PRICE_COLS in src/intf.h). +#: src/game.c:755 src/exch.c:150 +#, c-format +msgctxt "subtitle" +msgid "" +"Price per\n" +"share (%ls)" +msgstr "" +"Price per\n" +"share (%ls)" + +#. TRANSLATORS: The "Total value", "Current cash", +#. "Current debt" and "Interest rate" labels MUST all be +#. the same length (ie, right-padded with spaces as +#. needed) and must have at least one trailing space so +#. that the display routines work correctly. The maximum +#. length of each label is 36 characters. +#. +#. Note that some of these labels are used for both the +#. Player Status window and the Trading Bank window. +#: src/game.c:796 +msgctxt "label" +msgid "Total value: " +msgstr "Total value: " + +#: src/game.c:800 src/exch.c:323 +msgctxt "label" +msgid "Current cash: " +msgstr "Current cash: " + +#: src/game.c:807 src/exch.c:331 +msgctxt "label" +msgid "Current debt: " +msgstr "Current debt: " + +#: src/game.c:813 src/exch.c:336 +msgctxt "label" +msgid "Interest rate: " +msgstr "Interest rate: " + +#: src/move.c:235 src/exch.c:183 +msgid "^{<1>^} Display stock portfolio" +msgstr "^{<1>^} Display stock portfolio" + +#: src/move.c:237 +msgid "^{<2>^} Declare bankruptcy" +msgstr "^{<2>^} Declare bankruptcy" + +#: src/move.c:239 +msgid "^{<3>^} Save and end the game" +msgstr "^{<3>^} Save and end the game" + +#: src/move.c:241 +msgid "^{^} Quit the game" +msgstr "^{^} Quit the game" + +#: src/move.c:245 +#, c-format +msgid "Select move [^[%lc^]-^[%lc^]/^{1^}-^{3^}/^{^}]: " +msgstr "Select move [^[%lc^]-^[%lc^]/^{1^}-^{3^}/^{^}]: " + +#. TRANSLATORS: "Move" refers to the choice of +#. moves made by the current player (out of a +#. selection of 20 moves). +#: src/move.c:277 +#, c-format +msgid "Move ^{%lc^}" +msgstr "Move ^{%lc^}" + +#: src/move.c:297 +msgid "^{<2>^} (Declare bankruptcy)" +msgstr "^{<2>^} (Declare bankruptcy)" + +#: src/move.c:306 +msgid "^{<3>^} (Save and end the game)" +msgstr "^{<3>^} (Save and end the game)" + +#: src/move.c:327 +msgid "^{^} (Quit the game)" +msgstr "^{^} (Quit the game)" + +#: src/move.c:342 +msgid "Are you sure? [^{Y^}/^{N^}] " +msgstr "Are you sure? [^{Y^}/^{N^}] " + +#: src/move.c:359 src/move.c:437 +#, c-format +msgid "Saving game %d... " +msgstr "Saving game %d... " + +#: src/move.c:667 src/move.c:674 src/move.c:1018 src/move.c:1052 +msgid " Bankruptcy Court " +msgstr " Bankruptcy Court " + +#: src/move.c:668 +#, c-format +msgid "%ls has been declared bankrupt by the Interstellar Trading Bank." +msgstr "%ls has been declared bankrupt by the Interstellar Trading Bank." + +#: src/move.c:675 +#, c-format +msgid "%ls has declared bankruptcy." +msgstr "%ls has declared bankruptcy." + +#: src/move.c:743 +msgid " New Company " +msgstr " New Company " + +#: src/move.c:744 +#, c-format +msgid "" +"A new company has been formed!\n" +"Its name is ^{%ls^}." +msgstr "" +"A new company has been formed!\n" +"Its name is ^{%ls^}." + +#: src/move.c:803 +#, c-format +msgid "" +"^{%ls^} has just merged into ^{%ls^}.\n" +"Please note the following transactions:\n" +msgstr "" +"^{%ls^} has just merged into ^{%ls^}.\n" +"Please note the following transactions:\n" + +#: src/move.c:809 +msgid " Company Merger " +msgstr " Company Merger " + +#. TRANSLATORS: "Old stock" refers to the company that has +#. just ceased existence due to a merger. +#. +#. Note that the "Old stock" and "New stock" labels MUST be +#. the same length and must contain a trailing space for the +#. display routines to work correctly. The maximum length of +#. each label is 36 characters. +#: src/move.c:829 +msgctxt "label" +msgid "Old stock: " +msgstr "Old stock: " + +#. TRANSLATORS: "New stock" refers to the company that has +#. absorbed another due to a merger. +#: src/move.c:840 +msgctxt "label" +msgid "New Stock: " +msgstr "New Stock: " + +#. TRANSLATORS: "Bonus" refers to the bonus cash amount paid to +#. each player after two companies merge. %ls is the currency +#. symbol in the current locale. The maximum column width is +#. 12 characters INCLUDING the currency symbol (see +#. MERGE_BONUS_COLS in src/intf.h). +#: src/move.c:854 +#, c-format +msgctxt "subtitle" +msgid "Bonus (%ls)" +msgstr "Bonus (%ls)" + +#. TRANSLATORS: "Total" refers to the total number of shares in +#. the new company after a merger. The maximum column width is +#. 8 characters (see MERGE_TOTAL_STOCK_COLS in src/intf.h). +#: src/move.c:859 +msgctxt "subtitle" +msgid "Total" +msgstr "Total" + +#. TRANSLATORS: "New" refers to how many (new) shares each +#. player receives in the surviving company after a merger. +#. The maximum column width is 8 characters (see +#. MERGE_NEW_STOCK_COLS in src/intf.h). +#: src/move.c:866 +msgctxt "subtitle" +msgid "New" +msgstr "New" + +#. TRANSLATORS: "Old" refers to how many shares each player had +#. in the company ceasing existence. The maximum column width +#. is 8 characters (see MERGE_OLD_STOCK_COLS in src/intf.h). +#: src/move.c:872 +msgctxt "subtitle" +msgid "Old" +msgstr "Old" + +#: src/move.c:1019 +#, c-format +msgid "" +"%ls has been declared bankrupt by the Interstellar Trading Bank.\n" +"\n" +"^{All assets have been taken to repay outstanding loans.^}" +msgstr "" +"%ls has been declared bankrupt by the Interstellar Trading Bank.\n" +"\n" +"^{All assets have been taken to repay outstanding loans.^}" + +#: src/move.c:1041 +#, c-format +msgid "" +"%ls has been declared bankrupt by the Interstellar Trading Bank.\n" +"\n" +"^{The Bank has agreed to pay stock holders ^}%.2f%%^{ of the share value on " +"each share owned.^}" +msgstr "" +"%ls has been declared bankrupt by the Interstellar Trading Bank.\n" +"\n" +"^{The Bank has agreed to pay stock holders ^}%.2f%%^{ of the share value on " +"each share owned.^}" + +#. TRANSLATORS: The label "Amount paid per share" +#. refers to payment made by the Interstellar +#. Trading Bank to each player upon company +#. bankruptcy. This label MUST be the same +#. length as "Old share value" and MUST have at +#. least one trailing space for the display +#. routines to work correctly. The maximum +#. length is 28 characters. +#: src/move.c:1069 +msgctxt "label" +msgid "Amount paid per share: " +msgstr "Amount paid per share: " + +#. TRANSLATORS: "Old share value" refers to the +#. share price of a company before it was forced +#. into bankruptcy by the Bank. This label must be +#. the same width as "Amount paid per share". +#: src/move.c:1077 +msgctxt "label" +msgid "Old share value: " +msgstr "Old share value: " + +#: src/move.c:1170 src/exch.c:320 +msgid " Interstellar Trading Bank " +msgstr " Interstellar Trading Bank " + +#: src/move.c:1172 +#, c-format +msgid "" +"Your debt has amounted to %N!\n" +"^{The Bank has impounded ^}%N^{ from your cash.^}" +msgstr "" +"Your debt has amounted to %N!\n" +"^{The Bank has impounded ^}%N^{ from your cash.^}" + +#: src/exch.c:98 +msgid " Interstellar Stock Exchange " +msgstr " Interstellar Stock Exchange " + +#. TRANSLATORS: "Shares left" is a two-line column +#. label in a table containing the number of shares +#. left to be purchased in any given company. The +#. maximum column width is 10 characters (see +#. STOCK_LEFT_COLS in src/intf.h). +#: src/exch.c:127 +msgctxt "subtitle" +msgid "" +"Shares\n" +"left" +msgstr "" +"Shares\n" +"left" + +#. TRANSLATORS: "Shares issued" is a two-line column +#. label in a table containing the number of shares +#. already sold (ie, bought by all players) in any +#. given company. The maximum column width is 10 +#. characters (see STOCK_ISSUED_COLS in src/intf.h). +#: src/exch.c:134 +msgctxt "subtitle" +msgid "" +"Shares\n" +"issued" +msgstr "" +"Shares\n" +"issued" + +#: src/exch.c:185 +msgid "^{<2>^} Display galaxy map" +msgstr "^{<2>^} Display galaxy map" + +#: src/exch.c:187 +msgid "^{<3>^} Visit the Trading Bank" +msgstr "^{<3>^} Visit the Trading Bank" + +#: src/exch.c:189 +msgid "^{<4>^} Exit the Stock Exchange" +msgstr "^{<4>^} Exit the Stock Exchange" + +#: src/exch.c:192 +msgid "Enter selection [^[Company letter^]/^{1^}-^{4^}]: " +msgstr "Enter selection [^[Company letter^]/^{1^}-^{4^}]: " + +#. TRANSLATORS: The "Total value", "Current cash", "Current +#. debt", "Interest rate" and "Credit limit" labels MUST all be +#. the same length (ie, right-padded with spaces as needed) and +#. must have at least one trailing space so that the display +#. routines work correctly. The maximum length of each label +#. is 36 characters. +#. +#. Note that some of these labels are used for both the Player +#. Status window and the Trading Bank window. +#: src/exch.c:350 +msgctxt "label" +msgid "Credit limit: " +msgstr "Credit limit: " + +#. TRANSLATORS: The "Borrow money", "Repay debt" and "Exit +#. from the Bank" menu options must all be the same length +#. (ie, padded with trailing spaces as required). The maximum +#. length is 72 characters. +#: src/exch.c:365 +msgid "^{<1>^} Borrow money " +msgstr "^{<1>^} Borrow money " + +#: src/exch.c:367 +msgid "^{<2>^} Repay debt " +msgstr "^{<2>^} Repay debt " + +#: src/exch.c:369 +msgid "^{<3>^} Exit from the Bank" +msgstr "^{<3>^} Exit from the Bank" + +#: src/exch.c:372 +msgid "Enter selection [^{1^}-^{3^}]: " +msgstr "Enter selection [^{1^}-^{3^}]: " + +#: src/exch.c:425 +msgid " Insufficient Credit Limit " +msgstr " Insufficient Credit Limit " + +#: src/exch.c:426 +msgid "The Bank will not lend you any more money." +msgstr "The Bank will not lend you any more money." + +#: src/exch.c:446 +msgid "How much do you wish to borrow? " +msgstr "How much do you wish to borrow? " + +#: src/exch.c:478 +msgid " No Debt " +msgstr " No Debt " + +#: src/exch.c:479 +msgid "You have no debt to repay." +msgstr "You have no debt to repay." + +#: src/exch.c:483 +msgid " No Cash " +msgstr " No Cash " + +#: src/exch.c:484 +msgid "You have no cash with which to repay the debt!" +msgstr "You have no cash with which to repay the debt!" + +#: src/exch.c:504 +msgid "How much do you wish to repay? " +msgstr "How much do you wish to repay? " + +#. TRANSLATORS: %ls represents the company name. +#: src/exch.c:580 +#, c-format +msgid " Stock Transaction in %ls " +msgstr " Stock Transaction in %ls " + +#. TRANSLATORS: "Shares issued" represents the number of +#. shares already sold by the company to all players. +#. +#. Note that the labels "Shares issued", "Shares left", +#. "Price per share" and "Return" must all be the same length +#. and must have at least one trailing space for the output +#. routines to work correctly. The maximum length of each +#. label is 22 characters. +#: src/exch.c:591 +msgctxt "label|Stock A" +msgid "Shares issued: " +msgstr "Shares issued: " + +#. TRANSLATORS: "Shares left" is the number of shares that are +#. left to be purchased in the current company. +#: src/exch.c:599 +msgctxt "label|Stock A" +msgid "Shares left: " +msgstr "Shares left: " + +#. TRANSLATORS: "Price per share" is the cost of each share in +#. the current company. +#: src/exch.c:606 +msgctxt "label|Stock A" +msgid "Price per share: " +msgstr "Price per share: " + +#. TRANSLATORS: "Return" is the share return as a percentage. +#: src/exch.c:612 +msgctxt "label|Stock A" +msgid "Return: " +msgstr "Return: " + +#. TRANSLATORS: "Current holdings" is the number of shares the +#. current player owns in this particular company. +#. +#. Note that the labels "Current holdings", "Percentage owned" +#. and "Current cash" MUST all be the same length and contain at +#. least one trailing space for the display routines to work +#. correctly. The maximum length of each label is 18 +#. characters. +#: src/exch.c:625 +msgctxt "label|Stock B" +msgid "Current holdings: " +msgstr "Current holdings: " + +#. TRANSLATORS: "Percentage owned" is the current player's +#. percentage ownership in this particular company. +#: src/exch.c:632 +msgctxt "label|Stock B" +msgid "Percentage owned: " +msgstr "Percentage owned: " + +#: src/exch.c:637 +msgctxt "label|Stock B" +msgid "Current cash: " +msgstr "Current cash: " + +#: src/exch.c:648 +msgid "^{<1>^} Buy stock from company" +msgstr "^{<1>^} Buy stock from company" + +#: src/exch.c:650 +msgid "^{<2>^} Sell stock back to company" +msgstr "^{<2>^} Sell stock back to company" + +#: src/exch.c:652 +msgid "^{<3>^} Bid company to issue more shares" +msgstr "^{<3>^} Bid company to issue more shares" + +#: src/exch.c:654 +msgid "^{<4>^} Exit to the Stock Exchange" +msgstr "^{<4>^} Exit to the Stock Exchange" + +#: src/exch.c:657 +msgid "Enter selection [^{1^}-^{4^}]: " +msgstr "Enter selection [^{1^}-^{4^}]: " + +#: src/exch.c:713 +msgid " No Shares Available " +msgstr " No Shares Available " + +#: src/exch.c:714 +msgid "No more shares are available for purchase." +msgstr "No more shares are available for purchase." + +#: src/exch.c:718 +msgid " Insufficient Cash " +msgstr " Insufficient Cash " + +#: src/exch.c:719 +msgid "" +"You do not have enough cash\n" +"to purchase additional shares." +msgstr "" +"You do not have enough cash\n" +"to purchase additional shares." + +#: src/exch.c:730 +#, c-format +msgid "You can purchase ^{one^} share." +msgid_plural "You can purchase up to ^{%'ld^} shares." +msgstr[0] "You can purchase ^{one^} share." +msgstr[1] "You can purchase up to ^{%'ld^} shares." + +#: src/exch.c:736 +msgid "How many shares do you wish to purchase? " +msgstr "How many shares do you wish to purchase? " + +#: src/exch.c:757 +msgid " No Shares " +msgstr " No Shares " + +#: src/exch.c:758 +msgid "You do not have any shares to sell." +msgstr "You do not have any shares to sell." + +#: src/exch.c:765 +#, c-format +msgid "You can sell ^{one^} share." +msgid_plural "You can sell up to ^{%'ld^} shares." +msgstr[0] "You can sell ^{one^} share." +msgstr[1] "You can sell up to ^{%'ld^} shares." + +#: src/exch.c:771 +msgid "How many shares do you wish to sell? " +msgstr "How many shares do you wish to sell? " + +#: src/exch.c:799 +msgid " No Shares Issued " +msgstr " No Shares Issued " + +#. TRANSLATORS: %ls represents the company name. +#: src/exch.c:801 +#, c-format +msgid "" +"%ls has refused\n" +"to issue more shares." +msgstr "" +"%ls has refused\n" +"to issue more shares." + +#: src/exch.c:806 +msgid " Shares Issued " +msgstr " Shares Issued " + +#. TRANSLATORS: %ls represents the company name. +#: src/exch.c:808 +#, c-format +msgid "" +"%ls has issued\n" +"^{one^} more share." +msgid_plural "" +"%ls has issued\n" +"^{%'ld^} more shares." +msgstr[0] "" +"%ls has issued\n" +"^{one^} more share." +msgstr[1] "" +"%ls has issued\n" +"^{%'ld^} more shares." + +#: src/fileio.c:55 src/fileio.c:92 src/fileio.c:131 src/fileio.c:381 +#, c-format +msgid "%s: missing field on line %d" +msgstr "%s: missing field on line %d" + +#: src/fileio.c:60 +#, c-format +msgid "%s: illegal field on line %d: `%s'" +msgstr "%s: illegal field on line %d: ‘%s’" + +#: src/fileio.c:64 +#, c-format +msgid "%s: illegal value on line %d: `%s'" +msgstr "%s: illegal value on line %d: ‘%s’" + +#: src/fileio.c:96 src/fileio.c:135 src/fileio.c:393 +#, c-format +msgid "%s: illegal value on line %d" +msgstr "%s: illegal value on line %d" + +#: src/fileio.c:103 +#, c-format +msgid "%s: illegal characters on line %d" +msgstr "%s: illegal characters on line %d" + +#: src/fileio.c:184 +#, c-format +msgid "%s: could not convert string" +msgstr "%s: could not convert string" + +#: src/fileio.c:255 +msgid " Game Not Found " +msgstr " Game Not Found " + +#: src/fileio.c:256 +#, c-format +msgid "Game %d has not been saved to disk." +msgstr "Game %d has not been saved to disk." + +#: src/fileio.c:263 +msgid " Game Not Loaded " +msgstr " Game Not Loaded " + +#: src/fileio.c:264 +#, c-format +msgid "" +"Game %d could not be loaded from disk.\n" +"\n" +"^{File %s: %s^}" +msgstr "" +"Game %d could not be loaded from disk.\n" +"\n" +"^{File %s: %s^}" + +#: src/fileio.c:316 +#, c-format +msgid "%s: missing header in game file" +msgstr "%s: missing header in game file" + +#: src/fileio.c:319 +#, c-format +msgid "%s: not a valid game file" +msgstr "%s: not a valid game file" + +#: src/fileio.c:322 src/fileio.c:329 +#, c-format +msgid "%s: missing subheader in game file" +msgstr "%s: missing subheader in game file" + +#: src/fileio.c:325 +#, c-format +msgid "%s: saved under a different version of Star Traders" +msgstr "%s: saved under a different version of Star Traders" + +#: src/fileio.c:332 +#, c-format +msgid "%s: saved under an incompatible character encoding" +msgstr "%s: saved under an incompatible character encoding" + +#: src/fileio.c:340 +#, c-format +msgid "%s: illegal or missing field on line %d" +msgstr "%s: illegal or missing field on line %d" + +#: src/fileio.c:384 +#, c-format +msgid "%s: illegal field on line %d" +msgstr "%s: illegal field on line %d" + +#: src/fileio.c:466 src/fileio.c:487 +msgid " Game Not Saved " +msgstr " Game Not Saved " + +#: src/fileio.c:467 +#, c-format +msgid "" +"Game %d could not be saved to disk.\n" +"\n" +"^{Directory %s: %s^}" +msgstr "" +"Game %d could not be saved to disk.\n" +"\n" +"^{Directory %s: %s^}" + +#: src/fileio.c:488 +#, c-format +msgid "" +"Game %d could not be saved to disk.\n" +"\n" +"^{File %s: %s^}" +msgstr "" +"Game %d could not be saved to disk.\n" +"\n" +"^{File %s: %s^}" + +#. TRANSLATORS: The help text for Star Traders is marked up using a +#. custom mark-up format NOT used anywhere else in the source code. +#. +#. Each string is a single page of text that is displayed in an area 76 +#. columns wide by 16 lines high. Each line is delimited by "\n". NO +#. word-wrapping is performed: you must place the "\n" characters in the +#. appropriate place. Ideally, each line within the string should be +#. also (manually) space-justified or centred. TAB characters and other +#. control codes must NOT be used. If a string starts with "@" as the +#. very first character, that string is ignored (as are all strings +#. following): this allows a variable number of help text pages (from +#. one to ten). Multibyte strings are handled correctly (even those +#. requiring shift sequences!). +#. +#. The ASCII circumflex accent character "^" switches to a different +#. character rendition (also called attributes), depending on the +#. character following the "^": +#. +#. ^^ - Print the circumflex accent (ASCII code U+005E) +#. ^N - Switch to using the normal character rendition +#. ^B - Switch to using the bold character rendition +#. ^H - Switch to using the highlight character rendition +#. ^K - Switch to using the keycode character rendition (such as used for "") +#. ^e - Switch to using the character rendition used for empty space +#. ^o - Switch to using the character rendition used for outposts +#. ^s - Switch to using the character rendition used for stars +#. ^c - Switch to using the character rendition used for companies +#. ^k - Switch to using the character rendition used for keyboard choices on the galaxy map +#. +#. The help text parsing routines also understand the following "value +#. escapes" introduced by the ASCII tilde character "~"; these act like +#. "%" conversion specifiers in printf(): +#. +#. ~~ - Print the tilde character (ASCII code U+007E) [*] +#. ~x - Print the width of the galaxy map (MAX_X) [**] +#. ~y - Print the height of the galaxy map (MAX_Y) [**] +#. ~m - Print the number of moves available (NUMBER_MOVES) [**] +#. ~c - Print the maximum number of companies that can be formed (MAX_COMPANIES) [*] +#. ~t - Prints the default number of turns in the game (DEFAULT_MAX_TURN) [**] +#. ~1 to ~9 - Print the keycode for the N-th choice of move [***] +#. ~M - Print the keycode for the last choice of move [***] +#. ~A to ~H - Print the character used to represent the company on the galaxy map [***] +#. ~. - Print the character used to represent empty space on the map [***] +#. ~+ - Print the character used to represent outposts on the map [***] +#. ~* - Print the character used to represent stars on the map [***] +#. +#. [*] Takes one character space (column space) in the output +#. [**] Takes two column spaces in the output +#. [***] Takes one or two column spaces in the output, depending on the +#. appropriate strings in the current PO file. +#. +#. Note that all keycodes and map representation characters use locale- +#. specific characters; double-width characters ARE supported. Note +#. also that the tilde value escapes do NOT change the current character +#. rendition: a circumflex accent escape is needed for that. For +#. example, to display the first choice of move as it would be shown on +#. the galaxy map, use something like "^k~1^N" (a six-character sequence +#. that would translate to just one character (or maybe two) in the +#. output text). +#. +#: src/help.c:103 +msgid "" +"^BStar Traders^N is a simple game of interstellar trading. The object of the\n" +"game is to amass the greatest amount of wealth possible. This is done by\n" +"creating interstellar shipping lanes, expanding them and buying shares in\n" +"the companies controlling them. Shares appreciate in value as company\n" +"operations expand. In addition, the return on each share (as a percentage)\n" +"also changes. Players may also borrow from the Interstellar Trading Bank to\n" +"finance additional purchases on the Stock Exchange.\n" +"\n" +"The map of the galaxy is represented by a ^B~x^N x ^B~y^N grid. A typical section\n" +"of it may be:\n" +"\n" +" ^e ~. ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" +" ^e ~. ~. ~. ~. ~. ~. ~. ~. ~. ^N ^e ~. ^N represents ^Bempty space^N,\n" +" ^e ~. ^s~*^e ~. ~. ~. ~. ~. ~. ~. ^N ^s ~* ^N represents a ^Bstar^N.\n" +" ^e ~. ~. ~. ~. ~. ~. ~. ^s~*^e ~. ^N\n" +" ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ~. ^N\n" +msgstr "" +"^BStar Traders^N is a simple game of interstellar trading. The object of the\n" +"game is to amass the greatest amount of wealth possible. This is done by\n" +"creating interstellar shipping lanes, expanding them and buying shares in\n" +"the companies controlling them. Shares appreciate in value as company\n" +"operations expand. In addition, the return on each share (as a percentage)\n" +"also changes. Players may also borrow from the Interstellar Trading Bank to\n" +"finance additional purchases on the Stock Exchange.\n" +"\n" +"The map of the galaxy is represented by a ^B~x^N x ^B~y^N grid. A typical section\n" +"of it may be:\n" +"\n" +" ^e ~. ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" +" ^e ~. ~. ~. ~. ~. ~. ~. ~. ~. ^N ^e ~. ^N represents ^Bempty space^N,\n" +" ^e ~. ^s~*^e ~. ~. ~. ~. ~. ~. ~. ^N ^s ~* ^N represents a ^Bstar^N.\n" +" ^e ~. ~. ~. ~. ~. ~. ~. ^s~*^e ~. ^N\n" +" ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ~. ^N\n" + +#: src/help.c:122 +msgid "" +"The computer selects ^B~m^N moves (labeled ^k~1^N to ^k~M^N) at random, and places these\n" +"on the map. To select any of the highlighted positions, press that letter.\n" +"For example, some of the moves on the map may be:\n" +"\n" +"\n" +" ^e ^k~1^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" +" ^e ~. ~. ~. ^k~3^e ~. ~. ~. ~. ~. ^N\n" +" ^e ~. ^s~*^e ~. ~. ~. ~. ^k~5^e ~. ~. ^N Moves ^k~1^N to ^k~5^N shown.\n" +" ^e ~. ^k~2^e ~. ~. ^k~4^e ~. ~. ^s~*^e ~. ^N\n" +" ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ~. ^N\n" +"\n" +"\n" +"Selecting a position that is ^Bnot^N next to a star (such as moves ^k~1^N, ^k~3^N or ^k~5^N)\n" +"will set up an ^Boutpost^N, not belonging to any company. Thus, if move ^k~3^N is\n" +"selected on the above map, a ^o ~+ ^N would be placed at that position.\n" +msgstr "" +"The computer selects ^B~m^N moves (labelled ^k~1^N to ^k~M^N) at random, and places these\n" +"on the map. To select any of the highlighted positions, press that letter.\n" +"For example, some of the moves on the map may be:\n" +"\n" +"\n" +" ^e ^k~1^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" +" ^e ~. ~. ~. ^k~3^e ~. ~. ~. ~. ~. ^N\n" +" ^e ~. ^s~*^e ~. ~. ~. ~. ^k~5^e ~. ~. ^N Moves ^k~1^N to ^k~5^N shown.\n" +" ^e ~. ^k~2^e ~. ~. ^k~4^e ~. ~. ^s~*^e ~. ^N\n" +" ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ~. ^N\n" +"\n" +"\n" +"Selecting a position that is ^Bnot^N next to a star (such as moves ^k~1^N, ^k~3^N or ^k~5^N)\n" +"will set up an ^Boutpost^N, not belonging to any company. Thus, if move ^k~3^N is\n" +"selected on the above map, a ^o ~+ ^N would be placed at that position.\n" + +#: src/help.c:140 +msgid "" +"If, on the other hand, a position next to a star (or another outpost) is\n" +"selected, a ^Bcompany^N would be formed and its letter would appear on the map.\n" +"As a reward for creating the company, you are granted the first five shares.\n" +"Up to ^B~c^N companies can be created in this way.\n" +"\n" +"If a position next to an existing company is selected, the company would\n" +"expand its operations by one square. This increases the cost of its shares\n" +"and hence your return. Thus, if the map was as shown below, selecting ^k~6^N\n" +"or ^k~8^N increases Company ^B~B^N's shipping lane:\n" +"\n" +" ^e ^k~1^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" +" ^e ~. ~. ~. ^o~+^e ~. ~. ^k~6^e ~. ~. ^N\n" +" ^e ~. ^s~*^e ~. ~. ~. ~. ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~6^N or ^k~8^N increases Company ^B~B^N.\n" +" ^e ~. ^k~2^e ~. ~. ^k~4^e ~. ~. ^s~*^e ^c~B^e ^N\n" +" ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ^k~8^e ^N\n" +msgstr "" +"If, on the other hand, a position next to a star (or another outpost) is\n" +"selected, a ^Bcompany^N would be formed and its letter would appear on the map.\n" +"As a reward for creating the company, you are granted the first five shares.\n" +"Up to ^B~c^N companies can be created in this way.\n" +"\n" +"If a position next to an existing company is selected, the company would\n" +"expand its operations by one square. This increases the cost of its shares\n" +"and hence your return. Thus, if the map was as shown below, selecting ^k~6^N\n" +"or ^k~8^N increases Company ^B~B^N’s shipping lane:\n" +"\n" +" ^e ^k~1^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" +" ^e ~. ~. ~. ^o~+^e ~. ~. ^k~6^e ~. ~. ^N\n" +" ^e ~. ^s~*^e ~. ~. ~. ~. ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~6^N or ^k~8^N increases Company ^B~B^N.\n" +" ^e ~. ^k~2^e ~. ~. ^k~4^e ~. ~. ^s~*^e ^c~B^e ^N\n" +" ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ^k~8^e ^N\n" + +#: src/help.c:158 +msgid "" +"Selecting positions next to stars increases the value of your stock by about\n" +"five times as much as an extension not next to a star. Thus move ^k~6^N should\n" +"be preferred to move ^k~8^N.\n" +"\n" +" ^e ^c~C^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" +" ^e ^k~1^e ^o~+^e ~. ^o~+^e ~. ~. ^k~6^e ~. ~. ^N\n" +" ^e ~. ^s~*^e ~. ~. ~. ~. ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~6^N is preferred to ^k~8^N.\n" +" ^e ~. ^k~2^e ~. ~. ^k~4^e ~. ~. ^s~*^e ^c~B^e ^N\n" +" ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ^k~8^e ^N\n" +"\n" +"You may also expand any company by selecting positions next to outposts.\n" +"Such outposts will be swallowed up by that company. Thus, move ^k~1^N will\n" +"extend Company ^B~C^N by ^Btwo^N squares. As a bonus, outposts next to stars are\n" +"more valuable: the company's share price will increase by a greater amount\n" +"than it would for outposts not next to stars.\n" +msgstr "" +"Selecting positions next to stars increases the value of your stock by about\n" +"five times as much as an extension not next to a star. Thus move ^k~6^N should\n" +"be preferred to move ^k~8^N.\n" +"\n" +" ^e ^c~C^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" +" ^e ^k~1^e ^o~+^e ~. ^o~+^e ~. ~. ^k~6^e ~. ~. ^N\n" +" ^e ~. ^s~*^e ~. ~. ~. ~. ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~6^N is preferred to ^k~8^N.\n" +" ^e ~. ^k~2^e ~. ~. ^k~4^e ~. ~. ^s~*^e ^c~B^e ^N\n" +" ^e ~. ~. ~. ~. ^s~*^e ~. ~. ~. ^k~8^e ^N\n" +"\n" +"You may also expand any company by selecting positions next to outposts.\n" +"Such outposts will be swallowed up by that company. Thus, move ^k~1^N will\n" +"extend Company ^B~C^N by ^Btwo^N squares. As a bonus, outposts next to stars are\n" +"more valuable: the company’s share price will increase by a greater amount\n" +"than it would for outposts not next to stars.\n" + +#: src/help.c:176 +msgid "" +"If two companies are separated on the map by only one square, then they can\n" +"be ^Bmerged^N into one company by selecting that position (if available). For\n" +"example, on the map below, companies ^B~A^N and ^B~B^N can be merged by selecting ^k~5^N.\n" +"When this occurs, the company with the greater assets value takes over the\n" +"other one. Here, Company ^B~B^N might take over Company ^B~A^N. Company ^B~A^N ceases to\n" +"exist, although it may reappear as an entirely new company at a later stage.\n" +"\n" +" ^e ^k~1^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" +" ^e ~. ~. ~. ^c~A^e ^c~A^e ^k~5^e ^c~B^e ~. ~. ^N\n" +" ^e ~. ^s~*^e ~. ~. ^c~A^e ~. ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~5^N merges companies ^B~A^N and ^B~B^N.\n" +" ^e ~. ^k~2^e ~. ~. ~. ~. ~. ^s~*^e ^c~B^e ^N\n" +" ^e ~. ~. ~. ~. ^s~*^e ~. ^o~+^e ~. ~. ^N\n" +"\n" +"When companies merge, players are granted shares in the dominant company\n" +"proportional to the amount owned in the old company. As well, a cash bonus\n" +"is also paid, proportional to the percentage of the old company owned.\n" +msgstr "" +"If two companies are separated on the map by only one square, then they can\n" +"be ^Bmerged^N into one company by selecting that position (if available). For\n" +"example, on the map below, companies ^B~A^N and ^B~B^N can be merged by selecting ^k~5^N.\n" +"When this occurs, the company with the greater assets value takes over the\n" +"other one. Here, Company ^B~B^N might take over Company ^B~A^N. Company ^B~A^N ceases to\n" +"exist, although it may reappear as an entirely new company at a later stage.\n" +"\n" +" ^e ^k~1^e ~. ^s~*^e ~. ~. ~. ^s~*^e ^s~*^e ~. ^N\n" +" ^e ~. ~. ~. ^c~A^e ^c~A^e ^k~5^e ^c~B^e ~. ~. ^N\n" +" ^e ~. ^s~*^e ~. ~. ^c~A^e ~. ^c~B^e ^c~B^e ^c~B^e ^N Move ^k~5^N merges companies ^B~A^N and ^B~B^N.\n" +" ^e ~. ^k~2^e ~. ~. ~. ~. ~. ^s~*^e ^c~B^e ^N\n" +" ^e ~. ~. ~. ~. ^s~*^e ~. ^o~+^e ~. ~. ^N\n" +"\n" +"When companies merge, players are granted shares in the dominant company\n" +"proportional to the amount owned in the old company. As well, a cash bonus\n" +"is also paid, proportional to the percentage of the old company owned.\n" + +#: src/help.c:195 +msgid "" +"Once you select your move, you enter the ^BInterstellar Stock Exchange^N. Here\n" +"you may purchase shares, sell them, borrow from the Trading Bank or repay\n" +"some of your debt (if applicable). Note that each company issues a limited\n" +"number of shares -- you cannot go on buying for ever! You may, however, bid\n" +"for more shares to be issued. You have a better chance of succeeding if you\n" +"own a larger proportion of the company.\n" +"\n" +"The game usually ends after ^B~t^N turns. However, you may end the game sooner\n" +"by pressing ^K^N when asked to select a move. As well, individual\n" +"players can declare themselves bankrupt at any time. If your debt is large\n" +"enough, the Bank may do this for you! If you do not complete your game in\n" +"the time you have available, you may save the game and continue it later.\n" +"\n" +"\n" +"The ^Bwinner of the game^N is the person with the greatest net worth (total\n" +"value of cash, stock and debt). ^HGood luck^N and may the best person win!\n" +msgstr "" +"Once you select your move, you enter the ^BInterstellar Stock Exchange^N. Here\n" +"you may purchase shares, sell them, borrow from the Trading Bank or repay\n" +"some of your debt (if applicable). Note that each company issues a limited\n" +"number of shares -- you cannot go on buying for ever! You may, however, bid\n" +"for more shares to be issued. You have a better chance of succeeding if you\n" +"own a larger proportion of the company.\n" +"\n" +"The game usually ends after ^B~t^N turns. However, you may end the game sooner\n" +"by pressing ^K^N when asked to select a move. As well, individual\n" +"players can declare themselves bankrupt at any time. If your debt is large\n" +"enough, the Bank may do this for you! If you do not complete your game in\n" +"the time you have available, you may save the game and continue it later.\n" +"\n" +"\n" +"The ^Bwinner of the game^N is the person with the greatest net worth (total\n" +"value of cash, stock and debt). ^HGood luck^N and may the best person win!\n" + +#: src/help.c:215 +msgid "@ Help text, page 7" +msgstr "@ Help text, page 7" + +#: src/help.c:216 +msgid "@ Help text, page 8" +msgstr "@ Help text, page 8" + +#: src/help.c:217 +msgid "@ Help text, page 9" +msgstr "@ Help text, page 9" + +#: src/help.c:218 +msgid "@ Help text, page 10" +msgstr "@ Help text, page 10" + +#: src/help.c:270 +msgid " How to Play " +msgstr " How to Play " + +#: src/help.c:272 +#, c-format +msgid "Page %d of %d" +msgstr "Page %d of %d" + +#. TRANSLATORS: The reason the user is not asked "Press any +#. key to continue" is historical: many, many people used to +#. ask "where is the key?" :-) +#: src/help.c:473 src/intf.c:3022 +msgid "[ Press to continue ] " +msgstr "[ Press to continue ] " + +#. TRANSLATORS: The specific use of and +#. is not essential: you can use , +#. , , or instead of +#. , and almost any other key instead of +#. (other than , , , , +#. or <\>). +#: src/help.c:480 +msgid "[ Press to continue or for the previous page ] " +msgstr "[ Press to continue or for the previous page ] " + +#: src/intf.c:110 +#, c-format +msgid "%s: string has incorrect format: `%s'" +msgstr "%s: string has incorrect format: ‘%s’" + +#: src/intf.c:126 +#, c-format +msgid "%s: character has illegal width: `%lc'" +msgstr "%s: character has illegal width: ‘%lc’" + +#: src/intf.c:434 +#, c-format +msgid "terminal size is too small (%d x %d required)" +msgstr "terminal size is too small (%d x %d required)" + +#: src/intf.c:610 +msgid "Star Traders" +msgstr "Star Traders" + +#: src/intf.c:1262 +msgid "mkchstr_conv: NUL" +msgstr "mkchstr_conv: NUL" + +#: src/intf.c:1565 +#, c-format +msgid "mkchstr: `%s'" +msgstr "mkchstr: ‘%s’" + +#: src/intf.c:2022 src/intf.c:2067 +#, c-format +msgid "gettxline: illegal character in string: `%ls'" +msgstr "gettxline: illegal character in string: ‘%ls’" + +#. TRANSLATORS: The strings with msgctxt "input|Yes" and +#. "input|No" contain the keycodes used to determine whether a +#. user is answering "Yes" or "No" in response to some question. +#. Both upper and lower-case versions should be present. +#: src/intf.c:2939 +msgctxt "input|Yes" +msgid "Yy" +msgstr "Yy" + +#: src/intf.c:2941 +msgctxt "input|No" +msgid "Nn" +msgstr "Nn" + +#. TRANSLATORS: The strings "Yes" and "No" are printed as a +#. response to user input in answer to questions like "Are you +#. sure? [Y/N] " +#: src/intf.c:2992 +msgctxt "answer" +msgid "Yes" +msgstr "Yes" + +#: src/intf.c:2994 +msgctxt "answer" +msgid "No" +msgstr "No" + +#: src/utils.c:199 src/utils.c:220 +#, c-format +msgid "%s: " +msgstr "%s: " + +#: src/utils.c:225 +msgid ": " +msgstr ": " + +#: src/utils.c:238 +msgid "out of memory" +msgstr "out of memory" + +#: src/utils.c:571 +#, c-format +msgid "xmbstowcs: `%s'" +msgstr "xmbstowcs: ‘%s’" + +#: src/utils.c:611 +msgid "xwcrtomb: NUL" +msgstr "xwcrtomb: NUL" + +#: src/utils.c:616 +#, c-format +msgid "xwcrtomb: `%lc'" +msgstr "xwcrtomb: ‘%lc’" + +#: lib/getopt.c:547 lib/getopt.c:576 +#, c-format +msgid "%s: option '%s' is ambiguous; possibilities:" +msgstr "%s: option ‘%s’ is ambiguous; possibilities:" + +#: lib/getopt.c:624 lib/getopt.c:628 +#, c-format +msgid "%s: option '--%s' doesn't allow an argument\n" +msgstr "%s: option ‘--%s’ doesn’t allow an argument\n" + +#: lib/getopt.c:637 lib/getopt.c:642 +#, c-format +msgid "%s: option '%c%s' doesn't allow an argument\n" +msgstr "%s: option ‘%c%s’ doesn’t allow an argument\n" + +#: lib/getopt.c:685 lib/getopt.c:704 +#, c-format +msgid "%s: option '--%s' requires an argument\n" +msgstr "%s: option ‘--%s’ requires an argument\n" + +#: lib/getopt.c:742 lib/getopt.c:745 +#, c-format +msgid "%s: unrecognized option '--%s'\n" +msgstr "%s: unrecognized option ‘--%s’\n" + +#: lib/getopt.c:753 lib/getopt.c:756 +#, c-format +msgid "%s: unrecognized option '%c%s'\n" +msgstr "%s: unrecognized option ‘%c%s’\n" + +#: lib/getopt.c:805 lib/getopt.c:808 +#, c-format +msgid "%s: invalid option -- '%c'\n" +msgstr "%s: invalid option -- ‘%c’\n" + +#: lib/getopt.c:861 lib/getopt.c:878 lib/getopt.c:1088 lib/getopt.c:1106 +#, c-format +msgid "%s: option requires an argument -- '%c'\n" +msgstr "%s: option requires an argument -- ‘%c’\n" + +#: lib/getopt.c:934 lib/getopt.c:950 +#, c-format +msgid "%s: option '-W %s' is ambiguous\n" +msgstr "%s: option ‘-W %s’ is ambiguous\n" + +#: lib/getopt.c:974 lib/getopt.c:992 +#, c-format +msgid "%s: option '-W %s' doesn't allow an argument\n" +msgstr "%s: option ‘-W %s’ doesn’t allow an argument\n" + +#: lib/getopt.c:1013 lib/getopt.c:1031 +#, c-format +msgid "%s: option '-W %s' requires an argument\n" +msgstr "%s: option ‘-W %s’ requires an argument\n" From 735f7ce3d5e0addc7b6fc3f42f9eb5769f3f2fdd Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Sun, 28 Aug 2011 17:13:12 +1000 Subject: [PATCH 105/112] Remove more unwanted word-wrapping; propogate this to msgmerge(1) --- po/Makevars | 3 +++ po/en_AU.po | 6 ++---- po/en_CA.po | 6 ++---- po/en_GB.po | 6 ++---- po/en_US.po | 6 ++---- 5 files changed, 11 insertions(+), 16 deletions(-) diff --git a/po/Makevars b/po/Makevars index 8ef2d06..b330601 100644 --- a/po/Makevars +++ b/po/Makevars @@ -36,6 +36,9 @@ top_builddir = .. # These options get passed to xgettext XGETTEXT_OPTIONS = --from-code=UTF-8 --keyword=_ --keyword=N_ --width=132 +# These options get passed to msgmerge +MSGMERGE_OPTIONS = --width=132 + # Copyright holder that gets inserted into the header of the # $(DOMAIN).pot file. COPYRIGHT_HOLDER = John Zaitseff diff --git a/po/en_AU.po b/po/en_AU.po index dfb8fb9..29e5928 100644 --- a/po/en_AU.po +++ b/po/en_AU.po @@ -673,13 +673,11 @@ msgstr "" msgid "" "%ls has been declared bankrupt by the Interstellar Trading Bank.\n" "\n" -"^{The Bank has agreed to pay stock holders ^}%.2f%%^{ of the share value on " -"each share owned.^}" +"^{The Bank has agreed to pay stock holders ^}%.2f%%^{ of the share value on each share owned.^}" msgstr "" "%ls has been declared bankrupt by the Interstellar Trading Bank.\n" "\n" -"^{The Bank has agreed to pay stock holders ^}%.2f%%^{ of the share value on " -"each share owned.^}" +"^{The Bank has agreed to pay stock holders ^}%.2f%%^{ of the share value on each share owned.^}" #. TRANSLATORS: The label "Amount paid per share" #. refers to payment made by the Interstellar diff --git a/po/en_CA.po b/po/en_CA.po index 5b702ce..56aefee 100644 --- a/po/en_CA.po +++ b/po/en_CA.po @@ -673,13 +673,11 @@ msgstr "" msgid "" "%ls has been declared bankrupt by the Interstellar Trading Bank.\n" "\n" -"^{The Bank has agreed to pay stock holders ^}%.2f%%^{ of the share value on " -"each share owned.^}" +"^{The Bank has agreed to pay stock holders ^}%.2f%%^{ of the share value on each share owned.^}" msgstr "" "%ls has been declared bankrupt by the Interstellar Trading Bank.\n" "\n" -"^{The Bank has agreed to pay stock holders ^}%.2f%%^{ of the share value on " -"each share owned.^}" +"^{The Bank has agreed to pay stock holders ^}%.2f%%^{ of the share value on each share owned.^}" #. TRANSLATORS: The label "Amount paid per share" #. refers to payment made by the Interstellar diff --git a/po/en_GB.po b/po/en_GB.po index d056eb0..a748a00 100644 --- a/po/en_GB.po +++ b/po/en_GB.po @@ -673,13 +673,11 @@ msgstr "" msgid "" "%ls has been declared bankrupt by the Interstellar Trading Bank.\n" "\n" -"^{The Bank has agreed to pay stock holders ^}%.2f%%^{ of the share value on " -"each share owned.^}" +"^{The Bank has agreed to pay stock holders ^}%.2f%%^{ of the share value on each share owned.^}" msgstr "" "%ls has been declared bankrupt by the Interstellar Trading Bank.\n" "\n" -"^{The Bank has agreed to pay stock holders ^}%.2f%%^{ of the share value on " -"each share owned.^}" +"^{The Bank has agreed to pay stock holders ^}%.2f%%^{ of the share value on each share owned.^}" #. TRANSLATORS: The label "Amount paid per share" #. refers to payment made by the Interstellar diff --git a/po/en_US.po b/po/en_US.po index 24d0eaf..965a2e4 100644 --- a/po/en_US.po +++ b/po/en_US.po @@ -673,13 +673,11 @@ msgstr "" msgid "" "%ls has been declared bankrupt by the Interstellar Trading Bank.\n" "\n" -"^{The Bank has agreed to pay stock holders ^}%.2f%%^{ of the share value on " -"each share owned.^}" +"^{The Bank has agreed to pay stock holders ^}%.2f%%^{ of the share value on each share owned.^}" msgstr "" "%ls has been declared bankrupt by the Interstellar Trading Bank.\n" "\n" -"^{The Bank has agreed to pay stock holders ^}%.2f%%^{ of the share value on " -"each share owned.^}" +"^{The Bank has agreed to pay stock holders ^}%.2f%%^{ of the share value on each share owned.^}" #. TRANSLATORS: The label "Amount paid per share" #. refers to payment made by the Interstellar From e29b94f36ac662bbc83ce23d8ab67dd89f72f0bd Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Sun, 28 Aug 2011 17:17:10 +1000 Subject: [PATCH 106/112] List new features of Star Traders 7.2 The anticipated release date is tomorrow! --- NEWS | 26 +++++++++++++++++++------- doc/trader.6 | 20 ++++++++++---------- 2 files changed, 29 insertions(+), 17 deletions(-) diff --git a/NEWS b/NEWS index af59af1..e5868ab 100644 --- a/NEWS +++ b/NEWS @@ -15,11 +15,23 @@ consult the Subversion repository for "trader" on The ZAP Group web server at http://www.zap.org.au/services/svn/. -Version 7.2 (not yet released) ------------------------------- +Version 7.2 (29th August, 2011) +------------------------------- -@@@ To be written. Internationalisation, multibyte strings, terminal -resizing, signals, game file in UTF-8 +Star Traders has been internationalised! As part of this update, all +input and output routines have been rewritten to handle multibyte strings. +English (Australian, British, Canadian and US) translations have been +included. Translations for other languages (and corrections to existing +languages) are more than welcome! + +Game files are now stored in UTF-8 format (once decrypted!) and can be +loaded under any locale with automatic character set translation. This +does mean, however, that game files from versions 7.0 and 7.1 of Star +Traders will not load under this release. + +The program now better handles terminal resizing events (for versions of +Curses supporting such events). It also tries to restore the terminal +environment correctly when receiving a terminating signal. Version 7.1 (29th July, 2011) @@ -41,10 +53,10 @@ exercise for a number of software tools and libraries; the algorithms in the original Pascal and Visual Basic versions are reused for the game logic. -Note that the current version of Star Traders does NOT handle locales with +Note that versions 7.0 and 7.1 of Star Traders did NOT handle locales with multibyte character sequences (such as UTF-8) correctly. Each byte in a -multibyte sequence is treated as a separate character. Eight-bit locales -(such as US-ASCII, ISO8859-1, etc.) work correctly. +such a sequence was treated as a separate character. Eight-bit locales +(such as US-ASCII, ISO8859-1, etc.) worked correctly. Early history diff --git a/doc/trader.6 b/doc/trader.6 index a7beb9f..5a1a63c 100644 --- a/doc/trader.6 +++ b/doc/trader.6 @@ -41,7 +41,7 @@ .if \n[.g] .mso www.tmac .\" .\" ********************************************************************* -.TH TRADER 6 "22nd July, 2011" "Unix-like systems" +.TH TRADER 6 "29th August, 2011" "Unix-like systems" .SH NAME trader \- a game of interstellar trading .\" ********************************************************************* @@ -154,9 +154,11 @@ manual page for in-depth details). It requires a text console or window of at least 80\(mu24 in size. .TP .BR LANG ", " LC_ALL ", etc." -This version of Star Traders has rudimentary support for locales and will -use appropriate settings. In particular, numeric quantities will be -displayed using \fBLC_NUMERIC\fR and monetary quantities will use +This version of Star Traders has full support for locales and will use +appropriate settings. In particular, messages will be displayed using +\fBLC_MESSAGES\fR and \fBLANGUAGE\fR (if Star Traders has been translated +into that language). In addition, numeric quantities will be displayed +using \fBLC_NUMERIC\fR and monetary quantities will use \fBLC_MONETARY\fR. See the .BR locale (7) or @@ -172,10 +174,7 @@ inclusive. The game file is scrambled to prevent you or others from casually cheating! .\" ********************************************************************* .SH BUGS -The current version of Star Traders does \fInot\fR handle locales with -multibyte character sequences (such as UTF-8) correctly. Each byte in a -multibyte sequence is treated as a separate character. Eight-bit locales -(such as US-ASCII, ISO8859-1, etc.) work correctly. +None yet known... .\" ********************************************************************* .SH FEEDBACK Your comments, suggestions, corrections and enhancements are always @@ -262,8 +261,9 @@ on 15th September, 1995. Star Traders was then to languish until almost 16 years later... when the game was rewritten once again, this time in the C programming language. Version 7.0 was released on 25th July, 2011 for Unix-like operating -systems such as Linux. Now you, too, can run this small piece of -computing history! +systems such as Linux, with subsequent releases to add features and +correct bugs. Now you, too, can run this small piece of computing +history! .\" ********************************************************************* .SH "SEE ALSO" .URL http://www.zap.org.au/software/trader/ "Star Traders home page" From a6eb484a968d8cff653ad0e40951531d3d7815ce Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Mon, 29 Aug 2011 08:17:13 +1000 Subject: [PATCH 107/112] Make sure po/README is distributed --- po/Makevars | 3 +++ 1 file changed, 3 insertions(+) diff --git a/po/Makevars b/po/Makevars index b330601..28f3b22 100644 --- a/po/Makevars +++ b/po/Makevars @@ -50,3 +50,6 @@ MSGID_BUGS_ADDRESS = J.Zaitseff@zap.org.au # List of locale categories, beyond LC_MESSAGES, for which the message # catalogs shall be used. It is usually empty. EXTRA_LOCALE_CATEGORIES = + +# Additional files to distribute +DISTFILES += README From 1f3be161932046e904f2a7dee06aee006bef6345 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Mon, 29 Aug 2011 09:34:29 +1000 Subject: [PATCH 108/112] The "%lc" directive requires a wint_t type, not wchar_t This is essentially only to keep GCC quiet. --- src/intf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/intf.c b/src/intf.c index eb76e57..6a86b46 100644 --- a/src/intf.c +++ b/src/intf.c @@ -124,7 +124,7 @@ typedef struct txwin { c = (_var); \ if ((w = wcwidth(c)) < 1) { \ err_exit(_("%s: character has illegal width: `%lc'"), \ - __stringify(_err), c); \ + __stringify(_err), (wint_t) c); \ } \ \ memset(&mbstate, 0, sizeof(mbstate)); \ From 82ca16e11003fa8663d3799f0141456163a6892b Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Mon, 29 Aug 2011 10:34:27 +1000 Subject: [PATCH 109/112] Bug fix: wchar_t may be smaller than int On some platforms (eg, Cygwin), wchar_t is smaller than int, so type promotion requires an appropriate cast for va_arg. --- src/intf.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/intf.c b/src/intf.c index 6a86b46..9aa2fdf 100644 --- a/src/intf.c +++ b/src/intf.c @@ -1092,7 +1092,9 @@ int mkchstr_parse (const wchar_t *restrict format, break; case TYPE_WCHAR: - format_arg->a.a_wchar = va_arg(args, wchar_t); + format_arg->a.a_wchar = (wchar_t) (sizeof(wchar_t) < sizeof(int) ? + va_arg(args, int) : + va_arg(args, wchar_t)); break; case TYPE_INT: From e3733d8921998ae6ad2367ce81c0c5ebc5496544 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Mon, 29 Aug 2011 10:38:55 +1000 Subject: [PATCH 110/112] Define _XOPEN_SOURCE_EXTENDED, required by old versions of NcursesW The macro _XOPEN_SOURCE_EXTENDED is required by some old versions of NcursesW for wide-character function definitions. --- src/system.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/system.h b/src/system.h index b7f5143..42bae66 100644 --- a/src/system.h +++ b/src/system.h @@ -98,6 +98,8 @@ // X/Open-compatible Curses library +#define _XOPEN_SOURCE_EXTENDED 1 // Required by old versions of NcursesW + #if defined(HAVE_NCURSESW_CURSES_H) # include #elif defined(HAVE_NCURSESW_H) From 752eed74c52fc27609f17178f6914e4ed6e3a83a Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Mon, 29 Aug 2011 10:40:31 +1000 Subject: [PATCH 111/112] Cosmetic change: replace one space with one tab --- src/system.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/system.h b/src/system.h index 42bae66..e86c2f4 100644 --- a/src/system.h +++ b/src/system.h @@ -98,7 +98,7 @@ // X/Open-compatible Curses library -#define _XOPEN_SOURCE_EXTENDED 1 // Required by old versions of NcursesW +#define _XOPEN_SOURCE_EXTENDED 1 // Required by old versions of NcursesW #if defined(HAVE_NCURSESW_CURSES_H) # include From df3ccfd5838fdb9922581e3f656aa20b9d3b3120 Mon Sep 17 00:00:00 2001 From: John Zaitseff Date: Mon, 29 Aug 2011 10:51:19 +1000 Subject: [PATCH 112/112] Source line numbers have changed for all translations --- po/en_AU.po | 18 +++++++++--------- po/en_CA.po | 18 +++++++++--------- po/en_GB.po | 18 +++++++++--------- po/en_US.po | 18 +++++++++--------- 4 files changed, 36 insertions(+), 36 deletions(-) diff --git a/po/en_AU.po b/po/en_AU.po index 29e5928..678b878 100644 --- a/po/en_AU.po +++ b/po/en_AU.po @@ -14,7 +14,7 @@ msgid "" msgstr "" "Project-Id-Version: trader 7.2\n" "Report-Msgid-Bugs-To: J.Zaitseff@zap.org.au\n" -"POT-Creation-Date: 2011-08-28 14:55+1000\n" +"POT-Creation-Date: 2011-08-29 10:48+1000\n" "PO-Revision-Date: 2011-08-28 17:03+1000\n" "Last-Translator: John Zaitseff \n" "Language-Team: English (Australian)\n" @@ -1409,7 +1409,7 @@ msgstr "Page %d of %d" #. TRANSLATORS: The reason the user is not asked "Press any #. key to continue" is historical: many, many people used to #. ask "where is the key?" :-) -#: src/help.c:473 src/intf.c:3022 +#: src/help.c:473 src/intf.c:3024 msgid "[ Press to continue ] " msgstr "[ Press to continue ] " @@ -1442,16 +1442,16 @@ msgstr "terminal size is too small (%d x %d required)" msgid "Star Traders" msgstr "Star Traders" -#: src/intf.c:1262 +#: src/intf.c:1264 msgid "mkchstr_conv: NUL" msgstr "mkchstr_conv: NUL" -#: src/intf.c:1565 +#: src/intf.c:1567 #, c-format msgid "mkchstr: `%s'" msgstr "mkchstr: ‘%s’" -#: src/intf.c:2022 src/intf.c:2067 +#: src/intf.c:2024 src/intf.c:2069 #, c-format msgid "gettxline: illegal character in string: `%ls'" msgstr "gettxline: illegal character in string: ‘%ls’" @@ -1460,12 +1460,12 @@ msgstr "gettxline: illegal character in string: ‘%ls’" #. "input|No" contain the keycodes used to determine whether a #. user is answering "Yes" or "No" in response to some question. #. Both upper and lower-case versions should be present. -#: src/intf.c:2939 +#: src/intf.c:2941 msgctxt "input|Yes" msgid "Yy" msgstr "Yy" -#: src/intf.c:2941 +#: src/intf.c:2943 msgctxt "input|No" msgid "Nn" msgstr "Nn" @@ -1473,12 +1473,12 @@ msgstr "Nn" #. TRANSLATORS: The strings "Yes" and "No" are printed as a #. response to user input in answer to questions like "Are you #. sure? [Y/N] " -#: src/intf.c:2992 +#: src/intf.c:2994 msgctxt "answer" msgid "Yes" msgstr "Yes" -#: src/intf.c:2994 +#: src/intf.c:2996 msgctxt "answer" msgid "No" msgstr "No" diff --git a/po/en_CA.po b/po/en_CA.po index 56aefee..8487d55 100644 --- a/po/en_CA.po +++ b/po/en_CA.po @@ -14,7 +14,7 @@ msgid "" msgstr "" "Project-Id-Version: trader 7.2\n" "Report-Msgid-Bugs-To: J.Zaitseff@zap.org.au\n" -"POT-Creation-Date: 2011-08-28 14:55+1000\n" +"POT-Creation-Date: 2011-08-29 10:48+1000\n" "PO-Revision-Date: 2011-08-28 17:01+1000\n" "Last-Translator: John Zaitseff \n" "Language-Team: English (Canadian)\n" @@ -1409,7 +1409,7 @@ msgstr "Page %d of %d" #. TRANSLATORS: The reason the user is not asked "Press any #. key to continue" is historical: many, many people used to #. ask "where is the key?" :-) -#: src/help.c:473 src/intf.c:3022 +#: src/help.c:473 src/intf.c:3024 msgid "[ Press to continue ] " msgstr "[ Press to continue ] " @@ -1442,16 +1442,16 @@ msgstr "terminal size is too small (%d x %d required)" msgid "Star Traders" msgstr "Star Traders" -#: src/intf.c:1262 +#: src/intf.c:1264 msgid "mkchstr_conv: NUL" msgstr "mkchstr_conv: NUL" -#: src/intf.c:1565 +#: src/intf.c:1567 #, c-format msgid "mkchstr: `%s'" msgstr "mkchstr: ‘%s’" -#: src/intf.c:2022 src/intf.c:2067 +#: src/intf.c:2024 src/intf.c:2069 #, c-format msgid "gettxline: illegal character in string: `%ls'" msgstr "gettxline: illegal character in string: ‘%ls’" @@ -1460,12 +1460,12 @@ msgstr "gettxline: illegal character in string: ‘%ls’" #. "input|No" contain the keycodes used to determine whether a #. user is answering "Yes" or "No" in response to some question. #. Both upper and lower-case versions should be present. -#: src/intf.c:2939 +#: src/intf.c:2941 msgctxt "input|Yes" msgid "Yy" msgstr "Yy" -#: src/intf.c:2941 +#: src/intf.c:2943 msgctxt "input|No" msgid "Nn" msgstr "Nn" @@ -1473,12 +1473,12 @@ msgstr "Nn" #. TRANSLATORS: The strings "Yes" and "No" are printed as a #. response to user input in answer to questions like "Are you #. sure? [Y/N] " -#: src/intf.c:2992 +#: src/intf.c:2994 msgctxt "answer" msgid "Yes" msgstr "Yes" -#: src/intf.c:2994 +#: src/intf.c:2996 msgctxt "answer" msgid "No" msgstr "No" diff --git a/po/en_GB.po b/po/en_GB.po index a748a00..083868b 100644 --- a/po/en_GB.po +++ b/po/en_GB.po @@ -14,7 +14,7 @@ msgid "" msgstr "" "Project-Id-Version: trader 7.2\n" "Report-Msgid-Bugs-To: J.Zaitseff@zap.org.au\n" -"POT-Creation-Date: 2011-08-28 14:55+1000\n" +"POT-Creation-Date: 2011-08-29 10:48+1000\n" "PO-Revision-Date: 2011-08-28 17:03+1000\n" "Last-Translator: John Zaitseff \n" "Language-Team: English (British)\n" @@ -1409,7 +1409,7 @@ msgstr "Page %d of %d" #. TRANSLATORS: The reason the user is not asked "Press any #. key to continue" is historical: many, many people used to #. ask "where is the key?" :-) -#: src/help.c:473 src/intf.c:3022 +#: src/help.c:473 src/intf.c:3024 msgid "[ Press to continue ] " msgstr "[ Press to continue ] " @@ -1442,16 +1442,16 @@ msgstr "terminal size is too small (%d x %d required)" msgid "Star Traders" msgstr "Star Traders" -#: src/intf.c:1262 +#: src/intf.c:1264 msgid "mkchstr_conv: NUL" msgstr "mkchstr_conv: NUL" -#: src/intf.c:1565 +#: src/intf.c:1567 #, c-format msgid "mkchstr: `%s'" msgstr "mkchstr: ‘%s’" -#: src/intf.c:2022 src/intf.c:2067 +#: src/intf.c:2024 src/intf.c:2069 #, c-format msgid "gettxline: illegal character in string: `%ls'" msgstr "gettxline: illegal character in string: ‘%ls’" @@ -1460,12 +1460,12 @@ msgstr "gettxline: illegal character in string: ‘%ls’" #. "input|No" contain the keycodes used to determine whether a #. user is answering "Yes" or "No" in response to some question. #. Both upper and lower-case versions should be present. -#: src/intf.c:2939 +#: src/intf.c:2941 msgctxt "input|Yes" msgid "Yy" msgstr "Yy" -#: src/intf.c:2941 +#: src/intf.c:2943 msgctxt "input|No" msgid "Nn" msgstr "Nn" @@ -1473,12 +1473,12 @@ msgstr "Nn" #. TRANSLATORS: The strings "Yes" and "No" are printed as a #. response to user input in answer to questions like "Are you #. sure? [Y/N] " -#: src/intf.c:2992 +#: src/intf.c:2994 msgctxt "answer" msgid "Yes" msgstr "Yes" -#: src/intf.c:2994 +#: src/intf.c:2996 msgctxt "answer" msgid "No" msgstr "No" diff --git a/po/en_US.po b/po/en_US.po index 965a2e4..f9e65f1 100644 --- a/po/en_US.po +++ b/po/en_US.po @@ -14,7 +14,7 @@ msgid "" msgstr "" "Project-Id-Version: trader 7.2\n" "Report-Msgid-Bugs-To: J.Zaitseff@zap.org.au\n" -"POT-Creation-Date: 2011-08-28 14:55+1000\n" +"POT-Creation-Date: 2011-08-29 10:48+1000\n" "PO-Revision-Date: 2011-08-28 16:50+1000\n" "Last-Translator: John Zaitseff \n" "Language-Team: English\n" @@ -1409,7 +1409,7 @@ msgstr "Page %d of %d" #. TRANSLATORS: The reason the user is not asked "Press any #. key to continue" is historical: many, many people used to #. ask "where is the key?" :-) -#: src/help.c:473 src/intf.c:3022 +#: src/help.c:473 src/intf.c:3024 msgid "[ Press to continue ] " msgstr "[ Press to continue ] " @@ -1442,16 +1442,16 @@ msgstr "terminal size is too small (%d x %d required)" msgid "Star Traders" msgstr "Star Traders" -#: src/intf.c:1262 +#: src/intf.c:1264 msgid "mkchstr_conv: NUL" msgstr "mkchstr_conv: NUL" -#: src/intf.c:1565 +#: src/intf.c:1567 #, c-format msgid "mkchstr: `%s'" msgstr "mkchstr: ‘%s’" -#: src/intf.c:2022 src/intf.c:2067 +#: src/intf.c:2024 src/intf.c:2069 #, c-format msgid "gettxline: illegal character in string: `%ls'" msgstr "gettxline: illegal character in string: ‘%ls’" @@ -1460,12 +1460,12 @@ msgstr "gettxline: illegal character in string: ‘%ls’" #. "input|No" contain the keycodes used to determine whether a #. user is answering "Yes" or "No" in response to some question. #. Both upper and lower-case versions should be present. -#: src/intf.c:2939 +#: src/intf.c:2941 msgctxt "input|Yes" msgid "Yy" msgstr "Yy" -#: src/intf.c:2941 +#: src/intf.c:2943 msgctxt "input|No" msgid "Nn" msgstr "Nn" @@ -1473,12 +1473,12 @@ msgstr "Nn" #. TRANSLATORS: The strings "Yes" and "No" are printed as a #. response to user input in answer to questions like "Are you #. sure? [Y/N] " -#: src/intf.c:2992 +#: src/intf.c:2994 msgctxt "answer" msgid "Yes" msgstr "Yes" -#: src/intf.c:2994 +#: src/intf.c:2996 msgctxt "answer" msgid "No" msgstr "No"