quarry-0.2.0/0000755000175000017500000000000010530402567011500 5ustar bartbartquarry-0.2.0/build/0000755000175000017500000000000010530402567012577 5ustar bartbartquarry-0.2.0/build/config.guess0000755000175000017500000012513310132560461015120 0ustar bartbart#! /bin/sh # Attempt to guess a canonical system name. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002, 2003 Free Software Foundation, Inc. timestamp='2004-06-11' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # 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, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Per Bothner . # Please send patches to . Submit a context # diff and a properly formatted ChangeLog entry. # # This script attempts to guess a canonical system name similar to # config.sub. If it succeeds, it prints the system name on stdout, and # exits with 0. Otherwise, it exits with 1. # # The plan is that this can be called by configure scripts if you # don't specify an explicit build system type. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit 0 ;; --version | -v ) echo "$version" ; exit 0 ;; --help | --h* | -h ) echo "$usage"; exit 0 ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; * ) break ;; esac done if test $# != 0; then echo "$me: too many arguments$help" >&2 exit 1 fi trap 'exit 1' 1 2 15 # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a # headache to deal with in a portable fashion. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. # Portable tmp directory creation inspired by the Autoconf team. set_cc_for_build=' trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; : ${TMPDIR=/tmp} ; { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; dummy=$tmp/dummy ; tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; case $CC_FOR_BUILD,$HOST_CC,$CC in ,,) echo "int x;" > $dummy.c ; for c in cc gcc c89 c99 ; do if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found ; fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; esac ;' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) if (test -f /.attbin/uname) >/dev/null 2>&1 ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown # Note: order is significant - the case branches are not exclusive. case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ /usr/sbin/$sysctl 2>/dev/null || echo unknown)` case "${UNAME_MACHINE_ARCH}" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently, or will in the future. case "${UNAME_MACHINE_ARCH}" in arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep __ELF__ >/dev/null then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? os=netbsd else os=netbsdelf fi ;; *) os=netbsd ;; esac # The OS release # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. case "${UNAME_VERSION}" in Debian*) release='-gnu' ;; *) release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "${machine}-${os}${release}" exit 0 ;; amd64:OpenBSD:*:*) echo x86_64-unknown-openbsd${UNAME_RELEASE} exit 0 ;; amiga:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; arc:OpenBSD:*:*) echo mipsel-unknown-openbsd${UNAME_RELEASE} exit 0 ;; cats:OpenBSD:*:*) echo arm-unknown-openbsd${UNAME_RELEASE} exit 0 ;; hp300:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; luna88k:OpenBSD:*:*) echo m88k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; mac68k:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; macppc:OpenBSD:*:*) echo powerpc-unknown-openbsd${UNAME_RELEASE} exit 0 ;; mvme68k:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; mvme88k:OpenBSD:*:*) echo m88k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; mvmeppc:OpenBSD:*:*) echo powerpc-unknown-openbsd${UNAME_RELEASE} exit 0 ;; pmax:OpenBSD:*:*) echo mipsel-unknown-openbsd${UNAME_RELEASE} exit 0 ;; sgi:OpenBSD:*:*) echo mipseb-unknown-openbsd${UNAME_RELEASE} exit 0 ;; sun3:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; wgrisc:OpenBSD:*:*) echo mipsel-unknown-openbsd${UNAME_RELEASE} exit 0 ;; *:OpenBSD:*:*) echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE} exit 0 ;; *:ekkoBSD:*:*) echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} exit 0 ;; macppc:MirBSD:*:*) echo powerppc-unknown-mirbsd${UNAME_RELEASE} exit 0 ;; *:MirBSD:*:*) echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} exit 0 ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` ;; *5.*) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` ;; esac # According to Compaq, /usr/sbin/psrinfo has been available on # OSF/1 and Tru64 systems produced since 1995. I hope that # covers most systems running today. This code pipes the CPU # types through head -n 1, so we only detect the type of CPU 0. ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case "$ALPHA_CPU_TYPE" in "EV4 (21064)") UNAME_MACHINE="alpha" ;; "EV4.5 (21064)") UNAME_MACHINE="alpha" ;; "LCA4 (21066/21068)") UNAME_MACHINE="alpha" ;; "EV5 (21164)") UNAME_MACHINE="alphaev5" ;; "EV5.6 (21164A)") UNAME_MACHINE="alphaev56" ;; "EV5.6 (21164PC)") UNAME_MACHINE="alphapca56" ;; "EV5.7 (21164PC)") UNAME_MACHINE="alphapca57" ;; "EV6 (21264)") UNAME_MACHINE="alphaev6" ;; "EV6.7 (21264A)") UNAME_MACHINE="alphaev67" ;; "EV6.8CB (21264C)") UNAME_MACHINE="alphaev68" ;; "EV6.8AL (21264B)") UNAME_MACHINE="alphaev68" ;; "EV6.8CX (21264D)") UNAME_MACHINE="alphaev68" ;; "EV6.9A (21264/EV69A)") UNAME_MACHINE="alphaev69" ;; "EV7 (21364)") UNAME_MACHINE="alphaev7" ;; "EV7.9 (21364A)") UNAME_MACHINE="alphaev79" ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` exit 0 ;; Alpha*:OpenVMS:*:*) echo alpha-hp-vms exit 0 ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # Should we change UNAME_MACHINE based on the output of uname instead # of the specific Alpha model? echo alpha-pc-interix exit 0 ;; 21064:Windows_NT:50:3) echo alpha-dec-winnt3.5 exit 0 ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit 0;; *:[Aa]miga[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-amigaos exit 0 ;; *:[Mm]orph[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-morphos exit 0 ;; *:OS/390:*:*) echo i370-ibm-openedition exit 0 ;; *:OS400:*:*) echo powerpc-ibm-os400 exit 0 ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} exit 0;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp exit 0;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "`(/bin/universe) 2>/dev/null`" = att ; then echo pyramid-pyramid-sysv3 else echo pyramid-pyramid-bsd fi exit 0 ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit 0 ;; DRS?6000:unix:4.0:6*) echo sparc-icl-nx6 exit 0 ;; DRS?6000:UNIX_SV:4.2*:7*) case `/usr/bin/uname -p` in sparc) echo sparc-icl-nx7 && exit 0 ;; esac ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; i86pc:SunOS:5.*:*) echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in Series*|S4*) UNAME_RELEASE=`uname -v` ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` exit 0 ;; sun3*:SunOS:*:*) echo m68k-sun-sunos${UNAME_RELEASE} exit 0 ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) echo m68k-sun-sunos${UNAME_RELEASE} ;; sun4) echo sparc-sun-sunos${UNAME_RELEASE} ;; esac exit 0 ;; aushp:SunOS:*:*) echo sparc-auspex-sunos${UNAME_RELEASE} exit 0 ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor # > m68000). The system name ranges from "MiNT" over "FreeMiNT" # to the lowercase version "mint" (or "freemint"). Finally # the system name "TOS" denotes a system which is actually not # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit 0 ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit 0 ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit 0 ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) echo m68k-milan-mint${UNAME_RELEASE} exit 0 ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) echo m68k-hades-mint${UNAME_RELEASE} exit 0 ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-unknown-mint${UNAME_RELEASE} exit 0 ;; m68k:machten:*:*) echo m68k-apple-machten${UNAME_RELEASE} exit 0 ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} exit 0 ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit 0 ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix${UNAME_RELEASE} exit 0 ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix${UNAME_RELEASE} exit 0 ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix${UNAME_RELEASE} exit 0 ;; mips:*:*:UMIPS | mips:*:*:RISCos) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { #else int main (argc, argv) int argc; char *argv[]; { #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c \ && $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ && exit 0 echo mips-mips-riscos${UNAME_RELEASE} exit 0 ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax exit 0 ;; Motorola:*:4.3:PL8-*) echo powerpc-harris-powermax exit 0 ;; Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) echo powerpc-harris-powermax exit 0 ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit 0 ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 exit 0 ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 exit 0 ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 exit 0 ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] then if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ [ ${TARGET_BINARY_INTERFACE}x = x ] then echo m88k-dg-dgux${UNAME_RELEASE} else echo m88k-dg-dguxbcs${UNAME_RELEASE} fi else echo i586-dg-dgux${UNAME_RELEASE} fi exit 0 ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit 0 ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 exit 0 ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 exit 0 ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd exit 0 ;; *:IRIX*:*:*) echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` exit 0 ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix exit 0 ;; ia64:AIX:*:*) if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} exit 0 ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include main() { if (!__power_pc()) exit(1); puts("powerpc-ibm-aix3.2.5"); exit(0); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0 echo rs6000-ibm-aix3.2.5 elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi exit 0 ;; *:AIX:*:[45]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${IBM_ARCH}-ibm-aix${IBM_REV} exit 0 ;; *:AIX:*:*) echo rs6000-ibm-aix exit 0 ;; ibmrt:4.4BSD:*|romp-ibm:BSD:*) echo romp-ibm-bsd4.4 exit 0 ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to exit 0 ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx exit 0 ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 exit 0 ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd exit 0 ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 exit 0 ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` case "${UNAME_MACHINE}" in 9000/31? ) HP_ARCH=m68000 ;; 9000/[34]?? ) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` case "${sc_cpu_version}" in 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case "${sc_kernel_bits}" in 32) HP_ARCH="hppa2.0n" ;; 64) HP_ARCH="hppa2.0w" ;; '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 esac ;; esac fi if [ "${HP_ARCH}" = "" ]; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #define _HPUX_SOURCE #include #include int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); #endif long cpu = sysconf (_SC_CPU_VERSION); switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; default: puts ("hppa2.0"); break; } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; #endif default: puts ("hppa1.0"); break; } exit (0); } EOF (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac if [ ${HP_ARCH} = "hppa2.0w" ] then # avoid double evaluation of $set_cc_for_build test -n "$CC_FOR_BUILD" || eval $set_cc_for_build if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E -) | grep __LP64__ >/dev/null then HP_ARCH="hppa2.0w" else HP_ARCH="hppa64" fi fi echo ${HP_ARCH}-hp-hpux${HPUX_REV} exit 0 ;; ia64:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` echo ia64-hp-hpux${HPUX_REV} exit 0 ;; 3050*:HI-UX:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include int main () { long cpu = sysconf (_SC_CPU_VERSION); /* The order matters, because CPU_IS_HP_MC68K erroneously returns true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct results, however. */ if (CPU_IS_PA_RISC (cpu)) { switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; default: puts ("hppa-hitachi-hiuxwe2"); break; } } else if (CPU_IS_HP_MC68K (cpu)) puts ("m68k-hitachi-hiuxwe2"); else puts ("unknown-hitachi-hiuxwe2"); exit (0); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0 echo unknown-hitachi-hiuxwe2 exit 0 ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) echo hppa1.1-hp-bsd exit 0 ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd exit 0 ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit 0 ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) echo hppa1.1-hp-osf exit 0 ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf exit 0 ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then echo ${UNAME_MACHINE}-unknown-osf1mk else echo ${UNAME_MACHINE}-unknown-osf1 fi exit 0 ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites exit 0 ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd exit 0 ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit 0 ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd exit 0 ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd exit 0 ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd exit 0 ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*[A-Z]90:*:*:*) echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*TS:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; *:UNICOS/mp:*:*) echo nv1-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit 0 ;; 5000:UNIX_System_V:4.*:*) FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit 0 ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit 0 ;; sparc*:BSD/OS:*:*) echo sparc-unknown-bsdi${UNAME_RELEASE} exit 0 ;; *:BSD/OS:*:*) echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit 0 ;; *:FreeBSD:*:*) # Determine whether the default compiler uses glibc. eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include #if __GLIBC__ >= 2 LIBC=gnu #else LIBC= #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` # GNU/KFreeBSD systems have a "k" prefix to indicate we are using # FreeBSD's kernel, but not the complete OS. case ${LIBC} in gnu) kernel_only='k' ;; esac echo ${UNAME_MACHINE}-unknown-${kernel_only}freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`${LIBC:+-$LIBC} exit 0 ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin exit 0 ;; i*:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit 0 ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit 0 ;; x86:Interix*:[34]*) echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//' exit 0 ;; [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) echo i${UNAME_MACHINE}-pc-mks exit 0 ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we # UNAME_MACHINE based on the output of uname instead of i386? echo i586-pc-interix exit 0 ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin exit 0 ;; p*:CYGWIN*:*) echo powerpcle-unknown-cygwin exit 0 ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; *:GNU:*:*) # the GNU system echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit 0 ;; *:GNU/*:*:*) # other systems with GNU libc and userland echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu exit 0 ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit 0 ;; arm*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; cris:Linux:*:*) echo cris-axis-linux-gnu exit 0 ;; ia64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; m32r*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; m68*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; mips:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef mips #undef mipsel #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=mipsel #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=mips #else CPU= #endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0 ;; mips64:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef mips64 #undef mips64el #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=mips64el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=mips64 #else CPU= #endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0 ;; ppc:Linux:*:*) echo powerpc-unknown-linux-gnu exit 0 ;; ppc64:Linux:*:*) echo powerpc64-unknown-linux-gnu exit 0 ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; PCA57) UNAME_MACHINE=alphapca56 ;; EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} exit 0 ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in PA7*) echo hppa1.1-unknown-linux-gnu ;; PA8*) echo hppa2.0-unknown-linux-gnu ;; *) echo hppa-unknown-linux-gnu ;; esac exit 0 ;; parisc64:Linux:*:* | hppa64:Linux:*:*) echo hppa64-unknown-linux-gnu exit 0 ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux exit 0 ;; sh64*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; sh*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; sparc:Linux:*:* | sparc64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; x86_64:Linux:*:*) echo x86_64-unknown-linux-gnu exit 0 ;; i*86:Linux:*:*) # The BFD linker knows what the default object file format is, so # first see if it will tell us. cd to the root directory to prevent # problems with other programs or directories called `ld' in the path. # Set LC_ALL=C to ensure ld outputs messages in English. ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ | sed -ne '/supported targets:/!d s/[ ][ ]*/ /g s/.*supported targets: *// s/ .*// p'` case "$ld_supported_targets" in elf32-i386) TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" ;; a.out-i386-linux) echo "${UNAME_MACHINE}-pc-linux-gnuaout" exit 0 ;; coff-i386) echo "${UNAME_MACHINE}-pc-linux-gnucoff" exit 0 ;; "") # Either a pre-BFD a.out linker (linux-gnuoldld) or # one that does not give us useful --help. echo "${UNAME_MACHINE}-pc-linux-gnuoldld" exit 0 ;; esac # Determine whether the default compiler is a.out or elf eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include #ifdef __ELF__ # ifdef __GLIBC__ # if __GLIBC__ >= 2 LIBC=gnu # else LIBC=gnulibc1 # endif # else LIBC=gnulibc1 # endif #else #ifdef __INTEL_COMPILER LIBC=gnu #else LIBC=gnuaout #endif #endif #ifdef __dietlibc__ LIBC=dietlibc #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0 test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0 ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. echo i386-sequent-sysv4 exit 0 ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} exit 0 ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. echo ${UNAME_MACHINE}-pc-os2-emx exit 0 ;; i*86:XTS-300:*:STOP) echo ${UNAME_MACHINE}-unknown-stop exit 0 ;; i*86:atheos:*:*) echo ${UNAME_MACHINE}-unknown-atheos exit 0 ;; i*86:syllable:*:*) echo ${UNAME_MACHINE}-pc-syllable exit 0 ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) echo i386-unknown-lynxos${UNAME_RELEASE} exit 0 ;; i*86:*DOS:*:*) echo ${UNAME_MACHINE}-pc-msdosdjgpp exit 0 ;; i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} else echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} fi exit 0 ;; i*86:*:5:[78]*) case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} exit 0 ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else echo ${UNAME_MACHINE}-pc-sysv32 fi exit 0 ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i386. echo i386-pc-msdosdjgpp exit 0 ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit 0 ;; paragon:*:*:*) echo i860-intel-osf1 exit 0 ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 fi exit 0 ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv exit 0 ;; mc68k:UNIX:SYSTEM5:3.51m) echo m68k-convergent-sysv exit 0 ;; M680?0:D-NIX:5.3:*) echo m68k-diab-dnix exit 0 ;; M68*:*:R3V[5678]*:*) test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && echo i486-ncr-sysv4.3${OS_REL} && exit 0 /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && echo i486-ncr-sysv4 && exit 0 ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} exit 0 ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit 0 ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos${UNAME_RELEASE} exit 0 ;; rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} exit 0 ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) echo powerpc-unknown-lynxos${UNAME_RELEASE} exit 0 ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv${UNAME_RELEASE} exit 0 ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 exit 0 ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 exit 0 ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` echo ${UNAME_MACHINE}-sni-sysv4 else echo ns32k-sni-sysv fi exit 0 ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says echo i586-unisys-sysv4 exit 0 ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 exit 0 ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 exit 0 ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit 0 ;; mc68*:A/UX:*:*) echo m68k-apple-aux${UNAME_RELEASE} exit 0 ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit 0 ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then echo mips-nec-sysv${UNAME_RELEASE} else echo mips-unknown-sysv${UNAME_RELEASE} fi exit 0 ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit 0 ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos exit 0 ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit 0 ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} exit 0 ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux${UNAME_RELEASE} exit 0 ;; SX-6:SUPER-UX:*:*) echo sx6-nec-superux${UNAME_RELEASE} exit 0 ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit 0 ;; *:Rhapsody:*:*) echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} exit 0 ;; *:Darwin:*:*) case `uname -p` in *86) UNAME_PROCESSOR=i686 ;; powerpc) UNAME_PROCESSOR=powerpc ;; esac echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} exit 0 ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = "x86"; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} exit 0 ;; *:QNX:*:4*) echo i386-pc-qnx exit 0 ;; NSR-?:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} exit 0 ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux exit 0 ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv exit 0 ;; DS/*:UNIX_System_V:*:*) echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} exit 0 ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. if test "$cputype" = "386"; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi echo ${UNAME_MACHINE}-unknown-plan9 exit 0 ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 exit 0 ;; *:TENEX:*:*) echo pdp10-unknown-tenex exit 0 ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 exit 0 ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 exit 0 ;; *:TOPS-20:*:*) echo pdp10-unknown-tops20 exit 0 ;; *:ITS:*:*) echo pdp10-unknown-its exit 0 ;; SEI:*:*:SEIUX) echo mips-sei-seiux${UNAME_RELEASE} exit 0 ;; *:DragonFly:*:*) echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit 0 ;; esac #echo '(No uname command or uname output not recognized.)' 1>&2 #echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 eval $set_cc_for_build cat >$dummy.c < # include #endif main () { #if defined (sony) #if defined (MIPSEB) /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, I don't know.... */ printf ("mips-sony-bsd\n"); exit (0); #else #include printf ("m68k-sony-newsos%s\n", #ifdef NEWSOS4 "4" #else "" #endif ); exit (0); #endif #endif #if defined (__arm) && defined (__acorn) && defined (__unix) printf ("arm-acorn-riscix"); exit (0); #endif #if defined (hp300) && !defined (hpux) printf ("m68k-hp-bsd\n"); exit (0); #endif #if defined (NeXT) #if !defined (__ARCHITECTURE__) #define __ARCHITECTURE__ "m68k" #endif int version; version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; if (version < 4) printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); else printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); exit (0); #endif #if defined (MULTIMAX) || defined (n16) #if defined (UMAXV) printf ("ns32k-encore-sysv\n"); exit (0); #else #if defined (CMU) printf ("ns32k-encore-mach\n"); exit (0); #else printf ("ns32k-encore-bsd\n"); exit (0); #endif #endif #endif #if defined (__386BSD__) printf ("i386-pc-bsd\n"); exit (0); #endif #if defined (sequent) #if defined (i386) printf ("i386-sequent-dynix\n"); exit (0); #endif #if defined (ns32000) printf ("ns32k-sequent-dynix\n"); exit (0); #endif #endif #if defined (_SEQUENT_) struct utsname un; uname(&un); if (strncmp(un.version, "V2", 2) == 0) { printf ("i386-sequent-ptx2\n"); exit (0); } if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ printf ("i386-sequent-ptx1\n"); exit (0); } printf ("i386-sequent-ptx\n"); exit (0); #endif #if defined (vax) # if !defined (ultrix) # include # if defined (BSD) # if BSD == 43 printf ("vax-dec-bsd4.3\n"); exit (0); # else # if BSD == 199006 printf ("vax-dec-bsd4.3reno\n"); exit (0); # else printf ("vax-dec-bsd\n"); exit (0); # endif # endif # else printf ("vax-dec-bsd\n"); exit (0); # endif # else printf ("vax-dec-ultrix\n"); exit (0); # endif #endif #if defined (alliant) && defined (i860) printf ("i860-alliant-bsd\n"); exit (0); #endif exit (1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && $dummy && exit 0 # Apollos put the system type in the environment. test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; } # Convex versions that predate uname can use getsysinfo(1) if [ -x /usr/convex/getsysinfo ] then case `getsysinfo -f cpu_type` in c1*) echo c1-convex-bsd exit 0 ;; c2*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit 0 ;; c34*) echo c34-convex-bsd exit 0 ;; c38*) echo c38-convex-bsd exit 0 ;; c4*) echo c4-convex-bsd exit 0 ;; esac fi cat >&2 < in order to provide the needed information to handle your system. config.guess timestamp = $timestamp uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` /bin/uname -X = `(/bin/uname -X) 2>/dev/null` hostinfo = `(hostinfo) 2>/dev/null` /bin/universe = `(/bin/universe) 2>/dev/null` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` /bin/arch = `(/bin/arch) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` UNAME_MACHINE = ${UNAME_MACHINE} UNAME_RELEASE = ${UNAME_RELEASE} UNAME_SYSTEM = ${UNAME_SYSTEM} UNAME_VERSION = ${UNAME_VERSION} EOF exit 1 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: quarry-0.2.0/build/config.rpath0000755000175000017500000003521310132560461015107 0ustar bartbart#! /bin/sh # Output a system dependent set of variables, describing how to set the # run time search path of shared libraries in an executable. # # Copyright 1996-2003 Free Software Foundation, Inc. # Taken from GNU libtool, 2001 # Originally by Gordon Matzigkeit , 1996 # # 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 2 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, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # # The first argument passed to this file is the canonical host specification, # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # The environment variables CC, GCC, LDFLAGS, LD, with_gnu_ld # should be set by the caller. # # The set of defined variables is at the end of this script. # Known limitations: # - On IRIX 6.5 with CC="cc", the run time search patch must not be longer # than 256 bytes, otherwise the compiler driver will dump core. The only # known workaround is to choose shorter directory names for the build # directory and/or the installation directory. # All known linkers require a `.a' archive for static linking (except M$VC, # which needs '.lib'). libext=a shrext=.so host="$1" host_cpu=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` host_vendor=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` host_os=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` # Code taken from libtool.m4's AC_LIBTOOL_PROG_COMPILER_PIC. wl= if test "$GCC" = yes; then wl='-Wl,' else case "$host_os" in aix*) wl='-Wl,' ;; mingw* | pw32* | os2*) ;; hpux9* | hpux10* | hpux11*) wl='-Wl,' ;; irix5* | irix6* | nonstopux*) wl='-Wl,' ;; newsos6) ;; linux*) case $CC in icc|ecc) wl='-Wl,' ;; ccc) wl='-Wl,' ;; esac ;; osf3* | osf4* | osf5*) wl='-Wl,' ;; sco3.2v5*) ;; solaris*) wl='-Wl,' ;; sunos4*) wl='-Qoption ld ' ;; sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) wl='-Wl,' ;; sysv4*MP*) ;; uts4*) ;; esac fi # Code taken from libtool.m4's AC_LIBTOOL_PROG_LD_SHLIBS. hardcode_libdir_flag_spec= hardcode_libdir_separator= hardcode_direct=no hardcode_minus_L=no case "$host_os" in cygwin* | mingw* | pw32*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; openbsd*) with_gnu_ld=no ;; esac ld_shlibs=yes if test "$with_gnu_ld" = yes; then case "$host_os" in aix3* | aix4* | aix5*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then ld_shlibs=no fi ;; amigaos*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes # Samuel A. Falvo II reports # that the semantics of dynamic libraries on AmigaOS, at least up # to version 4, is to share data among multiple programs linked # with the same dynamic library. Since this doesn't match the # behavior of shared libraries on other platforms, we can use # them. ld_shlibs=no ;; beos*) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then : else ld_shlibs=no fi ;; cygwin* | mingw* | pw32*) # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then : else ld_shlibs=no fi ;; netbsd*) ;; solaris* | sysv5*) if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then ld_shlibs=no elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then : else ld_shlibs=no fi ;; sunos4*) hardcode_direct=yes ;; *) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then : else ld_shlibs=no fi ;; esac if test "$ld_shlibs" = yes; then # Unlike libtool, we use -rpath here, not --rpath, since the documented # option of GNU ld is called -rpath, not --rpath. hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' fi else case "$host_os" in aix3*) # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L=yes if test "$GCC" = yes; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct=unsupported fi ;; aix4* | aix5*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[23]|aix4.[23].*|aix5*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done esac fi hardcode_direct=yes hardcode_libdir_separator=':' if test "$GCC" = yes; then case $host_os in aix4.[012]|aix4.[012].*) collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && \ strings "$collect2name" | grep resolve_lib_name >/dev/null then # We have reworked collect2 hardcode_direct=yes else # We have old collect2 hardcode_direct=unsupported hardcode_minus_L=yes hardcode_libdir_flag_spec='-L$libdir' hardcode_libdir_separator= fi esac fi # Begin _LT_AC_SYS_LIBPATH_AIX. echo 'int main () { return 0; }' > conftest.c ${CC} ${LDFLAGS} conftest.c -o conftest aix_libpath=`dump -H conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` fi if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib" fi rm -f conftest.c conftest # End _LT_AC_SYS_LIBPATH_AIX. if test "$aix_use_runtimelinking" = yes; then hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' else hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" fi fi ;; amigaos*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes # see comment about different semantics on the GNU ld section ld_shlibs=no ;; bsdi4*) ;; cygwin* | mingw* | pw32*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec=' ' libext=lib ;; darwin* | rhapsody*) if $CC -v 2>&1 | grep 'Apple' >/dev/null ; then hardcode_direct=no fi ;; dgux*) hardcode_libdir_flag_spec='-L$libdir' ;; freebsd1*) ld_shlibs=no ;; freebsd2.2*) hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes ;; freebsd2*) hardcode_direct=yes hardcode_minus_L=yes ;; freebsd*) hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes ;; hpux9*) hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes ;; hpux10* | hpux11*) if test "$with_gnu_ld" = no; then case "$host_cpu" in hppa*64*) hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=no ;; ia64*) hardcode_libdir_flag_spec='-L$libdir' hardcode_direct=no # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes ;; *) hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; netbsd*) hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes ;; newsos6) hardcode_direct=yes hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; openbsd*) hardcode_direct=yes if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then hardcode_libdir_flag_spec='${wl}-rpath,$libdir' else case "$host_os" in openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) hardcode_libdir_flag_spec='-R$libdir' ;; *) hardcode_libdir_flag_spec='${wl}-rpath,$libdir' ;; esac fi ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; osf3*) hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; osf4* | osf5*) if test "$GCC" = yes; then hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' else # Both cc and cxx compiler support -rpath directly hardcode_libdir_flag_spec='-rpath $libdir' fi hardcode_libdir_separator=: ;; sco3.2v5*) ;; solaris*) hardcode_libdir_flag_spec='-R$libdir' ;; sunos4*) hardcode_libdir_flag_spec='-L$libdir' hardcode_direct=yes hardcode_minus_L=yes ;; sysv4) case $host_vendor in sni) hardcode_direct=yes # is this really true??? ;; siemens) hardcode_direct=no ;; motorola) hardcode_direct=no #Motorola manual says yes, but my tests say they lie ;; esac ;; sysv4.3*) ;; sysv4*MP*) if test -d /usr/nec; then ld_shlibs=yes fi ;; sysv4.2uw2*) hardcode_direct=yes hardcode_minus_L=no ;; sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[78]* | unixware7*) ;; sysv5*) hardcode_libdir_flag_spec= ;; uts4*) hardcode_libdir_flag_spec='-L$libdir' ;; *) ld_shlibs=no ;; esac fi # Check dynamic linker characteristics # Code taken from libtool.m4's AC_LIBTOOL_SYS_DYNAMIC_LINKER. libname_spec='lib$name' case "$host_os" in aix3*) ;; aix4* | aix5*) ;; amigaos*) ;; beos*) ;; bsdi4*) ;; cygwin* | mingw* | pw32*) shrext=.dll ;; darwin* | rhapsody*) shrext=.dylib ;; dgux*) ;; freebsd1*) ;; freebsd*) ;; gnu*) ;; hpux9* | hpux10* | hpux11*) case "$host_cpu" in ia64*) shrext=.so ;; hppa*64*) shrext=.sl ;; *) shrext=.sl ;; esac ;; irix5* | irix6* | nonstopux*) case "$host_os" in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= ;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 ;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 ;; *) libsuff= shlibsuff= ;; esac ;; esac ;; linux*oldld* | linux*aout* | linux*coff*) ;; linux*) ;; netbsd*) ;; newsos6) ;; nto-qnx) ;; openbsd*) ;; os2*) libname_spec='$name' shrext=.dll ;; osf3* | osf4* | osf5*) ;; sco3.2v5*) ;; solaris*) ;; sunos4*) ;; sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) ;; sysv4*MP*) ;; uts4*) ;; esac sed_quote_subst='s/\(["`$\\]\)/\\\1/g' escaped_wl=`echo "X$wl" | sed -e 's/^X//' -e "$sed_quote_subst"` shlibext=`echo "$shrext" | sed -e 's,^\.,,'` escaped_hardcode_libdir_flag_spec=`echo "X$hardcode_libdir_flag_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` sed -e 's/^\([a-zA-Z0-9_]*\)=/acl_cv_\1=/' <. Submit a context # diff and a properly formatted ChangeLog entry. # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS $0 [OPTION] ALIAS Canonicalize a configuration name. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.sub ($timestamp) Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit 0 ;; --version | -v ) echo "$version" ; exit 0 ;; --help | --h* | -h ) echo "$usage"; exit 0 ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" exit 1 ;; *local*) # First pass through any local machine types. echo $1 exit 0;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | linux-dietlibc | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | \ kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] then os=`echo $1 | sed 's/.*-/-/'` else os=; fi ;; esac ### Let's recognize common machines as not being operating systems so ### that things like config.sub decstation-3100 work. We also ### recognize some manufacturers as not being operating systems, so we ### can provide default operating systems below. case $os in -sun*os*) # Prevent following clause from handling this invalid input. ;; -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ -apple | -axis) os= basic_machine=$1 ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 ;; -scout) ;; -wrs) os=-vxworks basic_machine=$1 ;; -chorusos*) os=-chorusos basic_machine=$1 ;; -chorusrdb) os=-chorusrdb basic_machine=$1 ;; -hiux*) os=-hiuxwe2 ;; -sco5) os=-sco3.2v5 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -udk*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -lynx*) os=-lynxos ;; -ptx*) basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` ;; -windowsnt*) os=`echo $os | sed -e 's/windowsnt/winnt/'` ;; -psos*) os=-psos ;; -mint | -mint[0-9]*) basic_machine=m68k-atari os=-mint ;; esac # Decode aliases for certain CPU-COMPANY combinations. case $basic_machine in # Recognize the basic CPU types without company name. # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | am33_2.0 \ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ | c4x | clipper \ | d10v | d30v | dlx | dsp16xx \ | fr30 | frv \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ | m32r | m32rle | m68000 | m68k | m88k | mcore \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ | mips64vr | mips64vrel \ | mips64orion | mips64orionel \ | mips64vr4100 | mips64vr4100el \ | mips64vr4300 | mips64vr4300el \ | mips64vr5000 | mips64vr5000el \ | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ | mipsisa64 | mipsisa64el \ | mipsisa64r2 | mipsisa64r2el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ | msp430 \ | ns16k | ns32k \ | openrisc | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ | pyramid \ | sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv8 | sparcv9 | sparcv9b \ | strongarm \ | tahoe | thumb | tic4x | tic80 | tron \ | v850 | v850e \ | we32k \ | x86 | xscale | xstormy16 | xtensa \ | z8k) basic_machine=$basic_machine-unknown ;; m6811 | m68hc11 | m6812 | m68hc12) # Motorola 68HC11/12. basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. i*86 | x86_64) basic_machine=$basic_machine-pc ;; # Object if more than one company name word. *-*-*) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* \ | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ | clipper-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | elxsi-* \ | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* | iq2000-* \ | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | mcore-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ | mips64vr-* | mips64vrel-* \ | mips64orion-* | mips64orionel-* \ | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* \ | mips64vr5000-* | mips64vr5000el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa32r2-* | mipsisa32r2el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64r2-* | mipsisa64r2el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipstx39-* | mipstx39el-* \ | msp430-* \ | none-* | np1-* | nv1-* | ns16k-* | ns32k-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ | pyramid-* \ | romp-* | rs6000-* \ | sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \ | sparcv8-* | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ | tahoe-* | thumb-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tron-* \ | v850-* | v850e-* | vax-* \ | we32k-* \ | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \ | xtensa-* \ | ymp-* \ | z8k-*) ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) basic_machine=i386-unknown os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) basic_machine=m68000-att ;; 3b*) basic_machine=we32k-att ;; a29khif) basic_machine=a29k-amd os=-udi ;; abacus) basic_machine=abacus-unknown ;; adobe68k) basic_machine=m68010-adobe os=-scout ;; alliant | fx80) basic_machine=fx80-alliant ;; altos | altos3068) basic_machine=m68k-altos ;; am29k) basic_machine=a29k-none os=-bsd ;; amd64) basic_machine=x86_64-pc ;; amd64-*) basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; amdahl) basic_machine=580-amdahl os=-sysv ;; amiga | amiga-*) basic_machine=m68k-unknown ;; amigaos | amigados) basic_machine=m68k-unknown os=-amigaos ;; amigaunix | amix) basic_machine=m68k-unknown os=-sysv4 ;; apollo68) basic_machine=m68k-apollo os=-sysv ;; apollo68bsd) basic_machine=m68k-apollo os=-bsd ;; aux) basic_machine=m68k-apple os=-aux ;; balance) basic_machine=ns32k-sequent os=-dynix ;; c90) basic_machine=c90-cray os=-unicos ;; convex-c1) basic_machine=c1-convex os=-bsd ;; convex-c2) basic_machine=c2-convex os=-bsd ;; convex-c32) basic_machine=c32-convex os=-bsd ;; convex-c34) basic_machine=c34-convex os=-bsd ;; convex-c38) basic_machine=c38-convex os=-bsd ;; cray | j90) basic_machine=j90-cray os=-unicos ;; cr16c) basic_machine=cr16c-unknown os=-elf ;; crds | unos) basic_machine=m68k-crds ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; crx) basic_machine=crx-unknown os=-elf ;; da30 | da30-*) basic_machine=m68k-da30 ;; decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; decsystem10* | dec10*) basic_machine=pdp10-dec os=-tops10 ;; decsystem20* | dec20*) basic_machine=pdp10-dec os=-tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) basic_machine=m68k-motorola ;; delta88) basic_machine=m88k-motorola os=-sysv3 ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx ;; dpx2* | dpx2*-bull) basic_machine=m68k-bull os=-sysv3 ;; ebmon29k) basic_machine=a29k-amd os=-ebmon ;; elxsi) basic_machine=elxsi-elxsi os=-bsd ;; encore | umax | mmax) basic_machine=ns32k-encore ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson os=-ose ;; fx2800) basic_machine=i860-alliant ;; genix) basic_machine=ns32k-ns ;; gmicro) basic_machine=tron-gmicro os=-sysv ;; go32) basic_machine=i386-pc os=-go32 ;; h3050r* | hiux*) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; h8300hms) basic_machine=h8300-hitachi os=-hms ;; h8300xray) basic_machine=h8300-hitachi os=-xray ;; h8500hms) basic_machine=h8500-hitachi os=-hms ;; harris) basic_machine=m88k-harris os=-sysv3 ;; hp300-*) basic_machine=m68k-hp ;; hp300bsd) basic_machine=m68k-hp os=-bsd ;; hp300hpux) basic_machine=m68k-hp os=-hpux ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) basic_machine=m68000-hp ;; hp9k3[2-9][0-9]) basic_machine=m68k-hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) basic_machine=hppa1.1-hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) basic_machine=hppa1.1-hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; hppa-next) os=-nextstep3 ;; hppaosf) basic_machine=hppa1.1-hp os=-osf ;; hppro) basic_machine=hppa1.1-hp os=-proelf ;; i370-ibm* | ibm*) basic_machine=i370-ibm ;; # I'm not sure what "Sysv32" means. Should this be sysv3.2? i*86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; i386-vsta | vsta) basic_machine=i386-unknown os=-vsta ;; iris | iris4d) basic_machine=mips-sgi case $os in -irix*) ;; *) os=-irix4 ;; esac ;; isi68 | isi) basic_machine=m68k-isi os=-sysv ;; m88k-omron*) basic_machine=m88k-omron ;; magnum | m3230) basic_machine=mips-mips os=-sysv ;; merlin) basic_machine=ns32k-utek os=-sysv ;; mingw32) basic_machine=i386-pc os=-mingw32 ;; miniframe) basic_machine=m68000-convergent ;; *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) basic_machine=m68k-atari os=-mint ;; mips3*-*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` ;; mips3*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown ;; mmix*) basic_machine=mmix-knuth os=-mmixware ;; monitor) basic_machine=m68k-rom68k os=-coff ;; morphos) basic_machine=powerpc-unknown os=-morphos ;; msdos) basic_machine=i386-pc os=-msdos ;; mvs) basic_machine=i370-ibm os=-mvs ;; ncr3000) basic_machine=i486-ncr os=-sysv4 ;; netbsd386) basic_machine=i386-unknown os=-netbsd ;; netwinder) basic_machine=armv4l-rebel os=-linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony os=-newsos ;; news1000) basic_machine=m68030-sony os=-newsos ;; news-3600 | risc-news) basic_machine=mips-sony os=-newsos ;; necv70) basic_machine=v70-nec os=-sysv ;; next | m*-next ) basic_machine=m68k-next case $os in -nextstep* ) ;; -ns2*) os=-nextstep2 ;; *) os=-nextstep3 ;; esac ;; nh3000) basic_machine=m68k-harris os=-cxux ;; nh[45]000) basic_machine=m88k-harris os=-cxux ;; nindy960) basic_machine=i960-intel os=-nindy ;; mon960) basic_machine=i960-intel os=-mon960 ;; nonstopux) basic_machine=mips-compaq os=-nonstopux ;; np1) basic_machine=np1-gould ;; nv1) basic_machine=nv1-cray os=-unicosmp ;; nsr-tandem) basic_machine=nsr-tandem ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf ;; or32 | or32-*) basic_machine=or32-unknown os=-coff ;; os400) basic_machine=powerpc-ibm os=-os400 ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose ;; os68k) basic_machine=m68k-none os=-os68k ;; pa-hitachi) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; paragon) basic_machine=i860-intel os=-osf ;; pbd) basic_machine=sparc-tti ;; pbb) basic_machine=m68k-tti ;; pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; pentiumpro | p6 | 6x86 | athlon | athlon_*) basic_machine=i686-pc ;; pentiumii | pentium2 | pentiumiii | pentium3) basic_machine=i686-pc ;; pentium4) basic_machine=i786-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium4-*) basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; ppc) basic_machine=powerpc-unknown ;; ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle | ppc-le | powerpc-little) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little | ppc64-le | powerpc64-little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm ;; pw32) basic_machine=i586-unknown os=-pw32 ;; rom68k) basic_machine=m68k-rom68k os=-coff ;; rm[46]00) basic_machine=mips-siemens ;; rtpc | rtpc-*) basic_machine=romp-ibm ;; s390 | s390-*) basic_machine=s390-ibm ;; s390x | s390x-*) basic_machine=s390x-ibm ;; sa29200) basic_machine=a29k-amd os=-udi ;; sb1) basic_machine=mipsisa64sb1-unknown ;; sb1el) basic_machine=mipsisa64sb1el-unknown ;; sei) basic_machine=mips-sei os=-seiux ;; sequent) basic_machine=i386-sequent ;; sh) basic_machine=sh-hitachi os=-hms ;; sh64) basic_machine=sh64-unknown ;; sparclite-wrs | simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; sps7) basic_machine=m68k-bull os=-sysv2 ;; spur) basic_machine=spur-unknown ;; st2000) basic_machine=m68k-tandem ;; stratus) basic_machine=i860-stratus os=-sysv4 ;; sun2) basic_machine=m68000-sun ;; sun2os3) basic_machine=m68000-sun os=-sunos3 ;; sun2os4) basic_machine=m68000-sun os=-sunos4 ;; sun3os3) basic_machine=m68k-sun os=-sunos3 ;; sun3os4) basic_machine=m68k-sun os=-sunos4 ;; sun4os3) basic_machine=sparc-sun os=-sunos3 ;; sun4os4) basic_machine=sparc-sun os=-sunos4 ;; sun4sol2) basic_machine=sparc-sun os=-solaris2 ;; sun3 | sun3-*) basic_machine=m68k-sun ;; sun4) basic_machine=sparc-sun ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; sv1) basic_machine=sv1-cray os=-unicos ;; symmetry) basic_machine=i386-sequent os=-dynix ;; t3e) basic_machine=alphaev5-cray os=-unicos ;; t90) basic_machine=t90-cray os=-unicos ;; tic54x | c54x*) basic_machine=tic54x-unknown os=-coff ;; tic55x | c55x*) basic_machine=tic55x-unknown os=-coff ;; tic6x | c6x*) basic_machine=tic6x-unknown os=-coff ;; tx39) basic_machine=mipstx39-unknown ;; tx39el) basic_machine=mipstx39el-unknown ;; toad1) basic_machine=pdp10-xkl os=-tops20 ;; tower | tower-32) basic_machine=m68k-ncr ;; tpf) basic_machine=s390x-ibm os=-tpf ;; udi29k) basic_machine=a29k-amd os=-udi ;; ultra3) basic_machine=a29k-nyu os=-sym1 ;; v810 | necv810) basic_machine=v810-nec os=-none ;; vaxv) basic_machine=vax-dec os=-sysv ;; vms) basic_machine=vax-dec os=-vms ;; vpp*|vx|vx-*) basic_machine=f301-fujitsu ;; vxworks960) basic_machine=i960-wrs os=-vxworks ;; vxworks68) basic_machine=m68k-wrs os=-vxworks ;; vxworks29k) basic_machine=a29k-wrs os=-vxworks ;; w65*) basic_machine=w65-wdc os=-none ;; w89k-*) basic_machine=hppa1.1-winbond os=-proelf ;; xps | xps100) basic_machine=xps100-honeywell ;; ymp) basic_machine=ymp-cray os=-unicos ;; z8k-*-coff) basic_machine=z8k-unknown os=-sim ;; none) basic_machine=none-none os=-none ;; # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) basic_machine=hppa1.1-winbond ;; op50n) basic_machine=hppa1.1-oki ;; op60c) basic_machine=hppa1.1-oki ;; romp) basic_machine=romp-ibm ;; rs6000) basic_machine=rs6000-ibm ;; vax) basic_machine=vax-dec ;; pdp10) # there are many clones, so DEC is not a safe bet basic_machine=pdp10-unknown ;; pdp11) basic_machine=pdp11-dec ;; we32k) basic_machine=we32k-att ;; sh3 | sh4 | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; sh64) basic_machine=sh64-unknown ;; sparc | sparcv8 | sparcv9 | sparcv9b) basic_machine=sparc-sun ;; cydra) basic_machine=cydra-cydrome ;; orion) basic_machine=orion-highlevel ;; orion105) basic_machine=clipper-highlevel ;; mac | mpw | mac-mpw) basic_machine=m68k-apple ;; pmac | pmac-mpw) basic_machine=powerpc-apple ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; *) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` ;; *-commodore*) basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if [ x"$os" != x"" ] then case $os in # First match some system type aliases # that might get confused with valid system types. # -solaris* is a basic system type, with this one exception. -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; -solaris) os=-solaris2 ;; -svr4*) os=-sysv4 ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # First accept the basic system types. # The portable systems comes first. # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | -aos* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* | -openbsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* \ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -mingw32* | -linux-gnu* | -linux-uclibc* | -uxpv* | -beos* | -mpeix* | -udk* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) case $basic_machine in x86-* | i*86-*) ;; *) os=-nto$os ;; esac ;; -nto-qnx*) ;; -nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* | -beos* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; -linux-dietlibc) os=-linux-dietlibc ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) os=`echo $os | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) os=`echo $os | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition ;; -os400*) os=-os400 ;; -wince*) os=-wince ;; -osfrose*) os=-osfrose ;; -osf*) os=-osf ;; -utek*) os=-bsd ;; -dynix*) os=-bsd ;; -acis*) os=-aos ;; -atheos*) os=-atheos ;; -syllable*) os=-syllable ;; -386bsd) os=-bsd ;; -ctix* | -uts*) os=-sysv ;; -nova*) os=-rtmk-nova ;; -ns2 ) os=-nextstep2 ;; -nsk*) os=-nsk ;; # Preserve the version number of sinix5. -sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; -sinix*) os=-sysv4 ;; -tpf*) os=-tpf ;; -triton*) os=-sysv3 ;; -oss*) os=-sysv3 ;; -svr4) os=-sysv4 ;; -svr3) os=-sysv3 ;; -sysvr4) os=-sysv4 ;; # This must come after -sysvr4. -sysv*) ;; -ose*) os=-ose ;; -es1800*) os=-ose ;; -xenix) os=-xenix ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; -aros*) os=-aros ;; -kaos*) os=-kaos ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 exit 1 ;; esac else # Here we handle the default operating systems that come with various machines. # The value should be what the vendor currently ships out the door with their # machine or put another way, the most popular os provided with the machine. # Note that if you're going to try to match "-MANUFACTURER" here (say, # "-sun"), then you have to tell the case statement up towards the top # that MANUFACTURER isn't an operating system. Otherwise, code above # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. case $basic_machine in *-acorn) os=-riscix1.2 ;; arm*-rebel) os=-linux ;; arm*-semi) os=-aout ;; c4x-* | tic4x-*) os=-coff ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; pdp11-*) os=-none ;; *-dec | vax-*) os=-ultrix4.2 ;; m68*-apollo) os=-domain ;; i386-sun) os=-sunos4.0.2 ;; m68000-sun) os=-sunos3 # This also exists in the configure program, but was not the # default. # os=-sunos4 ;; m68*-cisco) os=-aout ;; mips*-cisco) os=-elf ;; mips*-*) os=-elf ;; or32-*) os=-coff ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; sparc-* | *-sun) os=-sunos4.1.1 ;; *-be) os=-beos ;; *-ibm) os=-aix ;; *-wec) os=-proelf ;; *-winbond) os=-proelf ;; *-oki) os=-proelf ;; *-hp) os=-hpux ;; *-hitachi) os=-hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) os=-sysv ;; *-cbm) os=-amigaos ;; *-dg) os=-dgux ;; *-dolphin) os=-sysv3 ;; m68k-ccur) os=-rtu ;; m88k-omron*) os=-luna ;; *-next ) os=-nextstep ;; *-sequent) os=-ptx ;; *-crds) os=-unos ;; *-ns) os=-genix ;; i370-*) os=-mvs ;; *-next) os=-nextstep3 ;; *-gould) os=-sysv ;; *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; *-sgi) os=-irix ;; *-siemens) os=-sysv4 ;; *-masscomp) os=-rtu ;; f30[01]-fujitsu | f700-fujitsu) os=-uxpv ;; *-rom68k) os=-coff ;; *-*bug) os=-coff ;; *-apple) os=-macos ;; *-atari*) os=-mint ;; *) os=-none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. vendor=unknown case $basic_machine in *-unknown) case $os in -riscix*) vendor=acorn ;; -sunos*) vendor=sun ;; -aix*) vendor=ibm ;; -beos*) vendor=be ;; -hpux*) vendor=hp ;; -mpeix*) vendor=hp ;; -hiux*) vendor=hitachi ;; -unos*) vendor=crds ;; -dgux*) vendor=dg ;; -luna*) vendor=omron ;; -genix*) vendor=ns ;; -mvs* | -opened*) vendor=ibm ;; -os400*) vendor=ibm ;; -ptx*) vendor=sequent ;; -tpf*) vendor=ibm ;; -vxsim* | -vxworks* | -windiss*) vendor=wrs ;; -aux*) vendor=apple ;; -hms*) vendor=hitachi ;; -mpw* | -macos*) vendor=apple ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) vendor=atari ;; -vos*) vendor=stratus ;; esac basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac echo $basic_machine$os exit 0 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: quarry-0.2.0/build/depcomp0000755000175000017500000002752510132560461014163 0ustar bartbart#! /bin/sh # depcomp - compile a program generating dependencies as side-effects # Copyright 1999, 2000 Free Software Foundation, Inc. # 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 2, 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, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA # 02111-1307, USA. # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Alexandre Oliva . if test -z "$depmode" || test -z "$source" || test -z "$object"; then echo "depcomp: Variables source, object and depmode must be set" 1>&2 exit 1 fi # `libtool' can also be set to `yes' or `no'. depfile=${depfile-`echo "$object" | sed 's,\([^/]*\)$,.deps/\1,;s/\.\([^.]*\)$/.P\1/'`} tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} rm -f "$tmpdepfile" # Some modes work just like other modes, but use different flags. We # parameterize here, but still list the modes in the big case below, # to make depend.m4 easier to write. Note that we *cannot* use a case # here, because this file can only contain one case statement. if test "$depmode" = hp; then # HP compiler uses -M and no extra arg. gccflag=-M depmode=gcc fi if test "$depmode" = dashXmstdout; then # This is just like dashmstdout with a different argument. dashmflag=-xM depmode=dashmstdout fi case "$depmode" in gcc3) ## gcc 3 implements dependency tracking that does exactly what ## we want. Yay! Note: for some reason libtool 1.4 doesn't like ## it if -MD -MP comes after the -MF stuff. Hmm. "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi mv "$tmpdepfile" "$depfile" ;; gcc) ## There are various ways to get dependency output from gcc. Here's ## why we pick this rather obscure method: ## - Don't want to use -MD because we'd like the dependencies to end ## up in a subdir. Having to rename by hand is ugly. ## (We might end up doing this anyway to support other compilers.) ## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like ## -MM, not -M (despite what the docs say). ## - Using -M directly means running the compiler twice (even worse ## than renaming). if test -z "$gccflag"; then gccflag=-MD, fi "$@" -Wp,"$gccflag$tmpdepfile" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ## The second -e expression handles DOS-style file names with drive letters. sed -e 's/^[^:]*: / /' \ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" ## This next piece of magic avoids the `deleted header file' problem. ## The problem is that when a header file which appears in a .P file ## is deleted, the dependency causes make to die (because there is ## typically no way to rebuild the header). We avoid this by adding ## dummy dependencies for each header file. Too bad gcc doesn't do ## this for us directly. tr ' ' ' ' < "$tmpdepfile" | ## Some versions of gcc put a space before the `:'. On the theory ## that the space means something, we add a space to the output as ## well. ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; sgi) if test "$libtool" = yes; then "$@" "-Wp,-MDupdate,$tmpdepfile" else "$@" -MDupdate "$tmpdepfile" fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files echo "$object : \\" > "$depfile" # Clip off the initial element (the dependent). Don't try to be # clever and replace this with sed code, as IRIX sed won't handle # lines with more than a fixed number of characters (4096 in # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; # the IRIX cc adds comments like `#:fec' to the end of the # dependency line. tr ' ' ' ' < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ tr ' ' ' ' >> $depfile echo >> $depfile # The second pass generates a dummy entry for each header file. tr ' ' ' ' < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ >> $depfile else # The sourcefile does not contain any dependencies, so just # store a dummy comment line, to avoid errors with the Makefile # "include basename.Plo" scheme. echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; aix) # The C for AIX Compiler uses -M and outputs the dependencies # in a .u file. This file always lives in the current directory. # Also, the AIX compiler puts `$object:' at the start of each line; # $object doesn't have directory information. stripped=`echo "$object" | sed -e 's,^.*/,,' -e 's/\(.*\)\..*$/\1/'` tmpdepfile="$stripped.u" outname="$stripped.o" if test "$libtool" = yes; then "$@" -Wc,-M else "$@" -M fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi if test -f "$tmpdepfile"; then # Each line is of the form `foo.o: dependent.h'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile" sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile" else # The sourcefile does not contain any dependencies, so just # store a dummy comment line, to avoid errors with the Makefile # "include basename.Plo" scheme. echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; tru64) # The Tru64 AIX compiler uses -MD to generate dependencies as a side # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put # dependencies in `foo.d' instead, so we check for that too. # Subdirectories are respected. tmpdepfile1="$object.d" tmpdepfile2=`echo "$object" | sed -e 's/.o$/.d/'` if test "$libtool" = yes; then "$@" -Wc,-MD else "$@" -MD fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile1" "$tmpdepfile2" exit $stat fi if test -f "$tmpdepfile1"; then tmpdepfile="$tmpdepfile1" else tmpdepfile="$tmpdepfile2" fi if test -f "$tmpdepfile"; then sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" # That's a space and a tab in the []. sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" else echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; #nosideeffect) # This comment above is used by automake to tell side-effect # dependency tracking mechanisms from slower ones. dashmstdout) # Important note: in order to support this mode, a compiler *must* # always write the proprocessed file to stdout, regardless of -o, # because we must use -o when running libtool. test -z "$dashmflag" && dashmflag=-M ( IFS=" " case " $* " in *" --mode=compile "*) # this is libtool, let us make it quiet for arg do # cycle over the arguments case "$arg" in "--mode=compile") # insert --quiet before "--mode=compile" set fnord "$@" --quiet shift # fnord ;; esac set fnord "$@" "$arg" shift # fnord shift # "$arg" done ;; esac "$@" $dashmflag | sed 's:^[^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" ) & proc=$! "$@" stat=$? wait "$proc" if test "$stat" != 0; then exit $stat; fi rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" tr ' ' ' ' < "$tmpdepfile" | \ ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; dashXmstdout) # This case only exists to satisfy depend.m4. It is never actually # run, as this mode is specially recognized in the preamble. exit 1 ;; makedepend) # X makedepend ( shift cleared=no for arg in "$@"; do case $cleared in no) set ""; shift cleared=yes esac case "$arg" in -D*|-I*) set fnord "$@" "$arg"; shift;; -*) ;; *) set fnord "$@" "$arg"; shift;; esac done obj_suffix="`echo $object | sed 's/^.*\././'`" touch "$tmpdepfile" ${MAKEDEPEND-makedepend} 2>/dev/null -o"$obj_suffix" -f"$tmpdepfile" "$@" ) & proc=$! "$@" stat=$? wait "$proc" if test "$stat" != 0; then exit $stat; fi rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" tail +3 "$tmpdepfile" | tr ' ' ' ' | \ ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" "$tmpdepfile".bak ;; cpp) # Important note: in order to support this mode, a compiler *must* # always write the proprocessed file to stdout, regardless of -o, # because we must use -o when running libtool. ( IFS=" " case " $* " in *" --mode=compile "*) for arg do # cycle over the arguments case $arg in "--mode=compile") # insert --quiet before "--mode=compile" set fnord "$@" --quiet shift # fnord ;; esac set fnord "$@" "$arg" shift # fnord shift # "$arg" done ;; esac "$@" -E | sed -n '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | sed '$ s: \\$::' > "$tmpdepfile" ) & proc=$! "$@" stat=$? wait "$proc" if test "$stat" != 0; then exit $stat; fi rm -f "$depfile" echo "$object : \\" > "$depfile" cat < "$tmpdepfile" >> "$depfile" sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; msvisualcpp) # Important note: in order to support this mode, a compiler *must* # always write the proprocessed file to stdout, regardless of -o, # because we must use -o when running libtool. ( IFS=" " case " $* " in *" --mode=compile "*) for arg do # cycle over the arguments case $arg in "--mode=compile") # insert --quiet before "--mode=compile" set fnord "$@" --quiet shift # fnord ;; esac set fnord "$@" "$arg" shift # fnord shift # "$arg" done ;; esac "$@" -E | sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile" ) & proc=$! "$@" stat=$? wait "$proc" if test "$stat" != 0; then exit $stat; fi rm -f "$depfile" echo "$object : \\" > "$depfile" . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" echo " " >> "$depfile" . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile" rm -f "$tmpdepfile" ;; none) exec "$@" ;; *) echo "Unknown depmode $depmode" 1>&2 exit 1 ;; esac exit 0 quarry-0.2.0/build/install-sh0000755000175000017500000001273610132560461014610 0ustar bartbart#!/bin/sh # # install - install a program, script, or datafile # This comes from X11R5 (mit/util/scripts/install.sh). # # Copyright 1991 by the Massachusetts Institute of Technology # # Permission to use, copy, modify, distribute, and sell this software and its # documentation for any purpose is hereby granted without fee, provided that # the above copyright notice appear in all copies and that both that # copyright notice and this permission notice appear in supporting # documentation, and that the name of M.I.T. not be used in advertising or # publicity pertaining to distribution of the software without specific, # written prior permission. M.I.T. makes no representations about the # suitability of this software for any purpose. It is provided "as is" # without express or implied warranty. # # Calling this script install-sh is preferred over install.sh, to prevent # `make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. It can only install one file at a time, a restriction # shared with many OS's install programs. # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit="${DOITPROG-}" # put in absolute paths if you don't have them in your path; or use env. vars. mvprog="${MVPROG-mv}" cpprog="${CPPROG-cp}" chmodprog="${CHMODPROG-chmod}" chownprog="${CHOWNPROG-chown}" chgrpprog="${CHGRPPROG-chgrp}" stripprog="${STRIPPROG-strip}" rmprog="${RMPROG-rm}" mkdirprog="${MKDIRPROG-mkdir}" transformbasename="" transform_arg="" instcmd="$mvprog" chmodcmd="$chmodprog 0755" chowncmd="" chgrpcmd="" stripcmd="" rmcmd="$rmprog -f" mvcmd="$mvprog" src="" dst="" dir_arg="" while [ x"$1" != x ]; do case $1 in -c) instcmd="$cpprog" shift continue;; -d) dir_arg=true shift continue;; -m) chmodcmd="$chmodprog $2" shift shift continue;; -o) chowncmd="$chownprog $2" shift shift continue;; -g) chgrpcmd="$chgrpprog $2" shift shift continue;; -s) stripcmd="$stripprog" shift continue;; -t=*) transformarg=`echo $1 | sed 's/-t=//'` shift continue;; -b=*) transformbasename=`echo $1 | sed 's/-b=//'` shift continue;; *) if [ x"$src" = x ] then src=$1 else # this colon is to work around a 386BSD /bin/sh bug : dst=$1 fi shift continue;; esac done if [ x"$src" = x ] then echo "install: no input file specified" exit 1 else true fi if [ x"$dir_arg" != x ]; then dst=$src src="" if [ -d $dst ]; then instcmd=: chmodcmd="" else instcmd=mkdir fi else # Waiting for this to be detected by the "$instcmd $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if [ -f $src -o -d $src ] then true else echo "install: $src does not exist" exit 1 fi if [ x"$dst" = x ] then echo "install: no destination specified" exit 1 else true fi # If destination is a directory, append the input filename; if your system # does not like double slashes in filenames, you may need to add some logic if [ -d $dst ] then dst="$dst"/`basename $src` else true fi fi ## this sed command emulates the dirname command dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` # Make sure that the destination directory exists. # this part is taken from Noah Friedman's mkinstalldirs script # Skip lots of stat calls in the usual case. if [ ! -d "$dstdir" ]; then defaultIFS=' ' IFS="${IFS-${defaultIFS}}" oIFS="${IFS}" # Some sh's can't handle IFS=/ for some reason. IFS='%' set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` IFS="${oIFS}" pathcomp='' while [ $# -ne 0 ] ; do pathcomp="${pathcomp}${1}" shift if [ ! -d "${pathcomp}" ] ; then $mkdirprog "${pathcomp}" else true fi pathcomp="${pathcomp}/" done fi if [ x"$dir_arg" != x ] then $doit $instcmd $dst && if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi else # If we're going to rename the final executable, determine the name now. if [ x"$transformarg" = x ] then dstfile=`basename $dst` else dstfile=`basename $dst $transformbasename | sed $transformarg`$transformbasename fi # don't allow the sed command to completely eliminate the filename if [ x"$dstfile" = x ] then dstfile=`basename $dst` else true fi # Make a temp file name in the proper directory. dsttmp=$dstdir/#inst.$$# # Move or copy the file name to the temp name $doit $instcmd $src $dsttmp && trap "rm -f ${dsttmp}" 0 && # and set any options; do chmod last to preserve setuid bits # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $instcmd $src $dsttmp" command. if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && # Now rename the file to the real destination. $doit $rmcmd -f $dstdir/$dstfile && $doit $mvcmd $dsttmp $dstdir/$dstfile fi && exit 0 quarry-0.2.0/build/missing0000755000175000017500000002123110132560461014171 0ustar bartbart#! /bin/sh # Common stub for a few missing GNU programs while installing. # Copyright 1996, 1997, 1999, 2000 Free Software Foundation, Inc. # Originally by Fran,cois Pinard , 1996. # 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 2, 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, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA # 02111-1307, USA. # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. if test $# -eq 0; then echo 1>&2 "Try \`$0 --help' for more information" exit 1 fi run=: # In the cases where this matters, `missing' is being run in the # srcdir already. if test -f configure.ac; then configure_ac=configure.ac else configure_ac=configure.in fi case "$1" in --run) # Try to run requested program, and just exit if it succeeds. run= shift "$@" && exit 0 ;; esac # If it does not exist, or fails to run (possibly an outdated version), # try to emulate it. case "$1" in -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an error status if there is no known handling for PROGRAM. Options: -h, --help display this help and exit -v, --version output version information and exit --run try to run the given command, and emulate it if it fails Supported PROGRAM values: aclocal touch file \`aclocal.m4' autoconf touch file \`configure' autoheader touch file \`config.h.in' automake touch all \`Makefile.in' files bison create \`y.tab.[ch]', if possible, from existing .[ch] flex create \`lex.yy.c', if possible, from existing .c help2man touch the output file lex create \`lex.yy.c', if possible, from existing .c makeinfo touch the output file tar try tar, gnutar, gtar, then tar without non-portable flags yacc create \`y.tab.[ch]', if possible, from existing .[ch]" ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) echo "missing 0.3 - GNU automake" ;; -*) echo 1>&2 "$0: Unknown \`$1' option" echo 1>&2 "Try \`$0 --help' for more information" exit 1 ;; aclocal) echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified \`acinclude.m4' or \`${configure_ac}'. You might want to install the \`Automake' and \`Perl' packages. Grab them from any GNU archive site." touch aclocal.m4 ;; autoconf) echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified \`${configure_ac}'. You might want to install the \`Autoconf' and \`GNU m4' packages. Grab them from any GNU archive site." touch configure ;; autoheader) echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified \`acconfig.h' or \`${configure_ac}'. You might want to install the \`Autoconf' and \`GNU m4' packages. Grab them from any GNU archive site." files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` test -z "$files" && files="config.h" touch_files= for f in $files; do case "$f" in *:*) touch_files="$touch_files "`echo "$f" | sed -e 's/^[^:]*://' -e 's/:.*//'`;; *) touch_files="$touch_files $f.in";; esac done touch $touch_files ;; automake) echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. You might want to install the \`Automake' and \`Perl' packages. Grab them from any GNU archive site." find . -type f -name Makefile.am -print | sed 's/\.am$/.in/' | while read f; do touch "$f"; done ;; bison|yacc) echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified a \`.y' file. You may need the \`Bison' package in order for those modifications to take effect. You can get \`Bison' from any GNU archive site." rm -f y.tab.c y.tab.h if [ $# -ne 1 ]; then eval LASTARG="\${$#}" case "$LASTARG" in *.y) SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` if [ -f "$SRCFILE" ]; then cp "$SRCFILE" y.tab.c fi SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` if [ -f "$SRCFILE" ]; then cp "$SRCFILE" y.tab.h fi ;; esac fi if [ ! -f y.tab.h ]; then echo >y.tab.h fi if [ ! -f y.tab.c ]; then echo 'main() { return 0; }' >y.tab.c fi ;; lex|flex) echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified a \`.l' file. You may need the \`Flex' package in order for those modifications to take effect. You can get \`Flex' from any GNU archive site." rm -f lex.yy.c if [ $# -ne 1 ]; then eval LASTARG="\${$#}" case "$LASTARG" in *.l) SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` if [ -f "$SRCFILE" ]; then cp "$SRCFILE" lex.yy.c fi ;; esac fi if [ ! -f lex.yy.c ]; then echo 'main() { return 0; }' >lex.yy.c fi ;; help2man) echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified a dependency of a manual page. You may need the \`Help2man' package in order for those modifications to take effect. You can get \`Help2man' from any GNU archive site." file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` if test -z "$file"; then file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'` fi if [ -f "$file" ]; then touch $file else test -z "$file" || exec >$file echo ".ab help2man is required to generate this page" exit 1 fi ;; makeinfo) if test -z "$run" && (makeinfo --version) > /dev/null 2>&1; then # We have makeinfo, but it failed. exit 1 fi echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified a \`.texi' or \`.texinfo' file, or any other file indirectly affecting the aspect of the manual. The spurious call might also be the consequence of using a buggy \`make' (AIX, DU, IRIX). You might want to install the \`Texinfo' package or the \`GNU make' package. Grab either from any GNU archive site." file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` if test -z "$file"; then file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file` fi touch $file ;; tar) shift if test -n "$run"; then echo 1>&2 "ERROR: \`tar' requires --run" exit 1 fi # We have already tried tar in the generic part. # Look for gnutar/gtar before invocation to avoid ugly error # messages. if (gnutar --version > /dev/null 2>&1); then gnutar ${1+"$@"} && exit 0 fi if (gtar --version > /dev/null 2>&1); then gtar ${1+"$@"} && exit 0 fi firstarg="$1" if shift; then case "$firstarg" in *o*) firstarg=`echo "$firstarg" | sed s/o//` tar "$firstarg" ${1+"$@"} && exit 0 ;; esac case "$firstarg" in *h*) firstarg=`echo "$firstarg" | sed s/h//` tar "$firstarg" ${1+"$@"} && exit 0 ;; esac fi echo 1>&2 "\ WARNING: I can't seem to be able to run \`tar' with the given arguments. You may want to install GNU tar or Free paxutils, or check the command line arguments." exit 1 ;; *) echo 1>&2 "\ WARNING: \`$1' is needed, and you do not seem to have it handy on your system. You might have modified some files without having the proper tools for further handling them. Check the \`README' file, it often tells you about the needed prerequirements for installing this package. You may also peek at any GNU archive site, in case some other package would contain this missing \`$1' program." exit 1 ;; esac exit 0 quarry-0.2.0/build/mkinstalldirs0000755000175000017500000000370410132560461015405 0ustar bartbart#! /bin/sh # mkinstalldirs --- make directory hierarchy # Author: Noah Friedman # Created: 1993-05-16 # Public domain errstatus=0 dirmode="" usage="\ Usage: mkinstalldirs [-h] [--help] [-m mode] dir ..." # process command line arguments while test $# -gt 0 ; do case $1 in -h | --help | --h*) # -h for help echo "$usage" 1>&2 exit 0 ;; -m) # -m PERM arg shift test $# -eq 0 && { echo "$usage" 1>&2; exit 1; } dirmode=$1 shift ;; --) # stop option processing shift break ;; -*) # unknown option echo "$usage" 1>&2 exit 1 ;; *) # first non-opt arg break ;; esac done for file do if test -d "$file"; then shift else break fi done case $# in 0) exit 0 ;; esac case $dirmode in '') if mkdir -p -- . 2>/dev/null; then echo "mkdir -p -- $*" exec mkdir -p -- "$@" fi ;; *) if mkdir -m "$dirmode" -p -- . 2>/dev/null; then echo "mkdir -m $dirmode -p -- $*" exec mkdir -m "$dirmode" -p -- "$@" fi ;; esac for file do set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` shift pathcomp= for d do pathcomp="$pathcomp$d" case $pathcomp in -*) pathcomp=./$pathcomp ;; esac if test ! -d "$pathcomp"; then echo "mkdir $pathcomp" mkdir "$pathcomp" || lasterr=$? if test ! -d "$pathcomp"; then errstatus=$lasterr else if test ! -z "$dirmode"; then echo "chmod $dirmode $pathcomp" lasterr="" chmod "$dirmode" "$pathcomp" || lasterr=$? if test ! -z "$lasterr"; then errstatus=$lasterr fi fi fi fi pathcomp="$pathcomp/" done done exit $errstatus # Local Variables: # mode: shell-script # sh-indentation: 2 # End: # mkinstalldirs ends here quarry-0.2.0/build/omf.make0000644000175000017500000000517710301744634014231 0ustar bartbart# # No modifications of this Makefile should be necessary. # # This file contains the build instructions for installing OMF files. It is # generally called from the makefiles for particular formats of documentation. # # Note that you must configure your package with --localstatedir=/var # so that the scrollkeeper-update command below will update the database # in the standard scrollkeeper directory. # # If it is impossible to configure with --localstatedir=/var, then # modify the definition of scrollkeeper_localstate_dir so that # it points to the correct location. Note that you must still use # $(localstatedir) in this or when people build RPMs it will update # the real database on their system instead of the one under RPM_BUILD_ROOT. # # Note: This make file is not incorporated into xmldocs.make because, in # general, there will be other documents install besides XML documents # and the makefiles for these formats should also include this file. # # About this file: # This file was derived from scrollkeeper_example2, a package # illustrating how to install documentation and OMF files for use with # ScrollKeeper 0.3.x and 0.4.x. For more information, see: # http://scrollkeeper.sourceforge.net/ # Version: 0.1.3 (last updated: March 20, 2002) # # 2005-08-28 Paul Pogonyshev # # Don't run `scrollkeeper-update' if # `--disable-scrollkeeper-update' option was passed to # `configure' script (at request from Michel Salim.) omf_dest_dir=$(datadir)/omf/@PACKAGE@ scrollkeeper_localstate_dir = $(localstatedir)/scrollkeeper # At some point, it may be wise to change to something like this: # scrollkeeper_localstate_dir = @SCROLLKEEPER_STATEDIR@ if DO_SCROLLKEEPER_UPDATE do_scrollkeeper_update = true else do_scrollkeeper_update = false endif omf: omf_timestamp omf_timestamp: $(omffile) -for file in $(omffile); do \ scrollkeeper-preinstall $(docdir)/$(docname).xml $(srcdir)/$$file $$file.out; \ done; \ touch omf_timestamp install-data-hook-omf: $(mkinstalldirs) $(DESTDIR)$(omf_dest_dir) for file in $(omffile); do \ $(INSTALL_DATA) $$file.out $(DESTDIR)$(omf_dest_dir)/$$file; \ done -if test "$(do_scrollkeeper_update)" = "true"; then \ scrollkeeper-update -p $(DESTDIR)$(scrollkeeper_localstate_dir) -o $(DESTDIR)$(omf_dest_dir); \ fi uninstall-local-omf: -for file in $(srcdir)/*.omf; do \ basefile=`basename $$file`; \ rm -f $(DESTDIR)$(omf_dest_dir)/$$basefile; \ done -rmdir $(DESTDIR)$(omf_dest_dir) -if test "$(do_scrollkeeper_update)" = "true"; then \ -scrollkeeper-update -p $(DESTDIR)$(scrollkeeper_localstate_dir); \ fi clean-local-omf: -for file in $(omffile); do \ rm -f $$file.out; \ done quarry-0.2.0/build/xmldocs.make0000644000175000017500000001071310425147762015117 0ustar bartbart# # No modifications of this Makefile should be necessary. # # To use this template: # 1) Define: figdir, docname, lang, omffile, and entities in # your Makefile.am file for each document directory, # although figdir, omffile, and entities may be empty # 2) Make sure the Makefile in (1) also includes # "include $(top_srcdir)/xmldocs.make" and # "dist-hook: app-dist-hook". # 3) Optionally define 'entities' to hold xml entities which # you would also like installed # 4) Figures must go under $(figdir)/ and be in PNG format # 5) You should only have one document per directory # 6) Note that the figure directory, $(figdir)/, should not have its # own Makefile since this Makefile installs those figures. # # example Makefile.am: # figdir = figures # docname = scrollkeeper-manual # lang = C # omffile=scrollkeeper-manual-C.omf # entities = fdl.xml # include $(top_srcdir)/xmldocs.make # dist-hook: app-dist-hook # # About this file: # This file was taken from scrollkeeper_example2, a package illustrating # how to install documentation and OMF files for use with ScrollKeeper # 0.3.x and 0.4.x. For more information, see: # http://scrollkeeper.sourceforge.net/ # Version: 0.1.2 (last updated: March 20, 2002) # # 2006-04-06 Paul Pogonyshev # # Replace `aux' directory with `build'. # 2004-11-29 Paul Pogonyshev # # Make XML installation conditional on ScrollKeeper presence. # If it is not present, then only install HTML file. # # 2004-10-11 Paul Pogonyshev # # Change path to `omf.make' from `$(top_srcdir)/' to # `$(top_srcdir)/aux/' (Quarry-specific). Change `docdir'. # Install and distribute `$(docname).html' too. # ********** Begin of section some packagers may need to modify ********** # This variable (docdir) specifies where the documents should be installed. # This default value should work for most packages. docdir = $(datadir)/@PACKAGE@/help/$(lang) # ********** You should not have to edit below this line ********** xml_files = $(entities) $(docname).xml $(docname).html EXTRA_DIST = $(xml_files) $(omffile) CLEANFILES = omf_timestamp if HAVE_SCROLLKEEPER include $(top_srcdir)/build/omf.make all: omf $(docname).xml: $(entities) -ourdir=`pwd`; \ cd $(srcdir); \ cp $(entities) $$ourdir endif # HAVE_SCROLLKEEPER app-dist-hook: if test "$(figdir)"; then \ $(mkinstalldirs) $(distdir)/$(figdir); \ for file in $(srcdir)/$(figdir)/*.png; do \ basefile=`echo $$file | sed -e 's,^.*/,,'`; \ $(INSTALL_DATA) $$file $(distdir)/$(figdir)/$$basefile; \ done \ fi if HAVE_SCROLLKEEPER install-data-local: omf $(mkinstalldirs) $(DESTDIR)$(docdir) for file in $(xml_files); do \ cp $(srcdir)/$$file $(DESTDIR)$(docdir); \ done if test "$(figdir)"; then \ $(mkinstalldirs) $(DESTDIR)$(docdir)/$(figdir); \ for file in $(srcdir)/$(figdir)/*.png; do \ basefile=`echo $$file | sed -e 's,^.*/,,'`; \ $(INSTALL_DATA) $$file $(DESTDIR)$(docdir)/$(figdir)/$$basefile; \ done \ fi install-data-hook: install-data-hook-omf uninstall-local: uninstall-local-doc uninstall-local-omf uninstall-local-doc: -if test "$(figdir)"; then \ for file in $(srcdir)/$(figdir)/*.png; do \ basefile=`echo $$file | sed -e 's,^.*/,,'`; \ rm -f $(DESTDIR)$(docdir)/$(figdir)/$$basefile; \ done; \ rmdir $(DESTDIR)$(docdir)/$(figdir); \ fi -for file in $(xml_files); do \ rm -f $(DESTDIR)$(docdir)/$$file; \ done -rmdir $(DESTDIR)$(docdir) clean-local: clean-local-doc clean-local-omf else # not HAVE_SCROLLKEEPER install-data-local: $(mkinstalldirs) $(DESTDIR)$(docdir) cp $(srcdir)/$(docname).html $(DESTDIR)$(docdir); if test "$(figdir)"; then \ $(mkinstalldirs) $(DESTDIR)$(docdir)/$(figdir); \ for file in $(srcdir)/$(figdir)/*.png; do \ basefile=`echo $$file | sed -e 's,^.*/,,'`; \ $(INSTALL_DATA) $$file $(DESTDIR)$(docdir)/$(figdir)/$$basefile; \ done \ fi install-data-hook: uninstall-local: uninstall-local-doc uninstall-local-doc: -if test "$(figdir)"; then \ for file in $(srcdir)/$(figdir)/*.png; do \ basefile=`echo $$file | sed -e 's,^.*/,,'`; \ rm -f $(DESTDIR)$(docdir)/$(figdir)/$$basefile; \ done; \ rmdir $(DESTDIR)$(docdir)/$(figdir); \ fi -rm -f $(DESTDIR)$(docdir)/$(docname).html; -rmdir $(DESTDIR)$(docdir) clean-local: clean-local-doc endif # not HAVE_SCROLLKEEPER # for non-srcdir builds, remove the copied entities. clean-local-doc: if test $(srcdir) != .; then \ rm -f $(entities); \ fi quarry-0.2.0/build/list.make0000644000175000017500000000301710217107327014410 0ustar bartbartSUFFIXES = .list .h # `LIST_FILES' must be set by the includer. The includer can use # `LIST_STAMP_FILES' and `LIST_GENERATED_FILES' and assume they are # set just as here. # LIST_STAMP_FILES = $(LIST_FILES:.list=.stamp) LIST_GENERATED_FILES = $(LIST_FILES:.list=.c) $(LIST_FILES:.list=.h) # Make everything depend on the `Makefile' and the list parser. $(LIST_STAMP_FILES) : Makefile $(PARSE_LIST_COMMAND) # `PARSE_LIST_COMMAND' and `PARSE_LIST_FLAGS' should be set by the # includer. # PARSE_LIST = $(PARSE_LIST_COMMAND) $(PARSE_LIST_FLAGS) # We use `cmp' here to avoid unneeded recompilations of files that # depend on generated ones (only really useful for `.h' files.) # PARSE_LIST_BUILD_RULE = \ if $(PARSE_LIST) `test -f '$<' || echo '$(srcdir)/'`$< \ $*.h.new $*.c.new; then \ if cmp -s $*.c.new $*.c; \ then rm -f $*.c.new; else mv -f $*.c.new $*.c; \ fi; \ if cmp -s $*.h.new $*.h; \ then rm -f $*.h.new; else mv -f $*.h.new $*.h; \ fi; \ echo timestamp > $@; \ else \ (rm -f $*.c $*.c.new $*.h $*.h.new ; exit 1) \ fi .list.stamp: $(PARSE_LIST_BUILD_RULE) # Since $(LIST_GENERATED_FILES) defined by the includer don't (at # least shouldn't) have any dependencies, if this rule is being # executed, it probably means that one of the files was removed. # Then all we can do is to force rebuilding of corresponding stamp # file, which builds the required sources ``by side-effect.'' # $(LIST_GENERATED_FILES): rm -f $*.stamp; $(MAKE) $(AM_MAKEFLAGS) $*.stamp quarry-0.2.0/data/0000755000175000017500000000000010530402565012407 5ustar bartbartquarry-0.2.0/data/Makefile.in0000644000175000017500000004277410455756655014514 0ustar bartbart# Makefile.in generated by automake 1.7.9 from Makefile.am. # @configure_input@ # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 # Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # Process this file with Automake to produce `Makefile.in'. # FIXME: Internationalize `quarry.desktop' and `quarry.xml'. Probably # need to use `intltool'. srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = .. am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : host_triplet = @host@ ACLOCAL = @ACLOCAL@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BUILD_SGF_UTILS_FALSE = @BUILD_SGF_UTILS_FALSE@ BUILD_SGF_UTILS_TRUE = @BUILD_SGF_UTILS_TRUE@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DO_SCROLLKEEPER_UPDATE_FALSE = @DO_SCROLLKEEPER_UPDATE_FALSE@ DO_SCROLLKEEPER_UPDATE_TRUE = @DO_SCROLLKEEPER_UPDATE_TRUE@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ GMSGFMT = @GMSGFMT@ HAVE_SCROLLKEEPER_FALSE = @HAVE_SCROLLKEEPER_FALSE@ HAVE_SCROLLKEEPER_TRUE = @HAVE_SCROLLKEEPER_TRUE@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ LDFLAGS = @LDFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ MAKEINFO = @MAKEINFO@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGMERGE = @MSGMERGE@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSUB = @POSUB@ QUARRY_GTHREAD_CFLAGS = @QUARRY_GTHREAD_CFLAGS@ QUARRY_GTHREAD_LIBS = @QUARRY_GTHREAD_LIBS@ QUARRY_GTK_CFLAGS = @QUARRY_GTK_CFLAGS@ QUARRY_GTK_DEPRECATED_FLAGS = @QUARRY_GTK_DEPRECATED_FLAGS@ QUARRY_GTK_LIBS = @QUARRY_GTK_LIBS@ QUARRY_WARNINGS = @QUARRY_WARNINGS@ QUARRY_WARNINGS_GTK = @QUARRY_WARNINGS_GTK@ RANLIB = @RANLIB@ REGISTER_MIME_TYPES_FALSE = @REGISTER_MIME_TYPES_FALSE@ REGISTER_MIME_TYPES_TRUE = @REGISTER_MIME_TYPES_TRUE@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ ac_ct_CC = @ac_ct_CC@ ac_ct_RANLIB = @ac_ct_RANLIB@ ac_ct_STRIP = @ac_ct_STRIP@ ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ datadir = @datadir@ exec_prefix = @exec_prefix@ have_scrollkeeper = @have_scrollkeeper@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localstatedir = @localstatedir@ mandir = @mandir@ oldincludedir = @oldincludedir@ prefix = @prefix@ program_transform_name = @program_transform_name@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ SUBDIRS = \ markup-themes \ textures FILES = \ gtkrc filesdir = $(datadir)/quarry files_DATA = $(FILES) DESKTOP_FILE = quarry.desktop desktopdir = $(datadir)/applications desktop_DATA = $(DESKTOP_FILE) ICON_FILE = quarry.png icondir = $(datadir)/pixmaps icon_DATA = $(ICON_FILE) @REGISTER_MIME_TYPES_TRUE@MIME_DESCRIPTION_FILE = quarry.xml @REGISTER_MIME_TYPES_TRUE@mimedir = $(datadir)/mime/packages @REGISTER_MIME_TYPES_TRUE@mime_DATA = $(MIME_DESCRIPTION_FILE) EXTRA_DIST = \ $(FILES) \ $(DESKTOP_FILE:.desktop=.desktop.in) \ $(ICON_FILE) \ $(MIME_DESCRIPTION_FILE) DISTCLEANFILES = *~ subdir = data ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 mkinstalldirs = $(SHELL) $(top_srcdir)/build/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = quarry.desktop DIST_SOURCES = DATA = $(desktop_DATA) $(files_DATA) $(icon_DATA) $(mime_DATA) RECURSIVE_TARGETS = info-recursive dvi-recursive pdf-recursive \ ps-recursive install-info-recursive uninstall-info-recursive \ all-recursive install-data-recursive install-exec-recursive \ installdirs-recursive install-recursive uninstall-recursive \ check-recursive installcheck-recursive DIST_COMMON = $(srcdir)/Makefile.in ChangeLog Makefile.am \ quarry.desktop.in DIST_SUBDIRS = $(SUBDIRS) all: all-recursive .SUFFIXES: $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4) cd $(top_srcdir) && \ $(AUTOMAKE) --foreign data/Makefile Makefile: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) quarry.desktop: $(top_builddir)/config.status quarry.desktop.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ uninstall-info-am: desktopDATA_INSTALL = $(INSTALL_DATA) install-desktopDATA: $(desktop_DATA) @$(NORMAL_INSTALL) $(mkinstalldirs) $(DESTDIR)$(desktopdir) @list='$(desktop_DATA)'; for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ f="`echo $$p | sed -e 's|^.*/||'`"; \ echo " $(desktopDATA_INSTALL) $$d$$p $(DESTDIR)$(desktopdir)/$$f"; \ $(desktopDATA_INSTALL) $$d$$p $(DESTDIR)$(desktopdir)/$$f; \ done uninstall-desktopDATA: @$(NORMAL_UNINSTALL) @list='$(desktop_DATA)'; for p in $$list; do \ f="`echo $$p | sed -e 's|^.*/||'`"; \ echo " rm -f $(DESTDIR)$(desktopdir)/$$f"; \ rm -f $(DESTDIR)$(desktopdir)/$$f; \ done filesDATA_INSTALL = $(INSTALL_DATA) install-filesDATA: $(files_DATA) @$(NORMAL_INSTALL) $(mkinstalldirs) $(DESTDIR)$(filesdir) @list='$(files_DATA)'; for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ f="`echo $$p | sed -e 's|^.*/||'`"; \ echo " $(filesDATA_INSTALL) $$d$$p $(DESTDIR)$(filesdir)/$$f"; \ $(filesDATA_INSTALL) $$d$$p $(DESTDIR)$(filesdir)/$$f; \ done uninstall-filesDATA: @$(NORMAL_UNINSTALL) @list='$(files_DATA)'; for p in $$list; do \ f="`echo $$p | sed -e 's|^.*/||'`"; \ echo " rm -f $(DESTDIR)$(filesdir)/$$f"; \ rm -f $(DESTDIR)$(filesdir)/$$f; \ done iconDATA_INSTALL = $(INSTALL_DATA) install-iconDATA: $(icon_DATA) @$(NORMAL_INSTALL) $(mkinstalldirs) $(DESTDIR)$(icondir) @list='$(icon_DATA)'; for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ f="`echo $$p | sed -e 's|^.*/||'`"; \ echo " $(iconDATA_INSTALL) $$d$$p $(DESTDIR)$(icondir)/$$f"; \ $(iconDATA_INSTALL) $$d$$p $(DESTDIR)$(icondir)/$$f; \ done uninstall-iconDATA: @$(NORMAL_UNINSTALL) @list='$(icon_DATA)'; for p in $$list; do \ f="`echo $$p | sed -e 's|^.*/||'`"; \ echo " rm -f $(DESTDIR)$(icondir)/$$f"; \ rm -f $(DESTDIR)$(icondir)/$$f; \ done mimeDATA_INSTALL = $(INSTALL_DATA) install-mimeDATA: $(mime_DATA) @$(NORMAL_INSTALL) $(mkinstalldirs) $(DESTDIR)$(mimedir) @list='$(mime_DATA)'; for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ f="`echo $$p | sed -e 's|^.*/||'`"; \ echo " $(mimeDATA_INSTALL) $$d$$p $(DESTDIR)$(mimedir)/$$f"; \ $(mimeDATA_INSTALL) $$d$$p $(DESTDIR)$(mimedir)/$$f; \ done uninstall-mimeDATA: @$(NORMAL_UNINSTALL) @list='$(mime_DATA)'; for p in $$list; do \ f="`echo $$p | sed -e 's|^.*/||'`"; \ echo " rm -f $(DESTDIR)$(mimedir)/$$f"; \ rm -f $(DESTDIR)$(mimedir)/$$f; \ done # This directory's subdirectories are mostly independent; you can cd # into them and run `make' without going through this Makefile. # To change the values of `make' variables: instead of editing Makefiles, # (1) if the variable is set in `config.status', edit `config.status' # (which will cause the Makefiles to be regenerated when you run `make'); # (2) otherwise, pass the desired values on the `make' command line. $(RECURSIVE_TARGETS): @set fnord $$MAKEFLAGS; amf=$$2; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ list='$(SUBDIRS)'; for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" mostlyclean-recursive clean-recursive distclean-recursive \ maintainer-clean-recursive: @set fnord $$MAKEFLAGS; amf=$$2; \ dot_seen=no; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ rev=''; for subdir in $$list; do \ if test "$$subdir" = "."; then :; else \ rev="$$subdir $$rev"; \ fi; \ done; \ rev="$$rev ."; \ target=`echo $@ | sed s/-recursive//`; \ for subdir in $$rev; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ done && test -z "$$fail" tags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ done ctags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ done ETAGS = etags ETAGSFLAGS = CTAGS = ctags CTAGSFLAGS = tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ if (etags --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ else \ include_option=--include; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test -f $$subdir/TAGS && \ tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(ETAGS_ARGS)$$tags$$unique" \ || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique ctags: CTAGS CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = .. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ case $$file in \ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ esac; \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ dir="/$$dir"; \ $(mkinstalldirs) "$(distdir)$$dir"; \ else \ dir=''; \ fi; \ if test -d $$d/$$file; then \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test -d $(distdir)/$$subdir \ || mkdir $(distdir)/$$subdir \ || exit 1; \ (cd $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" \ distdir=../$(distdir)/$$subdir \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile $(DATA) installdirs: installdirs-recursive installdirs-am: $(mkinstalldirs) $(DESTDIR)$(desktopdir) $(DESTDIR)$(filesdir) $(DESTDIR)$(icondir) $(DESTDIR)$(mimedir) install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -rm -f $(CONFIG_CLEAN_FILES) -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic mostlyclean-am distclean: distclean-recursive -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-recursive dvi-am: info: info-recursive info-am: install-data-am: install-desktopDATA install-filesDATA install-iconDATA \ install-mimeDATA @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) install-data-hook install-exec-am: install-info: install-info-recursive install-man: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-desktopDATA uninstall-filesDATA \ uninstall-iconDATA uninstall-info-am uninstall-mimeDATA @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) uninstall-hook uninstall-info: uninstall-info-recursive .PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am check check-am clean \ clean-generic clean-recursive ctags ctags-recursive distclean \ distclean-generic distclean-recursive distclean-tags distdir \ dvi dvi-am dvi-recursive info info-am info-recursive install \ install-am install-data install-data-am install-data-recursive \ install-desktopDATA install-exec install-exec-am \ install-exec-recursive install-filesDATA install-iconDATA \ install-info install-info-am install-info-recursive install-man \ install-mimeDATA install-recursive install-strip installcheck \ installcheck-am installdirs installdirs-am \ installdirs-recursive maintainer-clean maintainer-clean-generic \ maintainer-clean-recursive mostlyclean mostlyclean-generic \ mostlyclean-recursive pdf pdf-am pdf-recursive ps ps-am \ ps-recursive tags tags-recursive uninstall uninstall-am \ uninstall-desktopDATA uninstall-filesDATA uninstall-iconDATA \ uninstall-info-am uninstall-info-recursive uninstall-mimeDATA \ uninstall-recursive @REGISTER_MIME_TYPES_TRUE@install-data-hook: update-mime-database @REGISTER_MIME_TYPES_TRUE@uninstall-hook: update-mime-database @REGISTER_MIME_TYPES_TRUE@update-mime-database: @REGISTER_MIME_TYPES_TRUE@ (update-mime-database $(datadir)/mime \ @REGISTER_MIME_TYPES_TRUE@ || echo "*WARNING* failed to update the MIME database") @REGISTER_MIME_TYPES_TRUE@.PHONY: update-mime-database # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: quarry-0.2.0/data/ChangeLog0000644000175000017500000001037510530113036014157 0ustar bartbart2006-11-19 Paul Pogonyshev * (Quarry version 0.2.0.) 2006-10-29 Paul Pogonyshev * (Quarry version 0.1.20.) 2006-07-16 Paul Pogonyshev * (Quarry version 0.1.19.) 2006-07-14 Paul Pogonyshev * (Quarry version 0.1.18.) * quarry.png: New file (icon.) * quarry.desktop.in (Icon): Use `quarry.png'. (MimeType): New value. 2006-03-09 Paul Pogonyshev * (Quarry version 0.1.17.) 2006-03-08 Paul Pogonyshev * quarry.xml: Use de-facto standard application/x-go-sgf as the MIME type. Keep text/sgf as an alias. 2006-02-11 Paul Pogonyshev * Makefile.am: Install `quarry.xml' into the MIME database and rebuild it, unless this is disabled at configuration step. * quarry.xml: New file (SGF MIME specification.) 2005-09-27 Paul Pogonyshev * (Quarry version 0.1.16.) * quarry.desktop.in: Replace "Othello" with "Reversi". 2005-08-19 Michel Salim * quarry.desktop.in: New file. 2005-06-17 Paul Pogonyshev * (Quarry version 0.1.15.) 2005-04-28 Paul Pogonyshev * markup-themes/bold/last-move.svg: New file. * markup-themes/default/last-move.svg: New file. * markup-themes/filled/last-move.svg: New file. 2005-03-14 Paul Pogonyshev * (Quarry version 0.1.14.) 2005-03-13 Paul Pogonyshev * (Quarry version 0.1.13.) 2005-03-13 Brenn Hill * textures/wood2.jpg: New file. 2005-01-15 Paul Pogonyshev * (Quarry version 0.1.12.) 2005-01-06 Paul Pogonyshev * (Quarry version 0.1.11.) 2004-12-12 Paul Pogonyshev * markup-themes/filled: New directory. * markup-themes/filled/circle.svg: New file. * markup-themes/filled/cross.svg: New file. * markup-themes/filled/square.svg: New file. * markup-themes/filled/selected.svg: New file. * markup-themes/filled/triangle.svg: New file. * markup-themes/filled/theme.cfg: New file. * markup-themes/Makefile.am: Don't recurse in subdirectories, issue all commands right from `markup-themes' directory. * markup-themes/default/Makefile.am: Remove file. * markup-themes/bold/Makefile.am: Remove file. 2004-11-30 Paul Pogonyshev * (Quarry version 0.1.10.) 2004-10-22 Paul Pogonyshev * markup-themes/bold: New directory. * markup-themes/bold/Makefile.am: New file. * markup-themes/bold/circle.svg: New file. * markup-themes/bold/cross.svg: New file. * markup-themes/bold/square.svg: New file. * markup-themes/bold/selected.svg: New file. * markup-themes/bold/triangle.svg: New file. * markup-themes/bold/theme.cfg: New file. 2004-10-14 Paul Pogonyshev * (Quarry version 0.1.9.) * (Quarry version 0.1.8.) 2004-08-28 Arend Bayer * textures/wood1.jpg: Make texture less contrast. 2004-08-28 Paul Pogonyshev * (Quarry version 0.1.7.) 2004-08-22 Paul Pogonyshev * markup-themes/default/theme.cfg: New file. 2004-08-15 Paul Pogonyshev * (Quarry version 0.1.6.) 2004-08-13 Paul Pogonyshev * markup-themes, markup-themes/default: New directories. * markup-themes/Makefile.am, markup-themes/default/Makefile.am: New files. * markup-themes/default/circle.svg: New file. * markup-themes/default/cross.svg: New file. * markup-themes/default/square.svg: New file. * markup-themes/default/selected.svg: New file. * markup-themes/default/triangle.svg: New file. 2004-07-20 Paul Pogonyshev * (Quarry version 0.1.5.) 2004-05-13 Paul Pogonyshev * (Quarry version 0.1.4.) 2004-05-12 Paul Pogonyshev * (Quarry version 0.1.3.) 2004-04-21 Paul Pogonyshev * (Quarry version 0.1.2.) Changes before the project registration on Gna! (2004-04-12) were not logged. Copyright (C) 2004, 2005, 2006 Paul Pogonyshev. Copying and distribution of this file, with or without modification, are permitted provided the copyright notice and this notice are preserved. quarry-0.2.0/data/Makefile.am0000644000175000017500000000175210455756034014461 0ustar bartbart# Process this file with Automake to produce `Makefile.in'. # FIXME: Internationalize `quarry.desktop' and `quarry.xml'. Probably # need to use `intltool'. SUBDIRS = \ markup-themes \ textures FILES = \ gtkrc filesdir = $(datadir)/quarry files_DATA = $(FILES) DESKTOP_FILE = quarry.desktop desktopdir = $(datadir)/applications desktop_DATA = $(DESKTOP_FILE) ICON_FILE = quarry.png icondir = $(datadir)/pixmaps icon_DATA = $(ICON_FILE) if REGISTER_MIME_TYPES MIME_DESCRIPTION_FILE = quarry.xml mimedir = $(datadir)/mime/packages mime_DATA = $(MIME_DESCRIPTION_FILE) install-data-hook: update-mime-database uninstall-hook: update-mime-database update-mime-database: (update-mime-database $(datadir)/mime \ || echo "*WARNING* failed to update the MIME database") .PHONY: update-mime-database endif EXTRA_DIST = \ $(FILES) \ $(DESKTOP_FILE:.desktop=.desktop.in) \ $(ICON_FILE) \ $(MIME_DESCRIPTION_FILE) DISTCLEANFILES = *~ quarry-0.2.0/data/quarry.desktop.in0000644000175000017500000000051610455757667015762 0ustar bartbart[Desktop Entry] Encoding=UTF-8 Name=Quarry GenericName=Board Game GUI Comment=A multi-purpose board game GUI for Go, Amazons and Reversi Exec=quarry Icon=quarry.png Terminal=false Type=Application Version=@VERSION@ Categories=Application;GTK;GNOME;Game;BoardGame; StartupNotify=true MimeType=application/x-go-sgf;text/sgf;text/x-sgf; quarry-0.2.0/data/gtkrc0000644000175000017500000000041010036612364013440 0ustar bartbartstyle "sub-header" { font_name = ", bold" } style "dialog" { GtkDialog::content_area_border = 12 GtkDialog::button_spacing = 6 GtkDialog::action_area_border = 0 } widget "*.quarry-sub-header" style "sub-header" widget "quarry-dialog" style "dialog" quarry-0.2.0/data/quarry.png0000644000175000017500000000647510455756466014476 0ustar bartbart‰PNG  IHDR00Ø`nÐ IDATXíY[Œ]×Yþÿ]öíÜÏ\=ãËŒ+‰í4U0iªªTô$„‡""Q*á¥oHäx¬”TR@-(–x€Rµ$UJA$NRÅMã¸öØÍÌxŽc_-|Šújæœ+µ,á<¢yž÷ûýëׯ{Ãü¿àð‹õ«_úÚºWÂ;ÞãS´´|uþ¡€ÌýáÎ<ùÄõZô…?¹t×8œ¹žûÔÇ:Æ“ÉR‡_ß1e–EÂíç—¦.Qü«¹–äœÆi½™éò½»Åi‡Œ±I–sgq¾ Wo?Ó›×çg™#¢*‡Öº['"ª'ÒZ»ÐÆk[w‰Ó©“u®KrÎ}ò\’ç¹—Ý;8Ïsïl?ªF®êš¦é£ggãHpέµ?ܾkœóçæ¢€GÄnß¿ÄÞÛоr—•·ª\y-µTJ›azÐj„>Vf[òÜJðSœãó²Y—³ØObŒ=óø"¹üPÜU°¼úçyž«lü©‡çáØbÝ×CÆØo~î8ÚìÎpòñ§?¶L€+Kí…ˆ:Ñï~vi<—9YMËr¾yž‡ÃÏ<Òm×åò\=Äh¾=ó‹³w†ós íF°0“DGDö;Ogç«GšI`ßxÇÚÛJþ!gY¦²ñ“›¿ÿD+ŽÄ#gF“±”’ ®”–RÎ6©Óo¼×ûŸqòñ“ŸXºµ†âÌÉŽÂ9Çc¹Êü׿ôèÑnS~ýŸÖÖ¶”ß–K÷{ 4MOÌË_xðÈâl“À>xzŽ3òË8¿ü‰†øÆw®]ÿ¯q–»ì³_é$ö{fÁËÀ~ïó ö“8¤tÇ4ï]mÌ60ŒÊvû£áhìLÖ­ãBË}þñÜ?Ü™í$}dœâœ!gŒ1d€Î9Ƙ1fe©uîT»[³ƒÁœÝí‡Ã±5Y·ŽÇfùÓŸ<~f%iµ’HÂù,EgŒ{æÄ‘1æµD"¸g¹½8“œ=Ù½zm ¾ôåýêsOÀh2I¢ Ëcm~ωYFXn×åÕ³"¿C<ÚêÖʼn…°?rˆøìÿóWþà k-1 §áÌ©™VB‚3"òÄ8cŒ÷!Æ…@FDòì©™£m~³7€•¥&#hæÚq= {›[%y(‰„¯‡¥wü«(÷­tÂ(îr/¢16‰e»OFû33ñxÌРäŒ1ιÒ2‡DÌ0GˆŒ€3jD«KM!D®5XSm-Ê¡J$ü+_„ü‚³¹n«Ë-k-c €ÒñA§QÕ#gAŒ²¹BKpަËxÜJåTû‡bmc|Àúž°Ì,eå®=9г~ëŸ]êg‡˜÷¶UMÀ¹bÎ ‚`ŒCÏ܈È”ëU»6­µ`d­­JS¦O ퟤZlÛÓ.XJæ9"¬µÚh¥š¹˜»´;¶Ã5 ¨bWÀ=õ/z¢)[ðëQÞ$çyÄU!ª6÷ûYÝÊ“G¢¨&÷”ÈZO‰˜'͈0á«omîÌñVüŠ…9":BŽ!¡vÖ8[F€OE†„ˆÖïÞS®gÁ€ÃBE®õ³F–§<Õã+r¡ –¼èBpß2Æ1:8N˜æ¹+{ –aç½kƒ¢®–åõPDûð,û߃ ¿½lx y„^>Ï9+[R眵QÔÆ– ÄÙjV:DŒÂðõwãT9ç,$'À2wüü¶í9ÃA=$4p[It²]J©µQJçyžfYše™gއ9~Ñ!!‰Æ‡7÷sÜëí=R&W¹F馲sð¥ïÐþåoF* ¬3Æh¥³\ÿðÌ2À±ÅÆ…Jw”Íeõ¤ýP‹^º¯^þ|°Ó©îæ;ë¶Ýj ßo €jlÚ¹ÒY– Gãë?ÝXHvšµÚÂL‡ÂÃKZ^.VFn•’N)˜ [:8éE@Dc œ\d·zW¯nÎ5m!áÔ³¦¨à*Ëòáh´¾±1mŸ8R~_¨¨ZÌD©ÚJö•—ÁnŠsÝŸ=Sg?ºñÖOÖem1‰£r—ôÒLÒlgw/mœ;Á NÞ;Ïy‘+Ü!X‡èµµÆ DȘw…çŠazŽÆ@)e c!!91k-"¡k¬3öáÓÝn²ÿ£µË—¯¨ éôö51‘e“DZ²£{X¸Àd( àôl ÷qÃ=…¨÷U¶b¬&T5ÚýDD†TÝ0`e©qd®6ßÜØöOÏÒÿèžÿýŸ!bk­àpzµ3׉¬u•¨@^²‹ê@õ\Õ·Êɫߔ~/CÄ(à÷­´ƒ0Ú䰺܀F-j$Â9'‘6¦jüOßÝY–bû¢,IEND®B`‚quarry-0.2.0/data/quarry.xml0000644000175000017500000000275210403627774014474 0ustar bartbart Board game record quarry-0.2.0/data/markup-themes/0000755000175000017500000000000010530402565015171 5ustar bartbartquarry-0.2.0/data/markup-themes/bold/0000755000175000017500000000000010530402565016111 5ustar bartbartquarry-0.2.0/data/markup-themes/bold/circle.svg0000644000175000017500000000061310136030643020067 0ustar bartbart quarry-0.2.0/data/markup-themes/bold/cross.svg0000644000175000017500000000074110136030643017761 0ustar bartbart quarry-0.2.0/data/markup-themes/bold/last-move.svg0000644000175000017500000000064510234244506020546 0ustar bartbart quarry-0.2.0/data/markup-themes/bold/selected.svg0000644000175000017500000000067510136030643020426 0ustar bartbart quarry-0.2.0/data/markup-themes/bold/square.svg0000644000175000017500000000066110136030643020131 0ustar bartbart quarry-0.2.0/data/markup-themes/bold/triangle.svg0000644000175000017500000000066210136030643020437 0ustar bartbart quarry-0.2.0/data/markup-themes/bold/theme.cfg0000644000175000017500000000014010136030643017663 0ustar bartbart[Markup Theme "Bold"] Default markup size = 0.65 Size is relative = true Default opacity = 0.9 quarry-0.2.0/data/markup-themes/default/0000755000175000017500000000000010530402565016615 5ustar bartbartquarry-0.2.0/data/markup-themes/default/circle.svg0000644000175000017500000000061310107511274020575 0ustar bartbart quarry-0.2.0/data/markup-themes/default/cross.svg0000644000175000017500000000074110107511274020467 0ustar bartbart quarry-0.2.0/data/markup-themes/default/last-move.svg0000644000175000017500000000073310234244506021250 0ustar bartbart quarry-0.2.0/data/markup-themes/default/selected.svg0000644000175000017500000000066610107511274021134 0ustar bartbart quarry-0.2.0/data/markup-themes/default/square.svg0000644000175000017500000000066110107511274020637 0ustar bartbart quarry-0.2.0/data/markup-themes/default/triangle.svg0000644000175000017500000000066210107511274021145 0ustar bartbart quarry-0.2.0/data/markup-themes/default/theme.cfg0000644000175000017500000000014310112734021020365 0ustar bartbart[Markup Theme "Default"] Default markup size = 0.65 Size is relative = true Default opacity = 0.8 quarry-0.2.0/data/markup-themes/filled/0000755000175000017500000000000010530402565016430 5ustar bartbartquarry-0.2.0/data/markup-themes/filled/circle.svg0000644000175000017500000000064510157057363020426 0ustar bartbart quarry-0.2.0/data/markup-themes/filled/cross.svg0000644000175000017500000000103110157057363020304 0ustar bartbart quarry-0.2.0/data/markup-themes/filled/last-move.svg0000644000175000017500000000073310234244506021063 0ustar bartbart quarry-0.2.0/data/markup-themes/filled/selected.svg0000644000175000017500000000077210157057363020756 0ustar bartbart quarry-0.2.0/data/markup-themes/filled/square.svg0000644000175000017500000000071410157057363020462 0ustar bartbart quarry-0.2.0/data/markup-themes/filled/triangle.svg0000644000175000017500000000071410157057363020767 0ustar bartbart quarry-0.2.0/data/markup-themes/filled/theme.cfg0000644000175000017500000000014310157057363020220 0ustar bartbart[Markup Theme "Filled"] Default markup size = 0.65 Size is relative = true Default opacity = 0.85 quarry-0.2.0/data/markup-themes/Makefile.in0000644000175000017500000002316610425150132017237 0ustar bartbart# Makefile.in generated by automake 1.7.9 from Makefile.am. # @configure_input@ # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 # Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # Process this file with Automake to produce `Makefile.in'. srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = ../.. am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : host_triplet = @host@ ACLOCAL = @ACLOCAL@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BUILD_SGF_UTILS_FALSE = @BUILD_SGF_UTILS_FALSE@ BUILD_SGF_UTILS_TRUE = @BUILD_SGF_UTILS_TRUE@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DO_SCROLLKEEPER_UPDATE_FALSE = @DO_SCROLLKEEPER_UPDATE_FALSE@ DO_SCROLLKEEPER_UPDATE_TRUE = @DO_SCROLLKEEPER_UPDATE_TRUE@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ GMSGFMT = @GMSGFMT@ HAVE_SCROLLKEEPER_FALSE = @HAVE_SCROLLKEEPER_FALSE@ HAVE_SCROLLKEEPER_TRUE = @HAVE_SCROLLKEEPER_TRUE@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ LDFLAGS = @LDFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ MAKEINFO = @MAKEINFO@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGMERGE = @MSGMERGE@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSUB = @POSUB@ QUARRY_GTHREAD_CFLAGS = @QUARRY_GTHREAD_CFLAGS@ QUARRY_GTHREAD_LIBS = @QUARRY_GTHREAD_LIBS@ QUARRY_GTK_CFLAGS = @QUARRY_GTK_CFLAGS@ QUARRY_GTK_DEPRECATED_FLAGS = @QUARRY_GTK_DEPRECATED_FLAGS@ QUARRY_GTK_LIBS = @QUARRY_GTK_LIBS@ QUARRY_WARNINGS = @QUARRY_WARNINGS@ QUARRY_WARNINGS_GTK = @QUARRY_WARNINGS_GTK@ RANLIB = @RANLIB@ REGISTER_MIME_TYPES_FALSE = @REGISTER_MIME_TYPES_FALSE@ REGISTER_MIME_TYPES_TRUE = @REGISTER_MIME_TYPES_TRUE@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ ac_ct_CC = @ac_ct_CC@ ac_ct_RANLIB = @ac_ct_RANLIB@ ac_ct_STRIP = @ac_ct_STRIP@ ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ datadir = @datadir@ exec_prefix = @exec_prefix@ have_scrollkeeper = @have_scrollkeeper@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localstatedir = @localstatedir@ mandir = @mandir@ oldincludedir = @oldincludedir@ prefix = @prefix@ program_transform_name = @program_transform_name@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ nobase_dist_theme_DATA = \ default/circle.svg \ default/cross.svg \ default/last-move.svg \ default/selected.svg \ default/square.svg \ default/triangle.svg \ \ default/theme.cfg \ \ bold/circle.svg \ bold/cross.svg \ bold/last-move.svg \ bold/selected.svg \ bold/square.svg \ bold/triangle.svg \ \ bold/theme.cfg \ \ filled/circle.svg \ filled/cross.svg \ filled/last-move.svg \ filled/selected.svg \ filled/square.svg \ filled/triangle.svg \ \ filled/theme.cfg themedir = \ $(datadir)/quarry/markup-themes DISTCLEANFILES = \ *~ \ \ default/*~ \ bold/*~ \ filled/*~ subdir = data/markup-themes ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 mkinstalldirs = $(SHELL) $(top_srcdir)/build/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = DIST_SOURCES = DATA = $(nobase_dist_theme_DATA) DIST_COMMON = $(nobase_dist_theme_DATA) $(srcdir)/Makefile.in \ Makefile.am all: all-am .SUFFIXES: $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4) cd $(top_srcdir) && \ $(AUTOMAKE) --foreign data/markup-themes/Makefile Makefile: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) uninstall-info-am: nobase_dist_themeDATA_INSTALL = $(install_sh_DATA) install-nobase_dist_themeDATA: $(nobase_dist_theme_DATA) @$(NORMAL_INSTALL) $(mkinstalldirs) $(DESTDIR)$(themedir) @list='$(nobase_dist_theme_DATA)'; for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ f="$$p"; \ echo " $(nobase_dist_themeDATA_INSTALL) $$d$$p $(DESTDIR)$(themedir)/$$f"; \ $(nobase_dist_themeDATA_INSTALL) $$d$$p $(DESTDIR)$(themedir)/$$f; \ done uninstall-nobase_dist_themeDATA: @$(NORMAL_UNINSTALL) @list='$(nobase_dist_theme_DATA)'; for p in $$list; do \ f="$$p"; \ echo " rm -f $(DESTDIR)$(themedir)/$$f"; \ rm -f $(DESTDIR)$(themedir)/$$f; \ done tags: TAGS TAGS: ctags: CTAGS CTAGS: DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = ../.. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) $(mkinstalldirs) $(distdir)/bold $(distdir)/default $(distdir)/filled @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ case $$file in \ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ esac; \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ dir="/$$dir"; \ $(mkinstalldirs) "$(distdir)$$dir"; \ else \ dir=''; \ fi; \ if test -d $$d/$$file; then \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(DATA) installdirs: $(mkinstalldirs) $(DESTDIR)$(themedir) install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -rm -f $(CONFIG_CLEAN_FILES) -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: info: info-am info-am: install-data-am: install-nobase_dist_themeDATA install-exec-am: install-info: install-info-am install-man: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-info-am uninstall-nobase_dist_themeDATA .PHONY: all all-am check check-am clean clean-generic distclean \ distclean-generic distdir dvi dvi-am info info-am install \ install-am install-data install-data-am install-exec \ install-exec-am install-info install-info-am install-man \ install-nobase_dist_themeDATA install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ pdf-am ps ps-am uninstall uninstall-am uninstall-info-am \ uninstall-nobase_dist_themeDATA # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: quarry-0.2.0/data/markup-themes/Makefile.am0000644000175000017500000000126110234244506017225 0ustar bartbart# Process this file with Automake to produce `Makefile.in'. nobase_dist_theme_DATA = \ default/circle.svg \ default/cross.svg \ default/last-move.svg \ default/selected.svg \ default/square.svg \ default/triangle.svg \ \ default/theme.cfg \ \ bold/circle.svg \ bold/cross.svg \ bold/last-move.svg \ bold/selected.svg \ bold/square.svg \ bold/triangle.svg \ \ bold/theme.cfg \ \ filled/circle.svg \ filled/cross.svg \ filled/last-move.svg \ filled/selected.svg \ filled/square.svg \ filled/triangle.svg \ \ filled/theme.cfg themedir = \ $(datadir)/quarry/markup-themes DISTCLEANFILES = \ *~ \ \ default/*~ \ bold/*~ \ filled/*~ quarry-0.2.0/data/textures/0000755000175000017500000000000010530620454014271 5ustar bartbartquarry-0.2.0/data/textures/Makefile.in0000644000175000017500000002177110425150132016340 0ustar bartbart# Makefile.in generated by automake 1.7.9 from Makefile.am. # @configure_input@ # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 # Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # Process this file with Automake to produce `Makefile.in'. srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = ../.. am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : host_triplet = @host@ ACLOCAL = @ACLOCAL@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BUILD_SGF_UTILS_FALSE = @BUILD_SGF_UTILS_FALSE@ BUILD_SGF_UTILS_TRUE = @BUILD_SGF_UTILS_TRUE@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DO_SCROLLKEEPER_UPDATE_FALSE = @DO_SCROLLKEEPER_UPDATE_FALSE@ DO_SCROLLKEEPER_UPDATE_TRUE = @DO_SCROLLKEEPER_UPDATE_TRUE@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ GMSGFMT = @GMSGFMT@ HAVE_SCROLLKEEPER_FALSE = @HAVE_SCROLLKEEPER_FALSE@ HAVE_SCROLLKEEPER_TRUE = @HAVE_SCROLLKEEPER_TRUE@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ LDFLAGS = @LDFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ MAKEINFO = @MAKEINFO@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGMERGE = @MSGMERGE@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSUB = @POSUB@ QUARRY_GTHREAD_CFLAGS = @QUARRY_GTHREAD_CFLAGS@ QUARRY_GTHREAD_LIBS = @QUARRY_GTHREAD_LIBS@ QUARRY_GTK_CFLAGS = @QUARRY_GTK_CFLAGS@ QUARRY_GTK_DEPRECATED_FLAGS = @QUARRY_GTK_DEPRECATED_FLAGS@ QUARRY_GTK_LIBS = @QUARRY_GTK_LIBS@ QUARRY_WARNINGS = @QUARRY_WARNINGS@ QUARRY_WARNINGS_GTK = @QUARRY_WARNINGS_GTK@ RANLIB = @RANLIB@ REGISTER_MIME_TYPES_FALSE = @REGISTER_MIME_TYPES_FALSE@ REGISTER_MIME_TYPES_TRUE = @REGISTER_MIME_TYPES_TRUE@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ ac_ct_CC = @ac_ct_CC@ ac_ct_RANLIB = @ac_ct_RANLIB@ ac_ct_STRIP = @ac_ct_STRIP@ ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ datadir = @datadir@ exec_prefix = @exec_prefix@ have_scrollkeeper = @have_scrollkeeper@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localstatedir = @localstatedir@ mandir = @mandir@ oldincludedir = @oldincludedir@ prefix = @prefix@ program_transform_name = @program_transform_name@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ TEXTURES = \ wood1.jpg \ wood2.jpg texturesdir = $(pkgdatadir)/textures textures_DATA = $(TEXTURES) EXTRA_DIST = $(TEXTURES) DISTCLEANFILES = *~ subdir = data/textures ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 mkinstalldirs = $(SHELL) $(top_srcdir)/build/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = DIST_SOURCES = DATA = $(textures_DATA) DIST_COMMON = $(srcdir)/Makefile.in Makefile.am all: all-am .SUFFIXES: $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4) cd $(top_srcdir) && \ $(AUTOMAKE) --foreign data/textures/Makefile Makefile: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) uninstall-info-am: texturesDATA_INSTALL = $(INSTALL_DATA) install-texturesDATA: $(textures_DATA) @$(NORMAL_INSTALL) $(mkinstalldirs) $(DESTDIR)$(texturesdir) @list='$(textures_DATA)'; for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ f="`echo $$p | sed -e 's|^.*/||'`"; \ echo " $(texturesDATA_INSTALL) $$d$$p $(DESTDIR)$(texturesdir)/$$f"; \ $(texturesDATA_INSTALL) $$d$$p $(DESTDIR)$(texturesdir)/$$f; \ done uninstall-texturesDATA: @$(NORMAL_UNINSTALL) @list='$(textures_DATA)'; for p in $$list; do \ f="`echo $$p | sed -e 's|^.*/||'`"; \ echo " rm -f $(DESTDIR)$(texturesdir)/$$f"; \ rm -f $(DESTDIR)$(texturesdir)/$$f; \ done tags: TAGS TAGS: ctags: CTAGS CTAGS: DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = ../.. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ case $$file in \ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ esac; \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ dir="/$$dir"; \ $(mkinstalldirs) "$(distdir)$$dir"; \ else \ dir=''; \ fi; \ if test -d $$d/$$file; then \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(DATA) installdirs: $(mkinstalldirs) $(DESTDIR)$(texturesdir) install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -rm -f $(CONFIG_CLEAN_FILES) -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: info: info-am info-am: install-data-am: install-texturesDATA install-exec-am: install-info: install-info-am install-man: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-info-am uninstall-texturesDATA .PHONY: all all-am check check-am clean clean-generic distclean \ distclean-generic distdir dvi dvi-am info info-am install \ install-am install-data install-data-am install-exec \ install-exec-am install-info install-info-am install-man \ install-strip install-texturesDATA installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-generic pdf pdf-am ps ps-am uninstall \ uninstall-am uninstall-info-am uninstall-texturesDATA # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: quarry-0.2.0/data/textures/Makefile.am0000644000175000017500000000032510215115472016324 0ustar bartbart# Process this file with Automake to produce `Makefile.in'. TEXTURES = \ wood1.jpg \ wood2.jpg texturesdir = $(pkgdatadir)/textures textures_DATA = $(TEXTURES) EXTRA_DIST = $(TEXTURES) DISTCLEANFILES = *~ quarry-0.2.0/po/0000755000175000017500000000000010530402567012116 5ustar bartbartquarry-0.2.0/po/Makefile.in.in0000644000175000017500000003020510111665557014575 0ustar bartbart# Makefile for PO directory in any package using GNU gettext. # Copyright (C) 1995-1997, 2000-2004 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.14 PACKAGE = @PACKAGE@ VERSION = @VERSION@ SHELL = /bin/sh @SET_MAKE@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ datadir = @datadir@ localedir = $(datadir)/locale gettextsrcdir = $(datadir)/gettext/po INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ MKINSTALLDIRS = @MKINSTALLDIRS@ mkinstalldirs = $(SHELL) $(MKINSTALLDIRS) GMSGFMT = @GMSGFMT@ MSGFMT = @MSGFMT@ XGETTEXT = @XGETTEXT@ 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 $(DOMAIN).pot stamp-po \ $(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 -o $${lang}.gmo $${lang}.po"; \ cd $(srcdir) && rm -f $${lang}.gmo && $(GMSGFMT) -c --statistics -o t-$${lang}.gmo $${lang}.po && mv t-$${lang}.gmo $${lang}.gmo .sin.sed: sed -e '/^#/d' $< > t-$@ mv t-$@ $@ all: all-@USE_NLS@ all-yes: stamp-po all-no: # 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 -z "$(GMOFILES)" || $(MAKE) $(GMOFILES) @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 $(XGETTEXT) --default-domain=$(DOMAIN) --directory=$(top_srcdir) \ --add-comments=TRANSLATORS: $(XGETTEXT_OPTIONS) \ --files-from=$(srcdir)/POTFILES.in \ --copyright-holder='$(COPYRIGHT_HOLDER)' \ --msgid-bugs-address='$(MSGID_BUGS_ADDRESS)' 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) $${lang}.po $(DOMAIN).pot"; \ cd $(srcdir) && $(MSGMERGE_UPDATE) $${lang}.po $(DOMAIN).pot; \ 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 \ $(mkinstalldirs) $(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 $(mkinstalldirs) $(DESTDIR)$(datadir) @catalogs='$(CATALOGS)'; \ for cat in $$catalogs; do \ cat=`basename $$cat`; \ lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \ dir=$(localedir)/$$lang/LC_MESSAGES; \ $(mkinstalldirs) $(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 \ $(mkinstalldirs) $(DESTDIR)$(gettextsrcdir); \ else \ : ; \ fi installdirs-data-no: installdirs-data-yes: $(mkinstalldirs) $(DESTDIR)$(datadir) @catalogs='$(CATALOGS)'; \ for cat in $$catalogs; do \ cat=`basename $$cat`; \ lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \ dir=$(localedir)/$$lang/LC_MESSAGES; \ $(mkinstalldirs) $(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: $(DISTFILES) dists="$(DISTFILES)"; \ if test "$(PACKAGE)" = "gettext-tools"; then \ dists="$$dists Makevars.template"; \ 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); \ else \ cp -p $(srcdir)/$$file $(distdir); \ 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) $$lang.po $(DOMAIN).pot -o $$lang.new.po"; \ cd $(srcdir); \ if $(MSGMERGE) $$lang.po $(DOMAIN).pot -o $$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 "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) @: Makefile: Makefile.in.in $(top_builddir)/config.status @POMAKEFILEDEPS@ cd $(top_builddir) \ && CONFIG_FILES=$(subdir)/$@.in CONFIG_HEADERS= \ $(SHELL) ./config.status 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: quarry-0.2.0/po/remove-potcdate.sin0000644000175000017500000000066010111665704015730 0ustar bartbart# 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 } quarry-0.2.0/po/Makevars0000644000175000017500000000315210266014741013612 0ustar bartbartDOMAIN = $(PACKAGE) subdir = po top_builddir = .. # These options get passed to xgettext. XGETTEXT_OPTIONS = --keyword=_ --keyword=N_ --keyword=Q_ --from-code=UTF-8 # This is the copyright holder that gets inserted into the header of the # $(DOMAIN).pot file. Set this to the copyright holder of the surrounding # package. (Note that the msgstr strings, extracted from the package's # sources, belong to the copyright holder of the package.) Translators are # expected to transfer the copyright for their translations to this person # or entity, or to disclaim their copyright. The empty string stands for # the public domain; in this case the translators are expected to disclaim # their copyright. COPYRIGHT_HOLDER = Paul Pogonyshev # This is the email address or URL to which the translators shall report # bugs in the untranslated strings: # - Strings which are not entire sentences, see the maintainer guidelines # in the GNU gettext documentation, section 'Preparing Strings'. # - Strings which use unclear terms or require additional context to be # understood. # - Strings which make invalid assumptions about notation of date, time or # money. # - Pluralisation problems. # - Incorrect English spelling. # - Incorrect formatting. # It can be your email address, or a mailing list address where translators # can write to without being subscribed, or the URL of a web page through # which the translators can contact you. MSGID_BUGS_ADDRESS = quarry-dev@gna.org # This is the list of locale categories, beyond LC_MESSAGES, for which the # message catalogs shall be used. It is usually empty. EXTRA_LOCALE_CATEGORIES = quarry-0.2.0/po/POTFILES.in0000644000175000017500000000164110453305627013700 0ustar bartbart# Note that at least one file here (`src/board/games.c') is generated # at build-time. This means you can only update `quarry.pot' when # configured with build directory equal to source directory. # GTK+ interface files. src/gui-gtk/gtk-add-or-edit-label-dialog.c src/gui-gtk/gtk-color-button.c src/gui-gtk/gtk-control-center.c src/gui-gtk/gtk-file-dialog.c src/gui-gtk/gtk-game-info-dialog.c src/gui-gtk/gtk-games.c src/gui-gtk/gtk-goban-window.c src/gui-gtk/gtk-go-to-named-node-dialog.c src/gui-gtk/gtk-gtp-client-interface.c src/gui-gtk/gtk-new-game-dialog.c src/gui-gtk/gtk-new-game-record-dialog.c src/gui-gtk/gtk-parser-interface.c src/gui-gtk/gtk-preferences.c src/gui-gtk/gtk-resume-game-dialog.c src/gui-gtk/quarry-find-dialog.c src/gui-gtk/quarry-move-number-dialog.c src/gui-gtk/quarry-save-confirmation-dialog.c src/gui-gtk/quarry-stock.c # Board library files. src/board/board.c src/board/games.c src/board/go.c quarry-0.2.0/po/quarry.pot0000644000175000017500000013042610524132506014167 0ustar bartbart# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR Paul Pogonyshev # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: quarry-dev@gna.org\n" "POT-Creation-Date: 2006-11-07 18:33+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" #: src/gui-gtk/gtk-add-or-edit-label-dialog.c:73 msgid "" "Although board labels are not limited in length, it is better to use only " "one or two characters long labels. Longer labels will not be visible " "immediately or at all in most clients." msgstr "" #: src/gui-gtk/gtk-add-or-edit-label-dialog.c:87 msgid "Label _text:" msgstr "" #: src/gui-gtk/gtk-color-button.c:581 msgid "Pick a Color" msgstr "" #: src/gui-gtk/gtk-control-center.c:64 msgid "Quarry Control Center" msgstr "" #: src/gui-gtk/gtk-control-center.c:80 msgid "Ne_w Game Record" msgstr "" #: src/gui-gtk/gtk-control-center.c:96 msgid "_Resume Game" msgstr "" #: src/gui-gtk/gtk-file-dialog.c:281 msgid "" "Note that all information in the existing file will be lost permanently if " "you choose to overwrite it." msgstr "" #: src/gui-gtk/gtk-file-dialog.c:284 #, c-format msgid "" "File named `%s' already exists. Do you want to overwrite it with the one you " "are saving?" msgstr "" #: src/gui-gtk/gtk-game-info-dialog.c:231 #: src/gui-gtk/gtk-resume-game-dialog.c:325 msgid "N_ame:" msgstr "" #: src/gui-gtk/gtk-game-info-dialog.c:231 #: src/gui-gtk/gtk-resume-game-dialog.c:324 msgid "_Name:" msgstr "" #: src/gui-gtk/gtk-game-info-dialog.c:238 msgid "Team:" msgstr "" #: src/gui-gtk/gtk-game-info-dialog.c:244 msgid "Rank:" msgstr "" #: src/gui-gtk/gtk-game-info-dialog.c:256 #: src/gui-gtk/gtk-new-game-dialog.c:226 #: src/gui-gtk/gtk-resume-game-dialog.c:364 msgid "Black Player" msgstr "" #: src/gui-gtk/gtk-game-info-dialog.c:256 #: src/gui-gtk/gtk-new-game-dialog.c:226 #: src/gui-gtk/gtk-resume-game-dialog.c:364 msgid "White Player" msgstr "" #: src/gui-gtk/gtk-game-info-dialog.c:270 msgid "_Game name:" msgstr "" #: src/gui-gtk/gtk-game-info-dialog.c:273 msgid "_Place:" msgstr "" #: src/gui-gtk/gtk-game-info-dialog.c:277 msgid "Da_te:" msgstr "" #: src/gui-gtk/gtk-game-info-dialog.c:280 msgid "_Event:" msgstr "" #: src/gui-gtk/gtk-game-info-dialog.c:284 msgid "R_ound:" msgstr "" #: src/gui-gtk/gtk-game-info-dialog.c:295 #: src/gui-gtk/gtk-game-info-dialog.c:535 #: src/gui-gtk/gtk-game-info-dialog.c:541 msgid "Game Information" msgstr "" #: src/gui-gtk/gtk-game-info-dialog.c:298 msgid "Rule _set:" msgstr "" #: src/gui-gtk/gtk-game-info-dialog.c:324 #: src/gui-gtk/gtk-new-game-record-dialog.c:187 msgid "Han_dicap:" msgstr "" #: src/gui-gtk/gtk-game-info-dialog.c:347 #: src/gui-gtk/gtk-new-game-dialog.c:574 #: src/gui-gtk/gtk-new-game-record-dialog.c:231 msgid "_Komi:" msgstr "" #: src/gui-gtk/gtk-game-info-dialog.c:374 #: src/gui-gtk/gtk-new-game-dialog.c:444 msgid "_Main time:" msgstr "" #: src/gui-gtk/gtk-game-info-dialog.c:386 msgid "O_vertime:" msgstr "" #: src/gui-gtk/gtk-game-info-dialog.c:397 #: src/gui-gtk/gtk-new-game-dialog.c:602 msgid "Game Rules" msgstr "" #: src/gui-gtk/gtk-game-info-dialog.c:412 msgid "General" msgstr "" #: src/gui-gtk/gtk-game-info-dialog.c:415 msgid "Game re_sult:" msgstr "" #: src/gui-gtk/gtk-game-info-dialog.c:419 msgid "_Opening played:" msgstr "" #: src/gui-gtk/gtk-game-info-dialog.c:449 msgid "Comment / _description:" msgstr "" #: src/gui-gtk/gtk-game-info-dialog.c:463 msgid "Description & Result" msgstr "" #: src/gui-gtk/gtk-game-info-dialog.c:466 msgid "Co_pyright string:" msgstr "" #: src/gui-gtk/gtk-game-info-dialog.c:470 msgid "_Annotator:" msgstr "" #: src/gui-gtk/gtk-game-info-dialog.c:474 msgid "_Source:" msgstr "" #: src/gui-gtk/gtk-game-info-dialog.c:478 msgid "_Entered by:" msgstr "" #: src/gui-gtk/gtk-game-info-dialog.c:488 msgid "Copyright & Credits" msgstr "" #: src/gui-gtk/gtk-game-info-dialog.c:502 msgid "Game Record" msgstr "" #: src/gui-gtk/gtk-games.c:39 msgid "_Go" msgstr "" #: src/gui-gtk/gtk-games.c:40 msgid "_Amazons" msgstr "" #: src/gui-gtk/gtk-games.c:41 msgid "_Reversi" msgstr "" #: src/gui-gtk/gtk-games.c:45 msgid "Go Rules" msgstr "" #: src/gui-gtk/gtk-games.c:46 msgid "Amazons Rules" msgstr "" #: src/gui-gtk/gtk-games.c:47 msgid "Reversi Rules" msgstr "" #: src/gui-gtk/gtk-games.c:180 msgid "Board _size:" msgstr "" #: src/gui-gtk/gtk-goban-window.c:460 msgid "Open" msgstr "" #: src/gui-gtk/gtk-goban-window.c:460 msgid "Open a game record" msgstr "" #: src/gui-gtk/gtk-goban-window.c:465 msgid "Save" msgstr "" #: src/gui-gtk/gtk-goban-window.c:465 msgid "Save the current file" msgstr "" #: src/gui-gtk/gtk-goban-window.c:470 src/gui-gtk/gtk-goban-window.c:2025 msgid "Find" msgstr "" #: src/gui-gtk/gtk-goban-window.c:470 msgid "Search for a string in comments" msgstr "" #: src/gui-gtk/gtk-goban-window.c:475 msgid "Info" msgstr "" #: src/gui-gtk/gtk-goban-window.c:475 msgid "View and edit game information" msgstr "" #: src/gui-gtk/gtk-goban-window.c:481 msgid "Undo" msgstr "" #: src/gui-gtk/gtk-goban-window.c:481 msgid "Undo the last action" msgstr "" #: src/gui-gtk/gtk-goban-window.c:486 msgid "Redo" msgstr "" #: src/gui-gtk/gtk-goban-window.c:486 msgid "Redo the last undone action" msgstr "" #: src/gui-gtk/gtk-goban-window.c:491 msgid "Delete" msgstr "" #: src/gui-gtk/gtk-goban-window.c:491 msgid "Delete the current node" msgstr "" #: src/gui-gtk/gtk-goban-window.c:497 msgid "Root" msgstr "" #: src/gui-gtk/gtk-goban-window.c:497 msgid "Go to the root node" msgstr "" #: src/gui-gtk/gtk-goban-window.c:502 msgid "Back" msgstr "" #: src/gui-gtk/gtk-goban-window.c:502 msgid "Go to the previous node" msgstr "" #: src/gui-gtk/gtk-goban-window.c:507 msgid "Forward" msgstr "" #: src/gui-gtk/gtk-goban-window.c:507 msgid "Go to the next node" msgstr "" #: src/gui-gtk/gtk-goban-window.c:512 msgid "End" msgstr "" #: src/gui-gtk/gtk-goban-window.c:512 msgid "Go to the current variation's last node" msgstr "" #: src/gui-gtk/gtk-goban-window.c:518 msgid "Previous" msgstr "" #: src/gui-gtk/gtk-goban-window.c:518 msgid "Switch to the previous variation" msgstr "" #: src/gui-gtk/gtk-goban-window.c:524 msgid "Next" msgstr "" #: src/gui-gtk/gtk-goban-window.c:524 msgid "Switch to the next variation" msgstr "" #: src/gui-gtk/gtk-goban-window.c:629 msgid "/_File" msgstr "" #: src/gui-gtk/gtk-goban-window.c:630 msgid "/File/_New Game..." msgstr "" #: src/gui-gtk/gtk-goban-window.c:633 msgid "/File/Ne_w Game Record..." msgstr "" #: src/gui-gtk/gtk-goban-window.c:636 src/gui-gtk/gtk-goban-window.c:653 #: src/gui-gtk/gtk-goban-window.c:661 msgid "/File/" msgstr "" #: src/gui-gtk/gtk-goban-window.c:638 msgid "/File/_Open..." msgstr "" #: src/gui-gtk/gtk-goban-window.c:641 msgid "/File/_Resume Game..." msgstr "" #: src/gui-gtk/gtk-goban-window.c:645 msgid "/File/_Export..." msgstr "" #: src/gui-gtk/gtk-goban-window.c:646 msgid "/File/Export.../_ASCII Diagram" msgstr "" #: src/gui-gtk/gtk-goban-window.c:649 msgid "/File/Export.../_Sensei's Library Diagram" msgstr "" #: src/gui-gtk/gtk-goban-window.c:655 msgid "/File/_Save" msgstr "" #: src/gui-gtk/gtk-goban-window.c:658 msgid "/File/Save _As..." msgstr "" #: src/gui-gtk/gtk-goban-window.c:663 msgid "/File/_Close" msgstr "" #: src/gui-gtk/gtk-goban-window.c:666 msgid "/File/_Quit" msgstr "" #: src/gui-gtk/gtk-goban-window.c:671 msgid "/_Edit" msgstr "" #: src/gui-gtk/gtk-goban-window.c:672 msgid "/Edit/_Undo" msgstr "" #: src/gui-gtk/gtk-goban-window.c:675 msgid "/Edit/_Redo" msgstr "" #: src/gui-gtk/gtk-goban-window.c:678 src/gui-gtk/gtk-goban-window.c:695 #: src/gui-gtk/gtk-goban-window.c:739 src/gui-gtk/gtk-goban-window.c:747 #: src/gui-gtk/gtk-goban-window.c:767 src/gui-gtk/gtk-goban-window.c:778 #: src/gui-gtk/gtk-goban-window.c:783 msgid "/Edit/" msgstr "" #: src/gui-gtk/gtk-goban-window.c:680 msgid "/Edit/Cu_t" msgstr "" #: src/gui-gtk/gtk-goban-window.c:683 msgid "/Edit/_Copy" msgstr "" #: src/gui-gtk/gtk-goban-window.c:686 msgid "/Edit/_Paste" msgstr "" #: src/gui-gtk/gtk-goban-window.c:689 msgid "/Edit/_Delete Node" msgstr "" #: src/gui-gtk/gtk-goban-window.c:692 msgid "/Edit/Delete Node's C_hildren" msgstr "" #: src/gui-gtk/gtk-goban-window.c:698 msgid "/Edit/T_ools" msgstr "" #: src/gui-gtk/gtk-goban-window.c:699 msgid "/Edit/Tools/_Move Tool" msgstr "" #: src/gui-gtk/gtk-goban-window.c:702 msgid "/Edit/Tools/_Setup Tool" msgstr "" #: src/gui-gtk/gtk-goban-window.c:705 src/gui-gtk/gtk-goban-window.c:722 #: src/gui-gtk/gtk-goban-window.c:730 msgid "/Edit/Tools/" msgstr "" #: src/gui-gtk/gtk-goban-window.c:707 msgid "/Edit/Tools/C_ross Markup" msgstr "" #: src/gui-gtk/gtk-goban-window.c:710 msgid "/Edit/Tools/_Circle Markup" msgstr "" #: src/gui-gtk/gtk-goban-window.c:713 msgid "/Edit/Tools/S_quare Markup" msgstr "" #: src/gui-gtk/gtk-goban-window.c:716 msgid "/Edit/Tools/_Triangle Markup" msgstr "" #: src/gui-gtk/gtk-goban-window.c:719 msgid "/Edit/Tools/S_elected Markup" msgstr "" #: src/gui-gtk/gtk-goban-window.c:724 msgid "/Edit/Tools/_Label Tool" msgstr "" #: src/gui-gtk/gtk-goban-window.c:727 msgid "/Edit/Tools/_Number Tool" msgstr "" #: src/gui-gtk/gtk-goban-window.c:732 msgid "/Edit/Tools/Scori_ng Tool" msgstr "" #: src/gui-gtk/gtk-goban-window.c:736 msgid "/Edit/_Add Empty Node" msgstr "" #: src/gui-gtk/gtk-goban-window.c:741 msgid "/Edit/Move _Branch Up" msgstr "" #: src/gui-gtk/gtk-goban-window.c:744 msgid "/Edit/Move Branch Do_wn" msgstr "" #: src/gui-gtk/gtk-goban-window.c:749 msgid "/Edit/Edit Node _Name" msgstr "" #: src/gui-gtk/gtk-goban-window.c:752 msgid "/Edit/Set _Move Number" msgstr "" #: src/gui-gtk/gtk-goban-window.c:756 msgid "/Edit/P_layer to Move" msgstr "" #: src/gui-gtk/gtk-goban-window.c:757 msgid "/Edit/Player to Move/_White" msgstr "" #: src/gui-gtk/gtk-goban-window.c:760 msgid "/Edit/Player to Move/_Black" msgstr "" #: src/gui-gtk/gtk-goban-window.c:763 msgid "/Edit/Player to Move/By Game _Rules" msgstr "" #: src/gui-gtk/gtk-goban-window.c:769 msgid "/Edit/_Find" msgstr "" #: src/gui-gtk/gtk-goban-window.c:772 msgid "/Edit/Find Ne_xt" msgstr "" #: src/gui-gtk/gtk-goban-window.c:775 msgid "/Edit/Find Pre_vious" msgstr "" #: src/gui-gtk/gtk-goban-window.c:780 msgid "/Edit/Game _Information" msgstr "" #: src/gui-gtk/gtk-goban-window.c:785 msgid "/Edit/Pr_eferences" msgstr "" #: src/gui-gtk/gtk-goban-window.c:790 msgid "/_View" msgstr "" #: src/gui-gtk/gtk-goban-window.c:791 msgid "/View/_Main Toolbar" msgstr "" #: src/gui-gtk/gtk-goban-window.c:794 msgid "/View/_Editing Toolbar" msgstr "" #: src/gui-gtk/gtk-goban-window.c:797 msgid "/View/_Navigation Toolbar" msgstr "" #: src/gui-gtk/gtk-goban-window.c:800 src/gui-gtk/gtk-goban-window.c:805 #: src/gui-gtk/gtk-goban-window.c:813 msgid "/View/" msgstr "" #: src/gui-gtk/gtk-goban-window.c:802 msgid "/View/_Game Action Buttons" msgstr "" #: src/gui-gtk/gtk-goban-window.c:807 msgid "/View/Game _Tree" msgstr "" #: src/gui-gtk/gtk-goban-window.c:810 msgid "/View/_Recenter on Current Node" msgstr "" #: src/gui-gtk/gtk-goban-window.c:815 msgid "/View/_Control Center" msgstr "" #: src/gui-gtk/gtk-goban-window.c:820 msgid "/_Play" msgstr "" #: src/gui-gtk/gtk-goban-window.c:821 msgid "/Play/_Pass" msgstr "" #: src/gui-gtk/gtk-goban-window.c:824 src/gui-gtk/gtk-goban-window.c:829 msgid "/Play/" msgstr "" #: src/gui-gtk/gtk-goban-window.c:826 msgid "/Play/_Resign" msgstr "" #: src/gui-gtk/gtk-goban-window.c:831 msgid "/Play/_Adjourn Game" msgstr "" #: src/gui-gtk/gtk-goban-window.c:836 msgid "/_Go" msgstr "" #: src/gui-gtk/gtk-goban-window.c:837 msgid "/Go/_Previous Node" msgstr "" #: src/gui-gtk/gtk-goban-window.c:840 msgid "/Go/_Next Node" msgstr "" #: src/gui-gtk/gtk-goban-window.c:843 msgid "/Go/Ten Nodes _Backward" msgstr "" #: src/gui-gtk/gtk-goban-window.c:846 msgid "/Go/Ten Nodes _Forward" msgstr "" #: src/gui-gtk/gtk-goban-window.c:849 src/gui-gtk/gtk-goban-window.c:857 #: src/gui-gtk/gtk-goban-window.c:867 msgid "/Go/" msgstr "" #: src/gui-gtk/gtk-goban-window.c:851 msgid "/Go/_Root Node" msgstr "" #: src/gui-gtk/gtk-goban-window.c:854 msgid "/Go/Variation _Last Node" msgstr "" #: src/gui-gtk/gtk-goban-window.c:859 msgid "/Go/Pre_vious Variation" msgstr "" #: src/gui-gtk/gtk-goban-window.c:862 msgid "/Go/Ne_xt Variation" msgstr "" #: src/gui-gtk/gtk-goban-window.c:868 msgid "/Go/_Go to Named Node..." msgstr "" #: src/gui-gtk/gtk-goban-window.c:874 msgid "/_Help" msgstr "" #: src/gui-gtk/gtk-goban-window.c:875 msgid "/Help/_Contents" msgstr "" #: src/gui-gtk/gtk-goban-window.c:878 msgid "/Help/_About" msgstr "" #: src/gui-gtk/gtk-goban-window.c:884 msgid "/Move Tool" msgstr "" #: src/gui-gtk/gtk-goban-window.c:885 msgid "/Setup Tool" msgstr "" #: src/gui-gtk/gtk-goban-window.c:888 msgid "/Cross Markup" msgstr "" #: src/gui-gtk/gtk-goban-window.c:889 msgid "/Circle Markup" msgstr "" #: src/gui-gtk/gtk-goban-window.c:890 msgid "/Square Markup" msgstr "" #: src/gui-gtk/gtk-goban-window.c:891 msgid "/Triangle Markup" msgstr "" #: src/gui-gtk/gtk-goban-window.c:892 msgid "/Selected Markup" msgstr "" #: src/gui-gtk/gtk-goban-window.c:895 msgid "/Label Tool" msgstr "" #: src/gui-gtk/gtk-goban-window.c:896 msgid "/Number Tool" msgstr "" #: src/gui-gtk/gtk-goban-window.c:899 msgid "/Scoring Tool" msgstr "" #: src/gui-gtk/gtk-goban-window.c:964 msgid "Black" msgstr "" #: src/gui-gtk/gtk-goban-window.c:964 msgid "White" msgstr "" #: src/gui-gtk/gtk-goban-window.c:992 msgid "Pass" msgstr "" #: src/gui-gtk/gtk-goban-window.c:998 msgid "Resign" msgstr "" #: src/gui-gtk/gtk-goban-window.c:1438 #, c-format msgid "Save changes to game record `%s' before closing?" msgstr "" #: src/gui-gtk/gtk-goban-window.c:1447 msgid "Save changes to the untitled game record before closing?" msgstr "" #. TRANSLATORS: Width of this string in default font is used to #. determine the minimal width of the right board window side. #: src/gui-gtk/gtk-goban-window.c:1522 msgid "A good width for the right side to have." msgstr "" #. TRANSLATORS: It can never be 1 stone, always at least 2. #: src/gui-gtk/gtk-goban-window.c:1582 #, c-format msgid "" "Please set up %d (or less)\n" "stone of free handicap" msgid_plural "" "Please set up %d (or less)\n" "stones of free handicap" msgstr[0] "" msgstr[1] "" #: src/gui-gtk/gtk-goban-window.c:1774 msgid "Adjourn & Save As..." msgstr "" #: src/gui-gtk/gtk-goban-window.c:1774 msgid "Save As..." msgstr "" #: src/gui-gtk/gtk-goban-window.c:1923 #, c-format msgid "Error saving to file `%s'" msgstr "" #: src/gui-gtk/gtk-goban-window.c:1937 msgid "" "You can later resume the game by pressing the `Resume Game' button in Quarry " "Control Center, or selecting `Resume Game' item from the `File' menu." msgstr "" #: src/gui-gtk/gtk-goban-window.c:1943 #, c-format msgid "The game is adjourned and saved in file `%s'" msgstr "" #: src/gui-gtk/gtk-goban-window.c:1962 msgid "ASCII diagram has been exported to clipboard" msgstr "" #: src/gui-gtk/gtk-goban-window.c:1975 msgid "Sensei's Library diagram has been exported to clipboard" msgstr "" #: src/gui-gtk/gtk-goban-window.c:1990 msgid "" "You can usually paste the diagram in another application using `Ctrl+C' key " "combination or by selecting appropriate menu item." msgstr "" #: src/gui-gtk/gtk-goban-window.c:2446 msgid "Sorry, there are no named nodes in this game tree" msgstr "" #: src/gui-gtk/gtk-goban-window.c:2470 msgid "A GUI program for Go, Amazons and Reversi board games" msgstr "" #: src/gui-gtk/gtk-goban-window.c:2472 msgid "Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev and others" msgstr "" #: src/gui-gtk/gtk-goban-window.c:2488 msgid "About Quarry" msgstr "" #: src/gui-gtk/gtk-goban-window.c:2931 msgid "Really resign this game?" msgstr "" #: src/gui-gtk/gtk-goban-window.c:2935 msgid "_Resign" msgstr "" #: src/gui-gtk/gtk-goban-window.c:3524 msgid "Edit Board Label" msgstr "" #: src/gui-gtk/gtk-goban-window.c:3527 msgid "Add Board Label" msgstr "" #: src/gui-gtk/gtk-goban-window.c:4026 #, c-format msgid "%s (W) vs. %s" msgstr "" #: src/gui-gtk/gtk-goban-window.c:4050 msgid "Unnamed Game" msgstr "" #: src/gui-gtk/gtk-goban-window.c:4055 msgid "modified" msgstr "" #: src/gui-gtk/gtk-goban-window.c:4088 msgid "[unknown]" msgstr "" #: src/gui-gtk/gtk-goban-window.c:4121 src/gui-gtk/gtk-goban-window.c:4126 #, c-format msgid "%d capture" msgid_plural "%d captures" msgstr[0] "" msgstr[1] "" #: src/gui-gtk/gtk-goban-window.c:4136 #, c-format msgid "%s %s %.*f komi" msgstr "" #: src/gui-gtk/gtk-goban-window.c:4147 #, c-format msgid "%s %s %d komi" msgid_plural "%s %s %d komi" msgstr[0] "" msgstr[1] "" #: src/gui-gtk/gtk-goban-window.c:4163 src/gui-gtk/gtk-goban-window.c:4166 #, c-format msgid "%d disk" msgid_plural "%d disks" msgstr[0] "" msgstr[1] "" #: src/gui-gtk/gtk-goban-window.c:4197 #, c-format msgid "Move %d: " msgstr "" #: src/gui-gtk/gtk-goban-window.c:4201 #, c-format msgid "Last move: %u, " msgstr "" #. TRANSLATORS: This is an #. abbreviation of `Black'. #: src/gui-gtk/gtk-goban-window.c:4208 msgid "B " msgstr "" #. TRANSLATORS: This is an #. abbreviation of `White'. #: src/gui-gtk/gtk-goban-window.c:4211 msgid "W " msgstr "" #: src/gui-gtk/gtk-goban-window.c:4212 msgid "pass" msgstr "" #: src/gui-gtk/gtk-goban-window.c:4215 msgid "Game beginning" msgstr "" #: src/gui-gtk/gtk-goban-window.c:4233 msgid "; black to play" msgstr "" #: src/gui-gtk/gtk-goban-window.c:4233 msgid "; white to play" msgstr "" #: src/gui-gtk/gtk-goban-window.c:4236 msgid "; game over" msgstr "" #: src/gui-gtk/gtk-goban-window.c:4243 msgid "Black wins" msgstr "" #: src/gui-gtk/gtk-goban-window.c:4246 msgid "White wins" msgstr "" #: src/gui-gtk/gtk-goban-window.c:4250 msgid "Black wins by forfeit" msgstr "" #: src/gui-gtk/gtk-goban-window.c:4253 msgid "White wins by forfeit" msgstr "" #: src/gui-gtk/gtk-goban-window.c:4257 msgid "White resigns" msgstr "" #: src/gui-gtk/gtk-goban-window.c:4260 msgid "Black resigns" msgstr "" #: src/gui-gtk/gtk-goban-window.c:4272 msgid "White runs out of time and loses" msgstr "" #: src/gui-gtk/gtk-goban-window.c:4276 msgid "Black runs out of time and loses" msgstr "" #: src/gui-gtk/gtk-goban-window.c:4280 msgid "Game is draw" msgstr "" #: src/gui-gtk/gtk-goban-window.c:4499 msgid "By Game _Rules (Game Over)" msgstr "" #: src/gui-gtk/gtk-goban-window.c:4503 msgid "By Game _Rules (Black)" msgstr "" #: src/gui-gtk/gtk-goban-window.c:4507 msgid "By Game _Rules (White)" msgstr "" #: src/gui-gtk/gtk-goban-window.c:4551 msgid "insert node name here" msgstr "" #: src/gui-gtk/gtk-goban-window.c:4952 msgid "Set Move Number" msgstr "" #. TRANSLATORS: Note that game name will be in `normal' form. #: src/gui-gtk/gtk-goban-window.c:5062 #, c-format msgid "" "GTP engine `%s' reported it could handle %s game, but failed to initialize " "itself for it" msgstr "" #: src/gui-gtk/gtk-goban-window.c:5070 #, c-format msgid "GTP engine `%s' cannot handle %dx%d board size, sorry" msgstr "" #: src/gui-gtk/gtk-goban-window.c:5080 #, c-format msgid "GTP engine `%s' failed to clean the board" msgstr "" #: src/gui-gtk/gtk-goban-window.c:5086 #, c-format msgid "" "GTP engine `%s' failed to set initial time limits (it could ignore them, but " "not fail)" msgstr "" #: src/gui-gtk/gtk-goban-window.c:5094 #, c-format msgid "GTP engine `%s' failed to set handicap stones on board" msgstr "" #: src/gui-gtk/gtk-goban-window.c:5108 msgid "This is an engine error. You may want to report it to engine authors." msgstr "" #: src/gui-gtk/gtk-goban-window.c:5392 msgid "GTP engine is scoring..." msgstr "" #: src/gui-gtk/gtk-goban-window.c:5771 msgid "" "Unable to paste game record fragment from clipboard since it is not intended " "for pasting" msgstr "" #: src/gui-gtk/gtk-goban-window.c:5774 msgid "" "Clipboard SGF probably contains more than one game tree or not a single " "child of the root of the only game tree." msgstr "" #: src/gui-gtk/gtk-goban-window.c:5778 msgid "Unable to paste game record fragment from clipboard" msgstr "" #. TRANSLATORS: This message is shown if you e.g. copy a part of #. 13x13 game tree and try to paste it into a 19x19 game tree; or #. copy a part of a Reversi game tree and try to paste it into a #. Go game tree. #: src/gui-gtk/gtk-goban-window.c:5784 msgid "Clipboard game record fragment must be of different game or board size." msgstr "" #: src/gui-gtk/gtk-goban-window.c:5788 msgid "Clipboard contains an invalid game record fragment (SGF)" msgstr "" #: src/gui-gtk/gtk-goban-window.c:5937 msgid "" "Please select dead stones\n" "to score the game" msgstr "" #: src/gui-gtk/gtk-go-to-named-node-dialog.c:135 msgid "Go to Named Node" msgstr "" #: src/gui-gtk/gtk-go-to-named-node-dialog.c:150 msgid "Node _name:" msgstr "" #: src/gui-gtk/gtk-go-to-named-node-dialog.c:156 msgid "Node comment:" msgstr "" #: src/gui-gtk/gtk-go-to-named-node-dialog.c:331 msgid "comment|Empty" msgstr "" #: src/gui-gtk/gtk-go-to-named-node-dialog.c:334 msgid "There is no such node" msgstr "" #: src/gui-gtk/gtk-gtp-client-interface.c:282 msgid "Engine hung up" msgstr "" #: src/gui-gtk/gtk-gtp-client-interface.c:391 msgid "* ERROR: wrong response format\n" msgstr "" #: src/gui-gtk/gtk-gtp-client-interface.c:395 msgid "* WARNING: unexpected response:\n" msgstr "" #: src/gui-gtk/gtk-gtp-client-interface.c:399 msgid "* ERROR: unrecognized response line:\n" msgstr "" #: src/gui-gtk/gtk-gtp-client-interface.c:404 #, c-format msgid "* ERROR: mismatched ID (%d expected):\n" msgstr "" #: src/gui-gtk/gtk-gtp-client-interface.c:408 msgid "* ERROR: unexpected ID in response (the command had none):\n" msgstr "" #. TRANSLATORS: Don't put ellipsis here, this string will most #. often go to fixed-width font terminals. #: src/gui-gtk/gtk-gtp-client-interface.c:415 msgid "* WARNING: future GTP version, I don't know about it...\n" msgstr "" #: src/gui-gtk/gtk-new-game-dialog.c:98 msgid "" "Note that most GTP engines support only one game. Hence certain game / " "computer player combinations may be not possible to play." msgstr "" #: src/gui-gtk/gtk-new-game-dialog.c:102 msgid "Fi_xed handicap:" msgstr "" #: src/gui-gtk/gtk-new-game-dialog.c:102 msgid "_Free handicap:" msgstr "" #: src/gui-gtk/gtk-new-game-dialog.c:105 msgid "No limit" msgstr "" #: src/gui-gtk/gtk-new-game-dialog.c:105 msgid "Limited time for entire game" msgstr "" #: src/gui-gtk/gtk-new-game-dialog.c:106 msgid "Limited time per move" msgstr "" #: src/gui-gtk/gtk-new-game-dialog.c:106 msgid "Canadian overtime" msgstr "" #: src/gui-gtk/gtk-new-game-dialog.c:124 msgid "New Game" msgstr "" #: src/gui-gtk/gtk-new-game-dialog.c:167 #: src/gui-gtk/gtk-new-game-record-dialog.c:132 msgid "Game" msgstr "" #: src/gui-gtk/gtk-new-game-dialog.c:173 #: src/gui-gtk/gtk-resume-game-dialog.c:307 msgid "Hu_man" msgstr "" #: src/gui-gtk/gtk-new-game-dialog.c:173 #: src/gui-gtk/gtk-resume-game-dialog.c:308 msgid "Com_puter" msgstr "" #: src/gui-gtk/gtk-new-game-dialog.c:174 #: src/gui-gtk/gtk-resume-game-dialog.c:308 msgid "H_uman" msgstr "" #: src/gui-gtk/gtk-new-game-dialog.c:174 msgid "C_omputer" msgstr "" #: src/gui-gtk/gtk-new-game-dialog.c:238 msgid "Manage _Engine List" msgstr "" #: src/gui-gtk/gtk-new-game-dialog.c:258 msgid "_Swap" msgstr "" #: src/gui-gtk/gtk-new-game-dialog.c:287 msgid "Game & Players" msgstr "" #: src/gui-gtk/gtk-new-game-dialog.c:362 msgid "Time control _type:" msgstr "" #: src/gui-gtk/gtk-new-game-dialog.c:384 msgid "Time Limit" msgstr "" #: src/gui-gtk/gtk-new-game-dialog.c:387 msgid "K_eep track of total time" msgstr "" #: src/gui-gtk/gtk-new-game-dialog.c:407 msgid "Time _limit for game:" msgstr "" #: src/gui-gtk/gtk-new-game-dialog.c:413 msgid "(per player)" msgstr "" #: src/gui-gtk/gtk-new-game-dialog.c:427 msgid "Time _limit for move:" msgstr "" #: src/gui-gtk/gtk-new-game-dialog.c:461 msgid "_Overtime period length:" msgstr "" #: src/gui-gtk/gtk-new-game-dialog.c:478 msgid "Mo_ves per overtime:" msgstr "" #: src/gui-gtk/gtk-new-game-record-dialog.c:119 msgid "New Game Record" msgstr "" #: src/gui-gtk/gtk-new-game-record-dialog.c:189 msgid "_Place stones" msgstr "" #: src/gui-gtk/gtk-new-game-record-dialog.c:265 msgid "_White player:" msgstr "" #: src/gui-gtk/gtk-new-game-record-dialog.c:276 msgid "_Black player:" msgstr "" #: src/gui-gtk/gtk-new-game-record-dialog.c:287 msgid "Game _name:" msgstr "" #: src/gui-gtk/gtk-new-game-record-dialog.c:300 msgid "" "You can always change and expand game information later. Just choose `Edit/" "Game Information' menu item or press `Info' button on the main toolbar." msgstr "" #: src/gui-gtk/gtk-new-game-record-dialog.c:310 #: src/gui-gtk/gtk-resume-game-dialog.c:227 msgid "Short Game Information" msgstr "" #: src/gui-gtk/gtk-parser-interface.c:58 #, c-format msgid "Error reading file `%s'" msgstr "" #: src/gui-gtk/gtk-parser-interface.c:60 #, c-format msgid "File `%s' doesn't appear to be a valid SGF file" msgstr "" #: src/gui-gtk/gtk-parser-interface.c:63 msgid "" "Please check that the file exists and its permission allow you to read it." msgstr "" #: src/gui-gtk/gtk-parser-interface.c:67 msgid "" "Quarry uses SGF file format for storing game records. SGF files would " "normally have `sgf' extension, but that's not necessarily true. Please make " "sure you select a proper SGF file." msgstr "" #: src/gui-gtk/gtk-parser-interface.c:101 msgid "Open SGF File..." msgstr "" #: src/gui-gtk/gtk-parser-interface.c:192 #, c-format msgid "Parsing file `%s'..." msgstr "" #: src/gui-gtk/gtk-preferences.c:431 msgid "General" msgstr "" #: src/gui-gtk/gtk-preferences.c:434 msgid "Interface" msgstr "" #: src/gui-gtk/gtk-preferences.c:435 msgid "General Interface" msgstr "" #: src/gui-gtk/gtk-preferences.c:437 msgid "Editing & Viewing" msgstr "" #: src/gui-gtk/gtk-preferences.c:440 src/gui-gtk/gtk-preferences.c:441 msgid "Game Tree" msgstr "" #: src/gui-gtk/gtk-preferences.c:444 msgid "GTP" msgstr "" #: src/gui-gtk/gtk-preferences.c:447 src/gui-gtk/gtk-preferences.c:448 msgid "GTP Engines" msgstr "" #: src/gui-gtk/gtk-preferences.c:451 msgid "Game Records (SGF)" msgstr "" #: src/gui-gtk/gtk-preferences.c:454 msgid "Saving" msgstr "" #: src/gui-gtk/gtk-preferences.c:455 msgid "Saving Game Records" msgstr "" #: src/gui-gtk/gtk-preferences.c:458 msgid "Board Appearance" msgstr "" #: src/gui-gtk/gtk-preferences.c:462 msgid "Go Board Appearance" msgstr "" #: src/gui-gtk/gtk-preferences.c:465 msgid "Amazons Board Appearance" msgstr "" #: src/gui-gtk/gtk-preferences.c:468 msgid "Reversi Board Appearance" msgstr "" #: src/gui-gtk/gtk-preferences.c:478 msgid "Preferences" msgstr "" #: src/gui-gtk/gtk-preferences.c:515 msgid "Categor_y:" msgstr "" #: src/gui-gtk/gtk-preferences.c:641 msgid "Use _newer (GTK+ 2.4) file chooser" msgstr "" #: src/gui-gtk/gtk-preferences.c:642 msgid "Use _old-style file selection dialog" msgstr "" #: src/gui-gtk/gtk-preferences.c:672 msgid "File Chooser Dialog Style" msgstr "" #: src/gui-gtk/gtk-preferences.c:688 msgid "_Main toolbar style:" msgstr "" #: src/gui-gtk/gtk-preferences.c:692 msgid "_Editing toolbar style:" msgstr "" #: src/gui-gtk/gtk-preferences.c:696 msgid "N_avigation toolbar style:" msgstr "" #: src/gui-gtk/gtk-preferences.c:705 msgid "Toolbar Styles" msgstr "" #: src/gui-gtk/gtk-preferences.c:725 msgid "Desktop default" msgstr "" #: src/gui-gtk/gtk-preferences.c:726 msgid "Text below icons" msgstr "" #: src/gui-gtk/gtk-preferences.c:732 msgid "Text beside important icons" msgstr "" #: src/gui-gtk/gtk-preferences.c:735 msgid "Icons only" msgstr "" #: src/gui-gtk/gtk-preferences.c:736 msgid "Text only" msgstr "" #: src/gui-gtk/gtk-preferences.c:792 msgid "Show" msgstr "" #: src/gui-gtk/gtk-preferences.c:799 msgid "Name" msgstr "" #: src/gui-gtk/gtk-preferences.c:808 msgid "_List of GTP engines:" msgstr "" #: src/gui-gtk/gtk-preferences.c:856 msgid "Name:" msgstr "" #: src/gui-gtk/gtk-preferences.c:865 msgid "Version:" msgstr "" #: src/gui-gtk/gtk-preferences.c:875 src/gui-gtk/gtk-preferences.c:1630 msgid "Supported game:" msgstr "" #: src/gui-gtk/gtk-preferences.c:889 msgid "Command line:" msgstr "" #: src/gui-gtk/gtk-preferences.c:914 msgid "GTP Engine Information" msgstr "" #: src/gui-gtk/gtk-preferences.c:935 msgid "_Always" msgstr "" #: src/gui-gtk/gtk-preferences.c:935 msgid "A_utomatically" msgstr "" #: src/gui-gtk/gtk-preferences.c:935 msgid "_Never" msgstr "" #: src/gui-gtk/gtk-preferences.c:937 msgid "Al_ways" msgstr "" #: src/gui-gtk/gtk-preferences.c:937 msgid "Aut_omatically" msgstr "" #: src/gui-gtk/gtk-preferences.c:937 msgid "Ne_ver" msgstr "" #: src/gui-gtk/gtk-preferences.c:939 msgid "Scroll _minimal distance" msgstr "" #: src/gui-gtk/gtk-preferences.c:940 msgid "_Recenter view on the current node" msgstr "" #: src/gui-gtk/gtk-preferences.c:943 msgid "" "In automatic mode the game tree is shown only if it has at least one " "variation. In any case, you can show/hide game tree in each window " "separately." msgstr "" #: src/gui-gtk/gtk-preferences.c:947 msgid "" "In automatic mode the game tree view scrolls to show the current node only " "if it has been showing current node before. I.e. unless you scrolled it away " "manually." msgstr "" #: src/gui-gtk/gtk-preferences.c:992 msgid "Show Game Tree" msgstr "" #: src/gui-gtk/gtk-preferences.c:1039 msgid "Track Tree's Current Node" msgstr "" #: src/gui-gtk/gtk-preferences.c:1042 msgid "Show _tooltips" msgstr "" #: src/gui-gtk/gtk-preferences.c:1049 msgid "Tooltips" msgstr "" #: src/gui-gtk/gtk-preferences.c:1065 msgid "Always use _UTF-8 (recommended)" msgstr "" #: src/gui-gtk/gtk-preferences.c:1066 msgid "Preserve _original encoding" msgstr "" #: src/gui-gtk/gtk-preferences.c:1068 msgid "" "Note that many characters cannot be represented in non-UTF-8 encodings and " "thus some information may be lost if you use them. Quarry also works fastest " "with UTF-8; this may be important if you have very large SGF files." msgstr "" #: src/gui-gtk/gtk-preferences.c:1093 msgid "Encoding" msgstr "" #: src/gui-gtk/gtk-preferences.c:1103 msgid "_Relative to stone size" msgstr "" #: src/gui-gtk/gtk-preferences.c:1104 msgid "On _white stones:" msgstr "" #: src/gui-gtk/gtk-preferences.c:1105 msgid "On _black stones:" msgstr "" #: src/gui-gtk/gtk-preferences.c:1106 msgid "On _empty intersections:" msgstr "" #: src/gui-gtk/gtk-preferences.c:1120 msgid "_Relative to amazon size" msgstr "" #: src/gui-gtk/gtk-preferences.c:1121 msgid "On _white amazons:" msgstr "" #: src/gui-gtk/gtk-preferences.c:1122 msgid "On _black amazons:" msgstr "" #: src/gui-gtk/gtk-preferences.c:1123 src/gui-gtk/gtk-preferences.c:1182 msgid "On _empty fields:" msgstr "" #: src/gui-gtk/gtk-preferences.c:1142 msgid "Pick Checkerboard Pattern Color" msgstr "" #: src/gui-gtk/gtk-preferences.c:1151 msgid "Checkerboard _pattern color:" msgstr "" #: src/gui-gtk/gtk-preferences.c:1167 msgid "Checkerboard pattern _opacity:" msgstr "" #: src/gui-gtk/gtk-preferences.c:1179 msgid "_Relative to disk size" msgstr "" #: src/gui-gtk/gtk-preferences.c:1180 msgid "On _white disks:" msgstr "" #: src/gui-gtk/gtk-preferences.c:1181 msgid "On _black disks:" msgstr "" #: src/gui-gtk/gtk-preferences.c:1195 msgid "Use _texture:" msgstr "" #: src/gui-gtk/gtk-preferences.c:1196 msgid "Use _solid color:" msgstr "" #: src/gui-gtk/gtk-preferences.c:1271 msgid "Choose a Background Texture..." msgstr "" #: src/gui-gtk/gtk-preferences.c:1282 msgid "Pick Background Color" msgstr "" #: src/gui-gtk/gtk-preferences.c:1296 msgid "Pick Color for Grid and Labels" msgstr "" #: src/gui-gtk/gtk-preferences.c:1306 msgid "_Grid and labels color:" msgstr "" #: src/gui-gtk/gtk-preferences.c:1345 msgid "_Theme:" msgstr "" #: src/gui-gtk/gtk-preferences.c:1354 msgid "Use theme _defaults" msgstr "" #: src/gui-gtk/gtk-preferences.c:1371 msgid "_Size:" msgstr "" #: src/gui-gtk/gtk-preferences.c:1398 msgid "_Opacity:" msgstr "" #: src/gui-gtk/gtk-preferences.c:1413 msgid "Size & Opacity" msgstr "" #: src/gui-gtk/gtk-preferences.c:1429 msgid "Color" msgstr "" #: src/gui-gtk/gtk-preferences.c:1443 msgid "Pick Color for Markup" msgstr "" #: src/gui-gtk/gtk-preferences.c:1482 msgid "Background" msgstr "" #: src/gui-gtk/gtk-preferences.c:1484 msgid "Markup" msgstr "" #: src/gui-gtk/gtk-preferences.c:1630 msgid "Supported games:" msgstr "" #: src/gui-gtk/gtk-preferences.c:1637 msgid "This engine comes from site configuration." msgstr "" #: src/gui-gtk/gtk-preferences.c:1860 msgid "" "You can use `%n' and `%v' strings in Screen name field. They will " "substituted with name and version of the engine correspondingly. By default, " "`%n %v' is used." msgstr "" #: src/gui-gtk/gtk-preferences.c:1908 msgid "Modify GTP Engine Information" msgstr "" #: src/gui-gtk/gtk-preferences.c:1909 msgid "New GTP Engine" msgstr "" #: src/gui-gtk/gtk-preferences.c:1955 msgid "Command _line:" msgstr "" #: src/gui-gtk/gtk-preferences.c:1961 msgid "Choose GTP Engine..." msgstr "" #: src/gui-gtk/gtk-preferences.c:1972 msgid "Screen _name:" msgstr "" #: src/gui-gtk/gtk-preferences.c:2018 msgid "Querying engine's name, version and known commands..." msgstr "" #: src/gui-gtk/gtk-preferences.c:2039 msgid "" "Please make sure you typed engine's filename correctly and that you have " "permission to execute it." msgstr "" #: src/gui-gtk/gtk-preferences.c:2078 msgid "Waiting for the engine to quit..." msgstr "" #: src/gui-gtk/gtk-preferences.c:2182 msgid "" "The engine might have crashed, quit prematurely or disconnected. Please " "verify command line, including options, and consult engine's documentation " "if needed." msgstr "" #: src/gui-gtk/gtk-preferences.c:2197 #, c-format msgid "Lost connection to GTP Engine (%s)" msgstr "" #: src/gui-gtk/gtk-preferences.c:3011 msgid "" "Perhaps engine's binary has been deleted or changed. You will probably need " "to alter engine's command line in the Preferences dialog." msgstr "" #: src/gui-gtk/gtk-resume-game-dialog.c:92 msgid "Resume Game..." msgstr "" #: src/gui-gtk/gtk-resume-game-dialog.c:115 #, c-format msgid "The game stored in file `%s' (%s) is not supported by Quarry" msgstr "" #: src/gui-gtk/gtk-resume-game-dialog.c:138 msgid "" "This game appears to have been finished. Open it for viewing and/or editing " "instead?" msgstr "" #: src/gui-gtk/gtk-resume-game-dialog.c:212 msgid "Resuming Game" msgstr "" #: src/gui-gtk/gtk-resume-game-dialog.c:214 msgid "_Resume" msgstr "" #: src/gui-gtk/gtk-resume-game-dialog.c:231 msgid "Game:" msgstr "" #: src/gui-gtk/gtk-resume-game-dialog.c:240 msgid "Board size:" msgstr "" #: src/gui-gtk/gtk-resume-game-dialog.c:258 msgid "Handicap:" msgstr "" #: src/gui-gtk/gtk-resume-game-dialog.c:262 msgid "handicap|Not set" msgstr "" #: src/gui-gtk/gtk-resume-game-dialog.c:268 msgid "Komi:" msgstr "" #: src/gui-gtk/gtk-resume-game-dialog.c:271 msgid "komi|Not set" msgstr "" #: src/gui-gtk/gtk-resume-game-dialog.c:294 msgid "Filename:" msgstr "" #: src/gui-gtk/gtk-resume-game-dialog.c:307 msgid "Compu_ter" msgstr "" #: src/gui-gtk/quarry-find-dialog.c:104 msgid "Whole game _tree" msgstr "" #: src/gui-gtk/quarry-find-dialog.c:104 msgid "Current no_de only" msgstr "" #: src/gui-gtk/quarry-find-dialog.c:107 msgid "C_omments & node names" msgstr "" #: src/gui-gtk/quarry-find-dialog.c:108 msgid "Comm_ents only" msgstr "" #: src/gui-gtk/quarry-find-dialog.c:108 msgid "Node na_mes only" msgstr "" #: src/gui-gtk/quarry-find-dialog.c:154 msgid "Search _for:" msgstr "" #: src/gui-gtk/quarry-find-dialog.c:161 msgid "Case _sensitive" msgstr "" #: src/gui-gtk/quarry-find-dialog.c:169 msgid "Whole _words only" msgstr "" #: src/gui-gtk/quarry-find-dialog.c:177 msgid "Wrap _around" msgstr "" #: src/gui-gtk/quarry-find-dialog.c:191 msgid "A_uto-close this dialog" msgstr "" #: src/gui-gtk/quarry-find-dialog.c:202 msgid "Options" msgstr "" #: src/gui-gtk/quarry-find-dialog.c:251 msgid "Search Scope" msgstr "" #: src/gui-gtk/quarry-move-number-dialog.c:66 #: src/gui-gtk/quarry-move-number-dialog.c:148 msgid "Use se_quential move number" msgstr "" #: src/gui-gtk/quarry-move-number-dialog.c:66 msgid "_Set specific move number:" msgstr "" #: src/gui-gtk/quarry-save-confirmation-dialog.c:89 msgid "Close _without Saving" msgstr "" #: src/gui-gtk/quarry-save-confirmation-dialog.c:173 #, c-format msgid "" "If you don't save, changes from the last %d second will be lost permanently." msgid_plural "" "If you don't save, changes from the last %d seconds will be lost permanently." msgstr[0] "" msgstr[1] "" #: src/gui-gtk/quarry-save-confirmation-dialog.c:181 msgid "If you don't save, changes from the last minute will be discarded." msgstr "" #. TRANSLATORS: Cannot be one minute one second, actually. #: src/gui-gtk/quarry-save-confirmation-dialog.c:187 #, c-format msgid "" "If you don't save, changes from the last minute and %d second will be lost " "permanently." msgid_plural "" "If you don't save, changes from the last minute and %d seconds will be lost " "permanently." msgstr[0] "" msgstr[1] "" #: src/gui-gtk/quarry-save-confirmation-dialog.c:198 #, c-format msgid "" "If you don't save, changes from the last %d minute will be lost permanently." msgid_plural "" "If you don't save, changes from the last %d minutes will be lost permanently." msgstr[0] "" msgstr[1] "" #. TRANSLATORS: Cannot be one hour one minute, actually. #: src/gui-gtk/quarry-save-confirmation-dialog.c:212 #, c-format msgid "" "If you don't save, changes from the last hour and %d minute will be lost " "permanently." msgid_plural "" "If you don't save, changes from the last hour and %d minutes will be lost " "permanently." msgstr[0] "" msgstr[1] "" #: src/gui-gtk/quarry-save-confirmation-dialog.c:224 #, c-format msgid "" "If you don't save, changes from the last %d hour will be lost permanently." msgid_plural "" "If you don't save, changes from the last %d hours will be lost permanently." msgstr[0] "" msgstr[1] "" #: src/gui-gtk/quarry-stock.c:56 msgid "_New Game" msgstr "" #: src/gui-gtk/quarry-stock.c:57 msgid "_Open Game Record" msgstr "" #: src/gui-gtk/quarry-stock.c:59 msgid "_Browse..." msgstr "" #: src/gui-gtk/quarry-stock.c:60 msgid "Crea_te" msgstr "" #: src/gui-gtk/quarry-stock.c:61 msgid "_Done" msgstr "" #: src/gui-gtk/quarry-stock.c:62 msgid "_Go to Node" msgstr "" #: src/gui-gtk/quarry-stock.c:63 msgid "_Modify" msgstr "" #: src/gui-gtk/quarry-stock.c:64 msgid "Move _Up" msgstr "" #: src/gui-gtk/quarry-stock.c:65 msgid "Move _Down" msgstr "" #: src/gui-gtk/quarry-stock.c:66 msgid "find|_Next" msgstr "" #: src/gui-gtk/quarry-stock.c:67 msgid "_Overwrite" msgstr "" #: src/gui-gtk/quarry-stock.c:68 msgid "_Play" msgstr "" #: src/gui-gtk/quarry-stock.c:69 msgid "find|_Previous" msgstr "" #. TRANSLATORS: This is only used for non-integral scores. You #. should also add translation of `points' if it is required by #. your language. #: src/board/board.c:897 #, c-format msgid "Black wins by %.*f" msgstr "" #. TRANSLATORS: This is only used for non-integral scores. You #. should also add translation of `points' if it is required by #. your language. #: src/board/board.c:904 #, c-format msgid "White wins by %.*f" msgstr "" #: src/board/board.c:915 #, c-format msgid "Black wins by %d" msgid_plural "Black wins by %d" msgstr[0] "" msgstr[1] "" #: src/board/board.c:923 #, c-format msgid "White wins by %d" msgid_plural "White wins by %d" msgstr[0] "" msgstr[1] "" #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:29 msgid "Go" msgstr "" #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:43 msgid "Reversi" msgstr "" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:58 msgid "chess" msgstr "" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:73 msgid "Gomoku" msgstr "" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:88 msgid "Nine Men's Morris" msgstr "" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:103 msgid "Backgammon" msgstr "" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:118 msgid "Chinese chess" msgstr "" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:133 msgid "Shogi" msgstr "" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:148 msgid "Lines of Action" msgstr "" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:163 msgid "Ataxx" msgstr "" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:178 msgid "Hex" msgstr "" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:193 msgid "Jungle" msgstr "" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:208 msgid "Neutron" msgstr "" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:223 msgid "Philosopher's Football" msgstr "" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:238 msgid "Quadrature" msgstr "" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:253 msgid "Trax" msgstr "" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:268 msgid "Tantrix" msgstr "" #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:282 msgid "Amazons" msgstr "" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:297 msgid "Octi" msgstr "" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:312 msgid "Gess" msgstr "" #: src/board/go.c:1323 #, c-format msgid "White: %d territory" msgid_plural "White: %d territory" msgstr[0] "" msgstr[1] "" #: src/board/go.c:1328 src/board/go.c:1365 #, c-format msgid " + %d capture" msgid_plural " + %d captures" msgstr[0] "" msgstr[1] "" #. TRANSLATORS: e.g. `` + 6.5 komi = #. 87.5''. This is used only with #. fractional komi. #: src/board/go.c:1337 #, c-format msgid " %s %.*f komi = %.*f\n" msgstr "" #. TRANSLATORS: e.g. `` + 6 komi = 87''. #: src/board/go.c:1351 #, c-format msgid " %s %d komi = %d\n" msgid_plural " %s %d komi = %d\n" msgstr[0] "" msgstr[1] "" #: src/board/go.c:1360 #, c-format msgid "Black: %d territory" msgid_plural "Black: %d territory" msgstr[0] "" msgstr[1] "" #: src/board/go.c:1374 msgid "The game is draw" msgstr "" quarry-0.2.0/po/stamp-po0000644000175000017500000000001210525402427013571 0ustar bartbarttimestamp quarry-0.2.0/po/en.po0000644000175000017500000015665510524133016013073 0ustar bartbart# English translation of Quarry (proper punctuation only.) # Copyright (C) 2004, 2005, 2006 Paul Pogonyshev # This file is distributed under the same license as the Quarry package. # Paul Pogonyshev , 2005, 2006. # msgid "" msgstr "" "Project-Id-Version: Quarry\n" "Report-Msgid-Bugs-To: quarry-dev@gna.org\n" "POT-Creation-Date: 2006-11-07 18:33+0200\n" "PO-Revision-Date: 2006-10-28 15:05+0300\n" "Last-Translator: Paul Pogonyshev \n" "Language-Team: \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 ? 0 : 1;\n" #: src/gui-gtk/gtk-add-or-edit-label-dialog.c:73 msgid "" "Although board labels are not limited in length, it is better to use only " "one or two characters long labels. Longer labels will not be visible " "immediately or at all in most clients." msgstr "" "Although board labels are not limited in length, it is better to use only " "one or two characters long labels. Longer labels will not be visible " "immediately or at all in most clients." #: src/gui-gtk/gtk-add-or-edit-label-dialog.c:87 msgid "Label _text:" msgstr "Label _text:" #: src/gui-gtk/gtk-color-button.c:581 msgid "Pick a Color" msgstr "Pick a Color" #: src/gui-gtk/gtk-control-center.c:64 msgid "Quarry Control Center" msgstr "Quarry Control Center" #: src/gui-gtk/gtk-control-center.c:80 msgid "Ne_w Game Record" msgstr "Ne_w Game Record" #: src/gui-gtk/gtk-control-center.c:96 msgid "_Resume Game" msgstr "_Resume Game" #: src/gui-gtk/gtk-file-dialog.c:281 msgid "" "Note that all information in the existing file will be lost permanently if " "you choose to overwrite it." msgstr "" "Note that all information in the existing file will be lost permanently if " "you choose to overwrite it." #: src/gui-gtk/gtk-file-dialog.c:284 #, c-format msgid "" "File named `%s' already exists. Do you want to overwrite it with the one you " "are saving?" msgstr "" "File named ‘%s’ already exists. Do you want to overwrite it with the one you " "are saving?" #: src/gui-gtk/gtk-game-info-dialog.c:231 #: src/gui-gtk/gtk-resume-game-dialog.c:325 msgid "N_ame:" msgstr "N_ame:" #: src/gui-gtk/gtk-game-info-dialog.c:231 #: src/gui-gtk/gtk-resume-game-dialog.c:324 msgid "_Name:" msgstr "_Name:" #: src/gui-gtk/gtk-game-info-dialog.c:238 msgid "Team:" msgstr "Team:" #: src/gui-gtk/gtk-game-info-dialog.c:244 msgid "Rank:" msgstr "Rank:" #: src/gui-gtk/gtk-game-info-dialog.c:256 #: src/gui-gtk/gtk-new-game-dialog.c:226 #: src/gui-gtk/gtk-resume-game-dialog.c:364 msgid "Black Player" msgstr "Black Player" #: src/gui-gtk/gtk-game-info-dialog.c:256 #: src/gui-gtk/gtk-new-game-dialog.c:226 #: src/gui-gtk/gtk-resume-game-dialog.c:364 msgid "White Player" msgstr "White Player" #: src/gui-gtk/gtk-game-info-dialog.c:270 msgid "_Game name:" msgstr "_Game name:" #: src/gui-gtk/gtk-game-info-dialog.c:273 msgid "_Place:" msgstr "_Place:" #: src/gui-gtk/gtk-game-info-dialog.c:277 msgid "Da_te:" msgstr "Da_te:" #: src/gui-gtk/gtk-game-info-dialog.c:280 msgid "_Event:" msgstr "_Event:" #: src/gui-gtk/gtk-game-info-dialog.c:284 msgid "R_ound:" msgstr "R_ound:" #: src/gui-gtk/gtk-game-info-dialog.c:295 #: src/gui-gtk/gtk-game-info-dialog.c:535 #: src/gui-gtk/gtk-game-info-dialog.c:541 msgid "Game Information" msgstr "Game Information" #: src/gui-gtk/gtk-game-info-dialog.c:298 msgid "Rule _set:" msgstr "Rule _set:" #: src/gui-gtk/gtk-game-info-dialog.c:324 #: src/gui-gtk/gtk-new-game-record-dialog.c:187 msgid "Han_dicap:" msgstr "Han_dicap:" #: src/gui-gtk/gtk-game-info-dialog.c:347 #: src/gui-gtk/gtk-new-game-dialog.c:574 #: src/gui-gtk/gtk-new-game-record-dialog.c:231 msgid "_Komi:" msgstr "_Komi:" #: src/gui-gtk/gtk-game-info-dialog.c:374 #: src/gui-gtk/gtk-new-game-dialog.c:444 msgid "_Main time:" msgstr "_Main time:" #: src/gui-gtk/gtk-game-info-dialog.c:386 msgid "O_vertime:" msgstr "O_vertime:" #: src/gui-gtk/gtk-game-info-dialog.c:397 #: src/gui-gtk/gtk-new-game-dialog.c:602 msgid "Game Rules" msgstr "Game Rules" #: src/gui-gtk/gtk-game-info-dialog.c:412 msgid "General" msgstr "General" #: src/gui-gtk/gtk-game-info-dialog.c:415 msgid "Game re_sult:" msgstr "Game re_sult:" #: src/gui-gtk/gtk-game-info-dialog.c:419 msgid "_Opening played:" msgstr "_Opening played:" #: src/gui-gtk/gtk-game-info-dialog.c:449 msgid "Comment / _description:" msgstr "Comment / _description:" #: src/gui-gtk/gtk-game-info-dialog.c:463 msgid "Description & Result" msgstr "Description & Result" #: src/gui-gtk/gtk-game-info-dialog.c:466 msgid "Co_pyright string:" msgstr "Co_pyright string:" #: src/gui-gtk/gtk-game-info-dialog.c:470 msgid "_Annotator:" msgstr "_Annotator:" #: src/gui-gtk/gtk-game-info-dialog.c:474 msgid "_Source:" msgstr "_Source:" #: src/gui-gtk/gtk-game-info-dialog.c:478 msgid "_Entered by:" msgstr "_Entered by:" #: src/gui-gtk/gtk-game-info-dialog.c:488 msgid "Copyright & Credits" msgstr "Copyright & Credits" #: src/gui-gtk/gtk-game-info-dialog.c:502 msgid "Game Record" msgstr "Game Record" #: src/gui-gtk/gtk-games.c:39 msgid "_Go" msgstr "_Go" #: src/gui-gtk/gtk-games.c:40 msgid "_Amazons" msgstr "_Amazons" #: src/gui-gtk/gtk-games.c:41 msgid "_Reversi" msgstr "_Reversi" #: src/gui-gtk/gtk-games.c:45 msgid "Go Rules" msgstr "Go Rules" #: src/gui-gtk/gtk-games.c:46 msgid "Amazons Rules" msgstr "Amazons Rules" #: src/gui-gtk/gtk-games.c:47 msgid "Reversi Rules" msgstr "Reversi Rules" #: src/gui-gtk/gtk-games.c:180 msgid "Board _size:" msgstr "Board _size:" #: src/gui-gtk/gtk-goban-window.c:460 msgid "Open" msgstr "Open" #: src/gui-gtk/gtk-goban-window.c:460 msgid "Open a game record" msgstr "Open a game record" #: src/gui-gtk/gtk-goban-window.c:465 msgid "Save" msgstr "Save" #: src/gui-gtk/gtk-goban-window.c:465 msgid "Save the current file" msgstr "Save the current file" #: src/gui-gtk/gtk-goban-window.c:470 src/gui-gtk/gtk-goban-window.c:2025 msgid "Find" msgstr "Find" #: src/gui-gtk/gtk-goban-window.c:470 msgid "Search for a string in comments" msgstr "Search for a string in comments" #: src/gui-gtk/gtk-goban-window.c:475 msgid "Info" msgstr "Info" #: src/gui-gtk/gtk-goban-window.c:475 msgid "View and edit game information" msgstr "View and edit game information" #: src/gui-gtk/gtk-goban-window.c:481 msgid "Undo" msgstr "Undo" #: src/gui-gtk/gtk-goban-window.c:481 msgid "Undo the last action" msgstr "Undo the last action" #: src/gui-gtk/gtk-goban-window.c:486 msgid "Redo" msgstr "Redo" #: src/gui-gtk/gtk-goban-window.c:486 msgid "Redo the last undone action" msgstr "Redo the last undone action" #: src/gui-gtk/gtk-goban-window.c:491 msgid "Delete" msgstr "Delete" #: src/gui-gtk/gtk-goban-window.c:491 msgid "Delete the current node" msgstr "Delete the current node" #: src/gui-gtk/gtk-goban-window.c:497 msgid "Root" msgstr "Root" #: src/gui-gtk/gtk-goban-window.c:497 msgid "Go to the root node" msgstr "Go to the root node" #: src/gui-gtk/gtk-goban-window.c:502 msgid "Back" msgstr "Back" #: src/gui-gtk/gtk-goban-window.c:502 msgid "Go to the previous node" msgstr "Go to the previous node" #: src/gui-gtk/gtk-goban-window.c:507 msgid "Forward" msgstr "Forward" #: src/gui-gtk/gtk-goban-window.c:507 msgid "Go to the next node" msgstr "Go to the next node" #: src/gui-gtk/gtk-goban-window.c:512 msgid "End" msgstr "End" #: src/gui-gtk/gtk-goban-window.c:512 msgid "Go to the current variation's last node" msgstr "Go to the current variation’s last node" #: src/gui-gtk/gtk-goban-window.c:518 msgid "Previous" msgstr "Previous" #: src/gui-gtk/gtk-goban-window.c:518 msgid "Switch to the previous variation" msgstr "Switch to the previous variation" #: src/gui-gtk/gtk-goban-window.c:524 msgid "Next" msgstr "Next" #: src/gui-gtk/gtk-goban-window.c:524 msgid "Switch to the next variation" msgstr "Switch to the next variation" #: src/gui-gtk/gtk-goban-window.c:629 msgid "/_File" msgstr "/_File" #: src/gui-gtk/gtk-goban-window.c:630 msgid "/File/_New Game..." msgstr "/File/_New Game…" #: src/gui-gtk/gtk-goban-window.c:633 msgid "/File/Ne_w Game Record..." msgstr "/File/Ne_w Game Record…" #: src/gui-gtk/gtk-goban-window.c:636 src/gui-gtk/gtk-goban-window.c:653 #: src/gui-gtk/gtk-goban-window.c:661 msgid "/File/" msgstr "/File/" #: src/gui-gtk/gtk-goban-window.c:638 msgid "/File/_Open..." msgstr "/File/_Open…" #: src/gui-gtk/gtk-goban-window.c:641 msgid "/File/_Resume Game..." msgstr "/File/_Resume Game…" #: src/gui-gtk/gtk-goban-window.c:645 msgid "/File/_Export..." msgstr "/File/_Export…" #: src/gui-gtk/gtk-goban-window.c:646 msgid "/File/Export.../_ASCII Diagram" msgstr "/File/Export…/_ASCII Diagram" #: src/gui-gtk/gtk-goban-window.c:649 msgid "/File/Export.../_Sensei's Library Diagram" msgstr "/File/Export…/_Sensei’s Library Diagram" #: src/gui-gtk/gtk-goban-window.c:655 msgid "/File/_Save" msgstr "/File/_Save" #: src/gui-gtk/gtk-goban-window.c:658 msgid "/File/Save _As..." msgstr "/File/Save _As…" #: src/gui-gtk/gtk-goban-window.c:663 msgid "/File/_Close" msgstr "/File/_Close" #: src/gui-gtk/gtk-goban-window.c:666 msgid "/File/_Quit" msgstr "/File/_Quit" #: src/gui-gtk/gtk-goban-window.c:671 msgid "/_Edit" msgstr "/_Edit" #: src/gui-gtk/gtk-goban-window.c:672 msgid "/Edit/_Undo" msgstr "/Edit/_Undo" #: src/gui-gtk/gtk-goban-window.c:675 msgid "/Edit/_Redo" msgstr "/Edit/_Redo" #: src/gui-gtk/gtk-goban-window.c:678 src/gui-gtk/gtk-goban-window.c:695 #: src/gui-gtk/gtk-goban-window.c:739 src/gui-gtk/gtk-goban-window.c:747 #: src/gui-gtk/gtk-goban-window.c:767 src/gui-gtk/gtk-goban-window.c:778 #: src/gui-gtk/gtk-goban-window.c:783 msgid "/Edit/" msgstr "/Edit/" #: src/gui-gtk/gtk-goban-window.c:680 msgid "/Edit/Cu_t" msgstr "/Edit/Cu_t" #: src/gui-gtk/gtk-goban-window.c:683 msgid "/Edit/_Copy" msgstr "/Edit/_Copy" #: src/gui-gtk/gtk-goban-window.c:686 msgid "/Edit/_Paste" msgstr "/Edit/_Paste" #: src/gui-gtk/gtk-goban-window.c:689 msgid "/Edit/_Delete Node" msgstr "/Edit/_Delete Node" #: src/gui-gtk/gtk-goban-window.c:692 msgid "/Edit/Delete Node's C_hildren" msgstr "/Edit/Delete Node’s C_hildren" #: src/gui-gtk/gtk-goban-window.c:698 msgid "/Edit/T_ools" msgstr "/Edit/T_ools" #: src/gui-gtk/gtk-goban-window.c:699 msgid "/Edit/Tools/_Move Tool" msgstr "/Edit/Tools/_Move Tool" #: src/gui-gtk/gtk-goban-window.c:702 msgid "/Edit/Tools/_Setup Tool" msgstr "/Edit/Tools/_Setup Tool" #: src/gui-gtk/gtk-goban-window.c:705 src/gui-gtk/gtk-goban-window.c:722 #: src/gui-gtk/gtk-goban-window.c:730 msgid "/Edit/Tools/" msgstr "/Edit/Tools/" #: src/gui-gtk/gtk-goban-window.c:707 msgid "/Edit/Tools/C_ross Markup" msgstr "/Edit/Tools/C_ross Markup" #: src/gui-gtk/gtk-goban-window.c:710 msgid "/Edit/Tools/_Circle Markup" msgstr "/Edit/Tools/_Circle Markup" #: src/gui-gtk/gtk-goban-window.c:713 msgid "/Edit/Tools/S_quare Markup" msgstr "/Edit/Tools/S_quare Markup" #: src/gui-gtk/gtk-goban-window.c:716 msgid "/Edit/Tools/_Triangle Markup" msgstr "/Edit/Tools/_Triangle Markup" #: src/gui-gtk/gtk-goban-window.c:719 msgid "/Edit/Tools/S_elected Markup" msgstr "/Edit/Tools/S_elected Markup" #: src/gui-gtk/gtk-goban-window.c:724 msgid "/Edit/Tools/_Label Tool" msgstr "/Edit/Tools/_Label Tool" #: src/gui-gtk/gtk-goban-window.c:727 msgid "/Edit/Tools/_Number Tool" msgstr "/Edit/Tools/_Number Tool" #: src/gui-gtk/gtk-goban-window.c:732 msgid "/Edit/Tools/Scori_ng Tool" msgstr "/Edit/Tools/Scori_ng Tool" #: src/gui-gtk/gtk-goban-window.c:736 msgid "/Edit/_Add Empty Node" msgstr "/Edit/_Add Empty Node" #: src/gui-gtk/gtk-goban-window.c:741 msgid "/Edit/Move _Branch Up" msgstr "/Edit/Move _Branch Up" #: src/gui-gtk/gtk-goban-window.c:744 msgid "/Edit/Move Branch Do_wn" msgstr "/Edit/Move Branch Do_wn" #: src/gui-gtk/gtk-goban-window.c:749 msgid "/Edit/Edit Node _Name" msgstr "/Edit/Edit Node _Name" #: src/gui-gtk/gtk-goban-window.c:752 msgid "/Edit/Set _Move Number" msgstr "/Edit/Set _Move Number" #: src/gui-gtk/gtk-goban-window.c:756 msgid "/Edit/P_layer to Move" msgstr "/Edit/P_layer to Move" #: src/gui-gtk/gtk-goban-window.c:757 msgid "/Edit/Player to Move/_White" msgstr "/Edit/Player to Move/_White" #: src/gui-gtk/gtk-goban-window.c:760 msgid "/Edit/Player to Move/_Black" msgstr "/Edit/Player to Move/_Black" #: src/gui-gtk/gtk-goban-window.c:763 msgid "/Edit/Player to Move/By Game _Rules" msgstr "/Edit/Player to Move/By Game _Rules" #: src/gui-gtk/gtk-goban-window.c:769 msgid "/Edit/_Find" msgstr "/Edit/_Find" #: src/gui-gtk/gtk-goban-window.c:772 msgid "/Edit/Find Ne_xt" msgstr "/Edit/Find Ne_xt" #: src/gui-gtk/gtk-goban-window.c:775 msgid "/Edit/Find Pre_vious" msgstr "/Edit/Find Pre_vious" #: src/gui-gtk/gtk-goban-window.c:780 msgid "/Edit/Game _Information" msgstr "/Edit/Game _Information" #: src/gui-gtk/gtk-goban-window.c:785 msgid "/Edit/Pr_eferences" msgstr "/Edit/Pr_eferences" #: src/gui-gtk/gtk-goban-window.c:790 msgid "/_View" msgstr "/_View" #: src/gui-gtk/gtk-goban-window.c:791 msgid "/View/_Main Toolbar" msgstr "/View/_Main Toolbar" #: src/gui-gtk/gtk-goban-window.c:794 msgid "/View/_Editing Toolbar" msgstr "/View/_Editing Toolbar" #: src/gui-gtk/gtk-goban-window.c:797 msgid "/View/_Navigation Toolbar" msgstr "/View/_Navigation Toolbar" #: src/gui-gtk/gtk-goban-window.c:800 src/gui-gtk/gtk-goban-window.c:805 #: src/gui-gtk/gtk-goban-window.c:813 msgid "/View/" msgstr "/View/" #: src/gui-gtk/gtk-goban-window.c:802 msgid "/View/_Game Action Buttons" msgstr "/View/_Game Action Buttons" #: src/gui-gtk/gtk-goban-window.c:807 msgid "/View/Game _Tree" msgstr "/View/Game _Tree" #: src/gui-gtk/gtk-goban-window.c:810 msgid "/View/_Recenter on Current Node" msgstr "/View/_Recenter on Current Node" #: src/gui-gtk/gtk-goban-window.c:815 msgid "/View/_Control Center" msgstr "/View/_Control Center" #: src/gui-gtk/gtk-goban-window.c:820 msgid "/_Play" msgstr "/_Play" #: src/gui-gtk/gtk-goban-window.c:821 msgid "/Play/_Pass" msgstr "/Play/_Pass" #: src/gui-gtk/gtk-goban-window.c:824 src/gui-gtk/gtk-goban-window.c:829 msgid "/Play/" msgstr "/Play/" #: src/gui-gtk/gtk-goban-window.c:826 msgid "/Play/_Resign" msgstr "/Play/_Resign" #: src/gui-gtk/gtk-goban-window.c:831 msgid "/Play/_Adjourn Game" msgstr "/Play/_Adjourn Game" #: src/gui-gtk/gtk-goban-window.c:836 msgid "/_Go" msgstr "/_Go" #: src/gui-gtk/gtk-goban-window.c:837 msgid "/Go/_Previous Node" msgstr "/Go/_Previous Node" #: src/gui-gtk/gtk-goban-window.c:840 msgid "/Go/_Next Node" msgstr "/Go/_Next Node" #: src/gui-gtk/gtk-goban-window.c:843 msgid "/Go/Ten Nodes _Backward" msgstr "/Go/Ten Nodes _Backward" #: src/gui-gtk/gtk-goban-window.c:846 msgid "/Go/Ten Nodes _Forward" msgstr "/Go/Ten Nodes _Forward" #: src/gui-gtk/gtk-goban-window.c:849 src/gui-gtk/gtk-goban-window.c:857 #: src/gui-gtk/gtk-goban-window.c:867 msgid "/Go/" msgstr "/Go/" #: src/gui-gtk/gtk-goban-window.c:851 msgid "/Go/_Root Node" msgstr "/Go/_Root Node" #: src/gui-gtk/gtk-goban-window.c:854 msgid "/Go/Variation _Last Node" msgstr "/Go/Variation _Last Node" #: src/gui-gtk/gtk-goban-window.c:859 msgid "/Go/Pre_vious Variation" msgstr "/Go/Pre_vious Variation" #: src/gui-gtk/gtk-goban-window.c:862 msgid "/Go/Ne_xt Variation" msgstr "/Go/Ne_xt Variation" #: src/gui-gtk/gtk-goban-window.c:868 msgid "/Go/_Go to Named Node..." msgstr "/Go/_Go to Named Node…" #: src/gui-gtk/gtk-goban-window.c:874 msgid "/_Help" msgstr "/_Help" #: src/gui-gtk/gtk-goban-window.c:875 msgid "/Help/_Contents" msgstr "/Help/_Contents" #: src/gui-gtk/gtk-goban-window.c:878 msgid "/Help/_About" msgstr "/Help/_About" #: src/gui-gtk/gtk-goban-window.c:884 msgid "/Move Tool" msgstr "/Move Tool" #: src/gui-gtk/gtk-goban-window.c:885 msgid "/Setup Tool" msgstr "/Setup Tool" #: src/gui-gtk/gtk-goban-window.c:888 msgid "/Cross Markup" msgstr "/Cross Markup" #: src/gui-gtk/gtk-goban-window.c:889 msgid "/Circle Markup" msgstr "/Circle Markup" #: src/gui-gtk/gtk-goban-window.c:890 msgid "/Square Markup" msgstr "/Square Markup" #: src/gui-gtk/gtk-goban-window.c:891 msgid "/Triangle Markup" msgstr "/Triangle Markup" #: src/gui-gtk/gtk-goban-window.c:892 msgid "/Selected Markup" msgstr "/Selected Markup" #: src/gui-gtk/gtk-goban-window.c:895 msgid "/Label Tool" msgstr "/Label Tool" #: src/gui-gtk/gtk-goban-window.c:896 msgid "/Number Tool" msgstr "/Number Tool" #: src/gui-gtk/gtk-goban-window.c:899 msgid "/Scoring Tool" msgstr "/Scoring Tool" #: src/gui-gtk/gtk-goban-window.c:964 msgid "Black" msgstr "Black" #: src/gui-gtk/gtk-goban-window.c:964 msgid "White" msgstr "White" #: src/gui-gtk/gtk-goban-window.c:992 msgid "Pass" msgstr "Pass" #: src/gui-gtk/gtk-goban-window.c:998 msgid "Resign" msgstr "Resign" #: src/gui-gtk/gtk-goban-window.c:1438 #, c-format msgid "Save changes to game record `%s' before closing?" msgstr "Save changes to game record ‘%s’ before closing?" #: src/gui-gtk/gtk-goban-window.c:1447 msgid "Save changes to the untitled game record before closing?" msgstr "Save changes to the untitled game record before closing?" #. TRANSLATORS: Width of this string in default font is used to #. determine the minimal width of the right board window side. #: src/gui-gtk/gtk-goban-window.c:1522 msgid "A good width for the right side to have." msgstr "A good width for the right side to have." #. TRANSLATORS: It can never be 1 stone, always at least 2. #: src/gui-gtk/gtk-goban-window.c:1582 #, c-format msgid "" "Please set up %d (or less)\n" "stone of free handicap" msgid_plural "" "Please set up %d (or less)\n" "stones of free handicap" msgstr[0] "" "Please set up %d (or less)\n" "stone of free handicap" msgstr[1] "" "Please set up %d (or less)\n" "stones of free handicap" #: src/gui-gtk/gtk-goban-window.c:1774 msgid "Adjourn & Save As..." msgstr "Adjourn & Save As…" #: src/gui-gtk/gtk-goban-window.c:1774 msgid "Save As..." msgstr "Save As…" #: src/gui-gtk/gtk-goban-window.c:1923 #, c-format msgid "Error saving to file `%s'" msgstr "Error saving to file ‘%s’" #: src/gui-gtk/gtk-goban-window.c:1937 msgid "" "You can later resume the game by pressing the `Resume Game' button in Quarry " "Control Center, or selecting `Resume Game' item from the `File' menu." msgstr "" "You can later resume the game by pressing the ‘Resume Game’ button in Quarry " "Control Center, or selecting ‘Resume Game’ item from the ‘File’ menu." #: src/gui-gtk/gtk-goban-window.c:1943 #, c-format msgid "The game is adjourned and saved in file `%s'" msgstr "The game is adjourned and saved in file ‘%s’" #: src/gui-gtk/gtk-goban-window.c:1962 msgid "ASCII diagram has been exported to clipboard" msgstr "ASCII diagram has been exported to clipboard" #: src/gui-gtk/gtk-goban-window.c:1975 msgid "Sensei's Library diagram has been exported to clipboard" msgstr "Sensei’s Library diagram has been exported to clipboard" #: src/gui-gtk/gtk-goban-window.c:1990 msgid "" "You can usually paste the diagram in another application using `Ctrl+C' key " "combination or by selecting appropriate menu item." msgstr "" "You can usually paste the diagram in another application using ‘Ctrl+C’ key " "combination or by selecting appropriate menu item." #: src/gui-gtk/gtk-goban-window.c:2446 msgid "Sorry, there are no named nodes in this game tree" msgstr "Sorry, there are no named nodes in this game tree" #: src/gui-gtk/gtk-goban-window.c:2470 msgid "A GUI program for Go, Amazons and Reversi board games" msgstr "A GUI program for Go, Amazons and Reversi board games" #: src/gui-gtk/gtk-goban-window.c:2472 msgid "Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev and others" msgstr "Copyright © 2003, 2004, 2005, 2006 Paul Pogonyshev and others" #: src/gui-gtk/gtk-goban-window.c:2488 msgid "About Quarry" msgstr "About Quarry" #: src/gui-gtk/gtk-goban-window.c:2931 msgid "Really resign this game?" msgstr "Really resign this game?" #: src/gui-gtk/gtk-goban-window.c:2935 msgid "_Resign" msgstr "_Resign" #: src/gui-gtk/gtk-goban-window.c:3524 msgid "Edit Board Label" msgstr "Edit Board Label" #: src/gui-gtk/gtk-goban-window.c:3527 msgid "Add Board Label" msgstr "Add Board Label" #: src/gui-gtk/gtk-goban-window.c:4026 #, c-format msgid "%s (W) vs. %s" msgstr "%s (W) vs. %s" #: src/gui-gtk/gtk-goban-window.c:4050 msgid "Unnamed Game" msgstr "Unnamed Game" #: src/gui-gtk/gtk-goban-window.c:4055 msgid "modified" msgstr "modified" #: src/gui-gtk/gtk-goban-window.c:4088 msgid "[unknown]" msgstr "[unknown]" #: src/gui-gtk/gtk-goban-window.c:4121 src/gui-gtk/gtk-goban-window.c:4126 #, c-format msgid "%d capture" msgid_plural "%d captures" msgstr[0] "%d capture" msgstr[1] "%d captures" #: src/gui-gtk/gtk-goban-window.c:4136 #, c-format msgid "%s %s %.*f komi" msgstr "%s %s %.*f komi" #: src/gui-gtk/gtk-goban-window.c:4147 #, c-format msgid "%s %s %d komi" msgid_plural "%s %s %d komi" msgstr[0] "%s %s %d komi" msgstr[1] "%s %s %d komi" #: src/gui-gtk/gtk-goban-window.c:4163 src/gui-gtk/gtk-goban-window.c:4166 #, c-format msgid "%d disk" msgid_plural "%d disks" msgstr[0] "%d disk" msgstr[1] "%d disks" #: src/gui-gtk/gtk-goban-window.c:4197 #, c-format msgid "Move %d: " msgstr "Move %d: " #: src/gui-gtk/gtk-goban-window.c:4201 #, c-format msgid "Last move: %u, " msgstr "Last move: %u, " #. TRANSLATORS: This is an #. abbreviation of `Black'. #: src/gui-gtk/gtk-goban-window.c:4208 msgid "B " msgstr "B " #. TRANSLATORS: This is an #. abbreviation of `White'. #: src/gui-gtk/gtk-goban-window.c:4211 msgid "W " msgstr "W " #: src/gui-gtk/gtk-goban-window.c:4212 msgid "pass" msgstr "pass" #: src/gui-gtk/gtk-goban-window.c:4215 msgid "Game beginning" msgstr "Game beginning" #: src/gui-gtk/gtk-goban-window.c:4233 msgid "; black to play" msgstr "; black to play" #: src/gui-gtk/gtk-goban-window.c:4233 msgid "; white to play" msgstr "; white to play" #: src/gui-gtk/gtk-goban-window.c:4236 msgid "; game over" msgstr "; game over" #: src/gui-gtk/gtk-goban-window.c:4243 msgid "Black wins" msgstr "Black wins" #: src/gui-gtk/gtk-goban-window.c:4246 msgid "White wins" msgstr "White wins" #: src/gui-gtk/gtk-goban-window.c:4250 msgid "Black wins by forfeit" msgstr "Black wins by forfeit" #: src/gui-gtk/gtk-goban-window.c:4253 msgid "White wins by forfeit" msgstr "White wins by forfeit" #: src/gui-gtk/gtk-goban-window.c:4257 msgid "White resigns" msgstr "White resigns" #: src/gui-gtk/gtk-goban-window.c:4260 msgid "Black resigns" msgstr "Black resigns" #: src/gui-gtk/gtk-goban-window.c:4272 msgid "White runs out of time and loses" msgstr "White runs out of time and loses" #: src/gui-gtk/gtk-goban-window.c:4276 msgid "Black runs out of time and loses" msgstr "Black runs out of time and loses" #: src/gui-gtk/gtk-goban-window.c:4280 msgid "Game is draw" msgstr "Game is draw" #: src/gui-gtk/gtk-goban-window.c:4499 msgid "By Game _Rules (Game Over)" msgstr "By Game _Rules (Game Over)" #: src/gui-gtk/gtk-goban-window.c:4503 msgid "By Game _Rules (Black)" msgstr "By Game _Rules (Black)" #: src/gui-gtk/gtk-goban-window.c:4507 msgid "By Game _Rules (White)" msgstr "By Game _Rules (White)" #: src/gui-gtk/gtk-goban-window.c:4551 msgid "insert node name here" msgstr "insert node name here" #: src/gui-gtk/gtk-goban-window.c:4952 msgid "Set Move Number" msgstr "Set Move Number" #. TRANSLATORS: Note that game name will be in `normal' form. #: src/gui-gtk/gtk-goban-window.c:5062 #, c-format msgid "" "GTP engine `%s' reported it could handle %s game, but failed to initialize " "itself for it" msgstr "" "GTP engine ‘%s’ reported it could handle %s game, but failed to initialize " "itself for it" #: src/gui-gtk/gtk-goban-window.c:5070 #, c-format msgid "GTP engine `%s' cannot handle %dx%d board size, sorry" msgstr "GTP engine ‘%s’ cannot handle %d×%d board size, sorry" #: src/gui-gtk/gtk-goban-window.c:5080 #, c-format msgid "GTP engine `%s' failed to clean the board" msgstr "GTP engine ‘%s’ failed to clean the board" #: src/gui-gtk/gtk-goban-window.c:5086 #, c-format msgid "" "GTP engine `%s' failed to set initial time limits (it could ignore them, but " "not fail)" msgstr "" "GTP engine `%s' failed to set initial time limits (it could ignore them, but " "not fail)" #: src/gui-gtk/gtk-goban-window.c:5094 #, c-format msgid "GTP engine `%s' failed to set handicap stones on board" msgstr "GTP engine ‘%s’ failed to set handicap stones on board" #: src/gui-gtk/gtk-goban-window.c:5108 msgid "This is an engine error. You may want to report it to engine authors." msgstr "This is an engine error. You may want to report it to engine authors." #: src/gui-gtk/gtk-goban-window.c:5392 msgid "GTP engine is scoring..." msgstr "GTP engine is scoring…" #: src/gui-gtk/gtk-goban-window.c:5771 msgid "" "Unable to paste game record fragment from clipboard since it is not intended " "for pasting" msgstr "" "Unable to paste game record fragment from clipboard since it is not intended " "for pasting" #: src/gui-gtk/gtk-goban-window.c:5774 msgid "" "Clipboard SGF probably contains more than one game tree or not a single " "child of the root of the only game tree." msgstr "" "Clipboard SGF probably contains more than one game tree or not a single " "child of the root of the only game tree." #: src/gui-gtk/gtk-goban-window.c:5778 msgid "Unable to paste game record fragment from clipboard" msgstr "Unable to paste game record fragment from clipboard" #. TRANSLATORS: This message is shown if you e.g. copy a part of #. 13x13 game tree and try to paste it into a 19x19 game tree; or #. copy a part of a Reversi game tree and try to paste it into a #. Go game tree. #: src/gui-gtk/gtk-goban-window.c:5784 msgid "Clipboard game record fragment must be of different game or board size." msgstr "" "Clipboard game record fragment must be of different game or board size." #: src/gui-gtk/gtk-goban-window.c:5788 msgid "Clipboard contains an invalid game record fragment (SGF)" msgstr "Clipboard contains an invalid game record fragment (SGF)" #: src/gui-gtk/gtk-goban-window.c:5937 msgid "" "Please select dead stones\n" "to score the game" msgstr "" "Please select dead stones\n" "to score the game" #: src/gui-gtk/gtk-go-to-named-node-dialog.c:135 msgid "Go to Named Node" msgstr "Go to Named Node" #: src/gui-gtk/gtk-go-to-named-node-dialog.c:150 msgid "Node _name:" msgstr "Node _name:" #: src/gui-gtk/gtk-go-to-named-node-dialog.c:156 msgid "Node comment:" msgstr "Node comment:" #: src/gui-gtk/gtk-go-to-named-node-dialog.c:331 msgid "comment|Empty" msgstr "Empty" #: src/gui-gtk/gtk-go-to-named-node-dialog.c:334 msgid "There is no such node" msgstr "There is no such node" #: src/gui-gtk/gtk-gtp-client-interface.c:282 msgid "Engine hung up" msgstr "Engine hung up" #: src/gui-gtk/gtk-gtp-client-interface.c:391 msgid "* ERROR: wrong response format\n" msgstr "* ERROR: wrong response format\n" #: src/gui-gtk/gtk-gtp-client-interface.c:395 msgid "* WARNING: unexpected response:\n" msgstr "* WARNING: unexpected response:\n" #: src/gui-gtk/gtk-gtp-client-interface.c:399 msgid "* ERROR: unrecognized response line:\n" msgstr "* ERROR: unrecognized response line:\n" #: src/gui-gtk/gtk-gtp-client-interface.c:404 #, c-format msgid "* ERROR: mismatched ID (%d expected):\n" msgstr "* ERROR: mismatched ID (%d expected):\n" #: src/gui-gtk/gtk-gtp-client-interface.c:408 msgid "* ERROR: unexpected ID in response (the command had none):\n" msgstr "* ERROR: unexpected ID in response (the command had none):\n" #. TRANSLATORS: Don't put ellipsis here, this string will most #. often go to fixed-width font terminals. #: src/gui-gtk/gtk-gtp-client-interface.c:415 msgid "* WARNING: future GTP version, I don't know about it...\n" msgstr "* WARNING: future GTP version, I don’t know about it...\n" #: src/gui-gtk/gtk-new-game-dialog.c:98 msgid "" "Note that most GTP engines support only one game. Hence certain game / " "computer player combinations may be not possible to play." msgstr "" "Note that most GTP engines support only one game. Hence certain game / " "computer player combinations may be not possible to play." #: src/gui-gtk/gtk-new-game-dialog.c:102 msgid "Fi_xed handicap:" msgstr "Fi_xed handicap:" #: src/gui-gtk/gtk-new-game-dialog.c:102 msgid "_Free handicap:" msgstr "_Free handicap:" #: src/gui-gtk/gtk-new-game-dialog.c:105 msgid "No limit" msgstr "No limit" #: src/gui-gtk/gtk-new-game-dialog.c:105 msgid "Limited time for entire game" msgstr "Limited time for entire game" #: src/gui-gtk/gtk-new-game-dialog.c:106 msgid "Limited time per move" msgstr "Limited time per move" #: src/gui-gtk/gtk-new-game-dialog.c:106 msgid "Canadian overtime" msgstr "Canadian overtime" #: src/gui-gtk/gtk-new-game-dialog.c:124 msgid "New Game" msgstr "New Game" #: src/gui-gtk/gtk-new-game-dialog.c:167 #: src/gui-gtk/gtk-new-game-record-dialog.c:132 msgid "Game" msgstr "Game" #: src/gui-gtk/gtk-new-game-dialog.c:173 #: src/gui-gtk/gtk-resume-game-dialog.c:307 msgid "Hu_man" msgstr "Hu_man" #: src/gui-gtk/gtk-new-game-dialog.c:173 #: src/gui-gtk/gtk-resume-game-dialog.c:308 msgid "Com_puter" msgstr "Com_puter" #: src/gui-gtk/gtk-new-game-dialog.c:174 #: src/gui-gtk/gtk-resume-game-dialog.c:308 msgid "H_uman" msgstr "H_uman" #: src/gui-gtk/gtk-new-game-dialog.c:174 msgid "C_omputer" msgstr "C_omputer" #: src/gui-gtk/gtk-new-game-dialog.c:238 msgid "Manage _Engine List" msgstr "Manage _Engine List" #: src/gui-gtk/gtk-new-game-dialog.c:258 msgid "_Swap" msgstr "_Swap" #: src/gui-gtk/gtk-new-game-dialog.c:287 msgid "Game & Players" msgstr "Game & Players" #: src/gui-gtk/gtk-new-game-dialog.c:362 msgid "Time control _type:" msgstr "Time control _type:" #: src/gui-gtk/gtk-new-game-dialog.c:384 msgid "Time Limit" msgstr "Time Limit" #: src/gui-gtk/gtk-new-game-dialog.c:387 msgid "K_eep track of total time" msgstr "K_eep track of total time" #: src/gui-gtk/gtk-new-game-dialog.c:407 msgid "Time _limit for game:" msgstr "Time _limit for game:" #: src/gui-gtk/gtk-new-game-dialog.c:413 msgid "(per player)" msgstr "(per player)" #: src/gui-gtk/gtk-new-game-dialog.c:427 msgid "Time _limit for move:" msgstr "Time _limit for move:" #: src/gui-gtk/gtk-new-game-dialog.c:461 msgid "_Overtime period length:" msgstr "_Overtime period length:" #: src/gui-gtk/gtk-new-game-dialog.c:478 msgid "Mo_ves per overtime:" msgstr "Mo_ves per overtime:" #: src/gui-gtk/gtk-new-game-record-dialog.c:119 msgid "New Game Record" msgstr "New Game Record" #: src/gui-gtk/gtk-new-game-record-dialog.c:189 msgid "_Place stones" msgstr "_Place stones" #: src/gui-gtk/gtk-new-game-record-dialog.c:265 msgid "_White player:" msgstr "_White player:" #: src/gui-gtk/gtk-new-game-record-dialog.c:276 msgid "_Black player:" msgstr "_Black player:" #: src/gui-gtk/gtk-new-game-record-dialog.c:287 msgid "Game _name:" msgstr "Game _name:" #: src/gui-gtk/gtk-new-game-record-dialog.c:300 msgid "" "You can always change and expand game information later. Just choose `Edit/" "Game Information' menu item or press `Info' button on the main toolbar." msgstr "" "You can always change and expand game information later. Just choose ‘Edit/" "Game Information’ menu item or press ‘Info’ button on the main toolbar." #: src/gui-gtk/gtk-new-game-record-dialog.c:310 #: src/gui-gtk/gtk-resume-game-dialog.c:227 msgid "Short Game Information" msgstr "Short Game Information" #: src/gui-gtk/gtk-parser-interface.c:58 #, c-format msgid "Error reading file `%s'" msgstr "Error reading file ‘%s’" #: src/gui-gtk/gtk-parser-interface.c:60 #, c-format msgid "File `%s' doesn't appear to be a valid SGF file" msgstr "File ‘%s’ doesn’t appear to be a valid SGF file" #: src/gui-gtk/gtk-parser-interface.c:63 msgid "" "Please check that the file exists and its permission allow you to read it." msgstr "" "Please check that the file exists and its permission allow you to read it." #: src/gui-gtk/gtk-parser-interface.c:67 msgid "" "Quarry uses SGF file format for storing game records. SGF files would " "normally have `sgf' extension, but that's not necessarily true. Please make " "sure you select a proper SGF file." msgstr "" "Quarry uses SGF file format for storing game records. SGF files would " "normally have ‘sgf’ extension, but that’s not necessarily true. Please make " "sure you select a proper SGF file." #: src/gui-gtk/gtk-parser-interface.c:101 msgid "Open SGF File..." msgstr "Open SGF File…" #: src/gui-gtk/gtk-parser-interface.c:192 #, c-format msgid "Parsing file `%s'..." msgstr "Parsing file ‘%s’…" #: src/gui-gtk/gtk-preferences.c:431 msgid "General" msgstr "General" #: src/gui-gtk/gtk-preferences.c:434 msgid "Interface" msgstr "Interface" #: src/gui-gtk/gtk-preferences.c:435 msgid "General Interface" msgstr "General Interface" #: src/gui-gtk/gtk-preferences.c:437 msgid "Editing & Viewing" msgstr "Editing & Viewing" #: src/gui-gtk/gtk-preferences.c:440 src/gui-gtk/gtk-preferences.c:441 msgid "Game Tree" msgstr "Game Tree" #: src/gui-gtk/gtk-preferences.c:444 msgid "GTP" msgstr "GTP" #: src/gui-gtk/gtk-preferences.c:447 src/gui-gtk/gtk-preferences.c:448 msgid "GTP Engines" msgstr "GTP Engines" #: src/gui-gtk/gtk-preferences.c:451 msgid "Game Records (SGF)" msgstr "Game Records (SGF)" #: src/gui-gtk/gtk-preferences.c:454 msgid "Saving" msgstr "Saving" #: src/gui-gtk/gtk-preferences.c:455 msgid "Saving Game Records" msgstr "Saving Game Records" #: src/gui-gtk/gtk-preferences.c:458 msgid "Board Appearance" msgstr "Board Appearance" #: src/gui-gtk/gtk-preferences.c:462 msgid "Go Board Appearance" msgstr "Go Board Appearance" #: src/gui-gtk/gtk-preferences.c:465 msgid "Amazons Board Appearance" msgstr "Amazons Board Appearance" #: src/gui-gtk/gtk-preferences.c:468 msgid "Reversi Board Appearance" msgstr "Reversi Board Appearance" #: src/gui-gtk/gtk-preferences.c:478 msgid "Preferences" msgstr "Preferences" #: src/gui-gtk/gtk-preferences.c:515 msgid "Categor_y:" msgstr "Categor_y:" #: src/gui-gtk/gtk-preferences.c:641 msgid "Use _newer (GTK+ 2.4) file chooser" msgstr "Use _newer (GTK+ 2.4) file chooser" #: src/gui-gtk/gtk-preferences.c:642 msgid "Use _old-style file selection dialog" msgstr "Use _old-style file selection dialog" #: src/gui-gtk/gtk-preferences.c:672 msgid "File Chooser Dialog Style" msgstr "File Chooser Dialog Style" #: src/gui-gtk/gtk-preferences.c:688 msgid "_Main toolbar style:" msgstr "_Main toolbar style:" #: src/gui-gtk/gtk-preferences.c:692 msgid "_Editing toolbar style:" msgstr "_Editing toolbar style:" #: src/gui-gtk/gtk-preferences.c:696 msgid "N_avigation toolbar style:" msgstr "N_avigation toolbar style:" #: src/gui-gtk/gtk-preferences.c:705 msgid "Toolbar Styles" msgstr "Toolbar Styles" #: src/gui-gtk/gtk-preferences.c:725 msgid "Desktop default" msgstr "Desktop default" #: src/gui-gtk/gtk-preferences.c:726 msgid "Text below icons" msgstr "Text below icons" #: src/gui-gtk/gtk-preferences.c:732 msgid "Text beside important icons" msgstr "Text beside important icons" #: src/gui-gtk/gtk-preferences.c:735 msgid "Icons only" msgstr "Icons only" #: src/gui-gtk/gtk-preferences.c:736 msgid "Text only" msgstr "Text only" #: src/gui-gtk/gtk-preferences.c:792 msgid "Show" msgstr "Show" #: src/gui-gtk/gtk-preferences.c:799 msgid "Name" msgstr "Name" #: src/gui-gtk/gtk-preferences.c:808 msgid "_List of GTP engines:" msgstr "_List of GTP engines:" #: src/gui-gtk/gtk-preferences.c:856 msgid "Name:" msgstr "Name:" #: src/gui-gtk/gtk-preferences.c:865 msgid "Version:" msgstr "Version:" #: src/gui-gtk/gtk-preferences.c:875 src/gui-gtk/gtk-preferences.c:1630 msgid "Supported game:" msgstr "Supported game:" #: src/gui-gtk/gtk-preferences.c:889 msgid "Command line:" msgstr "Command line:" #: src/gui-gtk/gtk-preferences.c:914 msgid "GTP Engine Information" msgstr "GTP Engine Information" #: src/gui-gtk/gtk-preferences.c:935 msgid "_Always" msgstr "_Always" #: src/gui-gtk/gtk-preferences.c:935 msgid "A_utomatically" msgstr "A_utomatically" #: src/gui-gtk/gtk-preferences.c:935 msgid "_Never" msgstr "_Never" #: src/gui-gtk/gtk-preferences.c:937 msgid "Al_ways" msgstr "Al_ways" #: src/gui-gtk/gtk-preferences.c:937 msgid "Aut_omatically" msgstr "Aut_omatically" #: src/gui-gtk/gtk-preferences.c:937 msgid "Ne_ver" msgstr "Ne_ver" #: src/gui-gtk/gtk-preferences.c:939 msgid "Scroll _minimal distance" msgstr "Scroll _minimal distance" #: src/gui-gtk/gtk-preferences.c:940 msgid "_Recenter view on the current node" msgstr "_Recenter view on the current node" #: src/gui-gtk/gtk-preferences.c:943 msgid "" "In automatic mode the game tree is shown only if it has at least one " "variation. In any case, you can show/hide game tree in each window " "separately." msgstr "" "In automatic mode the game tree is shown only if it has at least one " "variation. In any case, you can show/hide game tree in each window " "separately." #: src/gui-gtk/gtk-preferences.c:947 msgid "" "In automatic mode the game tree view scrolls to show the current node only " "if it has been showing current node before. I.e. unless you scrolled it away " "manually." msgstr "" "In automatic mode the game tree view scrolls to show the current node only " "if it has been showing current node before. I.e. unless you scrolled it away " "manually." #: src/gui-gtk/gtk-preferences.c:992 msgid "Show Game Tree" msgstr "Show Game Tree" #: src/gui-gtk/gtk-preferences.c:1039 msgid "Track Tree's Current Node" msgstr "Track Tree’s Current Node" #: src/gui-gtk/gtk-preferences.c:1042 msgid "Show _tooltips" msgstr "Show _tooltips" #: src/gui-gtk/gtk-preferences.c:1049 msgid "Tooltips" msgstr "Tooltips" #: src/gui-gtk/gtk-preferences.c:1065 msgid "Always use _UTF-8 (recommended)" msgstr "Always use _UTF-8 (recommended)" #: src/gui-gtk/gtk-preferences.c:1066 msgid "Preserve _original encoding" msgstr "Preserve _original encoding" #: src/gui-gtk/gtk-preferences.c:1068 msgid "" "Note that many characters cannot be represented in non-UTF-8 encodings and " "thus some information may be lost if you use them. Quarry also works fastest " "with UTF-8; this may be important if you have very large SGF files." msgstr "" "Note that many characters cannot be represented in non-UTF-8 encodings and " "thus some information may be lost if you use them. Quarry also works fastest " "with UTF-8; this may be important if you have very large SGF files." #: src/gui-gtk/gtk-preferences.c:1093 msgid "Encoding" msgstr "Encoding" #: src/gui-gtk/gtk-preferences.c:1103 msgid "_Relative to stone size" msgstr "_Relative to stone size" #: src/gui-gtk/gtk-preferences.c:1104 msgid "On _white stones:" msgstr "On _white stones:" #: src/gui-gtk/gtk-preferences.c:1105 msgid "On _black stones:" msgstr "On _black stones:" #: src/gui-gtk/gtk-preferences.c:1106 msgid "On _empty intersections:" msgstr "On _empty intersections:" #: src/gui-gtk/gtk-preferences.c:1120 msgid "_Relative to amazon size" msgstr "_Relative to amazon size" #: src/gui-gtk/gtk-preferences.c:1121 msgid "On _white amazons:" msgstr "On _white amazons:" #: src/gui-gtk/gtk-preferences.c:1122 msgid "On _black amazons:" msgstr "On _black amazons:" #: src/gui-gtk/gtk-preferences.c:1123 src/gui-gtk/gtk-preferences.c:1182 msgid "On _empty fields:" msgstr "On _empty fields:" #: src/gui-gtk/gtk-preferences.c:1142 msgid "Pick Checkerboard Pattern Color" msgstr "Pick Checkerboard Pattern Color" #: src/gui-gtk/gtk-preferences.c:1151 msgid "Checkerboard _pattern color:" msgstr "Checkerboard _pattern color:" #: src/gui-gtk/gtk-preferences.c:1167 msgid "Checkerboard pattern _opacity:" msgstr "Checkerboard pattern _opacity:" #: src/gui-gtk/gtk-preferences.c:1179 msgid "_Relative to disk size" msgstr "_Relative to disk size" #: src/gui-gtk/gtk-preferences.c:1180 msgid "On _white disks:" msgstr "On _white disks:" #: src/gui-gtk/gtk-preferences.c:1181 msgid "On _black disks:" msgstr "On _black disks:" #: src/gui-gtk/gtk-preferences.c:1195 msgid "Use _texture:" msgstr "Use _texture:" #: src/gui-gtk/gtk-preferences.c:1196 msgid "Use _solid color:" msgstr "Use _solid color:" #: src/gui-gtk/gtk-preferences.c:1271 msgid "Choose a Background Texture..." msgstr "Choose a Background Texture…" #: src/gui-gtk/gtk-preferences.c:1282 msgid "Pick Background Color" msgstr "Pick Background Color" #: src/gui-gtk/gtk-preferences.c:1296 msgid "Pick Color for Grid and Labels" msgstr "Pick Color for Grid and Labels" #: src/gui-gtk/gtk-preferences.c:1306 msgid "_Grid and labels color:" msgstr "_Grid and labels color:" #: src/gui-gtk/gtk-preferences.c:1345 msgid "_Theme:" msgstr "_Theme:" #: src/gui-gtk/gtk-preferences.c:1354 msgid "Use theme _defaults" msgstr "Use theme _defaults" #: src/gui-gtk/gtk-preferences.c:1371 msgid "_Size:" msgstr "_Size:" #: src/gui-gtk/gtk-preferences.c:1398 msgid "_Opacity:" msgstr "_Opacity:" #: src/gui-gtk/gtk-preferences.c:1413 msgid "Size & Opacity" msgstr "Size & Opacity" #: src/gui-gtk/gtk-preferences.c:1429 msgid "Color" msgstr "Color" #: src/gui-gtk/gtk-preferences.c:1443 msgid "Pick Color for Markup" msgstr "Pick Color for Markup" #: src/gui-gtk/gtk-preferences.c:1482 msgid "Background" msgstr "Background" #: src/gui-gtk/gtk-preferences.c:1484 msgid "Markup" msgstr "Markup" #: src/gui-gtk/gtk-preferences.c:1630 msgid "Supported games:" msgstr "Supported games:" #: src/gui-gtk/gtk-preferences.c:1637 msgid "This engine comes from site configuration." msgstr "This engine comes from site configuration." #: src/gui-gtk/gtk-preferences.c:1860 msgid "" "You can use `%n' and `%v' strings in Screen name field. They will " "substituted with name and version of the engine correspondingly. By default, " "`%n %v' is used." msgstr "" "You can use ‘%n’ and ‘%v’ strings in Screen name field. They will " "substituted with name and version of the engine correspondingly. By default, " "‘%n %v’ is used." #: src/gui-gtk/gtk-preferences.c:1908 msgid "Modify GTP Engine Information" msgstr "Modify GTP Engine Information" #: src/gui-gtk/gtk-preferences.c:1909 msgid "New GTP Engine" msgstr "New GTP Engine" #: src/gui-gtk/gtk-preferences.c:1955 msgid "Command _line:" msgstr "Command _line:" #: src/gui-gtk/gtk-preferences.c:1961 msgid "Choose GTP Engine..." msgstr "Choose GTP Engine…" #: src/gui-gtk/gtk-preferences.c:1972 msgid "Screen _name:" msgstr "Screen _name:" #: src/gui-gtk/gtk-preferences.c:2018 msgid "Querying engine's name, version and known commands..." msgstr "Querying engine’s name, version and known commands…" #: src/gui-gtk/gtk-preferences.c:2039 msgid "" "Please make sure you typed engine's filename correctly and that you have " "permission to execute it." msgstr "" "Please make sure you typed engine’s filename correctly and that you have " "permission to execute it." #: src/gui-gtk/gtk-preferences.c:2078 msgid "Waiting for the engine to quit..." msgstr "Waiting for the engine to quit…" #: src/gui-gtk/gtk-preferences.c:2182 msgid "" "The engine might have crashed, quit prematurely or disconnected. Please " "verify command line, including options, and consult engine's documentation " "if needed." msgstr "" "The engine might have crashed, quit prematurely or disconnected. Please " "verify command line, including options, and consult engine’s documentation " "if needed." #: src/gui-gtk/gtk-preferences.c:2197 #, c-format msgid "Lost connection to GTP Engine (%s)" msgstr "Lost connection to GTP Engine (%s)" #: src/gui-gtk/gtk-preferences.c:3011 msgid "" "Perhaps engine's binary has been deleted or changed. You will probably need " "to alter engine's command line in the Preferences dialog." msgstr "" "Perhaps engine’s binary has been deleted or changed. You will probably need " "to alter engine’s command line in the Preferences dialog." #: src/gui-gtk/gtk-resume-game-dialog.c:92 msgid "Resume Game..." msgstr "Resume Game…" #: src/gui-gtk/gtk-resume-game-dialog.c:115 #, c-format msgid "The game stored in file `%s' (%s) is not supported by Quarry" msgstr "The game stored in file ‘%s’ (%s) is not supported by Quarry" #: src/gui-gtk/gtk-resume-game-dialog.c:138 msgid "" "This game appears to have been finished. Open it for viewing and/or editing " "instead?" msgstr "" "This game appears to have been finished. Open it for viewing and/or editing " "instead?" #: src/gui-gtk/gtk-resume-game-dialog.c:212 msgid "Resuming Game" msgstr "Resuming Game" #: src/gui-gtk/gtk-resume-game-dialog.c:214 msgid "_Resume" msgstr "_Resume" #: src/gui-gtk/gtk-resume-game-dialog.c:231 msgid "Game:" msgstr "Game:" #: src/gui-gtk/gtk-resume-game-dialog.c:240 msgid "Board size:" msgstr "Board size:" #: src/gui-gtk/gtk-resume-game-dialog.c:258 msgid "Handicap:" msgstr "Handicap:" #: src/gui-gtk/gtk-resume-game-dialog.c:262 msgid "handicap|Not set" msgstr "Not set" #: src/gui-gtk/gtk-resume-game-dialog.c:268 msgid "Komi:" msgstr "Komi:" #: src/gui-gtk/gtk-resume-game-dialog.c:271 msgid "komi|Not set" msgstr "Not set" #: src/gui-gtk/gtk-resume-game-dialog.c:294 msgid "Filename:" msgstr "Filename:" #: src/gui-gtk/gtk-resume-game-dialog.c:307 msgid "Compu_ter" msgstr "Compu_ter" #: src/gui-gtk/quarry-find-dialog.c:104 msgid "Whole game _tree" msgstr "Whole game _tree" #: src/gui-gtk/quarry-find-dialog.c:104 msgid "Current no_de only" msgstr "Current no_de only" #: src/gui-gtk/quarry-find-dialog.c:107 msgid "C_omments & node names" msgstr "C_omments & node names" #: src/gui-gtk/quarry-find-dialog.c:108 msgid "Comm_ents only" msgstr "Comm_ents only" #: src/gui-gtk/quarry-find-dialog.c:108 msgid "Node na_mes only" msgstr "Node na_mes only" #: src/gui-gtk/quarry-find-dialog.c:154 msgid "Search _for:" msgstr "Search _for:" #: src/gui-gtk/quarry-find-dialog.c:161 msgid "Case _sensitive" msgstr "Case _sensitive" #: src/gui-gtk/quarry-find-dialog.c:169 msgid "Whole _words only" msgstr "Whole _words only" #: src/gui-gtk/quarry-find-dialog.c:177 msgid "Wrap _around" msgstr "Wrap _around" #: src/gui-gtk/quarry-find-dialog.c:191 msgid "A_uto-close this dialog" msgstr "A_uto-close this dialog" #: src/gui-gtk/quarry-find-dialog.c:202 msgid "Options" msgstr "Options" #: src/gui-gtk/quarry-find-dialog.c:251 msgid "Search Scope" msgstr "Search Scope" #: src/gui-gtk/quarry-move-number-dialog.c:66 #: src/gui-gtk/quarry-move-number-dialog.c:148 msgid "Use se_quential move number" msgstr "Use se_quential move number" #: src/gui-gtk/quarry-move-number-dialog.c:66 msgid "_Set specific move number:" msgstr "_Set specific move number:" #: src/gui-gtk/quarry-save-confirmation-dialog.c:89 msgid "Close _without Saving" msgstr "Close _without Saving" #: src/gui-gtk/quarry-save-confirmation-dialog.c:173 #, c-format msgid "" "If you don't save, changes from the last %d second will be lost permanently." msgid_plural "" "If you don't save, changes from the last %d seconds will be lost permanently." msgstr[0] "" "If you don’t save, changes from the last %d second will be lost permanently." msgstr[1] "" "If you don’t save, changes from the last %d seconds will be lost permanently." #: src/gui-gtk/quarry-save-confirmation-dialog.c:181 msgid "If you don't save, changes from the last minute will be discarded." msgstr "If you don’t save, changes from the last minute will be discarded." #. TRANSLATORS: Cannot be one minute one second, actually. #: src/gui-gtk/quarry-save-confirmation-dialog.c:187 #, c-format msgid "" "If you don't save, changes from the last minute and %d second will be lost " "permanently." msgid_plural "" "If you don't save, changes from the last minute and %d seconds will be lost " "permanently." msgstr[0] "" "If you don’t save, changes from the last minute and %d second will be lost " "permanently." msgstr[1] "" "If you don’t save, changes from the last minute and %d seconds will be lost " "permanently." #: src/gui-gtk/quarry-save-confirmation-dialog.c:198 #, c-format msgid "" "If you don't save, changes from the last %d minute will be lost permanently." msgid_plural "" "If you don't save, changes from the last %d minutes will be lost permanently." msgstr[0] "" "If you don’t save, changes from the last %d minute will be lost permanently." msgstr[1] "" "If you don’t save, changes from the last %d minutes will be lost permanently." #. TRANSLATORS: Cannot be one hour one minute, actually. #: src/gui-gtk/quarry-save-confirmation-dialog.c:212 #, c-format msgid "" "If you don't save, changes from the last hour and %d minute will be lost " "permanently." msgid_plural "" "If you don't save, changes from the last hour and %d minutes will be lost " "permanently." msgstr[0] "" "If you don’t save, changes from the last hour and %d minute will be lost " "permanently." msgstr[1] "" "If you don’t save, changes from the last hour and %d minutes will be lost " "permanently." #: src/gui-gtk/quarry-save-confirmation-dialog.c:224 #, c-format msgid "" "If you don't save, changes from the last %d hour will be lost permanently." msgid_plural "" "If you don't save, changes from the last %d hours will be lost permanently." msgstr[0] "" "If you don’t save, changes from the last %d hour will be lost permanently." msgstr[1] "" "If you don’t save, changes from the last %d hours will be lost permanently." #: src/gui-gtk/quarry-stock.c:56 msgid "_New Game" msgstr "_New Game" #: src/gui-gtk/quarry-stock.c:57 msgid "_Open Game Record" msgstr "_Open Game Record" #: src/gui-gtk/quarry-stock.c:59 msgid "_Browse..." msgstr "_Browse…" #: src/gui-gtk/quarry-stock.c:60 msgid "Crea_te" msgstr "Crea_te" #: src/gui-gtk/quarry-stock.c:61 msgid "_Done" msgstr "_Done" #: src/gui-gtk/quarry-stock.c:62 msgid "_Go to Node" msgstr "_Go to Node" #: src/gui-gtk/quarry-stock.c:63 msgid "_Modify" msgstr "_Modify" #: src/gui-gtk/quarry-stock.c:64 msgid "Move _Up" msgstr "Move _Up" #: src/gui-gtk/quarry-stock.c:65 msgid "Move _Down" msgstr "Move _Down" #: src/gui-gtk/quarry-stock.c:66 msgid "find|_Next" msgstr "_Next" #: src/gui-gtk/quarry-stock.c:67 msgid "_Overwrite" msgstr "_Overwrite" #: src/gui-gtk/quarry-stock.c:68 msgid "_Play" msgstr "_Play" #: src/gui-gtk/quarry-stock.c:69 msgid "find|_Previous" msgstr "_Previous" #. TRANSLATORS: This is only used for non-integral scores. You #. should also add translation of `points' if it is required by #. your language. #: src/board/board.c:897 #, c-format msgid "Black wins by %.*f" msgstr "Black wins by %.*f" #. TRANSLATORS: This is only used for non-integral scores. You #. should also add translation of `points' if it is required by #. your language. #: src/board/board.c:904 #, c-format msgid "White wins by %.*f" msgstr "White wins by %.*f" #: src/board/board.c:915 #, c-format msgid "Black wins by %d" msgid_plural "Black wins by %d" msgstr[0] "Black wins by %d" msgstr[1] "Black wins by %d" #: src/board/board.c:923 #, c-format msgid "White wins by %d" msgid_plural "White wins by %d" msgstr[0] "White wins by %d" msgstr[1] "White wins by %d" #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:29 msgid "Go" msgstr "Go" #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:43 msgid "Reversi" msgstr "Reversi" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:58 msgid "chess" msgstr "chess" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:73 msgid "Gomoku" msgstr "Gomoku" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:88 msgid "Nine Men's Morris" msgstr "Nine Men’s Morris" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:103 msgid "Backgammon" msgstr "Backgammon" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:118 msgid "Chinese chess" msgstr "Chinese chess" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:133 msgid "Shogi" msgstr "Shogi" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:148 msgid "Lines of Action" msgstr "Lines of Action" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:163 msgid "Ataxx" msgstr "Ataxx" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:178 msgid "Hex" msgstr "Hex" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:193 msgid "Jungle" msgstr "Jungle" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:208 msgid "Neutron" msgstr "Neutron" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:223 msgid "Philosopher's Football" msgstr "Philosopher’s Football" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:238 msgid "Quadrature" msgstr "Quadrature" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:253 msgid "Trax" msgstr "Trax" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:268 msgid "Tantrix" msgstr "Tantrix" #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:282 msgid "Amazons" msgstr "Amazons" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:297 msgid "Octi" msgstr "Octi" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:312 msgid "Gess" msgstr "Gess" #: src/board/go.c:1323 #, c-format msgid "White: %d territory" msgid_plural "White: %d territory" msgstr[0] "White: %d territory" msgstr[1] "White: %d territory" #: src/board/go.c:1328 src/board/go.c:1365 #, c-format msgid " + %d capture" msgid_plural " + %d captures" msgstr[0] " + %d capture" msgstr[1] " + %d captures" #. TRANSLATORS: e.g. `` + 6.5 komi = #. 87.5''. This is used only with #. fractional komi. #: src/board/go.c:1337 #, c-format msgid " %s %.*f komi = %.*f\n" msgstr " %s %.*f komi = %.*f\n" #. TRANSLATORS: e.g. `` + 6 komi = 87''. #: src/board/go.c:1351 #, c-format msgid " %s %d komi = %d\n" msgid_plural " %s %d komi = %d\n" msgstr[0] " %s %d komi = %d\n" msgstr[1] " %s %d komi = %d\n" #: src/board/go.c:1360 #, c-format msgid "Black: %d territory" msgid_plural "Black: %d territory" msgstr[0] "Black: %d territory" msgstr[1] "Black: %d territory" #: src/board/go.c:1374 msgid "The game is draw" msgstr "The game is draw" quarry-0.2.0/po/en_GB.po0000644000175000017500000015664410524133117013443 0ustar bartbart# English (British) translation of Quarry. # Copyright (C) 2004, 2005, 2006 Paul Pogonyshev # This file is distributed under the same license as the Quarry package. # Paul Pogonyshev , 2005. # msgid "" msgstr "" "Project-Id-Version: Quarry\n" "Report-Msgid-Bugs-To: quarry-dev@gna.org\n" "POT-Creation-Date: 2006-11-07 18:33+0200\n" "PO-Revision-Date: 2006-10-28 15:05+0300\n" "Last-Translator: Paul Pogonyshev \n" "Language-Team: \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 ? 0 : 1;\n" #: src/gui-gtk/gtk-add-or-edit-label-dialog.c:73 msgid "" "Although board labels are not limited in length, it is better to use only " "one or two characters long labels. Longer labels will not be visible " "immediately or at all in most clients." msgstr "" "Although board labels are not limited in length, it is better to use only " "one or two characters long labels. Longer labels will not be visible " "immediately or at all in most clients." #: src/gui-gtk/gtk-add-or-edit-label-dialog.c:87 msgid "Label _text:" msgstr "Label _text:" #: src/gui-gtk/gtk-color-button.c:581 msgid "Pick a Color" msgstr "Pick a Colour" #: src/gui-gtk/gtk-control-center.c:64 msgid "Quarry Control Center" msgstr "Quarry Control Centre" #: src/gui-gtk/gtk-control-center.c:80 msgid "Ne_w Game Record" msgstr "Ne_w Game Record" #: src/gui-gtk/gtk-control-center.c:96 msgid "_Resume Game" msgstr "_Resume Game" #: src/gui-gtk/gtk-file-dialog.c:281 msgid "" "Note that all information in the existing file will be lost permanently if " "you choose to overwrite it." msgstr "" "Note that all information in the existing file will be lost permanently if " "you choose to overwrite it." #: src/gui-gtk/gtk-file-dialog.c:284 #, c-format msgid "" "File named `%s' already exists. Do you want to overwrite it with the one you " "are saving?" msgstr "" "File named ‘%s’ already exists. Do you want to overwrite it with the one you " "are saving?" #: src/gui-gtk/gtk-game-info-dialog.c:231 #: src/gui-gtk/gtk-resume-game-dialog.c:325 msgid "N_ame:" msgstr "N_ame:" #: src/gui-gtk/gtk-game-info-dialog.c:231 #: src/gui-gtk/gtk-resume-game-dialog.c:324 msgid "_Name:" msgstr "_Name:" #: src/gui-gtk/gtk-game-info-dialog.c:238 msgid "Team:" msgstr "Team:" #: src/gui-gtk/gtk-game-info-dialog.c:244 msgid "Rank:" msgstr "Rank:" #: src/gui-gtk/gtk-game-info-dialog.c:256 #: src/gui-gtk/gtk-new-game-dialog.c:226 #: src/gui-gtk/gtk-resume-game-dialog.c:364 msgid "Black Player" msgstr "Black Player" #: src/gui-gtk/gtk-game-info-dialog.c:256 #: src/gui-gtk/gtk-new-game-dialog.c:226 #: src/gui-gtk/gtk-resume-game-dialog.c:364 msgid "White Player" msgstr "White Player" #: src/gui-gtk/gtk-game-info-dialog.c:270 msgid "_Game name:" msgstr "_Game name:" #: src/gui-gtk/gtk-game-info-dialog.c:273 msgid "_Place:" msgstr "_Place:" #: src/gui-gtk/gtk-game-info-dialog.c:277 msgid "Da_te:" msgstr "Da_te:" #: src/gui-gtk/gtk-game-info-dialog.c:280 msgid "_Event:" msgstr "_Event:" #: src/gui-gtk/gtk-game-info-dialog.c:284 msgid "R_ound:" msgstr "R_ound:" #: src/gui-gtk/gtk-game-info-dialog.c:295 #: src/gui-gtk/gtk-game-info-dialog.c:535 #: src/gui-gtk/gtk-game-info-dialog.c:541 msgid "Game Information" msgstr "Game Information" #: src/gui-gtk/gtk-game-info-dialog.c:298 msgid "Rule _set:" msgstr "Rule _set:" #: src/gui-gtk/gtk-game-info-dialog.c:324 #: src/gui-gtk/gtk-new-game-record-dialog.c:187 msgid "Han_dicap:" msgstr "Han_dicap:" #: src/gui-gtk/gtk-game-info-dialog.c:347 #: src/gui-gtk/gtk-new-game-dialog.c:574 #: src/gui-gtk/gtk-new-game-record-dialog.c:231 msgid "_Komi:" msgstr "_Komi:" #: src/gui-gtk/gtk-game-info-dialog.c:374 #: src/gui-gtk/gtk-new-game-dialog.c:444 msgid "_Main time:" msgstr "_Main time:" #: src/gui-gtk/gtk-game-info-dialog.c:386 msgid "O_vertime:" msgstr "O_vertime:" #: src/gui-gtk/gtk-game-info-dialog.c:397 #: src/gui-gtk/gtk-new-game-dialog.c:602 msgid "Game Rules" msgstr "Game Rules" #: src/gui-gtk/gtk-game-info-dialog.c:412 msgid "General" msgstr "General" #: src/gui-gtk/gtk-game-info-dialog.c:415 msgid "Game re_sult:" msgstr "Game re_sult:" #: src/gui-gtk/gtk-game-info-dialog.c:419 msgid "_Opening played:" msgstr "_Opening played:" #: src/gui-gtk/gtk-game-info-dialog.c:449 msgid "Comment / _description:" msgstr "Comment / _description:" #: src/gui-gtk/gtk-game-info-dialog.c:463 msgid "Description & Result" msgstr "Description & Result" #: src/gui-gtk/gtk-game-info-dialog.c:466 msgid "Co_pyright string:" msgstr "Co_pyright string:" #: src/gui-gtk/gtk-game-info-dialog.c:470 msgid "_Annotator:" msgstr "_Annotator:" #: src/gui-gtk/gtk-game-info-dialog.c:474 msgid "_Source:" msgstr "_Source:" #: src/gui-gtk/gtk-game-info-dialog.c:478 msgid "_Entered by:" msgstr "_Entered by:" #: src/gui-gtk/gtk-game-info-dialog.c:488 msgid "Copyright & Credits" msgstr "Copyright & Credits" #: src/gui-gtk/gtk-game-info-dialog.c:502 msgid "Game Record" msgstr "Game Record" #: src/gui-gtk/gtk-games.c:39 msgid "_Go" msgstr "_Go" #: src/gui-gtk/gtk-games.c:40 msgid "_Amazons" msgstr "_Amazons" #: src/gui-gtk/gtk-games.c:41 msgid "_Reversi" msgstr "_Reversi" #: src/gui-gtk/gtk-games.c:45 msgid "Go Rules" msgstr "Go Rules" #: src/gui-gtk/gtk-games.c:46 msgid "Amazons Rules" msgstr "Amazons Rules" #: src/gui-gtk/gtk-games.c:47 msgid "Reversi Rules" msgstr "Reversi Rules" #: src/gui-gtk/gtk-games.c:180 msgid "Board _size:" msgstr "Board _size:" #: src/gui-gtk/gtk-goban-window.c:460 msgid "Open" msgstr "Open" #: src/gui-gtk/gtk-goban-window.c:460 msgid "Open a game record" msgstr "Open a game record" #: src/gui-gtk/gtk-goban-window.c:465 msgid "Save" msgstr "Save" #: src/gui-gtk/gtk-goban-window.c:465 msgid "Save the current file" msgstr "Save the current file" #: src/gui-gtk/gtk-goban-window.c:470 src/gui-gtk/gtk-goban-window.c:2025 msgid "Find" msgstr "Find" #: src/gui-gtk/gtk-goban-window.c:470 msgid "Search for a string in comments" msgstr "Search for a string in comments" #: src/gui-gtk/gtk-goban-window.c:475 msgid "Info" msgstr "Info" #: src/gui-gtk/gtk-goban-window.c:475 msgid "View and edit game information" msgstr "View and edit game information" #: src/gui-gtk/gtk-goban-window.c:481 msgid "Undo" msgstr "Undo" #: src/gui-gtk/gtk-goban-window.c:481 msgid "Undo the last action" msgstr "Undo the last action" #: src/gui-gtk/gtk-goban-window.c:486 msgid "Redo" msgstr "Redo" #: src/gui-gtk/gtk-goban-window.c:486 msgid "Redo the last undone action" msgstr "Redo the last undone action" #: src/gui-gtk/gtk-goban-window.c:491 msgid "Delete" msgstr "Delete" #: src/gui-gtk/gtk-goban-window.c:491 msgid "Delete the current node" msgstr "Delete the current node" #: src/gui-gtk/gtk-goban-window.c:497 msgid "Root" msgstr "Root" #: src/gui-gtk/gtk-goban-window.c:497 msgid "Go to the root node" msgstr "Go to the root node" #: src/gui-gtk/gtk-goban-window.c:502 msgid "Back" msgstr "Back" #: src/gui-gtk/gtk-goban-window.c:502 msgid "Go to the previous node" msgstr "Go to the previous node" #: src/gui-gtk/gtk-goban-window.c:507 msgid "Forward" msgstr "Forward" #: src/gui-gtk/gtk-goban-window.c:507 msgid "Go to the next node" msgstr "Go to the next node" #: src/gui-gtk/gtk-goban-window.c:512 msgid "End" msgstr "End" #: src/gui-gtk/gtk-goban-window.c:512 msgid "Go to the current variation's last node" msgstr "Go to the current variation’s last node" #: src/gui-gtk/gtk-goban-window.c:518 msgid "Previous" msgstr "Previous" #: src/gui-gtk/gtk-goban-window.c:518 msgid "Switch to the previous variation" msgstr "Switch to the previous variation" #: src/gui-gtk/gtk-goban-window.c:524 msgid "Next" msgstr "Next" #: src/gui-gtk/gtk-goban-window.c:524 msgid "Switch to the next variation" msgstr "Switch to the next variation" #: src/gui-gtk/gtk-goban-window.c:629 msgid "/_File" msgstr "/_File" #: src/gui-gtk/gtk-goban-window.c:630 msgid "/File/_New Game..." msgstr "/File/_New Game…" #: src/gui-gtk/gtk-goban-window.c:633 msgid "/File/Ne_w Game Record..." msgstr "/File/Ne_w Game Record…" #: src/gui-gtk/gtk-goban-window.c:636 src/gui-gtk/gtk-goban-window.c:653 #: src/gui-gtk/gtk-goban-window.c:661 msgid "/File/" msgstr "/File/" #: src/gui-gtk/gtk-goban-window.c:638 msgid "/File/_Open..." msgstr "/File/_Open…" #: src/gui-gtk/gtk-goban-window.c:641 msgid "/File/_Resume Game..." msgstr "/File/_Resume Game…" #: src/gui-gtk/gtk-goban-window.c:645 msgid "/File/_Export..." msgstr "/File/_Export…" #: src/gui-gtk/gtk-goban-window.c:646 msgid "/File/Export.../_ASCII Diagram" msgstr "/File/Export…/_ASCII Diagram" #: src/gui-gtk/gtk-goban-window.c:649 msgid "/File/Export.../_Sensei's Library Diagram" msgstr "/File/Export…/_Sensei’s Library Diagram" #: src/gui-gtk/gtk-goban-window.c:655 msgid "/File/_Save" msgstr "/File/_Save" #: src/gui-gtk/gtk-goban-window.c:658 msgid "/File/Save _As..." msgstr "/File/Save _As…" #: src/gui-gtk/gtk-goban-window.c:663 msgid "/File/_Close" msgstr "/File/_Close" #: src/gui-gtk/gtk-goban-window.c:666 msgid "/File/_Quit" msgstr "/File/_Quit" #: src/gui-gtk/gtk-goban-window.c:671 msgid "/_Edit" msgstr "/_Edit" #: src/gui-gtk/gtk-goban-window.c:672 msgid "/Edit/_Undo" msgstr "/Edit/_Undo" #: src/gui-gtk/gtk-goban-window.c:675 msgid "/Edit/_Redo" msgstr "/Edit/_Redo" #: src/gui-gtk/gtk-goban-window.c:678 src/gui-gtk/gtk-goban-window.c:695 #: src/gui-gtk/gtk-goban-window.c:739 src/gui-gtk/gtk-goban-window.c:747 #: src/gui-gtk/gtk-goban-window.c:767 src/gui-gtk/gtk-goban-window.c:778 #: src/gui-gtk/gtk-goban-window.c:783 msgid "/Edit/" msgstr "/Edit/" #: src/gui-gtk/gtk-goban-window.c:680 msgid "/Edit/Cu_t" msgstr "/Edit/Cu_t" #: src/gui-gtk/gtk-goban-window.c:683 msgid "/Edit/_Copy" msgstr "/Edit/_Copy" #: src/gui-gtk/gtk-goban-window.c:686 msgid "/Edit/_Paste" msgstr "/Edit/_Paste" #: src/gui-gtk/gtk-goban-window.c:689 msgid "/Edit/_Delete Node" msgstr "/Edit/_Delete Node" #: src/gui-gtk/gtk-goban-window.c:692 msgid "/Edit/Delete Node's C_hildren" msgstr "/Edit/Delete Node’s C_hildren" #: src/gui-gtk/gtk-goban-window.c:698 msgid "/Edit/T_ools" msgstr "/Edit/T_ools" #: src/gui-gtk/gtk-goban-window.c:699 msgid "/Edit/Tools/_Move Tool" msgstr "/Edit/Tools/_Move Tool" #: src/gui-gtk/gtk-goban-window.c:702 msgid "/Edit/Tools/_Setup Tool" msgstr "/Edit/Tools/_Setup Tool" #: src/gui-gtk/gtk-goban-window.c:705 src/gui-gtk/gtk-goban-window.c:722 #: src/gui-gtk/gtk-goban-window.c:730 msgid "/Edit/Tools/" msgstr "/Edit/Tools/" #: src/gui-gtk/gtk-goban-window.c:707 msgid "/Edit/Tools/C_ross Markup" msgstr "/Edit/Tools/C_ross Markup" #: src/gui-gtk/gtk-goban-window.c:710 msgid "/Edit/Tools/_Circle Markup" msgstr "/Edit/Tools/_Circle Markup" #: src/gui-gtk/gtk-goban-window.c:713 msgid "/Edit/Tools/S_quare Markup" msgstr "/Edit/Tools/S_quare Markup" #: src/gui-gtk/gtk-goban-window.c:716 msgid "/Edit/Tools/_Triangle Markup" msgstr "/Edit/Tools/_Triangle Markup" #: src/gui-gtk/gtk-goban-window.c:719 msgid "/Edit/Tools/S_elected Markup" msgstr "/Edit/Tools/S_elected Markup" #: src/gui-gtk/gtk-goban-window.c:724 msgid "/Edit/Tools/_Label Tool" msgstr "/Edit/Tools/_Label Tool" #: src/gui-gtk/gtk-goban-window.c:727 msgid "/Edit/Tools/_Number Tool" msgstr "/Edit/Tools/_Number Tool" #: src/gui-gtk/gtk-goban-window.c:732 msgid "/Edit/Tools/Scori_ng Tool" msgstr "/Edit/Tools/Scori_ng Tool" #: src/gui-gtk/gtk-goban-window.c:736 msgid "/Edit/_Add Empty Node" msgstr "/Edit/_Add Empty Node" #: src/gui-gtk/gtk-goban-window.c:741 msgid "/Edit/Move _Branch Up" msgstr "/Edit/Move _Branch Up" #: src/gui-gtk/gtk-goban-window.c:744 msgid "/Edit/Move Branch Do_wn" msgstr "/Edit/Move Branch Do_wn" #: src/gui-gtk/gtk-goban-window.c:749 msgid "/Edit/Edit Node _Name" msgstr "/Edit/Edit Node _Name" #: src/gui-gtk/gtk-goban-window.c:752 msgid "/Edit/Set _Move Number" msgstr "/Edit/Set _Move Number" #: src/gui-gtk/gtk-goban-window.c:756 msgid "/Edit/P_layer to Move" msgstr "/Edit/P_layer to Move" #: src/gui-gtk/gtk-goban-window.c:757 msgid "/Edit/Player to Move/_White" msgstr "/Edit/Player to Move/_White" #: src/gui-gtk/gtk-goban-window.c:760 msgid "/Edit/Player to Move/_Black" msgstr "/Edit/Player to Move/_Black" #: src/gui-gtk/gtk-goban-window.c:763 msgid "/Edit/Player to Move/By Game _Rules" msgstr "/Edit/Player to Move/By Game _Rules" #: src/gui-gtk/gtk-goban-window.c:769 msgid "/Edit/_Find" msgstr "/Edit/_Find" #: src/gui-gtk/gtk-goban-window.c:772 msgid "/Edit/Find Ne_xt" msgstr "/Edit/Find Ne_xt" #: src/gui-gtk/gtk-goban-window.c:775 msgid "/Edit/Find Pre_vious" msgstr "/Edit/Find Pre_vious" #: src/gui-gtk/gtk-goban-window.c:780 msgid "/Edit/Game _Information" msgstr "/Edit/Game _Information" #: src/gui-gtk/gtk-goban-window.c:785 msgid "/Edit/Pr_eferences" msgstr "/Edit/Pr_eferences" #: src/gui-gtk/gtk-goban-window.c:790 msgid "/_View" msgstr "/_View" #: src/gui-gtk/gtk-goban-window.c:791 msgid "/View/_Main Toolbar" msgstr "/View/_Main Toolbar" #: src/gui-gtk/gtk-goban-window.c:794 msgid "/View/_Editing Toolbar" msgstr "/View/_Editing Toolbar" #: src/gui-gtk/gtk-goban-window.c:797 msgid "/View/_Navigation Toolbar" msgstr "/View/_Navigation Toolbar" #: src/gui-gtk/gtk-goban-window.c:800 src/gui-gtk/gtk-goban-window.c:805 #: src/gui-gtk/gtk-goban-window.c:813 msgid "/View/" msgstr "/View/" #: src/gui-gtk/gtk-goban-window.c:802 msgid "/View/_Game Action Buttons" msgstr "/View/_Game Action Buttons" #: src/gui-gtk/gtk-goban-window.c:807 msgid "/View/Game _Tree" msgstr "/View/Game _Tree" #: src/gui-gtk/gtk-goban-window.c:810 msgid "/View/_Recenter on Current Node" msgstr "/View/_Recentre on Current Node" #: src/gui-gtk/gtk-goban-window.c:815 msgid "/View/_Control Center" msgstr "/View/_Control Centre" #: src/gui-gtk/gtk-goban-window.c:820 msgid "/_Play" msgstr "/_Play" #: src/gui-gtk/gtk-goban-window.c:821 msgid "/Play/_Pass" msgstr "/Play/_Pass" #: src/gui-gtk/gtk-goban-window.c:824 src/gui-gtk/gtk-goban-window.c:829 msgid "/Play/" msgstr "/Play/" #: src/gui-gtk/gtk-goban-window.c:826 msgid "/Play/_Resign" msgstr "/Play/_Resign" #: src/gui-gtk/gtk-goban-window.c:831 msgid "/Play/_Adjourn Game" msgstr "/Play/_Adjourn Game" #: src/gui-gtk/gtk-goban-window.c:836 msgid "/_Go" msgstr "/_Go" #: src/gui-gtk/gtk-goban-window.c:837 msgid "/Go/_Previous Node" msgstr "/Go/_Previous Node" #: src/gui-gtk/gtk-goban-window.c:840 msgid "/Go/_Next Node" msgstr "/Go/_Next Node" #: src/gui-gtk/gtk-goban-window.c:843 msgid "/Go/Ten Nodes _Backward" msgstr "/Go/Ten Nodes _Backward" #: src/gui-gtk/gtk-goban-window.c:846 msgid "/Go/Ten Nodes _Forward" msgstr "/Go/Ten Nodes _Forward" #: src/gui-gtk/gtk-goban-window.c:849 src/gui-gtk/gtk-goban-window.c:857 #: src/gui-gtk/gtk-goban-window.c:867 msgid "/Go/" msgstr "/Go/" #: src/gui-gtk/gtk-goban-window.c:851 msgid "/Go/_Root Node" msgstr "/Go/_Root Node" #: src/gui-gtk/gtk-goban-window.c:854 msgid "/Go/Variation _Last Node" msgstr "/Go/Variation _Last Node" #: src/gui-gtk/gtk-goban-window.c:859 msgid "/Go/Pre_vious Variation" msgstr "/Go/Pre_vious Variation" #: src/gui-gtk/gtk-goban-window.c:862 msgid "/Go/Ne_xt Variation" msgstr "/Go/Ne_xt Variation" #: src/gui-gtk/gtk-goban-window.c:868 msgid "/Go/_Go to Named Node..." msgstr "/Go/_Go to Named Node…" #: src/gui-gtk/gtk-goban-window.c:874 msgid "/_Help" msgstr "/_Help" #: src/gui-gtk/gtk-goban-window.c:875 msgid "/Help/_Contents" msgstr "/Help/_Contents" #: src/gui-gtk/gtk-goban-window.c:878 msgid "/Help/_About" msgstr "/Help/_About" #: src/gui-gtk/gtk-goban-window.c:884 msgid "/Move Tool" msgstr "/Move Tool" #: src/gui-gtk/gtk-goban-window.c:885 msgid "/Setup Tool" msgstr "/Setup Tool" #: src/gui-gtk/gtk-goban-window.c:888 msgid "/Cross Markup" msgstr "/Cross Markup" #: src/gui-gtk/gtk-goban-window.c:889 msgid "/Circle Markup" msgstr "/Circle Markup" #: src/gui-gtk/gtk-goban-window.c:890 msgid "/Square Markup" msgstr "/Square Markup" #: src/gui-gtk/gtk-goban-window.c:891 msgid "/Triangle Markup" msgstr "/Triangle Markup" #: src/gui-gtk/gtk-goban-window.c:892 msgid "/Selected Markup" msgstr "/Selected Markup" #: src/gui-gtk/gtk-goban-window.c:895 msgid "/Label Tool" msgstr "/Label Tool" #: src/gui-gtk/gtk-goban-window.c:896 msgid "/Number Tool" msgstr "/Number Tool" #: src/gui-gtk/gtk-goban-window.c:899 msgid "/Scoring Tool" msgstr "/Scoring Tool" #: src/gui-gtk/gtk-goban-window.c:964 msgid "Black" msgstr "Black" #: src/gui-gtk/gtk-goban-window.c:964 msgid "White" msgstr "White" #: src/gui-gtk/gtk-goban-window.c:992 msgid "Pass" msgstr "Pass" #: src/gui-gtk/gtk-goban-window.c:998 msgid "Resign" msgstr "Resign" #: src/gui-gtk/gtk-goban-window.c:1438 #, c-format msgid "Save changes to game record `%s' before closing?" msgstr "Save changes to game record ‘%s’ before closing?" #: src/gui-gtk/gtk-goban-window.c:1447 msgid "Save changes to the untitled game record before closing?" msgstr "Save changes to the untitled game record before closing?" #. TRANSLATORS: Width of this string in default font is used to #. determine the minimal width of the right board window side. #: src/gui-gtk/gtk-goban-window.c:1522 msgid "A good width for the right side to have." msgstr "A good width for the right side to have." #. TRANSLATORS: It can never be 1 stone, always at least 2. #: src/gui-gtk/gtk-goban-window.c:1582 #, c-format msgid "" "Please set up %d (or less)\n" "stone of free handicap" msgid_plural "" "Please set up %d (or less)\n" "stones of free handicap" msgstr[0] "" "Please set up %d (or less)\n" "stone of free handicap" msgstr[1] "" "Please set up %d (or less)\n" "stones of free handicap" #: src/gui-gtk/gtk-goban-window.c:1774 msgid "Adjourn & Save As..." msgstr "Adjourn & Save As…" #: src/gui-gtk/gtk-goban-window.c:1774 msgid "Save As..." msgstr "Save As…" #: src/gui-gtk/gtk-goban-window.c:1923 #, c-format msgid "Error saving to file `%s'" msgstr "Error saving to file ‘%s’" #: src/gui-gtk/gtk-goban-window.c:1937 msgid "" "You can later resume the game by pressing the `Resume Game' button in Quarry " "Control Center, or selecting `Resume Game' item from the `File' menu." msgstr "" "You can later resume the game by pressing the ‘Resume Game’ button in Quarry " "Control Centre, or selecting ‘Resume Game’ item from the ‘File’ menu." #: src/gui-gtk/gtk-goban-window.c:1943 #, c-format msgid "The game is adjourned and saved in file `%s'" msgstr "The game is adjourned and saved in file ‘%s’" #: src/gui-gtk/gtk-goban-window.c:1962 msgid "ASCII diagram has been exported to clipboard" msgstr "ASCII diagram has been exported to clipboard" #: src/gui-gtk/gtk-goban-window.c:1975 msgid "Sensei's Library diagram has been exported to clipboard" msgstr "Sensei’s Library diagram has been exported to clipboard" #: src/gui-gtk/gtk-goban-window.c:1990 msgid "" "You can usually paste the diagram in another application using `Ctrl+C' key " "combination or by selecting appropriate menu item." msgstr "" "You can usually paste the diagram in another application using ‘Ctrl+C’ key " "combination or by selecting appropriate menu item." #: src/gui-gtk/gtk-goban-window.c:2446 msgid "Sorry, there are no named nodes in this game tree" msgstr "Sorry, there are no named nodes in this game tree" #: src/gui-gtk/gtk-goban-window.c:2470 msgid "A GUI program for Go, Amazons and Reversi board games" msgstr "A GUI program for Go, Amazons and Reversi board games" #: src/gui-gtk/gtk-goban-window.c:2472 msgid "Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev and others" msgstr "Copyright © 2003, 2004, 2005, 2006 Paul Pogonyshev and others" #: src/gui-gtk/gtk-goban-window.c:2488 msgid "About Quarry" msgstr "About Quarry" #: src/gui-gtk/gtk-goban-window.c:2931 msgid "Really resign this game?" msgstr "Really resign this game?" #: src/gui-gtk/gtk-goban-window.c:2935 msgid "_Resign" msgstr "_Resign" #: src/gui-gtk/gtk-goban-window.c:3524 msgid "Edit Board Label" msgstr "Edit Board Label" #: src/gui-gtk/gtk-goban-window.c:3527 msgid "Add Board Label" msgstr "Add Board Label" #: src/gui-gtk/gtk-goban-window.c:4026 #, c-format msgid "%s (W) vs. %s" msgstr "%s (W) vs. %s" #: src/gui-gtk/gtk-goban-window.c:4050 msgid "Unnamed Game" msgstr "Unnamed Game" #: src/gui-gtk/gtk-goban-window.c:4055 msgid "modified" msgstr "modified" #: src/gui-gtk/gtk-goban-window.c:4088 msgid "[unknown]" msgstr "[unknown]" #: src/gui-gtk/gtk-goban-window.c:4121 src/gui-gtk/gtk-goban-window.c:4126 #, c-format msgid "%d capture" msgid_plural "%d captures" msgstr[0] "%d capture" msgstr[1] "%d captures" #: src/gui-gtk/gtk-goban-window.c:4136 #, c-format msgid "%s %s %.*f komi" msgstr "%s %s %.*f komi" #: src/gui-gtk/gtk-goban-window.c:4147 #, c-format msgid "%s %s %d komi" msgid_plural "%s %s %d komi" msgstr[0] "%s %s %d komi" msgstr[1] "%s %s %d komi" #: src/gui-gtk/gtk-goban-window.c:4163 src/gui-gtk/gtk-goban-window.c:4166 #, c-format msgid "%d disk" msgid_plural "%d disks" msgstr[0] "%d disk" msgstr[1] "%d disks" #: src/gui-gtk/gtk-goban-window.c:4197 #, c-format msgid "Move %d: " msgstr "Move %d: " #: src/gui-gtk/gtk-goban-window.c:4201 #, c-format msgid "Last move: %u, " msgstr "Last move: %u, " #. TRANSLATORS: This is an #. abbreviation of `Black'. #: src/gui-gtk/gtk-goban-window.c:4208 msgid "B " msgstr "B " #. TRANSLATORS: This is an #. abbreviation of `White'. #: src/gui-gtk/gtk-goban-window.c:4211 msgid "W " msgstr "W " #: src/gui-gtk/gtk-goban-window.c:4212 msgid "pass" msgstr "pass" #: src/gui-gtk/gtk-goban-window.c:4215 msgid "Game beginning" msgstr "Game beginning" #: src/gui-gtk/gtk-goban-window.c:4233 msgid "; black to play" msgstr "; black to play" #: src/gui-gtk/gtk-goban-window.c:4233 msgid "; white to play" msgstr "; white to play" #: src/gui-gtk/gtk-goban-window.c:4236 msgid "; game over" msgstr "; game over" #: src/gui-gtk/gtk-goban-window.c:4243 msgid "Black wins" msgstr "Black wins" #: src/gui-gtk/gtk-goban-window.c:4246 msgid "White wins" msgstr "White wins" #: src/gui-gtk/gtk-goban-window.c:4250 msgid "Black wins by forfeit" msgstr "Black wins by forfeit" #: src/gui-gtk/gtk-goban-window.c:4253 msgid "White wins by forfeit" msgstr "White wins by forfeit" #: src/gui-gtk/gtk-goban-window.c:4257 msgid "White resigns" msgstr "White resigns" #: src/gui-gtk/gtk-goban-window.c:4260 msgid "Black resigns" msgstr "Black resigns" #: src/gui-gtk/gtk-goban-window.c:4272 msgid "White runs out of time and loses" msgstr "White runs out of time and loses" #: src/gui-gtk/gtk-goban-window.c:4276 msgid "Black runs out of time and loses" msgstr "Black runs out of time and loses" #: src/gui-gtk/gtk-goban-window.c:4280 msgid "Game is draw" msgstr "Game is draw" #: src/gui-gtk/gtk-goban-window.c:4499 msgid "By Game _Rules (Game Over)" msgstr "By Game _Rules (Game Over)" #: src/gui-gtk/gtk-goban-window.c:4503 msgid "By Game _Rules (Black)" msgstr "By Game _Rules (Black)" #: src/gui-gtk/gtk-goban-window.c:4507 msgid "By Game _Rules (White)" msgstr "By Game _Rules (White)" #: src/gui-gtk/gtk-goban-window.c:4551 msgid "insert node name here" msgstr "insert node name here" #: src/gui-gtk/gtk-goban-window.c:4952 msgid "Set Move Number" msgstr "Set Move Number" #. TRANSLATORS: Note that game name will be in `normal' form. #: src/gui-gtk/gtk-goban-window.c:5062 #, c-format msgid "" "GTP engine `%s' reported it could handle %s game, but failed to initialize " "itself for it" msgstr "" "GTP engine ‘%s’ reported it could handle %s game, but failed to initialise " "itself for it" #: src/gui-gtk/gtk-goban-window.c:5070 #, c-format msgid "GTP engine `%s' cannot handle %dx%d board size, sorry" msgstr "GTP engine ‘%s’ cannot handle %d×%d board size, sorry" #: src/gui-gtk/gtk-goban-window.c:5080 #, c-format msgid "GTP engine `%s' failed to clean the board" msgstr "GTP engine ‘%s’ failed to clean the board" #: src/gui-gtk/gtk-goban-window.c:5086 #, c-format msgid "" "GTP engine `%s' failed to set initial time limits (it could ignore them, but " "not fail)" msgstr "" "GTP engine ‘%s’ failed to set initial time limits (it could ignore them, but " "not fail)" #: src/gui-gtk/gtk-goban-window.c:5094 #, c-format msgid "GTP engine `%s' failed to set handicap stones on board" msgstr "GTP engine ‘%s’ failed to set handicap stones on board" #: src/gui-gtk/gtk-goban-window.c:5108 msgid "This is an engine error. You may want to report it to engine authors." msgstr "This is an engine error. You may want to report it to engine authors." #: src/gui-gtk/gtk-goban-window.c:5392 msgid "GTP engine is scoring..." msgstr "GTP engine is scoring…" #: src/gui-gtk/gtk-goban-window.c:5771 msgid "" "Unable to paste game record fragment from clipboard since it is not intended " "for pasting" msgstr "" "Unable to paste game record fragment from clipboard since it is not intended " "for pasting" #: src/gui-gtk/gtk-goban-window.c:5774 msgid "" "Clipboard SGF probably contains more than one game tree or not a single " "child of the root of the only game tree." msgstr "" "Clipboard SGF probably contains more than one game tree or not a single " "child of the root of the only game tree." #: src/gui-gtk/gtk-goban-window.c:5778 msgid "Unable to paste game record fragment from clipboard" msgstr "Unable to paste game record fragment from clipboard" #. TRANSLATORS: This message is shown if you e.g. copy a part of #. 13x13 game tree and try to paste it into a 19x19 game tree; or #. copy a part of a Reversi game tree and try to paste it into a #. Go game tree. #: src/gui-gtk/gtk-goban-window.c:5784 msgid "Clipboard game record fragment must be of different game or board size." msgstr "" "Clipboard game record fragment must be of different game or board size." #: src/gui-gtk/gtk-goban-window.c:5788 msgid "Clipboard contains an invalid game record fragment (SGF)" msgstr "Clipboard contains an invalid game record fragment (SGF)" #: src/gui-gtk/gtk-goban-window.c:5937 msgid "" "Please select dead stones\n" "to score the game" msgstr "" "Please select dead stones\n" "to score the game" #: src/gui-gtk/gtk-go-to-named-node-dialog.c:135 msgid "Go to Named Node" msgstr "Go to Named Node" #: src/gui-gtk/gtk-go-to-named-node-dialog.c:150 msgid "Node _name:" msgstr "Node _name:" #: src/gui-gtk/gtk-go-to-named-node-dialog.c:156 msgid "Node comment:" msgstr "Node comment:" #: src/gui-gtk/gtk-go-to-named-node-dialog.c:331 msgid "comment|Empty" msgstr "Empty" #: src/gui-gtk/gtk-go-to-named-node-dialog.c:334 msgid "There is no such node" msgstr "There is no such node" #: src/gui-gtk/gtk-gtp-client-interface.c:282 msgid "Engine hung up" msgstr "Engine hung up" #: src/gui-gtk/gtk-gtp-client-interface.c:391 msgid "* ERROR: wrong response format\n" msgstr "* ERROR: wrong response format\n" #: src/gui-gtk/gtk-gtp-client-interface.c:395 msgid "* WARNING: unexpected response:\n" msgstr "* WARNING: unexpected response:\n" #: src/gui-gtk/gtk-gtp-client-interface.c:399 msgid "* ERROR: unrecognized response line:\n" msgstr "* ERROR: unrecognised response line:\n" #: src/gui-gtk/gtk-gtp-client-interface.c:404 #, c-format msgid "* ERROR: mismatched ID (%d expected):\n" msgstr "* ERROR: mismatched ID (%d expected):\n" #: src/gui-gtk/gtk-gtp-client-interface.c:408 msgid "* ERROR: unexpected ID in response (the command had none):\n" msgstr "* ERROR: unexpected ID in response (the command had none):\n" #. TRANSLATORS: Don't put ellipsis here, this string will most #. often go to fixed-width font terminals. #: src/gui-gtk/gtk-gtp-client-interface.c:415 msgid "* WARNING: future GTP version, I don't know about it...\n" msgstr "* WARNING: future GTP version, I don’t know about it...\n" #: src/gui-gtk/gtk-new-game-dialog.c:98 msgid "" "Note that most GTP engines support only one game. Hence certain game / " "computer player combinations may be not possible to play." msgstr "" "Note that most GTP engines support only one game. Hence certain game / " "computer player combinations may be not possible to play." #: src/gui-gtk/gtk-new-game-dialog.c:102 msgid "Fi_xed handicap:" msgstr "Fi_xed handicap:" #: src/gui-gtk/gtk-new-game-dialog.c:102 msgid "_Free handicap:" msgstr "_Free handicap:" #: src/gui-gtk/gtk-new-game-dialog.c:105 msgid "No limit" msgstr "No limit" #: src/gui-gtk/gtk-new-game-dialog.c:105 msgid "Limited time for entire game" msgstr "Limited time for entire game" #: src/gui-gtk/gtk-new-game-dialog.c:106 msgid "Limited time per move" msgstr "Limited time per move" #: src/gui-gtk/gtk-new-game-dialog.c:106 msgid "Canadian overtime" msgstr "Canadian overtime" #: src/gui-gtk/gtk-new-game-dialog.c:124 msgid "New Game" msgstr "New Game" #: src/gui-gtk/gtk-new-game-dialog.c:167 #: src/gui-gtk/gtk-new-game-record-dialog.c:132 msgid "Game" msgstr "Game" #: src/gui-gtk/gtk-new-game-dialog.c:173 #: src/gui-gtk/gtk-resume-game-dialog.c:307 msgid "Hu_man" msgstr "Hu_man" #: src/gui-gtk/gtk-new-game-dialog.c:173 #: src/gui-gtk/gtk-resume-game-dialog.c:308 msgid "Com_puter" msgstr "Com_puter" #: src/gui-gtk/gtk-new-game-dialog.c:174 #: src/gui-gtk/gtk-resume-game-dialog.c:308 msgid "H_uman" msgstr "H_uman" #: src/gui-gtk/gtk-new-game-dialog.c:174 msgid "C_omputer" msgstr "C_omputer" #: src/gui-gtk/gtk-new-game-dialog.c:238 msgid "Manage _Engine List" msgstr "Manage _Engine List" #: src/gui-gtk/gtk-new-game-dialog.c:258 msgid "_Swap" msgstr "_Swap" #: src/gui-gtk/gtk-new-game-dialog.c:287 msgid "Game & Players" msgstr "Game & Players" #: src/gui-gtk/gtk-new-game-dialog.c:362 msgid "Time control _type:" msgstr "Time control _type:" #: src/gui-gtk/gtk-new-game-dialog.c:384 msgid "Time Limit" msgstr "Time Limit" #: src/gui-gtk/gtk-new-game-dialog.c:387 msgid "K_eep track of total time" msgstr "K_eep track of total time" #: src/gui-gtk/gtk-new-game-dialog.c:407 msgid "Time _limit for game:" msgstr "Time _limit for game:" #: src/gui-gtk/gtk-new-game-dialog.c:413 msgid "(per player)" msgstr "(per player)" #: src/gui-gtk/gtk-new-game-dialog.c:427 msgid "Time _limit for move:" msgstr "Time _limit for move:" #: src/gui-gtk/gtk-new-game-dialog.c:461 msgid "_Overtime period length:" msgstr "_Overtime period length:" #: src/gui-gtk/gtk-new-game-dialog.c:478 msgid "Mo_ves per overtime:" msgstr "Mo_ves per overtime:" #: src/gui-gtk/gtk-new-game-record-dialog.c:119 msgid "New Game Record" msgstr "New Game Record" #: src/gui-gtk/gtk-new-game-record-dialog.c:189 msgid "_Place stones" msgstr "_Place stones" #: src/gui-gtk/gtk-new-game-record-dialog.c:265 msgid "_White player:" msgstr "_White player:" #: src/gui-gtk/gtk-new-game-record-dialog.c:276 msgid "_Black player:" msgstr "_Black player:" #: src/gui-gtk/gtk-new-game-record-dialog.c:287 msgid "Game _name:" msgstr "Game _name:" #: src/gui-gtk/gtk-new-game-record-dialog.c:300 msgid "" "You can always change and expand game information later. Just choose `Edit/" "Game Information' menu item or press `Info' button on the main toolbar." msgstr "" "You can always change and expand game information later. Just choose ‘Edit/" "Game Information’ menu item or press ‘Info’ button on the main toolbar." #: src/gui-gtk/gtk-new-game-record-dialog.c:310 #: src/gui-gtk/gtk-resume-game-dialog.c:227 msgid "Short Game Information" msgstr "Short Game Information" #: src/gui-gtk/gtk-parser-interface.c:58 #, c-format msgid "Error reading file `%s'" msgstr "Error reading file ‘%s’" #: src/gui-gtk/gtk-parser-interface.c:60 #, c-format msgid "File `%s' doesn't appear to be a valid SGF file" msgstr "File ‘%s’ doesn’t appear to be a valid SGF file" #: src/gui-gtk/gtk-parser-interface.c:63 msgid "" "Please check that the file exists and its permission allow you to read it." msgstr "" "Please check that the file exists and its permission allow you to read it." #: src/gui-gtk/gtk-parser-interface.c:67 msgid "" "Quarry uses SGF file format for storing game records. SGF files would " "normally have `sgf' extension, but that's not necessarily true. Please make " "sure you select a proper SGF file." msgstr "" "Quarry uses SGF file format for storing game records. SGF files would " "normally have ‘sgf’ extension, but that’s not necessarily true. Please make " "sure you select a correct SGF file." #: src/gui-gtk/gtk-parser-interface.c:101 msgid "Open SGF File..." msgstr "Open SGF File…" #: src/gui-gtk/gtk-parser-interface.c:192 #, c-format msgid "Parsing file `%s'..." msgstr "Parsing file ‘%s’…" #: src/gui-gtk/gtk-preferences.c:431 msgid "General" msgstr "General" #: src/gui-gtk/gtk-preferences.c:434 msgid "Interface" msgstr "Interface" #: src/gui-gtk/gtk-preferences.c:435 msgid "General Interface" msgstr "General Interface" #: src/gui-gtk/gtk-preferences.c:437 msgid "Editing & Viewing" msgstr "Editing & Viewing" #: src/gui-gtk/gtk-preferences.c:440 src/gui-gtk/gtk-preferences.c:441 msgid "Game Tree" msgstr "Game Tree" #: src/gui-gtk/gtk-preferences.c:444 msgid "GTP" msgstr "GTP" #: src/gui-gtk/gtk-preferences.c:447 src/gui-gtk/gtk-preferences.c:448 msgid "GTP Engines" msgstr "GTP Engines" #: src/gui-gtk/gtk-preferences.c:451 msgid "Game Records (SGF)" msgstr "Game Records (SGF)" #: src/gui-gtk/gtk-preferences.c:454 msgid "Saving" msgstr "Saving" #: src/gui-gtk/gtk-preferences.c:455 msgid "Saving Game Records" msgstr "Saving Game Records" #: src/gui-gtk/gtk-preferences.c:458 msgid "Board Appearance" msgstr "Board Appearance" #: src/gui-gtk/gtk-preferences.c:462 msgid "Go Board Appearance" msgstr "Go Board Appearance" #: src/gui-gtk/gtk-preferences.c:465 msgid "Amazons Board Appearance" msgstr "Amazons Board Appearance" #: src/gui-gtk/gtk-preferences.c:468 msgid "Reversi Board Appearance" msgstr "Reversi Board Appearance" #: src/gui-gtk/gtk-preferences.c:478 msgid "Preferences" msgstr "Preferences" #: src/gui-gtk/gtk-preferences.c:515 msgid "Categor_y:" msgstr "Categor_y:" #: src/gui-gtk/gtk-preferences.c:641 msgid "Use _newer (GTK+ 2.4) file chooser" msgstr "Use _newer (GTK+ 2.4) file chooser" #: src/gui-gtk/gtk-preferences.c:642 msgid "Use _old-style file selection dialog" msgstr "Use _old-style file selection dialogue" #: src/gui-gtk/gtk-preferences.c:672 msgid "File Chooser Dialog Style" msgstr "File Chooser Dialogue Style" #: src/gui-gtk/gtk-preferences.c:688 msgid "_Main toolbar style:" msgstr "_Main toolbar style:" #: src/gui-gtk/gtk-preferences.c:692 msgid "_Editing toolbar style:" msgstr "_Editing toolbar style:" #: src/gui-gtk/gtk-preferences.c:696 msgid "N_avigation toolbar style:" msgstr "N_avigation toolbar style:" #: src/gui-gtk/gtk-preferences.c:705 msgid "Toolbar Styles" msgstr "Toolbar Styles" #: src/gui-gtk/gtk-preferences.c:725 msgid "Desktop default" msgstr "Desktop default" #: src/gui-gtk/gtk-preferences.c:726 msgid "Text below icons" msgstr "Text below icons" #: src/gui-gtk/gtk-preferences.c:732 msgid "Text beside important icons" msgstr "Text beside important icons" #: src/gui-gtk/gtk-preferences.c:735 msgid "Icons only" msgstr "Icons only" #: src/gui-gtk/gtk-preferences.c:736 msgid "Text only" msgstr "Text only" #: src/gui-gtk/gtk-preferences.c:792 msgid "Show" msgstr "Show" #: src/gui-gtk/gtk-preferences.c:799 msgid "Name" msgstr "Name" #: src/gui-gtk/gtk-preferences.c:808 msgid "_List of GTP engines:" msgstr "_List of GTP engines:" #: src/gui-gtk/gtk-preferences.c:856 msgid "Name:" msgstr "Name:" #: src/gui-gtk/gtk-preferences.c:865 msgid "Version:" msgstr "Version:" #: src/gui-gtk/gtk-preferences.c:875 src/gui-gtk/gtk-preferences.c:1630 msgid "Supported game:" msgstr "Supported game:" #: src/gui-gtk/gtk-preferences.c:889 msgid "Command line:" msgstr "Command line:" #: src/gui-gtk/gtk-preferences.c:914 msgid "GTP Engine Information" msgstr "GTP Engine Information" #: src/gui-gtk/gtk-preferences.c:935 msgid "_Always" msgstr "_Always" #: src/gui-gtk/gtk-preferences.c:935 msgid "A_utomatically" msgstr "A_utomatically" #: src/gui-gtk/gtk-preferences.c:935 msgid "_Never" msgstr "_Never" #: src/gui-gtk/gtk-preferences.c:937 msgid "Al_ways" msgstr "Al_ways" #: src/gui-gtk/gtk-preferences.c:937 msgid "Aut_omatically" msgstr "Aut_omatically" #: src/gui-gtk/gtk-preferences.c:937 msgid "Ne_ver" msgstr "Ne_ver" #: src/gui-gtk/gtk-preferences.c:939 msgid "Scroll _minimal distance" msgstr "Scroll _minimal distance" #: src/gui-gtk/gtk-preferences.c:940 msgid "_Recenter view on the current node" msgstr "_Recentre view on the current node" #: src/gui-gtk/gtk-preferences.c:943 msgid "" "In automatic mode the game tree is shown only if it has at least one " "variation. In any case, you can show/hide game tree in each window " "separately." msgstr "" "In automatic mode the game tree is shown only if it has at least one " "variation. In any case, you can show/hide game tree in each window " "separately." #: src/gui-gtk/gtk-preferences.c:947 msgid "" "In automatic mode the game tree view scrolls to show the current node only " "if it has been showing current node before. I.e. unless you scrolled it away " "manually." msgstr "" "In automatic mode the game tree view scrolls to show the current node only " "if it has been showing current node before. I.e. unless you scrolled it away " "manually." #: src/gui-gtk/gtk-preferences.c:992 msgid "Show Game Tree" msgstr "Show Game Tree" #: src/gui-gtk/gtk-preferences.c:1039 msgid "Track Tree's Current Node" msgstr "Track Tree’s Current Node" #: src/gui-gtk/gtk-preferences.c:1042 msgid "Show _tooltips" msgstr "Show _tooltips" #: src/gui-gtk/gtk-preferences.c:1049 msgid "Tooltips" msgstr "Tooltips" #: src/gui-gtk/gtk-preferences.c:1065 msgid "Always use _UTF-8 (recommended)" msgstr "Always use _UTF-8 (recommended)" #: src/gui-gtk/gtk-preferences.c:1066 msgid "Preserve _original encoding" msgstr "Preserve _original encoding" #: src/gui-gtk/gtk-preferences.c:1068 msgid "" "Note that many characters cannot be represented in non-UTF-8 encodings and " "thus some information may be lost if you use them. Quarry also works fastest " "with UTF-8; this may be important if you have very large SGF files." msgstr "" "Note that many characters cannot be represented in non-UTF-8 encodings and " "thus some information may be lost if you use them. Quarry also works fastest " "with UTF-8; this may be important if you have very large SGF files." #: src/gui-gtk/gtk-preferences.c:1093 msgid "Encoding" msgstr "Encoding" #: src/gui-gtk/gtk-preferences.c:1103 msgid "_Relative to stone size" msgstr "_Relative to stone size" #: src/gui-gtk/gtk-preferences.c:1104 msgid "On _white stones:" msgstr "On _white stones:" #: src/gui-gtk/gtk-preferences.c:1105 msgid "On _black stones:" msgstr "On _black stones:" #: src/gui-gtk/gtk-preferences.c:1106 msgid "On _empty intersections:" msgstr "On _empty intersections:" #: src/gui-gtk/gtk-preferences.c:1120 msgid "_Relative to amazon size" msgstr "_Relative to amazon size" #: src/gui-gtk/gtk-preferences.c:1121 msgid "On _white amazons:" msgstr "On _white amazons:" #: src/gui-gtk/gtk-preferences.c:1122 msgid "On _black amazons:" msgstr "On _black amazons:" #: src/gui-gtk/gtk-preferences.c:1123 src/gui-gtk/gtk-preferences.c:1182 msgid "On _empty fields:" msgstr "On _empty fields:" #: src/gui-gtk/gtk-preferences.c:1142 msgid "Pick Checkerboard Pattern Color" msgstr "Pick Chequered Pattern Colour" #: src/gui-gtk/gtk-preferences.c:1151 msgid "Checkerboard _pattern color:" msgstr "Chequered _pattern colour:" #: src/gui-gtk/gtk-preferences.c:1167 msgid "Checkerboard pattern _opacity:" msgstr "Chequered pattern _opacity:" #: src/gui-gtk/gtk-preferences.c:1179 msgid "_Relative to disk size" msgstr "_Relative to disk size" #: src/gui-gtk/gtk-preferences.c:1180 msgid "On _white disks:" msgstr "On _white disks:" #: src/gui-gtk/gtk-preferences.c:1181 msgid "On _black disks:" msgstr "On _black disks:" #: src/gui-gtk/gtk-preferences.c:1195 msgid "Use _texture:" msgstr "Use _texture:" #: src/gui-gtk/gtk-preferences.c:1196 msgid "Use _solid color:" msgstr "Use _solid colour:" #: src/gui-gtk/gtk-preferences.c:1271 msgid "Choose a Background Texture..." msgstr "Choose a Background Texture…" #: src/gui-gtk/gtk-preferences.c:1282 msgid "Pick Background Color" msgstr "Pick Background Colour" #: src/gui-gtk/gtk-preferences.c:1296 msgid "Pick Color for Grid and Labels" msgstr "Pick Colour for Grid and Labels" #: src/gui-gtk/gtk-preferences.c:1306 msgid "_Grid and labels color:" msgstr "_Grid and labels colour:" #: src/gui-gtk/gtk-preferences.c:1345 msgid "_Theme:" msgstr "_Theme:" #: src/gui-gtk/gtk-preferences.c:1354 msgid "Use theme _defaults" msgstr "Use theme _defaults" #: src/gui-gtk/gtk-preferences.c:1371 msgid "_Size:" msgstr "_Size:" #: src/gui-gtk/gtk-preferences.c:1398 msgid "_Opacity:" msgstr "_Opacity:" #: src/gui-gtk/gtk-preferences.c:1413 msgid "Size & Opacity" msgstr "Size & Opacity" #: src/gui-gtk/gtk-preferences.c:1429 msgid "Color" msgstr "Colour" #: src/gui-gtk/gtk-preferences.c:1443 msgid "Pick Color for Markup" msgstr "Pick Colour for Markup" #: src/gui-gtk/gtk-preferences.c:1482 msgid "Background" msgstr "Background" #: src/gui-gtk/gtk-preferences.c:1484 msgid "Markup" msgstr "Markup" #: src/gui-gtk/gtk-preferences.c:1630 msgid "Supported games:" msgstr "Supported games:" #: src/gui-gtk/gtk-preferences.c:1637 msgid "This engine comes from site configuration." msgstr "This engine comes from site configuration." #: src/gui-gtk/gtk-preferences.c:1860 msgid "" "You can use `%n' and `%v' strings in Screen name field. They will " "substituted with name and version of the engine correspondingly. By default, " "`%n %v' is used." msgstr "" "You can use ‘%n’ and ‘%v’ strings in Screen name field. They will " "substituted with name and version of the engine correspondingly. By default, " "‘%n %v’ is used." #: src/gui-gtk/gtk-preferences.c:1908 msgid "Modify GTP Engine Information" msgstr "Modify GTP Engine Information" #: src/gui-gtk/gtk-preferences.c:1909 msgid "New GTP Engine" msgstr "New GTP Engine" #: src/gui-gtk/gtk-preferences.c:1955 msgid "Command _line:" msgstr "Command _line:" #: src/gui-gtk/gtk-preferences.c:1961 msgid "Choose GTP Engine..." msgstr "Choose GTP Engine…" #: src/gui-gtk/gtk-preferences.c:1972 msgid "Screen _name:" msgstr "Screen _name:" #: src/gui-gtk/gtk-preferences.c:2018 msgid "Querying engine's name, version and known commands..." msgstr "Querying engine’s name, version and known commands…" #: src/gui-gtk/gtk-preferences.c:2039 msgid "" "Please make sure you typed engine's filename correctly and that you have " "permission to execute it." msgstr "" "Please make sure you typed engine’s filename correctly and that you have " "permission to execute it." #: src/gui-gtk/gtk-preferences.c:2078 msgid "Waiting for the engine to quit..." msgstr "Waiting for the engine to quit…" #: src/gui-gtk/gtk-preferences.c:2182 msgid "" "The engine might have crashed, quit prematurely or disconnected. Please " "verify command line, including options, and consult engine's documentation " "if needed." msgstr "" "The engine might have crashed, quit prematurely or disconnected. Please " "verify command line, including options, and consult engine’s documentation " "if needed." #: src/gui-gtk/gtk-preferences.c:2197 #, c-format msgid "Lost connection to GTP Engine (%s)" msgstr "Lost connection to GTP Engine (%s)" #: src/gui-gtk/gtk-preferences.c:3011 msgid "" "Perhaps engine's binary has been deleted or changed. You will probably need " "to alter engine's command line in the Preferences dialog." msgstr "" "Perhaps engine’s binary has been deleted or changed. You will probably need " "to alter engine’s command line in the Preferences dialogue." #: src/gui-gtk/gtk-resume-game-dialog.c:92 msgid "Resume Game..." msgstr "Resume Game…" #: src/gui-gtk/gtk-resume-game-dialog.c:115 #, c-format msgid "The game stored in file `%s' (%s) is not supported by Quarry" msgstr "The game stored in file ‘%s’ (%s) is not supported by Quarry" #: src/gui-gtk/gtk-resume-game-dialog.c:138 msgid "" "This game appears to have been finished. Open it for viewing and/or editing " "instead?" msgstr "" "This game appears to have been finished. Open it for viewing and/or editing " "instead?" #: src/gui-gtk/gtk-resume-game-dialog.c:212 msgid "Resuming Game" msgstr "Resuming Game" #: src/gui-gtk/gtk-resume-game-dialog.c:214 msgid "_Resume" msgstr "_Resume" #: src/gui-gtk/gtk-resume-game-dialog.c:231 msgid "Game:" msgstr "Game:" #: src/gui-gtk/gtk-resume-game-dialog.c:240 msgid "Board size:" msgstr "Board size:" #: src/gui-gtk/gtk-resume-game-dialog.c:258 msgid "Handicap:" msgstr "Handicap:" #: src/gui-gtk/gtk-resume-game-dialog.c:262 msgid "handicap|Not set" msgstr "Not set" #: src/gui-gtk/gtk-resume-game-dialog.c:268 msgid "Komi:" msgstr "Komi:" #: src/gui-gtk/gtk-resume-game-dialog.c:271 msgid "komi|Not set" msgstr "Not set" #: src/gui-gtk/gtk-resume-game-dialog.c:294 msgid "Filename:" msgstr "Filename:" #: src/gui-gtk/gtk-resume-game-dialog.c:307 msgid "Compu_ter" msgstr "Compu_ter" #: src/gui-gtk/quarry-find-dialog.c:104 msgid "Whole game _tree" msgstr "Whole game _tree" #: src/gui-gtk/quarry-find-dialog.c:104 msgid "Current no_de only" msgstr "Current no_de only" #: src/gui-gtk/quarry-find-dialog.c:107 msgid "C_omments & node names" msgstr "C_omments & node names" #: src/gui-gtk/quarry-find-dialog.c:108 msgid "Comm_ents only" msgstr "Comm_ents only" #: src/gui-gtk/quarry-find-dialog.c:108 msgid "Node na_mes only" msgstr "Node na_mes only" #: src/gui-gtk/quarry-find-dialog.c:154 msgid "Search _for:" msgstr "Search _for:" #: src/gui-gtk/quarry-find-dialog.c:161 msgid "Case _sensitive" msgstr "Case _sensitive" #: src/gui-gtk/quarry-find-dialog.c:169 msgid "Whole _words only" msgstr "Whole _words only" #: src/gui-gtk/quarry-find-dialog.c:177 msgid "Wrap _around" msgstr "Wrap _around" #: src/gui-gtk/quarry-find-dialog.c:191 msgid "A_uto-close this dialog" msgstr "A_uto-close this dialogue" #: src/gui-gtk/quarry-find-dialog.c:202 msgid "Options" msgstr "Options" #: src/gui-gtk/quarry-find-dialog.c:251 msgid "Search Scope" msgstr "Search Scope" #: src/gui-gtk/quarry-move-number-dialog.c:66 #: src/gui-gtk/quarry-move-number-dialog.c:148 msgid "Use se_quential move number" msgstr "Use se_quential move number" #: src/gui-gtk/quarry-move-number-dialog.c:66 msgid "_Set specific move number:" msgstr "_Set specific move number:" #: src/gui-gtk/quarry-save-confirmation-dialog.c:89 msgid "Close _without Saving" msgstr "Close _without Saving" #: src/gui-gtk/quarry-save-confirmation-dialog.c:173 #, c-format msgid "" "If you don't save, changes from the last %d second will be lost permanently." msgid_plural "" "If you don't save, changes from the last %d seconds will be lost permanently." msgstr[0] "" "If you don’t save, changes from the last %d second will be lost permanently." msgstr[1] "" "If you don’t save, changes from the last %d seconds will be lost permanently." #: src/gui-gtk/quarry-save-confirmation-dialog.c:181 msgid "If you don't save, changes from the last minute will be discarded." msgstr "If you don’t save, changes from the last minute will be discarded." #. TRANSLATORS: Cannot be one minute one second, actually. #: src/gui-gtk/quarry-save-confirmation-dialog.c:187 #, c-format msgid "" "If you don't save, changes from the last minute and %d second will be lost " "permanently." msgid_plural "" "If you don't save, changes from the last minute and %d seconds will be lost " "permanently." msgstr[0] "" "If you don’t save, changes from the last minute and %d second will be lost " "permanently." msgstr[1] "" "If you don’t save, changes from the last minute and %d seconds will be lost " "permanently." #: src/gui-gtk/quarry-save-confirmation-dialog.c:198 #, c-format msgid "" "If you don't save, changes from the last %d minute will be lost permanently." msgid_plural "" "If you don't save, changes from the last %d minutes will be lost permanently." msgstr[0] "" "If you don’t save, changes from the last %d minute will be lost permanently." msgstr[1] "" "If you don’t save, changes from the last %d minutes will be lost permanently." #. TRANSLATORS: Cannot be one hour one minute, actually. #: src/gui-gtk/quarry-save-confirmation-dialog.c:212 #, c-format msgid "" "If you don't save, changes from the last hour and %d minute will be lost " "permanently." msgid_plural "" "If you don't save, changes from the last hour and %d minutes will be lost " "permanently." msgstr[0] "" "If you don’t save, changes from the last hour and %d minute will be lost " "permanently." msgstr[1] "" "If you don’t save, changes from the last hour and %d minutes will be lost " "permanently." #: src/gui-gtk/quarry-save-confirmation-dialog.c:224 #, c-format msgid "" "If you don't save, changes from the last %d hour will be lost permanently." msgid_plural "" "If you don't save, changes from the last %d hours will be lost permanently." msgstr[0] "" "If you don’t save, changes from the last %d hour will be lost permanently." msgstr[1] "" "If you don’t save, changes from the last %d hours will be lost permanently." #: src/gui-gtk/quarry-stock.c:56 msgid "_New Game" msgstr "_New Game" #: src/gui-gtk/quarry-stock.c:57 msgid "_Open Game Record" msgstr "_Open Game Record" #: src/gui-gtk/quarry-stock.c:59 msgid "_Browse..." msgstr "_Browse…" #: src/gui-gtk/quarry-stock.c:60 msgid "Crea_te" msgstr "Crea_te" #: src/gui-gtk/quarry-stock.c:61 msgid "_Done" msgstr "_Done" #: src/gui-gtk/quarry-stock.c:62 msgid "_Go to Node" msgstr "_Go to Node" #: src/gui-gtk/quarry-stock.c:63 msgid "_Modify" msgstr "_Modify" #: src/gui-gtk/quarry-stock.c:64 msgid "Move _Up" msgstr "Move _Up" #: src/gui-gtk/quarry-stock.c:65 msgid "Move _Down" msgstr "Move _Down" #: src/gui-gtk/quarry-stock.c:66 msgid "find|_Next" msgstr "_Next" #: src/gui-gtk/quarry-stock.c:67 msgid "_Overwrite" msgstr "_Overwrite" #: src/gui-gtk/quarry-stock.c:68 msgid "_Play" msgstr "_Play" #: src/gui-gtk/quarry-stock.c:69 msgid "find|_Previous" msgstr "_Previous" #. TRANSLATORS: This is only used for non-integral scores. You #. should also add translation of `points' if it is required by #. your language. #: src/board/board.c:897 #, c-format msgid "Black wins by %.*f" msgstr "Black wins by %.*f" #. TRANSLATORS: This is only used for non-integral scores. You #. should also add translation of `points' if it is required by #. your language. #: src/board/board.c:904 #, c-format msgid "White wins by %.*f" msgstr "White wins by %.*f" #: src/board/board.c:915 #, c-format msgid "Black wins by %d" msgid_plural "Black wins by %d" msgstr[0] "Black wins by %d" msgstr[1] "Black wins by %d" #: src/board/board.c:923 #, c-format msgid "White wins by %d" msgid_plural "White wins by %d" msgstr[0] "White wins by %d" msgstr[1] "White wins by %d" #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:29 msgid "Go" msgstr "Go" #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:43 msgid "Reversi" msgstr "Reversi" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:58 msgid "chess" msgstr "chess" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:73 msgid "Gomoku" msgstr "Gomoku" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:88 msgid "Nine Men's Morris" msgstr "Nine Men’s Morris" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:103 msgid "Backgammon" msgstr "Backgammon" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:118 msgid "Chinese chess" msgstr "Chinese chess" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:133 msgid "Shogi" msgstr "Shogi" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:148 msgid "Lines of Action" msgstr "Lines of Action" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:163 msgid "Ataxx" msgstr "Ataxx" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:178 msgid "Hex" msgstr "Hex" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:193 msgid "Jungle" msgstr "Jungle" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:208 msgid "Neutron" msgstr "Neutron" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:223 msgid "Philosopher's Football" msgstr "Philosopher’s Football" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:238 msgid "Quadrature" msgstr "Quadrature" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:253 msgid "Trax" msgstr "Trax" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:268 msgid "Tantrix" msgstr "Tantrix" #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:282 msgid "Amazons" msgstr "Amazons" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:297 msgid "Octi" msgstr "Octi" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:312 msgid "Gess" msgstr "Gess" #: src/board/go.c:1323 #, c-format msgid "White: %d territory" msgid_plural "White: %d territory" msgstr[0] "White: %d territory" msgstr[1] "White: %d territory" #: src/board/go.c:1328 src/board/go.c:1365 #, c-format msgid " + %d capture" msgid_plural " + %d captures" msgstr[0] " + %d capture" msgstr[1] " + %d captures" #. TRANSLATORS: e.g. `` + 6.5 komi = #. 87.5''. This is used only with #. fractional komi. #: src/board/go.c:1337 #, c-format msgid " %s %.*f komi = %.*f\n" msgstr " %s %.*f komi = %.*f\n" #. TRANSLATORS: e.g. `` + 6 komi = 87''. #: src/board/go.c:1351 #, c-format msgid " %s %d komi = %d\n" msgid_plural " %s %d komi = %d\n" msgstr[0] " %s %d komi = %d\n" msgstr[1] " %s %d komi = %d\n" #: src/board/go.c:1360 #, c-format msgid "Black: %d territory" msgid_plural "Black: %d territory" msgstr[0] "Black: %d territory" msgstr[1] "Black: %d territory" #: src/board/go.c:1374 msgid "The game is draw" msgstr "The game is draw" quarry-0.2.0/po/fr.po0000644000175000017500000016657510530113052013075 0ustar bartbart# fr translation of Quarry. # Copyright (C) 2005 Paul Pogonyshev # This file is distributed under the same license as the Quarry package. # Jérémie Knuesel , 2006. # # msgid "" msgstr "" "Project-Id-Version: Quarry\n" "Report-Msgid-Bugs-To: quarry-dev@gna.org\n" "POT-Creation-Date: 2006-11-07 18:33+0200\n" "PO-Revision-Date: 2006-11-11 17:28+0100\n" "Last-Translator: Jeremie Knuesel \n" "Language-Team: fr <->\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/gui-gtk/gtk-add-or-edit-label-dialog.c:73 msgid "" "Although board labels are not limited in length, it is better to use only " "one or two characters long labels. Longer labels will not be visible " "immediately or at all in most clients." msgstr "" "Bien que la longueur des étiquettes de plateau ne soit pas limitée, il est " "préférable de n'utiliser qu'un ou deux caractères. Les étiquettes plus " "longues ne seront pas visibles (ou pas immédiatement) dans la plupart des " "clients." #: src/gui-gtk/gtk-add-or-edit-label-dialog.c:87 msgid "Label _text:" msgstr "_Texte de l'étiquette :" #: src/gui-gtk/gtk-color-button.c:581 msgid "Pick a Color" msgstr "Choisissez une couleur" #: src/gui-gtk/gtk-control-center.c:64 msgid "Quarry Control Center" msgstr "Centre de contrôle Quarry" #: src/gui-gtk/gtk-control-center.c:80 msgid "Ne_w Game Record" msgstr "Nouvel _enregistrement de partie" #: src/gui-gtk/gtk-control-center.c:96 msgid "_Resume Game" msgstr "_Reprendre une partie" #: src/gui-gtk/gtk-file-dialog.c:281 msgid "" "Note that all information in the existing file will be lost permanently if " "you choose to overwrite it." msgstr "" "Notez que toutes les informations dans le fichier existant seront " "définitivement perdues si vous choisissez de l'écraser." #: src/gui-gtk/gtk-file-dialog.c:284 #, c-format msgid "" "File named `%s' already exists. Do you want to overwrite it with the one you " "are saving?" msgstr "" "Il existe déjà un fichier portant le nom \"%s\". Voulez-vous l'écraser avec " "celui que vous êtes en train d'enregistrer ?" #: src/gui-gtk/gtk-game-info-dialog.c:231 #: src/gui-gtk/gtk-resume-game-dialog.c:325 msgid "N_ame:" msgstr "_Nom :" #: src/gui-gtk/gtk-game-info-dialog.c:231 #: src/gui-gtk/gtk-resume-game-dialog.c:324 msgid "_Name:" msgstr "N_om :" #: src/gui-gtk/gtk-game-info-dialog.c:238 msgid "Team:" msgstr "Équipe :" #: src/gui-gtk/gtk-game-info-dialog.c:244 msgid "Rank:" msgstr "Rang :" #: src/gui-gtk/gtk-game-info-dialog.c:256 #: src/gui-gtk/gtk-new-game-dialog.c:226 #: src/gui-gtk/gtk-resume-game-dialog.c:364 msgid "Black Player" msgstr "Joueur noir" #: src/gui-gtk/gtk-game-info-dialog.c:256 #: src/gui-gtk/gtk-new-game-dialog.c:226 #: src/gui-gtk/gtk-resume-game-dialog.c:364 msgid "White Player" msgstr "Joueur blanc" #: src/gui-gtk/gtk-game-info-dialog.c:270 msgid "_Game name:" msgstr "Nom de la _partie :" #: src/gui-gtk/gtk-game-info-dialog.c:273 msgid "_Place:" msgstr "_Lieu :" #: src/gui-gtk/gtk-game-info-dialog.c:277 msgid "Da_te:" msgstr "_Date :" #: src/gui-gtk/gtk-game-info-dialog.c:280 msgid "_Event:" msgstr "_Événement :" #: src/gui-gtk/gtk-game-info-dialog.c:284 msgid "R_ound:" msgstr "_Manche :" #: src/gui-gtk/gtk-game-info-dialog.c:295 #: src/gui-gtk/gtk-game-info-dialog.c:535 #: src/gui-gtk/gtk-game-info-dialog.c:541 msgid "Game Information" msgstr "Informations sur la partie" #: src/gui-gtk/gtk-game-info-dialog.c:298 msgid "Rule _set:" msgstr "_Règles :" #: src/gui-gtk/gtk-game-info-dialog.c:324 #: src/gui-gtk/gtk-new-game-record-dialog.c:187 msgid "Han_dicap:" msgstr "_Handicap :" #: src/gui-gtk/gtk-game-info-dialog.c:347 #: src/gui-gtk/gtk-new-game-dialog.c:574 #: src/gui-gtk/gtk-new-game-record-dialog.c:231 msgid "_Komi:" msgstr "_Komi :" #: src/gui-gtk/gtk-game-info-dialog.c:374 #: src/gui-gtk/gtk-new-game-dialog.c:444 msgid "_Main time:" msgstr "Temps _principal :" #: src/gui-gtk/gtk-game-info-dialog.c:386 msgid "O_vertime:" msgstr "Temps _supplémentaire :" #: src/gui-gtk/gtk-game-info-dialog.c:397 #: src/gui-gtk/gtk-new-game-dialog.c:602 msgid "Game Rules" msgstr "Règles de la partie" #: src/gui-gtk/gtk-game-info-dialog.c:412 msgid "General" msgstr "Général" #: src/gui-gtk/gtk-game-info-dialog.c:415 msgid "Game re_sult:" msgstr "_Résultats de la partie :" #: src/gui-gtk/gtk-game-info-dialog.c:419 msgid "_Opening played:" msgstr "_Ouverture jouée :" #: src/gui-gtk/gtk-game-info-dialog.c:449 msgid "Comment / _description:" msgstr "_Commentaire / description :" #: src/gui-gtk/gtk-game-info-dialog.c:463 msgid "Description & Result" msgstr "Description & résultat" #: src/gui-gtk/gtk-game-info-dialog.c:466 msgid "Co_pyright string:" msgstr "_Mention de copyright :" #: src/gui-gtk/gtk-game-info-dialog.c:470 msgid "_Annotator:" msgstr "_Annotateur :" #: src/gui-gtk/gtk-game-info-dialog.c:474 msgid "_Source:" msgstr "_Source :" #: src/gui-gtk/gtk-game-info-dialog.c:478 msgid "_Entered by:" msgstr "_Données saisies par :" #: src/gui-gtk/gtk-game-info-dialog.c:488 msgid "Copyright & Credits" msgstr "Copyright" #: src/gui-gtk/gtk-game-info-dialog.c:502 msgid "Game Record" msgstr "Enregistrement de la partie" #: src/gui-gtk/gtk-games.c:39 msgid "_Go" msgstr "_Go" #: src/gui-gtk/gtk-games.c:40 msgid "_Amazons" msgstr "_Amazones" #: src/gui-gtk/gtk-games.c:41 msgid "_Reversi" msgstr "_Reversi" #: src/gui-gtk/gtk-games.c:45 msgid "Go Rules" msgstr "Règles du Go" #: src/gui-gtk/gtk-games.c:46 msgid "Amazons Rules" msgstr "Règles des Amazones" #: src/gui-gtk/gtk-games.c:47 msgid "Reversi Rules" msgstr "Règles du Reversi" #: src/gui-gtk/gtk-games.c:180 msgid "Board _size:" msgstr "_Taille du plateau :" #: src/gui-gtk/gtk-goban-window.c:460 msgid "Open" msgstr "Ouvrir" #: src/gui-gtk/gtk-goban-window.c:460 msgid "Open a game record" msgstr "Ouvrir une partie enregistrée" #: src/gui-gtk/gtk-goban-window.c:465 msgid "Save" msgstr "Enregistrer" #: src/gui-gtk/gtk-goban-window.c:465 msgid "Save the current file" msgstr "Enregistrer le fichier courant" #: src/gui-gtk/gtk-goban-window.c:470 src/gui-gtk/gtk-goban-window.c:2025 msgid "Find" msgstr "Rechercher" #: src/gui-gtk/gtk-goban-window.c:470 msgid "Search for a string in comments" msgstr "Recherche une chaîne de caractères dans les commentaires" #: src/gui-gtk/gtk-goban-window.c:475 msgid "Info" msgstr "Info" #: src/gui-gtk/gtk-goban-window.c:475 msgid "View and edit game information" msgstr "Afficher et éditer les informations sur la partie" #: src/gui-gtk/gtk-goban-window.c:481 msgid "Undo" msgstr "Annuler" #: src/gui-gtk/gtk-goban-window.c:481 msgid "Undo the last action" msgstr "Annuler la dernière action" #: src/gui-gtk/gtk-goban-window.c:486 msgid "Redo" msgstr "Restaurer" #: src/gui-gtk/gtk-goban-window.c:486 msgid "Redo the last undone action" msgstr "Restaurer la dernière action annulée" #: src/gui-gtk/gtk-goban-window.c:491 msgid "Delete" msgstr "Supprimer" #: src/gui-gtk/gtk-goban-window.c:491 msgid "Delete the current node" msgstr "Supprimer le noeud actif" #: src/gui-gtk/gtk-goban-window.c:497 msgid "Root" msgstr "Racine" #: src/gui-gtk/gtk-goban-window.c:497 msgid "Go to the root node" msgstr "Aller au noeud racine" #: src/gui-gtk/gtk-goban-window.c:502 msgid "Back" msgstr "Précédent" #: src/gui-gtk/gtk-goban-window.c:502 msgid "Go to the previous node" msgstr "Aller au noeud précédent" #: src/gui-gtk/gtk-goban-window.c:507 msgid "Forward" msgstr "Suivant" #: src/gui-gtk/gtk-goban-window.c:507 msgid "Go to the next node" msgstr "Aller au noeud suivant" #: src/gui-gtk/gtk-goban-window.c:512 msgid "End" msgstr "Fin" #: src/gui-gtk/gtk-goban-window.c:512 msgid "Go to the current variation's last node" msgstr "Aller au dernier noeud de la variation active" #: src/gui-gtk/gtk-goban-window.c:518 msgid "Previous" msgstr "Précédente" #: src/gui-gtk/gtk-goban-window.c:518 msgid "Switch to the previous variation" msgstr "Basculer sur la variation précédente" #: src/gui-gtk/gtk-goban-window.c:524 msgid "Next" msgstr "Suivante" #: src/gui-gtk/gtk-goban-window.c:524 msgid "Switch to the next variation" msgstr "Basculer sur la variation suivante" #: src/gui-gtk/gtk-goban-window.c:629 msgid "/_File" msgstr "/_Fichier" #: src/gui-gtk/gtk-goban-window.c:630 msgid "/File/_New Game..." msgstr "/Fichier/_Nouvelle partie..." #: src/gui-gtk/gtk-goban-window.c:633 msgid "/File/Ne_w Game Record..." msgstr "/Fichier/Nouvel _enregistrement de partie..." #: src/gui-gtk/gtk-goban-window.c:636 src/gui-gtk/gtk-goban-window.c:653 #: src/gui-gtk/gtk-goban-window.c:661 msgid "/File/" msgstr "/Fichier/" #: src/gui-gtk/gtk-goban-window.c:638 msgid "/File/_Open..." msgstr "/Fichier/_Ouvrir..." #: src/gui-gtk/gtk-goban-window.c:641 msgid "/File/_Resume Game..." msgstr "/Fichier/_Reprendre une partie..." #: src/gui-gtk/gtk-goban-window.c:645 msgid "/File/_Export..." msgstr "/Fichier/_Exporter..." #: src/gui-gtk/gtk-goban-window.c:646 msgid "/File/Export.../_ASCII Diagram" msgstr "/Fichier/Exporter.../Diagramme _ASCII" #: src/gui-gtk/gtk-goban-window.c:649 msgid "/File/Export.../_Sensei's Library Diagram" msgstr "/Fichier/Exporter.../Diagramme au format Sensei's Library" #: src/gui-gtk/gtk-goban-window.c:655 msgid "/File/_Save" msgstr "/Fichier/_Enregistrer" #: src/gui-gtk/gtk-goban-window.c:658 msgid "/File/Save _As..." msgstr "/Fichier/Enregistrer _sous..." #: src/gui-gtk/gtk-goban-window.c:663 msgid "/File/_Close" msgstr "/Fichier/_Fermer" #: src/gui-gtk/gtk-goban-window.c:666 msgid "/File/_Quit" msgstr "/Fichier/_Quitter" #: src/gui-gtk/gtk-goban-window.c:671 msgid "/_Edit" msgstr "/Édition" #: src/gui-gtk/gtk-goban-window.c:672 msgid "/Edit/_Undo" msgstr "/Édition/_Annuler" #: src/gui-gtk/gtk-goban-window.c:675 msgid "/Edit/_Redo" msgstr "/Édition/_Restaurer" #: src/gui-gtk/gtk-goban-window.c:678 src/gui-gtk/gtk-goban-window.c:695 #: src/gui-gtk/gtk-goban-window.c:739 src/gui-gtk/gtk-goban-window.c:747 #: src/gui-gtk/gtk-goban-window.c:767 src/gui-gtk/gtk-goban-window.c:778 #: src/gui-gtk/gtk-goban-window.c:783 msgid "/Edit/" msgstr "/Édition/" #: src/gui-gtk/gtk-goban-window.c:680 msgid "/Edit/Cu_t" msgstr "/Édition/_Couper" #: src/gui-gtk/gtk-goban-window.c:683 msgid "/Edit/_Copy" msgstr "/Édition/C_opier" #: src/gui-gtk/gtk-goban-window.c:686 msgid "/Edit/_Paste" msgstr "/Édition/Co_ller" #: src/gui-gtk/gtk-goban-window.c:689 msgid "/Edit/_Delete Node" msgstr "/Édition/_Supprimer le noeud" #: src/gui-gtk/gtk-goban-window.c:692 msgid "/Edit/Delete Node's C_hildren" msgstr "/Édition/Supprimer la _descendance du noeud" #: src/gui-gtk/gtk-goban-window.c:698 msgid "/Edit/T_ools" msgstr "/Édition/Ou_tils" #: src/gui-gtk/gtk-goban-window.c:699 msgid "/Edit/Tools/_Move Tool" msgstr "/Édition/Outils/_Coups" #: src/gui-gtk/gtk-goban-window.c:702 msgid "/Edit/Tools/_Setup Tool" msgstr "/Édition/Outils/_Situations" #: src/gui-gtk/gtk-goban-window.c:705 src/gui-gtk/gtk-goban-window.c:722 #: src/gui-gtk/gtk-goban-window.c:730 msgid "/Edit/Tools/" msgstr "/Édition/Outils/" #: src/gui-gtk/gtk-goban-window.c:707 msgid "/Edit/Tools/C_ross Markup" msgstr "/Édition/Outils/Marquage _croix" #: src/gui-gtk/gtk-goban-window.c:710 msgid "/Edit/Tools/_Circle Markup" msgstr "/Édition/Outils/Marquage c_ercle" #: src/gui-gtk/gtk-goban-window.c:713 msgid "/Edit/Tools/S_quare Markup" msgstr "/Édition/Outils/Marquage c_arré" #: src/gui-gtk/gtk-goban-window.c:716 msgid "/Edit/Tools/_Triangle Markup" msgstr "/Édition/Outils/Marquage _triangle" #: src/gui-gtk/gtk-goban-window.c:719 msgid "/Edit/Tools/S_elected Markup" msgstr "/Édition/Outils/Marquage _sélectionné" #: src/gui-gtk/gtk-goban-window.c:724 msgid "/Edit/Tools/_Label Tool" msgstr "/Édition/Outils/Outil d'étiquetage" #: src/gui-gtk/gtk-goban-window.c:727 msgid "/Edit/Tools/_Number Tool" msgstr "/Édition/Outils/Outil de numérotation" #: src/gui-gtk/gtk-goban-window.c:732 msgid "/Edit/Tools/Scori_ng Tool" msgstr "/Édition/Outils/Outil de score" #: src/gui-gtk/gtk-goban-window.c:736 msgid "/Edit/_Add Empty Node" msgstr "/Édition/_Ajouter un noeud vide" #: src/gui-gtk/gtk-goban-window.c:741 msgid "/Edit/Move _Branch Up" msgstr "/Édition/_Monter la branche" #: src/gui-gtk/gtk-goban-window.c:744 msgid "/Edit/Move Branch Do_wn" msgstr "/Édition/_Descendre la branche" #: src/gui-gtk/gtk-goban-window.c:749 msgid "/Edit/Edit Node _Name" msgstr "/Édition/Éditer le _nom du noeud" #: src/gui-gtk/gtk-goban-window.c:752 msgid "/Edit/Set _Move Number" msgstr "/Édition/_Définir le numéro du coup" #: src/gui-gtk/gtk-goban-window.c:756 msgid "/Edit/P_layer to Move" msgstr "/Édition/À _qui le tour" #: src/gui-gtk/gtk-goban-window.c:757 msgid "/Edit/Player to Move/_White" msgstr "/Édition/À qui le tour/_Blancs" #: src/gui-gtk/gtk-goban-window.c:760 msgid "/Edit/Player to Move/_Black" msgstr "/Édition/À qui le tour/_Noirs" #: src/gui-gtk/gtk-goban-window.c:763 msgid "/Edit/Player to Move/By Game _Rules" msgstr "/Édition/À qui le tour/Suivant les _règles" #: src/gui-gtk/gtk-goban-window.c:769 msgid "/Edit/_Find" msgstr "/Édition/_Rechercher" #: src/gui-gtk/gtk-goban-window.c:772 msgid "/Edit/Find Ne_xt" msgstr "/Édition/Rechercher le _suivant" #: src/gui-gtk/gtk-goban-window.c:775 msgid "/Edit/Find Pre_vious" msgstr "/Édition/Rechercher le _précédent" #: src/gui-gtk/gtk-goban-window.c:780 msgid "/Edit/Game _Information" msgstr "/Édition/_Informations sur la partie" #: src/gui-gtk/gtk-goban-window.c:785 msgid "/Edit/Pr_eferences" msgstr "/Édition/_Préférences" #: src/gui-gtk/gtk-goban-window.c:790 msgid "/_View" msgstr "/_Affichage" #: src/gui-gtk/gtk-goban-window.c:791 msgid "/View/_Main Toolbar" msgstr "/Affichage/Barre d'outils _principale" #: src/gui-gtk/gtk-goban-window.c:794 msgid "/View/_Editing Toolbar" msgstr "/Affichage/Barre d'_édition" #: src/gui-gtk/gtk-goban-window.c:797 msgid "/View/_Navigation Toolbar" msgstr "/Affichage/Barre de _navigation" #: src/gui-gtk/gtk-goban-window.c:800 src/gui-gtk/gtk-goban-window.c:805 #: src/gui-gtk/gtk-goban-window.c:813 msgid "/View/" msgstr "/Affichage/" #: src/gui-gtk/gtk-goban-window.c:802 msgid "/View/_Game Action Buttons" msgstr "/Affichage/_Boutons d'actions pour la partie" #: src/gui-gtk/gtk-goban-window.c:807 msgid "/View/Game _Tree" msgstr "/Affichage/_Arbre de la partie" #: src/gui-gtk/gtk-goban-window.c:810 msgid "/View/_Recenter on Current Node" msgstr "/Affichage/_Recentrer sur le noeud actif" #: src/gui-gtk/gtk-goban-window.c:815 msgid "/View/_Control Center" msgstr "/Affichage/_Centre de contrôle" #: src/gui-gtk/gtk-goban-window.c:820 msgid "/_Play" msgstr "/_Jouer" #: src/gui-gtk/gtk-goban-window.c:821 msgid "/Play/_Pass" msgstr "/Jouer/_Passer" #: src/gui-gtk/gtk-goban-window.c:824 src/gui-gtk/gtk-goban-window.c:829 msgid "/Play/" msgstr "/Jouer/" #: src/gui-gtk/gtk-goban-window.c:826 msgid "/Play/_Resign" msgstr "/Jouer/_Abandonner" #: src/gui-gtk/gtk-goban-window.c:831 msgid "/Play/_Adjourn Game" msgstr "/Jouer/Ajourner la _partie" #: src/gui-gtk/gtk-goban-window.c:836 msgid "/_Go" msgstr "/_Aller à" #: src/gui-gtk/gtk-goban-window.c:837 msgid "/Go/_Previous Node" msgstr "/Aller à/Noeud _précédent" #: src/gui-gtk/gtk-goban-window.c:840 msgid "/Go/_Next Node" msgstr "/Aller à/Noeud _suivant" #: src/gui-gtk/gtk-goban-window.c:843 msgid "/Go/Ten Nodes _Backward" msgstr "/Aller à/Dix noeud en _arrière" #: src/gui-gtk/gtk-goban-window.c:846 msgid "/Go/Ten Nodes _Forward" msgstr "/Aller à/Dix noeuds en a_vant" #: src/gui-gtk/gtk-goban-window.c:849 src/gui-gtk/gtk-goban-window.c:857 #: src/gui-gtk/gtk-goban-window.c:867 msgid "/Go/" msgstr "/Aller à/" #: src/gui-gtk/gtk-goban-window.c:851 msgid "/Go/_Root Node" msgstr "/Aller à/Noeud _racine" #: src/gui-gtk/gtk-goban-window.c:854 msgid "/Go/Variation _Last Node" msgstr "/Aller à/_Dernier noeud de la variation" #: src/gui-gtk/gtk-goban-window.c:859 msgid "/Go/Pre_vious Variation" msgstr "/Aller à/Variation précé_dente" #: src/gui-gtk/gtk-goban-window.c:862 msgid "/Go/Ne_xt Variation" msgstr "/Aller à/Variation su_ivante" #: src/gui-gtk/gtk-goban-window.c:868 msgid "/Go/_Go to Named Node..." msgstr "/Aller à/_Aller à un noeud nommé" #: src/gui-gtk/gtk-goban-window.c:874 msgid "/_Help" msgstr "/_Aide" #: src/gui-gtk/gtk-goban-window.c:875 msgid "/Help/_Contents" msgstr "/Aide/_Sommaire" #: src/gui-gtk/gtk-goban-window.c:878 msgid "/Help/_About" msgstr "/Aide/À _propos" #: src/gui-gtk/gtk-goban-window.c:884 msgid "/Move Tool" msgstr "/Coups" #: src/gui-gtk/gtk-goban-window.c:885 msgid "/Setup Tool" msgstr "/Situations" #: src/gui-gtk/gtk-goban-window.c:888 msgid "/Cross Markup" msgstr "/Marquage croix" #: src/gui-gtk/gtk-goban-window.c:889 msgid "/Circle Markup" msgstr "/Marquage cercle" #: src/gui-gtk/gtk-goban-window.c:890 msgid "/Square Markup" msgstr "/Marquage carré" #: src/gui-gtk/gtk-goban-window.c:891 msgid "/Triangle Markup" msgstr "/Marquage triangle" #: src/gui-gtk/gtk-goban-window.c:892 msgid "/Selected Markup" msgstr "/Marquage sélectionné" #: src/gui-gtk/gtk-goban-window.c:895 msgid "/Label Tool" msgstr "/Outil d'étiquetage" #: src/gui-gtk/gtk-goban-window.c:896 msgid "/Number Tool" msgstr "/Outil de numérotation" #: src/gui-gtk/gtk-goban-window.c:899 msgid "/Scoring Tool" msgstr "/Outil de score" #: src/gui-gtk/gtk-goban-window.c:964 msgid "Black" msgstr "Noirs" #: src/gui-gtk/gtk-goban-window.c:964 msgid "White" msgstr "Blancs" #: src/gui-gtk/gtk-goban-window.c:992 msgid "Pass" msgstr "Passer" #: src/gui-gtk/gtk-goban-window.c:998 msgid "Resign" msgstr "Abandonner" #: src/gui-gtk/gtk-goban-window.c:1438 #, c-format msgid "Save changes to game record `%s' before closing?" msgstr "Enregistrer les modifications de la partie \"%s\" avant de fermer ?" #: src/gui-gtk/gtk-goban-window.c:1447 msgid "Save changes to the untitled game record before closing?" msgstr "Enregistrer les modifications de la partie sans nom avant de fermer ?" #. TRANSLATORS: Width of this string in default font is used to #. determine the minimal width of the right board window side. #: src/gui-gtk/gtk-goban-window.c:1522 msgid "A good width for the right side to have." msgstr "Une bonne largeur pour le côté droit." #. TRANSLATORS: It can never be 1 stone, always at least 2. #: src/gui-gtk/gtk-goban-window.c:1582 #, c-format msgid "" "Please set up %d (or less)\n" "stone of free handicap" msgid_plural "" "Please set up %d (or less)\n" "stones of free handicap" msgstr[0] "" "Veuillez placer %d pierre\n" "(ou moins) de handicap libre" msgstr[1] "" "Veuillez placer %d pierres\n" "(ou moins) de handicap libre" #: src/gui-gtk/gtk-goban-window.c:1774 msgid "Adjourn & Save As..." msgstr "Ajourner & Enregistrer sous..." #: src/gui-gtk/gtk-goban-window.c:1774 msgid "Save As..." msgstr "Enregistrer sous..." #: src/gui-gtk/gtk-goban-window.c:1923 #, c-format msgid "Error saving to file `%s'" msgstr "Erreur lors de l'enregistrement du fichier \"%s\"" #: src/gui-gtk/gtk-goban-window.c:1937 msgid "" "You can later resume the game by pressing the `Resume Game' button in Quarry " "Control Center, or selecting `Resume Game' item from the `File' menu." msgstr "" "Vous pouvez reprendre la partie plus tard en pressant le bouton \"Reprendre " "la partie\" dans le centre de contrôle Quarry, ou en choisissant l'entrée " "correspondante du menu \"Fichier\"." #: src/gui-gtk/gtk-goban-window.c:1943 #, c-format msgid "The game is adjourned and saved in file `%s'" msgstr "La partie est ajournée et enregistrée dans le fichier \"%s\"" #: src/gui-gtk/gtk-goban-window.c:1962 msgid "ASCII diagram has been exported to clipboard" msgstr "Le diagramme ASCII a été exporté dans le presse-papier" #: src/gui-gtk/gtk-goban-window.c:1975 msgid "Sensei's Library diagram has been exported to clipboard" msgstr "" "Le diagramme au format Sensei's Library a été exporté dans le presse-papier" #: src/gui-gtk/gtk-goban-window.c:1990 msgid "" "You can usually paste the diagram in another application using `Ctrl+C' key " "combination or by selecting appropriate menu item." msgstr "" "Vous pouvez généralement coller le diagramme dans une autre application en " "utilisant la combinaison de touches \"Ctrl + C\", ou en choisissant l'entrée " "appropriée du menu." #: src/gui-gtk/gtk-goban-window.c:2446 msgid "Sorry, there are no named nodes in this game tree" msgstr "Désolé, il n'y a pas de noeud nommé dans cet arbre de partie" #: src/gui-gtk/gtk-goban-window.c:2470 msgid "A GUI program for Go, Amazons and Reversi board games" msgstr "Une interface graphique pour les jeux de Go, Amazones et Reversi" #: src/gui-gtk/gtk-goban-window.c:2472 msgid "Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev and others" msgstr "Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev et autres" #: src/gui-gtk/gtk-goban-window.c:2488 msgid "About Quarry" msgstr "À propos de Quarry" #: src/gui-gtk/gtk-goban-window.c:2931 msgid "Really resign this game?" msgstr "Réellement abandonner la partie ?" #: src/gui-gtk/gtk-goban-window.c:2935 msgid "_Resign" msgstr "_Abandonner" #: src/gui-gtk/gtk-goban-window.c:3524 msgid "Edit Board Label" msgstr "Éditer les étiquettes du plateau" #: src/gui-gtk/gtk-goban-window.c:3527 msgid "Add Board Label" msgstr "Ajouter une étiquette au plateau" #: src/gui-gtk/gtk-goban-window.c:4026 #, c-format msgid "%s (W) vs. %s" msgstr "%s (B) vs. %s" #: src/gui-gtk/gtk-goban-window.c:4050 msgid "Unnamed Game" msgstr "Partie sans nom" #: src/gui-gtk/gtk-goban-window.c:4055 msgid "modified" msgstr "modifié" #: src/gui-gtk/gtk-goban-window.c:4088 msgid "[unknown]" msgstr "[inconnu]" #: src/gui-gtk/gtk-goban-window.c:4121 src/gui-gtk/gtk-goban-window.c:4126 #, c-format msgid "%d capture" msgid_plural "%d captures" msgstr[0] "%d capture" msgstr[1] "%d captures" #: src/gui-gtk/gtk-goban-window.c:4136 #, c-format msgid "%s %s %.*f komi" msgstr "%s %s %.*f komi" #: src/gui-gtk/gtk-goban-window.c:4147 #, c-format msgid "%s %s %d komi" msgid_plural "%s %s %d komi" msgstr[0] "%s %s %d komi" msgstr[1] "%s %s %d komi" #: src/gui-gtk/gtk-goban-window.c:4163 src/gui-gtk/gtk-goban-window.c:4166 #, c-format msgid "%d disk" msgid_plural "%d disks" msgstr[0] "%d disque" msgstr[1] "%d disques" #: src/gui-gtk/gtk-goban-window.c:4197 #, c-format msgid "Move %d: " msgstr "Coup %d :" #: src/gui-gtk/gtk-goban-window.c:4201 #, c-format msgid "Last move: %u, " msgstr "Dernier coup: %u," #. TRANSLATORS: This is an #. abbreviation of `Black'. #: src/gui-gtk/gtk-goban-window.c:4208 msgid "B " msgstr "N" #. TRANSLATORS: This is an #. abbreviation of `White'. #: src/gui-gtk/gtk-goban-window.c:4211 msgid "W " msgstr "B" #: src/gui-gtk/gtk-goban-window.c:4212 msgid "pass" msgstr "passe" #: src/gui-gtk/gtk-goban-window.c:4215 msgid "Game beginning" msgstr "Début de partie" #: src/gui-gtk/gtk-goban-window.c:4233 msgid "; black to play" msgstr "; aux noirs de jouer" #: src/gui-gtk/gtk-goban-window.c:4233 msgid "; white to play" msgstr "; aux blancs de jouer" #: src/gui-gtk/gtk-goban-window.c:4236 msgid "; game over" msgstr "; fin de partie" #: src/gui-gtk/gtk-goban-window.c:4243 msgid "Black wins" msgstr "Les noirs ont gagné" #: src/gui-gtk/gtk-goban-window.c:4246 msgid "White wins" msgstr "Les blancs ont gagné" #: src/gui-gtk/gtk-goban-window.c:4250 msgid "Black wins by forfeit" msgstr "Les noirs gagnent par forfait" #: src/gui-gtk/gtk-goban-window.c:4253 msgid "White wins by forfeit" msgstr "Les blancs gagnent par forfait" #: src/gui-gtk/gtk-goban-window.c:4257 msgid "White resigns" msgstr "Les blancs abandonnent" #: src/gui-gtk/gtk-goban-window.c:4260 msgid "Black resigns" msgstr "Les noirs abandonnent" #: src/gui-gtk/gtk-goban-window.c:4272 msgid "White runs out of time and loses" msgstr "Les blancs perdent (temps épuisé)" #: src/gui-gtk/gtk-goban-window.c:4276 msgid "Black runs out of time and loses" msgstr "Les noirs perdent (temps épuisé)" #: src/gui-gtk/gtk-goban-window.c:4280 msgid "Game is draw" msgstr "Match nul" #: src/gui-gtk/gtk-goban-window.c:4499 msgid "By Game _Rules (Game Over)" msgstr "Suivant les _règles du jeu (fin de partie)" #: src/gui-gtk/gtk-goban-window.c:4503 msgid "By Game _Rules (Black)" msgstr "Suivant les _règles du jeu (noirs)" #: src/gui-gtk/gtk-goban-window.c:4507 msgid "By Game _Rules (White)" msgstr "Suivant les _règles du jeu (blancs)" #: src/gui-gtk/gtk-goban-window.c:4551 msgid "insert node name here" msgstr "insérez ici le nom du noeud" #: src/gui-gtk/gtk-goban-window.c:4952 msgid "Set Move Number" msgstr "Spécifier le numéro du coup" #. TRANSLATORS: Note that game name will be in `normal' form. #: src/gui-gtk/gtk-goban-window.c:5062 #, c-format msgid "" "GTP engine `%s' reported it could handle %s game, but failed to initialize " "itself for it" msgstr "" "Le moteur GTP \"%s\" a affirmé pouvoir prendre en charge le jeu %s, mais " "n'est pas parvenu a s'initialiser pour lui" #: src/gui-gtk/gtk-goban-window.c:5070 #, c-format msgid "GTP engine `%s' cannot handle %dx%d board size, sorry" msgstr "" "Désolé, le moteur GTP \"%s\" ne peut gérer les plateaux de taille %dx%d" #: src/gui-gtk/gtk-goban-window.c:5080 #, c-format msgid "GTP engine `%s' failed to clean the board" msgstr "Le moteur GTP \"%s\" n'est pas parvenu à nettoyer le plateau" #: src/gui-gtk/gtk-goban-window.c:5086 #, c-format msgid "" "GTP engine `%s' failed to set initial time limits (it could ignore them, but " "not fail)" msgstr "" "Le moteur GTP \"%s\" n'a pas réussi à définir les limites de temps initiales " "(il pourrait les ignorer, mais ne devrait pas échouer)" #: src/gui-gtk/gtk-goban-window.c:5094 #, c-format msgid "GTP engine `%s' failed to set handicap stones on board" msgstr "" "Le moteur GTP \"%s\" n'est pas parvenu à placer les pierres de handicap sur " "le plateau" #: src/gui-gtk/gtk-goban-window.c:5108 msgid "This is an engine error. You may want to report it to engine authors." msgstr "" "Ceci est une erreur provenant du moteur de jeu. Vous pourriez la communiquer " "aux auteurs de ce dernier." #: src/gui-gtk/gtk-goban-window.c:5392 msgid "GTP engine is scoring..." msgstr "Le moteur GTP calcule le score..." #: src/gui-gtk/gtk-goban-window.c:5771 msgid "" "Unable to paste game record fragment from clipboard since it is not intended " "for pasting" msgstr "" "Impossible de coller le fragment d'enregistrement de partie à partir du " "presse-papier, car il n'est pas fait pour être collé" #: src/gui-gtk/gtk-goban-window.c:5774 msgid "" "Clipboard SGF probably contains more than one game tree or not a single " "child of the root of the only game tree." msgstr "" "Le SGF du presse-papier contient probablement plus d'un arbre de partie, ou " "pas un seul descendant à la racine de l'unique arbre de partie." #: src/gui-gtk/gtk-goban-window.c:5778 msgid "Unable to paste game record fragment from clipboard" msgstr "" "Impossible de coller le fragment d'enregistrement de partie à partir du " "presse-papier" #. TRANSLATORS: This message is shown if you e.g. copy a part of #. 13x13 game tree and try to paste it into a 19x19 game tree; or #. copy a part of a Reversi game tree and try to paste it into a #. Go game tree. #: src/gui-gtk/gtk-goban-window.c:5784 msgid "Clipboard game record fragment must be of different game or board size." msgstr "" "Le fragment d'enregistrement de partie dans le presse-papier a probablement " "une taille de plateau différente." #: src/gui-gtk/gtk-goban-window.c:5788 msgid "Clipboard contains an invalid game record fragment (SGF)" msgstr "" "Le presse-papier contient un fragment d'enregistrement de partie (SGF) " "invalide" #: src/gui-gtk/gtk-goban-window.c:5937 msgid "" "Please select dead stones\n" "to score the game" msgstr "" "Veuillez choisir les pierres mortes\n" "pour établir le score" #: src/gui-gtk/gtk-go-to-named-node-dialog.c:135 msgid "Go to Named Node" msgstr "Aller à un noeud nommé" #: src/gui-gtk/gtk-go-to-named-node-dialog.c:150 msgid "Node _name:" msgstr "_Nom du noeud :" #: src/gui-gtk/gtk-go-to-named-node-dialog.c:156 msgid "Node comment:" msgstr "Commentaire du noeud :" #: src/gui-gtk/gtk-go-to-named-node-dialog.c:331 msgid "comment|Empty" msgstr "commentaire|Vide" #: src/gui-gtk/gtk-go-to-named-node-dialog.c:334 msgid "There is no such node" msgstr "Ce noeud n'existe pas" #: src/gui-gtk/gtk-gtp-client-interface.c:282 msgid "Engine hung up" msgstr "Le moteur s'est figé" #: src/gui-gtk/gtk-gtp-client-interface.c:391 msgid "* ERROR: wrong response format\n" msgstr "* ERREUR : mauvais format de réponse\n" #: src/gui-gtk/gtk-gtp-client-interface.c:395 msgid "* WARNING: unexpected response:\n" msgstr "* ATTENTION : réponse inattendue :\n" #: src/gui-gtk/gtk-gtp-client-interface.c:399 msgid "* ERROR: unrecognized response line:\n" msgstr "* ERREUR : ligne de réponse non reconnue :\n" #: src/gui-gtk/gtk-gtp-client-interface.c:404 #, c-format msgid "* ERROR: mismatched ID (%d expected):\n" msgstr "* ERREUR : l'ID ne correspond pas (attendu: %d) :\n" #: src/gui-gtk/gtk-gtp-client-interface.c:408 msgid "* ERROR: unexpected ID in response (the command had none):\n" msgstr "" "* ERREUR : ID inattendu dans la réponse (l'a commande n'en avant aucun) :\n" #. TRANSLATORS: Don't put ellipsis here, this string will most #. often go to fixed-width font terminals. #: src/gui-gtk/gtk-gtp-client-interface.c:415 msgid "* WARNING: future GTP version, I don't know about it...\n" msgstr "* ATTENTION : version future de GTP, je ne la connais pas.\n" #: src/gui-gtk/gtk-new-game-dialog.c:98 msgid "" "Note that most GTP engines support only one game. Hence certain game / " "computer player combinations may be not possible to play." msgstr "" "Notez que la plupart des moteurs GTP ne prennent en charge qu'une partie. " "Par conséquent certaines combinaisons jeu / joueur géré par l'ordinateur " "peuvent ne pas être possibles." #: src/gui-gtk/gtk-new-game-dialog.c:102 msgid "Fi_xed handicap:" msgstr "Handicap _fix :" #: src/gui-gtk/gtk-new-game-dialog.c:102 msgid "_Free handicap:" msgstr "Handicap _libre :" #: src/gui-gtk/gtk-new-game-dialog.c:105 msgid "No limit" msgstr "Pas de limite" #: src/gui-gtk/gtk-new-game-dialog.c:105 msgid "Limited time for entire game" msgstr "Temps limité pour toute la partie" #: src/gui-gtk/gtk-new-game-dialog.c:106 msgid "Limited time per move" msgstr "Temps limité par coup" #: src/gui-gtk/gtk-new-game-dialog.c:106 msgid "Canadian overtime" msgstr "Temps supplémentaire canadien" #: src/gui-gtk/gtk-new-game-dialog.c:124 msgid "New Game" msgstr "Nouvelle partie" #: src/gui-gtk/gtk-new-game-dialog.c:167 #: src/gui-gtk/gtk-new-game-record-dialog.c:132 msgid "Game" msgstr "Partie" #: src/gui-gtk/gtk-new-game-dialog.c:173 #: src/gui-gtk/gtk-resume-game-dialog.c:307 msgid "Hu_man" msgstr "_Humain" #: src/gui-gtk/gtk-new-game-dialog.c:173 #: src/gui-gtk/gtk-resume-game-dialog.c:308 msgid "Com_puter" msgstr "_Ordinateur" #: src/gui-gtk/gtk-new-game-dialog.c:174 #: src/gui-gtk/gtk-resume-game-dialog.c:308 msgid "H_uman" msgstr "H_umain" #: src/gui-gtk/gtk-new-game-dialog.c:174 msgid "C_omputer" msgstr "O_rdinateur" #: src/gui-gtk/gtk-new-game-dialog.c:238 msgid "Manage _Engine List" msgstr "_Gérer la liste des moteurs" #: src/gui-gtk/gtk-new-game-dialog.c:258 msgid "_Swap" msgstr "_Échanger" #: src/gui-gtk/gtk-new-game-dialog.c:287 msgid "Game & Players" msgstr "Partie & Joueurs" #: src/gui-gtk/gtk-new-game-dialog.c:362 msgid "Time control _type:" msgstr "_Type de contrôle du temps :" #: src/gui-gtk/gtk-new-game-dialog.c:384 msgid "Time Limit" msgstr "Limite de temps" #: src/gui-gtk/gtk-new-game-dialog.c:387 msgid "K_eep track of total time" msgstr "_Compter le temps total" #: src/gui-gtk/gtk-new-game-dialog.c:407 msgid "Time _limit for game:" msgstr "_Limite de temps pour la partie :" #: src/gui-gtk/gtk-new-game-dialog.c:413 msgid "(per player)" msgstr "(par joueur)" #: src/gui-gtk/gtk-new-game-dialog.c:427 msgid "Time _limit for move:" msgstr "_Limite de temps par coup :" #: src/gui-gtk/gtk-new-game-dialog.c:461 msgid "_Overtime period length:" msgstr "_Durée du temps supplémentaire :" #: src/gui-gtk/gtk-new-game-dialog.c:478 msgid "Mo_ves per overtime:" msgstr "_Coups par temps supplémentaire :" #: src/gui-gtk/gtk-new-game-record-dialog.c:119 msgid "New Game Record" msgstr "Nouvel enregistrement de partie" #: src/gui-gtk/gtk-new-game-record-dialog.c:189 msgid "_Place stones" msgstr "_Placer les pierres" #: src/gui-gtk/gtk-new-game-record-dialog.c:265 msgid "_White player:" msgstr "Joueur _blanc :" #: src/gui-gtk/gtk-new-game-record-dialog.c:276 msgid "_Black player:" msgstr "Joueur _noir :" #: src/gui-gtk/gtk-new-game-record-dialog.c:287 msgid "Game _name:" msgstr "_Nom de la partie :" #: src/gui-gtk/gtk-new-game-record-dialog.c:300 msgid "" "You can always change and expand game information later. Just choose `Edit/" "Game Information' menu item or press `Info' button on the main toolbar." msgstr "" "Vous pouvez modifier les informations sur la partie plus tard en choisissant " "\"Édition/Informations sur la partie\" dans le menu, ou en pression le " "bouton \"Info\" de la barre d'outils principale." #: src/gui-gtk/gtk-new-game-record-dialog.c:310 #: src/gui-gtk/gtk-resume-game-dialog.c:227 msgid "Short Game Information" msgstr "Informations brèves sur la partie" #: src/gui-gtk/gtk-parser-interface.c:58 #, c-format msgid "Error reading file `%s'" msgstr "Erreur lors de la lecture du fichier \"%s\"" #: src/gui-gtk/gtk-parser-interface.c:60 #, c-format msgid "File `%s' doesn't appear to be a valid SGF file" msgstr "Le fichier \"%s\" ne semble pas être un fichier SGF valide" #: src/gui-gtk/gtk-parser-interface.c:63 msgid "" "Please check that the file exists and its permission allow you to read it." msgstr "" "Veuillez vérifier que le fichier existe et que vous êtes autorisé à le lire." #: src/gui-gtk/gtk-parser-interface.c:67 msgid "" "Quarry uses SGF file format for storing game records. SGF files would " "normally have `sgf' extension, but that's not necessarily true. Please make " "sure you select a proper SGF file." msgstr "" "Quarry utilise le format de fichier SGF pour stocker les enregistrements de " "parties. Les fichiers SGF portent normalement l'extention \".sgf\", mais ce " "n'est pas toujours le cas. Assurez-vous de sélectionner un véritable fichier " "SGF." #: src/gui-gtk/gtk-parser-interface.c:101 msgid "Open SGF File..." msgstr "Ouvrir un fichier SGF..." #: src/gui-gtk/gtk-parser-interface.c:192 #, c-format msgid "Parsing file `%s'..." msgstr "Lecture du fichier \"%s\"..." #: src/gui-gtk/gtk-preferences.c:431 msgid "General" msgstr "Général" #: src/gui-gtk/gtk-preferences.c:434 msgid "Interface" msgstr "Interface" #: src/gui-gtk/gtk-preferences.c:435 msgid "General Interface" msgstr "Interface générale" #: src/gui-gtk/gtk-preferences.c:437 msgid "Editing & Viewing" msgstr "Édition & Affichage" #: src/gui-gtk/gtk-preferences.c:440 src/gui-gtk/gtk-preferences.c:441 msgid "Game Tree" msgstr "Arbre de la partie" #: src/gui-gtk/gtk-preferences.c:444 msgid "GTP" msgstr "GTP" #: src/gui-gtk/gtk-preferences.c:447 src/gui-gtk/gtk-preferences.c:448 msgid "GTP Engines" msgstr "Moteurs GTP" #: src/gui-gtk/gtk-preferences.c:451 msgid "Game Records (SGF)" msgstr "Enregistrements de parties (SGF)" #: src/gui-gtk/gtk-preferences.c:454 msgid "Saving" msgstr "Enregistrement" #: src/gui-gtk/gtk-preferences.c:455 msgid "Saving Game Records" msgstr "Enregistrement de parties" #: src/gui-gtk/gtk-preferences.c:458 msgid "Board Appearance" msgstr "Apparence du plateau" #: src/gui-gtk/gtk-preferences.c:462 msgid "Go Board Appearance" msgstr "Apparence du plateau de Go" #: src/gui-gtk/gtk-preferences.c:465 msgid "Amazons Board Appearance" msgstr "Apparence du plateau des Amazones" #: src/gui-gtk/gtk-preferences.c:468 msgid "Reversi Board Appearance" msgstr "Apparence du plateau de Reversi" #: src/gui-gtk/gtk-preferences.c:478 msgid "Preferences" msgstr "Préférences" #: src/gui-gtk/gtk-preferences.c:515 msgid "Categor_y:" msgstr "_Catégorie :" #: src/gui-gtk/gtk-preferences.c:641 msgid "Use _newer (GTK+ 2.4) file chooser" msgstr "Utiliser le _nouveau sélecteur de fichier (GTK+ 2.4)" #: src/gui-gtk/gtk-preferences.c:642 msgid "Use _old-style file selection dialog" msgstr "Utiliser l'_ancien sélecteur de fichier" #: src/gui-gtk/gtk-preferences.c:672 msgid "File Chooser Dialog Style" msgstr "Style du sélecteur de fichiers" #: src/gui-gtk/gtk-preferences.c:688 msgid "_Main toolbar style:" msgstr "Style de la barre d'outils _principale :" #: src/gui-gtk/gtk-preferences.c:692 msgid "_Editing toolbar style:" msgstr "Style de la barre d'_édition :" #: src/gui-gtk/gtk-preferences.c:696 msgid "N_avigation toolbar style:" msgstr "Style de la barre de _navigation :" #: src/gui-gtk/gtk-preferences.c:705 msgid "Toolbar Styles" msgstr "Styles des barres d'outils" #: src/gui-gtk/gtk-preferences.c:725 msgid "Desktop default" msgstr "Utiliser les réglages globaux" #: src/gui-gtk/gtk-preferences.c:726 msgid "Text below icons" msgstr "Texte sous les icônes" #: src/gui-gtk/gtk-preferences.c:732 msgid "Text beside important icons" msgstr "Texte à côté des icônes importantes" #: src/gui-gtk/gtk-preferences.c:735 msgid "Icons only" msgstr "Icônes uniquement" #: src/gui-gtk/gtk-preferences.c:736 msgid "Text only" msgstr "Texte uniquement" #: src/gui-gtk/gtk-preferences.c:792 msgid "Show" msgstr "Afficher" #: src/gui-gtk/gtk-preferences.c:799 msgid "Name" msgstr "Nom" #: src/gui-gtk/gtk-preferences.c:808 msgid "_List of GTP engines:" msgstr "_Liste des moteurs GTP :" #: src/gui-gtk/gtk-preferences.c:856 msgid "Name:" msgstr "Nom :" #: src/gui-gtk/gtk-preferences.c:865 msgid "Version:" msgstr "Version :" #: src/gui-gtk/gtk-preferences.c:875 src/gui-gtk/gtk-preferences.c:1630 msgid "Supported game:" msgstr "Jeux pris en charge :" #: src/gui-gtk/gtk-preferences.c:889 msgid "Command line:" msgstr "Ligne de commande :" #: src/gui-gtk/gtk-preferences.c:914 msgid "GTP Engine Information" msgstr "Informations sur le moteur GTP" #: src/gui-gtk/gtk-preferences.c:935 msgid "_Always" msgstr "_Toujours" #: src/gui-gtk/gtk-preferences.c:935 msgid "A_utomatically" msgstr "_Automatiquement" #: src/gui-gtk/gtk-preferences.c:935 msgid "_Never" msgstr "_Jamais" #: src/gui-gtk/gtk-preferences.c:937 msgid "Al_ways" msgstr "T_oujours" #: src/gui-gtk/gtk-preferences.c:937 msgid "Aut_omatically" msgstr "A_utomatiquement" #: src/gui-gtk/gtk-preferences.c:937 msgid "Ne_ver" msgstr "Jamai_s" #: src/gui-gtk/gtk-preferences.c:939 msgid "Scroll _minimal distance" msgstr "Faire défiler sur une distance _minimale" #: src/gui-gtk/gtk-preferences.c:940 msgid "_Recenter view on the current node" msgstr "_Recentrer la vue sur le noeud actif" #: src/gui-gtk/gtk-preferences.c:943 msgid "" "In automatic mode the game tree is shown only if it has at least one " "variation. In any case, you can show/hide game tree in each window " "separately." msgstr "" "En mode automatique l'arbre de la partie n'est affiché que s'il possède au " "moins une variation. Dans tous les cas, vous pouvez afficher et cacher " "l'arbre de la partie dans chaque fenêtre séparément." #: src/gui-gtk/gtk-preferences.c:947 msgid "" "In automatic mode the game tree view scrolls to show the current node only " "if it has been showing current node before. I.e. unless you scrolled it away " "manually." msgstr "" "En mode automatique la vue sur l'arbre de la partie défile pour afficher le " "noeud actif, uniquement si le noeud actif était auparavant affiché (c'est-à-" "dire à moins que vous ayez fait défiler l'arbre manuellement)." #: src/gui-gtk/gtk-preferences.c:992 msgid "Show Game Tree" msgstr "Afficher l'arbre de la partie" #: src/gui-gtk/gtk-preferences.c:1039 msgid "Track Tree's Current Node" msgstr "Traquer le noeud actif dans l'arbre" #: src/gui-gtk/gtk-preferences.c:1042 msgid "Show _tooltips" msgstr "Afficher les bulles d'aide" #: src/gui-gtk/gtk-preferences.c:1049 msgid "Tooltips" msgstr "Bulles d'aide" #: src/gui-gtk/gtk-preferences.c:1065 msgid "Always use _UTF-8 (recommended)" msgstr "Toujours utiliser l'_UTF-8 (recommandé)" #: src/gui-gtk/gtk-preferences.c:1066 msgid "Preserve _original encoding" msgstr "Préserver l'encodage d'_origine" #: src/gui-gtk/gtk-preferences.c:1068 msgid "" "Note that many characters cannot be represented in non-UTF-8 encodings and " "thus some information may be lost if you use them. Quarry also works fastest " "with UTF-8; this may be important if you have very large SGF files." msgstr "" "Notez que de nombreux caractères ne peuvent pas être représentés dans les " "encodages autres que UTF-8, ainsi certaines informations peuvent être " "perdues si vous les utilisez. Quarry fonctionne également plus vite avec " "l'UTF-8; cela peut être important si vous avez de très gros fichiers SGF." #: src/gui-gtk/gtk-preferences.c:1093 msgid "Encoding" msgstr "Encodage" #: src/gui-gtk/gtk-preferences.c:1103 msgid "_Relative to stone size" msgstr "_Relatif à la taille des pierres" #: src/gui-gtk/gtk-preferences.c:1104 msgid "On _white stones:" msgstr "Sur les pierres _blanches :" #: src/gui-gtk/gtk-preferences.c:1105 msgid "On _black stones:" msgstr "Sur les pierres _noires :" #: src/gui-gtk/gtk-preferences.c:1106 msgid "On _empty intersections:" msgstr "Sur les intersections _vides :" #: src/gui-gtk/gtk-preferences.c:1120 msgid "_Relative to amazon size" msgstr "_Relatif à la taille des amazones" #: src/gui-gtk/gtk-preferences.c:1121 msgid "On _white amazons:" msgstr "Sur les amazones _blanches :" #: src/gui-gtk/gtk-preferences.c:1122 msgid "On _black amazons:" msgstr "Sur les amazones _noires :" #: src/gui-gtk/gtk-preferences.c:1123 src/gui-gtk/gtk-preferences.c:1182 msgid "On _empty fields:" msgstr "Sur les cases _vides :" #: src/gui-gtk/gtk-preferences.c:1142 msgid "Pick Checkerboard Pattern Color" msgstr "Sélectionnez la couleur du quadrillage de l'échiquier" #: src/gui-gtk/gtk-preferences.c:1151 msgid "Checkerboard _pattern color:" msgstr "_Couleur du quadrillage :" #: src/gui-gtk/gtk-preferences.c:1167 msgid "Checkerboard pattern _opacity:" msgstr "_Opacité du quadrillage :" #: src/gui-gtk/gtk-preferences.c:1179 msgid "_Relative to disk size" msgstr "_Relatif à la taille des disques" #: src/gui-gtk/gtk-preferences.c:1180 msgid "On _white disks:" msgstr "Sur les disques _blancs :" #: src/gui-gtk/gtk-preferences.c:1181 msgid "On _black disks:" msgstr "Sur les disques _noirs :" #: src/gui-gtk/gtk-preferences.c:1195 msgid "Use _texture:" msgstr "Utiliser une _texture :" #: src/gui-gtk/gtk-preferences.c:1196 msgid "Use _solid color:" msgstr "Utiliser une couleur _unie :" #: src/gui-gtk/gtk-preferences.c:1271 msgid "Choose a Background Texture..." msgstr "Choisissez une texture d'arrière-plan..." #: src/gui-gtk/gtk-preferences.c:1282 msgid "Pick Background Color" msgstr "Sélectionnez la couleur d'arrière-plan" #: src/gui-gtk/gtk-preferences.c:1296 msgid "Pick Color for Grid and Labels" msgstr "Sélectionnez la couleur de la grille et des étiquettes" #: src/gui-gtk/gtk-preferences.c:1306 msgid "_Grid and labels color:" msgstr "Couleur de la _grille et des étiquettes :" #: src/gui-gtk/gtk-preferences.c:1345 msgid "_Theme:" msgstr "_Thème :" #: src/gui-gtk/gtk-preferences.c:1354 msgid "Use theme _defaults" msgstr "Utiliser les valeurs par _défaut du thème" #: src/gui-gtk/gtk-preferences.c:1371 msgid "_Size:" msgstr "_Taille :" #: src/gui-gtk/gtk-preferences.c:1398 msgid "_Opacity:" msgstr "_Opacité :" #: src/gui-gtk/gtk-preferences.c:1413 msgid "Size & Opacity" msgstr "Taille & Opacité" #: src/gui-gtk/gtk-preferences.c:1429 msgid "Color" msgstr "Couleur" #: src/gui-gtk/gtk-preferences.c:1443 msgid "Pick Color for Markup" msgstr "Sélectionnez une couleur pour le marquage" #: src/gui-gtk/gtk-preferences.c:1482 msgid "Background" msgstr "Arrière-plan" #: src/gui-gtk/gtk-preferences.c:1484 msgid "Markup" msgstr "Marquage" #: src/gui-gtk/gtk-preferences.c:1630 msgid "Supported games:" msgstr "Jeux pris en charge :" #: src/gui-gtk/gtk-preferences.c:1637 msgid "This engine comes from site configuration." msgstr "Ce moteur provient de la configuration du site." #: src/gui-gtk/gtk-preferences.c:1860 msgid "" "You can use `%n' and `%v' strings in Screen name field. They will " "substituted with name and version of the engine correspondingly. By default, " "`%n %v' is used." msgstr "" "Vous pouvez utiliser les chaînes de caractères \"%n\" et \"%v\" dans le " "champ \"Nom à l'écran\". Elles seront remplacées par le nom et la version du " "moteur, respectivement. Par défaut \"%n %v\" est utilisé comme nom à l'écran." #: src/gui-gtk/gtk-preferences.c:1908 msgid "Modify GTP Engine Information" msgstr "Modifier les informations sur le moteur GTP" #: src/gui-gtk/gtk-preferences.c:1909 msgid "New GTP Engine" msgstr "Nouveau moteur GTP" #: src/gui-gtk/gtk-preferences.c:1955 msgid "Command _line:" msgstr "_Ligne de commande :" #: src/gui-gtk/gtk-preferences.c:1961 msgid "Choose GTP Engine..." msgstr "Sélection du moteur GTP..." #: src/gui-gtk/gtk-preferences.c:1972 msgid "Screen _name:" msgstr "Nom à l'_écran :" #: src/gui-gtk/gtk-preferences.c:2018 msgid "Querying engine's name, version and known commands..." msgstr "" "Interrogation du moteur pour le nom, la version et les commandes connues..." #: src/gui-gtk/gtk-preferences.c:2039 msgid "" "Please make sure you typed engine's filename correctly and that you have " "permission to execute it." msgstr "" "Assurez-vous d'avoir bien écrit le nom de fichier du moteur, et que vous " "êtes autorisé à l'exécuter." #: src/gui-gtk/gtk-preferences.c:2078 msgid "Waiting for the engine to quit..." msgstr "En attente que le moteur quitte" #: src/gui-gtk/gtk-preferences.c:2182 msgid "" "The engine might have crashed, quit prematurely or disconnected. Please " "verify command line, including options, and consult engine's documentation " "if needed." msgstr "" "Le moteur a peut-être planté, quitté prématurément ou s'est déconnecté. " "Veuillez vérifier la ligne de commande, y compris les options, et consultez " "la documentation du moteur si nécessaire." #: src/gui-gtk/gtk-preferences.c:2197 #, c-format msgid "Lost connection to GTP Engine (%s)" msgstr "Connexion au moteur GTP (%s) perdue" #: src/gui-gtk/gtk-preferences.c:3011 msgid "" "Perhaps engine's binary has been deleted or changed. You will probably need " "to alter engine's command line in the Preferences dialog." msgstr "" "Le binaire du moteur a peut-être été supprimé ou modifié. Vous devrez " "probablement modifier la ligne de commande du moteur dans la boîte de " "dialogue \"Préférences\"." #: src/gui-gtk/gtk-resume-game-dialog.c:92 msgid "Resume Game..." msgstr "Reprendre la partie..." #: src/gui-gtk/gtk-resume-game-dialog.c:115 #, c-format msgid "The game stored in file `%s' (%s) is not supported by Quarry" msgstr "" "La partie stockée dans le fichier \"%s\" (%s) n'est pas prise en charge par " "Quarry" #: src/gui-gtk/gtk-resume-game-dialog.c:138 msgid "" "This game appears to have been finished. Open it for viewing and/or editing " "instead?" msgstr "" "Cette partie semble terminée. Voulez-vous l'ouvrir pour affichage et " "édition ?" #: src/gui-gtk/gtk-resume-game-dialog.c:212 msgid "Resuming Game" msgstr "Reprise de la partie" #: src/gui-gtk/gtk-resume-game-dialog.c:214 msgid "_Resume" msgstr "_Reprendre" #: src/gui-gtk/gtk-resume-game-dialog.c:231 msgid "Game:" msgstr "Partie :" #: src/gui-gtk/gtk-resume-game-dialog.c:240 msgid "Board size:" msgstr "Taille du plateau :" #: src/gui-gtk/gtk-resume-game-dialog.c:258 msgid "Handicap:" msgstr "Handicap :" #: src/gui-gtk/gtk-resume-game-dialog.c:262 msgid "handicap|Not set" msgstr "handicap|Non spécifié" #: src/gui-gtk/gtk-resume-game-dialog.c:268 msgid "Komi:" msgstr "Komi :" #: src/gui-gtk/gtk-resume-game-dialog.c:271 msgid "komi|Not set" msgstr "komi|Non spécifié" #: src/gui-gtk/gtk-resume-game-dialog.c:294 msgid "Filename:" msgstr "Nom de fichier :" #: src/gui-gtk/gtk-resume-game-dialog.c:307 msgid "Compu_ter" msgstr "_Ordinateur" #: src/gui-gtk/quarry-find-dialog.c:104 msgid "Whole game _tree" msgstr "_Tout l'arbre de la partie" #: src/gui-gtk/quarry-find-dialog.c:104 msgid "Current no_de only" msgstr "Uniquement le _noeud actif" #: src/gui-gtk/quarry-find-dialog.c:107 msgid "C_omments & node names" msgstr "_Commentaires & noms des noeuds" #: src/gui-gtk/quarry-find-dialog.c:108 msgid "Comm_ents only" msgstr "Co_mmentaires seulement" #: src/gui-gtk/quarry-find-dialog.c:108 msgid "Node na_mes only" msgstr "_Noms des noeuds seulement" #: src/gui-gtk/quarry-find-dialog.c:154 msgid "Search _for:" msgstr "_Rechercher :" #: src/gui-gtk/quarry-find-dialog.c:161 msgid "Case _sensitive" msgstr "_Sensible à la casse" #: src/gui-gtk/quarry-find-dialog.c:169 msgid "Whole _words only" msgstr "Mots _entiers seulement" #: src/gui-gtk/quarry-find-dialog.c:177 msgid "Wrap _around" msgstr "Recommencer au _début" #: src/gui-gtk/quarry-find-dialog.c:191 msgid "A_uto-close this dialog" msgstr "Fermer ce dialogue _automatiquement" #: src/gui-gtk/quarry-find-dialog.c:202 msgid "Options" msgstr "Options" #: src/gui-gtk/quarry-find-dialog.c:251 msgid "Search Scope" msgstr "Étendue de la recherche" #: src/gui-gtk/quarry-move-number-dialog.c:66 #: src/gui-gtk/quarry-move-number-dialog.c:148 msgid "Use se_quential move number" msgstr "Utiliser des numéros de coups sé_quentiels" #: src/gui-gtk/quarry-move-number-dialog.c:66 msgid "_Set specific move number:" msgstr "_Spécifier un numéro de coup :" #: src/gui-gtk/quarry-save-confirmation-dialog.c:89 msgid "Close _without Saving" msgstr "Fermer _sans enregistrer" #: src/gui-gtk/quarry-save-confirmation-dialog.c:173 #, c-format msgid "" "If you don't save, changes from the last %d second will be lost permanently." msgid_plural "" "If you don't save, changes from the last %d seconds will be lost permanently." msgstr[0] "" "Si vous n'enregistrez pas, les modifications depuis la dernière %d seconde " "seront définitivement perdues." msgstr[1] "" "Si vous n'enregistrez pas, les modifications depuis les %d dernières " "secondes seront définitivement perdues." #: src/gui-gtk/quarry-save-confirmation-dialog.c:181 msgid "If you don't save, changes from the last minute will be discarded." msgstr "" "Si vous n'enregistrez pas, les modifications depuis la dernière minute " "seront perdues." #. TRANSLATORS: Cannot be one minute one second, actually. #: src/gui-gtk/quarry-save-confirmation-dialog.c:187 #, c-format msgid "" "If you don't save, changes from the last minute and %d second will be lost " "permanently." msgid_plural "" "If you don't save, changes from the last minute and %d seconds will be lost " "permanently." msgstr[0] "" "Si vous n'enregistrez pas, les modifications depuis la dernière minute et %d " "seconde seront définitivement perdues." msgstr[1] "" "Si vous n'enregistrez pas, les modifications depuis la dernière minute et %d " "secondes seront définitivement perdues." #: src/gui-gtk/quarry-save-confirmation-dialog.c:198 #, c-format msgid "" "If you don't save, changes from the last %d minute will be lost permanently." msgid_plural "" "If you don't save, changes from the last %d minutes will be lost permanently." msgstr[0] "" "Si vous n'enregistrez pas, les modifications depuis la dernière %d minute " "seront définitivement perdues." msgstr[1] "" "Si vous n'enregistrez pas, les modifications depuis les %d dernières minutes " "seront définitivement perdues." #. TRANSLATORS: Cannot be one hour one minute, actually. #: src/gui-gtk/quarry-save-confirmation-dialog.c:212 #, c-format msgid "" "If you don't save, changes from the last hour and %d minute will be lost " "permanently." msgid_plural "" "If you don't save, changes from the last hour and %d minutes will be lost " "permanently." msgstr[0] "" "Si vous n'enregistrez pas, les modifications depuis la dernière heure et %d " "minute seront définitivement perdues." msgstr[1] "" "Si vous n'enregistrez pas, les modifications depuis la dernière heure et %d " "minutes seront définitivement perdues." #: src/gui-gtk/quarry-save-confirmation-dialog.c:224 #, c-format msgid "" "If you don't save, changes from the last %d hour will be lost permanently." msgid_plural "" "If you don't save, changes from the last %d hours will be lost permanently." msgstr[0] "" "Si vous n'enregistrez pas, les modifications depuis la dernière %d heure " "seront définitivement perdues." msgstr[1] "" "Si vous n'enregistrez pas, les modifications depuis les %d dernières heures " "seront définitivement perdues." #: src/gui-gtk/quarry-stock.c:56 msgid "_New Game" msgstr "_Nouvelle partie" #: src/gui-gtk/quarry-stock.c:57 msgid "_Open Game Record" msgstr "_Ouvrir une partie enregistrée" #: src/gui-gtk/quarry-stock.c:59 msgid "_Browse..." msgstr "_Parcourir..." #: src/gui-gtk/quarry-stock.c:60 msgid "Crea_te" msgstr "_Créer" #: src/gui-gtk/quarry-stock.c:61 msgid "_Done" msgstr "_Terminé" #: src/gui-gtk/quarry-stock.c:62 msgid "_Go to Node" msgstr "_Aller au noeud" #: src/gui-gtk/quarry-stock.c:63 msgid "_Modify" msgstr "_Modifier" #: src/gui-gtk/quarry-stock.c:64 msgid "Move _Up" msgstr "_Monter" #: src/gui-gtk/quarry-stock.c:65 msgid "Move _Down" msgstr "_Descendre" #: src/gui-gtk/quarry-stock.c:66 msgid "find|_Next" msgstr "rechercher|_Suivant" #: src/gui-gtk/quarry-stock.c:67 msgid "_Overwrite" msgstr "_Écraser" #: src/gui-gtk/quarry-stock.c:68 msgid "_Play" msgstr "_Jouer" #: src/gui-gtk/quarry-stock.c:69 msgid "find|_Previous" msgstr "rechercher|_Précédent" #. TRANSLATORS: This is only used for non-integral scores. You #. should also add translation of `points' if it is required by #. your language. #: src/board/board.c:897 #, c-format msgid "Black wins by %.*f" msgstr "Les noirs gagnent de %.*f points" #. TRANSLATORS: This is only used for non-integral scores. You #. should also add translation of `points' if it is required by #. your language. #: src/board/board.c:904 #, c-format msgid "White wins by %.*f" msgstr "Les blancs gagnent de %.*f points" #: src/board/board.c:915 #, c-format msgid "Black wins by %d" msgid_plural "Black wins by %d" msgstr[0] "Les noirs gagnent avec %d" msgstr[1] "Les noirs gagnent avec %d" #: src/board/board.c:923 #, c-format msgid "White wins by %d" msgid_plural "White wins by %d" msgstr[0] "Les blancs gagnent avec %d" msgstr[1] "Les blancs gagnent avec %d" #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:29 msgid "Go" msgstr "Go" #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:43 msgid "Reversi" msgstr "Reversi" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:58 msgid "chess" msgstr "échecs" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:73 msgid "Gomoku" msgstr "Gomoku" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:88 msgid "Nine Men's Morris" msgstr "Moulin" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:103 msgid "Backgammon" msgstr "Backgammon" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:118 msgid "Chinese chess" msgstr "Xiangqi" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:133 msgid "Shogi" msgstr "ShÅgi" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:148 msgid "Lines of Action" msgstr "Lignes d'action" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:163 msgid "Ataxx" msgstr "Ataxx" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:178 msgid "Hex" msgstr "Hex" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:193 msgid "Jungle" msgstr "Jungle" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:208 msgid "Neutron" msgstr "Neutron" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:223 msgid "Philosopher's Football" msgstr "Phutball" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:238 msgid "Quadrature" msgstr "Quadrature" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:253 msgid "Trax" msgstr "Trax" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:268 msgid "Tantrix" msgstr "Tantrix" #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:282 msgid "Amazons" msgstr "Amazones" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:297 msgid "Octi" msgstr "Octi" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:312 msgid "Gess" msgstr "Gess" #: src/board/go.c:1323 #, c-format msgid "White: %d territory" msgid_plural "White: %d territory" msgstr[0] "Blancs : %d territoire" msgstr[1] "Blancs : %d territoires" #: src/board/go.c:1328 src/board/go.c:1365 #, c-format msgid " + %d capture" msgid_plural " + %d captures" msgstr[0] " + %d capture" msgstr[1] " + %d captures" #. TRANSLATORS: e.g. `` + 6.5 komi = #. 87.5''. This is used only with #. fractional komi. #: src/board/go.c:1337 #, c-format msgid " %s %.*f komi = %.*f\n" msgstr " %s %.*f komi = %.*f\n" #. TRANSLATORS: e.g. `` + 6 komi = 87''. #: src/board/go.c:1351 #, c-format msgid " %s %d komi = %d\n" msgid_plural " %s %d komi = %d\n" msgstr[0] "%s %d komi = %d\n" msgstr[1] "%s %d komi = %d\n" #: src/board/go.c:1360 #, c-format msgid "Black: %d territory" msgid_plural "Black: %d territory" msgstr[0] "Noirs : %d territoire" msgstr[1] "Noirs : %d territoires" #: src/board/go.c:1374 msgid "The game is draw" msgstr "Match nul" quarry-0.2.0/po/pl.po0000644000175000017500000016532510530113052013071 0ustar bartbart# Polish translations for Quarry package. # Copyright (C) 2005 Paul Pogonyshev # This file is distributed under the same license as the Quarry package. # Robert Stefaniuk , 2005, 2006. # msgid "" msgstr "" "Project-Id-Version: Quarry 0.1.16\n" "Report-Msgid-Bugs-To: quarry-dev@gna.org\n" "POT-Creation-Date: 2006-11-07 18:33+0200\n" "PO-Revision-Date: 2006-11-07 18:42+0200\n" "Last-Translator: Robert Stefaniuk \n" "Language-Team: Polish \n" "MIME-Version: 1.1\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " "|| n%100>=20) ? 1 : 2);\n" #: src/gui-gtk/gtk-add-or-edit-label-dialog.c:73 msgid "" "Although board labels are not limited in length, it is better to use only " "one or two characters long labels. Longer labels will not be visible " "immediately or at all in most clients." msgstr "" "Chociaż nazwy etykiet mogÄ… mieć dowolnÄ… dÅ‚ugość, bezpieczniejsze sÄ… nazwy " "maksymalnie dwuznakowe. DÅ‚uższe nazwy mogÄ… być z poczÄ…tku niewidoczne albo " "niewidoczne wcale dla wiÄ™kszoÅ›ci klientów." #: src/gui-gtk/gtk-add-or-edit-label-dialog.c:87 msgid "Label _text:" msgstr "_Tekst etykiety:" #: src/gui-gtk/gtk-color-button.c:581 msgid "Pick a Color" msgstr "Wybór koloru" #: src/gui-gtk/gtk-control-center.c:64 msgid "Quarry Control Center" msgstr "Centrum sterowania Quarry" #: src/gui-gtk/gtk-control-center.c:80 msgid "Ne_w Game Record" msgstr "_Nowy zapis gry" #: src/gui-gtk/gtk-control-center.c:96 msgid "_Resume Game" msgstr "_DokoÅ„cz grÄ™" #: src/gui-gtk/gtk-file-dialog.c:281 msgid "" "Note that all information in the existing file will be lost permanently if " "you choose to overwrite it." msgstr "" "Pamietaj, że wszystkie dane z istniejÄ…cego pliku zostanÄ… bezpowrotnie " "utracone, jeÅ›li go nadpiszesz." #: src/gui-gtk/gtk-file-dialog.c:284 #, c-format msgid "" "File named `%s' already exists. Do you want to overwrite it with the one you " "are saving?" msgstr "" "Plik o nazwie „%s†już istnieje. Czy chcesz go zastÄ…pić obecnie zapisywanym " "plikiem?" #: src/gui-gtk/gtk-game-info-dialog.c:231 #: src/gui-gtk/gtk-resume-game-dialog.c:325 msgid "N_ame:" msgstr "G_racz:" #: src/gui-gtk/gtk-game-info-dialog.c:231 #: src/gui-gtk/gtk-resume-game-dialog.c:324 msgid "_Name:" msgstr "_Gracz:" #: src/gui-gtk/gtk-game-info-dialog.c:238 msgid "Team:" msgstr "Drużyna:" #: src/gui-gtk/gtk-game-info-dialog.c:244 msgid "Rank:" msgstr "Ranking:" #: src/gui-gtk/gtk-game-info-dialog.c:256 #: src/gui-gtk/gtk-new-game-dialog.c:226 #: src/gui-gtk/gtk-resume-game-dialog.c:364 msgid "Black Player" msgstr "Czarne" #: src/gui-gtk/gtk-game-info-dialog.c:256 #: src/gui-gtk/gtk-new-game-dialog.c:226 #: src/gui-gtk/gtk-resume-game-dialog.c:364 msgid "White Player" msgstr "BiaÅ‚e" #: src/gui-gtk/gtk-game-info-dialog.c:270 msgid "_Game name:" msgstr "_Nazwa gry:" #: src/gui-gtk/gtk-game-info-dialog.c:273 msgid "_Place:" msgstr "Miej_sce gry:" #: src/gui-gtk/gtk-game-info-dialog.c:277 msgid "Da_te:" msgstr "_Data:" #: src/gui-gtk/gtk-game-info-dialog.c:280 msgid "_Event:" msgstr "_OkolicznoÅ›ci:" #: src/gui-gtk/gtk-game-info-dialog.c:284 msgid "R_ound:" msgstr "R_unda:" #: src/gui-gtk/gtk-game-info-dialog.c:295 #: src/gui-gtk/gtk-game-info-dialog.c:535 #: src/gui-gtk/gtk-game-info-dialog.c:541 msgid "Game Information" msgstr "Informacje o grze" #: src/gui-gtk/gtk-game-info-dialog.c:298 msgid "Rule _set:" msgstr "ReguÅ‚_y:" #: src/gui-gtk/gtk-game-info-dialog.c:324 #: src/gui-gtk/gtk-new-game-record-dialog.c:187 msgid "Han_dicap:" msgstr "_Handikap:" #: src/gui-gtk/gtk-game-info-dialog.c:347 #: src/gui-gtk/gtk-new-game-dialog.c:574 #: src/gui-gtk/gtk-new-game-record-dialog.c:231 msgid "_Komi:" msgstr "_Komi:" #: src/gui-gtk/gtk-game-info-dialog.c:374 #: src/gui-gtk/gtk-new-game-dialog.c:444 msgid "_Main time:" msgstr "_Czas główny:" #: src/gui-gtk/gtk-game-info-dialog.c:386 msgid "O_vertime:" msgstr "C_zas dodatkowy:" #: src/gui-gtk/gtk-game-info-dialog.c:397 #: src/gui-gtk/gtk-new-game-dialog.c:602 msgid "Game Rules" msgstr "ReguÅ‚y gry" #: src/gui-gtk/gtk-game-info-dialog.c:412 msgid "General" msgstr "Ogólne informacje" #: src/gui-gtk/gtk-game-info-dialog.c:415 msgid "Game re_sult:" msgstr "_Wynik:" #: src/gui-gtk/gtk-game-info-dialog.c:419 msgid "_Opening played:" msgstr "Zagrane _otwarcie:" #: src/gui-gtk/gtk-game-info-dialog.c:449 msgid "Comment / _description:" msgstr "_Komentarz/opis:" #: src/gui-gtk/gtk-game-info-dialog.c:463 msgid "Description & Result" msgstr "Opis i wynik" #: src/gui-gtk/gtk-game-info-dialog.c:466 msgid "Co_pyright string:" msgstr "Wiersz praw _autorskich:" #: src/gui-gtk/gtk-game-info-dialog.c:470 msgid "_Annotator:" msgstr "_ZapisujÄ…cy:" #: src/gui-gtk/gtk-game-info-dialog.c:474 msgid "_Source:" msgstr "Ź_ródÅ‚o:" #: src/gui-gtk/gtk-game-info-dialog.c:478 msgid "_Entered by:" msgstr "_Twórca pliku:" #: src/gui-gtk/gtk-game-info-dialog.c:488 msgid "Copyright & Credits" msgstr "Informacje o pliku i prawach autorskich" #: src/gui-gtk/gtk-game-info-dialog.c:502 msgid "Game Record" msgstr "Autorzy i uprawnienia" #: src/gui-gtk/gtk-games.c:39 msgid "_Go" msgstr "_Go" #: src/gui-gtk/gtk-games.c:40 msgid "_Amazons" msgstr "Ama_zonki" #: src/gui-gtk/gtk-games.c:41 msgid "_Reversi" msgstr "_Reversi" #: src/gui-gtk/gtk-games.c:45 msgid "Go Rules" msgstr "ReguÅ‚y go" #: src/gui-gtk/gtk-games.c:46 msgid "Amazons Rules" msgstr "ReguÅ‚y amazonek" #: src/gui-gtk/gtk-games.c:47 msgid "Reversi Rules" msgstr "ReguÅ‚y reversi" #: src/gui-gtk/gtk-games.c:180 msgid "Board _size:" msgstr "Rozmiar _planszy:" #: src/gui-gtk/gtk-goban-window.c:460 msgid "Open" msgstr "Otwórz" #: src/gui-gtk/gtk-goban-window.c:460 msgid "Open a game record" msgstr "Otwiera zapisanÄ… grÄ™" #: src/gui-gtk/gtk-goban-window.c:465 msgid "Save" msgstr "Zapisz" #: src/gui-gtk/gtk-goban-window.c:465 msgid "Save the current file" msgstr "Zapisuje bieżący plik" #: src/gui-gtk/gtk-goban-window.c:470 src/gui-gtk/gtk-goban-window.c:2025 msgid "Find" msgstr "Znajdź" #: src/gui-gtk/gtk-goban-window.c:470 msgid "Search for a string in comments" msgstr "Szuka podanego tekstu w komentarzach" #: src/gui-gtk/gtk-goban-window.c:475 msgid "Info" msgstr "Informacje" #: src/gui-gtk/gtk-goban-window.c:475 msgid "View and edit game information" msgstr "Otwiera okno podglÄ…du i edycji informacji o grze" #: src/gui-gtk/gtk-goban-window.c:481 msgid "Undo" msgstr "Cofnij" #: src/gui-gtk/gtk-goban-window.c:481 msgid "Undo the last action" msgstr "Cofa ostatniÄ… operacjÄ™" #: src/gui-gtk/gtk-goban-window.c:486 msgid "Redo" msgstr "Ponów" #: src/gui-gtk/gtk-goban-window.c:486 msgid "Redo the last undone action" msgstr "Wykonuje z powrotem ostatniÄ… cofniÄ™tÄ… operacjÄ™" #: src/gui-gtk/gtk-goban-window.c:491 msgid "Delete" msgstr "UsuÅ„" #: src/gui-gtk/gtk-goban-window.c:491 msgid "Delete the current node" msgstr "Usuwa bieżący wÄ™zeÅ‚" #: src/gui-gtk/gtk-goban-window.c:497 msgid "Root" msgstr "PoczÄ…tek" #: src/gui-gtk/gtk-goban-window.c:497 msgid "Go to the root node" msgstr "Przechodzi do poczÄ…tku drzewa ruchów" #: src/gui-gtk/gtk-goban-window.c:502 msgid "Back" msgstr "Wstecz" #: src/gui-gtk/gtk-goban-window.c:502 msgid "Go to the previous node" msgstr "Przechodzi do poprzedniego wÄ™zÅ‚a" #: src/gui-gtk/gtk-goban-window.c:507 msgid "Forward" msgstr "Dalej" #: src/gui-gtk/gtk-goban-window.c:507 msgid "Go to the next node" msgstr "Przechodzi do nastÄ™pnego wÄ™zÅ‚a" #: src/gui-gtk/gtk-goban-window.c:512 msgid "End" msgstr "Koniec" #: src/gui-gtk/gtk-goban-window.c:512 msgid "Go to the current variation's last node" msgstr "Przechodzi do koÅ„ca bieżącej sekwencji ruchów" #: src/gui-gtk/gtk-goban-window.c:518 msgid "Previous" msgstr "Poprzedni" #: src/gui-gtk/gtk-goban-window.c:518 msgid "Switch to the previous variation" msgstr "Przechodzi do poprzedniego wariantu" #: src/gui-gtk/gtk-goban-window.c:524 msgid "Next" msgstr "NastÄ™pny" #: src/gui-gtk/gtk-goban-window.c:524 msgid "Switch to the next variation" msgstr "Przechodzi do nastÄ™pnego wariantu" #: src/gui-gtk/gtk-goban-window.c:629 msgid "/_File" msgstr "/_Plik" #: src/gui-gtk/gtk-goban-window.c:630 msgid "/File/_New Game..." msgstr "/Plik/Nowa _gra..." #: src/gui-gtk/gtk-goban-window.c:633 msgid "/File/Ne_w Game Record..." msgstr "/Plik/_Nowy zapis gry..." #: src/gui-gtk/gtk-goban-window.c:636 src/gui-gtk/gtk-goban-window.c:653 #: src/gui-gtk/gtk-goban-window.c:661 msgid "/File/" msgstr "/Plik/" #: src/gui-gtk/gtk-goban-window.c:638 msgid "/File/_Open..." msgstr "/Plik/_Otwórz..." #: src/gui-gtk/gtk-goban-window.c:641 msgid "/File/_Resume Game..." msgstr "/Plik/_DokoÅ„cz grÄ™..." #: src/gui-gtk/gtk-goban-window.c:645 msgid "/File/_Export..." msgstr "/Plik/_Eksport..." #: src/gui-gtk/gtk-goban-window.c:646 msgid "/File/Export.../_ASCII Diagram" msgstr "/Plik/Eksport.../Diagram _ASCII" #: src/gui-gtk/gtk-goban-window.c:649 msgid "/File/Export.../_Sensei's Library Diagram" msgstr "/Plik/Eksport.../Diagram dla _Sensei's Library" #: src/gui-gtk/gtk-goban-window.c:655 msgid "/File/_Save" msgstr "/Plik/_Zapisz" #: src/gui-gtk/gtk-goban-window.c:658 msgid "/File/Save _As..." msgstr "/Plik/Z_apisz jako..." #: src/gui-gtk/gtk-goban-window.c:663 msgid "/File/_Close" msgstr "/Plik/Za_mknij" #: src/gui-gtk/gtk-goban-window.c:666 msgid "/File/_Quit" msgstr "/Plik/Za_koÅ„cz" #: src/gui-gtk/gtk-goban-window.c:671 msgid "/_Edit" msgstr "/_Edycja" #: src/gui-gtk/gtk-goban-window.c:672 msgid "/Edit/_Undo" msgstr "/Edycja/_Cofnij" #: src/gui-gtk/gtk-goban-window.c:675 msgid "/Edit/_Redo" msgstr "/Edycja/P_onów" #: src/gui-gtk/gtk-goban-window.c:678 src/gui-gtk/gtk-goban-window.c:695 #: src/gui-gtk/gtk-goban-window.c:739 src/gui-gtk/gtk-goban-window.c:747 #: src/gui-gtk/gtk-goban-window.c:767 src/gui-gtk/gtk-goban-window.c:778 #: src/gui-gtk/gtk-goban-window.c:783 msgid "/Edit/" msgstr "/Edycja/" #: src/gui-gtk/gtk-goban-window.c:680 msgid "/Edit/Cu_t" msgstr "/Edycja/_Wytnij" #: src/gui-gtk/gtk-goban-window.c:683 msgid "/Edit/_Copy" msgstr "/Edycja/_Kopiuj" #: src/gui-gtk/gtk-goban-window.c:686 msgid "/Edit/_Paste" msgstr "/Edycja/Wkle_j" #: src/gui-gtk/gtk-goban-window.c:689 msgid "/Edit/_Delete Node" msgstr "/Edycja/_UsuÅ„ wÄ™zeÅ‚" #: src/gui-gtk/gtk-goban-window.c:692 msgid "/Edit/Delete Node's C_hildren" msgstr "/Edycja/U_suÅ„ dalsze wÄ™zÅ‚y" #: src/gui-gtk/gtk-goban-window.c:698 msgid "/Edit/T_ools" msgstr "/Edycja/_NarzÄ™dzia" #: src/gui-gtk/gtk-goban-window.c:699 msgid "/Edit/Tools/_Move Tool" msgstr "/Edycja/NarzÄ™dzia/Tryb _gry" #: src/gui-gtk/gtk-goban-window.c:702 msgid "/Edit/Tools/_Setup Tool" msgstr "/Edycja/NarzÄ™dzia/Tryb _edycji" #: src/gui-gtk/gtk-goban-window.c:705 src/gui-gtk/gtk-goban-window.c:722 #: src/gui-gtk/gtk-goban-window.c:730 msgid "/Edit/Tools/" msgstr "/Edycja/NarzÄ™dzia/" #: src/gui-gtk/gtk-goban-window.c:707 msgid "/Edit/Tools/C_ross Markup" msgstr "/Edycja/NarzÄ™dzia/Znaczniki: _krzyżyk" #: src/gui-gtk/gtk-goban-window.c:710 msgid "/Edit/Tools/_Circle Markup" msgstr "/Edycja/NarzÄ™dzia/Znaczniki: _okrÄ…g" #: src/gui-gtk/gtk-goban-window.c:713 msgid "/Edit/Tools/S_quare Markup" msgstr "/Edycja/NarzÄ™dzia/Znaczniki: kwa_drat" #: src/gui-gtk/gtk-goban-window.c:716 msgid "/Edit/Tools/_Triangle Markup" msgstr "/Edycja/NarzÄ™dzia/Znaczniki: _trójkÄ…t" #: src/gui-gtk/gtk-goban-window.c:719 msgid "/Edit/Tools/S_elected Markup" msgstr "/Edycja/NarzÄ™dzia/_Znaczniki: wÅ‚asny" #: src/gui-gtk/gtk-goban-window.c:724 msgid "/Edit/Tools/_Label Tool" msgstr "/Edycja/NarzÄ™dzia/Etykiet_y" #: src/gui-gtk/gtk-goban-window.c:727 msgid "/Edit/Tools/_Number Tool" msgstr "/Edycja/NarzÄ™dzia/_Numerowanie pól" #: src/gui-gtk/gtk-goban-window.c:732 msgid "/Edit/Tools/Scori_ng Tool" msgstr "/Edycja/NarzÄ™dzia/Ustalanie _wyniku" #: src/gui-gtk/gtk-goban-window.c:736 msgid "/Edit/_Add Empty Node" msgstr "/Edycja/_Dodaj pusty wÄ™zeÅ‚" #: src/gui-gtk/gtk-goban-window.c:741 msgid "/Edit/Move _Branch Up" msgstr "/Edycja/W_yższa gałąź" #: src/gui-gtk/gtk-goban-window.c:744 msgid "/Edit/Move Branch Do_wn" msgstr "/Edycja/N_iższa gałąź" #: src/gui-gtk/gtk-goban-window.c:749 msgid "/Edit/Edit Node _Name" msgstr "/Edycja/_Modyfikuj nazwÄ™ wÄ™zÅ‚a" #: src/gui-gtk/gtk-goban-window.c:752 msgid "/Edit/Set _Move Number" msgstr "/Edycja/Wstaw numer _ruchu" #: src/gui-gtk/gtk-goban-window.c:756 msgid "/Edit/P_layer to Move" msgstr "/Edycja/_Gracz wykonujÄ…cy ruch" #: src/gui-gtk/gtk-goban-window.c:757 msgid "/Edit/Player to Move/_White" msgstr "/Edycja/Gracz wykonujÄ…cy ruch/_BiaÅ‚y" #: src/gui-gtk/gtk-goban-window.c:760 msgid "/Edit/Player to Move/_Black" msgstr "/Edycja/Gracz wykonujÄ…cy ruch/_Czarny" #: src/gui-gtk/gtk-goban-window.c:763 msgid "/Edit/Player to Move/By Game _Rules" msgstr "/Edycja/Gracz wykonujÄ…cy ruch/_Zgodnie z reguÅ‚ami" #: src/gui-gtk/gtk-goban-window.c:769 msgid "/Edit/_Find" msgstr "/Edycja/_Znajdź" #: src/gui-gtk/gtk-goban-window.c:772 msgid "/Edit/Find Ne_xt" msgstr "/Edycja/Znajdź _nastÄ™pne" #: src/gui-gtk/gtk-goban-window.c:775 msgid "/Edit/Find Pre_vious" msgstr "/Edycja/Znajdź _poprzednie" #: src/gui-gtk/gtk-goban-window.c:780 msgid "/Edit/Game _Information" msgstr "/Edycja/In_formacja o grze" #: src/gui-gtk/gtk-goban-window.c:785 msgid "/Edit/Pr_eferences" msgstr "/Edycja/Pr_eferencje" #: src/gui-gtk/gtk-goban-window.c:790 msgid "/_View" msgstr "/_Widok" #: src/gui-gtk/gtk-goban-window.c:791 msgid "/View/_Main Toolbar" msgstr "/Widok/Pasek _główny" #: src/gui-gtk/gtk-goban-window.c:794 msgid "/View/_Editing Toolbar" msgstr "/Widok/Pasek _edycji" #: src/gui-gtk/gtk-goban-window.c:797 msgid "/View/_Navigation Toolbar" msgstr "/Widok/Pasek _poÅ‚ożenia" #: src/gui-gtk/gtk-goban-window.c:800 src/gui-gtk/gtk-goban-window.c:805 #: src/gui-gtk/gtk-goban-window.c:813 msgid "/View/" msgstr "/Widok/" #: src/gui-gtk/gtk-goban-window.c:802 msgid "/View/_Game Action Buttons" msgstr "/Widok/P_rzyciski gry" #: src/gui-gtk/gtk-goban-window.c:807 msgid "/View/Game _Tree" msgstr "/Widok/_Drzewo ruchów" #: src/gui-gtk/gtk-goban-window.c:810 msgid "/View/_Recenter on Current Node" msgstr "/Widok/_WyÅ›rodkuj na bieżącym węźle" #: src/gui-gtk/gtk-goban-window.c:815 msgid "/View/_Control Center" msgstr "/Widok/_Centrum sterowania" #: src/gui-gtk/gtk-goban-window.c:820 msgid "/_Play" msgstr "/_Gra" #: src/gui-gtk/gtk-goban-window.c:821 msgid "/Play/_Pass" msgstr "/Gra/_Pas" #: src/gui-gtk/gtk-goban-window.c:824 src/gui-gtk/gtk-goban-window.c:829 msgid "/Play/" msgstr "/Gra/" #: src/gui-gtk/gtk-goban-window.c:826 msgid "/Play/_Resign" msgstr "/Gra/Po_ddaj" #: src/gui-gtk/gtk-goban-window.c:831 msgid "/Play/_Adjourn Game" msgstr "/Gra/_Odłóż grÄ™" #: src/gui-gtk/gtk-goban-window.c:836 msgid "/_Go" msgstr "/_Idź" #: src/gui-gtk/gtk-goban-window.c:837 msgid "/Go/_Previous Node" msgstr "/Idź/_Poprzedni wÄ™zeÅ‚" #: src/gui-gtk/gtk-goban-window.c:840 msgid "/Go/_Next Node" msgstr "/Idź/_NastÄ™pny wÄ™zeÅ‚" #: src/gui-gtk/gtk-goban-window.c:843 msgid "/Go/Ten Nodes _Backward" msgstr "/Idź/DziesiÄ™_c wÄ™złów wstecz" #: src/gui-gtk/gtk-goban-window.c:846 msgid "/Go/Ten Nodes _Forward" msgstr "/Idź/_Dziesięć wÄ™złów w przód" #: src/gui-gtk/gtk-goban-window.c:849 src/gui-gtk/gtk-goban-window.c:857 #: src/gui-gtk/gtk-goban-window.c:867 msgid "/Go/" msgstr "/Idź/" #: src/gui-gtk/gtk-goban-window.c:851 msgid "/Go/_Root Node" msgstr "/Idź/P_oczÄ…tek" #: src/gui-gtk/gtk-goban-window.c:854 msgid "/Go/Variation _Last Node" msgstr "/Idź/_Koniec sekwencji" #: src/gui-gtk/gtk-goban-window.c:859 msgid "/Go/Pre_vious Variation" msgstr "/Idź/Poprzedni _wariant" #: src/gui-gtk/gtk-goban-window.c:862 msgid "/Go/Ne_xt Variation" msgstr "/Idź/NastÄ™pny warian_t" #: src/gui-gtk/gtk-goban-window.c:868 msgid "/Go/_Go to Named Node..." msgstr "/Idź/Idź do na_zwanego wÄ™zÅ‚a..." #: src/gui-gtk/gtk-goban-window.c:874 msgid "/_Help" msgstr "/Pomo_c" #: src/gui-gtk/gtk-goban-window.c:875 msgid "/Help/_Contents" msgstr "/Pomoc/_Zawartość" #: src/gui-gtk/gtk-goban-window.c:878 msgid "/Help/_About" msgstr "/Pomoc/_o programie" #: src/gui-gtk/gtk-goban-window.c:884 msgid "/Move Tool" msgstr "/Tryb gry" #: src/gui-gtk/gtk-goban-window.c:885 msgid "/Setup Tool" msgstr "/Tryb edycji" #: src/gui-gtk/gtk-goban-window.c:888 msgid "/Cross Markup" msgstr "/Znaczniki: krzyżyk" #: src/gui-gtk/gtk-goban-window.c:889 msgid "/Circle Markup" msgstr "/Znaczniki: okrÄ…g" #: src/gui-gtk/gtk-goban-window.c:890 msgid "/Square Markup" msgstr "/Znaczniki: kwadrat" #: src/gui-gtk/gtk-goban-window.c:891 msgid "/Triangle Markup" msgstr "/Znaczniki: trójkÄ…t" #: src/gui-gtk/gtk-goban-window.c:892 msgid "/Selected Markup" msgstr "/Znaczniki: wÅ‚asny" #: src/gui-gtk/gtk-goban-window.c:895 msgid "/Label Tool" msgstr "/Etykiety" #: src/gui-gtk/gtk-goban-window.c:896 msgid "/Number Tool" msgstr "/Numerowanie pól" #: src/gui-gtk/gtk-goban-window.c:899 msgid "/Scoring Tool" msgstr "/Ustalanie wyniku" #: src/gui-gtk/gtk-goban-window.c:964 msgid "Black" msgstr "Czarne" #: src/gui-gtk/gtk-goban-window.c:964 msgid "White" msgstr "BiaÅ‚e" #: src/gui-gtk/gtk-goban-window.c:992 msgid "Pass" msgstr "Pas" #: src/gui-gtk/gtk-goban-window.c:998 msgid "Resign" msgstr "Poddaj" #: src/gui-gtk/gtk-goban-window.c:1438 #, c-format msgid "Save changes to game record `%s' before closing?" msgstr "Zapisać zmiany w pliku „%s†przed jego zamkniÄ™ciem?" #: src/gui-gtk/gtk-goban-window.c:1447 msgid "Save changes to the untitled game record before closing?" msgstr "Zapisać zmiany w utworzonym pliku przed jego zamkniÄ™ciem?" #. TRANSLATORS: Width of this string in default font is used to #. determine the minimal width of the right board window side. #: src/gui-gtk/gtk-goban-window.c:1522 msgid "A good width for the right side to have." msgstr "WÅ‚aÅ›ciwa szerokość panelu po prawej stronie." #. TRANSLATORS: It can never be 1 stone, always at least 2. #: src/gui-gtk/gtk-goban-window.c:1582 #, c-format msgid "" "Please set up %d (or less)\n" "stone of free handicap" msgid_plural "" "Please set up %d (or less)\n" "stones of free handicap" msgstr[0] "%d" msgstr[1] "" "Ustaw gdziekolwiek %d (lub mniej)\n" "kamienie jako handikap" msgstr[2] "" "Ustaw gdziekolwiek %d (lub mniej)\n" "kamieni jako handikap" #: src/gui-gtk/gtk-goban-window.c:1774 msgid "Adjourn & Save As..." msgstr "Odłóż grÄ™ i zapisz jako..." #: src/gui-gtk/gtk-goban-window.c:1774 msgid "Save As..." msgstr "Zapisz jako..." #: src/gui-gtk/gtk-goban-window.c:1923 #, fuzzy, c-format msgid "Error saving to file `%s'" msgstr "Błąd przy próbie odczytu pliku „%sâ€" #: src/gui-gtk/gtk-goban-window.c:1937 msgid "" "You can later resume the game by pressing the `Resume Game' button in Quarry " "Control Center, or selecting `Resume Game' item from the `File' menu." msgstr "" "Można później dokoÅ„czyć tÄ™ grÄ™ wybierajÄ…c opcjÄ™ „DokoÅ„cz grę†w „Centrum " "Sterowania Quarryâ€, albo „DokoÅ„cz grę†w menu „Plikâ€." #: src/gui-gtk/gtk-goban-window.c:1943 #, c-format msgid "The game is adjourned and saved in file `%s'" msgstr "Gra jest przerwana i zapisana w pliku „%sâ€" #: src/gui-gtk/gtk-goban-window.c:1962 msgid "ASCII diagram has been exported to clipboard" msgstr "Diagram ASCII zostaÅ‚ wyeksportowany do schowka" #: src/gui-gtk/gtk-goban-window.c:1975 msgid "Sensei's Library diagram has been exported to clipboard" msgstr "Diagram w formacie Sensei's Library zostaÅ‚ wyeksportowany do schowka" #: src/gui-gtk/gtk-goban-window.c:1990 msgid "" "You can usually paste the diagram in another application using `Ctrl+C' key " "combination or by selecting appropriate menu item." msgstr "" "Zazwyczaj można wkleić diagram w innym programie używajÄ…c kombinacji " "klawiszy „Ctrl+C†lub wybierajÄ…c wÅ‚aÅ›ciwÄ… opcjÄ™ w menu." #: src/gui-gtk/gtk-goban-window.c:2446 msgid "Sorry, there are no named nodes in this game tree" msgstr "Przykro mi, ale nie ma żadnych nazwanych wÄ™złów" #: src/gui-gtk/gtk-goban-window.c:2470 msgid "A GUI program for Go, Amazons and Reversi board games" msgstr "Graficzny program do gier Go, Amazons i Reversi" #: src/gui-gtk/gtk-goban-window.c:2472 msgid "Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev and others" msgstr "Copyright © 2003, 2004, 2005, 2006 PaweÅ‚ Pogonyszew i inni" #: src/gui-gtk/gtk-goban-window.c:2488 msgid "About Quarry" msgstr "O programie Quarry" #: src/gui-gtk/gtk-goban-window.c:2931 msgid "Really resign this game?" msgstr "Czy naprawdÄ™ chcesz poddać tÄ™ grÄ™?" #: src/gui-gtk/gtk-goban-window.c:2935 msgid "_Resign" msgstr "_Poddaj" #: src/gui-gtk/gtk-goban-window.c:3524 msgid "Edit Board Label" msgstr "Modyfikuj wstawionÄ… etykietÄ™" #: src/gui-gtk/gtk-goban-window.c:3527 msgid "Add Board Label" msgstr "Dodaj etykietÄ™" #: src/gui-gtk/gtk-goban-window.c:4026 #, c-format msgid "%s (W) vs. %s" msgstr "%s (B) kontra %s" #: src/gui-gtk/gtk-goban-window.c:4050 msgid "Unnamed Game" msgstr "Nie nazwana gra" #: src/gui-gtk/gtk-goban-window.c:4055 msgid "modified" msgstr "zmieniony" #: src/gui-gtk/gtk-goban-window.c:4088 msgid "[unknown]" msgstr "[nieznane]" #: src/gui-gtk/gtk-goban-window.c:4121 src/gui-gtk/gtk-goban-window.c:4126 #, c-format msgid "%d capture" msgid_plural "%d captures" msgstr[0] "%d jeniec" msgstr[1] "%d jeÅ„ców" msgstr[2] "%d jeÅ„ców" #: src/gui-gtk/gtk-goban-window.c:4136 #, c-format msgid "%s %s %.*f komi" msgstr "%s %s %.*f komi" #: src/gui-gtk/gtk-goban-window.c:4147 #, c-format msgid "%s %s %d komi" msgid_plural "%s %s %d komi" msgstr[0] " %s %s %d komi" msgstr[1] " %s %s %d komi" msgstr[2] " %s %s %d komi" #: src/gui-gtk/gtk-goban-window.c:4163 src/gui-gtk/gtk-goban-window.c:4166 #, c-format msgid "%d disk" msgid_plural "%d disks" msgstr[0] "%d dysk" msgstr[1] "%d dyski" msgstr[2] "%d dysków" #: src/gui-gtk/gtk-goban-window.c:4197 #, c-format msgid "Move %d: " msgstr "Ruch %d: " #: src/gui-gtk/gtk-goban-window.c:4201 #, c-format msgid "Last move: %u, " msgstr "Ostatni ruch: %u, " #. TRANSLATORS: This is an #. abbreviation of `Black'. #: src/gui-gtk/gtk-goban-window.c:4208 msgid "B " msgstr "C " #. TRANSLATORS: This is an #. abbreviation of `White'. #: src/gui-gtk/gtk-goban-window.c:4211 msgid "W " msgstr "B " #: src/gui-gtk/gtk-goban-window.c:4212 msgid "pass" msgstr "pas" #: src/gui-gtk/gtk-goban-window.c:4215 msgid "Game beginning" msgstr "PoczÄ…tek gry" #: src/gui-gtk/gtk-goban-window.c:4233 msgid "; black to play" msgstr "; ruch czarnych" #: src/gui-gtk/gtk-goban-window.c:4233 msgid "; white to play" msgstr "; ruch biaÅ‚ych" #: src/gui-gtk/gtk-goban-window.c:4236 msgid "; game over" msgstr "; koniec gry" #: src/gui-gtk/gtk-goban-window.c:4243 msgid "Black wins" msgstr "Czarne wygraÅ‚y" #: src/gui-gtk/gtk-goban-window.c:4246 msgid "White wins" msgstr "BiaÅ‚e wygraÅ‚y" #: src/gui-gtk/gtk-goban-window.c:4250 msgid "Black wins by forfeit" msgstr "Czarne wygraÅ‚y przez poddanie" #: src/gui-gtk/gtk-goban-window.c:4253 msgid "White wins by forfeit" msgstr "BiaÅ‚e wygraÅ‚y przez poddanie" #: src/gui-gtk/gtk-goban-window.c:4257 msgid "White resigns" msgstr "BiaÅ‚e poddaÅ‚y grÄ™" #: src/gui-gtk/gtk-goban-window.c:4260 msgid "Black resigns" msgstr "Czarne poddaÅ‚y grÄ™" #: src/gui-gtk/gtk-goban-window.c:4272 msgid "White runs out of time and loses" msgstr "BiaÅ‚e wyczerpaÅ‚y czas i przegraÅ‚y" #: src/gui-gtk/gtk-goban-window.c:4276 msgid "Black runs out of time and loses" msgstr "Czarne wyczerpaÅ‚y czas i przegraÅ‚y" #: src/gui-gtk/gtk-goban-window.c:4280 msgid "Game is draw" msgstr "Remis" #: src/gui-gtk/gtk-goban-window.c:4499 msgid "By Game _Rules (Game Over)" msgstr "Zgodnie z _reguÅ‚ami (koniec)" #: src/gui-gtk/gtk-goban-window.c:4503 msgid "By Game _Rules (Black)" msgstr "Zgodnie z _reguÅ‚ami (czarny)" #: src/gui-gtk/gtk-goban-window.c:4507 msgid "By Game _Rules (White)" msgstr "Zgodnie z _reguÅ‚ami (biaÅ‚y)" #: src/gui-gtk/gtk-goban-window.c:4551 msgid "insert node name here" msgstr "wprowadź nazwÄ™ dla tego wÄ™zÅ‚a" #: src/gui-gtk/gtk-goban-window.c:4952 msgid "Set Move Number" msgstr "Wprowadź numer ruchu" #. TRANSLATORS: Note that game name will be in `normal' form. #: src/gui-gtk/gtk-goban-window.c:5062 #, c-format msgid "" "GTP engine `%s' reported it could handle %s game, but failed to initialize " "itself for it" msgstr "" "Algorytm GTP „%s†zgÅ‚osiÅ‚ możliwoÅ›c obsÅ‚ugi gry %s, ale nie zainicjowaÅ‚ " "swojego dziaÅ‚ania" #: src/gui-gtk/gtk-goban-window.c:5070 #, c-format msgid "GTP engine `%s' cannot handle %dx%d board size, sorry" msgstr "Algorytm GTP „%s†niestety nie obsÅ‚uguje rozmiaru planszy %dx%d" #: src/gui-gtk/gtk-goban-window.c:5080 #, c-format msgid "GTP engine `%s' failed to clean the board" msgstr "Algorytm GTP „%s†nie wyczyÅ›ciÅ‚ planszy" #: src/gui-gtk/gtk-goban-window.c:5086 #, c-format msgid "" "GTP engine `%s' failed to set initial time limits (it could ignore them, but " "not fail)" msgstr "" "Algorytm GTP „%s†nie ustawiÅ‚ poczÄ…tkowego limitu czasu (można go ignorować, " "ale nie błędnie ustawiać)" #: src/gui-gtk/gtk-goban-window.c:5094 #, c-format msgid "GTP engine `%s' failed to set handicap stones on board" msgstr "Algorytm GTP „%s†nie ustawiÅ‚ kamieni handikapowych na planszy" #: src/gui-gtk/gtk-goban-window.c:5108 msgid "This is an engine error. You may want to report it to engine authors." msgstr "To błąd algorytmu. Możesz go zgÅ‚osić jego twórcom." #: src/gui-gtk/gtk-goban-window.c:5392 msgid "GTP engine is scoring..." msgstr "Algorytm GTP szacuje wynik..." #: src/gui-gtk/gtk-goban-window.c:5771 msgid "" "Unable to paste game record fragment from clipboard since it is not intended " "for pasting" msgstr "" "Nie można wkleić fragmentu zapisu gry ze schowka ponieważ nie jest " "przeznaczony do wklejania" #: src/gui-gtk/gtk-goban-window.c:5774 msgid "" "Clipboard SGF probably contains more than one game tree or not a single " "child of the root of the only game tree." msgstr "" "SGF ze schowka prawdopodobnie zawiera wiÄ™cej niż jedno drzewo ruchów albo " "wiÄ™cej niż jednÄ… odnogÄ™ drzewa ruchów." #: src/gui-gtk/gtk-goban-window.c:5778 msgid "Unable to paste game record fragment from clipboard" msgstr "Nie można wkleić fragmentu zapisu gry ze schowka" #. TRANSLATORS: This message is shown if you e.g. copy a part of #. 13x13 game tree and try to paste it into a 19x19 game tree; or #. copy a part of a Reversi game tree and try to paste it into a #. Go game tree. #: src/gui-gtk/gtk-goban-window.c:5784 msgid "Clipboard game record fragment must be of different game or board size." msgstr "Zapis gry w schowku ma inny rozmiar planszy lub dotyczy innej gry." #: src/gui-gtk/gtk-goban-window.c:5788 msgid "Clipboard contains an invalid game record fragment (SGF)" msgstr "Schowek zawiera błędny fragment zapisu gry (SGF)" #: src/gui-gtk/gtk-goban-window.c:5937 msgid "" "Please select dead stones\n" "to score the game" msgstr "" "Zaznacz martwe kamienie, aby\n" "ustalić wynik" #: src/gui-gtk/gtk-go-to-named-node-dialog.c:135 msgid "Go to Named Node" msgstr "Idź do nazwanego wÄ™zÅ‚a" #: src/gui-gtk/gtk-go-to-named-node-dialog.c:150 msgid "Node _name:" msgstr "Szukana _nazwa:" #: src/gui-gtk/gtk-go-to-named-node-dialog.c:156 msgid "Node comment:" msgstr "Komentarz dla wÄ™zÅ‚a:" #: src/gui-gtk/gtk-go-to-named-node-dialog.c:331 msgid "comment|Empty" msgstr "komentarz|Brak" #: src/gui-gtk/gtk-go-to-named-node-dialog.c:334 msgid "There is no such node" msgstr "Nie znaleziono wÄ™zÅ‚a speÅ‚niajÄ…cego podane kryteria" #: src/gui-gtk/gtk-gtp-client-interface.c:282 msgid "Engine hung up" msgstr "Algorytm zawiesiÅ‚ siÄ™" #: src/gui-gtk/gtk-gtp-client-interface.c:391 msgid "* ERROR: wrong response format\n" msgstr "* BÅÄ„D: zÅ‚y format odpowiedzi\n" #: src/gui-gtk/gtk-gtp-client-interface.c:395 msgid "* WARNING: unexpected response:\n" msgstr "* OSTRZERZENIE: nieoczekiwana odpowiedź:\n" #: src/gui-gtk/gtk-gtp-client-interface.c:399 msgid "* ERROR: unrecognized response line:\n" msgstr "* BÅÄ„D: nierozpoznana linia odpowiedzi:\n" #: src/gui-gtk/gtk-gtp-client-interface.c:404 #, c-format msgid "* ERROR: mismatched ID (%d expected):\n" msgstr "* BÅÄ„D: niepoprawny ID (oczekiwano %d):\n" #: src/gui-gtk/gtk-gtp-client-interface.c:408 msgid "* ERROR: unexpected ID in response (the command had none):\n" msgstr "* BÅÄ„D: nieoczekiwany ID w odpowiedzi (komenda nie posiada):\n" #. TRANSLATORS: Don't put ellipsis here, this string will most #. often go to fixed-width font terminals. #: src/gui-gtk/gtk-gtp-client-interface.c:415 msgid "* WARNING: future GTP version, I don't know about it...\n" msgstr "* OSTRZEÅ»ENIE: nowa wersja GTP, nie znana mi...\n" #: src/gui-gtk/gtk-new-game-dialog.c:98 msgid "" "Note that most GTP engines support only one game. Hence certain game / " "computer player combinations may be not possible to play." msgstr "" "PamiÄ™taj, że wiÄ™kszość algorytmów GTP obsÅ‚uguje tylko jeden rodzaj gry. " "Dlatego niektóre kombinacje gier i graczy komputerowych nie mogÄ… być użyte." #: src/gui-gtk/gtk-new-game-dialog.c:102 msgid "Fi_xed handicap:" msgstr "_Handikap tradycyjny:" #: src/gui-gtk/gtk-new-game-dialog.c:102 msgid "_Free handicap:" msgstr "Handikap _wolny:" #: src/gui-gtk/gtk-new-game-dialog.c:105 msgid "No limit" msgstr "Bez limitu" #: src/gui-gtk/gtk-new-game-dialog.c:105 msgid "Limited time for entire game" msgstr "Limit czasu dla caÅ‚ej gry" #: src/gui-gtk/gtk-new-game-dialog.c:106 msgid "Limited time per move" msgstr "Limit czasu na każdy ruch" #: src/gui-gtk/gtk-new-game-dialog.c:106 msgid "Canadian overtime" msgstr "Kanadyjskie byo-yomi" #: src/gui-gtk/gtk-new-game-dialog.c:124 msgid "New Game" msgstr "Nowa gra" #: src/gui-gtk/gtk-new-game-dialog.c:167 #: src/gui-gtk/gtk-new-game-record-dialog.c:132 msgid "Game" msgstr "Gra" #: src/gui-gtk/gtk-new-game-dialog.c:173 #: src/gui-gtk/gtk-resume-game-dialog.c:307 msgid "Hu_man" msgstr "CzÅ‚o_wiek" #: src/gui-gtk/gtk-new-game-dialog.c:173 #: src/gui-gtk/gtk-resume-game-dialog.c:308 msgid "Com_puter" msgstr "Ko_mputer" #: src/gui-gtk/gtk-new-game-dialog.c:174 #: src/gui-gtk/gtk-resume-game-dialog.c:308 msgid "H_uman" msgstr "_CzÅ‚owiek" #: src/gui-gtk/gtk-new-game-dialog.c:174 msgid "C_omputer" msgstr "_Komputer" #: src/gui-gtk/gtk-new-game-dialog.c:238 msgid "Manage _Engine List" msgstr "Sprawdź _listÄ™ algorytmów" #: src/gui-gtk/gtk-new-game-dialog.c:258 msgid "_Swap" msgstr "_ZamieÅ„" #: src/gui-gtk/gtk-new-game-dialog.c:287 msgid "Game & Players" msgstr "Gra i przeciwnicy" #: src/gui-gtk/gtk-new-game-dialog.c:362 msgid "Time control _type:" msgstr "Re_guÅ‚y limitów czasowych:" #: src/gui-gtk/gtk-new-game-dialog.c:384 msgid "Time Limit" msgstr "Limit czasu" #: src/gui-gtk/gtk-new-game-dialog.c:387 msgid "K_eep track of total time" msgstr "Odmierzaj _czas caÅ‚kowity" #: src/gui-gtk/gtk-new-game-dialog.c:407 msgid "Time _limit for game:" msgstr "Limit czasowy dla _gry:" #: src/gui-gtk/gtk-new-game-dialog.c:413 msgid "(per player)" msgstr "(dla każdego z graczy)" #: src/gui-gtk/gtk-new-game-dialog.c:427 msgid "Time _limit for move:" msgstr "Limit czasowy dla _ruchu:" #: src/gui-gtk/gtk-new-game-dialog.c:461 msgid "_Overtime period length:" msgstr "_Okres czasu dodatkowego:" #: src/gui-gtk/gtk-new-game-dialog.c:478 msgid "Mo_ves per overtime:" msgstr "IloÅ›c _ruchów w tym okresie:" #: src/gui-gtk/gtk-new-game-record-dialog.c:119 msgid "New Game Record" msgstr "Nowy zapis gry" #: src/gui-gtk/gtk-new-game-record-dialog.c:189 msgid "_Place stones" msgstr "Ka_mienie na planszy" #: src/gui-gtk/gtk-new-game-record-dialog.c:265 msgid "_White player:" msgstr "_BiaÅ‚e:" #: src/gui-gtk/gtk-new-game-record-dialog.c:276 msgid "_Black player:" msgstr "_Czarne:" #: src/gui-gtk/gtk-new-game-record-dialog.c:287 msgid "Game _name:" msgstr "_Nazwa gry:" #: src/gui-gtk/gtk-new-game-record-dialog.c:300 msgid "" "You can always change and expand game information later. Just choose `Edit/" "Game Information' menu item or press `Info' button on the main toolbar." msgstr "" "Zawsze można rozszerzyć informacje o grze później. W tym celu wystarczy " "wybrać „Edycja|Informacje o grze†z menu programu, albo użyć przycisku " "„Informacje†z paska głównego." #: src/gui-gtk/gtk-new-game-record-dialog.c:310 #: src/gui-gtk/gtk-resume-game-dialog.c:227 msgid "Short Game Information" msgstr "Krótka informacja o grze" #: src/gui-gtk/gtk-parser-interface.c:58 #, c-format msgid "Error reading file `%s'" msgstr "Błąd przy próbie odczytu pliku „%sâ€" #: src/gui-gtk/gtk-parser-interface.c:60 #, c-format msgid "File `%s' doesn't appear to be a valid SGF file" msgstr "Plik „%s†nie wyglÄ…da na poprawny plik typu SGF" #: src/gui-gtk/gtk-parser-interface.c:63 msgid "" "Please check that the file exists and its permission allow you to read it." msgstr "" "Sprawdź, czy plik na pewno istnieje i jego uprawnienia pozwalajÄ… Ci go " "odczytywać." #: src/gui-gtk/gtk-parser-interface.c:67 msgid "" "Quarry uses SGF file format for storing game records. SGF files would " "normally have `sgf' extension, but that's not necessarily true. Please make " "sure you select a proper SGF file." msgstr "" "Quarry używa formatu SGF do zapisywania gier. Pliki SGF powinny raczej " "posiadać rozszerzenie „.sgfâ€, ale nie jest to konieczne. Upewnij siÄ™, że " "wybraÅ‚eÅ› wÅ‚aÅ›ciwy plik SGF." #: src/gui-gtk/gtk-parser-interface.c:101 msgid "Open SGF File..." msgstr "Otwórz plik SGF..." #: src/gui-gtk/gtk-parser-interface.c:192 #, c-format msgid "Parsing file `%s'..." msgstr "Przetwarzanie pliku „%sâ€..." #: src/gui-gtk/gtk-preferences.c:431 msgid "General" msgstr "Ogólne" #: src/gui-gtk/gtk-preferences.c:434 msgid "Interface" msgstr "Interfejs" #: src/gui-gtk/gtk-preferences.c:435 msgid "General Interface" msgstr "Ogólne opcje interfejsu" #: src/gui-gtk/gtk-preferences.c:437 msgid "Editing & Viewing" msgstr "Edycja i przeglÄ…danie" #: src/gui-gtk/gtk-preferences.c:440 src/gui-gtk/gtk-preferences.c:441 msgid "Game Tree" msgstr "Drzewo ruchów" #: src/gui-gtk/gtk-preferences.c:444 msgid "GTP" msgstr "GTP" #: src/gui-gtk/gtk-preferences.c:447 src/gui-gtk/gtk-preferences.c:448 msgid "GTP Engines" msgstr "Algorytmy GTP" #: src/gui-gtk/gtk-preferences.c:451 msgid "Game Records (SGF)" msgstr "Zapisy gier (SGF)" #: src/gui-gtk/gtk-preferences.c:454 msgid "Saving" msgstr "Zapis do pliku" #: src/gui-gtk/gtk-preferences.c:455 msgid "Saving Game Records" msgstr "Zapisywanie plików z grami" #: src/gui-gtk/gtk-preferences.c:458 msgid "Board Appearance" msgstr "WyglÄ…d planszy" #: src/gui-gtk/gtk-preferences.c:462 msgid "Go Board Appearance" msgstr "WyglÄ…d gobanu (planszy do gry go)" #: src/gui-gtk/gtk-preferences.c:465 msgid "Amazons Board Appearance" msgstr "WyglÄ…d planszy do gry amazonki" #: src/gui-gtk/gtk-preferences.c:468 msgid "Reversi Board Appearance" msgstr "WyglÄ…d planszy do gry reversi" #: src/gui-gtk/gtk-preferences.c:478 msgid "Preferences" msgstr "Preferencje" #: src/gui-gtk/gtk-preferences.c:515 msgid "Categor_y:" msgstr "Kategori_a:" #: src/gui-gtk/gtk-preferences.c:641 msgid "Use _newer (GTK+ 2.4) file chooser" msgstr "Używaj _nowszego (GTK+ 2.4) okna wyboru pliku" #: src/gui-gtk/gtk-preferences.c:642 msgid "Use _old-style file selection dialog" msgstr "Używaj _starszego okna wyboru pliku" #: src/gui-gtk/gtk-preferences.c:672 msgid "File Chooser Dialog Style" msgstr "Styl okna wyboru otwieranego pliku" #: src/gui-gtk/gtk-preferences.c:688 msgid "_Main toolbar style:" msgstr "Styl paska _głównego:" #: src/gui-gtk/gtk-preferences.c:692 msgid "_Editing toolbar style:" msgstr "Styl paska _edycji:" #: src/gui-gtk/gtk-preferences.c:696 msgid "N_avigation toolbar style:" msgstr "Styl paska _poÅ‚ożenia:" #: src/gui-gtk/gtk-preferences.c:705 msgid "Toolbar Styles" msgstr "WyglÄ…d listwy poleceÅ„" #: src/gui-gtk/gtk-preferences.c:725 msgid "Desktop default" msgstr "DomyÅ›lny dla Å›rodowiska" #: src/gui-gtk/gtk-preferences.c:726 msgid "Text below icons" msgstr "Tekst poniżej ikon" #: src/gui-gtk/gtk-preferences.c:732 msgid "Text beside important icons" msgstr "Tekst poniżej głównych ikon" #: src/gui-gtk/gtk-preferences.c:735 msgid "Icons only" msgstr "Tylko ikony" #: src/gui-gtk/gtk-preferences.c:736 msgid "Text only" msgstr "Tylko tekst" #: src/gui-gtk/gtk-preferences.c:792 msgid "Show" msgstr "DostÄ™pny" #: src/gui-gtk/gtk-preferences.c:799 msgid "Name" msgstr "Nazwa" #: src/gui-gtk/gtk-preferences.c:808 msgid "_List of GTP engines:" msgstr "_Lista algorytmów GTP:" #: src/gui-gtk/gtk-preferences.c:856 msgid "Name:" msgstr "Nazwa:" #: src/gui-gtk/gtk-preferences.c:865 msgid "Version:" msgstr "Wersja:" #: src/gui-gtk/gtk-preferences.c:875 src/gui-gtk/gtk-preferences.c:1630 msgid "Supported game:" msgstr "ObsÅ‚ugiwana gra:" #: src/gui-gtk/gtk-preferences.c:889 msgid "Command line:" msgstr "Polecenie:" #: src/gui-gtk/gtk-preferences.c:914 msgid "GTP Engine Information" msgstr "Informacja o algorytmie GTP" #: src/gui-gtk/gtk-preferences.c:935 msgid "_Always" msgstr "_Zawsze" #: src/gui-gtk/gtk-preferences.c:935 msgid "A_utomatically" msgstr "_Automatycznie" #: src/gui-gtk/gtk-preferences.c:935 msgid "_Never" msgstr "_Nigdy" #: src/gui-gtk/gtk-preferences.c:937 msgid "Al_ways" msgstr "Zaw_sze" #: src/gui-gtk/gtk-preferences.c:937 msgid "Aut_omatically" msgstr "Aut_omatycznie" #: src/gui-gtk/gtk-preferences.c:937 msgid "Ne_ver" msgstr "Ni_gdy" #: src/gui-gtk/gtk-preferences.c:939 msgid "Scroll _minimal distance" msgstr "U_trzymuj bieżący wÄ™zeÅ‚ w widoku drzewa" #: src/gui-gtk/gtk-preferences.c:940 msgid "_Recenter view on the current node" msgstr "_WyÅ›rodkuj widok drzewa na bieżącym węźle" #: src/gui-gtk/gtk-preferences.c:943 msgid "" "In automatic mode the game tree is shown only if it has at least one " "variation. In any case, you can show/hide game tree in each window " "separately." msgstr "" "W trybie automatycznym drzewo ruchów pokazywane jest jedynie wtedy, gdy " "posiada rozgałęzienia. Można je jednak wyÅ›wietlać i ukrywać niezależnie w " "każdym oknie." #: src/gui-gtk/gtk-preferences.c:947 msgid "" "In automatic mode the game tree view scrolls to show the current node only " "if it has been showing current node before. I.e. unless you scrolled it away " "manually." msgstr "" "W trybie automatycznym widok drzewa gry stara siÄ™ zawsze obejmować bieżący " "wÄ™zeÅ‚, o ile nie wypadÅ‚ on poza jego obrÄ™b przy przesuwaniu tego widoku " "przez użytkownika." #: src/gui-gtk/gtk-preferences.c:992 msgid "Show Game Tree" msgstr "Pokazuj drzewo ruchów" #: src/gui-gtk/gtk-preferences.c:1039 msgid "Track Tree's Current Node" msgstr "Podążaj za bieżącym wÄ™zÅ‚em" #: src/gui-gtk/gtk-preferences.c:1042 msgid "Show _tooltips" msgstr "Pokazuj _dopiski" #: src/gui-gtk/gtk-preferences.c:1049 msgid "Tooltips" msgstr "Dopiski" #: src/gui-gtk/gtk-preferences.c:1065 msgid "Always use _UTF-8 (recommended)" msgstr "_Zawsze używaj UTF-8 (zalecane)" #: src/gui-gtk/gtk-preferences.c:1066 msgid "Preserve _original encoding" msgstr "Zachowaj _oryginalne kodowanie" #: src/gui-gtk/gtk-preferences.c:1068 msgid "" "Note that many characters cannot be represented in non-UTF-8 encodings and " "thus some information may be lost if you use them. Quarry also works fastest " "with UTF-8; this may be important if you have very large SGF files." msgstr "" "UTF-8 jest zalecane, ponieważ pozwala używać o wiele wiÄ™kszej gamy znaków, " "niż inne standardy kodowania. Dodatkowo, Quarry operuje szybciej na plikach " "zapisanych w tym standardzie. Może to mieć szczególne znaczenie przy pracy z " "bardzo dużymi plikami SGF." #: src/gui-gtk/gtk-preferences.c:1093 msgid "Encoding" msgstr "Kodowanie" #: src/gui-gtk/gtk-preferences.c:1103 msgid "_Relative to stone size" msgstr "D_opasowany do rozmiaru kamieni" #: src/gui-gtk/gtk-preferences.c:1104 msgid "On _white stones:" msgstr "Na _biaÅ‚ych kamieniach:" #: src/gui-gtk/gtk-preferences.c:1105 msgid "On _black stones:" msgstr "Na c_zarnych kamieniach:" #: src/gui-gtk/gtk-preferences.c:1106 msgid "On _empty intersections:" msgstr "Na _pustych przeciÄ™ciach:" #: src/gui-gtk/gtk-preferences.c:1120 msgid "_Relative to amazon size" msgstr "D_opasowany do rozmiaru „amazonekâ€" #: src/gui-gtk/gtk-preferences.c:1121 msgid "On _white amazons:" msgstr "Na _biaÅ‚ych „amazonkachâ€:" #: src/gui-gtk/gtk-preferences.c:1122 msgid "On _black amazons:" msgstr "Na c_zarnych „amazonkachâ€:" #: src/gui-gtk/gtk-preferences.c:1123 src/gui-gtk/gtk-preferences.c:1182 msgid "On _empty fields:" msgstr "Na _pustych polach:" #: src/gui-gtk/gtk-preferences.c:1142 msgid "Pick Checkerboard Pattern Color" msgstr "Wybór koloru zaciemnienia czarnych pól" #: src/gui-gtk/gtk-preferences.c:1151 msgid "Checkerboard _pattern color:" msgstr "Kolor zaciemnienia _pól:" #: src/gui-gtk/gtk-preferences.c:1167 msgid "Checkerboard pattern _opacity:" msgstr "_Intensywność zaciemnienia pól:" #: src/gui-gtk/gtk-preferences.c:1179 msgid "_Relative to disk size" msgstr "D_opasowany do rozmiaru dysków" #: src/gui-gtk/gtk-preferences.c:1180 msgid "On _white disks:" msgstr "Na _biaÅ‚ych dyskach:" #: src/gui-gtk/gtk-preferences.c:1181 msgid "On _black disks:" msgstr "Na c_zarnych dyskach:" #: src/gui-gtk/gtk-preferences.c:1195 msgid "Use _texture:" msgstr "Użyj _tekstury:" #: src/gui-gtk/gtk-preferences.c:1196 msgid "Use _solid color:" msgstr "Użyj pojedyÅ„czego _koloru:" #: src/gui-gtk/gtk-preferences.c:1271 msgid "Choose a Background Texture..." msgstr "Wybór tekstury dla tÅ‚a..." #: src/gui-gtk/gtk-preferences.c:1282 msgid "Pick Background Color" msgstr "Wybór koloru tÅ‚a" #: src/gui-gtk/gtk-preferences.c:1296 msgid "Pick Color for Grid and Labels" msgstr "Wybór koloru siatki i współrzÄ™dnych" #: src/gui-gtk/gtk-preferences.c:1306 msgid "_Grid and labels color:" msgstr "Kolor naniesionych _lini:" #: src/gui-gtk/gtk-preferences.c:1345 msgid "_Theme:" msgstr "Moty_w:" #: src/gui-gtk/gtk-preferences.c:1354 msgid "Use theme _defaults" msgstr "_DomyÅ›lne dla motywu" #: src/gui-gtk/gtk-preferences.c:1371 msgid "_Size:" msgstr "_Rozmiar:" #: src/gui-gtk/gtk-preferences.c:1398 msgid "_Opacity:" msgstr "_Intensywność:" #: src/gui-gtk/gtk-preferences.c:1413 msgid "Size & Opacity" msgstr "Rozmiar i intensywność" #: src/gui-gtk/gtk-preferences.c:1429 msgid "Color" msgstr "Kolor" #: src/gui-gtk/gtk-preferences.c:1443 msgid "Pick Color for Markup" msgstr "Wybór koloru dla znaczników" #: src/gui-gtk/gtk-preferences.c:1482 msgid "Background" msgstr "TÅ‚o" #: src/gui-gtk/gtk-preferences.c:1484 msgid "Markup" msgstr "Znaczniki" #: src/gui-gtk/gtk-preferences.c:1630 msgid "Supported games:" msgstr "ObsÅ‚ugiwane gry:" #: src/gui-gtk/gtk-preferences.c:1637 msgid "This engine comes from site configuration." msgstr "Ten algorytm jest skonfigurowany globalnie." #: src/gui-gtk/gtk-preferences.c:1860 msgid "" "You can use `%n' and `%v' strings in Screen name field. They will " "substituted with name and version of the engine correspondingly. By default, " "`%n %v' is used." msgstr "" "Można użyć symboli specjalnych „%n†i „%v†w polu „WyÅ›wietlana nazwaâ€. BÄ™dÄ… " "zastÄ™powane odpowiednio: nazwÄ… algorytmu i jego wersjÄ…. DomyÅ›lnie używany " "jest opis „%n %vâ€." #: src/gui-gtk/gtk-preferences.c:1908 msgid "Modify GTP Engine Information" msgstr "Modyfikuj informacje o algorytmie GTP" #: src/gui-gtk/gtk-preferences.c:1909 msgid "New GTP Engine" msgstr "Nowy algorytm GTP" #: src/gui-gtk/gtk-preferences.c:1955 msgid "Command _line:" msgstr "_Polecenie:" #: src/gui-gtk/gtk-preferences.c:1961 msgid "Choose GTP Engine..." msgstr "Wybór algorytmu GTP..." #: src/gui-gtk/gtk-preferences.c:1972 msgid "Screen _name:" msgstr "WyÅ›wietlana _nazwa:" #: src/gui-gtk/gtk-preferences.c:2018 msgid "Querying engine's name, version and known commands..." msgstr "" "Komunikacja z algorytmem w celu ustalenia jego wersji, nazwy i obsÅ‚ugiwanych " "komend..." #: src/gui-gtk/gtk-preferences.c:2039 msgid "" "Please make sure you typed engine's filename correctly and that you have " "permission to execute it." msgstr "" "Upewnij siÄ™, że wskazaÅ‚eÅ› wÅ‚aÅ›ciwÄ… nazwÄ™ pliku wykonalnego algorytmu i masz " "uprawnienia do jego uruchamiania." #: src/gui-gtk/gtk-preferences.c:2078 msgid "Waiting for the engine to quit..." msgstr "Oczekiwanie na zakoÅ„czenie pracy algorytmu..." #: src/gui-gtk/gtk-preferences.c:2182 msgid "" "The engine might have crashed, quit prematurely or disconnected. Please " "verify command line, including options, and consult engine's documentation " "if needed." msgstr "" "Algorytm mógÅ‚ zawiesić siÄ™, zakoÅ„czyć przedwczeÅ›nie dziaÅ‚anie lub otrzymać " "komendÄ™ trybu GTP, którÄ… zinterpretowaÅ‚ jako koniec pracy. Sprawdź, czy " "wpisane polecenie jest wÅ‚aÅ›ciwe (zwróć uwagÄ™ na opcje dodatkowe). " "Ewentualnie zapoznaj siÄ™ z dokumentacjÄ… algorytmu." #: src/gui-gtk/gtk-preferences.c:2197 #, c-format msgid "Lost connection to GTP Engine (%s)" msgstr "Nieoczekiwane zakoÅ„czenie pracy z algorytmem (%s)" #: src/gui-gtk/gtk-preferences.c:3011 msgid "" "Perhaps engine's binary has been deleted or changed. You will probably need " "to alter engine's command line in the Preferences dialog." msgstr "" "Być może plik wykonalny algorytmu zostaÅ‚ usuniÄ™ty lub zmieniony. " "Prawdopodobnie polecenie uruchamiajÄ…ce algorytm bÄ™dzie musiaÅ‚o zostać " "zmienione w oknie preferencji." #: src/gui-gtk/gtk-resume-game-dialog.c:92 msgid "Resume Game..." msgstr "DokoÅ„cz grÄ™..." #: src/gui-gtk/gtk-resume-game-dialog.c:115 #, c-format msgid "The game stored in file `%s' (%s) is not supported by Quarry" msgstr "Gra przechowywana w pliku „%s†(%s) nie jest obsÅ‚ugiwana przez Qarry" #: src/gui-gtk/gtk-resume-game-dialog.c:138 msgid "" "This game appears to have been finished. Open it for viewing and/or editing " "instead?" msgstr "" "Ta gra wyglÄ…da na zakoÅ„czonÄ…. Czy otworzyć jÄ… w trybie przeglÄ…dania/edycji?" #: src/gui-gtk/gtk-resume-game-dialog.c:212 msgid "Resuming Game" msgstr "DokoÅ„czenie przerwanej gry" #: src/gui-gtk/gtk-resume-game-dialog.c:214 msgid "_Resume" msgstr "_DokoÅ„cz" #: src/gui-gtk/gtk-resume-game-dialog.c:231 msgid "Game:" msgstr "Gra:" #: src/gui-gtk/gtk-resume-game-dialog.c:240 msgid "Board size:" msgstr "Rozmiar planszy:" #: src/gui-gtk/gtk-resume-game-dialog.c:258 msgid "Handicap:" msgstr "Handikap:" #: src/gui-gtk/gtk-resume-game-dialog.c:262 msgid "handicap|Not set" msgstr "Nie ustalony" #: src/gui-gtk/gtk-resume-game-dialog.c:268 msgid "Komi:" msgstr "Komi:" #: src/gui-gtk/gtk-resume-game-dialog.c:271 msgid "komi|Not set" msgstr "Nie ustalone" #: src/gui-gtk/gtk-resume-game-dialog.c:294 msgid "Filename:" msgstr "Nazwa pliku:" #: src/gui-gtk/gtk-resume-game-dialog.c:307 msgid "Compu_ter" msgstr "_Komputer" #: src/gui-gtk/quarry-find-dialog.c:104 msgid "Whole game _tree" msgstr "_Drzewo caÅ‚ej gry" #: src/gui-gtk/quarry-find-dialog.c:104 msgid "Current no_de only" msgstr "_Tylko bieżący wÄ™zeÅ‚" #: src/gui-gtk/quarry-find-dialog.c:107 msgid "C_omments & node names" msgstr "Komentarze _i nazwy wÄ™złów" #: src/gui-gtk/quarry-find-dialog.c:108 msgid "Comm_ents only" msgstr "Tylko _komentarze" #: src/gui-gtk/quarry-find-dialog.c:108 msgid "Node na_mes only" msgstr "Tylko _nazwy wÄ™złów" #: src/gui-gtk/quarry-find-dialog.c:154 msgid "Search _for:" msgstr "_Znajdź:" #: src/gui-gtk/quarry-find-dialog.c:161 msgid "Case _sensitive" msgstr "_Rozróżnianie wielkoÅ›ci liter" #: src/gui-gtk/quarry-find-dialog.c:169 msgid "Whole _words only" msgstr "Tylko _caÅ‚e wyrazy" #: src/gui-gtk/quarry-find-dialog.c:177 msgid "Wrap _around" msgstr "_Automatyczny powrót do poczÄ…tku" #: src/gui-gtk/quarry-find-dialog.c:191 msgid "A_uto-close this dialog" msgstr "_Zamknij to okno po znalezieniu" #: src/gui-gtk/quarry-find-dialog.c:202 msgid "Options" msgstr "Opcje" #: src/gui-gtk/quarry-find-dialog.c:251 msgid "Search Scope" msgstr "Zakres wyszukiwania" #: src/gui-gtk/quarry-move-number-dialog.c:66 #: src/gui-gtk/quarry-move-number-dialog.c:148 msgid "Use se_quential move number" msgstr "Użyj numeru wÅ‚aÅ›ciwego dla _sekwencji" #: src/gui-gtk/quarry-move-number-dialog.c:66 msgid "_Set specific move number:" msgstr "Wpisz _rÄ™cznie numer ruchu" #: src/gui-gtk/quarry-save-confirmation-dialog.c:89 msgid "Close _without Saving" msgstr "Zamknij _bez zapisywania" #: src/gui-gtk/quarry-save-confirmation-dialog.c:173 #, c-format msgid "" "If you don't save, changes from the last %d second will be lost permanently." msgid_plural "" "If you don't save, changes from the last %d seconds will be lost permanently." msgstr[0] "" "JeÅ›li nie zapiszesz, zmiany z ostatniej %d sekundy zostanÄ… bezpowrotnie " "utracone." msgstr[1] "" "JeÅ›li nie zapiszesz, zmiany z ostatnch %d sekund zostanÄ… bezpowrotnie " "utracone." msgstr[2] "" "JeÅ›li nie zapiszesz, zmiany z ostatnich %d sekund zostanÄ… bezpowrotnie " "utracone." #: src/gui-gtk/quarry-save-confirmation-dialog.c:181 msgid "If you don't save, changes from the last minute will be discarded." msgstr "JeÅ›li nie zapiszesz, zmiany z ostatniej minuty zostanÄ… porzucone." #. TRANSLATORS: Cannot be one minute one second, actually. #: src/gui-gtk/quarry-save-confirmation-dialog.c:187 #, c-format msgid "" "If you don't save, changes from the last minute and %d second will be lost " "permanently." msgid_plural "" "If you don't save, changes from the last minute and %d seconds will be lost " "permanently." msgstr[0] "" "JeÅ›li nie zapiszesz, zmiany z ostatniej minuty i %d sekundyzostanÄ… " "bezpowrotnie utracone." msgstr[1] "" "JeÅ›li nie zapiszesz, zmiany z ostatniej minuty i %d sekund zostanÄ… " "bezpowrotnie utracone." msgstr[2] "" "JeÅ›li nie zapiszesz, zmiany z ostatniej minuty i %d sekund zostanÄ… " "bezpowrotnie utracone." #: src/gui-gtk/quarry-save-confirmation-dialog.c:198 #, c-format msgid "" "If you don't save, changes from the last %d minute will be lost permanently." msgid_plural "" "If you don't save, changes from the last %d minutes will be lost permanently." msgstr[0] "" "JeÅ›li nie zapiszesz, zmiany z ostatniej %d minuty zostanÄ… bezpowrotnie " "utracone." msgstr[1] "" "JeÅ›li nie zapiszesz, zmiany z ostatnich %d minut zostanÄ… bezpowrotnie " "utracone." msgstr[2] "" "JeÅ›li nie zapiszesz, zmiany z ostatnich %d minut zostanÄ… bezpowrotnie " "utracone." #. TRANSLATORS: Cannot be one hour one minute, actually. #: src/gui-gtk/quarry-save-confirmation-dialog.c:212 #, c-format msgid "" "If you don't save, changes from the last hour and %d minute will be lost " "permanently." msgid_plural "" "If you don't save, changes from the last hour and %d minutes will be lost " "permanently." msgstr[0] "" "JeÅ›li nie zapiszesz, zmiany z ostatniej godziny i %d minuty zostanÄ… " "bezpowrotnie utracone." msgstr[1] "" "JeÅ›li nie zapiszesz, zmiany z ostatniej godziny i %d minut zostanÄ… " "bezpowrotnie utracone." msgstr[2] "" "JeÅ›li nie zapiszesz, zmiany z ostatniej godziny i %d minut zostanÄ… " "bezpowrotnie utracone." #: src/gui-gtk/quarry-save-confirmation-dialog.c:224 #, c-format msgid "" "If you don't save, changes from the last %d hour will be lost permanently." msgid_plural "" "If you don't save, changes from the last %d hours will be lost permanently." msgstr[0] "" "JeÅ›li nie zapiszesz, zmiany z ostatniej %d godziny zostanÄ… bezpowrotnie " "utracone." msgstr[1] "" "JeÅ›li nie zapiszesz, zmiany z ostatnich %d godzin zostanÄ… bezpowrotnie " "utracone." msgstr[2] "" "JeÅ›li nie zapiszesz, zmiany z ostatnich %d godzin zostanÄ… bezpowrotnie " "utracone." #: src/gui-gtk/quarry-stock.c:56 msgid "_New Game" msgstr "Nowa _gra" #: src/gui-gtk/quarry-stock.c:57 msgid "_Open Game Record" msgstr "_Otwórz zapis gry" #: src/gui-gtk/quarry-stock.c:59 msgid "_Browse..." msgstr "_PrzeglÄ…daj..." #: src/gui-gtk/quarry-stock.c:60 msgid "Crea_te" msgstr "_Utwórz" #: src/gui-gtk/quarry-stock.c:61 msgid "_Done" msgstr "_Gotowe" #: src/gui-gtk/quarry-stock.c:62 msgid "_Go to Node" msgstr "Idż do _wÄ™zÅ‚a" #: src/gui-gtk/quarry-stock.c:63 msgid "_Modify" msgstr "_ZmieÅ„" #: src/gui-gtk/quarry-stock.c:64 msgid "Move _Up" msgstr "W _górÄ™" #: src/gui-gtk/quarry-stock.c:65 msgid "Move _Down" msgstr "W _dół" #: src/gui-gtk/quarry-stock.c:66 msgid "find|_Next" msgstr "_NastÄ™pny" #: src/gui-gtk/quarry-stock.c:67 msgid "_Overwrite" msgstr "_ZastÄ…p" #: src/gui-gtk/quarry-stock.c:68 msgid "_Play" msgstr "_Graj" #: src/gui-gtk/quarry-stock.c:69 msgid "find|_Previous" msgstr "_Poprzedni" #. TRANSLATORS: This is only used for non-integral scores. You #. should also add translation of `points' if it is required by #. your language. #: src/board/board.c:897 #, c-format msgid "Black wins by %.*f" msgstr "Czarne wygraÅ‚y o %.*f punktów" #. TRANSLATORS: This is only used for non-integral scores. You #. should also add translation of `points' if it is required by #. your language. #: src/board/board.c:904 #, c-format msgid "White wins by %.*f" msgstr "BiaÅ‚e wygraÅ‚y o %.*f punktów" #: src/board/board.c:915 #, c-format msgid "Black wins by %d" msgid_plural "Black wins by %d" msgstr[0] "Czarne wygraÅ‚y o %d punkt" msgstr[1] "Czarne wygraÅ‚y o %d punkty" msgstr[2] "Czarne wygraÅ‚y o %d punktów" #: src/board/board.c:923 #, c-format msgid "White wins by %d" msgid_plural "White wins by %d" msgstr[0] "BiaÅ‚e wygraÅ‚y o %d punkt" msgstr[1] "BiaÅ‚e wygraÅ‚y o %d punkty" msgstr[2] "BiaÅ‚e wygraÅ‚y o %d punktów" #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:29 msgid "Go" msgstr "go" #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:43 msgid "Reversi" msgstr "reversi" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:58 msgid "chess" msgstr "szachy" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:73 msgid "Gomoku" msgstr "gomoku" # FIXME: ПеревеÑти. #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:88 msgid "Nine Men's Morris" msgstr "Nine Men’s Morris" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:103 msgid "Backgammon" msgstr "trik-trak" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:118 msgid "Chinese chess" msgstr "szachy chiÅ„skie" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:133 msgid "Shogi" msgstr "szogi" # FIXME: polski odpowiednik #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:148 msgid "Lines of Action" msgstr "Lines of Action" # FIXME: polski odpowiednik #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:163 msgid "Ataxx" msgstr "Ataxx" # FIXME: polski odpowiednik #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:178 msgid "Hex" msgstr "Hex" # FIXME: polski odpowiednik #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:193 msgid "Jungle" msgstr "Jungle" # FIXME: polski odpowiednik #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:208 msgid "Neutron" msgstr "Neutron" # FIXME: polski odopiwednik #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:223 msgid "Philosopher's Football" msgstr "Philosopher’s Football" # FIXME: polski odpowiednik #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:238 msgid "Quadrature" msgstr "Quadrature" # FIXME: polski odpowiednik #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:253 msgid "Trax" msgstr "Trax" # FIXME: polski odpowiednik #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:268 msgid "Tantrix" msgstr "Tantrix" #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:282 msgid "Amazons" msgstr "amazonki" # FIXME: polski odpowiednik #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:297 msgid "Octi" msgstr "Octi" # FIXME: polski odpowiednik #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:312 msgid "Gess" msgstr "Gess" #: src/board/go.c:1323 #, c-format msgid "White: %d territory" msgid_plural "White: %d territory" msgstr[0] "BiaÅ‚e: %d punkt terytorium" msgstr[1] "BiaÅ‚e: %d punkty terytorium" msgstr[2] "BiaÅ‚e: %d punktów terytorium" #: src/board/go.c:1328 src/board/go.c:1365 #, c-format msgid " + %d capture" msgid_plural " + %d captures" msgstr[0] " + %d jeniec" msgstr[1] " + %d jeÅ„ców" msgstr[2] " + %d jeÅ„ców" #. TRANSLATORS: e.g. `` + 6.5 komi = #. 87.5''. This is used only with #. fractional komi. #: src/board/go.c:1337 #, c-format msgid " %s %.*f komi = %.*f\n" msgstr " %s %.*f komi = %.*f\n" #. TRANSLATORS: e.g. `` + 6 komi = 87''. #: src/board/go.c:1351 #, c-format msgid " %s %d komi = %d\n" msgid_plural " %s %d komi = %d\n" msgstr[0] " %s %d komi = %d\n" msgstr[1] " %s %d komi = %d\n" msgstr[2] " %s %d komi = %d\n" #: src/board/go.c:1360 #, c-format msgid "Black: %d territory" msgid_plural "Black: %d territory" msgstr[0] "Czarne: %d punkt terytorium" msgstr[1] "Czarne: %d punkty terytorium" msgstr[2] "Czarne: %d punktów terytorium" #: src/board/go.c:1374 msgid "The game is draw" msgstr "Gra zakoÅ„czyÅ‚a siÄ™ remisem" quarry-0.2.0/po/ru.po0000644000175000017500000021461610524133340013107 0ustar bartbart# Russian translations for Quarry package. # Copyright (C) 2004, 2005, 2006 Paul Pogonyshev # This file is distributed under the same license as the Quarry package. # Paul Pogonyshev , 2005, 2006. # msgid "" msgstr "" "Project-Id-Version: Quarry 0.1.15\n" "Report-Msgid-Bugs-To: quarry-dev@gna.org\n" "POT-Creation-Date: 2006-11-07 18:33+0200\n" "PO-Revision-Date: 2006-10-28 15:05+0300\n" "Last-Translator: Paul Pogonyshev \n" "Language-Team: Russian \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%" "10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" #: src/gui-gtk/gtk-add-or-edit-label-dialog.c:73 msgid "" "Although board labels are not limited in length, it is better to use only " "one or two characters long labels. Longer labels will not be visible " "immediately or at all in most clients." msgstr "" "Ð¥Ð¾Ñ‚Ñ Ð½Ð°Ð´Ð¿Ð¸Ñи не ограничены по длине, лучше не иÑпользовать более одного или " "двух Ñимволов. Более длинные надпиÑи будут не видны в большинÑтве клиентов." #: src/gui-gtk/gtk-add-or-edit-label-dialog.c:87 msgid "Label _text:" msgstr "ТекÑÑ‚ _надпиÑи:" #: src/gui-gtk/gtk-color-button.c:581 msgid "Pick a Color" msgstr "Выберите цвет" #: src/gui-gtk/gtk-control-center.c:64 msgid "Quarry Control Center" msgstr "Панель ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Quarry" #: src/gui-gtk/gtk-control-center.c:80 msgid "Ne_w Game Record" msgstr "ÐÐ¾Ð²Ð°Ñ _запиÑÑŒ партии" #: src/gui-gtk/gtk-control-center.c:96 msgid "_Resume Game" msgstr "_Возобновить партию" #: src/gui-gtk/gtk-file-dialog.c:281 msgid "" "Note that all information in the existing file will be lost permanently if " "you choose to overwrite it." msgstr "" "ЕÑли вы решите перепиÑать ÑущеÑтвующий файл, вÑÑ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð² нем будет " "безвозвратно потерÑна." #: src/gui-gtk/gtk-file-dialog.c:284 #, c-format msgid "" "File named `%s' already exists. Do you want to overwrite it with the one you " "are saving?" msgstr "Файл Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼ «%s» уже ÑущеÑтвует. Ð’Ñ‹ хотите перепиÑать его?" #: src/gui-gtk/gtk-game-info-dialog.c:231 #: src/gui-gtk/gtk-resume-game-dialog.c:325 msgid "N_ame:" msgstr "И_мÑ:" #: src/gui-gtk/gtk-game-info-dialog.c:231 #: src/gui-gtk/gtk-resume-game-dialog.c:324 msgid "_Name:" msgstr "_ИмÑ:" #: src/gui-gtk/gtk-game-info-dialog.c:238 msgid "Team:" msgstr "Команда:" #: src/gui-gtk/gtk-game-info-dialog.c:244 msgid "Rank:" msgstr "Ранг:" #: src/gui-gtk/gtk-game-info-dialog.c:256 #: src/gui-gtk/gtk-new-game-dialog.c:226 #: src/gui-gtk/gtk-resume-game-dialog.c:364 msgid "Black Player" msgstr "Черные" #: src/gui-gtk/gtk-game-info-dialog.c:256 #: src/gui-gtk/gtk-new-game-dialog.c:226 #: src/gui-gtk/gtk-resume-game-dialog.c:364 msgid "White Player" msgstr "Белые" #: src/gui-gtk/gtk-game-info-dialog.c:270 msgid "_Game name:" msgstr "_Ðазвание партии:" #: src/gui-gtk/gtk-game-info-dialog.c:273 msgid "_Place:" msgstr "МеÑ_то проведениÑ:" #: src/gui-gtk/gtk-game-info-dialog.c:277 msgid "Da_te:" msgstr "_Дата:" #: src/gui-gtk/gtk-game-info-dialog.c:280 msgid "_Event:" msgstr "_Событие:" #: src/gui-gtk/gtk-game-info-dialog.c:284 msgid "R_ound:" msgstr "Р_аунд:" #: src/gui-gtk/gtk-game-info-dialog.c:295 #: src/gui-gtk/gtk-game-info-dialog.c:535 #: src/gui-gtk/gtk-game-info-dialog.c:541 msgid "Game Information" msgstr "Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ партии" #: src/gui-gtk/gtk-game-info-dialog.c:298 msgid "Rule _set:" msgstr "_Правила:" #: src/gui-gtk/gtk-game-info-dialog.c:324 #: src/gui-gtk/gtk-new-game-record-dialog.c:187 msgid "Han_dicap:" msgstr "_Гандикап:" #: src/gui-gtk/gtk-game-info-dialog.c:347 #: src/gui-gtk/gtk-new-game-dialog.c:574 #: src/gui-gtk/gtk-new-game-record-dialog.c:231 msgid "_Komi:" msgstr "_Коми:" #: src/gui-gtk/gtk-game-info-dialog.c:374 #: src/gui-gtk/gtk-new-game-dialog.c:444 msgid "_Main time:" msgstr "ОÑновное _времÑ:" #: src/gui-gtk/gtk-game-info-dialog.c:386 msgid "O_vertime:" msgstr "Допо_лнительное времÑ:" #: src/gui-gtk/gtk-game-info-dialog.c:397 #: src/gui-gtk/gtk-new-game-dialog.c:602 msgid "Game Rules" msgstr "Правила игры" #: src/gui-gtk/gtk-game-info-dialog.c:412 msgid "General" msgstr "ÐžÐ±Ñ‰Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ" #: src/gui-gtk/gtk-game-info-dialog.c:415 msgid "Game re_sult:" msgstr "Резу_льтат партии:" #: src/gui-gtk/gtk-game-info-dialog.c:419 msgid "_Opening played:" msgstr "Сыграный _дебют:" #: src/gui-gtk/gtk-game-info-dialog.c:449 msgid "Comment / _description:" msgstr "_Комментарии/опиÑание:" #: src/gui-gtk/gtk-game-info-dialog.c:463 msgid "Description & Result" msgstr "ОпиÑание и результат" #: src/gui-gtk/gtk-game-info-dialog.c:466 msgid "Co_pyright string:" msgstr "_ÐвторÑкие права:" #: src/gui-gtk/gtk-game-info-dialog.c:470 msgid "_Annotator:" msgstr "Ð_ннотатор:" #: src/gui-gtk/gtk-game-info-dialog.c:474 msgid "_Source:" msgstr "_ИÑточник:" #: src/gui-gtk/gtk-game-info-dialog.c:478 msgid "_Entered by:" msgstr "_Создатель файла:" # «ÐвторÑкие права и благодарноÑти» Ñлишком длинно #: src/gui-gtk/gtk-game-info-dialog.c:488 msgid "Copyright & Credits" msgstr "БлагодарноÑти" #: src/gui-gtk/gtk-game-info-dialog.c:502 msgid "Game Record" msgstr "ЗапиÑÑŒ партии" #: src/gui-gtk/gtk-games.c:39 msgid "_Go" msgstr "_Го" #: src/gui-gtk/gtk-games.c:40 msgid "_Amazons" msgstr "_Ðмазонки" #: src/gui-gtk/gtk-games.c:41 msgid "_Reversi" msgstr "_РеверÑи" #: src/gui-gtk/gtk-games.c:45 msgid "Go Rules" msgstr "Правила го" #: src/gui-gtk/gtk-games.c:46 msgid "Amazons Rules" msgstr "Правила амазонок" #: src/gui-gtk/gtk-games.c:47 msgid "Reversi Rules" msgstr "Правила реверÑи" #: src/gui-gtk/gtk-games.c:180 msgid "Board _size:" msgstr "Размер _доÑки:" #: src/gui-gtk/gtk-goban-window.c:460 msgid "Open" msgstr "Открыть" #: src/gui-gtk/gtk-goban-window.c:460 msgid "Open a game record" msgstr "Открыть запиÑÑŒ партии" #: src/gui-gtk/gtk-goban-window.c:465 msgid "Save" msgstr "Сохранить" #: src/gui-gtk/gtk-goban-window.c:465 msgid "Save the current file" msgstr "Сохранить текущий файл" #: src/gui-gtk/gtk-goban-window.c:470 src/gui-gtk/gtk-goban-window.c:2025 msgid "Find" msgstr "Ðайти" #: src/gui-gtk/gtk-goban-window.c:470 msgid "Search for a string in comments" msgstr "Ðайти Ñтроку в комментариÑÑ…" #: src/gui-gtk/gtk-goban-window.c:475 msgid "Info" msgstr "Инфо" #: src/gui-gtk/gtk-goban-window.c:475 msgid "View and edit game information" msgstr "ПроÑмотреть и редактировать информацию о партии" #: src/gui-gtk/gtk-goban-window.c:481 msgid "Undo" msgstr "Отменить" #: src/gui-gtk/gtk-goban-window.c:481 msgid "Undo the last action" msgstr "Отменить поÑледнее дейÑтвие" #: src/gui-gtk/gtk-goban-window.c:486 msgid "Redo" msgstr "Вернуть" #: src/gui-gtk/gtk-goban-window.c:486 msgid "Redo the last undone action" msgstr "Вернуть поÑледнее отмененное дейÑтвие" #: src/gui-gtk/gtk-goban-window.c:491 msgid "Delete" msgstr "Удалить" #: src/gui-gtk/gtk-goban-window.c:491 msgid "Delete the current node" msgstr "Удалить текущий узел" #: src/gui-gtk/gtk-goban-window.c:497 msgid "Root" msgstr "Корень" #: src/gui-gtk/gtk-goban-window.c:497 msgid "Go to the root node" msgstr "Перейти к корневому узлу" #: src/gui-gtk/gtk-goban-window.c:502 msgid "Back" msgstr "Ðазад" #: src/gui-gtk/gtk-goban-window.c:502 msgid "Go to the previous node" msgstr "Перейти к предыдущему узлу" #: src/gui-gtk/gtk-goban-window.c:507 msgid "Forward" msgstr "Вперед" #: src/gui-gtk/gtk-goban-window.c:507 msgid "Go to the next node" msgstr "Перейти к Ñледующему узлу" #: src/gui-gtk/gtk-goban-window.c:512 msgid "End" msgstr "Конец" #: src/gui-gtk/gtk-goban-window.c:512 msgid "Go to the current variation's last node" msgstr "Перейти к поÑледнему узлу текущего варианта" #: src/gui-gtk/gtk-goban-window.c:518 msgid "Previous" msgstr "Предыдущий" #: src/gui-gtk/gtk-goban-window.c:518 msgid "Switch to the previous variation" msgstr "ПереключитьÑÑ Ð½Ð° предыдущий вариант" #: src/gui-gtk/gtk-goban-window.c:524 msgid "Next" msgstr "Следующий" #: src/gui-gtk/gtk-goban-window.c:524 msgid "Switch to the next variation" msgstr "ПереключитьÑÑ Ð½Ð° Ñледующий вариант" #: src/gui-gtk/gtk-goban-window.c:629 msgid "/_File" msgstr "/_Файл" #: src/gui-gtk/gtk-goban-window.c:630 msgid "/File/_New Game..." msgstr "/Файл/_ÐÐ¾Ð²Ð°Ñ Ð¿Ð°Ñ€Ñ‚Ð¸Ñ…" #: src/gui-gtk/gtk-goban-window.c:633 msgid "/File/Ne_w Game Record..." msgstr "/Файл/Ðов_Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ партии…" #: src/gui-gtk/gtk-goban-window.c:636 src/gui-gtk/gtk-goban-window.c:653 #: src/gui-gtk/gtk-goban-window.c:661 msgid "/File/" msgstr "/Файл/" #: src/gui-gtk/gtk-goban-window.c:638 msgid "/File/_Open..." msgstr "/Файл/_Открыть…" #: src/gui-gtk/gtk-goban-window.c:641 msgid "/File/_Resume Game..." msgstr "/Файл/_Возобновить партию…" #: src/gui-gtk/gtk-goban-window.c:645 msgid "/File/_Export..." msgstr "/Файл/_ЭкÑпортировать…" #: src/gui-gtk/gtk-goban-window.c:646 msgid "/File/Export.../_ASCII Diagram" msgstr "/Файл/ЭкÑпортировать…/ASCII-диаграмма" #: src/gui-gtk/gtk-goban-window.c:649 msgid "/File/Export.../_Sensei's Library Diagram" msgstr "/Файл/ЭкÑпортировать…/Диаграмма «Библиотеки СенÑеÑ»" #: src/gui-gtk/gtk-goban-window.c:655 msgid "/File/_Save" msgstr "/Файл/_Сохранить" #: src/gui-gtk/gtk-goban-window.c:658 msgid "/File/Save _As..." msgstr "/Файл/Сохранить _как…" #: src/gui-gtk/gtk-goban-window.c:663 msgid "/File/_Close" msgstr "/Файл/_Закрыть" #: src/gui-gtk/gtk-goban-window.c:666 msgid "/File/_Quit" msgstr "/Файл/Ð’_ыход" #: src/gui-gtk/gtk-goban-window.c:671 msgid "/_Edit" msgstr "/_Правка" #: src/gui-gtk/gtk-goban-window.c:672 msgid "/Edit/_Undo" msgstr "/Правка/_Отменить" #: src/gui-gtk/gtk-goban-window.c:675 msgid "/Edit/_Redo" msgstr "/Правка/Ве_рнуть" #: src/gui-gtk/gtk-goban-window.c:678 src/gui-gtk/gtk-goban-window.c:695 #: src/gui-gtk/gtk-goban-window.c:739 src/gui-gtk/gtk-goban-window.c:747 #: src/gui-gtk/gtk-goban-window.c:767 src/gui-gtk/gtk-goban-window.c:778 #: src/gui-gtk/gtk-goban-window.c:783 msgid "/Edit/" msgstr "/Правка/" #: src/gui-gtk/gtk-goban-window.c:680 msgid "/Edit/Cu_t" msgstr "/Правка/_Вырезать" #: src/gui-gtk/gtk-goban-window.c:683 msgid "/Edit/_Copy" msgstr "/Правка/_Копировать" #: src/gui-gtk/gtk-goban-window.c:686 msgid "/Edit/_Paste" msgstr "/Правка/Ð’ÑÑ‚_авить" #: src/gui-gtk/gtk-goban-window.c:689 msgid "/Edit/_Delete Node" msgstr "/Правка/_Удалить узел" #: src/gui-gtk/gtk-goban-window.c:692 msgid "/Edit/Delete Node's C_hildren" msgstr "/Правка/Удалить _дочерние узлы" #: src/gui-gtk/gtk-goban-window.c:698 msgid "/Edit/T_ools" msgstr "/Правка/_ИнÑтрументы" #: src/gui-gtk/gtk-goban-window.c:699 msgid "/Edit/Tools/_Move Tool" msgstr "/Правка/ИнÑтрументы/ИнÑтрумент _ходов" #: src/gui-gtk/gtk-goban-window.c:702 msgid "/Edit/Tools/_Setup Tool" msgstr "/Правка/ИнÑтрументы/_УÑтановка позиции" #: src/gui-gtk/gtk-goban-window.c:705 src/gui-gtk/gtk-goban-window.c:722 #: src/gui-gtk/gtk-goban-window.c:730 msgid "/Edit/Tools/" msgstr "/Правка/ИнÑтрументы/" #: src/gui-gtk/gtk-goban-window.c:707 msgid "/Edit/Tools/C_ross Markup" msgstr "/Правка/ИнÑтрументы/Разметка _креÑтиком" #: src/gui-gtk/gtk-goban-window.c:710 msgid "/Edit/Tools/_Circle Markup" msgstr "/Правка/ИнÑтрументы/Разметка к_ружком" #: src/gui-gtk/gtk-goban-window.c:713 msgid "/Edit/Tools/S_quare Markup" msgstr "/Правка/ИнÑтрументы/Разметка к_вадратом" #: src/gui-gtk/gtk-goban-window.c:716 msgid "/Edit/Tools/_Triangle Markup" msgstr "/Правка/ИнÑтрументы/Разметка _треугольником" #: src/gui-gtk/gtk-goban-window.c:719 msgid "/Edit/Tools/S_elected Markup" msgstr "/Правка/ИнÑтрументы/Разметка-в_ыбор" #: src/gui-gtk/gtk-goban-window.c:724 msgid "/Edit/Tools/_Label Tool" msgstr "/Правка/ИнÑтрументы/ИнÑтрумент _надпиÑей" #: src/gui-gtk/gtk-goban-window.c:727 msgid "/Edit/Tools/_Number Tool" msgstr "/Правка/ИнÑтрументы/ИнÑтрумент ну_мерации" #: src/gui-gtk/gtk-goban-window.c:732 msgid "/Edit/Tools/Scori_ng Tool" msgstr "/Правка/Tools/ИнÑтрумент _подÑчета очков" #: src/gui-gtk/gtk-goban-window.c:736 msgid "/Edit/_Add Empty Node" msgstr "/Правка/До_бавить пуÑтой узел" #: src/gui-gtk/gtk-goban-window.c:741 msgid "/Edit/Move _Branch Up" msgstr "/Правка/ПеремеÑтить ветку ввер_Ñ…" #: src/gui-gtk/gtk-goban-window.c:744 msgid "/Edit/Move Branch Do_wn" msgstr "/Правка/ПеремеÑтить ветку вни_з" #: src/gui-gtk/gtk-goban-window.c:749 msgid "/Edit/Edit Node _Name" msgstr "/Правка/Редак_тировать название узла" #: src/gui-gtk/gtk-goban-window.c:752 msgid "/Edit/Set _Move Number" msgstr "/Правка/УÑтановить но_мер хода" #: src/gui-gtk/gtk-goban-window.c:756 msgid "/Edit/P_layer to Move" msgstr "/Правка/С_ледующими ходÑÑ‚" #: src/gui-gtk/gtk-goban-window.c:757 msgid "/Edit/Player to Move/_White" msgstr "/Правка/Следующими ходÑÑ‚/_Белые" #: src/gui-gtk/gtk-goban-window.c:760 msgid "/Edit/Player to Move/_Black" msgstr "/Правка/Следующими ходÑÑ‚/_Черные" #: src/gui-gtk/gtk-goban-window.c:763 msgid "/Edit/Player to Move/By Game _Rules" msgstr "/Правка/Следующими ходÑÑ‚/По _правилам" #: src/gui-gtk/gtk-goban-window.c:769 msgid "/Edit/_Find" msgstr "/Правка/_Ðайти" #: src/gui-gtk/gtk-goban-window.c:772 msgid "/Edit/Find Ne_xt" msgstr "/Правка/Ðайти _Ñледующее" #: src/gui-gtk/gtk-goban-window.c:775 msgid "/Edit/Find Pre_vious" msgstr "/Правка/Ðайти _предыдущее" #: src/gui-gtk/gtk-goban-window.c:780 msgid "/Edit/Game _Information" msgstr "/Правка/Ин_Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ партии" #: src/gui-gtk/gtk-goban-window.c:785 msgid "/Edit/Pr_eferences" msgstr "/Правка/Парам_етры" #: src/gui-gtk/gtk-goban-window.c:790 msgid "/_View" msgstr "/_Вид" #: src/gui-gtk/gtk-goban-window.c:791 msgid "/View/_Main Toolbar" msgstr "/Вид/_Ð“Ð»Ð°Ð²Ð½Ð°Ñ Ð¿Ð°Ð½ÐµÐ»ÑŒ инÑтрументов" #: src/gui-gtk/gtk-goban-window.c:794 msgid "/View/_Editing Toolbar" msgstr "/Вид/Панель инÑтрументов _редактированиÑ" #: src/gui-gtk/gtk-goban-window.c:797 msgid "/View/_Navigation Toolbar" msgstr "/Вид/Панель инÑтрументов _навигации" #: src/gui-gtk/gtk-goban-window.c:800 src/gui-gtk/gtk-goban-window.c:805 #: src/gui-gtk/gtk-goban-window.c:813 msgid "/View/" msgstr "/Вид/" #: src/gui-gtk/gtk-goban-window.c:802 msgid "/View/_Game Action Buttons" msgstr "/Вид/Дополнительные _кнопки" #: src/gui-gtk/gtk-goban-window.c:807 msgid "/View/Game _Tree" msgstr "/Вид/_Дерево партии" #: src/gui-gtk/gtk-goban-window.c:810 msgid "/View/_Recenter on Current Node" msgstr "/Вид/_Центрировать на текущем узле" #: src/gui-gtk/gtk-goban-window.c:815 msgid "/View/_Control Center" msgstr "/Вид/Панель _управлениÑ" #: src/gui-gtk/gtk-goban-window.c:820 msgid "/_Play" msgstr "/_Игра" #: src/gui-gtk/gtk-goban-window.c:821 msgid "/Play/_Pass" msgstr "/Игра/_ПаÑÑ" #: src/gui-gtk/gtk-goban-window.c:824 src/gui-gtk/gtk-goban-window.c:829 msgid "/Play/" msgstr "/Игра/" #: src/gui-gtk/gtk-goban-window.c:826 msgid "/Play/_Resign" msgstr "/Игра/_СдатьÑÑ" #: src/gui-gtk/gtk-goban-window.c:831 msgid "/Play/_Adjourn Game" msgstr "/Play/_Отложить партию" #: src/gui-gtk/gtk-goban-window.c:836 msgid "/_Go" msgstr "/Перей_ти" #: src/gui-gtk/gtk-goban-window.c:837 msgid "/Go/_Previous Node" msgstr "/Перейти/_Предыдущий узел" #: src/gui-gtk/gtk-goban-window.c:840 msgid "/Go/_Next Node" msgstr "/Перейти/_Следующий узел" #: src/gui-gtk/gtk-goban-window.c:843 msgid "/Go/Ten Nodes _Backward" msgstr "/Перейти/ДеÑÑть узлов _вперед" #: src/gui-gtk/gtk-goban-window.c:846 msgid "/Go/Ten Nodes _Forward" msgstr "/Перейти/ДеÑÑть узлов _назад" #: src/gui-gtk/gtk-goban-window.c:849 src/gui-gtk/gtk-goban-window.c:857 #: src/gui-gtk/gtk-goban-window.c:867 msgid "/Go/" msgstr "/Перейти/" #: src/gui-gtk/gtk-goban-window.c:851 msgid "/Go/_Root Node" msgstr "/Перейти/_Корневой узел" #: src/gui-gtk/gtk-goban-window.c:854 msgid "/Go/Variation _Last Node" msgstr "/Перейти/ПоÑ_ледний узел варианта" #: src/gui-gtk/gtk-goban-window.c:859 msgid "/Go/Pre_vious Variation" msgstr "/Перейти/Пр_едыдущий вариант" #: src/gui-gtk/gtk-goban-window.c:862 msgid "/Go/Ne_xt Variation" msgstr "/Go/Сле_дующий вариант" #: src/gui-gtk/gtk-goban-window.c:868 msgid "/Go/_Go to Named Node..." msgstr "/Go/Перейти к _именованному узлу…" #: src/gui-gtk/gtk-goban-window.c:874 msgid "/_Help" msgstr "/_Справка" #: src/gui-gtk/gtk-goban-window.c:875 msgid "/Help/_Contents" msgstr "/Справка/_Содержание" #: src/gui-gtk/gtk-goban-window.c:878 msgid "/Help/_About" msgstr "/Справка/_О программе" #: src/gui-gtk/gtk-goban-window.c:884 msgid "/Move Tool" msgstr "/ИнÑтрумент ходов" #: src/gui-gtk/gtk-goban-window.c:885 msgid "/Setup Tool" msgstr "/УÑтановка позиции" #: src/gui-gtk/gtk-goban-window.c:888 msgid "/Cross Markup" msgstr "/Разметка креÑтиком" #: src/gui-gtk/gtk-goban-window.c:889 msgid "/Circle Markup" msgstr "/Разметка кружочком" #: src/gui-gtk/gtk-goban-window.c:890 msgid "/Square Markup" msgstr "/Разметка квадратом" #: src/gui-gtk/gtk-goban-window.c:891 msgid "/Triangle Markup" msgstr "/Разметка треугольником" #: src/gui-gtk/gtk-goban-window.c:892 msgid "/Selected Markup" msgstr "/Разметка-выбор" #: src/gui-gtk/gtk-goban-window.c:895 msgid "/Label Tool" msgstr "/ИнÑтрумент надпиÑей" #: src/gui-gtk/gtk-goban-window.c:896 msgid "/Number Tool" msgstr "/ИнÑтрумент нумерации" #: src/gui-gtk/gtk-goban-window.c:899 msgid "/Scoring Tool" msgstr "/ИнÑтрумент подÑчета очков" #: src/gui-gtk/gtk-goban-window.c:964 msgid "Black" msgstr "Черные" #: src/gui-gtk/gtk-goban-window.c:964 msgid "White" msgstr "Белые" #: src/gui-gtk/gtk-goban-window.c:992 msgid "Pass" msgstr "ПаÑÑ" #: src/gui-gtk/gtk-goban-window.c:998 msgid "Resign" msgstr "СдатьÑÑ" #: src/gui-gtk/gtk-goban-window.c:1438 #, c-format msgid "Save changes to game record `%s' before closing?" msgstr "Сохранить Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð² запиÑи партии «%s» перед закрытием?" #: src/gui-gtk/gtk-goban-window.c:1447 msgid "Save changes to the untitled game record before closing?" msgstr "Сохранить Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð² неименованной запиÑи партии перед закрытием?" #. TRANSLATORS: Width of this string in default font is used to #. determine the minimal width of the right board window side. #: src/gui-gtk/gtk-goban-window.c:1522 msgid "A good width for the right side to have." msgstr "Вполне подходÑÑ‰Ð°Ñ ÑˆÐ¸Ñ€Ð¸Ð½Ð° Ð´Ð»Ñ Ð¿Ñ€Ð°Ð²Ð¾Ð¹ колонки." #. TRANSLATORS: It can never be 1 stone, always at least 2. #: src/gui-gtk/gtk-goban-window.c:1582 #, c-format msgid "" "Please set up %d (or less)\n" "stone of free handicap" msgid_plural "" "Please set up %d (or less)\n" "stones of free handicap" msgstr[0] "" "ПожалуйÑта, размеÑтите %d (или меньше)\n" "камень Ñвободного гандикапа" msgstr[1] "" "ПожалуйÑта, размеÑтите %d (или меньше)\n" "ÐºÐ°Ð¼Ð½Ñ Ñвободного гандикапа" msgstr[2] "" "ПожалуйÑта, размеÑтите %d (или меньше)\n" "камней Ñвободного гандикапа" #: src/gui-gtk/gtk-goban-window.c:1774 msgid "Adjourn & Save As..." msgstr "Отложить партию и Ñохранить как…" #: src/gui-gtk/gtk-goban-window.c:1774 msgid "Save As..." msgstr "Сохранить как…" #: src/gui-gtk/gtk-goban-window.c:1923 #, c-format msgid "Error saving to file `%s'" msgstr "Ошибка при запиÑи файла «%s»" #: src/gui-gtk/gtk-goban-window.c:1937 msgid "" "You can later resume the game by pressing the `Resume Game' button in Quarry " "Control Center, or selecting `Resume Game' item from the `File' menu." msgstr "" "Ð’Ñ‹ можете вернутьÑÑ Ðº игре, нажав кнопку «Возобновить партию» в Панели " "ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Quarry или выбрав пункт «Возобновить партию» из меню «Файл»." #: src/gui-gtk/gtk-goban-window.c:1943 #, c-format msgid "The game is adjourned and saved in file `%s'" msgstr "ÐŸÐ°Ñ€Ñ‚Ð¸Ñ Ð¾Ñ‚Ð»Ð¾Ð¶ÐµÐ½Ð° и Ñохранена в файле «%s»" #: src/gui-gtk/gtk-goban-window.c:1962 msgid "ASCII diagram has been exported to clipboard" msgstr "ASCII-диаграмма ÑкÑпортирована в буфер обмена" #: src/gui-gtk/gtk-goban-window.c:1975 msgid "Sensei's Library diagram has been exported to clipboard" msgstr "Диаграмма «Библиотеки СенÑеÑ» ÑкÑпортирована в буфер обмена" #: src/gui-gtk/gtk-goban-window.c:1990 msgid "" "You can usually paste the diagram in another application using `Ctrl+C' key " "combination or by selecting appropriate menu item." msgstr "" "Обычно диаграмму можно вÑтавить в другом приложении, нажав «Ctrl+C» или " "выбрав ÑоответÑтвующий пункт меню." #: src/gui-gtk/gtk-goban-window.c:2446 msgid "Sorry, there are no named nodes in this game tree" msgstr "Извините, в Ñтом дереве нет именованных узлов" #: src/gui-gtk/gtk-goban-window.c:2470 msgid "A GUI program for Go, Amazons and Reversi board games" msgstr "УниверÑальный Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ Ð´Ð»Ñ Ð³Ð¾, амазонок и реверÑи" #: src/gui-gtk/gtk-goban-window.c:2472 msgid "Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev and others" msgstr "Copyright © 2003, 2004, 2005, 2006 Павел Погонышев и другие" #: src/gui-gtk/gtk-goban-window.c:2488 msgid "About Quarry" msgstr "О программе Quarry" #: src/gui-gtk/gtk-goban-window.c:2931 msgid "Really resign this game?" msgstr "Ð’Ñ‹ дейÑтвительно хотите Ñдать Ñту партию?" #: src/gui-gtk/gtk-goban-window.c:2935 msgid "_Resign" msgstr "_СдатьÑÑ" #: src/gui-gtk/gtk-goban-window.c:3524 msgid "Edit Board Label" msgstr "Редактирование надпиÑи" #: src/gui-gtk/gtk-goban-window.c:3527 msgid "Add Board Label" msgstr "Добавление надпиÑи" #: src/gui-gtk/gtk-goban-window.c:4026 #, c-format msgid "%s (W) vs. %s" msgstr "%s (б) против %s" #: src/gui-gtk/gtk-goban-window.c:4050 msgid "Unnamed Game" msgstr "БезымÑÐ½Ð½Ð°Ñ Ð¿Ð°Ñ€Ñ‚Ð¸Ñ" #: src/gui-gtk/gtk-goban-window.c:4055 msgid "modified" msgstr "изменен" #: src/gui-gtk/gtk-goban-window.c:4088 msgid "[unknown]" msgstr "[неизвеÑтно]" #: src/gui-gtk/gtk-goban-window.c:4121 src/gui-gtk/gtk-goban-window.c:4126 #, c-format msgid "%d capture" msgid_plural "%d captures" msgstr[0] "%d пленник" msgstr[1] "%d пленника" msgstr[2] "%d пленников" #: src/gui-gtk/gtk-goban-window.c:4136 #, c-format msgid "%s %s %.*f komi" msgstr "%s %s %.*f коми" #: src/gui-gtk/gtk-goban-window.c:4147 #, c-format msgid "%s %s %d komi" msgid_plural "%s %s %d komi" msgstr[0] "%s %s %d коми" msgstr[1] "%s %s %d коми" msgstr[2] "%s %s %d коми" #: src/gui-gtk/gtk-goban-window.c:4163 src/gui-gtk/gtk-goban-window.c:4166 #, c-format msgid "%d disk" msgid_plural "%d disks" msgstr[0] "%d диÑк" msgstr[1] "%d диÑка" msgstr[2] "%d диÑков" #: src/gui-gtk/gtk-goban-window.c:4197 #, c-format msgid "Move %d: " msgstr "Ход %d: " #: src/gui-gtk/gtk-goban-window.c:4201 #, c-format msgid "Last move: %u, " msgstr "ПоÑледний ход: %u, " #. TRANSLATORS: This is an #. abbreviation of `Black'. #: src/gui-gtk/gtk-goban-window.c:4208 msgid "B " msgstr "Ч " #. TRANSLATORS: This is an #. abbreviation of `White'. #: src/gui-gtk/gtk-goban-window.c:4211 msgid "W " msgstr "Б " #: src/gui-gtk/gtk-goban-window.c:4212 msgid "pass" msgstr "паÑÑ" #: src/gui-gtk/gtk-goban-window.c:4215 msgid "Game beginning" msgstr "Ðачало партии" #: src/gui-gtk/gtk-goban-window.c:4233 msgid "; black to play" msgstr "; ходÑÑ‚ черные" #: src/gui-gtk/gtk-goban-window.c:4233 msgid "; white to play" msgstr "; ходÑÑ‚ белые" #: src/gui-gtk/gtk-goban-window.c:4236 msgid "; game over" msgstr "; конец игры" #: src/gui-gtk/gtk-goban-window.c:4243 msgid "Black wins" msgstr "Черные выиграли" #: src/gui-gtk/gtk-goban-window.c:4246 msgid "White wins" msgstr "Белые выиграли" #: src/gui-gtk/gtk-goban-window.c:4250 msgid "Black wins by forfeit" msgstr "Черным заÑчитано техничеÑкое поражение" #: src/gui-gtk/gtk-goban-window.c:4253 msgid "White wins by forfeit" msgstr "Белым заÑчитано техничеÑкое поражение" #: src/gui-gtk/gtk-goban-window.c:4257 msgid "White resigns" msgstr "Белые ÑдалиÑÑŒ" #: src/gui-gtk/gtk-goban-window.c:4260 msgid "Black resigns" msgstr "Черные ÑдалиÑÑŒ" #: src/gui-gtk/gtk-goban-window.c:4272 msgid "White runs out of time and loses" msgstr "Белые проиграли по времени" #: src/gui-gtk/gtk-goban-window.c:4276 msgid "Black runs out of time and loses" msgstr "Черные проиграли по времени" #: src/gui-gtk/gtk-goban-window.c:4280 msgid "Game is draw" msgstr "ÐичьÑ" #: src/gui-gtk/gtk-goban-window.c:4499 msgid "By Game _Rules (Game Over)" msgstr "По правилам (конец игры)" #: src/gui-gtk/gtk-goban-window.c:4503 msgid "By Game _Rules (Black)" msgstr "По правилам (черные)" #: src/gui-gtk/gtk-goban-window.c:4507 msgid "By Game _Rules (White)" msgstr "По правилам (белые)" #: src/gui-gtk/gtk-goban-window.c:4551 msgid "insert node name here" msgstr "вÑтавьте здеÑÑŒ название узла" #: src/gui-gtk/gtk-goban-window.c:4952 msgid "Set Move Number" msgstr "УÑтановить номер хода" #. TRANSLATORS: Note that game name will be in `normal' form. #: src/gui-gtk/gtk-goban-window.c:5062 #, c-format msgid "" "GTP engine `%s' reported it could handle %s game, but failed to initialize " "itself for it" msgstr "" "GTP-движок «%s» Ñказал, что поддерживает игру %s, но не Ñмог " "инициализировать ÑÐµÐ±Ñ Ð´Ð»Ñ Ñтой игры" #: src/gui-gtk/gtk-goban-window.c:5070 #, c-format msgid "GTP engine `%s' cannot handle %dx%d board size, sorry" msgstr "GTP-движок «%s» не поддерживает размер доÑки %d×%d, извините" #: src/gui-gtk/gtk-goban-window.c:5080 #, c-format msgid "GTP engine `%s' failed to clean the board" msgstr "GTP-движок «%s» не Ñмог Ñмог очиÑтить доÑку" #: src/gui-gtk/gtk-goban-window.c:5086 #, c-format msgid "" "GTP engine `%s' failed to set initial time limits (it could ignore them, but " "not fail)" msgstr "" "GTP-движок «%s» не Ñмог уÑтановить начальные Ð¾Ð³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð¸Ñ Ð¿Ð¾ времени (он мог " "игнорировать их, но не Ñообщить об ошибке)" #: src/gui-gtk/gtk-goban-window.c:5094 #, c-format msgid "GTP engine `%s' failed to set handicap stones on board" msgstr "GTP-движок «%s» не Ñмог уÑтановить камни гандикапа на доÑке" #: src/gui-gtk/gtk-goban-window.c:5108 msgid "This is an engine error. You may want to report it to engine authors." msgstr "Это ошибка GTP-движка. Ð’Ñ‹ можете Ñообщить о ней его авторам." #: src/gui-gtk/gtk-goban-window.c:5392 msgid "GTP engine is scoring..." msgstr "GTP-движок подÑчитывает результат партии…" #: src/gui-gtk/gtk-goban-window.c:5771 msgid "" "Unable to paste game record fragment from clipboard since it is not intended " "for pasting" msgstr "" "Ðевозможно вÑтавить фрагмент запиÑи партии из буфера обмена, так как он Ð´Ð»Ñ " "Ñтого не предназначен" #: src/gui-gtk/gtk-goban-window.c:5774 msgid "" "Clipboard SGF probably contains more than one game tree or not a single " "child of the root of the only game tree." msgstr "" "SGF-фрагмент из буфера обмена, вероÑтно, Ñодержит более одного дерева игры, " "или не одного наÑледника у ÐºÐ¾Ñ€Ð½Ñ ÐµÐ´Ð¸Ð½Ñтвенного дерева." #: src/gui-gtk/gtk-goban-window.c:5778 msgid "Unable to paste game record fragment from clipboard" msgstr "Ðевозможно вÑтавить фрагмент запиÑи партии из буфера обмена" #. TRANSLATORS: This message is shown if you e.g. copy a part of #. 13x13 game tree and try to paste it into a 19x19 game tree; or #. copy a part of a Reversi game tree and try to paste it into a #. Go game tree. #: src/gui-gtk/gtk-goban-window.c:5784 msgid "Clipboard game record fragment must be of different game or board size." msgstr "" "Фрагмент запиÑи партии в буфере обмена, вероÑтно, был Ñоздан Ð´Ð»Ñ Ð´Ñ€ÑƒÐ³Ð¾Ð¹ игры " "или размера доÑки." #: src/gui-gtk/gtk-goban-window.c:5788 msgid "Clipboard contains an invalid game record fragment (SGF)" msgstr "Буфер обмена Ñодержит неправильный фрагмент запиÑи партии (SGF)" #: src/gui-gtk/gtk-goban-window.c:5937 msgid "" "Please select dead stones\n" "to score the game" msgstr "" "ПожалуйÑта, выберите мертвые камни\n" "Ð´Ð»Ñ Ð¿Ð¾Ð´Ñчета очков" #: src/gui-gtk/gtk-go-to-named-node-dialog.c:135 msgid "Go to Named Node" msgstr "Перейти к именованному узлу" #: src/gui-gtk/gtk-go-to-named-node-dialog.c:150 msgid "Node _name:" msgstr "_Ðазвание узла:" #: src/gui-gtk/gtk-go-to-named-node-dialog.c:156 msgid "Node comment:" msgstr "Комментарий узла:" #: src/gui-gtk/gtk-go-to-named-node-dialog.c:331 msgid "comment|Empty" msgstr "ОтÑутÑтвует" #: src/gui-gtk/gtk-go-to-named-node-dialog.c:334 msgid "There is no such node" msgstr "Узла Ñ Ñ‚Ð°ÐºÐ¸Ð¼ названием нет в дереве" #: src/gui-gtk/gtk-gtp-client-interface.c:282 msgid "Engine hung up" msgstr "Движок отключилÑÑ Ð¿Ð¾ ÑобÑтвенной инициативе" #: src/gui-gtk/gtk-gtp-client-interface.c:391 msgid "* ERROR: wrong response format\n" msgstr "* ОШИБКÐ: неверный формат ответа\n" #: src/gui-gtk/gtk-gtp-client-interface.c:395 msgid "* WARNING: unexpected response:\n" msgstr "* ПРЕДУПРЕЖДЕÐИЕ: неожиданный ответ\n" #: src/gui-gtk/gtk-gtp-client-interface.c:399 msgid "* ERROR: unrecognized response line:\n" msgstr "* ОШИБКÐ: нераÑÐ¿Ð¾Ð·Ð½Ð°Ð½Ð½Ð°Ñ Ñтрока ответа:\n" #: src/gui-gtk/gtk-gtp-client-interface.c:404 #, c-format msgid "* ERROR: mismatched ID (%d expected):\n" msgstr "* ОШИБКÐ: неÑоответÑтвующий идентификатор (ожидалоÑÑŒ %d):\n" #: src/gui-gtk/gtk-gtp-client-interface.c:408 msgid "* ERROR: unexpected ID in response (the command had none):\n" msgstr "" "* ОШИБКÐ: неожиданный идентификатор в ответе (в команде не было " "идентификатора):\n" #. TRANSLATORS: Don't put ellipsis here, this string will most #. often go to fixed-width font terminals. #: src/gui-gtk/gtk-gtp-client-interface.c:415 msgid "* WARNING: future GTP version, I don't know about it...\n" msgstr "* ПРЕДУПРЕЖДЕÐИЕ: верÑÐ¸Ñ GTP из будущего, Ñ Ð¾ такой не знаю...\n" #: src/gui-gtk/gtk-new-game-dialog.c:98 msgid "" "Note that most GTP engines support only one game. Hence certain game / " "computer player combinations may be not possible to play." msgstr "" "БольшинÑтво GTP-движков поддерживают только одну игру. ПоÑтому, некоторые " "комбинации игр и компьютерных оппонентов недоÑтупны." #: src/gui-gtk/gtk-new-game-dialog.c:102 msgid "Fi_xed handicap:" msgstr "Стандартный _гандикап:" #: src/gui-gtk/gtk-new-game-dialog.c:102 msgid "_Free handicap:" msgstr "Сво_бодный гандикап:" #: src/gui-gtk/gtk-new-game-dialog.c:105 msgid "No limit" msgstr "Без ограничениÑ" #: src/gui-gtk/gtk-new-game-dialog.c:105 msgid "Limited time for entire game" msgstr "Ограниченное Ð²Ñ€ÐµÐ¼Ñ Ð½Ð° вÑÑŽ партию" #: src/gui-gtk/gtk-new-game-dialog.c:106 msgid "Limited time per move" msgstr "Ограниченное Ð²Ñ€ÐµÐ¼Ñ Ð½Ð° ход" #: src/gui-gtk/gtk-new-game-dialog.c:106 msgid "Canadian overtime" msgstr "КанадÑкое дополнительное времÑ" #: src/gui-gtk/gtk-new-game-dialog.c:124 msgid "New Game" msgstr "ÐÐ¾Ð²Ð°Ñ Ð¿Ð°Ñ€Ñ‚Ð¸Ñ" #: src/gui-gtk/gtk-new-game-dialog.c:167 #: src/gui-gtk/gtk-new-game-record-dialog.c:132 msgid "Game" msgstr "Игра" #: src/gui-gtk/gtk-new-game-dialog.c:173 #: src/gui-gtk/gtk-resume-game-dialog.c:307 msgid "Hu_man" msgstr "Че_ловек" #: src/gui-gtk/gtk-new-game-dialog.c:173 #: src/gui-gtk/gtk-resume-game-dialog.c:308 msgid "Com_puter" msgstr "_Компьютер" #: src/gui-gtk/gtk-new-game-dialog.c:174 #: src/gui-gtk/gtk-resume-game-dialog.c:308 msgid "H_uman" msgstr "_Человек" #: src/gui-gtk/gtk-new-game-dialog.c:174 msgid "C_omputer" msgstr "_Компьютер" #: src/gui-gtk/gtk-new-game-dialog.c:238 msgid "Manage _Engine List" msgstr "Редактировать ÑпиÑок д_вижков" #: src/gui-gtk/gtk-new-game-dialog.c:258 msgid "_Swap" msgstr "_ПереÑтавить" #: src/gui-gtk/gtk-new-game-dialog.c:287 msgid "Game & Players" msgstr "Игра и Ñоперники" #: src/gui-gtk/gtk-new-game-dialog.c:362 msgid "Time control _type:" msgstr "Тип _ограничениÑ:" #: src/gui-gtk/gtk-new-game-dialog.c:384 msgid "Time Limit" msgstr "Ограничение по времени" #: src/gui-gtk/gtk-new-game-dialog.c:387 msgid "K_eep track of total time" msgstr "_ПодÑчитывать потраченное времÑ" #: src/gui-gtk/gtk-new-game-dialog.c:407 msgid "Time _limit for game:" msgstr "Огра_ничение на игру:" #: src/gui-gtk/gtk-new-game-dialog.c:413 msgid "(per player)" msgstr "(Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ из игроков)" #: src/gui-gtk/gtk-new-game-dialog.c:427 msgid "Time _limit for move:" msgstr "Ограничение на _ход:" #: src/gui-gtk/gtk-new-game-dialog.c:461 msgid "_Overtime period length:" msgstr "_Период дополнительного времени:" #: src/gui-gtk/gtk-new-game-dialog.c:478 msgid "Mo_ves per overtime:" msgstr "_Ходов на один период:" #: src/gui-gtk/gtk-new-game-record-dialog.c:119 msgid "New Game Record" msgstr "ÐÐ¾Ð²Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ партии" #: src/gui-gtk/gtk-new-game-record-dialog.c:189 msgid "_Place stones" msgstr "Раз_меÑтить камни" #: src/gui-gtk/gtk-new-game-record-dialog.c:265 msgid "_White player:" msgstr "_Белые:" #: src/gui-gtk/gtk-new-game-record-dialog.c:276 msgid "_Black player:" msgstr "_Черные:" #: src/gui-gtk/gtk-new-game-record-dialog.c:287 msgid "Game _name:" msgstr "_Ðазвание партии:" #: src/gui-gtk/gtk-new-game-record-dialog.c:300 msgid "" "You can always change and expand game information later. Just choose `Edit/" "Game Information' menu item or press `Info' button on the main toolbar." msgstr "" "Ð’Ñ‹ вÑегда можете изменить и дополнить Ñту информацию в дальнейшем. ПроÑто " "выберите Ñлемент меню «Правка/Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ партии» или нажмите кнопку «Инфо» " "на главной панели инÑтрументов." #: src/gui-gtk/gtk-new-game-record-dialog.c:310 #: src/gui-gtk/gtk-resume-game-dialog.c:227 msgid "Short Game Information" msgstr "ÐšÑ€Ð°Ñ‚ÐºÐ°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ партии" #: src/gui-gtk/gtk-parser-interface.c:58 #, c-format msgid "Error reading file `%s'" msgstr "Ошибка при чтении файла «%s»" #: src/gui-gtk/gtk-parser-interface.c:60 #, c-format msgid "File `%s' doesn't appear to be a valid SGF file" msgstr "Файл «%s» не ÑвлÑетÑÑ Ð¿Ñ€Ð°Ð²Ð¸Ð»ÑŒÐ½Ñ‹Ð¼ SGF-файлом" #: src/gui-gtk/gtk-parser-interface.c:63 msgid "" "Please check that the file exists and its permission allow you to read it." msgstr "" "ПожалуйÑта, проверьте, что файл ÑущеÑтвует, и права доÑтупа к нему разрешают " "вам чтение файла." #: src/gui-gtk/gtk-parser-interface.c:67 msgid "" "Quarry uses SGF file format for storing game records. SGF files would " "normally have `sgf' extension, but that's not necessarily true. Please make " "sure you select a proper SGF file." msgstr "" "Ð”Ð»Ñ Ñ…Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ Ð¿Ð°Ñ€Ñ‚Ð¸Ð¹ Quarry иÑпользует формат файлов SGF. SGF-файлы обычно " "имеют раÑширение «sgf», но Ñто необÑзательно. ПожалуйÑта, убедитеÑÑŒ, что вы " "выбрали правильный SGF-файл." #: src/gui-gtk/gtk-parser-interface.c:101 msgid "Open SGF File..." msgstr "Открыть SGF-файл…" #: src/gui-gtk/gtk-parser-interface.c:192 #, c-format msgid "Parsing file `%s'..." msgstr "Разбор файла «%s»…" #: src/gui-gtk/gtk-preferences.c:431 msgid "General" msgstr "Общие" #: src/gui-gtk/gtk-preferences.c:434 msgid "Interface" msgstr "ИнтерфейÑ" #: src/gui-gtk/gtk-preferences.c:435 msgid "General Interface" msgstr "Общие наÑтройки интерфейÑа" #: src/gui-gtk/gtk-preferences.c:437 msgid "Editing & Viewing" msgstr "Редактирование и проÑмотр" #: src/gui-gtk/gtk-preferences.c:440 src/gui-gtk/gtk-preferences.c:441 msgid "Game Tree" msgstr "Дерево партии" #: src/gui-gtk/gtk-preferences.c:444 msgid "GTP" msgstr "GTP" #: src/gui-gtk/gtk-preferences.c:447 src/gui-gtk/gtk-preferences.c:448 msgid "GTP Engines" msgstr "GTP-движки" #: src/gui-gtk/gtk-preferences.c:451 msgid "Game Records (SGF)" msgstr "ЗапиÑи партий (SGF)" #: src/gui-gtk/gtk-preferences.c:454 msgid "Saving" msgstr "Сохранение" #: src/gui-gtk/gtk-preferences.c:455 msgid "Saving Game Records" msgstr "Сохранение партий" #: src/gui-gtk/gtk-preferences.c:458 msgid "Board Appearance" msgstr "Внешний вид доÑки" #: src/gui-gtk/gtk-preferences.c:462 msgid "Go Board Appearance" msgstr "Внешний вид гобана" #: src/gui-gtk/gtk-preferences.c:465 msgid "Amazons Board Appearance" msgstr "Внешний вид доÑки Ð´Ð»Ñ Ð°Ð¼Ð°Ð·Ð¾Ð½Ð¾Ðº" #: src/gui-gtk/gtk-preferences.c:468 msgid "Reversi Board Appearance" msgstr "Внешний вид доÑки Ð´Ð»Ñ Ñ€ÐµÐ²ÐµÑ€Ñи" #: src/gui-gtk/gtk-preferences.c:478 msgid "Preferences" msgstr "ÐаÑтройки" #: src/gui-gtk/gtk-preferences.c:515 msgid "Categor_y:" msgstr "Категори_Ñ:" #: src/gui-gtk/gtk-preferences.c:641 msgid "Use _newer (GTK+ 2.4) file chooser" msgstr "ИÑпользовать но_вый (GTK+ 2.4) диалог выбора файлов" #: src/gui-gtk/gtk-preferences.c:642 msgid "Use _old-style file selection dialog" msgstr "ИÑпользовать Ñ_тарый диалог выбора файлов" #: src/gui-gtk/gtk-preferences.c:672 msgid "File Chooser Dialog Style" msgstr "Стиль диалога выбора файлов" #: src/gui-gtk/gtk-preferences.c:688 msgid "_Main toolbar style:" msgstr "Стиль _главной панели инÑтрументов:" #: src/gui-gtk/gtk-preferences.c:692 msgid "_Editing toolbar style:" msgstr "Стиль панели инÑтрументов _редактированиÑ:" #: src/gui-gtk/gtk-preferences.c:696 msgid "N_avigation toolbar style:" msgstr "Стиль панели инÑтрументов _навигации:" #: src/gui-gtk/gtk-preferences.c:705 msgid "Toolbar Styles" msgstr "Стили панелей инÑтрументов" #: src/gui-gtk/gtk-preferences.c:725 msgid "Desktop default" msgstr "По умолчанию" #: src/gui-gtk/gtk-preferences.c:726 msgid "Text below icons" msgstr "ТекÑÑ‚ под значками" #: src/gui-gtk/gtk-preferences.c:732 msgid "Text beside important icons" msgstr "ТекÑÑ‚ Ñ€Ñдом Ñо значками" #: src/gui-gtk/gtk-preferences.c:735 msgid "Icons only" msgstr "Только значки" #: src/gui-gtk/gtk-preferences.c:736 msgid "Text only" msgstr "Только текÑÑ‚" #: src/gui-gtk/gtk-preferences.c:792 msgid "Show" msgstr "Показывать" #: src/gui-gtk/gtk-preferences.c:799 msgid "Name" msgstr "Ðазвание" #: src/gui-gtk/gtk-preferences.c:808 msgid "_List of GTP engines:" msgstr "С_пиÑок GTP-движков:" #: src/gui-gtk/gtk-preferences.c:856 msgid "Name:" msgstr "Ðазвание:" #: src/gui-gtk/gtk-preferences.c:865 msgid "Version:" msgstr "ВерÑиÑ:" #: src/gui-gtk/gtk-preferences.c:875 src/gui-gtk/gtk-preferences.c:1630 msgid "Supported game:" msgstr "ÐŸÐ¾Ð´Ð´ÐµÑ€Ð¶Ð¸Ð²Ð°ÐµÐ¼Ð°Ñ Ð¸Ð³Ñ€Ð°:" #: src/gui-gtk/gtk-preferences.c:889 msgid "Command line:" msgstr "ÐšÐ¾Ð¼Ð°Ð½Ð´Ð½Ð°Ñ Ñтрока:" #: src/gui-gtk/gtk-preferences.c:914 msgid "GTP Engine Information" msgstr "Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ GTP-движке" #: src/gui-gtk/gtk-preferences.c:935 msgid "_Always" msgstr "_Ð’Ñегда" #: src/gui-gtk/gtk-preferences.c:935 msgid "A_utomatically" msgstr "_ÐвтоматичеÑки" #: src/gui-gtk/gtk-preferences.c:935 msgid "_Never" msgstr "_Ðикогда" #: src/gui-gtk/gtk-preferences.c:937 msgid "Al_ways" msgstr "Ð’Ñе_гда" #: src/gui-gtk/gtk-preferences.c:937 msgid "Aut_omatically" msgstr "Ðв_томатичеÑки" #: src/gui-gtk/gtk-preferences.c:937 msgid "Ne_ver" msgstr "Ðи_когда" #: src/gui-gtk/gtk-preferences.c:939 msgid "Scroll _minimal distance" msgstr "Отматывать на _минимальныое раÑÑтоÑние" #: src/gui-gtk/gtk-preferences.c:940 msgid "_Recenter view on the current node" msgstr "_Центрировать на текущем узле" #: src/gui-gtk/gtk-preferences.c:943 msgid "" "In automatic mode the game tree is shown only if it has at least one " "variation. In any case, you can show/hide game tree in each window " "separately." msgstr "" "Ð’ автоматичеÑком режиме дерево показываетÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ еÑли в нем еÑть хоть одна " "ветвь кроме оÑновной. Ð’ любом Ñлучае вы можете показывать/прÑтать дерево " "отдельно в каждом окне." #: src/gui-gtk/gtk-preferences.c:947 msgid "" "In automatic mode the game tree view scrolls to show the current node only " "if it has been showing current node before. I.e. unless you scrolled it away " "manually." msgstr "" "Ð’ автоматичеÑком режиме панель Ñ Ð´ÐµÑ€ÐµÐ²Ð¾Ð¼ перематываетÑÑ Ðº новому текущему " "узлу только еÑли она показывала текущий узел и раньше, то еÑть, еÑли вы не " "перемотали ее в другое меÑто дерева вручную." #: src/gui-gtk/gtk-preferences.c:992 msgid "Show Game Tree" msgstr "Показывать дерево партии" #: src/gui-gtk/gtk-preferences.c:1039 msgid "Track Tree's Current Node" msgstr "ОтÑлеживать текущий узел дерева" #: src/gui-gtk/gtk-preferences.c:1042 msgid "Show _tooltips" msgstr "Показывать вÑплывающие _подÑказки" #: src/gui-gtk/gtk-preferences.c:1049 msgid "Tooltips" msgstr "ПодÑказки" #: src/gui-gtk/gtk-preferences.c:1065 msgid "Always use _UTF-8 (recommended)" msgstr "_Ð’Ñегда иÑпользовать UTF-8 (рекоммендуетÑÑ)" #: src/gui-gtk/gtk-preferences.c:1066 msgid "Preserve _original encoding" msgstr "ИÑпользовать _оригинальную кодировку" #: src/gui-gtk/gtk-preferences.c:1068 msgid "" "Note that many characters cannot be represented in non-UTF-8 encodings and " "thus some information may be lost if you use them. Quarry also works fastest " "with UTF-8; this may be important if you have very large SGF files." msgstr "" "Заметьте, что многие Ñимволы не могут быть предÑтавлены в кодировках, " "отличных от UTF-8. ПоÑтому, чаÑть информации может быть потерÑна при " "Ñохранении Ñ Ð¸Ñпользованием таких кодировок. Кроме того, Quarry быÑтрее " "вÑего работает именно Ñ UTF-8, что может быть немаловажно при работе Ñ Ð¾Ñ‡ÐµÐ½ÑŒ " "большими SGF-файлами." #: src/gui-gtk/gtk-preferences.c:1093 msgid "Encoding" msgstr "Кодировка" #: src/gui-gtk/gtk-preferences.c:1103 msgid "_Relative to stone size" msgstr "_ОтноÑительно размера камней" #: src/gui-gtk/gtk-preferences.c:1104 msgid "On _white stones:" msgstr "Ðа _белых камнÑÑ…:" #: src/gui-gtk/gtk-preferences.c:1105 msgid "On _black stones:" msgstr "Ðа _черных камнÑÑ…:" #: src/gui-gtk/gtk-preferences.c:1106 msgid "On _empty intersections:" msgstr "Ðа _пуÑтых переÑечениÑÑ…:" #: src/gui-gtk/gtk-preferences.c:1120 msgid "_Relative to amazon size" msgstr "_ОтноÑительно размера «амазонок»" #: src/gui-gtk/gtk-preferences.c:1121 msgid "On _white amazons:" msgstr "Ðа _белых «амазонках»:" #: src/gui-gtk/gtk-preferences.c:1122 msgid "On _black amazons:" msgstr "Ðа _черных «амазонках»:" #: src/gui-gtk/gtk-preferences.c:1123 src/gui-gtk/gtk-preferences.c:1182 msgid "On _empty fields:" msgstr "Ðа _пуÑтых клетках:" #: src/gui-gtk/gtk-preferences.c:1142 msgid "Pick Checkerboard Pattern Color" msgstr "Выберите цвет шахматного риÑунка" #: src/gui-gtk/gtk-preferences.c:1151 msgid "Checkerboard _pattern color:" msgstr "Цвет _шахматного риÑунка:" #: src/gui-gtk/gtk-preferences.c:1167 msgid "Checkerboard pattern _opacity:" msgstr "_ÐепрозрачноÑть шахматного риÑунка:" #: src/gui-gtk/gtk-preferences.c:1179 msgid "_Relative to disk size" msgstr "_ОтноÑительно размера диÑков" #: src/gui-gtk/gtk-preferences.c:1180 msgid "On _white disks:" msgstr "Ðа _белых диÑках:" #: src/gui-gtk/gtk-preferences.c:1181 msgid "On _black disks:" msgstr "Ðа _черных диÑках:" #: src/gui-gtk/gtk-preferences.c:1195 msgid "Use _texture:" msgstr "ИÑпользовать _текÑтуру:" #: src/gui-gtk/gtk-preferences.c:1196 msgid "Use _solid color:" msgstr "_Одноцветный фон:" #: src/gui-gtk/gtk-preferences.c:1271 msgid "Choose a Background Texture..." msgstr "Выберите фоновую текÑтуру…" #: src/gui-gtk/gtk-preferences.c:1282 msgid "Pick Background Color" msgstr "Выберите цвет фона" #: src/gui-gtk/gtk-preferences.c:1296 msgid "Pick Color for Grid and Labels" msgstr "Выберите цвет координатной Ñетки и меток" #: src/gui-gtk/gtk-preferences.c:1306 msgid "_Grid and labels color:" msgstr "Цвет _координатной Ñетки и меток:" #: src/gui-gtk/gtk-preferences.c:1345 msgid "_Theme:" msgstr "_Тема:" #: src/gui-gtk/gtk-preferences.c:1354 msgid "Use theme _defaults" msgstr "_ИÑпользовать наÑтройки из темы" #: src/gui-gtk/gtk-preferences.c:1371 msgid "_Size:" msgstr "_Размер:" #: src/gui-gtk/gtk-preferences.c:1398 msgid "_Opacity:" msgstr "_ÐепрозрачноÑть:" #: src/gui-gtk/gtk-preferences.c:1413 msgid "Size & Opacity" msgstr "Размер и непрозрачноÑть" #: src/gui-gtk/gtk-preferences.c:1429 msgid "Color" msgstr "Цвет" #: src/gui-gtk/gtk-preferences.c:1443 msgid "Pick Color for Markup" msgstr "Выберите цвет разметки" #: src/gui-gtk/gtk-preferences.c:1482 msgid "Background" msgstr "Фон" #: src/gui-gtk/gtk-preferences.c:1484 msgid "Markup" msgstr "Разметка" #: src/gui-gtk/gtk-preferences.c:1630 msgid "Supported games:" msgstr "Поддерживаемае игры:" #: src/gui-gtk/gtk-preferences.c:1637 msgid "This engine comes from site configuration." msgstr "Этот движок опиÑан в конфигурации рабочего меÑта." #: src/gui-gtk/gtk-preferences.c:1860 msgid "" "You can use `%n' and `%v' strings in Screen name field. They will " "substituted with name and version of the engine correspondingly. By default, " "`%n %v' is used." msgstr "" "Ð’Ñ‹ можете иÑпользовать Ñпециальные Ñтроки «%n» и «%v» в поле «отображаемое " "название». Они будут заменены на название и верÑию движка ÑоответÑтвенно. По " "умолчанию, иÑпользуетÑÑ Â«%n %v»." #: src/gui-gtk/gtk-preferences.c:1908 msgid "Modify GTP Engine Information" msgstr "Изменить информацию о GTP-движке" #: src/gui-gtk/gtk-preferences.c:1909 msgid "New GTP Engine" msgstr "Ðовый GTP-движок" #: src/gui-gtk/gtk-preferences.c:1955 msgid "Command _line:" msgstr "_ÐšÐ¾Ð¼Ð°Ð½Ð´Ð½Ð°Ñ Ñтрока:" #: src/gui-gtk/gtk-preferences.c:1961 msgid "Choose GTP Engine..." msgstr "Выберите GTP-движок…" #: src/gui-gtk/gtk-preferences.c:1972 msgid "Screen _name:" msgstr "Отображаемое _название:" #: src/gui-gtk/gtk-preferences.c:2018 msgid "Querying engine's name, version and known commands..." msgstr "" "Запрашиваю название и верÑию движка, а также ÑпиÑок поддерживаемых команд…" #: src/gui-gtk/gtk-preferences.c:2039 msgid "" "Please make sure you typed engine's filename correctly and that you have " "permission to execute it." msgstr "" "ПожалуйÑта, убедитеÑÑŒ, что название файла движка набрано верно, и что у Ð²Ð°Ñ " "еÑть права на его выполнение." #: src/gui-gtk/gtk-preferences.c:2078 msgid "Waiting for the engine to quit..." msgstr "Ожидаю Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð¸Ñ Ñ€Ð°Ð±Ð¾Ñ‚Ñ‹ движка…" #: src/gui-gtk/gtk-preferences.c:2182 msgid "" "The engine might have crashed, quit prematurely or disconnected. Please " "verify command line, including options, and consult engine's documentation " "if needed." msgstr "" "Движок, возможно, «рухнул», завершил работу или отÑоединилÑÑ Ð¿Ð¾ ÑобÑтвенной " "инициативе. ПожалуйÑта, проверьте командную Ñтрочку, Ð²ÐºÐ»ÑŽÑ‡Ð°Ñ Ð¾Ð¿Ñ†Ð¸Ð¸. При " "необходимоÑти, проконÑультируйтеÑÑŒ Ñ Ð´Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñ†Ð¸ÐµÐ¹ движка." #: src/gui-gtk/gtk-preferences.c:2197 #, c-format msgid "Lost connection to GTP Engine (%s)" msgstr "ПотерÑна ÑвÑзь Ñ GTP-движком (%s)" #: src/gui-gtk/gtk-preferences.c:3011 msgid "" "Perhaps engine's binary has been deleted or changed. You will probably need " "to alter engine's command line in the Preferences dialog." msgstr "" "Видимо, иÑполнимый файл движка был удален или изменен. Вам необходимо " "изменить ÑоответÑтвующим образом командную Ñтроку Ð´Ð»Ñ Ð·Ð°Ð¿ÑƒÑка движка в " "диалоге наÑтроек." #: src/gui-gtk/gtk-resume-game-dialog.c:92 msgid "Resume Game..." msgstr "Возобновить партию…" #: src/gui-gtk/gtk-resume-game-dialog.c:115 #, c-format msgid "The game stored in file `%s' (%s) is not supported by Quarry" msgstr "Игра, ÑÐ¾Ñ…Ñ€Ð°Ð½ÐµÐ½Ð½Ð°Ñ Ð² файле «%s» (%s) не поддерживаетÑÑ Quarry" #: src/gui-gtk/gtk-resume-game-dialog.c:138 msgid "" "This game appears to have been finished. Open it for viewing and/or editing " "instead?" msgstr "" "Эта партиÑ, похоже, уже была завершена. Открыть ее Ð´Ð»Ñ Ð¿Ñ€Ð¾Ñмотра и/или " "редактированиÑ?" #: src/gui-gtk/gtk-resume-game-dialog.c:212 msgid "Resuming Game" msgstr "Возобновление партии" #: src/gui-gtk/gtk-resume-game-dialog.c:214 msgid "_Resume" msgstr "_Возобновить" #: src/gui-gtk/gtk-resume-game-dialog.c:231 msgid "Game:" msgstr "Игра:" #: src/gui-gtk/gtk-resume-game-dialog.c:240 msgid "Board size:" msgstr "Размер доÑки:" #: src/gui-gtk/gtk-resume-game-dialog.c:258 msgid "Handicap:" msgstr "Гандикап:" #: src/gui-gtk/gtk-resume-game-dialog.c:262 msgid "handicap|Not set" msgstr "Ðе указан" #: src/gui-gtk/gtk-resume-game-dialog.c:268 msgid "Komi:" msgstr "Коми:" #: src/gui-gtk/gtk-resume-game-dialog.c:271 msgid "komi|Not set" msgstr "Ðе указано" #: src/gui-gtk/gtk-resume-game-dialog.c:294 msgid "Filename:" msgstr "Ðазвание файла:" #: src/gui-gtk/gtk-resume-game-dialog.c:307 msgid "Compu_ter" msgstr "Компь_ютер" #: src/gui-gtk/quarry-find-dialog.c:104 msgid "Whole game _tree" msgstr "Ð’Ñе _дерево" #: src/gui-gtk/quarry-find-dialog.c:104 msgid "Current no_de only" msgstr "Только текущий _узел" #: src/gui-gtk/quarry-find-dialog.c:107 msgid "C_omments & node names" msgstr "Комментарии _и Ð½Ð°Ð·Ð²Ð°Ð½Ð¸Ñ ÑƒÐ·Ð»Ð¾Ð²" #: src/gui-gtk/quarry-find-dialog.c:108 msgid "Comm_ents only" msgstr "Только _комментарии" #: src/gui-gtk/quarry-find-dialog.c:108 msgid "Node na_mes only" msgstr "Только наз_Ð²Ð°Ð½Ð¸Ñ ÑƒÐ·Ð»Ð¾Ð²" #: src/gui-gtk/quarry-find-dialog.c:154 msgid "Search _for:" msgstr "_Ðайти:" #: src/gui-gtk/quarry-find-dialog.c:161 msgid "Case _sensitive" msgstr "Учитывать _региÑтр" #: src/gui-gtk/quarry-find-dialog.c:169 msgid "Whole _words only" msgstr "Только Ñлова _целиком" #: src/gui-gtk/quarry-find-dialog.c:177 msgid "Wrap _around" msgstr "ÐвтоматичеÑки на_чинать Ñначала" #: src/gui-gtk/quarry-find-dialog.c:191 msgid "A_uto-close this dialog" msgstr "Закрывать диалог _автоматичеÑки" #: src/gui-gtk/quarry-find-dialog.c:202 msgid "Options" msgstr "Параметры" #: src/gui-gtk/quarry-find-dialog.c:251 msgid "Search Scope" msgstr "ОблаÑть поиÑка" #: src/gui-gtk/quarry-move-number-dialog.c:66 #: src/gui-gtk/quarry-move-number-dialog.c:148 msgid "Use se_quential move number" msgstr "ИÑпользовать _поÑледовательный номер" #: src/gui-gtk/quarry-move-number-dialog.c:66 msgid "_Set specific move number:" msgstr "_УÑтановить конкретный номер:" #: src/gui-gtk/quarry-save-confirmation-dialog.c:89 msgid "Close _without Saving" msgstr "Закрыть _без ÑохранениÑ" #: src/gui-gtk/quarry-save-confirmation-dialog.c:173 #, c-format msgid "" "If you don't save, changes from the last %d second will be lost permanently." msgid_plural "" "If you don't save, changes from the last %d seconds will be lost permanently." msgstr[0] "" "ЕÑли вы решите не ÑохранÑть, то вÑе изменениÑ, Ñовершенные за поÑледнюю %d " "Ñекунду, будут безвозвратно потерÑны." msgstr[1] "" "ЕÑли вы решите не ÑохранÑть, то вÑе изменениÑ, Ñовершенные за поÑледние %d " "Ñекунды, будут безвозвратно потерÑны." msgstr[2] "" "ЕÑли вы решите не ÑохранÑть, то вÑе изменениÑ, Ñовершенные за поÑледние %d " "Ñекунд, будут безвозвратно потерÑны." #: src/gui-gtk/quarry-save-confirmation-dialog.c:181 msgid "If you don't save, changes from the last minute will be discarded." msgstr "" "ЕÑли вы решите не ÑохранÑть, то вÑе изменениÑ, Ñовершенные за поÑледнюю " "минуту, будут безвозвратно потерÑны." #. TRANSLATORS: Cannot be one minute one second, actually. #: src/gui-gtk/quarry-save-confirmation-dialog.c:187 #, c-format msgid "" "If you don't save, changes from the last minute and %d second will be lost " "permanently." msgid_plural "" "If you don't save, changes from the last minute and %d seconds will be lost " "permanently." msgstr[0] "" "ЕÑли вы решите не ÑохранÑть, то вÑе изменениÑ, Ñовершенные за поÑледнюю " "минуту и %d Ñекунду, будут безвозвратно потерÑны." msgstr[1] "" "ЕÑли вы решите не ÑохранÑть, то вÑе изменениÑ, Ñовершенные за поÑледнюю " "минуту и %d Ñекунды, будут безвозвратно потерÑны." msgstr[2] "" "ЕÑли вы решите не ÑохранÑть, то вÑе изменениÑ, Ñовершенные за поÑледнюю " "минуту и %d Ñекунд, будут безвозвратно потерÑны." #: src/gui-gtk/quarry-save-confirmation-dialog.c:198 #, c-format msgid "" "If you don't save, changes from the last %d minute will be lost permanently." msgid_plural "" "If you don't save, changes from the last %d minutes will be lost permanently." msgstr[0] "" "ЕÑли вы решите не ÑохранÑть, то вÑе изменениÑ, Ñовершенные за поÑледнюю %d " "минуту, будут безвозвратно потерÑны." msgstr[1] "" "ЕÑли вы решите не ÑохранÑть, то вÑе изменениÑ, Ñовершенные за поÑледние %d " "минуты, будут безвозвратно потерÑны." msgstr[2] "" "ЕÑли вы решите не ÑохранÑть, то вÑе изменениÑ, Ñовершенные за поÑледние %d " "минут, будут безвозвратно потерÑны." #. TRANSLATORS: Cannot be one hour one minute, actually. #: src/gui-gtk/quarry-save-confirmation-dialog.c:212 #, c-format msgid "" "If you don't save, changes from the last hour and %d minute will be lost " "permanently." msgid_plural "" "If you don't save, changes from the last hour and %d minutes will be lost " "permanently." msgstr[0] "" "ЕÑли вы решите не ÑохранÑть, то вÑе изменениÑ, Ñовершенные за поÑледний Ñ‡Ð°Ñ " "и %d минуту, будут безвозвратно потерÑны." msgstr[1] "" "ЕÑли вы решите не ÑохранÑть, то вÑе изменениÑ, Ñовершенные за поÑледний Ñ‡Ð°Ñ " "и %d минуты, будут безвозвратно потерÑны." msgstr[2] "" "ЕÑли вы решите не ÑохранÑть, то вÑе изменениÑ, Ñовершенные за поÑледний Ñ‡Ð°Ñ " "и %d минут, будут безвозвратно потерÑны." #: src/gui-gtk/quarry-save-confirmation-dialog.c:224 #, c-format msgid "" "If you don't save, changes from the last %d hour will be lost permanently." msgid_plural "" "If you don't save, changes from the last %d hours will be lost permanently." msgstr[0] "" "ЕÑли вы решите не ÑохранÑть, то вÑе изменениÑ, Ñовершенные за поÑледний %d " "чаÑ, будут безвозвратно потерÑны." msgstr[1] "" "ЕÑли вы решите не ÑохранÑть, то вÑе изменениÑ, Ñовершенные за поÑледние %d " "чаÑа, будут безвозвратно потерÑны." msgstr[2] "" "ЕÑли вы решите не ÑохранÑть, то вÑе изменениÑ, Ñовершенные за поÑледние %d " "чаÑов, будут безвозвратно потерÑны." #: src/gui-gtk/quarry-stock.c:56 msgid "_New Game" msgstr "_ÐÐ¾Ð²Ð°Ñ Ð¿Ð°Ñ€Ñ‚Ð¸Ñ" #: src/gui-gtk/quarry-stock.c:57 msgid "_Open Game Record" msgstr "_Открыть запиÑÑŒ партии" #: src/gui-gtk/quarry-stock.c:59 msgid "_Browse..." msgstr "_ПроÑмотреть…" #: src/gui-gtk/quarry-stock.c:60 msgid "Crea_te" msgstr "Со_здать" #: src/gui-gtk/quarry-stock.c:61 msgid "_Done" msgstr "_Готово" #: src/gui-gtk/quarry-stock.c:62 msgid "_Go to Node" msgstr "_Перейти" #: src/gui-gtk/quarry-stock.c:63 msgid "_Modify" msgstr "_Изменить" #: src/gui-gtk/quarry-stock.c:64 msgid "Move _Up" msgstr "Ð’_верх" #: src/gui-gtk/quarry-stock.c:65 msgid "Move _Down" msgstr "Ð’_низ" #: src/gui-gtk/quarry-stock.c:66 msgid "find|_Next" msgstr "_Следующее" #: src/gui-gtk/quarry-stock.c:67 msgid "_Overwrite" msgstr "_ПерепиÑать" #: src/gui-gtk/quarry-stock.c:68 msgid "_Play" msgstr "_Играть" #: src/gui-gtk/quarry-stock.c:69 msgid "find|_Previous" msgstr "_Предыдущее" #. TRANSLATORS: This is only used for non-integral scores. You #. should also add translation of `points' if it is required by #. your language. #: src/board/board.c:897 #, c-format msgid "Black wins by %.*f" msgstr "Черные выиграли %.*f очка" #. TRANSLATORS: This is only used for non-integral scores. You #. should also add translation of `points' if it is required by #. your language. #: src/board/board.c:904 #, c-format msgid "White wins by %.*f" msgstr "Белые выиграли %.*f очка" #: src/board/board.c:915 #, c-format msgid "Black wins by %d" msgid_plural "Black wins by %d" msgstr[0] "Черные выиграли %d очко" msgstr[1] "Черные выиграли %d очка" msgstr[2] "Черные выиграли %d очков" #: src/board/board.c:923 #, c-format msgid "White wins by %d" msgid_plural "White wins by %d" msgstr[0] "Белые выиграли %d очко" msgstr[1] "Белые выиграли %d очка" msgstr[2] "Белые выиграли %d очков" #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:29 msgid "Go" msgstr "го" #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:43 msgid "Reversi" msgstr "реверÑи" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:58 msgid "chess" msgstr "шахматы" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:73 msgid "Gomoku" msgstr "гомоку" # FIXME: ПеревеÑти. #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:88 msgid "Nine Men's Morris" msgstr "Nine Men’s Morris" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:103 msgid "Backgammon" msgstr "нарды" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:118 msgid "Chinese chess" msgstr "китайÑкие шахматы" #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:133 msgid "Shogi" msgstr "Ñёги" # FIXME: ПеревеÑти. #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:148 msgid "Lines of Action" msgstr "Lines of Action" # FIXME: ПеревеÑти. #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:163 msgid "Ataxx" msgstr "Ataxx" # FIXME: ПеревеÑти. #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:178 msgid "Hex" msgstr "Hex" # FIXME: ПеревеÑти. #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:193 msgid "Jungle" msgstr "Jungle" # FIXME: ПеревеÑти. #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:208 msgid "Neutron" msgstr "Neutron" # FIXME: ПеревеÑти. #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:223 msgid "Philosopher's Football" msgstr "Philosopher’s Football" # FIXME: ПеревеÑти. #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:238 msgid "Quadrature" msgstr "Quadrature" # FIXME: ПеревеÑти. #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:253 msgid "Trax" msgstr "Trax" # FIXME: ПеревеÑти. #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:268 msgid "Tantrix" msgstr "Tantrix" #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:282 msgid "Amazons" msgstr "амазонки" # FIXME: ПеревеÑти. #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:297 msgid "Octi" msgstr "Octi" # FIXME: ПеревеÑти. #. TRANSLATORS: Not important currently. #. TRANSLATORS: Use your language's natural capitalization for the #. name of the game. I.e. it doesn't have to start with a capital #. letter. #: src/board/games.c:312 msgid "Gess" msgstr "Gess" #: src/board/go.c:1323 #, c-format msgid "White: %d territory" msgid_plural "White: %d territory" msgstr[0] "Белые: %d очко территории" msgstr[1] "Белые: %d очка территории" msgstr[2] "Белые: %d очков территории" #: src/board/go.c:1328 src/board/go.c:1365 #, c-format msgid " + %d capture" msgid_plural " + %d captures" msgstr[0] " + %d пленник" msgstr[1] " + %d пленника" msgstr[2] " + %d пленников" #. TRANSLATORS: e.g. `` + 6.5 komi = #. 87.5''. This is used only with #. fractional komi. #: src/board/go.c:1337 #, c-format msgid " %s %.*f komi = %.*f\n" msgstr " %s %.*f коми = %.*f\n" #. TRANSLATORS: e.g. `` + 6 komi = 87''. #: src/board/go.c:1351 #, c-format msgid " %s %d komi = %d\n" msgid_plural " %s %d komi = %d\n" msgstr[0] " %s %d коми = %d\n" msgstr[1] " %s %d коми = %d\n" msgstr[2] " %s %d коми = %d\n" #: src/board/go.c:1360 #, c-format msgid "Black: %d territory" msgid_plural "Black: %d territory" msgstr[0] "Черные: %d очко территории" msgstr[1] "Черные: %d очка территории" msgstr[2] "Черные: %d очков территории" #: src/board/go.c:1374 msgid "The game is draw" msgstr "Игра завершилаÑÑŒ вничью" quarry-0.2.0/po/en.gmo0000644000175000017500000010052210530113071013211 0ustar bartbartÞ•ÀWx%y%#%³%Ð%ç%ø%& $& 2&&?&;f&%¢&È&8è& !'B' Q'_' f'q''¥'¶'Ë'ã'û'(#'(K(g(ƒ(–( ­( º(Ç(á(þ()3)N)f)})–)®)Ë) á)í) * * * %*1*8*)W**›* ­*º*Ë*Þ* í*ù* ++ +4+L+d+{+”+­+¼+Ï+ Þ+ë+ û+ , ,,&, :, F, T,b, s,,Ž,Ÿ,¦,·,Í,ä,ÿ,---M-T-[-`-g-n-u- …-‘-¡-¹- Ö-á-û-5 .(@.,i.–.®. ½.Ê.Ú.ï.µ÷.­/Í/Õ/ î/ü/000 0 $0/0 50 B0 P0 q0|0!0±0'Ç0 ï0 ü011:1Q1 h1r1„1 ”1Ÿ1¼1 Û1é1þ1p28Ž2GÇ23%383 >3H3W3 f3t3 Œ3–3?ª3ê3ò34 44+4@4P4a4j4n4}4•4¯4À4/Ú4X 5 c5m5r5z5 ‘555)Ó56ý5V46X‹6ä6ý677 "7 .7 97 C7O7 ^7 k7y77‡7™7ž7¡7µ7¾7'Ï7÷7 8#878>8 E8 P8Z8^8 e8–p8š9š¢9¬=:°ê:B›;“Þ;¡r<= =#=*=D= J=W=g=„=š="ª=Í=á=è=ý= > %>0>9>@>[>`>f>m>~>†>•>ž>®>³>Å> Î> Ú>è>fù>Û`?€<@ ½@È@Í@à@ñ@AA.AAARAdAiAzAA•AªA…¯A5BLBbB‚B¡B ·BJÄBbC+rCdžC DD+D 4D?D´UD5 E@EHENEgElEˆEE žE¬E´E ÍEÛE àEëE ðE0ûE8,FeF{F‚F –F¤F ½F ÊF×F7÷F/G?GEG\GaGpGG1ŽGÀGÐGáG þGH'H-H>H ZHdH,I/I<@I}I*“IT¾IEJ YJdJzJJ¤J³J¼JÖJ3ÛJXKhKmK ‚K"K$²K×K éK÷KL'L0LOL!RLtL zL ‡L •L ¶LÁL!ÔLöL' M4MFM WM’dM’÷M¦ŠN~1O °OºOÂO ËO×O æOñO÷O PP$P 4P@P DPPPhPoP …P‘P¦P®PµP ¼P ÆPÐPâPóP Q Q%Q-Q"3QVQoQ†QžQ¦Q ®Q»QÄQßQæQïQõQýQ R R R+R:RKR aRnRwRf|RãS#ùST:TQTbTrT ŽT œT&©T;ÐT% U2U:RU U®U ½UËU ÒUÝUýUV$V9VQViVV#•V¹VÕVñVW W (W5WOWlW‡W¡W¼WÔWëWXX9X OX[X nX zX ‡X “XŸX¦X+ÅXñX Y Y*Y;YNY ]YiY Y‹YY¤Y¼YÔYëYZZ,Z?Z NZ[Z kZ wZ ‚ZZ–Z ªZ ¶Z ÄZÒZ ãZïZþZ[['[=[T[o[ƒ[[½[Ä[Ë[Ð[×[Þ[å[ õ[\\)\ F\Q\k\5z\(°\,Ù\]] -]:]J]_]µg]^=^E^ ^^l^r^^„^ ‰^ ”^Ÿ^ ¥^ ²^ À^ á^ì^!ÿ^!_'7_ __ l_x__ª_Á_ Ø_â_ô_ ``,` K`Y`n`p`8þ`G7aa•a¨a ®a¸aÇa Öaäa üab>bYbabtb{b‚bšb¯b¿bÐbÙbÝbìbc&c7c5Qc\‡c äcîcócûc d:d-Yd:‡dVÂd\evee”e£e ´e Àe Ëe Õeáe ðe ýe fff+f0f3fGfPf)af‹fŸf·fËfÒf Ùf äfîfòf ùfšgžŸgž>h°Ýh´ŽiDCj“ˆj¡k¾k ÃkÍkÔkîk ôkll.lDl"Tlwl‹l’l§l Ål ÏlÚlãlêlm mmm(m0m?mHmXm]mqm zm †m”mf¥mÛ n€èn iotoyoŒoo¯oÁoÚoíoþopp&p9pApZp‰_pépqq8qWq mqJzqdÅq+*rdVr »rÇrãr ìr÷rº s7Èsttt't,tHtOt ^tlttt t›t  t«t °t4»t8ðt)u?uFu Zuhu u Žu›u9»uõuv v"v'v6vEv1Tv†v–v§v Ävåvívóvw wŸ*w0Êwûw@ xMx*cxTŽxEãx )y4yJy`ytyƒyŒy¨y3­yXáy:z?z Tz"az$„z©z »zÉzåzùz{!{!${F{ L{ Y{ g{ ˆ{“{!¦{È{'Þ{|| )|š6|žÑ|²p}‚#~ ¦~°~¸~ Á~Í~ Ü~ç~í~  *6 :F^e {‡œ¤« ² ¼ÆØé € €€#€")€L€e€|€”€œ€ ¤€±€º€Õ€Ü€å€ë€ó€ &<DM%!d¨8 T°¢b@·ˆ—2;ѵ±]wo˜®‡mc¢ÀKÖÓ™¦PŽ,gݯêÂyª¥m ÷œòœ[ 5~‚ ºp˜{Ô¹ö¦SNY¿„ÞEab¥Jrï½+Mivjü(™;1•Æ£*#kTŒé½>¬á šÈ!Ÿ7fNž ’}úU¤˧{/û‚Õt<‹)"âi‘A>€ÙG¶¿Ä@Ò'3 Ÿ-»=ƒ‡›ì‘–9G¸ù$ªzK…n†Ã6ºež~†§ß³Ü9è´qM#XVgwLŒÅÍÚCŽoà&DS­´`5sF¶ýš6hHÉn 7‰¾qY¨IîæB/_±ŠR€­²«=L+Zv ‹ã¾ErxµO,¯l»\uÀ?e^„&}pV«ðŠ…ÿ—Wu®JÌô(–"¼Z4å0C.]P0³8 4Uh|?ç1jyÇ'õÁÊAIfˆc¡¼×:”`*“.¬FƒñQ°l-ÏHzO¹í¤© ²a›ó£”ÎdÛ¡$‰ þØëXRW)x©Bk2%ä“Ð •¸·’:<_t3øQD|^ \s[ %s %.*f komi = %.*f %s %d komi = %d %s %d komi = %d + %d capture + %d captures%d capture%d captures%d disk%d disks%s %s %.*f komi%s %s %d komi%s %s %d komi%s (W) vs. %s(per player)* ERROR: mismatched ID (%d expected): * ERROR: unexpected ID in response (the command had none): * ERROR: unrecognized response line: * ERROR: wrong response format * WARNING: future GTP version, I don't know about it... * WARNING: unexpected response: /Circle Markup/Cross Markup/Edit//Edit/Cu_t/Edit/Delete Node's C_hildren/Edit/Edit Node _Name/Edit/Find Ne_xt/Edit/Find Pre_vious/Edit/Game _Information/Edit/Move Branch Do_wn/Edit/Move _Branch Up/Edit/P_layer to Move/Edit/Player to Move/By Game _Rules/Edit/Player to Move/_Black/Edit/Player to Move/_White/Edit/Pr_eferences/Edit/Set _Move Number/Edit/T_ools/Edit/Tools//Edit/Tools/C_ross Markup/Edit/Tools/S_elected Markup/Edit/Tools/S_quare Markup/Edit/Tools/Scori_ng Tool/Edit/Tools/_Circle Markup/Edit/Tools/_Label Tool/Edit/Tools/_Move Tool/Edit/Tools/_Number Tool/Edit/Tools/_Setup Tool/Edit/Tools/_Triangle Markup/Edit/_Add Empty Node/Edit/_Copy/Edit/_Delete Node/Edit/_Find/Edit/_Paste/Edit/_Redo/Edit/_Undo/File//File/Export.../_ASCII Diagram/File/Export.../_Sensei's Library Diagram/File/Ne_w Game Record.../File/Save _As.../File/_Close/File/_Export.../File/_New Game.../File/_Open.../File/_Quit/File/_Resume Game.../File/_Save/Go//Go/Ne_xt Variation/Go/Pre_vious Variation/Go/Ten Nodes _Backward/Go/Ten Nodes _Forward/Go/Variation _Last Node/Go/_Go to Named Node.../Go/_Next Node/Go/_Previous Node/Go/_Root Node/Help/_About/Help/_Contents/Label Tool/Move Tool/Number Tool/Play//Play/_Adjourn Game/Play/_Pass/Play/_Resign/Scoring Tool/Selected Markup/Setup Tool/Square Markup/Triangle Markup/View//View/Game _Tree/View/_Control Center/View/_Editing Toolbar/View/_Game Action Buttons/View/_Main Toolbar/View/_Navigation Toolbar/View/_Recenter on Current Node/_Edit/_File/_Go/_Help/_Play/_View; black to play; game over; white to playBoard AppearanceEditing & ViewingGTPGame Records (SGF)GeneralA GUI program for Go, Amazons and Reversi board gamesA good width for the right side to have.ASCII diagram has been exported to clipboardA_uto-close this dialogA_utomaticallyAbout QuarryAdd Board LabelAdjourn & Save As...Al_waysAlthough board labels are not limited in length, it is better to use only one or two characters long labels. Longer labels will not be visible immediately or at all in most clients.Always use _UTF-8 (recommended)AmazonsAmazons Board AppearanceAmazons RulesAtaxxAut_omaticallyB BackBackgammonBackgroundBlackBlack PlayerBlack resignsBlack runs out of time and losesBlack winsBlack wins by %.*fBlack wins by %dBlack wins by %dBlack wins by forfeitBlack: %d territoryBlack: %d territoryBoard _size:Board size:By Game _Rules (Black)By Game _Rules (Game Over)By Game _Rules (White)C_omments & node namesC_omputerCanadian overtimeCase _sensitiveCategor_y:Checkerboard _pattern color:Checkerboard pattern _opacity:Chinese chessChoose GTP Engine...Choose a Background Texture...Clipboard SGF probably contains more than one game tree or not a single child of the root of the only game tree.Clipboard contains an invalid game record fragment (SGF)Clipboard game record fragment must be of different game or board size.Close _without SavingCo_pyright string:ColorCom_puterComm_ents onlyCommand _line:Command line:Comment / _description:Compu_terCopyright & CreditsCopyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev and othersCrea_teCurrent no_de onlyDa_te:DeleteDelete the current nodeDescription & ResultDesktop defaultEdit Board LabelEncodingEndEngine hung upError reading file `%s'Error saving to file `%s'Fi_xed handicap:File Chooser Dialog StyleFile `%s' doesn't appear to be a valid SGF fileFile named `%s' already exists. Do you want to overwrite it with the one you are saving?Filename:FindForwardGTP Engine InformationGTP EnginesGTP engine `%s' cannot handle %dx%d board size, sorryGTP engine `%s' failed to clean the boardGTP engine `%s' failed to set handicap stones on boardGTP engine `%s' failed to set initial time limits (it could ignore them, but not fail)GTP engine `%s' reported it could handle %s game, but failed to initialize itself for itGTP engine is scoring...GameGame & PlayersGame InformationGame RecordGame RulesGame TreeGame _name:Game beginningGame is drawGame re_sult:Game:GeneralGeneral InterfaceGessGoGo Board AppearanceGo RulesGo to Named NodeGo to the current variation's last nodeGo to the next nodeGo to the previous nodeGo to the root nodeGomokuH_umanHan_dicap:Handicap:HexHu_manIcons onlyIf you don't save, changes from the last %d hour will be lost permanently.If you don't save, changes from the last %d hours will be lost permanently.If you don't save, changes from the last %d minute will be lost permanently.If you don't save, changes from the last %d minutes will be lost permanently.If you don't save, changes from the last %d second will be lost permanently.If you don't save, changes from the last %d seconds will be lost permanently.If you don't save, changes from the last hour and %d minute will be lost permanently.If you don't save, changes from the last hour and %d minutes will be lost permanently.If you don't save, changes from the last minute and %d second will be lost permanently.If you don't save, changes from the last minute and %d seconds will be lost permanently.If you don't save, changes from the last minute will be discarded.In automatic mode the game tree is shown only if it has at least one variation. In any case, you can show/hide game tree in each window separately.In automatic mode the game tree view scrolls to show the current node only if it has been showing current node before. I.e. unless you scrolled it away manually.InfoInterfaceJungleK_eep track of total timeKomi:Label _text:Last move: %u, Limited time for entire gameLimited time per moveLines of ActionLost connection to GTP Engine (%s)Manage _Engine ListMarkupMo_ves per overtime:Modify GTP Engine InformationMove %d: Move _DownMove _UpN_ame:N_avigation toolbar style:NameName:Ne_verNe_w Game RecordNeutronNew GTP EngineNew GameNew Game RecordNextNine Men's MorrisNo limitNode _name:Node comment:Node na_mes onlyNote that all information in the existing file will be lost permanently if you choose to overwrite it.Note that many characters cannot be represented in non-UTF-8 encodings and thus some information may be lost if you use them. Quarry also works fastest with UTF-8; this may be important if you have very large SGF files.Note that most GTP engines support only one game. Hence certain game / computer player combinations may be not possible to play.O_vertime:OctiOn _black amazons:On _black disks:On _black stones:On _empty fields:On _empty intersections:On _white amazons:On _white disks:On _white stones:OpenOpen SGF File...Open a game recordOptionsParsing file `%s'...PassPerhaps engine's binary has been deleted or changed. You will probably need to alter engine's command line in the Preferences dialog.Philosopher's FootballPick Background ColorPick Checkerboard Pattern ColorPick Color for Grid and LabelsPick Color for MarkupPick a ColorPlease check that the file exists and its permission allow you to read it.Please make sure you typed engine's filename correctly and that you have permission to execute it.Please select dead stones to score the gamePlease set up %d (or less) stone of free handicapPlease set up %d (or less) stones of free handicapPreferencesPreserve _original encodingPreviousQuadratureQuarry Control CenterQuarry uses SGF file format for storing game records. SGF files would normally have `sgf' extension, but that's not necessarily true. Please make sure you select a proper SGF file.Querying engine's name, version and known commands...R_ound:Rank:Really resign this game?RedoRedo the last undone actionResignResume Game...Resuming GameReversiReversi Board AppearanceReversi RulesRootRule _set:SaveSave As...Save changes to game record `%s' before closing?Save changes to the untitled game record before closing?Save the current fileSavingSaving Game RecordsScreen _name:Scroll _minimal distanceSearch ScopeSearch _for:Search for a string in commentsSensei's Library diagram has been exported to clipboardSet Move NumberShogiShort Game InformationShowShow Game TreeShow _tooltipsSize & OpacitySorry, there are no named nodes in this game treeSupported game:Supported games:Switch to the next variationSwitch to the previous variationTantrixTeam:Text below iconsText beside important iconsText onlyThe engine might have crashed, quit prematurely or disconnected. Please verify command line, including options, and consult engine's documentation if needed.The game is adjourned and saved in file `%s'The game is drawThe game stored in file `%s' (%s) is not supported by QuarryThere is no such nodeThis engine comes from site configuration.This game appears to have been finished. Open it for viewing and/or editing instead?This is an engine error. You may want to report it to engine authors.Time LimitTime _limit for game:Time _limit for move:Time control _type:Toolbar StylesTooltipsTrack Tree's Current NodeTraxUnable to paste game record fragment from clipboardUnable to paste game record fragment from clipboard since it is not intended for pastingUndoUndo the last actionUnnamed GameUse _newer (GTK+ 2.4) file chooserUse _old-style file selection dialogUse _solid color:Use _texture:Use se_quential move numberUse theme _defaultsVersion:View and edit game informationW Waiting for the engine to quit...WhiteWhite PlayerWhite resignsWhite runs out of time and losesWhite winsWhite wins by %.*fWhite wins by %dWhite wins by %dWhite wins by forfeitWhite: %d territoryWhite: %d territoryWhole _words onlyWhole game _treeWrap _aroundYou can always change and expand game information later. Just choose `Edit/Game Information' menu item or press `Info' button on the main toolbar.You can later resume the game by pressing the `Resume Game' button in Quarry Control Center, or selecting `Resume Game' item from the `File' menu.You can use `%n' and `%v' strings in Screen name field. They will substituted with name and version of the engine correspondingly. By default, `%n %v' is used.You can usually paste the diagram in another application using `Ctrl+C' key combination or by selecting appropriate menu item.[unknown]_Always_Amazons_Annotator:_Black player:_Browse..._Done_Editing toolbar style:_Entered by:_Event:_Free handicap:_Game name:_Go_Go to Node_Grid and labels color:_Komi:_List of GTP engines:_Main time:_Main toolbar style:_Modify_Name:_Never_New Game_Opacity:_Open Game Record_Opening played:_Overtime period length:_Overwrite_Place stones_Place:_Play_Recenter view on the current node_Relative to amazon size_Relative to disk size_Relative to stone size_Resign_Resume_Resume Game_Reversi_Set specific move number:_Size:_Source:_Swap_Theme:_White player:chesscomment|Emptyfind|_Nextfind|_Previoushandicap|Not setinsert node name herekomi|Not setmodifiedpassProject-Id-Version: Quarry Report-Msgid-Bugs-To: quarry-dev@gna.org POT-Creation-Date: 2006-11-07 18:33+0200 PO-Revision-Date: 2006-10-28 15:05+0300 Last-Translator: Paul Pogonyshev Language-Team: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=2; plural=n == 1 ? 0 : 1; %s %.*f komi = %.*f %s %d komi = %d %s %d komi = %d + %d capture + %d captures%d capture%d captures%d disk%d disks%s %s %.*f komi%s %s %d komi%s %s %d komi%s (W) vs. %s(per player)* ERROR: mismatched ID (%d expected): * ERROR: unexpected ID in response (the command had none): * ERROR: unrecognized response line: * ERROR: wrong response format * WARNING: future GTP version, I don’t know about it... * WARNING: unexpected response: /Circle Markup/Cross Markup/Edit//Edit/Cu_t/Edit/Delete Node’s C_hildren/Edit/Edit Node _Name/Edit/Find Ne_xt/Edit/Find Pre_vious/Edit/Game _Information/Edit/Move Branch Do_wn/Edit/Move _Branch Up/Edit/P_layer to Move/Edit/Player to Move/By Game _Rules/Edit/Player to Move/_Black/Edit/Player to Move/_White/Edit/Pr_eferences/Edit/Set _Move Number/Edit/T_ools/Edit/Tools//Edit/Tools/C_ross Markup/Edit/Tools/S_elected Markup/Edit/Tools/S_quare Markup/Edit/Tools/Scori_ng Tool/Edit/Tools/_Circle Markup/Edit/Tools/_Label Tool/Edit/Tools/_Move Tool/Edit/Tools/_Number Tool/Edit/Tools/_Setup Tool/Edit/Tools/_Triangle Markup/Edit/_Add Empty Node/Edit/_Copy/Edit/_Delete Node/Edit/_Find/Edit/_Paste/Edit/_Redo/Edit/_Undo/File//File/Export…/_ASCII Diagram/File/Export…/_Sensei’s Library Diagram/File/Ne_w Game Record…/File/Save _As…/File/_Close/File/_Export…/File/_New Game…/File/_Open…/File/_Quit/File/_Resume Game…/File/_Save/Go//Go/Ne_xt Variation/Go/Pre_vious Variation/Go/Ten Nodes _Backward/Go/Ten Nodes _Forward/Go/Variation _Last Node/Go/_Go to Named Node…/Go/_Next Node/Go/_Previous Node/Go/_Root Node/Help/_About/Help/_Contents/Label Tool/Move Tool/Number Tool/Play//Play/_Adjourn Game/Play/_Pass/Play/_Resign/Scoring Tool/Selected Markup/Setup Tool/Square Markup/Triangle Markup/View//View/Game _Tree/View/_Control Center/View/_Editing Toolbar/View/_Game Action Buttons/View/_Main Toolbar/View/_Navigation Toolbar/View/_Recenter on Current Node/_Edit/_File/_Go/_Help/_Play/_View; black to play; game over; white to playBoard AppearanceEditing & ViewingGTPGame Records (SGF)GeneralA GUI program for Go, Amazons and Reversi board gamesA good width for the right side to have.ASCII diagram has been exported to clipboardA_uto-close this dialogA_utomaticallyAbout QuarryAdd Board LabelAdjourn & Save As…Al_waysAlthough board labels are not limited in length, it is better to use only one or two characters long labels. Longer labels will not be visible immediately or at all in most clients.Always use _UTF-8 (recommended)AmazonsAmazons Board AppearanceAmazons RulesAtaxxAut_omaticallyB BackBackgammonBackgroundBlackBlack PlayerBlack resignsBlack runs out of time and losesBlack winsBlack wins by %.*fBlack wins by %dBlack wins by %dBlack wins by forfeitBlack: %d territoryBlack: %d territoryBoard _size:Board size:By Game _Rules (Black)By Game _Rules (Game Over)By Game _Rules (White)C_omments & node namesC_omputerCanadian overtimeCase _sensitiveCategor_y:Checkerboard _pattern color:Checkerboard pattern _opacity:Chinese chessChoose GTP Engine…Choose a Background Texture…Clipboard SGF probably contains more than one game tree or not a single child of the root of the only game tree.Clipboard contains an invalid game record fragment (SGF)Clipboard game record fragment must be of different game or board size.Close _without SavingCo_pyright string:ColorCom_puterComm_ents onlyCommand _line:Command line:Comment / _description:Compu_terCopyright & CreditsCopyright © 2003, 2004, 2005, 2006 Paul Pogonyshev and othersCrea_teCurrent no_de onlyDa_te:DeleteDelete the current nodeDescription & ResultDesktop defaultEdit Board LabelEncodingEndEngine hung upError reading file ‘%s’Error saving to file ‘%s’Fi_xed handicap:File Chooser Dialog StyleFile ‘%s’ doesn’t appear to be a valid SGF fileFile named ‘%s’ already exists. Do you want to overwrite it with the one you are saving?Filename:FindForwardGTP Engine InformationGTP EnginesGTP engine ‘%s’ cannot handle %d×%d board size, sorryGTP engine ‘%s’ failed to clean the boardGTP engine ‘%s’ failed to set handicap stones on boardGTP engine `%s' failed to set initial time limits (it could ignore them, but not fail)GTP engine ‘%s’ reported it could handle %s game, but failed to initialize itself for itGTP engine is scoring…GameGame & PlayersGame InformationGame RecordGame RulesGame TreeGame _name:Game beginningGame is drawGame re_sult:Game:GeneralGeneral InterfaceGessGoGo Board AppearanceGo RulesGo to Named NodeGo to the current variation’s last nodeGo to the next nodeGo to the previous nodeGo to the root nodeGomokuH_umanHan_dicap:Handicap:HexHu_manIcons onlyIf you don’t save, changes from the last %d hour will be lost permanently.If you don’t save, changes from the last %d hours will be lost permanently.If you don’t save, changes from the last %d minute will be lost permanently.If you don’t save, changes from the last %d minutes will be lost permanently.If you don’t save, changes from the last %d second will be lost permanently.If you don’t save, changes from the last %d seconds will be lost permanently.If you don’t save, changes from the last hour and %d minute will be lost permanently.If you don’t save, changes from the last hour and %d minutes will be lost permanently.If you don’t save, changes from the last minute and %d second will be lost permanently.If you don’t save, changes from the last minute and %d seconds will be lost permanently.If you don’t save, changes from the last minute will be discarded.In automatic mode the game tree is shown only if it has at least one variation. In any case, you can show/hide game tree in each window separately.In automatic mode the game tree view scrolls to show the current node only if it has been showing current node before. I.e. unless you scrolled it away manually.InfoInterfaceJungleK_eep track of total timeKomi:Label _text:Last move: %u, Limited time for entire gameLimited time per moveLines of ActionLost connection to GTP Engine (%s)Manage _Engine ListMarkupMo_ves per overtime:Modify GTP Engine InformationMove %d: Move _DownMove _UpN_ame:N_avigation toolbar style:NameName:Ne_verNe_w Game RecordNeutronNew GTP EngineNew GameNew Game RecordNextNine Men’s MorrisNo limitNode _name:Node comment:Node na_mes onlyNote that all information in the existing file will be lost permanently if you choose to overwrite it.Note that many characters cannot be represented in non-UTF-8 encodings and thus some information may be lost if you use them. Quarry also works fastest with UTF-8; this may be important if you have very large SGF files.Note that most GTP engines support only one game. Hence certain game / computer player combinations may be not possible to play.O_vertime:OctiOn _black amazons:On _black disks:On _black stones:On _empty fields:On _empty intersections:On _white amazons:On _white disks:On _white stones:OpenOpen SGF File…Open a game recordOptionsParsing file ‘%s’…PassPerhaps engine’s binary has been deleted or changed. You will probably need to alter engine’s command line in the Preferences dialog.Philosopher’s FootballPick Background ColorPick Checkerboard Pattern ColorPick Color for Grid and LabelsPick Color for MarkupPick a ColorPlease check that the file exists and its permission allow you to read it.Please make sure you typed engine’s filename correctly and that you have permission to execute it.Please select dead stones to score the gamePlease set up %d (or less) stone of free handicapPlease set up %d (or less) stones of free handicapPreferencesPreserve _original encodingPreviousQuadratureQuarry Control CenterQuarry uses SGF file format for storing game records. SGF files would normally have ‘sgf’ extension, but that’s not necessarily true. Please make sure you select a proper SGF file.Querying engine’s name, version and known commands…R_ound:Rank:Really resign this game?RedoRedo the last undone actionResignResume Game…Resuming GameReversiReversi Board AppearanceReversi RulesRootRule _set:SaveSave As…Save changes to game record ‘%s’ before closing?Save changes to the untitled game record before closing?Save the current fileSavingSaving Game RecordsScreen _name:Scroll _minimal distanceSearch ScopeSearch _for:Search for a string in commentsSensei’s Library diagram has been exported to clipboardSet Move NumberShogiShort Game InformationShowShow Game TreeShow _tooltipsSize & OpacitySorry, there are no named nodes in this game treeSupported game:Supported games:Switch to the next variationSwitch to the previous variationTantrixTeam:Text below iconsText beside important iconsText onlyThe engine might have crashed, quit prematurely or disconnected. Please verify command line, including options, and consult engine’s documentation if needed.The game is adjourned and saved in file ‘%s’The game is drawThe game stored in file ‘%s’ (%s) is not supported by QuarryThere is no such nodeThis engine comes from site configuration.This game appears to have been finished. Open it for viewing and/or editing instead?This is an engine error. You may want to report it to engine authors.Time LimitTime _limit for game:Time _limit for move:Time control _type:Toolbar StylesTooltipsTrack Tree’s Current NodeTraxUnable to paste game record fragment from clipboardUnable to paste game record fragment from clipboard since it is not intended for pastingUndoUndo the last actionUnnamed GameUse _newer (GTK+ 2.4) file chooserUse _old-style file selection dialogUse _solid color:Use _texture:Use se_quential move numberUse theme _defaultsVersion:View and edit game informationW Waiting for the engine to quit…WhiteWhite PlayerWhite resignsWhite runs out of time and losesWhite winsWhite wins by %.*fWhite wins by %dWhite wins by %dWhite wins by forfeitWhite: %d territoryWhite: %d territoryWhole _words onlyWhole game _treeWrap _aroundYou can always change and expand game information later. Just choose ‘Edit/Game Information’ menu item or press ‘Info’ button on the main toolbar.You can later resume the game by pressing the ‘Resume Game’ button in Quarry Control Center, or selecting ‘Resume Game’ item from the ‘File’ menu.You can use ‘%n’ and ‘%v’ strings in Screen name field. They will substituted with name and version of the engine correspondingly. By default, ‘%n %v’ is used.You can usually paste the diagram in another application using ‘Ctrl+C’ key combination or by selecting appropriate menu item.[unknown]_Always_Amazons_Annotator:_Black player:_Browse…_Done_Editing toolbar style:_Entered by:_Event:_Free handicap:_Game name:_Go_Go to Node_Grid and labels color:_Komi:_List of GTP engines:_Main time:_Main toolbar style:_Modify_Name:_Never_New Game_Opacity:_Open Game Record_Opening played:_Overtime period length:_Overwrite_Place stones_Place:_Play_Recenter view on the current node_Relative to amazon size_Relative to disk size_Relative to stone size_Resign_Resume_Resume Game_Reversi_Set specific move number:_Size:_Source:_Swap_Theme:_White player:chessEmpty_Next_PreviousNot setinsert node name hereNot setmodifiedpassquarry-0.2.0/po/en_GB.gmo0000644000175000017500000010053710530113071013567 0ustar bartbartÞ•ÀWx%y%#%³%Ð%ç%ø%& $& 2&&?&;f&%¢&È&8è& !'B' Q'_' f'q''¥'¶'Ë'ã'û'(#'(K(g(ƒ(–( ­( º(Ç(á(þ()3)N)f)})–)®)Ë) á)í) * * * %*1*8*)W**›* ­*º*Ë*Þ* í*ù* ++ +4+L+d+{+”+­+¼+Ï+ Þ+ë+ û+ , ,,&, :, F, T,b, s,,Ž,Ÿ,¦,·,Í,ä,ÿ,---M-T-[-`-g-n-u- …-‘-¡-¹- Ö-á-û-5 .(@.,i.–.®. ½.Ê.Ú.ï.µ÷.­/Í/Õ/ î/ü/000 0 $0/0 50 B0 P0 q0|0!0±0'Ç0 ï0 ü011:1Q1 h1r1„1 ”1Ÿ1¼1 Û1é1þ1p28Ž2GÇ23%383 >3H3W3 f3t3 Œ3–3?ª3ê3ò34 44+4@4P4a4j4n4}4•4¯4À4/Ú4X 5 c5m5r5z5 ‘555)Ó56ý5V46X‹6ä6ý677 "7 .7 97 C7O7 ^7 k7y77‡7™7ž7¡7µ7¾7'Ï7÷7 8#878>8 E8 P8Z8^8 e8–p8š9š¢9¬=:°ê:B›;“Þ;¡r<= =#=*=D= J=W=g=„=š="ª=Í=á=è=ý= > %>0>9>@>[>`>f>m>~>†>•>ž>®>³>Å> Î> Ú>è>fù>Û`?€<@ ½@È@Í@à@ñ@AA.AAARAdAiAzAA•AªA…¯A5BLBbB‚B¡B ·BJÄBbC+rCdžC DD+D 4D?D´UD5 E@EHENEgElEˆEE žE¬E´E ÍEÛE àEëE ðE0ûE8,FeF{F‚F –F¤F ½F ÊF×F7÷F/G?GEG\GaGpGG1ŽGÀGÐGáG þGH'H-H>H ZHdH,I/I<@I}I*“IT¾IEJ YJdJzJJ¤J³J¼JÖJ3ÛJXKhKmK ‚K"K$²K×K éK÷KL'L0LOL!RLtL zL ‡L •L ¶LÁL!ÔLöL' M4MFM WM’dM’÷M¦ŠN~1O °OºOÂO ËO×O æOñO÷O PP$P 4P@P DPPPhPoP …P‘P¦P®PµP ¼P ÆPÐPâPóP Q Q%Q-Q"3QVQoQ†QžQ¦Q ®Q»QÄQßQæQïQõQýQ R R R+R:RKR aRnRwRf|RãS#ùST:TQTbTrT ŽT œT&©T;ÐT% U2U:RU U®U ½UËU ÒUÝUýUV$V9VQViVV#•V¹VÕVñVW W (W5WOWlW‡W¡W¼WÔWëWXX9X OX[X nX zX ‡X “XŸX¦X+ÅXñX Y Y*Y;YNY ]YiY Y‹YY¤Y¼YÔYëYZZ,Z?Z NZ[Z kZ wZ ‚ZZ–Z ªZ ¶Z ÄZÒZ ãZïZþZ[['[=[T[o[ƒ[[½[Ä[Ë[Ð[×[Þ[å[ õ[\\)\ F\Q\k\5z\(°\,Ù\] ] /]<]L]a]µi]^?^G^ `^n^t^ƒ^†^ ‹^ –^¡^ §^ ´^ Â^ ã^î^!_#_'9_ a_ n_z_‘_¬_Ã_ Ú_ä_ö_ ``,` H`V`k`pŠ`8û`G4a|a’a¥a ¬a¶aÅa Ôaâa úab>bWb_brbyb€b˜b­b½bÎb×bÛbêbc$c5c5Qc\‡c äcîcócûc d:d-Yd:‡dZÂd\eze“e˜e§e ¸e Äe Ïe Ùeåe ôe ffff/f4f7fKfTf)eff£f»fÏfÖf Ýf èfòföf ýfšgž£gžBh°áh´’iDGj“Œj¡ kÂk ÇkÑkØkòk økll2lHl"Xl{ll–l«l Él ÓlÞlçlîl mmmm,m4mCmLm\mamum ~m Šm˜mf©mÛn€ìn moxo}oo¡o³oÅoÞoñoppp*p=pEp^p‹cpïpqq=q]q tqJ‚qdÍq+2rd^r ÃrÏrër ôrÿr»s7Ñs ttt0t5tQtXt gtut}t –t¤t ©t´t ¹t4Ät8ùt2uHuOu cuqu Šu —u¤u9Äuþuvv+v0v?vNv1]vvŸv°v Ívîvövüv w )wŸ3w0Ówx@xVx*lxT—xEìx 2y=ySyiy}yŒy•y±y3¶yXêyCzHz ]z"jz&z´z ÇzÕzñz{{-{!0{R{ X{ e{ s{ ”{Ÿ{!²{Ô{'ê{|$| 5|šB|žÝ|²|}‚/~ ²~¼~Ä~ Í~Ù~ è~ó~ù~ & 6B FRkr ˆ”©±¸ ¿ ÉÓåö € €(€0€"6€Y€r€‰€¡€©€ ±€¾€Ç€â€é€ò€ø€ !+3IQZ%!d¨8 T°¢b@·ˆ—2;ѵ±]wo˜®‡mc¢ÀKÖÓ™¦PŽ,gݯêÂyª¥m ÷œòœ[ 5~‚ ºp˜{Ô¹ö¦SNY¿„ÞEab¥Jrï½+Mivjü(™;1•Æ£*#kTŒé½>¬á šÈ!Ÿ7fNž ’}úU¤˧{/û‚Õt<‹)"âi‘A>€ÙG¶¿Ä@Ò'3 Ÿ-»=ƒ‡›ì‘–9G¸ù$ªzK…n†Ã6ºež~†§ß³Ü9è´qM#XVgwLŒÅÍÚCŽoà&DS­´`5sF¶ýš6hHÉn 7‰¾qY¨IîæB/_±ŠR€­²«=L+Zv ‹ã¾ErxµO,¯l»\uÀ?e^„&}pV«ðŠ…ÿ—Wu®JÌô(–"¼Z4å0C.]P0³8 4Uh|?ç1jyÇ'õÁÊAIfˆc¡¼×:”`*“.¬FƒñQ°l-ÏHzO¹í¤© ²a›ó£”ÎdÛ¡$‰ þØëXRW)x©Bk2%ä“Ð •¸·’:<_t3øQD|^ \s[ %s %.*f komi = %.*f %s %d komi = %d %s %d komi = %d + %d capture + %d captures%d capture%d captures%d disk%d disks%s %s %.*f komi%s %s %d komi%s %s %d komi%s (W) vs. %s(per player)* ERROR: mismatched ID (%d expected): * ERROR: unexpected ID in response (the command had none): * ERROR: unrecognized response line: * ERROR: wrong response format * WARNING: future GTP version, I don't know about it... * WARNING: unexpected response: /Circle Markup/Cross Markup/Edit//Edit/Cu_t/Edit/Delete Node's C_hildren/Edit/Edit Node _Name/Edit/Find Ne_xt/Edit/Find Pre_vious/Edit/Game _Information/Edit/Move Branch Do_wn/Edit/Move _Branch Up/Edit/P_layer to Move/Edit/Player to Move/By Game _Rules/Edit/Player to Move/_Black/Edit/Player to Move/_White/Edit/Pr_eferences/Edit/Set _Move Number/Edit/T_ools/Edit/Tools//Edit/Tools/C_ross Markup/Edit/Tools/S_elected Markup/Edit/Tools/S_quare Markup/Edit/Tools/Scori_ng Tool/Edit/Tools/_Circle Markup/Edit/Tools/_Label Tool/Edit/Tools/_Move Tool/Edit/Tools/_Number Tool/Edit/Tools/_Setup Tool/Edit/Tools/_Triangle Markup/Edit/_Add Empty Node/Edit/_Copy/Edit/_Delete Node/Edit/_Find/Edit/_Paste/Edit/_Redo/Edit/_Undo/File//File/Export.../_ASCII Diagram/File/Export.../_Sensei's Library Diagram/File/Ne_w Game Record.../File/Save _As.../File/_Close/File/_Export.../File/_New Game.../File/_Open.../File/_Quit/File/_Resume Game.../File/_Save/Go//Go/Ne_xt Variation/Go/Pre_vious Variation/Go/Ten Nodes _Backward/Go/Ten Nodes _Forward/Go/Variation _Last Node/Go/_Go to Named Node.../Go/_Next Node/Go/_Previous Node/Go/_Root Node/Help/_About/Help/_Contents/Label Tool/Move Tool/Number Tool/Play//Play/_Adjourn Game/Play/_Pass/Play/_Resign/Scoring Tool/Selected Markup/Setup Tool/Square Markup/Triangle Markup/View//View/Game _Tree/View/_Control Center/View/_Editing Toolbar/View/_Game Action Buttons/View/_Main Toolbar/View/_Navigation Toolbar/View/_Recenter on Current Node/_Edit/_File/_Go/_Help/_Play/_View; black to play; game over; white to playBoard AppearanceEditing & ViewingGTPGame Records (SGF)GeneralA GUI program for Go, Amazons and Reversi board gamesA good width for the right side to have.ASCII diagram has been exported to clipboardA_uto-close this dialogA_utomaticallyAbout QuarryAdd Board LabelAdjourn & Save As...Al_waysAlthough board labels are not limited in length, it is better to use only one or two characters long labels. Longer labels will not be visible immediately or at all in most clients.Always use _UTF-8 (recommended)AmazonsAmazons Board AppearanceAmazons RulesAtaxxAut_omaticallyB BackBackgammonBackgroundBlackBlack PlayerBlack resignsBlack runs out of time and losesBlack winsBlack wins by %.*fBlack wins by %dBlack wins by %dBlack wins by forfeitBlack: %d territoryBlack: %d territoryBoard _size:Board size:By Game _Rules (Black)By Game _Rules (Game Over)By Game _Rules (White)C_omments & node namesC_omputerCanadian overtimeCase _sensitiveCategor_y:Checkerboard _pattern color:Checkerboard pattern _opacity:Chinese chessChoose GTP Engine...Choose a Background Texture...Clipboard SGF probably contains more than one game tree or not a single child of the root of the only game tree.Clipboard contains an invalid game record fragment (SGF)Clipboard game record fragment must be of different game or board size.Close _without SavingCo_pyright string:ColorCom_puterComm_ents onlyCommand _line:Command line:Comment / _description:Compu_terCopyright & CreditsCopyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev and othersCrea_teCurrent no_de onlyDa_te:DeleteDelete the current nodeDescription & ResultDesktop defaultEdit Board LabelEncodingEndEngine hung upError reading file `%s'Error saving to file `%s'Fi_xed handicap:File Chooser Dialog StyleFile `%s' doesn't appear to be a valid SGF fileFile named `%s' already exists. Do you want to overwrite it with the one you are saving?Filename:FindForwardGTP Engine InformationGTP EnginesGTP engine `%s' cannot handle %dx%d board size, sorryGTP engine `%s' failed to clean the boardGTP engine `%s' failed to set handicap stones on boardGTP engine `%s' failed to set initial time limits (it could ignore them, but not fail)GTP engine `%s' reported it could handle %s game, but failed to initialize itself for itGTP engine is scoring...GameGame & PlayersGame InformationGame RecordGame RulesGame TreeGame _name:Game beginningGame is drawGame re_sult:Game:GeneralGeneral InterfaceGessGoGo Board AppearanceGo RulesGo to Named NodeGo to the current variation's last nodeGo to the next nodeGo to the previous nodeGo to the root nodeGomokuH_umanHan_dicap:Handicap:HexHu_manIcons onlyIf you don't save, changes from the last %d hour will be lost permanently.If you don't save, changes from the last %d hours will be lost permanently.If you don't save, changes from the last %d minute will be lost permanently.If you don't save, changes from the last %d minutes will be lost permanently.If you don't save, changes from the last %d second will be lost permanently.If you don't save, changes from the last %d seconds will be lost permanently.If you don't save, changes from the last hour and %d minute will be lost permanently.If you don't save, changes from the last hour and %d minutes will be lost permanently.If you don't save, changes from the last minute and %d second will be lost permanently.If you don't save, changes from the last minute and %d seconds will be lost permanently.If you don't save, changes from the last minute will be discarded.In automatic mode the game tree is shown only if it has at least one variation. In any case, you can show/hide game tree in each window separately.In automatic mode the game tree view scrolls to show the current node only if it has been showing current node before. I.e. unless you scrolled it away manually.InfoInterfaceJungleK_eep track of total timeKomi:Label _text:Last move: %u, Limited time for entire gameLimited time per moveLines of ActionLost connection to GTP Engine (%s)Manage _Engine ListMarkupMo_ves per overtime:Modify GTP Engine InformationMove %d: Move _DownMove _UpN_ame:N_avigation toolbar style:NameName:Ne_verNe_w Game RecordNeutronNew GTP EngineNew GameNew Game RecordNextNine Men's MorrisNo limitNode _name:Node comment:Node na_mes onlyNote that all information in the existing file will be lost permanently if you choose to overwrite it.Note that many characters cannot be represented in non-UTF-8 encodings and thus some information may be lost if you use them. Quarry also works fastest with UTF-8; this may be important if you have very large SGF files.Note that most GTP engines support only one game. Hence certain game / computer player combinations may be not possible to play.O_vertime:OctiOn _black amazons:On _black disks:On _black stones:On _empty fields:On _empty intersections:On _white amazons:On _white disks:On _white stones:OpenOpen SGF File...Open a game recordOptionsParsing file `%s'...PassPerhaps engine's binary has been deleted or changed. You will probably need to alter engine's command line in the Preferences dialog.Philosopher's FootballPick Background ColorPick Checkerboard Pattern ColorPick Color for Grid and LabelsPick Color for MarkupPick a ColorPlease check that the file exists and its permission allow you to read it.Please make sure you typed engine's filename correctly and that you have permission to execute it.Please select dead stones to score the gamePlease set up %d (or less) stone of free handicapPlease set up %d (or less) stones of free handicapPreferencesPreserve _original encodingPreviousQuadratureQuarry Control CenterQuarry uses SGF file format for storing game records. SGF files would normally have `sgf' extension, but that's not necessarily true. Please make sure you select a proper SGF file.Querying engine's name, version and known commands...R_ound:Rank:Really resign this game?RedoRedo the last undone actionResignResume Game...Resuming GameReversiReversi Board AppearanceReversi RulesRootRule _set:SaveSave As...Save changes to game record `%s' before closing?Save changes to the untitled game record before closing?Save the current fileSavingSaving Game RecordsScreen _name:Scroll _minimal distanceSearch ScopeSearch _for:Search for a string in commentsSensei's Library diagram has been exported to clipboardSet Move NumberShogiShort Game InformationShowShow Game TreeShow _tooltipsSize & OpacitySorry, there are no named nodes in this game treeSupported game:Supported games:Switch to the next variationSwitch to the previous variationTantrixTeam:Text below iconsText beside important iconsText onlyThe engine might have crashed, quit prematurely or disconnected. Please verify command line, including options, and consult engine's documentation if needed.The game is adjourned and saved in file `%s'The game is drawThe game stored in file `%s' (%s) is not supported by QuarryThere is no such nodeThis engine comes from site configuration.This game appears to have been finished. Open it for viewing and/or editing instead?This is an engine error. You may want to report it to engine authors.Time LimitTime _limit for game:Time _limit for move:Time control _type:Toolbar StylesTooltipsTrack Tree's Current NodeTraxUnable to paste game record fragment from clipboardUnable to paste game record fragment from clipboard since it is not intended for pastingUndoUndo the last actionUnnamed GameUse _newer (GTK+ 2.4) file chooserUse _old-style file selection dialogUse _solid color:Use _texture:Use se_quential move numberUse theme _defaultsVersion:View and edit game informationW Waiting for the engine to quit...WhiteWhite PlayerWhite resignsWhite runs out of time and losesWhite winsWhite wins by %.*fWhite wins by %dWhite wins by %dWhite wins by forfeitWhite: %d territoryWhite: %d territoryWhole _words onlyWhole game _treeWrap _aroundYou can always change and expand game information later. Just choose `Edit/Game Information' menu item or press `Info' button on the main toolbar.You can later resume the game by pressing the `Resume Game' button in Quarry Control Center, or selecting `Resume Game' item from the `File' menu.You can use `%n' and `%v' strings in Screen name field. They will substituted with name and version of the engine correspondingly. By default, `%n %v' is used.You can usually paste the diagram in another application using `Ctrl+C' key combination or by selecting appropriate menu item.[unknown]_Always_Amazons_Annotator:_Black player:_Browse..._Done_Editing toolbar style:_Entered by:_Event:_Free handicap:_Game name:_Go_Go to Node_Grid and labels color:_Komi:_List of GTP engines:_Main time:_Main toolbar style:_Modify_Name:_Never_New Game_Opacity:_Open Game Record_Opening played:_Overtime period length:_Overwrite_Place stones_Place:_Play_Recenter view on the current node_Relative to amazon size_Relative to disk size_Relative to stone size_Resign_Resume_Resume Game_Reversi_Set specific move number:_Size:_Source:_Swap_Theme:_White player:chesscomment|Emptyfind|_Nextfind|_Previoushandicap|Not setinsert node name herekomi|Not setmodifiedpassProject-Id-Version: Quarry Report-Msgid-Bugs-To: quarry-dev@gna.org POT-Creation-Date: 2006-11-07 18:33+0200 PO-Revision-Date: 2006-10-28 15:05+0300 Last-Translator: Paul Pogonyshev Language-Team: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=2; plural=n == 1 ? 0 : 1; %s %.*f komi = %.*f %s %d komi = %d %s %d komi = %d + %d capture + %d captures%d capture%d captures%d disk%d disks%s %s %.*f komi%s %s %d komi%s %s %d komi%s (W) vs. %s(per player)* ERROR: mismatched ID (%d expected): * ERROR: unexpected ID in response (the command had none): * ERROR: unrecognised response line: * ERROR: wrong response format * WARNING: future GTP version, I don’t know about it... * WARNING: unexpected response: /Circle Markup/Cross Markup/Edit//Edit/Cu_t/Edit/Delete Node’s C_hildren/Edit/Edit Node _Name/Edit/Find Ne_xt/Edit/Find Pre_vious/Edit/Game _Information/Edit/Move Branch Do_wn/Edit/Move _Branch Up/Edit/P_layer to Move/Edit/Player to Move/By Game _Rules/Edit/Player to Move/_Black/Edit/Player to Move/_White/Edit/Pr_eferences/Edit/Set _Move Number/Edit/T_ools/Edit/Tools//Edit/Tools/C_ross Markup/Edit/Tools/S_elected Markup/Edit/Tools/S_quare Markup/Edit/Tools/Scori_ng Tool/Edit/Tools/_Circle Markup/Edit/Tools/_Label Tool/Edit/Tools/_Move Tool/Edit/Tools/_Number Tool/Edit/Tools/_Setup Tool/Edit/Tools/_Triangle Markup/Edit/_Add Empty Node/Edit/_Copy/Edit/_Delete Node/Edit/_Find/Edit/_Paste/Edit/_Redo/Edit/_Undo/File//File/Export…/_ASCII Diagram/File/Export…/_Sensei’s Library Diagram/File/Ne_w Game Record…/File/Save _As…/File/_Close/File/_Export…/File/_New Game…/File/_Open…/File/_Quit/File/_Resume Game…/File/_Save/Go//Go/Ne_xt Variation/Go/Pre_vious Variation/Go/Ten Nodes _Backward/Go/Ten Nodes _Forward/Go/Variation _Last Node/Go/_Go to Named Node…/Go/_Next Node/Go/_Previous Node/Go/_Root Node/Help/_About/Help/_Contents/Label Tool/Move Tool/Number Tool/Play//Play/_Adjourn Game/Play/_Pass/Play/_Resign/Scoring Tool/Selected Markup/Setup Tool/Square Markup/Triangle Markup/View//View/Game _Tree/View/_Control Centre/View/_Editing Toolbar/View/_Game Action Buttons/View/_Main Toolbar/View/_Navigation Toolbar/View/_Recentre on Current Node/_Edit/_File/_Go/_Help/_Play/_View; black to play; game over; white to playBoard AppearanceEditing & ViewingGTPGame Records (SGF)GeneralA GUI program for Go, Amazons and Reversi board gamesA good width for the right side to have.ASCII diagram has been exported to clipboardA_uto-close this dialogueA_utomaticallyAbout QuarryAdd Board LabelAdjourn & Save As…Al_waysAlthough board labels are not limited in length, it is better to use only one or two characters long labels. Longer labels will not be visible immediately or at all in most clients.Always use _UTF-8 (recommended)AmazonsAmazons Board AppearanceAmazons RulesAtaxxAut_omaticallyB BackBackgammonBackgroundBlackBlack PlayerBlack resignsBlack runs out of time and losesBlack winsBlack wins by %.*fBlack wins by %dBlack wins by %dBlack wins by forfeitBlack: %d territoryBlack: %d territoryBoard _size:Board size:By Game _Rules (Black)By Game _Rules (Game Over)By Game _Rules (White)C_omments & node namesC_omputerCanadian overtimeCase _sensitiveCategor_y:Chequered _pattern colour:Chequered pattern _opacity:Chinese chessChoose GTP Engine…Choose a Background Texture…Clipboard SGF probably contains more than one game tree or not a single child of the root of the only game tree.Clipboard contains an invalid game record fragment (SGF)Clipboard game record fragment must be of different game or board size.Close _without SavingCo_pyright string:ColourCom_puterComm_ents onlyCommand _line:Command line:Comment / _description:Compu_terCopyright & CreditsCopyright © 2003, 2004, 2005, 2006 Paul Pogonyshev and othersCrea_teCurrent no_de onlyDa_te:DeleteDelete the current nodeDescription & ResultDesktop defaultEdit Board LabelEncodingEndEngine hung upError reading file ‘%s’Error saving to file ‘%s’Fi_xed handicap:File Chooser Dialogue StyleFile ‘%s’ doesn’t appear to be a valid SGF fileFile named ‘%s’ already exists. Do you want to overwrite it with the one you are saving?Filename:FindForwardGTP Engine InformationGTP EnginesGTP engine ‘%s’ cannot handle %d×%d board size, sorryGTP engine ‘%s’ failed to clean the boardGTP engine ‘%s’ failed to set handicap stones on boardGTP engine ‘%s’ failed to set initial time limits (it could ignore them, but not fail)GTP engine ‘%s’ reported it could handle %s game, but failed to initialise itself for itGTP engine is scoring…GameGame & PlayersGame InformationGame RecordGame RulesGame TreeGame _name:Game beginningGame is drawGame re_sult:Game:GeneralGeneral InterfaceGessGoGo Board AppearanceGo RulesGo to Named NodeGo to the current variation’s last nodeGo to the next nodeGo to the previous nodeGo to the root nodeGomokuH_umanHan_dicap:Handicap:HexHu_manIcons onlyIf you don’t save, changes from the last %d hour will be lost permanently.If you don’t save, changes from the last %d hours will be lost permanently.If you don’t save, changes from the last %d minute will be lost permanently.If you don’t save, changes from the last %d minutes will be lost permanently.If you don’t save, changes from the last %d second will be lost permanently.If you don’t save, changes from the last %d seconds will be lost permanently.If you don’t save, changes from the last hour and %d minute will be lost permanently.If you don’t save, changes from the last hour and %d minutes will be lost permanently.If you don’t save, changes from the last minute and %d second will be lost permanently.If you don’t save, changes from the last minute and %d seconds will be lost permanently.If you don’t save, changes from the last minute will be discarded.In automatic mode the game tree is shown only if it has at least one variation. In any case, you can show/hide game tree in each window separately.In automatic mode the game tree view scrolls to show the current node only if it has been showing current node before. I.e. unless you scrolled it away manually.InfoInterfaceJungleK_eep track of total timeKomi:Label _text:Last move: %u, Limited time for entire gameLimited time per moveLines of ActionLost connection to GTP Engine (%s)Manage _Engine ListMarkupMo_ves per overtime:Modify GTP Engine InformationMove %d: Move _DownMove _UpN_ame:N_avigation toolbar style:NameName:Ne_verNe_w Game RecordNeutronNew GTP EngineNew GameNew Game RecordNextNine Men’s MorrisNo limitNode _name:Node comment:Node na_mes onlyNote that all information in the existing file will be lost permanently if you choose to overwrite it.Note that many characters cannot be represented in non-UTF-8 encodings and thus some information may be lost if you use them. Quarry also works fastest with UTF-8; this may be important if you have very large SGF files.Note that most GTP engines support only one game. Hence certain game / computer player combinations may be not possible to play.O_vertime:OctiOn _black amazons:On _black disks:On _black stones:On _empty fields:On _empty intersections:On _white amazons:On _white disks:On _white stones:OpenOpen SGF File…Open a game recordOptionsParsing file ‘%s’…PassPerhaps engine’s binary has been deleted or changed. You will probably need to alter engine’s command line in the Preferences dialogue.Philosopher’s FootballPick Background ColourPick Chequered Pattern ColourPick Colour for Grid and LabelsPick Colour for MarkupPick a ColourPlease check that the file exists and its permission allow you to read it.Please make sure you typed engine’s filename correctly and that you have permission to execute it.Please select dead stones to score the gamePlease set up %d (or less) stone of free handicapPlease set up %d (or less) stones of free handicapPreferencesPreserve _original encodingPreviousQuadratureQuarry Control CentreQuarry uses SGF file format for storing game records. SGF files would normally have ‘sgf’ extension, but that’s not necessarily true. Please make sure you select a correct SGF file.Querying engine’s name, version and known commands…R_ound:Rank:Really resign this game?RedoRedo the last undone actionResignResume Game…Resuming GameReversiReversi Board AppearanceReversi RulesRootRule _set:SaveSave As…Save changes to game record ‘%s’ before closing?Save changes to the untitled game record before closing?Save the current fileSavingSaving Game RecordsScreen _name:Scroll _minimal distanceSearch ScopeSearch _for:Search for a string in commentsSensei’s Library diagram has been exported to clipboardSet Move NumberShogiShort Game InformationShowShow Game TreeShow _tooltipsSize & OpacitySorry, there are no named nodes in this game treeSupported game:Supported games:Switch to the next variationSwitch to the previous variationTantrixTeam:Text below iconsText beside important iconsText onlyThe engine might have crashed, quit prematurely or disconnected. Please verify command line, including options, and consult engine’s documentation if needed.The game is adjourned and saved in file ‘%s’The game is drawThe game stored in file ‘%s’ (%s) is not supported by QuarryThere is no such nodeThis engine comes from site configuration.This game appears to have been finished. Open it for viewing and/or editing instead?This is an engine error. You may want to report it to engine authors.Time LimitTime _limit for game:Time _limit for move:Time control _type:Toolbar StylesTooltipsTrack Tree’s Current NodeTraxUnable to paste game record fragment from clipboardUnable to paste game record fragment from clipboard since it is not intended for pastingUndoUndo the last actionUnnamed GameUse _newer (GTK+ 2.4) file chooserUse _old-style file selection dialogueUse _solid colour:Use _texture:Use se_quential move numberUse theme _defaultsVersion:View and edit game informationW Waiting for the engine to quit…WhiteWhite PlayerWhite resignsWhite runs out of time and losesWhite winsWhite wins by %.*fWhite wins by %dWhite wins by %dWhite wins by forfeitWhite: %d territoryWhite: %d territoryWhole _words onlyWhole game _treeWrap _aroundYou can always change and expand game information later. Just choose ‘Edit/Game Information’ menu item or press ‘Info’ button on the main toolbar.You can later resume the game by pressing the ‘Resume Game’ button in Quarry Control Centre, or selecting ‘Resume Game’ item from the ‘File’ menu.You can use ‘%n’ and ‘%v’ strings in Screen name field. They will substituted with name and version of the engine correspondingly. By default, ‘%n %v’ is used.You can usually paste the diagram in another application using ‘Ctrl+C’ key combination or by selecting appropriate menu item.[unknown]_Always_Amazons_Annotator:_Black player:_Browse…_Done_Editing toolbar style:_Entered by:_Event:_Free handicap:_Game name:_Go_Go to Node_Grid and labels colour:_Komi:_List of GTP engines:_Main time:_Main toolbar style:_Modify_Name:_Never_New Game_Opacity:_Open Game Record_Opening played:_Overtime period length:_Overwrite_Place stones_Place:_Play_Recentre view on the current node_Relative to amazon size_Relative to disk size_Relative to stone size_Resign_Resume_Resume Game_Reversi_Set specific move number:_Size:_Source:_Swap_Theme:_White player:chessEmpty_Next_PreviousNot setinsert node name hereNot setmodifiedpassquarry-0.2.0/po/fr.gmo0000644000175000017500000011030310530113071013214 0ustar bartbartÞ•ÀWx%y%#%³%Ð%ç%ø%& $& 2&&?&;f&%¢&È&8è& !'B' Q'_' f'q''¥'¶'Ë'ã'û'(#'(K(g(ƒ(–( ­( º(Ç(á(þ()3)N)f)})–)®)Ë) á)í) * * * %*1*8*)W**›* ­*º*Ë*Þ* í*ù* ++ +4+L+d+{+”+­+¼+Ï+ Þ+ë+ û+ , ,,&, :, F, T,b, s,,Ž,Ÿ,¦,·,Í,ä,ÿ,---M-T-[-`-g-n-u- …-‘-¡-¹- Ö-á-û-5 .(@.,i.–.®. ½.Ê.Ú.ï.µ÷.­/Í/Õ/ î/ü/000 0 $0/0 50 B0 P0 q0|0!0±0'Ç0 ï0 ü011:1Q1 h1r1„1 ”1Ÿ1¼1 Û1é1þ1p28Ž2GÇ23%383 >3H3W3 f3t3 Œ3–3?ª3ê3ò34 44+4@4P4a4j4n4}4•4¯4À4/Ú4X 5 c5m5r5z5 ‘555)Ó56ý5V46X‹6ä6ý677 "7 .7 97 C7O7 ^7 k7y77‡7™7ž7¡7µ7¾7'Ï7÷7 8#878>8 E8 P8Z8^8 e8–p8š9š¢9¬=:°ê:B›;“Þ;¡r<= =#=*=D= J=W=g=„=š="ª=Í=á=è=ý= > %>0>9>@>[>`>f>m>~>†>•>ž>®>³>Å> Î> Ú>è>fù>Û`?€<@ ½@È@Í@à@ñ@AA.AAARAdAiAzAA•AªA…¯A5BLBbB‚B¡B ·BJÄBbC+rCdžC DD+D 4D?D´UD5 E@EHENEgElEˆEE žE¬E´E ÍEÛE àEëE ðE0ûE8,FeF{F‚F –F¤F ½F ÊF×F7÷F/G?GEG\GaGpGG1ŽGÀGÐGáG þGH'H-H>H ZHdH,I/I<@I}I*“IT¾IEJ YJdJzJJ¤J³J¼JÖJ3ÛJXKhKmK ‚K"K$²K×K éK÷KL'L0LOL!RLtL zL ‡L •L ¶LÁL!ÔLöL' M4MFM WM’dM’÷M¦ŠN~1O °OºOÂO ËO×O æOñO÷O PP$P 4P@P DPPPhPoP …P‘P¦P®PµP ¼P ÆPÐPâPóP Q Q%Q-Q"3QVQoQ†QžQ¦Q ®Q»QÄQßQæQïQõQýQ R R R+R:RKR aRnRwRe|RâS!øST7TNTcTsT T T4ªTMßT.-U'\U<„U&ÁUèUùU VV,&V"SV vV$—V%¼VâVWW-9WgW ‡W¨W&ÁWèWúW X(-X!VXxX!˜X$ºXßX'÷XY#Ófgg5g >gHgagzg"™g¼gÅgÉg)ßg/ h9hJh9jh{¤h i 2i=iEi diHpi;¹iUõi…KjrÑj!Dkfkmk~k™kµkÊkÝkòk l l )l 3l=lRlWlZl ulƒl-œlÊlálülmm !m .m:m>mFmÖYmØ0nÚ oèäoìÍpWºqËrÜÞr»s ÀsÊsÑsésñs t"t@tWt#gt‹t¨t"±t+Ôt u uuu#&uJuNuUu ]u~u†u™u©uÉuÒu Ùuçu÷uv{*v*¦vµÑw‡x¡x¦xÂxÛxöxy.yKyfyƒyŠy£yÂyÊyåy«ìy˜z(¡z7Êz8{*;{f{P}{iÎ{:8|ns| â| ð| } })}éD}K.~ z~…~#~ ±~&»~ â~í~!AT [ frB†FÉ€/€>€X€)l€–€¯€:¾€Nù€Hf"m™·Ò?ä$‚;‚"Q‚&t‚›‚ £‚®‚'Å‚í‚Æþ‚<Ń „Q „^„/t„Q¤„gö„^…"n…‘…®…Í… è…#ö…†V†v†ö†þ†‡5*‡(`‡‰‡§‡,À‡+í‡ ˆ2$ˆWˆYˆyˆ €ˆˆ#¤ˆȈ!Þˆ5‰6‰0U‰†‰ž‰¹‰ÁЉ·’ŠãJ‹¯.Œ ÞŒ èŒ òŒüŒ  ) 3Tm}¥©+¹åîŽ)Ž FŽPŽXŽ`Ž qŽ~ŽžŽ#³Ž ׎áŽõŽþŽ$"*!M!o ‘ ¨¾!Ç é ô ÿ &.?Skƒ ´½%!d¨8 T°¢b@·ˆ—2;ѵ±]wo˜®‡mc¢ÀKÖÓ™¦PŽ,gݯêÂyª¥m ÷œòœ[ 5~‚ ºp˜{Ô¹ö¦SNY¿„ÞEab¥Jrï½+Mivjü(™;1•Æ£*#kTŒé½>¬á šÈ!Ÿ7fNž ’}úU¤˧{/û‚Õt<‹)"âi‘A>€ÙG¶¿Ä@Ò'3 Ÿ-»=ƒ‡›ì‘–9G¸ù$ªzK…n†Ã6ºež~†§ß³Ü9è´qM#XVgwLŒÅÍÚCŽoà&DS­´`5sF¶ýš6hHÉn 7‰¾qY¨IîæB/_±ŠR€­²«=L+Zv ‹ã¾ErxµO,¯l»\uÀ?e^„&}pV«ðŠ…ÿ—Wu®JÌô(–"¼Z4å0C.]P0³8 4Uh|?ç1jyÇ'õÁÊAIfˆc¡¼×:”`*“.¬FƒñQ°l-ÏHzO¹í¤© ²a›ó£”ÎdÛ¡$‰ þØëXRW)x©Bk2%ä“Ð •¸·’:<_t3øQD|^ \s[ %s %.*f komi = %.*f %s %d komi = %d %s %d komi = %d + %d capture + %d captures%d capture%d captures%d disk%d disks%s %s %.*f komi%s %s %d komi%s %s %d komi%s (W) vs. %s(per player)* ERROR: mismatched ID (%d expected): * ERROR: unexpected ID in response (the command had none): * ERROR: unrecognized response line: * ERROR: wrong response format * WARNING: future GTP version, I don't know about it... * WARNING: unexpected response: /Circle Markup/Cross Markup/Edit//Edit/Cu_t/Edit/Delete Node's C_hildren/Edit/Edit Node _Name/Edit/Find Ne_xt/Edit/Find Pre_vious/Edit/Game _Information/Edit/Move Branch Do_wn/Edit/Move _Branch Up/Edit/P_layer to Move/Edit/Player to Move/By Game _Rules/Edit/Player to Move/_Black/Edit/Player to Move/_White/Edit/Pr_eferences/Edit/Set _Move Number/Edit/T_ools/Edit/Tools//Edit/Tools/C_ross Markup/Edit/Tools/S_elected Markup/Edit/Tools/S_quare Markup/Edit/Tools/Scori_ng Tool/Edit/Tools/_Circle Markup/Edit/Tools/_Label Tool/Edit/Tools/_Move Tool/Edit/Tools/_Number Tool/Edit/Tools/_Setup Tool/Edit/Tools/_Triangle Markup/Edit/_Add Empty Node/Edit/_Copy/Edit/_Delete Node/Edit/_Find/Edit/_Paste/Edit/_Redo/Edit/_Undo/File//File/Export.../_ASCII Diagram/File/Export.../_Sensei's Library Diagram/File/Ne_w Game Record.../File/Save _As.../File/_Close/File/_Export.../File/_New Game.../File/_Open.../File/_Quit/File/_Resume Game.../File/_Save/Go//Go/Ne_xt Variation/Go/Pre_vious Variation/Go/Ten Nodes _Backward/Go/Ten Nodes _Forward/Go/Variation _Last Node/Go/_Go to Named Node.../Go/_Next Node/Go/_Previous Node/Go/_Root Node/Help/_About/Help/_Contents/Label Tool/Move Tool/Number Tool/Play//Play/_Adjourn Game/Play/_Pass/Play/_Resign/Scoring Tool/Selected Markup/Setup Tool/Square Markup/Triangle Markup/View//View/Game _Tree/View/_Control Center/View/_Editing Toolbar/View/_Game Action Buttons/View/_Main Toolbar/View/_Navigation Toolbar/View/_Recenter on Current Node/_Edit/_File/_Go/_Help/_Play/_View; black to play; game over; white to playBoard AppearanceEditing & ViewingGTPGame Records (SGF)GeneralA GUI program for Go, Amazons and Reversi board gamesA good width for the right side to have.ASCII diagram has been exported to clipboardA_uto-close this dialogA_utomaticallyAbout QuarryAdd Board LabelAdjourn & Save As...Al_waysAlthough board labels are not limited in length, it is better to use only one or two characters long labels. Longer labels will not be visible immediately or at all in most clients.Always use _UTF-8 (recommended)AmazonsAmazons Board AppearanceAmazons RulesAtaxxAut_omaticallyB BackBackgammonBackgroundBlackBlack PlayerBlack resignsBlack runs out of time and losesBlack winsBlack wins by %.*fBlack wins by %dBlack wins by %dBlack wins by forfeitBlack: %d territoryBlack: %d territoryBoard _size:Board size:By Game _Rules (Black)By Game _Rules (Game Over)By Game _Rules (White)C_omments & node namesC_omputerCanadian overtimeCase _sensitiveCategor_y:Checkerboard _pattern color:Checkerboard pattern _opacity:Chinese chessChoose GTP Engine...Choose a Background Texture...Clipboard SGF probably contains more than one game tree or not a single child of the root of the only game tree.Clipboard contains an invalid game record fragment (SGF)Clipboard game record fragment must be of different game or board size.Close _without SavingCo_pyright string:ColorCom_puterComm_ents onlyCommand _line:Command line:Comment / _description:Compu_terCopyright & CreditsCopyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev and othersCrea_teCurrent no_de onlyDa_te:DeleteDelete the current nodeDescription & ResultDesktop defaultEdit Board LabelEncodingEndEngine hung upError reading file `%s'Error saving to file `%s'Fi_xed handicap:File Chooser Dialog StyleFile `%s' doesn't appear to be a valid SGF fileFile named `%s' already exists. Do you want to overwrite it with the one you are saving?Filename:FindForwardGTP Engine InformationGTP EnginesGTP engine `%s' cannot handle %dx%d board size, sorryGTP engine `%s' failed to clean the boardGTP engine `%s' failed to set handicap stones on boardGTP engine `%s' failed to set initial time limits (it could ignore them, but not fail)GTP engine `%s' reported it could handle %s game, but failed to initialize itself for itGTP engine is scoring...GameGame & PlayersGame InformationGame RecordGame RulesGame TreeGame _name:Game beginningGame is drawGame re_sult:Game:GeneralGeneral InterfaceGessGoGo Board AppearanceGo RulesGo to Named NodeGo to the current variation's last nodeGo to the next nodeGo to the previous nodeGo to the root nodeGomokuH_umanHan_dicap:Handicap:HexHu_manIcons onlyIf you don't save, changes from the last %d hour will be lost permanently.If you don't save, changes from the last %d hours will be lost permanently.If you don't save, changes from the last %d minute will be lost permanently.If you don't save, changes from the last %d minutes will be lost permanently.If you don't save, changes from the last %d second will be lost permanently.If you don't save, changes from the last %d seconds will be lost permanently.If you don't save, changes from the last hour and %d minute will be lost permanently.If you don't save, changes from the last hour and %d minutes will be lost permanently.If you don't save, changes from the last minute and %d second will be lost permanently.If you don't save, changes from the last minute and %d seconds will be lost permanently.If you don't save, changes from the last minute will be discarded.In automatic mode the game tree is shown only if it has at least one variation. In any case, you can show/hide game tree in each window separately.In automatic mode the game tree view scrolls to show the current node only if it has been showing current node before. I.e. unless you scrolled it away manually.InfoInterfaceJungleK_eep track of total timeKomi:Label _text:Last move: %u, Limited time for entire gameLimited time per moveLines of ActionLost connection to GTP Engine (%s)Manage _Engine ListMarkupMo_ves per overtime:Modify GTP Engine InformationMove %d: Move _DownMove _UpN_ame:N_avigation toolbar style:NameName:Ne_verNe_w Game RecordNeutronNew GTP EngineNew GameNew Game RecordNextNine Men's MorrisNo limitNode _name:Node comment:Node na_mes onlyNote that all information in the existing file will be lost permanently if you choose to overwrite it.Note that many characters cannot be represented in non-UTF-8 encodings and thus some information may be lost if you use them. Quarry also works fastest with UTF-8; this may be important if you have very large SGF files.Note that most GTP engines support only one game. Hence certain game / computer player combinations may be not possible to play.O_vertime:OctiOn _black amazons:On _black disks:On _black stones:On _empty fields:On _empty intersections:On _white amazons:On _white disks:On _white stones:OpenOpen SGF File...Open a game recordOptionsParsing file `%s'...PassPerhaps engine's binary has been deleted or changed. You will probably need to alter engine's command line in the Preferences dialog.Philosopher's FootballPick Background ColorPick Checkerboard Pattern ColorPick Color for Grid and LabelsPick Color for MarkupPick a ColorPlease check that the file exists and its permission allow you to read it.Please make sure you typed engine's filename correctly and that you have permission to execute it.Please select dead stones to score the gamePlease set up %d (or less) stone of free handicapPlease set up %d (or less) stones of free handicapPreferencesPreserve _original encodingPreviousQuadratureQuarry Control CenterQuarry uses SGF file format for storing game records. SGF files would normally have `sgf' extension, but that's not necessarily true. Please make sure you select a proper SGF file.Querying engine's name, version and known commands...R_ound:Rank:Really resign this game?RedoRedo the last undone actionResignResume Game...Resuming GameReversiReversi Board AppearanceReversi RulesRootRule _set:SaveSave As...Save changes to game record `%s' before closing?Save changes to the untitled game record before closing?Save the current fileSavingSaving Game RecordsScreen _name:Scroll _minimal distanceSearch ScopeSearch _for:Search for a string in commentsSensei's Library diagram has been exported to clipboardSet Move NumberShogiShort Game InformationShowShow Game TreeShow _tooltipsSize & OpacitySorry, there are no named nodes in this game treeSupported game:Supported games:Switch to the next variationSwitch to the previous variationTantrixTeam:Text below iconsText beside important iconsText onlyThe engine might have crashed, quit prematurely or disconnected. Please verify command line, including options, and consult engine's documentation if needed.The game is adjourned and saved in file `%s'The game is drawThe game stored in file `%s' (%s) is not supported by QuarryThere is no such nodeThis engine comes from site configuration.This game appears to have been finished. Open it for viewing and/or editing instead?This is an engine error. You may want to report it to engine authors.Time LimitTime _limit for game:Time _limit for move:Time control _type:Toolbar StylesTooltipsTrack Tree's Current NodeTraxUnable to paste game record fragment from clipboardUnable to paste game record fragment from clipboard since it is not intended for pastingUndoUndo the last actionUnnamed GameUse _newer (GTK+ 2.4) file chooserUse _old-style file selection dialogUse _solid color:Use _texture:Use se_quential move numberUse theme _defaultsVersion:View and edit game informationW Waiting for the engine to quit...WhiteWhite PlayerWhite resignsWhite runs out of time and losesWhite winsWhite wins by %.*fWhite wins by %dWhite wins by %dWhite wins by forfeitWhite: %d territoryWhite: %d territoryWhole _words onlyWhole game _treeWrap _aroundYou can always change and expand game information later. Just choose `Edit/Game Information' menu item or press `Info' button on the main toolbar.You can later resume the game by pressing the `Resume Game' button in Quarry Control Center, or selecting `Resume Game' item from the `File' menu.You can use `%n' and `%v' strings in Screen name field. They will substituted with name and version of the engine correspondingly. By default, `%n %v' is used.You can usually paste the diagram in another application using `Ctrl+C' key combination or by selecting appropriate menu item.[unknown]_Always_Amazons_Annotator:_Black player:_Browse..._Done_Editing toolbar style:_Entered by:_Event:_Free handicap:_Game name:_Go_Go to Node_Grid and labels color:_Komi:_List of GTP engines:_Main time:_Main toolbar style:_Modify_Name:_Never_New Game_Opacity:_Open Game Record_Opening played:_Overtime period length:_Overwrite_Place stones_Place:_Play_Recenter view on the current node_Relative to amazon size_Relative to disk size_Relative to stone size_Resign_Resume_Resume Game_Reversi_Set specific move number:_Size:_Source:_Swap_Theme:_White player:chesscomment|Emptyfind|_Nextfind|_Previoushandicap|Not setinsert node name herekomi|Not setmodifiedpassProject-Id-Version: Quarry Report-Msgid-Bugs-To: quarry-dev@gna.org POT-Creation-Date: 2006-11-07 18:33+0200 PO-Revision-Date: 2006-11-11 17:28+0100 Last-Translator: Jeremie Knuesel Language-Team: fr <-> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=2; plural=(n != 1); %s %.*f komi = %.*f %s %d komi = %d %s %d komi = %d + %d capture + %d captures%d capture%d captures%d disque%d disques%s %s %.*f komi%s %s %d komi%s %s %d komi%s (B) vs. %s(par joueur)* ERREUR : l'ID ne correspond pas (attendu: %d) : * ERREUR : ID inattendu dans la réponse (l'a commande n'en avant aucun) : * ERREUR : ligne de réponse non reconnue : * ERREUR : mauvais format de réponse * ATTENTION : version future de GTP, je ne la connais pas. * ATTENTION : réponse inattendue : /Marquage cercle/Marquage croix/Édition//Édition/_Couper/Édition/Supprimer la _descendance du noeud/Édition/Éditer le _nom du noeud/Édition/Rechercher le _suivant/Édition/Rechercher le _précédent/Édition/_Informations sur la partie/Édition/_Descendre la branche/Édition/_Monter la branche/Édition/À _qui le tour/Édition/À qui le tour/Suivant les _règles/Édition/À qui le tour/_Noirs/Édition/À qui le tour/_Blancs/Édition/_Préférences/Édition/_Définir le numéro du coup/Édition/Ou_tils/Édition/Outils//Édition/Outils/Marquage _croix/Édition/Outils/Marquage _sélectionné/Édition/Outils/Marquage c_arré/Édition/Outils/Outil de score/Édition/Outils/Marquage c_ercle/Édition/Outils/Outil d'étiquetage/Édition/Outils/_Coups/Édition/Outils/Outil de numérotation/Édition/Outils/_Situations/Édition/Outils/Marquage _triangle/Édition/_Ajouter un noeud vide/Édition/C_opier/Édition/_Supprimer le noeud/Édition/_Rechercher/Édition/Co_ller/Édition/_Restaurer/Édition/_Annuler/Fichier//Fichier/Exporter.../Diagramme _ASCII/Fichier/Exporter.../Diagramme au format Sensei's Library/Fichier/Nouvel _enregistrement de partie.../Fichier/Enregistrer _sous.../Fichier/_Fermer/Fichier/_Exporter.../Fichier/_Nouvelle partie.../Fichier/_Ouvrir.../Fichier/_Quitter/Fichier/_Reprendre une partie.../Fichier/_Enregistrer/Aller à//Aller à/Variation su_ivante/Aller à/Variation précé_dente/Aller à/Dix noeud en _arrière/Aller à/Dix noeuds en a_vant/Aller à/_Dernier noeud de la variation/Aller à/_Aller à un noeud nommé/Aller à/Noeud _suivant/Aller à/Noeud _précédent/Aller à/Noeud _racine/Aide/À _propos/Aide/_Sommaire/Outil d'étiquetage/Coups/Outil de numérotation/Jouer//Jouer/Ajourner la _partie/Jouer/_Passer/Jouer/_Abandonner/Outil de score/Marquage sélectionné/Situations/Marquage carré/Marquage triangle/Affichage//Affichage/_Arbre de la partie/Affichage/_Centre de contrôle/Affichage/Barre d'_édition/Affichage/_Boutons d'actions pour la partie/Affichage/Barre d'outils _principale/Affichage/Barre de _navigation/Affichage/_Recentrer sur le noeud actif/Édition/_Fichier/_Aller à/_Aide/_Jouer/_Affichage; aux noirs de jouer; fin de partie; aux blancs de jouerApparence du plateauÉdition & AffichageGTPEnregistrements de parties (SGF)GénéralUne interface graphique pour les jeux de Go, Amazones et ReversiUne bonne largeur pour le côté droit.Le diagramme ASCII a été exporté dans le presse-papierFermer ce dialogue _automatiquement_AutomatiquementÀ propos de QuarryAjouter une étiquette au plateauAjourner & Enregistrer sous...T_oujoursBien que la longueur des étiquettes de plateau ne soit pas limitée, il est préférable de n'utiliser qu'un ou deux caractères. Les étiquettes plus longues ne seront pas visibles (ou pas immédiatement) dans la plupart des clients.Toujours utiliser l'_UTF-8 (recommandé)AmazonesApparence du plateau des AmazonesRègles des AmazonesAtaxxA_utomatiquementNPrécédentBackgammonArrière-planNoirsJoueur noirLes noirs abandonnentLes noirs perdent (temps épuisé)Les noirs ont gagnéLes noirs gagnent de %.*f pointsLes noirs gagnent avec %dLes noirs gagnent avec %dLes noirs gagnent par forfaitNoirs : %d territoireNoirs : %d territoires_Taille du plateau :Taille du plateau :Suivant les _règles du jeu (noirs)Suivant les _règles du jeu (fin de partie)Suivant les _règles du jeu (blancs)_Commentaires & noms des noeudsO_rdinateurTemps supplémentaire canadien_Sensible à la casse_Catégorie :_Couleur du quadrillage :_Opacité du quadrillage :XiangqiSélection du moteur GTP...Choisissez une texture d'arrière-plan...Le SGF du presse-papier contient probablement plus d'un arbre de partie, ou pas un seul descendant à la racine de l'unique arbre de partie.Le presse-papier contient un fragment d'enregistrement de partie (SGF) invalideLe fragment d'enregistrement de partie dans le presse-papier a probablement une taille de plateau différente.Fermer _sans enregistrer_Mention de copyright :Couleur_OrdinateurCo_mmentaires seulement_Ligne de commande :Ligne de commande :_Commentaire / description :_OrdinateurCopyrightCopyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev et autres_CréerUniquement le _noeud actif_Date :SupprimerSupprimer le noeud actifDescription & résultatUtiliser les réglages globauxÉditer les étiquettes du plateauEncodageFinLe moteur s'est figéErreur lors de la lecture du fichier "%s"Erreur lors de l'enregistrement du fichier "%s"Handicap _fix :Style du sélecteur de fichiersLe fichier "%s" ne semble pas être un fichier SGF valideIl existe déjà un fichier portant le nom "%s". Voulez-vous l'écraser avec celui que vous êtes en train d'enregistrer ?Nom de fichier :RechercherSuivantInformations sur le moteur GTPMoteurs GTPDésolé, le moteur GTP "%s" ne peut gérer les plateaux de taille %dx%dLe moteur GTP "%s" n'est pas parvenu à nettoyer le plateauLe moteur GTP "%s" n'est pas parvenu à placer les pierres de handicap sur le plateauLe moteur GTP "%s" n'a pas réussi à définir les limites de temps initiales (il pourrait les ignorer, mais ne devrait pas échouer)Le moteur GTP "%s" a affirmé pouvoir prendre en charge le jeu %s, mais n'est pas parvenu a s'initialiser pour luiLe moteur GTP calcule le score...PartiePartie & JoueursInformations sur la partieEnregistrement de la partieRègles de la partieArbre de la partie_Nom de la partie :Début de partieMatch nul_Résultats de la partie :Partie :GénéralInterface généraleGessGoApparence du plateau de GoRègles du GoAller à un noeud nomméAller au dernier noeud de la variation activeAller au noeud suivantAller au noeud précédentAller au noeud racineGomokuH_umain_Handicap :Handicap :Hex_HumainIcônes uniquementSi vous n'enregistrez pas, les modifications depuis la dernière %d heure seront définitivement perdues.Si vous n'enregistrez pas, les modifications depuis les %d dernières heures seront définitivement perdues.Si vous n'enregistrez pas, les modifications depuis la dernière %d minute seront définitivement perdues.Si vous n'enregistrez pas, les modifications depuis les %d dernières minutes seront définitivement perdues.Si vous n'enregistrez pas, les modifications depuis la dernière %d seconde seront définitivement perdues.Si vous n'enregistrez pas, les modifications depuis les %d dernières secondes seront définitivement perdues.Si vous n'enregistrez pas, les modifications depuis la dernière heure et %d minute seront définitivement perdues.Si vous n'enregistrez pas, les modifications depuis la dernière heure et %d minutes seront définitivement perdues.Si vous n'enregistrez pas, les modifications depuis la dernière minute et %d seconde seront définitivement perdues.Si vous n'enregistrez pas, les modifications depuis la dernière minute et %d secondes seront définitivement perdues.Si vous n'enregistrez pas, les modifications depuis la dernière minute seront perdues.En mode automatique l'arbre de la partie n'est affiché que s'il possède au moins une variation. Dans tous les cas, vous pouvez afficher et cacher l'arbre de la partie dans chaque fenêtre séparément.En mode automatique la vue sur l'arbre de la partie défile pour afficher le noeud actif, uniquement si le noeud actif était auparavant affiché (c'est-à-dire à moins que vous ayez fait défiler l'arbre manuellement).InfoInterfaceJungle_Compter le temps totalKomi :_Texte de l'étiquette :Dernier coup: %u,Temps limité pour toute la partieTemps limité par coupLignes d'actionConnexion au moteur GTP (%s) perdue_Gérer la liste des moteursMarquage_Coups par temps supplémentaire :Modifier les informations sur le moteur GTPCoup %d :_Descendre_Monter_Nom :Style de la barre de _navigation :NomNom :Jamai_sNouvel _enregistrement de partieNeutronNouveau moteur GTPNouvelle partieNouvel enregistrement de partieSuivanteMoulinPas de limite_Nom du noeud :Commentaire du noeud :_Noms des noeuds seulementNotez que toutes les informations dans le fichier existant seront définitivement perdues si vous choisissez de l'écraser.Notez que de nombreux caractères ne peuvent pas être représentés dans les encodages autres que UTF-8, ainsi certaines informations peuvent être perdues si vous les utilisez. Quarry fonctionne également plus vite avec l'UTF-8; cela peut être important si vous avez de très gros fichiers SGF.Notez que la plupart des moteurs GTP ne prennent en charge qu'une partie. Par conséquent certaines combinaisons jeu / joueur géré par l'ordinateur peuvent ne pas être possibles.Temps _supplémentaire :OctiSur les amazones _noires :Sur les disques _noirs :Sur les pierres _noires :Sur les cases _vides :Sur les intersections _vides :Sur les amazones _blanches :Sur les disques _blancs :Sur les pierres _blanches :OuvrirOuvrir un fichier SGF...Ouvrir une partie enregistréeOptionsLecture du fichier "%s"...PasserLe binaire du moteur a peut-être été supprimé ou modifié. Vous devrez probablement modifier la ligne de commande du moteur dans la boîte de dialogue "Préférences".PhutballSélectionnez la couleur d'arrière-planSélectionnez la couleur du quadrillage de l'échiquierSélectionnez la couleur de la grille et des étiquettesSélectionnez une couleur pour le marquageChoisissez une couleurVeuillez vérifier que le fichier existe et que vous êtes autorisé à le lire.Assurez-vous d'avoir bien écrit le nom de fichier du moteur, et que vous êtes autorisé à l'exécuter.Veuillez choisir les pierres mortes pour établir le scoreVeuillez placer %d pierre (ou moins) de handicap libreVeuillez placer %d pierres (ou moins) de handicap librePréférencesPréserver l'encodage d'_originePrécédenteQuadratureCentre de contrôle QuarryQuarry utilise le format de fichier SGF pour stocker les enregistrements de parties. Les fichiers SGF portent normalement l'extention ".sgf", mais ce n'est pas toujours le cas. Assurez-vous de sélectionner un véritable fichier SGF.Interrogation du moteur pour le nom, la version et les commandes connues..._Manche :Rang :Réellement abandonner la partie ?RestaurerRestaurer la dernière action annuléeAbandonnerReprendre la partie...Reprise de la partieReversiApparence du plateau de ReversiRègles du ReversiRacine_Règles :EnregistrerEnregistrer sous...Enregistrer les modifications de la partie "%s" avant de fermer ?Enregistrer les modifications de la partie sans nom avant de fermer ?Enregistrer le fichier courantEnregistrementEnregistrement de partiesNom à l'_écran :Faire défiler sur une distance _minimaleÉtendue de la recherche_Rechercher :Recherche une chaîne de caractères dans les commentairesLe diagramme au format Sensei's Library a été exporté dans le presse-papierSpécifier le numéro du coupShÅgiInformations brèves sur la partieAfficherAfficher l'arbre de la partieAfficher les bulles d'aideTaille & OpacitéDésolé, il n'y a pas de noeud nommé dans cet arbre de partieJeux pris en charge :Jeux pris en charge :Basculer sur la variation suivanteBasculer sur la variation précédenteTantrixÉquipe :Texte sous les icônesTexte à côté des icônes importantesTexte uniquementLe moteur a peut-être planté, quitté prématurément ou s'est déconnecté. Veuillez vérifier la ligne de commande, y compris les options, et consultez la documentation du moteur si nécessaire.La partie est ajournée et enregistrée dans le fichier "%s"Match nulLa partie stockée dans le fichier "%s" (%s) n'est pas prise en charge par QuarryCe noeud n'existe pasCe moteur provient de la configuration du site.Cette partie semble terminée. Voulez-vous l'ouvrir pour affichage et édition ?Ceci est une erreur provenant du moteur de jeu. Vous pourriez la communiquer aux auteurs de ce dernier.Limite de temps_Limite de temps pour la partie :_Limite de temps par coup :_Type de contrôle du temps :Styles des barres d'outilsBulles d'aideTraquer le noeud actif dans l'arbreTraxImpossible de coller le fragment d'enregistrement de partie à partir du presse-papierImpossible de coller le fragment d'enregistrement de partie à partir du presse-papier, car il n'est pas fait pour être colléAnnulerAnnuler la dernière actionPartie sans nomUtiliser le _nouveau sélecteur de fichier (GTK+ 2.4)Utiliser l'_ancien sélecteur de fichierUtiliser une couleur _unie :Utiliser une _texture :Utiliser des numéros de coups sé_quentielsUtiliser les valeurs par _défaut du thèmeVersion :Afficher et éditer les informations sur la partieBEn attente que le moteur quitteBlancsJoueur blancLes blancs abandonnentLes blancs perdent (temps épuisé)Les blancs ont gagnéLes blancs gagnent de %.*f pointsLes blancs gagnent avec %dLes blancs gagnent avec %dLes blancs gagnent par forfaitBlancs : %d territoireBlancs : %d territoiresMots _entiers seulement_Tout l'arbre de la partieRecommencer au _débutVous pouvez modifier les informations sur la partie plus tard en choisissant "Édition/Informations sur la partie" dans le menu, ou en pression le bouton "Info" de la barre d'outils principale.Vous pouvez reprendre la partie plus tard en pressant le bouton "Reprendre la partie" dans le centre de contrôle Quarry, ou en choisissant l'entrée correspondante du menu "Fichier".Vous pouvez utiliser les chaînes de caractères "%n" et "%v" dans le champ "Nom à l'écran". Elles seront remplacées par le nom et la version du moteur, respectivement. Par défaut "%n %v" est utilisé comme nom à l'écran.Vous pouvez généralement coller le diagramme dans une autre application en utilisant la combinaison de touches "Ctrl + C", ou en choisissant l'entrée appropriée du menu.[inconnu]_Toujours_Amazones_Annotateur :Joueur _noir :_Parcourir..._TerminéStyle de la barre d'_édition :_Données saisies par :_Événement :Handicap _libre :Nom de la _partie :_Go_Aller au noeudCouleur de la _grille et des étiquettes :_Komi :_Liste des moteurs GTP :Temps _principal :Style de la barre d'outils _principale :_ModifierN_om :_Jamais_Nouvelle partie_Opacité :_Ouvrir une partie enregistrée_Ouverture jouée :_Durée du temps supplémentaire :_Écraser_Placer les pierres_Lieu :_Jouer_Recentrer la vue sur le noeud actif_Relatif à la taille des amazones_Relatif à la taille des disques_Relatif à la taille des pierres_Abandonner_Reprendre_Reprendre une partie_Reversi_Spécifier un numéro de coup :_Taille :_Source :_Échanger_Thème :Joueur _blanc :échecscommentaire|Viderechercher|_Suivantrechercher|_Précédenthandicap|Non spécifiéinsérez ici le nom du noeudkomi|Non spécifiémodifiépassequarry-0.2.0/po/pl.gmo0000644000175000017500000010576310530113072013237 0ustar bartbartÞ•¿W h%i%#%£%À%×%è%ø% & "&&/&;V&%’&¸&8Ø& '2' A'O' V'a''•'¦'»'Ó'ë'(#(;(W(s(†( ( ª(·(Ñ(î( )#)>)V)m)†)ž)») Ñ)Ý) ð) ü) * *!*(*)G*q*‹* *ª*»*Î* Ý*é* ÿ* ++$+<+T+k+„++¬+¿+ Î+Û+ ë+ ÷+ ,,, *, 6, D,R, c,o,~,,–,§,½,Ô,ï,--=-D-K-P-W-^-e- u--‘-©- Æ-Ñ-ë-5ú-(0.,Y.†.ž. ­.º.Ê.ß.µç./½/Å/ Þ/ì/ò/00 0 00 %0 20 @0 a0l0!0¡0'·0 ß0 ì0ø01*1A1 X1b1t1 „11¬1 Ë1Ù1î1p 28~2G·2ÿ23(3 .383G3 V3d3 |3†3?š3Ú3â3õ3ü34404@4Q4Z4^4m4…4–4/°4Xà4 95C5H5P5 g55s5)©56Ó5V 6Xa6º6Ó6Ø6ç6 ø6 7 7 7%7 47 A7O7U7]7o7t7w7‹7”7'¥7Í7á7ù7 88 8 &80848 ;8–F8šÝ8šx9¬:°À:Bq;“´;¡H<ê< ï<ù<== =-===Z=p="€=£=·=¾=Ó= ñ= û=>>>1>6><>C>T>\>k>t>„>‰>›> ¤> °>¾>fÏ>Û6?€@ “@ž@£@¶@Ç@Ù@ë@AA(A:A?APAcAkA€A……A B"B8BXBwB BJšBbåB+HCdtC ÙCåCD DD´+D5àDEE$E=EBE^EeE tE‚EŠE £E±E ¶EÁE ÆE0ÑE8F;FQFXF lFzF “F  F­F7ÍFGGG2G7GFGUG1dG–G¦G·G ÔGõGýGHH 0H:H,ØHI<ISI*iIT”IEéI /J:JPJfJzJ‰J’J¬J3±JXåJ>KCK XK"eK$ˆK­K ¿KÍKéKýKL%L!(LJL PL ]L kL ŒL—L!ªLÌL'âL MM -M’:M’ÍM¦`N~O †OO˜O ¡O­O ¼OÇOÍO åOòOúO PP P&P>PEP [PgP|P„P‹P ’P œP¦P¸PÉP âP íPûPQ" Q,QEQ\QtQ|Q „Q‘QšQµQ¼QÅQËQÓQâQ èQ öQRR!R 7RDRMR³RRT5T*RT!}TŸT»T,ËTøT U*!U?LU*ŒU!·U1ÙU* V6VIV^VgVwV!•V·VÒVîV W#W=W3]W&‘W&¸WßWôWX#X'7X&_X&†X$­X%ÒXøXY$2YWY(wY Y½YÍYäYõYZZ$Z+Z.KZzZ“Z©Z¸ZÊZÝZïZÿZ [%[,[E[!^[$€[¥[#½[á[ú[\$\8\ L\ V\`\r\x\ Œ\ –\£\µ\ É\Ö\ê\]]]:]O]e]|](–]¿]È]Ï]Ö]Þ]ä]ì] ü] ^^0^ N^Y^r^/^0±^/â^_2_A_T_d_ƒ_Ï‹_ [`|`…`¥`¶`¼`Ë`Î` Õ`ß`ä`ë`ò`$a,a¬à š~Ç!ž6fNž’|ùT£ʦ{.ú‚Ôs;‹)"áh‘@=ØGµ¾Ã?Ñ'2 Ÿ,º=ƒ†šë–€8F·ø#©zJ„n†Â5¹e~…§Þ³Û9ç´qM#WVgvK‹ÄÌŒÙCŽoß&DR¬³`4sFµü™6gHÈm7‰½pX§IíåB/_°‰Q€­²ª<L*Yu Šâ½ErxkN,®lº\t¿?d]ƒ%}pU«ïŠ…þœ–Vu®JËó(•!»Z4ä/ B.\P0²7 3Uh|>æ1ixÆ&ôÀÉAHe‡b »Ö9“_)“-«E‚ðQ¯-ÎGyO¸ì¤¨ ±`›ò£”ÍcÚ¡$ˆ ý×êXRW(w©Aj2$ã’Ï •·¶‘:<^t3÷PC{^ [r[ %s %.*f komi = %.*f %s %d komi = %d %s %d komi = %d + %d capture + %d captures%d capture%d captures%d disk%d disks%s %s %.*f komi%s %s %d komi%s %s %d komi%s (W) vs. %s(per player)* ERROR: mismatched ID (%d expected): * ERROR: unexpected ID in response (the command had none): * ERROR: unrecognized response line: * ERROR: wrong response format * WARNING: future GTP version, I don't know about it... * WARNING: unexpected response: /Circle Markup/Cross Markup/Edit//Edit/Cu_t/Edit/Delete Node's C_hildren/Edit/Edit Node _Name/Edit/Find Ne_xt/Edit/Find Pre_vious/Edit/Game _Information/Edit/Move Branch Do_wn/Edit/Move _Branch Up/Edit/P_layer to Move/Edit/Player to Move/By Game _Rules/Edit/Player to Move/_Black/Edit/Player to Move/_White/Edit/Pr_eferences/Edit/Set _Move Number/Edit/T_ools/Edit/Tools//Edit/Tools/C_ross Markup/Edit/Tools/S_elected Markup/Edit/Tools/S_quare Markup/Edit/Tools/Scori_ng Tool/Edit/Tools/_Circle Markup/Edit/Tools/_Label Tool/Edit/Tools/_Move Tool/Edit/Tools/_Number Tool/Edit/Tools/_Setup Tool/Edit/Tools/_Triangle Markup/Edit/_Add Empty Node/Edit/_Copy/Edit/_Delete Node/Edit/_Find/Edit/_Paste/Edit/_Redo/Edit/_Undo/File//File/Export.../_ASCII Diagram/File/Export.../_Sensei's Library Diagram/File/Ne_w Game Record.../File/Save _As.../File/_Close/File/_Export.../File/_New Game.../File/_Open.../File/_Quit/File/_Resume Game.../File/_Save/Go//Go/Ne_xt Variation/Go/Pre_vious Variation/Go/Ten Nodes _Backward/Go/Ten Nodes _Forward/Go/Variation _Last Node/Go/_Go to Named Node.../Go/_Next Node/Go/_Previous Node/Go/_Root Node/Help/_About/Help/_Contents/Label Tool/Move Tool/Number Tool/Play//Play/_Adjourn Game/Play/_Pass/Play/_Resign/Scoring Tool/Selected Markup/Setup Tool/Square Markup/Triangle Markup/View//View/Game _Tree/View/_Control Center/View/_Editing Toolbar/View/_Game Action Buttons/View/_Main Toolbar/View/_Navigation Toolbar/View/_Recenter on Current Node/_Edit/_File/_Go/_Help/_Play/_View; black to play; game over; white to playBoard AppearanceEditing & ViewingGTPGame Records (SGF)GeneralA GUI program for Go, Amazons and Reversi board gamesA good width for the right side to have.ASCII diagram has been exported to clipboardA_uto-close this dialogA_utomaticallyAbout QuarryAdd Board LabelAdjourn & Save As...Al_waysAlthough board labels are not limited in length, it is better to use only one or two characters long labels. Longer labels will not be visible immediately or at all in most clients.Always use _UTF-8 (recommended)AmazonsAmazons Board AppearanceAmazons RulesAtaxxAut_omaticallyB BackBackgammonBackgroundBlackBlack PlayerBlack resignsBlack runs out of time and losesBlack winsBlack wins by %.*fBlack wins by %dBlack wins by %dBlack wins by forfeitBlack: %d territoryBlack: %d territoryBoard _size:Board size:By Game _Rules (Black)By Game _Rules (Game Over)By Game _Rules (White)C_omments & node namesC_omputerCanadian overtimeCase _sensitiveCategor_y:Checkerboard _pattern color:Checkerboard pattern _opacity:Chinese chessChoose GTP Engine...Choose a Background Texture...Clipboard SGF probably contains more than one game tree or not a single child of the root of the only game tree.Clipboard contains an invalid game record fragment (SGF)Clipboard game record fragment must be of different game or board size.Close _without SavingCo_pyright string:ColorCom_puterComm_ents onlyCommand _line:Command line:Comment / _description:Compu_terCopyright & CreditsCopyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev and othersCrea_teCurrent no_de onlyDa_te:DeleteDelete the current nodeDescription & ResultDesktop defaultEdit Board LabelEncodingEndEngine hung upError reading file `%s'Fi_xed handicap:File Chooser Dialog StyleFile `%s' doesn't appear to be a valid SGF fileFile named `%s' already exists. Do you want to overwrite it with the one you are saving?Filename:FindForwardGTP Engine InformationGTP EnginesGTP engine `%s' cannot handle %dx%d board size, sorryGTP engine `%s' failed to clean the boardGTP engine `%s' failed to set handicap stones on boardGTP engine `%s' failed to set initial time limits (it could ignore them, but not fail)GTP engine `%s' reported it could handle %s game, but failed to initialize itself for itGTP engine is scoring...GameGame & PlayersGame InformationGame RecordGame RulesGame TreeGame _name:Game beginningGame is drawGame re_sult:Game:GeneralGeneral InterfaceGessGoGo Board AppearanceGo RulesGo to Named NodeGo to the current variation's last nodeGo to the next nodeGo to the previous nodeGo to the root nodeGomokuH_umanHan_dicap:Handicap:HexHu_manIcons onlyIf you don't save, changes from the last %d hour will be lost permanently.If you don't save, changes from the last %d hours will be lost permanently.If you don't save, changes from the last %d minute will be lost permanently.If you don't save, changes from the last %d minutes will be lost permanently.If you don't save, changes from the last %d second will be lost permanently.If you don't save, changes from the last %d seconds will be lost permanently.If you don't save, changes from the last hour and %d minute will be lost permanently.If you don't save, changes from the last hour and %d minutes will be lost permanently.If you don't save, changes from the last minute and %d second will be lost permanently.If you don't save, changes from the last minute and %d seconds will be lost permanently.If you don't save, changes from the last minute will be discarded.In automatic mode the game tree is shown only if it has at least one variation. In any case, you can show/hide game tree in each window separately.In automatic mode the game tree view scrolls to show the current node only if it has been showing current node before. I.e. unless you scrolled it away manually.InfoInterfaceJungleK_eep track of total timeKomi:Label _text:Last move: %u, Limited time for entire gameLimited time per moveLines of ActionLost connection to GTP Engine (%s)Manage _Engine ListMarkupMo_ves per overtime:Modify GTP Engine InformationMove %d: Move _DownMove _UpN_ame:N_avigation toolbar style:NameName:Ne_verNe_w Game RecordNeutronNew GTP EngineNew GameNew Game RecordNextNine Men's MorrisNo limitNode _name:Node comment:Node na_mes onlyNote that all information in the existing file will be lost permanently if you choose to overwrite it.Note that many characters cannot be represented in non-UTF-8 encodings and thus some information may be lost if you use them. Quarry also works fastest with UTF-8; this may be important if you have very large SGF files.Note that most GTP engines support only one game. Hence certain game / computer player combinations may be not possible to play.O_vertime:OctiOn _black amazons:On _black disks:On _black stones:On _empty fields:On _empty intersections:On _white amazons:On _white disks:On _white stones:OpenOpen SGF File...Open a game recordOptionsParsing file `%s'...PassPerhaps engine's binary has been deleted or changed. You will probably need to alter engine's command line in the Preferences dialog.Philosopher's FootballPick Background ColorPick Checkerboard Pattern ColorPick Color for Grid and LabelsPick Color for MarkupPick a ColorPlease check that the file exists and its permission allow you to read it.Please make sure you typed engine's filename correctly and that you have permission to execute it.Please select dead stones to score the gamePlease set up %d (or less) stone of free handicapPlease set up %d (or less) stones of free handicapPreferencesPreserve _original encodingPreviousQuadratureQuarry Control CenterQuarry uses SGF file format for storing game records. SGF files would normally have `sgf' extension, but that's not necessarily true. Please make sure you select a proper SGF file.Querying engine's name, version and known commands...R_ound:Rank:Really resign this game?RedoRedo the last undone actionResignResume Game...Resuming GameReversiReversi Board AppearanceReversi RulesRootRule _set:SaveSave As...Save changes to game record `%s' before closing?Save changes to the untitled game record before closing?Save the current fileSavingSaving Game RecordsScreen _name:Scroll _minimal distanceSearch ScopeSearch _for:Search for a string in commentsSensei's Library diagram has been exported to clipboardSet Move NumberShogiShort Game InformationShowShow Game TreeShow _tooltipsSize & OpacitySorry, there are no named nodes in this game treeSupported game:Supported games:Switch to the next variationSwitch to the previous variationTantrixTeam:Text below iconsText beside important iconsText onlyThe engine might have crashed, quit prematurely or disconnected. Please verify command line, including options, and consult engine's documentation if needed.The game is adjourned and saved in file `%s'The game is drawThe game stored in file `%s' (%s) is not supported by QuarryThere is no such nodeThis engine comes from site configuration.This game appears to have been finished. Open it for viewing and/or editing instead?This is an engine error. You may want to report it to engine authors.Time LimitTime _limit for game:Time _limit for move:Time control _type:Toolbar StylesTooltipsTrack Tree's Current NodeTraxUnable to paste game record fragment from clipboardUnable to paste game record fragment from clipboard since it is not intended for pastingUndoUndo the last actionUnnamed GameUse _newer (GTK+ 2.4) file chooserUse _old-style file selection dialogUse _solid color:Use _texture:Use se_quential move numberUse theme _defaultsVersion:View and edit game informationW Waiting for the engine to quit...WhiteWhite PlayerWhite resignsWhite runs out of time and losesWhite winsWhite wins by %.*fWhite wins by %dWhite wins by %dWhite wins by forfeitWhite: %d territoryWhite: %d territoryWhole _words onlyWhole game _treeWrap _aroundYou can always change and expand game information later. Just choose `Edit/Game Information' menu item or press `Info' button on the main toolbar.You can later resume the game by pressing the `Resume Game' button in Quarry Control Center, or selecting `Resume Game' item from the `File' menu.You can use `%n' and `%v' strings in Screen name field. They will substituted with name and version of the engine correspondingly. By default, `%n %v' is used.You can usually paste the diagram in another application using `Ctrl+C' key combination or by selecting appropriate menu item.[unknown]_Always_Amazons_Annotator:_Black player:_Browse..._Done_Editing toolbar style:_Entered by:_Event:_Free handicap:_Game name:_Go_Go to Node_Grid and labels color:_Komi:_List of GTP engines:_Main time:_Main toolbar style:_Modify_Name:_Never_New Game_Opacity:_Open Game Record_Opening played:_Overtime period length:_Overwrite_Place stones_Place:_Play_Recenter view on the current node_Relative to amazon size_Relative to disk size_Relative to stone size_Resign_Resume_Resume Game_Reversi_Set specific move number:_Size:_Source:_Swap_Theme:_White player:chesscomment|Emptyfind|_Nextfind|_Previoushandicap|Not setinsert node name herekomi|Not setmodifiedpassProject-Id-Version: Quarry 0.1.16 Report-Msgid-Bugs-To: quarry-dev@gna.org POT-Creation-Date: 2006-11-07 18:33+0200 PO-Revision-Date: 2006-11-07 18:42+0200 Last-Translator: Robert Stefaniuk Language-Team: Polish MIME-Version: 1.1 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2); %s %.*f komi = %.*f %s %d komi = %d %s %d komi = %d %s %d komi = %d + %d jeniec + %d jeÅ„ców + %d jeÅ„ców%d jeniec%d jeÅ„ców%d jeÅ„ców%d dysk%d dyski%d dysków%s %s %.*f komi %s %s %d komi %s %s %d komi %s %s %d komi%s (B) kontra %s(dla każdego z graczy)* BÅÄ„D: niepoprawny ID (oczekiwano %d): * BÅÄ„D: nieoczekiwany ID w odpowiedzi (komenda nie posiada): * BÅÄ„D: nierozpoznana linia odpowiedzi: * BÅÄ„D: zÅ‚y format odpowiedzi * OSTRZEÅ»ENIE: nowa wersja GTP, nie znana mi... * OSTRZERZENIE: nieoczekiwana odpowiedź: /Znaczniki: okrÄ…g/Znaczniki: krzyżyk/Edycja//Edycja/_Wytnij/Edycja/U_suÅ„ dalsze wÄ™zÅ‚y/Edycja/_Modyfikuj nazwÄ™ wÄ™zÅ‚a/Edycja/Znajdź _nastÄ™pne/Edycja/Znajdź _poprzednie/Edycja/In_formacja o grze/Edycja/N_iższa gałąź/Edycja/W_yższa gałąź/Edycja/_Gracz wykonujÄ…cy ruch/Edycja/Gracz wykonujÄ…cy ruch/_Zgodnie z reguÅ‚ami/Edycja/Gracz wykonujÄ…cy ruch/_Czarny/Edycja/Gracz wykonujÄ…cy ruch/_BiaÅ‚y/Edycja/Pr_eferencje/Edycja/Wstaw numer _ruchu/Edycja/_NarzÄ™dzia/Edycja/NarzÄ™dzia//Edycja/NarzÄ™dzia/Znaczniki: _krzyżyk/Edycja/NarzÄ™dzia/_Znaczniki: wÅ‚asny/Edycja/NarzÄ™dzia/Znaczniki: kwa_drat/Edycja/NarzÄ™dzia/Ustalanie _wyniku/Edycja/NarzÄ™dzia/Znaczniki: _okrÄ…g/Edycja/NarzÄ™dzia/Etykiet_y/Edycja/NarzÄ™dzia/Tryb _gry/Edycja/NarzÄ™dzia/_Numerowanie pól/Edycja/NarzÄ™dzia/Tryb _edycji/Edycja/NarzÄ™dzia/Znaczniki: _trójkÄ…t/Edycja/_Dodaj pusty wÄ™zeÅ‚/Edycja/_Kopiuj/Edycja/_UsuÅ„ wÄ™zeÅ‚/Edycja/_Znajdź/Edycja/Wkle_j/Edycja/P_onów/Edycja/_Cofnij/Plik//Plik/Eksport.../Diagram _ASCII/Plik/Eksport.../Diagram dla _Sensei's Library/Plik/_Nowy zapis gry.../Plik/Z_apisz jako.../Plik/Za_mknij/Plik/_Eksport.../Plik/Nowa _gra.../Plik/_Otwórz.../Plik/Za_koÅ„cz/Plik/_DokoÅ„cz grÄ™.../Plik/_Zapisz/Idź//Idź/NastÄ™pny warian_t/Idź/Poprzedni _wariant/Idź/DziesiÄ™_c wÄ™złów wstecz/Idź/_Dziesięć wÄ™złów w przód/Idź/_Koniec sekwencji/Idź/Idź do na_zwanego wÄ™zÅ‚a.../Idź/_NastÄ™pny wÄ™zeÅ‚/Idź/_Poprzedni wÄ™zeÅ‚/Idź/P_oczÄ…tek/Pomoc/_o programie/Pomoc/_Zawartość/Etykiety/Tryb gry/Numerowanie pól/Gra//Gra/_Odłóż grÄ™/Gra/_Pas/Gra/Po_ddaj/Ustalanie wyniku/Znaczniki: wÅ‚asny/Tryb edycji/Znaczniki: kwadrat/Znaczniki: trójkÄ…t/Widok//Widok/_Drzewo ruchów/Widok/_Centrum sterowania/Widok/Pasek _edycji/Widok/P_rzyciski gry/Widok/Pasek _główny/Widok/Pasek _poÅ‚ożenia/Widok/_WyÅ›rodkuj na bieżącym węźle/_Edycja/_Plik/_Idź/Pomo_c/_Gra/_Widok; ruch czarnych; koniec gry; ruch biaÅ‚ychWyglÄ…d planszyEdycja i przeglÄ…danieGTPZapisy gier (SGF)OgólneGraficzny program do gier Go, Amazons i ReversiWÅ‚aÅ›ciwa szerokość panelu po prawej stronie.Diagram ASCII zostaÅ‚ wyeksportowany do schowka_Zamknij to okno po znalezieniu_AutomatycznieO programie QuarryDodaj etykietÄ™Odłóż grÄ™ i zapisz jako...Zaw_szeChociaż nazwy etykiet mogÄ… mieć dowolnÄ… dÅ‚ugość, bezpieczniejsze sÄ… nazwy maksymalnie dwuznakowe. DÅ‚uższe nazwy mogÄ… być z poczÄ…tku niewidoczne albo niewidoczne wcale dla wiÄ™kszoÅ›ci klientów._Zawsze używaj UTF-8 (zalecane)amazonkiWyglÄ…d planszy do gry amazonkiReguÅ‚y amazonekAtaxxAut_omatycznieC Wstecztrik-trakTÅ‚oCzarneCzarneCzarne poddaÅ‚y grÄ™Czarne wyczerpaÅ‚y czas i przegraÅ‚yCzarne wygraÅ‚yCzarne wygraÅ‚y o %.*f punktówCzarne wygraÅ‚y o %d punktCzarne wygraÅ‚y o %d punktyCzarne wygraÅ‚y o %d punktówCzarne wygraÅ‚y przez poddanieCzarne: %d punkt terytoriumCzarne: %d punkty terytoriumCzarne: %d punktów terytoriumRozmiar _planszy:Rozmiar planszy:Zgodnie z _reguÅ‚ami (czarny)Zgodnie z _reguÅ‚ami (koniec)Zgodnie z _reguÅ‚ami (biaÅ‚y)Komentarze _i nazwy wÄ™złów_KomputerKanadyjskie byo-yomi_Rozróżnianie wielkoÅ›ci literKategori_a:Kolor zaciemnienia _pól:_Intensywność zaciemnienia pól:szachy chiÅ„skieWybór algorytmu GTP...Wybór tekstury dla tÅ‚a...SGF ze schowka prawdopodobnie zawiera wiÄ™cej niż jedno drzewo ruchów albo wiÄ™cej niż jednÄ… odnogÄ™ drzewa ruchów.Schowek zawiera błędny fragment zapisu gry (SGF)Zapis gry w schowku ma inny rozmiar planszy lub dotyczy innej gry.Zamknij _bez zapisywaniaWiersz praw _autorskich:KolorKo_mputerTylko _komentarze_Polecenie:Polecenie:_Komentarz/opis:_KomputerInformacje o pliku i prawach autorskichCopyright © 2003, 2004, 2005, 2006 PaweÅ‚ Pogonyszew i inni_Utwórz_Tylko bieżący wÄ™zeÅ‚_Data:UsuÅ„Usuwa bieżący wÄ™zeÅ‚Opis i wynikDomyÅ›lny dla Å›rodowiskaModyfikuj wstawionÄ… etykietÄ™KodowanieKoniecAlgorytm zawiesiÅ‚ siÄ™Błąd przy próbie odczytu pliku „%sâ€_Handikap tradycyjny:Styl okna wyboru otwieranego plikuPlik „%s†nie wyglÄ…da na poprawny plik typu SGFPlik o nazwie „%s†już istnieje. Czy chcesz go zastÄ…pić obecnie zapisywanym plikiem?Nazwa pliku:ZnajdźDalejInformacja o algorytmie GTPAlgorytmy GTPAlgorytm GTP „%s†niestety nie obsÅ‚uguje rozmiaru planszy %dx%dAlgorytm GTP „%s†nie wyczyÅ›ciÅ‚ planszyAlgorytm GTP „%s†nie ustawiÅ‚ kamieni handikapowych na planszyAlgorytm GTP „%s†nie ustawiÅ‚ poczÄ…tkowego limitu czasu (można go ignorować, ale nie błędnie ustawiać)Algorytm GTP „%s†zgÅ‚osiÅ‚ możliwoÅ›c obsÅ‚ugi gry %s, ale nie zainicjowaÅ‚ swojego dziaÅ‚aniaAlgorytm GTP szacuje wynik...GraGra i przeciwnicyInformacje o grzeAutorzy i uprawnieniaReguÅ‚y gryDrzewo ruchów_Nazwa gry:PoczÄ…tek gryRemis_Wynik:Gra:Ogólne informacjeOgólne opcje interfejsuGessgoWyglÄ…d gobanu (planszy do gry go)ReguÅ‚y goIdź do nazwanego wÄ™zÅ‚aPrzechodzi do koÅ„ca bieżącej sekwencji ruchówPrzechodzi do nastÄ™pnego wÄ™zÅ‚aPrzechodzi do poprzedniego wÄ™zÅ‚aPrzechodzi do poczÄ…tku drzewa ruchówgomoku_CzÅ‚owiek_Handikap:Handikap:HexCzÅ‚o_wiekTylko ikonyJeÅ›li nie zapiszesz, zmiany z ostatniej %d godziny zostanÄ… bezpowrotnie utracone.JeÅ›li nie zapiszesz, zmiany z ostatnich %d godzin zostanÄ… bezpowrotnie utracone.JeÅ›li nie zapiszesz, zmiany z ostatnich %d godzin zostanÄ… bezpowrotnie utracone.JeÅ›li nie zapiszesz, zmiany z ostatniej %d minuty zostanÄ… bezpowrotnie utracone.JeÅ›li nie zapiszesz, zmiany z ostatnich %d minut zostanÄ… bezpowrotnie utracone.JeÅ›li nie zapiszesz, zmiany z ostatnich %d minut zostanÄ… bezpowrotnie utracone.JeÅ›li nie zapiszesz, zmiany z ostatniej %d sekundy zostanÄ… bezpowrotnie utracone.JeÅ›li nie zapiszesz, zmiany z ostatnch %d sekund zostanÄ… bezpowrotnie utracone.JeÅ›li nie zapiszesz, zmiany z ostatnich %d sekund zostanÄ… bezpowrotnie utracone.JeÅ›li nie zapiszesz, zmiany z ostatniej godziny i %d minuty zostanÄ… bezpowrotnie utracone.JeÅ›li nie zapiszesz, zmiany z ostatniej godziny i %d minut zostanÄ… bezpowrotnie utracone.JeÅ›li nie zapiszesz, zmiany z ostatniej godziny i %d minut zostanÄ… bezpowrotnie utracone.JeÅ›li nie zapiszesz, zmiany z ostatniej minuty i %d sekundyzostanÄ… bezpowrotnie utracone.JeÅ›li nie zapiszesz, zmiany z ostatniej minuty i %d sekund zostanÄ… bezpowrotnie utracone.JeÅ›li nie zapiszesz, zmiany z ostatniej minuty i %d sekund zostanÄ… bezpowrotnie utracone.JeÅ›li nie zapiszesz, zmiany z ostatniej minuty zostanÄ… porzucone.W trybie automatycznym drzewo ruchów pokazywane jest jedynie wtedy, gdy posiada rozgałęzienia. Można je jednak wyÅ›wietlać i ukrywać niezależnie w każdym oknie.W trybie automatycznym widok drzewa gry stara siÄ™ zawsze obejmować bieżący wÄ™zeÅ‚, o ile nie wypadÅ‚ on poza jego obrÄ™b przy przesuwaniu tego widoku przez użytkownika.InformacjeInterfejsJungleOdmierzaj _czas caÅ‚kowityKomi:_Tekst etykiety:Ostatni ruch: %u, Limit czasu dla caÅ‚ej gryLimit czasu na każdy ruchLines of ActionNieoczekiwane zakoÅ„czenie pracy z algorytmem (%s)Sprawdź _listÄ™ algorytmówZnacznikiIloÅ›c _ruchów w tym okresie:Modyfikuj informacje o algorytmie GTPRuch %d: W _dółW _górÄ™G_racz:Styl paska _poÅ‚ożenia:NazwaNazwa:Ni_gdy_Nowy zapis gryNeutronNowy algorytm GTPNowa graNowy zapis gryNastÄ™pnyNine Men’s MorrisBez limituSzukana _nazwa:Komentarz dla wÄ™zÅ‚a:Tylko _nazwy wÄ™złówPamietaj, że wszystkie dane z istniejÄ…cego pliku zostanÄ… bezpowrotnie utracone, jeÅ›li go nadpiszesz.UTF-8 jest zalecane, ponieważ pozwala używać o wiele wiÄ™kszej gamy znaków, niż inne standardy kodowania. Dodatkowo, Quarry operuje szybciej na plikach zapisanych w tym standardzie. Może to mieć szczególne znaczenie przy pracy z bardzo dużymi plikami SGF.PamiÄ™taj, że wiÄ™kszość algorytmów GTP obsÅ‚uguje tylko jeden rodzaj gry. Dlatego niektóre kombinacje gier i graczy komputerowych nie mogÄ… być użyte.C_zas dodatkowy:OctiNa c_zarnych „amazonkachâ€:Na c_zarnych dyskach:Na c_zarnych kamieniach:Na _pustych polach:Na _pustych przeciÄ™ciach:Na _biaÅ‚ych „amazonkachâ€:Na _biaÅ‚ych dyskach:Na _biaÅ‚ych kamieniach:OtwórzOtwórz plik SGF...Otwiera zapisanÄ… grÄ™OpcjePrzetwarzanie pliku „%sâ€...PasByć może plik wykonalny algorytmu zostaÅ‚ usuniÄ™ty lub zmieniony. Prawdopodobnie polecenie uruchamiajÄ…ce algorytm bÄ™dzie musiaÅ‚o zostać zmienione w oknie preferencji.Philosopher’s FootballWybór koloru tÅ‚aWybór koloru zaciemnienia czarnych pólWybór koloru siatki i współrzÄ™dnychWybór koloru dla znacznikówWybór koloruSprawdź, czy plik na pewno istnieje i jego uprawnienia pozwalajÄ… Ci go odczytywać.Upewnij siÄ™, że wskazaÅ‚eÅ› wÅ‚aÅ›ciwÄ… nazwÄ™ pliku wykonalnego algorytmu i masz uprawnienia do jego uruchamiania.Zaznacz martwe kamienie, aby ustalić wynik%dUstaw gdziekolwiek %d (lub mniej) kamienie jako handikapUstaw gdziekolwiek %d (lub mniej) kamieni jako handikapPreferencjeZachowaj _oryginalne kodowaniePoprzedniQuadratureCentrum sterowania QuarryQuarry używa formatu SGF do zapisywania gier. Pliki SGF powinny raczej posiadać rozszerzenie „.sgfâ€, ale nie jest to konieczne. Upewnij siÄ™, że wybraÅ‚eÅ› wÅ‚aÅ›ciwy plik SGF.Komunikacja z algorytmem w celu ustalenia jego wersji, nazwy i obsÅ‚ugiwanych komend...R_unda:Ranking:Czy naprawdÄ™ chcesz poddać tÄ™ grÄ™?PonówWykonuje z powrotem ostatniÄ… cofniÄ™tÄ… operacjÄ™PoddajDokoÅ„cz grÄ™...DokoÅ„czenie przerwanej gryreversiWyglÄ…d planszy do gry reversiReguÅ‚y reversiPoczÄ…tekReguÅ‚_y:ZapiszZapisz jako...Zapisać zmiany w pliku „%s†przed jego zamkniÄ™ciem?Zapisać zmiany w utworzonym pliku przed jego zamkniÄ™ciem?Zapisuje bieżący plikZapis do plikuZapisywanie plików z gramiWyÅ›wietlana _nazwa:U_trzymuj bieżący wÄ™zeÅ‚ w widoku drzewaZakres wyszukiwania_Znajdź:Szuka podanego tekstu w komentarzachDiagram w formacie Sensei's Library zostaÅ‚ wyeksportowany do schowkaWprowadź numer ruchuszogiKrótka informacja o grzeDostÄ™pnyPokazuj drzewo ruchówPokazuj _dopiskiRozmiar i intensywnośćPrzykro mi, ale nie ma żadnych nazwanych wÄ™złówObsÅ‚ugiwana gra:ObsÅ‚ugiwane gry:Przechodzi do nastÄ™pnego wariantuPrzechodzi do poprzedniego wariantuTantrixDrużyna:Tekst poniżej ikonTekst poniżej głównych ikonTylko tekstAlgorytm mógÅ‚ zawiesić siÄ™, zakoÅ„czyć przedwczeÅ›nie dziaÅ‚anie lub otrzymać komendÄ™ trybu GTP, którÄ… zinterpretowaÅ‚ jako koniec pracy. Sprawdź, czy wpisane polecenie jest wÅ‚aÅ›ciwe (zwróć uwagÄ™ na opcje dodatkowe). Ewentualnie zapoznaj siÄ™ z dokumentacjÄ… algorytmu.Gra jest przerwana i zapisana w pliku „%sâ€Gra zakoÅ„czyÅ‚a siÄ™ remisemGra przechowywana w pliku „%s†(%s) nie jest obsÅ‚ugiwana przez QarryNie znaleziono wÄ™zÅ‚a speÅ‚niajÄ…cego podane kryteriaTen algorytm jest skonfigurowany globalnie.Ta gra wyglÄ…da na zakoÅ„czonÄ…. Czy otworzyć jÄ… w trybie przeglÄ…dania/edycji?To błąd algorytmu. Możesz go zgÅ‚osić jego twórcom.Limit czasuLimit czasowy dla _gry:Limit czasowy dla _ruchu:Re_guÅ‚y limitów czasowych:WyglÄ…d listwy poleceÅ„DopiskiPodążaj za bieżącym wÄ™zÅ‚emTraxNie można wkleić fragmentu zapisu gry ze schowkaNie można wkleić fragmentu zapisu gry ze schowka ponieważ nie jest przeznaczony do wklejaniaCofnijCofa ostatniÄ… operacjÄ™Nie nazwana graUżywaj _nowszego (GTK+ 2.4) okna wyboru plikuUżywaj _starszego okna wyboru plikuUżyj pojedyÅ„czego _koloru:Użyj _tekstury:Użyj numeru wÅ‚aÅ›ciwego dla _sekwencji_DomyÅ›lne dla motywuWersja:Otwiera okno podglÄ…du i edycji informacji o grzeB Oczekiwanie na zakoÅ„czenie pracy algorytmu...BiaÅ‚eBiaÅ‚eBiaÅ‚e poddaÅ‚y grÄ™BiaÅ‚e wyczerpaÅ‚y czas i przegraÅ‚yBiaÅ‚e wygraÅ‚yBiaÅ‚e wygraÅ‚y o %.*f punktówBiaÅ‚e wygraÅ‚y o %d punktBiaÅ‚e wygraÅ‚y o %d punktyBiaÅ‚e wygraÅ‚y o %d punktówBiaÅ‚e wygraÅ‚y przez poddanieBiaÅ‚e: %d punkt terytoriumBiaÅ‚e: %d punkty terytoriumBiaÅ‚e: %d punktów terytoriumTylko _caÅ‚e wyrazy_Drzewo caÅ‚ej gry_Automatyczny powrót do poczÄ…tkuZawsze można rozszerzyć informacje o grze później. W tym celu wystarczy wybrać „Edycja|Informacje o grze†z menu programu, albo użyć przycisku „Informacje†z paska głównego.Można później dokoÅ„czyć tÄ™ grÄ™ wybierajÄ…c opcjÄ™ „DokoÅ„cz grę†w „Centrum Sterowania Quarryâ€, albo „DokoÅ„cz grę†w menu „Plikâ€.Można użyć symboli specjalnych „%n†i „%v†w polu „WyÅ›wietlana nazwaâ€. BÄ™dÄ… zastÄ™powane odpowiednio: nazwÄ… algorytmu i jego wersjÄ…. DomyÅ›lnie używany jest opis „%n %vâ€.Zazwyczaj można wkleić diagram w innym programie używajÄ…c kombinacji klawiszy „Ctrl+C†lub wybierajÄ…c wÅ‚aÅ›ciwÄ… opcjÄ™ w menu.[nieznane]_ZawszeAma_zonki_ZapisujÄ…cy:_Czarne:_PrzeglÄ…daj..._GotoweStyl paska _edycji:_Twórca pliku:_OkolicznoÅ›ci:Handikap _wolny:_Nazwa gry:_GoIdż do _wÄ™zÅ‚aKolor naniesionych _lini:_Komi:_Lista algorytmów GTP:_Czas główny:Styl paska _głównego:_ZmieÅ„_Gracz:_NigdyNowa _gra_Intensywność:_Otwórz zapis gryZagrane _otwarcie:_Okres czasu dodatkowego:_ZastÄ…pKa_mienie na planszyMiej_sce gry:_Graj_WyÅ›rodkuj widok drzewa na bieżącym węźleD_opasowany do rozmiaru „amazonekâ€D_opasowany do rozmiaru dyskówD_opasowany do rozmiaru kamieni_Poddaj_DokoÅ„cz_DokoÅ„cz grÄ™_ReversiWpisz _rÄ™cznie numer ruchu_Rozmiar:Ź_ródÅ‚o:_ZamieÅ„Moty_w:_BiaÅ‚e:szachykomentarz|Brak_NastÄ™pny_PoprzedniNie ustalonywprowadź nazwÄ™ dla tego wÄ™zÅ‚aNie ustalonezmienionypasquarry-0.2.0/po/ru.gmo0000644000175000017500000013520210530113072013241 0ustar bartbartÞ•ÀWx%y%#%³%Ð%ç%ø%& $& 2&&?&;f&%¢&È&8è& !'B' Q'_' f'q''¥'¶'Ë'ã'û'(#'(K(g(ƒ(–( ­( º(Ç(á(þ()3)N)f)})–)®)Ë) á)í) * * * %*1*8*)W**›* ­*º*Ë*Þ* í*ù* ++ +4+L+d+{+”+­+¼+Ï+ Þ+ë+ û+ , ,,&, :, F, T,b, s,,Ž,Ÿ,¦,·,Í,ä,ÿ,---M-T-[-`-g-n-u- …-‘-¡-¹- Ö-á-û-5 .(@.,i.–.®. ½.Ê.Ú.ï.µ÷.­/Í/Õ/ î/ü/000 0 $0/0 50 B0 P0 q0|0!0±0'Ç0 ï0 ü011:1Q1 h1r1„1 ”1Ÿ1¼1 Û1é1þ1p28Ž2GÇ23%383 >3H3W3 f3t3 Œ3–3?ª3ê3ò34 44+4@4P4a4j4n4}4•4¯4À4/Ú4X 5 c5m5r5z5 ‘555)Ó56ý5V46X‹6ä6ý677 "7 .7 97 C7O7 ^7 k7y77‡7™7ž7¡7µ7¾7'Ï7÷7 8#878>8 E8 P8Z8^8 e8–p8š9š¢9¬=:°ê:B›;“Þ;¡r<= =#=*=D= J=W=g=„=š="ª=Í=á=è=ý= > %>0>9>@>[>`>f>m>~>†>•>ž>®>³>Å> Î> Ú>è>fù>Û`?€<@ ½@È@Í@à@ñ@AA.AAARAdAiAzAA•AªA…¯A5BLBbB‚B¡B ·BJÄBbC+rCdžC DD+D 4D?D´UD5 E@EHENEgElEˆEE žE¬E´E ÍEÛE àEëE ðE0ûE8,FeF{F‚F –F¤F ½F ÊF×F7÷F/G?GEG\GaGpGG1ŽGÀGÐGáG þGH'H-H>H ZHdH,I/I<@I}I*“IT¾IEJ YJdJzJJ¤J³J¼JÖJ3ÛJXKhKmK ‚K"K$²K×K éK÷KL'L0LOL!RLtL zL ‡L •L ¶LÁL!ÔLöL' M4MFM WM’dM’÷M¦ŠN~1O °OºOÂO ËO×O æOñO÷O PP$P 4P@P DPPPhPoP …P‘P¦P®PµP ¼P ÆPÐPâPóP Q Q%Q-Q"3QVQoQ†QžQ¦Q ®Q»QÄQßQæQïQõQýQ R R R+R:RKR aRnRwRÄ|RATA[TDT;âT)UHU5\U’U+ªUgÖU’>VHÑV;WjVWBÁW$X$)XNX]X7}XCµX,ùX.&Y3UY9‰Y;ÃY.ÿYD.Z;sZ9¯Z!éZ7 [%C[%i[I[AÙ[I\Ee\E«\Kñ\E=]Mƒ]GÑ]Q^5k^#¡^&Å^ì^_&_D_ d_Bo_b²_2`'H`p`*Š`%µ`Û`ø`1a@a^a&oa4–a5Ëa3b=5b;sb,¯b.Üb* c&6c%]c&ƒc ªc(Ëc ôc$ÿc$d8d1Rd„d"¡d$Äd,éde"e*BeKme2¹e=ìeA*f>lf«f ºfÅfÖf çfòfûfg+g'Cg7kg £g&®gÕg]çgREhP˜h;éh%iAi#^i=‚i ÀiÎiKäj0k8Akzkšk k¼k Àk ËkÖk Ýk êk÷k3lGl+el‘lImŽ[mêmn$n+Bn"nn6‘nÈn:Ün"o:o.OoB~o!Áo$ão3pëî‰a-‹Œ˜Œ«Œ;²Œ îŒøŒ<4/q¡6±7è Ž'1Ž9YŽ “Ž ŸŽ ©ŽµŽE¾Ž'%7]e$™¾Ñå )@®j#‘è=“)&”P”*U” €” ¡”"”,å”(•;•Z•y•ˆ•(§•Е!ã•–%–4—"M—=p—K®—*ú—%˜«?˜¾ë˜cª™hšw›EŠ›Л å›(ð›4œ‹N Ú çLñ>žGMž•ž&¤ž'Ëžóž6Ÿ9Ÿ WŸdŸuŸˆŸh¥Ÿ| *‹ ¶ !Ë +í H¡b¡ ~¡3‹¡p¿¡(0¢Y¢3b¢–¢.«¢?Ú¢,£SG£&›£&£Aé£C+¤o¤w¤"‡¤+ª¤Ö¤~î¤Hm¦,¶¦cã¦@G§[ˆ§œä§i¨*ë¨&©$=©b©2‚©µ©;È©ªo ª³yª-«4>«!s«V•«Mì«:¬+Z¬E†¬:̬ ­Y­o­>s­ ²­ ½­È­1â­®)0®yZ®GÔ®ˆ¯'¥¯ͯ;â¯Q°p±Kq²¿½³}´ ”´¢´´´É´Ø´ ó´OµQµqµ%‚µ¨µȵε<Þµ ¶!&¶H¶Af¶¨¶º¶öÓ¶ì¶) ·5·<S·· ¦·!Ç· é·6÷·=.¸5l¸5¢¸ظè¸$¹%¹65¹l¹{¹޹ ¦¹ ±¹¾¹͹ä¹ø¹º5 ºVºjºyº%!d¨8 T°¢b@·ˆ—2;ѵ±]wo˜®‡mc¢ÀKÖÓ™¦PŽ,gݯêÂyª¥m ÷œòœ[ 5~‚ ºp˜{Ô¹ö¦SNY¿„ÞEab¥Jrï½+Mivjü(™;1•Æ£*#kTŒé½>¬á šÈ!Ÿ7fNž ’}úU¤˧{/û‚Õt<‹)"âi‘A>€ÙG¶¿Ä@Ò'3 Ÿ-»=ƒ‡›ì‘–9G¸ù$ªzK…n†Ã6ºež~†§ß³Ü9è´qM#XVgwLŒÅÍÚCŽoà&DS­´`5sF¶ýš6hHÉn 7‰¾qY¨IîæB/_±ŠR€­²«=L+Zv ‹ã¾ErxµO,¯l»\uÀ?e^„&}pV«ðŠ…ÿ—Wu®JÌô(–"¼Z4å0C.]P0³8 4Uh|?ç1jyÇ'õÁÊAIfˆc¡¼×:”`*“.¬FƒñQ°l-ÏHzO¹í¤© ²a›ó£”ÎdÛ¡$‰ þØëXRW)x©Bk2%ä“Ð •¸·’:<_t3øQD|^ \s[ %s %.*f komi = %.*f %s %d komi = %d %s %d komi = %d + %d capture + %d captures%d capture%d captures%d disk%d disks%s %s %.*f komi%s %s %d komi%s %s %d komi%s (W) vs. %s(per player)* ERROR: mismatched ID (%d expected): * ERROR: unexpected ID in response (the command had none): * ERROR: unrecognized response line: * ERROR: wrong response format * WARNING: future GTP version, I don't know about it... * WARNING: unexpected response: /Circle Markup/Cross Markup/Edit//Edit/Cu_t/Edit/Delete Node's C_hildren/Edit/Edit Node _Name/Edit/Find Ne_xt/Edit/Find Pre_vious/Edit/Game _Information/Edit/Move Branch Do_wn/Edit/Move _Branch Up/Edit/P_layer to Move/Edit/Player to Move/By Game _Rules/Edit/Player to Move/_Black/Edit/Player to Move/_White/Edit/Pr_eferences/Edit/Set _Move Number/Edit/T_ools/Edit/Tools//Edit/Tools/C_ross Markup/Edit/Tools/S_elected Markup/Edit/Tools/S_quare Markup/Edit/Tools/Scori_ng Tool/Edit/Tools/_Circle Markup/Edit/Tools/_Label Tool/Edit/Tools/_Move Tool/Edit/Tools/_Number Tool/Edit/Tools/_Setup Tool/Edit/Tools/_Triangle Markup/Edit/_Add Empty Node/Edit/_Copy/Edit/_Delete Node/Edit/_Find/Edit/_Paste/Edit/_Redo/Edit/_Undo/File//File/Export.../_ASCII Diagram/File/Export.../_Sensei's Library Diagram/File/Ne_w Game Record.../File/Save _As.../File/_Close/File/_Export.../File/_New Game.../File/_Open.../File/_Quit/File/_Resume Game.../File/_Save/Go//Go/Ne_xt Variation/Go/Pre_vious Variation/Go/Ten Nodes _Backward/Go/Ten Nodes _Forward/Go/Variation _Last Node/Go/_Go to Named Node.../Go/_Next Node/Go/_Previous Node/Go/_Root Node/Help/_About/Help/_Contents/Label Tool/Move Tool/Number Tool/Play//Play/_Adjourn Game/Play/_Pass/Play/_Resign/Scoring Tool/Selected Markup/Setup Tool/Square Markup/Triangle Markup/View//View/Game _Tree/View/_Control Center/View/_Editing Toolbar/View/_Game Action Buttons/View/_Main Toolbar/View/_Navigation Toolbar/View/_Recenter on Current Node/_Edit/_File/_Go/_Help/_Play/_View; black to play; game over; white to playBoard AppearanceEditing & ViewingGTPGame Records (SGF)GeneralA GUI program for Go, Amazons and Reversi board gamesA good width for the right side to have.ASCII diagram has been exported to clipboardA_uto-close this dialogA_utomaticallyAbout QuarryAdd Board LabelAdjourn & Save As...Al_waysAlthough board labels are not limited in length, it is better to use only one or two characters long labels. Longer labels will not be visible immediately or at all in most clients.Always use _UTF-8 (recommended)AmazonsAmazons Board AppearanceAmazons RulesAtaxxAut_omaticallyB BackBackgammonBackgroundBlackBlack PlayerBlack resignsBlack runs out of time and losesBlack winsBlack wins by %.*fBlack wins by %dBlack wins by %dBlack wins by forfeitBlack: %d territoryBlack: %d territoryBoard _size:Board size:By Game _Rules (Black)By Game _Rules (Game Over)By Game _Rules (White)C_omments & node namesC_omputerCanadian overtimeCase _sensitiveCategor_y:Checkerboard _pattern color:Checkerboard pattern _opacity:Chinese chessChoose GTP Engine...Choose a Background Texture...Clipboard SGF probably contains more than one game tree or not a single child of the root of the only game tree.Clipboard contains an invalid game record fragment (SGF)Clipboard game record fragment must be of different game or board size.Close _without SavingCo_pyright string:ColorCom_puterComm_ents onlyCommand _line:Command line:Comment / _description:Compu_terCopyright & CreditsCopyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev and othersCrea_teCurrent no_de onlyDa_te:DeleteDelete the current nodeDescription & ResultDesktop defaultEdit Board LabelEncodingEndEngine hung upError reading file `%s'Error saving to file `%s'Fi_xed handicap:File Chooser Dialog StyleFile `%s' doesn't appear to be a valid SGF fileFile named `%s' already exists. Do you want to overwrite it with the one you are saving?Filename:FindForwardGTP Engine InformationGTP EnginesGTP engine `%s' cannot handle %dx%d board size, sorryGTP engine `%s' failed to clean the boardGTP engine `%s' failed to set handicap stones on boardGTP engine `%s' failed to set initial time limits (it could ignore them, but not fail)GTP engine `%s' reported it could handle %s game, but failed to initialize itself for itGTP engine is scoring...GameGame & PlayersGame InformationGame RecordGame RulesGame TreeGame _name:Game beginningGame is drawGame re_sult:Game:GeneralGeneral InterfaceGessGoGo Board AppearanceGo RulesGo to Named NodeGo to the current variation's last nodeGo to the next nodeGo to the previous nodeGo to the root nodeGomokuH_umanHan_dicap:Handicap:HexHu_manIcons onlyIf you don't save, changes from the last %d hour will be lost permanently.If you don't save, changes from the last %d hours will be lost permanently.If you don't save, changes from the last %d minute will be lost permanently.If you don't save, changes from the last %d minutes will be lost permanently.If you don't save, changes from the last %d second will be lost permanently.If you don't save, changes from the last %d seconds will be lost permanently.If you don't save, changes from the last hour and %d minute will be lost permanently.If you don't save, changes from the last hour and %d minutes will be lost permanently.If you don't save, changes from the last minute and %d second will be lost permanently.If you don't save, changes from the last minute and %d seconds will be lost permanently.If you don't save, changes from the last minute will be discarded.In automatic mode the game tree is shown only if it has at least one variation. In any case, you can show/hide game tree in each window separately.In automatic mode the game tree view scrolls to show the current node only if it has been showing current node before. I.e. unless you scrolled it away manually.InfoInterfaceJungleK_eep track of total timeKomi:Label _text:Last move: %u, Limited time for entire gameLimited time per moveLines of ActionLost connection to GTP Engine (%s)Manage _Engine ListMarkupMo_ves per overtime:Modify GTP Engine InformationMove %d: Move _DownMove _UpN_ame:N_avigation toolbar style:NameName:Ne_verNe_w Game RecordNeutronNew GTP EngineNew GameNew Game RecordNextNine Men's MorrisNo limitNode _name:Node comment:Node na_mes onlyNote that all information in the existing file will be lost permanently if you choose to overwrite it.Note that many characters cannot be represented in non-UTF-8 encodings and thus some information may be lost if you use them. Quarry also works fastest with UTF-8; this may be important if you have very large SGF files.Note that most GTP engines support only one game. Hence certain game / computer player combinations may be not possible to play.O_vertime:OctiOn _black amazons:On _black disks:On _black stones:On _empty fields:On _empty intersections:On _white amazons:On _white disks:On _white stones:OpenOpen SGF File...Open a game recordOptionsParsing file `%s'...PassPerhaps engine's binary has been deleted or changed. You will probably need to alter engine's command line in the Preferences dialog.Philosopher's FootballPick Background ColorPick Checkerboard Pattern ColorPick Color for Grid and LabelsPick Color for MarkupPick a ColorPlease check that the file exists and its permission allow you to read it.Please make sure you typed engine's filename correctly and that you have permission to execute it.Please select dead stones to score the gamePlease set up %d (or less) stone of free handicapPlease set up %d (or less) stones of free handicapPreferencesPreserve _original encodingPreviousQuadratureQuarry Control CenterQuarry uses SGF file format for storing game records. SGF files would normally have `sgf' extension, but that's not necessarily true. Please make sure you select a proper SGF file.Querying engine's name, version and known commands...R_ound:Rank:Really resign this game?RedoRedo the last undone actionResignResume Game...Resuming GameReversiReversi Board AppearanceReversi RulesRootRule _set:SaveSave As...Save changes to game record `%s' before closing?Save changes to the untitled game record before closing?Save the current fileSavingSaving Game RecordsScreen _name:Scroll _minimal distanceSearch ScopeSearch _for:Search for a string in commentsSensei's Library diagram has been exported to clipboardSet Move NumberShogiShort Game InformationShowShow Game TreeShow _tooltipsSize & OpacitySorry, there are no named nodes in this game treeSupported game:Supported games:Switch to the next variationSwitch to the previous variationTantrixTeam:Text below iconsText beside important iconsText onlyThe engine might have crashed, quit prematurely or disconnected. Please verify command line, including options, and consult engine's documentation if needed.The game is adjourned and saved in file `%s'The game is drawThe game stored in file `%s' (%s) is not supported by QuarryThere is no such nodeThis engine comes from site configuration.This game appears to have been finished. Open it for viewing and/or editing instead?This is an engine error. You may want to report it to engine authors.Time LimitTime _limit for game:Time _limit for move:Time control _type:Toolbar StylesTooltipsTrack Tree's Current NodeTraxUnable to paste game record fragment from clipboardUnable to paste game record fragment from clipboard since it is not intended for pastingUndoUndo the last actionUnnamed GameUse _newer (GTK+ 2.4) file chooserUse _old-style file selection dialogUse _solid color:Use _texture:Use se_quential move numberUse theme _defaultsVersion:View and edit game informationW Waiting for the engine to quit...WhiteWhite PlayerWhite resignsWhite runs out of time and losesWhite winsWhite wins by %.*fWhite wins by %dWhite wins by %dWhite wins by forfeitWhite: %d territoryWhite: %d territoryWhole _words onlyWhole game _treeWrap _aroundYou can always change and expand game information later. Just choose `Edit/Game Information' menu item or press `Info' button on the main toolbar.You can later resume the game by pressing the `Resume Game' button in Quarry Control Center, or selecting `Resume Game' item from the `File' menu.You can use `%n' and `%v' strings in Screen name field. They will substituted with name and version of the engine correspondingly. By default, `%n %v' is used.You can usually paste the diagram in another application using `Ctrl+C' key combination or by selecting appropriate menu item.[unknown]_Always_Amazons_Annotator:_Black player:_Browse..._Done_Editing toolbar style:_Entered by:_Event:_Free handicap:_Game name:_Go_Go to Node_Grid and labels color:_Komi:_List of GTP engines:_Main time:_Main toolbar style:_Modify_Name:_Never_New Game_Opacity:_Open Game Record_Opening played:_Overtime period length:_Overwrite_Place stones_Place:_Play_Recenter view on the current node_Relative to amazon size_Relative to disk size_Relative to stone size_Resign_Resume_Resume Game_Reversi_Set specific move number:_Size:_Source:_Swap_Theme:_White player:chesscomment|Emptyfind|_Nextfind|_Previoushandicap|Not setinsert node name herekomi|Not setmodifiedpassProject-Id-Version: Quarry 0.1.15 Report-Msgid-Bugs-To: quarry-dev@gna.org POT-Creation-Date: 2006-11-07 18:33+0200 PO-Revision-Date: 2006-10-28 15:05+0300 Last-Translator: Paul Pogonyshev Language-Team: Russian MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2); %s %.*f коми = %.*f %s %d коми = %d %s %d коми = %d %s %d коми = %d + %d пленник + %d пленника + %d пленников%d пленник%d пленника%d пленников%d диÑк%d диÑка%d диÑков%s %s %.*f коми%s %s %d коми%s %s %d коми%s %s %d коми%s (б) против %s(Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ из игроков)* ОШИБКÐ: неÑоответÑтвующий идентификатор (ожидалоÑÑŒ %d): * ОШИБКÐ: неожиданный идентификатор в ответе (в команде не было идентификатора): * ОШИБКÐ: нераÑÐ¿Ð¾Ð·Ð½Ð°Ð½Ð½Ð°Ñ Ñтрока ответа: * ОШИБКÐ: неверный формат ответа * ПРЕДУПРЕЖДЕÐИЕ: верÑÐ¸Ñ GTP из будущего, Ñ Ð¾ такой не знаю... * ПРЕДУПРЕЖДЕÐИЕ: неожиданный ответ /Разметка кружочком/Разметка креÑтиком/Правка//Правка/_Вырезать/Правка/Удалить _дочерние узлы/Правка/Редак_тировать название узла/Правка/Ðайти _Ñледующее/Правка/Ðайти _предыдущее/Правка/Ин_Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ партии/Правка/ПеремеÑтить ветку вни_з/Правка/ПеремеÑтить ветку ввер_Ñ…/Правка/С_ледующими ходÑÑ‚/Правка/Следующими ходÑÑ‚/По _правилам/Правка/Следующими ходÑÑ‚/_Черные/Правка/Следующими ходÑÑ‚/_Белые/Правка/Парам_етры/Правка/УÑтановить но_мер хода/Правка/_ИнÑтрументы/Правка/ИнÑтрументы//Правка/ИнÑтрументы/Разметка _креÑтиком/Правка/ИнÑтрументы/Разметка-в_ыбор/Правка/ИнÑтрументы/Разметка к_вадратом/Правка/Tools/ИнÑтрумент _подÑчета очков/Правка/ИнÑтрументы/Разметка к_ружком/Правка/ИнÑтрументы/ИнÑтрумент _надпиÑей/Правка/ИнÑтрументы/ИнÑтрумент _ходов/Правка/ИнÑтрументы/ИнÑтрумент ну_мерации/Правка/ИнÑтрументы/_УÑтановка позиции/Правка/ИнÑтрументы/Разметка _треугольником/Правка/До_бавить пуÑтой узел/Правка/_Копировать/Правка/_Удалить узел/Правка/_Ðайти/Правка/Ð’ÑÑ‚_авить/Правка/Ве_рнуть/Правка/_Отменить/Файл//Файл/ЭкÑпортировать…/ASCII-диаграмма/Файл/ЭкÑпортировать…/Диаграмма «Библиотеки СенÑеÑ»/Файл/Ðов_Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ партии…/Файл/Сохранить _как…/Файл/_Закрыть/Файл/_ЭкÑпортировать…/Файл/_ÐÐ¾Ð²Ð°Ñ Ð¿Ð°Ñ€Ñ‚Ð¸Ñ…/Файл/_Открыть…/Файл/Ð’_ыход/Файл/_Возобновить партию…/Файл/_Сохранить/Перейти//Go/Сле_дующий вариант/Перейти/Пр_едыдущий вариант/Перейти/ДеÑÑть узлов _вперед/Перейти/ДеÑÑть узлов _назад/Перейти/ПоÑ_ледний узел варианта/Go/Перейти к _именованному узлу…/Перейти/_Следующий узел/Перейти/_Предыдущий узел/Перейти/_Корневой узел/Справка/_О программе/Справка/_Содержание/ИнÑтрумент надпиÑей/ИнÑтрумент ходов/ИнÑтрумент нумерации/Игра//Play/_Отложить партию/Игра/_ПаÑÑ/Игра/_СдатьÑÑ/ИнÑтрумент подÑчета очков/Разметка-выбор/УÑтановка позиции/Разметка квадратом/Разметка треугольником/Вид//Вид/_Дерево партии/Вид/Панель _управлениÑ/Вид/Панель инÑтрументов _редактированиÑ/Вид/Дополнительные _кнопки/Вид/_Ð“Ð»Ð°Ð²Ð½Ð°Ñ Ð¿Ð°Ð½ÐµÐ»ÑŒ инÑтрументов/Вид/Панель инÑтрументов _навигации/Вид/_Центрировать на текущем узле/_Правка/_Файл/Перей_ти/_Справка/_Игра/_Вид; ходÑÑ‚ черные; конец игры; ходÑÑ‚ белыеВнешний вид доÑкиРедактирование и проÑмотрGTPЗапиÑи партий (SGF)ОбщиеУниверÑальный Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ Ð´Ð»Ñ Ð³Ð¾, амазонок и реверÑиВполне подходÑÑ‰Ð°Ñ ÑˆÐ¸Ñ€Ð¸Ð½Ð° Ð´Ð»Ñ Ð¿Ñ€Ð°Ð²Ð¾Ð¹ колонки.ASCII-диаграмма ÑкÑпортирована в буфер обменаЗакрывать диалог _автоматичеÑки_ÐвтоматичеÑкиО программе QuarryДобавление надпиÑиОтложить партию и Ñохранить как…ВÑе_Ð³Ð´Ð°Ð¥Ð¾Ñ‚Ñ Ð½Ð°Ð´Ð¿Ð¸Ñи не ограничены по длине, лучше не иÑпользовать более одного или двух Ñимволов. Более длинные надпиÑи будут не видны в большинÑтве клиентов._Ð’Ñегда иÑпользовать UTF-8 (рекоммендуетÑÑ)амазонкиВнешний вид доÑки Ð´Ð»Ñ Ð°Ð¼Ð°Ð·Ð¾Ð½Ð¾ÐºÐŸÑ€Ð°Ð²Ð¸Ð»Ð° амазонокAtaxxÐв_томатичеÑкиЧ ÐазаднардыФонЧерныеЧерныеЧерные ÑдалиÑьЧерные проиграли по времениЧерные выигралиЧерные выиграли %.*f очкаЧерные выиграли %d очкоЧерные выиграли %d очкаЧерные выиграли %d очковЧерным заÑчитано техничеÑкое поражениеЧерные: %d очко территорииЧерные: %d очка территорииЧерные: %d очков территорииРазмер _доÑки:Размер доÑки:По правилам (черные)По правилам (конец игры)По правилам (белые)Комментарии _и Ð½Ð°Ð·Ð²Ð°Ð½Ð¸Ñ ÑƒÐ·Ð»Ð¾Ð²_КомпьютерКанадÑкое дополнительное времÑУчитывать _региÑтрКатегори_Ñ:Цвет _шахматного риÑунка:_ÐепрозрачноÑть шахматного риÑунка:китайÑкие шахматыВыберите GTP-движок…Выберите фоновую текÑтуру…SGF-фрагмент из буфера обмена, вероÑтно, Ñодержит более одного дерева игры, или не одного наÑледника у ÐºÐ¾Ñ€Ð½Ñ ÐµÐ´Ð¸Ð½Ñтвенного дерева.Буфер обмена Ñодержит неправильный фрагмент запиÑи партии (SGF)Фрагмент запиÑи партии в буфере обмена, вероÑтно, был Ñоздан Ð´Ð»Ñ Ð´Ñ€ÑƒÐ³Ð¾Ð¹ игры или размера доÑки.Закрыть _без ÑохранениÑ_ÐвторÑкие права:Цвет_КомпьютерТолько _комментарии_ÐšÐ¾Ð¼Ð°Ð½Ð´Ð½Ð°Ñ Ñтрока:ÐšÐ¾Ð¼Ð°Ð½Ð´Ð½Ð°Ñ Ñтрока:_Комментарии/опиÑание:Компь_ютерБлагодарноÑтиCopyright © 2003, 2004, 2005, 2006 Павел Погонышев и другиеСо_здатьТолько текущий _узел_Дата:УдалитьУдалить текущий узелОпиÑание и результатПо умолчаниюРедактирование надпиÑиКодировкаКонецДвижок отключилÑÑ Ð¿Ð¾ ÑобÑтвенной инициативеОшибка при чтении файла «%s»Ошибка при запиÑи файла «%s»Стандартный _гандикап:Стиль диалога выбора файловФайл «%s» не ÑвлÑетÑÑ Ð¿Ñ€Ð°Ð²Ð¸Ð»ÑŒÐ½Ñ‹Ð¼ SGF-файломФайл Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼ «%s» уже ÑущеÑтвует. Ð’Ñ‹ хотите перепиÑать его?Ðазвание файла:ÐÐ°Ð¹Ñ‚Ð¸Ð’Ð¿ÐµÑ€ÐµÐ´Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ GTP-движкеGTP-движкиGTP-движок «%s» не поддерживает размер доÑки %d×%d, извинитеGTP-движок «%s» не Ñмог Ñмог очиÑтить доÑкуGTP-движок «%s» не Ñмог уÑтановить камни гандикапа на доÑкеGTP-движок «%s» не Ñмог уÑтановить начальные Ð¾Ð³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð¸Ñ Ð¿Ð¾ времени (он мог игнорировать их, но не Ñообщить об ошибке)GTP-движок «%s» Ñказал, что поддерживает игру %s, но не Ñмог инициализировать ÑÐµÐ±Ñ Ð´Ð»Ñ Ñтой игрыGTP-движок подÑчитывает результат партии…ИграИгра и ÑÐ¾Ð¿ÐµÑ€Ð½Ð¸ÐºÐ¸Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ партииЗапиÑÑŒ партииПравила игрыДерево партии_Ðазвание партии:Ðачало партииÐичьÑРезу_льтат партии:Игра:ÐžÐ±Ñ‰Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸ÑОбщие наÑтройки интерфейÑаGessгоВнешний вид гобанаПравила гоПерейти к именованному узлуПерейти к поÑледнему узлу текущего вариантаПерейти к Ñледующему узлуПерейти к предыдущему узлуПерейти к корневому узлугомоку_Человек_Гандикап:Гандикап:HexЧе_ловекТолько значкиЕÑли вы решите не ÑохранÑть, то вÑе изменениÑ, Ñовершенные за поÑледний %d чаÑ, будут безвозвратно потерÑны.ЕÑли вы решите не ÑохранÑть, то вÑе изменениÑ, Ñовершенные за поÑледние %d чаÑа, будут безвозвратно потерÑны.ЕÑли вы решите не ÑохранÑть, то вÑе изменениÑ, Ñовершенные за поÑледние %d чаÑов, будут безвозвратно потерÑны.ЕÑли вы решите не ÑохранÑть, то вÑе изменениÑ, Ñовершенные за поÑледнюю %d минуту, будут безвозвратно потерÑны.ЕÑли вы решите не ÑохранÑть, то вÑе изменениÑ, Ñовершенные за поÑледние %d минуты, будут безвозвратно потерÑны.ЕÑли вы решите не ÑохранÑть, то вÑе изменениÑ, Ñовершенные за поÑледние %d минут, будут безвозвратно потерÑны.ЕÑли вы решите не ÑохранÑть, то вÑе изменениÑ, Ñовершенные за поÑледнюю %d Ñекунду, будут безвозвратно потерÑны.ЕÑли вы решите не ÑохранÑть, то вÑе изменениÑ, Ñовершенные за поÑледние %d Ñекунды, будут безвозвратно потерÑны.ЕÑли вы решите не ÑохранÑть, то вÑе изменениÑ, Ñовершенные за поÑледние %d Ñекунд, будут безвозвратно потерÑны.ЕÑли вы решите не ÑохранÑть, то вÑе изменениÑ, Ñовершенные за поÑледний Ñ‡Ð°Ñ Ð¸ %d минуту, будут безвозвратно потерÑны.ЕÑли вы решите не ÑохранÑть, то вÑе изменениÑ, Ñовершенные за поÑледний Ñ‡Ð°Ñ Ð¸ %d минуты, будут безвозвратно потерÑны.ЕÑли вы решите не ÑохранÑть, то вÑе изменениÑ, Ñовершенные за поÑледний Ñ‡Ð°Ñ Ð¸ %d минут, будут безвозвратно потерÑны.ЕÑли вы решите не ÑохранÑть, то вÑе изменениÑ, Ñовершенные за поÑледнюю минуту и %d Ñекунду, будут безвозвратно потерÑны.ЕÑли вы решите не ÑохранÑть, то вÑе изменениÑ, Ñовершенные за поÑледнюю минуту и %d Ñекунды, будут безвозвратно потерÑны.ЕÑли вы решите не ÑохранÑть, то вÑе изменениÑ, Ñовершенные за поÑледнюю минуту и %d Ñекунд, будут безвозвратно потерÑны.ЕÑли вы решите не ÑохранÑть, то вÑе изменениÑ, Ñовершенные за поÑледнюю минуту, будут безвозвратно потерÑны.Ð’ автоматичеÑком режиме дерево показываетÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ еÑли в нем еÑть хоть одна ветвь кроме оÑновной. Ð’ любом Ñлучае вы можете показывать/прÑтать дерево отдельно в каждом окне.Ð’ автоматичеÑком режиме панель Ñ Ð´ÐµÑ€ÐµÐ²Ð¾Ð¼ перематываетÑÑ Ðº новому текущему узлу только еÑли она показывала текущий узел и раньше, то еÑть, еÑли вы не перемотали ее в другое меÑто дерева вручную.ИнфоИнтерфейÑJungle_ПодÑчитывать потраченное времÑКоми:ТекÑÑ‚ _надпиÑи:ПоÑледний ход: %u, Ограниченное Ð²Ñ€ÐµÐ¼Ñ Ð½Ð° вÑÑŽ партиюОграниченное Ð²Ñ€ÐµÐ¼Ñ Ð½Ð° ходLines of ActionПотерÑна ÑвÑзь Ñ GTP-движком (%s)Редактировать ÑпиÑок д_вижковРазметка_Ходов на один период:Изменить информацию о GTP-движкеХод %d: Ð’_низВ_верхИ_мÑ:Стиль панели инÑтрументов _навигации:ÐазваниеÐазвание:Ðи_когдаÐÐ¾Ð²Ð°Ñ _запиÑÑŒ партииNeutronÐовый GTP-движокÐÐ¾Ð²Ð°Ñ Ð¿Ð°Ñ€Ñ‚Ð¸ÑÐÐ¾Ð²Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ партииСледующийNine Men’s MorrisБез ограничениÑ_Ðазвание узла:Комментарий узла:Только наз_Ð²Ð°Ð½Ð¸Ñ ÑƒÐ·Ð»Ð¾Ð²Ð•Ñли вы решите перепиÑать ÑущеÑтвующий файл, вÑÑ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð² нем будет безвозвратно потерÑна.Заметьте, что многие Ñимволы не могут быть предÑтавлены в кодировках, отличных от UTF-8. ПоÑтому, чаÑть информации может быть потерÑна при Ñохранении Ñ Ð¸Ñпользованием таких кодировок. Кроме того, Quarry быÑтрее вÑего работает именно Ñ UTF-8, что может быть немаловажно при работе Ñ Ð¾Ñ‡ÐµÐ½ÑŒ большими SGF-файлами.БольшинÑтво GTP-движков поддерживают только одну игру. ПоÑтому, некоторые комбинации игр и компьютерных оппонентов недоÑтупны.Допо_лнительное времÑ:OctiÐа _черных «амазонках»:Ðа _черных диÑках:Ðа _черных камнÑÑ…:Ðа _пуÑтых клетках:Ðа _пуÑтых переÑечениÑÑ…:Ðа _белых «амазонках»:Ðа _белых диÑках:Ðа _белых камнÑÑ…:ОткрытьОткрыть SGF-файл…Открыть запиÑÑŒ партииПараметрыРазбор файла «%s»…ПаÑÑВидимо, иÑполнимый файл движка был удален или изменен. Вам необходимо изменить ÑоответÑтвующим образом командную Ñтроку Ð´Ð»Ñ Ð·Ð°Ð¿ÑƒÑка движка в диалоге наÑтроек.Philosopher’s FootballВыберите цвет фонаВыберите цвет шахматного риÑункаВыберите цвет координатной Ñетки и метокВыберите цвет разметкиВыберите цветПожалуйÑта, проверьте, что файл ÑущеÑтвует, и права доÑтупа к нему разрешают вам чтение файла.ПожалуйÑта, убедитеÑÑŒ, что название файла движка набрано верно, и что у Ð²Ð°Ñ ÐµÑть права на его выполнение.ПожалуйÑта, выберите мертвые камни Ð´Ð»Ñ Ð¿Ð¾Ð´Ñчета очковПожалуйÑта, размеÑтите %d (или меньше) камень Ñвободного гандикапаПожалуйÑта, размеÑтите %d (или меньше) ÐºÐ°Ð¼Ð½Ñ Ñвободного гандикапаПожалуйÑта, размеÑтите %d (или меньше) камней Ñвободного гандикапаÐаÑтройкиИÑпользовать _оригинальную кодировкуПредыдущийQuadratureПанель ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ QuarryÐ”Ð»Ñ Ñ…Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ Ð¿Ð°Ñ€Ñ‚Ð¸Ð¹ Quarry иÑпользует формат файлов SGF. SGF-файлы обычно имеют раÑширение «sgf», но Ñто необÑзательно. ПожалуйÑта, убедитеÑÑŒ, что вы выбрали правильный SGF-файл.Запрашиваю название и верÑию движка, а также ÑпиÑок поддерживаемых команд…Р_аунд:Ранг:Ð’Ñ‹ дейÑтвительно хотите Ñдать Ñту партию?ВернутьВернуть поÑледнее отмененное дейÑтвиеСдатьÑÑВозобновить партию…Возобновление партииреверÑиВнешний вид доÑки Ð´Ð»Ñ Ñ€ÐµÐ²ÐµÑ€ÑиПравила реверÑиКорень_Правила:СохранитьСохранить как…Сохранить Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð² запиÑи партии «%s» перед закрытием?Сохранить Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð² неименованной запиÑи партии перед закрытием?Сохранить текущий файлСохранениеСохранение партийОтображаемое _название:Отматывать на _минимальныое раÑÑтоÑниеОблаÑть поиÑка_Ðайти:Ðайти Ñтроку в комментариÑхДиаграмма «Библиотеки СенÑеÑ» ÑкÑпортирована в буфер обменаУÑтановить номер ходаÑÑ‘Ð³Ð¸ÐšÑ€Ð°Ñ‚ÐºÐ°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ партииПоказыватьПоказывать дерево партииПоказывать вÑплывающие _подÑказкиРазмер и непрозрачноÑтьИзвините, в Ñтом дереве нет именованных ÑƒÐ·Ð»Ð¾Ð²ÐŸÐ¾Ð´Ð´ÐµÑ€Ð¶Ð¸Ð²Ð°ÐµÐ¼Ð°Ñ Ð¸Ð³Ñ€Ð°:Поддерживаемае игры:ПереключитьÑÑ Ð½Ð° Ñледующий вариантПереключитьÑÑ Ð½Ð° предыдущий вариантTantrixКоманда:ТекÑÑ‚ под значкамиТекÑÑ‚ Ñ€Ñдом Ñо значкамиТолько текÑтДвижок, возможно, «рухнул», завершил работу или отÑоединилÑÑ Ð¿Ð¾ ÑобÑтвенной инициативе. ПожалуйÑта, проверьте командную Ñтрочку, Ð²ÐºÐ»ÑŽÑ‡Ð°Ñ Ð¾Ð¿Ñ†Ð¸Ð¸. При необходимоÑти, проконÑультируйтеÑÑŒ Ñ Ð´Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñ†Ð¸ÐµÐ¹ движка.ÐŸÐ°Ñ€Ñ‚Ð¸Ñ Ð¾Ñ‚Ð»Ð¾Ð¶ÐµÐ½Ð° и Ñохранена в файле «%s»Игра завершилаÑÑŒ вничьюИгра, ÑÐ¾Ñ…Ñ€Ð°Ð½ÐµÐ½Ð½Ð°Ñ Ð² файле «%s» (%s) не поддерживаетÑÑ QuarryУзла Ñ Ñ‚Ð°ÐºÐ¸Ð¼ названием нет в деревеЭтот движок опиÑан в конфигурации рабочего меÑта.Эта партиÑ, похоже, уже была завершена. Открыть ее Ð´Ð»Ñ Ð¿Ñ€Ð¾Ñмотра и/или редактированиÑ?Это ошибка GTP-движка. Ð’Ñ‹ можете Ñообщить о ней его авторам.Ограничение по времениОгра_ничение на игру:Ограничение на _ход:Тип _ограничениÑ:Стили панелей инÑтрументовПодÑказкиОтÑлеживать текущий узел дереваTraxÐевозможно вÑтавить фрагмент запиÑи партии из буфера обменаÐевозможно вÑтавить фрагмент запиÑи партии из буфера обмена, так как он Ð´Ð»Ñ Ñтого не предназначенОтменитьОтменить поÑледнее дейÑтвиеБезымÑÐ½Ð½Ð°Ñ Ð¿Ð°Ñ€Ñ‚Ð¸ÑИÑпользовать но_вый (GTK+ 2.4) диалог выбора файловИÑпользовать Ñ_тарый диалог выбора файлов_Одноцветный фон:ИÑпользовать _текÑтуру:ИÑпользовать _поÑледовательный номер_ИÑпользовать наÑтройки из темыВерÑиÑ:ПроÑмотреть и редактировать информацию о партииБ Ожидаю Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð¸Ñ Ñ€Ð°Ð±Ð¾Ñ‚Ñ‹ движка…БелыеБелыеБелые ÑдалиÑьБелые проиграли по времениБелые выигралиБелые выиграли %.*f очкаБелые выиграли %d очкоБелые выиграли %d очкаБелые выиграли %d очковБелым заÑчитано техничеÑкое поражениеБелые: %d очко территорииБелые: %d очка территорииБелые: %d очков территорииТолько Ñлова _целикомВÑе _деревоÐвтоматичеÑки на_чинать ÑначалаВы вÑегда можете изменить и дополнить Ñту информацию в дальнейшем. ПроÑто выберите Ñлемент меню «Правка/Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ партии» или нажмите кнопку «Инфо» на главной панели инÑтрументов.Ð’Ñ‹ можете вернутьÑÑ Ðº игре, нажав кнопку «Возобновить партию» в Панели ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Quarry или выбрав пункт «Возобновить партию» из меню «Файл».Ð’Ñ‹ можете иÑпользовать Ñпециальные Ñтроки «%n» и «%v» в поле «отображаемое название». Они будут заменены на название и верÑию движка ÑоответÑтвенно. По умолчанию, иÑпользуетÑÑ Â«%n %v».Обычно диаграмму можно вÑтавить в другом приложении, нажав «Ctrl+C» или выбрав ÑоответÑтвующий пункт меню.[неизвеÑтно]_Ð’Ñегда_ÐмазонкиÐ_ннотатор:_Черные:_ПроÑмотреть…_ГотовоСтиль панели инÑтрументов _редактированиÑ:_Создатель файла:_Событие:Сво_бодный гандикап:_Ðазвание партии:_Го_ПерейтиЦвет _координатной Ñетки и меток:_Коми:С_пиÑок GTP-движков:ОÑновное _времÑ:Стиль _главной панели инÑтрументов:_Изменить_ИмÑ:_Ðикогда_ÐÐ¾Ð²Ð°Ñ Ð¿Ð°Ñ€Ñ‚Ð¸Ñ_ÐепрозрачноÑть:_Открыть запиÑÑŒ партииСыграный _дебют:_Период дополнительного времени:_ПерепиÑатьРаз_меÑтить камниМеÑ_то проведениÑ:_Играть_Центрировать на текущем узле_ОтноÑительно размера «амазонок»_ОтноÑительно размера диÑков_ОтноÑительно размера камней_СдатьÑÑ_Возобновить_Возобновить партию_РеверÑи_УÑтановить конкретный номер:_Размер:_ИÑточник:_ПереÑтавить_Тема:_Белые:шахматыОтÑутÑтвует_Следующее_ПредыдущееÐе указанвÑтавьте здеÑÑŒ название узлаÐе указаноизмененпаÑÑquarry-0.2.0/po/ChangeLog0000644000175000017500000001231410530113026013656 0ustar bartbart2006-11-19 Paul Pogonyshev * (Quarry version 0.2.0.) * pl.po: Partially update, though I don't know Polish. 2006-11-11 Jeremie Knuesel * fr.po: Update. 2006-11-07 Paul Pogonyshev * quarry.pot: Force update. * en.po: Update. * en_GB.po: Update. * ru.po: Update. 2006-10-30 Robert Stefaniuk * pl.po: Update. 2006-10-29 Jeremie Knuesel * fr.po: Update. 2006-10-29 Paul Pogonyshev * (Quarry version 0.1.20.) 2006-10-28 Paul Pogonyshev * quarry.pot: Force update. * en.po: Update. * en_GB.po: Update. * ru.po: Update. 2006-07-16 Paul Pogonyshev * (Quarry version 0.1.19.) * pl.po: Remove accidentally left slash character, which triggers a severe bug (#6367.) 2006-07-14 Paul Pogonyshev * (Quarry version 0.1.18.) * en.po: New file (English "translation.") * LINGUAS: Add `en' code. * pl.po: Add year 2006 to the copyright string. 2006-07-14 Jérémie Knuesel * fr.po: Update. 2006-07-13 Jérémie Knuesel * fr.po: Update. 2006-07-13 Robert Stefaniuk * pl.po: Update. 2006-07-11 Paul Pogonyshev * quarry.pot: Force update. * en_GB.po: Update. * ru.po: Update. * POTFILES.in: Add `src/gui-gtk/quarry-find-dialog.c'. 2006-04-19 Robert Stefaniuk * pl.po: Update. 2006-03-09 Paul Pogonyshev * (Quarry version 0.1.17.) 2006-03-08 Paul Pogonyshev * en_GB.po: Update. * ru.po: Update. * quarry.pot: Force update. * POTFILES.in: Add `src/gui-gtk/quarry-move-number-dialog.c' and `src/board/board.c'. 2006-01-16 Robert Stefaniuk * pl.po: Update. 2005-12-23 Paul Pogonyshev * LINGUAS: Add `pl' code. 2005-12-19 Robert Stefaniuk * pl.po: New file (Polish translation.) 2005-10-30 Paul Pogonyshev * (Quarry version 0.1.16.) * ru.po: New file (Russian translation.) * LINGUAS: Add `ru' code. * en_GB.po: Update. * quarry.pot: Force update. * POTFILES.in: Add `src/gui-gtk/quarry-save-confirmation-dialog.c', remove `src/gui-gtk/gtk-utils.c'. 2005-07-15 Paul Pogonyshev * POTFILES.in: Add `src/gui-gtk/gtk-go-to-named-node-dialog.c', `src/board/games.c' and `src/board/go.c'. * Makevars (XGETTEXT_OPTIONS): Add `--keyword=Q_'. 2005-06-30 Paul Pogonyshev * Rules-quot: Remove file. * insert-header.sin: Remove file, unused without quotes catalogs. * boldquot.sed: Remove file. Bold quotes are additionally only useful for console programs. * en@boldquot.header: Remove file. * quot.sed: Remove file. Proper quotes are good, but the way they are implemented is not :(. * en@quot.header: Remove file. 2005-06-25 Paul Pogonyshev * en_GB.po: New file (British English translation.) * LINGUAS: List `en_GB' code. 2005-06-20 Paul Pogonyshev * POTFILES.in: Add `src/gui-gtk/gtk-new-game-record-dialog.c'. Remove `src/gui-gtk/gtk-utils.c' as it doesn't contain any translatable strings. 2005-06-17 Paul Pogonyshev * (Quarry version 0.1.15.) 2005-04-12 Paul Pogonyshev * quarry.pot: Force update. * POTFILES.in: Add `src/gui-gtk/gtk-file-dialog.c' and `src/gui-gtk/gtk-resume-game-dialog.c'. * LINGUAS: Add `fr' code for French translation. 2005-04-11 Jérémie Knuesel * fr.po: New file (French translation.) 2005-03-14 Paul Pogonyshev * (Quarry version 0.1.14.) 2005-03-13 Paul Pogonyshev * (Quarry version 0.1.13.) 2005-01-15 Paul Pogonyshev * (Quarry version 0.1.12.) 2005-01-06 Paul Pogonyshev * (Quarry version 0.1.11.) 2004-11-30 Paul Pogonyshev * (Quarry version 0.1.10.) 2004-10-14 Paul Pogonyshev * (Quarry version 0.1.9.) * (Quarry version 0.1.8.) 2004-08-30 Paul Pogonyshev * POTFILES.in: Add `src/gui-gtk/gtk-game-info-dialog.c'. 2004-08-28 Paul Pogonyshev * (Quarry version 0.1.7.) * Makevars (XGETTEXT_OPTIONS): Add `--from-code=UTF-8'. 2004-08-21 Paul Pogonyshev * Makevars: New file. * LINGUAS: New file (empty). * POTFILES.in: New file. 2004-08-21 gettextize * Makefile.in.in: New file, from gettext-0.14.1. * boldquot.sed: New file, from gettext-0.14.1. * en@boldquot.header: New file, from gettext-0.14.1. * en@quot.header: New file, from gettext-0.14.1. * insert-header.sin: New file, from gettext-0.14.1. * quot.sed: New file, from gettext-0.14.1. * remove-potcdate.sin: New file, from gettext-0.14.1. * Rules-quot: New file, from gettext-0.14.1. Copyright (C) 2004, 2005, 2006 Paul Pogonyshev. Copying and distribution of this file, with or without modification, are permitted provided the copyright notice and this notice are preserved. Local Variables: coding: utf-8 End: quarry-0.2.0/po/LINGUAS0000644000175000017500000000005410455545061013145 0ustar bartbart# Available translations: en en_GB fr pl ru quarry-0.2.0/README0000644000175000017500000001234010521204427012353 0ustar bartbart ABOUT QUARRY Quarry is a universal board game interface program. At present it supports three games: Go, Amazons and Reversi. It is intended to be useful for both users and developers of game engines (i.e. programs that play board games). Quarry uses are currently limited to playing against a computer program (e.g. GNU Go) and browsing and editing SGF game records. Future versions will also support Internet game servers and more. Latest Quarry versions can be found at the homepage: http://home.gna.org/quarry/ INSTALLATION The usual `./configure; make; make install' should build and install Quarry. The only serious requirement for Quarry are GTK+ 2.x and librsvg 2.5+ libraries, everything else must be present on a sane system. See file INSTALL for details. RUNNING QUARRY Please refer to the Quarry Manual for help. If, for some reason, you cannot open the manual from Quarry Help menu, direct your browser to the file `help/C/quarry.html'. (There may also be translations of the manual to your language in directories other than `C'.) REPORTING BUGS Please use bug tracker at the Gna! project page for bug submissions. Point your browser to https://gna.org/bugs/?group=quarry Before submitting a bug, please update to the latest CVS version of Quarry and verify that the bug is still present. Don't forget to check if the bug has been submitted already. Please include the following information in your bug report: * Bug description and the way to reproduce the bug. * Output of Quarry in the terminal, if any. It would typically die with a message like this: quarry: file-name.c:123: some_function_name: Assertion `...' failed. * If you fail to configure or build Quarry in the first place, please send in several last lines of `configure's and/or `make's output, depending on where the problem occurred. * System information, including version of GTK+. You can find it by typing pkg-config --modversion gtk+-2.0 in command line. Remember that only GTK+ 2.0 or later is supported. If you have an older version, Quarry will fail to configure and it is not a bug. * Everything else you find relevant. COPYRIGHTS AND LICENSES All files are copyrighted by Paul Pogonyshev and/or other Quarry authors (see file AUTHORS) except as noted below. See each specific file for details. All files are licensed under the GNU General Public License version 2 or (at your option) any later version except as noted below. GNU GPL version 2 can be found in the file COPYING. All files named `quarry.xml' and `quarry.html' in `help/*' directories are licensed under GNU Free Documentation License, version 1.2 or any later version, with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. GNU FDL version 1.2 can be found in file named COPYING-DOC. * Three files `src/utils/getopt.c', `src/utils/getopt1.c' and `src/utils/getopt.h' are copyrighted by the Free Software Foundation and are distributed under GNU LGPL version 2.1 or later. * Files `src/gui-gtk/gtk-color-button.c' and `src/gui-gtk/gtk-color-button.h' are copyrighted 1998, 1999 by Red Hat, Inc. They are licensed GNU LGPL version 2 or later. * Files `src/gui-gtk/gtk-qhbox.c' and `src/gui-gtk/gtk-qvbox.c' are copyrighted 1995-1997 by Peter Mattis, Spencer Kimball and Josh MacDonald and copyrighted in subsequent years by Paul Pogonyshev. They are licensed under GNU GPL version 2 or later. * File `data/textures/wood1.jpg' can be distributed freely [1]. * File `data/textures/wood2.jpg' is copyrighted 2005 by Brenn Hill and is distributed under Creative Commons Attribution-NonCommercial- ShareAlike 2.0 license, which can be found at http://creativecommons.org/licenses/by-nc-sa/2.0/legalcode. * All SVG files in `data/markup-themes' subdirectories are placed in public domain by Paul Pogonyshev. * Files in the root directory of the distribution (this directory) and `build' directory are either licensed by different parties as free software or are in public domain. [1] This file was taken from http://www.grsites.com/ On the site there is a disclaimer with the following text: "Disclaimer: Background textures found on this site were not created by the webmaster. They were obtained from various sources on the internet that labeled them as "freely distributable". If you should discover images in this collection which you recognize as copyrighted, please email the webmaster immediately so that they may be removed." And in its "Terms of use" section, it is stated that "The background textures found on this site were not created by the webmaster, but were obtained from various sources on the internet that described these graphics as freeware. Some of the authors, however, might disapprove if their graphics were used, for example, as part of a commercial software package. Therefore, these graphics are best suited for personal use (i.e. on a personal web site.)" I'm very interested in a good texture that is either cleanly licensed in a non-restrictive way that allows redistribution and modification or is in public domain. If you happen to have/know about such a texture that would fit Quarry's look, please send it or a link to it to . quarry-0.2.0/Makefile.in0000644000175000017500000004366610425150132013553 0ustar bartbart# Makefile.in generated by automake 1.7.9 from Makefile.am. # @configure_input@ # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 # Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # Process this file with Automake to produce `Makefile.in'. srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = . am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : host_triplet = @host@ ACLOCAL = @ACLOCAL@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BUILD_SGF_UTILS_FALSE = @BUILD_SGF_UTILS_FALSE@ BUILD_SGF_UTILS_TRUE = @BUILD_SGF_UTILS_TRUE@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DO_SCROLLKEEPER_UPDATE_FALSE = @DO_SCROLLKEEPER_UPDATE_FALSE@ DO_SCROLLKEEPER_UPDATE_TRUE = @DO_SCROLLKEEPER_UPDATE_TRUE@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ GMSGFMT = @GMSGFMT@ HAVE_SCROLLKEEPER_FALSE = @HAVE_SCROLLKEEPER_FALSE@ HAVE_SCROLLKEEPER_TRUE = @HAVE_SCROLLKEEPER_TRUE@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ LDFLAGS = @LDFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ MAKEINFO = @MAKEINFO@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGMERGE = @MSGMERGE@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSUB = @POSUB@ QUARRY_GTHREAD_CFLAGS = @QUARRY_GTHREAD_CFLAGS@ QUARRY_GTHREAD_LIBS = @QUARRY_GTHREAD_LIBS@ QUARRY_GTK_CFLAGS = @QUARRY_GTK_CFLAGS@ QUARRY_GTK_DEPRECATED_FLAGS = @QUARRY_GTK_DEPRECATED_FLAGS@ QUARRY_GTK_LIBS = @QUARRY_GTK_LIBS@ QUARRY_WARNINGS = @QUARRY_WARNINGS@ QUARRY_WARNINGS_GTK = @QUARRY_WARNINGS_GTK@ RANLIB = @RANLIB@ REGISTER_MIME_TYPES_FALSE = @REGISTER_MIME_TYPES_FALSE@ REGISTER_MIME_TYPES_TRUE = @REGISTER_MIME_TYPES_TRUE@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ ac_ct_CC = @ac_ct_CC@ ac_ct_RANLIB = @ac_ct_RANLIB@ ac_ct_STRIP = @ac_ct_STRIP@ ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ datadir = @datadir@ exec_prefix = @exec_prefix@ have_scrollkeeper = @have_scrollkeeper@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localstatedir = @localstatedir@ mandir = @mandir@ oldincludedir = @oldincludedir@ prefix = @prefix@ program_transform_name = @program_transform_name@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ SUBDIRS = \ data \ help \ po \ src EXTRA_DIST = \ COPYING-DOC DISTCLEANFILES = *~ subdir = . ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 mkinstalldirs = $(SHELL) $(top_srcdir)/build/mkinstalldirs CONFIG_HEADER = config.h CONFIG_CLEAN_FILES = DIST_SOURCES = RECURSIVE_TARGETS = info-recursive dvi-recursive pdf-recursive \ ps-recursive install-info-recursive uninstall-info-recursive \ all-recursive install-data-recursive install-exec-recursive \ installdirs-recursive install-recursive uninstall-recursive \ check-recursive installcheck-recursive DIST_COMMON = README $(srcdir)/Makefile.in $(srcdir)/configure AUTHORS \ COPYING ChangeLog INSTALL Makefile.am NEWS THANKS TODO \ aclocal.m4 build/config.guess build/config.rpath \ build/config.sub build/depcomp build/install-sh build/missing \ build/mkinstalldirs config.h.in configure.ac DIST_SUBDIRS = $(SUBDIRS) all: config.h $(MAKE) $(AM_MAKEFLAGS) all-recursive .SUFFIXES: am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4) cd $(top_srcdir) && \ $(AUTOMAKE) --foreign Makefile Makefile: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe) $(top_builddir)/config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck $(srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(srcdir)/configure.ac $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES) cd $(srcdir) && $(AUTOCONF) $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ configure.ac cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) config.h: stamp-h1 @if test ! -f $@; then \ rm -f stamp-h1; \ $(MAKE) stamp-h1; \ else :; fi stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status @rm -f stamp-h1 cd $(top_builddir) && $(SHELL) ./config.status config.h $(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(top_srcdir)/configure.ac $(ACLOCAL_M4) cd $(top_srcdir) && $(AUTOHEADER) touch $(srcdir)/config.h.in distclean-hdr: -rm -f config.h stamp-h1 uninstall-info-am: # This directory's subdirectories are mostly independent; you can cd # into them and run `make' without going through this Makefile. # To change the values of `make' variables: instead of editing Makefiles, # (1) if the variable is set in `config.status', edit `config.status' # (which will cause the Makefiles to be regenerated when you run `make'); # (2) otherwise, pass the desired values on the `make' command line. $(RECURSIVE_TARGETS): @set fnord $$MAKEFLAGS; amf=$$2; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ list='$(SUBDIRS)'; for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" mostlyclean-recursive clean-recursive distclean-recursive \ maintainer-clean-recursive: @set fnord $$MAKEFLAGS; amf=$$2; \ dot_seen=no; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ rev=''; for subdir in $$list; do \ if test "$$subdir" = "."; then :; else \ rev="$$subdir $$rev"; \ fi; \ done; \ rev="$$rev ."; \ target=`echo $@ | sed s/-recursive//`; \ for subdir in $$rev; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ done && test -z "$$fail" tags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ done ctags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ done ETAGS = etags ETAGSFLAGS = CTAGS = ctags CTAGSFLAGS = tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ if (etags --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ else \ include_option=--include; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test -f $$subdir/TAGS && \ tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(ETAGS_ARGS)$$tags$$unique" \ || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique ctags: CTAGS CTAGS: ctags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = . distdir = $(PACKAGE)-$(VERSION) am__remove_distdir = \ { test ! -d $(distdir) \ || { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \ && rm -fr $(distdir); }; } GZIP_ENV = --best distuninstallcheck_listfiles = find . -type f -print distcleancheck_listfiles = find . -type f -print distdir: $(DISTFILES) @case `sed 15q $(srcdir)/NEWS` in \ *"$(VERSION)"*) : ;; \ *) \ echo "NEWS not updated; not releasing" 1>&2; \ exit 1;; \ esac $(am__remove_distdir) mkdir $(distdir) $(mkinstalldirs) $(distdir)/build $(distdir)/data $(distdir)/po @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ case $$file in \ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ esac; \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ dir="/$$dir"; \ $(mkinstalldirs) "$(distdir)$$dir"; \ else \ dir=''; \ fi; \ if test -d $$d/$$file; then \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test -d $(distdir)/$$subdir \ || mkdir $(distdir)/$$subdir \ || exit 1; \ (cd $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" \ distdir=../$(distdir)/$$subdir \ distdir) \ || exit 1; \ fi; \ done -find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ ! -type d ! -perm -444 -exec $(SHELL) $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r $(distdir) dist-gzip: distdir $(AMTAR) chof - $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz $(am__remove_distdir) dist dist-all: distdir $(AMTAR) chof - $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz $(am__remove_distdir) # This target untars the dist file and tries a VPATH configuration. Then # it guarantees that the distribution is self-contained by making another # tarfile. distcheck: dist $(am__remove_distdir) GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(AMTAR) xf - chmod -R a-w $(distdir); chmod a+w $(distdir) mkdir $(distdir)/_build mkdir $(distdir)/_inst chmod a-w $(distdir) dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && cd $(distdir)/_build \ && ../configure --srcdir=.. --prefix="$$dc_install_base" \ $(DISTCHECK_CONFIGURE_FLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) dvi \ && $(MAKE) $(AM_MAKEFLAGS) check \ && $(MAKE) $(AM_MAKEFLAGS) install \ && $(MAKE) $(AM_MAKEFLAGS) installcheck \ && $(MAKE) $(AM_MAKEFLAGS) uninstall \ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ distuninstallcheck \ && chmod -R a-w "$$dc_install_base" \ && ({ \ (cd ../.. && $(mkinstalldirs) "$$dc_destdir") \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ } || { rm -rf "$$dc_destdir"; exit 1; }) \ && rm -rf "$$dc_destdir" \ && $(MAKE) $(AM_MAKEFLAGS) dist-gzip \ && rm -f $(distdir).tar.gz \ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck $(am__remove_distdir) @echo "$(distdir).tar.gz is ready for distribution" | \ sed 'h;s/./=/g;p;x;p;x' distuninstallcheck: @cd $(distuninstallcheck_dir) \ && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \ || { echo "ERROR: files left after uninstall:" ; \ if test -n "$(DESTDIR)"; then \ echo " (check DESTDIR support)"; \ fi ; \ $(distuninstallcheck_listfiles) ; \ exit 1; } >&2 distcleancheck: distclean @if test '$(srcdir)' = . ; then \ echo "ERROR: distcleancheck can only run from a VPATH build" ; \ exit 1 ; \ fi @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left in build directory after distclean:" ; \ $(distcleancheck_listfiles) ; \ exit 1; } >&2 check-am: all-am check: check-recursive all-am: Makefile config.h installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -rm -f $(CONFIG_CLEAN_FILES) -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic mostlyclean-am distclean: distclean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -f Makefile distclean-am: clean-am distclean-generic distclean-hdr distclean-tags dvi: dvi-recursive dvi-am: info: info-recursive info-am: install-data-am: install-exec-am: install-info: install-info-recursive install-man: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-info-am uninstall-info: uninstall-info-recursive .PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am check check-am clean \ clean-generic clean-recursive ctags ctags-recursive dist \ dist-all dist-gzip distcheck distclean distclean-generic \ distclean-hdr distclean-recursive distclean-tags distcleancheck \ distdir distuninstallcheck dvi dvi-am dvi-recursive info \ info-am info-recursive install install-am install-data \ install-data-am install-data-recursive install-exec \ install-exec-am install-exec-recursive install-info \ install-info-am install-info-recursive install-man \ install-recursive install-strip installcheck installcheck-am \ installdirs installdirs-am installdirs-recursive \ maintainer-clean maintainer-clean-generic \ maintainer-clean-recursive mostlyclean mostlyclean-generic \ mostlyclean-recursive pdf pdf-am pdf-recursive ps ps-am \ ps-recursive tags tags-recursive uninstall uninstall-am \ uninstall-info-am uninstall-info-recursive uninstall-recursive # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: quarry-0.2.0/configure0000755000175000017500000110421210530112726013403 0ustar bartbart#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.59 for Quarry 0.2.0. # # Report bugs to . # # Copyright (C) 2003 Free Software Foundation, Inc. # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## --------------------- ## ## M4sh Initialization. ## ## --------------------- ## # Be Bourne compatible if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then set -o posix fi DUALCASE=1; export DUALCASE # for MKS sh # Support unset when possible. if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then as_unset=unset else as_unset=false fi # Work around bugs in pre-3.0 UWIN ksh. $as_unset ENV MAIL MAILPATH PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. for as_var in \ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ LC_TELEPHONE LC_TIME do if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then eval $as_var=C; export $as_var else $as_unset $as_var fi done # Required to use basename. if expr a : '\(a\)' >/dev/null 2>&1; then as_expr=expr else as_expr=false fi if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi # Name of the executable. as_me=`$as_basename "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)$' \| \ . : '\(.\)' 2>/dev/null || echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } /^X\/\(\/\/\)$/{ s//\1/; q; } /^X\/\(\/\).*/{ s//\1/; q; } s/.*/./; q'` # PATH needs CR, and LINENO needs CR and PATH. # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi as_lineno_1=$LINENO as_lineno_2=$LINENO as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` test "x$as_lineno_1" != "x$as_lineno_2" && test "x$as_lineno_3" = "x$as_lineno_2" || { # Find who we are. Look in the path if we contain no path at all # relative or not. case $0 in *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2 { (exit 1); exit 1; }; } fi case $CONFIG_SHELL in '') as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for as_base in sh bash ksh sh5; do case $as_dir in /*) if ("$as_dir/$as_base" -c ' as_lineno_1=$LINENO as_lineno_2=$LINENO as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` test "x$as_lineno_1" != "x$as_lineno_2" && test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } CONFIG_SHELL=$as_dir/$as_base export CONFIG_SHELL exec "$CONFIG_SHELL" "$0" ${1+"$@"} fi;; esac done done ;; esac # Create $as_me.lineno as a copy of $as_myself, but with $LINENO # uniformly replaced by the line number. The first 'sed' inserts a # line-number line before each line; the second 'sed' does the real # work. The second script uses 'N' to pair each line-number line # with the numbered line, and appends trailing '-' during # substitution so that $LINENO is not a special case at line end. # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) sed '=' <$as_myself | sed ' N s,$,-, : loop s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, t loop s,-$,, s,^['$as_cr_digits']*\n,, ' >$as_me.lineno && chmod +x $as_me.lineno || { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 { (exit 1); exit 1; }; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensible to this). . ./$as_me.lineno # Exit status is that of the last command. exit } case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in *c*,-n*) ECHO_N= ECHO_C=' ' ECHO_T=' ' ;; *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; *) ECHO_N= ECHO_C='\c' ECHO_T= ;; esac if expr a : '\(a\)' >/dev/null 2>&1; then as_expr=expr else as_expr=false fi rm -f conf$$ conf$$.exe conf$$.file echo >conf$$.file if ln -s conf$$.file conf$$ 2>/dev/null; then # We could just check for DJGPP; but this test a) works b) is more generic # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). if test -f conf$$.exe; then # Don't use ln at all; we don't have any links as_ln_s='cp -p' else as_ln_s='ln -s' fi elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.file if mkdir -p . 2>/dev/null; then as_mkdir_p=: else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_executable_p="test -f" # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" # IFS # We need space, tab and new line, in precisely that order. as_nl=' ' IFS=" $as_nl" # CDPATH. $as_unset CDPATH # Name of the host. # hostname on some systems (SVR3.2, Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` exec 6>&1 # # Initializations. # ac_default_prefix=/usr/local ac_config_libobj_dir=. cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= SHELL=${CONFIG_SHELL-/bin/sh} # Maximum number of lines to put in a shell here document. # This variable seems obsolete. It should probably be removed, and # only ac_max_sed_lines should be used. : ${ac_max_here_lines=38} # Identity of this package. PACKAGE_NAME='Quarry' PACKAGE_TARNAME='quarry' PACKAGE_VERSION='0.2.0' PACKAGE_STRING='Quarry 0.2.0' PACKAGE_BUGREPORT='quarry-dev@gna.org' ac_unique_file="src/quarry.c" # Factoring default headers for most tests. ac_includes_default="\ #include #if HAVE_SYS_TYPES_H # include #endif #if HAVE_SYS_STAT_H # include #endif #if STDC_HEADERS # include # include #else # if HAVE_STDLIB_H # include # endif #endif #if HAVE_STRING_H # if !STDC_HEADERS && HAVE_MEMORY_H # include # endif # include #endif #if HAVE_STRINGS_H # include #endif #if HAVE_INTTYPES_H # include #else # if HAVE_STDINT_H # include # endif #endif #if HAVE_UNISTD_H # include #endif" ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO AMTAR install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM AWK SET_MAKE am__leading_dot MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE RANLIB ac_ct_RANLIB QUARRY_WARNINGS QUARRY_WARNINGS_GTK CPP EGREP LIBOBJS MKINSTALLDIRS USE_NLS MSGFMT GMSGFMT XGETTEXT MSGMERGE build build_cpu build_vendor build_os host host_cpu host_vendor host_os INTL_MACOSX_LIBS LIBICONV LTLIBICONV INTLLIBS LIBINTL LTLIBINTL POSUB have_scrollkeeper HAVE_SCROLLKEEPER_TRUE HAVE_SCROLLKEEPER_FALSE PKG_CONFIG ac_pt_PKG_CONFIG QUARRY_GTK_CFLAGS QUARRY_GTK_LIBS QUARRY_GTHREAD_CFLAGS QUARRY_GTHREAD_LIBS GLIB_GENMARSHAL BUILD_SGF_UTILS_TRUE BUILD_SGF_UTILS_FALSE QUARRY_GTK_DEPRECATED_FLAGS DO_SCROLLKEEPER_UPDATE_TRUE DO_SCROLLKEEPER_UPDATE_FALSE REGISTER_MIME_TYPES_TRUE REGISTER_MIME_TYPES_FALSE LTLIBOBJS' ac_subst_files='' # Initialize some variables set by options. ac_init_help= ac_init_version=false # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datadir='${prefix}/share' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' libdir='${exec_prefix}/lib' includedir='${prefix}/include' oldincludedir='/usr/include' infodir='${prefix}/info' mandir='${prefix}/man' ac_prev= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval "$ac_prev=\$ac_option" ac_prev= continue fi ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'` # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_option in -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad | --data | --dat | --da) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ | --da=*) datadir=$ac_optarg ;; -disable-* | --disable-*) ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid feature name: $ac_feature" >&2 { (exit 1); exit 1; }; } ac_feature=`echo $ac_feature | sed 's/-/_/g'` eval "enable_$ac_feature=no" ;; -enable-* | --enable-*) ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid feature name: $ac_feature" >&2 { (exit 1); exit 1; }; } ac_feature=`echo $ac_feature | sed 's/-/_/g'` case $ac_option in *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; *) ac_optarg=yes ;; esac eval "enable_$ac_feature='$ac_optarg'" ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst \ | --locals | --local | --loca | --loc | --lo) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* \ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid package name: $ac_package" >&2 { (exit 1); exit 1; }; } ac_package=`echo $ac_package| sed 's/-/_/g'` case $ac_option in *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; *) ac_optarg=yes ;; esac eval "with_$ac_package='$ac_optarg'" ;; -without-* | --without-*) ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid package name: $ac_package" >&2 { (exit 1); exit 1; }; } ac_package=`echo $ac_package | sed 's/-/_/g'` eval "with_$ac_package=no" ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) { echo "$as_me: error: unrecognized option: $ac_option Try \`$0 --help' for more information." >&2 { (exit 1); exit 1; }; } ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 { (exit 1); exit 1; }; } ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` eval "$ac_envvar='$ac_optarg'" export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` { echo "$as_me: error: missing argument to $ac_option" >&2 { (exit 1); exit 1; }; } fi # Be sure to have absolute paths. for ac_var in exec_prefix prefix do eval ac_val=$`echo $ac_var` case $ac_val in [\\/$]* | ?:[\\/]* | NONE | '' ) ;; *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 { (exit 1); exit 1; }; };; esac done # Be sure to have absolute paths. for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \ localstatedir libdir includedir oldincludedir infodir mandir do eval ac_val=$`echo $ac_var` case $ac_val in [\\/$]* | ?:[\\/]* ) ;; *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 { (exit 1); exit 1; }; };; esac done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. If a cross compiler is detected then cross compile mode will be used." >&2 elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then its parent. ac_confdir=`(dirname "$0") 2>/dev/null || $as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$0" : 'X\(//\)[^/]' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$0" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` srcdir=$ac_confdir if test ! -r $srcdir/$ac_unique_file; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r $srcdir/$ac_unique_file; then if test "$ac_srcdir_defaulted" = yes; then { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2 { (exit 1); exit 1; }; } else { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 { (exit 1); exit 1; }; } fi fi (cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null || { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2 { (exit 1); exit 1; }; } srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'` ac_env_build_alias_set=${build_alias+set} ac_env_build_alias_value=$build_alias ac_cv_env_build_alias_set=${build_alias+set} ac_cv_env_build_alias_value=$build_alias ac_env_host_alias_set=${host_alias+set} ac_env_host_alias_value=$host_alias ac_cv_env_host_alias_set=${host_alias+set} ac_cv_env_host_alias_value=$host_alias ac_env_target_alias_set=${target_alias+set} ac_env_target_alias_value=$target_alias ac_cv_env_target_alias_set=${target_alias+set} ac_cv_env_target_alias_value=$target_alias ac_env_CC_set=${CC+set} ac_env_CC_value=$CC ac_cv_env_CC_set=${CC+set} ac_cv_env_CC_value=$CC ac_env_CFLAGS_set=${CFLAGS+set} ac_env_CFLAGS_value=$CFLAGS ac_cv_env_CFLAGS_set=${CFLAGS+set} ac_cv_env_CFLAGS_value=$CFLAGS ac_env_LDFLAGS_set=${LDFLAGS+set} ac_env_LDFLAGS_value=$LDFLAGS ac_cv_env_LDFLAGS_set=${LDFLAGS+set} ac_cv_env_LDFLAGS_value=$LDFLAGS ac_env_CPPFLAGS_set=${CPPFLAGS+set} ac_env_CPPFLAGS_value=$CPPFLAGS ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set} ac_cv_env_CPPFLAGS_value=$CPPFLAGS ac_env_CPP_set=${CPP+set} ac_env_CPP_value=$CPP ac_cv_env_CPP_set=${CPP+set} ac_cv_env_CPP_value=$CPP ac_env_PKG_CONFIG_set=${PKG_CONFIG+set} ac_env_PKG_CONFIG_value=$PKG_CONFIG ac_cv_env_PKG_CONFIG_set=${PKG_CONFIG+set} ac_cv_env_PKG_CONFIG_value=$PKG_CONFIG ac_env_QUARRY_GTK_CFLAGS_set=${QUARRY_GTK_CFLAGS+set} ac_env_QUARRY_GTK_CFLAGS_value=$QUARRY_GTK_CFLAGS ac_cv_env_QUARRY_GTK_CFLAGS_set=${QUARRY_GTK_CFLAGS+set} ac_cv_env_QUARRY_GTK_CFLAGS_value=$QUARRY_GTK_CFLAGS ac_env_QUARRY_GTK_LIBS_set=${QUARRY_GTK_LIBS+set} ac_env_QUARRY_GTK_LIBS_value=$QUARRY_GTK_LIBS ac_cv_env_QUARRY_GTK_LIBS_set=${QUARRY_GTK_LIBS+set} ac_cv_env_QUARRY_GTK_LIBS_value=$QUARRY_GTK_LIBS ac_env_QUARRY_GTHREAD_CFLAGS_set=${QUARRY_GTHREAD_CFLAGS+set} ac_env_QUARRY_GTHREAD_CFLAGS_value=$QUARRY_GTHREAD_CFLAGS ac_cv_env_QUARRY_GTHREAD_CFLAGS_set=${QUARRY_GTHREAD_CFLAGS+set} ac_cv_env_QUARRY_GTHREAD_CFLAGS_value=$QUARRY_GTHREAD_CFLAGS ac_env_QUARRY_GTHREAD_LIBS_set=${QUARRY_GTHREAD_LIBS+set} ac_env_QUARRY_GTHREAD_LIBS_value=$QUARRY_GTHREAD_LIBS ac_cv_env_QUARRY_GTHREAD_LIBS_set=${QUARRY_GTHREAD_LIBS+set} ac_cv_env_QUARRY_GTHREAD_LIBS_value=$QUARRY_GTHREAD_LIBS # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures Quarry 0.2.0 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] _ACEOF cat <<_ACEOF Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --datadir=DIR read-only architecture-independent data [PREFIX/share] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --infodir=DIR info documentation [PREFIX/info] --mandir=DIR man documentation [PREFIX/man] _ACEOF cat <<\_ACEOF Program names: --program-prefix=PREFIX prepend PREFIX to installed program names --program-suffix=SUFFIX append SUFFIX to installed program names --program-transform-name=PROGRAM run sed PROGRAM on installed program names System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of Quarry 0.2.0:";; esac cat <<\_ACEOF Optional Features: --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-maintainer-mode enable make rules and dependencies not useful (and sometimes confusing) to the casual installer --disable-dependency-tracking Speeds up one-time builds --enable-dependency-tracking Do not reject slow dependency extractors --disable-nls do not use Native Language Support --disable-rpath do not hardcode runtime library paths --enable-sgf-utils enable automatic building and installation of standalone SGF utilities --disable-gtk-deprecated disable deprecated GTK+ features (for maintainers; don't use for normal builds) --disable-scrollkeeper-update don't update ScrollKeeper database (for packagers) --disable-mime-database-update don't update the Shared MIME-info Database Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-gnu-ld assume the C compiler uses GNU ld default=no --with-libiconv-prefix[=DIR] search for libiconv in DIR/include and DIR/lib --without-libiconv-prefix don't search for libiconv in includedir and libdir --with-libintl-prefix[=DIR] search for libintl in DIR/include and DIR/lib --without-libintl-prefix don't search for libintl in includedir and libdir Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory CPPFLAGS C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor PKG_CONFIG path to pkg-config utility QUARRY_GTK_CFLAGS C compiler flags for QUARRY_GTK, overriding pkg-config QUARRY_GTK_LIBS linker flags for QUARRY_GTK, overriding pkg-config QUARRY_GTHREAD_CFLAGS C compiler flags for QUARRY_GTHREAD, overriding pkg-config QUARRY_GTHREAD_LIBS linker flags for QUARRY_GTHREAD, overriding pkg-config Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to . _ACEOF fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. ac_popdir=`pwd` for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d $ac_dir || continue ac_builddir=. if test "$ac_dir" != .; then ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` # A "../" for each directory in $ac_dir_suffix. ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` else ac_dir_suffix= ac_top_builddir= fi case $srcdir in .) # No --srcdir option. We are building in place. ac_srcdir=. if test -z "$ac_top_builddir"; then ac_top_srcdir=. else ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` fi ;; [\\/]* | ?:[\\/]* ) # Absolute path. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ;; *) # Relative path. ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_builddir$srcdir ;; esac # Do not use `cd foo && pwd` to compute absolute paths, because # the directories may not exist. case `pwd` in .) ac_abs_builddir="$ac_dir";; *) case "$ac_dir" in .) ac_abs_builddir=`pwd`;; [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; *) ac_abs_builddir=`pwd`/"$ac_dir";; esac;; esac case $ac_abs_builddir in .) ac_abs_top_builddir=${ac_top_builddir}.;; *) case ${ac_top_builddir}. in .) ac_abs_top_builddir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; esac;; esac case $ac_abs_builddir in .) ac_abs_srcdir=$ac_srcdir;; *) case $ac_srcdir in .) ac_abs_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; esac;; esac case $ac_abs_builddir in .) ac_abs_top_srcdir=$ac_top_srcdir;; *) case $ac_top_srcdir in .) ac_abs_top_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; esac;; esac cd $ac_dir # Check for guested configure; otherwise get Cygnus style configure. if test -f $ac_srcdir/configure.gnu; then echo $SHELL $ac_srcdir/configure.gnu --help=recursive elif test -f $ac_srcdir/configure; then echo $SHELL $ac_srcdir/configure --help=recursive elif test -f $ac_srcdir/configure.ac || test -f $ac_srcdir/configure.in; then echo $ac_configure --help else echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi cd "$ac_popdir" done fi test -n "$ac_init_help" && exit 0 if $ac_init_version; then cat <<\_ACEOF Quarry configure 0.2.0 generated by GNU Autoconf 2.59 Copyright (C) 2003 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit 0 fi exec 5>config.log cat >&5 <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by Quarry $as_me 0.2.0, which was generated by GNU Autoconf 2.59. Invocation command line was $ $0 $@ _ACEOF { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` hostinfo = `(hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. echo "PATH: $as_dir" done } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_sep= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; 2) ac_configure_args1="$ac_configure_args1 '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'" # Get rid of the leading space. ac_sep=" " ;; esac done done $as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } $as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Be sure not to use single quotes in there, as some shells, # such as our DU 5.0 friend, will then `close' the trap. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo cat <<\_ASBOX ## ---------------- ## ## Cache variables. ## ## ---------------- ## _ASBOX echo # The following way of writing the cache mishandles newlines in values, { (set) 2>&1 | case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in *ac_space=\ *) sed -n \ "s/'"'"'/'"'"'\\\\'"'"''"'"'/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p" ;; *) sed -n \ "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" ;; esac; } echo cat <<\_ASBOX ## ----------------- ## ## Output variables. ## ## ----------------- ## _ASBOX echo for ac_var in $ac_subst_vars do eval ac_val=$`echo $ac_var` echo "$ac_var='"'"'$ac_val'"'"'" done | sort echo if test -n "$ac_subst_files"; then cat <<\_ASBOX ## ------------- ## ## Output files. ## ## ------------- ## _ASBOX echo for ac_var in $ac_subst_files do eval ac_val=$`echo $ac_var` echo "$ac_var='"'"'$ac_val'"'"'" done | sort echo fi if test -s confdefs.h; then cat <<\_ASBOX ## ----------- ## ## confdefs.h. ## ## ----------- ## _ASBOX echo sed "/^$/d" confdefs.h | sort echo fi test "$ac_signal" != 0 && echo "$as_me: caught signal $ac_signal" echo "$as_me: exit $exit_status" } >&5 rm -f core *.core && rm -rf conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -rf conftest* confdefs.h # AIX cpp loses on an empty file, so make sure it contains at least a newline. echo >confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer explicitly selected file to automatically selected ones. if test -z "$CONFIG_SITE"; then if test "x$prefix" != xNONE; then CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" else CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" fi fi for ac_site_file in $CONFIG_SITE; do if test -r "$ac_site_file"; then { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special # files actually), so we avoid doing that. if test -f "$cache_file"; then { echo "$as_me:$LINENO: loading cache $cache_file" >&5 echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . $cache_file;; *) . ./$cache_file;; esac fi else { echo "$as_me:$LINENO: creating cache $cache_file" >&5 echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in `(set) 2>&1 | sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val="\$ac_cv_env_${ac_var}_value" eval ac_new_val="\$ac_env_${ac_var}_value" case $ac_old_set,$ac_new_set in set,) { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 echo "$as_me: former value: $ac_old_val" >&2;} { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 echo "$as_me: current value: $ac_new_val" >&2;} ac_cache_corrupted=: fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 echo "$as_me: error: changes in the environment can compromise the build" >&2;} { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} { (exit 1); exit 1; }; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # Check if the script is running in the proper directory. Alarm if it # is not. ac_aux_dir= for ac_dir in build $srcdir/build; do if test -f $ac_dir/install-sh; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f $ac_dir/install.sh; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break elif test -f $ac_dir/shtool; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in build $srcdir/build" >&5 echo "$as_me: error: cannot find install-sh or install.sh in build $srcdir/build" >&2;} { (exit 1); exit 1; }; } fi ac_config_guess="$SHELL $ac_aux_dir/config.guess" ac_config_sub="$SHELL $ac_aux_dir/config.sub" ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure. # Initialize Automake and add maintainer mode as an option. am__api_version="1.7" # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AmigaOS /C/install, which installs bootblocks on floppy discs # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6 if test -z "$INSTALL"; then if test "${ac_cv_path_install+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. # Account for people who put trailing slashes in PATH elements. case $as_dir/ in ./ | .// | /cC/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" break 3 fi fi done done ;; esac done fi if test "${ac_cv_path_install+set}" = set; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. We don't cache a # path for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the path is relative. INSTALL=$ac_install_sh fi fi echo "$as_me:$LINENO: result: $INSTALL" >&5 echo "${ECHO_T}$INSTALL" >&6 # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' echo "$as_me:$LINENO: checking whether build environment is sane" >&5 echo $ECHO_N "checking whether build environment is sane... $ECHO_C" >&6 # Just in case sleep 1 echo timestamp > conftest.file # Do `set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` if test "$*" = "X"; then # -L didn't work. set X `ls -t $srcdir/configure conftest.file` fi rm -f conftest.file if test "$*" != "X $srcdir/configure conftest.file" \ && test "$*" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". { { echo "$as_me:$LINENO: error: ls -t appears to fail. Make sure there is not a broken alias in your environment" >&5 echo "$as_me: error: ls -t appears to fail. Make sure there is not a broken alias in your environment" >&2;} { (exit 1); exit 1; }; } fi test "$2" = conftest.file ) then # Ok. : else { { echo "$as_me:$LINENO: error: newly created file is older than distributed files! Check your system clock" >&5 echo "$as_me: error: newly created file is older than distributed files! Check your system clock" >&2;} { (exit 1); exit 1; }; } fi echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 test "$program_prefix" != NONE && program_transform_name="s,^,$program_prefix,;$program_transform_name" # Use a double $ so make ignores it. test "$program_suffix" != NONE && program_transform_name="s,\$,$program_suffix,;$program_transform_name" # Double any \ or $. echo might interpret backslashes. # By default was `s,x,x', remove it if useless. cat <<\_ACEOF >conftest.sed s/[\\$]/&&/g;s/;s,x,x,$// _ACEOF program_transform_name=`echo $program_transform_name | sed -f conftest.sed` rm conftest.sed # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" # Use eval to expand $SHELL if eval "$MISSING --run true"; then am_missing_run="$MISSING --run " else am_missing_run= { echo "$as_me:$LINENO: WARNING: \`missing' script is too old or missing" >&5 echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;} fi for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_AWK+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AWK="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then echo "$as_me:$LINENO: result: $AWK" >&5 echo "${ECHO_T}$AWK" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -n "$AWK" && break done echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5 echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6 set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,:./+-,___p_,'` if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.make <<\_ACEOF all: @echo 'ac_maketemp="$(MAKE)"' _ACEOF # GNU make sometimes prints "make[1]: Entering...", which would confuse us. eval `${MAKE-make} -f conftest.make 2>/dev/null | grep temp=` if test -n "$ac_maketemp"; then eval ac_cv_prog_make_${ac_make}_set=yes else eval ac_cv_prog_make_${ac_make}_set=no fi rm -f conftest.make fi if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 SET_MAKE= else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 SET_MAKE="MAKE=${MAKE-make}" fi rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null # test to see if srcdir already configured if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then { { echo "$as_me:$LINENO: error: source directory already configured; run \"make distclean\" there first" >&5 echo "$as_me: error: source directory already configured; run \"make distclean\" there first" >&2;} { (exit 1); exit 1; }; } fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi # Define the identity of the package. PACKAGE='quarry' VERSION='0.2.0' cat >>confdefs.h <<_ACEOF #define PACKAGE "$PACKAGE" _ACEOF cat >>confdefs.h <<_ACEOF #define VERSION "$VERSION" _ACEOF # Some tools Automake needs. ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} AMTAR=${AMTAR-"${am_missing_run}tar"} install_sh=${install_sh-"$am_aux_dir/install-sh"} # Installed binaries are usually stripped using `strip' when the user # run `make install-strip'. However `strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the `STRIP' environment variable to overrule this program. if test "$cross_compiling" != no; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_STRIP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then echo "$as_me:$LINENO: result: $STRIP" >&5 echo "${ECHO_T}$STRIP" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done test -z "$ac_cv_prog_ac_ct_STRIP" && ac_cv_prog_ac_ct_STRIP=":" fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5 echo "${ECHO_T}$ac_ct_STRIP" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi STRIP=$ac_ct_STRIP else STRIP="$ac_cv_prog_STRIP" fi fi INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s" # We need awk for the "check" target. The system "awk" is bad on # some platforms. echo "$as_me:$LINENO: checking whether to enable maintainer-specific portions of Makefiles" >&5 echo $ECHO_N "checking whether to enable maintainer-specific portions of Makefiles... $ECHO_C" >&6 # Check whether --enable-maintainer-mode or --disable-maintainer-mode was given. if test "${enable_maintainer_mode+set}" = set; then enableval="$enable_maintainer_mode" USE_MAINTAINER_MODE=$enableval else USE_MAINTAINER_MODE=no fi; echo "$as_me:$LINENO: result: $USE_MAINTAINER_MODE" >&5 echo "${ECHO_T}$USE_MAINTAINER_MODE" >&6 if test $USE_MAINTAINER_MODE = yes; then MAINTAINER_MODE_TRUE= MAINTAINER_MODE_FALSE='#' else MAINTAINER_MODE_TRUE='#' MAINTAINER_MODE_FALSE= fi MAINT=$MAINTAINER_MODE_TRUE ac_config_headers="$ac_config_headers config.h" # Checks for programs. ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 echo "${ECHO_T}$ac_ct_CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi CC=$ac_ct_CC else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="cc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 echo "${ECHO_T}$ac_ct_CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi CC=$ac_ct_CC else CC="$ac_cv_prog_CC" fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 echo "${ECHO_T}$ac_ct_CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -n "$ac_ct_CC" && break done CC=$ac_ct_CC fi fi test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH See \`config.log' for more details." >&5 echo "$as_me: error: no acceptable C compiler found in \$PATH See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } # Provide some information about the compiler. echo "$as_me:$LINENO:" \ "checking for C compiler version" >&5 ac_compiler=`set X $ac_compile; echo $2` { (eval echo "$as_me:$LINENO: \"$ac_compiler --version &5\"") >&5 (eval $ac_compiler --version &5) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (eval echo "$as_me:$LINENO: \"$ac_compiler -v &5\"") >&5 (eval $ac_compiler -v &5) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (eval echo "$as_me:$LINENO: \"$ac_compiler -V &5\"") >&5 (eval $ac_compiler -V &5) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. echo "$as_me:$LINENO: checking for C compiler default output file name" >&5 echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6 ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5 (eval $ac_link_default) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then # Find the output, starting from the most likely. This scheme is # not robust to junk in `.', hence go to wildcards (a.*) only as a last # resort. # Be careful to initialize this variable, since it used to be cached. # Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile. ac_cv_exeext= # b.out is created by i960 compilers. for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; conftest.$ac_ext ) # This is the source file. ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` # FIXME: I believe we export ac_cv_exeext for Libtool, # but it would be cool to find out if it's true. Does anybody # maintain Libtool? --akim. export ac_cv_exeext break;; * ) break;; esac done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { echo "$as_me:$LINENO: error: C compiler cannot create executables See \`config.log' for more details." >&5 echo "$as_me: error: C compiler cannot create executables See \`config.log' for more details." >&2;} { (exit 77); exit 77; }; } fi ac_exeext=$ac_cv_exeext echo "$as_me:$LINENO: result: $ac_file" >&5 echo "${ECHO_T}$ac_file" >&6 # Check the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. echo "$as_me:$LINENO: checking whether the C compiler works" >&5 echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6 # FIXME: These cross compiler hacks should be removed for Autoconf 3.0 # If not cross compiling, check that we can run a simple program. if test "$cross_compiling" != yes; then if { ac_try='./$ac_file' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { echo "$as_me:$LINENO: error: cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details." >&5 echo "$as_me: error: cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi fi fi echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 rm -f a.out a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save # Check the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6 echo "$as_me:$LINENO: result: $cross_compiling" >&5 echo "${ECHO_T}$cross_compiling" >&6 echo "$as_me:$LINENO: checking for suffix of executables" >&5 echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6 if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` export ac_cv_exeext break;; * ) break;; esac done else { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute suffix of executables: cannot compile and link See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi rm -f conftest$ac_cv_exeext echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 echo "${ECHO_T}$ac_cv_exeext" >&6 rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT echo "$as_me:$LINENO: checking for suffix of object files" >&5 echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6 if test "${ac_cv_objext+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute suffix of object files: cannot compile See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 echo "${ECHO_T}$ac_cv_objext" >&6 OBJEXT=$ac_cv_objext ac_objext=$OBJEXT echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6 if test "${ac_cv_c_compiler_gnu+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_compiler_gnu=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_compiler_gnu=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6 GCC=`test $ac_compiler_gnu = yes && echo yes` ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS CFLAGS="-g" echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6 if test "${ac_cv_prog_cc_g+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_prog_cc_g=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_prog_cc_g=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 echo "${ECHO_T}$ac_cv_prog_cc_g" >&6 if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5 echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6 if test "${ac_cv_prog_cc_stdc+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_prog_cc_stdc=no ac_save_CC=$CC cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #include #include /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std1 is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std1. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF # Don't try gcc -ansi; that turns off useful extensions and # breaks some systems' header files. # AIX -qlanglvl=ansi # Ultrix and OSF/1 -std1 # HP-UX 10.20 and later -Ae # HP-UX older versions -Aa -D_HPUX_SOURCE # SVR4 -Xc -D__EXTENSIONS__ for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_prog_cc_stdc=$ac_arg break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext done rm -f conftest.$ac_ext conftest.$ac_objext CC=$ac_save_CC fi case "x$ac_cv_prog_cc_stdc" in x|xno) echo "$as_me:$LINENO: result: none needed" >&5 echo "${ECHO_T}none needed" >&6 ;; *) echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5 echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6 CC="$CC $ac_cv_prog_cc_stdc" ;; esac # Some people use a C++ compiler to compile C. Since we use `exit', # in C++ we need to declare it. In case someone uses the same compiler # for both compiling C and C++ we need to have the C++ compiler decide # the declaration of exit, since it's the most demanding environment. cat >conftest.$ac_ext <<_ACEOF #ifndef __cplusplus choke me #endif _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then for ac_declaration in \ '' \ 'extern "C" void std::exit (int) throw (); using std::exit;' \ 'extern "C" void std::exit (int); using std::exit;' \ 'extern "C" void exit (int) throw ();' \ 'extern "C" void exit (int);' \ 'void exit (int);' do cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_declaration #include int main () { exit (42); ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 continue fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_declaration int main () { exit (42); ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext done rm -f conftest* if test -n "$ac_declaration"; then echo '#ifdef __cplusplus' >>confdefs.h echo $ac_declaration >>confdefs.h echo '#endif' >>confdefs.h fi else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu DEPDIR="${am__leading_dot}deps" ac_config_commands="$ac_config_commands depfiles" am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo done .PHONY: am__doit END # If we don't find an include directive, just comment out the code. echo "$as_me:$LINENO: checking for style of include used by $am_make" >&5 echo $ECHO_N "checking for style of include used by $am_make... $ECHO_C" >&6 am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # We grep out `Entering directory' and `Leaving directory' # messages which can occur if `w' ends up in MAKEFLAGS. # In particular we don't look at `^make:' because GNU make might # be invoked under some other name (usually "gmake"), in which # case it prints its new name instead of `make'. if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then am__include=include am__quote= _am_result=GNU fi # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then am__include=.include am__quote="\"" _am_result=BSD fi fi echo "$as_me:$LINENO: result: $_am_result" >&5 echo "${ECHO_T}$_am_result" >&6 rm -f confinc confmf # Check whether --enable-dependency-tracking or --disable-dependency-tracking was given. if test "${enable_dependency_tracking+set}" = set; then enableval="$enable_dependency_tracking" fi; if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' fi if test "x$enable_dependency_tracking" != xno; then AMDEP_TRUE= AMDEP_FALSE='#' else AMDEP_TRUE='#' AMDEP_FALSE= fi depcc="$CC" am_compiler_list= echo "$as_me:$LINENO: checking dependency style of $depcc" >&5 echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6 if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named `D' -- because `-MD' means `put the output # in D'. mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c : > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf case $depmode in nosideeffect) # after this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; none) break ;; esac # We check with `-c' and `-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle `-M -o', and we need to detect this. if depmode=$depmode \ source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # (even with -Werror). So we grep stderr for any message # that says an option was ignored. if grep 'ignoring option' conftest.err >/dev/null 2>&1; then :; else am_cv_CC_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CC_dependencies_compiler_type=none fi fi echo "$as_me:$LINENO: result: $am_cv_CC_dependencies_compiler_type" >&5 echo "${ECHO_T}$am_cv_CC_dependencies_compiler_type" >&6 CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= am__fastdepCC_FALSE='#' else am__fastdepCC_TRUE='#' am__fastdepCC_FALSE= fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_RANLIB+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then echo "$as_me:$LINENO: result: $RANLIB" >&5 echo "${ECHO_T}$RANLIB" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done test -z "$ac_cv_prog_ac_ct_RANLIB" && ac_cv_prog_ac_ct_RANLIB=":" fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5 echo "${ECHO_T}$ac_ct_RANLIB" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi RANLIB=$ac_ct_RANLIB else RANLIB="$ac_cv_prog_RANLIB" fi if test "$GCC" = "yes"; then # I would like to use `-W' too, but, unfortunately, it generates a # few warnings which I cannot stand. I find it cleaner to write # `FIRST_XXX <= xxx && xxx <= LAST_XXX' even if `xxx' is unsigned # and `FIRST_XXX' is zero. It also complains about missing # initializers of private fields of GTK+ structures, which I don't # want to touch. # # `-Wbad-function-cast' is generally good, but yells at things like # `(int) floor(...)', which is intolerable. QUARRY_WARNINGS='-Wall -Waggregate-return -Wcast-align -Wcast-qual -Wmissing-declarations -Wmissing-prototypes -Wnested-externs -Wpointer-arith -Wredundant-decls -Wshadow -Wstrict-prototypes -Wunused-parameter -Wwrite-strings' # `-Wstrict-prototypes' and `-Wshadow' launch alarms on GTK+ # headers, so they are excluded. `-Wwrite-strings' is excluded, # because certain GTK+ structures lack `const' attribute for `gchar # *' fields. # # `-Wcast-qual' is removed, because certain GTK+/GLib structures # have `gchar *' fields, which we sometimes need to assign results # of gettext() and friends. Also, GLib data structures operate with # `gpointer's and `-Wcast-qual' generates warnings on adding # constant strings to them. QUARRY_WARNINGS_GTK='-Wall -Waggregate-return -Wcast-align -Wmissing-declarations -Wmissing-prototypes -Wnested-externs -Wpointer-arith -Wredundant-decls -Wunused-parameter' else QUARRY_WARNINGS='' QUARRY_WARNINGS_GTK='' fi # Checks for header files. ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6 # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if test "${ac_cv_prog_CPP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether non-existent headers # can be detected and how. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then # Broken: success on invalid input. continue else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi echo "$as_me:$LINENO: result: $CPP" >&5 echo "${ECHO_T}$CPP" >&6 ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether non-existent headers # can be detected and how. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then # Broken: success on invalid input. continue else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details." >&5 echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu echo "$as_me:$LINENO: checking for egrep" >&5 echo $ECHO_N "checking for egrep... $ECHO_C" >&6 if test "${ac_cv_prog_egrep+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if echo a | (grep -E '(a|b)') >/dev/null 2>&1 then ac_cv_prog_egrep='grep -E' else ac_cv_prog_egrep='egrep' fi fi echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5 echo "${ECHO_T}$ac_cv_prog_egrep" >&6 EGREP=$ac_cv_prog_egrep echo "$as_me:$LINENO: checking for ANSI C header files" >&5 echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6 if test "${ac_cv_header_stdc+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_header_stdc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_header_stdc=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); exit (0); } _ACEOF rm -f conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then : else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_header_stdc=no fi rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi fi echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 echo "${ECHO_T}$ac_cv_header_stdc" >&6 if test $ac_cv_header_stdc = yes; then cat >>confdefs.h <<\_ACEOF #define STDC_HEADERS 1 _ACEOF fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_Header=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_Header=no" fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in limits.h float.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if eval "test \"\${$as_ac_Header+set}\" = set"; then echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 else # Is the header compilable? echo "$as_me:$LINENO: checking $ac_header usability" >&5 echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6 # Is the header present? echo "$as_me:$LINENO: checking $ac_header presence" >&5 echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6 # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ( cat <<\_ASBOX ## --------------------------------- ## ## Report this to quarry-dev@gna.org ## ## --------------------------------- ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 fi if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done # Checks for typedefs, structures, and compiler characteristics. echo "$as_me:$LINENO: checking for an ANSI C-conforming const" >&5 echo $ECHO_N "checking for an ANSI C-conforming const... $ECHO_C" >&6 if test "${ac_cv_c_const+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { /* FIXME: Include the comments suggested by Paul. */ #ifndef __cplusplus /* Ultrix mips cc rejects this. */ typedef int charset[2]; const charset x; /* SunOS 4.1.1 cc rejects this. */ char const *const *ccp; char **p; /* NEC SVR4.0.2 mips cc rejects this. */ struct point {int x, y;}; static struct point const zero = {0,0}; /* AIX XL C 1.02.0.0 rejects this. It does not let you subtract one const X* pointer from another in an arm of an if-expression whose if-part is not a constant expression */ const char *g = "string"; ccp = &g + (g ? g-g : 0); /* HPUX 7.0 cc rejects these. */ ++ccp; p = (char**) ccp; ccp = (char const *const *) p; { /* SCO 3.2v4 cc rejects this. */ char *t; char const *s = 0 ? (char *) 0 : (char const *) 0; *t++ = 0; } { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ int x[] = {25, 17}; const int *foo = &x[0]; ++foo; } { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ typedef const int *iptr; iptr p = 0; ++p; } { /* AIX XL C 1.02.0.0 rejects this saying "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ struct s { int j; const int *ap[3]; }; struct s *b; b->j = 5; } { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ const int foo = 10; } #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_c_const=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_c_const=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_c_const" >&5 echo "${ECHO_T}$ac_cv_c_const" >&6 if test $ac_cv_c_const = no; then cat >>confdefs.h <<\_ACEOF #define const _ACEOF fi echo "$as_me:$LINENO: checking for inline" >&5 echo $ECHO_N "checking for inline... $ECHO_C" >&6 if test "${ac_cv_c_inline+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_c_inline=no for ac_kw in inline __inline__ __inline; do cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifndef __cplusplus typedef int foo_t; static $ac_kw foo_t static_foo () {return 0; } $ac_kw foo_t foo () {return 0; } #endif _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_c_inline=$ac_kw; break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext done fi echo "$as_me:$LINENO: result: $ac_cv_c_inline" >&5 echo "${ECHO_T}$ac_cv_c_inline" >&6 case $ac_cv_c_inline in inline | yes) ;; *) case $ac_cv_c_inline in no) ac_val=;; *) ac_val=$ac_cv_c_inline;; esac cat >>confdefs.h <<_ACEOF #ifndef __cplusplus #define inline $ac_val #endif _ACEOF ;; esac echo "$as_me:$LINENO: checking for size_t" >&5 echo $ECHO_N "checking for size_t... $ECHO_C" >&6 if test "${ac_cv_type_size_t+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { if ((size_t *) 0) return 0; if (sizeof (size_t)) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_type_size_t=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type_size_t=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_type_size_t" >&5 echo "${ECHO_T}$ac_cv_type_size_t" >&6 if test $ac_cv_type_size_t = yes; then : else cat >>confdefs.h <<_ACEOF #define size_t unsigned _ACEOF fi # Check size of some types. echo "$as_me:$LINENO: checking for int" >&5 echo $ECHO_N "checking for int... $ECHO_C" >&6 if test "${ac_cv_type_int+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { if ((int *) 0) return 0; if (sizeof (int)) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_type_int=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type_int=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_type_int" >&5 echo "${ECHO_T}$ac_cv_type_int" >&6 echo "$as_me:$LINENO: checking size of int" >&5 echo $ECHO_N "checking size of int... $ECHO_C" >&6 if test "${ac_cv_sizeof_int+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "$ac_cv_type_int" = yes; then # The cast to unsigned long works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. if test "$cross_compiling" = yes; then # Depending upon the size, compute the lo and hi bounds. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { static int test_array [1 - 2 * !(((long) (sizeof (int))) >= 0)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_lo=0 ac_mid=0 while :; do cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { static int test_array [1 - 2 * !(((long) (sizeof (int))) <= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_hi=$ac_mid; break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_lo=`expr $ac_mid + 1` if test $ac_lo -le $ac_mid; then ac_lo= ac_hi= break fi ac_mid=`expr 2 '*' $ac_mid + 1` fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { static int test_array [1 - 2 * !(((long) (sizeof (int))) < 0)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_hi=-1 ac_mid=-1 while :; do cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { static int test_array [1 - 2 * !(((long) (sizeof (int))) >= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_lo=$ac_mid; break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_hi=`expr '(' $ac_mid ')' - 1` if test $ac_mid -le $ac_hi; then ac_lo= ac_hi= break fi ac_mid=`expr 2 '*' $ac_mid` fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_lo= ac_hi= fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext # Binary search between lo and hi bounds. while test "x$ac_lo" != "x$ac_hi"; do ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo` cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { static int test_array [1 - 2 * !(((long) (sizeof (int))) <= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_hi=$ac_mid else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_lo=`expr '(' $ac_mid ')' + 1` fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext done case $ac_lo in ?*) ac_cv_sizeof_int=$ac_lo;; '') { { echo "$as_me:$LINENO: error: cannot compute sizeof (int), 77 See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute sizeof (int), 77 See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } ;; esac else if test "$cross_compiling" = yes; then { { echo "$as_me:$LINENO: error: internal error: not reached in cross-compile" >&5 echo "$as_me: error: internal error: not reached in cross-compile" >&2;} { (exit 1); exit 1; }; } else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include long longval () { return (long) (sizeof (int)); } unsigned long ulongval () { return (long) (sizeof (int)); } #include #include int main () { FILE *f = fopen ("conftest.val", "w"); if (! f) exit (1); if (((long) (sizeof (int))) < 0) { long i = longval (); if (i != ((long) (sizeof (int)))) exit (1); fprintf (f, "%ld\n", i); } else { unsigned long i = ulongval (); if (i != ((long) (sizeof (int)))) exit (1); fprintf (f, "%lu\n", i); } exit (ferror (f) || fclose (f) != 0); ; return 0; } _ACEOF rm -f conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_sizeof_int=`cat conftest.val` else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) { { echo "$as_me:$LINENO: error: cannot compute sizeof (int), 77 See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute sizeof (int), 77 See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi rm -f conftest.val else ac_cv_sizeof_int=0 fi fi echo "$as_me:$LINENO: result: $ac_cv_sizeof_int" >&5 echo "${ECHO_T}$ac_cv_sizeof_int" >&6 cat >>confdefs.h <<_ACEOF #define SIZEOF_INT $ac_cv_sizeof_int _ACEOF echo "$as_me:$LINENO: checking for double" >&5 echo $ECHO_N "checking for double... $ECHO_C" >&6 if test "${ac_cv_type_double+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { if ((double *) 0) return 0; if (sizeof (double)) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_type_double=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type_double=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_type_double" >&5 echo "${ECHO_T}$ac_cv_type_double" >&6 echo "$as_me:$LINENO: checking size of double" >&5 echo $ECHO_N "checking size of double... $ECHO_C" >&6 if test "${ac_cv_sizeof_double+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "$ac_cv_type_double" = yes; then # The cast to unsigned long works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. if test "$cross_compiling" = yes; then # Depending upon the size, compute the lo and hi bounds. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { static int test_array [1 - 2 * !(((long) (sizeof (double))) >= 0)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_lo=0 ac_mid=0 while :; do cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { static int test_array [1 - 2 * !(((long) (sizeof (double))) <= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_hi=$ac_mid; break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_lo=`expr $ac_mid + 1` if test $ac_lo -le $ac_mid; then ac_lo= ac_hi= break fi ac_mid=`expr 2 '*' $ac_mid + 1` fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { static int test_array [1 - 2 * !(((long) (sizeof (double))) < 0)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_hi=-1 ac_mid=-1 while :; do cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { static int test_array [1 - 2 * !(((long) (sizeof (double))) >= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_lo=$ac_mid; break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_hi=`expr '(' $ac_mid ')' - 1` if test $ac_mid -le $ac_hi; then ac_lo= ac_hi= break fi ac_mid=`expr 2 '*' $ac_mid` fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_lo= ac_hi= fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext # Binary search between lo and hi bounds. while test "x$ac_lo" != "x$ac_hi"; do ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo` cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { static int test_array [1 - 2 * !(((long) (sizeof (double))) <= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_hi=$ac_mid else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_lo=`expr '(' $ac_mid ')' + 1` fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext done case $ac_lo in ?*) ac_cv_sizeof_double=$ac_lo;; '') { { echo "$as_me:$LINENO: error: cannot compute sizeof (double), 77 See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute sizeof (double), 77 See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } ;; esac else if test "$cross_compiling" = yes; then { { echo "$as_me:$LINENO: error: internal error: not reached in cross-compile" >&5 echo "$as_me: error: internal error: not reached in cross-compile" >&2;} { (exit 1); exit 1; }; } else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include long longval () { return (long) (sizeof (double)); } unsigned long ulongval () { return (long) (sizeof (double)); } #include #include int main () { FILE *f = fopen ("conftest.val", "w"); if (! f) exit (1); if (((long) (sizeof (double))) < 0) { long i = longval (); if (i != ((long) (sizeof (double)))) exit (1); fprintf (f, "%ld\n", i); } else { unsigned long i = ulongval (); if (i != ((long) (sizeof (double)))) exit (1); fprintf (f, "%lu\n", i); } exit (ferror (f) || fclose (f) != 0); ; return 0; } _ACEOF rm -f conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_sizeof_double=`cat conftest.val` else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) { { echo "$as_me:$LINENO: error: cannot compute sizeof (double), 77 See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute sizeof (double), 77 See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi rm -f conftest.val else ac_cv_sizeof_double=0 fi fi echo "$as_me:$LINENO: result: $ac_cv_sizeof_double" >&5 echo "${ECHO_T}$ac_cv_sizeof_double" >&6 cat >>confdefs.h <<_ACEOF #define SIZEOF_DOUBLE $ac_cv_sizeof_double _ACEOF echo "$as_me:$LINENO: checking for void *" >&5 echo $ECHO_N "checking for void *... $ECHO_C" >&6 if test "${ac_cv_type_void_p+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { if ((void * *) 0) return 0; if (sizeof (void *)) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_type_void_p=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type_void_p=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_type_void_p" >&5 echo "${ECHO_T}$ac_cv_type_void_p" >&6 echo "$as_me:$LINENO: checking size of void *" >&5 echo $ECHO_N "checking size of void *... $ECHO_C" >&6 if test "${ac_cv_sizeof_void_p+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "$ac_cv_type_void_p" = yes; then # The cast to unsigned long works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. if test "$cross_compiling" = yes; then # Depending upon the size, compute the lo and hi bounds. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { static int test_array [1 - 2 * !(((long) (sizeof (void *))) >= 0)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_lo=0 ac_mid=0 while :; do cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { static int test_array [1 - 2 * !(((long) (sizeof (void *))) <= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_hi=$ac_mid; break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_lo=`expr $ac_mid + 1` if test $ac_lo -le $ac_mid; then ac_lo= ac_hi= break fi ac_mid=`expr 2 '*' $ac_mid + 1` fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { static int test_array [1 - 2 * !(((long) (sizeof (void *))) < 0)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_hi=-1 ac_mid=-1 while :; do cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { static int test_array [1 - 2 * !(((long) (sizeof (void *))) >= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_lo=$ac_mid; break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_hi=`expr '(' $ac_mid ')' - 1` if test $ac_mid -le $ac_hi; then ac_lo= ac_hi= break fi ac_mid=`expr 2 '*' $ac_mid` fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_lo= ac_hi= fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext # Binary search between lo and hi bounds. while test "x$ac_lo" != "x$ac_hi"; do ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo` cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { static int test_array [1 - 2 * !(((long) (sizeof (void *))) <= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_hi=$ac_mid else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_lo=`expr '(' $ac_mid ')' + 1` fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext done case $ac_lo in ?*) ac_cv_sizeof_void_p=$ac_lo;; '') { { echo "$as_me:$LINENO: error: cannot compute sizeof (void *), 77 See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute sizeof (void *), 77 See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } ;; esac else if test "$cross_compiling" = yes; then { { echo "$as_me:$LINENO: error: internal error: not reached in cross-compile" >&5 echo "$as_me: error: internal error: not reached in cross-compile" >&2;} { (exit 1); exit 1; }; } else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include long longval () { return (long) (sizeof (void *)); } unsigned long ulongval () { return (long) (sizeof (void *)); } #include #include int main () { FILE *f = fopen ("conftest.val", "w"); if (! f) exit (1); if (((long) (sizeof (void *))) < 0) { long i = longval (); if (i != ((long) (sizeof (void *)))) exit (1); fprintf (f, "%ld\n", i); } else { unsigned long i = ulongval (); if (i != ((long) (sizeof (void *)))) exit (1); fprintf (f, "%lu\n", i); } exit (ferror (f) || fclose (f) != 0); ; return 0; } _ACEOF rm -f conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_sizeof_void_p=`cat conftest.val` else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) { { echo "$as_me:$LINENO: error: cannot compute sizeof (void *), 77 See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute sizeof (void *), 77 See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi rm -f conftest.val else ac_cv_sizeof_void_p=0 fi fi echo "$as_me:$LINENO: result: $ac_cv_sizeof_void_p" >&5 echo "${ECHO_T}$ac_cv_sizeof_void_p" >&6 cat >>confdefs.h <<_ACEOF #define SIZEOF_VOID_P $ac_cv_sizeof_void_p _ACEOF # Checks for library functions. for ac_func in vprintf do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_func" >&5 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 if eval "test \"\${$as_ac_var+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case declares $ac_func. For example, HP-UX 11i declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $ac_func /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char $ac_func (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_$ac_func) || defined (__stub___$ac_func) choke me #else char (*f) () = $ac_func; #endif #ifdef __cplusplus } #endif int main () { return f != $ac_func; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_var=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF echo "$as_me:$LINENO: checking for _doprnt" >&5 echo $ECHO_N "checking for _doprnt... $ECHO_C" >&6 if test "${ac_cv_func__doprnt+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define _doprnt to an innocuous variant, in case declares _doprnt. For example, HP-UX 11i declares gettimeofday. */ #define _doprnt innocuous__doprnt /* System header to define __stub macros and hopefully few prototypes, which can conflict with char _doprnt (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef _doprnt /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char _doprnt (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub__doprnt) || defined (__stub____doprnt) choke me #else char (*f) () = _doprnt; #endif #ifdef __cplusplus } #endif int main () { return f != _doprnt; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_func__doprnt=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func__doprnt=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_func__doprnt" >&5 echo "${ECHO_T}$ac_cv_func__doprnt" >&6 if test $ac_cv_func__doprnt = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_DOPRNT 1 _ACEOF fi fi done echo "$as_me:$LINENO: checking for working memcmp" >&5 echo $ECHO_N "checking for working memcmp... $ECHO_C" >&6 if test "${ac_cv_func_memcmp_working+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "$cross_compiling" = yes; then ac_cv_func_memcmp_working=no else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { /* Some versions of memcmp are not 8-bit clean. */ char c0 = 0x40, c1 = 0x80, c2 = 0x81; if (memcmp(&c0, &c2, 1) >= 0 || memcmp(&c1, &c2, 1) >= 0) exit (1); /* The Next x86 OpenStep bug shows up only when comparing 16 bytes or more and with at least one buffer not starting on a 4-byte boundary. William Lewis provided this test program. */ { char foo[21]; char bar[21]; int i; for (i = 0; i < 4; i++) { char *a = foo + i; char *b = bar + i; strcpy (a, "--------01111111"); strcpy (b, "--------10000000"); if (memcmp (a, b, 16) >= 0) exit (1); } exit (0); } ; return 0; } _ACEOF rm -f conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_func_memcmp_working=yes else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_func_memcmp_working=no fi rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi echo "$as_me:$LINENO: result: $ac_cv_func_memcmp_working" >&5 echo "${ECHO_T}$ac_cv_func_memcmp_working" >&6 test $ac_cv_func_memcmp_working = no && case $LIBOBJS in "memcmp.$ac_objext" | \ *" memcmp.$ac_objext" | \ "memcmp.$ac_objext "* | \ *" memcmp.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS memcmp.$ac_objext" ;; esac for ac_func in memrchr do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_func" >&5 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 if eval "test \"\${$as_ac_var+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case declares $ac_func. For example, HP-UX 11i declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $ac_func /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char $ac_func (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_$ac_func) || defined (__stub___$ac_func) choke me #else char (*f) () = $ac_func; #endif #ifdef __cplusplus } #endif int main () { return f != $ac_func; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_var=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done # Require math library. echo "$as_me:$LINENO: checking for library containing floor" >&5 echo $ECHO_N "checking for library containing floor... $ECHO_C" >&6 if test "${ac_cv_search_floor+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_func_search_save_LIBS=$LIBS ac_cv_search_floor=no cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char floor (); int main () { floor (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_search_floor="none required" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test "$ac_cv_search_floor" = no; then for ac_lib in m; do LIBS="-l$ac_lib $ac_func_search_save_LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char floor (); int main () { floor (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_search_floor="-l$ac_lib" break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext done fi LIBS=$ac_func_search_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_search_floor" >&5 echo "${ECHO_T}$ac_cv_search_floor" >&6 if test "$ac_cv_search_floor" != no; then test "$ac_cv_search_floor" = "none required" || LIBS="$ac_cv_search_floor $LIBS" fi # Find iconv(). It is usually sitting in GNU C library, but may # sometimes be in a separate `libiconv' library. # # FIXME: Is this needed anymore given that we use gettext? Check what # AM_ICONV() is good for. echo "$as_me:$LINENO: checking for library containing iconv" >&5 echo $ECHO_N "checking for library containing iconv... $ECHO_C" >&6 if test "${ac_cv_search_iconv+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_func_search_save_LIBS=$LIBS ac_cv_search_iconv=no cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char iconv (); int main () { iconv (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_search_iconv="none required" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test "$ac_cv_search_iconv" = no; then for ac_lib in iconv; do LIBS="-l$ac_lib $ac_func_search_save_LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char iconv (); int main () { iconv (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_search_iconv="-l$ac_lib" break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext done fi LIBS=$ac_func_search_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_search_iconv" >&5 echo "${ECHO_T}$ac_cv_search_iconv" >&6 if test "$ac_cv_search_iconv" != no; then test "$ac_cv_search_iconv" = "none required" || LIBS="$ac_cv_search_iconv $LIBS" fi # Turn on GNU gettext support. MKINSTALLDIRS= if test -n "$ac_aux_dir"; then case "$ac_aux_dir" in /*) MKINSTALLDIRS="$ac_aux_dir/mkinstalldirs" ;; *) MKINSTALLDIRS="\$(top_builddir)/$ac_aux_dir/mkinstalldirs" ;; esac fi if test -z "$MKINSTALLDIRS"; then MKINSTALLDIRS="\$(top_srcdir)/mkinstalldirs" fi echo "$as_me:$LINENO: checking whether NLS is requested" >&5 echo $ECHO_N "checking whether NLS is requested... $ECHO_C" >&6 # Check whether --enable-nls or --disable-nls was given. if test "${enable_nls+set}" = set; then enableval="$enable_nls" USE_NLS=$enableval else USE_NLS=yes fi; echo "$as_me:$LINENO: result: $USE_NLS" >&5 echo "${ECHO_T}$USE_NLS" >&6 # Prepare PATH_SEPARATOR. # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi # Find out how to test for executable files. Don't use a zero-byte file, # as systems may use methods other than mode bits to determine executability. cat >conf$$.file <<_ASEOF #! /bin/sh exit 0 _ASEOF chmod +x conf$$.file if test -x conf$$.file >/dev/null 2>&1; then ac_executable_p="test -x" else ac_executable_p="test -f" fi rm -f conf$$.file # Extract the first word of "msgfmt", so it can be a program name with args. set dummy msgfmt; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_path_MSGFMT+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else case "$MSGFMT" in [\\/]* | ?:[\\/]*) ac_cv_path_MSGFMT="$MSGFMT" # Let the user override the test with a path. ;; *) ac_save_IFS="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$ac_save_IFS" test -z "$ac_dir" && ac_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $ac_executable_p "$ac_dir/$ac_word$ac_exec_ext"; then echo "$as_me: trying $ac_dir/$ac_word..." >&5 if $ac_dir/$ac_word --statistics /dev/null >&5 2>&1 && (if $ac_dir/$ac_word --statistics /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi); then ac_cv_path_MSGFMT="$ac_dir/$ac_word$ac_exec_ext" break 2 fi fi done done IFS="$ac_save_IFS" test -z "$ac_cv_path_MSGFMT" && ac_cv_path_MSGFMT=":" ;; esac fi MSGFMT="$ac_cv_path_MSGFMT" if test "$MSGFMT" != ":"; then echo "$as_me:$LINENO: result: $MSGFMT" >&5 echo "${ECHO_T}$MSGFMT" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi # Extract the first word of "gmsgfmt", so it can be a program name with args. set dummy gmsgfmt; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_path_GMSGFMT+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else case $GMSGFMT in [\\/]* | ?:[\\/]*) ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_GMSGFMT="$as_dir/$ac_word$ac_exec_ext" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done test -z "$ac_cv_path_GMSGFMT" && ac_cv_path_GMSGFMT="$MSGFMT" ;; esac fi GMSGFMT=$ac_cv_path_GMSGFMT if test -n "$GMSGFMT"; then echo "$as_me:$LINENO: result: $GMSGFMT" >&5 echo "${ECHO_T}$GMSGFMT" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi # Prepare PATH_SEPARATOR. # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi # Find out how to test for executable files. Don't use a zero-byte file, # as systems may use methods other than mode bits to determine executability. cat >conf$$.file <<_ASEOF #! /bin/sh exit 0 _ASEOF chmod +x conf$$.file if test -x conf$$.file >/dev/null 2>&1; then ac_executable_p="test -x" else ac_executable_p="test -f" fi rm -f conf$$.file # Extract the first word of "xgettext", so it can be a program name with args. set dummy xgettext; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_path_XGETTEXT+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else case "$XGETTEXT" in [\\/]* | ?:[\\/]*) ac_cv_path_XGETTEXT="$XGETTEXT" # Let the user override the test with a path. ;; *) ac_save_IFS="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$ac_save_IFS" test -z "$ac_dir" && ac_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $ac_executable_p "$ac_dir/$ac_word$ac_exec_ext"; then echo "$as_me: trying $ac_dir/$ac_word..." >&5 if $ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null >&5 2>&1 && (if $ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi); then ac_cv_path_XGETTEXT="$ac_dir/$ac_word$ac_exec_ext" break 2 fi fi done done IFS="$ac_save_IFS" test -z "$ac_cv_path_XGETTEXT" && ac_cv_path_XGETTEXT=":" ;; esac fi XGETTEXT="$ac_cv_path_XGETTEXT" if test "$XGETTEXT" != ":"; then echo "$as_me:$LINENO: result: $XGETTEXT" >&5 echo "${ECHO_T}$XGETTEXT" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi rm -f messages.po # Prepare PATH_SEPARATOR. # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi # Find out how to test for executable files. Don't use a zero-byte file, # as systems may use methods other than mode bits to determine executability. cat >conf$$.file <<_ASEOF #! /bin/sh exit 0 _ASEOF chmod +x conf$$.file if test -x conf$$.file >/dev/null 2>&1; then ac_executable_p="test -x" else ac_executable_p="test -f" fi rm -f conf$$.file # Extract the first word of "msgmerge", so it can be a program name with args. set dummy msgmerge; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_path_MSGMERGE+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else case "$MSGMERGE" in [\\/]* | ?:[\\/]*) ac_cv_path_MSGMERGE="$MSGMERGE" # Let the user override the test with a path. ;; *) ac_save_IFS="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$ac_save_IFS" test -z "$ac_dir" && ac_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $ac_executable_p "$ac_dir/$ac_word$ac_exec_ext"; then echo "$as_me: trying $ac_dir/$ac_word..." >&5 if $ac_dir/$ac_word --update -q /dev/null /dev/null >&5 2>&1; then ac_cv_path_MSGMERGE="$ac_dir/$ac_word$ac_exec_ext" break 2 fi fi done done IFS="$ac_save_IFS" test -z "$ac_cv_path_MSGMERGE" && ac_cv_path_MSGMERGE=":" ;; esac fi MSGMERGE="$ac_cv_path_MSGMERGE" if test "$MSGMERGE" != ":"; then echo "$as_me:$LINENO: result: $MSGMERGE" >&5 echo "${ECHO_T}$MSGMERGE" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi if test "$GMSGFMT" != ":"; then if $GMSGFMT --statistics /dev/null >/dev/null 2>&1 && (if $GMSGFMT --statistics /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi); then : ; else GMSGFMT=`echo "$GMSGFMT" | sed -e 's,^.*/,,'` echo "$as_me:$LINENO: result: found $GMSGFMT program is not GNU msgfmt; ignore it" >&5 echo "${ECHO_T}found $GMSGFMT program is not GNU msgfmt; ignore it" >&6 GMSGFMT=":" fi fi if test "$XGETTEXT" != ":"; then if $XGETTEXT --omit-header --copyright-holder= --msgid-bugs-address= /dev/null >/dev/null 2>&1 && (if $XGETTEXT --omit-header --copyright-holder= --msgid-bugs-address= /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi); then : ; else echo "$as_me:$LINENO: result: found xgettext program is not GNU xgettext; ignore it" >&5 echo "${ECHO_T}found xgettext program is not GNU xgettext; ignore it" >&6 XGETTEXT=":" fi rm -f messages.po fi ac_config_commands="$ac_config_commands default-1" if test "X$prefix" = "XNONE"; then acl_final_prefix="$ac_default_prefix" else acl_final_prefix="$prefix" fi if test "X$exec_prefix" = "XNONE"; then acl_final_exec_prefix='${prefix}' else acl_final_exec_prefix="$exec_prefix" fi acl_save_prefix="$prefix" prefix="$acl_final_prefix" eval acl_final_exec_prefix=\"$acl_final_exec_prefix\" prefix="$acl_save_prefix" # Make sure we can run config.sub. $ac_config_sub sun4 >/dev/null 2>&1 || { { echo "$as_me:$LINENO: error: cannot run $ac_config_sub" >&5 echo "$as_me: error: cannot run $ac_config_sub" >&2;} { (exit 1); exit 1; }; } echo "$as_me:$LINENO: checking build system type" >&5 echo $ECHO_N "checking build system type... $ECHO_C" >&6 if test "${ac_cv_build+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_build_alias=$build_alias test -z "$ac_cv_build_alias" && ac_cv_build_alias=`$ac_config_guess` test -z "$ac_cv_build_alias" && { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5 echo "$as_me: error: cannot guess build type; you must specify one" >&2;} { (exit 1); exit 1; }; } ac_cv_build=`$ac_config_sub $ac_cv_build_alias` || { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_build_alias failed" >&5 echo "$as_me: error: $ac_config_sub $ac_cv_build_alias failed" >&2;} { (exit 1); exit 1; }; } fi echo "$as_me:$LINENO: result: $ac_cv_build" >&5 echo "${ECHO_T}$ac_cv_build" >&6 build=$ac_cv_build build_cpu=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` build_vendor=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` build_os=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` echo "$as_me:$LINENO: checking host system type" >&5 echo $ECHO_N "checking host system type... $ECHO_C" >&6 if test "${ac_cv_host+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_host_alias=$host_alias test -z "$ac_cv_host_alias" && ac_cv_host_alias=$ac_cv_build_alias ac_cv_host=`$ac_config_sub $ac_cv_host_alias` || { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_host_alias failed" >&5 echo "$as_me: error: $ac_config_sub $ac_cv_host_alias failed" >&2;} { (exit 1); exit 1; }; } fi echo "$as_me:$LINENO: result: $ac_cv_host" >&5 echo "${ECHO_T}$ac_cv_host" >&6 host=$ac_cv_host host_cpu=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` host_vendor=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` host_os=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` # Check whether --with-gnu-ld or --without-gnu-ld was given. if test "${with_gnu_ld+set}" = set; then withval="$with_gnu_ld" test "$withval" = no || with_gnu_ld=yes else with_gnu_ld=no fi; # Prepare PATH_SEPARATOR. # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. echo "$as_me:$LINENO: checking for ld used by GCC" >&5 echo $ECHO_N "checking for ld used by GCC... $ECHO_C" >&6 case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [\\/]* | [A-Za-z]:[\\/]*) re_direlt='/[^/][^/]*/\.\./' # Canonicalize the path of ld ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'` while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then echo "$as_me:$LINENO: checking for GNU ld" >&5 echo $ECHO_N "checking for GNU ld... $ECHO_C" >&6 else echo "$as_me:$LINENO: checking for non-GNU ld" >&5 echo $ECHO_N "checking for non-GNU ld... $ECHO_C" >&6 fi if test "${acl_cv_path_LD+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -z "$LD"; then IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}" for ac_dir in $PATH; do test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then acl_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some GNU ld's only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$acl_cv_path_LD" -v 2>&1 < /dev/null` in *GNU* | *'with BFD'*) test "$with_gnu_ld" != no && break ;; *) test "$with_gnu_ld" != yes && break ;; esac fi done IFS="$ac_save_ifs" else acl_cv_path_LD="$LD" # Let the user override the test with a path. fi fi LD="$acl_cv_path_LD" if test -n "$LD"; then echo "$as_me:$LINENO: result: $LD" >&5 echo "${ECHO_T}$LD" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -z "$LD" && { { echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5 echo "$as_me: error: no acceptable ld found in \$PATH" >&2;} { (exit 1); exit 1; }; } echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5 echo $ECHO_N "checking if the linker ($LD) is GNU ld... $ECHO_C" >&6 if test "${acl_cv_prog_gnu_ld+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # I'd rather use --version here, but apparently some GNU ld's only accept -v. case `$LD -v 2>&1 &5 echo "${ECHO_T}$acl_cv_prog_gnu_ld" >&6 with_gnu_ld=$acl_cv_prog_gnu_ld echo "$as_me:$LINENO: checking for shared library run path origin" >&5 echo $ECHO_N "checking for shared library run path origin... $ECHO_C" >&6 if test "${acl_cv_rpath+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \ ${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh . ./conftest.sh rm -f ./conftest.sh acl_cv_rpath=done fi echo "$as_me:$LINENO: result: $acl_cv_rpath" >&5 echo "${ECHO_T}$acl_cv_rpath" >&6 wl="$acl_cv_wl" libext="$acl_cv_libext" shlibext="$acl_cv_shlibext" hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec" hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator" hardcode_direct="$acl_cv_hardcode_direct" hardcode_minus_L="$acl_cv_hardcode_minus_L" # Check whether --enable-rpath or --disable-rpath was given. if test "${enable_rpath+set}" = set; then enableval="$enable_rpath" : else enable_rpath=yes fi; use_additional=yes acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" # Check whether --with-libiconv-prefix or --without-libiconv-prefix was given. if test "${with_libiconv_prefix+set}" = set; then withval="$with_libiconv_prefix" if test "X$withval" = "Xno"; then use_additional=no else if test "X$withval" = "X"; then acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" else additional_includedir="$withval/include" additional_libdir="$withval/lib" fi fi fi; LIBICONV= LTLIBICONV= INCICONV= rpathdirs= ltrpathdirs= names_already_handled= names_next_round='iconv ' while test -n "$names_next_round"; do names_this_round="$names_next_round" names_next_round= for name in $names_this_round; do already_handled= for n in $names_already_handled; do if test "$n" = "$name"; then already_handled=yes break fi done if test -z "$already_handled"; then names_already_handled="$names_already_handled $name" uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'` eval value=\"\$HAVE_LIB$uppername\" if test -n "$value"; then if test "$value" = yes; then eval value=\"\$LIB$uppername\" test -z "$value" || LIBICONV="${LIBICONV}${LIBICONV:+ }$value" eval value=\"\$LTLIB$uppername\" test -z "$value" || LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }$value" else : fi else found_dir= found_la= found_so= found_a= if test $use_additional = yes; then if test -n "$shlibext" && test -f "$additional_libdir/lib$name.$shlibext"; then found_dir="$additional_libdir" found_so="$additional_libdir/lib$name.$shlibext" if test -f "$additional_libdir/lib$name.la"; then found_la="$additional_libdir/lib$name.la" fi else if test -f "$additional_libdir/lib$name.$libext"; then found_dir="$additional_libdir" found_a="$additional_libdir/lib$name.$libext" if test -f "$additional_libdir/lib$name.la"; then found_la="$additional_libdir/lib$name.la" fi fi fi fi if test "X$found_dir" = "X"; then for x in $LDFLAGS $LTLIBICONV; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" case "$x" in -L*) dir=`echo "X$x" | sed -e 's/^X-L//'` if test -n "$shlibext" && test -f "$dir/lib$name.$shlibext"; then found_dir="$dir" found_so="$dir/lib$name.$shlibext" if test -f "$dir/lib$name.la"; then found_la="$dir/lib$name.la" fi else if test -f "$dir/lib$name.$libext"; then found_dir="$dir" found_a="$dir/lib$name.$libext" if test -f "$dir/lib$name.la"; then found_la="$dir/lib$name.la" fi fi fi ;; esac if test "X$found_dir" != "X"; then break fi done fi if test "X$found_dir" != "X"; then LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-L$found_dir -l$name" if test "X$found_so" != "X"; then if test "$enable_rpath" = no || test "X$found_dir" = "X/usr/lib"; then LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so" else haveit= for x in $ltrpathdirs; do if test "X$x" = "X$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then ltrpathdirs="$ltrpathdirs $found_dir" fi if test "$hardcode_direct" = yes; then LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so" else if test -n "$hardcode_libdir_flag_spec" && test "$hardcode_minus_L" = no; then LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so" haveit= for x in $rpathdirs; do if test "X$x" = "X$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then rpathdirs="$rpathdirs $found_dir" fi else haveit= for x in $LDFLAGS $LIBICONV; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X-L$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then LIBICONV="${LIBICONV}${LIBICONV:+ }-L$found_dir" fi if test "$hardcode_minus_L" != no; then LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so" else LIBICONV="${LIBICONV}${LIBICONV:+ }-l$name" fi fi fi fi else if test "X$found_a" != "X"; then LIBICONV="${LIBICONV}${LIBICONV:+ }$found_a" else LIBICONV="${LIBICONV}${LIBICONV:+ }-L$found_dir -l$name" fi fi additional_includedir= case "$found_dir" in */lib | */lib/) basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e 's,/lib/*$,,'` additional_includedir="$basedir/include" ;; esac if test "X$additional_includedir" != "X"; then if test "X$additional_includedir" != "X/usr/include"; then haveit= if test "X$additional_includedir" = "X/usr/local/include"; then if test -n "$GCC"; then case $host_os in linux* | gnu* | k*bsd*-gnu) haveit=yes;; esac fi fi if test -z "$haveit"; then for x in $CPPFLAGS $INCICONV; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X-I$additional_includedir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_includedir"; then INCICONV="${INCICONV}${INCICONV:+ }-I$additional_includedir" fi fi fi fi fi if test -n "$found_la"; then save_libdir="$libdir" case "$found_la" in */* | *\\*) . "$found_la" ;; *) . "./$found_la" ;; esac libdir="$save_libdir" for dep in $dependency_libs; do case "$dep" in -L*) additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` if test "X$additional_libdir" != "X/usr/lib"; then haveit= if test "X$additional_libdir" = "X/usr/local/lib"; then if test -n "$GCC"; then case $host_os in linux* | gnu* | k*bsd*-gnu) haveit=yes;; esac fi fi if test -z "$haveit"; then haveit= for x in $LDFLAGS $LIBICONV; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X-L$additional_libdir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_libdir"; then LIBICONV="${LIBICONV}${LIBICONV:+ }-L$additional_libdir" fi fi haveit= for x in $LDFLAGS $LTLIBICONV; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X-L$additional_libdir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_libdir"; then LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-L$additional_libdir" fi fi fi fi ;; -R*) dir=`echo "X$dep" | sed -e 's/^X-R//'` if test "$enable_rpath" != no; then haveit= for x in $rpathdirs; do if test "X$x" = "X$dir"; then haveit=yes break fi done if test -z "$haveit"; then rpathdirs="$rpathdirs $dir" fi haveit= for x in $ltrpathdirs; do if test "X$x" = "X$dir"; then haveit=yes break fi done if test -z "$haveit"; then ltrpathdirs="$ltrpathdirs $dir" fi fi ;; -l*) names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` ;; *.la) names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` ;; *) LIBICONV="${LIBICONV}${LIBICONV:+ }$dep" LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }$dep" ;; esac done fi else LIBICONV="${LIBICONV}${LIBICONV:+ }-l$name" LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-l$name" fi fi fi done done if test "X$rpathdirs" != "X"; then if test -n "$hardcode_libdir_separator"; then alldirs= for found_dir in $rpathdirs; do alldirs="${alldirs}${alldirs:+$hardcode_libdir_separator}$found_dir" done acl_save_libdir="$libdir" libdir="$alldirs" eval flag=\"$hardcode_libdir_flag_spec\" libdir="$acl_save_libdir" LIBICONV="${LIBICONV}${LIBICONV:+ }$flag" else for found_dir in $rpathdirs; do acl_save_libdir="$libdir" libdir="$found_dir" eval flag=\"$hardcode_libdir_flag_spec\" libdir="$acl_save_libdir" LIBICONV="${LIBICONV}${LIBICONV:+ }$flag" done fi fi if test "X$ltrpathdirs" != "X"; then for found_dir in $ltrpathdirs; do LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-R$found_dir" done fi echo "$as_me:$LINENO: checking for CFPreferencesCopyAppValue" >&5 echo $ECHO_N "checking for CFPreferencesCopyAppValue... $ECHO_C" >&6 if test "${gt_cv_func_CFPreferencesCopyAppValue+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else gt_save_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS -I/System/Library/Frameworks/CoreFoundation.framework/Headers" gt_save_LIBS="$LIBS" LIBS="$LIBS -framework CoreFoundation" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { CFPreferencesCopyAppValue(NULL, NULL) ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then gt_cv_func_CFPreferencesCopyAppValue=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 gt_cv_func_CFPreferencesCopyAppValue=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext CPPFLAGS="$gt_save_CPPFLAGS" LIBS="$gt_save_LIBS" fi echo "$as_me:$LINENO: result: $gt_cv_func_CFPreferencesCopyAppValue" >&5 echo "${ECHO_T}$gt_cv_func_CFPreferencesCopyAppValue" >&6 if test $gt_cv_func_CFPreferencesCopyAppValue = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_CFPREFERENCESCOPYAPPVALUE 1 _ACEOF fi echo "$as_me:$LINENO: checking for CFLocaleCopyCurrent" >&5 echo $ECHO_N "checking for CFLocaleCopyCurrent... $ECHO_C" >&6 if test "${gt_cv_func_CFLocaleCopyCurrent+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else gt_save_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS -I/System/Library/Frameworks/CoreFoundation.framework/Headers" gt_save_LIBS="$LIBS" LIBS="$LIBS -framework CoreFoundation" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { CFLocaleCopyCurrent(); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then gt_cv_func_CFLocaleCopyCurrent=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 gt_cv_func_CFLocaleCopyCurrent=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext CPPFLAGS="$gt_save_CPPFLAGS" LIBS="$gt_save_LIBS" fi echo "$as_me:$LINENO: result: $gt_cv_func_CFLocaleCopyCurrent" >&5 echo "${ECHO_T}$gt_cv_func_CFLocaleCopyCurrent" >&6 if test $gt_cv_func_CFLocaleCopyCurrent = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_CFLOCALECOPYCURRENT 1 _ACEOF fi INTL_MACOSX_LIBS= if test $gt_cv_func_CFPreferencesCopyAppValue = yes || test $gt_cv_func_CFLocaleCopyCurrent = yes; then INTL_MACOSX_LIBS="-Wl,-framework -Wl,CoreFoundation" fi echo "$as_me:$LINENO: checking whether NLS is requested" >&5 echo $ECHO_N "checking whether NLS is requested... $ECHO_C" >&6 # Check whether --enable-nls or --disable-nls was given. if test "${enable_nls+set}" = set; then enableval="$enable_nls" USE_NLS=$enableval else USE_NLS=yes fi; echo "$as_me:$LINENO: result: $USE_NLS" >&5 echo "${ECHO_T}$USE_NLS" >&6 LIBINTL= LTLIBINTL= POSUB= if test "$USE_NLS" = "yes"; then gt_use_preinstalled_gnugettext=no echo "$as_me:$LINENO: checking for GNU gettext in libc" >&5 echo $ECHO_N "checking for GNU gettext in libc... $ECHO_C" >&6 if test "${gt_cv_func_gnugettext1_libc+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include extern int _nl_msg_cat_cntr; extern int *_nl_domain_bindings; int main () { bindtextdomain ("", ""); return * gettext ("") + _nl_msg_cat_cntr + *_nl_domain_bindings ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then gt_cv_func_gnugettext1_libc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 gt_cv_func_gnugettext1_libc=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $gt_cv_func_gnugettext1_libc" >&5 echo "${ECHO_T}$gt_cv_func_gnugettext1_libc" >&6 if test "$gt_cv_func_gnugettext1_libc" != "yes"; then am_save_CPPFLAGS="$CPPFLAGS" for element in $INCICONV; do haveit= for x in $CPPFLAGS; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X$element"; then haveit=yes break fi done if test -z "$haveit"; then CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }$element" fi done echo "$as_me:$LINENO: checking for iconv" >&5 echo $ECHO_N "checking for iconv... $ECHO_C" >&6 if test "${am_cv_func_iconv+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else am_cv_func_iconv="no, consider installing GNU libiconv" am_cv_lib_iconv=no cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include int main () { iconv_t cd = iconv_open("",""); iconv(cd,NULL,NULL,NULL,NULL); iconv_close(cd); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then am_cv_func_iconv=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test "$am_cv_func_iconv" != yes; then am_save_LIBS="$LIBS" LIBS="$LIBS $LIBICONV" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include int main () { iconv_t cd = iconv_open("",""); iconv(cd,NULL,NULL,NULL,NULL); iconv_close(cd); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then am_cv_lib_iconv=yes am_cv_func_iconv=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS="$am_save_LIBS" fi fi echo "$as_me:$LINENO: result: $am_cv_func_iconv" >&5 echo "${ECHO_T}$am_cv_func_iconv" >&6 if test "$am_cv_func_iconv" = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_ICONV 1 _ACEOF fi if test "$am_cv_lib_iconv" = yes; then echo "$as_me:$LINENO: checking how to link with libiconv" >&5 echo $ECHO_N "checking how to link with libiconv... $ECHO_C" >&6 echo "$as_me:$LINENO: result: $LIBICONV" >&5 echo "${ECHO_T}$LIBICONV" >&6 else CPPFLAGS="$am_save_CPPFLAGS" LIBICONV= LTLIBICONV= fi use_additional=yes acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" # Check whether --with-libintl-prefix or --without-libintl-prefix was given. if test "${with_libintl_prefix+set}" = set; then withval="$with_libintl_prefix" if test "X$withval" = "Xno"; then use_additional=no else if test "X$withval" = "X"; then acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" else additional_includedir="$withval/include" additional_libdir="$withval/lib" fi fi fi; LIBINTL= LTLIBINTL= INCINTL= rpathdirs= ltrpathdirs= names_already_handled= names_next_round='intl ' while test -n "$names_next_round"; do names_this_round="$names_next_round" names_next_round= for name in $names_this_round; do already_handled= for n in $names_already_handled; do if test "$n" = "$name"; then already_handled=yes break fi done if test -z "$already_handled"; then names_already_handled="$names_already_handled $name" uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'` eval value=\"\$HAVE_LIB$uppername\" if test -n "$value"; then if test "$value" = yes; then eval value=\"\$LIB$uppername\" test -z "$value" || LIBINTL="${LIBINTL}${LIBINTL:+ }$value" eval value=\"\$LTLIB$uppername\" test -z "$value" || LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }$value" else : fi else found_dir= found_la= found_so= found_a= if test $use_additional = yes; then if test -n "$shlibext" && test -f "$additional_libdir/lib$name.$shlibext"; then found_dir="$additional_libdir" found_so="$additional_libdir/lib$name.$shlibext" if test -f "$additional_libdir/lib$name.la"; then found_la="$additional_libdir/lib$name.la" fi else if test -f "$additional_libdir/lib$name.$libext"; then found_dir="$additional_libdir" found_a="$additional_libdir/lib$name.$libext" if test -f "$additional_libdir/lib$name.la"; then found_la="$additional_libdir/lib$name.la" fi fi fi fi if test "X$found_dir" = "X"; then for x in $LDFLAGS $LTLIBINTL; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" case "$x" in -L*) dir=`echo "X$x" | sed -e 's/^X-L//'` if test -n "$shlibext" && test -f "$dir/lib$name.$shlibext"; then found_dir="$dir" found_so="$dir/lib$name.$shlibext" if test -f "$dir/lib$name.la"; then found_la="$dir/lib$name.la" fi else if test -f "$dir/lib$name.$libext"; then found_dir="$dir" found_a="$dir/lib$name.$libext" if test -f "$dir/lib$name.la"; then found_la="$dir/lib$name.la" fi fi fi ;; esac if test "X$found_dir" != "X"; then break fi done fi if test "X$found_dir" != "X"; then LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }-L$found_dir -l$name" if test "X$found_so" != "X"; then if test "$enable_rpath" = no || test "X$found_dir" = "X/usr/lib"; then LIBINTL="${LIBINTL}${LIBINTL:+ }$found_so" else haveit= for x in $ltrpathdirs; do if test "X$x" = "X$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then ltrpathdirs="$ltrpathdirs $found_dir" fi if test "$hardcode_direct" = yes; then LIBINTL="${LIBINTL}${LIBINTL:+ }$found_so" else if test -n "$hardcode_libdir_flag_spec" && test "$hardcode_minus_L" = no; then LIBINTL="${LIBINTL}${LIBINTL:+ }$found_so" haveit= for x in $rpathdirs; do if test "X$x" = "X$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then rpathdirs="$rpathdirs $found_dir" fi else haveit= for x in $LDFLAGS $LIBINTL; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X-L$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then LIBINTL="${LIBINTL}${LIBINTL:+ }-L$found_dir" fi if test "$hardcode_minus_L" != no; then LIBINTL="${LIBINTL}${LIBINTL:+ }$found_so" else LIBINTL="${LIBINTL}${LIBINTL:+ }-l$name" fi fi fi fi else if test "X$found_a" != "X"; then LIBINTL="${LIBINTL}${LIBINTL:+ }$found_a" else LIBINTL="${LIBINTL}${LIBINTL:+ }-L$found_dir -l$name" fi fi additional_includedir= case "$found_dir" in */lib | */lib/) basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e 's,/lib/*$,,'` additional_includedir="$basedir/include" ;; esac if test "X$additional_includedir" != "X"; then if test "X$additional_includedir" != "X/usr/include"; then haveit= if test "X$additional_includedir" = "X/usr/local/include"; then if test -n "$GCC"; then case $host_os in linux* | gnu* | k*bsd*-gnu) haveit=yes;; esac fi fi if test -z "$haveit"; then for x in $CPPFLAGS $INCINTL; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X-I$additional_includedir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_includedir"; then INCINTL="${INCINTL}${INCINTL:+ }-I$additional_includedir" fi fi fi fi fi if test -n "$found_la"; then save_libdir="$libdir" case "$found_la" in */* | *\\*) . "$found_la" ;; *) . "./$found_la" ;; esac libdir="$save_libdir" for dep in $dependency_libs; do case "$dep" in -L*) additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` if test "X$additional_libdir" != "X/usr/lib"; then haveit= if test "X$additional_libdir" = "X/usr/local/lib"; then if test -n "$GCC"; then case $host_os in linux* | gnu* | k*bsd*-gnu) haveit=yes;; esac fi fi if test -z "$haveit"; then haveit= for x in $LDFLAGS $LIBINTL; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X-L$additional_libdir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_libdir"; then LIBINTL="${LIBINTL}${LIBINTL:+ }-L$additional_libdir" fi fi haveit= for x in $LDFLAGS $LTLIBINTL; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X-L$additional_libdir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_libdir"; then LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }-L$additional_libdir" fi fi fi fi ;; -R*) dir=`echo "X$dep" | sed -e 's/^X-R//'` if test "$enable_rpath" != no; then haveit= for x in $rpathdirs; do if test "X$x" = "X$dir"; then haveit=yes break fi done if test -z "$haveit"; then rpathdirs="$rpathdirs $dir" fi haveit= for x in $ltrpathdirs; do if test "X$x" = "X$dir"; then haveit=yes break fi done if test -z "$haveit"; then ltrpathdirs="$ltrpathdirs $dir" fi fi ;; -l*) names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` ;; *.la) names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` ;; *) LIBINTL="${LIBINTL}${LIBINTL:+ }$dep" LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }$dep" ;; esac done fi else LIBINTL="${LIBINTL}${LIBINTL:+ }-l$name" LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }-l$name" fi fi fi done done if test "X$rpathdirs" != "X"; then if test -n "$hardcode_libdir_separator"; then alldirs= for found_dir in $rpathdirs; do alldirs="${alldirs}${alldirs:+$hardcode_libdir_separator}$found_dir" done acl_save_libdir="$libdir" libdir="$alldirs" eval flag=\"$hardcode_libdir_flag_spec\" libdir="$acl_save_libdir" LIBINTL="${LIBINTL}${LIBINTL:+ }$flag" else for found_dir in $rpathdirs; do acl_save_libdir="$libdir" libdir="$found_dir" eval flag=\"$hardcode_libdir_flag_spec\" libdir="$acl_save_libdir" LIBINTL="${LIBINTL}${LIBINTL:+ }$flag" done fi fi if test "X$ltrpathdirs" != "X"; then for found_dir in $ltrpathdirs; do LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }-R$found_dir" done fi echo "$as_me:$LINENO: checking for GNU gettext in libintl" >&5 echo $ECHO_N "checking for GNU gettext in libintl... $ECHO_C" >&6 if test "${gt_cv_func_gnugettext1_libintl+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else gt_save_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS $INCINTL" gt_save_LIBS="$LIBS" LIBS="$LIBS $LIBINTL" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include extern int _nl_msg_cat_cntr; extern #ifdef __cplusplus "C" #endif const char *_nl_expand_alias (const char *); int main () { bindtextdomain ("", ""); return * gettext ("") + _nl_msg_cat_cntr + *_nl_expand_alias ("") ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then gt_cv_func_gnugettext1_libintl=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 gt_cv_func_gnugettext1_libintl=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test "$gt_cv_func_gnugettext1_libintl" != yes && test -n "$LIBICONV"; then LIBS="$LIBS $LIBICONV" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include extern int _nl_msg_cat_cntr; extern #ifdef __cplusplus "C" #endif const char *_nl_expand_alias (const char *); int main () { bindtextdomain ("", ""); return * gettext ("") + _nl_msg_cat_cntr + *_nl_expand_alias ("") ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then LIBINTL="$LIBINTL $LIBICONV" LTLIBINTL="$LTLIBINTL $LTLIBICONV" gt_cv_func_gnugettext1_libintl=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi CPPFLAGS="$gt_save_CPPFLAGS" LIBS="$gt_save_LIBS" fi echo "$as_me:$LINENO: result: $gt_cv_func_gnugettext1_libintl" >&5 echo "${ECHO_T}$gt_cv_func_gnugettext1_libintl" >&6 fi if test "$gt_cv_func_gnugettext1_libc" = "yes" \ || { test "$gt_cv_func_gnugettext1_libintl" = "yes" \ && test "$PACKAGE" != gettext-runtime \ && test "$PACKAGE" != gettext-tools; }; then gt_use_preinstalled_gnugettext=yes else LIBINTL= LTLIBINTL= INCINTL= fi if test -n "$INTL_MACOSX_LIBS"; then if test "$gt_use_preinstalled_gnugettext" = "yes" \ || test "$nls_cv_use_gnu_gettext" = "yes"; then LIBINTL="$LIBINTL $INTL_MACOSX_LIBS" LTLIBINTL="$LTLIBINTL $INTL_MACOSX_LIBS" fi fi if test "$gt_use_preinstalled_gnugettext" = "yes" \ || test "$nls_cv_use_gnu_gettext" = "yes"; then cat >>confdefs.h <<\_ACEOF #define ENABLE_NLS 1 _ACEOF else USE_NLS=no fi fi echo "$as_me:$LINENO: checking whether to use NLS" >&5 echo $ECHO_N "checking whether to use NLS... $ECHO_C" >&6 echo "$as_me:$LINENO: result: $USE_NLS" >&5 echo "${ECHO_T}$USE_NLS" >&6 if test "$USE_NLS" = "yes"; then echo "$as_me:$LINENO: checking where the gettext function comes from" >&5 echo $ECHO_N "checking where the gettext function comes from... $ECHO_C" >&6 if test "$gt_use_preinstalled_gnugettext" = "yes"; then if test "$gt_cv_func_gnugettext1_libintl" = "yes"; then gt_source="external libintl" else gt_source="libc" fi else gt_source="included intl directory" fi echo "$as_me:$LINENO: result: $gt_source" >&5 echo "${ECHO_T}$gt_source" >&6 fi if test "$USE_NLS" = "yes"; then if test "$gt_use_preinstalled_gnugettext" = "yes"; then if test "$gt_cv_func_gnugettext1_libintl" = "yes"; then echo "$as_me:$LINENO: checking how to link with libintl" >&5 echo $ECHO_N "checking how to link with libintl... $ECHO_C" >&6 echo "$as_me:$LINENO: result: $LIBINTL" >&5 echo "${ECHO_T}$LIBINTL" >&6 for element in $INCINTL; do haveit= for x in $CPPFLAGS; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X$element"; then haveit=yes break fi done if test -z "$haveit"; then CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }$element" fi done fi cat >>confdefs.h <<\_ACEOF #define HAVE_GETTEXT 1 _ACEOF cat >>confdefs.h <<\_ACEOF #define HAVE_DCGETTEXT 1 _ACEOF fi POSUB=po fi INTLLIBS="$LIBINTL" # Check for ScrollKeeper. # Extract the first word of "scrollkeeper-config", so it can be a program name with args. set dummy scrollkeeper-config; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_have_scrollkeeper+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$have_scrollkeeper"; then ac_cv_prog_have_scrollkeeper="$have_scrollkeeper" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_have_scrollkeeper="yes" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done test -z "$ac_cv_prog_have_scrollkeeper" && ac_cv_prog_have_scrollkeeper="no" fi fi have_scrollkeeper=$ac_cv_prog_have_scrollkeeper if test -n "$have_scrollkeeper"; then echo "$as_me:$LINENO: result: $have_scrollkeeper" >&5 echo "${ECHO_T}$have_scrollkeeper" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi if test "$have_scrollkeeper" = "yes"; then HAVE_SCROLLKEEPER_TRUE= HAVE_SCROLLKEEPER_FALSE='#' else HAVE_SCROLLKEEPER_TRUE='#' HAVE_SCROLLKEEPER_FALSE= fi if test "$have_scrollkeeper" = "yes"; then cat >>confdefs.h <<\_ACEOF #define HAVE_SCROLLKEEPER 1 _ACEOF fi # Require GTK+ 2.0.0 or later and librsvg 2.5.0 or later. if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_path_PKG_CONFIG+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else case $PKG_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done ;; esac fi PKG_CONFIG=$ac_cv_path_PKG_CONFIG if test -n "$PKG_CONFIG"; then echo "$as_me:$LINENO: result: $PKG_CONFIG" >&5 echo "${ECHO_T}$PKG_CONFIG" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi if test -z "$ac_cv_path_PKG_CONFIG"; then ac_pt_PKG_CONFIG=$PKG_CONFIG # Extract the first word of "pkg-config", so it can be a program name with args. set dummy pkg-config; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_path_ac_pt_PKG_CONFIG+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else case $ac_pt_PKG_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done ;; esac fi ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG if test -n "$ac_pt_PKG_CONFIG"; then echo "$as_me:$LINENO: result: $ac_pt_PKG_CONFIG" >&5 echo "${ECHO_T}$ac_pt_PKG_CONFIG" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi PKG_CONFIG=$ac_pt_PKG_CONFIG else PKG_CONFIG="$ac_cv_path_PKG_CONFIG" fi fi if test -n "$PKG_CONFIG"; then _pkg_min_version=0.9.0 echo "$as_me:$LINENO: checking pkg-config is at least version $_pkg_min_version" >&5 echo $ECHO_N "checking pkg-config is at least version $_pkg_min_version... $ECHO_C" >&6 if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 PKG_CONFIG="" fi fi pkg_failed=no echo "$as_me:$LINENO: checking for QUARRY_GTK_CFLAGS" >&5 echo $ECHO_N "checking for QUARRY_GTK_CFLAGS... $ECHO_C" >&6 if test "${pkg_cv_QUARRY_GTK_CFLAGS+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "x$ac_cv_env_QUARRY_GTK_CFLAGS_set" = "xset"; then pkg_cv_QUARRY_GTK_CFLAGS=$ac_cv_env_QUARRY_GTK_CFLAGS_value elif test -n "$PKG_CONFIG"; then if { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists \"gtk+-2.0 >= 2.0.0 librsvg-2.0 >= 2.5.0\" >/dev/null 2>&1") >&5 ($PKG_CONFIG --exists "gtk+-2.0 >= 2.0.0 librsvg-2.0 >= 2.5.0" >/dev/null 2>&1) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then pkg_cv_QUARRY_GTK_CFLAGS=`$PKG_CONFIG --cflags "gtk+-2.0 >= 2.0.0 librsvg-2.0 >= 2.5.0" 2>/dev/null` else pkg_failed=yes fi else pkg_failed=untried fi fi echo "$as_me:$LINENO: result: $pkg_cv_QUARRY_GTK_CFLAGS" >&5 echo "${ECHO_T}$pkg_cv_QUARRY_GTK_CFLAGS" >&6 echo "$as_me:$LINENO: checking for QUARRY_GTK_LIBS" >&5 echo $ECHO_N "checking for QUARRY_GTK_LIBS... $ECHO_C" >&6 if test "${pkg_cv_QUARRY_GTK_LIBS+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "x$ac_cv_env_QUARRY_GTK_LIBS_set" = "xset"; then pkg_cv_QUARRY_GTK_LIBS=$ac_cv_env_QUARRY_GTK_LIBS_value elif test -n "$PKG_CONFIG"; then if { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists \"gtk+-2.0 >= 2.0.0 librsvg-2.0 >= 2.5.0\" >/dev/null 2>&1") >&5 ($PKG_CONFIG --exists "gtk+-2.0 >= 2.0.0 librsvg-2.0 >= 2.5.0" >/dev/null 2>&1) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then pkg_cv_QUARRY_GTK_LIBS=`$PKG_CONFIG --libs "gtk+-2.0 >= 2.0.0 librsvg-2.0 >= 2.5.0" 2>/dev/null` else pkg_failed=yes fi else pkg_failed=untried fi fi echo "$as_me:$LINENO: result: $pkg_cv_QUARRY_GTK_LIBS" >&5 echo "${ECHO_T}$pkg_cv_QUARRY_GTK_LIBS" >&6 if test $pkg_failed = yes; then QUARRY_GTK_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "gtk+-2.0 >= 2.0.0 librsvg-2.0 >= 2.5.0"` # Put the nasty error message in config.log where it belongs echo "$QUARRY_GTK_PKG_ERRORS" 1>&5 { { echo "$as_me:$LINENO: error: Package requirements (gtk+-2.0 >= 2.0.0 librsvg-2.0 >= 2.5.0) were not met. Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. Alternatively you may set the QUARRY_GTK_CFLAGS and QUARRY_GTK_LIBS environment variables to avoid the need to call pkg-config. See the pkg-config man page for more details." >&5 echo "$as_me: error: Package requirements (gtk+-2.0 >= 2.0.0 librsvg-2.0 >= 2.5.0) were not met. Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. Alternatively you may set the QUARRY_GTK_CFLAGS and QUARRY_GTK_LIBS environment variables to avoid the need to call pkg-config. See the pkg-config man page for more details." >&2;} { (exit 1); exit 1; }; } elif test $pkg_failed = untried; then { { echo "$as_me:$LINENO: error: The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. Alternatively you may set the QUARRY_GTK_CFLAGS and QUARRY_GTK_LIBS environment variables to avoid the need to call pkg-config. See the pkg-config man page for more details. To get pkg-config, see . See \`config.log' for more details." >&5 echo "$as_me: error: The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. Alternatively you may set the QUARRY_GTK_CFLAGS and QUARRY_GTK_LIBS environment variables to avoid the need to call pkg-config. See the pkg-config man page for more details. To get pkg-config, see . See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } else QUARRY_GTK_CFLAGS=$pkg_cv_QUARRY_GTK_CFLAGS QUARRY_GTK_LIBS=$pkg_cv_QUARRY_GTK_LIBS : fi # Threads are not required for Quarry. While Glib is probably always # compiled with thread support, let's not insist anyway. pkg_failed=no echo "$as_me:$LINENO: checking for QUARRY_GTHREAD_CFLAGS" >&5 echo $ECHO_N "checking for QUARRY_GTHREAD_CFLAGS... $ECHO_C" >&6 if test "${pkg_cv_QUARRY_GTHREAD_CFLAGS+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "x$ac_cv_env_QUARRY_GTHREAD_CFLAGS_set" = "xset"; then pkg_cv_QUARRY_GTHREAD_CFLAGS=$ac_cv_env_QUARRY_GTHREAD_CFLAGS_value elif test -n "$PKG_CONFIG"; then if { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists \"gthread-2.0 >= 2.0.0\" >/dev/null 2>&1") >&5 ($PKG_CONFIG --exists "gthread-2.0 >= 2.0.0" >/dev/null 2>&1) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then pkg_cv_QUARRY_GTHREAD_CFLAGS=`$PKG_CONFIG --cflags "gthread-2.0 >= 2.0.0" 2>/dev/null` else pkg_failed=yes fi else pkg_failed=untried fi fi echo "$as_me:$LINENO: result: $pkg_cv_QUARRY_GTHREAD_CFLAGS" >&5 echo "${ECHO_T}$pkg_cv_QUARRY_GTHREAD_CFLAGS" >&6 echo "$as_me:$LINENO: checking for QUARRY_GTHREAD_LIBS" >&5 echo $ECHO_N "checking for QUARRY_GTHREAD_LIBS... $ECHO_C" >&6 if test "${pkg_cv_QUARRY_GTHREAD_LIBS+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "x$ac_cv_env_QUARRY_GTHREAD_LIBS_set" = "xset"; then pkg_cv_QUARRY_GTHREAD_LIBS=$ac_cv_env_QUARRY_GTHREAD_LIBS_value elif test -n "$PKG_CONFIG"; then if { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists \"gthread-2.0 >= 2.0.0\" >/dev/null 2>&1") >&5 ($PKG_CONFIG --exists "gthread-2.0 >= 2.0.0" >/dev/null 2>&1) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then pkg_cv_QUARRY_GTHREAD_LIBS=`$PKG_CONFIG --libs "gthread-2.0 >= 2.0.0" 2>/dev/null` else pkg_failed=yes fi else pkg_failed=untried fi fi echo "$as_me:$LINENO: result: $pkg_cv_QUARRY_GTHREAD_LIBS" >&5 echo "${ECHO_T}$pkg_cv_QUARRY_GTHREAD_LIBS" >&6 if test $pkg_failed = yes; then QUARRY_GTHREAD_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "gthread-2.0 >= 2.0.0"` # Put the nasty error message in config.log where it belongs echo "$QUARRY_GTHREAD_PKG_ERRORS" 1>&5 : elif test $pkg_failed = untried; then : else QUARRY_GTHREAD_CFLAGS=$pkg_cv_QUARRY_GTHREAD_CFLAGS QUARRY_GTHREAD_LIBS=$pkg_cv_QUARRY_GTHREAD_LIBS : fi # Needed to generate Quarry-specific marshallers (see # `src/gui-gtk/Makefile.am'). GLIB_GENMARSHAL=`$PKG_CONFIG --variable=glib_genmarshal glib-2.0` # Optionally enable automatic building and installation of standalone # SGF utilities (only `sgf-diff' at the moment). Even if not enabled, # the utilities can still be built manually. # Check whether --enable-sgf-utils or --disable-sgf-utils was given. if test "${enable_sgf_utils+set}" = set; then enableval="$enable_sgf_utils" fi; if test "$enable_sgf_utils" = "yes"; then BUILD_SGF_UTILS_TRUE= BUILD_SGF_UTILS_FALSE='#' else BUILD_SGF_UTILS_TRUE='#' BUILD_SGF_UTILS_FALSE= fi # Optionally disable deprecated GTK+ code (for maintainers---to check # if some code should be replaced with newer). # Check whether --enable-gtk-deprecated or --disable-gtk-deprecated was given. if test "${enable_gtk_deprecated+set}" = set; then enableval="$enable_gtk_deprecated" fi; if test "$enable_gtk_deprecated" = "no"; then QUARRY_GTK_DEPRECATED_FLAGS='-D G_DISABLE_DEPRECATED -D GDK_DISABLE_DEPRECATED -D GDK_PIXBUF_DISABLE_DEPRECATED -D GTK_DISABLE_DEPRECATED' else QUARRY_GTK_DEPRECATED_FLAGS='' fi # Check whether --enable-scrollkeeper-update or --disable-scrollkeeper-update was given. if test "${enable_scrollkeeper_update+set}" = set; then enableval="$enable_scrollkeeper_update" fi; if test "$have_scrollkeeper" == "yes" && test "$enable_scrollkeeper_update" != "no"; then DO_SCROLLKEEPER_UPDATE_TRUE= DO_SCROLLKEEPER_UPDATE_FALSE='#' else DO_SCROLLKEEPER_UPDATE_TRUE='#' DO_SCROLLKEEPER_UPDATE_FALSE= fi # Check whether --enable-mime-database-update or --disable-mime-database-update was given. if test "${enable_mime_database_update+set}" = set; then enableval="$enable_mime_database_update" fi; if test "$enable_mime_database_update" != "no"; then REGISTER_MIME_TYPES_TRUE= REGISTER_MIME_TYPES_FALSE='#' else REGISTER_MIME_TYPES_TRUE='#' REGISTER_MIME_TYPES_FALSE= fi # Write `Makefile's. ac_config_files="$ac_config_files Makefile data/Makefile data/quarry.desktop data/markup-themes/Makefile data/textures/Makefile help/Makefile help/C/Makefile po/Makefile.in src/Makefile src/board/Makefile src/gtp/Makefile src/gui-gtk/Makefile src/gui-utils/Makefile src/sgf/Makefile src/utils/Makefile" # The end. cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, don't put newlines in cache variables' values. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. { (set) 2>&1 | case `(ac_space=' '; set | grep ac_space) 2>&1` in *ac_space=\ *) # `set' does not quote correctly, so add quotes (double-quote # substitution turns \\\\ into \\, and sed turns \\ into \). sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n \ "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" ;; esac; } | sed ' t clear : clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ : end' >>confcache if diff $cache_file confcache >/dev/null 2>&1; then :; else if test -w $cache_file; then test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file" cat confcache >$cache_file else echo "not updating unwritable cache $cache_file" fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # VPATH may cause trouble with some makes, so we remove $(srcdir), # ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=/{ s/:*\$(srcdir):*/:/; s/:*\${srcdir}:*/:/; s/:*@srcdir@:*/:/; s/^\([^=]*=[ ]*\):*/\1/; s/:*$//; s/^[^=]*=[ ]*$//; }' fi DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_i=`echo "$ac_i" | sed 's/\$U\././;s/\.o$//;s/\.obj$//'` # 2. Add them. ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext" ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"MAINTAINER_MODE\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"MAINTAINER_MODE\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${HAVE_SCROLLKEEPER_TRUE}" && test -z "${HAVE_SCROLLKEEPER_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"HAVE_SCROLLKEEPER\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"HAVE_SCROLLKEEPER\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${BUILD_SGF_UTILS_TRUE}" && test -z "${BUILD_SGF_UTILS_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"BUILD_SGF_UTILS\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"BUILD_SGF_UTILS\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${DO_SCROLLKEEPER_UPDATE_TRUE}" && test -z "${DO_SCROLLKEEPER_UPDATE_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"DO_SCROLLKEEPER_UPDATE\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"DO_SCROLLKEEPER_UPDATE\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${REGISTER_MIME_TYPES_TRUE}" && test -z "${REGISTER_MIME_TYPES_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"REGISTER_MIME_TYPES\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"REGISTER_MIME_TYPES\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi : ${CONFIG_STATUS=./config.status} ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 echo "$as_me: creating $CONFIG_STATUS" >&6;} cat >$CONFIG_STATUS <<_ACEOF #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF ## --------------------- ## ## M4sh Initialization. ## ## --------------------- ## # Be Bourne compatible if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then set -o posix fi DUALCASE=1; export DUALCASE # for MKS sh # Support unset when possible. if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then as_unset=unset else as_unset=false fi # Work around bugs in pre-3.0 UWIN ksh. $as_unset ENV MAIL MAILPATH PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. for as_var in \ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ LC_TELEPHONE LC_TIME do if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then eval $as_var=C; export $as_var else $as_unset $as_var fi done # Required to use basename. if expr a : '\(a\)' >/dev/null 2>&1; then as_expr=expr else as_expr=false fi if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi # Name of the executable. as_me=`$as_basename "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)$' \| \ . : '\(.\)' 2>/dev/null || echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } /^X\/\(\/\/\)$/{ s//\1/; q; } /^X\/\(\/\).*/{ s//\1/; q; } s/.*/./; q'` # PATH needs CR, and LINENO needs CR and PATH. # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi as_lineno_1=$LINENO as_lineno_2=$LINENO as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` test "x$as_lineno_1" != "x$as_lineno_2" && test "x$as_lineno_3" = "x$as_lineno_2" || { # Find who we are. Look in the path if we contain no path at all # relative or not. case $0 in *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5 echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;} { (exit 1); exit 1; }; } fi case $CONFIG_SHELL in '') as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for as_base in sh bash ksh sh5; do case $as_dir in /*) if ("$as_dir/$as_base" -c ' as_lineno_1=$LINENO as_lineno_2=$LINENO as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` test "x$as_lineno_1" != "x$as_lineno_2" && test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } CONFIG_SHELL=$as_dir/$as_base export CONFIG_SHELL exec "$CONFIG_SHELL" "$0" ${1+"$@"} fi;; esac done done ;; esac # Create $as_me.lineno as a copy of $as_myself, but with $LINENO # uniformly replaced by the line number. The first 'sed' inserts a # line-number line before each line; the second 'sed' does the real # work. The second script uses 'N' to pair each line-number line # with the numbered line, and appends trailing '-' during # substitution so that $LINENO is not a special case at line end. # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) sed '=' <$as_myself | sed ' N s,$,-, : loop s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, t loop s,-$,, s,^['$as_cr_digits']*\n,, ' >$as_me.lineno && chmod +x $as_me.lineno || { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5 echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;} { (exit 1); exit 1; }; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensible to this). . ./$as_me.lineno # Exit status is that of the last command. exit } case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in *c*,-n*) ECHO_N= ECHO_C=' ' ECHO_T=' ' ;; *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; *) ECHO_N= ECHO_C='\c' ECHO_T= ;; esac if expr a : '\(a\)' >/dev/null 2>&1; then as_expr=expr else as_expr=false fi rm -f conf$$ conf$$.exe conf$$.file echo >conf$$.file if ln -s conf$$.file conf$$ 2>/dev/null; then # We could just check for DJGPP; but this test a) works b) is more generic # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). if test -f conf$$.exe; then # Don't use ln at all; we don't have any links as_ln_s='cp -p' else as_ln_s='ln -s' fi elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.file if mkdir -p . 2>/dev/null; then as_mkdir_p=: else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_executable_p="test -f" # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" # IFS # We need space, tab and new line, in precisely that order. as_nl=' ' IFS=" $as_nl" # CDPATH. $as_unset CDPATH exec 6>&1 # Open the log real soon, to keep \$[0] and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. Logging --version etc. is OK. exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX } >&5 cat >&5 <<_CSEOF This file was extended by Quarry $as_me 0.2.0, which was generated by GNU Autoconf 2.59. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ _CSEOF echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5 echo >&5 _ACEOF # Files that config.status was made for. if test -n "$ac_config_files"; then echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS fi if test -n "$ac_config_headers"; then echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS fi if test -n "$ac_config_links"; then echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS fi if test -n "$ac_config_commands"; then echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS fi cat >>$CONFIG_STATUS <<\_ACEOF ac_cs_usage="\ \`$as_me' instantiates files from templates according to the current configuration. Usage: $0 [OPTIONS] [FILE]... -h, --help print this help, then exit -V, --version print version number, then exit -q, --quiet do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Configuration commands: $config_commands Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_cs_version="\\ Quarry config.status 0.2.0 configured by $0, generated by GNU Autoconf 2.59, with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" Copyright (C) 2003 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." srcdir=$srcdir INSTALL="$INSTALL" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # If no file are specified by the user, then we need to provide default # value. By we need to know if files were specified by the user. ac_need_defaults=: while test $# != 0 do case $1 in --*=*) ac_option=`expr "x$1" : 'x\([^=]*\)='` ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'` ac_shift=: ;; -*) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; *) # This is not an option, so the user has probably given explicit # arguments. ac_option=$1 ac_need_defaults=false;; esac case $ac_option in # Handling of the options. _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --vers* | -V ) echo "$ac_cs_version"; exit 0 ;; --he | --h) # Conflict between --help and --header { { echo "$as_me:$LINENO: error: ambiguous option: $1 Try \`$0 --help' for more information." >&5 echo "$as_me: error: ambiguous option: $1 Try \`$0 --help' for more information." >&2;} { (exit 1); exit 1; }; };; --help | --hel | -h ) echo "$ac_cs_usage"; exit 0 ;; --debug | --d* | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift CONFIG_FILES="$CONFIG_FILES $ac_optarg" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" ac_need_defaults=false;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1 Try \`$0 --help' for more information." >&5 echo "$as_me: error: unrecognized option: $1 Try \`$0 --help' for more information." >&2;} { (exit 1); exit 1; }; } ;; *) ac_config_targets="$ac_config_targets $1" ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF if \$ac_cs_recheck; then echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF # # INIT-COMMANDS section. # AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" # Capture the value of obsolete ALL_LINGUAS because we need it to compute # POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES, CATALOGS. But hide it # from automake. eval 'OBSOLETE_ALL_LINGUAS''="$ALL_LINGUAS"' # Capture the value of LINGUAS because we need it to compute CATALOGS. LINGUAS="${LINGUAS-%UNSET%}" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF for ac_config_target in $ac_config_targets do case "$ac_config_target" in # Handling of arguments. "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;; "data/Makefile" ) CONFIG_FILES="$CONFIG_FILES data/Makefile" ;; "data/quarry.desktop" ) CONFIG_FILES="$CONFIG_FILES data/quarry.desktop" ;; "data/markup-themes/Makefile" ) CONFIG_FILES="$CONFIG_FILES data/markup-themes/Makefile" ;; "data/textures/Makefile" ) CONFIG_FILES="$CONFIG_FILES data/textures/Makefile" ;; "help/Makefile" ) CONFIG_FILES="$CONFIG_FILES help/Makefile" ;; "help/C/Makefile" ) CONFIG_FILES="$CONFIG_FILES help/C/Makefile" ;; "po/Makefile.in" ) CONFIG_FILES="$CONFIG_FILES po/Makefile.in" ;; "src/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; "src/board/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/board/Makefile" ;; "src/gtp/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/gtp/Makefile" ;; "src/gui-gtk/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/gui-gtk/Makefile" ;; "src/gui-utils/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/gui-utils/Makefile" ;; "src/sgf/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/sgf/Makefile" ;; "src/utils/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/utils/Makefile" ;; "depfiles" ) CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "default-1" ) CONFIG_COMMANDS="$CONFIG_COMMANDS default-1" ;; "config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 echo "$as_me: error: invalid argument: $ac_config_target" >&2;} { (exit 1); exit 1; }; };; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason to put it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Create a temporary directory, and hook for its removal unless debugging. $debug || { trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0 trap '{ (exit 1); exit 1; }' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" } || { tmp=./confstat$$-$RANDOM (umask 077 && mkdir $tmp) } || { echo "$me: cannot create a temporary directory in ." >&2 { (exit 1); exit 1; } } _ACEOF cat >>$CONFIG_STATUS <<_ACEOF # # CONFIG_FILES section. # # No need to generate the scripts if there are no CONFIG_FILES. # This happens for instance when ./config.status config.h if test -n "\$CONFIG_FILES"; then # Protect against being on the right side of a sed subst in config.status. sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g; s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF s,@SHELL@,$SHELL,;t t s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t s,@exec_prefix@,$exec_prefix,;t t s,@prefix@,$prefix,;t t s,@program_transform_name@,$program_transform_name,;t t s,@bindir@,$bindir,;t t s,@sbindir@,$sbindir,;t t s,@libexecdir@,$libexecdir,;t t s,@datadir@,$datadir,;t t s,@sysconfdir@,$sysconfdir,;t t s,@sharedstatedir@,$sharedstatedir,;t t s,@localstatedir@,$localstatedir,;t t s,@libdir@,$libdir,;t t s,@includedir@,$includedir,;t t s,@oldincludedir@,$oldincludedir,;t t s,@infodir@,$infodir,;t t s,@mandir@,$mandir,;t t s,@build_alias@,$build_alias,;t t s,@host_alias@,$host_alias,;t t s,@target_alias@,$target_alias,;t t s,@DEFS@,$DEFS,;t t s,@ECHO_C@,$ECHO_C,;t t s,@ECHO_N@,$ECHO_N,;t t s,@ECHO_T@,$ECHO_T,;t t s,@LIBS@,$LIBS,;t t s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t s,@INSTALL_DATA@,$INSTALL_DATA,;t t s,@CYGPATH_W@,$CYGPATH_W,;t t s,@PACKAGE@,$PACKAGE,;t t s,@VERSION@,$VERSION,;t t s,@ACLOCAL@,$ACLOCAL,;t t s,@AUTOCONF@,$AUTOCONF,;t t s,@AUTOMAKE@,$AUTOMAKE,;t t s,@AUTOHEADER@,$AUTOHEADER,;t t s,@MAKEINFO@,$MAKEINFO,;t t s,@AMTAR@,$AMTAR,;t t s,@install_sh@,$install_sh,;t t s,@STRIP@,$STRIP,;t t s,@ac_ct_STRIP@,$ac_ct_STRIP,;t t s,@INSTALL_STRIP_PROGRAM@,$INSTALL_STRIP_PROGRAM,;t t s,@AWK@,$AWK,;t t s,@SET_MAKE@,$SET_MAKE,;t t s,@am__leading_dot@,$am__leading_dot,;t t s,@MAINTAINER_MODE_TRUE@,$MAINTAINER_MODE_TRUE,;t t s,@MAINTAINER_MODE_FALSE@,$MAINTAINER_MODE_FALSE,;t t s,@MAINT@,$MAINT,;t t s,@CC@,$CC,;t t s,@CFLAGS@,$CFLAGS,;t t s,@LDFLAGS@,$LDFLAGS,;t t s,@CPPFLAGS@,$CPPFLAGS,;t t s,@ac_ct_CC@,$ac_ct_CC,;t t s,@EXEEXT@,$EXEEXT,;t t s,@OBJEXT@,$OBJEXT,;t t s,@DEPDIR@,$DEPDIR,;t t s,@am__include@,$am__include,;t t s,@am__quote@,$am__quote,;t t s,@AMDEP_TRUE@,$AMDEP_TRUE,;t t s,@AMDEP_FALSE@,$AMDEP_FALSE,;t t s,@AMDEPBACKSLASH@,$AMDEPBACKSLASH,;t t s,@CCDEPMODE@,$CCDEPMODE,;t t s,@am__fastdepCC_TRUE@,$am__fastdepCC_TRUE,;t t s,@am__fastdepCC_FALSE@,$am__fastdepCC_FALSE,;t t s,@RANLIB@,$RANLIB,;t t s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t s,@QUARRY_WARNINGS@,$QUARRY_WARNINGS,;t t s,@QUARRY_WARNINGS_GTK@,$QUARRY_WARNINGS_GTK,;t t s,@CPP@,$CPP,;t t s,@EGREP@,$EGREP,;t t s,@LIBOBJS@,$LIBOBJS,;t t s,@MKINSTALLDIRS@,$MKINSTALLDIRS,;t t s,@USE_NLS@,$USE_NLS,;t t s,@MSGFMT@,$MSGFMT,;t t s,@GMSGFMT@,$GMSGFMT,;t t s,@XGETTEXT@,$XGETTEXT,;t t s,@MSGMERGE@,$MSGMERGE,;t t s,@build@,$build,;t t s,@build_cpu@,$build_cpu,;t t s,@build_vendor@,$build_vendor,;t t s,@build_os@,$build_os,;t t s,@host@,$host,;t t s,@host_cpu@,$host_cpu,;t t s,@host_vendor@,$host_vendor,;t t s,@host_os@,$host_os,;t t s,@INTL_MACOSX_LIBS@,$INTL_MACOSX_LIBS,;t t s,@LIBICONV@,$LIBICONV,;t t s,@LTLIBICONV@,$LTLIBICONV,;t t s,@INTLLIBS@,$INTLLIBS,;t t s,@LIBINTL@,$LIBINTL,;t t s,@LTLIBINTL@,$LTLIBINTL,;t t s,@POSUB@,$POSUB,;t t s,@have_scrollkeeper@,$have_scrollkeeper,;t t s,@HAVE_SCROLLKEEPER_TRUE@,$HAVE_SCROLLKEEPER_TRUE,;t t s,@HAVE_SCROLLKEEPER_FALSE@,$HAVE_SCROLLKEEPER_FALSE,;t t s,@PKG_CONFIG@,$PKG_CONFIG,;t t s,@ac_pt_PKG_CONFIG@,$ac_pt_PKG_CONFIG,;t t s,@QUARRY_GTK_CFLAGS@,$QUARRY_GTK_CFLAGS,;t t s,@QUARRY_GTK_LIBS@,$QUARRY_GTK_LIBS,;t t s,@QUARRY_GTHREAD_CFLAGS@,$QUARRY_GTHREAD_CFLAGS,;t t s,@QUARRY_GTHREAD_LIBS@,$QUARRY_GTHREAD_LIBS,;t t s,@GLIB_GENMARSHAL@,$GLIB_GENMARSHAL,;t t s,@BUILD_SGF_UTILS_TRUE@,$BUILD_SGF_UTILS_TRUE,;t t s,@BUILD_SGF_UTILS_FALSE@,$BUILD_SGF_UTILS_FALSE,;t t s,@QUARRY_GTK_DEPRECATED_FLAGS@,$QUARRY_GTK_DEPRECATED_FLAGS,;t t s,@DO_SCROLLKEEPER_UPDATE_TRUE@,$DO_SCROLLKEEPER_UPDATE_TRUE,;t t s,@DO_SCROLLKEEPER_UPDATE_FALSE@,$DO_SCROLLKEEPER_UPDATE_FALSE,;t t s,@REGISTER_MIME_TYPES_TRUE@,$REGISTER_MIME_TYPES_TRUE,;t t s,@REGISTER_MIME_TYPES_FALSE@,$REGISTER_MIME_TYPES_FALSE,;t t s,@LTLIBOBJS@,$LTLIBOBJS,;t t CEOF _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # Split the substitutions into bite-sized pieces for seds with # small command number limits, like on Digital OSF/1 and HP-UX. ac_max_sed_lines=48 ac_sed_frag=1 # Number of current file. ac_beg=1 # First line for current file. ac_end=$ac_max_sed_lines # Line after last line for current file. ac_more_lines=: ac_sed_cmds= while $ac_more_lines; do if test $ac_beg -gt 1; then sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag else sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag fi if test ! -s $tmp/subs.frag; then ac_more_lines=false else # The purpose of the label and of the branching condition is to # speed up the sed processing (if there are no `@' at all, there # is no need to browse any of the substitutions). # These are the two extra sed commands mentioned above. (echo ':t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed if test -z "$ac_sed_cmds"; then ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed" else ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed" fi ac_sed_frag=`expr $ac_sed_frag + 1` ac_beg=$ac_end ac_end=`expr $ac_end + $ac_max_sed_lines` fi done if test -z "$ac_sed_cmds"; then ac_sed_cmds=cat fi fi # test -n "$CONFIG_FILES" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". case $ac_file in - | *:- | *:-:* ) # input from stdin cat >$tmp/stdin ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; * ) ac_file_in=$ac_file.in ;; esac # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories. ac_dir=`(dirname "$ac_file") 2>/dev/null || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` { if $as_mkdir_p; then mkdir -p "$ac_dir" else as_dir="$ac_dir" as_dirs= while test ! -d "$as_dir"; do as_dirs="$as_dir $as_dirs" as_dir=`(dirname "$as_dir") 2>/dev/null || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` done test ! -n "$as_dirs" || mkdir $as_dirs fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} { (exit 1); exit 1; }; }; } ac_builddir=. if test "$ac_dir" != .; then ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` # A "../" for each directory in $ac_dir_suffix. ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` else ac_dir_suffix= ac_top_builddir= fi case $srcdir in .) # No --srcdir option. We are building in place. ac_srcdir=. if test -z "$ac_top_builddir"; then ac_top_srcdir=. else ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` fi ;; [\\/]* | ?:[\\/]* ) # Absolute path. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ;; *) # Relative path. ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_builddir$srcdir ;; esac # Do not use `cd foo && pwd` to compute absolute paths, because # the directories may not exist. case `pwd` in .) ac_abs_builddir="$ac_dir";; *) case "$ac_dir" in .) ac_abs_builddir=`pwd`;; [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; *) ac_abs_builddir=`pwd`/"$ac_dir";; esac;; esac case $ac_abs_builddir in .) ac_abs_top_builddir=${ac_top_builddir}.;; *) case ${ac_top_builddir}. in .) ac_abs_top_builddir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; esac;; esac case $ac_abs_builddir in .) ac_abs_srcdir=$ac_srcdir;; *) case $ac_srcdir in .) ac_abs_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; esac;; esac case $ac_abs_builddir in .) ac_abs_top_srcdir=$ac_top_srcdir;; *) case $ac_top_srcdir in .) ac_abs_top_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; esac;; esac case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_builddir$INSTALL ;; esac # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ if test x"$ac_file" = x-; then configure_input= else configure_input="$ac_file. " fi configure_input=$configure_input"Generated from `echo $ac_file_in | sed 's,.*/,,'` by configure." # First look for the input files in the build tree, otherwise in the # src tree. ac_file_inputs=`IFS=: for f in $ac_file_in; do case $f in -) echo $tmp/stdin ;; [\\/$]*) # Absolute (can't be DOS-style, as IFS=:) test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 echo "$as_me: error: cannot find input file: $f" >&2;} { (exit 1); exit 1; }; } echo "$f";; *) # Relative if test -f "$f"; then # Build tree echo "$f" elif test -f "$srcdir/$f"; then # Source tree echo "$srcdir/$f" else # /dev/null tree { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 echo "$as_me: error: cannot find input file: $f" >&2;} { (exit 1); exit 1; }; } fi;; esac done` || { (exit 1); exit 1; } if test x"$ac_file" != x-; then { echo "$as_me:$LINENO: creating $ac_file" >&5 echo "$as_me: creating $ac_file" >&6;} rm -f "$ac_file" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF sed "$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s,@configure_input@,$configure_input,;t t s,@srcdir@,$ac_srcdir,;t t s,@abs_srcdir@,$ac_abs_srcdir,;t t s,@top_srcdir@,$ac_top_srcdir,;t t s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t s,@builddir@,$ac_builddir,;t t s,@abs_builddir@,$ac_abs_builddir,;t t s,@top_builddir@,$ac_top_builddir,;t t s,@abs_top_builddir@,$ac_abs_top_builddir,;t t s,@INSTALL@,$ac_INSTALL,;t t " $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out rm -f $tmp/stdin if test x"$ac_file" != x-; then mv $tmp/out $ac_file else cat $tmp/out rm -f $tmp/out fi done _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # # CONFIG_HEADER section. # # These sed commands are passed to sed as "A NAME B NAME C VALUE D", where # NAME is the cpp macro being defined and VALUE is the value it is being given. # # ac_d sets the value in "#define NAME VALUE" lines. ac_dA='s,^\([ ]*\)#\([ ]*define[ ][ ]*\)' ac_dB='[ ].*$,\1#\2' ac_dC=' ' ac_dD=',;t' # ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE". ac_uA='s,^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' ac_uB='$,\1#\2define\3' ac_uC=' ' ac_uD=',;t' for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". case $ac_file in - | *:- | *:-:* ) # input from stdin cat >$tmp/stdin ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; * ) ac_file_in=$ac_file.in ;; esac test x"$ac_file" != x- && { echo "$as_me:$LINENO: creating $ac_file" >&5 echo "$as_me: creating $ac_file" >&6;} # First look for the input files in the build tree, otherwise in the # src tree. ac_file_inputs=`IFS=: for f in $ac_file_in; do case $f in -) echo $tmp/stdin ;; [\\/$]*) # Absolute (can't be DOS-style, as IFS=:) test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 echo "$as_me: error: cannot find input file: $f" >&2;} { (exit 1); exit 1; }; } # Do quote $f, to prevent DOS paths from being IFS'd. echo "$f";; *) # Relative if test -f "$f"; then # Build tree echo "$f" elif test -f "$srcdir/$f"; then # Source tree echo "$srcdir/$f" else # /dev/null tree { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 echo "$as_me: error: cannot find input file: $f" >&2;} { (exit 1); exit 1; }; } fi;; esac done` || { (exit 1); exit 1; } # Remove the trailing spaces. sed 's/[ ]*$//' $ac_file_inputs >$tmp/in _ACEOF # Transform confdefs.h into two sed scripts, `conftest.defines' and # `conftest.undefs', that substitutes the proper values into # config.h.in to produce config.h. The first handles `#define' # templates, and the second `#undef' templates. # And first: Protect against being on the right side of a sed subst in # config.status. Protect against being in an unquoted here document # in config.status. rm -f conftest.defines conftest.undefs # Using a here document instead of a string reduces the quoting nightmare. # Putting comments in sed scripts is not portable. # # `end' is used to avoid that the second main sed command (meant for # 0-ary CPP macros) applies to n-ary macro definitions. # See the Autoconf documentation for `clear'. cat >confdef2sed.sed <<\_ACEOF s/[\\&,]/\\&/g s,[\\$`],\\&,g t clear : clear s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*\)\(([^)]*)\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp t end s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp : end _ACEOF # If some macros were called several times there might be several times # the same #defines, which is useless. Nevertheless, we may not want to # sort them, since we want the *last* AC-DEFINE to be honored. uniq confdefs.h | sed -n -f confdef2sed.sed >conftest.defines sed 's/ac_d/ac_u/g' conftest.defines >conftest.undefs rm -f confdef2sed.sed # This sed command replaces #undef with comments. This is necessary, for # example, in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. cat >>conftest.undefs <<\_ACEOF s,^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */, _ACEOF # Break up conftest.defines because some shells have a limit on the size # of here documents, and old seds have small limits too (100 cmds). echo ' # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS echo ' if grep "^[ ]*#[ ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS echo ' # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS echo ' :' >>$CONFIG_STATUS rm -f conftest.tail while grep . conftest.defines >/dev/null do # Write a limited-size here document to $tmp/defines.sed. echo ' cat >$tmp/defines.sed <>$CONFIG_STATUS # Speed up: don't consider the non `#define' lines. echo '/^[ ]*#[ ]*define/!b' >>$CONFIG_STATUS # Work around the forget-to-reset-the-flag bug. echo 't clr' >>$CONFIG_STATUS echo ': clr' >>$CONFIG_STATUS sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS echo 'CEOF sed -f $tmp/defines.sed $tmp/in >$tmp/out rm -f $tmp/in mv $tmp/out $tmp/in ' >>$CONFIG_STATUS sed 1,${ac_max_here_lines}d conftest.defines >conftest.tail rm -f conftest.defines mv conftest.tail conftest.defines done rm -f conftest.defines echo ' fi # grep' >>$CONFIG_STATUS echo >>$CONFIG_STATUS # Break up conftest.undefs because some shells have a limit on the size # of here documents, and old seds have small limits too (100 cmds). echo ' # Handle all the #undef templates' >>$CONFIG_STATUS rm -f conftest.tail while grep . conftest.undefs >/dev/null do # Write a limited-size here document to $tmp/undefs.sed. echo ' cat >$tmp/undefs.sed <>$CONFIG_STATUS # Speed up: don't consider the non `#undef' echo '/^[ ]*#[ ]*undef/!b' >>$CONFIG_STATUS # Work around the forget-to-reset-the-flag bug. echo 't clr' >>$CONFIG_STATUS echo ': clr' >>$CONFIG_STATUS sed ${ac_max_here_lines}q conftest.undefs >>$CONFIG_STATUS echo 'CEOF sed -f $tmp/undefs.sed $tmp/in >$tmp/out rm -f $tmp/in mv $tmp/out $tmp/in ' >>$CONFIG_STATUS sed 1,${ac_max_here_lines}d conftest.undefs >conftest.tail rm -f conftest.undefs mv conftest.tail conftest.undefs done rm -f conftest.undefs cat >>$CONFIG_STATUS <<\_ACEOF # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ if test x"$ac_file" = x-; then echo "/* Generated by configure. */" >$tmp/config.h else echo "/* $ac_file. Generated by configure. */" >$tmp/config.h fi cat $tmp/in >>$tmp/config.h rm -f $tmp/in if test x"$ac_file" != x-; then if diff $ac_file $tmp/config.h >/dev/null 2>&1; then { echo "$as_me:$LINENO: $ac_file is unchanged" >&5 echo "$as_me: $ac_file is unchanged" >&6;} else ac_dir=`(dirname "$ac_file") 2>/dev/null || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` { if $as_mkdir_p; then mkdir -p "$ac_dir" else as_dir="$ac_dir" as_dirs= while test ! -d "$as_dir"; do as_dirs="$as_dir $as_dirs" as_dir=`(dirname "$as_dir") 2>/dev/null || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` done test ! -n "$as_dirs" || mkdir $as_dirs fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} { (exit 1); exit 1; }; }; } rm -f $ac_file mv $tmp/config.h $ac_file fi else cat $tmp/config.h rm -f $tmp/config.h fi # Compute $ac_file's index in $config_headers. _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $ac_file | $ac_file:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $ac_file" >`(dirname $ac_file) 2>/dev/null || $as_expr X$ac_file : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X$ac_file : 'X\(//\)[^/]' \| \ X$ac_file : 'X\(//\)$' \| \ X$ac_file : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X$ac_file | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'`/stamp-h$_am_stamp_count done _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # # CONFIG_COMMANDS section. # for ac_file in : $CONFIG_COMMANDS; do test "x$ac_file" = x: && continue ac_dest=`echo "$ac_file" | sed 's,:.*,,'` ac_source=`echo "$ac_file" | sed 's,[^:]*:,,'` ac_dir=`(dirname "$ac_dest") 2>/dev/null || $as_expr X"$ac_dest" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_dest" : 'X\(//\)[^/]' \| \ X"$ac_dest" : 'X\(//\)$' \| \ X"$ac_dest" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$ac_dest" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` { if $as_mkdir_p; then mkdir -p "$ac_dir" else as_dir="$ac_dir" as_dirs= while test ! -d "$as_dir"; do as_dirs="$as_dir $as_dirs" as_dir=`(dirname "$as_dir") 2>/dev/null || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` done test ! -n "$as_dirs" || mkdir $as_dirs fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} { (exit 1); exit 1; }; }; } ac_builddir=. if test "$ac_dir" != .; then ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` # A "../" for each directory in $ac_dir_suffix. ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` else ac_dir_suffix= ac_top_builddir= fi case $srcdir in .) # No --srcdir option. We are building in place. ac_srcdir=. if test -z "$ac_top_builddir"; then ac_top_srcdir=. else ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` fi ;; [\\/]* | ?:[\\/]* ) # Absolute path. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ;; *) # Relative path. ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_builddir$srcdir ;; esac # Do not use `cd foo && pwd` to compute absolute paths, because # the directories may not exist. case `pwd` in .) ac_abs_builddir="$ac_dir";; *) case "$ac_dir" in .) ac_abs_builddir=`pwd`;; [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; *) ac_abs_builddir=`pwd`/"$ac_dir";; esac;; esac case $ac_abs_builddir in .) ac_abs_top_builddir=${ac_top_builddir}.;; *) case ${ac_top_builddir}. in .) ac_abs_top_builddir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; esac;; esac case $ac_abs_builddir in .) ac_abs_srcdir=$ac_srcdir;; *) case $ac_srcdir in .) ac_abs_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; esac;; esac case $ac_abs_builddir in .) ac_abs_top_srcdir=$ac_top_srcdir;; *) case $ac_top_srcdir in .) ac_abs_top_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; esac;; esac { echo "$as_me:$LINENO: executing $ac_dest commands" >&5 echo "$as_me: executing $ac_dest commands" >&6;} case $ac_dest in depfiles ) test x"$AMDEP_TRUE" != x"" || for mf in $CONFIG_FILES; do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named `Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # So let's grep whole file. if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then dirpart=`(dirname "$mf") 2>/dev/null || $as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$mf" : 'X\(//\)[^/]' \| \ X"$mf" : 'X\(//\)$' \| \ X"$mf" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$mf" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` else continue fi grep '^DEP_FILES *= *[^ #]' < "$mf" > /dev/null || continue # Extract the definition of DEP_FILES from the Makefile without # running `make'. DEPDIR=`sed -n -e '/^DEPDIR = / s///p' < "$mf"` test -z "$DEPDIR" && continue # When using ansi2knr, U may be empty or an underscore; expand it U=`sed -n -e '/^U = / s///p' < "$mf"` test -d "$dirpart/$DEPDIR" || mkdir "$dirpart/$DEPDIR" # We invoke sed twice because it is the simplest approach to # changing $(DEPDIR) to its actual value in the expansion. for file in `sed -n -e ' /^DEP_FILES = .*\\\\$/ { s/^DEP_FILES = // :loop s/\\\\$// p n /\\\\$/ b loop p } /^DEP_FILES = / s/^DEP_FILES = //p' < "$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`(dirname "$file") 2>/dev/null || $as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$file" : 'X\(//\)[^/]' \| \ X"$file" : 'X\(//\)$' \| \ X"$file" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` { if $as_mkdir_p; then mkdir -p $dirpart/$fdir else as_dir=$dirpart/$fdir as_dirs= while test ! -d "$as_dir"; do as_dirs="$as_dir $as_dirs" as_dir=`(dirname "$as_dir") 2>/dev/null || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` done test ! -n "$as_dirs" || mkdir $as_dirs fi || { { echo "$as_me:$LINENO: error: cannot create directory $dirpart/$fdir" >&5 echo "$as_me: error: cannot create directory $dirpart/$fdir" >&2;} { (exit 1); exit 1; }; }; } # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done ;; default-1 ) for ac_file in $CONFIG_FILES; do # Support "outfile[:infile[:infile...]]" case "$ac_file" in *:*) ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; esac # PO directories have a Makefile.in generated from Makefile.in.in. case "$ac_file" in */Makefile.in) # Adjust a relative srcdir. ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'` ac_dir_suffix="/`echo "$ac_dir"|sed 's%^\./%%'`" ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'` # In autoconf-2.13 it is called $ac_given_srcdir. # In autoconf-2.50 it is called $srcdir. test -n "$ac_given_srcdir" || ac_given_srcdir="$srcdir" case "$ac_given_srcdir" in .) top_srcdir=`echo $ac_dots|sed 's%/$%%'` ;; /*) top_srcdir="$ac_given_srcdir" ;; *) top_srcdir="$ac_dots$ac_given_srcdir" ;; esac # Treat a directory as a PO directory if and only if it has a # POTFILES.in file. This allows packages to have multiple PO # directories under different names or in different locations. if test -f "$ac_given_srcdir/$ac_dir/POTFILES.in"; then rm -f "$ac_dir/POTFILES" test -n "$as_me" && echo "$as_me: creating $ac_dir/POTFILES" || echo "creating $ac_dir/POTFILES" cat "$ac_given_srcdir/$ac_dir/POTFILES.in" | sed -e "/^#/d" -e "/^[ ]*\$/d" -e "s,.*, $top_srcdir/& \\\\," | sed -e "\$s/\(.*\) \\\\/\1/" > "$ac_dir/POTFILES" POMAKEFILEDEPS="POTFILES.in" # ALL_LINGUAS, POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES depend # on $ac_dir but don't depend on user-specified configuration # parameters. if test -f "$ac_given_srcdir/$ac_dir/LINGUAS"; then # The LINGUAS file contains the set of available languages. if test -n "$OBSOLETE_ALL_LINGUAS"; then test -n "$as_me" && echo "$as_me: setting ALL_LINGUAS in configure.in is obsolete" || echo "setting ALL_LINGUAS in configure.in is obsolete" fi ALL_LINGUAS_=`sed -e "/^#/d" -e "s/#.*//" "$ac_given_srcdir/$ac_dir/LINGUAS"` # Hide the ALL_LINGUAS assigment from automake. eval 'ALL_LINGUAS''=$ALL_LINGUAS_' POMAKEFILEDEPS="$POMAKEFILEDEPS LINGUAS" else # The set of available languages was given in configure.in. eval 'ALL_LINGUAS''=$OBSOLETE_ALL_LINGUAS' fi # Compute POFILES # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).po) # Compute UPDATEPOFILES # as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update) # Compute DUMMYPOFILES # as $(foreach lang, $(ALL_LINGUAS), $(lang).nop) # Compute GMOFILES # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).gmo) case "$ac_given_srcdir" in .) srcdirpre= ;; *) srcdirpre='$(srcdir)/' ;; esac POFILES= UPDATEPOFILES= DUMMYPOFILES= GMOFILES= for lang in $ALL_LINGUAS; do POFILES="$POFILES $srcdirpre$lang.po" UPDATEPOFILES="$UPDATEPOFILES $lang.po-update" DUMMYPOFILES="$DUMMYPOFILES $lang.nop" GMOFILES="$GMOFILES $srcdirpre$lang.gmo" done # CATALOGS depends on both $ac_dir and the user's LINGUAS # environment variable. INST_LINGUAS= if test -n "$ALL_LINGUAS"; then for presentlang in $ALL_LINGUAS; do useit=no if test "%UNSET%" != "$LINGUAS"; then desiredlanguages="$LINGUAS" else desiredlanguages="$ALL_LINGUAS" fi for desiredlang in $desiredlanguages; do # Use the presentlang catalog if desiredlang is # a. equal to presentlang, or # b. a variant of presentlang (because in this case, # presentlang can be used as a fallback for messages # which are not translated in the desiredlang catalog). case "$desiredlang" in "$presentlang"*) useit=yes;; esac done if test $useit = yes; then INST_LINGUAS="$INST_LINGUAS $presentlang" fi done fi CATALOGS= if test -n "$INST_LINGUAS"; then for lang in $INST_LINGUAS; do CATALOGS="$CATALOGS $lang.gmo" done fi test -n "$as_me" && echo "$as_me: creating $ac_dir/Makefile" || echo "creating $ac_dir/Makefile" sed -e "/^POTFILES =/r $ac_dir/POTFILES" -e "/^# Makevars/r $ac_given_srcdir/$ac_dir/Makevars" -e "s|@POFILES@|$POFILES|g" -e "s|@UPDATEPOFILES@|$UPDATEPOFILES|g" -e "s|@DUMMYPOFILES@|$DUMMYPOFILES|g" -e "s|@GMOFILES@|$GMOFILES|g" -e "s|@CATALOGS@|$CATALOGS|g" -e "s|@POMAKEFILEDEPS@|$POMAKEFILEDEPS|g" "$ac_dir/Makefile.in" > "$ac_dir/Makefile" for f in "$ac_given_srcdir/$ac_dir"/Rules-*; do if test -f "$f"; then case "$f" in *.orig | *.bak | *~) ;; *) cat "$f" >> "$ac_dir/Makefile" ;; esac fi done fi ;; esac done ;; esac done _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF { (exit 0); exit 0; } _ACEOF chmod +x $CONFIG_STATUS ac_clean_files=$ac_clean_files_save # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || { (exit 1); exit 1; } fi quarry-0.2.0/AUTHORS0000644000175000017500000000016410076031035012542 0ustar bartbartList of people contributed to Quarry, in chronological order of first contribution. Paul Pogonyshev Martin Holters quarry-0.2.0/COPYING0000644000175000017500000004313310237132720012532 0ustar bartbart GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 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 2 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, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. quarry-0.2.0/ChangeLog0000644000175000017500000002406010530112764013251 0ustar bartbart2006-10-29 Paul Pogonyshev * configure.ac: Quarry version 0.2.0. * README: Update. * NEWS: Update. * TODO: Update. 2006-10-29 Paul Pogonyshev * configure.ac: Quarry version 0.1.20. * NEWS: Update. * TODO: Update. 2006-07-16 Paul Pogonyshev * configure.ac: Quarry version 0.1.19. * NEWS: Update. 2006-07-14 Paul Pogonyshev * configure.ac: Quarry version 0.1.18. * NEWS: Update. * TODO: Update. 2006-07-13 Paul Pogonyshev * THANKS: Also thank Jérémie Knuesel for bug reports. 2006-04-30 Paul Pogonyshev * build: Rename from `aux' to avoid conflicts with system reserved word on Win32 (Cygwin, bug #5836, fastgo@gmail.com.) 2006-03-09 Paul Pogonyshev * configure.ac: Quarry version 0.1.17. * NEWS: Update. * TODO: Update. 2006-02-11 Paul Pogonyshev * configure.ac: Add `--disable-mime-database-update' option. 2006-01-30 Paul Pogonyshev * (Globally: use the new copyright updating scheme suggested by the GNU project, i.e. include all the years when Quarry changed, not particular file changed. Update all relevant files to include years 2005 and 2006.) 2005-10-31 Paul Pogonyshev * configure.ac: Arrange for `DO_SCROLLKEEPER_UPDATE' conditional be defined even if there is no ScrollKeeper (otherwise `configure' doesn't work.) Reported by Heikki Levanto. 2005-10-30 Paul Pogonyshev * configure.ac: Quarry version 0.1.16. * NEWS: Update. * TODO: Update. 2005-09-27 Paul Pogonyshev * README: Replace "Othello" with "Reversi" and generally update. 2005-08-21 Paul Pogonyshev * aux/omf.make: Fix last change. 2005-08-20 Paul Pogonyshev * aux/omf.make: Update to latest version from `gnome-common' module. Honor the new `--disable-scrollkeeper-update' option. * aux/xmldocs.make: Merge in changes from `gnome-common' module. * configure.ac: Generate `data/quarry.desktop'. Add `--disable-scrollkeeper-update' option at request from Michel Salim. Rearrange some options for better grouping in `configure --help' output. 2005-07-15 Paul Pogonyshev * INSTALL: Mention that `po/quarry.pot' can be updated only when configured with `builddir' equal to `srcdir'. * configure.ac (QUARRY_WARNINGS_GTK): Remove `-Wcast-qual' which became a source of annoying warnings recently. * README-TRANSLATORS: New file. 2005-06-27 Paul Pogonyshev * configure.ac: Check size of `int', `double' and `void *' types. 2005-06-17 Paul Pogonyshev * configure.ac: Quarry version 0.1.15. * NEWS: Update. * TODO: Update. 2005-06-16 Paul Pogonyshev * acinclude.m4: Remove file. All the files it contained should be found in `/usr/share/aclocal' or `/usr/local/share/autoconf' if you have `pkg-config' and `gettext' installed. * configure.ac: Add `foreign' and `check-news' arguments to the `AM_INIT_AUTOMAKE' macro. 2005-05-07 Paul Pogonyshev * COPYING: Update to the latest version from www.gnu.org to reflect the change of FSF address. * COPYING-DOC: Likewise. 2005-04-12 Paul Pogonyshev * THANKS: Thank Jérémie Knuesel for the French translation. 2005-03-18 Paul Pogonyshev * aux/list.make (SUFFIXES): Also add `.h' in suffixes to make `rm -f $*.stamp' below work as expected. (LIST_STAMP_FILES, LIST_GENERATED_FILES): New variables, generate from `LIST_FILES' with `make's substitution reference. 2005-03-14 Paul Pogonyshev * configure.ac: Quarry version 0.1.14. * NEWS: Update. 2005-03-13 Paul Pogonyshev * configure.ac: Quarry version 0.1.13. * NEWS: Update. * TODO: Update; * THANKS: Thank Brenn Hill for the new woodgrain texture. * README: Add legal information about `data/textures/wood2.jpg'. 2005-03-12 Paul Pogonyshev * INSTALL: Add `BUILDING IN A SEPARATE DIRECTORY' section. * aux/list.make: New file. 2005-01-22 Paul Pogonyshev * TODO: New file. 2005-01-20 Paul Pogonyshev * README-PACKAGERS: Fix the name of site configuration file. 2005-01-19 Paul Pogonyshev * README-PACKAGERS: New file. * README: General update. Remove `RUNNING QUARRY' section contents and refer readers to the manual instead. 2005-01-17 Arend Bayer * INSTALL: Make system requirements more explicit. 2005-01-15 Paul Pogonyshev * configure.ac: Quarry version 0.1.12. * NEWS: Update. * THANKS: New file. 2005-01-06 Paul Pogonyshev * configure.ac: Quarry version 0.1.11. * NEWS: Update. 2004-12-12 Paul Pogonyshev * configure.ac: Don't generate `Makefile's in `data/markup-themes' subdirectories anymore. 2004-11-30 Paul Pogonyshev * configure.ac: Quarry version 0.1.10. * NEWS: Update. 2004-11-29 Paul Pogonyshev * aux/xmldocs.make: Make XML installation conditional on ScrollKeeper presence. If it is not present, then only install HTML file. * configure.ac: Check if ScrollKeeper package is installed. 2004-10-22 Paul Pogonyshev * configure.ac: Generate `Makefile' in `data/markup-themes/bold'. 2004-10-14 Paul Pogonyshev * configure.ac: Quarry version 0.1.9. * NEWS: Update. * configure.ac: Quarry version 0.1.8. * NEWS: Update. 2004-10-11 Paul Pogonyshev * COPYING-DOC: New file. * help: New directory. * aux/omf.make, aux/xmldocs.make: New files. 2004-10-06 Paul Pogonyshev * configure.ac: Declare `aux/' as auxiliary directory. * aux: New directory, pile auxiliary files there; use this `ChangeLog'. * aux/config.guess: Move from `config.guess'. * aux/config.rpath: Likewise. * aux/config.sub: Likewise. * aux/depcomp: Likewise. * aux/install-sh: Likewise. * aux/missing: Likewise. * aux/mkinstalldirs: Likewise. 2004-09-11 Paul Pogonyshev * NEWS: Add all news from version 0.1.2 to 0.1.7 (change in policy: add news items for development versions too). 2004-08-28 Paul Pogonyshev * configure.ac: Quarry version 0.1.7. 2004-08-21 Paul Pogonyshev * configure.ac: Add GNU gettext configuration macro. * acinclude.m4: Merge in six GNU gettext `.m4' files. * config.guess: New file, from ftp://ftp.gnu.org/pub/gnu/config/. * config.sub: New file, from ftp://ftp.gnu.org/pub/gnu/config/. 2004-08-21 gettextize * config.rpath: New file. * mkinstalldirs: Updated. * po: New directory. 2004-08-20 Paul Pogonyshev * configure.ac: Disable SGF utilities by default: they are not useful yet anyway. 2004-08-18 Paul Pogonyshev * configure.ac: Search for library containing iconv(). 2004-08-15 Paul Pogonyshev * README: Mention new requirement for `librsvg'. * INSTALL: Likewise. * configure.ac: Quarry version 0.1.6. 2004-08-13 Paul Pogonyshev * configure.ac: Generate `Makefile's also in `data/markup-themes' and `data/markup-themes/default'. * configure.ac: Require `librsvg': on the second thought, it is not worth the work to provide an alternative way of generating markup pixbufs. Also, require librsvg 2.5.0 at least, because earlier versions fail to render certain files. 2004-08-09 Paul Pogonyshev * configure.ac: Don't abort configuration if `gthread' library is not installed (optional for Quarry). Configure Quarry to use `librsvg' if it is installed. Define `HAVE_LIBRSVG' in `config.h' if it is. 2004-07-20 Paul Pogonyshev * configure.ac: Quarry version 0.1.5. 2004-07-16 Paul Pogonyshev * configure.ac: Remove `-Wbad-function-cast' from `QUARRY_WARNINGS' and `QUARRY_WARNINGS_GTK', because it yells at `(int) floor(...)'. * configure.ac: Search for library containing floor() and friends (must be `-lm'). * AUTHORS: Add Martin Holters. 2004-05-13 Paul Pogonyshev * README: Add information about GTP engines to `RUNNING QUARRY' section. * README: Add information about how to submit bug descriptions to Gna! bug tracker. * INSTALL: Likewise. * configure.ac: Quarry version 0.1.4 (bug-fix version). 2004-05-12 Paul Pogonyshev * configure.ac: Quarry version 0.1.3. 2004-04-26 Paul Pogonyshev * README: Add information about new files `src/utils/getopt.c', `src/utils/getopt1.c' and `src/utils/getopt.h'. Add information about new files `src/gui-gtk/gtk-color-button.c' and `src/gui-gtk/gtk-color-button.h'. 2004-04-25 Paul Pogonyshev * configure.ac: Fix mail address: , not . * INSTALL: Likewise. * README: Likewise. 2004-04-21 Paul Pogonyshev * configure.ac: Quarry version 0.1.2. * configure.ac: New option `--disable-sgf-utils'. * configure.ac: Convert `dnl' comments to `#' comments as suggested by Autoconf manual. 2004-04-14 Paul Pogonyshev * configure.ac: Add `AM_MAINTAINER_MODE' so that `Makefile's don't try to run Autoconf and/or Automake by default. 2004-04-13 Paul Pogonyshev * configure.ac: Remove `QUARRY_WARNINGS_REDUCED' variable, because `-Wwrite-strings' gives warnings on too many pieces of GTK+ code and it's not worth it to use the flag for some files and not the others. Changes before the project registration on Gna! (2004-04-12) were not logged. Copyright (C) 2004, 2005, 2006 Paul Pogonyshev. Copying and distribution of this file, with or without modification, are permitted provided the copyright notice and this notice are preserved. Local Variables: coding: iso-8859-1 End: quarry-0.2.0/INSTALL0000644000175000017500000000612210266015124012525 0ustar bartbart SYSTEM REQUIREMENTS To compile Quarry you need the following libraries: * GTK+ 2.0 or later (http://gtk.org/download/) * librsvg 2.5 or later (http://ftp.gnome.org/pub/gnome/sources/librsvg/) Note that you need both the libraries, and the header include files, which often come in a separate development pacakge. You should first try to install these from your distribution; otherwise, download them from the locations indicated above. QUARRY INSTALLATION INSTRUCTIONS Untar the sources, `cd' to the directory where you unpacked Quarry and invoke `configure' script: ./configure [OPTIONS] If configure does not succeed, please check whether your system satisfies the requirements listed in the previous section. Now invoke the `make' program: make If it succeeded then you are done. You should now have a binary named `quarry' residing in the `src' directory. If something went wrong, please have a look at the next section. After this, you should install Quarry by typing make install (you may need to login as super-user first). After this, everything should be set up just fine. Note that Quarry binary can be placed anywhere. This means that you can run the copy in your build directory as well the installed one. Also, if you rebuild Quarry, you don't need to reinstall it unless files in `data/' subdirectory has changed or you intend to run the installed binary, not the one in build directory. BUILDING IN A SEPARATE DIRECTORY Starting with version 0.1.13 Quarry supports building in a separate directory. It is not tested thoroughly, but should work just fine. To build Quarry in a separate directory, proceed as usually: mkdir some-build-directory cd some-build-directory path/to/source/directory/configure make make install Your build directory can be named whatever you like; the only requirement is that it is placed outside the source directory. `path/to/source/directory/configure' should be the path to the topmost directory of the distribution (where this file is placed), not to `src/'. However, if you configure Quarry for building in a separate directory, you will not be able to update `po/quarry.pot' file. It depends on some files generated in build process and deficiencies in gettext's infrastructure prevent `make' from finding the files outside the source directory. This is not much of a problem as updating `po/quarry.pot' should only be done by project maintainer, so unless you are about forking Quarry, this should be of no concern to you. INSTALLATION PROBLEMS If Quarry won't configure or compile on your system and you are sure that the system requirements are satisfied, I would certainly like to fix that. See file named README for details on how to report bugs. Remember that the more information you provide, the more likely I will fix the problem. Before sending a bug report, please make sure that GTK+ 2.x is installed: type pkg-config --modversion gtk+-2.0 If the library is installed, it will print the exact version. If it is not, `pkg-config' will tell you that or fail to run at all. Don't forget to include GTK+ version in your bug report. quarry-0.2.0/Makefile.am0000644000175000017500000000023110132563441013525 0ustar bartbart# Process this file with Automake to produce `Makefile.in'. SUBDIRS = \ data \ help \ po \ src EXTRA_DIST = \ COPYING-DOC DISTCLEANFILES = *~ quarry-0.2.0/NEWS0000644000175000017500000003051010530112637012172 0ustar bartbart*** Quarry 0.2.0 ***************************************************** * * * Quarry 0.2.0 features: * * * * * Support for Go, Amazons and Reversi games. * * * * * Nice resizable board (see screen shots.) * * * * * Playing games: * * - GNU Go, GRhino or any other GTP engine can be your opponent. * * - Computer vs. computer and human vs. human games are an * * option too. * * - Good support for time control. * * - Games can be adjourned and later resumed. * * * * * Game records: * * - Game record editor is simple, but supports all standard * * editing commands and has an undo history. * * - All games can be stored in widely supported SGF FF[4] file * * format. * * - Fast and robust parser can read SGF files of any version. * * - In particular, Kogo's Joseki Dictionary can be browsed with * * Quarry. * * - Game tree view allows for easy navigation of game records. * * - Text search in comments is a powerful tool if you know what * * to search for. * * - Go board position can be exported in a format suitable for * * inserting into Sensei's Library. * * - Support for various SGF labels and markup. * * * ********************************************************************** * Some bug-fixes. * Fixed and somewhat expanded manual. * Updated translations: en_GB, fr, pl, ru. --- New in Quarry 0.1.20 --------------------------------------------- * Many bug-fixes, including two crashing bugs on 64-bit platforms. * Significantly expanded manual. * Updated translations: en_GB, ru. --- New in Quarry 0.1.19 --------------------------------------------- * A severe bug fixed in the Polish translation, see bug #6367. --- New in Quarry 0.1.18 --------------------------------------------- * Undo/redo history has been completed and now includes comment and node name changes. * Standard clipboard operations (cut, copy and paste) are supported for game subtrees. * Board diagrams in ASCII and Sensei's format can be copied to clipboard. * Somewhat expanded manual. * Updated translations: en_GB, fr, pl, ru. * Build process improvements, other improvements and bug-fixes. --- New in Quarry 0.1.17 --------------------------------------------- * More features for editing SGF game records: it is now possible to rearrange game tree branches, explicitly set the move number and change the player to move (useful e.g. in problems.) * Game tree view now shows tooltips over nodes. Tooltips display node's move, name and comment text. * Quarry now registers `application/x-go-sgf' MIME type (for SGF game records) during installation. GNOME 2.8+ desktop will pick the type up automatically. However, Quarry cannot associate itself with the type yet... * New translation: Polish (pl), by Robert Stefaniuk. Updated translations: en_GB, ru. * Many bug-fixes and small improvements. --- New in Quarry 0.1.16 --------------------------------------------- * Quarry is now an SGF editor! In addition to features added in 0.1.15 and earlier, it is now possible to create game records without playing a game; undo/redo history has been drastically improved and is now really useful; there is an editing toolbar. However, undo/redo of comments and node names still needs an improvement. * Command to jump straight to a named node. Advantage over text search here is name completion. (Only for GTK+ 2.4 and up.) * Somewhat updated and expanded manual. * New translations: British English (en_GB), Russian (ru.) * Bug-fixes and small improvements. --- New in Quarry 0.1.15 --------------------------------------------- * First stab at making Quarry an SGF editor. New editing commands: deletion of nodes, position setup (arbitrary addition/removal of pieces), SGF markup editing and scoring of Go positions. * As a special editing feature, undo/redo history is supported. However, it is quite crude in this version and will often work not the way you expect. In particular, it completely ignores all properties and concentrates on node addition/removal only. * Support for node names. They are now shown above comments (much like text headers), can be edited and searched the same way comments can be searched. * Added support for GTK+ 2.4 file chooser dialog. You can still opt to use old-style file selection dialog in Preferences. * First translation: French (fr), by Jérémie Knuesel. * Bug-fixes and small improvements. --- New in Quarry 0.1.14 --------------------------------------------- * Two bug-fixes, including fix for #2089, which caused segfaults when adding new GTP engines. --- New in Quarry 0.1.13 --------------------------------------------- * Warning about potential loss of information is no longer shown on file overwriting: there must be no possibility for it anymore. * It is now possible to adjourn and later resume a game. Actually, you can resume any unfinished game, even one stored from another client. * Improved time control handling. In particular, player who runs out of time now actually loses the game. * Improvements in game tree view, including better tracking of current node, clear indication of current tree branch and less flickering. * New, alternative, woodgrain background by Brenn Hill. It is not the default, but you can select it in the Preferences dialog. * Small improvements and bug-fixes. --- New in Quarry 0.1.12 --------------------------------------------- * Bug-fixes in game tree view. In particular, bug #1969 is fixed, which crashed Quarry on many SGF files. --- New in Quarry 0.1.11 --------------------------------------------- * New Game Tree View control provides means of easily navigating game record trees. It looks much like that of cGoban 1 and has similar features. However, it also allows collapsing/expanding individual nodes (by right-clicking) and is much faster. * Basic support for debugging GTP connections from command line. Use it if your engine won't work with Quarry out of the box. * New fancy markup theme "Filled." * Many bug-fixes (including bug #1929) and improvements here and there. --- New in Quarry 0.1.10 --------------------------------------------- * New useful feature: text search in comments. Can be invaluable when browsing through a very large game tree like a joseki dictionary or a GNU Go debug trace. * Much improved displaying of SGF labels. In particular, no more black labels on black stones. * Two toolbars and a pseudo-toolbar are added. Those who prefer more window space can just hide the toolbars. * New markup theme "Bold." Just like the default theme, but with thicker lines. * Many bug-fixes and small improvements. --- New in Quarry 0.1.9 ---------------------------------------------- * Compilation-time error with GTK+ 2.4 fixed (bug #898, mateusz@kaduk.net.) * Minor bug-fixes in game information editing. --- New in Quarry 0.1.8 ---------------------------------------------- * Full support for SGF game information, including editing. * Support for resignation. Most importantly, Quarry now handles resignations by GTP engines. * Support for SGF labels in addition to recently added support for SGF markup. Displaying code still need tweaks to make labels more readable in certain cases. * Quarry is now bundled with documentation. * You can now choose in Preferences dialog whether to save all SGF files in UTF-8 or preserve original encoding. However, support for other encodings is at about the same level as in 0.1.7. * Bug-fixes, better support for earlier GTK+ versions and yet further improved support for locales. --- New in Quarry 0.1.7 ---------------------------------------------- * Partial support for different encodings of SGF files. It is not yet complete, but at least all single-byte encodings should work. * GTP engines now automatically score games they play. (By Martin Holters) * Comments can now be edited. Just modify the text in the comment pane and your changes will be remembered. * Mouse wheel can be used to go back and forth between moves (Suggested by David Gómez). * Othello disks now look like disks, not like Go stones. * Markup appearance is now configurable. * Quarry is internationalized, though there are no translations yet. * Other small improvements and bug-fixes. --- New in Quarry 0.1.6 ---------------------------------------------- * False eyes are now carefully examined and don't yield territory when they shouldn't when scoring Go games. However, sekis are still not handled. * SGF markup is finally displayed on board. Note that if you have customized board background, markup can appear just barely noticeable to you. Markup appearance will be customizeable in the next version. * Many miscellaneous improvements in Preferences dialog. It shouldn't crash anymore. * Board (goban) now visually indicates when it has focus and so when arrow keys without Alt can be used for navigation. * Bug-fixes (including bug #522) and minor improvements. --- New in Quarry 0.1.5 ---------------------------------------------- * Time control. This includes time limit per game, time limit per move and Canadian overtime (also known as Canadian byo-yomi). Of course games without time limits are possible as well. Note that at present if a player runs out of time, he doesn't lose automatically. * Important game information is now displayed under player names. For Go this is the number of captures and the komi. For Othello this is the number of disks a player has on board. * It is now safe to navigate game tree while a game is played. For instance, when you have two GTP engines playing against each other, you can go back to the game beginning and study moves at whatever speed you like. In earlier versions this would lead to a corrupted game. * Bug-fixes, including better support for locales. --- New in Quarry 0.1.4 ---------------------------------------------- * Severe bug in 0.1.3 fixed. --- New in Quarry 0.1.3 ---------------------------------------------- * Support for game rules. This includes board size for all three games and hadicap (both fixed and free) and komi for Go. * Go games can now be scored by the user. Automatic scoring by the playing GTP engines is not yet implemented. * Customizable board appearance (only backround at present, not the pieces). Because of the appearance of certain internal machinery, all three games now look differently by default: Go looks just like before, Amazons has checkerboard pattern and Othello has dark green solid background. * Bug-fixes, including some backports to pre-2.4 GTK+. --- New in Quarry 0.1.2 ---------------------------------------------- * Support for saving SGF files integrated into GUI. * Finally a way to pass when playing Go. * New feature: SGF diff. It will allow to generate difference between two SGF files as a third SGF file. This way you will be able to easily find what has changed between two version of an SGF file as easily as you can find difference between versions of a text file with UNIX `diff' program. At present the feature is far from being really useful. It is added as a proof of concept. Look for program `sgf-diff' in `src/sgf/' if you want to give it a try. * Many bug-fixes. Copyright (C) 2004, 2005, 2006 Paul Pogonyshev. Copying and distribution of this file, with or without modification, are permitted provided the copyright notice and this notice are preserved. Local Variables: coding: iso-8859-1 End: quarry-0.2.0/THANKS0000644000175000017500000000065710455526527012434 0ustar bartbart ACKNOWLEDGMENTS Special thanks go to Arend Bayer for numerous spotted bugs and suggested small improvements. Thanks to Brenn Hill for the `wood2.jpg' woodgrain texture. Thanks to Jérémie Knuesel for the French, historically the first, translation of Quarry and several bug reports. I'd like to thank all other people who provided bug reports, wishes and other useful feedback. Local Variables: coding: iso-8859-1 End: quarry-0.2.0/TODO0000644000175000017500000000427110530112321012156 0ustar bartbart THINGS PLANNED FOR 0.4/1.0 * INTERNET GAME SERVER(S) SUPPORT ** Start with IGS. KGS has proprietary protocol and NNGS/old IGS isn't really used anymore. * PLAYING GAMES ** Optionally display move list. Requires pondering on where to place it, since the right column has no more place... * VIEWING GAME RECORDS ** Display values of various SGF properties (`VA', `BM' etc.) ** Support multiple games in one file, same for editing. ** GAME TREE VIEW *** Maybe add command to narrow to a subtree. * EDITING GAME RECORDS ** Support editing various SGF properties (`VA', `BM' etc.) * BOARD APPEARANCE ** Make Amazons look like chess queens (with SVG.) * GTP SUPPORT ** Add some sort of GTP console for generic GTP engine access. Look at GoGui for an example. ** Add `GTP wrapper' mode. The idea is to sit on a GTP channel, display the board status and keep SGF records of what's going on. This way you can connect an engine to an arbitrary internet GTP server and see the games in Quarry in real-time. * SGF PARSING ** Complete support for charsets. * INTERNAL BOARD CODE ** Score sekis correctly. * GENERAL GUI ** Make the Control Center nicer, with graphics. Requires artistic contributions, therefore postponed from 0.2. * GENERAL ** Drop support for GTK+ 2.0 and 2.2 at least. Remove all related code, obviously. ** Make functions receive `size_t' and `gsize' where appropriate. E.g. string lengths should have these types. Be extra careful with passing through `...'. ** Maybe reimplement everything in C++/Gtkmm? (Loads of work...) HOW TO EDIT THIS FILE When adding a specific to-do item, start it with a verb (``fix'', ``implement'', ``add'' etc.) When adding a placement (for instance, a name of a module) for to-do items, make it a noun or a phrase that acts as a noun and uppercase the entire line to make it stand out. When something has been implemented, delete or update the appropriate entry here, don't mark it with ``done'' or something similar. This file is only meant to track unimplemented, but planned features. Those that have been implemented should be mentioned in NEWS (and in ChangeLog.) Local variables: mode: outline End: quarry-0.2.0/aclocal.m40000644000175000017500000041416010425150125013337 0ustar bartbart# generated automatically by aclocal 1.7.9 -*- Autoconf -*- # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002 # Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. # Do all the work for Automake. -*- Autoconf -*- # This macro actually does too much some checks are only needed if # your package does certain things. But this isn't really a big deal. # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 # Free Software Foundation, Inc. # 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 2, 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, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA # 02111-1307, USA. # serial 10 AC_PREREQ([2.54]) # Autoconf 2.50 wants to disallow AM_ names. We explicitly allow # the ones we care about. m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) # AM_INIT_AUTOMAKE([OPTIONS]) # ----------------------------------------------- # The call with PACKAGE and VERSION arguments is the old style # call (pre autoconf-2.50), which is being phased out. PACKAGE # and VERSION should now be passed to AC_INIT and removed from # the call to AM_INIT_AUTOMAKE. # We support both call styles for the transition. After # the next Automake release, Autoconf can make the AC_INIT # arguments mandatory, and then we can depend on a new Autoconf # release and drop the old call support. AC_DEFUN([AM_INIT_AUTOMAKE], [AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl AC_REQUIRE([AC_PROG_INSTALL])dnl # test to see if srcdir already configured if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi AC_SUBST([CYGPATH_W]) # Define the identity of the package. dnl Distinguish between old-style and new-style calls. m4_ifval([$2], [m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl AC_SUBST([PACKAGE], [$1])dnl AC_SUBST([VERSION], [$2])], [_AM_SET_OPTIONS([$1])dnl AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl _AM_IF_OPTION([no-define],, [AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl # Some tools Automake needs. AC_REQUIRE([AM_SANITY_CHECK])dnl AC_REQUIRE([AC_ARG_PROGRAM])dnl AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version}) AM_MISSING_PROG(AUTOCONF, autoconf) AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version}) AM_MISSING_PROG(AUTOHEADER, autoheader) AM_MISSING_PROG(MAKEINFO, makeinfo) AM_MISSING_PROG(AMTAR, tar) AM_PROG_INSTALL_SH AM_PROG_INSTALL_STRIP # We need awk for the "check" target. The system "awk" is bad on # some platforms. AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AM_SET_LEADING_DOT])dnl _AM_IF_OPTION([no-dependencies],, [AC_PROVIDE_IFELSE([AC_PROG_CC], [_AM_DEPENDENCIES(CC)], [define([AC_PROG_CC], defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl AC_PROVIDE_IFELSE([AC_PROG_CXX], [_AM_DEPENDENCIES(CXX)], [define([AC_PROG_CXX], defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl ]) ]) # When config.status generates a header, we must update the stamp-h file. # This file resides in the same directory as the config header # that is generated. The stamp files are numbered to have different names. # Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the # loop where config.status creates the headers, so we can generate # our stamp files there. AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], [# Compute $1's index in $config_headers. _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $1 | $1:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $1" >`AS_DIRNAME([$1])`/stamp-h[]$_am_stamp_count]) # Copyright 2002 Free Software Foundation, Inc. # 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 2, 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, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA # AM_AUTOMAKE_VERSION(VERSION) # ---------------------------- # Automake X.Y traces this macro to ensure aclocal.m4 has been # generated from the m4 files accompanying Automake X.Y. AC_DEFUN([AM_AUTOMAKE_VERSION],[am__api_version="1.7"]) # AM_SET_CURRENT_AUTOMAKE_VERSION # ------------------------------- # Call AM_AUTOMAKE_VERSION so it can be traced. # This function is AC_REQUIREd by AC_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], [AM_AUTOMAKE_VERSION([1.7.9])]) # Helper functions for option handling. -*- Autoconf -*- # Copyright 2001, 2002 Free Software Foundation, Inc. # 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 2, 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, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA # 02111-1307, USA. # serial 2 # _AM_MANGLE_OPTION(NAME) # ----------------------- AC_DEFUN([_AM_MANGLE_OPTION], [[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) # _AM_SET_OPTION(NAME) # ------------------------------ # Set option NAME. Presently that only means defining a flag for this option. AC_DEFUN([_AM_SET_OPTION], [m4_define(_AM_MANGLE_OPTION([$1]), 1)]) # _AM_SET_OPTIONS(OPTIONS) # ---------------------------------- # OPTIONS is a space-separated list of Automake options. AC_DEFUN([_AM_SET_OPTIONS], [AC_FOREACH([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) # _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) # ------------------------------------------- # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) # # Check to make sure that the build environment is sane. # # Copyright 1996, 1997, 2000, 2001 Free Software Foundation, Inc. # 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 2, 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, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA # 02111-1307, USA. # serial 3 # AM_SANITY_CHECK # --------------- AC_DEFUN([AM_SANITY_CHECK], [AC_MSG_CHECKING([whether build environment is sane]) # Just in case sleep 1 echo timestamp > conftest.file # Do `set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` if test "$[*]" = "X"; then # -L didn't work. set X `ls -t $srcdir/configure conftest.file` fi rm -f conftest.file if test "$[*]" != "X $srcdir/configure conftest.file" \ && test "$[*]" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken alias in your environment]) fi test "$[2]" = conftest.file ) then # Ok. : else AC_MSG_ERROR([newly created file is older than distributed files! Check your system clock]) fi AC_MSG_RESULT(yes)]) # -*- Autoconf -*- # Copyright 1997, 1999, 2000, 2001 Free Software Foundation, Inc. # 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 2, 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, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA # 02111-1307, USA. # serial 3 # AM_MISSING_PROG(NAME, PROGRAM) # ------------------------------ AC_DEFUN([AM_MISSING_PROG], [AC_REQUIRE([AM_MISSING_HAS_RUN]) $1=${$1-"${am_missing_run}$2"} AC_SUBST($1)]) # AM_MISSING_HAS_RUN # ------------------ # Define MISSING if not defined so far and test if it supports --run. # If it does, set am_missing_run to use it, otherwise, to nothing. AC_DEFUN([AM_MISSING_HAS_RUN], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" # Use eval to expand $SHELL if eval "$MISSING --run true"; then am_missing_run="$MISSING --run " else am_missing_run= AC_MSG_WARN([`missing' script is too old or missing]) fi ]) # AM_AUX_DIR_EXPAND # Copyright 2001 Free Software Foundation, Inc. # 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 2, 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, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA # 02111-1307, USA. # For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets # $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to # `$srcdir', `$srcdir/..', or `$srcdir/../..'. # # Of course, Automake must honor this variable whenever it calls a # tool from the auxiliary directory. The problem is that $srcdir (and # therefore $ac_aux_dir as well) can be either absolute or relative, # depending on how configure is run. This is pretty annoying, since # it makes $ac_aux_dir quite unusable in subdirectories: in the top # source directory, any form will work fine, but in subdirectories a # relative path needs to be adjusted first. # # $ac_aux_dir/missing # fails when called from a subdirectory if $ac_aux_dir is relative # $top_srcdir/$ac_aux_dir/missing # fails if $ac_aux_dir is absolute, # fails when called from a subdirectory in a VPATH build with # a relative $ac_aux_dir # # The reason of the latter failure is that $top_srcdir and $ac_aux_dir # are both prefixed by $srcdir. In an in-source build this is usually # harmless because $srcdir is `.', but things will broke when you # start a VPATH build or use an absolute $srcdir. # # So we could use something similar to $top_srcdir/$ac_aux_dir/missing, # iff we strip the leading $srcdir from $ac_aux_dir. That would be: # am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` # and then we would define $MISSING as # MISSING="\${SHELL} $am_aux_dir/missing" # This will work as long as MISSING is not called from configure, because # unfortunately $(top_srcdir) has no meaning in configure. # However there are other variables, like CC, which are often used in # configure, and could therefore not use this "fixed" $ac_aux_dir. # # Another solution, used here, is to always expand $ac_aux_dir to an # absolute PATH. The drawback is that using absolute paths prevent a # configured tree to be moved without reconfiguration. # Rely on autoconf to set up CDPATH properly. AC_PREREQ([2.50]) AC_DEFUN([AM_AUX_DIR_EXPAND], [ # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` ]) # AM_PROG_INSTALL_SH # ------------------ # Define $install_sh. # Copyright 2001 Free Software Foundation, Inc. # 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 2, 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, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA # 02111-1307, USA. AC_DEFUN([AM_PROG_INSTALL_SH], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl install_sh=${install_sh-"$am_aux_dir/install-sh"} AC_SUBST(install_sh)]) # AM_PROG_INSTALL_STRIP # Copyright 2001 Free Software Foundation, Inc. # 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 2, 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, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA # 02111-1307, USA. # One issue with vendor `install' (even GNU) is that you can't # specify the program used to strip binaries. This is especially # annoying in cross-compiling environments, where the build's strip # is unlikely to handle the host's binaries. # Fortunately install-sh will honor a STRIPPROG variable, so we # always use install-sh in `make install-strip', and initialize # STRIPPROG with the value of the STRIP variable (set by the user). AC_DEFUN([AM_PROG_INSTALL_STRIP], [AC_REQUIRE([AM_PROG_INSTALL_SH])dnl # Installed binaries are usually stripped using `strip' when the user # run `make install-strip'. However `strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the `STRIP' environment variable to overrule this program. dnl Don't test for $cross_compiling = yes, because it might be `maybe'. if test "$cross_compiling" != no; then AC_CHECK_TOOL([STRIP], [strip], :) fi INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) # -*- Autoconf -*- # Copyright (C) 2003 Free Software Foundation, Inc. # 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 2, 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, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA # 02111-1307, USA. # serial 1 # Check whether the underlying file-system supports filenames # with a leading dot. For instance MS-DOS doesn't. AC_DEFUN([AM_SET_LEADING_DOT], [rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null AC_SUBST([am__leading_dot])]) # serial 5 -*- Autoconf -*- # Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. # 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 2, 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, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA # 02111-1307, USA. # There are a few dirty hacks below to avoid letting `AC_PROG_CC' be # written in clear, in which case automake, when reading aclocal.m4, # will think it sees a *use*, and therefore will trigger all it's # C support machinery. Also note that it means that autoscan, seeing # CC etc. in the Makefile, will ask for an AC_PROG_CC use... # _AM_DEPENDENCIES(NAME) # ---------------------- # See how the compiler implements dependency checking. # NAME is "CC", "CXX", "GCJ", or "OBJC". # We try a few techniques and use that to set a single cache variable. # # We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was # modified to invoke _AM_DEPENDENCIES(CC); we would have a circular # dependency, and given that the user is not expected to run this macro, # just rely on AC_PROG_CC. AC_DEFUN([_AM_DEPENDENCIES], [AC_REQUIRE([AM_SET_DEPDIR])dnl AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl AC_REQUIRE([AM_MAKE_INCLUDE])dnl AC_REQUIRE([AM_DEP_TRACK])dnl ifelse([$1], CC, [depcc="$CC" am_compiler_list=], [$1], CXX, [depcc="$CXX" am_compiler_list=], [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'], [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'], [depcc="$$1" am_compiler_list=]) AC_CACHE_CHECK([dependency style of $depcc], [am_cv_$1_dependencies_compiler_type], [if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named `D' -- because `-MD' means `put the output # in D'. mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_$1_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` fi for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c : > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf case $depmode in nosideeffect) # after this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; none) break ;; esac # We check with `-c' and `-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle `-M -o', and we need to detect this. if depmode=$depmode \ source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # (even with -Werror). So we grep stderr for any message # that says an option was ignored. if grep 'ignoring option' conftest.err >/dev/null 2>&1; then :; else am_cv_$1_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_$1_dependencies_compiler_type=none fi ]) AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) AM_CONDITIONAL([am__fastdep$1], [ test "x$enable_dependency_tracking" != xno \ && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) ]) # AM_SET_DEPDIR # ------------- # Choose a directory name for dependency files. # This macro is AC_REQUIREd in _AM_DEPENDENCIES AC_DEFUN([AM_SET_DEPDIR], [AC_REQUIRE([AM_SET_LEADING_DOT])dnl AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl ]) # AM_DEP_TRACK # ------------ AC_DEFUN([AM_DEP_TRACK], [AC_ARG_ENABLE(dependency-tracking, [ --disable-dependency-tracking Speeds up one-time builds --enable-dependency-tracking Do not reject slow dependency extractors]) if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' fi AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) AC_SUBST([AMDEPBACKSLASH]) ]) # Generate code to set up dependency tracking. -*- Autoconf -*- # Copyright 1999, 2000, 2001, 2002 Free Software Foundation, Inc. # 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 2, 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, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA # 02111-1307, USA. #serial 2 # _AM_OUTPUT_DEPENDENCY_COMMANDS # ------------------------------ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], [for mf in $CONFIG_FILES; do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named `Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # So let's grep whole file. if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then dirpart=`AS_DIRNAME("$mf")` else continue fi grep '^DEP_FILES *= *[[^ @%:@]]' < "$mf" > /dev/null || continue # Extract the definition of DEP_FILES from the Makefile without # running `make'. DEPDIR=`sed -n -e '/^DEPDIR = / s///p' < "$mf"` test -z "$DEPDIR" && continue # When using ansi2knr, U may be empty or an underscore; expand it U=`sed -n -e '/^U = / s///p' < "$mf"` test -d "$dirpart/$DEPDIR" || mkdir "$dirpart/$DEPDIR" # We invoke sed twice because it is the simplest approach to # changing $(DEPDIR) to its actual value in the expansion. for file in `sed -n -e ' /^DEP_FILES = .*\\\\$/ { s/^DEP_FILES = // :loop s/\\\\$// p n /\\\\$/ b loop p } /^DEP_FILES = / s/^DEP_FILES = //p' < "$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`AS_DIRNAME(["$file"])` AS_MKDIR_P([$dirpart/$fdir]) # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done ])# _AM_OUTPUT_DEPENDENCY_COMMANDS # AM_OUTPUT_DEPENDENCY_COMMANDS # ----------------------------- # This macro should only be invoked once -- use via AC_REQUIRE. # # This code is only required when automatic dependency tracking # is enabled. FIXME. This creates each `.P' file that we will # need in order to bootstrap the dependency handling code. AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], [AC_CONFIG_COMMANDS([depfiles], [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) ]) # Check to see how 'make' treats includes. -*- Autoconf -*- # Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. # 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 2, 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, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA # 02111-1307, USA. # serial 2 # AM_MAKE_INCLUDE() # ----------------- # Check to see how make treats includes. AC_DEFUN([AM_MAKE_INCLUDE], [am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo done .PHONY: am__doit END # If we don't find an include directive, just comment out the code. AC_MSG_CHECKING([for style of include used by $am_make]) am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # We grep out `Entering directory' and `Leaving directory' # messages which can occur if `w' ends up in MAKEFLAGS. # In particular we don't look at `^make:' because GNU make might # be invoked under some other name (usually "gmake"), in which # case it prints its new name instead of `make'. if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then am__include=include am__quote= _am_result=GNU fi # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then am__include=.include am__quote="\"" _am_result=BSD fi fi AC_SUBST([am__include]) AC_SUBST([am__quote]) AC_MSG_RESULT([$_am_result]) rm -f confinc confmf ]) # AM_CONDITIONAL -*- Autoconf -*- # Copyright 1997, 2000, 2001 Free Software Foundation, Inc. # 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 2, 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, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA # 02111-1307, USA. # serial 5 AC_PREREQ(2.52) # AM_CONDITIONAL(NAME, SHELL-CONDITION) # ------------------------------------- # Define a conditional. AC_DEFUN([AM_CONDITIONAL], [ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl AC_SUBST([$1_TRUE]) AC_SUBST([$1_FALSE]) if $2; then $1_TRUE= $1_FALSE='#' else $1_TRUE='#' $1_FALSE= fi AC_CONFIG_COMMANDS_PRE( [if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then AC_MSG_ERROR([conditional "$1" was never defined. Usually this means the macro was only invoked conditionally.]) fi])]) # Add --enable-maintainer-mode option to configure. # From Jim Meyering # Copyright 1996, 1998, 2000, 2001, 2002 Free Software Foundation, Inc. # 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 2, 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, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA # 02111-1307, USA. # serial 2 AC_DEFUN([AM_MAINTAINER_MODE], [AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles]) dnl maintainer-mode is disabled by default AC_ARG_ENABLE(maintainer-mode, [ --enable-maintainer-mode enable make rules and dependencies not useful (and sometimes confusing) to the casual installer], USE_MAINTAINER_MODE=$enableval, USE_MAINTAINER_MODE=no) AC_MSG_RESULT([$USE_MAINTAINER_MODE]) AM_CONDITIONAL(MAINTAINER_MODE, [test $USE_MAINTAINER_MODE = yes]) MAINT=$MAINTAINER_MODE_TRUE AC_SUBST(MAINT)dnl ] ) AU_DEFUN([jm_MAINTAINER_MODE], [AM_MAINTAINER_MODE]) # gettext.m4 serial 37 (gettext-0.14.4) dnl Copyright (C) 1995-2005 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl dnl This file can can be used in projects which are not available under dnl the GNU General Public License or the GNU Library General Public dnl License but which still want to provide support for the GNU gettext dnl functionality. dnl Please note that the actual code of the GNU gettext library is covered dnl by the GNU Library General Public License, and the rest of the GNU dnl gettext package package is covered by the GNU General Public License. dnl They are *not* in the public domain. dnl Authors: dnl Ulrich Drepper , 1995-2000. dnl Bruno Haible , 2000-2003. dnl Macro to add for using GNU gettext. dnl Usage: AM_GNU_GETTEXT([INTLSYMBOL], [NEEDSYMBOL], [INTLDIR]). dnl INTLSYMBOL can be one of 'external', 'no-libtool', 'use-libtool'. The dnl default (if it is not specified or empty) is 'no-libtool'. dnl INTLSYMBOL should be 'external' for packages with no intl directory, dnl and 'no-libtool' or 'use-libtool' for packages with an intl directory. dnl If INTLSYMBOL is 'use-libtool', then a libtool library dnl $(top_builddir)/intl/libintl.la will be created (shared and/or static, dnl depending on --{enable,disable}-{shared,static} and on the presence of dnl AM-DISABLE-SHARED). If INTLSYMBOL is 'no-libtool', a static library dnl $(top_builddir)/intl/libintl.a will be created. dnl If NEEDSYMBOL is specified and is 'need-ngettext', then GNU gettext dnl implementations (in libc or libintl) without the ngettext() function dnl will be ignored. If NEEDSYMBOL is specified and is dnl 'need-formatstring-macros', then GNU gettext implementations that don't dnl support the ISO C 99 formatstring macros will be ignored. dnl INTLDIR is used to find the intl libraries. If empty, dnl the value `$(top_builddir)/intl/' is used. dnl dnl The result of the configuration is one of three cases: dnl 1) GNU gettext, as included in the intl subdirectory, will be compiled dnl and used. dnl Catalog format: GNU --> install in $(datadir) dnl Catalog extension: .mo after installation, .gmo in source tree dnl 2) GNU gettext has been found in the system's C library. dnl Catalog format: GNU --> install in $(datadir) dnl Catalog extension: .mo after installation, .gmo in source tree dnl 3) No internationalization, always use English msgid. dnl Catalog format: none dnl Catalog extension: none dnl If INTLSYMBOL is 'external', only cases 2 and 3 can occur. dnl The use of .gmo is historical (it was needed to avoid overwriting the dnl GNU format catalogs when building on a platform with an X/Open gettext), dnl but we keep it in order not to force irrelevant filename changes on the dnl maintainers. dnl AC_DEFUN([AM_GNU_GETTEXT], [ dnl Argument checking. ifelse([$1], [], , [ifelse([$1], [external], , [ifelse([$1], [no-libtool], , [ifelse([$1], [use-libtool], , [errprint([ERROR: invalid first argument to AM_GNU_GETTEXT ])])])])]) ifelse([$2], [], , [ifelse([$2], [need-ngettext], , [ifelse([$2], [need-formatstring-macros], , [errprint([ERROR: invalid second argument to AM_GNU_GETTEXT ])])])]) define([gt_included_intl], ifelse([$1], [external], [no], [yes])) define([gt_libtool_suffix_prefix], ifelse([$1], [use-libtool], [l], [])) AC_REQUIRE([AM_PO_SUBDIRS])dnl ifelse(gt_included_intl, yes, [ AC_REQUIRE([AM_INTL_SUBDIR])dnl ]) dnl Prerequisites of AC_LIB_LINKFLAGS_BODY. AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) AC_REQUIRE([AC_LIB_RPATH]) dnl Sometimes libintl requires libiconv, so first search for libiconv. dnl Ideally we would do this search only after the dnl if test "$USE_NLS" = "yes"; then dnl if test "$gt_cv_func_gnugettext_libc" != "yes"; then dnl tests. But if configure.in invokes AM_ICONV after AM_GNU_GETTEXT dnl the configure script would need to contain the same shell code dnl again, outside any 'if'. There are two solutions: dnl - Invoke AM_ICONV_LINKFLAGS_BODY here, outside any 'if'. dnl - Control the expansions in more detail using AC_PROVIDE_IFELSE. dnl Since AC_PROVIDE_IFELSE is only in autoconf >= 2.52 and not dnl documented, we avoid it. ifelse(gt_included_intl, yes, , [ AC_REQUIRE([AM_ICONV_LINKFLAGS_BODY]) ]) dnl Sometimes, on MacOS X, libintl requires linking with CoreFoundation. gt_INTL_MACOSX dnl Set USE_NLS. AM_NLS ifelse(gt_included_intl, yes, [ BUILD_INCLUDED_LIBINTL=no USE_INCLUDED_LIBINTL=no ]) LIBINTL= LTLIBINTL= POSUB= dnl If we use NLS figure out what method if test "$USE_NLS" = "yes"; then gt_use_preinstalled_gnugettext=no ifelse(gt_included_intl, yes, [ AC_MSG_CHECKING([whether included gettext is requested]) AC_ARG_WITH(included-gettext, [ --with-included-gettext use the GNU gettext library included here], nls_cv_force_use_gnu_gettext=$withval, nls_cv_force_use_gnu_gettext=no) AC_MSG_RESULT($nls_cv_force_use_gnu_gettext) nls_cv_use_gnu_gettext="$nls_cv_force_use_gnu_gettext" if test "$nls_cv_force_use_gnu_gettext" != "yes"; then ]) dnl User does not insist on using GNU NLS library. Figure out what dnl to use. If GNU gettext is available we use this. Else we have dnl to fall back to GNU NLS library. dnl Add a version number to the cache macros. define([gt_api_version], ifelse([$2], [need-formatstring-macros], 3, ifelse([$2], [need-ngettext], 2, 1))) define([gt_cv_func_gnugettext_libc], [gt_cv_func_gnugettext]gt_api_version[_libc]) define([gt_cv_func_gnugettext_libintl], [gt_cv_func_gnugettext]gt_api_version[_libintl]) AC_CACHE_CHECK([for GNU gettext in libc], gt_cv_func_gnugettext_libc, [AC_TRY_LINK([#include ]ifelse([$2], [need-formatstring-macros], [#ifndef __GNU_GETTEXT_SUPPORTED_REVISION #define __GNU_GETTEXT_SUPPORTED_REVISION(major) ((major) == 0 ? 0 : -1) #endif changequote(,)dnl typedef int array [2 * (__GNU_GETTEXT_SUPPORTED_REVISION(0) >= 1) - 1]; changequote([,])dnl ], [])[extern int _nl_msg_cat_cntr; extern int *_nl_domain_bindings;], [bindtextdomain ("", ""); return * gettext ("")]ifelse([$2], [need-ngettext], [ + * ngettext ("", "", 0)], [])[ + _nl_msg_cat_cntr + *_nl_domain_bindings], gt_cv_func_gnugettext_libc=yes, gt_cv_func_gnugettext_libc=no)]) if test "$gt_cv_func_gnugettext_libc" != "yes"; then dnl Sometimes libintl requires libiconv, so first search for libiconv. ifelse(gt_included_intl, yes, , [ AM_ICONV_LINK ]) dnl Search for libintl and define LIBINTL, LTLIBINTL and INCINTL dnl accordingly. Don't use AC_LIB_LINKFLAGS_BODY([intl],[iconv]) dnl because that would add "-liconv" to LIBINTL and LTLIBINTL dnl even if libiconv doesn't exist. AC_LIB_LINKFLAGS_BODY([intl]) AC_CACHE_CHECK([for GNU gettext in libintl], gt_cv_func_gnugettext_libintl, [gt_save_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS $INCINTL" gt_save_LIBS="$LIBS" LIBS="$LIBS $LIBINTL" dnl Now see whether libintl exists and does not depend on libiconv. AC_TRY_LINK([#include ]ifelse([$2], [need-formatstring-macros], [#ifndef __GNU_GETTEXT_SUPPORTED_REVISION #define __GNU_GETTEXT_SUPPORTED_REVISION(major) ((major) == 0 ? 0 : -1) #endif changequote(,)dnl typedef int array [2 * (__GNU_GETTEXT_SUPPORTED_REVISION(0) >= 1) - 1]; changequote([,])dnl ], [])[extern int _nl_msg_cat_cntr; extern #ifdef __cplusplus "C" #endif const char *_nl_expand_alias (const char *);], [bindtextdomain ("", ""); return * gettext ("")]ifelse([$2], [need-ngettext], [ + * ngettext ("", "", 0)], [])[ + _nl_msg_cat_cntr + *_nl_expand_alias ("")], gt_cv_func_gnugettext_libintl=yes, gt_cv_func_gnugettext_libintl=no) dnl Now see whether libintl exists and depends on libiconv. if test "$gt_cv_func_gnugettext_libintl" != yes && test -n "$LIBICONV"; then LIBS="$LIBS $LIBICONV" AC_TRY_LINK([#include ]ifelse([$2], [need-formatstring-macros], [#ifndef __GNU_GETTEXT_SUPPORTED_REVISION #define __GNU_GETTEXT_SUPPORTED_REVISION(major) ((major) == 0 ? 0 : -1) #endif changequote(,)dnl typedef int array [2 * (__GNU_GETTEXT_SUPPORTED_REVISION(0) >= 1) - 1]; changequote([,])dnl ], [])[extern int _nl_msg_cat_cntr; extern #ifdef __cplusplus "C" #endif const char *_nl_expand_alias (const char *);], [bindtextdomain ("", ""); return * gettext ("")]ifelse([$2], [need-ngettext], [ + * ngettext ("", "", 0)], [])[ + _nl_msg_cat_cntr + *_nl_expand_alias ("")], [LIBINTL="$LIBINTL $LIBICONV" LTLIBINTL="$LTLIBINTL $LTLIBICONV" gt_cv_func_gnugettext_libintl=yes ]) fi CPPFLAGS="$gt_save_CPPFLAGS" LIBS="$gt_save_LIBS"]) fi dnl If an already present or preinstalled GNU gettext() is found, dnl use it. But if this macro is used in GNU gettext, and GNU dnl gettext is already preinstalled in libintl, we update this dnl libintl. (Cf. the install rule in intl/Makefile.in.) if test "$gt_cv_func_gnugettext_libc" = "yes" \ || { test "$gt_cv_func_gnugettext_libintl" = "yes" \ && test "$PACKAGE" != gettext-runtime \ && test "$PACKAGE" != gettext-tools; }; then gt_use_preinstalled_gnugettext=yes else dnl Reset the values set by searching for libintl. LIBINTL= LTLIBINTL= INCINTL= fi ifelse(gt_included_intl, yes, [ if test "$gt_use_preinstalled_gnugettext" != "yes"; then dnl GNU gettext is not found in the C library. dnl Fall back on included GNU gettext library. nls_cv_use_gnu_gettext=yes fi fi if test "$nls_cv_use_gnu_gettext" = "yes"; then dnl Mark actions used to generate GNU NLS library. BUILD_INCLUDED_LIBINTL=yes USE_INCLUDED_LIBINTL=yes LIBINTL="ifelse([$3],[],\${top_builddir}/intl,[$3])/libintl.[]gt_libtool_suffix_prefix[]a $LIBICONV" LTLIBINTL="ifelse([$3],[],\${top_builddir}/intl,[$3])/libintl.[]gt_libtool_suffix_prefix[]a $LTLIBICONV" LIBS=`echo " $LIBS " | sed -e 's/ -lintl / /' -e 's/^ //' -e 's/ $//'` fi CATOBJEXT= if test "$gt_use_preinstalled_gnugettext" = "yes" \ || test "$nls_cv_use_gnu_gettext" = "yes"; then dnl Mark actions to use GNU gettext tools. CATOBJEXT=.gmo fi ]) if test -n "$INTL_MACOSX_LIBS"; then if test "$gt_use_preinstalled_gnugettext" = "yes" \ || test "$nls_cv_use_gnu_gettext" = "yes"; then dnl Some extra flags are needed during linking. LIBINTL="$LIBINTL $INTL_MACOSX_LIBS" LTLIBINTL="$LTLIBINTL $INTL_MACOSX_LIBS" fi fi if test "$gt_use_preinstalled_gnugettext" = "yes" \ || test "$nls_cv_use_gnu_gettext" = "yes"; then AC_DEFINE(ENABLE_NLS, 1, [Define to 1 if translation of program messages to the user's native language is requested.]) else USE_NLS=no fi fi AC_MSG_CHECKING([whether to use NLS]) AC_MSG_RESULT([$USE_NLS]) if test "$USE_NLS" = "yes"; then AC_MSG_CHECKING([where the gettext function comes from]) if test "$gt_use_preinstalled_gnugettext" = "yes"; then if test "$gt_cv_func_gnugettext_libintl" = "yes"; then gt_source="external libintl" else gt_source="libc" fi else gt_source="included intl directory" fi AC_MSG_RESULT([$gt_source]) fi if test "$USE_NLS" = "yes"; then if test "$gt_use_preinstalled_gnugettext" = "yes"; then if test "$gt_cv_func_gnugettext_libintl" = "yes"; then AC_MSG_CHECKING([how to link with libintl]) AC_MSG_RESULT([$LIBINTL]) AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCINTL]) fi dnl For backward compatibility. Some packages may be using this. AC_DEFINE(HAVE_GETTEXT, 1, [Define if the GNU gettext() function is already present or preinstalled.]) AC_DEFINE(HAVE_DCGETTEXT, 1, [Define if the GNU dcgettext() function is already present or preinstalled.]) fi dnl We need to process the po/ directory. POSUB=po fi ifelse(gt_included_intl, yes, [ dnl If this is used in GNU gettext we have to set BUILD_INCLUDED_LIBINTL dnl to 'yes' because some of the testsuite requires it. if test "$PACKAGE" = gettext-runtime || test "$PACKAGE" = gettext-tools; then BUILD_INCLUDED_LIBINTL=yes fi dnl Make all variables we use known to autoconf. AC_SUBST(BUILD_INCLUDED_LIBINTL) AC_SUBST(USE_INCLUDED_LIBINTL) AC_SUBST(CATOBJEXT) dnl For backward compatibility. Some configure.ins may be using this. nls_cv_header_intl= nls_cv_header_libgt= dnl For backward compatibility. Some Makefiles may be using this. DATADIRNAME=share AC_SUBST(DATADIRNAME) dnl For backward compatibility. Some Makefiles may be using this. INSTOBJEXT=.mo AC_SUBST(INSTOBJEXT) dnl For backward compatibility. Some Makefiles may be using this. GENCAT=gencat AC_SUBST(GENCAT) dnl For backward compatibility. Some Makefiles may be using this. INTLOBJS= if test "$USE_INCLUDED_LIBINTL" = yes; then INTLOBJS="\$(GETTOBJS)" fi AC_SUBST(INTLOBJS) dnl Enable libtool support if the surrounding package wishes it. INTL_LIBTOOL_SUFFIX_PREFIX=gt_libtool_suffix_prefix AC_SUBST(INTL_LIBTOOL_SUFFIX_PREFIX) ]) dnl For backward compatibility. Some Makefiles may be using this. INTLLIBS="$LIBINTL" AC_SUBST(INTLLIBS) dnl Make all documented variables known to autoconf. AC_SUBST(LIBINTL) AC_SUBST(LTLIBINTL) AC_SUBST(POSUB) ]) dnl Checks for all prerequisites of the intl subdirectory, dnl except for INTL_LIBTOOL_SUFFIX_PREFIX (and possibly LIBTOOL), INTLOBJS, dnl USE_INCLUDED_LIBINTL, BUILD_INCLUDED_LIBINTL. AC_DEFUN([AM_INTL_SUBDIR], [ AC_REQUIRE([AC_PROG_INSTALL])dnl AC_REQUIRE([AM_MKINSTALLDIRS])dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([gt_GLIBC2])dnl AC_REQUIRE([AC_PROG_RANLIB])dnl AC_REQUIRE([AC_ISC_POSIX])dnl AC_REQUIRE([AC_HEADER_STDC])dnl AC_REQUIRE([AC_C_CONST])dnl AC_REQUIRE([bh_C_SIGNED])dnl AC_REQUIRE([AC_C_INLINE])dnl AC_REQUIRE([AC_TYPE_OFF_T])dnl AC_REQUIRE([AC_TYPE_SIZE_T])dnl AC_REQUIRE([gl_AC_TYPE_LONG_LONG])dnl AC_REQUIRE([gt_TYPE_LONGDOUBLE])dnl AC_REQUIRE([gt_TYPE_WCHAR_T])dnl AC_REQUIRE([gt_TYPE_WINT_T])dnl AC_REQUIRE([gl_AC_HEADER_INTTYPES_H]) AC_REQUIRE([gl_AC_HEADER_STDINT_H]) AC_REQUIRE([gt_TYPE_INTMAX_T]) AC_REQUIRE([gt_PRINTF_POSIX]) AC_REQUIRE([AC_FUNC_ALLOCA])dnl AC_REQUIRE([AC_FUNC_MMAP])dnl AC_REQUIRE([gl_GLIBC21])dnl AC_REQUIRE([gt_INTDIV0])dnl AC_REQUIRE([gl_AC_TYPE_UINTMAX_T])dnl AC_REQUIRE([gt_HEADER_INTTYPES_H])dnl AC_REQUIRE([gt_INTTYPES_PRI])dnl AC_REQUIRE([gl_XSIZE])dnl AC_REQUIRE([gt_INTL_MACOSX])dnl AC_CHECK_TYPE([ptrdiff_t], , [AC_DEFINE([ptrdiff_t], [long], [Define as the type of the result of subtracting two pointers, if the system doesn't define it.]) ]) AC_CHECK_HEADERS([argz.h limits.h locale.h nl_types.h malloc.h stddef.h \ stdlib.h string.h unistd.h sys/param.h]) AC_CHECK_FUNCS([asprintf fwprintf getcwd getegid geteuid getgid getuid \ mempcpy munmap putenv setenv setlocale snprintf stpcpy strcasecmp strdup \ strtoul tsearch wcslen __argz_count __argz_stringify __argz_next \ __fsetlocking]) dnl Use the _snprintf function only if it is declared (because on NetBSD it dnl is defined as a weak alias of snprintf; we prefer to use the latter). gt_CHECK_DECL(_snprintf, [#include ]) gt_CHECK_DECL(_snwprintf, [#include ]) dnl Use the *_unlocked functions only if they are declared. dnl (because some of them were defined without being declared in Solaris dnl 2.5.1 but were removed in Solaris 2.6, whereas we want binaries built dnl on Solaris 2.5.1 to run on Solaris 2.6). dnl Don't use AC_CHECK_DECLS because it isn't supported in autoconf-2.13. gt_CHECK_DECL(feof_unlocked, [#include ]) gt_CHECK_DECL(fgets_unlocked, [#include ]) gt_CHECK_DECL(getc_unlocked, [#include ]) case $gt_cv_func_printf_posix in *yes) HAVE_POSIX_PRINTF=1 ;; *) HAVE_POSIX_PRINTF=0 ;; esac AC_SUBST([HAVE_POSIX_PRINTF]) if test "$ac_cv_func_asprintf" = yes; then HAVE_ASPRINTF=1 else HAVE_ASPRINTF=0 fi AC_SUBST([HAVE_ASPRINTF]) if test "$ac_cv_func_snprintf" = yes; then HAVE_SNPRINTF=1 else HAVE_SNPRINTF=0 fi AC_SUBST([HAVE_SNPRINTF]) if test "$ac_cv_func_wprintf" = yes; then HAVE_WPRINTF=1 else HAVE_WPRINTF=0 fi AC_SUBST([HAVE_WPRINTF]) AM_ICONV AM_LANGINFO_CODESET if test $ac_cv_header_locale_h = yes; then gt_LC_MESSAGES fi if test -n "$INTL_MACOSX_LIBS"; then CPPFLAGS="$CPPFLAGS -I/System/Library/Frameworks/CoreFoundation.framework/Headers" fi dnl intl/plural.c is generated from intl/plural.y. It requires bison, dnl because plural.y uses bison specific features. It requires at least dnl bison-1.26 because earlier versions generate a plural.c that doesn't dnl compile. dnl bison is only needed for the maintainer (who touches plural.y). But in dnl order to avoid separate Makefiles or --enable-maintainer-mode, we put dnl the rule in general Makefile. Now, some people carelessly touch the dnl files or have a broken "make" program, hence the plural.c rule will dnl sometimes fire. To avoid an error, defines BISON to ":" if it is not dnl present or too old. AC_CHECK_PROGS([INTLBISON], [bison]) if test -z "$INTLBISON"; then ac_verc_fail=yes else dnl Found it, now check the version. AC_MSG_CHECKING([version of bison]) changequote(<<,>>)dnl ac_prog_version=`$INTLBISON --version 2>&1 | sed -n 's/^.*GNU Bison.* \([0-9]*\.[0-9.]*\).*$/\1/p'` case $ac_prog_version in '') ac_prog_version="v. ?.??, bad"; ac_verc_fail=yes;; 1.2[6-9]* | 1.[3-9][0-9]* | [2-9].*) changequote([,])dnl ac_prog_version="$ac_prog_version, ok"; ac_verc_fail=no;; *) ac_prog_version="$ac_prog_version, bad"; ac_verc_fail=yes;; esac AC_MSG_RESULT([$ac_prog_version]) fi if test $ac_verc_fail = yes; then INTLBISON=: fi ]) dnl Checks for special options needed on MacOS X. dnl Defines INTL_MACOSX_LIBS. AC_DEFUN([gt_INTL_MACOSX], [ dnl Check for API introduced in MacOS X 10.2. AC_CACHE_CHECK([for CFPreferencesCopyAppValue], gt_cv_func_CFPreferencesCopyAppValue, [gt_save_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS -I/System/Library/Frameworks/CoreFoundation.framework/Headers" gt_save_LIBS="$LIBS" LIBS="$LIBS -framework CoreFoundation" AC_TRY_LINK([#include ], [CFPreferencesCopyAppValue(NULL, NULL)], [gt_cv_func_CFPreferencesCopyAppValue=yes], [gt_cv_func_CFPreferencesCopyAppValue=no]) CPPFLAGS="$gt_save_CPPFLAGS" LIBS="$gt_save_LIBS"]) if test $gt_cv_func_CFPreferencesCopyAppValue = yes; then AC_DEFINE([HAVE_CFPREFERENCESCOPYAPPVALUE], 1, [Define to 1 if you have the MacOS X function CFPreferencesCopyAppValue in the CoreFoundation framework.]) fi dnl Check for API introduced in MacOS X 10.3. AC_CACHE_CHECK([for CFLocaleCopyCurrent], gt_cv_func_CFLocaleCopyCurrent, [gt_save_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS -I/System/Library/Frameworks/CoreFoundation.framework/Headers" gt_save_LIBS="$LIBS" LIBS="$LIBS -framework CoreFoundation" AC_TRY_LINK([#include ], [CFLocaleCopyCurrent();], [gt_cv_func_CFLocaleCopyCurrent=yes], [gt_cv_func_CFLocaleCopyCurrent=no]) CPPFLAGS="$gt_save_CPPFLAGS" LIBS="$gt_save_LIBS"]) if test $gt_cv_func_CFLocaleCopyCurrent = yes; then AC_DEFINE([HAVE_CFLOCALECOPYCURRENT], 1, [Define to 1 if you have the MacOS X function CFLocaleCopyCurrent in the CoreFoundation framework.]) fi INTL_MACOSX_LIBS= if test $gt_cv_func_CFPreferencesCopyAppValue = yes || test $gt_cv_func_CFLocaleCopyCurrent = yes; then INTL_MACOSX_LIBS="-Wl,-framework -Wl,CoreFoundation" fi AC_SUBST([INTL_MACOSX_LIBS]) ]) dnl gt_CHECK_DECL(FUNC, INCLUDES) dnl Check whether a function is declared. AC_DEFUN([gt_CHECK_DECL], [ AC_CACHE_CHECK([whether $1 is declared], ac_cv_have_decl_$1, [AC_TRY_COMPILE([$2], [ #ifndef $1 char *p = (char *) $1; #endif ], ac_cv_have_decl_$1=yes, ac_cv_have_decl_$1=no)]) if test $ac_cv_have_decl_$1 = yes; then gt_value=1 else gt_value=0 fi AC_DEFINE_UNQUOTED([HAVE_DECL_]translit($1, [a-z], [A-Z]), [$gt_value], [Define to 1 if you have the declaration of `$1', and to 0 if you don't.]) ]) dnl Usage: AM_GNU_GETTEXT_VERSION([gettext-version]) AC_DEFUN([AM_GNU_GETTEXT_VERSION], []) # po.m4 serial 7 (gettext-0.14.3) dnl Copyright (C) 1995-2005 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl dnl This file can can be used in projects which are not available under dnl the GNU General Public License or the GNU Library General Public dnl License but which still want to provide support for the GNU gettext dnl functionality. dnl Please note that the actual code of the GNU gettext library is covered dnl by the GNU Library General Public License, and the rest of the GNU dnl gettext package package is covered by the GNU General Public License. dnl They are *not* in the public domain. dnl Authors: dnl Ulrich Drepper , 1995-2000. dnl Bruno Haible , 2000-2003. AC_PREREQ(2.50) dnl Checks for all prerequisites of the po subdirectory. AC_DEFUN([AM_PO_SUBDIRS], [ AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AC_PROG_INSTALL])dnl AC_REQUIRE([AM_MKINSTALLDIRS])dnl AC_REQUIRE([AM_NLS])dnl dnl Perform the following tests also if --disable-nls has been given, dnl because they are needed for "make dist" to work. dnl Search for GNU msgfmt in the PATH. dnl The first test excludes Solaris msgfmt and early GNU msgfmt versions. dnl The second test excludes FreeBSD msgfmt. AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt, [$ac_dir/$ac_word --statistics /dev/null >&]AS_MESSAGE_LOG_FD[ 2>&1 && (if $ac_dir/$ac_word --statistics /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi)], :) AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT) dnl Search for GNU xgettext 0.12 or newer in the PATH. dnl The first test excludes Solaris xgettext and early GNU xgettext versions. dnl The second test excludes FreeBSD xgettext. AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext, [$ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null >&]AS_MESSAGE_LOG_FD[ 2>&1 && (if $ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi)], :) dnl Remove leftover from FreeBSD xgettext call. rm -f messages.po dnl Search for GNU msgmerge 0.11 or newer in the PATH. AM_PATH_PROG_WITH_TEST(MSGMERGE, msgmerge, [$ac_dir/$ac_word --update -q /dev/null /dev/null >&]AS_MESSAGE_LOG_FD[ 2>&1], :) dnl This could go away some day; the PATH_PROG_WITH_TEST already does it. dnl Test whether we really found GNU msgfmt. if test "$GMSGFMT" != ":"; then dnl If it is no GNU msgfmt we define it as : so that the dnl Makefiles still can work. if $GMSGFMT --statistics /dev/null >/dev/null 2>&1 && (if $GMSGFMT --statistics /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi); then : ; else GMSGFMT=`echo "$GMSGFMT" | sed -e 's,^.*/,,'` AC_MSG_RESULT( [found $GMSGFMT program is not GNU msgfmt; ignore it]) GMSGFMT=":" fi fi dnl This could go away some day; the PATH_PROG_WITH_TEST already does it. dnl Test whether we really found GNU xgettext. if test "$XGETTEXT" != ":"; then dnl If it is no GNU xgettext we define it as : so that the dnl Makefiles still can work. if $XGETTEXT --omit-header --copyright-holder= --msgid-bugs-address= /dev/null >/dev/null 2>&1 && (if $XGETTEXT --omit-header --copyright-holder= --msgid-bugs-address= /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi); then : ; else AC_MSG_RESULT( [found xgettext program is not GNU xgettext; ignore it]) XGETTEXT=":" fi dnl Remove leftover from FreeBSD xgettext call. rm -f messages.po fi AC_OUTPUT_COMMANDS([ for ac_file in $CONFIG_FILES; do # Support "outfile[:infile[:infile...]]" case "$ac_file" in *:*) ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; esac # PO directories have a Makefile.in generated from Makefile.in.in. case "$ac_file" in */Makefile.in) # Adjust a relative srcdir. ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'` ac_dir_suffix="/`echo "$ac_dir"|sed 's%^\./%%'`" ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'` # In autoconf-2.13 it is called $ac_given_srcdir. # In autoconf-2.50 it is called $srcdir. test -n "$ac_given_srcdir" || ac_given_srcdir="$srcdir" case "$ac_given_srcdir" in .) top_srcdir=`echo $ac_dots|sed 's%/$%%'` ;; /*) top_srcdir="$ac_given_srcdir" ;; *) top_srcdir="$ac_dots$ac_given_srcdir" ;; esac # Treat a directory as a PO directory if and only if it has a # POTFILES.in file. This allows packages to have multiple PO # directories under different names or in different locations. if test -f "$ac_given_srcdir/$ac_dir/POTFILES.in"; then rm -f "$ac_dir/POTFILES" test -n "$as_me" && echo "$as_me: creating $ac_dir/POTFILES" || echo "creating $ac_dir/POTFILES" cat "$ac_given_srcdir/$ac_dir/POTFILES.in" | sed -e "/^#/d" -e "/^[ ]*\$/d" -e "s,.*, $top_srcdir/& \\\\," | sed -e "\$s/\(.*\) \\\\/\1/" > "$ac_dir/POTFILES" POMAKEFILEDEPS="POTFILES.in" # ALL_LINGUAS, POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES depend # on $ac_dir but don't depend on user-specified configuration # parameters. if test -f "$ac_given_srcdir/$ac_dir/LINGUAS"; then # The LINGUAS file contains the set of available languages. if test -n "$OBSOLETE_ALL_LINGUAS"; then test -n "$as_me" && echo "$as_me: setting ALL_LINGUAS in configure.in is obsolete" || echo "setting ALL_LINGUAS in configure.in is obsolete" fi ALL_LINGUAS_=`sed -e "/^#/d" -e "s/#.*//" "$ac_given_srcdir/$ac_dir/LINGUAS"` # Hide the ALL_LINGUAS assigment from automake. eval 'ALL_LINGUAS''=$ALL_LINGUAS_' POMAKEFILEDEPS="$POMAKEFILEDEPS LINGUAS" else # The set of available languages was given in configure.in. eval 'ALL_LINGUAS''=$OBSOLETE_ALL_LINGUAS' fi # Compute POFILES # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).po) # Compute UPDATEPOFILES # as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update) # Compute DUMMYPOFILES # as $(foreach lang, $(ALL_LINGUAS), $(lang).nop) # Compute GMOFILES # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).gmo) case "$ac_given_srcdir" in .) srcdirpre= ;; *) srcdirpre='$(srcdir)/' ;; esac POFILES= UPDATEPOFILES= DUMMYPOFILES= GMOFILES= for lang in $ALL_LINGUAS; do POFILES="$POFILES $srcdirpre$lang.po" UPDATEPOFILES="$UPDATEPOFILES $lang.po-update" DUMMYPOFILES="$DUMMYPOFILES $lang.nop" GMOFILES="$GMOFILES $srcdirpre$lang.gmo" done # CATALOGS depends on both $ac_dir and the user's LINGUAS # environment variable. INST_LINGUAS= if test -n "$ALL_LINGUAS"; then for presentlang in $ALL_LINGUAS; do useit=no if test "%UNSET%" != "$LINGUAS"; then desiredlanguages="$LINGUAS" else desiredlanguages="$ALL_LINGUAS" fi for desiredlang in $desiredlanguages; do # Use the presentlang catalog if desiredlang is # a. equal to presentlang, or # b. a variant of presentlang (because in this case, # presentlang can be used as a fallback for messages # which are not translated in the desiredlang catalog). case "$desiredlang" in "$presentlang"*) useit=yes;; esac done if test $useit = yes; then INST_LINGUAS="$INST_LINGUAS $presentlang" fi done fi CATALOGS= if test -n "$INST_LINGUAS"; then for lang in $INST_LINGUAS; do CATALOGS="$CATALOGS $lang.gmo" done fi test -n "$as_me" && echo "$as_me: creating $ac_dir/Makefile" || echo "creating $ac_dir/Makefile" sed -e "/^POTFILES =/r $ac_dir/POTFILES" -e "/^# Makevars/r $ac_given_srcdir/$ac_dir/Makevars" -e "s|@POFILES@|$POFILES|g" -e "s|@UPDATEPOFILES@|$UPDATEPOFILES|g" -e "s|@DUMMYPOFILES@|$DUMMYPOFILES|g" -e "s|@GMOFILES@|$GMOFILES|g" -e "s|@CATALOGS@|$CATALOGS|g" -e "s|@POMAKEFILEDEPS@|$POMAKEFILEDEPS|g" "$ac_dir/Makefile.in" > "$ac_dir/Makefile" for f in "$ac_given_srcdir/$ac_dir"/Rules-*; do if test -f "$f"; then case "$f" in *.orig | *.bak | *~) ;; *) cat "$f" >> "$ac_dir/Makefile" ;; esac fi done fi ;; esac done], [# Capture the value of obsolete ALL_LINGUAS because we need it to compute # POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES, CATALOGS. But hide it # from automake. eval 'OBSOLETE_ALL_LINGUAS''="$ALL_LINGUAS"' # Capture the value of LINGUAS because we need it to compute CATALOGS. LINGUAS="${LINGUAS-%UNSET%}" ]) ]) dnl Postprocesses a Makefile in a directory containing PO files. AC_DEFUN([AM_POSTPROCESS_PO_MAKEFILE], [ # When this code is run, in config.status, two variables have already been # set: # - OBSOLETE_ALL_LINGUAS is the value of LINGUAS set in configure.in, # - LINGUAS is the value of the environment variable LINGUAS at configure # time. changequote(,)dnl # Adjust a relative srcdir. ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'` ac_dir_suffix="/`echo "$ac_dir"|sed 's%^\./%%'`" ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'` # In autoconf-2.13 it is called $ac_given_srcdir. # In autoconf-2.50 it is called $srcdir. test -n "$ac_given_srcdir" || ac_given_srcdir="$srcdir" case "$ac_given_srcdir" in .) top_srcdir=`echo $ac_dots|sed 's%/$%%'` ;; /*) top_srcdir="$ac_given_srcdir" ;; *) top_srcdir="$ac_dots$ac_given_srcdir" ;; esac # Find a way to echo strings without interpreting backslash. if test "X`(echo '\t') 2>/dev/null`" = 'X\t'; then gt_echo='echo' else if test "X`(printf '%s\n' '\t') 2>/dev/null`" = 'X\t'; then gt_echo='printf %s\n' else echo_func () { cat < "$ac_file.tmp" if grep -l '@TCLCATALOGS@' "$ac_file" > /dev/null; then # Add dependencies that cannot be formulated as a simple suffix rule. for lang in $ALL_LINGUAS; do frobbedlang=`echo $lang | sed -e 's/\..*$//' -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'` cat >> "$ac_file.tmp" < /dev/null; then # Add dependencies that cannot be formulated as a simple suffix rule. for lang in $ALL_LINGUAS; do frobbedlang=`echo $lang | sed -e 's/_/-/g' -e 's/^sr-CS/sr-SP/' -e 's/@latin$/-Latn/' -e 's/@cyrillic$/-Cyrl/' -e 's/^sr-SP$/sr-SP-Latn/' -e 's/^uz-UZ$/uz-UZ-Latn/'` cat >> "$ac_file.tmp" <> "$ac_file.tmp" <, 1995-2000. dnl Bruno Haible , 2000-2003. AC_PREREQ(2.50) AC_DEFUN([AM_NLS], [ AC_MSG_CHECKING([whether NLS is requested]) dnl Default is enabled NLS AC_ARG_ENABLE(nls, [ --disable-nls do not use Native Language Support], USE_NLS=$enableval, USE_NLS=yes) AC_MSG_RESULT($USE_NLS) AC_SUBST(USE_NLS) ]) AC_DEFUN([AM_MKINSTALLDIRS], [ dnl Tell automake >= 1.10 to complain if mkinstalldirs is missing. m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([mkinstalldirs])]) dnl If the AC_CONFIG_AUX_DIR macro for autoconf is used we possibly dnl find the mkinstalldirs script in another subdir but $(top_srcdir). dnl Try to locate it. MKINSTALLDIRS= if test -n "$ac_aux_dir"; then case "$ac_aux_dir" in /*) MKINSTALLDIRS="$ac_aux_dir/mkinstalldirs" ;; *) MKINSTALLDIRS="\$(top_builddir)/$ac_aux_dir/mkinstalldirs" ;; esac fi if test -z "$MKINSTALLDIRS"; then MKINSTALLDIRS="\$(top_srcdir)/mkinstalldirs" fi AC_SUBST(MKINSTALLDIRS) ]) # progtest.m4 serial 4 (gettext-0.14.2) dnl Copyright (C) 1996-2003, 2005 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl dnl This file can can be used in projects which are not available under dnl the GNU General Public License or the GNU Library General Public dnl License but which still want to provide support for the GNU gettext dnl functionality. dnl Please note that the actual code of the GNU gettext library is covered dnl by the GNU Library General Public License, and the rest of the GNU dnl gettext package package is covered by the GNU General Public License. dnl They are *not* in the public domain. dnl Authors: dnl Ulrich Drepper , 1996. AC_PREREQ(2.50) # Search path for a program which passes the given test. dnl AM_PATH_PROG_WITH_TEST(VARIABLE, PROG-TO-CHECK-FOR, dnl TEST-PERFORMED-ON-FOUND_PROGRAM [, VALUE-IF-NOT-FOUND [, PATH]]) AC_DEFUN([AM_PATH_PROG_WITH_TEST], [ # Prepare PATH_SEPARATOR. # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi # Find out how to test for executable files. Don't use a zero-byte file, # as systems may use methods other than mode bits to determine executability. cat >conf$$.file <<_ASEOF #! /bin/sh exit 0 _ASEOF chmod +x conf$$.file if test -x conf$$.file >/dev/null 2>&1; then ac_executable_p="test -x" else ac_executable_p="test -f" fi rm -f conf$$.file # Extract the first word of "$2", so it can be a program name with args. set dummy $2; ac_word=[$]2 AC_MSG_CHECKING([for $ac_word]) AC_CACHE_VAL(ac_cv_path_$1, [case "[$]$1" in [[\\/]]* | ?:[[\\/]]*) ac_cv_path_$1="[$]$1" # Let the user override the test with a path. ;; *) ac_save_IFS="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in ifelse([$5], , $PATH, [$5]); do IFS="$ac_save_IFS" test -z "$ac_dir" && ac_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $ac_executable_p "$ac_dir/$ac_word$ac_exec_ext"; then echo "$as_me: trying $ac_dir/$ac_word..." >&AS_MESSAGE_LOG_FD if [$3]; then ac_cv_path_$1="$ac_dir/$ac_word$ac_exec_ext" break 2 fi fi done done IFS="$ac_save_IFS" dnl If no 4th arg is given, leave the cache variable unset, dnl so AC_PATH_PROGS will keep looking. ifelse([$4], , , [ test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$4" ])dnl ;; esac])dnl $1="$ac_cv_path_$1" if test ifelse([$4], , [-n "[$]$1"], ["[$]$1" != "$4"]); then AC_MSG_RESULT([$]$1) else AC_MSG_RESULT(no) fi AC_SUBST($1)dnl ]) # lib-prefix.m4 serial 4 (gettext-0.14.2) dnl Copyright (C) 2001-2005 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Bruno Haible. dnl AC_LIB_ARG_WITH is synonymous to AC_ARG_WITH in autoconf-2.13, and dnl similar to AC_ARG_WITH in autoconf 2.52...2.57 except that is doesn't dnl require excessive bracketing. ifdef([AC_HELP_STRING], [AC_DEFUN([AC_LIB_ARG_WITH], [AC_ARG_WITH([$1],[[$2]],[$3],[$4])])], [AC_DEFUN([AC_][LIB_ARG_WITH], [AC_ARG_WITH([$1],[$2],[$3],[$4])])]) dnl AC_LIB_PREFIX adds to the CPPFLAGS and LDFLAGS the flags that are needed dnl to access previously installed libraries. The basic assumption is that dnl a user will want packages to use other packages he previously installed dnl with the same --prefix option. dnl This macro is not needed if only AC_LIB_LINKFLAGS is used to locate dnl libraries, but is otherwise very convenient. AC_DEFUN([AC_LIB_PREFIX], [ AC_BEFORE([$0], [AC_LIB_LINKFLAGS]) AC_REQUIRE([AC_PROG_CC]) AC_REQUIRE([AC_CANONICAL_HOST]) AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) dnl By default, look in $includedir and $libdir. use_additional=yes AC_LIB_WITH_FINAL_PREFIX([ eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" ]) AC_LIB_ARG_WITH([lib-prefix], [ --with-lib-prefix[=DIR] search for libraries in DIR/include and DIR/lib --without-lib-prefix don't search for libraries in includedir and libdir], [ if test "X$withval" = "Xno"; then use_additional=no else if test "X$withval" = "X"; then AC_LIB_WITH_FINAL_PREFIX([ eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" ]) else additional_includedir="$withval/include" additional_libdir="$withval/lib" fi fi ]) if test $use_additional = yes; then dnl Potentially add $additional_includedir to $CPPFLAGS. dnl But don't add it dnl 1. if it's the standard /usr/include, dnl 2. if it's already present in $CPPFLAGS, dnl 3. if it's /usr/local/include and we are using GCC on Linux, dnl 4. if it doesn't exist as a directory. if test "X$additional_includedir" != "X/usr/include"; then haveit= for x in $CPPFLAGS; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) if test "X$x" = "X-I$additional_includedir"; then haveit=yes break fi done if test -z "$haveit"; then if test "X$additional_includedir" = "X/usr/local/include"; then if test -n "$GCC"; then case $host_os in linux* | gnu* | k*bsd*-gnu) haveit=yes;; esac fi fi if test -z "$haveit"; then if test -d "$additional_includedir"; then dnl Really add $additional_includedir to $CPPFLAGS. CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }-I$additional_includedir" fi fi fi fi dnl Potentially add $additional_libdir to $LDFLAGS. dnl But don't add it dnl 1. if it's the standard /usr/lib, dnl 2. if it's already present in $LDFLAGS, dnl 3. if it's /usr/local/lib and we are using GCC on Linux, dnl 4. if it doesn't exist as a directory. if test "X$additional_libdir" != "X/usr/lib"; then haveit= for x in $LDFLAGS; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) if test "X$x" = "X-L$additional_libdir"; then haveit=yes break fi done if test -z "$haveit"; then if test "X$additional_libdir" = "X/usr/local/lib"; then if test -n "$GCC"; then case $host_os in linux*) haveit=yes;; esac fi fi if test -z "$haveit"; then if test -d "$additional_libdir"; then dnl Really add $additional_libdir to $LDFLAGS. LDFLAGS="${LDFLAGS}${LDFLAGS:+ }-L$additional_libdir" fi fi fi fi fi ]) dnl AC_LIB_PREPARE_PREFIX creates variables acl_final_prefix, dnl acl_final_exec_prefix, containing the values to which $prefix and dnl $exec_prefix will expand at the end of the configure script. AC_DEFUN([AC_LIB_PREPARE_PREFIX], [ dnl Unfortunately, prefix and exec_prefix get only finally determined dnl at the end of configure. if test "X$prefix" = "XNONE"; then acl_final_prefix="$ac_default_prefix" else acl_final_prefix="$prefix" fi if test "X$exec_prefix" = "XNONE"; then acl_final_exec_prefix='${prefix}' else acl_final_exec_prefix="$exec_prefix" fi acl_save_prefix="$prefix" prefix="$acl_final_prefix" eval acl_final_exec_prefix=\"$acl_final_exec_prefix\" prefix="$acl_save_prefix" ]) dnl AC_LIB_WITH_FINAL_PREFIX([statement]) evaluates statement, with the dnl variables prefix and exec_prefix bound to the values they will have dnl at the end of the configure script. AC_DEFUN([AC_LIB_WITH_FINAL_PREFIX], [ acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" $1 exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" ]) # lib-link.m4 serial 6 (gettext-0.14.3) dnl Copyright (C) 2001-2005 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Bruno Haible. AC_PREREQ(2.50) dnl AC_LIB_LINKFLAGS(name [, dependencies]) searches for libname and dnl the libraries corresponding to explicit and implicit dependencies. dnl Sets and AC_SUBSTs the LIB${NAME} and LTLIB${NAME} variables and dnl augments the CPPFLAGS variable. AC_DEFUN([AC_LIB_LINKFLAGS], [ AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) AC_REQUIRE([AC_LIB_RPATH]) define([Name],[translit([$1],[./-], [___])]) define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-], [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])]) AC_CACHE_CHECK([how to link with lib[]$1], [ac_cv_lib[]Name[]_libs], [ AC_LIB_LINKFLAGS_BODY([$1], [$2]) ac_cv_lib[]Name[]_libs="$LIB[]NAME" ac_cv_lib[]Name[]_ltlibs="$LTLIB[]NAME" ac_cv_lib[]Name[]_cppflags="$INC[]NAME" ]) LIB[]NAME="$ac_cv_lib[]Name[]_libs" LTLIB[]NAME="$ac_cv_lib[]Name[]_ltlibs" INC[]NAME="$ac_cv_lib[]Name[]_cppflags" AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME) AC_SUBST([LIB]NAME) AC_SUBST([LTLIB]NAME) dnl Also set HAVE_LIB[]NAME so that AC_LIB_HAVE_LINKFLAGS can reuse the dnl results of this search when this library appears as a dependency. HAVE_LIB[]NAME=yes undefine([Name]) undefine([NAME]) ]) dnl AC_LIB_HAVE_LINKFLAGS(name, dependencies, includes, testcode) dnl searches for libname and the libraries corresponding to explicit and dnl implicit dependencies, together with the specified include files and dnl the ability to compile and link the specified testcode. If found, it dnl sets and AC_SUBSTs HAVE_LIB${NAME}=yes and the LIB${NAME} and dnl LTLIB${NAME} variables and augments the CPPFLAGS variable, and dnl #defines HAVE_LIB${NAME} to 1. Otherwise, it sets and AC_SUBSTs dnl HAVE_LIB${NAME}=no and LIB${NAME} and LTLIB${NAME} to empty. AC_DEFUN([AC_LIB_HAVE_LINKFLAGS], [ AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) AC_REQUIRE([AC_LIB_RPATH]) define([Name],[translit([$1],[./-], [___])]) define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-], [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])]) dnl Search for lib[]Name and define LIB[]NAME, LTLIB[]NAME and INC[]NAME dnl accordingly. AC_LIB_LINKFLAGS_BODY([$1], [$2]) dnl Add $INC[]NAME to CPPFLAGS before performing the following checks, dnl because if the user has installed lib[]Name and not disabled its use dnl via --without-lib[]Name-prefix, he wants to use it. ac_save_CPPFLAGS="$CPPFLAGS" AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME) AC_CACHE_CHECK([for lib[]$1], [ac_cv_lib[]Name], [ ac_save_LIBS="$LIBS" LIBS="$LIBS $LIB[]NAME" AC_TRY_LINK([$3], [$4], [ac_cv_lib[]Name=yes], [ac_cv_lib[]Name=no]) LIBS="$ac_save_LIBS" ]) if test "$ac_cv_lib[]Name" = yes; then HAVE_LIB[]NAME=yes AC_DEFINE([HAVE_LIB]NAME, 1, [Define if you have the $1 library.]) AC_MSG_CHECKING([how to link with lib[]$1]) AC_MSG_RESULT([$LIB[]NAME]) else HAVE_LIB[]NAME=no dnl If $LIB[]NAME didn't lead to a usable library, we don't need dnl $INC[]NAME either. CPPFLAGS="$ac_save_CPPFLAGS" LIB[]NAME= LTLIB[]NAME= fi AC_SUBST([HAVE_LIB]NAME) AC_SUBST([LIB]NAME) AC_SUBST([LTLIB]NAME) undefine([Name]) undefine([NAME]) ]) dnl Determine the platform dependent parameters needed to use rpath: dnl libext, shlibext, hardcode_libdir_flag_spec, hardcode_libdir_separator, dnl hardcode_direct, hardcode_minus_L. AC_DEFUN([AC_LIB_RPATH], [ dnl Tell automake >= 1.10 to complain if config.rpath is missing. m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([config.rpath])]) AC_REQUIRE([AC_PROG_CC]) dnl we use $CC, $GCC, $LDFLAGS AC_REQUIRE([AC_LIB_PROG_LD]) dnl we use $LD, $with_gnu_ld AC_REQUIRE([AC_CANONICAL_HOST]) dnl we use $host AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT]) dnl we use $ac_aux_dir AC_CACHE_CHECK([for shared library run path origin], acl_cv_rpath, [ CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \ ${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh . ./conftest.sh rm -f ./conftest.sh acl_cv_rpath=done ]) wl="$acl_cv_wl" libext="$acl_cv_libext" shlibext="$acl_cv_shlibext" hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec" hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator" hardcode_direct="$acl_cv_hardcode_direct" hardcode_minus_L="$acl_cv_hardcode_minus_L" dnl Determine whether the user wants rpath handling at all. AC_ARG_ENABLE(rpath, [ --disable-rpath do not hardcode runtime library paths], :, enable_rpath=yes) ]) dnl AC_LIB_LINKFLAGS_BODY(name [, dependencies]) searches for libname and dnl the libraries corresponding to explicit and implicit dependencies. dnl Sets the LIB${NAME}, LTLIB${NAME} and INC${NAME} variables. AC_DEFUN([AC_LIB_LINKFLAGS_BODY], [ define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-], [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])]) dnl By default, look in $includedir and $libdir. use_additional=yes AC_LIB_WITH_FINAL_PREFIX([ eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" ]) AC_LIB_ARG_WITH([lib$1-prefix], [ --with-lib$1-prefix[=DIR] search for lib$1 in DIR/include and DIR/lib --without-lib$1-prefix don't search for lib$1 in includedir and libdir], [ if test "X$withval" = "Xno"; then use_additional=no else if test "X$withval" = "X"; then AC_LIB_WITH_FINAL_PREFIX([ eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" ]) else additional_includedir="$withval/include" additional_libdir="$withval/lib" fi fi ]) dnl Search the library and its dependencies in $additional_libdir and dnl $LDFLAGS. Using breadth-first-seach. LIB[]NAME= LTLIB[]NAME= INC[]NAME= rpathdirs= ltrpathdirs= names_already_handled= names_next_round='$1 $2' while test -n "$names_next_round"; do names_this_round="$names_next_round" names_next_round= for name in $names_this_round; do already_handled= for n in $names_already_handled; do if test "$n" = "$name"; then already_handled=yes break fi done if test -z "$already_handled"; then names_already_handled="$names_already_handled $name" dnl See if it was already located by an earlier AC_LIB_LINKFLAGS dnl or AC_LIB_HAVE_LINKFLAGS call. uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'` eval value=\"\$HAVE_LIB$uppername\" if test -n "$value"; then if test "$value" = yes; then eval value=\"\$LIB$uppername\" test -z "$value" || LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$value" eval value=\"\$LTLIB$uppername\" test -z "$value" || LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$value" else dnl An earlier call to AC_LIB_HAVE_LINKFLAGS has determined dnl that this library doesn't exist. So just drop it. : fi else dnl Search the library lib$name in $additional_libdir and $LDFLAGS dnl and the already constructed $LIBNAME/$LTLIBNAME. found_dir= found_la= found_so= found_a= if test $use_additional = yes; then if test -n "$shlibext" && test -f "$additional_libdir/lib$name.$shlibext"; then found_dir="$additional_libdir" found_so="$additional_libdir/lib$name.$shlibext" if test -f "$additional_libdir/lib$name.la"; then found_la="$additional_libdir/lib$name.la" fi else if test -f "$additional_libdir/lib$name.$libext"; then found_dir="$additional_libdir" found_a="$additional_libdir/lib$name.$libext" if test -f "$additional_libdir/lib$name.la"; then found_la="$additional_libdir/lib$name.la" fi fi fi fi if test "X$found_dir" = "X"; then for x in $LDFLAGS $LTLIB[]NAME; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) case "$x" in -L*) dir=`echo "X$x" | sed -e 's/^X-L//'` if test -n "$shlibext" && test -f "$dir/lib$name.$shlibext"; then found_dir="$dir" found_so="$dir/lib$name.$shlibext" if test -f "$dir/lib$name.la"; then found_la="$dir/lib$name.la" fi else if test -f "$dir/lib$name.$libext"; then found_dir="$dir" found_a="$dir/lib$name.$libext" if test -f "$dir/lib$name.la"; then found_la="$dir/lib$name.la" fi fi fi ;; esac if test "X$found_dir" != "X"; then break fi done fi if test "X$found_dir" != "X"; then dnl Found the library. LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$found_dir -l$name" if test "X$found_so" != "X"; then dnl Linking with a shared library. We attempt to hardcode its dnl directory into the executable's runpath, unless it's the dnl standard /usr/lib. if test "$enable_rpath" = no || test "X$found_dir" = "X/usr/lib"; then dnl No hardcoding is needed. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" else dnl Use an explicit option to hardcode DIR into the resulting dnl binary. dnl Potentially add DIR to ltrpathdirs. dnl The ltrpathdirs will be appended to $LTLIBNAME at the end. haveit= for x in $ltrpathdirs; do if test "X$x" = "X$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then ltrpathdirs="$ltrpathdirs $found_dir" fi dnl The hardcoding into $LIBNAME is system dependent. if test "$hardcode_direct" = yes; then dnl Using DIR/libNAME.so during linking hardcodes DIR into the dnl resulting binary. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" else if test -n "$hardcode_libdir_flag_spec" && test "$hardcode_minus_L" = no; then dnl Use an explicit option to hardcode DIR into the resulting dnl binary. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" dnl Potentially add DIR to rpathdirs. dnl The rpathdirs will be appended to $LIBNAME at the end. haveit= for x in $rpathdirs; do if test "X$x" = "X$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then rpathdirs="$rpathdirs $found_dir" fi else dnl Rely on "-L$found_dir". dnl But don't add it if it's already contained in the LDFLAGS dnl or the already constructed $LIBNAME haveit= for x in $LDFLAGS $LIB[]NAME; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) if test "X$x" = "X-L$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir" fi if test "$hardcode_minus_L" != no; then dnl FIXME: Not sure whether we should use dnl "-L$found_dir -l$name" or "-L$found_dir $found_so" dnl here. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" else dnl We cannot use $hardcode_runpath_var and LD_RUN_PATH dnl here, because this doesn't fit in flags passed to the dnl compiler. So give up. No hardcoding. This affects only dnl very old systems. dnl FIXME: Not sure whether we should use dnl "-L$found_dir -l$name" or "-L$found_dir $found_so" dnl here. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name" fi fi fi fi else if test "X$found_a" != "X"; then dnl Linking with a static library. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_a" else dnl We shouldn't come here, but anyway it's good to have a dnl fallback. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir -l$name" fi fi dnl Assume the include files are nearby. additional_includedir= case "$found_dir" in */lib | */lib/) basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e 's,/lib/*$,,'` additional_includedir="$basedir/include" ;; esac if test "X$additional_includedir" != "X"; then dnl Potentially add $additional_includedir to $INCNAME. dnl But don't add it dnl 1. if it's the standard /usr/include, dnl 2. if it's /usr/local/include and we are using GCC on Linux, dnl 3. if it's already present in $CPPFLAGS or the already dnl constructed $INCNAME, dnl 4. if it doesn't exist as a directory. if test "X$additional_includedir" != "X/usr/include"; then haveit= if test "X$additional_includedir" = "X/usr/local/include"; then if test -n "$GCC"; then case $host_os in linux* | gnu* | k*bsd*-gnu) haveit=yes;; esac fi fi if test -z "$haveit"; then for x in $CPPFLAGS $INC[]NAME; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) if test "X$x" = "X-I$additional_includedir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_includedir"; then dnl Really add $additional_includedir to $INCNAME. INC[]NAME="${INC[]NAME}${INC[]NAME:+ }-I$additional_includedir" fi fi fi fi fi dnl Look for dependencies. if test -n "$found_la"; then dnl Read the .la file. It defines the variables dnl dlname, library_names, old_library, dependency_libs, current, dnl age, revision, installed, dlopen, dlpreopen, libdir. save_libdir="$libdir" case "$found_la" in */* | *\\*) . "$found_la" ;; *) . "./$found_la" ;; esac libdir="$save_libdir" dnl We use only dependency_libs. for dep in $dependency_libs; do case "$dep" in -L*) additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` dnl Potentially add $additional_libdir to $LIBNAME and $LTLIBNAME. dnl But don't add it dnl 1. if it's the standard /usr/lib, dnl 2. if it's /usr/local/lib and we are using GCC on Linux, dnl 3. if it's already present in $LDFLAGS or the already dnl constructed $LIBNAME, dnl 4. if it doesn't exist as a directory. if test "X$additional_libdir" != "X/usr/lib"; then haveit= if test "X$additional_libdir" = "X/usr/local/lib"; then if test -n "$GCC"; then case $host_os in linux* | gnu* | k*bsd*-gnu) haveit=yes;; esac fi fi if test -z "$haveit"; then haveit= for x in $LDFLAGS $LIB[]NAME; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) if test "X$x" = "X-L$additional_libdir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_libdir"; then dnl Really add $additional_libdir to $LIBNAME. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$additional_libdir" fi fi haveit= for x in $LDFLAGS $LTLIB[]NAME; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) if test "X$x" = "X-L$additional_libdir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_libdir"; then dnl Really add $additional_libdir to $LTLIBNAME. LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$additional_libdir" fi fi fi fi ;; -R*) dir=`echo "X$dep" | sed -e 's/^X-R//'` if test "$enable_rpath" != no; then dnl Potentially add DIR to rpathdirs. dnl The rpathdirs will be appended to $LIBNAME at the end. haveit= for x in $rpathdirs; do if test "X$x" = "X$dir"; then haveit=yes break fi done if test -z "$haveit"; then rpathdirs="$rpathdirs $dir" fi dnl Potentially add DIR to ltrpathdirs. dnl The ltrpathdirs will be appended to $LTLIBNAME at the end. haveit= for x in $ltrpathdirs; do if test "X$x" = "X$dir"; then haveit=yes break fi done if test -z "$haveit"; then ltrpathdirs="$ltrpathdirs $dir" fi fi ;; -l*) dnl Handle this in the next round. names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` ;; *.la) dnl Handle this in the next round. Throw away the .la's dnl directory; it is already contained in a preceding -L dnl option. names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` ;; *) dnl Most likely an immediate library name. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$dep" LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$dep" ;; esac done fi else dnl Didn't find the library; assume it is in the system directories dnl known to the linker and runtime loader. (All the system dnl directories known to the linker should also be known to the dnl runtime loader, otherwise the system is severely misconfigured.) LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name" LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-l$name" fi fi fi done done if test "X$rpathdirs" != "X"; then if test -n "$hardcode_libdir_separator"; then dnl Weird platform: only the last -rpath option counts, the user must dnl pass all path elements in one option. We can arrange that for a dnl single library, but not when more than one $LIBNAMEs are used. alldirs= for found_dir in $rpathdirs; do alldirs="${alldirs}${alldirs:+$hardcode_libdir_separator}$found_dir" done dnl Note: hardcode_libdir_flag_spec uses $libdir and $wl. acl_save_libdir="$libdir" libdir="$alldirs" eval flag=\"$hardcode_libdir_flag_spec\" libdir="$acl_save_libdir" LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag" else dnl The -rpath options are cumulative. for found_dir in $rpathdirs; do acl_save_libdir="$libdir" libdir="$found_dir" eval flag=\"$hardcode_libdir_flag_spec\" libdir="$acl_save_libdir" LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag" done fi fi if test "X$ltrpathdirs" != "X"; then dnl When using libtool, the option that works for both libraries and dnl executables is -R. The -R options are cumulative. for found_dir in $ltrpathdirs; do LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-R$found_dir" done fi ]) dnl AC_LIB_APPENDTOVAR(VAR, CONTENTS) appends the elements of CONTENTS to VAR, dnl unless already present in VAR. dnl Works only for CPPFLAGS, not for LIB* variables because that sometimes dnl contains two or three consecutive elements that belong together. AC_DEFUN([AC_LIB_APPENDTOVAR], [ for element in [$2]; do haveit= for x in $[$1]; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) if test "X$x" = "X$element"; then haveit=yes break fi done if test -z "$haveit"; then [$1]="${[$1]}${[$1]:+ }$element" fi done ]) # lib-ld.m4 serial 3 (gettext-0.13) dnl Copyright (C) 1996-2003 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl Subroutines of libtool.m4, dnl with replacements s/AC_/AC_LIB/ and s/lt_cv/acl_cv/ to avoid collision dnl with libtool.m4. dnl From libtool-1.4. Sets the variable with_gnu_ld to yes or no. AC_DEFUN([AC_LIB_PROG_LD_GNU], [AC_CACHE_CHECK([if the linker ($LD) is GNU ld], acl_cv_prog_gnu_ld, [# I'd rather use --version here, but apparently some GNU ld's only accept -v. case `$LD -v 2>&1 conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. AC_MSG_CHECKING([for ld used by GCC]) case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [[\\/]* | [A-Za-z]:[\\/]*)] [re_direlt='/[^/][^/]*/\.\./'] # Canonicalize the path of ld ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'` while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then AC_MSG_CHECKING([for GNU ld]) else AC_MSG_CHECKING([for non-GNU ld]) fi AC_CACHE_VAL(acl_cv_path_LD, [if test -z "$LD"; then IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}" for ac_dir in $PATH; do test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then acl_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some GNU ld's only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$acl_cv_path_LD" -v 2>&1 < /dev/null` in *GNU* | *'with BFD'*) test "$with_gnu_ld" != no && break ;; *) test "$with_gnu_ld" != yes && break ;; esac fi done IFS="$ac_save_ifs" else acl_cv_path_LD="$LD" # Let the user override the test with a path. fi]) LD="$acl_cv_path_LD" if test -n "$LD"; then AC_MSG_RESULT($LD) else AC_MSG_RESULT(no) fi test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH]) AC_LIB_PROG_LD_GNU ]) # iconv.m4 serial AM4 (gettext-0.11.3) dnl Copyright (C) 2000-2002 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Bruno Haible. AC_DEFUN([AM_ICONV_LINKFLAGS_BODY], [ dnl Prerequisites of AC_LIB_LINKFLAGS_BODY. AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) AC_REQUIRE([AC_LIB_RPATH]) dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV dnl accordingly. AC_LIB_LINKFLAGS_BODY([iconv]) ]) AC_DEFUN([AM_ICONV_LINK], [ dnl Some systems have iconv in libc, some have it in libiconv (OSF/1 and dnl those with the standalone portable GNU libiconv installed). dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV dnl accordingly. AC_REQUIRE([AM_ICONV_LINKFLAGS_BODY]) dnl Add $INCICONV to CPPFLAGS before performing the following checks, dnl because if the user has installed libiconv and not disabled its use dnl via --without-libiconv-prefix, he wants to use it. The first dnl AC_TRY_LINK will then fail, the second AC_TRY_LINK will succeed. am_save_CPPFLAGS="$CPPFLAGS" AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCICONV]) AC_CACHE_CHECK(for iconv, am_cv_func_iconv, [ am_cv_func_iconv="no, consider installing GNU libiconv" am_cv_lib_iconv=no AC_TRY_LINK([#include #include ], [iconv_t cd = iconv_open("",""); iconv(cd,NULL,NULL,NULL,NULL); iconv_close(cd);], am_cv_func_iconv=yes) if test "$am_cv_func_iconv" != yes; then am_save_LIBS="$LIBS" LIBS="$LIBS $LIBICONV" AC_TRY_LINK([#include #include ], [iconv_t cd = iconv_open("",""); iconv(cd,NULL,NULL,NULL,NULL); iconv_close(cd);], am_cv_lib_iconv=yes am_cv_func_iconv=yes) LIBS="$am_save_LIBS" fi ]) if test "$am_cv_func_iconv" = yes; then AC_DEFINE(HAVE_ICONV, 1, [Define if you have the iconv() function.]) fi if test "$am_cv_lib_iconv" = yes; then AC_MSG_CHECKING([how to link with libiconv]) AC_MSG_RESULT([$LIBICONV]) else dnl If $LIBICONV didn't lead to a usable library, we don't need $INCICONV dnl either. CPPFLAGS="$am_save_CPPFLAGS" LIBICONV= LTLIBICONV= fi AC_SUBST(LIBICONV) AC_SUBST(LTLIBICONV) ]) AC_DEFUN([AM_ICONV], [ AM_ICONV_LINK if test "$am_cv_func_iconv" = yes; then AC_MSG_CHECKING([for iconv declaration]) AC_CACHE_VAL(am_cv_proto_iconv, [ AC_TRY_COMPILE([ #include #include extern #ifdef __cplusplus "C" #endif #if defined(__STDC__) || defined(__cplusplus) size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft); #else size_t iconv(); #endif ], [], am_cv_proto_iconv_arg1="", am_cv_proto_iconv_arg1="const") am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);"]) am_cv_proto_iconv=`echo "[$]am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'` AC_MSG_RESULT([$]{ac_t:- }[$]am_cv_proto_iconv) AC_DEFINE_UNQUOTED(ICONV_CONST, $am_cv_proto_iconv_arg1, [Define as const if the declaration of iconv() needs const.]) fi ]) # glibc2.m4 serial 1 dnl Copyright (C) 2000-2002, 2004 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. # Test for the GNU C Library, version 2.0 or newer. # From Bruno Haible. AC_DEFUN([gt_GLIBC2], [ AC_CACHE_CHECK(whether we are using the GNU C Library 2 or newer, ac_cv_gnu_library_2, [AC_EGREP_CPP([Lucky GNU user], [ #include #ifdef __GNU_LIBRARY__ #if (__GLIBC__ >= 2) Lucky GNU user #endif #endif ], ac_cv_gnu_library_2=yes, ac_cv_gnu_library_2=no) ] ) AC_SUBST(GLIBC2) GLIBC2="$ac_cv_gnu_library_2" ] ) # isc-posix.m4 serial 2 (gettext-0.11.2) dnl Copyright (C) 1995-2002 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. # This file is not needed with autoconf-2.53 and newer. Remove it in 2005. # This test replaces the one in autoconf. # Currently this macro should have the same name as the autoconf macro # because gettext's gettext.m4 (distributed in the automake package) # still uses it. Otherwise, the use in gettext.m4 makes autoheader # give these diagnostics: # configure.in:556: AC_TRY_COMPILE was called before AC_ISC_POSIX # configure.in:556: AC_TRY_RUN was called before AC_ISC_POSIX undefine([AC_ISC_POSIX]) AC_DEFUN([AC_ISC_POSIX], [ dnl This test replaces the obsolescent AC_ISC_POSIX kludge. AC_CHECK_LIB(cposix, strerror, [LIBS="$LIBS -lcposix"]) ] ) # signed.m4 serial 1 (gettext-0.10.40) dnl Copyright (C) 2001-2002 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Bruno Haible. AC_DEFUN([bh_C_SIGNED], [ AC_CACHE_CHECK([for signed], bh_cv_c_signed, [AC_TRY_COMPILE(, [signed char x;], bh_cv_c_signed=yes, bh_cv_c_signed=no)]) if test $bh_cv_c_signed = no; then AC_DEFINE(signed, , [Define to empty if the C compiler doesn't support this keyword.]) fi ]) # longlong.m4 serial 5 dnl Copyright (C) 1999-2004 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Paul Eggert. # Define HAVE_LONG_LONG if 'long long' works. AC_DEFUN([gl_AC_TYPE_LONG_LONG], [ AC_CACHE_CHECK([for long long], ac_cv_type_long_long, [AC_TRY_LINK([long long ll = 1LL; int i = 63;], [long long llmax = (long long) -1; return ll << i | ll >> i | llmax / ll | llmax % ll;], ac_cv_type_long_long=yes, ac_cv_type_long_long=no)]) if test $ac_cv_type_long_long = yes; then AC_DEFINE(HAVE_LONG_LONG, 1, [Define if you have the 'long long' type.]) fi ]) # longdouble.m4 serial 1 (gettext-0.12) dnl Copyright (C) 2002-2003 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Bruno Haible. dnl Test whether the compiler supports the 'long double' type. dnl Prerequisite: AC_PROG_CC AC_DEFUN([gt_TYPE_LONGDOUBLE], [ AC_CACHE_CHECK([for long double], gt_cv_c_long_double, [if test "$GCC" = yes; then gt_cv_c_long_double=yes else AC_TRY_COMPILE([ /* The Stardent Vistra knows sizeof(long double), but does not support it. */ long double foo = 0.0; /* On Ultrix 4.3 cc, long double is 4 and double is 8. */ int array [2*(sizeof(long double) >= sizeof(double)) - 1]; ], , gt_cv_c_long_double=yes, gt_cv_c_long_double=no) fi]) if test $gt_cv_c_long_double = yes; then AC_DEFINE(HAVE_LONG_DOUBLE, 1, [Define if you have the 'long double' type.]) fi ]) # wchar_t.m4 serial 1 (gettext-0.12) dnl Copyright (C) 2002-2003 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Bruno Haible. dnl Test whether has the 'wchar_t' type. dnl Prerequisite: AC_PROG_CC AC_DEFUN([gt_TYPE_WCHAR_T], [ AC_CACHE_CHECK([for wchar_t], gt_cv_c_wchar_t, [AC_TRY_COMPILE([#include wchar_t foo = (wchar_t)'\0';], , gt_cv_c_wchar_t=yes, gt_cv_c_wchar_t=no)]) if test $gt_cv_c_wchar_t = yes; then AC_DEFINE(HAVE_WCHAR_T, 1, [Define if you have the 'wchar_t' type.]) fi ]) # wint_t.m4 serial 1 (gettext-0.12) dnl Copyright (C) 2003 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Bruno Haible. dnl Test whether has the 'wint_t' type. dnl Prerequisite: AC_PROG_CC AC_DEFUN([gt_TYPE_WINT_T], [ AC_CACHE_CHECK([for wint_t], gt_cv_c_wint_t, [AC_TRY_COMPILE([#include wint_t foo = (wchar_t)'\0';], , gt_cv_c_wint_t=yes, gt_cv_c_wint_t=no)]) if test $gt_cv_c_wint_t = yes; then AC_DEFINE(HAVE_WINT_T, 1, [Define if you have the 'wint_t' type.]) fi ]) # inttypes_h.m4 serial 6 dnl Copyright (C) 1997-2004 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Paul Eggert. # Define HAVE_INTTYPES_H_WITH_UINTMAX if exists, # doesn't clash with , and declares uintmax_t. AC_DEFUN([gl_AC_HEADER_INTTYPES_H], [ AC_CACHE_CHECK([for inttypes.h], gl_cv_header_inttypes_h, [AC_TRY_COMPILE( [#include #include ], [uintmax_t i = (uintmax_t) -1;], gl_cv_header_inttypes_h=yes, gl_cv_header_inttypes_h=no)]) if test $gl_cv_header_inttypes_h = yes; then AC_DEFINE_UNQUOTED(HAVE_INTTYPES_H_WITH_UINTMAX, 1, [Define if exists, doesn't clash with , and declares uintmax_t. ]) fi ]) # stdint_h.m4 serial 5 dnl Copyright (C) 1997-2004 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Paul Eggert. # Define HAVE_STDINT_H_WITH_UINTMAX if exists, # doesn't clash with , and declares uintmax_t. AC_DEFUN([gl_AC_HEADER_STDINT_H], [ AC_CACHE_CHECK([for stdint.h], gl_cv_header_stdint_h, [AC_TRY_COMPILE( [#include #include ], [uintmax_t i = (uintmax_t) -1;], gl_cv_header_stdint_h=yes, gl_cv_header_stdint_h=no)]) if test $gl_cv_header_stdint_h = yes; then AC_DEFINE_UNQUOTED(HAVE_STDINT_H_WITH_UINTMAX, 1, [Define if exists, doesn't clash with , and declares uintmax_t. ]) fi ]) # intmax.m4 serial 2 (gettext-0.14.2) dnl Copyright (C) 2002-2005 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Bruno Haible. dnl Test whether the system has the 'intmax_t' type, but don't attempt to dnl find a replacement if it is lacking. AC_DEFUN([gt_TYPE_INTMAX_T], [ AC_REQUIRE([gl_AC_HEADER_INTTYPES_H]) AC_REQUIRE([gl_AC_HEADER_STDINT_H]) AC_CACHE_CHECK(for intmax_t, gt_cv_c_intmax_t, [AC_TRY_COMPILE([ #include #include #if HAVE_STDINT_H_WITH_UINTMAX #include #endif #if HAVE_INTTYPES_H_WITH_UINTMAX #include #endif ], [intmax_t x = -1;], gt_cv_c_intmax_t=yes, gt_cv_c_intmax_t=no)]) if test $gt_cv_c_intmax_t = yes; then AC_DEFINE(HAVE_INTMAX_T, 1, [Define if you have the 'intmax_t' type in or .]) fi ]) # printf-posix.m4 serial 2 (gettext-0.13.1) dnl Copyright (C) 2003 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Bruno Haible. dnl Test whether the printf() function supports POSIX/XSI format strings with dnl positions. AC_DEFUN([gt_PRINTF_POSIX], [ AC_REQUIRE([AC_PROG_CC]) AC_CACHE_CHECK([whether printf() supports POSIX/XSI format strings], gt_cv_func_printf_posix, [ AC_TRY_RUN([ #include #include /* The string "%2$d %1$d", with dollar characters protected from the shell's dollar expansion (possibly an autoconf bug). */ static char format[] = { '%', '2', '$', 'd', ' ', '%', '1', '$', 'd', '\0' }; static char buf[100]; int main () { sprintf (buf, format, 33, 55); return (strcmp (buf, "55 33") != 0); }], gt_cv_func_printf_posix=yes, gt_cv_func_printf_posix=no, [ AC_EGREP_CPP(notposix, [ #if defined __NetBSD__ || defined _MSC_VER || defined __MINGW32__ || defined __CYGWIN__ notposix #endif ], gt_cv_func_printf_posix="guessing no", gt_cv_func_printf_posix="guessing yes") ]) ]) case $gt_cv_func_printf_posix in *yes) AC_DEFINE(HAVE_POSIX_PRINTF, 1, [Define if your printf() function supports format strings with positions.]) ;; esac ]) # glibc21.m4 serial 3 dnl Copyright (C) 2000-2002, 2004 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. # Test for the GNU C Library, version 2.1 or newer. # From Bruno Haible. AC_DEFUN([gl_GLIBC21], [ AC_CACHE_CHECK(whether we are using the GNU C Library 2.1 or newer, ac_cv_gnu_library_2_1, [AC_EGREP_CPP([Lucky GNU user], [ #include #ifdef __GNU_LIBRARY__ #if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1) || (__GLIBC__ > 2) Lucky GNU user #endif #endif ], ac_cv_gnu_library_2_1=yes, ac_cv_gnu_library_2_1=no) ] ) AC_SUBST(GLIBC21) GLIBC21="$ac_cv_gnu_library_2_1" ] ) # intdiv0.m4 serial 1 (gettext-0.11.3) dnl Copyright (C) 2002 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Bruno Haible. AC_DEFUN([gt_INTDIV0], [ AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_CACHE_CHECK([whether integer division by zero raises SIGFPE], gt_cv_int_divbyzero_sigfpe, [ AC_TRY_RUN([ #include #include static void #ifdef __cplusplus sigfpe_handler (int sig) #else sigfpe_handler (sig) int sig; #endif { /* Exit with code 0 if SIGFPE, with code 1 if any other signal. */ exit (sig != SIGFPE); } int x = 1; int y = 0; int z; int nan; int main () { signal (SIGFPE, sigfpe_handler); /* IRIX and AIX (when "xlc -qcheck" is used) yield signal SIGTRAP. */ #if (defined (__sgi) || defined (_AIX)) && defined (SIGTRAP) signal (SIGTRAP, sigfpe_handler); #endif /* Linux/SPARC yields signal SIGILL. */ #if defined (__sparc__) && defined (__linux__) signal (SIGILL, sigfpe_handler); #endif z = x / y; nan = y / y; exit (1); } ], gt_cv_int_divbyzero_sigfpe=yes, gt_cv_int_divbyzero_sigfpe=no, [ # Guess based on the CPU. case "$host_cpu" in alpha* | i[34567]86 | m68k | s390*) gt_cv_int_divbyzero_sigfpe="guessing yes";; *) gt_cv_int_divbyzero_sigfpe="guessing no";; esac ]) ]) case "$gt_cv_int_divbyzero_sigfpe" in *yes) value=1;; *) value=0;; esac AC_DEFINE_UNQUOTED(INTDIV0_RAISES_SIGFPE, $value, [Define if integer division by zero raises signal SIGFPE.]) ]) # uintmax_t.m4 serial 9 dnl Copyright (C) 1997-2004 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Paul Eggert. AC_PREREQ(2.13) # Define uintmax_t to 'unsigned long' or 'unsigned long long' # if it is not already defined in or . AC_DEFUN([gl_AC_TYPE_UINTMAX_T], [ AC_REQUIRE([gl_AC_HEADER_INTTYPES_H]) AC_REQUIRE([gl_AC_HEADER_STDINT_H]) if test $gl_cv_header_inttypes_h = no && test $gl_cv_header_stdint_h = no; then AC_REQUIRE([gl_AC_TYPE_UNSIGNED_LONG_LONG]) test $ac_cv_type_unsigned_long_long = yes \ && ac_type='unsigned long long' \ || ac_type='unsigned long' AC_DEFINE_UNQUOTED(uintmax_t, $ac_type, [Define to unsigned long or unsigned long long if and don't define.]) else AC_DEFINE(HAVE_UINTMAX_T, 1, [Define if you have the 'uintmax_t' type in or .]) fi ]) # ulonglong.m4 serial 4 dnl Copyright (C) 1999-2004 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Paul Eggert. # Define HAVE_UNSIGNED_LONG_LONG if 'unsigned long long' works. AC_DEFUN([gl_AC_TYPE_UNSIGNED_LONG_LONG], [ AC_CACHE_CHECK([for unsigned long long], ac_cv_type_unsigned_long_long, [AC_TRY_LINK([unsigned long long ull = 1ULL; int i = 63;], [unsigned long long ullmax = (unsigned long long) -1; return ull << i | ull >> i | ullmax / ull | ullmax % ull;], ac_cv_type_unsigned_long_long=yes, ac_cv_type_unsigned_long_long=no)]) if test $ac_cv_type_unsigned_long_long = yes; then AC_DEFINE(HAVE_UNSIGNED_LONG_LONG, 1, [Define if you have the 'unsigned long long' type.]) fi ]) # inttypes.m4 serial 1 (gettext-0.11.4) dnl Copyright (C) 1997-2002 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Paul Eggert. # Define HAVE_INTTYPES_H if exists and doesn't clash with # . AC_DEFUN([gt_HEADER_INTTYPES_H], [ AC_CACHE_CHECK([for inttypes.h], gt_cv_header_inttypes_h, [ AC_TRY_COMPILE( [#include #include ], [], gt_cv_header_inttypes_h=yes, gt_cv_header_inttypes_h=no) ]) if test $gt_cv_header_inttypes_h = yes; then AC_DEFINE_UNQUOTED(HAVE_INTTYPES_H, 1, [Define if exists and doesn't clash with .]) fi ]) # inttypes-pri.m4 serial 1 (gettext-0.11.4) dnl Copyright (C) 1997-2002 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Bruno Haible. # Define PRI_MACROS_BROKEN if exists and defines the PRI* # macros to non-string values. This is the case on AIX 4.3.3. AC_DEFUN([gt_INTTYPES_PRI], [ AC_REQUIRE([gt_HEADER_INTTYPES_H]) if test $gt_cv_header_inttypes_h = yes; then AC_CACHE_CHECK([whether the inttypes.h PRIxNN macros are broken], gt_cv_inttypes_pri_broken, [ AC_TRY_COMPILE([#include #ifdef PRId32 char *p = PRId32; #endif ], [], gt_cv_inttypes_pri_broken=no, gt_cv_inttypes_pri_broken=yes) ]) fi if test "$gt_cv_inttypes_pri_broken" = yes; then AC_DEFINE_UNQUOTED(PRI_MACROS_BROKEN, 1, [Define if exists and defines unusable PRI* macros.]) fi ]) # xsize.m4 serial 3 dnl Copyright (C) 2003-2004 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. AC_DEFUN([gl_XSIZE], [ dnl Prerequisites of lib/xsize.h. AC_REQUIRE([gl_SIZE_MAX]) AC_REQUIRE([AC_C_INLINE]) AC_CHECK_HEADERS(stdint.h) ]) # size_max.m4 serial 2 dnl Copyright (C) 2003 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Bruno Haible. AC_DEFUN([gl_SIZE_MAX], [ AC_CHECK_HEADERS(stdint.h) dnl First test whether the system already has SIZE_MAX. AC_MSG_CHECKING([for SIZE_MAX]) result= AC_EGREP_CPP([Found it], [ #include #if HAVE_STDINT_H #include #endif #ifdef SIZE_MAX Found it #endif ], result=yes) if test -z "$result"; then dnl Define it ourselves. Here we assume that the type 'size_t' is not wider dnl than the type 'unsigned long'. dnl The _AC_COMPUTE_INT macro works up to LONG_MAX, since it uses 'expr', dnl which is guaranteed to work from LONG_MIN to LONG_MAX. _AC_COMPUTE_INT([~(size_t)0 / 10], res_hi, [#include ], result=?) _AC_COMPUTE_INT([~(size_t)0 % 10], res_lo, [#include ], result=?) _AC_COMPUTE_INT([sizeof (size_t) <= sizeof (unsigned int)], fits_in_uint, [#include ], result=?) if test "$fits_in_uint" = 1; then dnl Even though SIZE_MAX fits in an unsigned int, it must be of type dnl 'unsigned long' if the type 'size_t' is the same as 'unsigned long'. AC_TRY_COMPILE([#include extern size_t foo; extern unsigned long foo; ], [], fits_in_uint=0) fi if test -z "$result"; then if test "$fits_in_uint" = 1; then result="$res_hi$res_lo"U else result="$res_hi$res_lo"UL fi else dnl Shouldn't happen, but who knows... result='~(size_t)0' fi fi AC_MSG_RESULT([$result]) if test "$result" != yes; then AC_DEFINE_UNQUOTED([SIZE_MAX], [$result], [Define as the maximum value of type 'size_t', if the system doesn't define it.]) fi ]) # codeset.m4 serial AM1 (gettext-0.10.40) dnl Copyright (C) 2000-2002 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Bruno Haible. AC_DEFUN([AM_LANGINFO_CODESET], [ AC_CACHE_CHECK([for nl_langinfo and CODESET], am_cv_langinfo_codeset, [AC_TRY_LINK([#include ], [char* cs = nl_langinfo(CODESET);], am_cv_langinfo_codeset=yes, am_cv_langinfo_codeset=no) ]) if test $am_cv_langinfo_codeset = yes; then AC_DEFINE(HAVE_LANGINFO_CODESET, 1, [Define if you have and nl_langinfo(CODESET).]) fi ]) # lcmessage.m4 serial 4 (gettext-0.14.2) dnl Copyright (C) 1995-2002, 2004-2005 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl dnl This file can can be used in projects which are not available under dnl the GNU General Public License or the GNU Library General Public dnl License but which still want to provide support for the GNU gettext dnl functionality. dnl Please note that the actual code of the GNU gettext library is covered dnl by the GNU Library General Public License, and the rest of the GNU dnl gettext package package is covered by the GNU General Public License. dnl They are *not* in the public domain. dnl Authors: dnl Ulrich Drepper , 1995. # Check whether LC_MESSAGES is available in . AC_DEFUN([gt_LC_MESSAGES], [ AC_CACHE_CHECK([for LC_MESSAGES], gt_cv_val_LC_MESSAGES, [AC_TRY_LINK([#include ], [return LC_MESSAGES], gt_cv_val_LC_MESSAGES=yes, gt_cv_val_LC_MESSAGES=no)]) if test $gt_cv_val_LC_MESSAGES = yes; then AC_DEFINE(HAVE_LC_MESSAGES, 1, [Define if your file defines LC_MESSAGES.]) fi ]) # pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- # # Copyright © 2004 Scott James Remnant . # # 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 2 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, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # PKG_PROG_PKG_CONFIG([MIN-VERSION]) # ---------------------------------- AC_DEFUN([PKG_PROG_PKG_CONFIG], [m4_pattern_forbid([^_?PKG_[A-Z_]+$]) m4_pattern_allow([^PKG_CONFIG(_PATH)?$]) AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])dnl if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) fi if test -n "$PKG_CONFIG"; then _pkg_min_version=m4_ifval([$1], [$1], [0.9.0]) AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) PKG_CONFIG="" fi fi[]dnl ])# PKG_PROG_PKG_CONFIG # _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) # --------------------------------------------- m4_define([_PKG_CONFIG], [if test "x$ac_cv_env_[]$1[]_set" = "xset"; then pkg_cv_[]$1=$ac_cv_env_[]$1[]_value elif test -n "$PKG_CONFIG"; then if AC_RUN_LOG([$PKG_CONFIG --exists "$3" >/dev/null 2>&1]); then pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` else pkg_failed=yes fi else pkg_failed=untried fi[]dnl ])# _PKG_CONFIG # PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], # [ACTION-IF-NOT-FOUND]) # # # Note that if there is a possibility the first call to # PKG_CHECK_MODULES might not happen, you should be sure to include an # explicit call to PKG_PROG_PKG_CONFIG in your configure.in # # # -------------------------------------------------------------- AC_DEFUN([PKG_CHECK_MODULES], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl pkg_failed=no AC_CACHE_CHECK([for $1][_CFLAGS], [pkg_cv_][$1][_CFLAGS], [_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])]) AC_CACHE_CHECK([for $1][_LIBS], [pkg_cv_][$1][_LIBS], [_PKG_CONFIG([$1][_LIBS], [libs], [$2])]) if test $pkg_failed = yes; then $1[]_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"` # Put the nasty error message in config.log where it belongs echo "$$1[]_PKG_ERRORS" 1>&AS_MESSAGE_LOG_FD ifelse([$4], , [AC_MSG_ERROR(dnl [Package requirements ($2) were not met. Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. Alternatively you may set the $1_CFLAGS and $1_LIBS environment variables to avoid the need to call pkg-config. See the pkg-config man page for more details.])], [$4]) elif test $pkg_failed = untried; then ifelse([$4], , [AC_MSG_FAILURE(dnl [The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. Alternatively you may set the $1_CFLAGS and $1_LIBS environment variables to avoid the need to call pkg-config. See the pkg-config man page for more details. To get pkg-config, see .])], [$4]) else $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS $1[]_LIBS=$pkg_cv_[]$1[]_LIBS ifelse([$3], , :, [$3]) fi[]dnl ])# PKG_CHECK_MODULES quarry-0.2.0/config.h.in0000644000175000017500000000537710261760467013546 0ustar bartbart/* config.h.in. Generated from configure.ac by autoheader. */ /* Define to 1 if translation of program messages to the user's native language is requested. */ #undef ENABLE_NLS /* Define if the GNU dcgettext() function is already present or preinstalled. */ #undef HAVE_DCGETTEXT /* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ #undef HAVE_DOPRNT /* Define to 1 if you have the header file. */ #undef HAVE_FLOAT_H /* Define if the GNU gettext() function is already present or preinstalled. */ #undef HAVE_GETTEXT /* Define if you have the iconv() function. */ #undef HAVE_ICONV /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_LIMITS_H /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* Define to 1 if you have the `memrchr' function. */ #undef HAVE_MEMRCHR /* Define if you have ScrollKeeper package installed. */ #undef HAVE_SCROLLKEEPER /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* Define to 1 if you have the `vprintf' function. */ #undef HAVE_VPRINTF /* The name of the package. */ #undef PACKAGE /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the version of this package. */ #undef PACKAGE_VERSION /* The size of a `double', as computed by sizeof. */ #undef SIZEOF_DOUBLE /* The size of a `int', as computed by sizeof. */ #undef SIZEOF_INT /* The size of a `void *', as computed by sizeof. */ #undef SIZEOF_VOID_P /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS /* The version of the distribution. */ #undef VERSION /* Define to empty if `const' does not conform to ANSI C. */ #undef const /* Define to `__inline__' or `__inline' if that's what the C compiler calls it, or to nothing if 'inline' is not supported under any name. */ #ifndef __cplusplus #undef inline #endif /* Define to `unsigned' if does not define. */ #undef size_t quarry-0.2.0/configure.ac0000644000175000017500000001310010530112721013747 0ustar bartbartdnl Process this file with Autoconf to produce a `configure' script. # Package name and version. AC_INIT([Quarry], [0.2.0], [quarry-dev@gna.org]) AC_PREREQ(2.57) # Check if the script is running in the proper directory. Alarm if it # is not. AC_CONFIG_SRCDIR(src/quarry.c) AC_CONFIG_AUX_DIR(build) # Initialize Automake and add maintainer mode as an option. AM_INIT_AUTOMAKE([foreign check-news]) AM_MAINTAINER_MODE AC_CONFIG_HEADER(config.h) AH_TEMPLATE(PACKAGE, [The name of the package.]) AH_TEMPLATE(VERSION, [The version of the distribution.]) # Checks for programs. AC_PROG_CC AC_PROG_RANLIB AC_SUBST(QUARRY_WARNINGS) AC_SUBST(QUARRY_WARNINGS_GTK) if test "$GCC" = "yes"; then # I would like to use `-W' too, but, unfortunately, it generates a # few warnings which I cannot stand. I find it cleaner to write # `FIRST_XXX <= xxx && xxx <= LAST_XXX' even if `xxx' is unsigned # and `FIRST_XXX' is zero. It also complains about missing # initializers of private fields of GTK+ structures, which I don't # want to touch. # # `-Wbad-function-cast' is generally good, but yells at things like # `(int) floor(...)', which is intolerable. QUARRY_WARNINGS='-Wall -Waggregate-return -Wcast-align -Wcast-qual -Wmissing-declarations -Wmissing-prototypes -Wnested-externs -Wpointer-arith -Wredundant-decls -Wshadow -Wstrict-prototypes -Wunused-parameter -Wwrite-strings' # `-Wstrict-prototypes' and `-Wshadow' launch alarms on GTK+ # headers, so they are excluded. `-Wwrite-strings' is excluded, # because certain GTK+ structures lack `const' attribute for `gchar # *' fields. # # `-Wcast-qual' is removed, because certain GTK+/GLib structures # have `gchar *' fields, which we sometimes need to assign results # of gettext() and friends. Also, GLib data structures operate with # `gpointer's and `-Wcast-qual' generates warnings on adding # constant strings to them. QUARRY_WARNINGS_GTK='-Wall -Waggregate-return -Wcast-align -Wmissing-declarations -Wmissing-prototypes -Wnested-externs -Wpointer-arith -Wredundant-decls -Wunused-parameter' else QUARRY_WARNINGS='' QUARRY_WARNINGS_GTK='' fi # Checks for header files. AC_HEADER_STDC AC_CHECK_HEADERS(limits.h float.h) # Checks for typedefs, structures, and compiler characteristics. AC_C_CONST AC_C_INLINE AC_TYPE_SIZE_T # Check size of some types. AC_CHECK_SIZEOF([int], , [#include ]) AC_CHECK_SIZEOF([double], , [#include ]) AC_CHECK_SIZEOF([void *], , [#include ]) # Checks for library functions. AC_FUNC_VPRINTF AC_FUNC_MEMCMP AC_CHECK_FUNCS(memrchr) # Require math library. AC_SEARCH_LIBS(floor, m) # Find iconv(). It is usually sitting in GNU C library, but may # sometimes be in a separate `libiconv' library. # # FIXME: Is this needed anymore given that we use gettext? Check what # AM_ICONV() is good for. AC_SEARCH_LIBS(iconv, iconv) # Turn on GNU gettext support. AM_GNU_GETTEXT([external]) # Check for ScrollKeeper. AC_CHECK_PROG(have_scrollkeeper, scrollkeeper-config, yes, no) AM_CONDITIONAL(HAVE_SCROLLKEEPER, test "$have_scrollkeeper" = "yes") if test "$have_scrollkeeper" = "yes"; then AC_DEFINE(HAVE_SCROLLKEEPER, 1, [Define if you have ScrollKeeper package installed.]) fi # Require GTK+ 2.0.0 or later and librsvg 2.5.0 or later. PKG_CHECK_MODULES(QUARRY_GTK, gtk+-2.0 >= 2.0.0 librsvg-2.0 >= 2.5.0) AC_SUBST(QUARRY_GTK_CFLAGS) AC_SUBST(QUARRY_GTK_LIBS) # Threads are not required for Quarry. While Glib is probably always # compiled with thread support, let's not insist anyway. PKG_CHECK_MODULES(QUARRY_GTHREAD, gthread-2.0 >= 2.0.0, :, :) AC_SUBST(QUARRY_GTHREAD_CFLAGS) AC_SUBST(QUARRY_GTHREAD_LIBS) # Needed to generate Quarry-specific marshallers (see # `src/gui-gtk/Makefile.am'). AC_SUBST(GLIB_GENMARSHAL, [`$PKG_CONFIG --variable=glib_genmarshal glib-2.0`]) # Optionally enable automatic building and installation of standalone # SGF utilities (only `sgf-diff' at the moment). Even if not enabled, # the utilities can still be built manually. AC_ARG_ENABLE(sgf-utils, AC_HELP_STRING([--enable-sgf-utils], [enable automatic building and installation of standalone SGF utilities])) AM_CONDITIONAL(BUILD_SGF_UTILS, test "$enable_sgf_utils" = "yes") # Optionally disable deprecated GTK+ code (for maintainers---to check # if some code should be replaced with newer). AC_ARG_ENABLE(gtk-deprecated, AC_HELP_STRING([--disable-gtk-deprecated], [disable deprecated GTK+ features (for maintainers; don't use for normal builds)])) AC_SUBST(QUARRY_GTK_DEPRECATED_FLAGS) if test "$enable_gtk_deprecated" = "no"; then QUARRY_GTK_DEPRECATED_FLAGS='-D G_DISABLE_DEPRECATED -D GDK_DISABLE_DEPRECATED -D GDK_PIXBUF_DISABLE_DEPRECATED -D GTK_DISABLE_DEPRECATED' else QUARRY_GTK_DEPRECATED_FLAGS='' fi AC_ARG_ENABLE(scrollkeeper-update, AC_HELP_STRING([--disable-scrollkeeper-update], [don't update ScrollKeeper database (for packagers)])) AM_CONDITIONAL(DO_SCROLLKEEPER_UPDATE, [test "$have_scrollkeeper" == "yes" && test "$enable_scrollkeeper_update" != "no"]) AC_ARG_ENABLE(mime-database-update, AC_HELP_STRING([--disable-mime-database-update], [don't update the Shared MIME-info Database])) AM_CONDITIONAL(REGISTER_MIME_TYPES, test "$enable_mime_database_update" != "no") # Write `Makefile's. AC_CONFIG_FILES(Makefile data/Makefile data/quarry.desktop data/markup-themes/Makefile data/textures/Makefile help/Makefile help/C/Makefile po/Makefile.in src/Makefile src/board/Makefile src/gtp/Makefile src/gui-gtk/Makefile src/gui-utils/Makefile src/sgf/Makefile src/utils/Makefile) # The end. AC_OUTPUT quarry-0.2.0/COPYING-DOC0000644000175000017500000004766310237132720013151 0ustar bartbart GNU Free Documentation License Version 1.2, November 2002 Copyright (C) 2000,2001,2002 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. 0. PREAMBLE The purpose of this License is to make a manual, textbook, or other functional and useful document "free" in the sense of freedom: to assure everyone the effective freedom to copy and redistribute it, with or without modifying it, either commercially or noncommercially. Secondarily, this License preserves for the author and publisher a way to get credit for their work, while not being considered responsible for modifications made by others. This License is a kind of "copyleft", which means that derivative works of the document must themselves be free in the same sense. It complements the GNU General Public License, which is a copyleft license designed for free software. We have designed this License in order to use it for manuals for free software, because free software needs free documentation: a free program should come with manuals providing the same freedoms that the software does. But this License is not limited to software manuals; it can be used for any textual work, regardless of subject matter or whether it is published as a printed book. We recommend this License principally for works whose purpose is instruction or reference. 1. APPLICABILITY AND DEFINITIONS This License applies to any manual or other work, in any medium, that contains a notice placed by the copyright holder saying it can be distributed under the terms of this License. Such a notice grants a world-wide, royalty-free license, unlimited in duration, to use that work under the conditions stated herein. The "Document", below, refers to any such manual or work. Any member of the public is a licensee, and is addressed as "you". You accept the license if you copy, modify or distribute the work in a way requiring permission under copyright law. A "Modified Version" of the Document means any work containing the Document or a portion of it, either copied verbatim, or with modifications and/or translated into another language. A "Secondary Section" is a named appendix or a front-matter section of the Document that deals exclusively with the relationship of the publishers or authors of the Document to the Document's overall subject (or to related matters) and contains nothing that could fall directly within that overall subject. (Thus, if the Document is in part a textbook of mathematics, a Secondary Section may not explain any mathematics.) The relationship could be a matter of historical connection with the subject or with related matters, or of legal, commercial, philosophical, ethical or political position regarding them. The "Invariant Sections" are certain Secondary Sections whose titles are designated, as being those of Invariant Sections, in the notice that says that the Document is released under this License. If a section does not fit the above definition of Secondary then it is not allowed to be designated as Invariant. The Document may contain zero Invariant Sections. If the Document does not identify any Invariant Sections then there are none. The "Cover Texts" are certain short passages of text that are listed, as Front-Cover Texts or Back-Cover Texts, in the notice that says that the Document is released under this License. A Front-Cover Text may be at most 5 words, and a Back-Cover Text may be at most 25 words. A "Transparent" copy of the Document means a machine-readable copy, represented in a format whose specification is available to the general public, that is suitable for revising the document straightforwardly with generic text editors or (for images composed of pixels) generic paint programs or (for drawings) some widely available drawing editor, and that is suitable for input to text formatters or for automatic translation to a variety of formats suitable for input to text formatters. A copy made in an otherwise Transparent file format whose markup, or absence of markup, has been arranged to thwart or discourage subsequent modification by readers is not Transparent. An image format is not Transparent if used for any substantial amount of text. A copy that is not "Transparent" is called "Opaque". Examples of suitable formats for Transparent copies include plain ASCII without markup, Texinfo input format, LaTeX input format, SGML or XML using a publicly available DTD, and standard-conforming simple HTML, PostScript or PDF designed for human modification. Examples of transparent image formats include PNG, XCF and JPG. Opaque formats include proprietary formats that can be read and edited only by proprietary word processors, SGML or XML for which the DTD and/or processing tools are not generally available, and the machine-generated HTML, PostScript or PDF produced by some word processors for output purposes only. The "Title Page" means, for a printed book, the title page itself, plus such following pages as are needed to hold, legibly, the material this License requires to appear in the title page. For works in formats which do not have any title page as such, "Title Page" means the text near the most prominent appearance of the work's title, preceding the beginning of the body of the text. A section "Entitled XYZ" means a named subunit of the Document whose title either is precisely XYZ or contains XYZ in parentheses following text that translates XYZ in another language. (Here XYZ stands for a specific section name mentioned below, such as "Acknowledgements", "Dedications", "Endorsements", or "History".) To "Preserve the Title" of such a section when you modify the Document means that it remains a section "Entitled XYZ" according to this definition. The Document may include Warranty Disclaimers next to the notice which states that this License applies to the Document. These Warranty Disclaimers are considered to be included by reference in this License, but only as regards disclaiming warranties: any other implication that these Warranty Disclaimers may have is void and has no effect on the meaning of this License. 2. VERBATIM COPYING You may copy and distribute the Document in any medium, either commercially or noncommercially, provided that this License, the copyright notices, and the license notice saying this License applies to the Document are reproduced in all copies, and that you add no other conditions whatsoever to those of this License. You may not use technical measures to obstruct or control the reading or further copying of the copies you make or distribute. However, you may accept compensation in exchange for copies. If you distribute a large enough number of copies you must also follow the conditions in section 3. You may also lend copies, under the same conditions stated above, and you may publicly display copies. 3. COPYING IN QUANTITY If you publish printed copies (or copies in media that commonly have printed covers) of the Document, numbering more than 100, and the Document's license notice requires Cover Texts, you must enclose the copies in covers that carry, clearly and legibly, all these Cover Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on the back cover. Both covers must also clearly and legibly identify you as the publisher of these copies. The front cover must present the full title with all words of the title equally prominent and visible. You may add other material on the covers in addition. Copying with changes limited to the covers, as long as they preserve the title of the Document and satisfy these conditions, can be treated as verbatim copying in other respects. If the required texts for either cover are too voluminous to fit legibly, you should put the first ones listed (as many as fit reasonably) on the actual cover, and continue the rest onto adjacent pages. If you publish or distribute Opaque copies of the Document numbering more than 100, you must either include a machine-readable Transparent copy along with each Opaque copy, or state in or with each Opaque copy a computer-network location from which the general network-using public has access to download using public-standard network protocols a complete Transparent copy of the Document, free of added material. If you use the latter option, you must take reasonably prudent steps, when you begin distribution of Opaque copies in quantity, to ensure that this Transparent copy will remain thus accessible at the stated location until at least one year after the last time you distribute an Opaque copy (directly or through your agents or retailers) of that edition to the public. It is requested, but not required, that you contact the authors of the Document well before redistributing any large number of copies, to give them a chance to provide you with an updated version of the Document. 4. MODIFICATIONS You may copy and distribute a Modified Version of the Document under the conditions of sections 2 and 3 above, provided that you release the Modified Version under precisely this License, with the Modified Version filling the role of the Document, thus licensing distribution and modification of the Modified Version to whoever possesses a copy of it. In addition, you must do these things in the Modified Version: A. Use in the Title Page (and on the covers, if any) a title distinct from that of the Document, and from those of previous versions (which should, if there were any, be listed in the History section of the Document). You may use the same title as a previous version if the original publisher of that version gives permission. B. List on the Title Page, as authors, one or more persons or entities responsible for authorship of the modifications in the Modified Version, together with at least five of the principal authors of the Document (all of its principal authors, if it has fewer than five), unless they release you from this requirement. C. State on the Title page the name of the publisher of the Modified Version, as the publisher. D. Preserve all the copyright notices of the Document. E. Add an appropriate copyright notice for your modifications adjacent to the other copyright notices. F. Include, immediately after the copyright notices, a license notice giving the public permission to use the Modified Version under the terms of this License, in the form shown in the Addendum below. G. Preserve in that license notice the full lists of Invariant Sections and required Cover Texts given in the Document's license notice. H. Include an unaltered copy of this License. I. Preserve the section Entitled "History", Preserve its Title, and add to it an item stating at least the title, year, new authors, and publisher of the Modified Version as given on the Title Page. If there is no section Entitled "History" in the Document, create one stating the title, year, authors, and publisher of the Document as given on its Title Page, then add an item describing the Modified Version as stated in the previous sentence. J. Preserve the network location, if any, given in the Document for public access to a Transparent copy of the Document, and likewise the network locations given in the Document for previous versions it was based on. These may be placed in the "History" section. You may omit a network location for a work that was published at least four years before the Document itself, or if the original publisher of the version it refers to gives permission. K. For any section Entitled "Acknowledgements" or "Dedications", Preserve the Title of the section, and preserve in the section all the substance and tone of each of the contributor acknowledgements and/or dedications given therein. L. Preserve all the Invariant Sections of the Document, unaltered in their text and in their titles. Section numbers or the equivalent are not considered part of the section titles. M. Delete any section Entitled "Endorsements". Such a section may not be included in the Modified Version. N. Do not retitle any existing section to be Entitled "Endorsements" or to conflict in title with any Invariant Section. O. Preserve any Warranty Disclaimers. If the Modified Version includes new front-matter sections or appendices that qualify as Secondary Sections and contain no material copied from the Document, you may at your option designate some or all of these sections as invariant. To do this, add their titles to the list of Invariant Sections in the Modified Version's license notice. These titles must be distinct from any other section titles. You may add a section Entitled "Endorsements", provided it contains nothing but endorsements of your Modified Version by various parties--for example, statements of peer review or that the text has been approved by an organization as the authoritative definition of a standard. You may add a passage of up to five words as a Front-Cover Text, and a passage of up to 25 words as a Back-Cover Text, to the end of the list of Cover Texts in the Modified Version. Only one passage of Front-Cover Text and one of Back-Cover Text may be added by (or through arrangements made by) any one entity. If the Document already includes a cover text for the same cover, previously added by you or by arrangement made by the same entity you are acting on behalf of, you may not add another; but you may replace the old one, on explicit permission from the previous publisher that added the old one. The author(s) and publisher(s) of the Document do not by this License give permission to use their names for publicity for or to assert or imply endorsement of any Modified Version. 5. COMBINING DOCUMENTS You may combine the Document with other documents released under this License, under the terms defined in section 4 above for modified versions, provided that you include in the combination all of the Invariant Sections of all of the original documents, unmodified, and list them all as Invariant Sections of your combined work in its license notice, and that you preserve all their Warranty Disclaimers. The combined work need only contain one copy of this License, and multiple identical Invariant Sections may be replaced with a single copy. If there are multiple Invariant Sections with the same name but different contents, make the title of each such section unique by adding at the end of it, in parentheses, the name of the original author or publisher of that section if known, or else a unique number. Make the same adjustment to the section titles in the list of Invariant Sections in the license notice of the combined work. In the combination, you must combine any sections Entitled "History" in the various original documents, forming one section Entitled "History"; likewise combine any sections Entitled "Acknowledgements", and any sections Entitled "Dedications". You must delete all sections Entitled "Endorsements". 6. COLLECTIONS OF DOCUMENTS You may make a collection consisting of the Document and other documents released under this License, and replace the individual copies of this License in the various documents with a single copy that is included in the collection, provided that you follow the rules of this License for verbatim copying of each of the documents in all other respects. You may extract a single document from such a collection, and distribute it individually under this License, provided you insert a copy of this License into the extracted document, and follow this License in all other respects regarding verbatim copying of that document. 7. AGGREGATION WITH INDEPENDENT WORKS A compilation of the Document or its derivatives with other separate and independent documents or works, in or on a volume of a storage or distribution medium, is called an "aggregate" if the copyright resulting from the compilation is not used to limit the legal rights of the compilation's users beyond what the individual works permit. When the Document is included in an aggregate, this License does not apply to the other works in the aggregate which are not themselves derivative works of the Document. If the Cover Text requirement of section 3 is applicable to these copies of the Document, then if the Document is less than one half of the entire aggregate, the Document's Cover Texts may be placed on covers that bracket the Document within the aggregate, or the electronic equivalent of covers if the Document is in electronic form. Otherwise they must appear on printed covers that bracket the whole aggregate. 8. TRANSLATION Translation is considered a kind of modification, so you may distribute translations of the Document under the terms of section 4. Replacing Invariant Sections with translations requires special permission from their copyright holders, but you may include translations of some or all Invariant Sections in addition to the original versions of these Invariant Sections. You may include a translation of this License, and all the license notices in the Document, and any Warranty Disclaimers, provided that you also include the original English version of this License and the original versions of those notices and disclaimers. In case of a disagreement between the translation and the original version of this License or a notice or disclaimer, the original version will prevail. If a section in the Document is Entitled "Acknowledgements", "Dedications", or "History", the requirement (section 4) to Preserve its Title (section 1) will typically require changing the actual title. 9. TERMINATION You may not copy, modify, sublicense, or distribute the Document except as expressly provided for under this License. Any other attempt to copy, modify, sublicense or distribute the Document is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 10. FUTURE REVISIONS OF THIS LICENSE The Free Software Foundation may publish new, revised versions of the GNU Free Documentation License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. See http://www.gnu.org/copyleft/. Each version of the License is given a distinguishing version number. If the Document specifies that a particular numbered version of this License "or any later version" applies to it, you have the option of following the terms and conditions either of that specified version or of any later version that has been published (not as a draft) by the Free Software Foundation. If the Document does not specify a version number of this License, you may choose any version ever published (not as a draft) by the Free Software Foundation. ADDENDUM: How to use this License for your documents To use this License in a document you have written, include a copy of the License in the document and put the following copyright and license notices just after the title page: Copyright (c) YEAR YOUR NAME. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License". If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, replace the "with...Texts." line with this: with the Invariant Sections being LIST THEIR TITLES, with the Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST. If you have Invariant Sections without Cover Texts, or some other combination of the three, merge those two alternatives to suit the situation. If your document contains nontrivial examples of program code, we recommend releasing these examples in parallel under your choice of free software license, such as the GNU General Public License, to permit their use in free software. quarry-0.2.0/help/0000755000175000017500000000000010530402565012426 5ustar bartbartquarry-0.2.0/help/Makefile.in0000644000175000017500000003520110425150132014465 0ustar bartbart# Makefile.in generated by automake 1.7.9 from Makefile.am. # @configure_input@ # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 # Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # Process this file with Automake to produce `Makefile.in'. srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = .. am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : host_triplet = @host@ ACLOCAL = @ACLOCAL@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BUILD_SGF_UTILS_FALSE = @BUILD_SGF_UTILS_FALSE@ BUILD_SGF_UTILS_TRUE = @BUILD_SGF_UTILS_TRUE@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DO_SCROLLKEEPER_UPDATE_FALSE = @DO_SCROLLKEEPER_UPDATE_FALSE@ DO_SCROLLKEEPER_UPDATE_TRUE = @DO_SCROLLKEEPER_UPDATE_TRUE@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ GMSGFMT = @GMSGFMT@ HAVE_SCROLLKEEPER_FALSE = @HAVE_SCROLLKEEPER_FALSE@ HAVE_SCROLLKEEPER_TRUE = @HAVE_SCROLLKEEPER_TRUE@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ LDFLAGS = @LDFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ MAKEINFO = @MAKEINFO@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGMERGE = @MSGMERGE@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSUB = @POSUB@ QUARRY_GTHREAD_CFLAGS = @QUARRY_GTHREAD_CFLAGS@ QUARRY_GTHREAD_LIBS = @QUARRY_GTHREAD_LIBS@ QUARRY_GTK_CFLAGS = @QUARRY_GTK_CFLAGS@ QUARRY_GTK_DEPRECATED_FLAGS = @QUARRY_GTK_DEPRECATED_FLAGS@ QUARRY_GTK_LIBS = @QUARRY_GTK_LIBS@ QUARRY_WARNINGS = @QUARRY_WARNINGS@ QUARRY_WARNINGS_GTK = @QUARRY_WARNINGS_GTK@ RANLIB = @RANLIB@ REGISTER_MIME_TYPES_FALSE = @REGISTER_MIME_TYPES_FALSE@ REGISTER_MIME_TYPES_TRUE = @REGISTER_MIME_TYPES_TRUE@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ ac_ct_CC = @ac_ct_CC@ ac_ct_RANLIB = @ac_ct_RANLIB@ ac_ct_STRIP = @ac_ct_STRIP@ ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ datadir = @datadir@ exec_prefix = @exec_prefix@ have_scrollkeeper = @have_scrollkeeper@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localstatedir = @localstatedir@ mandir = @mandir@ oldincludedir = @oldincludedir@ prefix = @prefix@ program_transform_name = @program_transform_name@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ SUBDIRS = C cssdir = $(datadir)/quarry/help css_DATA = quarry-help.css EXTRA_DIST = \ quarry-help.css \ quarry-help.sed DISTCLEANFILES = *~ subdir = help ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 mkinstalldirs = $(SHELL) $(top_srcdir)/build/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = DIST_SOURCES = DATA = $(css_DATA) RECURSIVE_TARGETS = info-recursive dvi-recursive pdf-recursive \ ps-recursive install-info-recursive uninstall-info-recursive \ all-recursive install-data-recursive install-exec-recursive \ installdirs-recursive install-recursive uninstall-recursive \ check-recursive installcheck-recursive DIST_COMMON = $(srcdir)/Makefile.in ChangeLog Makefile.am DIST_SUBDIRS = $(SUBDIRS) all: all-recursive .SUFFIXES: $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4) cd $(top_srcdir) && \ $(AUTOMAKE) --foreign help/Makefile Makefile: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) uninstall-info-am: cssDATA_INSTALL = $(INSTALL_DATA) install-cssDATA: $(css_DATA) @$(NORMAL_INSTALL) $(mkinstalldirs) $(DESTDIR)$(cssdir) @list='$(css_DATA)'; for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ f="`echo $$p | sed -e 's|^.*/||'`"; \ echo " $(cssDATA_INSTALL) $$d$$p $(DESTDIR)$(cssdir)/$$f"; \ $(cssDATA_INSTALL) $$d$$p $(DESTDIR)$(cssdir)/$$f; \ done uninstall-cssDATA: @$(NORMAL_UNINSTALL) @list='$(css_DATA)'; for p in $$list; do \ f="`echo $$p | sed -e 's|^.*/||'`"; \ echo " rm -f $(DESTDIR)$(cssdir)/$$f"; \ rm -f $(DESTDIR)$(cssdir)/$$f; \ done # This directory's subdirectories are mostly independent; you can cd # into them and run `make' without going through this Makefile. # To change the values of `make' variables: instead of editing Makefiles, # (1) if the variable is set in `config.status', edit `config.status' # (which will cause the Makefiles to be regenerated when you run `make'); # (2) otherwise, pass the desired values on the `make' command line. $(RECURSIVE_TARGETS): @set fnord $$MAKEFLAGS; amf=$$2; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ list='$(SUBDIRS)'; for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" mostlyclean-recursive clean-recursive distclean-recursive \ maintainer-clean-recursive: @set fnord $$MAKEFLAGS; amf=$$2; \ dot_seen=no; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ rev=''; for subdir in $$list; do \ if test "$$subdir" = "."; then :; else \ rev="$$subdir $$rev"; \ fi; \ done; \ rev="$$rev ."; \ target=`echo $@ | sed s/-recursive//`; \ for subdir in $$rev; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ done && test -z "$$fail" tags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ done ctags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ done ETAGS = etags ETAGSFLAGS = CTAGS = ctags CTAGSFLAGS = tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ if (etags --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ else \ include_option=--include; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test -f $$subdir/TAGS && \ tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(ETAGS_ARGS)$$tags$$unique" \ || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique ctags: CTAGS CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = .. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ case $$file in \ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ esac; \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ dir="/$$dir"; \ $(mkinstalldirs) "$(distdir)$$dir"; \ else \ dir=''; \ fi; \ if test -d $$d/$$file; then \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test -d $(distdir)/$$subdir \ || mkdir $(distdir)/$$subdir \ || exit 1; \ (cd $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" \ distdir=../$(distdir)/$$subdir \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile $(DATA) installdirs: installdirs-recursive installdirs-am: $(mkinstalldirs) $(DESTDIR)$(cssdir) install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -rm -f $(CONFIG_CLEAN_FILES) -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic mostlyclean-am distclean: distclean-recursive -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-recursive dvi-am: info: info-recursive info-am: install-data-am: install-cssDATA install-exec-am: install-info: install-info-recursive install-man: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-cssDATA uninstall-info-am uninstall-info: uninstall-info-recursive .PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am check check-am clean \ clean-generic clean-recursive ctags ctags-recursive distclean \ distclean-generic distclean-recursive distclean-tags distdir \ dvi dvi-am dvi-recursive info info-am info-recursive install \ install-am install-cssDATA install-data install-data-am \ install-data-recursive install-exec install-exec-am \ install-exec-recursive install-info install-info-am \ install-info-recursive install-man install-recursive \ install-strip installcheck installcheck-am installdirs \ installdirs-am installdirs-recursive maintainer-clean \ maintainer-clean-generic maintainer-clean-recursive mostlyclean \ mostlyclean-generic mostlyclean-recursive pdf pdf-am \ pdf-recursive ps ps-am ps-recursive tags tags-recursive \ uninstall uninstall-am uninstall-cssDATA uninstall-info-am \ uninstall-info-recursive uninstall-recursive # Convert DocBook help to HTML, which is used as fallback if `yelp' is # not available. # # This should be done by maintainer only. No need to do it when just # building Quarry. html: for directory in $(SUBDIRS); do \ if test -e $$directory/quarry.xml; then \ xmlto xhtml-nochunks $$directory/quarry.xml -o $$directory; \ if test -e $$directory/quarry.html; then \ sed -f quarry-help.sed \ < $$directory/quarry.html > quarry.html.tmp; \ mv quarry.html.tmp $$directory/quarry.html; \ fi; \ fi; \ done # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: quarry-0.2.0/help/ChangeLog0000644000175000017500000000563610530402556014212 0ustar bartbart2006-11-20 Paul Pogonyshev * C/Makefile.am: Add accidentally forgotten `authors.xml' to `entities'. 2006-11-19 Paul Pogonyshev * (Quarry version 0.2.0.) * C/quarry.xml: Fix, update and expand a little. * C/fdl.xml: Use `simplesect' tag to suppress TOC. * C/authors.xml: New file. * C/figures/board-window.png: New file. * C/figures/control-center.png: Update. * quarry-help.css (div.figure): Set left margin to zero. 2006-10-29 Paul Pogonyshev * (Quarry version 0.1.20.) 2006-10-28 Paul Pogonyshev * C/quarry.xml: Expand. Raise level of all sections by 1 by converting `article' to a `book'. * quarry-help.css: Use bold font for GUI labels. 2006-07-16 Paul Pogonyshev * (Quarry version 0.1.19.) 2006-07-14 Paul Pogonyshev * (Quarry version 0.1.18.) * C/quarry.xml: Expand somewhat. 2006-03-09 Paul Pogonyshev * (Quarry version 0.1.17.) 2005-10-30 Paul Pogonyshev * (Quarry version 0.1.16.) * C/figures/control-center.png: Update for newer Quarry versions. * C/quarry.xml: Update and expand somewhat. * quarry-help.css: Add a few rules to make the HTML look more like what `yelp' displays. * quarry-help.sed: Add rule to replace `->' with a proper arrow. * Makefile.am (html): Change target format from `html-nochunks' to `xhtml-nochunks'. 2005-09-27 Paul Pogonyshev * C/quarry.xml: Use "Reversi" instead of "Othello". 2005-06-17 Paul Pogonyshev * (Quarry version 0.1.15.) 2005-05-07 Paul Pogonyshev * C/fdl.xml: Update FSF address. 2005-03-14 Paul Pogonyshev * (Quarry version 0.1.14.) 2005-03-13 Paul Pogonyshev * (Quarry version 0.1.13.) 2005-01-15 Paul Pogonyshev * (Quarry version 0.1.12.) 2005-01-06 Paul Pogonyshev * (Quarry version 0.1.11.) 2004-11-30 Paul Pogonyshev * (Quarry version 0.1.10.) 2004-11-13 Paul Pogonyshev * C/quarry.xml (register-game-playing-program): Fix typo (bug #1835.) 2004-10-14 Paul Pogonyshev * (Quarry version 0.1.9.) * (Quarry version 0.1.8.) 2004-10-11 Paul Pogonyshev * quarry-help.css: New file. * C/figures: New directory. * C/figures/control-center.png: New file. * C: New directory. * C/Makefile.am: New file. * C/quarry-C.omf: New file. * C/quarry.xml: New file. * C/legal.xml: New file. * C/fdl.xml: New file. * C/quarry.html: New file. * Makefile.am: New file. * quarry-help.sed: New file. Copyright (C) 2004, 2005, 2006 Paul Pogonyshev. Copying and distribution of this file, with or without modification, are permitted provided the copyright notice and this notice are preserved. quarry-0.2.0/help/Makefile.am0000644000175000017500000000142010331447035014457 0ustar bartbart# Process this file with Automake to produce `Makefile.in'. SUBDIRS = C # Convert DocBook help to HTML, which is used as fallback if `yelp' is # not available. # # This should be done by maintainer only. No need to do it when just # building Quarry. html: for directory in $(SUBDIRS); do \ if test -e $$directory/quarry.xml; then \ xmlto xhtml-nochunks $$directory/quarry.xml -o $$directory; \ if test -e $$directory/quarry.html; then \ sed -f quarry-help.sed \ < $$directory/quarry.html > quarry.html.tmp; \ mv quarry.html.tmp $$directory/quarry.html; \ fi; \ fi; \ done cssdir = $(datadir)/quarry/help css_DATA = quarry-help.css EXTRA_DIST = \ quarry-help.css \ quarry-help.sed DISTCLEANFILES = *~ quarry-0.2.0/help/quarry-help.css0000644000175000017500000000233710530106041015404 0ustar bartbartbody { background: #cccccc; color: #000000; } td.contents { background: #ffffff; border: 1px solid #000000; } h1 { font-size: 200%; font-weight: bold; } h2 { font-size: 160%; font-weight: bold; } h3 { font-size: 130%; font-weight: bold; } h4 { font-size: 110%; font-weight: bold; } h5 { font-size: 100%; font-weight: bold; } p { text-align: justify; } hr { margin-top: 0.6em; margin-bottom: 0.6em; } th { border: 1px solid #888888; } td { border: 1px solid #888888; } dd { margin-left: 0.5in; } a { color: #0020ff; text-decoration: underline; } a:visited { color: #403050; text-decoration: underline; } a:hover { color: #4080ff; text-decoration: underline; } a:focus { background: #eeeeee; } div.legalnotice { font-size: 90%; } div.toc { background: #f4f4ff; border: 1px solid #a0a0c0; margin: 0.5em 2em; padding: 0.5em 2.5em; } div.appendix { margin-top: 4em; } div.figure { margin-left: 0; } span.term { font-style: italic; } div.note h3 { font-size: 100%; font-weight: bold; text-decoration: underline; } span.guimenu, span.guisubmenu, span.guimenuitem, span.guibutton, span.guilabel { font-weight: bold; } strong.command { font-family: monospace; font-weight: normal; } quarry-0.2.0/help/quarry-help.sed0000644000175000017500000000100110331200240015345 0ustar bartbarts/<\/head>/<\/head>/ s/]*>/
/ s/<\/body>/<\/td><\/tr><\/table><\/body>/ s/-\> &app; Authors Programming Paul Pogonyshev Main author, programming, design. Martin Holters Programming. Translation Jérémie Knuesel French translation. Paul Pogonyshev British English and Russian translations. Robert Stefaniuk Polish translation. quarry-0.2.0/help/C/fdl.xml0000644000175000017500000006656510530105777014126 0ustar bartbart Version 1.2, November 2002 2000 2001 2002 Free Software Foundation, Inc.
Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
GNU Free Documentation License Version 1.2, November 2002
Copyright © 2000, 2001, 2002 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
0. PREAMBLE The purpose of this License is to make a manual, textbook, or other functional and useful document free in the sense of freedom: to assure everyone the effective freedom to copy and redistribute it, with or without modifying it, either commercially or noncommercially. Secondarily, this License preserves for the author and publisher a way to get credit for their work, while not being considered responsible for modifications made by others. This License is a kind of copyleft, which means that derivative works of the document must themselves be free in the same sense. It complements the GNU General Public License, which is a copyleft license designed for free software. We have designed this License in order to use it for manuals for free software, because free software needs free documentation: a free program should come with manuals providing the same freedoms that the software does. But this License is not limited to software manuals; it can be used for any textual work, regardless of subject matter or whether it is published as a printed book. We recommend this License principally for works whose purpose is instruction or reference. 1. APPLICABILITY AND DEFINITIONS This License applies to any manual or other work, in any medium, that contains a notice placed by the copyright holder saying it can be distributed under the terms of this License. Such a notice grants a world-wide, royalty-free license, unlimited in duration, to use that work under the conditions stated herein. The Document, below, refers to any such manual or work. Any member of the public is a licensee, and is addressed as you. You accept the license if you copy, modify or distribute the work in a way requiring permission under copyright law. A Modified Version of the Document means any work containing the Document or a portion of it, either copied verbatim, or with modifications and/or translated into another language. A Secondary Section is a named appendix or a front-matter section of the Document that deals exclusively with the relationship of the publishers or authors of the Document to the Document’s overall subject (or to related matters) and contains nothing that could fall directly within that overall subject. (Thus, if the Document is in part a textbook of mathematics, a Secondary Section may not explain any mathematics.) The relationship could be a matter of historical connection with the subject or with related matters, or of legal, commercial, philosophical, ethical or political position regarding them. The Invariant Sections are certain Secondary Sections whose titles are designated, as being those of Invariant Sections, in the notice that says that the Document is released under this License. If a section does not fit the above definition of Secondary then it is not allowed to be designated as Invariant. The Document may contain zero Invariant Sections. If the Document does not identify any Invariant Sections then there are none. The Cover Texts are certain short passages of text that are listed, as Front-Cover Texts or Back-Cover Texts, in the notice that says that the Document is released under this License. A Front-Cover Text may be at most 5 words, and a Back-Cover Text may be at most 25 words. A Transparent copy of the Document means a machine-readable copy, represented in a format whose specification is available to the general public, that is suitable for revising the document straightforwardly with generic text editors or (for images composed of pixels) generic paint programs or (for drawings) some widely available drawing editor, and that is suitable for input to text formatters or for automatic translation to a variety of formats suitable for input to text formatters. A copy made in an otherwise Transparent file format whose markup, or absence of markup, has been arranged to thwart or discourage subsequent modification by readers is not Transparent. An image format is not Transparent if used for any substantial amount of text. A copy that is not Transparent is called Opaque. Examples of suitable formats for Transparent copies include plain ASCII without markup, Texinfo input format, LaTeX input format, SGML or XML using a publicly available DTD, and standard-conforming simple HTML, PostScript or PDF designed for human modification. Examples of transparent image formats include PNG, XCF and JPG. Opaque formats include proprietary formats that can be read and edited only by proprietary word processors, SGML or XML for which the DTD and/or processing tools are not generally available, and the machine-generated HTML, PostScript or PDF produced by some word processors for output purposes only. The Title Page means, for a printed book, the title page itself, plus such following pages as are needed to hold, legibly, the material this License requires to appear in the title page. For works in formats which do not have any title page as such, Title Page means the text near the most prominent appearance of the work’s title, preceding the beginning of the body of the text. A section Entitled XYZ means a named subunit of the Document whose title either is precisely XYZ or contains XYZ in parentheses following text that translates XYZ in another language. (Here XYZ stands for a specific section name mentioned below, such as Acknowledgements, Dedications, Endorsements, or History.) To Preserve the Title of such a section when you modify the Document means that it remains a section Entitled XYZ according to this definition. The Document may include Warranty Disclaimers next to the notice which states that this License applies to the Document. These Warranty Disclaimers are considered to be included by reference in this License, but only as regards disclaiming warranties: any other implication that these Warranty Disclaimers may have is void and has no effect on the meaning of this License. 2. VERBATIM COPYING You may copy and distribute the Document in any medium, either commercially or noncommercially, provided that this License, the copyright notices, and the license notice saying this License applies to the Document are reproduced in all copies, and that you add no other conditions whatsoever to those of this License. You may not use technical measures to obstruct or control the reading or further copying of the copies you make or distribute. However, you may accept compensation in exchange for copies. If you distribute a large enough number of copies you must also follow the conditions in section 3. You may also lend copies, under the same conditions stated above, and you may publicly display copies. 3. COPYING IN QUANTITY If you publish printed copies (or copies in media that commonly have printed covers) of the Document, numbering more than 100, and the Document’s license notice requires Cover Texts, you must enclose the copies in covers that carry, clearly and legibly, all these Cover Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on the back cover. Both covers must also clearly and legibly identify you as the publisher of these copies. The front cover must present the full title with all words of the title equally prominent and visible. You may add other material on the covers in addition. Copying with changes limited to the covers, as long as they preserve the title of the Document and satisfy these conditions, can be treated as verbatim copying in other respects. If the required texts for either cover are too voluminous to fit legibly, you should put the first ones listed (as many as fit reasonably) on the actual cover, and continue the rest onto adjacent pages. If you publish or distribute Opaque copies of the Document numbering more than 100, you must either include a machine-readable Transparent copy along with each Opaque copy, or state in or with each Opaque copy a computer-network location from which the general network-using public has access to download using public-standard network protocols a complete Transparent copy of the Document, free of added material. If you use the latter option, you must take reasonably prudent steps, when you begin distribution of Opaque copies in quantity, to ensure that this Transparent copy will remain thus accessible at the stated location until at least one year after the last time you distribute an Opaque copy (directly or through your agents or retailers) of that edition to the public. It is requested, but not required, that you contact the authors of the Document well before redistributing any large number of copies, to give them a chance to provide you with an updated version of the Document. 4. MODIFICATIONS You may copy and distribute a Modified Version of the Document under the conditions of sections 2 and 3 above, provided that you release the Modified Version under precisely this License, with the Modified Version filling the role of the Document, thus licensing distribution and modification of the Modified Version to whoever possesses a copy of it. In addition, you must do these things in the Modified Version: Use in the Title Page (and on the covers, if any) a title distinct from that of the Document, and from those of previous versions (which should, if there were any, be listed in the History section of the Document). You may use the same title as a previous version if the original publisher of that version gives permission. List on the Title Page, as authors, one or more persons or entities responsible for authorship of the modifications in the Modified Version, together with at least five of the principal authors of the Document (all of its principal authors, if it has fewer than five), unless they release you from this requirement. State on the Title page the name of the publisher of the Modified Version, as the publisher. Preserve all the copyright notices of the Document. Add an appropriate copyright notice for your modifications adjacent to the other copyright notices. Include, immediately after the copyright notices, a license notice giving the public permission to use the Modified Version under the terms of this License, in the form shown in the Addendum below. Preserve in that license notice the full lists of Invariant Sections and required Cover Texts given in the Document’s license notice. Include an unaltered copy of this License. Preserve the section Entitled History, Preserve its Title, and add to it an item stating at least the title, year, new authors, and publisher of the Modified Version as given on the Title Page. If there is no section Entitled History in the Document, create one stating the title, year, authors, and publisher of the Document as given on its Title Page, then add an item describing the Modified Version as stated in the previous sentence. Preserve the network location, if any, given in the Document for public access to a Transparent copy of the Document, and likewise the network locations given in the Document for previous versions it was based on. These may be placed in the History section. You may omit a network location for a work that was published at least four years before the Document itself, or if the original publisher of the version it refers to gives permission. For any section Entitled Acknowledgements or Dedications, Preserve the Title of the section, and preserve in the section all the substance and tone of each of the contributor acknowledgements and/or dedications given therein. Preserve all the Invariant Sections of the Document, unaltered in their text and in their titles. Section numbers or the equivalent are not considered part of the section titles. Delete any section Entitled Endorsements. Such a section may not be included in the Modified Version. Do not retitle any existing section to be Entitled Endorsements or to conflict in title with any Invariant Section. Preserve any Warranty Disclaimers. If the Modified Version includes new front-matter sections or appendices that qualify as Secondary Sections and contain no material copied from the Document, you may at your option designate some or all of these sections as invariant. To do this, add their titles to the list of Invariant Sections in the Modified Version’s license notice. These titles must be distinct from any other section titles. You may add a section Entitled Endorsements, provided it contains nothing but endorsements of your Modified Version by various parties—for example, statements of peer review or that the text has been approved by an organization as the authoritative definition of a standard. You may add a passage of up to five words as a Front-Cover Text, and a passage of up to 25 words as a Back-Cover Text, to the end of the list of Cover Texts in the Modified Version. Only one passage of Front-Cover Text and one of Back-Cover Text may be added by (or through arrangements made by) any one entity. If the Document already includes a cover text for the same cover, previously added by you or by arrangement made by the same entity you are acting on behalf of, you may not add another; but you may replace the old one, on explicit permission from the previous publisher that added the old one. The author(s) and publisher(s) of the Document do not by this License give permission to use their names for publicity for or to assert or imply endorsement of any Modified Version. 5. COMBINING DOCUMENTS You may combine the Document with other documents released under this License, under the terms defined in section 4 above for modified versions, provided that you include in the combination all of the Invariant Sections of all of the original documents, unmodified, and list them all as Invariant Sections of your combined work in its license notice, and that you preserve all their Warranty Disclaimers. The combined work need only contain one copy of this License, and multiple identical Invariant Sections may be replaced with a single copy. If there are multiple Invariant Sections with the same name but different contents, make the title of each such section unique by adding at the end of it, in parentheses, the name of the original author or publisher of that section if known, or else a unique number. Make the same adjustment to the section titles in the list of Invariant Sections in the license notice of the combined work. In the combination, you must combine any sections Entitled History in the various original documents, forming one section Entitled History; likewise combine any sections Entitled Acknowledgements, and any sections Entitled Dedications. You must delete all sections Entitled Endorsements. 6. COLLECTIONS OF DOCUMENTS You may make a collection consisting of the Document and other documents released under this License, and replace the individual copies of this License in the various documents with a single copy that is included in the collection, provided that you follow the rules of this License for verbatim copying of each of the documents in all other respects. You may extract a single document from such a collection, and distribute it individually under this License, provided you insert a copy of this License into the extracted document, and follow this License in all other respects regarding verbatim copying of that document. 7. AGGREGATION WITH INDEPENDENT WORKS A compilation of the Document or its derivatives with other separate and independent documents or works, in or on a volume of a storage or distribution medium, is called an aggregate if the copyright resulting from the compilation is not used to limit the legal rights of the compilation’s users beyond what the individual works permit. When the Document is included in an aggregate, this License does not apply to the other works in the aggregate which are not themselves derivative works of the Document. If the Cover Text requirement of section 3 is applicable to these copies of the Document, then if the Document is less than one half of the entire aggregate, the Document’s Cover Texts may be placed on covers that bracket the Document within the aggregate, or the electronic equivalent of covers if the Document is in electronic form. Otherwise they must appear on printed covers that bracket the whole aggregate. 8. TRANSLATION Translation is considered a kind of modification, so you may distribute translations of the Document under the terms of section 4. Replacing Invariant Sections with translations requires special permission from their copyright holders, but you may include translations of some or all Invariant Sections in addition to the original versions of these Invariant Sections. You may include a translation of this License, and all the license notices in the Document, and any Warranty Disclaimers, provided that you also include the original English version of this License and the original versions of those notices and disclaimers. In case of a disagreement between the translation and the original version of this License or a notice or disclaimer, the original version will prevail. If a section in the Document is Entitled Acknowledgements, Dedications, or History, the requirement (section 4) to Preserve its Title (section 1) will typically require changing the actual title. 9. TERMINATION You may not copy, modify, sublicense, or distribute the Document except as expressly provided for under this License. Any other attempt to copy, modify, sublicense or distribute the Document is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 10. FUTURE REVISIONS OF THIS LICENSE The Free Software Foundation may publish new, revised versions of the GNU Free Documentation License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. See http://www.gnu.org/copyleft/. Each version of the License is given a distinguishing version number. If the Document specifies that a particular numbered version of this License or any later version applies to it, you have the option of following the terms and conditions either of that specified version or of any later version that has been published (not as a draft) by the Free Software Foundation. If the Document does not specify a version number of this License, you may choose any version ever published (not as a draft) by the Free Software Foundation. ADDENDUM: How to use this License for your documents To use this License in a document you have written, include a copy of the License in the document and put the following copyright and license notices just after the title page: If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, replace the with...Texts. line with this:
with the Invariant Sections being LIST THEIR TITLES, with the Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST.
If you have Invariant Sections without Cover Texts, or some other combination of the three, merge those two alternatives to suit the situation. If your document contains nontrivial examples of program code, we recommend releasing these examples in parallel under your choice of free software license, such as the GNU General Public License, to permit their use in free software.
quarry-0.2.0/help/C/legal.xml0000644000175000017500000000476310132561445014431 0ustar bartbart Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled GNU Free Documentation License or in the file COPYING-DOCS distributed with this manual. DOCUMENT AND MODIFIED VERSIONS OF THE DOCUMENT ARE PROVIDED UNDER THE TERMS OF THE GNU FREE DOCUMENTATION LICENSE WITH THE FURTHER UNDERSTANDING THAT: DOCUMENT IS PROVIDED ON AN AS IS BASIS, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE DOCUMENT OR MODIFIED VERSION OF THE DOCUMENT IS FREE OF DEFECTS MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY, ACCURACY, AND PERFORMANCE OF THE DOCUMENT OR MODIFIED VERSION OF THE DOCUMENT IS WITH YOU. SHOULD ANY DOCUMENT OR MODIFIED VERSION PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE INITIAL WRITER, AUTHOR OR ANY CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY DOCUMENT OR MODIFIED VERSION OF THE DOCUMENT IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER; AND UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER IN TORT (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL THE AUTHOR, INITIAL WRITER, ANY CONTRIBUTOR, OR ANY DISTRIBUTOR OF THE DOCUMENT OR MODIFIED VERSION OF THE DOCUMENT, OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER DAMAGES OR LOSSES ARISING OUT OF OR RELATING TO USE OF THE DOCUMENT AND MODIFIED VERSIONS OF THE DOCUMENT, EVEN IF SUCH PARTY SHALL HAVE BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. quarry-0.2.0/help/C/quarry.xml0000644000175000017500000025260010530102211014643 0ustar bartbart Quarry"> ]> &app; Manual 2004 2005 2006 Paul Pogonyshev &LEGAL; Paul Pogonyshev
pogonyshev@gmx.net
Quarry Manual V&manrevision; &date; Paul Pogonyshev pogonyshev@gmx.net This manual describes version &appversion; of Quarry. Feedback To report a bug or make a suggestion regarding the &app; application or this manual, either send a message to quarry-dev@gna.org or use &app; bug tracker. Quarry quarry
Introduction The &app; application allows you to play the board games of Go, Amazons and Reversi. You can play with computer programs or with another human, and save, view and edit game records. &app; provides the following features: Support for Go, Amazons and Reversi games. Nice resizable board. Playing games: GNU Go, GRhino or any other GTP (Game Text Protocol) engine can be your opponent. Computer vs. computer and human vs. human games are an option too. Good support for time control. Games can be adjourned and later resumed. Game records: All games can be stored in widely supported SGF FF[4] file format. Fast and robust parser can read SGF files of any version. In particular, Kogo’s Joseki Dictionary can be browsed with &app;. Game Tree View allows for easy navigation of game records. Text search in comments is a powerful tool if you know what to search for. Go board position can be exported in a format suitable for inserting into Sensei’s Library. Support for various SGF labels and markup. &app; itself can play neither Go, nor Amazons, nor Reversi. To have a computer opponent, you need to find a program (e.g. GNU Go mentioned above) that supports GTP and register it in &app;. &app; does not have any support for Internet game servers and it will not be added before versions 0.3.x. Getting Started
To Start &app; You can start &app; from your Applications menu, it should typically be available under Games Board Games . However, this may depend on the exact way you installed the program and your operating system. &app; can also be started from the command line. Simply type quarry in and press Return. You can also have &app; open one or more game records immediatly after you start it. Just type quarry file1.sgf file2.sgf ... in the command line and press Return. &app; will start with specified file(s) open. Filenames don’t have to end in .sgf, but names of SGF files typically do have this suffix.
When You Start &app; When you start &app;, Control Center window is displayed:
&app; Control Center Shows &app; Control Center window.
The Control Center window consists of the following elements: New Game button This button allows you to start a new game. It will pop up the New Game dialog where you can select the game (Go, Amazons or Reversi), opponents and game-specific rules. New Game Record button Clicking this buttons allows you to create a game record without actually playing a game. New Game Record dialog will be shown, asking you for basic game record parameters. Open Game Record button This button allows you to select a game record for viewing and/or editing. You will need to pick the file with the game record in the standard Open File dialog. Resume Game button Click this button to resume a game you adjourned earlier. Actually, you can resume about any unfinished game, even one you started in a different client. A standart Open File dialog will be popped up for you to select the file containing the game record you wish to resume. Preferences button This button opens the &app; Preferences dialog. Quit button Closes all windows and quits the program. However, if there are unsaved changes in any of the open game records, you will be asked what to do with them first.
Usage
To Start a New Game To start a new game, click the New Game button in the &app; Control Center window or choose File New Game… menu item in any of the already open Board Windows. The New Game dialog will appear, where you can choose the kind of game you want and the opponents. If you want to play against a computer program, you need to register it in &app; first (once only, of course.) To do this, click the Manage Engine List button in the dialog. For more information, see the detailed description of New Game dialog.
To Open a Game Record You can open a game record in one of three ways: Click the Open Game Record button in the Control Center window. &app; will display the Open SGF File dialog. Select the file with the game record you want to open and click the OK. Choose File Open menu item or simply press Ctrl+O in any opened Board window. Similarly to the previous case, &app; will display the Open SGF File dialog. When starting &app; from the command line, specify the name of file (or several names at once): quarry file1.sgf file2.sgf ... The specified file(s) will be opened automatically.
To Save a Game Record To save a game record, choose File Save menu item in its Board window (or simply press Ctrl+S.) If the game record does not yet have a filename, &app; will display the Save As dialog. Enter the name for the file, then click the OK. If you want to save a game record under a different filename, choose File Save As menu item. Enter a name for the file in the Save As dialog and click OK.
To Register a Game-Playing Program To register a game-playing program in &app;, first open the Preferences dialog and select GTP Engines category in its left pane. (You can also click the Manage Engine List button in the New Game dialog, which immediatly displays the GTP Engines category.) Then click the Add button and, in the appeared dialog, enter the command line required to launch the program in GTP mode. You should consult the program’s manual to find out how the command line should look like. For instance, command line for GNU Go should be like this (note the double hyphens): gnugo --mode gtp --quiet Other programs may require different options or no options at all.
To Adjourn a Game To adjourn a game, choose Play Adjourn Game menu item. If the game has never been saved yet, you will need to enter the name of the file you would like to store it in. Actually, adjourning differs from saving only in that it closes the game’s window.
To Resume a Game To resume a previously adjourned game, click Resume Game button in the &app; Control Center window or select Resume Game… item from the File menu. You will be prompted for the file that contains the game record. When you select the file, Resuming Game Dialog pops up, where you should specify the players. &app; will try to guess the opponents based on the data stored in the game record, but it can make a mistake in determining whether there are any computer players and which engines should play. You will always have the final say, though, and will be able to correct any mistakes. If the game you select is already finished, you will be prompted to open it for viewing and/or editing instead of resuming.
Quarry Windows and Menus
New Game Dialog The New Game dialog consists of two pages, Game & Players and Game Rules. When you open the dialog, the first page appears. When you click Next button, the second page is displayed, which is specific for each of three games—Go, Amazons and Reversi.
Game & Players Page On this page you can select one of three available games and the opponents. You can make selections in arbitrary order—first choose the game and then the opponents or the other way round. At any time, all playable combinations of games and computer players are marked with Yes icons, while all unplayable combinations are marked with No icons. The Next button is sensitive only when a playable combination of game and opponents is selected. Before playing against a computer program (e.g. GNU Go, you need to register it in &app;. See GTP Engines section for how to do this. Game & Players page conists of the following controls: Game section Here you can select the game you want to play, either Go, Amazons or Reversi (also known as Othello). Note that most programs can play only one game. White Player and Black Player sections This set of controls determines the opponents. Each opponent can be either a human or a computer program. For a human player you can specify her name (defaults to your name as reported by the system.) Computer opponent should be selected from the drop-down list. If the list does not contain the program you want to play against, click the Manage Engine List at the end of the dialog to register the program in &app;. Which player is to move first depends on the game. In Go and Reversi black moves first, while in Amazons white has the first turn. You can always change sides with the Swap button to the right. Swap button This button allows you to easily swap players’ sides. It does nothing else but copying settings from White Player section to Black Player section and vice versa. Manage Engine List button This button opens &app; Preferences dialog at the GTP Engines page. A convenient way to register new program and/or modify parameters of the already registered ones just before starting a new game. Next button When you are done with this page, click the Next button to tweak game specific rules on the next page.
Game Rules Page On this page you can select the rules for the game. The page has two parts. The upper part is different for each of Go, Amazons and Reversi games and contains game-specific rules. The lower part contains time limit settings controls and is the same for all three games. It is described last. When you have selected the rules you want, click the Play button to start the game.
Go Rules Go has many different rule sets that differ in scoring details, treating of some special positions etc. Currently, &app; doesn’t make any difference between them. However, existing rule controls should be enough in most cases. Board Size spin button Choose the size of board for the game here. Go is traditionally played on a 19×19 board. 9×9 and 13×13 boards are also common. &app; doesn’t limit you to these—choose any size between 5×5 and 25×25 inclusive. Traditional board size buttons These buttons allows you to quickly select one of three traditional Go board sizes—either 9×9, 13×13 or 19×19. Handicap controls When one of the players is weaker, it is common practice in Go to give him handicap stones. This gives her better chances to win and makes the game more challenging (and thus more interesting) for the stronger player. The weaker player is traditionally playing as black. &app; supports both fixed (also known as Japanese) and free (Chinese) handicaps. In the first case, handicap stones are placed following a traditional pattern, at hoshi points. Maximal fixed handicap is 9 stones. With free handicap, on the other hand, black player actively places the handicap stones at any intersections on the board. Free handicap is practically not limited. &app; treats free handicap as non-obligatory: it allows black to place fewer handicap stones than specified in game rules (but not less than two.) If you want an even game, simply set the handicap to zero. Komi spin button Komi is the compensation to the white player for playing second. It is usually non-integer to make draws impossible. The currently suggested komi for even game on 19×19 board is 6.5 points. Smaller (or even negative) komi gives some advantage to black player and can be used in addition to or instead of handicap. See also time limit settings description.
Amazons Rules At present, Amazons rules in &app; are limited to board size and common time limit settings. Standard board size for Amazons is 10×10 (which is also selectable with the small button to the right), but you can choose anything from 5×5 to 25×25 inclusive.
Reversi Rules Reversi rules in &app; are limited to board size and time limit settings described just below this section. Standard board size for Reversi is 8×8, though 10×10 boards are not uncommon either. This is reflected by the choice of traditional board sizes with the buttons to the right. However, in &app; you can select any even board size from 6×6 to 24×24 inclusive.
Time Limit Settings &app; allows to play games with limited time for both players. This also applies to computer program players—they have to honor the alloted time or lose. Of course the programs are properly notified about the time limit settings and the remaining time. Computer opponents use CPU time to generate moves. This means that they usually need less time on faster machines and more on slower machines. Also, if you run a computationally intensive task while playing, your computer opponents may become slower. Finally, certain computer programs may also think on opponent’s time. &app; has four types of time control: No limit Both opponents can take as much time as they like on each move, there are no limits. In this mode you can select the Keep track of total time option. Then &app; will display the total time spent on move pondering by each player. This is purely for your information and serves no other purpose. Limited time for entire game Each player has limited time to play the whole game. If a player fails to finish the game in the alloted time, she loses. Note that time limit doesn’t depend on the number of moves in the game. Limited time per move Each move has to be played in fixed time. Time not used is not stored and not added to available time on next moves. When using this mode, keep in mind that in most games there are difficult positions that require more pondering time. Canadian overtime (also known as Canadian byo-yomi) This time control is often used in Go, but has nothing Go-specific, so it can be used in any other move-based game. Canadian overtime has the advantage of imposing certain speed of play, but, at the same time, allowing to occasionally spend more time on important moves. Canadian overtime has three parameters: main time, overtime period length and moves per overtime. Both players begin game in their main time. During main time they can play any number of moves at any speed. When main time for a player is up, first overtime period begins. During each overtime period a player has to play the specified number of moves (moves per overtime.) If she fails to do so, she loses on time. Otherwise, next overtime (of the very same length) begins and the player has to play the same number of moves this before the time is up again. The number of overtimes is unlimited and they are completely equal to each other: time not used in one overtime period is not stored and not added to other overtime periods.
New Game Record Dialog The New Game Record dialog allows you to start a new game record without actually playing a game. When you are done entering game record information, press the Create button. Or press the Cancel button to cancel game record creation. The dialog consists of the following controls besides the mentioned buttons: Game selectors Here you choose the game you want to create a record of—Go, Amazons or Reversi. All the games supported by &app; are listed. Rules section This section contains various controls for basic game rules. They are described in more details in the New Game dialog section. One important change is the Place stones check button to the right of handicap spin button. It determines whether &app; should place the handicap stones for you, or not. Stones are placed as if the handicap is fixed, but you can always change stones setup later if needed. Short Game Information Here you can enter the names of white and black player and the name of the game. You can change or expand this information later, using the Game Information dialog .
Resuming Game Dialog The Resuming Game Dialog allows you to specify or correct game players when resuming a game. It also shows some information about the game, most of which is not editable. You can specify both game players and fix their names, if needed. There are two radio buttons and a combo box for each player. Radio buttons control whether a player is a human or a computer (some GTP engine.) If you select to let computer control a player, you can choose any available GTP engine from the list for it. &app; tries to guess players based on their names, as stored in the game record. Normally, if the game was adjourned in &app; and you don’t alter computer player names, it should guess correctly. However, you can always override and correct its decision.
Board Windows Board windows are the main part of &app;. They are used to play games and view and edit game records. To the left in a window is the game board itself. The exact appearance of the board depends on the current game (Go, Amazons or Reversi) and can be configured. On the right side of the window there is information pane, including the comment window. There can also be the game tree view to the bottom of the right pane.
&app; Board Window showing Kogo’s Joseki Dictionary Shows &app; Board Window with Kogo’s Joseki Dictionary.
The Board Board displays current game position, including pieces, markup, labels and variations of the current node. Coordinate labels are shown on the edges of the board. They depend on the current game. In the top-left corner a small rectangle is drawn if the board has focus. The last move made is marked. Depending on the markup theme, this can be a cross or a bullet. On the screen shot above, last placed stone at P15 is marked with a cross. This section can be improved.
Variations &app; treats variations as siblings of the current node. This is like Jago does and unlike CGoban. You always see the current variation and it is not a potential for the next node/move. On the board, non-current variations that contain a move are shown as small ghostly pieces. Variations that don’t contain a move or contain a pass move (in Go) can be seen only in the Game Tree View. Screen shot above shows two variations—at Q18 and Q19—of the white move on the board. You can activate (switch to) a particular variation by right-clicking on the ghost stone on the board. For instance, right-clicking on Q18 in the window shown in the screen shot would make White Q18 the current move. In rare cases when there are multiple variations with the same move, right-clicking and shift-right-clicking scrolls through the list of such variations. Alternative ways of switching to different variations include using the Game Tree View and using menu items, toolbar buttons or keyboard shortcuts.
Keyboard Navigation Board has several keyboard shortcuts to ease game record navigation. Remember, that these shortcuts are active only if the board has focus, as indicated with a small rectangle in the top-left corner. Otherwise, you should type them with Alt modifier: more complicated shortcuts work everywhere in Board Windows.
Board keyboard shortcuts Shortcut Action Left arrow Go to the previous node (current node’s parent.) Right arrow Go to the next node (current node’s child.) By default, next node is the first child, but it is remembered if you switch to a different child. Page Up Go ten nodes backward. If there are less than ten nodes, stop at the root of the game tree. Page Down Go ten nodes forward. If there are less than ten nodes, stop at the branch end. Home Go to the game tree root. End Go to the last node in the current branch (variation.) Up arrow Go to the previous variation of the current node. I.e. go to the previous child of the parent of the current node. Down arrow Go to the next variation of the current node. I.e. go to the next child of the parent of the current node.
Board Window Information Pane Game Information Pane shows information about the game in general, about the last move made and about the current node. Some of its components are optional and can be hidden in the View menu. Player Information At the top of the pane is the player information for both players. It shows player name, team and rank (first line), plus game-specific information (second line.) If name is missing, string [unknown] is shown in its place. If team or rank is not specified, they are simply not shown. Game-specific information includes number of captures made by a player plus white player’s komi for Go; and number of disks on the board for Reversi. Player Clocks Close to player information are the clocks. When a game is played, they display the time left for a player. Additionally, they can display number of pieces left in the current Canadian overtime period in smaller digits to the right. When a game record is viewed, clocks display time left after move in the current node has been played. Clocks can be empty if a game is played without time limits. Move Information Below player information and clocks a single line displays move information. It shows last move (usually, current node’s move) number and the move itself. Afterwards, player to move is specified. This can sometimes seemingly contradict with the last move, but it is allowed to override player to move in game records (see Edit Player to Move submenu.) This feature is often used in problem collections. Game Result Below move information game result is shown, but only at the very last node of the game. This is done in order to prevent spoiling of watching of unknown games. Also, if the game lacks any result or is unfinished there is nothing to show at all. Game Action Buttons Yet below there are game action buttons. These include Pass (for Go) and Resign. Because functionality of this buttons is quite rarely used and they take up space, you can hide them using View Game Action Buttons menu item. They are shown by default mainly as a reminder of the options you have. Comment Window Most of the right side is taken by comment window. It displays any commentary the current node has. Comment can be edited and you don’t need to take any actions to save your edits. Edits are also saved in the undo history and can be undone and redone freely. If the current node has a name, it is shown above comment in bold underlined font. It can be edited just like comment and you don’t need any special steps to edit node name. However, to create a name for a node that lacks one, use Edit Edit Node Name menu item. It will insert a placeholder for node name in the window, which you can then replace with actual name. To delete a name, simply delete all its text. &app; will notice it and remove node line from the window. Game Tree View Finally, there can be the Game Tree View, described in detail in the next section. Its visibility is controlled by View Game Tree menu item and preferences.
Game Tree View Game Tree View shows game record as a tree in a style used by CGoban1. Generally, it is of interest only if the game record contains variations. For instance, a debut/joseki dictionary or a well-annotated game with alternate branches. Visibility of Game Tree View is controlled with Game Tree item in View menu and with preferences. Node with a move of a specific player, including pass move in Go, are shown as pieces of player’s color. Other nodes, including position setup, at present lack any icon. Nodes that belong to a same branch (variation) are connected with a line and the current branch is highlighted. Current node is shown within a black rectangle. If it is not visible, you can bring it onscreen using Recenter on Current Node command from the View menu. Subtrees can be collapsed/expanded by right-clicking on subtree root. This is useful to hide nodes you are not interested in currently. Roots of collapsed nodes have a cross on them. If a mouse is held over a node, a tooltip with information about the node is shown. It includes move number, move itself, node name and comment. Of course, some of these can be absent from the tooltip, if they are not present in the node to begin with. If node comment is too long, only first part of it is shown. Tooltips can be disabled in preferences if they look too distracting to you.
Board Window Menu
<guimenu>File</guimenu> menu New Game… Show New Game Dialog to start a new game. New Game Record… Show New Game Record Dialog to create a new game record without actually playing a game. Open… Open a game record. Record may as well have been saved in a different application. Resume Game… Open a game record and show Resume Game Dialog to resume the game. Games adjourned in different applications can be resumed too. Export… ASCII Diagram Export current board position as a free-format ASCII diagram to the clipboard. Useful e.g. to mail game position if you don’t need a full-blown SGF. Only board position without any markup is stored. Sensei’s Library Diagram Export current board position as a Sensei’s Library diagram to the clipboard. Pieces, circle and square markup and labels are exported. Result, of course, can be imported into the Sensei’s Library. Only available for Go games. It is currenly impossible to export only part of the board. You need to manually delete unneeded information in such cases. Save Save the game record under its filename. If the game record is new, ask for filename first. This command is disabled if the game record is not modified. Save as… Save the game record under a different filename. Close Close the board window. If the game record is modified, ask whether to save it first. Quit Quit &app;. Prompts to save any unsaved game records first.
<guimenu>Edit</guimenu> menu Undo Undo the last change made in the current game record. Redo Redo the last undone change made in the current game record. Cut Cut subtree having the current node as its root into clipboard. Copy Copy subtree having the current node as its root into clipboard. Paste Paste subtree contained in clipboard as last child of the current node. This command may fail if e.g. the subtree was copied from a different kind of game. It is currently impossible to determine if the clipboard contains anything, therefore this menu item is sensitive even if there is no subtree to paste. Delete Node Delete the current node together with its children from the game record. Tools Tools are very important as they are the most used (together with comment editing) way of modifying game records. Active tool can also be changed using the editing toolbar of from keyboard. Move Tool Activate tool which is used to play new moves in the current game record. Setup Tool Activate tool which is used to add and remove pieces from the current node. Cross Markup Activate tool which adds cross markup to the current position. Circle Markup Activate tool which adds circle markup to the current position. Cross Markup Activate tool which adds cross markup to the current position. Square Markup Activate tool which adds sqiare markup to the current position. Triangle Markup Activate tool which adds triangle markup to the current position. Selected Markup Activate tool which adds selected markup to the current position. It is not recommended to use this type of markup, as it has no standard appearance and may confuse other users. Label Tool Activate tool which places single letter and arbitrary text labels on the board. Number Tool Activate tool which places number labels on the board. Scoring Tool Activate tool which scores the current position. This tool is valid only for Go games. Add Empty Node Add an empty children to the current node. Standard way of adding children is by playing moves, but this command allows you to add node without any move. Move Branch Up Move current branch up i.e. swap it with the previous branch. Useful to rearrange branches in the game record. Move Branch Down Move current branch down i.e. swap it with the next branch. Useful to rearrange branches in the game record. Edit Node Name Edit the name of the current node. If the node has no name, it is inserted. Otherwise, you can edit node just by directly modifying it in the comment window and this command simply selects the name. Set Move Number Set the number of the current move. Normally, move number is incremented by one after each move, but there are cases when this must be overridden, for instance, if game record starts not at the game beginning. Player to Move Sometimes it is needed to explicitly set who is to move next, for instance, in a problem collection. White Set player to move to White, regardless of what game rules say. Black Set player to move to Black, regardless of what game rules say. By Game Rules Let game rules determine who is to move next (this is the default.) Find Show the Find Dialog to find a string in node comments and/or names. Find Next Repeat the last search in forward direction. If there were no last search, acts just as Find menu item. Find Previous Repeat the last search in backward direction. If there were no last search, acts just as Find menu item. Game Information Show the Game Information Dialog to view and/org edit game information. Preferences Show the Preferences Dialog to change &app; settings.
<guimenu>View</guimenu> menu Main Toolbar Show or hide main toolbar in this window. Editing Toolbar Show or hide editing toolbar in this window. Navigation Toolbar Show or hide navigation toolbar in this window. Game Action Buttons Show or hide Game Action Buttons (Pass for Go game and Resign.) They have quite rarely used functionality and take precious space on the right. Game Tree Show or hide Game Tree View in this window. Its visibility can also be globally changed in the preferences. Recenter on Current Node Recenter Game Tree View on the current node. Of course, the view should be shown to begin with. Control Center Show &app; Control Center.
<guimenu>Play</guimenu> menu Pass Play a pass move. (Only valid in Go.) Resign Resign current game. Opponent is declared a winner. Adjourn Game Adjourn current game and save game record, so it can be later resumed.
<guimenu>Go</guimenu> menu This menu’s title is English verb go, not game name. Previous Node Go to the previous node (current node’s parent.) Next Node Go to the next node (current node’s child.) By default, next node is the first child, but it is remembered if you switch to a different child. Ten Nodes Backward Go ten nodes backward. If there are less than ten nodes, stop at the root of the game tree. Ten Nodes Forward Go ten nodes forward. If there are less than ten nodes, stop at the branch end. Root Node Go to the game tree root. Variation Last Node Go to the last node in the current branch (variation.) Previous Variation Go to the previous variation of the current node. I.e. go to the previous child of the parent of the current node. Next Node Go to the next variation of the current node. I.e. go to the next child of the parent of the current node. Go to Named Node… Go to a named node given its name. You can also use Find Dialog for this purpose, but this way there is completion on node names.
<guimenu>Help</guimenu> menu Contents Show this help. About Show short information about &app; and its version.
Find Dialog Find Dialog allows you to search for text in node names and/or comments. It is invaluable for large game records, especially those containing multiple branches, like debut/joseki dictionaries. When a node with matching text is found, board window switches to it, if needed. Matching text is selected in information pane. Search can be repeated later without opening this dialog using Edit menu items or from keyboard. Dialog contains several controls: Search for field Enter the text to search for here. Field also has a history with up to 10 most recently found strings. Optons There a few options that control the search. It can be case-sensitive or case-insensitive. It can be restricted to whole words or include any match. Search can be wrapped around when the end or beginning of search domain is reached, or stop there. You can also select Auto-close this dialog button. In this case, the dialog will be hidden after any successful search. You can repeat search afterwards using Find Next and Find Previous items of Edit menu or using Ctrl+G and Shift+Ctrl+G key combinations. Search scope Search domain can include the whole game record tree or the current node only. The latter option is only interesting if current node’s comment is very long. Search can also be performed in node names, comments or both. Typically, you will want to search in both of them, but can sometimes wish to restrict search to decrease number of matches you are not interested in. Next and Previous buttons When search parameters are entered, click one of this buttons, depending on direction you wish search to be performed. Buttons can be pressed repeatedly to repeat search. However, if Auto-close this dialog option is selected, dialog will be closed on first successful search. These buttons can be disabled if a search in certain direction certainly won’t hit any matches. However, they are many cases when this cannot be determined in advance (quickly), so activating one of these buttons is not guaranteed to find anything. Close button Close the dialog without performing any further search. Use it when you’ve finished searching or changed your mind.
Game Information Dialog The Game Information Dialog allows you to set values that describe game tree as a whole and are not specific to a particular move or position in the game. It has a lot of fields which are splitted in three pages. All fields are optional and can be empty (not set), but defining them gives additional description to the game. Fields on the first page (General) describe the game opponents, rules of the game and non-spoiling game details. Field on the second page (Description & Result) are generally spoiling and can even disclose game outcome. The third page (Game Record) describe the record itself. White Player and Black Player This group of fields allows you to describe the opponents in the game. The Name fields should be obvious. The Team fields are used when the game is a part of a match between two teams, for instance national teams. Usually, they are left empty. The Rank of the opponents can be entered in the appropriate fields. This is usually the rank as applies to the game in question. For instance, this can be the rank awarded by the federation guiding the tournament or it can be the rank of an Internet server where the game took place. Values of these fields are also displayed in the right column of board windows. Game Name The name of the game. This field can be empty if the game is not special and doesn’t have a distinguished name. Place The place the game took place at. This can be a geographical location or the name of an Internet server. Date The date the game took place on. It should be in the international format of YYYY-MM-DD. For instance 2006-07-23 means 23 July 2006. Event The event this game is part of. For instance, this can be the name of a tournament. This field is often empty. Round The round this game is part of. For instance 1st round or Semifinal. This field is often empty, especially if Event is. Rule set Descriptive name of the rules this game was played in accordance with. For instance, for Go this can be Japanese, Chinese etc. Handicap For Go only: number of stones the black was allowed to place on his first move. This field is either 0 or not set for the games with no handicap. Value of this field is only informational. It doesn’t imply any particular setting of the black stones. Komi For Go only: the compensation, in points, the white receives for having the second turn. Can be negative or not set. However, it should always be set for games with non-zero komi, as otherwise proper scoring is impossible. Main time Main time each player has. Should not be set if the game is played with no time limit. Overtime Description of the overtime rules used for this game. For instance, 25/600 Canadian means Canadian overtime with 10 minutes (600 seconds) for every 25 moves. Game result The result of the game in SGF format. Valid <guilabel>Game result</guilabel> values Value Meaning Void There is no result yet (the game is not finished) or there can be no result at all (e.g. for problems.) 0 or Draw The game is draw, i.e. is finished, but there’s no winner. W+score or B+score A player has won by the specified score. For instance, W+6.5 means that white has won by 6.5 points. W+ or B+ A player has won. Used mainly for the games without a notion for score, e.g. Amazons. W+Resign or B+Resign or W+R or B+R A player has won by resignation. W+Time or B+Time or W+T or B+T A player has won on time. I.e. his opponent exceeded his time limit. W+Forfeit or B+Forfeit or W+F or B+F A player has won by forfeit, e.g. his opponent made an illegal move. ? Game result is unknown.
Opening played Description of the opening played in the game. This field is often empty. Comment / description Description for the entire game. It can be some background information and/or the summary of the game. Copyright string Short copyright information for the game record. Annotator The name of the person who provided comments (annotation) for the game. Source The source of the game record (book, journal etc.) Often is empty if the game record was in electronic form to begin with. Entered by Name of the person who entered the game record. Usually empty for automatically created records.
Settings To configure &app; either click the Preferences button in the Control Center window or choose Edit Preferences menu item. The Preferences dialog is displayed. It consists of the following categories: General Interface Editing & Viewing Game Tree GTP GTP Engines Game Records (SGF) Saving Board Appearance Go Board Appearance Amazons Board Appearance Reversi Board Appearance
General Interface General interface of &app; can be configured at this page. It is not really related to the functionality of the application. File Chooser Dialog Style You can use either the new file chooser or the old one, which was the default on pre-2.4 GTK+. This option will be removed in &app; ver. 0.3. It was added when the new file chooser was in early development stages and had significant usability problems. Nowadays it has little sense to keep supporting the old one. Toolbar Styles By default, &app; uses desktop settings for all its toolbars. However, you can choose specific style for each of three toolbar kinds. You can also return toolbars to using desktop defaults here.
Game Tree Here you can customize appearance and behavior of the Game Tree View. Show Game Tree You can choose whether the Game Tree View is shown in Board Windows by default. If you choose Automatically option, it will be shown if game record has anything in addition to the main branch. In any case, you can show or hide the view manually, using View Game Tree menu item. In this case, automatic showing will be disabled, even if corresponding option is selected. Track Tree’s Current Node You can choose whether the view should track the current node, i.e. reposition itself to show it. In automatic mode it only tracks the current node if it was showing it before. This mode prevents the view from scrolling if you intentionally scrolled it to some part of the tree not containing the current node. You can always force the view to display the current node by using View Recenter on Current Node menu item. You can also choose whether the view will scroll minimal possible distance while tracking (i.e. the current node will be somewhere near an edge), or if it will always recenter on the current node if needed. These options don’t make sense if tracking is disabled, so they are disabled then too. Show tooltips Choose whether Game Tree View should show tooltips over nodes. See view description for details. You may want to disable tooltips if they look too distracting.
GTP Engines At this page, all game-playing programs registered in &app; are shown. You can register new programs and modify information in existing entries. All registered programs are shown in the list labeled List of GTP engines. When you select one of them, some information about it is shown in the lower part of the dialog. This inlcudes program name, version, supported game(s) and command line. The command line is exactly what you specified while registering the program, while the rest of information is reported by the program itself. Programs from the list are also shown in the New Game and Resuming Game dialogs as available computer opponents. However, you can hide some of them by removing the mark beside the program name in the Show column. This may be better than removing a program record altogether in case you later regain your interest in it. Also, some GTP engines may be listed in &app; system-wide settings; those cannot be removed, only hidden. There are also five buttons on this page: Add and Modify buttons These two buttons allow you to register another program, or modify information about an already registered one, correspondingly. They both pop up the GTP Engine Information dialog. Remove button This button removes a game-playing program from the list of registered programs. The unregistered program will not appear in the New Game dialog as an available opponent. Of course, the program itself is not touched and you can re-register it in &app; later. Move Up and Move Down buttons Using these two buttons you can rearrange registered programs. Computer opponents in the New Game dialog are listed in exactly the same order as on this page, so you may want to place more frequently used programs on the top. Another way to reorder GTP programs is to drag-and-drop their names in the list.
GTP Engine Information Dialog This dialog is shown whenever you want to register a game-playing program in &app; or modify information about an already registered one. Depending on the situation, it can be titled either New GTP Engine or Modify GTP Engine Information. After you fill in the dialog, press the Add or OK button. &app; will launch the program to check if it works and ask it for some information. If the message Querying engine’s name, version and known commands… appears and persists for too long (more than a few seconds), this most likely indicates that the command line you specify starts the program in non-GTP mode or starts a wrong program to begin with. If you don’t expect the program to be very slow on initialization, then click the Cancel button and fix the command line. The dialog has two text entry fields: Command line The command line to start the program should be entered here. You can use the Browse button to select the program, but normally just specifying program filename is enough. (More exactly, it is enough if the program is installed in a directory that is in your $PATH environment variable.) In any case, you should enter program-specific options after its filename. To find out which options should be used, see the manual of the program in question. For GNU Go, the command line should look like this (note the double hyphens): gnugo --mode gtp --quiet You may also want to specify additional options. See GNU Go documentation for more information. Screen name In this field you can specify the way &app; will display the name of the program. You can enter the full name or use special symbols %n and %v. They will be replaced with the name and version of the program as it reports them itself. In most cases the default value of %n %v is what you want, but sometimes it makes sense to alter it. For instance, you can specify %n %v level 5 here if you fixed program’s level in the command line. If, for some reason, you need the percent sign in the name, type it in as %% (the percent sign is used as escape symbol in this field.)
Saving Game Records Currently, you can only specify whether to save game records in UTF-8 or to preserve original encoding. The former option is recommended because UTF-8 can encode any character and because Quarry loads UTF-8 encoded game records faster than with any other encoding. However, you may want to preserve original encoding if, for instance, you use other SGF editor/viewer with poor support for UTF-8 or this is required for some reason for distribution.
Go Board Appearance Sorry, not documented yet…
Amazons Board Appearance Sorry, not documented yet…
Reversi Board Appearance Sorry, not documented yet…
&AUTHORS; &FDL; quarry-0.2.0/help/C/quarry.html0000644000175000017500000036610110530105471015024 0ustar bartbart Quarry Manual

Quarry Manual

Paul Pogonyshev

This manual describes version 0.2 of Quarry.

Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled “GNU Free Documentation License†or in the file COPYING-DOCS distributed with this manual.

DOCUMENT AND MODIFIED VERSIONS OF THE DOCUMENT ARE PROVIDED UNDER THE TERMS OF THE GNU FREE DOCUMENTATION LICENSE WITH THE FURTHER UNDERSTANDING THAT:

  1. DOCUMENT IS PROVIDED ON AN “AS IS†BASIS, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE DOCUMENT OR MODIFIED VERSION OF THE DOCUMENT IS FREE OF DEFECTS MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY, ACCURACY, AND PERFORMANCE OF THE DOCUMENT OR MODIFIED VERSION OF THE DOCUMENT IS WITH YOU. SHOULD ANY DOCUMENT OR MODIFIED VERSION PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE INITIAL WRITER, AUTHOR OR ANY CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY DOCUMENT OR MODIFIED VERSION OF THE DOCUMENT IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER; AND

  2. UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER IN TORT (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL THE AUTHOR, INITIAL WRITER, ANY CONTRIBUTOR, OR ANY DISTRIBUTOR OF THE DOCUMENT OR MODIFIED VERSION OF THE DOCUMENT, OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER DAMAGES OR LOSSES ARISING OUT OF OR RELATING TO USE OF THE DOCUMENT AND MODIFIED VERSIONS OF THE DOCUMENT, EVEN IF SUCH PARTY SHALL HAVE BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES.

Feedback

To report a bug or make a suggestion regarding the Quarry application or this manual, either send a message to or use Quarry bug tracker.

Revision History
Revision Quarry Manual V0.2November 2006

Paul Pogonyshev


Introduction

The Quarry application allows you to play the board games of Go, Amazons and Reversi. You can play with computer programs or with another human, and save, view and edit game records.

Quarry provides the following features:

  • Support for Go, Amazons and Reversi games.

  • Nice resizable board.

  • Playing games:

    • GNU Go, GRhino or any other GTP (Game Text Protocol) engine can be your opponent.

    • Computer vs. computer and human vs. human games are an option too.

    • Good support for time control.

    • Games can be adjourned and later resumed.

  • Game records:

    • All games can be stored in widely supported SGF FF[4] file format.

    • Fast and robust parser can read SGF files of any version.

    • In particular, Kogo’s Joseki Dictionary can be browsed with Quarry.

    • Game Tree View allows for easy navigation of game records.

    • Text search in comments is a powerful tool if you know what to search for.

    • Go board position can be exported in a format suitable for inserting into Sensei’s Library.

    • Support for various SGF labels and markup.

Note

Quarry itself can play neither Go, nor Amazons, nor Reversi. To have a computer opponent, you need to find a program (e.g. GNU Go mentioned above) that supports GTP and register it in Quarry.

Note

Quarry does not have any support for Internet game servers and it will not be added before versions 0.3.x.

Chapter 1. Getting Started

To Start Quarry

You can start Quarry from your Applications menu, it should typically be available under Games → Board Games. However, this may depend on the exact way you installed the program and your operating system.

Quarry can also be started from the command line. Simply type quarry in and press Return.

You can also have Quarry open one or more game records immediatly after you start it. Just type

quarry file1.sgf file2.sgf ...

in the command line and press Return. Quarry will start with specified file(s) open.

Note

Filenames don’t have to end in .sgf, but names of SGF files typically do have this suffix.

When You Start Quarry

When you start Quarry, Control Center window is displayed:

Figure 1.1. Quarry Control Center


		Shows Quarry Control Center window.

The Control Center window consists of the following elements:

New Game button

This button allows you to start a new game. It will pop up the New Game dialog where you can select the game (Go, Amazons or Reversi), opponents and game-specific rules.

New Game Record button

Clicking this buttons allows you to create a game record without actually playing a game. New Game Record dialog will be shown, asking you for basic game record parameters.

Open Game Record button

This button allows you to select a game record for viewing and/or editing. You will need to pick the file with the game record in the standard Open File dialog.

Resume Game button

Click this button to resume a game you adjourned earlier. Actually, you can resume about any unfinished game, even one you started in a different client. A standart Open File dialog will be popped up for you to select the file containing the game record you wish to resume.

Preferences button

This button opens the Quarry Preferences dialog.

Quit button

Closes all windows and quits the program. However, if there are unsaved changes in any of the open game records, you will be asked what to do with them first.

Chapter 2. Usage

To Start a New Game

To start a new game, click the New Game button in the Quarry Control Center window or choose File → New Game… menu item in any of the already open Board Windows. The New Game dialog will appear, where you can choose the kind of game you want and the opponents.

If you want to play against a computer program, you need to register it in Quarry first (once only, of course.) To do this, click the Manage Engine List button in the dialog.

For more information, see the detailed description of New Game dialog.

To Open a Game Record

You can open a game record in one of three ways:

  • Click the Open Game Record button in the Control Center window. Quarry will display the Open SGF File dialog. Select the file with the game record you want to open and click the OK.

  • Choose File → Open menu item or simply press Ctrl+O in any opened Board window. Similarly to the previous case, Quarry will display the Open SGF File dialog.

  • When starting Quarry from the command line, specify the name of file (or several names at once):

    quarry file1.sgf file2.sgf ...

    The specified file(s) will be opened automatically.

To Save a Game Record

To save a game record, choose File → Save menu item in its Board window (or simply press Ctrl+S.) If the game record does not yet have a filename, Quarry will display the Save As dialog. Enter the name for the file, then click the OK.

If you want to save a game record under a different filename, choose File → Save As menu item. Enter a name for the file in the Save As dialog and click OK.

To Register a Game-Playing Program

To register a game-playing program in Quarry, first open the Preferences dialog and select GTP Engines category in its left pane. (You can also click the Manage Engine List button in the New Game dialog, which immediatly displays the GTP Engines category.)

Then click the Add button and, in the appeared dialog, enter the command line required to launch the program in GTP mode. You should consult the program’s manual to find out how the command line should look like. For instance, command line for GNU Go should be like this (note the double hyphens):

gnugo --mode gtp --quiet

Other programs may require different options or no options at all.

To Adjourn a Game

To adjourn a game, choose Play → Adjourn Game menu item. If the game has never been saved yet, you will need to enter the name of the file you would like to store it in.

Actually, adjourning differs from saving only in that it closes the game’s window.

To Resume a Game

To resume a previously adjourned game, click Resume Game button in the Quarry Control Center window or select Resume Game… item from the File menu. You will be prompted for the file that contains the game record.

When you select the file, Resuming Game Dialog pops up, where you should specify the players. Quarry will try to guess the opponents based on the data stored in the game record, but it can make a mistake in determining whether there are any computer players and which engines should play. You will always have the final say, though, and will be able to correct any mistakes.

If the game you select is already finished, you will be prompted to open it for viewing and/or editing instead of resuming.

Chapter 3. Quarry Windows and Menus

New Game Dialog

The New Game dialog consists of two pages, Game & Players and Game Rules. When you open the dialog, the first page appears. When you click Next button, the second page is displayed, which is specific for each of three games—Go, Amazons and Reversi.

Game & Players Page

On this page you can select one of three available games and the opponents. You can make selections in arbitrary order—first choose the game and then the opponents or the other way round. At any time, all playable combinations of games and computer players are marked with “Yes†icons, while all unplayable combinations are marked with “No†icons. The Next button is sensitive only when a playable combination of game and opponents is selected.

Note

Before playing against a computer program (e.g. GNU Go, you need to register it in Quarry. See GTP Engines section for how to do this.

Game & Players page conists of the following controls:

Game section

Here you can select the game you want to play, either Go, Amazons or Reversi (also known as Othello). Note that most programs can play only one game.

White Player and Black Player sections

This set of controls determines the opponents. Each opponent can be either a human or a computer program. For a human player you can specify her name (defaults to your name as reported by the system.) Computer opponent should be selected from the drop-down list. If the list does not contain the program you want to play against, click the Manage Engine List at the end of the dialog to register the program in Quarry.

Which player is to move first depends on the game. In Go and Reversi black moves first, while in Amazons white has the first turn. You can always change sides with the Swap button to the right.

Swap button

This button allows you to easily swap players’ sides. It does nothing else but copying settings from White Player section to Black Player section and vice versa.

Manage Engine List button

This button opens Quarry Preferences dialog at the GTP Engines page. A convenient way to register new program and/or modify parameters of the already registered ones just before starting a new game.

Next button

When you are done with this page, click the Next button to tweak game specific rules on the next page.

Game Rules Page

On this page you can select the rules for the game. The page has two parts. The upper part is different for each of Go, Amazons and Reversi games and contains game-specific rules. The lower part contains time limit settings controls and is the same for all three games. It is described last.

When you have selected the rules you want, click the Play button to start the game.

Go Rules

Go has many different rule sets that differ in scoring details, treating of some special positions etc. Currently, Quarry doesn’t make any difference between them. However, existing rule controls should be enough in most cases.

Board Size spin button

Choose the size of board for the game here. Go is traditionally played on a 19×19 board. 9×9 and 13×13 boards are also common. Quarry doesn’t limit you to these—choose any size between 5×5 and 25×25 inclusive.

Traditional board size buttons

These buttons allows you to quickly select one of three “traditional†Go board sizes—either 9×9, 13×13 or 19×19.

Handicap controls

When one of the players is weaker, it is common practice in Go to give him handicap stones. This gives her better chances to win and makes the game more challenging (and thus more interesting) for the stronger player. The weaker player is traditionally playing as black.

Quarry supports both fixed (also known as Japanese) and free (Chinese) handicaps. In the first case, handicap stones are placed following a traditional pattern, at hoshi points. Maximal fixed handicap is 9 stones. With free handicap, on the other hand, black player actively places the handicap stones at any intersections on the board. Free handicap is practically not limited.

Note

Quarry treats free handicap as non-obligatory: it allows black to place fewer handicap stones than specified in game rules (but not less than two.)

If you want an “even†game, simply set the handicap to zero.

Komi spin button

Komi is the compensation to the white player for playing second. It is usually non-integer to make draws impossible. The currently suggested komi for “even†game on 19×19 board is 6.5 points. Smaller (or even negative) komi gives some advantage to black player and can be used in addition to or instead of handicap.

See also time limit settings description.

Amazons Rules

At present, Amazons rules in Quarry are limited to board size and common time limit settings. Standard board size for Amazons is 10×10 (which is also selectable with the small button to the right), but you can choose anything from 5×5 to 25×25 inclusive.

Reversi Rules

Reversi rules in Quarry are limited to board size and time limit settings described just below this section. Standard board size for Reversi is 8×8, though 10×10 boards are not uncommon either. This is reflected by the choice of “traditional†board sizes with the buttons to the right. However, in Quarry you can select any even board size from 6×6 to 24×24 inclusive.

Time Limit Settings

Quarry allows to play games with limited time for both players. This also applies to computer program players—they have to honor the alloted time or lose. Of course the programs are properly notified about the time limit settings and the remaining time.

Note

Computer opponents use CPU time to generate moves. This means that they usually need less time on faster machines and more on slower machines. Also, if you run a computationally intensive task while playing, your computer opponents may become slower. Finally, certain computer programs may also “think†on opponent’s time.

Quarry has four types of time control:

No limit

Both opponents can take as much time as they like on each move, there are no limits. In this mode you can select the Keep track of total time option. Then Quarry will display the total time spent on move pondering by each player. This is purely for your information and serves no other purpose.

Limited time for entire game

Each player has limited time to play the whole game. If a player fails to finish the game in the alloted time, she loses. Note that time limit doesn’t depend on the number of moves in the game.

Limited time per move

Each move has to be played in fixed time. Time not used is not stored and not added to available time on next moves. When using this mode, keep in mind that in most games there are “difficult†positions that require more pondering time.

Canadian overtime (also known as Canadian byo-yomi)

This time control is often used in Go, but has nothing Go-specific, so it can be used in any other move-based game. Canadian overtime has the advantage of imposing certain speed of play, but, at the same time, allowing to occasionally spend more time on important moves.

Canadian overtime has three parameters: main time, overtime period length and moves per overtime. Both players begin game in their main time. During main time they can play any number of moves at any speed. When main time for a player is up, first overtime period begins. During each overtime period a player has to play the specified number of moves (moves per overtime.) If she fails to do so, she loses on time. Otherwise, next overtime (of the very same length) begins and the player has to play the same number of moves this before the time is up again. The number of overtimes is unlimited and they are completely equal to each other: time not used in one overtime period is not stored and not added to other overtime periods.

New Game Record Dialog

The New Game Record dialog allows you to start a new game record without actually playing a game. When you are done entering game record information, press the Create button. Or press the Cancel button to cancel game record creation.

The dialog consists of the following controls besides the mentioned buttons:

Game selectors

Here you choose the game you want to create a record of—Go, Amazons or Reversi. All the games supported by Quarry are listed.

Rules section

This section contains various controls for basic game rules. They are described in more details in the New Game dialog section.

One important change is the Place stones check button to the right of handicap spin button. It determines whether Quarry should place the handicap stones for you, or not. Stones are placed as if the handicap is fixed, but you can always change stones setup later if needed.

Short Game Information

Here you can enter the names of white and black player and the name of the game. You can change or expand this information later, using the Game Information dialog .

Resuming Game Dialog

The Resuming Game Dialog allows you to specify or correct game players when resuming a game. It also shows some information about the game, most of which is not editable.

You can specify both game players and fix their names, if needed. There are two radio buttons and a combo box for each player. Radio buttons control whether a player is a human or a computer (some GTP engine.) If you select to let computer control a player, you can choose any available GTP engine from the list for it.

Quarry tries to guess players based on their names, as stored in the game record. Normally, if the game was adjourned in Quarry and you don’t alter computer player names, it should guess correctly. However, you can always override and correct its decision.

Board Windows

Board windows are the main part of Quarry. They are used to play games and view and edit game records. To the left in a window is the game board itself. The exact appearance of the board depends on the current game (Go, Amazons or Reversi) and can be configured. On the right side of the window there is information pane, including the comment window. There can also be the game tree view to the bottom of the right pane.

Figure 3.1. Quarry Board Window showing Kogo’s Joseki Dictionary


		Shows Quarry Board Window with Kogo’s Joseki Dictionary.

The Board

Board displays current game position, including pieces, markup, labels and variations of the current node. Coordinate labels are shown on the edges of the board. They depend on the current game. In the top-left corner a small rectangle is drawn if the board has focus.

The last move made is marked. Depending on the markup theme, this can be a cross or a bullet. On the screen shot above, last placed stone at P15 is marked with a cross.

Note

This section can be improved.

Variations

Quarry treats variations as siblings of the current node. This is like Jago does and unlike CGoban. You always see the current variation and it is not a potential for the next node/move.

On the board, non-current variations that contain a move are shown as small ghostly pieces. Variations that don’t contain a move or contain a pass move (in Go) can be seen only in the Game Tree View. Screen shot above shows two variations—at Q18 and Q19—of the white move on the board.

You can activate (switch to) a particular variation by right-clicking on the ghost stone on the board. For instance, right-clicking on Q18 in the window shown in the screen shot would make White Q18 the current move. In rare cases when there are multiple variations with the same move, right-clicking and shift-right-clicking scrolls through the list of such variations. Alternative ways of switching to different variations include using the Game Tree View and using menu items, toolbar buttons or keyboard shortcuts.

Keyboard Navigation

Board has several keyboard shortcuts to ease game record navigation. Remember, that these shortcuts are active only if the board has focus, as indicated with a small rectangle in the top-left corner. Otherwise, you should type them with Alt modifier: more complicated shortcuts work everywhere in Board Windows.

Table 3.1. Board keyboard shortcuts

ShortcutAction
Left arrow Go to the previous node (current node’s parent.)
Right arrow Go to the next node (current node’s child.) By default, next node is the first child, but it is remembered if you switch to a different child.
Page Up Go ten nodes backward. If there are less than ten nodes, stop at the root of the game tree.
Page Down Go ten nodes forward. If there are less than ten nodes, stop at the branch end.
Home Go to the game tree root.
End Go to the last node in the current branch (variation.)
Up arrow Go to the previous variation of the current node. I.e. go to the previous child of the parent of the current node.
Down arrow Go to the next variation of the current node. I.e. go to the next child of the parent of the current node.

Board Window Information Pane

Game Information Pane shows information about the game in general, about the last move made and about the current node. Some of its components are optional and can be hidden in the View menu.

Player Information

At the top of the pane is the player information for both players. It shows player name, team and rank (first line), plus game-specific information (second line.) If name is missing, string “[unknown]†is shown in its place. If team or rank is not specified, they are simply not shown.

Game-specific information includes number of captures made by a player plus white player’s komi for Go; and number of disks on the board for Reversi.

Player Clocks

Close to player information are the clocks. When a game is played, they display the time left for a player. Additionally, they can display number of pieces left in the current Canadian overtime period in smaller digits to the right. When a game record is viewed, clocks display time left after move in the current node has been played. Clocks can be empty if a game is played without time limits.

Move Information

Below player information and clocks a single line displays move information. It shows last move (usually, current node’s move) number and the move itself. Afterwards, player to move is specified. This can sometimes seemingly contradict with the last move, but it is allowed to override player to move in game records (see Edit → Player to Move submenu.) This feature is often used in problem collections.

Game Result

Below move information game result is shown, but only at the very last node of the game. This is done in order to prevent spoiling of watching of unknown games. Also, if the game lacks any result or is unfinished there is nothing to show at all.

Game Action Buttons

Yet below there are game action buttons. These include Pass (for Go) and Resign. Because functionality of this buttons is quite rarely used and they take up space, you can hide them using View → Game Action Buttons menu item. They are shown by default mainly as a reminder of the options you have.

Comment Window

Most of the right side is taken by comment window. It displays any commentary the current node has. Comment can be edited and you don’t need to take any actions to save your edits. Edits are also saved in the undo history and can be undone and redone freely.

If the current node has a name, it is shown above comment in bold underlined font. It can be edited just like comment and you don’t need any special steps to edit node name. However, to create a name for a node that lacks one, use Edit → Edit Node Name menu item. It will insert a placeholder for node name in the window, which you can then replace with actual name. To delete a name, simply delete all its text. Quarry will notice it and remove node line from the window.

Game Tree View

Finally, there can be the Game Tree View, described in detail in the next section. Its visibility is controlled by View → Game Tree menu item and preferences.

Game Tree View

Game Tree View shows game record as a tree in a style used by CGoban1. Generally, it is of interest only if the game record contains variations. For instance, a debut/joseki dictionary or a well-annotated game with alternate branches. Visibility of Game Tree View is controlled with Game Tree item in View menu and with preferences.

Node with a move of a specific player, including pass move in Go, are shown as pieces of player’s color. Other nodes, including position setup, at present lack any icon. Nodes that belong to a same branch (variation) are connected with a line and the current branch is highlighted. Current node is shown within a black rectangle. If it is not visible, you can bring it onscreen using Recenter on Current Node command from the View menu.

Subtrees can be collapsed/expanded by right-clicking on subtree root. This is useful to hide nodes you are not interested in currently. Roots of collapsed nodes have a cross on them.

If a mouse is held over a node, a tooltip with information about the node is shown. It includes move number, move itself, node name and comment. Of course, some of these can be absent from the tooltip, if they are not present in the node to begin with. If node comment is too long, only first part of it is shown. Tooltips can be disabled in preferences if they look too distracting to you.

Board Window Menu

File menu

New Game…

Show New Game Dialog to start a new game.

New Game Record…

Show New Game Record Dialog to create a new game record without actually playing a game.

Open…

Open a game record. Record may as well have been saved in a different application.

Resume Game…

Open a game record and show Resume Game Dialog to resume the game. Games adjourned in different applications can be resumed too.

Export…

ASCII Diagram

Export current board position as a free-format ASCII diagram to the clipboard. Useful e.g. to mail game position if you don’t need a full-blown SGF. Only board position without any markup is stored.

Sensei’s Library Diagram

Export current board position as a Sensei’s Library diagram to the clipboard. Pieces, circle and square markup and labels are exported. Result, of course, can be imported into the Sensei’s Library. Only available for Go games.

Note

It is currenly impossible to export only part of the board. You need to manually delete unneeded information in such cases.

Save

Save the game record under its filename. If the game record is new, ask for filename first. This command is disabled if the game record is not modified.

Save as…

Save the game record under a different filename.

Close

Close the board window. If the game record is modified, ask whether to save it first.

Quit

Quit Quarry. Prompts to save any unsaved game records first.

Edit menu

Undo

Undo the last change made in the current game record.

Redo

Redo the last undone change made in the current game record.

Cut

Cut subtree having the current node as its root into clipboard.

Copy

Copy subtree having the current node as its root into clipboard.

Paste

Paste subtree contained in clipboard as last child of the current node. This command may fail if e.g. the subtree was copied from a different kind of game.

Note

It is currently impossible to determine if the clipboard contains anything, therefore this menu item is sensitive even if there is no subtree to paste.

Delete Node

Delete the current node together with its children from the game record.

Tools

Tools are very important as they are the most used (together with comment editing) way of modifying game records. Active tool can also be changed using the editing toolbar of from keyboard.

Move Tool

Activate tool which is used to play new moves in the current game record.

Setup Tool

Activate tool which is used to add and remove pieces from the current node.

Cross Markup

Activate tool which adds cross markup to the current position.

Circle Markup

Activate tool which adds circle markup to the current position.

Cross Markup

Activate tool which adds cross markup to the current position.

Square Markup

Activate tool which adds sqiare markup to the current position.

Triangle Markup

Activate tool which adds triangle markup to the current position.

Selected Markup

Activate tool which adds selected markup to the current position.

Note

It is not recommended to use this type of markup, as it has no standard appearance and may confuse other users.

Label Tool

Activate tool which places single letter and arbitrary text labels on the board.

Number Tool

Activate tool which places number labels on the board.

Scoring Tool

Activate tool which scores the current position. This tool is valid only for Go games.

Add Empty Node

Add an empty children to the current node. Standard way of adding children is by playing moves, but this command allows you to add node without any move.

Move Branch Up

Move current branch up i.e. swap it with the previous branch. Useful to rearrange branches in the game record.

Move Branch Down

Move current branch down i.e. swap it with the next branch. Useful to rearrange branches in the game record.

Edit Node Name

Edit the name of the current node. If the node has no name, it is inserted. Otherwise, you can edit node just by directly modifying it in the comment window and this command simply selects the name.

Set Move Number

Set the number of the current move. Normally, move number is incremented by one after each move, but there are cases when this must be overridden, for instance, if game record starts not at the game beginning.

Player to Move

Sometimes it is needed to explicitly set who is to move next, for instance, in a problem collection.

White

Set player to move to White, regardless of what game rules say.

Black

Set player to move to Black, regardless of what game rules say.

By Game Rules

Let game rules determine who is to move next (this is the default.)

Find

Show the Find Dialog to find a string in node comments and/or names.

Find Next

Repeat the last search in forward direction. If there were no last search, acts just as Find menu item.

Find Previous

Repeat the last search in backward direction. If there were no last search, acts just as Find menu item.

Game Information

Show the Game Information Dialog to view and/org edit game information.

Preferences

Show the Preferences Dialog to change Quarry settings.

View menu

Main Toolbar

Show or hide main toolbar in this window.

Editing Toolbar

Show or hide editing toolbar in this window.

Navigation Toolbar

Show or hide navigation toolbar in this window.

Game Action Buttons

Show or hide Game Action Buttons (Pass for Go game and Resign.) They have quite rarely used functionality and take precious space on the right.

Game Tree

Show or hide Game Tree View in this window. Its visibility can also be globally changed in the preferences.

Recenter on Current Node

Recenter Game Tree View on the current node. Of course, the view should be shown to begin with.

Control Center

Show Quarry Control Center.

Play menu

Pass

Play a pass move. (Only valid in Go.)

Resign

Resign current game. Opponent is declared a winner.

Adjourn Game

Adjourn current game and save game record, so it can be later resumed.

Go menu

Note

This menu’s title is English verb “goâ€, not game name.

Previous Node

Go to the previous node (current node’s parent.)

Next Node

Go to the next node (current node’s child.) By default, next node is the first child, but it is remembered if you switch to a different child.

Ten Nodes Backward

Go ten nodes backward. If there are less than ten nodes, stop at the root of the game tree.

Ten Nodes Forward

Go ten nodes forward. If there are less than ten nodes, stop at the branch end.

Root Node

Go to the game tree root.

Variation Last Node

Go to the last node in the current branch (variation.)

Previous Variation

Go to the previous variation of the current node. I.e. go to the previous child of the parent of the current node.

Next Node

Go to the next variation of the current node. I.e. go to the next child of the parent of the current node.

Go to Named Node…

Go to a named node given its name. You can also use Find Dialog for this purpose, but this way there is completion on node names.

Help menu

Contents

Show this help.

About

Show short information about Quarry and its version.

Find Dialog

Find Dialog allows you to search for text in node names and/or comments. It is invaluable for large game records, especially those containing multiple branches, like debut/joseki dictionaries.

When a node with matching text is found, board window switches to it, if needed. Matching text is selected in information pane. Search can be repeated later without opening this dialog using Edit menu items or from keyboard.

Dialog contains several controls:

Search for field

Enter the text to search for here. Field also has a history with up to 10 most recently found strings.

Optons

There a few options that control the search. It can be case-sensitive or case-insensitive. It can be restricted to whole words or include any match. Search can be wrapped around when the end or beginning of search domain is reached, or stop there.

You can also select Auto-close this dialog button. In this case, the dialog will be hidden after any successful search. You can repeat search afterwards using Find Next and Find Previous items of Edit menu or using Ctrl+G and Shift+Ctrl+G key combinations.

Search scope

Search domain can include the whole game record tree or the current node only. The latter option is only interesting if current node’s comment is very long.

Search can also be performed in node names, comments or both. Typically, you will want to search in both of them, but can sometimes wish to restrict search to decrease number of matches you are not interested in.

Next and Previous buttons

When search parameters are entered, click one of this buttons, depending on direction you wish search to be performed. Buttons can be pressed repeatedly to repeat search. However, if Auto-close this dialog option is selected, dialog will be closed on first successful search.

These buttons can be disabled if a search in certain direction certainly won’t hit any matches. However, they are many cases when this cannot be determined in advance (quickly), so activating one of these buttons is not guaranteed to find anything.

Close button

Close the dialog without performing any further search. Use it when you’ve finished searching or changed your mind.

Game Information Dialog

The Game Information Dialog allows you to set values that describe game tree as a whole and are not specific to a particular move or position in the game. It has a lot of fields which are splitted in three pages. All fields are optional and can be empty (not set), but defining them gives additional description to the game.

Fields on the first page (General) describe the game opponents, rules of the game and non-spoiling game details. Field on the second page (Description & Result) are generally spoiling and can even disclose game outcome. The third page (Game Record) describe the record itself.

White Player and Black Player

This group of fields allows you to describe the opponents in the game. The Name fields should be obvious. The Team fields are used when the game is a part of a match between two teams, for instance national teams. Usually, they are left empty. The Rank of the opponents can be entered in the appropriate fields. This is usually the rank as applies to the game in question. For instance, this can be the rank awarded by the federation guiding the tournament or it can be the rank of an Internet server where the game took place.

Values of these fields are also displayed in the right column of board windows.

Game Name

The name of the game. This field can be empty if the game is not special and doesn’t have a distinguished name.

Place

The place the game took place at. This can be a geographical location or the name of an Internet server.

Date

The date the game took place on. It should be in the international format of YYYY-MM-DD. For instance 2006-07-23 means 23 July 2006.

Event

The event this game is part of. For instance, this can be the name of a tournament. This field is often empty.

Round

The round this game is part of. For instance “1st round†or “Semifinalâ€. This field is often empty, especially if Event is.

Rule set

Descriptive name of the rules this game was played in accordance with. For instance, for Go this can be “Japaneseâ€, “Chinese†etc.

Handicap

For Go only: number of stones the black was allowed to place on his first move. This field is either 0 or not set for the games with no handicap.

Note

Value of this field is only informational. It doesn’t imply any particular setting of the black stones.

Komi

For Go only: the compensation, in points, the white receives for having the second turn. Can be negative or not set. However, it should always be set for games with non-zero komi, as otherwise proper scoring is impossible.

Main time

Main time each player has. Should not be set if the game is played with no time limit.

Overtime

Description of the overtime rules used for this game. For instance, “25/600 Canadian†means Canadian overtime with 10 minutes (600 seconds) for every 25 moves.

Game result

The result of the game in SGF format.

Table 3.2. Valid Game result values

ValueMeaning
Void There is no result yet (the game is not finished) or there can be no result at all (e.g. for problems.)
0 or Draw The game is draw, i.e. is finished, but there’s no winner.
W+score or B+score A player has won by the specified score. For instance, “W+6.5†means that white has won by 6.5 points.
W+ or B+ A player has won. Used mainly for the games without a notion for score, e.g. Amazons.
W+Resign or B+Resign or W+R or B+R A player has won by resignation.
W+Time or B+Time or W+T or B+T A player has won on time. I.e. his opponent exceeded his time limit.
W+Forfeit or B+Forfeit or W+F or B+F A player has won by forfeit, e.g. his opponent made an illegal move.
? Game result is unknown.

Opening played

Description of the opening played in the game. This field is often empty.

Comment / description

Description for the entire game. It can be some background information and/or the summary of the game.

Copyright string

Short copyright information for the game record.

Annotator

The name of the person who provided comments (annotation) for the game.

Source

The source of the game record (book, journal etc.) Often is empty if the game record was in electronic form to begin with.

Entered by

Name of the person who entered the game record. Usually empty for automatically created records.

Chapter 4. Settings

To configure Quarry either click the Preferences button in the Control Center window or choose Edit → Preferences menu item.

The Preferences dialog is displayed. It consists of the following categories:

General Interface

General interface of Quarry can be configured at this page. It is not really related to the functionality of the application.

File Chooser Dialog Style

You can use either the new file chooser or the old one, which was the default on pre-2.4 GTK+.

Note

This option will be removed in Quarry ver. 0.3. It was added when the new file chooser was in early development stages and had significant usability problems. Nowadays it has little sense to keep supporting the old one.

Toolbar Styles

By default, Quarry uses desktop settings for all its toolbars. However, you can choose specific style for each of three toolbar kinds. You can also return toolbars to using desktop defaults here.

Game Tree

Here you can customize appearance and behavior of the Game Tree View.

Show Game Tree

You can choose whether the Game Tree View is shown in Board Windows by default. If you choose Automatically option, it will be shown if game record has anything in addition to the main branch. In any case, you can show or hide the view manually, using View → Game Tree menu item. In this case, automatic showing will be disabled, even if corresponding option is selected.

Track Tree’s Current Node

You can choose whether the view should track the current node, i.e. reposition itself to show it. In automatic mode it only tracks the current node if it was showing it before. This mode prevents the view from scrolling if you intentionally scrolled it to some part of the tree not containing the current node. You can always force the view to display the current node by using View → Recenter on Current Node menu item.

You can also choose whether the view will scroll minimal possible distance while tracking (i.e. the current node will be somewhere near an edge), or if it will always recenter on the current node if needed. These options don’t make sense if tracking is disabled, so they are disabled then too.

Show tooltips

Choose whether Game Tree View should show tooltips over nodes. See view description for details. You may want to disable tooltips if they look too distracting.

GTP Engines

At this page, all game-playing programs registered in Quarry are shown. You can register new programs and modify information in existing entries.

All registered programs are shown in the list labeled List of GTP engines. When you select one of them, some information about it is shown in the lower part of the dialog. This inlcudes program name, version, supported game(s) and command line. The command line is exactly what you specified while registering the program, while the rest of information is reported by the program itself.

Programs from the list are also shown in the New Game and Resuming Game dialogs as available computer opponents. However, you can hide some of them by removing the mark beside the program name in the Show column. This may be better than removing a program record altogether in case you later regain your interest in it. Also, some GTP engines may be listed in Quarry system-wide settings; those cannot be removed, only hidden.

There are also five buttons on this page:

Add and Modify buttons

These two buttons allow you to register another program, or modify information about an already registered one, correspondingly. They both pop up the GTP Engine Information dialog.

Remove button

This button removes a game-playing program from the list of registered programs. The unregistered program will not appear in the New Game dialog as an available opponent. Of course, the program itself is not touched and you can re-register it in Quarry later.

Move Up and Move Down buttons

Using these two buttons you can rearrange registered programs. Computer opponents in the New Game dialog are listed in exactly the same order as on this page, so you may want to place more frequently used programs on the top. Another way to reorder GTP programs is to drag-and-drop their names in the list.

GTP Engine Information Dialog

This dialog is shown whenever you want to register a game-playing program in Quarry or modify information about an already registered one. Depending on the situation, it can be titled either New GTP Engine or Modify GTP Engine Information. After you fill in the dialog, press the Add or OK button. Quarry will launch the program to check if it works and ask it for some information.

Note

If the message “Querying engine’s name, version and known commands…†appears and persists for too long (more than a few seconds), this most likely indicates that the command line you specify starts the program in non-GTP mode or starts a wrong program to begin with. If you don’t expect the program to be very slow on initialization, then click the Cancel button and fix the command line.

The dialog has two text entry fields:

Command line

The command line to start the program should be entered here. You can use the Browse button to select the program, but normally just specifying program filename is enough. (More exactly, it is enough if the program is installed in a directory that is in your $PATH environment variable.) In any case, you should enter program-specific options after its filename. To find out which options should be used, see the manual of the program in question.

For GNU Go, the command line should look like this (note the double hyphens):

gnugo --mode gtp --quiet

You may also want to specify additional options. See GNU Go documentation for more information.

Screen name

In this field you can specify the way Quarry will display the name of the program. You can enter the full name or use special symbols “%n†and “%vâ€. They will be replaced with the name and version of the program as it reports them itself. In most cases the default value of “%n %v†is what you want, but sometimes it makes sense to alter it. For instance, you can specify “%n %v level 5†here if you fixed program’s level in the command line. If, for some reason, you need the percent sign in the name, type it in as “%%†(the percent sign is used as escape symbol in this field.)

Saving Game Records

Currently, you can only specify whether to save game records in UTF-8 or to preserve original encoding. The former option is recommended because UTF-8 can encode any character and because Quarry loads UTF-8 encoded game records faster than with any other encoding. However, you may want to preserve original encoding if, for instance, you use other SGF editor/viewer with poor support for UTF-8 or this is required for some reason for distribution.

Go Board Appearance

Sorry, not documented yet…

Amazons Board Appearance

Sorry, not documented yet…

Reversi Board Appearance

Sorry, not documented yet…

Appendix A. Quarry Authors

Programming

Paul Pogonyshev

Main author, programming, design.

Martin Holters

Programming.

Translation

Jérémie Knuesel

French translation.

Paul Pogonyshev

British English and Russian translations.

Robert Stefaniuk

Polish translation.

Appendix B. GNU Free Documentation License

Version 1.2, November 2002


  Free Software Foundation, Inc.
  51 Franklin Street, Fifth Floor,
  Boston, MA
  02110-1301
  USA

Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.

Version 1.2, November 2002

Copyright © 2000, 2001, 2002 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.

0. PREAMBLE

The purpose of this License is to make a manual, textbook, or other functional and useful document “free†in the sense of freedom: to assure everyone the effective freedom to copy and redistribute it, with or without modifying it, either commercially or noncommercially. Secondarily, this License preserves for the author and publisher a way to get credit for their work, while not being considered responsible for modifications made by others.

This License is a kind of “copyleftâ€, which means that derivative works of the document must themselves be free in the same sense. It complements the GNU General Public License, which is a copyleft license designed for free software.

We have designed this License in order to use it for manuals for free software, because free software needs free documentation: a free program should come with manuals providing the same freedoms that the software does. But this License is not limited to software manuals; it can be used for any textual work, regardless of subject matter or whether it is published as a printed book. We recommend this License principally for works whose purpose is instruction or reference.

1. APPLICABILITY AND DEFINITIONS

This License applies to any manual or other work, in any medium, that contains a notice placed by the copyright holder saying it can be distributed under the terms of this License. Such a notice grants a world-wide, royalty-free license, unlimited in duration, to use that work under the conditions stated herein. The “Documentâ€, below, refers to any such manual or work. Any member of the public is a licensee, and is addressed as “youâ€. You accept the license if you copy, modify or distribute the work in a way requiring permission under copyright law.

A “Modified Version†of the Document means any work containing the Document or a portion of it, either copied verbatim, or with modifications and/or translated into another language.

A “Secondary Section†is a named appendix or a front-matter section of the Document that deals exclusively with the relationship of the publishers or authors of the Document to the Document's overall subject (or to related matters) and contains nothing that could fall directly within that overall subject. (Thus, if the Document is in part a textbook of mathematics, a Secondary Section may not explain any mathematics.) The relationship could be a matter of historical connection with the subject or with related matters, or of legal, commercial, philosophical, ethical or political position regarding them.

The “Invariant Sections†are certain Secondary Sections whose titles are designated, as being those of Invariant Sections, in the notice that says that the Document is released under this License. If a section does not fit the above definition of Secondary then it is not allowed to be designated as Invariant. The Document may contain zero Invariant Sections. If the Document does not identify any Invariant Sections then there are none.

The “Cover Texts†are certain short passages of text that are listed, as Front-Cover Texts or Back-Cover Texts, in the notice that says that the Document is released under this License. A Front-Cover Text may be at most 5 words, and a Back-Cover Text may be at most 25 words.

A “Transparent†copy of the Document means a machine-readable copy, represented in a format whose specification is available to the general public, that is suitable for revising the document straightforwardly with generic text editors or (for images composed of pixels) generic paint programs or (for drawings) some widely available drawing editor, and that is suitable for input to text formatters or for automatic translation to a variety of formats suitable for input to text formatters. A copy made in an otherwise Transparent file format whose markup, or absence of markup, has been arranged to thwart or discourage subsequent modification by readers is not Transparent. An image format is not Transparent if used for any substantial amount of text. A copy that is not “Transparent†is called “Opaqueâ€.

Examples of suitable formats for Transparent copies include plain ASCII without markup, Texinfo input format, LaTeX input format, SGML or XML using a publicly available DTD, and standard-conforming simple HTML, PostScript or PDF designed for human modification. Examples of transparent image formats include PNG, XCF and JPG. Opaque formats include proprietary formats that can be read and edited only by proprietary word processors, SGML or XML for which the DTD and/or processing tools are not generally available, and the machine-generated HTML, PostScript or PDF produced by some word processors for output purposes only.

The “Title Page†means, for a printed book, the title page itself, plus such following pages as are needed to hold, legibly, the material this License requires to appear in the title page. For works in formats which do not have any title page as such, “Title Page†means the text near the most prominent appearance of the work's title, preceding the beginning of the body of the text.

A section “Entitled XYZ†means a named subunit of the Document whose title either is precisely XYZ or contains XYZ in parentheses following text that translates XYZ in another language. (Here XYZ stands for a specific section name mentioned below, such as “Acknowledgementsâ€, “Dedicationsâ€, “Endorsementsâ€, or “Historyâ€.) To “Preserve the Title†of such a section when you modify the Document means that it remains a section “Entitled XYZ†according to this definition.

The Document may include Warranty Disclaimers next to the notice which states that this License applies to the Document. These Warranty Disclaimers are considered to be included by reference in this License, but only as regards disclaiming warranties: any other implication that these Warranty Disclaimers may have is void and has no effect on the meaning of this License.

2. VERBATIM COPYING

You may copy and distribute the Document in any medium, either commercially or noncommercially, provided that this License, the copyright notices, and the license notice saying this License applies to the Document are reproduced in all copies, and that you add no other conditions whatsoever to those of this License. You may not use technical measures to obstruct or control the reading or further copying of the copies you make or distribute. However, you may accept compensation in exchange for copies. If you distribute a large enough number of copies you must also follow the conditions in section 3.

You may also lend copies, under the same conditions stated above, and you may publicly display copies.

3. COPYING IN QUANTITY

If you publish printed copies (or copies in media that commonly have printed covers) of the Document, numbering more than 100, and the Document's license notice requires Cover Texts, you must enclose the copies in covers that carry, clearly and legibly, all these Cover Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on the back cover. Both covers must also clearly and legibly identify you as the publisher of these copies. The front cover must present the full title with all words of the title equally prominent and visible. You may add other material on the covers in addition. Copying with changes limited to the covers, as long as they preserve the title of the Document and satisfy these conditions, can be treated as verbatim copying in other respects.

If the required texts for either cover are too voluminous to fit legibly, you should put the first ones listed (as many as fit reasonably) on the actual cover, and continue the rest onto adjacent pages.

If you publish or distribute Opaque copies of the Document numbering more than 100, you must either include a machine-readable Transparent copy along with each Opaque copy, or state in or with each Opaque copy a computer-network location from which the general network-using public has access to download using public-standard network protocols a complete Transparent copy of the Document, free of added material. If you use the latter option, you must take reasonably prudent steps, when you begin distribution of Opaque copies in quantity, to ensure that this Transparent copy will remain thus accessible at the stated location until at least one year after the last time you distribute an Opaque copy (directly or through your agents or retailers) of that edition to the public.

It is requested, but not required, that you contact the authors of the Document well before redistributing any large number of copies, to give them a chance to provide you with an updated version of the Document.

4. MODIFICATIONS

You may copy and distribute a Modified Version of the Document under the conditions of sections 2 and 3 above, provided that you release the Modified Version under precisely this License, with the Modified Version filling the role of the Document, thus licensing distribution and modification of the Modified Version to whoever possesses a copy of it. In addition, you must do these things in the Modified Version:

  1. Use in the Title Page (and on the covers, if any) a title distinct from that of the Document, and from those of previous versions (which should, if there were any, be listed in the History section of the Document). You may use the same title as a previous version if the original publisher of that version gives permission.

  2. List on the Title Page, as authors, one or more persons or entities responsible for authorship of the modifications in the Modified Version, together with at least five of the principal authors of the Document (all of its principal authors, if it has fewer than five), unless they release you from this requirement.

  3. State on the Title page the name of the publisher of the Modified Version, as the publisher.

  4. Preserve all the copyright notices of the Document.

  5. Add an appropriate copyright notice for your modifications adjacent to the other copyright notices.

  6. Include, immediately after the copyright notices, a license notice giving the public permission to use the Modified Version under the terms of this License, in the form shown in the Addendum below.

  7. Preserve in that license notice the full lists of Invariant Sections and required Cover Texts given in the Document's license notice.

  8. Include an unaltered copy of this License.

  9. Preserve the section Entitled “Historyâ€, Preserve its Title, and add to it an item stating at least the title, year, new authors, and publisher of the Modified Version as given on the Title Page. If there is no section Entitled “History†in the Document, create one stating the title, year, authors, and publisher of the Document as given on its Title Page, then add an item describing the Modified Version as stated in the previous sentence.

  10. Preserve the network location, if any, given in the Document for public access to a Transparent copy of the Document, and likewise the network locations given in the Document for previous versions it was based on. These may be placed in the “History†section. You may omit a network location for a work that was published at least four years before the Document itself, or if the original publisher of the version it refers to gives permission.

  11. For any section Entitled “Acknowledgements†or “Dedicationsâ€, Preserve the Title of the section, and preserve in the section all the substance and tone of each of the contributor acknowledgements and/or dedications given therein.

  12. Preserve all the Invariant Sections of the Document, unaltered in their text and in their titles. Section numbers or the equivalent are not considered part of the section titles.

  13. Delete any section Entitled “Endorsementsâ€. Such a section may not be included in the Modified Version.

  14. Do not retitle any existing section to be Entitled “Endorsements†or to conflict in title with any Invariant Section.

  15. Preserve any Warranty Disclaimers.

If the Modified Version includes new front-matter sections or appendices that qualify as Secondary Sections and contain no material copied from the Document, you may at your option designate some or all of these sections as invariant. To do this, add their titles to the list of Invariant Sections in the Modified Version's license notice. These titles must be distinct from any other section titles.

You may add a section Entitled “Endorsementsâ€, provided it contains nothing but endorsements of your Modified Version by various parties—for example, statements of peer review or that the text has been approved by an organization as the authoritative definition of a standard.

You may add a passage of up to five words as a Front-Cover Text, and a passage of up to 25 words as a Back-Cover Text, to the end of the list of Cover Texts in the Modified Version. Only one passage of Front-Cover Text and one of Back-Cover Text may be added by (or through arrangements made by) any one entity. If the Document already includes a cover text for the same cover, previously added by you or by arrangement made by the same entity you are acting on behalf of, you may not add another; but you may replace the old one, on explicit permission from the previous publisher that added the old one.

The author(s) and publisher(s) of the Document do not by this License give permission to use their names for publicity for or to assert or imply endorsement of any Modified Version.

5. COMBINING DOCUMENTS

You may combine the Document with other documents released under this License, under the terms defined in section 4 above for modified versions, provided that you include in the combination all of the Invariant Sections of all of the original documents, unmodified, and list them all as Invariant Sections of your combined work in its license notice, and that you preserve all their Warranty Disclaimers.

The combined work need only contain one copy of this License, and multiple identical Invariant Sections may be replaced with a single copy. If there are multiple Invariant Sections with the same name but different contents, make the title of each such section unique by adding at the end of it, in parentheses, the name of the original author or publisher of that section if known, or else a unique number. Make the same adjustment to the section titles in the list of Invariant Sections in the license notice of the combined work.

In the combination, you must combine any sections Entitled “History†in the various original documents, forming one section Entitled “Historyâ€; likewise combine any sections Entitled “Acknowledgementsâ€, and any sections Entitled “Dedicationsâ€. You must delete all sections Entitled “Endorsements.â€

6. COLLECTIONS OF DOCUMENTS

You may make a collection consisting of the Document and other documents released under this License, and replace the individual copies of this License in the various documents with a single copy that is included in the collection, provided that you follow the rules of this License for verbatim copying of each of the documents in all other respects.

You may extract a single document from such a collection, and distribute it individually under this License, provided you insert a copy of this License into the extracted document, and follow this License in all other respects regarding verbatim copying of that document.

7. AGGREGATION WITH INDEPENDENT WORKS

A compilation of the Document or its derivatives with other separate and independent documents or works, in or on a volume of a storage or distribution medium, is called an “aggregate†if the copyright resulting from the compilation is not used to limit the legal rights of the compilation's users beyond what the individual works permit. When the Document is included in an aggregate, this License does not apply to the other works in the aggregate which are not themselves derivative works of the Document.

If the Cover Text requirement of section 3 is applicable to these copies of the Document, then if the Document is less than one half of the entire aggregate, the Document's Cover Texts may be placed on covers that bracket the Document within the aggregate, or the electronic equivalent of covers if the Document is in electronic form. Otherwise they must appear on printed covers that bracket the whole aggregate.

8. TRANSLATION

Translation is considered a kind of modification, so you may distribute translations of the Document under the terms of section 4. Replacing Invariant Sections with translations requires special permission from their copyright holders, but you may include translations of some or all Invariant Sections in addition to the original versions of these Invariant Sections. You may include a translation of this License, and all the license notices in the Document, and any Warranty Disclaimers, provided that you also include the original English version of this License and the original versions of those notices and disclaimers. In case of a disagreement between the translation and the original version of this License or a notice or disclaimer, the original version will prevail.

If a section in the Document is Entitled “Acknowledgementsâ€, “Dedicationsâ€, or “Historyâ€, the requirement (section 4) to Preserve its Title (section 1) will typically require changing the actual title.

9. TERMINATION

You may not copy, modify, sublicense, or distribute the Document except as expressly provided for under this License. Any other attempt to copy, modify, sublicense or distribute the Document is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.

10. FUTURE REVISIONS OF THIS LICENSE

The Free Software Foundation may publish new, revised versions of the GNU Free Documentation License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. See http://www.gnu.org/copyleft/.

Each version of the License is given a distinguishing version number. If the Document specifies that a particular numbered version of this License “or any later version†applies to it, you have the option of following the terms and conditions either of that specified version or of any later version that has been published (not as a draft) by the Free Software Foundation. If the Document does not specify a version number of this License, you may choose any version ever published (not as a draft) by the Free Software Foundation.

ADDENDUM: How to use this License for your documents

To use this License in a document you have written, include a copy of the License in the document and put the following copyright and license notices just after the title page:

Copyright © YEAR YOUR NAME.

Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled “GNU Free Documentation Licenseâ€.

If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, replace the “with...Texts.†line with this:

with the Invariant Sections being LIST THEIR TITLES, with the Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST.

If you have Invariant Sections without Cover Texts, or some other combination of the three, merge those two alternatives to suit the situation.

If your document contains nontrivial examples of program code, we recommend releasing these examples in parallel under your choice of free software license, such as the GNU General Public License, to permit their use in free software.

quarry-0.2.0/help/C/quarry-C.omf0000644000175000017500000000152110132561445015016 0ustar bartbart pogonyshev@gmx.net (Paul Pogonyshev) pogonyshev@gmx.net (Paul Pogonyshev) Quarry Manual V0.2 2004-10-06 User manual for the Quarry application. user's guide quarry-0.2.0/help/C/figures/0000755000175000017500000000000010530402565014254 5ustar bartbartquarry-0.2.0/help/C/figures/board-window.png0000644000175000017500000070702110530402565017365 0ustar bartbart‰PNG  IHDReÈó+ IDATxÚìu|GÇg÷Ü-w!…â)Å]‚C"EKp§h¯Z´@)^Jâ‡âîV‚„O.v®+ï®×ÈÂÝxçû¡÷ivwvì™™ß>3;‹õÚõ@ ·qóØŸ:¥ŸšµhQ½FMX(@ xpÿ.¥¢zíú×þ¢‘‡_,@ ·òð֥̔$: "ºÚ³ÔŒÄhLŽ“·_Z.Þ/ôó`×á‡úqP”¾âe§’±ššððw^e–””Äåóß38´T@*V8WW”é…"IdíaeŽŽKcùÞOQ_|Û#–ײ®”ÈoÇÕJŸF÷¾—¢¾ð £{#qû/ýJõc!R1ÿbG…ƒCK…@ ¤Rña…suE‘„BKœ¸‘¨ËPq|}=q7›Í:}ûù¼ÏBÙÉyH¦†ýŸã§²jGIÐÒÒ„"Z¡´Rß38´TˆX1¶= ÷”<‘”'”–óÔûÜÖE݉o/¦5&_½þ1O(]?½W%O³JÕ‰†dýï³ú}†Ta$¡áÛ{ó™(úLýµÓÈ!}‚¹/Žo›sYÏɘ,ìÙ\LJÎÕeNä]|¤ÂQ¦^¯·Z­f³Çq+Nn>ö’dzà¸Ôþ8†“›'r–ªÚJ¹sÖëç/îßÐiT|¡8¢F}Ÿà*e,5xùÔ"€ Êü2¦= ÏÔ¢^•-õ™øU O:råð_¿ÝVó„†ËºžbQ»4TÈM‰ á|‘´œ§¨„‘$Y­:­.=3ëúÝÇ7Ò¬lŸÆ`–ç¶Ž3øÖ€òe ®+"Ibù{u )W ªüiv[ ßÕÞz«OØÞ‡A­Ã}™è´n©p¹_è©m—¾šÑ&¤yKËžeXžþ°·w¥ê½FöbÁ^?“öâIÉ‹"b>‹mQžà×hÐÚþÊûWO¢(­ÔàeI¨âg¼%Œ{i‹ÅB„Ñh´X,V«5Ô—gF97ž? É,ŸêÆ©ýÏî] Žú<4úó¼ì´3mˆü¼AýV]KDªE‚ÀQ”æ@-‰<öòi/$«JÉݪ‰Q|ïªë¯ÈýÃÜ0JEÍÉÜêP¦½ä‹dŲÿõw¿*S_ e;®Ä xøW©Ú¢y«az5º|dÞ‘×™7‹Ã{kز2øN?B¿ªž ´0iÓ¾§Ï}êÚYjVÜVª3$·ú„ é}b €Ã÷ $žrÿP‹þÕÆtý°¯aÒü•y\¡Ä“ÎdÁ®¾z¡J ƒôO2“‹«’D¨ñEË·' üÆÉ}$NÔlÜ€àîÅc7ψmÝ­X"Qy%³S3˜q%Qc2™H’Ä0Ìb±Ð©F„?IgŸý§Ðþ81Ç„J²ÈR5ã¢ÌL~þìÞÕöýÆÈ}ƒ¨#1uý½õ×Àˆj¾!UJ,³éf§%ص®M¯áÞaehU¨ \ˆ2íePlÜŒnÕ¸À¸föäß.gH½lê^àߥv`„—€°¬ô´Óç®\ÉDØ,@Y\>F/},˧ÁqtO¡Oç:A‘>B.Jäde^¼tíd’…ÃÙ†€ €+÷ؽºŒ®ýkÃmÍö…c-¿‹€ÒŸº”i/ÉIãýùûª,Æäñ ãâïÏ]JH½Š…e‹=ÚÖ ¬æ/sh…9§Î^9“lÝ0kuŸÓ;VØŠ±X@Y^6ª`ú– ½›~é+f–”W/wᅳ žAQi•º³[y$iÔkž=y²íØ#WÌâð–n˜¹íR¯ÆÕ"|D:z¬ÐÒN¼¸ú·M¹tžHJg0ÙâÈù}Cͺ§C~:ËJ¹±-×ÁõÅ€{+ÏpøB±Ü‡Ã8(CžPâá ‹r\ãÅjªü¥úA É'<´W½ S—uöÜeû[}†丨Æú}©;<¾vÐgÊrÿxúù 0íœt“A#`ÉaWï2/Ôû¬F*}ÇÏã‹ÿó„¬SåŸ?´µX,¥¯Ù°-7NݤÃ?ŽÞ8} ~Ë®5¶-®(s-Td€ {,Ø~>‡  ÃÀÜ­¡<È[Àâ±;}!ØsNYt1wmæä#@³JõBÔîðóû×C¢>÷ò ²ñò ‰úüùýëþ¡UJDЧÈJM:±smµºOì\Û¶w¼O`XñB å*›ô_5¦WÍŸ¶(Dau¿ëQ]ˆâÖ,\w-ß3 üMG2 ’/’z„ÇÔ6 ÿ¾ê´ªÕ»nÞ¸ã\¾Ð>,Gì?£O5†>uáâ%·S5²ÀðöíÚ™íï?}åŸóGªÇzF„V«g‹… è8ËÔ•3šÐ¿üœjæEÅÆÍëW}ìР—<|ƒy"i„4{îÒC÷_fúWk¶|ä—~¬ä±›Sd>TÀ)±øË§Y$ŠzTëÙnDTõ¶‚‚EOé Sìá[Çðò¯}j¥žÅæÚg¿¾„ø+QÍù Ä2:î  >Q3:Ƹ¢ÞÕŠÊYªî7$¾wÄ”Öaêä«C§íW3=NQrÞá“4$EíYßaÄÏß¾vú×öù¥¡4 K TÐÚ¨]jÒ©EROØÕ»Ì UÊÈ^î€Å…%ñ‹ÝAŠ,KWÔiÒäͳ‡Ò“žf¥¼ˆmÙ¥v“v%;ìRuj¯ ÿŠtnàóÓ°*‘rSF’YªtnÄfÑéÒÄoΰªþDÏ&ÒßDwhÈf2r ×Ê}Š”ûè5…HùÈIu|ûš–ÝÕkÞ©e÷AÇ·¯ÉI…@Üe-ûæöf£Èé¹SöÜÏõð ñ«&ñôc°Ø‚4jBCÀï?l|ššaTeÿùë)A; ˆÎÍH6êÔZ"Ø4{Ý“×éúÂÌM«.Øú5ƒ¦ÐqØþÓW¶î;Î+0‚/’Õ0H’Lzñ¸ /K§Ê½wëÖÒ¥+AÙ ¦”ãû;¸ç—m™ø9á÷G¯Ò­FõÉ[ z4ÊMO2èTEßõ¿Z5¡1oøaüœÝ70ÌjÛ¯–Ê]™ CÁˆ„"€-n¤ÉË6h íÃ6hÉG‘¿f->~ë‰Éb*ÌIß±e£ýIýŸýËS¤Ô•óϺú8Éj5=¼rÀ‘~¡L{©×"rñÌãçJ=NâIwdQÍ•éImQ–çV\šŒ8¼G‡Ò,¸0¸3+'Y¯ÎGÒ>˜C’øüí×uª|@’öyc¢€ô8‡/âòE¶4—Z†MÚG¸È¢ÊoEïTªn6$A¶ DðÛ÷ž¦¦TYÛÖžÿï8òÉ’ƒ¢vlHiùeÐ/ÚlÔ[LØÛD£R²Ý¤taS(ŠÖmç‘‘üÌ7(¢n³8EË9–9‘GcÐ-K¸¿¨F¨ gûHÜbAp'p„$Iñ ˆìÙ­†LHcá™l†±,÷r1O$ÉËJ/æ ËËJç‰$åq¸)3^ÿ½mu«¯††G‚"ªµújØßÛVw0ÖÓ/Nä¹¾‹Žíú®]ËY?~5qÊD&x0˜EÓ_ è€}©Y|ßРèš4:àÈšdï˽¿äÓ»S”¿àèš4ºÞþQÂqX¡DNÕ)_$;¯²´–0oØ„›ôÙyÉÉ)ÇN\ÏDè(Vf½¿íþîÙH@Ìýs½ýý˜üÙ‹Äò"çÁþE¸(²sÚ˜5×sä~!~¡1¢7§þíªËôl›Ë¥XL«ÙhA3°ö~2Û3 °Ju¾Ø³š¶å€<‘Ô+(Â;(â²\”ò<“_Œ‡wP‹Ã (]«Ê5jUL¾´[«ZUýÅBjN(ÓKÿ¯¼;ª¶øzøWቤŽo¸Y˜ÐÐcB-Îüô<$Ü;ŒEÓ¤îxlžPü_¿{Q+e0Y ËvªÔ2lì2‹rPãKF´±ÝfÀŒ•ÿYE÷¡ ©dÚ¨B8®¥ÇX¢¬?MCrPÔŽ ƒ/–––ߢB ŒÀ­pùx&òJÙ§Àv]y‘$yûüÑÌ”þ!Q™)ÏoŸ?Z§i‡’)t4‘Wò “Ã&,VtÀqEq !  c×{EV @òò ³r=TªG!r+‚¼}"¯jÍ/þÞ¹î³zlŠG™ñúÕÓ»í{/épCJ8ÜߺˆY-WŽí¾bw%fµ<¾uÑÛ?¸dph©.âŸí ½Ibç´ß-_µyÙ²+šÝ“ZÌA¾™æ %|‘ ¥1¨ fƒÎlÔ‘o¬G¥3ífÇaù!Q¶Ùî¿Ö74Ѝè'åùùóüüjEƒÁ?]ã ÅeìOööû;¸'I@óú ²@¯À¦Sç4*‰§¯íåç þÞ5½C‡Qßüø«ÙÓW,÷a°Øö±;HuŠÉñ˜ /ØùЧ\ öJ=é &óÍÍËŠ¢3{Ök];22<Ü?(œ-öè2j sMM© .ÏýÜóüî;‚ì²bnÓj!>AUë5jÛ¥ËôiãxB1QÔïsx‚ü;Æÿq!Šš©fNÑ*íc/+a(.‘›7ªÓ#”ûüìÖiçòÄÞ¶‰*ì…Ý·´8ÙgéÌÏ=£:ŸÃc7ù²–Ù µ˜ôéV+c$Hâ²\2yöG®i-€¡µߌ¶}¾‰ÿ½Ì–#‡{çð+AÆôhÙTÈÈ{ô[@ž@T,ï¯.ä>ù…I¯1êÕ¶xK-Ó{¸È¢Ô¸@"ó Š¯ñEx/|‚"Yå1¤’i;³?‘$ÉasúJH=†cÍ[„Ú_ÿ)ÒßÛ ½:ßq?àØ0Ò¢®+Üûí‹Ãcsy°·wÝ¿bƒµ§`hTÉž>þå!‘Õnœ9rfßû7Î ‰¬Vžà4­qû±ÍãhÔŸÛ<®qû4ͱ®xËD^û†¡&“‘Å`8Ù¾aŽã†žK"…*½Á€a˜No0zƒ1ȇûªÌyŠN£°È€°È·©TÛ´eÅD.œÈsíSƒÉ’xú¨r^ŒYG¬ޤݠ ¼«¶<Í`°òǯÉé×2vÕÊ.,`ÍLK^ñãÆ=¯‡__,à _LÙ¤Þ¾õo«»jr³NŸÜú "IŒ÷„:ÉAXû ]-«QõšqZ˸L£N}ûÒ‰_îHåök“K<ö¼åþŽîiÊ»t_&Õ§$Ì‘ré­úÅ‹¤s{ÿ4hÛÜ"É’ÈýLéOÆm –ýrüôo7,[_l^¾”)Ñó‡1«E¯7dd¤­Z¾a×¹Ç2ß ïÀp¾Pb5g]¼§[ÓÏFN›!ç3 s2Oœ<¤)0óEÒ §G7X³o/`àÌ•Â_#z{–ËN‚ `×çÙj³xcOUÖù“;@è]òß©"h£ªöì 8¹è‹#JäL»X3¶æ>È´ù„«ƒ M׈e^Êðò˼±+³´q¾E9¨qjBªrRÉ´éò¿Û¢Ú¶åok:©•™gNmý†–ZY½!ÈN}!ÈqPÔŽ ã¿ïsAèlÏ.rnÉùñn>ß7œ'”ÀÄ•^¨ÿt µµ®Ý¨uùGv§/yeÝ&íÊ©+zíú÷<"O­/vb°Ï£^Ïf³]MmëOIV³Å„ˆ^é£Yl&Ž&³E«Ó§¦¼j¥¿Ìø¶d”šÜ¬wý2ERR’PîóžÁ¡¥:ì”Y)Ï>AU¼ƒ"0«E•—òB[˜Ë勼ƒ"„2/£NS“¦×¨h4:@³røB©—¿Dî¢ÊËÊËL5èT &›+®±cqo“êÒ—]GÔˆ ‰©¥ÊË)+,Ín‚@§.Щòuêc&ƒD(ó”ûÚ¿ŽŽ Ìyƒ˜¶N˯#jĆV­íàþF½¶¬{r"M¾2?;M§.@Q‹ÃEP@ –ñÅ2*ßV&>ª¼ììÔ—­Z –‘$aЪi U\%KR§*ˆe<‘³˜1«™ÎdKä>b¹›Ë·/jÏ€PMAnAvšN]€ (‹Ë£Ñè|‘”/’Z­–œÔ—š‚\:ƒá.”zÚ§ÇÓ?ÄA–s3^Û×f±úˆeÊôäÂÜ,l®ÀdÐj óRŸ *€b)C‚jþÔÆËj|Ûl˜wdÍðêõù%´ŽYéÁŸÏkã“{ï÷¡+_„T­­-Ì+« å~Á$Iªó³nQj¼Ä¦èCš“„¥vóî5ê‡V­Sy €c˜*/+/3Å U1˜l&›£×–ZY»!ëôlžÐa„}V¯Ø­bÛ6ìèÇ~¼iÂàí©!1µ#k0àÖš.ãà g銜´ä‡7/•¹ Š¢8ŽHÁpœN£a.X9ª'¯såt:Óh2å*3|xÊ`_ÿ«yNþÌ0ú~Ÿ„3Ù®@(ñ ÊU ö@„ÉdIå>L&K§ÊÇqœÅæ0 ¶‡7‹ÍÑ« z €ÍáóÅRî›Ígöh°ó4ãþ‹×l‰wç>§VüÆæòØ\>Î8 kƒ/ÑPÎ0èÔ8†±¹|žPÌJÙ<ݳ, (x²•N§Ó Ç÷§9¼§ØÃ‹Åæê5…­ Ç1Áå yB ›+@ß©@ìÁd±¥ž¾L[§ÊGP”$I±Ì‹Æ`PÅU²$uªêZ›Ãæòy1‡_´c¤}QÓit±Ì“ÍáêÕ…z­ŠÀ1‡Çå 9\>4(‚/’š :ÊóüŸ€³\¬6‹EʈÑ@”'u:“%”Êå¾A [ öoÞÀ-–/:‹[-Œ¸¿ñGO,’yqùÂRú³ðîéî^èµ…R¹o±4+C›Ãá ¸|¡Ó-ŠV+¢LIì0䤡(F¯T†@ ‰‡7u±Ùd`²8|‘TîÌ`±ŠUÖÇnHÅ"rÜ80Œ’·º°÷ØÎ”çù9˜oH”ÔÓ—ÅdÁo„¹m-”›…suE‘ªPk,vb€×.VËb±N]OoëO`€Äq‹HÉÒ»‘ìà ôb„йî–쥈ͼ÷{>ïZj%Dì)kW+$ÜK€`¦ôÔ”cûwl¿øRæXå3ñ›=úœB æƒîþ­‹‹þ®yG×ò …åï:jvkÔEİ47Níþnù~i`•ਚ2ïÒ¿5f5›´ê|£NÃ`±"çÍV¢•Тæ jN’D^Ú³e3¾¿f„V×'8Vw%1$g†I¯Õª ,F=›'à‹d,V„ ½PT8KWd¦$=¼y©HB©tFW””Åh0êÔïšÜ¤¤$_Ääpß38´ÔJˆN•¯UèTù$IZL«ÅÂæñe^þO_çzÎuªü‚ܬ¼Œ×(&ñô•ûÙâtŒz­V•——•¦W2ÙŸ@Ÿ@7 E®¶(*_•—““–DR$óòH<`uW~Cr[Wù¸„³tEÆë¤'ò\´tŽÅåQq¿S(_D|ÏàJ—z­†$MƒÉbsù|‘”+(>U÷þ Âb±eÞ<‘„/’r¸|è™w)‚ Êå x‘@,㋤Ô‹»E!Bg2Årož@ÌËx\hüQ’ÛºÈÇ% œ«+мP½ Ö+@ È[IK~ér/@ È' ‹@ ä]¡šU÷ö‚0°P @ŠÁápP=k|xóÍîäF£Q*•Â2‚@ )FAA÷ïºr8‘@ òÎ@ @ %@ ”P@ Ÿ „âr¹ÅþçCáΔ|ðÌVòôÀ¢€@ ”PÿœŠá†áð}"}ŸŽðšý´°ØÁ§³½"Æ~@q@Áˆ">0yYŽ•pw"Hìø¦ù[Öð– „ÿðêúÝqá…{””Gù(%Àð_¨#.MŸ¡å òþñNXØ`ûøcÅ¿½Á nȵãÒЩr¯ZíóbM“>;Ý*ŸãìÎÕ¿?©ùãÆGIiêü¬{g÷Œê}üÇî°!A J('x ï[Òºn”D(ôª6pæï‚tEÒomR|(ˆ‚bb¿[s¶X’l¿s˜Å­BîL~fÄlG0ã³ÉwUqAÅr]jf-š«bÏX›hl½Ioþ¯+]ÕXÞ'ãéÝàÇ3NÏ(vJ“~{L×F¾b¾H^¿Ã·÷µVcþA™WC þo–ìpypâM\Óm7môÍí ÚÔ¯*â±QÛ#0²Mï›O>°]sví´Ø˜ !_;}Ý9×î[mŒËåž[;-6&H$Æ|¡Øt ¶vT" U’œËŠÖsïM^w4« ðÙÕÁ‰‹[L¿âôX2NMj÷ÃíY[/ææžÿsÖƒ_»Àæ$+§ïªx¹0}W¶–ŒÝõÊväÕ®±’Ö+}™hy2Ë6èÈ~¹]i˜Õg¼î¶ÖÐe­Kætn tÕ§Âcâæ4›²þyf¾*ûÙäØÔî½öpdçF¦{8åߢ;3ŽÙjUn¾lñíñ«8¸àõþa=ügúæsyª¼ó[fü3¯Çð)®Èf9m¬ç‚‡³·^È-̽¸uÖíÚO:•<@œR¯]ÿuˤ>ð¢×ëìN^Ò—c0¸\.%Plÿ3;Ê;ü\Ò7>EÛwZõä!ñ*åÕ $®TïËÔ/Öþ§s«¥¶àÑ÷þõ–K‰í*†.c]È—7s_ÿNý98X^ÿJòp?~93{5þóÙ±»Ï ¬òr[›ÏG^iµûéþ6~Ù?yñ½µ *VEÙ!¬™/ﮚ6à/rÖ³ýýÊÊ)aÍ—ø´PçÝS?_Öê¡2e+¥þæ|æ¤dÊ IDATrêeoÞ»&À[ÈZ •ÐËü"õØPOÁ§?V—Qæ?˜ÝE§|µÂYUo«}Ån_û“n¦ÿk!¿îbÊy±¶yT ÛîäGÏ^[±aý—G‘lÌÒiªx€|‚TÜ×UVŒæèE‰mJ¢&°Ä¹%Å÷Þ“6{UšvT€@›¶ò­çF?~ù3=®Å³~gÁÀ*‡=츺ãõŸ.ƒ6}výžÔâ`t…“D ¡‰½C›vrnÑ×Å‹+ûüøáßÿ}íaÎ  #ªò]_¶×ÔÛ¹KêÈM…'Ö¡ñﮟÞ@€”:T5íÎ3<ùW‚Kb¦ò¢Xᬪ·EWNoo!‘õ9Ñ@ @ ç@wúqÜVFrè.M7YôŸÝŸ.`ò‚/:~weÔö¶—§®þbÁ‘wʬ(|™ROch» …¼ßeiñ-´úÚ«•È‹p‘Ó¥YÍzk‡¯½ö{s_™F¹ü"‡Ðwk:Õºrɽ„'Ë¿ï´ê`Åbï álË1Œ¶Ó‘6›­¶¼6F–ù@ ï‰ó×B ñã+N¤»:Ýý³;½Ù í]3ÛnTä–Q§£Ç·´³yä™ÈQí\ZeœI[.1\ùüÒˆösíê™ýËÜzs:wÔÅ/fW´ÎcÆíï`XQ»ÇÄ×ïh$‰ë snœüwc…IK:¯ŽëwôŸ×o*eM×¥“\‘ÍrÚ˜ÍBRîþÝ¿ÃêÞ+ÇÁ@ Ê+¡äõ¾»³gêÕ5¢ü¤2ÿ*ÃÜõÙÐM¾[Y[kú·ùåÈ÷Ÿ'ôùR"”4é7§ÚÔÝ%îZòíêu„<ÞûÌ45^2úÞú{£—4®@f»ÄÍøèŽ€€Ž£p3>¨k K«sÅß+SWö‹kÅMð¾ÕþTxÿ XJòÚøÈ ß¡ —z4£ wÕwßÄ„ú Äòèúmæo¿±éä#ê‚àn¿íúî³9}K’Æ}çTŸ¶g]— Wd³œ6¶gZµ„¾%BÉ—}j~ä—6þ°ÁC ÄY¼ÃyšìËÓš­øâéîÎÿ'ù}Ï÷1!)FÅßÈ+uSW‚%ºg\tà¸úPóû”†©àî€~'6?œó±”‰ãM ù༃„rÿèõÇËJ8TW8I\.—Æòš¹çJ=óc)(• òéH(ÈGÊÿ§" @ .…E@ %@ ”P@ •ÿ¬…âp8°P @ŠÁápÊ”P/^¼xðàA©ÁªW¯îáá‘™™ KòNøúúæååA»‚@`3‡ùL]&“•.¡|xæÌ™kÖ¬Y¸p¡ÉdÊÎÎNLL|ö’âV E’$A¸A¸D©U«VNNŽUäâĉ0>3;;;\ÀJKK e¡¡lZJJJ ~SSSØŒãÇ#"¿çϟשS‡J¹ë’7pàÀ‡ ² ÌfóóçÏ“““Ûµkg±XÜS€ä»ðúõë .DGG?}úôC‰Ê´‚ þ¬ ú `KU%R7nÜ žzõê•õâû™ßöëÛ³êt,8H[¯Ú×}âôï¢ÓfôêÕ‹ËåŽ;öúõë°»„¸š·Žùùù°MUþ‡¢.*Ô^ETÎŽÔ%Š ˆW¯^5iÒ¤J•*þþþ‚7ðùü»wïZ­VwfO¡PlØsô«æu-\Z£uÜž©£¢›¶Þ;utÕÖvMÓ²Ýîé"[´Ý>qdTËv¿Z¿Á’%Ë;6©=lò …B¥R¹ºÚŠívj“ÉÌÏÏŸ>}úúõëÅb±Ùl®$fD†aV«%--­Aƒ;wî¬]»vbbâ‡röðù|‚ ¬Vë÷ýP àñxAPª·²¹£NŸ>ݬY³èHñ™S›ÏŸý³}»Æ‡ž\³ziïÞ={÷î×qö÷ÓØ,FïÞØlÖáƒkwl_Z­ªgóæÍOŸ> Çxˆëàr¹¶ñB£ÑPÍÙþ‚¼¼¼€€ƒÁPò”Ú5—Ë5›Í†}ì…l6›Ý_€e•j@@@FF†Ùl¦žíOñx<>ŸïÀ>M eµZ èŸ0oÂÍ;Ç'^JÏz@ý›¿hê¸ñÃÍf“;K!!!aP·¶+þ<>ïû&“¦Ÿ^¾lìØ‘Ë7í›òí× Çb±¸4…¥ê'ªˆ( n6›Åb±¯¯ïo¿ý&•JM&w ^¯üøqnnnnnnrrr1ñôæ±Çq\©TΜ9óèÑ£M›6­U«–ûýOA…B¡ÓéH’ü€*ʦ–¬V«B¡‰DƒÁ@%²ò4þN:íÞ¹¼ZµªþÁÁÁUx\Id•7ï=}úRU¨ÎHÏÞàô¢ÅKFSDxXâÉå°ýý¼]1»S§Np˜‡¸Ñ|ö^ ##ƒrÏÛë§ÀÀ@@nn®Ñhtgƒ¢†s€Z­®<ϱö?I¥R­Vë¶i·¦'222))Éd2Ù«(ê”{ød%ÔÅ‹ç ?û,&7?‰ú§Ì{©Ì{YµZ°Ål¹~ý:AànËžB¡Øð×±±ý;nܸqÆæmJ¥rúöÝJ¥rÚ¶ÝJ¥2áÀ‘ÜÜÜU*•?9©Óéæ8¸qãÆ±º,X½Y¡P¨ÕjƒQþè¶nÝê$Y€Û~ Øl¶H$jÙ²å²eËd2Ù»ª¨ ¤ŠÇãU­ZU.—Ëåò[ÚlÊÉæn¯[·®H$*(È{òä‰ûõI’B¡P¥R%$$Ðh4F º7«›ž3›Í”v¿yó¦T*EQ”jù÷·.о}ûÖ¨QÀæpù|qD•*ÞÞaÚ·îûu§È¨ÐÀ@Ÿ6­†‡=|ð¬Zµ:Ádp8l¡€çÄârV^ Ÿ…:óël%VìÇxJ?]x (((pçðOé§}—Ÿ4Ⱥ¿P)½ê”¿¿ePQTìû.?«[·îË—/íUuª,{¨<¥ê| uâäñÙŠñ£Á¨×ŒF“Ùl±Z­^Þ²¨ª¡‡4™Ì†áÿÅE^BBÂîm—o>äÈ‘¸¸¸·þÆÇÇÿºõàäoû&$$ˆD"·Í<þW<ÙÀõz=‹ÅÈåò¦M›nÙ²¥oß¾nxJNNNCZZAàÙÙÙ)))/_&=|øP«Õà8®Tæ…‚#â·lÙ2þü¢ŸÔjõ¡mS …··÷Æg̘¡R©(ߎãn[=†ãx^^ž@ X±b…D"Q('®ìºqã†\.w¢Šr Û¶mãpxQÑõ”m4šƒ£c"Úµoߥk·¾_w›0aP‡Mc¢Ã¾hPÓj5Òh¨D,±X,J%ü9Ä}Ø7J?½ÎQ«t&€ÉdrÛBé§ËÒL `µZ‰Tf§”íÑÎ 6Ê·ï‚CnVQ%WHSK¿ˆñë»àPlll1U–=T*èÎ÷B]8?rT¿—I÷õŽ“4¥ÑQƒ HµÏ"þ¹•§R©ž={V,à–-[ºvíJ£Ñœë…úcïñ1ý:Î;wÕªU¿üòËW_}åà·sçÎ'Nüþûï‡OùòByyy¹Á°H’$Iâôé3Ë–Í¿té& Y³#FŒoѼ¹Åb‹ÅÅ‚,Y²ä»ï¾{'Ù»bs>I9—J¥T{´µ‰D‚ã8uÅb~ÿÓÁ­“[wŸ{rïììììk†µ8+44ôìÙ³ÑÑÑ\.Çq† ˆ«õSRRRÍš5/^¼xüÂôôôýoíÜvÈæ½¿Ü¹sÇÓÓS©T .—KŠ¢.MOy¸~ý<ŸŸÔªukE Âêá›Lz.—#•ð ÏQfŠE‡çã Rës²³ïÜy¬7ݰ”õ©ZHå¤zõêÕ«WwÝý)ý”ªTß~ž­3Z­Zµ*yYff&—Ëe2™ÎmÚ”~JÎVSãw©ŸùS*•,Ë¥½qÅàr¹¥§¡H‹Ïƒô?ì LMML&Ó 5Z½ÉJ¥'66öúõëááál6ûc±çK(‹ÕÂd1ÕÕj5›,4JgÐI‚$2,,08ØŸÃrØ"“"‹Åb²4]¥ÊoÝ¢w^^‡Ãqb]&$$dddL_´nàÀwîÜ7nÜ‘#GÿÆÇǯüóÀÔøþ={ö1b„Õjun³,M_ã$ öíÛ»xñO#F|³`Á ½ÞpãÆ½„„Ù&“±{·®M›4ÖëuéÙYÙ÷ï?Ðksúé§1cÆP«m\ÄÑ£Gãââ………z½Îß?°lÙÒÎ;kµZ‡e2™­V+›Í’Je¸IP}¥Ÿm›Bé'ê·÷ˆßNîýäÉ“˜˜˜Ó§OGGGSËÌ]§Z(=Gé§ÄÄÄ3—Ž6uÏáÍÝ:ô߸{iÿ®cþÜÿë7l*ŠÇã‘$ùÁ%T¡JÃ`d]¼xÞÏ/@ zzzÓPêÑ…ÄqÜÇ/Òj1ªÕ…I¯^<~t/-=Û`pÇÒJ?•õ©ZHåÄ¥ó&yyy!!!©JõÄ,’$Y Úž‹‰\Å yKù$IækŒ;/$®Û&##ÃÏÏω}µM?¥*5,$É=é4à ŠPÿ•'kǶÉÏÏ—Éd4 E+Ñ&A”/çè—Œ ¡öoÚòÔ&ƒW?ü°·JÕÏßw›ŠÒÍf+nÁ“ÃpÂ`Ær õ¯²T¶ô4mÕîü©cááá•P’ºIBefäÐPZV–’Åb› Aét H#Xl&›Ã²`:³VKâ$‚"$Aà‰Yñ‚B5Àh42 jÀsŠ9*Š ;þÛ¿Ó¼yóöíÛWž¹¼nݺ͞={ØÄYnóBQ>•ß_? U«<ž×ÇW""‚;vl¹iÓúØØXÆb±BBB<år±XôìÉ]€V«u„"I2..Žì=zT»v-JKI$’ªUcêÔ©K„ÝfEónÓOàñãÇÅô“ýï?ÿüCígájÕB¥§f͚ׯ_?séÈW]¾Ù¹ÿ÷.íúÚôõ{÷î]OOÏüü|‹ÅÂb±>¸ŠJJJµX¬bÁlÊŠ<•9i6G£5à¸Õ /Ä1sFfza¡š IAP5ÍV‹Ëg´¡~úéׯßÖ­[£¢¢œ~ç‚‚‚Úµk§*Õw^䘭8å«Ç ŒšÎKÎVÓi¨ÃSÒ2jµZ.—;]?%¦°™t*vœÀ0¼¨—³Ú`0¸ôiö½†ã|ƒN³%›*CEé4hS;DôýŸîôE½ÎÑÜ~ž]ZzP[z(_Tppðÿ©„ÒéŒVŒ(ÈU™­Öµ«vå¾ËŠfÍšyxx 40.®£D"qŠ*%%eÆÏëãããW¬XѳgOÇsy‹/Ž_¹õà̱C»wïî./AÄ¥K7–-ûÁÇ'æúõ#z½A§3øúú>ýknn®‡L&•JqÇ1\.÷|Íd\ºa•ýÍ5jdêîÝ»R©ŒËåhµ:H‡#‘HÜ9KM„J¥‹ÅGÝòCí¦ƒ÷Ûÿî_Û¯küÖ¿6MR(+V¬?~¼Ùlæp8®P-T®:¤P(Ž;0fØä™‹ö›:å§î#û,™¶ð+ê·Wëé5kÖLOO×jµb±˜ çÎV¿+.\hÒ¤ÉÂ… t£··˜ pÁÍf½PÈ*È×ëty©Tdµb™YJ­V÷êU: x¸páT —bÅŠzµZ=xÒÜçéù—¥[°¢E<‚àI ·‚$É ÓP8u­ I’‘±m¯m <==1 s‘[ðçÏŸ?O»ûó¼µçtÚcîê“GöYbûíÑbj×®]SRRÔjµ··7Žãt:ýöùºuënÝ:­TšóówÏ›7/-õ>ƒp8B£Ñh6ëÓ3rØ,æ«ät×ç祿5ªe ¸®™ï¹ôìÒ½$@Ïž=]{±ùôcjwé]p‚Tç8ùÓ</aëå¿.%:˜ ±º2K¨sw“-&%õ<”ƴ蘞žŽ¢¨KgÐ.¨1¬˜`§ÜF`VÌd6[-Ø“‡/B‚#Ø,ç,ÈW(kwýuǵ;ÿž:uêªm‡fΜùËæýÓ§O_µíЬÓÖíú{Ö¬Y+ÿ<0{öì_6ïûé§Ÿ–mÚ;þ›n}†q›Š¢cÇî›6mèÞ½½—Hä!—ûתU0lèÈb…&àó\‚À[·nýë¯+¨*»|ùr£F&OžT¿~=±XŒã¸X,y³"ªèMÕ·Þöýíʦ¢¸\®Á` TÔÑ£G;tèðòåËÕ«WûÕ½ÿ—N_O;uãô…B‘››ëïïoµZ©!œ ‚ Ô.šûNnìÙzôâõc›ÖîÓ¢E‹o¾ù&44tÿþý]»v¥ô“A”ö­ ú Àá°é zLL4›Í Õ¨Õ\Nóð0ùÈ‘½ŸŠ¤;hÔÃDÚAwn=óôôLLº B¹œ$°‰*‚ )ŒÕŠY¬V‹Ù’Ÿ¯~pÿYxX˜L&s–êÕ«WS¬ß¿óüõ»º4ª>4~ô¬i“gÍ[8öÛA3~?dâ´ÙF};fâÔQßî3`ÈëWí8tzú˜at Ã1œÀÛµk«×ë/^Ç>¨ÿ¢õÛgŒ°iﱩ£ã‡ꦵP8NƒÁ‰„8n¥3hf“A6iâø%?/Cä«^_oømm£F ÝÓ\qÏÍUÞ½{ßÞ •˜ø,$$D©ÌŒ¬’››i±Xþ›=²<ë{®…*UEÆ‚‚½^/“Ét:B¡8³kR“¸9k×®•ËåF£Ñu¯S^¨#GŽlÞ÷³B¡À0ÌÛÛÛb± ¹\nµZ+•ÿɶ#0…Þ Èd€——¬æçQ™éR©0<<8?¿Eÿ“`£ÑH£Ñ¨mGÜ?l4×þ¾äÅŒÉÿV¥úùâºæp]¤ö¢áãõ!9KD–³œÕÌQåp8aaa6Å{vïÞÍår©íšmWŠD"'vÔ%Uõ¹sçØl¶½«EQ.—ûÁß)¥R™ŸŸO}ªÁvz0þ ú)333##C£Ñغ ’$Û´iSÌÿäëë+“É\=ìºVB½çd¶É`æp™z½‘Ú…Ÿš¼Eû\“€$1'³â8Ž[,VêlVfî¹37çÿô#Çw–E*Šu{NLü¦Û/[öN?æÐ¡}úôíÚ%nì¸É+~Yò×ÞCnÞØûëû÷î8xX»ÎÝgN™°`ýö]k7mÓÉm^( +ú5‡Ã–Éd|>ì@zöìn4™V¯^ :,þÎíëlË oäþðá£~ýúQËÉ=ztéÒ¥Fá8Þ Á,Ë××çÍ.áÔwTÊ%¡œ²H¢Te±X„B¡ÙlÎÍÍMHHHKK ¸ÿ¾F£ñòòrÑ>‚ñâÅ‹ˆˆˆçÏŸW©ReÈ!Z­ÖÃÃÃ0@€a5Užù; ÃìGA*MJ#ËaT†Íf“$ùAö^´¡Û—ƒ·L¾4Ævdóà•Ý~¿ºµÓ¿êìÚi3Vìx’Z( ŒùzÜüùÛa†Ç~ÝŸf?‘Ò‹4aÍñ‰Ù›šQ•K¼oÉ„ùn=ËdIÛö›°zî`.ZÞj*WyN}¼ú©ü*ʉͼ˜ŠªÓ}•___‘HdÓñ”âqî{6ÅT5åãr¹öQÓh4‹UÙ|Q(вX,™L&‹m35Ôj•iî×OTÅùùùQÛwQI²O½~¢¶¡ùˆ%x¿ÉìV­Û¾Hzœ•¥´Zq꣌AROÀ@0'p‚òB™Í’f³åYbò—_~ùÅ_°˜N3Ç„„„¤¤¤ñs—OÔãÛ‘£¯]º°oï_ß º|Ù¢qã§Û ðø IDATlß¶ù«Þ}ìÛ3xèð#GO5|ášÍÓF\±õàŒI£‡ â/”Åbyó)7›Íb0þÝk„N§÷ìÑ],ý4!  ?_*•„Ëm ÇñÞ½ûØ^Ç£¼P”Šòô”ËdRG¤ŸŸÏ›Dn[ URE‘$Éb±¨Ùº:uê$&&ΞÜK¡P!“É(?ë¼P@¡PLœÿþýÀÀÀ¬¬,£ÑÈçó©TQ‰¬õÑQa¯[…›yÖ¤Q¦:PQ‹%‰¨ Áí»WÌÔÛ«(ƒÁàñxÀ¾»«T ܃A§Óíµ%YžœÙvéÒ%çNýD¥G(Ú§‡rG=9³mË–-þþþ6ý„¢(uª¤=¸ú!á]ßùk¡Îž=àY€±±õgNÊã ì=´ïï…š6gñ¤A½®ß1iܘ۷vïÙ«cûÖcÆO^¾tÑÎÝûŽ>0ôÛGŽîܹKÓVífN8Õ[W/iß±³{¼P:Çq@’)zI¼yi‹jÀ‰¸i“ÆUc¢M&“J­æñøîÜÊ~w.j(‹e2™Âä¾î Šg•KØ9ÅÿT¬›£'Nçóù·oß^úã·AQ­:uêäååe6›…B¡KËŠÃá :l ¦^½zÕÇÇ'//Ïb±P"£²u¯†éõz€Á`p¹åz»S¯7R@£Ñ¨7w>@Òúâ ][Œ8Úk_OÀÑŠ®ÎÒíŠv餃ñGŸv®.„Ôé´ýèðè.?¯ë²¢ó’6sÆî·ÇS—í˜|¶Ýê%€•C×ýt.©µÀö«6sËîå!ñ`áÕò¤¥¬¸Ÿúÿ¡ÂÍ|Äv6åd?Og¯¢¨©4æ†-j‹©(Û,öDzÍG©ýÏýû÷©¾ÝúÉAgxäÈ@àååeÓOŽíÁ¹ ¥ª¨ò?<8-”Ÿ_À­[7L&åY)oïÈ óù|‰DÆf³h-[¶d^¼8-aþ̉£\²|Íò%Ö¯Þ²m×ßGî;päð¡ýß rèÐví:,ûyÑøQíÙ2uÄ€•{þž:i‚{ÖB¥§§‹…\’¤^·+òm¢B}[ƒ†¢6[&“¢4´°PÅd2¨Ù3WÛº½J92žÍf/]ºœú3?¿€úL:õid;ÕåÖµP%UŽãÔw] E·nÝär¹Åb¡Ö$º¨ùÙfù|þ Aƒþø4hÐààÁƒ:ŽÚ…ÜÕoW¨f‹Ö&ææ–3“É0™ÌT S/å}¨LùµXUçÛËšÎõÀ‰÷ê&·ð³?»;Ïð4FjûS3Å À ÏúKįCoiGÖ0-š+óS=’ëz6fé4U¼GÿûoAÊÛó”—ãSÿ?ú©bÍÜ`0\¾|Ø­m*©¢nݺÅápÜ<ðS**==ÝjµVÂFýNyÉÍÍÕét”;ÍÅXVz?~L9ìÅâÿ¼Ù ˆmí@(º(µ%UÔ;9_¿ÊÓÓS(bʽm+Õ)3™L&“åD fÍš†Y,–Ž;*Šš5k*Ѝ¨(…B P(Äb±B¡ðððP(ß|óB¡èѣǚ5k†zóæM£Ñ(•J]jCׯç2 o'Bb¿@0ÌjµZÍ EŒÚÝ{.ÿ”=ŽãëÖ­¡*‚Á`V­Z•zj9r—Ë -é +O¥9w-T1P ÌÏÏW©T|>ßd2Q«È]½Ò“N§[,‘H4xðà‘#Gêt:jTåüØ8õ¿zõê‘#GöúªÍÕ«×p‚HKÏ¢Óé( ¥Ñÿ}¬7™ÌAäåZ­Ø®]ÇçÍ›Ç`0 “Éü`¨Aè ×·›qu˜Ðaýzùú „&\ÖÖkêŸIçFF?_?Í·ÃR! à$¸­,ŒäTÆ…À5ïÓÌ#""€ÝÚ&û±À¦¢¨mÞÜ9öSé¡f—>v Åb±(^eÈ‚ ~~~f³™êXŠMÚ¯*i.RQï:yíüµPL&‹Á`R⩜ù¥„–+Þ—F¤nݺÑÑÑ£G.,,1b„Z­.Ïovv¶Ñh‹Å.5² 6 :´.\èºúþýû))É~~þëÖ­yúô)ŸÏCQôÇçòù¼;wîˆÅÂk×n¼qi€Åb@Ú³gÏËÙ½:q-T1¨IF©Tj6›íõ“ë*±èkY †a"‘ˆŠ½Òê'ª@$Illìü1hÐ ê`jj–PÈ7Œ»víÉÏWY,Ø•+wçÎÝ¢.زe‹@ ‰DÅÞHr¿#ªúÈ£@û¿ú;ÕÓƒ»,±pNµ¢gUâR®ÇWÔÿ×ÿqðÃF ÀÈM?,2ìZ=êà?¾âDúÎ.ÁH†ƒ¸œúè¨ðG…›¹‡‡‡ýsu±–K-‘¦¼nþ¡–}ì[£Qs •$ö¥Z,IÔ)ÛÚ)Wo§B©¨ ,þsþZ¨JµøƒJ ŸÏ·X,žžžV«ÕËË«œ¿Ôöž.}àîÝ»w\\œF£y×od²Ùl×½¨ÿùçŸW,à‚ Þz+üOö"‰Ãá`ÆãñH’¤êÎÕÖøÆWÇÀqœÇãá8^9WAÙ,‡‡Z´h‘™™ùâÅ‹K—.Íš5«Ô‹'OžÜ¸q ‚ X,ŸÏçñxÔrפ雟?.õ̤%ëÄõ«¿ou›ÏýÓïÙmM×åw¨S ‰qEWæœCZþ  Žß™á©ˆ„réšÈÿ-Ю NWöö§ZŒXxcÄÂR/«>ãªfFñƒÍîl6°bipWY§>Ò9ßuŽ6sÈÿ¨ƒf`{˜€¸Ší]äºJ¾Ü=ë³@O¯âß9v¿])ŠJRÅ•'%•Äœ Ÿ€„…ÃÇÿsÛqs®+a!;a-nN]9ûûÍûϼÊÖ ¼C[týfîÜѬ3A¦ÛgŽßzü"O­§1~!µê7¨âQÉÍ®2<ž–çAsøØU3Ï¿èUñò,§])Š„„„ò,Çh4¾¿ôA”Í—„DÕh×®‘†º?%ïd]t&GâéýYÝö=ŒèÕ”¸ÏN ÿ申™ÛlAéb¯à&q}/žìǤ¹Ç8íûa„Æ{~Ѳë÷‹gUV®O‹TÎñâý¥Ï§Ñ¼ïZ(š?°~ýŒ/'ü~|aÕ IaÊãÍ?O¬ûÏ£[Èè`Íéý]knóêõÚÞGÊÇMš´—Oo^Ø^3ìì]w|ÅÛffw¯¤“ÐAªt‚Ø@Py  ((ŠŠADÅÞ»"bÇFU¨ EŠìXPˆ( HI€@ruwgÞ?ænnn÷îrIBÜçã/w[ff¿ûyžyÊu&=¼²ÅÛÑsDà髲ðÕ[?¥ï$‘pµq– eòäÉÀ¨y`Ïö/—¿6k~Þ ¶8–˜Þ·{ûºo>yeÊgY³t2æwÄ‘„2räȃµ~Jÿ5XݱiíÔ»F6¼Ñ†·.:ô<ÌÌpñßO½±_Ï[wüôÔáùFÑR[õ®Ä«œ–-[öèÑ#àç'Îþ¦Õ+Ÿ¿¥k«úš¢ÕoÕõ–VÝßâ«!Oþ"–Ÿ«¦ÞÖ½C³œ¬œ£:œtï+ßʧÿ²èñ¾'´ËËÎnЬӨ;gù£ ¯×ûõ«ûu똟™W·ÉiÃ'üT¦§ÓŸ¿ï¿tèiMêx©®3ìnÒöØs/¿¨.îßþNÑôGzà¾~aöâ!“ê»'>ôT@Z]1ÓÿÔCwëvÿòÙËÏ?õàý÷OœüÌ‚÷×è5\²G¬ÓS÷ýÛWî=©ÃQ9Y9Í:t¿õÅ•5Ô’„ ðz½&c^¯W4uåÔÛºwh–™Ý¬C÷Û§­ªðÊéãªB³Ðßk?~ù…§ºÿ¾ž4óõ¥»B±pÿ“Ÿ~ñݯ7É'nú潟ž|ÿ}÷O~úÅ÷¾ù³R7 ÁPXˬÛkèÈ|àŠêÊ)pRC-ISÑê4lñƒG½òÁÏ… ~üç ß» ßMþè½QIÿjŽüw¤ ¯9"Z£6'Þ3{ñ?Ç6»SÐKŸ‚3ýÔkÞñʇæØ<‡s`Ûšk†œÒ¨ 73§n·Wþ(‘ðoKžpR§‚œ¬ÆmN¸{Öö«íù¡èØ &Ìø¼¦‡:Ùy½ÞwŸߥeÃÌŒŒð/sëuI¯=ñÆèGó„º9_§è¬|š€þõù®F–Pv0Å”©ë¯2ÂòåÏ^ûÛ ±l¼Ã&ýtwÑ'ÅûŠ?-ºkÍ}ýoü`;ÿ~×ç÷ö}píMÓ–íØ»o×󚯬Ïí18žýغñÏ,ü»dÿ¶ _ ¯¿zÐàYé´'_ŇÃå3cÔ4¡ <=geË^Co»÷Á‰ÜѧeÙëó×+j½ÿèïî ݼló2½îÿŽÊÎðoþð¥U;N9çòûzøŽ —ÔÝûùKl;dO%Yß·pã™÷­¹«èÓâ}ÅϽkݤᇲ\ðûýüÃæÅ£‡=üýí³W•”–|<çŽï:wÌ[[ҡ׃ÒÂW?/î1ø’{œxߎËÝ6·h-‡ò?–¿òÑöÓοú‡¼fd¿ÝŸ¾.NÙ÷ëâ×WýÓû¼«œøÐ5#ûîüøµ·7¨Â­£:"*”'ÇÉ!hIÚo¹{Âìkzá‰tÞ»ÔÇÈàŸÓ¹š#ÿÁUTÏdaþÿô’ì';8+!Ô(ÙúÛË÷Ìm3ŽÑá¬zß<ý÷ö”îÜpS÷­çœ÷&ÿ~ç§÷ž2vÑÈIó·ïûñÝižo¬ AþX:éøþOŽ[ðÃÓ£O®ÑANÍÀãW,øfc¹Ï§e÷èþãµÝ~í_9ë—ikÊÂP¾cÚ_žÁ=²µ•¯Ssп>ßÕÈ*MY±/pA}«s±·þÁ}+ÄŸW-;àØæš¢5?vÀÜeW{†ÿÜÓ&.ŸÖ÷ØVn…ä4îtçœ7~{ùqÖÔ_ؽW#uš]ñØk%ßML§=ç 8~é“¿¶xÙß|¿qóÙ$pÛ5wtc…™aµé1¬|ë*ÍEÚ÷?ú÷%kÕhyöWljsV!Pý‹Åßö»tX§æ`ê åžrΈ]ß®p©mkÒ/–_“õý™qEb0[wÖ«ËÆÕ,Òü'o|{ì²×ŸÐRS4^ lñ O2à7¢K«úˆê&rwé{žoûGšK€/ß^ÛíÒ º4Ïg†á)h9ü’“Ä)Ÿ/ÿõÄKGvmQÀ ÃSÐjø%Ý~^ú…V©½-FËölÿxákžÿÇ¿X'5Û’JJFƒ‹ƒûÞMç½Kÿ˜Êéˆ#)V0;ÿøîáËÎÉ/¼µBz9ˆÌ£àÌì£ÚwÃôs?¸3bB^»dhö™Q­ßˆ‹NhšzÙŸ‹ç~¸aë®@ØžF«Mú»÷<¶v¯`·|Ršq[‹lª‡¿+ …`I´F / †ôÐA“ÔJR²¾ÏÝåûYÌv×<^,ÁÿwkuÊPÃÁ¯Ë‡I5}+Æåágá÷~sôø”Ÿò³O¿©Iì'wÝ“õò§‰:ÌŠ÷ˆo¹%¶, Zý«n?…QRआZRE‘–géÔ†K¿~\u*ÍY¤°°°¨¨è`yä8rh¤¨¨¨°°0Wyq >k™>þcL…ôr™'ÆÃÌ(Þòë¬û.;jáïK.ÿÎ'Œ¹gùêŸö–‡@ ú•å¿&®úµâžA£W´þöëù µƒìœp¾H=êÄ8¼ýu}6Œ\ £Ú,™üÓÀ~5ñsè7bþ¬M}Þn¹~’ÎZ®S (Å”÷¯ÏwÿæêÌ<Ïk»|W7ÎŒ¬]¯ºóúKº{œ"/>ÕP*œ׾ëIÆïÛøþS¯.>鎋 ÊÞŸ9?ÔíìkÏo—›å% ßrëa×€6™K¿ÛÅqÙ»¾}/«ÝYYÂŒ2¸þÁ‰õÕë7‹ÌZìr¢"Šw©a4ˆ°*c«kŒø˜#‰;Ž‚l?!PñÂ%êNn”îÚ¼âչ˾úç²u Nj¨%Uߎ9îÜ~é¿wé¿›ñ-.,,äS²³.9‚¤°°°°°pÍš5ÕY03¸õ×Õ÷^ráÍ/üüÁmÇþ Ý@JÝæ…7O]4±a?€ à®Þç—™ºzÖiò³ x3ók$’Û¯¿÷ʼnsW]wK¿?™ª›Óú¶åÄþ3&ma?žýäñú”ùŽ{a7ÚØ:Râ"Egåëâ 舘ïªK|׎i7ìÚׯ^8Zþòµñ϶·@üùÔ†Ò‡¢£ömx*£~DˬNªŠÆžš52šžh†V«šjÃßïÝù]ÝT×C²}_‰c›ô=þŸé©Ý†~ôÅî¯iÁÌ0Ÿízo}éðÖžÃ걬—!féú3r¤Fkµõ(«KCÝbÊ „K¿UÜí*<±k¦öéîÀi¹‘÷>Xü…l¸údW wì§ÏÕŒÎÉØÐ.<ÐÛxÐ#&?Väïy½›¥ÂI͵¤ò¯CxÊ¥S:^õvúï]Šc„L’Æ‘UžuÉMq7ëÜ{ÚªyÍZøç†_i¤jU-à¬ô‹Â(£‘€ß—ÿ.ÛzÍà,‚ ìï—Ä1£f>öóž‰Ç$L®ßsì×+³{÷évà¹U oø00Vóoj¸ý­ëÕæ·6ÌhxsãÒÛ—Üâ>ê–ü¨î—¬³ÿîtXÍwɤºV–N7->á{úŒ|íŸÅº©ÿ¹vòÕ§Ý»¹ûâ:Šc¦žuñò¶ÔØòÃò‹¼pþs×ñï'̾þ£+úOYüEiÀÐ~úâë‡XÍöLyyÁ·?o*õ)£þý»¿\67³io@Úy•¥kþô…õòâÍoÏŽùö»s{¶ ¿|ü÷Ç¢V½ò=†N ç°¿Ï›þÕú­Ašzh×–õË^{¡âG^Ã{ž?_ ææï—<ë…´€X3­ºññÁ/œ5rÙ÷›£yqÈ“7¬‹ŸÖ·ÍÊéó7n+ÑMÆL½øïõ gÖ¶ßÿ€™©Oì1¨ð‹¯nܱŸ2ºïŸ oÌŽ­•O>³Ãç3Š6î(þôuǽ•mq5ëÛÐ\ü»¥ÄÉAoI¥Ÿ#5Jwmùä9—ŸQø2:ûí›;§ÿÞ¥8¦[–6ã»m4#ÿÅ7Å‘#Q\9§Nê¢_½tkjzIñ“œ•z[J¶üôÄUç6ü¿‡ùßó=7Îù,`˜»ÿìªþŠã®›>zúYÃßøü· nîݲîÑ«N“¯’×ù‚O¿žµj©ãg~[ÓoA¥øÌ«ÛιúÃöú@ÿ fû¨íÕgŠ_“uö L@µc¾«)+V fóõ”;ï¾ô]ÿÜ]–U¯eŸ!ýÕµrR¨7oëtÛ…§ž·uoN“£îYúP¿&üûêÔ¨J&ô:úëo?ûdé¶ò éɪӼ]—±—ŸÂ¨G š¿`ÞÄEe®ì‚.=·³… Ô§{Á´—>nôã ˜aÑ¤×ø‘9ï²|å›»ÂH­ß´õ‰=‡«šK‡þEŠiÒ÷Üu݈žçmÛ_ç¨çÝòÆÇ7õo5¦Fkåw>‚}òñÒWçïÚg€’[·Qa¯‘gto`êÁÔ'æ}Ö¨>-?uWiГ[·°×È?—¿a·ŽC.ððþüé»JÇô¾hPׂ /˜P: ,|¯èõæþ)prhZ’P¸ Q\yõ·ë||ÿ‹ž{ñÂÓµ¨‘+÷.Å1Ï?~å¹çÓî2ʘß﯉·Ø‘ÿ¬ zvÄ­ƒŸ‚¡SªV…ÐÎ4ß@ˆäÔoÑ{ð%ŸNd¥š²ü¹ó/¾¬Þ5»rµ=ïš"¸uÿ¾A¯?}ö‰ë¯råúí;Œ¾íiË5³[ øà‡…Cº÷¿¨ôõ¹7~˜0ðQCF™×=~`Sh:ðjsÜ——9*fzHÒÙƒ8U!Aèa5ß%5 žxæEÓž~¸y½,xóÍ7“­àŠŠŠÚµkwüñÇWÍqN-„‰ª(c„€1FMC× ýISUŒÿZQ]"O#V\.S=2¨t)EU Æ£”š†a˜Ô¡¹JÉš5kÖ¯__5\aEU Á£Ô4u=útì96åo°¢ª Á(჎ûI7Òz öÛ!¬º5õÔ89è-qÄ‘Zöš;âÈ‘õÎ;À²•«§Ì|]©}=dÔ ‡Íd?…¤Œº›© öãpÈp@óo 5ô‘ØÃÚž£\þÆrbüƒNzÍb¿£z X1NzKqÄG9L;Càˆ#Ž8âˆ#Ž8rØ-¡œŠ¤Ž8âˆ#Ž8∳„rÄGqÄGqÄYB9âˆ#Ž8âˆ#Ž8K(GqÄGqÄg åˆ#Ž8âˆ#Ž8â,¡qÄGqÄGj…Äå…â•ÒWXXXPPPåZ’Žüg¥Q£Fš¦9¸rÄç5wÊ‘ZõTK¨Ô5>-';âHš˜spåˆ#Îk#µ@B¡X7g#ÏGqÄGq¤Òâ,¡qÄGqÄGœ%”#Ž8âˆ#Ž8âHÍKÒ2ÃëÖ­[·n3@Ž8âˆ#µR*t~uÄGª¾„9r¤3@Ž8âˆ#µRŠŠŠœ%”#ŽÔÈŠË?Ÿ\‡ !ªªúý~Ç …EA Âá°Çãñù|.—KUU]×KKK].ÛíÖ4 (5cÀÄBŒ1ÆBŒÌ0U¢íÙ]¼¿¼,//Ï“‘A)U4·aáp833“R£¤¤¤ Nža¡P(++Ëï+Ó4-hšæñxcLUUJ)ƘRªªªiš išÏï÷x2MÆ•øý~EQt]WUbŠ¢(aÆÆà LÊ“÷mÆó)¥¾²òìììp8ŒBDÁ#F)¥á`Àëõ†B!—Ë…1öù|ápØ4ͼüJ)`@“QÀ4MŒ1!(Ã3Ý`Œ•8 ëzNVCDu¹"¦RcŒ1.Ý»/++ !ä÷ûó²³wïÞ]Ÿ¿wïÞŒŒ —ÛíóùFªK€°iBU5MS× —ËUVVæõz1 Œ±SjRB!„Áðž*Œ1ñøaˆ1ÄÿDEž,fB„89âÒðô)µ`óz½¼˜}ê_q¤úR/ÆXP@”¼ÿR>ŒÓBHþ^p«å`YLÓ¤”Š‹‹Å)âKùú,^øuxk€RªëºaŒ1~qùü3¿N»ØÿLÖ~¹ò¶9ÙñbTÅÀŠŸì×ätlï¦x"öÛ™¦ÉGn¿.KwR?/!B„Ô„žRhÿ*¯×›Sp¬èÿ꫎ñz½…—}&ÆìØ‚¯×»j¨²‹-¾¢rÄ‘C·„²¼º2A[ÞOù{Á2vNä7e ñ_)¥òõíô‘ŒŒä[púãóŸ9ßQJ9à ‘éF¾¾e’qâŬ#7L¾…}¬bסŒ™Ô>oÉ£Á'9yî$ÿ^ž6ì¤åYð?™MRÀ Ålê ÄAˆƒ#!‡ç„äÊéÝ+Ç­û׿³7È¿™ºllÿYþgpï;ëýº;çÔÞ9® ¯æ÷û”#ÿæJ~We¾•ZquRX²7!Dá6yY­äœ%®)hÅ®½Åìüñ:4™"-÷M¨Û%Tþ,“J²y¢ðÉÛ);Á¼B#ìf¹§?KGä‹ðËr±÷ÎþAº>XV¾iB{C™ÒAˆƒ!GB[¹ö¸|xùû=>ðÕ‚=ì]ÊÍN{~xò»^#Ÿ²vÑ3ƒ{[¿NvN~Ãg]öÑ?>‹åIØŸ,¶¨íŸÎ¹àŒî r3s :u?ãÑyNþtGêJ(C‚Ú ÙD»å_â „À¢ú`®e)ŠÂ7é…]¼íò}¹.hçñY(‹‚Ddº”/•‚ÎR/%+<ØÎ}òŸŒ1` EI 1ånÊdZtVØýÉf>sØ ñ]&“xQ ÔûÌ×Ô$CdùÓAˆƒ!G"BÛ9©ó„Îð!óF IDATÛ‹ë`×W“cÇLè O~²Ö¿¸:^ßE>¥ÿÃën™ùî¶];ÞžÜoíÊyžv§Ýe·K•|÷Daÿ«V›½>øië¾~pâÞû/;uôk›œe#é‹’æk/ÄîÓ (HhyN¦›bŒ7ôÑÐy{:žwƼA^ñò'Ó\-B¨ã°×c\†qNnf×.MÇêT˜«0›ÎÍœŒ>¨|ãõoæºõ~¤¹ŽnÓèÜ!Ç]Ø­N ¿„­ÆüŽçFªD…ääx[4Ííwz—Q§5Q¤Ž#›îé”4ëPJ;;×ÞÈІ›¦ÉuîÄÒôÆûÛ~ÐK–Ã6.Ã`±© a˦Oü$Á€ÑUïÿ0çÃM?mÞ Ȳr3;uh|ö€ÎýÛ{ÓGH»Á3ÿX6Ö2˜­úOÛ´|L2„BE‘çx BZôŸ¾á­QÉ"æþÜ…}‚RÊÒþì—7­¸R_ö÷–‘7qÜ%}Ü$¡íÙì+âCË~/nzwlj„صîÈ mÏš™Õ ã·Ó· äÑ1¯ÍÙþcÙ•„ È‰T6~ð¹³Í—³µY7ýÿä{µ´èû‚xOsëdõìÙáæ‘G7«<‡˜zùìWÖ,øbû–½áÌ:Ù§žÜþºs[d¦DˆCºŒxSüš›yÒIGß0¢e%1BRs3C¯¾²zþçoÚP½ÞÎ…G;°ÓÀœ„IÆ!-ÏœšŒ„¿3T ¤²’!‡íœT÷„«Þ-Y3 ÏדÖ"¬N½qj¯)Ýšü jVôm1Œ;¡@>eâÒ)=fÀ©?×¼Q¶íe€§+¼Ñ³= læ¼û:æ{²GM~ýÚ™ÝrëŒ 8+GÎÊî(ŒÛ‡ÎNxÊË®„HÑ(Ê`@À0@Œ± öÝ|[§'ÿÕÇÆò¾p>à¡”bø6¿sYyy¹¦i`ßž²%KVºå»ï_<)¡Õ]&eÞ3N;Ì Ý9aþ¶v]î»wp»†3ú}ý?‹Þþ8,ñzª;ž2®AÚ5Z±ç²yÅØ`Øð—PUÕív«ªº§¸Ä0 EQ„q^¬3"*~ôÔd8zá_ß¾Ôãñø|ǹ)!cÓÇÔk„…m@î\t¸ŒÇî}óOË›/ëÓµyNa¥{Ë~úuû[EïöxhB„ˆ5mŸˆZ"[ì±X)ì‘'l;BPôƒ‚0F3`†IMˆbGÈîŸ×œ´~Ôíƒ/96ׂi4}ˬR‘¿ŒLuÑžØ0}{á˜&D ¤lûOol¶#„HîJòJÑ0 ¸®Þ¶«Wî»§} !òPFˆ´d!„cÑCe7ß°|wÇNOLêѾAFÉ?».XÝÿê’Ÿ;= »ÆÞqyWî—·F¹Ýî` P²sï왫FûÖ 8Æ!v€ .t¹\~Ÿ¯x×¾y¯­¾ä å“»ÛTˆ;‡,zháÙ&Oì~t]o |ÿºu/xíý…Ã*…?WŒeŒý>ÇÓrÀ Î!¡P( ƒA!•âÔ9<ŕӧg¶ëË’E¦=¼nOVãë ó;_ß4ëñ_.÷÷\Xpewï›ë–O¹ AF„Ô|`TOçF3¶•À…Móå/ƒûÞw–Ž´ñèðBÈAäÃyZº®k>cæ#_=¾Á¯·> ŸÐÞn™¸úƒ±:…×YŽ×¤î¦>$¿ì-óKâóp–Ž´%¥4‹WŽüe#0cÌçóq á‹ ‹çÁXaŒ'ŒÁ„¨üOÎêëæüÜûò¦i^rQÝ—‹vóÝ~ž…ßË0 Î#@ÀãñƒAntá „ÇãÑuk· Þø2»áÑc¾áÅ)FÓ4Þ…P(M9Ce§‡éoïse »‘Àâáë:ÏÔ"Ðu«¶â¢û¥¥¥„„•ËnêôÛ[ßó .|ˆTL8G«DQ0áÓ×åÑUUE—Ë¥i_rl6[ B\.W2„RrfȸåµbHˆ„P2„Ì^^zÙÕm,:¾ËK~´ $úgR„D6¸+â@ ‚Cf½³ïòkÚ[2àÒ6~°±Rá-‘Œ&CHji¡¡U%fš©"‡DRYIÃVºLèo›ãÎo͆]ÓÇ.€Ž×u­Â5í Û˜¦Yðĺ=Î:À‘šÚÈK¦?‰IÅ+›Î¹±_MóÁïÜs.õÐp°ñ Ý‚3? BÓÌ$!*â0MSP0ÿæ¨3å˪žìžéÉicŒ(å´"¦p]×¶v|U™ù@Ž÷¾1µg‹Vm‰|FÜs$Qô BÈ[§M¨ì €“)¥Ô4yrB$E6‰µçANßÐrÀtK;yc$Ÿõ…µ$âh¢?«2Úñì8w¨ßß¹ñM ÆÞÉ=yÞ;`Þ‘«Zü]ª†n¶Kc@V“T!–ä§#†ý»¢w¯YSçƒI]¼†™! ¹JI˜8 Ö$·_ÛìÂg6¼·blÕ ?ô›pbâÃB0ƦKïÄ¿i;à¾úÆÎ¦7wK»´ ’`â@}\fÞ™§ZâÎk*ÿ.}–±"„Ñ]Ûw¿úÒÇõ ­,‡|\nÞ§ZâÎiòýR)„ˆ@ÉÎ}oÎ_ײ0BRsÈã; ½jÞ'·8þè‚ÖÍóOèTàAŸCä&UŠCR ä°•ºÝ®ø |K¹;·Ïùu½à©3h`¾çí~}R½*\³Wùͧ´Ã×§ad×oüëw>ßã¶yï8{ù´ÞmóKwüõÍ'¾úòÔ¢rVŽœ%”ÅçÃb4æÓ¶ðȱosÈþ1ñ¦/{6~‰ÏìéP\™÷tÔÚ|¤ƒfO‹"ï2ÈYïø¯[–^Î ÀXY©oÎ++ï~nÛg÷µ­âz0¸Ýn®a«šbëi*}EîBSS–pÇÇz$£”R”!ÄÃ,{5À–w¯ ´to‰¦iÁ+Š"O!@ä¶Ú zìÇ ž;™›l“ „ÙÆs„Èkâ4R‡t:‡7,;/»Gs/lQM‰!„ÑJ!ÚœSÓ»Üy fµµ{ħÃ!ÍOëùe׎ï}±õ×-»>[ùõ»•[ï>ó‚ÞƒË!R.‰ÊqH „¶âÎí{R¶kõP“þ·Š/o8§ù;ÓÓ²ŽXÇ]…kθ{Äð‰o lU¢zu:ÿùãFwN|~tŸÎÅeᬺMO8µïÅ÷-v–Ž´%”]±³$V±ÐœR¢Þ›ºù—¿Æ"ê `ßföLg{B—(k"K„¶È­a:ŒëÔË}U¯ç/ýˆ±6Qà Bäi#¡ÀiÙdÙ~cXž’Ìq…öˆJ)bTŽ'’“÷mte6cŒ!ÙûÀËÁb)6R-ÎrÀ¥TL–ö#I¼ï ØK±NÇØí9=‹,ÞgŒÊ†Ç ´0½æ’påañ£¯!bX,½“ƒÿs[´ž;ɸüŽw 6ðæS2S{Ф@ˆ}îO!q×AèÖñM.iç=°º÷µ}Œ(­4BDóŽj{GóãW•=ـ䲖&Bze‘·öê£ê!Á}\™ÍÓß@­úqÁÈÌÌ̲²2·ÛíRµ²²2;Bì´e„œ–IÞÚ§*ˆK«Ü¿YõÖ­Bà§×†egg—ØÿÏß%Ï=÷åƒK÷¼zN„©CÜyu ÈÄ0sËšoκ÷ã Þìp9DZ‡9Ìå£û,ßt{ú;¿-ÌΞ9SþFþ|ìµSÿ¸Öjÿ®{ÜÐé ‡:ëGjj %û)[2ö‚-Ùœ¸/‰ê…»ŸÚ3i úzñîòýA=œ±yÊùo®vÈÏÿ+Ó:!B,’…&0“åq\”Išf`š&QUB°\©*ávÕ•ƒò¯žþ×°[–M–yÑâ’ÉST…+÷¦iòÝJ.D†ØKýÔvðYŒ1fR0)Ã8ÖAÆpÔ˜D¥ x úKY Á†Lj¨Ó«‚Ä-V "ÜcQ.GE/€I¹¡­ã3fhÁ¥OýzÉC…( H쉄U!vË–<±%ËB(ÀBøYY ›¾4_}û;„úÝ×· µY%Bì-O !ÒŸ!õ;woÿâ’»¡àݱ!Ýx•Š+ ŒñczμnåïÇœ&`š¹´îÕ/nºøîö2B?ûãу¤I1)8$!B¦Dréàü1Ïmu_'¹åKfýÞè„ãR ÄÎ!MªÄ(4l\0ù‘ÞÇ_þéîAƒ¨ÈŽ49„K“c õÀë -OUç9WHe8$5B©•²nݺuëÖÕšîÎŰ+¶BYªˆuhÕZ2»}…©ç¶|üYNç“ë*¨,ª'aÅsog×ýïº+µ'†áë ‘ÆFDÍÄ멬dgiÑÜÏêvê"SpÜÖ „]«osîYÇ_÷ê%Ï—ß4äèö¼F ðûú¾ýÃ÷KXfâ3,ƒ=!£e¿­/^þÁúÕ¨ùòáù4PfFf/F)¥&exz™1m– «ýCÖ’ !¦aðfBWÚ-.‰ÍIç#ø£GZY›súŸþÕ¼3(»ihÛZ忏I°<°~Ã? ¥-°#å›®B59f-¶°¡+!B,ƒ&Ïܖݱ̺‹^ì{ùøwo õ›4¨Aòõ“ÈÁƒì.V•@ˆÍºÑœˆ'¦ 1MÊLƒ"Åþ#§ ´ZÎŒQyÏÜnY•¦ƒ¶ÃþW8~áÏëw iݶž»t÷¾7®ž±³ÁÊ{òÓ·BU !öìÛòç¶çœuüÕEß ßsN»¶õ]e;Kæ/ølÊF÷Ëç¤@ˆCø}B´¬·7§w}S>£G–!©9äô›?ºt`û^…udiûKö.œ·*¿ýq5„Ji¥8¤B„8R+—P#Gެ5Ý)**:‚—P ëBƒ߸0+++ †ÃáììlîÄ-óvîõÛ…Ì(*>{bSy÷‡1ÖýŠÖ7ß¹–Ó!¡+€¨*ê9ðoZ™-ÎÎÍìv|óyc›[6…s€iZõï×ħϛÿú×÷Ü»xãÎv¹Ú´m4ìì>£›O|ä7vÒ v„¤æé#šñöwÏOÙ]ì§¹ùÙ'žØzÞCĚƾJ‡C’!„UžCR Ä‘Z,kü¬ôâ˜.§Ùyöøˆ›²„$rüÀLÊ †(Ÿ,™;€5#Öf`Œ±ìÆÇ­MŠ‹‹htE€‚f(°æ ÉÏÏ÷••‹Í¬P(D¢õ*Á‹…¦cŒuQlÞ”ˆbÅ=|dÏá#{FhŽìÅiW£yÌ3¥Æ#†0Æ¿-ºDQ"Ô\\\œ•••››6 îö b ¦€Lˆ%¢D1„0ÆÜå“0²ñ­K‰ªê&Û[²›’‘‘‘••ðùEÄ5Ÿ 97Oˆ„•žÀ+®*//ù+Šb”‰âÀb›) ½MRœÝmÀÙÝ,7¤¯fµ#dӻ㘠!€(ŠÈaŒA|6Hªûˆš‘!"XžÒäö‚{{”Œ%£Îô™çE³#00AÆ?ß»Ê0 ¹/77—GòÛbÉ̉Âcˆ²µó/9Ó©„KGóWKFb‘x+<ù6/sàÀB0¹çñÁÏ|«(!–U !Š–såØ>£Ç0`|=Q¹m €MïŽ-//¯>‡Õ{Ùèÿ]zÝ·càÅËÖ—™­´¤IÈ!_ÍèoAHN“.ß¿ˆ"$5‡´ìrô#]ÚÆªÑ1#¶6­*‡$CHe9$BœEFí– 68K¨Ã` eRj˜á`Èårqו(FXWÅårBTUšM(òºÝÌ4!`P02™ŠØ¡PÆ8KSS‰î¹pUŒ¨*¥ ëzVVÛEá; &Œ1¢©£ü_Ĩ ÌëqÂ!0 j€è¦•ˆO1c&@2"i¸™aP„C,Dx ¾“E¦”ò„3@ìƒÌ€‘h.™HT cDÕÂá°Ëåò(Ïp{¦n„L—ª1ÆLjjŠÆçKŒ1cÔ¥ªÈ0‰¢êzH×uEÑÆÔ0°K¥@ÂX7MÀ˜Bš¢1‚˜¢(º®s7X¾Ft¹\ü”––Œù¢'ÒeÄx6 †``†i ÄLSLÂzØãñ˜aCUݦÉô ¡e¸¸…FQˆišÑad ª*_{©ªJ¹ÝS«%æ_EcæºÏÖfÖoï 俉âÉõžŽ½ZÝå±nm© BœEFí–¶mÛ:ƒðï/¡˜‘êˆbÃ>^ybŒ1în©ïB1Êé!aŒ£ÿòØ“˜o¥¼<Ƙ±ÐdîóÂõB†Rˆ‚0ç&9¦7¡ýl~öî0Ûî†%‹ˆê ‘f˜Àd1ˆj{,²GeÆÔ{àΪ–æQ`‘º&ѽJ)‰y‚2‹›HÜÞVTÙ²ˆh§Ü-Vª}ÆÛ!|‹,TŠf ¥w²Té:LrôY³òÜwo;€ƒÿ&Bêw=ñÛYíÊý>‡C*…G+”c…:tyâO;)ÇùKÊ~ LT*MìcŽ¢×”SDJ¿X“‚t# !„§èÄ©aÄ0Šß…$Œi ;vœwm|‘5XŒ€(׊!J•N‹0Ù7L¦ãØü'jÈC‚LŒòô€¥=9ô âÝQù¥p¼¶\ÆÒ`îf+ŠÀ$› ÿ]„lXryYYYV†âó…„8q8$}„8‹ Ç åÈ!µBA|UW;&PÂ$6áZ^]‹JD)å9ýä€äHf[Õ3‘1E.ìÉ*ÖÅŸIò2Ûé^f@ SHì‹P$‘O‚‘A”YJÌ÷B ’,.c YsÏ%‰^Žº»RJ1òǨ Ô(;[ËÆYLÒ‰ ÛbOÐAˆƒ!µ!Ž8V(Ç UãK({Þ™„‘õ]DZáX½„P¬RµU¥` I» "–‡—ˆŠ/§@böÊÄÅe!ŠKÏõÆIO$ÌCáä‰a† ˜ÔªA⨞;½ÆØ6J‰båQE1ˆ${öøÒL˳5bƒBÌbEˆåÙ³çU²<‘„ûöú.B„89Bâˆc…r¤f—P–ܸöf¹iôxœ¬¿1ÍÛæ4já Ê")‚#]ÀŒE5xÌQnb§‘R ±+0ÙN¢¤+‘«'6ÁÈ1Ìñ)øD@ù{u‚¥ñIöx$íáwA6±lŽˆªò!©Ä“ý9/;qâ äHDˆ#Žªú²eó^èÛï$Ç •j#O~ëdú³KωDî ‚©!"+Ñ*Ri'Iw´kÉ ×‘Ɉ,R«_ÂÓâë`¿ˆð •ù·Â˜„‰$>VIE2·˜¹Ž‚˜×¶$qN˜¼XÅD¸÷2«·…dFd?M&|@|G’×árâ äÐ#„RЙŠQÓÔPØAHRkÄëTt¶×Ë«ÔEªsúáÖC`…âö'¾„ª¹{ñV(™ 5McŒ·ÛmɃ)Ihš£BÊxTK8µ„S' z(ÑÄ- QTU …tàE£t]w¹\Œ1EQ€2^)Ý4M¹ˆl$v&žÂ¸I?âK ‘Bžº®cŒ¢Šè¡(éc‘¢cˆ¯è‰Ä80Æ…³¿a™™™ÊË5M£ÔàÌO Ó£¹˜aºÝ®}ûüÌ03=^>\`@UUƒ«ìªjF8b0!̤ ™HQ(c”1^ÞÐuÕ¥†€Ò®-<¿‹¢(”Ò`0èñx0Æ<¿o³a!„2tƒ—€P5­¬¬Ìëõ"„¨iƒAUQøPÊÖu]Ô‹ ”º\.± a†<ÒÜ‘ÕdB„:„ÂAVÇÄÙ˜`F³4àgÉPö;©Bj“&«ŸƒØ±:Ì­PŽÃUºV¨–gFj\oZ>F(p”Rj†æ­žÿÕÎm¥FÝÆu/ÑýŠî¹–+¤IXãÂîx!4HñþÛc’-½•#QG"a±‘4ÅReÝ~.àž¹Gæ'ÎÑ”Rï‚bQ¿T{á&ôKŒ Q±UKfÑw±mÁ§"UUVDp–iÒ„ÝáÓŒ$%Û „*/ÕB¡É"?!–ìö ³9q’BLPCÐÈåò¸#¨ ·©ùÍ:ÅAwµLÑþ[)¼d?÷—7.”Lmîs?ßþϳnãz_Ò낎Ȃg««vKBËw`²“ªvØ!¸~íÉ µù½q>Ÿ¯ãÐÙ–„u=»|öþ†/<:¼K“ŒÝïœ1u弿/jæ²Ð_ÂøšµÙRØÙsÆDÍbQF@ Â|W²À)IY­!fÑ`jñcÀ,é„$õŸ>-# å6sYáCaÄPuŒ1f8¢¤’Hò¼èÝ£») GRÐXxeGW»L$‹7!Þ9Œ1÷?Å :¯8+ ­æ1BÈN¼rÛxè“!òÅåx!B*…Ê ˆ¹Ý^Ë¥( ¦‡ `4ÆaMsï,GÍÝþˆ­ê¿_ŠÎcŒuºè BÞrÑK{=~ç™Ç¶Ì=Pr`æÌwßÌï3¸@¼U­û–œøÆëõ®šq×=S^]óÛêÊíÚûÜgf=Ö9Kµ\aÏEÿ;ó¦S\ðôè“SŸ²rêmwLyý×­ûòŽêpÁu<2¦7„|Y¯õ {wÅñqí‰7Nùæ Ž¼êÖyfSql-Í–+TšÎLUöyªéëK(‹bÇ_{Î}W—/:ò_ IDAT=7ýŒÎn (¿AÁuןÚwâÖ '·“ÒÜ%ÖÕ¸R(ª$+cžÌ!û¥Ê?Éú·=LŠi z/k¥t{cýñ’¥qÌG)³8—Ä3¦hÃqʨ½"˜t"K˜œP œ)‘2Ê5Wdš&VÆÀ´»ªðíBˆØF±Ôº—ó÷¤‰AЖÐ*¾ë!öMHÔ ÇAˆƒ40s—¦©ŠË¥)ŠBMÊLªó%B!MÓþÞhÕà?‡û’÷¾ÏL}e`K¦+˜ÔmTÿÆ[ÿwêÛÝÞ0Åšø?"g?¶núÔ…}Ž=š•o›{ïðAƒgýµr¬|ÀK'ýoôw.øáŠ“¦>eóâÑÃÞòÒ¢Ugvm²}í»c‡œ;¦þ÷ÓÎn¦e÷èþãµÝþ‘õ¼¡ý+gý2íâ²GŽÏÒÊwLûË3¸G¶–fKj %;0¥88ÍÃÁõx+HÙ„å?UU¾Ò€¤c(e¥[6PÚFެ¶¿ä2oÚ³ñZ¶u,^±B‘•ÇÈÕ3åÌ¿œÅhܼµv`K …^Ež:l/unÑq£¦iPŒ@!D!„»SÄ3í‰a¸w…Ȧc¯èŒ’ää‘5lÄQX“†ÁÈRJ‰ª(Š"zËÊD…WH’Ù/aBEA¢É"êŠ„È ·Å…ÖAˆƒ4bRÐY¦Š1Æ$b²‰Aeüò…´½û˲¼Ú !‘1”B)8!¼ÿï?Vm ²6ÉÔ_Xà¨ÓìŠÇ^»¹~o€ØÂåóǘ^Ѓ>ÙŽûŸMP>˜¯Zøäçneê%âÏ÷ ½¢õ·_Ïo¨átNy£Äÿ[‡:â§¼7ûKÚL€ö×õÙ0r%Œj³dòO_øÕÄϡ߈ù³6õy»}:-©9+Ô'µ!/”œo7¶Ã}O¿î¬^ùòæÛþ]ªç5Èxf!úñ[\R¬ŸP­Þ’wÄGž J©a˜é”2„€Rs¸6)åÖ¨Jæ4?œ%›¦ÉÀd`rⳟÛÕ]ˆæÊ:ãæ¡Ûg|rÛËþÞoÔiPpÎ9'¡5+å%T$¼ÑIŽí×ßûâĹ«®»¥_³j^*§õlˉügLÚÂ~<ûÉã'ô)ó÷Ân´±uÎ!ëNMGäõ8©|¹ú½ÿ8l*¶B%ü>欪¸F\Ôã²+=<|úŸß¿x=£ad …0ßéO!‚ 6.¹ 0A™& ƒøLÓt©J$–ÿ²ÜÜì={öx2¼^¯·ÌïËÊÊ¢ŒƒaMSZõÒú%—„aÅ¥y4×î=%¹9yº®{<žGzB( „ qeíM„P»³6,½!Ä`@ ‚‰a„]×C`NNŽ¿¼Üãñø|>EQ4MÓu]%Jyy™KQÝn·¯¼¼¼¼üÄÑïü¾p$ß2„Cn·›¯b”™fÄž‡0ƪBT%l˜!MÓôP( y½^aŒqëS¿™{nnv¶ËåÒu"„ìܹ³ /O×uŒ˜ªª;vì¨S§ŽÛë)óû23²}>¦ªª×ëÕ©Iu0n3pæ7¯žW'7/¹\®p8Œ1(˜ðo±äUU à”¢ŠÔAŠ¢Pj@ëÓÿXv%0*Q|>ŸßïÏËË …BŠ¢B·Ûmšf(òx"9PZŠòddx½Þæý^ظüJD°Õ'º%(-eŒº\.·Û !ÏûË‚‘é ëTO†Ö¦ÿþÎé D@~"„´8kó{ãÒAH(®ß n2„}nѯ¯H!ååÂáp2„´^ô×[£ÒAˆ¢h%{÷$CH§sæü²è’t{Á!¤í Y?-¸(„P`¦i"‚ýaì3뫪É @)}jÎ7W?Æçó¦Á·±|Ðø¡MÚ5Ë®‡t>ï¯åW¤ƒÔrtÿ©ëßBRsHáˆy ëºaÔŒ3ücŒy&f h|±aÌ¢¯q]ti¯óFDâÛýÝ+™™ sŒ0ÔÚ¼<o š­Ü‘5b äí4O¬ßsì×+³{÷évà¹U o_áñà ¼O­ß÷@§ˆ!ªtý“Þ‚á‘Vóoj¸ý­ëÕæ·6ÌhxsãÒÛ—Üâ>ê–|õÐÿêý÷V@³æu+TbáÜÁ£B\.—0Aq=c¬ë:ÿ•RjƧs·¶î× L0MÆ0†˜ ŒE²ÔHž”2fº<c¦ÉGÜ\ÀåRù\ÅW`&ƒ°a*Qx%ÔÒÒ9¹uBA6Lf0JT­<à¢hDUs&˜(QÀÈÐ D0VH(2¨©iwØ D8+Bˆ M×uP0AqSTE…UUE€ôPc …B¦i¬"ŠÅTgºi2áP(lR¶gï^0 ^!Ê|ÊL"ˆ†#À¡P˜ézn<Â¥”R—Çã+„)#(00( é¦ê€•` ˜‘©¸\.EQ|þ2‚Àëq¹4L©6¨IÁ#Uõhša&“²°nº½(ªŠb) d˜¦ŠU¬¨ P“2“1†(£TUE›À5(`EQQ0Æ&‹Mü_ BxÖŸÉÌÈ…B!i!$ qe<BÒEˆKs5)B M„0ÆUI†H! 6LÈ‚2 „˜,B@Up:a(B€23M„œØ’ORj„Q˜ † Ó¤boK× Ý0#ª3“RÊX™ÏWÇmT–C l¦…ÔÂ?§ƒÔ¡Ä4Â9R#déóZõ;łں„º£KÁ…·Îzãþ‹šdÂ߯ºìU•X~u¾àÓ¯sÎìyêøËŸ»â„ÔßøøàãÏÙmÑ ýŽi²mí{ㆾ8äéïįg^Ýö„«?ìöÔ£ÐB‡ãÆ}tü¤I‡rjÚ ÅíO| õ_®ÇW±;y|Ò°gþÄw× lÑ£}†oO颅_>[\ÿsc˜E\J@òØœf˜U”Žˆ‚Pœ FFꚥÌd”RÊˆŠ±"Ü-!yuñ§uŸQÔ§LLð\%„†aPÊLJ¥¼Æ"`Û2\-gÀ„þ¾A¦i¢òÜ3$šÙ„H‘41^¥ÔŒ¸—R`È4uf&Õ5ŒÂ,r¥"­–z*u“RjJ~¾€åÅ>øôÀÓ\òÖš<žÅ–Pv„X²YÉ…‹àùŠ"—©&B(0”!T!&BäŒv„ð”B"c› !i"„¥DHôQ¦…dbɇž!‚CAö…u"ÀÅ£¦i”gO2t“°@¦G­,BÒEHj±›ê«Æ!bL*Dˆð¾· dð¤¯ï¼ °Y&Õ÷ì[²ä›gw7xë¦<ÐC2Bj«Œ^úö†Ë'ô8ú–Ò9ªÝq#oX´øÊÓÒ?=»Å€~X8¤{ÿ‹J_Ÿ{Óé)Žl>tÆü]·Þqá©çó¤·½9éìØàQCF™×=~`Sh:ðjsÜ——9êPŽÃ¡±Bqû““<õ^ã{7üÏVý§ÀŸ+Æò—ü¾n®‡žýhÜŽPVAö)=Ú,y²C®’ƒDø4(&ËÔ;†b»ÄN¾ §1ûô&2‹¼‚2÷‰¥Ôµæ›\¼ar >Ê Œ0 Š ¨™˜`Œ£¼Jaˆ2œ°ŠÄ¥ç”›º(o ïflž3M~…1rX{”k© +Kï ~ ˆDi¡èfA²µ…å –j|:±øÀ¥Fˆ5©  !(”/á“•saÛ"pRM„ÈŽ)©BI¨kËá‚ûÎ~ „$´J!D溙á¿JÊ5Í„˜nzÔÊвòòzY4'+lažésHj„‰6»b„^ôfÄgÔBز»­6yP±É(e&Ï3`÷b(Fˆÿ›8c>„aÉs–P‚ŠìpQŒ‹^ „Ä‘{J„(§@ÇO:‘wvìIGÒAˆ0UˆnãI†n«¨>B š€ „˜)§‹HŽˆÏo^Yñ¸”f ²Àçówl• h išÂ7æªÇ!©rh8$úSÅ©‡8âX¡©ñ%¯¥ÅyD¼ööZZv2Jóöò5e]*5=Ù6í•ä!¾F„pŒ¨Ôd)ŽÇ󚲇)‚0íFûÔ&=ᔆ¡L)qszºp#i …(¥¢(‡ð–ç!»U!„ÅŒ#ücµ;п‚{!³*#Dn¤!PÉÂÉ"¶Ï*DJ^†6æ3Tm„ðëT!Ì5ûGˆÅú•!‡ŒC yùȃÅ!ÎäçX¡+T/¡EÑu=‹0Ùå(!åñ´{º®cUAÑheóX yŒ±‚°IMYCâú™ÈñÈ …B„UU9ã„B¦iº\®òòò¬¬,3Én‡e/(îö¡(Šø3geeÉ2— “ œ°þ¼(nï÷û½^/ƘWø"Àöîßçõz~_VVýp8èreûýþŒŒ îÈ}B¡PÄÏB!̤Œ1ŸÏ‡1ÎÌÌô‚¼ –až /ŸoøO”Òp8ìv»!ê9!¦gžòÇår…Ëý¦a*Š‹›Œ„ “2D!Äs-òéM×uÆLB®‡¢Í;oÆSc”áüN!XÕÃAÇ"ò¸sLuyî!„×S¼!bMP!BøNV2„D ¢ÕF·ú¤ƒJ©¦iɼÈ| HˆÞÂt‚xPH„ÄmW„€¤IhÑ©‡fBÒçÔIÍ!¼mÕç~J:IŸCìqµ[Î~…3ÿþ*¡†‰ x>CʆB1„M`‰[õb‹Ú'+»B”+·[tz‘YÛâÃ!Ô5áÖÂÒ` Û[ŒÍ¨„*'Y» ‹¦æº#!„g%6 ƒ"H˜ú%Q…K Šn¡ˆùCö•·–,}A¢”Ó}¤‘È21 ŒÀ ŒRJ0 ‚‚¥†luù5 „Ø‹vsH:±¸¿X’Bõ· Dy«BÄLŸ!|ýQ}„€©Z=„ÀAAˆ}yQ5© uj„¤Ï!©’>‡T!¢"¤:âHm•¢¢¢ÚÔ#x eÉjh÷쎙€ZÌÝ”^¯Ã’NøN Oa9‹ ] sÙS×`…Èî™â0Œ±8Wdò…ä‘5²Ûµ}¯Á/ß”àHLBÈ`)‘{™@ئ"„0æJ-‰Š®ë,~s§ÂýnQˆ8F€¼V£””;§0`†ÉýjŽºÐX¦ŸÈ€3Æ€™ÀH$Ç@ÔdÀ"!ˆD™‹ŒoX4•²ùAGˆ˜öª9¯£!` §ªi„D‚³’ „Ï‘ÕGH|ËS!1”!ܰ”.B¢KòšCˆ°>V!ü:é äÐpHä ¦êpˆ#µx u˜/;j“àt–PòF†Ø¼·(Ör’A$‘o„Ð å©K¨Âr>@ÎrhŒœ—ÒBX ‰,–EQäå$‰”‘é/¡‡©=艢i·ÉóEQ@ró‚h&q#ÎËü0ˆÃÙüÄñ"²ÆÎø"÷R¤d˜ÔrYyKؼÍÌd@ìÉ?-áèL„@:±Kì¨÷O…±„SYbQÓS Ä.UCˆ˜"DܺB„Ø_d„@|Tf•bYîT!¢ Õä±0ª!©9$Ùz¨²ñnòUFˆÌ©’>‡Tʽ숓_AšTh™#J5L (Ê0 Ä(ƒhy,9·oBë´=?¡¦iÁ`P(”×éXS‘uªH¨(‹ï°Nvkž 3Ѝ !UUMÝàËS„ÏÒ‚†MjªDŠ¢¨ªÊ9ŽRÊYBÐ#í·zÒªàÒ˜ó4?À«d`9“8P Œ™Ê‰V÷@|×@åGs¿ jr‚‘È:,š’‚lª BâöL“#+Q<$AHäô4’`„%„ðé ľ“h’O!!H†1‰V!ö.'CÂV„ì-7>þ¾d{IxëNÿ)§œrÍ¿7©§5Ê'{6Ìñ¢ûy!sm/oh’l?s¿3¯×_zÈUêÓýÅÍp¹G­"‡lX|y(J!ésHj„¤Ï!©’šC$ý¶„T“Cj‡ìßðÜ©ã=÷Ö»CNlö÷š%#Ï>5«óW·ÉqfwGþ}+”}%'–U:y×/E®Ü2会r*ˆÅ„3Ë5e¥âk2$\B‰[ËqR„(‹+‹­»‡¼\à>ÑÜd‰o⽓Ý/¸Ì?sSw)ådå˜ßIxkÙßÂî’/ü'ì ·%õ¨4æØÂïvWÙ É·²±"DÄ.%CˆUFˆ|÷Ô‘KV!ü'C¿]õ"lú). ÍXZüðœí_ýÜV°âñz½ k[vÓÏ~ \ÿì†'çÿµ{_°B„„Lu§ÞÖŸÝWÉíàÎnšW§n¼Ü¼¼|5£‘’ÓaÃN?ýSׯÕá rè9¤š6¶Ô©‡Ôš9lùØ'N~ñó{´q)®Ö݇͛zòcW$<ò·%Ï 8©SANVã6'Ü=ë þåmk®rJ£‚ÜÌœºÝ\ùc™.LM«¦ÞÖ½C³œ¬œ£:œtï+ßÊ&(oT¥Ä7^¯÷Ý'ÆwiÙ03#ƒóË¢ÇûžÐ./;»A³N£îœåÉ–ýõÞåƒNiR¯NVnA§“ú?ñæ÷Îꤖ,¡êR ûqö|[&»ÂÇ#GìK(a¶çáz¹˜d_rK« >%#/Ÿž¬_(¥eÍ^ª‚1$—Âå3ˆFœQ-‰Jw ŽÊFBަí5wqÔC"J¸&Æ`qGµŸ•p®âÕg#—ˆgó‹þ30T!öã"Ä>AZ"oU!$°?Ù6M2„@\~ÈT …3e5"¯*R#Dô÷ÇM¾GçïÞ´ {½ÞŒ¨x<·Û­ªªªªš¦ýºU¿{ÆÆ¯.±#„F²?œUŒNtç¶ÊÊÊÈÈðfdx½^Ûíri.MÓ\.-+Ó‹2šþ²·õß{p•9¤B„¤æˆ°;ˆ’!©9DÞÀMêpH­‘é¿•N8½‘ø³áiöý:Ã~ØÎOï=e좑“æo-Þ÷ã»Ó<ßÜÅ¿ïpÖ½ožþû?{Jwn¸©ûÖsÎ{Sœ2lÒOw}R¼¯øÓ¢»ÖÜ×ÿƶC´‹?*6oüª‚ßl,÷ù`×ç÷ö}píMÓ–íØ»o×󚯬Ïí‘•Üè^f½wí¦¥»·.~·Ç;«“Ú°‘gL$QoÑM%†c`FþC °Xåö× Êc`ò¹„ÏÙ j¼cDŒx1yU‚‚ÁÀ­Ž'š£Ir"ó¢å‚[B¦n0“&Ë^#Vrq(p,m6Ÿ{"Š)ÏàÇ"(DÆ„¨DÕ†a^)‹`D0ÆŒ‚I©aRÐ ¬*&DËšš”¡X–‘âŦßS1˜E aÀˆ± ó»GkŽñ`fS MLæ&``Ì[9Œ!©*Æ›¥”FÔ\©5‘°¬JeÀ›^B0Jþ}õi"$fœH„þG:1uƒ¹’"Â!‘ÒB€ï7xùýýn·Ûëq»ÝnEQ¸ùŠç&7Ú ƒ=9ïÏë(ëÖ©®!PÊ*ÓŽÍÌðºÝ.·KS2L3ÖC8À¥&Q4•ffælØCÝÞº!N‡C(…0#:ÕÂ,LTˆÔ5À!©’šCÄ¥þŸ½7“«*ÓÇß³Ü{kï½;}!„5!È&P‘\•Q]tPG\Æ¿ŽÃˆ¢‚€€" ˆ,‚£EQp "[‘„l¤÷®®º÷ží÷Ç©:}êÞªêê%üÓç£|:U·NÝå©÷¼ç}Ÿ÷yÇEÈTlÈf û[><8;vÓÜÌAaþéøaWwÃ9«ŸýÀíZ|àçoxD¿¾ùé_”i}Ïe?>·ûh€ê_´úG'ì× <áG÷_´÷©W]ùÒ=½oÜúÙ¥mIý÷5çÞð_¬gwsöûÂïúö¢ ákÀïýûßsT{Ö€¥ozÇå·½cÆ;y#D¡˜ˆÐ `Zà7˜ãx—L* IÎc %çLθÏXÈ9SJ*%„âL„¡ã¥ãHY,äãN¹5¦—L*£Å"u7‘9Sú÷±PR!”ʤÁ\¡8" ±Ô4L/áR#)8`@JH%$RB°Ð¡$B(ôƒL*…„Œ)!â"D¤Bú%ùb…/Á¥6ÄX‚¶WT”FZîH.ãŽãÇ˶¶Œäi29„€iÀ„Pa¡ÐVX2R± `~À9-½d QÚ74¬e\º^’3©$…%SH"Œ©¾X×óBÆ ™L–W2® Zê& CLÆe2• ™r=Oa2ê“™´A(òƒ‚ã# áPŒ &A‚)ADÉ%ÅBAoü¹˜8˜8R!)€…‚³€` ñaŒ¥€ ¤‚П Bt d\„„œ‡œÕA4Š©ê D—ªB a„Bê D!¤B A„(Î >úѯú<ÏK&“™ò0!(×u)¥¦ˆ!äºîwïýÇ΂’3B÷K§’Éd"“Ne3™\6“ɤҩd2á¹®Sž§Ô¼/—Í<¿½¥o8¬oC¨C/½qÛ€š¹<‹» òtÑŽÑ”ÏØ¤mˆv—AH} "¤¾ )9p ¤qGÈÿµ¥î–mùË–·Æ_/ôüîüSŽœÛÙ’J¥2MóxñeóÖ'÷j6·,ûôèöMâ{OhMš¿°-ÿñ=ge³Yý›jê8Œ>£ßºþìƒÞûÙrf IDAT~òßnºýç/ôf\“7NJï¥{~å¥ÕØlJdÇ×®~âágz·ðd6}ÀŠùçŸ>¡#Ò±rzˆ`%EI\®DbUÒbN"„ŒF¯Ù"i¦†ÒÕ4J9 {R”ê«%¨ª•&zÙ6ìó¢T@Â¥"ÐQ­¨Ã0š=PÚÀé˜<2uÎQJB‘¬J²™R!…ÊÄìhF*)%‰¤*óeõÚC%ý?(÷ÜEæBpu¡p+ÍQŽ–iÒ:¡ˆP…‘ežM©X]KÚ@©ð[*ÝèC霌‘ÂM"”‰ð•}!¤BH…a¨i½RÊb±8<<ÜÑÙi0lWÒE2)J)Më4„ „@_H „”r:SFÀâ8N-„¥´„`U!úÛ_K„ ¬îùÓ4•ò´Ï”H$ +K)Å9×R™Æ…B1I¾sç‹W|âƒBHOa¾×”v]'áy©d2™ô(¡RIÝe2FÖMd.TL¤r>·óÄ5"$âÝ›2é$Æ”’Žã¼y[Á릊IØ8‹kr6Ä&0ÕGH}bÛÞú9ì£÷–6gÛ G{¯¼ñ/÷?Ù³#ÏSÙôò^rî‹éø=’wDZ"ãþe$|k“§ÿæŸt3+j-hñ—¾ø¶3F.¸þ‰›Þ>»-GT1•i³Xc²Éžc}§PðäŽeÉ*ËîÉW=²æ#?øèŸŸ|ð–+>uÞAŸ¼çÇŸ[5ã ìöQ(èxåÁ‹×Ýw¾ÍbÑoýç%«ŸošsóU§¯]}î#W½ó˜Öþ‹¿òT’1m;ý·‘3°Sõº«—-ß§¼ŒÛ ¯V;T«ÇŽ“šm*"6V°Þ…G$…j5RÕk•],c¨¦ZJÇædTU͉_—ù^Ö5|}¶aêðƒib7”°‹¥MÇxÓÜ-"*a ™<”‘ä‰×|ÙÑ—oJè#L "Äœü.ETv­ƒ»ÓY!Pf‹}p-„è5~ê1ìŸqÒ7ÌŸß$µœ·&æd2#×_÷Ü+£O=¿Ý „)O¸Ýšïì8Ôq¨ž‡`‚Ç7²×&„¥$@­/¾Zˆ‹|"„aÍq½$¤“©„çy®ë8DË)¹^bËP’ñÉ ªÕâMцÔGȸ6$Bï«…'nyϺû/0®yâÿõéÕ϶.úî7N{üÇïäÚßÑÚwî¿>Yù»ï8ïæo?¼ÕüsÛo¿Ý²ÏùñÃÎêÎ|ýÙ¾øë7o¹ñ§ÌkÏ#›`¿õ­µƒæïµßJwY < $¬ÃZ¼Þ{¡ØûóZ§zΜ̿?´¹Ö» |ÇŸúüwø³gÖþü_;sÆ;y#¸P‘Ju{³«MÀ϶³+Þ¿hq[Â!4×’;ó#oíÝb>e¶ÝRJ\æÐH)ƒ 0šu¶ Q£±Û&Ø?þª,Ϊ¢çUµX FMJü«3[M2k\oÊ™Òe³ÊlVý©Ô0â dD+Ù¶§zBíéºÇlKæDZR€UfÎÊXÛ©Ò‰ý)Ji6›!vkU{¶Òa Ä4š"BléÅ© $RäAˆ9xŠ1Ÿ!q•¦É!ä'úì$]ÜØÓÚwƒRzûƒ/ù¡ÐÙ6ÜL)©¼çå1!Çi{! !”L$Á˜ŒÛ<Ë9Ôu ëÿ¶îŠýâ úÖ=/ýv]!@Žã¾ºSí׆ÄmÚ„lÈ϶³ëÎÞwQ«Gjjk>ã¬cFw¬ïißã¸ë?ý‡‹N¿ó‰—B®ÿߟžqá.½þ¸øa—ÜxÞ'ž~×^ð™èßøÌ×.z»~ý¤¶ä¥?|¬ÈÅŽu]tüWì\â‡X³‘K¾qÍÿtÂug\s‰~ýЬû½§6›göùíúìM¯%/®ûóç¾ó¢Z§úÉ[?õ›s¿úg,rVþûïûÔûÑo½é´ßó»5CE&‚á'ºÏk>bÆ;yƒ¸P‘uËà#„>{`ú³w¿²q)€üàÈ?~¤kÿ½#V)PBšZÎy±X­ÄÙäibD¤<ʦgZ•MØ^EÌ’c¬¼Y°ãZvµjzÍž5ÒbƒÚöÙk‰­*Y˶ڻy»ô¦ê߈UïÇ #Ê„PCXÏÊXŠAJ8ã‹'ÿßqß“úàììùw~y>,²Xê …’¥î]A$×qlmµÍ²Ñ›Žç,âmgjE¡ª^ˆ‚JE"eQI0Ò-Ní¤’RŠXý³"yL÷¨Z%³¹cúvQJõjDÖ`-.j Ž”R + ããúIÇVg¦–¯cD™m*¨l—f’k¶*’IëHSs–JbLt¨À~Xñ„K!vÒ Œ@B5è:‰øOSAH<ÆP$ã!Ä䆦ˆ{QŒ#¤” ™2B*nr]„¼²µ$¡o¬&<™¶zœó0 #*ØvDª§¿¸sÀ_ºB£ç¦•‚3„!BÀ9„¤!c¾AÈ8Ó^”öŸd©•Œ qï`ÐÙêÚa’ê¶Š\p8ò½û.N…‚‹æ¶æÓŽi¿öáo=u–E22„š³d!¤¾ )Í3e„ÄÓ‹õmHé` !ï¿ìäÇþù§§Ü–Íò‚Ÿ}{O P£¿Íî>ö=ýsþ¹qÛç´K:íÒ¨¶ï>u†ù畟£r¿íÂÿþß ÿ;>Ïžg~í™3¿fþéæV\}÷#W[|þÌÒ$qÕƒùo;뎷ŸsïcϹýØsf<’7š U'Þ«m߯¿uÿÚ9{ÞûåËçf6ï¸é{Ÿÿ½m·´=²åÒ¿sÓA]=LFåÅuñq×OËõìyÒ÷§ežÅÇ^;-óìñî[¦ežÃþéîi™çЬž–yö:ùæé¹?ÇozîÏGî¦ç5=×µôÔLÏù÷Ýéù]¼§¡¶£‡vX*5æ?iÍ¡’(‘‘2±#;åâC—•X wÜ|•‚s0¦='Bˆþƒq†ÌÄ¢t JH!Ë“r^ñ„žçåûÎ)ÛP 8JJ8,% _ëž»¹æ¿ e§JIò1°Eïjôîísê­Óó¼N˜;•ú·F‚0%B)…ë…•Ž7&÷WW­~aÞ¾·]¶xq+£Á­ßÿÍÙWm¼ë‚vÛóžYüfÆÌx-\¨Z»1ýóþò‡¿wëʽ3.VÐ>»ãÒÏsãÀg…ftÙh+ìê¶ pefgÝ}çrÎGFF”RÙlVoãÒé4¥´¯¯Ïó¼l:524ÜÒ”J§ÓÔñòù|*›ñ}ŸRª”Úû”[ÖþâœÁþþ\.—J¥¶öô´t´1Æ®'CÆCæQ‡+©P7! „FXRJ—{!‚•R{žpÃK\È8×§%H)EnÎdÃ0d~@=·PÍä²aRJ㌱\.Ç9‚`Ó¦MÇæ/ß{–¾Waæóù¦¦V.e2ž3<2’Ëå8c’‹=Û3©t6fB¸® æB¤R)Œñ¾§ÜôÄß›J¥šššüÂ(c ƒlomËçóIÏA »ÉD®µq.K$…ü°®Ó— ¥\~úÝOÞvJ®¹5ŸÏ{‰”RÊsÝ¡¡¡l®I)Eˆ£”ÂÄÑž.¥4ô!D*PJñ¹®ËX€1^rü /ß~iM¨”rçöJ©þþþŽŽŽ|>ŸÉ¤›²YJéèè¨&&#¥”`}½Å Lç²+?tÏú_žÏÅa<(ú©D¢8:Ú¿³7›É$’Iä:²3¨…½O½ùO·¾»„¤’iß÷k!dÙ©7¿|ïÙ D¯gµ²òŒŸ¬½÷¬F2ÎÜD"Q !KÞuÝú‡.n!‚óÑÑÑZyÓ‡ïyá®4‚K®Ù¬N&.e‡sxyØ8³¡DÝøïǶ¼+tÿ¼Ùç\`Ì@IÉ9Å R^3¦ÿÏ9B‡¢4GŠsÁ•?hÅÒ¦¶öfcC¤çŒ)¨ „ @Z@‹ Á9ãŒëÃÇYÿÀØåïÿɳ÷þS#©oCö<þúu÷ßBêÛ>tÄZÜØùô1Õ:KÞÞî~剑[ï:¸3Ìs!²­ÿü™cðÁà‚"9Á™13fÆGCêäZ`Æltt`ßó¼RçwTÚ !¤È.ÑI¢0 •RétZ¯®ëj£ËßL¤ºP($“Ió-‰DB[}°ŽÉ&±*¥ …‚骷kŒ± Ì̺þˆ1f2V6‘Ó\šÙpëÇ1UÜ´æ:BJ7¡l1õÉcL' ÍSSwƈC¨0 ‰„©hK$ù|^Ÿ|Úê•LŸÛèè(‹E„P†ú« ÙÂqœ R©”¾"J©þ¬ž_)¥—+}d)§FˆV[–Rú¾oÚr^R ÃPký·¾›{aç× B\×"¤Ì¥‹ÌnׯEˆA®Š(7ß!Ú;¬…°Huõ¢Uª§ŽÆX„è;ÖB<Ï›„ÌëtõUkÍ ŠÅ¢ïû¾_b1EQ¶ŒEW‹ö\êë#CÆü ,ýBÁ/Š…b±èûš¥3y%ŒsÁ¹¦L%(„`Û†$9:Z`Œët¿Û:$„\0Æóý=Ž—Ój´P ƒüDmˆN¸4‚ÆmÈkƒmCôÅÚ‘*‚E2³øÕ(ÏŒ™Ñh¼ZzÓŸSæâoþí¹ž¢ØÑ÷­+Ûµÿ¾åÜ>@¸ü •±+š-ÔÊÖj!o;Y×M%³M·Œ° LV6iÔaE8ö·Wp¶´@(\I Êæ–FX«Rv„•\‡[©Š$_âb,ãëwj!Äœ†Í”2ï¾®b{ó»BlJÍT2» ‹’Kõ¡)Ûå!­Á9oËQȦ] lÀÂñ0dAP"’Ëž˜™Ì„µŒó±BÑgÅAŒP6åØ6„Rì ¼þ¬yt˺~(ø@ßÐêG÷\ÙÄ8‚ËB*AwwùA‹ˆ!ä_V¤ÎÿÚŸ_Øî )û¶íüΕ¿îzÓ¡µ ;fÆÌ˜»*‘g~Ì{žT*Xô®k`ýè×Oúü)®}ô’ËîÝ:ÌSM™Ãß¼ì¶Óç!QÑIJ þB¹LÉnjVg%–V0ÒÂÌnké)f ¶òJE^²Ú÷ڄЈªSÕõ¦*u=^’±}ãò¤”`ë3Ŭ¶nCa¯6B¯,ÉĈõôçB•M»lwÇ6ÙÁZ>Mü»f°tQV‰_ã©*`aKF5ˆÞ~ $R·‹b»nõr›Û~êճÛs2þ–ïûG°GÂ+Ù“Åþ“[ò!I)&%Y'e4û‰sÁËîZ2ßú†öœC“؉#¤#å¿:˜Wɼk yâÏ›(H/åëàv`!nKK`ÎDmT–.N!0=±q^!{ŸT¢î}ò÷àwׯrâ¥'ì¼í/ŸýÒ}Û†y2—>äÐ¥w^´„ïì±2³øÍŒ™±Ë](ó‹]wßùRÊÑÑÑ–––|>?f&Hò¼óŽ:ÿ|”J¥@J¤Äðà@Gí‚)Ñ2¡ò’鯱FcabæP£“«¶w‘º›È*UªÆ/¯µRJŒk:põ¼K²EÛ³¸`LÕÈM©Å:(ÀH–Ô¡A€¢•]AËeÕ[ÆÐn,_U÷Òª*aPµn+Þ!Xon«–íTu¡"’6XEàñÍ·ýÏ:©ÕÌu‰ËöÄÛ»¾~bßöú±/a*éhv÷™‡_ÜÂ+87ÖÚä'íìê¬ß‚.·%—èh)%¡Òž¢¢§P¤ Ï#—]¨1?@H)…äšü¤ý§ É#[Ó³p[:÷-(Å]ÙÑM}üÜæ³À?©;å: Ĥô‹ÁðÈp{†%=‚)(B ,‰9.B^R' Aȳ÷K)ERI!†ƒBQ#„ºé‹.>ö#gF‹…T: ÷T"dfñ›3c—'òâ5ØõÕŸ‘[„Œý5j~&ÆPJ1”{»6…Šï†#²uæ;þ-:›€‰sÔ²}¶ÿa_¾Ýô¾–sP+Ì'4}àK%Ж$4TJ}*¥ µYÍ:4·#î@¥Ì•m²P²½TŒlý§‚Ȭ…Z2ªU£PSAˆ9™× !u±BHDÈq*ùÐ1X…æ¸M!7ÿÕ¯‡aÈÃâqGÌ€ùÝMûÍ. ô E?Ã0Ô%x!caÈBÆYÈK‡a†EßÉnݺeï9 æu¥«ÚLÍÎ lëÍŠ#ùѾÁÑá]¹0—¦ÝéIØ(kyLцÔñŸ&„q²iAÈÌâ73fÆkáBA¥Nn¤kD\H)¥DE:Ʀ!W•WŽd|LO°èØÆ(€¥RWгÙ!öÎ;®3n¼½*iÀޝhþuä€RñPl’1Vî«–”‹žYMÊ{\ 1ŠF­³¯4ÂjŠ„š"Ÿ5 ƒ}+"a¤úÖ|*‰G¡ª"$žŒ ÄN>N!ëfó !¡Îï‚Sç ›«$*‡y]sÿOZ5§%çÍîȤŽùÆ\ ïÙ¾sûÎÞÑÑB±A„a° daaaE?(ŠÃ#ù›¶v§²):»=í9¸– É¥…í"%¶ðá͸ØCÙŽVo¸» ·7'æte‘Õòh÷µ!µ&™^„Ì,~3cfìòDĈÌñßóX6¡6:’b3<Uc¥ œÞIÛ{¦H»+¨A^¶M¡B`aöš¸²u†`¯°2Õ¹(šuÂØ±·­icû’#4j¨ÖOF:aŒ¡,~Xõ4J­I+™.v¤*Þ³–÷S•eé¥U6ÇÈH“OBªFwª"$îÌÙ±of}„ij]{¬×;N3o!q.àä¢ç9bEGÏŽ¡Û³a7ÞѰ Â0ä¬xò[fí»G›CѲ­‘|ñ’nÚ;°ùåžÑ¦\‹ã:†¼¥y:…a~ttëÖm]©ÞE³s),[Ð<šªcC’×™!„4e²ŽçrŒ¨ë"„p%Š·!uÌÈÄÓfC š¨ÁTlH!3‹ß̘»Ü…²º¬½@–öd¥_)F ˆ¬£)4¶U¢ Œ©æiJFRDú¢’æi²G„¢Hÿ õ\(cô¹” ”D€0¦@¡Ü +¨¼™«½9ÃfÕ±¶€ °µ§ÇýG#ÖYËA—fˆÎSfºèOa¤ ½Ù=WØe@c¡÷è @!XaD1¢å G KP ° ë-TÍÀR©Q™J‰Rz\årÌM@ *ÏäR^TÆAÈX̬Bìüb}„ÄH!úqL!¥hS‘¨B¬yÆAˆ}+â…QCQX#ä]‡ww¶§o{à•ͽ~ª©ä÷}A—{Ü{æR”¼|i;¥8ŽCöÍázÖ¬ïqR]éTÒ„ µÿTôƒþAQܱÏ,žM%Jس“4Q2.BêÛú.Tã6d¼O£6Ävê#¤qGÈÌâ73fÆ.w¡ÁBÉy†¡nóà8%Á? )¥a,µe 9!NÒI(¥DÈU(¤G$&EÆS®'‚ÑÂH^…,•LSJ}bÏ)gm’X2‰Pzž`¦uP ùÉ9‘Š( ”rÅ …B6›¥IÁ0 аK¨Ï¸ž‡——…Âq< HÂ#‚¥”Þ+Å!¸¼s-•ƒ,Û´ic¤°BB€×uÈÀ÷R\ &FÄK¦$u=¡”‚ºnÏŽÔu`Ô÷3™L~` ä\«¹àHFÆ¥Ž¦µ:-Åä¥L$@g´Phjj ƒ@!J!Bâ8)D=K)÷’É èêŽ|Œ±ÂDH(!¦B&¤B °*—ã%Ø‚d2ÅE¨@*¬˜dŽãpÁ.-É> %Ëö°¾o‰I#A¡˜…œ T !Ð Bp]„@ÃÁu¿ÐB0ž„)ë dcáj !‡í×Ù–¥Ï®zâï;óbkoÁ„ë Î¯­É9lùâöÖ””²9í¾iŸÙžW„*ß·CönoIõ=½ö¹-âfû‡¦N3ž”áðÒ9nsÎ ÔÒ”8x¿¹© èOÔ†Œ‹ú6DÈDlž´ Ѿpp—"dfÌŒ™ñZ$òâÙ-vÒ›]„V „D\‚TÚ¬(BÁ8â’”ë"Qk4–0*uòB˜Btý‹@b.©j%•0 YÞÀ ŒÀÂWm¼Z}( H)J§*@I„’ ðØNWê¦R”R-Ù§æRF@ߢºÑ¾ÈùTío*%þ7˜*€"dß]½áDQÇ1ÝåLšÌ$Jì8“,}©fƒ;¶›¯ 3L!æÙÕGˆ*ßÕZ)m¸@H\?ÉFH颦Œh!„×!€n!„R!Kæ5/˜Ý¼ÇÜtÿûä×½îKïú‘)™M9sº²­IJq!ª’¦³xnss÷ °W·ÎÉŸùÖã×|îhŒ1c.¥4›r;çdfwdA Uã6dÉ{o}þî3AHã6¤>B^R2Í»!»éÐ}§¢{9õfÆÌ˜Œ eˆFѸJÔŠ…1/·ƒB€RHA˜sÎÂPA1Š+Úéå\O‹Çúq–ÒöºI‚N4aKÏ^¤m¦Bœ4mW£ÄÉ1×§D2k‘u»»»aØ­IǾ4VR1Ǧ™ƒS–Žb„1ö_UeZJK}OÇÒ#ŒKŒ zú•'âaŒkXïI"4áw<„ØuRUÓ‚¨F¯žBì{R!&±µK•§ub¨Í!AË6»n²§wX;C\ɤG›³^:åq.mµÏ:Ixt¿=š—ÌÍmé€ÝJ)F²«=—M'ŠÅâTlȸ©oC Rzãÿwb¾q—"äuî$•Ààx-]ó>ò„Ï]ñïµ&fì™±›¹P¶ýµÏPµüÇ2Lœs¬‰R)P”Rθ.¸Å˜TÕi44Xóû¶ ï1Æ\ )q¸eJÝBÃ_Ž3£ËÖªºEkÄêÙ.ÎU2ªƒÆ¬ë5FÛ¶Zœ­±(H¹_=Ä´•틵M¼ýŒ0 …¢>-ÄlSÝ.—=udÅ­êLBôùŒ‹)%ÁØ´‚‰#ÄDׯEH„AçļÆ1lå]ŠûL!£¶æ,šÛ$«!!ê8Ö@ˆç:]miX8;çºn†®K'mCÆBHã!¤¾ ‰8RS±!upÒ8Bì]å®CÈë|è(‘†¹õ’“?yÕãbÛžýÆÌ‚=3v×(”©5Ä˯”ɼ”wRJ¤RŠ"r!8·çWl¹+“]’• &½9Ö=øt[«H>²ƒŒ—ˆ‘RÊXÂÆÈØ†SJAU/áÑ]± ÜÎ6¥RPáù­¯PjW7ç[¢cA Pñƒ-MEP J@`Ót+.è-ëØÎ¸šÌ¸šBJ)¿ñ"¥t¨ SGˆ^e_?Ñß[ !öÌõ¡ #„ú†ØýO õŽŒlè)®ZµêßY?«ÏŸž¼jv[³[ !áBú†øCÜ>8¸q{qÕªUÿÆ‹s»¼î6züÝíÍ^ãéæ¿øSϦá†m…U«V}êº ó;½®ftâÝÝíNã6$N>½ÜÏvîDÙûî8z]x,/ÃÅ­yðÆ‚œìöp‘‚–QÇ»ïŽã^æ7’ó;–¸Å”;„‚ö;ÍCï¾;n|~ pPÂÁ9ÍÃ)WM!z4‚ÆmH!»ÅúD¼ÜÑç\ Ÿ¼sxÃÍU\¨u·¼ë€ý!’m}ØqøöÕÿ¶0Q ÿ½ðà—þó;>öÔ¶Ö²C/øìå—¾ïÀÈÇûÖܺêèOl äû¾òó[>}ôŒC03vI*¢ŒÕšLÙC€RB‚” T©Ë=€d\A¢˜€Bï3eÿæu ¼ ÎÝE¨Tªªê •=̾ÜXÃI”ôFzÉéB¸êј)›¢%ð@®¢ª¥P 1Ê‘Ýû™ÔžŽôö·‘nY¦áÔð!¦„€F–}^ IDAT"ˬµb<¶qRÑb,†û‘M!eäµCˆ}þý#üîGv¾°‰BL“)¢„[åÆÞâo×¼¸|qò}om›_ngÏé7·ÿjçó¯2 3ÏÆírý–Â#O½¸ÿâÔïìîhñê#¤o˜Ýö«mÏm #ólØ!_ÞÊ÷·—V,I}àèÎΖD} §OîƒçÎÏ9!”R ¥ä‚3Ö:ï/Ðpë’\ï¸6ÄçÎ`¸ìšç8!äfÆæQNçóCnŸÙžJcC¸C|1$æ8ÍÔAÈ«<Ÿµƒn[ÜÞŸIL؆D Ú´#d7r¡d8òèm—@ÓçV=àw_õë§n>xiës«¿tį8¶wŸµ÷žC/þ`¿Ã.)6ñƒ{þxìÊyë×ÜøõOÁûµ?ÛóØuo>é³;8½àÚG¿yÖÊo`fL¿ e·Äªª]ñ#WcÒG¤©”n"*Ç`eë ¶½(k¥X›-do›ì2®ÂRÕ…²¥«#|—xð\oRë8:0£‹º”ÒuH<¤«c(¥P·y\IÐÊCTz –üL鞘 ”ÊøB ˜¤JöÝ„¡*$!ôùèÐÆAˆØ¡"pŒ?()•DªªC09„@#1òâSGHtú.=»!xþ–çžÈ–/IÅRÒxf}ñ' rIêÌóÜÿßo\wÖ‰³<`N!¨tÖ¬úñ¯{¹ª7Ïß_ñŸûþú×µjew-2Âr!]™jÏ8Õ®˜”ŠsÎA%Z7ýykúÒm¢°(Y!â…µžLeëÏóì@zß:¯µ¦ áMBtÖiê‘J!„þþJñöGF‰D*™H$Úe‘R2ÆÂ0´!Ĺúö]/<¹ëð6BôÝ[³nø¦_ö%‰Tjüy®¹k£ƒCöm‹#ä¯ë†¾·z{ƒçsõ=›1&‡îÛ·!CaÎO¿)“N%^Âs)¥" Y€¥¤„ºŽLgš6÷-#ý/ï“«‚Ö¶Üà<Ï÷JÎ6·¤ªØaÖÌ2‡66On]o·ä[váÉÙéEÔîÂôzš %Ñ_~ûŒ÷ýÇ#_øÀ­g>vqä˜Ñ-¿ùôÇÿó¡'þÞ;RÔy[áÿC¿uí+Ãpé^-µæ?ø}_É yÑÿüå‹ïœ7ãÌŒIô?óµø»Ÿ}ÛôÐÿ÷õ_ìÎF‡ãnh?qõ7Î$ýøÒKÿ:Ìø3cWE¡ÌVfÏ“¾¯ÿùÒêóìæ¢w}7:£×ü·Þ¡©¡JH„)$¤¤]*‚!¤pg¶"²¢dI+»²^FÊÒšm·°ˆTãë×cL Ïs"¡©x¼*^S±(FÇj†ãœÓ1^B¹Þ,FyýhŸ]ïCÊåÓ²†„‹9^J©Å¡Ueg.ªVØ•_Ä*À›I¢j5uý#Ç‚[ ¤jnr±[ÖÄ•õYõbñK&²š:B~þø0—$•ò´¢}ÇrÄNin²vÍy2InZ½éÿ]Ø2öÔúÙcLâ‰Îó;_¼üâƒì¾ó7Û'>þÎ]ëþóü}í„‘ôòL"íºNÂóRÉd2éQB¥’c!%eŒ’B”õ ’©ÜoŸí;é l#$ïì3Ñy©ìïŸÛ~ò¡Ä~ }|Q23áy{®÷ăpãK[¼B–Ÿt“þ㹟Ÿc#ä€Þ5ˉ–?~ÿ˜Ýs‘RµÜ¡oÍÀ7>ôæ$FÅÞÿ±ßúØÂÜW_üæ‹_Ù¯µê¤‡\pý£”õÏ·¼sù‰w>þ?GÏIÏx3c—D¡ôxùþó_Z}^|•}åÁ‹ÖÜñu÷û_^øÒêó®:"»òCGÚYÁXPôãPÙ]aT•Y¨"Ž‘©¨2mD#ù){™±{”ÖòŸ"TU›Œ,¢P»·nÄüAe{×:MÌu™ì’ÞCÛ¢; d“C ‚q½[ó–¤R µŽ_™Éd÷-¥É”ùCé‚§ˆ{CâØ¨Õ{8îUí’Qú#‰`B1¤ò©#dli®†ªáª‰dC&sÚSDHï`øâf®Õô01žH›B¨,,X»9üÛºó¬{‡øó¯†“˜çù ù5/î0WÝ7þý•Â$æynÃè_×õ„„([ë8¢ãPÇ)©MLðÞ½Ô"„(%>j~þ•!sÏCéáìÂIÌÃHÛ‹FÌ ¸£¼9“˜'€æ7ŽL;Bž¹ïœç8?Ž¿ÞvƳ÷œµöç=uÇÿöÓý°ÌÊz{Ćìë“d#|ë\è8ø‹ñwßÛ™€Ëý+lûæÙ—Ùo]|Ç—›)þî üÅ“ë™ä;×ÿõ¿?-¸;ðœk»öœ°÷ñ÷xÔÝ/ Îx3cú]¨ˆ\ü÷oû%a~Óžö®~W“”R ‰è@”`\¡ ¨fˆ˜ŒHIWľ˜?ìÕÔ¦¼D¯ cm¾!¦ûRç#ˆÍav)\Õu7Ò»WÇE<Ï«sŸíØõeƈð¦õG4/5ΗK °ªg\ú¯Âcâ×*a‹ÏGHĉ ¤‚±$$@C±ƒI»B ²X²BlêÕTòП{í¤T¶¶=¿È#£”Þýð†bP",?ô§“žç'½dæyp óÜõë ~À5BúÑ\J‰íøJYª¢àBjðK©#’0 !”L$þø\ÞJ»‹Þ°sòó<›/úLŸçŽBÛ¤çyüÙ¼¹?ãÚóû:BŠƒ¯þÇ3ÞUÇ7ï^¢©T*•Je›guÕº£O¿ä_œ?æÊ‡nxÇòùW¿çÀû?xüMö[Í{Ÿ÷Üãwžq8ºôÔÃ[rmo~ßgÈQWÄg8ଫ¿á5úÂ9‡rÃ{f‚™1͉¼Z…ßU˜_^ù‡•}W3†°¼ð—LJ•¥áâ¹ ;Û!P#TaM@!„s¦ËyÌv!Dʼ‡ŠPÂñUÜ^ïÍZhWÁÄ­Œ*Éú*[ìÑ6qž²«Wåó§È©çªVktj8ÚJ”¾‘"0¦nn£âB§«”R ýW[‚Y–¼%’ J¡¨*žÑåÖ±fÉDŸc”mP‰ú.HÉÿSJL!ÆW˜"B¢ÁªJ„D|ĺÁQ_sRAåöjSDÈ–¡9Ì­t˜Š1ÆÓ[ÒÓœFÿÛ¶3ßÝš…7ï &=Oßß²=¿d^“RjKïäϧo˜mÙ™Ÿ›ÆRJ‘l…1%-ÁXÉ%B! CƸ¦ Ù4<¥Ű›ëé+,™×ÂižÊ<Ûz gg@’ܤçANvËöáÝéqßÏL!]óçågÝŠQ¥ yÝ®Iõ[¯Øïæ–žö‹?fþùõ‹*>Ø²ß ×üä„qçßïÌoùÍW`fì*u€˜€µþñ^þÒó™?|©Y‹c«$K¼W~VYÌ:+š‹®¾‘œŽ™ b»P%†€Ää}ª&ž¬·p,À>$‡Ja˜È¢X5áeÍÕIÓØ%“¬‰D;ŒÏa„m¤R峬Xì/­¦‰5jÌû©æL@ ‚TùŨ–D-„@¥ô@érCˆ¾Þ©#ĸPSDˆ>¯×B6ö€$ô]Ò¾£>­á†¡öZ ¥ÆŽmï÷wöº[“J© [Gx“›§§¿¸s`T»,S›ÇßÑ_èN$¥”£2åI%„àŒaˆpÎ!)DȘï‡A2δעýYÖæÎ3Ü;XÜc~³Rj”%&?Oˆw”\¨|蹓ŸmïYÐn!P!‡;y„C¯þ÷ºô¯.kŠÛ™Åï:žyæ™gžyæ s9Ë—/_¾|ùnìB¡j<Ùøa÷^þÄŸ’ÅV.¨œó è3ÆTPæ“! cd¥™–¿ÿöi¹ž%'~oZæYzüõÓóø§éºŽøèϦežOÿá´Ì³ì„ïNË<+?ùËé™çÌ»§ež}O½eZæYuÎêé9Ÿãolä°Ã;,•óW4]]û‹: §‡­\`†ˆ~µ5;Ùyø™—ýl:ægùa=Ï7¿_Á¹Óž !DÿÁ8C„¡ŽýèÀ¢ìKÁáì/=Xžçª©ÌsÖ~9-ó|è²_LÚïÔ{$¤°ê¯j¨µ³f\()åýßYsè9ÇdIt'3ãB½±]¨3Ï<ó s9·ÝvÛnìBÅ빪æÑó;Ö~õ•–§ÞšC‚aÝt œŸá,࡯¤‚`…‘"åèˆõK~ú'g°BèR'™Í$’®_ p @âŒ*.²™TÀBìP)¥ïû¹\NqQ(ÒÙ&Î9q¨b¯ÓnÝø«‹‡séŒD„0ÁM@ÂÄfql¹aû¥Ôž'ÜðÒ–!’’ J©RÂ÷}×szzzZ[›‹Å “ΆaH)Õ:7Éd2(óù<Æ8—Ëíýî[×Üþþ  …‚n9’mj¡ž‹1æJ*„¤@qá`"B–¡”º OGGü0Й£ïýácß?%‘Hd³YBHXô EÛ¶m›=«[û¦”Ò;vÌ;WQÄ9ïíímíh…„Ôõ`4_L¥R{|ÃSw~$›ÍŒAˆ (ú£ ×óà •N#„ ­G`B‰ÑRo5ÝÔÁÒã®]{ÿEúÁ9X)¥ŠÅb:fŒ …L&¦é8ÙÀÀ@*•Ò4É+ø…Áᑾ·~þO}óXšô†F†¥”H縙LÆK'°ë—€C´2 y!Ÿ¯…e'ýàé¾·„¸‰$!¤Bö9åæç~v#±·q„ìûî[»éÄF¢ŒZÙÿ䛞{àüFòÉ«_Ò ­Ñ®4Õ :¦‡a2QJÔµ_|çÊ¥m­-¹‹¾ñ÷)Ì×}ñøUoš—HÐó/_3•ó¹æ_Ž\¹ ÃF†·†EÎssPRrNµHd)ÆÓÿçœ ¡C?š“ĹÃÂ5Ÿ}Û›˜ÉxOmü<,,\ó…w¾¢;áѧ·ûœ‹IŸÏõ_:î-+g#ÅëÛ]þl§‰¹!g–8Q' UVmÕBPùk¿¹±ù‘#²v ” 5f\7öxúo½®â€«vïDžP’RZjrYªC¡ï§‰áááL&£„ÀÿøŠ¿ýéw'`L +}êº> Ré¤ïû˜ -¬‡)‘XB8ØEK¡3XIŒ”ÂR‚$HI&pÂÁ„ŒŽŽ6gÒZÄÈsÀgQ9€ ª¸àœ;ž0£Å`%‘”ŠSB¹ä $g!¸Ž ¤P˜"(õ +‘š1B”.D&€€’ªi×.ç !A.— CÅO¤’Ä¡~¡¨Ôèèh.—+%âR"B©ÆØñ\!µcá0 !BQ¹Õ|)¥8&”„1p^âB!‚‹ŸÉe¹Å0ȸ)½B¤äHÖ2}ˆú,tžRбÐq]!!a%$Ïs”‚ét:êº\(@G (¥”PÍ“%€&#)¥P c¬ÛÜ€D%úv°l:«!Dç¾j!BˆBõ®CAˆGp„j!P !Ð B4ÿ«B´óÑBæt¸wúÕI^;ki„²lE¿ÕÙâ(¡¤ln§»aûæÁŠ éa4·+±¡‡MnžY- ÎÄÈh1㺔3ÖªÓµBJÂJ>™TR”\θóÇ8œ3ÆÃ0LRR ˜,'?O ”ïKc“<GbŒ Ïdž؉¹úÑ6ÊR„Üõ§Žúر®’Ja&xĆÌ8oì±víÚêu…2M3lÑE{Œl{ñšííO¿9 ’•¤’BÉ€1ÁBÉ™D ˆÁÈ¡@0Ä…ÊÉ(Peq$*%1¢€– ”*½Xþ¸îi *Ú§K$•R¢2) µƒØR) )Ó™¹RN‰›\ÙÍÞlï ÷ÈqœŠ¸ÁX¬kŸ•H˜ýbé~J©yÍqÆŒiðbø!}æ1èû€ÂPÁÚ±/Ãâ•s)‰ý"Æ0Šu¡¯¨@4÷A@©5„]—n#¤–ŠÕØ-¶ D)%”¬ƒs^3„Ä©6BâñªÉ!dì–Ž‡9mÎ?¶ÌqÎ#°±õíÁ9oÍ`Èe<„Ðì6gýÖpró´å(¤ÒŽRjN‡»~‹?éóQJåR®`\å·û™Ù€” caj´‹_rÅÆ|θnÄ EŸ@A6å*ª°ÃOMrž°8 gR`Öïí“g@©d.ã1ÆêÛx¼¿¾ Ñf$‚‘mÏ_ÓÓñèA)ô·…<Œ ™oà±lÙ²™›ðzq¡¤”‹+qƒ4Ùè÷Ÿ?–ªüæóÇ^rÕ8¤Ô+„Îû踶¶¡ˆ]—‹µ[€Ti]^!…*kè0Æ„"„”áNX ¿Ô ì¢÷H›³rR²žz¤µ>UÔWÉ㈞qªÚAÍÑÚÍ¥F å¥!$”Æc°ÏDJ©×Zˆ5x±ÏÖæ7ÈÉV[D;¢1cÖõ¸AUŠkä‰ T¡Ø¤%í=±ù R * ¤jÓåÉ!$"‹o„W˜!2"aßXˆ)M!¥i@Èq‡wýæ¯kuRÏî´mÙöTLÈ÷ýÖ/HxTß“ãßÜõ›§^œÜ<‡¯Ø#镲Ÿ'¼eöÃîä<û-H%ˆFH7ÚþòH!$)Ťôp”ÝVHH!ç‚—ûî…!óý `hIöœ¤»S;ÿ1Ùyöè& ¯ôKYÔ^\³}’ó,î&žK±!æ7;.B8åf}̾§Ü/Üs¶ùø­WP@ZíÒ"+«æªµh­Ô×p(%J]u+ Ú#ŒÇ\–²ë`ÌŸ®Ö¶ëàJÕÈ”bL«ök³_±Ý#!¥¥¯Ö÷ÐÝÄU@#Þ5gýë­8ÞhÉDÄê¸!¶Ž—¹•¦ªDˆv¡ÆEˆMÈ«ŠûTë#¤ä»Ô@H#?Háá¤b—PÅ5:?ÆÒÕš\6—¼´µá³c6ZôMˆ16¿Óiκ-I}pG‹·ï÷…MžgA—×’Kt´¦Êó$ö_œznƒ?ñyÜÖœ×Õâi„$d(^.8{%<\vYÆdN…”RH®IKÚ_ ‚‘ühßšj…ö–qÈ#!ÝTpMtxKª‹t¶¥4BÒ Eø¶B‘Nø|F¶¥»pgkª„Ø.T}„i„@øÚ"D)Y!v˜¤>B"Õ©Q„@£‘ÆË‚:óØ9ÿqÓz®Üˆ eÜkÑ!Ÿ0 YP8ö°…J©y³²&„öáãçþú9w&0OX8îˆe€`Þ¬œ9í³N^ü¯Wýs5¡yŽ?|) 4¿3‚i2G¼ôRokSK»ã:—´¿”ZüŒE}8óý`$?ºeë–ýç"@° +kžÔ^Í;ÿÒ›•¹Ö ͳß@Íïμí;käñ ½¹‰Ì³uëÖýæa„Ñüî\#6¤þéFHĆÌ,~3Q¨™(Ô.w¡ôˆ”wí1UT5½ÂJVQp)°J)Ïó*:£)¥×­Š\¾EŠ çDÞ*gÛ,ùì’>O™¬S¦ì éhhP½•FRJ(»#”:š˜¢MÕØÎ[òH â€­÷aÒ˜‹Õ]îÍj¹f)Jb“z.”-:UUË»ªÜT –N!ÐBÆnN „ØëJ}„评”ζB≞ZAu·§?rܬkïÝìy^D•Þ¾‡&Þ“ÏçO:¢£)ãÎjKy.ñýP?ÊYm© O[ô¯k|žSšÓ’KÌîÈ&=*˽»ÚR矶ð›™çÝoݒ󺛮ƒ‹¬dC\´ ÿe ?¸¥¹É¡c @+ØK)d‰Ä2A~´ðêæm³R}ÙTzVÆMxÔÜØ¬'—5mY³CN`žd_.šÓ™I%ÆJ~s6…–4÷<»}óÌÎæÒéÙí©¤G5ìë#$…šº Ñ)òÈngfÌD¡fÆ®u¡„šÚbK“è©uPJ36J‰'Ç‘\(&H‰³\Ú•¥ã ×"A…H.F'AÊa¡#FZiwlƒ R*!¥Ä€#ˆÇeº@¬—‹&E™LÍ¡VJQJ¡\¶-1‘R P@0¢Ätðµåê“Ñf×v¤µ/·m"¶â%ñtæz`ŒwŒbmÝ jÎ+®~i{TµÚ’@LlJ ”6‚ciÒ)}ªB .Ĕ맂Rî²Bì]D}„èqØ~íÅn¹#Â®íµØ.‹Ž÷ð°xÚQÝ{ÌK{Ùc~S!‡¯˜uæÎáÛ½agœyXñ”#gﳸ5áÑe Û"9ü€YýCÅÞ¿¡‘ó9õÈYû-mO:dÙâ6^(Ú6dNjt`çãÛ Ë›š[×Ñ%&q¦SfAæGG·nÝ:ËݹhV6éÑ¥ór„ì1 oí]»±gnS®eœy¶m›“š×æ%=ºçü–È£_<‹ oZßShÊ5ןgÛ¶žÙÙ¡EÝÉ„‹÷\ÐbûFuRú®Ò¸ ©ßÅrfÌD¡&:Î>ëŸàæ[®ž‰BÕñæ¦6W&þ;ÔM7)¥°"¤âJÚ Á±Ò0¥”””ÒÈŽÊþºˆåƒJ)ݽªu„•: ^Z(•BRE'©·«%Zµë‹”’RªJ 1œ l–pçVp5gÂ^§•RZZ&Þ‘ÐDwªêrÙ.TÙ]ƒAJ»PU»™Ú÷<’´Ï­ê³¶]™I#<Ïk!‘5`Ò)1ßk ¤|¯„TN^!æ'¹°9M~ôÀú-}Òvm5åHáûþ¼òŽƒçÌêh‚í¿GÁ(ŽãŽ˜7»3{ë}ë6ídµæYÐå½ëð¥MYR¼bY—ãb1÷çÄ£uäÈm¿Ü°q{±Ö<‹fyo?h~gk†¼bYgÂs‹A±!t˵½kž©5Ùº JòœöWŠ~Ð?0èoÙ³-lmJ:^¹÷,Âa¥ªõº,å­ß𗼚lšWkžp´gŸ¹ª-—Tœ¯XÚNˆ216ä°}›œ·?ùò67ÝUk^رß|Ü”NQ‚XÖIŠzk!ÄxZÓhCÆÕö›3Q¨IŒúàǾy& UãmJµ¦‹I•‰”S6ZÐqBHúŽãêí”87E×étšK¡¹´Ä¡ aᱟ1çÜAXá–ûÏ3Î]’ ÃÐu]]×#¥ô<cðÒ?Ü—H$¤ä!ó)§¦Ì¿¼„ÐH>ŸÊfôëZòŽRW 0ƪ\O)· Qe²üغ®éÒº3BØ÷ýT*3::ŠÁ3ÎÀÏó$(J©>»¡ÔØÄb±˜Íf…à®ëê›I)%€8!FÂ@‡v’ɤ¹á¾ïSJcåµk®çi޳ì IDATyÃÃù¦¦&BcŒº%‚0 Ç1DTÏ£zž0 ½Dʈk†„fp3Æ\×ÕÌ8RfÙ‹t;¶³“GˆU–_!ú˜:rå׸ÑDZ€ AˆiQ\!Ð BÏõ}¿BLÄbB9tÿ®Œ'_xeð‰¿÷¡§ß÷áRÔ–ÅíÞ+dRT)™M‘åËf‘^Jq§P(h„¼yÅì–,yöå'žÙÞ?"¶îÌûpÜÕêµ7¹‡¯˜×œó %—\¹×,Jq¤äÐÜœUoš7»3û¿OozríÐΰ§¯P „KѬ¶DK¿ýàe¹4É盳î¡,,4Ñ͈ yóÞMí[‡Öö¬Ù´-á¤ZúF8&N3ž‘_<‹ÐfáJšK;‡8¸Ä÷ UmÈ¡û´%èÖõ›ŸÝ´ÑU$58 ˜:_Ì$¤÷œŸÌÌu¤”-YoŸ…É„7œªjCXÚÚœ~îë_Ù(ˆ—ë6ç#%YÒM[$ %ç­Ü«ËdÕ±!&0.B¦bCÞ0kX*U*b¨ß\oÜI¦òñ×Ûå¼Q(Ò.Ô®û®7J›{›hb” QѤ0ôc¬s'‚qŽ@ †¡E©’å;ejõŠKÑÊ˲’OmȧDSd„äab¬×æZQý®Ѫx;IiBgŽ´¯®ì"DÓ[\ËKbL!V—=•°ZX‚ªÅ‘ÆõÕdçÄÙE‘KŽ\©¾«aÈÍ»š«aEúùj/ 䙎¥ aò)¹\ Ä.Ç› BpLïjr1Œ´× B"~ÁììÂÙMó»ÃyáºîÇ.ÿÍwÿõ탃©Tš$œ„‡çt¦çÎÊiÅN!Æ}ÑY<·eÁœ¶=æåvø\ˆK.ÿõuÿvœùÆLÊ™ßÝÔÝ‘‰Sï+‚ ÎÎ6'ç­Ø«{ÓÖ„ÐÇþëáoÿË‘ÉdÒ÷‹É¤›NÒ9-{,è¤+QφÌkOÌjModÛGöhÇ_þ›ë¾x ÆTJ(‰¹Ø£#7gVÎóœúY2;·¨‹nÙé?·nÓÂçÓ×üùêKßâx®Ïh2é$<<·#½xNkPôë#dÑœ¦îŽÔúMÛzGQ'\ôŸ¿¸î Çç.!$›vçÍÊÎîÈ`«ÅuƒJ¾iGÈ,ð:ñ~¦ñZŒ#õ:BͮƯÈÓ­LCr»JYYýJ ¤å¢t,´PúåKV ”.½ªXÏ Õc¤ÍŸmGÌJ_â+#ÉÔê0$JÂÎàhÞniglúrÏNdÄ’†²me¬cj›§±zl Å”‡`–ÀR‚”e~±Ò¤,ÆUÛÍêýieA™Y•MdÞ¸&‘êä›l·ÃDÅôCä|l½Ô×NŸ5naõc4BL”e\„ØrJSABªB" R„ÄIZ6BÀâ]ƒ¥¦!¶*•> ™pöZØœtÅ`ñœ¦>µ·5wÎÊ!¢l²š}Á6B’.ÝsAó²Edp$€Ås›@2á4g½„KG%°ÿÒŽ=ædú‹°dn³—ð@&çÍnw)iІ¸Y¶0½—ã9,™×‚Nx$›¦A~8ƒœ’pÉ~{´¤ÑHQØc^3¦Q˜ÛÝŠÙ¨ I%œý—vî³Xõû° ;‹rÔÑšÉe’fk1A¢çßµ™oìQ52¤ Lñ`Òä{ æ#¨“kÊ‚- 0¦j]NåàòvVrAQŽ£çJI(ÉüPJÁØõ0¥6ÚT—”I;cE^š£Î%C ¤1ú%Ó_.ès¡”¢š9 -Mm-\ØÖ\©JfЖ«Ju›Æ^J)jªêÍŒ0 /#ÅD c«²Š(—ùvÅœ¾?ñˆQœsmLª­S!–ê.1ºZ'" U+6]RÏ”qbîö®FH¥KT!æP\̽A„”<×)#$RSiž8Á¨£% Kæ4eH1›Kº 8›(B\B:[Ó°d~«0{ª­Äñ°‡‡’öæ,™×œH$ŠÅbÒ£š4!‚)élu`ÑÜ&‚°.þõ'Ž×!ÙŒKæ6)Œ8¨¤G‹Ÿ¨ ¡u¶¦ôuégáºÎ´Ø]‡7ªëOÉ™WR©Ô#ßûâ—®þñ“/l”^óÊ·½÷ª›¾¾Ö‰Ìзæ¶cŽû—#¿òÓoŸ÷–úùíõ—}þêŸ<ÿê@Ëü}>xÉå—_ð6‡ïÜãÓý;þ¤Qÿ|È¥WÿùJL<¸£õªõ;Ϲ žÉk…jÌ4iÎÓ®ž7p¡â›|Šþ5êÕWJ‰F„E$ KEÉ%I7Œ¥Ôq¥€±²ÖÈxîÉ„.¤ž¶6«v!D¢€`\„Z: imE…RRE)˜Í.ÆXfý¸``—¼Ç†)#’¤ê­Šn ¥þ°t¨jëJ$¤ËÁ€Ø1 sœZUSÙ½Aé%ʰôjd$1ãŽW#Ã:˜4B Lø¨ÈÆ:Ž;ññÚ áz)»Pã#¤ìÖB¼ÆÑ'_ !„pHléæ8S`‰ûî8â%?ðÂQQì[â<¢·!ƒ>úõ“C[úÅÆþªU«.¾òÅy‰îVüÎCÛ¼‰Øƒá#zy ßÒ®Zµêâk7Îípf·‘SŽš“ò&€P’ÞB» ¹"KÜwÇkó#2è_ЖwÜIÚs@ÈämÈÿÍqêן¹ñú{Ž>p©ÊoþÑ¿Ÿ~ò)7½òÛ í^^ýßÇœw×~ºæÜ·t×ÿȆŸ÷¾¯nüÁ½·rî–§¼ð´÷^Ðõ×N]àæ?)ñòí; gv¦‚¡ßÞôÜ ¹ü ¬›ßvÃ+ÉSϹ žÉ®ˆBÙ¦:7xØk0ÿn…»½šUNbÇ4ÑDJ‰1Á+Têuehņ!¶«Ka³½¨ (Å9w\7’41$he)öêåJ(ð(%¤ÖF2Œj™³óÿcï½ã,-ªüÿsªê 7tšéÉÃÌ0C†!g ¬$AQ1 Yñk\ÌúÝ]~†UÖ°¬Š¢€"ˆ "¢«‹qI²df`bO§{ŸPUç÷G=OݺÏí¾÷N÷ _w¶ë54Ý7<ý<Ï}÷©S§Îùœò’ú3 äd6ä®§ã[ 4úå²gBV§½§ij.ᑵòÃ×=sÞ?Ì;êÊd6ä¾§“ë;"I´9΃ÏÈ}åñ NZ´÷o2²%®Žy{…}®ë®ç*K{žY2H[eC¬7¿½ ù_8^5XjL~á •n´?þøc'ûã]þxçwø¬›·Ü°±öàªYö©UÿXÛ¸À`w¾ôá3ÿ Þ²Û-ÿz߉_:ñ÷Ÿø ûºï\õØKoÞ£›3Ù~Q¨ÿqã~.Q@§°¥`g]ÓÉJRIK™rÆ@JJ’$à¡ùó5 HLÒ‚&"l(Y3RAf1§€!r DÔ P3@βPFÐ&ãAÇqÁ‚+ 7ÇÅ­>Ë£# šU¶µÖŒ´‰3 €ÛøLËH@ùþ„R ˆˆƒÆìˆˆ‚ç9ÔxJkMDdÎ ˆ9a€&w„1†œM®æ¢ &"f®ŽAÖ­K7E¬•R£`4¤˜ª)(·Ÿ 3å4Þ!ÌÙMBtIH&5mBH·#º'„¨!M¢v„´ÔinB&Œoµq²‡ãjäïW-—Ã0_€R©$Ici­¸ð=]©ö=¼I'É“».šÀ†ÜóŒºáÞ Ãr†ahwýÒ4M’Äuj¥¤K¿ÿ, ½ƒöœÕjCîy"úÚÕÂ0,—:ç3×?yá ƒ¯8¬·•Mõr-Ü·ZéæºzÚ¸P«5‹go… ÉLs7„tmC&$df¸cÿc+ù×Üñ΋]:ÍCõíò!zêà‘Ú?|ê)ºçä;ð]/?àKëñÑ]ú^°ËÙÞy‡v,ü÷ï~ò¿›Nm†<† È,š²ÎðD ®×=ÏBŒŽ{ž†!‘ŽÒP—J¦q2V@ÀBßc52œCäÂļ!Œ”V¦ ôh}´\ ÍUyÜc êÑx¹z‚ mÚ4þ)“ ð¸Çjõz©R6áD%­uµ§¯%¾¢Æ@xRJ­¤Ç9c€hZ½ÚµhB Aƒ¾Ù€Ëö2@sÁ @#‡8Š˜@©S`(|/®GÕJÅÄäÍ\»ió†þÞ>dtÁGÒR§ 1NÈ‘{ Eª%j@bxŒ%iì Œ™~Ä1‘)ƒL(ð|•&*Mc‚qR*|­”T‰xiB(•j’a4®‡aŸÔ 2Î#G!ñ.ADIAä­®”K¥RX)—Jaèy‚ˆÒTrƈ²^¼ŒIããööTÝGÔ½O¥¥RikóÀSµ»Ù´ÿÊ9æJS U°p ×ÃÀ?»ÇÎ=ÝØ6¹eBîûáZª}NùJÞ®(#D«ø#ÿxë¦ýüäÿ]½r^uÓÓ¯ùÞoÙǺ„ì¨SÚ¹·ÞüðÙï:|׋·Ä|ÉÊÎ|Ï÷¾Þ1Ý¿½wçãÿó®›N9ô¸7nùö5ï{Y›W.{õW¾³îýzÃQgQƒÜø©“;€KNy‹z÷¸ìtâÛÕÛþû¬S–¼÷á…‰B™øÓŒ:yû@Ù@·]ÄÛgºñ¶?ÍÞ÷ŽsVy‹W,üÀÅÇ©ñ¨P™Å…06«¨’@M.”«jS(r¥®Ýy¨˜ËœÏ匈¡}cÖ¾-o7ÙìØjÂì‚»0aØÉó ‹ÉKuKÁ›‹Šc0$Ûw‹†’#Ú4Ëó×§é¬ZJcÓçÒh3§³™O)%8Óç!èü…¬¥+d/4!!B­ô„÷òMkŽW{BLqV«îÑ6'$£L—÷f¶'¤EàgŠ„¸.T+!à„ߦCˆë+·'dÃè€ßÇ›;0‚VJI¥ªHÚ½ „ˆ¥0üí_k;Í©úˆˆøËÇ2]ÖBY™õ ’Üöæ !nùí†CöYR~vÏø”sýOŸX¹¬?ðlˆEÿT¯ë¾±e Kaèu´!…¿š)òèÍ¿üãì~sá^ÃÃøhùÂ÷_|JE.!;’Ûd´¼ø“ß»Ïo¼ÃjüЙ™LT«ˆ¹}Ä}ª<﨟<±¡ã[à¥~úÎ ?=ñ)Í}s­öfó}iö)…ã´9ìôuÉ_˜(ÔÌèr#l5Šu¡ÜYðŠ[6ŸôÏ/¶³H¡$o%Ž¥RÉ nò7s³QØÈs׸…)Öµ¶š)Û°f´§‹‘­•R÷\±GD¤‰¢DÎÐ…C–øiˆyÿZFHÙ“1_ÝZåUg\‡žóý?^ûZP@Š´àNËF 4"7¿¦átj"¥A€Òš™ ¸,·I³\®¸Ù¼jd„HžÇKÒ㥔 µR$µòD`Ûé"q@ä‚£Éü$ÈŽ @™x˜TV@Ì¢ ™Ûƺ\m)lý¸„¸/kCˆÛ@fBB Kö©²ò”oÀоúð-gO“̧éDH£LaBB²µ Bá @ˆ‰~uCˆæ½Ö¯•R¥iC¼>NÒ$ISiª.¹ÿÁ×úñŸ‹Ê³z>zϹ¢’'œÚòt!„]ºËtlîÕÚcÄ­šP½‘µæd˜z.×Ù]¼öÊ(“=•ÏCY2Žm‘ H Q·Ý^}•}ïAg~ç¾ïŸÍÅÕ¹DbÈ4 æbfvTÚddépwõ¯uSá›LRSceKÍ3YKD•Mؤ¤d%Ôœ\ûG˜`´ÖºOx€hlGˆ™N\B KdëÙ:¶!¤Ðœ®•˜DL¼•&ÁI‡ã?e«·“®zðgµ'dBq‡Ææ d©+m™ð†O™¼!N©!YyÇt }¿LJ)™Ê8IAJ ˆZ©$M£(‰ã$•©ñ6ŒŸ¡ÉT`ÒXÌ6 EËËœóg‡4z™…IT2Œ™Àd’$Æûq7pm\gÃpº~¨¾jg@ħÖ'(øÔ޳ns´~s͸Pc±ïU¦z] [·¹¶|§Ž6¤]š†Ì ùå¸þô}÷Ÿöɿݿ6*õW_rÔª¾yUi"BfÆŽ:f¢PGQ(ƹ+,ä&®JMŸùƒúì‡NØwiÏðºÍW~駯þ¼ÿŸo_G¡a­5Z?Ɇ¯ó_tÄy?Ú&׳×éßÚ&ÇÙõ„+¶á]Þ딯Oó{¾úÛäLVŸüµmrœUÇ_¹MŽsÐû~½M޳âÔooÃÏk“§ûyíûšon“3Ù勞n›+zýw¶Éqv9î?ºyÙõ_ÿ‚RJJ§©ñ08çæ›TÊ$Iã$11°QZéÜéPÞøáŸšãzè¡F÷Òø=VýÕ$€§ù°17€%úMuŽÃ§xœz¬ÞôÑÛ·Éu½éƒ[aåLÆ!š¬S)Úä@îû~=IÃ0Ü夫ïýÎëÂ0ÔZsÏ'"ÐY©°çyYÿTMv—§),Œˆ˜""Úå¤+½õ|&ÐFþmþMEH ¢(*^\J¥ŒEõþþþD¦ëž{~þüù«N¹Ú½Ürp&µ<¬Õjåžjœ&Œ)í1.€¸"'ã£#@„ŒA–ÃÑÚx"¥û¾ö[ÜüVS}MJŽŽöVËcccIû¾¤ÊåòøÈ(ó }&øøøhµZMBˆ8NÇëµÁYs”Ö«N½î‘ž#¼R½^~€H¤tœÔM·²0 Á©[lî”’¥:I¥8ç»wùC·ž&[ÅišúžGD£#ãÕjµ6:&„èéï©ööÀÐð°ÂΙV)hÉU[}Öͺô(,J“°Úã—C¯R¡OÜSDÀ8p¤4NÖ¯_‡ˆ“ràY·>ùƒ3»!„ tt´•7 üðœö„hDœŒ½^ýÍ¿Þô–ö„øèÅq\¯×i¿åR+!ûpÅÝ?<·B*¥’ñ&$䀷Þòà·Oë† (+¢ÉÙç5ß|øÖóº!äÏÏÆ¦°Hk)c™Ô»”*•ijþ“R*eB6&—HJ•$µ/}øè£öœ qtÑUÏ›@‘ÛÏÑÝ3ÃÝ9³‰M‚é/}ðè—´Óèðæ÷}mãÔÃé²ý¢ýõVKw®‰¦s]ÿñ‘—yÀNH²½ Ùóä«Ý )BÓÿ' PålYxuýóÿÙwõ@8ZŸ5oà]ï}É·Îþ¾ë ̻ۅ3c& 53¶— …y2›ù¨”2í´8çiš¾qçÀv¨µª^¯×ëußó82’*䡜§iê{A’$œq­µïg'†aÇA•¿r¹lì²Ùñ1 .AÔjµR©$„ÐZGQ400¤Òó<Û™ÄjåqÏ¢¨øÆš÷š¦ëFjÙmaa­ãWV€Qý!dh²8çZGI4ú¾Ç4Òqi­‘#EQd.ç¾ë_¿×Y<ìÏßzÖZ‚@+#¿ó¼èL“Ô„Œ‘Â0LâXk…,ëZ­Vk‘Ñ=bçQù\p@-G6>6Rž3‡ˆ{žG …çq†Œ³4NT ËAE‘`ltxdVÏ€Y°FQT¡9xšÆçKÅ“$ñ<Ï|²Œ1ó£™]ì&8iãg Ûœ#D6žI9òTyÚf¦ýÑ‘yf8]Ûˆ3à,o¸HŠH#0b&7˜PçSf! Û9sk(µ'˜©2Ѭaˆ`&-ƒqô8 8c‚sRš I¥uVZ:+ª" `„¦Ëd“ÎÈô VžñŒ{Û[?”æë*ÖiwCˆëBµÍZmA†Û„Ì£™„è’ÆG˜Œs.ÝB¤Ñ„„@VŸß™Æ~ýD„˜Óé†es£»ÖŒ!¢‚ñ¼,ÀÑž0YBR*™÷§K’4ŠâÍCû,a9åÿ°wåŽGFÌßQAiÂz·®ÇcãIQ¾zQ)æž¼òÀ¾ŸÝóÜÔŽó¢}—‡7/5vï¦)^׊…^à‹nlHaÛ†½NÌR÷|ÕUðÐMo6ïê™·üò—<ùáKn¾gm=ì©zè®ß=IÁ†ÌL~;êØ{ッ½öÚérþÇG¡””ýð¬±Ñšïû:•¶öÇü=/?t¯ëÛÛ­g eRoŽ d¡=ŠŒ·J›©«à?µÎ¾ï»ÍÏݩε†îL™é¸ ºIñ5_–8­1†ì-L£«l¶Ðˆ!›|¬CcÛÖZ-Ä,6“J•JB/—ö!'§[ò ßJ#ç\Ke¢,Öe1[ZRK¢9…D¶ù¤Ìc A>­Ri¹À©[œØŸÎUšc`±~Ië‡RcP³Ö !Y¼dBܨgBòó™.!-•†.!ਃ¶'ÄŠXOHˆ‰WuCH#Oq"BÌ芥Ûb³¾ÚR ˆ«uµºƒ k‘ ÆéÊ£>Zk•õBÉüŒ8F×V‰9YÖ9=|õ|z`½Ì$Ð7וl5_m$)MÓŃl 7˜;P6×8»Çßg™ßÓ[}œ%sDÕŸ3š®ì'B>7¥ëz®²Ð›3PêÆ†ØÏ«#!ýѹZkÐÄHe Y~Èê_´_=‰5Àx½ÞËŠ„̸;° õwîvìH£óZÄlØ9Æ*Q³j€µG…ÒqcÂâ86Y2m\(ælÓìæ4ly?$IR¨c/l¾Øu¤<Ì`ÎÁºe®Èµ+¯çÄPšÎê‚|@†Èš;w"c`.ÂþFÓÃ!³‰€™qutD›¶Eƒ¦æ Âñ€{’ Iq$Ÿ F¦]nR;7AKÅšZáBAQkM¤´©•7ÿÌ÷æÁ–Y0‚!rÆ8c/!­ñÅ!ÔŽ„¤Ì·!6ºÐ™†m™`ãlJ„˜Ù !­¡]B ëøÔ™†¸×âÚðЦZ­ÅI’$¦T-IÓ$I“T¦‰Ì¾O’8IêQ4:6¾víšÝ,]ØkoÚïE2¾ÝÔoûÕ<ž$‰Lj/;`€vš_µ/8ïøE¨ã­:NšÔ^vÐ\­ô’ù=–Uó¶lÚ¸U×µfíÚ]wblÉ‚þnlˆëò¶'d:6dGšÆøî'Ú{y_Oßò½úÔMnï_·­Ô/gÆŽïBÙr;3M˜øÒºoÿVíòÎíàÑêBµúmù`gÇJ˜º'cD òB…ÉÒ=ÉB\¤UºÓ]Ig“ @sŸ *ä—d 2­Ö™X“I¼Ö:•Z*ÔT°bî6]J !ÈúåOØ0€‰1Ø ¸:㦯†ˆej~æ„ D£ù¼Œ½nuSÜ{8ÙÇ4eBœ}¨v„´†¦ „€#7ÕžÉdµ *  áöõ-­B&#duP‡âS“’%¸LBäZ$ !Õ† ÙÉé-³ÝælX·aãøx­^ã8‰“$‰Ó8I“8‰“$Ž“8ŽëQ\«ÕGFÇžzf킞-½±`°R „µ!ƒUöæƒD­VË*ÝÈûx’$ccc'1¿¿Ç[8§úÜÚ¹ýþ[îÙªãwؼþž`ÁœJkCª!ìÜ»f«®k^Ï–ÞŠ·`N5ðy76¤eï{ØVBv˜9løáËŽzÛ÷Þvùíë‡ÖÿôÊwüàíGýÇ#Ã3SûÌø»p¡Ì$d'H›;\ÈÉ-tðµæÏÆŒpbkŒÖfa}½/ÊR.—o¿ô¢}–/¨V*æ‘û¿÷ÙW´r ·wþÒÕoùðUµ|¥4úÄOÎ>éÈÅsgõô®>ì¸KoüËŒw²ãD¡Z{ÃDÑe¶Ddà8¢6S,™ÕXVF¬×¬tAO]p€@“Ê]VK‚ˆ‰L¥”Údòæ½d. gœsáqî{µ”‰”‰éÁiÚírΑ3BP¤iBƈ¬9ä@`¶BŠKC3'™KÀ<ÌžuâƒL64K|dšPIAÄ@3Ò5!5¼CBT ˆ¡F0ÿ ÚZÄC–¥1è¼—YãcBDœs1À 9qŒCBÓB›OÝšïÖ,¢ö»º®‰wwë¦@tG‘nO4÷iCHcBšˆ,Ú7mBA¯N„4R£&"º$$ ÅmgBº1(BÚ£g÷ÙkÖ<}ÿÚçÖ mÙ´yËÓϮݰöÑ=Œî¼0ôÛwå<αՆ¼|uï{›;XªGQ”8#Žã(ŠFGGçõȳOXº×.³=ÁöÚe¶ï‰VrÒ ß}ʼÁrÔæ8óûô§ìºÇŠßû­š”ƒVrÐÊêÊÁç×>ó@›ëZ¿æ‘½v_¶ ìq¶ïnó„`]ÚìÃë‚îmÈ$„ìãÊ·¼ëe í Žy×Ð_i}Ùó¿úø‘|ïÌO}çé C÷Ü~Eé1¯:áŸþÇ+Y»iËó¿ïЧO}íö-§}ê¾^ûË C~uíGþô{﮼K-Oï¢;¿û‡GÇÆÇ`Ýo>þйû}Wüè¹ÍCÿ÷õËúÌK?˜yrç¾ø ½¯þøÝ=·eýÓß¿ì=o¾hÆ;ù1:¤“sqœpΓ$ ÃòèèhX¤TÆÀÖëµJ¥"<Çu¥iz¾ŒbÔDZ„å8Mzûúâ4ñŒØ gZªÐ÷)¾ÝhðÐŒ'‰òE€ I«ñ±Ñ Â0¨Õj€HR*? 4@©TB¤iJ„JI!ü À/ùJ‘Rʘ¥DÖS•å{<ª#cA¹"µb 82" F€¨cl||4)áù Mz©TJ•ËeRzdd¤§RÒš¼RÈ‘ ðÂõ7 Γ&ÉЖ-•JFȺopŽ‚1•&,QQ‡B$ñ˜ç‡¨RÈ R)Qä,Jb$Hµf@iš¦2ð6^«”«Ù„&iCjΕø¾þæÍ›zú{`Ë–-=}}:‚¨žjEÊtEÎY(ŽÜó€ûž"Í“q’Ô£j_œºKÛõÂ.|Íf‡S¹&óÙÑ(ëÇ©Ý22”gŒ±ÉÉìZ„H)¹?)!Ð%!}}©ž”“× !‰JLwå €. I’¸R©LFß !$XBì†`7„ä¾²zvoiýÜ÷Ì“žlN™ðâ¨^ 5¤£;ÏÅ9Ë*¨ZÂ÷šÏ|.&´!ûÏâsÃ{žýýCC›FÕs›jõXÎûJúàUóJžðûÊ«—$I4™ 9h÷ƒ•ûùùŸÖ רº¡$J”/pî€?oÀ?|ïgÏ*kMЇí»&³!ûìÖß×3úÀ?ñ´â~ïæɸHâz%Ð*Þ²ji¥Rö9½UŸÝæ!R×»´!¹ÿÛ™îmH+!;ÌvÏXrPoô«&cw·¾ì ç^qö­}ÝþƒP^¾ÿ‡®¸Ã<þìÝ·ä/™uê®;gÁK^o~¾ðÖkŽ_= –íü5?ºp“¿pé£ÿºµ§÷Ùo¼×ÙYyÄeç\ñ‰;{Å‚ „‹Vø›7|~ç àÓÿ ¿ÚýèÔöx°ë/ûäµ/›ñNvª°fj Wdaä,­ÁÄ„B˜ÎïœsîyZipšŠg­¾Hƒ*fÉØµ22“²ÌLz2çÜ&µd+3±`š Ï“•RæU,H ”éÑÉÑ?ˆ™CÝhÞi”‚Ýí!pZÛ"fMjÝä³vÔVI6¦™¦k1-Z¥¢D2ÿ2õ<ºY´])%˜)D÷”«Ÿ„:oª<û9˜]Ó gL0&h¦9CÅ€L  ýÝ äd©N…D"£!¹­ÉÜôN„h’H^Bl²NGBêI2œŒ0ù¼]¢€^B»#¤¡Á6=Bhû²b§¾Áÿ™ õC£õÞèŸýÕçÞyx©ZQ2Р{Êþ¢åÙ½ž@ª Y¾ gѕ˞ßsÁÏ¿ä?/ÿðËÀðð0Q-ù+vØuÙ¼$I⸠Y±¸wùN³æöÈM£2‹>óÛ/üãœ{Bˆ8MÊ!ßi~o… §2ncC–ïÔ?^ßãO=·n çâÛ.¹ùò  ãX%Qù΋gÍ,#r7i¯BŠ´OÛ†´ò¿mª»ú¹±öžÕúxíù_¼ëüÝö»û6ŀظ3ïZÙo¿Øý=ãëöØjêøY%ûýמÙmþEMQóì×]~ÖA/Ýãà“_sÂxø1/ßcþLÆúáB¹É¿Ø\<ÍõÀM;BxžR!DJ)8Ûmˆç–½°chëÌmí·™Ÿ0ßå1z,vYÌÍÆƒÕJ¥‘*r;ú1Œ Ì—ÎŒ1¥Uûm¥” vÛÌž|…­]1½BQŒI ™0G^k™ÊÄhJœPhB–O<&IÅþj&rÑ퉎fÖýö¾¹m)%¾UŒ$F6ˆ4kJÓ·ánËMpS M[Y'çf*„äáö„1‚6„dßwAˆŒÍÅd„¸¹Jí É®'!ÄÙèœ!®kÒ–Ùòý½R.y«W”9 ž^»v^ØWé­ ½>k 7Õi’$ÝØrà­^1{år6\“°bqjïS}•¾žr]Ú/ðöXÖÇ„¥–/ìåžW-‡¦³zˆq{>ímH)«vÜ}Éìá‘V,@Ô¤Ë Ìæ¨…çOÁ†Lf§cC$î°räûTý?Ž&/é ÌÉØŸüê>“ZúÈÑgŒžùï®:fáì^Nõru¶CpÎS;=ÏùŠàOë‡v/M0ížô…;îzóÏnÿåþtûÕÿúîs|×M×}ðÈå¼ eZå%mòGCÁ9oÀ„&›X0FÍUNšå(@n›a7›5ïÁmVr–›’ï X»ŸI2* ¢aý•nX(#¥È‘3Æ4ê*ý«˜2–Ka5Íjv²ÉWÞ6ÙÞ"î¤QK)I PÚT“êL÷ÇÊ|cvQŠ@g+H¡ÒÔõE´Öܽ…ô#×7/'òo º‘­™L–Â©Í:œ“â¦UMHˆfu$Ä<;!Yvà´ i8A`íiþmqU¦CH!ˆX Äý §Fç8ØÀòE½=ý}I’(%§`C82£µ|Q#ذ1F.¦`C<Á+evž_A(»tÿ—¿ÿË Þò»ÁegÀŸšqPþþëèB5l¨&PY85êÀ­`¢"*R„È1L%R1Ý,Ì`lkžmíºP®F0ä¥òn†)›Êd´Rö$F‘íäEù2”sÛA¹EaîUæq ÈbêNò‡U©vÓ;+Ö·bBøySp+˜œ{¥ˆ”ÖÚÔ“›FìŸ*cÈxS¹¸,qoŽm5ï*CšVÊYÇöFεÀ¬ „É"p®gSПܶ„˜]¶Ž„¸Õ‚Ó$ÄÜ¥É . q£\­„4­YÛâå×5!!µíLH¡³Ûv"Ä}pk I)x.ZúT¼Ç3p䯿òq8âá‘Û27VÞ”mˆ=“¢ Ù4œ\ÿÓç>ûí'/úÜGyäùÿöÀ%ß|â[?߸q8™² q/­=!ÝÛVBv˜9ì•—¿ç7žþß=šÈä±;¿{Æ¿yïå¯l}Ù;¯<÷ÊN¿á7F©ÚüÔ½Ÿ¾ð󸉳Kïýæ¯ëR­ä×÷/î[.?áM·Ýõ”Ôò©»n{ãñ_:ã²wšÇéñ¿òçgíüÐ>ƒoxÿUOo©kYä·óŠ ';Õw}ãÝ??ç¸/~ÿ·[ê2­Ü÷Û¾û´ƒÍSœrÑM¿¸k¸žªxäO?ùaÐÄŒw²ãäBlSöçM`:‡¹+©ÑðQSÖzÓ†›š Óªõ·h­9ÏâÒgÙ"Ì,RÍñóÅ¢«ëÚ•G¡0…æ á6ëæ¦ž}®‚ss‡ˆ䙕dÀ9gž°§d×ñŒŒ˜3¡dÔÙš›°ævÙ€ $C¡¹…=={VŒ¡ÒŽ7‚«tœŸ9Ú·Bw¼ }© 7qÜÇq„Ø€A{B ℸQ±éb§Ø 1÷°B ‚™Bì§Ö‘DÜ&„¸Ñ©D›õ.PYây}­µT2Mûoî£ã;y#k—õ?Ïpê6dš„€£+Ö=!›†Ó~ñüýOÆÙ­a™“Rê‰õêѵò÷>¼÷òð¬—Íîõ¶–w´=!ÝÛVBv˜9¬÷wüò²± Î{ù¹Olžµó>çÿû/ß¾[_ëËæ¿ø_~õï—¾ûݧœ÷КʢUç~àóæñ/ÞvÙozëÜw¬ë[¸ûkßq-¼ÿ$û–?°úo8êµOoî[¼ê-»õ’c›Çÿã³ç½æ5¾oý¨&ªÕjçÞzóÃg¿ëð]/Þó%+8ó=ßûþyÇLxªs~ÿŸoœwñ'ßý‰³ªayõ!/;çW›§®½`¿ùÄùþáÁÔïßûðã®ÿÕ•3ÞÉŽàBe-›˜fŒ!™©%ûgúØ‚[–…p˜`Œ˜àd Â5Q¿¶ýŸLKLÖ²Mà&ÐØ]†<,/¬†è¬0Þ¶»r%…ˆÈ´‘'bM~†qÔ5E€ò ò&½" £7Mz“€Œ¸@€3 fu†ÌyæHkbk×HkPó}r–·ÎåœsŽ˜«íA³H’=³’vŒò›ÓP'@³SJDœ{ÍT#² ¤ ½Ÿm—‰ìLZcWÓ"º!¤µKLÈÌ:’MŸ“ÝB؆ìû.a,Û·š˜7êÓ–Ö[4UBXBZ]ÌŽ„ '½uŸ°Tõ<+ÁERÊ4åy£d¨G;ݳ¡2ß{dEy«mvGH{â:‘í ±6ä/Œ^÷³!I¢\.ÛF„*ï‹gîÒ_ŸL.¾ìsN\|Ø^s¶Ê†¸a³„tmCZoÑŽ4ö<ýƒ¿>ýƒ_¶ê”÷þä”÷=°=ϸýÏgØ/}GC§àè >uçŸj=Îng~úÞ3?mô{÷ùâw|ÑyÁ‡ÎÌÒªz°äè·\ô[Z¹Ç±gëØ³g<’Î…rRÜÉ¢ ×”ÿÈ!©]~Ùu-1N¸ùc¦¦tòÖã„7ݵ”›»ãnx™¸½ÉÕŠ»ÆˆƒŸ¬É—“Na ×kbéY^°D£3Dؤ™]ˆ&íä\ó¼EkëBß|5;’¬QeŸm¬)¡wo—ä6æH†­‚û‰íì)5ç*¹ëæmIˆÂiCH¡ƒït1=d&#¤é„g™6![âÞZp@µRà |!J¥’$Y @¤µâÂ÷t¥Ú÷Ħ]øº§–Í£îmH¶{>nwL ¤1RJDŒãجÏt*9 Yê¥iZ*•¬:¶IÞTJ¡&’J)%„¨×ë¦T…3ÏX7óz" yk0À¼·¢RªT*Û%©mRkÅoÂ04? !Œ²…a(¥äœ 5œS!¬Ï20´F¢(ФJ@鸑Öå œK)1õ<Ï”yw7ëõºYO'IA¦©œyD)Õ××§”Š¢Èó¹ [|ËTû^¨5˜‹J¥’¦)i­LÞ4UŒ‰8Ny¶À¤ÔŒ ¥HJ À”"Î=RyŽd€Ó!º!Ä|m€. 1wi2B, QJµ!ĺ!ÄÊOHˆ‰4tCˆÖº !æï¢Bâ8nCHn1º DS"½š·W¥\*•Âj¥ÜS­ööT«Õr¥\*…ï{& ÇX&ßÛS}pýœ±˜woCº%¤½ ±QºŽ„$I²yT]ó_[‚ (•JÕ|T*•R©†¡ïûùue 6ß÷¿|ÓÏo¬M͆´'¤{ÒJÈÌä73fÆvBÙåæ®§~ÃüøäÍgÙ+#X~Â× ¯ä泌Q#ÝX Ûu’¦LŸÈT\V„Ö…‚óyiϺR˜x¾&àh'9)¥2«ÃÖFm¤–›V~N ÅØh"“à Y§à6ƒÄèMÛÄÇEÅ,1:¿¦U{Þ¨5^äš.…¼­}܈|ß÷<1fL¶í¯b›Í9!}n±ÞjGÑæ(ægCþXø\lŠÛãÅb?5rz »N ÑZ3FÛ„3­MFHÅ6„¹ÒIɃÓ%¤)ž×–¦Z !Ðܾ° !Míw¦GÈÆtYÐWñ}/ ‚r©T*‚ Mš1öÌÚu}=ÎMõšpç¼Tîýå½O8¸AH{N>ûtÉÃY !¢ë1$5/—ã3…ahe5¬cd¹@ÈÌä×~t£<>3fFGQÒšñ±ïŸå ¶äÄ«²>íJ’ȦÉ'|þøø8úaˆ ”R¤90L) EHȳ¶Ùa³Rj‚æP®lmûeg,cî oªšõ<ÏCAs¬ž˜i¥ÚZy„`v¡ÈQÓAhFO;{BÈ;¯ç¢uƒ ïÕª4ÆM´I÷Ô tÞVDl}ÑÊ7Ë„B“±áfÅ2†DÆÌùàJfÛŽ®4^ Í}Z:zNBŒ­g€B}Wµ"d@ 3Bº!D)L·!Zrt&#Äø=“Ð%!¬ !વ'$;áÉè’&ï¡…È{Qw$ÄîšM“XùÊ_`|Ïž'„œqÔ¸ió†knüñN=Ö÷rã“·=‚G0ðàÏì¶¤Ü 1_»!¤ƒ Ä: IDATn Ù4¢ï{2)•J^>l ÈíXh!Œˆ÷?9~ï#›Øs~—6 u“rï7O.÷Tw9åÚVBîþÖkJB„å qQ‹â±‘á!3cfÌŒí¾‘gVcn™B”RÏvmdÌ­-š5ÙzwñmÂ;怶·kA¦Ï†¯í1–Í^¶ž²îWHÀ9g­ËåFzxaFligÛÆWÈ_¯© š#<ÏXvsz6Ô}é¦n%†c‚qw­ÉÁ)ÒÑMEmne8%÷æö*¥ìqZ{ñj­z¶›æR¨?×$¡mÕ„ÙÄm1l¸„T“âžvBrðI ±t$¤à L™I*Ô2BÜÇÛ‚´mid(O·–m:„¬‚»Ž‹ÖYô«%ű֚œîufÛ´†¿ýëX­žtcC —JêHH{’Åuº ä?ÿ2ìnÒA³`[«Šl!¾ý“Çêq²µ6dj„@GBf&¿™13¶{Š¢¦‚`®Ùq·âð7\½n8 «¥•+½þ´ŽÝ5¢TJ%%Ó, s’P@¨µ•ÞvÛ‰g Î$­ æÑõÌÖ+MR)®¤”È也öP3$£ƒÇ\g±‘a š€Ü§І¡iÊE5MߌÈØpŽYè›_ª”b¹ùkX7Ô…ÙËD S€ ‰1SºfZ/ÒZ©”sÔºéPÎEÃ1º‘f’0:@©’˜Ï.œs†œ!ÏgMÅã š&’É'ÅÖ8…{B솑%$“LÔh>_Tš ! µêHˆ;;N“ÝÏ™!¹å„„ØÙ½3!¨Ûb&øni–*b.¿B2UÆi"y/o8Á*M¥ý€’4%")•”ÆÇs¥¬¢×ûìú±]öv´!Ó&$³u]òìfi¥,Íâ!o§£Mf•”²ézœ(ì¦átͺÑ]vêÛ:Ò–cCr{Õ Ž{Û-FUX-­Zµøu§ð’EEBf&¿™13¶¿ Źù#w#+¦*ÛØ‘•ï~ñé{í¿¤¬“è¾{Ÿºô’ïÝÿNzß~%W»Ï ‚†¼ÿ»£òk³4lbVà® ­Æ4×`Þ‡ÝnTM6ë»oÌ^We?êF›)DÔÍKI"B£AcTYˆ¨áº1T‰âŽùsÖ|DD`Õz4Ù5e£8Ü©=.Xނܹ½Ró½Éw±ºÆ‰LKpä®2µ;µk­Ñùu®=8¥L­ñ†¦ýID«ßh ± –FÙšiŠÌ-žê†ƒABìÉw$ÄÌpÛ€L²hbBò—΄䛆â¼=!…¸H;w$Äz!͹km‹<¯LJ)™Ê8Iá¹u¤Ò¤õó6‘¦õ‡ÆJãIœ*¥J¡Ÿ¤4ÑxÂÖo®­XÐÓц˜¼nioCìíHÈSëb¡y¥Ixr;“$1^”<³¿èùÍõõ›Ç Õ½ iOÈd6d×ý–¾ýÄåGî:»ø÷Þ÷ôÿwÉM÷]xì«´23fÆÌØŽ.”5^nØÉüÍ›¿Õ›Þ³oX®*¥”(íðnW,ÕGð¸æß÷o ×€!5Iè0"IÎJhï×]¿M®g—“®Þ&ÇYþÊ/m“ãì|üUÛä8»Ÿ¼m®k·W}}›gÅqWl“ãì{ö-Ûä8Ÿ÷Ómrœ•§~sÛ\×7m“ãìúšom“ã,9éšms>'tõ¹_ÿõ/(¥¤TqšâèèØÕ7ܦqiúÅÿÅzǾã¨ó€”’pöǺý4÷>eÛ|^û¼éݼìÐC5ú™Æ²K“;•æÃÆÖ\g7ŠÕ?pk÷§”/è ¢áúgºÙdäUælH«µ¿öÚkgfÄ™13&gžyæT\(Uˆ6A®dv÷^û¹{ÞûÚ}YÑ+¤zèÞ¿]òow½øM'h` 5#Ƴ¦MbÁM¿Ë¤#)"  40`€H[==¬¢‘!’ÑXʳ( P 9jBÛÔd$0§¶Ù¤aZBÓ'$ ¶å™.9Å„ Û•œÎê(S2žmVØD¯|ɨ2«s¨”âZ3"ÓðrBhO´ &ÌÓD$òÖZ¶)½Éö„°—ç eZ‘yøÐ¦=c Yv÷ˆ”›©š©K ‹¸Ñ²Ê>, Î„˜‹Í È$¯ä„@·„h2»@]‚´m1W3!Ð%!¶¨kBBò›0]B káÒ™\StbBK‚N„°t(Šg¢ÖĘ2éæõIšj¢4‘©Ÿš°“”2•*•2IÓZ=Šk›¼J%”R¶·!M£-!ímHöþ.Y4›?þ\l¯Å¨Y‚S—gœ'7IÞÊ{ÎêØSñMuEBh'BrBÎüâ}ž¸ë‘» T=ùÀÝûÄ¥¿ñéGé~’˜3cfL1 ¥ZyZ–“±úu7À½×Ÿnžú§—ô\÷íß\üðPø’¥s;ó˜séeŒÀ¨Ô¹1dZ‡1•k'ºp¡ šˆjpÄ´ÖõÇ`®> ‘›_©µf(¹‘â-èÙ˜<ÓfëßXÑN”IšÕ»%Êní1gB­‰µltBžœ«µÎl/cd9"Q“l`¡ü˜1ææ, !$Äæ»ŽL’ÄHÔØü {á¦ØÇ.ˆí¯ÀB[Ö‚È™¥ì‡b&&DÖ†„:PBDó”$-Ik åÓb¯±=!ùÉMJHöc„Ø€Á´ ÑŽTD‘h®0mCH¡€®@ˆ½' ±’bF7„8g5!îþ~{B–Ïÿ´f µŒçrŽ¥¬ÿ!¥’y_¹$I£(Þ<4¼t†>ïÆ†@ׄtoCÚòÊÃæüü/çû¶Ú•p<»Â.&.EÑá{/}Ñ q}âö„¬zó÷³~âWàñkÞò‰cú®úÞ?þè–:ˆ¥Ëæ½úì^·/23fÆÌØî.”5 ½á ÓëÀæ’›g—­^üù£÷#¢z½^*Wk2m*ÉåÌ*j𳛕Ž]Á›Üˆ0Û°]kÈÔãZt™í£5(IÜG·;JnfÑÉ0È%³ÌfŒ=ÃÆä”MKÊw–…¼ŸµƒJ)a'•挽c¦nÜ"nŽBA¦É™qíôëVBìÄÙ‘+4!!yŒç…#¤UýÜ%ĽÏí ±=­'$ļkú„´ºà“‚ˆ}¾Ûœ ë6l¯Õëq'q’$q'i'q’ÄqÇq=ŠkµúÈèØSϬÅ×VKlÞìràó­²! éÞ†´'„1>°|Î jµš‘€r);ìãI’ŒÄÂþž`áÜžRèuCH!ºMlH+!3“ß̘Û}#Ðô¢¢l†YR-0†Z“"-µÊö;œ–`Jœ1`Œ´DÊ­…}YkV#""g°±gAMÝóɘòžx¨5iBnÔ· 5 rÁ¸0'@ ŒìžÕqææ_^-@LãÓƒ1µ…Í;ñ¸‰Snׂ…*HV6•ó(À 3PnЩ^cÝD»`vB˜äVסdŒi-'“Ñs®¨a…Í÷îUç–š´›4}B2H:B-]Ÿ‹„@ׄ i­&# [Bš?Ê"!Т¾35Bò)¶3!œsãMHHö§>mBòóï– ½CÏþíùñ¾ÞÏ÷lû9­µÊTËÓ8NÆÆÇ×®}n^yãü~/ôù.Kúºµ!öãèHH]blÈṷ̂ɯßú r¿5¾k³ ’$‘itÊKí¹bvˆ•Ëf;&¤ iq^· ™™13fÆöu¡ I­a•¬0Ĉ£0„T‡Â_¾MpU…5"C @˜nd„€4f-8ˆ0“IÒÈŠ@pR2ÓΜÖíŒ1†‚˜dŒ7¯››YŽsÓvRÖªVµÆÜ$÷«»”l5î}cZ¿®0‡‘“%ÛúqX§ÁÝk01•RÊ´s±Ýã'ldVPLµ÷¤‘´‹ˆØ´ådó…ÑÞ¼íMu"Äì'vCH#g"B KBšg¬©bR‹&#$s » ¤×\ œ‚Ó!$?ÿ®@8tu?Üýô_6ì]T)—¬Š’ñŸêQ¼yhËøÐS{,ƾª¯•\½Û híñþLÙ=å6¸TÅìFÅh4‰[Œ±w±cb4jL¢¦h¬ˆÆBb××Þ’{ì¨4Ѝ \àrË)»;3ï³;gvvÏžåž{ÂO>ærÊž=»ßóÌÌS~^¥›Vlèì!BÔ[´¸˜™ÍZþ“ns•_-Mô·0ÆHeþ£úZ¥ÙÊ·aŒgœió È123â±~‚ˆIÖEHÂÔ¨BP%y6–ðëËRB^HIRI4q„¨ù²6!ÚŽb†uª¢aCˆñ–BTh8–à ©)¼bÛÖØõZGjm[Ö £F´twwXk°½®Îö––\l@ZBjØ€”„DmH6co:zØF£Ä’ά·v ”Ë’Ö–†\†r-U?½ m- IoC¢„ôO~ÿ«#ŸÏËž+ôTù|‘Ug¤ªÈ3¼*ÕÈpôr,B ¦ÆÇµ"º?V¥Ë¢²EŒ1ÁVP•cQjaDe} €¯Üèz^%•c 0â˜l7ïn%«ÃNdE¾XÙcˆd U„.êôh–„“Lõôgc†Ó¯ClêCTh*z ¥ûGÄH¿µ©çH¯ˆN.×—ý¸bŸí1!±›ã(!êĪ•ʾ„”D„ë¹V!z‚s”?`š‚Cý²Ç„çoZßñdBŒ¨3! €õF4¯3¬am­H­6D¿_É„$ÛHIH5‚(Ÿ_ Ÿ.GŒ›ÀYxíÏÝzܺ-M-ný½ßß÷vò¡ö_{ÐÝmEõÏ%ï”Ïçõ+õHqɃÖÞ¿Ú 44µ¬3f‹ÃÏþãW.¯yzùÈXÅ—nkà‚µ–.òK®T•*¹B‹bJÁò)Dp¸B'Ø!à¨vÔ&hI¸LÈ0DEVXÚI ˜#ðWÈõxÉõ„ôä B1±0±`Hp$‡ÃL!"„l‹¬ÕÛ T-}[·}†±†p¿¡›ªX–%ß% že`ËX$éõÉQ±ciH ¨¨j¨æ*ú·Ð¥#1 %P7Žkq"v2Vq®R¹>‰„è•ù±„@JBB+«®'¢ÞK9p5 ÑëìúމYôœeXê´!ïÞ;-%!QòÕrçÁWK×>Ñuú _|ûÛß>ÿ¶¥¿¿oÑÏ,ZÜáõ˜è¨Ç6Dí ’ IoCYic·Î›¯œ·\dùÜ+néÚm%|t¡Pˆõgpwɱ;lýxi‹ÛŸ™µtùâÞr~Ûÿ’|¨Ów1ý‘êŸó®ÿ÷à¿yõõÈÂgoZ{3ªCWûâW¾n­y×ïrÈ]5OO=¥F¿m5[BéóœÞðAùÌUR$„úTW)å²6,`ì~ ¬ óœ‘ÚO#$£ˆsÎFùzt ÔÏ D „8èEæqµR­}aµ¢­¾&$4£ÇRá§!˜Z „@\J,!QÕ+0«ý{HH5/T”COÁ ĸY „¨Ï%‚\¨: Ñçø•CˆnC–u±›ž\vÑßÏZ`}¹ÜÂ4—ÏçÉ~Ö/¾_:ÆükX°´‹ÕiC’ ©iC ,C_¿ ‰²òÇå3öÿóÑ·ëÜvô5ûß|…þÈ?o8oûG576ÚxûŸÝø,x…÷‡ ·ÔãúºgÜàaï<xÿ+wßvÜÀææá£6=òç7øŠ- ÿóûý^XûWýþÇ›¬ÓJ°=jóÝ~3óåä·lzÎn\ý”úç=O}qâågõÂÍê‘ÿiÎwÏÙ¤ê”Jì‘ãwüõ}ñ÷óûîR?{ÃyÛo<ª¥©eÝw¸ðÖ×£/èøüS÷ûöˆÁ[†|kòñïtVšAÍyøªÉ;l:¸¥ií±Û^póKÑ÷.y{æVÇŸ~Ó‹Q”á-‹ÞÍXßUζ¸ä¡AÃvê`Z¶Œ³hôõæ½Uk aõ<=QþÈ¥Ÿ_¦ ë ÂzßÍXÕ™j¢šº)W¹«Ê'¯6µÒøJq^„±€J Áßhê2ÊB¥•Ê¿~‘³}‰tF [(AU›ôï«ô䥈z×u•˜^TQÆØA†ûK„$dH0ŒU”’œÖµgÔUÕ½úú0í·w¶xÙ;OÞ˜{íÆ?zô·ÛLúÃÉ÷½ý§ãv2¼eºÏ¬ÚÝì­³Í Úç’>?þ‘Ê¿øÇiö÷¯“£«ÖÊpïÞu½Ó“ï.–k@UÃT,¢JœdÒ²(?3Wm×õ>¦þK”f±†ÙB™Æ ¸@MŒÈØúþ¤,/Цø °(pÀX „D0G€ŒG`=Ù?Â!Çq=!–M©…-¿w—̶ñCRþd‡€„,Ô³Ar+C!_uü/Æ!"»‘ó7ðÁ¤bt·År[¯Olr5/_UýA€ƒ|k•¥^!BäU®IG~y|5B4ïÈJ"Ĉ¼˜}ýüëX›(HIˆÍŒ!$Hñ©IHx…ÔW„†¥~R“iCfý·ûŽ Ùù|¾)r •ÉdlÛ–Yç„O?ßóÉ¿ß[´B„hÑ·„Ô°!šíM&$½ ‰ò D¯˜±ß…'=&ÿõØIî7ãrªÌÎzèÄÇîÜgÛ lj¯¿ÍÔ¿=vƒgþö¹rœ}zÙgÿs¯ßO€k޽ñ²ÇoÜ}« ³”´¬½éÏo¿gÎ_Î]¡3zbYi«ç¯úΖlj9f‹ã.˜¡;6â§LkÈ9ëðË>^Ÿü!;êì,±ÎÚ éÊ9Ë ûëÛ¿~ö`«úÄÊÝ/ç¾vá´ýFìziÍÓ›0õÇWß÷¯EËÚ?óÊE‡ouÍ[^ðôi¾×IÞ1y«õlj¯·Õä;;iæÉW/ø|ÖÃûï8¾Ñ&4×zÀy]üÚåòñ«Ž»ñ˜Gï?d—Mò6¼ÁVç‡]G/^ò®¼9sÖ‹Çî´VÍs¨v7{ëlqÒßOû…rNþåÜçö‡ï¬r<Î=Æ\Ïs§dY„T*Ac.B"ŸÏ–ËEË"¶M=ÏQ½dC !„뺠o€¤©*‹ŽDP¡žÇ ±Ü²“ÉdüÜIB‘ë–)%ÀóÛ"ÅÀ0.<–Ïå²vFßu]„„[*"ÎÌ-$0pàŒ Œx.¹@ª²†b H÷¸ë RbQ€YàˆsĹv&ƒåœ3!ÏskhlöB„r„=!X B,›#Ìå¥%˜q(9žË¦Vsë l®¡mi{G{§Sr=‡ÙÔo»á N-»èºã†æf.cÂ!BH&“\Nåv¡è646wJ\ |C“ë1.ë1¹rp]‹sÀ[–庥Øu]è.æ1®çÉþzˆ`3@ ne(†0á%§ˆ.9eˆZv >΀cÂc«‡ CMB\ŽÇ€”„È«Fˆœ¹Ó"eª) A') ñ<–@¤$„Úv!’,è]R“„P{Ýùbg&“ÉårÁP.(µ~R{Û¶o~ø³¶¥Ý+`CR’lC‚ô¯Ú„¤·!QB¾‘EÔÚß½v›Yg¾Øá8/œ9kÛk5ÜÓV8{ãVõÏŸSh»†~ëÊŸ^úz§NÇK¿ùlðåÛ€[výxìð¦¦&y+[†lïv¿»BçãrqîCÅ+ï{eñò%o>qÓ w.ßù„G ÏJtLúɸg®ú>þËócNØ&ž8æ«?€Ï›9þô=«ù´òù|CSë¶{÷éºÇ<{÷jžÞ¿ïº|mÇ5Ø$×4dâÔyö×sNÍÓ€ÓÇUÜ`7:³û«;Ì«Eÿ:~ŸG˜Ïç[ÖñŠÉÇo]ØuÞ„Öøåæ/§|KöµWïž8,UÚxµ»Ù[gÛ2ö§‡fŸ9÷ÅPZöÔøÄÆ7¬rK(åßþ°ûÇM¹y“}o5r¥Õ¶ªÜþÅ”“žÝù„Ç ~´eJ%ºÞŒŠ*fÌÿ@i9¬r—é—>3éo*4 „oòäËP¸à"mÎdDʼn#kùõ˜¿·ƘL0Å”l Œ”B±ÜbD€`L-„ R*9@hccscc#%¶ðX%TOaTNÉ&Êr)8"„`L¡‘ÀQ"ýa˜ l샕Ü"¥Ôű(Á4¶ÆÊØ^«?¢ûW=n¢“c 1Éd‘$BŸe,jÄ jÂK DÏJ&$V}¾× €”„H…£j„@JB¸`½BˆÎI”ˆˆeW#$­ ©Eˆvߋ힠r •Íf³Ùl&“‘Î'˲T¿^=Ëãäš{椷!ôi©“ù²4„lyòã»{ä”éÕéjût×#ŸµûµQB¾)GÔï¦O:õü—_>ÿ'“§ÿަ; Dšÿ¸ç°sïøæN?oÄä?4LÀ_/ëìììêêêîî. ÝÝ]+t:[4Ú÷ÿõâm6J16zÛKïzðãûϨù®u¦ÿù£7À#.8pêHX{Ò‹žû <íÜ“§¬“ÞÝÝùÅÇïüõO猰W¸ÇNóÇ—=‘ꥢê?äøÅ®wîzæ+³çwv ]K„ÐeíâïÊV{LÊzßÏ.è}*zz¶?½~êߎ½fÿé—S¯=aUL'WÛ²—nÝ÷½‡p¹Y¥Ô–•õ‹Wÿù·£¹Š ÿŒv»ÔiBÌ>6]—>Ò;n‚Ö@Í0±iãÕºGŦЪT\=ÈHV=Õ !¥R‰"wÀRUœ»Šòp!›•êóºøúùÉ˲³¬ž“¡Ëè‹£"#úiWË_‰¢„è©ÇQBbÓ¨S›ðÑ3Bô‹°ê²"/!Fšv Q_°O Ñ—P+‡¥ì?Ÿ92u]åsRÕi´‚šýiá½–¦$D?Ÿ: Ñ?1Ù3öï¦}å¤%ÄsK¿¼ðÕc.Ú-™•ðô)§<=áš° œÿãËÔ?Û?øC~ðåßßúõÑïýö·â¢?Í>îÒíäƒÇ¬ÝxáSŸ×s2'l:ÐX­¥yW~ÈÁ›;¿¸táK;¼‡ÓÚùàœ®Î«Ú¶ØP®.]Ç‚Û2-;§Êñú°]ý½ìÃ?6 ›f¼à/ :§ŸºÏ:ƒ› ‚ÎÏoQ¹VãÿY{ÌaO|õŸ¿ýÛaßúÅ=sb_@¥~^Š»Ù[g;â;žðÕŸ¯ûtéwúãŽÃWÅ%”ú›‚oá™éï7=¹ä»ß9d½¬áWÐ wk¯DµŠ0C¥7Zw£Wë'ý-z’,T©ºŠµÎ Åɦ‚3¯xSÑœj­-Ë­îZM*ºB&Dµy‚J%õ¬ž_¯/üzu‚9çˆ`BíéÞ¥²ÚuÝØ¢ôؼ`zÐtzT>“NHlŸ8ýúÇV_×$ÄXy„ÄÞšXBtH=„Ä A8Á9 !úuˆAM\MBôk%4aÆdBÔ®&–p.]!¾°SßÒ]\úÇWžüà}»?þÄOgô ã5 ùû¬åzÂJKQZÔ•¤”>ðìgŲ׻„$ÛØ@‚  rÓ äٙϵí2qÚzu tB¾©% zÛÜ÷ߟ{[ÔuÖ•û\·÷´ÇÞúÔãÞ§o=6mïë÷ûÃY¾fÔ™;³G/éâgÑ÷~²N“ºíŒ;éê_j/zn±ã½—9ãÀíVè\öœþ³ƒ¸ø­O3Îÿ÷Í‹¦í·ÞÔ+õÐ[µ7ž·Óð îúY÷,Û×xµÏZ¯á¢g/ÏìÅKµí§=øü¬ö‚ÃÊï>{çÁ»þbò¥W¤9½ö>üñ·ç{Ü›ÿöã‡M¾îàkN3^0ePî¬Û_(zìë¹/œ4éõøiÓ›¾÷ïyqNÉeKç¿û»“B’7ûÑó¯Þüìé;ÿxFLÝÜ·šì›Þüœ§¸›½u¶€³W]²ÝÅûLé:ñŠì7Ô8×\Ö¨=^ç¢ÖÅÿ™sÙü‘7ì?$a‡ qí3õ¥OÔ’&/e¢¶[ë<ÏeÛTcoMÿŒÓCò÷—21ÓÏÍ þÒÉè«U”ÕŒ 2Æ€q$üšÌköÊN¹\–Ùª¡¬:I=š P%g¬‡ÌŒ gÙ*Kf?¨[­-×W]j$肆Ly0;Êÿ„âÕg+Dˆ±ŠRÍ %DkªŸŠ%ÄŸw«’ÿîW!D-Åj¢—¯G Q—®&!ºs(JHìb1– (ÐÄz@Èá/¼¿õFÛÜ·Ïï¾ÛÔ¦Ò%ï|U“/—2Ýëãyžž&‹nä€/íb w¥±!ƒè™ QëΚ„¨œÂ(!‹ßy󷟸aê`ý.ë„Àª7ÖÛÿ¦»ºÙŇî<°ià·^<á¼{oÜw”Zy]tÊF—î÷ûO¿@½~Èv?}óÞs_¾þŒqk·9ö„_ß½Ù±·&ä!顱ãî=lÀ9ìÐÚ2`³ÝŽ˜¿á©Ïß¼OšSÝü¼‰¯Ÿwߨ“¿­Ùù˜ÑOŸ|Ã.?Ѓ/^íôn?~Âý—4näàÃG~Áß¾óëGï8j¬|jù¼«Œ9­Úï=oÓ_ºóÀæùÕ–¿|ôª=F/¸úñk>»æè¡lµ÷ÃN˜©¾Ë%ÏÿyòÍgì7¼uÀf{WüÖ¯Í`âú“Ÿyûþy¿žtØ•7žºöÊã¯ûÁ6Í ò+$ÞÍÞ9[}Ø oþ'7œ¸Ñ7mÍ6ÃBíxtm!õSw mçܼäºë÷ÒõR ]i%úT…ÄDߢ[(cŸ­‚Á¡P—:=×nT1ÆceÕeƒ°ØÀ„ž®A1-/çœ`ÌÕ™kfQ¾Þqb[[@*òÁÅ$šè—È/JÒ¼ñFÈ@`ä1–#„qA¡~ï• ” cæ1œžq©hˆáyR )ƒ%UPmMÖBbbzFˆ>ÃÕCˆH$Dÿ¬dB„¬£ªBˆñ3L DµÕIˆú:±„~‘oŠöØsF0rˆ½ýˆ1׿1GˆQÉ„,øºŒhN.G\וËh%4*ým2ÝPuB|½´ôõÒîµej¢¶:5 I¶!> )©fCÜúã¢ë¯Ø‰„U4uBVòHÈ}ÖŸúîI¿{õ¤ßžlÂù/wD¤”ÖÝõÈ»v=²žO;õÌL=sEß5t›]3ôGÆŸòܲSzr ÏŽß㘙{ûÔÕ?ºüÔ;ßK8Ú«'þ6áƒlrð“o¬ÿý©•Øx¿³žÚffl3ÌÛù©OÇ\Éi¿{wZèÞ%ÜM}ìzâo{|¶‹_¿fÈî×ÏSø†­@ÑcщíêK^ÚãÔÆØ(êä×RÍ>ªÇÇO½¥W¾ÏfûßÚ+Ç?åÆ^9ÎØ)3zå8›|gï|¯}zçúŒž<½W޳ñäzå8éë3fòu½Äáí½ó½Ž¨w®óîêë3©—îû>Ió²;)jCÊů¯~óÝWÚ–wòHF¦¿Z l}ˆ¿aÝ~ûíó¤²~’ºYòºGJ.¡ GTÉa‡ŸÿpÚï5µw®OÈxBE —ÙlÆÂ×ߨþî¼§÷»`ß1™²áŽ5T¾úÇê;.xýóþ‹PZúöáÓžºí½‹¿Ás¨½„ŠþVusö·OŠpÙ3ú4¸ý¼sÏa±>ÿ„hËSv<ιee2™ÌòeíãlÆ"„t.[jÛ¶[*Ù¶ÝÔÜÐÞÞnç²mmmù\ã€<ÎJ¥R®¡ÑuÝM¸ýí{¦546‹E™}Yì.544”ËeJ©Œã”J¥|>ßÙÝe´‡S¦c~²À¾ °´Yœsá1Û¶™ç0Ær™¬ëº€1†˜Èf³…îRcccÙs;;;›ZšÀØI7Ì{ô8^,»º½R<ÖÝÙ•Ïç½²ÓÐЀ©ío8Ànçs.p„‰ÂÆÄsÜŽeícšËdr¹±Sf̺ó` ÐÜÜ\ê.ttt <°\.ËïØÞÙnÛvCCÃÂ… m‚ T*9 ÍMK—-ojj*{ cL‰å8Î&ûßöÞýÓ²–Í9‚1‚c;›‘¶U€Tf«ìÒÝÝÝØØ(¯$„XÒŸ<~‚¼}®àœs˲–/_žËåTðwñâÅC‡€b±ØÑÑÑÒÒ‚Œ{ŽÃ²Ù<¶èfûýeöc'Šå\.çÏ‚H!0gc§Ð½xÉ˦ù††††F„P5B6šzÓ»w’†°çyÕ¿Ïô?% !þ¯  !£÷¼nöCG¥!.ª2áÇO̺aJBlJÛÛÛ«²á¾·½w÷iÉæ2…B¡!ã¦Ü<÷±ãÒ¢ÿÀ£„l²ï­³:* !±6䦽TØ`ëÛoöœ%KúÚëQ'¢Üõ½u×a’®xOu¶‘ÎÕYEÆõäb F‚Åâº_ì¹íÆC²É6dÌ^×Îyä„4„$Ûu÷¼"ma|‡4c®ëÊtx›P„¬N"„„9øë[>ꆳÿªoÿGíyý¬;æqŽÃþÑ?VÇ‘ÏçIfØÏï}i»&{Õ]B1×£”vutÚÔò€ Ë¢Ëö7“ɼsÏ¡ÅbQjû …m§ÝûâÍScÙ†¼4U™L¦’ö„dî$WNïL&£ÌD©TÊår²ã„eYår9ÓÜ(›@Ù¶].—óù¼œêä‘eÉ’|½rMBÊå²Ú˜Êª7•HQ.—従"?E¹Ó<Ï“Iò8žàÂc€–þqÆÅX¾Ëó5d`†1ÆÕ´!Ô9Ö$$Ù†øÁ¸„H¶më„|úĉÝ]å®!„Q´Õ¡÷|ôȱÝÝÝ:!ýspÿXFÿ­"S5xÑ j¤YQ%Á©=‰Õt‰v<06—FŒÑnBOõ0T°c=ÈHO®æ`Ó¨tkô½,ÄÕѨÏBú…‚Joy•ó¡÷©Ez"ˆìK_)Ì gÙ†t³ÂÍ \ºetg“Í\e*kµÊ5£t(¡ÍYlRÏ©¦ •@ˆžTKé5 ÑÞûŽýŸÉ„_Í D¹NB*Ç©Eˆr0Çqyú= Ä_L¤ $Ö†LÌk>k+ ±¬{éô9 \ãKÈðH­“\×-—ËŽã”Ëeù‡Šâé^(UÀ8°@sC¦&!j½^§ I€?Ö†@s¶B„ôþÑ?VR c¼Éþ·ÉG&8Þ¹çP½ÌXÿ­j]¢„L¨TV€`s 7ò«8ç²Òâ¤9ç4¢ªˆÁ?Ư>…§UCý¯FÚfÇeË+!€‘ÀH Lp)ÄŒÔ÷Œ¤Wæ-,€‹Ê÷•FB7¯Híãå,[ÍüI߉ÿ‚ ½)`ݬ#÷õåUõ‹¶U6V·É×Mo<§oßU?yƒB©g×"Äp D M› ™,«’f;!‚ÎÆ „@JB8ç¨:!ÆB3#‰Þ Dþ‘†ã$ûˆy2鉱!§NÜúâ7^Ÿ<«ÜmÜqøXøtNMB¾¿õ€f/‚ ÛöÔß«œOr½U*•¶ßtT.c­¨ AõÙЊû™pò#òÅëïÿøàá£ÒÒ?ùõþÑçK(5f?x¤Ü8:Ž“Édd·}Û'¥ïÝshw±(ùþ¦w†¦I5>…sޱ41‹ª|”Ø]²^°#ÿNð+@•®*6á?fO°:ÔUDÔ'Ýæç2½ Zâ*ÂâÁ—Rûuõ½0Æ"àSÉ°Ê ¥{_|ïBà`á½I—l½køL/eøñê~KýZòK:!”äºúŒ^“Pã¹ú‘íÓê'ÄŸª¡Š³:Ѽ˜É„È‹Us#Q°÷Â$$vêí!èªFH¬ il^绤”z¥bÛÒ¥'¬ÿš„ n¶6eÏ^à+YZ*ú*J®º”Ĩaö€¦ÌÖ|BÔJ½&!5mè}$«2ëê½Eí†\¦!ïa@U™ûȱþGk„ôO~ý£ôy Oý°•¾Ÿ’h3ä@ÐÓ̱[·¨ñ·ã8¾Û@Ó„TûéèééÛY™B«› C)*Ý©öØ¢ˆ†¾]¬cÉp°'(ÜèßTDtqŒ­¼ªŸ­ÿ¼{Š&øë³cň£ÏÿÑZ°Ã¸DÊF‘© ï©?SÊÿÕCHôÚÆKKÏQ:¥±„è慎h¦!F Ð "âŠÕÑ%§c,S:í! 5ÓM&„'¢âŒ½eCÒrä#/™ãz ¹ú¯|Üq×)ì¹ãHXwxs"”õÛ„PrmH”þÑ?úGŸ/¡b¥Fú‚²­ºœGF‰CŸÿôíTº‹.A¢Ñ„h(ÁÈG‰]E%lŽtØcu±£/02Ã*I2xT¥rÄ’rÎ¥T±òyT¼PAå6h¹_jÕ¢OÁ*GTûšQ]SÝ UmžèuBbç‰Ø $ý(!Ѱî!Õf—(!±ÂžÕ&³Bô %$v®%DsoÄ¢{}’ ‰zÝŒëÓ+„@¸‹@ý6¤&!¡a­ÙÃwX(¤”¾RC=î8NWWפ†hά5¸!›¡+jC’ I¶!ú“ IoC¢„ôþÑ?ú>Ç9pŽBÉj)!(Æ2N ÿÀH¤sΨç!Dd‹Sm~@†ã$²E3f8•Ô¢«³¯>!9HxÒ ×+Þ#-¯ÓÏÒË…´ÖZéÍÉ•Ÿ"3XFŒ1+›³•‘+íoƒ4¨Ò¨D?¦žÔ¬fiUUt5ôß°É6䪓XÉ®èr ´VР÷‘­ƒˆäÓôŒ}¦I&Dϯª‡à3â Ñ¡M&!Ä«zšp„(ïNMBŒèg z³Ð(!߈ ùÖø%ßúô—ˆØÑ¶z* ÊqÏ-î³óZã7hÍe¬1£¦$Dy‹kRÓ†è7š÷ éŸüúGÿèó%”ÉÿA¸$!$M/×wœŒ1ÂcsŒ1p”Õ, ¹­ü’±¨~ßõøýõ È hÊì´õ: 9º6 %!É6$XÕ&$½ ‰Ò?ùõþÑ÷^( V)ú•¢#¡\T ü=“üS„ !Å PQ )>äv…j¶sÁU:Š1ÅXp!@U8 ì2ƹÃÃHº”r4„›O !SPÅíR –ÎíJÅx8º‡ ´BÝ=Ρ’äáÿ¡.­Š";“‹YBÎ=ybžç‹p‚0€¬‚æ0ÀJõ ¸àª_ç\0.(EÂw« „¤l±j` Œ{r• UŠ $@€-¤…!.uWpßq¬¹yoŠYsŸDˆòŽÔ"D¹ª) ‰fÅô!ÊkX“ (åx«Iˆ^ Gô!ZU=6dÜ>Óßþë!© Ûu×j^wDë°¨Ì3”Ò/~êÒS¶0` ë¸˜†ÝÃÒ·Ö IDATpÔàÖ&J ^A½BDÃåuÛ(!ý“_ÿè}¿„Ò’$”ÖŽŒhèÉ%jâ”›{)VÄ9B„ì» ‚ù[XÀUØ>Z],Ÿ!ͺǹ2+2ETO;•-bKÙ!\,D(9”d€_y, ’Q[qÔG²+b›ÃQ3ˆvwÇ(×çž[,92”à8ŽmS0’çƒBÄ·¿ZÙ‘Ô¶ñ³ dú…[‰L™…B±œJTÎ9¢§J©0ñ"¨(z‘7: !zÕ}”}⩇€Þ!ĸ} „ˆH’N`Jê'Ĉ]&¢nV,!ú«‡uûzц$µ! Ö¸õ4¸£àÀ#[š›› âCZ36Éd³¥RiEmˆþ“ï-’LH=6¤òëýce,¡]ˆM´PO ¬0®¤SƘW„û àbKÞdGr„G@‚ ¶Y/Ì­MW:Ž ôiÙ LÜPõ ŒW¤š*8ç¾°‹/Ó+´Â¢hNCT'In3™Œ ¨X,J§ÆØ“rÞ$œA*¾cY†1æÌSOÉÞv²Éìã‘PnL„zÑ„—ڗ髥߸â—º ¸ÅXBâ*™þAÑ«KHHú'Bˆ~©“ 1d¬ B È©ªIˆ‘Ùm¢&éš„DÿF]Ï-W웵!–E†¶Ú°ÁÈÍÍÊå2¥¤Ç6D}‹š„$Ûuýk’Þ†D éŸüúGÿ¨Ôø!¹<¦i”´Å\ø)¢\¨f,ÒìÊž ÑšääÓe•… ©*k/‹-0‘§gÔù‡‡®Yñ“G/,*­fdzfâÖµÒÒHCn<õTÉu<ÁeŒ ô^. ‰©™Y­Ñº Ĩ˃K_‹Ñ$ªËÀèú{Ɔ8êH¨–D\!ÆÍM DE4b ‰þc Q‰}Jˆ„$ !z £zÑçï(!ê ÔIˆ¾K&Dÿ;Jm­{ц$’Þ†ÔCHµ+¹¢6ÄXVö!ý“_ÿè}î…ªütÃ?¹¨~’ïGˆƒp9cLxžG¬À@Hø¥7Hļ0!,Ò@J_(`QqþC¸ÆX øÆ £J—î ©øÈ!ÂÚÖ#„¤a’É"•v ±—úÅ©ì>ƒk(¤Î2lÛ¶Ç¿g­¨Îˆà”RbѨÎ< <cª@`f9ø]³Â加õŽÐûëE5õéPw9ô!2ªR“yYz…¨jWˆ= :‘àõUÑfÓdB”S'–5ƒÖIH%ˆS‹=§0JˆþuV!É6$X\9„$Ûyœ4„Ô²!ºªlȪ<-½ûî»ï¾ûîš6O˜0a„ ±OÍš5kéÒ¥kÚimmÝb‹-Vï%”ÚÊ–WÿÛÏ8á ‘¢0.g2IÒ·;ò?¡ .»è¿jBˆÀØïô±’þ ª•1&OWµÐímt‚äœËB`îKV, ‘%úÚîVV¬1jáY­;¯1…ÈG2ù²)µh&Ÿó˜#ÅýìŒ-ô‰„fîCÙ©Ê2Æ”üÆ¡ ÒpƒéûrÃkjEûèéÞ)É€Q‘©©ô«›Ý£> Â"Š „D/¾N9L5 ñ§÷*„K¨B¢JlÑ%ÂJ%¤† ^!ÄHè1!€°è]’LHz%d_?M›6mM[1Ìœ9S.¤b×OcÆŒYÓ.ȼyófÍšµŠ¯¢j7xQÕ".¯ÈøI¸ÊvÒ·À*³X7yºvKåíÈÞËš#¹ÒP"ŽÆ Œ”IËåÉžëúlª;ŠŒ…—ÑKN߯6›‹}KÔ™'G&—¥–…)µ³bYçžp©Öý© r^TñýëDr©ÙK€6æÈh¤) :•À_O Qkôš„•KR!Q‡¥NHÈ’HHtÄ~tMB¢ê:!’£Ï‰ADºÌV#Ä( 0ÞUr˜V”Ðt¡zˆ¬B’mHì}ï ‰^ÃúmH”Uy µ®Ÿ<Ï›6mZ¬ïmÍ\?qÎÇŒ³êûÞj5x!„ÈçóÅbQþêššš¤Q¶,K©†\8/‹ÙlÖå €744d³Ù\cƒÀ¹&'`Rü—s1ÖÙÙ™ÍfåY–¥úPJe„'¸ÀÈÊØ!&8¢DïªR†mÛVVêtË. *“Ô²ˆ4yžçÈw•Ëe!„ç9ÜqJú¿\HYá1µ}‹RÎüÀ“*·,Ëu]Ji6›•Žz5WÉD/`Œ•Ë厮N`e3.óB™LF~—®®.?'ÔólÛv]W>ÞÐÐÐÝÝ­~`dz•Ë妦&!D¹\ÖÓE1ÆårYfËJÅ#Õ’Lïêà8ŽÜˆËw™t"ÿ)}*~áü ©sãÇׂLŽz€4„8ž‹1N R"SHIâ"åÞ¨IˆzA,!¤æÔ$D6-©Fˆº¡5 ‘©FˆòŠÕ$DÏõ‰¢ÊuÚHIH² €”„$Ûy#Ò’lC”é¨IHz%¤?‹e•Z.¨)£@\ÂåjÈ“eÏü7ß·öð1úÞtþûŸÜòè‡ÏýgÉÒ’8¨y»m×?ýÈ×R%µ‘­ˆËü }ëÆ9÷8'œ+i©¤‘æðò-Òèá­èξ²'ó“3¸±ùƒ¸ä-p–”f«T~Ý*•}ZB(—zÙcðëeôŽrúZ'Á½¸äÕ¦)ÚÔL¦Ä!C9B¿2ÆN½šD]ˆ8Ø!Fï#ƒU „À0RâOùU‰Þj„èIâ•LˆL±®F„ãn „!À¨ª {\V)BŒ`Ï {¡zlCŒûžH_¥ÙøÈ{ä‹_Ÿ>Eÿ frëãsÿùÎW‹ bÀÀüöÛ>çè-×ÎbÃ¥Ú?V‘õ“ã8ý×au\?Õ^BQêg#νïðîRqËi÷ªý“œxçgï:nï)hôÐ â©'_?ø\ç¹ßM´‹ÂQ&•1¦W£øR4Z§§hàCþìU¡²çyjßi\ôŠNœPEQ—ÿSˆv›ûA0?ù&a¹½¿>žç5É¡¸O¢ëÛD˜Œ¢S¢ ®nèÚÍðù¼ù/½<{ÿsù«Wo«Ò?U¯"ËÝõØ?¢žÕ;‡1–‰@4_½¦ìòÌe»¶ËÈuX ±¥ñ‡‡î²ü³£[µ·óW—Üè‚=±%Ö†Fm¬Õ26 Zý¡º—Cb®’¾!0štÆmµC•k2 ¢4—õO4NFÖ!3Î¥ÿIæ T^Ñ‚AÊ‚ÜUG“WÔWVJ‰ÒþFÏÂýÞ£{ÐP¹Vœ@@ôú•k!Lpƒ=«F—ÌIOˆòÁT#ĸû „o7Z  ™'áʵB¢eö:!êR'!2x”†C¢=–Ÿ4„)8! I"ÕCˆ|< !É6ÄXöŠ I&$Ù†gÒòËw?æ{ëo0(‹äšó?8èÛËçÏ6韪W…µ‚ÜQôýç³zpÂ1¾_®\Œ1ÅÄ"cÔÝÑõÈ=/ ÞdK)—RM-&èMæê»äèÞ+Ú7ÞØ¥E«‡ ,é8ÞYrŠ·ºwJ‚ÚdØ>™ä¡’J%‘9"†r1„ëØ±E%LpŽ€ Œ‰m1¨“£`‚”µÝщYý­29ä-P¤ÚªªZtã›Fµ¹õ(vIÚ{„àÊ4{ßÔ+Ç;¥w¶Nº±WŽ3á ¿õÊqFïÛ;×góÌì•ãlÑKßkÂ÷öÊqvûñ?{ç:ïu}ïü.öýK¯gâñõÊq6ÛÿöÞ±?“{ÇŽ)?–ì`(8—Õ‘ÙlY–ã–9@ƒ%”\}-KŒsþß'~\ììøøÃOyøí#óÑ oTiø¸æ-¤ …æ|1÷?Ÿwä.‡ ûྭ _üòË/ÁYÇ’Ï_zìo?7ìÝFx=ºÿÇ{lÿšiÅ–P²$Øßõ ‚§•Ï€,BÀ[·œyÎî7ü8À(¤KÁÖ›éà V9Å>z|Ç’e–e1›Ø¶]êèB5neŒ•;»›²ù¯Û7¶4 ÁÊårÖ¶/Y²ÖZka‚0"²è·½cùv‡ÞûŸ°,«­­Í²¬†¦Æ®®®ÆÆFÁg®,TÁÇÉeóg¡®îb6›e (ÂŽãÙÔÚhÊ ó;Y@¥ YFFòÍSgçò††¦R©P,— $GBtvv677cJ—wvX–•ÉdFïuã{÷ÊËn¹P¤·,rÙ®b)kQˆ‚(vÚÚÚò 9.D.—kli)”ŠÙLÞåŒRê.,[Ú6x`ëFÞþßÇŽï.B ¹l©P\Ö¶d@K‹M-"“±>üïGëŽeYVgggccc©T²m›sÈçóeÏíèèhnnæœo4å–9ÿw”¿Uœ1–ÍfU·ôøùªZ-›öõ ‚0¾Þ^7|úĉòÁö¥K›ššJ¥!¤T*ÙÙ ¥–ǹmÛ…BÁ¦TÒÖÖ†ÛÐÚ,°pŠN¡»{»#~÷îCìl0*3NmK0cL1îjïèj_N)mЊ(á,J«2~Ò?t|B,B­Œ] ÜñÎ}ÓÒâ÷-®BÈèÉ7¼}×!iñ×-—«²ÁÞ7|x÷aiÉäsD5BÆxÇÓÚ9 !Ë;«²É¾·~øèñiÑéQB6>àŽÙ™†ÁQ®!_­¹ë囦¤!$Ù†l4å–Ù™†d2nïé>vBB’mȆ{ßä/¡„ïß’j˜Û¶AØ í1ÂA.ãÜæòúÀ„àãAÃZÎ8ý{·ñ$†‰5Ôx¡ì‘ãwüõ]7b/€u|þÆÏO=ãþÞëp­MvÚoú]×nÞd@ç'O~Ú¥Oýûýå5~»£Î¼ô¬·Jx|ßm´Ó¤ço~dÝÇþ÷‹XöÉ;/¿5çëön’mZgÌfßÞvEÜÎ/½ôÖ‚EK]Ž[‡ŽÛl» –>-µŠúêƒ×^™5wiÁÉ4 ÜpÓíþóÊò©3fLÙeë7Þ›»xY— ö µ7Øé;;´Zÿ³¹w5¾µ- “És\°)uJEÆ=„Á !ð<·¹¡¡»«3gYà:€)rœ]×å‚9žƒ)ò„‡E„ºãl++8ò‚’ÆX&“±mÛŒ¹à 0%À8sÜl6ë2 °{¥2Å0×Î(àÌsÊ‚yù\0×)66d36žcœ{nYê[í.“ÎîÙvc \—¡@²ÏWõ H`$0BcÊ90&„@”Ú¶msÎ ¥"µmL)¦”ƒÈår–eq€M-×u‹¥ázžp¼!À¸Â$,+ÛØÔY,bL@n¡d#"¸gS̘+°`Ž+í¯ Ä`ŒmÛ–[RùO©S.—`— ‰ü/ìrÆ™(J‚ÁT…BH¡P g™\B-Ëõ<Æ9&DÈVaˆ`L "~1Ç9xœ»Œ¹Œ™„¸,™ĸp9¢Hi)¹ŽeY „@JBlŠ ´„‘@@ZB,B€^!R"Kóª) ‘ÿ«F¤$$Ù†@JBjØ€Ô„$ÚHKH² Q1Üš„HÉ„ Ķ Búý°ñÞïzÎô¹_.i_ôáÙÛvÀA¾Ó÷¸]mÞÿÂY/lÿú³¯9³í¡'?¾š á9eÍ€âÂ×}³më½~tþEŸÆÑë:ï?õn—œþž{è™ÑO9÷ç—\rÑ ïe/~µµ)«yеà¥'ÞZ²ý~GýòWŸvô”òûÿPOÀßg—·Üý ó.¼ø¢ŸŸ¹ÃðeOÿã‹ FkèÊœí–2¶ X¥T™ø}~óê³.ïvðÅg‹/»ìŸã¾·½l«í³Áƒ¤¿­^ÿÌ…ttQ„ „¬õOð“H#„È\ $€`À î1ÏAH@ÿÃÀ1ø]ßdÖ¶T-é4U []·@Ùÿ?™Ê*™"za6AËÇ0âFàH ßqÆ㈇’ ÕqˆJ^A•éTy$zF‹®‰ Z ”.Hã÷ÁкÀFãô•œŒ8õvƒ„Aˆ_r#áw]Å"³H „Kµ¡ê„€J3ªEÂ"•5$’@Ê âgW! -!²‰Gý„¨cÆ¢ŽV“}D HKH² €”„$ÛHIH²   ¥NBü—¥ DÚ¹”Ô ™tÉKO¿¿¤Û$ÄÂ/—]ö›¿Ûcgƒ5tp÷˹¯]8m¿»^ ŸÏzxÿÇ7Ú„æZ8﯋_»\¾êùöÒáì2¸)Cìü˜­¿÷›™/'?¾:,ŸD¡cñ[ÿz:3hk™bøÞssvØÿ‰ëXüå‹»6œ¸Ç׳^XwH¾,³¾³]¶ÜþÙüùËÊxÂw~H‡éûÏ‹m~Àw?tÙ¢/–¬&o®?{àɇì¼éˆ®% ?ûrñÐ;[XøÂÚk·¬¡<¿ÊƒÑûÜ"Ywïé0çÃ¥!øã^­WßýÒO?XVàxí­{|o»û¦ŽÏ3µX`$¤,8ÒV¦ÒRƒÞx\庈 Ëc,3Ú•¡÷„´ ¨ž¬[×­>QÁY¨VôѪÙH¥ˆzž¸Rl¬wÌð' ê“*¥Aeœs$;kó™>ÍpíĤŽ!cŒ*Gµ²y½ìYunÇARZ!bõk^Eˆt{xŒÉ0¡^ *# ¢éí „¨XR,! åá&"ĪEd)ê$¤¢»Gˆ\²¤!D¦uW#$™‡ô„HÓ’lC œ¦Ýc"íOý„ȃ×Oˆ2‰5 =ùùâ]NyfÝúIÈU{¼êöž1gi‘ãaÚöüîvý` a²F ™QŽ0|ƒïL9æÙË…Eÿ:ý„_>þÊ{K»Ê€‚ôÜŽÚö»ã·Û÷{OÜn›wûþøáùäÇWåqî¹çV\&tÐgíÁÊKàÂëÞúÇç558„Ý2ÏßyÜÐ[/ÿÓë­5dèá#FÝ‹v‡"ƒ¶þi·ÃçǼ®žÝ´ÁúòãO»˜>ÇYf´¯‰K(ÿçÅ܊Ŧ¦&*Æhì6ã¯Þb,wÜE_.2dH¦!Ã@ððÞTÛbQ#9]Î àyÒê€ôÎ_ª…–ªKRâ7ƶX/ÛMWF¡¿oábÇÜs–.šÿòÓÈ×ÝÿÔ‹ÿý²­««kiÛÂ÷_ÛÛZGèÚlâ†/Ýü·¥E!DWÛ‚gŸxE¨–¨ç©’ÜBÊ®§TÅ©…sáЃB2{CTH ÝÅÊ5âD‚«<¹3ÞRMˆcŒx(Z›âw„xE‡‰@™AÚ>ýɧ8B"Ë4X}öR'éWÁ`$¸¿ ª\4™zB)Ü 5vˆ,t Iyü„ß Uc̲¨>[΄Jv6ýyt9M=aE%•G/f"¾BP B4Ç@]„„gîdB8€¨N¤$¤"HGˆòÕ$DÏ "9LCˆR¸Ž%D]ç: ‘Ç©ŸÊ­6$øè4„Ô°! 5„î%¤ÀÕ_sðáG=õ«–têLøéTùøÌ·¼ä²NzmŽk˜°ã¤»žŸžüøj4Ö›¸á«U,Ë®ƒ-Ê!XÊòîdš IDAT/CY[~;ùu¤Àu]Á˜mÛò¤‡ ««Kž‰œ–2™Œã8Œ±ÆÆF¡-›Í–ËeÀÒç*i:å{åq0Æ]]]òYuûTÈCº äaÈ‹úšõ¢îl2!òÊô !òŸÕ‘ß+ !Fi›Aˆüˆ4„ÈãT#Dy k¢êÑb €”„È»_=A§BdSý6D¿ï+‡d¢G9“ ©iCÔª7™ô6$JÈš³~ZÿQ´ +/þè¿_ùÓeaù— æ4oÞ¼yÍÿ|áòÞÔ-Ÿ;ï£?ûbQ·Ë£=üüÛ ,øä¿½õêswLbðf; Ö]íÓô„YMoq /”ŠÐc-`$¨¶÷ò›H©0<øò?p¸ €¸fbŒ ©ã'‚–†‰yLµ…’#e0Ši¹jl¿ R5õ‰Doœþ}¥yuËÂÈ2À¨ùÇ$X ·TN W’LHOäSƤÏ¢Aõ²çyj—/­¡J~Š–V©sÓŸ2š°*W‘#"g@}ÇÍж‘_9„„ª#„(ïHMBª]±Ø*ª•@F¨WÉd2½Bˆ~A¢„@¸®³Ç„@ÄiÔ3B Õc"ùIEÈʱ!Ú ô!«×jã2«ž¼þoü‚|k8홵—¬|ózãw:jïKËÔyVÿƒm†u·Ú< Š ãR1‚Œ’fÁ¸|¯ÊN­˜ ­Mž´wLp®‰¾ §ò½R]Wn|ýæ$á^¹º¡L [&“ìŠ7 «ÚVú»@!Hàg.“ºäª2c $ÈžґÀ¾9ö“m-êyžã8Ô²Á(88B¨\.Ë÷ÊÊ2•D­*GZ…Z´–;êÀGÈO #@$@ ü–òÀýHLCáBåvô!•;›Hˆ^_'!ú©® „ dBÔmªEˆêÊÒ§„ȉ¹~BÔäQ§ ñ×Luâ{ûê&R)jÖ&$„\/ÙXBV—õÓjç3ëëUÔªPS9dô–ûmýýaƒdlÊ=§kùןµ•ÖÀ:…?$=Cù–Uô/ª,ç§Hë&-¬´eKå\jY(ØòBt‰j¥BH/wÅâ„7Êr÷¦| B¶PÆŽ9jþ|ÙðêÉÑ¥¤Ú=«ãËmeEøXr¬6ïúò6!š )¥®çAY Œ #²„ïPuõ¹–e Î Å#aE}\´)|Jñ’ìz²Ž¡d]mÎè1!’ú ‰ºRªb¸Fúˆå©IHôô!†»(ðé+Bô9 "/{ý6ÄÆ­DB’mHtáÞ„¬.+ ¹æþ+´Z¥rÅåmŸ.o[öµyJæ’±ŠDÄJôêÿåœs×#ÙLÅ’j(D%é¤ ±q5U®¥îè®æ!ˆµAÆFUñSy²¦Fа‚…`žçPJ1J1B‚s/¶èÝ <ô7 ¹üÿR’ÉdºËR!P2°6?^.éªLKŒùyÓ–¥käTÛk/Ÿ5OhJT ?òzQ$™˜|Øž›K3EÕ&D&MÇ–‘HHåÞÕ"„s.ßÙ§„ô!òÁúmDÄúšd¢Ý¸„Ô´!•KÝK6$JÈj±¶PɲÿÛ#å¢aÍÑôZVQµ¼è ¤²M„»@Ì`ŒyØü1ÆlB,B1Æ‚W:ãqÎÄÛ2¹AÔ-£^Æ ~‘vEèEMF1¶.z$´sfŒGÛo Áj:“UÖª>EÒ;J/"¾1& Œ C€¤w½€ºä—êyêàz£Ïó,‚åM°VMÔþÆVžG—w±êA†6O¢Ž°Ò‰–ë²X½Bô !À@¤!„1Fmºº™ûoÖ†€&€—LH² _¶ ^’ì± ‰²ŠÏL2%`͉ÉòšäßÑ¥‰ºº8Jk,¡dL%'cBˆ+B;WUõëÏš\*²xžÜß,rΑ_ȇzM­o úƒúS&*?F›`â[ã¯6]©Ï…°Q6|`²ê%úZ£m.¤ð±^]oH†V.Áˆ`à"ð´ÈS¶m[…® œ+u“åãŽãdòPÝIc¨¿T Ĉ a%, R Š}¯^²^?!AÔ¦!*¤T5-Õ$ÄPÊ1 ÑÎy!D¤#D®«b8Ø ;É¢„@zBÔO;JDƒzfC@¶aNAH² 1–P=¶!òÁú ©æM¯Ç†Ä²jŽ &Ìœ9sÚ´i«QÂV¯Œ™3gN˜0!úxkkë¼yóÆŒ³¦ÉzÍ›7¯µµuõ^ByeÇ„[œ»c.&€qæ!àXp  ‘g@ ÷yžœ Æy ¯gÛ6¥”yntûʱàÝO !ØuÈÆ]Ï«äkWf8q|Ÿ: ÙaÔXTæŒê=LTá´,:“cŒVÍ;ASgˆ1”„€”¿“­*„6±aÄ@€‘'¸,R›i-Õ¸¬ÐT‘åf\/ è¤hèé%ˆÓHEœ¸Ðªà²Ÿ¼2òêÖCˆI-BT²K5Bä|™†Œh!Ð;„@ BQ'!¡»“HGI„¨ƒÔIHlг„gný6DzûÒ’lCT˜¯6!‰6ÂÄÛèª~%dU^BÉõ¬ac„ ±K¨-¶ØbÖ¬YóæÍ[Ó.Hkkë[l±z/¡²v p]W¶Wr½bqYç°aC»» °RÙá˜"Åb‰Ø™eݭùÌŶíy‘¥–Å9w]·©¡Ñ"ˆbR(²6-{e  ¥NÎqÇ-aJòÚôïsæ Æ0FèãY]ýàÿœ½”ÛöÖÛŽ¹ô´Ö¡Kϲ@¾`‰ƒ±,‹ Ìx¥q•áµF mpy$#›qΙ¬ÐAH`@UûŸ#Œ„9,0Œ"ˆ0äFÓEõäe°Ý"*¹®ZøChHÛ';Š1mÇÏApкUDfü]oø”嵌äÛAÖ@F.ÅäÎ[¿nz2/ñÁÕþ«§§Ä^–h "VˆURÉÒå\'Dú(0ƘR+cË$Ôg¥#!Ô+„’xB .á=ž½=_„uOk"õ"«ý«"?h" %!É6¢Ò }LH² ñÿNAH² ÑÏ$™1{]/ÿþ艓tBæ½ýáuÌynöR‘Éo·ýØ“§ o¨BHÿèý£žQ«Í0¦ˆ` xöÝÏøHù“v`’ÃøÄ‡¾Úu¿ÿ>ã G/¸ýü _}L³+]2z‘yl4AY®å4(‡|¬:H¸F ׺^¶íuˆâ ¦ò@õ¢ëP&i¤¨þTåY.t](5ôÌÖØ¡b@‚q$*²RÒÙM¢bÁ£»|+ QbTsµmDÖlÒ5¥ÚåeT×J&F·ÎÑNJ—ò‹­r¯9;&‚)I Çmýk’à0[aBd~rÝ„iæQ°”„(G,!šDp!W¿KHE‡)ލk§‡„ô !±ÎªZÕCHp¿j’lC¢^¨zls–a+%¤ôþ±2¼PXp€@@”›šs΅ǹ\`÷ÿþÅ&MŒîó””-Eõò]cÛj솴 Õí5p1j¤£ÛëèÕ˜!b·ÝÑ­*à˜½/„Õ‡A몑°–ÅÞRÐÂM$”ã]Æ/ô ²Ú~½š·)ºÕŽõެÈì( B0¦ „Ñ·”„ÄÞÓhÓ·4„T;ÚŠ½Îñ>ÑZ„èY_õ¢š¨ô)!±Ñ¨XB ŒAˆꪇèö g6DÏX9„Ô´!êsë'äÿþðÂèïn%¤ôþQÿ¨™N^Ù¢É!ÿÏÞy‡IQ¤ ü­ê0a IÁ@ñàÌ'wžDÄ€áÄ„"*èwæp'"zg:9³"‚ŠY\ÁæQjð=s.A!a5 Ìì¥øÂñí§^ûÇú힜ԅR—Õ…ä-]ºtéÒ¥•I±R~ÁErö|ë­·êêêô_iß¾ý{ìQô*»o&È×s3µ<ÅÂF -ù×;¼Açÿã·íÍŠI/nÊ5Õl …²aš—>>y$‹–é²víÚ·À¦a œnN%ãñ¿]µå–]êëq“ÉäÊ•+·íѳ¦¦¦¡±Ù²,¦£ÞþðÙ+Ÿ="H§Ó¶7 £¾n}ÇŽS©B(•J±-Æ8•jŠÅb(óRá{¸Œë†±Ã¨{>{îtD‚…¡p Á767¹®[][ƒ1nlØP•H666ÖÔÔÔ×××ÖÖº®ÛÔÔT[[‹1îqàí?q† <Ïëܹ3`ŒœÑs2¶m;ŽÃÉBBvbíÚµCŽ{xÉ#Ƕoß~ýúõP2™lllt]·]»ÚuëÖuèÐáûï¿ïؾC,™hJ5›1!ä8‹¶ç¹¤±±1Y]eFßw­xvyj\Bô2dÛƒï^ñäIQÑˇÌüäéS¢¢—!½†ß)鯸`D!P†HZ4„ÐûO½4ñyü¯[ÿ«ÿÙõ;•-ò—Pãǯ̲•ò .3fÌàK(¶~>|¸þ+ .|ë­·ÂVQòLB#lŽç@²¦:–L`ÓðdÒ.%èÛw–N| fœß¯«AB¶iñ ˆq\D(3èÉ4§š6¤Óé\‚ì~ÈÏ›Ÿkš& §ËÒp²Hÿ©TÊó<Çñ2jjÚqÃJ©ç„°Ð)ìGCêQQ×q‰ÇòRùË Ô#N&€šö<—;àˆ¡‡Å£%ÖH˲؉€iš×1,Ó£„µ™åŒ`ñv b‘uVLë‘[¤ú.Ö¾m,xŽC\×@¤œ ¶L`1ʉ‹ÜãQ’¨J²‘df¶†m±9žä²øË¹™,§ŠõÑq¦ÏO¥RüÖ¼…¦iRJ™ÿs"‘`²ïJ¶ !ÈÀ*!ìé;™ âœÖý‚„pÇÃ0B "!ÙS’`B "!¼Ú@B "!lTK'„å÷#„ñ…t:Ý„@DBô2òsí-CÀϾR˜½ €ˆ„èeˆ¿íŒLˆI>!Ÿ¿úŸÓ¢¹7 Ûœ@B*¥R~å%Êú öÙg¦ª°‹ '˜{™†aùƾk—/?þ±æ®Ü¹»…€¦Í”ŠqY,ËsBAH˜ãœNšÉÃŽE6M›Õ“ a——Ý6P‹ø·({òÌQC, T«ÑøZÍV!‡¼âVá‘‹¹oè°ÍGLÌåÎ-'¤È=LEÏ}¯xŽ0žÔ„d«b×4ÞCb EòÝ DBDˆ8€2!Ân¸B ë‹T°ÀHZMl‹ è¦@Hî…á^­JD%D+CÔxq2„özBô2„¯fJ—! D7h!?}üÑ 4͹yïíb8ŒÊ ºY}nÊEWì†ê6ìú(_?¬Bh÷+WFµˆRð Ïÿ<ò^ÿ(ñØG`Ñ}‡#ÓB†yôUKpèÈq_ñ¯üçÉSºš~¼8žáË4M¶ùf®M,-”‰±r*/´Š¦ –eQêù ĢÍ`läÁy’bJrþÀ,X÷nYy €4¨±í»j̲Ÿ‹>ÕB®â“…¤uh¨¥”!@ˆІï;½ü7AÈ™%yxñéÝ—dŸ«‡%—ç­û½ö€=I„rÝ@˜6Ž6L›6#c!ƒH¶y@1€—Ÿ›¯B@0'ׂH["Œ–Bˆ‰†c !¢ØÕÂÓ’ .ÂAÙ„@DBô2Ê"Cü%x²ÈÀUW !ÜT®÷ˆ;à³!ÇÿmÉÝ÷°œaÖ ÷½¥BH¥´tÕ›CH-âüx̵ï!dÞüÄÄ(×OœsÓ¥[ýÞÕZsñ²NVŒ².¡€‚GÁ[6÷DÓ¶S©/™L6¬¯7°e`ë•G޳±ÙÔÔ´níÚv;Å«« ðgÉ `ˆ dkjEünßE¿¾¯ ÔBIÿ¢zõ€2)Ÿ½ˆš|Ý´¡ÄD–ý¥¹_ue×WžòXH*%g•&0Õ)̧‰M¢Œ#a°³Ji %+#D|‡Af„ ˆ{3!DUÀ$DÍg[!Q !ÒXmF„ä¢nJ$Ò0Bøj!D/CüßEÉ„ˆmzBÚF†ˆÏWOÈg αˇkÁì£c±K<ŒM;N§RM!•òK-ß½xúgÍnç¦Ù%R>éd×1× žxî’g¼¶êñý¶þ•Þ°aÃÞxãè× j!žÄBY’O@€ Ãò~lŠõÞl.t3Žç¸~l˜¨e§*bH:±°džGT©‡ÀŠYºÕÐ’f q1öOÍ»žB‘ ™#mm¥XÆÔ#@(K䉌»XÓÜ?é1àìÔÂÏV|‹{ž¾cš}ŸÇ>¦”z”¸$/@9w]æa¾õGa]æ2W”ô¿ BòÚ´„¨Ñ)EBÄ»´ !ìd*ŒˆHH`¤€"É;øS€²ÈC„@Ydˆ´î)Z†d×D­Kȯùüë½Ço¾ûÀÚ„e';üvÿ±/|×È/X¹à¶ƒ÷Ü¡6nYñš{|볟J\éï?0eçÞ]mÓîÖo×ɳޔ.«<ʧïÝùo{w±M{ë{L¹çMM_›üìqýéý7gMÞ}@wÛ´»ô:ù¾¼c»1×ïÿþëðë.Æ ãÿ—g Eˆ'šð (Ƙ;Óå¶tQÅßAŠBV²xA`,;éD”JaO *(Ôé)?Æ1Ê,’‹N”ÕëK¡ó¢èò4öYÅ’…YÒ¬ä¶Ââì…s½SLˆN–a©<•›/!ÒrA"$¨Î̓Q ¥"j¡ô„¨oZƒ\G6 B ëöQ¶‘!êAdkòkž)÷»âƒKg¿²¶¾î¹ïÅüÝ…ìýþ}ùÀ‘g-†ƒ}SW÷Íâƒ`ñÙ‡ œüï ÔY@ùþÕ‹v>aêׯ,ý¾nÅ÷¬¹åPñSMå?]õÊ…»œxåw]Ç~øCÝò7î­Ÿq¸¦w÷®\§ý¶“ôþè;ëî}}EÝŽÝrÕU'ïzÁË«øG~{Ô­¸§²~Rÿ.q åRêQê!–™3›3Kˆÿ¸”!·ûUû{ lH=‚’V@Œ•‡±ÉlQùîO’ìËêÛ³öÊ43AÀÁÛGég#FØãëéwr"sˆÊ!7ÏGÊ9C)%Y+"9âò]¢ ?÷“žbºYòv…™Êª¶Ã¹~ vwÊþ•Bˆxk !zíH‹‘«I„¨Kð⑎·Ú€¼ÙQ!Äo@BDcóÀl0‘ !BòÖL%ÈP<ù‹#²î„ ÑËÉ\„ P‰µ!¿ÚrÝówë×Õ²ªöw4|ãGË›6öF‡ÒÉs®è×¹ªªs¿©s.£Ô½iì´ˆÕÞpâ„ÒKž¼z@çdu×®}êñS}å>=i:¡tòœ©ý:%«:÷Ÿúøešf¼Ý€?´‹Iï_6÷ïºT%;õ›úøe”’»NÎõ+Öî©«²~jé**’í˜/#©ágJ)%A ¤w˜/³fu]×ÉæZçºhCðx‚ ö‘‘õ¬¢‚bß·@hþŠÏl<ñ%ˆª¦ÖÂÈô{I—’JªQB !ˆfÂÿÂogÖqÆÏ²Ž‘ hâù‚”‰™ï)¥fäÏ <Â-…ÅÄ«rÚ !„e Ñ:±è_9޳ž«Š#DüCO¢:B "!Hâßb“!DÔO „вv2ˆ…wJ—!~ÍÑË(!Ùn–*Cr+ªÖ$ä×¼„:a+?¶:%{9ã» 0¶«ÿiÕ–c`ÃwQÃÏ\µÆu«f/«»?ÕW®ÿ”Õ||îÓãµæ7z;¾aÕÌ_úµ”7‚J–Plj6B¥4fÛñ˜í׎Y™L(ã9¦v"–lWýóúu„!DÁ@¸&YUHú>FÌÚNĉƘç e¿|Û¶-lÇ%®G)56F4§yfQøìxÌñ2‘xÌ"žC‰k›ñ‡©Íˆib—8„¸®›¡„`„ æ{ƒQâeÒˆxÄÉ ‚,lQl¤’Êx ”‰?>7S„˜ÿ·—5¡mÚи¡¾¸že˜nÆ3±e L\7“I³Èó\H§ÓزbžKÆl)ý£Û³»„8žçQ #ÃàñL&ãO]žg Žãd2Ïó,ÃŒY6 ?ˆF¨K¨K0E˜"êyn&ƒ²G$Ô#ÀR’y³´°m‹íé160 Ãõ(¡a“Ng\—xØ4 Ëp<‡Å¢gS ky)„@Bˆë±?ÂáÓCB¨†€¨„`@B "!žçi€ˆ„¤Ói !‘êyB²k’„dÛL”E†°ßEBô2"¢—!‘½ ñ—†‰.C ùÕ[ÐG_‚D=œÕO©%|J¢]¸[ ¯×§£ß'½þ5°kvƒJiaÁõO¾¶ÜrZ±#v?†ÂcË4L[& )AwFDÐBQJÉ=WSÌE}# ÊøÀOC(!Ä¥žëyžG Ô£aéK=î-L‰?;"„€`„ Œ ®ÅŒœKI±p» œL šèB<@1E 1?ÔíxØs‘Ô„Âj‚Ø\†WåJ)P¢Ê –¸‹?µ;³?u)¡8Ô¾»8BÂlkTB°–nFSê !~{"‘“‚„2怹iYÛ¬ReH6ZwABô2"R@†øy‹Ë@?€k=B*E-§v¯€ô­Ëxª»Ÿø›RËøn[Âí; IDATÕðÈOMìå†ïï‰^¹þÓq[UÀ?ðOuyÃNêÓî~­ôþìü¯Wo•S’­Y<Úõ=¹Â@«,¡ˆRÄß'ÑÇ­¤š`qL!(jÎ}Æ#¢=iPº‹”¿3ï@!ÿ CšÔÕª¤1íH@pxf4¢'FÍ“®Ï„@¸­.¿¯ä/™è²Íº(FÕ‹¡ç&ü^~CŒ „@è‘TO)„¨].ŽÑdS D4LÑÂÆ¹tBøéL«" ]Ñ„€hÞ^‚ Ġµ%!‰™[*CøoUB*“ŸZÎ{àÿ,„®æ*„иYçò¿à-øÝ•¿¯0Pæ%”8?©n½êoX ]#ý†5àÃÄb`3DKj¹ Ã`af0Æ6ªR#kÖ.R㹸÷o—?oñzÄ(,LbêÅ–@Ylžèš.^,…6–ÃÌÙ£@!sW±Á¢ozÐÆ"D „]!†e¶!‘NE‰„¨Î"!k Å’~Ã]:!7kBÔ'CÄ[´!•¢–-÷šúÑ37užÒ­¶¶ÛÐgœ!7ÍÿøÊa[²Oï:¶{»øÝ«Ã~[í}í¢û.ÛêëY:×öùÝ Îx ²¢T®ÿ´û~ÓÞžui·ïgoߥ¶÷žc“§ÎÕô¢û~wöI˜«?8÷ÉÕÍâûOœR5vÞµ]¶¿ïû­.¹û¿ÿܯ;{¿é§9.]c&úܱO÷_Õãnß¾ýÂ… Ó…ÊË/¿Ü¾}û°J §–Öì÷ÉvEÌÓ˜%faf|)‚\yü=v n“HH)róØÏ¥”É# ˆoàÖj€)P®Ú÷ãfMX¶ÑR.æÄäºn`¼D¾=eíš;BmIy 6Lœç²6RT ‰ †Å—üë»eÉ ¥û"*dâB ²°7ºcš–Š]yq„ˆÓ¡žl˜m@_B$Ä>_2!’˽Dä%÷Ðâ;w¶2!ìwQº 2ɾ¦)‘°ãž–ÊqýÔz„ü:Iê:Rz§ïˆIÏŽ˜øÝÏõí¹³ôõ9þŠÅÇ_Áþn^ûäU§B|‹áQ*/øé.']õÞI9åÓ•ãÂ}3­._4d—)ïNsûa¯ž'öñÝSÔW·y¶Ké.=ÒåWšœ-Œ^~ùå‚—•º„âŠkþ;dù;™øÕ!’ž90‹´Y ÔÀCPX))AηÅ4(Îå\ð ²rMJÎ%/ÎO?Gª÷eƒÀÂÃŒ{LÓd {Eá¹<ÇXŽªj$g~$¸á¨ë0ñon8Â#« ®Z`‘ ‚ÀØÓmCH`˜éÀùFOÅHK”…>G$„ùê—NˆFÿ'é!6Bø9`›¢—!™ ÓEµT†HãÖÚ„üzÊW\1eÊ”6¾ióÚùk´W½v>BçG¼øÝ);O¡—·ýølÄRWW%ÓðÂ… ‹?Ècjö?F z.Š06ø§†aš¦¥Qh‡e' ÜA†Y’ú·ˆÔÀ,á9ßmçtütêQêѼÛ@@lDÌÅɼ{ئYÌÏ*ÍCL%BÐj^ 4á ¥9€ }ÇqXÈi1¡¸kç³T.ˆ"äyùÊ2Ô…M¼öh §j•( !|)ßf„HG„ú†(„ˆ!¼[‘€MK†D$D/C@ˆ ¶©É•ʱ]¥üÊK”õì³Ï>uuuÅk¡ 6™‡³hMiš¦eY²Oµa,hÍšgž™¯š–d(»»ãºa*4i±˜·4¡<à Lg¡Î1žçPBˆ±ü—~†Èð†öuQÌi"BP´@V˜Df›Ú@%·¬Ê3:¡þ8‹*Æ#–q–¥(¦„uÞ6„„©y¤)LHP.¼" <®o*$Ñâ§neBÄkô„ˆ9ãQ´PÅÂêoSB´2„]\:!Òž§h¯oUB~…åòË/¿üòË+K‡J)c)°gbÖ \ø²“)J©eYì% <“ÉdLÓÄ;Ž#Š6)ñ;K“Îõÿ’¼@q˾mb.?ŽãX–•N§-Ëb’Ȳ¬ææf&yÙ–ÚÈ&‹`[mÖ6 Øq}ã Û¶}yÀì0X›ýžpÇqœ¦¦&õ¨‚É2˲X¿üüWUU±m=ÏeËFŒ477ó0Ê’Z^ìcB2™ k$jîGÆmNÇaCÄšäº.{étº]»vl¬lËÀˆ&â¶“I @½LºÙÌPbq’LÅlÓ² `Ìqâz†?#ë)%ÄÊÚô°G£¦ªmBXäh !¬Qáë›@BXmIˆã8B$-£†ö!‘J\ !‘qe£ÂÞ/RÓè ÑËÈF(Hˆ^†°±*Q±§'$º Q ©L~•R)¥—ÂZ(öûxÄlöÎÊgOã:g¦aî;Ú·°ûïÌC¥ùUÔŠsQ‚‚z.#4Pù”„JC=J4g^|]áG~å›|.Ù[Hß ´è >¤YÛ'md¥z¤pLÀÇSTJq'g6›2¹ÏÚÆ]¸ @ŽÒ;±ñ„D³må„`ŒAþ"!þ¬tÖ…5g™Dˆ¢'„j QƒZ›ÑB¥õÁÐÂÏã6Bô2D:Ë.Z†@TBÚD†¨ç’a„ô~‡/–ž!µy×ãç°>[pF!•R)•ÒºZ(®L^ñÔ¸OŸÏwBb¬”ÏŸÿùÓã!ßæFœ yŠx®(âf¤’ë²”[Ô\2¡~V ÓÇSøÿÄr¹Ù Š0 ²{•téds–ƒB<6R“mé.ÕÉ PÈJRRœ¸”ç+$Ä„²R®ø¼6 lL/ëz‰ TCk Ÿê¤ >RÆÖM“VmB“Ü©A:6BÄó²M±=¥B3J!„×SF¢'D/CÔö‡²rá+žHÈ»Œùð‰ô„TJ¥TJ«/¡ÄI]éP?p/n"™øS#â¨âOJÌ={ù Ík (š•}Ÿ‚ ecv–gçåN^ZÖ ¤°a ÞÅÈ+’Óuoä° ]{Äñ­P†Å7BŠCß9CÖ»»DBç‰(„¨¹½$B¸V£ !RR3…ˆHˆªþ \<$„ûÛ—Hˆºæ !ˆ‘žÙo«upö"޶ž½ ˆNˆN†ˆpzB ÊÈÏßÜz„TJ¥TJkäÀŠR!÷fÞ*” JPöS ¤ðΆ '}”B) \n-b`¹”ÊKÃ0<2‹N* Žœ84J)äÊ£¥@1 @‹Øœ©Ó’h2œ'Ú|i-­_’§lG.E‚ÎßÁ{ìB&B”žX–A)ósvý¤ïÈdƒ%ÀœŸ…@É”¢ˆZ&‡B))Ž •Ür¡ !i€Í”ÕH¹8B<ÏÑ’7—D”…iMP´ ?NUaB É( !êiikR™ü*¥RZ} Å÷¯žç—÷ÛV”Â:‹Ê fºÃCä©›Zi¹À2™çB¤ ì d ̃ûCpntQƒm Däló¾ôwÛª±‚*Ѥ-2ó…6 $ÆÁ«}š¢,•¤{©Z ip!e kÀ7²R;Ý|§ÅìTÊö£Ìî5/ôŸdò_Ð}’"6R"A<»i!¼³a„€`ÖS ! -Gˆø¦ž<Ïó |)&T‰Hˆ¢þÉ#Dzèq} 'D/C|­XÉ2‚ žŠ!ª¢®hBï[IðR)•²1–P‹‰–ÙT<Æ wògâæ/¡v9ቲô§×w–¥žÞ#¦—¥ž!Ç<\–zv8ü¾²Ô³ýåiOŸáåŸþcf—ç¹2£<ãš{b<'„476ÖÔÔüôÓOãêd’52•J% ÓÂkÖüTUU‹Åêëëc±ÛÔ®_¿¾¶¶!4àð‡VÎ?)<ÏóTUU55¥06€eÅlÛv]bš&[4SÏÍ—¿˜=í¾#îZ¹pÖØCét:™LÖ7nàá™5ÆØ6̦¦¦êdPÏû¹®ÎŠ›µµµ†ad2™~‡ÎZ>÷$êzÜÌĆi[È4˜·®ûùgJi!ýGßóùÓã£B=°,+Œ>ÝþѼqQI&“¬Í„ô5sÙ¼“£²¡©Ùó¼0Bú ¿ƒ ë Y¿~]mmm!ƒŽ~胊BHSSSmmm!ƒÇ<ðÙ‚3¢"ê‡TB¶=sùüñQavßa„ô5ó³¢¢—!Û Ÿ¹ì©¢¢—!}‡ß¶üÙ QÑËçËZ%DD€D]ý¨+°ŠG^¥TJyKÅ´9ÓœvÓVÌD@ÆMŽ%lŒP7·<â`ÃÿS‚›À£0¸ÄM9ij™†i`J<Çɸ®K(6\ÈéÞmÛr‰çQâhNeˆ¶a;é´a#d úÆ(Áà›FSS3§ ˜È€ uÏq<—’ln‚ê9NÀ—þÌ–cÌBãxžÃN%âñ8W°‹;Ó4™@4M3‘HdEuÝ 2 € ÓñˆG¡¡±‰r<™L%®cBð<êzÔ%àð("%Ì2„âñ%ÀÉÄlVO̲€IP0±a&"”ÅÈI§Ó¾Qªã'CœŒ…xÄË8,¦fã8¦K˜þ‚ɵ¶·í˜…u‰ƒMDq=aÌÎþÒ˜dw¹þÑ¡@(¢2!¦m„BdB !h&“Ö Áia‹BW©e!„ý…ÆÆF !‘ÿ)ŒˆHÿHD%D+C "!z•½ ¬ÃrABô2Ä_oE–!J ÁDH¥TJ¥´úŠ)°iH©\×õ(‘H Y="ð ? 3e‘|1"ˆ²gòó‹*Î,´ãeH66Kn{K=Á,y°h9ËD ðÿsET¤‰›æ(;1­¯êGù!€K_¢ÞNÝ&–.È¥õˆŸ¿Œø¡ ¹GºTx*.ÉvÄ¿£!„_2p¨k=Åõ<*š<ÿ+”W›žÙÊG!ü`› !Ÿ“NCH¾hñ„ˆ©dUB h±DB ÜA¯E„°¢¢—!ü±$D/C ,„DW”!¼×%"^,R)•R)­}Ç}GÜÅÞtØ}ð¿¹'°€‡ÖÜmÜ<øô™ ¢ÙcÎ@*k ˜IBDip~ÑwÉqæ‰,°ÉFº…Ô`ý„—uÃÆR‚Uˆ EÑ©çr©ÍÀ³.ˆÝô·€ù¾åR*{ßã:ßÄAšêÄ>b:z^ØÑ…ˆ-šyã­lj0!äc0||¨ï.»ÌÞñ]~ò憫%„P!FN !|ô6B@1g#„‡õ &D9‘ #D´¶V \ÆÙ‚„` !àèD"D•!¢ýxYÉ u!B6/"þÞõ„ôᛂõ=h:,æTþÜ;Ö­Ùçà;à•;‡«„TJ¥TJë.¡x„ßÏŽ÷<ϲ,Çqâñ¸ŸÁ¥tÅ“'Û¶í¦3«^k˜vN!äa„ Œ1FÌŠaL‚pÙĬ%øŽÙó<Ë2¹&ž_Â$&qY4bBŠ@È7gu ¡'Ípy»hÁK±àV ùé®guŠ1EÁÊÃÞˆæ<þ¤c€ü¬y„€a84 $[m!â¾™ûŠ3B¨PƒyˆF D •~ß‚„Hq7:!bKJ!„ݨµ [R !|kQˆ2¤ !ÑeH)„D×Bé ïzBV,<-× b4ÔE÷Q•HÆqúêï$B*“_¥TJ«äzÆ€iš\@K¾Ä¹í¯ÑcÌtpQ0ò寘m”×ãy«„e¶ã)«!ø@HHZ/k)¨wA ¨~ÊkŒ£¦‹‡ðX— ¦ìðu=êuåƒÀS8gÁ!#?å;{_¾5!$-Ô@›0µl„dç*=!RR•VOBøÚe!DŠ T4!<ï[‰„¨Nµ­Aˆ¿{+Y†D%$º )…ˆ+§M„J©”Ji‹ƒ<®Ðf”ÿ7Íò$’z„RÊŽarrÐÀˆP À“eúR;xc‡Å-5³WeFê7ÂRü\@]£DÜD²¤šK+¬=ù;ì¼;²µ¿¤¥þnÒŸ·0Eد–@b·fÖ$(7_blªêqɇoÊ¥c¶ª‰¾EmB”ƒÅ"­n=BDƒžðøàŠRKËYJD%DŒuÔz„@6Go‰„®ÒŠ òãKMHô¢—!áý*^†¨„T&¿J©”V×B…Q,¦ ‹Å6”Xh=*H¢JÜ–9Ž#&07šâR Ê‚â¯8;ÐÀ³)(æÞ lw\âR]2Ï…ŸÌØ;Ì틉H¶½–¬‘+TŒ±)åufþDì}ñÜ-ÌH"wZ‘5§$“ðÖ#D 6-ùIì5„¨5·!úŒ@Bxñ°öD$Ķm !L …üìÎÅ"þÛÑË"…¶ !z".Ùõ„D—!*!e™?ôé¥7îÜVY&n¾¹?&\p©$Y§2yÊ|TŠBH›É¾Ö]†¨„hšzþAÝoŸ÷5¹âÖ7;ïÕùÝiówV½tÇÖÃ/ˆ¢Ž-¥hFUÒäµR*¥RJ]BiRÔE!d€°3ÀYÓ løK–vQÒ^Šë·ùA€”[Jü"·a’‘}=g‡!œ\”’7JÚ ÉÊö}à¯]’ R§¸>€õHê;%Hœ&Ù”À>bÓdMI¤˜@î(žb­MˆÚ†0]]ABT´DB˜v¤- QM†[ƒþAB¸­R !-çZ›Ï7U´ Ñ¢—!¥LÛúçÞ„h³ã%û/›¶€¿|xÁ·“þyñ¯år×¼ù¸dûû­ÙS÷þMï¤eÄ«;ýnôÄ% ޤíV{÷¿Ç¯ùÃàqËjߵϟ.œÞDZe­Ão×ðù‚ãܵSMÂŒUõºïµ, ¼8¬#ðâ­ç éÕÕ2¬®½†œÛKRÃTeÏ^;¡·< ‡¦×?yÃ~CûTÙfÇm_<ý ý}Yå¯Üzþ^]cVb›A{Ï|wõû÷OÙ½÷¸ë9t俾ojÑeš¶é‡åí™—íÕÅ6í®½†œ{Ë‹b÷5Õ|븄ÂJFô@!(åçBQ”ÝâcDPÞæ +¹KEã.¿øäûñ­6·lPå{“ÉJ.M¸ë¯8CDªŒhã6ÍH?3®ËQ7R<."Ð<¼:AòðÇÜr6[ÀžçïnÙèYf #w-ÑäB¬aǬ¼ñ¢ªB !ªÏ”Dˆ¸–Ò¢N¿ B¤ƒT‰åT(”žË2P,„Âÿµ )Hˆ^†ð7U„hZØ¡ÿúåß~v x™og­ká³¶Ü0oi£@Ý«WËûu`øû¾ý™5™µ_-:vËÿtÐtua'¶ð‡×/Ý{ò{Ïz±®9õåâ¹=—]½×ùo´tÞÚ®k;›µ¶þý¨“ys•þâwÓ–­ªK7¬^0ýÂÕs'^Ö‘/æœ8êŠE—=üfcºñ­G&/šrÈÉO|Ø5©Lx±ÓÓK¾ñÑ÷úûW/Ýå”ÇOºáÉÕRŸ¼2+ùß‹ô÷eå¸ÇÝ™¯,kjüéö±Öé¿ß}Ô=õw<ÿacãš›J·ÿ-ºLÿD†åÛçÎÞç/ïLyìí © o=:僫å_ÑT¨ùÖ¯e %ÅÇ“JΩåä ¥4gÇÀC2æKÑ[Ü2Š?xÕ GeW5’àÊ 1B ß¹–r”.F¤T%©h£èþœ5Pðü‰_”}þ}ªo—ÔAÑjX<èä£Á>ÔðB<(/D)„äÍgá„ðXSa„€âìFˆ_G"DÀÖ&„/Y4¢(²¥„ðÇѪ„„i‰Z*C 2!z¢·m\"®„ô„D—!*!:±ou¹d[2ueÔ~]¢ÇÅqú¨Oí5ý ?Îúq«‹;[þÜ1óGï¹}Ò6ª:ö8ýÆ9«ßªïò'ÜvýK÷ ß¹OÜ4Úo=xÊ#ó>šqN‹í7‡ýùŽùÿ]ŸJÿøÅ{;yçxñÂo5׿º.uòQì\3ìd¿]üÇc‹/ ëÈugÏô‡ïÖÛ6í^»6ç…‰sκ6J;ozø¯ý:Wìõ 'Þ6áù§ÇþqǤmvî½óä{ÞŒrß{æ];t»- »fĹ÷º©ÏgͽzÈvØËº7¶è2ý –Æß{ÖóŽÚ¹§mÚ½v9ôñÎŽòˆ5ßÚLKá ”RÈZŠèwQùB*·é!ÄË]Á±L¸øã:i2Á¤š»q‹T~ (zH³7MÃbqq‡•J²Â"«k¼¸Ô_¸Ø•3h@ʼ"F+&„Îóvfw1MÓu]¯ˆ}…©Hn>¬¿ÜFÇËDyÀ”4ˆÈÏ–!†AbMcOciéÝú„ˆ1! gëRµt¥¢·Þ á–F„°é0 !ªÉ¼HÿJAB,ËÒâ7#!°)¢—!ΠhÚèäÑeˆøROHt¢¢Çõs·ýep÷ïVÎxµßÄ3à÷û]7m<Òõ›ù÷ ¼`¿òðΉÜtïã9«õ5ÏXµaý¶íNËóZm™cøûsÿéÿewvØÄ rºíùçkVÏ »~æøÝöê9øˆ£¶û®Ãö;hàVÉÀËÂ:òÐê¦/uäm1è’¦Õ½î(ØÎQQz=sÕ†Ï~ÓQýºþ¾tˆùS§ÝökŸ{)>‚(—éŸHذÜûCã§;äš7ð€k V¨ùÖ/S %É©0õ»j•Âá}?g? 0„Ù ‰±€ÅÝXØÜËZ 'ªè¹ƒ·ähe+¸…o¹¼“´G’ÇP˜[8ˆ¢ûï—èRÎ&H”O:V`°…Ï|?Ê¢$Ï£(v*‘Q¡¨z)‚qjBäänÅÂ5I%Â,¬y„èeˆ¸ZÚdHࢪì„è¹íag~3ÿV˜7ç«cÛ¶>ä˜ï_™¯Ü¼üìC·-zÊñ(|Øb¶eÙíWÊÖ®÷éÍ??£¹à°Ûß\öÜM{ôH¾óìÌáý»Ž¹òµ’çÍHÆ[ŠÞkÔÒûJ_û~”ËŠ{"4h´ 5ßúe.¡øæL5<¤Wc«põ»´×ä{,Uzª^ßRôa%Êœ…YÔ´CP„_5BÚxq³«¶S=¶ ”"B1 õ —rwø.NÙ„j’) © ‘OÄ[âT‘õi2Yg67DŒ4[¨6 DL[Hˆdê¡!D"A"D|R›!’&pÕ…ü0Å"þk=BØÅQ‰.Cô„èezËÞ IDATH‹Ë0B /Cy+V’]Ž’yòõµ«n_»Åé[U@õV:ÖÏùhCà «‡Œé”hÁIBâ„|ÚÖÕ—.ø¦ŒsXý×3cíÿ¨¿¦ÇÎL¼`òÌGž]ñÕsO^uT‹ê?¶sòúæ/×}|]²óŸ»¦)š^ŸÒ­úê¥kZtßò–âžÈ‰]«®_¶NhÞõQ*Ô|뻄R£’„ Ó°ðÍš-š¨<—v“{_õ#5ƒi Õ…hfÁ¶àm*# _¾ã’h”Z0Üp -H`ËùJgÕ8TÒ1€¬TÙì¼clš¶hl·:ÊéC«˜†¯5µ¡›!ü!ùiw5„ð”„@ÍÙæKˆKÈõõ¯­ZUµcìÕï¾û²¡ÝdH N®ì„lØ_¿ÕÅžoô¸ÈöÍí‹zVÿõÅ+è°‹ZÔÁ=jí;Þý†«øÎøÂçOØwÚœ7Ö5»Nóú%oÌ›tèN-ªpð!gÎyõ½uM/ÝðÁK¶çE£®¹Qsý ƒ'<öòâºfÇK׿³p^¬Ã°Ý¿ù€£æ/úÂ%î‹æuÀ-GÞrQ`×4EÓëóî=ãöF?üúG)Ç[ûå;åwï[ÞRÜ9ÿ®±·pÌÓ‹¿Ì6ïæ(j¾›gœ­By,)U¾¬ëºÄõ€PŠPs:M0ò¸ZŸjJÔVg<[È2(¶ÆµI ň ‡‘kIdãB×ó½îRŒÒ®ƒ-Ó%¤±¹Ù4Ít:ÍN?ìDÜ¥À>ePÓÂéL³m®“x)Û &rmL’vŒd\ÓÀN&m,U©ÈsI0A,²/3ªPlxˆ€ „eá• Pd`d`ÇsY8lo&ãz¦ó“À; ”z®m¨çdÀI§|‰†0`DMJL—"JõÍ×B äQB€¦‡€­x,žŒ5¥S–ˆëbÍzž[ñňÚ×KÚ1 aa†aÅ<„ídU}: ±11ØfšÏÀà ð(¤—u!•J1³SBõü >Äõü|iÌ£Š"B `a Ø Øð.…ˆDˆã¥›SB "! !Œ÷(„xˆjñµÙ±MCCD$Ä2 ! IOC×>$ÄC¸,„èeD$D•!¯ûyêÒ¥SþûÎËWZÌ{?þ躥K/ýÏ>o¨+Z†°ƒ’(„èeHV4&$º Q )87 ùë°·Ï{´ÿY{ówöžÐwáø[ÿø—–­xfÜtæÍ£v´²ËÍ.»ÿå£ù—þû–I=·H$;n7nÊCƒ'<vâ¸døŒ»âÔ«âíºsñì}¯{áÑñý5 xtâÐÇ®·MûDU§Þ<°fîÛ÷¶¨ý=ÇÜ7ï/;M³[ÜŒï6fòoþ:ÿž#zvMS4½Þê×¼}ç¨é“n—ˆõÛû¤¦=¯+xßò–èOD,ÛŒ¸ý…©C/;bç¸ßý¨Éƒ/}*J…šoÕ­˜Ö¡ßy›ÝÊ,¸Cb[®^úVlËæÃƒæaÅïÿåÁe}Ÿjߥý1ÇîuÖãêÆ‘†zòƒ<5E¹T (îE¢Þ›‡jä»Rž¾” ÇÿÜJççWç&™Qlòv¨Lù¯dÚ <ýa¦¸˜õ-‚œ}(å;P1F(ä{ä©j×uY8¾¼ü-ùF£Ü;×à›]J¨lÿÁ>nÑZ² ñ+'4p7¦½Ð¢q.šnHѱõ„H:­Ö"D8`Òäš‚[\)„d;^*!þB*!eHK yå»U,_ѵ*yÎz'ƒnzxúŸXòÓš9_|qýûKÆè7¬k×"d”À•„JÈ€3ØûËŒ—ùìå×<õÕÇ?¦·Ø²ãŸŽß{ÂnÉ–ÚluÝu¶çÌßÙáÿþ›ú¿`í úÿ£ÿ‰ÓVœ8M¼f»}O»ï©QN9ßßaÄ„ÇFLˆþõFL˜SèzMG`ÿ³¦}pÖ4õ[j×4jz=èÈ‹^=2@Ãv_6ý#(ø2¬múaÙó´k?8-ç$øÏ³i”Ά}kÚ‘?牿´%ÿ¥­\8¡©©ið÷û?é¬9AÃwËÆÜüùß®<䀾Éï/»ôºíú=e;KIxž'T)ED:È ³] 4e•²bñ(Õ9©Ç B)EXÌÆ€Ôœ¾ˆg­ª?YóÐ&iøÙ¬äß ë”í_@(‚˜ o¾ K0ÌWÒI÷'OŠ_´çyÜ!!ÄûÇ&KJIÖªr« ¨þ`E¨‘êQŸç£ž_C)„BHOsHHö$«TBôg…"!y+ !Ù“ªÂ„¨‘EBäy=œ¿I¡„@RH†@2ä³ú†GV~¶G—Î'ôë—HÄS©`@Û×Ö\¹Ë.|úéC+Vn÷H&[*CrËÙÒdˆX§žå Æ{ž7ðYÔË#¤ñ‡•ãîYuå_÷=h@û¿øî¬)OÆ»~Ò¶I}ÝJ©”X¦„möyjPÈ7|ýöv9{ÿQÛÙ†Ñc@›ÏÚò®›¾†È.<ï³m±äH"zCxb,É,@“UõòÕ× k°jçiMÔæB¹%„Ú5©#jŽUîçJ¾³@éÌo+»sç+½ ZË$Dò®Ò©„­vÂW›!jŒ¢â‘Œ@ ¿‘¥¿¿Bø 9ž{÷òO¶­©>¦gUqÇè¿]mÍŒeŸüøøQ 8dEø5„äÆ*KÈëÓ— 9yבýk,Œ{lßû–³¶ºû¶oÂ:R)•R)­µ„Rãï‰I£à‘o2§­âû-‡ì´þ«ƒÖb´õÁl—Å¿Ëÿçóh.Í#MK³‘è;Ù$äbañh#ÐÍ*Ê0EÉÍ)MlÛ>†÷¸èò4—SQø•*î¡ygùþU:iâÙHÄì–³ù²Äum‘×Ô!’^ªOJ"DŠÊ|YCw #²žG á>ê*!;ñ >òÁ6#DUÀH„°I1 !â̪ É6)˜È÷_+šÒBMHïáw@¢ÂeÈ—ëë×¥#zõ4òj¹V2¦w¯ºtfUsóÆ’!êÖ«¥2äÑo3ÚÞæ„tÞiÇúo>•©L~•R)m¤… s9F-kö†T[\üY‰ÎNói¦q†’ÜO$Gâ1U·Ñ\(ðÝ'!„*{î‚JlUUZË•°0W=GÜÅÿî5üN¹ãAá^įsäØ,În6!‹ð(ƒGšº‚Sv„‡ÌV]¾U»(Þ É;Lœ$4„ð`Ea„„-PTBØè©„ôÉÚ”À€Q÷•HHØYL @TI„h`!â§¥"I„H½(šÈ‹¹§#$L†ô=øîÜom䌂„ðï~Y_zÖÔjÙ®º|¹¾~ãÊ(„¨°—Ÿ¤Èö1à„X‰ÎNjDHeò«”J)½D²…Rg¦<07@Íæ`Ž*HŒ¶Âö‘@)OÈ‘7øØGÊÒŸ>£î-K=ý…9µô"­¢Š(;õ`yÆgøô²ÔÓwdyêé=¢<õô}oŸ×ÀÑ÷oô'î·äÐ{ÊRÏoÇÍ+Ï8šYžzFÞ]ÆçµýÑQU;Äì­Ìoz@æð¼qî°_Õ»/|ßøÑ+-mI¿ƒ§CY _ØIŽ”RD)Ê´Pê¶„}ËPbI° ™“A¥TJ¥´úJüAŠ¿C_Ä'Œ¥Íd÷¤¿wÌ4ýd%:Bà9}Páu.}ø˜X"aÛ6Eƺuë è®®¦Ô[»vm§-:8Ž“J¥jjjšê×'‰t:mÛv,knnFÅãñ 6$‰^‡ÞûåÓãÇI&“Ï5­8EÈŽYétÚ²,×uM»®‹ Ë0 „03E!0(x€‚×ÄŒå Æce ÈNÍ6ÔÔÔøV¨¦…1Æ@)¥éæ¦D"ÑÜÜlYV¿ü™oå³§aÓr3iD ¥Bňp]—"ÀÛ¦B†aÔýüs]]]muÒŠ%ªkk›Ó΀CïþßcÇÅãq˲Öü´:WWW×ÕÕUÅã?ýôS·­¶ª¯¯¯®®¶c±t:M`Ó ”¦×4MÓ¶!l@zpûÏO¢AQ×Ã4¥›=Ï1 +#À®ëRŠ ÃÈ>19a!)¥½GÜñé3|< Èd2,cSSS"‘Èd2–e! ©Tªºº:“ɘ¦Éw:Ï\z ¿óó…§3S£ˆ´QJ iN545Æb±0Bv?qî²¹'D!„ÝW%dûÑyÏkÙS'è ɪpƒ é}Ð_>ì?mkßñæ&0Æ_¿³¤}AbF'ŒMŒMJ¥†Å^òr|ÈØÞˆÛ©X–ÅÝ­Y¦3BHsss"‘H¥R<¿óEJ$,Ô Å‹1fb—= Û¶YƒÙäÊ…ö¹y[½|+Çq2™Œ‹ÁqÖx~ BÈçÏŽç•,Ÿ »žG^À[Ø`§-–ašØ`‡)â „b±Ÿ9X¨CˆÅb¶m3guféÒÐÐL&Ç¡”Æã ×õ,Ëv]/ß7Ð÷`b­eã™J¥0ƶmcŒÓét:îØÈ­…X%Ù—.¥,[eq$B á”666rBš››Y~1>$Äqö”K'$•JòÙÂÓøóúpîq%ùÑ: a_¬««c a_B¥TCD$Ä0 !þ®+!DCŸ‚„„ÉÏœÁÁ—Ïžm««]BVeÒ"!LþpBVÖ­£=jk[*C $ñy2„QO?±•9fû‘eNÈÚ¥ÿ«Ý¦·DÈ/~n®(H*Ïkã/¡ÂtH|R6iТÛ_™÷á:—ÐoW|uÞ?M8gÛ(ú'ŠyÒ5‰=ä[BðQö\T¤çŒq< ¦|IÁ¦Š¶±µñâéQEßu,ˆ- ÄÇ[L(ÆKqg BxË¥d#-"Dµ¤)ŽɾG$dÙS'À'óO.œó5„¨äK„Hz !â8·!"•ÏžŸ?sz‹Ù¶¦º½m>¼bEÆq8!âÀãŸÞÞ¶¶N&7– < ÐÈÈÏ+Œ1þã™;|0û½çV6:ùzùgÞ´ê¤ñ[I„lâ3SÅyð×P~O9jPƒ¾#îÚñðÙ0øˆû2“ŸîUm9à¾S·žuüGßó§?Üwü'o 4Ï¿)ûbB(1 ©ÒüǶ§Žã°’’ÇŠÔr.CÙ>˜mõØ»”'­šN}ª/sžSž/ì ÅÔŒ'—ä/_ð ’Ÿ 𠸹4Ÿ˜vAyÊ#dÅêø—22j´'Ñ|‚ÒzD!Drwo=Bøó*HˆÆu_‚DOH`è„"aº‡Ö&¤¸Íbk-%ÄÄÆ‰={}YßðèW_;ŽL¥ðàÊ•_5lß¿¿!8©!Cô„èeˆfý$²ýá÷ :b6 8tVŸƒïâãÐaÛA³Nêvÿ¯:bö‘ÿXrà¤ÃŽîjH„èÛ_ÿÍ;§¼ëU1îþÍ~'½ßàðö¼5{êÞ¿é´Œxu§ßž¸¤!·š|{æ¥C{u±M»k¯!çÞòbX^¹õü!½ºÆ¬Ä6ƒöžùîê÷{ÿîq+ÖsèÈ}ߤà[3.Ú3WmÞGAÏ4‰}ñÖó†ôêjV×^Cοí%±mšÞ5¯™›¬Ý¥Þ¼:2ßo]½åŠf·ˆ†°XÖ,¾o`»öïx½üßã×üap¸eµïÚçONo"Ø4|¾àøwíT“0cU}†î{í#‹øGa_×ôºˆÚxÉÔÿ;V3„Ÿ±ÓÙÙ?½ÁÕö¿ë3Ò6Cz^š±9-¡x¯>]pÚ’9c?{îô?î“§O…BŸ=w˜;ãøeóÇýûÎCNÝ£V•€õxbÞPþSw¥äï†D]T²1Sƒ‹' QdŸj¡©Ê2Ñ_Š×¢b!z¤³.3×ò:ù¹†èpDá¾Tü~¥˜KõK‡üx8q’‚3Ia`ÄÅ6#Dyò¤åóOY6ïäOŸ/¶¡÷nýùç¨åóNz÷îÃÎÖA%D_zíÙ¾—Üóõº¦ôú¯.Þó«CFçÜ}Füýƒ?ßþÌšÆÌÚ¯»å:È· ÿö¹³÷ùË;S{{CjÃ[NùàªCÃ*?îqwæ+Ëšº}¬uúïwuOýÏØØ¸ææ£ÒÇí/g»ûfÁÄý§|påïlHmx{ÎU_=Zü4°1’³³TásNuÅ¢Ë~³1ÝøÖ#“M9ää'¾,Ø;Ht:üší¿9i^îâoŸ?Ó>è®~ ³ˆjF˜•OŸºjÇý®=ûéo;ã÷ðÃë—î=ù½‹g½XלúrñܞˮÞëü7Ô±=q÷1펺jÙªºtÃêÓ/\=×Ë®ÿzX¯‹«»v¯Ñ‰÷ÿØéº§ÿï¶w2°aÕmŸ%֖߫„€ô¼4bsZB‰ç;RLgßIDØKI3„~ï&Å»¨ Õ ÃÀàgæB‰ë×£’•B(Ša@˜úA½ùTÁ3(¸iÜ5Jûin÷*í¤C*z¼¼dˆRœÍ",ÆH$¤`?¢æŸ½/Fˆûéì£12¤:?sQ_ •  €uÒ•«ÒâÇÑÙLñkŽ@ˆ  $B(Ö".åK!$G³’eHAB$²_÷­'l»-P¸áƒ%ÿóßö¬:ååWoþ߇@áâï³U·Nh‚²%CTBôOmÍ'ÿ³×Õ¶a&:uÙã?ý÷oü£™o<8zÏí“¶QÕ±Çé7ÎYýîTöþ ãï=ëùGGíÜÓ6í^»úø g‡U~ϼk‡n·…a׌8÷^7õù¬¹WÙ®{Y·B^Býã´ûÿüüCía›v¡?ôB^Š™°ÆhÊugÏô‡ïÖÛ6í^»6ç…‰sκ6b…'Ì>ë_g^ÄÇnÆ9¯N¾eßâ:¨axý–ñ{^üîcËþûnìO¸íú—î¾sŸ¸i´ßzð”Gæ}4ãõÖ¯®K|Ô;×Ä ;Ùo—ÿñØâ(_ëuqµñrÖÈmf<ý |=ÿ*dÂoüŸÝ3{›‘“ >¦"žl‰å»ï¾ ü[_ {䩹JÄ_ M80rn+éƒÓpËMž¦ƒ›&Ð|›IèäÇFB!BC›á‡_  Ì0a‚bTJâeŠ „ D !Ä#óE Îy‚@š¤Î²tñžë²f†ÁãŨ—à];øy9üÜ[¹ûE#Û†qw®"^Ö6„d×£Á„ˆ—B;}+È&ª+™( !\+Öf„¨2¤Wuõ”m·]CÈG?ü°øÕOèÛ·{"±MU•‰qRP†@PT÷Ö!a¥éû—ÏwÉ3ÿ^²vCx†(8¼s"7ÄûxÎjö÷½?4~:0ç÷·ÅÀ ® ¬ü€1ö‡aw€ýÚç^òÚx¹ïÇÆÏú·ç/Û÷?àï£)­núbPÇ\;]Ò´ºÀQ*lßÿ/'ÆkÏyç§›ví’úyÁíxâÚ­ªŠë f„Ÿ¹ä “ží»tÉ“ÝìÜ›3VmX¿m»Óòbªh@fŽßm¯žƒ8úÐa»ï:l¿ƒn•Œòõ°^W/Ï?à“1/À©ýŸüÛÒÑw~sêë0bìCÓ?=à¹SO¶ÄõÓÒ¥K {÷îâße°…R7RÜÒ"P,†X~(ö4ïq«¸ucÓ!æ´l߯& q‚” 6ùq†eY|ƒq1¨`÷Íb CqÜó7 ȵxDtÑ·ìÒ”,*ùY—Ù°gÁÿ÷÷úÅQAø(ikltBÄèÛ„ðÕ@AB¤Z"„·° !ÒzBÃm)„@DB¤c ‰‘=!a¶Ì\TBx{J%$+Á (ClÓìYS³Ç[4þ/½ï6ÛlWUe(š°¢eˆž‚2$L»V´ Q Ñ?µ‹ö<¬aß ßûü'—Pê5QZ8…¼4‰š íËàš…Qh… ´uþeæa÷Ÿp#|øKGϘXt5#¼óˆ‘ÉϽ÷ůÅë= 6¤˜‰BöP> >êa·¿¹ì¹›öè‘|çÙ™Ãûwsåk-úzykkßw2ýòêõM_\ù%½åˆ[2Nnh\~óxrßö›Úy\÷îÝÌÖOüï2h¡Tÿ_˜xA^ Íœ”CàŠQ @|9ˆ‚³è®AÁ69)‰›20E@€bÈÀªápv.Ç.Í9cŒ‡€a*Ö”ˆ dó‚ÍKî*Z˜Ï3! Œ1F”ùɹ/0€K)"¬wÙ1D˜ò€r Bˆ"ÄÎ Ã0¨(`Œ=‚—‹Í…lVsÅËl@Eƒc#ü!Jh.ý ͦDwØiBüóˆpBÄé Qãe‹„°é' !ÙT­Kˆ¤Õ+š¼…f)„“q)„°q.!E"D/C¢R@†ø£W:!Нdˆþ©Íøºaõ9‡×¾¾+ʃ>±kÕõËÖ];ØWð¬ûøú²Ìm't­šöIÝßmÁ^Ö-ŸibCÈ|BÇvN^ÿñÏWçÚy]²óŸZ0×î3}§;ÜüÅyóèøÌU[Ý/Ío9lÒÿi·ç^¿Y×›×ë+lNÛºúÒßÌ=¢gÁš{ì|ÀÄ€ôºÿTmy8\öc‹¾^ÆÚ°ÕéâîÍ<1Éîù—nUÝ.Ùºîü'ÏIlwi' G^m¹Šj‘þ)šÊ#Äõ2©´olD¨e˜nÆ€X,ƶeL ét:ÓìщK<ÀÈ£."Âþðrÿˆ‹±ÿKöµ–Åâ%“Iök7M“™˜Ø ”¶åRÂþw)ñ€Ú‰xs&Ý”jNeÒqÇs™úÚu]Ê:à9®›qœ´ã¤]—xeQs˜R<KafSe ŒM掵ü„ˆ $ °ÑØØL Êd7íÈÀ€pSŠ1 1ËÂlÓrtã†zJ<€¸.Å@€xԌό Àéæ4r)%9<¦JA¥ÓiÏóLÓä¡#YKü.#Š1 €(€RÏEˆzž7 ð¨kX0r2®M×ñˆG™4ǘMBÔ²,Ã!?$`8{@ÀF¦BØÔXÃ)ŒÆOB2®£!"‚¨ŽŽ@ˆmÚB "!¦ijaÓg$B0Õ~\¢„`¤!Ê"C "!z )$C "!z’Í… ‰.CTBô’t§ÄY³^kv½—¿vʾ—G™Kοkì­óôâ/]â~±hþQÜ\–‰íüÛ½ùÀã|ðµKܯÞ_pÜ‘ªÝ£Ö¾ãÝoUgÝtøÍ5ÑÙvÞrä-µ A8~ÇÕ»O>èÀ “nŒãâû¥á-v:þ%³_š¸ë„;ßöÇáá Ÿ?aßisÞX×ì:Íë—¼1oÒ¡;©Õ:xÂc//®kv¼tý; çÅ: kÑ×Ë^ÛÈÿ0kü¿^prþ3O}~ÀÿlÑój³"꟢ÛBµ®Fí e»rèžÍ슀OHùó±¿+Íúžˆ¹HÅƘ*ofóÂö…#dú!(-˽¾U͹š;]Uk~W_%NrxŒ³¦¸D°t¡â(sea‹Å[0Q›µ] À oIÞA€xÄ ž\PJM s£RÿJf+Ù±ðÃé¼€æG«ò‡7Z8ã–â«!ãìÿÁ„äh.DˆišB@É›V!y¯%"ÝNCˆ8ò*!â£Ùá6I%ˈHˆ^†°÷£Òf2$Ϫ2D%D_îxñ®¯n[‹í°ÿ¤-'>e‚ØfÄí/LzÙ;Ç­øîGM|éSe™Ø¶5}áe;^:zhÜŠïzÄ¥.x ‰Â:ž›Î¼yÔŽVïdÏ1÷ÍûËN“Çì7ã»™ü›¿Î¿çˆ-jRß“g;_~>sÒö¥ô«à×öõúÇÏ,¿bߣ¯yºìþ—æ_úï[&õÜ"‘ì¸Ý¸) ž×èщC»bÜ6íUz_ðÀš¹oßËÞøõ²×¶Ý‘§ziïχn ÛŽþ?/í?r»=¯6[?-]º”­¢z#ôd IDATøßå<Èã/Õi;Ï^R´¥À’çAP–rIX 9nƒó K§X)l÷ÏvœL¤RŒòO „ Œ‰Fg]+JnýÊ»Ào >‘hDj¶GYŽ2y‹Ey Re*•²î`Á+/[°bx8ßÄJ5ÚȽg‘øs «X!‰1èb !¡‚„° Îa„@YÉ5¬­ ‹ÕÉW A€4„HM-š®u.Q†@~šê¢eÿ¨ !›¯ VV:ìxÜ+Ç_Þ|N¨ÛøÎž§]ûÁi9ï¶žM5ã£)¾?ìôë>8ý:öwã÷3§ÿíÀ‚éâ´'†ùíÖ´ΚV°maíùéí» ¿{‡¤©@ÿ2Ê'·ÜûÕï7ä–#ûž:wßSõn‡挘¼š ùº¦×EÔ&•d×q”Žc':6ÒóÒcÖJ§xü,ÿ]f-”:A†Ùoª›°0),í\ŬÜ!YŒŒ¢æKWs§‡5FŒ×—9PÜKV\‡ÙÃJŽNùþ0²7¾tGLŒœˆçï³ý1ó3—‚HŠÞÑX ë'‰ ñqÆèYõHˆøf !j¿ÂSµâ‘U°ªa£02!#HHä‡8×¢Žak"),K—! ÑËL¹õ„D—!zBô2$p J”!*!°ù”ß»rñg«=ê~óá+§ïáÎç\¾“Z»ø˜£<|ÿH¨”_VõOÑm¡¢¦†üœRÐBþ´¨õ<¾Bb ”ËeA”¬”¢¬ˆáoòðwââ !!*ià™œ½%Ä)™‚BˆÇ—¡b´?ä¦ØÈ²g5ðÌè5'm™HD”k›˜5¨GóâAúèq_žÜãpsĨ¬E'QMœ½Ð€tãÂ<Ì“õ„°–„’¯Ž*ž±ÁmCH˜gK aö9­Mˆ¸ÔhBô2„¯ÿ Ò62$lç]vB6—rý0çôƒvüàó5µÝúŽ:ñú/ùÍÆj BȈm9å©E»×ØP)¿¬"꟢¯¢Ì(+›À|jTë@‡dUÏÜÓä÷â2EÜ¥QÈÛhJ&ÒnUJX¦Ÿô;æ¬PF,R¥p‘6‹š,ÓûñdüN – H%Ã0¨—uTFÁw‘ g­ ðpm×LˆßUÃýo!dY–/éF eŒÂÉ[&„T«áî`!újÿ‚’ ɛڵ„Ò„äÜ·!ÑeHÛRP†h´ne”!›KÙóä©ïžd} l‚äˆhhTkm@ˆäV¦§‚„°õÃ/Ã0¸s\`j”ˆ„ @m@ˆ’Ö D/CDÝØ¦@ˆþ.å"¤R*¥R¤UTùãB1Ï”T*ÅD[ss³´¡S2€mÛ¢(d¿Xî}#Má~@”ìÀ²,ö{ßqœX,ÆÒH†‘Éd kíÄëäùDEÆŽxØim*•ò<Ï4,›ù©Ê|G6ÛòJ&VlÛÍÕþ®ëÆãñTªÉ6 B\Vq½„£®Ç'Õ‰$k':~ê™Tš 5êêzH8‚t]×qd`ž\§±ãy¾Ø°°~ñ^s­û"BÈDWŒ»ã—x^ss3«OílÌyß !±XŒ=Vg~î6BK!„/ Â-Ãa”NûnBDêR¡®§!„=÷(„ðeA !b¯õ„X–¥!„Õ…lî¶`B¤ÕUÑ2„u3 !zÂåO‰2ÊBû4 !ÑeˆJHYŠf5VY¨µÒÀ¶^…¿òGÖ*q¡$ï_ÓN2÷Ýõâ'?Ø÷à»ö9{áìÅ a[Uñˆ-ÊѲª±—Î}¤db‘zý-=‰h©±jX<>ŽÌ2—]ÃÂîq5»h·pë ©"Ê÷—AP:^ÉÔWr¤â1™XlîÍøSáís ‹¸RýÏ1lM¤ÈÔ­AˆxY)„”"PŠ#„Û¨Ù£™‚„H64!Ò9WÑ„ˆã\ ! hƒÚ†½ %O߯•!|UQ†P’¹ÆËû߀Q3÷ïAˆê&’¯8Õ P €ˆ„„äJÞg É›ÎBø³+Hˆdâ-"­Å5„`@m@HàªU ÑËPB_–.Cô„èeŸ‚„ˆ2ä¥[ÜõuÕõ׌ùßS'==yu/½2gµ«!D#öÏ?¨ûíór ÚVÜúfç½:¿;ícþΪ—îØzø玊2iÓ)•ÇQð¯¸y‘–PRøÁ©ÿ®ŸqÉ΃ºÆ0 Ž[vštöïnýçWüJQŸ¡f)—ž¨êR'MBa[ÌÀpPªH ¼2pe­ >ÕêY”A_pü»vªI˜±ª>C÷½ö‘EaËtñ¹¿tëyCzuµM»K¯¡—Î|[¼&ì#xñÖóþŸ½3“¢8ø[UÝ=Çœ+x! ‚ (Qã‘hˆˆ ˆ(hÅ Q9ŒŠ‚(Æ!Š "rˆ DàõCT0¼1Šr-{ÌÑÝUõýQ3µ5}Mïβdëáá™™®®ªþÍ[Uo½G÷ö­t¢·jß}ôãoªW-`X§ƒšÅó×Å€Jü†È­ôU+¸*̪wŒÛ3Ç×îC3Zµï~ó£+s>òºip߃;è×ÔŠ­]×÷„æEbwûýÿT°Q›ÝÀ«¨:Ä…ÊßJ¬T¤Pù¦ 2œŒïÑ¡1v/<ã ¸…µ*S¤ªCÝ8*;L¦nÁB"¶*Jü³¾{h¡œau\3”K¥v&-!Z6^Aqê “cQË}žÈÊ/K'¦š +e¶m›¦iš¦eY™ÔôÙÞfJ0î©8q×ïÏQóÌ+‚s©ùŽJˆûLÁ“·è÷;ÖÉKã<€y‹ ñ_r9 ~ø~„äÌ£"gë}„ÈÚxå%$¤ ÉKH° É©-†‘!âª0„¨2„ñU–øpÏÖoêvHݬÓD¾ùÞ]6jþ0{wÓÛºl]õò¿ª-nß÷ûSÇfâË}þ²îÓ^ÙQmîܲæ­ÿ¯wïî‘Wû¸íÝq§Oødìì•åÉÔæµ‹Ûm¼ïÔÑï¹Û0ä¤MݳñÇòtåöWgܶ}ñ°0óY¿{Ößµ`uUªêÃ?º£ç¨×ÈûѦECúݵfüüUÕéê^˜°fâ¹W¾´Y^5leËeë·R×#sÜ7¸’à!Ÿ0ª~W…@µñê›[_~æÄu~飪TÕ‡‹îÙp_õSÏ›÷½nMmæøž·Ïù~w"½gËØ“·œÛÿ…àf7ÌYÞ^±…Rö¢Œ;©øšÖ~ösŠr¾û—]Ó{ÏJíV™Ò•:¯Ý€cË9Ü!§!_¦‚Lå,ÀoâñÔ<©/;9wN4G’yy‰c²ÉhVxŠo9o¹[¨î´I*¤Anf.ÄX<˲¤’\1xäóRm¡Ü·VÏPüô4nBÔ hŽR É+ÖkÂQ掕_p  ¯*n¢m¯{xÑöópzøòÇ'½9çì¢izH׉/¼üùÌ›Ü_{gwêÊAg”•Dˆïø«³Z°6Ì|6òûõhghF»ý^\1rîÐÉy?zpÔâ+^pâá†f´?áüE+†/Y“£æ‘ùwv,+Î{ßàJj;DÁW…@¿Æ?tí3|ãù¾Çµ54£íq}Ÿ_qc˜›Ö{Sw|ñ÷§Sl-ÖbÐø…¿¬¾·¶c¾ØB¡ξlÆÃ÷¶= „s“(Ï>ûìàÁƒ~÷–D"‘H$š5k–N§…J?Qµç¥?™ûö–öØÍZ5ïwΑsgøåß®`ŒUUT@¬¨(‹QÎ8çˆ`çé@v?8Tî)?îÒ…±¥±4–Æ¢–¯]^YY™L'8àd¡:•4 #™JB4BãÜâŒ1À"e2{öùžyçû­åvó[žÞ1OÍxÿ«Å—#¬qŒª*Ê-ËjÒ¤I$±Ò&tæ£BÈ«2èСâõ3Néÿñƒ_0î¨ßóŽÛ-ÚRËšÓÙ»µX{jíþ¨‰N6%íæZf}Éì]z¬=µÊÅU&ã:¿[Ë\‰_ƒÞ ¸*äú5¾©N¾MZ-²CÁìDoéÚï!w'LS?½uÃU·¿òþúUiï;š]ïeæÌ™’ù×^{íì³Ïvh¡Ü¯Óéô[o½¥~3NÀò·>˜úÔüüq¡<Þ$ÆeWŸ1àâêh4J)ݹuÍóÅm”¸vYkG„®Â^›¼¬¼Xz`‚¢” /ýÒÒÒd²šRÑ5˲0Æ&‰ŠÊ¦MKwîÜ+ŠÇãñÊDuII ã<•2 C;üœÙ_,b&M-bÄŒÈ/;w4mÒ̲¬X,&b OoB$Ç '­=Eyî¬/_¹F¸½`@†‰mÛ„˲ÒÉT“&MUU±X¬ººZÓ4Ã0,ËÒ‰VUUÑôh4Z]UUUUuÂÐe_½4X$Ít4ß×1Æ)ÍhkÆX׈®™6E†a¥Óf*Ç)Âã}Ÿøè™ ›––F"˲0 BȶmÛZ6kfYF\×õŸ~ú©yóæÑx¬2Q]\TZ]]Í€ëºÇ-F™EãŽç>õÑs5oÚ,e¦#‘ˆišƒ†‰Ð4HÇuá/-¬dÑ¥ŽAÓ4ÆlèÐ÷Éo–_ N´êêjÇ";™LŠÁ„¤ÓéX,&Üã+ÊËB±¢¢x<Þö¬i_¿zmð"»¢¼œs‰D¢Ñ¨!].|æóEƒÃ€-fùÒ¡ï“_-»& !5:/BŽ»aþÂRUUaš¦!GzvÓËW„!DÓŒ»vúÒù‚yŸ/†š¸!úÍútÑeaaÀ)¥~„Ñçɯ_†`ÒyÐ ›^½& !Á2äˆ>O|±lhB‚eH×?¼–eÙ¶ÍhŽÕ9ÆX$¥Á€C #â#b\qÕé—\ž!d×÷«çŒ¢À1 À˜Kaކë/Çœpë+ Çÿ6íÜ÷ ük)`.ß[æÛ!0 ñÜsnئŽ9ùüÊá³?™wæÁ-K O"¯1/¨¨öOõf %d‡¬"DªT/ËT¦¯=õ]Ǿ…™jqQ©F  @)g 8GŒ£€€Çœ!ÎFˆ Ž9ç‘XLŽuÖt"]׉8y™6µ(ˆžCåå†M§,àØ¦Ü¤ŒèFU2D3ˆnèF0ÁDcÀ‰®F6£ˆ`¬›Ñ´eŠ`ÌŒDBˆc „ ˆn$ gý•×0±Ò¦† d¥MŒq:æQJ ÖÈafqˤœB86)ã;wíjsε9b¼º¢’¦lš²™Í)å"¾œN›‰D’-¢ëbH#±˜e3“q`ÀÀf¯ªœ¼½ûÀ–±ð3“†º“¾öâq¯n saÛ½†ß:aÖ Ë¿Úòú’{‰7›ëø›TM}Éí‹ÕK&mÜ-_ïÚ8©¨õ¼ý¡,>iÃ.ùÑî ÆË. Óµ„¯$ä(”ðèY.oU4å‹rùgù—Sê·y!›:óûʹ7 hSVJTn}rÿÕç7'wGý¹hÊ'«7UÙ{vì~nÎÊGw´œqasGâÌ3þó JÒ‰&»£E¤Æ,çÀP΄•cœrÆãc¬¹Ýmܶ f¼[OdO8fÛŒ ÓSÈÆ5VmTU§ôšÑƒšý_Ær–3+q3ø ÓAuCÏEv Œ1š1/eÀ9¥§6eƘ#ÌPβPf¤=· Œ1êôãrn„ï!Îd“äZÊ“OK7!Ù%BBÆ+…€.ÏǺ! qUr’y@!ÉŒ­!! á„de~Bä?OBül¹ê,C $ ,!µòk«³ Q-–‚ QeÈ%®_ým¥ Pµ³|ÞÌWïÿùÀ¿žÛ$€¼åÎß8ö¹Ñ¤í#£æ2Æ´+¾så]ü´1µšc~]jLÿx«´ =ÿ¶7.ï9eÑ{»“¶•ܳþ½—Gœw¬ûªÎ}‡-xkmyÒ¢éŠ^{9Òì4ñþ„îeož±ew’ÙÉ/W/»ü·×¨W=Öëâek7ÛÌÞ¼vÙEgN<ã–¼ydÀÔ^ƒ–®Ùd3{Óš¥ƒz=zá£cÂt$G§º’£PB ïåÓþ0õ¬K_]÷½Íì-ÿ|õÒ³¦ÖoóB6µËØÈÙÿHÚôç/ÿquÏ?ý7/¡Übb úäû–á3¿¿uå§øàüº¹¦È/ÆÞÔXÉE€O Ý1K|û=©zD;Âóàý䣪±WCð1ns €& ¤cD–. ˆæ4DõkR˜T ª×RͼåÅN#O—ïœ>ìˆ×†>vÆÇÖjŽ™ùÈ Sûuѳ]>à¤;>_:îýGG´k‹·8쪉Ïwöœûª‡·à®«m+jyø­ÏîXüá\ñþõ+^;éßÏhS=ÖâìauóŠzÕÒ;»ŽxbTö¸`üñw¯˜ÖçмµøôËw;aà‰Q-zâÀ Ýî\:ç‚¶a:¢–ð•„¥€r}hûÍxm|—qý‹êÑ.wä­ ‰ÕcóB6uúÊ'·<2¸$9æÌ­‡/Ø—PZÞõ“êf%ñQ'³¨×‰©TJ¨åS©TMROáJ“Ù¶"Äól!ÝÞäÁ¿ÃyÛ½uÌ+jl‡5xeAwú:e³qyúÁ太;©aL•9 1ΙØÃsÎ…$tHvÇl$æ2G¼ÕIÇùØqÍùEMœå`)¯Ö“ã¼íÌ&ó~æ;¡§'î˜:.B !޾¸ W\1?BÔÝnBÀÇ…ª¶„Ôüºò‚I!™y·`Bdµâ§Œ©-!M¨‚T/„„—!Á„4” „¨2¤Ë©—ô9YþŒ`{ !yç†V'Ì£Ö<õcn\º1O=næNC¦|5$ç´è°ž×,îyMðÝé3lQ@Fi÷é[5]ÝÒ©iCÏ“טìYaÀGgŽœ²n䔼£äîH*ñ|GåÁW…À%úi×=¸îºÅëêŸf͸÷¬¼7 è{ݚڬ˥ov©üsêM<<™û“ÊsÓãØj;¼ÇU÷x‡q·½¹ŒžìØæ:²ä:þ—¡ÿÔ3¿è¼1úÀ?º<’ÜЂ1çܶ©iZ–iS“q[ü“^þsD…uºS«º}ÔÊyZFŹQ1@™cax‘­6s ƒ*Œ8F€GÀ8CØæ€9G C¹q¢¹S U!îÞyâ–B÷ $g÷ïï9ß`„`ŒQw‚ qs®"aËOH6[­'!šœ.BÜêºeH^B‚eHÍn$! #C2‚#!áeH=\cù)§\õçµßn§ÜÞúÙÛ×y[›þÔ8&{ñ ÏűÇr'µplàj¥ôvˆ?·ÀòlON%w©gdäçÙ;÷­å,…Ä(¥–¶©)õÿêA¹ Íì½¶žQýVQîh–B:»ÏeJ ÏàéÙ1ôˆ@íxÿ)BÔÙ×MˆßkKx…#÷$ÄÓ†\щB€Y[^BÜ?Ç3ÝO iây»:È\ ýÞ"¤qòûŸ-“N³®ëÝ%ªE»}ƒÖÒÊÛ»5ŽÉÞ:Ès畱=T%DŽà€Ì²Æ4<«ÇÎì•…Ös`ŒSŠuqN„H6媟ÚÐ=ù7ôaqÝZúŒFcy: ¤ñb(c6``Ìf qN³BœÓŒìÈ!@Ùͺ*¦Å™â`Û6ÒcLXz‚W„@‡ì¾KÙL™U³ûÆ8q¦©i·Å‰5K«šLª„cE3FB™à™E·œH­Éî„h"ø Cˆ#\¡;G[½"—y :?B„®¢pB € !4€À8,!àOxÅ7¯ƒ Є„—!Á„4Œ ‘«¥¼„"Cþû /ìàò§œ|åÝ_ywã84ÄJ¸ 9¢†<†5<¯jê^*ø—à©»Rã,Kùâ0ô©•)œú}Œ±mÛRÂJËÐì-h@®4ÏíxÍ~‘qÛ¶5‚Eˆ¼0c(#M+K(Ä“¡«U/qpG¸VÍAäŒÂ±;œwæydàe“Ò„¸SÝÕ™µ‘nB – Éý‘Çgy ñ Ñ. Ã[8!5Gc…~¦Ùû9!-N! &CÀ?}ɯɝ±4–ÂKžƒ2D ™~‰“lq[òæNhÔ}ÙËc«ÌÛ4•g×,¬&ÒOfÀ9§À)ðLØ=@£8B#‚3“.d#ˆ“Œ<“¶îㄨ Ý„¸_ìmB2ÎY>„@Ö«@Br[Dˆ¥íG@hB0jBä‰d„ˆzÂÒ02$óCRˆ ùßœðöý5DN¤Íhqðý®¼}Ý󿵿ÿK(UÏ!ïk5HgÄË6Bî U¯¹V=Þ…ŒP]c¹ÍÁ߬ÄOÓ4UÔ‚O@UüyZ˜ºž!r(4Mƒ\ß%¹Â“Õñ0€l2,é«%¿/×Fn‰/c/É ²åê\õÐqXŠxÌd@Ôn::ž¹Õ'!†‡²ÄM(NXÁ„¸Ý©TBÛôBÜ¥n„ÈóOBä­óâÖ7¨„@®Wf qÈ÷:"ÛP  ‘ £¼„Ë¿õPme¸|ëFˆ*7‚ /Cje^ÖXj[êwlåó¢éª ï/>«ùê3zÜÜ8DûåÊñPãÇZp¹;÷C¼æàsÀ<;AR&w™0Îl*^ˆwÔBp!r-÷%~„ D„$„g ¤= qÐRg’YB… $¼ &¤adˆ"œóR  Ö8ÚùÁ¼»Oïvx\'Ñâ–§ô¾¾²&ËÞ§ ïÿm×¶Q]oÚªÃ%·ÍH0ïÅ÷ÛîÞ¾UDÚùôYoÿç3OêtpT´;ÿ”_«ØúÑu}Oh^!Fq·ß_ñÏì]BËÖé f;ç¬kŸ>ºIÓáÓßÍÛ˜g;®ý†f´jßýæGWúõýÍÇnéÞ¾•¡´?nܬÕOW>vK÷ö­t¢·jß}ôãozžJ{”çæÄhÕ®Ë ,Þ³i¶ã#¿€ K&ÿþ¸E†Ö¢M×±3ÞsWë1µø]ÐñýÍ;D~{’¼˜U~÷êegв$¦EŠ:×óÖì‹K(·bFÝË:ïÄÚQÍ2Ô¸šj8u&sÔ©nj!7'ƒçJÞZˆà¢ì>Ä^!íå›h¡ rø7‰Þ©2WìƒÅk¡ŠÀëº.^¨›c18ÂÇóÖRj;"Ð8ì'Ün·lv±C¾«ö.~G0â§òuâÈâ&ÄÁ@ QïLˆ#sY Øq»Â Q¶Bü´Pµ%r#WÕY†È_Y^B^†HˆÔ±Rˆ É«0p<‚>Y÷Çi¯ì¨6wnYó‡Öÿ×»÷ ñþ¶wÇ>ᓱ³W–'S›×.n·ñ¾SG¿çYí¥ íYooLTÿ2m°~ÝoNê7§búŸUWï˜:(}陋ï´?s|ÏÛç|¿;‘Þ³eìÉ[Îíÿ‚¼|ØÊ–ËÖo¥¹¾–_ÿíž.¿`Ô² _ÿ›àÆüðú¨ßÝñÑÄV¥ª>xqâº{Îóë~¿{Ößµ`uUªêÃ?º£ç¨×ïoZ4¤ß]kÆÏ_U®þà… k&ž{åK›Ý—{”çæ/ÌÞ¾eÃÌ;5ë4Êñ‰ß@ýôθ_]½ðŠÉK¶W¥¾x{v|µ3UŸcÄÔâwmpÇëÐ_?–JÀ“rÒÀ&ƒîÙøcyºrû«3nÛ¾xXC.¡´ðG³Ž]—‡ƒËØGÎ(…Rªkؽ„’|Ýqx)£b×%ç!_˜+‚œÃB6ëjäþN•†œqGSÝf JxeÎ9RbŒ1Ö²,!G#Î9åÀP®‡‘ì¬m[îÙ‰dôž+_§ùvfÎ&”RÎ)Æà0Gu›šºç*ιS-ªb1à(ë>Yï¯`Bd~„¸'H!êQ!„€O€D7!žáÁe œ—´iG£š!jg !D]UâiŒ\7Bd„B­ ‹Œ0„ËÌÈÔ« &$X†¨¸Á„"Cj[f½÷\ÿ²@‹¶×=¼è¥'Œ€‡/|ÒªÏ>¨¢‡tøÂ˵¾¦¬u×0çåŽk€>7ϵo?döâûº7ÍüY>¡;À8ØñÅß³_o1hüÂË›ž p™øû‘ùwvl™“ÍíÝG‡^0í—ÅלÖ:.Þ hÌä¡sG¾±©_×ÐþWç-\1ªå±÷{ötä/НµëÑïÅ#Ûõ™ìo÷(€øá=&ÌYê|{bûüðU—fýüÝ?ÇŸC¯ºÔ™ˆ×o fýXug·žÕzŽXÎÊÆçÚàŽ×¡¿u¸$àÉÎzâ©íº>vÆ3‹7dO„÷•%”E"Z:m‰“øtÚÒõÆš8À!fÛÔ²€1Û¶(µ-;eY¦m[•‡rÛ¢&jQS× çÔ²ÓÀX2QE-[däE$㪓IÍÐhÔ´-žqíÁ”3ŽP¼¸lSJ¹0Ì„f$jâ#FmÀ€8eœ2Ä)µÌ”™¦œ!„ÌTº8G”QËâ”êÄ@ˆ0ŽÄ¿Œ©Çz$j ß„y¥1@X#€‘ˆæ‚˜M©eëºAôHIóæ»+«´X¬:mÖÒ¥! –I…f– Œ[é´•JÛ¶]HFbq¤i;÷Tp¢Y63"1Ûbœ!à˜Y1„±&:kD"¦e@,Ó41ì¶8P`LÓÄšnÙ,/6-nD"“êT2V\Ä ¥Ò Ý :FV: Q]Ãlj1`„` ÂYT#ÉDBlümJ1Ñ1ÑGŒ‚eRÛJ A¶iaŒ§€ ÄÓfªB !¦m›¶@„%„ñB $!6ã„@hB!„@HB!„@HB¸m’,€¨! –!b¹†`! –!™\BÂË7!õ5…PŸU¦Tcvƨ÷†<ðOQÆœ|~eÏÛ>ùî›qN2é2è¹ôèsNü»ç®ü>dc8dcÛË?}—0¾µþ Òh×íöÙËzçŽðå——ÛsÄò=¥ÿPÇkƒÙùÓVm|ý‘_·´|ÖÙZ üó?ö--”#},c,Y±ýÞ—÷¶¸S¿Y/zvèÃk>«Êh\„Ñ& ÆÅ1ÑÌQ6³fƈ5ç—†bY#e¹EÊ쑳Ûd¾÷<ã_ÍrmoÔ.ÅúA¾)ÂÌ”µŠ{1"î â5Æ™ \ök(+R¸ÀèDÓ4Í Z& G â 1ÎÊã9J{¬‰­ Afg €d/°w påP#£5aÂB…hˆh# ²v6Òÿˆ1Æf6Ó\8´g¾8.Ì;äI‘V/9û~Æâ¦iJ-]2™,//÷$DÞÚq’R7BB t>„@Íû–ŒI¯!ÂÔ7 !˜"îÞ„ Ì€P<é !B,CÜæAu“!ªS0!Á2D•½Á„¨2ÄJì™2ýßyú˜s» ~þŠI«6VÓBòXx DÃM!×R<îÕ­õ5!Íü¾rîMÚ”••[Ÿ øfëÓF¬û¿Éó.ê6fþ†0ÒªhÒÆÝòÏÝ&ùÕ¬~mׯIE­‡ˆ×(‹OÚ°K©áÁxÙ%µ0š =¤.¥ã,r ®>¨ø¾í?bjñ»¶n¯C›ëø›TÍEÉí‹CbÖ¶G¯á·N˜õÂò¯¶¼¾äžAûÐÊas#ÊCãV~Þ¼í“ÎÛ¸ôªw¦ö>½ÉÎ+F,-U5Žwâµ g ÚNЬ^jøé”+Ï×ò&Èóó`÷´„u5«K(ÕÕá',“º'„—"Uu6–õ „X6Ê‹#–Œû,ÕÑ/y_i-+ÃÈ֚¦)Ô2UˆšPBu––A“er7G" ‡a²<‡K%OBäES3‘‡\„¨ñÁ„ÈÆïUBr— A„¨™ÎÜ„Hë༄ÈÐ󞄈9¾pB ëÙ——5‹›U&"Ÿ—'!êc &$X†¨f”…>)¥ ‘!Á„ä•!ªy_Hòè}llrðÜ)­ñ²LísfóÃnÿ$€`ÉÿëRcúÇ[ÜöžÛ—÷œ²è½ÝIÛJîYÿÞË#Î;¶ÎRÿ–±‘³ÿ‘´éÏ_þãêžÊ3ã{ÙGëç½9ü„aO|˜·1£ŸüX¯‹—­Ýl3{Óš¥ƒzMõ«V~móÚe9uðŒ[2ŠŸGLí5héšMÙ½ðÑ1á»æÒ®ylûæõ\}îA= 9P·Ì½~Z¯þóßý_:îýGG´k‹·8쪉Ïwö\'¤é+ŸÜòÈà’Hä˜3G´¾ ï÷KÛ÷{wÃ+_ÞÕó¢ûßnÌ¡}¦­¸û¸ñôˆêÑ“Mè:îo~u.½³ëø'Fõh Æ÷Ši}ï·øôËw;aà‰Q-zâÀ Ýî\:ç‚¶µP°…R%&­Ñéäëš_ùáß®9Pžqÿ‡Oô›1¢o“X¤ãéW$N~0xÄÔâwmÝ:¾¿²\¿âµ“þýìñ‡6Õc-ÎöP—1¯„ÁìÅáÇ-¸ëªC›ÆŠZ~ë³;8·!—PZÈ%”º«ûã±ñ‘󾸳÷AGÅ¡ª¼òåExü ÙŸ%wIÀÉhËcÓ¶“É$‘xèE·ÃÏEõ.V<›°:‹H¯Úlzf<`"»×s•{VŒk¢)9’ÆK‰†r7újh?ÙZãêœëzã9òîóG@@BGdBðñ,•¿RÕ-”\ªcÆ(眈™€qÑx›RȦ!‹Åbž„ÆÂ© !jï !D̸…"|Èý‘ ˜ ÉûÛ IˆCñ@ˆg¦á:"Wž„@ž¨Za ý–`âeý_†\ttÌK›îpäA%¤r÷ž×^y¿U·î„ÓÕiÈ”¯†Lñ1Ew¾sXÏk÷¼& ®yÿlÖåÒ·?»T¾?õ&ž÷òxëÓßù©*LcN¾öu×> ÿüë(oƒžž#&¯1Ùó£3GNY7rJ@ïÊ1¤ Ñ0Ãè7PÐùÂ1ï\8& ZLj©ÅóÚ0ÏÛß0Cd”vŸþ·Uª‹ã„!ù1;¦Ï°E}4A-–Pnu:ÆøÂ[{|ë²¾ 3!ç‹<äõiGA¯ ¿bKÊY&”K:Žê†®ëXÙjK­µ#Þ´ûÌÂ2ÂO åÙ¹‰¸b(€EØCP Ä$áìô¸v©*w!³4M£D8Ö`\T:qÎydÎrh¤T€Yˆ-Vƒ2«qª 7]š<:Q£"É“5Ñœga[¢>,OBT'sõH¨n„8fÇBqë¼!ÉGˆ<*uRt’YÊLHÎ "SDHˆãÌ×AäFrª3! 7 !Á2$SOÁ„¸ÃÈs†¼öžwÏ\ž‰+XrP»…Á9 ¤±4–Ʋw—Pž™AW>þƆCŽyî¶¶'ÞbÏÏ»ž˜þÆ%“7½{GG±u_+ )duJ)Ž` a”íÏ~¢^úÓñܧ꥞ög=^/õtP?JÅ“.[X/õœ8ä•z©çÈ~sêg|ú̬Ÿñ²¸žžWýôëˆþ³ë§=gO¯ŸßÅÏÖO¿úÔÏïôØAÏÔK=].ž_/õÝÿéúy^}ëg| 7º© AX#”sŽ‹õ"B£ìݧWuP‡ÅºÑRK쮘3çÍkÝòÒˆƒUµVnвÆÒXËÞ_B¹÷+|XõìÂeÉ Ä¡åAŒºéws†¬d¬ƒt\°ŒœsÛ¶ ‘¶‚×Ãu~µìÛ¶+++9ç%%%b·{÷"MÓvî܉DJŠâ•{*š5)Ù]±§¨¨HÓ#UUUñ’âT*¥içü¨óæ~¹ôêò]»JKKãñøÛ¶5+kaYVÔˆ0Ó²M+¢é6gfD3~4aœs‡Ì9ïØwÆ×¯^gÙ¶hF:Ö✄+**š—˜¦i¥ÒZÄH$ª‹KKLÓÔ4Z¶eY¥¥¥¶m§Óé­[·ö¹õýo_!–išUUUMš4·‹ÅqD¯¨¬,--µ-‹Ùtû¶Ÿ‹ãE%EE¥†a€NöTVØ”ÆãqŒñ1çÍú`Þ…ñx¼I“&©DµeYxyyyËæ-ªªªb!TQQaÄ¢¥Í[X¶Í¨FUÂ;Lt1ÖuÐÂ5ÏžWÚ´yUUU$çœG cÏž=%¥M8ç„èœsLt±ÒÕ4ÍL¥)¥ñ¢(çÜ6-Ã0,+1>¼ÏŒo–_›Ù@1¶ýç_ÊÊÊ8ç»ví*++«ªª*.Ž———7))Ñ4­ººZPFœsjíÞ¹#™6‹JKº_úÒ·¯]kÓsàt2F“ÕÕ»¶ï().ŽÆbÈÐYVgàGÈQýç¬~z@Bâ±¢T*åGH§þs¾Y|eBÄ|æGH÷‹ç¹øŠ0„´9øh4êGÈá½§}û÷áa¡¶]]]íGÈñ—¿´qÁÂbFUU•!Gž;ë«åÃÂ’£bqrÒEë\†’Ò¦H#~„œ6üï_,†`Òõ¢ùŸ-¾, !Á2¤cŸ'¾ZvmB‚eH·K€+Å´¬’ê(±†’§ùS×%žx¢K—fQ‹Ò­ËnÓçÉAK Áçh¥qdKÝJþ/"¥—؆!=e‘H$+%A˜/HCTÕFüiš&缨¨H̆a#Üߤ¦:‘HÄb1©ÆF£B²ˆ/ ¼x!\x„ÔK$2¨Ø®Y–%ôürõfš¦eY²mª!§ÜêÉs ñ]×ŲO&OMØ:Bä ˆŠÆ€eYâ@P ÓÝ´e]£ÀMÓŒF£Ò_)VUU‰Æ§Ói1ȶmËC“êêjH&“!Ó4Å­¥%‡®ëét:‹iš&®õsÎERñÍ̉ !!˲c©TJ¦;µíLT!Ó4…°¯EGTÛ õôÄAˆh¶B’®ìŽS¡0„¨~^ž„@6ùF^BÄÜïG(FuÁ„ˆ(Õ…bYV!òp-/!‘H¤^!„"Þ,œy˜—`Y¼¼„ËIHxÒ0„¨2r `B'¿ÆÒXb %… ´!¸¥[Ñu“Önü%M9ßµmûÔ)oµêÞCµƒÉží„³–£À8ÊÄ;ÎÉëwzè—BØvÊ!µ¥'³š-ÁaUpXY[M»ÃËac¡Þ=ÇfK, pŽÀæŒWÑÝF¸jqX%»SC8†NuYâ\VÆ!óbúÅ›–Íp°o¢®æ÷/BT“šBQ¯òc£pBÀ+:‘'!Á2Äñdÿkdˆ{¸Â2¢slì¬/ÿõSµÍØ®_vN¹ÿÕVÇv ¤qòk,e¯äy ˆ>£ûì˜÷ÑMcÿXaÇ›ŸxÂ/\ÓNH¤ø$×\ 2¨gݔԤfr–)'€ŽŒujZSž›SL*ÔÈ+9ç’~é yNgýDŒ#õ•#5ºç鈖Pc ÆgrIm„(Æãª›OÆC*ó—1~Ò_mŒðw{cÉ!uä‘ PqûeØV} !Ä3€…($!Òzz!Äá·—Q—nÁ„8²D;q,wö#B‚eäº.Ö¨BÜ«Ì0„œ9üôÏ[;òöE?VØñÒ¢_ŸrôÓ—¶CVÊg¿ÇŒA}ÝôÛùczß8íÛÕu3ê hdí߫ݯß1l, ±„r,ÉH"½aÄYWMš†J&“Jl^ð” j¨=iTί`‡’ÂBêÌÁ'“«w¿Ç,•Éä•kcû.à‚æ€ÜL«<ënã^-yî )pÀˆe¢C®å tJ©–õ¢a"Ý£Ô¯#{¼;'+xE¬q¯2ÁÖ2û>·Ïž'!ŽIÂ-úïâ§n„¸Ãö¸Ó»î;„¨ÃLˆÚ…}Ÿ÷2Â`’©§`B 3/! #C´P2D3â—]Ò㦚i†Á9×b‘D"QM} ùÏNÉy¯ þ•×?2ñƒ­—U¦¾yN‹ø%_ì¼$›mÇú«ËºÍ¾hÕO/üºµx'¹ca‹NO'v¾Ò¸ÔØ˾ùDB…ÖtHÏïdd"¯R&Êh~r™Ñ-3æÚo©ÊVYGÍî®n‘e:Õ˱‹õ“}ê“S»/“Þ,üÔlŽ >âMa?‘qÎnAÃE‘¦HIÖ!l;Ü«È2¯Šl(Y*òƒ•¸B#éGˆ_UO-T!„ÈÆ4!ŠØZâ丗 >]Í%â'gj+C $!Á2rƒiÕY†¬ŸjEHÞY½RàÌñ™ÌäMWU˜ŽõŒî}ð´—kÀ}õت²SË>žR“ÌäÇ7§rö­û`¿Ëþ[B…ïsè“!7È›ÇAÍQ¶«F¦žá•ú|™Ósl)@‰AìP«ÂQµñŒ“Wßîi4 îž…ýµã BÄ»+©a"ŸXnþyQ³eYÒÜUFô›ËÝQsÇ+à <ã¾VN êP8ÔHÁÒ¼BÜZ(OBÜ'>BÔ£¥BW®’ÿ5Bܶ2{ƒÇÒ­Î2Äñ€þkdˆ_%õKHÀÍŠ÷#%Ýå*ûúcGe_񨁮û¦{äÕn~0ïîÓ»×I´¸å)ý‡¯¯´îU±õ£ëúžÐ¼(BŒân¿¿âŸ_–·£^x]n?sã”WåŸó_ýaÄ_ÇnûÇ ùΪ‡6ôº½sp#úõéÂûÛµmT×›¶êpÉm3Ì{±åW³_O+¿{õ²³NhYÓ"EŽëùÀ kÜuú}'ø@yÃ’É¿?®C‘¡µhÓuìŒ÷ò¶°À;"„Þ|ì–îí[šq@ûãÆÍúPýŽßG°ò±[º·o¥½Uûî£S½jùÃ:ÔŒ(òg_³ä å‘çWÔ¿Ž¼Qîlªz\Úøí±ÔœªÐt¤»ãeUª)ú†€}d€zLM*w¥ªàv„Ÿv”{&97䵎ÐÉj32©Is-]šª0{YÙf·šD}vŽ3 z$ÄS»ãIˆ{ª®!îɬn„ä×S¿Ÿ—‡­·ÛÌ<$!n[Àºâ>˜Û„@N ‹ºËÈzÀHH€ÙK„ä•!àÔ â&$@楧ö}õÌÏ H—¯œñéãUšPõãã߯œZj8–ƒÍVŸ¿¬ûã´WvT›;·¬ùCëÿëÝ{FÀ½ÚŸ9¾çís¾ßHïÙ2öä-çö!¤.ÊΔL IDATq³Nùæ{wÙ ¨ùÃìÝMoë>²uÕËÿª¶¸}ßWìO›…i¤»_ÛÞwú„OÆÎ^YžLm^»¸ÝÆûNýžgóüjöëé“6tÏÆËÓ•Û_qÛöŶÃ|ÇQ~zgܯ®^xÅä%Û«R_¼=;¾zLÞxGèwÏú»¬®JU}¸`âGwôõúy?Ú´hH¿»ÖŒŸ¿ª:]ýÁ ÖL<÷Ê—6Ë«†­l¹lýVªd«ßcè½¾„RºX¹Âg­8ªÙ*iŒ5a§™û3Vµÿ޽š|“h('ÃB‚–PRÛŒ1à "X¸1‹o‹ (»™ó_ÞÖ ”²䀕==ΙrS„ƒÎÔà¬'ké"®ÂHz¹{vÈeŒ1{tàÀáa¤a¤e;Ž€f€Ëÿ(÷Uˆ;qN9Ï–aä7ãòì¸Bjæà@Bj4"âž UBÄã(œŒ¶)! ¢Ô“‡‡Û¦ƒKÇ„ˆ†Näú@ÔY†@½¼„ /Cò)xÂÊu&$¼ q,ùGžsèÌe[àû¥÷ îzo|;gÞ¡çŒÈ;©Ìzï¹þ'7HQ‹¶×=¼hûÇwœ—íøâïO=¦Ø Z¬Å ñ Y}oÔ°~ÀímØÝß”@ÅwÆÚŽ}L‡Òû?ßÕ?ÏþùÀ±e:ßHµ<|ùã“ÞœsvQ4=¤ëÄ^þ|æMµê¾_OßÙºrÐe%bÄ;þ꬇¬u׿;Ž2yÈãÃÞX6øŒ.qC+;¼Ç„9«jõ€êpGùÆ‹ýz´34£]~/®9wèä¼=8jñˆ/ 8ñpC3ÚŸpþ¢Ã¬IÂóÈü;;–ïÇyµLfÛ¦i¦³mÛÔõLÀž”iZ4öŽPÎÓ¦MˆÓ£:'Ô´¹I †IÒ²‰n ›%*«xÚŠëMÓR– $»kç1Ì,Q“E´Æšˆƒ’¨ªd¶M'œišfs;‘H€F£¤!l-ã ϹF –Iu=‚a@cD0Gˆ"°³3mKÈUÏÀ[VšsšŒçÀg q@€aX"•àˆÛŒZŒÚŒGbqH3"”s‹RÍ0v•—k†Õ©”&M3mÛ"š‹Û4„eCˆ-µ4X±,+‘Hdl‡u½:‘Ðtrà(çˆh€ ÑuÀ8Ò"›1Ó²#± L4#mÚŒ#Ž eH› ˜eqÀ<ëlÁ¶mé:±©ÉrÌ-f›Ûˆ€M©¦ë ¸Í(e@™àXü+„CÑ0c,€I$ê…KÆõBe,€MˆÍƒ€„djð!êE†@HB‚e„$¤adˆ¨jo\ŽÝë‹¿®€%÷þ«ÿSý?¹û]x~Æ×½FwR5è-ÚZÛ¾œøé­+Î>±eI!DŒ2;ùu!óÙ¹7õúCà›™ïtþ;øÍðŽMÙ[—>}ô­}ëÖH˜ùcÕµmšˆP^c£¸»U½®VÝ÷ë鬡'žÚ®ëàácg<³xÃO ïeYˆï8/ù±êÎn-êü€êpG}t3ùºùQ·Uo››÷£ç·'Æv®igóη'¶×¤è×"¶ÛByRøEŽ›]„æ”!›ãB¬p”RjÙÈf$ëoäÐZc€d¶K; ‚0!„ˆà0Œ:º0îwd #Ê`Œ#Ž0ìŒ;çx•cÈÍWCS (g¹– Ù/hš–Ù§’?/‡‚Á­íó4jÉ‘•Œ1¦œdvð˜#`9ßGa#„5]׈!6¦ò˜L޳*‘³•pÑ›Œ½…—á‹C ×ùì‚ á8̆;!n»ŸBD§ &BBiB $!$;CHGõCHH’—ð2$!2$ðð©v2ö6!Á¥éøæûö$6ýy3ô‚GÍÏ&TV9õg<ሦõ;9ùüÊž·}òÝ/6ãœ&8/(óL›óoغô1xyÑ–‹Ï?9÷âŸÞž oOýrÔymê\3åðYeʶm™…š1Z/==Úª¯?òë¶ñ–Ï:»S«þ‡ûÚ0ßñ„¢Îý­ã¹ïAù×¢ïóñË´ßS:dDc­!c›sáxL)΂°mÛ–iRJ5ŒÜ픢Z\“3sl/’$ˆƒ&¬ˆ?Gð ºJ@¿sá•ÆŽ“5‡ºšÝ]Z¨©Iknêr)wOØ2K|¦…"žb0« ñšÿ¹Gµš–É{Zsl1Â8cqÂ@T/qŽá…{^^„€0øÍGˆê'åIÔ !àc^][B9„H[ø½Jä> D5-râi;UB u½¾dH^B‚eäVøËyǽJH¾C±–cNÞúÒ£Ýtû!壗Ü;l\KݹëÖ¢¤®3ÐÌï+·ß4 „ ¨üþÉç³ø—v7¯~wçÓv6ÿùÀb(>pX‹ŠÑŸW=1y{÷oZÖB¥áè×µ‡{uëâ ÚÁ^èiÛ½†÷èéÝÿWÔzŒÿÙ}¹çwšëø›íÍ43¹½&UèÕß÷¯“Ž+«sƒk{G˜´q÷]3*¥]'µ’÷£?”Å'mØu_ö£ÝŒ—]æ‰ì7¶PòרþžÁËýG‘¶m ÃF‘U>“1ʲ¸gÜ<ÅÈÑXHú‰¹ÙÑw¤umá¶{u‹wlÉ`©§ 8‡4%ôŸëÂA&Øì]5zuØ{6Rñî³cÆRŸ‹jêîF Fˆv˜IùÇBˆhO^B¤É­!R»–—÷êÓ3ŠUƒ"­•÷*!9F0¹1Ä€`R£BÊGH° q,¤ê,C‚Rá q(êö!yË979{èß¾õ\8wô1³®yãÈÏqí×¥Æô·ÖYwÔ¿eläì$múó—ÿ¸ºçŸ ŸÒîüÍcŸMÚŽ12ŠJcL»â;WÞÅOS«zý=ÿ¶7.ï9eÑ{»“¶•ܳþ½—Gœwl½ô´sßa ÞZ[ž´hºâ£×^Ž4;Í}­ßw&t/xóŒ-»“ÌN~¹zÙ忽F^rËÜë§õê?ÿÝÏSݹyݽWŸR«ÖÖáŽðX¯‹—­Ýl3{óÚe9uðŒ[ò~4æ‘S{ Zºf“ÍìMk–êõè…Ž óD €¬ÿƒ»cñ‡sÝ×ú}çú¯ôïg?´©kqö°‡ºŒ©‰zà÷øD¿#ú6‰E:ž~EâäkÕÚ:Ü–ÞÙuüÀ£z´Çã¿{Å´>‡æý¨ÝÀ§_¾ãØ OŒjÑNèvçÒ9´ óDöƒ²BÉ®HŽ·¨ƒLÒ’|„¨ª ½Gˆza!2Dþ¨ó,CO0€†‘!¶W :kuçW‰×±–úE¢ï4dÊWC¦ø­óq6ëréÛŸ]*ÿœzsJPg«æQkžúÎ17®Nݘ§Iîšý€Ãz^³¸ç5áÏñïøõô˜>ÃõÉ2Àï;Fi÷é[5]ygšt¾pÌ;Ž ßÂÂïØsÄäu#&{v!à£3GNY7rJÞÁt?‘}!º–™‡Ü3þoΜ×lW3—0ŒpjÙ¶i1ËÎ9G X•õž'%R·MªøsGrò\B©ú ‡½‹[y.6©S…°%YÄ3tâ>‡srÿÔ`ÂÝ )çPÀ8cŒA͉¤ÜµKß(áìJÄÄ‚xF¾#î1GRJE{„bc Aˆ¨Š‡bRyœ1Î÷\ÔCˆ /^8!î3;Gpóz!$cã‚MÓÔ8×B 4!(AE8Bpý‚œ+€½*CŒ¼2c\¸ ‘gÓy A…ÒXËÿriÚ´ék¯½ö»ßý.øko½õVÓ¦Mëa åŽìØvSÆRl „g3aÀ,›Ù6§ a¢Š¤Ö©êqÎ0Æî苪BÛS›íh˜§ø‡umˆSU‡&CŠ?Áž |]×Å’E•Ô9yÎ::k¨áŒõ'Û잃U+éš3êÕÏÃAƹ؇‰­ìyLS(! Lˆ»ažK¨ Q—PÁ„ˆS§Â a¹Éï<˜Â¢ªÇö BD†¸Ëë&C o‚¼Ú˽GHã ÚX—Pb…”÷ku_B £±BVñÛÖ4Ͳ¬¢¢"¡?§¶…0ŽF£ \YTTTUQÑ¢¤ÄÐôÊÊJÛ´tBŠâEÑhÄFܦTcŒšTм”™”ÇafehÒ¶L& †‰DBIB¢Ñ¨Ø«Ù¶­ëº¦iÆb1ÎyQQ‘øšHJ*H©†¥R6©Á|U÷"„g(«·'âMÃ0‰DiiÓòòr˲cÑhT¼ˆD"bƒiÛ¶”z«(N'Ó©XQ bgâ  aÄ1€x<¾gw9ÆØˆFÒé4ç<‰`„Ò©”ÑhTlpMÓ,)Ša€t:­ëºðTÒu1†1ÂÙ¦…¢1Ä!YõèzÄ0¢‰F֘͒ɴˆe¬D1&ÒåGŒ !º-ƒÒu]ì°¥™|†\wB !º®‹FúÕÕÕaÓ§!P/„ˆ‡†d2)ÚæIHf Aˆp7ó#D´' !<ŽÃÂ-”›©a*P†ˆzÂ,C $!Á2DY½$C¤ÜÈKHxâ&¤qm,õ[Âî;¥M›6mÚäuQQQQÇ%xùÊv»èyg-Ñf_-¹ÈiÊSf¥MŠ8¢ŒSŒ ç@€â!@žVŒ³L¬ì\ƸXÕ©),Þøâ}˲,F#ݽÅtè«Ü^0¹ûѬc´kÜ6§ò…ô÷Å¢<>Õ,—d]Ò˜Où}Ƙ•‰ÔãAÁ„d> AH­dH!„€[<$!ú>áËÏëË„j,¥±Ô©h!eŸª²þ×ÂÁ±XLü, ÃXô§gvÍœ&rŒ8Êõ ±¬4µ™MAMŽ1ÇÈ!w>/ÂÜÒ±0Bˆ#œQM«‰«Ü¶“ªC?ï>ûSÄkÎ%w6‡¤sçÖuˆ?ÈF(vÒº‹ô›øŒî=ëÌ,50 ®‡„mËæëº^óŒçÀ²_v*jžÑÌ!G#qôÄ¿¬ùHf/í·“ð4o÷O•{aÍPמi2\8!ŽDlÂ!ÇÏ±Ž„dt6’©ß‡çj)ˆ@H¶žü„pà @(1 !ÄsY¹ßòåÒ¡@YEùJ©¼óøò:÷ ¤qòk,¥ð‚CªæŽKò÷ŸÚ³yâ§ÆÔ>MÀam@æ 6‘Ô²)¥bûˆ²›H‡Èp¸t9ä‹|¡ÊJ[êÒE0=pÅ} è£ÛBÂÓU[ÝúûYb9ü}Ä®Wªè=Û ^¢z9|³¥jA\"æ·½(Á=WÆ™ÿ9—%¾Ÿ ›»†0„8¢v©„„"DU&í„@®³d!ªaÍÞ#DË~GH° q,\êLˆ·düÊùtêFˆYõã„õ‘Gû6 ¤~'’†Y“5üʯÎwü¯Y¤6@GtÒ~/ö§%”êÖëËz¯ë¥¿nFª’?ÚìñçÙÐp~Zkq‰Ã€ÚMWmxñYÍWŸÑãæÆõмì~£µ0'w;ñ.y`õ)Ãûc°ä²m;LY–…B2R€Ž1RººLÔëV?gf½ÔsDŸ'꥞úê×)W-©—zŽ4¯^êéÔwz½ÔÓý¯ÕO=ƒÖK=ÇôŸ[/õœvõ+õÓž>OÖÏóP?ý:âìúyî].|¦^ê9ê¼úéWÇóë§žõ4>9«ÆD®@k†¯ æœqÎ_}â_']}V1âêѱNÍ»„ú×}Vñ—-O^/þlÝáøq3W5=ç°¾~úá¸c=5”Ì»ûö)Oôùfivüï/šöÌÃÇ–d,ñ?]xÿˆ??ñáÆG›ÖgÈ­OÝmgjxåþko~dÁ7Ûö$Ëß-9xd²òŸ¢e×;júú©bݵ86íǪSK ¹ ®üîÕ®ŸøÚªOËMÜö˜“†ÞöÀ˜‹{ß+”¦€­Úu¹áÅ#9à1õ£Š­Ýv݈ï¬ßcé]~sáœ%3»g{·aÉäQžþÁg›£­zÇã÷sfhÙ±öéßüîÆ3î_úøõ¿q<²•ÞúpÖ¸ëï}ê³ïË›µ9æÒ›&É»Œ¹[/+©h¶gQÇÊ3Ü~¶„rûsÉ×ÕÛ¿¼os³µ§—¦Êw×ìóÇ”4«}·­´m¦8cÀÌ1â$»÷U~Éëæ_l%LCÓc%Åј‘Jšl é$UYÍmZRO[&Ö5ÆX*•*--å6M$E%MlÛ&ºF)=òü§·¼1¼¼¼¢´¨˜R ˆ!B,jK…¹Ü¤ glP #@±ÕèØwÆ×¯^—ÙÂ2ˆ1›jšÆ9M¥RFDß¶m[óæM“ÉtqQ‰išš¦™¦‰ŠÅbéd²ªª c\ZZzÔ€§ÿùüEét:‘Hˆ„%MšiclsÆBnSjZU•š¦ÑC@I™iq.pì…óÞ{ê¼h4ZRRB1“)¢¡Ÿ~úé Ö婦i¿üòË!‡Â5dÛöŽ;š—µŽ(¥š€êªd<?²ßŒµ/)))I[„‚dª:jDRf:^T„¢€„÷µÜ‚kH¹Õ8çqŽàˆ³ÿryF¶ê˜sΓÉdQQ‘eY‰D¢¸¸XúÒ‹ÍýîÝ»ãñ¸0ã`¶e%R‰òŠÊ»O÷þÚ)gi±ÈžÊ ÆâÑâââHQ:5èD¸[¦¨ªò#¤Ó¹³×Í»0 !F4Fñ#äèóæløÛ•aQ·nBŽðô{³Î C¥Ô²,?Bºô›õù«×†!$jD~ùå?B:_ôÜ— /C`T]ô#¤ÛÀg¾~íú0„¨ 7!Ý.zþóÅCÂÒªyY"‘ð#äð‹žùê•«Ã,CŽüÒ/]†`rDŸ'¾yíú0„ËŽç>嘊lFMÛbÀ1ÃÑ-çÕ;¾›²µÉªÓš¸Ï‹k4Í8¿-Ô”Ç6ܼæ2Ç›—?qóm=¦À¸§é¹Déó—usf¿Ò«GG^¹uÎý{÷žñÓÿ€mïŽ;}Â7Ï>³òŒníRÛ>Ÿt}¿SGõÉ”ÌbbØÊ–o­ßÚ±¬úǾzæçÄVñtùÊŸ>~eåC'”U?>þm|À©¥9+Ç!' <è¾%ý¶y„~»þ½'' ƒ‹×æ½Wˆåª½}ëWK¦ßجÓ(Ç'íÏ?ý©9-92JËÝwá¹ý_øáÍËà§wÆýêê·f¼´dé)GUo]7ýžQ0l•zá×»ç7W<ÿ§e®ûÍAîö»gýüWV÷îvð¿×½>ôœž£þbjïCÜ#³iÑ~wm~ö•UçèŸ,¿ªï¹W¶Þ ¡ø5 `(>úáõQ¿»cÃüW>ìÝíàþùÚ5眗wÌzS•Š€f{–à±Ú/ò(gXËx… ÎKŠŠBf*¥2ï/÷¼ñ´(Ëd\!r5¬Yi+™Li†‘²Òñ¢3MlÓ¸))*ŠÆ£ ó4¥6F€1£ñ19ÈsÌ0‚8²)Ö0&¤ººÚЉQƒJ§,Œ4éA·©mÛ›q¨N&s†ã6Ƙ28³-Ó¶L ™Ù†ÇÂ>€S†aAüA` ™O™Í)ËäNà!”N§KKKMÓ6 ƒ·¨­z¬(.÷yÕÕÕÒ™œ#d3†‰ÆãÑx\"³¿â¨EMYϘh9‚0V¤ N¦SÍhÒLCvÇ4¢åb>KY¦pÎM+5L©Àæ”Y‰èœSj¥£†Æ˜¶)D0Ñ)å¶Í ƒhâô„Ò1!0ÊmÀœ#àC`1š¶­B’ÕÕ€S_B !! A"F2 !i„@HBÄÉ“!â€; !µë‡N€„pŒ€„ä‘!! –!â”3 !Á2DŽs^B‚eˆz0Lˆ[†¼4íóß\}¼! ,Ëw%/k]äx3Þú²Ô®å~—Ìzï¹þ'7HQ‹¶×=¼hûÇw‹÷¾üñIoÎ9»G‡¨FšÒuâ />ó&yÕ#óï«yΡ3—m€ï—Þƒ4¸ë½mðíœy‡ž3Âq¯wv§®tFYI„ñŽ¿:ë¡kÃÜ+ÿI Ñh{ÌÈi?¾øîD§vä‹¿<õ˜bƒh±ƒÆ/üeõ½âýÉCöƲÁgt‰ZÙá=&ÌÉY?½ûèГÇ~¼`ã¿5ÁÈ7^ì×£¡ízô{qÅȹC'{ŽÌƒ£XñÒ€74£ý ç/Z1|ÑÈ‚0M:W6©ý¯Î[¸bTÞ1(Ív—¼cµ¿j¡dJÕÅ·òÇO§ÿÜbÝI%ŽKfeñQÄ(giË¢–Él‹S¤ÁH×€`·Ê&&§Àgã3!ÀÀÏÚ1 0 8ç™7³—‹œjFTÎbœsšûS °'`œ£NÆlÎõŒùmn6{¹½“fjˆ±úÁœ`B0Ò¢b¿X£’1Œ°ËP)=HM(!¦@ÑGi’ Æ#„!Ç&Cí†b5l3FÔ71Æ€‘# ½ÃXŽ…LjÕÒÖ“¿#m•Cçœr@ˆ„#Ämâ£âÖWÕš!ÍGˆê„ï&$ó¼BÂ9 Ämȵ· )Cò,C Á –!nK²2¤rÛçOþÒìíîñ„ÔoP«™W¢¨µ]¼žùcÕž6M®UB5£×¯EÍUGîõÅÀpM§%÷þ«ÿSýWÝý.ôüüŒ¯{½~´s¹6ôÄSÛu½à¢óN;é„Ó~ßûèãaî•ßæ†Û¿lþìÉ;.¾êÒß¿~¹úÄOoÝpÕí¯¼¿~gUdµ³~¬ú¶[ Ïj_¹½÷Ëø×ú%¾m}t3ùºùQ·UokðW÷È<¿=±©sÍ]šw¾=±½=Àô€ EÀGs·U­6éè[îó€Ðì:ŒÕ~©…âOJ=‘<cüÔ=ŸôÑCG JU™lD×u/ز,áö".”í<]©Ý¦—ÿŒ1ÑB\Jeâg<ÍY•KÒ¼iS•K˜z•ÛeZ=åt¤…wÈAá-Ò5¨9¶Ô@Þî‰D†3v„úe_÷¾Ž%”£#këž#Ýs¶:¤ÒµÞMˆ;)©›CˆgÒåºòÿì‚3r- IDATw¼,E•øÏ9UÝ=3÷Þà!P„'%)Š ×eEI’L ‚iÙ5ìºÊŠ‚Š"¢J×€×@’$Y@ —nš™îª:¿?ª»¦¦»§§ß½÷=ÀßëËΛ;ÓS]ýíS§NÌ%½ÛœÕ$„YW…t­™^Ôólñç§šbuèO³¨IˆÏd‘ðJxWR-CŠKàÌÉ~}8!õeH5!Õ2ÄݑՕ!ç|þÖÝÚÉËC t¼q½æyMåÞœ~ìÜÆz{­î£î˜èØë&­ìÕSIo"<ÿd~賫¦üôCüå¾ßqòÄÔ=§?N'??ß^ãMgüö®Ÿö²ÍZ×_uöž[mxЧUç·jCÉgm¾ÓG¿uÕ£¿üxî/'½üM»ŸxóO(ì§ýF:0 ½q—7ìÕzàûçü쯕êÛÀCÔ\®@ÅTTü‰ûOÌ5æ|5žù\=U¨\îëúÁ¯¾íÓ;¶Š‚Ã=í6s8IͦWd2û@±I»ßÎ)çOõ3ŬÏÀo†…Ôe'2z}Áj4œÏ~K…2Òœ8v ƒN‡è9(‰dz„Å$çÒµ¼ #ûO?]È­4¥­Ð P¶gèö«¯ãXaò«Ï0ˆAK‹OˆU¡†â+7¥„ø×RMˆk¼ZJH-Àº¨šÌ˜—dWJ èüX$Ä^Ô B PVû©%ÄÞ¦:„TË7ž¡„Ô—!Õ„Ô—!³!ÄW¡ª ÉMþq_xó¿mרIHõUüë±Ûžúž|Èÿ¹Ç|q»÷§‰XS79úÙ£»úáZ«Q°è#›´?|éqáæßxdã>{å —}¨ùÜ- JÖ©ÍvÙãØŸ|ö÷®º÷/?¾ì3¯îoUÞAæ7êüuâœí¿éóÂÄý$#7ýìmO–žgñnÇÝò_8÷NºðÎA¿uÊ]+Üëåw2²øˆÒ½yƒÖ)w.wÿ\qçç[¼¥zSQñ§#6ñ‡´âÎS†ÎyŸW«ŸŠŠaÏ`®ž‘*”¿•,nÓ+ú6Xï{ÇZkÎ:°WýútsúŠùÀ}ò ³ö…»Wr°o‡WÒQd€+¡¨Eù²¯¯=»6€@‚¤R†\h¢`ƒ‚P²±V;:I"€²Ò8~-A¿TŒ[í;všK‡ö§¥¸çÎíìsÕs½AŠ¥™‹YþÀ˯:q{û—Í ¿vÃÃu*œpá‰?yÛî§^rÝŠ¶JÚ«n½îòãöÝqЇ÷úÀÖß:ê·ýðÞ°÷ Ûý®Ÿlý»× ÞxÌE×Þ´²èîøõ×\-Ü­ÎoÕЀÍÒ‡nýÜ‘{o¼ûçsØoQó}ßúU[éÇïùÕ‘»ÿ»{ÿøsÞsÆû]øë?u½ì¡[þóÈWøßZoÇ·^ë¹??ö%Ç|ý¥¿÷•=½ò¦‡”QÝtå!¯;ýð3/ýØI§íú_qãƒÊ¨o¼âà=¾|à—Oª@ÅTTý釻!=xãïqúÐ9÷Ã.Cçê©BÙ ¿çËùJkŸ$iQ­²ή« ãɲçÚ÷?_dä×ãG¶ï›,ƒóƒœÕ4•¶²"tGkW°þ'§ÀËä*nLýU$·Â?ow nÊ̓«dS|3·”æH}-­²]ÖÅunÆ„@BÜÂ0ˆœÕ„ØOB*ê+–:zâÚÏ’¢ Uì}T‡œJš#$·öÏ^† %¤Z†ôüô $g…šR$d˜Ahƒ o»e߯­‡½jÛ‘hdÛWv{s¿[n9‘ÌâiN{ïéûl ¨nïÏzéÇÿtÅÇ~óåã6_¯ÙZÿ¹ïü v8滃>üÜߥ»úƒûn ›î÷ÝÕGøÜâǾì /úä;Ÿ³ 9²èy>ÿÉüᜡ¿µòÞSnyü 3Af ·zùA·¬÷Ž?üðí¹Ï|ígßøËi‡EÑv¯;nñ±¹÷7úçÿþÃ×÷9ó¸7ÎoF[¾úíÓ/Ïë^ó–ìóë;tÏ'w?ä¿Rüé+>±Ã¿´k#hìrÀ¿½èS?=ã Ï)áæ}çòïxòA»6dc׃NÞéW¸¼¶A¨˜ŠŠ?=ç güôS/ü·vi—|òûáÐ9ï³ÕõSQ1ìÒ£z®žžÇpr­µ}êÀk ËD Q¡\—û$û désh#=¥”Ä‚À°bã;{©aÌlŒ”²¸u?—IDÚ0³«P\ w0Ö žŠAf4œ?IÕlP/žbo)+­¤” ÀÆ(¥’Ð.Z–Ñ¥»åü9—VŸÙ ×&¶?JktyçÁþ*än,ífêϹÛçò­rñÑ¥ÊîŒ €(Šê’[fLHº§@H6†§ !ý'¯"¤ÔG…°ñY})<3'Ľ9Kbϳ6 Y;2Ä!›+RAÅÿ'ǧD,­;ÖkP…’RÚº#Î ”¶‰È\6¶0 ýìÆ ívе¥\JíÈȈ2ÚÆÒŠ@2¢W4V) i­Ã¬ÿ|¢T(Fã8ÃPaE[D‘bùø²F£aŒŠ“ŽTÒ%q»íˆ819ÙKKk$I¢”’2ÔZ0q–ö,„°V|ŽcÛ©'µ]«sB¤N§ÓjNMM! "J”€N·E‘–RÚñûQ)BJ'ÛíöØØ˜Ö* C;™RJ¨„pyFvãÞl6Ý„w:)¥MM²…m2EEãã“óçÏB$I"Ã4 =Žc›ÐdoSI{ž8Ž£FËŽÄEHØøÜ$IÂ0´·Ì-“Î~ëTê{fNˆ—t]AˆýL!öÖ!ÄFï"ºÝnB\ÚRB &!Av:A„8‹Å, qzÉPB‚ ˜žžDˆáPBüÕºHˆïÛš ±Ž°:„T˨IHµ Éž‹á„TËçJÈldȺÅoݱîøë_ÿºråÊêÏ,X°`Á‚3T¡r!ÎJœ‹[tj»ƒ#"k׉R¬uÇX cÐàl+ç‰Z+O…¶ò²ñ:C¹Ÿ6Æ@DdmTÇD.·«tÏgÿªu>çÙw•†ˆºÚ˜ý»ð¼óBií"ü,ÿTÚÒÀò ¦\ò ޽(Æš”šCý›BDq¬Ü_µÖ.?²þ¬n¬i)íYVa愤*W Büd«ÙB…jF3#ÄÅ=M©ŽFªOˆs½•Rß–ÞgÚ)^µ”ÙÈ(„¥ÏŒ§Í’ðú‚Ï’ÿTkˆuÇS~<#zÀý+W®\¹råž{îYý±k®©êB6<#϶g²O£ët‰¸.ƒÝî{ìûv1–R‚H#‹5dœ˜¾.F.ûåRœ4ñ刓ãi¼2»#´pYâ Ú·ÏÛ¸Ýb)”ÒàY×û ÈD’Hæº~ÚæñH  %¹$& ƒ„(Š… ÀÀ(´†pÃöC Fù"E!"·é´7ÑΛëO¬”rq¬«õTÛÏœÌ&1”¿œÒlAä BŠ Ò BŠAZ>!þ=BÓœ’«J5cBì•"dr¿”GÂÊÙ⬘C ©–!Vû¬CÈ0bÏ¿f Yw¬;Ö©PCõ'xÍk^Sa©^Ü.Š~õê^ÍâÌPoE ¥…œ(Ål€4DAF$¥ÍàE¶‚·…"²K¬¸© ÐÆ/”ŠAD@ì©PÌÒF¯b²m.ä×\) fÏ¥–bv-ÜmQW°ãïmO]\0!'ºL–ô±²2ÚÅC8ñçBD‹‹Y1¢Ö‰TýË–Ú\')¥¸uâ<愨Cˆ›í5MHÿ‚WEH.r¨Xª»&!éÒ;kBü8â5Gˆ›ç:„ø¿•#üºçs!CfIˆûëÊjBêË5GȺtݱî˜ý1¼:yñµ³–Û§Ñ®¾éVÐnþœ˜°)Ü@(¤tÕu‹[´¢Ð±ç÷½ àåî"¢(%5õ+å}ÌØ\v?1Û¯Ocek®X_j†±M° Kh.v3§µ6Œ†\°µWíší…ßוœô @úLÑm*ú†{Ø{dß·«‘¬ÅeµÎQšé½º„€ ø¨$$·±.â;>Ö!HU„d*ÔpBr5²ŸrBìà²ZÇœR-CrZàS.CR‡` Bªeˆ›¬5JÈêÞ͵³ ­ÖþmÝñƒnÇêÞ¦gúmîÈó3¤r= k>àÄ“KȲ¦{w’8Žs‘F9ñš °ßÍ-=szV±×N*¥ˆX_¦¸l +§œàv‹´Ÿa”+ÜâÞñ« ú;ÈÜää.͹0Šå—ŠkR±V;@IžT1:ʪÿå¶¼n-qçô‹Û9qž¬=cBü“Tâ߸RBÀ«Ÿ9Bü¥½š\S!¾C§šû˜¬iB`@‰È"!ÎPQJÈŒE^ŽÜó5cRtG>µ2¼`ùjBªeˆoÐZs„¬Í…m¯õ[,íÕû~òÖ#ñÐß=æÞi?yqký½þ?YtÿÁ.pf£]û®¡cx8y±RŸ{†H­ýH‚(1&Žã8ŽSï€6q“ABsSfFêÕ€ñwcI’ØÏûϼ ùì ø »IfKÈ4R*n쎶Žùº˜ª %Á64!õP6 ('Ê}œ%¢6g„/*C.À"WŠ0——ûâ 3@®® Ø‚{VL‡aXl^Vê šBÒ? #Äm)%Äݸ¡„¤¹H©ÿä2 ä6'C ±‰Ùâ_ïl)mäqëtBrÒ•!C ©–!P“ú2d!U2ÄékšµvœðúM>qù_ßrÔVöŸ÷~å·¼rƒN½.^lßùûÏ¿öì=ÿ}èb´Îöóô9þÁnÇn»•[¿îºëfíÈc›5 èÅÛúr6×ÿë8é*•ƒ `f+ íãk;„纎¤6ÙRA`ŒQ6æQØžçhÈ~PPj*0ÁZÔ‹}X5¤•¿Äfösã7õ/ Ò4Ü[†P0;_ŒÕØl™è­Žˆ(…HS{¼?¥_g¶c¦œé¢¯† Òj.ˆhGN6àÃ~…lăé³:ØŸ%"c”¶Ñ»`ó½m… ò7âuìüÅžk³! .!dS¨5 I‹ýÌš6U„@}B˜«)›öRB õW×!9‡{!}ε5&CÀ+5^MHµ €9!Äþµ!Õ2$ÝÝÖ!¤¶ )%¤Z ÌÉŸßû©Wïô¼V £‹^±ß±·N$îó·_üßÿ´Ãf X°áo9ñÌi“_\·ÿèëî:õj÷Ï ¯þÛq_üÈc¿:Ó½óÛÿ¹s¾ ú‡rõúý± €=î¼ì ¯}á#¡\Ó>rfouüÙWŽßyɆ6\²ó _ý¹?W}6^(2sé &!wÿ˜xàê·þËK5e4²Å wÿÜ÷nt#œÁJ·Ï'0þ›hlg‡È{v|öRï0þf<®¾C*=~þ•ãw^²a(Ãg-yáÇÎ~jº»µ¥:úÓpŠ€B—ÆBØ:0ÝvÛîP»Ý®ÖºÑhA'éšf3 ÔqÛt»‚n„ 4H„R ˆ]l&€"ŽN’„ØL´'”ŽÉhÝí0´;S„HZ±l"+GQ šn·I k>€HFQÔ4FÇæ·;q6Ð`$ÈZ‚ˆ‘µN”еNŒ5´3 )Ã>/²ÄÈŒt“IT&BFé‘FS@jígæeË—†À¤5DRHl”Ibff(Bid’(ÊP„ÈJi‹è$I¢ŒŽUb”„€(uë$£% Ö:ŠBc´ÒqI·I©ubXI„n·-%Ù=4ID"2 ¥H4‹ ÒŒˆm/wh4I’¸”%»¡÷Ècl^h̆¨CH D{j²‚;ž:„0c!P›ª j"™+¨KˆNT!P“Ã\Aضе1„ÀœÈ¨IHµ €š„T˨IHµ I ó5©/CŠ„ 50ä,^oø¯[>xÆžœŠ—ýåÆ7/þ¿×¿>U€ûõÇ^}òÍùÖÏV¶;ÝôƒÍïúì+Oȯ= ·ú~è?—+:þÛ·V,8qç÷-ž¼ü¶©€Õgï5ÿ¾åÂê4¶:€Gù±yñÛ¿pÙÒÉÎÝ¿øVë÷i9ï/9bŸOÞøoþvª;õ»ï|ãìýŽKrß:æg‹®¼õaiù3›„ÜIÜqÄKšðgîúûÊîÄÒ«ÏqIl"c5"ØIQ`ØF¸Tí,Ce›f𺵃¿òùÁ¥ÚJyq!Pˆi-µ1ÌÚT’žjÖ„ø–†Ùâ JUsBHú|Õ „³PîRBrv¦âÆ<”jâ‰!„TËp½‰ž&2$ýòpBr2Ĩé /ºáàã¯Øå°‹^ýþk¾ñë'+YÝæìë¾»ßË·i…bdýÍÞý¥K–Þð)ûþ—ÞöÕS~þí=wÙ¢!Å‚gïðß»üOg}(?#Á³>º©ùÔý+`üÏ77ûHC'm1ï¿ÿ´¦ÿÖã}dƒ€ªhÐQgð…#¾zÌO®<üŸ·o…rƒçírò·kßÿüûpÜO/Ý×ç…2\ò’7]òÓc/y_¯½Éi~bË Fg9 ¹“¸ã—+:ï8øŸ7‹DØÚòÅÿò?ÝTzÕ#œÁêüîûözÎYW> ½â3(á“×=þö¹ÏÙ븣2Èø¾Ÿ|Ÿ]6e¸ù.û|ÿ§ï;ç¨/Òô%[ÉF;9" SMó˜0ý˜2@Ø« H!ŒÑn<¹rG¹Ð×Ak¤7*]$¤Øè4{³? ¶‚{u„€W¶šœ6#¼t­a„p! ëR,¢áµ ÉÅrBœûi(!p-’ûb!Õ2²–5C &C &!«#CxÆ2¤"¶¬B†h=ý‘/{bëm>ûñn¹Q´ìÑ•^ökÚñµƒYÝÕeÿ š½e£±…N–Ú×gý}rÕ¦óîkþS¢Ÿíý¯Ûì÷?wÁ7_qÿY¿ÜòØ÷À«ŽÝòó§ÞßÛðá+¾³í‡¿5ô‡5pöß'ÿ¼ÓúÅ÷/X:ýà zï¯÷‚N/]ðµÔ@²~sö“;IoHGíúÊÍw8à}w{éKv{íë·Ý¨Uú±êÎ`Hu~wÛö¸û ŸÂ»¶ºì?oÛï›ûýöS¿†7~Á™÷íñãmgŒÊÀP¹mö®n›§[ðŧ*(jµô'¨“‘gC)!«ÆkŒ¹û²ŸÿaÑ‹¿qÄ–[mÐHm¶øÃ'ì]šûãH¿Ix©²’–]ñgrIC¹ŽåNJºüœtòÚY*þJ :ç¼âRaëÇØ•F)å5sÈ%k"BÎöÐŒyA) úËåZƒa¿q/(Ä}Òdë¥RØKÉæ,¢$ ÊMQ1¢ÅFqZr„—Aæëb 'k:*TBú#`ª)ø™!!¹9BüîÙâ?DÕ„äb–s„@YÁªA½ùÖ!à5ý}:ÈbTYBî¾ôoXoç¯öü­EÅs–lüÑPAÈ\-9šáމŽÿ¬ŒgI÷˜MßôÞ‡¯ø \~É_}ÓsàÙ{úè/΀_œ~Ïû÷ÝtM µz× •v¯œƒ1 :É›Îøí]?>íe›µ®¿êì=·Úð Oÿª~0÷l†Tçw<ÿd~賫¦üôCüå¾ßqòÄÔ=§?N'?ÁM_½K{ZCyì²Q¬Ô0Æ|óš•ûüŠÊ=îYuG³ÙŒ¢ÈV)M*Éíq‹)3þFÐO›·~‡¢åÃU"öSykd£˜\ ¥ üLO€œ]#`íç¼är•{ÉG  5÷9 ˜ÒSèÏ»Fì FN;;€éO væïZ #rŠfÆ(£WðÆe1!32 ÀPH6®{† ùÿ!÷ "ãÊs„ø^Aˆ¿–T⌃ÉmÙgLÔÊWNHúÓ5q·K Iok-BÌZ ¤ÏúUIH.10Gô𜱠ñ¥G5!Õ2²êäORÔ½êȳ¯Zñ¦£–Ô'dˆ{±f½£Ÿ=ú±«ú±Ö³Û9¾ì×Ëþ~ƲõÞ½Ñ(ŒntÌúã—üirâ Kw>hQs5\'ýc«9€#7ýlY§á7oÐ:åÎåîŸ+îü|kƒ·¬î:Zs Åc³]ö8öÃ'Ÿý½«îýË/ûÌÁ¥8³V©ôwû}¯‹>²Iû×nþñG6þè³WžpÙ‡šÏýØ¢€fŒÊ ã”»V¸×Ëï:edñÿ8*”‹pÅè´Ö¿œÔ;Þ~ÛáÇÿp뽿¹ó[¿÷oÜ7¡Ù—Œ~Ý”t–¥Ì½ƒe-œJ‹Ç8ëHUõÞþb☿3Úõb*™ž*ûPÚ˜ú†WZ_*·lôN›í&³R|VöiƒÌÔ_^ÈOrv'Tqâ:føËƒ]ÄRC¢¨Ï³Õþ‘XL)ªpe"q-Br dÎQâ»êâ;¿J ¥¢‹„äÖì!PVKz„¤{Úâ»ã‡ÂzN)6¬ô )ªPƒ©–!¾µ¯šje‰EO¡ ©°lUò‹I½ýŸî<â£?zÉÛ/~åq?úȹwOéá„ :^6/üÚ ›KÈ žø“·í~ê%×­h«¤½êÖë.?nßK?ù‰Wmô‘ïž 6;)´ÃÇð¤ÍG?ñ³Oòn'­Ö¢•[ÍÎ{ÎØc¿ ý§N¢—=tËù ûþI§íú_qãƒÊ¨o¼âà=¾|à—OZÝu´þ$øÇ ÞxÌE×Þ´²èîøõ×\-Ü­ôg6Š! úÝܱ×¶þÖQÿ»í‡÷€½OØîìwýdëì5T_ÙãÐ+ozHõÐMWòºÓ?óøš6³<,XpÍ5×t‡×^{mE›a|Éžo=óKÿ¹Ù³ÆÀ6u·ÇùçŸøá‡?zíqI’RÀäÄôÈÈH{rêŇƒ]vúüáK^üüE+}ò´Ó|Ý‚]râBÅ:Á®jOvV®D‰ÔIâ±…ëÉF(š-†¤fF! Àlþ†3aݱîXw¬;ÖÞqßeïêv»ív[³ ›¨ÕAÊè@6§§§[c£Ý$&£tHBî´÷×íü‚ϲÙÖ‹‚UO®:ÿ‚ßÿz½—ÿàèõ•ÒAµ ëî ‚Œ™œœÜú€s­w¿xÛm·ÝvÛmëf~Ýñ|ì°Ã;ì°ƒûçï~÷»ŠþwNÓzÙË^æ¿Óívàªkwú7/¬Nž3ËoÛ S>±ëâîd@bƒM6üàñ¯þî‘¿ØŠuü²e’$ruûÎL³ü¿o¼qÁz £(;ÎøªU .lò‰'žhEa«ÕZñä²0 ›£­GydñâÅZë•ããóçÏa¶ã¤Ñhl±Ï9·}ÿÍFÃ#‚™Áh»ñ ‚ íŸjÒ q.Þ‚‘˜™43óû|ã¾™[§k IDATC2ÝŒ:c>u:d€N§ÓŒ‚n»Ól6`²Ó^°`A¬’Ç}lñâÅ!Ýnw»CÎý÷ðÅŸ _ü±6 ,4ën<51ÌHEQ£Õ˜˜žŠ• ¢h§C.¸÷‡ïTJ !X뉉‰y£­ÉÉÉ¸Ó ÃX·Z­©ñ $5B’bjjbttŒMO¦ÚÓ‹ÖÛ@³íß½÷ÊwÉ Ùn·e!2kÓÛF£Ýn7 èïâõÁHY”ÖBˆ-ßðõ»t´uî&I3OŒOŽŽNOLJ)ÇÌ7V¬Z%¥ ‘dtFQ¬Ûã“/xÇoü«¬’Ý [`dT6BfÈ “nüÄ#â BvyǺüð:„NLL "dÉϺÿÊ#ëbq!Ûïî—¾½!ÅÒ'dç½Î¼åÊ£ê2ÒlÚJÖ¥„¼èWÜuáAu‰¢–fDÈŽž{ÏŽ®CˆsÍ—²Å¾ßºó{o©CHgåJ0<ˆçïuÖýW½»!Õ2d›C.ùóåo­CHµ yÞμïêw×!¤Z†l·ß9¾Eèûÿ%»sDÞ®)>ù¯/Ü8žæõŸµðø¾ú¼£‰GíóÚ@zß]8huYw¬…ãX²dÉÌ^¯;fät£¹w乯UöÙ³UaÞüÜÈh-„H’$í®€ˆ6¢‚ˆÚív»Ý‚ Ñh!†kÀž$‰k ï×›i4V³#"¥T«Õ²rÙÚóm»Ð(Ц§§›Í¦‡èt:öÃ~;à$I¬„rùDvT®ù¨=¹ Úè¹Ø‚)ˆœ–åC$I íöë$†A›n·ÓnO#3w:{ªvgª·!+ÙgŒI´ ÃÒòK]‘õ 5¬²à!¶ÅF#¥ýAGGGŸ."îtа4J ¤©Éq)PÊ AI7Ö‰ŠdtºabÕ¸IcçÄ.{vê¬s$Žã \½;{.Ëku÷Ë9J ¬7mÄ"!v6†Çq«Õª ÄÎsBì^{ÚjB¹‚¨Iˆíø6{Bì¬"j"„¨ Äy!gIˆý@BjÊ¡„TËÈjC ©/Cª ©/Cêrøf!ø„Ø©DȺåóé ?ýö·¿}àfðzÝñ49äP*×Ïÿé½Ûò¹O9bËž®zlé_ýù&»îÚÛŒe_ÒM€1& ”‚ˆ ô5ììËôñzE‰²6¢~=b×ÝݦLûñ þ!„p) ö¯š¡˜wCD€`EO±1gß„0««¥cY2¢$DÊ¿®T½cÍH`8­Í l ÷:±»iGL›?¸åúºýðŽ4üV@® ½ýg@hŒ²ê2AZ#'µcjÖŒñ3}Ší¢÷ïëâ®k(!nd¥„@ I%!¸ñ^ !„ˆx!é°k’ ĽNˆ1„€W4BJîìBêËjB†É˜B`Îdø‘ïƒ ñeÈ?}p§ý¿ôÇSßòyc¼ü‰ß»øÆgïºk5!뎧ö°ö¤%K–8ÛRÍ×ë¦î£B¥mlý¡,nwlÃ矵û}'þ×nû{»1앯Øö¢wlæÅGr±P“”Ò6ö"DZï‡ÐK¤ì•ôÊ·øÚRE~p>a»¿Ç§>™exöÕör•³bY>s®×,bZG"§ áÈ„©p¯k AƸ~šÙ ͦ±R;둲÷FžŠ~@H²y=v+œ6 ‘$„D’„ŒÀ‚H ÁÚøm1´1i8f@`` F›e£ƒÙ¤ï€) %„@U!ƒ™â/EBÀËØ¯& ç„T£@Ô$„ˆ BìXêÂllÂv)!ö[uéùë˱éCH¿U&OHQë!9²‚ú2d6„¸? %¤Z†äv°„ø2ddñ6_ûç[>þùkn{´¶^õÊm.{çf »ƒY·ø=M´(k[ªÿzݤ=ó¬PZ)'Sìöeó—nþÎ[QÁt§ƒÞRÇýKl¯.ŸAµ úU(ãÒv|ÙW\9Â0ôì}©j¼Ã—ƒÌlL¯ûz>!( z€â2ý ƒd$WûÀ J„tñq k[›ËHçDéD10YiîiÈÅ?ä*8kƒ B£´ÝC;•Å:,”QúVd$€³d+cŒÍBgmtÒ«¦^Îѧ/BÕ;ÄRBriê}æ‡Õ'$µ— Ê2¼Ê ÉÆ3[B yd>!àU­&ÄÞéA„¤Žö„ôŠ•bZ„hSMˆ‹é™ !EjM²2d„@MBªeˆ»_C ÉÉ%/Ýþ‚nw»ÆèÖ舔Ø6 Y·ø=M|y3³E­;ž*d½Äƒ ð ¨äúsnm,¹K ív»Ä’´fªBA±š°†Tª1ÄqLB JŠvÕŠm 1£µÖ†í%øÅ‹Ñn*s&°]W³Mv/ÝÐ ’“kéªÉD`— û` ×ô •ÒZ)ƒ€R’ý*!mnL¶]ªWG 5÷ûÉÛȬr($±ífz©½I0JSÐW:WåÏ5~±%¼™ÉV{v%™¬e!«sÓ«rN™jhËÒ̯àa!½”ò„¸[6œþRæ3'«±÷º!„©Í¢ŒgŠ›%!v"ë’Ûä´ãÓpBÒ9@ˆïÿš2”jÒ·eš!}ÖPœ¹ q*ÔPBf#CÖ-~OýiµìOëlQÏ<ÊŠÑœ†xÙù"%¶½»dưagñfë’ï·*O’Ù½ÁßAf+i³ZÂFÃ…¯L¥Ñ9¹ä”œ/ÀßI§±G¹>¥•¨È3÷"±Ë+ǰ1&Q†&@ÿâÙvɤŸ”’~iüR*š­ÁmˆÁψdà¬,§$Àic´²#[€/ç®ua+Å9t›fLˆç‡ª"¤´’¡Oˆ¿2URtåäY“kDª "¤¤:¨GHþOƒ I\…²à a]AxAâ³! -ÿf)C†R-CüñWR_†TR-C žÍ9!EBÖ-~O/ÞŒÿ»îxf¨PÖ†ïÄ"’Míî?À+ ,Ðkƒíÿzq Ðïqóëéù2È«b—‹c‚Àæ ‘”®ÃIÖ!´/&Ú&ÙݤRÊ%¦åìúK)"Y?…ÛcØ“žý?‘6_39¿')V½ñôìÿÆF–0x¾9ÖŒÌNžº_'f4‹ÛõƒÇݶ» „Nû?# ÒÃôq» ßb|q1ø·ÔÃbϦÍÌ ¯î_!ipÉ`B ?jÆ„ø×UMˆmâ6ˆÞ #Ä e–„ô9³Ö!½[<;B Ë|œ+2”j’Ý—ÙÊ·JHµ ñµÌ5GHñö­« õ”Ö°4³×ëŽÕ=æ¤.Ôj[¡rÍDsë."²Í0œÖRˆVªÙVšAhD¤Y3›´Ñ2˜’½c¯ˆÑЗ1Ýk«$TÊØ8MB4~ø§ !ƒaÐU]¥b¥³F ²5’£ fÖÆ0³ @Iƒ ôïÏÈÆ…b¯qô Al›õ^Y•a“µd'"@€d j%™ f@0hÙhcìÜ1¢!`BcØvqÏÕÖbB$BJÃLÖˬw›Q€" ’`˜Q° bB¶ ’ÐXc¿ßÅzÇÕ^Ýœ©gAÔ#„Ù”&…9B ¯•f!½€÷2BRkßì q&a„¤¸ j’šâž6„ôyè „øÞºÙÈëùªCHµ I§®!Õ2h.dHæ"NH}2€¼ uôÑGÀýWÇ0†1¢Xi[É¢ÙQJIj­Ù*”Ýn—Y‡a¨’R÷NmC×l‰ç ’$Bh­†Rj|||ã7žžž~â‰'ÆÆÆæÏŸßétÚívÜi‡a8ázH@L'Z„µÒ±QÌ,@ÅݤÛ1JGhŽŒ‰@v»q¢µBHwºë-\HíñI!3==ÙM’8‚eË–…aØaæå«V.\¸PJ©•Ñ ‚F@¦ ;q5IÜB˜$ÞþM߀û¯yO§Ó‘R’̬m¨># {ÇzokRUÆI(¥lOL âh«ñäŠ'GÆF§»Ó!###S«Ú­±QfX515›BÀFA¢U§=½råÎïýiªH}îeѱæ¼Ñ l±°¶mÐZ‡a˜LwV¬XH’aЛD:‰—/_>Þh«ÕXú÷DŽı‘‘Gyd£6Úòà‹í9ºü°G}tþÂyÝnwþÂõ&Æ'[cóˆd»“´Z­©v·Ñh k)…RêJÈÏn§BYýiÏ=÷¬–i×\sÍï~÷»AZÔ¼ !Q›ÄV^i4I’!•ÒVÀ¶ÛÓÆh­m6ª„&1h¸Ûí2cÔh1¼ó»IlýMDd”n„@Fm¢(tÖx$IÅ¡ŒP#+=9>EQ£Ñ˜žžd@VJ“” ÙlI)m¢8Ž!+­6C ¬µ¶b)VíDÇ €A‡è´§’¤K•Ñš­Ô‚$ÁÆiCDSS`XKI‚€Nân»Ñ …“íi’ ͆¢ 19>1od4‰ãåË—‡ahÒîB`$’˜ºqgÕ*4IÜ$£P'ÈJ0ÛžLPW' slŒN’dzz: ‚ÎÔôHk4]ul†Qt¬cµ¢©ÎtQvÛí ˆe§ÍÚp¬µA!¨i" @„fCDªÇíŽkšázñºøYç²ñÛº£ŒQ6&ÆÆm̆¨CˆŽ“Ô0€¨IQ!P“"¬ ÄÆÀÕ!$Öq!P“{ƒ€š„°¤ BÀ‹Î®&„YWs"C &!Õ2ÄÆEÕ!¤Z†@MBªeH¦ÿ'¤¾ )R!ö·Øû윟=×H§hƒ,í|Z´x9££ŸWaƒäìw]÷E“ÙÁs‰BY_ÅTE½ÞØší·Ñkmm‡hŒÑl ¦UÖÉ@H)™ªÈv·Ó« QÕCÚssÎ#ìzå*²ú}üA?-ÔýÍgwµï¼ü¤ß¹p½Òi÷¥:ô×Çvy?ö3÷_rˆýâfû}7×b³Ê)®l‡»ÏPBü_¯£?Àk^óš KÕÙVúõˆ‹ Ì:³EàÔ/à ®!Dø®zp­¾Ø€69‹W\‹p­²l;ŸÔ¸M©ãßΠ•¤Y ‚Öl\wU©=¢×»íŒçe5.õ÷¬þÓb÷Ž=ÜQbo™é»Û¢UiŽk¬íÿˆ!mÎjúÃq´ÖhlÝš ÏÇÆ^»í¹íîƒmÝ`»¡"I$Á&B BMÖÚs¶:è»òA,~W²A­ÁfLˆ ›­&İò­¡EBì«CH;îV’ÆóÖ D¯BêÒ“&³#„× !eæÌÉ€š„TË7Ê¡„Ô—!³$$-³–!EBJ¥ý=—¿Ã¾Øfÿó½*}ØœÉ9}Aùþ¤>69¥ÁgÆzKm5T[m5˜è…AN’œíÓ©û¾7—UÀÖÂgk®J)‘ˆûì—‚Œ§1X9gìÀÏ„ ܦ"G£o—u GqÑñ ¥v–J›p_JÚÝïåÇÿ†ÊŠŸAÕÀœ~ãÇ*؃ˆþpækíû/}÷Ï]*¨Œs»C¡‹ü3‘¹=¨Ž#/×$5wÏ|­Ó¬³ÑvÞ¥”@˜µÖ´õc8Nîæßw<•$z”ûvo«„&Êî'\ˆ " ˆdßãQ©/B¡7gFÊœ#}CîÆ—ÆÈ£geî4ÚæönáÉûÓVˆCÖZµ4FÍgÂSVJùõÝ"„ˆl°X€gU~$Mn34ÈÉ;3BÜOT⋆RBüǬšÕ+ñc•ª é¥Ù—âogEˆß4·’â z:’óèÍ^† %¤Z†ø‘éÕ„Ô—!Õ„TËAgž ©é‡eæû¯<Ò¾~ÞÞß±:b¡žªqͧíµön+@V‚óªÒ~Ïþ˜íTSŸŠÌà%ÞæªÚM¡¤UIµÕNœÉ!EC{ŒiWÄ ¤”9Õ‡mcìvÎzÀû’úDè´7ô}Ù¾.âþ€‘P 2ˆ„à6ó` ©ÚX?bÄ8N®ûÌ‹í0v>úê€DDÃÖZfÍ0Yor ú|èl…@!ˆ„ |àò·ØsnuÐ¥6œÁN€}@3€M¿†DÏ8BÖv8¹SÛ‹¥áükH«ßf ˜Ð*­’ˆ!§–Ê  ô‡ú:lf6¾òëR²Rlÿ)¥m@ö¤¿Î>ã å DÄ`ìv¡ŽÖ˜×4½½EOf9u!K€r¦nŠ„“øÆ(¥XKÐÆf“ÈžL/J3²å¥Îšixkƒðg ~ä â^=Ã2ý&W7²ÉTjÍÍ•á™ýu8â?W¥„8kÖPBì_’>t³&ÄϨ&ªéÿÅ BüþÙR”h¹m\q_;Búx›… ÉMòŒeˆuÀÕ!díÈ>E¶šÚ2¤HHùz†SÓ“wýðíÛì{޵EÝ~éáQ£©ŒfØÆ…S*T,M‚ šÚ`’zùü0AhŒFcl¸;§šŸÖ "ÇqÜj5´ÖÎtD`ßoµSSSóçÏGän·«”"­µAHw“$iJI Æ×_UJ J´Ûm q ”&)PH¥™Á$]ëå7D" ‰q»#¥­µŠ›Ñ@’m°ÃZ·šÍF%ZP’$A$í¶B©“®h5 -²R\Àd‘QغµˆlŒ6Z³ $ aŒaVÖòg#¥Â(²éšÙ(h=2:OiF!¥Pˆ 4HŒš€HèÄ*ÑL2· ;Ýþá‰[ïûù»`‹C.øÛ•GOuÚˆÒ ÄZüéžÓfÕ¸šžžnFrtD,Z¯õÜ „"Š"6©²7ÝNFFçMMwÂFÔK”~èÊ·o¶÷9ð¢w\sÿÞl›Dʈ›ïY>ÑÁ'W¶ ›dáX0Ú„-7i4DÇŽFDÒ5+$ìÄmÔé´e?!‰SÉP”‘$&ÖmiTÜßh=A fFH·­ÿü·É‰¶Z5‘he¢PŒÔÔæÏn,ŒRB†ªD»í¶Ûu×]7gV(ßã€Æé¤lMľ1Í¥âh6‰f͈‚˜0Ñ+m‹éÚM¤owëye…Ý&Ò™æ¬\³¤ç©0YŸ,ÛÏÁÆœ¦¢?Ûÿ d›0òëYûWéRƒS›zÁܯ&C¯˜õŠ“”¡ÛéúLÞ\ifmŒ±ù䈌ÐÛª"‰>S§¿ö'ǵôòëþÙ6¨ˆ}+%‘DÅpàÒ~¥îÍœ%Üw~Ï!!v·4”ß®;KBì, &jâ›"Š„¤¡k5 ~}ŸëX¬Cˆï°Xs„øoΆT{˜µ ñƒ'Ö!4'„TËÿÒª ©/CŠ„” |ÖÖ\w÷©GoûÎ'"ÃbÊl0 ÏÑ¢ š×hŒ4›Íf£%Ây¬¿ÊlòÄD+V©Ì÷·æd©ólúf¼|Ýö‚K(W9¹OAwáù‚\BhI Nûeãù zÖ°BvǦÖ²6ˆDĬRWÀ~]ÖÜàý˜§ÜÓ”m@ÚÇ@kÍ@‚$I)(`BWNÖÚ”" " ètbrttÞï¿ðÏö„ÏÞûˆ8ÝÕ7Ü=yíÍ«^ªÇ§(RjÆUÓðÐcñOo\yóý©Ž²úë‚—($¢`B&RüöÌ=Òx¸ý/HSý‡»&~uûô_—ê•ÓÌ(¤”Hr¢C/åŸÞ´ê÷wOvb(^ri€‡}¡˜&õúÓôÑX$£yÆH«Ùl¶Fe4_6žõdgƒ¥#ʬ!Ó}ó=¿ºeÕßžÔmDAÀ VNÃ#+ðºÛ;7Ü39˜¡¶ØÝvÛÍýwnT(ß«ê[È­ÅŒˆÐïXÉý¾RËíó } K*;@ÿ˜å~Åý–k)jOå‚Ý܆Ò=“vçvre¾ÎàÚÊþ³W,\ý¡•î=ÌB ¤_j/ÝïÚ’µ*bVꆨß\YôŒä ~g ?îlVviÑg/™MN•>ð¥~k]ô»¯.!NªV’›–§!þc<BÜ•’Îa Br3s„¸»6”0»¦ ñSÕæD†Ì’?vêé@H!œkdH‘AƒwUâîúÁáöÍW½ã²6n" Ã0 à ‚0RŠôÿ¤ÂùMÎo—,Q­\®¢'·F]ªÍç´¨âÅ‹µ–^iÑlœK•Èm«rM‡°ÂÏ[d킵sa…þœXg´õÉv:!ÄèèèèèèßÜßžgÇ·^|Ýí“ONpéM’RÊÞ³!¥\6?¿yÅ#KÛ¹X_Ë!¢{.>ؾÿ¢wþè7wN/ç »ñRÊ H=ì¶Mç+Õ¯nYõ÷';¥÷¨hÕîꨛȨÇRÈ )¥$($†óŸl/šìÔ%äñåñM÷vVLö®= ÒÑJ)—Ã/o^ñÈÒöPý©øzV*”M©ñe“í‹ ÀΜUl³…­ H’$j6š6ÀÖLïoÙŠn‚\Žƒ‹rpå©ÒoØF_:?N.òÎÎ]N„ùû¡œË6{ÝÓœÀ^KÿüôÕÄ#é…º*2þfŠ˜e5÷ØÐ=¥˜Y¤ Úv°Ä%qö°;i—æ&Çóú§ù#Ìœ&±÷þj RIñÀ\œccBêRìR,U“»|Î!6u!é네'Dˆoõ©$¤8E3%„*)êR3%æD†@mBªeˆïž!P“jâ›Í†R[†§¨B…²üÄq|çåoÝxñ³öxÍng\tG EaFaFa’HÚL6 ‚héÔØøTZ¸¼–Û~pt,-r["–Sܽä»|PfΡœ‹ÀËÝ_ߌWT¡*tèâ¢TÃîËÝ3^ê€áœùÍ}Åæ¦¹×vJo=sŸf³¹xñâÓ¿w{ ­¶F(Œ")¥Å …B Ãô›ÛWü}Yׯϙ“•Rºp{Î/_|WQ…QÔh4Â0´Ác^[$ÐŒÿw벿>6YÜ›åf £Â.m†Í0A…a#Ó÷)e”"£¥Óó|-j!-ëÞrÿ4’´`†aEQ†v.˜’ˆ ˆßݱ²Žþ´ZZ å²ÔF—벞 ²³ú²“;¾œbNöÙÌRÿ‹¹óôµ‡ëßKå|œÃËî5S±žùû}GCu…›ÒM@îz­-²º…Æ–uä˜Î5¯@Ã~D­ÈZ´7ú鳑>Ä}#͉SîÞQÊÆFôÉÿ§‹·¯B’úA3U äš'¤¸­œ1!¶ÆÁ:Bþ1I}ƒ³&ÄUz:’s€®!B Þ_´”Æžù^kÐ8óâÛà ˆ¢0´{|‘iÏ„`}œQ,lÅ1ÛFÔöÎÄ’s¶]`EM¨˜l[TSŠšP±Ù û"Òi™ÙÌZ™³o§ºxøvÇ,aÜk»¿´¹ìu&u:MÎ!˜–¥Õ9Mš±‘ïªw»]­u'áÿùàëmúÅY?¸3ÃÐÞ¤ 2R ¥½³Ðú÷o}°=Õéõ¾ôsë´ÖI’´cþÜ_kÏyÆÅwDQvÛeà%yôn]犉é¸TË´ŸQ»¸A …”2 ‚(Œa†A$ƒ@ÕËR«"!†A°*^ЉM!SuÛSA„aÔhDöÒSœ'¡m4Êuª(=®+;æ@…šœ˜–"ìLvTGVí΂iOO2è JÇqÒ ‚ˆÛí®{UÒ‰ãN¬Â¨¹pýõ”1ÖhsdI¦’P3hï’¦¦¦|뺔ÒiĈØív-=&QP)•$I’$ÍfÓm.má›ÊËJk­¥”ívÛnµq»vW—uBè¥h­›Í–Û’:]Û¦S"b£Ñ°ÿ”RÚÊFÌlë€ !V¬XÑ Ì”Ò=ui†1ÈÜét”ŽA›n»ÃÆ´¢†¦Jc‚ ˆã˜™ƒ@øÁv»m#ã8Ž¢(Š¢n·›$‰}Gk=þ|­u§Ó B!%¤)E*1aÐ0lŒÅÈÈH’$ÌlŒ¶=V“DÉn7AÙ¦™H)C$µf¥ iÍB¬³$ÀÙu±÷¢‚¨Iˆ¥A„8†ârkK ±›ø:„¸òߥ„XKCBŒ1„Øç¢!Ýn·‚^ ÷PB Ws"Cl@IBªeˆ³Ò %¤¾ ©&¤¾ ©&¤¾ )RaA±?AɾõÅRŠ ¾vÑ­R!ÓH¶:¦=‰0Ñ_ï™ ¬ åçE›¥:¯Üû–¿¢Âk¶XêkÎpñ²bxÅOBYŸ";ÕƒZh—#]b‡ÿEcŒè/¯ï›K1q'IÂÚÜùw¥ßwðŽV»úÚ÷oM3 …RX»NÏÄM÷MønßÞ|*­ï~D+Æã‘=Ó×/¹CJ)¤R8ç õ,‘õ¬+ ¸cYNÝñïÈ”^`c !B™ê9ÖT„YÑ{‰· ‚è/O@!w>8­Mš½ëÎÈ@…Ò9H IDATÈžýÉî¶zUk9#/çl¶ÿ}é1×ä>sÇұ·1µO û ·. m,]/±4ÚÏúÉÍ û‰ÔÓi-†m\+”RXJ髨ƒv½¥¡¯~¶ +ëÂlc8!â”ÂÕ¨°õ¦‹Ï¦±•ÙlØVíi÷±tTiK™ª(tUœ™í&ƒˆ¬ÅÒuÏp; î™ôÓöN[M]co–ÏK·ªƒ¢ qFAâÞ]+Ò—š4˜cŒí–1{B(«WJÈ ‡f‘¶W:€Ì 3[Bú¬•„ôí‰ „øÉ Õ„ô•xYc„øfãjBªeˆï€˜ !½P÷a„Ô—!Õ„ •!ýÛÜZ2dÛ}ÏÉ}ñÞ‹ß\AÈ Êƒ†%’ÈyöÆ}ðð]μä"úÊ<öÍ;0©îä¾ À€D 4–¯_4?ò«åÈ/†dù%ˆ¸`Ô,ÆŸ½]~Ü}ÎðYJfî‘· ¨_:2— ðê&±ÃØŸ^Ãlöíú«åOˆk—ÉÌÀ@™¾¨ö»§ÛG$ÍÛ×Fkí®®›'&ÌÈ‘:|—¯¥÷èæ¾ ô"I\7 ^…‘å“üäx²Þ¨Èé‹D4Ý5O¬bBJyÜ!;|ó‡÷Ñéþñý‡½¨§Ý ¥- ñÉ•ñãËÛ‹×oíµ†˱Ló"Ad ˜ ƒ!¤4Á%rZË¬æÆ²U+›A !í®y|EÒh4…öi&¢TŸÏÚDfWžõ_JÔÐŒ<6Ùsk÷”ö¡½ÿÒÃþò£wÜ}ñ[î¿âí]s " £ÓV ŒH¡¶Ý›\Ø,|€ ³Îõ£-º`Šm¿zž`¤œ¬LŸcëÅP:¿earå2ÊиJ¯®°‡ïª(ƵI)!+„Æ BÈâ>)ëÕj  ›#ZomE“}Áø gE RZ1˱ÂlñC»¦ô—-®òX`Ñ+\ë/3¥Â¢¢#ì`B k[¢ÚëªQ$ !~M¼RBŠA¾ƒ±«Ú@B¼‚*Õ„X³Ä B|QUMHÖ2­œ¨IH±Oˆ[‡â¼f³$Äÿ@‘,÷«!•2Äþ·!õeÈB*eˆ½•u*Cò1C5dÜõQ÷_}äýWyÃwö½å‚« ©P¡¬¬˜JFˆŽ{ËζÐÈéß½ÑhÛ•™­É‰Ó B)å_‹•2ƒ’Š÷¢§E1”–«ˆÏ1™+ÜUÌ—K2uÑr¹´¯Anߢ±hjT8-—­Fýö6Ö&wïÒֶ݂ž¾”2ò'ZµŸß÷–íW¾tÞ ìÔAëÄ‚´LŒÕ*ˆèŽVÙüé\ÝÑWB WhãýÙ9O;ÿF«ÖcØ/è˜jÓHBÜ~ï²$ÑÅ"ìm=–9–!ks™V<1†-K黣€ RʇŸPÚp‘m÷O,ukûvú Á9†¨P®ýª³Û§Kë¬ó”Ònod³‹Jó=»þ„Ñóµ+U‡ëõ7u[4׿³/LϤ¹ÐBb(n—«Ù­(]Z–’j9—_ ƒÀJv;< Ú÷<ƒ«}©?›„¿×ÐM´)†ˆårC\=Ö^•äBY}cŒuvûMasùçÆkv;Ô®P*€J I9Fˆ?ì BЉÐ9BÜ;C Éi3&d@ÒrJˆÿ~5!ÈsCH1{hf„øII³!ÄŸ„"!ÎZ~|¼8Qû½ñuóçI!læ¦Ëª‘¥2ÝG¥&e­6Z+Ýã¥O.¿é–;ŠçÜd“Ml‹;ü2l:;rãü÷ßËW¡àÚk¯­Ö‚,X0 Jûû†¢­^ô¼ìó¼W¿`qgbüÎ;þö?Ÿ¾øö÷ïû¡›Zk„|'žG— dýß½*¿Žþ^a þÒÕøÉ%× ô’–¡Pñ¬Tô{õû3;$¤ÞfÇnæÒÎuÝ‚4Á ÜSÝu¬…'þ¼=ŸM[ͪõv{Ê^*î«,’k–…îWnH¹þ‹±Jz[p~eji·E~ýÐÅÜO”žÎÚôIÛRBœ¬ìë eûvy„ý,¥„¸FlƒéE! #Äu½˜-!½ ‡B2ÏËpB<³v !þÉ« É5+ÍâÖã¡„ø½„‹„äb×Ö!Õ2Ä:òêR-CÜÄÎ’Lþ '¤¾ ©&Äá6/Ûîøƒ·~ÉsG¹Ûþ¿ën?ãK¿xà½ÿò‰WŽVR¡kF`Ðlc QL„Æ Ò»ÞáKçÝ µùÂwþpì!;eŠ&06œõ|…n¢s‘F~°‘ {÷3¤zþ\)UO_d·ögåOó¹œÅ¡¶”ót•Ùû\lìU‘°ÖJÏÓ …vo°å^_»ãòw ÒA­VDDiS‘ŒU dB@`[ªƒ³À´ÒÈtTöl Ö¼˜Î•6Ƙn‘È0V`ŸAâ¸Cv:õ¼ë1_½ôö£Þ´MÚ ’ sϪˆÝXô²üìÉÅA©î¦A)ÈÆ˜cÝé‹ç^ï÷6.FŽrK)ذAVÆ€Òl 0sNå⬪è±4¨È–ŸšgyÎñP:Îܱ馛nºé¦C½uãeza-Ê=xN0À%Ú‘™›¸í¼ËóÎÙB¾ìÄëÿõœWsæ"•R†a¨C›– äœåÙŠÀнÐoþÞœ8&·Øçœ99Ï’=Ϙ“ólþƳçä<[í77×µå¾ßž“ó<ï gÎÉyv:òŠ99ÏKŽþÉœœgëΛë:ôÒ99Ïó¼`Nγé>çÍÍxöš£û~Äçä<;¼inî׎o»|näÏÞßœ³‹tƹ<ß¹iRÊ0á?²  ÙÚùE›}y3ÚóÓüèË^+ƒÐ²)8-ZtÒC[MZid6BÑvwóîƒwüÒy7m¾xÞõï=d§4ñ 1¬uJ)KLw¹ó\MK)& ôwÊ­ƒ¹f…þis ¬[-§)ú1ãÅ ­Ô­–Y +{¼`¿oÞqù»ŠÝûò€‹Aë¾OÒ·´ùWáëï}0g'“VYPZ! PH† !:ëËÝvì¡;aêµ6d²ŽXdû¡¥9­N DZÞViȨ"i£™ùè¶#¢$‰0IÛ;/I4#X:“¸óŠ6Øt£yB ^öèÄú##£ÖgbmPhKÃ1cºI‚ŒÝ¸ËÌÖ‘' &ÝXi³|Åòù‡oºÞŽ´šQ%I1Õn_{ëtµ„€(¤D$‹Yc¶Ñ âxrj ˆDŸwh­eäÙDrÖDÓ3±¦wztñV‰²àIDA$ˆHBØ–‚ŒÂ ³- ’žœ{ÖÑ?]tXE®®ÝØØX·ÛšX5ÒlH)—>ñØ¢E‹ÚS“ã“‹7ÙXÇÉTgÚv 7ÀN'̼ý[.½ïoê´­yklþ¼ŽJ¤”Z©PÈöÔtšðšR‘@f­ljÜjŸ³î¿æ=¶ñª-N'„0F!ƒa-€W¯˜7:&„HbVJ'I<6669==66#ÉëÏ|èêwA¢§&&§''Q«qzzª5:&¢ a[MFv_"ÂÀZž\º4 „Œš­°5¢–ìùõû®xgˆeË–r¬š­hzrrtt4Žc[LLkýÈ#¬·Þz$±ÑhLwºc£ódÔ˜šjG".]¶|Á‚Ïß묇®y÷ÔÔ¤ÍôL”"˜œn/X°€™£¨é”w»3–RÆqlŒ±?‘œ¡YòÆoçDÄ2ó½|ƒ$4€…F@’í*——íªåòÀ @ ‰Á` H ¶«ª«W×ZÕíÕ®UµjUµÛ3!Œ˜‘1 a»ÆUÕUv2’O”1ï¥Þ73ï8çìÝ?vĹçFļd>=¹;É%îË!2nÄûì³÷·¿¼·Â`Æ,ëA’dJëĘA+•sÔ23µ BR£4r!° BFƒ•4Í:K"Ä»¢!R]!JÄQ –DHØùµ"DF…—AHžç‘Âð2Éó¼!°,B”é@,‰î"Ë ¤;†À’Ù%†,‰îRqªvGHG ™žúN:<§!Í‘r­µ;Ö:ïË>‹#ï·Ö:çÉyçý[oy®$:¼ñ%Q¬sÞN MtÌâªq¹ aÆÚÔ-;>B 7+±*ÃÔ’­Ø?§Cö©9.P˽ïMeÝñyo«Ë”,ÖSh±wUçU¬ÊŽ$CðWA†QZ&bž¼J‘Њ¬“«÷ú^*×ÿ·>ðEa^KVGD½ MTp˜‘›²ÒG€² è¼‹IEÎ{¢²JQÿ4ÔD‡= Ìi¢kz¤HSçü KÞ9ç­Ñyëœwž<•ŸbÃÌì=Yë\1afÁRŒAÊaˆX&OÄÁ¹<3yÏd J÷ʳB…„=ÜÏý_ú¾qz³`W|í/ßðO¿ð_óÃ’²W“ÆÊ#*VºüDÅ8GÉ\Ä ôÌž™<—“í °šzmPéè)›âé+cÌÀˆ‘ƒ-(s4±Ž¥¦>ÍŠ¥âÇÿû*…¯†“¥Œ P4‹Ë™²0o\iNV;‰9ƒ*dRU!1D‡pXŒªÓ0œÆšž”v:6î_‘JilP*VåÃSX¦mäêÉxykt‹öazN¸Ò÷o"¤&­ÉàÎ!–Eq'B`I„ Ÿ„Èí[„X!q¦‰ê"ì!ñWºR)F¶#¤6<Û2¤î!Ý1d^…÷CÊßß7Bäæ/ƒî2»¡»!$Ž!7üëÏÿÁC›“sßzä;ÿøÿ|è'_y]B¥Pau_ëå¢í+š¯V¬÷V8¿Do}ŵ²‚ýö¾HÕLÔd2]_ÓÆ¨Ò䆈€F5JiD(/ä[ª"›[kìeS—¡)^Kqj9Pì/Ôú[aØ<æÓt÷òþÌ­%Ëâ…´ÖFa<'[Ó ™½€¹³ŠùæA V6B‰.©ÓI¼« @Î&½éeÏ‘çâwïþ’ôãä€çÊŒž=€!¿¼ô‚žs¾šœ#/wRg#òUýhÖ¬Xáî¢sGƨ/ ׇ^$ ÍÛ’¯Ò)ïËéN•†¹wäýt:=¼ª³Ä4rÑ-ÄÓ\"ÅÄ2òÇP©9pE{²¨Ýt¡<°|Š>=!üÛŸ9ðGŸøÓ¿ÿš=çç?ñ¿ü;?ò ?ó[?½â£†®bP µÄ¶Ï`¨975;âm‚*ú–xiE2ÿ¿R Ïõ¬•>ïý$=š‘pµïιÍÏÏþ@eÐÛšÖFÇÃae‹$høÄTôxÚ*Åsyþ„lkXŽ//I°vþ5Á’ÆB8—üU+«¯yu „* 옋vM!0o€µ!s«rB*vEÈŒ²?„ÔºаÐZ!±A!Ð&=ÚŠp["Ë $~âši­Uì!òÅe²d Ù!Ëdzƒîó\KÆß|Þúýú¯?~Ë{ž}Ë=ÿüÞïüÈ+ÿÁoýÃÕ„,J¡BÅh@Ú²¶œ÷·f£éôÖW\+3ê¿õ¾/8ç‹Â:»e4E€Åœ0¨‚ɲ=ã •²¢³ («:;Ïž°ÊSg<}(ÛÄ’–ªŒ2uR£5x.Y¼‰Òè˜@Vˆ µ$yR=s¦ ?‹Õ±[r)âÀ(¿âú;‚_dÍwŽòå|Lo[-.1‘ÐQYrä<“*“€Ò ô UGF!ašÊ·¼üjùÊ;îý{¦Õ>&‡ý¤2™arÐKÎ9hBnDµ¹»jø’‰¨ì*³¤ZkC•&jÐ3Í=1Œ¼e‹PÓ¢¹FØpP5LçÈ®°Ö[‰ÁA?i"$5pxÞyöDž8L0—uæÙ6†;´<ž¬ æí´Jªõ5?ðë¿úS_úèÏíž›>üÏè¶Ÿ8TͳÔ5Ýc{£8¶FŸ8üEADÉW‰~µmm!ïfÒmÕw¡’¨Ï”–Rm­,ÜZ…\E9çP6hzc…†!Þ0CTã(ÔDhBà ¿–ÃÐã“æ‹ÈŸ„·,?“´î5ãAЦ@\ó6µú_6R{Y½î!¥‰Øb„„ Ê]¢”ê@H|qºK±·ºŠž„4F;"d¦ ІùûGHs°|BšÓ:OBæ¶^éŽ!5ý¤3CºÒCš)×21äÒ¼ümÿæÆ¯~òõê>ùk?öÆ;ÜÖÉÎ41©,Ï&ÍÖ‡ÓÉ–sž˜=‘—^ CY5ÅËó/½â:ç½uî×ïúãÍñæá€+½J¶•úÚLÆãÑåyZYNòüôx JBëý$Ÿš´J1ó°ß×LùöÖæÆM§\äFU ^ˆ€èœ÷J©~o8ÙÜ1h€Y¥¨Ñ³·6×DÊ{DÔ‰IL¦ÑxFë=(å <³#vÄ 4Ž·¶•I¼(2¥ìxþP&)œõLÖ•ÌÙ*&F=þ¹¨£§Œõ…Ź£4¨83‰HX9òŒ°½3Fam–ÞÞàCù\H“Iš¡1[;“Ñhe'w¹%ÏÀ¨¬§KŽ ·S)¿H9§ä†ò'0ÿÊ+¯“¯üæ¿èlñÌ FF'‡WGYÒ±É$WÊLs[äîÚK×4°gíLñœ)òBHE ˆžÙyGDÌþ²‹Ö€qmÔGÔ3óìRtÝœw€ó4„ ž•õÞ »X)P(…¨Òﹺs¥Ge ížÊ€E]ù·w45`3—•i˜¥×4ËÕ±¾«…ƤYoÐï•2Ì<ê™ç>=“–««nùJ«‰ˆ½H€ó[n¾FŒ ÿå;ÿë — ûF)‘AGä²ð&~k£Þ]¾ê¬õ‡rkIµøƒÈyŸçù% ³T‰1*;!¤ZìlmïØÂI“Vðã;صH½7„„C7Bšv÷5„„…sW„Dâ{-©j}õ¬W¡°Ü~•›0,Iµ °gª¦!¶Ôí+¥@)FdD!@ı¯Ù4i0‚¹.FÍ‹;4Órv7S< IDAT÷ƒr{½ÿÒÖIÜB`I„tÇÚ)í9†4’×3CZ²(…ªñ¢Î?’®÷Oož:¶¹µ=L¦Ó<Ï‹¢(òÂæÓ|g2=½¹9>½qtÕ}æm/•ß½ìwÆùx‹D™v縦Ec35 ʦܔL0 " ½)ÒGÃ}vJ›!ßj½}ñ…je¶…ÛúÈ}·É·žõÂ;bîPüßV¯ÉÐ(onP¹QŽ•ICcL’¥¡l©”ºøÜÁ_6&¾ˆGeSÏykm>Ž2¾ö²µûo¿±ÔfûùJMZ†mØÛ%®üÝ+W†©/ ëb•3yQŒzpí厮Â9‡ض†Æõ¶ód‡G[ãÓÇÇ–ò<Ÿäù4/&Óüôæx{üÄ‘•b}-5Fsh¨æ+M„\ñôƒïÙi5.:϶rÎåùtÒµ—8ºÞjªPÐæ„?Ã!Þµf5KÓ­bk  $÷±¨©  !2aÙUe%<й-BDY(Ÿ°šXˆB#›ŸÖQŽÀ{m‰›M›ú¦‡]mŽ£þâë –.Ú¿6¿5S­z RuþPñ^\”rZ™.Mšyã1æúxê‚~Á“‡Ùu^€)/ƒÙ¶¾ !°$Bj»ÿ=#¤¹7­éG/‰Z ¯!"Áý Ž‹Ò¬B=µY>†t#dù²O„, Ãï=†´"d× í~î¡þÓr6Ƨ¿7Þ±uú{[ã“Ç76Žmœ8vìøé“Ç&›ß[Õ'Ÿ¶®Œâ,QÏ8ÿ@š¨erá9+?zõ9Ͻtu}{ [9O›g ­ᪧ÷¯¾ø`¯gz™9ÛҚ̀¨ŒI¤›¬µé÷ûD”çyšfy^ôz}LÓŒSÁ³üJ’îlOLÖÚ^¯Y¦_Õ#ÚÁZë¢(ŒIC£Ä9ÿKQ¢JçEPzÍl'‡åÌúž"ïkW„9"2‹R^%â‰;"ïk„̦ƤI6è§i|Á«~½:|°ÿŒóKÒÏúZ}­d}ðŒóÖ.8wue˜†þÉ;_XÞ£—½"EÐZLŽyt}pñ…Î=˜dxÁÑQp8ëºP ”gôŒòÂxÆÜzGà GÖsù-G‹4Qêø“J&q 5È¥ŸIûËð€leúD£QF£V¨2‰Èc*ª¤ó@),•‘U0Àö€^äVy®TΠ4¢öP÷ª=´1c(îת ­ã0±¬‹H…q“„[‹w5š|@Ò¿o~ûË$ŽE¼XƘ.Ç‚|¬#§â5» ªÞÄÙ?B:–Æ!1y¶!òߥ¢uB„K· BšË^2|FRkët ¤F®!¤ö+©Í"Õ+*u#dNQ°€3C–EÈ.1`I„tÇ8OêFHw iM÷Cši½ªW½ì’`ò-£õp,—¨ž L5²¨ç¾îaâÌFã\Í`R­Ìýý÷\îz¬ÿ4ƒ+–48ô[ÔƒnV¿j•’Ú#Q³]«6l“°ñðýAéàöZ%©I'ošõÖ†-jçŸõ{&I”1i/ÓIâJ3»¹kÞÞÁÕÞújou˜&I}þÀ{ÿ—÷•½Ë^þ¡ÖÛÚÐZk£õ°Ÿ®¯öÖ×ú‡ VG½41­i²ÜvŠýdm˜XÍÖFɨŸ0ò>¢}h¥·¾Ú;¸Ú ’Ĩ€§† Õ¼©ñ64îMsD™ál%.`CD'½ @˜wÐ*©¦rc…FækJ]>ëÜìÒ(Z¨ö‰Ý|ùw1V<«Q«çxñά9O!²„­bMíyãÞ|L©]‡VêC«ŽNíÊæ>þJ$r]ßÙ0a<Ý=Œ-~\­ßÝ3BQ[j‰ù­‰&ûvAˆø§/BHmžë, ¤.n4îìŠZ Û3Bêì¥y„@übBj?ð$ÅfÕdo1–DHw €³ŒåcH!‹þ¥×¿«(Š y!Fñ³‹E_ãÍ[(/Q©Q~~óþ2‹zú‹0L&9¥••¹5rp‘ù¢ÉdÒëõ,y‡½^¯?2x"vƼLæ9ïýx<îõz…³J©$I­7ÆKÆ1±Â$KÑ3¡Ñq6&MÓId PZŸò€xï“DÇœ3­µò9WPQLK q$V ßølÅ {þ;ä·c¨beH~ÀÌ2'kŒéõzÒì O™˜ð„ðÞçy¾¹5f€¤—Yï1Ë2y/[[[a@;MÓ`à3···@æß$¤Ñbee…™¿|×ÏÉO^ûªË}Á[,/ß•ƒœ)„ÉI2쳃§`"Oˆa‚&Œ\¡V:)÷sò-Iÿk°P,c¦v‡·€d»Ä¢dAa³+ P¥hEŽIJÄhM­+'wP¥¥E€,ÚfsW!jæÒ9ò÷ÁEôíZJëÖ&ES#ìªåá”§H òq©¹ jŠ5Ôv5r·€¾¶ÕhNJÇ{b…º­•@õ‰¸¶–ìööŒ˜„Ûx2¿!2Ú· Bñ, æU×;ø4`w#$Åò2_êØ;BB`9S1dW„tÇ8#6çµ½Åh8±ì3†t ¤ùqå ïY4¼¨F²h”=dQWÜü¡¸VKéblD¹užø\óI<–kˆeê’§­=²Øƒ¯©2°à-Sëà^­ß$¯CuÉón_4ü(ˆ >]µFg¬Ò9“~­žypâ¾[œëì2²Õäýè«åë_DŠeñÜbS7ÿL!$lHh¾Fû$!äl§PñŽkg¡fH‘0/Ð\¥fêa‹®ò¬ü¨grø¾T«Ç°Ÿ–YXõ0®<"ʙҠMÉ D­Ëô¶Bv ¥vƒ[Ï*ˆ©Ôºòµ­^M׿i‚Q“]Y´ƒŒƒl<ó?®Z×F¬1n!5Èx¾æ]#jÍ…Ek@k«¾öHö*ùî3¯¿+6/ l°:hU´Ú'Bä ÙØ'!OA#¯9žm‘·’â^˜—®u‘ƒrÉ¢Y“ÆXKocU°©ˆ8/ªÒMkv­(¾»h%µÑèrÈ9ˆ¾,Ú…Ä®¶$4ér±âH =Âc¨m[K ‰9 ]}Ô²¨P\‰Š1‹3Žà5u¸f¢6{T‹r]³Âñý"$nFt÷>ºRßP.FȬ¤Ü†ø‰ØBZÇŽö€Ž0TCHSd(FHÜ€ëFH½û$!$>à~bH+ñv1–DHw i6øöCB«è Æ&B]ÉÇî+}ß®|ñ]ñUmÊ/ºãµ¥Ô7?ñ e·èÕ“ê`®cÞUm°«©çž öeK:€<~›³~ÍFgìø[#àÇyL¼mX¦Z{ˆÿƒ’]~ÉóßÑÜZ„æ—T¡á†Ôb…žH¶ ÁÆ üb]9`†“q Rãlÿû»ž_Þ£WÞÛ:ÙÐÁ_ôÝ= DÞ°DÙ'!OYªµº;=•XŒ¦dd¬&tF7ÿðʽD–ºiì!ïƒÑdÐ,–Ä¥!*mW FD º™)Ç€Ð"/6·/s®m•Ã%€bD…P(B@”~„ŠÙ¦‘M1¢h”€ÖIjL¢y•n)ÞX-vzî–‹žx^jZ+¥+ÕAÿ*e5Šã›/7ðÕ¢Rs·U²­¯éî@$\¶BPߺ\š{¦ï !r•wEˆ®;UGÎBšÜÏfùa„`B`I„ÄÝÌ„TŸ]2Ÿ!=Y©–=ÇX!Ý1$Þï!Q÷m„ìC¢ØÛåcH!1ÿŸþEyýìÞ°9R[vu‹Žž°çÏÏ;6=rbzàäNßQ×EËàk¾EþyõÍw †$VLrúú_L¾øèäO¥ÿøÐôß}ió¿6þÚ·w&¹[Ô¯‚ÎÙ`ãØ-‘ßTún@Œ ÉqóN Ô.=·–“cö-Œ`.{á;K€Y‹•M{ø”{Ú¦ºøX~ÎùÁížuP^™qƒF{&B TJ§‰¯lOä ŠS¨Vwð@‚ Ô:ÙÃ<þé×–ÙÞ‹Þw™=ë:¸éŽûÀøþ/žüãG¶¾úí­iâçÜ Q:Ñ&®a‡-ÜzÛ®n¹Ã§íy§üEOØóN»ÃÛtUÚí¹ôdN䑨GE1©ýétGkT ¼·ˆ<ôò|’$:Ms…«DL…eÆÌÖZ (Âbá¦Ê€Ìd2)¸A@mœgçHëÄæE–eå Ö­ÍÑà½wEšèÄ( Oìü ß陵ßZ‹Èv:AòÙÛ\#+ ¯Q!ƒ³¬¨â@ ¢Q ‘YÇDb‘¡ì,!sše¨ yæÂ9ëýp´ê<¢6„Êy`DŨu’*’K«•'˜ÎzV&Y]?Ôë7NœÚ<5.¦Ö>5I =š$XKJ WW‰A)tY´ÖY–1ÉRžîLìp´º½3%ÆÁpÅ:OŒÖyY¬uZ'D%5ÒÚÂ%Ãíé¤ðÎ[çÄ_µ·KFJ2CàQƒgЧŵš9š$­ÄÇÅÔIŒÔÝ~"`Ø!–¡p¾!°$BäÏ-Bˆ¬ÜË Dˆ2‹K"µê@,‰ç|B`I„˜4í@,‰ßJƒb¿1–DHw €%²K X!Ý1¤ZwGÈò1¤‰Ž <þÙrV늽[)Åh¶èð^ z‡M¶Úï ûYÖËú:YôЉâȱq¿p ’„¼òØ'ËZÔ³^ú~˜üÀ£[ÿñË›ßÙ ­\뤗$)³Þœà_wÿáËãÛÚÉ]í8!™¨#f“‰\ÑæfƒÂÚ\ÙŽº¢¡cUË«jmÁ¦‚L³ ÛlT…_yìþR»üâçß.Õ¢ ž³çcï°NWúýÑp0èõ*]e³~¼8º±=*×ºÕÆ˜,ËDý2”*KŠ´B¨Èû²6fXKª„/ªÂÒþöý¯¯îч‘ÀŒéð^dúçètµ×ô²,ëõUºŠéáù9ÇÇCë1.ý6Y1µÜegê¿ðÈæúòæ_÷§wU’$  9=U~Ìþû7¿ðñVîa^·]êm³QF&€gµE‡su‘éI²µ^o8è÷å<“á¹'ùi“GxækP»¦Pñ¥ ´Óp3&'þâgñ~ôµŸ ©}³à_ƒÝœÌÉüf”H|ùÿ€„‡Uv™JDdć²rÏQJ1—!/vµŒ›dØfú\ïs£_îmÁ{Ï ´2Ê­VXÎ{Ù*™õtZ€6£Ñêh42:eçgTИ: \›œeÙG2IÖoPDÍ Yi4Zê°Ò¨jûà0ëaL%Š“­LkzÞ¡ï !µVs¬w)„„Aå]Jè»#Ä{ߘÔÖzõG,‰Q8Z„X!ÄþŒ $ÆI!ÐË^„î"[ÕeÒC¤¾µ BºcH<뾄̴'öC&'þâ'^uߥ7ÜÕE)Tè"=ò™²õ“o¼/W™ì`’$Ib’$1‰ÑF—BF§iŠéÚ÷¶WOmsÕÚœ}ÆÄ/¸äE]÷Š{þËWOoŒY¤I’¦iš&‰QZiJ¡Öú‰1ü·¯ïüõưœ] /sìDä­ …ÉolNÑ»â\–>µ’¦Ço¹F‡ ícßÐ hò>› DÄ’çãö[Xj—ÿÄë?±£ÎO‡ÒDÞ²N³4ËRc´BÔFgYª³ƒ“ÃãÉŒ%;Š^¯g’„*Ó$I¡Â¤Ì«6kr1\ÃŒž\«0™û¥•.=?ñÆûmúŒ¤·.·ÆÙØ*­”VZ•¦ ¦kÇvŽ'*Ø2†vdSŽþzcú_¿zú‰MN“$KÓ4I¡•6¢:¾ÉÿåÁÓÿóø$0=f½9fï}ÍKª l¢ÏOz*é$ÕIb´R Ð-ç¹±³¾¹sÖS¨Àk© Sñ«ÿ쿽öWÚÙZ‹‡Í5²îçÜàj]/[«»±ôQl«T›®„6NY“=·+y+^j q8xªk­§Ó©Öz4F#™›%ë°9È#Fès)Ô¬€YÓ¯Š[$Ac­ÆnïZÞ`èŒÄ§½ˆ¿Ò=Lјβ„´>ö†ø"üíGH9‘·Bj4í=#$¼Á'!q õÿ'„Äç³O„ÄñûŠ!–ßð¯~Z’°e²ˆ|ÍÌ}â5O;÷èÏüä¿óã'F§‰É’$K’4M’$1Zk£–+Ÿ1éÆöèôN½&²%I…ááÿ|¿ß?÷Üsûƒ_^ÂY–¥ij´Ö¨Œ’eZ)¥ô翱õ—ÇvB»vþlE¼K© Fª7‹¢d3å¼6•{*ï=Kkɳ'ˆLÌÈ3ûʹÑ;¬¥=Ǿž4¼·KJÏA"<Ý›\Ïw|ìë‰1iš¤I’“ei–õ’*¥³4Í6¶WOmGl£Ó45W\…Jk@…ˆž‰5*µ¼E]]ÄAB‹<ðGCY&‚Þ¾yßëÊûþÉGÓ,íeIš˜,•äYò\T •V*M²'¦k§¶Ûäã§õ»Ó¾1fÔIš¤YšfiÖËÒ,UFÀmP•íuõ'_?õßÇi {ö¤ tñ- |ïé&ë%‰IÓ$KÓL©$1Z+-ØTJ+“¤'&gÝf8<ÀM)úÿŽûžøéŸºù¢´UT&®ù¸]¢PkW7çnj¿8štD’]4uÕ;†“ké|°ôíÔ&£"t‹¥âZ«I†,{‘rLìè±db,þæœC­ˆµòÀM©Ù`«R…(y4‡Ò[9€åòéô„ªè"„Ônë~RË“ÏÒT!*I Äà‹ß8ujk¢ :v¨ jc OiÒcB‡<µE’$Þ{IÅRPŠ˜€•Ñàɶ×ëYï!妹Q¨¼-€¼Aò®ÈÙ»A¿—D𶘌†½,ÕìŠTk r6—2_y¡ˆQéñöŽ(ͦiO)¬õ(²ŸÌ¥î#h dÈŠ¼¹ÿ®"×ó®O#M²~¿ßï÷c(ISmŒ6Ò$1I’sr²Â`¬µ“éTÚë\¸¾ÖBdt€œ$½ÑÊx2QJ#£Ý™¦¨™\(8úºa€tš¦RÖ’ŠšTžç •%v|üö[å<ß~σ‰I¥ãŸ¥™Ö¨6Æ( UÙ NÓã[0™ÒÚ$‰uÎ)­@Q«©ƒ¯þùNIMMùÔÚ(¥Ó,SF'i¢TÙ[×Jó>1)¼cÎÙÕáp{kÜOôÄ–"£¡Þº×UY/M2“eY–f•R:1©BdO$ÉúÙN¡Â³; ѱ‡¾ök~Ñ/;ÒX›û'h³ÏlÎC6ç):&¨›íö¸GÞlo/°Ñ­Sgc•Mx]>@¥úÑLi0¬Xq­âŠëŸxB.;håüj^ˆ|Y‚‹O2ž°‹hl©j›µ g±ÊöCmP¢Þ#k|tè‚Î…òju”ÏEéNξ/„ÔÖ¹&Bm¦›‘îL+Bžuûà²ëß± BÊjÿ"„5a7„Ìîþ„@$5Þx|½‰pévEH\j"¤5YlEˆt1!$GØ3B.¿þNø·}n„,C:²k iŠAì-†Ôd:R‹!ß{ðOíÏŸþî›Î‰•,!¤ƒ¹1+ ™sP™ôó?lŒN’äûŠtîd¬¼8ˆ BâWhLöçÇæPá˜<”½Ñ,Mù«œ<þò+®•÷rçÇ¿.•¨²Q¤T9ð¨å°žð‹Ÿ(BNï½4檮=2T•ÖZE,•j«×ZkTT­@!29ï DÖÀ¨XÊNB€S@âÊ"%°ùþ¬ÆÅ=­ÙmZÓÚü/¯ù{r=ï¸÷Áð®å©†Rœ ”B“dù„ŽY<K#Ql‘ŸgBiÌ‘÷ì)$â³ÑW–™˜* Ë¿€Š0~¸íhmþÑ«¨:ϯ&Ib¤y+ͼҨQ+@mÒ?û kzóázèÛ›žP‹]O•uL ¥V¥”ÔZ{Ÿÿúa¥*1äÒ¹Ùâ9Ú$e7YúËå15–oœXÈÒ=)TØñ„›‘oýÍ?yçñwÿ‹kõ‚xTÓ•Ž ‰š y+!¦¹ÏŽÃ}«ÈD<ÆÙœ-oNµŽYÖ$@Zƒ˜®— fŒD—¿pæÔ}éKß*Q¹¿÷4·.6ȵ9ä²–Uãk-Vè¼×ZK\®Q«é£l¥­Së^w‹"C\`²‰Ezk{CH+!foYtz×¼ü½áõsozß®ÙUbgW„èè<㓉R{ ÏB"«„Ôê"O!Bžõ’w‡ŸüÑ_øôY@È21¤6¿çR"a „Ä1ÄM6nû­ïÝõ/¯Óó Y„EÌ™˜•­IbôÖWô§ bÕGƒ÷­ IDAT‰èf‚&¥ÐCoãt^«€ÊÉXÒsÊ)¥cþÑ+¯H¼ížËÔ P ‰ËCƒ@tã´?¶1Q È, ªÉCÄzô­¤º8)¯—BQëvWõÑEÃùµkß}ç‘õH~æ¿úïÈ‹w|ä+ˆ *-P qÏ1£ÖаrËÕdÞš!xÕPK±Ä¿gü‚ I戈X“!¢Rø+¯¼NŽðžO?¦P¡‚r0«+å"*ðÜ;~rÒÚ¶Þ™úï°!ÔäßÊ'PCËÛ„§Ý÷NLêæ Y¡g ÙšB…Jé²Ð­4VvÖ¥Ñf„O>ó²P`vEI“lÿÿÇþÙ_ùñË2lê1”VÒà²H.|]4HöÿqÕï=#ǹòEï<ƒWùª×|lŸG¸æ–»ÏÌûzÉ™¹>—¼ðÎ3rœg½ðŽ3rœ«_q÷¼_—¿èŽ}ãðýgæ}Ýúé3s_vÏ9Î¥/8C÷ý%ï9ƒ÷ëoùÈ>pí+?zfÞ׋ï„3ú%)¹"Äx ‹}͆ö×õ?ßð«/¹¼§š™(AÕŽ„yÑÎÖÔ_~k\ôµVeC Õ/¿êºÛïù ÿÞ‡xóÍ×z".f¨ä#X¡J’䯎ك£Ô˜H®I±÷þ[߯Lµ7ßtÕ~÷î/¿åÆg1Å™ƒ0”úÚ7Oüøs{YÛ éÄg*Tò‚šsçÖƒ–lÔ 2B!q¬]ºX>¾ö"þñŽéðÝͼ‡™$.ˆ·¾ô9ïþÔ# üŽ>xÛ˯öD’Ž 3—ëÈ •I’¿þ<ýàl-F­H®L$èß]aefa…D3<€ z?åµ*f¨ðW^uÝÛïù ÿ·ø¥[®ãÙ>JìÀ‰@2ÆüÕ1{äàL ?œÀ7¿³5Sy(eE0홈˜˜±äkV·øëß>}ÁáUÕ°Ýv#•(F`@,µè‰E˜˜JäH1Ê"æYO¡šÏêû¿µÿêÞ ›>üàÇ^%¥fZ‚DÙ¼Ó߸ïõyáˆ(I²,ËNŸ<¥”êe‰Öz|òDš¦v:MÓteuxêÔ©´ßÛØØôGpä§Ói8²Ö>ç¥ïÿòG_=&“‰”'ÛÓáp˜ç¹t÷1Óét0Œ··jöpa¨”ºâú;ûÜ[XñLáT)"bçÓ4õ®ðÞ÷³žµxïÑs¯×ÛÙžŽF£ÜÙñx|Ý+>¿Óßs£›NÀùíñÖ`0py1•IÐÊÁ(ô-*Í̩Ү°›'O)¥L?ËúýË^ôûÞ}‹X]]nïlnn:|0Ïsy§Æ§Ò4‡ßýîwS­:4ÃÕ•'O¯¬¬äÎ+¥ŒNŠ¢xöï{èã¯î%)1{̤Ò^&Rhf«8looF#¹™àïü³ÏÝVŽu0Q’$§OŸî÷û¡ù{üøñ£GÀd2ÙÜÜ\[[CDö䊂z½JÌU?÷ž‡ïÓÎ$ï÷ûe»™™y¥T±³}ü‰'’Ô †Ãáp„ˆ‹rù‹ßõÕ»_± B•s®‰Ë®á ßþÃ_îFH¹yZ€Kžwûß~]7BVÖV€˜&ÓÉÖv!WÿÒôàG^™h³“ï‘õ>I|o8 ¡ø –ï\j~Õ." påõt:í÷û²KH’$Ïólu$&PÂt ÈäÈ2²„!i­ ÑyžxÉÄJ RTÆNk-%<Î9!”EW&v^ò}TeµÓ(%¿%r̬Pi­½³B¡ _øÓ¯½†‡>tót{§g’Iaqg¼%ž‘¨Ùhí¬M‡}ï=h$"c E!„kmo0“OŒ ÛÄÓ§O¯­­mooW26HDkkkÞ[Çä˜ò<ϲLì3‹¢ÀT i@‚¾µ€LšÇ¸,,#?Aä‹¢<æR.Χ}Ñ‚$1Y’Ê?5ª^š!CböˆRJ-BˆœÞ2‘[ßDÈßz£p¡à¡ÿâ®!^ŒGv ÄZ›¦©ÈRN‹ÂZÛDµB$•Y„Ý ³†¸ÕD$z_ùÚ'_÷œŸ+ëXŸÿÀ»"¤;†Èën„,C )ïFHw ‘C-ƒ8†<þ©×‘F4ÆÀg<ÿŽ/ÝucBÑÉC®Px­@R$&r¼ù–ë~û}ÿÃýæû>ÿ–›ŸK䉈ÉsY7‘D Û{`% äw…Ê9·Y¥Pä½×ý[o¾æ·?ø½ûþoÞöâ+ËcI_‹+ZÏÖŽÛ™ºxc¬……ˆqx^>®†iÄxh øœ,²½ƒvÁ'jކÔJâ_ɽΤC‡$ŽÂÖÚ[_zõï}øOtû=_yë-Ï%ï 3 *ÛQD–tn©&â™J Ub´|ª²~Ÿ¹÷›—D/[ù‘^3#*‰$OL¥r !¿î%WÜñѯz¢·Ýó +?¼÷ÞI"åÏ‹âøÆ‰?}ðkM\þùiššè#”ú"ÑÓs½÷“ÉäÛÜló†þôÚÚŠÑ:1Æ$ƈ¼'"y"ç|ëy>ïúKÎöD^ÍBÞp)¡T“¸Ðªé²(U¯mXã>DJùa *صãøAªÑ“»;ÙAò¿i.Ý:G3ÛdÄ fÞò¢HûÍûÞûT(®;“pÕÚ/·\ó,Û9ݬyó‡ÚèVÍMˆs„õ·?§œ;?:ÔasÖÊzY!ñ‘éBu $Þ¶"$Ä]ÞkyäÓ·À×?ù†ý#$þgBšo­†YË`©\t £½c!­=‚= ¤L&–@HG yä3o€ÿôŽç-ƒîöëÝÙ5†„|}Ÿ1¤üËÇ8?hEHëGà-)¥ˆ‘‰=±#rÎ…Í‹"Ï‹ÛnºF˜ËÖWL¹2  ïr[É&;5¬‡™¹Š÷’F8kßü²çÈZ÷{÷~UˆüÒ ,ß0{OEîƒ^@˜hºÖÔäÊj—+¬ßÆ6¥ cÇÏøë­èØ[>+# _Y¼9òÎ9g]a‹ÂÚ×ÿÜ•r=ã}Ÿ/—zfér1±'òDž ÷ÌÁ±1L‘ri«¹ï•7¼'N›â$Lªª¡‰D°H”þ™=Ë}wrßo}ésä<]ó¾—M]^D³« µ”÷}.ÇñqúÞ àzùÇh)‚ >­u…µEa k;Îó©i䩘€ÅÐ7kµ"jcÜŒÎÆÌŠu̬U} oz>Ë”.´I5TFT3áž•+å[~~YmzútÑ¢8^}Ëž¸œ•@`/Ï4–M‹V Ù“  ÊîvµCò Îâ1ìã5`­Ÿ[èÐ`ñƒ&oh=ó‚ö¼Rʱ_Dé]$fxFË $v:kEH¯…Ðf­ÐT¼š—‹÷>)¯Ø\@ˆ XåÇßþ…g½ä½ð¬—¼û+÷¾fÿ©T–XÀ+²Î)«˜Á;ÿ–›žû›øyzûG|ë-×Jg”PÉ5÷Î{W@ N‚Råhg5"YTaóJâ·>ûÆg^ÿ.ø‘[ïûúݯ„†npÇÃêÑ‹@¾QfN×¼ìýH» Ç-Å€·D“õΑóì‹ÂNó¼(lžçy>µÎÞvãs¤áôÛø"{b’Ö–\.¶ùt:) •q&€JŒ¾.ÏÒpÂMäS¯“ó|ö+>&·¶¶¤"(w9˲¢(¤©-OGjÈ:‡ ›Ë)åUm§p–á\+AÍýQÆ–ÊAù§£fGíńĚ£xX#C©z?éØÀÕÚgM´ì !A§´!µ Ó=#¤Ù‚Y„Z£°†fÞ°!1É£UÁrI„Ìv!™év#„:úŒûŒ!0oU¶g„Äu»n„tÇ’SµïÒÑJÞs i"¤£áRþ:M÷žØ{ï=yçI/ä|É0 ,O^ºNެsÞN8MtMµuuPŽeÌø/^˜+å@þ[n|¶¼¯·}ô!¦©œˆ†= Ì™VzžùŒ×ê«*¨¯wÂVòäË[PY´•Ï~UWd Ò¤^±»ã¬/±çÊÿYk½õ伫þP¨O;bOt¶S¨Ö§´F_¨Å2¹5*ߢ8ºÅÛ»²öÛHA m¶Î”¶£]7ÇMæP-êug©°ì&p98ŠaR¹I‰H¤ŠÃö¢Y…й_!k‰*ËáEo³©k:§Ï±`8ãi]'ZH5æJ !ÐаÞBEÀ&BZ…=wUj)óD¤‰Öµ¶!µC !qÕ§!ͪ[“Ͱ„ÔªG{Ž!µêoU éFHw ‰±!ËÇ&BvÍ¢¼-,û’ÁC’/y–Î9_6ñÊEÌKVdÝ™LÖWU¢g#>á]_qáÈZk­ ,•òF36Ì[^þùù·ßûµ°ŽZk/::.s šÖQ'u$§Ù𹆲œø€4S¨š†jí~`<üé2;•×]ÛyVê=å•’ŠØzg#ç‰éÖŸ- Äí÷¦¦ÆOc‹ÌR(¢ôÀI•I@iPzåµ±GÉâ9,N"ê×ç½÷àã6¨ ÷´É¥ˆ·È\ýd÷D^—ñŒ#*ãÏn„`õ§!–DH<3øä!FO6BBW®!°,Bæ$›Šäß/B òbÛg )ã×éŽ!pFRK¡öC`¾Fø$!d™á‰õþÎt²c‹r}*ÿW¶HˆÏzÊ•{ÁÙÔ ÍÿÐÓ {&´A•j“c”V 3#'…¶‹ØàPéXNF)£T)'UVÖ{ÏÀ‚$Uv ‚rtNÈÌ  4v{åy/bÝ6»°f8:›™‚Ù½|]–¹Ã*4&Ízƒ~¨” û!‰&¾²IGRE*L,W<ˆê’Œm0"C IŠlq`@Iÿt!¶È–3Õ‘›lm?=Ã!.Ì~Ë «¹°… Ñm©É t ¤ùñd ¤6!ÕذÅÜ!1šiN~ì!‰j?1$oÜ!1$TÎ` ÙBf—îÌÅ&B:Z“qÝñà‡xbk¼•‹¾gU’ֻ¹¢°ÓétóÔé•trp%M>²>Ç´Ö†ž²¬ÜÏ8oå¹— ½·Þ‹&§´[hNµÙ{ÿ†\,ò°×ÿÓû¯õBî"CpÆ‘«ov£ òÍ­IxÇl0)²„ùÖšq[Í;2Ιb«lyÿÁ[åÅ×ßÙA €õµ–œÞoåy7ñd½·ÖÖYë [¼ö…—<úØ·ó¼xÁ/}r}-“j:êH‹Ë{-§”¦i<®Çsá?i­ÿâß\uôî\TÆ“¯ZÓ#sb<Þ*Š¢pÖÙrŒ®peF"zQÓéôô©Ó%Zã¡ýŽbÞ…çŒ~ðŠ5ò®ÖѳeBé}Tðºü¢á‘ƒ=cÔáƒýÚ¡t0èQêÀ€tlss<™L«<ß[k k¥É˜|žÞªí§`"¯6è:u2Í”¾Ä£4ЉH•ÅLˆ”Çê{ˆš0`X ÜL!$RÄBIºñjê1õˆøµ’›µÜVsø&%³îî®°?ôTŠ€•Ñ2ºÙ´‡¬]øÙ“æ"ÿŒC@Mm«Cz´¦;· a¶I‹ÙB ²ïFHí6Õ/<R»}iòb„ÀAHH¡vEHm$»†nÎìò‰›g*†t#¤;†ˆzÖþÒÁßs éFÈ~bÈ2ÚòqÞ!³>ØoomçÓ|Zy^E‘çE>-¦“|ss¼µ¹qdÅ£áÜÃÃXÛå»JÁ[`ÏàŸù´þß½b8LœÍs)nÈø”£’t5-ŠAÆW_<úÄ¿þ)9K^üû ê”®´ÅÁkiàÖÞïœC3ÑœÁ-3*V žJFæ/ °BÐ XT¥š*Íñ­¦Sõ£÷—ÙÉ•7¼{QaLbã…çô 6Ožüîæxk:™æ¢°ií4/¦Ó|2™nŽ·vÆ'ÎY³Ÿù½äwä?Bë\¾ÎZz`B…ÙW…½2"hTˆø§|¹üÊU¯úH)úT%ë’è ž8]ïŸÚ<}|kk'Ïói^Ý÷iyž§7Ç›§]-ÖFF+<ïðH5©¡]/×üØÕëƒŒŠ¢(&çmQx©Åd:$öºËV¯£àië=¬Ci\Ž€ •RŒšQ3¹ëzU;uâ»§7ÇÓÉd:ɧ“©ÔM­uy^œÞoon]³k#ý¤P8âC­ZESbYÛڌ̬OÏuVÁܰ=0"’W¢ÙæPA‰Ðâ mS ¯¹WŽågj±2Žqa©ˆ«Ê±àG­ =#u6òî¦N’l1I–ÊŸzƒ":ë@H“»#$÷]R”«!$,Ò»"¤öº†Ú’¼g„Ôh¿«bH7BºcHü.ºÒCj,ì3Cši_Œfe4jU8« Ó^vt={ú90JNnžþîÖÖÉ'¾·qìôæñícã Ï1I i†ž·戒‰ IDATÏå´{i¬µbÑfÝäÔÉã+ýäG{ÿªƒ×\”¬\ÏøÉÎv^ãñ¸—òüg~Î¥ëÃQ?í%_ú`9SöC?o¢1Kt1Ýé¥&w9—îgQL™= vÊà+ˆœÑˆŠÓÔ8W0xOVk¤ÚN'ZÁ©'62£Á;шrŽz½Aî¼d¥­#f “ĤH X£sDŽhäŠèÆ ¸L³¹ï¶À7B­ CfdÖˆ£Á@jÀçî_|®î©ÍÓ3Þ¨Thy…Þ"W“·µb9¡iÍ#:Ž(HDZŒŠÚ× ”’‘ªê ¹:ÉÝÒVQ5Á%Á˜RÕ#Tc/•ÿ´jªå† #ÄUUÖEHi4æfR“i\[¼oFH˜ù¯"¤*45 !¡¶M!~Ý$BÂ"N3BŠ^!0A£ü¹CH³ ©vK=×i¶!áÅ6#d]f¡ž#2Éà×¶>¹Wɋ㎜{ÞŽ™…¹Öâ\ka¶µs±sÔ®Þ‡õz8hù}¡P®C0lkÕy‘Œ"µs¡sÜs»¶u·-´wíœ]œkïXl{øì‘‡õzÝØŸÃ·>y¾;ÉãÏ»Æ76–äÂì&U5ck•Jµ¿R¾0ô¿CÐ}6$` l—üþÛß]TϺª–îÑEò°m3GÞ;l[g¾/ô’ù^¼}¡}ôa½ÃÛîÚݧÿï¼Úý‰ó{&¶ù¡“–FA!‹Ä’W—eæ;‡¹½_òy/ÊUº@÷oÉ‹Ýc˜Ûµ½»0ÛZœk/εw.vŽ9|îˆÅ=ªÕ ™ìu¥ÔÎÅ™ãŽ\8|{oa¾³8ß^\èì\ìÄü‘;»Dx„`ðÀF±lw’⺠¬oBÖìXèœxÌâ®mÙŽšëÆŸG?oöÈ]³s3­iQ·Ø…ò¡LÉò†ï ÿšGqëbh×öë)RÕ…)ÉÖ=Ø% L˜ÄBjf\„(ØÙÊa40¡0Žˆb¼ìUµ¹U…^Òic¬T%vÇEú½²¥Ae†WIúÒý•³)U=J!fé;áaK•‚ÚÇ :Ñ6<ÛÍ ¤Ê«EH-'tc©Õ=Úr„”­!Õ Dˆç0­‹RùxÃ))2@evý!FÈz6¶!Õf«!ÄÅÆ[kCš2½ ©"¤!U«“>"ftÚÑ|/Y˜mÍ÷’^7VRTíÞØ5‚B‚P(•@€N¦P0³°–Ü9×9l{oa¶5ÛMÜ1CÔåyþý/ù/¹ø†*¼z¥U=Žæ)˵5\ÃTõA«ÆÌß¿­Ð.?áì«j…cÂ䢢ێç{Éâ\Û­§kj¢,ð›ŸxýÐ3»¢y¿.uÃùoúD‘2î¸ö …göê„RïÕª …˜é$ ³-wßg:‘”Ø€œÚiŒå!í–šŸIg»Û滽™vǵ!6Kåb˪ŸçÄv¢f»ÑÂl²m¾3×kÝŒ»w( yŽ^à^:ÐäWÁ\¶FRŠa™ÈÝ<ÂuŒ;c$†³_ƒ?Ç¢xïRs%råè!A1‰Q mKÄ'å @m% \ ¦¡¢ûRÑ$¬mc©>¥þü“vKE‘P2n%i¥y.¬M %jðóɃ¼tYÏÉ EúzÇ(€®L“B8Á›p¶ƒ7¬%òiµcv]ll!þ™_!Î o!Õ„åBÆçŸ7#&!¤67S‹jWˆ0DÓ Ä_x-BFy¯õRÊ´UéÉ[‚Wpß¼ CFRC'ß ©%woÒ†TÒàB9$Tgž„>_óî8~ ã‰@%A eÖÖZöå]`°ˆ lñt¥(cÌoÏ1g_ g¾íoîýÂ%bTÁ 3C  •˜ÊÉ»¹Õ‘VØè GRà¥{¨ýûo}×îs?ÇŸuå–oÛ'uŃ{.÷yÙ0 Iå·£á(¢(BY4~ºütEn­¹å]ÇŸ÷øÙË÷ÜwýÅUaýÚ‰7?É Õk•%„ê,”[ôN§3 Üõ÷z½a6r+Øm·h0´Z-M€ºÝn«ÕjÏt,›á³mΑ±Ö®¬¬´Z­aJ3òºJ)§a˜X`”ÄŒh™P£}s¬ ÝÜA70Òu«ºí<Ф3yƃ³,cfcrÊó±ÐÿEbW`f3êw€H)²`ijs¿µÖJ©V«åJ'~¯ÒZû†^¥”µ6˲åÕˆZ‰¶†“$q×âæ> !Œ1q»`km·Û][[ómDžé•eY¯×cæ,ËBº¨¢¦u#qç“ç¹cH¸w7<ÁG<îªK~fH!Øp}6ƒ˜!¹Ñþ™¯Eˆ}˜!î8“S"‰âÓ*ë"ÄÿB-B<5g]„xµ÷Z„øº.BÜA&!ÄgÅÖEHÈõ©"ÄÇÁ›´!0%BšmL‰fânÄ4i¶!Þt¬‹émH!S&cj¥ƒÖÝ+…]Á„ˆ …PÒ“&‰ˆØ ‚¬4) uK§µ¾ÿoÞî¾ùüó¯…Ê—’\*°úyÀ%ת:ó±t´’c]ÍrUékÞ~)û3¯Üý»o=ýh1!XDb¤}P›Ô©Å€{ £ô"ŽºÉi’;&è@Ì–­a«AƵŲX*°¤µBÜý¹7Ÿö¦ëàÄs®vÜ#Ÿrå¡*ÞiγJe¤Û³Cy&K•Sˆ@È©±Ú‚ƒŽŒÈÖ’cþ•ê‘Û.EDC$„è§­õÌlOÑ_^ít:ý~fffyyyvvÖZÛï÷{½"æiê\d"zå;¾í¹ÜÕòN:늇ö\øP,e4úSef!…‚Ø0sÁ7¯L›~øæwžðêÀ1g_uÏWK±Õ’ÅO8B”f(=%¤€ÆÉ ÏaJ)åÝ !\@véuÿÊ~ì/ο÷¦KnûñeñS¿þ繡 åœO×Oa™èïÿë¿C)µÖ‘TóÛç/¸èçÿä¶›˜O'"…²6ðbf ÚÇØ3^¡K5¿Z]£ÒæQ[×›Âw®3¦õ…Ë@öÞq_°êD£ÐDBQÝ’·Î!ÓH %’R(¤Þ¬5ÃF_–+Ez‹©#¯!ÉïˆE_–+Ö„Ër>ã?­í& Â×€¥æ²*BÜm-µ&¹[¼„!¨!µÁ}-Bª ü!ÓpN}þ&"dÜ~5 Ä«ÎÕ"Ä]þæâ;×EÈØQAÈdÞq Bl ¿Í $ìB¢MØ*“ió6d„4ÚêŽ8 ùÛ?ü9G(%2Ìo_xó;~õ÷¿ðI¢OBHíÉgYæ*ìDd ¹ fš¦­VËqã\! †b¤®C¾Ýnû 3D)¡«”pó‘„’Ú”¢Ó›QJh­-Až™$I¢(²Öê<'"…«¨y«”Õ†´q5efΩN3(„øÞçßú‚7| Nü•+¸íÝÖZÉ ¥´, Z6éÐ]äØêL%×–Eš¦ÖZc,¢ìõæB]~K$¥.¶(9¶L r£A`"ÑÕ‘‹›kI[DZ’BSmý{ä¶KÿtÜÙW=pË»\8ˆZO-o3¢÷øjÛ²¤ý™â•'Ÿ^Þ5³W JDG®rgèÃ!÷ò¹¨ϺâáÛ/÷ Ms¾÷ÑþÊ€ÖR°ŒJ@¯£eŽÝ!{½Úí¶Öš,S»Ûɲ̱üâ;NzíÇ`÷y{àÖwºGRkæpïší•|µŸõºý^GÌÍDÇÞNl !–åšn³H´„H¹n§£|ã1$ø—le0X&ˆÎ÷¢ùY{üQùYå¼Ûà{챃×Ñ9˜ŸŸŸŸŸß  …ã ÂC‚DŦ ý•µ/ßüµm'žä=!Ђ߯ô3„†Œ1:Œ’kæDb¹;¦¥Ug°CH11[žÆèƒÆL-!ÓB†?-t &PpJ–ÆÔŸKÊÅ¡ %„‘B%-¡$BÆQ>оÞç0ç,…\P›&õL·à¾ñÛ‡ªRJcœêÔá.—óÜ¡NÜoš×zqœ>égˇ îTB\/wBJLÆ„„:„À”ʽL@H€ÃÍ ¶!ˆGl!cl!Í6†£ÐÖEH³ q™‰MØ@ä©ÒhCBºØ†lˆÍÖÿpë?oá™ ©½Yᔆêmmê±(;^Kä@!ˆLð‰(PI) ²o)¢QA‡‚õ8ä¹ú¤‚òå¼õÝ'{ œ|Î5ß¹þÍÌr…¶C4uŒŽâD*i”2y„ý8â4ï¢Q |EZµð^ÝŠñÍ#ѯêëá[ß}‚;Ïó>òÈž÷nä㑊æUŒØf "cÖsy®\=ÿòüh¹×®©½úì¬÷¢N8ûЇo¿|Ñ.=µ?7† RQ$ˆ–˜eôÈý#¶ë3Ÿ/c5¦ƒƒã9¶‡o}× ç~N>÷£ß¿ùƒŒîýaÿÇ)Ï9I@È8‰P-õùàjþÐ;æÄËŸ¿ ž BÈbŸXÎȶ@DEÀD–"­zØ×“6‘bz„¤Ý÷x¾ ï+UñÛK\NÍÃOî?bgë…ÇvK·ïàÁƒ<묳š-Øž={6^È+˜½ò/ÃÇç¿îÇŸsÍK.¹ñþ‘Þÿ›ÇC„€b 8… xáå‡wŒjÿvÊk>þ¢7æ÷ÿÖ\û_No@Hƒ 5‰ÈÒü>@ùAÚÃ7Îub§FŠRH £ŠP*!¢ ‘FM^¢R#vœèp>šD¡„¸ïÖbzîÙ¿ýyr¬j-ÄqÇQ¤¢HI¥d$¥’JE*IbÑZØO»ú&.nH7-ÄkV!JçŽ.ÓÅ-hÚ =¦Ñ¢Ú'âá[ ½¨7þç¯.Å?Ó^8±×ëv»n·Óé´[­$‰“8Ž“$îÍtTïØo=qÔ£?†;¾|ÌÛ‹ŠÞ ÏÿÄ?ß½²w‰"¥â(ŠTTŒHR‘”R*)•zú ý»o>óø3ƒ‘‡ë`•cZPwßðf÷þŒ7~î«ßëï_Å8Šã(VQÇqœ$Qù{æ ý‡o>óÄÞtJ„d6éãóT2ŸÄqâN4–J wkU$£8ÂdaŸÙ¹¦“)òÔýµ²}‘$I’´â8‰ DJHwä§÷›¼cŸ?OïB­ë?À«^õª†L•𯅠ã3ÿ€Ýó…Kb)žyjÿµû§ÿóªÇ¿øÛÇYk™Ç¶F$€a¸Lý8mŽžÕ†éŒÏêõü×|t‹ú>´%Ç9õõŸÜšó9÷š-9ÎÉç}dKŽãôN6ÿ:ý×mÉqN|í֬ϋÞðé-9΋·èºNÛ[rœWýÆW¶f'kÒ<»çâµß’ãü쥷mÉqN{ýµ[cÎÙ;æwb ¦¼EQÔjµ0Šr0()}w:I€Ü~Ù ¬èüš/¿ãOîÿ‡ÿxTÈQq´ø†B¤ç«…n@­ºR‰¦ã›Hj{Ç,·¢;f·‘J!Ñ»¹ˆŒŒå­7”eqùÅÑ,N‚‡ÿîòŸ¿ä ¿üªŸ¿ææß÷Ö—+¥,IPq$„b’¥"Š[VwtûýP´ÂZˆ\OÓºÚa:ŠØºõ¹‰@ˆbRPñƒÛ/»à?í¿ýñÿÝévZ­¤•ÄJ)4Öæ¹ÎDÀLd¥Š#êÎÌÞ»÷ð,}ôˆÅ¦Úë÷_þÂó?±k×®^÷ß{Û+¤d ¤`Ñ"ƒ²Š¤büÚ=_qjï¤cÚ%'$Œ?tû»O;ÿÓ»víúàg¾ó¾·¿B q’¸[,¥$fB” ,1~ýÞå(ŠŽ9¼×ŒÜ¶ttxÅJIåòÄdQ  …ˆ¢d¦Z¦¿°Bž: ¿û¨ŽUÇQEN˜™c¤¹xž ­ßüþêá§Z.”k .ž !„D4¾yFˆm‡-þÎû~ùš7ß‚|4[!x(iÏCÏÜ…†¢L–Â/Äý·^º¼ï@E6–q§Ë«ˆ8»}ÑZ›­¬õZï}ffn–ÙfYÖŠãgöí;üðÃ…DÒ5ý\^:óâï¹émQíÝ»7Š¢nofuuuff† Éjר LÝn7Ïóv«cÈ"âêÚ ÕjY`…"ÏM¬¢Ýç]ùàmïuϼ÷Ö­µ‹rÏÊÊR·ÛKÓþ K·mÛÆ–yeeevvV(µ´²EQ’$'žuÕÝ7\L™Îú…bqÇvn·Vi+RPÖú{÷îítÛÄÜn·gææúé •t4Y)eºÖ?°ïö…ÅÝ\ûÈm—® ˆØm·ÒþàÀÞ}óss±Š8I¢ûyèècމ¢heeeff&MÓ8މ ÓédF»."Ú}ÞÇîûâ;Ü3`™¬µ­VË7x»\@ÁW zÙ˜|Bž% tìYW>ºç=…#¿¯×KÓTJ™¦iÜJ”Š QÇý~?vC@÷îÝ+dÍ/βà|÷×ÖÎ|ûÍw]QÜjƒÀÌ’Š#¶ÆeoW.¯\RJÍÍ/¢’„)5 !§ž}ÕÃ_ºt„DREI< !§Ÿÿ©ï~þ-Ó ¤˜J;!'žs埻h„˜\ë,›„ãϽòþëß: B’N›€'!ää >õwø…i²¼´2333 !/xí'î¿õÒi2êUòüó?uïMoŸ!LØîv&!ä%}îkל7 BšmÈîó>vïMoŸ!Í6ä”s¯¾ÿ¶Ë¦AH³ qŸ‚æöxÇU2Žc–(òaîC P ¢%Љ% â°ÃwþÎ8çš ¿„x4 vòžÂ¿¸)5^ …u)ç%Ê×Kþ‘µ@H[!eœ8“ôôáð8ž¹¬³\b4Îï¶$nýèo^qÃ=J©+>÷û.y11°Š"D$+­°À<$¡aEO­vbÍíb7YKr\ëÕ娀‹‘)U²61;≄ äJ«ÜADÌ)úó?z_·Ón·[ÝN»ÝjE‘bf­‚™ŒµÆX!ŠÄäloæþ};g;ODBŒ/p?µþ_ýÏ|;Š¢+o¼ûwßúò¢ÔéØfb!…”’˜P(ù­û—wmï kýÈÌ–Ý€gë–wÑŸþ_gÿÕgèŠîþÝK΄(ŠÀF‘@Ö"‰ÑHïoÝ·´}¾ÝiÉIÑ2±3QR*EJ)%¥`WÁd¶V0õQÈ$‰–ÒÅÃH7 ¤ŸÙ{Ë#¥â8N’D¸Ot}ˆBZkÈ9õ¶fœîV½ÖëÈ‹#FH’l®AÛX©<X2(À°E­S”ñÚêJ;ŠÐkrèv Ä67¹PhØ T(•Î-ÄQ‹ ÍÖÚ$Iâ8ŽAb7,Ù\·Z-m 2D Lš)ÀêÈ* kòŒ­é´[€`u>˜é¶’X²Éc)Èè €8ŠÔZ`‰QÈ•µ>€`Æ8n ¡À‚Ö¹ˆ¡"² - VC)„"7]@©Ø©÷ÓŠc¡”PŠ€ÛívEnœx¬"­õ M-°6†sÓ–,1³ä(jÍôV!$2ê~£d2±Öjlsí{¦|DZ IÝÿ:%˜,Ë@ MÌBºA M–,ú)¸HÂåÃQ€ì÷ÓBûŸlÒn )Uic,‘’¡à@)ÜØQjO€!ÒÖjk§Aˆ1z¶Û­"¦AHªsÇ%œ„˜!±ÂF„À´an@À´‰¤l@l B`J„¸ôÃ$„À”q_“S"¤Ù†¸ži²Ž ˜!6¦EH³ ñ5ÜuÒ`C"aA¨„L*;ÔάUK–ªÓI²ÕeQœo‰gf¶T[ qY(Ÿ1*}Äš™“2ú‹ÎPJFQôá¿+•tu?1 ‹Á8n”œŒ’'WÚþ̽Q©©¢T„©ër°ïs"Õì©ô˜¤Õ㨕$v»Óiµ[­V+I’8Š#çU8TGã“R¶:³_{@5d¡îùÁª%ü½K^©”RJ]qãÝ®Ž'˜ §ª*†úh¾z×K£œF:™ïùAŸëâ—Ǽá®(Š”RR)éÇ*HŒ_¿goBúvAJ劊‘rÇ+j³Å%S0§Bb·Ý'rïS"RF‘rrnײFšESXðøã׾ߔ e˜,°óˆ“8v“ÒßøßùÇ{ö­d–­ýÑ£Oý韺¨­W IDATþÓî÷rצ‹ì‡4×pk(hòwÁsæØaàP»5z™Ùºõvž¸ ™Œ59"K`ÈîK  b'0–‚¬{µ.QvxQ~݆ʖX¨Ú/vD ƒ‰èÄRY`¡x‹À„NøŽ¬eKHå!«×§”±hêñœSÏ#)ix„µ×ªÊ¹”r¤]6œ “' ñ8?ýj¢”òN@A¦6r‡©rkjBNmh2BF4£õ‚‚2n›Ò€”g…7ÇjB¦Eˆ›ºy„”ŒN !þhë"$|Uâºu¦AH³ €)ÒlC`J„4ÛO0ß$BŠ_›!¡ ¹ðýßþû{÷. 4åú_~üþðöS~õß6 dR;¡o8¨Îú˜¤êz%"»,³E7Ý×ã³ø[¿<0a\SÃs¡<‡,è¤$gÜžù[o|±;ó«n¼G p’ÔÃ[âE‰PH)1ž;°f=àCˆê¥¡„QÕ•—ÜÐÒŸšÈÄ»\ÓµÔÐË££ùÛï¯ZæbÛƒ?ê׳ŸÚ§ök—¥{ß%¯pY½ßp׈Gã.Ù/¸S®G|ú`þãiY5Wûú©ýZ©”ú­‹_âŽyõ¾' Ý·JgÉð’|P?½P‹c‘Ý=rŸD!pø_€‚#Gèâwí „@ÍÉÞ¥¼!ýÔ>u@{&¥RÒu– ‚s>¼ãÁô þÓ]wÝå<§ðýf]¨PLÂK ÿ÷_]¼ù3ÿüKoûÜ‹.ºáíï¿3yé™7¾ãyÅ‚*øc„SÁ€Ì>5]Ò¥µ4jg,T§¥úøÀƒõ;ªZõÕÃÍö¢6h yJ¢Ï¥‰P™XW ,è­-IâV ¡áSêº4?ï··ÒqüRºÜK<ªQ“–n„”$€Ã9Dȵ!>L¬EHÈÃýéBHiúï†Râ)n!žÖ]‹f~Å,ê§šû?$v# åTB‹ ”Šâ¸$­IDȂݧ‚&$ æÂÔæyž$qZI)Í¢Dþ#çÐuš*®ŠW¯º!_ ³B9ÌX¸-Êå©H(–Ë»çȦ3Ó¡9&,ryÜ·”,F¾Bð/V§¸3³³K®L®„€Ž¦áb«1m\†b|&n1BŠÈ`=„i4WHc3BÂA!ã›Ù¡@HèÄTâ´.B¬µ(Õ$„Àhœó¦S"¤”Å)!¤H[lÚ†8Ž×4i¶!0%B ­Ïz™Þ†Ô"¤¡0ᆹ2³sÃÆËv…Ñpܬòê\:ÆIn"X²hÇ&Ô™§BŽP*%"N( „½ê–Q «b—Ðb cŒÌôÎלúá¾k‰þüãÿßåžNd­eDl\x -®¥YÔ¶ÆZk™Ð"±E‹– XX_ÀeéNH :~7 !رgQ 3ÕæùVÒx¡ÃÖZ£M–çNÉÚ\ë4ͳ,×F;/ÊùOÃô ÷µ|fÿJu–V5ƒt÷Tíê¢ï|í)WÞx7}ðÓßúõ7½Øåcˆ©äǯ¥¶ŸêmÐ ]‰âઉ’ѢƕßõšS®øüÝDôáîr^žsMB_ÏZ; –——«çùÚs~in®§¤Œ”R‘ríxγDÆXcüŒ`k‰¬%KÖ›åù3{÷ßñ{j=ž8vTñòñ›w»«çùðÚ†Zžóœ|.j yþù4Æx)÷ª<]­ærm2<Ì|ºvÜÑ_˜“÷âëô!-Ñ9¡Õ‘éP7±byÅ᪨ÒðøŽ0«öŽPª¹jå…J'%Y?ïB•zkýÌÈpdG5f­a«¯bƒ×…ªÞ¸I\Ñ’ßB&Åå%„„c.jfûšR;Ôl©ÕΞp9M²H6‹pÁ«)sx'#$ÿ¬"d¼ŽÓ„ÒȹB ¢ãº1Ãñäë"¤Ù†ܬM#d’Ú€ qµÏç!ëÖ&UÖüÛ²…DÎSÊ¥ÁøÄ1òòÐÅwÄ I´¼ÚL^‘Å)-lˆ´¶Zë\ë<×o;÷D—ÿ§¾iµŽÖnÉZÖœ*1fÚ–DMK÷±4Ý¥Z[¨þN­Ã—[pÂè™ÖišõûƒÕµ¾ûZëišå¹ËEM‚dý ]kaµ¯kŽ©G€/œm¬±¿öêÝÎyÿµß°Ö2 k¥ÀÀ@LLl 2mKjøBˆ,·Ì.uEÖX×ÒaŒ¹ü‚Ó|–¬d(‡½>U£¤¿G.çîQ®µeß<'×}~qÊ“xôaÜå\¥âP#_¬æ<×åBù\Ô”\¨õD Œñ%¤BÉCÊL¯*^:9"‚ñÒƒk*D¹ð¨á¦K…ó(t+Õ‰ÜÚ-]U#n’¥ &Œ7šp?†òhµ­ ¢ñ°óƒ‘£ œ8۽ʒ†€ ‡j´hCœb2cP®,Jì—ÄFD×1&¯ª]$L#v¶»Aa!¦:çuÒ”ŒR§ñ!E®ƒ µ„ŒïÜÍ!žŒ˜!#Û]‡Ÿ=Z!%¦K !‡Ó Äó–jâ×y“qÇÙBÖ±! ùÚREHƒÕ¤½°4Æ Ð­uê¾ ›9!‚ÔMZ ™s“äjÃÝCf‚5…CFlÐDÖkŒ½ìüÓ>xÝd郟ûöo¾ñ "²L®™ÓUÈ K–)Š"dr|€B0 %d6!6|F°b"&¸¤:u‚®ÚdŒ¢oŒÕFkm¼?á\ Ç‘2ÆæY¿Ö9Qr˜}°¶Hé1kˆèݯ{þ‡®ÿ}àÓßxï…/¶Öü$ ̹6%'C vµQ0 ¤ÐFÂ{/<=¤RJKV 0ÆäZK%¬%KÌZç?{úÎ#wÍE‘Bh­‰Œ”òÉÕùVÒJÆJÉÂïÀ¢‘Bç¹ÑFH‘ RB°Ö1Ÿ@ç:×ú™§Ÿþý·ýüãwE‘\Ú`ÿÒÁ]»OÚ­/ý¯§‰œ}+ê0ˆÙÜ5g ¸:$kP“çF›†*^)ÿ´5Y(_G,¢ )a\é¸<n<ˆ<’!“@ÜÍÚøÒSëÃnfv”ŽRxíi-ÇsÝÆ»iæ–7‹£”¦C„,Mlp:<$Àù\ØR[åÃV@|¾'´³“<ôR·]‰j]¹-TÍóW»0ü…o!E£Ðz©N/!įí&2©#÷¹CˆÓ^š„8ä)¸DºÚÓ¬7f2tÖGH³ ñ¤ûŸþI3B6cC&œŒ£îí•€5ic?Ũtá‚¡ö ªR-ÛòêÜÉ»\Bí¨R[À˜j¹Ð–È’5dŒ1ynœ/’ë<7ú7ßô—Ôù‹OÓƒ ¡-&²+F)…Kƒ­ûA2¬vÅ‚žÑ±HcÒ°m÷ýX¦Zk—$K³|0Hûý´ßôƒAšfYžç¹«ä9c¬1Z›<Ïcek6ëÙ®ò¤[=cKk.¿ðt÷£¿¼î[Ää˜å>nê$’ˆÝ”§ð™í §ªÅìˆJ¦pHÝÐD²DÖ­¡cK ߘ˜gÚʽ+!D cÝ9’5–´±ÚX·Ú*®×!¯|¨'F‘fÖÆ”2ßUîˆþÒµv©(mÝ9Ó¨Z˜/¦i¸PÓWñÖw¡üt@GÜs§â4ñ3ÔGÕZë8Ž½ÑŒœê˜*RBš<ãØZ«” *ŽÜO½Gïâfß°EQ8Ã$Ïs÷/¥iŠˆKKKî9tzwiZh·k­‹Á[J­®®::›ßkgggݧt:g’|sP©pP¢’øÝ¥Ðªq}UZ»hÔcµñ!r¸ccƒA¦s¹q@äÛ¿ÝÚFIì®ÎOçuĶ6ŽcwÎĬ®®º3qÛR’$yž[kgff\…Â-Z«ÕrÃ#•Rá^åíþÖG±ººê~êoŸ7¾.mà‡²UyÍD´„ø;ÛŒ/C¼y„¸ÿ„Â*MRk[ !…ÞÕñ<ÇZ„ø¬áºñ›P-B`J„¸»? !0>µ~Ãq¦ÍÛð¾„4Û0‹ÓŒumˆ÷z›2½ ©"d]o™|F­Ëèù|!0&qÂJÅ//§V0Cņ’bµ(ƒ65ÆZCÖ.ü«­5ÆZmµ5ï½ðEn3½â¦ï1³%v{³6ÆšTÑJ*Éa(&fåÇ/¿Æõ´Ài¨/Jêi–çÚä¹Î²<Ͳ4Ëiš¦Y–åY–ç¹KQÚXmL®uæƒú#³émÄþ±E6ËZë¸PÌ|åw$˜™¸#ÄÑèv¸ßì&ÀÃdŽ?¦%ÒæàRÁmxX ¢N" Žd!vàÚ %c‡÷h˜p3êA8DÌÄ4ôSˆ”(!d¶#†À&cœ fœÛi\ÝÖ«T0øƒ6×ò¾¼­q¡<¾EP0j˜9Z&4 CÄH…N®_…Ç"Œ™¼Y …‚üÓèbo& c¯ý_˜bœdm6n,äB)U×ñUÿQì"‹qö®(ª Å6) žÐë€jhkŒ1>{䬡'?U[«BEµ–_]ŸRSn•öQ0Zí<©’ÌB„x“·.Bª¹Š†.ªC€!Ä– Ä_6‰ê#"¤–´„Ôæ57€’Ú° ³˜Í9d6d,ôÜ ¤™¦®@À¨¿¬¸§„>ƒ:ÒñøiˆÒÓ:µÕ%*­ÃL‹•}ª?8Úøð+/Ü'­sG‡*Šw:Ïuše+«kƒåÇgZrÇB»º¶Ý¶Ú¹.Œr8ÄT㈉èò _änèû?õ ·,ó]ÙJd·¥ª3ŒcÉÛz`¼çä …®læ,ªwܬõWó3ª•¨n;ª"DI°6l7Ý£â0LäRƒîËZc­6&Í2“¯ÄJö:I!3è°yö' O™jx†äý§†^Ô ëB­Ï.,©†²"U µQb†vø(:må0ä-MÛIü6\*êû÷¥Cµ‡¢$”W[•Ÿ$ÖRëJ†ƒåÝû°[2¬ò„IòêvÅ,ÆNɹÖÚš,Ëœnux§½ å” «Š %ã†Õ &HV÷Ú‘tîß– Ädó©¦R&!¤ªåø\ ħFÖEHmncËRŠà2‰ ´µñÿnÒ†”Z76lC P]?4i¶!ÍþÇV!¤Þ…"CV3%1‰UeMW$cåP–‡‰"¥\ÔçºJYIWVö©8Çèw¤4÷¿ÎíËóÜÑ×|m7ì½ðŒ«Ï†®6«ý5£­±¤µ.vh"c%²ÆS®Íe¯9ÕíÍøìË+Ë;zœ¦Ù|/ñrY!œ€Yžç B›bˆ²Ëáy>Ÿ§Ü=ç õûýj²–ˆ^pøêÒÁ}ýþÀuß¾TÑ›ft>ìSËó,Ïiº²ºöøã»=³DG>Wö¼ô”EW…³Öj­-Y/cá|&FÀw½öTwüÌ·´NO:j˜;­"šeÙÜÜœûÃ8’gœÔ‹h•1¬Ö900YãüFtÚN¤un>þð[»Øk×"d±Óï÷W ª—ûrúÆmvÔyÒZ»zažåkýµùŽ€V µ9ã¤9,Ä7ØZ3|ŽÀ þ+ÜH(´@­±d9JT^Õ¢OÕŽéâÑPC¬¶%¾ÁX„’¢&™éI)÷Rë–•&‰øù޼ðKJd¶ÆäDFPJ ðºÝ¿cÉ„’ýEDT2IøÒ~Sº2jšaÛŽgņC0jC¢ªïUÛ˜Ò ·!£fÀF„4Sž-Bj9ã5[Ôú¡„L‹ê1Öun¯‡P è¹CHU»ac $›±!Uq„ç!Í6$øÎ:Y׆T™Ô›´!U„4Ü,ÆE¸&»ê’zä„êóÍqxèÙ{Ry1Ò,xUõ2üù—2Žþò[±˜—Vûý‚LìÒn76V[cŒµZcÞ}Þî,Ï.¯¼÷O¾)˜é(!ÀuêAyÊr9„(¥*ë}P!T­x"ÎvðÔ{Ÿ~fïÚZ0Ȳ,Ïò<Ït–ë<–ö²lfýþ`yeõ‡ÿòÄ—öüS¯#Ÿ·s¦ÓŠj?±ÛV/;e^k](¸”±ïR,t¡ˆÞ{ዜ#ògÿz·Ït¢HÉ’:ƒ[Ø™¶zùîY=JìK¾ ?6cÇÚ<ÏO>j¦•¨^'vÅÁ*BZ±X쬭®õu^0µLQ|%KV[cu‘›ÒÚdy¾´²Ú‹ÓvÍõZIÕ"¤ÛR/;i&ÏG H.Hð4ÖmÌä’g¹Î5Ê3þ|“KètW VIÌÃÛn)e$•‚‰üü¸IY5OS(åîo,ÜÇù £Äû EÂè9´øA˜n’ð¾ *aR’Þ ÇA—rc%²ˆf§ý¶…+é[W<§Áçá›))µç5E´ŠÕ.eš[6ƒ6{hRe†•d±¶!.ÎÞ/:²óØ“O>±´¼²Úï÷é MÓ4¤é Mûƒt­?X]];ppé±ÇûÒm¿¼²ú¾ÿþ¿v»­á);z×ÌKwÏY«­µTTÕh$VRð¿ÉóozÑÚÚ3¿êÝŸ]œk… ’!Z„Gïêž~\˚ܖ gLyÊCÖœrÌÌÎŶRbÛB»!;æTO\Y]ͲuÞuLc¶é ]:¸4zq‰‹„µ³{Æ ]k2­ ‘SNM>tLŽŸ|DûPs¡\ÆÌWCü3Pmµóêa®[z7tÉÓþ !ÕfæpÞBIš/ÌÜúA"î7kÛPCNCi·¨§Ð`VJÔ0Õ/Q”b£P2t´PR¸Qö0ÔÛ ×ã8ö¥«PŸÆqÜ‚¸¬r(iS Á«“°¦«^ݧlÞÞ B …kFH)#RBˆ?ìº)E–%„„çü“€ð¾4#Ä­Ø$„”ò ™$ùl~³Š*1hc6¤àMfRÚù6lC\ºg…Id ÍØZ„L"lnñxá²öJ7… çä”ìÕOøSÏu+ØÝ/ìZÛ[K+KϬ¬® ƒÔµ¹ ‰Ûiš-¯¬®­ìÛÖêßøÇ¿è~ÚEŸ/"ÿ©Tö Yó¥3œÙN¦ªf:Ãÿ=óÔÞ±½GôÃï=ñäÓ\Z^Y^Y]Y][^^]ZZÞ·ÿàc?zâ©Çî;íˆÕ?ûíãþäôó?Ú¨œ|ÌüϾ­›Pžç¡°¤£–cÒ,í&ô²S÷|ø|÷'/½ø†Pf¢ þœyÅ©½NlÝ1½x€÷¨²,ëÆöe§.îXh Ä]Û:"8ÉZ„±#ÞÞ]Y^~feu-MÓÑ=Jót¹{´º¼wG/[˜Âa‹¬Ó³rÒ‘½3OÎ2G,<÷¹Úè,˺ ½è„Ùíó­-çB­'­™å‘ic­¶ –¬A ÁL¬£µ (€Q:`1ôa¬×sÒìÖèjø;Ʊ Ãé§RJ¡sŒ,ic°ÄFô,\  Ã@|(³€\Rè >šf˜xœ…CÂ]¿Œ›ºPRg¨1”R‚“¿Ã! È›X"€@Å솦ÀT#סí;œ^ßðö)÷MÎIùg'8hÌäæÉ{#ï×p3)@²B¯ƒ·_Nƒª !°5ñuM"dìî4"„° !£øxs©-zn!@VoÞ†¸lß4i¶!>{½>BmHñï¦mHuÓݼ ©"¤ö$­ÕD®fÊN6˜ÀQµ‚Q†\žä2É‹r“å€0ÿUH¥2¡û)31ẛ–spJ®¿[Ì÷uf:öéýûžØŸZ,’¤Õʳ,Q,Ø,&º=«tFq÷ßxñî >ÇŸû‰»n¸@Ji-ƒ@ ÑŒà±3B¡fvwÁbÌÀ‚A §á­ />i~ûÜàyøÁGò¸³ðøÓn·gƒNl­· f“QÍ÷’oîÍ/yÓupÂYÝ|Ì£võ:-ùÔ¾ÁŸ\>°dVúZ™ÄÑl7žk‹“vÍ,.ÎF‘ŒÞñ™ ÿô¢7}ö¡[ÞY ~Ša9l™íQ‡uæfâÈøá>BZYËúý´ÝŠgڪ׎Ü1§$¶%ж£‹A›EBßÞiÅé3ö\”­AjȵþZ¯³Í¶ÏGØQRÊvÏooK!¦AÈ‘;»í|0{ú ävy-7Iõºñ\G½k¶ÝŽûËËq$¦áBÁÎÈkÅ-dÐZ»ñJÚ V;lçÚZ?›f9 (ƒTÆÉåµÅöi«Ecd’‘Š"GÍëug"‰JÈ~¿ßŠUf2 àH¹N…’ÆX"£$¢à8Vi+aIK)£XêtЊÛ÷í=ꨣÀš4M£(2†Z­X@Rg¦•$£HÅH X0³1$% !‘‡M.ÅSí¥]€îlª›tNY1ÓéXf)¥¶FÅQAÒŸ9EîJM2 IDAT’e!yå(~­VK0˜\»ÐFá X&Dì-Ì÷ûýƒƒµ™™Á"Íó$Š¢¤}`éÇE-Ck‰Â<öûƒ¹¹Ù\ëÙhΤ’Ù¶Õ$üa0JÖZ?¶–„’(Ežk)·K€*’–MqZÌÖ²AT(A(´–,åís3b]„ àBšmˆO}­‹fR¬Þ™Þ†Ô!¤©mÐW®‡çæhdÖûx|þF3Ūг°0iHI5ªÚ–2ñÑw2Ž—Ø`q¶5ÓVJä{®tf¸ÓZÉ ¤4“Äj['jµ ò¾.:õÂÏÀéÞøÀ­oÉAŽeÛ D"R‰/ÅÃPëfMÒŒ`æãœ;úyó‡?øäþ•µ\ýe¸ê÷%ϳ$éê,ïu“ã^ص­³6HïüÜEg¼é³Óx– ³­¹™Öb/zêa-µZIÇRFyž¯®.ÇJlŸowÛjmeå¡[Þuây€Ïûè}s ãPl‰9·0›Ì϶ZJƒlYkWVVºÝná—[‚v,´•°NZsJ„,̶zøÀJ¶²–A‡‘ì 1Nl RÈŹÎülÛk=NƒÅ¹öìL²k­¥†™‹AÔB8–[‰ÖlÒiÉÇÓu¸Pð,gä©uïŠRa™$zàŽûßÿùþçËœ´^ùÊÝtÙóB¥¢$@á4K Á÷ðDQ$Q¸º,Ô "-8[nɶDd‹Vjd8±¦’-X°p½+¥E]+}„£ƒ0 våmÿpbPþcÔ" ¢õffñ0A0­¢"¥SÀkü”ÝZ@÷çà «€JkºÈ;\·Ìë†ÕOÊTÿ­AÕØaDµeßZ„Õl­Þv©  B¦E3G7ƒa†¤!P7z¢!áx¾ Bü=]!Îêo!.»> !îƒ~‚0%BšmH•Áö\#¤Ù†ï§@H³ Ïdz„t˻ȲÖVk«)TJ)@ˆÀ¤uÀJÅD„(Ý”á¡lÝc)D«Õr‹üðí—…<9×)„ 333nnO·Û=þ¬+à‘=ïɲL)¥µNÓtaa!˲,˃Áââ¢B©øØ_ùkçE=°çÒ’°…%@f d‘ÉÍÝ’xmm­ÕjÍõzƒÁÀ%b•RÊïßð–S.ü4¼øâî½ñ-BiC:'‘@°dU¶ Zœˆ”ÖZÈè§!0hâBÕ¾ßTŠyl‚PZfí:™óÁ~¡: ±æXÞ:‹Öúg%D˜H¯M‡@E¿x|À¤D”å†.§RG2¾%m›1'wh[Cs6©=$´³<>TµšËq*Y2Þ8>o©èÙ 5 '´»e•áZ¨‘L„:ýž1¦`êjµË}âî¸!„»„4$Ìž5B\ä²i„”hæUð)â3µ©‚R4 ¤¶³!ᜇ*Bª© "`KR›¬ÚBÆ|¾Í dx¿ÖEH³ ©f¡ž­ Ñé~ušÒðÚýÚkG')}Q)&5è‹Àú–³§J)¡dÉG7Æ8T×Ê÷†ãç\¶ …SHaÊŠkÕx'þ¤m>œHÂ!áýᛋ\Ô‰ç}D„Üj„@)°Ü“X;FišŠ[u|5g|~ÈùdpòYW×¶Z‡©&‰BJQJ²Ž¸w–Ü Ä>I‘‡»àÓ0Aê¯Ú‘úSŠ-­ëB1€`BDB(éÓÔDô7ùÝ¿üR ‚h0©xé, koÛw«ár —`äÇU .µµêj}0ÄPm†°züê#Ê’Ça#tXñc%ž]Ž≠ãøÄ{¨ó[[x‚ºqµ23¥ð¥6˜žnwäuBlˆÌfR{O«CߦAȤ£=[„T×¹>'ºBBÖ×fâ³SÏ)Bj«Qµ©èH!$,um!Õð`c6$Ì«„¬kCüçn !·üå×wŸýsÍ©}Ýñ©× =‰»¶¨$çHuE…eøU;…ÓQ£ªNCè»×F×¥}½”ثүa8¯½ö#¾ÓÛÜûãξª:ö¤vÁCÚõ³ò¢B÷+t¡J 8ì$ oýC{.¯zQÕÈ­¤òñÃGÀ}ÿ{7\ìŽsÒk>Y+•ì–‘G=•£eÿ)EÈV½Ö¥“B4B 6¶8ûoÜþ­÷ܵçw·1[¶†­C¬s,XÒZ !”f¨ú%†>ò Ï¿öÙŸü׫ß:ù¼lɺœtöÕ[rœÓÞð©-9Î /øô–çäs®Ùšzü9WnÉqÎxóõ[s>õ÷ýëÏö8ÏÝǶæº.¼îñ¦yýÜ{ÿvK޳ûÜ­y¾NË—¶‡›|N „œòú­y¾N}õÖ¬O°Yféc×\‚dˆ¥RÊ;ö|ýƒKGþýÛv!3 §˜ÀÆD“®&ÜÓ[w¿îSðüó?s÷ onZ ¥ÃíÍ—2§áPzZz莔üýfX’€wé+Љ> €c‘£Œ“õ`½¯ìÞ[k£HùymLg+mÃßú®Îýœ|ÞÕ÷ÞôkÍíu¥ôgµ¡dÎIIe·ô Ý÷ðÚs¹³ 'Ÿuõ{.­ ª£*½ ê”zç쟯<ëçß³^þk·ÝwÃ!eÊ{¢“ò ?u9”.ÔÐ#d`Q¤åY|çöÿý[ÿ„_ü¯gô$X;T¦"Z;jÔ•Cõ[è®ß‚–’$‘‘2Dûöí[ض(””(²AÚiµžþÑ»v¶²|Èt:‡zèècëõz+kƒ(Š\böÔ×_ûÐm—2B–eqÜ’R.\Ú¶m[š¦ˆ˜¦© Ñ„iÚO’„€]—Šár£¥”/xõÇþÛ÷ ‰`) ‘bmÐ7ÆÌÌö„k+«Ývgmm­×ë-//ÏÎÎcúýþìì¬âØ_ùð½_¸duuÕZ»cÇQÖf2­Îã8v%p'‰ä¼ævÜÞ·oßö»Ÿ»h~~~iiIv:µµ5cÌÜÜìž|òÉmó I§ÝO*‰QkíÔö¬¡µµµÎLWJyÒÙW?pÛ»‰H)ŌƘ(’¡âŸ{´Öî_¥T–envDE@N8ûCÝö^wóAE2Vruuuvnfyyiùàþ$‰²Aº}Ç¢1FÁ„ÖÚµµµùÅm2iåDÐZû‚×òÎëÞ¨„$¢|*¥¢Vâ&gåy.”LÚmŒ¤”’ŒMûƒI9ñ¬«~pûeÓ D[êt:“rÒ¹WÝ÷ÅwNƒXEBˆI9á쫾}ýEÓ $í÷‰hBN<ë q6#ÄØ<ŽãIyé%_øêÕçLƒÕÕÕn·; !?Ó $Œ‰«y᯻ãçMƒ±Æ©lPÝHl!€ë«RJ`& `àá À¢o‡-rB8X$!k“$ö’¶v¼H]ª±>ð¥_;ù5sÑÔ÷_îÚOí#O ö/çK«šA  ¹™x®+O:º×mKŸ[šÆs ·ÅÒÇêïWØÎƒ~hÏe'žuUèE• Ö–ØX¶R€»ö32ô´ñÞßâjy§^xã#_ºÄ³ ,ËwhÑP'“65B;h #€†Úñ#wpèMBƒóÔOíÖûviUkÃdó‹f¦ÇžÌ)µ1„X«¶K"1‘Ql¬Ã4˜‹ˆ¦zóóó{öìyÕ«^Õì}å+_™ŸŸß  ¥” "J(©­A):½¥ÄÃ_»ëÒ/çÿË‹vIEÑÿÏÞ—ÇIRUéžs—ˆÌ¬µ«›¦eišnÖ†—ÁeFqFÙ7fAuü³8›óæ3êS\F Ù÷emÜPG”}én é½öÊŒˆ»¼?nÄÍ›±eVWuïUüš¢*++òÆ/Î=÷œï|GJ…¡RŠ!zŒ›»Â“‘0Í­LÇÁ°ÞˆáÏK$ÌI)©njp3Æ”Rœz"ŒlÇÇF£!¥B"Òžž>Wo^&áÄ$;×å*ÐR+ ¨BAŸ¢ébfˆ¥ZªH Ïó%‘6¬ª”Š©ZZÛ¾’:ùÞöL`Œ…"¢œI­Ì˜MÉ E'nl.)Í>b¨›‹U£H%…3($œ€Ñ(¯V«Qi©Uµ«©TRJQ›5Þ,´æÙˆ¢ˆ`¬nuªÌÕ ¡¤”œÓF£Q©TÌ&ÃnÝ̵˜úçjµjŒ¯”’´ö*×Z!$Š"© „ïûE1—ß!f*J"$©YÎG%;AHÜd¾!Æ`u‚3«SGY‚sÇ;AH•J¥!ÆèO!àת ¤Ü†Ä1†RnCÌ8;AH¹ );BH¹ ‰××É#dõ/aH8 RZƒŽBªµÑp¢·Uiþ9Ý2I«šˆ¾[Ʋ@J¥µv‹v !@ *M Ö,kÈxi&6á]lj›1†XV$oîÝêûÎÝíðK`÷Ã/Zyï¹ ùÌËã¢"áŒR!Äð„‹^|müoÿ=újÚaʪQ¶åv–Ïšüm‹µâ¾³mq+Ñ`|÷¸,”h$±x½]ÝÌG¾‘¡ƒ™{ôâ=›ä0ÿ˜kVÞ~ª6Žsãu”2Æ8¥!ãLJ¥d×`ÐáÐoÖD›!VMÄDC>µz|ÃPÂ=ÒÃãzÓˆXõÇñf{{ïR±jû D#Á¹Èz¨‡Tk¨j¥@ÈêÆ Âh(’iÐÇè(¿Yýýý[îBBŒX­ÅA6´jå§ï‰nþúŸoÕ[ük•ÐnµF­A5ë_ŒÌƒ¹\΃µûáÀþ'\óÕ/¡‘qÎ ¥RJ°Þ°EAºn0úÉÃ\Ô»ãvÕÎéänén !šëdÛ¶H-œ'çþ[/jÑá—¾pÿ'cÚS+Œ•R”ÆqkË…2e³‘(gœsóÑO\ÂâÓn€÷ÿ“û–}Š{Œ{>BcZ›h"A_kAfo˜ºÈÆÞj³»bÉZ¼vsøØª1¥ óxóî« DkJéú!¹~óÐ;÷¥ÛÏâ $¾`óª•.J€VJ+0µ’€€5DÐ7¬wôê©Qí¼óÎ;ï¼sÛ[622²…trë³#Ѧá8R²ôË­ÿÓŸ>têM|ôνN¾eÁ‡¯ß,ª¦$ÉT>£ÛýŠ"a¥­šRÅÆšÍ}üxE öWÉ\·.šhÕ’—u n\k§âÞ òü.E´eËZvÙpøYfkÖð™ÊÒ–%$Y•—ŽeZZ_l–?Ðt…—»ºmÂìRQ[.ÿÞ™•C™.Y„Pææ!ãH! ‘ Y„¸'Ÿ B\:y9Bé6@ˆ› BRëqB)AˆkÅÊ’M+v¤/EHŒ|„@‡)·!0-6ĺàSFL‹ ÉMX´µ!'üãÃk_~ჾ‥7pÊM‹Ž½rƒÐå)çü"⊜¹ã¼¹<ä½ËîxŽsî{ÜçÜó<Ïã܈,QB$”W6Ž÷ 릋{#LÛµ,õ>-ùf*"ÑôÝiïÓç¶ó³Œ­EÈöÂsφˆ+î:»Z­Î›7ïÛ7<Îã«ö|ß7§ZšÊ"5þúÉͯ¬/Ù’e/3—¢§`œ=íªûb.Ôî‡^ J ¹a­Ôî(‰É5Õ/m[nD\qÛ)æ¾ïŽÜc¾Ç}Ï«ø¾çqÎ9£”™ûN(£Ôó*ƒÁÀhƒ¤"gÙÑ®Û=òܘššOC×3¾>5Ò-@óÔÐKm‹@ø ó+ÌcžÏ}Ïó <gæ”{É÷£içB‘ö.3ȸUrüÏ{ìú“^¸ëãOÝpòÊÛO_óý3·ãæ~Ç5 Ùç?eñ³9à>²‰êܧEaª87òéú³ ´}°Ûª¼ÃQZÂ8/Qvn×ÉòÌ·»g5.T¶C»û‡ÙG±¨¦)ÕòDk²²7EuRE‰HÂ)áH‰iΕEˆ;EåÉVªoBŠº&çÖ—½‰ÒTÝÌCd”H‹’j×ýº#¤Ü†¤ê-Fˆ]YÛ"dÛØì:AÈÏïøøó÷ž³òÎ=~Ó)Ýxò³w|t…„ä¯È´B)5B…w_zçŒ1vñ-OpÏ«V+¦mg$ζcœ<%”xœo­…¡Ž%à“ŒRµZ5˜1MŽ !aV«U{°bžJ©ÞÞ^«LQ …”1 Z¡°¹ØÛì-ç<Š"óÕºkæü&™Å«×ë6½;<<ÜÝÝÝh4ÌIbŽcÚd´q,†Gë_ÿÛ£cœssíf½7‚ªŒ1³ðÇ^ˆÖ”‡Ÿ¯‹ÊH? Z›— !,\Í™@Q­Vƒ¤+¶!Ø¡ny*­µèèËÍ c†HdIî6e4Ê ©¼««kllÌÜ‹Hâý—Ÿoîû²ï¯àœW*>çŒQêqN L˜æˆˆàq¾a¬k¼™ä»uÎV¥æœMDO¼8ah‚>÷Ì?qN¥Ô¯ø†î2öžX]J¢l{J‰çyf´^Å«TüŠï{^WÔŒ2­ãœSº­]( R))AIPÚ4ùB©ÝɵU4É{ÇŽ0’‘ˆEJeH&•UÉ*¥š#nD-UNnÛ4¶$h%@Zª'’F¬J ¢Áü+ÒìOåòSjÅ©âIe&IiÓ\ °%ÖŽeIÝâ ݬí½„èäu«}¬µ–Z Õ"PnK—­Ìwö¾”›cW$µaJmõþ_BHK¢­!Ù…ÖEH*,¿ b•"„ŽW'ÉU Ø„´FÒ€iAH.¶!0-6ÄÍË”#¤Ü†Ø »­Šüª>Ëâ2”y˜C™÷ÙÓdŒrÎ/¾åqÆâh IÂ0M¸8ׯ¸ÿÒúöw¤PÇ\Çý°›$I+:‚Yà¢^1)$§â1ö°eón%¼ùÃg_nHŸýÈ;ŒOpÑÍSB8cfÑG@J(AB’ž}ˆ(þæÉõ[¼g5rIåÙÝ‚ëEÍ?âÒÔ3˜ UØË´DÀ–¸—B­uæÊ?}â¾æ¾_tÛSŒ1Ïã¦ëœ¹×hâ;Ä䊑{þ7æ«ç›‘<½z\*4n«{PJeÙvRHˆTø»§7— dB΢”Žãœ{œ3Î5±¬ä„Ähú!!¸­](¥Zª ÝJK[L×ÜÒI•›þ7;Èܸe9z²»7wX©ÔFÓ­íÌ]lËçyëTØ#wwH’¸~J:¯“CKÄ>ÙÖ»*Ì©È äédhÒ¼j·ÅD+×/g±,jåêÛoR„¤Ü…BòÎùæ@ˆcÈ"ÄB•#$Ûñfk ¤y!o „@«\ÐënC²‰È­"ÊBB#S¬Ç¤X>{ÚAf ß½áQ‚$Îdº]l¶– „ʦ¡Àúy¹ÙÉ"žY*¡÷lÁDÙˆ Â¼‘Lõ·{³Ü œ½}n%š ÆXR”yÏDC®’”PFéç?úN3{ß¹áéhB‚³C_?®Ý4Ñöåþèº2Eðv)w®%ÑZ[ÕÍݼÌ(g‚næõ²X2‰TësÛSIE4ï'„âçOYbÞ¿ìŽçå $Ôî„IÙ»ÂÚæ‘(7˜:Ñk7‡© C‹¿„Ä}¨ì%ov>SQš*Úe’”‚6OÐ)\E :iý:¸PBk©µDÓ™3i™L7¸ÿ¬•NÅ'›{ §"#Wç*k¤²Ý'Lɪá¢ÚÛ`ƒ¬ÃST z~5ŸX’¿}L™3Wa/ÅòËUWsUn”u2wwó.É4õ @æ*þ!$Ñ!JO BŠ2ƒn­ÐÔmˆËç.GH¹ iBHr™Sµ!ÍÕek"$÷$œsCd‘RJà¦5¬qY…çŸ|€BùÍ«#¥’¦ù¬T²éù¢M)õÇ'B3ÜÜ@o.ç¬9%Œ·=έȵT–RíÖŸf­ Kû½TJiõ©“Çý»7>j¼“–©vVŸz¨F'Âò Œ';•wã£9ŸPÚ²£`u’Ñ{çÙw»Ûæ,»1–ÉHâ¬MÞ­Æ^Œ­´”ê³§.‰ïûu¯Qi"ÞèÆ4ín ² œ#É|‚¹AæÏ¤TRj¥¤Åëí%^ôèx˜EˆFß­´ÖR*)¥PR˜ï≋ ô’IŸ~ªm›aD¤õ"”ZkßóQ*áù< ¤ʈzÌ«úµ¾îÍÕÞnŽL+M‘ôÔºì~‘ B2jžÒ0 UÒfX)Uõ+œÐ ”ZkŠ„"‘ ãÀØMB­ø‘ 5ªŠÏ•Œ´óÃPˆÈ(^B(cD¨ˆ"ÔÊ#ˆÔÔÞ  V2¨¤R‘rÂ5!AdlE¥£j×f˜<©TÌËÃÏbœ²(¾ïK)!Â0@#S„¥!Œs_ ”è‚Ø›0{va¸„ðXF[ÍžJ¥‚ˆJšTêJ‰RJÃË3òƒˆ(©´Tµ”" }ÎMŠDK…JH-¥‰mz7zJ¹Zk¤”)¥Â0T”sJ0’‘éon– †¨¸å€îj­-B”ˆƒŠb—‡¶!Œ–  S„¤9|.B`ld´„H)ƒ(*AˆJbæå1*‚E€¢¥,AHâ“t„³³ÌEL‹ 1ÏE')·!à1Ò BÊmtˆr›…ÎÒ¡ ÉEHöˆÖ"€H2®5ÑJIBR"´†Ož´ÿ·®}X*õ«:oé’8K«T3(£Ak ¯G³z+Y_Ç ö4¿‡tèÈ¥ðÇU‰G›ÎØb:ƒ ­¢Eߤ(önrsh4T”RZiA1†Ÿ:iñ·¯ÿ½RêÂëþÔI‹ Kp8Òè„È^{I"Ïþ¡%çÙÈSAŠÜ\cAÀRëU?8kc¯€>zûê;?®”"„º¢ÖÖ…r}MëiIðŒcl":‘ˆ0$g·×woz\*uá Âö«”ÒøBJJ!ƒ0ܰqóï{*;°vÚÉ0èíáM­T˜É-º{)e½^ÏÕ8öˆ¿êëëa”rÆgÌÜMD­”TJ™;ÎC\¸M£PM(K§§•ñÙã@Bg”1¹µʉBi­Q51ÁÜ=„ŽIñn¨)£ ŽýáÈÔÈh©LoB cT©xuDDP†ùOmÇ}ÒlIÛi 6ámÖ4AUJI ‰F(‘®u“mkt‹öpI¶Al³Ãkæ«Ö´Ê$eÐð6•Š> ÿTh¥I!¿{ËR´­Ì"„”"ÄÒhÚ"DKU‚x< ¤Ó~¢í¢¦ !E˜oL„X;>U’¨u·EH¹ €ÒƆÄ}‹§!6ųõR’Ÿ5Ž”j ¥Š"FQFŸ\z€©ûÆ5¿‘VêÛü—„Ó”‚0”6:¢ZÕÃKÒÙ'<¦I~7z7N“›¼Ë=[6_­¡2DŒDÜc#^Ø…ˆ„Rž{¾fMþÖu(¥lÓ^)uÉÎyÖ­ÜãÈKSãLÑíBIt¡v€ÿ®:Þü¸Û1—[2œ¥Ë­ ‰}qM´4i:PRG¡ÂHDêÜã÷1÷= ?µÜwåHç”8Æa2Í.E‹Sû³¸-z”£Zé¸Å¦Q$ >Ã(*ç¶ŽBµ4P±$W6Ëž.‡69^ Ó)ð‚¦¹QGë¡3B€AJî6·Z;û´@km¿Nš|^ I憔»$¸<wlXØÊÆ®½––ŽCIçL­-{µÖ’òeÏtƒÊåQEŒ³yËŒ4§"„ h³C¡”‚ÎOäoB².Ô–!Äå ¼âSÊëO!ÖôoU„$_§Špt/§bC @ e²6Ä:µSDHü«)Û{Ç·*BŠNbBÎ9&0%5‚PÔ¢HH¥”T^ûÛó—.i.Rñ,k)#B1Fr•r;ͧ¢SEf2‚¹MÖr \7.õ~÷N1 Ri¥”’R_I*u·÷ùî*¥¾}ý#Ÿ>ùÀT:ñËAÅyG%ô„çîüØžÇ\{{å ÷ëÞʨB.ß¾ü«ïj:cîuìå/Üžu¡²óŸ.VÐ"ά©8¼¤M‘óOÜ?CD”Z!`£(­4B )D‰Í›ç}r¯]vè÷<¦ÌH­õÝ®C EF(%Mˆ÷¸*Š"s  „DBPJ•”aj)Þw`—í{jÕŠÂ(ЇG·ßaÞ+cý^µJ)E‚Œ1КQÁàAƒÒZ(%£HJ4êARÊ^ _.T–f‘»ÍÊmC˜2m%àKHåÙa¸w]jeRøfÿddf!œÐ¢S¥äÔr?´hðF Å0[]¿>Åç¡ß㔢¹XÆŒ_Î+¾ ‡aBÖ<Ÿ#aHJ $Ò (o„‘Ö¡”‘’0 ” ¢(’RFB)-M] !•‚‰´ÒJÈ8X­5ôט’RK¥¤R…R†RFREREIÉ®q„-J¥aÛIÕ]cA €B‘ PK¥¥’¡P‘2¨PD¡”BF†¥•$ˆJ¨( •ÛÖ…ÊÖCÚHûH'œ2é*ƒåæqSÚB¹:xÙMp¶[uR«JÌ?c8çÆeÃ-¤ù/½½†¼¢åt6Íš¿ÜÈsJ^ÖRVÛ í@žÒc¶ÀZ{}¤è‡¦4$±Ÿú—3’¢Ô9jŽÞL S—•;mB²¼ò-Cˆ»–#ÄÊ oU„Xª-B\RóT’*¹O!Zš{”!$æ¹M!Y¯=•žxCÙûPO!ELáÉÚ×Úz)?"ÕH(¿JH)¤ˆ„E$ÌR~úäƒ ®¾uÝÃJ~’REBHÑShh=És7³aŶ¶!¨ÔÝÏU¸Èp+la=¼ž Ä6|šaSK“ГRÊOž¸ùÐo]ûpŒÌŸ5Ÿg¤Ä·Î­­§Û󸫋öYð§îoŠöÜíg$ç¼*«èkz䙇®Y!ê"‘Ó‹oz…aó¾'ô·„ðîÜwÕ5h§)1=5êªH¸ä§˜›oü'¥ÌnšóéqšÞ¢«FâÉ+!¥PB'ð?<Çî¾êur¡²p&Òè2ÂråFtÁ‘V¶ä;+‹’ʳ6‡Ä¨&M![-5°­¤Ñ" ˜ §$òrÉ=†:Wž4Éî’S5%{;lQIviI17Sä³\¯Èm¹J +kk#$Wf:w½)Gˆ!U#¦!vÙh‹S«?u„”ÄÿRqˆ7B i5³ÍRnC c„”Ù¶^T‡6$5o[!¹ÌêaI©„ˆ;!¤*’ {E©OŸ|`Ó‹JÅz½1»—2ŠÙ€bn†4{§R1Ô¼‡”˜šP—ž›Â.šÿldÔ DB¼¥f¹4RJKMNV}¡”þô)KÌ'~ëºGdÌ}V"ŠÞ2¯‹R,ÇCnD|æö˜Bfn„8GEi-•[ꦉŸ¿û1×êèË]ÿÕºPn[k=«Ea¤l]›QB.Ý5A˜’†»ML4fuFrR± ßÚ­dZÒVHa>C%,(åx¢æ:…;ïÐÍ(É"dVMAûPq|+q§’×L„+µ”òõˆBB¨ùJ"Ш¤–BFÓÐ& =0ÆxI@»Èæî ‹˜¤˜”qBRª”˜îñöqÒ å›œST ¥ÖR·|œ#G€Ð’¾QÙqÆ\Ç·‘óÔšdC2J©¶øìbP"o˜z® . ÎÝ–¹Û”ÔV>¶ÝšÕCñ •6‰ŒlBá ˆ–ñ”"Ä]ª³€iAH3Ç¿­’JæÆ:Aˆ[V½ðƲ!"¤Ü†@¦ådždR²g6ïgD¡"}‰KÅ…Yø”RÊ4EPçŸ| ñ3¾yÍÃBÈ(2c»ª<IrÏï*A¸)Î,W©'öÚKv5Y<˜7¯Ygôv=ì’ìÎ-wÔ„½Jk€™×Ÿ»3ö¢uYÖuK¹ÝœjT£‘HªØ¤2Š”2–¸H^*öª„AŠp”S¨UYŠ<€ˆ]U6wK Ò” ™+ɯ´¿‹V<Ö]ó²áL£‹"ËFW-jvœJIŠx]y¹„MWÞÜ3›J+bPS vÙ-{n±I"TÚ¶(‰ä†‹Á•6-R†©éG aXŸ)ñߘš˜¿¶1©X}‘üIök*n·J)êƒkµS-âsÝÇÅ­~]RæIMH[„”åI ¤¤îÌMœµEˆiɾµâ¾§!©hPsqŠ1·-RnCÌ›§ŽòPeç6¤Yµ5RjèP)PætÕ‰0´a')ã•ÕÄg̪Î_ºDH ñµ+=26²]/@_·ïòÛR¹T—â™Òm*tC5ÚÊG7eun'u‹p÷sÝÊ’l¯I—™Žˆ.ìC-[Ã.öén }æ´ƒÌå|óšßJ-ع׽öÜLe[ûéÛN7ßïuü5)_DÇZ‘Éý2›¸y Î^¬ù«Çn<ÙüÉ.‡^djî 冣¶ëª7Q$\çQjÃeÒÊøOB‰HFRDBA82:2§G#bo——- @ÄÎBY/*ÎãÛäÖ†¶/„P"Úý-ÝÐ×ãç"dnOhÆé¸QJ*íàS ©è”TÊPж© ežpk|MfÊt 4?†a(¥4í !Q¹¦Í<ÕVTÆ´IwÍnÊÎ !Ò5½J™Ór΃ àœ›{Ã9¯×ë±ÚŠ”J)» QÉL…a¨D"Öbñ<ÏØ#s]æÁ³c ¢(Š¢hbbÂMU¸Ë çÜíIéêê2Ûz[ÉbfÌÞæz½ne”S‹íc¥L—GÏób®eòXÎiEfŠÌ„æ^AÐ××gæÊã” ®V¼(lP”huFc½?£“Ä(ú3#æ–EQ¤„¤ß,s¥Z)Θé©nnM–É´ b{!Ä\E'±þM.BÌ9·%B¢(*AH*ÊX‚óµ!Ð!B´%€âz6Y„˜×§ŽpZÓ”#¤Ü†Ø·-BÊmˆ™«©#Ä]*ÊÒ¹ É"¤m"+œÌªŒŒOD† c²$B˜LœÚBñ©“Âphdô¼½Õã´§æQŠ)aJŒ ES³W¾%1-L35%µ™©!¥èƒf1®zxÐÂ.Ó~ØJlpÖxQÖ øô©ÿûÅ?«ú¬·ËgŒšdǓۘhåg™o/½Ñf{[.¼@‡Ö­ÌpkõÖOÞršùÕþ§Þ互Y T8™]¸w³Ô:NãI) »È¤5#iî{Ÿ¨ø´·»b’nÙMw¿mQ_EN2O%ò¬Îk­´–B„A°ÇÎÝövû¦©u!>ÇÙµñññzFaI¡„“ RŠH&ig 14:ú:D¡ìbæ^Ã~'\»ÏñW/<æ »õÉFòSLç¬î7ƒL1s)¢MÄkUtªœaeýäV¤ú_BnHK0RR~ß6ڗܦNîšÑTwL7(åºù¶’»E ùE³ö‰µ’µ%Qô\„Pç(B´v¨-BH¶gY !×od y¶*BЩӉw>Ëbÿö ‚r’Í•l™ 1yoR´Ø·EÈ£.[pIJEG_Þ!BòNB©¥±3Æfuc7Û<66†Q̉±:IÂpEEFãÌ#¬Xùb„<÷Æ9³ªEá7ë4¸¥‘­ómĺL L÷eSáfÿ¦¼‹¢TŠÊΤRŠh €Ù CB4h!U$Þ:§zÀîU)#W_(pˆkþ•”"ŠÎ_ºÿøø¸ÖúÐsož3P+*ÌÌ>%™h«3þö3îÈTÆ­uÜ^ÔyôGh¶аê®Çä¤ã®Ì6ÊtSÉ=ØË‡FFÆ‚FF‘½ñ‘T†¬)¦0ýÝÜãlîì®ðï<¯û E½ª9Ÿ­‰¼$'¢HI±×®=ÛõW)Á9³ª%™ÝKûü‘ѱxœVm*Фˆ¤Ág†Fcdh¸ _Ê/L6:+îúxÖÖd£nG(2·*Õ 2]Q³\Ôf3„Ö•Õ¨…ä_kZ=YMAj$ 07§ž%œf•iJú•Ú–¨ÙNÛ¢âì™Ý»¤äãÜÈJA1åB¥ž®4—(ј¤ö˜2BAéÎ’M(¼ñG¿;@H®*`Qïª×!n¾ì€w]SEF£Ë×Kõo?»‹Ø~vdTÙRyËvþv]£#ÃëGÇÆFŸCÃ#cÃgUÇûºéëàB¥v6·ZTiœ»‰´æ/«ˆ“5©†Áöav æEoEbÛ­-¨0iŒ•{±¶Q‰û¬¦0”[=‘Ûà=k²b¸,”ö¸óãn²f:÷äÍ%6³IÍZ¥-ˆ1¸É2l¶!Y^N !nT£!ÙV¦­’ÝÜç:OmâÈL!YŸ#UqÖ!BÒ,Ÿ­ƒû¤âÎv9BÊmˆ¡Ùt†2âFAÊÒÖ†@kÿæ­‡,¡Ê&û”RFƒâyÞŽÛu½e ò亱áuõñá×֮߸ipæM££›ÇG×ϪŒ¿u®WñXµÂVÞsv\ÿuä%I{€8Ãhé¡fítC¿ãããæÖBêõºÝc$ÉPF‹»¡”›íºo²M¶¢…=çÜv¤¶ÍCêõzµZm4ÆršÁ bµZ5K¸•ó6ä]wìû³}g¸°wn?ó©ŒÂ`ttLIQárv¾m¯Yû/œS«x• [qϧ̵/:üRw¶S<°(ŠLòÚ¾Á̹RÊóUñYOwu—ú´¦ù·¥ŒáÞiní݋縰gv/T¸acbb¢Ñ˜ð™œÝƒíÙ¿d¯í8ãÎ;ô2Š d§¹½»ïÀkdptxýØÈЦMƒ›6¯ß°qtd0߸]W}û^ÉPW}>í.T;ur 4­“&—ÄøLµŠVh~«µÒª}Á­1Nå*…Y¢k¼P"Qhv(¥RjÃèÔ®áhšC†´ÖÐ*”§‘€Ö ‰’t²š\Âì²äR†[L[l a²çϲ}-á1; Ãä6ÿ¢&Îi’ÂqtÔ‰º†V`°èÔkèR„h…SGH Y„4Ý…¶QX‚x“"$å‹l1B¤ŒJÒ²O !0-Iù[lCÌºÞ BÚÙ˜„¤Ë¬¶BÚ’š1n÷¡2»¿Öß ÃãÑØDøôs«`—O/ÑZ+ÅÑ÷X_7ï®q­õó÷žcÖûG,3ZG¹1û Øæ¹E¯mB³š™²Ô4fs .€­"QÉþÁî!}ÕþZ_7 !RF”R4Hâ{´¯»Ú]ã qå½ç.<âãE­\~Ž+UﺭnB¿YÚ¸æ¾æø·ŸqÌÿÐ?ûƒ³LÎ €h­±5a½+›€¸'¶ól^á®Oì~ôe0ÿØ+~wÙÑn¸‘¸S1ÐWÝŽ{}µñMC•J%Š"B#T†8ÃîÞ×í!R­5é¤(uVo¥§æÍé¯Ú~Ìõºï{”Ð |Õ¼Ú@£´s„˜sniŒN„ MãE¢}‚š ÚU«l?§kÍð¶u¡ìþUJ Š:פ4²@qqLp“BjnqédÞ”HA!R$VD8^ò{£ëÖ¿Jw›OrëØš0.²)Ù-²ñú)EWÏ=Uó¹Õ¹JÙ¤x*ª‘𥔯„XéžÞî8-“×ù™l ÍV¯Eú/Eùo[>¹õb/¶!àôÈœ B²l˜-CHj[_‚–Êó) $÷G‹æ‹í’ ÿ´ $uÓ_w„@¦${ËlH›² âþ$“²!Ù@ÝÖ@H»ìADÐRƒ0»eBõÈöo»øƒúªJ B æóJÅhº­®µòÞ³‹üB[8æö¹+Ú=fª#u|‡ ôuS²^©4ºa͸”©\™Œf:›@_í©UÙøDCkÍ=Ÿ3Z«xœS€fReŽç.:âXxزU Ÿ ²Ý«ìÀTNhê«î9{#/€½Ž½råg)¥”ñ¦iFÆ"ÅjBD€¸Ç¶UŽ¥”¾x÷ÙóºÞñ‰»ž¸öD7Pçú+&¿¹Ý@wwâŽ× !œr­T·Ï„DÑ|Ìt¸…`ŒÌ¨Í™Um4D=>W¾ïûÍûûºÇÆÆ¶!öœA ƒ(ž @Í'õ1]ƒ¬ûõòË/ •µ¿¿¿¿¿:\(Ð.³!7 5)9J©1ºÕ…zû·O‹K8ÿCOËyv?ü’i9Ï’“oœ–óìsüÕÓrž½><=ãYpØôÌÏ¢¯™žû~Ô¥Ó3ÏÇ^1=ó|ì•Ó4ÏMËyö›&Î?ì{Óô|MÏu™ueêÇÂ#§çù2kçôp,œDv'}‚‹Dÿ³&šVró&ô¥µ6KMÖ¡Y½¥Dj3lëE-<âÒÇo;ÝõTRÎn‘Ù *×óH±¤Ý…“¦jøS›1× v3ˆkoöôÔ**¥÷ÍtfG²rù9 [{¾ìùDç)+c7!–©ŽZ¹gn×zQ ¹ò™ÛNUJEÜr®XŠf]“?\{â¹äÖU·‘}'u«æjUÎ "#\A¥ÌAHùxZ@ŽX«òjOp]©T!bŠ1ç¬U“¢]­Tî6chhhhhè°Ã+äòåË·œ e]¨HIƒ$p*SrÀMbr€FÐ5iÑä0Â_ˆ±HݽgŽ™cæ˜9þ8Zl#*@…ìbÐÉ‘õÀÚVä&2Jn$ ÃÕœŽ%ûŸp]® }ª5r–Ó–ç;’Ô²•}O:;Öˆ¢”ˆ{·ÒJH%¤– ”¶/‚Òq=ŽÕ+, Ï8=†îS2ó+—Ÿ“ÚmIèY]ŒT¬%›‹|áþóÌî} -·Ukâ4[´·I!¤X†© †Özåmq˜=N¸&UÆS‘¶Ìsg™ÔÊîÆ_· B¬ ÕÖ€C9¤$RÕ& ¥‰®‡uêQî3¥óh¾ïûÔ“‘¿Â¥Š8çR*@¥aÆC¢D$¢(ôçŒÆý»#M€#g@¨E¬¾ïœµk×vuuqîù¾/CµaÓFBÈìÙ³‹bŒmÞ¸©¿¿_FAب÷öÏÚ¼ysO¥tpp°»§OÁ| ¥Q$ƒ ¨V«Œ±H Â"jCi¬ú•0 )屿jw-q ·Î­x2ª*†ÊW¯×»»»…õz½««kbb¢V«@Œ1CHœ5kVAÔëõBcžP2È´h¡2Û; ÃplxDJY«Õ<ϧÜ×/­~qöìÙÛÍž]¯×õžžžM›6QJ+œ#£ˆ888ØÓÓÃ=ºqÝÚ®®ªïûA´Ö~­ºqãÆþþ~ÎùÈÈH­V#”›qÆ@§Ä¤±A›rf7øv IDAT†ˆJ!$Œœó =ŸI)¡Mw www+І†¡ïûJ) b, ç\†Ñæá!Æý¾Yˆ:ŠEQ„>ãÄD7¥JçÈP¨ˆFp!3ùÿ ! 0’ Â0ì­DĘ'!D*(¯( J¢V`Ĩ|o||¼R©ôõôÔëu·Ëaû¸  -˜C'ñ°ÜXT*cÝ CÀ/êATþAY2\V\ ’ÒK›ê2G*ö–ª°±"ÛØÑœRéBÿÉ„dVÜw¶á•/8ì’ç—Ÿ›;W¥òº£¦¢kOÜzú⯀½O¼î¹ÛÏPRiŒ¥øRÕ¬¶Ö!uÇR«µ~úÆSö9åFXrækîú„ÕœÊÆä&‰ì|·[ĺõ2G›(”‘!Œ¦Z!¬’JN×FÓçº%zlÊFÉ—  ®¥ö˜#Âf¤}"ª¤wŽ]¤¦õ„aò—9‹ñ‡¨ÜÙÌ ¶Ýع¡ÎlM*ë0E$jUt¿³ÛDŠ„Ò4+¢)ì+UÜ¿Li+pìºó®^”+Á’îÿ@ù%J §5¤òhRIqf2ƒ„lm„Ø?lƒ¶¡¯ÖÜŸ»ŒMêxáþOºñ˜¸Î1afõÓ³K]ò¶tttüJyQ§‹«‰o{¸ê£ÙÚ%}YW——R~‹ÀòÀvIQ÷!Wå2·EOê´ÏÜk—ïùák̦Â-âsŸñ’¾ãVõÞ<¡O^w’yç®G_GƒL‘GÆyê!“rVrï×VBȶv¡r›?#âÞÇ\¹ïqWÀ¢c¯ÜãØ+R²EJ$)«‚~ö&™$±½¶ú7÷#:Lö»ûŒ\]¶‡û ºãqŸº8‘œ”E¤y³ ÌnR¡µª lº\Z÷ñvKFÝÒYwžãÊíø¯Òx¢”¦>ºÄ°6·5ο"„¸­+!Óìv!3™AÈ´#dá—Î?ô8èôÛÞ~ÆmR¸¤™A2†Žc–¡<Ù­¼ÖúÉ;âlÑ'^ïÖ änò]”ÆVw•BUk…m*„Q¤D#(Ð))Ê{RJ4(Wé °¤è$@hΓò¢²kk+m˔ѥ»£§… <}S¬AµßÉ7¸1ã#›<#¥”jŠº)Bëz~öZlËï‰3»µÌ掂e–ÞÔ!“rV²zñ[!ÓîBµI䥒ß6úôÎf*¹ ݤ,žDIb©[0,r$D#B&ì¦EM‰ ÄÕ˜’sÖÜ ØV8y3[—Qîº\¼Mƒ;Vå/W%/¥R~rû鹱˘]xÜ@´;oÖswu•RBŽ©i7¥”´Î´ë WŽ˜ ØŒêÎ d!3ÙšYqÏ'8£RÊñ‘ÑT}e!{jFaµZ•¡à¼"¥ŽÂëòÃ0DDƨ”ÒÒ€5çÜOqΕB¢Z\=D-•ò™ïŸ¹÷qWÀî‡^üÜaÄó}?ˆà¹?›G‚z‘%z«8°ih¯Ýúk*”‚R @Œ…44(mJÖAI–À)Ž'q®DQÔÓÓc0À3wœªµ¦Z™¯¨•]«Vêa0ѨÛ.1‘„ŬsÓNJ-Dh®Z˜†? %U°|jŠD)eD«€¢RÊfôö8|Ù‹?üT3‡¨p,ê&^÷D¤TcU¦•¯éÐï¥Zk©¤Ç¼¤bšh­|ÎQHÊø37.Ýû”›õô-§Ÿ+P ¡êg^‹Öm˜ˆ¢±®šß×ãwUqû¢µ0Á6D ‚À÷}s †††(!J©§®_ºïi7À¹õ…{>¡”Ôˆ°y8¸ï¡õ/¯^YÿòD |»Ì«nßÇüÅ[zX.Bl¹jBBÅ7Nl§X_=ô…¦R^}ÅÈl¯Ñ­4§Ì"ÄÿìÓA­RÑR"¥à"dãHø£ßmzucôÒkªpxëÜÊŽ³é1ïšçµö‰Êï}ï{³/þò—¿œª •Û’>hDƒBåꯠ !`RÈZ›¬ÍCebæFë$aÏÅ;KBcF¡Ë<í¾ïBLU¶îØrû¤"¶%ÆÜ@‚¹¢%VÏ=ƒ«i™ûþ¬T 8*| Û;h©´a8RjÀg­³]rù†6˜‰H[£¸³6Zמ¤~µÅ”#¢ÖÐviœAÈ BfòæEHËïH¤4\Î8òNV—¨0£wß¹¦ÒyÏc®xögÕõ誱¡q"•T’pÎ=NÆëj4ˆÖ¬ß0oÀÛo÷îZ…͈ØBFO ™‚„ä«™Ìf##WÚ#Þ-ˆ&ÂŒ;o'"£ ã­E®Ê<´Zʽ¿VóVÝî‡^ó?tÑóËÏ•Š G³$©Ò*¡”UQpÎ4C‘Ú`£gb¤Ñ_3³‰I~Y6@J?y͇÷;ãvØç¤ëŸ½óÌz ž\=¾qXSB@ΙTš « £ò™Õc]úàÅ=¾ï»<§Ô³ðò=çì|ä2ØýÈËVÞùÑCâ–Ÿm|jMH)E$Ȫ5ª¥”«×ŠU¯ˆŸ=úô~ók'¿N­VË"ÄYpH¾9ÚUû;ñ~†ˆ¾¥”"ŠúÂ0Z3¾Ó_ùÓ.}ëº|U”4„ÖÖzÃHtËO×?µ:ˆ·ˆÉ8׬—Ïÿ)øéVì³3?öàî·vâó—¿üeÊ‹êÄê(‘çb1Ù¿IûzÚIeâRnDh\˜—2 …)|gÃdÔŒŒ4EÑ„º,³\Æ\ùrRxwün²6Û6·M^QAf3ï u³a¸ù•éHjÞæ£m]®»^Úþ\Eê®uCn­å¤è3™AÈ BÞŒÉ_ Õ,“üÊ-k²,"¶"ÏÌýÃÇ“N·žrÓ/Þ4¢g÷gœsîqÆ™qheëÅOÙø§ õ¢Ú«TbW°>·Õ`Jv+Ë 4¼=+žM¢ÊÉ»1-)'O§\“ãùÆœ°??ëûß™úý÷›3Ïãàõ­Ÿ5\Ç¢ù4Yògn<%žÏ“oþå“£›GsÎ=/ùÂc„PJ(£lÓ(üìÑ¡WÖO¤ú1§´ ^¾?ÎèýÙYwåú×V¼ªkµZWrT«ÕJ¥Â¹ùïé5¹rõ¯ŸXß!B†ÃîMø¿o~OOWWW­««V«U+ß÷|Ïó|ßëé®aí­OnœÿÒÌ펕eå?ºjô+×¾²âU2Îg_‘ÿuˆGž+Öt}¦ý'èDÔ (8Ÿ}¶Kô¢1e¤FZOgeñRqx{NÓØÙmQî8Ü|DZ†®Ôüu(µRò‡nÅ,dúH¸Å¥Eý­l­ÝªèŒÐƒùsÏóìbf^1±ts~³½v;k¶²P !ÌΕ3Zj^w³*E$‰f¶3]>g2ƒ„¼ Rî¦Èø¹eY)¿¤CßzåÝŸ¨V«óæÍ»ðúG­çä{>÷8£,ÕvZýõ“ƒ¯¬O1³Ä²Ô.}Þݤ÷u ((ƒO½­¨…_ÑŒ!âªûÏÝqÞÜòÞ+îzžsVñ½Šçû¾çù眙KGBRB9÷6ý# ’ ¶è5¿}ýãÆ]ð=¯âW|ßçœSJg¶Ÿ·ò맆^ÝØpI])­õc7ž800°dÉ…^­VëIãšø¾ïy^L·¢Tjö›×<ôä†,q3…¡ g„/©uõÖjÕžî®ÞžîÞîîî®Z­Z­øžÇÍ™ÇywwßêÑ]W¯U%Uæxtåè²»7(è`œÀ¿{çÚrpÏ©sÿ©½ å2ÜÇÛø¤W÷j›ÑàD#ª^Y%îìãa ¡©'!‹ãrµÙ45Ú’ç?{™¹õ8)’來ƒÒDCÖŶév÷lf?meN J°àÈ >§6aÙ®mKuf2ƒ„¼yRäÞÙéJyxåF(mÒç^øDC~å¯eŒqÎ/½ã'`Œ1¢Œ !HlE<¥ôág†Æë¢Ã`§]¶íàÝ„i:|¨5:7Ýê%…ÝúGjrß™G†¸ÕûÙæî}”ŠÜsÅær/¾å ß÷+ÕÄÙa”šdP4Ý GĬPØÕ:I¡:%¥ã ù•Ïý•™ÏKn}ÊsîyFtŠÐ¤RúðsÃtÒô-]b„‡£w½ó@ß÷«ÕjwrØÐŽõKì³ãyÞ%w½²nS½È b Y½²¸«V­V+Ý]µžîîÞžîîîZWÓb‰ Ic½=ÝÏ®Ÿ=ÚN†¡ò™“Äu@ο„Ì d!oF„”ø»nÝb® ¤»F¦Ò²9kL«“úôKu¥É§dù½›g4 ?1JŒpF«,…Tø›'7déG)ÿɸ nI<´6ØÎõ€S©ÛT\³<“ÛyÒÖ|}”òÏñÆ(çü¢ÛžˆÓ†ŒJ‘Ä470tDDBqÿ•Á–æ¸v/G¡^nH‰Ÿ=-žÏ‹n~ÜdÍÖsŠ«3A*xè©ÐZ«ëº&w<8)j\“J¥R©T|ß7AØßeÌ-ŒED¡èwn[•- ³ÙììWº¿}ýïM4 \1ë•"â†añÚÆq×ØÓŽ©g_‰E°lŒÐfW­ÅHE¬ñ™5xnC*ƒl2 ðæ™M ç,;R»Ìñ•c³–!¥ÓˆÎ~vÍh*ÍmæÃPðø “ç¶v¡H¦#zQ˜2z*ˆ¨ uTCÍSØJîÌ­ˆqZ· ;Ugd·Ú)´ÊKX/ØZ•ªß)àt²dåj:±Ö¾dS¼Vt3&ŸJ‚˜Òö´ÌÙä<€HïnÍìqædvË•¢U¦ k6‹ßrß[c 3™AÈ BÞŒ)ÿ’ˆ•¸Pæ´BKØ/°NþüÅ×M÷ðü“0ï¹èÖ'@ZçÉê˜çNž\µI•lÉÕ(rùR¶“n¶mœË(giòÛ†”ÿdO>T“Eñ‚Ó4:à^÷;©L¯á¸â•i`Í{i]d¯Æ·õ…׿™¿¼à´ƒÌ{¾yíÃÒá½!&.jâDQB[¹12KÌ¿ÿ·›S…¢Y1ØlÞÜMoüá õ@¤nbýÄc´µOKüô ét†Q.˜5"V+•_?5„2ËÏ[þІ-§{ô÷÷/_¾«$ïÆÍG,<ê²Ø‹f´·¯º`×í>ø}OïzÝOW?±fx¤¡{û»÷Ý{§ãŽØÿˆ½k#ä»}Í}祲çQW<¿üœ"„@^¹‹‡=»zÍòs‹’•t“8¸àC¯ºï‹‘—^<ýoµäô¿ú×#v„ìÞ½4Ö°àˆek~x^9Bì2œ­ÙÙýðKzvØÿÑËN!ä?ξ檵á ÷›Bˆ Äõ6Žè€ÖzïÝqáËÞç"d÷£/ò†³±åK1ÃZDÍpAŽ]}ÝãßÿÍÚ—7‡Ý½ï~Ï^ûñv “¶5Í–õ„ôô¾ëÝ{~ñŒEoå“¶!JŒ_uínyðU3ž÷¼g¯ NÚ­·!Ùoö^z“½§½ýÝï:xÑßœ±h·J>BÊmˆ¯yèÆ_¾üÂú:¯Õ/~ë‰GíÌâ¾yæ³ævqÑûŸ¸õôV¿g6¤!3ËçÌ1sLýh¯N®”¢4‡(›êŽNí¨û“Öwš¿M6‹RÊKoüÂßí{áןÆ#ßg3 Ù¶£%̃5÷ž361^«ÕõÆèðÄ}w?tÖ~ìò÷YµÜ¬Â/!4ÝWá—>{Ó+‹öûò?»÷Ž5Ùž{îÕÛîü ¼ýÄ’ÉÉí ùìÎò}?h4^ùãº5/m¾ëž¹·åÿñînÔDk„–橹ùûâ³?ø8÷½±‘áJ¥RñþÌ+w\wßaÿ~|ç‰ïÚdbD›FÉxË’ ½ `K.ÆᆧW|ô«+Ïú»ã>²ï '¶Eˆën¦ŠÌß]zÙ+ž½“í¡Ã¯qÛæÛNÈ‹¯è"ÒD;!;î²ÃßýÓáWønĽ'eCVÜþ£Çv|Û/?³0ª5ÎÙaιçéÿËŸ¿wøæ“»¶!HÈö;Îù›¿?â’߉¸_îç–ÛÿýðØOï<`E ÐÝÛó®÷ìýî÷î3„d£h9SÑ™ )GHöx衇†††ÊÜßß_®€¡¡¡¶'™ÔÑögŽ™£Ô•³š¶N" 8¹óx !Œ$®F¬ïûAP¨öv‡RxÔãH”DkPš#ÓFs…€Ö¨PÒXüB=wÝSï;ó=A½qúisο~ãÒOo/Ak‚avW|¡Äx½>§:+“ýðª¡!‘çy&DAX÷8Q@@®ß´üÞ‡zwÚ‹¡ðˆªz5 ÆéÄÄcL+ (¥P!c ‘$¼ré›>ù½Ý4¡Êt"‚¸Å„!cJ¤V„’HŠ(ŠŒ¤ c,’y¾Ö dúœ€Ç(-£Ðc4 ÐÝ}ößîwùç‡SÑDkZ!¨Dü†R*•"H‚Hh „WüJÍNQ É)E­mûF¥¯øÑ„4B; dÍó9†RÎ$¯Ö5Ô÷#håSÞP’  A$@J5$!€H•RD'먄0‚¨€É¤i}ùÍëÏþΡ HK‹.­èI!²€"„pîMD2¨7j•*ú¨µÎ"JÂ8i"‚z,B€Qò‹›ü{×~ç/çw!D!¨‰©Jm¢¥ð}?…ÐH`Þ;þümߺú®¡EGÍb `|ãÊom˜÷û·uß @§24¸ïç"Xל«>ÒuÖ²5þ}¯Aä#Y‰\„\z×àG¿±[,_” äØóÿçç#K?à"„ê„XÁ D “µ!—Ý3xÖ… R9òŒ=¾ùÏ+Õ Û!$kC€pf†¨UBÊmÈ®þt]xâN•N²Å6$FªIÙr„äúO‡vXùš°|ùrØyçsûòË/wr’IåŸ8sÌ¢nùòå=ôÐôzQí+òRÒñ>IéܽZ‘›ÎËÜk}ù‘Êe§záD¸Ã5.°~þ1=­²1êlp~c®vOË«}ïÏ ÉC)¥ô³Þ[43´ÖŒÊÿÕÇÍ:±(ë…w+‚,‡ÃsuÖ¢`ô&Ã`HÚ¤"8]H²Ãµ½Ì× ³Ê]¿Ô†UL9±›-r«pm" ö9ö*÷$/.ÿ¤éáªtš!„˜½?•_êçSG,:úÒÎêöp ‘:GˆyƒYil¬ÅühIÄ\sß_ÿ®ÿ¯DET„l½œéEHóO¿ô×»žò­—ŽþòÐúgßýÇþúb©B)„ä=î§,8ì¯ö¾ùÚk^]ttWBÜæ6eò‹Qùý,…êÀ¢`ô†Î£,-Üs­ô†?m¸jÙOæ.>h²6ägcòK³¸ë’Rz½o 'ž™Bšó¦Ôú×6ßrã¯ûwÛÍ!å6äÿœ¿÷‡Ï»ùÇïÙíí ç.ØmàíûÌ©àÖBȤmH)B²ûøN\ŸC9ä(rh¦Ýjû‰3ÇÌ1)ènÓ(TQ#O$˜­—Nõ m­©n1ªZ#€Ú´ê·xèÁ„YõŸö‰þãùÆWö©¤bï¹¢y.erÕm4¾ïS‚CG®¹ò§_ºð¥_ý¯=cB¨ÖHÜn ˜í)aÔ1;tyf!kâSñvßhIl¹½)’¢ìø·JkPh :Ü&sæçïþ„Ôõ¸%çÃC® å6‹­v¦<ýƒ3}ßëêê²™8³Xõ‘æè@÷îh–²k­`Ÿ½ëc#VÞ}Ž¡Ã+—Œ™þíY„€COuÞh ÚTß4³ÿ¶m.ܶP°ë»æwßöàÅíþ©ƒªÅ±SBˆ¤Î&OÍo·_ò®Åß¼ùáñù‹aÝÿ~a»ÿY\ÓRÙ÷´´$#ñŸ)= ©¿pÁþ—‡ÿÚî¥"¥4"I#ôôLZÅš"sêõÜÕz¿ã¯1¯ô ô|ð>7|t÷)Ú‹÷ýY„äÞ ½Ohz¼ÒýÅ»›üf!å6d×CÞõ«öþñoþøÌšµÿóÀï?³Ž}ñŸ=eÏê4Û8½>9RŽ™cæ˜9¶® •íj^4Ý| S;“ËU*Úôüèâ?>³jåAN¹ØœÁ—àÂ~+´eÏi…lQUZÙÉœæœû™C¾{Ú÷Š•‹ VÙÔÒKïŠNè§–dàò—‹.$æ× ÛW›WøÝ»Ä—€I¤'Õÿ\éÜfìÆüeÅuRKrQ§‚ÜÒnwòÔ9;¬ ˆIDATÌ2á§tŠŽj¾ù@ýþ 8kŽo‡ñü½ŸëHuˆ(hàZ¢õgY;nàÁEHÊ_,CHFsÙüIÿ® núº<ó‹wOœý¡¿;dò)ðÉú55„d{Ù&Q–xíÄ¿ÿüÎg]±îŸáWïû܇#$P!ö´=;Îÿ·Ýñ¹ŸïvÙa•Ô ‹ Ö\„üE½s0úÈltÒ\áwïšBH‘»àþøägT«UÓ…jú®Lʆ| ›þ`0:s;Ï}=}Å«Í.AH® yê–“+•J}büOÜøo=øŸ÷ Þtj5!mmHeÖ¬£8Z rÍÿ=ê_~qÊ͇N¯ ± ÁÉÙvéäxï{ß;ÙÆaîñꫯî´ÓN[öýÌ1slÙ1EÐv~´ï‘çê讀FAFs¥HZ4"´l}d0ôŸ/áï~ð‰§n8ù×—ùø KŸ¹u)¾ôÈŠ Iv?7UQœª·‡wŒ $´Ö±»§Ê5gç={Ù²Õå®dÛ­[ª:,6dJ^öÕ's ±hÍ †˜¤5¨–=´í³áŠì¹j¼æ·Æ·È†£Z/™Bºâ •%!+/[´(À9Ç͹ì›Ïè¼I˜BŠç.i0õäF,Øž!…H*rb¿o"ÄaOÛëÙq—›þûý¸üþûñæ-(ÄëpqÊúOéÅRkÔ0oÉ{özäþñ‘Ùÿ¶¸æâ*…·#} !æã B޼à/_ºéÁg&¢¬hPÓ"„œyxÿÕ¿˜BÈ÷¿óøG/.š¢l32;ì©Û³Ž¸ò{ϧrßU«v|Ûî%ÉÚæ8‘¼e×y_ýÚ!+ïüõk¡,AH[bŽ·°8ª¯›fâ>˜“±!mÒÉR4•æÕW_}â‰'^}õÕ-ø~æ˜9¦èE½þ.T¶CS–õbMžcÈ.c©3¯ùÙƒ}û¼½G "R^û—ýü/ÿb$U~•ÙkÈ4–O"1rÃk.þöÛíw€RJ;Q™¶Aì…'ù¶?þúÌ‹òÕ ¡¡1Qô÷«¾ôO7C)/!·­•»‘¡ñß=¼úó{ÃÍ8ÿÊ“ç´Ä32M¼Ý?wüRA©”£»3Î-žO7ˆh]R ÄìU/<þп ž8ôË¿üñS‡êB)512þè#«²3¼Ï œ– îøS)rPòÒl&EH×vo½ê;xþºûÿáž mSÛ‘T˜4BZïuë…ã7¯^ú“+ßO1ÿSlܱ!îh©?ë'õ|ú{/!ÄD˜r²ðÃXü§ÇN¿è©g× `ÓÚMÿ·½ó‘ªºâø¹÷Í›+»>ÜX–ÑFÛQc©¶RÚX«±T[Ej"°âØ¿ªmýCCÿ`"«Úbv¡­?Ò"ˆ«iJ›ðQ# T*Ò6Õ¨ë® ³ófÞ{÷ö3s÷Î}oÞ¼]–uÁó Ù¼™Þ¼yóÝsÏ=÷ÜsžÛ¸ýÉ£¿½¹=¾Vd¸Þ„ñ!ónºöŠ#ïÞºqÿÁ#%/úô?ûÌŽ'þÝòèò)1 ijC2“:î?_<ôV!^!‘6déÛ¶ç“O¿¨R ûü…çûÚ/ºâ´+$™ iªÓ=uvvæóùÎÎNŒ-%?&€8#¼¨D¹P†ÉÓ[%“˜  v×õsÕvŠ ÙæÞã7>2ݰ ‹×ÌùŃûå‚ËŒ%ªº2q,`ê\xÃuµmNë‚ù³ÿ°¦ u¯`IÕª‚[™unyéOo¯]»ýðÑÏdæÍëüñ²¥º>…W+”‘š{ã ´›;†ó½ï\õøwg¦-ð„¶ÁhÂô„ôâÂ0ÛL‚w{nö}s‰ô¥ Õ-H%­ˆ@¯§ƒ'·³—À,‹qø•áé5ãZZ‰©ÆÓk×/ýÕ}[6ýõO E§õ—Ìxjýò)m¸¡=Ò ‚)Ô†B8ç U(@…èñ³°BXí Å8gœK~ ‚¬TX!¹ÉÓ^xþûwÝ×÷3oéo–ÏÔ¢Ý ^TU\xm]ÄC;ïŒ\XÔ«eŒÀ^…XšS¢{ŠØ³LWÈì«^Ù·ëEmÅPWˆæ²„ÙõO]×Ó»ÿþ_ýù£Ê$§mñây¯=s¹^ʸ¼FÉ‹PßÀnt6„óìOÿ¨·çŸÿò廞„œ3«wÕØnŒBÂ6 …,]=kýã‡Rß\¯° Ù´¢kóŽ}Ïmge÷5«×p)¥W8zÃo¼"¸ ½¡B"mÈ{ü‰!É3/ûçïs‘ ‰·!³/óH~.cŒ%!‚ÈÅîä6¤‘BFjCbÒô‹Û³gϘxQ*·Iřĩsº3¢šçBU*õ'‡!0¬"Åb3r8ç¥R ‹ª5xÎSœ§¤dR2nY6>Tã¾çy¸[çFjíɶmµÝûX !J¥R.—s]Wõ·Âÿ‹9ª®ëât ^¤Ói¼àr¹œN§Õ¯7øŒœY>žçU*ÇgðâÕ[¨?88ˆåìðõ˜Ñ‰ÆÝæÚhÛJ¥¸…a$ý0Æ2™Œúؼ 2™L:Æ¡3] …BKK zÙlÎ÷ÛNû~ ïü¬¬FÍÃûéº.çÙ)d|†•Û¤âL iì'&¾ÿIzäEΞõ¹šJZ ç6ɱ•gõáðxLÚxʇ_ O¶ªÃƒhVd­Ñ©çyŒ'XÁ”u{ŒYµ±óÙh7ž‚«óˆ àÕ8¼ÖKYFöÔà .ÞƒÏcæJµzí‹P[ÓÃyµÇëÐ)«•w—î=!rñ²žó:ÎûõÚ‹¥ôH!_M…L½tþ;›æ•]²!#UHÂAèTbQ*¶4ŠŸ1Áý'H^Ô¢5è©—PŸj¬(;­j%d„^ÕZ¯£&a†uÃé©çyhÎbVIÔ¬§w¸Ø”Ífq†m§SMl_ã8|¥=zïÔA@Á@HÌó ír׳šjWRÍ]Pep®YÍ®™B5ÉÖG#Œ.„ ùpÀ½o2àWSÁ8mˆñè8þ ù`Çêþþþ)ív±X!…BȆ$Wȸ Eº?4Òc‚˜Èþ$Ì…Ò­ŒQzÇ0sá<†„›½õw1 ºhV“{øÕ%)K§_RmÚÍ}؈ÏhÔ(¢¶ö¨!“BßO¤·¼Õlhuíƒ Îêë_7ZHÕóa GBµ—*üJK»uÆiýCa½iU21þzH!¤RÈÙ¡‚ N» Õùí Æ3µƒ©ctáóthÇÓë5Mû SbÏ<ã˾¹£¾€®ç™ºWcû½ŒR)„rF(ÄÀqœ¾¾¾%K–Ä¿l÷îÝ1MždDÄ¿#AŒ‰tÇØ…Êçó[·n¥ï† â¬$ŸÏë-Z´wïÞ¦MÄÇqçĉ~‹cÕØ1ïH Uç8ÎØönâB`AÄY̘0qvÃéAA EAA.AAÄÄ£. «AAñPŠ ‚ bĤàõ¾7guQAX‚ ‚ ˆæ|ôñ§Àþõ—UwlòèvAA$¤§›ýªIYƒ?Ù|IEND®B`‚quarry-0.2.0/help/C/figures/control-center.png0000644000175000017500000003371410530402565017730 0ustar bartbart‰PNG  IHDRÈ'c_›* IDATxÚíw\ÇûÇg÷öz?@zïHQÄ.6Œ=‰F,QcIìýªQ±Å’Ĩ‰-6ìݨ±Æ¨±kl`EEEÇõãnËïÅã¤yÀDæýâÅëvnwfvî³Ï”Ý}ˆì>@ ÖàæÉíŒVUt§N¡aá°Q 5$)ñ.­-$²ûàˆ–mm½a£@¬Âý/e¤¦`ßÀàä×y°E VÁÆÞ©XX¤ÖŠÑk5z­²J‡px"o•Ã5o++¶ö[a!µ"-F­×*½½«ÖϦ¤¤¸|A oPªªy[Y·µMÂ*}À˜F;XBÑ•ÄÂËIùÎö¼H–Ÿ#§p‹Iԭ熋‰rg[N‹ —3E±UÏ{–-µH§ôñ©òèÍÇÇ;%%…'Ôðð%¬š·•u[»B‹EQȺc9Ùjƒí”˜ª¸˜”Û?Šß¹¹ŒÈï§9Zs¸—ªø'éM¿¶’ØÖÎåÚ<Aªg 3ª}xƒVÍÛʺ­],,´Ì7ž¨ßrœQTT¤Vc».ä…xq^æ!JÎ;éeFHÑòê„"Z­ºÒÖðð%¬š·•u[»Â®ðâƒBei4£ÑXTTD„‘ N>§X¶!3OÇ *áØn›rµ\NΙ¯ž>K¼¡V Dß°Ž~Xîá–]Cˆ Xx¨W+{) 𼜜Ûw»›…òDL6·~ŠÆÎÅ1º±££DÆc£®P(¾ßuÓòS¶°­Jåpÿúß$I„µêj¾sâÕ3(ʉêôÞ¢+ì ¤Ì{iJƒÁ@’¤N§3 F£Ñˉ_„ro$—N÷q•fXf±nüu8ùÞU€&^Mò²Òþ>°Ñ¿I«]ú”=©Ôb‘$¢ŒJ®¡ ºf¬wŸ¶í±£»v͹øÈÀ’„·lÿ¿ÝZ\´þ×Ö™+Õ7UE¶mþE˜í“Ë/Útõu#’yûx"ÛŠ )ÏbQ$qãÌ!Š ÃÛuG ¸{ñäÍ¿ÿˆêÚ·TAh%]aÙ*…{0¯M¾w56~¼“;Ԭ퉫Ý|ƒ<ýÊXa¯Ÿ•–rzïú˜ÏG;¸zWÜë—wé‡4mïÄyqtÅ’]·9|¡@ŒÝ<ü[¡û/Ÿ´žÚøÜâéÓó·©}ƒf¬æ‹e|± °â›îæ)2¿æsºØR¥Ó(“=Úyò–'asù+ÆÅfï¼ôy»`_G1CýoõÎ%ãK%ž”ºKY×ü¾5ã‹e“Å‘øÿ0È«HýxÄâs|‘Œ'”˜*,ñ ý"Ì6çîËŽ±Ø\¾X¦Ó&ݹåÓ¤µUÇXåäÞ¦I7΀ŠhwçŸã7ÎþÑ¢sŸð6Ý,ií ÇXþ®Â~Q`×…l’Bpg‚¢¾mìÜ„l>§gKáþó9ÅéHQŸh'wG!šY®Å¨YòÓÄëžMìÝM)öÎîžMž&^wñò+s RêðâžôuÊé=ë‚›·;½g]·cݼ+(·œú´o*lÜr E9Žî~6Žî Ê{÷Á'N¾=›çŸþS –(ŠÊMOAQD(±1›“öÜñJl|eY ~>šø<Ã%8ú—¯[;³_NHHµqt£wû6Šø¿ËÓtl Eù"iÙDÛàO» í&,Xöc2Y[§fÏRähØžyÍÛµ³l_zˆÄ·F.>,"‰²gWn[Yf±ÀÛ1VéšµïŽêæ¹£é)3SŸEuîѾ{Ùv-·µ+ì éÕÊ1ØW¼åðý@»O‘Ÿ³ˆÉF‚ônïâ%Ü}깟»,ÈSâã.æ°˜–Ì 5J¹WP“R{Ú9¹¾xt¯TbE³Â¬´”S»Övþt¸›Oc7ïS»ÖÆÆ]ÖnUtù†q€ä:‘»›ÔÞ…ÍåÄàˆ¢Tò-Z¥‘öL –!nˆ¹°„A.þýPU !("åîIZÛtÌIÿÞÔ‡.>ï:ÏÉÞÍC¦ŽÀ<1ïÁÑ4ƒ¯³G/vö X&’ØÅzp)Šøa×uµÈ©‘«yÍ[ð€#™ ¡«¯³O(À¬›Y!‚ Í£{¤§‘Ñ=nžÿóê™ÃŠDvˆ«(‹ÆX ³ÈXÄ€BP„€8A ¢eØó¤^Žöv®Rk0&–šk/å½D-è ]¼G´9š°Ê+¨i#'לŒ´î4ŽhãâPö@´LWØ.ösπв¥¸z–5xåÖçÔÕü61ñ#C®îSõ¦Ppkêx²ó(›Íesx(S‚!(‚09o­@%Àßï>ƒ $¶Qf¶ìm»1ƒ‰1°wóÝDK½#C7Ø©_08Þ>LDªåw „2G‘Ô–¢æþu25f€ïà)íϯiЩø"™…ëÌ-Oî]/»[@“¨®ý¿,·­Jåpûâ©kgþhÓ¯yt@dÇO½zæ0ÆÀ"Úu{okWØž¾òÊPTÄd2¾”³.¿€"p¤{ˆ··Q^¨,*2h´:£z䤉EKgm»÷÷ôytçjÊû±4.^þÌKÎár}7µx ]Nº<ñâi¿Ø®±sGg­þ+5“ƒ‚ •¯¯M=úFØÈU(–žW:KX3co~®g²Y=ºû–h×T†¶"ÖȦ¶GTžCÇõ,é²`¾[Ù>Ô<‘ÍåÝ>öbȘàñý;{‹˜9‰« ê,µå Å¥Ô¿¾õÛ?ÌoÚ_¢Ü»÷nn‘ã‰eN6¯Ó³+oêFŽ.Ze@ÙhäèRÞbA990Œv±ý›µënJ‰êØÃ(ʨ(‹ºÂØ6^z½ŽÍd’ÛÆ 'H’È¥y¡F«Åq\­Ñju:VçîÈ{Q¾Å*G²®Þþ®Þþ¬Ú!5[ô+çHŸ·{ÓÎÄÆ~1Ñ–¹ØðX åÔŽ1«ÿDeŽö®Þ|‘ôÐæ³h×ÖuFðìŒô¿%´>ÊÔH{·\àôŒº|ó§…™Îì^#Ê´R^éï$"TOê:pfÙ%6W"’ڱ؜R'ÌŠïž;óõmqÏ6¡¾q³òPŠP«”KäTÞÔm»F´íZ¥¶*›CÙ›·ïnakWh± (‚L&c›; %Šp’ý"WÆæ°‚ÔTjMVfz»ì%båû e-VU/ ‹Ã‘ÚÙ>zðàÚ…³n´ éöûÄh÷í6þñZ,•5rbsy¸Q¾iëžsÞPň1Œ¹{È$•<ßÑÃW(±ÁˆÂ«7Ês3pxµ'J¾1wmfêSú³©ôr<¡`çÅüÅ1öFÝó)…þž"© Rf”Äd±$vŠü¬MÛ÷ô:ÆÄ0&IþMÛX·©­’ƒEc, (Š 'ŒÁÀIB"4r ½ÊµÃ0–N¯ÏÍyãÈÏñpr¹šgå›ÐhÍnBWÔF¡„ÍâÅ2R®}ymÚ‡ƒ~Ü8wÆì=$E"DRʈ¤U!E‘._ –6röÄX,¡Ä–/” n(_$Ñ©•‹-’ÙÙ9¹3Ù¡ÄÖt} %¶¦ÒERÛ²‰ŒÍ öæ7/bð%b{ž@Tn¹<>‹å^\aµ’À0Ñò§f5j+ë¶v…]!(޳ Š¢H’D ‚…1)’ p0r©§'oäz8ò£¼˜ÞnL&«üY!Š Õš« (‚ H ¯è[‡Ëâp¥vŽŽ¼¸ÑgÔ­Z!µstx+f¾HÂI*:\ –Ñë¨e1_P5¥”M ïÛ¶·˜iÐ*/Ù8ã@Ž›ŸÔΑÉbWT"ÆdVR¨UšÚ*9¼£¶Èîƒ [¨ÖÕÆ}.ƒN«S+ªñìW fqy5<Ü’Ez•"_£c,¶P,ã‹euð¼N£Ræåe¦ir‡këèfëèÆ¶¬ÂµÔÔVÉæÍ«”û7/Õî¤l¼}ÈÐr¸1}` ·‡kÃq±±w©ËûÊ‚ Êã ùB±Pb#Ëè{°©­ÞÚµþÌ;‡Ç¯Éè5<¼~Âã y|a©»¼©­ÛÚµk± 6¤6ÀÑ¡.„6› [RmŠŠŠÇÏéîß„ »B ‚@aA ° (, ‚Ô°j“”””””Û®Zë¢U[¼°cÇZ^µÛBU5(p¯FUý1ǃÿ?îÿ$IÆêɉì>xý/‹,kÇŽÐb5H’ùùù\.×ÂýíóX×VmÜÕÄbiµÚÚ¶ÃÙÙÙJ¥²’:ØÛÛshw1ëA{Õ+(( (ªîf…4µ­*À“'OV¬X¡T*Y¬rÞ[4B¡°S§Nqqq"‘ªÁŠª¢_T–Édùùùu-¬:°X)))¶¶¶ëׯæÂ¢/#¹\~åʕǯ]»vüøñôÈRsU™¬TM,Võïu`±|>ŸÏç—U€ —’$9gÎÇ¡,j®*óM™LVí¬j:+¬mPEߺŒ¢_ö'I’¢(’$hgà2™,>>žÉdBmY‚‚‚ ¬º±X&ãLC$Ac0ʳ²²;vÄ0,!!A¯×—R¿S“)d\~jë½:·pu°Ф.>¡=OØýϳÿ´°jb±êõË\XEÒú¢( EQ,&óúµëË–-ÓéôZF¡(lÔ¨‘——W‡̻΅žÇ‡î·}€W-ÖÔÍíqZÐsÁ¢ÍQÁÞB(ÈL½}õÜ®Eý¶OúO[¬vŒ (’$ ÚT™Û-©T:zô¨ß~]ýóOËçÍ›;bø0Œž>}JÏhLÄoÛqkÊgOuå÷’ýصy€T$rp6{“–¤åUI£(“›9õíG¢¹øªÒPzöº¶ï>Ƹ›»–Ä´h,æsP&ÇÖÍ?fÀØ„3ŪR¦ßß§­“­D ¶k7*Qe4]œÿ¬›ä.É|#b¶ÞÎKܵ¨}˜·T$ lÙ÷l–¶òzÖg‹UßÇXÅC+‚ I“ªŠ?$ÁÀB¡ÐÑÑÑÝÝÝÏÏWÀçF’|§ëc ›œãÔü±²9g_ž×uÁ½iëgÈ“¯îñx²¼ÓÌ+–¨Õ'œç»r´€"ŹM×ßRêÌõ/¹½Z‰X¥òY±ü֤߆Tr A=æG»áiF~aVò´¨×ý>ßoúêËCøºS÷òóRWdNèÒ¾ÿvåªc·óòÒ~êg÷kåõ„c¬Akˆ ˆâ$AR$I’IŠÂ0ŒÁ`ˆÅB¡P€  \Ó4z_Äů^z¡õבëŸXßµ©7cˆƒgoÛ÷xËtú«±±.[N¤Òþ\Š``ÑÕlÀËm;]bÇ”Íÿhn@£Ê|i¤ß;Ú·U €ÅÀ¸²~ÿÛ™{s™é« û6q“2X˜ pýËu{懹IèMÅó_ß[Oh±j2‚¡{BˆI‚ È’>‘ £Ñ@’Š¢b‘ˆ‰1+8KΊ#3çöša|Wu›3Õãü„B¡@ àóùb»(£¦¸ó œØ)yõ9ÀÑe÷?Yóɽŗ{7¥tšXQ5K5MñE˜uaT¯v.¤<O vÅuÏM{v’ßFc°œÅ%›„1ï½õ„«f]!EÒ¦ˆ2Q¼î@šô0ŒÁb±*ÊD8aEøÅ OÍ ÜÊ‘«T*µZ­Ñh´Z­F£¦¿ûÌ¢R—+µ¯–¤R?÷þÙðhJótM2ËG\6ó8)wg¶¶T㘷ÏwÑTÑS®=JUi´Zu>E•tÖeÝ+—¥’zB‹U}’$pœ èþÀqÇq‚ ÿŠ"‹G`IRd%ùôß°/eÖ§4%·ëG8 æN/¿]˜6Óœt3ÿ˜Ìô˜áÈwüÖ¹pæÑé·é6ÌrZlÊÄЕc6V2œÞ’¦Ú0¾—«­ˆUú檶@%õ„«Fc,ljwõ„ÓR#‰·3F’")PéÜã5Þ÷CÀ磘R&%Lþ{dìªÃW u¸Q§¼åØäO#MßvÿÆÛ7g'Åb'%|ý·ÿ7ÝË›O<§]Ñʱˉ*Eyö3{L;|búí’'rž^» ª-Py=¡Åª®°Š”‘ pÇ ' œ$ Zaô ž6fïuç;dg‡Ä)¦M»È·÷O¿ºvr€³ÌÆÅoô¢½!#·š¾uë3Œ("Æ}â pý䢈ø²[¹Ù" ÑŠ¿ÌjÏûmÆÐ /'¡Ä.°EÌ»nl=ó€ÞaÕ‰__ÿ:¼‘DÒ´ÇdûÑ;ªÚ•׳~Z,¬ž[,ÇF#Aà€¢òΤ¯øÞ=œ' Š$É2«t%ì·™¿™%¸EÛ=¬ü+§ÑP­v(ý™kÓ§òóEP^ÿñ û_Xþ¯ñ€S·˜6¯-·z•lVRÏZµXþé†j/ÑV>l×ét:Ž$ð’a-EQ B’$0¿ÛC‘æ£{z_>¿üUF X¬üzj⃠R¡ª œB¬ 탴&9@aAÊQUÍŸ †ÂjXþ¨µÞ`@ëþ Ž‹=“k¾@äìúÅÄ¥o D}ÖŸ_Bùk¡çñ¡{^Ôn‘º9½BçžQ|½hóƒ”4E~æ½sû¿‰ <µ¨_Ÿ,íD­Èû÷äFŸÌ„ŽŸíj 6ò«ºØC,'¿È¹ ‡3.̳$‡ÇGWƵ ¶ ýšÏÙTâcíܺÿE¹‹"÷ ¨™ëÏ››ÆS? ór¼}A÷ß­óZ¹‰…b÷ ¨kÏ5a5h{”á½9d]œ×vÌ¡ø%{_çÊO­çÞüŽNuø«OÝ™™p>¯0ï¶YwöýGª)ãqçmÜ|¦ÖhoþšÚýÿn}·ãb®<÷Âöï’–|öLVd÷Áw“_Ëår¹\®µ€ 6hk@qï .øÜE¼2)ëD­vª›hmJ®igEîu–  ýùì¿–kîiµÚ¤ßÛ¢L4æp²V«½1/ÜoÈÙ²¥ˆ0ôRca•ÔŠ4&ÏÏT“£Åí *|8–Y²É`Ú¾·žåœ¬V«U+_$]šÑË«QÄÒ÷æ0ÑU4þòë²¹tL¾žfÚL»>Ià0ÒTЮ´|ÓW㜅So¦›6ÓoN+©I¥h4F£V«•JeaaaAAA~~¾å?:­¢ODvü^ˆ@9+ŽÌ ì5c؃µL31›3ÕJ?‡qf.¤Ø¦Nì” ó£]ì]_|Ä Ü»)¥Ó‘J\ì!eçÅ¿wÖ…I£çž¸v¿@]0•,v±WQ=+™Ž±Až~o[3ÕBËyïj_žöqPIº4è[m^ «èÍ8×ôÕöl̓IÉž“øñãï iˆ‹½bK *x|ãxo—Œo×<°,¤ªíi~}RàÏ•ÄÝÀ‡\Çj8.öÇ=$zýù=÷˜a *Ïa˜£`ùƒr^lÿÔ–·â‰Ü´Yøägžmùƒ§øFüÉ…f{®hXÂjh.öØâvKÂŒßüùºò&nøjCÏö]~¬7©IKÇv¤Ó§þØkMøãw^á$þêÎñøkûü<µüêý6`]!'ÝsMÃhx.öz®xuÆŠÊsph¿àâê¸M“û8È$!1_éZ,¢Ó=úþ¾wFÈüAí¤Bi»AóCÿ·}o÷rKq‰YùçÜ&ßl-IÛÇÏž¾¯îY«EX…žƒ>Ì"‘EÕu„ÕºTUEŽùL@kVT•uÆ9V©Jm K­VXe7(¬â «¹ªjÏñä¿«-¬†ÅÃØ“P[VV ]…|Üã­j :^k 0™Ì:t¼ÖЀŽ× µt¼©GÀ—) PX(,…‚@aA V¦ÊëXpi´aRUo{Xm]!…‚@aA PX(,…©¯Tç Ò—/_>zô¶]!((ÈÓÓ³Ö…E«ªÿþ°ÅTU[Uî ¡ª8Ž÷ïß¿cA*¤&oºCaA*TUMÞI†Â‚TØ Öäp(,ˆõUjîÆˆ ˆäääK—.iµZNG»‘ ëØ±c­DÈÔI'XóLjj±²²2·ïج7äð¸PL Dd‘1÷à¡íwîÞ²Jý uL}ñèwõêåÌÌô!ú”@J¥TïÛ}âß›×CCšˆD"øSýçðöö~öìÙÖõ—ûöëf$ôJe@(ñòuIº{ïÑ£..næþþ †]¹.t ÛÍK—í;q)5W-°soûÙŒÃXŒººN‰sûÖl;p2)9U©ÅEvNÁ­ûÑ»¥gýœ¦Heˆí\[vé7wîX&ã?ªÎš ëáƒû_ÄǤ¥¿**2 `LeH$"[Îú +UJmVvŠ (A‚‚øAÇ Ê`¼Ó^$.ŸØ=6+rÔÏ{¾ p‘¦?Ù·öÿºÇÞ¿pú)£Ö§©_öe× ü˜é3WDxX 0;=ñߡÞ»åùºü1^¾|  cvêƒmK&öåpeËu-º¦?›J­"B.W**¹\U(Wææ$êÙ56bÀ ˜)Ó†M>tÚô/§|ûeÏÞþøãˆÑh ý<›2y²nØ]oüðMˆ»“Á´sùfÉÁiî·¿\—lºš¯l[×®™¯oD»Ë÷Þ3¯Cò‰µŸwkãïãÚ¬ÃÄvéÞÆgóôô¼shÕ€Øö>Þþ›ö5÷±¦œÉγ„áGÃO®™ÝÔ_Äc£[æìÝ{誽ŪRg&ÎÞ«IŸ·oãØøißfâééymÛâ¸vÍü|ZÆ Ø›Tððð/}:Fùûøµí1âbŽî½5,„Át𠟺jKö•å–äðìôïñ=:ùú„·ê¶t׿¦tºÅ|¼}šµ‹[¼íйi<·nVÇaÞ^^tʽ½Ë{´‹ðõñmÖ.nQÂë(«ªÑ¿öïßO™áà}áÒÞ¥?OˆײUhTËàQÁ-Z·nÖºm“ÖmC[· kÝ&¬UëШ–!Á!ÞÞÞÞÓ§Oß»wovv–)“ÉÍ‚6gj¨wÑdnj6…þìááØlÐ_I¯ ¸áuÒ_ƒšÍ»I•scY“N_ŸOz¥ÇqEæãåÃ[Ç-¸a:*´ãèÓ·ži ¸¦ -aV÷æý¨2Lm´µLéæ„w|üßdÇuGõÅ!Sþ‘Ÿ}?]ŽÔg× òöo5pÁƒôBz3¼ë¯ï­¡9書Oø{sȾ¶,0¬÷á«O´<ÿUÒÊi}éô×'¦„vòî+nH½wêóð€i'ÒLE Zþ"¿ø”3/Ì3µmjâ™F£±¨¨H¯×Ó3ýýû÷W5úWM…åíãqúìΣzÿ¼báé3OžÙSáßé=ÇŽï8rlû‰S{'L}æÌIS&M|¼ä8Yª¡ \njY% L_ýyIëà½Y%²0júõ0u2_WòSé_yû‘²&ü‡IDAT4-û‹{—SzEÆŸÀަüÿ),*ÎÜéááqIQ²i*«’–/,Ï~™øã˜öÍzn|o‹Z/HÊ/›ÛìÈ ÅÍZìᢠÈÙ¦‚N”4Ëü¨Ææm›ÿh©U„ewF£!3CÞ¹£‹›·¨$æ1EG¢ÞNb ‚2)C‘A©’g夿äæT©”Q¾%Q¾$>£u¹í˜Ø“­UµUA„·n2NÉÔíNà ´Ìn™ÆÑô G—suÎôeçþ},×À»1èÚŠ‹cp2˜€Ö¢’MSY•×°Üñ;€Éó;tcÈ{sØ›­ý'HR6«#ùúKþ%ébÿ¯õùíXHov‘”4Ë\Ýó¶õý €µ~ð%/PuhݲUX¡*'ŒeWD(Š"ÇIC‘Q«Ó½xö†ÃÚÚÚ™öŒ–pçê¾txgAUŸ{ˆ-éøÎO_ÞAÓ’½9ÕŸ=u–påꇛ•NëÉô3/é7Z3dÙŸ?·µ— ”ÞÓ»$B¢…1è,¬áÛÁ{Ñ›§·–OøfþÖ'ûÆ…Xƒ…1èJ «ýt5¼“©×ù|±F›£Õ© cQ‘¡¨È ×u:ƒ^oÔj‹4½Z­S«4J¥º _ùðAŠTbëêâjÊd䟳•Êùà¬M¾ÃF˜6×?W˜>>ßÀµ+>Б·ü|FMNaÌWA¿»³’Ý“¡ùqx7'™€Mæîªæ_Õ" ¶K`ëå×=^3&ËHTžÃçö¼5åeÓ{Úp6<+‰,§x¶žcÓ«ÜúÙqÍÛVñì÷z!,#ŽÛÚØ4öÈ+ÈT«tJ…F©Ð*E¡J©P+*¹\Y¯ÈÏ+ÌËSÈó•éi9r¹>8$ÜÑÑÉ”IÀØ-M^.ÿtÖÚ©ù8ç§>ømfÿ_GlãoÚgÛàñßO'H"ýþßãã·öYüUq¹jô¥©ƒ6žüW¡'p½êñ¿gæ}Õ½J§à7rsýÆ®#ç¹ùP®ÑS¡-̽sáÓ]¥œyûoè "ïÅ郪û¯z5d‰¢¾kŒÏúëMå9Œü1~ÇQGo>- yú£_g/OŒ™×mëàqgï§$‘vÿì¸Á ±ÿ7¦üê-îcjÛ´ûgÇÙZ/Ö±H‚d±X<>––‘‡ãIŠ"HŠ"IŠ 'pn4â8Žã8‘ü8•Ï•E4mÊç JÔÉV:±é‡¥“>ï’š§Úº·éþÙ‰#̱~¸è›Þ£ßŠý>›²ýÑŽtºMø¸3¿Û-X5wÕägZ„Ø´í#WVé†ðû½ŽoY¹eá„i)é"±smÞfåÞ ô w.3arðì\‘½wÏ¿…Cª”µkØuQïC7€Ø…•äШåŒ?­›;wø´çY|¿AãçÓé®±?mÈ]¸øëÞcÞ(ÄÎ~}Çÿ>»»K¹¥8F/Ø>eÉœ±=Gg*%Î~½¾Þpuþàš «ÊaåŽ?nþi³æM—-Ÿûìùƒìœ7¸‘ I’¤E‘I‘$EŽF#Žã”^gP(Œýú ìÕ«·P(BQKí¥§§'=þ€ÔÁ½BSX9ú3‡Ã9pà@\\Ü{µfX¹… ü°h……qšX,VLL×èèho®ªJž§†zj ·t""šoذÇqKžeÀ0L( …Bƒa¾òþâÅ‹J. R µm±ê…°d2™H$²ð¹0E ƒUõRRR °êŒz¯ÁÀ( ÐZ©R/¿[[0^!¤VúÄÅ+„‘å ¶¬,,zU 6ýÇ?¹«nðÀ*tàÀþýûÃx… „Õº°è5'ú}~HC Žœ‚ÐÚªFI|a…‚@aA PXÿÕ™&%%%%%Á¶k „†††††Öº°hUÁ` :`Uµ…VCXPU Çããã«ÑAÁ1¤Bjòœ¤BU 8+„XŠ¢ RˆõUeáÛ1PX*¨Ê*Ž×SañÞˆœ½C¿˜¸ôøü2ø©­?ôêÜÂÕÁN(’ºø„öšþ¼9S­ôsWž{»u_6ïÙ»Ö‘ÍZuìè`QhŒN’âˉÁrt—lƼ÷Zö×1÷„f: ZÇÚ¬ “FÏ=qí~º¼ëÐÚÕ€]a¥ƒwªàñã½]2¾]ó€N'(p+G®R©ÔjµF£ÑjµšþªçÊów.oáνujkï0A?\²ÈhWºùÞB͉“rwfkËž…ió»èªè)×¥ª4Z­:Ÿ¢ÈÚ¨–%ƒwŽ{Hôúó{îÿ80Ã@F8 æN¯h÷¦GOžµvÛá¤ä#G—[o)MÑ—¬VèòŽTµ•jbÊÄЕc6V2œÞ’¦Ú0¾—«­ˆUúæZª–¥°Åí–„¿ùó5`RÂä¿GÆ®:|¥P‡uÊûWŽMþ4’Þ-¢Ï¸ƒî*tF¢Hyëô1¶¤5>+ÌvÐŒM¯ u$®{zóÄÈ®c«ZJ }gl>ñpœvUDÿ)Ç.'¨tEhäÙ7Îì1íð‰ wê¶K:œÈyzilì‚ZªVè¹zàÕ+v‘3nïŸ~uíäg™‹ßèE{CFn-žXŒ ?¸x´¯£ÌÖµñ¬Ýù{.n(ž-þy$2cw+_G‘Ì¥÷¸_O9TÕÒ+)ô]û*Zñ׃Yíy¿Íäå$”ضˆùa×­gŠûñU'~}ýëðFIÓ“íG逸j|T³Bè@棡Í ­®*>Ÿ_nºF£?|m«Ê*ù`V©ŠÕ…¥V«ëFÁrØêƒã5«Ú M´S¹Ù³¿»}÷aVVî×cFmÞ´133ÓÜM…R©Ü¶mÛåË—9’‘‘a­–ÿhƒ4‘$¹iÓ¦;wÊd²æ‘-Ò3²Eb)@»wóüùó[´hÑ­[·‹/&''CMXEUÖÊ ­‡ç¶mÛ¶œì C‘¾ÿþgΜéÚµk‘^74þ‹»wïšL4EQçÎsww?|ø°‹‹K£F¬[û¾ qkT‘ÇJÈOX$IJ$Æ òùyÙ—/ 8ù9áaAçþ>›““CQTaaá_|1þüO>ùD§Ó 8ÐÁÁÁ”CIH:¡ØÕ·Éi+²Uö!6zÂo³Ï<‚.O?ªÁ{XXØ;w._½ÁÄP&ó›Ã‰lÞ\Æcüùÿ¦Û§_ÿ7ntëÖmÿþý{öìáñx"‘H$™ç@ƒ Û§·VÿoXûöO|Q¥:\Wþ °…úøx,Š¢ƒ òò xù:ëñÓ÷&<|”Ë—v‰éîîæ´páBFsóæÍ)S¦ØØØ4jÔH"‘°X¬²Y! –K`«E»¼9;ËdÌNý4.ÌËQð¶+7JÇ#(Š6{•ìfy†ôž7v.ŽiÑØF$Ú¹tülÒ}UÉÚãã£+ãZÛŠ…Î~Íçl* èUÕzPX‚ ›Ívwwïܹó¬Y³fΜ9eÊ”ÆÁ!?,YJhzFv“&MŽ?&“ɤR)ŸÏg2™‚X˜ÿ¸ó¶n>Sk4 â(mŕކÁ©<˜›%Òô^ž4nåÁ´x7±gï¾Cg®Íûe; À–_—®Y»vì˜1>ŒŠŠòòtµ³³]0ÿÿ†#ÊÞË…iÖgÒQÚü¹ïi„Êw«F†å^JU*·çÊów‡ž=õÏÍ[§¶.›üU³IwÎl ÇX±mÛ¶cçn 1Õ#Þ¼c6‹Ó®]»:\»~/”téÞ±C›];·¸vj×g=»4oÞ\*•òx<.—Û¢E &“¹üÇ{öìi0ÍïÆW2À*û•[ô°=ÑÃÞ»§…»UiOó” >SO÷™Zö¨Šr Œ±+fD}[MXÖºi4)4FJ¯×{ûùݼv5ñÒ±6Í‚cbbìììx<ƒÁ…Â&Mš|úég[·n¥(jìØ±¦ ”{ƒÞœùO ËŠwÅ]]]A·ÿSAƒ_½|–xéXˆ¯kŸ>}\\\„B¡)†a"‘(:::22’¢(s1A Õ‡Ÿ²ÞÅ+ < ÷ï {Î݉¡Ht«ðØØXooo‘HÄd2Í ¢µE/4 ( CZ‹3^!‹ÅŠŽŽvtt|óæ AÞÞÞööö"‘ˆÅb•U0‚ tÏh­æ€X«1ëc¼B.—^W¤n´ãBje¼ãB*Æ+„Ô0^!¤V€ñ !õøŠ= …‚@ ° PX(,ÄÊÀx…‹€ñ !°+„@aA PX(,…‚@aA ãBÞŒW©`¼Bˆõñ !ÖÆ+„ÔŠªjò¦{ƒ{éÇñgÏžY²§§§'‡Ãi˜ªú˜ãÖYYYÝ»woÜ8H§ÓéõzµZc4J¥J¡P˜{¸téRDDDÃTUÍ=5,aÑ#†ˆˆ¦+Wþ’——›——÷&##=-­°°ðîÝÄ[·nC7'ÖòvÖ°„µxñâ>}ú`S*•bƒÏH$™MFFÆóç/Ìã¦XCå#S•µ²jXƒ÷¿ÿþ{ذaæ)‚ˆD"ooo777sÏ*VlbS¤§ÅÇ/¬t3 ê!˜QŸM+‡Ž­Âb±\\œù>ÆÂ˜l&“ÍDÐÒ‹(z½rú°¦¾®¡ÄÕ·é°é+ÓŠ¨°†Û6 íäKª•ü$ü/Yië/è=ü+;;;“}Bc2Ø‚€ ùŽÅ"ùÃZ´xÓzò¦SK»Kå©~šuçÁ¿[l°÷\œ•¸‡Âúãl#Ý2¤·þÎåâ¾//#”T)SoXÛ}È—b±H¡PèõzÆÄXl&Ê@Æ¢wüÔû¦÷üäß¾¢7í½Ã§¯9/éëßç燧‡€w£…™ìB Í•Éh}ôjkƒwŠ"•r<-…6KtZsi¨„•+†Mš¬P(NŸ>Ãb±0&ƒÅa1(@FožÇªuO&\X*ã/VO˜Ýz5˜nQTZ[ Çz}üÂÂqòùKÅë³J¥#,¶-…ÍŸ÷}—nÝPuvvf$b,6“1ÐwÇX'åºåö¥ãðì¿Ðˆ),Š:®T½³@…pþ‘JçŽgckÕâÎ;L6F2Ø Œ úÖË÷{2'¡#Ö†:+4âx¶RYý§ €[$ûùÍ]ù‹§—'†a´?U Ø,&›ÃbÓ¢qRî®ìÒ/´Ù;Ù’h¨¡*¬|•jýíÛ‡ ÿ^p€ôàÑsf‡„4¦G]ôŠ¢ ÊâáMŒÿ&hÕ„Ý¥rÞ5nµG߉ôg)MÑ—¬>èòŽ”Ó; Ñ`„õñw…«Ö®5}^´hQêË—ò Àñ󿆆†èõEïŽÆŠb,Œ½Ó6žüG«ÈÆÆ)~š2´±»¤0õá–Ÿ¦üpÝáêÎæô³ÂlÍØ´ïûÁ.ðüÎùïÇŒ-[“BÖï·ÓGE¸ PX¿(™Í­]»öï—/Ûyz¶nÝZ¯×ÑÂ"B¥R)JL&Æb3Ùlòn s“n¼vsͼ¹#º5MÉ(0Ï.îtÒ¶@^q~õç‘ä“ZùN/,b¸DÄO9txTÇR5ùíÇQýû7›–£")꣟6¬[:¶¶¶÷îEQ†at¼–‚‚‚ĤÄüëÒi&Ÿ!µ•%®€‹•Yöd°]Æ/Ù|ûiZ¡ZS˜uÞMw))·Äà±Da«öŸOÏ-T+óÝ<3+>Ê$Ó¿ø¥I/³ÔMCXt¨wñ k•„„„‚‚’$´Zí«W¯î%%¦¼zþoÒMŒÍ°s“±¸,&c` (ƒQÉ}~¦0òÏ}cB;Úîù _. ¤PkÂú¯„t … …¢°°ð¯ógîÞ¿“ü20H;&›‰11zíŠÈ—š–űý¼Ü7åêÌG¯°îÑ£GK—,Wi”(†20ƒ"(‚ ˆùYägÉÍÏ‹ŽŠX.jµú#ÓÖǯ°†Y‡ÿaÉžþþþ¦&V*•µú3||Úªñ k·ïǰ&MšÔåµÛ0µãBje¼ãB*Æ+„Ô0^!¤V€ñ !õøŠ= …‚@ ° PX(, …‚@ ° õžwîÁ@‹©ßëÄÉÓî®Î°- V!5í Dv ›bEnžÜþÿ–K)›sÚ¼þIEND®B`‚quarry-0.2.0/src/0000755000175000017500000000000010530402570012261 5ustar bartbartquarry-0.2.0/src/Makefile.in0000644000175000017500000004313610425150133014333 0ustar bartbart# Makefile.in generated by automake 1.7.9 from Makefile.am. # @configure_input@ # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 # Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # Process this file with Automake to produce `Makefile.in'. srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = .. am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : host_triplet = @host@ ACLOCAL = @ACLOCAL@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BUILD_SGF_UTILS_FALSE = @BUILD_SGF_UTILS_FALSE@ BUILD_SGF_UTILS_TRUE = @BUILD_SGF_UTILS_TRUE@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DO_SCROLLKEEPER_UPDATE_FALSE = @DO_SCROLLKEEPER_UPDATE_FALSE@ DO_SCROLLKEEPER_UPDATE_TRUE = @DO_SCROLLKEEPER_UPDATE_TRUE@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ GMSGFMT = @GMSGFMT@ HAVE_SCROLLKEEPER_FALSE = @HAVE_SCROLLKEEPER_FALSE@ HAVE_SCROLLKEEPER_TRUE = @HAVE_SCROLLKEEPER_TRUE@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ LDFLAGS = @LDFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ MAKEINFO = @MAKEINFO@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGMERGE = @MSGMERGE@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSUB = @POSUB@ QUARRY_GTHREAD_CFLAGS = @QUARRY_GTHREAD_CFLAGS@ QUARRY_GTHREAD_LIBS = @QUARRY_GTHREAD_LIBS@ QUARRY_GTK_CFLAGS = @QUARRY_GTK_CFLAGS@ QUARRY_GTK_DEPRECATED_FLAGS = @QUARRY_GTK_DEPRECATED_FLAGS@ QUARRY_GTK_LIBS = @QUARRY_GTK_LIBS@ QUARRY_WARNINGS = @QUARRY_WARNINGS@ QUARRY_WARNINGS_GTK = @QUARRY_WARNINGS_GTK@ RANLIB = @RANLIB@ REGISTER_MIME_TYPES_FALSE = @REGISTER_MIME_TYPES_FALSE@ REGISTER_MIME_TYPES_TRUE = @REGISTER_MIME_TYPES_TRUE@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ ac_ct_CC = @ac_ct_CC@ ac_ct_RANLIB = @ac_ct_RANLIB@ ac_ct_STRIP = @ac_ct_STRIP@ ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ datadir = @datadir@ exec_prefix = @exec_prefix@ have_scrollkeeper = @have_scrollkeeper@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localstatedir = @localstatedir@ mandir = @mandir@ oldincludedir = @oldincludedir@ prefix = @prefix@ program_transform_name = @program_transform_name@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ SUBDIRS = \ utils \ board \ sgf \ gtp \ gui-utils \ gui-gtk AM_CPPFLAGS = \ -D LOCALE_DIR=\"$(datadir)/locale\" \ \ $(QUARRY_WARNINGS) \ \ -I $(top_srcdir)/src/gui-gtk \ -I $(top_srcdir)/src/gui-utils \ -I $(top_srcdir)/src/board \ -I $(top_builddir)/src/board \ -I $(top_srcdir)/src/utils bin_PROGRAMS = quarry quarry_SOURCES = \ quarry.c \ \ gettext.h \ quarry.h \ quarry-main.h quarry_LDADD = \ $(top_builddir)/src/gui-gtk/libguigtk.a \ $(top_builddir)/src/gui-utils/libguiutils.a \ $(top_builddir)/src/gtp/libgtp.a \ $(top_builddir)/src/sgf/libsgf.a \ $(top_builddir)/src/board/libboard.a \ $(top_builddir)/src/utils/libutils.a \ \ $(QUARRY_GTK_LIBS) \ $(QUARRY_GTHREAD_LIBS) DISTCLEANFILES = *~ subdir = src ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 mkinstalldirs = $(SHELL) $(top_srcdir)/build/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = bin_PROGRAMS = quarry$(EXEEXT) PROGRAMS = $(bin_PROGRAMS) am_quarry_OBJECTS = quarry.$(OBJEXT) quarry_OBJECTS = $(am_quarry_OBJECTS) quarry_DEPENDENCIES = $(top_builddir)/src/gui-gtk/libguigtk.a \ $(top_builddir)/src/gui-utils/libguiutils.a \ $(top_builddir)/src/gtp/libgtp.a \ $(top_builddir)/src/sgf/libsgf.a \ $(top_builddir)/src/board/libboard.a \ $(top_builddir)/src/utils/libutils.a quarry_LDFLAGS = DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/build/depcomp am__depfiles_maybe = depfiles @AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/quarry.Po COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ DIST_SOURCES = $(quarry_SOURCES) RECURSIVE_TARGETS = info-recursive dvi-recursive pdf-recursive \ ps-recursive install-info-recursive uninstall-info-recursive \ all-recursive install-data-recursive install-exec-recursive \ installdirs-recursive install-recursive uninstall-recursive \ check-recursive installcheck-recursive DIST_COMMON = $(srcdir)/Makefile.in ChangeLog Makefile.am DIST_SUBDIRS = $(SUBDIRS) SOURCES = $(quarry_SOURCES) all: all-recursive .SUFFIXES: .SUFFIXES: .c .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4) cd $(top_srcdir) && \ $(AUTOMAKE) --foreign src/Makefile Makefile: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) $(mkinstalldirs) $(DESTDIR)$(bindir) @list='$(bin_PROGRAMS)'; for p in $$list; do \ p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ if test -f $$p \ ; then \ f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ echo " $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) $$p $(DESTDIR)$(bindir)/$$f"; \ $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) $$p $(DESTDIR)$(bindir)/$$f || exit 1; \ else :; fi; \ done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; for p in $$list; do \ f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ echo " rm -f $(DESTDIR)$(bindir)/$$f"; \ rm -f $(DESTDIR)$(bindir)/$$f; \ done clean-binPROGRAMS: -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) quarry$(EXEEXT): $(quarry_OBJECTS) $(quarry_DEPENDENCIES) @rm -f quarry$(EXEEXT) $(LINK) $(quarry_LDFLAGS) $(quarry_OBJECTS) $(quarry_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) core *.core distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/quarry.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ @am__fastdepCC_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ @am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ @am__fastdepCC_TRUE@ fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `test -f '$<' || echo '$(srcdir)/'`$< .c.obj: @am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ @am__fastdepCC_TRUE@ -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi`; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ @am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ @am__fastdepCC_TRUE@ fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi` uninstall-info-am: # This directory's subdirectories are mostly independent; you can cd # into them and run `make' without going through this Makefile. # To change the values of `make' variables: instead of editing Makefiles, # (1) if the variable is set in `config.status', edit `config.status' # (which will cause the Makefiles to be regenerated when you run `make'); # (2) otherwise, pass the desired values on the `make' command line. $(RECURSIVE_TARGETS): @set fnord $$MAKEFLAGS; amf=$$2; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ list='$(SUBDIRS)'; for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" mostlyclean-recursive clean-recursive distclean-recursive \ maintainer-clean-recursive: @set fnord $$MAKEFLAGS; amf=$$2; \ dot_seen=no; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ rev=''; for subdir in $$list; do \ if test "$$subdir" = "."; then :; else \ rev="$$subdir $$rev"; \ fi; \ done; \ rev="$$rev ."; \ target=`echo $@ | sed s/-recursive//`; \ for subdir in $$rev; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ done && test -z "$$fail" tags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ done ctags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ done ETAGS = etags ETAGSFLAGS = CTAGS = ctags CTAGSFLAGS = tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ if (etags --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ else \ include_option=--include; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test -f $$subdir/TAGS && \ tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(ETAGS_ARGS)$$tags$$unique" \ || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique ctags: CTAGS CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = .. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ case $$file in \ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ esac; \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ dir="/$$dir"; \ $(mkinstalldirs) "$(distdir)$$dir"; \ else \ dir=''; \ fi; \ if test -d $$d/$$file; then \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test -d $(distdir)/$$subdir \ || mkdir $(distdir)/$$subdir \ || exit 1; \ (cd $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" \ distdir=../$(distdir)/$$subdir \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile $(PROGRAMS) installdirs: installdirs-recursive installdirs-am: $(mkinstalldirs) $(DESTDIR)$(bindir) install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -rm -f $(CONFIG_CLEAN_FILES) -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-binPROGRAMS clean-generic mostlyclean-am distclean: distclean-recursive -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-recursive dvi-am: info: info-recursive info-am: install-data-am: install-exec-am: install-binPROGRAMS install-info: install-info-recursive install-man: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-compile mostlyclean-generic pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-info-am uninstall-info: uninstall-info-recursive .PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am check check-am clean \ clean-binPROGRAMS clean-generic clean-recursive ctags \ ctags-recursive distclean distclean-compile distclean-generic \ distclean-recursive distclean-tags distdir dvi dvi-am \ dvi-recursive info info-am info-recursive install install-am \ install-binPROGRAMS install-data install-data-am \ install-data-recursive install-exec install-exec-am \ install-exec-recursive install-info install-info-am \ install-info-recursive install-man install-recursive \ install-strip installcheck installcheck-am installdirs \ installdirs-am installdirs-recursive maintainer-clean \ maintainer-clean-generic maintainer-clean-recursive mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-recursive \ pdf pdf-am pdf-recursive ps ps-am ps-recursive tags \ tags-recursive uninstall uninstall-am uninstall-binPROGRAMS \ uninstall-info-am uninstall-info-recursive uninstall-recursive # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: quarry-0.2.0/src/ChangeLog0000644000175000017500000054563010530113006014041 0ustar bartbart2006-11-19 Paul Pogonyshev * (Quarry version 0.2.0.) * gui-gtk/gtk-sgf-tree-view.c (gtk_sgf_tree_view_center_on_current_node): Bug-fix: store adjustment values before calling center_on_current_node() for passing to update_view_port_and_maybe_move_or_resize_window(). 2006-11-07 Paul Pogonyshev * gui-gtk/quarry-save-confirmation-dialog.c (update_secondary_text): Make two version of a string passed through ngettext() contain the same number of conversion specifiers (bug #7585, Bjørn Ingmar Berg.) 2006-11-01 Paul Pogonyshev * gui-gtk/gtk-utils.c (gtk_utils_show_and_forget_dialog): New function: add "Help" button with accelerator on "F1". * gui-gtk/gtk-game-info-dialog.c (gtk_game_info_dialog_init): Use it. * gui-gtk/gtk-new-game-record-dialog.c (gtk_new_game_record_dialog_init): Likewise. * gui-gtk/gtk-preferences.c (gtk_preferences_dialog_present): Likewise. * gui-gtk/gtk-progress-dialog.c (gtk_progress_dialog_set_help_link_id): Likewise. * gui-gtk/gtk-resume-game-dialog.c (gtk_resume_game_dialog_present): Likewise. * gui-gtk/quarry-assistant.c (quarry_assistant_set_page_help_link_id) (quarry_assistant_set_page_help_link_id_callback): Likewise. * gui-gtk/quarry-find-dialog.c (quarry_find_dialog_init): Likewise. 2006-10-31 Paul Pogonyshev * gui-utils/configuration.c (write_string): Bug-fix: properly handle non-ASCII characters in `string' (spotted by Bjørn Ingmar Berg.) 2006-10-29 Paul Pogonyshev * gui-gtk/gtk-control-center.c (gtk_control_center_present): Add standard actions to "F1" and "Ctrl+W" accelerators. * (Quarry version 0.1.20.) * gui-gtk/gtk-goban-window.c (text_buffer_mark_set): Mark removal of node name row as user action so it is included in undo history. 2006-10-28 Paul Pogonyshev * gui-gtk/gtk-go-to-named-node-dialog.c (gtk_go_to_named_node_dialog_init): Remove separator from the dialog. * gui-gtk/quarry-find-dialog.c (quarry_find_dialog_init): Add "Help" button. * gui-gtk/gtk-goban-window.c (find_dialog_response): Process clicks on it. * gui-gtk/gtk-resume-game-dialog.c (gtk_resume_game_dialog_present): Add "Help" button. (gtk_resume_game_dialog_response): Process clicks on it. * gui-gtk/gtk-goban-window.c (do_save_collection): Show error dialog on writing error. * gui-utils/configuration.c (configuration_write_to_file): Print error to `stderr' if unable to write for some reason. * sgf/sgf-writer.c (sgf_write_file): Change return type to `const char*' and return error, if any. * utils/buffered-writer.c (buffered_writer_init): Change return type to `const char*' and return result of strerror() on error in opening file. Initialize new field `error_string' to NULL. (buffered_writer_dispose): Free `error_string'. (flush_buffer): Set `error_string' on error. * gui-utils/configuration-internals.h: Remove file, use `configuration.h' directly. * sgf/sgf-tree.c (sgf_game_tree_new, sgf_game_tree_set_game): Adapt to memory_pool_init() change. * utils/memory-pool.c: Hopefully a fix for #6432. (memory_pool_init): Add `index_field_offset' argument and store it in the structure. (memory_pool_alloc, memory_pool_free, memory_pool_traverse) (memory_pool_traverse_data): Use `index_field_offset'. (memory_chunk_new): Add `index_field_offset' argument. * utils/utils.h (STRUCTURE_FIELD_OFFSET): Move here from `gui-utils/configuration-internals.h'. 2006-10-15 Paul Pogonyshev * gui-gtk/gtk-goban-window.c (initialize_gtp_player): Add code to handle failed initialization gracefully and inform user. 2006-10-14 Paul Pogonyshev * gui-gtk/gtk-game-info-dialog.c (undo_or_redo_availability_changed): Swap undo histories to determine can undo/can redo state on the valid history (bug #7419.) 2006-10-12 Paul Pogonyshev * gui-gtk/gui-back-end.c (initialize_main_loop): Set default icon as some/most window managers don't use application's icon (suggested by Michel Salim). 2006-10-08 Paul Pogonyshev * gtp/gtp-client.c (gtp_client_set_free_handicap): Bug-fix: use `buffer.string', not just `buffer' where we need string (fixes a bug on 64-bit machines, maybe #6432.) (gtp_client_play_move): Likewise. * gui-gtk/gtk-goban-window.c (update_comment_and_node_name_if_needed): Remove old FIXME. * gui-gtk/gtk-new-game-dialog.c (gtk_new_game_dialog_init): Likewise. * gui-gtk/quarry-find-dialog.c (quarry_find_dialog_init): Likewise. * gui-gtk/gtk-help.c (gtk_help_display): Show error dialog in case `mozilla' doesn't start. * gui-gtk/gtk-game-info-dialog.c (gtk_game_info_dialog_init): Call new function update_title(). (update_title): New function. (set_field_text): Call update_title() if game name changes. (update_property): Likewise. 2006-08-22 Paul Pogonyshev * gui-gtk/gtk-control-center.c (gtk_control_center_present): Add accelerators consistent with goban windows to most buttons. 2006-08-15 Paul Pogonyshev * sgf/sgf-utils.c (find_board_state_data): Fix typo bug. 2006-08-06 Paul Pogonyshev * gui-gtk/gtk-freezable-spin-button.c (gtk_freezable_spin_button_output): Unfreeze if adjustment's value changes for some reason (fixes mouse blocking in freezed state.) 2006-07-29 Paul Pogonyshev * gui-gtk/gtk-sgf-tree-view.c (SHOULD_TRACK_CURRENT_NODE): Make it work when `current_tree' is NULL (bug #6475.) (track_current_node): Likewise. (center_on_current_node): Likewise. (update_view_port): Likewise. (update_view_port_and_maybe_move_or_resize_window): Likewise. 2006-07-18 Paul Pogonyshev * gui-gtk/quarry-find-dialog.c (quarry_find_dialog_set_search_history): Mark some variables as unused for old versions of GTK+. * gui-gtk/gtk-utils.c (g_signal_accumulator_true_handled): Likewise. * gui-gtk/gtk-game-info-dialog.c (game_info_spin_button_focus_out_event): Fix typo error. 2006-07-17 Paul Pogonyshev * gui-gtk/gtk-file-dialog.c (gtk_file_dialog_get_filename): Avoid warnings for missed return on non-GCC compilers. (gtk_file_dialog_set_filename): Likewise. * gui-gtk/gtk-game-info-dialog.c (get_field): Likewise. (get_page_index): Likewise. (get_property_type): Likewise. (get_field_text): Likewise. (game_info_spin_button_focus_out_event): Likewise. * gui-gtk/gtk-games.c (gtk_games_create_board_size_adjustment): Likewise. * gui-gtk/gtk-goban.c (get_or_create_label_feedback_pixbuf): Likewise. * gui-gtk/gtk-goban-window.c (free_handicap_mode_goban_clicked): Likewise. (update_set_player_to_move_commands): Likewise. * gui-gtk/quarry-find-dialog.c (quarry_find_text): Likewise. * gui-gtk/gtk-goban-window.c (receive_copied_sgf): Initialize some variables to avoid compiler warnings. * gui-gtk/quarry-text-buffer.c: Include `gtk-utils.h' to get definition of g_signal_accumulator_true_handled() on old GTK+ versions. (quarry_text_buffer_insert_text): Initialize a variable to avoid compiler warning. 2006-07-16 Paul Pogonyshev * (Quarry version 0.1.19.) 2006-07-15 Paul Pogonyshev * utils/buffered-writer.c (update_column): Fix for the case of missing memrchr(). 2006-07-14 Paul Pogonyshev * (Quarry version 0.1.18.) * gui-gtk/gtk-new-game-dialog.c (begin_game): Create SGF collection and a temporary board before anything else to satisfy some assertions. * gui-gtk/gtk-goban-window.c (receive_copied_sgf): Add a comment for the translators in an obscure place (requested by Jérémie Knuesel.) 2006-07-13 Paul Pogonyshev * gui-gtk/gtk-named-vbox.c (gtk_named_vbox_size_request): Fix for the case of invisible label (reported by Jérémie Knuesel.) * gui-gtk/gtk-sgf-tree-view.c (map_modified): Call update_view_port_and_maybe_move_or_resize_window() even if we are not tracking the current node since the map size might have changed. Reported by Jérémie Knuesel. * gui-gtk/gtk-goban-window.c (text_buffer_receive_undo_entry): Only keep using `undo_entry_data' if there's an undo history; otherwise it is deleted (reported by Jérémie Knuesel.) (update_comment_and_node_name_if_needed): Likewise. 2006-07-12 Paul Pogonyshev * gui-gtk/gtk-game-info-dialog.c (gtk_game_info_dialog_class_init): Add bindings for undo and redo actions. Create `undo-history-action' signal. (gtk_game_info_dialog_init): Add "Help" button. (gtk_game_info_dialog_response): Handle help response. (gtk_game_info_dialog_undo_history_action): New function, break out of gtk_game_info_dialog_response(). * gui-gtk/quarry-marshal.glist: New marshaller `VOID:BOOLEAN'. * gui-gtk/gtk-help.c (gtk_help_display): Don't assert that `link_id' is not NULL, it is not necessary true. 2006-07-11 Paul Pogonyshev * gui-gtk/gtk-new-game-record-dialog.c (gtk_new_game_record_dialog_init): Add "Help" button. (gtk_new_game_record_dialog_response): Handle help response. * gui-gtk/gtk-game-info-dialog.c (gtk_game_info_dialog_class_init): Hook up new function gtk_game_info_dialog_finalize(). (gtk_game_info_dialog_init): Add "Undo" and "Redo" buttons. Change some accelerators to make way for them. Connect enable_simple_undo() function. Use GtkTextView, not QuarryTextView, since the latter manages its own undo history. Initialize new fields `sgf_undo_history', `simple_undo_field', `simple_redo_field' and `simple_redo_value'. (create_and_pack_game_info_entry): Add `dialog' argument. Connect enable_simple_undo() function. (gtk_game_info_dialog_response): Handle undo and redo responses. (gtk_game_info_dialog_finalize): New function. (gtk_game_info_dialog_set_node): Use new set_field_text() function. (get_field, get_page_index, get_property_type, get_field_text) (set_field_text, do_set_field_text): New functions. (game_info_spin_button_focus_out_event): Use renamed update_property() function also for property deletion. (enable_simple_undo, undo_or_redo_availability_changed): New functions. (update_property): Rename from update_property_if_changed(). Use SGF undo history and related functions. (property_has_changed): New function. * sgf/sgf-undo.c (sgf_undo_history_delete_redo_entries): New function, break out of sgf_utils_apply_undo_history_entry(). (sgf_utils_undo): Fix typo and make function not undo everything at once. * gui-gtk/gtk-utils.c (gtk_utils_set_text_buffer_text): Fix for the case of empty text. * sgf/sgf.h: Fix `SgfCustomOperationEntryFunction' definition. 2006-07-09 Paul Pogonyshev * gui-gtk/gtk-goban-window.c (update_children_for_new_node): Always set comment and node name if the buffer is not modified. (set_comment_and_node_name): Set buffer unmodified. (update_comment_and_node_name_if_needed): Hide last undo history entry. * sgf/sgf-undo.c (sgf_undo_history_hide_last_applied_entry): New function. (sgf_utils_undo): Don't stop after hidden entries. (sgf_utils_redo): Likewise. (sgf_utils_apply_undo_history_entry): Initialize new `is_hidden' field. * gui-gtk/gtk-goban-window.c (gtk_goban_window_init): Add menu items for standard clipboard operations. Change some accelerators to make way for the new menu items. (update_commands_sensitivity): Update sensitivity of the new commands. (cut_operation, copy_operation, paste_operation, get_copied_sgf) (delete_copied_sgf, receive_copied_sgf): New functions. * sgf/sgf-utils.c (sgf_utils_create_subtree_sgf) (sgf_utils_paste_sgf): New functions. * sgf/sgf.h (SGF_MIME_TYPE): New macro. * sgf/sgf-tree.c (sgf_node_duplicate_recursively): Fix: use sgf_node_duplicate_recursively() for recursion. 2006-07-08 Paul Pogonyshev * sgf/sgf-writer.c (SGF_WRITER_BUFFER_SIZE): New macro. (sgf_write_in_memory): New function. (write_collection): New function, break out of sgf_write_file(). (write_node_sequence): Constify `node' argument. (do_write_go_move): Likewise. (do_write_reversi_move): Likewise. (do_write_amazons_move): Likewise. (sgf_write_none): Constify `value' argument. (sgf_write_number): Likewise. (sgf_write_real): Likewise. (sgf_write_double): Likewise. (sgf_write_color): Likewise. (sgf_write_simple_text): Likewise. (sgf_write_fake_simple_text): Likewise. (sgf_write_text): Likewise. (sgf_write_list_of_point): Likewise. (sgf_write_list_of_vector): Likewise. (sgf_write_list_of_label): Likewise. (sgf_write_figure_description): Likewise. (sgf_write_unknown): Likewise. * utils/buffered-writer.c (buffered_writer_init): Initialize new fields `first_chunk' and `buffer_size'. Open file in binary mode. (buffered_writer_init_memory, buffered_writer_add_character): New functions. (flush_buffer): Add special code for memory buffered writers. * gui-gtk/gtk-goban-window.c (do_export_diagram): Use `GDK_SELECTION_CLIPBOARD' and `GDK_SELECTION_PRIMARY' constants. (show_about_dialog): Use only ASCII characters in strings translated by gettext. 2006-07-07 Paul Pogonyshev * gui-gtk/gtk-goban-window.c (show_find_dialog): Use new QuarryFindDialog. Set new `close_automatically' field. Set dialog's search history. (find_dialog_response): Add `find_dialog' argument. (do_find_text): Use new quarry_find_text() function. Rebuild search history after successful searches. * gui-gtk/quarry-find-dialog.c: New file, broken out of `gui-gtk/gtk-goban-window.c'. * gui-gtk/quarry-find-dialog.h: New file. * utils/string-list.c (string_list_clamp_size): New function. 2006-07-06 Paul Pogonyshev * gui-gtk/gtk-file-dialog.c: Revert proper punctuation changes: they are not supported by gettext with GNU libc < 2.3.3, quite recent. * gui-gtk/gtk-goban-window.c: Likewise. * gui-gtk/gtk-new-game-record-dialog.c: Likewise. * gui-gtk/gtk-parser-interface.c: Likewise. * gui-gtk/gtk-preferences.c: Likewise. * gui-gtk/gtk-resume-game-dialog.c: Likewise. * gui-gtk/quarry-save-confirmation-dialog.c: Likewise. * gui-gtk/quarry-stock.c: Likewise. * sgf/sgf-parser.c (parse_buffer): Initialize new `file_error' field. Return `SGF_ERROR_READING_FILE' if the field becomes set. (refresh_buffer): Cancel parsing on file errors instead of dying in assertion failure. (expand_buffer): Likewise. * gui-utils/time-control.c (time_control_save_settings_in_sgf_node): Use sgf_utils_set_text_property() so that results are stored in undo history. Add `side-effect' argument. (time_control_save_state_in_sgf_node): Add `side-effect' argument. * sgf/sgf-utils.c (sgf_utils_apply_setup_changes): Add `side-effect' argument. (sgf_utils_apply_markup_changes): Likewise. (sgf_utils_set_none_property): Likewise. (sgf_utils_set_number_property): Likewise. (sgf_utils_set_real_property): Likewise. (sgf_utils_set_text_property): Likewise. (sgf_utils_set_list_of_point_property): Likewise. (sgf_utils_set_list_of_label_property): Likewise. (sgf_utils_append_text_property): Likewise. (sgf_utils_set_score_result): Likewise. (sgf_utils_set_time_left): Likewise. (sgf_utils_delete_property): Likewise. (do_set_pointer_property): Likewise. * sgf/sgf-undo.c (sgf_change_node_inlined_color_undo_history_entry_new): Add `side-effect' argument (sgf_new_property_undo_history_entry_new): Likewise. (sgf_delete_property_undo_history_entry_new): Likewise. (sgf_change_property_undo_history_entry_new): Likewise. (sgf_change_real_property_undo_history_entry_new): Likewise. (sgf_operation_change_node_move_color_do_change): Do not set `tree->node_to_switch_to' if `side-effect' field is set. (sgf_operation_add_property): Likewise. (sgf_operation_delete_property): Likewise. (sgf_operation_change_property_do_change): Likewise. (sgf_operation_change_real_property_do_change): Likewise. * gui-gtk/gtk-goban-window.c (gtk_goban_window_init): Add "File/Export..." submenu. (export_ascii_diagram, export_senseis_library_diagram) (do_export_diagram): New functions. (update_commands_sensitivity): Make "Export.../Sensei's Library Diagram" item sensitive only for Go trees. * sgf/sgf-utils.c (sgf_utils_export_position_as_ascii) (sgf_utils_export_position_as_senseis_library_diagram) (add_horizontal_coordinates, add_horizontal_line): New functions. 2006-07-05 Paul Pogonyshev * gui-gtk/gtk-file-dialog.c: Use proper punctuation. * gui-gtk/gtk-goban-window.c: Likewise. * gui-gtk/gtk-new-game-record-dialog.c: Likewise. * gui-gtk/gtk-parser-interface.c: Likewise. * gui-gtk/gtk-preferences.c: Likewise. * gui-gtk/gtk-resume-game-dialog.c: Likewise. * gui-gtk/gtk-sgf-tree-view.c: Likewise. * gui-gtk/quarry-save-confirmation-dialog.c: Likewise. * gui-gtk/quarry-stock.c: Likewise. 2006-07-03 Paul Pogonyshev * gui-gtk/gtk-goban-window.c (gtk_goban_window_init): Create QuarryTextBuffer to receive undo entries. Bind `end-user-action' and `receive-undo-entry' signals. (do_save_collection): New function, partly broken out common part of gtk_goban_window_save() and save_file_as_response(). (handle_go_scoring_results): Wrap everything in SGF action. Use sgf_utils_*() function, which honor undo histories. Use fetch_comment_and_node_name() and set_comment_and_node_name() around comment change. (set_current_tree): Call new function update_comment_and_node_name_if_needed() instead of fetch_comment_and_node_name(). (do_resign_game): Use sgf_utils_*() function, which honor undo histories. (update_children_for_new_node): Add `text_handled' argument. Call update_children_for_new_node() instead of fetch_comment_and_node_name(). Save buffer state after inserting new node's comment and node name, if asked. (set_comment_and_node_name): New function, broken out of update_children_for_new_node(). (insert_node_name): Wrap all operations in one user action so that undo entry is correct. (text_buffer_insert_text): Don't do anything if buffer is undoing or redoing. (text_buffer_after_insert_text): Likewise. (text_buffer_mark_set): Likewise. (text_buffer_end_user_action): New function, set `node_name_inserted' here only. (text_buffer_receive_undo_entry): New function. (text_buffer_undo, text_buffer_redo, text_buffer_set_state_undo) (text_buffer_set_state_redo): New functions. (update_comment_and_node_name_if_needed): New function, partly broken out of fetch_comment_and_node_name(). (move_has_been_played): Use sgf_utils_*() function, which honor undo histories. (player_is_out_of_time): Likewise. * gui-gtk/quarry-text-buffer.c (quarry_text_buffer_combine_undo_entries): Fix for the case when `previous_undo_entry' becomes empty. (quarry_text_buffer_get_state, quarry_text_buffer_set_state): New functions. * sgf/sgf-utils.c (sgf_utils_append_text_property): Rename from sgf_node_append_text_property() and modify to honor undo histories. (sgf_utils_set_score_result): Likewise, rename from sgf_node_add_score_result(). (sgf_utils_apply_custom_undo_entry): New function. * sgf/sgf-undo.c (sgf_undo_history_is_last_applied_entry_single) (sgf_undo_history_check_last_applied_custom_entry_type) (sgf_undo_history_get_last_applied_custom_entry_data): New functions. (sgf_custom_undo_history_entry_new) (sgf_operation_custom_undo, sgf_operation_custom_redo) (sgf_operation_custom_free_data): New functions. * sgf/sgf-undo-operations.list: Add `SGF_OPERATION_CUSTOM'. 2006-06-15 Paul Pogonyshev * gui-gtk/quarry-text-buffer.c (quarry_text_buffer_init): Initialize new fields `is_undoing_or_redoing' and `block_all_modifications'. Connect new function quarry_text_buffer_modification_guard() to `delete-range', `insert-text', `apply-tag' and `remove-tag' signals. (quarry_text_buffer_delete_range): Don't touch state index fields when `is_undoing_or_redoing' is true. Remove all tags first, so that appropriate undo operations are recorded. Reset `block_all_modifications'. (quarry_text_buffer_insert_text): Likewise for state indices and `block_all_modifications'. Ensure that inherited tags are recorded as buffer modifications. (quarry_text_buffer_apply_tag): Implement. (quarry_text_buffer_remove_tag): Implement. (quarry_text_buffer_modification_guard) (quarry_text_buffer_is_undoing_or_redoing): New functions. (quarry_text_buffer_undo): Use new undo_or_redo () function. (quarry_text_buffer_redo): Likewise. (undo_or_redo): New function, code of quarry_text_buffer_undo() and quarry_text_buffer_redo() conditioned on `undo' parameter. Don't save `last_assigned_state_index' (not modified now). Set `is_undoing_or_redoing' to TRUE while in this function. (quarry_text_buffer_combine_undo_entries): Combine entries with tag operations too (but don't count them when deciding whether to combine at all.) (get_text_operation, adjust_operation_offsets): New functions. (add_operation): Pass `undo_entry' instead of `buffer' for consistency. (delete_operation): New function. (insert_text): Remove all tags from the newly inserted text to prevent tag inheriting from accidentally spoiling undo/redo consistency. (apply_tag, remove_tag): New functions. 2006-06-02 Paul Pogonyshev * gui-gtk/quarry-assistant.c: Rename from `gtk-assistant.c' to make way for actual GtkAssistant of GTK+ 2.10 and up. Rename functions etc. as appropriate. (Suggested by David Gómez.) * gui-gtk/quarry-assistant.h: Rename from `gtk-assistant.h'. 2006-03-09 Paul Pogonyshev * (Quarry version 0.1.17.) 2006-02-24 Paul Pogonyshev * gui-gtk/gtk-preferences.c (gtk_preferences_dialog_present): Rearrange some code to avoid compiler warnings. * gui-gtk/gtk-goban-window.c (initialize_gtp_player): Call gtp_client_clear_board() since `boardsize' command is not guaranteed to do that. * gtp/gtp-client.c (gtp_client_clear_board): New function. * gui-gtk/gtk-gtp-client-interface.c (log_gtp_stream_error): Fix typo. 2006-02-22 Paul Pogonyshev * gui-gtk/gtk-sgf-tree-view.c (VIEW_PORT_NODE): New macro, break out of gtk_sgf_tree_view_button_release_event(). (gtk_sgf_tree_view_class_init): Hook up new gtk_sgf_tree_view_motion_notify_event(). (gtk_sgf_tree_view_init): Reset new `last_tooltips_node' field. (gtk_sgf_tree_view_realize): Add all pointer movement-related flags to the event mask. (gtk_sgf_tree_view_button_release_event): Call new synthesize_enter_notify_event(). (gtk_sgf_tree_view_motion_notify_event): New function. (gtk_sgf_tree_view_finalize): Unset view's tooltip, if any. (gtk_sgf_tree_view_get_tooltips_enabled) (gtk_sgf_tree_view_set_tooltips_enabled, append_limited_text) (get_shared_tooltips, synthesize_enter_notify_event): New functions. * gui-gtk/gtk-preferences.c (create_game_tree_page): Add a check button controlling whether tooltips are shown on the game tree view. Adjust a mnemonic. (create_markup_box): Wrap `theme_hbox' in a GtkNamedVbox for better alignment and don't pack a dummy label into it. (update_game_tree_tooltips_status): New function. * gui-gtk/gtk-named-vbox.c (gtk_named_vbox_init): Don't show the label just yet. (gtk_named_vbox_new): Use gtk_named_vbox_set_label_text() instead of explicit gtk_label_set_text() call. (gtk_named_vbox_size_request): Don't request space for the label if it is not visible. (gtk_named_vbox_size_allocate): Likewise: don't allocate. (gtk_named_vbox_set_label_text): Show or hide the label depending on whether text is empty. * sgf/sgf-utils.c (sgf_utils_get_node_move_number): New function. * gui-utils/common-configuration-values.list: Add value controlling whether to show tooltips in game tree view. * gui-utils/common-configuration-defaults.list: Likewise. * gui-gtk/gtk-go-to-named-node-dialog.c (set_selected_node): Make comment window contain text "Empty" when there is no comment and don't make it sensitive. 2006-02-21 Paul Pogonyshev * gui-gtk/quarry-message-dialog.c (quarry_message_dialog_class_init): New function. (quarry_message_dialog_init): Create only one label (so that user can select the complete text, not only part.) Initialize new `primary_text' and `secondary_text' fields. (quarry_message_dialog_finalize): New function. (quarry_message_dialog_set_primary_text): Call set_label_text(). (quarry_message_dialog_set_secondary_text): Likewise. (set_label_text): New function. * gui-utils/parse-configuration.c (configuration_parse_values2): Bug-fix: write `\000' instead of `\0' to avoid misinterpretations if followed by a digit. * gui-gtk/gtk-games.c (gtk_games_create_board_size_selector_box): New function, break out a common part of gtk_new_game_dialog_init() and gtk_new_game_record_dialog_init() and add quick standard board size selectors. (set_standard_board_size): New function. * board/games.list: Add standard board sizes data to the three supported games. * board/parse-game-list.c (game_list_parse_game2): Parse and write a set of standard board sizes (written in format suitable for string_list_fill_from_string().) 2006-02-20 Paul Pogonyshev * sgf/sgf-parser.c (format_error_valist): Change `buffer' type from `char *' to `StringBuffer *'. Don't return anything. * sgf/sgf-parser.h (MAX_ERROR_LENGTH): Remove macro. * sgf/sgf-utils.c (sgf_utils_format_node_move): Change `buffer' type from `char *' to `StringBuffer *'. Don't return anything. * board/amazons.c (amazons_format_move): Change `buffer' type from `char *' to `StringBuffer *'. Don't return anything. * board/go.c (go_format_move): Change `buffer' type from `char *' to `StringBuffer *'. Don't return anything. (go_score_game): Change `detailed_score' type from `char **' to `StringBuffer *'. Don't allocate `detailed_score' but write to the buffer instead (if non-NULL.) * board/reversi.c (reversi_format_move): Change `buffer' type from `char *' to `StringBuffer *'. Don't return anything. * board/board.c (game_format_point): Change `buffer' type from `char *' to `StringBuffer *'. Don't return anything. (game_format_position_list): Likewise. (game_format_move): Likewise. (game_format_move_valist): Likewise. (game_format_score_difference): Add `buffer' argument, don't allocate and return a string. * board/board.h (SUGGESTED_POSITION_LIST_BUFFER_SIZE): Remove macro. * utils/string-buffer.c (string_buffer_steal_string): New function. 2006-02-19 Paul Pogonyshev * gui-gtk/gtk-parser-interface.c (gtk_parser_interface_present): Update for new `response' callback usage scheme of gtk_file_dialog_new(). * gui-gtk/gtk-utils.c (browse_button_clicked): Likewise. * gui-gtk/gtk-goban-window.c (gtk_goban_window_save): Use new gtk_file_dialog_set_current_name() function when saving the file for the first time. Update for new `response' callback scheme. (save_file_as_response): Use gtk_window_get_modal() check instead of gtk_main_level() to determine if we should destroy the dialog (the latter doesn't work.) * gui-gtk/gtk-file-dialog.c (gtk_file_dialog_new): Remove `response_callback' and `user_data' arguments. Don't create custom data structure or connect handlers to free it. (gtk_file_dialog_set_filename): With GtkFileChooser, use gtk_file_chooser_set_current_name() when the filename is not an absolute path or doesn't exist. (gtk_file_dialog_set_current_name): New function. (file_chooser_save_response): Remove `data' argument. Don't invoke user callback. Stop signal emission if confirmation dialog is shown (this is to make it work from gtk_dialog_run().) (file_selection_open_response): Likewise; stop emission if a directory is selected. (file_selection_save_response): Likewise; stop emission in both cases. (check_if_overwriting_file): Remove `data' argument. (overwrite_confirmation): Remove `data' argument. Don't invoke user callback, but instead emit `response' signal on the file dialog after disconnecting our handlers. * gui-gtk/gtk-goban-window.c (update_game_specific_information): Use ngettext() for integral komi, use proper minus sign. (update_move_information): Use new game_format_score_difference(). * board/go.c (go_score_game): Use ngettext() for integral komi, use new game_format_score_difference(), use proper minus sign. * board/board.c (game_format_score_difference): New function, break common part out of go_score_game() and update_move_information(). Use ngettext() for integral score differences. * gui-gtk/gtk-goban-window.c (gtk_goban_window_init): Only call gtk_item_factory_set_translate_func() if ENABLE_NLS is true, else it won't compile without NLS (thanks to C Thomas for bug-report.) 2006-02-18 Paul Pogonyshev * gui-gtk/gtk-file-dialog.c: Include `gtk-utils.c' again, else GTK_2_4_OR_LATER never gets defined. 2006-02-09 Paul Pogonyshev * gui-gtk/gtk-goban-window.c (gtk_goban_window_init): Rename "Set Player to Move" submenu to "Player to Move". * gui-gtk/gtk-goban-window.c (gtk_goban_window_init): Add "Edit/Move Branch Up" and "Edit/Move Branch Down" menu items. Resolve a mnemonics conflict. (update_commands_sensitivity): Update sensitivity of the new commands. (swap_adjacent_branches): New function. * sgf/sgf-utils.c (sgf_utils_swap_current_node_with): New function. * sgf/sgf-undo.c (sgf_swap_nodes_undo_history_entry_new) (sgf_operation_swap_nodes_do_swap): New functions. * sgf/sgf-undo-operations.list: Add `SGF_OPERATION_SWAP_NODES'. 2006-02-05 Paul Pogonyshev * gui-gtk/gtk-goban-window.c (gtk_goban_window_init): Add "Edit/Set Move Number" menu item. Adjust some mnemonics. (update_commands_sensitivity): Update sensitivity of the new command. (set_move_number): New function. * gui-gtk/quarry-move-number-dialog.c: New file. * gui-gtk/quarry-move-number-dialog.h: New file. * sgf/sgf-utils.c (sgf_utils_get_sequential_move_number): New function. * board/board.c (board_get_move_number): New function. * (Globally in board/: add BoardStackEntry structure that encapsulates `move_number' and, possibly, `grid_copy' fields. Include it in all game-specific stack entry structures.) 2006-02-04 Paul Pogonyshev * gui-gtk/gtk-goban-window.c (gtk_goban_window_init): Add "Edit/Set Player to Move" submenu. Initialize new `updating_set_player_commands' field. (update_children_for_new_node): Call new function update_set_player_to_move_commands(). (update_set_player_to_move_commands, set_player_to_move): New functions. * sgf/sgf-utils.c (sgf_utils_append_variation): Make it return the new node. (sgf_utils_set_number_property): Add special case for `PL' property. (sgf_utils_determine_player_to_move_by_rules) (sgf_utils_find_board_state_data): New functions. (sgf_utils_descend_nodes): Adapt to new `PL' value storage scheme. Check for `PL' for all non-move nodes, since in Quarry a node with only a `PL' property is not considered a setup node internally. (sgf_utils_ascend_nodes): Likewise. (find_board_state_data): New function, break out of sgf_utils_ascend_nodes(). Similar change for `PL' property as for sgf_utils_descend_nodes(). (determine_final_color_to_play): Make the `tree' argument `const'. * sgf/sgf-undo.c (sgf_change_node_inlined_color_undo_history_entry_new): Rename from sgf_change_node_move_color_undo_history_entry_new(). Add `operation' argument. (sgf_operation_change_node_move_color_do_change): Record the node as `node_to_switch_to'. (sgf_operation_change_node_to_play_color_do_change): New function. * sgf/sgf-undo-operations.list: Add `SGF_OPERATION_CHANGE_NODE_TO_PLAY_COLOR'. * sgf/sgf-writer.c (write_node_sequence): Add special case to write `PL' at appropriate place between other properties. * sgf/sgf-properties.list (PL): Use `not_stored' storage type and new sgf_parse_to_play() parser. * sgf/sgf-parser.c (complete_node_and_update_board): Adapt to new `PL' value storage scheme. (do_parse_color): New function, broken out of sgf_parse_color(). (sgf_parse_color): Remove special case for `PL' property, this function is not invoked for it anymore. (sgf_parse_to_play): New function. * sgf/sgf-tree.c (sgf_node_new): Initialize new `to_play_color' field. (sgf_node_duplicate): Copy `to_play_color' field. * board/board.h: Include `assert.h' since board_position_list_delete() uses assert(). * (Globally in gui-gtk/: use GLib g_return_*(), and other debug macros instead of plain assert(). The intention is to make Quarry more robust against programming errors.) 2006-02-01 Paul Pogonyshev * gui-gtk/gtk-game-info-dialog.c (gtk_game_info_dialog_set_node): Call quarry_history_text_buffer_reset_history(). * gui-gtk/quarry-history-text-buffer.c (quarry_history_text_buffer_reset_history): New function. * gui-gtk/quarry-text-buffer.c: Rename all `modifications_count' to `state_index'. (quarry_text_buffer_class_init): Hook up new quarry_text_buffer_modified_changed(). (quarry_text_buffer_init): Initialize new fields `last_assigned_state_index' and `unmodified_state_index'. (quarry_text_buffer_delete_range): Adjust renamed `state_index' so that it counts different buffer states, not just the number of modifications (these are different after undo operations.) (quarry_text_buffer_insert_text): Likewise. (quarry_text_buffer_modified_changed): New function (quarry_text_buffer_undo): Set the buffer to unmodified state if `state_index' is equal to `unmodified_state_index' after the operation. Inhibit undo entry combinations on the next step. (quarry_text_buffer_redo): Likewise. 2006-01-30 Paul Pogonyshev * gui-gtk/quarry-history-text-buffer.c (quarry_history_text_buffer_receive_undo_entry): Try to combine the just received entry with the last one using new quarry_text_buffer_combine_undo_entries(). * gui-gtk/quarry-text-buffer.c (quarry_text_buffer_init): Initialize new `modifications_count', `last_modification_time' and `previous_modification_time' fields. (quarry_text_buffer_delete_range): Increment `modifications_count'. (quarry_text_buffer_insert_text): Likewise. (quarry_text_buffer_begin_user_action): Update modification times. Set entry's `modifications_count_before'. (quarry_text_buffer_end_user_action): Set entry's `modifications_count_after'. (quarry_text_buffer_undo): Check that entry's modification count matches the expected for the buffer. Update buffer's count after undoing. (quarry_text_buffer_redo): Likewise. (quarry_text_buffer_combine_undo_entries): New function. * (Globally: use the new copyright updating scheme suggested by the GNU project, i.e. include all the years when Quarry changed, not particular file changed. Update all relevant files to include years 2005 and 2006.) 2006-01-29 Paul Pogonyshev * gui-gtk/gtk-game-info-dialog.c (gtk_game_info_dialog_init): Use QuarryTextView instead of GtkTextView to get undo history. * gui-gtk/quarry-text-view.c: New file. * gui-gtk/quarry-text-view.h: New file. * gui-gtk/quarry-history-text-buffer.c: New file. * gui-gtk/quarry-history-text-buffer.h: New file. * gui-gtk/quarry-text-buffer.c: New file. * gui-gtk/quarry-text-buffer.h: New file. * gui-gtk/gtk-utils.c (g_signal_accumulator_true_handled): Implement for pre-2.4 GTK+ (was not present in those versions.) * gui-gtk/quarry-marshal.glist: New marshaller `BOOLEAN:POINTER'. 2006-01-27 Paul Pogonyshev * gui-gtk/gtk-file-selector.c (gtk_file_selector_init): Use new entry_focus_out_event() instead of gtk_file_selector_repopulate() as `focus-out-event' handler. Fixes a crushing bug reported by Arend Bayer. (entry_focus_out_event): New function: invoke gtk_file_selector_repopulate() and return `FALSE'. 2005-11-11 Paul Pogonyshev * gui-gtk/gtk-utils.c (gtk_utils_create_invisible_notebook): Block `key-press-event' and `key-release-event' signals with new block_key_signal(). (block_key_signal): New function. 2005-11-02 Paul Pogonyshev * gui-gtk/gtk-goban-window.c (gtk_goban_window_init): Don't force window maximization, it goes in the way of the window manager (suggested by Heikki Levanto.) 2005-10-30 Paul Pogonyshev * (Quarry version 0.1.16.) * gui-gtk/gtk-goban-window.c (game_has_been_adjourned): Add a missing `the' article to a string constant. (update_children_for_new_node): Add `forced' argument so that the rest of code doesn't have to change `last_displayed_node' to force an update. (Fixes bug with disappearing comment changes.) Reset `text_buffer' modification state. (fetch_comment_and_node_name): Temporary set comment and node name with sgf_utils_set_text_property(). Still bad, but better than not saving changes in undo history at all. * gui-gtk/gtk-preferences.c (create_game_tree_page): Squeeze a double space in a string constant. * gui-gtk/gtk-help.c (gtk_help_display): Pass a `file://' URI, not just a filename to the browser, otherwise `#' fragment specialization doesn't work. 2005-10-29 Paul Pogonyshev * gui-gtk/gtk-new-game-record-dialog.c (gtk_new_game_record_dialog_init): Initialize widgets in accordance to saved configuration values. (gtk_new_game_record_dialog_response): Pass players' names and game name through sgf_utils_normalize_text(). Save configuration values as set up in the dialog this time. * gui-gtk/gtk-new-game-dialog.c (begin_game): Pass players' and engines' names through sgf_utils_normalize_text(). * gui-gtk/gtk-configuration.list: Add configuration parameters for new game records. * gui-utils/configuration.c (configuration_read_from_file): Handle nullable configuration values. (write_section): Likewise. * gui-utils/parse-configuration.c (configuration_parse_values2): Handle nullable configuration values. (configuration_parse_defaults2): Likewise. (look_at_field_type): Detect nullable configuration value types. (add_field_declaration_if_needed): Handle nullable configuration values. * gui-gtk/quarry-save-confirmation-dialog.c (quarry_save_confirmation_dialog_init): Pass "Close without Saving" string through gettext. (update_secondary_text): Remove parentheses that confused gettext. 2005-10-28 Paul Pogonyshev * (Globally: remove periods at the end of message dialog primary texts to conform with HIG.) * gui-gtk/gtk-control-center.c (gtk_control_center_quit): Ask all goban windows if they need saving first. * gui-gtk/gtk-goban-window.c (gtk_goban_window_new): Don't set no-file windows to be irreversibly modified. (gtk_goban_window_stops_closing): New function. (collection_modification_state_changed): Treat no-file windows differently. Track time of first modification. (gtk_goban_window_close): New function. (update_window_title): Treat no-file windows differently. * gui-gtk/quarry-save-confirmation-dialog.c: New file, partially inherit code from removed gtk_utils_create_message_dialog(). * gui-gtk/quarry-save-confirmation-dialog.h: New file. * gui-gtk/quarry-message-dialog.c: New file. * gui-gtk/quarry-message-dialog.h: New file. * gui-gtk/gtk-utils.c (gtk_utils_show_and_forget_dialog): New function. (gtk_utils_create_message_dialog): Remove function, partially inherited by new file `quarry-message-dialog.c'. 2005-09-28 Paul Pogonyshev * gui-gtk/gtk-preferences.c (handle_drag_and_drop): Return early in no-op drag-and-drop to avoid assertion failure in string_list_move(). (gtk_preferences_guess_engine_by_name): Improve for the case of multiple versions of the same engine. * gui-gtk/gtk-goban-window.c (leave_game_mode): Call update_commands_sensitivity() since editing tools become available. (update_commands_sensitivity): Don't touch "Edit/Go to Named Node" menu item if it is not present to begin with. * gui-gtk/gui-back-end.c (run_main_loop): Use `for' loops instead of g_ptr_array_foreach(), which is absent from old GLib versions. 2005-09-27 Paul Pogonyshev * (Globally: use "Reversi" instead of "Othello" everywhere to avoid potential trademark problems as suggested by Michel Alexandre Salim.) * gui-utils/tile-renderer.c (render_reversi_disks): Rename from render_othello_disks(). * gui-gtk/gtk-new-game-dialog.c (gtk_new_game_dialog_init): Adjust a couple mnemonics because of letter 'O' becoming unused. * gui-gtk/gtk-preferences.c (create_reversi_board_appearance_page): Rename from create_othello_board_appearance_page(). * gui-gtk/quarry-stock.c: Adjust mnemonic of `QUARRY_STOCK_CREATE' item: 'R' is now taken by "Reversi". * gtp/gtp-client.c (gtp_client_set_game): Add special case to supply "Othello" as game name, per de facto GTP standard. (store_supported_games_list): Likewise in opposite direction: translate "Othello" to "Reversi". * sgf/sgf-parser.c (do_parse_reversi_move): Rename from do_parse_othello_move(). * sgf/sgf-writer.c (do_write_reversi_move): Rename from do_write_othello_move(). * board/reversi.c: Rename from `othello.c'. * board/reversi.h: Rename from `othello.h'. * board/reversi.c (reversi_adjust_color_to_play): Rename from othello_adjust_color_to_play(). (reversi_get_default_setup): Rename from othello_get_default_setup(). (reversi_is_legal_move): Rename from othello_is_legal_move(). (reversi_play_move): Rename from othello_play_move(). (reversi_undo): Rename from othello_undo(). (reversi_apply_changes): Rename from othello_apply_changes(). (reversi_add_dummy_move_entry): Rename from othello_add_dummy_move_entry(). (reversi_format_move): Rename from othello_format_move(). (reversi_parse_move): Rename from othello_parse_move(). (reversi_validate_board): Rename from othello_validate_board(). (reversi_dump_board): Rename from othello_dump_board(). (reversi_count_disks): Rename from othello_count_disks(). 2005-09-26 Paul Pogonyshev * sgf/sgf-parser.c (do_parse_simple_text): Fix leading whitespace skipping (`continue' won't work in `do ... while (0)' loop.) * gui-gtk/gtk-goban-window.c (gtk_goban_window_init): Add "Label Tool" and "Number Tool" items to "Edit" and editing tools menus. Initialize new `next_sgf_label' and `labels_mode' fields. (about_to_change_node): Emit `click-canceled' signal on window's goban. (label_mode_pointer_moved, label_mode_goban_clicked): New functions. (update_children_for_new_node): Reset `next_sgf_label'. (update_commands_sensitivity): Handle sensitivity of new menu items. (activate_label_tool): New function. * gui-gtk/gtk-add-or-edit-label-dialog.c: New file. * gui-gtk/gtk-add-or-edit-label-dialog.h: New file. * gui-gtk/gtk-goban.c (VERTICAL_LINE_GAP): New macro, broke out of draw_vertical_line_with_gaps() and gtk_goban_update(). (gtk_goban_init): Reset various new fields related to label feedback. (gtk_goban_expose): Add code for rendering semi-transparent label feedback using new get_or_create_label_feedback_pixbuf(). Use markup colors also for labels instead of black/white (via new render_label().) Alter label color based on SGF markup too: improves label readability. (draw_vertical_line_with_gaps): Also make gaps for label feedback. (draw_horizontal_line_with_gaps): Likewise. (gtk_goban_button_press_event): New function. (gtk_goban_leave_notify_event): Reset label feedback too. (gtk_goban_finalize): Call new free_label_feedback_data(). (gtk_goban_set_label_feedback): New function. (emit_pointer_moved): When resetting feedback overlay, reset label feedback too. (create_label_text_pixbuf, get_or_create_label_feedback_pixbuf) (free_label_feedback_data): New functions. * sgf/sgf-tree.c (sgf_game_tree_delete): Use sgf_undo_history_delete() instead of removed. sgf_undo_history_delete_dont_free_data() (sgf_label_list_get_label, sgf_label_list_set_label) (sgf_label_list_contains_label, compare_sgf_labels): New functions. * sgf/sgf-undo.c (sgf_undo_history_delete_dont_free_data): Remove function: data in `SgfChangePropertyOperationEntry' isn't linked from property pool and it's not worth it to have special-case code for this. * board/board.h (POINTS_LESS_THAN): New macro. 2005-09-25 Paul Pogonyshev * gui-gtk/gtk-tile-set.c (scale_and_paint_svg_image): Change a lot of types and use explicit casting to suppress all GCC 4.0 warnings. * gui-gtk/gtk-named-vbox.h (_GtkNamedVBox): Change type of `left_padding' field to `int' to avoid GCC 4.0 warning. * gui-gtk/gtk-gtp-client-interface.c (handle_engine_output): Change type of `bytes_read' to `gsize' to silence GCC 4.0 warning. (handle_engine_stderr): Likewise. * gui-utils/tile-renderer.c (duplicate_and_adjust_alpha): Change type of `new_pixel_data' and `scan' to `unsigned char *' to deal with GCC 4.0 warnings. (saturate_and_set_alpha): Likewise. (combine_pixels_diagonally): Likewise. * sgf/sgf-utils.c (sgf_utils_descend_nodes): Explicitly cast an argument of sgf_node_get_number_property_value() to `int *' to prevent GCC 4.0 warning. * utils/buffered-writer.c (buffered_writer_add_character): Change type of `buffer_size' and some local variables to `size_t'. (Dealing with GCC 4.0 warnings.) (buffered_writer_add_newline): Likewise for local variables. (buffered_writer_cat_as_string): Likewise for `length' and local variables. (buffered_writer_cat_as_strings): Likewise for length arguments from variadic argument list. (buffered_writer_vprintf): Likewise for a local variable. (buffered_writer_vcprintf): Likewise. (update_column): Likewise for `length' and a local variable. 2005-07-17 Paul Pogonyshev * gui-utils/tile-renderer.c (duplicate_and_adjust_alpha): Replace `image_size' argument with `width' and `height'. (saturate_and_set_alpha): New function. 2005-07-16 Paul Pogonyshev * gui-gtk/gtk-game-info-dialog.c (gtk_game_info_dialog_init): Fix: set mnemonic widget for "Comment / Description" label to be the text view, not its scrollable parent. * gui-utils/common-configuration-values.list (amazons_board_appearance_values): Fix two wrong `markup_colors' indices. 2005-07-15 Paul Pogonyshev * gui-gtk/gtk-goban-window.c: Add some comments for translators. (gtk_goban_window_init): Add "Add Empty Node" item to "Edit" menu. Remove accidental mnemonic from toolbar editing tool menu. Pass "Pass" and "Resign" strings through gettext(). (gtk_goban_window_enter_game_mode): Pass "Please set up..." message through ngettext(): not all languages have the same forms for all integers greater than 1. (show_go_to_named_node_dialog): Fix gtk_utils_create_message_dialog() invocation arguments order. (update_commands_sensitivity): Sensitize/desensitize new menu item as appropriate. Make search and "Go to Named Node" commands insensitive in special modes. (append_empty_variation): New function. * gui-gtk/gtk-go-to-named-node-dialog.c (gtk_go_to_named_node_dialog_new): Explicitly cast `node_name' to `gpointer' to suppress warning. (gtk_go_to_named_node_dialog_finalize): Arrange for calling new free_node_list() function on each `completion_tree' node. (free_node_list): New function. * gui-gtk/quarry-stock.c: Add context information to the renamed stock items' strings. (quarry_stock_init): Use Q_() instead of _() to handle context. * gui-gtk/quarry-stock.h (QUARRY_STOCK_FIND_NEXT): Rename from `QUARRY_STOCK_NEXT'. (QUARRY_STOCK_FIND_PREVIOUS): Rename from `QUARRY_STOCK_PREVIOUS'. * gui-gtk/gtk-assistant.c (gtk_assistant_init): Use `GTK_STOCK_GO_FORWARD' instead of `QUARRY_STOCK_NEXT' (as suggested by HIG.) * gui-gtk/gtk-preferences.c (gtk_preferences_dialog_present): Generate game name labels in category tree with gtk_games_get_capitalized_name(). (create_gtp_engines_page): Prepare "Supported game(s):" label for using `game'/`games' as appropriate. (create_saving_sgf_page): Add accidentally missing mnemonics. (gtk_preferences_dialog_update_gtp_engine_info): Translate game names and capitalize the first. Set `game'/`games' as described above. * gui-gtk/gtk-resume-game-dialog.c (analyze_game_to_be_resumed): Pass name of unsupported game through gettext. (gtk_resume_game_dialog_present): Use gtk_games_get_capitalized_name() for retreiving game name. Add context information to "Not set" strings. * gui-gtk/gtk-games.c (gtk_games_get_capitalized_name): New function. (gtk_games_name_to_index): Use new function game_from_game_name() and return GTK_GAME_UNSUPPORTED, not -1 if the game is not supported. * gui-gtk/gui-back-end.c (gui_back_end_register_object_to_finalize): Use GPtrArray instead of GSList for `objects_to_finalize'. (gui_back_end_register_pointer_to_free): New function. (run_main_loop): Free the registered pointers and GPtrArray's. * board/board.c (game_from_game_name): New function, essentially move code of gtk_games_name_to_index() here. * board/games.list: Add `GAME_INVALID' identifier. * board/go.c (go_score_game): Chop the text into pieces to allow proper translation. Use gettext and utils_cat_printf(). * quarry.h (Q_): New macro. * utils/utils.c (utils_cat_printf): New function. (utils_cat_vprintf): New function, essentially move code of utils_vprintf() here. (utils_gettext_with_context): New function. * board/parse-game-list.c (CAPITALIZATION_HINT): New macro. (game_list_parse_game2): Mark game names in output up for `xgettext' harvesting. Add comments for translators. 2005-07-11 Paul Pogonyshev * gui-gtk/gtk-goban-window.c (gtk_goban_window_init): Add "Go to Named Node" item in "Go" menu when using GTK+ 2.4 and up. (gtk_goban_window_enter_game_record_mode): Set undo history notification callback to undo_or_redo_availability_changed(). (undo_or_redo_availability_changed): New function, break out of update_commands_sensitivity(). (show_go_to_named_node_dialog): New function. (set_current_tree): Call undo_or_redo_availability_changed(). (set_goban_signal_handlers): Call gtk_goban_force_feedback_poll(): changing editing tool normally involves changing feedback. * gui-gtk/gtk-go-to-named-node-dialog.c: New file. * gui-gtk/gtk-go-to-named-node-dialog.h: New file. * gui-gtk/quarry-stock.c: New stock item `QUARRY_STOCK_GO_TO_NODE. * sgf/sgf-undo.c (sgf_undo_history_new): Initialize new `notification_callback' and `user_data' fields. (sgf_undo_history_set_notification_callback): New function. (begin_undoing_or_redoing): Set `could_undo' and `could_redo' fields of `tree'. (end_undoing_or_redoing): Send notification if undo/redo availability has changed (based on `could_undo' and `could_redo'.) * sgf/sgf-privates.h (UNDO_HISTORY_DO_NOTIFY): New macro. 2005-07-10 Paul Pogonyshev * sgf/sgf-undo.c: New file, break out of `sgf-utils.c'. (sgf_undo_history_new): Link up the new history to tree's list of undo histories. (sgf_undo_history_delete): Detach the history from tree's list of undo histories. (sgf_new_node_undo_history_entry_new): Rename from create_new_node_undo_history_entry() and make global. Remove `tree' argument and retrieve `current_variation' field from `new_node->parent', not `tree->current_node' (removes restriction on new node's parent.) (sgf_delete_node_undo_history_entry_new): New function, break out of sgf_utils_delete_current_node(). (sgf_delete_node_children_undo_history_entry_new): New function, break out of sgf_utils_delete_current_node_children(). (sgf_change_node_move_color_undo_history_entry_new): New function, break out of sgf_utils_apply_setup_changes(). (sgf_new_property_undo_history_entry_new): Rename from create_new_property_undo_history_entry() and make global. (sgf_delete_property_undo_history_entry_new): Rename from create_delete_property_undo_history_entry() and make global. (sgf_change_property_undo_history_entry_new): Rename from create_change_property_undo_history_entry() and make global. (sgf_change_real_property_undo_history_entry_new): New function, break out of sgf_utils_set_real_property(). (sgf_utils_apply_undo_history_entry): Rename from apply_undo_history_entry() and make global. * sgf/sgf-tree.c (sgf_game_tree_new): Set new `undo_history_list' field to NULL. (sgf_game_tree_delete): Delete all undo histories in `undo_history_list'. * sgf/sgf-utils.c (sgf_utils_do_switch_to_given_node): Rename from do_switch_to_given_node() and make global. (sgf_utils_descend_nodes): Rename from descend_nodes() and make global. (sgf_utils_ascend_nodes): Rename from ascend_nodes() and make global. 2005-07-09 Paul Pogonyshev * gui-gtk/gtk-goban-window.c (gtk_goban_window_init): Add "Editing toolbar" item in "View" menu. Add editing toolbar with some buttons and an option menu for selecting editing tool. (gtk_goban_window_finalize): Unreference new `tools_item_factory' field. (show_or_hide_editing_toolbar, tools_option_menu_changed) (synchronize_tools_menus): New functions. (update_commands_sensitivity): Set editing toolbar's button sensitive or insensitive, as appropriate. Call synchronize_tools_menus(). (activate_move_tool): Call synchronize_tools_menus (). (activate_setup_tool): Likewise. (activate_scoring_tool): Likewise. (activate_markup_tool): Likewise. * gui-gtk/gtk-preferences.c (create_gtk_ui_page): Also create controls for editing toolbar parameters. (create_toolbar_style_box): New function, break out of create_gtk_ui_page(). (gtk_preferences_register_editing_toolbar): New function. * gui-gtk/gtk-configuration.list: Add configuration parameters for editing toolbars. * sgf/sgf-tree.c (sgf_collection_is_modified): Rename accidentally left `num_modified_trees' to `num_modified_undo_histories'. (sgf_collection_set_unmodified): Likewise. * sgf/sgf-utils.c (end_undoing_or_redoing): Likewise. 2005-07-04 Paul Pogonyshev * gui-gtk/gtk-goban-window.c (gtk_goban_window_new): Set collection notification callback to new collection_modification_state_changed(). Set `is_irreversibly_modified' for newly created collections. (set_sgf_collection_is_modified): Remove function. (collection_modification_state_changed): New function. (gtk_goban_window_save): Call sgf_collection_set_unmodified() after a successful save. (save_file_as_response): Likewise. (game_info_dialog_property_changed): Don't call removed set_sgf_collection_is_modified() and rely on notifications. (handle_go_scoring_results): Likewise. (play_pass_move): Likewise. (do_resign_game): Likewise. (playing_mode_goban_clicked): Likewise. (setup_mode_goban_clicked): Likewise. (markup_mode_goban_clicked): Likewise. (fetch_comment_and_node_name): Likewise. (move_has_been_played): Likewise. (player_is_out_of_time): Likewise. (delete_current_node): Likewise. (delete_current_node_children): Likewise. * sgf/sgf-utils.c (sgf_undo_history_new): Initialize new `unmodified_state_entry' field. (begin_undoing_or_redoing): Set new `tree_was_modified' and `collection_was_modified' fields. (end_undoing_or_redoing): Bug-fix: emit notifications even if `node_to_switch_to' is NULL. Emit notification about collection's modification state change when appropriate. (apply_undo_history_entry): Set `is_irreversibly_modified' collection's field when modifying a tree without an undo history. * sgf/sgf-tree.c (sgf_collection_new): Initialize new fields `num_modified_undo_histories', `is_irreversibly_modified', `notification_callback' and `user_data' fields. (sgf_collection_add_game_tree): Set `tree->collection' field. (sgf_collection_is_modified, sgf_collection_set_unmodified) (sgf_collection_set_notification_callback): New functions. (sgf_game_tree_new): Initialize new `collection' field. * sgf/sgf-privates.h (COLLECTION_DO_NOTIFY): New macro. (GAME_TREE_DO_NOTIFY): Rename from DO_NOTIFY() and move from `sgf-utils.c' 2005-07-03 Paul Pogonyshev * gui-gtk/gtk-utils.c (browsing_dialog_response): Die in assertion failure if `data->associated_entry' is not `GTK_ENTRY' or `GTK_FILE_SELECTOR' (avoid warning about uninitialized `entry'.) * sgf/sgf-utils.c (sgf_utils_apply_setup_changes): Initialize `undo_history' to avoid GCC warning. (sgf_utils_end_action): Bug-fix: call end_undoing_or_redoing() whenever `undo_operation_level' is zero, don't require an undo history. * sgf/sgf-utils.c (sgf_utils_append_variation): Call sgf_utils_begin_action() and sgf_utils_end_action(). (sgf_utils_apply_setup_changes): Call sgf_utils_begin_action() and sgf_utils_end_action(). Pass node's `move_color' change through undo history so that it is done not only the first time. (sgf_utils_apply_markup_changes): Call sgf_utils_begin_action() and sgf_utils_end_action(). (sgf_utils_set_none_property, sgf_utils_set_number_property) (sgf_utils_set_real_property, sgf_utils_set_text_property) (sgf_utils_set_list_of_label_property): New functions. (sgf_utils_set_time_left): Use sgf_utils_set_*() functions instead of sgf_node_add_*() ones. Call sgf_utils_begin_action() and sgf_utils_end_action(). (sgf_utils_delete_current_node): Call sgf_utils_begin_action() and sgf_utils_end_action(). (sgf_utils_delete_current_node_children): Likewise. (sgf_utils_delete_property, sgf_utils_begin_action) (sgf_utils_end_action): New functions. (sgf_utils_undo): Call begin_undoing_or_redoing() and end_undoing_or_redoing(). Handle actions comprised of multiple history entries. (sgf_utils_redo): Likewise. (sgf_undo_history_delete): Use delete_undo_history_entry() to handle NULL `free_data' functions. (do_set_pointer_property, strings_are_equal) (create_new_property_undo_history_entry) (create_delete_property_undo_history_entry) (create_change_property_undo_history_entry): New functions. (delete_undo_history_entry): New function, don't call `free_data' if it is NULL. (begin_undoing_or_redoing, set_is_modifying_map) (set_is_modifying_tree, end_undoing_or_redoing): New functions. (apply_undo_history_entry): Use delete_undo_history_entry(). Initialize `is_last_in_action' field of the `entry'. (sgf_operation_add_node): Pass notifications through set_is_modifying_*() functions. Schedule current tree node switching using `node_to_switch_to' field. (sgf_operation_delete_node): Likewise. (sgf_operation_delete_node_children_undo): Likewise. (sgf_operation_delete_node_children_redo): Likewise. (sgf_operation_change_node_move_color_do_change) (sgf_operation_add_property, sgf_operation_delete_property) (sgf_operation_new_property_free_data) (sgf_operation_delete_property_free_data) (sgf_operation_change_property_do_change) (sgf_operation_change_property_free_data): New functions. (sgf_operation_change_real_property_do_change): New function, conditioned on `SGF_REAL_VALUES_ALLOCATED_SEPARATELY'. (find_property_link): New function. * sgf/sgf-undo-operations.list: New operations: `SGF_OPERATION_CHANGE_NODE_MOVE_COLOR', `SGF_OPERATION_NEW_PROPERTY', `SGF_OPERATION_DELETE_PROPERTY', `SGF_OPERATION_CHANGE_PROPERTY' and (conditional) `SGF_OPERATION_CHANGE_REAL_PROPERTY'. * sgf/sgf.h (sgf_utils_set_double_property) (sgf_utils_set_color_property): New macros. * sgf/sgf-tree.c (sgf_game_tree_new): Initialize new field `undo_operation_level'. (sgf_property_free_value): New function, break code out of free_property_value() and change signature. (sgf_label_lists_are_equal): New function. 2005-06-30 Paul Pogonyshev * board/board.h (POINTS_ARE_EQUAL): Move from `sgf/sgf-diff-utils.c' * sgf/sgf-writer.c (sgf_write_none): Change `value' type from `SgfValue' to `SgfValue *'. (sgf_write_number): Likewise. (sgf_write_real): Likewise. Also access `value->real' as determined by `SGF_REAL_VALUES_ALLOCATED_SEPARATELY'. (sgf_write_double): Likewise. (sgf_write_color): Likewise. (sgf_write_simple_text): Likewise. (sgf_write_fake_simple_text): Likewise. (sgf_write_text): Likewise. (sgf_write_list_of_point): Likewise. (sgf_write_list_of_vector): Likewise. (sgf_write_list_of_label): Likewise. (sgf_write_figure_description): Likewise. (sgf_write_unknown): Likewise. * sgf/sgf-parser.c (sgf_parse_real): Access `(*link)->value.real' as determined by `SGF_REAL_VALUES_ALLOCATED_SEPARATELY'. * sgf/sgf-tree.c (sgf_node_get_real_property_value): Access `properties->value.real' as determined by `SGF_REAL_VALUES_ALLOCATED_SEPARATELY'. (sgf_node_add_real_property): Likewise. (sgf_property_duplicate): Likewise. * sgf/sgf-properties.list: Use `SGF_REAL_VALUES_ALLOCATED_SEPARATELY' as appropriate. * sgf/parse-sgf-list.c (SGF_REAL_VALUES_ALLOCATED_SEPARATELY): New macro. Pass it as condition to parse_list_main(). * board/games.list: Add '@' signs before all directives. * sgf/sgf-errors.list: Likewise. * sgf/sgf-undo-operations.list: Likewise. * gui-utils/markup-theme-configuration.list: Likewise. * gui-gtk/gtk-configuration.list: Likewise. * utils/parse-list.c: Add conditionals support. Make all directives (`mode', `c_include' etc.) start with '@' sign. (parse_list_main): Add `conditions' argument. Strip `_NEW' suffix (if present) from `.h' file global control macro name. Empty the new condition stack. (do_parse_lists): Die in error if condition stack is not empty after having processed the list file. Process new `@define_condition' directive. (read_line): Process new `@if', `@ifnot', `@else' and `@endif' directives. Ignore lines inside condition blocks when condition is false. (get_condition, push_condition_stack, pop_condition_stack): New functions. 2005-06-25 Paul Pogonyshev * gui-gtk/gtk-utils.c (gtk_utils_create_message_dialog): Use g_markup_escape_text() on message and hint texts. (gtk_utils_create_titled_page): Likewise for title text. * sgf/sgf-utils.c (find_time_control_data): Add `const' qualifier to `tree' argument. 2005-06-23 Paul Pogonyshev * sgf/sgf-utils.c (sgf_utils_set_time_left): New function, break out of time_control_save_state_in_sgf_node() in `gui-utils/time-control.c', but also update board state of the tree if setting time in the current node. (sgf_utils_find_time_control_data): New function. (find_time_control_data): Only use ``weird fix'' if `upper_limit' has children. 2005-06-22 Paul Pogonyshev * gui-gtk/gtk-goban-window.c (go_scoring_mode_cancel): New function. (handle_go_scoring_results): New function, break out of go_scoring_mode_done(). Use `board' and `board_state' stored in the current tree (they may correspond to the off-screen game position.) (update_commands_sensitivity): Desensitize all tools except the move tool when playing a game. Likewise for scoring tool when scoring a game (unlike scoring a position in a game record.) (move_has_been_played): Use board stored in the current tree (same as for handle_go_scoring_results().) When scoring using GTP engines, don't leave game mode yet. (engine_has_scored): If the human gets to score, be sure to switch to the game position node. If the engines agree with each other, add results to the game position node instead of the displayed node. And leave game mode here. (cancel_scoring): Likewise, except that ``engines agree'' case cannot happen here. (enter_scoring_mode): Activate appropriate menu item and let the callback do the rest. (activate_scoring_tool): Move most code of enter_scoring_mode() here. Allow to cancel scoring when not in game mode. Guess ``initial'' dead stones from SGF territory properties using go_guess_dead_stones(). * board/go.c (go_guess_dead_stones): New function. 2005-06-19 Paul Pogonyshev * gui-gtk/gtk-new-game-dialog.c: Make it a GLib class (lots of small changes everywhere.) (gtk_new_game_dialog_get_type): New function. (gtk_new_game_dialog_init): New function, break out of gtk_new_game_dialog_present(). Pass `game_labels[k]' string through gettext. (gtk_new_game_dialog_present): Only allow one dialog at a time. (swap_players): Change argument's type to `GtkNewGameDialog'. (get_selected_game): Likewise. (show_game_specific_rules): Likewise. (set_handicap_adjustment_limits): Likewise. (get_game_rules_help_link_id): Likewise. (instantiate_players): Likewise. * gui-gtk/gtk-new-game-dialog.h (GTK_TYPE_NEW_GAME_DIALOG) (GTK_NEW_GAME_DIALOG, GTK_NEW_GAME_DIALOG_CLASS) (GTK_IS_NEW_GAME_DIALOG, GTK_IS_NEW_GAME_DIALOG_CLASS) (GTK_NEW_GAME_DIALOG_GET_CLASS): New macros. * gui-gtk/gtk-assistant.c (gtk_assistant_set_user_data): New function. * gui-gtk/gtk-goban-window.c (gtk_goban_window_init): Add "New Game Record" item to the "File" menu. * gui-gtk/gtk-control-center.c (gtk_control_center_present): Add "New Game Record Button". Pass "Resume Game" string through gettext. * gui-gtk/gtk-new-game-record-dialog.c: New file. * gui-gtk/gtk-new-game-record-dialog.h: New file. * gui-gtk/gtk-games.c (game_rules_labels): New global array of constant strings. (gtk_games_create_board_size_adjustment) (gtk_games_create_handicap_adjustment) (gtk_games_create_komi_adjustmet): New functions, break out of gtk_new_game_dialog_present(). (gtk_games_set_handicap_adjustment_limits): New function, break out of set_handicap_adjustment_limits() in `gtk-new-game-dialog.c'. 2005-06-18 Paul Pogonyshev * gui-gtk/gtk-utils.c (gtk_utils_pack_array_in_box) (gtk_utils_get_selected_radio_index): New functions. * gui-gtk/quarry-stock.c: New stock item `QUARRY_STOCK_CREATE'. * gui-gtk/gtk-sgf-tree-view.c (configure_adjustment): Add `original_value' argument and call gtk_adjustment_value_changed() if current value doesn't match original. Fixes problem when tree view's scrollbars wouldn't reflect most scrolls. 2005-06-17 Paul Pogonyshev * (Quarry version 0.1.15.) * gui-gtk/gtk-goban-window.c (gtk_goban_window_init): Add items for five SGF markup types to the "Edit/Tools" menu. (setup_mode_pointer_moved): When removing a string of stones with Ctrl-click, hide all feedback if the pointer moves outside the string. (setup_mode_goban_clicked): Likewise, don't make any changes if pointer has been moved outside the string. Call set_sgf_collection_is_modified(): we're not switching to proper modification tracking with undo history yet. (markup_mode_pointer_moved, markup_mode_goban_clicked) (activate_markup_tool): New functions. * sgf/sgf-utils.c (sgf_utils_apply_markup_changes): New function. * board/board.c (board_position_list_add_position): Allow `list' to be NULL. * board/go.c (go_is_same_string): New function. * gui-gtk/gtk-goban.c (gtk_goban_expose): Handle `GOBAN_MARKUP_GHOSTIFY_SGF_MARKUP' and `GOBAN_MARKUP_GHOSTIFY_SGF_MARKUP_SLIGHTLY' flags. (gtk_goban_button_press_event): Reset new `anti_slip_disabled' field upon a new button press. (gtk_goban_button_release_event): Use `anti_slip_disabled' instead of checking if press point has been reset to null. Set new `non_empty_feedback' field in the data sent to callbacks. (gtk_goban_set_overlay_data): Add `sgf_markup_tile' argument. (gtk_goban_disable_anti_slip_mode): Set `anti_slip_disabled' to `TRUE' instead of setting the press point to null. (gtk_goban_set_contents): Add `sgf_markup_contents' argument. Free the dummy overlay contents (a memory leak plug.) (gtk_goban_get_sgf_markup_contents): New function. (set_feedback_data): Handle all the new SGF markup feedbacks. Set `non_empty_feedback' field. (set_overlay_data): Add `sgf_markup_tile' arguments. Add special handling for ghostifying flags in goban markup. * gui-gtk/gtk-goban.h: A whole lot of new feedback types for SGF markup feedback. Add `GOBAN_MARKUP_GHOSTIFY_SGF_MARKUP', `GOBAN_MARKUP_GHOSTIFY_SGF_MARKUP_SLIGHTLY', `GOBAN_MARKUP_GRID_FLAGS_MASK', `GOBAN_MARKUP_SGF_FLAGS_MASK' and `GOBAN_SGF_MARKUP_TILE_DONT_CHANGE' constants. (GtkGobanClickData): Replace `feedback_tile' field with `non_empty_feedback'. * gui-gtk/gtk-tile-set.c (gtk_sgf_markup_tile_set_create): Create additional 25% and 50% transparent tiles. (gtk_sgf_markup_tile_set_delete): Unreference new tiles. (create_pixbuf_from_pixel_data): New function. * gui-gtk/gtk-tile-set.h (SGF_MARKUP_OPAQUE) (SGF_MARKUP_25_TRANSPARENT, SGF_MARKUP_50_TRANSPARENT) (NUM_ALL_SGF_MARKUP_SHADES): New macros. 2005-06-15 Paul Pogonyshev * gui-gtk/gtk-goban-window.c (gtk_goban_window_init): Add "Edit/Tools" submenu. Initialize new `drawn_position_list' field. (free_handicap_mode_done): Use grid_diff() instead of gtk_goban_diff_against_grid(). (go_scoring_mode_done): Modify to work when used as an editing tool instead of in game mode. (set_goban_signal_handlers): Emit `click-canceled' signal on the goban. (setup_mode_pointer_moved, setup_mode_goban_clicked) (delete_drawn_position_list): New functions. (activate_move_tool, activate_setup_tool, activate_scoring_tool): New functions. * sgf/sgf-utils.c (sgf_utils_apply_setup_changes) (sgf_utils_set_list_of_point_property): New functions. (create_new_node_undo_history_entry): New function, break out of sgf_utils_append_variation(). 2005-05-09 Paul Pogonyshev * gui-gtk/gtk-goban.c (gtk_goban_class_init): Create `click-canceled' signal. Fix copy'n'paste bug in `goban-clicked' signal creation. (gtk_goban_size_allocate): Emit `click-canceled'. (gtk_goban_button_release_event): Emit `click-canceled' when needed; handle cases when anti-slipping is disabled. (gtk_goban_leave_notify_event): Emit `click-canceled'. (gtk_goban_click_canceled): New function. (gtk_goban_disable_anti_slip_mode): New function. (gtk_goban_diff_against_grid): Remove function (essentially moved to grid_diff() in `board/board.c'.) (set_feedback_data): Handle two new feedbacks: `GOBAN_FEEDBACK_GHOSTIFY' and `GOBAN_FEEDBACK_GHOSTIFY_SLIGHTLY'. Process goban markup feedback before main feedback, because the latter can now modify the former. * board/board.c (board_position_list_union): Add `const' modifier to both arguments. (board_position_list_add_position): New function. (grid_diff): New function, essentially inherit code of gtk_goban_diff_against_grid() from `gui-gtk/gtk-goban.c'. 2005-05-08 Paul Pogonyshev * gui-gtk/gtk-qbox.h (GTK_IS_QBOX): Remove extra parenthesis. 2005-05-07 Paul Pogonyshev * (Globally: update FSF address in the legal notices.) 2005-04-28 Paul Pogonyshev * gui-utils/common-configuration-defaults.list: Make default markup color on white stones a little darker for all games. * gui-gtk/gtk-goban.c (gtk_goban_init): Initalize `last_move_pos' field that replaced `last_move_x' and `last_move_y'. (gtk_goban_set_parameters): Fill `sgf_markup' grid with `SGF_MARKUP_NONE', not `TILE_NONE' value. (gtk_goban_expose): Remove special code for marking last move position. Do that based on `last_move_pos' field with SGF markup instead. (gtk_goban_update): Remove special code for invalidation last move position area. Properly update `last_move_pos' instead. * gui-gtk/gtk-tile-set.c (gtk_sgf_markup_tile_set_create): Create an additional pseudo-SGF markup for last move from file named `last-move.svg'. (gtk_sgf_markup_tile_set_delete): Delete it. * sgf/sgf.h (SGF_MARKUP_NONE): Set to -1 to make way for `SGF_PSEUDO_MARKUP_LAST_MOVE' in `gui-gtk/gtk-tile-set.h'. * gui-gtk/gtk-goban-window.c (gtk_goban_window_init): Add "Quit" menu item. * gui-gtk/gtk-control-center.c (gtk_control_center_present): Add "Quit" button (part of #2290.) (gtk_control_center_quit): New function. * gui-gtk/gtk-resume-game-dialog.c (gtk_resume_game): Use static variable to store pointer to file dialog used for resuming games. * gui-gtk/gtk-parser-interface.c (gtk_parser_interface_present): Add `dialog_window' parameter and only create new file dialog if there is no dialog of requested type already present. Use static variable to store default opening dialog. 2005-04-27 Paul Pogonyshev * gui-gtk/gtk-resume-game-dialog.c (do_resume_game): Don't assert that instantiation was successful, just do nothing if it was not. * gui-gtk/gtk-new-game-dialog.c (gtk_new_game_dialog_present): Use gtk_preferences_guess_engine_by_name(). (begin_game): Don't assert that instantiation was successful, just do nothing if it was not. * gui-gtk/gtk-preferences.c (gtk_preferences_guess_engine_by_name): Rename from guess_engine_by_player_name() and move from `gui-gtk/gtk-resume-game-dialog.c' here. (gtk_preferences_create_engine_selector): Replace `engine_name' argument with `engine_data' and so don't resolve engines names. (gtk_preferences_set_engine_selector_game_index): Bug-fix for pre-2.4 GTK+: preserve the selection; it gets lost since the menu is rebuilt from scratch. (gtk_preferences_instantiate_selected_engine): When `have_error' is set and we don't try to instantiate engine, at least reset the `gtp_client' pointer to NULL. Add missing dot to error message. (gtk_preferences_do_instantiate_engines): If `have_error' is set, call `instantiation_callback' with `INSTANTIATION_FAILED' status. * gui-gtk/gtk-games.h (GtkGameIndex): Add `GTK_GAME_ANY'. 2005-04-24 Paul Pogonyshev * board/go.c (go_score_game): Plug a memory leak. * gui-gtk/gtk-goban-window.c (move_has_been_generated): Use gtk_sgf_tree_signal_proxy_push_tree_state() and gtk_sgf_tree_signal_proxy_pop_tree_state(). * gui-gtk/gtk-sgf-tree-signal-proxy.c (gtk_sgf_tree_signal_proxy_finalize): New function. (gtk_sgf_tree_signal_proxy_attach): Initialize new `state_stack' field with NULL. (gtk_sgf_tree_signal_proxy_push_tree_state) (gtk_sgf_tree_signal_proxy_pop_tree_state): New functions. (receive_notification): Block current node-related signals when `state_stack' is not empty. For other signals, temporary restore original board state. (Indirect fix for SGF tree view behaviour when browsing a game in progress.) 2005-04-23 Paul Pogonyshev * gui-gtk/gtk-configuration.list: Add "Search in" configuration parameter. * gui-gtk/gtk-goban-window.c (gtk_goban_window_class_init): Create text tags for highlighting of node names in the commentary text buffer. (gtk_goban_window_init): Add "Edit Node Name" item in the menu. Create text buffer ourself, with custom tag table. (show_find_dialog): Create a set of radio buttons for selecting between comments and/or node name search. Some minor redesign. Use gtk_utils_make_window_only_horizontally_resizable(). (find_dialog_response): Retrieve property search scope settings. (do_find_text): Search in comments and/or node names, as requested. When mapping normalized text to original, only work with one line (matches cannot cross line boundaries.) Use gtk_text_view_scroll_to_mark() instead of gtk_text_view_scroll_to_iter() as suggested by the API reference. (get_top_buffer_part, get_bottom_buffer_part): New functions. (update_children_for_new_node): Call new insert_node_name() if the new node has a name. (insert_node_name, select_node_name, text_buffer_insert_text) (text_buffer_after_insert_text, text_buffer_mark_set): New functions. (fetch_comment_and_node_name): Rename from fetch_comment_if_changed(). Also fetch node name if needed. * gui-gtk/gtk-utils.c (gtk_text_buffer_select_range): New function: trivial implementation for pre-2.4 GTK+ so that other code can avoid version checks. 2005-04-12 Paul Pogonyshev * gui-gtk/gtk-goban-window.c (gtk_goban_window_init): Register gettext() with gtk_item_factory_set_translate_func() to allow proper translation of menu items. Prevent collapse of main menu on GTK+ 2.4 and up with gtk_toolbar_set_show_arrow(). Mark some items as important with new `flags' argument of gtk_utils_append_toolbar_button(). Don't translate argument string to gtk_utils_set_menu_items_sensitive() with _() call (unneeded after registering the translation function.) (gtk_goban_window_new): Don't translate argument string to gtk_utils_set_menu_items_sensitive(). (set_sgf_collection_is_modified): Likewise. (show_or_hide_main_toolbar): Likewise for gtk_item_factory_get_widget() argument. (show_or_hide_navigation_toolbar): Likewise. (show_or_hide_game_action_buttons): Likewise. (show_or_hide_sgf_tree_view): Likewise. (update_commands_sensitivity): Likewise. * gui-gtk/gtk-preferences.c (create_gtk_ui_page): Use ``beside'', not ``besides''. The latter carries different meaning. Assert toolbar style constants and style name strings consistency. Don't allow text beside icons for pre-2.4 GTK+. (change_toolbar_style): Adjust toolbar style for older GTK+ because of the above change. (set_toolbar_style): Don't allow text beside icons for pre-2.4 versions of GTK+. * gui-gtk/gtk-configuration.list (gtk_ui_section_values): Use ``beside'', not ``besides''. * gui-gtk/gtk-utils.c (gtk_utils_append_toolbar_button): Add `flags' argument. Use GtkToolButton and new argument for GTK+ 2.4 and up. * gui-gtk/gtk-utils.h (gtk_utils_append_toolbar_space): New macro (behaviour depends on GTK+ version.) (gtk_toolbar_set_show_arrow): Define to nothing for pre-2.4 versions of GTK+. 2005-04-08 Paul Pogonyshev * sgf/sgf-utils.c (sgf_utils_delete_current_node): Set `parent_current_variation' to a neighbor of `tree->current_node', not to `tree->current_node' itself (fixes segfaults and incorrect behaviour spotted by Evan Daniel.) * sgf/sgf-tree.c (sgf_node_get_previous_node): New function. (sgf_node_get_last_child): Assert that `node' is not NULL. 2005-03-28 Paul Pogonyshev * gui-gtk/gtk-parser-interface.c (open_game_record): Call gtk_goban_window_enter_game_record_mode(). * gui-gtk/gtk-goban-window.c: Add labels to all navigation toolbar buttons. (gtk_goban_window_init): Add "Undo", "Redo", "Delete Node" and "Delete Node's Children" menu items to "Edit" menu. (gtk_goban_window_enter_game_record_mode): New function. (leave_game_mode): Call gtk_goban_window_enter_game_record_mode(). (update_children_for_new_node): Don't try to fetch comment if `goban_window->last_displayed_node' is NULL. (update_commands_sensitivity): Sensitize/desensitize new menu items as appropriate. (undo_operation, redo_operation, delete_current_node) (delete_current_node_children): New functions. * sgf/sgf-utils.c (sgf_utils_append_variation): Rely on apply_undo_history_entry() and functions it invokes for performing the main job. (sgf_utils_delete_current_node) (sgf_utils_delete_current_node_children, sgf_utils_undo) (sgf_utils_redo, sgf_undo_history_new, sgf_undo_history_delete) (sgf_undo_history_delete_dont_free_data): New functions. (do_switch_to_given_node): New function, break out of sgf_utils_switch_to_given_node(). (apply_undo_history_entry, sgf_operation_add_node) (sgf_operation_delete_node, sgf_operation_new_node_free_data) (sgf_operation_delete_node_free_data) (sgf_operation_delete_node_children_undo) (sgf_operation_delete_node_children_redo) (sgf_operation_delete_node_children_free_data, find_node_link): New functions. * sgf/sgf.h (sgf_utils_can_undo, sgf_utils_can_redo): New macros. * sgf/sgf-tree.c (sgf_game_tree_new): Initialize new `undo_history' field with NULL. (sgf_game_tree_delete): Delete undo history if needed. (sgf_node_append_child): Remove function. (sgf_node_get_last_child): New function. (sgf_node_is_game_info_node): Don't use links where they are not needed. (GET_PROPERTY_VALUE): Likewise. (sgf_node_get_number_property_value): Likewise. (sgf_node_get_real_property_value): Likewise. * sgf/sgf-undo.h: New file. * sgf/sgf-undo-operations.list: New file. * sgf/parse-sgf-list.c: Add mode to parse undo operations list. (undo_operation_list_parse_undo_operation2): New function. 2005-03-20 Paul Pogonyshev * gui-gtk/gtk-goban-window.c (gtk_goban_window_init): Force `goban' widget to grab focus. (show_game_information_dialog): Make `game_info_dialog' always stay above `goban_window'. * gui-gtk/gtk-file-selector.c (gtk_file_selector_finalize): Free `last_directory' string, don't leak it. 2005-03-19 Paul Pogonyshev * gui-gtk/gtk-goban-window.c (gtk_goban_window_init): Register toolbars with gtk_preferences_register_main_toolbar() and gtk_preferences_register_navigation_toolbar(). * gui-gtk/gtk-preferences.c (gtk_preferences_dialog_present): Add "General" category with "Interface" subcategory. Don't make "Close" button default (not recommended by HIG.) (create_gtp_engines_page): New function. (gtk_preferences_dialog_response): Handle `PREFERENCES_PAGE_GTK_UI'. (change_toolbar_style, gtk_preferences_register_main_toolbar) (gtk_preferences_register_navigation_toolbar) (do_register_toolbar, unregister_toolbar) (gtk_preferences_have_non_hidden_gtp_engine): New functions. * gui-utils/configuration.c (configuration_read_from_file): Tweak enumeration value parsing to allow values with embedded whitespace. * gui-utils/parse-configuration.c (configuration_parse_values2): Fix line-wrapping of `enumeration_values_as_strings'. * gui-gtk/gtk-configuration.list: Add configuration parameters for file chooser dialog and toolbar styles. * gtp/gtp-test.c (send_to_engine): Use write() instead of fwrite() and fdatasync() instead of fflush(). (main): Move all side-effect function calls out of `assert's to make the code work with assertions disabled (spotted by Darren Cook.) Don't wrap `engine_in' in a stream, use file descriptor. * sgf/sgf-parser.c (refresh_buffer): Fix `assert' as described above. (expand_buffer): Likewise. * sgf/sgf-diff.c (main): Fix `assert's as described above. * gui-gtk/gtk-tile-set.c (gtk_sgf_markup_tile_set_create): Fix `assert' as described above. (scale_and_paint_svg_image): Don't assert that rsvg_handle_write() and rsvg_handle_close() are successful. * gui-gtk/gtk-preferences.c (do_remove_gtp_engine): Fix `assert' as described above. (do_move_gtp_engine): Likewise. (gtk_gtp_engine_dialog_present): Likewise. * gui-gtk/gtk-goban-window.c (go_scoring_mode_done): Don't assert that komi is set and make it default to 0.0. 2005-03-19 Sjoerd Simons * board/board.h: Use `signed char' instead of `char' as field type in BoardPoint structure (`char' may be signed or unsigned depending on architecture.) 2005-03-18 Paul Pogonyshev * board/Makefile.am: Add explicit dependency to solve problems with parallel build. (LIST_STAMP_FILES, LIST_GENERATED_FILES): Remove variables, now defined in `$(top_srcdir)/aux/list.make'. * sgf/Makefile.am: Likewise. * gui-utils/Makefile.am: Likewise. * gui-gtk/Makefile.am: Likewise. 2005-03-17 Paul Pogonyshev * gui-gtk/gtk-goban-window.c (gtk_goban_window_save): Use gtk_file_dialog_new() and friends.. (suggest_filename): Return filename in UTF-8 rather than in file system encoding. (save_file_as_response): Use gtk_file_dialog_get_filename(). * gui-gtk/gtk-parser-interface.c (gtk_parser_interface_present): Use gtk_file_dialog_new() and friends. (open_file_response): Likewise. * gui-gtk/gtk-utils.c (gtk_utils_add_file_selection_response_handlers): Remove function. (file_selection_response, overwrite_confirmation): Remove functions (code inherited by `gui-gtk/gtk-file-dialog.c'.) (browse_button_clicked): Use gtk_file_dialog_new() and friends. (browsing_dialog_response): Likewise. * gui-gtk/gtk-file-dialog.c, gui-gtk/gtk-file-dialog.h: New files. 2005-03-14 Paul Pogonyshev * (Quarry version 0.1.14.) * gtp/gtp-client.c (store_protocol_version): Guard all accesses to `client', it may be NULL. Prevents segfaults. * gui-gtk/gtk-preferences.c (engine_is_visible_and_supports_game): Gracefully handle cases when called with iterator, for which data is not yet set. Prevents segfaults (bug #2089, magnade@gmail.com.) 2005-03-13 Paul Pogonyshev * (Quarry version 0.1.13.) * gui-gtk/Makefile.am: Rename `quarry-marshal.list' to `quarry-marshal.glist' in `EXTRA_DIST' too. * gui-gtk/gtk-goban-window.c (gtk_goban_window_init): Initialize `time_controls' with NULL. (gtk_goban_window_enter_game_mode): Replace `black_time_control' and `white_time_control' arguments with single `time_control'. (gtk_goban_window_resume_game): Remove `black_time_control' and `white_time_control' arguments altogether. Simply reuse time controls created by set_current_tree(). Set time controls' states after skipping played moves. (leave_game_mode): Don't delete time controls. (set_current_tree): Create and set time control using time_control_new_from_sgf_node(). (set_time_controls): New function. (update_children_for_new_node): When not in game mode, set clock's displayed time from `goban_window->sgf_board_state'. (update_window_title): Place ``modified'' string in brackets: too many parentheses already. * gui-utils/time-control.c (time_control_new_from_sgf_node) (time_control_duplicate, time_control_save_settings_in_sgf_node) (time_control_save_state_in_sgf_node) (time_control_apply_defaults_if_needed, time_control_set_state): New functions. SGF saving functions are broken out of begin_game() and move_has_been_played() correspondingly. (time_control_is_short_on_time): Always add overtime length to the remaining time. Effectively, don't report ``short on time'' when in the end of main time, but having a long overtime in reserve. * gui-utils/Makefile.am (AM_CPPFLAGS): Add `src/sgf' to include search path. * sgf/sgf-utils.c (sgf_utils_enter_tree): Initialize `tree->board_state' with `board_state' argument. (sgf_utils_go_down_in_tree): Remove `board_state' argument and use `tree->board_state' instead. (sgf_utils_go_up_in_tree): Likewise. (sgf_utils_switch_to_variation): Likewise. (sgf_utils_switch_to_given_variation): Likewise. (sgf_utils_append_variation): Likewise. (do_enter_tree): Remove `board_state' argument. Initialize new `tree->board_state' fields related to time control. (descend_nodes): Remove `board_state' argument. Track `game_info_node' here and set new `game_info_node_depth' field as appropriate. Only check `PL' property value for setup nodes. Call new find_time_control_data() function. (ascend_nodes): Remove `board_state' argument. Bug-fix: always find `last_move_node' (could be erroneously set to NULL in rare cases.) Only check `PL' property value for setup nodes. Simplify `game_info_node' evaluation using `game_info_node_depth' field. Call find_time_control_data(). (find_game_info_node): Remove function. (find_time_control_data): New function. (determine_final_color_to_play): Remove `board_state' argument. * sgf/sgf-tree.c (sgf_game_tree_new): Initialize new `board_state' field. (sgf_game_tree_set_state): Handle new `board_state' field of SgfGameTree and SgfBoardState structures. (sgf_game_tree_get_state): Likewise. 2005-03-12 Paul Pogonyshev * gui-gtk/gtk-preferences.c (create_background_table): Use GtkFileSelector for background texture selection when the widget is defined (on GTK+ 2.4 and up.) (board_background_texture_changed): New function. * gui-gtk/gtk-utils.c (gtk_utils_create_browse_button): Assert that `associated_entry' is a GtkEntry or GtkFileSelector. (browse_button_clicked): Handle GtkFileSelector case. (browsing_dialog_response): Likewise. * gui-gtk/quarry-marshal.glist: Rename from `quarry-marshal.list'. * Makefile.am: Use `top_builddir' where appropriate to allow building in a separate directory. * utils/Makefile.am: Likewise. * board/Makefile.am: Likewise. * sgf/Makefile.am: Likewise. * gtp/Makefile.am: Likewise. * gui-utils/Makefile.am: Likewise. * gtk-utils/Makefile.am: Likewise. * gtp/Makefile.am: Include `$(EXTRA_PROGRAMS)' in `CLEANFILES', not `MOSTLYCLEANFILES'. * sgf/Makefile.am: Likewise. * board/Makefile.am: Use `$(top_srcdir)/aux/list.make' to generate rules to parse `games.list'. * sgf/Makefile.am: Likewise for `sgf-errors.list' and `sgf-properties.list'. * gui-utils/Makefile.am: Likewise for `markup-theme-configuration.list'. Add missing `MOSTLYCLEANFILES'. * gui-gtk/Makefile.am: Likewise for `gtk-configuration.list'. 2005-03-11 Paul Pogonyshev * board/games.list: Add `mode' command at the beginning. * sgf/sgf-errors.list: Likewise. * sgf/sgf-properties.list: Likewise. * gui-utils/markup-theme-configuration.list: Likewise. * gui-gtk/gtk-configuration.list: Likewise. * gui-gtk/gtk-configuration.list: Adapt to new substitution scheme. Use `$top_srcdir$' passed through command line instead of relative path to allow building in a separate directory. * gui-utils/common-configuration-defaults.list: Adapt to new substitution scheme. * board/parse-game-list.c: Specify mode in `game_lists' (now required.) * gui-utils/parse-configuration.c: Likewise for `list_set'. * utils/parse-list.c (parse_list_main): Signal error if a substitution name contains a dollar sign. Get mode from list file, not from command line. (print_usage): Remove `list_sets' and `num_sets' arguments and code to output information about removed command line argument. (read_line): Reimplement substitutions: replace `$substition-name$' with corresponding substituion value in all lines before any further processing, even `include_list' checks. 2005-03-10 Paul Pogonyshev * gui-gtk/gtk-file-selector.c, gui-gtk/gtk-file-selector.h: New files. 2005-03-06 Paul Pogonyshev * sgf/sgf-properties.list: Rename `SGF_TIME_LEFT_4BLACK' to `SGF_TIME_LEFT_FOR_BLACK' and likewise for other properties. * gui-gtk/gtk-goban-window.c (gtk_goban_window_init): Use `QUARRY_STOCK_MENU_ITEM_ABOUT' for that menu item. (show_about_dialog): Use native GtkAboutDialog with GTK+ 2.6+. * gui-gtk/gtk-preferences.c (gtk_preferences_init): Fix GTK+ 2.4+ compilation: gtk_tree_model_filter_set_visible_func(), not gtk_tree_model_filter_set_visible_function(). (gtk_preferences_dialog_present): Move previously global `preferences_dialog_categories' here. Use `GTK_STOCK_EXECUTE' for "GTP Engines" page and `QUARRY_STOCK_ICON_FILE' for "Game Records (SGF)" category. * gui-gtk/quarry-stock.h (QUARRY_STOCK_ICON_DIRECTORY) (QUARRY_STOCK_FILE, QUARRY_STOCK_MENU_ITEM_ABOUT): New compatibility macros for GTK+ stock items. * gui-gtk/gtk-utils.h (GTK_2_6_OR_LATER): New macro. (gtk_dialog_set_default_response): Define this to gtk_utils_workaround_set_default_response() for GTK+ 2.0. * gui-gtk/gtk-utils.c (gtk_utils_workaround_set_default_response): New function, for GTK+ 2.0 only. * gui-gtk/gtk-goban-window.c (gtk_goban_window_new): Sensitize/desensitize "Save" menu item and toolbar button, depending on whether the SGF collection was read from file. (set_sgf_collection_is_modified): New temporary function. (gtk_goban_window_save): Mark SGF collection as unmodified after saving. (save_file_as_response): Likewise. (game_info_dialog_property_changed): Mark SGF collection as modified after the change. (go_scoring_mode_done): Likewise. (play_pass_move): Likewise. (do_resign_game): Likewise. (playing_mode_goban_clicked): Likewise. (update_window_title): Append " (modified)" to the window title if appropriate. If there is no game name and no associated file, set window title to "Unnamed Game". (fetch_comment_if_changed): Mark SGF collection as modified after the change. Also take care to notice if the comment has not been changed. (move_has_been_played): Mark SGF collection as modified after the change. (player_is_out_of_time): Likewise. 2005-03-05 Paul Pogonyshev * gui-gtk/gtk-goban-window.c (gtk_goban_window_init): Add "Recenter on Current Node" menu item in "View" menu. Desensitize it if game tree view is not shown right away. (do_find_text): Don't assert for `text_to_find', call show_find_dialog() if it is not set. (game_info_dialog_property_changed): Call update_window_title() when `SGF_GAME_NAME' property is changed. (show_or_hide_sgf_tree_view): Sensitize/desensitize "Recenter on Current Node" menu item depending on `sgf_tree_view' visibility. Recenter `sgf_tree_view' after showing it. (recenter_sgf_tree_view): New function. (update_player_information): Standardize function prototype and compute SGF property types from `player_color' argument. * gui-gtk/gtk-sgf-tree-view.c (gtk_sgf_tree_view_style_set): New function. (gtk_sgf_tree_view_center_on_current_node): New function. (track_current_node): Use update_view_port_and_maybe_move_or_resize_window(). (center_on_current_node): New function, break out of track_current_node(). (update_view_port_and_maybe_move_or_resize_window): Always call gtk_widget_queue_draw() for now. (about_to_modify_map): Don't do anything if the view's widget is not realized. (about_to_change_current_node): Likewise. (current_node_changed): Likewise. (map_modified): Likewise. * sgf/sgf-tree-map.c (update_internal_view_port): Allocate one more SgfGameTreeMapLine, because do_update_internal_view_port() can write there without advancing the pointer. (update_internal_view_port): Add another skipping optimization. * sgf/sgf-tree.c (sgf_game_tree_delete): Call sgf_game_tree_invalidate_map() before deleting all nodes to avoid accessing freed memory. 2005-03-02 Paul Pogonyshev * gui-gtk/gtk-resume-game-dialog.c (guess_engine_by_player_name): Don't crash if `player_name' is NULL, just return NULL. 2005-03-01 Paul Pogonyshev * gui-gtk/gtk-sgf-tree-view.c (SHOULD_TRACK_CURRENT_NODE): New macro, broken out of gtk_sgf_tree_view_update_view_port(). (gtk_sgf_tree_view_realize): Only request events for the `output_window' to avoid unnecessary exposures. (gtk_sgf_tree_view_expose): Use precomputed tile maps for drawing. (gtk_sgf_tree_view_unrealize): Free tile maps. (gtk_sgf_tree_view_set_sgf_tree): Hook up handlers to GtkSgfTreeSignalProxy signals. (gtk_sgf_tree_view_update_view_port): Don't try to track current node (it's buggy here since the map might have changed.) (track_current_node): New function, broken out of gtk_sgf_tree_view_update_view_port(). (update_view_port): Compute tile maps based on result of sgf_game_tree_fill_map_view_port() and sgf_game_tree_get_current_branch_marks(). (about_to_modify_map, about_to_change_current_node) (current_node_changed, map_modified): New functions; track current node here. * gui-gtk/gtk-goban-window.c (set_current_tree): Attach a GtkSgfTreeSignalProxy to the tree. (sgf_tree_view_clicked): Don't call gtk_sgf_tree_view_update_view_port(). (update_children_for_new_node): Likewise. (move_has_been_generated): Likewise. * gui-gtk/gtk-sgf-tree-signal-proxy.h: New file. * gui-gtk/gtk-sgf-tree-signal-proxy.c: New file. * gui-gtk/quarry-marshal.list: New marshaller `VOID:POINTER,POINTER'. * sgf/sgf-utils.c (DO_NOTIFY): New macro. (sgf_utils_go_down_in_tree): Send `about-to-change-current-node' and `current-node-changed' notifications. (sgf_utils_go_up_in_tree): Likewise. (sgf_utils_switch_to_variation): Likewise. (sgf_utils_switch_to_given_variation): Likewise. (sgf_utils_switch_to_given_node): Likewise. (sgf_utils_append_variation): Send various notifications. (sgf_utils_set_node_is_collapsed): Send `about-to-modify-map' and `map-modified' notifications. 2005-02-26 Paul Pogonyshev * sgf/sgf-tree.c (sgf_game_tree_new): Initialize new `notification_callback' field; don't initialize removed `free_user_data'. (sgf_game_tree_delete): Send deletion notification. Don't use removed `free_user_data'. (sgf_game_tree_set_user_data): Remove function. (sgf_game_tree_set_notification_callback): New function. 2005-01-28 Paul Pogonyshev * gui-gtk/gtk-progress-dialog.c: Don't comment it out when `THREADS_SUPPORTED' is false, the widget is usable either way. Compiling without threads was impossible because of this. 2005-01-25 Paul Pogonyshev * quarry.c: Update copyright string. * gui-gtk/gtk-goban-window.c (show_about_dialog): Likewise. 2005-01-22 Paul Pogonyshev * gui-gtk/gtk-goban-window.c (gtk_goban_window_init): Add "Resume Game" and "Close" items in "File" menu and "Adjourn Game" in "Play" menu. Change mnemonic for "New Game" item and use "Ctrl+N" shortcut for it. (gtk_goban_window_resume_game): New function. (do_enter_game_mode): New function, break out of gtk_goban_window_enter_game_mode(). (leave_game_mode): Fix copy'n'paste bug (`BLACK_INDEX' => `WHITE_INDEX'), caused segmentation faults. (gtk_goban_window_save): Handle game adjourning. Use new suggest_filename() function for providing default filename in dialog. (suggest_filename): New function. (save_file_as_response): Handle game adjourning. (game_has_been_adjourned): New function. (free_handicap_mode_done): Call free_handicap_has_been_placed() after leave_special_mode(), the latter changes the SGF tree. (go_scoring_mode_done): Call reenter_current_node() after leave_special_mode() for the same reason. (play_pass_move): Call update_children_for_new_node() after move_has_been_played() for the same reason. (resign_game): Rename from play_resign(). Call update_children_for_new_node() after move_has_been_played(). (navigate_goban): Don't do anything if the window is in a special mode. (update_window_title): Remove `game_info_node' argument. (update_game_specific_information): Make `goban_window' argument `const'. (update_move_information): Likewise. (update_commands_sensitivity): New function, break out from update_children_for_new_node(). Set sensitivity of "Adjourn Game" menu item. Desensitize navigation commands when in special mode. (initialize_gtp_player): Don't ask GTP engine to place free handicap stones when `pending_free_handicap' is zero (when resuming games.) (enter_scoring_mode): Call new update_commands_sensitivity() function. (move_has_been_generated): Call update_children_for_new_node() after move_has_been_played(). * gui-gtk/gtk-resume-game-dialog.c: New file. * gui-gtk/gtk-resume-game-dialog.h: New file . * gui-gtk/gtk-preferences.c (gtk_preferences_init): Create filtered models for each supported games (GTK+ 2.4+ only.) (gtk_preferences_create_engine_selector): Add `only_this_game' argument. (gtk_preferences_set_engine_selector_game_index): Assert that the selector is not one-game-only. (gtk_preferences_set_engine_selector_selection): Make `engine_data' argument `const'. Handle one-game-only selectors. (gtk_preferences_get_engine_selector_selection): Handle one-game-only selectors. (engine_is_visible_and_supports_game): New function. (build_and_attach_menu): Handle one-game-only selectors. * gui-gtk/gtk-utils.c (do_align_left_widget): Handle boxes inside other boxes more intelligently. * gui-gtk/gtk-games.c (gtk_games_get_game_index): New function. * utils/utils.c (utils_parse_double): Allow `result' to be NULL (for simple value validation.) 2005-01-21 Paul Pogonyshev * gui-gtk/gtk-parser-interface.c (gtk_parser_interface_present_default): New function, to use in place of old calls to gtk_parser_interface_present(). (gtk_parser_interface_present): Add `title' and `callback' arguments. Use gtk_window_present() instead of gtk_widget_show(). (open_file_response): Add `callback' argument. (open_game_record): New function, break out of analyze_parsed_data() (or gtk_parse_sgf_file() for non-threading version.) Use gtk_window_present() instead of gtk_widget_show(). (gtk_parse_sgf_file): Add `callback' argument. Make `filename' always absolute. (analyze_parsed_data): Call `callback' that should deal with parsed data (default callback is open_game_record().) (gtk_parse_sgf_file): (Non-threading version) Same as for threading version. Also make compilable. * gui-gtk/gtk-control-center.c (gtk_control_center_present): Add "Resume Game" button. Reduce spacing between button groups. * gui-gtk/gtk-goban-window.c (gtk_goban_window_save): Take care to use UTF-8 for widgets/output and file system encoding for everything else in filenames. (update_window_title): Likewise. * gui-gtk/gtk-parser-interface.c (gtk_parse_sgf_file): Likewise. (analyze_parsed_data): Likewise. * gui-gtk/gtk-utils.c (file_selection_response): Likewise. (browse_button_clicked): Likewise. (browsing_dialog_response): Likewise. 2005-01-19 Paul Pogonyshev * gui-gtk/gtk-new-game-dialog.c (update_game_and_players_page): Use gtk_preferences_have_non_hidden_gtp_engine() to determine if there are computer opponents available. * gui-gtk/gtk-preferences.c (gtk_preferences_init): Add `ENGINES_IS_VISIBLE' column to tree model. Recompute engine names based on `screen_name' fields. For GTK+ 2.4+ create a filtered model based on this column. (create_gtp_engines_page): Add "Show" column to the list. Fix "Support game(s):" label. Create a label for displaying additional information. (gtk_preferences_dialog_update_gtp_engine_info): Don't allow removing engines coming from site configuration. Show whether engine is coming from there in additional label. (show_or_hide_gtp_engine): New function. (do_remove_gtp_engine): Use gtk_preferences_have_non_hidden_gtp_engine(). (gtk_preferences_have_non_hidden_gtp_engine): New function. (gtk_preferences_create_engine_selector): Use filtered model for GTK+ 2.4+ to exclude hidden engines. (gtk_preferences_set_engine_selector_selection): Take hidden engines into account. (gtk_preferences_get_engine_selector_selection): Likewise. (build_and_attach_menu): Likewise. (update_engine_screen_name): Add `update_tree_model' argument. * gui-gtk/gui-back-end.c (initialize_main_loop): Read site configuration file if the user doesn't have any configuration yet. * gui-utils/common-configuration-values.list: Add values for tracking site configuration and hidden engines to `gtp_engine_section_values'. * gui-utils/common-configuration-defaults.list: Likewise. * gui-utils/configuration.c (configuration_read_from_file): Support new `VALUE_TYPE_BOOLEAN_WRITE_TRUE_ONLY' value type. (write_section): Likewise. (configuration_init_repeatable_section): New function. * gui-utils/parse-configuration.c (configuration_parse_values2): Support new `VALUE_TYPE_BOOLEAN_WRITE_TRUE_ONLY' value type. (configuration_parse_defaults2): Likewise. (add_field_declaration_if_needed): Likewise. (look_at_field_type): New function. * utils/string-list.c (string_list_dispose_item) (string_list_steal_item, string_list_steal_first_item): New functions. 2005-01-18 Paul Pogonyshev * gui-gtk/gtk-goban-window.c (leave_game_mode): New function. (do_resign_game): Call leave_game_mode(). (move_has_been_played): Call time_control_*() functions itself, GtkClock doesn't do it anymore. Call leave_game_mode() if the move is too late or if the game ends normally. (move_has_been_generated): Ignore move when not in game mode. (start_clock_if_needed): Call time_control_start(). (player_is_out_of_time): New function. * gui-gtk/gtk-clock.c (gtk_clock_init): Initialize all fields. (gtk_clock_realize): Call set_background_pixmap(). (set_background_pixmap): New function. (gtk_clock_finalize): Don't assume that GLib event source exists if `time_control' is set. (gtk_clock_start, gtk_clock_stop) (gtk_clock_initialize_for_time_control, clock_set_time): Remove functions. (gtk_clock_set_time, gtk_clock_use_time_control) (gtk_clock_time_control_state_changed) (fetch_time_from_time_control, do_set_time, ensure_clock_size) (clock_tick_callback):New functions, partially inherit removed code. (time_control_watch_prepare, time_control_watch_check) (time_control_watch_dispatch) (time_control_watch_source_set_tick_time): New functions. * gui-utils/time-control.c (time_control_get_time_till_seconds_update) (time_control_is_short_on_time): New functions. 2005-01-17 Paul Pogonyshev * gui-gtk/gtk-goban-window.c (gtk_goban_window_save): Don't show warning about potential information loss. * sgf/sgf-writer.c (write_game_tree): Write `ST' property value, if set. (sgf_write_list_of_vector): Implement. (sgf_write_figure_description): New function. * sgf/sgf-parser.c (sgf_parse_constrained_number): Also handle `PM' property. (sgf_parse_list_of_point): Use end_parsing_value() instead of next_token_in_value() so that whitespaces is warned about. (sgf_parse_list_of_vector): Implement. (sgf_parse_list_of_label): Treat non-composite values as values with empty label. (sgf_parse_figure): Implement. (sgf_parse_print_mode): Remove function. (sgf_parse_style): Implement. * sgf/sgf-errors.list (SGF_WARNING_DUPLICATE_VECTOR) (SGF_ERROR_ZERO_LENGTH_VECTOR, SGF_WARNING_UNKNOWN_FLAGS) (SGF_ERROR_FIGURE_FLAGS_EXPECTED, SGF_WARNING_UNKNOWN_PRINT_MODE): New error strings. * sgf/sgf-properties.list (ST): Use `not_stored' storage type. (FG): Change storage type to `figure_description'. (PM): Use `sgf_parse_constrained_number' as value parser. * sgf/sgf-tree.c (sgf_game_tree_new): Initialize new `style_is_set' field. (sgf_game_tree_duplicate): Copy `style' field only if it is set. (sgf_node_get_list_of_label_property_value): New function. (sgf_node_add_pointer_property): Handle values of `SGF_FIGURE_DESCRIPTION' type. (sgf_property_duplicate): Handle values of `SGF_LIST_OF_VECTOR' and `SGF_FIGURE_DESCRIPTION' types. (free_property_value): Handle `SGF_FIGURE_DESCRIPTION' value type. (SGF_VECTOR_LIST_DEFAULT_INITIAL_SIZE) (SGF_VECTOR_LIST_SIZE_INCREMENT): New macros. (sgf_vector_list_new, sgf_vector_list_shrink) (sgf_vector_list_add_vector, sgf_vector_list_has_vector) (sgf_vector_list_duplicate, sgf_figure_description_new) (sgf_figure_description_duplicate) (sgf_figure_description_delete): New functions. * sgf/sgf.h (sgf_vector_list_delete): New macro. 2005-01-15 Paul Pogonyshev * (Quarry version 0.1.12.) * sgf/sgf-tree-map.c (VIEW_PORT_NODE, VIEW_PORT_LINE_ADJUSTMENT): New macros. (sgf_game_tree_get_current_branch_marks): New function. (sgf_game_tree_node_is_within_view_port): Bug-fix: don't assume that the requested view port dimensions match internal view port. (update_internal_view_port): Check if internal view port already contains necessary data (was previously checked at higher level.) (do_update_internal_view_port): Bug-fix: remove primary tree line storage out of the `for' loop, could cause serious memory corruption (bug #1969, Arend Bayer.) * sgf/sgf-utils.c (do_enter_tree): Adjust new `current_node_depth' field according to changes of `current_node'. (descend_nodes): Likewise. (ascend_nodes): Likewise. * sgf/sgf-tree.c (sgf_game_tree_new): Initialize new `current_node_depth' field. (sgf_game_tree_set_state): Also save `current_node_depth'. Change prototype and don't return old state. (sgf_game_tree_get_state): New function, break out of sgf_game_tree_set_state(). 2005-01-06 Paul Pogonyshev * (Quarry version 0.1.11.) * gui-gtk/gtk-goban-window.c (gtk_goban_window_init): Maximize the window by default. (sgf_tree_view_clicked): New function. * gui-gtk/gtk-utils.c (gtk_utils_set_sensitive_on_toggle): Add `reverse_meaning' argument. (set_widget_sensitivity_on_toggle_reversed): New function. * gui-gtk/gtk-preferences.c (create_game_tree_page): Add controls for tracking current node configuration parameters. (store_radio_button_setting): Bug-fix: radio button groups are in reverse-creation order, cope with that. Use library functions. (update_markup_theme_defaults_usage): Always initialize `use_theme_defaults'. * gui-utils/common-configuration-sections.list: Rename "Editing and Viewing" section to "Game Tree View". * gui-utils/common-configuration-values.list: Add values for whether to track current node in the game tree view. * gui-utils/common-configuration-defaults.list: Likewise. Also change the default for `show_game_tree' to `SHOW_GAME_TREE_AUTOMATICALLY'. * gui-gtk/gtk-sgf-tree-view.c (gtk_sgf_tree_view_class_init): Add integer `button_index' argument to "sgf-tree-view-clicked" signal. (gtk_sgf_tree_view_init): Don't call gtk_goban_base_set_game(). Initialize new `map_width' and `map_height' fields. (gtk_sgf_tree_view_realize): Call sgf_game_tree_get_map_dimensions() instead of update_view_port(). (gtk_sgf_tree_view_size_request): Base size request on internal `map_width' and `map_height' fields. (gtk_sgf_tree_view_expose): Draw a cross over collapsed nodes. (gtk_sgf_tree_view_button_press_event) (gtk_sgf_tree_view_button_release_event): Also pass on right button clicks. (gtk_sgf_tree_view_unrealize): Free view port data. (gtk_sgf_tree_view_finalize): Don't free view port (unneeded.) (gtk_sgf_tree_view_set_sgf_tree): Don't call removed sgf_game_tree_activate_map(); call gtk_goban_base_set_game(). (gtk_sgf_tree_view_update_view_port): Scroll view port as needed when tracking the current node. (configure_adjustment): Use `map_width' and `map_height'. (update_view_port_and_maybe_move_or_resize_window): Make `original_hadjustment_value' and `original_vadjustment_value' arguments. Replace first call to update_view_port() with a call to sgf_game_tree_get_map_dimensions(). Request full redraw if window size changes. * gui-gtk/quarry-marshal.list: New marshaller `VOID:POINTER,INT'. * sgf/sgf-utils.c (sgf_utils_append_variation): Pass `tree->current_node' to sgf_game_tree_invalidate_map(). (sgf_utils_set_node_is_collapsed): New function. * sgf/sgf-tree-map.c (REPORT_PERFORMANCE_STATISTICS): Rename macro from `PRINT_RUN_TIMES'. (DECLARE_TIME_VARIABLES, STORE_STARTING_TIME, PRINT_RUN_TIME) (MIN_NODES_PER_DATA_CHUNK): New macros. (sgf_game_tree_activate_map, sgf_game_tree_deactivate_map): Remove functions. (sgf_game_tree_invalidate_map): Add `node' parameter and rewrite to handle new intermediate data. (sgf_game_tree_get_map_dimensions): New function. (sgf_game_tree_fill_map_view_port): Rename from sgf_game_tree_update_view_port(). (sgf_game_tree_get_node_coordinates) (sgf_game_tree_node_is_within_view_port) (find_intermediate_data_for_node, view_port_is_after_data_point) (view_port_is_before_data_point, free_map_data_point) (update_internal_map_data): New functions. (update_internal_view_port): Optimize for speed capitalizing on data stored by update_internal_map_data(). (do_update_internal_view_port): Break out of update_internal_view_port(). (get_node_coordinates): New function. 2005-01-03 Paul Pogonyshev * sgf/sgf-tree.c (sgf_game_tree_new): Initialize new `map_data_list' field. (sgf_game_tree_delete): Call sgf_game_tree_invalidate_map() to free all memory allocated for the map. (sgf_node_new): Initialize new `has_intermediate_map_data' field. 2004-12-31 Paul Pogonyshev * gui-gtk/gtk-goban-base.c (gtk_goban_base_unrealize): Call parent's method. 2004-12-30 Paul Pogonyshev * board/board.c (board_position_list_union): Rewrite to avoid accessing unallocated memory in some cases (bug #1929, warped_dragon@hotmail.com.) * gui-gtk/gtk-goban-window.c (move_has_been_played): Add time control information to the game SGF tree. * gui-gtk/gtk-new-game-dialog.c (begin_game): Add information about game time limits to the game SGF tree. * sgf/sgf-properties.list: Sort `TM' property before 'OT'. (MN, OB, OW): Use `sgf_parse_constrained_number' as value parser. * sgf/sgf-parser.c (parse_buffer): Reset new `data->ko_property_error_position.line' field. Delete error lists when parsing failed with `SGF_INVALID_FILE'. (complete_node_and_update_board): Add error if there is `KO' property, but no move in the node. Split nodes with setup properties and `MN' mixed. (sgf_parse_none): Store error position if parsing `KO' property. (sgf_parse_constrained_number): New function. (sgf_parse_move_number, sgf_parse_moves_left): Remove functions. (insert_error_valist): Bug-fix: store line and column in the inserted item, not in the last. * sgf/sgf-errors.list (SGF_ERROR_KO_PROPERTY_WITHOUT_MOVE): New error string. * utils/string-list.c (string_list_insert): Return the inserted item. (string_list_insert_from_buffer): Likewise. (string_list_insert_ready): Likewise. (string_list_insert_ready_item): Likewise. * sgf/sgf-tree.c (sgf_node_find_property): Allow `link' to be NULL. 2004-12-29 Paul Pogonyshev * gui-gtk/gtk-parser-interface.c (analyze_parsed_data): Cast `data->parent' to GtkWindow type only when non-NULL. If there is no parent window, make error dialog non-modal and register it with gtk_control_center_window_created(). (gtk_parse_sgf_file): Likewise. Also fix for changed gtk_utils_create_message_dialog() prototype. * sgf/sgf-tree-map.c (update_internal_view_port): Fix bug that caused overlapping branches in rare cases (reported by Arend Bayer.) 2004-12-25 Paul Pogonyshev * gui-gtk/gtk-preferences.c (update_board_markup_theme): Bug-fix: duplicate theme name, don't just copy the pointer. * gui-gtk/gtk-sgf-tree-view.c (gtk_sgf_tree_view_realize): Call parent class method. * gui-gtk/gtk-goban.c (gtk_goban_set_parameters): Don't emit `appearance-changed' signal. (gtk_goban_realize): Call parent class method. (gtk_goban_size_allocate): Don't calculate stones and SGF markup margins. (gtk_goban_expose): Use new compute_goban_margins() function. (gtk_goban_appearance_changed): Remove function. (gtk_goban_allocate_screen_resources) (gtk_goban_free_screen_resources): New functions, inherit code of removed gtk_goban_base_appearance_changed(). (gtk_goban_finalize): Don't unreference `small_tile_set'. (gtk_goban_update): Use compute_goban_margins(). (set_overlay_data): Likewise. (compute_goban_margins): New function. * gui-gtk/gtk-goban-base.c (gtk_goban_base_class_init): Create `allocate-screen-resources' and `free-screen-resources' signals; don't create `appearance-changed' signal. (gtk_goban_base_realize, gtk_goban_base_unrealize): New functions. (gtk_goban_base_appearance_changed): Remove function. (gtk_goban_base_allocate_screen_resources) (gtk_goban_base_free_screen_resources): New functions, inherit code of removed gtk_goban_base_appearance_changed(). (gtk_goban_base_finalize): Don't unreference tile sets here. (gtk_goban_base_update_appearance): Emit the new signals, not `appearance-changed' and only if the widget is realized. (gtk_goban_base_set_cell_size): Likewise. * gui-gtk/gtk-assistant.c (gtk_assistant_update_buttons): Workaround GTK+ 2.0 problem that caused annoying warnings in some cases. * quarry.c (main): Parse command line after gui_back_end_init() is called so that GTK+/GLib options are not seen by getopt_long(). * gui-gtk/gtk-goban-window.c (gtk_goban_window_init): Add "New Game" and "Control Center" menu items. (save_file_as_response): Call update_window_title() when saving to a (different) file. (show_or_hide_navigation_toolbar): Fix copy'n'paste bug: use `show_navigation_toolbar' field, not `show_main_toolbar' one. (update_window_title): When there is no game name, try to create window title from use players' names. Set window title even if there's no base name. (initialize_gtp_player): Return 1 to indicate no error to the GTP client module. * gtp/gtp-client.c (parse_final_status_list): Take care to signal error only if the list is badly formatted. * gui-gtk/gtk-gtp-client-interface.c (log_gtp_stream_error): Don't assume that there is a log file, errors are reported regardless of GTP client's echo status. * gui-gtk/gtk-goban.c (gtk_goban_size_allocate): Fix bug with cell size calculation that occured when the resulting font was larger than requested (reported by Arend Bayer.) 2004-12-24 Paul Pogonyshev * gui-gtk/gtk-gtp-client-interface.c (gtk_create_gtp_client): Handle GTP debugging options: hook up necessary callbacks, create pipe and IO channel for child's stderr etc. (handle_engine_stderr, log_gtp_stream, log_gtp_stream_error): New functions. (client_deleted): Close stderr channel and log file if necessary. * gtp/gtp-client.c (gtp_client_grab_response): Report errors before response lines. Properly ignore empty lines between responses. (dispatch_response): Send an empty line to `line_callback' after any potential error. (store_protocol_version): Send a warning about future GTP version. * quarry-main.h: New file. * quarry.c (main): Parse command line. Add `--gtp-log', `--gtp-show-stderr', `--help', `--usage' and `--version' options. 2004-12-23 Paul Pogonyshev * board/amazons.c (amazons_parse_move): Also parse moves in A1-B2/C3 and A1-B2xC3 formats (wish #1952, emarkus@cs.ualberta.ca.) 2004-12-22 Paul Pogonyshev * sgf/sgf-parser.c (sgf_parse_list_of_label): When combining label lists ensure that the old list's text strings are not freed as we reuse them (bug reported by Arend Bayer.) 2004-12-11 Paul Pogonyshev * gui-gtk/gtk-preferences.c: Add "Game Tree" category. (create_saving_sgf_page): New function. (create_markup_box): Alter layout to reflect changes in theme default usage policy. Remove two buttons and add a check button. (gtk_preferences_dialog_response): Handle `PREFERENCES_PAGE_GAME_TREE'. (update_board_background_texture): New function. (update_board_appearance): Remove accidental code duplication. (update_board_markup_theme): Rename from update_board_markup(). (use_theme_default_size, use_theme_default_opacity): Remove functions. (update_markup_theme_defaults_usage): New function. * gui-gtk/gtk-utils.h (gtk_utils_block_signal_handlers) (gtk_utils_unblock_signal_handlers): New macros. * gui-gtk/gtk-tile-set.c (gtk_sgf_markup_tile_set_create_or_reuse): Adapt to new theme defaults usage scheme. * gui-utils/common-configuration-values.list: Add "Use theme defaults" value. Add previously forgotten "Markup theme" value to `amazons_board_appearance_values' * gui-utils/common-configuration-defaults.list: Likewise for `use_theme_defaults' * sgf/sgf-tree-map.c (sgf_game_tree_update_view_port): Fix `if' condition, don't call update_internal_view_port() when not needed. * gui-gtk/gtk-goban-window.c (gtk_goban_window_init): Add "Game Tree" check menu item. Don't pack `sgf_tree_view's parent widget to `vpaned' unless configured to always show game tree view. Initialize new `sgf_tree_view_visibility_locked' field. (gtk_goban_window_enter_game_mode): Never hide clocks. (gtk_goban_window_destroy): Unreference `sgf_tree_view's parent. (show_or_hide_sgf_tree_view, show_sgf_tree_view_automatically): New functions. (set_current_tree): When configured to show game tree view automatically, show/hide it depending on whether the new tree has any variations. But respect `sgf_tree_view_visibility_locked', set by show_or_hide_sgf_tree_view() when invoked from menu. (update_children_for_new_node): Call show_sgf_tree_view_automatically() for `current_node'. (update_game_information): Never hide players' information. (update_player_information): Set return type to `void'. (move_has_been_generated): Call show_sgf_tree_view_automatically() for `game_position_node'. 2004-12-10 Paul Pogonyshev * gui-utils/common-configuration-sections.list: Add configuration parameter for whether and when to show game tree view. * gui-utils/common-configuration-values.list: Likewise. * gui-utils/common-configuration-defaults.list: Likewise. * gui-utils/configuration.c (configuration_read_from_file): Add support for `enumeration' value type. (parse_integer): New function, broken out of configuration_read_from_file(). (write_section): Add support for `enumeration' value type. * gui-utils/parse-configuration.c (configuration_parse_sections2): Adjust output to follow modified (see `ChangeLog' entry of 12 October) coding convention. (configuration_parse_values2): Likewise. (configuration_parse_defaults2): Likewise. (configuration_finalize_defaults): Likewise. (add_field_dispose_call_if_needed): Likewise. (finish_function): Likewise. (configuration_initialize_sections): Save `c_file_array_name' on the heap, don't write to `h_file_bottom' yet. (configuration_parse_values2): Add support for `enumeration' value type. (configuration_initialize_defaults): Perform write to `h_file_bottom' delayed in configuration_initialize_sections(). (configuration_parse_defaults2): Add support for `enumeration' value type. (configuration_parse_defaults2): Likewise. (add_field_declaration_if_needed): Likewise. * gui-gtk/gtk-sgf-tree-view.c (gtk_sgf_tree_view_size_allocate): Remove debugging leftover. (gtk_sgf_tree_view_expose): Only draw if the widget is realized, not if `current_tree' is set. Implement line clipping to workaround X drawing problems with very long lines (over 32K.) (gtk_sgf_tree_view_update_view_port): Do nothing if widget is not realized. 2004-12-09 Paul Pogonyshev * gui-gtk/gtk-goban-window.c (gtk_goban_window_init): Add an GtkSgfTreeView to the sidebar. (set_current_tree): Inform `sgf_tree_view' about the change. (switch_to_given_node): New function. (update_children_for_new_node): Force `sgf_tree_view' view port update. (move_has_been_generated): Likewise if not displaying game node. * sgf/sgf-utils.c (sgf_utils_append_variation): Call new function sgf_game_tree_invalidate_map(). * gui-gtk/gtk-sgf-tree-view.c, gui-gtk/gtk-sgf-tree-view.h: New files. * gui-gtk/quarry-marshal.list: New marshaller `VOID:OBJECT,OBJECT'. * sgf/sgf-parser.c (complete_node_and_update_board): Make last change work. 2004-12-08 Paul Pogonyshev * utils/utils.c (utils_realloc): Don't choke if `realloc (..., 0)' returns NULL. * sgf/sgf-tree-map.c: New file. * sgf/sgf-tree.c (sgf_game_tree_new): Initialize new `user_data', `free_user_data', `map_width', `view_port_nodes' and `view_port_lines' fields. (sgf_game_tree_delete): Free `user_data' (if necessary), `view_port_nodes' and `view_port_lines' fields. (sgf_game_tree_set_user_data): New function. (sgf_node_new): Initialize new `is_collapsed' field. 2004-12-06 Paul Pogonyshev * gui-gtk/gtk-preferences.c (update_board_background_texture): Use gtk_goban_base_update_appearance() instead of gtk_goban_update_appearance(). (update_board_markup): Likewise. (update_board_appearance): Likewise. * gui-gtk/gtk-goban.c (gtk_goban_get_type): Descend from GtkGobanBase, not GtkWidget. (gtk_goban_set_parameters): Use new function gtk_goban_base_set_game() and `appearance-changed' signal. (gtk_goban_size_allocate): Use new function gtk_goban_base_set_cell_size(). Be a nice inherited method and call parent's method instead of doing everything itself. (unreference_cached_objects, set_goban_style_appearance) (gtk_goban_appearance_changed): Remove functions (part of functionality went to `gui-gtk/gtk-goban-base.c'.) (gtk_goban_appearance_changed): New function (inherit most of set_goban_non_style_appearance() functionality.) (gtk_goban_update_appearance): Remove function (functionality inherited by gtk_goban_base_update_appearance().) * gui-gtk/gtk-goban-base.c, gui-gtk/gtk-goban-base.h: New files (part of `gui-gtk/gtk-goban.c' fuctionality.) 2004-11-30 Paul Pogonyshev * (Quarry version 0.1.10.) 2004-11-29 Paul Pogonyshev * gui-gtk/gtk-help.c (gtk_help_display): Don't try to launch Yelp if ScrollKeeper wasn't found on configure stage. 2004-11-26 Paul Pogonyshev * gui-gtk/gtk-goban-window.c (IS_IN_SPECIAL_MODE): New macro. (gtk_goban_window_init): Use `GTK_STOCK_PROPERTIES'es shortcut and icon for "Game Information" menu item. Add "View" sub-menu. Rearrange "Go" sub-menu items so that "previous"-like items always go before "next"-like. (gtk_goban_window_init): Add main and navigation toolbars. Add "Pass" and "Resign" buttons to the sidebar. Tweak sidebar spacing. (gtk_goban_window_enter_game_mode): Call update_children_for_new_node() since result of USER_CAN_PLAY_MOVES() might change. Bug-fix: don't start user's clock if the user is setting free handicap. (show_or_hide_main_toolbar, show_or_hide_navigation_toolbar) (show_or_hide_game_action_buttons): New functions. (set_current_tree): Show or hide "Pass" button depending on game. (play_resign): Ask user if she really wants to resign first. (do_resign_game): New function, broken out of play_resign(). (update_children_for_new_node): Also sensitize/desensitize toolbar buttons and game action buttons. Make "Pass" and "Resign" menu items and buttons insensitive when in special mode. (move_has_been_played): ReSet `in_game_mode' if game is over. (move_has_been_generated): Use do_resign_game() instead of play_resign(). * gui-gtk/gtk-configuration.list: Add "GTK+ User Interface" section. * gui-utils/configuration.c (IS_ACCEPTABLE_NAME_CHARACTER): New macro. (configuration_read_from_file): Use IS_ACCEPTABLE_NAME_CHARACTER(). This allows digits, hyphen, plus sign and apostrophe in names, in addition to digits accepted before. * utils/string-buffer.c (string_buffer_vcprintf): Bug-fix: increase string length also when buffer reallocation is needed. 2004-11-25 Paul Pogonyshev * gui-gtk/gtk-utils.c (gtk_utils_append_toolbar_button) (invoke_toolbar_button_callback) (gtk_utils_set_toolbar_buttons_sensitive) (set_toolbar_item_sensitive): New functions. 2004-11-24 Paul Pogonyshev * gui-gtk/gtk-goban-window.c (play_resign): Bug-fix: don't stop the clock if we don't have a time control in the first place. 2004-11-15 Paul Pogonyshev * gui-utils/configuration.c (configuration_read_from_file): Don't segfault on certain malformed input. (parse_string): Respect comments starting with '#' symbol (this will break old configuration files with custom colors.) (write_section): Write colors enclosed in quotes, because they contain '#' symbol. * sgf/sgf-tree.c (sgf_node_split): Bug-fix: set `node->move_color' to `EMPTY' since the move is moved to the child node. * sgf/sgf-parser.c (complete_node_and_update_board): Bug-fix: remove `PL' properties that have no effect, not those changing color to move. 2004-11-14 Paul Pogonyshev * gui-gtk/gtk-goban-window.c (do_find_text): Scroll text view so that the found text is always visible. 2004-10-20 Paul Pogonyshev * gui-gtk/gtk-goban.c (gtk_goban_expose): Only use draw_horizontal_line_with_gaps() and draw_vertical_line_with_gaps() for Go, not other games. Draw labels on black stones using white color. Don't draw last move indicator over SGF labels. * gui-gtk/gtk-configuration.list: Add "Find Dialog Parameters" section. * gui-gtk/gtk-goban-window.c (gtk_goban_window_init): Add "Find", "Find Next" and "Find Previous" menu items. Initialize new `find_dialog' and `text_to_find' fields. (gtk_goban_window_finalize): Free `text_to_find' and destroy `find_dialog' (if present.) (show_find_dialog, find_dialog_response) (find_dialog_parameters_changed, do_find_text) (strstr_whole_word, strrstr_whole_word) (char_is_word_constituent, get_normalized_text) (get_offset_in_original_text): New functions. (about_to_change_node, just_changed_node): New functions, broken out of navigate_goban(). (playing_mode_goban_clicked): Bug-fix: invoke new about_to_change_node() and just_changed_node() when switching variations on right button click (could lead to game tree corruption when playing a game.) (update_move_information): Bug-fix: only call sgf_node_get_result() if there is a game-info node in the first place. * sgf/sgf-utils.c (sgf_utils_switch_to_given_node): New function. 2004-10-19 Paul Pogonyshev * gui-gtk/quarry-stock.c: New stock item `QUARRY_STOCK_PREVIOUS'. * sgf/sgf-tree.c (sgf_game_tree_traverse_forward) (sgf_game_tree_traverse_backward, sgf_node_traverse_forward) (sgf_node_traverse_backward): New functions. * gui-gtk/gtk-control-center.c (gtk_control_center_destroy): Remove function, use gtk_utils_null_pointer_on_destroy() instead. * gui-gtk/gtk-goban-window.c (save_file_as_destroy): Likewise. (game_info_dialog_destroyed): Likewise. (about_dialog_destroy): Likewise. * gui-gtk/gtk-preferences.c (gtk_preferences_dialog_destroy): Likewise. * gui-gtk/gtk-utils.c (gtk_utils_null_pointer_on_destroy) (null_pointer_on_destroy) (null_pointer_on_destroy_ask_control_center): New functions. * gui-gtk/gtk-goban-window.c (show_about_dialog): Fix copyright string (add year 2003.) Center-justify copyright label. Use `GTK_RESPONSE_CANCEL' for the "Close" button, so that the dialog can be closed with Escape. 2004-10-18 Paul Pogonyshev * gui-gtk/gtk-goban.c (gtk_goban_set_parameters): Update goban's hoshi points using new go_get_hoshi_points() function. (gtk_goban_size_allocate): Don't touch hoshi points here. (gtk_goban_expose): Use new draw_vertical_line_with_gaps() and draw_horizontal_line_with_gaps() to draw all lines. Don't draw hoshi points over SGF labels. (draw_vertical_line_with_gaps, draw_horizontal_line_with_gaps): New functions. (gtk_goban_finalize): Free overlay data, don't leak memory. (gtk_goban_update): Adjust `rectangle_sgf_label' so that label gaps get redrawn properly. (find_hoshi_points): Remove function. * board/go.c (go_get_hoshi_points): New function, inherit code of removed find_hoshi_points() in `gui-gtk/gtk-goban.c'. * gui-gtk/gtk-new-game-dialog.c (begin_game): Bug-fix: duplicate "Void" string before passing it to sgf_node_add_text_property(). * gui-gtk/gtk-utils.c (time_spin_button_output): Use utils_ncprintf() once more: now it knows about field width. * utils/utils.c (utils_vncprintf): Add support for field width This is an indirect bug-fix for write_section() in `gui-utils/configuration.c', it used to write time incorrectly. 2004-10-14 Paul Pogonyshev * (Quarry version 0.1.9.) * gui-gtk/gtk-utils.c (freeze_on_empty_input): Use gtk_freezable_spin_button_freeze_and_stop_input(). * gui-gtk/gtk-freezable-spin-button.c (gtk_freezable_spin_button_init): Reset new `is_in_output' field. (gtk_freezable_spin_button_new): Connect also to `input' signal. (gtk_freezable_spin_button_output): Set `is_in_output' while changing entry's text. (gtk_freezable_spin_button_input): New function. (gtk_freezable_spin_button_changed): Bug-fix: only unfreeze when changed not from our own `output' signal handler. (gtk_freezable_spin_button_freeze_and_stop_input): New function. * gui-gtk/gtk-game-info-dialog.c (gtk_game_info_dialog_init): Bug-fix: Call gtk_utils_convert_to_time_spin_button() after gtk_utils_freeze_on_empty_input(), so that time_spin_button_input() is the last handler. 2004-10-14 anonymous * gui-gtk/gtk-preferences.c (prepare_to_rebuild_menus) (rebuild_all_menus): Fix macro definition for GTK+ 2.4 broken by extra spaces (bug #898.) 2004-10-14 Paul Pogonyshev * (Quarry version 0.1.8.) 2004-10-13 Paul Pogonyshev * gui-gtk/gtk-goban-window.c (game_info_dialog_property_changed): New function. (update_player_information): Add a comma before ranks not starting with a digit (i.e. "Honinbo".) * gui-gtk/gtk-game-info-dialog.c: Enable editing of game information. Add `property-changed' signal. (gtk_game_info_dialog_init): Remove temporary notice from dialog title. Make all controls save their values (i.e. editable.) Use GtkFreezableSpinButton for handicap, komi and main time entries. Adjust some mnemonic keys to make space for not yet added "Help" button. (create_and_pack_game_info_entry): New function. (gtk_game_info_dialog_set_node): Bug-fix: set `main_time' adjustment for all games, not just for Go. Freeze spin buttons when properties have illegal (from SGF point of view) values. (game_info_entry_focus_out_event, game_comment_focus_out_event) (game_info_spin_button_value_changed) (game_info_spin_button_focus_out_event) (update_property_if_changed): New functions. * gui-gtk/gtk-utils.c (gtk_utils_create_freezable_spin_button): New function. (gtk_utils_convert_to_time_spin_button): New function, break out of gtk_utils_create_time_spin_button(). (gtk_utils_set_text_buffer_text): New function, break out of update_children_for_new_node() (in `gui-gtk/gtk-goban-window.c'.) (gtk_utils_freeze_on_empty_input, freeze_on_empty_input): New functions. * gui-gtk/gtk-freezable-spin-button.c: New file. * gui-gtk/gtk-freezable-spin-button.h: New file. 2004-10-12 Paul Pogonyshev * sgf/sgf-utils.c (sgf_utils_normalize_text): Add `is_simple_text' parameter. Handle simple text. Remove all occurences of '\r' character. Don't leak `buffer' if `text' contains whitespace only. * gui-gtk/gtk-utils.h (GtkUtilsBrowsingDoneCallback): Make really the same as the prototype of the `focus-out-event' handler. * gui-gtk/gtk-preferences.c (update_board_background_texture): Likewise. * (Globally: put a space before opening parenthesis in function calls and so be closer to GNU coding standard. Files will be converted only when some other change is being commited.) 2004-10-11 Paul Pogonyshev * gui-gtk/gtk-preferences.c (gtk_preferences_dialog_present): Add help button. (create_gtp_engines_page): Change "Supported games" label to "Supported game(s)". Make "Supported game(s)" go before "Command line". (gtk_preferences_dialog_destroy): New function. (gtk_gtp_engine_dialog_response): Call gtk_progress_dialog_set_help_link_id(). * gui-gtk/gtk-preferences.h: Add previously missed `PREFERENCES_PAGE_SGF_SAVING'. * gui-gtk/gtk-progress-dialog.c (gtk_progress_dialog_init): Reset new `help_link_id' field to NULL. (gtk_progress_dialog_update): New function. (gtk_progress_dialog_response): Handle `GTK_RESPONSE_HELP'. * gui-gtk/gtk-new-game-dialog.c (gtk_new_game_dialog_present): Change some mnemonic keys to make space for new "Help" button. Set help links for both assistant pages. (instantiate_players): New function. * gui-gtk/gtk-assistant.c (gtk_assistant_init): Initialize new `help_button' field to NULL. (gtk_assistant_update_buttons): Sensitize or desensitize help button if present. (gtk_assistant_response): Handle `GTK_RESPONSE_HELP'. (gtk_assistant_add_page): Reset new `help_link_id' and `help_link_id_callback' fields to NULL. (gtk_assistant_set_page_help_link_id) (gtk_assistant_set_page_help_link_id_callback): New functions. * gui-gtk/gtk-goban-window.c (gtk_goban_window_init): Add "Contents" (of "Help") menu item. (show_help_contents): New function. * gui-gtk/gtk-help.c, gui-gtk/gtk-help.h: New files. 2004-10-05 Paul Pogonyshev * sgf/sgf-parser.c (parse_property): Adjust to changed storage of unknown properties. (parse_unknown_property_values): Likewise. Add `property_value_list' argument; add values to that list. 2004-10-04 Paul Pogonyshev * sgf/sgf-writer.c (do_write_text): Add `terminating_character' argument. Output `terminating_character' in encoding specified by `CA' property, so that the file is parseable. (sgf_write_simple_text, sgf_write_text, sgf_write_list_of_label): Don't write terminating ']', do_write_text() does this now. (sgf_write_unknown): Adjust to work with changed storage of unknown properties. Output ']' like do_write_text() now does. * sgf/sgf-tree.c (sgf_node_find_unknown_property) (sgf_property_duplicate, free_property_value): Cope with changed storage of unknown properties. (sgf_property_delete): Use free_property_value(). (free_property_value): Compile unconditionally (for use from sgf_property_delete()). Make `inline'. * sgf/sgf.h: Change storage of unknown properties: store them in `StringList's now. 2004-10-03 Paul Pogonyshev * gui-gtk/gtk-goban.c (gtk_goban_set_parameters): Reset `grid', `goban_markup', `sgf_markup' and `sgf_labels'. Free `sgf_labels' strings if needed. (gtk_goban_expose): Render SGF labels. (gtk_goban_finalize): Free `sgf_labels' strings if needed. (gtk_goban_update): New argument `sgf_label_list'. Use grid_copy() instead of memcpy(). * gui-gtk/gtk-goban.h (KEEP_SGF_LABELS): New macro. * board/board.c (DO_FILL_GRID, DO_COPY_GRID): New macros. (board_fill_grid, board_fill_int_grid): Remove functions. (grid_fill, int_grid_fill, pointer_grid_fill): New functions, inherit removed functions' code. (grid_copy, int_grid_copy, pointer_grid_copy): New functions. * board/board.h (uint_grid_fill, board_fill_grid) (board_fill_int_grid, board_fill_pointer_grid, uint_grid_copy): New macros. 2004-09-13 Paul Pogonyshev * gui-gtk/gtk-utils.c (gtk_utils_workaround_focus_bug): New function. * gui-gtk/gtk-assistant.c (gtk_assistant_response): Use it. * gui-gtk/gtk-goban-window.c (USER_IS_TO_PLAY): New macro. (gtk_goban_window_enter_game_mode): Use USER_IS_TO_PLAY() instead of USER_CAN_PLAY_MOVES(). (free_handicap_has_been_placed): Don't start clock if white player is a GTP engine that hasn't yet initialized (fixes crashes). (initialize_gtp_player): Bug-fix: only check if handicap is fixed if the number of stones doesn't exceed maximal fixed handicap for game's board size in the first place. Otherwise an assertion in go_get_fixed_handicap_stones() fails. * gui-gtk/gtk-goban-window.c (gtk_goban_window_init): Center-justify `move_information_label'. (update_move_information): Print result when browsing the last node of main variation. (move_has_been_generated): Handle resignation of GTP engines. 2004-09-12 Paul Pogonyshev * sgf/sgf-tree.c (sgf_node_get_result): New function. * sgf/sgf-utils.c (do_enter_tree): Keep value of new `last_main_variation_node' field of `SgfBoardState' structure valid. (descend_nodes): Likewise. (ascend_nodes): Likewise. 2004-09-10 Paul Pogonyshev * gui-gtk/gtk-goban-window.c (gtk_goban_window_init): Add "Resign" menu item. (play_resign): New function. (update_children_for_new_node): Sensitize/desensitize "Resign" menu item. (go_scoring_mode_done): Add game result SGF property. (move_has_been_played): Likewise for Amazons and Othello. * sgf/sgf-utils.c (sgf_utils_append_variation): Rename from sgf_utils_append_move_variation(). Handle variations without moves (when `color' is set to `EMPTY'). * sgf/sgf-tree.c (sgf_node_add_score_result) (sgf_node_append_text_property): New functions. * gui-gtk/gtk-new-game-dialog.c (begin_game): Set game result to "Void" initially. * gtp/gtp-client.c (parse_generated_move): Handle "resign" answer of GTP engines. * board/board-topology.h (SPECIAL_X, SPECIAL_Y, SPECIAL_POSITION): New macros. * gtp/gtp-client.h (RESIGNATION_X, RESIGNATION_Y, RESIGNATION): New macros. 2004-09-09 Paul Pogonyshev * gui-gtk/gtk-utils.h (gtk_utils_make_window_only_horizontally_resizable): Define to nothing for pre-2.2 GTK+ (workaround GTK+ bug). * gui-gtk/gtk-parser-interface.c (gtk_parse_sgf_file): Don't use GTK_WIDGET() on NULL pointer. * gui-gtk/gtk-progress-dialog.c (gtk_progress_dialog_new): Likewise. * gui-gtk/gtk-assistant.c (gtk_assistant_update_buttons): Make `is_last_page' calculation work in pre-2.2 case. * gui-gtk/gtk-preferences.c (do_remove_gtp_engine): Pre-2.4 (or pre-2.2?) gtk_list_store_remove() didn't return anything. Add special case. * gui-gtk/gtk-clock.c (gtk_clock_expose): Remove `const' from `black_color' and `gray_color' declaration to avoid warnings with earlier GTK+ versions. 2004-08-31 Paul Pogonyshev * utils/utils.c (utils_parse_double): Bug-fix: don't skip one extra character when there is no decimal dot. * sgf/sgf-tree.c (sgf_node_get_time_limit): New function. * gui-gtk/gtk-goban-window.c (gtk_goban_window_init): Add "Game Information" menu item. Initialize new `game_info_dialog' field. (gtk_goban_window_destroy): Destroy game info dialog if exists. (show_game_information_dialog, game_info_dialog_destroyed): New functions. (update_game_information): Call gtk_game_info_dialog_set_node() if game info dialog exists. * sgf/sgf-properties.list: Rename `SGF_RULES' to `SGF_RULE_SET'. * gui-gtk/gtk-game-info-dialog.c, gui-gtk/gtk-game-info-dialog.h: New files. * gui-gtk/gtk-utils.c (gtk_utils_create_entry): Add `mode' argument. (advance_focus): New function. (gtk_utils_align_left_widgets) (do_align_left_widgets, do_align_left_widget): New functions. (time_spin_button_output): Bug-fix: use sprintf() again, utils_ncprintf() doesn't know about field width. 2004-08-30 Paul Pogonyshev * sgf/sgf-parser.c (sgf_parse_date): Fall back to sgf_parse_simple_text() for now. (sgf_parse_result): Implement with error checking. (looking_at, invalid_game_info_property): New functions. 2004-08-29 Paul Pogonyshev * sgf/sgf-writer.c (sgf_write_file): Remove `1||' accidentally left in the code. * gui-gtk/gtk-goban-window.c (gtk_goban_window_save): Use configuration variable to decide whether to force UTF-8. (save_file_as_response): Likewise. * gui-gtk/gtk-preferences.c: Add "Game Records (SGF)" category. (create_saving_sgf_page, store_toggle_setting): New functions. (update_board_background): Remove function. (update_board_markup): Remove GtkCheckButton case. (update_board_appearance): Add GtkToggleButton case. Bug-fix: don't ignore first field of appearance structures. * gui-utils/common-configuration-sections.list: Add configuration parameter (whether to force UTF-8 encoding) for saving SGF files. * gui-utils/common-configuration-values.list: Likewise. * gui-utils/common-configuration-defaults.list: Likewise. * gui-gtk/gtk-new-game-dialog.c (begin_game): Use *cprintf() functions when locale-specific formatting is not needed and is not expected. * gui-gtk/gtk-tile-set.c (scale_and_paint_svg_image): Likewise. * gui-gtk/gtk-utils.c (time_spin_button_output): Likewise. * gui-utils/configuration.c (write_section): Likewise. * gui-utils/parse-configuration.c: Likewise. * gtp/gtp-client.c (send_command): Likewise. * sgf/parse-sgf-list.c: Likewise. * sgf/sgf-diff-utils.c (do_generate_text_diff): Likewise. * sgf/sgf-parser.c: Likewise. * sgf/sgf-tree.c (sgf_node_get_handicap): Likewise. * sgf/sgf-utils.c (sgf_utils_set_handicap): Likewise. * sgf/sgf-writer.c: Likewise. * board/board.c (game_format_point): Likewise. * board/parse-game-list.c (game_list_parse_game2): Likewise. * utils/parse-list.c (do_parse_lists): Likewise. * utils/buffered-writer.c (buffered_writer_vprintf): Properly handle cases when vsnprintf() returns -1. (buffered_writer_printf, buffered_writer_vprintf): New functions. * utils/string-buffer.c (string_buffer_vprintf): Properly handle cases when vsnprintf() returns -1. (string_buffer_cprintf, string_buffer_vcprintf): New functions. * utils/utils.c (FORMAT_DOUBLE_DECIMALS): Remove macro (replaced with new anonymous enumeration). (utils_cprintf, utils_vcprintf, utils_ncprintf, utils_vncprintf): New functions. (utils_vprintf): Properly handle vsnprintf() return value after the very first call. (utils_format_double): Remove function (code is inherited by utils_vncprintf()). (utils_parse_double): Allow the string contain '+' as the first character. 2004-08-28 Paul Pogonyshev * (Quarry version 0.1.7.) * gui-gtk/gtk-goban-window.c (gtk_goban_window_init): New sub-menus: "Edit" with "Preferences" item and "Help" with "About" item. (show_preferences_dialog, show_about_dialog) (about_dialog_destroy): New functions. * gui-gtk/gtk-preferences.c (gtk_preferences_dialog_present): Change type of `page_to_select' parameter to `gpointer'. 2004-08-27 Paul Pogonyshev * gui-gtk/gtk-tile-set.c (gtk_main_tile_set_create_or_reuse): Restore accidentally removed special case: only use odd-sized tiles for Go (otherwise they won't center properly). * gui-utils/tile-renderer.c (render_go_stones): Fix stone center positioning once more (previous fix didn't work in all cases). Remove debug output accidentally left in the code. (render_othello_disks): Likewise for disk center positioning. * gui-gtk/gtk-goban-window.c (gtk_goban_window_init): Make sure right side doesn't shrink below certain width (suggested by Arend Bayer). (force_minimal_width): New function. 2004-08-26 Paul Pogonyshev * gui-utils/tile-renderer.c (render_othello_disks): New function. * gui-gtk/gtk-tile-set.c (gtk_main_tile_set_create): Use render_othello_disks() for Othello. 2004-08-25 Paul Pogonyshev * gui-gtk/gtk-goban.c (set_goban_non_style_appearance): Update goban's SGF markup tile set. * gui-gtk/gtk-preferences.c (create_go_board_appearance_page): Create a page for markup appearance configuration. (create_amazons_board_appearance_page): Likewise. (create_othello_board_appearance_page): Likewise. (create_board_appearance_notebook_page): Add markup page to the notebook (passed as new parameter `markup_widget'). (update_board_background): Remove only GtkColorButton case. Change `game_index's type to `gpointer'. (update_board_background_texture): Likewise for `game_index'. (create_markup_box, update_board_grid_and_labels_color) (use_theme_default_size, use_theme_default_opacity) (game_to_board_appearance_structure): New functions. (update_board_grid_and_labels_color, update_checkerboard_pattern): Remove functions. (update_board_appearance): New function, contains code from update_board_background(), update_board_grid_and_labels_color() and update_checkerboard_pattern(). * gui-gtk/gtk-tile-set.c (gtk_sgf_markup_tile_set_create_or_reuse): Remove `theme' parameter. Handle markup configuration. Scale markup for Go when decrementing markup cell/pixbuf size. Update for new `GtkSgfMarkupTileSetKey' format. (gtk_sgf_markup_tile_set_compare_keys): Update for new `GtkSgfMarkupTileSetKey' format. (gtk_sgf_markup_tile_set_duplicate_key): Likewise. (gtk_sgf_markup_tile_set_create): Handle markup configuration. Read files here instead of scale_and_paint_svg_image(). Reuse pixbufs when markup color over different backgrounds match. (scale_and_paint_svg_image): Empty `color_properties' string list just in case not all declared properties exist. 2004-08-24 Martin Holters * board/board.c (board_position_list_union): New function. * utils/string-list.c (string_list_count_items): New function. * gtp/gtp-client.c (gtp_client_final_status_list) (parse_final_status_list): New functions. * gui-gtk/gtk-goban-window.c (engine_has_scored) (enter_scoring_mode, cancel_scoring): New functions. (move_has_been_played): Invoke gtp_client_final_status_list() of GTP engine player(s) (if any) before user may score. 2004-08-23 Paul Pogonyshev * gui-gtk/gtk-utils.c (gtk_utils_create_selector): Pass items' text through _() also for pre-2.4 version of the function. (gtk_utils_create_selector_from_string_list): New function. * quarry.c (main): Invoke gui_utils_enumerate_themes() before anything else GUI-related and gui_utils_discard_theme_lists() afterwards. Don't call gui_back_end_main_*() if gui_back_end_init() failed in the first place. * Makefile.am (AM_CPPFLAGS): Add `src/gui-utils' and `src/board' to include path (the latter is required by `gui-utils/gui-utils.h', not by `quarry.c' itself). * gui-utils/gui-utils.c (gui_utils_enumerate_themes) (gui_utils_discard_theme_lists): New functions. * gui-utils/configuration.c (configuration_read_from_file): Return non-zero if file is read successfully. * gui-utils/Makefile.am (AM_CPPFLAGS): Define `PACKAGE_DATA_DIR'. * utils/Makefile.am: Make `tags' target depend on `libutils.a' and `libparselist.a', as otherwise `make tags' won't work in a clean source tree. 2004-08-22 Paul Pogonyshev * gui-utils/markup-theme-configuration.list: New file. * gui-utils/common-configuration-values.list: Add configuration parameters for markup appearance for all supported games. * gui-utils/common-configuration-defaults.list: Likewise. * gui-gtk/gtk-goban-window.c (update_children_for_new_node): Move cursor to comment's first line. (fetch_comment_if_changed): Don't store empty comments, delete them. * sgf/sgf-utils.c (sgf_utils_normalize_text): Return NULL if normalized comment is empty. 2004-08-21 Paul Pogonyshev * gui-gtk/gtk-goban-window.c (gtk_goban_window_save): Make sure that the comment for the current node is saved if needed. (save_file_as_response): Likewise. (set_current_tree): Likewise. (update_children_for_new_node): Likewise, but for the node goban just left. Append one newline to the displayed comment to ease editing. (fetch_comment_if_changed): New function. * sgf/sgf-utils.c (sgf_utils_normalize_text): New function. * sgf/sgf-tree.c (sgf_node_add_number_property): Add `overwrite' parameter. (sgf_node_add_real_property): Likewise. (sgf_node_add_pointer_property): Likewise. * sgf/sgf.h (sgf_node_add_double_property): Add `overwrite' parameter. (sgf_node_add_color_property): Likewise. (sgf_node_add_text_property): Likewise. (sgf_node_add_list_of_point_property): Likewise. (sgf_node_add_list_of_label_property): Likewise. * gettext.h (textdomain): Cast to `void' when NLS is disabled to avoid pointless compiler warnings. (bindtextdomain): Likewise. (bind_textdomain_codeset): Likewise. * gui-gtk/gtk-color-button.c: Use _(). * gui-gtk/gtk-control-center.c: Likewise. * gui-gtk/gtk-gtp-client-interface.c: Likewise. * gui-gtk/gtk-games.c: Use N_(). * gui-gtk/gtk-goban-window.c: Use _(), N_() and ngettext(). Tweak some strings to allow better l10n. * gui-gtk/gtk-new-game-dialog.c: Use _() and N_(). * gui-gtk/gtk-parser-interface.c: Likewise. * gui-gtk/gtk-preferences.c: Likewise. * gui-gtk/quarry-stock.c: Likewise. * gui-gtk/gtk-utils.c (file_selection_response): Use _() and N_(). (gtk_utils_create_selector): Invoke _() on items' text. (gtk_utils_create_radio_chain): Likewise for labels' text. * gettext.h: New file, copied from GNU gettext 0.14.1. * quarry.h (_, N_): New macros: i18n. * quarry.c (main): Initialize i18n text domain. 2004-08-19 Paul Pogonyshev * gui-gtk/gtk-new-game-dialog.c (begin_game): Set UTF-8 encoding for the created game tree. * sgf/sgf-writer.c (sgf_write_file): New parameter `force_utf8'. (write_game_tree): Write `CA' property. Create an iconv handle for converting text property values if conversion is requested. (do_write_text): Tell buffered writer to convert text. Skip UTF-8 characters, not just bytes. (sgf_write_fake_simple_text): Likewise. (sgf_write_unknown): Likewise. * sgf/sgf-properties.list: Mark `CA' property as not stored. * sgf/sgf-parser.c (sgf_parse_char_set): New function. * utils/buffered-writer.c (buffered_writer_init): Reset new field `iconv_handle' to NULL. (buffered_writer_add_character): Convert incoming text using iconv(), if requested. (buffered_writer_add_newline): Likewise. (buffered_writer_cat_as_string): Likewise. (buffered_writer_vprintf): Likewise. (update_column): Count UTF-8 characters, not bytes. * utils/utils.h (buffered_writer_set_iconv_handle): New macro. * quarry.h (IS_UTF8_STARTER): New macro. 2004-08-18 Paul Pogonyshev * sgf/sgf-parser.c: Start handling of non-UTF-8 encodings. (parse_buffer): Open/close iconv handles. (parse_root): Parse value of `CA' property and create an iconv handle for converting to UTF-8. (do_parse_simple_text): Invoke convert_text_to_utf8(). (do_parse_text): Likewise. (convert_text_to_utf8): New function. * sgf/sgf-tree.c (sgf_game_tree_new): Initialize new `char_set' field. (sgf_game_tree_delete): Free `char_set'. (sgf_game_tree_duplicate): Duplicate value of `char_set'. * utils/utils.c (utils_duplicate_string): Allow `string' to be NULL. 2004-08-17 Paul Pogonyshev * gui-gtk/gtk-goban.c (gtk_goban_scroll_event): New function (navigate goban in respond to mouse wheel movement, wish #610, David Gómez). 2004-08-16 Paul Pogonyshev * gui-gtk/gtk-parser-interface.c (analyze_parsed_data): Free `data', don't leak memory. 2004-08-15 Paul Pogonyshev * (Quarry version 0.1.6.) * gui-utils/tile-renderer.c (render_go_stones): Fix stone center positioning (used to be off by 0.5 pixels both horizontally and vertically). 2004-08-14 Paul Pogonyshev * gui-gtk/gtk-goban.c: Tweak stones' placement and size. (gtk_goban_size_allocate): Create a tile set for drawing SGF markup. (gtk_goban_expose): Draw SGF markup. (unreference_cached_objects): New function. (gtk_goban_update): Handle incoming SGF markup, don't ignore it. * gui-gtk/gui-back-end.c (gui_back_end_image_new) (gui_back_end_image_delete): Remove functions. * gui-gtk/gtk-tile-set.h: Rename from `gtk-tile-set-interface.h'. * gui-gtk/gtk-tile-set.c: New file (part of `gui-utils/tile-set.c' functionality and more). * gui-utils/tile-renderer.c (PIXEL): Remove macro. (tile_set_create_or_reuse, tile_set_unreference) (tile_set_dump_recycle): Remove functions. (render_go_stones): Rename from `create_go_stone_images'. Only render basic images here (one black, one white). (duplicate_and_adjust_alpha, combine_pixels_diagonally): New functions. * gui-utils/tile-renderer.c: Rename from `tile-set.c'. * gui-utils/tile-renderer.h: Rename from `tile-set.h'. * utils/object-cache.c: New file (part of `gui-utils/tile-set.c' functionality). 2004-08-13 Paul Pogonyshev * Makefile.am (quarry_LDADD): Remove recently added `QUARRY_RSVG_LIBS' (it is now merged into `QUARRY_GTHREAD_LIBS'). * gui-gtk/Makefile.am (QUARRY_FULL_GTK_CFLAGS): Remove `QUARRY_RSVG_CFLAGS' (it is now merged into `QUARRY_GTHREAD_CFLAGS'). (AM_CPPFLAGS): Remove `PACKAGE_TEXTURES_DIR', it is obviously derivable from `PACKAGE_DATA_DIR'. 2004-08-12 Paul Pogonyshev * gui-gtk/gtk-preferences.c (gtk_gtp_engine_dialog_present): Properly handle requests for modification of engine information (don't die with assertion failure). (gtk_gtp_engine_dialog_response, client_deleted): Handle "modify engine information" version of dialog. (update_engine_screen_name) (find_gtp_tree_model_iterator_by_engines_data): New functions (break out of chain_client_initialized()). * gui-gtk/quarry-stock.c: New stock item `QUARRY_STOCK_MODIFY'. * gui-gtk/gtk-preferences.c (create_background_table): Add button for browsing for a texture. (browse_for_gtp_engine, browsing_dialog_response): Remove functions. * gui-gtk/gtk-utils.c (gtk_utils_create_browse_button) (browse_button_clicked, browsing_dialog_response): New functions (mostly inherit code of removed functions in `gtk-preferences.c'). * gui-gtk/gtk-preferences.c (gtk_preferences_dialog_present): Adapt page selection to new (tree) categories model. Don't crash when invoked with preferences dialog already shown and `page_to_select' equal to -1. 2004-08-11 Paul Pogonyshev * gui-gtk/gtk-preferences.c: Split "Board Appearance" category into three (one per game). (gtk_preferences_dialog_present): Arrange preferences categories in a tree rather than in a list. (create_board_appearance_page): Remove function. (create_go_board_appearance_page) (create_amazons_board_appearance_page) (create_othello_board_appearance_page) (create_board_appearance_widgets) (create_board_appearance_notebook_page): New functions (essentially, inherit the code of removed create_board_appearance_page()). (gtk_preferences_dialog_change_page): Take care not to switch to nonexistent pages. 2004-08-10 Paul Pogonyshev * board/go.c (go_mark_territory_on_grid): Detect false eyes that don't yield territory and don't mark them. 2004-08-09 Paul Pogonyshev * Makefile.am (quarry_LDADD): Include `QUARRY_GTHREAD_LIBS' (split off from `QUARRY_GTK_LIBS') and new `QUARRY_RSVG_LIBS' flags. * gui-gtk/Makefile.am (QUARRY_FULL_GTK_CFLAGS): Include `QUARRY_GTHREAD_CFLAGS' (split off from `QUARRY_GTK_CFLAGS') and new `QUARRY_RSVG_CFLAGS'. 2004-08-07 Paul Pogonyshev * gui-gtk/gtk-preferences.c (create_gtp_engines_page): Create GTP engine information labels. (gtk_preferences_dialog_update_gtp_engine_info): Display selected GTP engine name, version, command line and supported games in corresponding labels. * gui-gtk/gtk-utils.c (gtk_utils_create_left_aligned_label): New function. * utils/string-list.c (string_list_implode): New function. * gui-gtk/gtk-goban.c (gtk_goban_expose): Draw a small rectangle to indicate focused state of widget. (gtk_goban_button_press_event): Grab focus when goban is clicked outside the playing area (e.g. on labels). (gtk_goban_focus_in_or_out_event): New function. 2004-08-04 Paul Pogonyshev * quarry.c (main): Use `SIG_IGN' as signal handler for `SIGPIPE'. (catch_broken_pipe_signal): Remove function. 2004-07-22 Paul Pogonyshev * gui-gtk/gtk-goban-window.c (gtk_goban_window_save): Handle "Save" command, but issue warning about potential loss of information (bug #522, David Gómez). 2004-07-20 Paul Pogonyshev * (Quarry version 0.1.5.) * gui-gtk/gtk-goban-window.c: Make it safe to navigate to a different node while a game (with GTP engines participating) is going on. (IS_DISPLAYING_GAME_NODE): New macro. (navigate_goban): Handle special cases of navigating from/to the current game node. (move_has_been_generated): Take care to attach new moves to the current game's node, not to the displayed node. * board/board.c (board_duplicate_without_stacks): New function. 2004-07-16 Paul Pogonyshev * sgf/sgf-tree.c (sgf_game_tree_set_state): New function. * gui-utils/parse-configuration.c (configuration_parse_defaults2): Initialize a few variables to avoid compiler warnings. * gui-gtk/gtk-new-game-dialog.c (gtk_new_game_dialog_present): Likewise. (begin_game): Likewise. 2004-07-16 Martin Holters * board/go.c (go_score_game): Don't use utils_format_double(), format as user's locale specifies. * gui-gtk/gtk-goban-window.c (update_game_specific_information): Likewise. * sgf/sgf-tree.c (sgf_node_get_komi): Use utils_parse_double(). * gui-utils/configuration.c (configuration_read_from_file): Likewise for parsing values of type `VALUE_TYPE_REAL'. * utils/utils.c (utils_format_double): Don't use sprintf() and thus be locale insensitive. (utils_parse_double): New function, parse doubles in locale-insensitive manner. 2004-06-19 Paul Pogonyshev * gui-gtk/gtk-utils.c (time_spin_button_input): Use new function utils_parse_time() (which contains the code previously resided here). * gui-gtk/gtk-utils.h (gtk_utils_set_selector_active_item_index): New macro. * gui-gtk/gtk-new-game-dialog.c (gtk_new_game_dialog_present): Initialize time control parameter widgets from configuration variables. (begin_game): Store time control configuration at successful game start. * gui-gtk/gtk-configuration-structures.c: Remove file. * gui-gtk/gtk-configuration-structures.h: Remove file. * gui-gtk/gtk-configuration.list: Ask `parse-configuration' to declare `NewGameConfiguration' structure. Break game-specific variables out to separate sections. Add time control variables for each game. * gui-utils/common-configuration-defaults.list: Update for new format of fields of structural types. * gui-utils/parse-configuration.c: Rewrite to allow random structure declarations and array fields. Add support for configuration variables of `time' type. (push_subscription_stack, pop_subscription_stack) (recursively_build_full_field_name) (add_field_declaration_if_needed) (add_field_dispose_call_if_needed) (recursively_build_full_field_name): New functions. * gui-utils/configuration.c (configuration_read_from_file) (write_section): Add support for `time' configuration value type. (write_section): Change indentation of variable value from 16 to 24 (variable names are usually long). * utils/parse-list.c (parse_thing): Allow `FIELD_NAME' to have '[' as its first character. Handle new thing type, `TIME_VALUE'. * utils/utils.c (utils_cat_string): Allow `string' argument to be NULL. (utils_cat_as_string): Likewise. (utils_format_double): Rename from format_double() and move here. (utils_parse_time): Break out from time_spin_button_input() (a function in `gui-gtk/gtk-utils.c'). * utils/format.c: Remove file. 2004-06-18 Paul Pogonyshev * sgf/sgf-parser.c (parse_property): Bug-fix: store return value of utils_cat_as_string() back in `(*link)->value.text'. 2004-06-12 Paul Pogonyshev * gui-gtk/gtk-goban-window.c (gtk_goban_window_init): Create labels for displaying game-specific information (number of captures and komi for Go, number of disks for Othello). (set_current_tree): Hide the labels for Amazons (not used). (update_game_specific_information): New function, fill the labels with information. * gui-gtk/gtk-utils.c (gtk_utils_set_widgets_visible): New function. * board/othello.c (othello_count_disks): New function. * gui-utils/tile-set.c (create_go_stone_images): Create 50% transparent tile of mixed colors (half black, half white). * gui-gtk/gtk-goban-window.c (update_children_for_new_node): Mark positions with variations of both color with new tile. * gui-gtk/gtk-goban-window.c (gtk_goban_window_init): Create clock widgets for both players. (gtk_goban_window_enter_game_mode): Take care of time control. (initialize_gtp_player): Likewise. (move_has_been_played): Likewise. (generate_move_via_gtp, start_clock_if_needed): New functions. * gui-gtk/gtk-clock.c, gui-gtk/gtk-clock.h: New files. * gtp/gtp-client.c (COLOR_STRING): New macro. (gtp_client_send_time_settings, gtp_client_send_time_left): New functions. 2004-06-10 Paul Pogonyshev * gui-gtk/gtk-new-game-dialog.c (gtk_new_game_dialog_present): Add time control parameters widgets. (time_control_type_changed): New function. (begin_game): Create `TimeControl' objects when needed. * gui-gtk/gtk-utils.c (gtk_utils_create_time_spin_button) (time_spin_button_output, time_spin_button_input): New functions. * gui-gtk/gui-back-end.c (gui_back_end_timer_restart) (gui_back_end_timer_delete) (gui_back_end_timer_get_seconds_elapsed): New functions. * gui-utils/time-control.c, gui-utils/time-control.h: New files. 2004-06-06 Paul Pogonyshev * gui-gtk/gtk-utils.c (gtk_utils_create_selector) (gtk_utils_create_invisible_notebook): New functions. 2004-06-01 Paul Pogonyshev * gui-gtk/gtk-preferences.c (gtk_preferences_finalize): Remove. (gtk_preferences_init): Register `gtp_engines_list_store' with gui_back_end_register_object_to_finalize(). * gui-gtk/gui-back-end.c (gui_back_end_register_object_to_finalize): New function. (run_main_loop): Dereference objects from `objects_to_finalize' list. 2004-05-27 Paul Pogonyshev * gui-gtk/gtk-preferences.c (chain_client_initialized): Update engine's information after successful initialization. I.e. notice version upgrades, etc. automatically. * utils/string-list.c (string_list_duplicate_items): Bug-fix: don't leave the new list unterminated, write NULL in the last `next' pointer. 2004-05-21 Paul Pogonyshev * gui-gtk/gtk-goban-window.c (initialize_gtp_player): Don't send `fixed_handicap 0' GTP command (specification requires to just omit it). 2004-05-13 Paul Pogonyshev * sgf/sgf.h: Remove types `SgfPoint', `SgfPositionList', `SgfAmazonsMoveData' and `SgfAbstractMoveData' and all `#define'd pseudo-functions. * sgf/sgf.h: Use types from board code instead of removed ones. * sgf/sgf-diff-utils.c: Likewise. * sgf/sgf-parser.c: Likewise. * sgf/sgf-tree.c: Likewise. * sgf/sgf-utils.c: Likewise. * sgf/sgf-writer.c: Likewise. * (Quarry version 0.1.4.) * gui-gtk/gtk-goban-window.c (playing_mode_goban_clicked): Bug-fix: use `GOBAN_TILE_DONT_CHANGE' instead of `TILE_NONE'. Caused serious problems with all games when trying to play an illegal move. (free_handicap_mode_goban_clicked): Likewise. 2004-05-12 Paul Pogonyshev * (Quarry version 0.1.3.) * gui-gtk/gtk-goban-window.c: Add support for user scoring of Go games. Cope with the changes in goban's feedback handling. (update_territory_markup, go_scoring_mode_done) (reenter_current_node, go_scoring_mode_pointer_moved) (go_scoring_mode_goban_clicked): New functions. (play_pass_move): Call move_has_been_played() after updating controls for new SGF node so that the former function can change goban's contents. (playing_mode_goban_clicked): Likewise. (update_children_for_new_node): Make dead stones more transparent. (free_handicap_has_been_placed): Use reenter_current_node(). * gui-gtk/gtk-goban.c: Add possibility for overlays to span several positions by using position lists. Make overlays overwrite goban markup as well as the main grid. (gtk_goban_set_contents): Rename from gtk_goban_set_grid_contents(). (set_feedback_data): Handle more feedback types, including goban markup overwriting feedbacks. * board/go.c (go_get_string_stones) (go_get_logically_dead_stones, go_score_game) (go_mark_territory_on_grid): New functions. 2004-05-10 Paul Pogonyshev * board/board.c (board_position_list_sort) (board_position_lists_overlap) (board_position_list_find_position) (board_position_list_mark_on_grid): New functions. * utils/utils.c (utils_compare_ints): New function. 2004-05-09 Paul Pogonyshev * gui-gtk/gtk-new-game-dialog.c (set_handicap_adjustment_limits): Don't use adjustment properties: they only appeared in GTK+ 2.4. 2004-05-01 Paul Pogonyshev * gui-gtk/gtk-preferences.c (create_board_appearance_page): Add controls for configuring Amazons' checkerboard pattern. Change controls layout: consider grid and labels a part of background. (update_board_grid_and_labels_color): Rename from update_board_foreground(). (update_checkerboard_pattern): New function. * gui-utils/common-configuration-values.list: Rename "Foreground" configuration variable to "Grid and labels color". * gui-gtk/gtk-utils.c (gtk_utils_pack_in_box): Add a way to request packing in box end. (gtk_utils_create_mnemonic_label): New function. * gui-gtk/gtk-named-vbox.c (gtk_named_vbox_size_request) (gtk_named_vbox_size_allocate): Use `QUARRY_SPACING_SMALL' instead of the box spacing as distance between the label and the contents. * gui-gtk/gtk-goban-window.c (gtk_goban_window_init): Use `QUARRY_SPACING_SMALL' instead of `QUARRY_SPACING_GOBAN_WINDOW' for the gap between players' control sets. 2004-04-30 Paul Pogonyshev * gui-gtk/gtk-goban.c (gtk_goban_expose): Don't draw clipped objects (significant speedup). (gtk_goban_expose): Draw checkerboard pattern if requested. (set_goban_style_appearance): Rename from set_goban_appearance_style(). (set_goban_non_style_appearance): New function. Only handles checkerboard pattern at present. * gui-utils/tile-set.c (tile_set_create_or_reuse): Initialize `cell_size' parameter of `TileSet' structure. * gui-utils/common-configuration-sections.list: Add configuration parameters for checkerboard pattern for Amazons board. * gui-utils/common-configuration-values.list: Likewise. * gui-utils/common-configuration-defaults.list: Likewise. * gui-utils/parse-configuration.c (configuration_parse_defaults2): Add support for structure fields in new (generated) structures. * gui-utils/common-configuration-values.list: Remove value identifiers (not used now). * gui-gtk/gtk-configuration.list: Likewise. * gui-utils/configuration.c (configuration_set_section_values): Remove function. (configuration_set_string_value) (configuration_set_string_list_value) (configuration_set_string_list_value_steal_strings): New functions. * utils/string-list.c (string_list_duplicate_items): Add `const' modifier to second argument. * gui-gtk/gtk-new-game-dialog.c (begin_game): Free `data' structure. 2004-04-29 Paul Pogonyshev * gui-gtk/gtk-goban-window.c (gtk_goban_window_finalize): Unreference `item_factory'. 2004-04-28 Paul Pogonyshev * utils/utils.h (string_list_is_empty) (string_list_is_single_string): Don't cast to `const StringList *' to avoid GCC 3.3+ warnings. * gui-utils/configuration.c (write_section): Cast to `const StringList *' to cope with the above change. * gui-gtk/gtk-goban-window.c: Add full support for free handicap. (GTP_ENGINE_CAN_PLAY_MOVES): New macro. (gtk_goban_window_init): Create "special mode" control set. (gtk_goban_window_enter_game_mode): Enter free handicap special mode if user is to set up free handicap. (enter_special_mode, leave_special_mode) (free_handicap_mode_done) (set_goban_signal_handlers, free_handicap_mode_pointer_moved) (free_handicap_mode_goban_clicked) (free_handicap_has_been_placed): New functions. (navigate_goban): Rename from playing_mode_navigate_goban(). Navigation should always work the same way or just be disabled. (initialize_gtp_player): Rewrite: make reentrant and more generic. (gtp_player_initialized_for_game): Remove (essentially include in the above function). (move_has_been_played): Rewrite. Remove `color' parameter again. Generate moves even if opponent is not initialized. * gui-gtk/quarry-stock.c: New stock item `QUARRY_STOCK_DONE'. * gui-gtk/gtk-new-game-dialog.c (gtk_new_game_dialog_present): Don't desensitize free handicap controls: unneeded now. * gui-gtk/gtk-goban.h: New feedback types `GOBAN_FEEDBACK_ADD_BLACK_OR_REMOVE' and `GOBAN_FEEDBACK_ADD_WHITE_OR_REMOVE'. Remove `_DEFAULT' from `GOBAN_FEEDBACK_MOVE' and its color variants. * gui-gtk/gtk-goban.c (gtk_goban_set_grid_contents) (gtk_goban_get_grid_contents, gtk_goban_diff_against_grid): New functions. (set_overlay_data): Allow setting overlay tile to `TILE_NONE'. (set_feedback_data): Handle new feedback types. Cope with the above change. * gui-gtk/gtk-utils.h: Define gtk_entry_set_alignment() to nothing unless GTK+ version is 2.4 or higher. (G_MAXUINT8, G_MAXUINT16): Define if not yet defined by GLib headers. * gtp/gtp-client.c (gtp_client_place_free_handicap) (parse_free_handicap_placement, gtp_client_set_free_handicap): New functions. * board/board.c (game_format_position_list) (game_parse_position_list): New functions. * sgf/sgf-utils.c (sgf_utils_add_free_handicap_stones): New function. (determine_final_color_to_play): If there is positive handicap, set `sgf_color_to_play' to `WHITE' only if handicap stones are present in the same node. 2004-04-27 Paul Pogonyshev * utils/memory-pool.c (memory_pool_free): Fix bug: do free the very last item in the pool if asked. Fix typo: when profiling, increment the number of freed items, not of allocated ones. * sgf/sgf-diff-utils.c (generate_sgf_collection_diff) (generate_sgf_node_layer_diff): Initialize some variables to silence GCC warnings. * gui-utils/configuration.c (configuration_read_from_file): Likewise. * gui-gtk/gtk-utils.c (gtk_utils_create_titled_page): Likewise. * gui-gtk/gtk-color-button.c: Various backports to GTK+ pre-2.4 and for compilation in Quarry source tree. See file for details. * gui-gtk/quarry-marshal.list: New marshaller `VOID:VOID'. * gui-gtk/Makefile.am: Fix typo in `quarry-marshal.c' build rule: ">", not ">>". 2004-04-26 Paul Pogonyshev * gui-gtk/gtk-color-button.c, gui-gtk/gtk-color-button.h: New files, copy from GTK+ version 2.4.0. Rename to follow Quarry filename standard. Modify to avoid compilation if GTK+ 2.4 is present anyway. * gui-gtk/gtk-preferences.c (create_board_appearance_page): Implement. Add controls for all implemented board appearance configuration variables. (update_board_background, update_board_background_texture) (update_board_foreground): New functions. * gui-gtk/gtk-goban.c: Keep track of all goban widgets. (gtk_goban_update_appearance): New function. * utils/utils.h (QUARRY_COLORS_ARE_EQUAL): New macro. * gui-utils/common-configuration-defaults.list: Use value substitution for default texture file paths. * gui-gtk/Makefile.am: Pass `PACKAGE_TEXTURES_DIR' variable to `parse-configuration' utility. * gui-utils/parse-configuration.c (configuration_parse_defaults2): Read defaults of type `string' with parse_multiline_string() so that value substitution makes sense. * utils/parse-list.c: Add new `substitute_value' command support. Add command-line options support. (parse_list_main): Print help/usage messages to `stdout' or `stderr' according to GNU standards. (print_usage): New function. * utils/utils.h (AssociationList): New global string list type. * utils/string-list.c (association_list_item_dispose) (association_list_find_association): New functions. * utils/getopt.c, utils/getopt1.c, utils/getopt.h: New files, copy from GNU C Library version 2.3.2. 2004-04-25 Paul Pogonyshev * gui-gtk/gtk-goban.c: Use style modifiers instead of new style for changing widget appearance. (set_goban_appearance_style): New function. * gui-gtk/gtk-utils.c (gtk_utils_set_gdk_color) (gtk_utils_set_quarry_color): New functions. * gui-utils/parse-configuration.c (configuration_parse_sections2): Bug-fix: don't try to define new structure several times. * gui-utils/common-configuration-sections.list: Add configuration data for board appearance for Go, Amazons and Othello games. * gui-utils/common-configuration-values.list: Likewise. * gui-utils/common-configuration-defaults.list: Likewise. * gui-utils/configuration.c (configuration_read_from_file): Only consider first word of value when parsing values of non-string configuration variables. * gui-utils/parse-configuration.c: Add support for `color' configuration value type. * gui-utils/configuration.c: Likewise. * utils/utils.h (QuarryColor): New structure. * utils/parse-list.c (parse_color): New function. * gui-utils/configuration-internals.h: Include `utils.h' for the `QuarryColor' structure. 2004-04-24 Paul Pogonyshev * gui-utils/configuration.c (configuration_read_from_file): Close configuration file. 2004-04-23 Paul Pogonyshev * gui-gtk/gtk-configuration.list: Add configuration variables for game rules to "New Game Parameters" section. * gui-gtk/gtk-new-game-dialog.c (gtk_new_game_dialog_present): Use new configuration variables for initialization. (begin_game): Set them when beginning new game. * gui-utils/parse-configuration.c: Add support for configuration variables of type `real'. * gui-utils/configuration.c: Likewise. * gui-utils/configuration.c: Complete support for configuration variables of type `int' (reading from file). * gui-gtk/gtk-goban-window.c (initialize_gtp_player): Add support for fixed handicap and komi. * gtp/gtp-client.c (gtp_client_set_fixed_handicap) (gtp_client_set_komi): New functions. * sgf/sgf-tree.c (sgf_node_get_komi): New function. * gui-gtk/gtk-new-game-dialog.c: Implement game rules (partially). (show_game_specific_rules, set_handicap_adjustment_limits): New functions. * sgf/sgf-utils.c (sgf_utils_set_handicap): New function. * board/go.c (go_get_max_fixed_handicap) (go_get_fixed_handicap_stones): New functions. * gui-gtk/gtk-utils.c (gtk_utils_create_spin_button): New function. 2004-04-22 Paul Pogonyshev * gui-gtk/gtk-games.h (GTK_MIN_BOARD_SIZE, GTK_MAX_BOARD_SIZE): New macros. * quarry.h (MIN, MAX, ROUND_DOWN): New macros. Use `#undef' to avoid conflicts with GLib or whatever else. * gui-gtk/gtk-utils.c (gtk_utils_create_titled_page): Don't use gtk_widget_show_all() on page contents (too intrusive). (gtk_utils_create_titled_page): Use gtk_utils_pack_in_box(). * gui-gtk/gtk-assistant.c (gtk_assistant_add_page): Show added pages. 2004-04-21 Paul Pogonyshev * (Quarry version 0.1.2.) * sgf/sgf-diff-utils.c: New file with various functions for comparing SGF game trees and their collections. * sgf/sgf-diff.c: New file with standalone `sgf-diff' utility code (very simplistic at present). * sgf/sgf-writer.c (sgf_write_file): Add empty line between SGF game trees. * sgf/sgf-tree.c (sgf_node_delete): Rewrite to reduce stack usage when branching factor is high (follow algorithm of parse_node_tree() and parse_node_sequence() from `sgf-parser.c'). (sgf_node_count_subtree_nodes): Likewise (had different problem). (sgf_node_count_subtree_nodes): Rename from sgf_node_count_sub_tree_nodes(). * sgf/sgf-tree.c (sgf_game_tree_duplicate) (sgf_game_tree_duplicate_with_nodes) (sgf_node_duplicate, sgf_node_duplicate_recursively) (sgf_node_duplicate_to_given_depth, sgf_property_duplicate): New functions. (sgf_label_list_duplicate): New function. * board/board.h (board_position_list_duplicate): New macro. * sgf/sgf.h (sgf_position_list_duplicate): New macro. 2004-04-20 Paul Pogonyshev * gui-gtk/gtk-goban-window.c (move_has_been_played): Fix crashes when `color_to_play' is EMPTY (happens in Othello games) by getting explicit `color' argument from the caller. 2004-04-18 Paul Pogonyshev * sgf/sgf-parser.c (parse_buffer): Fix bug that prevented correct parsing of files with multiple SGF game trees. 2004-04-17 Paul Pogonyshev * board/board.c (board_position_lists_are_equal): Rename from board_position_list_equal(). * sgf/sgf.h (sgf_position_lists_are_equal): Likewise. 2004-04-16 Paul Pogonyshev * gui-gtk/gtk-goban-window.c (USER_CAN_PLAY_MOVES): New macro. (gtk_goban_window_init): New sub-menu "Play" with "Pass" item. (play_pass_move): New function. (update_children_for_new_node): Sensitize/desensitize "Pass" menu item depending on the current game and who is to play. 2004-04-15 Paul Pogonyshev * gui-gtk/gtk-utils.c (gtk_utils_create_message_dialog): Comment gtk_window_set_skip_taskbar_hint() call out because it prevents KDE window manager from giving message dialogs focus. Also make dialog modal even it has no parent (unless flags tell otherwise). * gui-gtk/gtk-goban-window.c (gtk_goban_window_save): Use gtk_utils_add_file_selection_response_handlers(). * gui-gtk/gtk-parser-interface.c (gtk_parser_interface_present): Likewise. * gui-gtk/gtk-preferences.c (browse_for_gtp_engine): Likewise. * gui-gtk/gtk-utils.c (gtk_utils_add_file_selection_response_handlers) (overwrite_confirmation, file_selection_response): New functions. Ask user if she really wants to overwrite existing file. (gtk_utils_create_message_dialog): Remove `response_callback' argument. Add `GTK_UTILS_DESTROY_ON_RESPONSE' flag to acomplish similar goal. * gui-gtk/quarry-stock.c: New stock item `QUARRY_STOCK_OVERWRITE'. 2004-04-14 Paul Pogonyshev * gui-utils/tile-set.c (tile_set_dump_recycle): Bug-fix: don't deadlock when performing "lazy" recycling. * gui-gtk/gtk-utils.c (gtk_utils_set_menu_items_sensitive): New function. * gui-gtk/gtk-goban-window.c: Remove `navigate_goban' signal. (gtk_goban_window_init): Add "Go" (as verb) sub-menu. Replace `navigate_goban' signal with generated `GtkAccelGroup' bindings. (update_children_for_new_node): Set items of "Go" sub-menu sensitive or insensitive depending on the node. * gui-gtk/gtk-goban.c (gtk_goban_class_init): Initialize `navigate' class member, even if GLib does that itself. * gui-gtk/gtk-preferences.c (engine_selector_destroyed): Free selector data, don't leak memory. * board/amazons.c (amazons_is_legal_move): Bug-fix: make function work properly when "to" point is a null point. 2004-04-13 Paul Pogonyshev * sgf/sgf-writer.c (do_write_point_or_rectangle): Fix typo ('[' instead of ']') that caused severe SGF file corruptions. * gui-gtk/gtk-goban-window.c: Add basic support for SGF file saving. Note: quite dangerous now, because it never checks or asks anything, just writes. (gtk_goban_window_save) (save_file_as_response, save_file_as_destroy): New functions. * gui-gtk/gtk-goban-window.c (gtk_goban_window_init): Add menu bar to window (with just few items for now). * gui-gtk/Makefile.am: Remove custom build rules for `quarry-stock.o', because `QUARRY_WARNINGS_GTK' does not contain `-Wwrite-strings' (which is problematic for this file) anymore. Changes before the project registration on Gna! (2004-04-12) were not logged. Copyright (C) 2004, 2005, 2006 Paul Pogonyshev. Copying and distribution of this file, with or without modification, are permitted provided the copyright notice and this notice are preserved. Local Variables: coding: iso-8859-1 End: quarry-0.2.0/src/Makefile.am0000644000175000017500000000151410370756325014332 0ustar bartbart# Process this file with Automake to produce `Makefile.in'. SUBDIRS = \ utils \ board \ sgf \ gtp \ gui-utils \ gui-gtk AM_CPPFLAGS = \ -D LOCALE_DIR=\"$(datadir)/locale\" \ \ $(QUARRY_WARNINGS) \ \ -I $(top_srcdir)/src/gui-gtk \ -I $(top_srcdir)/src/gui-utils \ -I $(top_srcdir)/src/board \ -I $(top_builddir)/src/board \ -I $(top_srcdir)/src/utils bin_PROGRAMS = quarry quarry_SOURCES = \ quarry.c \ \ gettext.h \ quarry.h \ quarry-main.h quarry_LDADD = \ $(top_builddir)/src/gui-gtk/libguigtk.a \ $(top_builddir)/src/gui-utils/libguiutils.a \ $(top_builddir)/src/gtp/libgtp.a \ $(top_builddir)/src/sgf/libsgf.a \ $(top_builddir)/src/board/libboard.a \ $(top_builddir)/src/utils/libutils.a \ \ $(QUARRY_GTK_LIBS) \ $(QUARRY_GTHREAD_LIBS) DISTCLEANFILES = *~ quarry-0.2.0/src/quarry.c0000644000175000017500000001273410367247764014003 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "gui-back-end.h" #include "gui-utils.h" #include "utils.h" #include "quarry-main.h" #include #include #include #include enum { /* Options with no short equivalent. */ OPTION_GTP_LOG = UCHAR_MAX + 1, OPTION_GTP_SHOW_STDERR, OPTION_HELP, OPTION_USAGE, OPTION_VERSION }; static const struct option quarry_options[] = { { "gtp-log", required_argument, NULL, OPTION_GTP_LOG }, { "gtp-show-stderr", no_argument, NULL, OPTION_GTP_SHOW_STDERR }, { "help", no_argument, NULL, OPTION_HELP }, { "usage", no_argument, NULL, OPTION_USAGE }, { "version", no_argument, NULL, OPTION_VERSION }, { NULL, no_argument, NULL, 0 } }; static const char *usage_string = "Usage: %s [OPTION...] [GAME-RECORD-FILE...]\n"; static const char *help_string = "\n" "GTP debugging options:\n" " --gtp-log=BASE-NAME log GTP streams to files named `BASE-NAME.';\n" " single hyphen stands for stdout\n" " --gtp-show-stderr pipe GTP servers' stderr to Quarry's stderr;\n" " if `--gtp-log' is specified, pipe stderr there\n" "\n" "Help options:\n" " --help display this help and exit\n" " --usage display brief usage message and exit\n" " --version output version information and exit\n" "\n" "Report bugs at https://gna.org/bugs/?group=quarry " "or to .\n"; static const char *version_string = PACKAGE_STRING "\n" "\n" "Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev and others.\n" "This is free software; see the source for copying conditions. There is NO\n" "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"; /* Global option variables. */ /* Whether to log GTP conversations and where. Either NULL (don't log * anything), points to '-' (log to stdout), or points to some other * string, in which case log to file named `.', where * BASE-NAME is the value of this variable and PID is the PID of the * child. */ const char *option_gtp_log_base_name = NULL; /* Whether to show children's stderr. If yes, pipe them to Quarry's * stderr, or to whatever `option_gtp_log_base_name' specifies if that * is non-NULL. */ int option_gtp_show_stderr = 0; int main (int argc, char *argv[]) { int return_code = 0; int option; utils_remember_program_name (argv[0]); /* As a side effect, gui_utils_enumerate_themes() determines if * Quarry is (supposedly properly) installed: it returns zero if no * themes are found. */ if (gui_utils_enumerate_themes ()) { bindtextdomain (PACKAGE, LOCALE_DIR); bind_textdomain_codeset (PACKAGE, "UTF-8"); textdomain (PACKAGE); if (gui_back_end_init (&argc, &argv)) { while ((option = getopt_long (argc, argv, "", quarry_options, NULL)) != -1) { switch (option) { case OPTION_GTP_LOG: option_gtp_log_base_name = optarg; break; case OPTION_GTP_SHOW_STDERR: option_gtp_show_stderr = 1; break; case OPTION_USAGE: case OPTION_HELP: printf (usage_string, full_program_name); if (option == OPTION_HELP) fputs (help_string, stdout); goto exit_quarry; case OPTION_VERSION: fputs (version_string, stdout); goto exit_quarry; default: fprintf (stderr, "Try `%s --help' for more information.\n", full_program_name); return_code = 255; goto exit_quarry; } } /* When a GTP engine crashes (or it is not a GTP engine to begin * with), we receive this signal and better not abort on it. */ signal (SIGPIPE, SIG_IGN); if (optind == argc) return_code = gui_back_end_main_default (); else { return_code = gui_back_end_main_open_files (argc - optind, argv + optind); } } else return_code = 253; } else return_code = 254; exit_quarry: gui_utils_discard_theme_lists (); utils_free_program_name_strings (); #if ENABLE_MEMORY_PROFILING utils_print_memory_profiling_info (); #endif return return_code; } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gettext.h0000644000175000017500000000635610237132521014130 0ustar bartbart/* Convenience header for conditional use of GNU . Copyright (C) 1995-1998, 2000-2002 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2, 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* 2005-05-07 Paul Pogonyshev * * Update FSF address in the legal notice above. * * 2004-08-21 Paul Pogonyshev * * Cast textdomain() and friends to `void' when NLS is disabled. * Otherwise GCC gives pointless warnings. */ #ifndef _LIBGETTEXT_H #define _LIBGETTEXT_H 1 /* NLS can be disabled through the configure --disable-nls option. */ #if ENABLE_NLS /* Get declarations of GNU message catalog functions. */ # include #else /* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which chokes if dcgettext is defined as a macro. So include it now, to make later inclusions of a NOP. We don't include as well because people using "gettext.h" will not include , and also including would fail on SunOS 4, whereas is OK. */ #if defined(__sun) # include #endif /* Disabled NLS. The casts to 'const char *' serve the purpose of producing warnings for invalid uses of the value returned from these functions. On pre-ANSI systems without 'const', the config.h file is supposed to contain "#define const". */ # define gettext(Msgid) ((const char *) (Msgid)) # define dgettext(Domainname, Msgid) ((const char *) (Msgid)) # define dcgettext(Domainname, Msgid, Category) ((const char *) (Msgid)) # define ngettext(Msgid1, Msgid2, N) \ ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2)) # define dngettext(Domainname, Msgid1, Msgid2, N) \ ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2)) # define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \ ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2)) # define textdomain(Domainname) ((void) (const char *) (Domainname)) # define bindtextdomain(Domainname, Dirname) ((void) (const char *) (Dirname)) # define bind_textdomain_codeset(Domainname, Codeset) \ ((void) (const char *) (Codeset)) #endif /* A pseudo function call that serves as a marker for the automated extraction of messages, but does not call gettext(). The run-time translation is done at a different place in the code. The argument, String, should be a literal string. Concatenated strings and other string expressions won't work. The macro's expansion is not parenthesized, so that it is suitable as initializer for static 'char[]' or 'const char[]' variables. */ #define gettext_noop(String) String #endif /* _LIBGETTEXT_H */ quarry-0.2.0/src/quarry.h0000644000175000017500000000657510367243004013775 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* The main purpose of this file is to use stuff in `config.h' in a * include-once protected way. There are also some commonly used * things, like i18n macros. * * It should be included in every other `.h' file. */ #ifndef QUARRY_H #define QUARRY_H #include "config.h" #include /* I prefer this to be stated explicitly. Also saves from warnings in * some compilers (and this warning is asked from GCC by `configure' * and Makefiles just to be aware of the problem). */ #define UNUSED(parameter) ((void) (parameter)) /* More portable va_copy(). */ #if defined va_copy #define QUARRY_VA_COPY(dest, src) va_copy ((dest), (src)) #elif defined __va_copy #define QUARRY_VA_COPY(dest, src) __va_copy ((dest), (src)) #else #ifdef HAVE_MEMORY_H #include #endif /* This is recommended by Autoconf manual. */ #define QUARRY_VA_COPY(dest, src) \ memcpy (&(dest), &(src), sizeof (va_list)) #endif /* A set of useful macros. */ #undef MIN #define MIN(a, b) ((a) < (b) ? (a) : (b)) #undef MAX #define MAX(a, b) ((a) > (b) ? (a) : (b)) #undef ROUND_DOWN #define ROUND_DOWN(value, power_of_2) \ ((value) & ~((power_of_2) - 1)) #undef ROUND_UP #define ROUND_UP(value, power_of_2) \ (((value) + (power_of_2) - 1) & ~((power_of_2) - 1)) /* I18n macros. The `gettext.h' header disables NLS itself, if * requested by `configure' script. */ #include "gettext.h" #define _(string) gettext (string) #define N_(string) gettext_noop (string) /* Function utils_gettext_with_context() is similar to GLib's * g_strip_context(), but also contains the call to gettext() itself. * Since the Q_() macro has the same signature, as GLib's variant, we * use the same name. */ #define Q_(string) utils_gettext_with_context (string) /* Determine if given byte (`character') starts an UTF-8 character, * probably a multi-byte one. */ #define IS_UTF8_STARTER(character) \ ((signed char) (character) >= (signed char) 0xc0) #endif /* QUARRY_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/quarry-main.h0000644000175000017500000000315010367243016014704 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef QUARRY_MAIN_H #define QUARRY_MAIN_H #include "quarry.h" extern const char *option_gtp_log_base_name; extern int option_gtp_show_stderr; #endif /* QUARRY_MAIN_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/utils/0000755000175000017500000000000010530402567013427 5ustar bartbartquarry-0.2.0/src/utils/Makefile.in0000644000175000017500000003410610425150133015470 0ustar bartbart# Makefile.in generated by automake 1.7.9 from Makefile.am. # @configure_input@ # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 # Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # Process this file with Automake to produce `Makefile.in'. srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = ../.. am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : host_triplet = @host@ ACLOCAL = @ACLOCAL@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BUILD_SGF_UTILS_FALSE = @BUILD_SGF_UTILS_FALSE@ BUILD_SGF_UTILS_TRUE = @BUILD_SGF_UTILS_TRUE@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DO_SCROLLKEEPER_UPDATE_FALSE = @DO_SCROLLKEEPER_UPDATE_FALSE@ DO_SCROLLKEEPER_UPDATE_TRUE = @DO_SCROLLKEEPER_UPDATE_TRUE@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ GMSGFMT = @GMSGFMT@ HAVE_SCROLLKEEPER_FALSE = @HAVE_SCROLLKEEPER_FALSE@ HAVE_SCROLLKEEPER_TRUE = @HAVE_SCROLLKEEPER_TRUE@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ LDFLAGS = @LDFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ MAKEINFO = @MAKEINFO@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGMERGE = @MSGMERGE@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSUB = @POSUB@ QUARRY_GTHREAD_CFLAGS = @QUARRY_GTHREAD_CFLAGS@ QUARRY_GTHREAD_LIBS = @QUARRY_GTHREAD_LIBS@ QUARRY_GTK_CFLAGS = @QUARRY_GTK_CFLAGS@ QUARRY_GTK_DEPRECATED_FLAGS = @QUARRY_GTK_DEPRECATED_FLAGS@ QUARRY_GTK_LIBS = @QUARRY_GTK_LIBS@ QUARRY_WARNINGS = @QUARRY_WARNINGS@ QUARRY_WARNINGS_GTK = @QUARRY_WARNINGS_GTK@ RANLIB = @RANLIB@ REGISTER_MIME_TYPES_FALSE = @REGISTER_MIME_TYPES_FALSE@ REGISTER_MIME_TYPES_TRUE = @REGISTER_MIME_TYPES_TRUE@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ ac_ct_CC = @ac_ct_CC@ ac_ct_RANLIB = @ac_ct_RANLIB@ ac_ct_STRIP = @ac_ct_STRIP@ ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ datadir = @datadir@ exec_prefix = @exec_prefix@ have_scrollkeeper = @have_scrollkeeper@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localstatedir = @localstatedir@ mandir = @mandir@ oldincludedir = @oldincludedir@ prefix = @prefix@ program_transform_name = @program_transform_name@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ AM_CPPFLAGS = \ $(QUARRY_WARNINGS) \ \ -I $(top_srcdir)/src noinst_LIBRARIES = \ libparselist.a \ libutils.a libutils_a_SOURCES = \ buffered-writer.c \ getopt.c \ getopt1.c \ memory-pool.c \ object-cache.c \ string-buffer.c \ string-list.c \ utils.c \ \ getopt.h \ utils.h libparselist_a_SOURCES = \ parse-list.c \ \ parse-list.h # This libraries are used for automated generation of source files in # other directories. TAGS_DEPENDENCIES = \ libutils.a \ libparselist.a DISTCLEANFILES = *~ subdir = src/utils ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 mkinstalldirs = $(SHELL) $(top_srcdir)/build/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = LIBRARIES = $(noinst_LIBRARIES) libparselist_a_AR = $(AR) cru libparselist_a_LIBADD = am_libparselist_a_OBJECTS = parse-list.$(OBJEXT) libparselist_a_OBJECTS = $(am_libparselist_a_OBJECTS) libutils_a_AR = $(AR) cru libutils_a_LIBADD = am_libutils_a_OBJECTS = buffered-writer.$(OBJEXT) getopt.$(OBJEXT) \ getopt1.$(OBJEXT) memory-pool.$(OBJEXT) object-cache.$(OBJEXT) \ string-buffer.$(OBJEXT) string-list.$(OBJEXT) utils.$(OBJEXT) libutils_a_OBJECTS = $(am_libutils_a_OBJECTS) DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/build/depcomp am__depfiles_maybe = depfiles @AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/buffered-writer.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/getopt.Po ./$(DEPDIR)/getopt1.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/memory-pool.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/object-cache.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/parse-list.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/string-buffer.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/string-list.Po ./$(DEPDIR)/utils.Po COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ DIST_SOURCES = $(libparselist_a_SOURCES) $(libutils_a_SOURCES) DIST_COMMON = $(srcdir)/Makefile.in Makefile.am SOURCES = $(libparselist_a_SOURCES) $(libutils_a_SOURCES) all: all-am .SUFFIXES: .SUFFIXES: .c .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4) cd $(top_srcdir) && \ $(AUTOMAKE) --foreign src/utils/Makefile Makefile: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) AR = ar clean-noinstLIBRARIES: -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) libparselist.a: $(libparselist_a_OBJECTS) $(libparselist_a_DEPENDENCIES) -rm -f libparselist.a $(libparselist_a_AR) libparselist.a $(libparselist_a_OBJECTS) $(libparselist_a_LIBADD) $(RANLIB) libparselist.a libutils.a: $(libutils_a_OBJECTS) $(libutils_a_DEPENDENCIES) -rm -f libutils.a $(libutils_a_AR) libutils.a $(libutils_a_OBJECTS) $(libutils_a_LIBADD) $(RANLIB) libutils.a mostlyclean-compile: -rm -f *.$(OBJEXT) core *.core distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/buffered-writer.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt1.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/memory-pool.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/object-cache.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parse-list.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/string-buffer.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/string-list.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ @am__fastdepCC_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ @am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ @am__fastdepCC_TRUE@ fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `test -f '$<' || echo '$(srcdir)/'`$< .c.obj: @am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ @am__fastdepCC_TRUE@ -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi`; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ @am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ @am__fastdepCC_TRUE@ fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi` uninstall-info-am: ETAGS = etags ETAGSFLAGS = CTAGS = ctags CTAGSFLAGS = tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(ETAGS_ARGS)$$tags$$unique" \ || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = ../.. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ case $$file in \ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ esac; \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ dir="/$$dir"; \ $(mkinstalldirs) "$(distdir)$$dir"; \ else \ dir=''; \ fi; \ if test -d $$d/$$file; then \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LIBRARIES) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -rm -f $(CONFIG_CLEAN_FILES) -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: info: info-am info-am: install-data-am: install-exec-am: install-info: install-info-am install-man: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-info-am .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ clean-noinstLIBRARIES ctags distclean distclean-compile \ distclean-generic distclean-tags distdir dvi dvi-am info \ info-am install install-am install-data install-data-am \ install-exec install-exec-am install-info install-info-am \ install-man install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-compile mostlyclean-generic pdf pdf-am \ ps ps-am tags uninstall uninstall-am uninstall-info-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: quarry-0.2.0/src/utils/Makefile.am0000644000175000017500000000113510112734225015456 0ustar bartbart# Process this file with Automake to produce `Makefile.in'. AM_CPPFLAGS = \ $(QUARRY_WARNINGS) \ \ -I $(top_srcdir)/src noinst_LIBRARIES = \ libparselist.a \ libutils.a libutils_a_SOURCES = \ buffered-writer.c \ getopt.c \ getopt1.c \ memory-pool.c \ object-cache.c \ string-buffer.c \ string-list.c \ utils.c \ \ getopt.h \ utils.h libparselist_a_SOURCES = \ parse-list.c \ \ parse-list.h # This libraries are used for automated generation of source files in # other directories. TAGS_DEPENDENCIES = \ libutils.a \ libparselist.a DISTCLEANFILES = *~ quarry-0.2.0/src/utils/parse-list.c0000644000175000017500000007222010367243120015655 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "parse-list.h" #include "utils.h" #include #include #include #include #include #include #include #include typedef struct _FileListItem FileListItem; typedef struct _FileList FileList; struct _FileListItem { FileListItem *next; char *filename; FILE *file; int line_number; }; struct _FileList { FileListItem *first; FileListItem *last; int item_size; StringListItemDispose item_dispose; }; #define file_list_new() \ ((FileList *) string_list_new_derived (sizeof (FileListItem), \ ((StringListItemDispose) \ file_list_item_dispose))) #define file_list_init(list) \ string_list_init_derived ((list), sizeof (FileListItem), \ ((StringListItemDispose) \ file_list_item_dispose)) #define STATIC_FILE_LIST \ STATIC_STRING_LIST_DERIVED (FileListItem, file_list_item_dispose) static void file_list_item_dispose (FileListItem *item); #define file_list_get_item(list, item_index) \ ((FileListItem *) string_list_get_item ((list), (item_index))) #define file_list_find(list, filename) \ ((FileListItem *) string_list_find ((list), (filename))) #define file_list_find_after_notch(list, filename, notch) \ ((FileListItem *) \ string_list_find_after_notch ((list), (filename), (notch))) typedef struct _ConditionStackEntry ConditionStackEntry; struct _ConditionStackEntry { ConditionStackEntry *next; const PredefinedCondition *condition; char is_true; char is_in_else_clause; }; inline static void print_usage (FILE *where); static FILE * open_file (const char *filename, int for_writing); static int do_parse_lists (FILE *h_file, FILE *c_file, const ListDescription *lists); static void reuse_last_line (char **current_line); static const PredefinedCondition * get_condition (char **line); inline static void push_condition_stack (const PredefinedCondition *condition, int is_negated); inline static void pop_condition_stack (void); const char *tab_string = "\t\t\t\t\t\t\t\t\t\t\t\t"; StringBuffer h_file_top; StringBuffer h_file_bottom; StringBuffer c_file_top; StringBuffer c_file_bottom; static AssociationList substitutions = STATIC_ASSOCIATION_LIST; static const PredefinedCondition *predefined_conditions; static FileList list_files = STATIC_FILE_LIST; static StringList lines = STATIC_STRING_LIST; static int last_line_reusable = 0; static ConditionStackEntry *condition_stack = NULL; enum { OPTION_HELP = UCHAR_MAX + 1 }; static const struct option parse_list_options[] = { { "help", no_argument, NULL, OPTION_HELP }, { "define", required_argument, NULL, 'D' }, { "substitute", required_argument, NULL, 'D' }, { NULL, no_argument, NULL, 0 } }; static const char *help_string = "\n" "Options:\n" " -D, --define SYMBOL=SUBSTITUTION\n" " define a symbol for `$...$'-style substitutions\n" " --help display this help and exit\n"; int parse_list_main (int argc, char *argv[], const ListDescriptionSet *list_sets, int num_sets, const PredefinedCondition *conditions) { int option; int result = 255; utils_remember_program_name (argv[0]); while ((option = getopt_long (argc, argv, "D:", parse_list_options, NULL)) != -1) { switch (option) { case OPTION_HELP: print_usage (stdout); printf (help_string); result = 0; goto exit_parse_list_main; case 'D': { const char *delimiter = strchr (optarg, '='); if (delimiter) { if (memchr (optarg, '$', delimiter - optarg)) { fprintf (stderr, ("%s: fatal: " "substitution name cannot contain dollar signs\n"), short_program_name); goto exit_parse_list_main; } string_list_add_from_buffer (&substitutions, optarg, delimiter - optarg); substitutions.last->association = utils_duplicate_string (delimiter + 1); } else { string_list_add (&substitutions, optarg); substitutions.last->association = utils_duplicate_string (""); } } break; default: fprintf (stderr, "Try `%s --help' for more information.\n", full_program_name); goto exit_parse_list_main; } } if (argc - optind == 3) { char *list_file_name = argv[optind]; char *h_file_name = argv[optind + 1]; char *c_file_name = argv[optind + 2]; FILE *list_file = open_file (list_file_name, 0); if (list_file) { char *line; const ListDescription *lists = NULL; int k; string_list_prepend (&list_files, list_file_name); list_files.first->file = list_file; list_files.first->line_number = 0; do line = read_line (); while (line && (! *line || *line == '#')); if (looking_at ("@mode", &line)) { const char *mode = parse_thing (IDENTIFIER, &line, "mode name"); if (mode) { for (k = 0; k < num_sets; k++) { if (strcmp (mode, list_sets[k].mode_name) == 0) { lists = list_sets[k].lists; break; } } if (!lists) print_error ("fatal: unknown mode `%s'", mode); } } else print_error ("fatal: `@mode' expected"); if (lists) { FILE *h_file = open_file (h_file_name, 1); if (h_file) { FILE *c_file = open_file (c_file_name, 1); if (c_file) { static const char *preamble = "/* This file is automatically generated by `%s'.\n" " * Do not modify it, edit `%s' instead.\n" " */\n"; int n; int h_file_name_length = strlen (h_file_name); fprintf (h_file, preamble, short_program_name, list_file_name); fprintf (c_file, preamble, short_program_name, list_file_name); for (k = h_file_name_length; k >= 1; k--) { if (h_file_name[k - 1] == DIRECTORY_SEPARATOR) break; } for (n = 0; k < h_file_name_length; k++) { if (isalnum (h_file_name[k])) h_file_name[n++] = toupper (h_file_name[k]); else if (h_file_name[k] == '.' || h_file_name[k] == '_' || h_file_name[k] == '-') h_file_name[n++] = '_'; } h_file_name[n] = 0; if (n > 4 && strcmp (h_file_name + n - 4, "_NEW") == 0) h_file_name[n - 4] = 0; fprintf (h_file, "\n\n#ifndef QUARRY_%s\n#define QUARRY_%s\n", h_file_name, h_file_name); predefined_conditions = conditions; result = do_parse_lists (h_file, c_file, lists); fprintf (h_file, "\n\n#endif /* QUARRY_%s */\n", h_file_name); fclose (c_file); } fclose (h_file); } } string_list_empty (&list_files); while (condition_stack) pop_condition_stack (); } } else { print_usage (stderr); fprintf (stderr, "Try `%s --help' for more information.\n", full_program_name); } exit_parse_list_main: string_list_empty (&substitutions); utils_free_program_name_strings (); return result; } static void print_usage (FILE *where) { fprintf (where, "Usage: %s [OPTION]... LIST_FILE H_FILE C_FILE\n", full_program_name); } static void file_list_item_dispose (FileListItem *item) { fclose (item->file); } static FILE * open_file (const char *filename, int for_writing) { FILE *file = fopen (filename, for_writing ? "w" : "r"); if (!file) { fprintf (stderr, "%s: can't open file `%s' for %s\n", short_program_name, filename, for_writing ? "writing" : "reading"); } return file; } static int do_parse_lists (FILE *h_file, FILE *c_file, const ListDescription *lists) { int k; int result = 1; int had_c_includes = 0; int had_h_includes = 0; int in_list = 0; int equal_to_last = 0; int h_file_line_length = 0; int num_c_file_array_elements = 0; int pending_linefeeds = 0; const char *h_file_enum_name = NULL; const char *c_file_array_name = NULL; char *last_identifier = NULL; char *pending_h_comment = NULL; char *pending_c_comment = NULL; char *pending_eol_comment = NULL; StringBuffer c_file_arrays[NUM_LIST_SORT_ORDERS]; StringBuffer *list_c_file_array = NULL; StringBuffer h_file_enums; string_buffer_init (&h_file_top, 0x2000, 0x1000); string_buffer_init (&h_file_bottom, 0x2000, 0x1000); string_buffer_init (&h_file_enums, 0x2000, 0x1000); string_buffer_init (&c_file_top, 0x2000, 0x1000); string_buffer_init (&c_file_bottom, 0x2000, 0x1000); for (k = 0; k < NUM_LIST_SORT_ORDERS; k++) string_buffer_init (&c_file_arrays[k], 0x2000, 0x1000); while (1) { char *line = read_line (); if (!line) { while (lists->name && lists->multiple_lists_allowed) lists++; if (!condition_stack) { if (!lists->name) { result = 0; if (lists->list_finalizer) { if (lists->list_finalizer (NULL)) result = 1; } } else { fprintf (stderr, "%s: unexpected end of file: list of type `%s' expected\n", short_program_name, lists->name); } } else { fprintf (stderr, "%s: unexpected end of file: condition `%s' unterminated\n", short_program_name, condition_stack->condition->identifier); } break; } if (! *line) continue; if (line[0] == '#') { if (line[1] == '>') { line = line + 2; while (isspace (*line)) line++; utils_free (pending_h_comment); pending_h_comment = utils_duplicate_string (line); utils_free (pending_c_comment); pending_c_comment = utils_duplicate_string (line); } continue; } if (in_list) { if (line[0] != '}') { char first_char = line[0]; const char *identifier = NULL; if (first_char != '=' && first_char != '+') { if (lists->line_parser1) { if (lists->line_parser1 (&line)) break; if (!line) continue; while (*line && isspace (*line)) line++; } } else { if (!h_file_enum_name) { print_error ("`+' and `=' directives are not allowed " "in lists that don't generate enumerations"); break; } do line++; while (isspace (*line)); } if ((!pending_eol_comment || ! *pending_eol_comment) && last_identifier && h_file_enum_name) string_buffer_cat_string (&h_file_enums, ",\n"); if (pending_eol_comment) { if (*pending_eol_comment && h_file_enum_name) { string_buffer_cprintf (&h_file_enums, ",%s/* %s */\n", TABBING (7, h_file_line_length + 1), pending_eol_comment); } utils_free (pending_eol_comment); pending_eol_comment = NULL; } if (pending_h_comment) { if (*pending_h_comment && h_file_enum_name) { if (last_identifier) string_buffer_add_character (&h_file_enums, '\n'); string_buffer_cat_strings (&h_file_enums, " /* ", pending_h_comment, " */\n", NULL); } utils_free (pending_h_comment); pending_h_comment = NULL; } if (h_file_enum_name) { identifier = parse_thing (IDENTIFIER, &line, "identifier"); if (!identifier) break; string_buffer_cat_strings (&h_file_enums, " ", identifier, NULL); h_file_line_length = 2 + strlen (identifier); if (first_char == '=' || equal_to_last) { string_buffer_cat_strings (&h_file_enums, " = ", last_identifier, NULL); h_file_line_length += 3 + strlen (last_identifier); } utils_free (last_identifier); last_identifier = utils_duplicate_string (identifier); } if (first_char != '+') { if (first_char != '=') { if (c_file_array_name && *lists->c_file_array_type) { if (num_c_file_array_elements > 0) { string_buffer_add_character (list_c_file_array, ','); string_buffer_add_characters (list_c_file_array, '\n', 1 + pending_linefeeds); } if (pending_c_comment) { if (*pending_c_comment) { if (num_c_file_array_elements > 0) string_buffer_add_character (list_c_file_array, '\n'); string_buffer_cat_strings (list_c_file_array, " /* ", pending_c_comment, " */\n", NULL); } utils_free (pending_c_comment); pending_c_comment = NULL; } } if (c_file_array_name) num_c_file_array_elements++; pending_linefeeds = 0; if (lists->line_parser2 (list_c_file_array, &line, identifier, &pending_eol_comment, &pending_linefeeds)) break; if (*line) { print_error ("unexpected characters at the end of line"); break; } if (pending_linefeeds < 0) { pending_linefeeds = 0; if (! *line) { while (1) { line = read_line (); if (line && ! *line) pending_linefeeds++; else { reuse_last_line (&line); break; } } } } } equal_to_last = 0; } else { if (equal_to_last) { print_error ("second inserted identifier in a row; " "did you mean `='?"); break; } equal_to_last = 1; } } else { if (!last_identifier && num_c_file_array_elements == 0) { print_error ("empty list `%s'", lists->name); break; } if (pending_eol_comment) { if (*pending_eol_comment && h_file_enum_name) { string_buffer_cprintf (&h_file_enums, "%s/* %s */", TABBING (7, h_file_line_length), pending_eol_comment); } utils_free (pending_eol_comment); pending_eol_comment = NULL; } if (lists->list_finalizer) { if (lists->list_finalizer (list_c_file_array)) break; } if (h_file_enum_name) { if (strcmp (h_file_enum_name, "unnamed") != 0) { string_buffer_cat_strings (&h_file_enums, "\n} ", h_file_enum_name, ";\n", NULL); } else string_buffer_cat_string (&h_file_enums, "\n};\n"); } if (c_file_array_name && *lists->c_file_array_type) string_buffer_cat_string (list_c_file_array, "\n};\n"); if (!lists->multiple_lists_allowed) lists++; in_list = 0; } } else { if (looking_at ("@include", &line) || looking_at ("@c_include", &line)) { if (! *line) { print_error ("filename expected"); break; } if (!had_c_includes) { fputs ("\n\n", c_file); had_c_includes = 1; } fprintf (c_file, "#include %s\n", line); } else if (looking_at ("@h_include", &line)) { if (! *line) { print_error ("filename expected"); break; } if (had_h_includes != 1) { fputs ((had_h_includes == 0 ? "\n\n" : "\n"), h_file); had_h_includes = 1; } fprintf (h_file, "#include %s\n", line); } else if (looking_at ("@define_condition", &line)) { const PredefinedCondition *condition = get_condition (&line); if (!condition) break; if (had_h_includes != 2) { fputs ((had_h_includes == 0 ? "\n\n" : "\n"), h_file); had_h_includes = 2; } fprintf (h_file, "#define %s%s%d\n", condition->identifier, TABBING (4, 8 + strlen (condition->identifier)), condition->value); } else { const char *identifier = parse_thing (IDENTIFIER, &line, "list name"); if (!identifier) break; if (!lists->name) { print_error ("unexpected list beginning"); break; } if (lists->multiple_lists_allowed && strcmp (identifier, lists->name) != 0 && (lists + 1)->name) lists++; if (strcmp (identifier, lists->name) == 0) { if (looking_at ("-", &line)) { if (lists->enumeration_required) { print_error ("enumeration name expected"); break; } h_file_enum_name = NULL; } else { h_file_enum_name = parse_thing (IDENTIFIER, &line, "enumeration name"); if (!h_file_enum_name) break; } if (!lists->c_file_array_type) { if (!looking_at ("-", &line)) { print_error ("unexpected array name"); break; } c_file_array_name = NULL; } else { if (looking_at ("-", &line)) { print_error ("array name expected"); break; } c_file_array_name = parse_thing (IDENTIFIER, &line, "array name"); if (!c_file_array_name) break; } if (*line != '{') { print_error ("list opening brace expected"); break; } if (*(line + 1)) { print_error ("unexpected characters at the end of line"); break; } if (pending_h_comment) { if (*pending_h_comment && h_file_enum_name) { string_buffer_cat_strings (&h_file_enums, "/* ", pending_h_comment, " */\n", NULL); } utils_free (pending_h_comment); pending_h_comment = NULL; } assert (0 <= lists->sort_order && lists->sort_order <= NUM_LIST_SORT_ORDERS); list_c_file_array = &c_file_arrays[lists->sort_order]; if (h_file_enum_name) { if (strcmp (h_file_enum_name, "unnamed") != 0) string_buffer_cat_string (&h_file_enums, "\n\ntypedef enum {\n"); else string_buffer_cat_string (&h_file_enums, "\n\nenum {\n"); } if (c_file_array_name && *lists->c_file_array_type) { string_buffer_cat_strings (list_c_file_array, "\n\n", lists->c_file_array_type, c_file_array_name, "[] = {\n", NULL); } if (lists->list_initializer) { if (lists->list_initializer (list_c_file_array, h_file_enum_name, c_file_array_name)) break; } in_list = 1; equal_to_last = 0; num_c_file_array_elements = 0; pending_linefeeds = 1; utils_free (last_identifier); last_identifier = NULL; } else { print_error ("list name `%s' expected, got `%s'", lists->name, identifier); break; } } } } if (h_file_top.length > 0) fwrite (h_file_top.string, h_file_top.length, 1, h_file); if (h_file_enums.length > 0) fwrite (h_file_enums.string, h_file_enums.length, 1, h_file); if (h_file_bottom.length > 0) fwrite (h_file_bottom.string, h_file_bottom.length, 1, h_file); string_buffer_dispose (&h_file_top); string_buffer_dispose (&h_file_bottom); string_buffer_dispose (&h_file_enums); if (c_file_top.length > 0) fwrite (c_file_top.string, c_file_top.length, 1, c_file); for (k = 0; k < NUM_LIST_SORT_ORDERS; k++) { fwrite (c_file_arrays[k].string, c_file_arrays[k].length, 1, c_file); string_buffer_dispose (&c_file_arrays[k]); } if (c_file_bottom.length > 0) fwrite (c_file_bottom.string, c_file_bottom.length, 1, c_file); string_buffer_dispose (&c_file_top); string_buffer_dispose (&c_file_bottom); utils_free (last_identifier); utils_free (pending_h_comment); utils_free (pending_c_comment); utils_free (pending_eol_comment); string_list_empty (&lines); return result; } static void reuse_last_line (char **current_line) { static char empty_line[] = ""; assert (!last_line_reusable); last_line_reusable = 1; *current_line = empty_line; } void print_error (const char *format_string, ...) { va_list arguments; if (!string_list_is_empty (&list_files)) { fprintf (stderr, "%s:%d: ", list_files.first->filename, list_files.first->line_number); } va_start (arguments, format_string); vfprintf (stderr, format_string, arguments); va_end (arguments); fputc ('\n', stderr); } char * read_line (void) { char *line; if (!last_line_reusable) { int length; char *beginning; char *end; read_next_line: line = NULL; while (!line && !string_list_is_empty (&list_files)) { line = utils_fgets (list_files.first->file, &length); if (!line) string_list_delete_first_item (&list_files); } if (!line) return NULL; list_files.first->line_number++; for (beginning = line; *beginning; beginning++) { if (!isspace (*beginning)) break; } for (end = line + length; end > beginning; end--) { if (!isspace (*(end - 1))) break; } *end = 0; if (*beginning) { char *scan; for (scan = beginning; scan < end; scan++) { if (*scan == '$') { if (* ++scan == '$') { char *copy_scan; for (copy_scan = scan; copy_scan < end; copy_scan++) *copy_scan = *(copy_scan + 1); end--; } else { char *second_delimiter_scan; for (second_delimiter_scan = scan + 1; second_delimiter_scan < end; second_delimiter_scan++) { if (*second_delimiter_scan == '$') break; } if (second_delimiter_scan < end) { const char *substitution; int substitution_length; char *new_line; *second_delimiter_scan = 0; substitution = association_list_find_association (&substitutions, scan); if (!substitution) { print_error ("undefined substitution symbol `%s'", scan); goto error; } substitution_length = strlen (substitution); new_line = utils_cat_as_strings (NULL, beginning, (scan - 1) - beginning, substitution, substitution_length, second_delimiter_scan + 1, end - (second_delimiter_scan + 1), NULL); scan = new_line + (((scan - 1) - beginning) + substitution_length); beginning = new_line; end = scan + (end - (second_delimiter_scan + 1)); utils_free (line); line = new_line; } else { print_error ("warning: possible unterminated substitution"); break; } } } } if (looking_at ("@include_list", &beginning)) { if (*beginning) { FILE *new_list_file = fopen (beginning, "r"); if (new_list_file) { string_list_prepend_from_buffer (&list_files, beginning, end - beginning); list_files.first->file = new_list_file; list_files.first->line_number = 0; } else { print_error ("can't open file %s for reading", beginning); string_list_empty (&list_files); } } else { print_error ("name of file to include is missing"); string_list_empty (&list_files); } utils_free (line); goto read_next_line; } else if (looking_at ("@if", &beginning)) { const PredefinedCondition *condition = get_condition (&beginning); if (!condition) goto error; push_condition_stack (condition, 0); utils_free (line); goto read_next_line; } else if (looking_at ("@ifnot", &beginning)) { const PredefinedCondition *condition = get_condition (&beginning); if (!condition) goto error; push_condition_stack (condition, 1); utils_free (line); goto read_next_line; } else if (looking_at ("@else", &beginning)) { if (!condition_stack || condition_stack->is_in_else_clause) { print_error ("unexpected `@else'"); goto error; } condition_stack->is_in_else_clause = 1; utils_free (line); goto read_next_line; } else if (looking_at ("@endif", &beginning)) { if (!condition_stack) { print_error ("unexpected `@endif'"); goto error; } pop_condition_stack (); utils_free (line); goto read_next_line; } } if (condition_stack && !(condition_stack->is_true ^ condition_stack->is_in_else_clause)) { /* In conditioned block and with false condition: skip line. */ utils_free (line); goto read_next_line; } string_list_add_from_buffer (&lines, beginning, end - beginning); utils_free (line); } last_line_reusable = 0; return lines.last->text; error: string_list_empty (&list_files); utils_free (line); return NULL; } static const PredefinedCondition * get_condition (char **line) { const PredefinedCondition *condition; const char *condition_identifier = parse_thing (IDENTIFIER, line, "condition identifier"); if (!condition_identifier) return NULL; for (condition = predefined_conditions; condition->identifier; condition++) { if (strcmp (condition->identifier, condition_identifier) == 0) return condition; } print_error ("unknown condition identifier `%s'", condition_identifier); return NULL; } const char * parse_thing (Thing thing, char **line, const char *type) { const char *value; while (*line && ! **line) *line = read_line (); if (! *line) { print_error ("%s expected", type); return NULL; } value = *line; if (thing != STRING && thing != STRING_OR_NULL && (thing != STRING_OR_IDENTIFIER || **line != '"')) { do { int expected_character; switch (thing) { case IDENTIFIER: case STRING_OR_IDENTIFIER: expected_character = (isalpha (**line) || **line == '_' || (*line != value && isdigit (**line))); break; case PROPERTY_IDENTIFIER: expected_character = isupper (**line); break; case FIELD_NAME: expected_character = (isalpha (**line) || **line == '_' || ** line == '[' || (*line != value && (isdigit (**line) || **line == '.' || **line == ']'))); break; case INTEGER_NUMBER: expected_character = isdigit (**line); break; case FLOATING_POINT_NUMBER: expected_character = isdigit (**line) || **line == '.'; break; case TIME_VALUE: expected_character = (isdigit (**line) || **line == ':' || **line == '.'); break; default: assert (0); } if (!expected_character) { print_error ("unexpected character '%c' in %s", **line, type); return NULL; } (*line)++; } while (**line && !isspace (**line)); } else { if (thing == STRING_OR_NULL) { char *possible_null = *line; if (looking_at ("NULL", line)) { *(possible_null + 4) = 0; return possible_null; } } if (**line != '"') { print_error ("string%s expected", (thing == STRING ? "" : (thing == STRING_OR_NULL ? " or NULL" : "or identifier"))); return NULL; } while (1) { (*line)++; if (! **line || (**line == '\\' && ! *(*line + 1))) { print_error ("unterminated string"); return NULL; } if (**line == '"') { (*line)++; break; } if (**line == '\\') (*line)++; } } if (**line) { **line = 0; do (*line)++; while (isspace (**line)); } return value; } char * parse_multiline_string (char **line, const char *type, const char *line_separator, int null_allowed) { const char *string_chunk; char *string; string_chunk = parse_thing (null_allowed ? STRING_OR_NULL : STRING, line, type); if (!string_chunk) return NULL; string = utils_duplicate_string (string_chunk); if (*string != '"') return string; while (! **line) { *line = read_line (); if (! *line) { utils_free (string); return NULL; } if (**line == '"') { string_chunk = parse_thing (STRING, line, type); if (!string_chunk) { utils_free (string); return NULL; } string = utils_cat_strings (string, line_separator, string_chunk, NULL); } else { reuse_last_line (line); break; } } return string; } int parse_color (char **line, QuarryColor *color, const char *type) { int num_digits; int red; int green; int blue; while (*line && ! **line) *line = read_line (); if (! *line || * (*line)++ != '#') { print_error ("%s expected", type); return 0; } for (num_digits = 0; isxdigit (**line) && num_digits <= 6; num_digits++) (*line)++; if ((num_digits != 6 && num_digits != 3) || (**line && !isspace (**line))) { print_error ("%s expected", type); return 0; } if (num_digits == 6) sscanf ((*line) - 6, "%2x%2x%2x", &red, &green, &blue); else { sscanf ((*line) - 3, "%1x%1x%1x", &red, &green, &blue); red *= 0x11; green *= 0x11; blue *= 0x11; } while (isspace (**line)) (*line)++; color->red = red; color->green = green; color->blue = blue; return 1; } int looking_at (const char *what, char **line) { int length = strlen (what); while (*line && ! **line) *line = read_line (); if (*line && strncmp (*line, what, length) == 0 && (!(*line) [length] || isspace ((*line) [length]))) { *line += length; while (isspace (**line)) (*line)++; return 1; } return 0; } inline static void push_condition_stack (const PredefinedCondition *condition, int is_negated) { ConditionStackEntry *entry = utils_malloc (sizeof (ConditionStackEntry)); entry->condition = condition; entry->is_true = (condition->value != 0) ^ (is_negated != 0); entry->is_in_else_clause = 0; entry->next = condition_stack; condition_stack = entry; } inline static void pop_condition_stack (void) { ConditionStackEntry *entry = condition_stack; condition_stack = entry->next; utils_free (entry); } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/utils/parse-list.h0000644000175000017500000000766410367243132015677 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef QUARRY_PARSE_LIST_H #define QUARRY_PARSE_LIST_H #include "utils.h" #include "quarry.h" #include #define TABBING(tab_position, from) \ ((tab_position) > (from) / 8 \ ? tab_string + 12 - ((tab_position) - ((from) / 8)) : " ") typedef enum { SORT_FIRST, SORT_NORMAL, SORT_LAST, NUM_LIST_SORT_ORDERS } ListSortOrder; typedef struct _ListDescription ListDescription; typedef struct _ListDescriptionSet ListDescriptionSet; typedef struct _PredefinedCondition PredefinedCondition; struct _ListDescription { const char *name; int multiple_lists_allowed; ListSortOrder sort_order; int enumeration_required; const char *c_file_array_type; int (* list_initializer) (StringBuffer *c_file_array, const char *h_file_enum_name, const char *c_file_array_name); int (* line_parser1) (char **line); int (* line_parser2) (StringBuffer *c_file_array, char **line, const char *identifier, char **pending_eol_comment, int *pending_linefeeds); int (* list_finalizer) (StringBuffer *c_file_array); }; struct _ListDescriptionSet { const char *mode_name; const ListDescription *lists; }; struct _PredefinedCondition { const char *identifier; int value; }; typedef enum { IDENTIFIER, PROPERTY_IDENTIFIER, FIELD_NAME, INTEGER_NUMBER, FLOATING_POINT_NUMBER, TIME_VALUE, STRING, STRING_OR_NULL, STRING_OR_IDENTIFIER, } Thing; int parse_list_main (int argc, char *argv[], const ListDescriptionSet *list_sets, int num_sets, const PredefinedCondition *conditions); void print_error (const char *format_string, ...); char * read_line (void); const char * parse_thing (Thing thing, char **line, const char *type); char * parse_multiline_string (char **line, const char *type, const char *line_separator, int null_allowed); int parse_color (char **line, QuarryColor *color, const char *type); #define PARSE_THING(store_in, thing, line, type) \ do { \ (store_in) = parse_thing ((thing), (line), (type)); \ if (!(store_in)) \ return 1; \ } while (0) #define PARSE_IDENTIFIER(store_in, line, type) \ PARSE_THING ((store_in), IDENTIFIER, (line), (type)) int looking_at (const char *what, char **line); extern StringBuffer h_file_top; extern StringBuffer h_file_bottom; extern StringBuffer c_file_top; extern StringBuffer c_file_bottom; extern const char *tab_string; #endif /* QUARRY_PARSE_LIST_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/utils/buffered-writer.c0000644000175000017500000003045510520636027016675 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* This module provides a buffered file writer with a few useful * features: * * - Allows on-the-fly re-encoding of incoming text. Moreover, * required encoding can change arbitrary between writes to the * buffer (use buffered_writer_set_iconv_handle() macro to change * it). Incoming text must be in UTF-8. * * - Tracks current column in the output stream, thus making output * formatting easier for higher level code. */ #include "utils.h" #include #include #include #include #include /* For memrchr(), if it is present at all. */ #define __USE_GNU #include #ifdef HAVE_MEMORY_H #include #endif static void flush_buffer (BufferedWriter *writer); static void update_column (BufferedWriter *writer, const char *buffer, size_t length); const char* buffered_writer_init (BufferedWriter *writer, const char *filename, size_t buffer_size) { assert (writer); assert (buffer_size > MB_LEN_MAX); if (filename) { writer->file = fopen (filename, "wb"); if (!writer->file) return strerror (errno); } else writer->file = stdout; writer->first_chunk = NULL; writer->buffer_size = buffer_size; writer->buffer = utils_malloc (buffer_size); writer->buffer_pointer = writer->buffer; writer->buffer_end = writer->buffer + buffer_size; writer->iconv_handle = NULL; writer->column = 0; writer->successful = 1; writer->error_string = NULL; return NULL; } void buffered_writer_init_memory (BufferedWriter *writer, size_t buffer_size) { assert (writer); assert (buffer_size > sizeof (BufferedWriterChunkData) + MB_LEN_MAX); writer->file = NULL; writer->first_chunk = utils_malloc (buffer_size); writer->buffer_size = buffer_size; writer->buffer = (char *) (writer->first_chunk + 1); writer->buffer_pointer = writer->buffer; writer->buffer_end = ((char *) writer->first_chunk) + buffer_size; writer->iconv_handle = NULL; writer->column = 0; writer->successful = 1; writer->first_chunk->next_chunk = NULL; } int buffered_writer_dispose (BufferedWriter *writer) { assert (writer); assert (writer->file); assert (!writer->first_chunk); if (writer->buffer_pointer != writer->buffer) flush_buffer (writer); if (writer->file != stdout) fclose (writer->file); utils_free (writer->buffer); utils_free (writer->error_string); return writer->successful; } char * buffered_writer_dispose_memory (BufferedWriter *writer, int *data_length) { BufferedWriterChunkData *chunk; char *result; char *result_scan; assert (writer); assert (!writer->file); assert (writer->first_chunk); assert (data_length); chunk = ((BufferedWriterChunkData*) writer->buffer) - 1; chunk->chunk_size = writer->buffer_pointer - writer->buffer; *data_length = 0; for (chunk = writer->first_chunk; chunk; chunk = chunk->next_chunk) *data_length += chunk->chunk_size; result = utils_malloc (*data_length); result_scan = result; for (chunk = writer->first_chunk; chunk;) { BufferedWriterChunkData *next_chunk = chunk->next_chunk; memcpy (result_scan, (char *) (chunk + 1), chunk->chunk_size); result_scan += chunk->chunk_size; utils_free (chunk); chunk = next_chunk; } return result; } void buffered_writer_add_character (BufferedWriter *writer, char character) { assert (writer); /* The character must not be a multi-byte UTF-8 character. */ assert (!(character & 0x80) && character != '\n'); if (!writer->iconv_handle) *writer->buffer_pointer++ = character; else { char *input_text = &character; size_t input_bytes_left = 1; size_t output_bytes_left = writer->buffer_end - writer->buffer_pointer; iconv (writer->iconv_handle, &input_text, &input_bytes_left, &writer->buffer_pointer, &output_bytes_left); if (input_bytes_left) { flush_buffer (writer); iconv (writer->iconv_handle, &input_text, &input_bytes_left, &writer->buffer_pointer, &output_bytes_left); } } if (writer->buffer_pointer == writer->buffer_end) flush_buffer (writer); writer->column++; if (character == '\t') writer->column = ROUND_UP (writer->column, 8); } /* FIXME: Output system-specific line terminator. */ void buffered_writer_add_newline (BufferedWriter *writer) { assert (writer); if (!writer->iconv_handle) *writer->buffer_pointer++ = '\n'; else { char input_character = '\n'; char *input_text = &input_character; size_t input_bytes_left = 1; size_t output_bytes_left = writer->buffer_end - writer->buffer_pointer; iconv (writer->iconv_handle, &input_text, &input_bytes_left, &writer->buffer_pointer, &output_bytes_left); if (input_bytes_left) { flush_buffer (writer); iconv (writer->iconv_handle, &input_text, &input_bytes_left, &writer->buffer_pointer, &output_bytes_left); } } if (writer->buffer_pointer == writer->buffer_end) flush_buffer (writer); writer->column = 0; } void buffered_writer_cat_string (BufferedWriter *writer, const char *string) { buffered_writer_cat_as_string (writer, string, strlen (string)); } void buffered_writer_cat_strings (BufferedWriter *writer, ...) { va_list arguments; const char *string; va_start (arguments, writer); while ((string = va_arg (arguments, const char *)) != NULL) buffered_writer_cat_as_string (writer, string, strlen (string)); va_end (arguments); } void buffered_writer_cat_as_string (BufferedWriter *writer, const char *buffer, size_t length) { assert (writer); assert (buffer); update_column (writer, buffer, length); if (!writer->iconv_handle) { while (length > 0) { size_t chunk_size = MIN (length, writer->buffer_end - writer->buffer_pointer); memcpy (writer->buffer_pointer, buffer, chunk_size); writer->buffer_pointer += chunk_size; if (writer->buffer_pointer == writer->buffer_end) flush_buffer (writer); buffer += chunk_size; length -= chunk_size; } } else { while (length > 0) { size_t output_bytes_left = writer->buffer_end - writer->buffer_pointer; /* Dumb doesn't apply `const' to input buffer?! This * is nasty, but a warning for nothing is even worse. */ iconv (writer->iconv_handle, (char **) (void *) &buffer, &length, &writer->buffer_pointer, &output_bytes_left); if (writer->buffer_pointer == writer->buffer_end) flush_buffer (writer); } } } void buffered_writer_cat_as_strings (BufferedWriter *writer, ...) { va_list arguments; const char *buffer; va_start (arguments, writer); while ((buffer = va_arg (arguments, const char *)) != NULL) buffered_writer_cat_as_string (writer, buffer, va_arg (arguments, size_t)); va_end (arguments); } void buffered_writer_printf (BufferedWriter *writer, const char *format_string, ...) { va_list arguments; va_start (arguments, format_string); buffered_writer_vprintf (writer, format_string, arguments); va_end (arguments); } void buffered_writer_vprintf (BufferedWriter *writer, const char *format_string, va_list arguments) { va_list arguments_copy; size_t characters_written; char *string; assert (writer); assert (format_string); if (!writer->iconv_handle && (writer->buffer_end - writer->buffer_pointer >= strlen (format_string))) { /* No encoding conversion is requested. Try to print the string * directly in the buffer. */ QUARRY_VA_COPY (arguments_copy, arguments); characters_written = vsnprintf (writer->buffer_pointer, (writer->buffer_end - writer->buffer_pointer), format_string, arguments_copy); va_end (arguments_copy); if (characters_written < writer->buffer_end - writer->buffer_pointer && characters_written != -1) { update_column (writer, writer->buffer_pointer, characters_written); writer->buffer_pointer += characters_written; return; } } string = utils_vprintf (format_string, arguments); buffered_writer_cat_string (writer, string); utils_free (string); } void buffered_writer_cprintf (BufferedWriter *writer, const char *format_string, ...) { va_list arguments; va_start (arguments, format_string); buffered_writer_vcprintf (writer, format_string, arguments); va_end (arguments); } void buffered_writer_vcprintf (BufferedWriter *writer, const char *format_string, va_list arguments) { char *string; assert (writer); assert (format_string); if (!writer->iconv_handle && (writer->buffer_end - writer->buffer_pointer >= strlen (format_string))) { size_t characters_written; va_list arguments_copy; /* No encoding conversion is requested. Try to print the string * directly in the buffer. */ QUARRY_VA_COPY (arguments_copy, arguments); characters_written = utils_vncprintf (writer->buffer_pointer, (writer->buffer_end - writer->buffer_pointer), format_string, arguments_copy); va_end (arguments_copy); if (characters_written < writer->buffer_end - writer->buffer_pointer) { update_column (writer, writer->buffer_pointer, characters_written); writer->buffer_pointer += characters_written; return; } } string = utils_vcprintf (format_string, arguments); buffered_writer_cat_string (writer, string); utils_free (string); } static void flush_buffer (BufferedWriter *writer) { if (writer->file) { if (writer->successful) { writer->successful = fwrite (writer->buffer, writer->buffer_pointer - writer->buffer, 1, writer->file); writer->buffer_pointer = writer->buffer; if (!writer->successful) writer->error_string = utils_duplicate_string (strerror (errno)); } } else { BufferedWriterChunkData *chunk = ((BufferedWriterChunkData*) writer->buffer) - 1; chunk->chunk_size = writer->buffer_pointer - writer->buffer; chunk->next_chunk = utils_malloc (writer->buffer_size); chunk = chunk->next_chunk; chunk->next_chunk = NULL; writer->buffer = (char *) (chunk + 1); writer->buffer_pointer = writer->buffer; writer->buffer_end = ((char *) chunk) + writer->buffer_size; } } static void update_column (BufferedWriter *writer, const char *buffer, size_t length) { const char *last_line; const char *buffer_end = buffer + length; #ifdef HAVE_MEMRCHR last_line = memrchr (buffer, '\n', length); if (last_line) { writer->column = 0; last_line++; } else last_line = buffer; #else size_t k; for (k = length; --k >= 0;) { if (buffer[k] == '\n') { writer->column = 0; break; } } last_line = buffer + (k + 1); #endif while (last_line < buffer_end) { if (IS_UTF8_STARTER (*last_line)) { writer->column++; if (*last_line == '\t') writer->column = ROUND_UP (writer->column, 8); } last_line++; } } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/utils/getopt.c0000644000175000017500000010343610237132521015076 0ustar bartbart/* Getopt for GNU. NOTE: getopt is now part of the C library, so if you don't know what "Keep this file name-space clean" means, talk to drepper@gnu.org before changing it! Copyright (C) 1987,88,89,90,91,92,93,94,95,96,98,99,2000,2001,2002 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library 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 Lesser General Public License for more details. You should have received a copy of the GNU Library General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* 2005-05-07 Paul Pogonyshev * * Update FSF address in the legal notice above. */ /* This tells Alpha OSF/1 not to define a getopt prototype in . Ditto for AIX 3.2 and . */ #ifndef _NO_PROTO # define _NO_PROTO #endif #ifdef HAVE_CONFIG_H # include #endif #if !defined __STDC__ || !__STDC__ /* This is a separate conditional since some stdc systems reject `defined (const)'. */ # ifndef const # define const # endif #endif #include /* Comment out all this code if we are using the GNU C Library, and are not actually compiling the library itself. This code is part of the GNU C Library, but also included in many other GNU distributions. Compiling and linking in this code is a waste when using the GNU C library (especially if it is a shared library). Rather than having every GNU program understand `configure --with-gnu-libc' and omit the object files, it is simpler to just do this in the source for each such file. */ #define GETOPT_INTERFACE_VERSION 2 #if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2 # include # if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION # define ELIDE_CODE # endif #endif #ifndef ELIDE_CODE /* This needs to come after some library #include to get __GNU_LIBRARY__ defined. */ #ifdef __GNU_LIBRARY__ /* Don't include stdlib.h for non-GNU C libraries because some of them contain conflicting prototypes for getopt. */ # include # include #endif /* GNU C library. */ #ifdef VMS # include # if HAVE_STRING_H - 0 # include # endif #endif #ifndef _ /* This is for other GNU distributions with internationalized messages. */ # if (HAVE_LIBINTL_H && ENABLE_NLS) || defined _LIBC # include # ifndef _ # define _(msgid) gettext (msgid) # endif # else # define _(msgid) (msgid) # endif # if defined _LIBC && defined USE_IN_LIBIO # include # endif #endif #ifndef attribute_hidden # define attribute_hidden #endif /* This version of `getopt' appears to the caller like standard Unix `getopt' but it behaves differently for the user, since it allows the user to intersperse the options with the other arguments. As `getopt' works, it permutes the elements of ARGV so that, when it is done, all the options precede everything else. Thus all application programs are extended to handle flexible argument order. Setting the environment variable POSIXLY_CORRECT disables permutation. Then the behavior is completely standard. GNU application programs can use a third alternative mode in which they can distinguish the relative order of options and other arguments. */ #include "getopt.h" /* For communication from `getopt' to the caller. When `getopt' finds an option that takes an argument, the argument value is returned here. Also, when `ordering' is RETURN_IN_ORDER, each non-option ARGV-element is returned here. */ char *optarg; /* Index in ARGV of the next element to be scanned. This is used for communication to and from the caller and for communication between successive calls to `getopt'. On entry to `getopt', zero means this is the first call; initialize. When `getopt' returns -1, this is the index of the first of the non-option elements that the caller should itself scan. Otherwise, `optind' communicates from one call to the next how much of ARGV has been scanned so far. */ /* 1003.2 says this must be 1 before any call. */ int optind = 1; /* Formerly, initialization of getopt depended on optind==0, which causes problems with re-calling getopt as programs generally don't know that. */ int __getopt_initialized attribute_hidden; /* The next char to be scanned in the option-element in which the last option character we returned was found. This allows us to pick up the scan where we left off. If this is zero, or a null string, it means resume the scan by advancing to the next ARGV-element. */ static char *nextchar; /* Callers store zero here to inhibit the error message for unrecognized options. */ int opterr = 1; /* Set to an option character which was unrecognized. This must be initialized on some systems to avoid linking in the system's own getopt implementation. */ int optopt = '?'; /* Describe how to deal with options that follow non-option ARGV-elements. If the caller did not specify anything, the default is REQUIRE_ORDER if the environment variable POSIXLY_CORRECT is defined, PERMUTE otherwise. REQUIRE_ORDER means don't recognize them as options; stop option processing when the first non-option is seen. This is what Unix does. This mode of operation is selected by either setting the environment variable POSIXLY_CORRECT, or using `+' as the first character of the list of option characters. PERMUTE is the default. We permute the contents of ARGV as we scan, so that eventually all the non-options are at the end. This allows options to be given in any order, even with programs that were not written to expect this. RETURN_IN_ORDER is an option available to programs that were written to expect options and other ARGV-elements in any order and that care about the ordering of the two. We describe each non-option ARGV-element as if it were the argument of an option with character code 1. Using `-' as the first character of the list of option characters selects this mode of operation. The special argument `--' forces an end of option-scanning regardless of the value of `ordering'. In the case of RETURN_IN_ORDER, only `--' can cause `getopt' to return -1 with `optind' != ARGC. */ static enum { REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER } ordering; /* Value of POSIXLY_CORRECT environment variable. */ static char *posixly_correct; #ifdef __GNU_LIBRARY__ /* We want to avoid inclusion of string.h with non-GNU libraries because there are many ways it can cause trouble. On some systems, it contains special magic macros that don't work in GCC. */ # include # define my_index strchr #else # if HAVE_STRING_H # include # else # include # endif /* Avoid depending on library functions or files whose names are inconsistent. */ #ifndef getenv extern char *getenv (); #endif static char * my_index (str, chr) const char *str; int chr; { while (*str) { if (*str == chr) return (char *) str; str++; } return 0; } /* If using GCC, we can safely declare strlen this way. If not using GCC, it is ok not to declare it. */ #ifdef __GNUC__ /* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. That was relevant to code that was here before. */ # if (!defined __STDC__ || !__STDC__) && !defined strlen /* gcc with -traditional declares the built-in strlen to return int, and has done so at least since version 2.4.5. -- rms. */ extern int strlen (const char *); # endif /* not __STDC__ */ #endif /* __GNUC__ */ #endif /* not __GNU_LIBRARY__ */ /* Handle permutation of arguments. */ /* Describe the part of ARGV that contains non-options that have been skipped. `first_nonopt' is the index in ARGV of the first of them; `last_nonopt' is the index after the last of them. */ static int first_nonopt; static int last_nonopt; #ifdef _LIBC /* Stored original parameters. XXX This is no good solution. We should rather copy the args so that we can compare them later. But we must not use malloc(3). */ extern int __libc_argc; extern char **__libc_argv; /* Bash 2.0 gives us an environment variable containing flags indicating ARGV elements that should not be considered arguments. */ # ifdef USE_NONOPTION_FLAGS /* Defined in getopt_init.c */ extern char *__getopt_nonoption_flags; static int nonoption_flags_max_len; static int nonoption_flags_len; # endif # ifdef USE_NONOPTION_FLAGS # define SWAP_FLAGS(ch1, ch2) \ if (nonoption_flags_len > 0) \ { \ char __tmp = __getopt_nonoption_flags[ch1]; \ __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \ __getopt_nonoption_flags[ch2] = __tmp; \ } # else # define SWAP_FLAGS(ch1, ch2) # endif #else /* !_LIBC */ # define SWAP_FLAGS(ch1, ch2) #endif /* _LIBC */ /* Exchange two adjacent subsequences of ARGV. One subsequence is elements [first_nonopt,last_nonopt) which contains all the non-options that have been skipped so far. The other is elements [last_nonopt,optind), which contains all the options processed since those non-options were skipped. `first_nonopt' and `last_nonopt' are relocated so that they describe the new indices of the non-options in ARGV after they are moved. */ #if defined __STDC__ && __STDC__ static void exchange (char **); #endif static void exchange (argv) char **argv; { int bottom = first_nonopt; int middle = last_nonopt; int top = optind; char *tem; /* Exchange the shorter segment with the far end of the longer segment. That puts the shorter segment into the right place. It leaves the longer segment in the right place overall, but it consists of two parts that need to be swapped next. */ #if defined _LIBC && defined USE_NONOPTION_FLAGS /* First make sure the handling of the `__getopt_nonoption_flags' string can work normally. Our top argument must be in the range of the string. */ if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len) { /* We must extend the array. The user plays games with us and presents new arguments. */ char *new_str = malloc (top + 1); if (new_str == NULL) nonoption_flags_len = nonoption_flags_max_len = 0; else { memset (__mempcpy (new_str, __getopt_nonoption_flags, nonoption_flags_max_len), '\0', top + 1 - nonoption_flags_max_len); nonoption_flags_max_len = top + 1; __getopt_nonoption_flags = new_str; } } #endif while (top > middle && middle > bottom) { if (top - middle > middle - bottom) { /* Bottom segment is the short one. */ int len = middle - bottom; register int i; /* Swap it with the top part of the top segment. */ for (i = 0; i < len; i++) { tem = argv[bottom + i]; argv[bottom + i] = argv[top - (middle - bottom) + i]; argv[top - (middle - bottom) + i] = tem; SWAP_FLAGS (bottom + i, top - (middle - bottom) + i); } /* Exclude the moved bottom segment from further swapping. */ top -= len; } else { /* Top segment is the short one. */ int len = top - middle; register int i; /* Swap it with the bottom part of the bottom segment. */ for (i = 0; i < len; i++) { tem = argv[bottom + i]; argv[bottom + i] = argv[middle + i]; argv[middle + i] = tem; SWAP_FLAGS (bottom + i, middle + i); } /* Exclude the moved top segment from further swapping. */ bottom += len; } } /* Update records for the slots the non-options now occupy. */ first_nonopt += (optind - last_nonopt); last_nonopt = optind; } /* Initialize the internal data when the first call is made. */ #if defined __STDC__ && __STDC__ static const char *_getopt_initialize (int, char *const *, const char *); #endif static const char * _getopt_initialize (argc, argv, optstring) int argc; char *const *argv; const char *optstring; { /* Start processing options with ARGV-element 1 (since ARGV-element 0 is the program name); the sequence of previously skipped non-option ARGV-elements is empty. */ first_nonopt = last_nonopt = optind; nextchar = NULL; posixly_correct = getenv ("POSIXLY_CORRECT"); /* Determine how to handle the ordering of options and nonoptions. */ if (optstring[0] == '-') { ordering = RETURN_IN_ORDER; ++optstring; } else if (optstring[0] == '+') { ordering = REQUIRE_ORDER; ++optstring; } else if (posixly_correct != NULL) ordering = REQUIRE_ORDER; else ordering = PERMUTE; #if defined _LIBC && defined USE_NONOPTION_FLAGS if (posixly_correct == NULL && argc == __libc_argc && argv == __libc_argv) { if (nonoption_flags_max_len == 0) { if (__getopt_nonoption_flags == NULL || __getopt_nonoption_flags[0] == '\0') nonoption_flags_max_len = -1; else { const char *orig_str = __getopt_nonoption_flags; int len = nonoption_flags_max_len = strlen (orig_str); if (nonoption_flags_max_len < argc) nonoption_flags_max_len = argc; __getopt_nonoption_flags = (char *) malloc (nonoption_flags_max_len); if (__getopt_nonoption_flags == NULL) nonoption_flags_max_len = -1; else memset (__mempcpy (__getopt_nonoption_flags, orig_str, len), '\0', nonoption_flags_max_len - len); } } nonoption_flags_len = nonoption_flags_max_len; } else nonoption_flags_len = 0; #endif return optstring; } /* Scan elements of ARGV (whose length is ARGC) for option characters given in OPTSTRING. If an element of ARGV starts with '-', and is not exactly "-" or "--", then it is an option element. The characters of this element (aside from the initial '-') are option characters. If `getopt' is called repeatedly, it returns successively each of the option characters from each of the option elements. If `getopt' finds another option character, it returns that character, updating `optind' and `nextchar' so that the next call to `getopt' can resume the scan with the following option character or ARGV-element. If there are no more option characters, `getopt' returns -1. Then `optind' is the index in ARGV of the first ARGV-element that is not an option. (The ARGV-elements have been permuted so that those that are not options now come last.) OPTSTRING is a string containing the legitimate option characters. If an option character is seen that is not listed in OPTSTRING, return '?' after printing an error message. If you set `opterr' to zero, the error message is suppressed but we still return '?'. If a char in OPTSTRING is followed by a colon, that means it wants an arg, so the following text in the same ARGV-element, or the text of the following ARGV-element, is returned in `optarg'. Two colons mean an option that wants an optional arg; if there is text in the current ARGV-element, it is returned in `optarg', otherwise `optarg' is set to zero. If OPTSTRING starts with `-' or `+', it requests different methods of handling the non-option ARGV-elements. See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. Long-named options begin with `--' instead of `-'. Their names may be abbreviated as long as the abbreviation is unique or is an exact match for some defined option. If they have an argument, it follows the option name in the same ARGV-element, separated from the option name by a `=', or else the in next ARGV-element. When `getopt' finds a long-named option, it returns 0 if that option's `flag' field is nonzero, the value of the option's `val' field if the `flag' field is zero. The elements of ARGV aren't really const, because we permute them. But we pretend they're const in the prototype to be compatible with other systems. LONGOPTS is a vector of `struct option' terminated by an element containing a name which is zero. LONGIND returns the index in LONGOPT of the long-named option found. It is only valid when a long-named option has been found by the most recent call. If LONG_ONLY is nonzero, '-' as well as '--' can introduce long-named options. */ int _getopt_internal (argc, argv, optstring, longopts, longind, long_only) int argc; char *const *argv; const char *optstring; const struct option *longopts; int *longind; int long_only; { int print_errors = opterr; if (optstring[0] == ':') print_errors = 0; if (argc < 1) return -1; optarg = NULL; if (optind == 0 || !__getopt_initialized) { if (optind == 0) optind = 1; /* Don't scan ARGV[0], the program name. */ optstring = _getopt_initialize (argc, argv, optstring); __getopt_initialized = 1; } /* Test whether ARGV[optind] points to a non-option argument. Either it does not have option syntax, or there is an environment flag from the shell indicating it is not an option. The later information is only used when the used in the GNU libc. */ #if defined _LIBC && defined USE_NONOPTION_FLAGS # define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \ || (optind < nonoption_flags_len \ && __getopt_nonoption_flags[optind] == '1')) #else # define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0') #endif if (nextchar == NULL || *nextchar == '\0') { /* Advance to the next ARGV-element. */ /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been moved back by the user (who may also have changed the arguments). */ if (last_nonopt > optind) last_nonopt = optind; if (first_nonopt > optind) first_nonopt = optind; if (ordering == PERMUTE) { /* If we have just processed some options following some non-options, exchange them so that the options come first. */ if (first_nonopt != last_nonopt && last_nonopt != optind) exchange ((char **) argv); else if (last_nonopt != optind) first_nonopt = optind; /* Skip any additional non-options and extend the range of non-options previously skipped. */ while (optind < argc && NONOPTION_P) optind++; last_nonopt = optind; } /* The special ARGV-element `--' means premature end of options. Skip it like a null option, then exchange with previous non-options as if it were an option, then skip everything else like a non-option. */ if (optind != argc && !strcmp (argv[optind], "--")) { optind++; if (first_nonopt != last_nonopt && last_nonopt != optind) exchange ((char **) argv); else if (first_nonopt == last_nonopt) first_nonopt = optind; last_nonopt = argc; optind = argc; } /* If we have done all the ARGV-elements, stop the scan and back over any non-options that we skipped and permuted. */ if (optind == argc) { /* Set the next-arg-index to point at the non-options that we previously skipped, so the caller will digest them. */ if (first_nonopt != last_nonopt) optind = first_nonopt; return -1; } /* If we have come to a non-option and did not permute it, either stop the scan or describe it to the caller and pass it by. */ if (NONOPTION_P) { if (ordering == REQUIRE_ORDER) return -1; optarg = argv[optind++]; return 1; } /* We have found another option-ARGV-element. Skip the initial punctuation. */ nextchar = (argv[optind] + 1 + (longopts != NULL && argv[optind][1] == '-')); } /* Decode the current option-ARGV-element. */ /* Check whether the ARGV-element is a long option. If long_only and the ARGV-element has the form "-f", where f is a valid short option, don't consider it an abbreviated form of a long option that starts with f. Otherwise there would be no way to give the -f short option. On the other hand, if there's a long option "fubar" and the ARGV-element is "-fu", do consider that an abbreviation of the long option, just like "--fu", and not "-f" with arg "u". This distinction seems to be the most useful approach. */ if (longopts != NULL && (argv[optind][1] == '-' || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1]))))) { char *nameend; const struct option *p; const struct option *pfound = NULL; int exact = 0; int ambig = 0; int indfound = -1; int option_index; for (nameend = nextchar; *nameend && *nameend != '='; nameend++) /* Do nothing. */ ; /* Test all long options for either exact match or abbreviated matches. */ for (p = longopts, option_index = 0; p->name; p++, option_index++) if (!strncmp (p->name, nextchar, nameend - nextchar)) { if ((unsigned int) (nameend - nextchar) == (unsigned int) strlen (p->name)) { /* Exact match found. */ pfound = p; indfound = option_index; exact = 1; break; } else if (pfound == NULL) { /* First nonexact match found. */ pfound = p; indfound = option_index; } else if (long_only || pfound->has_arg != p->has_arg || pfound->flag != p->flag || pfound->val != p->val) /* Second or later nonexact match found. */ ambig = 1; } if (ambig && !exact) { if (print_errors) { #if defined _LIBC && defined USE_IN_LIBIO char *buf; if (__asprintf (&buf, _("%s: option `%s' is ambiguous\n"), argv[0], argv[optind]) >= 0) { if (_IO_fwide (stderr, 0) > 0) __fwprintf (stderr, L"%s", buf); else fputs (buf, stderr); free (buf); } #else fprintf (stderr, _("%s: option `%s' is ambiguous\n"), argv[0], argv[optind]); #endif } nextchar += strlen (nextchar); optind++; optopt = 0; return '?'; } if (pfound != NULL) { option_index = indfound; optind++; if (*nameend) { /* Don't test has_arg with >, because some C compilers don't allow it to be used on enums. */ if (pfound->has_arg) optarg = nameend + 1; else { if (print_errors) { #if defined _LIBC && defined USE_IN_LIBIO char *buf; int n; #endif if (argv[optind - 1][1] == '-') { /* --option */ #if defined _LIBC && defined USE_IN_LIBIO n = __asprintf (&buf, _("\ %s: option `--%s' doesn't allow an argument\n"), argv[0], pfound->name); #else fprintf (stderr, _("\ %s: option `--%s' doesn't allow an argument\n"), argv[0], pfound->name); #endif } else { /* +option or -option */ #if defined _LIBC && defined USE_IN_LIBIO n = __asprintf (&buf, _("\ %s: option `%c%s' doesn't allow an argument\n"), argv[0], argv[optind - 1][0], pfound->name); #else fprintf (stderr, _("\ %s: option `%c%s' doesn't allow an argument\n"), argv[0], argv[optind - 1][0], pfound->name); #endif } #if defined _LIBC && defined USE_IN_LIBIO if (n >= 0) { if (_IO_fwide (stderr, 0) > 0) __fwprintf (stderr, L"%s", buf); else fputs (buf, stderr); free (buf); } #endif } nextchar += strlen (nextchar); optopt = pfound->val; return '?'; } } else if (pfound->has_arg == 1) { if (optind < argc) optarg = argv[optind++]; else { if (print_errors) { #if defined _LIBC && defined USE_IN_LIBIO char *buf; if (__asprintf (&buf, _("\ %s: option `%s' requires an argument\n"), argv[0], argv[optind - 1]) >= 0) { if (_IO_fwide (stderr, 0) > 0) __fwprintf (stderr, L"%s", buf); else fputs (buf, stderr); free (buf); } #else fprintf (stderr, _("%s: option `%s' requires an argument\n"), argv[0], argv[optind - 1]); #endif } nextchar += strlen (nextchar); optopt = pfound->val; return optstring[0] == ':' ? ':' : '?'; } } nextchar += strlen (nextchar); if (longind != NULL) *longind = option_index; if (pfound->flag) { *(pfound->flag) = pfound->val; return 0; } return pfound->val; } /* Can't find it as a long option. If this is not getopt_long_only, or the option starts with '--' or is not a valid short option, then it's an error. Otherwise interpret it as a short option. */ if (!long_only || argv[optind][1] == '-' || my_index (optstring, *nextchar) == NULL) { if (print_errors) { #if defined _LIBC && defined USE_IN_LIBIO char *buf; int n; #endif if (argv[optind][1] == '-') { /* --option */ #if defined _LIBC && defined USE_IN_LIBIO n = __asprintf (&buf, _("%s: unrecognized option `--%s'\n"), argv[0], nextchar); #else fprintf (stderr, _("%s: unrecognized option `--%s'\n"), argv[0], nextchar); #endif } else { /* +option or -option */ #if defined _LIBC && defined USE_IN_LIBIO n = __asprintf (&buf, _("%s: unrecognized option `%c%s'\n"), argv[0], argv[optind][0], nextchar); #else fprintf (stderr, _("%s: unrecognized option `%c%s'\n"), argv[0], argv[optind][0], nextchar); #endif } #if defined _LIBC && defined USE_IN_LIBIO if (n >= 0) { if (_IO_fwide (stderr, 0) > 0) __fwprintf (stderr, L"%s", buf); else fputs (buf, stderr); free (buf); } #endif } nextchar = (char *) ""; optind++; optopt = 0; return '?'; } } /* Look at and handle the next short option-character. */ { char c = *nextchar++; char *temp = my_index (optstring, c); /* Increment `optind' when we start to process its last character. */ if (*nextchar == '\0') ++optind; if (temp == NULL || c == ':') { if (print_errors) { #if defined _LIBC && defined USE_IN_LIBIO char *buf; int n; #endif if (posixly_correct) { /* 1003.2 specifies the format of this message. */ #if defined _LIBC && defined USE_IN_LIBIO n = __asprintf (&buf, _("%s: illegal option -- %c\n"), argv[0], c); #else fprintf (stderr, _("%s: illegal option -- %c\n"), argv[0], c); #endif } else { #if defined _LIBC && defined USE_IN_LIBIO n = __asprintf (&buf, _("%s: invalid option -- %c\n"), argv[0], c); #else fprintf (stderr, _("%s: invalid option -- %c\n"), argv[0], c); #endif } #if defined _LIBC && defined USE_IN_LIBIO if (n >= 0) { if (_IO_fwide (stderr, 0) > 0) __fwprintf (stderr, L"%s", buf); else fputs (buf, stderr); free (buf); } #endif } optopt = c; return '?'; } /* Convenience. Treat POSIX -W foo same as long option --foo */ if (temp[0] == 'W' && temp[1] == ';') { char *nameend; const struct option *p; const struct option *pfound = NULL; int exact = 0; int ambig = 0; int indfound = 0; int option_index; /* This is an option that requires an argument. */ if (*nextchar != '\0') { optarg = nextchar; /* If we end this ARGV-element by taking the rest as an arg, we must advance to the next element now. */ optind++; } else if (optind == argc) { if (print_errors) { /* 1003.2 specifies the format of this message. */ #if defined _LIBC && defined USE_IN_LIBIO char *buf; if (__asprintf (&buf, _("%s: option requires an argument -- %c\n"), argv[0], c) >= 0) { if (_IO_fwide (stderr, 0) > 0) __fwprintf (stderr, L"%s", buf); else fputs (buf, stderr); free (buf); } #else fprintf (stderr, _("%s: option requires an argument -- %c\n"), argv[0], c); #endif } optopt = c; if (optstring[0] == ':') c = ':'; else c = '?'; return c; } else /* We already incremented `optind' once; increment it again when taking next ARGV-elt as argument. */ optarg = argv[optind++]; /* optarg is now the argument, see if it's in the table of longopts. */ for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++) /* Do nothing. */ ; /* Test all long options for either exact match or abbreviated matches. */ for (p = longopts, option_index = 0; p->name; p++, option_index++) if (!strncmp (p->name, nextchar, nameend - nextchar)) { if ((unsigned int) (nameend - nextchar) == strlen (p->name)) { /* Exact match found. */ pfound = p; indfound = option_index; exact = 1; break; } else if (pfound == NULL) { /* First nonexact match found. */ pfound = p; indfound = option_index; } else /* Second or later nonexact match found. */ ambig = 1; } if (ambig && !exact) { if (print_errors) { #if defined _LIBC && defined USE_IN_LIBIO char *buf; if (__asprintf (&buf, _("%s: option `-W %s' is ambiguous\n"), argv[0], argv[optind]) >= 0) { if (_IO_fwide (stderr, 0) > 0) __fwprintf (stderr, L"%s", buf); else fputs (buf, stderr); free (buf); } #else fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"), argv[0], argv[optind]); #endif } nextchar += strlen (nextchar); optind++; return '?'; } if (pfound != NULL) { option_index = indfound; if (*nameend) { /* Don't test has_arg with >, because some C compilers don't allow it to be used on enums. */ if (pfound->has_arg) optarg = nameend + 1; else { if (print_errors) { #if defined _LIBC && defined USE_IN_LIBIO char *buf; if (__asprintf (&buf, _("\ %s: option `-W %s' doesn't allow an argument\n"), argv[0], pfound->name) >= 0) { if (_IO_fwide (stderr, 0) > 0) __fwprintf (stderr, L"%s", buf); else fputs (buf, stderr); free (buf); } #else fprintf (stderr, _("\ %s: option `-W %s' doesn't allow an argument\n"), argv[0], pfound->name); #endif } nextchar += strlen (nextchar); return '?'; } } else if (pfound->has_arg == 1) { if (optind < argc) optarg = argv[optind++]; else { if (print_errors) { #if defined _LIBC && defined USE_IN_LIBIO char *buf; if (__asprintf (&buf, _("\ %s: option `%s' requires an argument\n"), argv[0], argv[optind - 1]) >= 0) { if (_IO_fwide (stderr, 0) > 0) __fwprintf (stderr, L"%s", buf); else fputs (buf, stderr); free (buf); } #else fprintf (stderr, _("%s: option `%s' requires an argument\n"), argv[0], argv[optind - 1]); #endif } nextchar += strlen (nextchar); return optstring[0] == ':' ? ':' : '?'; } } nextchar += strlen (nextchar); if (longind != NULL) *longind = option_index; if (pfound->flag) { *(pfound->flag) = pfound->val; return 0; } return pfound->val; } nextchar = NULL; return 'W'; /* Let the application handle it. */ } if (temp[1] == ':') { if (temp[2] == ':') { /* This is an option that accepts an argument optionally. */ if (*nextchar != '\0') { optarg = nextchar; optind++; } else optarg = NULL; nextchar = NULL; } else { /* This is an option that requires an argument. */ if (*nextchar != '\0') { optarg = nextchar; /* If we end this ARGV-element by taking the rest as an arg, we must advance to the next element now. */ optind++; } else if (optind == argc) { if (print_errors) { /* 1003.2 specifies the format of this message. */ #if defined _LIBC && defined USE_IN_LIBIO char *buf; if (__asprintf (&buf, _("\ %s: option requires an argument -- %c\n"), argv[0], c) >= 0) { if (_IO_fwide (stderr, 0) > 0) __fwprintf (stderr, L"%s", buf); else fputs (buf, stderr); free (buf); } #else fprintf (stderr, _("%s: option requires an argument -- %c\n"), argv[0], c); #endif } optopt = c; if (optstring[0] == ':') c = ':'; else c = '?'; } else /* We already incremented `optind' once; increment it again when taking next ARGV-elt as argument. */ optarg = argv[optind++]; nextchar = NULL; } } return c; } } int getopt (argc, argv, optstring) int argc; char *const *argv; const char *optstring; { return _getopt_internal (argc, argv, optstring, (const struct option *) 0, (int *) 0, 0); } #endif /* Not ELIDE_CODE. */ #ifdef TEST /* Compile with -DTEST to make an executable for use in testing the above definition of `getopt'. */ int main (argc, argv) int argc; char **argv; { int c; int digit_optind = 0; while (1) { int this_option_optind = optind ? optind : 1; c = getopt (argc, argv, "abc:d:0123456789"); if (c == -1) break; switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (digit_optind != 0 && digit_optind != this_option_optind) printf ("digits occur in two different argv-elements.\n"); digit_optind = this_option_optind; printf ("option %c\n", c); break; case 'a': printf ("option a\n"); break; case 'b': printf ("option b\n"); break; case 'c': printf ("option c with value `%s'\n", optarg); break; case '?': break; default: printf ("?? getopt returned character code 0%o ??\n", c); } } if (optind < argc) { printf ("non-option ARGV-elements: "); while (optind < argc) printf ("%s ", argv[optind++]); printf ("\n"); } exit (0); } #endif /* TEST */ quarry-0.2.0/src/utils/getopt1.c0000644000175000017500000001121110237132521015144 0ustar bartbart/* getopt_long and getopt_long_only entry points for GNU getopt. Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library 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 Lesser General Public License for more details. You should have received a copy of the GNU Library General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* 2005-05-07 Paul Pogonyshev * * Update FSF address in the legal notice above. */ #ifdef HAVE_CONFIG_H #include #endif #ifdef _LIBC # include #else # include "getopt.h" #endif #if !defined __STDC__ || !__STDC__ /* This is a separate conditional since some stdc systems reject `defined (const)'. */ #ifndef const #define const #endif #endif #include /* Comment out all this code if we are using the GNU C Library, and are not actually compiling the library itself. This code is part of the GNU C Library, but also included in many other GNU distributions. Compiling and linking in this code is a waste when using the GNU C library (especially if it is a shared library). Rather than having every GNU program understand `configure --with-gnu-libc' and omit the object files, it is simpler to just do this in the source for each such file. */ #define GETOPT_INTERFACE_VERSION 2 #if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2 #include #if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION #define ELIDE_CODE #endif #endif #ifndef ELIDE_CODE /* This needs to come after some library #include to get __GNU_LIBRARY__ defined. */ #ifdef __GNU_LIBRARY__ #include #endif #ifndef NULL #define NULL 0 #endif int getopt_long (argc, argv, options, long_options, opt_index) int argc; char *const *argv; const char *options; const struct option *long_options; int *opt_index; { return _getopt_internal (argc, argv, options, long_options, opt_index, 0); } /* Like getopt_long, but '-' as well as '--' can indicate a long option. If an option that starts with '-' (not '--') doesn't match a long option, but does match a short option, it is parsed as a short option instead. */ int getopt_long_only (argc, argv, options, long_options, opt_index) int argc; char *const *argv; const char *options; const struct option *long_options; int *opt_index; { return _getopt_internal (argc, argv, options, long_options, opt_index, 1); } # ifdef _LIBC libc_hidden_def (getopt_long) libc_hidden_def (getopt_long_only) # endif #endif /* Not ELIDE_CODE. */ #ifdef TEST #include int main (argc, argv) int argc; char **argv; { int c; int digit_optind = 0; while (1) { int this_option_optind = optind ? optind : 1; int option_index = 0; static struct option long_options[] = { {"add", 1, 0, 0}, {"append", 0, 0, 0}, {"delete", 1, 0, 0}, {"verbose", 0, 0, 0}, {"create", 0, 0, 0}, {"file", 1, 0, 0}, {0, 0, 0, 0} }; c = getopt_long (argc, argv, "abc:d:0123456789", long_options, &option_index); if (c == -1) break; switch (c) { case 0: printf ("option %s", long_options[option_index].name); if (optarg) printf (" with arg %s", optarg); printf ("\n"); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (digit_optind != 0 && digit_optind != this_option_optind) printf ("digits occur in two different argv-elements.\n"); digit_optind = this_option_optind; printf ("option %c\n", c); break; case 'a': printf ("option a\n"); break; case 'b': printf ("option b\n"); break; case 'c': printf ("option c with value `%s'\n", optarg); break; case 'd': printf ("option d with value `%s'\n", optarg); break; case '?': break; default: printf ("?? getopt returned character code 0%o ??\n", c); } } if (optind < argc) { printf ("non-option ARGV-elements: "); while (optind < argc) printf ("%s ", argv[optind++]); printf ("\n"); } exit (0); } #endif /* TEST */ quarry-0.2.0/src/utils/memory-pool.c0000644000175000017500000002715610520520537016062 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* Memory pools are used for storing large numbers of small items of * same size (e.g. SGF nodes and properties). They store the items in * chunks, each consisting of NUM_ITEMS_IN_CHUNK items. * * The advantages are: * * - way less calls to malloc() and free() (faster memory management); * * - smaller memory footprint (the smaller the items, the better); * * - fast traversing of all allocated items (in no particular order, * though; the callback must not make any assumptions); * * - very fast "flushing" of pools which frees all items stored. * * The disadvantage is that all items must include a field of * `ItemIndex' type (unsigned char.) * * * Chunks in memory pools are kept in double-linked list. Non-full * chunks (with at least one free item) are kept together in the * list's head. At least one non-full chunk must always be present. * * Each item must jave a field of `ItemIndex' type. This field is * private to memory pool and must not be used from outside. * * When an item is allocated, this field contains item's index in * chunk and is used in memory_pool_free() for finding chunk structure * in memory. When an item is free, the field contains index of * chunk's next free item. * * Knowing the above, it is possible to say if an item in chunk is * free (provided that you have a pointer to chunk). This fact is * used in item traversing. */ #include "utils.h" #if ENABLE_MEMORY_POOLS #include #include #ifdef HAVE_MEMORY_H #include #endif static MemoryChunk * memory_chunk_new (int item_size, int index_field_offset); #if ENABLE_MEMORY_PROFILING #include int num_pools_initialized = 0; int num_pools_flushed = 0; #endif /* ENABLE_MEMORY_PROFILING */ /* Initialize a MemoryPool structure to store items of given size. */ void memory_pool_init (MemoryPool *pool, int item_size, int index_field_offset) { MemoryChunk *chunk; assert (pool); assert (item_size > 0); assert (0 <= index_field_offset && index_field_offset < item_size); pool->item_size = item_size; pool->index_field_offset = index_field_offset; chunk = memory_chunk_new (item_size, index_field_offset); chunk->next = NULL; chunk->previous = NULL; pool->first_chunk= chunk; pool->last_chunk = chunk; #if ENABLE_MEMORY_PROFILING pool->number = ++num_pools_initialized; fprintf (stderr, ("Memory pool number %d initialized:\n" " size of item: %6d bytes\n" " size of chunk: %6d bytes\n\n"), pool->number, item_size, (sizeof (MemoryChunk) - sizeof (int) + NUM_ITEMS_IN_CHUNK * item_size)); pool->num_chunks_allocated = 1; pool->num_chunks_freed = 0; pool->num_items_allocated = 0; pool->num_items_freed = 0; #endif /* ENABLE_MEMORY_PROFILING */ } /* Allocate an item from given memory pool. */ void * memory_pool_alloc (MemoryPool *pool) { MemoryChunk *chunk = pool->first_chunk; int item_index; void *item; assert (pool->item_size > 0); item_index = chunk->first_free_item; item = (char *) chunk->memory + item_index * pool->item_size; if (--chunk->num_free_items) { chunk->first_free_item = * (ItemIndex *) ((char *) item + pool->index_field_offset); } else { if (chunk->next && chunk->next->num_free_items > 0) { /* The chunk is full now, but is followed by at least one * non-full chunk. We have to move this one to the tail of * pool's list of chunks. */ chunk->next->previous = NULL; pool->first_chunk = chunk->next; chunk->next = NULL; chunk->previous = pool->last_chunk; pool->last_chunk = chunk; } else { /* We need at least one non-full chunk. */ chunk = memory_chunk_new (pool->item_size, pool->index_field_offset); chunk->next = pool->first_chunk; chunk->previous = NULL; pool->first_chunk->previous = chunk; pool->first_chunk = chunk; #if ENABLE_MEMORY_PROFILING pool->num_chunks_allocated++; #endif } } * (ItemIndex *) ((char *) item + pool->index_field_offset) = item_index; #if ENABLE_MEMORY_PROFILING pool->num_items_allocated++; #endif return item; } /* Free an item which was allocated from given pool. Note that even * if all items are freed, you still have to call memory_pool_flush() * to free all memory allocated by the pool. */ void memory_pool_free (MemoryPool *pool, void *item) { MemoryChunk *chunk; ItemIndex item_index = * (ItemIndex *) ((char *) item + pool->index_field_offset); assert (pool->item_size > 0); chunk = (MemoryChunk *) ((char *) item - item_index * pool->item_size - (sizeof (MemoryChunk) - sizeof (int))); if (chunk->num_free_items < NUM_ITEMS_IN_CHUNK - 1) { if (chunk->num_free_items == 0 && chunk->previous->num_free_items == 0) { /* The chunk is not full now, but is not in "non-full" head of * the pool's chunk list. We have to move it to the head. */ chunk->previous->next = chunk->next; if (chunk->next) chunk->next->previous = chunk->previous; else pool->last_chunk = chunk->previous; chunk->previous = NULL; chunk->next = pool->first_chunk; pool->first_chunk = chunk; } } else { if (chunk->previous || (chunk->next && chunk->next->num_free_items > 0)) { /* The chunk is not the only non-full chunk in the pool. There * is no reason to keep it. */ if (chunk->next) chunk->next->previous = chunk->previous; else pool->last_chunk = chunk->previous; if (chunk->previous) chunk->previous->next = chunk->next; else pool->first_chunk = chunk->next; utils_free (chunk); #if ENABLE_MEMORY_PROFILING pool->num_items_freed++; pool->num_chunks_freed++; #endif /* Since the whole chunk is freed, we don't need to free the * item itself. Return now. */ return; } /* We cannot free the chunk because it is the only "non-full" one. * Just fall through and free the item, leaving the chunk around. */ } chunk->num_free_items++; * (ItemIndex *) ((char *) item + pool->index_field_offset) = chunk->first_free_item; chunk->first_free_item = item_index; #if ENABLE_MEMORY_PROFILING pool->num_items_freed++; #endif } int memory_pool_count_items (const MemoryPool *pool) { int num_items = 0; MemoryChunk *chunk; assert (pool); if (pool->item_size > 0) { /* Traverse chunks in "backward" direction, because it would mean * traversing chunks in order of allocation in the most common * case. */ for (chunk = pool->last_chunk; chunk; chunk = chunk->previous) num_items += NUM_ITEMS_IN_CHUNK - chunk->num_free_items; } return num_items; } void memory_pool_traverse (const MemoryPool *pool, MemoryPoolCallback callback) { MemoryChunk *chunk; int item_size = pool->item_size; char *memory; int k; assert (item_size > 0); /* Traverse full chunks. We do this in "backward" direction, * because it would mean traversing chunks in order of allocation in * the most common case. */ for (chunk = pool->last_chunk; chunk->num_free_items == 0; chunk = chunk->previous) { for (memory = (char *) chunk->memory, k = 0; k < NUM_ITEMS_IN_CHUNK; memory += pool->item_size, k++) callback (memory); } /* Traverse non-full chunks. In this case we need to test if an * item is allocated before invoking callback on it. */ do { for (memory = (char *) chunk->memory, k = 0; k < NUM_ITEMS_IN_CHUNK; memory += pool->item_size, k++) { if (* (ItemIndex *) (memory + pool->index_field_offset) == k) callback (memory); } chunk = chunk->previous; } while (chunk); } void memory_pool_traverse_data (const MemoryPool *pool, MemoryPoolDataCallback callback, void *data) { MemoryChunk *chunk = pool->first_chunk; int item_size = pool->item_size; char *memory; int k; assert (item_size > 0); /* Traverse full chunks. We do this in "backward" direction, * because it would mean traversing chunks in order of allocation in * the most common case. */ for (chunk = pool->last_chunk; chunk->num_free_items == 0; chunk = chunk->previous) { for (memory = (char *) chunk->memory, k = 0; k < NUM_ITEMS_IN_CHUNK; memory += pool->item_size, k++) callback (memory, data); } /* Traverse non-full chunks. In this case we need to test if an * item is allocated before invoking callback on it. */ do { for (memory = (char *) chunk->memory, k = 0; k < NUM_ITEMS_IN_CHUNK; memory += pool->item_size, k++) { if (* (ItemIndex *) (memory + pool->index_field_offset) == k) callback (memory, data); } chunk = chunk->previous; } while (chunk); } /* Flush given memory pool. This frees all pool's items and allocated * memory. The pool becomes uninitialized and to use it again, you * must call memory_pool_init(). * * Note that you don't have to free each item individually before * calling this function. */ void memory_pool_flush (MemoryPool *pool) { MemoryChunk *chunk; assert (pool->item_size > 0); for (chunk = pool->first_chunk; chunk;) { MemoryChunk *next = chunk->next; utils_free (chunk); chunk = next; } pool->item_size = 0; pool->first_chunk = NULL; pool->last_chunk = NULL; #if ENABLE_MEMORY_PROFILING num_pools_flushed++; fprintf (stderr, ("Memory pool %d flushed; detailed information:\n" " number of chunks allocated: %10u\n" " number of chunks freed: %10u\n" " number of items allocated: %10u\n" " number of items freed: %10u\n\n"), pool->number, pool->num_chunks_allocated, pool->num_chunks_freed, pool->num_items_allocated, pool->num_items_freed); #endif } /* Allocate a new MemoryChunk structure with all items being free. */ static MemoryChunk * memory_chunk_new (int item_size, int index_field_offset) { MemoryChunk *chunk = utils_malloc (sizeof (MemoryChunk) - sizeof (int) + NUM_ITEMS_IN_CHUNK * item_size); char *memory; int k; for (memory = (char *) chunk->memory, k = 0; k < NUM_ITEMS_IN_CHUNK; memory += item_size, k++) * (ItemIndex *) (memory + index_field_offset) = k + 1; chunk->first_free_item = 0; chunk->num_free_items = NUM_ITEMS_IN_CHUNK; return chunk; } #endif /* ENABLE_MEMORY_POOLS */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/utils/object-cache.c0000644000175000017500000001322210367243111016076 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "utils.h" #include /* Return an object corresponding to given `key'. If such an object * is not present in the cache yet, it is created. */ void * object_cache_create_or_reuse_object (ObjectCache *cache, const void *key) { ObjectCacheEntry *stock_entry; ObjectCacheEntry **link; assert (cache); assert (key); /* Check if we have required object in stock. */ for (stock_entry = cache->first_stock_entry; stock_entry; stock_entry = stock_entry->next) { if (cache->compare_keys (key, stock_entry->key)) { stock_entry->reference_counter++; return stock_entry->object; } } /* Maybe such an object is present in the dump, pending for * deletion? Then we move it to stock and avoid recreating it. */ link = &cache->first_dump_entry; while (*link) { ObjectCacheEntry *dump_entry = *link; if (cache->compare_keys (key, dump_entry->key)) { *link = dump_entry->next; dump_entry->next = cache->first_stock_entry; cache->first_stock_entry = dump_entry; dump_entry->reference_counter = 1; cache->current_dump_size--; return dump_entry->object; } link = &dump_entry->next; } stock_entry = utils_malloc (sizeof (ObjectCacheEntry)); stock_entry->reference_counter = 1; stock_entry->next = cache->first_stock_entry; stock_entry->key = cache->duplicate_key (key); stock_entry->object = cache->create_object (key); cache->first_stock_entry = stock_entry; return stock_entry->object; } /* Unreference given object. If the object is referenced only once, * then it is either moved to dump or deleted instantly (depending on * whether the dump exists at all). */ void object_cache_unreference_object (ObjectCache *cache, void *object) { ObjectCacheEntry **link; assert (cache); for (link = &cache->first_stock_entry; *link; ) { ObjectCacheEntry *stock_entry = *link; if (stock_entry->object == object) { if (--stock_entry->reference_counter == 0) { *link = stock_entry->next; if (cache->max_dump_size > 0) { stock_entry->next = cache->first_dump_entry; cache->first_dump_entry = stock_entry; if (++cache->current_dump_size > cache->max_dump_size) object_cache_recycle_dump (cache, 1); } else { cache->delete_key (stock_entry->key); cache->delete_object (stock_entry->object); utils_free (stock_entry); } } return; } link = &stock_entry->next; } assert (0); } /* Recycle an object cache. On first recycle, objects' reference * counters are set to -1. On second recycle objects are deleted * unless they have been requested again with * object_cache_create_or_reuse_object(). * * If `lazy_recycling' is set, this function recycles only one object * set. This feature is probably not useful outside this module. */ void object_cache_recycle_dump (ObjectCache *cache, int lazy_recycling) { ObjectCacheEntry **link; assert (cache); for (link = &cache->first_dump_entry; *link; ) { ObjectCacheEntry *dump_entry = *link; if (dump_entry->reference_counter == 0 && !lazy_recycling) dump_entry->reference_counter = -1; else if (dump_entry->reference_counter == -1 || (lazy_recycling && !dump_entry->next)) { *link = dump_entry->next; cache->delete_key (dump_entry->key); cache->delete_object (dump_entry->object); utils_free (dump_entry); cache->current_dump_size--; if (lazy_recycling) return; continue; } link = &dump_entry->next; } } /* Unconditionally delete all objects stored in cache, including * dumped ones. This frees all memory allocated by the cache itself * too. After a call to this function the cache becomes unusable. */ void object_cache_free (ObjectCache *cache) { ObjectCacheEntry *entry; assert (cache); for (entry = cache->first_stock_entry; entry; ) { ObjectCacheEntry *next_entry = entry->next; cache->delete_key (entry->key); cache->delete_object (entry->object); utils_free (entry); entry = next_entry; } for (entry = cache->first_dump_entry; entry; ) { ObjectCacheEntry *next_entry = entry->next; cache->delete_key (entry->key); cache->delete_object (entry->object); utils_free (entry); entry = next_entry; } } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/utils/string-buffer.c0000644000175000017500000002016210376422062016351 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "utils.h" #include #include #include #include #ifdef HAVE_MEMORY_H #include #endif static void reallocate_if_needed (StringBuffer *string_buffer, int length_increase); StringBuffer * string_buffer_new (int initial_size, int size_increment) { StringBuffer *string_buffer = utils_malloc (sizeof (StringBuffer)); string_buffer_init (string_buffer, initial_size, size_increment); return string_buffer; } void string_buffer_init (StringBuffer *string_buffer, int initial_size, int size_increment) { string_buffer->string = utils_malloc (initial_size); string_buffer->string[0] = 0; string_buffer->length = 0; string_buffer->current_size = initial_size; string_buffer->size_increment = size_increment; } void string_buffer_dispose (StringBuffer *string_buffer) { assert (string_buffer); utils_free (string_buffer->string); } void string_buffer_empty (StringBuffer *string_buffer) { string_buffer->string[0] = 0; string_buffer->length = 0; } char * string_buffer_steal_string (StringBuffer *string_buffer) { assert (string_buffer); return utils_realloc (string_buffer->string, string_buffer->length + 1); } void string_buffer_delete (StringBuffer *string_buffer) { string_buffer_dispose (string_buffer); utils_free (string_buffer); } void string_buffer_add_characters (StringBuffer *string_buffer, char character, int num_characters) { reallocate_if_needed (string_buffer, num_characters); memset (string_buffer->string + string_buffer->length, character, num_characters); string_buffer->length += num_characters; string_buffer->string[string_buffer->length] = 0; } void string_buffer_cat_string (StringBuffer *string_buffer, const char *string) { int length; assert (string_buffer); assert (string); length = strlen (string); reallocate_if_needed (string_buffer, length); memcpy (string_buffer->string + string_buffer->length, string, length + 1); string_buffer->length += length; } void string_buffer_cat_strings (StringBuffer *string_buffer, ...) { int k; int to_cat_lengths[16]; int length_increase = 0; va_list arguments; assert (string_buffer); va_start (arguments, string_buffer); for (k = 0; ;) { int length; const char *to_cat = va_arg (arguments, const char *); if (!to_cat) break; length = strlen (to_cat); if (k < (int) (sizeof to_cat_lengths / sizeof (int))) to_cat_lengths[k++] = length; length_increase += length; } va_end (arguments); reallocate_if_needed (string_buffer, length_increase); va_start (arguments, string_buffer); for (k = 0; ;) { int length; const char *to_cat = va_arg (arguments, const char *); if (!to_cat) break; length = (k < (int) (sizeof to_cat_lengths / sizeof (int)) ? to_cat_lengths[k++] : (int) strlen (to_cat)); memcpy (string_buffer->string + string_buffer->length, to_cat, length); string_buffer->length += length; } va_end (arguments); string_buffer->string[string_buffer->length] = 0; } void string_buffer_cat_as_string (StringBuffer *string_buffer, const char *buffer, int length) { assert (string_buffer); assert (buffer); reallocate_if_needed (string_buffer, length); memcpy (string_buffer->string + string_buffer->length, buffer, length); string_buffer->length += length; string_buffer->string[string_buffer->length] = 0; } void string_buffer_cat_as_strings (StringBuffer *string_buffer, ...) { int length_increase = 0; va_list arguments; assert (string_buffer); va_start (arguments, string_buffer); while (va_arg (arguments, const char *)) length_increase += va_arg (arguments, int); va_end (arguments); reallocate_if_needed (string_buffer, length_increase); va_start (arguments, string_buffer); while (1) { int length; const char *buffer = va_arg (arguments, const char *); if (!buffer) break; length = va_arg (arguments, int); memcpy (string_buffer->string + string_buffer->length, buffer, length); string_buffer->length += length; } va_end (arguments); string_buffer->string[string_buffer->length] = 0; } void string_buffer_printf (StringBuffer *string_buffer, const char *format_string, ...) { va_list arguments; va_start (arguments, format_string); string_buffer_vprintf (string_buffer, format_string, arguments); va_end (arguments); } void string_buffer_vprintf (StringBuffer *string_buffer, const char *format_string, va_list arguments) { assert (string_buffer); assert (format_string); while (1) { int length; va_list arguments_copy; QUARRY_VA_COPY (arguments_copy, arguments); length = vsnprintf (string_buffer->string + string_buffer->length, string_buffer->current_size - string_buffer->length, format_string, arguments_copy); va_end (arguments_copy); if (length < string_buffer->current_size - string_buffer->length && length != -1) { string_buffer->length += length; break; } reallocate_if_needed (string_buffer, (length > -1 ? length : string_buffer->size_increment)); } } void string_buffer_cprintf (StringBuffer *string_buffer, const char *format_string, ...) { va_list arguments; va_start (arguments, format_string); string_buffer_vcprintf (string_buffer, format_string, arguments); va_end (arguments); } void string_buffer_vcprintf (StringBuffer *string_buffer, const char *format_string, va_list arguments) { int length; va_list arguments_copy; assert (string_buffer); assert (format_string); QUARRY_VA_COPY (arguments_copy, arguments); length = utils_vncprintf (string_buffer->string + string_buffer->length, (string_buffer->current_size - string_buffer->length), format_string, arguments_copy); va_end (arguments_copy); if (length >= string_buffer->current_size - string_buffer->length) { reallocate_if_needed (string_buffer, length); length = utils_vncprintf (string_buffer->string + string_buffer->length, (string_buffer->current_size - string_buffer->length), format_string, arguments); } string_buffer->length += length; } static void reallocate_if_needed (StringBuffer *string_buffer, int length_increase) { int new_size = string_buffer->length + length_increase + 1; if (new_size > string_buffer->current_size) { int num_increments = (((new_size - string_buffer->current_size) + (string_buffer->size_increment - 1)) / string_buffer->size_increment); string_buffer->current_size += (num_increments * string_buffer->size_increment); string_buffer->string = utils_realloc (string_buffer->string, string_buffer->current_size); } } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/utils/string-list.c0000644000175000017500000003614010453531213016051 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003 Paul Pogonyshev. * * Copyright (C) 2004 Paul Pogonyshev and Martin Holters. * * Copyright (C) 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "utils.h" #include #include #include #include #define DISPOSE_ITEM(list, item) \ do { \ if ((list)->item_dispose) \ (list)->item_dispose (item); \ utils_free ((item)->text); \ utils_free (item); \ } while (0) #define MAKE_NEW_ITEM_FROM_STRING \ StringList *list = (StringList *) abstract_list; \ StringListItem *item; \ assert (list); \ item = utils_malloc (list->item_size); \ item->text = utils_duplicate_string (string) #define MAKE_NEW_ITEM_FROM_BUFFER \ StringList *list = (StringList *) abstract_list; \ StringListItem *item; \ assert (list); \ assert (buffer); \ item = utils_malloc (list->item_size); \ item->text = utils_duplicate_as_string (buffer, length) #define MAKE_NEW_ITEM_FROM_READY_STRING \ StringList *list = (StringList *) abstract_list; \ StringListItem *item; \ assert (list); \ item = utils_malloc (list->item_size); \ item->text = allocated_string #define CONVERT_READY_ITEM \ StringList *list = (StringList *) abstract_list; \ StringListItem *item = (StringListItem *) abstract_item; \ assert (list); \ assert (item) #define ADD_ITEM \ item->next = NULL; \ if (list->last) \ list->last->next = item; \ else \ list->first = item; \ list->last = item #define PREPEND_ITEM \ item->next = list->first; \ list->first = item; \ if (!list->last) \ list->last = item #define INSERT_ITEM \ do { \ StringListItem *notch = (StringListItem *) abstract_notch; \ if (notch) { \ item->next = notch->next; \ notch->next = item; \ } \ else { \ item->next = list->first; \ list->first = item; \ } \ if (!item->next) \ list->last = item; \ } while (0) void * string_list_new_derived (int item_size, StringListItemDispose item_dispose) { void *list = utils_malloc (sizeof (StringList)); string_list_init_derived (list, item_size, item_dispose); return list; } void string_list_delete (void *abstract_list) { string_list_empty (abstract_list); utils_free (abstract_list); } void string_list_init_derived (void *abstract_list, int item_size, StringListItemDispose item_dispose) { StringList *list = (StringList *) abstract_list; list->first = NULL; list->last = NULL; list->item_size = item_size; list->item_dispose = item_dispose; } void string_list_empty (void *abstract_list) { StringList *list = (StringList *) abstract_list; StringListItem *this_item; assert (list); for (this_item = list->first; this_item;) { StringListItem *next_item = this_item->next; DISPOSE_ITEM (list, this_item); this_item = next_item; } list->first = NULL; list->last = NULL; } int string_list_count_items (void *abstract_list) { StringList *list = (StringList *) abstract_list; StringListItem *this_item; int num_items = 0; assert (list); for (this_item = list->first; this_item; this_item = this_item->next) num_items++; return num_items; } void string_list_fill_from_string (void *abstract_list, const char *super_string) { const char *buffer; assert (super_string); for (buffer = super_string; *buffer;) { int length = strlen (buffer); string_list_add_from_buffer (abstract_list, buffer, length); buffer += length + 1; } } void string_list_duplicate_items (StringList *list, const StringList *duplicate_from_list) { const StringListItem *item; StringListItem *last_duplicated_item = NULL; StringListItem **link; assert (list); assert (list->first == NULL); assert (duplicate_from_list); link = &list->first; for (item = duplicate_from_list->first; item; item = item->next) { last_duplicated_item = utils_malloc (sizeof (StringListItem)); last_duplicated_item->text = utils_duplicate_string (item->text); *link = last_duplicated_item; link = &last_duplicated_item->next; } *link = NULL; list->last = last_duplicated_item; } void string_list_steal_items (void *abstract_list, void *steal_from) { StringList *list = (StringList *) abstract_list; StringList *steal_from_list = (StringList *) steal_from; assert (list); assert (list->first == NULL); assert (steal_from_list); assert (steal_from_list->item_size == list->item_size); assert (steal_from_list->item_dispose == list->item_dispose); list->first = steal_from_list->first; list->last = steal_from_list->last; steal_from_list->first = NULL; steal_from_list->last = NULL; } void string_list_add (void *abstract_list, const char *string) { MAKE_NEW_ITEM_FROM_STRING; ADD_ITEM; } void string_list_add_from_buffer (void *abstract_list, const char *buffer, int length) { MAKE_NEW_ITEM_FROM_BUFFER; ADD_ITEM; } void string_list_add_ready (void *abstract_list, char *allocated_string) { MAKE_NEW_ITEM_FROM_READY_STRING; ADD_ITEM; } void string_list_add_ready_item (void *abstract_list, void *abstract_item) { CONVERT_READY_ITEM; ADD_ITEM; } void string_list_prepend (void *abstract_list, const char *string) { MAKE_NEW_ITEM_FROM_STRING; PREPEND_ITEM; } void string_list_prepend_from_buffer (void *abstract_list, const char *buffer, int length) { MAKE_NEW_ITEM_FROM_BUFFER; PREPEND_ITEM; } void string_list_prepend_ready (void *abstract_list, char *allocated_string) { MAKE_NEW_ITEM_FROM_READY_STRING; PREPEND_ITEM; } void string_list_prepend_ready_item (void *abstract_list, void *abstract_item) { CONVERT_READY_ITEM; PREPEND_ITEM; } void * string_list_insert (void *abstract_list, void *abstract_notch, const char *string) { MAKE_NEW_ITEM_FROM_STRING; INSERT_ITEM; return item; } void * string_list_insert_from_buffer (void *abstract_list, void *abstract_notch, const char *buffer, int length) { MAKE_NEW_ITEM_FROM_BUFFER; INSERT_ITEM; return item; } void * string_list_insert_ready (void *abstract_list, void *abstract_notch, char *allocated_string) { MAKE_NEW_ITEM_FROM_READY_STRING; INSERT_ITEM; return item; } void * string_list_insert_ready_item (void *abstract_list, void *abstract_notch, void *abstract_item) { CONVERT_READY_ITEM; INSERT_ITEM; return item; } void string_list_dispose_item (const void *abstract_list, void *abstract_item) { const StringList *list = (const StringList *) abstract_list; StringListItem *item = (StringListItem *) abstract_item; assert (list); assert (item); DISPOSE_ITEM (list, item); } void string_list_delete_item (void *abstract_list, void *abstract_item) { StringList *list = (StringList *) abstract_list; StringListItem *item = (StringListItem *) abstract_item; StringListItem *previous_item; StringListItem **link; assert (list); assert (item); for (link = &list->first, previous_item = NULL; *link != item; link = &previous_item->next) { previous_item = *link; assert (previous_item); } *link = item->next; if (!item->next) list->last = previous_item; DISPOSE_ITEM (list, item); } void string_list_delete_first_item (void *abstract_list) { StringList *list = (StringList *) abstract_list; StringListItem *first; assert (list); assert (list->first); first = list->first; list->first = first->next; if (list->first == NULL) list->last = NULL; DISPOSE_ITEM (list, first); } void * string_list_steal_item (void *abstract_list, void *abstract_item) { StringList *list = (StringList *) abstract_list; StringListItem *item = (StringListItem *) abstract_item; StringListItem *previous_item; StringListItem **link; assert (list); assert (item); for (link = &list->first, previous_item = NULL; *link != item; link = &previous_item->next) { previous_item = *link; assert (previous_item); } *link = item->next; if (!item->next) list->last = previous_item; return item; } void * string_list_steal_first_item (void *abstract_list) { StringList *list = (StringList *) abstract_list; StringListItem *first; assert (list); assert (list->first); first = list->first; list->first = first->next; if (list->first == NULL) list->last = NULL; return first; } int string_list_clamp_size (void *abstract_list, int max_size) { StringList *list = (StringList *) abstract_list; StringListItem **link; int num_items_skipped; assert (list); for (link = &list->first, num_items_skipped = 0; *link && num_items_skipped < max_size; link = &(*link)->next) num_items_skipped++; if (*link) { StringListItem *this_item; for (this_item = *link; this_item;) { StringListItem *next_item = this_item->next; DISPOSE_ITEM (list, this_item); this_item = next_item; } *link = NULL; return 1; } else return 0; } int string_list_get_item_index (void *abstract_list, void *abstract_item) { StringList *list = (StringList *) abstract_list; StringListItem *item = (StringListItem *) abstract_item; StringListItem *this_item; int item_index; assert (list); assert (item); for (item_index = 0, this_item = list->first; this_item; this_item = this_item->next, item_index++) { if (this_item == item) return item_index; } return -1; } StringListItem * string_list_get_item (void *abstract_list, int item_index) { StringList *list = (StringList *) abstract_list; assert (list); if (item_index >= 0) { StringListItem *item; for (item = list->first; item; item = item->next) { if (!item_index--) return item; } } return NULL; } StringListItem * string_list_find (const void *abstract_list, const char *text) { const StringList *list = (const StringList *) abstract_list; StringListItem *item; assert (list); assert (text); for (item = list->first; item; item = item->next) { if (strcmp (item->text, text) == 0) break; } return item; } StringListItem * string_list_find_after_notch (const void *abstract_list, const char *text, const void *abstract_notch) { const StringList *list = (const StringList *) abstract_list; const StringListItem *notch = (const StringListItem *) abstract_notch; StringListItem *item; assert (list); assert (text); for (item = notch ? notch->next : list->first; item; item = item->next) { if (strcmp (item->text, text) == 0) break; } return item; } void string_list_swap_with_next (void *abstract_list, void *abstract_item) { StringList *list = (StringList *) abstract_list; StringListItem *item = (StringListItem *) abstract_item; StringListItem *next_item = item->next; StringListItem **link; assert (list); assert (item); assert (next_item); for (link = &list->first; *link != item; link = &(*link)->next) assert (*link); *link = next_item; item->next = next_item->next; next_item->next = item; if (!item->next) list->last = item; } void string_list_swap_with_previous (void *abstract_list, void *abstract_item) { StringList *list = (StringList *) abstract_list; StringListItem *item = (StringListItem *) abstract_item; StringListItem *previous_item; StringListItem **link; assert (list); assert (item); assert (item != list->first); for (link = &list->first; ; link = &previous_item->next) { previous_item = *link; assert (previous_item); if (previous_item->next == item) break; } *link = item; previous_item->next = item->next; item->next = previous_item; if (!previous_item->next) list->last = previous_item; } void string_list_move (void *abstract_list, void *abstract_item, void *abstract_notch) { StringList *list = (StringList *) abstract_list; StringListItem *item = (StringListItem *) abstract_item; StringListItem *notch = (StringListItem *) abstract_notch; StringListItem *previous_item; StringListItem **link; assert (list); assert (item); assert (item != notch); for (link = &list->first, previous_item = NULL; *link != item; link = &previous_item->next) { previous_item = *link; assert (previous_item); } *link = item->next; if (!item->next) list->last = previous_item; if (notch) { item->next = notch->next; notch->next = item; } else { item->next = list->first; list->first = item; } if (!item->next) list->last = item; } char * string_list_implode (const void *abstract_list, const char *separator) { const StringList *list = (const StringList *) abstract_list; char *result = NULL; assert (list); assert (separator); if (list->first) { const StringListItem *item; int separator_length = strlen (separator); int result_length; char *scan; for (result_length = 1, item = list->first; item; item = item->next) result_length += strlen (item->text) + separator_length; result = utils_malloc (result_length); for (scan = result, item = list->first; item; item = item->next) { int item_text_length = strlen (item->text); memcpy (scan, item->text, item_text_length); scan += item_text_length; if (item->next) { memcpy (scan, separator, separator_length); scan += separator_length; } } *scan = 0; } return result; } void association_list_item_dispose (AssociationListItem *item) { utils_free (item->association); } inline char * association_list_find_association (AssociationList *list, const char *key) { AssociationListItem *item = association_list_find (list, key); return item ? item->association : NULL; } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/utils/utils.c0000644000175000017500000006776110367243167014763 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003 Paul Pogonyshev. * * Copyright (C) 2004 Paul Pogonyshev and Martin Holters. * * Copyright (C) 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "utils.h" #include #include #include #include #include #include #include #ifdef HAVE_FLOAT_H #include #endif #ifdef HAVE_MEMORY_H #include #endif enum { PRECISION_DEFAULT = 6, PRECISION_SPECIAL = -1, PRECISION_PASSED_IN = -2 }; #if ENABLE_MEMORY_PROFILING static unsigned int num_mallocs = 0; static unsigned int num_reallocs = 0; static unsigned int num_frees = 0; static unsigned int num_bytes_allocated = 0; static unsigned int num_bytes_on_heap = 0; #endif char *full_program_name = NULL; char *short_program_name = NULL; char *program_directory = NULL; /* Call malloc() and check that it succeeds. Panic if it does not. * This function can also log some profiling information when * ENABLE_MEMORY_PROFILING is nonzero. * * This is a good place to store critical information (if any) when * out of memory. No critical information to store at present, * though, so this is not implemented. */ void * utils_malloc (size_t size) { void *pointer = malloc (size); #if ENABLE_MEMORY_PROFILING num_mallocs++; num_bytes_allocated += size; num_bytes_on_heap += (sizeof (void *) + (((size + sizeof (int) - 1) / sizeof (int)) * sizeof (int))); #endif if (pointer) return pointer; fprintf (stderr, ("%s: fatal error: out of memory " "(failed to allocate %d bytes)\n"), short_program_name, size); exit (255); } /* Convenience function. Allocate memory chunk and initialize all its * bytes to zero. */ void * utils_malloc0 (size_t size) { void *pointer = utils_malloc (size); memset (pointer, 0, size); return pointer; } /* Same as utils_malloc(), but based on realloc() instead of malloc(). * * When memory profiling is enabled, utils_realloc (NULL, ...) and * utils_realloc (..., 0) calls are counted as calls to utils_malloc() * and utils_free() respectively. */ void * utils_realloc (void *pointer, size_t size) { #if ENABLE_MEMORY_PROFILING if (pointer && size) num_reallocs++; else { if (!pointer) num_mallocs++; else num_frees++; } #endif pointer = realloc (pointer, size); if (pointer || size == 0) return pointer; fprintf (stderr, ("%s: fatal error: out of memory " "(failed to allocate %d bytes)\n"), short_program_name, size); exit (255); } #if ENABLE_MEMORY_PROFILING /* Free given memory block and log profiling information. */ void utils_free (void *pointer) { if (pointer) { num_frees++; free (pointer); } } /* Dump profiling information and warn if any allocated memory has not * been freed. */ void utils_print_memory_profiling_info (void) { fputs ("Memory profiling information:\n\n", stderr); fprintf (stderr, ("Numbers of calls:\n utils_malloc(): %10u\n" " utils_realloc(): %10u\n utils_free(): %10u\n\n"), num_mallocs, num_reallocs, num_frees); if (num_mallocs > num_frees) { fprintf (stderr, "%u memory blocks were not freed!\n\n", num_mallocs - num_frees); } fprintf (stderr, ("Total %u bytes allocated\n" "Guessed total dynamic memory footprint: %u bytes\n\n"), num_bytes_allocated, num_bytes_on_heap); #if ENABLE_MEMORY_POOLS fprintf (stderr, "Total %d memory pools initialized, %d flushed\n\n", num_pools_initialized, num_pools_flushed); if (num_pools_initialized > num_pools_flushed) { fprintf (stderr, "%d memory pools were not flushed!\n\n", num_pools_initialized - num_pools_flushed); } #endif } #endif /* ENABLE_MEMORY_PROFILING */ /* Allocate a copy of given string on heap. Analogous to strdup(), * which does not belong to most accepted standards (neither ASCII C, * nor POSIX). */ char * utils_duplicate_string (const char *string) { if (string) { int length = strlen (string); char *new_string = utils_malloc (length + 1); memcpy (new_string, string, length + 1); return new_string; } return NULL; } /* Allocate a copy of given buffer (pointer + length) on heap. */ void * utils_duplicate_buffer (const void *buffer, int length) { char *buffer_copy = utils_malloc (length); memcpy (buffer_copy, buffer, length); return buffer_copy; } /* Similar to utils_duplicate_buffer(), but also appends a zero byte * to the copy, thus making it a valid ASCIIZ string. */ char * utils_duplicate_as_string (const char *buffer, int length) { char *string = utils_malloc (length + 1); memcpy (string, buffer, length); string[length] = 0; return string; } /* Append second string to first. The first string is reallocated to * fit the concatenation. It must be a result of a previous heap * allocation or NULL. In the latter case, this function behaves just * like `utils_duplicate_string (to_cat)'. */ char * utils_cat_string (char *string, const char *to_cat) { int current_length = (string ? strlen (string) : 0); int to_cat_length = strlen (to_cat); char *new_string = utils_realloc (string, current_length + to_cat_length + 1); memcpy (new_string + current_length, to_cat, to_cat_length + 1); return new_string; } /* Append one or more strings to a given `string'. Last parameter * must be NULL (serves as parameter list terminator). * * Amount of space needed to store the concatenation of all strings is * calculated dynamically and `string' is reallocated accordingly. If * `string' is NULL, all the rest of strings are concatenated and are * stored in a newly allocated buffer. */ char * utils_cat_strings (char *string, ...) { int k; int current_length = (string ? strlen (string) : 0); int to_cat_lengths[16]; int length_increase = 0; char *new_string; va_list arguments; va_start (arguments, string); for (k = 0; ;) { int length; const char *to_cat = va_arg (arguments, const char *); if (!to_cat) break; length = strlen (to_cat); if (k < (int) (sizeof to_cat_lengths / sizeof (int))) to_cat_lengths[k++] = length; length_increase += length; } va_end (arguments); new_string = utils_realloc (string, current_length + length_increase + 1); va_start (arguments, string); for (k = 0; ;) { int length; const char *to_cat = va_arg (arguments, const char *); if (!to_cat) break; length = (k < (int) (sizeof to_cat_lengths / sizeof (int)) ? to_cat_lengths[k++] : (int) strlen (to_cat)); memcpy (new_string + current_length, to_cat, length); current_length += length; } va_end (arguments); new_string[current_length] = 0; return new_string; } /* Same as utils_cat_string(), but the second parameter is any buffer * and need not be a zero-terminated string. Result is still a valid * string, of course. * * The `string' can be NULL, in which case calling this function is * identical to calling `utils_duplicate_as_string (buffer, length)'. */ char * utils_cat_as_string (char *string, const char *buffer, int length) { int current_length = (string ? strlen (string) : 0); char *new_string = utils_realloc (string, current_length + length + 1); memcpy (new_string + current_length, buffer, length); new_string[current_length + length] = 0; return new_string; } /* Similar to utils_cat_strings() except that all parameters except * the first might pointer to non-terminated buffers (not necessarily * ASCIIZ strings). Each buffer parameter, except for terminating * NULL, must be followed by its length. * * As for all other `utils_cat_*' functions, `string' can be NULL. */ char * utils_cat_as_strings (char *string, ...) { int current_length = (string ? strlen (string) : 0); int length_increase = 0; char *new_string; va_list arguments; va_start (arguments, string); while (va_arg (arguments, const char *)) length_increase += va_arg (arguments, int); va_end (arguments); new_string = utils_realloc (string, current_length + length_increase + 1); va_start (arguments, string); while (1) { int length; const char *buffer = va_arg (arguments, const char *); if (!buffer) break; length = va_arg (arguments, int); memcpy (new_string + current_length, buffer, length); current_length += length; } va_end (arguments); new_string[current_length] = 0; return new_string; } /* Store program name for future use (on heap). This function * initializes `full_program_name', `short_program_name' and * `program_directory' variables. * * FIXME: DIRECTORY_SEPARATOR is still always '/'. */ void utils_remember_program_name (const char *argv0) { int short_name_pos; int length; length = strlen (argv0); for (short_name_pos = length; short_name_pos >= 0; short_name_pos--) { if (argv0[short_name_pos] == DIRECTORY_SEPARATOR) break; } short_name_pos++; full_program_name = utils_duplicate_as_string (argv0, length); short_program_name = utils_duplicate_as_string (argv0 + short_name_pos, length - short_name_pos); program_directory = utils_duplicate_as_string (argv0, short_name_pos); } /* Convenience function. Free the three program name strings stored * by utils_remember_program_name(). This can safely be called * without really storing them, though there is probably no reason not * to do that in the first place. */ void utils_free_program_name_strings (void) { utils_free (full_program_name); utils_free (short_program_name); utils_free (program_directory); } /* Call sprintf() with given `format_string' and arguments and return * its result in a dynamically allocated buffer. The current locale * is taken into account. */ char * utils_printf (const char *format_string, ...) { char *string; va_list arguments; va_start (arguments, format_string); string = utils_cat_vprintf (NULL, format_string, arguments); va_end (arguments); return string; } /* Same as utils_printf(), but `arguments' are passed as `va_list'. */ char * utils_vprintf (const char *format_string, va_list arguments) { return utils_cat_vprintf (NULL, format_string, arguments); } /* Call sprintf() with given `format_string' and arguments and * concatenate its result to given `string'. If `string' is NULL, * works just as utils_printf(). The current locale is taken into * account. */ char * utils_cat_printf (char *string, const char *format_string, ...) { va_list arguments; va_start (arguments, format_string); string = utils_cat_vprintf (string, format_string, arguments); va_end (arguments); return string; } /* Same as utils_cat_printf(), but `arguments' are passed as * `va_list'. */ char * utils_cat_vprintf (char *string, const char *format_string, va_list arguments) { char buffer[0x1000]; int head_length; int length; va_list arguments_copy; QUARRY_VA_COPY (arguments_copy, arguments); length = vsnprintf (buffer, sizeof buffer, format_string, arguments_copy); va_end (arguments_copy); if (-1 < length && length < (int) sizeof buffer) return utils_cat_as_string (string, buffer, length); head_length = (string ? strlen (string) : 0); length = (length > -1 ? length + 1 : 2 * sizeof buffer); while (1) { int required_length; string = utils_realloc (string, head_length + length); QUARRY_VA_COPY (arguments_copy, arguments); required_length = vsnprintf (string + head_length, length, format_string, arguments_copy); va_end (arguments_copy); if (-1 < required_length && required_length < length) { if (required_length < length) return utils_realloc (string, head_length + required_length + 1); else return string; } length = (required_length > -1 ? required_length + 1 : 2 * length); } } /* Call utils_ncprintf() with given `format_string' and arguments and * return its result in a dynamically allocated buffer. This function * ignores locales and should be used in cases when arguments are to * be formatted according to C locale. */ char * utils_cprintf (const char *format_string, ...) { char *string; int num_bytes_required; va_list arguments; va_start (arguments, format_string); num_bytes_required = utils_vncprintf (NULL, 0, format_string, arguments) + 1; va_end (arguments); string = utils_malloc (num_bytes_required); va_start (arguments, format_string); utils_vncprintf (string, num_bytes_required, format_string, arguments); va_end (arguments); return string; } /* Same as utils_cprintf(), but `arguments' are passed as * `va_list'. */ char * utils_vcprintf (const char *format_string, va_list arguments) { char *string; int num_bytes_required; va_list arguments_copy; QUARRY_VA_COPY (arguments_copy, arguments); num_bytes_required = (utils_vncprintf (NULL, 0, format_string, arguments_copy) + 1); va_end (arguments_copy); string = utils_malloc (num_bytes_required); utils_vncprintf (string, num_bytes_required, format_string, arguments); return string; } /* Format arguments in accordance with `format_string' and store * result in given `buffer'. At most `buffer_size' bytes (including * terminating '\0') are written. This function always formats * according to C locale; current locale is ignored. * * Only a subset of standard conversion specifiers is understood: `%c' * (character, must be ASCII), `%d' (decimal number), `%f' * (floating-point number) and `%s' (string). * * A '+' before `%d' or `%f' forces sign before positive numbers (by * default it is omitted). * * Width is supported for `%d', `%f' and `%s' conversions. As * usually, width starting with zero digit implies zero padding * instead of blank padding. * * Default precision for `%f' conversion is 6. Precision can be * changed in the conversion specifier in one of the following ways: * * `%.Nf' (where N is a non-negative decimal)---use precision N. * * `%.*f'---get precision as an integer argument. * * `%.f'---"special" precision: default precision (6) is used, but * all terminating zeros are removed, except if directly following * decimal point. So, 1.25 would get formatted as "1.25", not as * "1.250000", while 1.0 would get formatted as "1.0", not as "1.". */ int utils_ncprintf (char *buffer, int buffer_size, const char *format_string, ...) { int num_bytes_required; va_list arguments; va_start (arguments, format_string); num_bytes_required = utils_vncprintf (buffer, buffer_size, format_string, arguments); va_end (arguments); return num_bytes_required; } #define CHECK_FOR_END_OF_BUFFER \ do { \ if (buffer == buffer_end) { \ *buffer = 0; \ buffer = NULL; \ } \ } while (0) /* Same as utils_ncprintf(), but `arguments' are passed as * `va_list'. */ int utils_vncprintf (char *buffer, int buffer_size, const char *format_string, va_list arguments) { int num_bytes_required = 0; char *buffer_end = (buffer ? buffer + buffer_size - 1 : NULL); assert (buffer_size > 1 || !buffer); assert (format_string); while (*format_string) { if (*format_string != '%') { if (buffer) { *buffer++ = *format_string; CHECK_FOR_END_OF_BUFFER; } num_bytes_required++; format_string++; } else { const char *format_specifier = ++format_string; int sign_is_forced = 0; int field_width = -1; char padding_character = ' '; int precision = PRECISION_DEFAULT; if (*format_string == '+') { sign_is_forced = 1; format_string++; } if ('0' <= *format_string && *format_string <= '9') { if (*format_string == '0') padding_character = '0'; field_width = *format_string++ - '0'; while ('0' <= *format_string && *format_string <= '9') field_width = field_width * 10 + (*format_string++ - '0'); } if (*format_string == '.') { precision = PRECISION_SPECIAL; format_string++; if ('0' <= *format_string && *format_string <= '9') { for (precision = (*format_string++ - '0'); '0' <= *format_string && *format_string <= '9'; format_string++) precision = precision * 10 + (*format_string - '0'); } else if (*format_string == '*') { precision = PRECISION_PASSED_IN; format_string++; } if (*format_string != 'f') { format_string = format_specifier; continue; } } switch (*format_string++) { case 'c': if (!sign_is_forced || field_width != -1) { char character = (char) va_arg (arguments, int); if (buffer) { *buffer++ = (!(character & 0x80) ? character : ' '); CHECK_FOR_END_OF_BUFFER; } num_bytes_required++; } else format_string = format_specifier; break; case 'd': { int number = va_arg (arguments, int); char sign = 0; unsigned magnitude = (number >= 0 ? number : -number); unsigned magnitude_copy = magnitude; int num_digits = 0; if (number < 0 || sign_is_forced) { sign = (number < 0 ? '-' : '+'); num_bytes_required++; field_width--; } do { num_digits++; magnitude_copy /= 10; } while (magnitude_copy); if (field_width <= num_digits) { if (sign && buffer) { *buffer++ = sign; CHECK_FOR_END_OF_BUFFER; } num_bytes_required += num_digits; } else { if (sign && padding_character == '0' && buffer) { *buffer++ = sign; CHECK_FOR_END_OF_BUFFER; } if (buffer) { if (buffer_end - buffer > field_width - num_digits) { memset (buffer, padding_character, field_width - num_digits); buffer += field_width - num_digits; if (sign && padding_character == ' ' && buffer) { *buffer++ = sign; CHECK_FOR_END_OF_BUFFER; } } else { memset (buffer, padding_character, buffer_end - buffer); *buffer_end = 0; buffer = NULL; } } num_bytes_required += field_width; } if (buffer) { int k; while (num_digits > buffer_end - buffer) { magnitude /= 10; num_digits--; } for (k = num_digits; --k >= 0; ) { *(buffer + k) = '0' + (magnitude % 10); magnitude /= 10; } buffer += num_digits; CHECK_FOR_END_OF_BUFFER; } } break; case 'f': if (precision == PRECISION_PASSED_IN) { precision = va_arg (arguments, int); if (precision < 0) precision = 0; } { double number = va_arg (arguments, double); char sign = 0; int shift; int num_bytes_to_write; if (number < 0.0 || sign_is_forced) { sign = (number < 0.0 ? '-' : '+'); if (number < 0.0) number = -number; num_bytes_required++; field_width--; } if (precision != PRECISION_SPECIAL) { /* After this addition, proper rounding becomes simple * truncation. */ number += 0.5 * pow (10, -precision); } else { double fraction; number += 0.5 * pow (10, -PRECISION_DEFAULT); fraction = ((number - floor (number)) * pow (10, PRECISION_DEFAULT - 1)); /* Calculate precision: reduce from `PRECISION_DEFAULT' * down to 1 for as long as last digit is zero. */ for (precision = PRECISION_DEFAULT; precision > 1 && fraction - floor (fraction) < 0.1; precision--) fraction /= 10.0; } if (number >= 10.0) shift = 1 + floor (log10 (number)); else shift = 1; num_bytes_to_write = shift + (precision > 0 ? precision + 1 : 0); if (field_width <= num_bytes_to_write) { if (sign && buffer) { *buffer++ = sign; CHECK_FOR_END_OF_BUFFER; } num_bytes_required += num_bytes_to_write; } else { if (sign && padding_character == '0' && buffer) { *buffer++ = sign; CHECK_FOR_END_OF_BUFFER; } if (buffer) { if (buffer_end - buffer > field_width - num_bytes_to_write) { memset (buffer, padding_character, field_width - num_bytes_to_write); buffer += field_width - num_bytes_to_write; if (sign && padding_character == ' ' && buffer) { *buffer++ = sign; CHECK_FOR_END_OF_BUFFER; } } else { memset (buffer, padding_character, buffer_end - buffer); *buffer_end = 0; buffer = NULL; } } num_bytes_required += field_width; } if (buffer) { int k; /* Make number less than 10.0. */ number *= pow (10, (double) -(shift - 1)); if (num_bytes_to_write > buffer_end - buffer) num_bytes_to_write = buffer_end - buffer; for (k = 0; k < num_bytes_to_write; k++) { if (shift--) { *buffer++ = '0' + (char) (int) floor (number); number = (number - floor (number)) * 10.0; } else *buffer++ = '.'; } CHECK_FOR_END_OF_BUFFER; } } break; case 's': if (!sign_is_forced) { const char *string = va_arg (arguments, const char *); int length = strlen (string); if (buffer) { if (field_width > length) { if (buffer_end - buffer > field_width - length) { memset (buffer, padding_character, field_width - length); buffer += field_width - length; } else { memset (buffer, padding_character, buffer_end - buffer); *buffer_end = 0; buffer = NULL; } } if (buffer) { if (buffer_end - buffer > length) { memcpy (buffer, string, length); buffer += length; } else { memcpy (buffer, string, buffer_end - buffer); *buffer_end = 0; buffer = NULL; } } } num_bytes_required += MAX (length, field_width); } else format_string = format_specifier; break; default: format_string = format_specifier; } } } if (buffer) *buffer = 0; return num_bytes_required; } char * utils_special_printf (const char *format_string, ...) { char *string; va_list arguments; va_start (arguments, format_string); string = utils_special_vprintf (format_string, arguments); va_end (arguments); return string; } char * utils_special_vprintf (const char *format_string, va_list arguments) { char *string = NULL; const char *chunk_beginning = format_string; const char *string_scan = format_string; do { if (*string_scan == '%' || ! *string_scan) { if (string_scan > chunk_beginning) { if (string) { string = utils_cat_as_string (string, chunk_beginning, string_scan - chunk_beginning); } else { string = utils_duplicate_as_string (chunk_beginning, string_scan - chunk_beginning); } } if (*string_scan == '%' && * ++string_scan) { va_list arguments_copy; int format_character; chunk_beginning = string_scan; QUARRY_VA_COPY (arguments_copy, arguments); while ((format_character = va_arg (arguments_copy, int)) != 0) { const char *substitution = va_arg (arguments_copy, const char *); if (format_character == (int) *string_scan) { if (substitution) string = utils_cat_string (string, substitution); chunk_beginning++; break; } } va_end (arguments_copy); } } } while (*string_scan++); return string; } /* Read a line from file and allocate it dynamically as a single * string. If `length' is not NULL, it will be set to the length of * the resulting line. * * If the function is not able to read a single byte, NULL is returned * and `*length' is set to zero. */ char * utils_fgets (FILE *file, int *length) { char buffer[0x1000]; char *string = NULL; if (length) *length = 0; while (fgets (buffer, sizeof buffer, file)) { int chunk_length = strlen (buffer); if (!string) string = utils_duplicate_as_string (buffer, chunk_length); else string = utils_cat_as_string (string, buffer, chunk_length); if (length) *length += chunk_length; if (buffer[chunk_length - 1] == '\n') break; } return string; } /* Translate `msgid' using gettext() and strip context information if * needed. If gettext() performs actual translation (i.e. returns * something different than `msgid'), this function does nothing * extra. Else it strips context (part before a bar character, * inclusive) from `msgid' and returns the rest. When there is no bar * character in the string (i.e., no context), `msgid' is returned * unchanged. */ const char * utils_gettext_with_context (const char *msgid) { const char *msgstr = gettext (msgid); if (msgstr == msgid) { const char *context_end = strchr (msgstr, '|'); if (context_end) msgstr = context_end + 1; } return msgstr; } /* A function suitable for passing as fourth argument to qsort() for * sorting array of `int's in ascending order. */ int utils_compare_ints (const void *first_int, const void *second_int) { return * (const int *) first_int - * (const int *) second_int; } /* Parse a double number in a locale independent way. The string may * contain an optional sign ('+' or '-'), followed by digits, * optionally followed by a '.', optionally followed by more digits. * If the first character other then those is not '\0', a parsing * error is assumed and zero is returned. Otherwise, nonzero is * returned. Parsing an empty string produces 0.0 and returns * nonzero. */ int utils_parse_double (const char *float_string, double *result) { const char *scan = float_string; int is_negative = 0; if (result) *result = 0.0; if (*scan == '+' || *scan == '-') is_negative = (*scan++ == '-'); while (*scan >= '0' && *scan <= '9') { if (result) *result = *result * 10 + (double) (*scan - '0'); scan++; } if (*scan == '.') { double factor = 0.1; scan++; while (*scan >= '0' && *scan <= '9') { if (result) *result += (double) (*(scan) - '0') * factor; scan++; factor /= 10.0; } } if (is_negative && result) *result = - *result; return *scan == '\0'; } int utils_parse_time (const char *time_string) { const char *scan; int num_colons = 0; int digits_and_colons_only = 1; for (scan = time_string; *scan; scan++) { if (*scan == ':') { if (++num_colons > 2 || !digits_and_colons_only) return -1; } else if (*scan < '0' || '9' < *scan) { digits_and_colons_only = 0; if (num_colons != 0) return -1; } } if (num_colons > 0) { int hours = 0; int minutes = 0; int seconds = 0; int num_chars_eaten; if (num_colons == 2) { if (*time_string != ':') { sscanf (time_string, "%d:%n", &hours, &num_chars_eaten); time_string += num_chars_eaten; } else time_string++; } if (*time_string != ':') { sscanf (time_string, "%d:%n", &minutes, &num_chars_eaten); time_string += num_chars_eaten; } else time_string++; sscanf (time_string, "%d", &seconds); return (hours * 60 + minutes) * 60 + seconds; } else { char *minutes_end; double minutes_double = strtod (time_string, &minutes_end); if (minutes_end == time_string || minutes_double < 0.0 || minutes_double > (INT_MAX / 60.0) - 1.0) return -1; return (int) (60.0 * minutes_double + 0.5); } } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/utils/getopt.h0000644000175000017500000001462310237132521015102 0ustar bartbart/* Declarations for getopt. Copyright (C) 1989-1994, 1996-1999, 2001 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library 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 Lesser General Public License for more details. You should have received a copy of the GNU Library General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* 2005-05-07 Paul Pogonyshev * * Update FSF address in the legal notice above. */ #ifndef _GETOPT_H #ifndef __need_getopt # define _GETOPT_H 1 #endif /* If __GNU_LIBRARY__ is not already defined, either we are being used standalone, or this is the first header included in the source file. If we are being used with glibc, we need to include , but that does not exist if we are standalone. So: if __GNU_LIBRARY__ is not defined, include , which will pull in for us if it's from glibc. (Why ctype.h? It's guaranteed to exist and it doesn't flood the namespace with stuff the way some other headers do.) */ #if !defined __GNU_LIBRARY__ # include #endif #ifdef __cplusplus extern "C" { #endif /* For communication from `getopt' to the caller. When `getopt' finds an option that takes an argument, the argument value is returned here. Also, when `ordering' is RETURN_IN_ORDER, each non-option ARGV-element is returned here. */ extern char *optarg; /* Index in ARGV of the next element to be scanned. This is used for communication to and from the caller and for communication between successive calls to `getopt'. On entry to `getopt', zero means this is the first call; initialize. When `getopt' returns -1, this is the index of the first of the non-option elements that the caller should itself scan. Otherwise, `optind' communicates from one call to the next how much of ARGV has been scanned so far. */ extern int optind; /* Callers store zero here to inhibit the error message `getopt' prints for unrecognized options. */ extern int opterr; /* Set to an option character which was unrecognized. */ extern int optopt; #ifndef __need_getopt /* Describe the long-named options requested by the application. The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector of `struct option' terminated by an element containing a name which is zero. The field `has_arg' is: no_argument (or 0) if the option does not take an argument, required_argument (or 1) if the option requires an argument, optional_argument (or 2) if the option takes an optional argument. If the field `flag' is not NULL, it points to a variable that is set to the value given in the field `val' when the option is found, but left unchanged if the option is not found. To have a long-named option do something other than set an `int' to a compiled-in constant, such as set a value from `optarg', set the option's `flag' field to zero and its `val' field to a nonzero value (the equivalent single-letter option character, if there is one). For long options that have a zero `flag' field, `getopt' returns the contents of the `val' field. */ struct option { # if (defined __STDC__ && __STDC__) || defined __cplusplus const char *name; # else char *name; # endif /* has_arg can't be an enum because some compilers complain about type mismatches in all the code that assumes it is an int. */ int has_arg; int *flag; int val; }; /* Names for the values of the `has_arg' field of `struct option'. */ # define no_argument 0 # define required_argument 1 # define optional_argument 2 #endif /* need getopt */ /* Get definitions and prototypes for functions to process the arguments in ARGV (ARGC of them, minus the program name) for options given in OPTS. Return the option character from OPTS just read. Return -1 when there are no more options. For unrecognized options, or options missing arguments, `optopt' is set to the option letter, and '?' is returned. The OPTS string is a list of characters which are recognized option letters, optionally followed by colons, specifying that that letter takes an argument, to be placed in `optarg'. If a letter in OPTS is followed by two colons, its argument is optional. This behavior is specific to the GNU `getopt'. The argument `--' causes premature termination of argument scanning, explicitly telling `getopt' that there are no more options. If OPTS begins with `--', then non-option arguments are treated as arguments to the option '\0'. This behavior is specific to the GNU `getopt'. */ #if (defined __STDC__ && __STDC__) || defined __cplusplus # ifdef __GNU_LIBRARY__ /* Many other libraries have conflicting prototypes for getopt, with differences in the consts, in stdlib.h. To avoid compilation errors, only prototype getopt for the GNU C library. */ extern int getopt (int ___argc, char *const *___argv, const char *__shortopts); # else /* not __GNU_LIBRARY__ */ extern int getopt (); # endif /* __GNU_LIBRARY__ */ # ifndef __need_getopt extern int getopt_long (int ___argc, char *const *___argv, const char *__shortopts, const struct option *__longopts, int *__longind); extern int getopt_long_only (int ___argc, char *const *___argv, const char *__shortopts, const struct option *__longopts, int *__longind); /* Internal only. Users should not call this directly. */ extern int _getopt_internal (int ___argc, char *const *___argv, const char *__shortopts, const struct option *__longopts, int *__longind, int __long_only); # endif #else /* not __STDC__ */ extern int getopt (); # ifndef __need_getopt extern int getopt_long (); extern int getopt_long_only (); extern int _getopt_internal (); # endif #endif /* __STDC__ */ #ifdef __cplusplus } #endif /* Make sure we later can get all the definitions and declarations. */ #undef __need_getopt #endif /* getopt.h */ quarry-0.2.0/src/utils/utils.h0000644000175000017500000004345410520636627014757 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003 Paul Pogonyshev. * * Copyright (C) 2004 Paul Pogonyshev and Martin Holters. * * Copyright (C) 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef QUARRY_UTILS_H #define QUARRY_UTILS_H #include "quarry.h" #include #include #include #include /* Set to zero to disable memory pools. */ #define ENABLE_MEMORY_POOLS 1 /* Set to 1 to get lots of information about memory allocation. */ #define ENABLE_MEMORY_PROFILING 0 /* FIXME: proper `#ifdef's to make this work under Windows. */ #define DIRECTORY_SEPARATOR '/' /* Just a useful structure to have around. */ typedef struct _QuarryColor QuarryColor; struct _QuarryColor { unsigned char red; unsigned char green; unsigned char blue; }; #define STRUCTURE_FIELD_OFFSET(StructureType, field) \ (((const char *) &((StructureType *) NULL)->field) \ - (const char *) NULL) #define QUARRY_COLORS_ARE_EQUAL(first_color, second_color) \ ((first_color).red == (second_color).red \ && (first_color).green == (second_color).green \ && (first_color).blue == (second_color).blue) /* `utils.c' global functions. */ void * utils_malloc (size_t size); void * utils_malloc0 (size_t size); void * utils_realloc (void *pointer, size_t size); #if ENABLE_MEMORY_PROFILING void utils_free (void *pointer); void utils_print_memory_profiling_info (void); #else /* not ENABLE_MEMORY_PROFILING */ #define utils_free free #endif /* not ENABLE_MEMORY_PROFILING */ char * utils_duplicate_string (const char *string); void * utils_duplicate_buffer (const void *buffer, int length); char * utils_duplicate_as_string (const char *buffer, int length); char * utils_cat_string (char *string, const char *to_cat); char * utils_cat_strings (char *string, ...); char * utils_cat_as_string (char *string, const char *buffer, int length); char * utils_cat_as_strings (char *string, ...); void utils_remember_program_name (const char *argv0); void utils_free_program_name_strings (void); char * utils_printf (const char *format_string, ...); char * utils_vprintf (const char *format_string, va_list arguments); char * utils_cat_printf (char *string, const char *format_string, ...); char * utils_cat_vprintf (char *string, const char *format_string, va_list arguments); char * utils_cprintf (const char *format_string, ...); char * utils_vcprintf (const char *format_string, va_list arguments); int utils_ncprintf (char *buffer, int buffer_size, const char *format_string, ...); int utils_vncprintf (char *buffer, int buffer_size, const char *format_string, va_list arguments); char * utils_special_printf (const char *format_string, ...); char * utils_special_vprintf (const char *format_string, va_list arguments); char * utils_fgets (FILE *file, int *length); const char * utils_gettext_with_context (const char *msgid); int utils_compare_ints (const void *first_int, const void *second_int); int utils_parse_double (const char *float_string, double *result); int utils_parse_time (const char *time_string); extern char *full_program_name; extern char *short_program_name; extern char *program_directory; /* `memory-pool.c' declarations and global functions. */ #if ENABLE_MEMORY_POOLS #define NUM_ITEMS_IN_CHUNK 128 /* NOTE: this field is private to memory pool, it should never be * accessed from other code, especially, it must _never_ be * written to. */ #define MEMORY_POOL_ITEM_INDEX ItemIndex item_index typedef char ItemIndex; typedef struct _MemoryChunk MemoryChunk; typedef struct _MemoryPool MemoryPool; struct _MemoryChunk { MemoryChunk *next; MemoryChunk *previous; ItemIndex first_free_item; unsigned char num_free_items; /* We use `int' here to force proper memory alignment. */ int memory[1]; }; struct _MemoryPool { int item_size; int index_field_offset; MemoryChunk *first_chunk; MemoryChunk *last_chunk; #if ENABLE_MEMORY_PROFILING int number; unsigned int num_chunks_allocated; unsigned int num_chunks_freed; unsigned int num_items_allocated; unsigned int num_items_freed; #endif }; typedef void (* MemoryPoolCallback) (void *item); typedef void (* MemoryPoolDataCallback) (void *item, void *data); void memory_pool_init (MemoryPool *pool, int item_size, int index_field_offset); void * memory_pool_alloc (MemoryPool *pool); void memory_pool_free (MemoryPool *pool, void *item); int memory_pool_count_items (const MemoryPool *pool); void memory_pool_traverse (const MemoryPool *pool, MemoryPoolCallback callback); void memory_pool_traverse_data (const MemoryPool *pool, MemoryPoolDataCallback callback, void *data); void memory_pool_flush (MemoryPool *pool); #if ENABLE_MEMORY_PROFILING extern int num_pools_initialized; extern int num_pools_flushed; #endif #else /* not ENABLE_MEMORY_POOLS */ #define MEMORY_POOL_ITEM_INDEX typedef struct _MemoryPool MemoryPool; struct _MemoryPool { int item_size; }; #define memory_pool_init(pool, _item_size, index_field_offset) \ ((pool)->item_size = (_item_size)) #define memory_pool_alloc(pool) \ utils_malloc ((pool)->item_size) #define memory_pool_free(pool, item) \ (UNUSED (pool), utils_free (item)) /* Functions memory_pool_count_items(), memory_pool_traverse(), * memory_pool_traverse_data() and memory_pool_flush() cannot be * emulated. They must not be used if ENABLE_MEMORY_POOLS is zero. */ #endif /* not ENABLE_MEMORY_POOLS */ /* `string-list.c' declarations and global functions. */ /* Note that string lists and notches (items) are passed to functions * as `void *'. Creating useful derived string lists seems impossible * otherwise. Either it involves lots of ugly typecasts which remove * all advantages of type checking, or forces to reimplement all list * functionality with new types, thus making "derivation" senseless. * * The only thing to remember when using string lists is to _always_ * double check what you actually pass as function parameters. */ typedef void (* StringListItemDispose) (void *abstract_item); typedef struct _StringListItem StringListItem; typedef struct _StringList StringList; struct _StringListItem { StringListItem *next; char *text; }; struct _StringList { StringListItem *first; StringListItem *last; int item_size; StringListItemDispose item_dispose; }; #define string_list_new() \ ((StringList *) \ string_list_new_derived (sizeof (StringListItem), NULL)) #define string_list_init(list) \ string_list_init_derived ((list), sizeof (StringListItem), NULL) #define STATIC_STRING_LIST \ STATIC_STRING_LIST_DERIVED (StringListItem, NULL) #define STATIC_STRING_LIST_DERIVED(ItemType, item_dispose) \ { NULL, NULL, \ sizeof (ItemType), (StringListItemDispose) (item_dispose) } void * string_list_new_derived (int item_size, StringListItemDispose item_dispose); void string_list_init_derived (void *abstract_list, int item_size, StringListItemDispose item_dispose); void string_list_delete (void *abstract_list); void string_list_empty (void *abstract_list); #define string_list_is_empty(abstract_list) \ ((abstract_list)->first == NULL) #define string_list_is_single_string(abstract_list) \ ((abstract_list)->first != NULL \ && (abstract_list)->first == (abstract_list)->last) int string_list_count_items (void *abstract_list); void string_list_fill_from_string (void *abstract_list, const char *super_string); /* Note that this function only operates on non-derived StringLists. * I don't want to introduce copy constructor for list items unless * really needed. */ void string_list_duplicate_items (StringList *list, const StringList *duplicate_from_list); void string_list_steal_items (void *abstract_list, void *steal_from); void string_list_add (void *abstract_list, const char *string); void string_list_add_from_buffer (void *abstract_list, const char *buffer, int length); void string_list_add_ready (void *abstract_list, char *allocated_string); void string_list_add_ready_item (void *abstract_list, void *abstract_item); void string_list_prepend (void *abstract_list, const char *string); void string_list_prepend_from_buffer (void *abstract_list, const char *buffer, int length); void string_list_prepend_ready (void *abstract_list, char *allocated_string); void string_list_prepend_ready_item (void *abstract_list, void *abstract_item); void * string_list_insert (void *abstract_list, void *abstract_notch, const char *string); void * string_list_insert_from_buffer (void *abstract_list, void *abstract_notch, const char *buffer, int length); void * string_list_insert_ready (void *abstract_list, void *abstract_notch, char *allocated_string); void * string_list_insert_ready_item (void *abstract_list, void *abstract_notch, void *abstract_item); void string_list_dispose_item (const void *abstract_list, void *abstract_item); void string_list_delete_item (void *abstract_list, void *abstract_item); void string_list_delete_first_item (void *abstract_list); void * string_list_steal_item (void *abstract_list, void *abstract_item); void * string_list_steal_first_item (void *abstract_list); int string_list_clamp_size (void *abstract_list, int max_size); int string_list_get_item_index (void *abstract_list, void *abstract_item); StringListItem * string_list_get_item (void *abstract_list, int item_index); StringListItem * string_list_find (const void *abstract_list, const char *text); StringListItem * string_list_find_after_notch (const void *abstract_list, const char *text, const void *abstract_notch); void string_list_swap_with_next (void *abstract_list, void *abstract_item); void string_list_swap_with_previous (void *abstract_list, void *abstract_item); void string_list_move (void *abstract_list, void *abstract_item, void *abstract_notch); char * string_list_implode (const void *abstract_list, const char *separator); /* A type derived from string list. */ typedef struct _AssociationListItem AssociationListItem; typedef struct _AssociationList AssociationList; struct _AssociationListItem { AssociationListItem *next; char *key; char *association; }; struct _AssociationList { AssociationListItem *first; AssociationListItem *last; int item_size; StringListItemDispose item_dispose; }; #define association_list_new() \ ((AssociationList *) \ string_list_new_derived (sizeof (AssociationListItem), \ ((StringListItemDispose) \ association_list_item_dispose))) #define association_list_init(list) \ string_list_init_derived ((list), sizeof (AssociationListItem), \ ((StringListItemDispose) \ association_list_item_dispose)) #define STATIC_ASSOCIATION_LIST \ STATIC_STRING_LIST_DERIVED (AssociationListItem, \ association_list_item_dispose) void association_list_item_dispose (AssociationListItem *item); #define association_list_get_item(list, item_index) \ ((AssociationListItem *) string_list_get_item ((list), (item_index))) #define association_list_find(list, key) \ ((AssociationListItem *) string_list_find ((list), (key))) #define association_list_find_after_notch(list, key, notch) \ ((AssociationListItem *) string_list_find_after_notch ((list), (key), \ (notch))) inline char * association_list_find_association (AssociationList *list, const char *key); /* `string-buffer.c' declarations and global functions. */ typedef struct _StringBuffer StringBuffer; struct _StringBuffer { char *string; int length; int current_size; int size_increment; }; StringBuffer * string_buffer_new (int initial_size, int size_increment); void string_buffer_init (StringBuffer *string_buffer, int initial_size, int size_increment); void string_buffer_delete (StringBuffer *string_buffer); void string_buffer_dispose (StringBuffer *string_buffer); void string_buffer_empty (StringBuffer *string_buffer); char * string_buffer_steal_string (StringBuffer *string_buffer); #define string_buffer_add_character(string_buffer, character) \ string_buffer_add_characters ((string_buffer), (character), 1) void string_buffer_add_characters (StringBuffer *string_buffer, char character, int num_characters); void string_buffer_cat_string (StringBuffer *string_buffer, const char *string); void string_buffer_cat_strings (StringBuffer *string_buffer, ...); void string_buffer_cat_as_string (StringBuffer *string_buffer, const char *buffer, int length); void string_buffer_cat_as_strings (StringBuffer *string_buffer, ...); void string_buffer_printf (StringBuffer *string_buffer, const char *format_string, ...); void string_buffer_vprintf (StringBuffer *string_buffer, const char *format_string, va_list arguments); void string_buffer_cprintf (StringBuffer *string_buffer, const char *format_string, ...); void string_buffer_vcprintf (StringBuffer *string_buffer, const char *format_string, va_list arguments); /* `buffered-writer.c' declarations and global functions. */ typedef struct _BufferedWriter BufferedWriter; typedef struct _BufferedWriterChunkData BufferedWriterChunkData; struct _BufferedWriter { FILE *file; BufferedWriterChunkData *first_chunk; size_t buffer_size; char *buffer; char *buffer_pointer; char *buffer_end; iconv_t iconv_handle; size_t column; int successful; char* error_string; }; struct _BufferedWriterChunkData { BufferedWriterChunkData *next_chunk; size_t chunk_size; }; const char * buffered_writer_init (BufferedWriter *writer, const char *filename, size_t buffer_size); void buffered_writer_init_memory (BufferedWriter *writer, size_t buffer_size); int buffered_writer_dispose (BufferedWriter *writer); char * buffered_writer_dispose_memory (BufferedWriter *writer, int *data_length); #define buffered_writer_set_iconv_handle(writer, handle) \ ((writer)->iconv_handle = (handle)) void buffered_writer_add_character (BufferedWriter *writer, char character); void buffered_writer_add_newline (BufferedWriter *writer); void buffered_writer_cat_string (BufferedWriter *writer, const char *string); void buffered_writer_cat_strings (BufferedWriter *writer, ...); void buffered_writer_cat_as_string (BufferedWriter *writer, const char *buffer, size_t length); void buffered_writer_cat_as_strings (BufferedWriter *writer, ...); void buffered_writer_printf (BufferedWriter *writer, const char *format_string, ...); void buffered_writer_vprintf (BufferedWriter *writer, const char *format_string, va_list arguments); void buffered_writer_cprintf (BufferedWriter *writer, const char *format_string, ...); void buffered_writer_vcprintf (BufferedWriter *writer, const char *format_string, va_list arguments); /* `object-cache.c' declarations and global functions. */ typedef int (* ObjectCacheCompareKeys) (const void *first_key, const void *second_key); typedef void * (* ObjectCacheCreate) (const void *key); typedef void (* ObjectCacheDelete) (void *object); typedef struct _ObjectCacheEntry ObjectCacheEntry; typedef struct _ObjectCache ObjectCache; struct _ObjectCacheEntry { int reference_counter; ObjectCacheEntry *next; void *key; void *object; }; struct _ObjectCache { ObjectCacheEntry *first_stock_entry; ObjectCacheEntry *first_dump_entry; int current_dump_size; int max_dump_size; ObjectCacheCompareKeys compare_keys; ObjectCacheCreate duplicate_key; ObjectCacheCreate create_object; ObjectCacheDelete delete_key; ObjectCacheDelete delete_object; }; void * object_cache_create_or_reuse_object (ObjectCache *cache, const void *key); void object_cache_unreference_object (ObjectCache *cache, void *object); void object_cache_recycle_dump (ObjectCache *cache, int lazy_recycling); void object_cache_free (ObjectCache *cache); #endif /* QUARRY_UTILS_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/board/0000755000175000017500000000000010530402567013356 5ustar bartbartquarry-0.2.0/src/board/Makefile.in0000644000175000017500000004044410425150133015421 0ustar bartbart# Makefile.in generated by automake 1.7.9 from Makefile.am. # @configure_input@ # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 # Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # Process this file with Automake produce `Makefile.in'. srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = ../.. am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : host_triplet = @host@ ACLOCAL = @ACLOCAL@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BUILD_SGF_UTILS_FALSE = @BUILD_SGF_UTILS_FALSE@ BUILD_SGF_UTILS_TRUE = @BUILD_SGF_UTILS_TRUE@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DO_SCROLLKEEPER_UPDATE_FALSE = @DO_SCROLLKEEPER_UPDATE_FALSE@ DO_SCROLLKEEPER_UPDATE_TRUE = @DO_SCROLLKEEPER_UPDATE_TRUE@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ GMSGFMT = @GMSGFMT@ HAVE_SCROLLKEEPER_FALSE = @HAVE_SCROLLKEEPER_FALSE@ HAVE_SCROLLKEEPER_TRUE = @HAVE_SCROLLKEEPER_TRUE@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ LDFLAGS = @LDFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ MAKEINFO = @MAKEINFO@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGMERGE = @MSGMERGE@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSUB = @POSUB@ QUARRY_GTHREAD_CFLAGS = @QUARRY_GTHREAD_CFLAGS@ QUARRY_GTHREAD_LIBS = @QUARRY_GTHREAD_LIBS@ QUARRY_GTK_CFLAGS = @QUARRY_GTK_CFLAGS@ QUARRY_GTK_DEPRECATED_FLAGS = @QUARRY_GTK_DEPRECATED_FLAGS@ QUARRY_GTK_LIBS = @QUARRY_GTK_LIBS@ QUARRY_WARNINGS = @QUARRY_WARNINGS@ QUARRY_WARNINGS_GTK = @QUARRY_WARNINGS_GTK@ RANLIB = @RANLIB@ REGISTER_MIME_TYPES_FALSE = @REGISTER_MIME_TYPES_FALSE@ REGISTER_MIME_TYPES_TRUE = @REGISTER_MIME_TYPES_TRUE@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ ac_ct_CC = @ac_ct_CC@ ac_ct_RANLIB = @ac_ct_RANLIB@ ac_ct_STRIP = @ac_ct_STRIP@ ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ datadir = @datadir@ exec_prefix = @exec_prefix@ have_scrollkeeper = @have_scrollkeeper@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localstatedir = @localstatedir@ mandir = @mandir@ oldincludedir = @oldincludedir@ prefix = @prefix@ program_transform_name = @program_transform_name@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ AM_CPPFLAGS = \ $(QUARRY_WARNINGS) \ \ -I $(top_srcdir)/src \ -I $(top_srcdir)/src/utils noinst_LIBRARIES = libboard.a LIST_FILES = games.list PARSE_LIST_COMMAND = ./parse-game-list$(EXEEXT) PARSE_LIST_FLAGS = SUFFIXES = .list .h # `LIST_FILES' must be set by the includer. The includer can use # `LIST_STAMP_FILES' and `LIST_GENERATED_FILES' and assume they are # set just as here. # LIST_STAMP_FILES = $(LIST_FILES:.list=.stamp) LIST_GENERATED_FILES = $(LIST_FILES:.list=.c) $(LIST_FILES:.list=.h) # `PARSE_LIST_COMMAND' and `PARSE_LIST_FLAGS' should be set by the # includer. # PARSE_LIST = $(PARSE_LIST_COMMAND) $(PARSE_LIST_FLAGS) # We use `cmp' here to avoid unneeded recompilations of files that # depend on generated ones (only really useful for `.h' files.) # PARSE_LIST_BUILD_RULE = \ if $(PARSE_LIST) `test -f '$<' || echo '$(srcdir)/'`$< \ $*.h.new $*.c.new; then \ if cmp -s $*.c.new $*.c; \ then rm -f $*.c.new; else mv -f $*.c.new $*.c; \ fi; \ if cmp -s $*.h.new $*.h; \ then rm -f $*.h.new; else mv -f $*.h.new $*.h; \ fi; \ echo timestamp > $@; \ else \ (rm -f $*.c $*.c.new $*.h $*.h.new ; exit 1) \ fi libboard_a_SOURCES = \ amazons.c \ board.c \ go.c \ reversi.c \ \ amazons.h \ board.h \ board-topology.h \ board-internals.h \ game-info.h \ go.h \ reversi.h \ \ $(LIST_FILES) nodist_libboard_a_SOURCES = $(LIST_GENERATED_FILES) BUILT_SOURCES = $(LIST_STAMP_FILES) noinst_PROGRAMS = parse-game-list parse_game_list_SOURCES = parse-game-list.c parse_game_list_LDADD = \ $(top_builddir)/src/utils/libparselist.a \ $(top_builddir)/src/utils/libutils.a DISTCLEANFILES = *~ MOSTLYCLEANFILES = \ $(LIST_STAMP_FILES) \ $(LIST_GENERATED_FILES) subdir = src/board ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 mkinstalldirs = $(SHELL) $(top_srcdir)/build/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = LIBRARIES = $(noinst_LIBRARIES) libboard_a_AR = $(AR) cru libboard_a_LIBADD = am__objects_1 = am_libboard_a_OBJECTS = amazons.$(OBJEXT) board.$(OBJEXT) go.$(OBJEXT) \ reversi.$(OBJEXT) $(am__objects_1) am__objects_2 = games.$(OBJEXT) am__objects_3 = $(am__objects_2) $(am__objects_1) nodist_libboard_a_OBJECTS = $(am__objects_3) libboard_a_OBJECTS = $(am_libboard_a_OBJECTS) \ $(nodist_libboard_a_OBJECTS) noinst_PROGRAMS = parse-game-list$(EXEEXT) PROGRAMS = $(noinst_PROGRAMS) am_parse_game_list_OBJECTS = parse-game-list.$(OBJEXT) parse_game_list_OBJECTS = $(am_parse_game_list_OBJECTS) parse_game_list_DEPENDENCIES = $(top_builddir)/src/utils/libparselist.a \ $(top_builddir)/src/utils/libutils.a parse_game_list_LDFLAGS = DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/build/depcomp am__depfiles_maybe = depfiles @AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/amazons.Po ./$(DEPDIR)/board.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/games.Po ./$(DEPDIR)/go.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/parse-game-list.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/reversi.Po COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ DIST_SOURCES = $(libboard_a_SOURCES) $(parse_game_list_SOURCES) DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/build/list.make \ Makefile.am SOURCES = $(libboard_a_SOURCES) $(nodist_libboard_a_SOURCES) $(parse_game_list_SOURCES) all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: .list .h .c .o .obj .stamp $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/build/list.make $(top_srcdir)/configure.ac $(ACLOCAL_M4) cd $(top_srcdir) && \ $(AUTOMAKE) --foreign src/board/Makefile Makefile: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) AR = ar clean-noinstLIBRARIES: -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) libboard.a: $(libboard_a_OBJECTS) $(libboard_a_DEPENDENCIES) -rm -f libboard.a $(libboard_a_AR) libboard.a $(libboard_a_OBJECTS) $(libboard_a_LIBADD) $(RANLIB) libboard.a clean-noinstPROGRAMS: -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS) parse-game-list$(EXEEXT): $(parse_game_list_OBJECTS) $(parse_game_list_DEPENDENCIES) @rm -f parse-game-list$(EXEEXT) $(LINK) $(parse_game_list_LDFLAGS) $(parse_game_list_OBJECTS) $(parse_game_list_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) core *.core distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/amazons.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/board.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/games.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parse-game-list.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/reversi.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ @am__fastdepCC_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ @am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ @am__fastdepCC_TRUE@ fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `test -f '$<' || echo '$(srcdir)/'`$< .c.obj: @am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ @am__fastdepCC_TRUE@ -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi`; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ @am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ @am__fastdepCC_TRUE@ fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi` uninstall-info-am: ETAGS = etags ETAGSFLAGS = CTAGS = ctags CTAGSFLAGS = tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(ETAGS_ARGS)$$tags$$unique" \ || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = ../.. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) $(mkinstalldirs) $(distdir)/../../build @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ case $$file in \ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ esac; \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ dir="/$$dir"; \ $(mkinstalldirs) "$(distdir)$$dir"; \ else \ dir=''; \ fi; \ if test -d $$d/$$file; then \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-am all-am: Makefile $(LIBRARIES) $(PROGRAMS) installdirs: install: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) clean-generic: distclean-generic: -rm -f $(CONFIG_CLEAN_FILES) -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) clean: clean-am clean-am: clean-generic clean-noinstLIBRARIES clean-noinstPROGRAMS \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: info: info-am info-am: install-data-am: install-exec-am: install-info: install-info-am install-man: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-info-am .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ clean-noinstLIBRARIES clean-noinstPROGRAMS ctags distclean \ distclean-compile distclean-generic distclean-tags distdir dvi \ dvi-am info info-am install install-am install-data \ install-data-am install-exec install-exec-am install-info \ install-info-am install-man install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \ uninstall-am uninstall-info-am # Avoid problems with parallel builds. games.c: games.h # Make everything depend on the `Makefile' and the list parser. $(LIST_STAMP_FILES) : Makefile $(PARSE_LIST_COMMAND) .list.stamp: $(PARSE_LIST_BUILD_RULE) # Since $(LIST_GENERATED_FILES) defined by the includer don't (at # least shouldn't) have any dependencies, if this rule is being # executed, it probably means that one of the files was removed. # Then all we can do is to force rebuilding of corresponding stamp # file, which builds the required sources ``by side-effect.'' # $(LIST_GENERATED_FILES): rm -f $*.stamp; $(MAKE) $(AM_MAKEFLAGS) $*.stamp # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: quarry-0.2.0/src/board/Makefile.am0000644000175000017500000000171310425150037015407 0ustar bartbart# Process this file with Automake produce `Makefile.in'. AM_CPPFLAGS = \ $(QUARRY_WARNINGS) \ \ -I $(top_srcdir)/src \ -I $(top_srcdir)/src/utils noinst_LIBRARIES = libboard.a LIST_FILES = games.list PARSE_LIST_COMMAND = ./parse-game-list$(EXEEXT) PARSE_LIST_FLAGS = # Avoid problems with parallel builds. games.c: games.h include $(top_srcdir)/build/list.make libboard_a_SOURCES = \ amazons.c \ board.c \ go.c \ reversi.c \ \ amazons.h \ board.h \ board-topology.h \ board-internals.h \ game-info.h \ go.h \ reversi.h \ \ $(LIST_FILES) nodist_libboard_a_SOURCES = $(LIST_GENERATED_FILES) BUILT_SOURCES = $(LIST_STAMP_FILES) noinst_PROGRAMS = parse-game-list parse_game_list_SOURCES = parse-game-list.c parse_game_list_LDADD = \ $(top_builddir)/src/utils/libparselist.a \ $(top_builddir)/src/utils/libutils.a DISTCLEANFILES = *~ MOSTLYCLEANFILES = \ $(LIST_STAMP_FILES) \ $(LIST_GENERATED_FILES) quarry-0.2.0/src/board/amazons.c0000644000175000017500000002533710376424133015205 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "amazons.h" #include "board-internals.h" #include #include static inline int amazon_has_any_legal_move (const char grid[BOARD_FULL_GRID_SIZE], int pos); /* Just handle weird situations when there are no amazons of either * color on board. Even if a player has no legal move, he is still to * play according to Amazons rules (and thus loses the game). */ int amazons_adjust_color_to_play (const Board *board, BoardRuleSet rule_set, int color) { int pos; int have_other_color = 0; UNUSED (rule_set); for (pos = POSITION (0, 0); ON_GRID (board->grid, pos); pos += (BOARD_MAX_WIDTH + 1) - board->width) { for (; ON_GRID (board->grid, pos); pos++) { if (board->grid[pos] == color) return color; else if (board->grid[pos] == OTHER_COLOR (color)) have_other_color = 1; } } return have_other_color ? OTHER_COLOR (color) : EMPTY; } /* Determine if Amazons game is over, i.e. if there is no legal move * for `color_to_play'. */ int amazons_is_game_over (const Board *board, BoardRuleSet rule_set, int color_to_play) { int pos; assert (rule_set < NUM_AMAZONS_RULE_SETS); for (pos = POSITION (0, 0); ON_GRID (board->grid, pos); pos += (BOARD_MAX_WIDTH + 1) - board->width) { for (; ON_GRID (board->grid, pos); pos++) { if (board->grid[pos] == color_to_play && amazon_has_any_legal_move (board->grid, pos)) return 0; } } return 1; } /* Get the default setup for Amazons. */ int amazons_get_default_setup (int width, int height, BoardPositionList **black_stones, BoardPositionList **white_stones) { int x1 = (width - 1) / 3; int x2 = (width - 1) - x1; int y1 = (height - 1) / 3; int y2 = (height - 1) - y1; *black_stones = board_position_list_new_empty (4); (*black_stones)->positions[0] = POSITION (x1, 0); (*black_stones)->positions[1] = POSITION (x2, 0); (*black_stones)->positions[2] = POSITION (0, y1); (*black_stones)->positions[3] = POSITION (width - 1, y1); *white_stones = board_position_list_new_empty (4); (*white_stones)->positions[0] = POSITION (0, y2); (*white_stones)->positions[1] = POSITION (width - 1, y2); (*white_stones)->positions[2] = POSITION (x1, height - 1); (*white_stones)->positions[3] = POSITION (x2, height - 1); return 1; } /* Determine if a move is legal according to specified rule set. If * "to" point is a null point, determine if there is any legal move * for the amazon at "from". Likewise, if the "shoot-arrow-to" point * is a null point, determine if there is any legal move involving * given "from" and "to" points (there is always at least one). */ int amazons_is_legal_move (const Board *board, BoardRuleSet rule_set, int color, va_list move) { const char *grid = board->grid; int pos; int to_x; int to_y; int to_pos; BoardAmazonsMoveData move_data; int from_pos; int shoot_arrow_to_pos; int direction; assert (rule_set < NUM_AMAZONS_RULE_SETS); to_x = va_arg (move, int); to_y = va_arg (move, int); move_data = va_arg (move, BoardAmazonsMoveData); assert (ON_BOARD (board, move_data.from.x, move_data.from.y)); from_pos = POINT_TO_POSITION (move_data.from); if (grid[from_pos] != color) return 0; if (rule_set == AMAZONS_RULE_SET_SGF) return 1; if (IS_NULL_POINT (to_x, to_y)) return amazon_has_any_legal_move (grid, from_pos); assert (ON_BOARD (board, to_x, to_y)); direction = determine_position_delta (to_x - move_data.from.x, to_y - move_data.from.y); if (!direction) return 0; to_pos = POSITION (to_x, to_y); for (pos = from_pos; pos != to_pos; ) { pos += direction; if (grid[pos] != EMPTY) return 0; } if (IS_NULL_POINT (move_data.shoot_arrow_to.x, move_data.shoot_arrow_to.y)) return 1; assert (ON_BOARD (board, move_data.shoot_arrow_to.x, move_data.shoot_arrow_to.y)); direction = determine_position_delta (move_data.shoot_arrow_to.x - to_x, move_data.shoot_arrow_to.y - to_y); if (!direction) return 0; shoot_arrow_to_pos = POINT_TO_POSITION (move_data.shoot_arrow_to); do { pos += direction; if (grid[pos] != EMPTY && pos != from_pos) return 0; } while (pos != shoot_arrow_to_pos); return 1; } static inline int amazon_has_any_legal_move (const char grid[BOARD_FULL_GRID_SIZE], int pos) { int k; for (k = 0; k < 8; k++) { if (grid[pos + delta[k]] == EMPTY) return 1; } return 0; } void amazons_play_move (Board *board, int color, va_list move) { char *grid = board->grid; int to_x; int to_y; AmazonsMoveStackEntry *stack_entry = ALLOCATE_AMAZONS_MOVE_STACK_ENTRY (board); BoardAmazonsMoveData move_data; to_x = va_arg (move, int); to_y = va_arg (move, int); move_data = va_arg (move, BoardAmazonsMoveData); assert (ON_BOARD (board, move_data.from.x, move_data.from.y)); assert (ON_BOARD (board, to_x, to_y)); assert (ON_BOARD (board, move_data.shoot_arrow_to.x, move_data.shoot_arrow_to.y)); assert (grid[POINT_TO_POSITION (move_data.from)] == color); stack_entry->from = POINT_TO_POSITION (move_data.from); stack_entry->to = POSITION (to_x, to_y); stack_entry->misc.shoot_arrow_to = POINT_TO_POSITION (move_data.shoot_arrow_to); stack_entry->to_contents = grid[stack_entry->to]; stack_entry->shoot_arrow_to_contents = grid[stack_entry->misc.shoot_arrow_to]; grid[stack_entry->from] = EMPTY; grid[stack_entry->to] = color; grid[stack_entry->misc.shoot_arrow_to] = ARROW; stack_entry->common.move_number = board->move_number++; } void amazons_undo (Board *board) { AmazonsMoveStackEntry *stack_entry = POP_AMAZONS_MOVE_STACK_ENTRY (board); if (stack_entry->from != NULL_POSITION) { board->grid[stack_entry->from] = board->grid[stack_entry->to]; board->grid[stack_entry->to] = stack_entry->to_contents; board->grid[stack_entry->misc.shoot_arrow_to] = stack_entry->shoot_arrow_to_contents; } else if (stack_entry->misc.num_changes > 0) board_undo_changes (board, stack_entry->misc.num_changes); board->move_number = stack_entry->common.move_number; } void amazons_apply_changes (Board *board, int num_changes) { AmazonsMoveStackEntry *stack_entry = ALLOCATE_AMAZONS_MOVE_STACK_ENTRY (board); stack_entry->from = NULL_POSITION; stack_entry->misc.num_changes = num_changes; stack_entry->common.move_number = board->move_number; } void amazons_add_dummy_move_entry (Board *board) { amazons_apply_changes (board, 0); } void amazons_validate_board (const Board *board) { UNUSED (board); } void amazons_dump_board (const Board *board) { static const char contents[5] = {'.', '@', 'O', '=', '?'}; static const char coordinates[] = " A B C D E F G H I J K L M N O P Q R S T U V W X Y"; int x; int y; fprintf (stderr, " %.*s\n", board->width * 2, coordinates); for (y = 0; y < board->height; y++) { fprintf (stderr, "%3d", board->height - y); for (x = 0; x < board->width; x++) fprintf (stderr, " %c", contents[(int) board->grid[POSITION (x, y)]]); fprintf (stderr, "%3d\n", board->height - y); } fprintf (stderr, " %.*s\n", board->width * 2, coordinates); } void amazons_format_move (int board_width, int board_height, StringBuffer *buffer, va_list move) { int x = va_arg (move, int); int y = va_arg (move, int); BoardAmazonsMoveData move_data = va_arg (move, BoardAmazonsMoveData); game_format_point (GAME_AMAZONS, board_width, board_height, buffer, move_data.from.x, move_data.from.y); string_buffer_add_character (buffer, '-'); game_format_point (GAME_AMAZONS, board_width, board_height, buffer, x, y); string_buffer_add_character (buffer, '-'); game_format_point (GAME_AMAZONS, board_width, board_height, buffer, move_data.shoot_arrow_to.x, move_data.shoot_arrow_to.y); } /* Parse an Amazons move. Quarry understands three commonly used (and * similar to each other) formats: A1-B2-C3, A1-B2/C3 and A1-B2xC3. * This is of course only half of the work, as when speaking GTP, the * other side has to understand us too (we speak the first vartiant.) */ int amazons_parse_move (int board_width, int board_height, const char *move_string, int *x, int *y, BoardAbstractMoveData *move_data) { int x_temp; int y_temp; int num_characters_eaten; assert (move_data); num_characters_eaten = game_parse_point (GAME_AMAZONS, board_width, board_height, move_string, &x_temp, &y_temp); if (num_characters_eaten > 0 && move_string[num_characters_eaten] == '-') { const char *pointer = move_string + num_characters_eaten + 1; move_data->amazons.from.x = x_temp; move_data->amazons.from.y = y_temp; num_characters_eaten = game_parse_point (GAME_AMAZONS, board_width, board_height, pointer, x, y); if (num_characters_eaten > 0 && (pointer[num_characters_eaten] == '-' || pointer[num_characters_eaten] == '/' || pointer[num_characters_eaten] == 'x')) { pointer += num_characters_eaten + 1; num_characters_eaten = game_parse_point (GAME_AMAZONS, board_width, board_height, pointer, &x_temp, &y_temp); if (num_characters_eaten) { move_data->amazons.shoot_arrow_to.x = x_temp; move_data->amazons.shoot_arrow_to.y = y_temp; return (pointer - move_string) + num_characters_eaten; } } } return 0; } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/board/board.c0000644000175000017500000007607510376423647014642 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003 Paul Pogonyshev. * * Copyright (C) 2004 Paul Pogonyshev and Martin Holters. * * Copyright (C) 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "board-internals.h" #include "game-info.h" #include "utils.h" #include #include #ifdef HAVE_MEMORY_H #include #endif #define CHANGE_STACK_SIZE_INCREMENT BOARD_MAX_POSITIONS static void clear_board_grid (Board *board); static void ensure_change_stack_space (Board *board, int num_entries); const int delta[8] = { SOUTH (0), WEST (0), NORTH (0), EAST (0), SOUTH (WEST (0)), NORTH (WEST (0)), NORTH (EAST (0)), SOUTH (EAST (0)) }; /* Dynamically allocate a Board structure for specified game and with * specified dimensions. The board is cleared. */ Board * board_new (Game game, int width, int height) { Board *board = utils_malloc (sizeof (Board)); int move_stack_bytes = (((int) (width * height * game_info[game].relative_num_moves_per_game)) * game_info[game].stack_entry_size); assert (game >= FIRST_GAME && GAME_IS_SUPPORTED (game)); assert (BOARD_MIN_WIDTH <= width && width <= BOARD_MAX_WIDTH); assert (BOARD_MIN_HEIGHT <= height && height <= BOARD_MAX_HEIGHT); board->game = game; board->width = width; board->height = height; board->is_legal_move = game_info[game].is_legal_move; board->play_move = game_info[game].play_move; board->undo = game_info[game].undo; clear_board_grid (board); if (game_info[game].reset_game_data) game_info[game].reset_game_data (board, 1); board->move_number = 0; board->move_stack = utils_malloc (move_stack_bytes); board->move_stack_pointer = board->move_stack; board->move_stack_end = (char *) board->move_stack + move_stack_bytes; board->change_stack = utils_malloc (width * height * sizeof (BoardChangeStackEntry)); board->change_stack_pointer = board->change_stack; board->change_stack_end = (board->change_stack + width * height); return board; } /* Free a previously allocated Board structure and its stacks. */ void board_delete (Board *board) { assert (board); utils_free (board->move_stack); utils_free (board->change_stack); utils_free (board); } /* Duplicate given board, but don't copy the stacks. The stacks of * the copy will be empty. */ Board * board_duplicate_without_stacks (const Board *board) { Board *board_copy; int x; int y; int pos; assert (board); board_copy = board_new (board->game, board->width, board->height); board_copy->move_number = board->move_number; for (y = 0, pos = POSITION (0, 0); y < board->height; y++) { for (x = 0; x < board->width; x++, pos++) board_copy->grid[pos] = board->grid[pos]; pos += BOARD_MAX_WIDTH + 1 - board->width; } if (board->game == GAME_GO) memcpy (&board_copy->data.go, &board->data.go, sizeof (GoBoardData)); return board_copy; } /* Set board dimensions to specified values and clear the board as * needed. This may include clearing board's grid, resetting * game-specific data (e.g. ko state for Go) and reallocating board * stacks (to save memory). Board stacks will be empty regardless of * whether they were reallocated. */ void board_set_parameters (Board *board, Game game, int width, int height) { int move_stack_bytes = (((int) (width * height * game_info[game].relative_num_moves_per_game)) * game_info[game].stack_entry_size); int need_full_reset = 1; assert (board); assert (game >= FIRST_GAME && GAME_IS_SUPPORTED (game)); assert (BOARD_MIN_WIDTH <= width && width <= BOARD_MAX_WIDTH); assert (BOARD_MIN_HEIGHT <= height && height <= BOARD_MAX_HEIGHT); if (board->width != width || board->height != height || board->move_stack_pointer != board->move_stack) { board->width = width; board->height = height; clear_board_grid (board); } else if (board->game != game) { board->game = game; board->is_legal_move = game_info[game].is_legal_move; board->play_move = game_info[game].play_move; board->undo = game_info[game].undo; } else need_full_reset = 0; if (game_info[game].reset_game_data) game_info[game].reset_game_data (board, need_full_reset); board->move_number = 0; if ((char *) board->move_stack_end - (char *) board->move_stack != move_stack_bytes) { board->move_stack = utils_realloc (board->move_stack, move_stack_bytes); board->move_stack_end = ((char *) board->move_stack + move_stack_bytes); } board->move_stack_pointer = board->move_stack; if (board->change_stack_end - board->change_stack != width * height) { board->change_stack = utils_realloc (board->change_stack, (width * height * sizeof (BoardChangeStackEntry))); board->change_stack_end = board->change_stack + width * height; } board->change_stack_pointer = board->change_stack; } static void clear_board_grid (Board *board) { char *grid; int x; int y; int pos; grid = board->grid; pos = 0; for (x = -1; x <= board->width; x++) grid[pos++] = OFF_GRID; for (y = 0; y < board->height; y++) { pos += BOARD_MAX_WIDTH - 1 - board->width; grid[pos++] = OFF_GRID; for (x = 0; x < board->width; x++) grid[pos++] = EMPTY; grid[pos++] = OFF_GRID; } pos += BOARD_MAX_WIDTH - 1 - board->width; for (x = -1; x <= board->width; x++) grid[pos++] = OFF_GRID; } /* Normally color to play is alternating. However, in some games * (i.e. Reversi) there are situations where one of the players has to * skip his move. Also, changing board state by adding/removing * pieces can lead to situation where one of the players doesn't have * a legal move. Then it's logical to let the other to take his turn. * Finally, if neither of the player has a legal move, this function * returns EMPTY. * * Note that pass is a legal move in Go, so this function just returns * `color' if the game is Go. */ int board_adjust_color_to_play (const Board *board, BoardRuleSet rule_set, int color) { assert (board); assert (rule_set >= FIRST_RULE_SET); if (!IS_STONE (color)) { assert (color == EMPTY); color = game_info[board->game].color_to_play_first; } if (game_info[board->game].adjust_color_to_play) { color = game_info[board->game].adjust_color_to_play (board, rule_set, color); } return color; } /* Determine if the game played on a given board is over. Parameter * `color_to_play' must be adjusted with board_adjust_color_to_play(). */ int board_is_game_over (const Board *board, BoardRuleSet rule_set, int color_to_play) { assert (board); assert (rule_set >= FIRST_RULE_SET); if (color_to_play == EMPTY) return 1; assert (IS_STONE (color_to_play)); if (game_info[board->game].is_game_over == NULL) return 0; return game_info[board->game].is_game_over (board, rule_set, color_to_play); } /* Determine if a move is legal according to specified rules. */ inline int board_is_legal_move (const Board *board, BoardRuleSet rule_set, int color, ...) { va_list move; int result; assert (board); assert (rule_set >= FIRST_RULE_SET); assert (IS_STONE (color)); va_start (move, color); result = board->is_legal_move (board, rule_set, color, move); va_end (move); return result; } /* Play the specified move on the given board. */ inline void board_play_move (Board *board, int color, ...) { va_list move; assert (board); assert (IS_STONE (color)); #if BOARD_VALIDATION_LEVEL == 2 if (board->move_stack_pointer == board->move_stack_end) board_increase_move_stack_size (board); memcpy (((BoardStackEntry *) board->move_stack_pointer).grid_copy, board->grid, BOARD_GRID_SIZE * sizeof (char)); #endif va_start (move, color); board->play_move (board, color, move); va_end (move); #if BOARD_VALIDATION_LEVEL > 0 board_validate (board); #endif } /* Apply changes (adding/removing of stones) on board. Unused change * list pointers can be set to NULL. */ void board_apply_changes (Board *board, const BoardPositionList *const change_lists[NUM_ON_GRID_VALUES]) { int color; int num_changes; assert (board); assert (!change_lists[SPECIAL_ON_GRID_VALUE] || board->game == GAME_AMAZONS); #if BOARD_VALIDATION_LEVEL == 2 if (board->move_stack_pointer == board->move_stack_end) board_increase_move_stack_size (board); memcpy (((BoardStackEntry *) board->move_stack_pointer).grid_copy, board->grid, BOARD_GRID_SIZE * sizeof (char)); #endif num_changes = 0; for (color = 0; color < NUM_ON_GRID_VALUES; color++) { if (change_lists[color]) num_changes += change_lists[color]->num_positions; } assert (num_changes > 0); ensure_change_stack_space (board, num_changes); for (color = 0; color < NUM_ON_GRID_VALUES; color++) { if (change_lists[color]) { int k; for (k = 0; k < change_lists[color]->num_positions; k++) { int pos = change_lists[color]->positions[k]; board->change_stack_pointer->position = pos; board->change_stack_pointer->contents = board->grid[pos]; board->change_stack_pointer++; board->grid[pos] = color; } } } game_info[board->game].apply_changes (board, num_changes); #if BOARD_VALIDATION_LEVEL > 0 board_validate (board); #endif } /* Add a dummy stack entry that can be removed later with * board_undo(). This can serve two purposes: not caring about * whether board_undo() should be called and providing a simple way of * tracking unexpectedly changing move number (i.e. with MN[] SGF * property that doesn't correspond a real move). */ inline void board_add_dummy_move_entry (Board *board) { assert (board); #if BOARD_VALIDATION_LEVEL == 2 if (board->move_stack_pointer == board->move_stack_end) board_increase_move_stack_size (board); memcpy (((BoardStackEntry *) board->move_stack_pointer).grid_copy, board->grid, BOARD_GRID_SIZE * sizeof (char)); #endif game_info[board->game].add_dummy_move_entry (board); } /* Undo a number of previously played moves and/or sets of board * changes. If not moves or changes are in the stack yet, return * zero. */ inline int board_undo (Board *board, int num_undos) { int k; assert (board); assert (((char *) board->move_stack_pointer - (num_undos * game_info[board->game].stack_entry_size)) >= (char *) board->move_stack); for (k = 0; k < num_undos; k++) board->undo (board); #if BOARD_VALIDATION_LEVEL > 0 board_validate (board); #endif #if BOARD_VALIDATION_LEVEL == 2 { const char * grid_copy = ((BoardStackEntry *) board->move_stack_pointer).grid_copy; int x; int y; for (y = 0; y < board->height; y++) { for (x = 0; x < board->width; x++) assert (board->grid[POSITION (x, y)] == grid_copy[POSITION (x, y)]); } } #endif return 1; } int board_get_move_number (const Board *board, int num_moves_backward) { assert (board); assert (num_moves_backward >= 0); assert (((char *) board->move_stack_pointer - (num_moves_backward * game_info[board->game].stack_entry_size)) >= (char *) board->move_stack); if (num_moves_backward == 0) return board->move_number; else { const BoardStackEntry *stack_entry = ((const BoardStackEntry *) ((const char *) board->move_stack_pointer - (num_moves_backward * game_info[board->game].stack_entry_size))); return stack_entry->move_number; } } inline void board_undo_changes (Board *board, int num_changes) { int k; for (k = 0; k < num_changes; k++) { board->change_stack_pointer--; board->grid[board->change_stack_pointer->position] = board->change_stack_pointer->contents; } } /* Allocate an entry on stack. The duty of the function is to * reallocate the stack if there is no more space in it. It also * saves boards' grid on heap if heavy board debugging is on. */ void board_increase_move_stack_size (Board *board) { int stack_bytes_increment = (((int) (board->width * board->height * 0.5 * game_info[board->game].relative_num_moves_per_game)) * game_info[board->game].stack_entry_size); int new_stack_bytes = (((char *) board->move_stack_end - (char *) board->move_stack) + stack_bytes_increment); board->move_stack = utils_realloc (board->move_stack, new_stack_bytes); board->move_stack_end = (char *) board->move_stack + new_stack_bytes; board->move_stack_pointer = ((char *) board->move_stack_end - stack_bytes_increment); } static void ensure_change_stack_space (Board *board, int num_entries) { if (board->change_stack_pointer + num_entries > board->change_stack_end) { int size_increment = ((1 + (num_entries - 1) / CHANGE_STACK_SIZE_INCREMENT) * CHANGE_STACK_SIZE_INCREMENT); int new_stack_size = (board->change_stack_end - board->change_stack + size_increment); board->change_stack = utils_realloc (board->change_stack, new_stack_size * sizeof (BoardChangeStackEntry)); board->change_stack_end = board->change_stack + new_stack_size; board->change_stack_pointer = board->change_stack_end - size_increment; } } int determine_position_delta (int delta_x, int delta_y) { if (delta_x > 0) { if (delta_y == delta_x) return SOUTH (EAST (0)); else if (delta_y == -delta_x) return NORTH (EAST (0)); else if (delta_y == 0) return EAST (0); } else if (delta_x < 0) { if (delta_y == delta_x) return NORTH (WEST (0)); else if (delta_y == -delta_x) return SOUTH (WEST (0)); else if (delta_y == 0) return WEST (0); } else { if (delta_y > 0) return SOUTH (0); else if (delta_y < 0) return NORTH (0); } return 0; } /* Dump the contents of given board's grid to stderr. */ inline void board_dump (const Board *board) { assert (board); game_info[board->game].dump_board (board); } inline void board_validate (const Board *board) { assert (board); game_info[board->game].validate_board (board); } BoardPositionList * board_position_list_new (const int *positions, int num_positions) { BoardPositionList *list; assert (0 <= num_positions && num_positions < BOARD_MAX_POSITIONS); list = utils_malloc (sizeof (BoardPositionList) - (BOARD_MAX_POSITIONS - num_positions) * sizeof (int)); list->num_positions = num_positions; memcpy (list->positions, positions, num_positions * sizeof (int)); return list; } BoardPositionList * board_position_list_new_empty (int num_positions) { BoardPositionList *list; assert (0 <= num_positions && num_positions < BOARD_MAX_POSITIONS); list = utils_malloc (sizeof (BoardPositionList) - (BOARD_MAX_POSITIONS - num_positions) * sizeof (int)); list->num_positions = num_positions; return list; } void board_position_list_sort (BoardPositionList *list) { assert (list); if (list->num_positions > 1) { qsort (list->positions, list->num_positions, sizeof (int), utils_compare_ints); } } /* Position lists are always stored sorted in ascending order of * positions. This is essential in the following functions and also * for SGF writer. */ BoardPositionList* board_position_list_union (const BoardPositionList *list1, const BoardPositionList *list2) { int i; int j; int k; BoardPositionList *dest; assert (list1); assert (list2); dest = board_position_list_new_empty (list1->num_positions + list2->num_positions); for (i = 0, j = 0, k = 0; i < list1->num_positions && j < list2->num_positions;) { if (list1->positions[i] > list2->positions[j]) dest->positions[k++] = list2->positions[j++]; else if (list1->positions[i] < list2->positions[j]) dest->positions[k++] = list1->positions[i++]; else { /* Same element in both source lists. */ dest->positions[k++] = list1->positions[i++]; j++; } } /* One or both of source lists are out. Copy the tail of the other * list. */ if (i < list1->num_positions) { memcpy (dest->positions + k, list1->positions + i, (list1->num_positions - i) * sizeof (int)); k += list1->num_positions - i; } else if (j < list2->num_positions) { memcpy (dest->positions + k, list2->positions + j, (list2->num_positions - j) * sizeof (int)); k += list2->num_positions - j; } dest->num_positions = k; return utils_realloc (dest, (sizeof (BoardPositionList) - (BOARD_MAX_POSITIONS - k) * sizeof (int))); } /* Add a single position to the `list', without creating a new * position list. It is OK if the position is already there. Since * this function may reallocate the list, you need to assign return * value back to your pointer. * * It is also possible to pass NULL as `list'. In this case, the * function returns a newly allocated list with just one position in * it. In other words, * * list = board_position_list_add_position (list, pos); * * will do The Right Thing whether `list' is NULL or not. */ BoardPositionList * board_position_list_add_position (BoardPositionList *list, int pos) { if (!list) return board_position_list_new (&pos, 1); if (board_position_list_find_position (list, pos) == -1) { int k; list->num_positions++; list = utils_realloc (list, (sizeof (BoardPositionList) - ((BOARD_MAX_POSITIONS - list->num_positions) * sizeof (int)))); /* Unfortunately, bsearch() doesn't allow to find where to insert * the element if it is missing. */ for (k = list->num_positions; --k > 0 && list->positions[k - 1] > pos;) list->positions[k] = list->positions[k - 1]; list->positions[k] = pos; } return list; } /* Determine if two position lists are equal, i.e. contain identical * positions. */ int board_position_lists_are_equal (const BoardPositionList *first_list, const BoardPositionList *second_list) { int k; assert (first_list); assert (second_list); if (first_list->num_positions != second_list->num_positions) return 0; for (k = 0; k < first_list->num_positions; k++) { if (first_list->positions[k] != second_list->positions[k]) return 0; } return 1; } /* Determine if two position have at least one common position. */ int board_position_lists_overlap (const BoardPositionList *first_list, const BoardPositionList *second_list) { int i; int j; assert (first_list); assert (second_list); for (i = 0, j = 0; i < first_list->num_positions && j < second_list->num_positions;) { if (first_list->positions[i] < second_list->positions[j]) i++; else if (first_list->positions[i] > second_list->positions[j]) j++; else return 1; } return 0; } /* Find given position in list. If position is found, return its * index or -1 otherwise. The index may be useful for locating * associated data in array. */ int board_position_list_find_position (const BoardPositionList *list, int pos) { assert (list); if (list->num_positions > 1) { int *position_pointer = bsearch (&pos, list->positions, list->num_positions, sizeof (int), utils_compare_ints); return position_pointer ? position_pointer - list->positions : -1; } return list->num_positions == 1 && list->positions[0] == pos ? 0 : -1; } void board_position_list_mark_on_grid (const BoardPositionList *list, char grid[BOARD_GRID_SIZE], char value) { int k; assert (list); assert (grid); for (k = 0; k < list->num_positions; k++) grid[list->positions[k]] = value; } Game game_from_game_name (const char *game_name, int case_sensitive) { Game game; assert (game_name); for (game = FIRST_GAME; game <= LAST_GAME; game++) { if (case_sensitive ? strcmp (game_name, game_info[game].name) == 0 : strcasecmp (game_name, game_info[game].name) == 0) return game; } return GAME_INVALID; } void game_format_point (Game game, int board_width, int board_height, StringBuffer *buffer, int x, int y) { assert (game >= FIRST_GAME && GAME_IS_SUPPORTED (game)); assert (BOARD_MIN_WIDTH <= board_width && board_width <= BOARD_MAX_WIDTH); assert (BOARD_MIN_HEIGHT <= board_height && board_height <= BOARD_MAX_HEIGHT); assert (buffer); assert (ON_SIZED_GRID (board_width, board_height, x, y)); string_buffer_cprintf (buffer, "%c%d", game_info[game].horizontal_coordinates[x], (game_info[game].reversed_vertical_coordinates ? board_height - y : y + 1)); } void game_format_position_list (Game game, int board_width, int board_height, StringBuffer *buffer, const BoardPositionList *position_list) { int k; assert (position_list); for (k = 0; k < position_list->num_positions; k++) { int pos = position_list->positions[k]; if (k > 0) string_buffer_add_character (buffer, ' '); game_format_point (game, board_width, board_height, buffer, POSITION_X (pos), POSITION_Y (pos)); } } void game_format_move (Game game, int board_width, int board_height, StringBuffer *buffer, ...) { va_list move; assert (game >= FIRST_GAME && GAME_IS_SUPPORTED (game)); va_start (move, buffer); game_info[game].format_move (board_width, board_height, buffer, move); va_end (move); } void game_format_move_valist (Game game, int board_width, int board_height, StringBuffer *buffer, va_list move) { assert (game >= FIRST_GAME && GAME_IS_SUPPORTED (game)); game_info[game].format_move (board_width, board_height, buffer, move); } void game_format_score_difference (Game game, StringBuffer *buffer, double score) { /* We may want to distinguish based on game later. */ UNUSED (game); assert (game >= FIRST_GAME && GAME_IS_SUPPORTED (game)); if (fabs (score - floor (score + 0.005)) >= 0.005) { int num_digits = ((score + 0.005) * 10 - floor ((score + 0.005) * 10) >= 0.1 ? 2 : 1); if (score > 0.0) { /* TRANSLATORS: This is only used for non-integral scores. You should also add translation of `points' if it is required by your language. */ string_buffer_printf (buffer, _("Black wins by %.*f"), num_digits, score); } else { /* TRANSLATORS: This is only used for non-integral scores. You should also add translation of `points' if it is required by your language. */ string_buffer_printf (buffer, _("White wins by %.*f"), num_digits, -score); } } else { int integral_score = (int) floor (score + 0.005); if (integral_score > 0) { /* TRANSLATORS: You should add translation of `points' if it is required by your language. */ string_buffer_printf (buffer, ngettext ("Black wins by %d", "Black wins by %d", integral_score), integral_score); } else { /* TRANSLATORS: You should add translation of `points' if it is required by your language. */ string_buffer_printf (buffer, ngettext ("White wins by %d", "White wins by %d", -integral_score), -integral_score); } } } int game_parse_point (Game game, int board_width, int board_height, const char *point_string, int *x, int *y) { int x_temp; char x_normalized; assert (game >= FIRST_GAME && GAME_IS_SUPPORTED (game)); assert (BOARD_MIN_WIDTH <= board_width && board_width <= BOARD_MAX_WIDTH); assert (BOARD_MIN_HEIGHT <= board_height && board_height <= BOARD_MAX_HEIGHT); assert (point_string); assert (x); assert (y); if ('A' <= *point_string && *point_string < 'Z') x_temp = *point_string - 'A'; else if ('a' <= *point_string && *point_string < 'z') x_temp = *point_string - 'a'; else return 0; x_normalized = game_info[game].horizontal_coordinates[0] + x_temp; if (x_temp < board_width && game_info[game].horizontal_coordinates[x_temp] == x_normalized) *x = x_temp; else if (x_temp - 1 < board_width && (game_info[game].horizontal_coordinates[x_temp - 1] == x_normalized)) *x = x_temp - 1; else return 0; if ('1' <= *(point_string + 1) && *(point_string + 1) <= '9') { int num_characters_eaten; sscanf (point_string + 1, "%d%n", y, &num_characters_eaten); if (*y <= board_height) { if (game_info[game].reversed_vertical_coordinates) *y = board_height - *y; else (*y)--; return 1 + num_characters_eaten; } } return 0; } BoardPositionList * game_parse_position_list (Game game, int board_width, int board_height, const char *positions_string) { assert (positions_string); if (*positions_string) { BoardPositionList *position_list; int num_positions = 0; char present_positions[BOARD_GRID_SIZE]; int x; int y; int k; int pos; for (y = 0, pos = POSITION (0, 0); y < board_height; y++) { for (x = 0; x < board_width; x++, pos++) present_positions[pos] = 0; pos += BOARD_MAX_WIDTH + 1 - board_width; } do { int num_characters_eaten = game_parse_point (game, board_width, board_height, positions_string, &x, &y); if (!num_characters_eaten) return NULL; pos = POSITION (x, y); if (present_positions[pos]) return NULL; present_positions[pos] = 1; num_positions++; positions_string += num_characters_eaten; if (*positions_string == ' ') positions_string++; } while (*positions_string); position_list = board_position_list_new_empty (num_positions); for (y = 0, pos = POSITION (0, 0), k = 0; k < num_positions; y++) { for (x = 0; x < board_width; x++, pos++) { if (present_positions[pos]) position_list->positions[k++] = pos; } pos += BOARD_MAX_WIDTH + 1 - board_width; } return position_list; } return NULL; } int game_parse_move (Game game, int board_width, int board_height, const char *move_string, int *x, int *y, BoardAbstractMoveData *move_data) { assert (game >= FIRST_GAME && GAME_IS_SUPPORTED (game)); assert (BOARD_MIN_WIDTH <= board_width && board_width <= BOARD_MAX_WIDTH); assert (BOARD_MIN_HEIGHT <= board_height && board_height <= BOARD_MAX_HEIGHT); assert (move_string); assert (x); assert (y); return game_info[game].parse_move (board_width, board_height, move_string, x, y, move_data); } /* Determine default setup for the given game and board dimensions. * If the default setup is not empty, nonzero is returned and zero * otherwise. */ inline int game_get_default_setup (Game game, int width, int height, BoardPositionList **black_stones, BoardPositionList **white_stones) { assert (game >= FIRST_GAME && GAME_IS_SUPPORTED (game)); assert (BOARD_MIN_WIDTH <= width && width <= BOARD_MAX_WIDTH); assert (BOARD_MIN_HEIGHT <= height && height <= BOARD_MAX_HEIGHT); assert (black_stones); assert (white_stones); return (game_info[game].get_default_setup && game_info[game].get_default_setup (width, height, black_stones, white_stones)); } #define DO_FILL_GRID(grid, width, height, value) \ do { \ int x; \ int y; \ int pos; \ assert (grid); \ assert (BOARD_MIN_WIDTH <= (width) \ && (width) <= BOARD_MAX_WIDTH); \ assert (BOARD_MIN_HEIGHT <= (height) \ && (height) <= BOARD_MAX_HEIGHT); \ for (y = 0, pos = POSITION (0, 0); y < (height); y++) { \ for (x = 0; x < (width); x++, pos++) \ (grid) [pos] = (value); \ pos += BOARD_MAX_WIDTH + 1 - (width); \ } \ } while (0) void grid_fill (char grid[BOARD_GRID_SIZE], int width, int height, char value) { DO_FILL_GRID (grid, width, height, value); } void int_grid_fill (int grid[BOARD_GRID_SIZE], int width, int height, int value) { DO_FILL_GRID (grid, width, height, value); } void pointer_grid_fill (void *grid[BOARD_GRID_SIZE], int width, int height, void *value) { DO_FILL_GRID (grid, width, height, value); } #define DO_COPY_GRID(destination, source, type, width, height) \ do { \ int pos; \ assert (destination); \ assert (source); \ assert (BOARD_MIN_WIDTH <= (width) \ && (width) <= BOARD_MAX_WIDTH); \ assert (BOARD_MIN_HEIGHT <= (height) \ && (height) <= BOARD_MAX_HEIGHT); \ for (pos = POSITION (0, 0); pos < POSITION (0, (height)); \ pos = SOUTH (pos)) { \ memcpy ((destination) + pos, (source) + pos, \ (width) * sizeof (type)); \ } \ } while (0) void grid_copy (char destination[BOARD_GRID_SIZE], const char source[BOARD_GRID_SIZE], int width, int height) { DO_COPY_GRID ((destination), (source), char, (width), (height)); } void int_grid_copy (int destination[BOARD_GRID_SIZE], const int source[BOARD_GRID_SIZE], int width, int height) { DO_COPY_GRID ((destination), (source), int, (width), (height)); } void pointer_grid_copy (void *destination[BOARD_GRID_SIZE], const void *source[BOARD_GRID_SIZE], int width, int height) { DO_COPY_GRID ((destination), (source), const void *, (width), (height)); } int grid_diff (const char grid1[BOARD_GRID_SIZE], const char grid2[BOARD_GRID_SIZE], int width, int height, BoardPositionList *difference_lists[NUM_ON_GRID_VALUES]) { int k; int x; int y; int pos; int num_positions[NUM_ON_GRID_VALUES]; int positions[NUM_ON_GRID_VALUES][BOARD_MAX_POSITIONS]; int have_difference = 0; assert (grid1); assert (grid2); assert (BOARD_MIN_WIDTH <= (width) && (width) <= BOARD_MAX_WIDTH); assert (BOARD_MIN_HEIGHT <= (height) && (height) <= BOARD_MAX_HEIGHT); for (k = 0; k < NUM_ON_GRID_VALUES; k++) num_positions[k] = 0; for (y = 0, pos = POSITION (0, 0); y < height; y++) { for (x = 0; x < width; x++, pos++) { int new_contents = grid2[pos]; if (new_contents != grid1[pos]) { assert (0 <= new_contents && new_contents < NUM_ON_GRID_VALUES); positions[new_contents][num_positions[new_contents]++] = pos; } } pos += BOARD_MAX_WIDTH + 1 - width; } for (k = 0; k < NUM_ON_GRID_VALUES; k++) { if (num_positions[k] > 0) { difference_lists[k] = board_position_list_new (positions[k], num_positions[k]); have_difference = 1; } else difference_lists[k] = NULL; } return have_difference; } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/board/go.c0000644000175000017500000012556710376424622014153 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * \ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "go.h" #include "board-internals.h" #include "utils.h" #include #include #include #ifdef HAVE_MEMORY_H #include #endif #define LIBERTY(grid, pos) ((grid) [pos] == EMPTY) #define STRING_NUMBER(board, pos) \ ((board)->data.go.string_number[pos]) #define LIBERTIES(board, pos) \ ((board)->data.go.liberties[STRING_NUMBER ((board), (pos))]) #define MARK_POSITION(board, pos) \ ((board)->data.go.marked_positions[pos] \ = (board)->data.go.position_mark) #define UNMARKED_POSITION(board, pos) \ ((board)->data.go.marked_positions[pos] \ != (board)->data.go.position_mark) #define MARK_STRING(board, pos) \ ((board)->data.go.marked_strings[STRING_NUMBER ((board), (pos))] \ = (board)->data.go.string_mark) #define UNMARKED_STRING(board, pos) \ ((board)->data.go.marked_strings[STRING_NUMBER ((board), (pos))] \ != (board)->data.go.string_mark) enum { ALLY = EMPTY + 1, OPPONENT, CAPTURE }; enum { NORMAL_MOVE = PASS_MOVE + 1, POSITION_CHANGE, DUMMY_MOVE_ENTRY }; static int is_suicide (const Board *board, int color, int pos); static void rebuild_strings (Board *board); static void do_play_move (Board *board, int color, int pos); static void do_play_over_own_stone (Board *board, int pos); static void do_play_over_enemy_stone (Board *board, int pos); static int join_strings (Board *board, int color, int pos, int new_liberties, int *allies, int num_allies); static int remove_string (Board *board, int pos); static int change_string_number (Board *board, int pos, int string_number); static void reconstruct_string (Board *board, int color, int pos, int single_liberty); static int allocate_string (Board *board); void go_reset_game_data (Board *board, int forced_reset) { board->data.go.ko_master = EMPTY; board->data.go.prisoners[BLACK_INDEX] = 0; board->data.go.prisoners[WHITE_INDEX] = 0; board->data.go.last_string_number = -1; if (forced_reset) { int k; for (k = 0; k < GO_STRING_RING_SIZE; k++) board->data.go.liberties[k] = -1; } if (forced_reset || board->data.go.position_mark != 0) { int x; int y; int pos; board->data.go.position_mark = 0; for (y = -1, pos = POSITION (-1, -1); y <= board->height; y++) { for (x = -1; x <= board->width; x++, pos++) board->data.go.marked_positions[pos] = 0; pos += BOARD_MAX_WIDTH + 1 - (1 + board->width + 1); } } if (forced_reset || board->data.go.string_mark != 0) { board->data.go.string_mark = 0; memset (board->data.go.marked_strings, 0, sizeof board->data.go.marked_strings); } } int go_is_game_over (const Board *board, BoardRuleSet rule_set, int color_to_play) { GoMoveStackEntry *stack_entry = ((GoMoveStackEntry *) board->move_stack_pointer); UNUSED (rule_set); UNUSED (color_to_play); while (--stack_entry > (GoMoveStackEntry *) board->move_stack) { if (stack_entry->type == PASS_MOVE) break; if (stack_entry->type != DUMMY_MOVE_ENTRY) return 0; } if (stack_entry > (GoMoveStackEntry *) board->move_stack) { int last_pass_color = stack_entry->suicide_or_pass_color; while (--stack_entry >= (GoMoveStackEntry *) board->move_stack) { if (stack_entry->type == PASS_MOVE) { return (stack_entry->suicide_or_pass_color == OTHER_COLOR (last_pass_color)); } if (stack_entry->type != DUMMY_MOVE_ENTRY) break; } } return 0; } /* Determine if a move is suicide. This is rule set independent. */ static int is_suicide (const Board *board, int color, int pos) { const char *grid = board->grid; int k; int single_liberty = (grid[pos] == EMPTY ? 1 : 0); for (k = 0; k < 4; k++) { int neighbor = pos + delta[k]; if (LIBERTY (grid, neighbor) || (ON_GRID (grid, neighbor) && ((grid[neighbor] == color) ^ (LIBERTIES (board, neighbor) == single_liberty)))) return 0; } return 1; } /* Determine if a move is legal according to specified rule set. This * typically involves checks for ko rule violation, disallowed suicide * moves etc. */ int go_is_legal_move (const Board *board, BoardRuleSet rule_set, int color, va_list move) { int x = va_arg (move, int); int y = va_arg (move, int); int pos = POSITION (x, y); assert (rule_set < NUM_GO_RULE_SETS); if (rule_set == GO_RULE_SET_SGF) return 1; if (pos != PASS_MOVE) { assert (ON_BOARD (board, x, y)); /* Determine if a move is legal in terms of default rule set. * It is illegal to violate the ko rule or play suicides. */ return (board->grid[pos] == EMPTY && (color != OTHER_COLOR (board->data.go.ko_master) || pos != board->data.go.ko_position) && !is_suicide (board, color, pos)); } return 1; } void go_play_move (Board *board, int color, va_list move) { GoMoveStackEntry *stack_entry; int x = va_arg (move, int); int y = va_arg (move, int); int pos = POSITION (x, y); if (pos != PASS_MOVE) { assert (ON_BOARD (board, x, y)); if (board->grid[pos] == EMPTY) do_play_move (board, color, pos); else if (board->grid[pos] == color) do_play_over_own_stone (board, pos); else do_play_over_enemy_stone (board, pos); } else { stack_entry = ALLOCATE_GO_MOVE_STACK_ENTRY (board); stack_entry->type = PASS_MOVE; stack_entry->suicide_or_pass_color = color; stack_entry->ko_master = board->data.go.ko_master; stack_entry->ko_position = board->data.go.ko_position; board->data.go.ko_master = EMPTY; stack_entry->common.move_number = board->move_number++; } } void go_apply_changes (Board *board, int num_changes) { GoMoveStackEntry *stack_entry = ALLOCATE_GO_MOVE_STACK_ENTRY (board); stack_entry->type = POSITION_CHANGE; stack_entry->num.changes = num_changes; stack_entry->ko_master = board->data.go.ko_master; stack_entry->ko_position = board->data.go.ko_position; stack_entry->common.move_number = board->move_number; board->data.go.ko_master = EMPTY; rebuild_strings (board); } void go_add_dummy_move_entry (Board *board) { GoMoveStackEntry *stack_entry = ALLOCATE_GO_MOVE_STACK_ENTRY (board); /* Ko data is not changed, but go_undo() restores it anyway, so we * need to initialize stack's copy of it. */ stack_entry->type = DUMMY_MOVE_ENTRY; stack_entry->ko_master = board->data.go.ko_master; stack_entry->ko_position = board->data.go.ko_position; stack_entry->common.move_number = board->move_number; } /* Rebuild all board strings from scratch. Used after complex * position changes that are not handled incrementally. */ static void rebuild_strings (Board *board) { int pos; int string_number = 0; for (pos = POSITION (0, 0); ON_GRID (board->grid, pos); pos += (BOARD_MAX_WIDTH + 1) - board->width) { for (; ON_GRID (board->grid, pos); pos++) STRING_NUMBER (board, pos) = -1; } for (pos = POSITION (0, 0); ON_GRID (board->grid, pos); pos += (BOARD_MAX_WIDTH + 1) - board->width) { for (; ON_GRID (board->grid, pos); pos++) { if (board->grid[pos] != EMPTY && STRING_NUMBER (board, pos) == -1) { board->data.go.position_mark++; board->data.go.liberties[string_number] = change_string_number (board, pos, string_number); string_number++; } } } board->data.go.last_string_number = string_number - 1; while (string_number < GO_STRING_RING_SIZE) board->data.go.liberties[string_number++] = -1; #if BOARD_VALIDATION_LEVEL > 0 go_validate_board (board); #endif } /* Do the real job of go_play_move() when the move position is empty * (most of the cases). */ static void do_play_move (Board *board, int color, int pos) { char *grid = board->grid; int k; int direct_liberties = 0; int move_is_suicide = 1; int allies[4]; int num_allies = 0; int captures[4]; int num_captures = 0; GoMoveStackEntry *stack_entry = ALLOCATE_GO_MOVE_STACK_ENTRY (board); stack_entry->type = NORMAL_MOVE; stack_entry->contents = EMPTY; stack_entry->position = pos; stack_entry->ko_master = board->data.go.ko_master; stack_entry->ko_position = board->data.go.ko_position; stack_entry->prisoners[BLACK_INDEX] = board->data.go.prisoners[BLACK_INDEX]; stack_entry->prisoners[WHITE_INDEX] = board->data.go.prisoners[WHITE_INDEX]; stack_entry->common.move_number = board->move_number++; board->data.go.position_mark++; board->data.go.string_mark++; for (k = 0; k < 4; k++) { int neighbor = pos + delta[k]; stack_entry->status[k] = EMPTY; if (LIBERTY (grid, neighbor)) { direct_liberties++; MARK_POSITION (board, neighbor); } else if (ON_GRID (grid, neighbor) && UNMARKED_STRING (board, neighbor)) { if (grid[neighbor] == color) { stack_entry->status[k] = ALLY; allies[num_allies++] = neighbor; if (LIBERTIES (board, neighbor) > 1) move_is_suicide = 0; } else { if (LIBERTIES (board, neighbor) > 1) { stack_entry->status[k] = OPPONENT; LIBERTIES (board, neighbor)--; } else { stack_entry->status[k] = CAPTURE; captures[num_captures++] = neighbor; move_is_suicide = 0; } } MARK_STRING (board, neighbor); } } if (!move_is_suicide || direct_liberties > 0) { int captured_stones = 0; stack_entry->num.liberties = join_strings (board, color, pos, direct_liberties, allies, num_allies); for (k = 0; k < num_captures; k++) captured_stones += remove_string (board, captures[k]); if (captured_stones != 1 || direct_liberties > 0 || num_allies > 0) board->data.go.ko_master = EMPTY; else { board->data.go.ko_master = color; board->data.go.ko_position = captures[0]; } board->data.go.prisoners[COLOR_INDEX (color)] += captured_stones; } else { int other = OTHER_COLOR (color); stack_entry->suicide_or_pass_color = color; board->data.go.ko_master = EMPTY; for (k = 0; k < 4; k++) { if (stack_entry->status[k] == OPPONENT) LIBERTIES (board, pos + delta[k])++; } board->data.go.prisoners[COLOR_INDEX (other)]++; for (k = 0; k < num_allies; k++) { board->data.go.prisoners[COLOR_INDEX (other)] += remove_string (board, allies[k]); } } } static void do_play_over_own_stone (Board *board, int pos) { char *grid = board->grid; int k; int color = grid[pos]; int other = OTHER_COLOR (color); int captured_stones = 0; GoMoveStackEntry *stack_entry = ALLOCATE_GO_MOVE_STACK_ENTRY (board); stack_entry->type = NORMAL_MOVE; stack_entry->contents = color; stack_entry->position = pos; stack_entry->num.liberties = LIBERTIES (board, pos); stack_entry->ko_master = board->data.go.ko_master; stack_entry->ko_position = board->data.go.ko_position; stack_entry->prisoners[BLACK_INDEX] = board->data.go.prisoners[BLACK_INDEX]; stack_entry->prisoners[WHITE_INDEX] = board->data.go.prisoners[WHITE_INDEX]; stack_entry->common.move_number = board->move_number++; for (k = 0; k < 4; k++) { int neighbor = pos + delta[k]; stack_entry->status[k] = EMPTY; if (grid[neighbor] == other && LIBERTIES (board, neighbor) == 0) { stack_entry->status[k] = CAPTURE; captured_stones += remove_string (board, neighbor); } } board->data.go.ko_master = EMPTY; if (LIBERTIES (board, pos) > 0) board->data.go.prisoners[COLOR_INDEX (color)] += captured_stones; else { stack_entry->suicide_or_pass_color = color; board->data.go.prisoners[COLOR_INDEX (other)] += remove_string (board, pos); } } static void do_play_over_enemy_stone (Board *board, int pos) { char *grid = board->grid; int other = grid[pos]; int color = OTHER_COLOR (other); int k; int string_number = STRING_NUMBER (board, pos); grid[pos] = EMPTY; board->data.go.string_mark++; for (k = 0; k < 4; k++) { int neighbor = pos + delta[k]; if (grid[neighbor] == other) { if (STRING_NUMBER (board, neighbor) == string_number) { int new_string_number = allocate_string (board); board->data.go.position_mark++; board->data.go.liberties[new_string_number] = change_string_number (board, neighbor, new_string_number); } } else if (grid[neighbor] == color && UNMARKED_STRING (board, neighbor)) { LIBERTIES (board, neighbor)++; MARK_STRING (board, neighbor); } } LIBERTIES (board, pos) = -1; do_play_move (board, color, pos); ((GoMoveStackEntry *) board->move_stack_pointer - 1)->contents = other; #if BOARD_VALIDATION_LEVEL == 2 ((GoMoveStackEntry *) board->move_stack_pointer - 1)->grid_copy[pos] = other; #endif } /* Join several strings together and calculate the number of liberties * of the resulting string. The strings to be joined must be found by * the caller of this function. It also actually plays the move given * by `color' and `pos' parameters on the board. * * Return the number of liberties the resulting string has had before. * This information is used when undoing moves. */ static int join_strings (Board *board, int color, int pos, int new_liberties, int *allies, int num_allies) { char *grid = board->grid; int liberties; int string_number; if (num_allies == 0) { string_number = allocate_string (board); liberties = -1; } else { int k; string_number = STRING_NUMBER (board, allies[0]); liberties = LIBERTIES (board, allies[0]); if (num_allies == 1) { new_liberties = liberties - 1; for (k = 0; k < 4; k++) { int neighbor = pos + delta[k]; if (LIBERTY (grid, neighbor)) { int i; for (i = 0; i < 4; i++) { if (grid[neighbor + delta[i]] == color && STRING_NUMBER (board, neighbor + delta[i]) == string_number) break; } if (i == 4) new_liberties++; } } } else { MARK_POSITION (board, pos); new_liberties += change_string_number (board, allies[0], string_number); for (k = 1; k < num_allies; k++) { LIBERTIES (board, allies[k]) = -1; new_liberties += change_string_number (board, allies[k], string_number); } } } grid[pos] = color; STRING_NUMBER (board, pos) = string_number; board->data.go.liberties[string_number] = new_liberties; return liberties; } /* Remove the given string from the board and recalculate the number * of liberties of each its neighbor. The number of stones removed is * returned. */ static int remove_string (Board *board, int pos) { char *grid = board->grid; int color = grid[pos]; int other = OTHER_COLOR (color); int queue[BOARD_MAX_POSITIONS]; int queue_start = 0; int queue_end = 1; grid[pos] = EMPTY; queue[0] = pos; do { int k; int stone = queue[queue_start++]; board->data.go.string_mark++; for (k = 0; k < 4; k++) { int neighbor = stone + delta[k]; if (grid[neighbor] == other) { if (UNMARKED_STRING (board, neighbor)) { LIBERTIES (board, neighbor)++; MARK_STRING (board, neighbor); } } else if (grid[neighbor] == color) { grid[neighbor] = EMPTY; queue[queue_end++] = neighbor; } } } while (queue_start < queue_end); LIBERTIES (board, pos) = -1; return queue_end; } /* Change the number of given string and return the number of its * unmarked liberties. */ static int change_string_number (Board *board, int pos, int string_number) { const char *grid = board->grid; int color = grid[pos]; int queue[BOARD_MAX_POSITIONS]; int queue_start = 0; int queue_end = 1; int unmarked_liberties = 0; queue[0] = pos; MARK_POSITION (board, pos); do { int stone = queue[queue_start++]; STRING_NUMBER (board, stone) = string_number; /* Profiling shows that this function is by far the most expensive * in the whole Go board code. Therefore, it is the only one that * uses loop unrolling for speedup. */ if (UNMARKED_POSITION (board, SOUTH (stone))) { if (grid[SOUTH (stone)] == color) queue[queue_end++] = SOUTH (stone); else if (LIBERTY (grid, SOUTH (stone))) unmarked_liberties++; MARK_POSITION (board, SOUTH (stone)); } if (UNMARKED_POSITION (board, WEST (stone))) { if (grid[WEST (stone)] == color) queue[queue_end++] = WEST (stone); else if (LIBERTY (grid, WEST (stone))) unmarked_liberties++; MARK_POSITION (board, WEST (stone)); } if (UNMARKED_POSITION (board, NORTH (stone))) { if (grid[NORTH (stone)] == color) queue[queue_end++] = NORTH (stone); else if (LIBERTY (grid, NORTH (stone))) unmarked_liberties++; MARK_POSITION (board, NORTH (stone)); } if (UNMARKED_POSITION (board, EAST (stone))) { if (grid[EAST (stone)] == color) queue[queue_end++] = EAST (stone); else if (LIBERTY (grid, EAST (stone))) unmarked_liberties++; MARK_POSITION (board, EAST (stone)); } } while (queue_start < queue_end); return unmarked_liberties; } void go_undo (Board *board) { GoMoveStackEntry *stack_entry = POP_GO_MOVE_STACK_ENTRY (board); if (stack_entry->type == NORMAL_MOVE) { char *grid = board->grid; int k; int pos = stack_entry->position; int color = grid[pos]; if (color != EMPTY) { int first_ally = 1; int single_liberty = (stack_entry->contents != color ? 1 : 0); grid[pos] = EMPTY; for (k = 0; k < 4; k++) { if (stack_entry->status[k] == ALLY) { if (first_ally) first_ally = 0; else { int string_number = allocate_string (board); board->data.go.position_mark++; board->data.go.liberties[string_number] = change_string_number (board, pos + delta[k], string_number); } } else if (stack_entry->status[k] == OPPONENT) LIBERTIES (board, pos + delta[k])++; } grid[pos] = OFF_GRID; for (k = 0; k < 4; k++) { if (stack_entry->status[k] == CAPTURE) { reconstruct_string (board, OTHER_COLOR (color), pos + delta[k], single_liberty); } } LIBERTIES (board, pos) = stack_entry->num.liberties; grid[pos] = stack_entry->contents; } else { color = stack_entry->suicide_or_pass_color; if (stack_entry->contents != color) { grid[pos] = OFF_GRID; for (k = 0; k < 4; k++) { if (stack_entry->status[k] == ALLY) reconstruct_string (board, color, pos + delta[k], 1); } grid[pos] = stack_entry->contents; } else reconstruct_string (board, color, pos, 0); } if (stack_entry->contents == OTHER_COLOR (color)) { int allies[4]; int num_allies = 0; int direct_liberties = 0; board->data.go.position_mark++; board->data.go.string_mark++; for (k = 0; k < 4; k++) { int neighbor = pos + delta[k]; if (LIBERTY (grid, neighbor)) { direct_liberties++; MARK_POSITION (board, neighbor); } else if (ON_GRID (grid, neighbor) && UNMARKED_STRING (board, neighbor)) { if (grid[neighbor] == color) LIBERTIES (board, neighbor)--; else allies[num_allies++] = neighbor; MARK_STRING (board, neighbor); } } join_strings (board, stack_entry->contents, pos, direct_liberties, allies, num_allies); } board->data.go.prisoners[BLACK_INDEX] = stack_entry->prisoners[BLACK_INDEX]; board->data.go.prisoners[WHITE_INDEX] = stack_entry->prisoners[WHITE_INDEX]; } else if (stack_entry->type == POSITION_CHANGE) { board_undo_changes (board, stack_entry->num.changes); rebuild_strings (board); } board->data.go.ko_master = stack_entry->ko_master; board->data.go.ko_position = stack_entry->ko_position; board->move_number = stack_entry->common.move_number; } /* Reconstruct a string of given color at given position. It takes * all empty intersections linked with `pos' and makes a string in * their place. Liberties of neighbors are properly adjusted. */ static void reconstruct_string (Board *board, int color, int pos, int single_liberty) { char *grid = board->grid; int other = OTHER_COLOR (color); int string_number = allocate_string (board); int queue[BOARD_MAX_POSITIONS]; int queue_start = 0; int queue_end = 1; grid[pos] = color; STRING_NUMBER (board, pos) = string_number; queue[0] = pos; do { int k; int stone = queue[queue_start++]; board->data.go.string_mark++; for (k = 0; k < 4; k++) { int neighbor = stone + delta[k]; if (grid[neighbor] == other) { if (UNMARKED_STRING (board, neighbor)) { LIBERTIES (board, neighbor)--; MARK_STRING (board, neighbor); } } else if (LIBERTY (grid, neighbor)) { grid[neighbor] = color; STRING_NUMBER (board, neighbor) = string_number; queue[queue_end++] = neighbor; } } } while (queue_start < queue_end); LIBERTIES (board, pos) = single_liberty; } /* Allocate a string on the board. Finds the first free string in the * ring and returns its number. */ static int allocate_string (Board *board) { int string_number = board->data.go.last_string_number; do { if (string_number < GO_STRING_RING_SIZE - 1) string_number++; else string_number = 0; } while (board->data.go.liberties[string_number] != -1); board->data.go.last_string_number = string_number; return string_number; } void go_format_move (int board_width, int board_height, StringBuffer *buffer, va_list move) { int x = va_arg (move, int); int y = va_arg (move, int); if (!IS_PASS (x, y)) game_format_point (GAME_GO, board_width, board_height, buffer, x, y); else string_buffer_cat_string (buffer, "pass"); } int go_parse_move (int board_width, int board_height, const char *move_string, int *x, int *y, BoardAbstractMoveData *move_data) { UNUSED (move_data); if (strncasecmp (move_string, "pass", 4) != 0) { return game_parse_point (GAME_GO, board_width, board_height, move_string, x, y); } *x = PASS_X; *y = PASS_Y; return 4; } void go_validate_board (const Board *board) { const char *grid = board->grid; int k; int x; int y; int present_strings[GO_STRING_RING_SIZE]; int liberties[GO_STRING_RING_SIZE]; memset (present_strings, 0, sizeof present_strings); memset (liberties, 0, sizeof liberties); for (y = 0; y < board->height; y++) { for (x = 0; x < board->width; x++) { int pos = POSITION (x, y); if (IS_STONE (grid[pos])) { present_strings[STRING_NUMBER (board, pos)] = 1; for (k = 0; k < 4; k++) { if (grid[pos + delta[k]] == grid[pos]) { assert (STRING_NUMBER (board, pos + delta[k]) == STRING_NUMBER (board, pos)); } } } else { int num_neighbor_strings = 0; int neighbor_strings[4]; assert (grid[pos] == EMPTY); for (k = 0; k < 4; k++) { int neighbor = pos + delta[k]; if (IS_STONE (grid[neighbor])) { int i; int string = STRING_NUMBER (board, neighbor); for (i = 0; i < num_neighbor_strings; i++) { if (string == neighbor_strings[i]) break; } if (i == num_neighbor_strings) { liberties[string]++; neighbor_strings[num_neighbor_strings++] = string; } } } } } } for (k = 0; k < GO_STRING_RING_SIZE; k++) { if (present_strings[k]) assert (board->data.go.liberties[k] == liberties[k]); else assert (board->data.go.liberties[k] == -1); } } void go_dump_board (const Board *board) { static const char contents[NUM_VALID_BOARD_VALUES] = {'.', '@', 'O', '?', '?'}; static const char coordinates[] = " A B C D E F G H J K L M N O P Q R S T U V W X Y Z"; int x; int y; fprintf (stderr, " %.*s\n", board->width * 2, coordinates); for (y = 0; y < board->height; y++) { fprintf (stderr, "%3d", board->height - y); for (x = 0; x < board->width; x++) fprintf (stderr, " %c", contents[(int) board->grid[POSITION (x, y)]]); fprintf (stderr, board->height > 9 ? "%3d\n" : "%2d\n", board->height - y); } fprintf (stderr, " %.*s\n", board->width * 2, coordinates); } /* Go-specific functions. */ /* Get maximal number of fixed handicap stones that can be placed on a * board of given dimensions. */ int go_get_max_fixed_handicap (int board_width, int board_height) { assert (BOARD_MIN_WIDTH <= board_width && board_width <= BOARD_MAX_WIDTH); assert (BOARD_MIN_HEIGHT <= board_height && board_height <= BOARD_MAX_HEIGHT); if (board_width > 7 && board_height > 7) { return ((board_width % 2 == 1 && board_width > 7 ? 3 : 2) * (board_height % 2 == 1 && board_height > 7 ? 3 : 2)); } else return 0; } /* Get positions of given number of fixed handicap stones. */ BoardPositionList * go_get_fixed_handicap_stones (int board_width, int board_height, int num_stones) { /* Minimal handicap at which nth stone (counting by ascending board * position) is set. */ static const int min_handicaps[9] = { 3, 8, 2, 6, 5, 6, 2, 8, 4 }; BoardPositionList *handicap_stones; int horizontal_edge_gap = (board_width >= 13 ? 3 : 2); int vertical_edge_gap = (board_height >= 13 ? 3 : 2); int stone_index; int k; if (num_stones == 0) return NULL; assert (num_stones > 1 && num_stones <= go_get_max_fixed_handicap (board_width, board_height)); handicap_stones = board_position_list_new_empty (num_stones); for (k = 0, stone_index = 0; k < 9; k++) { /* There is an additional requirement that the fifth (tengen) * stone is only placed when the number of handicap stones is odd. */ if (num_stones >= min_handicaps[k] && (k != 4 || num_stones % 2 == 1)) { /* A little of obscure arithmetics that works. */ int stone_x = ((1 - (k % 3)) * horizontal_edge_gap + ((k % 3) * (board_width - 1)) / 2); int stone_y = ((1 - (k / 3)) * vertical_edge_gap + ((k / 3) * (board_height - 1)) / 2); handicap_stones->positions[stone_index++] = POSITION (stone_x, stone_y); } } return handicap_stones; } /* Get the hoshi points for given board size. Up to 9 points can be * filled, so the caller should simply statically allocate an * appropriate array. The number of hoshi points is returned. * * The `hoshi_points' array is not sorted in any particular order. */ int go_get_hoshi_points (int board_width, int board_height, BoardPoint hoshi_points[9]) { assert (BOARD_MIN_WIDTH <= board_width && board_width <= BOARD_MAX_WIDTH); assert (BOARD_MIN_HEIGHT <= board_height && board_height <= BOARD_MAX_HEIGHT); assert (hoshi_points); if (board_width >= 5 && board_width != 6 && board_height >= 5 && board_height != 6) { int edge_distance_x = (board_width > 11 ? 3 : 2); int edge_distance_y = (board_height > 11 ? 3 : 2); int num_hoshi_points; /* Four hoshi points in corners. */ hoshi_points[0].x = edge_distance_x; hoshi_points[0].y = edge_distance_y; hoshi_points[1].x = board_width - 1 - edge_distance_x; hoshi_points[1].y = edge_distance_y; hoshi_points[2].x = edge_distance_x; hoshi_points[2].y = board_height - 1 - edge_distance_y; hoshi_points[3].x = board_width - 1 - edge_distance_x; hoshi_points[3].y = board_height - 1 - edge_distance_y; if (board_width % 2 == 1 && board_height % 2 == 1) { /* The tengen. */ hoshi_points[4].x = board_width / 2; hoshi_points[4].y = board_height / 2; num_hoshi_points = 5; } else num_hoshi_points = 4; if (board_width % 2 == 1 && board_width >= 13) { /* The top hoshi. */ hoshi_points[num_hoshi_points].x = board_width / 2; hoshi_points[num_hoshi_points++].y = edge_distance_y; /* The bottom hoshi. */ hoshi_points[num_hoshi_points].x = board_width / 2; hoshi_points[num_hoshi_points++].y = board_height - 1 - edge_distance_y; } if (board_height % 2 == 1 && board_height >= 13) { /* The left hoshi. */ hoshi_points[num_hoshi_points].x = edge_distance_x; hoshi_points[num_hoshi_points++].y = board_height / 2; /* The right hoshi. */ hoshi_points[num_hoshi_points].x = board_width - 1 - edge_distance_x; hoshi_points[num_hoshi_points++].y = board_height / 2; } return num_hoshi_points; } else return 0; } /* Weird names of arguments because y1() is a standard function. */ int go_is_same_string (Board *board, int _x1, int _y1, int _x2, int _y2) { const char *grid = board->grid; int pos1 = POSITION (_x1, _y1); int pos2 = POSITION (_x2, _y2); assert (board); assert (board->game == GAME_GO); assert (ON_BOARD (board, _x1, _y1)); assert (ON_BOARD (board, _x2, _y2)); if (IS_STONE (grid[pos1])) { if (pos1 == pos2) return 1; if (grid[pos1] == grid[pos2]) { int color = grid[pos1]; int queue[BOARD_MAX_POSITIONS]; int queue_start = 0; int queue_end = 1; board->data.go.position_mark++; queue[0] = pos1; MARK_POSITION (board, pos1); do { int k; int stone = queue[queue_start++]; for (k = 0; k < 4; k++) { int neighbor = stone + delta[k]; if (grid[neighbor] == color && UNMARKED_POSITION (board, neighbor)) { if (neighbor == pos2) return 1; queue[queue_end++] = neighbor; MARK_POSITION (board, neighbor); } } } while (queue_start < queue_end); } } return 0; } BoardPositionList * go_get_string_stones (Board *board, int x, int y) { int pos = POSITION (x, y); assert (board); assert (board->game == GAME_GO); assert (ON_BOARD (board, x, y)); if (IS_STONE (board->grid[pos])) { BoardPositionList *position_list; const char *grid = board->grid; int color = grid[pos]; int stones[BOARD_MAX_POSITIONS]; int queue_start = 0; int queue_end = 1; board->data.go.position_mark++; stones[0] = pos; MARK_POSITION (board, pos); do { int k; int stone = stones[queue_start++]; for (k = 0; k < 4; k++) { int neighbor = stone + delta[k]; if (grid[neighbor] == color && UNMARKED_POSITION (board, neighbor)) { stones[queue_end++] = neighbor; MARK_POSITION (board, neighbor); } } } while (queue_start < queue_end); position_list = board_position_list_new (stones, queue_end); board_position_list_sort (position_list); return position_list; } else return NULL; } /* Find all stones that shold be logically dead if the stone at given * position is dead and the game is finished. At present, all strings * that are connectable over empty vertecies are included (i.e. a * player should have territory around opponent's dead stones). This * policy may need refinement. */ BoardPositionList * go_get_logically_dead_stones (Board *board, int x, int y) { int pos = POSITION (x, y); assert (board); assert (board->game == GAME_GO); assert (ON_BOARD (board, x, y)); if (IS_STONE (board->grid[POSITION (x, y)])) { BoardPositionList *position_list; const char *grid = board->grid; int color = grid[pos]; int stones[BOARD_MAX_POSITIONS]; int empty_vertices[BOARD_MAX_POSITIONS]; int stones_queue_start = 0; int stones_queue_end = 1; int empty_vertices_queue_start = 0; int empty_vertices_queue_end = 0; board->data.go.position_mark++; stones[0] = pos; MARK_POSITION (board, pos); do { int k; pos = (stones_queue_start < stones_queue_end ? stones[stones_queue_start++] : empty_vertices[empty_vertices_queue_start++]); for (k = 0; k < 4; k++) { int neighbor = pos + delta[k]; if ((grid[neighbor] == color || grid[neighbor] == EMPTY) && UNMARKED_POSITION (board, neighbor)) { if (grid[neighbor] == color) stones[stones_queue_end++] = neighbor; else empty_vertices[empty_vertices_queue_end++] = neighbor; MARK_POSITION (board, neighbor); } } } while (stones_queue_start < stones_queue_end || empty_vertices_queue_start < empty_vertices_queue_end); position_list = board_position_list_new (stones, stones_queue_end); board_position_list_sort (position_list); return position_list; } else return NULL; } void go_score_game (Board *board, const char *dead_stones, double komi, double *score, StringBuffer *detailed_score, BoardPositionList **black_territory, BoardPositionList **white_territory) { char territory[BOARD_GRID_SIZE]; int num_territory_positions[NUM_COLORS] = { 0, 0 }; int territory_positions[NUM_COLORS][BOARD_MAX_POSITIONS]; int num_prisoners[NUM_COLORS]; int x; int y; int pos; int black_score; double white_score; double score_difference; assert (board); num_prisoners[BLACK_INDEX] = board->data.go.prisoners[BLACK_INDEX]; num_prisoners[WHITE_INDEX] = board->data.go.prisoners[WHITE_INDEX]; board_fill_grid (board, territory, EMPTY); go_mark_territory_on_grid (board, territory, dead_stones, BLACK, WHITE); for (y = 0, pos = POSITION (0, 0); y < board->height; y++) { for (x = 0; x < board->width; x++, pos++) { if (territory[pos] != EMPTY) { int color_index = COLOR_INDEX (territory[pos]); territory_positions[color_index] [num_territory_positions[color_index]++] = pos; if (board->grid[pos] != EMPTY) num_prisoners[color_index]++; } } pos += BOARD_MAX_WIDTH + 1 - board->width; } black_score = (num_territory_positions[BLACK_INDEX] + num_prisoners[BLACK_INDEX]); white_score = (num_territory_positions[WHITE_INDEX] + num_prisoners[WHITE_INDEX] + komi); score_difference = black_score - white_score; if (score) *score = score_difference; if (detailed_score) { int komi_is_fractional = (fabs (fabs (komi) - floor (fabs (komi) + 0.005)) >= 0.005); string_buffer_printf (detailed_score, ngettext ("White: %d territory", "White: %d territory", num_territory_positions[WHITE_INDEX]), num_territory_positions[WHITE_INDEX]); string_buffer_printf (detailed_score, ngettext (" + %d capture", " + %d captures", num_prisoners[WHITE_INDEX]), num_prisoners[WHITE_INDEX]); if (komi_is_fractional) { string_buffer_printf (detailed_score, /* TRANSLATORS: e.g. `` + 6.5 komi = 87.5''. This is used only with fractional komi. */ _(" %s %.*f komi = %.*f\n"), (komi >= 0.0 ? "+" : "\xe2\x88\x92"), ((int) floor (komi * 100.0 + 0.5) % 10 == 0 ? 1 : 2), fabs (komi), ((int) floor (white_score * 100.0 + 0.5) % 10 == 0 ? 1 : 2), white_score); } else { int absolute_integral_komi = (int) floor (fabs (komi) + 0.005); string_buffer_printf (detailed_score, /* TRANSLATORS: e.g. `` + 6 komi = 87''. */ ngettext (" %s %d komi = %d\n", " %s %d komi = %d\n", absolute_integral_komi), (komi >= 0.0 ? "+" : "\xe2\x88\x92"), absolute_integral_komi, (int) floor (white_score + 0.005)); } string_buffer_printf (detailed_score, ngettext ("Black: %d territory", "Black: %d territory", num_territory_positions[BLACK_INDEX]), num_territory_positions[BLACK_INDEX]); string_buffer_printf (detailed_score, ngettext (" + %d capture", " + %d captures", num_prisoners[BLACK_INDEX]), num_prisoners[BLACK_INDEX]); string_buffer_printf (detailed_score, " = %.*f\n\n", (komi_is_fractional ? 1 : 0), (double) black_score); if (fabs (score_difference) >= 0.005) game_format_score_difference (GAME_GO, detailed_score, score_difference); else string_buffer_cat_string (detailed_score, _("The game is draw")); } if (black_territory) { *black_territory = board_position_list_new (territory_positions[BLACK_INDEX], num_territory_positions[BLACK_INDEX]); } if (white_territory) { *white_territory = board_position_list_new (territory_positions[WHITE_INDEX], num_territory_positions[WHITE_INDEX]); } } /* Mark territory on given grid with specified marks. The grid must * be reset to whatever value the caller wants before calling this * function. go_mark_territory_on_grid() will not overwrite grid * values' at dame and stone positions. * * Grid `dead_stones' should have non-zeros in positions of dead * stones and zeros elsewhere. It is assumed that `dead_stones' are * filled sanely, i.e all stones of any string are either dead or * alive. * * FIXME: Improve this function. It doesn't detect sekis. */ void go_mark_territory_on_grid (Board *board, char *grid, const char *dead_stones, char black_territory_mark, char white_territory_mark) { const char *board_grid = board->grid; int x; int y; int pos; char territory[BOARD_GRID_SIZE]; char false_eyes[BOARD_GRID_SIZE]; int queue[BOARD_MAX_POSITIONS]; assert (board); assert (board->game == GAME_GO); assert (grid); assert (dead_stones); /* First simply look for regions bounded by alive stones of only one * color and claim they are territory. Also look for false eyes. */ board_fill_grid (board, territory, EMPTY); board_fill_grid (board, false_eyes, 0); board->data.go.position_mark++; for (y = 0, pos = POSITION (0, 0); y < board->height; y++) { for (x = 0; x < board->width; x++, pos++) { if (UNMARKED_POSITION (board, pos) && (board_grid[pos] == EMPTY || dead_stones[pos])) { /* Found another connected set of empty vertices and/or dead * stones. Loop over it marking positions and determine if it * is a proper territory, i.e. if it has adjacent living * stones of only one color. */ int queue_start = 0; int queue_end = 1; char alive_neighbors = 0; queue[0] = pos; MARK_POSITION (board, pos); do { int k; int pos2 = queue[queue_start++]; for (k = 0; k < 4; k++) { int neighbor = pos2 + delta[k]; if ((board_grid[neighbor] == EMPTY || (IS_STONE (board_grid[neighbor]) && dead_stones[neighbor])) && UNMARKED_POSITION (board, neighbor)) { queue[queue_end++] = neighbor; MARK_POSITION (board, neighbor); } else if (IS_STONE (board_grid[neighbor]) && !dead_stones[neighbor]) alive_neighbors |= board_grid[neighbor]; } } while (queue_start < queue_end); if (IS_STONE (alive_neighbors)) { for (queue_start = 0; queue_start < queue_end; queue_start++) { int k; int pos2 = queue[queue_start]; int other = OTHER_COLOR (alive_neighbors); int diagonal_score = 0; territory[pos2] = alive_neighbors; /* Does this position look like a false eye? */ for (k = 4; k < 8; k++) { if (board_grid[pos2 + delta[k]] == other && !dead_stones[pos2 + delta[k]]) diagonal_score += 2; else if (!ON_GRID (board_grid, pos2 + delta[k])) diagonal_score++; } if (diagonal_score >= 4) false_eyes[pos2] = 1; } } } } pos += BOARD_MAX_WIDTH + 1 - board->width; } /* Determine which false eyes don't yield territory points and erase * territory under them. */ do { restart_false_eye_checking: board->data.go.position_mark++; for (y = 0, pos = POSITION (0, 0); y < board->height; y++) { for (x = 0; x < board->width; x++, pos++) { if (UNMARKED_POSITION (board, pos) && board_grid[pos] != EMPTY && !dead_stones[pos]) { int color = board_grid[pos]; int queue_start = 0; int queue_end = 1; int affected_false_eye = NULL_POSITION; int not_connected_to_an_eye = 1; queue[0] = pos; MARK_POSITION (board, pos); do { int k; int pos2 = queue[queue_start++]; for (k = 0; k < 4; k++) { int neighbor = pos2 + delta[k]; if (ON_GRID (board_grid, neighbor)) { if ((board_grid[neighbor] == color || ((board_grid[neighbor] == EMPTY || dead_stones[neighbor]) && !false_eyes[neighbor] && (territory[neighbor] != EMPTY || (board_grid[neighbor] == EMPTY && board_grid[pos2] == color)))) && UNMARKED_POSITION (board, neighbor)) { queue[queue_end++] = neighbor; MARK_POSITION (board, neighbor); if (territory[neighbor] != EMPTY) not_connected_to_an_eye = 0; } else if (false_eyes[neighbor] && territory[neighbor] != EMPTY) { if (affected_false_eye != NULL_POSITION && neighbor != affected_false_eye) not_connected_to_an_eye = 0; affected_false_eye = neighbor; } } } } while (queue_start < queue_end); if (not_connected_to_an_eye && affected_false_eye != NULL_POSITION) { territory[affected_false_eye] = EMPTY; goto restart_false_eye_checking; } } } pos += BOARD_MAX_WIDTH + 1 - board->width; } } while (0); /* Finally, mark the territory on the supplied grid. */ for (y = 0, pos = POSITION (0, 0); y < board->height; y++) { for (x = 0; x < board->width; x++, pos++) { if (territory[pos] != EMPTY) { grid[pos] = (territory[pos] == BLACK ? black_territory_mark : white_territory_mark); } } pos += BOARD_MAX_WIDTH + 1 - board->width; } } void go_guess_dead_stones (Board *board, char *dead_stones, const BoardPositionList *black_territory, const BoardPositionList *white_territory) { const char *grid = board->grid; int queue[BOARD_MAX_POSITIONS]; int queue_start = 0; int queue_end = 0; int k; assert (board); assert (dead_stones); board->data.go.position_mark++; if (black_territory) { for (k = 0; k < black_territory->num_positions; k++) { int pos = black_territory->positions[k]; if (grid[pos] == WHITE) { queue[queue_end++] = pos; MARK_POSITION (board, pos); } } } if (white_territory) { for (k = 0; k < white_territory->num_positions; k++) { int pos = white_territory->positions[k]; if (grid[pos] == BLACK) { queue[queue_end++] = pos; MARK_POSITION (board, pos); } } } while (queue_start < queue_end) { int stone = queue[queue_start++]; dead_stones[stone] = 1; for (k = 0; k < 4; k++) { int neighbor = stone + delta[k]; if (grid[neighbor] == grid[stone] && UNMARKED_POSITION (board, neighbor)) { queue[queue_end++] = neighbor; MARK_POSITION (board, neighbor); } } } } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/board/reversi.c0000644000175000017500000001717710376424230015215 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "reversi.h" #include "board-internals.h" #include #include #ifdef HAVE_MEMORY_H #include #endif static inline int is_legal_move (const char grid[BOARD_FULL_GRID_SIZE], BoardRuleSet rule_set, int color, int pos); int reversi_adjust_color_to_play (const Board *board, BoardRuleSet rule_set, int color) { int pos; int check_color = color; if (rule_set == REVERSI_RULE_SET_SGF) return color; assert (rule_set < NUM_REVERSI_RULE_SETS); do { for (pos = POSITION (0, 0); ON_GRID (board->grid, pos); pos += (BOARD_MAX_WIDTH + 1) - board->width) { for (; ON_GRID (board->grid, pos); pos++) { if (board->grid[pos] == EMPTY && is_legal_move (board->grid, rule_set, check_color, pos)) return check_color; } } check_color = OTHER_COLOR (check_color); } while (check_color != color); return EMPTY; } /* Get the default setup for Reversi (only defined for even-sized * boards): * * .... * .OX. * .XO. * .... */ int reversi_get_default_setup (int width, int height, BoardPositionList **black_stones, BoardPositionList **white_stones) { if (width % 2 != 0 || height % 2 != 0) return 0; *black_stones = board_position_list_new_empty (2); (*black_stones)->positions[0] = POSITION (width / 2, height / 2 - 1); (*black_stones)->positions[1] = POSITION (width / 2 - 1, height / 2); *white_stones = board_position_list_new_empty (2); (*white_stones)->positions[0] = POSITION (width / 2 - 1, height / 2 - 1); (*white_stones)->positions[1] = POSITION (width / 2, height / 2); return 1; } /* Determine if a move is legal according to specified rule set. */ int reversi_is_legal_move (const Board *board, BoardRuleSet rule_set, int color, va_list move) { int x = va_arg (move, int); int y = va_arg (move, int); int pos = POSITION (x, y); assert (rule_set < NUM_REVERSI_RULE_SETS); assert (ON_BOARD (board, x, y)); if (rule_set != REVERSI_RULE_SET_SGF) { if (board->grid[pos] == EMPTY) return is_legal_move (board->grid, rule_set, color, pos); return 0; } return 1; } static inline int is_legal_move (const char grid[BOARD_FULL_GRID_SIZE], BoardRuleSet rule_set, int color, int pos) { int k; int other = OTHER_COLOR (color); UNUSED (rule_set); for (k = 0; k < 8; k++) { int beam = pos + delta[k]; if (grid[beam] == other) { do beam += delta[k]; while (grid[beam] == other); if (grid[beam] == color) return 1; } } return 0; } void reversi_play_move (Board *board, int color, va_list move) { char *grid = board->grid; int k; int other = OTHER_COLOR (color); int x = va_arg (move, int); int y = va_arg (move, int); int pos = POSITION (x, y); ReversiMoveStackEntry *stack_entry = ALLOCATE_REVERSI_MOVE_STACK_ENTRY (board); assert (ON_BOARD (board, x, y)); memset (stack_entry->num.flips, 0, sizeof stack_entry->num.flips); for (k = 0; k < 8; k++) { int beam = pos + delta[k]; if (grid[beam] == other) { do beam += delta[k]; while (grid[beam] == other); if (grid[beam] == color) { beam -= delta[k]; do { grid[beam] = color; stack_entry->num.flips[k]++; beam -= delta[k]; } while (beam != pos); } } } stack_entry->position = pos; stack_entry->contents = grid[pos]; stack_entry->common.move_number = board->move_number++; grid[pos] = color; } void reversi_undo (Board *board) { ReversiMoveStackEntry *stack_entry = POP_REVERSI_MOVE_STACK_ENTRY (board); if (stack_entry->position != NULL_POSITION) { int k; int pos = stack_entry->position; int other = OTHER_COLOR (board->grid[pos]); for (k = 0; k < 8; k++) { if (stack_entry->num.flips[k]) { int flips = 0; int beam = pos; do { beam += delta[k]; board->grid[beam] = other; } while (++flips < stack_entry->num.flips[k]); } } board->grid[pos] = stack_entry->contents; } else if (stack_entry->num.changes > 0) board_undo_changes (board, stack_entry->num.changes); board->move_number = stack_entry->common.move_number; } void reversi_apply_changes (Board *board, int num_changes) { ReversiMoveStackEntry *stack_entry = ALLOCATE_REVERSI_MOVE_STACK_ENTRY (board); stack_entry->position = NULL_POSITION; stack_entry->num.changes = num_changes; stack_entry->common.move_number = board->move_number; } void reversi_add_dummy_move_entry (Board *board) { reversi_apply_changes (board, 0); } void reversi_format_move (int board_width, int board_height, StringBuffer *buffer, va_list move) { int x = va_arg (move, int); int y = va_arg (move, int); game_format_point (GAME_REVERSI, board_width, board_height, buffer, x, y); } int reversi_parse_move (int board_width, int board_height, const char *move_string, int *x, int *y, BoardAbstractMoveData *move_data) { UNUSED (move_data); return game_parse_point (GAME_REVERSI, board_width, board_height, move_string, x, y); } void reversi_validate_board (const Board *board) { UNUSED (board); } void reversi_dump_board (const Board *board) { static const char contents[] = {'.', '@', 'O', '?'}; static const char coordinates[] = " A B C D E F G H I J K L M N O P Q R S T U V W X Y"; int x; int y; fprintf (stderr, " %.*s\n", board->width * 2, coordinates); for (y = 0; y < board->height; y++) { fprintf (stderr, "%3d", board->height - y); for (x = 0; x < board->width; x++) fprintf (stderr, " %c", contents[(int) board->grid[POSITION (x, y)]]); fprintf (stderr, "%3d\n", board->height - y); } fprintf (stderr, " %.*s\n", board->width * 2, coordinates); } /* Reversi-specific function. */ void reversi_count_disks (const Board *board, int *num_black_disks, int *num_white_disks) { int pos; assert (board); assert (board->game == GAME_REVERSI); assert (num_black_disks && num_white_disks); *num_black_disks = 0; *num_white_disks = 0; for (pos = POSITION (0, 0); ON_GRID (board->grid, pos); pos += (BOARD_MAX_WIDTH + 1) - board->width) { for (; ON_GRID (board->grid, pos); pos++) { if (board->grid[pos] == BLACK) (*num_black_disks)++; else if (board->grid[pos] == WHITE) (*num_white_disks)++; } } } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/board/amazons.h0000644000175000017500000000621010376424013015174 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef QUARRY_AMAZONS_H #define QUARRY_AMAZONS_H #include "board-internals.h" #include "utils.h" #include "quarry.h" #include #define ALLOCATE_AMAZONS_MOVE_STACK_ENTRY(board) \ ALLOCATE_MOVE_STACK_ENTRY ((board), AmazonsMoveStackEntry) #define POP_AMAZONS_MOVE_STACK_ENTRY(board) \ POP_MOVE_STACK_ENTRY ((board), AmazonsMoveStackEntry) typedef struct _AmazonsMoveStackEntry AmazonsMoveStackEntry; struct _AmazonsMoveStackEntry { BoardStackEntry common; char to_contents; char shoot_arrow_to_contents; int from; int to; union { int shoot_arrow_to; int num_changes; } misc; }; int amazons_adjust_color_to_play (const Board *board, BoardRuleSet rule_set, int color); int amazons_is_game_over (const Board *board, BoardRuleSet rule_set, int color_to_play); int amazons_get_default_setup (int width, int height, BoardPositionList **black_stones, BoardPositionList **white_stones); int amazons_is_legal_move (const Board *board, BoardRuleSet rule_set, int color, va_list move); void amazons_play_move (Board *board, int color, va_list move); void amazons_undo (Board *board); void amazons_apply_changes (Board *board, int num_changes); void amazons_add_dummy_move_entry (Board *board); void amazons_format_move (int board_width, int board_height, StringBuffer *buffer, va_list move); int amazons_parse_move (int board_width, int board_height, const char *move_string, int *x, int *y, BoardAbstractMoveData *move_data); void amazons_validate_board (const Board *board); void amazons_dump_board (const Board *board); #endif /* QUARRY_AMAZONS_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/board/board.h0000644000175000017500000002725310376425523014634 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef QUARRY_BOARD_H #define QUARRY_BOARD_H #include "board-topology.h" #include "games.h" #include "utils.h" #include "quarry.h" #include #include #define EMPTY 0 #define FIRST_COLOR 1 #define BLACK 1 #define WHITE 2 #define NUM_COLORS 2 /* NOTE: padding for game-specific on-grid values (like arrows for * Amazons). */ #define SPECIAL_ON_GRID_VALUE 3 #define NUM_ON_GRID_VALUES 4 #define OFF_GRID NUM_ON_GRID_VALUES #define NUM_VALID_BOARD_VALUES 5 #define COLOR_INDEX(color) ((color) - FIRST_COLOR) #define BLACK_INDEX COLOR_INDEX (BLACK) #define WHITE_INDEX COLOR_INDEX (WHITE) /* "Stone" is Go terminology. */ #define IS_STONE(color) ((color) == BLACK || (color) == WHITE) #define OTHER_COLOR(color) (BLACK + WHITE - (color)) #define OTHER_INDEX(index) (BLACK_INDEX + WHITE_INDEX - (index)) #define POINTS_ARE_EQUAL(first_point, second_point) \ ((first_point).x == (second_point).x \ && (first_point).y == (second_point).y) #define POINTS_LESS_THAN(first_point, second_point) \ ((first_point).y < (second_point).y \ || ((first_point).y == (second_point).y \ && (first_point).x < (second_point).x)) typedef struct _BoardPoint BoardPoint; struct _BoardPoint { signed char x; signed char y; }; /* Go-specific definitions. */ #define GO_STRING_RING_SIZE (BOARD_MAX_POSITIONS \ + BOARD_MAX_WIDTH + BOARD_MAX_HEIGHT) #define PASS_X NULL_X #define PASS_Y NULL_Y #define PASS_MOVE NULL_POSITION #define IS_PASS(x, y) IS_NULL_POINT ((x), (y)) typedef struct _GoBoardData GoBoardData; struct _GoBoardData{ int ko_master; int ko_position; int prisoners[NUM_COLORS]; int last_string_number; int string_number[BOARD_GRID_SIZE]; int liberties[GO_STRING_RING_SIZE]; unsigned int position_mark; unsigned int string_mark; unsigned int marked_positions[BOARD_GRID_SIZE]; unsigned int marked_strings[GO_STRING_RING_SIZE]; }; /* Amazons-specific definition. */ #define ARROW SPECIAL_ON_GRID_VALUE typedef struct _BoardAmazonsMoveData BoardAmazonsMoveData; typedef union _BoardAbstractMoveData BoardAbstractMoveData; struct _BoardAmazonsMoveData { BoardPoint from; BoardPoint shoot_arrow_to; }; union _BoardAbstractMoveData { BoardAmazonsMoveData amazons; }; typedef enum { FIRST_RULE_SET, RULE_SET_SGF = FIRST_RULE_SET, RULE_SET_DEFAULT, GO_RULE_SET_SGF = RULE_SET_SGF, GO_RULE_SET_DEFAULT = RULE_SET_DEFAULT, NUM_GO_RULE_SETS, REVERSI_RULE_SET_SGF = RULE_SET_SGF, REVERSI_RULE_SET_DEFAULT = RULE_SET_DEFAULT, NUM_REVERSI_RULE_SETS, AMAZONS_RULE_SET_SGF = RULE_SET_SGF, AMAZONS_RULE_SET_DEFAULT = RULE_SET_DEFAULT, NUM_AMAZONS_RULE_SETS } BoardRuleSet; typedef struct _BoardChangeStackEntry BoardChangeStackEntry; typedef struct _Board Board; typedef int (* BoardIsLegalMoveFunction) (const Board *board, BoardRuleSet rule_set, int color, va_list move); typedef void (* BoardPlayMoveFunction) (Board *board, int color, va_list move); typedef void (* BoardUndoFunction) (Board *board); struct _Board { Game game; int width; int height; unsigned int move_number; char grid[BOARD_FULL_GRID_SIZE]; void *move_stack; void *move_stack_pointer; void *move_stack_end; BoardChangeStackEntry *change_stack; BoardChangeStackEntry *change_stack_pointer; BoardChangeStackEntry *change_stack_end; BoardIsLegalMoveFunction is_legal_move; BoardPlayMoveFunction play_move; BoardUndoFunction undo; union { GoBoardData go; } data; }; typedef struct _BoardPositionList BoardPositionList; struct _BoardPositionList { int num_positions; int positions[BOARD_MAX_POSITIONS]; }; Board * board_new (Game game, int width, int height); void board_delete (Board *board); Board * board_duplicate_without_stacks (const Board *board); void board_set_parameters (Board *board, Game game, int width, int height); #define board_clear(board) \ board_set_parameters ((board), (board)->game, \ (board)->width, (board)->height) int board_adjust_color_to_play (const Board *board, BoardRuleSet rule_set, int color); int board_is_game_over (const Board *board, BoardRuleSet rule_set, int color_to_play); inline int board_is_legal_move (const Board *board, BoardRuleSet rule_set, int color, ...); inline void board_play_move (Board *board, int color, ...); void board_apply_changes (Board *board, const BoardPositionList *const change_lists[NUM_ON_GRID_VALUES]); inline void board_add_dummy_move_entry (Board *board); inline int board_undo (Board *board, int num_moves); int board_get_move_number (const Board *board, int num_moves_backward); inline void board_dump (const Board *board); inline void board_validate (const Board *board); BoardPositionList * board_position_list_new (const int *positions, int num_positions); BoardPositionList * board_position_list_new_empty (int num_positions); #define board_position_list_delete(position_list) \ do { \ assert (position_list); \ utils_free (position_list); \ } while (0) #define board_position_list_duplicate(position_list) \ ((BoardPositionList *) \ utils_duplicate_buffer ((position_list), \ (sizeof (BoardPositionList) \ - ((BOARD_MAX_POSITIONS - \ (position_list)->num_positions) \ * sizeof (int))))) BoardPositionList * board_position_list_union (const BoardPositionList *list1, const BoardPositionList *list2); BoardPositionList * board_position_list_add_position (BoardPositionList *list, int pos); void board_position_list_sort (BoardPositionList *list); int board_position_lists_are_equal (const BoardPositionList *first_list, const BoardPositionList *second_list); int board_position_lists_overlap (const BoardPositionList *first_list, const BoardPositionList *second_list); int board_position_list_find_position (const BoardPositionList *list, int pos); void board_position_list_mark_on_grid (const BoardPositionList *list, char grid[BOARD_GRID_SIZE], char value); Game game_from_game_name (const char *game_name, int case_sensitive); void game_format_point (Game game, int board_width, int board_height, StringBuffer *buffer, int x, int y); void game_format_position_list (Game game, int board_width, int board_height, StringBuffer *buffer, const BoardPositionList *position_list); void game_format_move (Game game, int board_width, int board_height, StringBuffer *buffer, ...); void game_format_move_valist (Game game, int board_width, int board_height, StringBuffer *buffer, va_list move); void game_format_score_difference (Game game, StringBuffer *buffer, double score); int game_parse_point (Game game, int board_width, int board_height, const char *point_string, int *x, int *y); BoardPositionList * game_parse_position_list (Game game, int board_width, int board_height, const char *positions_string); int game_parse_move (Game game, int board_width, int board_height, const char *move_string, int *x, int *y, BoardAbstractMoveData *move_data); inline int game_get_default_setup (Game game, int width, int height, BoardPositionList **black_stones, BoardPositionList **white_stones); void grid_fill (char grid[BOARD_GRID_SIZE], int width, int height, char value); void int_grid_fill (int grid[BOARD_GRID_SIZE], int width, int height, int value); void pointer_grid_fill (void *grid[BOARD_GRID_SIZE], int width, int height, void *value); void grid_copy (char destination[BOARD_GRID_SIZE], const char source[BOARD_GRID_SIZE], int width, int height); void int_grid_copy (int destination[BOARD_GRID_SIZE], const int source[BOARD_GRID_SIZE], int width, int height); void pointer_grid_copy (void *destination[BOARD_GRID_SIZE], const void *source[BOARD_GRID_SIZE], int width, int height); #define uint_grid_fill(grid, width, height, value) \ int_grid_fill ((int *) (grid), (width), (height), (value)) #define board_fill_grid(board, grid, value) \ grid_fill ((grid), (board)->width, (board)->height, (value)) #define board_fill_int_grid(board, grid, value) \ int_grid_fill ((grid), (board)->width, (board)->height, (value)) #define board_fill_uint_grid(board, grid, value) \ board_fill_int_grid ((board), (int *) (grid), (value)) #define board_fill_pointer_grid(board, grid, value) \ pointer_grid_fill ((grid), (board)->width, (board)->height, (value)) #define uint_grid_copy(destination, source, width, height) \ int_grid_copy ((int *) (destination), (int *) source, \ (width), (height)) int grid_diff (const char grid1[BOARD_GRID_SIZE], const char grid2[BOARD_GRID_SIZE], int width, int height, BoardPositionList *difference_lists[NUM_ON_GRID_VALUES]); /* Go-specific functions. */ int go_get_max_fixed_handicap (int board_width, int board_height); BoardPositionList * go_get_fixed_handicap_stones (int board_width, int board_height, int num_stones); int go_get_hoshi_points (int board_width, int board_height, BoardPoint hoshi_points[9]); int go_is_same_string (Board *board, int _x1, int _y1, int _x2, int _y2); BoardPositionList * go_get_string_stones (Board *board, int x, int y); BoardPositionList * go_get_logically_dead_stones (Board *board, int x, int y); void go_score_game (Board *board, const char *dead_stones, double komi, double *score, StringBuffer *detailed_score, BoardPositionList **black_territory, BoardPositionList **white_territory); void go_mark_territory_on_grid (Board *board, char *grid, const char *dead_stones, char black_territory_mark, char white_territory_mark); void go_guess_dead_stones (Board *board, char *dead_stones, const BoardPositionList *black_territory, const BoardPositionList *white_territory); /* Reversi-specific function. */ void reversi_count_disks (const Board *board, int *num_black_disks, int *num_white_disks); #endif /* QUARRY_BOARD_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/board/board-topology.h0000644000175000017500000000576610367243531016510 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef QUARRY_BOARD_TOPOLOGY_H #define QUARRY_BOARD_TOPOLOGY_H #include "quarry.h" #define BOARD_MIN_WIDTH 5 #define BOARD_MIN_HEIGHT 5 #define BOARD_MAX_WIDTH 25 #define BOARD_MAX_HEIGHT 25 #define POSITION(x, y) ((1 + (y)) * (1 + BOARD_MAX_WIDTH) + (1 + (x))) #define POINT_TO_POSITION(point) \ POSITION ((point).x, (point).y) #define POSITION_X(pos) (((pos) % (1 + BOARD_MAX_WIDTH)) - 1) #define POSITION_Y(pos) (((pos) / (1 + BOARD_MAX_WIDTH)) - 1) #define SOUTH(pos) ((pos) + (1 + BOARD_MAX_WIDTH)) #define WEST(pos) ((pos) - 1) #define NORTH(pos) ((pos) - (1 + BOARD_MAX_WIDTH)) #define EAST(pos) ((pos) + 1) #define BOARD_MAX_POSITIONS (BOARD_MAX_WIDTH * BOARD_MAX_HEIGHT) #define BOARD_GRID_SIZE (POSITION (BOARD_MAX_WIDTH - 1, \ BOARD_MAX_HEIGHT - 1) + 1) #define BOARD_FULL_GRID_SIZE (POSITION (BOARD_MAX_WIDTH, \ BOARD_MAX_HEIGHT) + 1) #define ON_SIZED_GRID(width, height, x, y) \ ((unsigned int) (x) < (unsigned int) (width) \ && (unsigned int) (y) < (unsigned int) (height)) #define ON_BOARD(board, x, y) \ ON_SIZED_GRID ((board)->width, (board)->height, (x), (y)) #define NULL_X (-1) #define NULL_Y (-1) #define NULL_POSITION POSITION (NULL_X, NULL_Y) #define IS_NULL_POINT(x, y) ((x) == NULL_X && (y) == NULL_Y) /* These values has no meaning for the board code, but they cannot be * mistook for normal coordinates. Higher-level modules can treat * them in a special way. */ #define SPECIAL_X (-2) #define SPECIAL_Y (-2) #define SPECIAL_POSITION POSITION (SPECIAL_X, SPECIAL_Y) #endif /* QUARRY_BOARD_TOPOLOGY_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/board/board-internals.h0000644000175000017500000000714310371421203016607 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef QUARRY_BOARD_INTERNALS_H #define QUARRY_BOARD_INTERNALS_H #include "board.h" #include "quarry.h" /* When set to 1, the board is validated after each change (playing a * move, adding/removing stones or undo). This includes validating of * grid contents (i.e. only stones or "empty" values are allowed on * grid for Go), consistency of internal data (for Go: string numbers * and number of liberties for each string). * * When set to 2, it is additionally verified that board_undo() does * indeed revert grid to previous state and not something else. * * Zero means that no automated validation is ever done. */ #define BOARD_VALIDATION_LEVEL 0 #define SOUTH(pos) ((pos) + (1 + BOARD_MAX_WIDTH)) #define WEST(pos) ((pos) - 1) #define NORTH(pos) ((pos) - (1 + BOARD_MAX_WIDTH)) #define EAST(pos) ((pos) + 1) #define ON_GRID(grid, pos) ((grid) [pos] != OFF_GRID) /* Cast expressions are not allowed as lvalues by ISO C and may be * frowned upon by strict compilers, hence the tricks below. Must be * optimized away in any case. */ #define ALLOCATE_MOVE_STACK_ENTRY(board, MoveStackEntryType) \ (((board)->move_stack_pointer == (board)->move_stack_end \ ? board_increase_move_stack_size (board) \ : (void) 0), \ (board)->move_stack_pointer \ = (MoveStackEntryType *) (board)->move_stack_pointer + 1, \ (MoveStackEntryType *) (board)->move_stack_pointer - 1) #define POP_MOVE_STACK_ENTRY(board, MoveStackEntryType) \ ((MoveStackEntryType *) \ ((board)->move_stack_pointer \ = (MoveStackEntryType *) (board)->move_stack_pointer - 1)) typedef struct _BoardStackEntry BoardStackEntry; struct _BoardStackEntry { #if BOARD_VALIDATION_LEVEL == 2 /* Causes problems with very deep branches, since stack is allocated * in one memory chunk. */ char grid_copy[BOARD_GRID_SIZE]; #endif int move_number; }; struct _BoardChangeStackEntry { short position; char contents; }; inline void board_undo_changes (Board *board, int num_undos); int determine_position_delta (int delta_x, int delta_y); void board_increase_move_stack_size (Board *board); extern const int delta[8]; #endif /* QUARRY_BOARD_INTERNALS_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/board/game-info.h0000644000175000017500000000576010376450545015410 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef QUARRY_GAME_INFO_H #define QUARRY_GAME_INFO_H #include "games.h" #include "board-internals.h" #include "utils.h" #include "quarry.h" #define GAME_IS_SUPPORTED(game) \ ((game) <= LAST_GAME && game_info[game].default_board_size != 0) typedef struct _GameInfo GameInfo; struct _GameInfo { const char *name; int default_board_size; const char *standard_board_sizes; int color_to_play_first; int (* adjust_color_to_play) (const Board *board, BoardRuleSet rule_set, int color); int (* is_game_over) (const Board *board, BoardRuleSet rule_set, int color_to_play); const char *horizontal_coordinates; int reversed_vertical_coordinates; int (* get_default_setup) (int width, int height, BoardPositionList **black_stones, BoardPositionList **white_stones); void (* reset_game_data) (Board *board, int forced_reset); BoardIsLegalMoveFunction is_legal_move; BoardPlayMoveFunction play_move; BoardUndoFunction undo; void (* apply_changes) (Board *board, int num_changes); void (* add_dummy_move_entry) (Board *board); void (* format_move) (int board_width, int board_height, StringBuffer *buffer, va_list move); int (* parse_move) (int board_width, int board_height, const char *move_string, int *x, int *y, BoardAbstractMoveData *move_data); void (* validate_board) (const Board *board); void (* dump_board) (const Board *board); int stack_entry_size; float relative_num_moves_per_game; }; extern const GameInfo game_info[]; #endif /* QUARRY_GAME_INFO_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/board/go.h0000644000175000017500000000564210376424151014144 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef QUARRY_GO_H #define QUARRY_GO_H #include "board-internals.h" #include "utils.h" #include "quarry.h" #include #define ALLOCATE_GO_MOVE_STACK_ENTRY(board) \ ALLOCATE_MOVE_STACK_ENTRY ((board), GoMoveStackEntry) #define POP_GO_MOVE_STACK_ENTRY(board) \ POP_MOVE_STACK_ENTRY ((board), GoMoveStackEntry) typedef struct _GoMoveStackEntry GoMoveStackEntry; struct _GoMoveStackEntry { BoardStackEntry common; char type; char contents; char suicide_or_pass_color; int position; char status[4]; union { int liberties; int changes; } num; int ko_master; int ko_position; int prisoners[NUM_COLORS]; }; void go_reset_game_data (Board *board, int forced_reset); int go_is_game_over (const Board *board, BoardRuleSet rule_set, int color_to_play); int go_is_legal_move (const Board *board, BoardRuleSet rule_set, int color, va_list move); void go_play_move (Board *board, int color, va_list move); void go_undo (Board *board); void go_apply_changes (Board *board, int num_changes); void go_add_dummy_move_entry (Board *board); void go_format_move (int board_width, int board_height, StringBuffer *buffer, va_list move); int go_parse_move (int board_width, int board_height, const char *move_string, int *x, int *y, BoardAbstractMoveData *move_data); void go_validate_board (const Board *board); void go_dump_board (const Board *board); #endif /* QUARRY_GO_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/board/reversi.h0000644000175000017500000000611510376424214015212 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef QUARRY_REVERSI_H #define QUARRY_REVERSI_H #include "board-internals.h" #include "utils.h" #include "quarry.h" #include #define ALLOCATE_REVERSI_MOVE_STACK_ENTRY(board) \ ALLOCATE_MOVE_STACK_ENTRY ((board), ReversiMoveStackEntry) #define POP_REVERSI_MOVE_STACK_ENTRY(board) \ POP_MOVE_STACK_ENTRY ((board), ReversiMoveStackEntry) typedef struct _ReversiMoveStackEntry ReversiMoveStackEntry; struct _ReversiMoveStackEntry { BoardStackEntry common; int position; char contents; union { char flips[8]; int changes; } num; }; int reversi_adjust_color_to_play (const Board *board, BoardRuleSet rule_set, int color); int reversi_is_game_over (const Board *board, BoardRuleSet rule_set, int color_to_play); int reversi_get_default_setup (int width, int height, BoardPositionList **black_stones, BoardPositionList **white_stones); int reversi_is_legal_move (const Board *board, BoardRuleSet rule_set, int color, va_list move); void reversi_play_move (Board *board, int color, va_list move); void reversi_undo (Board *board); void reversi_apply_changes (Board *board, int num_changes); void reversi_add_dummy_move_entry (Board *board); void reversi_format_move (int board_width, int board_height, StringBuffer *buffer, va_list move); int reversi_parse_move (int board_width, int board_height, const char *move_string, int *x, int *y, BoardAbstractMoveData *move_data); void reversi_validate_board (const Board *board); void reversi_dump_board (const Board *board); #endif /* QUARRY_REVERSI_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/board/games.list0000644000175000017500000000770410376450755015371 0ustar bartbart# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # This file is part of Quarry # # # # Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. # # # # 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 2 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, write to the Free # # Software Foundation, Inc., 51 Franklin Street, Fifth Floor, # # Boston, MA 02110-1301, USA. # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # @mode games @c_include "game-info.h" @c_include "go.h" @c_include "reversi.h" @c_include "amazons.h" @c_include games Game game_info { # List of games, in the same order they are numbered in SGF. #> Dummy entry, to fill zero index. NULL GAME_DUMMY UNSUPPORTED = GAME_INVALID + FIRST_GAME #> GM[1], Go. "Go" GAME_GO 19 { 9 13 19 } black NULL go_is_game_over ABCDEFGHJKLMNOPQRSTUVWXYZ reversed NULL go_reset_game_data go_is_legal_move go_play_move go_undo go_apply_changes go_add_dummy_move_entry go_format_move go_parse_move go_validate_board go_dump_board GoMoveStackEntry 0.8 #> GM[2], Othello (which we call Reversi to avoid potential #> trademark problems.) "Reversi" GAME_REVERSI 8 { 8 10 } black reversi_adjust_color_to_play NULL ABCDEFGHIJKLMNOPQRSTUVWXY normal reversi_get_default_setup NULL reversi_is_legal_move reversi_play_move reversi_undo reversi_apply_changes reversi_add_dummy_move_entry reversi_format_move reversi_parse_move reversi_validate_board reversi_dump_board ReversiMoveStackEntry 0.95 #> GM[3], chess. "chess" GAME_CHESS UNSUPPORTED #> GM[4], Gomoku + Renju. "Gomoku" GAME_GOMOKU UNSUPPORTED #> GM[5], Nine Men's Morris. "Nine Men's Morris" GAME_NINE_MENS_MORRIS UNSUPPORTED #> GM[6], Backgammon. "Backgammon" GAME_BACKGAMMON UNSUPPORTED #> GM[7], Chinese chess. "Chinese chess" GAME_CHINESE_CHESS UNSUPPORTED #> GM[8], Shogi. "Shogi" GAME_SHOGI UNSUPPORTED #> GM[9], Lines of Action. "Lines of Action" GAME_LINES_OF_ACTION UNSUPPORTED #> GM[10], Ataxx. "Ataxx" GAME_ATAXX UNSUPPORTED #> GM[11], Hex. "Hex" GAME_HEX UNSUPPORTED #> GM[12], Jungle. "Jungle" GAME_JUNGLE UNSUPPORTED #> GM[13], Neutron. "Neutron" GAME_NEUTRON UNSUPPORTED #> GM[14], Philosopher's Football. "Philosopher's Football" GAME_PHILOSOPHERS_FOOTBALL UNSUPPORTED #> GM[15], Quadrature. "Quadrature" GAME_QUADRATURE UNSUPPORTED #> GM[16], Trax. "Trax" GAME_TRAX UNSUPPORTED #> GM[17], Tantrix. "Tantrix" GAME_TANTRIX UNSUPPORTED #> GM[18], Amazons. "Amazons" GAME_AMAZONS 10 { 10 } white amazons_adjust_color_to_play amazons_is_game_over ABCDEFGHIJKLMNOPQRSTUVWXY reversed amazons_get_default_setup NULL amazons_is_legal_move amazons_play_move amazons_undo amazons_apply_changes amazons_add_dummy_move_entry amazons_format_move amazons_parse_move amazons_validate_board amazons_dump_board AmazonsMoveStackEntry 0.95 #> GM[19], Octi. "Octi" GAME_OCTI UNSUPPORTED #> GM[20], Gess. "Gess" GAME_GESS UNSUPPORTED = LAST_GAME } quarry-0.2.0/src/board/parse-game-list.c0000644000175000017500000001733210376452436016532 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "parse-list.h" #include "board-topology.h" #include "utils.h" #include #include #define CAPITALIZATION_HINT \ " /* TRANSLATORS: Use your language's natural capitalization for the\n" \ " name of the game. I.e. it doesn't have to start with a capital\n" \ " letter. */\n" static int game_list_parse_game1 (char **line); static int game_list_parse_game2 (StringBuffer *c_file_arrays, char **line, const char *identifier, char **pending_eol_comment, int *pending_linefeeds); static const ListDescription game_lists[] = { { "games", 0, SORT_NORMAL, 0, "const GameInfo ", NULL, game_list_parse_game1, game_list_parse_game2, NULL }, { NULL, 0, SORT_NORMAL, 0, NULL, NULL, NULL, NULL, NULL } }; const ListDescriptionSet list_set = { "games", game_lists }; static const char *game_full_name; int main (int argc, char *argv[]) { return parse_list_main (argc, argv, &list_set, 1, NULL); } static int game_list_parse_game1 (char **line) { PARSE_THING (game_full_name, STRING_OR_NULL, line, "game full name"); return 0; } static int game_list_parse_game2 (StringBuffer *c_file_arrays, char **line, const char *identifier, char **pending_eol_comment, int *pending_linefeeds) { const char *default_board_size; StringBuffer standard_board_sizes; const char *color_to_play_first; const char *adjust_color_to_play_function; const char *is_game_over_function; const char *horizontal_coordinates; int reversed_vertical_coordinates_flag; const char *get_default_setup_function; const char *reset_game_data_function; const char *is_legal_move_function; const char *play_move_function; const char *undo_function; const char *apply_changes_function; const char *add_dummy_move_entry_function; const char *format_move_function; const char *parse_move_function; const char *validate_board_function; const char *dump_board_function; const char *move_stack_entry_structure; const char *relative_num_moves_per_game; UNUSED (identifier); UNUSED (pending_eol_comment); UNUSED (pending_linefeeds); if (looking_at ("UNSUPPORTED", line)) { /* A special, but very common case. */ if (strcmp (game_full_name, "NULL") != 0) { string_buffer_cprintf (c_file_arrays, (" /* TRANSLATORS: Not important currently. */\n" CAPITALIZATION_HINT " { N_(%s), "), game_full_name); } else string_buffer_cat_string (c_file_arrays, " { NULL, "); string_buffer_cat_string (c_file_arrays, ("0, NULL, EMPTY, NULL,\n" " NULL,\n NULL, 0,\n NULL, NULL,\n" " NULL, NULL, NULL,\n NULL, NULL,\n" " NULL, NULL,\n NULL, NULL,\n" " 0, 0.0 }")); return 0; } PARSE_THING (default_board_size, INTEGER_NUMBER, line, "default board size"); string_buffer_init (&standard_board_sizes, 0x20, 0x20); if (looking_at ("{", line)) { while (!looking_at ("}", line)) { const char *board_size; PARSE_THING (board_size, INTEGER_NUMBER, line, "board size"); if (standard_board_sizes.length == 0) string_buffer_add_character (&standard_board_sizes, '"'); string_buffer_cat_string (&standard_board_sizes, board_size); string_buffer_cat_string (&standard_board_sizes, "\\000"); } if (standard_board_sizes.length > 0) string_buffer_add_character (&standard_board_sizes, '"'); } if (standard_board_sizes.length == 0) string_buffer_cat_string (&standard_board_sizes, "NULL"); if (looking_at ("black", line)) color_to_play_first = "BLACK"; else if (looking_at ("white", line)) color_to_play_first = "WHITE"; else { print_error ("color to play first expected"); return 1; } PARSE_IDENTIFIER (adjust_color_to_play_function, line, "adjust_color_to_play function"); PARSE_IDENTIFIER (is_game_over_function, line, "is_game_over function"); PARSE_IDENTIFIER (horizontal_coordinates, line, "horizontal coordinates"); if (strlen (horizontal_coordinates) > BOARD_MAX_WIDTH) { print_error ("too many horizontal coordinates (%d)", strlen (horizontal_coordinates)); return 1; } if (looking_at ("normal", line)) reversed_vertical_coordinates_flag = 0; else if (looking_at ("reversed", line)) reversed_vertical_coordinates_flag = 1; else { print_error ("reversed vertical coordinates flag expected"); return 1; } PARSE_IDENTIFIER (get_default_setup_function, line, "get_default_setup function"); PARSE_IDENTIFIER (reset_game_data_function, line, "reset_game_data function"); PARSE_IDENTIFIER (is_legal_move_function, line, "is_legal_move function"); PARSE_IDENTIFIER (play_move_function, line, "play_move function"); PARSE_IDENTIFIER (undo_function, line, "undo function"); PARSE_IDENTIFIER (apply_changes_function, line, "apply_changes function"); PARSE_IDENTIFIER (add_dummy_move_entry_function, line, "add_dummy_move_entry function"); PARSE_IDENTIFIER (format_move_function, line, "format_move function"); PARSE_IDENTIFIER (parse_move_function, line, "parse_move function"); PARSE_IDENTIFIER (validate_board_function, line, "validate_board function"); PARSE_IDENTIFIER (dump_board_function, line, "dump_board function"); PARSE_IDENTIFIER (move_stack_entry_structure, line, "MoveStackEntry structure"); PARSE_THING (relative_num_moves_per_game, FLOATING_POINT_NUMBER, line, "relative number of moves per game"); string_buffer_cprintf (c_file_arrays, (CAPITALIZATION_HINT " { N_(%s), %s, %s, %s, %s,\n %s,\n" " \"%s\", %d,\n %s, %s,\n %s, %s, %s,\n" " %s, %s,\n %s, %s,\n %s, %s,\n" " sizeof (%s), %s }"), game_full_name, default_board_size, standard_board_sizes.string, color_to_play_first, adjust_color_to_play_function, is_game_over_function, horizontal_coordinates, reversed_vertical_coordinates_flag, get_default_setup_function, reset_game_data_function, is_legal_move_function, play_move_function, undo_function, apply_changes_function, add_dummy_move_entry_function, format_move_function, parse_move_function, validate_board_function, dump_board_function, move_stack_entry_structure, relative_num_moves_per_game); string_buffer_dispose (&standard_board_sizes); return 0; } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/sgf/0000755000175000017500000000000010530402570013040 5ustar bartbartquarry-0.2.0/src/sgf/Makefile.in0000644000175000017500000004774210425150133015121 0ustar bartbart# Makefile.in generated by automake 1.7.9 from Makefile.am. # @configure_input@ # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 # Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # Process this file with Automake to produce `Makefile.in'. srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = ../.. am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : host_triplet = @host@ ACLOCAL = @ACLOCAL@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BUILD_SGF_UTILS_FALSE = @BUILD_SGF_UTILS_FALSE@ BUILD_SGF_UTILS_TRUE = @BUILD_SGF_UTILS_TRUE@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DO_SCROLLKEEPER_UPDATE_FALSE = @DO_SCROLLKEEPER_UPDATE_FALSE@ DO_SCROLLKEEPER_UPDATE_TRUE = @DO_SCROLLKEEPER_UPDATE_TRUE@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ GMSGFMT = @GMSGFMT@ HAVE_SCROLLKEEPER_FALSE = @HAVE_SCROLLKEEPER_FALSE@ HAVE_SCROLLKEEPER_TRUE = @HAVE_SCROLLKEEPER_TRUE@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ LDFLAGS = @LDFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ MAKEINFO = @MAKEINFO@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGMERGE = @MSGMERGE@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSUB = @POSUB@ QUARRY_GTHREAD_CFLAGS = @QUARRY_GTHREAD_CFLAGS@ QUARRY_GTHREAD_LIBS = @QUARRY_GTHREAD_LIBS@ QUARRY_GTK_CFLAGS = @QUARRY_GTK_CFLAGS@ QUARRY_GTK_DEPRECATED_FLAGS = @QUARRY_GTK_DEPRECATED_FLAGS@ QUARRY_GTK_LIBS = @QUARRY_GTK_LIBS@ QUARRY_WARNINGS = @QUARRY_WARNINGS@ QUARRY_WARNINGS_GTK = @QUARRY_WARNINGS_GTK@ RANLIB = @RANLIB@ REGISTER_MIME_TYPES_FALSE = @REGISTER_MIME_TYPES_FALSE@ REGISTER_MIME_TYPES_TRUE = @REGISTER_MIME_TYPES_TRUE@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ ac_ct_CC = @ac_ct_CC@ ac_ct_RANLIB = @ac_ct_RANLIB@ ac_ct_STRIP = @ac_ct_STRIP@ ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ datadir = @datadir@ exec_prefix = @exec_prefix@ have_scrollkeeper = @have_scrollkeeper@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localstatedir = @localstatedir@ mandir = @mandir@ oldincludedir = @oldincludedir@ prefix = @prefix@ program_transform_name = @program_transform_name@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ AM_CPPFLAGS = \ $(QUARRY_WARNINGS) \ \ -I $(top_srcdir)/src \ -I $(top_srcdir)/src/board \ -I $(top_builddir)/src/board \ -I $(top_srcdir)/src/utils noinst_LIBRARIES = libsgf.a LIST_FILES = \ sgf-errors.list \ sgf-properties.list \ sgf-undo-operations.list PARSE_LIST_COMMAND = ./parse-sgf-list$(EXEEXT) PARSE_LIST_FLAGS = SUFFIXES = .list .h # `LIST_FILES' must be set by the includer. The includer can use # `LIST_STAMP_FILES' and `LIST_GENERATED_FILES' and assume they are # set just as here. # LIST_STAMP_FILES = $(LIST_FILES:.list=.stamp) LIST_GENERATED_FILES = $(LIST_FILES:.list=.c) $(LIST_FILES:.list=.h) # `PARSE_LIST_COMMAND' and `PARSE_LIST_FLAGS' should be set by the # includer. # PARSE_LIST = $(PARSE_LIST_COMMAND) $(PARSE_LIST_FLAGS) # We use `cmp' here to avoid unneeded recompilations of files that # depend on generated ones (only really useful for `.h' files.) # PARSE_LIST_BUILD_RULE = \ if $(PARSE_LIST) `test -f '$<' || echo '$(srcdir)/'`$< \ $*.h.new $*.c.new; then \ if cmp -s $*.c.new $*.c; \ then rm -f $*.c.new; else mv -f $*.c.new $*.c; \ fi; \ if cmp -s $*.h.new $*.h; \ then rm -f $*.h.new; else mv -f $*.h.new $*.h; \ fi; \ echo timestamp > $@; \ else \ (rm -f $*.c $*.c.new $*.h $*.h.new ; exit 1) \ fi libsgf_a_SOURCES = \ sgf-diff-utils.c \ sgf-parser.c \ sgf-tree.c \ sgf-tree-map.c \ sgf-undo.c \ sgf-utils.c \ sgf-writer.c \ \ sgf.h \ sgf-parser.h \ sgf-privates.h \ sgf-undo.h \ sgf-writer.h \ \ $(LIST_FILES) nodist_libsgf_a_SOURCES = $(LIST_GENERATED_FILES) BUILT_SOURCES = $(LIST_STAMP_FILES) noinst_PROGRAMS = parse-sgf-list parse_sgf_list_SOURCES = parse-sgf-list.c parse_sgf_list_LDADD = \ $(top_builddir)/src/utils/libparselist.a \ $(top_builddir)/src/utils/libutils.a # `sgf-diff' can be made optional with `configure'. EXTRA_PROGRAMS = \ sgf-diff \ sgf-test @BUILD_SGF_UTILS_FALSE@bin_PROGRAMS = @BUILD_SGF_UTILS_TRUE@bin_PROGRAMS = sgf-diff sgf_diff_SOURCES = sgf-diff.c sgf_diff_LDADD = \ libsgf.a \ $(top_builddir)/src/board/libboard.a \ $(top_builddir)/src/utils/libutils.a sgf_test_SOURCES = sgf-test.c sgf_test_LDADD = \ libsgf.a \ $(top_builddir)/src/board/libboard.a \ $(top_builddir)/src/utils/libutils.a DISTCLEANFILES = *~ CLEANFILES = $(EXTRA_PROGRAMS) MOSTLYCLEANFILES = \ $(LIST_STAMP_FILES) \ $(LIST_GENERATED_FILES) subdir = src/sgf ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 mkinstalldirs = $(SHELL) $(top_srcdir)/build/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = LIBRARIES = $(noinst_LIBRARIES) libsgf_a_AR = $(AR) cru libsgf_a_LIBADD = am__objects_1 = am_libsgf_a_OBJECTS = sgf-diff-utils.$(OBJEXT) sgf-parser.$(OBJEXT) \ sgf-tree.$(OBJEXT) sgf-tree-map.$(OBJEXT) sgf-undo.$(OBJEXT) \ sgf-utils.$(OBJEXT) sgf-writer.$(OBJEXT) $(am__objects_1) am__objects_2 = sgf-errors.$(OBJEXT) sgf-properties.$(OBJEXT) \ sgf-undo-operations.$(OBJEXT) am__objects_3 = $(am__objects_2) $(am__objects_1) nodist_libsgf_a_OBJECTS = $(am__objects_3) libsgf_a_OBJECTS = $(am_libsgf_a_OBJECTS) $(nodist_libsgf_a_OBJECTS) EXTRA_PROGRAMS = sgf-diff$(EXEEXT) sgf-test$(EXEEXT) @BUILD_SGF_UTILS_TRUE@bin_PROGRAMS = sgf-diff$(EXEEXT) @BUILD_SGF_UTILS_FALSE@bin_PROGRAMS = noinst_PROGRAMS = parse-sgf-list$(EXEEXT) PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS) am_parse_sgf_list_OBJECTS = parse-sgf-list.$(OBJEXT) parse_sgf_list_OBJECTS = $(am_parse_sgf_list_OBJECTS) parse_sgf_list_DEPENDENCIES = $(top_builddir)/src/utils/libparselist.a \ $(top_builddir)/src/utils/libutils.a parse_sgf_list_LDFLAGS = am_sgf_diff_OBJECTS = sgf-diff.$(OBJEXT) sgf_diff_OBJECTS = $(am_sgf_diff_OBJECTS) sgf_diff_DEPENDENCIES = libsgf.a $(top_builddir)/src/board/libboard.a \ $(top_builddir)/src/utils/libutils.a sgf_diff_LDFLAGS = am_sgf_test_OBJECTS = sgf-test.$(OBJEXT) sgf_test_OBJECTS = $(am_sgf_test_OBJECTS) sgf_test_DEPENDENCIES = libsgf.a $(top_builddir)/src/board/libboard.a \ $(top_builddir)/src/utils/libutils.a sgf_test_LDFLAGS = DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/build/depcomp am__depfiles_maybe = depfiles @AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/parse-sgf-list.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/sgf-diff-utils.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/sgf-diff.Po ./$(DEPDIR)/sgf-errors.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/sgf-parser.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/sgf-properties.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/sgf-test.Po ./$(DEPDIR)/sgf-tree-map.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/sgf-tree.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/sgf-undo-operations.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/sgf-undo.Po ./$(DEPDIR)/sgf-utils.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/sgf-writer.Po COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ DIST_SOURCES = $(libsgf_a_SOURCES) $(parse_sgf_list_SOURCES) \ $(sgf_diff_SOURCES) $(sgf_test_SOURCES) DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/build/list.make \ Makefile.am SOURCES = $(libsgf_a_SOURCES) $(nodist_libsgf_a_SOURCES) $(parse_sgf_list_SOURCES) $(sgf_diff_SOURCES) $(sgf_test_SOURCES) all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: .list .h .c .o .obj .stamp $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/build/list.make $(top_srcdir)/configure.ac $(ACLOCAL_M4) cd $(top_srcdir) && \ $(AUTOMAKE) --foreign src/sgf/Makefile Makefile: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) AR = ar clean-noinstLIBRARIES: -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) libsgf.a: $(libsgf_a_OBJECTS) $(libsgf_a_DEPENDENCIES) -rm -f libsgf.a $(libsgf_a_AR) libsgf.a $(libsgf_a_OBJECTS) $(libsgf_a_LIBADD) $(RANLIB) libsgf.a binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) $(mkinstalldirs) $(DESTDIR)$(bindir) @list='$(bin_PROGRAMS)'; for p in $$list; do \ p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ if test -f $$p \ ; then \ f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ echo " $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) $$p $(DESTDIR)$(bindir)/$$f"; \ $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) $$p $(DESTDIR)$(bindir)/$$f || exit 1; \ else :; fi; \ done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; for p in $$list; do \ f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ echo " rm -f $(DESTDIR)$(bindir)/$$f"; \ rm -f $(DESTDIR)$(bindir)/$$f; \ done clean-binPROGRAMS: -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) clean-noinstPROGRAMS: -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS) parse-sgf-list$(EXEEXT): $(parse_sgf_list_OBJECTS) $(parse_sgf_list_DEPENDENCIES) @rm -f parse-sgf-list$(EXEEXT) $(LINK) $(parse_sgf_list_LDFLAGS) $(parse_sgf_list_OBJECTS) $(parse_sgf_list_LDADD) $(LIBS) sgf-diff$(EXEEXT): $(sgf_diff_OBJECTS) $(sgf_diff_DEPENDENCIES) @rm -f sgf-diff$(EXEEXT) $(LINK) $(sgf_diff_LDFLAGS) $(sgf_diff_OBJECTS) $(sgf_diff_LDADD) $(LIBS) sgf-test$(EXEEXT): $(sgf_test_OBJECTS) $(sgf_test_DEPENDENCIES) @rm -f sgf-test$(EXEEXT) $(LINK) $(sgf_test_LDFLAGS) $(sgf_test_OBJECTS) $(sgf_test_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) core *.core distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parse-sgf-list.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sgf-diff-utils.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sgf-diff.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sgf-errors.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sgf-parser.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sgf-properties.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sgf-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sgf-tree-map.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sgf-tree.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sgf-undo-operations.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sgf-undo.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sgf-utils.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sgf-writer.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ @am__fastdepCC_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ @am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ @am__fastdepCC_TRUE@ fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `test -f '$<' || echo '$(srcdir)/'`$< .c.obj: @am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ @am__fastdepCC_TRUE@ -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi`; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ @am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ @am__fastdepCC_TRUE@ fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi` uninstall-info-am: ETAGS = etags ETAGSFLAGS = CTAGS = ctags CTAGSFLAGS = tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(ETAGS_ARGS)$$tags$$unique" \ || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = ../.. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) $(mkinstalldirs) $(distdir)/../../build @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ case $$file in \ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ esac; \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ dir="/$$dir"; \ $(mkinstalldirs) "$(distdir)$$dir"; \ else \ dir=''; \ fi; \ if test -d $$d/$$file; then \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-am all-am: Makefile $(LIBRARIES) $(PROGRAMS) installdirs: $(mkinstalldirs) $(DESTDIR)$(bindir) install: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -rm -f $(CONFIG_CLEAN_FILES) -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) clean: clean-am clean-am: clean-binPROGRAMS clean-generic clean-noinstLIBRARIES \ clean-noinstPROGRAMS mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: info: info-am info-am: install-data-am: install-exec-am: install-binPROGRAMS install-info: install-info-am install-man: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-info-am .PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ clean-generic clean-noinstLIBRARIES clean-noinstPROGRAMS ctags \ distclean distclean-compile distclean-generic distclean-tags \ distdir dvi dvi-am info info-am install install-am \ install-binPROGRAMS install-data install-data-am install-exec \ install-exec-am install-info install-info-am install-man \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \ tags uninstall uninstall-am uninstall-binPROGRAMS \ uninstall-info-am # Avoid problems with parallel builds. sgf-errors.c: sgf-errors.h sgf-properties.c: sgf-properties.h sgf-undo-operations.c: sgf-undo-operations.h # Make everything depend on the `Makefile' and the list parser. $(LIST_STAMP_FILES) : Makefile $(PARSE_LIST_COMMAND) .list.stamp: $(PARSE_LIST_BUILD_RULE) # Since $(LIST_GENERATED_FILES) defined by the includer don't (at # least shouldn't) have any dependencies, if this rule is being # executed, it probably means that one of the files was removed. # Then all we can do is to force rebuilding of corresponding stamp # file, which builds the required sources ``by side-effect.'' # $(LIST_GENERATED_FILES): rm -f $*.stamp; $(MAKE) $(AM_MAKEFLAGS) $*.stamp # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: quarry-0.2.0/src/sgf/Makefile.am0000644000175000017500000000327010425150054015076 0ustar bartbart# Process this file with Automake to produce `Makefile.in'. AM_CPPFLAGS = \ $(QUARRY_WARNINGS) \ \ -I $(top_srcdir)/src \ -I $(top_srcdir)/src/board \ -I $(top_builddir)/src/board \ -I $(top_srcdir)/src/utils noinst_LIBRARIES = libsgf.a LIST_FILES = \ sgf-errors.list \ sgf-properties.list \ sgf-undo-operations.list PARSE_LIST_COMMAND = ./parse-sgf-list$(EXEEXT) PARSE_LIST_FLAGS = # Avoid problems with parallel builds. sgf-errors.c: sgf-errors.h sgf-properties.c: sgf-properties.h sgf-undo-operations.c: sgf-undo-operations.h include $(top_srcdir)/build/list.make libsgf_a_SOURCES = \ sgf-diff-utils.c \ sgf-parser.c \ sgf-tree.c \ sgf-tree-map.c \ sgf-undo.c \ sgf-utils.c \ sgf-writer.c \ \ sgf.h \ sgf-parser.h \ sgf-privates.h \ sgf-undo.h \ sgf-writer.h \ \ $(LIST_FILES) nodist_libsgf_a_SOURCES = $(LIST_GENERATED_FILES) BUILT_SOURCES = $(LIST_STAMP_FILES) noinst_PROGRAMS = parse-sgf-list parse_sgf_list_SOURCES = parse-sgf-list.c parse_sgf_list_LDADD = \ $(top_builddir)/src/utils/libparselist.a \ $(top_builddir)/src/utils/libutils.a # `sgf-diff' can be made optional with `configure'. EXTRA_PROGRAMS = \ sgf-diff \ sgf-test if BUILD_SGF_UTILS bin_PROGRAMS = sgf-diff else bin_PROGRAMS = endif sgf_diff_SOURCES = sgf-diff.c sgf_diff_LDADD = \ libsgf.a \ $(top_builddir)/src/board/libboard.a \ $(top_builddir)/src/utils/libutils.a sgf_test_SOURCES = sgf-test.c sgf_test_LDADD = \ libsgf.a \ $(top_builddir)/src/board/libboard.a \ $(top_builddir)/src/utils/libutils.a DISTCLEANFILES = *~ CLEANFILES = $(EXTRA_PROGRAMS) MOSTLYCLEANFILES = \ $(LIST_STAMP_FILES) \ $(LIST_GENERATED_FILES) quarry-0.2.0/src/sgf/sgf-diff-utils.c0000644000175000017500000006465710367243247016065 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "sgf.h" #include "board.h" #include "utils.h" #include #include #include #include #define OUT_OF_GRAPH INT_MAX #define NUM_CONTEXT_TREES 1 #define CONTEXT_TREE_ROOT_DEPTH 3 #define NUM_CONTEXT_NODES 1 #define CONTEXT_NODE_DEPTH 2 #define NUM_TEXT_CONTEXT_LINES 3 typedef struct _TextLine TextLine; struct _TextLine { const char *string; int length; }; typedef struct _TextDiffData TextDiffData; struct _TextDiffData { int hunk_first_line_in_original; int hunk_first_line_in_modified; char *current_hunk; }; typedef struct _EditGraphDiagonal EditGraphDiagonal; typedef struct _EditGraphLayer EditGraphLayer; typedef struct _EditGraph EditGraph; struct _EditGraphDiagonal { const void *from_trace_element; const void *to_trace_element; int trace_x; }; struct _EditGraphLayer { EditGraphLayer *next; EditGraphLayer *previous; int path_diagonal; EditGraphDiagonal diagonals[1]; }; struct _EditGraph { int full_distance; EditGraphLayer *last_layer; }; typedef int (* ComparisonFunction) (const void *first_element, const void *second_element); typedef const void * (* GetNextElementFunction) (const void *element); static void build_abstract_edit_graph (EditGraph *edit_graph, const void *from_sequence, const void *to_sequence, int num_skipped_elements, ComparisonFunction are_equal, GetNextElementFunction get_next); static const EditGraphLayer * reconstruct_minimal_path (const EditGraph *edit_graph); static void edit_graph_dispose (EditGraph *edit_graph); static int game_trees_are_equal (const SgfGameTree *first_tree, const SgfGameTree *second_tree); static const SgfGameTree * get_next_game_tree (const SgfGameTree *tree); static void generate_sgf_collection_diff (const EditGraph *edit_graph, const SgfCollection *from_collection, const SgfCollection *to_collection, SgfCollection *difference); static void add_context_game_trees (const SgfGameTree *context_subsequence, int num_trees, SgfCollection *difference); static void build_node_layer_diff (const SgfNode *from_node_layer, const SgfNode *to_node_layer, SgfGameTree *tree, SgfNode *parent); static int generic_nodes_are_equal (const SgfNode *first_node, const SgfNode *second_node); static int amazons_nodes_are_equal (const SgfNode *first_node, const SgfNode *second_node); static int node_position_lists_are_equal (const SgfNode *first_node, const SgfNode *second_node, SgfType type); static const SgfNode * get_next_node (const SgfNode *node); static void generate_sgf_node_layer_diff (const EditGraph *edit_graph, const SgfNode *from_node_layer, const SgfNode *to_node_layer, SgfGameTree *tree, SgfNode *parent); #if 0 static TextLine * chop_text_into_lines (const char *text); static int text_lines_are_equal (const TextLine *first_text_line, const TextLine *second_text_line); static const TextLine * get_next_text_line (const TextLine *text_line); static char * do_generate_text_diff (const EditGraphLayer *layer, int layer_distance, int layer_diagonal, int is_last_layer, const TextLine *from_lines_sequence, const TextLine *to_lines_sequence, TextDiffData *data); static char * generate_text_diff (const EditGraph *edit_graph, const TextLine *from_lines_sequence, const TextLine *to_lines_sequence); #endif SgfCollection * sgf_diff (const SgfCollection *from_collection, const SgfCollection *to_collection) { EditGraph edit_graph; SgfCollection *difference = sgf_collection_new (); const SgfGameTree *from_tree_subsequence; const SgfGameTree *to_tree_subsequence; int num_skipped_trees; assert (from_collection); assert (to_collection); from_tree_subsequence = from_collection->first_tree; to_tree_subsequence = to_collection->first_tree; for (num_skipped_trees = 0; (from_tree_subsequence && to_tree_subsequence && game_trees_are_equal (from_tree_subsequence, to_tree_subsequence)); num_skipped_trees++) { from_tree_subsequence = from_tree_subsequence->next; to_tree_subsequence = to_tree_subsequence->next; } build_abstract_edit_graph (&edit_graph, from_tree_subsequence, to_tree_subsequence, num_skipped_trees, (ComparisonFunction) game_trees_are_equal, (GetNextElementFunction) get_next_game_tree); generate_sgf_collection_diff (&edit_graph, from_collection, to_collection, difference); edit_graph_dispose (&edit_graph); if (difference->num_trees > 0) return difference; sgf_collection_delete (difference); return NULL; } static void build_abstract_edit_graph (EditGraph *edit_graph, const void *from_sequence, const void *to_sequence, int num_skipped_elements, ComparisonFunction are_equal, GetNextElementFunction get_next) { EditGraphLayer *current_layer; int current_distance = 0; current_layer = utils_malloc (sizeof (EditGraphLayer)); current_layer->previous = NULL; current_layer->diagonals[0].from_trace_element = from_sequence; current_layer->diagonals[0].to_trace_element = to_sequence; current_layer->diagonals[0].trace_x = num_skipped_elements; if (!from_sequence && !to_sequence) { current_layer->next = NULL; current_layer->path_diagonal = 0; edit_graph->full_distance = 0; edit_graph->last_layer = current_layer; return; } while (1) { int k; EditGraphLayer *previous_layer = current_layer; current_distance++; current_layer = utils_malloc (sizeof (EditGraphLayer) + (current_distance * sizeof (EditGraphDiagonal))); current_layer->previous = previous_layer; previous_layer->next = current_layer; for (k = 0; k <= current_distance; k++) { const void *from_element; const void *to_element; int x; if (k == 0 || (k != current_distance && (previous_layer->diagonals[k].trace_x > previous_layer->diagonals[k - 1].trace_x))) { if (!previous_layer->diagonals[k].to_trace_element) { current_layer->diagonals[k].from_trace_element = NULL; current_layer->diagonals[k].to_trace_element = NULL; current_layer->diagonals[k].trace_x = OUT_OF_GRAPH; continue; } from_element = previous_layer->diagonals[k].from_trace_element; to_element = get_next (previous_layer->diagonals[k].to_trace_element); x = previous_layer->diagonals[k].trace_x; } else { if (!previous_layer->diagonals[k - 1].from_trace_element) { current_layer->diagonals[k].from_trace_element = NULL; current_layer->diagonals[k].to_trace_element = NULL; current_layer->diagonals[k].trace_x = OUT_OF_GRAPH; continue; } from_element = get_next (previous_layer->diagonals[k - 1].from_trace_element); to_element = previous_layer->diagonals[k - 1].to_trace_element; x = previous_layer->diagonals[k - 1].trace_x + 1; } while (from_element && to_element) { if (are_equal (from_element, to_element)) { from_element = get_next (from_element); to_element = get_next (to_element); x++; } else break; } current_layer->diagonals[k].from_trace_element = from_element; current_layer->diagonals[k].to_trace_element = to_element; current_layer->diagonals[k].trace_x = x; if (!from_element && !to_element) { current_layer->next = NULL; current_layer->path_diagonal = k; edit_graph->full_distance = current_distance; edit_graph->last_layer = current_layer; return; } } } } static const EditGraphLayer * reconstruct_minimal_path (const EditGraph *edit_graph) { const EditGraphLayer *layer = edit_graph->last_layer; int layer_distance = edit_graph->full_distance; while (layer_distance > 0) { EditGraphLayer *previous_layer = layer->previous; int path_diagonal = layer->path_diagonal; if (path_diagonal == 0 || (path_diagonal != layer_distance && (previous_layer->diagonals[path_diagonal].trace_x > previous_layer->diagonals[path_diagonal - 1].trace_x))) previous_layer->path_diagonal = path_diagonal; else previous_layer->path_diagonal = path_diagonal - 1; layer = previous_layer; layer_distance--; } return layer; } static void edit_graph_dispose (EditGraph *edit_graph) { EditGraphLayer *this_layer; EditGraphLayer *previous_layer; for (this_layer = edit_graph->last_layer; this_layer; this_layer = previous_layer) { previous_layer = this_layer->previous; utils_free (this_layer); } } /* FIXME: This function is way too forgiving. Make it stricter. */ static int game_trees_are_equal (const SgfGameTree *first_tree, const SgfGameTree *second_tree) { if (first_tree->game != second_tree->game || first_tree->board_width != second_tree->board_width || first_tree->board_height != second_tree->board_height) return 0; return (first_tree->game != GAME_AMAZONS ? generic_nodes_are_equal (first_tree->root, second_tree->root) : amazons_nodes_are_equal (first_tree->root, second_tree->root)); } static const SgfGameTree * get_next_game_tree (const SgfGameTree *tree) { return tree->next; } /* FIXME: Add hunk "headers" generation (needs standardization?). */ static void generate_sgf_collection_diff (const EditGraph *edit_graph, const SgfCollection *from_collection, const SgfCollection *to_collection, SgfCollection *difference) { const SgfGameTree *from_tree_subsequence = from_collection->first_tree; const SgfGameTree *to_tree_subsequence = to_collection->first_tree; const SgfGameTree *leading_context_subsequence = NULL; const EditGraphLayer *zero_layer = reconstruct_minimal_path (edit_graph); const EditGraphLayer *layer; int layer_distance; int x = 0; int num_leading_context_trees = 0; int num_traling_context_trees; for (layer = zero_layer, layer_distance = 0; layer; layer = layer->next, layer_distance++) { int trace_x = layer->diagonals[layer->path_diagonal].trace_x; if (layer_distance > 0) { add_context_game_trees (leading_context_subsequence, num_leading_context_trees, difference); if (layer->path_diagonal == layer->previous->path_diagonal) { /* A game tree got added. */ SgfGameTree *added_tree = sgf_game_tree_duplicate_with_nodes (to_tree_subsequence); /* FIXME: Add SGF property that shows that the game tree got * added (needs standardization?). */ sgf_collection_add_game_tree (difference, added_tree); to_tree_subsequence = to_tree_subsequence->next; } else { /* A game tree got deleted. */ SgfGameTree *deleted_tree = sgf_game_tree_duplicate_with_nodes (from_tree_subsequence); /* FIXME: Add SGF property that shows that the game tree got * deleted (needs standardization?). */ sgf_collection_add_game_tree (difference, deleted_tree); from_tree_subsequence = from_tree_subsequence->next; x++; } num_traling_context_trees = 0; } else num_traling_context_trees = NUM_CONTEXT_TREES; num_leading_context_trees = 0; while (x < trace_x) { SgfGameTree *tree_difference = sgf_game_tree_duplicate (from_tree_subsequence); build_node_layer_diff (from_tree_subsequence->root, to_tree_subsequence->root, tree_difference, NULL); if (tree_difference->root) { add_context_game_trees (leading_context_subsequence, num_leading_context_trees, difference); sgf_collection_add_game_tree (difference, tree_difference); num_leading_context_trees = 0; num_traling_context_trees = 0; } else { sgf_game_tree_delete (tree_difference); if (num_traling_context_trees < NUM_CONTEXT_TREES) { add_context_game_trees (from_tree_subsequence, 1, difference); num_traling_context_trees++; } else { if (num_leading_context_trees < NUM_CONTEXT_TREES) { if (num_leading_context_trees++ == 0) leading_context_subsequence = from_tree_subsequence; } else leading_context_subsequence = leading_context_subsequence->next; } } from_tree_subsequence = from_tree_subsequence->next; to_tree_subsequence = to_tree_subsequence->next; x++; } } } static void add_context_game_trees (const SgfGameTree *context_subsequence, int num_trees, SgfCollection *difference) { int k; for (k = 0; k < num_trees; k++, context_subsequence = context_subsequence->next) { SgfGameTree *context_tree = sgf_game_tree_duplicate (context_subsequence); context_tree->root = sgf_node_duplicate_to_given_depth (context_subsequence->root, context_tree, NULL, CONTEXT_TREE_ROOT_DEPTH); sgf_collection_add_game_tree (difference, context_tree); } } static void build_node_layer_diff (const SgfNode *from_node_layer, const SgfNode *to_node_layer, SgfGameTree *tree, SgfNode *parent) { EditGraph edit_graph; const ComparisonFunction nodes_are_equal = (ComparisonFunction) (tree->game != GAME_AMAZONS ? generic_nodes_are_equal : amazons_nodes_are_equal); const SgfNode *from_node_subsequence = from_node_layer; const SgfNode *to_node_subsequence = to_node_layer; int num_skipped_nodes; for (num_skipped_nodes = 0; (from_node_subsequence && to_node_subsequence && nodes_are_equal (from_node_subsequence, to_node_subsequence)); num_skipped_nodes++) { from_node_subsequence = from_node_subsequence->next; to_node_subsequence = to_node_subsequence->next; } build_abstract_edit_graph (&edit_graph, from_node_subsequence, to_node_subsequence, num_skipped_nodes, nodes_are_equal, (GetNextElementFunction) get_next_node); generate_sgf_node_layer_diff (&edit_graph, from_node_layer, to_node_layer, tree, parent); edit_graph_dispose (&edit_graph); } static int generic_nodes_are_equal (const SgfNode *first_node, const SgfNode *second_node) { if (first_node->move_color != second_node->move_color) return 0; if (IS_STONE (first_node->move_color)) return POINTS_ARE_EQUAL (first_node->move_point, second_node->move_point); else if (first_node->move_color == SETUP_NODE) { return (node_position_lists_are_equal (first_node, second_node, SGF_ADD_BLACK) && node_position_lists_are_equal (first_node, second_node, SGF_ADD_WHITE) && node_position_lists_are_equal (first_node, second_node, SGF_ADD_EMPTY)); } else { /* FIXME: What to do in this case? */ return 1; } } static int amazons_nodes_are_equal (const SgfNode *first_node, const SgfNode *second_node) { if (first_node->move_color != second_node->move_color) return 0; if (IS_STONE (first_node->move_color)) { return (POINTS_ARE_EQUAL (first_node->data.amazons.from, second_node->data.amazons.from) && POINTS_ARE_EQUAL (first_node->move_point, second_node->move_point) && POINTS_ARE_EQUAL (first_node->data.amazons.shoot_arrow_to, second_node->data.amazons.shoot_arrow_to)); } else if (first_node->move_color == SETUP_NODE) { return (node_position_lists_are_equal (first_node, second_node, SGF_ADD_BLACK) && node_position_lists_are_equal (first_node, second_node, SGF_ADD_WHITE) && node_position_lists_are_equal (first_node, second_node, SGF_ADD_EMPTY) && node_position_lists_are_equal (first_node, second_node, SGF_ADD_ARROWS)); } else { /* FIXME: What to do in this case? */ return 1; } } static int node_position_lists_are_equal (const SgfNode *first_node, const SgfNode *second_node, SgfType type) { const BoardPositionList *first_position_list = sgf_node_get_list_of_point_property_value (first_node, type); const BoardPositionList *second_position_list = sgf_node_get_list_of_point_property_value (second_node, type); if (first_position_list && second_position_list) { return board_position_lists_are_equal (first_position_list, second_position_list); } return first_position_list == NULL && second_position_list == NULL; } static const SgfNode * get_next_node (const SgfNode *node) { return node->next; } static void generate_sgf_node_layer_diff (const EditGraph *edit_graph, const SgfNode *from_node_layer, const SgfNode *to_node_layer, SgfGameTree *tree, SgfNode *parent) { SgfNode **link = (parent ? &parent->child : &tree->root); const SgfNode *leading_context_subsequence = NULL; const EditGraphLayer *zero_layer = reconstruct_minimal_path (edit_graph); const EditGraphLayer *layer; int layer_distance; int x = 0; int num_leading_context_nodes = 0; int num_traling_context_nodes; for (layer = zero_layer, layer_distance = 0; layer; layer = layer->next, layer_distance++) { int k; int trace_x = layer->diagonals[layer->path_diagonal].trace_x; if (layer_distance > 0) { for (k = 0; k < num_leading_context_nodes; k++) { *link = sgf_node_duplicate_to_given_depth (leading_context_subsequence, tree, parent, CONTEXT_NODE_DEPTH); link = & (*link)->next; leading_context_subsequence = leading_context_subsequence->next; } if (layer->path_diagonal == layer->previous->path_diagonal) { /* A node got added. * * FIXME: Add SGF property that shows that the node got added * (needs standardization?). */ *link = sgf_node_duplicate_recursively (to_node_layer, tree, parent); to_node_layer = to_node_layer->next; } else { /* A node got deleted. * * FIXME: Add SGF property that shows that the node got deleted * (needs standardization?). */ *link = sgf_node_duplicate_recursively (from_node_layer, tree, parent); from_node_layer = from_node_layer->next; x++; } num_traling_context_nodes = 0; } else num_traling_context_nodes = NUM_CONTEXT_NODES; num_leading_context_nodes = 0; while (x < trace_x) { int is_context_node = 1; if (from_node_layer->child || to_node_layer->child) { SgfNode *node_difference = sgf_node_duplicate (from_node_layer, tree, parent); build_node_layer_diff (from_node_layer->child, to_node_layer->child, tree, node_difference); if (node_difference->child) { for (k = 0; k < num_leading_context_nodes; k++) { *link = sgf_node_duplicate_to_given_depth (leading_context_subsequence, tree, parent, CONTEXT_NODE_DEPTH); link = & (*link)->next; leading_context_subsequence = leading_context_subsequence->next; } *link = node_difference; link = &node_difference->next; num_leading_context_nodes = 0; num_traling_context_nodes = 0; is_context_node = 0; } else sgf_node_delete (node_difference, tree); } if (is_context_node) { if (num_traling_context_nodes < NUM_CONTEXT_NODES) { *link = sgf_node_duplicate_to_given_depth (from_node_layer, tree, parent, CONTEXT_NODE_DEPTH); link = & (*link)->next; num_traling_context_nodes++; } else { if (num_leading_context_nodes < NUM_CONTEXT_TREES) { if (num_leading_context_nodes++ == 0) leading_context_subsequence = from_node_layer; } else leading_context_subsequence = leading_context_subsequence->next; } } from_node_layer = from_node_layer->next; to_node_layer = to_node_layer->next; x++; } } } #if 0 static TextLine * chop_text_into_lines (const char *text) { TextLine *lines = NULL; int num_allocated_lines = 0; int num_lines = 0; while (1) { const char *line_end = strchr (text, '\n'); if (num_lines + 2 > num_allocated_lines) { num_allocated_lines += 20; lines = utils_realloc (lines, num_allocated_lines * sizeof (TextLine)); } lines[num_lines].string = text; if (line_end) { lines[num_lines++].length = line_end - text; text = line_end + 1; } else { lines[num_lines++].length = strlen (text); break; } } lines[num_lines].string = NULL; return lines; } static int text_lines_are_equal (const TextLine *first_text_line, const TextLine *second_text_line) { return (first_text_line->length == second_text_line->length && (strncmp (first_text_line->string, second_text_line->string, first_text_line->length) == 0)); } static const TextLine * get_next_text_line (const TextLine *text_line) { if ((text_line + 1)->string != NULL) return text_line + 1; return NULL; } static char * generate_text_diff (const EditGraph *edit_graph, const TextLine *from_lines_sequence, const TextLine *to_lines_sequence) { TextDiffData data; return do_generate_text_diff (edit_graph->last_layer, edit_graph->full_distance, /* edit_graph->last_layer_diagonal */ 0, 1, from_lines_sequence, to_lines_sequence, &data); } /* Recursively generate unified text diff based on given edit graph * layer. * * FIXME: It doesn't work at all after the change of the EditGraph * structure (or rather generate_text_diff() does not). * * FIXME: Speed this function up by first calculating the diff size * and only then copying strings. */ static char * do_generate_text_diff (const EditGraphLayer *layer, int layer_distance, int layer_diagonal, int last_layer, const TextLine *from_lines_sequence, const TextLine *to_lines_sequence, TextDiffData *data) { int k; int first_line_index; int last_snake_line_index = layer->diagonals[layer_diagonal].trace_x; char *difference; if (layer_distance) { const EditGraphLayer *previous_layer = layer->previous; int first_snake_line_index; if (layer_diagonal == 0 || (layer_diagonal != layer_distance && (previous_layer->diagonals[layer_diagonal].trace_x > previous_layer->diagonals[layer_diagonal - 1].trace_x))) { int added_line_index = (previous_layer->diagonals[layer_diagonal].trace_x - (2 * layer_diagonal - layer_distance) - 1); difference = do_generate_text_diff (previous_layer, layer_distance - 1, layer_diagonal, 0, from_lines_sequence, to_lines_sequence, data); data->current_hunk = utils_cat_as_strings (data->current_hunk, "+", 1, to_lines_sequence[added_line_index].string, to_lines_sequence[added_line_index].length, "\n", 1, NULL); first_snake_line_index = previous_layer->diagonals[layer_diagonal].trace_x; } else { int deleted_line_index = previous_layer->diagonals[layer_diagonal - 1].trace_x; difference = do_generate_text_diff (previous_layer, layer_distance - 1, layer_diagonal - 1, 0, from_lines_sequence, to_lines_sequence, data); data->current_hunk = utils_cat_as_strings (data->current_hunk, "-", 1, from_lines_sequence[deleted_line_index].string, from_lines_sequence[deleted_line_index].length, "\n", 1, NULL); first_snake_line_index = deleted_line_index + 1; } if ((last_snake_line_index - first_snake_line_index > 2 * NUM_TEXT_CONTEXT_LINES) || last_layer) { char buffer[64]; int length; int last_hunk_line_index = (first_snake_line_index + NUM_TEXT_CONTEXT_LINES); int trace_y_adjustment = 2 * layer_diagonal - layer_distance; if (last_hunk_line_index > last_snake_line_index) last_hunk_line_index = last_snake_line_index; length = utils_ncprintf (buffer, sizeof buffer, "@@ -%d,%d +%d,%d @@\n", data->hunk_first_line_in_original + 1, (last_hunk_line_index - data->hunk_first_line_in_original), data->hunk_first_line_in_modified + 1, ((last_hunk_line_index - trace_y_adjustment) - data->hunk_first_line_in_modified)); if (difference) difference = utils_cat_as_string (difference, buffer, length); else difference = utils_duplicate_as_string (buffer, length); difference = utils_cat_string (difference, data->current_hunk); utils_free (data->current_hunk); for (k = first_snake_line_index; k < last_hunk_line_index; k++) { difference = utils_cat_as_strings (difference, " ", 1, from_lines_sequence[k].string, from_lines_sequence[k].length, "\n", 1, NULL); } if (last_layer) return difference; first_line_index = last_snake_line_index - NUM_TEXT_CONTEXT_LINES; data->hunk_first_line_in_original = first_line_index; data->hunk_first_line_in_modified = (first_line_index - trace_y_adjustment); data->current_hunk = NULL; } else first_line_index = first_snake_line_index; } else { difference = NULL; first_line_index = last_snake_line_index - NUM_TEXT_CONTEXT_LINES; if (first_line_index < 0) first_line_index = 0; data->hunk_first_line_in_original = first_line_index; data->hunk_first_line_in_modified = first_line_index; data->current_hunk = NULL; } for (k = first_line_index; k < last_snake_line_index; k++) { data->current_hunk = utils_cat_as_strings (data->current_hunk, " ", 1, from_lines_sequence[k].string, from_lines_sequence[k].length, "\n", 1, NULL); } return difference; } #endif /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/sgf/sgf-parser.c0000644000175000017500000025625010453263175015301 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* This SGF parser is monstrously large, but since it is already * written and it is good, there's no point in throwing it out ;) * * The parser provides the following features: * * - Full support of SGF 1--4 (SGF 1--3 files are upgraded to SGF 4). * * - Robustness: can handle many erroneous files. * * - Quite complete error checking: use it to test your SGF writer. * * - No limits on any string lengths (be that text property value or * property identifier) except those imposed by memory availability. * * - High parsing speed (if anyone out there has huge SGF files...) * * - Reading of input file in chunks: smaller memory footprint (again, * noticeable on huge files only). * * - Thread safety; simple progress/cancellation interface (must be * matched with support at higher levels). */ /* FIXME: add more comments, especially in tricky/obscure places. */ #include "sgf.h" #include "sgf-parser.h" #include "sgf-errors.h" #include "sgf-privates.h" #include "board.h" #include "game-info.h" #include "utils.h" #include #include #include #include #include #include #include #ifdef HAVE_MEMORY_H #include #endif #define SGF_END 0 /* SGF specification remains silent about escaping in non-text * properties, but `SGFC' allows escaping in them. Function * next_token_in_value() provides transparent escaping. In order to * avoid premature end of value parsing, escaped ']' is replaced with * the below character, which is never returned by next_character(). */ #define ESCAPED_BRACKET '\r' typedef struct _BufferPositionStorage BufferPositionStorage; struct _BufferPositionStorage { char token; int line; int column; int pending_column; }; #define STORE_BUFFER_POSITION(data, index, storage) \ do { \ (data)->stored_buffer_pointers[index] = (data)->buffer_pointer; \ (storage).token = (data)->token; \ (storage).line = (data)->line; \ (storage).column = (data)->column; \ (storage).pending_column = (data)->pending_column; \ } while (0) #define RESTORE_BUFFER_POSITION(data, index, storage) \ do { \ (data)->buffer_pointer = (data)->stored_buffer_pointers[index]; \ (data)->token = (storage).token; \ (data)->line = (storage).line; \ (data)->column = (storage).column; \ (data)->pending_column = (storage).pending_column; \ } while (0) #define STORE_ERROR_POSITION(data, storage) \ do { \ (storage).line = (data)->line; \ (storage).column = (data)->column; \ (storage).notch = (data)->error_list->last; \ } while (0) static int parse_buffer (SgfParsingData *data, SgfCollection **collection, SgfErrorList **error_list, const SgfParserParameters *parameters, int *bytes_parsed, const int *cancellation_flag); static int parse_root (SgfParsingData *data); static SgfNode * parse_node_tree (SgfParsingData *data, SgfNode *parent); static void parse_node_sequence (SgfParsingData *data, SgfNode *node); static void parse_property (SgfParsingData *data); static void refresh_buffer (SgfParsingData *data); static void expand_buffer (SgfParsingData *data); static int complete_node_and_update_board (SgfParsingData *data, int is_leaf_node); static void create_position_lists (SgfParsingData *data, BoardPositionList **position_list, const SgfType *property_types, int num_properties, const unsigned int marked_positions[BOARD_GRID_SIZE], unsigned int current_mark); static void discard_single_value (SgfParsingData *data); static void discard_values (SgfParsingData *data); static void parse_unknown_property_values (SgfParsingData *data, StringList *property_value_list); static int do_parse_number (SgfParsingData *data, int *number); static int do_parse_real (SgfParsingData *data, double *real); inline static int do_parse_color (SgfParsingData *data); static char * do_parse_simple_text (SgfParsingData *data, char extra_stop_character); static char * do_parse_text (SgfParsingData *data, char *existing_text); static char * convert_text_to_utf8 (SgfParsingData *data, char *existing_text); static int do_parse_point (SgfParsingData *data, BoardPoint *point); static SgfError do_parse_go_move (SgfParsingData *data); static SgfError do_parse_reversi_move (SgfParsingData *data); static SgfError do_parse_amazons_move (SgfParsingData *data); inline static int do_parse_point_or_rectangle (SgfParsingData *data, BoardPoint *left_top, BoardPoint *right_bottom); static int do_parse_list_of_point (SgfParsingData *data, unsigned int marked_positions[BOARD_GRID_SIZE], unsigned int current_mark, int value, SgfError duplication_error, const char match_grid[BOARD_GRID_SIZE]); static int do_parse_board_size (SgfParsingData *data, int *width, int *height, int add_errors); static int looking_at (SgfParsingData *data, const char **strings, int num_strings); static void add_error (SgfParsingData *data, SgfError error, ...); static void insert_error (SgfParsingData *data, SgfError error, SgfErrorPosition *error_position, ...); static void insert_error_valist (SgfParsingData *data, SgfError error, SgfErrorPosition *error_position, va_list arguments); static SgfError invalid_game_info_property (SgfParsingData *data, SgfProperty *property, BufferPositionStorage *storage); inline static void begin_parsing_value (SgfParsingData *data); static int is_composed_value (SgfParsingData *data, int expecting_simple_text); static SgfError end_parsing_value (SgfParsingData *data); static void format_error_valist (SgfParsingData *data, StringBuffer *buffer, SgfError error, va_list arguments); inline static void next_token (SgfParsingData *data); static void next_token_in_value (SgfParsingData *data); static void next_character (SgfParsingData *data); const SgfParserParameters sgf_parser_defaults = { 4 * 1024 * 1024, 64 * 1024, 1024 * 1024, 0 }; /* Read an SGF file and parse all game trees it contains. If the * maximum buffer size specified in `parameters' is not enough to keep * the whole file in memory, this function sets up data required for * refreshing the buffer. */ int sgf_parse_file (const char *filename, SgfCollection **collection, SgfErrorList **error_list, const SgfParserParameters *parameters, int *file_size, int *bytes_parsed, const int *cancellation_flag) { int result; FILE *file; assert (filename); assert (collection); assert (error_list); assert (parameters); /* Buffer size parameters should be sane. */ assert (parameters->max_buffer_size >= 512 * 1024); assert (parameters->buffer_size_increment >= 256 * 1024); assert (parameters->buffer_refresh_margin >= 1024); assert (8 * parameters->buffer_refresh_margin <= parameters->max_buffer_size); *collection = NULL; *error_list = NULL; result = SGF_ERROR_READING_FILE; file = fopen (filename, "rb"); if (file) { if (fseek (file, 0, SEEK_END) != -1) { SgfParsingData parsing_data; int max_buffer_size = ROUND_UP (parameters->max_buffer_size, 4 * 1024); int local_file_size; int buffer_size; char *buffer; local_file_size = ftell (file); if (local_file_size == 0) { fclose (file); return SGF_INVALID_FILE; } if (file_size) *file_size = local_file_size; rewind (file); if (local_file_size <= max_buffer_size) buffer_size = local_file_size; else buffer_size = max_buffer_size; buffer = utils_malloc (buffer_size); if (fread (buffer, buffer_size, 1, file) == 1) { parsing_data.buffer = buffer; parsing_data.buffer_end = buffer + buffer_size; parsing_data.buffer_size = buffer_size; parsing_data.file_bytes_remaining = local_file_size - buffer_size; if (local_file_size <= max_buffer_size) parsing_data.buffer_refresh_point = parsing_data.buffer_end; else { parsing_data.buffer_size_increment = ROUND_UP (parameters->buffer_size_increment, 4 * 1024); parsing_data.buffer_refresh_margin = ROUND_UP (parameters->buffer_refresh_margin, 1024); parsing_data.buffer_refresh_point = parsing_data.buffer_end - parsing_data.buffer_refresh_margin; parsing_data.file = file; } result = parse_buffer (&parsing_data, collection, error_list, parameters, bytes_parsed, cancellation_flag); } utils_free (parsing_data.buffer); } fclose (file); } return result; } /* Parse SGF data in a buffer and creates a game collection from it. * In case of errors it returns NULL. * * Note that the data in buffer is overwritten in process, at least * partially. */ int sgf_parse_buffer (char *buffer, int size, SgfCollection **collection, SgfErrorList **error_list, const SgfParserParameters *parameters, int *bytes_parsed, const int *cancellation_flag) { SgfParsingData parsing_data; assert (buffer); assert (size >= 0); assert (collection); assert (error_list); assert (parameters); parsing_data.buffer = buffer; parsing_data.buffer_refresh_point = buffer + size; parsing_data.buffer_end = buffer + size; parsing_data.file_bytes_remaining = 0; return parse_buffer (&parsing_data, collection, error_list, parameters, bytes_parsed, cancellation_flag); } static int parse_buffer (SgfParsingData *data, SgfCollection **collection, SgfErrorList **error_list, const SgfParserParameters *parameters, int *bytes_parsed, const int *cancellation_flag) { int dummy_bytes_parsed; int dummy_cancellation_flag; assert (parameters->first_column == 0 || parameters->first_column == 1); *collection = sgf_collection_new (); *error_list = sgf_error_list_new (); memset (data->times_error_reported, 0, sizeof data->times_error_reported); data->buffer_pointer = data->buffer; data->buffer_offset_in_file = 0; if (bytes_parsed) { *bytes_parsed = 0; data->bytes_parsed = bytes_parsed; } else data->bytes_parsed = &dummy_bytes_parsed; data->file_error = 0; data->cancelled = 0; if (cancellation_flag) data->cancellation_flag = cancellation_flag; else { dummy_cancellation_flag = 0; data->cancellation_flag = &dummy_cancellation_flag; } data->token = 0; data->line = 0; data->pending_column = 0; data->first_column = parameters->first_column; data->ko_property_error_position.line = 0; data->non_sgf_point_error_position.line = 0; data->zero_byte_error_position.line = 0; data->board = NULL; data->error_list = *error_list; data->latin1_to_utf8 = iconv_open ("UTF-8", "ISO-8859-1"); assert (data->latin1_to_utf8 != (iconv_t) (-1)); next_token (data); do { /* Skip any junk that might appear before game tree. */ if (data->token == '(') { next_token (data); if (data->token != ';') continue; } else { next_token (data); continue; } /* Parse the tree. */ data->tree = sgf_game_tree_new (); if (parse_root (data)) sgf_collection_add_game_tree (*collection, data->tree); else sgf_game_tree_delete (data->tree); if (data->tree_char_set_to_utf8 != data->latin1_to_utf8 && data->tree_char_set_to_utf8 != NULL) iconv_close (data->tree_char_set_to_utf8); } while (data->token != SGF_END); if (data->board) board_delete (data->board); iconv_close (data->latin1_to_utf8); if (data->cancelled || (*collection)->num_trees == 0) { string_list_delete (*error_list); *error_list = NULL; sgf_collection_delete (*collection); *collection = NULL; if (data->file_error) return SGF_ERROR_READING_FILE; else return data->cancelled ? SGF_PARSING_CANCELLED : SGF_INVALID_FILE; } if (string_list_is_empty (*error_list)) { string_list_delete (*error_list); *error_list = NULL; } return SGF_PARSED; } /* Parse root node. This function is needed because values of `CA', * `GM' and `SZ' properties are crucial for property value validation. * The function does nothing but finding these properties (if they are * present at all). Afterwards, root node is parsed as usually. */ static int parse_root (SgfParsingData *data) { SgfGameTree *tree = data->tree; BufferPositionStorage storage; data->tree_char_set_to_utf8 = data->latin1_to_utf8; STORE_BUFFER_POSITION (data, 1, storage); data->in_parse_root = 1; data->game = 0; data->board_width = 0; next_token (data); while (data->token != ';' && data->token != '(' && data->token != ')' && data->token != SGF_END) { SgfType property_type = SGF_NUM_PROPERTIES; while (data->token != '[' && data->token != SGF_END) { if ('A' <= data->token && data->token <= 'Z') { if (property_type >= SGF_NUM_PROPERTIES) { property_type = (property_tree[property_type - SGF_NUM_PROPERTIES] [1 + (data->token - 'A')]); } else property_type = SGF_UNKNOWN; } else if (data->token < 'a' || 'z' < data->token) { property_type = SGF_NUM_PROPERTIES; next_token (data); continue; } next_character (data); } if (property_type >= SGF_NUM_PROPERTIES) property_type = property_tree[property_type - SGF_NUM_PROPERTIES][0]; if (property_type == SGF_GAME_TYPE && !data->game) { next_token (data); if (do_parse_number (data, &data->game)) { if (1 <= data->game && data->game <= 1000) { if ((data->board_width || !GAME_IS_SUPPORTED (data->game)) && tree->char_set) break; } else data->game = 0; } } else if (property_type == SGF_BOARD_SIZE && !data->board_width) { next_token (data); if (do_parse_board_size (data, &data->board_width, &data->board_height, 0) && data->game && tree->char_set) break; } else if (property_type == SGF_CHAR_SET && !tree->char_set) { tree->char_set = do_parse_simple_text (data, SGF_END); if (tree->char_set) { char *char_set_uppercased = utils_duplicate_string (tree->char_set); char *scan; /* We now deal with an UTF-8 string, so uppercasing latin * letters is not a problem. */ for (scan = char_set_uppercased; *scan; scan++) { if ('a' <= *scan && *scan <= 'z') *scan += 'A' - 'a'; } data->tree_char_set_to_utf8 = (strcmp (char_set_uppercased, "UTF-8") == 0 ? NULL : iconv_open ("UTF-8", char_set_uppercased)); utils_free (char_set_uppercased); if (data->tree_char_set_to_utf8 != (iconv_t) (-1)) { if (data->game && data->board_width) break; } else { data->tree_char_set_to_utf8 = data->latin1_to_utf8; utils_free (tree->char_set); } } } discard_values (data); } if (data->game) data->game_type_expected = 1; else { data->game = GAME_GO; data->game_type_expected = 0; } if (GAME_IS_SUPPORTED (data->game)) { if (data->board_width == 0) { data->board_width = game_info[data->game].default_board_size; data->board_height = game_info[data->game].default_board_size; } if (data->board_width > SGF_MAX_BOARD_SIZE) data->board_width = SGF_MAX_BOARD_SIZE; if (data->board_height > SGF_MAX_BOARD_SIZE) data->board_height = SGF_MAX_BOARD_SIZE; data->use_board = (BOARD_MIN_WIDTH <= data->board_width && data->board_width <= BOARD_MAX_WIDTH && BOARD_MIN_HEIGHT <= data->board_height && data->board_height <= BOARD_MAX_HEIGHT); if (data->use_board) { if (data->game == GAME_GO) data->do_parse_move = do_parse_go_move; else if (data->game == GAME_REVERSI) data->do_parse_move = do_parse_reversi_move; else if (data->game == GAME_AMAZONS) data->do_parse_move = do_parse_amazons_move; else assert (0); if (!data->board) { data->board = board_new (data->game, data->board_width, data->board_height); } else { board_set_parameters (data->board, data->game, data->board_width, data->board_height); } data->board_common_mark = 0; data->board_change_mark = 0; data->board_markup_mark = 0; board_fill_uint_grid (data->board, data->common_marked_positions, 0); board_fill_uint_grid (data->board, data->changed_positions, 0); board_fill_uint_grid (data->board, data->marked_positions, 0); if (data->game == GAME_GO) { data->board_territory_mark = 0; board_fill_uint_grid (data->board, data->territory_positions, 0); } } } RESTORE_BUFFER_POSITION (data, 1, storage); data->in_parse_root = 0; data->game_info_node = NULL; data->has_any_setup_property = 0; data->first_setup_add_property = 1; data->has_any_markup_property = 0; data->first_markup_property = 1; data->has_any_territory_property = 0; data->first_territory_property = 1; sgf_game_tree_set_game (tree, data->game); tree->board_width = data->board_width; tree->board_height = data->board_height; tree->file_format = 0; tree->root = parse_node_tree (data, NULL); if (data->token == SGF_END && !data->cancelled) add_error (data, SGF_CRITICAL_UNEXPECTED_END_OF_FILE); next_token (data); if (tree->root) { tree->current_node = tree->root; return 1; } return 0; } static SgfNode * parse_node_tree (SgfParsingData *data, SgfNode *parent) { SgfNode *node; /* Skip any junk that might appear before the first node. */ while (data->token != ';') { if (data->token == ')') { add_error (data, SGF_ERROR_EMPTY_VARIATION); next_token (data); return NULL; } if (data->token == SGF_END) return NULL; next_token (data); } STORE_ERROR_POSITION (data, data->node_error_position); next_token (data); node = sgf_node_new (data->tree, parent); parse_node_sequence (data, node); /* Skip any junk after the last variation. */ while (data->token != ')' && data->token != SGF_END) next_token (data); return node; } /* Parse a sequence (a straight tree branch) of nodes. * * It would have been more straightforward to parse a single node and * then recurse, but parsing whole sequences saves huge amounts of * stack space. It even prevents segment violations (due to stack * finiteness) in case of extremely long node sequences (a bug found * with `sgf-board-stress.pike'). Finally, it saves almost 10% * runtime in the latter case :). */ static void parse_node_sequence (SgfParsingData *data, SgfNode *node) { SgfNode *game_info_node = data->game_info_node; int num_undos = 0; while (1) { if (*data->cancellation_flag) { data->cancelled = 1; data->buffer_end = data->buffer_pointer; data->buffer_refresh_point = data->buffer_end; } *data->bytes_parsed = (data->buffer_offset_in_file + (data->buffer_pointer - data->buffer)); if (data->buffer_pointer > data->buffer_refresh_point) refresh_buffer (data); data->node = node; while (data->token != ';' && data->token != '(' && data->token != ')' && data->token != SGF_END) parse_property (data); if (data->node == node) { num_undos += complete_node_and_update_board (data, (data->token != ';' && data->token != '(')); node = data->node; if (data->token == ';') { STORE_ERROR_POSITION (data, data->node_error_position); next_token (data); node->child = sgf_node_new (data->tree, node); node = node->child; continue; } if (data->token == '(') { SgfNode **link = &node->child; do { next_token (data); *link = parse_node_tree (data, node); if (*link) link = & (*link)->next; next_token (data); } while (data->token == '('); } } break; } board_undo (data->board, num_undos); data->game_info_node = game_info_node; } static void parse_property (SgfParsingData *data) { /* FIXME: this loop should add errors in certain cases. */ while (data->token != '[') { data->temp_buffer = data->buffer; STORE_ERROR_POSITION (data, data->property_name_error_position); while (data->token != '[') { if ('A' <= data->token && data->token <= 'Z') *data->temp_buffer++ = data->token; else if (data->token == ';' || data->token == '(' || data->token == ')' || data->token == SGF_END) return; else if (data->token < 'a' || 'z' < data->token) { if (data->token != ' ' && data->token != '\n') data->temp_buffer = data->buffer; next_token (data); break; } next_character (data); } } if (data->temp_buffer > data->buffer) { char *name = data->buffer; char *name_end = data->temp_buffer; SgfType property_type = 0; /* We have parsed some name. Now look it up in the name tree. */ while (1) { property_type = property_tree[property_type][1 + (*name - 'A')]; name++; if (property_type < SGF_NUM_PROPERTIES) { if (name < name_end) property_type = SGF_UNKNOWN; break; } property_type -= SGF_NUM_PROPERTIES; if (name == name_end) { property_type = property_tree[property_type][0]; break; } } if (property_type != SGF_UNKNOWN) { data->property_type = property_type; /* Root and game-info nodes cannot appear anywhere. */ if (SGF_FIRST_GAME_INFO_PROPERTY <= property_type && property_type <= SGF_LAST_GAME_INFO_PROPERTY && data->game_info_node != data->node && data->game_info_node != NULL) add_error (data, SGF_ERROR_MISPLACED_GAME_INFO_PROPERTY); else if (SGF_FIRST_ROOT_PROPERTY <= property_type && property_type <= SGF_LAST_ROOT_PROPERTY && data->node->parent) add_error (data, SGF_ERROR_MISPLACED_ROOT_PROPERTY); else { SgfError error; error = property_info[property_type].value_parser (data); if (error > SGF_LAST_FATAL_ERROR) { if (SGF_FIRST_GAME_INFO_PROPERTY <= property_type && property_type <= SGF_LAST_GAME_INFO_PROPERTY) data->game_info_node = data->node; if (error != SGF_SUCCESS) { add_error (data, error); discard_single_value (data); } if (data->token != '[') return; add_error (data, SGF_ERROR_MULTIPLE_VALUES); } else { if (error != SGF_FAIL) add_error (data, error); } } } else { /* An unknown property. We preserve it for it might be used by * some other program (and SGF specification requires us to do * so). The property is preserved as a string list: * * name (identifier), value, value ... */ SgfProperty **link; if (!sgf_node_find_unknown_property (data->node, data->buffer, name_end - data->buffer, &link)) { *link = sgf_property_new (data->tree, SGF_UNKNOWN, *link); (*link)->value.unknown_value_list = string_list_new (); string_list_add_from_buffer ((*link)->value.unknown_value_list, data->buffer, name_end - data->buffer); } else { /* Duplicated unknown properties. Assume list value type. */ add_error (data, SGF_WARNING_UNKNOWN_PROPERTIES_MERGED, data->buffer); } parse_unknown_property_values (data, (*link)->value.unknown_value_list); return; } } discard_values (data); } /* Refresh a buffer by reading next portion of data from file. Data * left from previous reading that has not been parsed yet is copied * to the buffer beginning. Note that we reserve one extra byte at * the very beginning of the buffer for storing current token. */ static void refresh_buffer (SgfParsingData *data) { int unused_bytes = data->buffer_end - data->buffer_pointer; int bytes_to_read = data->buffer_size - (unused_bytes + 1); memcpy (data->buffer + 1, data->buffer_pointer, unused_bytes); if (data->file_bytes_remaining <= bytes_to_read) { bytes_to_read = data->file_bytes_remaining; data->buffer_end = (data->buffer + 1) + unused_bytes + bytes_to_read; data->buffer_refresh_point = data->buffer_end; } if (fread ((data->buffer + 1) + unused_bytes, bytes_to_read, 1, data->file) != 1) { data->file_error = 1; data->cancelled = 1; data->buffer_end = data->buffer_pointer; data->buffer_refresh_point = data->buffer_end; data->token = SGF_END; return; } data->buffer_pointer = data->buffer + 1; data->file_bytes_remaining -= bytes_to_read; data->buffer_offset_in_file += data->buffer_size - (unused_bytes + 1); *data->bytes_parsed = (data->buffer_offset_in_file + (data->buffer_pointer - data->buffer)); } /* Reallocate buffer to increase its size and read more data from * file. This is an emergency function: it is only called if not a * single node started within `data->buffer_refresh_margin', which * must be very unlikely for sane SGF files. */ static void expand_buffer (SgfParsingData *data) { const char *original_buffer = data->buffer; int buffer_increase = data->buffer_size_increment; if (data->file_bytes_remaining <= 2 * buffer_increase) buffer_increase = data->file_bytes_remaining; data->buffer = utils_realloc ((char *) data->buffer, data->buffer_size + buffer_increase); data->buffer_pointer = data->buffer + data->buffer_size; if (fread ((char *) data->buffer + data->buffer_size, buffer_increase, 1, data->file) != 1) { data->file_error = 1; data->cancelled = 1; data->buffer_end = data->buffer_pointer; data->buffer_refresh_point = data->buffer_end; data->token = SGF_END; return; } data->buffer_size += buffer_increase; data->buffer_end = data->buffer + data->buffer_size; data->temp_buffer += data->buffer - original_buffer; data->stored_buffer_pointers[0] += data->buffer - original_buffer; data->stored_buffer_pointers[1] += data->buffer - original_buffer; data->file_bytes_remaining -= buffer_increase; if (data->file_bytes_remaining > 0) { data->buffer_refresh_point = (data->buffer_end - data->buffer_refresh_margin); } else data->buffer_refresh_point = data->buffer_end; *data->bytes_parsed = (data->buffer_offset_in_file + (data->buffer_pointer - data->buffer)); } static int complete_node_and_update_board (SgfParsingData *data, int is_leaf_node) { int num_undos = 0; int has_setup_add_properties = 0; BoardPositionList *position_lists[NUM_ON_GRID_VALUES]; if (!data->first_setup_add_property && (data->has_setup_add_properties[BLACK] || data->has_setup_add_properties[WHITE] || data->has_setup_add_properties[EMPTY] || data->has_setup_add_properties[SPECIAL_ON_GRID_VALUE])) { /* Create setup add properties position lists. */ has_setup_add_properties = 1; create_position_lists (data, position_lists, NULL, NUM_ON_GRID_VALUES, data->changed_positions, data->board_change_mark); } /* For root node there might be default setup. */ if (!data->node->parent && !has_setup_add_properties && data->use_board && game_get_default_setup (data->game, data->board_width, data->board_height, &position_lists[BLACK], &position_lists[WHITE])) { data->has_any_setup_property = 1; has_setup_add_properties = 1; position_lists[EMPTY] = NULL; position_lists[SPECIAL_ON_GRID_VALUE] = NULL; } if (has_setup_add_properties && data->use_board) { board_apply_changes (data->board, (const BoardPositionList **) position_lists); num_undos++; } /* Amazons move are senseless if there is no piece of appropriate * color at "from" point. Such moves are deleted. */ if (data->game == GAME_AMAZONS && data->node->move_color != EMPTY && (data->board->grid[POINT_TO_POSITION (data->node->data.amazons.from)] != data->node->move_color)) { insert_error (data, SGF_ERROR_SENSELESS_MOVE, &data->move_error_position, data->node->data.amazons.from.x, data->node->data.amazons.from.y); data->node->move_color = EMPTY; } if (data->ko_property_error_position.line) { if (data->node->move_color == EMPTY) { insert_error (data, SGF_ERROR_KO_PROPERTY_WITHOUT_MOVE, &data->ko_property_error_position); } data->ko_property_error_position.line = 0; } if (data->has_any_setup_property) { data->has_any_setup_property = 0; data->first_setup_add_property = 1; /* Nodes with both setup and move properties have to be split. */ if (data->node->move_color != EMPTY || sgf_node_find_property (data->node, SGF_MOVE_NUMBER, NULL)) { if (has_setup_add_properties || data->node->to_play_color == data->node->move_color) { sgf_node_split (data->node, data->tree); insert_error (data, SGF_ERROR_MIXED_SETUP_ADD_AND_MOVE_PROPERTIES, &data->node_error_position); } else { data->node->to_play_color = EMPTY; insert_error (data, SGF_ERROR_MIXED_PL_AND_MOVE_PROPERTIES, &data->node_error_position); } } if (has_setup_add_properties) { /* Add setup add properties to the node. */ if (position_lists[BLACK]) { sgf_node_add_list_of_point_property (data->node, data->tree, SGF_ADD_BLACK, position_lists[BLACK], 0); } if (position_lists[WHITE]) { sgf_node_add_list_of_point_property (data->node, data->tree, SGF_ADD_WHITE, position_lists[WHITE], 0); } if (position_lists[EMPTY]) { sgf_node_add_list_of_point_property (data->node, data->tree, SGF_ADD_EMPTY, position_lists[EMPTY], 0); } if (position_lists[SPECIAL_ON_GRID_VALUE]) { /* NOTE: might have to "if" further if we have more games. */ sgf_node_add_list_of_point_property (data->node, data->tree, SGF_ADD_ARROWS, position_lists[ARROW], 0); } data->node->move_color = SETUP_NODE; } if (data->node->child) data->node = data->node->child; } if (data->has_any_markup_property) { static const SgfType markup_property_types[NUM_SGF_MARKUPS] = { SGF_MARK, SGF_CIRCLE, SGF_SQUARE, SGF_TRIANGLE, SGF_SELECTED }; data->has_any_markup_property = 0; data->first_markup_property = 1; create_position_lists (data, NULL, markup_property_types, NUM_SGF_MARKUPS, data->marked_positions, data->board_markup_mark); } if (data->has_any_territory_property) { static const SgfType territory_property_types[NUM_COLORS] = { SGF_BLACK_TERRITORY, SGF_WHITE_TERRITORY }; data->first_territory_property = 1; data->has_any_territory_property = 0; create_position_lists (data, NULL, territory_property_types, NUM_COLORS, data->territory_positions, data->board_territory_mark); } if (IS_STONE (data->node->move_color) && !is_leaf_node && data->use_board) { sgf_utils_play_node_move (data->node, data->board); num_undos++; } return num_undos; } static void create_position_lists (SgfParsingData *data, BoardPositionList **position_lists, const SgfType *property_types, int num_properties, const unsigned int marked_positions[BOARD_GRID_SIZE], unsigned int current_mark) { int positions[NUM_SGF_MARKUPS][BOARD_MAX_POSITIONS]; int num_positions[NUM_SGF_MARKUPS]; int value; int x; int y; for (value = 0; value < num_properties; value++) num_positions[value] = 0; for (y = 0; y < data->board_height; y++) { for (x = 0; x < data->board_width; x++) { int pos = POSITION (x, y); if (marked_positions[pos] >= current_mark) { value = marked_positions[pos] - current_mark; positions[value][num_positions[value]++] = pos; } } } for (value = 0; value < num_properties; value++) { if (num_positions[value] > 0) { BoardPositionList *position_list = board_position_list_new (positions[value], num_positions[value]); if (position_lists) position_lists[value] = position_list; else { sgf_node_add_list_of_point_property (data->node, data->tree, property_types[value], position_list, 0); } } else if (position_lists) position_lists[value] = NULL; } } /* Skip a value of a property without storing it anywhere. */ static void discard_single_value (SgfParsingData *data) { while (data->token != ']' && data->token != SGF_END) { if (data->token == '\\') next_character (data); next_character (data); } next_token (data); } /* Skip all values of a property without storing them. Used when * something is wrong. */ static void discard_values (SgfParsingData *data) { do discard_single_value (data); while (data->token == '['); } /* Parse a value of an unknown property. No assumptions about format * of the property are made besides that "\]" is considered an escaped * bracket and doesn't terminate value string. Unknown properties are * always allowed to have a list of values. * * FIXME: Add charsets support. */ static void parse_unknown_property_values (SgfParsingData *data, StringList *property_value_list) { do { data->temp_buffer = data->buffer; next_character (data); while (data->token != ']' && data->token != SGF_END) { *data->temp_buffer++ = data->token; if (data->token == '\\') { next_character (data); *data->temp_buffer++ = data->token; } next_character (data); } if (data->token == SGF_END) return; string_list_add_from_buffer (property_value_list, data->buffer, data->temp_buffer - data->buffer); next_token (data); } while (data->token == '['); } /* Parse value of "none" type. Basically value validation only. */ SgfError sgf_parse_none (SgfParsingData *data) { SgfProperty **link; if (sgf_node_find_property (data->node, data->property_type, &link)) return SGF_FATAL_DUPLICATE_PROPERTY; if (data->property_type == SGF_KO) data->ko_property_error_position = data->property_name_error_position; *link = sgf_property_new (data->tree, data->property_type, *link); next_character (data); if (data->token == ']') { next_token (data); return SGF_SUCCESS; } return SGF_ERROR_NON_EMPTY_VALUE; } /* Parse a number. This function is used instead of atoi() or * strtol() because we prefer not to create a string for the latter. * This function operates directly on buffer. In addition, with * library functions, it would have been difficult to check for * errors. */ static int do_parse_number (SgfParsingData *data, int *number) { int negative = 0; unsigned value = 0; if (data->token == '-' || data->token == '+') { if (data->token == '-') negative = 1; next_token_in_value (data); } if ('0' <= data->token && data->token <= '9') { do { if (value < (UINT_MAX / 10U)) value = value * 10 + (data->token - '0'); else value = UINT_MAX; next_token_in_value (data); } while ('0' <= data->token && data->token <= '9'); if (!negative) { if (value <= INT_MAX) { *number = value; return 1; } *number = INT_MAX; } else { if (value <= - (unsigned) INT_MIN) { *number = -value; return 1; } *number = INT_MIN; } return 2; } return 0; } /* Parse a number, but discard it as illegal if negative, or * non-positive (for `MN' property.) For `PM' property, give a * warning if the print mode specified is not described in SGF * specification. */ SgfError sgf_parse_constrained_number (SgfParsingData *data) { SgfProperty **link; BufferPositionStorage storage; int number; if (sgf_node_find_property (data->node, data->property_type, &link)) return SGF_FATAL_DUPLICATE_PROPERTY; begin_parsing_value (data); if (data->token == ']') return SGF_FATAL_EMPTY_VALUE; STORE_BUFFER_POSITION (data, 0, storage); if (do_parse_number (data, &number) && number >= (data->property_type != SGF_MOVE_NUMBER ? 0 : 1)) { if (data->property_type == SGF_PRINT_MODE && number >= NUM_SGF_PRINT_MODES) add_error (data, SGF_WARNING_UNKNOWN_PRINT_MODE, number); *link = sgf_property_new (data->tree, data->property_type, *link); (*link)->value.number = number; return end_parsing_value (data); } RESTORE_BUFFER_POSITION (data, 0, storage); return SGF_FATAL_INVALID_VALUE; } static int do_parse_real (SgfParsingData *data, double *real) { double value = 0.0; int negative = 0; if (data->token == '-' || data->token == '+') { if (data->token == '-') negative = 1; next_token_in_value (data); } if (('0' <= data->token && data->token <= '9') || data->token == '.') { SgfErrorPosition integer_part_error_position; if ('0' <= data->token && data->token <= '9') { do { value = value * 10 + (double) (data->token - '0'); next_token_in_value (data); } while ('0' <= data->token && data->token <= '9'); integer_part_error_position.line = 0; } else STORE_ERROR_POSITION (data, integer_part_error_position); if (data->token == '.') { next_token_in_value (data); if ('0' <= data->token && data->token <= '9') { double decimal_multiplier = 0.1; do { value += decimal_multiplier * (double) (data->token - '0'); decimal_multiplier /= 10; next_token_in_value (data); } while ('0' <= data->token && data->token <= '9'); } else { if (integer_part_error_position.line) return 0; } } if (integer_part_error_position.line) { insert_error (data, SGF_WARNING_INTEGER_PART_SUPPLIED, &integer_part_error_position); } if (!negative) { /* OMG, wrote this with floats, but with doubles, I doubt it * makes any sense at all ;). No point in deleting anyway, * right? */ if (value <= 10e100) { *real = value; return 1; } *real = 10e100; } else { if (value >= -10e100) { *real = -value; return 1; } *real = -10e100; } add_error (data, SGF_ERROR_TOO_LARGE_ABSOLUTE_VALUE); return 2; } return 0; } SgfError sgf_parse_real (SgfParsingData *data) { SgfProperty **link; BufferPositionStorage storage; double real; if (sgf_node_find_property (data->node, data->property_type, &link)) return SGF_FATAL_DUPLICATE_PROPERTY; begin_parsing_value (data); if (data->token == ']') return SGF_FATAL_EMPTY_VALUE; STORE_BUFFER_POSITION (data, 0, storage); if (do_parse_real (data, &real)) { *link = sgf_property_new (data->tree, data->property_type, *link); #if SGF_REAL_VALUES_ALLOCATED_SEPARATELY (*link)->value.real = utils_duplicate_buffer (&real, sizeof (double)); #else (*link)->value.real = real; #endif return end_parsing_value (data); } RESTORE_BUFFER_POSITION (data, 0, storage); return SGF_FATAL_INVALID_VALUE; } /* Parse a "double" value. Allowed values are [1] (normal) and [2] * (emphasized). Anything else is considered an error. */ SgfError sgf_parse_double (SgfParsingData *data) { SgfProperty **link; if (sgf_node_find_property (data->node, data->property_type, &link)) return SGF_FATAL_DUPLICATE_PROPERTY; begin_parsing_value (data); *link = sgf_property_new (data->tree, data->property_type, *link); (*link)->value.emphasized = (data->token == '2'); if (data->token == '1' || data->token == '2') { next_token_in_value (data); return end_parsing_value (data); } return SGF_ERROR_INVALID_DOUBLE_VALUE; } static int do_parse_color (SgfParsingData *data) { if (data->token == 'B') return BLACK; if (data->token == 'W') return WHITE; if (data->token == 'b' || data->token == 'w') { add_error (data, SGF_WARNING_LOWER_CASE_COLOR, data->token, data->token - ('b' - 'B')); return data->token == 'b' ? BLACK : WHITE; } return EMPTY; } /* Parse color value. [W] stands for white and [B] - for black. No * other values are allowed except that [w] and [b] are upcased and * warned about. */ SgfError sgf_parse_color (SgfParsingData *data) { SgfProperty **link; int color; if (sgf_node_find_property (data->node, data->property_type, &link)) return SGF_FATAL_DUPLICATE_PROPERTY; begin_parsing_value (data); if (data->token == ']') return SGF_FATAL_EMPTY_VALUE; color = do_parse_color (data); if (color != EMPTY) { *link = sgf_property_new (data->tree, data->property_type, *link); (*link)->value.color = color; next_token_in_value (data); return end_parsing_value (data); } return SGF_FATAL_INVALID_VALUE; } /* Parse a simple text value. All leading and trailing whitespace * characters are removed. Other newlines, if encountered, are * converted into spaces. Escaped newlines are removed completely. * Return either a heap copy of parsed values or NULL in case of error * (empty value). * * The `extra_stop_character' parameter should be set to either * SGF_END or color (':') depending on desired value terminator in * addition to ']'. */ static char * do_parse_simple_text (SgfParsingData *data, char extra_stop_character) { data->temp_buffer = data->buffer; /* Skip leading whitespace. */ while (1) { next_token (data); if (data->token == '\\') { next_character (data); if (data->token == ' ' || data->token == '\n') continue; *data->temp_buffer++ = data->token; next_character (data); } break; } if (data->temp_buffer != data->buffer || (data->token != ']' && data->token != extra_stop_character && data->token != SGF_END)) { do { if (data->token != '\\' && data->token != '\n') *data->temp_buffer++ = data->token; else if (data->token == '\\') { next_character (data); if (data->token != '\n') *data->temp_buffer++ = data->token; } else *data->temp_buffer++ = ' '; next_character (data); } while (data->token != ']' && data->token != extra_stop_character && data->token != SGF_END); /* Delete trailing whitespace. */ while (*(data->temp_buffer - 1) == ' ') data->temp_buffer--; return convert_text_to_utf8 (data, NULL); } return NULL; } static char * do_parse_text (SgfParsingData *data, char *existing_text) { next_character (data); data->temp_buffer = data->buffer; while (data->token != ']' && data->token != SGF_END) { if (data->token != '\\') *data->temp_buffer++ = data->token; else { next_character (data); if (data->token != '\n') *data->temp_buffer++ = data->token; } next_character (data); } while (1) { if (data->temp_buffer == data->buffer) { add_error (data, SGF_WARNING_EMPTY_VALUE); next_token (data); return existing_text; } if ((*(data->temp_buffer - 1) != ' ' && *(data->temp_buffer - 1) != '\n')) break; data->temp_buffer--; } next_token (data); if (existing_text) existing_text = utils_cat_as_string (existing_text, "\n\n", 2); return convert_text_to_utf8 (data, existing_text); } /* Convert text to UTF-8 encoding. Text to be converted is bounded by * `data->buffer' and `data->temp_buffer' pointers. Memory between * `data->temp_buffer' and `data->buffer_pointer' can be used as * conversion buffer and thus overwritten. * * Converted text is concatenated to `existing_text'. If * `existing_text' is NULL to begin with, then converted text is * allocated in a new memory region on the heap. */ static char * convert_text_to_utf8 (SgfParsingData *data, char *existing_text) { if (data->tree_char_set_to_utf8) { char local_buffer[0x1000]; char *original_text = data->buffer; size_t original_bytes_left = data->temp_buffer - data->buffer; char *utf8_buffer; size_t utf8_buffer_size; if (data->buffer_pointer - data->temp_buffer > sizeof local_buffer) { utf8_buffer = data->temp_buffer; utf8_buffer_size = data->buffer_pointer - data->temp_buffer; } else { utf8_buffer = local_buffer; utf8_buffer_size = sizeof local_buffer; } while (original_bytes_left > 0) { size_t utf8_bytes_left = utf8_buffer_size; char *utf8_text = utf8_buffer; iconv (data->tree_char_set_to_utf8, &original_text, &original_bytes_left, &utf8_text, &utf8_bytes_left); existing_text = utils_cat_as_string (existing_text, utf8_buffer, utf8_text - utf8_buffer); } return existing_text; } else { /* The text is already in UTF-8, no conversion needed. */ return utils_cat_as_string (existing_text, data->buffer, data->temp_buffer - data->buffer); } } /* Parse a simple text value, that is, a line of text. */ SgfError sgf_parse_simple_text (SgfParsingData *data) { SgfProperty **link; char *text; if (sgf_node_find_property (data->node, data->property_type, &link)) return SGF_FATAL_DUPLICATE_PROPERTY; text = do_parse_simple_text (data, SGF_END); if (text) { next_token (data); *link = sgf_property_new (data->tree, data->property_type, *link); (*link)->value.text = text; return SGF_SUCCESS; } return SGF_WARNING_PROPERTY_WITH_EMPTY_VALUE; } SgfError sgf_parse_text (SgfParsingData *data) { int property_found; SgfProperty **link; char *text; property_found = sgf_node_find_property (data->node, data->property_type, &link); if (property_found) { add_error (data, SGF_WARNING_PROPERTIES_MERGED); text = do_parse_text (data, (*link)->value.text); } else text = do_parse_text (data, NULL); if (data->token == '[') { add_error (data, SGF_WARNING_VALUES_MERGED); do text = do_parse_text (data, text); while (data->token == '['); } if (!property_found) { if (!text) { /* Not really a success, but simpler this way. */ return SGF_SUCCESS; } *link = sgf_property_new (data->tree, data->property_type, *link); } (*link)->value.text = text; return SGF_SUCCESS; } static int do_parse_point (SgfParsingData *data, BoardPoint *point) { if (('a' <= data->token && data->token <= 'z') || ('A' <= data->token && data->token <= 'Z')) { char x = data->token; next_token_in_value (data); if (('a' <= data->token && data->token <= 'z') || ('A' <= data->token && data->token <= 'Z')) { char y = data->token; next_token_in_value (data); point->x = (x >= 'a' ? x - 'a' : x - 'A' + ('z' - 'a' + 1)); point->y = (y >= 'a' ? y - 'a' : y - 'A' + ('z' - 'a' + 1)); return (point->x < data->board_width && point->y < data->board_height ? 0 : 1); } if ('1' <= data->token && data->token <= '9') { int y; do_parse_number (data, &y); point->x = (x >= 'a' ? x - 'a' : x - 'A'); if (data->game == GAME_GO) { if (point->x == 'I' - 'A') return 2; if (point->x > 'I' - 'A') point->x--; } if (point->x < data->board_width && y <= data->board->height) { point->y = (data->game != GAME_REVERSI ? data->board->height - y : y - 1); if (!data->times_error_reported[SGF_WARNING_NON_SGF_POINT_NOTATION] && !data->non_sgf_point_error_position.line) { STORE_ERROR_POSITION (data, data->non_sgf_point_error_position); data->non_sgf_point_x = x; data->non_sgf_point_y = y; } return 0; } point->x = -1; return 1; } } return 2; } static SgfError do_parse_go_move (SgfParsingData *data) { BoardPoint *move_point = &data->node->move_point; if (data->token != ']') { BufferPositionStorage storage; STORE_BUFFER_POSITION (data, 0, storage); switch (do_parse_point (data, move_point)) { case 0: return SGF_SUCCESS; case 1: if (move_point->x != 19 || move_point->y != 19 || data->board_width > 19 || data->board_height > 19) return SGF_FATAL_MOVE_OUT_OF_BOARD; break; default: RESTORE_BUFFER_POSITION (data, 0, storage); return SGF_FATAL_INVALID_VALUE; } } move_point->x = PASS_X; move_point->y = PASS_Y; return SGF_SUCCESS; } static SgfError do_parse_reversi_move (SgfParsingData *data) { if (data->token != ']') { BufferPositionStorage storage; STORE_BUFFER_POSITION (data, 0, storage); switch (do_parse_point (data, &data->node->move_point)) { case 0: return SGF_SUCCESS; case 1: return SGF_FATAL_MOVE_OUT_OF_BOARD; default: RESTORE_BUFFER_POSITION (data, 0, storage); return SGF_FATAL_INVALID_VALUE; } } return SGF_FATAL_EMPTY_VALUE; } static SgfError do_parse_amazons_move (SgfParsingData *data) { if (data->token != ']') { int point_parsing_error; BufferPositionStorage storage; STORE_BUFFER_POSITION (data, 0, storage); point_parsing_error = do_parse_point (data, &data->node->data.amazons.from); if (point_parsing_error == 0) { point_parsing_error = do_parse_point (data, &data->node->move_point); if (point_parsing_error == 0) { point_parsing_error = do_parse_point (data, &data->node->data.amazons.shoot_arrow_to); if (point_parsing_error == 0) return SGF_SUCCESS; } } if (point_parsing_error == 1) return SGF_FATAL_MOVE_OUT_OF_BOARD; RESTORE_BUFFER_POSITION (data, 0, storage); return SGF_FATAL_INVALID_VALUE; } return SGF_FATAL_EMPTY_VALUE; } SgfError sgf_parse_move (SgfParsingData *data) { SgfError error; begin_parsing_value (data); if (data->node->move_color == EMPTY) { error = data->do_parse_move (data); if (error == SGF_SUCCESS) { data->node->move_color = (data->property_type == SGF_BLACK ? BLACK : WHITE); if (data->game == GAME_AMAZONS) data->move_error_position = data->property_name_error_position; return end_parsing_value (data); } } else { SgfNode *current_node = data->node; SgfNode *node = sgf_node_new (data->tree, NULL); data->node = node; error = data->do_parse_move (data); data->node = current_node; if (error == SGF_SUCCESS) { int num_undos; add_error (data, SGF_ERROR_ANOTHER_MOVE); num_undos = complete_node_and_update_board (data, 0); node->move_color = (data->property_type == SGF_BLACK ? BLACK : WHITE); node->parent = data->node; data->node->child = node; if (end_parsing_value (data) == SGF_ERROR_ILLEGAL_TRAILING_CHARACTERS) add_error (data, SGF_ERROR_ILLEGAL_TRAILING_CHARACTERS); if (data->token == '[') { add_error (data, SGF_ERROR_MULTIPLE_VALUES); discard_values (data); } STORE_ERROR_POSITION (data, data->node_error_position); if (data->game == GAME_AMAZONS) data->move_error_position = data->property_name_error_position; parse_node_sequence (data, node); board_undo (data->board, num_undos); return SGF_SUCCESS; } else sgf_node_delete (node, data->tree); } data->non_sgf_point_error_position.line = 0; return error; } static int do_parse_point_or_rectangle (SgfParsingData *data, BoardPoint *left_top, BoardPoint *right_bottom) { int point_parsing_error; BufferPositionStorage storage; begin_parsing_value (data); if (data->token == ']') { add_error (data, SGF_WARNING_EMPTY_VALUE); next_token (data); return 0; } STORE_BUFFER_POSITION (data, 0, storage); point_parsing_error = do_parse_point (data, left_top); if (point_parsing_error == 0) { if (!is_composed_value (data, 0)) *right_bottom = *left_top; else { point_parsing_error = do_parse_point (data, right_bottom); if (point_parsing_error == 0) { if (left_top->x > right_bottom->x || left_top->y > right_bottom->y) { add_error (data, SGF_ERROR_INVALID_CORNERS); if (left_top->x > right_bottom->x) { int temp_x = left_top->x; left_top->x = right_bottom->x; right_bottom->x = temp_x; } if (left_top->y > right_bottom->y) { int temp_y = left_top->y; left_top->y = right_bottom->y; right_bottom->y = temp_y; } } else if (left_top->x == right_bottom->x && left_top->y == right_bottom->y) add_error (data, SGF_WARNING_POINT_AS_RECTANGLE); } } } switch (point_parsing_error) { case 0: if (end_parsing_value (data) == SGF_ERROR_ILLEGAL_TRAILING_CHARACTERS) { add_error (data, SGF_ERROR_ILLEGAL_TRAILING_CHARACTERS); next_token (data); } return 1; case 1: add_error (data, SGF_ERROR_POINT_OUT_OF_BOARD); discard_single_value (data); break; default: RESTORE_BUFFER_POSITION (data, 0, storage); add_error (data, SGF_ERROR_INVALID_VALUE); next_token (data); } data->non_sgf_point_error_position.line = 0; return 0; } static int do_parse_list_of_point (SgfParsingData *data, unsigned int marked_positions[BOARD_GRID_SIZE], unsigned int current_mark, int value, SgfError duplication_error, const char match_grid[BOARD_GRID_SIZE]) { int num_parsed_positions = 0; do { BoardPoint left_top; BoardPoint right_bottom; if (do_parse_point_or_rectangle (data, &left_top, &right_bottom)) { int x; int y; for (y = left_top.y; y <= right_bottom.y; y++) { for (x = left_top.x; x <= right_bottom.x; x++) { int pos = POSITION (x, y); if (marked_positions[pos] < current_mark) { if (!match_grid || match_grid[pos] != value) { marked_positions[pos] = current_mark + value; num_parsed_positions++; } else add_error (data, SGF_WARNING_SETUP_HAS_NO_EFFECT, x, y); } else { if (marked_positions[pos] == current_mark + value) add_error (data, SGF_WARNING_DUPLICATE_POINT, x, y); else add_error (data, duplication_error, x, y); } } } } } while (data->token == '['); return num_parsed_positions; } SgfError sgf_parse_list_of_point (SgfParsingData *data) { SgfProperty **link; int num_positions = 0; if (data->property_type == SGF_ILLEGAL_MOVE && data->game != GAME_GO) { add_error (data, SGF_ERROR_WRONG_GAME, game_info[GAME_GO].name, game_info[data->game].name); return SGF_FAIL; } data->board_common_mark++; if (sgf_node_find_property (data->node, data->property_type, &link)) { int k; BoardPositionList *position_list = (*link)->value.position_list; num_positions = position_list->num_positions; for (k = 0; k < num_positions; k++) { data->common_marked_positions[position_list->positions[k]] = data->board_common_mark; } sgf_property_delete_at_link (link, data->tree); add_error (data, SGF_WARNING_PROPERTIES_MERGED); } if (property_info[data->property_type].value_type == SGF_ELIST_OF_POINT) { BufferPositionStorage storage; STORE_BUFFER_POSITION (data, 0, storage); begin_parsing_value (data); if (data->token == ']') { end_parsing_value (data); if (data->token == '[') { add_error (data, SGF_ERROR_VALUES_AFTER_EMPTY_LIST); discard_values (data); } } else RESTORE_BUFFER_POSITION (data, 0, storage); } if (data->token == '[') { num_positions += do_parse_list_of_point (data, data->common_marked_positions, data->board_common_mark, 0, SGF_FAIL, NULL); } if (num_positions > 0 || property_info[data->property_type].value_type == SGF_ELIST_OF_POINT) { int k; int x; int y; *link = sgf_property_new (data->tree, data->property_type, *link); (*link)->value.position_list = board_position_list_new_empty (num_positions); for (y = 0, k = 0; k < num_positions; y++) { for (x = 0; x < data->board_width; x++) { if (data->common_marked_positions[POSITION (x, y)] == data->board_common_mark) (*link)->value.position_list->positions[k++] = POSITION (x, y); } } } return SGF_SUCCESS; } SgfError sgf_parse_list_of_vector (SgfParsingData *data) { int property_found; SgfProperty **link; SgfVectorList *vector_list; property_found = sgf_node_find_property (data->node, data->property_type, &link); if (!property_found) vector_list = sgf_vector_list_new (-1); else { add_error (data, SGF_WARNING_PROPERTIES_MERGED); vector_list = (*link)->value.vector_list; } do { int point_parsing_error; BufferPositionStorage storage; BoardPoint from_point; BoardPoint to_point; begin_parsing_value (data); if (data->token == ']') { add_error (data, SGF_WARNING_EMPTY_VALUE); next_token (data); continue; } STORE_BUFFER_POSITION (data, 0, storage); point_parsing_error = do_parse_point (data, &from_point); if (point_parsing_error == 0) { if (is_composed_value (data, 0)) point_parsing_error = do_parse_point (data, &to_point); else point_parsing_error = -1; } switch (point_parsing_error) { case 0: if (from_point.x != to_point.x || from_point.y != to_point.y) { if (!sgf_vector_list_has_vector (vector_list, from_point, to_point)) { if (end_parsing_value (data) == SGF_ERROR_ILLEGAL_TRAILING_CHARACTERS) { add_error (data, SGF_ERROR_ILLEGAL_TRAILING_CHARACTERS); next_token (data); } vector_list = sgf_vector_list_add_vector (vector_list, from_point, to_point); continue; } else { add_error (data, SGF_WARNING_DUPLICATE_VECTOR, from_point.x, from_point.y, to_point.x, to_point.y); } } else { add_error (data, SGF_ERROR_ZERO_LENGTH_VECTOR, from_point.x, from_point.y, to_point.x, to_point.y); } discard_single_value (data); break; case 1: add_error (data, SGF_ERROR_POINT_OUT_OF_BOARD); discard_single_value (data); break; default: RESTORE_BUFFER_POSITION (data, 0, storage); add_error (data, SGF_ERROR_INVALID_VALUE); next_token (data); } data->non_sgf_point_error_position.line = 0; } while (data->token == '['); if (vector_list->num_vectors > 0) { if (!property_found) *link = sgf_property_new (data->tree, data->property_type, *link); (*link)->value.vector_list = sgf_vector_list_shrink (vector_list); } return SGF_SUCCESS; } SgfError sgf_parse_list_of_label (SgfParsingData *data) { SgfProperty **link; char *labels[BOARD_GRID_SIZE]; int num_labels = 0; data->board_common_mark++; if (sgf_node_find_property (data->node, data->property_type, &link)) { int k; SgfLabelList *label_list = (*link)->value.label_list; num_labels = label_list->num_labels; for (k = 0; k < num_labels; k++) { int pos = POINT_TO_POSITION (label_list->labels[k].point); labels[pos] = label_list->labels[k].text; label_list->labels[k].text = NULL; data->common_marked_positions[pos] = data->board_common_mark; } sgf_property_delete_at_link (link, data->tree); add_error (data, SGF_WARNING_PROPERTIES_MERGED); } do { begin_parsing_value (data); if (data->token != ']') { BufferPositionStorage storage; BoardPoint point; int pos; STORE_BUFFER_POSITION (data, 0, storage); switch (do_parse_point (data, &point)) { case 0: pos = POINT_TO_POSITION (point); if (data->common_marked_positions[pos] != data->board_common_mark) { if (is_composed_value (data, 1)) { labels[pos] = do_parse_simple_text (data, SGF_END); if (labels[pos]) { data->common_marked_positions[pos] = data->board_common_mark; num_labels++; } else add_error (data, SGF_WARNING_EMPTY_LABEL, point.x, point.y); } else add_error (data, SGF_WARNING_EMPTY_LABEL, point.x, point.y); if (end_parsing_value (data) == SGF_ERROR_ILLEGAL_TRAILING_CHARACTERS) { add_error (data, SGF_ERROR_ILLEGAL_TRAILING_CHARACTERS); next_token (data); } continue; } add_error (data, SGF_ERROR_DUPLICATE_LABEL, point.x, point.y); discard_single_value (data); data->non_sgf_point_error_position.line = 0; continue; case 1: add_error (data, SGF_ERROR_POINT_OUT_OF_BOARD); discard_single_value (data); continue; } RESTORE_BUFFER_POSITION (data, 0, storage); add_error (data, SGF_ERROR_INVALID_VALUE); data->non_sgf_point_error_position.line = 0; } else add_error (data, SGF_WARNING_EMPTY_VALUE); next_token (data); } while (data->token == '['); if (num_labels > 0) { SgfLabelList *label_list = sgf_label_list_new_empty (num_labels); int k; int x; int y; *link = sgf_property_new (data->tree, data->property_type, *link); (*link)->value.label_list = label_list; for (y = 0, k = 0; k < num_labels; y++) { for (x = 0; x < data->board_width; x++) { if (data->common_marked_positions[POSITION (x, y)] == data->board_common_mark) { label_list->labels[k].point.x = x; label_list->labels[k].point.y = y; label_list->labels[k].text = labels[POSITION (x, y)]; k++; } } } } return SGF_SUCCESS; } /* Parse a value of `AP' property (composed simpletext ":" * simpletext). The value is stored in SgfGameTree structure. */ SgfError sgf_parse_application (SgfParsingData *data) { char *text; if (data->tree->application_name) return SGF_FATAL_DUPLICATE_PROPERTY; /* Parse the first part of value. */ text = do_parse_simple_text (data, ':'); if (text) { data->tree->application_name = text; if (data->token == ':') { /* Parse the second part of value. */ data->tree->application_version = do_parse_simple_text (data, SGF_END); } else if (data->token == ']') add_error (data, SGF_WARNING_COMPOSED_SIMPLE_TEXT_EXPECTED); next_token (data); return SGF_SUCCESS; } return SGF_WARNING_PROPERTY_WITH_EMPTY_VALUE; } static int do_parse_board_size (SgfParsingData *data, int *width, int *height, int add_errors) { BufferPositionStorage storage; STORE_BUFFER_POSITION (data, 0, storage); if (!do_parse_number (data, width) || *width < SGF_MIN_BOARD_SIZE) { if (add_errors) { RESTORE_BUFFER_POSITION (data, 0, storage); add_error (data, SGF_FATAL_INVALID_VALUE); } return 0; } if (is_composed_value (data, 0)) { if (!do_parse_number (data, height) || *height < SGF_MIN_BOARD_SIZE) { if (add_errors) { RESTORE_BUFFER_POSITION (data, 0, storage); add_error (data, SGF_FATAL_INVALID_VALUE); } return 0; } if (*height == *width && add_errors) add_error (data, SGF_WARNING_SAME_WIDTH_AND_HEIGHT); } else *height = *width; if (*width > SGF_MAX_BOARD_SIZE || *height > SGF_MAX_BOARD_SIZE) { int original_width = *width; int original_height = *height; if (*height > SGF_MAX_BOARD_SIZE) *height = SGF_MAX_BOARD_SIZE; if (*width > SGF_MAX_BOARD_SIZE) *width = SGF_MAX_BOARD_SIZE; if (add_errors) { add_error (data, SGF_ERROR_TOO_LARGE_BOARD, original_width, original_height, *width, *height); } } return 1; } SgfError sgf_parse_board_size (SgfParsingData *data) { SgfProperty **link; int width; int height; if (sgf_node_find_property (data->node, data->property_type, &link)) return SGF_FATAL_DUPLICATE_PROPERTY; begin_parsing_value (data); if (data->token == ']') return SGF_FATAL_EMPTY_VALUE; if (do_parse_board_size (data, &width, &height, 1)) return end_parsing_value (data); return SGF_FAIL; } /* FIXME: write this function. */ SgfError sgf_parse_char_set (SgfParsingData *data) { discard_values (data); return SGF_SUCCESS; } /* FIXME: write this function. */ SgfError sgf_parse_date (SgfParsingData *data) { return sgf_parse_simple_text (data); } SgfError sgf_parse_figure (SgfParsingData *data) { SgfProperty **link; BufferPositionStorage storage; int figure_flags = SGF_FIGURE_USE_DEFAULTS; int flags_parsed; char *diagram_name = NULL; if (sgf_node_find_property (data->node, data->property_type, &link)) return SGF_FATAL_DUPLICATE_PROPERTY; *link = sgf_property_new (data->tree, data->property_type, *link); begin_parsing_value (data); if (data->token == ']') { (*link)->value.figure = NULL; return SGF_SUCCESS; } STORE_BUFFER_POSITION (data, 0, storage); flags_parsed = do_parse_number (data, &figure_flags); if (flags_parsed) { if (figure_flags & ~SGF_FIGURE_FLAGS_MASK) add_error (data, SGF_WARNING_UNKNOWN_FLAGS); if (is_composed_value (data, 1)) diagram_name = do_parse_simple_text (data, SGF_END); else add_error (data, SGF_WARNING_COMPOSED_SIMPLE_TEXT_EXPECTED); } else { add_error (data, SGF_ERROR_FIGURE_FLAGS_EXPECTED); RESTORE_BUFFER_POSITION (data, 0, storage); diagram_name = do_parse_simple_text (data, SGF_END); } (*link)->value.figure = sgf_figure_description_new (figure_flags, diagram_name); return end_parsing_value (data); } SgfError sgf_parse_file_format (SgfParsingData *data) { BufferPositionStorage storage; int file_format; if (data->tree->file_format) return SGF_FATAL_DUPLICATE_PROPERTY; begin_parsing_value (data); if (data->token == ']') return SGF_FATAL_EMPTY_VALUE; STORE_BUFFER_POSITION (data, 0, storage); if (do_parse_number (data, &file_format) && 1 <= file_format && file_format <= 1000) { if (file_format > 4) add_error (data, SGF_CRITICAL_FUTURE_FILE_FORMAT, file_format); data->tree->file_format = file_format; return end_parsing_value (data); } RESTORE_BUFFER_POSITION (data, 0, storage); return SGF_FATAL_INVALID_VALUE; } /* Parse a `GM' property. Note that this property is not stored, this * function only validates it. Property value is actually parsed by * parse_root() and is kept in SgfGameTree structure. */ SgfError sgf_parse_game_type (SgfParsingData *data) { BufferPositionStorage storage; int game_type; if (!data->game_type_expected) return SGF_FATAL_DUPLICATE_PROPERTY; begin_parsing_value (data); if (data->token == ']') return SGF_FATAL_EMPTY_VALUE; STORE_BUFFER_POSITION (data, 0, storage); if (do_parse_number (data, &game_type) && 1 <= game_type && game_type <= 1000) { if (game_type > LAST_GAME) add_error (data, SGF_WARNING_UNKNOWN_GAME, game_type); else if (!GAME_IS_SUPPORTED (game_type)) { add_error (data, SGF_WARNING_UNSUPPORTED_GAME, game_info[game_type].name, game_type); } data->game_type_expected = 0; return end_parsing_value (data); } RESTORE_BUFFER_POSITION (data, 0, storage); return (data->game_type_expected ? SGF_FATAL_INVALID_VALUE : SGF_FATAL_INVALID_GAME_TYPE); } SgfError sgf_parse_handicap (SgfParsingData *data) { SgfProperty **link; BufferPositionStorage storage; int handicap; if (data->game != GAME_GO) { add_error (data, SGF_ERROR_WRONG_GAME, game_info[GAME_GO].name, game_info[data->game].name); return SGF_FAIL; } if (sgf_node_find_property (data->node, data->property_type, &link)) return SGF_FATAL_DUPLICATE_PROPERTY; STORE_BUFFER_POSITION (data, 0, storage); begin_parsing_value (data); if (data->token == ']') return SGF_FATAL_EMPTY_VALUE; *link = sgf_property_new (data->tree, data->property_type, *link); if (do_parse_number (data, &handicap) && data->token == ']') { if (handicap > data->board_width * data->board_height) { handicap = data->board_width * data->board_height; add_error (data, SGF_WARNING_HANDICAP_REDUCED, handicap); } else if (handicap == 1 || handicap < 0) { handicap = 0; add_error (data, SGF_ERROR_INVALID_HANDICAP); } (*link)->value.text = utils_cprintf ("%d", handicap); return end_parsing_value (data); } return invalid_game_info_property (data, *link, &storage); } SgfError sgf_parse_komi (SgfParsingData *data) { SgfProperty **link; BufferPositionStorage storage; double komi; if (data->game != GAME_GO) { add_error (data, SGF_ERROR_WRONG_GAME, game_info[GAME_GO].name, game_info[data->game].name); return SGF_FAIL; } if (sgf_node_find_property (data->node, data->property_type, &link)) return SGF_FATAL_DUPLICATE_PROPERTY; STORE_BUFFER_POSITION (data, 0, storage); begin_parsing_value (data); if (data->token == ']') return SGF_FATAL_EMPTY_VALUE; *link = sgf_property_new (data->tree, data->property_type, *link); if (do_parse_real (data, &komi) && data->token == ']') { (*link)->value.text = utils_cprintf ("%.f", komi); return end_parsing_value (data); } return invalid_game_info_property (data, *link, &storage); } SgfError sgf_parse_markup_property (SgfParsingData *data) { int markup; if (data->first_markup_property) { for (markup = 0; markup < NUM_SGF_MARKUPS; markup++) data->has_markup_properties[markup] = 0; data->first_markup_property = 0; data->board_markup_mark += NUM_SGF_MARKUPS; } if (data->property_type == SGF_MARK) markup = SGF_MARKUP_CROSS; else if (data->property_type == SGF_CIRCLE) markup = SGF_MARKUP_CIRCLE; else if (data->property_type == SGF_SQUARE) markup = SGF_MARKUP_SQUARE; else if (data->property_type == SGF_TRIANGLE) markup = SGF_MARKUP_TRIANGLE; else if (data->property_type == SGF_SELECTED) markup = SGF_MARKUP_SELECTED; else assert (0); if (data->has_markup_properties[markup]) add_error (data, SGF_WARNING_PROPERTIES_MERGED); if (do_parse_list_of_point (data, data->marked_positions, data->board_markup_mark, markup, SGF_ERROR_DUPLICATE_MARKUP, NULL)) { data->has_any_markup_property = 1; data->has_markup_properties[markup] = 1; } return SGF_SUCCESS; } SgfError sgf_parse_result (SgfParsingData *data) { SgfProperty **link; BufferPositionStorage storage; if (sgf_node_find_property (data->node, data->property_type, &link)) return SGF_FATAL_DUPLICATE_PROPERTY; STORE_BUFFER_POSITION (data, 0, storage); begin_parsing_value (data); if (data->token == ']') return SGF_FATAL_EMPTY_VALUE; *link = sgf_property_new (data->tree, data->property_type, *link); if (data->token == 'B' || data->token == 'W') { char color = data->token; next_token_in_value (data); if (data->token == '+') { next_token_in_value (data); if (('0' <= data->token && data->token <= '9') || data->token == '.') { double score; if (do_parse_real (data, &score) && data->token == ']') { (*link)->value.text = utils_cprintf ("%c+%.f", color, score); return end_parsing_value (data); } } else { static const char *non_score_results[6] = { "F", "Forfeit", "R", "Resign", "T", "Time" }; int result_index = looking_at (data, non_score_results, 6); if (result_index != -1) { /* Use full-word reasons internally. */ (*link)->value.text = utils_cprintf ("%c+%s", color, non_score_results[result_index | 1]); return end_parsing_value (data); } } } } else { static const char *no_winner_results[4] = { "0", "?", "Draw", "Void" }; int result_index = looking_at (data, no_winner_results, 4); if (result_index != -1) { /* Prefer "Draw" to "0". */ (*link)->value.text = utils_duplicate_string (no_winner_results[result_index != 0 ? result_index : 2]); return end_parsing_value (data); } } return invalid_game_info_property (data, *link, &storage); } SgfError sgf_parse_setup_property (SgfParsingData *data) { int color; if (data->first_setup_add_property) { for (color = 0; color < NUM_ON_GRID_VALUES; color++) data->has_setup_add_properties[color] = 0; data->first_setup_add_property = 0; data->board_change_mark += NUM_ON_GRID_VALUES; } if (data->property_type == SGF_ADD_BLACK) color = BLACK; else if (data->property_type == SGF_ADD_WHITE) color = WHITE; else if (data->property_type == SGF_ADD_EMPTY) color = EMPTY; else if (data->property_type == SGF_ADD_ARROWS) { if (data->game != GAME_AMAZONS) { add_error (data, SGF_ERROR_WRONG_GAME, game_info[GAME_AMAZONS].name, game_info[data->game].name); return SGF_FAIL; } color = ARROW; } else assert (0); if (data->has_setup_add_properties[color]) add_error (data, SGF_WARNING_PROPERTIES_MERGED); if (do_parse_list_of_point (data, data->changed_positions, data->board_change_mark, color, SGF_ERROR_DUPLICATE_SETUP, data->board->grid)) { data->has_any_setup_property = 1; data->has_setup_add_properties[color] = 1; } return SGF_SUCCESS; } SgfError sgf_parse_style (SgfParsingData *data) { BufferPositionStorage storage; if (data->tree->style_is_set) return SGF_FATAL_DUPLICATE_PROPERTY; begin_parsing_value (data); if (data->token == ']') return SGF_FATAL_EMPTY_VALUE; STORE_BUFFER_POSITION (data, 0, storage); if (do_parse_number (data, &data->tree->style)) { data->tree->style_is_set = 1; if (data->tree->style & ~SGF_STYLE_FLAGS_MASK) add_error (data, SGF_WARNING_UNKNOWN_FLAGS); return end_parsing_value (data); } RESTORE_BUFFER_POSITION (data, 0, storage); return SGF_FATAL_INVALID_VALUE; } SgfError sgf_parse_territory (SgfParsingData *data) { int color_index; if (data->game != GAME_GO) { add_error (data, SGF_ERROR_WRONG_GAME, game_info[GAME_GO].name, game_info[data->game].name); return SGF_FAIL; } if (data->first_territory_property) { data->has_territory_properties[BLACK_INDEX] = 0; data->has_territory_properties[WHITE_INDEX] = 0; data->first_territory_property = 0; data->board_territory_mark += NUM_COLORS; } if (data->property_type == SGF_BLACK_TERRITORY) color_index = BLACK_INDEX; else if (data->property_type == SGF_WHITE_TERRITORY) color_index = WHITE_INDEX; else assert (0); if (data->has_territory_properties[color_index]) add_error (data, SGF_WARNING_PROPERTIES_MERGED); if (do_parse_list_of_point (data, data->territory_positions, data->board_territory_mark, color_index, SGF_ERROR_DUPLICATE_TERRITORY, NULL)) { data->has_any_territory_property = 1; data->has_territory_properties[color_index] = 1; } return SGF_SUCCESS; } SgfError sgf_parse_time_limit (SgfParsingData *data) { SgfProperty **link; BufferPositionStorage storage; double time_limit; if (sgf_node_find_property (data->node, data->property_type, &link)) return SGF_FATAL_DUPLICATE_PROPERTY; STORE_BUFFER_POSITION (data, 0, storage); begin_parsing_value (data); if (data->token == ']') return SGF_FATAL_EMPTY_VALUE; if (do_parse_real (data, &time_limit) && data->token == ']') { if (time_limit < 0.0) { RESTORE_BUFFER_POSITION (data, 0, storage); next_character (data); return SGF_FATAL_NEGATIVE_TIME_LIMIT; } *link = sgf_property_new (data->tree, data->property_type, *link); (*link)->value.text = utils_cprintf ("%.f", time_limit); return end_parsing_value (data); } *link = sgf_property_new (data->tree, data->property_type, *link); return invalid_game_info_property (data, *link, &storage); } SgfError sgf_parse_to_play (SgfParsingData *data) { if (data->node->to_play_color != EMPTY) return SGF_FATAL_DUPLICATE_PROPERTY; begin_parsing_value (data); if (data->token == ']') return SGF_FATAL_EMPTY_VALUE; data->node->to_play_color = do_parse_color (data); if (data->node->to_play_color != EMPTY) { /* `PL' is a setup property. */ data->has_any_setup_property = 1; next_token_in_value (data); return end_parsing_value (data); } return SGF_FATAL_INVALID_VALUE; } /* FIXME: write this function. */ SgfError sgf_parse_letters (SgfParsingData *data) { begin_parsing_value (data); while (data->token != ']') next_token (data); return end_parsing_value (data); } /* FIXME: write this function. */ SgfError sgf_parse_simple_markup (SgfParsingData *data) { begin_parsing_value (data); while (data->token != ']') next_token (data); return end_parsing_value (data); } static int looking_at (SgfParsingData *data, const char **strings, int num_strings) { int first_candidate = 0; int last_candidate = num_strings; int character_index; for (character_index = 0; first_candidate < last_candidate; character_index++) { int k; if (data->token == ']') return strings[first_candidate][character_index] ? -1 : first_candidate; for (k = first_candidate; k < last_candidate; k++) { if (strings[k][character_index] < data->token) first_candidate++; else if (strings[k][character_index] > data->token) { last_candidate = k; break; } } next_token_in_value (data); } return -1; } static void add_error (SgfParsingData *data, SgfError error, ...) { va_list arguments; if (error < SGF_FIRST_PROPERTY_NAME_ERROR || SGF_LAST_PROPERTY_NAME_ERROR < error) { StringBuffer buffer; if (error != SGF_WARNING_ERROR_SUPPRESSED && data->times_error_reported[error] == MAX_TIMES_TO_REPORT_ERROR) return; string_buffer_init (&buffer, 0x200, 0x200); va_start (arguments, error); format_error_valist (data, &buffer, error, arguments); va_end (arguments); string_list_add_ready (data->error_list, string_buffer_steal_string (&buffer)); data->error_list->last->line = data->line; data->error_list->last->column = data->column + data->first_column; if (error != SGF_WARNING_ERROR_SUPPRESSED && ++data->times_error_reported[error] == MAX_TIMES_TO_REPORT_ERROR) add_error (data, SGF_WARNING_ERROR_SUPPRESSED); } else { va_start (arguments, error); insert_error_valist (data, error, &data->property_name_error_position, arguments); va_end (arguments); } } static void insert_error (SgfParsingData *data, SgfError error, SgfErrorPosition *error_position, ...) { va_list arguments; va_start (arguments, error_position); insert_error_valist (data, error, error_position, arguments); va_end (arguments); } static void insert_error_valist (SgfParsingData *data, SgfError error, SgfErrorPosition *error_position, va_list arguments) { SgfErrorListItem *error_item; StringBuffer buffer; if (error != SGF_WARNING_ERROR_SUPPRESSED && data->times_error_reported[error] == MAX_TIMES_TO_REPORT_ERROR) return; string_buffer_init (&buffer, 0x200, 0x200); format_error_valist (data, &buffer, error, arguments); error_item = string_list_insert_ready (data->error_list, error_position->notch, string_buffer_steal_string (&buffer)); error_item->line = error_position->line; error_item->column = error_position->column + data->first_column; if (error != SGF_WARNING_ERROR_SUPPRESSED && ++data->times_error_reported[error] == MAX_TIMES_TO_REPORT_ERROR) { error_position->notch = error_position->notch->next; insert_error (data, SGF_WARNING_ERROR_SUPPRESSED, error_position); } } static SgfError invalid_game_info_property (SgfParsingData *data, SgfProperty *property, BufferPositionStorage *storage) { RESTORE_BUFFER_POSITION (data, 0, *storage); property->value.text = do_parse_simple_text (data, SGF_END); RESTORE_BUFFER_POSITION (data, 0, *storage); next_character (data); return SGF_ERROR_INVALID_GAME_INFO_PROPERTY; } inline static void begin_parsing_value (SgfParsingData *data) { data->whitespace_error_position.line = 0; next_token_in_value (data); } static int is_composed_value (SgfParsingData *data, int expecting_simple_text) { BufferPositionStorage storage; int whitespace_line; int whitespace_passed; if (data->token == ']') return 0; STORE_BUFFER_POSITION (data, 2, storage); whitespace_line = data->whitespace_error_position.line; whitespace_passed = data->whitespace_passed; while (data->token != ':' && data->token != ']' && data->token != SGF_END) next_token_in_value (data); if (data->token == ':') { if (!expecting_simple_text) { next_token_in_value (data); if (data->token == ']') { RESTORE_BUFFER_POSITION (data, 2, storage); data->whitespace_error_position.line = whitespace_line; data->whitespace_passed = whitespace_passed; return 0; } } if (storage.token != ':' && !data->in_parse_root) { RESTORE_BUFFER_POSITION (data, 2, storage); add_error (data, SGF_ERROR_ILLEGAL_TRAILING_CHARACTERS_BEFORE_COLON); if (data->whitespace_error_position.line && !(whitespace_line && whitespace_passed)) data->whitespace_error_position.line = 0; if (!expecting_simple_text) next_token_in_value (data); } return 1; } RESTORE_BUFFER_POSITION (data, 2, storage); data->whitespace_error_position.line = whitespace_line; data->whitespace_passed = whitespace_passed; return 0; } static SgfError end_parsing_value (SgfParsingData *data) { if (data->non_sgf_point_error_position.line) { insert_error (data, SGF_WARNING_NON_SGF_POINT_NOTATION, &data->non_sgf_point_error_position, data->non_sgf_point_x, data->non_sgf_point_y); data->non_sgf_point_error_position.line = 0; } if (data->whitespace_error_position.line && (data->token == ']' || data->whitespace_passed)) { insert_error (data, SGF_WARNING_ILLEGAL_WHITESPACE, &data->whitespace_error_position); } if (data->token == ']') { next_token (data); return SGF_SUCCESS; } return SGF_ERROR_ILLEGAL_TRAILING_CHARACTERS; } /* Format an error. It recognizes the following custom conversion * specifiers in addition to standard `%c', `%d' and `%s': * * - `%N' stands for current property name (stack is untouched). * * - `%V' stands for current value (shortened if needed; no arguments * are taken from stack). * * - `%P': two integers are taken from the stack and coordinates of * the point they make are put into output buffer. * * - `%M': move, stored in `data->node' is formatted according to * current game. */ static void format_error_valist (SgfParsingData *data, StringBuffer *buffer, SgfError error, va_list arguments) { const char *format_string = sgf_errors[error]; while (*format_string) { if (*format_string != '%') string_buffer_add_character (buffer, *format_string++); else { format_string++; switch (*format_string++) { case 'N': string_buffer_cat_string (buffer, property_info[data->property_type].name); break; case 'V': data->temp_buffer = data->buffer; if (data->token == ESCAPED_BRACKET) { *data->temp_buffer++ = '\\'; *data->temp_buffer++ = ']'; next_character (data); } while (data->token != *format_string && data->token != SGF_END) { if (data->token == '\\') { *data->temp_buffer++ = data->token; next_character (data); } *data->temp_buffer++ = (data->token != '\n' ? data->token : ' '); if (data->token == ' ' || data->token == '\n') next_token (data); else next_character (data); } if (data->temp_buffer - data->buffer <= 27) { string_buffer_cat_as_string (buffer, data->buffer, data->temp_buffer - data->buffer); } else { /* Value is long, only output the beginning and the end. */ string_buffer_cat_as_string (buffer, data->buffer, 12); string_buffer_add_characters (buffer, '.', 3); string_buffer_cat_as_string (buffer, data->temp_buffer - 12, 12); } break; case 'P': { int x = va_arg (arguments, int); int y = va_arg (arguments, int); game_format_point (data->game, data->board_width, data->board_height, buffer, x, y); } break; case 'M': sgf_utils_format_node_move (data->tree, data->node, buffer, "B ", "W ", NULL); break; case 'c': string_buffer_add_character (buffer, (char) va_arg (arguments, int)); break; case 'd': string_buffer_printf (buffer, "%d", va_arg (arguments, int)); break; case 's': string_buffer_cat_string (buffer, va_arg (arguments, const char *)); break; case 0: break; default: string_buffer_add_character (buffer, *(format_string - 1)); } } } } /* Read characters from the input buffer skipping any whitespace * encountered. This is just a wrapper around next_character(). */ inline static void next_token (SgfParsingData *data) { do next_character (data); while (data->token == ' ' || data->token == '\n'); } /* Similar to next_token() except that keeps track of the first * whitespace encountered (if any). This information is used by * end_parsing_value() for reporting errors. * * This function also handles the escape character ('\') transparently * for its callers (SGF specification remains silent about escaping in * non-text properties, but this is the way `SGFC' behaves). */ static void next_token_in_value (SgfParsingData *data) { next_character (data); if (data->token == '\\') { next_character (data); if (data->token == ']') data->token = ESCAPED_BRACKET; } data->whitespace_passed = 1; if (data->token == ' ' || data->token == '\n') { if (!data->whitespace_error_position.line) { STORE_ERROR_POSITION (data, data->whitespace_error_position); data->whitespace_passed = 0; } do { next_character (data); if (data->token == '\\') { next_character (data); if (data->token == ']') data->token = ESCAPED_BRACKET; } } while (data->token == ' ' || data->token == '\n'); } } /* Read a character from the input buffer. All linebreak combinations * allowed by SGF (LF, CR, CR LF, LF CR) are replaced with a single * '\n'. All other whitespace characters ('\t', '\v' and '\f') are * converted to spaces. The function also keeps track of the current * line and column in the buffer. */ static void next_character (SgfParsingData *data) { if (data->buffer_pointer < data->buffer_end) { char token = *data->buffer_pointer++; /* Update current line and column based on the _previous_ * character. This way newlines appear at ends of lines. */ data->column = data->pending_column; if (data->column == 0) data->line++; if (token != '\n' && token != '\r') { if (token == 0) { if (!data->zero_byte_error_position.line) { /* To avoid spoiling add_error() calls, we add warning about * zero byte after the complete buffer is parsed. */ STORE_ERROR_POSITION (data, data->zero_byte_error_position); } while (data->buffer_pointer < data->buffer_end && *data->buffer_pointer == 0) { data->buffer_pointer++; data->pending_column++; } next_character (data); return; } data->token = token; data->pending_column++; /* SGF specification tells to handle '\t', '\v' and '\f' as a * space. Also, '\t' updates column in a non-standard way. */ if (token == '\t') { data->pending_column = ROUND_UP (data->pending_column, 8); data->token = ' '; } if (token == '\v' || token == '\f') data->token = ' '; } else { if (data->buffer_pointer == data->buffer_end && data->buffer_refresh_point < data->buffer_end) expand_buffer (data); if (data->buffer_pointer < data->buffer_end && token + *data->buffer_pointer == '\n' + '\r') { /* Two character linebreak, e.g. for Windows systems. */ data->buffer_pointer++; } data->token = '\n'; data->pending_column = 0; } } else { if (data->buffer_refresh_point == data->buffer_end) data->token = SGF_END; else { expand_buffer (data); next_character (data); } } } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/sgf/sgf-tree.c0000644000175000017500000012166310520515076014736 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "sgf.h" #include "sgf-privates.h" #include "sgf-undo.h" #include "board.h" #include "utils.h" #include #include #include #include inline static void free_property_value (SgfProperty *property); static int compare_sgf_labels (const void *first_label, const void *second_label); /* Dynamically allocate and initialize an SgfCollection structure with * no game trees. */ SgfCollection * sgf_collection_new (void) { SgfCollection *collection = utils_malloc (sizeof (SgfCollection)); collection->num_trees = 0; collection->first_tree = NULL; collection->last_tree = NULL; collection->num_modified_undo_histories = 0; collection->is_irreversibly_modified = 0; collection->notification_callback = NULL; collection->user_data = NULL; return collection; } /* Free a previously allocated SgfCollection structure and all its * game trees. */ void sgf_collection_delete (SgfCollection *collection) { SgfGameTree *this_tree; assert (collection); for (this_tree = collection->first_tree; this_tree;) { SgfGameTree *next_tree = this_tree->next; sgf_game_tree_delete (this_tree); this_tree = next_tree; } utils_free (collection); } /* Add a game tree at the end of a collection. Fields of both * structures are updated in order to keep game trees properly linked. */ void sgf_collection_add_game_tree (SgfCollection *collection, SgfGameTree *tree) { assert (collection); assert (tree); tree->collection = collection; tree->previous = collection->last_tree; tree->next = NULL; if (collection->last_tree) collection->last_tree->next = tree; else collection->first_tree = tree; collection->num_trees++; collection->last_tree = tree; } int sgf_collection_is_modified (const SgfCollection *collection) { assert (collection); return (collection->num_modified_undo_histories > 0 || collection->is_irreversibly_modified); } /* Note: caller is responsible for resetting any undo histories that * are used with collection's trees, but are not attached to them * right now. */ void sgf_collection_set_unmodified (SgfCollection *collection) { SgfGameTree *tree; if (!sgf_collection_is_modified (collection)) return; collection->num_modified_undo_histories = 0; collection->is_irreversibly_modified = 0; for (tree = collection->first_tree; tree; tree = tree->next) { if (tree->undo_history) { tree->undo_history->unmodified_state_entry = tree->undo_history->last_applied_entry; } } COLLECTION_DO_NOTIFY (collection); } void sgf_collection_set_notification_callback (SgfCollection *collection, SgfCollectionNotificationCallback callback, void *user_data) { assert (collection); collection->notification_callback = callback; collection->user_data = user_data; } /* Dynamically allocate an SgfGameTree structure. */ SgfGameTree * sgf_game_tree_new (void) { SgfGameTree *tree = utils_malloc (sizeof (SgfGameTree)); tree->collection = NULL; tree->previous = NULL; tree->next = NULL; tree->root = NULL; tree->current_node = NULL; tree->current_node_depth = 0; tree->board = NULL; tree->board_state = NULL; tree->undo_history = NULL; tree->undo_history_list = NULL; tree->undo_operation_level = 0; tree->char_set = NULL; tree->application_name = NULL; tree->application_version = NULL; tree->style_is_set = 0; tree->node_pool.item_size = 0; memory_pool_init (&tree->property_pool, sizeof (SgfProperty), STRUCTURE_FIELD_OFFSET (SgfProperty, item_index)); tree->notification_callback = NULL; tree->user_data = NULL; tree->map_data_list = NULL; tree->view_port_nodes = NULL; tree->view_port_lines = NULL; return tree; } SgfGameTree * sgf_game_tree_new_with_root (Game game, int board_width, int board_height, int provide_default_setup) { SgfGameTree *tree = sgf_game_tree_new (); BoardPositionList *black_stones; BoardPositionList *white_stones; assert (SGF_MIN_BOARD_SIZE <= board_width && board_width <= SGF_MAX_BOARD_SIZE); assert (SGF_MIN_BOARD_SIZE <= board_height && board_height <= SGF_MAX_BOARD_SIZE); sgf_game_tree_set_game (tree, game); tree->board_width = board_width; tree->board_height = board_height; tree->root = sgf_node_new (tree, NULL); tree->current_node = tree->root; if (provide_default_setup && game_get_default_setup (game, board_width, board_height, &black_stones, &white_stones)) { tree->root->move_color = SETUP_NODE; if (black_stones) { sgf_node_add_list_of_point_property (tree->root, tree, SGF_ADD_BLACK, black_stones, 0); } if (white_stones) { sgf_node_add_list_of_point_property (tree->root, tree, SGF_ADD_WHITE, white_stones, 0); } } return tree; } /* Free a previously allocated game tree and all its nodes. */ void sgf_game_tree_delete (SgfGameTree *tree) { SgfUndoHistory *undo_history; assert (tree); if (tree->notification_callback) tree->notification_callback (tree, SGF_GAME_TREE_DELETED, tree->user_data); sgf_game_tree_invalidate_map (tree, NULL); undo_history = tree->undo_history_list; while (undo_history) { SgfUndoHistory *next_undo_history = undo_history->next; sgf_undo_history_delete (undo_history, tree); undo_history = next_undo_history; } #if ENABLE_MEMORY_POOLS memory_pool_traverse (&tree->property_pool, (MemoryPoolCallback) free_property_value); memory_pool_flush (&tree->property_pool); if (tree->node_pool.item_size > 0) memory_pool_flush (&tree->node_pool); #else if (tree->root) sgf_node_delete (tree->root, tree); #endif utils_free (tree->char_set); utils_free (tree->application_name); utils_free (tree->application_version); utils_free (tree); } void sgf_game_tree_set_game (SgfGameTree *tree, Game game) { int node_size; int index_field_offset; assert (tree); assert (FIRST_GAME <= game && game <= LAST_GAME); tree->game = game; if (game == GAME_GO) { node_size = sizeof (SgfNodeGo); index_field_offset = STRUCTURE_FIELD_OFFSET (SgfNodeGo, item_index); } else if (game == GAME_REVERSI) { node_size = sizeof (SgfNodeReversi); index_field_offset = STRUCTURE_FIELD_OFFSET (SgfNodeReversi, item_index); } else if (game == GAME_AMAZONS) { node_size = sizeof (SgfNodeAmazons); index_field_offset = STRUCTURE_FIELD_OFFSET (SgfNodeAmazons, item_index); } else { node_size = sizeof (SgfNodeGeneric); index_field_offset = STRUCTURE_FIELD_OFFSET (SgfNodeGeneric, item_index); } memory_pool_init (&tree->node_pool, node_size, index_field_offset); } /* Set given tree's associated board, board state and current node. * All fields but `board_state' must be non-NULL. */ void sgf_game_tree_set_state (SgfGameTree *tree, const SgfGameTreeState *state) { assert (tree); assert (state); assert (state->board); assert (state->board->game == tree->game); assert (state->board->width == tree->board_width); assert (state->board->height == tree->board_height); assert (state->current_node); tree->board = state->board; tree->board_state = state->board_state; tree->current_node = state->current_node; tree->current_node_depth = state->current_node_depth; } void sgf_game_tree_get_state (SgfGameTree *tree, SgfGameTreeState *state) { assert (tree); assert (state); state->board = tree->board; state->board_state = tree->board_state; state->current_node = tree->current_node; state->current_node_depth = tree->current_node_depth; } /* Create a copy of given game tree structure. Nodes are not * duplicated (not even root.) User data is not copied either. Use * sgf_game_tree_duplicate_with_nodes() if you need a copy with all * nodes. */ SgfGameTree * sgf_game_tree_duplicate (const SgfGameTree *tree) { SgfGameTree *tree_copy = sgf_game_tree_new (); assert (tree); sgf_game_tree_set_game (tree_copy, tree->game); tree_copy->board_width = tree->board_width; tree_copy->board_height = tree->board_height; tree_copy->char_set = utils_duplicate_string (tree->char_set); tree_copy->style_is_set = tree->style_is_set; if (tree->style_is_set) tree_copy->style = tree->style; return tree_copy; } SgfGameTree * sgf_game_tree_duplicate_with_nodes (const SgfGameTree *tree) { SgfGameTree *tree_copy; assert (tree); assert (tree->root); tree_copy = sgf_game_tree_duplicate (tree); tree_copy->root = sgf_node_duplicate_recursively (tree->root, tree_copy, NULL); return tree_copy; } /* Get the ``first'' node in the `tree' in traversing sense. This is * always the root of the tree, but the caller should not know this. * * Trees are traversed forward in this order: * * - The first node is the root. * * - The next node is... * the `child', if it exists; * the `next' (in normal sense) node of the `parent', if exists; * the `next' node of second order parent (`->parent->parent') if * exists; * ... * * See also sgf_node_traverse_forward(). */ SgfNode * sgf_game_tree_traverse_forward (const SgfGameTree *tree) { assert (tree); return tree->root; } /* Get the ``last'' node in the `tree' traversing order. The backward * traversing order is defined by reversing the forward traversing * order. Traversing backward is generally slower. * * See also sgf_node_traverse_backward(). */ SgfNode * sgf_game_tree_traverse_backward (const SgfGameTree *tree) { SgfNode *result; assert (tree); result = tree->root; if (!result) return NULL; while (1) { if (!result->child) return result; result = result->child; while (result->next) result = result->next; } } int sgf_game_tree_count_nodes (const SgfGameTree *tree) { assert (tree); #if ENABLE_MEMORY_POOLS return memory_pool_count_items (&tree->node_pool); #else return tree->root ? sgf_node_count_subtree_nodes (tree->root) : 0; #endif } void sgf_game_tree_set_notification_callback (SgfGameTree *tree, SgfGameTreeNotificationCallback callback, void *user_data) { assert (tree); tree->notification_callback = callback; tree->user_data = user_data; } /* Dynamically allocate an SgfNode structure and links it to the * specified parent node. */ SgfNode * sgf_node_new (SgfGameTree *tree, SgfNode *parent) { SgfNode *node; node = memory_pool_alloc (&tree->node_pool); node->parent = parent; node->child = NULL; node->next = NULL; node->current_variation = NULL; node->is_collapsed = 0; node->has_intermediate_map_data = 0; node->to_play_color = EMPTY; node->move_color = EMPTY; node->properties = NULL; return node; } /* Free a previously allocated SgfNode structure and all its * properties. All children nodes are deleted as well. To reduce * stack usage, non-branching sequences of nodes are deleted in a * loop, not with recursion. */ void sgf_node_delete (SgfNode *node, SgfGameTree *tree) { assert (node); /* Delete a sequence of nodes starting at the given `node' until it * ends or we find a branching point. */ do { SgfProperty *this_property; SgfNode *next_node = node->child; for (this_property = node->properties; this_property;) { SgfProperty *next_property = this_property->next; sgf_property_delete (this_property, tree); this_property = next_property; } memory_pool_free (&tree->node_pool, node); node = next_node; } while (node && !node->next); /* Recurse for each branch. */ while (node) { SgfNode *next_node = node->next; sgf_node_delete (node, tree); node = next_node; } } /* Get the previous node of given node. Return NULL if the node is * the first child or has no parent at all (is tree root.) */ SgfNode * sgf_node_get_previous_node (const SgfNode *node) { assert (node); if (node->parent && node->parent->child != node) { SgfNode *child; for (child = node->parent->child; child->next != node; child = child->next) assert (child); return child; } return NULL; } /* Get the last child of given node (the first is `node->child'.) Can * return NULL if the node has no children at all. */ SgfNode * sgf_node_get_last_child (const SgfNode *node) { SgfNode *last_child; assert (node); last_child = node->child; if (last_child) { while (last_child->next) last_child = last_child->next; } return last_child; } /* Create a copy of an SGF node (with properties) for a given tree. * This function copies only the specified node, not its children. * Use sgf_node_duplicate_recursively() if you need a copy of full * subtree. */ SgfNode * sgf_node_duplicate (const SgfNode *node, SgfGameTree *tree, SgfNode *parent) { SgfNode *node_copy = sgf_node_new (tree, parent); const SgfProperty *property; SgfProperty **link; assert (node); assert (tree); node_copy->to_play_color = node->to_play_color; node_copy->move_color = node->move_color; if (IS_STONE (node->move_color)) { node_copy->move_point = node->move_point; if (tree->game == GAME_AMAZONS) node_copy->data.amazons = node->data.amazons; } for (property = node->properties, link = &node_copy->properties; property; property = property->next, link = & (*link)->next) *link = sgf_property_duplicate (property, tree, NULL); return node_copy; } /* Make a copy of given node and all its children. * * As in other functions, recursion only happens for sibling subnodes, * not the subnodes in main variation for performance reasons. */ SgfNode * sgf_node_duplicate_recursively (const SgfNode *node, SgfGameTree *tree, SgfNode *parent) { /* Duplicate just the given node. */ SgfNode *node_copy = sgf_node_duplicate (node, tree, parent); /* Duplicate all nodes in sequence until we find a branching * point or the sequence ends. */ parent = node_copy; while (1) { node = node->child; if (!node || node->next) break; parent->child = sgf_node_duplicate (node, tree, parent); parent = parent->child; } if (node) { SgfNode **link; /* Recurse for each branch. */ for (link = &parent->child; node; node = node->next, link = & (*link)->next) *link = sgf_node_duplicate_recursively (node, tree, parent); } return node_copy; } /* Similar to sgf_node_duplicate_recursively(), but duplicates only * some levels of nodes, not the whole node subtree. If `depth' * parameter is 1, duplicate only the node itself. If it is 2 then * direct children are included and so on. */ SgfNode * sgf_node_duplicate_to_given_depth (const SgfNode *node, SgfGameTree *tree, SgfNode *parent, int depth) { SgfNode *node_copy = sgf_node_duplicate (node, tree, parent); assert (depth > 0); if (depth > 1) { SgfNode **link; for (node = node->child, link = &node_copy->child; node; node = node->next, link = & (*link)->next) { *link = sgf_node_duplicate_to_given_depth (node, tree, node_copy, depth - 1); } } return node_copy; } /* Find a property specified by type in a given node. If a property * of this type is found, (*link) is set to point to the link to the * found property and nonzero is returned. Otherwise, return value is * zero (*link) is set to point to the link on which to insert a * property of given type. * * Maybe `SgfProperty ***link' is not the easiest thing to explain, * but it is very easy to work with (see `sgf-parser.c'.) */ int sgf_node_find_property (SgfNode *node, SgfType type, SgfProperty ***link) { SgfProperty **internal_link; assert (node); for (internal_link = &node->properties; *internal_link; internal_link = & (*internal_link)->next) { if ((*internal_link)->type >= type) { if (link) *link = internal_link; return (*internal_link)->type == type; } } if (link) *link = internal_link; return 0; } /* Find an unknown property by its identifier (name). Return value * and the meaning of (*link) variable are the same as for * sgf_node_find_property() function above. */ int sgf_node_find_unknown_property (SgfNode *node, char *id, int length, SgfProperty ***link) { assert (node); assert (id); assert (link); if (sgf_node_find_property (node, SGF_UNKNOWN, link)) { for (; **link; *link = & (**link)->next) { char *stored_id = (**link)->value.unknown_value_list->first->text; int relation = strncmp (stored_id, id, length); if (relation > 0) return 0; if (relation == 0 && !stored_id[length]) return 1; } } return 0; } /* Return nonzero if a given node contains at least one game-info * property or, in other words, is a game-info node. */ int sgf_node_is_game_info_node (const SgfNode *node) { const SgfProperty *property; assert (node); for (property = node->properties; property; property = property->next) { if (property->type >= SGF_FIRST_GAME_INFO_PROPERTY) return property->type <= SGF_LAST_GAME_INFO_PROPERTY; } return 0; } /* Functions below are used for retrieving specific properties' * values. They are of higher level than sgf_node_find_property() and * should always be used instead of the latter outside SGF code. * * Note that their code overlaps with sgf_node_find_property() * somewhat, but since it is simple anyway, it seems that the extra * couple of lines is a good exchange for the `const' modifier. */ /* This macro is used in many of the below function. */ #define GET_PROPERTY_VALUE(type_assertion, return_field, fail_value) \ do { \ const SgfProperty *property; \ assert (node); \ assert (type_assertion); \ for (property = node->properties; \ property && property->type <= type; \ property = property->next) { \ if (property->type == type) \ return property->value.return_field; \ } \ return fail_value; \ } while (0) /* Get the value of property of specified type with `number' value * type. If such a property has not been found, return value is zero * and (*number) remains untouched. */ int sgf_node_get_number_property_value (const SgfNode *node, SgfType type, int *number) { const SgfProperty *property; assert (node); assert (property_info[type].value_type == SGF_NUMBER); for (property = node->properties; property && property->type <= type; property = property->next) { if (property->type == type) { *number = property->value.number; return 1; } } return 0; } /* Get the value of `double' property of specified type. Value of 1 * means "normal", 2--"emphasized. Zero means there's no such * property at all. */ int sgf_node_get_double_property_value (const SgfNode *node, SgfType type) { GET_PROPERTY_VALUE (property_info[type].value_type == SGF_DOUBLE, emphasized, 0); } /* Get the value of specified `color' property or EMPTY if it is * not present. */ int sgf_node_get_color_property_value (const SgfNode *node, SgfType type) { GET_PROPERTY_VALUE (property_info[type].value_type == SGF_COLOR, color, EMPTY); } /* Return handicap (`HA') property value if it is stored in the given * node, or -1 otherwise. Handicaps are stored as text internally, * because SGF specification requires to preserve illegally formated * game-info properties. Therefore, some validation tricks are * necessary before returning anything. */ int sgf_node_get_handicap (const SgfNode *node) { const char *text = sgf_node_get_text_property_value (node, SGF_HANDICAP); if (text) { int handicap = atoi (text); if (0 <= handicap && handicap <= BOARD_MAX_POSITIONS) { char buffer[32]; utils_ncprintf (buffer, sizeof buffer, "%d", handicap); if (strcmp (text, buffer) == 0) return handicap; } } return -1; } int sgf_node_get_komi (const SgfNode *node, double *komi) { const char *text = sgf_node_get_text_property_value (node, SGF_KOMI); if (text) return utils_parse_double (text, komi); return 0; } SgfResult sgf_node_get_result (const SgfNode *node, double *score) { const char *result = sgf_node_get_text_property_value (node, SGF_RESULT); if (result) { if (strcmp (result, "?") == 0) return SGF_RESULT_UNKNOWN; if (strcmp (result, "Draw") == 0 || strcmp (result, "0") == 0) return SGF_RESULT_DRAW; if (strcmp (result, "Void") == 0) return SGF_RESULT_VOID; if ((*result == 'B' || *result == 'W') && *(result + 1) == '+') { int color_index = (*result == 'B' ? BLACK_INDEX : WHITE_INDEX); result += 2; if (! *result) return SGF_RESULT_WIN | color_index; if (strcmp (result, "F") == 0 || strcmp (result, "Forfeit") == 0) return SGF_RESULT_WIN_BY_FORFEIT | color_index; if (strcmp (result, "R") == 0 || strcmp (result, "Resign") == 0) return SGF_RESULT_WIN_BY_RESIGNATION | color_index; if (strcmp (result, "T") == 0 || strcmp (result, "Time") == 0) return SGF_RESULT_WIN_BY_TIME | color_index; if ('0' <= *result && *result <= '9' && utils_parse_double (result, score)) return SGF_RESULT_WIN_BY_SCORE | color_index; } return SGF_RESULT_INVALID; } return SGF_RESULT_NOT_SET; } int sgf_node_get_time_limit (const SgfNode *node, double *time_limit) { const char *text = sgf_node_get_text_property_value (node, SGF_TIME_LIMIT); if (text) return utils_parse_double (text, time_limit); return 0; } /* Get the value of `real' property of specified type. Return value * is the same as for sgf_node_get_number_property_value(). */ int sgf_node_get_real_property_value (const SgfNode *node, SgfType type, double *value) { const SgfProperty *property; assert (node); assert (property_info[type].value_type == SGF_REAL); for (property = node->properties; property && property->type <= type; property = property->next) { if (property->type == type) { #if SGF_REAL_VALUES_ALLOCATED_SEPARATELY *value = * property->value.real; #else *value = property->value.real; #endif return 1; } } return 0; } const char * sgf_node_get_text_property_value (const SgfNode *node, SgfType type) { GET_PROPERTY_VALUE ((property_info[type].value_type == SGF_SIMPLE_TEXT || property_info[type].value_type == SGF_FAKE_SIMPLE_TEXT || property_info[type].value_type == SGF_TEXT), text, NULL); } const BoardPositionList * sgf_node_get_list_of_point_property_value (const SgfNode *node, SgfType type) { GET_PROPERTY_VALUE ((property_info[type].value_type == SGF_LIST_OF_POINT || property_info[type].value_type == SGF_ELIST_OF_POINT), position_list, NULL); } const SgfVectorList * sgf_node_get_list_of_vector_property_value (const SgfNode *node, SgfType type) { GET_PROPERTY_VALUE (property_info[type].value_type == SGF_LIST_OF_VECTOR, vector_list, NULL); } const SgfLabelList * sgf_node_get_list_of_label_property_value (const SgfNode *node, SgfType type) { GET_PROPERTY_VALUE (property_info[type].value_type == SGF_LIST_OF_LABEL, label_list, NULL); } /* Functions for adding/overwriting property values. */ int sgf_node_add_none_property (SgfNode *node, SgfGameTree *tree, SgfType type) { SgfProperty **link; assert (node); assert (property_info[type].value_type == SGF_NONE); if (!sgf_node_find_property (node, type, &link)) { *link = sgf_property_new (tree, type, *link); return 1; } return 0; } int sgf_node_add_number_property (SgfNode *node, SgfGameTree *tree, SgfType type, int number, int overwrite) { SgfProperty **link; assert (node); assert (property_info[type].value_type == SGF_NUMBER || property_info[type].value_type == SGF_DOUBLE || property_info[type].value_type == SGF_COLOR); if (!sgf_node_find_property (node, type, &link)) { *link = sgf_property_new (tree, type, *link); (*link)->value.number = number; return 1; } if (overwrite) { (*link)->value.number = number; return 1; } return 0; } int sgf_node_add_real_property (SgfNode *node, SgfGameTree *tree, SgfType type, double value, int overwrite) { SgfProperty **link; assert (node); assert (property_info[type].value_type == SGF_REAL); if (!sgf_node_find_property (node, type, &link)) { *link = sgf_property_new (tree, type, *link); #if SGF_REAL_VALUES_ALLOCATED_SEPARATELY (*link)->value.real = utils_duplicate_buffer (&value, sizeof (double)); #else (*link)->value.real = value; #endif return 1; } if (overwrite) { #if SGF_REAL_VALUES_ALLOCATED_SEPARATELY * (*link)->value.real = value; #else (*link)->value.real = value; #endif return 1; } return 0; } int sgf_node_add_pointer_property (SgfNode *node, SgfGameTree *tree, SgfType type, void *pointer, int overwrite) { SgfProperty **link; void *pointer_to_free; assert (node); assert (SGF_FIRST_MALLOC_TYPE <= property_info[type].value_type && property_info[type].value_type <= SGF_LAST_MALLOC_TYPE && property_info[type].value_type != SGF_REAL && type != SGF_UNKNOWN); if (!sgf_node_find_property (node, type, &link)) { *link = sgf_property_new (tree, type, *link); (*link)->value.memory_block = pointer; return 1; } pointer_to_free = (overwrite ? (*link)->value.memory_block : pointer); switch (property_info[type].value_type) { default: utils_free (pointer_to_free); break; case SGF_LIST_OF_LABEL: sgf_label_list_delete (pointer_to_free); break; case SGF_FIGURE_DESCRIPTION: if (pointer_to_free) sgf_figure_description_delete (pointer_to_free); break; } if (overwrite) { (*link)->value.memory_block = pointer; return 1; } return 0; } /* Find and delete property of given type in the node. Return nonzero * if succeded, or zero if there is no such property. */ int sgf_node_delete_property (SgfNode *node, SgfGameTree *tree, SgfType type) { SgfProperty **link; assert (node); if (sgf_node_find_property (node, type, &link)) { SgfProperty *next_property = (*link)->next; sgf_property_delete (*link, tree); *link = next_property; return 1; } return 0; } /* Split given node into two, leaving all root, game info, setup and * node name properties in the node and moving the rest into its child * (which is created). * * This is a low level function, which should only be used by SGF * parser. It assumes that the node doesn't have any children yet. */ void sgf_node_split (SgfNode *node, SgfGameTree *tree) { SgfProperty *property; SgfProperty **node_link; SgfProperty **child_link; assert (tree); assert (node); node->child = sgf_node_new (tree, node); node->child->move_color = node->move_color; node->child->move_point = node->move_point; node->move_color = EMPTY; node_link = &node->properties; child_link = &node->child->properties; for (property = node->properties; property; property = property->next) { /* This is mainly to avoid GCC warning. */ SgfType type = property->type; if ((SGF_FIRST_ROOT_PROPERTY <= type && type <= SGF_LAST_ROOT_PROPERTY) || (SGF_FIRST_GAME_INFO_PROPERTY <= type && type <= SGF_LAST_GAME_INFO_PROPERTY) || (SGF_FIRST_SETUP_PROPERTY <= type && type <= SGF_LAST_SETUP_PROPERTY) || type == SGF_NODE_NAME) { *node_link = property; node_link = &property->next; } else { *child_link = property; child_link = &property->next; } } *node_link = NULL; *child_link = NULL; } /* Get ``next'' node in tree-traversing sense. See * sgf_game_tree_traverse_forward() for details. */ SgfNode * sgf_node_traverse_forward (const SgfNode *node) { assert (node); if (node->child) return node->child; while (!node->next) { node = node->parent; if (!node) return NULL; } return node->next; } /* Get ``previous'' node in tree-traversing sense. See * sgf_game_tree_traverse_backward() for details. */ SgfNode * sgf_node_traverse_backward (const SgfNode *node) { SgfNode *parent; SgfNode *result; assert (node); parent = node->parent; if (!parent) return NULL; result = parent->child; if (result == node) return parent; while (result->next != node) result = result->next; while (1) { if (!result->child) return result; result = result->child; while (result->next) result = result->next; } } int sgf_node_count_subtree_nodes (const SgfNode *node) { int num_nodes = 0; assert (node); /* Count number of nodes in non-branching node sequence. */ do { num_nodes++; node = node->child; } while (node && !node->next); /* Recursively count nodes in all branches, if any. */ while (node) { num_nodes += sgf_node_count_subtree_nodes (node); node = node->next; } return num_nodes; } /* Dynamically allocate an SgfProperty structure and initialize its * type and pointer to the next property with given values. */ inline SgfProperty * sgf_property_new (SgfGameTree *tree, SgfType type, SgfProperty *next) { SgfProperty *property = memory_pool_alloc (&tree->property_pool); property->type = type; property->next = next; return property; } /* Free a previously allocated SgfProperty structure and, if needed, * its value. Only values of `simpletext', `text' or any of list * types need to be freed. Values of other types are stored in the * property structure itself. */ inline void sgf_property_delete (SgfProperty *property, SgfGameTree *tree) { assert (property); assert (tree); free_property_value (property); memory_pool_free (&tree->property_pool, property); } /* Delete property attached to a given `link'. */ void sgf_property_delete_at_link (SgfProperty **link, SgfGameTree *tree) { SgfProperty *next_property = (*link)->next; sgf_property_delete (*link, tree); *link = next_property; } /* Copy given `property' and its value for use in the given game * `tree'. */ SgfProperty * sgf_property_duplicate (const SgfProperty *property, SgfGameTree *tree, SgfProperty *next) { SgfProperty *property_copy = sgf_property_new (tree, property->type, next); switch (property_info[property->type].value_type) { case SGF_NUMBER: case SGF_DOUBLE: case SGF_COLOR: property_copy->value.number = property->value.number; break; case SGF_REAL: #if SGF_REAL_VALUES_ALLOCATED_SEPARATELY property_copy->value.real = utils_duplicate_buffer (property->value.real, sizeof (double)); #else property_copy->value.real = property->value.real; #endif break; case SGF_SIMPLE_TEXT: case SGF_FAKE_SIMPLE_TEXT: case SGF_TEXT: property_copy->value.text = utils_duplicate_string (property->value.text); break; case SGF_TYPE_UNKNOWN: property_copy->value.unknown_value_list = string_list_new (); string_list_duplicate_items (property_copy->value.unknown_value_list, property->value.unknown_value_list); break; case SGF_LIST_OF_POINT: case SGF_ELIST_OF_POINT: property_copy->value.position_list = board_position_list_duplicate (property->value.position_list); break; case SGF_LIST_OF_VECTOR: property_copy->value.vector_list = sgf_vector_list_duplicate (property->value.vector_list); break; case SGF_LIST_OF_LABEL: property_copy->value.label_list = sgf_label_list_duplicate (property->value.label_list); break; case SGF_FIGURE_DESCRIPTION: property_copy->value.figure = sgf_figure_description_duplicate (property->value.figure); break; default: /* Make sure all property types are handled. */ assert (property_info[property->type].value_type == SGF_NONE); }; return property_copy; } void sgf_property_free_value (SgfValueType value_type, SgfValue *value) { /* `SGF_REAL' type may or may not belong to this range. */ if (SGF_FIRST_MALLOC_TYPE <= value_type && value_type <= SGF_LAST_MALLOC_TYPE) { switch (value_type) { default: utils_free (value->memory_block); break; case SGF_LIST_OF_LABEL: sgf_label_list_delete (value->label_list); break; case SGF_FIGURE_DESCRIPTION: if (value->figure) sgf_figure_description_delete (value->figure); break; case SGF_TYPE_UNKNOWN: string_list_delete (value->unknown_value_list); break; } } } inline static void free_property_value (SgfProperty *property) { sgf_property_free_value (property_info[property->type].value_type, &property->value); } #define SGF_VECTOR_LIST_DEFAULT_INITIAL_SIZE 0x20 #define SGF_VECTOR_LIST_SIZE_INCREMENT 0x80 SgfVectorList * sgf_vector_list_new (int num_vectors) { SgfVectorList *list; if (num_vectors < 0) num_vectors = SGF_VECTOR_LIST_DEFAULT_INITIAL_SIZE; list = utils_malloc (sizeof (SgfVectorList) + (num_vectors - 1) * sizeof (SgfVector)); list->allocated_num_vectors = num_vectors; list->num_vectors = 0; return list; } SgfVectorList * sgf_vector_list_shrink (SgfVectorList *list) { assert (list); if (list->allocated_num_vectors > list->num_vectors) { list = utils_realloc (list, (sizeof (SgfVectorList) + (list->num_vectors - 1) * sizeof (SgfVector))); list->allocated_num_vectors = list->num_vectors; } return list; } SgfVectorList * sgf_vector_list_add_vector (SgfVectorList *list, BoardPoint from_point, BoardPoint to_point) { assert (list); if (list->num_vectors == list->allocated_num_vectors) { list->allocated_num_vectors += SGF_VECTOR_LIST_SIZE_INCREMENT; list = utils_realloc (list, (sizeof (SgfVectorList) + ((list->allocated_num_vectors - 1) * sizeof (SgfVector)))); } list->vectors[list->num_vectors].from_point = from_point; list->vectors[list->num_vectors++].to_point = to_point; return list; } int sgf_vector_list_has_vector (const SgfVectorList *list, BoardPoint from_point, BoardPoint to_point) { int k; assert (list); for (k = 0; k < list->num_vectors; k++) { if (list->vectors[k].from_point.x == from_point.x && list->vectors[k].from_point.y == from_point.y && list->vectors[k].to_point.x == to_point.x && list->vectors[k].to_point.y == to_point.y) return 1; } return 0; } SgfVectorList * sgf_vector_list_duplicate (const SgfVectorList *list) { SgfVectorList *list_copy; assert (list); list_copy = utils_malloc (sizeof (SgfVectorList) + (list->num_vectors - 1) * sizeof (SgfVector)); list_copy->allocated_num_vectors = list->num_vectors; list_copy->num_vectors = list->num_vectors; memcpy (list_copy->vectors, list->vectors, list->num_vectors * sizeof (SgfVector)); return list_copy; } SgfLabelList * sgf_label_list_new (int num_labels, BoardPoint *points, char **labels) { SgfLabelList *list; int k; assert (0 <= num_labels && num_labels < BOARD_MAX_POSITIONS); list = utils_malloc (sizeof (SgfLabelList) + (num_labels - 1) * sizeof (SgfLabel)); list->num_labels = num_labels; for (k = 0; k < num_labels; k++) { list->labels[k].point = points[k]; list->labels[k].text = labels[k]; } return list; } SgfLabelList * sgf_label_list_new_empty (int num_labels) { SgfLabelList *list; assert (0 <= num_labels && num_labels < BOARD_MAX_POSITIONS); list = utils_malloc (sizeof (SgfLabelList) + (num_labels - 1) * sizeof (SgfLabel)); list->num_labels = num_labels; return list; } void sgf_label_list_delete (SgfLabelList *list) { int k; assert (list); for (k = 0; k < list->num_labels; k++) utils_free (list->labels[k].text); utils_free (list); } const char * sgf_label_list_get_label (const SgfLabelList *list, BoardPoint point) { assert (list); if (list->num_labels > 0) { if (list->num_labels > 1) { SgfLabel key = { { point.x, point.y }, NULL }; SgfLabel *label = bsearch (&key, list->labels, list->num_labels, sizeof (SgfLabel), compare_sgf_labels); if (label) return label->text; } else { if (POINTS_ARE_EQUAL (list->labels[0].point, point)) return list->labels[0].text; } } return NULL; } /* FIXME: It is better to hack at existing lists rather than creating * new ones all the times. Tweak all * sgf_node_get_list_of_*_property_value() to return non-const * values and expand undo module to handle incremental list * changes. */ SgfLabelList * sgf_label_list_set_label (const SgfLabelList *old_list, BoardPoint point, char *label_text) { SgfLabelList *new_list; int num_labels; int i; int j; if (!old_list) { if (label_text) return sgf_label_list_new (1, &point, &label_text); else return NULL; } num_labels = old_list->num_labels; if (label_text) num_labels++; if (sgf_label_list_get_label (old_list, point)) num_labels--; new_list = sgf_label_list_new_empty (num_labels); for (i = 0, j = 0; (i < old_list->num_labels && POINTS_LESS_THAN (old_list->labels[i].point, point)); i++, j++) { new_list->labels[j].point = old_list->labels[i].point; new_list->labels[j].text = utils_duplicate_string (old_list->labels[i].text); } if (i < old_list->num_labels && POINTS_ARE_EQUAL (old_list->labels[i].point, point)) i++; if (label_text) { new_list->labels[j].point = point; new_list->labels[j].text = label_text; j++; } while (j < num_labels) { new_list->labels[j].point = old_list->labels[i].point; new_list->labels[j].text = utils_duplicate_string (old_list->labels[i].text); i++; j++; } return new_list; } SgfLabelList * sgf_label_list_duplicate (const SgfLabelList *list) { SgfLabelList *list_copy = sgf_label_list_new_empty (list->num_labels); int k; assert (list); for (k = 0; k < list->num_labels; k++) { list_copy->labels[k].point = list->labels[k].point; list_copy->labels[k].text = utils_duplicate_string (list->labels[k].text); } return list_copy; } int sgf_label_lists_are_equal (const SgfLabelList *first_list, const SgfLabelList *second_list) { int k; assert (first_list); assert (second_list); if (first_list->num_labels != second_list->num_labels) return 0; for (k = 0; k < first_list->num_labels; k++) { if (!POINTS_ARE_EQUAL (first_list->labels[k].point, second_list->labels[k].point) || (strcmp (first_list->labels[k].text, second_list->labels[k].text) != 0)) return 0; } return 1; } /* Determine if the `list' contains given `label' at some position. */ int sgf_label_list_contains_label (const SgfLabelList *list, const char *label) { int k; assert (list); assert (label); for (k = 0; k < list->num_labels; k++) { if (strcmp (list->labels[k].text, label) == 0) return 1; } return 0; } static int compare_sgf_labels (const void *first_label, const void *second_label) { const BoardPoint first_point = ((const SgfLabel *) first_label)->point; const BoardPoint second_point = ((const SgfLabel *) second_label)->point; if (first_point.y < second_point.y) return -1; if (first_point.y > second_point.y) return 1; return (first_point.x < second_point.x ? -1 : (first_point.x > second_point.x ? 1 : 0)); } SgfFigureDescription * sgf_figure_description_new (int flags, char *diagram_name) { SgfFigureDescription *figure = utils_malloc (sizeof (SgfFigureDescription)); figure->flags = flags; figure->diagram_name = diagram_name; return figure; } SgfFigureDescription * sgf_figure_description_duplicate (const SgfFigureDescription *figure) { SgfFigureDescription *figure_copy = utils_malloc (sizeof (SgfFigureDescription)); assert (figure); figure_copy->flags = figure->flags; figure_copy->diagram_name = utils_duplicate_string (figure->diagram_name); return figure_copy; } void sgf_figure_description_delete (SgfFigureDescription *figure) { assert (figure); utils_free (figure->diagram_name); utils_free (figure); } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/sgf/sgf-tree-map.c0000644000175000017500000011217310367243376015517 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* Generate flat ``maps'' of SGF trees. The used layout is the same * as in cGoban 1, but the speed is much higher :-) * * Work is distributed like this: * * - update_internal_map_data() calculates map width and height and, * for very large trees, stores some internal data at some nodes; * this data is later used to remap only necessary tree chunks * instead of the whole tree. * * - update_internal_view_port() uses do_update_internal_view_port() * to actually generate a rectangular piece of the map (view port), * using the data previously stored by update_internal_map_data(). */ #include "sgf.h" #include "utils.h" #include #ifdef HAVE_MEMORY_H #include #endif /* Define to non-zero to make various functions report run times and * other performance information. */ #define REPORT_PERFORMANCE_STATISTICS 0 #if REPORT_PERFORMANCE_STATISTICS #include #include #define DECLARE_TIME_VARIABLES \ struct timeval start_time; \ struct timeval finish_time #define STORE_STARTING_TIME gettimeofday (&start_time, NULL) #define PRINT_RUN_TIME(function_name) \ do { \ gettimeofday (&finish_time, NULL); \ fprintf (stderr, "Time spent in " #function_name "(): %f\n", \ ((finish_time.tv_usec - start_time.tv_usec) * 0.000001 \ + (finish_time.tv_sec - start_time.tv_sec))); \ } while (0) #else /* not REPORT_PERFORMANCE_STATISTICS */ #define DECLARE_TIME_VARIABLES #define STORE_STARTING_TIME #define PRINT_RUN_TIME(function_name) #endif /* not REPORT_PERFORMANCE_STATISTICS */ #define MIN_NODES_PER_DATA_CHUNK 0x4000 #define Y_LEVEL_ARRAY_INITIAL_SIZE 0x400 /* Must be a power of two. */ #define Y_LEVEL_ARRAY_SIZE_GRAIN 0x400 #define VIEW_PORT_NODE(tree, x, y) \ ((tree)->view_port_nodes \ + (((y) - (tree)->view_port_y0) \ * ((tree)->view_port_x1 - (tree)->view_port_x0)) \ + ((x) - (tree)->view_port_x0)) #define VIEW_PORT_LINE_ADJUSTMENT(tree, width) \ (((tree)->view_port_x1 - (tree)->view_port_x0) - (width)) static SgfGameTreeMapData * find_intermediate_data_for_node (const SgfGameTree *tree, const SgfNode *node, int strictly_before_node); static int view_port_is_after_data_point (const SgfGameTree *tree, const SgfGameTreeMapData *intermediate_data); static int view_port_is_before_data_point (const SgfGameTree *tree, const SgfGameTreeMapData *intermediate_data); static void free_map_data_point (SgfGameTreeMapData *data_point); static void update_internal_map_data (SgfGameTree *tree); static void update_internal_view_port (SgfGameTree *tree, int view_port_x0, int view_port_y0, int view_port_x1, int view_port_y1); static SgfGameTreeMapLine * do_update_internal_view_port (const SgfGameTree *tree, const SgfGameTreeMapData *intermediate_data, SgfGameTreeMapLine *line_pointer); static int get_node_coordinates (SgfGameTree *tree, const SgfNode *node_to_find, int *node_x, int *node_y); /* Invalidate `tree's map or a portion of it. If `node' is non-NULL, * assume that the map remains valid everywhere _before_ the node (in * sgf_node_traverse_backward() sense) and invalidate the rest. If * `node' is NULL (or equals to `tree->root'), invalidate the entire * map. * * Invalidating entire map always frees all allocated memory. */ void sgf_game_tree_invalidate_map (SgfGameTree *tree, SgfNode *node) { assert (tree); if (tree->map_data_list) { SgfGameTreeMapData *last_valid_data_point = (node ? find_intermediate_data_for_node (tree, node, 1) :NULL); if (last_valid_data_point) { SgfGameTreeMapData *data_point; int invalidate_view_port = 0; if (last_valid_data_point != tree->last_valid_data_point) { for (data_point = last_valid_data_point->next; data_point != tree->last_valid_data_point; data_point = data_point->next) { utils_free (data_point->y_level); data_point->y_level = NULL; } tree->last_valid_data_point = last_valid_data_point; if (tree->view_port_nodes) { invalidate_view_port = !view_port_is_before_data_point (tree, last_valid_data_point); } } if (!invalidate_view_port) return; } else { free_map_data_point (tree->map_data_list); tree->map_data_list = NULL; } } /* Invalidate the view port. */ utils_free (tree->view_port_nodes); utils_free (tree->view_port_lines); tree->view_port_nodes = NULL; tree->view_port_lines = NULL; } void sgf_game_tree_get_map_dimensions (SgfGameTree *tree, int *map_width, int *map_height) { assert (tree); if (map_width || map_height) { update_internal_map_data (tree); if (map_width) *map_width = tree->map_width; if (map_height) *map_height = tree->map_height; } } void sgf_game_tree_fill_map_view_port (SgfGameTree *tree, int view_port_x0, int view_port_y0, int view_port_x1, int view_port_y1, SgfNode ***view_port_nodes, SgfGameTreeMapLine **view_port_lines, int *num_view_port_lines) { int view_port_width = view_port_x1 - view_port_x0; int view_port_height = view_port_y1 - view_port_y0; assert (tree); assert (0 <= view_port_x0 && view_port_x0 < view_port_x1); assert (0 <= view_port_y0 && view_port_y0 < view_port_y1); assert (view_port_nodes); assert (view_port_lines); assert (num_view_port_lines); update_internal_view_port (tree, view_port_x0, view_port_y0, view_port_x1, view_port_y1); if (tree->view_port_x0 == view_port_x0 && tree->view_port_x1 == view_port_x1) { /* Just duplicate the required portion of view port. */ *view_port_nodes = utils_duplicate_buffer ((tree->view_port_nodes + ((view_port_y0 - tree->view_port_y0) * view_port_width)), (view_port_width * view_port_height * sizeof (SgfNode *))); } else { SgfNode **copy_pointer; SgfNode **original_pointer; int y; /* A little more complication. */ *view_port_nodes = utils_malloc (view_port_width * view_port_height * sizeof (SgfNode *)); copy_pointer = *view_port_nodes; original_pointer = VIEW_PORT_NODE (tree, view_port_x0, view_port_y0); for (y = 0; y < view_port_height; y++) { memcpy (copy_pointer, original_pointer, view_port_width * sizeof (SgfNode *)); copy_pointer += view_port_width; original_pointer += tree->view_port_x1 - tree->view_port_x0; } } *view_port_lines = utils_duplicate_buffer (tree->view_port_lines, (tree->num_view_port_lines * sizeof (SgfGameTreeMapLine))); *num_view_port_lines = tree->num_view_port_lines; } char * sgf_game_tree_get_current_branch_marks (SgfGameTree *tree, int view_port_x0, int view_port_y0, int view_port_x1, int view_port_y1) { int view_port_width = view_port_x1 - view_port_x0; int view_port_height = view_port_y1 - view_port_y0; char *current_branch_marks = utils_malloc (view_port_width * view_port_height * sizeof (char)); const SgfNode *const *view_port_scan; char *current_branch_marks_scan; int x; int y; SgfNode *node; assert (tree); assert (tree->current_node); assert (0 <= view_port_x0 && view_port_x0 < view_port_x1); assert (0 <= view_port_y0 && view_port_y0 < view_port_y1); update_internal_view_port (tree, view_port_x0, view_port_y0, view_port_x1, view_port_y1); for (view_port_scan = ((const SgfNode *const *) VIEW_PORT_NODE (tree, view_port_x0, view_port_y0)), current_branch_marks_scan = current_branch_marks, y = view_port_y0; y < view_port_y1; view_port_scan += VIEW_PORT_LINE_ADJUSTMENT (tree, view_port_width), y++) { for (x = view_port_x0; x < view_port_x1; x++) { if (*view_port_scan++) *current_branch_marks_scan++ = SGF_NON_CURRENT_BRANCH_NODE; else *current_branch_marks_scan++ = SGF_NO_NODE; } } node = tree->current_node; for (x = tree->current_node_depth; x > view_port_x0; x--) node = node->parent; do { if (x >= view_port_x0) { for (view_port_scan = ((const SgfNode *const *) VIEW_PORT_NODE (tree, x, view_port_y0)), y = view_port_y0; y < view_port_y1; view_port_scan += tree->view_port_x1 - tree->view_port_x0, y++) { if (*view_port_scan == node) { * (current_branch_marks + (y - view_port_y0) * view_port_width + (x - view_port_x0)) = (x < tree->current_node_depth ? SGF_CURRENT_BRANCH_HEAD_NODE : (x > tree->current_node_depth ? SGF_CURRENT_BRANCH_TAIL_NODE : SGF_CURRENT_NODE)); break; } } } if (!node->current_variation) { if (!node->child) return current_branch_marks; node->current_variation = node->child; } node = node->current_variation; x++; } while (x < view_port_x1); return current_branch_marks; } /* Store given `node' coordinates in the tree map in `node_x' and * `node_y' and return non-zero. However, this function can fail with * zero return value if the node is in a collapsed subtree (and thus * is not included in the map.) In this case `node_x' and `node_y' * are not modified. */ int sgf_game_tree_get_node_coordinates (SgfGameTree *tree, const SgfNode *node, int *node_x, int *node_y) { assert (tree); assert (node); assert (node_x); assert (node_y); /* First try simple solution. */ if (tree->view_port_nodes && sgf_game_tree_node_is_within_view_port (tree, node, tree->view_port_x0, tree->view_port_y0, tree->view_port_x1, tree->view_port_y1, node_x, node_y)) return 1; return get_node_coordinates (tree, node, node_x, node_y); } /* Check if the given `node' is within specified map view port and * return non-zero if it is. If `node_x' and `node_y' are non-NULL, * `node's coordinates are stored in them. * * It is legal to call this function with a different from current * view port, but this is not very efficient, as it will force view * port update. You should probably use * sgf_game_tree_get_node_coordinates() instead in such cases. */ int sgf_game_tree_node_is_within_view_port (SgfGameTree *tree, const SgfNode *node, int view_port_x0, int view_port_y0, int view_port_x1, int view_port_y1, int *node_x, int *node_y) { const SgfNode *const *view_port_scan; int view_port_width = view_port_x1 - view_port_x0; int x; int y; assert (tree); assert (node); assert (0 <= view_port_x0 && view_port_x0 < view_port_x1); assert (0 <= view_port_y0 && view_port_y0 < view_port_y1); update_internal_view_port (tree, view_port_x0, view_port_y0, view_port_x1, view_port_y1); for (view_port_scan = ((const SgfNode *const *) VIEW_PORT_NODE (tree, view_port_x0, view_port_y0)), y = view_port_y0; y < view_port_y1; view_port_scan += VIEW_PORT_LINE_ADJUSTMENT (tree, view_port_width), y++) { for (x = view_port_x0; x < view_port_x1; x++) { if (*view_port_scan++ == node) { if (node_x) *node_x = x; if (node_y) *node_y = y; return 1; } } } return 0; } static SgfGameTreeMapData * find_intermediate_data_for_node (const SgfGameTree *tree, const SgfNode *node, int strictly_before_node) { SgfGameTreeMapData *intermediate_data; if (strictly_before_node || !node->has_intermediate_map_data) { do { /* This is essentially a loop of inlined * sgf_node_traverse_backward(). However, we only stop at * leaves, since intermediate map data is stored only in leaves. */ SgfNode *previous_child; while (node->parent && node->parent->child == node) node = node->parent; if (!node->parent) return NULL; previous_child = node->parent->child; while (previous_child->next != node) previous_child = previous_child->next; for (node = previous_child; node->child; ) { node = node->child; while (node->next) node = node->next; } } while (!node->has_intermediate_map_data); } for (intermediate_data = tree->map_data_list; (intermediate_data != tree->last_valid_data_point && intermediate_data->node != node);) intermediate_data = intermediate_data->next; return intermediate_data; } static int view_port_is_after_data_point (const SgfGameTree *tree, const SgfGameTreeMapData *intermediate_data) { int last_valid_y_level = intermediate_data->last_valid_y_level; int x; if (tree->view_port_x0 > last_valid_y_level) { return (tree->view_port_y0 > intermediate_data->y_level[last_valid_y_level]); } for (x = tree->view_port_x0; x < tree->view_port_x1 && x <= last_valid_y_level; x++) { if (tree->view_port_y0 <= intermediate_data->y_level[x]) return 0; } return 1; } static int view_port_is_before_data_point (const SgfGameTree *tree, const SgfGameTreeMapData *intermediate_data) { int last_valid_y_level = intermediate_data->last_valid_y_level; int x; if (tree->view_port_x0 > last_valid_y_level) { return (tree->view_port_y1 <= intermediate_data->y_level[last_valid_y_level] + 1); } for (x = tree->view_port_x0; x < tree->view_port_x1 && x <= last_valid_y_level; x++) { if (tree->view_port_y1 > intermediate_data->y_level[x] + 1) return 0; } return 1; } static void free_map_data_point (SgfGameTreeMapData *data_point) { while (data_point) { SgfGameTreeMapData *next_data_point = data_point->next; data_point->node->has_intermediate_map_data = 0; utils_free (data_point->y_level); utils_free (data_point); data_point = next_data_point; } } /* Recompute map width and height and, maybe, internal data, if the * tree is large enough. The algorithm is explained in the comments * in the function. */ static void update_internal_map_data (SgfGameTree *tree) { SgfNode *node; int node_count; int x; int largest_x_so_far; int *y_level; int y_level_array_size; int last_valid_y_level; SgfGameTreeMapData **intermediate_data_link; DECLARE_TIME_VARIABLES; STORE_STARTING_TIME; if (tree->map_data_list && !tree->last_valid_data_point) { /* Nothing to update, everything is valid. */ return; } if (tree->map_data_list) { /* We have at least some chunks of intermediate data left from a * previous run. Skip corresponding part of the tree. */ last_valid_y_level = tree->last_valid_data_point->last_valid_y_level; y_level_array_size = ROUND_UP (last_valid_y_level + 1, Y_LEVEL_ARRAY_SIZE_GRAIN); y_level = utils_malloc (y_level_array_size * sizeof (int)); memcpy (y_level, tree->last_valid_data_point->y_level, (last_valid_y_level + 1) * sizeof (int)); node = tree->last_valid_data_point->node; x = tree->last_valid_data_point->x; largest_x_so_far = tree->last_valid_data_point->largest_x_so_far; node_count = 0; intermediate_data_link = &tree->last_valid_data_point->next; /* Maybe there are leftovers of invalidated data. */ free_map_data_point (*intermediate_data_link); } else { /* We have no data left from the previous run or there was no * previous run at all. Start from scratch. */ y_level_array_size = Y_LEVEL_ARRAY_INITIAL_SIZE; y_level = utils_malloc (y_level_array_size * sizeof (int)); y_level[0] = 0; last_valid_y_level = 0; /* First scan the tree ``trunk'', i.e. the main variation. It is * a little different from all else variations in that starting * `x' is zero. So it is broken out of the main loop below. */ node = tree->root; x = 0; while (node->child && !node->is_collapsed) { node = node->child; x++; } largest_x_so_far = x; node_count = x + 1; intermediate_data_link = &tree->map_data_list; } while (1) { /* Find the next branch fork by ascending the last layed out * branch in the root direction. */ while (!node->next) { if (!node->parent) { /* No more branch forks as we are at the root. */ goto finished; } x--; node = node->parent; } node = node->next; node_count++; if (x < last_valid_y_level) { /* This case is the most complicated. The branch may bend with * its first part going diagonally, like that marked with '@' * below: * * ...-O-O-O-O-O-O * \ \ * @ O-O * \ * @-@-@ */ if (node->child && !node->is_collapsed) { SgfNode *branch_scan_node; int branch_scan_x; int branch_highest_y; int branch_scan_delta; int branch_y; /* First scan the branch to find its main part's `y' * coordinate. Since `y_level' doesn't change past * `last_valid_y_level', we stop if we reach it. */ branch_scan_node = node->child; branch_scan_x = x + 1; while (branch_scan_x < last_valid_y_level && branch_scan_node->child && !branch_scan_node->is_collapsed) { branch_scan_node = branch_scan_node->child; branch_scan_x++; } branch_highest_y = y_level[branch_scan_x] + 1; /* Now find where the branch bends. More precisely, we find * such `y' coordinate of the first branch node that bended * branch doesn't collide with any already layed out branches. */ for (branch_y = y_level[x] + 1, branch_scan_delta = 1; branch_scan_delta < branch_highest_y - branch_y; branch_scan_delta++) { branch_y = MAX (branch_y, (y_level[x + branch_scan_delta] + 1 - branch_scan_delta)); } /* Update `y_level' for (x - 1) (because of the branch * attachment line) and the diagonal part of the branch. */ y_level[x - 1] = branch_y - 1; y_level[x] = branch_y; while (branch_y < branch_highest_y) { y_level[++x] = ++branch_y; node = node->child; node_count++; } if (branch_y >= y_level[last_valid_y_level]) { /* We reach a new highest `y' for the map. Truncate * `y_level'. */ last_valid_y_level = x; /* Skip the rest of the nodes. */ while (node->child && !node->is_collapsed) { x++; node = node->child; node_count++; } } else { int x_scan; /* Skip the rest of the nodes, but also update `y_level'. * We are guaranteed to remain in the allocated part of it, * since `branch_y' is small enough. */ while (node->child && !node->is_collapsed) { y_level[++x] = branch_y; node = node->child; node_count++; } /* We need to update `y_level'. */ for (x_scan = x + 1; y_level[x_scan] < branch_y; x_scan++) y_level[x_scan] = branch_y; } } else { /* In case the branch has only one (non-collapsed) node, we * skip all the above complications at once. */ y_level[x - 1] = y_level[x]++; if (y_level[x] >= y_level[last_valid_y_level]) { /* New highest `y' coordinate. */ last_valid_y_level = x; } else { int y = y_level[x]; int x_scan; /* We need to update `y_level'. */ for (x_scan = x + 1; y_level[x_scan] < y; x_scan++) y_level[x_scan] = y; } } } else { /* The branch starts at or beyond `last_valid_y_level'. It can * only go horizontally, so this case is simpler. */ if (x > last_valid_y_level) { int previous_branch_y; /* We are past `last_valid_y_level'. Here is an example: * * ...-O-O * \ * O-O-O-O-O-O-O-O * ^ \ * | @-@-@-@ * `last_valid_y_level' */ if (x > y_level_array_size) { /* The only case when we need to increase the `y_level' * array size. */ y_level_array_size = ROUND_UP (x, Y_LEVEL_ARRAY_SIZE_GRAIN); y_level = utils_realloc (y_level, (y_level_array_size * sizeof (int))); } /* Fill `y_level' between `last_valid_y_level' and `x', at the * same time setting the former to be equal to the latter. */ previous_branch_y = y_level[last_valid_y_level]; while (++last_valid_y_level < x) y_level[last_valid_y_level] = previous_branch_y; y_level[x] = previous_branch_y + 1; } else { /* `x' is the same as `last_valid_y_level'. Basically the * same as the above case except that we don't need to * increase `last_valid_y_level', so this all reduces to a * single statement. */ y_level[x - 1] = y_level[x]++; } /* Skip the nodes. They are all beyond `last_valid_y_level', so * we don't need to update `y_level'. */ while (node->child && !node->is_collapsed) { x++; node = node->child; node_count++; } } /* Maybe this branch'es leaf is beyond the known tree width? */ if (x > largest_x_so_far) largest_x_so_far = x; if (node_count >= MIN_NODES_PER_DATA_CHUNK) { SgfGameTreeMapData *intermediate_data = utils_malloc (sizeof (SgfGameTreeMapData)); intermediate_data->node = node; intermediate_data->x = x; intermediate_data->y_level = utils_duplicate_buffer (y_level, (last_valid_y_level + 1) * sizeof (int)); intermediate_data->last_valid_y_level = last_valid_y_level; intermediate_data->largest_x_so_far = largest_x_so_far; *intermediate_data_link = intermediate_data; intermediate_data_link = &intermediate_data->next; node->has_intermediate_map_data = 1; node_count = 0; } } finished: /* Fix map width by adding missing 1. Write map height. */ tree->map_width = largest_x_so_far + 1; tree->map_height = y_level[last_valid_y_level] + 1; /* All intermediate data is valid. */ tree->last_valid_data_point = NULL; /* Terminate the list. */ *intermediate_data_link = NULL; utils_free (y_level); PRINT_RUN_TIME (update_internal_map_data); } static void update_internal_view_port (SgfGameTree *tree, int view_port_x0, int view_port_y0, int view_port_x1, int view_port_y1) { int view_port_width = view_port_x1 - view_port_x0; int view_port_height = view_port_y1 - view_port_y0; SgfGameTreeMapLine *line_pointer; DECLARE_TIME_VARIABLES; #if REPORT_PERFORMANCE_STATISTICS int num_total_tree_chunks; int num_skipped_tree_chunks = 0; const SgfGameTreeMapData *intermediate_data_scan; for (intermediate_data_scan = tree->map_data_list, num_total_tree_chunks = 1; intermediate_data_scan; intermediate_data_scan = intermediate_data_scan->next) num_total_tree_chunks++; #endif /* not REPORT_PERFORMANCE_STATISTICS */ if (tree->view_port_nodes && tree->view_port_x0 <= view_port_x0 && tree->view_port_y0 <= view_port_y0 && tree->view_port_x1 >= view_port_x1 && tree->view_port_y1 >= view_port_y1) { /* Nothing to update. */ return; } tree->view_port_x0 = view_port_x0; tree->view_port_y0 = view_port_y0; tree->view_port_x1 = view_port_x1; tree->view_port_y1 = view_port_y1; update_internal_map_data (tree); STORE_STARTING_TIME; utils_free (tree->view_port_nodes); utils_free (tree->view_port_lines); tree->view_port_nodes = utils_malloc0 (view_port_width * view_port_height * sizeof (SgfNode *)); tree->view_port_lines = utils_malloc ((3 * view_port_width * view_port_height + 1) * sizeof (SgfGameTreeMapLine)); line_pointer = tree->view_port_lines; if (tree->map_data_list) { const SgfGameTreeMapData *intermediate_data = NULL; const SgfGameTreeMapData *next_intermediate_data = tree->map_data_list; /* FIXME: There is probably still space for improvement here. * This code performs well in near-leaves parts of the * tree, but doesn't skip much around tree root. */ while (view_port_is_after_data_point (tree, next_intermediate_data)) { intermediate_data = next_intermediate_data; next_intermediate_data = intermediate_data->next; #if REPORT_PERFORMANCE_STATISTICS num_skipped_tree_chunks++; #endif if (!next_intermediate_data) break; } while (1) { /* Skip chunks that lie completely to the right of the view * port. This can sometimes give large advantage when browsing * near the root of the tree. We add 1 to `view_port_x1' here * to avoid losing certain lines. */ if (!intermediate_data || !next_intermediate_data || intermediate_data->last_valid_y_level < view_port_x1 + 1 || next_intermediate_data->last_valid_y_level < view_port_x1 + 1 || (intermediate_data->y_level[view_port_x1 + 1] < next_intermediate_data->y_level[view_port_x1 + 1])) { line_pointer = do_update_internal_view_port (tree, intermediate_data, line_pointer); } #if REPORT_PERFORMANCE_STATISTICS else num_skipped_tree_chunks++; #endif intermediate_data = next_intermediate_data; if (!intermediate_data || view_port_is_before_data_point (tree, intermediate_data)) break; next_intermediate_data = intermediate_data->next; } #if REPORT_PERFORMANCE_STATISTICS while (intermediate_data) { num_skipped_tree_chunks++; intermediate_data = intermediate_data->next; } #endif } else line_pointer = do_update_internal_view_port (tree, NULL, line_pointer); tree->num_view_port_lines = (line_pointer - tree->view_port_lines); tree->view_port_lines = utils_realloc (tree->view_port_lines, (char *) line_pointer - (char *) tree->view_port_lines); PRINT_RUN_TIME (update_internal_view_port); #if REPORT_PERFORMANCE_STATISTICS fprintf (stderr, "update_internal_view_port(): Skipped %d of %d tree chunks\n", num_skipped_tree_chunks, num_total_tree_chunks); #endif } #define IS_WITHIN_VIEW_PORT(x, y) \ (view_port_x0 <= (x) && (x) < view_port_x1 \ && view_port_y0 <= (y) && (y) < view_port_y1) #define WRITE_VIEW_PORT_NODE(x, y, node) \ do { \ * (tree->view_port_nodes + \ ((y) - view_port_y0) * view_port_width + ((x) - view_port_x0)) \ = (node); \ } while (0) /* Lay out a part of the `tree' specified by `intermediate_data' (NULL * means the part starting at the tree root.) Algorithm is * essentially the same as used in update_internal_map_data(), but * this function has to watch if layed out nodes are within the * requested view ports and track connection lines. */ static SgfGameTreeMapLine * do_update_internal_view_port (const SgfGameTree *tree, const SgfGameTreeMapData *intermediate_data, SgfGameTreeMapLine *line_pointer) { int view_port_x0 = tree->view_port_x0; int view_port_y0 = tree->view_port_y0; int view_port_x1 = tree->view_port_x1; int view_port_y1 = tree->view_port_y1; int view_port_width = view_port_x1 - view_port_x0; SgfNode *node; int x; int y; int *y_level; int y_level_array_size; int last_valid_y_level; DECLARE_TIME_VARIABLES; STORE_STARTING_TIME; if (intermediate_data) { last_valid_y_level = intermediate_data->last_valid_y_level; y_level_array_size = ROUND_UP (last_valid_y_level + 1, Y_LEVEL_ARRAY_SIZE_GRAIN); y_level = utils_malloc (y_level_array_size * sizeof (int)); memcpy (y_level, intermediate_data->y_level, (last_valid_y_level + 1) * sizeof (int)); node = intermediate_data->node; x = intermediate_data->x; } else { y_level_array_size = Y_LEVEL_ARRAY_INITIAL_SIZE; y_level = utils_malloc (y_level_array_size * sizeof (int)); y_level[0] = 0; last_valid_y_level = 0; for (node = tree->root, x = 0; ; ) { if (IS_WITHIN_VIEW_PORT (x, 0)) WRITE_VIEW_PORT_NODE (x, 0, node); if (!node->child || node->is_collapsed) break; x++; node = node->child; } if (view_port_y0 == 0 && view_port_x0 <= x) { line_pointer->x0 = 0; line_pointer->y0 = 0; line_pointer->y1 = 0; line_pointer->x2 = 0; line_pointer->x3 = x; line_pointer++; } } do { while (!node->next) { if (!node->parent) goto finished; x--; node = node->parent; } node = node->next; if (x < last_valid_y_level) { if (node->child && !node->is_collapsed) { SgfNode *branch_scan_node = node->child; int branch_scan_delta; int branch_leaf_x = x + 1; int branch_leaf_y; int have_node_within_view_port = 0; while (branch_scan_node->child && !branch_scan_node->is_collapsed) { branch_scan_node = branch_scan_node->child; branch_leaf_x++; } branch_leaf_y = y_level[MIN (branch_leaf_x, last_valid_y_level)] + 1; for (y = y_level[x] + 1, branch_scan_delta = 1; branch_scan_delta < branch_leaf_y - y; branch_scan_delta++) y = MAX (y, y_level[x + branch_scan_delta] + 1 - branch_scan_delta); line_pointer->x0 = x - 1; line_pointer->y0 = y_level[x - 1]; y_level[x - 1] = y - 1; for (; y < branch_leaf_y; x++, y++, node = node->child) { y_level[x] = y; if (IS_WITHIN_VIEW_PORT (x, y)) { WRITE_VIEW_PORT_NODE (x, y, node); have_node_within_view_port = 1; } } if (IS_WITHIN_VIEW_PORT (x, y)) { WRITE_VIEW_PORT_NODE (x, y, node); have_node_within_view_port = 1; } line_pointer->x2 = x; if (y >= y_level[last_valid_y_level]) { y_level[x] = y; last_valid_y_level = x; } else { do y_level[x++] = y; while (y_level[x] < y); x = line_pointer->x2; } while (x < branch_leaf_x) { x++; node = node->child; if (IS_WITHIN_VIEW_PORT (x, y)) { WRITE_VIEW_PORT_NODE (x, y, node); have_node_within_view_port = 1; } } if (have_node_within_view_port || (view_port_x0 <= line_pointer->x0 && line_pointer->x0 < view_port_x1 && line_pointer->y0 < view_port_y1 && y_level[line_pointer->x0] >= view_port_y0)) { line_pointer->y1 = y_level[line_pointer->x0]; line_pointer->x3 = branch_leaf_x; line_pointer++; } } else { y = ++y_level[x]; if (y >= y_level[last_valid_y_level]) last_valid_y_level = x; else { int x_scan; for (x_scan = x + 1; y_level[x_scan] < y; x_scan++) y_level[x_scan] = y; } if (IS_WITHIN_VIEW_PORT (x, y)) WRITE_VIEW_PORT_NODE (x, y, node); if (IS_WITHIN_VIEW_PORT (x, y) || (view_port_x0 <= x - 1 && x - 1 < view_port_x1 && y_level[x - 1] < view_port_y1 && y - 1 >= view_port_y0)) { line_pointer->x0 = x - 1; line_pointer->y0 = y_level[x - 1]; line_pointer->y1 = y - 1; line_pointer->x2 = x; line_pointer->x3 = x; line_pointer++; } y_level[x - 1] = y - 1; } } else { int have_node_within_view_port = 0; line_pointer->x0 = x - 1; if (x > last_valid_y_level) { if (x > y_level_array_size) { y_level_array_size += ROUND_UP (x, Y_LEVEL_ARRAY_SIZE_GRAIN); y_level = utils_realloc (y_level, y_level_array_size * sizeof (int)); } y = y_level[last_valid_y_level]; line_pointer->y0 = y; while (++last_valid_y_level < x) y_level[last_valid_y_level] = y; y_level[x] = ++y; } else { line_pointer->y0 = y_level[x - 1]; y_level[x - 1] = y_level[x]; y = ++y_level[x]; } while (1) { if (IS_WITHIN_VIEW_PORT (x, y)) { WRITE_VIEW_PORT_NODE (x, y, node); have_node_within_view_port = 1; } if (!node->child || node->is_collapsed) break; x++; node = node->child; } if (have_node_within_view_port || (view_port_x0 <= line_pointer->x0 && line_pointer->x0 < view_port_x1 && view_port_y0 <= y - 1 && line_pointer->y0 < view_port_y1)) { line_pointer->y1 = y - 1; line_pointer->x2 = line_pointer->x0 + 1; line_pointer->x3 = x; line_pointer++; } } } while (!node->has_intermediate_map_data); finished: utils_free (y_level); PRINT_RUN_TIME (do_update_internal_view_port); return line_pointer; } /* Get `node_to_find's coordinates in the `tree's map. Uses the same * algorithm as update_internal_map_data(), but never lays out more * than one chunk of the tree and stops if bumps into * `node_to_find'. */ static int get_node_coordinates (SgfGameTree *tree, const SgfNode *node_to_find, int *node_x, int *node_y) { const SgfGameTreeMapData *intermediate_data; const SgfNode *node; int x; int *y_level; int y_level_array_size; int last_valid_y_level; DECLARE_TIME_VARIABLES; update_internal_map_data (tree); STORE_STARTING_TIME; intermediate_data = find_intermediate_data_for_node (tree, node_to_find, 0); if (intermediate_data) { last_valid_y_level = intermediate_data->last_valid_y_level; y_level_array_size = ROUND_UP (last_valid_y_level + 1, Y_LEVEL_ARRAY_SIZE_GRAIN); y_level = utils_malloc (y_level_array_size * sizeof (int)); memcpy (y_level, intermediate_data->y_level, (last_valid_y_level + 1) * sizeof (int)); node = intermediate_data->node; x = intermediate_data->x; } else { y_level_array_size = Y_LEVEL_ARRAY_INITIAL_SIZE; y_level = utils_malloc (y_level_array_size * sizeof (int)); y_level[0] = 0; last_valid_y_level = 0; node = tree->root; x = 0; while (node->child && !node->is_collapsed) { if (node == node_to_find) goto found_the_node; node = node->child; x++; } } do { while (!node->next) { if (node == node_to_find) goto found_the_node; if (!node->parent) goto failed_to_find_node; x--; node = node->parent; } if (node == node_to_find) goto found_the_node; node = node->next; if (x < last_valid_y_level) { if (node->child && !node->is_collapsed) { SgfNode *branch_scan_node; int branch_scan_x; int branch_highest_y; int branch_scan_delta; int branch_y; branch_scan_node = node->child; branch_scan_x = x + 1; while (branch_scan_x < last_valid_y_level && branch_scan_node->child && !branch_scan_node->is_collapsed) { branch_scan_node = branch_scan_node->child; branch_scan_x++; } branch_highest_y = y_level[branch_scan_x] + 1; for (branch_y = y_level[x] + 1, branch_scan_delta = 1; branch_scan_delta < branch_highest_y - branch_y; branch_scan_delta++) { branch_y = MAX (branch_y, (y_level[x + branch_scan_delta] + 1 - branch_scan_delta)); } y_level[x - 1] = branch_y - 1; y_level[x] = branch_y; while (branch_y < branch_highest_y) { if (node == node_to_find) goto found_the_node; y_level[++x] = ++branch_y; node = node->child; } if (branch_y >= y_level[last_valid_y_level]) { last_valid_y_level = x; while (node->child && !node->is_collapsed) { if (node == node_to_find) goto found_the_node; x++; node = node->child; } } else { int x_scan; while (node->child && !node->is_collapsed) { if (node == node_to_find) goto found_the_node; y_level[++x] = branch_y; node = node->child; } for (x_scan = x + 1; y_level[x_scan] < branch_y; x_scan++) y_level[x_scan] = branch_y; } } else { y_level[x - 1] = y_level[x]++; if (node == node_to_find) goto found_the_node; if (y_level[x] >= y_level[last_valid_y_level]) last_valid_y_level = x; else { int y = y_level[x]; int x_scan; for (x_scan = x + 1; y_level[x_scan] < y; x_scan++) y_level[x_scan] = y; } } } else { if (x > last_valid_y_level) { int previous_branch_y; if (x > y_level_array_size) { y_level_array_size = ROUND_UP (x, Y_LEVEL_ARRAY_SIZE_GRAIN); y_level = utils_realloc (y_level, (y_level_array_size * sizeof (int))); } previous_branch_y = y_level[last_valid_y_level]; while (++last_valid_y_level < x) y_level[last_valid_y_level] = previous_branch_y; y_level[x] = previous_branch_y + 1; } else y_level[x - 1] = y_level[x]++; while (node->child && !node->is_collapsed) { if (node == node_to_find) goto found_the_node; x++; node = node->child; } } } while (!node->has_intermediate_map_data); failed_to_find_node: /* Can happen if the requested node is within a collapsed subtree or * if the call is seriously f*cked up with a non-existant node, for * instance. */ utils_free (y_level); PRINT_RUN_TIME (get_node_coordinates); return 0; found_the_node: *node_x = x; *node_y = y_level[MIN (x, last_valid_y_level)]; utils_free (y_level); PRINT_RUN_TIME (get_node_coordinates); return 1; } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/sgf/sgf-undo.c0000644000175000017500000006737010454772373014763 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* Implementation of loggable and revertable changes to SGF trees, * which are stored in the form of undo histories. Many non-static * function here are private to the SGF module. All external entry * points are contained in the first page, but the reverse is not * true. * * This file is very closely related to `sgf-undo.c' and was actually * a part of it earlier. There are mutual interactions between the * two. Also, since undo histories are optional, most functions here * take an `SgfGameTree' as its first argument and such functions have * `sgf_utils' as name prefix. */ #include "sgf.h" #include "sgf-privates.h" #include "sgf-undo.h" #include "board.h" #include "utils.h" #include #ifdef HAVE_MEMORY_H #include #endif inline static void delete_undo_history_entry (SgfUndoHistoryEntry *entry, int is_applied, SgfGameTree *tree); static void begin_undoing_or_redoing (SgfGameTree *tree); static void set_is_modifying_map (SgfGameTree *tree); static void set_is_modifying_tree (SgfGameTree *tree); static void end_undoing_or_redoing (SgfGameTree *tree); inline static SgfNode ** find_node_link (SgfNode *parent, const SgfNode *next); inline static SgfProperty ** find_property_link (SgfNode *node, const SgfProperty *next); SgfUndoHistory * sgf_undo_history_new (SgfGameTree *tree) { SgfUndoHistory *history = utils_malloc (sizeof (SgfUndoHistory)); assert (tree); history->first_entry = NULL; history->last_entry = NULL; history->last_applied_entry = NULL; history->unmodified_state_entry = NULL; history->notification_callback = NULL; history->user_data = NULL; history->next = tree->undo_history_list; tree->undo_history_list = history; return history; } void sgf_undo_history_delete (SgfUndoHistory *history, SgfGameTree *tree) { SgfUndoHistory **link; SgfUndoHistoryEntry *this_entry; int is_applied; assert (history); assert (tree); /* Detach the `history' from the list of histories associated with * `tree'. */ link = &tree->undo_history_list; while (*link != history) { assert (*link); link = & (*link)->next; } *link = history->next; for (this_entry = history->first_entry, is_applied = 1; this_entry;) { SgfUndoHistoryEntry *next_entry = this_entry->next; if (this_entry->previous == history->last_applied_entry) is_applied = 0; delete_undo_history_entry (this_entry, is_applied, tree); this_entry = next_entry; } utils_free (history); } void sgf_undo_history_hide_last_applied_entry (SgfUndoHistory *history) { assert (history); assert (history->last_applied_entry); history->last_applied_entry->is_hidden = 1; } int sgf_undo_history_is_last_applied_entry_single (const SgfUndoHistory *history) { assert (history); if (history->last_applied_entry) { return (history->last_applied_entry->is_last_in_action && (!history->last_applied_entry->previous || history->last_applied_entry->previous->is_last_in_action)); } else return 0; } int sgf_undo_history_check_last_applied_custom_entry_type (const SgfUndoHistory *history, const SgfCustomUndoHistoryEntryData *entry_data) { const SgfCustomOperationEntry *custom_entry; assert (history); assert (entry_data); custom_entry = (const SgfCustomOperationEntry *) history->last_applied_entry; return (custom_entry && custom_entry->entry.operation_index == SGF_OPERATION_CUSTOM && custom_entry->entry_data == entry_data); } void * sgf_undo_history_get_last_applied_custom_entry_data (const SgfUndoHistory *history) { assert (history); assert (history->last_applied_entry); assert (history->last_applied_entry->operation_index == SGF_OPERATION_CUSTOM); return (((const SgfCustomOperationEntry *) history->last_applied_entry) ->user_data); } void sgf_undo_history_delete_redo_entries (SgfUndoHistory *history, SgfGameTree *tree) { SgfUndoHistoryEntry *this_entry; assert (history); if (history->last_applied_entry) { this_entry = history->last_applied_entry->next; history->last_applied_entry->next = NULL; } else { this_entry = history->first_entry; history->first_entry = NULL; } while (this_entry) { SgfUndoHistoryEntry *next_entry = this_entry->next; delete_undo_history_entry (this_entry, 0, tree); this_entry = next_entry; } } void sgf_undo_history_set_notification_callback (SgfUndoHistory *history, SgfUndoHistoryNotificationCallback notification_callback, void *user_data) { assert (history); history->notification_callback = notification_callback; history->user_data = user_data; } /* Designate a beginning of an undoable action. Must always be paired * by a call to sgf_utils_end_action(). Such actions can and do nest * and only the topmost-level invocation of sgf_utils_begin_action() * and sgf_utils_end_action() constitute a user-visible action. * * This allows to easily construct composite actions. By convention, * all functions in this file that alter undo history must set up an * action, so that the top-level code can avoid this if it only needs * a ``single-primitive action.'' */ void sgf_utils_begin_action (SgfGameTree *tree) { assert (tree); if (tree->undo_operation_level++ == 0) begin_undoing_or_redoing (tree); } /* Finish an undoable action. See sgf_utils_begin_action() for more * information. */ void sgf_utils_end_action (SgfGameTree *tree) { assert (tree); tree->undo_operation_level--; assert (tree->undo_operation_level >= 0); if (tree->undo_operation_level == 0) { if (tree->undo_history && tree->undo_history->last_entry) tree->undo_history->last_entry->is_last_in_action = 1; end_undoing_or_redoing (tree); } } void sgf_utils_undo (SgfGameTree *tree) { SgfUndoHistoryEntry *entry; int is_hidden_entry = 0; assert (tree); assert (tree->board_state); assert (tree->undo_operation_level == 0); if (!sgf_utils_can_undo (tree)) return; begin_undoing_or_redoing (tree); entry = tree->undo_history->last_applied_entry; do { if (entry->is_last_in_action) is_hidden_entry = entry->is_hidden; sgf_undo_operations[entry->operation_index].undo (entry, tree); entry = entry->previous; } while (entry && (!entry->is_last_in_action || is_hidden_entry)); tree->undo_history->last_applied_entry = entry; end_undoing_or_redoing (tree); } void sgf_utils_redo (SgfGameTree *tree) { SgfUndoHistory *history; SgfUndoHistoryEntry *entry; assert (tree); assert (tree->board_state); assert (tree->undo_operation_level == 0); if (!sgf_utils_can_redo (tree)) return; history = tree->undo_history; entry = (history->last_applied_entry ? history->last_applied_entry->next : history->first_entry); begin_undoing_or_redoing (tree); while (1) { sgf_undo_operations[entry->operation_index].redo (entry, tree); if (entry->is_last_in_action && (!entry->is_hidden || !entry->next)) break; entry = entry->next; assert (entry); } history->last_applied_entry = entry; end_undoing_or_redoing (tree); } /* All remaining functions are private to the SGF module. */ SgfUndoHistoryEntry * sgf_new_node_undo_history_entry_new (SgfNode *new_node) { SgfNodeOperationEntry *operation_data = utils_malloc (sizeof (SgfNodeOperationEntry)); operation_data->entry.operation_index = SGF_OPERATION_NEW_NODE; operation_data->node = new_node; operation_data->parent_current_variation = new_node->parent->current_variation; return (SgfUndoHistoryEntry *) operation_data; } SgfUndoHistoryEntry * sgf_delete_node_undo_history_entry_new (SgfNode *node) { SgfNodeOperationEntry *operation_data = utils_malloc (sizeof (SgfNodeOperationEntry)); operation_data->entry.operation_index = SGF_OPERATION_DELETE_NODE; operation_data->node = node; /* This field is used after node deletion. So, we should set it so * it is _not_ equal to the `node', which is being deleted. Use a * neighbor node instead. */ operation_data->parent_current_variation = (node->next ? node->next : sgf_node_get_previous_node (node)); return (SgfUndoHistoryEntry *) operation_data; } SgfUndoHistoryEntry * sgf_delete_node_children_undo_history_entry_new (SgfNode *node) { SgfNodeOperationEntry *operation_data = utils_malloc (sizeof (SgfNodeOperationEntry)); operation_data->entry.operation_index = SGF_OPERATION_DELETE_NODE_CHILDREN; operation_data->node = node->child; operation_data->parent_current_variation = node->current_variation; return (SgfUndoHistoryEntry *) operation_data; } SgfUndoHistoryEntry * sgf_swap_nodes_undo_history_entry_new (SgfNode *node1, SgfNode *node2) { SgfTwoNodesOperationEntry *operation_data = utils_malloc (sizeof (SgfTwoNodesOperationEntry)); operation_data->entry.operation_index = SGF_OPERATION_SWAP_NODES; operation_data->node1 = node1; operation_data->node2 = node2; operation_data->parent_current_variation = node1->parent->current_variation; return (SgfUndoHistoryEntry *) operation_data; } SgfUndoHistoryEntry * sgf_change_node_inlined_color_undo_history_entry_new (SgfNode *node, SgfUndoOperation operation, int new_color, int side_effect) { SgfChangeNodeInlinedColorOperationEntry *operation_data = utils_malloc (sizeof (SgfChangeNodeInlinedColorOperationEntry)); operation_data->entry.operation_index = operation; operation_data->node = node; operation_data->color = new_color; operation_data->side_effect = side_effect; return (SgfUndoHistoryEntry *) operation_data; } SgfUndoHistoryEntry * sgf_new_property_undo_history_entry_new (SgfGameTree *tree, SgfNode *node, SgfProperty **link, SgfType type, int side_effect) { SgfPropertyOperationEntry *operation_data = utils_malloc (sizeof (SgfPropertyOperationEntry)); operation_data->entry.operation_index = SGF_OPERATION_NEW_PROPERTY; operation_data->node = node; operation_data->property = sgf_property_new (tree, type, *link); operation_data->side_effect = side_effect; return (SgfUndoHistoryEntry *) operation_data; } SgfUndoHistoryEntry * sgf_delete_property_undo_history_entry_new (SgfNode *node, SgfProperty *property, int side_effect) { SgfPropertyOperationEntry *operation_data = utils_malloc (sizeof (SgfPropertyOperationEntry)); operation_data->entry.operation_index = SGF_OPERATION_DELETE_PROPERTY; operation_data->node = node; operation_data->property = property; operation_data->side_effect = side_effect; return (SgfUndoHistoryEntry *) operation_data; } SgfUndoHistoryEntry * sgf_change_property_undo_history_entry_new (SgfNode *node, SgfProperty *property, int side_effect) { SgfChangePropertyOperationEntry *operation_data = utils_malloc (sizeof (SgfChangePropertyOperationEntry)); operation_data->entry.operation_index = SGF_OPERATION_CHANGE_PROPERTY; operation_data->node = node; operation_data->property = property; operation_data->side_effect = side_effect; return (SgfUndoHistoryEntry *) operation_data; } #if SGF_REAL_VALUES_ALLOCATED_SEPARATELY SgfUndoHistoryEntry * sgf_change_real_property_undo_history_entry_new (SgfNode *node, SgfProperty *property, double new_value, int side_effect) { SgfChangeRealPropertyOperationEntry *operation_data = utils_malloc (sizeof (SgfChangeRealPropertyOperationEntry)); operation_data->entry.operation_index = SGF_OPERATION_CHANGE_REAL_PROPERTY; operation_data->node = node; operation_data->property = property; operation_data->value = new_value; operation_data->side_effect = side_effect; return (SgfUndoHistoryEntry *) operation_data; } #endif /* SGF_REAL_VALUES_ALLOCATED_SEPARATELY */ SgfUndoHistoryEntry * sgf_custom_undo_history_entry_new (const SgfCustomUndoHistoryEntryData *entry_data, void *user_data, SgfNode *node_to_switch_to) { SgfCustomOperationEntry *operation_data = utils_malloc (sizeof (SgfCustomOperationEntry)); operation_data->entry.operation_index = SGF_OPERATION_CUSTOM; operation_data->entry_data = entry_data; operation_data->user_data = user_data; operation_data->node_to_switch_to = node_to_switch_to; return (SgfUndoHistoryEntry *) operation_data; } inline static void delete_undo_history_entry (SgfUndoHistoryEntry *entry, int is_applied, SgfGameTree *tree) { if (sgf_undo_operations[entry->operation_index].free_data) { sgf_undo_operations[entry->operation_index].free_data (entry, is_applied, tree); } utils_free (entry); } static void begin_undoing_or_redoing (SgfGameTree *tree) { tree->node_to_switch_to = NULL; tree->is_modifying_map = 0; tree->is_modifying_tree = 0; if (tree->undo_history) { tree->tree_was_modified = (tree->undo_history->last_applied_entry != tree->undo_history->unmodified_state_entry); tree->could_undo = sgf_utils_can_undo (tree); tree->could_redo = sgf_utils_can_redo (tree); } tree->collection_was_modified = sgf_collection_is_modified (tree->collection); } static void set_is_modifying_map (SgfGameTree *tree) { if (!tree->is_modifying_map) { GAME_TREE_DO_NOTIFY (tree, SGF_ABOUT_TO_MODIFY_MAP); tree->is_modifying_map = 1; } } static void set_is_modifying_tree (SgfGameTree *tree) { if (!tree->is_modifying_tree) { GAME_TREE_DO_NOTIFY (tree, SGF_ABOUT_TO_MODIFY_TREE); tree->is_modifying_tree = 1; } } static void end_undoing_or_redoing (SgfGameTree *tree) { SgfNode *node_to_switch_to = tree->node_to_switch_to; if (node_to_switch_to) { GAME_TREE_DO_NOTIFY (tree, SGF_ABOUT_TO_CHANGE_CURRENT_NODE); if (tree->current_node->parent == node_to_switch_to) { /* A common case, optimize it. */ sgf_utils_ascend_nodes (tree, 1); } else sgf_utils_do_switch_to_given_node (tree, node_to_switch_to); GAME_TREE_DO_NOTIFY (tree, SGF_CURRENT_NODE_CHANGED); } if (tree->is_modifying_tree) GAME_TREE_DO_NOTIFY (tree, SGF_TREE_MODIFIED); if (tree->is_modifying_map) GAME_TREE_DO_NOTIFY (tree, SGF_MAP_MODIFIED); if (tree->undo_history) { if (tree->tree_was_modified && (tree->undo_history->last_applied_entry == tree->undo_history->unmodified_state_entry)) tree->collection->num_modified_undo_histories--; else if (!tree->tree_was_modified && (tree->undo_history->last_applied_entry != tree->undo_history->unmodified_state_entry)) tree->collection->num_modified_undo_histories++; if (tree->could_undo != sgf_utils_can_undo (tree) || tree->could_redo != sgf_utils_can_redo (tree)) UNDO_HISTORY_DO_NOTIFY (tree->undo_history); } if (sgf_collection_is_modified (tree->collection) != tree->collection_was_modified) COLLECTION_DO_NOTIFY (tree->collection); } void sgf_utils_apply_undo_history_entry (SgfGameTree *tree, SgfUndoHistoryEntry *entry) { SgfUndoHistory *history = tree->undo_history; if (history) { sgf_undo_history_delete_redo_entries (history, tree); if (history->last_applied_entry) { history->last_applied_entry->next = entry; entry->previous = history->last_applied_entry; } else { history->first_entry = entry; entry->previous = NULL; } history->last_entry = entry; history->last_applied_entry = entry; entry->next = NULL; entry->is_last_in_action = 0; entry->is_hidden = 0; } /* Perform the operation. */ sgf_undo_operations[entry->operation_index].redo (entry, tree); if (!history) { delete_undo_history_entry (entry, 1, tree); tree->collection->is_irreversibly_modified = 1; } } void sgf_operation_add_node (SgfUndoHistoryEntry *entry, SgfGameTree *tree) { SgfNode *node = ((SgfNodeOperationEntry *) entry)->node; set_is_modifying_map (tree); set_is_modifying_tree (tree); tree->node_to_switch_to = node; * find_node_link (node->parent, node->next) = node; sgf_game_tree_invalidate_map (tree, node->parent); } void sgf_operation_delete_node (SgfUndoHistoryEntry *entry, SgfGameTree *tree) { SgfNode *node = ((SgfNodeOperationEntry *) entry)->node; SgfNode *parent = node->parent; set_is_modifying_map (tree); set_is_modifying_tree (tree); tree->node_to_switch_to = parent; * find_node_link (parent, node) = node->next; parent->current_variation = (((SgfNodeOperationEntry *) entry) ->parent_current_variation); sgf_game_tree_invalidate_map (tree, parent); } void sgf_operation_new_node_free_data (SgfUndoHistoryEntry *entry, int is_applied, SgfGameTree *tree) { if (!is_applied) sgf_node_delete (((SgfNodeOperationEntry *) entry)->node, tree); } void sgf_operation_delete_node_free_data (SgfUndoHistoryEntry *entry, int is_applied, SgfGameTree *tree) { if (is_applied) sgf_node_delete (((SgfNodeOperationEntry *) entry)->node, tree); } void sgf_operation_delete_node_children_undo (SgfUndoHistoryEntry *entry, SgfGameTree *tree) { SgfNode *first_child = ((SgfNodeOperationEntry *) entry)->node; SgfNode *parent = first_child->parent; set_is_modifying_map (tree); set_is_modifying_tree (tree); tree->node_to_switch_to = parent; parent->child = first_child; parent->current_variation = ((SgfNodeOperationEntry *) entry)->parent_current_variation; sgf_game_tree_invalidate_map (tree, parent); } void sgf_operation_delete_node_children_redo (SgfUndoHistoryEntry *entry, SgfGameTree *tree) { SgfNode *parent = ((SgfNodeOperationEntry *) entry)->node->parent; set_is_modifying_map (tree); set_is_modifying_tree (tree); tree->node_to_switch_to = parent; parent->child = NULL; parent->current_variation = NULL; sgf_game_tree_invalidate_map (tree, parent); } void sgf_operation_delete_node_children_free_data (SgfUndoHistoryEntry *entry, int is_applied, SgfGameTree *tree) { if (is_applied) { SgfNode *this_node = ((SgfNodeOperationEntry *) entry)->node; do { SgfNode *next_node = this_node->next; sgf_node_delete (this_node, tree); this_node = next_node; } while (this_node); } } void sgf_operation_swap_nodes_do_swap (SgfUndoHistoryEntry *entry, SgfGameTree *tree) { SgfNode *node1 = ((SgfTwoNodesOperationEntry *) entry)->node1; SgfNode *node2 = ((SgfTwoNodesOperationEntry *) entry)->node2; SgfNode *parent = node1->parent; SgfNode *temp; SgfNode **link; assert (node1->parent == node2->parent); set_is_modifying_map (tree); set_is_modifying_tree (tree); tree->node_to_switch_to = node1; link = &parent->child; while (*link != node1 && *link != node2) { assert (*link); link = & (*link)->next; } if (*link == node2) { temp = node1; node1 = node2; node2 = temp; } *link = node2; temp = node1->next; node1->next = node2->next; node2->next = temp; do { assert (*link); link = & (*link)->next; } while (*link != node2); *link = node1; sgf_game_tree_invalidate_map (tree, parent); } /* Works as both undo and redo handler. Since we just swap move * colors between the node and the undo history entry, it will always * do the right thing. */ void sgf_operation_change_node_move_color_do_change (SgfUndoHistoryEntry *entry, SgfGameTree *tree) { SgfChangeNodeInlinedColorOperationEntry *color_entry = (SgfChangeNodeInlinedColorOperationEntry *) entry; int temp_color; if (!color_entry->side_effect) tree->node_to_switch_to = color_entry->node; temp_color = color_entry->node->move_color; color_entry->node->move_color = color_entry->color; color_entry->color = temp_color; } /* Works as both undo and redo handler. Since we just swap move * colors between the node and the undo history entry, it will always * do the right thing. */ void sgf_operation_change_node_to_play_color_do_change (SgfUndoHistoryEntry *entry, SgfGameTree *tree) { SgfChangeNodeInlinedColorOperationEntry *color_entry = (SgfChangeNodeInlinedColorOperationEntry *) entry; SgfNode *node = (SgfNode *) color_entry->node; int temp_color; tree->node_to_switch_to = node; temp_color = node->to_play_color; node->to_play_color = color_entry->color; color_entry->color = temp_color; if (node == tree->current_node) sgf_utils_find_board_state_data (tree, 1, 0); } void sgf_operation_add_property (SgfUndoHistoryEntry *entry, SgfGameTree *tree) { SgfNode *node = ((SgfPropertyOperationEntry *) entry)->node; SgfProperty *property = ((SgfPropertyOperationEntry *) entry)->property; if (!((SgfPropertyOperationEntry *) entry)->side_effect) tree->node_to_switch_to = node; * find_property_link (node, property->next) = property; } void sgf_operation_delete_property (SgfUndoHistoryEntry *entry, SgfGameTree *tree) { SgfNode *node = ((SgfPropertyOperationEntry *) entry)->node; SgfProperty *property = ((SgfPropertyOperationEntry *) entry)->property; if (!((SgfPropertyOperationEntry *) entry)->side_effect) tree->node_to_switch_to = node; * find_property_link (node, property) = property->next; } void sgf_operation_new_property_free_data (SgfUndoHistoryEntry *entry, int is_applied, SgfGameTree *tree) { if (!is_applied) { sgf_property_delete (((SgfPropertyOperationEntry *) entry)->property, tree); } } void sgf_operation_delete_property_free_data (SgfUndoHistoryEntry *entry, int is_applied, SgfGameTree *tree) { if (is_applied) { sgf_property_delete (((SgfPropertyOperationEntry *) entry)->property, tree); } } /* Works as both undo and redo handler. Since we just swap values * between the property and the undo history entry, it will always do * the right thing. */ void sgf_operation_change_property_do_change (SgfUndoHistoryEntry *entry, SgfGameTree *tree) { SgfChangePropertyOperationEntry *const change_entry = (SgfChangePropertyOperationEntry *) entry; SgfNode *node = change_entry->node; SgfProperty *property = change_entry->property; SgfValue *value = &change_entry->value; if (!change_entry->side_effect) tree->node_to_switch_to = node; switch (property_info[property->type].value_type) { case SGF_NUMBER: case SGF_DOUBLE: case SGF_COLOR: { int temp_number = property->value.number; property->value.number = value->number; value->number = temp_number; } break; case SGF_SIMPLE_TEXT: case SGF_FAKE_SIMPLE_TEXT: case SGF_TEXT: { char *temp_text = property->value.text; property->value.text = value->text; value->text = temp_text; } break; case SGF_TYPE_UNKNOWN: { StringList *temp_unknown_value_list = property->value.unknown_value_list; property->value.unknown_value_list = value->unknown_value_list; value->unknown_value_list = temp_unknown_value_list; } break; case SGF_LIST_OF_POINT: case SGF_ELIST_OF_POINT: { BoardPositionList *temp_position_list = property->value.position_list; property->value.position_list = value->position_list; value->position_list = temp_position_list; } break; case SGF_LIST_OF_VECTOR: { SgfVectorList *temp_vector_list = property->value.vector_list; property->value.vector_list = value->vector_list; value->vector_list = temp_vector_list; } break; case SGF_LIST_OF_LABEL: { SgfLabelList *temp_label_list = property->value.label_list; property->value.label_list = value->label_list; value->label_list = temp_label_list; } break; case SGF_FIGURE_DESCRIPTION: { SgfFigureDescription *temp_figure = property->value.figure; property->value.figure = value->figure; value->figure = temp_figure; } break; case SGF_REAL: case SGF_NONE: case SGF_NOT_STORED: assert (0); }; } void sgf_operation_change_property_free_data (SgfUndoHistoryEntry *entry, int is_applied, SgfGameTree *tree) { SgfProperty *property = ((SgfChangePropertyOperationEntry *) entry)->property; SgfValue *value = & ((SgfChangePropertyOperationEntry *) entry)->value; UNUSED (tree); UNUSED (is_applied); /* We free the value unconditionally: if the entry has been undone, * it contains the new value, else---the original. */ sgf_property_free_value (property_info[property->type].value_type, value); } #if SGF_REAL_VALUES_ALLOCATED_SEPARATELY /* Works as both undo and redo handler. Since we just swap values * between the property and the undo history entry, it will always do * the right thing. */ void sgf_operation_change_real_property_do_change (SgfUndoHistoryEntry *entry, SgfGameTree *tree) { SgfChangeRealPropertyOperationEntry *change_entry = (SgfChangeRealPropertyOperationEntry *) entry; SgfNode *node = change_entry->node; SgfProperty *property = change_entry->property; double temp_value; if (!change_entry->side_effect) tree->node_to_switch_to = node; temp_value = *property->value.real; *property->value.real = change_entry->value; change_entry->value = temp_value; } #endif void sgf_operation_custom_undo (SgfUndoHistoryEntry *entry, SgfGameTree *tree) { SgfCustomOperationEntry *custom_entry = (SgfCustomOperationEntry *) entry; if (custom_entry->entry_data->undo) custom_entry->entry_data->undo (custom_entry->user_data, tree); if (custom_entry->node_to_switch_to) tree->node_to_switch_to = custom_entry->node_to_switch_to; } void sgf_operation_custom_redo (SgfUndoHistoryEntry *entry, SgfGameTree *tree) { SgfCustomOperationEntry *custom_entry = (SgfCustomOperationEntry *) entry; if (custom_entry->entry_data->redo) custom_entry->entry_data->redo (custom_entry->user_data, tree); if (custom_entry->node_to_switch_to) tree->node_to_switch_to = custom_entry->node_to_switch_to; } void sgf_operation_custom_free_data (SgfUndoHistoryEntry *entry, int is_applied, SgfGameTree *tree) { SgfCustomOperationEntry *custom_entry = (SgfCustomOperationEntry *) entry; UNUSED (is_applied); if (custom_entry->entry_data->free_data) custom_entry->entry_data->free_data (custom_entry->user_data, tree); } inline static SgfNode ** find_node_link (SgfNode *parent, const SgfNode *next) { SgfNode **link = &parent->child; while (*link != next) { assert (*link); link = & (*link)->next; } return link; } inline static SgfProperty ** find_property_link (SgfNode *node, const SgfProperty *next) { SgfProperty **link = &node->properties; while (*link != next) { assert (*link); link = & (*link)->next; } return link; } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/sgf/sgf-utils.c0000644000175000017500000015151510470176207015141 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "sgf.h" #include "sgf-privates.h" #include "sgf-undo.h" #include "board.h" #include "game-info.h" #include "utils.h" #include #include #ifdef HAVE_MEMORY_H #include #endif typedef int (* ValuesComparator) (const void *first_value, const void *second_value); static void add_horizontal_coordinates (const SgfGameTree *tree, StringBuffer *buffer); static void add_horizontal_line (const SgfGameTree *tree, StringBuffer *buffer, int sensei_style); static void do_enter_tree (SgfGameTree *tree, SgfNode *down_to); static void find_board_state_data (const SgfGameTree *tree, SgfNode *node, int need_color_to_move, int need_move_coordinates); static void find_time_control_data (const SgfGameTree *tree, SgfNode *upper_limit, SgfNode *lower_limit); static void determine_final_color_to_play (const SgfGameTree *tree); static int do_set_pointer_property (SgfNode *node, SgfGameTree *tree, SgfType type, ValuesComparator values_are_equal, void *new_value, int side_effect); static int strings_are_equal (const void *first_string, const void *second_string); inline void sgf_utils_play_node_move (const SgfNode *node, Board *board) { assert (node); if (board->game != GAME_AMAZONS) { board_play_move (board, node->move_color, node->move_point.x, node->move_point.y); } else { board_play_move (board, node->move_color, node->move_point.x, node->move_point.y, node->data.amazons); } } void sgf_utils_format_node_move (const SgfGameTree *tree, const SgfNode *node, StringBuffer *buffer, const char *black_string, const char *white_string, const char *pass_string) { assert (tree); assert (node); assert (buffer); assert (IS_STONE (node->move_color)); if (node->move_color == BLACK) { if (black_string) string_buffer_cat_string (buffer, black_string); } else { if (white_string) string_buffer_cat_string (buffer, white_string); } if (tree->game != GAME_AMAZONS) { if (tree->game != GAME_GO || !IS_PASS (node->move_point.x, node->move_point.y)) { game_format_move (tree->game, tree->board_width, tree->board_height, buffer, node->move_point.x, node->move_point.y); } else if (pass_string) string_buffer_cat_string (buffer, pass_string); } else { game_format_move (tree->game, tree->board_width, tree->board_height, buffer, node->move_point.x, node->move_point.y, node->data.amazons); } } void sgf_utils_enter_tree (SgfGameTree *tree, Board *board, SgfBoardState *board_state) { assert (tree); assert (tree->root); assert (tree->current_node); assert (board_state); tree->board = board; tree->board_state = board_state; do_enter_tree (tree, tree->current_node); } /* Go down (forward) in the given tree by `num_nodes' nodes, always * following the current variation. If variation end (a node without * children) is reached, the function stops gracefully. Negative * values of `num_nodes' are allowed and will cause the function to go * up to the variation end. */ void sgf_utils_go_down_in_tree (SgfGameTree *tree, int num_nodes) { assert (tree); assert (tree->current_node); assert (tree->board_state); if (num_nodes != 0 && tree->current_node->child) { GAME_TREE_DO_NOTIFY (tree, SGF_ABOUT_TO_CHANGE_CURRENT_NODE); sgf_utils_descend_nodes (tree, num_nodes); GAME_TREE_DO_NOTIFY (tree, SGF_CURRENT_NODE_CHANGED); } } /* Go up (back) in the given tree by `num_nodes' nodes, but stop if * tree root is reached. Negative values are allowed and will cause * the function to go up to the root. * * As a speed optimization for very deep trees, ascending to root node * is done with sgf_utils_enter_tree() instead of undoing from the * current node. */ void sgf_utils_go_up_in_tree (SgfGameTree *tree, int num_nodes) { assert (tree); assert (tree->current_node); assert (tree->board_state); if (num_nodes != 0 && tree->current_node->parent) { GAME_TREE_DO_NOTIFY (tree, SGF_ABOUT_TO_CHANGE_CURRENT_NODE); if (num_nodes > 0) sgf_utils_ascend_nodes (tree, num_nodes); else do_enter_tree (tree, tree->root); GAME_TREE_DO_NOTIFY (tree, SGF_CURRENT_NODE_CHANGED); } } int sgf_utils_count_variations (const SgfGameTree *tree, int of_current_node, int black_variations[BOARD_GRID_SIZE], int white_variations[BOARD_GRID_SIZE], int *other_variations) { SgfNode *node; int total_variations = 0; assert (tree); assert (tree->current_node); if (black_variations) board_fill_int_grid (tree->board, black_variations, 0); if (white_variations) board_fill_int_grid (tree->board, white_variations, 0); node = tree->current_node; if (of_current_node) { if (node->parent) node = node->parent->child; } else node = node->child; while (node) { if (IS_STONE (node->move_color) && !IS_PASS (node->move_point.x, node->move_point.y)) { if (node->move_color == BLACK) { if (black_variations) black_variations[POINT_TO_POSITION (node->move_point)]++; } else { if (white_variations) white_variations[POINT_TO_POSITION (node->move_point)]++; } } else if (other_variations) (*other_variations)++; total_variations++; node = node->next; } return total_variations; } SgfNode * sgf_utils_find_variation_at_position (SgfGameTree *tree, int x, int y, SgfDirection direction, int after_current) { SgfNode *node; assert (tree); assert (tree->current_node); assert (direction == SGF_NEXT || direction == SGF_PREVIOUS); node = tree->current_node; if (direction == SGF_NEXT) { if (!after_current) { if (!node->parent) return NULL; node = node->parent->child; } else node = node->next; while (node) { if (IS_STONE (node->move_color) && node->move_point.x == x && node->move_point.y == y) break; node = node->next; } return node; } else { SgfNode *result = NULL; SgfNode *limit; limit = (after_current ? tree->current_node : NULL); if (node->parent) node = node->parent->child; while (node != limit) { if (IS_STONE (node->move_color) && node->move_point.x == x && node->move_point.y == y) result = node; node = node->next; } return result; } } void sgf_utils_switch_to_variation (SgfGameTree *tree, SgfDirection direction) { SgfNode *switch_to; SgfNode *parent; assert (tree); assert (tree->current_node); assert (tree->board_state); assert (direction == SGF_NEXT || direction == SGF_PREVIOUS); parent = tree->current_node->parent; if (direction == SGF_NEXT) { switch_to = tree->current_node->next; if (!switch_to) return; } else { if (parent && parent->child != tree->current_node) { switch_to = parent->child; while (switch_to->next != tree->current_node) switch_to = switch_to->next; } else return; } GAME_TREE_DO_NOTIFY (tree, SGF_ABOUT_TO_CHANGE_CURRENT_NODE); sgf_utils_ascend_nodes (tree, 1); parent->current_variation = switch_to; sgf_utils_descend_nodes (tree, 1); GAME_TREE_DO_NOTIFY (tree, SGF_CURRENT_NODE_CHANGED); } void sgf_utils_switch_to_given_variation (SgfGameTree *tree, SgfNode *node) { assert (tree); assert (tree->current_node); assert (node); assert (tree->current_node->parent == node->parent); assert (tree->board_state); if (tree->current_node != node) { GAME_TREE_DO_NOTIFY (tree, SGF_ABOUT_TO_CHANGE_CURRENT_NODE); sgf_utils_ascend_nodes (tree, 1); node->parent->current_variation = node; sgf_utils_descend_nodes (tree, 1); GAME_TREE_DO_NOTIFY (tree, SGF_CURRENT_NODE_CHANGED); } } void sgf_utils_switch_to_given_node (SgfGameTree *tree, SgfNode *node) { assert (tree); assert (tree->current_node); assert (node); assert (tree->board_state); if (tree->current_node != node) { GAME_TREE_DO_NOTIFY (tree, SGF_ABOUT_TO_CHANGE_CURRENT_NODE); sgf_utils_do_switch_to_given_node (tree, node); GAME_TREE_DO_NOTIFY (tree, SGF_CURRENT_NODE_CHANGED); } } /* Append a variation to the current node. The new variation may * contain a move or it may not. If `color' is either `BLACK' or * `WHITE', arguments after it should specify a move according to * tree's game. If `color' is `EMPTY', then the new variation will * not contain a move. */ SgfNode * sgf_utils_append_variation (SgfGameTree *tree, int color, ...) { SgfNode *new_node; assert (tree); assert (tree->current_node); assert (tree->board_state); new_node = sgf_node_new (tree, tree->current_node); if (color != EMPTY) { va_list arguments; assert (IS_STONE (color)); va_start (arguments, color); new_node->move_color = color; new_node->move_point.x = va_arg (arguments, int); new_node->move_point.y = va_arg (arguments, int); if (tree->game == GAME_AMAZONS) new_node->data.amazons = va_arg (arguments, BoardAmazonsMoveData); va_end (arguments); } sgf_utils_begin_action (tree); sgf_utils_apply_undo_history_entry (tree, sgf_new_node_undo_history_entry_new (new_node)); sgf_utils_end_action (tree); return new_node; } int sgf_utils_apply_setup_changes (SgfGameTree *tree, const char grid[BOARD_GRID_SIZE], int side_effect) { BoardPositionList *difference_lists[NUM_ON_GRID_VALUES]; SgfNode *node; SgfUndoHistory *undo_history = NULL; int have_any_difference; int new_move_color; int created_new_node = 0; int anything_changed = 0; assert (tree); assert (tree->current_node); assert (tree->board); assert (grid); node = tree->current_node; if (node->move_color == SETUP_NODE) { if (node->parent) sgf_utils_ascend_nodes (tree, 1); else board_undo (tree->board, 1); } grid_diff (tree->board->grid, grid, tree->board_width, tree->board_height, difference_lists); assert (!difference_lists[ARROW] || tree->game == GAME_AMAZONS); have_any_difference = (difference_lists[EMPTY] || difference_lists[BLACK] || difference_lists[WHITE] || difference_lists[ARROW]); new_move_color = (have_any_difference ? SETUP_NODE : EMPTY); sgf_utils_begin_action (tree); if (IS_STONE (node->move_color)) { if (!have_any_difference) return 0; node = sgf_node_new (tree, node); node->move_color = new_move_color; created_new_node = 1; /* Don't save property additions in the undo history: just * adding/removing the new node is sufficient. */ undo_history = tree->undo_history; tree->undo_history = NULL; } else if (node->move_color != new_move_color) { SgfUndoHistoryEntry *entry = (sgf_change_node_inlined_color_undo_history_entry_new (node, SGF_OPERATION_CHANGE_NODE_MOVE_COLOR, new_move_color, side_effect)); sgf_utils_apply_undo_history_entry (tree, entry); } anything_changed |= (sgf_utils_set_list_of_point_property (node, tree, SGF_ADD_EMPTY, difference_lists[EMPTY], side_effect)); anything_changed |= (sgf_utils_set_list_of_point_property (node, tree, SGF_ADD_BLACK, difference_lists[BLACK], side_effect)); anything_changed |= (sgf_utils_set_list_of_point_property (node, tree, SGF_ADD_WHITE, difference_lists[WHITE], side_effect)); anything_changed |= (sgf_utils_set_list_of_point_property (node, tree, SGF_ADD_ARROWS, difference_lists[ARROW], side_effect)); if (created_new_node) { tree->undo_history = undo_history; sgf_utils_apply_undo_history_entry (tree, sgf_new_node_undo_history_entry_new (node)); } else { if (node->parent) sgf_utils_descend_nodes (tree, 1); else do_enter_tree (tree, node); } sgf_utils_end_action (tree); return anything_changed; } int sgf_utils_apply_markup_changes (SgfGameTree *tree, const char markup_grid[BOARD_GRID_SIZE], int side_effect) { int num_positions[NUM_SGF_MARKUPS]; int positions[NUM_SGF_MARKUPS][BOARD_MAX_POSITIONS]; BoardPositionList *new_markup_lists[NUM_SGF_MARKUPS]; int k; int x; int y; int anything_changed = 0; assert (tree); assert (tree->current_node); assert (markup_grid); for (k = 0; k < NUM_SGF_MARKUPS; k++) num_positions[k] = 0; for (y = 0; y < tree->board_height; y++) { for (x = 0; x < tree->board_width; x++) { int pos = POSITION (x, y); int markup = markup_grid[pos]; if (markup != SGF_MARKUP_NONE) { assert (markup < NUM_SGF_MARKUPS); positions[markup][num_positions[markup]++] = pos; } } } for (k = 0; k < NUM_SGF_MARKUPS; k++) { if (num_positions[k] > 0) { new_markup_lists[k] = board_position_list_new (positions[k], num_positions[k]); } else new_markup_lists[k] = NULL; } sgf_utils_begin_action (tree); anything_changed |= (sgf_utils_set_list_of_point_property (tree->current_node, tree, SGF_MARK, new_markup_lists[SGF_MARKUP_CROSS], side_effect)); anything_changed |= (sgf_utils_set_list_of_point_property (tree->current_node, tree, SGF_CIRCLE, new_markup_lists[SGF_MARKUP_CIRCLE], side_effect)); anything_changed |= (sgf_utils_set_list_of_point_property (tree->current_node, tree, SGF_SQUARE, new_markup_lists[SGF_MARKUP_SQUARE], side_effect)); anything_changed |= (sgf_utils_set_list_of_point_property (tree->current_node, tree, SGF_TRIANGLE, new_markup_lists[SGF_MARKUP_TRIANGLE], side_effect)); anything_changed |= (sgf_utils_set_list_of_point_property (tree->current_node, tree, SGF_SELECTED, new_markup_lists[SGF_MARKUP_SELECTED], side_effect)); sgf_utils_end_action (tree); return anything_changed; } int sgf_utils_set_none_property (SgfNode *node, SgfGameTree *tree, SgfType type, int side_effect) { SgfProperty **link; SgfUndoHistoryEntry *entry; assert (node); assert (tree); assert (property_info[type].value_type == SGF_NONE); if (sgf_node_find_property (node, type, &link)) return 0; sgf_utils_begin_action (tree); entry = sgf_new_property_undo_history_entry_new (tree, node, link, type, side_effect); sgf_utils_apply_undo_history_entry (tree, entry); sgf_utils_end_action (tree); return 1; } int sgf_utils_set_number_property (SgfNode *node, SgfGameTree *tree, SgfType type, int number, int side_effect) { SgfProperty **link; SgfUndoHistoryEntry *entry; assert (node); assert (tree); if (type != SGF_TO_PLAY) { assert (property_info[type].value_type == SGF_NUMBER || property_info[type].value_type == SGF_DOUBLE || property_info[type].value_type == SGF_COLOR); if (sgf_node_find_property (node, type, &link)) { if ((*link)->value.number == number) return 0; entry = sgf_change_property_undo_history_entry_new (node, *link, side_effect); ((SgfChangePropertyOperationEntry *) entry)->value.number = number; } else { entry = sgf_new_property_undo_history_entry_new (tree, node, link, type, side_effect); ((SgfPropertyOperationEntry *) entry)->property->value.number = number; } } else { if (node->to_play_color == number) return 0; assert (number == EMPTY || (!IS_STONE (node->move_color) && IS_STONE (number))); entry = (sgf_change_node_inlined_color_undo_history_entry_new (node, SGF_OPERATION_CHANGE_NODE_TO_PLAY_COLOR, number, side_effect)); } sgf_utils_begin_action (tree); sgf_utils_apply_undo_history_entry (tree, entry); sgf_utils_end_action (tree); return 1; } int sgf_utils_set_real_property (SgfNode *node, SgfGameTree *tree, SgfType type, double value, int side_effect) { SgfProperty **link; SgfUndoHistoryEntry *entry; assert (node); assert (tree); assert (property_info[type].value_type == SGF_REAL); if (sgf_node_find_property (node, type, &link)) { #if SGF_REAL_VALUES_ALLOCATED_SEPARATELY if (* (*link)->value.real == value) return 0; entry = sgf_change_real_property_undo_history_entry_new (node, *link, value, side_effect); #else /* not SGF_REAL_VALUES_ALLOCATED_SEPARATELY */ if ((*link)->value.real == value) return 0; entry = sgf_change_property_undo_history_entry_new (node, *link, side_effect); ((SgfChangePropertyOperationEntry *) entry)->value.real = value; #endif /* not SGF_REAL_VALUES_ALLOCATED_SEPARATELY */ } else { entry = sgf_new_property_undo_history_entry_new (tree, node, link, type, side_effect); #if SGF_REAL_VALUES_ALLOCATED_SEPARATELY ((SgfPropertyOperationEntry *) entry)->property->value.real = utils_duplicate_buffer (&value, sizeof (double)); #else ((SgfPropertyOperationEntry *) entry)->property->value.real = value; #endif } sgf_utils_begin_action (tree); sgf_utils_apply_undo_history_entry (tree, entry); sgf_utils_end_action (tree); return 1; } int sgf_utils_set_text_property (SgfNode *node, SgfGameTree *tree, SgfType type, char *text, int side_effect) { assert (property_info[type].value_type == SGF_SIMPLE_TEXT || property_info[type].value_type == SGF_FAKE_SIMPLE_TEXT || property_info[type].value_type == SGF_TEXT); return do_set_pointer_property (node, tree, type, strings_are_equal, text, side_effect); } int sgf_utils_set_list_of_point_property (SgfNode *node, SgfGameTree *tree, SgfType type, BoardPositionList *position_list, int side_effect) { assert (property_info[type].value_type == SGF_LIST_OF_POINT || property_info[type].value_type == SGF_ELIST_OF_POINT); return do_set_pointer_property (node, tree, type, ((ValuesComparator) board_position_lists_are_equal), position_list, side_effect); } int sgf_utils_set_list_of_label_property (SgfNode *node, SgfGameTree *tree, SgfType type, SgfLabelList *label_list, int side_effect) { assert (property_info[type].value_type == SGF_LIST_OF_LABEL); return do_set_pointer_property (node, tree, type, (ValuesComparator) sgf_label_lists_are_equal, label_list, side_effect); } /* Add a text property to a given node. If such a property already * exists, don't overwrite its value, but instead append new value to * the old one, putting `separator' in between. If this property * doesn't yet exist, the `separator' is not used. If `separator' is * NULL, then "\n\n" is used. * * Return non-zero if the value is appended (zero if added). */ int sgf_utils_append_text_property (SgfNode *node, SgfGameTree *tree, SgfType type, char *text, const char *separator, int side_effect) { const char *existing_text; assert (node); assert (property_info[type].value_type == SGF_SIMPLE_TEXT || property_info[type].value_type == SGF_FAKE_SIMPLE_TEXT || property_info[type].value_type == SGF_TEXT); existing_text = sgf_node_get_text_property_value (node, type); if (existing_text) { char *text_to_free = text; text = utils_cat_strings (utils_duplicate_string (existing_text), (separator ? separator : "\n\n"), text, NULL); utils_free (text_to_free); } return do_set_pointer_property (node, tree, type, strings_are_equal, text, side_effect); } int sgf_utils_set_score_result (SgfNode *node, SgfGameTree *tree, double score, int side_effect) { char *result; if (score < -0.000005 || 0.000005 < score) { char color_who_won = (score > 0.0 ? 'B' : 'W'); if (tree->game == GAME_GO && fabs (score - floor (score + 0.000005)) >= 0.000005) result = utils_cprintf ("%c+%.f", color_who_won, fabs (score)); else result = utils_cprintf ("%c+%d", color_who_won, (int) fabs (score)); } else result = utils_duplicate_string ("Draw"); return do_set_pointer_property (node, tree, SGF_RESULT, strings_are_equal, result, side_effect); } int sgf_utils_set_time_left (SgfNode *node, SgfGameTree *tree, int color, double time_left, int moves_left, int side_effect) { assert (node); assert (tree); assert (IS_STONE (color)); sgf_utils_begin_action (tree); sgf_utils_set_real_property (node, tree, (color == BLACK ? SGF_TIME_LEFT_FOR_BLACK : SGF_TIME_LEFT_FOR_WHITE), time_left, side_effect); if (moves_left) { sgf_utils_set_number_property (node, tree, (color == BLACK ? SGF_MOVES_LEFT_FOR_BLACK : SGF_MOVES_LEFT_FOR_WHITE), moves_left, side_effect); } sgf_utils_end_action (tree); if (tree->board_state && tree->current_node == node) { tree->board_state->time_left[COLOR_INDEX (color)] = time_left; tree->board_state->moves_left[COLOR_INDEX (color)] = moves_left; } return 1; } void sgf_utils_apply_custom_undo_entry (SgfGameTree *tree, const SgfCustomUndoHistoryEntryData *entry_data, void *user_data, SgfNode *node_to_switch_to) { SgfUndoHistoryEntry *entry; assert (tree); assert (entry_data); entry = sgf_custom_undo_history_entry_new (entry_data, user_data, node_to_switch_to); sgf_utils_begin_action (tree); sgf_utils_apply_undo_history_entry (tree, entry); sgf_utils_end_action (tree); } int sgf_utils_get_node_move_number (const SgfNode *node, const SgfGameTree *tree) { int num_moves; assert (node); assert (IS_STONE (node->move_color)); assert (tree); for (num_moves = 0; node && node != tree->current_node; node = node->parent) { int move_number; if (sgf_node_get_number_property_value (node, SGF_MOVE_NUMBER, &move_number)) return move_number + num_moves; if (IS_STONE (node->move_color)) num_moves++; } if (!node) return num_moves; else return tree->board->move_number + num_moves; } int sgf_utils_get_sequential_move_number (const SgfGameTree *tree) { int move_number; assert (tree); assert (tree->current_node); assert (tree->board); if (sgf_node_find_property (tree->current_node, SGF_MOVE_NUMBER, NULL)) { if (tree->current_node->parent) move_number = board_get_move_number (tree->board, 1); else move_number = 0; if (IS_STONE (tree->current_node->move_color)) move_number++; } else move_number = tree->board->move_number; return move_number; } int sgf_utils_determine_player_to_move_by_rules (const SgfGameTree *tree) { int color_to_play_copy; int sgf_color_to_play_copy; int color_to_play_by_rules; assert (tree); assert (tree->current_node); color_to_play_copy = tree->board_state->color_to_play; sgf_color_to_play_copy = tree->board_state->sgf_color_to_play; find_board_state_data (tree, tree->current_node, 1, 0); determine_final_color_to_play (tree); color_to_play_by_rules = tree->board_state->color_to_play; tree->board_state->color_to_play = color_to_play_copy; tree->board_state->sgf_color_to_play = sgf_color_to_play_copy; return color_to_play_by_rules; } void sgf_utils_find_board_state_data (const SgfGameTree *tree, int need_color_to_move, int need_move_coordinates) { assert (tree); assert (tree->current_node); find_board_state_data (tree, tree->current_node, need_color_to_move, need_move_coordinates); } void sgf_utils_find_time_control_data (const SgfGameTree *tree) { assert (tree); assert (tree->current_node); find_time_control_data (tree, tree->root, tree->current_node); } void sgf_utils_delete_current_node (SgfGameTree *tree) { SgfUndoHistoryEntry *entry; assert (tree); assert (tree->current_node); assert (tree->current_node->parent); assert (tree->board_state); entry = sgf_delete_node_undo_history_entry_new (tree->current_node); sgf_utils_begin_action (tree); sgf_utils_apply_undo_history_entry (tree, entry); sgf_utils_end_action (tree); } void sgf_utils_delete_current_node_children (SgfGameTree *tree) { SgfUndoHistoryEntry *entry; assert (tree); assert (tree->current_node); assert (tree->board_state); /* Is there anything to delete at all? */ if (!tree->current_node->child) return; entry = sgf_delete_node_children_undo_history_entry_new (tree->current_node); sgf_utils_begin_action (tree); sgf_utils_apply_undo_history_entry (tree, entry); sgf_utils_end_action (tree); } void sgf_utils_swap_current_node_with (SgfGameTree *tree, SgfNode *swap_with) { SgfUndoHistoryEntry *entry; assert (tree); assert (tree->current_node); assert (swap_with); assert (tree->current_node != swap_with); assert (tree->current_node->parent == swap_with->parent); entry = sgf_swap_nodes_undo_history_entry_new (tree->current_node, swap_with); sgf_utils_begin_action (tree); sgf_utils_apply_undo_history_entry (tree, entry); sgf_utils_end_action (tree); } int sgf_utils_delete_property (SgfNode *node, SgfGameTree *tree, SgfType type, int side_effect) { SgfProperty **link; assert (node); assert (tree); if (sgf_node_find_property (node, type, &link)) { SgfUndoHistoryEntry *entry = sgf_delete_property_undo_history_entry_new (node, *link, side_effect); sgf_utils_begin_action (tree); sgf_utils_apply_undo_history_entry (tree, entry); sgf_utils_end_action (tree); return 1; } return 0; } void sgf_utils_set_node_is_collapsed (SgfGameTree *tree, SgfNode *node, int is_collapsed) { assert (tree); assert (node); if ((is_collapsed && !node->is_collapsed) || (!is_collapsed && node->is_collapsed)) { GAME_TREE_DO_NOTIFY (tree, SGF_ABOUT_TO_MODIFY_MAP); node->is_collapsed = (is_collapsed ? 1 : 0); sgf_game_tree_invalidate_map (tree, node); GAME_TREE_DO_NOTIFY (tree, SGF_MAP_MODIFIED); } } void sgf_utils_get_markup (const SgfGameTree *tree, char markup[BOARD_GRID_SIZE]) { SgfNode *node; const BoardPositionList *position_list; int k; assert (tree); assert (tree->current_node); assert (markup); node = tree->current_node; board_fill_grid (tree->board, markup, SGF_MARKUP_NONE); position_list = sgf_node_get_list_of_point_property_value (node, SGF_MARK); if (position_list) { for (k = 0; k < position_list->num_positions; k++) markup[position_list->positions[k]] = SGF_MARKUP_CROSS; } position_list = sgf_node_get_list_of_point_property_value (node, SGF_CIRCLE); if (position_list) { for (k = 0; k < position_list->num_positions; k++) markup[position_list->positions[k]] = SGF_MARKUP_CIRCLE; } position_list = sgf_node_get_list_of_point_property_value (node, SGF_SQUARE); if (position_list) { for (k = 0; k < position_list->num_positions; k++) markup[position_list->positions[k]] = SGF_MARKUP_SQUARE; } position_list = sgf_node_get_list_of_point_property_value (node, SGF_TRIANGLE); if (position_list) { for (k = 0; k < position_list->num_positions; k++) markup[position_list->positions[k]] = SGF_MARKUP_TRIANGLE; } position_list = sgf_node_get_list_of_point_property_value (node, SGF_SELECTED); if (position_list) { for (k = 0; k < position_list->num_positions; k++) markup[position_list->positions[k]] = SGF_MARKUP_SELECTED; } } void sgf_utils_mark_territory_on_grid (const SgfGameTree *tree, char grid[BOARD_GRID_SIZE], char black_territory_mark, char white_territory_mark) { assert (tree); assert (tree->board); assert (tree->current_node); assert (grid); if (tree->game == GAME_GO) { const BoardPositionList *territory_list; int k; territory_list = sgf_node_get_list_of_point_property_value (tree->current_node, SGF_BLACK_TERRITORY); if (territory_list) { for (k = 0; k < territory_list->num_positions; k++) { if (tree->board->grid[territory_list->positions[k]] != BLACK) grid[territory_list->positions[k]] = black_territory_mark; } } territory_list = sgf_node_get_list_of_point_property_value (tree->current_node, SGF_WHITE_TERRITORY); if (territory_list) { for (k = 0; k < territory_list->num_positions; k++) { if (tree->board->grid[territory_list->positions[k]] != WHITE) grid[territory_list->positions[k]] = white_territory_mark; } } } } /* Set handicap in the `tree's current node (normally root). If fixed * handicap is requested, the function also adds `AB' property with * required number of handicap stones. */ void sgf_utils_set_handicap (SgfGameTree *tree, int handicap, int is_fixed) { assert (tree); assert (tree->game == GAME_GO); assert (tree->current_node); assert (handicap == 0 || handicap > 1); assert (!IS_STONE (tree->current_node->move_color)); if (is_fixed) { if (handicap != 0) { BoardPositionList *handicap_stones = go_get_fixed_handicap_stones (tree->board_width, tree->board_height, handicap); tree->current_node->move_color = SETUP_NODE; sgf_node_add_list_of_point_property (tree->current_node, tree, SGF_ADD_BLACK, handicap_stones, 0); } } else assert (handicap < tree->board_width * tree->board_height); sgf_node_add_text_property (tree->current_node, tree, SGF_HANDICAP, utils_cprintf ("%d", handicap), 1); } void sgf_utils_add_free_handicap_stones (SgfGameTree *tree, BoardPositionList *handicap_stones) { int handicap; assert (tree); assert (tree->current_node); assert (handicap_stones); handicap = sgf_node_get_handicap (tree->current_node); assert (0 < handicap_stones->num_positions && handicap_stones->num_positions <= handicap); tree->current_node->move_color = SETUP_NODE; sgf_node_add_list_of_point_property (tree->current_node, tree, SGF_ADD_BLACK, handicap_stones, 0); } /* Normalize text for an SGF property. * * For simple text: convert '\t' into appropriate number of spaces, * replace '\n', '\v' and '\f' characters with one space, remove all * '\r' characters and trim both leading and trailing whitespace. * * For other (multiline) text: convert '\t' into appropriate number of * spaces,. convert '\v' and '\f' into a few linefeeds, remove all * '\r' characters and, finally, trim trailing whitespace. */ char * sgf_utils_normalize_text (const char *text, int is_simple_text) { const char *normalized_up_to; int current_column = 0; StringBuffer buffer; char *scan; assert (text); if (is_simple_text) { while (*text == ' ' || *text == '\t' || *text == '\n' || *text == '\r' || *text == '\v' || *text == '\f') { if (*text != '\r') { current_column++; if (*text == '\t') current_column = ROUND_UP (current_column, 8); } text++; } } if (! *text) return NULL; string_buffer_init (&buffer, 0x1000, 0x1000); for (normalized_up_to = text; *text; text++) { if (IS_UTF8_STARTER (*text)) { if (*text != '\n' || is_simple_text) { current_column++; if (*text == '\t' || *text == '\v' || *text == '\f' || *text == '\n' || *text == '\r') { string_buffer_cat_as_string (&buffer, normalized_up_to, text - normalized_up_to); normalized_up_to = text + 1; if (*text == '\t') { int tab_to_column = ROUND_UP (current_column, 8); string_buffer_add_characters (&buffer, ' ', tab_to_column - current_column); current_column = tab_to_column; } else if (*text != '\r') { if (is_simple_text) { /* Convert all whitespace into a single space * character. */ string_buffer_add_character (&buffer, ' '); } else { /* This is hardly important. Insert a few empty * lines. */ string_buffer_add_characters (&buffer, '\n', 4); current_column = 0; } } else { /* Remove. */ current_column--; } } } else current_column = 0; } } string_buffer_cat_as_string (&buffer, normalized_up_to, text - normalized_up_to); /* Trim end whitespace. */ for (scan = buffer.string + buffer.length; ; scan--) { if (scan == buffer.string) { string_buffer_dispose (&buffer); return NULL; } if (*(scan - 1) != ' ' && *(scan - 1) != '\n') break; } *scan = 0; return utils_realloc (buffer.string, (scan + 1) - buffer.string); } /* Create and return an in-memory SGF of a subtree of `tree', starting * at `subtree_root'. The resulting SGF tree always has extra dummy * root, which is used to setup board. I.e. `subtree_root' will * correspond to the only child of SGF game tree root. */ char * sgf_utils_create_subtree_sgf (SgfGameTree *tree, SgfNode *subtree_root, int *sgf_length) { SgfNode *current_node; SgfCollection *pseudo_collection; SgfGameTree *pseudo_tree; SgfNode *pseudo_root; SgfNode *pseudo_subtree_root; Board *board; SgfBoardState board_state; char *result; assert (tree); assert (tree->board); assert (tree->board_state); assert (subtree_root); assert (sgf_length); pseudo_collection = sgf_collection_new (); pseudo_tree = sgf_game_tree_new_with_root (tree->game, tree->board_width, tree->board_height, 0); pseudo_root = pseudo_tree->root; sgf_collection_add_game_tree (pseudo_collection, pseudo_tree); current_node = tree->current_node; if (subtree_root != current_node) sgf_utils_do_switch_to_given_node (tree, subtree_root); board = board_new (tree->game, tree->board_width, tree->board_height); sgf_utils_enter_tree (pseudo_tree, board, &board_state); /* Copy board grid state to the pseudo tree. */ sgf_utils_apply_setup_changes (pseudo_tree, tree->board->grid, 1); /* FIXME: Should the board be deleted by the tree itself? */ board_delete (board); if (current_node != subtree_root) sgf_utils_do_switch_to_given_node (tree, current_node); pseudo_subtree_root = sgf_node_duplicate (subtree_root, pseudo_tree, pseudo_root); pseudo_subtree_root->child = subtree_root->child; pseudo_root->child = pseudo_subtree_root; result = sgf_write_in_memory (pseudo_collection, 1, sgf_length); /* Don't accidentally delete real tree's nodes! */ pseudo_subtree_root->child = NULL; sgf_collection_delete (pseudo_collection); return result; } SgfPasteResult sgf_utils_paste_sgf (SgfGameTree *tree, SgfNode *parent_node, char *sgf, int sgf_length) { SgfCollection *parsed_collection; SgfGameTree *parsed_tree; SgfErrorList *errors; SgfNode *node_to_paste; int parsing_result; assert (tree); assert (tree->current_node); assert (parent_node); assert (sgf); assert (sgf_length > 0); parsing_result = sgf_parse_buffer (sgf, sgf_length, &parsed_collection, &errors, &sgf_parser_defaults, NULL, NULL); /* FIXME: Errors are ignored. */ if (errors) string_list_delete (errors); switch (parsing_result) { case SGF_PARSING_CANCELLED: case SGF_ERROR_READING_FILE: assert (0); case SGF_INVALID_FILE: return SGF_INVALID_SGF; } if (parsed_collection->num_trees != 1) { sgf_collection_delete (parsed_collection); return SGF_NOT_CLIPBOARD_SGF; } parsed_tree = parsed_collection->first_tree; /* A valid SGF to paste must have exactly one root child. */ if (!parsed_tree->root || !parsed_tree->root->child || parsed_tree->root->child->next) { sgf_collection_delete (parsed_collection); return SGF_NOT_CLIPBOARD_SGF; } if (parsed_tree->game != tree->game || parsed_tree->board_width != tree->board_width || parsed_tree->board_height != tree->board_height) { sgf_collection_delete (parsed_collection); return SGF_COULDNT_PASTE; } /* This is quite ugly, but we have to duplicate everything for the * tree we paste into, because node and property allocation is * tree-specific with memory pools (the default.) */ node_to_paste = sgf_node_duplicate_recursively (parsed_tree->root->child, tree, parent_node); sgf_collection_delete (parsed_collection); if (parent_node != tree->current_node) sgf_utils_do_switch_to_given_node (tree, parent_node); sgf_utils_begin_action (tree); sgf_utils_apply_undo_history_entry (tree, sgf_new_node_undo_history_entry_new (node_to_paste)); sgf_utils_end_action (tree); return SGF_PASTED; } char * sgf_utils_export_position_as_ascii (const SgfGameTree *tree) { StringBuffer result; BoardPoint hoshi_points[9]; int num_hoshi_points = 0; int x; int y; assert (tree); assert (tree->board); assert (tree->board_state); if (tree->game == GAME_GO) { num_hoshi_points = go_get_hoshi_points (tree->board_width, tree->board_height, hoshi_points); } string_buffer_init (&result, 0x400, 0x200); add_horizontal_coordinates (tree, &result); add_horizontal_line (tree, &result, 0); for (y = 0; y < tree->board_height; y++) { int vertical_coordinate = (game_info[tree->game].reversed_vertical_coordinates ? tree->board_height - y : y + 1); string_buffer_printf (&result, "%*d |", tree->board_height < 10 ? 1 : 2, vertical_coordinate); if (tree->board_state->last_move_x != 0 || tree->board_state->last_move_y != y) string_buffer_add_character (&result, ' '); else string_buffer_add_character (&result, '('); for (x = 0; x < tree->board_width; x++) { char character = '.'; switch (tree->board->grid[POSITION (x, y)]) { case EMPTY: { int k; for (k = 0; k < num_hoshi_points; k++) { if (x == hoshi_points[k].x && y == hoshi_points[k].y) { character = '+'; break; } } } break; case BLACK: character = 'X'; break; case WHITE: character = 'O'; break; case SPECIAL_ON_GRID_VALUE: character = '='; break; default: assert (0); } string_buffer_add_character (&result, character); if ((tree->board_state->last_move_x != x && tree->board_state->last_move_x != x + 1) || tree->board_state->last_move_y != y) string_buffer_add_character (&result, ' '); else { if (tree->board_state->last_move_x == x) string_buffer_add_character (&result, ')'); else string_buffer_add_character (&result, '('); } } string_buffer_printf (&result, "| %-*d\n", tree->board_height < 10 ? 1 : 2, vertical_coordinate); } add_horizontal_line (tree, &result, 0); add_horizontal_coordinates (tree, &result); return string_buffer_steal_string (&result); } char * sgf_utils_export_position_as_senseis_library_diagram (const SgfGameTree *tree) { StringBuffer result; const SgfBoardState *board_state; const BoardPositionList* circle_mark; const BoardPositionList* square_mark; const SgfLabelList *labels; int x; int y; assert (tree); assert (tree->game == GAME_GO); assert (tree->board); assert (tree->board_state); assert (tree->current_node); board_state = tree->board_state; circle_mark = sgf_node_get_list_of_point_property_value (tree->current_node, SGF_CIRCLE); square_mark = sgf_node_get_list_of_point_property_value (tree->current_node, SGF_SQUARE); labels = sgf_node_get_list_of_label_property_value (tree->current_node, SGF_LABEL); string_buffer_init (&result, 0x400, 0x200); string_buffer_add_characters (&result, '$', 2); if (board_state->last_move_node) { string_buffer_add_character (&result, board_state->last_move_node->move_color == BLACK ? 'B' : 'W'); } string_buffer_cat_string (&result, " \n"); add_horizontal_line (tree, &result, 1); for (y = 0; y < tree->board_height; y++) { string_buffer_cat_string (&result, "$$ |"); for (x = 0; x < tree->board_width; x++) { static const char *characters = ".CSXB#OW@1"; int pos = POSITION (x, y); const char *character; string_buffer_add_character (&result, ' '); if (tree->board->grid[pos] == EMPTY) { if (labels) { BoardPoint point = { x, y }; const char *label = sgf_label_list_get_label (labels, point); if (label && (('a' <= label[0] && label[0] <= 'z') || ('A' <= label[0] && label[0] <= 'Z')) && !label[1]) { char label_character = label[0]; if ('A' <= label_character && label_character <= 'Z') label_character -= 'A' - 'a'; string_buffer_add_character (&result, label_character); continue; } } character = characters; } else { switch (tree->board->grid[pos]) { case BLACK: character = characters + 3; break; case WHITE: character = characters + 6; break; default: assert (0); } } if (circle_mark && board_position_list_find_position (circle_mark, pos) != -1) character += 1; else if (square_mark && board_position_list_find_position (square_mark, pos) != -1) character += 2; else if (IS_STONE (tree->board->grid[pos]) && tree->board_state->last_move_x == x && tree->board_state->last_move_y == y) character = characters + 9; string_buffer_add_character (&result, *character); } string_buffer_cat_string (&result, " |\n"); } add_horizontal_line (tree, &result, 1); return string_buffer_steal_string (&result); } static void add_horizontal_coordinates (const SgfGameTree *tree, StringBuffer *buffer) { int x; string_buffer_add_characters (buffer, ' ', tree->board_height < 10 ? 3 : 4); for (x = 0; x < tree->board_width; x++) { char coordinate_character = game_info[tree->game].horizontal_coordinates[x]; string_buffer_add_character (buffer, ' '); string_buffer_add_character (buffer, coordinate_character); } string_buffer_add_character (buffer, '\n'); } static void add_horizontal_line (const SgfGameTree *tree, StringBuffer *buffer, int sensei_style) { if (sensei_style) string_buffer_cat_string (buffer, "$$ "); else { string_buffer_add_characters (buffer, ' ', tree->board_height < 10 ? 2 : 3); } string_buffer_add_character (buffer, '+'); string_buffer_add_characters (buffer, '-', 2 * tree->board_width + 1); string_buffer_add_character (buffer, '+'); string_buffer_add_character (buffer, '\n'); } static void do_enter_tree (SgfGameTree *tree, SgfNode *down_to) { static SgfNode root_predecessor; SgfBoardState *const board_state = tree->board_state; SgfNode *node; int num_nodes = 1; board_set_parameters (tree->board, tree->game, tree->board_width, tree->board_height); board_state->sgf_color_to_play = EMPTY; board_state->last_move_x = NULL_X; board_state->last_move_y = NULL_Y; board_state->game_info_node = NULL; board_state->last_move_node = NULL; board_state->last_main_variation_node = NULL; board_state->time_left[BLACK_INDEX] = -1.0; board_state->time_left[WHITE_INDEX] = -1.0; board_state->moves_left[BLACK_INDEX] = -1; board_state->moves_left[WHITE_INDEX] = -1; for (node = tree->root; node != down_to; node = node->current_variation) { assert (node); num_nodes++; } /* Use a fake SGF node so that sgf_utils_descend_nodes() has * something to descend from. */ root_predecessor.child = tree->root; root_predecessor.current_variation = tree->root; tree->current_node = &root_predecessor; tree->current_node_depth = -1; sgf_utils_descend_nodes (tree, num_nodes); } inline void sgf_utils_do_switch_to_given_node (SgfGameTree *tree, SgfNode *node) { SgfNode *path_scan; for (path_scan = node; path_scan->parent; path_scan = path_scan->parent) path_scan->parent->current_variation = path_scan; do_enter_tree (tree, node); } /* Descend in an SGF tree from current node by one or more nodes, * always following node's current variation. Nodes' move or setup * properties, whichever are present, are played on tree's associated * board and `board_state' is updated as needed. */ void sgf_utils_descend_nodes (SgfGameTree *tree, int num_nodes) { SgfBoardState *const board_state = tree->board_state; SgfNode *node = tree->current_node; tree->current_node_depth += num_nodes; do { if (node->current_variation) { if (node->current_variation != node->child && !board_state->last_main_variation_node) board_state->last_main_variation_node = node; } else { if (!node->child) { tree->current_node_depth -= num_nodes; break; } node->current_variation = node->child; } node = node->current_variation; if (!board_state->game_info_node && sgf_node_is_game_info_node (node)) { board_state->game_info_node = node; board_state->game_info_node_depth = (tree->current_node_depth - (num_nodes - 1)); } if (IS_STONE (node->move_color)) { sgf_utils_play_node_move (node, tree->board); board_state->sgf_color_to_play = OTHER_COLOR (node->move_color); board_state->last_move_x = node->move_point.x; board_state->last_move_node = node; } else { if (node->move_color == SETUP_NODE) { const BoardPositionList *position_lists[NUM_ON_GRID_VALUES]; position_lists[BLACK] = sgf_node_get_list_of_point_property_value (node, SGF_ADD_BLACK); position_lists[WHITE] = sgf_node_get_list_of_point_property_value (node, SGF_ADD_WHITE); position_lists[EMPTY] = sgf_node_get_list_of_point_property_value (node, SGF_ADD_EMPTY); if (tree->game == GAME_AMAZONS) { position_lists[ARROW] = sgf_node_get_list_of_point_property_value (node, SGF_ADD_ARROWS); } else position_lists[ARROW] = NULL; board_apply_changes (tree->board, position_lists); board_state->last_move_x = NULL_X; } else board_add_dummy_move_entry (tree->board); if (node->to_play_color != EMPTY) board_state->sgf_color_to_play = node->to_play_color; } if (node->move_color != SETUP_NODE) { sgf_node_get_number_property_value (node, SGF_MOVE_NUMBER, (int *) &tree->board->move_number); } } while (--num_nodes != 0); if (node != tree->current_node) { if (board_state->last_move_x != NULL_X) board_state->last_move_y = board_state->last_move_node->move_point.y; else board_state->last_move_y = NULL_Y; find_time_control_data (tree, tree->current_node, node); tree->current_node = node; determine_final_color_to_play (tree); } } void sgf_utils_ascend_nodes (SgfGameTree *tree, int num_nodes) { SgfBoardState *const board_state = tree->board_state; SgfNode *node = tree->current_node; int k; for (k = 0; k < num_nodes && node->parent; k++) { node = node->parent; if (board_state->last_main_variation_node == node) board_state->last_main_variation_node = NULL; } if (node->parent) { board_undo (tree->board, num_nodes); find_board_state_data (tree, node, 1, 1); find_time_control_data (tree, NULL, node); tree->current_node = node; tree->current_node_depth -= num_nodes; if (board_state->game_info_node && board_state->game_info_node_depth > tree->current_node_depth) board_state->game_info_node = NULL; determine_final_color_to_play (tree); } else do_enter_tree (tree, tree->root); } static void find_board_state_data (const SgfGameTree *tree, SgfNode *node, int need_color_to_move, int need_move_coordinates) { SgfBoardState *const board_state = tree->board_state; if (!need_color_to_move && !need_move_coordinates) return; board_state->last_move_node = NULL; if (need_color_to_move) board_state->sgf_color_to_play = EMPTY; while (1) { if (IS_STONE (node->move_color)) { if (board_state->sgf_color_to_play == EMPTY) board_state->sgf_color_to_play = OTHER_COLOR (node->move_color); board_state->last_move_node = node; if (need_move_coordinates) { board_state->last_move_x = node->move_point.x; board_state->last_move_y = node->move_point.y; } break; } else { if (board_state->sgf_color_to_play == EMPTY) { /* `PL' is a setup property, so we check only here. */ board_state->sgf_color_to_play = node->to_play_color; } if (node->move_color == SETUP_NODE) { if (need_move_coordinates) { board_state->last_move_x = NULL_X; board_state->last_move_y = NULL_Y; need_move_coordinates = 0; } } } node = node->parent; if (!node) { if (need_move_coordinates) { board_state->last_move_x = NULL_X; board_state->last_move_y = NULL_Y; } break; } } } static void find_time_control_data (const SgfGameTree *tree, SgfNode *upper_limit, SgfNode *lower_limit) { SgfBoardState *const board_state = tree->board_state; SgfNode *node; char have_time_left_for_black = 0; char have_time_left_for_white = 0; char have_moves_left_for_black = 0; char have_moves_left_for_white = 0; if (!upper_limit) { have_time_left_for_black = (board_state->time_left[BLACK_INDEX] == -1.0); have_time_left_for_white = (board_state->time_left[WHITE_INDEX] == -1.0); have_moves_left_for_black = (board_state->moves_left[BLACK_INDEX] == -1); have_moves_left_for_white = (board_state->moves_left[WHITE_INDEX] == -1); } else { /* Weird fix for do_enter_tree()'s `root_predecessor'. */ if (upper_limit->child) upper_limit = upper_limit->child->parent; } node = lower_limit; while (!(have_time_left_for_black && have_time_left_for_white && have_moves_left_for_black && have_moves_left_for_white)) { if (!have_time_left_for_black) { have_time_left_for_black = (sgf_node_get_real_property_value (node, SGF_TIME_LEFT_FOR_BLACK, &board_state->time_left[BLACK_INDEX])); } if (!have_time_left_for_white) { have_time_left_for_white = (sgf_node_get_real_property_value (node, SGF_TIME_LEFT_FOR_WHITE, &board_state->time_left[WHITE_INDEX])); } if (!have_moves_left_for_black) { have_moves_left_for_black = (sgf_node_get_number_property_value (node, SGF_MOVES_LEFT_FOR_BLACK, &board_state->moves_left[BLACK_INDEX])); } if (!have_moves_left_for_white) { have_moves_left_for_white = (sgf_node_get_number_property_value (node, SGF_MOVES_LEFT_FOR_WHITE, &board_state->moves_left[WHITE_INDEX])); } node = node->parent; if (node == upper_limit) break; } } static void determine_final_color_to_play (const SgfGameTree *tree) { const SgfNode *game_info_node = tree->board_state->game_info_node; if (tree->board_state->sgf_color_to_play == EMPTY && tree->game == GAME_GO && game_info_node) { int handicap = sgf_node_get_handicap (game_info_node); if (handicap > 0 && sgf_node_get_list_of_point_property_value (game_info_node, SGF_ADD_BLACK)) tree->board_state->sgf_color_to_play = WHITE; else if (handicap == 0) tree->board_state->sgf_color_to_play = BLACK; } tree->board_state->color_to_play = board_adjust_color_to_play (tree->board, RULE_SET_DEFAULT, tree->board_state->sgf_color_to_play); } static int do_set_pointer_property (SgfNode *node, SgfGameTree *tree, SgfType type, ValuesComparator values_are_equal, void *new_value, int side_effect) { SgfProperty **link; SgfUndoHistoryEntry *entry; assert (node); assert (tree); if (sgf_node_find_property (node, type, &link)) { if (new_value) { if (values_are_equal ((*link)->value.memory_block, new_value)) { SgfValue value; value.memory_block = new_value; sgf_property_free_value (property_info[type].value_type, &value); return 0; } entry = sgf_change_property_undo_history_entry_new (node, *link, side_effect); ((SgfChangePropertyOperationEntry *) entry)->value.memory_block = new_value; } else entry = sgf_delete_property_undo_history_entry_new (node, *link, side_effect); } else { if (!new_value) return 0; entry = sgf_new_property_undo_history_entry_new (tree, node, link, type, side_effect); ((SgfPropertyOperationEntry *) entry)->property->value.memory_block = new_value; } sgf_utils_begin_action (tree); sgf_utils_apply_undo_history_entry (tree, entry); sgf_utils_end_action (tree); return 1; } static int strings_are_equal (const void *first_string, const void *second_string) { return (strcmp ((const char *) first_string, (const char *) second_string) == 0); } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/sgf/sgf-writer.c0000644000175000017500000005401010520637074015305 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "sgf.h" #include "sgf-writer.h" #include "sgf-privates.h" #include "board.h" #include "utils.h" #include #include #include #include #include #define SGF_WRITER_BUFFER_SIZE 0x4000 static void write_collection (SgfWritingData *data, SgfCollection *collection, int force_utf8); static void write_game_tree (SgfWritingData *data, SgfGameTree *tree, int force_utf8); static void write_node_sequence (SgfWritingData *data, const SgfNode *node); inline static void do_write_point (SgfWritingData *data, BoardPoint point); static void do_write_point_or_rectangle (SgfWritingData *data, BoardPoint left_top, BoardPoint right_bottom); static void do_write_go_move (SgfWritingData *data, const SgfNode *node); static void do_write_reversi_move (SgfWritingData *data, const SgfNode *node); static void do_write_amazons_move (SgfWritingData *data, const SgfNode *node); static int do_write_text (SgfWritingData *data, const char *text, char terminating_character, int simple); /* NOTE: if `filename' is NULL, write to stdout. * FIXME: add proper comment and actually write this function. */ char * sgf_write_file (const char *filename, SgfCollection *collection, int force_utf8) { SgfWritingData data; const char *initialization_error; assert (collection); initialization_error = buffered_writer_init (&data.writer, filename, SGF_WRITER_BUFFER_SIZE); if (initialization_error) return utils_duplicate_string (initialization_error); write_collection (&data, collection, force_utf8); if (data.writer.successful) { buffered_writer_dispose (&data.writer); return NULL; } else { char* error = utils_duplicate_string (data.writer.error_string); buffered_writer_dispose (&data.writer); return error; } } char * sgf_write_in_memory (SgfCollection *collection, int force_utf8, int *sgf_length) { SgfWritingData data; assert (collection); assert (sgf_length); buffered_writer_init_memory (&data.writer, SGF_WRITER_BUFFER_SIZE); write_collection (&data, collection, force_utf8); return buffered_writer_dispose_memory (&data.writer, sgf_length); } static void write_collection (SgfWritingData *data, SgfCollection *collection, int force_utf8) { for (data->tree = collection->first_tree; data->tree; data->tree = data->tree->next) { write_game_tree (data, data->tree, force_utf8); if (data->tree->next) buffered_writer_add_newline (&data->writer); if (!data->writer.successful) break; } } static void write_game_tree (SgfWritingData *data, SgfGameTree *tree, int force_utf8) { SgfNode *root = tree->root; const BoardPositionList *root_black_stones; const BoardPositionList *root_white_stones; BoardPositionList *black_stones; BoardPositionList *white_stones; int default_setup_hidden = 0; buffered_writer_cprintf (&data->writer, "(;GM[%d]FF[4]\n", tree->game); if (force_utf8 || tree->char_set) { buffered_writer_cprintf (&data->writer, "CA[%s]\n", force_utf8 ? "UTF-8" : tree->char_set); } buffered_writer_cat_string (&data->writer, "AP[" PACKAGE_NAME ":" PACKAGE_VERSION "]\n"); if (tree->board_width == tree->board_height) buffered_writer_cprintf (&data->writer, "SZ[%d]\n", tree->board_width); else { buffered_writer_cprintf (&data->writer, "SZ[%d:%d]\n", tree->board_width, tree->board_height); } if (tree->style_is_set) buffered_writer_cprintf (&data->writer, "ST[%d]\n", tree->style); root_black_stones = sgf_node_get_list_of_point_property_value (root, SGF_ADD_BLACK); root_white_stones = sgf_node_get_list_of_point_property_value (root, SGF_ADD_WHITE); if (root_black_stones && root_white_stones && (tree->game != GAME_AMAZONS || !sgf_node_get_list_of_point_property_value (root, SGF_ADD_ARROWS))) { if (game_get_default_setup (tree->game, tree->board_width, tree->board_height, &black_stones, &white_stones)) { if (board_position_lists_are_equal (root_black_stones, black_stones) && board_position_lists_are_equal (root_white_stones, white_stones)) { sgf_node_delete_property (root, tree, SGF_ADD_BLACK); sgf_node_delete_property (root, tree, SGF_ADD_WHITE); default_setup_hidden = 1; } else { board_position_list_delete (black_stones); board_position_list_delete (white_stones); } } } if (data->tree->game == GAME_GO) data->do_write_move = do_write_go_move; else if (data->tree->game == GAME_REVERSI) data->do_write_move = do_write_reversi_move; else if (data->tree->game == GAME_AMAZONS) data->do_write_move = do_write_amazons_move; else assert (0); if (force_utf8 || (tree->char_set && strcmp (tree->char_set, "UTF-8") == 0)) data->utf8_to_tree_encoding = NULL; else { data->utf8_to_tree_encoding = iconv_open ((tree->char_set ? tree->char_set : "ISO-8859-1"), "UTF-8"); assert (data->utf8_to_tree_encoding != (iconv_t) (-1)); } write_node_sequence (data, root); if (data->utf8_to_tree_encoding) iconv_close (data->utf8_to_tree_encoding); if (data->writer.column > 0) buffered_writer_add_newline (&data->writer); buffered_writer_add_character (&data->writer, ')'); buffered_writer_add_newline (&data->writer); if (default_setup_hidden) { sgf_node_add_list_of_point_property (root, tree, SGF_ADD_BLACK, black_stones, 0); sgf_node_add_list_of_point_property (root, tree, SGF_ADD_WHITE, white_stones, 0); } } static void write_node_sequence (SgfWritingData *data, const SgfNode *node) { while (1) { SgfValue to_play; SgfProperty *property; if (IS_STONE (node->move_color)) { buffered_writer_add_character (&data->writer, node->move_color == BLACK ? 'B' : 'W'); buffered_writer_add_character (&data->writer, '['); data->do_write_move (data, node); buffered_writer_add_character (&data->writer, ']'); } to_play.color = node->to_play_color; for (property = node->properties; property; property = property->next) { if (property_info[property->type].value_writer) { if (data->writer.column >= FILL_BREAK_POINT) buffered_writer_add_newline (&data->writer); if (to_play.color != EMPTY && property->type > SGF_LAST_SETUP_PROPERTY) { buffered_writer_cat_string (&data->writer, property_info[SGF_TO_PLAY].name); sgf_write_color (data, &to_play); to_play.color = EMPTY; } buffered_writer_cat_string (&data->writer, property_info[property->type].name); property_info[property->type].value_writer (data, &property->value); if (SGF_FIRST_GAME_INFO_PROPERTY <= property->type && property->type <= SGF_LAST_GAME_INFO_PROPERTY && data->writer.column > 0) buffered_writer_add_newline (&data->writer); } else assert (0); } /* This can happen if there are no properties after `PL'. */ if (to_play.color != EMPTY) { buffered_writer_cat_string (&data->writer, property_info[SGF_TO_PLAY].name); sgf_write_color (data, &to_play); } if (!node->child) break; node = node->child; if (!node->next) { if (data->writer.column >= FILL_BREAK_POINT - 1) buffered_writer_add_newline (&data->writer); buffered_writer_add_character (&data->writer, ';'); continue; } do { if (data->writer.column > 0) buffered_writer_add_newline (&data->writer); buffered_writer_add_character (&data->writer, '('); buffered_writer_add_character (&data->writer, ';'); write_node_sequence (data, node); if (data->writer.column >= FILL_COLUMN - 1) buffered_writer_add_newline (&data->writer); buffered_writer_add_character (&data->writer, ')'); node = node->next; } while (node); break; } } inline static void do_write_point (SgfWritingData *data, BoardPoint point) { buffered_writer_add_character (&data->writer, (point.x < 'z' - 'a' + 1 ? 'a' + point.x : 'A' + (point.x - ('z' - 'a' + 1)))); buffered_writer_add_character (&data->writer, (point.y < 'z' - 'a' + 1 ? 'a' + point.y : 'A' + (point.y - ('z' - 'a' + 1)))); } static void do_write_point_or_rectangle (SgfWritingData *data, BoardPoint left_top, BoardPoint right_bottom) { buffered_writer_add_character (&data->writer, '['); do_write_point (data, left_top); if (left_top.x != right_bottom.x || left_top.y != right_bottom.y) { buffered_writer_add_character (&data->writer, ':'); do_write_point (data, right_bottom); } buffered_writer_add_character (&data->writer, ']'); if (data->writer.column >= FILL_BREAK_POINT) buffered_writer_add_newline (&data->writer); } static void do_write_go_move (SgfWritingData *data, const SgfNode *node) { if (node->move_point.x != PASS_X) do_write_point (data, node->move_point); } static void do_write_reversi_move (SgfWritingData *data, const SgfNode *node) { do_write_point (data, node->move_point); } static void do_write_amazons_move (SgfWritingData *data, const SgfNode *node) { /* Move-amazon-from point. */ do_write_point (data, node->data.amazons.from); /* Move-amazon-to point. */ do_write_point (data, node->move_point); /* Shoot-arrow-to point. */ do_write_point (data, node->data.amazons.shoot_arrow_to); } void sgf_write_none (SgfWritingData *data, const SgfValue *value) { UNUSED (value); buffered_writer_add_character (&data->writer, '['); buffered_writer_add_character (&data->writer, ']'); } void sgf_write_number (SgfWritingData *data, const SgfValue *value) { buffered_writer_add_character (&data->writer, '['); buffered_writer_cprintf (&data->writer, "%d", value->number); buffered_writer_add_character (&data->writer, ']'); } void sgf_write_real (SgfWritingData *data, const SgfValue *value) { buffered_writer_add_character (&data->writer, '['); #if SGF_REAL_VALUES_ALLOCATED_SEPARATELY buffered_writer_cprintf (&data->writer, "%.f", *value->real); #else buffered_writer_cprintf (&data->writer, "%.f", value->real); #endif buffered_writer_add_character (&data->writer, ']'); } void sgf_write_double (SgfWritingData *data, const SgfValue *value) { buffered_writer_add_character (&data->writer, '['); buffered_writer_add_character (&data->writer, value->emphasized ? '2' : '1'); buffered_writer_add_character (&data->writer, ']'); } void sgf_write_color (SgfWritingData *data, const SgfValue *value) { buffered_writer_add_character (&data->writer, '['); buffered_writer_add_character (&data->writer, value->color == BLACK ? 'B' : 'W'); buffered_writer_add_character (&data->writer, ']'); } /* FIXME: Comment. * * Argument `terminating_character' should be ither ']' or ':'. Other * values are not prohibited, but they don't make sense in SGF. */ static int do_write_text (SgfWritingData *data, const char *text, char terminating_character, int simple) { const char *lookahead; const char *written_up_to; int columns_left = FILL_COLUMN - data->writer.column; int multi_line_value = 0; buffered_writer_set_iconv_handle (&data->writer, data->utf8_to_tree_encoding); for (lookahead = text; ; lookahead++) { if (!IS_UTF8_STARTER (*lookahead)) continue; columns_left--; if (*lookahead == ']' || *lookahead == '\\') columns_left--; if ((*lookahead == ' ' && (columns_left >= 0 || simple)) || *lookahead == '\n' || ! *lookahead) { for (written_up_to = text; text < lookahead; text++) { if (*text == ']' || *text == '\\') { buffered_writer_cat_as_string (&data->writer, written_up_to, text - written_up_to); written_up_to = text; buffered_writer_add_character (&data->writer, '\\'); } } buffered_writer_cat_as_string (&data->writer, written_up_to, text - written_up_to); if (*lookahead == '\n') { buffered_writer_add_newline (&data->writer); columns_left = FILL_COLUMN; text++; } else if (! *lookahead) break; } if (columns_left < 0) { if (*text == ' ') { if (simple) { text++; columns_left++; } else { if (text < lookahead - 1) { buffered_writer_add_character (&data->writer, ' '); text++; } buffered_writer_add_character (&data->writer, '\\'); columns_left--; } } else { const char *line_limit = lookahead - 1; if (!ispunct (*line_limit)) { while (line_limit > text + 1 && !ispunct (*(line_limit - 1))) line_limit--; if (line_limit <= text + 1) line_limit = lookahead - 1; } for (written_up_to = text; text < line_limit; text++) { if (*text == ']' || *text == '\\') { buffered_writer_cat_as_string (&data->writer, written_up_to, text - written_up_to); written_up_to = text; buffered_writer_add_character (&data->writer, '\\'); } } buffered_writer_cat_as_string (&data->writer, written_up_to, text - written_up_to); buffered_writer_add_character (&data->writer, '\\'); columns_left--; } columns_left += data->writer.column; buffered_writer_add_newline (&data->writer); multi_line_value = 1; } } /* Note that terminating character is written in encoding specified * by `CA' property. SGF specification remains silent about this, * but otherwise files can become unparseable in certain encodings. */ buffered_writer_add_character (&data->writer, terminating_character); buffered_writer_set_iconv_handle (&data->writer, NULL); return multi_line_value; } void sgf_write_simple_text (SgfWritingData *data, const SgfValue *value) { int multi_line_value; buffered_writer_add_character (&data->writer, '['); multi_line_value = do_write_text (data, value->text, ']', 1); if (multi_line_value) buffered_writer_add_newline (&data->writer); } void sgf_write_fake_simple_text (SgfWritingData *data, const SgfValue *value) { const char *text; const char *written_up_to; buffered_writer_add_character (&data->writer, '['); buffered_writer_set_iconv_handle (&data->writer, data->utf8_to_tree_encoding); for (text = value->text, written_up_to = text; *text; text++) { if (*text == '\\' || *text == ']') { buffered_writer_cat_as_string (&data->writer, written_up_to, text - written_up_to); written_up_to = text; buffered_writer_add_character (&data->writer, '\\'); } } buffered_writer_cat_as_string (&data->writer, written_up_to, text - written_up_to); buffered_writer_set_iconv_handle (&data->writer, NULL); buffered_writer_add_character (&data->writer, ']'); buffered_writer_add_newline (&data->writer); } void sgf_write_text (SgfWritingData *data, const SgfValue *value) { int multi_line_value; buffered_writer_add_character (&data->writer, '['); multi_line_value = do_write_text (data, value->text, ']', 0); if (multi_line_value) buffered_writer_add_newline (&data->writer); } /* Write a compressed list of points. See SGF 4 specification for * description of compressed list. The algorithm used here should be * moderately efficient, extremely fast and quite simple. * * NOTE: It relies on points being sorted in ascending order. */ void sgf_write_list_of_point (SgfWritingData *data, const SgfValue *value) { int num_positions = value->position_list->num_positions; int *positions = value->position_list->positions; if (num_positions > 1) { int k; int x; int width = data->tree->board_width; BoardPoint left_top[BOARD_MAX_WIDTH]; BoardPoint right_bottom; for (x = 0; x < width; x++) left_top[x].x = NULL_X; for (k = 1; k <= num_positions ; k++) { int left_x = POSITION_X (positions[k - 1]); int y = POSITION_Y (positions[k - 1]); int limit_x; right_bottom.x = left_x; right_bottom.y = y - 1; while (left_top[(int) right_bottom.x].x != left_x) { if (left_top[(int) right_bottom.x].x != NULL_X) { do_write_point_or_rectangle (data, left_top[(int) right_bottom.x], right_bottom); left_top[(int) right_bottom.x].x = NULL_X; } if (k == num_positions || positions[k] != EAST (positions[k - 1])) { left_top[(int) right_bottom.x].x = left_x; left_top[(int) right_bottom.x].y = y; break; } right_bottom.x++; k++; } if (k < num_positions && positions[k] < SOUTH (positions[k - 1])) limit_x = POSITION_X (positions[k]); else limit_x = right_bottom.x; while (1) { if (++right_bottom.x == width) { right_bottom.x = 0; right_bottom.y++; } if (right_bottom.x == limit_x) break; if (left_top[(int) right_bottom.x].x != NULL_X) { do_write_point_or_rectangle (data, left_top[(int) right_bottom.x], right_bottom); left_top[(int) right_bottom.x].x = NULL_X; } } if (k == num_positions || positions[k] > SOUTH (positions[k - 1])) { if (left_top[(int) right_bottom.x].x != NULL_X) { do_write_point_or_rectangle (data, left_top[(int) right_bottom.x], right_bottom); left_top[(int) right_bottom.x].x = NULL_X; } } } if (data->writer.column > 0) buffered_writer_add_newline (&data->writer); } else { buffered_writer_add_character (&data->writer, '['); if (num_positions == 1) { BoardPoint point; point.x = POSITION_X (positions[0]); point.y = POSITION_Y (positions[0]); do_write_point (data, point); } buffered_writer_add_character (&data->writer, ']'); } } void sgf_write_list_of_vector (SgfWritingData *data, const SgfValue *value) { int k; int num_vectors = value->vector_list->num_vectors; const SgfVector *vectors = value->vector_list->vectors; for (k = 0; k < num_vectors; k++) { if (data->writer.column >= FILL_BREAK_POINT) buffered_writer_add_newline (&data->writer); buffered_writer_add_character (&data->writer, '['); do_write_point (data, vectors[k].from_point); buffered_writer_add_character (&data->writer, ':'); do_write_point (data, vectors[k].to_point); buffered_writer_add_character (&data->writer, ']'); } if (data->writer.column > 0) buffered_writer_add_newline (&data->writer); } void sgf_write_list_of_label (SgfWritingData *data, const SgfValue *value) { SgfLabelList *label_list = value->label_list; int multi_line_value = 0; int k; for (k = 0; k < label_list->num_labels; k++) { buffered_writer_add_character (&data->writer, '['); do_write_point (data, label_list->labels[k].point); buffered_writer_add_character (&data->writer, ':'); multi_line_value += do_write_text (data, label_list->labels[k].text, ']', 1); if (data->writer.column >= FILL_BREAK_POINT) buffered_writer_add_newline (&data->writer); } if ((label_list->num_labels > 1 || multi_line_value) && data->writer.column > 0) buffered_writer_add_newline (&data->writer); } void sgf_write_figure_description (SgfWritingData *data, const SgfValue *value) { buffered_writer_add_character (&data->writer, '['); if (value->figure) buffered_writer_cprintf (&data->writer, "%d:", value->figure->flags); if (value->figure && value->figure->diagram_name) do_write_text (data, value->figure->diagram_name, ']', 1); else buffered_writer_add_character (&data->writer, ']'); } void sgf_write_unknown (SgfWritingData *data, const SgfValue *value) { const StringListItem *list_item = value->unknown_value_list->first; int need_newline; buffered_writer_cat_string (&data->writer, list_item->text); list_item = list_item->next; if (!list_item->next) { const char *lookahead; need_newline = 0; for (lookahead = list_item->text; *lookahead; lookahead++) { if (*lookahead == '\\') lookahead++; if (*lookahead == '\n') { need_newline = 1; break; } } } else need_newline = 1; do { buffered_writer_add_character (&data->writer, '['); buffered_writer_set_iconv_handle (&data->writer, data->utf8_to_tree_encoding); buffered_writer_cat_string (&data->writer, list_item->text); buffered_writer_add_character (&data->writer, ']'); buffered_writer_set_iconv_handle (&data->writer, NULL); list_item = list_item->next; if (list_item) { const char *lookahead; int columns_left = FILL_COLUMN - data->writer.column - 1; for (lookahead = list_item->text; *lookahead && *lookahead != '\n'; lookahead++) { if (IS_UTF8_STARTER (*lookahead)) { if (*lookahead == '\\') { if (--columns_left >= 0 && *++lookahead == '\n') break; } if (--columns_left < 0) { buffered_writer_add_newline (&data->writer); break; } } } } } while (list_item); if (need_newline && data->writer.column > 0) buffered_writer_add_newline (&data->writer); } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/sgf/sgf.h0000644000175000017500000007270210520636622014006 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef QUARRY_SGF_H #define QUARRY_SGF_H #include "sgf-properties.h" #include "board.h" #include "utils.h" #include "quarry.h" /* `sgf-tree.c' global declarations and functions. */ /* We don't use Go-specific MIME type here and I think it is right, * since we mean generic SGF here. */ #define SGF_MIME_TYPE "text/x-sgf" /* Note that in this means that the node has one of the `add sth.' * properties. Other setup (in SGF sense) nodes, like `PL' do not * count! */ #define SETUP_NODE SPECIAL_ON_GRID_VALUE enum { SGF_MARKUP_CROSS, SGF_MARKUP_CIRCLE, SGF_MARKUP_SQUARE, SGF_MARKUP_TRIANGLE, SGF_MARKUP_SELECTED, NUM_SGF_MARKUPS, /* Defined to -1 so that higher level code can easily add more * non-empty (pseudo) markups above `SGF_MARKUP_SELECTED'. */ SGF_MARKUP_NONE = -1 }; enum { SGF_STYLE_CURRENT_NODE_VARIATIONS = 1 << 0, SGF_STYLE_NO_BOARD_MARKUP = 1 << 1, SGF_STYLE_FLAGS_MASK = 0x3 }; enum { SGF_FIGURE_SHOW_COORDINATES = 1 << 0, SGF_FIGURE_SHOW_DIAGRAM_NAME = 1 << 1, SGF_FIGURE_LIST_MISSED_MOVES = 1 << 2, SGF_FIGURE_REMOVE_CAPTURES = 1 << 8, SGF_FIGURE_SHOW_HOSHI_POINTS = 1 << 9, SGF_FIGURE_USE_DEFAULTS = 1 << 15, SGF_FIGURE_FLAGS_MASK = 0x8307 }; enum { SGF_PRINT_MODE_NO_MOVE_NUMBERS, SGF_PRINT_MODE_SHOW_MOVE_NUMBERS, SGF_PRINT_MODE_MOVE_NUMBERS_MODULO_100, NUM_SGF_PRINT_MODES }; typedef enum { SGF_ABOUT_TO_MODIFY_MAP, SGF_ABOUT_TO_MODIFY_TREE, SGF_ABOUT_TO_CHANGE_CURRENT_NODE, SGF_CURRENT_NODE_CHANGED, SGF_TREE_MODIFIED, SGF_MAP_MODIFIED, SGF_GAME_TREE_DELETED } SgfGameTreeNotificationCode; typedef struct _SgfVector SgfVector; typedef struct _SgfVectorList SgfVectorList; typedef struct _SgfLabel SgfLabel; typedef struct _SgfLabelList SgfLabelList; typedef struct _SgfFigureDescription SgfFigureDescription; typedef union _SgfValue SgfValue; typedef struct _SgfProperty SgfProperty; typedef struct _SgfNode SgfNode; typedef struct _SgfNodeGeneric SgfNodeGeneric; typedef struct _SgfNodeGeneric SgfNodeGo; typedef struct _SgfNodeGeneric SgfNodeReversi; typedef struct _SgfNodeAmazons SgfNodeAmazons; typedef struct _SgfBoardState SgfBoardState; typedef struct _SgfUndoHistoryEntry SgfUndoHistoryEntry; typedef struct _SgfUndoHistory SgfUndoHistory; typedef void (* SgfUndoHistoryNotificationCallback) (SgfUndoHistory *undo_history, void *user_data); typedef struct _SgfGameTree SgfGameTree; typedef void (* SgfCustomOperationEntryFunction) (void *user_data, SgfGameTree *tree); typedef struct _SgfCustomUndoHistoryEntryData SgfCustomUndoHistoryEntryData; typedef struct _SgfGameTreeMapData SgfGameTreeMapData; typedef struct _SgfGameTreeMapLine SgfGameTreeMapLine; typedef void (* SgfGameTreeNotificationCallback) (SgfGameTree *tree, SgfGameTreeNotificationCode notification_code, void *user_data); typedef struct _SgfCollection SgfCollection; typedef void (* SgfCollectionNotificationCallback) (SgfCollection *collection, void *user_data); struct _SgfVector { BoardPoint from_point; BoardPoint to_point; }; struct _SgfVectorList { /* This field is private to the implementation. */ int allocated_num_vectors; int num_vectors; SgfVector vectors[1]; }; struct _SgfLabel { BoardPoint point; char *text; }; struct _SgfLabelList { int num_labels; SgfLabel labels[1]; }; struct _SgfFigureDescription { int flags; char *diagram_name; }; /* Union is a very handy thing, but unfortunately, standard C doesn't * allow casting to them. The main problem is size of members: while * on any sane 32-bit machine they are all 32 bits, that's not true in * general case. Therefore, casting from pointer to member type to * pointer to union (which is allowed by compiler) is a no-no thing. */ union _SgfValue { int number; #if SGF_REAL_VALUES_ALLOCATED_SEPARATELY /* Have to allocate doubles on heap :( */ double *real; #else double real; #endif int emphasized; int color; void *memory_block; char *text; BoardPositionList *position_list; SgfVectorList *vector_list; SgfLabelList *label_list; SgfFigureDescription *figure; /* For unknown properties. First string stores identifier, the * rest---property values. */ StringList *unknown_value_list; }; #define SGF_TYPE_STORAGE_BITS 8 /* AFAIK, enums are unsigned when possible, but we better be careful * to avoid random bugs jumping out of nowhere. */ #if SGF_NUM_PROPERTIES > (1 << (SGF_TYPE_STORAGE_BITS - 1)) #error Too many property types. Increase SGF_TYPE_STORAGE_BITS. #endif struct _SgfProperty { MEMORY_POOL_ITEM_INDEX; SgfType type : SGF_TYPE_STORAGE_BITS; SgfProperty *next; SgfValue value; }; /* This strucuture is used for game-independent node access. However, * accessing to game-specific fields (in `data' union) is only allowed * if the node belongs to game tree for corresponding game. Otherwise * nasty things like memory corruption or access violation will * happen. */ struct _SgfNode { MEMORY_POOL_ITEM_INDEX; unsigned int is_collapsed : 1; unsigned int has_intermediate_map_data : 1; unsigned int to_play_color : 2; unsigned int move_color : 2; BoardPoint move_point; SgfNode *parent; SgfNode *child; SgfNode *next; SgfNode *current_variation; SgfProperty *properties; BoardAbstractMoveData data; }; /* These two structure are only used in sgf_game_tree_set_game() to * determine the size of node required for given game. For huge SGF * trees four bytes wasted on BoardAmazonsMoveData when it is not * required might lead to significant memory footprint increase. */ struct _SgfNodeGeneric { MEMORY_POOL_ITEM_INDEX; unsigned int is_collapsed : 1; unsigned int has_intermediate_map_data : 1; unsigned int to_play_color : 2; unsigned int move_color : 2; BoardPoint move_point; SgfNode *parent; SgfNode *child; SgfNode *next; SgfNode *current_variation; SgfProperty *properties; }; struct _SgfNodeAmazons { MEMORY_POOL_ITEM_INDEX; unsigned int is_collapsed : 1; unsigned int has_intermediate_map_data : 1; unsigned int to_play_color : 2; unsigned int move_color : 2; BoardPoint move_point; SgfNode *parent; SgfNode *child; SgfNode *next; SgfNode *current_variation; SgfProperty *properties; BoardAmazonsMoveData amazons; }; /* An SgfBoardState structure is associated with a tree (much like a * board.) It is only used and kept valid by `sgf-utils' module. * * Fields must not be changed from outside `sgf-utils' module. */ struct _SgfBoardState { int color_to_play; int last_move_x; int last_move_y; SgfNode *game_info_node; int game_info_node_depth; SgfNode *last_move_node; /* Will be NULL if in main variation. */ SgfNode *last_main_variation_node; /* Time control data as stored in the game record. Negative values * mean that the property is not set. */ double time_left[NUM_COLORS]; int moves_left[NUM_COLORS]; /* Private fields. Must be of no interest outside `sgf-utils'. */ int sgf_color_to_play; }; struct _SgfUndoHistory { SgfUndoHistoryEntry *first_entry; SgfUndoHistoryEntry *last_entry; SgfUndoHistoryEntry *last_applied_entry; SgfUndoHistoryEntry *unmodified_state_entry; SgfUndoHistory *next; SgfUndoHistoryNotificationCallback notification_callback; void *user_data; }; struct _SgfCustomUndoHistoryEntryData { SgfCustomOperationEntryFunction undo; SgfCustomOperationEntryFunction redo; SgfCustomOperationEntryFunction free_data; }; struct _SgfGameTreeMapData { SgfGameTreeMapData *next; SgfNode *node; int x; int *y_level; int last_valid_y_level; int largest_x_so_far; }; struct _SgfGameTreeMapLine { int x0; int y0; int y1; int x2; int x3; }; struct _SgfGameTree { SgfCollection *collection; SgfGameTree *previous; SgfGameTree *next; SgfNode *root; SgfNode *current_node; int current_node_depth; int game; int board_width; int board_height; Board *board; SgfBoardState *board_state; /* The currently active undo history. */ SgfUndoHistory *undo_history; /* Head of the undo history list for this tree. */ SgfUndoHistory *undo_history_list; /* These fields are related to the undo history, but are used even * if there is no active history. */ int undo_operation_level; SgfNode *node_to_switch_to; unsigned int is_modifying_map : 1; unsigned int is_modifying_tree : 1; unsigned int tree_was_modified : 1; unsigned int collection_was_modified : 1; unsigned int could_undo : 1; unsigned int could_redo : 1; int file_format; char *char_set; char *application_name; char *application_version; int style_is_set; int style; MemoryPool node_pool; MemoryPool property_pool; SgfGameTreeNotificationCallback notification_callback; void *user_data; /* The ``map.'' */ int map_width; int map_height; SgfGameTreeMapData *map_data_list; SgfGameTreeMapData *last_valid_data_point; int view_port_x0; int view_port_y0; int view_port_x1; int view_port_y1; SgfNode **view_port_nodes; int num_view_port_lines; SgfGameTreeMapLine *view_port_lines; }; struct _SgfCollection { int num_trees; SgfGameTree *first_tree; SgfGameTree *last_tree; int num_modified_undo_histories; int is_irreversibly_modified; SgfCollectionNotificationCallback notification_callback; void *user_data; }; typedef struct _SgfGameTreeState SgfGameTreeState; struct _SgfGameTreeState { Board *board; SgfBoardState *board_state; SgfNode *current_node; int current_node_depth; }; typedef enum { SGF_RESULT_WIN, SGF_RESULT_BLACK_WIN = SGF_RESULT_WIN + BLACK_INDEX, SGF_RESULT_WHITE_WIN = SGF_RESULT_WIN + WHITE_INDEX, SGF_RESULT_WIN_BY_FORFEIT, SGF_RESULT_BLACK_WIN_BY_FORFEIT = (SGF_RESULT_WIN_BY_FORFEIT + BLACK_INDEX), SGF_RESULT_WHITE_WIN_BY_FORFEIT = (SGF_RESULT_WIN_BY_FORFEIT + WHITE_INDEX), SGF_RESULT_WIN_BY_RESIGNATION, SGF_RESULT_BLACK_WIN_BY_RESIGNATION = (SGF_RESULT_WIN_BY_RESIGNATION + BLACK_INDEX), SGF_RESULT_WHITE_WIN_BY_RESIGNATION = (SGF_RESULT_WIN_BY_RESIGNATION + WHITE_INDEX), SGF_RESULT_WIN_BY_SCORE, SGF_RESULT_BLACK_WIN_BY_SCORE = SGF_RESULT_WIN_BY_SCORE + BLACK_INDEX, SGF_RESULT_WHITE_WIN_BY_SCORE = SGF_RESULT_WIN_BY_SCORE + WHITE_INDEX, SGF_RESULT_WIN_BY_TIME, SGF_RESULT_BLACK_WIN_BY_TIME = SGF_RESULT_WIN_BY_TIME + BLACK_INDEX, SGF_RESULT_WHITE_WIN_BY_TIME = SGF_RESULT_WIN_BY_TIME + WHITE_INDEX, SGF_RESULT_UNKNOWN, SGF_RESULT_DRAW, SGF_RESULT_VOID, SGF_RESULT_NOT_SET, SGF_RESULT_INVALID } SgfResult; SgfCollection * sgf_collection_new (void); void sgf_collection_delete (SgfCollection *collection); void sgf_collection_add_game_tree (SgfCollection *collection, SgfGameTree *tree); int sgf_collection_is_modified (const SgfCollection *collection); void sgf_collection_set_unmodified (SgfCollection *collection); void sgf_collection_set_notification_callback (SgfCollection *collection, SgfCollectionNotificationCallback callback, void *user_data); SgfGameTree * sgf_game_tree_new (void); SgfGameTree * sgf_game_tree_new_with_root (Game game, int board_width, int board_height, int provide_default_setup); void sgf_game_tree_delete (SgfGameTree *tree); void sgf_game_tree_set_game (SgfGameTree *tree, Game game); void sgf_game_tree_set_state (SgfGameTree *tree, const SgfGameTreeState *state); void sgf_game_tree_get_state (SgfGameTree *tree, SgfGameTreeState *state); SgfGameTree * sgf_game_tree_duplicate (const SgfGameTree *tree); SgfGameTree * sgf_game_tree_duplicate_with_nodes (const SgfGameTree *tree); SgfNode * sgf_game_tree_traverse_forward (const SgfGameTree *tree); SgfNode * sgf_game_tree_traverse_backward (const SgfGameTree *tree); int sgf_game_tree_count_nodes (const SgfGameTree *tree); void sgf_game_tree_set_notification_callback (SgfGameTree *tree, SgfGameTreeNotificationCallback callback, void *user_data); SgfNode * sgf_node_new (SgfGameTree *tree, SgfNode *parent); void sgf_node_delete (SgfNode *node, SgfGameTree *tree); SgfNode * sgf_node_get_previous_node (const SgfNode *node); SgfNode * sgf_node_get_last_child (const SgfNode *node); SgfNode * sgf_node_duplicate (const SgfNode *node, SgfGameTree *tree, SgfNode *parent); SgfNode * sgf_node_duplicate_recursively (const SgfNode *node, SgfGameTree *tree, SgfNode *parent); SgfNode * sgf_node_duplicate_to_given_depth (const SgfNode *node, SgfGameTree *tree, SgfNode *parent, int depth); int sgf_node_find_property (SgfNode *node, SgfType type, SgfProperty ***link); int sgf_node_find_unknown_property (SgfNode *node, char *id, int length, SgfProperty ***link); int sgf_node_is_game_info_node (const SgfNode *node); int sgf_node_get_number_property_value (const SgfNode *node, SgfType type, int *number); int sgf_node_get_double_property_value (const SgfNode *node, SgfType type); int sgf_node_get_color_property_value (const SgfNode *node, SgfType type); int sgf_node_get_real_property_value (const SgfNode *node, SgfType type, double *value); const char * sgf_node_get_text_property_value (const SgfNode *node, SgfType type); const BoardPositionList * sgf_node_get_list_of_point_property_value (const SgfNode *node, SgfType type); const SgfVectorList * sgf_node_get_list_of_vector_property_value (const SgfNode *node, SgfType type); const SgfLabelList * sgf_node_get_list_of_label_property_value (const SgfNode *node, SgfType type); int sgf_node_get_handicap (const SgfNode *node); int sgf_node_get_komi (const SgfNode *node, double *komi); SgfResult sgf_node_get_result (const SgfNode *node, double *score); int sgf_node_get_time_limit (const SgfNode *node, double *time_limit); int sgf_node_add_none_property (SgfNode *node, SgfGameTree *tree, SgfType type); int sgf_node_add_number_property (SgfNode *node, SgfGameTree *tree, SgfType type, int number, int overwrite); int sgf_node_add_real_property (SgfNode *node, SgfGameTree *tree, SgfType type, double value, int overwrite); int sgf_node_add_pointer_property (SgfNode *node, SgfGameTree *tree, SgfType type, void *pointer, int overwrite); #define sgf_node_add_double_property(node, tree, type, emphasized, \ overwrite) \ sgf_node_add_number_property ((node), (tree), (type), (emphasized), \ (overwrite)) #define sgf_node_add_color_property(node, tree, type, color, overwrite) \ sgf_node_add_number_property ((node), (tree), (type), (color), \ (overwrite)) #define sgf_node_add_text_property(node, tree, type, text, overwrite) \ sgf_node_add_pointer_property ((node), (tree), (type), (text), \ (overwrite)) #define sgf_node_add_list_of_point_property(node, tree, \ type, position_list, \ overwrite) \ sgf_node_add_pointer_property ((node), (tree), \ (type), (position_list), (overwrite)) #define sgf_node_add_list_of_label_property(node, tree, \ type, label_list, \ overwrite) \ sgf_node_add_pointer_property ((node), (tree), (type), (label_list), \ (overwrite)) int sgf_node_delete_property (SgfNode *node, SgfGameTree *tree, SgfType type); void sgf_node_split (SgfNode *node, SgfGameTree *tree); SgfNode * sgf_node_traverse_forward (const SgfNode *node); SgfNode * sgf_node_traverse_backward (const SgfNode *node); int sgf_node_count_subtree_nodes (const SgfNode *node); inline SgfProperty * sgf_property_new (SgfGameTree *tree, SgfType type, SgfProperty *next); inline void sgf_property_delete (SgfProperty *property, SgfGameTree *tree); void sgf_property_delete_at_link (SgfProperty **link, SgfGameTree *tree); SgfProperty * sgf_property_duplicate (const SgfProperty *property, SgfGameTree *tree, SgfProperty *next); SgfVectorList * sgf_vector_list_new (int num_vectors); #define sgf_vector_list_delete(list) \ do { \ assert (list); \ utils_free (list); \ } while (0) SgfVectorList * sgf_vector_list_shrink (SgfVectorList *list); SgfVectorList * sgf_vector_list_add_vector (SgfVectorList *list, BoardPoint from_point, BoardPoint to_point); int sgf_vector_list_has_vector (const SgfVectorList *list, BoardPoint from_point, BoardPoint to_point); SgfVectorList * sgf_vector_list_duplicate (const SgfVectorList *list); SgfLabelList * sgf_label_list_new (int num_labels, BoardPoint *points, char **labels); SgfLabelList * sgf_label_list_new_empty (int num_labels); void sgf_label_list_delete (SgfLabelList *list); SgfLabelList * sgf_label_list_duplicate (const SgfLabelList *list); const char * sgf_label_list_get_label (const SgfLabelList *list, BoardPoint point); SgfLabelList * sgf_label_list_set_label (const SgfLabelList *old_list, BoardPoint point, char *label_text); int sgf_label_lists_are_equal (const SgfLabelList *first_list, const SgfLabelList *second_list); int sgf_label_list_contains_label (const SgfLabelList *list, const char *label); SgfFigureDescription * sgf_figure_description_new (int flags, char *diagram_name); void sgf_figure_description_delete (SgfFigureDescription *figure); SgfFigureDescription * sgf_figure_description_duplicate (const SgfFigureDescription *figure); /* `sgf-parser.c' global declarations, functions and variables. */ #define SGF_MIN_BOARD_SIZE 1 #define SGF_MAX_BOARD_SIZE 52 enum { SGF_PARSED, SGF_PARSING_CANCELLED, SGF_ERROR_READING_FILE, SGF_INVALID_FILE }; typedef struct _SgfParserParameters SgfParserParameters; struct _SgfParserParameters { int max_buffer_size; int buffer_refresh_margin; int buffer_size_increment; int first_column; }; typedef struct _SgfErrorListItem SgfErrorListItem; typedef struct _SgfErrorList SgfErrorList; struct _SgfErrorListItem { SgfErrorListItem *next; char *text; int line; int column; }; struct _SgfErrorList { SgfErrorListItem *first; SgfErrorListItem *last; int item_size; StringListItemDispose item_dispose; }; #define sgf_error_list_new() \ ((SgfErrorList *) string_list_new_derived (sizeof (SgfErrorListItem), \ NULL)) #define sgf_error_list_init(list) \ string_list_init_derived ((list), sizeof (SgfErrorListItem), NULL) #define STATIC_SGF_ERROR_LIST \ STATIC_STRING_LIST_DERIVED (SgfErrorListItem, NULL) #define sgf_error_list_get_item(list, item_index) \ ((SgfErrorListItem *) string_list_get_item ((list), (item_index))) #define sgf_error_list_find(list, text) \ ((SgfErrorListItem *) string_list_find ((list), (text))) #define sgf_error_list_find_after_notch(list, text, notch) \ ((SgfErrorListItem *) \ string_list_find_after_notch ((list), (text) (notch))) int sgf_parse_file (const char *filename, SgfCollection **collection, SgfErrorList **error_list, const SgfParserParameters *parameters, int *file_size, int *bytes_parsed, const int *cancellation_flag); int sgf_parse_buffer (char *buffer, int size, SgfCollection **collection, SgfErrorList **error_list, const SgfParserParameters *parameters, int *bytes_parsed, const int *cancellation_flag); extern const SgfParserParameters sgf_parser_defaults; /* `sgf-writer.c' global functions. */ char * sgf_write_file (const char *filename, SgfCollection *collection, int force_utf8); char * sgf_write_in_memory (SgfCollection *collection, int force_utf8, int *sgf_length); /* `sgf-utils.c' global declarations and functions. */ typedef enum { SGF_NEXT, SGF_PREVIOUS } SgfDirection; typedef enum { SGF_PASTED, SGF_COULDNT_PASTE, SGF_NOT_CLIPBOARD_SGF, SGF_INVALID_SGF } SgfPasteResult; inline void sgf_utils_play_node_move (const SgfNode *node, Board *board); void sgf_utils_format_node_move (const SgfGameTree *tree, const SgfNode *node, StringBuffer *buffer, const char *black_string, const char *white_string, const char *pass_string); void sgf_utils_enter_tree (SgfGameTree *tree, Board *board, SgfBoardState *board_state); void sgf_utils_go_down_in_tree (SgfGameTree *tree, int num_nodes); void sgf_utils_go_up_in_tree (SgfGameTree *tree, int num_nodes); int sgf_utils_count_variations (const SgfGameTree *tree, int of_current_node, int black_variations[BOARD_GRID_SIZE], int white_variations[BOARD_GRID_SIZE], int *other_variations); SgfNode * sgf_utils_find_variation_at_position (SgfGameTree *tree, int x, int y, SgfDirection direction, int after_current); void sgf_utils_switch_to_variation (SgfGameTree *tree, SgfDirection direction); void sgf_utils_switch_to_given_variation (SgfGameTree *tree, SgfNode *node); void sgf_utils_switch_to_given_node (SgfGameTree *tree, SgfNode *node); SgfNode * sgf_utils_append_variation (SgfGameTree *tree, int color, ...); int sgf_utils_apply_setup_changes (SgfGameTree *tree, const char grid[BOARD_GRID_SIZE], int side_effect); int sgf_utils_apply_markup_changes (SgfGameTree *tree, const char markup_grid[BOARD_GRID_SIZE], int side_effect); int sgf_utils_set_none_property (SgfNode *node, SgfGameTree *tree, SgfType type, int side_effect); int sgf_utils_set_number_property (SgfNode *node, SgfGameTree *tree, SgfType type, int number, int side_effect); int sgf_utils_set_real_property (SgfNode *node, SgfGameTree *tree, SgfType type, double value, int side_effect); int sgf_utils_set_text_property (SgfNode *node, SgfGameTree *tree, SgfType type, char *text, int side_effect); int sgf_utils_set_list_of_point_property (SgfNode *node, SgfGameTree *tree, SgfType type, BoardPositionList *position_list, int side_effect); int sgf_utils_set_list_of_label_property (SgfNode *node, SgfGameTree *tree, SgfType type, SgfLabelList *label_list, int side_effect); #define sgf_utils_set_double_property(node, tree, type, emphasized, \ side_effect) \ sgf_utils_set_number_property ((node), (tree), (type), (emphasized), \ (side_effect)) #define sgf_utils_set_color_property(node, tree, type, color, \ side_effect) \ sgf_utils_set_number_property ((node), (tree), (type), (color), \ (side_effect)) int sgf_utils_append_text_property (SgfNode *node, SgfGameTree *tree, SgfType type, char *text, const char *separator, int side_effect); int sgf_utils_set_score_result (SgfNode *node, SgfGameTree *tree, double score, int side_effect); int sgf_utils_set_time_left (SgfNode *node, SgfGameTree *tree, int color, double time_left, int moves_left, int side_effect); void sgf_utils_apply_custom_undo_entry (SgfGameTree *tree, const SgfCustomUndoHistoryEntryData *entry_data, void *user_data, SgfNode *node_to_switch_to); int sgf_utils_get_node_move_number (const SgfNode *node, const SgfGameTree *tree); int sgf_utils_get_sequential_move_number (const SgfGameTree *tree); int sgf_utils_determine_player_to_move_by_rules (const SgfGameTree *tree); void sgf_utils_find_board_state_data (const SgfGameTree *tree, int need_color_to_move, int need_move_coordinates); void sgf_utils_find_time_control_data (const SgfGameTree *tree); void sgf_utils_delete_current_node (SgfGameTree *tree); void sgf_utils_delete_current_node_children (SgfGameTree *tree); void sgf_utils_swap_current_node_with (SgfGameTree *tree, SgfNode *swap_with); int sgf_utils_delete_property (SgfNode *node, SgfGameTree *tree, SgfType type, int side_effect); void sgf_utils_set_node_is_collapsed (SgfGameTree *tree, SgfNode *node, int is_collapsed); void sgf_utils_get_markup (const SgfGameTree *tree, char markup[BOARD_GRID_SIZE]); void sgf_utils_mark_territory_on_grid (const SgfGameTree *tree, char grid[BOARD_GRID_SIZE], char black_territory_mark, char white_territory_mark); void sgf_utils_set_handicap (SgfGameTree *tree, int handicap, int is_fixed); void sgf_utils_add_free_handicap_stones (SgfGameTree *tree, BoardPositionList *handicap_stones); char * sgf_utils_normalize_text (const char *text, int is_simple_text); char * sgf_utils_create_subtree_sgf (SgfGameTree *tree, SgfNode *subtree_root, int *sgf_length); SgfPasteResult sgf_utils_paste_sgf (SgfGameTree *tree, SgfNode *parent_node, char *sgf, int sgf_length); char * sgf_utils_export_position_as_ascii (const SgfGameTree *tree); char * sgf_utils_export_position_as_senseis_library_diagram (const SgfGameTree *tree); /* `sgf-undo.c' global functions. */ SgfUndoHistory * sgf_undo_history_new (SgfGameTree *tree); void sgf_undo_history_delete (SgfUndoHistory *history, SgfGameTree *associated_tree); void sgf_undo_history_set_notification_callback (SgfUndoHistory *history, SgfUndoHistoryNotificationCallback notification_callback, void *user_data); void sgf_undo_history_hide_last_applied_entry (SgfUndoHistory *history); int sgf_undo_history_is_last_applied_entry_single (const SgfUndoHistory *history); int sgf_undo_history_check_last_applied_custom_entry_type (const SgfUndoHistory *history, const SgfCustomUndoHistoryEntryData *entry_data); void * sgf_undo_history_get_last_applied_custom_entry_data (const SgfUndoHistory *history); void sgf_undo_history_delete_redo_entries (SgfUndoHistory *history, SgfGameTree *tree); void sgf_utils_begin_action (SgfGameTree *tree); void sgf_utils_end_action (SgfGameTree *tree); #define sgf_utils_can_undo(tree) \ ((tree)->undo_history && (tree)->undo_history->last_applied_entry) #define sgf_utils_can_redo(tree) \ ((tree)->undo_history \ && ((tree)->undo_history->last_applied_entry \ != (tree)->undo_history->last_entry)) void sgf_utils_undo (SgfGameTree *tree); void sgf_utils_redo (SgfGameTree *tree); /* `sgf-diff-utils.c' global functions. */ SgfCollection * sgf_diff (const SgfCollection *from_collection, const SgfCollection *to_collection); /* `sgf-tree-map.c' global declarations and functions. */ enum { SGF_NO_NODE, SGF_NON_CURRENT_BRANCH_NODE, SGF_CURRENT_BRANCH_HEAD_NODE, SGF_CURRENT_NODE, SGF_CURRENT_BRANCH_TAIL_NODE }; void sgf_game_tree_invalidate_map (SgfGameTree *tree, SgfNode *node); void sgf_game_tree_get_map_dimensions (SgfGameTree *tree, int *map_width, int *map_height); void sgf_game_tree_fill_map_view_port (SgfGameTree *tree, int view_port_x0, int view_port_y0, int view_port_x1, int view_port_y1, SgfNode ***view_port_nodes, SgfGameTreeMapLine **view_port_lines, int *num_view_port_lines); char * sgf_game_tree_get_current_branch_marks (SgfGameTree *tree, int view_port_x0, int view_port_y0, int view_port_x1, int view_port_y1); int sgf_game_tree_get_node_coordinates (SgfGameTree *tree, const SgfNode *node, int *node_x, int *node_y); int sgf_game_tree_node_is_within_view_port (SgfGameTree *tree, const SgfNode *node, int view_port_x0, int view_port_y0, int view_port_x1, int view_port_y1, int *node_x, int *node_y); #endif /* QUARRY_SGF_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/sgf/sgf-parser.h0000644000175000017500000001354410453261734015302 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef QUARRY_SGF_PARSER_H #define QUARRY_SGF_PARSER_H #include "sgf.h" #include "sgf-errors.h" #include "board.h" #include "utils.h" #include "quarry.h" #include #include #define MAX_TIMES_TO_REPORT_ERROR 10 typedef struct _SgfErrorPosition SgfErrorPosition; typedef struct _SgfParsingData SgfParsingData; struct _SgfErrorPosition { int line; int column; SgfErrorListItem *notch; }; struct _SgfParsingData { char *buffer; int buffer_size; int buffer_size_increment; const char *buffer_pointer; const char *buffer_end; char *temp_buffer; int buffer_refresh_margin; const char *buffer_refresh_point; int file_error; const int *cancellation_flag; int cancelled; const char *stored_buffer_pointers[3]; char token; iconv_t latin1_to_utf8; iconv_t tree_char_set_to_utf8; FILE *file; int file_bytes_remaining; int buffer_offset_in_file; int *bytes_parsed; int line; int column; int pending_column; int first_column; int in_parse_root; SgfErrorList *error_list; char times_error_reported[SGF_NUM_ERRORS]; int game; int game_type_expected; SgfError (* do_parse_move) (SgfParsingData *data); int board_width; int board_height; int use_board; Board *board; SgfNode *game_info_node; SgfGameTree *tree; SgfNode *node; SgfType property_type; SgfErrorPosition property_name_error_position; SgfErrorPosition move_error_position; SgfErrorPosition node_error_position; SgfErrorPosition ko_property_error_position; SgfErrorPosition non_sgf_point_error_position; char non_sgf_point_x; int non_sgf_point_y; int whitespace_passed; SgfErrorPosition whitespace_error_position; SgfErrorPosition zero_byte_error_position; unsigned int board_common_mark; unsigned int common_marked_positions[BOARD_GRID_SIZE]; int has_any_setup_property; char has_setup_add_properties[NUM_ON_GRID_VALUES]; int first_setup_add_property; unsigned int board_change_mark; unsigned int changed_positions[BOARD_GRID_SIZE]; int has_any_markup_property; char has_markup_properties[NUM_SGF_MARKUPS]; int first_markup_property; unsigned int board_markup_mark; unsigned int marked_positions[BOARD_GRID_SIZE]; int has_any_territory_property; char has_territory_properties[NUM_COLORS]; int first_territory_property; unsigned int board_territory_mark; unsigned int territory_positions[BOARD_GRID_SIZE]; }; #define DECLARE_VALUE_PARSER(name) \ SgfError name (SgfParsingData *data) DECLARE_VALUE_PARSER (sgf_parse_none); DECLARE_VALUE_PARSER (sgf_parse_real); DECLARE_VALUE_PARSER (sgf_parse_constrained_number); DECLARE_VALUE_PARSER (sgf_parse_double); DECLARE_VALUE_PARSER (sgf_parse_color); DECLARE_VALUE_PARSER (sgf_parse_simple_text); DECLARE_VALUE_PARSER (sgf_parse_text); DECLARE_VALUE_PARSER (sgf_parse_move); DECLARE_VALUE_PARSER (sgf_parse_list_of_point); DECLARE_VALUE_PARSER (sgf_parse_list_of_vector); DECLARE_VALUE_PARSER (sgf_parse_list_of_label); DECLARE_VALUE_PARSER (sgf_parse_application); DECLARE_VALUE_PARSER (sgf_parse_board_size); DECLARE_VALUE_PARSER (sgf_parse_char_set); DECLARE_VALUE_PARSER (sgf_parse_date); DECLARE_VALUE_PARSER (sgf_parse_figure); DECLARE_VALUE_PARSER (sgf_parse_file_format); DECLARE_VALUE_PARSER (sgf_parse_game_type); DECLARE_VALUE_PARSER (sgf_parse_handicap); DECLARE_VALUE_PARSER (sgf_parse_komi); DECLARE_VALUE_PARSER (sgf_parse_markup_property); DECLARE_VALUE_PARSER (sgf_parse_result); DECLARE_VALUE_PARSER (sgf_parse_setup_property); DECLARE_VALUE_PARSER (sgf_parse_style); DECLARE_VALUE_PARSER (sgf_parse_territory); DECLARE_VALUE_PARSER (sgf_parse_time_limit); DECLARE_VALUE_PARSER (sgf_parse_to_play); DECLARE_VALUE_PARSER (sgf_parse_letters); DECLARE_VALUE_PARSER (sgf_parse_simple_markup); /* Tree structure used by parse_properties() for very quick property * name lookup. */ extern const SgfType property_tree[][1 + ('Z' - 'A' + 1)]; /* List of errors the parser generates on incorrect input. */ extern const char *sgf_errors[]; #endif /* QUARRY_SGF_PARSER_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/sgf/sgf-privates.h0000644000175000017500000000620310453564141015633 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef QUARRY_SGF_PRIVATES_H #define QUARRY_SGF_PRIVATES_H #include "sgf.h" #include "sgf-properties.h" #include "sgf-parser.h" #include "sgf-writer.h" #include "sgf-errors.h" #include "quarry.h" #define COLLECTION_DO_NOTIFY(collection) \ do { \ if ((collection)->notification_callback) \ (collection)->notification_callback ((collection), \ (collection)->user_data); \ } while (0) #define GAME_TREE_DO_NOTIFY(tree, notification_code) \ do { \ if ((tree)->notification_callback) \ (tree)->notification_callback ((tree), (notification_code), \ (tree)->user_data); \ } while (0) #define UNDO_HISTORY_DO_NOTIFY(history) \ do { \ if ((history)->notification_callback) \ (history)->notification_callback ((history), \ (history)->user_data); \ } while (0) typedef struct _SgfPropertyInfo SgfPropertyInfo; struct _SgfPropertyInfo { #if !SGF_LONG_NAMES char name[4]; #else char *name; #endif SgfValueType value_type; SgfError (* value_parser) (SgfParsingData *data); void (* value_writer) (SgfWritingData *data, const SgfValue *value); }; /* Information about each property type. */ extern const SgfPropertyInfo property_info[]; /* Defined in `sgf-tree.c' and is only used from `sgf-utils.c'. */ void sgf_property_free_value (SgfValueType value_type, SgfValue *value); /* Defined in `sgf-utils.c', but also used from `sgf-undo.c'. */ inline void sgf_utils_do_switch_to_given_node (SgfGameTree *tree, SgfNode *node); void sgf_utils_descend_nodes (SgfGameTree *tree, int num_nodes); void sgf_utils_ascend_nodes (SgfGameTree *tree, int num_nodes); #endif /* QUARRY_SGF_PRIVATES_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/sgf/sgf-undo.h0000644000175000017500000001575110454171227014753 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef QUARRY_SGF_UNDO_H #define QUARRY_SGF_UNDO_H #include "sgf.h" #include "sgf-undo-operations.h" #include "quarry.h" typedef struct _SgfUndoOperationInfo SgfUndoOperationInfo; struct _SgfUndoOperationInfo { void (* undo) (SgfUndoHistoryEntry *entry, SgfGameTree *tree); void (* redo) (SgfUndoHistoryEntry *entry, SgfGameTree *tree); void (* free_data) (SgfUndoHistoryEntry *entry, int is_applied, SgfGameTree *tree); }; struct _SgfUndoHistoryEntry { SgfUndoHistoryEntry *next; SgfUndoHistoryEntry *previous; unsigned char operation_index; char is_last_in_action; char is_hidden; }; typedef struct _SgfNodeOperationEntry SgfNodeOperationEntry; typedef struct _SgfTwoNodesOperationEntry SgfTwoNodesOperationEntry; typedef struct _SgfChangeNodeInlinedColorOperationEntry SgfChangeNodeInlinedColorOperationEntry; typedef struct _SgfPropertyOperationEntry SgfPropertyOperationEntry; typedef struct _SgfChangePropertyOperationEntry SgfChangePropertyOperationEntry; typedef struct _SgfChangeRealPropertyOperationEntry SgfChangeRealPropertyOperationEntry; typedef struct _SgfCustomOperationEntry SgfCustomOperationEntry; struct _SgfNodeOperationEntry { SgfUndoHistoryEntry entry; SgfNode *node; SgfNode *parent_current_variation; }; struct _SgfTwoNodesOperationEntry { SgfUndoHistoryEntry entry; SgfNode *node1; SgfNode *node2; SgfNode *parent_current_variation; }; struct _SgfChangeNodeInlinedColorOperationEntry { SgfUndoHistoryEntry entry; SgfNode *node; int color; int side_effect; }; struct _SgfPropertyOperationEntry { SgfUndoHistoryEntry entry; SgfNode *node; SgfProperty *property; int side_effect; }; struct _SgfChangePropertyOperationEntry { SgfUndoHistoryEntry entry; SgfNode *node; SgfProperty *property; SgfValue value; int side_effect; }; struct _SgfChangeRealPropertyOperationEntry { SgfUndoHistoryEntry entry; SgfNode *node; SgfProperty *property; double value; int side_effect; }; struct _SgfCustomOperationEntry { SgfUndoHistoryEntry entry; const SgfCustomUndoHistoryEntryData *entry_data; void *user_data; SgfNode *node_to_switch_to; }; /* Undo operations. */ extern const SgfUndoOperationInfo sgf_undo_operations[]; #define DECLARE_UNDO_OR_REDO_FUNCTION(name) \ void name (SgfUndoHistoryEntry *entry, SgfGameTree *tree); #define DECLARE_FREE_DATA_FUNCTION(name) \ void name (SgfUndoHistoryEntry *entry, int is_applied, \ SgfGameTree *tree); /* Used both for node adding and removing undo/redo. */ DECLARE_UNDO_OR_REDO_FUNCTION (sgf_operation_add_node); DECLARE_UNDO_OR_REDO_FUNCTION (sgf_operation_delete_node); DECLARE_FREE_DATA_FUNCTION (sgf_operation_new_node_free_data); DECLARE_FREE_DATA_FUNCTION (sgf_operation_delete_node_free_data); DECLARE_UNDO_OR_REDO_FUNCTION (sgf_operation_delete_node_children_undo); DECLARE_UNDO_OR_REDO_FUNCTION (sgf_operation_delete_node_children_redo); DECLARE_FREE_DATA_FUNCTION (sgf_operation_delete_node_children_free_data); /* Used both for node adding and removing undo/redo. */ DECLARE_UNDO_OR_REDO_FUNCTION (sgf_operation_swap_nodes_do_swap); DECLARE_UNDO_OR_REDO_FUNCTION (sgf_operation_change_node_move_color_do_change); DECLARE_UNDO_OR_REDO_FUNCTION (sgf_operation_change_node_to_play_color_do_change); /* Used both for node adding and removing undo/redo. */ DECLARE_UNDO_OR_REDO_FUNCTION (sgf_operation_add_property); DECLARE_UNDO_OR_REDO_FUNCTION (sgf_operation_delete_property); DECLARE_FREE_DATA_FUNCTION (sgf_operation_new_property_free_data); DECLARE_FREE_DATA_FUNCTION (sgf_operation_delete_property_free_data); /* Used as both undo and redo handler. */ DECLARE_UNDO_OR_REDO_FUNCTION (sgf_operation_change_property_do_change); DECLARE_FREE_DATA_FUNCTION (sgf_operation_change_property_free_data); #if SGF_REAL_VALUES_ALLOCATED_SEPARATELY /* Used as both undo and redo handler. */ DECLARE_UNDO_OR_REDO_FUNCTION (sgf_operation_change_real_property_do_change); #endif DECLARE_UNDO_OR_REDO_FUNCTION (sgf_operation_custom_undo); DECLARE_UNDO_OR_REDO_FUNCTION (sgf_operation_custom_redo); DECLARE_FREE_DATA_FUNCTION (sgf_operation_custom_free_data); void sgf_utils_apply_undo_history_entry (SgfGameTree *tree, SgfUndoHistoryEntry *entry); SgfUndoHistoryEntry * sgf_new_node_undo_history_entry_new (SgfNode *new_node); SgfUndoHistoryEntry * sgf_delete_node_undo_history_entry_new (SgfNode *node); SgfUndoHistoryEntry * sgf_delete_node_children_undo_history_entry_new (SgfNode *node); SgfUndoHistoryEntry * sgf_swap_nodes_undo_history_entry_new (SgfNode *node1, SgfNode *node2); SgfUndoHistoryEntry * sgf_change_node_inlined_color_undo_history_entry_new (SgfNode *node, SgfUndoOperation operation, int new_color, int side_effect); SgfUndoHistoryEntry * sgf_new_property_undo_history_entry_new (SgfGameTree *tree, SgfNode *node, SgfProperty **link, SgfType type, int side_effect); SgfUndoHistoryEntry * sgf_delete_property_undo_history_entry_new (SgfNode *node, SgfProperty *property, int side_effect); SgfUndoHistoryEntry * sgf_change_property_undo_history_entry_new (SgfNode *node, SgfProperty *property, int side_effect); SgfUndoHistoryEntry * sgf_change_real_property_undo_history_entry_new (SgfNode *node, SgfProperty *property, double new_value, int side_effect); SgfUndoHistoryEntry * sgf_custom_undo_history_entry_new (const SgfCustomUndoHistoryEntryData *entry_data, void *user_data, SgfNode *node_to_switch_to); #endif /* QUARRY_SGF_UNDO_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/sgf/sgf-writer.h0000644000175000017500000000511210453564000015302 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef QUARRY_SGF_WRITER_H #define QUARRY_SGF_WRITER_H #include "sgf.h" #include "utils.h" #include "quarry.h" #include #include #define FILL_COLUMN 72 #define FILL_BREAK_POINT (FILL_COLUMN - 15) typedef struct _SgfWritingData SgfWritingData; struct _SgfWritingData { BufferedWriter writer; SgfGameTree *tree; iconv_t utf8_to_tree_encoding; void (* do_write_move) (SgfWritingData *data, const SgfNode *node); }; #define DECLARE_VALUE_WRITER(name) \ void name (SgfWritingData *data, const SgfValue *value) DECLARE_VALUE_WRITER (sgf_write_none); DECLARE_VALUE_WRITER (sgf_write_number); DECLARE_VALUE_WRITER (sgf_write_real); DECLARE_VALUE_WRITER (sgf_write_double); DECLARE_VALUE_WRITER (sgf_write_color); DECLARE_VALUE_WRITER (sgf_write_simple_text); DECLARE_VALUE_WRITER (sgf_write_fake_simple_text); DECLARE_VALUE_WRITER (sgf_write_text); DECLARE_VALUE_WRITER (sgf_write_list_of_point); DECLARE_VALUE_WRITER (sgf_write_list_of_vector); DECLARE_VALUE_WRITER (sgf_write_list_of_label); DECLARE_VALUE_WRITER (sgf_write_figure_description); DECLARE_VALUE_WRITER (sgf_write_unknown); #endif /* QUARRY_SGF_WRITER_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/sgf/sgf-errors.list0000644000175000017500000002042210367243257016043 0ustar bartbart# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # This file is part of Quarry # # # # Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. # # # # 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 2 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, write to the Free # # Software Foundation, Inc., 51 Franklin Street, Fifth Floor, # # Boston, MA 02110-1301, USA. # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # @mode errors @c_include "quarry.h" @c_include errors SgfError sgf_errors { SGF_CRITICAL_UNEXPECTED_END_OF_FILE "critical: unexpected end of file, information may be lost " "(proceeded with read data)" SGF_FATAL_INVALID_VALUE "error: property `%N' with invalid value [%V] (deleted)" SGF_FATAL_INVALID_GAME_TYPE "error: invalid game type [%V] (deleted; assuming Go, GM[1])" SGF_FATAL_MOVE_OUT_OF_BOARD "error: move in `%N' property value is out of board (property deleted)" + SGF_FIRST_PROPERTY_NAME_ERROR SGF_FATAL_EMPTY_VALUE "error: property `%N' with empty value (deleted)" SGF_FATAL_DUPLICATE_PROPERTY "error: duplicate property `%N' (deleted)" SGF_FATAL_NEGATIVE_TIME_LIMIT "error: negative value of time limit (`TM') property (property deleted)" SGF_FAIL NULL = SGF_LAST_FATAL_ERROR SGF_CRITICAL_FUTURE_FILE_FORMAT "critical: future SGF version, FF[%d] - be careful when saving (reading on)" SGF_ERROR_MISPLACED_GAME_INFO_PROPERTY "error: game-info property `%N' outside game-info node (deleted)" SGF_ERROR_INVALID_GAME_INFO_PROPERTY "error: game-info property `%N' with invalid value [%V] (preserved)" SGF_ERROR_MISPLACED_ROOT_PROPERTY "error: root property `%N' outside root node (deleted)" SGF_ERROR_WRONG_GAME "error: %s-specific property `%N' in %s game tree (deleted)" SGF_WARNING_PROPERTY_WITH_EMPTY_VALUE "warning: property `%N' with empty value (deleted)" SGF_WARNING_PROPERTIES_MERGED "warning: duplicate property `%N' (values merged)" SGF_WARNING_UNKNOWN_PROPERTIES_MERGED "warning: duplicate unknown property `%s' " "(assuming list type; values merged)" SGF_ERROR_ANOTHER_MOVE "error: move property `%N' in a node already having a move (split node)" = SGF_LAST_PROPERTY_NAME_ERROR SGF_ERROR_MIXED_SETUP_ADD_AND_MOVE_PROPERTIES "error: setup and move properties mixed in one node (split node)" SGF_ERROR_MIXED_PL_AND_MOVE_PROPERTIES "error: setup and move properties mixed in one node (deleted `PL' property)" SGF_ERROR_SENSELESS_MOVE "error: move %M is senseless: no piece of appropriate color at %P (deleted)" SGF_ERROR_KO_PROPERTY_WITHOUT_MOVE "error: `KO' property in a node without a move (deleted)" SGF_WARNING_NON_SGF_POINT_NOTATION "warning: non-SGF point notation `%c%d' " "(parsed anyway; note: this warning is reported once only)" SGF_ERROR_EMPTY_VARIATION "error: variation without nodes (deleted)" SGF_WARNING_EMPTY_VALUE "warning: empty value of property `%N' (value ignored)" SGF_ERROR_NON_EMPTY_VALUE "error: value [%V] of property `%N' is not empty as it should be " "(value deleted)" SGF_ERROR_MULTIPLE_VALUES "error: property `%N' cannot have a list of values " "(all values but first deleted)" SGF_WARNING_VALUES_MERGED "warning: property `%N' cannot have a list of values (values merged)" SGF_ERROR_INVALID_VALUE "error: invalid value [%V] of property `%N' (value deleted)" SGF_WARNING_COMPOSED_SIMPLE_TEXT_EXPECTED "warning: composed simple text value expected (assuming empty second part)" SGF_ERROR_INVALID_DOUBLE_VALUE "error: property `%N' with invalid value [%V], while expected [1] or [2] " "(assuming [1])" SGF_WARNING_LOWER_CASE_COLOR "warning: lower-case color `%c' in property `%N' (upcased to `%c')" SGF_WARNING_INTEGER_PART_SUPPLIED "warning: missed integral part of floating-point number in value " "of property `%N' (zero supplied)" SGF_WARNING_FRACTIONAL_PART_SUPPLIED "warning: missed fractional part of floating-point number in value " "of property `%N' (zero supplied)" SGF_ERROR_TOO_LARGE_ABSOLUTE_VALUE "error: too large (by absolute value) floating-point number in value " " of property `%N' (replaced with something huge)" SGF_ERROR_POINT_OUT_OF_BOARD "error: point in `%N' property value is out of board (value deleted)" SGF_ERROR_INVALID_CORNERS "error: rectangle corners specified in value of property `%N' " "are not upper left and lower right ones (fixed)" SGF_WARNING_POINT_AS_RECTANGLE "warning: rectangle specified in value of property `%N' is single point " "(second corner ignored)" SGF_ERROR_VALUES_AFTER_EMPTY_LIST "error: more values after empty list value [] in property `%N' (deleted)" SGF_WARNING_SETUP_HAS_NO_EFFECT "warning: point %P in `%N' setup property value doesn't change the board " "(value ignored)" SGF_WARNING_DUPLICATE_POINT "warning: point %P was already listed in another `%N' property value " "(ignored)" SGF_ERROR_DUPLICATE_SETUP "error: point %P (in `%N' property value) was already listed " "in another setup property (deleted)" SGF_ERROR_DUPLICATE_MARKUP "error: point %P (in `%N' property value) was already listed " "in another markup property (deleted)" SGF_ERROR_DUPLICATE_TERRITORY "error: point %P (in `%N' property value) was already listed " "in another territory property (deleted)" SGF_WARNING_DUPLICATE_VECTOR "warning: vector/line %P:%P was already listed in another `%N' " "property value (ignored)" SGF_ERROR_ZERO_LENGTH_VECTOR "error: vector/line %P:%P has zero length (deleted)" SGF_ERROR_DUPLICATE_LABEL "error: point %P already has a label (value deleted)" SGF_WARNING_EMPTY_LABEL "warning: empty label at point %P (ignored)" SGF_ERROR_TOO_LARGE_BOARD "error: board of size %dx%d is too large per SGF standard (assuming %dx%d)" SGF_WARNING_SAME_WIDTH_AND_HEIGHT "warning: board is specified as rectangular, but with equal width and height " "(height ignored)" SGF_WARNING_UNKNOWN_GAME "warning: unknown game type [%d], presumably new in SGF standard " "(only general properties will be validated)" SGF_WARNING_UNSUPPORTED_GAME "warning: unsupported game: %s, GM[%d] " "(only general properties will be validated)" SGF_ERROR_INVALID_HANDICAP "error: handicap cannot be negative or equal to 1 (assuming 0)" SGF_WARNING_HANDICAP_REDUCED "warning: handicap larger than the number of board vertices " "(reduced to %d)" SGF_WARNING_UNKNOWN_FLAGS "warning: flags not listed in SGF specification used in `%N' property value " "(unknown flags kept)" SGF_ERROR_FIGURE_FLAGS_EXPECTED "error: flags expected in the value of property `FG' " "(default flags supplied)" SGF_WARNING_UNKNOWN_PRINT_MODE "warning: unknown print mode %d not listed in SGF specification " "(kept anyway)" SGF_WARNING_ZERO_BYTE "warning: zero byte encountered " "(ignored; note: this warning is reported once only)" SGF_WARNING_ILLEGAL_WHITESPACE "warning: whitespace in value of non-text property `%N' (ignored)" SGF_ERROR_ILLEGAL_TRAILING_CHARACTERS "error: illegal trailing character(s) [...%V] in value of property `%N' " "(deleted)" SGF_ERROR_ILLEGAL_TRAILING_CHARACTERS_BEFORE_COLON "error: illegal trailing character(s) [...%V:...] in first part " "of composed value of property `%N' (deleted)" SGF_WARNING_ERROR_SUPPRESSED "warning: the above error is reported too frequently (suppressed)" = SGF_NUM_ERRORS = SGF_SUCCESS } quarry-0.2.0/src/sgf/sgf-properties.list0000644000175000017500000001666410371160241016722 0ustar bartbart# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # This file is part of Quarry # # # # Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. # # # # 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 2 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, write to the Free # # Software Foundation, Inc., 51 Franklin Street, Fifth Floor, # # Boston, MA 02110-1301, USA. # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # @mode properties @c_include "sgf-privates.h" @c_include "sgf-parser.h" @c_include "sgf-writer.h" @define_condition SGF_REAL_VALUES_ALLOCATED_SEPARATELY value_types SgfValueType - { #> Value types. none SGF_NONE sgf_write_none number SGF_NUMBER sgf_write_number double SGF_DOUBLE sgf_write_double color SGF_COLOR sgf_write_color @if SGF_REAL_VALUES_ALLOCATED_SEPARATELY + SGF_FIRST_MALLOC_TYPE real SGF_REAL sgf_write_real @else real SGF_REAL sgf_write_real + SGF_FIRST_MALLOC_TYPE @endif simple_text SGF_SIMPLE_TEXT sgf_write_simple_text fake_simple_text SGF_FAKE_SIMPLE_TEXT sgf_write_fake_simple_text text SGF_TEXT sgf_write_text list_of_point SGF_LIST_OF_POINT sgf_write_list_of_point elist_of_point SGF_ELIST_OF_POINT sgf_write_list_of_point list_of_vector SGF_LIST_OF_VECTOR sgf_write_list_of_vector list_of_label SGF_LIST_OF_LABEL sgf_write_list_of_label figure_description SGF_FIGURE_DESCRIPTION sgf_write_figure_description unknown SGF_TYPE_UNKNOWN sgf_write_unknown = SGF_LAST_MALLOC_TYPE #> Special value "type" for properties which are not stored. not_stored SGF_NOT_STORED NULL } properties SgfType property_info { #> Root properties. + SGF_FIRST_ROOT_PROPERTY FF SGF_FILE_FORMAT not_stored sgf_parse_file_format GM SGF_GAME_TYPE not_stored sgf_parse_game_type CA SGF_CHAR_SET not_stored sgf_parse_char_set ST SGF_STYLE not_stored sgf_parse_style AP SGF_APPLICATION not_stored sgf_parse_application SZ SGF_BOARD_SIZE not_stored sgf_parse_board_size = SGF_LAST_ROOT_PROPERTY #> Game information properties. + SGF_FIRST_GAME_INFO_PROPERTY # Note that all values are stored as `simple_text', because SGF # specification requires us to preserve incorrectly formatted # game-info properties. GN SGF_GAME_NAME simple_text sgf_parse_simple_text EV SGF_EVENT simple_text sgf_parse_simple_text RO SGF_ROUND simple_text sgf_parse_simple_text PC SGF_PLACE simple_text sgf_parse_simple_text DT SGF_DATE simple_text sgf_parse_date RU SGF_RULE_SET simple_text sgf_parse_simple_text #> `HA' and `KM' are specific to Go. HA SGF_HANDICAP fake_simple_text sgf_parse_handicap KM SGF_KOMI fake_simple_text sgf_parse_komi TM SGF_TIME_LIMIT fake_simple_text sgf_parse_time_limit OT SGF_OVERTIME simple_text sgf_parse_simple_text PB SGF_PLAYER_BLACK simple_text sgf_parse_simple_text BT SGF_BLACK_TEAM simple_text sgf_parse_simple_text BR SGF_BLACK_RANK simple_text sgf_parse_simple_text PW SGF_PLAYER_WHITE simple_text sgf_parse_simple_text WT SGF_WHITE_TEAM simple_text sgf_parse_simple_text WR SGF_WHITE_RANK simple_text sgf_parse_simple_text AN SGF_ANNOTATOR simple_text sgf_parse_simple_text CP SGF_COPYRIGHT simple_text sgf_parse_simple_text SO SGF_SOURCE simple_text sgf_parse_simple_text US SGF_USER simple_text sgf_parse_simple_text ON SGF_OPENING simple_text sgf_parse_simple_text GC SGF_GAME_COMMENT text sgf_parse_text RE SGF_RESULT simple_text sgf_parse_result = SGF_LAST_GAME_INFO_PROPERTY #> Setup properties. + SGF_FIRST_SETUP_PROPERTY AB SGF_ADD_BLACK list_of_point sgf_parse_setup_property AW SGF_ADD_WHITE list_of_point sgf_parse_setup_property AE SGF_ADD_EMPTY list_of_point sgf_parse_setup_property # `AA' is specific to Amazons. AA SGF_ADD_ARROWS list_of_point sgf_parse_setup_property PL SGF_TO_PLAY not_stored sgf_parse_to_play = SGF_LAST_SETUP_PROPERTY #> Move properties. B SGF_BLACK not_stored sgf_parse_move W SGF_WHITE not_stored sgf_parse_move KO SGF_KO none sgf_parse_none MN SGF_MOVE_NUMBER number sgf_parse_constrained_number #> Node annotation properties. N SGF_NODE_NAME simple_text sgf_parse_simple_text C SGF_COMMENT text sgf_parse_text HO SGF_HOTSPOT double sgf_parse_double UC SGF_UNCLEAR double sgf_parse_double V SGF_VALUE real sgf_parse_real GB SGF_GOOD_4BLACK double sgf_parse_double DM SGF_DAME double sgf_parse_double GW SGF_GOOD_4WHITE double sgf_parse_double #> Move annotation properties. BM SGF_BAD_MOVE double sgf_parse_double DO SGF_DOUBTFUL none sgf_parse_none IT SGF_INTERESTING none sgf_parse_none TE SGF_TESUJI double sgf_parse_double #> Timing properties. BL SGF_TIME_LEFT_FOR_BLACK real sgf_parse_real OB SGF_MOVES_LEFT_FOR_BLACK number sgf_parse_constrained_number WL SGF_TIME_LEFT_FOR_WHITE real sgf_parse_real OW SGF_MOVES_LEFT_FOR_WHITE number sgf_parse_constrained_number #> Markup properties. MA SGF_MARK list_of_point sgf_parse_markup_property CR SGF_CIRCLE list_of_point sgf_parse_markup_property SQ SGF_SQUARE list_of_point sgf_parse_markup_property TR SGF_TRIANGLE list_of_point sgf_parse_markup_property SL SGF_SELECTED list_of_point sgf_parse_markup_property LB SGF_LABEL list_of_label sgf_parse_list_of_label #> `TB' and `TW' are Go-specific. TB SGF_BLACK_TERRITORY list_of_point sgf_parse_territory TW SGF_WHITE_TERRITORY list_of_point sgf_parse_territory AR SGF_ARROW list_of_vector sgf_parse_list_of_vector LN SGF_LINE list_of_vector sgf_parse_list_of_vector DD SGF_DIMMED elist_of_point sgf_parse_list_of_point #> Miscellaneous properties. FG SGF_FIGURE figure_description sgf_parse_figure PM SGF_PRINT_MODE number sgf_parse_constrained_number VW SGF_VIEW_PORT elist_of_point sgf_parse_list_of_point #> Custom extension properties we support. IL SGF_ILLEGAL_MOVE list_of_point sgf_parse_list_of_point ##> Outdated properties (FF[1] - FF[3]). #EL SGF_EVALUATED not_stored #EX SGF_EXPECTED not_stored #ID SGF_IDENTIFIER not_stored #L SGF_LETTERS not_stored sgf_parse_letters #M SGF_SIMPLE_MARKUP not_stored sgf_parse_simple_markup #OM SGF_MOVES_OVERTIME not_stored #OP SGF_OVERTIME_LENGTH not_stored #OV SGF_OPERATOR_OVERHEAD not_stored #RG SGF_REGION not_stored #SC SGF_SECURE_STONES not_stored #> The number of known properties. + SGF_KNOWN_PROPERTIES #> Any property we don't know about (e.g. a custom extension). - SGF_UNKNOWN unknown NULL #> Total number of all properties (known and unknown). + SGF_NUM_PROPERTIES unknown SGF_UNKNOWN total SGF_NUM_PROPERTIES } quarry-0.2.0/src/sgf/sgf-undo-operations.list0000644000175000017500000000572410444571725017665 0ustar bartbart# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # This file is part of Quarry # # # # Copyright (C) 2005, 2006 Paul Pogonyshev. # # # # 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 2 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, write to the Free # # Software Foundation, Inc., 51 Franklin Street, Fifth Floor, # # Boston, MA 02110-1301, USA. # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # @mode undo_operations @c_include "sgf-undo.h" operations SgfUndoOperation sgf_undo_operations { SGF_OPERATION_NEW_NODE sgf_operation_delete_node sgf_operation_add_node sgf_operation_new_node_free_data SGF_OPERATION_DELETE_NODE sgf_operation_add_node sgf_operation_delete_node sgf_operation_delete_node_free_data SGF_OPERATION_DELETE_NODE_CHILDREN sgf_operation_delete_node_children_undo sgf_operation_delete_node_children_redo sgf_operation_delete_node_children_free_data SGF_OPERATION_SWAP_NODES sgf_operation_swap_nodes_do_swap sgf_operation_swap_nodes_do_swap NULL SGF_OPERATION_CHANGE_NODE_MOVE_COLOR sgf_operation_change_node_move_color_do_change sgf_operation_change_node_move_color_do_change NULL SGF_OPERATION_CHANGE_NODE_TO_PLAY_COLOR sgf_operation_change_node_to_play_color_do_change sgf_operation_change_node_to_play_color_do_change NULL SGF_OPERATION_NEW_PROPERTY sgf_operation_delete_property sgf_operation_add_property sgf_operation_new_property_free_data SGF_OPERATION_DELETE_PROPERTY sgf_operation_add_property sgf_operation_delete_property sgf_operation_delete_property_free_data SGF_OPERATION_CHANGE_PROPERTY sgf_operation_change_property_do_change sgf_operation_change_property_do_change sgf_operation_change_property_free_data @if SGF_REAL_VALUES_ALLOCATED_SEPARATELY SGF_OPERATION_CHANGE_REAL_PROPERTY sgf_operation_change_real_property_do_change sgf_operation_change_real_property_do_change NULL @endif SGF_OPERATION_CUSTOM sgf_operation_custom_undo sgf_operation_custom_redo sgf_operation_custom_free_data + SGF_NUM_OPERATIONS } quarry-0.2.0/src/sgf/parse-sgf-list.c0000644000175000017500000002725610367243224016067 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "parse-list.h" #include "utils.h" #include #include #include /* True for current 32-bit platforms. The reason for this is that * real properties are very rare and we don't want to waste space in * `SgfValue' just because `double' has larger size than the other * value types. * * Floats have so low precision, that there will be problems with * storing fractional number of seconds in it. So we have to use * doubles. */ #define SGF_REAL_VALUES_ALLOCATED_SEPARATELY \ (SIZEOF_DOUBLE > SIZEOF_INT && SIZEOF_DOUBLE > SIZEOF_VOID_P) typedef struct _ValueTypeListItem ValueTypeListItem; typedef struct _ValueTypeList ValueTypeList; struct _ValueTypeListItem { ValueTypeListItem *next; char *infile_name; const char *c_name; const char *value_writer_function; }; struct _ValueTypeList { ValueTypeListItem *first; ValueTypeListItem *last; int item_size; StringListItemDispose item_dispose; }; #define value_type_list_new() \ string_list_new_derived (sizeof (ValueTypeListItem), NULL) #define value_type_list_init(list) \ string_list_init_derived ((list), sizeof (ValueTypeListItem), NULL) #define STATIC_VALUE_TYPE_LIST \ STATIC_STRING_LIST_DERIVED (ValueTypeListItem, NULL) #define value_type_list_get_item(list, item_index) \ ((ValueTypeListItem *) string_list_get_item ((list), (item_index))) #define value_type_list_find(list, infile_name) \ ((ValueTypeListItem *) string_list_find ((list), (infile_name))) #define value_type_list_find_after_notch(list, infile_name, notch) \ ((ValueTypeListItem *) \ string_list_find_after_notch ((list), (infile_name), (notch))) typedef struct _TreeNode TreeNode; struct _TreeNode { int index; char *identifiers[1 + ('Z' - 'A')]; TreeNode *children[1 + ('Z' - 'A')]; }; static int value_type_list_parse_type1 (char **line); static int value_type_list_parse_type2 (StringBuffer *c_file_arrays, char **line, const char *identifier, char **pending_eol_comment, int *pending_linefeeds); static int property_list_parse_type1 (char **line); static int property_list_parse_type2 (StringBuffer *c_file_arrays, char **line, const char *identifier, char **pending_eol_comment, int *pending_linefeeds); static int property_list_finalize (StringBuffer *c_file_arrays); static int error_list_parse_error2 (StringBuffer *c_file_arrays, char **line, const char *identifier, char **pending_eol_comment, int *pending_linefeeds); static int undo_operation_list_parse_undo_operation2 (StringBuffer *c_file_arrays, char **line, const char *identifier, char **pending_eol_comment, int *pending_linefeeds); static void enumerate_nodes (TreeNode *node); static void print_nodes (const TreeNode *node, const char *identifier); static void delete_nodes (TreeNode *node); static const ListDescription properties_lists[] = { { "value_types", 0, SORT_NORMAL, 1, NULL, NULL, value_type_list_parse_type1, value_type_list_parse_type2, NULL }, { "properties", 0, SORT_NORMAL, 1, "const SgfPropertyInfo ", NULL, property_list_parse_type1, property_list_parse_type2, property_list_finalize }, { NULL, 0, SORT_NORMAL, 0, NULL, NULL, NULL, NULL, NULL } }; static const ListDescription errors_list[] = { { "errors", 0, SORT_NORMAL, 0, "const char *", NULL, NULL, error_list_parse_error2, NULL }, { NULL, 0, SORT_NORMAL, 0, NULL, NULL, NULL, NULL, NULL } }; static const ListDescription undo_operations_list[] = { { "operations", 0, SORT_NORMAL, 1, "const SgfUndoOperationInfo ", NULL, NULL, undo_operation_list_parse_undo_operation2, NULL }, { NULL, 0, SORT_NORMAL, 0, NULL, NULL, NULL, NULL, NULL } }; static const ListDescriptionSet list_sets[] = { { "properties", properties_lists }, { "errors", errors_list }, { "undo_operations", undo_operations_list } }; static const PredefinedCondition conditions[] = { { "SGF_REAL_VALUES_ALLOCATED_SEPARATELY", SGF_REAL_VALUES_ALLOCATED_SEPARATELY }, { NULL, 0 } }; static ValueTypeList value_types = STATIC_VALUE_TYPE_LIST; static const char *property_id; static const char *total; static const char *unknown; static int long_names = 0; static TreeNode *root = NULL; int main (int argc, char *argv[]) { int result; result = parse_list_main (argc, argv, list_sets, sizeof list_sets / sizeof (ListDescriptionSet), conditions); string_list_empty (&value_types); return result; } static int value_type_list_parse_type1 (char **line) { const char *infile_name; PARSE_IDENTIFIER (infile_name, line, "value type"); string_list_add (&value_types, infile_name); return 0; } static int value_type_list_parse_type2 (StringBuffer *c_file_arrays, char **line, const char *identifier, char **pending_eol_comment, int *pending_linefeeds) { UNUSED (c_file_arrays); UNUSED (pending_eol_comment); UNUSED (pending_linefeeds); value_types.last->c_name = identifier; PARSE_IDENTIFIER (value_types.last->value_writer_function, line, "writer function"); return 0; } static int property_list_parse_type1 (char **line) { if (looking_at ("unknown", line)) { PARSE_IDENTIFIER (unknown, line, "`unknown' identifier"); *line = NULL; } else if (looking_at ("total", line)) { PARSE_IDENTIFIER (total, line, "`total' identifier"); *line = NULL; } else { if (looking_at ("-", line)) { static const char null_string[] = ""; property_id = null_string; } else PARSE_THING (property_id, PROPERTY_IDENTIFIER, line, "property id"); if (strlen (property_id) > 2) { print_error ("warning: strangely long property name `%s'", property_id); if (strlen (property_id) > 3) long_names = 1; } } return 0; } static int property_list_parse_type2 (StringBuffer *c_file_arrays, char **line, const char *identifier, char **pending_eol_comment, int *pending_linefeeds) { const char *infile_value_type; const char *parser_function; ValueTypeListItem *value_type; TreeNode *node; UNUSED (pending_linefeeds); PARSE_IDENTIFIER (infile_value_type, line, "value type"); value_type = value_type_list_find (&value_types, infile_value_type); if (!value_type) { print_error ("unknown property value type `%s'", infile_value_type); return 1; } PARSE_IDENTIFIER (parser_function, line, "parser function"); *pending_eol_comment = utils_duplicate_string (property_id); string_buffer_cprintf (c_file_arrays, " { \"%s\", %s, %s, %s }", property_id, value_type->c_name, parser_function, value_type->value_writer_function); if (*property_id) { const char *pointer; if (!root) root = (TreeNode *) utils_malloc0 (sizeof (TreeNode)); for (pointer = property_id, node = root; *(pointer + 1); pointer++) { TreeNode **child = &node->children[*pointer - 'A']; if (! *child) *child = (TreeNode *) utils_malloc0 (sizeof (TreeNode)); node = *child; } if (node->identifiers[*pointer - 'A']) { print_error ("duplicated property `%s'", property_id); return 1; } node->identifiers[*pointer - 'A'] = utils_duplicate_string (identifier); } return 0; } static int property_list_finalize (StringBuffer *c_file_arrays) { UNUSED (c_file_arrays); if (! *total) { print_error ("`total' identifier missed"); return 1; } if (! *unknown) { print_error ("`unknown' identifier missed"); return 1; } string_buffer_cprintf (&h_file_bottom, "\n\n#define SGF_LONG_NAMES\t\t%d\n", long_names); enumerate_nodes (root); string_buffer_cat_string (&c_file_bottom, ("\nconst SgfType" " property_tree[][1 + ('Z' - 'A' + 1)] = {")); print_nodes (root, NULL); string_buffer_cat_string (&c_file_bottom, "\n }\n};\n"); delete_nodes (root); return 0; } static void enumerate_nodes (TreeNode *node) { static int node_index = 0; int k; node->index = node_index++; for (k = 0; k < 'Z' - 'A' + 1; k++) { if (node->children[k]) enumerate_nodes (node->children[k]); } } static void print_nodes (const TreeNode *node, const char *identifier) { int k; if (node->index) string_buffer_cat_string (&c_file_bottom, "\n },"); string_buffer_cat_strings (&c_file_bottom, "\n {\n ", identifier ? identifier : unknown, NULL); for (k = 0; k < 'Z' - 'A' + 1; k++) { if (node->children[k]) { string_buffer_cprintf (&c_file_bottom, ",\n %s + %d", total, node->children[k]->index); } else { string_buffer_cat_strings (&c_file_bottom, ",\n ", (node->identifiers[k] ? node->identifiers[k] : unknown), NULL); } } for (k = 0; k < 'Z' - 'A' + 1; k++) { if (node->children[k]) print_nodes (node->children[k], node->identifiers[k]); } } static void delete_nodes (TreeNode *node) { int k; for (k = 0; k < 'Z' - 'A' + 1; k++) { if (node->identifiers[k]) utils_free (node->identifiers[k]); if (node->children[k]) delete_nodes (node->children[k]); } utils_free (node); } static int error_list_parse_error2 (StringBuffer *c_file_arrays, char **line, const char *identifier, char **pending_eol_comment, int *pending_linefeeds) { char *string; UNUSED (identifier); UNUSED (pending_eol_comment); string = parse_multiline_string (line, "error string or NULL", "\n ", 1); if (!string) return 1; string_buffer_cat_strings (c_file_arrays, " ", string, NULL); utils_free (string); *pending_linefeeds = -1; return 0; } static int undo_operation_list_parse_undo_operation2 (StringBuffer *c_file_arrays, char **line, const char *identifier, char **pending_eol_comment, int *pending_linefeeds) { const char *undo_function; const char *redo_function; const char *free_data_function; UNUSED (identifier); UNUSED (pending_eol_comment); UNUSED (pending_linefeeds); PARSE_IDENTIFIER (undo_function, line, "undo function"); PARSE_IDENTIFIER (redo_function, line, "redo function"); PARSE_IDENTIFIER (free_data_function, line, "free data function"); string_buffer_cprintf (c_file_arrays, " { %s,\n %s,\n %s }", undo_function, redo_function, free_data_function); return 0; } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/sgf/sgf-diff.c0000644000175000017500000000521710367243236014710 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "sgf.h" #include "utils.h" #include #include int main (int argc, char *argv[]) { int result = 0; SgfErrorList *error_list; utils_remember_program_name (argv[0]); if (argc == 3) { SgfCollection *first_collection; SgfCollection *second_collection; SgfCollection *difference; if (sgf_parse_file (argv[1], &first_collection, &error_list, &sgf_parser_defaults, NULL, NULL, NULL) != SGF_PARSED) assert (0); if (error_list) string_list_delete (error_list); if (sgf_parse_file (argv[2], &second_collection, &error_list, &sgf_parser_defaults, NULL, NULL, NULL) != SGF_PARSED) assert (0); if (error_list) string_list_delete (error_list); difference = sgf_diff (first_collection, second_collection); sgf_collection_delete (first_collection); sgf_collection_delete (second_collection); if (difference) { sgf_write_file (NULL, difference, 1); sgf_collection_delete (difference); } } else { fprintf (stderr, "Usage: %s FROM-FILE TO-FILE\n", argv[0]); result = 255; } utils_free_program_name_strings (); #if ENABLE_MEMORY_PROFILING utils_print_memory_profiling_info (); #endif return result; } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/sgf/sgf-test.c0000644000175000017500000000535010367243360014753 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "sgf.h" #include "utils.h" #include int main (int argc, char *argv[]) { int k; int result = 0; SgfCollection *collection; SgfErrorList *error_list; utils_remember_program_name (argv[0]); if (argc > 1) { for (k = 1; k < argc; k++) { switch (sgf_parse_file (argv[k], &collection, &error_list, &sgf_parser_defaults, NULL, NULL, NULL)) { case SGF_PARSED: if (error_list) { SgfErrorListItem *item; printf ("%s:\n", argv[k]); for (item = error_list->first; item; item = item->next) printf ("%d(%d): %s\n", item->line, item->column, item->text); string_list_delete (error_list); putchar ('\n'); result = 1; } #if 0 else printf ("File `%s' parsed without errors\n\n", argv[k]); #endif #if 0 sgf_write_file (NULL, collection); #endif sgf_collection_delete (collection); break; case SGF_ERROR_READING_FILE: printf ("Error reading file `%s'\n\n", argv[k]); result = 1; break; case SGF_INVALID_FILE: printf ("File `%s' doesn't seem to be an SGF file\n\n", argv[k]); result = 1; break; } } } else { fprintf (stderr, "Usage: %s INFILE ...\n", argv[0]); result = 255; } utils_free_program_name_strings (); #if ENABLE_MEMORY_PROFILING utils_print_memory_profiling_info (); #endif return result; } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gtp/0000755000175000017500000000000010530402570013053 5ustar bartbartquarry-0.2.0/src/gtp/Makefile.in0000644000175000017500000003230610425150133015122 0ustar bartbart# Makefile.in generated by automake 1.7.9 from Makefile.am. # @configure_input@ # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 # Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # Process this file with Automake to produce `Makefile.in'. srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = ../.. am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : host_triplet = @host@ ACLOCAL = @ACLOCAL@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BUILD_SGF_UTILS_FALSE = @BUILD_SGF_UTILS_FALSE@ BUILD_SGF_UTILS_TRUE = @BUILD_SGF_UTILS_TRUE@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DO_SCROLLKEEPER_UPDATE_FALSE = @DO_SCROLLKEEPER_UPDATE_FALSE@ DO_SCROLLKEEPER_UPDATE_TRUE = @DO_SCROLLKEEPER_UPDATE_TRUE@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ GMSGFMT = @GMSGFMT@ HAVE_SCROLLKEEPER_FALSE = @HAVE_SCROLLKEEPER_FALSE@ HAVE_SCROLLKEEPER_TRUE = @HAVE_SCROLLKEEPER_TRUE@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ LDFLAGS = @LDFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ MAKEINFO = @MAKEINFO@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGMERGE = @MSGMERGE@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSUB = @POSUB@ QUARRY_GTHREAD_CFLAGS = @QUARRY_GTHREAD_CFLAGS@ QUARRY_GTHREAD_LIBS = @QUARRY_GTHREAD_LIBS@ QUARRY_GTK_CFLAGS = @QUARRY_GTK_CFLAGS@ QUARRY_GTK_DEPRECATED_FLAGS = @QUARRY_GTK_DEPRECATED_FLAGS@ QUARRY_GTK_LIBS = @QUARRY_GTK_LIBS@ QUARRY_WARNINGS = @QUARRY_WARNINGS@ QUARRY_WARNINGS_GTK = @QUARRY_WARNINGS_GTK@ RANLIB = @RANLIB@ REGISTER_MIME_TYPES_FALSE = @REGISTER_MIME_TYPES_FALSE@ REGISTER_MIME_TYPES_TRUE = @REGISTER_MIME_TYPES_TRUE@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ ac_ct_CC = @ac_ct_CC@ ac_ct_RANLIB = @ac_ct_RANLIB@ ac_ct_STRIP = @ac_ct_STRIP@ ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ datadir = @datadir@ exec_prefix = @exec_prefix@ have_scrollkeeper = @have_scrollkeeper@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localstatedir = @localstatedir@ mandir = @mandir@ oldincludedir = @oldincludedir@ prefix = @prefix@ program_transform_name = @program_transform_name@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ AM_CPPFLAGS = \ $(QUARRY_WARNINGS) \ \ -I $(top_srcdir)/src \ -I $(top_srcdir)/src/board \ -I $(top_builddir)/src/board \ -I $(top_srcdir)/src/sgf \ -I $(top_builddir)/src/sgf \ -I $(top_srcdir)/src/utils noinst_LIBRARIES = libgtp.a libgtp_a_SOURCES = \ gtp-client.c \ \ gtp-client.h EXTRA_PROGRAMS = gtp-test gtp_test_SOURCES = gtp-test.c gtp_test_LDADD = \ libgtp.a \ $(top_builddir)/src/board/libboard.a \ $(top_builddir)/src/utils/libutils.a DISTCLEANFILES = *~ CLEANFILES = $(EXTRA_PROGRAMS) subdir = src/gtp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 mkinstalldirs = $(SHELL) $(top_srcdir)/build/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = LIBRARIES = $(noinst_LIBRARIES) libgtp_a_AR = $(AR) cru libgtp_a_LIBADD = am_libgtp_a_OBJECTS = gtp-client.$(OBJEXT) libgtp_a_OBJECTS = $(am_libgtp_a_OBJECTS) EXTRA_PROGRAMS = gtp-test$(EXEEXT) am_gtp_test_OBJECTS = gtp-test.$(OBJEXT) gtp_test_OBJECTS = $(am_gtp_test_OBJECTS) gtp_test_DEPENDENCIES = libgtp.a $(top_builddir)/src/board/libboard.a \ $(top_builddir)/src/utils/libutils.a gtp_test_LDFLAGS = DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/build/depcomp am__depfiles_maybe = depfiles @AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/gtp-client.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/gtp-test.Po COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ DIST_SOURCES = $(libgtp_a_SOURCES) $(gtp_test_SOURCES) DIST_COMMON = $(srcdir)/Makefile.in Makefile.am SOURCES = $(libgtp_a_SOURCES) $(gtp_test_SOURCES) all: all-am .SUFFIXES: .SUFFIXES: .c .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4) cd $(top_srcdir) && \ $(AUTOMAKE) --foreign src/gtp/Makefile Makefile: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) AR = ar clean-noinstLIBRARIES: -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) libgtp.a: $(libgtp_a_OBJECTS) $(libgtp_a_DEPENDENCIES) -rm -f libgtp.a $(libgtp_a_AR) libgtp.a $(libgtp_a_OBJECTS) $(libgtp_a_LIBADD) $(RANLIB) libgtp.a gtp-test$(EXEEXT): $(gtp_test_OBJECTS) $(gtp_test_DEPENDENCIES) @rm -f gtp-test$(EXEEXT) $(LINK) $(gtp_test_LDFLAGS) $(gtp_test_OBJECTS) $(gtp_test_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) core *.core distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gtp-client.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gtp-test.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ @am__fastdepCC_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ @am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ @am__fastdepCC_TRUE@ fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `test -f '$<' || echo '$(srcdir)/'`$< .c.obj: @am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ @am__fastdepCC_TRUE@ -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi`; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ @am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ @am__fastdepCC_TRUE@ fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi` uninstall-info-am: ETAGS = etags ETAGSFLAGS = CTAGS = ctags CTAGSFLAGS = tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(ETAGS_ARGS)$$tags$$unique" \ || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = ../.. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ case $$file in \ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ esac; \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ dir="/$$dir"; \ $(mkinstalldirs) "$(distdir)$$dir"; \ else \ dir=''; \ fi; \ if test -d $$d/$$file; then \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LIBRARIES) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -rm -f $(CONFIG_CLEAN_FILES) -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: info: info-am info-am: install-data-am: install-exec-am: install-info: install-info-am install-man: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-info-am .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ clean-noinstLIBRARIES ctags distclean distclean-compile \ distclean-generic distclean-tags distdir dvi dvi-am info \ info-am install install-am install-data install-data-am \ install-exec install-exec-am install-info install-info-am \ install-man install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-compile mostlyclean-generic pdf pdf-am \ ps ps-am tags uninstall uninstall-am uninstall-info-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: quarry-0.2.0/src/gtp/Makefile.am0000644000175000017500000000112710214656533015121 0ustar bartbart# Process this file with Automake to produce `Makefile.in'. AM_CPPFLAGS = \ $(QUARRY_WARNINGS) \ \ -I $(top_srcdir)/src \ -I $(top_srcdir)/src/board \ -I $(top_builddir)/src/board \ -I $(top_srcdir)/src/sgf \ -I $(top_builddir)/src/sgf \ -I $(top_srcdir)/src/utils noinst_LIBRARIES = libgtp.a libgtp_a_SOURCES = \ gtp-client.c \ \ gtp-client.h EXTRA_PROGRAMS = gtp-test gtp_test_SOURCES = gtp-test.c gtp_test_LDADD = \ libgtp.a \ $(top_builddir)/src/board/libboard.a \ $(top_builddir)/src/utils/libutils.a DISTCLEANFILES = *~ CLEANFILES = $(EXTRA_PROGRAMS) quarry-0.2.0/src/gtp/gtp-client.c0000644000175000017500000007351110512254220015271 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2004 Paul Pogonyshev and Martin Holters. * * Copyright (C) 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* GTP client is an interface to a GTP engine (an external program). * It issues specific commands and parses engine's responses. * * GTP client is a very generic module that doesn't know what a GTP * engine is, how to start it or communicate with it. Instead, it * uses a callback function to send information to the engine and any * response from the engine can be passed to it by calling function * gtp_client_grab_response(). */ /* Fuck me if I remember what the internal command/response counters * are for... (consider this a FIXME.) */ /* To be consistent with de facto GTP standard set up with first * versions of Quarry and Inge Wallin's (currently private) Reversi * engine, we use "Othello", not "Reversi" as game name for GTP. (See * gtp_client_set_game() and store_supported_games_list().) */ #include "gtp-client.h" #include "board.h" #include "game-info.h" #include "utils.h" #include #include #define COLOR_STRING(color) (color == BLACK ? "black" : "white") typedef struct _GtpClientUserCallbackData GtpClientUserCallbackData; struct _GtpClientUserCallbackData { GtpClientResponseCallback response_callback; void *user_data; int integer_data; void *pointer_data; }; static void do_delete_client (GtpClient *client); static void send_command (GtpClient *client, GtpClientResponseCallback response_callback, void *user_data, const char *format_string, ...); static inline GtpClientUserCallbackData * store_user_callback_data (GtpClientResponseCallback response_callback, void *user_data, int integer_data, void *pointer_data); static void dispatch_response (GtpClient *client); static int store_protocol_version (GtpClient *client, int successful); static int store_single_line_response (GtpClient *client, int successful, char **copy); static int store_known_commands_list (GtpClient *client, int successful); static int store_supported_games_list (GtpClient *client, int successful); static int change_client_integer_parameter (GtpClient *client, int successful, GtpClientUserCallbackData *callback_data); static int parse_free_handicap_placement (GtpClient *client, int successful, GtpClientUserCallbackData *callback_data); static int parse_generated_move (GtpClient *client, int successful, GtpClientUserCallbackData *callback_data); static int parse_final_status_list (GtpClient *client, int successful, GtpClientUserCallbackData *callback_data); /* Create a new client for an engine that can be sent commands to by * calling `send_to_engine' callback. Function specified in * `line_callback'--if not NULL--will be called each time the client * receives a full line of response from the engine. Parameter * `deleted_callback' is optional and should be used for freeing any * resources (normally, closing pipes) used to communicate with the * engine upon client deletion. * * Parameter `user_data' will be passed to all three callbacks. */ GtpClient * gtp_client_new (GtpClientSendToEngine send_to_engine, GtpClientLineCallback line_callback, GtpClientErrorCallback error_callback, GtpClientInitializedCallback initialized_callback, GtpClientDeletedCallback deleted_callback, void *user_data) { GtpClient *client = utils_malloc (sizeof (GtpClient)); assert (send_to_engine); client->send_to_engine = send_to_engine; client->line_callback = line_callback; client->error_callback = error_callback; client->deleted_callback = deleted_callback; client->initialized_callback = initialized_callback; client->user_data = user_data; client->engine_name = NULL; client->engine_version = NULL; string_list_init (&client->known_commands); string_list_init (&client->supported_games); client->game = GAME_DUMMY; client->board_size = 0; gtp_command_list_init (&client->pending_commands); string_list_init (&client->response); client->incomplete_line = 0; client->echo_mode = 0; client->operation_stage = GTP_CLIENT_UNINITIALIZED; client->internal_command_index = 0; client->internal_response_index = 0; return client; } void gtp_client_setup_connection (GtpClient *client) { assert (client); assert (client->operation_stage == GTP_CLIENT_UNINITIALIZED); send_command (client, (GtpClientResponseCallback) store_protocol_version, NULL, "protocol_version"); send_command (client, (GtpClientResponseCallback) store_single_line_response, &client->engine_name, "name"); send_command (client, (GtpClientResponseCallback) store_single_line_response, &client->engine_version, "version"); send_command (client, (GtpClientResponseCallback) store_known_commands_list, NULL, "list_commands"); } /* Free a previously allocated GtpClient structure and all internal * information. If non-NULL `deleted_callback' is specified at client * creation, it is called from this function. * * You should use gtp_client_quit() function most of the time (which * schedules a call to gtp_client_delete()). Use this function * directly only when an engine is unreachable (it crashed or the * connection is broken). */ void gtp_client_delete (GtpClient *client) { GtpCommandListItem *item; assert (client); if (client->deleted_callback) client->deleted_callback (client, client->user_data); /* If there are any pending commands then their response callbacks * are called with `client' set to NULL and `successful' to zero, * thus indicating that commands were not actually responded to. * Callbacks should just perform cleanups (like freeing any * allocated resources) if needed. */ for (item = client->pending_commands.first; item; item = item->next) { if (item->response_callback && (item->response_callback != (GtpClientResponseCallback) do_delete_client)) item->response_callback (NULL, 0, item->user_data); } string_list_empty (&client->pending_commands); do_delete_client (client); } static void do_delete_client (GtpClient *client) { string_list_empty (&client->response); utils_free (client->engine_name); utils_free (client->engine_version); string_list_empty (&client->known_commands); string_list_empty (&client->supported_games); utils_free (client); } /* Send client's engine `quit' command and delete the client upon * receiving response. */ void gtp_client_quit (GtpClient *client) { assert (client); assert (client->operation_stage != GTP_CLIENT_UNINITIALIZED); if (client->operation_stage != GTP_CLIENT_QUIT_SCHEDULED) { send_command (client, (GtpClientResponseCallback) do_delete_client, NULL, "quit"); client->operation_stage = GTP_CLIENT_QUIT_SCHEDULED; } } void gtp_client_grab_response (GtpClient *client, char *response, int length) { char *const response_end = response + length; char *buffer_beginning; assert (client); assert (response); assert (length >= 0); for (buffer_beginning = response; buffer_beginning < response_end;) { char *buffer_pointer = buffer_beginning; char *line_pointer = buffer_beginning; while (1) { unsigned char character = *buffer_pointer++; if (character != '\n') { /* Skip all control characters. */ if ((character > 31 && character != 127) || character == '\t') *line_pointer++ = character; if (buffer_pointer < response_end) continue; } if (character != '\n' || buffer_pointer != buffer_beginning + 1 || client->incomplete_line || string_list_is_empty (&client->response)) { char *end_of_line = line_pointer; if (character == '\n') { /* Ignore trailing whitespace. */ while (end_of_line > buffer_beginning && (*(end_of_line - 1) == ' ' || *(end_of_line - 1) == '\t')) end_of_line--; *end_of_line++ = '\n'; if (end_of_line == buffer_beginning) { /* Delete trailing whitespace in the stored incomplete * line beginnning (actually, full line). */ char *stored_line = client->response.last->text; char *end_of_stored_line = stored_line + strlen (stored_line); while (end_of_stored_line > stored_line && (*(end_of_stored_line - 1) == ' ' || *(end_of_stored_line - 1) == '\t')) end_of_stored_line--; *end_of_stored_line = 0; } } if (!client->incomplete_line) { string_list_add_from_buffer (&client->response, buffer_beginning, end_of_line - buffer_beginning); } else { if (end_of_line > buffer_beginning) { client->response.last->text = utils_cat_as_string (client->response.last->text, buffer_beginning, end_of_line - buffer_beginning); } } if (character == '\n') { char *this_line = client->response.last->text; if (string_list_is_empty (&client->pending_commands)) { if (*this_line != '\n' && client->error_callback) { client->error_callback (GTP_WARNING_UNEXPECTED_OUTPUT, -1, client->user_data); } if (client->line_callback) client->line_callback (this_line, 0, -1, client->user_data); string_list_empty (&client->response); } else if (string_list_is_single_string (&client->response) && *this_line != '\n') { /* First line of response contains success flag and * command/response id. We need to check and store * these for further processing. */ GtpError error = GTP_SUCCESS; char *line_beginning = this_line + 1; int command_id = client->pending_commands.first->command_id; if (this_line[0] == '=' || this_line[0] == '?') { client->successful = (this_line[0] == '='); if (command_id >= 0) { int response_id = -1; if ('0' <= *line_beginning && *line_beginning <= '9') { int num_characters_eaten; sscanf (line_beginning, "%d%n", &response_id, &num_characters_eaten); line_beginning += num_characters_eaten; } if (response_id != command_id) error = GTP_ERROR_MISMATCHED_ID; } else if ('0' <= *line_beginning && *line_beginning <= '9') error = GTP_ERROR_UNEXPECTED_ID; if (error == GTP_SUCCESS && (*line_beginning != ' ' && *line_beginning != '\t' && *line_beginning != '\n')) error = GTP_ERROR_UNRECOGNIZED_RESPONSE; } else error = GTP_ERROR_UNRECOGNIZED_RESPONSE; if (error == GTP_SUCCESS) { if (client->line_callback && client->pending_commands.first->command) { client->line_callback (client->pending_commands.first->command, 1, client->internal_response_index, client->user_data); client->line_callback (this_line, 0, client->internal_response_index, client->user_data); } /* Throw '=' / '?' flag and command id out of stored * response line. */ client->response.first->text = utils_duplicate_string (line_beginning); utils_free (this_line); } else { if (client->error_callback) client->error_callback (error, command_id, client->user_data); if (client->line_callback) client->line_callback (this_line, 0, -1, client->user_data); string_list_empty (&client->response); } } else { if (client->pending_commands.first->command) { client->line_callback (this_line, 0, client->internal_response_index, client->user_data); } if (string_list_is_single_string (&client->response)) string_list_empty (&client->response); } client->incomplete_line = 0; } else client->incomplete_line = 1; } else { /* Two consecutive newlines--we've got a full response! */ dispatch_response (client); } break; } buffer_beginning = buffer_pointer; } } int gtp_client_set_echo_mode (GtpClient *client, int echo_mode) { int current_echo_mode; assert (client); current_echo_mode = client->echo_mode; client->echo_mode = echo_mode; return current_echo_mode; } int gtp_client_is_known_command (const GtpClient *client, const char *command) { assert (client); assert (command); return (string_list_is_empty (&client->known_commands) || string_list_find (&client->known_commands, command) != NULL); } void gtp_client_set_game (GtpClient *client, GtpClientResponseCallback response_callback, void *user_data, Game game) { assert (client); assert (game >= FIRST_GAME && GAME_IS_SUPPORTED (game)); send_command (client, (GtpClientResponseCallback) change_client_integer_parameter, store_user_callback_data (response_callback, user_data, game, &client->game), "set_game %s", /* See note at the top of the file. */ (game != GAME_REVERSI ? game_info[game].name : "Othello")); } void gtp_client_set_board_size (GtpClient *client, GtpClientResponseCallback response_callback, void *user_data, int board_size) { assert (client); assert (GTP_MIN_BOARD_SIZE <= board_size && board_size <= GTP_MAX_BOARD_SIZE && BOARD_MIN_WIDTH <= board_size && board_size <= BOARD_MAX_WIDTH && BOARD_MIN_HEIGHT <= board_size && board_size <= BOARD_MAX_HEIGHT); send_command (client, (GtpClientResponseCallback) change_client_integer_parameter, store_user_callback_data (response_callback, user_data, board_size, &client->board_size), "boardsize %d", board_size); } void gtp_client_clear_board (GtpClient *client, GtpClientResponseCallback response_callback, void *user_data) { assert (client); send_command (client, response_callback, user_data, "clear_board"); } void gtp_client_set_fixed_handicap (GtpClient *client, GtpClientResponseCallback response_callback, void *user_data, int handicap) { assert (client); send_command (client, response_callback, user_data, "fixed_handicap %d", handicap); } void gtp_client_place_free_handicap (GtpClient *client, GtpClientFreeHandicapCallback response_callback, void *user_data, int handicap) { assert (client); send_command (client, (GtpClientResponseCallback) parse_free_handicap_placement, store_user_callback_data (((GtpClientResponseCallback) response_callback), user_data, handicap, NULL), "place_free_handicap %d", handicap); } void gtp_client_set_free_handicap (GtpClient *client, GtpClientResponseCallback response_callback, void *user_data, const BoardPositionList *handicap_stones) { StringBuffer buffer; assert (client); assert (handicap_stones); string_buffer_init (&buffer, 0x100, 0x100); game_format_position_list (GAME_GO, client->board_size, client->board_size, &buffer, handicap_stones); send_command (client, response_callback, user_data, "set_free_handicap %s", buffer.string); string_buffer_dispose (&buffer); } void gtp_client_set_komi (GtpClient *client, GtpClientResponseCallback response_callback, void *user_data, double komi) { assert (client); send_command (client, response_callback, user_data, "komi %.f", komi); } void gtp_client_send_time_settings (GtpClient *client, GtpClientResponseCallback response_callback, void *user_data, int main_time, int byo_yomi_time, int moves_per_byo_yomi_period) { assert (client); assert (main_time >= 0 && byo_yomi_time >= 0 && moves_per_byo_yomi_period >= 0 && (byo_yomi_time == 0 || moves_per_byo_yomi_period > 0)); /* GTP uses slightly different values for "no limit". */ if (main_time == 0 && byo_yomi_time == 0) byo_yomi_time = 1; send_command (client, response_callback, user_data, "time_settings %d %d %d", main_time, byo_yomi_time, moves_per_byo_yomi_period); } void gtp_client_send_time_left (GtpClient *client, GtpClientResponseCallback response_callback, void *user_data, int color, int seconds_left, int moves_left) { assert (client); assert (IS_STONE (color)); assert (seconds_left >= 0 && moves_left >= 0); send_command (client, response_callback, user_data, "time_left %s %d %d", COLOR_STRING (color), seconds_left, moves_left); } void gtp_client_play_move (GtpClient *client, GtpClientResponseCallback response_callback, void *user_data, int color, ...) { va_list move; StringBuffer move_buffer; assert (client); assert (IS_STONE (color)); string_buffer_init (&move_buffer, 0x10, 0x20); va_start (move, color); game_format_move_valist (client->game, client->board_size, client->board_size, &move_buffer, move); va_end (move); send_command (client, response_callback, user_data, client->protocol_version != 1 ? "play %s %s" : "%s %s", COLOR_STRING (color), move_buffer.string); string_buffer_dispose (&move_buffer); } void gtp_client_play_move_from_sgf_node (GtpClient *client, GtpClientResponseCallback response_callback, void *user_data, const SgfGameTree *sgf_game_tree, const SgfNode *sgf_node) { assert (client); assert (sgf_game_tree); assert (sgf_game_tree->game == client->game); assert (sgf_game_tree->board_width == client->board_size && sgf_game_tree->board_height == client->board_size); assert (sgf_node); if (client->game != GAME_AMAZONS) { gtp_client_play_move (client, response_callback, user_data, sgf_node->move_color, sgf_node->move_point.x, sgf_node->move_point.y); } else { gtp_client_play_move (client, response_callback, user_data, sgf_node->move_color, sgf_node->move_point.x, sgf_node->move_point.y, sgf_node->data.amazons); } } void gtp_client_generate_move (GtpClient *client, GtpClientMoveCallback response_callback, void *user_data, int color) { assert (client); assert (IS_STONE (color)); send_command (client, (GtpClientResponseCallback) parse_generated_move, store_user_callback_data (((GtpClientResponseCallback) response_callback), user_data, color, NULL), client->protocol_version != 1 ? "genmove %s" : "genmove_%s", COLOR_STRING (color)); } void gtp_client_final_status_list (GtpClient *client, GtpClientFinalStatusListCallback response_callback, void *user_data, GtpStoneStatus status) { const char *status_string = NULL; assert (client); switch (status) { case GTP_ALIVE: status_string = "alive"; break; case GTP_DEAD: status_string = "dead"; break; case GTP_SEKI: status_string = "seki"; break; } assert (status_string); send_command (client, (GtpClientResponseCallback) parse_final_status_list, store_user_callback_data (((GtpClientResponseCallback) response_callback), user_data, status, NULL), "final_status_list %s", status_string); } static void send_command (GtpClient *client, GtpClientResponseCallback response_callback, void *user_data, const char *format_string, ...) { char *command; va_list arguments; va_start (arguments, format_string); command = utils_vcprintf (format_string, arguments); va_end (arguments); command = utils_cat_string (command, "\n"); string_list_add_ready (&client->pending_commands, client->echo_mode ? command : NULL); client->pending_commands.last->command_id = -1; client->pending_commands.last->response_callback = response_callback; client->pending_commands.last->user_data = user_data; client->send_to_engine (command, client->user_data); if (!client->echo_mode) utils_free (command); client->internal_command_index++; } static inline GtpClientUserCallbackData * store_user_callback_data (GtpClientResponseCallback response_callback, void *user_data, int integer_data, void *pointer_data) { GtpClientUserCallbackData *callback_data = utils_malloc (sizeof (GtpClientUserCallbackData)); callback_data->response_callback = response_callback; callback_data->user_data = user_data; callback_data->integer_data = integer_data; callback_data->pointer_data = pointer_data; return callback_data; } static void dispatch_response (GtpClient *client) { StringListItem *list_item; GtpClientResponseCallback response_callback = client->pending_commands.first->response_callback; void *user_data = client->pending_commands.first->user_data; /* Normalize all response lines by collapsing all whitespace (spaces * and tabs) to a single space to ease further parsing. Leading * whitespace is removed completely and newline is dropped as well. */ for (list_item = client->response.first; list_item; list_item = list_item->next) { char *line_pointer = list_item->text; char *new_line_pointer = list_item->text; while (*line_pointer == ' ' || *line_pointer == '\t') line_pointer++; while (*line_pointer != '\n') { if (*line_pointer != ' ' && *line_pointer != '\t') *new_line_pointer++ = *line_pointer++; else { do line_pointer++; while (*line_pointer == ' ' || *line_pointer == '\t'); *new_line_pointer++ = ' '; } } *new_line_pointer = 0; } if (response_callback && response_callback != (GtpClientResponseCallback) do_delete_client && !response_callback (client, client->successful, user_data) && client->error_callback) { client->error_callback (GTP_ERROR_WRONG_RESPONSE_FORMAT, client->internal_response_index, client->user_data); } if (client->line_callback && client->pending_commands.first->command) { client->line_callback ("\n", 0, client->internal_response_index, client->user_data); } string_list_delete_first_item (&client->pending_commands); if (response_callback != (GtpClientResponseCallback) do_delete_client) { string_list_empty (&client->response); client->internal_response_index++; } else { /* This special case is needed, because do_delete_client() frees * the `client' structure, so it avoids segmentation faults. */ if (client->deleted_callback) { client->operation_stage = GTP_CLIENT_QUIT; client->deleted_callback (client, client->user_data); } assert (string_list_is_empty (&client->pending_commands)); do_delete_client (client); } } static int store_protocol_version (GtpClient *client, int successful) { int result; if (client) client->protocol_version = 1; result = (!successful || sscanf (client->response.first->text, "%d", &client->protocol_version)); if (successful) { if (client->protocol_version > 2) { if (client->error_callback) { client->error_callback (GTP_WARNING_FUTURE_GTP_VERSION, client->internal_response_index, client->user_data); } } else if (client->protocol_version < 1) { result = 0; client->protocol_version = 1; } } return result; } static int store_single_line_response (GtpClient *client, int successful, char **copy) { if (successful && string_list_is_single_string (&client->response)) *copy = utils_duplicate_string (client->response.first->text); return !successful || string_list_is_single_string (&client->response); } static int store_known_commands_list (GtpClient *client, int successful) { int valid_response = 1; if (successful) { StringListItem *list_item; for (list_item = client->response.first; list_item; list_item = list_item->next) { if (!*list_item->text || strchr (list_item->text, ' ')) { valid_response = 0; break; } } if (valid_response) string_list_steal_items (&client->known_commands, &client->response); } if (client) { if (gtp_client_is_known_command (client, "list_games")) { send_command (client, (GtpClientResponseCallback) store_supported_games_list, NULL, "list_games"); } else store_supported_games_list (client, 0); } return valid_response; } static int store_supported_games_list (GtpClient *client, int successful) { if (successful) { StringListItem *list_item; string_list_steal_items (&client->supported_games, &client->response); for (list_item = client->supported_games.first; list_item; list_item = list_item->next) { /* See note at the top of the file. */ if (strcmp (list_item->text, "Othello") == 0) { utils_free (list_item->text); list_item->text = utils_duplicate_string (game_info[GAME_REVERSI].name); break; } } if (string_list_is_single_string (&client->supported_games)) { Game game; for (game = FIRST_GAME; game <= LAST_GAME; game++) { if (GAME_IS_SUPPORTED (game) && strcmp (client->supported_games.first->text, game_info[game].name) == 0) { client->game = game; break; } } } } else if (client) { string_list_add (&client->supported_games, "Go"); client->game = GAME_GO; } if (client) { client->operation_stage = GTP_CLIENT_WORKING; if (client->initialized_callback) client->initialized_callback (client, client->user_data); } return 1; } static int change_client_integer_parameter (GtpClient *client, int successful, GtpClientUserCallbackData *callback_data) { if (successful) * (int *) callback_data->pointer_data = callback_data->integer_data; if (callback_data->response_callback) { callback_data->response_callback (client, successful, callback_data->user_data); } utils_free (callback_data); return (!successful || (string_list_is_single_string (&client->response) && ! *client->response.first->text)); } static int parse_free_handicap_placement (GtpClient *client, int successful, GtpClientUserCallbackData *callback_data) { GtpClientFreeHandicapCallback free_handicap_callback = (GtpClientFreeHandicapCallback) callback_data->response_callback; BoardPositionList *handicap_stones = NULL; if (successful && string_list_is_single_string (&client->response)) { handicap_stones = game_parse_position_list (GAME_GO, client->board_size, client->board_size, client->response.first->text); } free_handicap_callback (client, handicap_stones != NULL, callback_data->user_data, handicap_stones); utils_free (callback_data); return !successful || handicap_stones != NULL; } static int parse_generated_move (GtpClient *client, int successful, GtpClientUserCallbackData *callback_data) { GtpClientMoveCallback move_callback = ((GtpClientMoveCallback) callback_data->response_callback); int move_parsed = 0; if (successful && string_list_is_single_string (&client->response)) { int x; int y; BoardAbstractMoveData move_data; int num_characters_eaten; num_characters_eaten = game_parse_move (client->game, client->board_size, client->board_size, client->response.first->text, &x, &y, &move_data); if (num_characters_eaten == 0 && strcasecmp (client->response.first->text, "resign") == 0) { x = RESIGNATION_X; y = RESIGNATION_Y; num_characters_eaten = 6; } if (num_characters_eaten > 0 && !client->response.first->text[num_characters_eaten]) { if (move_callback) { move_callback (client, 1, callback_data->user_data, callback_data->integer_data, x, y, &move_data); } move_parsed = 1; } } if (!move_parsed && move_callback) { move_callback (client, 0, callback_data->user_data, EMPTY, PASS_X, PASS_Y, NULL); } utils_free (callback_data); return !successful || move_parsed; } static int parse_final_status_list (GtpClient *client, int successful, GtpClientUserCallbackData *callback_data) { GtpClientFinalStatusListCallback final_status_list_callback = (GtpClientFinalStatusListCallback) callback_data->response_callback; if (successful) { StringListItem *this_item; BoardPositionList *stones = board_position_list_new_empty (0); if (!string_list_is_single_string (&client->response) || *client->response.first->text) { for (this_item = client->response.first; this_item; this_item = this_item->next) { BoardPositionList *string = game_parse_position_list (GAME_GO, client->board_size, client->board_size, this_item->text); if (string) { BoardPositionList *stones_new = board_position_list_union (stones, string); board_position_list_delete (stones); board_position_list_delete (string); stones = stones_new; } else { board_position_list_delete (stones); break; } } } else { /* Empty response is valid as well. */ this_item = NULL; } if (!this_item) { /* The list is parsed just fine. */ final_status_list_callback (client, successful, callback_data->user_data, callback_data->integer_data, stones); utils_free (callback_data); board_position_list_delete (stones); return 1; } } final_status_list_callback (client, 0, callback_data->user_data, callback_data->integer_data, NULL); utils_free (callback_data); return !successful; } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gtp/gtp-client.h0000644000175000017500000002005710377670256015317 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2004 Paul Pogonyshev and Martin Holters. * * Copyright (C) 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef QUARRY_GTP_CLIENT_H #define QUARRY_GTP_CLIENT_H #include "sgf.h" #include "board.h" #include "utils.h" #include "quarry.h" #include #define GTP_MIN_BOARD_SIZE 2 #define GTP_MAX_BOARD_SIZE 25 #define RESIGNATION_X SPECIAL_X #define RESIGNATION_Y SPECIAL_X #define RESIGNATION SPECIAL_POSITION typedef enum { GTP_CLIENT_UNINITIALIZED, GTP_CLIENT_WORKING, GTP_CLIENT_QUIT_SCHEDULED, GTP_CLIENT_QUIT } GtpClientOperationStage; typedef enum { GTP_ERROR_WRONG_RESPONSE_FORMAT, GTP_WARNING_UNEXPECTED_OUTPUT, GTP_ERROR_UNRECOGNIZED_RESPONSE, GTP_ERROR_MISMATCHED_ID, GTP_ERROR_UNEXPECTED_ID, GTP_WARNING_FUTURE_GTP_VERSION, /* Used internally */ GTP_SUCCESS } GtpError; typedef enum { GTP_ALIVE, GTP_DEAD, GTP_SEKI } GtpStoneStatus; typedef struct _GtpClient GtpClient; typedef void (* GtpClientSendToEngine) (const char *command, void *user_data); typedef void (* GtpClientLineCallback) (const char *line, int is_command, int internal_index, void *user_data); typedef void (* GtpClientErrorCallback) (GtpError error, int command_id, void *user_data); typedef void (* GtpClientInitializedCallback) (GtpClient *client, void *user_data); typedef void (* GtpClientDeletedCallback) (GtpClient *client, void *user_data); typedef int (* GtpClientResponseCallback) (GtpClient *client, int successful, void *user_data); typedef struct _GtpCommandListItem GtpCommandListItem; typedef struct _GtpCommandList GtpCommandList; struct _GtpCommandListItem { GtpCommandListItem *next; char *command; int command_id; GtpClientResponseCallback response_callback; void *user_data; }; struct _GtpCommandList { GtpCommandListItem *first; GtpCommandListItem *last; int item_size; StringListItemDispose item_dispose; }; #define gtp_command_list_new() \ ((GtpCommandList *) \ string_list_new_derived (sizeof (GtpCommandListItem), NULL) #define gtp_command_list_init(list) \ string_list_init_derived ((list), sizeof (GtpCommandListItem), NULL) #define STATIC_GTP_COMMAND_LIST \ STATIC_STRING_LIST_DERIVED (GtpCommandListItem, NULL) #define gtp_command_list_get_item(list, item_index) \ ((GtpCommandListItem *) string_list_get_item ((list), (item_index))) #define gtp_command_list_find(list, command) \ ((GtpCommandListItem *) string_list_find ((list), (command))) #define gtp_command_list_find_after_notch(list, command, notch) \ ((GtpCommandListItem *) \ string_list_find_after_notch ((list), (command), (notch))) struct _GtpClient { GtpClientSendToEngine send_to_engine; GtpClientLineCallback line_callback; GtpClientErrorCallback error_callback; GtpClientInitializedCallback initialized_callback; GtpClientDeletedCallback deleted_callback; void *user_data; int protocol_version; char *engine_name; char *engine_version; StringList known_commands; StringList supported_games; Game game; int board_size; GtpCommandList pending_commands; StringList response; int incomplete_line; int successful; int echo_mode; GtpClientOperationStage operation_stage; int internal_command_index; int internal_response_index; }; typedef void (* GtpClientFreeHandicapCallback) (GtpClient *client, int successful, void *user_data, BoardPositionList *handicap_stones); typedef void (* GtpClientMoveCallback) (GtpClient *client, int successful, void *user_data, int color, int x, int y, BoardAbstractMoveData *move_data); typedef void (* GtpClientFinalStatusListCallback) (GtpClient *client, int successful, void *user_data, GtpStoneStatus status, BoardPositionList *stones); GtpClient * gtp_client_new (GtpClientSendToEngine send_to_engine, GtpClientLineCallback line_callback, GtpClientErrorCallback error_callback, GtpClientInitializedCallback initialized_callback, GtpClientDeletedCallback deletied_callback, void *user_data); void gtp_client_setup_connection (GtpClient *client); void gtp_client_delete (GtpClient *client); void gtp_client_quit (GtpClient *client); void gtp_client_grab_response (GtpClient *client, char *response, int length); int gtp_client_set_echo_mode (GtpClient *client, int echo_mode); #define gtp_client_echo_on(client) gtp_client_set_echo_mode ((client), 1) #define gtp_client_echo_off(client) gtp_client_set_echo_mode ((client), 0) int gtp_client_is_known_command (const GtpClient *client, const char *command); void gtp_client_set_game (GtpClient *client, GtpClientResponseCallback response_callback, void *user_data, Game game); void gtp_client_set_board_size (GtpClient *client, GtpClientResponseCallback response_callback, void *user_data, int board_size); void gtp_client_clear_board (GtpClient *client, GtpClientResponseCallback response_callback, void *user_data); void gtp_client_set_fixed_handicap (GtpClient *client, GtpClientResponseCallback response_callback, void *user_data, int handicap); void gtp_client_place_free_handicap (GtpClient *client, GtpClientFreeHandicapCallback response_callback, void *user_data, int handicap); void gtp_client_set_free_handicap (GtpClient *client, GtpClientResponseCallback response_callback, void *user_data, const BoardPositionList *handicap_stones); void gtp_client_set_komi (GtpClient *client, GtpClientResponseCallback response_callback, void *user_data, double komi); void gtp_client_send_time_settings (GtpClient *client, GtpClientResponseCallback response_callback, void *user_data, int main_time, int byo_yomi_time, int moves_per_byo_yomi_period); void gtp_client_send_time_left (GtpClient *client, GtpClientResponseCallback response_callback, void *user_data, int color, int seconds_left, int moves_left); void gtp_client_play_move (GtpClient *client, GtpClientResponseCallback response_callback, void *user_data, int color, ...); void gtp_client_play_move_from_sgf_node (GtpClient *client, GtpClientResponseCallback response_callback, void *user_data, const SgfGameTree *sgf_game_tree, const SgfNode *sgf_node); void gtp_client_generate_move (GtpClient *client, GtpClientMoveCallback response_callback, void *user_data, int color); void gtp_client_final_status_list (GtpClient *client, GtpClientFinalStatusListCallback response_callback, void *user_data, GtpStoneStatus status); #endif /* QUARRY_GTP_CLIENT_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gtp/gtp-test.c0000644000175000017500000001274310367243662015012 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "gtp-client.h" #include "utils.h" #include #include #include #include #include #include #include static int client_is_alive = 1; static void send_to_engine (const char *command, void *user_data) { write (* (int *) user_data, command, strlen (command)); fdatasync (* (int *) user_data); } static void line_callback (const char *line, int is_command, int internal_index, void *user_data) { UNUSED (user_data); printf ("%c [%d] %s", is_command ? '>' : ' ', internal_index, line); } static void error_callback (GtpError error, int command_id, void *user_data) { UNUSED (command_id); UNUSED (user_data); fprintf (stderr, "*** GTP error %d ***\n", error); } static void initialized_callback (GtpClient *client, void *user_data) { UNUSED (user_data); printf ("Connected to %s version %s using GTP %d\n", client->engine_name, client->engine_version, client->protocol_version); gtp_client_quit (client); } static void deleted_callback (GtpClient *client, void *user_data) { UNUSED (client); UNUSED (user_data); client_is_alive = 0; } int main (int argc, char *argv[], char *envp[]) { int result = 0; utils_remember_program_name (argv[0]); if (argc > 1) { int engine_in_pipe[2]; int engine_out_pipe[2]; pid_t child_pid; if (pipe (engine_in_pipe) != 0) assert (0); if (pipe (engine_out_pipe) != 0) assert (0); child_pid = fork (); if (child_pid == 0) { int descriptor; int open_max = sysconf (_SC_OPEN_MAX); for (descriptor = 0; descriptor < open_max; descriptor++) { if (descriptor != STDERR_FILENO) fcntl (descriptor, F_SETFD, FD_CLOEXEC); } if (dup2 (engine_in_pipe[0], STDIN_FILENO) != STDIN_FILENO) assert (0); if (dup2 (engine_out_pipe[1], STDOUT_FILENO) != STDOUT_FILENO) assert (0); execve (argv[1], argv + 1, envp); fprintf (stderr, "%s: error: unable to execute %s\n", argv[0], argv[1]); exit (255); } else { close (engine_in_pipe[0]); close (engine_out_pipe[1]); if (child_pid > 0) { int engine_in = engine_in_pipe[1]; int engine_out = engine_out_pipe[0]; GtpClient *client = gtp_client_new (send_to_engine, line_callback, error_callback, initialized_callback, deleted_callback, &engine_in); gtp_client_echo_on (client); gtp_client_setup_connection (client); while (client_is_alive) { fd_set in_set; FD_ZERO (&in_set); FD_SET (STDIN_FILENO, &in_set); FD_SET (engine_out, &in_set); if (select (engine_out + 1, &in_set, NULL, NULL, NULL) <= 0) break; if (FD_ISSET (engine_out, &in_set)) { /* The intention is to stress gtp_client_grab_response() * here. We first sleep for a little bit hoping that more * input will arive. Then we throw the response at the * function in random chunks, completely disregarding line * boundaries. */ usleep (1); while (client_is_alive) { char buffer[0x1000]; int bytes_read = read (engine_out, buffer, sizeof buffer); int processed_length = 0; while (processed_length < bytes_read) { int random_chunk_length = 1 + random () % (((bytes_read - processed_length) * 3) / 2); if (random_chunk_length > bytes_read - processed_length) random_chunk_length = bytes_read - processed_length; gtp_client_grab_response (client, buffer + processed_length, random_chunk_length); processed_length += random_chunk_length; } if (bytes_read < sizeof buffer) break; } } } close (engine_in); close (engine_out); } else { fprintf (stderr, "%s: error: unable to fork\n", argv[0]); close (engine_in_pipe[1]); close (engine_out_pipe[0]); result = 254; } } } else { fprintf (stderr, "Usage: %s ENGINE [PARAMETER ...]\n", full_program_name); result = 255; } utils_free_program_name_strings (); #if ENABLE_MEMORY_PROFILING utils_print_memory_profiling_info (); #endif return result; } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-utils/0000755000175000017500000000000010530402570014203 5ustar bartbartquarry-0.2.0/src/gui-utils/Makefile.in0000644000175000017500000004175210520514412016257 0ustar bartbart# Makefile.in generated by automake 1.7.9 from Makefile.am. # @configure_input@ # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 # Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # Process this file with Automake to produce `Makefile.in'. srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = ../.. am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : host_triplet = @host@ ACLOCAL = @ACLOCAL@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BUILD_SGF_UTILS_FALSE = @BUILD_SGF_UTILS_FALSE@ BUILD_SGF_UTILS_TRUE = @BUILD_SGF_UTILS_TRUE@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DO_SCROLLKEEPER_UPDATE_FALSE = @DO_SCROLLKEEPER_UPDATE_FALSE@ DO_SCROLLKEEPER_UPDATE_TRUE = @DO_SCROLLKEEPER_UPDATE_TRUE@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ GMSGFMT = @GMSGFMT@ HAVE_SCROLLKEEPER_FALSE = @HAVE_SCROLLKEEPER_FALSE@ HAVE_SCROLLKEEPER_TRUE = @HAVE_SCROLLKEEPER_TRUE@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ LDFLAGS = @LDFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ MAKEINFO = @MAKEINFO@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGMERGE = @MSGMERGE@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSUB = @POSUB@ QUARRY_GTHREAD_CFLAGS = @QUARRY_GTHREAD_CFLAGS@ QUARRY_GTHREAD_LIBS = @QUARRY_GTHREAD_LIBS@ QUARRY_GTK_CFLAGS = @QUARRY_GTK_CFLAGS@ QUARRY_GTK_DEPRECATED_FLAGS = @QUARRY_GTK_DEPRECATED_FLAGS@ QUARRY_GTK_LIBS = @QUARRY_GTK_LIBS@ QUARRY_WARNINGS = @QUARRY_WARNINGS@ QUARRY_WARNINGS_GTK = @QUARRY_WARNINGS_GTK@ RANLIB = @RANLIB@ REGISTER_MIME_TYPES_FALSE = @REGISTER_MIME_TYPES_FALSE@ REGISTER_MIME_TYPES_TRUE = @REGISTER_MIME_TYPES_TRUE@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ ac_ct_CC = @ac_ct_CC@ ac_ct_RANLIB = @ac_ct_RANLIB@ ac_ct_STRIP = @ac_ct_STRIP@ ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ datadir = @datadir@ exec_prefix = @exec_prefix@ have_scrollkeeper = @have_scrollkeeper@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localstatedir = @localstatedir@ mandir = @mandir@ oldincludedir = @oldincludedir@ prefix = @prefix@ program_transform_name = @program_transform_name@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ AM_CPPFLAGS = \ -D PACKAGE_DATA_DIR=\"$(pkgdatadir)\" \ \ $(QUARRY_WARNINGS) \ \ -I $(top_srcdir)/src \ -I $(top_srcdir)/src/sgf \ -I $(top_builddir)/src/sgf \ -I $(top_srcdir)/src/board \ -I $(top_builddir)/src/board \ -I $(top_srcdir)/src/utils noinst_LIBRARIES = libguiutils.a LIST_FILES = markup-theme-configuration.list PARSE_LIST_COMMAND = ./parse-configuration$(EXEEXT) PARSE_LIST_FLAGS = SUFFIXES = .list .h # `LIST_FILES' must be set by the includer. The includer can use # `LIST_STAMP_FILES' and `LIST_GENERATED_FILES' and assume they are # set just as here. # LIST_STAMP_FILES = $(LIST_FILES:.list=.stamp) LIST_GENERATED_FILES = $(LIST_FILES:.list=.c) $(LIST_FILES:.list=.h) # `PARSE_LIST_COMMAND' and `PARSE_LIST_FLAGS' should be set by the # includer. # PARSE_LIST = $(PARSE_LIST_COMMAND) $(PARSE_LIST_FLAGS) # We use `cmp' here to avoid unneeded recompilations of files that # depend on generated ones (only really useful for `.h' files.) # PARSE_LIST_BUILD_RULE = \ if $(PARSE_LIST) `test -f '$<' || echo '$(srcdir)/'`$< \ $*.h.new $*.c.new; then \ if cmp -s $*.c.new $*.c; \ then rm -f $*.c.new; else mv -f $*.c.new $*.c; \ fi; \ if cmp -s $*.h.new $*.h; \ then rm -f $*.h.new; else mv -f $*.h.new $*.h; \ fi; \ echo timestamp > $@; \ else \ (rm -f $*.c $*.c.new $*.h $*.h.new ; exit 1) \ fi libguiutils_a_SOURCES = \ configuration.c \ gui-utils.c \ tile-renderer.c \ time-control.c \ \ configuration.h \ gui-utils.h \ tile-renderer.h \ time-control.h \ \ $(LIST_FILES) nodist_libguiutils_a_SOURCES = $(LIST_GENERATED_FILES) BUILT_SOURCES = $(LIST_STAMP_FILES) noinst_PROGRAMS = parse-configuration parse_configuration_SOURCES = parse-configuration.c parse_configuration_LDADD = \ $(top_builddir)/src/utils/libparselist.a \ $(top_builddir)/src/utils/libutils.a EXTRA_DIST = \ common-configuration-sections.list \ common-configuration-values.list \ common-configuration-defaults.list DISTCLEANFILES = *~ MOSTLYCLEANFILES = \ $(LIST_STAMP_FILES) \ $(LIST_GENERATED_FILES) subdir = src/gui-utils ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 mkinstalldirs = $(SHELL) $(top_srcdir)/build/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = LIBRARIES = $(noinst_LIBRARIES) libguiutils_a_AR = $(AR) cru libguiutils_a_LIBADD = am__objects_1 = am_libguiutils_a_OBJECTS = configuration.$(OBJEXT) gui-utils.$(OBJEXT) \ tile-renderer.$(OBJEXT) time-control.$(OBJEXT) $(am__objects_1) am__objects_2 = markup-theme-configuration.$(OBJEXT) am__objects_3 = $(am__objects_2) $(am__objects_1) nodist_libguiutils_a_OBJECTS = $(am__objects_3) libguiutils_a_OBJECTS = $(am_libguiutils_a_OBJECTS) \ $(nodist_libguiutils_a_OBJECTS) noinst_PROGRAMS = parse-configuration$(EXEEXT) PROGRAMS = $(noinst_PROGRAMS) am_parse_configuration_OBJECTS = parse-configuration.$(OBJEXT) parse_configuration_OBJECTS = $(am_parse_configuration_OBJECTS) parse_configuration_DEPENDENCIES = \ $(top_builddir)/src/utils/libparselist.a \ $(top_builddir)/src/utils/libutils.a parse_configuration_LDFLAGS = DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/build/depcomp am__depfiles_maybe = depfiles @AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/configuration.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/gui-utils.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/markup-theme-configuration.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/parse-configuration.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/tile-renderer.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/time-control.Po COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ DIST_SOURCES = $(libguiutils_a_SOURCES) $(parse_configuration_SOURCES) DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/build/list.make \ Makefile.am SOURCES = $(libguiutils_a_SOURCES) $(nodist_libguiutils_a_SOURCES) $(parse_configuration_SOURCES) all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: .list .h .c .o .obj .stamp $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/build/list.make $(top_srcdir)/configure.ac $(ACLOCAL_M4) cd $(top_srcdir) && \ $(AUTOMAKE) --foreign src/gui-utils/Makefile Makefile: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) AR = ar clean-noinstLIBRARIES: -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) libguiutils.a: $(libguiutils_a_OBJECTS) $(libguiutils_a_DEPENDENCIES) -rm -f libguiutils.a $(libguiutils_a_AR) libguiutils.a $(libguiutils_a_OBJECTS) $(libguiutils_a_LIBADD) $(RANLIB) libguiutils.a clean-noinstPROGRAMS: -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS) parse-configuration$(EXEEXT): $(parse_configuration_OBJECTS) $(parse_configuration_DEPENDENCIES) @rm -f parse-configuration$(EXEEXT) $(LINK) $(parse_configuration_LDFLAGS) $(parse_configuration_OBJECTS) $(parse_configuration_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) core *.core distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/configuration.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gui-utils.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/markup-theme-configuration.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parse-configuration.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tile-renderer.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/time-control.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ @am__fastdepCC_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ @am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ @am__fastdepCC_TRUE@ fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `test -f '$<' || echo '$(srcdir)/'`$< .c.obj: @am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ @am__fastdepCC_TRUE@ -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi`; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ @am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ @am__fastdepCC_TRUE@ fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi` uninstall-info-am: ETAGS = etags ETAGSFLAGS = CTAGS = ctags CTAGSFLAGS = tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(ETAGS_ARGS)$$tags$$unique" \ || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = ../.. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) $(mkinstalldirs) $(distdir)/../../build @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ case $$file in \ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ esac; \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ dir="/$$dir"; \ $(mkinstalldirs) "$(distdir)$$dir"; \ else \ dir=''; \ fi; \ if test -d $$d/$$file; then \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-am all-am: Makefile $(LIBRARIES) $(PROGRAMS) installdirs: install: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) clean-generic: distclean-generic: -rm -f $(CONFIG_CLEAN_FILES) -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) clean: clean-am clean-am: clean-generic clean-noinstLIBRARIES clean-noinstPROGRAMS \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: info: info-am info-am: install-data-am: install-exec-am: install-info: install-info-am install-man: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-info-am .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ clean-noinstLIBRARIES clean-noinstPROGRAMS ctags distclean \ distclean-compile distclean-generic distclean-tags distdir dvi \ dvi-am info info-am install install-am install-data \ install-data-am install-exec install-exec-am install-info \ install-info-am install-man install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \ uninstall-am uninstall-info-am # Avoid problems with parallel builds. markup-theme-configuration.c: markup-theme-configuration.h # Make everything depend on the `Makefile' and the list parser. $(LIST_STAMP_FILES) : Makefile $(PARSE_LIST_COMMAND) .list.stamp: $(PARSE_LIST_BUILD_RULE) # Since $(LIST_GENERATED_FILES) defined by the includer don't (at # least shouldn't) have any dependencies, if this rule is being # executed, it probably means that one of the files was removed. # Then all we can do is to force rebuilding of corresponding stamp # file, which builds the required sources ``by side-effect.'' # $(LIST_GENERATED_FILES): rm -f $*.stamp; $(MAKE) $(AM_MAKEFLAGS) $*.stamp # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: quarry-0.2.0/src/gui-utils/Makefile.am0000644000175000017500000000253710520514370016247 0ustar bartbart# Process this file with Automake to produce `Makefile.in'. AM_CPPFLAGS = \ -D PACKAGE_DATA_DIR=\"$(pkgdatadir)\" \ \ $(QUARRY_WARNINGS) \ \ -I $(top_srcdir)/src \ -I $(top_srcdir)/src/sgf \ -I $(top_builddir)/src/sgf \ -I $(top_srcdir)/src/board \ -I $(top_builddir)/src/board \ -I $(top_srcdir)/src/utils noinst_LIBRARIES = libguiutils.a LIST_FILES = markup-theme-configuration.list PARSE_LIST_COMMAND = ./parse-configuration$(EXEEXT) PARSE_LIST_FLAGS = # Avoid problems with parallel builds. markup-theme-configuration.c: markup-theme-configuration.h include $(top_srcdir)/build/list.make libguiutils_a_SOURCES = \ configuration.c \ gui-utils.c \ tile-renderer.c \ time-control.c \ \ configuration.h \ gui-utils.h \ tile-renderer.h \ time-control.h \ \ $(LIST_FILES) nodist_libguiutils_a_SOURCES = $(LIST_GENERATED_FILES) BUILT_SOURCES = $(LIST_STAMP_FILES) noinst_PROGRAMS = parse-configuration parse_configuration_SOURCES = parse-configuration.c parse_configuration_LDADD = \ $(top_builddir)/src/utils/libparselist.a \ $(top_builddir)/src/utils/libutils.a EXTRA_DIST = \ common-configuration-sections.list \ common-configuration-values.list \ common-configuration-defaults.list DISTCLEANFILES = *~ MOSTLYCLEANFILES = \ $(LIST_STAMP_FILES) \ $(LIST_GENERATED_FILES) quarry-0.2.0/src/gui-utils/configuration.c0000644000175000017500000005170310521724307017231 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* This file contains run-time code that deals with configuration. It * includes both configuration file parser and writer. The parser is * implemented to be very forgiving. For instance, it just ignores * lines it does not understand and allows random junk at line ends. */ /* FIXME: Clean it up, some functions have become overcomplicated. */ #include "configuration.h" #include "utils.h" #include #include #include /* Cannot use is*() functions since we don't want to depend on the * current locale. */ #define IS_ACCEPTABLE_NAME_CHARACTER(character) \ (('A' <= (character) && (character) <= 'Z') \ || ('a' <= (character) && (character) <= 'z') \ || ('0' <= (character) && (character) <= '9') \ || (character) == '-' || (character) == '+' || (character) == '\'') static const char *configuration_file_intro_comment = "# This is Quarry configuration file.\n#\n" "# You probably don't really want to edit it directly as you can tweak\n" "# all the settings from Quarry itself. However, editing the file is\n" "# absolutely OK, just make sure that its general format is preserved.\n"; static char * parse_string (char **line_scan, char fuzzy_terminator); static int parse_integer (const char *integer_string, int *result); static void write_section (BufferedWriter *writer, const ConfigurationSection *section, const void *section_structure, const char *section_text_field); static void write_string (BufferedWriter *writer, const char *string); void configuration_init (const ConfigurationSection *sections, int num_sections) { int k; assert (sections); for (k = 0; k < num_sections; k++, sections++) { if (!sections->is_repeatable && sections->section_structure_init) sections->section_structure_init (sections->section_structure); } } void configuration_dispose (const ConfigurationSection *sections, int num_sections) { int k; assert (sections); for (k = 0; k < num_sections; k++, sections++) { if (sections->section_structure_dispose) sections->section_structure_dispose (sections->section_structure); } } int configuration_read_from_file (const ConfigurationSection *sections, int num_sections, const char *filename) { FILE *file = fopen (filename, "r"); if (file) { const ConfigurationSection *current_section = NULL; void *current_section_structure = NULL; char *line; while ((line = utils_fgets (file, NULL)) != NULL) { char *scan; int parsing_section_name = 0; for (scan = line; *scan == ' ' || *scan == '\t';) scan++; if (*scan == '[') { do scan++; while (*scan == ' ' || *scan == '\t'); parsing_section_name = 1; } if (IS_ACCEPTABLE_NAME_CHARACTER (*scan)) { const char *name = scan; char *name_pointer = scan; char name_terminating_character; while (1) { do *name_pointer++ = *scan++; while (IS_ACCEPTABLE_NAME_CHARACTER (*scan)); while (*scan == ' ' || *scan == '\t') scan++; if (IS_ACCEPTABLE_NAME_CHARACTER (*scan)) *name_pointer++ = ' '; else break; } name_terminating_character = *scan; *name_pointer = 0; if (!parsing_section_name && name_terminating_character == '=' && current_section) { const ConfigurationValue *value; int k; for (k = 0, value = current_section->values; k < current_section->num_values; k++, value++) { if (strcasecmp (value->name, name) == 0) break; } if (k < current_section->num_values) { void *field = (((char *) current_section_structure) + value->field_offset); scan++; if (value->type & VALUE_TYPE_IS_NULLABLE) { const char *null_scan = scan; int is_null = 0; while (*null_scan == ' ' || *null_scan == '\t') null_scan++; if (strncasecmp (null_scan, "null", 4) == 0) { null_scan += 4; while (*null_scan == ' ' || *null_scan == '\t') null_scan++; if (!*null_scan || *null_scan == '\n' || *null_scan == '\r') { /* FIXME: Not exactly right since we don't always * assign a value below. */ is_null = 1; } } /* FIXME: Not nice. */ * ((int *) (field) - 1) = is_null; } if (! (value->type & VALUE_TYPE_IS_NULLABLE && * ((int *) (field) - 1))) { if ((value->type & ~VALUE_TYPE_IS_NULLABLE) != VALUE_TYPE_STRING_LIST) { char *string = parse_string (&scan, 0); if (string) { if ((value->type & ~VALUE_TYPE_IS_NULLABLE) == VALUE_TYPE_STRING) { utils_free (* (char **) field); * (char **) field = string; } else { char *actual_contents = NULL; char *whitespace_scan; int enumeration_value = 0; for (actual_contents = string; *actual_contents == ' ' || *actual_contents == '\t';) actual_contents++; if ((value->type & ~VALUE_TYPE_IS_NULLABLE) == VALUE_TYPE_ENUMERATION) { const char *value_string; int actual_contents_length; /* Trim trailing whitespace. */ for (whitespace_scan = (actual_contents + (strlen (actual_contents) - 1)); (whitespace_scan >= actual_contents && (*whitespace_scan == ' ' || *whitespace_scan == '\t'));) whitespace_scan--; *(whitespace_scan + 1) = 0; actual_contents_length = ((whitespace_scan + 1) - actual_contents); for (value_string = value->enumeration_values_as_strings, enumeration_value = 0; *value_string; enumeration_value++) { do { int value_string_length = strlen (value_string); if (actual_contents_length == value_string_length && (strcasecmp (actual_contents, value_string) == 0)) { * (int *) field = enumeration_value; goto enumeration_value_found; } value_string += value_string_length + 1; } while (*value_string); value_string++; } } /* Find first whitespace character and break line * at its position. */ for (whitespace_scan = actual_contents; (*whitespace_scan != ' ' && *whitespace_scan != '\t' && *whitespace_scan != 0);) whitespace_scan++; *whitespace_scan = 0; switch (value->type & ~VALUE_TYPE_IS_NULLABLE) { case VALUE_TYPE_BOOLEAN: case VALUE_TYPE_BOOLEAN_WRITE_TRUE_ONLY: if (strcasecmp (actual_contents, "true") == 0 || strcasecmp (actual_contents, "yes") == 0 || strcmp (actual_contents, "1") == 0) * (int *) field = 1; else if (strcasecmp (actual_contents, "false") == 0 || strcasecmp (actual_contents, "no") == 0 || strcmp (actual_contents, "0") == 0) * (int *) field = 0; break; case VALUE_TYPE_INT: parse_integer (actual_contents, (int *) field); break; case VALUE_TYPE_ENUMERATION: { int numeric_value; /* A second attempt, try to parse as numeric * value. Placed separately, because we have * a different `actual_contents' here, more * suited for numeric parsing. */ if (parse_integer (actual_contents, &numeric_value) && 0 <= numeric_value && numeric_value < enumeration_value) * (int *) field = numeric_value; } break; case VALUE_TYPE_REAL: utils_parse_double (actual_contents, (double *) field); break; case VALUE_TYPE_COLOR: { int num_digits; if (*actual_contents == '#') actual_contents++; for (num_digits = 0; ((('0' <= *actual_contents && *actual_contents <= '9') || ('a' <= *actual_contents && *actual_contents <= 'f') || ('A' <= *actual_contents && *actual_contents <= 'F')) && num_digits <= 6); num_digits++) actual_contents++; if (num_digits == 6 || num_digits == 3) { int red; int green; int blue; if (num_digits == 6) { sscanf (actual_contents - 6, "%2x%2x%2x", &red, &green, &blue); } else { sscanf (actual_contents - 3, "%1x%1x%1x", &red, &green, &blue); red *= 0x11; green *= 0x11; blue *= 0x11; } ((QuarryColor *) field)->red = red; ((QuarryColor *) field)->green = green; ((QuarryColor *) field)->blue = blue; } } break; case VALUE_TYPE_TIME: { int seconds = utils_parse_time (actual_contents); if (seconds >= 0) * (int *) field = seconds; } break; default: assert (0); } enumeration_value_found: utils_free (string); } } } else { int first_value = 1; do { char *string = parse_string (&scan, ','); if (string) { if (first_value) { string_list_empty (field); first_value = 0; } string_list_add_ready (field, string); } else break; } while (*scan++ == ','); } } } } else if (parsing_section_name && (name_terminating_character == ']' || name_terminating_character == '"')) { int k; const ConfigurationSection *section; current_section = NULL; for (k = 0, section = sections; k < num_sections; k++, section++) { if (strcasecmp (section->name, name) == 0) break; } if (k < num_sections) { if (section->is_repeatable) { char *section_name = NULL; if (name_terminating_character == '"') { *scan = name_terminating_character; section_name = parse_string (&scan, '"'); } if (*scan == ']') { string_list_add_ready (section->section_structure, section_name); current_section = section; current_section_structure = ((StringList *) section->section_structure)->last; if (section->section_structure_init) section->section_structure_init (current_section_structure); } } else if (!section->is_repeatable && name_terminating_character == ']') { current_section = section; current_section_structure = section->section_structure; } } } } utils_free (line); } fclose (file); return 1; } return 0; } static char * parse_string (char **line_scan, char fuzzy_terminator) { char *buffer = *line_scan; char *buffer_pointer = buffer; while (**line_scan == ' ' || **line_scan == '\t') (*line_scan)++; if (**line_scan == '"') { while (* ++(*line_scan) != '"') { if (**line_scan == '\\') { (*line_scan)++; if (**line_scan == 'n' || **line_scan == '\r') { *buffer_pointer++ = (**line_scan == 'n' ? '\n' : '\r'); continue; } } if (! **line_scan) return NULL; *buffer_pointer++ = **line_scan; } (*line_scan)++; } else { if (fuzzy_terminator != '"') { while (**line_scan && **line_scan != fuzzy_terminator && **line_scan != '#') *buffer_pointer++ = * (*line_scan)++; while (buffer_pointer > buffer && (*(buffer_pointer - 1) == ' ' || *(buffer_pointer - 1) == '\t' || *(buffer_pointer - 1) == '\n' || *(buffer_pointer - 1) == '\r')) buffer_pointer--; } else return NULL; } while (**line_scan == ' ' || **line_scan == '\t') (*line_scan)++; return utils_duplicate_as_string (buffer, buffer_pointer - buffer); } int parse_integer (const char *integer_string, int *result) { /* FIXME: Can be improved. */ const char *digit_scan = integer_string; if (*digit_scan == '+' || *digit_scan == '-') digit_scan++; if ('0' <= *integer_string && *integer_string <= '9') { *result = atoi (integer_string); return 1; } return 0; } int configuration_write_to_file (const ConfigurationSection *sections, int num_sections, const char *filename) { BufferedWriter writer; const char* initialization_error = buffered_writer_init (&writer, filename, 0x1000); if (!initialization_error) { int k; buffered_writer_cat_string (&writer, configuration_file_intro_comment); for (k = 0; k < num_sections; k++, sections++) { if (sections->is_repeatable) { StringList *abstract_list = (StringList *) sections->section_structure; StringListItem *abstract_item; for (abstract_item = abstract_list->first; abstract_item; abstract_item = abstract_item->next) { write_section (&writer, sections, abstract_item, abstract_item->text); } } else write_section (&writer, sections, sections->section_structure, NULL); } if (!writer.successful) { fprintf (stderr, "error writing configuration: %s\n", writer.error_string); } return buffered_writer_dispose (&writer); } else { fprintf (stderr, "error opening configuration file for writing: %s\n", initialization_error); } return 0; } static void write_section (BufferedWriter *writer, const ConfigurationSection *section, const void *section_structure, const char *section_text_field) { const ConfigurationValue *value; int k; buffered_writer_cat_strings (writer, "\n[", section->name, NULL); if (section_text_field) { buffered_writer_add_character (writer, ' '); write_string (writer, section_text_field); } buffered_writer_cat_string (writer, "]\n"); for (k = 0, value = section->values; k < section->num_values; k++, value++) { const void *field = (((const char *) section_structure) + value->field_offset); ConfigurationValueType value_type = value->type; int is_null = 0; if (value_type & VALUE_TYPE_IS_NULLABLE) { /* FIXME: Not nice. */ is_null = (* (((const int *) field) - 1)); value_type &= ~VALUE_TYPE_IS_NULLABLE; } if (!is_null && ((value_type == VALUE_TYPE_STRING && ! * (char *const *) field) || (value_type == VALUE_TYPE_STRING_LIST && string_list_is_empty ((const StringList *) field)) || (value_type == VALUE_TYPE_BOOLEAN_WRITE_TRUE_ONLY && ! * (const int *) field))) continue; buffered_writer_cat_string (writer, value->name); if (writer->column < 24) { do buffered_writer_add_character (writer, '\t'); while (writer->column < 24); } else buffered_writer_add_character (writer, ' '); buffered_writer_cat_string (writer, "= "); if (is_null) buffered_writer_cat_string (writer, "null"); else { switch (value_type) { case VALUE_TYPE_STRING: write_string (writer, * (char *const *) field); break; case VALUE_TYPE_STRING_LIST: { StringListItem *item; for (item = ((const StringList *) field)->first; item; item = item->next) { write_string (writer, item->text); if (item->next) buffered_writer_cat_string (writer, ", "); } } break; case VALUE_TYPE_BOOLEAN: case VALUE_TYPE_BOOLEAN_WRITE_TRUE_ONLY: buffered_writer_cat_string (writer, * (const int *) field ? "true" : "false"); break; case VALUE_TYPE_INT: buffered_writer_cprintf (writer, "%d", * (const int *) field); break; case VALUE_TYPE_ENUMERATION: { const char *value_string; int enumeration_value; for (value_string = value->enumeration_values_as_strings, enumeration_value = * (const int *) field; enumeration_value--; ) { do value_string += strlen (value_string) + 1; while (*value_string); value_string++; } write_string (writer, value_string); } break; case VALUE_TYPE_REAL: buffered_writer_cprintf (writer, "%.f", * (const double *) field); break; case VALUE_TYPE_COLOR: /* I believe this cannot be locale-dependent, right? */ buffered_writer_printf (writer, "\"#%02x%02x%02x\"", ((const QuarryColor *) field)->red, ((const QuarryColor *) field)->green, ((const QuarryColor *) field)->blue); break; case VALUE_TYPE_TIME: if (* (const int *) field < 60 * 60) { buffered_writer_cprintf (writer, "%02d:%02d", (* (const int *) field) / 60, (* (const int *) field) % 60); } else { buffered_writer_cprintf (writer, "%d:%02d:%02d", (* (const int *) field) / (60 * 60), ((* (const int *) field) / 60) % 60, (* (const int *) field) % 60); } break; default: assert (0); } } buffered_writer_add_newline (writer); } } static void write_string (BufferedWriter *writer, const char *string) { buffered_writer_add_character (writer, '"'); while (*string) { if (*string == '\n' || *string == '\r' || *string == '"' || *string == '\\') buffered_writer_add_character (writer, '\\'); const char* utf8_character = string; do string++; while (!IS_UTF8_STARTER (*string)); if (*utf8_character != '\n' && *utf8_character != '\r') { buffered_writer_cat_as_string (writer, utf8_character, string - utf8_character); } else { buffered_writer_add_character (writer, *utf8_character == '\n' ? 'n' : 'r'); } } buffered_writer_add_character (writer, '"'); } void configuration_combine_string_lists (void *main_configuration, void *site_configuration, int tag_field_offset) { StringList *main_configuration_list = (StringList *) main_configuration; StringList *site_configuration_list = (StringList *) site_configuration; StringListItem *main_configuration_item; for (main_configuration_item = main_configuration_list->first; main_configuration_item; ) { /* Required since we may delete some items. */ StringListItem *next_main_configuration_item = main_configuration_item->next; const char *tag = * ((const char **) ((char *) main_configuration_item + tag_field_offset)); if (tag && !string_list_find (site_configuration_list, tag)) { string_list_delete_item (main_configuration_list, main_configuration_item); } main_configuration_item = next_main_configuration_item; } while (!string_list_is_empty (site_configuration_list)) { StringListItem *site_configuration_item = string_list_steal_first_item (site_configuration_list); if (site_configuration_item->text) { for (main_configuration_item = main_configuration_list->first; main_configuration_item; main_configuration_item = main_configuration_item->next) { const char *tag = * ((const char **) ((char *) main_configuration_item + tag_field_offset)); if (tag && strcmp (tag, site_configuration_item->text) == 0) break; } if (!main_configuration_item) { * ((char **) ((char *) site_configuration_item + tag_field_offset)) = utils_duplicate_string (site_configuration_item->text); string_list_add_ready_item (main_configuration_list, site_configuration_item); continue; } } string_list_dispose_item (site_configuration_list, site_configuration_item); } } void configuration_init_repeatable_section (const ConfigurationSection *section, void *abstract_list_item) { assert (section); assert (section->is_repeatable); assert (abstract_list_item); if (section->section_structure_init) section->section_structure_init (abstract_list_item); } void configuration_set_string_value (char **configuration_variable, const char *string) { assert (configuration_variable); utils_free (*configuration_variable); *configuration_variable = utils_duplicate_string (string); } void configuration_set_string_list_value (StringList *configuration_variable, const StringList *string_list) { assert (configuration_variable); assert (string_list); string_list_empty (configuration_variable); string_list_duplicate_items (configuration_variable, string_list); } void configuration_set_string_list_value_steal_strings (StringList *configuration_variable, StringList *string_list) { assert (configuration_variable); assert (string_list); string_list_empty (configuration_variable); string_list_steal_items (configuration_variable, string_list); } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-utils/gui-utils.c0000644000175000017500000001141310367244050016276 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "configuration.h" #include "gui-utils.h" #include "markup-theme-configuration.h" #include "board.h" #include "utils.h" #include #include #include #include /* These will probably cause serious portability problems. Will need * to make dependent on OS. */ #include #include #include #include int gui_utils_enumerate_themes (void) { /* We don't need to initialize themes' configuration sections as * they are all repeatable. */ DIR *markup_themes_directory = opendir (PACKAGE_DATA_DIR "/markup-themes"); struct dirent *directory_entry; if (!markup_themes_directory) { /* FIXME: Add proper i18n at some point (and same below). */ fprintf (stderr, "%s: fatal error: directory `%s' doesn't exist\n", short_program_name, PACKAGE_DATA_DIR); fprintf (stderr, "%s: seems like you need to reinstall me\n", short_program_name); return 0; } while ((directory_entry = readdir (markup_themes_directory)) != NULL) { if (strcmp (directory_entry->d_name, ".") != 0 && strcmp (directory_entry->d_name, "..") != 0) { char *theme_directory = utils_cat_strings (NULL, PACKAGE_DATA_DIR "/markup-themes/", directory_entry->d_name, NULL); struct stat file_statistics; if (stat (theme_directory, &file_statistics) == 0 && S_ISDIR (file_statistics.st_mode)) { char *theme_configuration_file = utils_cat_strings (NULL, theme_directory, "/theme.cfg", NULL); configuration_read_from_file (markup_theme_configuration_sections, NUM_MARKUP_THEME_CONFIGURATION_SECTIONS, theme_configuration_file); if (markup_themes.last && markup_themes.last->directory == NULL) { /* Configuration file has been read and contained a theme * description. We assume that SVG files are in place. */ markup_themes.last->directory = utils_duplicate_string (directory_entry->d_name); } utils_free (theme_configuration_file); } utils_free (theme_directory); } } closedir (markup_themes_directory); if (!string_list_find (&markup_themes, "Default")) { fprintf (stderr, "%s: fatal error: `Default' markup theme not found\n", short_program_name); fprintf (stderr, "%s: seems like you need to reinstall me\n", short_program_name); return 0; } return 1; } void gui_utils_discard_theme_lists (void) { configuration_dispose (markup_theme_configuration_sections, NUM_MARKUP_THEME_CONFIGURATION_SECTIONS); } void gui_utils_mark_variations_on_grid (char grid[BOARD_GRID_SIZE], const Board *board, int black_variations[BOARD_GRID_SIZE], int white_variations[BOARD_GRID_SIZE], char black_variations_mark, char white_variations_mark, char mixed_variations_mark) { int x; int y; assert (grid); assert (board); assert (black_variations); assert (white_variations); for (y = 0; y < board->height; y++) { for (x = 0; x < board->width; x++) { int pos = POSITION (x, y); if (board->grid[pos] == EMPTY) { if (black_variations[pos] > 0) { if (white_variations[pos] > 0) grid[pos] = mixed_variations_mark; else grid[pos] = black_variations_mark; } else { if (white_variations[pos] > 0) grid[pos] = white_variations_mark; } } } } } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-utils/tile-renderer.c0000644000175000017500000004036110367244123017122 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "tile-renderer.h" #include "board.h" #include "utils.h" #include #include #if HAVE_MEMORY_H #include #endif #define SQR(x) ((x) * (x)) const GoStonesParameters go_stones_defaults = { 0.91, 4.0, 4.0, { -0.3, -0.4, 80 }, { { 0.05, 0.55, 0.4, 8.0, { 120, 120, 120 } }, { 0.2, 0.6, 0.2, 10.0, { 255, 240, 220 } } } }; const ReversiDisksParameters reversi_disks_defaults = { 0.91, 0.3, 0.25, { -0.3, -0.4, 80 }, { { 0.05, 0.55, 0.4, 8.0, { 120, 120, 120 } }, { 0.2, 0.6, 0.2, 10.0, { 255, 250, 235 } } } }; /* FIXME: replace with better antialising. */ #define SUPERSAMPLING_FACTOR 4 void render_go_stones (int cell_size, const GoStonesParameters *parameters, unsigned char *black_pixel_data, int black_row_stride, unsigned char *white_pixel_data, int white_row_stride, int *stones_x_offset, int *stones_y_offset) { double stone_radius = 0.5 * parameters->relative_stone_size * cell_size; double stone_radius_in_pixels = (cell_size % 2 == 1 ? ceil (stone_radius - 0.5) + 0.5 : ceil (stone_radius)); double center_x = (parameters->light.dx < 0.0 ? stone_radius_in_pixels : cell_size - stone_radius_in_pixels); double center_y = (parameters->light.dy < 0.0 ? stone_radius_in_pixels : cell_size - stone_radius_in_pixels); double squared_lense_radius = SQR (parameters->lense_radius); double stone_half_height = (parameters->lense_radius - sqrt (squared_lense_radius - 1.0) + 1.0 / parameters->ellipsoid_radius); double light_vector_length = sqrt (SQR (parameters->light.dx) + SQR (parameters->light.dy) + 1.0); double light_dx = parameters->light.dx / light_vector_length; double light_dy = parameters->light.dy / light_vector_length; double light_dz = 1.0 / light_vector_length; double shadow_center_dx = stone_half_height * parameters->light.dx; double shadow_center_dy = stone_half_height * parameters->light.dy; double black_ambiance_level = 255 * parameters->stones[BLACK_INDEX].ambiance_level; double black_diffusion_level = 255 * parameters->stones[BLACK_INDEX].diffusion_level; double black_highlight_level = 255 * parameters->stones[BLACK_INDEX].highlight_level; double white_ambiance_level = 255 * parameters->stones[WHITE_INDEX].ambiance_level; double white_diffusion_level = 255 * parameters->stones[WHITE_INDEX].diffusion_level; double white_highlight_level = 255 * parameters->stones[WHITE_INDEX].highlight_level; int x; int y; for (y = 0; y < cell_size; y++) { for (x = 0; x < cell_size; x++) { int x_subpixel; int y_subpixel; double black_intensity = 0.0; double white_intensity = 0.0; int opacity = 0; for (y_subpixel = 1; y_subpixel < 2 * SUPERSAMPLING_FACTOR; y_subpixel += 2) { double dy = (((y - center_y) + y_subpixel / (double) (2 * SUPERSAMPLING_FACTOR)) / stone_radius); for (x_subpixel = 1; x_subpixel < 2 * SUPERSAMPLING_FACTOR; x_subpixel += 2) { double dx = (((x - center_x) + x_subpixel / (double) (2 * SUPERSAMPLING_FACTOR)) / stone_radius); double squared_r = SQR (dx) + SQR (dy); if (squared_r >= 1.0) { if (SQR (dx + shadow_center_dx) + SQR (dy + shadow_center_dy) <= 1.0) opacity += parameters->light.shadow_level; continue; } else { double A = sqrt (squared_lense_radius - squared_r); double B = parameters->ellipsoid_radius * sqrt (1.0 - squared_r); double dz = (A * B) / (A + B); double normal_length = sqrt (squared_r + SQR (dz)); double cos_alpha = ((dx * light_dx + dy * light_dy + dz * light_dz) / normal_length); if (cos_alpha > 0.0) { double cos_beta = (2.0 * ((dz / normal_length) * cos_alpha) - light_dz); if (cos_beta > 0.0) { black_intensity += (black_highlight_level * pow (cos_beta, (parameters ->stones[BLACK_INDEX].highlight_sharpness))); white_intensity += (white_highlight_level * pow (cos_beta, (parameters ->stones[WHITE_INDEX].highlight_sharpness))); } black_intensity += (black_ambiance_level + black_diffusion_level * cos_alpha); white_intensity += (white_ambiance_level + white_diffusion_level * cos_alpha); } } opacity += 255; } } if (opacity) { black_intensity /= opacity; white_intensity /= opacity; opacity /= SQR (SUPERSAMPLING_FACTOR); *black_pixel_data++ = MIN ((parameters->stones[BLACK_INDEX].color.red * black_intensity), 255); *black_pixel_data++ = MIN ((parameters->stones[BLACK_INDEX].color.green * black_intensity), 255); *black_pixel_data++ = MIN ((parameters->stones[BLACK_INDEX].color.blue * black_intensity), 255); *black_pixel_data++ = opacity; *white_pixel_data++ = MIN ((parameters->stones[WHITE_INDEX].color.red * white_intensity), 255); *white_pixel_data++ = MIN ((parameters->stones[WHITE_INDEX].color.green * white_intensity), 255); *white_pixel_data++ = MIN ((parameters->stones[WHITE_INDEX].color.blue * white_intensity), 255); *white_pixel_data++ = opacity; } else { *black_pixel_data++ = 0; *black_pixel_data++ = 0; *black_pixel_data++ = 0; *black_pixel_data++ = 0; *white_pixel_data++ = 0; *white_pixel_data++ = 0; *white_pixel_data++ = 0; *white_pixel_data++ = 0; } } black_pixel_data += black_row_stride - 4 * cell_size; white_pixel_data += white_row_stride - 4 * cell_size; } *stones_x_offset = - (int) (center_x - 0.5); *stones_y_offset = - (int) (center_y - 0.5); } void render_reversi_disks (int cell_size, const ReversiDisksParameters *parameters, unsigned char *black_pixel_data, int black_row_stride, unsigned char *white_pixel_data, int white_row_stride, int *disks_x_offset, int *disks_y_offset) { double disk_radius = 0.5 * parameters->relative_disk_size * cell_size; double disk_radius_in_pixels = (cell_size % 2 == 1 ? ceil (disk_radius - 0.5) + 0.5 : ceil (disk_radius)); double disk_flat_part_radius = 1.0 - parameters->border_curve_size; double center_x = (parameters->light.dx < 0.0 ? disk_radius_in_pixels : cell_size - disk_radius_in_pixels); double center_y = (parameters->light.dy < 0.0 ? disk_radius_in_pixels : cell_size - disk_radius_in_pixels); double light_vector_length = sqrt (SQR (parameters->light.dx) + SQR (parameters->light.dy) + 1.0); double light_dx = parameters->light.dx / light_vector_length; double light_dy = parameters->light.dy / light_vector_length; double light_dz = 1.0 / light_vector_length; double shadow_center_dx = (parameters->height_to_diameter_ratio * parameters->light.dx); double shadow_center_dy = (parameters->height_to_diameter_ratio * parameters->light.dy); double black_ambiance_level = 255 * parameters->disks[BLACK_INDEX].ambiance_level; double black_diffusion_level = 255 * parameters->disks[BLACK_INDEX].diffusion_level; double black_highlight_level = 255 * parameters->disks[BLACK_INDEX].highlight_level; double black_flat_part_intensity = (black_ambiance_level + (black_diffusion_level * light_dz) + (black_highlight_level * pow (light_dz, parameters->disks[BLACK_INDEX].highlight_sharpness))); double white_ambiance_level = 255 * parameters->disks[WHITE_INDEX].ambiance_level; double white_diffusion_level = 255 * parameters->disks[WHITE_INDEX].diffusion_level; double white_highlight_level = 255 * parameters->disks[WHITE_INDEX].highlight_level; double white_flat_part_intensity = (white_ambiance_level + (white_diffusion_level * light_dz) + (white_highlight_level * pow (light_dz, parameters->disks[WHITE_INDEX].highlight_sharpness))); int x; int y; for (y = 0; y < cell_size; y++) { for (x = 0; x < cell_size; x++) { int x_subpixel; int y_subpixel; double black_intensity = 0.0; double white_intensity = 0.0; int opacity = 0; for (y_subpixel = 1; y_subpixel < 2 * SUPERSAMPLING_FACTOR; y_subpixel += 2) { double dy = (((y - center_y) + y_subpixel / (double) (2 * SUPERSAMPLING_FACTOR)) / disk_radius); for (x_subpixel = 1; x_subpixel < 2 * SUPERSAMPLING_FACTOR; x_subpixel += 2) { double dx = (((x - center_x) + x_subpixel / (double) (2 * SUPERSAMPLING_FACTOR)) / disk_radius); double squared_r = SQR (dx) + SQR (dy); if (squared_r >= 1.0) { if (SQR (dx + shadow_center_dx) + SQR (dy + shadow_center_dy) <= 1.0) opacity += parameters->light.shadow_level; continue; } else { double r = sqrt (squared_r); if (r <= disk_flat_part_radius) { black_intensity += black_flat_part_intensity; white_intensity += white_flat_part_intensity; } else { double dr = r - disk_flat_part_radius; double dx_scaled = dx * dr / r; double dy_scaled = dy * dr / r; double dz = (parameters->height_to_diameter_ratio * sqrt (1.0 - SQR (dr / parameters->border_curve_size))); double normal_length = sqrt (SQR (dr) + SQR (dz)); double cos_alpha = ((dx_scaled * light_dx + dy_scaled * light_dy + dz * light_dz) / normal_length); if (cos_alpha > 0.0) { double cos_beta = (2.0 * ((dz / normal_length) * cos_alpha) - light_dz); if (cos_beta > 0.0) { black_intensity += (black_highlight_level * pow (cos_beta, (parameters ->disks[BLACK_INDEX].highlight_sharpness))); white_intensity += (white_highlight_level * pow (cos_beta, (parameters ->disks[WHITE_INDEX].highlight_sharpness))); } black_intensity += (black_ambiance_level + black_diffusion_level * cos_alpha); white_intensity += (white_ambiance_level + white_diffusion_level * cos_alpha); } } } opacity += 255; } } if (opacity) { black_intensity /= opacity; white_intensity /= opacity; opacity /= SQR (SUPERSAMPLING_FACTOR); *black_pixel_data++ = MIN ((parameters->disks[BLACK_INDEX].color.red * black_intensity), 255); *black_pixel_data++ = MIN ((parameters->disks[BLACK_INDEX].color.green * black_intensity), 255); *black_pixel_data++ = MIN ((parameters->disks[BLACK_INDEX].color.blue * black_intensity), 255); *black_pixel_data++ = opacity; *white_pixel_data++ = MIN ((parameters->disks[WHITE_INDEX].color.red * white_intensity), 255); *white_pixel_data++ = MIN ((parameters->disks[WHITE_INDEX].color.green * white_intensity), 255); *white_pixel_data++ = MIN ((parameters->disks[WHITE_INDEX].color.blue * white_intensity), 255); *white_pixel_data++ = opacity; } else { *black_pixel_data++ = 0; *black_pixel_data++ = 0; *black_pixel_data++ = 0; *black_pixel_data++ = 0; *white_pixel_data++ = 0; *white_pixel_data++ = 0; *white_pixel_data++ = 0; *white_pixel_data++ = 0; } } black_pixel_data += black_row_stride - 4 * cell_size; white_pixel_data += white_row_stride - 4 * cell_size; } *disks_x_offset = - (int) (center_x - 0.5); *disks_y_offset = - (int) (center_y - 0.5); } /* Make a copy of given pixel data, but with changed alpha channel * (opacity). Alpha value is first multiplied by `alpha_up' and then * divided by `alpha_down' (which must be larger). So, this function * can only be used to make a more transparent copy of the pixels. */ unsigned char * duplicate_and_adjust_alpha (int alpha_up, int alpha_down, int width, int height, unsigned char *pixel_data, int row_stride) { unsigned char *new_pixel_data = utils_malloc (height * row_stride); unsigned char *scan; int x; int y; assert (0 < alpha_up && alpha_up < alpha_down); assert (width > 0 && height > 0); assert (pixel_data); assert (row_stride >= 4 * width); for (scan = new_pixel_data, y = 0; y < height; y++) { for (x = 0; x < width; x++) { /* Simply copy color values. */ *scan++ = *pixel_data++; *scan++ = *pixel_data++; *scan++ = *pixel_data++; /* And adjust alpha. */ *scan++ = (alpha_up * ((int) *pixel_data++)) / alpha_down; } pixel_data += row_stride - 4 * width; scan += row_stride - 4 * width; } return new_pixel_data; } /* Make a colored copy of given monochrome pixel data, possibly making * the copy more transparent in process. The input should contain * only shades of gray. All pixels in the output have the same * `color' and varying opacity with black in input converted to fully * transparent pixels and white---to fully opaque. In addition, * opacity may be scaled down as in duplicate_and_adjust_alpha(), but * saturate_and_set_alpha() allows `alpha_up' equal to `alpha_down'. * * This function's main purpose is to replace background in * prerendered text with transparency, something that cannot be done * easily with X at present. */ unsigned char * saturate_and_set_alpha (QuarryColor color, int alpha_up, int alpha_down, int width, int height, unsigned char *pixel_data, int row_stride) { unsigned char *new_pixel_data = utils_malloc (height * row_stride); unsigned char *scan; int x; int y; assert (0 < alpha_up && alpha_up <= alpha_down); assert (width > 0 && height > 0); assert (pixel_data); assert (row_stride >= 4 * width); for (scan = new_pixel_data, y = 0; y < height; y++) { for (x = 0; x < width; x++) { /* Fill the color bytes. */ *scan++ = color.red; *scan++ = color.green; *scan++ = color.blue; /* Set and scale alpha channel. We actually only use the Red * channel in input for this, but the caller shouldn't assume * this behavior. */ *scan++ = (alpha_up * ((int) *pixel_data)) / alpha_down; pixel_data += 4; } pixel_data += row_stride - 4 * width; scan += row_stride - 4 * width; } return new_pixel_data; } /* Combine two square images into one: the first is placed in the * lower-right corner, the second---in the upper-left. */ unsigned char * combine_pixels_diagonally (int image_size, unsigned char *first_pixel_data, unsigned char *second_pixel_data, int row_stride) { unsigned char *new_pixel_data = utils_malloc (image_size * row_stride); unsigned char *scan; int y; assert (image_size > 0); assert (first_pixel_data); assert (second_pixel_data); assert (row_stride >= 4 * image_size); for (scan = new_pixel_data, y = 0; y < image_size; y++) { int left_sub_line_size = 4 * (image_size - y - 1); /* FIXME: blend at the diagonal. */ memcpy (scan, second_pixel_data, 4 * left_sub_line_size); memcpy (scan + left_sub_line_size, first_pixel_data + left_sub_line_size, 4 * (y + 1)); first_pixel_data += row_stride; second_pixel_data += row_stride; scan += row_stride; } return new_pixel_data; } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-utils/time-control.c0000644000175000017500000003104310453257104016771 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "time-control.h" #include "sgf.h" #include "utils.h" #include #include #include #include TimeControl * time_control_new (int main_time, int overtime_length, int moves_per_overtime) { TimeControl *time_control = utils_malloc (sizeof (TimeControl)); time_control_init (time_control, main_time, overtime_length, moves_per_overtime); return time_control; } TimeControl * time_control_new_from_sgf_node (const SgfNode *sgf_node) { double main_time = 0.0; const char *overtime_description; int overtime_length = 0; int moves_per_overtime = 0; sgf_node_get_time_limit (sgf_node, &main_time); overtime_description = sgf_node_get_text_property_value (sgf_node, SGF_OVERTIME); if (overtime_description) { /* FIXME: Nasty. We certainly need utils_sscanf() for * locale-independent string parsing. */ const char *scan; for (scan = overtime_description; '0' <= *scan && *scan <= '9'; scan++) overtime_length = overtime_length * 10 + (*scan - '0'); if (overtime_length > 0) { if (strcmp (scan, " per move") == 0) moves_per_overtime = 1; else if (*scan++ == '/') { moves_per_overtime = overtime_length; overtime_length = 0; for (; '0' <= *scan && *scan <= '9'; scan++) overtime_length = overtime_length * 10 + (*scan - '0'); if (overtime_length == 0 || strcmp (scan, " Canadian") != 0) { overtime_length = 0; moves_per_overtime = 0; } } else overtime_length = 0; } } if (main_time > 0 || overtime_length > 0) return time_control_new (main_time, overtime_length, moves_per_overtime); return NULL; } /* Note that this function only duplicates the settings, not the * state of its argument. */ inline TimeControl * time_control_duplicate (const TimeControl *time_control) { return time_control_new (time_control->main_time, time_control->overtime_length, time_control->moves_per_overtime); } void time_control_init (TimeControl *time_control, int main_time, int overtime_length, int moves_per_overtime) { assert (time_control); assert (main_time >= 0 && overtime_length >= 0 && moves_per_overtime >= 0 && (overtime_length == 0 || moves_per_overtime > 0)); time_control->main_time = main_time; time_control->overtime_length = overtime_length; time_control->moves_per_overtime = moves_per_overtime; time_control->seconds_elapsed = 0.0; time_control->moves_to_play = (main_time > 0 || overtime_length == 0 ? 0 : moves_per_overtime); time_control->timer_object = NULL; time_control->is_active = 0; } void time_control_delete (TimeControl *time_control) { time_control_dispose (time_control); utils_free (time_control); } void time_control_dispose (TimeControl *time_control) { assert (time_control); if (time_control->timer_object) gui_back_end_timer_delete (time_control->timer_object); } void time_control_save_settings_in_sgf_node (const TimeControl *time_control, SgfNode *sgf_node, SgfGameTree *sgf_tree, int side_effect) { assert (time_control); assert (sgf_node); assert (sgf_tree); if (time_control->main_time > 0.0 || time_control->overtime_length > 0.0) { char *overtime_description; if (time_control->overtime_length == 0) overtime_description = utils_duplicate_string ("none"); else if (time_control->moves_per_overtime == 1) { overtime_description = utils_cprintf ("%d per move", time_control->overtime_length); } else { overtime_description = utils_cprintf ("%d/%d Canadian", time_control->moves_per_overtime, time_control->overtime_length); } sgf_utils_set_text_property (sgf_node, sgf_tree, SGF_TIME_LIMIT, utils_cprintf ("%d.0", time_control->main_time), side_effect); sgf_utils_set_text_property (sgf_node, sgf_tree, SGF_OVERTIME, overtime_description, side_effect); } } void time_control_save_state_in_sgf_node (const TimeControl *time_control, SgfNode *sgf_node, SgfGameTree *sgf_tree, int color, int side_effect) { double seconds_left; int moves_to_play; assert (time_control); assert (!time_control->is_active); if (!TIME_CONTROL_CLOCK_RUNS_DOWN (time_control)) return; seconds_left = time_control_get_time_left (time_control, &moves_to_play); sgf_utils_set_time_left (sgf_node, sgf_tree, color, floor (seconds_left * 1000.0 + 0.5) / 1000.0, moves_to_play, side_effect); } void time_control_apply_defaults_if_needed (const TimeControl *time_control, double seconds_left, int moves_to_play, double *new_seconds_left, int *new_moves_to_play) { assert (time_control); assert (new_seconds_left); assert (new_moves_to_play); if (seconds_left >= 0.0) *new_seconds_left = seconds_left; else { *new_seconds_left = (time_control->main_time > 0 ? time_control->main_time : time_control->overtime_length); } if (moves_to_play >= 0) *new_moves_to_play = moves_to_play; else { *new_moves_to_play = (time_control->main_time > 0 ? 0 : time_control->moves_per_overtime); } } /* FIXME: Validate new state. */ void time_control_set_state (TimeControl *time_control, double seconds_left, int moves_to_play) { double new_seconds_left; assert (time_control); assert (!time_control->is_active); time_control_apply_defaults_if_needed (time_control, seconds_left, moves_to_play, &new_seconds_left, &time_control->moves_to_play); if (time_control->moves_to_play) { time_control->seconds_elapsed = (time_control->overtime_length - new_seconds_left); } else { time_control->seconds_elapsed = (time_control->main_time - new_seconds_left); } } /* Start timer (time control object's owner is about to play a move). * Return (positive) number of seconds within which a move absolutely * has to be played, or the player loses on time. If the player is * already out of time, return `OUT_OF_TIME'. When there are no time * limits, return `NO_TIME_LIMITS'. */ double time_control_start (TimeControl *time_control) { double time_remaining; assert (time_control); assert (!time_control->is_active); time_control->timer_object = gui_back_end_timer_restart (time_control->timer_object); time_control->is_active = 1; if (time_control->moves_to_play == 0) { if (time_control->main_time == 0) return NO_TIME_LIMITS; time_remaining = ((double) time_control->main_time + (double) time_control->overtime_length - time_control->seconds_elapsed); } else { time_remaining = (((double) time_control->overtime_length - time_control->seconds_elapsed)); } return (time_remaining > 0.0 ? time_remaining : OUT_OF_TIME); } /* Get the number of seconds the clock should show and, optionally, * number of moves to be played in the current overtime pediod. If * the number of seconds is negative or zero, then the player has lost * on time. If the number of moves to be played is zero, then the * player is currently in main time, not in his overtime period. */ double time_control_get_clock_seconds (const TimeControl *time_control, int *moves_to_play) { double seconds_elapsed; assert (time_control); seconds_elapsed = time_control->seconds_elapsed; if (time_control->is_active) { seconds_elapsed += gui_back_end_timer_get_seconds_elapsed (time_control->timer_object); } if (moves_to_play) *moves_to_play = time_control->moves_to_play; if (time_control->moves_to_play == 0) { if (time_control->main_time > 0) { double result = (double) time_control->main_time - seconds_elapsed; if (result <= 0.0) { if (moves_to_play) *moves_to_play = time_control->moves_per_overtime; result += (double) time_control->overtime_length; } return result; } return seconds_elapsed; } else return (double) time_control->overtime_length - seconds_elapsed; } /* Stop timer (a move has been played) and update internals * accordingly. Return value and parameters are as for * time_control_get_clock_seconds(). */ double time_control_stop (TimeControl *time_control, int *moves_to_play) { assert (time_control); assert (time_control->is_active); time_control->seconds_elapsed += gui_back_end_timer_get_seconds_elapsed (time_control->timer_object); time_control->is_active = 0; if (time_control->moves_to_play == 0) { if (time_control->seconds_elapsed < (double) time_control->main_time || time_control->overtime_length == 0) { if (moves_to_play) *moves_to_play = 0; if (time_control->main_time > 0) { return ((double) time_control->main_time - time_control->seconds_elapsed); } else return time_control->seconds_elapsed; } time_control->seconds_elapsed -= (double) time_control->main_time; time_control->moves_to_play = time_control->moves_per_overtime; } if (--time_control->moves_to_play == 0) { if (time_control->seconds_elapsed < (double) time_control->overtime_length) time_control->seconds_elapsed = 0.0; time_control->moves_to_play = time_control->moves_per_overtime; } if (moves_to_play) *moves_to_play = time_control->moves_to_play; return ((double) time_control->overtime_length - time_control->seconds_elapsed); } double time_control_get_time_left (const TimeControl *time_control, int *moves_to_play) { double time_remaining; assert (time_control); assert (!time_control->is_active); if (moves_to_play) *moves_to_play = time_control->moves_to_play; if (time_control->moves_to_play == 0) { if (time_control->main_time == 0) return NO_TIME_LIMITS; time_remaining = ((double) time_control->main_time - time_control->seconds_elapsed); } else { time_remaining = ((double) time_control->overtime_length - time_control->seconds_elapsed); } return (time_remaining > 0.0 ? time_remaining : OUT_OF_TIME); } /* NOTE: this function assumes that seconds displayed are * * ceil (time_control_get_clock_seconds (...)) */ double time_control_get_time_till_seconds_update (const TimeControl *time_control) { double seconds_elapsed; assert (time_control); seconds_elapsed = time_control->seconds_elapsed; if (time_control->is_active) { seconds_elapsed += gui_back_end_timer_get_seconds_elapsed (time_control->timer_object); } return (ceil (seconds_elapsed + (TIME_CONTROL_CLOCK_RUNS_DOWN (time_control) ? DBL_EPSILON : 0.0)) - seconds_elapsed); } int time_control_is_short_on_time (const TimeControl *time_control) { double seconds_elapsed; double seconds_left; assert (time_control); if (!TIME_CONTROL_CLOCK_RUNS_DOWN (time_control)) return 0; seconds_elapsed = time_control->seconds_elapsed; if (time_control->is_active) { seconds_elapsed += gui_back_end_timer_get_seconds_elapsed (time_control->timer_object); } if (time_control->moves_to_play == 0) { seconds_left = (((double) time_control->main_time - seconds_elapsed) + (double) time_control->overtime_length); } else seconds_left = (double) time_control->overtime_length - seconds_elapsed; return 0.0 < seconds_left && seconds_left <= 30.0; } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-utils/configuration.h0000644000175000017500000000703610367244027017242 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef QUARRY_CONFIGURATION_H #define QUARRY_CONFIGURATION_H #include "utils.h" #include "quarry.h" typedef enum { VALUE_TYPE_INVALID = -1, VALUE_TYPE_STRING = 0, VALUE_TYPE_STRING_LIST, VALUE_TYPE_BOOLEAN, VALUE_TYPE_BOOLEAN_WRITE_TRUE_ONLY, VALUE_TYPE_INT, VALUE_TYPE_ENUMERATION, VALUE_TYPE_REAL, VALUE_TYPE_COLOR, VALUE_TYPE_TIME, NUM_VALUE_TYPES, VALUE_TYPE_IS_NULLABLE = 0x8000 } ConfigurationValueType; typedef struct _ConfigurationSection ConfigurationSection; typedef struct _ConfigurationValue ConfigurationValue; struct _ConfigurationSection { const char *name; int is_repeatable; void *section_structure; void (* section_structure_init) (void *section_structure); void (* section_structure_dispose) (void *section_structure); const ConfigurationValue *values; int num_values; }; struct _ConfigurationValue { const char *name; ConfigurationValueType type; int field_offset; /* Used only for `VALUE_TYPE_ENUMERATION'. */ const char *enumeration_values_as_strings; }; void configuration_init (const ConfigurationSection *sections, int num_sections); void configuration_dispose (const ConfigurationSection *sections, int num_sections); int configuration_read_from_file (const ConfigurationSection *sections, int num_sections, const char *filename); int configuration_write_to_file (const ConfigurationSection *sections, int num_sections, const char *filename); void configuration_combine_string_lists (void *main_configuration, void *site_configuration, int tag_field_offset); void configuration_init_repeatable_section (const ConfigurationSection *section, void *abstract_list_item); void configuration_set_string_value (char **configuration_variable, const char *string); void configuration_set_string_list_value (StringList *configuration_variable, const StringList *string_list); void configuration_set_string_list_value_steal_strings (StringList *configuration_variable, StringList *string_list); #endif /* QUARRY_CONFIGURATION_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-utils/gui-utils.h0000644000175000017500000000363710367244060016315 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef QUARRY_GUI_UTILS_H #define QUARRY_GUI_UTILS_H #include "board.h" #include "quarry.h" int gui_utils_enumerate_themes (void); void gui_utils_discard_theme_lists (void); void gui_utils_mark_variations_on_grid (char grid[BOARD_GRID_SIZE], const Board *board, int black_variations[BOARD_GRID_SIZE], int white_variations[BOARD_GRID_SIZE], char black_variations_mark, char white_variations_mark, char mixed_variations_mark); #endif /* QUARRY_GUI_UTILS_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-utils/tile-renderer.h0000644000175000017500000000746710367244130017137 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef QUARRY_TILE_RENDERER_H #define QUARRY_TILE_RENDERER_H #include "board.h" #include "utils.h" #include "quarry.h" typedef struct _PieceParameters PieceParameters; typedef struct _LightParameters LightParameters; typedef struct _GoStonesParameters GoStonesParameters; typedef struct _ReversiDisksParameters ReversiDisksParameters; struct _PieceParameters { double ambiance_level; double diffusion_level; double highlight_level; double highlight_sharpness; QuarryColor color; }; struct _LightParameters { double dx; double dy; int shadow_level; }; struct _GoStonesParameters { /* Go-specific fields, describing shape of stones. */ double relative_stone_size; double lense_radius; double ellipsoid_radius; LightParameters light; PieceParameters stones[NUM_COLORS]; }; struct _ReversiDisksParameters { /* Reversi-specific fields, describing shape of disks. */ double relative_disk_size; double height_to_diameter_ratio; double border_curve_size; LightParameters light; PieceParameters disks[NUM_COLORS]; }; /* FIXME: Will need to be removed or replaced with configuration * variables. */ extern const GoStonesParameters go_stones_defaults; extern const ReversiDisksParameters reversi_disks_defaults; void render_go_stones (int cell_size, const GoStonesParameters *parameters, unsigned char *black_pixel_data, int black_row_stride, unsigned char *white_pixel_data, int white_row_stride, int *stones_x_offset, int *stones_y_offset); void render_reversi_disks (int cell_size, const ReversiDisksParameters *parameters, unsigned char *black_pixel_data, int black_row_stride, unsigned char *white_pixel_data, int white_row_stride, int *disks_x_offset, int *disks_y_offset); unsigned char * duplicate_and_adjust_alpha (int alpha_up, int alpha_down, int width, int height, unsigned char *pixel_data, int row_stride); unsigned char * saturate_and_set_alpha (QuarryColor color, int alpha_up, int alpha_down, int width, int height, unsigned char *pixel_data, int row_stride); unsigned char * combine_pixels_diagonally (int image_size, unsigned char *first_pixel_data, unsigned char *second_pixel_data, int row_stride); #endif /* QUARRY_TILE_RENDERER_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-utils/time-control.h0000644000175000017500000000745410453257121017006 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef QUARRY_TIME_CONTROL_H #define QUARRY_TIME_CONTROL_H #include "sgf.h" #include "quarry.h" #define OUT_OF_TIME (-1.0) #define NO_TIME_LIMITS 0.0 #define TIME_CONTROL_CLOCK_RUNS_DOWN(time_control) \ ((time_control)->main_time > 0 \ || (time_control)->overtime_length > 0) typedef struct _TimeControl TimeControl; struct _TimeControl { int main_time; int overtime_length; int moves_per_overtime; double seconds_elapsed; int moves_to_play; void *timer_object; int is_active; }; TimeControl * time_control_new (int main_time, int overtime_length, int moves_per_overtime); TimeControl * time_control_new_from_sgf_node (const SgfNode *sgf_node); inline TimeControl * time_control_duplicate (const TimeControl *time_control); void time_control_init (TimeControl *time_control, int main_time, int overtime_length, int moves_per_overtime); void time_control_delete (TimeControl *time_control); void time_control_dispose (TimeControl *time_control); void time_control_save_settings_in_sgf_node (const TimeControl *time_control, SgfNode *sgf_node, SgfGameTree *sgf_tree, int side_effect); void time_control_save_state_in_sgf_node (const TimeControl *time_control, SgfNode *sgf_node, SgfGameTree *sgf_tree, int color, int side_effect); void time_control_apply_defaults_if_needed (const TimeControl *time_control, double seconds_left, int moves_to_play, double *new_seconds_left, int *new_moves_to_play); void time_control_set_state (TimeControl *time_control, double seconds_left, int moves_to_play); double time_control_start (TimeControl *time_control); double time_control_get_clock_seconds (const TimeControl *time_control, int *moves_to_play); double time_control_stop (TimeControl *time_control, int *moves_to_play); double time_control_get_time_left (const TimeControl *time_control, int *moves_to_play); double time_control_get_time_till_seconds_update (const TimeControl *time_control); int time_control_is_short_on_time (const TimeControl *time_control); /* GUI back-end specific functions (don't belong to GUI utils.) */ void * gui_back_end_timer_restart (void *timer_object); void gui_back_end_timer_delete (void *timer_object); double gui_back_end_timer_get_seconds_elapsed (void *timer_object); #endif /* QUARRY_TIME_CONTROL_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-utils/markup-theme-configuration.list0000644000175000017500000000424010520515314022344 0ustar bartbart# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # This file is part of Quarry # # # # Copyright (C) 2004, 2005, 2006 Paul Pogonyshev. # # # # 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 2 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, write to the Free # # Software Foundation, Inc., 51 Franklin Street, Fifth Floor, # # Boston, MA 02110-1301, USA. # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # @mode configuration @h_include "configuration.h" @h_include "utils.h" @c_include "markup-theme-configuration.h" @c_include "utils.h" section_list unnamed markup_theme_configuration_sections { SECTION_MARKUP_THEME "Markup Theme" repeatable new MarkupThemeList name markup_theme_list STATIC_MARKUP_THEME_LIST markup_themes markup_theme_configuration_section_values markup_theme_configuration_defaults + NUM_MARKUP_THEME_CONFIGURATION_SECTIONS } values - markup_theme_configuration_section_values { "Default markup size" default_size real "Size is relative" size_is_relative boolean "Default opacity" default_opacity real } defaults - markup_theme_configuration_defaults { directory string NULL default_size real 0.65 size_is_relative boolean true default_opacity real 1.0 } quarry-0.2.0/src/gui-utils/parse-configuration.c0000644000175000017500000013335210376703276020354 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "configuration.h" #include "parse-list.h" #include "utils.h" #include #include #include #define VALUE_TYPE_STRUCTURE NUM_VALUE_TYPES typedef struct _SectionData SectionData; struct _SectionData { const char *section_name; int is_repeatable; int is_new_structure; const char *structure_type; const char *structure_name; const char *dispose_function_name; const char *static_list_macro; const char *list_text_field_name; const char *list_function_prefix; }; typedef struct _SectionArrayListItem SectionArrayListItem; typedef struct _SectionArrayList SectionArrayList; struct _SectionArrayListItem { SectionArrayListItem *next; char *array; SectionData section_data; }; struct _SectionArrayList { SectionArrayListItem *first; SectionArrayListItem *last; int item_size; StringListItemDispose item_dispose; }; #define section_array_list_new() \ string_list_new_derived (sizeof (SectionArrayListItem), NULL) #define section_array_list_init(list) \ string_list_init_derived ((list), sizeof (SectionArrayListItem), \ NULL) #define STATIC_SECTION_ARRAY_LIST \ STATIC_STRING_LIST_DERIVED (SectionArrayListItem, NULL) #define section_array_list_get_item(list, item_index) \ ((SectionArrayListItem *) string_list_get_item ((list), \ (item_index))) #define section_array_list_find(list, array) \ ((SectionArrayListItem *) string_list_find ((list), (array))) #define section_array_list_find_after_notch(list, array, notch) \ ((SectionArrayListItem *) \ string_list_find_after_notch ((list), (array), (notch))) typedef struct _SubscriptionStackItem SubscriptionStackItem; struct _SubscriptionStackItem { SubscriptionStackItem *previous; const char *field_name_part; int is_array_subscription; ConfigurationValueType array_element_type; int num_array_dimensions; int declaring_new_structure; StringBuffer structure_declaration; StringBuffer dispose_function; const char *structure_type; const char *dispose_function_name; }; static int configuration_initialize_sections (StringBuffer *c_file_arrays, const char *h_file_enum_name, const char *c_file_array_name); static int configuration_parse_sections2 (StringBuffer *c_file_arrays, char **line, const char *identifier, char **pending_eol_comment, int *pending_linefeeds); static int configuration_initialize_values (StringBuffer *c_file_arrays, const char *h_file_enum_name, const char *c_file_array_name); static int configuration_parse_values2 (StringBuffer *c_file_arrays, char **line, const char *identifier, char **pending_eol_comment, int *pending_linefeeds); static int configuration_initialize_defaults (StringBuffer *c_file_arrays, const char *h_file_enum_name, const char *c_file_array_name); static int configuration_parse_defaults2 (StringBuffer *c_file_arrays, char **line, const char *identifier, char **pending_eol_comment, int *pending_linefeeds); static int configuration_finalize_defaults (StringBuffer *c_file_arrays); static int configuration_finalize (StringBuffer *c_file_arrays); static ConfigurationValueType look_at_field_type (char **line); static int section_datum_equal (const SectionData *first_data, const SectionData *second_data); static void push_subscription_stack (int is_array_subscription, int is_new_structure, int do_start_structure_declaration, const char *structure_type, const char *dispose_function_name); static SubscriptionStackItem * pop_subscription_stack (int do_write_dispose_function_prototype); static void recursively_build_full_field_name (const SubscriptionStackItem *stack_item, char **full_field_name); static void add_field_declaration_if_needed (SubscriptionStackItem *stack_item, ConfigurationValueType field_type, const char *field_name, const char *structure_type, const char *array_dimensions); static void add_field_dispose_call_if_needed (SubscriptionStackItem *stack_item, const char *dispose_field_function, const char *dispose_field_prefix, const char *field_name); static void open_initialization_braces (int num_levels); static void close_initialization_braces (int num_levels); static void add_initialization_indentation (int indentation_level); static void finish_function (StringBuffer *prototypes_buffer, const char *function_name, const char *function_name_suffix, int function_defined, int *last_function_defined); static const ListDescription configuration_lists[] = { { "section_list", 0, SORT_LAST, 1, "const ConfigurationSection ", configuration_initialize_sections, NULL, configuration_parse_sections2, NULL }, { "values", 1, SORT_NORMAL, 0, "static const ConfigurationValue ", configuration_initialize_values, NULL, configuration_parse_values2, NULL }, { "defaults", 1, SORT_FIRST, 0, "", configuration_initialize_defaults, NULL, configuration_parse_defaults2, configuration_finalize_defaults }, { NULL, 0, SORT_NORMAL, 0, NULL, NULL, NULL, NULL, configuration_finalize } }; const ListDescriptionSet list_set = { "configuration", configuration_lists }; static char *configuration_sections_array_name; static SectionArrayList value_arrays = STATIC_SECTION_ARRAY_LIST; static SectionArrayList defaults_lists = STATIC_SECTION_ARRAY_LIST; static const SectionData *current_values_data; static const SectionData *current_defaults_data; static const char *current_defaults_list; static StringBuffer initialization_values; static StringBuffer dispose_function_prototypes; static StringBuffer dispose_functions; static SubscriptionStackItem *stack_pointer = NULL; static StringList declared_structures = STATIC_STRING_LIST; static StringList empty_dispose_functions = STATIC_STRING_LIST; static int any_fields_to_init; static const char *last_array_index; static int current_subscription_level; int main (int argc, char *argv[]) { int result; string_buffer_init (&initialization_values, 0x400, 0x100); string_buffer_init (&dispose_function_prototypes, 0x400, 0x100); string_buffer_init (&dispose_functions, 0x1000, 0x400); result = parse_list_main (argc, argv, &list_set, 1, NULL); string_list_empty (&value_arrays); string_list_empty (&defaults_lists); string_list_empty (&declared_structures); string_list_empty (&empty_dispose_functions); string_buffer_dispose (&initialization_values); string_buffer_dispose (&dispose_function_prototypes); string_buffer_dispose (&dispose_functions); return result; } static int configuration_initialize_sections (StringBuffer *c_file_arrays, const char *h_file_enum_name, const char *c_file_array_name) { UNUSED (c_file_arrays); UNUSED (h_file_enum_name); configuration_sections_array_name = utils_duplicate_string (c_file_array_name); return 0; } static int configuration_parse_sections2 (StringBuffer *c_file_arrays, char **line, const char *identifier, char **pending_eol_comment, int *pending_linefeeds) { SectionData section_data = { NULL, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL }; const char *section_values_array; const char *section_defaults_list; SectionArrayListItem *existing_section_array; UNUSED (identifier); UNUSED (pending_eol_comment); UNUSED (pending_linefeeds); PARSE_THING (section_data.section_name, STRING, line, "section name"); if (looking_at ("repeatable", line)) section_data.is_repeatable = 1; else if (looking_at ("single", line)) section_data.is_repeatable = 0; else { print_error ("section type (`single' or `repeatable') expected"); return 1; } if (looking_at ("new", line)) section_data.is_new_structure = 1; else if (looking_at ("existing", line)) section_data.is_new_structure = 0; else { print_error ("new structure flag (`new' or `existing') expected"); return 1; } PARSE_IDENTIFIER (section_data.structure_type, line, "section structure type"); if (!section_data.is_repeatable) { PARSE_IDENTIFIER (section_data.dispose_function_name, line, "section structure dispose function"); } else { PARSE_IDENTIFIER (section_data.list_text_field_name, line, "section list text field name"); PARSE_IDENTIFIER (section_data.list_function_prefix, line, "section list function prefix"); PARSE_IDENTIFIER (section_data.static_list_macro, line, "section static list macro"); } PARSE_IDENTIFIER (section_data.structure_name, line, "section structure name"); PARSE_IDENTIFIER (section_values_array, line, "section values array name"); PARSE_IDENTIFIER (section_defaults_list, line, "section defaults list name"); existing_section_array = section_array_list_find (&value_arrays, section_values_array); if (!existing_section_array) { string_list_add (&value_arrays, section_values_array); value_arrays.last->section_data = section_data; } else { if (!section_datum_equal (§ion_data, &existing_section_array->section_data)) { print_error (("sections %s and %s values arrays match, " "but not structures"), existing_section_array->section_data.section_name, section_data.section_name); return 1; } } existing_section_array = section_array_list_find (&defaults_lists, section_defaults_list); if (!existing_section_array) { string_list_add (&defaults_lists, section_defaults_list); defaults_lists.last->section_data = section_data; } else { if (!section_datum_equal (§ion_data, &existing_section_array->section_data)) { print_error (("sections %s and %s defaults lists match, " "but not structures"), existing_section_array->section_data.section_name, section_data.section_name); return 1; } } string_buffer_cprintf (c_file_arrays, (" { %s, %d,\n &%s,\n %s_init, %s,\n %s,\n" " sizeof %s / sizeof (ConfigurationValue) }"), section_data.section_name, section_data.is_repeatable, section_data.structure_name, section_defaults_list, (section_data.is_repeatable ? "string_list_empty" : section_data.dispose_function_name), section_values_array, section_values_array); return 0; } static int configuration_initialize_values (StringBuffer *c_file_arrays, const char *h_file_enum_name, const char *c_file_array_name) { SectionArrayListItem *value_array = section_array_list_find (&value_arrays, c_file_array_name); UNUSED (c_file_arrays); UNUSED (h_file_enum_name); if (!value_array) { print_error ("section value list `%s' was not described in section list", c_file_array_name); return 1; } current_values_data = &value_array->section_data; return 0; } static int configuration_parse_values2 (StringBuffer *c_file_arrays, char **line, const char *identifier, char **pending_eol_comment, int *pending_linefeeds) { const char *value_name; const char *field_name; const char *value_type; int is_nullable = 0; char *enumeration_values_as_strings = NULL; UNUSED (identifier); UNUSED (pending_eol_comment); UNUSED (pending_linefeeds); PARSE_THING (value_name, STRING, line, "value name"); PARSE_THING (field_name, FIELD_NAME, line, "field name"); if (looking_at ("nullable", line)) is_nullable = 1; if (looking_at ("string", line)) value_type = "VALUE_TYPE_STRING"; else if (looking_at ("string_list", line)) value_type = "VALUE_TYPE_STRING_LIST"; else if (looking_at ("boolean", line)) value_type = "VALUE_TYPE_BOOLEAN"; else if (looking_at ("boolean_write_true_only", line)) value_type = "VALUE_TYPE_BOOLEAN_WRITE_TRUE_ONLY"; else if (looking_at ("int", line)) value_type = "VALUE_TYPE_INT"; else if (looking_at ("enumeration", line)) { int is_new_enumeration; value_type = "VALUE_TYPE_ENUMERATION"; if (looking_at ("new", line)) { is_new_enumeration = 1; string_buffer_cat_string (&h_file_bottom, "\n\nenum {\n "); } else if (looking_at ("existing", line)) { /* FIXME: Think of a way to reuse enumerations nicely. */ is_new_enumeration = 0; } else { print_error ("new enumeration flag (`new' or `existing') expected"); return 1; } while (1) { const char *element_identifier; const char *value_string; PARSE_IDENTIFIER (element_identifier, line, "enumeration element identifier"); if (strcmp (element_identifier, "end") == 0) { if (!enumeration_values_as_strings) { print_error ("empty enumeration"); return 1; } break; } if (is_new_enumeration) { if (enumeration_values_as_strings) string_buffer_cat_string (&h_file_bottom, ",\n "); string_buffer_cat_string (&h_file_bottom, element_identifier); } if (enumeration_values_as_strings) { enumeration_values_as_strings = utils_cat_string (enumeration_values_as_strings, "\\0\"\n \""); } do { PARSE_THING (value_string, STRING, line, "enumeration value string"); enumeration_values_as_strings = utils_cat_as_strings (enumeration_values_as_strings, value_string + 1, strlen (value_string) - 2, "\\000", 4, NULL); while (*line && ! **line) *line = read_line (); } while (*line && **line == '"'); } if (is_new_enumeration) string_buffer_cat_string (&h_file_bottom, "\n};\n"); } else if (looking_at ("real", line)) value_type = "VALUE_TYPE_REAL"; else if (looking_at ("color", line)) value_type = "VALUE_TYPE_COLOR"; else if (looking_at ("time", line)) value_type = "VALUE_TYPE_TIME"; else { print_error ("value/field type expected"); return 1; } string_buffer_cprintf (c_file_arrays, (" { %s, %s%s,\n" " STRUCTURE_FIELD_OFFSET (%s%s, %s),\n "), value_name, value_type, (is_nullable ? " | VALUE_TYPE_IS_NULLABLE" : ""), current_values_data->structure_type, current_values_data->is_repeatable ? "Item" : "", field_name); if (enumeration_values_as_strings) { string_buffer_cat_strings (c_file_arrays, "\"", enumeration_values_as_strings, "\\0\" }", NULL); utils_free (enumeration_values_as_strings); } else string_buffer_cat_string (c_file_arrays, "NULL }"); return 0; } static int configuration_initialize_defaults (StringBuffer *c_file_arrays, const char *h_file_enum_name, const char *c_file_array_name) { SectionArrayListItem *defaults_list = section_array_list_find (&defaults_lists, c_file_array_name); UNUSED (c_file_arrays); UNUSED (h_file_enum_name); if (configuration_sections_array_name) { string_buffer_cat_strings (&h_file_bottom, "\n\nextern const ConfigurationSection\t", configuration_sections_array_name, "[];\n\n", NULL); utils_free (configuration_sections_array_name); configuration_sections_array_name = NULL; } if (!defaults_list) { print_error ("defaults list `%s' was not described in section list", c_file_array_name); return 1; } current_defaults_list = c_file_array_name; current_defaults_data = &defaults_list->section_data; push_subscription_stack (0, current_defaults_data->is_new_structure, !current_defaults_data->is_repeatable, current_defaults_data->structure_type, current_defaults_data->dispose_function_name); if (current_defaults_data->is_repeatable) { int structure_type_length = strlen (current_defaults_data->structure_type); string_buffer_cprintf (&stack_pointer->structure_declaration, ("\n\ntypedef struct _%sItem%s%sItem;\n" "typedef struct _%s%s%s;\n\n"), current_defaults_data->structure_type, TABBING (5, 16 + structure_type_length + 4), current_defaults_data->structure_type, current_defaults_data->structure_type, TABBING (5, 16 + structure_type_length), current_defaults_data->structure_type); string_buffer_cprintf (&stack_pointer->structure_declaration, ("struct _%sItem {\n" " %sItem%s*next;\n char%s*%s;\n\n"), current_defaults_data->structure_type, current_defaults_data->structure_type, TABBING (4, 2 + structure_type_length + 4), TABBING (4, 6), current_defaults_data->list_text_field_name); } string_buffer_empty (&initialization_values); any_fields_to_init = 0; last_array_index = NULL; current_subscription_level = 0; return 0; } static int configuration_parse_defaults2 (StringBuffer *c_file_arrays, char **line, const char *identifier, char **pending_eol_comment, int *pending_linefeeds) { const char *field_name; UNUSED (c_file_arrays); UNUSED (identifier); UNUSED (pending_eol_comment); UNUSED (pending_linefeeds); PARSE_THING (field_name, (stack_pointer->is_array_subscription ? FIELD_NAME : IDENTIFIER), line, "field name"); if (strcmp (field_name, "end") != 0) { char *full_field_name = NULL; int full_field_subscription_length; ConfigurationValueType field_type; const char *structure_type; const char *dispose_field_function = NULL; const char *dispose_field_prefix = ""; const char *default_value = NULL; int is_null = 0; char *multiline_string = NULL; const char *string_to_duplicate = NULL; char buffer[64]; recursively_build_full_field_name (stack_pointer, &full_field_name); full_field_name = utils_cat_string (full_field_name, field_name); full_field_subscription_length = 13 + strlen (full_field_name); if (stack_pointer->is_array_subscription) field_type = stack_pointer->array_element_type; else field_type = look_at_field_type (line); switch (field_type & ~VALUE_TYPE_IS_NULLABLE) { case VALUE_TYPE_STRING: default_value = "NULL"; dispose_field_function = "utils_free"; break; case VALUE_TYPE_STRING_LIST: default_value = "STATIC_STRING_LIST"; dispose_field_function = "string_list_empty"; dispose_field_prefix = "&"; break; case VALUE_TYPE_BOOLEAN: case VALUE_TYPE_BOOLEAN_WRITE_TRUE_ONLY: case VALUE_TYPE_INT: case VALUE_TYPE_ENUMERATION: case VALUE_TYPE_TIME: default_value = "0"; break; case VALUE_TYPE_REAL: default_value = "0.0"; break; case VALUE_TYPE_COLOR: default_value = "{ 0, 0, 0 }"; break; } if (field_type & VALUE_TYPE_IS_NULLABLE && looking_at ("null", line)) is_null = 1; else { switch (field_type & ~VALUE_TYPE_IS_NULLABLE) { case VALUE_TYPE_STRING: while (*line && ! **line) *line = read_line (); if (*line && **line == '"') { multiline_string = parse_multiline_string (line, ("string constant, `char *' variable, " "or NULL"), (full_field_subscription_length > 32 ? "\n\t\t\t " : "\n\t\t\t\t\t\t\t "), 0); string_to_duplicate = multiline_string; } else { PARSE_IDENTIFIER (string_to_duplicate, line, "string constant, `char *' variable or NULL"); if (strcmp (string_to_duplicate, "NULL") == 0) string_to_duplicate = NULL; } break; case VALUE_TYPE_STRING_LIST: if (!looking_at ("-", line)) { /* FIXME */ } break; case VALUE_TYPE_BOOLEAN: case VALUE_TYPE_BOOLEAN_WRITE_TRUE_ONLY: if (looking_at ("true", line)) default_value = "1"; else if (looking_at ("false", line)) default_value = "0"; else { print_error ("`true' or `false' expected"); utils_free (full_field_name); return 1; } break; case VALUE_TYPE_INT: PARSE_THING (default_value, INTEGER_NUMBER, line, "integer number"); break; case VALUE_TYPE_ENUMERATION: /* FIXME: It would be good to check that the value is one of * those described in corresponding `values' list, but I * don't want to bother with this now. */ PARSE_IDENTIFIER (default_value, line, "enumeration element identifier"); break; case VALUE_TYPE_REAL: PARSE_THING (default_value, FLOATING_POINT_NUMBER, line, "real number"); break; case VALUE_TYPE_COLOR: { QuarryColor color; if (!parse_color (line, &color, "color")) { utils_free (full_field_name); return 1; } utils_ncprintf (buffer, sizeof buffer, "{ %d, %d, %d }", color.red, color.green, color.blue); default_value = buffer; } break; case VALUE_TYPE_TIME: { int seconds; PARSE_THING (default_value, TIME_VALUE, line, "time value"); seconds = utils_parse_time (default_value); if (seconds < 0) { utils_free (full_field_name); return 1; } utils_ncprintf (buffer, sizeof buffer, "%d", seconds); default_value = buffer; } break; case VALUE_TYPE_STRUCTURE: { int is_new_structure; utils_free (full_field_name); if (!stack_pointer->is_array_subscription) { if (looking_at ("new", line)) is_new_structure = 1; else if (looking_at ("existing", line)) is_new_structure = 0; else { print_error ("new structure flag (`new' or `existing') " "expected"); return 1; } PARSE_IDENTIFIER (structure_type, line, "structure field type"); if (!looking_at ("-", line)) { PARSE_IDENTIFIER (dispose_field_function, line, "dispose function"); } } else { is_new_structure = stack_pointer->declaring_new_structure; structure_type = stack_pointer->structure_type; dispose_field_function = stack_pointer->dispose_function_name; } push_subscription_stack (0, is_new_structure, 1, structure_type, dispose_field_function); stack_pointer->field_name_part = field_name; if (!current_defaults_data->is_repeatable) open_initialization_braces (1); add_field_declaration_if_needed (stack_pointer->previous, VALUE_TYPE_STRUCTURE, field_name, structure_type, NULL); return 0; } default: if (!stack_pointer->is_array_subscription && looking_at ("array", line)) { const char *dimensions; utils_free (full_field_name); push_subscription_stack (1, 0, 0, NULL, NULL); stack_pointer->field_name_part = field_name; PARSE_THING (dimensions, FIELD_NAME, line, "array dimensions"); stack_pointer->array_element_type = look_at_field_type (line); if (stack_pointer->array_element_type == VALUE_TYPE_STRUCTURE) { if (looking_at ("new", line)) stack_pointer->declaring_new_structure = 1; else if (looking_at ("existing", line)) stack_pointer->declaring_new_structure = 0; else { print_error ("new structure flag (`new' or `existing') " "expected"); return 1; } PARSE_IDENTIFIER (stack_pointer->structure_type, line, "type of structure array elements"); if (!looking_at ("-", line)) { PARSE_IDENTIFIER (stack_pointer->dispose_function_name, line, "dispose function"); } else stack_pointer->dispose_function_name = NULL; } else if (stack_pointer->array_element_type == VALUE_TYPE_INVALID) { print_error ("array element type expected"); return 1; } add_field_declaration_if_needed (stack_pointer->previous, stack_pointer->array_element_type, field_name, stack_pointer->structure_type, dimensions); if (!current_defaults_data->is_repeatable) { for (stack_pointer->num_array_dimensions = 0; *dimensions; dimensions++) { if (*dimensions == '[') stack_pointer->num_array_dimensions++; } open_initialization_braces (stack_pointer->num_array_dimensions); } return 0; } print_error ("field type expected"); return 1; } } if (current_defaults_data->is_repeatable || string_to_duplicate) { if (!any_fields_to_init) { const char *type_suffix = (current_defaults_data->is_repeatable ? "Item" : ""); string_buffer_cprintf (&c_file_bottom, ("\n\nstatic void\n" "%s_init (void *section_structure)\n{\n" " %s%s *structure" " = (%s%s *) section_structure;\n\n"), current_defaults_list, current_defaults_data->structure_type, type_suffix, current_defaults_data->structure_type, type_suffix); any_fields_to_init = 1; } if (field_type & VALUE_TYPE_IS_NULLABLE) { string_buffer_cprintf (&c_file_bottom, " structure->%s_is_null%s= %d;\n", full_field_name, (full_field_subscription_length > 24 ? "\n " : (TABBING (4, full_field_subscription_length - 8))), is_null); } if ((field_type & ~VALUE_TYPE_IS_NULLABLE) != VALUE_TYPE_STRING_LIST) { string_buffer_cprintf (&c_file_bottom, " structure->%s%s= ", full_field_name, (full_field_subscription_length > 32 ? "\n " : TABBING (4, full_field_subscription_length))); if (!string_to_duplicate) { string_buffer_cat_strings (&c_file_bottom, default_value, ";\n", NULL); } else { string_buffer_cat_strings (&c_file_bottom, "utils_duplicate_string (", string_to_duplicate, ");\n", NULL); } } else { string_buffer_cat_strings (&c_file_bottom, " string_list_init (&structure->", full_field_name, ");\n", NULL); } } if (!current_defaults_data->is_repeatable) { if (last_array_index) { int subscription_level_difference = stack_pointer->num_array_dimensions; const char *field_name_scan; const char *last_array_index_scan; for (field_name_scan = field_name, last_array_index_scan = last_array_index; (*field_name_scan == *last_array_index_scan && *field_name_scan != 0); field_name_scan++, last_array_index_scan++) { if (*field_name_scan == '[') subscription_level_difference--; } close_initialization_braces (subscription_level_difference); open_initialization_braces (subscription_level_difference); } if (initialization_values.length > 0 && (initialization_values.string[initialization_values.length - 1] != '{')) string_buffer_add_character (&initialization_values, ','); string_buffer_add_character (&initialization_values, '\n'); add_initialization_indentation (current_subscription_level + 1); if (field_type & VALUE_TYPE_IS_NULLABLE) { /* FIXME: Fails for nullable array elements. */ string_buffer_cprintf (&initialization_values, "%d, ", is_null); } string_buffer_cat_string (&initialization_values, default_value); if (stack_pointer->is_array_subscription) last_array_index = field_name; } add_field_declaration_if_needed (stack_pointer, field_type, field_name, NULL, NULL); add_field_dispose_call_if_needed (stack_pointer, dispose_field_function, dispose_field_prefix, field_name); utils_free (full_field_name); utils_free (multiline_string); } else { SubscriptionStackItem *stack_item = pop_subscription_stack (1); if (!stack_pointer) { print_error ("unmatched `end'"); utils_free (stack_item); return 1; } if (!stack_item->is_array_subscription) { add_field_dispose_call_if_needed (stack_pointer, stack_item->dispose_function_name, "&", stack_item->field_name_part); } if (!current_defaults_data->is_repeatable) { close_initialization_braces (stack_item->is_array_subscription ? stack_item->num_array_dimensions : 1); last_array_index = NULL; } if (stack_pointer->is_array_subscription) stack_pointer->declaring_new_structure = 0; utils_free (stack_item); } return 0; } static int configuration_finalize_defaults (StringBuffer *c_file_arrays) { static int last_init_function_defined = 0; SectionArrayListItem *defaults_list = NULL; int structure_type_length = strlen (current_defaults_data->structure_type); int any_fields_disposed = (stack_pointer->dispose_function.length > 0); string_buffer_add_character (c_file_arrays, '\n'); string_buffer_add_character (&h_file_bottom, '\n'); close_initialization_braces (0); while ((defaults_list = section_array_list_find_after_notch (&defaults_lists, current_defaults_list, defaults_list)) != NULL) { if (current_defaults_data->is_repeatable) { string_buffer_cprintf (c_file_arrays, "\n%s %s = %s;\n", current_defaults_data->structure_type, defaults_list->section_data.structure_name, current_defaults_data->static_list_macro); } else { string_buffer_cprintf (c_file_arrays, "\n%s %s = {%s\n};\n", current_defaults_data->structure_type, defaults_list->section_data.structure_name, initialization_values.string); } string_buffer_cprintf (&h_file_bottom, "extern %s%s%s;\n", current_defaults_data->structure_type, TABBING (5, 7 + structure_type_length), defaults_list->section_data.structure_name); } if (any_fields_to_init) string_buffer_cat_string (&c_file_bottom, "}\n"); finish_function (&c_file_top, current_defaults_list, "_init", any_fields_to_init, &last_init_function_defined); utils_free (pop_subscription_stack (!current_defaults_data->is_repeatable)); if (stack_pointer) { print_error ("`end' expected, unterminated %s", stack_pointer->is_array_subscription ? "array" : "structure"); do utils_free (pop_subscription_stack (0)); while (stack_pointer); return 1; } if (current_defaults_data->is_new_structure && current_defaults_data->is_repeatable) { int list_type_length = strlen (current_defaults_data->structure_type); int list_text_field_name_length = strlen (current_defaults_data->list_text_field_name); int list_function_prefix_length = strlen (current_defaults_data->list_function_prefix); int static_list_macro_length = strlen (current_defaults_data->static_list_macro); string_buffer_cprintf (&h_file_top, ("\nstruct _%s {\n" " %sItem%s*first;\n %sItem%s*last;\n\n" " int%s item_size;\n" " StringListItemDispose%s item_dispose;\n};" "\n\n\n"), current_defaults_data->structure_type, current_defaults_data->structure_type, TABBING (4, 2 + list_type_length + 4), current_defaults_data->structure_type, TABBING (4, 2 + list_type_length + 4), TABBING (4, 5), TABBING (4, 23)); string_buffer_cprintf (&h_file_top, ("#define %s_new()%s\\\n" " string_list_new_derived (sizeof (%sItem),"), current_defaults_data->list_function_prefix, TABBING (9, 8 + list_function_prefix_length + 6), current_defaults_data->structure_type); if (any_fields_disposed) { string_buffer_cprintf (&h_file_top, ("%s\\\n\t\t\t ((StringListItemDispose)%s\\\n" "\t\t\t %s_item_dispose))\n\n"), TABBING (9, 33 + list_type_length + 6), TABBING (9, 50), current_defaults_data->list_function_prefix); } else string_buffer_cat_string (&h_file_top, " NULL)\n\n"); string_buffer_cprintf (&h_file_top, ("#define %s_init(list)%s\\\n" " string_list_init_derived ((list), " "sizeof (%sItem),"), current_defaults_data->list_function_prefix, TABBING (9, 8 + list_function_prefix_length + 11), current_defaults_data->structure_type); if (any_fields_disposed) { string_buffer_cprintf (&h_file_top, ("%s\\\n\t\t\t ((StringListItemDispose)%s\\\n" "\t\t\t %s_item_dispose))\n\n"), TABBING (9, 42 + list_type_length + 6), TABBING (9, 51), current_defaults_data->list_function_prefix); } else string_buffer_cat_string (&h_file_top, " NULL)\n\n"); string_buffer_cprintf (&h_file_top, ("#define %s%s\\\n" " STATIC_STRING_LIST_DERIVED (%sItem,"), current_defaults_data->static_list_macro, TABBING (9, 8 + static_list_macro_length), current_defaults_data->structure_type); if (any_fields_disposed) { string_buffer_cprintf (&h_file_top, "%s\\\n\t\t\t %s_item_dispose)\n\n", TABBING (9, 29 + list_type_length + 5), current_defaults_data->list_function_prefix); } else string_buffer_cat_string (&h_file_top, " NULL)\n\n"); if (any_fields_disposed) { string_buffer_cprintf (&h_file_top, "void\t\t%s_item_dispose (%sItem *item);\n\n", current_defaults_data->list_function_prefix, current_defaults_data->structure_type); } string_buffer_cprintf (&h_file_top, ("\n#define " "%s_get_item(list, item_index)%s\\\n" " ((%sItem *)%s\\\n" " string_list_get_item " "((list), (item_index)))\n"), current_defaults_data->list_function_prefix, TABBING (9, 8 + list_function_prefix_length + 27), current_defaults_data->structure_type, TABBING (9, 4 + list_type_length + 7)); string_buffer_cprintf (&h_file_top, ("\n#define %s_find(list, %s)%s\\\n" " ((%sItem *) " "string_list_find ((list), (%s)))\n"), current_defaults_data->list_function_prefix, current_defaults_data->list_text_field_name, TABBING (9, (8 + list_function_prefix_length + 12 + list_text_field_name_length + 1)), current_defaults_data->structure_type, current_defaults_data->list_text_field_name); string_buffer_cprintf (&h_file_top, ("\n#define " "%s_find_after_notch(list, %s, notch)%s\\\n" " ((%sItem *)%s\\\n" " string_list_find_after_notch ((list), " "(%s), (notch)))\n"), current_defaults_data->list_function_prefix, current_defaults_data->list_text_field_name, TABBING (9, (8 + list_function_prefix_length + 24 + list_text_field_name_length + 8)), current_defaults_data->structure_type, TABBING (9, 4 + list_type_length + 7), current_defaults_data->list_text_field_name); } return 0; } static int configuration_finalize (StringBuffer *c_file_arrays) { UNUSED (c_file_arrays); if (dispose_function_prototypes.length > 0) { string_buffer_cat_as_string (&c_file_top, dispose_function_prototypes.string, dispose_function_prototypes.length); } if (dispose_functions.length > 0) { string_buffer_cat_as_string (&c_file_bottom, dispose_functions.string, dispose_functions.length); } return 0; } /* Note: doesn't handle "array" string, because it is not a real type. * If the caller allows "array" in this context, it should check for * it manually if look_at_field_type() returns `VALUE_TYPE_INVALID'. */ static ConfigurationValueType look_at_field_type (char **line) { ConfigurationValueType nullable_flag = (looking_at ("nullable", line) ? VALUE_TYPE_IS_NULLABLE : 0); if (looking_at ("string", line)) return VALUE_TYPE_STRING | nullable_flag; if (looking_at ("string_list", line)) return VALUE_TYPE_STRING_LIST | nullable_flag; if (looking_at ("boolean", line)) return VALUE_TYPE_BOOLEAN | nullable_flag; if (looking_at ("boolean_write_true_only", line)) return VALUE_TYPE_BOOLEAN_WRITE_TRUE_ONLY | nullable_flag; if (looking_at ("int", line)) return VALUE_TYPE_INT | nullable_flag; if (looking_at ("enumeration", line)) return VALUE_TYPE_ENUMERATION | nullable_flag; if (looking_at ("real", line)) return VALUE_TYPE_REAL | nullable_flag; if (looking_at ("color", line)) return VALUE_TYPE_COLOR | nullable_flag; if (looking_at ("time", line)) return VALUE_TYPE_TIME | nullable_flag; if (looking_at ("structure", line)) { if (nullable_flag == VALUE_TYPE_IS_NULLABLE) { print_error ("structures cannot be nullable"); return VALUE_TYPE_INVALID; } return VALUE_TYPE_STRUCTURE; } return VALUE_TYPE_INVALID; } static int section_datum_equal (const SectionData *first_data, const SectionData *second_data) { if (first_data->is_repeatable != second_data->is_repeatable || strcmp (first_data->structure_type, second_data->structure_type) != 0) return 0; if (first_data->is_repeatable) { return (strcmp (first_data->list_text_field_name, second_data->list_text_field_name) == 0 && strcmp (first_data->list_function_prefix, second_data->list_function_prefix) == 0 && strcmp (first_data->static_list_macro, second_data->static_list_macro) == 0); } else { return (strcmp (first_data->dispose_function_name, second_data->dispose_function_name) == 0); } } static void push_subscription_stack (int is_array_subscription, int is_new_structure, int do_start_structure_declaration, const char *structure_type, const char *dispose_function_name) { SubscriptionStackItem *new_stack_item = utils_malloc (sizeof (SubscriptionStackItem)); new_stack_item->previous = stack_pointer; stack_pointer = new_stack_item; if (is_new_structure && string_list_find (&declared_structures, structure_type)) is_new_structure = 0; stack_pointer->is_array_subscription = is_array_subscription; stack_pointer->declaring_new_structure = is_new_structure; stack_pointer->structure_type = structure_type; if (is_new_structure) { string_buffer_init (&stack_pointer->structure_declaration, 0x400, 0x100); string_buffer_init (&stack_pointer->dispose_function, 0x400, 0x100); if (do_start_structure_declaration) { string_buffer_cprintf (&stack_pointer->structure_declaration, "\n\ntypedef struct _%s%s%s;\n\nstruct _%s {\n", structure_type, TABBING (5, 16 + strlen (structure_type)), structure_type, structure_type); } string_list_add (&declared_structures, structure_type); } stack_pointer->dispose_function_name = dispose_function_name; } static SubscriptionStackItem * pop_subscription_stack (int do_write_dispose_function_prototype) { static int last_dispose_function_defined = 0; SubscriptionStackItem *current_stack_item = stack_pointer; if (stack_pointer->declaring_new_structure) { string_buffer_cat_as_strings (&h_file_top, stack_pointer->structure_declaration.string, stack_pointer->structure_declaration.length, "};\n", 3, NULL); if (stack_pointer->dispose_function.length > 0) { string_buffer_cat_as_strings (&dispose_functions, stack_pointer->dispose_function.string, stack_pointer->dispose_function.length, "}\n", 2, NULL); } else { string_list_add (&empty_dispose_functions, stack_pointer->dispose_function_name); } if (do_write_dispose_function_prototype) { finish_function (&dispose_function_prototypes, stack_pointer->dispose_function_name, "", stack_pointer->dispose_function.length > 0, &last_dispose_function_defined); } string_buffer_dispose (&stack_pointer->structure_declaration); string_buffer_dispose (&stack_pointer->dispose_function); } stack_pointer = stack_pointer->previous; return current_stack_item; } static void recursively_build_full_field_name (const SubscriptionStackItem *stack_item, char **full_field_name) { if (stack_item->previous) { recursively_build_full_field_name (stack_item->previous, full_field_name); *full_field_name = utils_cat_strings (*full_field_name, stack_item->field_name_part, (stack_item->is_array_subscription ? NULL : "."), NULL); } } static void add_field_declaration_if_needed (SubscriptionStackItem *stack_item, ConfigurationValueType field_type, const char *field_name, const char *structure_type, const char *array_dimensions) { if (!stack_item->is_array_subscription && stack_item->declaring_new_structure) { const char *field_type_string; switch (field_type & ~VALUE_TYPE_IS_NULLABLE) { case VALUE_TYPE_STRING: field_type_string = "char"; break; case VALUE_TYPE_STRING_LIST: field_type_string = "StringList"; break; case VALUE_TYPE_BOOLEAN: case VALUE_TYPE_BOOLEAN_WRITE_TRUE_ONLY: case VALUE_TYPE_INT: case VALUE_TYPE_ENUMERATION: case VALUE_TYPE_TIME: field_type_string = "int"; break; case VALUE_TYPE_REAL: field_type_string = "double"; break; case VALUE_TYPE_COLOR: field_type_string = "QuarryColor"; break; default: field_type_string = structure_type; } if (field_type & VALUE_TYPE_IS_NULLABLE) { string_buffer_cprintf (&stack_item->structure_declaration, " int\t\t\t\t %s_is_null%s;\n", field_name, array_dimensions ? array_dimensions : ""); } string_buffer_cprintf (&stack_item->structure_declaration, " %s%s%c%s%s;\n", field_type_string, TABBING (4, 2 + strlen (field_type_string)), (((field_type & ~VALUE_TYPE_IS_NULLABLE) != VALUE_TYPE_STRING) ? ' ' : '*'), field_name, array_dimensions ? array_dimensions : ""); } } static void add_field_dispose_call_if_needed (SubscriptionStackItem *stack_item, const char *dispose_field_function, const char *dispose_field_prefix, const char *field_name) { if (stack_item->is_array_subscription) stack_item = stack_item->previous; if (stack_item->declaring_new_structure && dispose_field_function && !string_list_find (&empty_dispose_functions, dispose_field_function)) { int is_repeatable = (!stack_item->previous && current_defaults_data->is_repeatable); if (stack_item->dispose_function.length == 0) { if (is_repeatable) { string_buffer_cprintf (&stack_item->dispose_function, ("\n\nvoid\n" "%s_item_dispose (%sItem *item)\n{\n"), current_defaults_data->list_function_prefix, current_defaults_data->structure_type); } else { string_buffer_cprintf (&stack_item->dispose_function, ("\n\nstatic void\n" "%s (void *section_structure)\n{\n" " %s *structure = (%s *) section_structure;" "\n\n"), stack_item->dispose_function_name, stack_item->structure_type, stack_item->structure_type); } } string_buffer_cprintf (&stack_item->dispose_function, " %s (%s%s->%s%s);\n", dispose_field_function, dispose_field_prefix, (is_repeatable ? "item" : "structure"), (stack_pointer->is_array_subscription ? stack_pointer->field_name_part : ""), field_name); } } static void open_initialization_braces (int num_levels) { if (num_levels > 0) { int k; if (initialization_values.length > 0 && (initialization_values.string[initialization_values.length - 1] != '{')) string_buffer_add_character (&initialization_values, ','); for (k = 0; k < num_levels; k++) { string_buffer_add_character (&initialization_values, '\n'); add_initialization_indentation (++current_subscription_level); string_buffer_add_character (&initialization_values, '{'); } } } static void close_initialization_braces (int num_levels) { int k; for (k = 0; k < num_levels; k++) { string_buffer_add_character (&initialization_values, '\n'); add_initialization_indentation (current_subscription_level--); string_buffer_add_character (&initialization_values, '}'); } } static void add_initialization_indentation (int indentation_level) { static const char *six_spaces = " "; if (indentation_level >= 4) { string_buffer_cat_string (&initialization_values, TABBING (indentation_level / 4, 0)); } if (indentation_level % 4) { string_buffer_cat_string (&initialization_values, six_spaces + 2 * (3 - (indentation_level % 4))); } } static void finish_function (StringBuffer *prototypes_buffer, const char *function_name, const char *function_name_suffix, int function_defined, int *last_function_defined) { if (prototypes_buffer->length > 0) { if (*last_function_defined != function_defined) string_buffer_add_character (prototypes_buffer, '\n'); } else string_buffer_add_characters (prototypes_buffer, '\n', 2); if (function_defined) { string_buffer_cat_strings (prototypes_buffer, "static void\t", function_name, function_name_suffix, " (void *section_structure);\n", NULL); } else { int function_name_length = (strlen (function_name) + strlen (function_name_suffix)); string_buffer_cat_strings (prototypes_buffer, "#define\t\t", function_name, function_name_suffix, TABBING (8, 16 + function_name_length), "NULL\n", NULL); } *last_function_defined = function_defined; } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-utils/common-configuration-sections.list0000644000175000017500000000472510367243776023115 0ustar bartbart# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # This file is part of Quarry # # # # Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. # # # # 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 2 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, write to the Free # # Software Foundation, Inc., 51 Franklin Street, Fifth Floor, # # Boston, MA 02110-1301, USA. # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # SECTION_GTP_ENGINES "GTP Engine" repeatable new GtpEngineList screen_name gtp_engine_list STATIC_GTP_ENGINE_LIST gtp_engines gtp_engine_section_values gtp_engine_defaults SECTION_GAME_TREE_VIEW "Game Tree View" single new GameTreeView game_tree_view_dispose game_tree_view game_tree_view_values game_tree_view_defaults SECTION_SGF "SGF" single new SgfConfiguration sgf_configuration_dispose sgf_configuration sgf_configuration_values sgf_configuration_defaults SECTION_GO_BOARD_APPEARANCE "Go Board Appearance" single new BoardAppearance board_appearance_dispose go_board_appearance board_appearance_values go_board_appearance_defaults SECTION_AMAZONS_BOARD_APPEARANCE "Amazons Board Appearance" single new AmazonsBoardAppearance amazons_board_appearance_dispose amazons_board_appearance amazons_board_appearance_values amazons_board_appearance_defaults SECTION_REVERSI_BOARD_APPEARANCE "Reversi Board Appearance" single new BoardAppearance board_appearance_dispose reversi_board_appearance board_appearance_values reversi_board_appearance_defaults quarry-0.2.0/src/gui-utils/common-configuration-values.list0000644000175000017500000000763110377142345022553 0ustar bartbart# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # This file is part of Quarry # # # # Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. # # # # 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 2 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, write to the Free # # Software Foundation, Inc., 51 Franklin Street, Fifth Floor, # # Boston, MA 02110-1301, USA. # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # values - gtp_engine_section_values { "Screen name format" screen_name_format string "Name" name string "Version" version string "Site configuration name" site_configuration_name string "Hidden by user" is_hidden boolean_write_true_only "Command line" command_line string "Supported games" supported_games string_list } values - game_tree_view_values { "Show tooltips" show_tooltips boolean "Show game tree" show_game_tree enumeration new SHOW_GAME_TREE_ALWAYS "Always" SHOW_GAME_TREE_AUTOMATICALLY "Auto" "Automatically" SHOW_GAME_TREE_NEVER "Never" end "Track current node" track_current_node enumeration new TRACK_CURRENT_NODE_ALWAYS "Always" TRACK_CURRENT_NODE_AUTOMATICALLY "Auto" "Automatically" TRACK_CURRENT_NODE_NEVER "Never" end "Center on current node" center_on_current_node boolean } values - sgf_configuration_values { "Force UTF-8" force_utf8 boolean } values - board_appearance_values { "Use background texture" use_background_texture boolean "Background texture" background_texture string "Background color" background_color color "Grid and labels color" grid_and_labels_color color "Markup theme" markup_theme string "Use theme defaults" use_theme_defaults boolean "Markup size" markup_size real "Markup size is relative" markup_size_is_relative boolean "Markup opacity" markup_opacity real "Markup color on white" markup_colors[2] color "Markup color on black" markup_colors[1] color "Markup color on other" markup_colors[0] color } values - amazons_board_appearance_values { "Use background texture" board_appearance.use_background_texture boolean "Background texture" board_appearance.background_texture string "Background color" board_appearance.background_color color "Checkerboard pattern color" checkerboard_pattern_color color "Checkerboard pattern opacity" checkerboard_pattern_opacity real "Grid and labels color" board_appearance.grid_and_labels_color color "Markup theme" board_appearance.markup_theme string "Use theme defaults" board_appearance.use_theme_defaults boolean "Markup size" board_appearance.markup_size real "Markup size is relative" board_appearance.markup_size_is_relative boolean "Markup opacity" board_appearance.markup_opacity real "Markup color on white" board_appearance.markup_colors[2] color "Markup color on black" board_appearance.markup_colors[1] color "Markup color on other" board_appearance.markup_colors[0] color } quarry-0.2.0/src/gui-utils/common-configuration-defaults.list0000644000175000017500000000712210377142337023057 0ustar bartbart# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # This file is part of Quarry # # # # Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. # # # # 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 2 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, write to the Free # # Software Foundation, Inc., 51 Franklin Street, Fifth Floor, # # Boston, MA 02110-1301, USA. # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # defaults - gtp_engine_defaults { screen_name_format string "%n %v" name string NULL version string NULL site_configuration_name string NULL is_hidden boolean_write_true_only false command_line string NULL supported_games string_list - } defaults - game_tree_view_defaults { show_tooltips boolean true show_game_tree enumeration SHOW_GAME_TREE_AUTOMATICALLY track_current_node enumeration TRACK_CURRENT_NODE_AUTOMATICALLY center_on_current_node boolean false } defaults - sgf_configuration_defaults { force_utf8 boolean true } defaults - go_board_appearance_defaults { use_background_texture boolean true background_texture string "$PACKAGE_TEXTURES_DIR$/wood1.jpg" background_color color #dbb665 grid_and_labels_color color #000000 markup_theme string "Default" use_theme_defaults boolean true markup_size real 0.65 markup_size_is_relative boolean true markup_opacity real 0.8 markup_colors array [3] color [0] #186010 [1] #e6d8c6 [2] #505050 end } defaults - amazons_board_appearance_defaults { board_appearance structure new BoardAppearance board_appearance_dispose use_background_texture boolean true background_texture string "$PACKAGE_TEXTURES_DIR$/wood1.jpg" background_color color #dbb665 grid_and_labels_color color #000000 markup_theme string "Default" use_theme_defaults boolean true markup_size real 0.65 markup_size_is_relative boolean true markup_opacity real 0.8 markup_colors array [3] color [0] #222222 [1] #e6d8c6 [2] #505050 end end # Force some brownish tint. checkerboard_pattern_color color #604000 checkerboard_pattern_opacity real 0.4 } defaults - reversi_board_appearance_defaults { use_background_texture boolean false background_texture string NULL background_color color #087834 grid_and_labels_color color #cceebb markup_theme string "Default" use_theme_defaults boolean true markup_size real 0.65 markup_size_is_relative boolean true markup_opacity real 0.8 markup_colors array [3] color [0] #cceebb [1] #e6d8c6 [2] #505050 end } quarry-0.2.0/src/gui-gtk/0000755000175000017500000000000010530402572013632 5ustar bartbartquarry-0.2.0/src/gui-gtk/Makefile.in0000644000175000017500000006124010513274635015712 0ustar bartbart# Makefile.in generated by automake 1.7.9 from Makefile.am. # @configure_input@ # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 # Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # Process this file with Automake to produce `Makefile.in'. srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = ../.. am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : host_triplet = @host@ ACLOCAL = @ACLOCAL@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BUILD_SGF_UTILS_FALSE = @BUILD_SGF_UTILS_FALSE@ BUILD_SGF_UTILS_TRUE = @BUILD_SGF_UTILS_TRUE@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DO_SCROLLKEEPER_UPDATE_FALSE = @DO_SCROLLKEEPER_UPDATE_FALSE@ DO_SCROLLKEEPER_UPDATE_TRUE = @DO_SCROLLKEEPER_UPDATE_TRUE@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ GMSGFMT = @GMSGFMT@ HAVE_SCROLLKEEPER_FALSE = @HAVE_SCROLLKEEPER_FALSE@ HAVE_SCROLLKEEPER_TRUE = @HAVE_SCROLLKEEPER_TRUE@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ LDFLAGS = @LDFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ MAKEINFO = @MAKEINFO@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGMERGE = @MSGMERGE@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSUB = @POSUB@ QUARRY_GTHREAD_CFLAGS = @QUARRY_GTHREAD_CFLAGS@ QUARRY_GTHREAD_LIBS = @QUARRY_GTHREAD_LIBS@ QUARRY_GTK_CFLAGS = @QUARRY_GTK_CFLAGS@ QUARRY_GTK_DEPRECATED_FLAGS = @QUARRY_GTK_DEPRECATED_FLAGS@ QUARRY_GTK_LIBS = @QUARRY_GTK_LIBS@ QUARRY_WARNINGS = @QUARRY_WARNINGS@ QUARRY_WARNINGS_GTK = @QUARRY_WARNINGS_GTK@ RANLIB = @RANLIB@ REGISTER_MIME_TYPES_FALSE = @REGISTER_MIME_TYPES_FALSE@ REGISTER_MIME_TYPES_TRUE = @REGISTER_MIME_TYPES_TRUE@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ ac_ct_CC = @ac_ct_CC@ ac_ct_RANLIB = @ac_ct_RANLIB@ ac_ct_STRIP = @ac_ct_STRIP@ ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ datadir = @datadir@ exec_prefix = @exec_prefix@ have_scrollkeeper = @have_scrollkeeper@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localstatedir = @localstatedir@ mandir = @mandir@ oldincludedir = @oldincludedir@ prefix = @prefix@ program_transform_name = @program_transform_name@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ QUARRY_FULL_GTK_CFLAGS = \ $(QUARRY_GTK_CFLAGS) \ $(QUARRY_GTK_DEPRECATED_FLAGS) \ $(QUARRY_GTHREAD_CFLAGS) AM_CPPFLAGS = \ -D DATA_DIR=\"$(datadir)\" \ -D PACKAGE_DATA_DIR=\"$(pkgdatadir)\" \ \ $(QUARRY_WARNINGS_GTK) \ \ -I $(top_srcdir)/src \ -I $(top_srcdir)/src/board \ -I $(top_builddir)/src/board \ -I $(top_srcdir)/src/gtp \ -I $(top_srcdir)/src/gui-utils \ -I $(top_builddir)/src/gui-utils \ -I $(top_srcdir)/src/sgf \ -I $(top_builddir)/src/sgf \ -I $(top_srcdir)/src/utils \ \ $(QUARRY_FULL_GTK_CFLAGS) noinst_LIBRARIES = libguigtk.a LIST_FILES = gtk-configuration.list PARSE_LIST_COMMAND = \ $(top_builddir)/src/gui-utils/parse-configuration$(EXEEXT) PARSE_LIST_FLAGS = \ -D top_srcdir="$(top_srcdir)" \ -D PACKAGE_TEXTURES_DIR="$(pkgdatadir)/textures" SUFFIXES = .list .h # `LIST_FILES' must be set by the includer. The includer can use # `LIST_STAMP_FILES' and `LIST_GENERATED_FILES' and assume they are # set just as here. # LIST_STAMP_FILES = $(LIST_FILES:.list=.stamp) LIST_GENERATED_FILES = $(LIST_FILES:.list=.c) $(LIST_FILES:.list=.h) # `PARSE_LIST_COMMAND' and `PARSE_LIST_FLAGS' should be set by the # includer. # PARSE_LIST = $(PARSE_LIST_COMMAND) $(PARSE_LIST_FLAGS) # We use `cmp' here to avoid unneeded recompilations of files that # depend on generated ones (only really useful for `.h' files.) # PARSE_LIST_BUILD_RULE = \ if $(PARSE_LIST) `test -f '$<' || echo '$(srcdir)/'`$< \ $*.h.new $*.c.new; then \ if cmp -s $*.c.new $*.c; \ then rm -f $*.c.new; else mv -f $*.c.new $*.c; \ fi; \ if cmp -s $*.h.new $*.h; \ then rm -f $*.h.new; else mv -f $*.h.new $*.h; \ fi; \ echo timestamp > $@; \ else \ (rm -f $*.c $*.c.new $*.h $*.h.new ; exit 1) \ fi libguigtk_a_SOURCES = \ gtk-add-or-edit-label-dialog.c \ gtk-clock.c \ gtk-color-button.c \ gtk-control-center.c \ gtk-file-dialog.c \ gtk-file-selector.c \ gtk-freezable-spin-button.c \ gtk-game-info-dialog.c \ gtk-games.c \ gtk-goban.c \ gtk-goban-base.c \ gtk-goban-window.c \ gtk-go-to-named-node-dialog.c \ gtk-gtp-client-interface.c \ gtk-help.c \ gtk-named-vbox.c \ gtk-new-game-dialog.c \ gtk-new-game-record-dialog.c \ gtk-parser-interface.c \ gtk-preferences.c \ gtk-progress-dialog.c \ gtk-qbox.c \ gtk-qhbox.c \ gtk-qvbox.c \ gtk-resume-game-dialog.c \ gtk-sgf-tree-signal-proxy.c \ gtk-sgf-tree-view.c \ gtk-tile-set.c \ gtk-utils.c \ gui-back-end.c \ quarry-assistant.c \ quarry-find-dialog.c \ quarry-history-text-buffer.c \ quarry-message-dialog.c \ quarry-move-number-dialog.c \ quarry-save-confirmation-dialog.c \ quarry-stock.c \ quarry-text-buffer.c \ quarry-text-view.c \ \ gtk-add-or-edit-label-dialog.h \ gtk-clock.h \ gtk-color-button.h \ gtk-control-center.h \ gtk-file-dialog.h \ gtk-file-selector.h \ gtk-freezable-spin-button.h \ gtk-game-info-dialog.h \ gtk-games.h \ gtk-goban.h \ gtk-goban-base.h \ gtk-goban-window.h \ gtk-go-to-named-node-dialog.h \ gtk-gtp-client-interface.h \ gtk-help.h \ gtk-named-vbox.h \ gtk-new-game-dialog.h \ gtk-new-game-record-dialog.h \ gtk-parser-interface.h \ gtk-preferences.h \ gtk-progress-dialog.h \ gtk-qbox.h \ gtk-qhbox.h \ gtk-qvbox.h \ gtk-resume-game-dialog.h \ gtk-sgf-tree-signal-proxy.h \ gtk-sgf-tree-view.h \ gtk-thread-interface.h \ gtk-tile-set.h \ gtk-utils.h \ gui-back-end.h \ quarry-assistant.h \ quarry-find-dialog.h \ quarry-history-text-buffer.h \ quarry-message-dialog.h \ quarry-move-number-dialog.h \ quarry-save-confirmation-dialog.h \ quarry-stock.h \ quarry-text-buffer.h \ quarry-text-view.h \ \ $(LIST_FILES) nodist_libguigtk_a_SOURCES = \ $(LIST_GENERATED_FILES) \ \ quarry-marshal.c \ \ quarry-marshal.h BUILT_SOURCES = \ $(LIST_STAMP_FILES) \ \ quarry-marshal.h # This seems to be the best way of solving circular references. libguigtk_a_LIBADD = $(top_builddir)/src/gui-utils/libguiutils.a EXTRA_DIST = quarry-marshal.glist DISTCLEANFILES = *~ MOSTLYCLEANFILES = \ $(LIST_STAMP_FILES) \ $(LIST_GENERATED_FILES) \ \ quarry-marshal.c \ \ quarry-marshal.h subdir = src/gui-gtk ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 mkinstalldirs = $(SHELL) $(top_srcdir)/build/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = LIBRARIES = $(noinst_LIBRARIES) libguigtk_a_AR = $(AR) cru libguigtk_a_DEPENDENCIES = $(top_builddir)/src/gui-utils/libguiutils.a am__objects_1 = am_libguigtk_a_OBJECTS = gtk-add-or-edit-label-dialog.$(OBJEXT) \ gtk-clock.$(OBJEXT) gtk-color-button.$(OBJEXT) \ gtk-control-center.$(OBJEXT) gtk-file-dialog.$(OBJEXT) \ gtk-file-selector.$(OBJEXT) gtk-freezable-spin-button.$(OBJEXT) \ gtk-game-info-dialog.$(OBJEXT) gtk-games.$(OBJEXT) \ gtk-goban.$(OBJEXT) gtk-goban-base.$(OBJEXT) \ gtk-goban-window.$(OBJEXT) \ gtk-go-to-named-node-dialog.$(OBJEXT) \ gtk-gtp-client-interface.$(OBJEXT) gtk-help.$(OBJEXT) \ gtk-named-vbox.$(OBJEXT) gtk-new-game-dialog.$(OBJEXT) \ gtk-new-game-record-dialog.$(OBJEXT) \ gtk-parser-interface.$(OBJEXT) gtk-preferences.$(OBJEXT) \ gtk-progress-dialog.$(OBJEXT) gtk-qbox.$(OBJEXT) \ gtk-qhbox.$(OBJEXT) gtk-qvbox.$(OBJEXT) \ gtk-resume-game-dialog.$(OBJEXT) \ gtk-sgf-tree-signal-proxy.$(OBJEXT) gtk-sgf-tree-view.$(OBJEXT) \ gtk-tile-set.$(OBJEXT) gtk-utils.$(OBJEXT) \ gui-back-end.$(OBJEXT) quarry-assistant.$(OBJEXT) \ quarry-find-dialog.$(OBJEXT) \ quarry-history-text-buffer.$(OBJEXT) \ quarry-message-dialog.$(OBJEXT) \ quarry-move-number-dialog.$(OBJEXT) \ quarry-save-confirmation-dialog.$(OBJEXT) \ quarry-stock.$(OBJEXT) quarry-text-buffer.$(OBJEXT) \ quarry-text-view.$(OBJEXT) $(am__objects_1) am__objects_2 = gtk-configuration.$(OBJEXT) am__objects_3 = $(am__objects_2) $(am__objects_1) nodist_libguigtk_a_OBJECTS = $(am__objects_3) quarry-marshal.$(OBJEXT) libguigtk_a_OBJECTS = $(am_libguigtk_a_OBJECTS) \ $(nodist_libguigtk_a_OBJECTS) DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/build/depcomp am__depfiles_maybe = depfiles @AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/gtk-add-or-edit-label-dialog.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/gtk-clock.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/gtk-color-button.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/gtk-configuration.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/gtk-control-center.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/gtk-file-dialog.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/gtk-file-selector.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/gtk-freezable-spin-button.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/gtk-game-info-dialog.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/gtk-games.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/gtk-go-to-named-node-dialog.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/gtk-goban-base.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/gtk-goban-window.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/gtk-goban.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/gtk-gtp-client-interface.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/gtk-help.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/gtk-named-vbox.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/gtk-new-game-dialog.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/gtk-new-game-record-dialog.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/gtk-parser-interface.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/gtk-preferences.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/gtk-progress-dialog.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/gtk-qbox.Po ./$(DEPDIR)/gtk-qhbox.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/gtk-qvbox.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/gtk-resume-game-dialog.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/gtk-sgf-tree-signal-proxy.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/gtk-sgf-tree-view.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/gtk-tile-set.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/gtk-utils.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/gui-back-end.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/quarry-assistant.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/quarry-find-dialog.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/quarry-history-text-buffer.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/quarry-marshal.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/quarry-message-dialog.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/quarry-move-number-dialog.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/quarry-save-confirmation-dialog.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/quarry-stock.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/quarry-text-buffer.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/quarry-text-view.Po COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ DIST_SOURCES = $(libguigtk_a_SOURCES) DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/build/list.make \ Makefile.am SOURCES = $(libguigtk_a_SOURCES) $(nodist_libguigtk_a_SOURCES) all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: .list .h .c .o .obj .stamp $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/build/list.make $(top_srcdir)/configure.ac $(ACLOCAL_M4) cd $(top_srcdir) && \ $(AUTOMAKE) --foreign src/gui-gtk/Makefile Makefile: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) AR = ar clean-noinstLIBRARIES: -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) libguigtk.a: $(libguigtk_a_OBJECTS) $(libguigtk_a_DEPENDENCIES) -rm -f libguigtk.a $(libguigtk_a_AR) libguigtk.a $(libguigtk_a_OBJECTS) $(libguigtk_a_LIBADD) $(RANLIB) libguigtk.a mostlyclean-compile: -rm -f *.$(OBJEXT) core *.core distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gtk-add-or-edit-label-dialog.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gtk-clock.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gtk-color-button.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gtk-configuration.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gtk-control-center.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gtk-file-dialog.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gtk-file-selector.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gtk-freezable-spin-button.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gtk-game-info-dialog.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gtk-games.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gtk-go-to-named-node-dialog.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gtk-goban-base.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gtk-goban-window.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gtk-goban.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gtk-gtp-client-interface.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gtk-help.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gtk-named-vbox.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gtk-new-game-dialog.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gtk-new-game-record-dialog.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gtk-parser-interface.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gtk-preferences.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gtk-progress-dialog.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gtk-qbox.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gtk-qhbox.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gtk-qvbox.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gtk-resume-game-dialog.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gtk-sgf-tree-signal-proxy.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gtk-sgf-tree-view.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gtk-tile-set.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gtk-utils.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gui-back-end.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/quarry-assistant.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/quarry-find-dialog.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/quarry-history-text-buffer.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/quarry-marshal.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/quarry-message-dialog.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/quarry-move-number-dialog.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/quarry-save-confirmation-dialog.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/quarry-stock.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/quarry-text-buffer.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/quarry-text-view.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ @am__fastdepCC_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ @am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ @am__fastdepCC_TRUE@ fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `test -f '$<' || echo '$(srcdir)/'`$< .c.obj: @am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ @am__fastdepCC_TRUE@ -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi`; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ @am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ @am__fastdepCC_TRUE@ fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi` uninstall-info-am: ETAGS = etags ETAGSFLAGS = CTAGS = ctags CTAGSFLAGS = tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(ETAGS_ARGS)$$tags$$unique" \ || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = ../.. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) $(mkinstalldirs) $(distdir)/../../build @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ case $$file in \ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ esac; \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ dir="/$$dir"; \ $(mkinstalldirs) "$(distdir)$$dir"; \ else \ dir=''; \ fi; \ if test -d $$d/$$file; then \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-am all-am: Makefile $(LIBRARIES) installdirs: install: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) clean-generic: distclean-generic: -rm -f $(CONFIG_CLEAN_FILES) -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) clean: clean-am clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: info: info-am info-am: install-data-am: install-exec-am: install-info: install-info-am install-man: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-info-am .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ clean-noinstLIBRARIES ctags distclean distclean-compile \ distclean-generic distclean-tags distdir dvi dvi-am info \ info-am install install-am install-data install-data-am \ install-exec install-exec-am install-info install-info-am \ install-man install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-compile mostlyclean-generic pdf pdf-am \ ps ps-am tags uninstall uninstall-am uninstall-info-am # Avoid problems with parallel builds. gtk-configuration.c: gtk-configuration.h # Make everything depend on the `Makefile' and the list parser. $(LIST_STAMP_FILES) : Makefile $(PARSE_LIST_COMMAND) .list.stamp: $(PARSE_LIST_BUILD_RULE) # Since $(LIST_GENERATED_FILES) defined by the includer don't (at # least shouldn't) have any dependencies, if this rule is being # executed, it probably means that one of the files was removed. # Then all we can do is to force rebuilding of corresponding stamp # file, which builds the required sources ``by side-effect.'' # $(LIST_GENERATED_FILES): rm -f $*.stamp; $(MAKE) $(AM_MAKEFLAGS) $*.stamp quarry-marshal.c : $(srcdir)/quarry-marshal.glist $(GLIB_GENMARSHAL) --stdinc --prefix=quarry_marshal --body \ `test -f '$<' || echo '$(srcdir)/'`$< > $@ \ || (rm -f $@; exit 1) quarry-marshal.h : $(srcdir)/quarry-marshal.glist $(GLIB_GENMARSHAL) --stdinc --prefix=quarry_marshal --header \ `test -f '$<' || echo '$(srcdir)/'`$< > $@ \ || (rm -f $@; exit 1) # FIXME: find a nicer way to avoid warnings in `quarry-marshal.c' # (missing prototypes are easy; the trick is to cope with # unused parameters). quarry-marshal.$(OBJEXT) : quarry-marshal.c quarry-marshal.h $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(QUARRY_FULL_GTK_CFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) \ -o quarry-marshal.$(OBJEXT) \ -c quarry-marshal.c \ || (rm -f quarry-marshal.$(OBJEXT) ; exit 1) # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: quarry-0.2.0/src/gui-gtk/Makefile.am0000644000175000017500000001046510513274536015704 0ustar bartbart# Process this file with Automake to produce `Makefile.in'. QUARRY_FULL_GTK_CFLAGS = \ $(QUARRY_GTK_CFLAGS) \ $(QUARRY_GTK_DEPRECATED_FLAGS) \ $(QUARRY_GTHREAD_CFLAGS) AM_CPPFLAGS = \ -D DATA_DIR=\"$(datadir)\" \ -D PACKAGE_DATA_DIR=\"$(pkgdatadir)\" \ \ $(QUARRY_WARNINGS_GTK) \ \ -I $(top_srcdir)/src \ -I $(top_srcdir)/src/board \ -I $(top_builddir)/src/board \ -I $(top_srcdir)/src/gtp \ -I $(top_srcdir)/src/gui-utils \ -I $(top_builddir)/src/gui-utils \ -I $(top_srcdir)/src/sgf \ -I $(top_builddir)/src/sgf \ -I $(top_srcdir)/src/utils \ \ $(QUARRY_FULL_GTK_CFLAGS) noinst_LIBRARIES = libguigtk.a LIST_FILES = gtk-configuration.list PARSE_LIST_COMMAND = \ $(top_builddir)/src/gui-utils/parse-configuration$(EXEEXT) PARSE_LIST_FLAGS = \ -D top_srcdir="$(top_srcdir)" \ -D PACKAGE_TEXTURES_DIR="$(pkgdatadir)/textures" # Avoid problems with parallel builds. gtk-configuration.c: gtk-configuration.h include $(top_srcdir)/build/list.make quarry-marshal.c : $(srcdir)/quarry-marshal.glist $(GLIB_GENMARSHAL) --stdinc --prefix=quarry_marshal --body \ `test -f '$<' || echo '$(srcdir)/'`$< > $@ \ || (rm -f $@; exit 1) quarry-marshal.h : $(srcdir)/quarry-marshal.glist $(GLIB_GENMARSHAL) --stdinc --prefix=quarry_marshal --header \ `test -f '$<' || echo '$(srcdir)/'`$< > $@ \ || (rm -f $@; exit 1) # FIXME: find a nicer way to avoid warnings in `quarry-marshal.c' # (missing prototypes are easy; the trick is to cope with # unused parameters). quarry-marshal.$(OBJEXT) : quarry-marshal.c quarry-marshal.h $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(QUARRY_FULL_GTK_CFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) \ -o quarry-marshal.$(OBJEXT) \ -c quarry-marshal.c \ || (rm -f quarry-marshal.$(OBJEXT) ; exit 1) libguigtk_a_SOURCES = \ gtk-add-or-edit-label-dialog.c \ gtk-clock.c \ gtk-color-button.c \ gtk-control-center.c \ gtk-file-dialog.c \ gtk-file-selector.c \ gtk-freezable-spin-button.c \ gtk-game-info-dialog.c \ gtk-games.c \ gtk-goban.c \ gtk-goban-base.c \ gtk-goban-window.c \ gtk-go-to-named-node-dialog.c \ gtk-gtp-client-interface.c \ gtk-help.c \ gtk-named-vbox.c \ gtk-new-game-dialog.c \ gtk-new-game-record-dialog.c \ gtk-parser-interface.c \ gtk-preferences.c \ gtk-progress-dialog.c \ gtk-qbox.c \ gtk-qhbox.c \ gtk-qvbox.c \ gtk-resume-game-dialog.c \ gtk-sgf-tree-signal-proxy.c \ gtk-sgf-tree-view.c \ gtk-tile-set.c \ gtk-utils.c \ gui-back-end.c \ quarry-assistant.c \ quarry-find-dialog.c \ quarry-history-text-buffer.c \ quarry-message-dialog.c \ quarry-move-number-dialog.c \ quarry-save-confirmation-dialog.c \ quarry-stock.c \ quarry-text-buffer.c \ quarry-text-view.c \ \ gtk-add-or-edit-label-dialog.h \ gtk-clock.h \ gtk-color-button.h \ gtk-control-center.h \ gtk-file-dialog.h \ gtk-file-selector.h \ gtk-freezable-spin-button.h \ gtk-game-info-dialog.h \ gtk-games.h \ gtk-goban.h \ gtk-goban-base.h \ gtk-goban-window.h \ gtk-go-to-named-node-dialog.h \ gtk-gtp-client-interface.h \ gtk-help.h \ gtk-named-vbox.h \ gtk-new-game-dialog.h \ gtk-new-game-record-dialog.h \ gtk-parser-interface.h \ gtk-preferences.h \ gtk-progress-dialog.h \ gtk-qbox.h \ gtk-qhbox.h \ gtk-qvbox.h \ gtk-resume-game-dialog.h \ gtk-sgf-tree-signal-proxy.h \ gtk-sgf-tree-view.h \ gtk-thread-interface.h \ gtk-tile-set.h \ gtk-utils.h \ gui-back-end.h \ quarry-assistant.h \ quarry-find-dialog.h \ quarry-history-text-buffer.h \ quarry-message-dialog.h \ quarry-move-number-dialog.h \ quarry-save-confirmation-dialog.h \ quarry-stock.h \ quarry-text-buffer.h \ quarry-text-view.h \ \ $(LIST_FILES) nodist_libguigtk_a_SOURCES = \ $(LIST_GENERATED_FILES) \ \ quarry-marshal.c \ \ quarry-marshal.h BUILT_SOURCES = \ $(LIST_STAMP_FILES) \ \ quarry-marshal.h # This seems to be the best way of solving circular references. libguigtk_a_LIBADD = $(top_builddir)/src/gui-utils/libguiutils.a EXTRA_DIST = quarry-marshal.glist DISTCLEANFILES = *~ MOSTLYCLEANFILES = \ $(LIST_STAMP_FILES) \ $(LIST_GENERATED_FILES) \ \ quarry-marshal.c \ \ quarry-marshal.h quarry-0.2.0/src/gui-gtk/gtk-add-or-edit-label-dialog.c0000644000175000017500000001023410371154463021172 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "gtk-add-or-edit-label-dialog.h" #include "gtk-utils.h" #include enum { NODE_NAME, NODE_OBJECT, NUM_COLUMNS }; static void gtk_add_or_edit_label_dialog_init (GtkAddOrEditLabelDialog *dialog); GType gtk_add_or_edit_label_dialog_get_type (void) { static GType add_or_edit_label_dialog_type = 0; if (!add_or_edit_label_dialog_type) { static GTypeInfo add_or_edit_label_dialog_info = { sizeof (GtkAddOrEditLabelDialogClass), NULL, NULL, NULL, NULL, NULL, sizeof (GtkAddOrEditLabelDialog), 0, (GInstanceInitFunc) gtk_add_or_edit_label_dialog_init, NULL }; add_or_edit_label_dialog_type = g_type_register_static (GTK_TYPE_DIALOG, "GtkAddOrEditLabelDialog", &add_or_edit_label_dialog_info, 0); } return add_or_edit_label_dialog_type; } static void gtk_add_or_edit_label_dialog_init (GtkAddOrEditLabelDialog *dialog) { static const gchar *hint_text = N_("Although board labels are not limited in length, it is better to " "use only one or two characters long labels. Longer labels will " "not be visible immediately or at all in most clients."); GtkWidget *entry; GtkWidget *label; GtkWidget *hbox; GtkWidget *vbox; gtk_utils_make_window_only_horizontally_resizable (GTK_WINDOW (dialog)); entry = gtk_utils_create_entry (NULL, RETURN_ACTIVATES_DEFAULT); dialog->label_entry = GTK_ENTRY (entry); label = gtk_utils_create_mnemonic_label (_("Label _text:"), entry); hbox = gtk_utils_pack_in_box (GTK_TYPE_HBOX, QUARRY_SPACING, label, GTK_UTILS_FILL, entry, GTK_UTILS_PACK_DEFAULT, NULL); label = gtk_utils_create_left_aligned_label (_(hint_text)); gtk_label_set_line_wrap (GTK_LABEL (label), TRUE); vbox = gtk_utils_pack_in_box (GTK_TYPE_VBOX, QUARRY_SPACING_SMALL, hbox, GTK_UTILS_FILL, label, GTK_UTILS_FILL, NULL); gtk_widget_show_all (vbox); gtk_utils_standardize_dialog (&dialog->dialog, vbox); gtk_dialog_add_buttons (&dialog->dialog, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OK, GTK_RESPONSE_OK, NULL); gtk_dialog_set_default_response (&dialog->dialog, GTK_RESPONSE_OK); } GtkWidget * gtk_add_or_edit_label_dialog_new (void) { return GTK_WIDGET (g_object_new (GTK_TYPE_ADD_OR_EDIT_LABEL_DIALOG, NULL)); } void gtk_add_or_edit_label_dialog_set_label_text (GtkAddOrEditLabelDialog *dialog, const gchar *label_text) { g_return_if_fail (GTK_IS_ADD_OR_EDIT_LABEL_DIALOG (dialog)); gtk_entry_set_text (dialog->label_entry, label_text); } const gchar * gtk_add_or_edit_label_dialog_get_label_text (GtkAddOrEditLabelDialog *dialog) { g_return_val_if_fail (GTK_IS_ADD_OR_EDIT_LABEL_DIALOG (dialog), NULL); return gtk_entry_get_text (dialog->label_entry); } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/gtk-clock.c0000644000175000017500000005462410371145664015700 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* A widget that shows time for a player. Its LED-like look is * inspired by KDE system clock (its "digital" variant), but it shares * no code with KDE's widget, if only because that one is based on Qt. */ #include "gtk-clock.h" #include "gui-back-end.h" #include "time-control.h" #include #include #define CLOCK_DIGIT_WIDTH(symbol_parameters) \ ((symbol_parameters).segment_length + 2 \ + (symbol_parameters).segment_thickness) #define CLOCK_SEMICOLON_WIDTH(symbol_parameters) \ ((symbol_parameters).segment_thickness * 3 - 2 \ + CLOCK_SHADOW_OFFSET_X (symbol_parameters)) #define CLOCK_SYMBOL_HEIGHT(symbol_parameters) \ (2 * (symbol_parameters).segment_length \ + CLOCK_SHADOW_OFFSET_Y (symbol_parameters)) #define CLOCK_SHADOW_OFFSET_X(symbol_parameters) \ ((3 * ((symbol_parameters).segment_thickness + 1)) / 4) #define CLOCK_SHADOW_OFFSET_Y(symbol_parameters) \ (((symbol_parameters).segment_thickness + 1) / 2) typedef struct _TimeControlWatchSource TimeControlWatchSource; struct _TimeControlWatchSource { GSource source; GTimeVal clock_tick_time; }; typedef gdouble (* TimeControlWatchCallback) (gpointer user_data); static void gtk_clock_class_init (GtkClockClass *class); static void gtk_clock_init (GtkClock *clock); static void gtk_clock_realize (GtkWidget *widget); static void gtk_clock_size_request (GtkWidget *widget, GtkRequisition *requisition); static void set_background_pixmap (GtkClock *clock); static gboolean gtk_clock_expose (GtkWidget *widget, GdkEventExpose *event); static void draw_led_symbol (GtkClockSymbolParameters *symbol_parameters, GdkWindow *window, GdkGC *gc, gint symbol, gint x0, gint y0); static void draw_semicolon (GtkClockSymbolParameters *symbol_parameters, GdkWindow *window, GdkGC *gc, gint x0, gint y0); static void gtk_clock_finalize (GObject *object); inline static gdouble fetch_time_from_time_control (GtkClock *clock); static void do_set_time (GtkClock *clock, gdouble seconds, gint moves); static void ensure_clock_size (GtkClock *clock, gint seconds, gint moves); static gdouble clock_tick_callback (GtkClock *clock); inline static gboolean time_control_watch_prepare (GSource *source, gint *timeout); static gboolean time_control_watch_check (GSource *source); static gboolean time_control_watch_dispatch (GSource *source, GSourceFunc callback, gpointer user_data); static void time_control_watch_source_set_tick_time (TimeControlWatchSource *watch_source, GTimeVal *current_time, double time_till_next_clock_tick); static gchar *background_xpm[] = { "8 8 2 1", "x c #c6c7b9", "X c #9fa092", "xxxxxxxx", "XXXXXXXX", "xxxxxxxx", "XXXXXXXX", "xxxxxxxx", "XXXXXXXX", "xxxxxxxx", "XXXXXXXX", }; static gchar *highlighted_background_xpm[] = { "8 8 2 1", "x c #f2f3e2", "X c #d2d3c1", "xxxxxxxx", "XXXXXXXX", "xxxxxxxx", "XXXXXXXX", "xxxxxxxx", "XXXXXXXX", "xxxxxxxx", "XXXXXXXX", }; static GdkPixmap *background_pixmap = NULL; static GdkPixmap *highlighted_background_pixmap = NULL; static GSourceFuncs time_control_watch_functions = { time_control_watch_prepare, time_control_watch_check, time_control_watch_dispatch, NULL, }; GType gtk_clock_get_type (void) { static GType clock_type = 0; if (!clock_type) { static GTypeInfo clock_info = { sizeof (GtkClockClass), NULL, NULL, (GClassInitFunc) gtk_clock_class_init, NULL, NULL, sizeof (GtkClock), 1, (GInstanceInitFunc) gtk_clock_init, NULL }; clock_type = g_type_register_static (GTK_TYPE_WIDGET, "GtkClock", &clock_info, 0); } return clock_type; } static void gtk_clock_class_init (GtkClockClass *class) { GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class); G_OBJECT_CLASS (class)->finalize = gtk_clock_finalize; widget_class->realize = gtk_clock_realize; widget_class->expose_event = gtk_clock_expose; widget_class->size_request = gtk_clock_size_request; } static void gtk_clock_init (GtkClock *clock) { clock->normal_symbol_parameters.segment_length = 9; clock->normal_symbol_parameters.segment_thickness = 2; clock->small_symbol_parameters.segment_length = 7; clock->small_symbol_parameters.segment_thickness = 2; clock->max_hours_positions = 0; clock->max_moves_positions = 0; clock->seconds = -1; clock->moves = -1; clock->is_highlighted = FALSE; clock->time_control = NULL; clock->time_control_watch_source = NULL; } GtkWidget * gtk_clock_new (void) { return GTK_WIDGET (g_object_new (GTK_TYPE_CLOCK, NULL)); } static void gtk_clock_realize (GtkWidget *widget) { GdkWindowAttr attributes; static const gint attributes_mask = (GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP); static const gint event_mask = GDK_EXPOSURE_MASK; GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED); attributes.event_mask = gtk_widget_get_events (widget) | event_mask; attributes.x = widget->allocation.x; attributes.y = widget->allocation.y; attributes.width = widget->allocation.width; attributes.height = widget->allocation.height; attributes.wclass = GDK_INPUT_OUTPUT; attributes.visual = gtk_widget_get_visual (widget); attributes.colormap = gtk_widget_get_colormap (widget); attributes.window_type = GDK_WINDOW_CHILD; widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask); gdk_window_set_user_data (widget->window, widget); widget->style = gtk_style_attach (widget->style, widget->window); set_background_pixmap (GTK_CLOCK (widget)); } static void set_background_pixmap (GtkClock *clock) { GtkWidget *widget = GTK_WIDGET (clock); GdkPixmap **pixmap = (clock->is_highlighted ? &highlighted_background_pixmap : &background_pixmap); gchar **xpm_data = (clock->is_highlighted ? highlighted_background_xpm : background_xpm); if (!*pixmap) { *pixmap = gdk_pixmap_create_from_xpm_d (widget->window, NULL, NULL, xpm_data); gui_back_end_register_object_to_finalize (*pixmap); } gdk_window_set_back_pixmap (widget->window, *pixmap, FALSE); } static void gtk_clock_size_request (GtkWidget *widget, GtkRequisition *requisition) { GtkClock *clock = GTK_CLOCK (widget); const gint normal_digit_width = CLOCK_DIGIT_WIDTH (clock->normal_symbol_parameters); requisition->width = (((clock->max_hours_positions + 4) * normal_digit_width) + ((clock->max_hours_positions > 0 ? 2 : 1) * CLOCK_SEMICOLON_WIDTH (clock->normal_symbol_parameters)) + 4 * clock->normal_symbol_parameters.segment_thickness); if (clock->max_moves_positions > 0) { requisition->width += (normal_digit_width + (clock->max_moves_positions * CLOCK_DIGIT_WIDTH (clock->small_symbol_parameters))); } requisition->height = (CLOCK_SYMBOL_HEIGHT (clock->normal_symbol_parameters) + 2 * (clock->normal_symbol_parameters.segment_thickness + 1) + CLOCK_SHADOW_OFFSET_Y (clock->normal_symbol_parameters)); } static gboolean gtk_clock_expose (GtkWidget *widget, GdkEventExpose *event) { GtkClock *clock = GTK_CLOCK (widget); GdkGC *gc = gdk_gc_new (widget->window); const gint normal_digit_width = CLOCK_DIGIT_WIDTH (clock->normal_symbol_parameters); const gint normal_semicolon_width = CLOCK_SEMICOLON_WIDTH (clock->normal_symbol_parameters); const gint small_digit_width = CLOCK_DIGIT_WIDTH (clock->small_symbol_parameters); int pass; UNUSED (event); if (!GTK_WIDGET_DRAWABLE (widget)) return FALSE; gdk_gc_set_line_attributes (gc, 0, GDK_LINE_SOLID, GDK_CAP_NOT_LAST, GDK_JOIN_ROUND); for (pass = 0; pass < 2; pass++) { static GdkColor black_color = { 0, 0, 0, 0 }; static GdkColor gray_color = { 0, 0x8000, 0x8000, 0x8000 }; int x = (widget->allocation.width + 1 - clock->normal_symbol_parameters.segment_thickness); int y = clock->normal_symbol_parameters.segment_thickness + 1; int k; gdk_gc_set_rgb_fg_color (gc, pass == 0 ? &gray_color : &black_color); if (clock->max_moves_positions > 0) { int x_moves = x; int y_moves = (y + CLOCK_SYMBOL_HEIGHT (clock->normal_symbol_parameters) - CLOCK_SYMBOL_HEIGHT (clock->small_symbol_parameters)); if (pass == 0) y_moves += CLOCK_SHADOW_OFFSET_Y (clock->small_symbol_parameters); else x_moves -= CLOCK_SHADOW_OFFSET_X (clock->small_symbol_parameters); if (clock->moves > 0) { k = clock->moves; do { draw_led_symbol (&clock->small_symbol_parameters, widget->window, gc, k % 10, x_moves -= small_digit_width, y_moves); } while ((k /= 10) > 0); } else { for (k = 0; k < clock->max_moves_positions; k++) { draw_led_symbol (&clock->small_symbol_parameters, widget->window, gc, -1, x_moves -= small_digit_width, y_moves); } } x -= clock->max_moves_positions * small_digit_width + normal_digit_width; } if (pass == 0) y += CLOCK_SHADOW_OFFSET_Y (clock->normal_symbol_parameters); else x -= CLOCK_SHADOW_OFFSET_X (clock->normal_symbol_parameters); k = (clock->seconds >= 0 ? clock->seconds : -60 * 60 + 1); /* Seconds. */ draw_led_symbol (&clock->normal_symbol_parameters, widget->window, gc, k % 10, x -= normal_digit_width, y); k /= 10; draw_led_symbol (&clock->normal_symbol_parameters, widget->window, gc, k % 6, x -= normal_digit_width, y); k /= 6; /* A semicolon separating minutes and seconds. */ draw_semicolon (&clock->normal_symbol_parameters, widget->window, gc, x -= normal_semicolon_width, y); /* Minutes. */ draw_led_symbol (&clock->normal_symbol_parameters, widget->window, gc, k % 10, x -= normal_digit_width, y); k /= 10; draw_led_symbol (&clock->normal_symbol_parameters, widget->window, gc, k % 6, x -= normal_digit_width, y); k /= 6; if (k > 0) { /* A semicolon separating hours and minutes. */ draw_semicolon (&clock->normal_symbol_parameters, widget->window, gc, x -= normal_semicolon_width, y); /* Hours. */ do { draw_led_symbol (&clock->normal_symbol_parameters, widget->window, gc, k % 10, x -= normal_digit_width, y); } while ((k /= 10) > 0); } } g_object_unref (gc); return FALSE; } #define SET_POINT(index, _x, _y) \ (points[index].x = (_x), points[index].y = (_y)) static void draw_led_symbol (GtkClockSymbolParameters *symbol_parameters, GdkWindow *window, GdkGC *gc, gint symbol, gint x0, gint y0) { static const guchar segment_masks[11] = { 0x77, 0x24, 0x5d, 0x6d, 0x2e, 0x6b, 0x7b, 0x25, 0x7f, 0x6f, 0x08 }; GdkPoint points[6]; gint num_points; const gint segment_length = symbol_parameters->segment_length; const gint segment_thickness = symbol_parameters->segment_thickness - 1; const gint x1 = x0 + segment_length; const gint y1 = y0 + segment_length; const gint y2 = y0 + 2 * segment_length; const gint y1_up = y1 - (segment_thickness + 1) / 2; const gint y1_down = y1 + (segment_thickness) / 2; guchar segment_mask; gint segment_index; if (0 <= symbol && symbol <= 9) segment_mask = segment_masks[symbol]; else segment_mask = segment_masks[10]; for (segment_index = 0; segment_index < 7; segment_index++) { if (!(segment_mask & (1 << segment_index))) continue; if (segment_index != 3) { switch (segment_index) { case 0: SET_POINT (0, x0 + 1, y0); SET_POINT (1, x1 - 1, y0); SET_POINT (2, x1 - 1 - segment_thickness, y0 + segment_thickness); SET_POINT (3, x0 + 1 + segment_thickness, y0 + segment_thickness); break; case 1: SET_POINT (0, x0, y0 + 1); SET_POINT (1, x0, y1 - 1); SET_POINT (2, x0 + segment_thickness, y1_up - 1); SET_POINT (3, x0 + segment_thickness, y0 + 1 + segment_thickness); break; case 2: SET_POINT (0, x1, y0 + 1); SET_POINT (1, x1, y1 - 1); SET_POINT (2, x1 - segment_thickness, y1_up - 1); SET_POINT (3, x1 - segment_thickness, y0 + 1 + segment_thickness); break; case 4: SET_POINT (0, x0, y1 + 1); SET_POINT (1, x0, y2 - 1); SET_POINT (2, x0 + segment_thickness, y2 - 1 - segment_thickness); SET_POINT (3, x0 + segment_thickness, y1_down + 1); break; case 5: SET_POINT (0, x1, y1 + 1); SET_POINT (1, x1, y2 - 1); SET_POINT (2, x1 - segment_thickness, y2 - 1 - segment_thickness); SET_POINT (3, x1 - segment_thickness, y1_down + 1); break; case 6: SET_POINT (0, x0 + 1, y2); SET_POINT (1, x1 - 1, y2); SET_POINT (2, x1 - 1 - segment_thickness, y2 - segment_thickness); SET_POINT (3, x0 + 1 + segment_thickness, y2 - segment_thickness); break; } num_points = 4; } else { SET_POINT (0, x0 + 2, y1); SET_POINT (1, x0 + 1 + segment_thickness, y1_up); SET_POINT (2, x1 - 1 - segment_thickness, y1_up); SET_POINT (3, x1 - 2, y1); SET_POINT (4, x1 - 1 - segment_thickness, y1_down); SET_POINT (5, x0 + 1 + segment_thickness, y1_down); num_points = 6; } /* This is an ugly piece of code, but filled polygons don't look * good. Polygons that are both filled and outlined are much * nicer. */ gdk_draw_polygon (window, gc, FALSE, points, num_points); gdk_draw_polygon (window, gc, TRUE, points, num_points); } } static void draw_semicolon (GtkClockSymbolParameters *symbol_parameters, GdkWindow *window, GdkGC *gc, gint x0, gint y0) { const gint segment_length = symbol_parameters->segment_length; const gint segment_thickness = symbol_parameters->segment_thickness; int k; for (k = 0, x0 += segment_thickness - 1, y0 += segment_length / 2; k < 2; k++, y0 += segment_length) { GdkPoint points[4]; SET_POINT (0, x0, y0); SET_POINT (1, x0 + segment_thickness, y0); SET_POINT (2, x0 + segment_thickness, y0 + segment_thickness); SET_POINT (3, x0, y0 + segment_thickness); gdk_draw_polygon (window, gc, TRUE, points, 4); } } static void gtk_clock_finalize (GObject *object) { GtkClock *clock = GTK_CLOCK (object); if (clock->time_control_watch_source > 0) g_source_destroy (clock->time_control_watch_source); } void gtk_clock_set_time (GtkClock *clock, gdouble seconds, gint moves) { g_return_if_fail (GTK_IS_CLOCK (clock)); g_return_if_fail (!clock->time_control); do_set_time (clock, seconds, moves); } void gtk_clock_use_time_control (GtkClock *clock, const TimeControl *time_control, GtkClockOutOfTimeCallback out_of_time_callback, gpointer user_data) { g_return_if_fail (GTK_IS_CLOCK (clock)); if (clock->time_control_watch_source > 0) { g_source_destroy (clock->time_control_watch_source); clock->time_control_watch_source = NULL; } clock->time_control = time_control; clock->out_of_time_callback = out_of_time_callback; clock->user_data = user_data; if (time_control) { ensure_clock_size (clock, MAX (time_control->main_time, time_control->overtime_length), time_control->moves_per_overtime); fetch_time_from_time_control (clock); gtk_clock_time_control_state_changed (clock); } } void gtk_clock_time_control_state_changed (GtkClock *clock) { g_return_if_fail (GTK_IS_CLOCK (clock)); g_return_if_fail (clock->time_control); if (clock->time_control_watch_source && !clock->time_control->is_active) { g_source_destroy (clock->time_control_watch_source); clock->time_control_watch_source = NULL; fetch_time_from_time_control (clock); } else if (!clock->time_control_watch_source && clock->time_control->is_active) { GTimeVal current_time; gdouble time_till_next_clock_tick = time_control_get_time_till_seconds_update (clock->time_control); clock->time_control_watch_source = g_source_new (&time_control_watch_functions, sizeof (TimeControlWatchSource)); g_get_current_time (¤t_time); time_control_watch_source_set_tick_time ((TimeControlWatchSource *) clock->time_control_watch_source, ¤t_time, time_till_next_clock_tick); g_source_set_callback (clock->time_control_watch_source, (GSourceFunc) clock_tick_callback, clock, NULL); g_source_attach (clock->time_control_watch_source, NULL); if (time_control_is_short_on_time (clock->time_control)) { clock->is_highlighted = TRUE; if (GTK_WIDGET_REALIZED (clock)) { set_background_pixmap (clock); gtk_widget_queue_draw (GTK_WIDGET (clock)); } } } } inline static double fetch_time_from_time_control (GtkClock *clock) { gint moves_to_play; gdouble seconds = time_control_get_clock_seconds (clock->time_control, &moves_to_play); do_set_time (clock, seconds, moves_to_play); return seconds; } static void do_set_time (GtkClock *clock, gdouble seconds, gint moves) { gint seconds_int = (seconds >= 0.0 ? (gint) ceil (seconds) : -1); if (moves < 0) moves = -1; if (clock->seconds != seconds_int || clock->moves != moves) { clock->seconds = seconds_int; clock->moves = moves; if (clock->is_highlighted || (clock->time_control && clock->time_control->is_active && time_control_is_short_on_time (clock->time_control))) { clock->is_highlighted = !clock->is_highlighted; if (GTK_WIDGET_REALIZED (clock)) set_background_pixmap (clock); } gtk_widget_queue_draw (GTK_WIDGET (clock)); ensure_clock_size (clock, seconds_int, moves); } } static gdouble clock_tick_callback (GtkClock *clock) { double clock_seconds = fetch_time_from_time_control (clock); double time_till_next_clock_tick = time_control_get_time_till_seconds_update (clock->time_control); if (clock_seconds <= 0.0 && clock->out_of_time_callback) clock->out_of_time_callback (clock, clock->user_data); return time_till_next_clock_tick; } /* Ensure that the `clock' size is enough to display given time and * number of moves left. */ static void ensure_clock_size (GtkClock *clock, gint seconds, gint moves) { gint required_hours_positions; gint required_moves_positions; for (required_hours_positions = 0, seconds /= (60 * 60); seconds > 0; seconds /= 10) required_hours_positions++; for (required_moves_positions = 0; moves > 0; moves /= 10) required_moves_positions++; if (clock->max_hours_positions >= required_hours_positions && clock->max_moves_positions >= required_moves_positions) return; clock->max_hours_positions = MAX (clock->max_hours_positions, required_hours_positions); clock->max_moves_positions = MAX (clock->max_moves_positions, required_moves_positions); gtk_widget_queue_resize (GTK_WIDGET (clock)); } /* The purpose of this event source is to allow very in-time clock * updates (the error seems to be only about 0.01--0.02 seconds) and * avoid using timeout event source with very small interval. */ inline static gboolean time_control_watch_prepare (GSource *source, gint *timeout) { const TimeControlWatchSource *watch_source = (const TimeControlWatchSource *) source; GTimeVal current_time; g_source_get_current_time (source, ¤t_time); if (watch_source->clock_tick_time.tv_sec < current_time.tv_sec || (watch_source->clock_tick_time.tv_sec == current_time.tv_sec && watch_source->clock_tick_time.tv_usec <= current_time.tv_usec) /* The system clock must have been set backwards, update the * widget now. This will look weird, but at least it is better * than freezing the clock and doing weird things after a * (potentially long) delay. */ || watch_source->clock_tick_time.tv_sec > current_time.tv_sec + 1) { if (timeout) *timeout = 0; return TRUE; } if (timeout) { *timeout = (((watch_source->clock_tick_time.tv_sec - current_time.tv_sec) * 1000) + ((watch_source->clock_tick_time.tv_usec - current_time.tv_usec) / 1000)); } return FALSE; } static gboolean time_control_watch_check (GSource *source) { return time_control_watch_prepare (source, NULL); } static gboolean time_control_watch_dispatch (GSource *source, GSourceFunc callback, gpointer user_data) { GTimeVal current_time; TimeControlWatchSource *watch_source = (TimeControlWatchSource *) source; gdouble time_till_next_clock_tick = ((TimeControlWatchCallback) callback) (user_data); g_source_get_current_time (source, ¤t_time); time_control_watch_source_set_tick_time (watch_source, ¤t_time, time_till_next_clock_tick); return TRUE; } static void time_control_watch_source_set_tick_time (TimeControlWatchSource *watch_source, GTimeVal *current_time, double time_till_next_clock_tick) { /* Safety margin, to avoid false dispatches. */ time_till_next_clock_tick += 0.01; watch_source->clock_tick_time.tv_sec = current_time->tv_sec + (int) floor (time_till_next_clock_tick); watch_source->clock_tick_time.tv_usec = (current_time->tv_usec + (int) floor (time_till_next_clock_tick * 1000000.0)); if (watch_source->clock_tick_time.tv_usec >= 1000000) { watch_source->clock_tick_time.tv_sec += watch_source->clock_tick_time.tv_usec / 1000000; watch_source->clock_tick_time.tv_usec %= 1000000; } } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/gtk-color-button.c0000644000175000017500000007454710237132522017230 0ustar bartbart/* * GTK - The GIMP Toolkit * Copyright (C) 1998, 1999 Red Hat, Inc. * All rights reserved. * * This Library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This Library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with the Gnome Library; see the file COPYING.LIB. If * not, write to the Free Software Foundation, Inc., 51 Franklin * Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* Color picker button for GNOME * * Author: Federico Mena * * Modified by the GTK+ Team and others 2003. See the AUTHORS * file for a list of people on the GTK+ Team. See the ChangeLog * files for a list of changes. These files are distributed with * GTK+ at ftp://ftp.gtk.org/pub/gtk/. */ /* 2005-05-07 Paul Pogonyshev * * Update FSF address in the legal notice above. * * 2004-08-20 Paul Pogonyshev * * Return `gettext' _() macro invocation in the only user-visible * place. * * 2004-04-27 Paul Pogonyshev * * Remove `gettext' stuff as not yet supported in Quarry. * * Use `quarry_marshal_VOID__VOID' instead of * `_gtk_marshal_VOID__VOID'. * * Move `GtkColorButtonPrivate' into `GtkColorButton' (apparently * pre-2.4 GLib doesn't have support for privates). * * "Use" unused parameters with UNUSED() macro. * * 2004-04-26 Paul Pogonyshev * * Include into Quarry to backport to pre-2.4 GTK+. Modify to * compile with Quarry. Modify to exclude all code if compiling * with GTK+ 2.4 or later. Remove "Since: 2.4" comments. */ #include "gtk-color-button.h" #include "gtk-utils.h" #if !GTK_2_4_OR_LATER #include "quarry-marshal.h" #include /* Size of checks and gray levels for alpha compositing checkerboard */ #define CHECK_SIZE 4 #define CHECK_DARK 21845 /* 65535 / 3 */ #define CHECK_LIGHT 43690 /* Properties */ enum { PROP_0, PROP_USE_ALPHA, PROP_TITLE, PROP_COLOR, PROP_ALPHA }; /* Signals */ enum { COLOR_SET, LAST_SIGNAL }; static void gtk_color_button_class_init (GtkColorButtonClass *klass); static void gtk_color_button_init (GtkColorButton *color_button); /* gobject signals */ static void gtk_color_button_finalize (GObject *object); static void gtk_color_button_set_property (GObject *object, guint param_id, const GValue *value, GParamSpec *pspec); static void gtk_color_button_get_property (GObject *object, guint param_id, GValue *value, GParamSpec *pspec); /* gtkwidget signals */ static void gtk_color_button_realize (GtkWidget *widget); static void gtk_color_button_state_changed (GtkWidget *widget, GtkStateType previous_state); static void gtk_color_button_style_set (GtkWidget *widget, GtkStyle *previous_style); /* gtkbutton signals */ static void gtk_color_button_clicked (GtkButton *button); /* source side drag signals */ static void gtk_color_button_drag_begin (GtkWidget *widget, GdkDragContext *context, gpointer data); static void gtk_color_button_drag_data_get (GtkWidget *widget, GdkDragContext *context, GtkSelectionData *selection_data, guint info, guint time, GtkColorButton *color_button); /* target side drag signals */ static void gtk_color_button_drag_data_received (GtkWidget *widget, GdkDragContext *context, gint x, gint y, GtkSelectionData *selection_data, guint info, guint32 time, GtkColorButton *color_button); static gpointer parent_class = NULL; static guint color_button_signals[LAST_SIGNAL] = { 0 }; static GtkTargetEntry drop_types[] = { { "application/x-color", 0, 0 } }; GType gtk_color_button_get_type (void) { static GType color_button_type = 0; if (!color_button_type) { static const GTypeInfo color_button_info = { sizeof (GtkColorButtonClass), NULL, /* base_init */ NULL, /* base_finalize */ (GClassInitFunc) gtk_color_button_class_init, NULL, /* class_finalize */ NULL, /* class_data */ sizeof (GtkColorButton), 0, /* n_preallocs */ (GInstanceInitFunc) gtk_color_button_init, }; color_button_type = g_type_register_static (GTK_TYPE_BUTTON, "GtkColorButton", &color_button_info, 0); } return color_button_type; } static void gtk_color_button_class_init (GtkColorButtonClass *klass) { GObjectClass *gobject_class; GtkObjectClass *object_class; GtkWidgetClass *widget_class; GtkButtonClass *button_class; gobject_class = G_OBJECT_CLASS (klass); object_class = GTK_OBJECT_CLASS (klass); widget_class = GTK_WIDGET_CLASS (klass); button_class = GTK_BUTTON_CLASS (klass); parent_class = g_type_class_peek_parent (klass); gobject_class->get_property = gtk_color_button_get_property; gobject_class->set_property = gtk_color_button_set_property; gobject_class->finalize = gtk_color_button_finalize; widget_class->state_changed = gtk_color_button_state_changed; widget_class->realize = gtk_color_button_realize; widget_class->style_set = gtk_color_button_style_set; button_class->clicked = gtk_color_button_clicked; klass->color_set = NULL; /** * GtkColorButton:use-alpha: * * If this property is set to %TRUE, the color swatch on the button is rendered against a * checkerboard background to show its opacity and the opacity slider is displayed in the * color selection dialog. */ g_object_class_install_property (gobject_class, PROP_USE_ALPHA, g_param_spec_boolean ("use_alpha", "Use alpha", "Whether or not to give the color an alpha value", FALSE, (G_PARAM_READABLE | G_PARAM_WRITABLE))); /** * GtkColorButton:title: * * The title of the color selection dialog */ g_object_class_install_property (gobject_class, PROP_TITLE, g_param_spec_string ("title", "Title", "The title of the color selection dialog", "Pick a Color", (G_PARAM_READABLE | G_PARAM_WRITABLE))); /** * GtkColorButton:color: * * The selected color. */ g_object_class_install_property (gobject_class, PROP_COLOR, g_param_spec_boxed ("color", "Current Color", "The selected color", GDK_TYPE_COLOR, G_PARAM_READABLE | G_PARAM_WRITABLE)); /** * GtkColorButton:alpha: * * The selected opacity value (0 fully transparent, 65535 fully opaque). */ g_object_class_install_property (gobject_class, PROP_ALPHA, g_param_spec_uint ("alpha", "Current Alpha", "The selected opacity value (0 fully transparent, 65535 fully opaque)", 0, 65535, 65535, G_PARAM_READABLE | G_PARAM_WRITABLE)); /** * GtkColorButton::color-set: * @widget: the object which received the signal. * * The ::color-set signal is emitted when the user selects a color. When handling this signal, * use gtk_color_button_get_color() and gtk_color_button_get_alpha() to find out which color * was just selected. */ color_button_signals[COLOR_SET] = g_signal_new ("color_set", G_TYPE_FROM_CLASS (gobject_class), G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GtkColorButtonClass, color_set), NULL, NULL, quarry_marshal_VOID__VOID, G_TYPE_NONE, 0); } static void render (GtkColorButton *color_button) { gint dark_r, dark_g, dark_b; gint light_r, light_g, light_b; gint i, j, rowstride; gint width, height; gint c1[3], c2[3]; guchar *pixels; guint8 insensitive_r = 0; guint8 insensitive_g = 0; guint8 insensitive_b = 0; width = color_button->priv->drawing_area->allocation.width; height = color_button->priv->drawing_area->allocation.height; if (color_button->priv->pixbuf == NULL || gdk_pixbuf_get_width (color_button->priv->pixbuf) != width || gdk_pixbuf_get_height (color_button->priv->pixbuf) != height) { if (color_button->priv->pixbuf != NULL) g_object_unref (color_button->priv->pixbuf); color_button->priv->pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, width, height); } /* Compute dark and light check colors */ insensitive_r = GTK_WIDGET(color_button)->style->bg[GTK_STATE_INSENSITIVE].red >> 8; insensitive_g = GTK_WIDGET(color_button)->style->bg[GTK_STATE_INSENSITIVE].green >> 8; insensitive_b = GTK_WIDGET(color_button)->style->bg[GTK_STATE_INSENSITIVE].blue >> 8; if (color_button->priv->use_alpha) { dark_r = ((CHECK_DARK << 16) + (color_button->priv->color.red - CHECK_DARK) * color_button->priv->alpha) >> 24; dark_g = ((CHECK_DARK << 16) + (color_button->priv->color.green - CHECK_DARK) * color_button->priv->alpha) >> 24; dark_b = ((CHECK_DARK << 16) + (color_button->priv->color.blue - CHECK_DARK) * color_button->priv->alpha) >> 24; light_r = ((CHECK_LIGHT << 16) + (color_button->priv->color.red - CHECK_LIGHT) * color_button->priv->alpha) >> 24; light_g = ((CHECK_LIGHT << 16) + (color_button->priv->color.green - CHECK_LIGHT) * color_button->priv->alpha) >> 24; light_b = ((CHECK_LIGHT << 16) + (color_button->priv->color.blue - CHECK_LIGHT) * color_button->priv->alpha) >> 24; } else { dark_r = light_r = color_button->priv->color.red >> 8; dark_g = light_g = color_button->priv->color.green >> 8; dark_b = light_b = color_button->priv->color.blue >> 8; } /* Fill image buffer */ pixels = gdk_pixbuf_get_pixels (color_button->priv->pixbuf); rowstride = gdk_pixbuf_get_rowstride (color_button->priv->pixbuf); for (j = 0; j < height; j++) { if ((j / CHECK_SIZE) & 1) { c1[0] = dark_r; c1[1] = dark_g; c1[2] = dark_b; c2[0] = light_r; c2[1] = light_g; c2[2] = light_b; } else { c1[0] = light_r; c1[1] = light_g; c1[2] = light_b; c2[0] = dark_r; c2[1] = dark_g; c2[2] = dark_b; } for (i = 0; i < width; i++) { if (!GTK_WIDGET_SENSITIVE (GTK_WIDGET (color_button)) && (i+j)%2) { *(pixels + j * rowstride + i * 3) = insensitive_r; *(pixels + j * rowstride + i * 3 + 1) = insensitive_g; *(pixels + j * rowstride + i * 3 + 2) = insensitive_b; } else if ((i / CHECK_SIZE) & 1) { *(pixels + j * rowstride + i * 3) = c1[0]; *(pixels + j * rowstride + i * 3 + 1) = c1[1]; *(pixels + j * rowstride + i * 3 + 2) = c1[2]; } else { *(pixels + j * rowstride + i * 3) = c2[0]; *(pixels + j * rowstride + i * 3 + 1) = c2[1]; *(pixels + j * rowstride + i * 3 + 2) = c2[2]; } } } } /* Handle exposure events for the color picker's drawing area */ static gint expose_event (GtkWidget *widget, GdkEventExpose *event, gpointer data) { GtkColorButton *color_button = GTK_COLOR_BUTTON (data); gint width = color_button->priv->drawing_area->allocation.width; gint height = color_button->priv->drawing_area->allocation.height; if (color_button->priv->pixbuf == NULL || width != gdk_pixbuf_get_width (color_button->priv->pixbuf) || height != gdk_pixbuf_get_height (color_button->priv->pixbuf)) render (color_button); gdk_draw_pixbuf (widget->window, color_button->priv->gc, color_button->priv->pixbuf, event->area.x, event->area.y, event->area.x, event->area.y, event->area.width, event->area.height, GDK_RGB_DITHER_MAX, event->area.x, event->area.y); return FALSE; } static void gtk_color_button_realize (GtkWidget *widget) { GtkColorButton *color_button = GTK_COLOR_BUTTON (widget); GTK_WIDGET_CLASS (parent_class)->realize (widget); if (color_button->priv->gc == NULL) color_button->priv->gc = gdk_gc_new (widget->window); render (color_button); } static void gtk_color_button_style_set (GtkWidget *widget, GtkStyle *previous_style) { GtkColorButton *color_button = GTK_COLOR_BUTTON (widget); GTK_WIDGET_CLASS (parent_class)->style_set (widget, previous_style); if (GTK_WIDGET_REALIZED (widget)) { if (color_button->priv->pixbuf != NULL) g_object_unref (color_button->priv->pixbuf); color_button->priv->pixbuf = NULL; } } static void gtk_color_button_state_changed (GtkWidget *widget, GtkStateType previous_state) { GtkColorButton *color_button = GTK_COLOR_BUTTON (widget); if (widget->state == GTK_STATE_INSENSITIVE || previous_state == GTK_STATE_INSENSITIVE) { if (color_button->priv->pixbuf != NULL) g_object_unref (color_button->priv->pixbuf); color_button->priv->pixbuf = NULL; } } static void gtk_color_button_drag_data_received (GtkWidget *widget, GdkDragContext *context, gint x, gint y, GtkSelectionData *selection_data, guint info, guint32 time, GtkColorButton *color_button) { guint16 *dropped; UNUSED(widget); UNUSED(context); UNUSED(x); UNUSED(y); UNUSED(info); UNUSED(time); if (selection_data->length < 0) return; /* We accept drops with the wrong format, since the KDE color * chooser incorrectly drops application/x-color with format 8. */ if (selection_data->length != 8) { g_warning ("Received invalid color data\n"); return; } dropped = (guint16 *)selection_data->data; color_button->priv->color.red = dropped[0]; color_button->priv->color.green = dropped[1]; color_button->priv->color.blue = dropped[2]; color_button->priv->alpha = dropped[3]; if (color_button->priv->pixbuf != NULL) g_object_unref (color_button->priv->pixbuf); color_button->priv->pixbuf = NULL; gtk_widget_queue_draw (color_button->priv->drawing_area); g_signal_emit (color_button, color_button_signals[COLOR_SET], 0); g_object_freeze_notify (G_OBJECT (color_button)); g_object_notify (G_OBJECT (color_button), "color"); g_object_notify (G_OBJECT (color_button), "alpha"); g_object_thaw_notify (G_OBJECT (color_button)); } static void set_color_icon (GdkDragContext *context, GdkColor *color) { GdkPixbuf *pixbuf; guint32 pixel; pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, 48, 32); pixel = ((color->red & 0xff00) << 16) | ((color->green & 0xff00) << 8) | (color->blue & 0xff00); gdk_pixbuf_fill (pixbuf, pixel); gtk_drag_set_icon_pixbuf (context, pixbuf, -2, -2); g_object_unref (pixbuf); } static void gtk_color_button_drag_begin (GtkWidget *widget, GdkDragContext *context, gpointer data) { GtkColorButton *color_button = data; UNUSED(widget); set_color_icon (context, &color_button->priv->color); } static void gtk_color_button_drag_data_get (GtkWidget *widget, GdkDragContext *context, GtkSelectionData *selection_data, guint info, guint time, GtkColorButton *color_button) { guint16 dropped[4]; UNUSED(widget); UNUSED(context); UNUSED(info); UNUSED(time); dropped[0] = color_button->priv->color.red; dropped[1] = color_button->priv->color.green; dropped[2] = color_button->priv->color.blue; dropped[3] = color_button->priv->alpha; gtk_selection_data_set (selection_data, selection_data->target, 16, (guchar *)dropped, 8); } static void gtk_color_button_init (GtkColorButton *color_button) { GtkWidget *alignment; GtkWidget *frame; PangoLayout *layout; PangoRectangle rect; /* Create the widgets */ color_button->priv = &color_button->the_priv; gtk_widget_push_composite_child (); alignment = gtk_alignment_new (0.5, 0.5, 0.5, 1.0); gtk_container_set_border_width (GTK_CONTAINER (alignment), 1); gtk_container_add (GTK_CONTAINER (color_button), alignment); gtk_widget_show (alignment); frame = gtk_frame_new (NULL); gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_OUT); gtk_container_add (GTK_CONTAINER (alignment), frame); gtk_widget_show (frame); color_button->priv->drawing_area = gtk_drawing_area_new (); layout = gtk_widget_create_pango_layout (GTK_WIDGET (color_button), "Black"); pango_layout_get_pixel_extents (layout, NULL, &rect); gtk_widget_set_size_request (color_button->priv->drawing_area, rect.width - 2, rect.height - 2); g_signal_connect (color_button->priv->drawing_area, "expose_event", G_CALLBACK (expose_event), color_button); gtk_container_add (GTK_CONTAINER (frame), color_button->priv->drawing_area); gtk_widget_show (color_button->priv->drawing_area); color_button->priv->title = g_strdup (_("Pick a Color")); /* default title */ /* Create the buffer for the image so that we can create an image. * Also create the picker's pixmap. */ color_button->priv->pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, rect.width, rect.height); color_button->priv->gc = NULL; /* Start with opaque black, alpha disabled */ color_button->priv->color.red = 0; color_button->priv->color.green = 0; color_button->priv->color.blue = 0; color_button->priv->alpha = 65535; color_button->priv->use_alpha = FALSE; gtk_drag_dest_set (GTK_WIDGET (color_button), GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_HIGHLIGHT | GTK_DEST_DEFAULT_DROP, drop_types, 1, GDK_ACTION_COPY); gtk_drag_source_set (GTK_WIDGET(color_button), GDK_BUTTON1_MASK|GDK_BUTTON3_MASK, drop_types, 1, GDK_ACTION_COPY); g_signal_connect (color_button, "drag_begin", G_CALLBACK (gtk_color_button_drag_begin), color_button); g_signal_connect (color_button, "drag_data_received", G_CALLBACK (gtk_color_button_drag_data_received), color_button); g_signal_connect (color_button, "drag_data_get", G_CALLBACK (gtk_color_button_drag_data_get), color_button); gtk_widget_pop_composite_child (); } static void gtk_color_button_finalize (GObject *object) { GtkColorButton *color_button = GTK_COLOR_BUTTON (object); if (color_button->priv->gc != NULL) g_object_unref (G_OBJECT (color_button->priv->gc)); color_button->priv->gc = NULL; if (color_button->priv->cs_dialog != NULL) gtk_widget_destroy (color_button->priv->cs_dialog); color_button->priv->cs_dialog = NULL; if (color_button->priv->pixbuf != NULL) g_object_unref (color_button->priv->pixbuf); color_button->priv->pixbuf = NULL; g_free (color_button->priv->title); color_button->priv->title = NULL; G_OBJECT_CLASS (parent_class)->finalize (object); } /** * gtk_color_button_new: * * Creates a new color button. This returns a widget in the form of * a small button containing a swatch representing the current selected * color. When the button is clicked, a color-selection dialog will open, * allowing the user to select a color. The swatch will be updated to reflect * the new color when the user finishes. * * Returns: a new color button. */ GtkWidget * gtk_color_button_new (void) { return g_object_new (GTK_TYPE_COLOR_BUTTON, NULL); } /** * gtk_color_button_new_with_color: * @color: A #GdkColor to set the current color with. * * Creates a new color button. * * Returns: a new color button. */ GtkWidget * gtk_color_button_new_with_color (const GdkColor *color) { return g_object_new (GTK_TYPE_COLOR_BUTTON, "color", color, NULL); } static void dialog_ok_clicked (GtkWidget *widget, gpointer data) { GtkColorButton *color_button = GTK_COLOR_BUTTON (data); GtkColorSelection *color_selection; UNUSED(widget); color_selection = GTK_COLOR_SELECTION (GTK_COLOR_SELECTION_DIALOG (color_button->priv->cs_dialog)->colorsel); gtk_color_selection_get_current_color (color_selection, &color_button->priv->color); color_button->priv->alpha = gtk_color_selection_get_current_alpha (color_selection); if (color_button->priv->pixbuf != NULL) g_object_unref (color_button->priv->pixbuf); color_button->priv->pixbuf = NULL; gtk_widget_hide (color_button->priv->cs_dialog); gtk_widget_queue_draw (color_button->priv->drawing_area); g_signal_emit (color_button, color_button_signals[COLOR_SET], 0); g_object_freeze_notify (G_OBJECT (color_button)); g_object_notify (G_OBJECT (color_button), "color"); g_object_notify (G_OBJECT (color_button), "alpha"); g_object_thaw_notify (G_OBJECT (color_button)); } static gboolean dialog_destroy (GtkWidget *widget, gpointer data) { GtkColorButton *color_button = GTK_COLOR_BUTTON (data); UNUSED(widget); color_button->priv->cs_dialog = NULL; return FALSE; } static void dialog_cancel_clicked (GtkWidget *widget, gpointer data) { GtkColorButton *color_button = GTK_COLOR_BUTTON (data); UNUSED(widget); gtk_widget_hide (color_button->priv->cs_dialog); } static void gtk_color_button_clicked (GtkButton *button) { GtkColorButton *color_button = GTK_COLOR_BUTTON (button); GtkColorSelectionDialog *color_dialog; /* if dialog already exists, make sure it's shown and raised */ if (!color_button->priv->cs_dialog) { /* Create the dialog and connects its buttons */ GtkWidget *parent; parent = gtk_widget_get_toplevel (GTK_WIDGET (color_button)); color_button->priv->cs_dialog = gtk_color_selection_dialog_new (color_button->priv->title); color_dialog = GTK_COLOR_SELECTION_DIALOG (color_button->priv->cs_dialog); if (parent) gtk_window_set_transient_for (GTK_WINDOW (color_dialog), GTK_WINDOW (parent)); g_signal_connect (color_dialog->ok_button, "clicked", G_CALLBACK (dialog_ok_clicked), color_button); g_signal_connect (color_dialog->cancel_button, "clicked", G_CALLBACK (dialog_cancel_clicked), color_button); g_signal_connect (color_dialog, "destroy", G_CALLBACK (dialog_destroy), color_button); /* If there is a grabbed window, set new dialog as modal */ if (gtk_grab_get_current ()) gtk_window_set_modal (GTK_WINDOW (color_button->priv->cs_dialog),TRUE); } color_dialog = GTK_COLOR_SELECTION_DIALOG (color_button->priv->cs_dialog); gtk_color_selection_set_has_opacity_control (GTK_COLOR_SELECTION (color_dialog->colorsel), color_button->priv->use_alpha); gtk_color_selection_set_previous_color (GTK_COLOR_SELECTION (color_dialog->colorsel), &color_button->priv->color); gtk_color_selection_set_previous_alpha (GTK_COLOR_SELECTION (color_dialog->colorsel), color_button->priv->alpha); gtk_color_selection_set_current_color (GTK_COLOR_SELECTION (color_dialog->colorsel), &color_button->priv->color); gtk_color_selection_set_current_alpha (GTK_COLOR_SELECTION (color_dialog->colorsel), color_button->priv->alpha); gtk_window_present (GTK_WINDOW (color_button->priv->cs_dialog)); } /** * gtk_color_button_set_color: * @color_button: a #GtkColorButton. * @color: A #GdkColor to set the current color with. * * Sets the current color to be @color. **/ void gtk_color_button_set_color (GtkColorButton *color_button, const GdkColor *color) { g_return_if_fail (GTK_IS_COLOR_BUTTON (color_button)); color_button->priv->color.red = color->red; color_button->priv->color.green = color->green; color_button->priv->color.blue = color->blue; if (color_button->priv->pixbuf != NULL) g_object_unref (color_button->priv->pixbuf); color_button->priv->pixbuf = NULL; gtk_widget_queue_draw (color_button->priv->drawing_area); g_object_notify (G_OBJECT (color_button), "color"); } /** * gtk_color_button_set_alpha: * @color_button: a #GtkColorButton. * @alpha: an integer between 0 and 65535. * * Sets the current opacity to be @alpha. **/ void gtk_color_button_set_alpha (GtkColorButton *color_button, guint16 alpha) { g_return_if_fail (GTK_IS_COLOR_BUTTON (color_button)); color_button->priv->alpha = alpha; if (color_button->priv->pixbuf != NULL) g_object_unref (color_button->priv->pixbuf); color_button->priv->pixbuf = NULL; gtk_widget_queue_draw (color_button->priv->drawing_area); g_object_notify (G_OBJECT (color_button), "alpha"); } /** * gtk_color_button_get_color: * @color_button: a #GtkColorButton. * @color: a #GdkColor to fill in with the current color. * * Sets @color to be the current color in the #GtkColorButton widget. **/ void gtk_color_button_get_color (GtkColorButton *color_button, GdkColor *color) { g_return_if_fail (GTK_IS_COLOR_BUTTON (color_button)); color->red = color_button->priv->color.red; color->green = color_button->priv->color.green; color->blue = color_button->priv->color.blue; } /** * gtk_color_button_get_alpha: * @color_button: a #GtkColorButton. * * Returns the current alpha value. * * Return value: an integer between 0 and 65535. **/ guint16 gtk_color_button_get_alpha (GtkColorButton *color_button) { g_return_val_if_fail (GTK_IS_COLOR_BUTTON (color_button), 0); return color_button->priv->alpha; } /** * gtk_color_button_set_use_alpha: * @color_button: a #GtkColorButton. * @use_alpha: %TRUE if color button should use alpha channel, %FALSE if not. * * Sets whether or not the color button should use the alpha channel. */ void gtk_color_button_set_use_alpha (GtkColorButton *color_button, gboolean use_alpha) { g_return_if_fail (GTK_IS_COLOR_BUTTON (color_button)); use_alpha = (use_alpha != FALSE); if (color_button->priv->use_alpha != use_alpha) { color_button->priv->use_alpha = use_alpha; render (color_button); gtk_widget_queue_draw (color_button->priv->drawing_area); g_object_notify (G_OBJECT (color_button), "use_alpha"); } } /** * gtk_color_button_get_use_alpha: * @color_button: a #GtkColorButton. * * Does the color selection dialog use the alpha channel? * * Returns: %TRUE if the color sample uses alpha channel, %FALSE if not. */ gboolean gtk_color_button_get_use_alpha (GtkColorButton *color_button) { g_return_val_if_fail (GTK_IS_COLOR_BUTTON (color_button), FALSE); return color_button->priv->use_alpha; } /** * gtk_color_button_set_title: * @color_button: a #GtkColorButton * @title: String containing new window title. * * Sets the title for the color selection dialog. */ void gtk_color_button_set_title (GtkColorButton *color_button, const gchar *title) { gchar *old_title; g_return_if_fail (GTK_IS_COLOR_BUTTON (color_button)); old_title = color_button->priv->title; color_button->priv->title = g_strdup (title); g_free (old_title); if (color_button->priv->cs_dialog) gtk_window_set_title (GTK_WINDOW (color_button->priv->cs_dialog), color_button->priv->title); g_object_notify (G_OBJECT (color_button), "title"); } /** * gtk_color_button_get_title: * @color_button: a #GtkColorButton * * Gets the title of the color selection dialog. * * Returns: An internal string, do not free the return value */ G_CONST_RETURN gchar * gtk_color_button_get_title (GtkColorButton *color_button) { g_return_val_if_fail (GTK_IS_COLOR_BUTTON (color_button), NULL); return color_button->priv->title; } static void gtk_color_button_set_property (GObject *object, guint param_id, const GValue *value, GParamSpec *pspec) { GtkColorButton *color_button = GTK_COLOR_BUTTON (object); switch (param_id) { case PROP_USE_ALPHA: gtk_color_button_set_use_alpha (color_button, g_value_get_boolean (value)); break; case PROP_TITLE: gtk_color_button_set_title (color_button, g_value_get_string (value)); break; case PROP_COLOR: gtk_color_button_set_color (color_button, g_value_get_boxed (value)); break; case PROP_ALPHA: gtk_color_button_set_alpha (color_button, g_value_get_uint (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); break; } } static void gtk_color_button_get_property (GObject *object, guint param_id, GValue *value, GParamSpec *pspec) { GtkColorButton *color_button = GTK_COLOR_BUTTON (object); GdkColor color; switch (param_id) { case PROP_USE_ALPHA: g_value_set_boolean (value, gtk_color_button_get_use_alpha (color_button)); break; case PROP_TITLE: g_value_set_string (value, gtk_color_button_get_title (color_button)); break; case PROP_COLOR: gtk_color_button_get_color (color_button, &color); g_value_set_boxed (value, &color); break; case PROP_ALPHA: g_value_set_uint (value, gtk_color_button_get_alpha (color_button)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); break; } } #endif /* !GTK_2_4_OR_LATER */ quarry-0.2.0/src/gui-gtk/gtk-control-center.c0000644000175000017500000001636110521206733017527 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "gtk-control-center.h" #include "gtk-goban-window.h" #include "gtk-help.h" #include "gtk-new-game-dialog.h" #include "gtk-new-game-record-dialog.h" #include "gtk-parser-interface.h" #include "gtk-preferences.h" #include "gtk-resume-game-dialog.h" #include "gtk-utils.h" #include "quarry-stock.h" #include #include static GSList *windows = NULL; static int num_other_reasons_to_live = 0; static GtkWindow *control_center = NULL; void gtk_control_center_present (void) { if (!control_center) { GtkWidget *vbox; GtkWidget *new_game_button; GtkWidget *new_game_record_button; GtkWidget *open_game_record_button; GtkWidget *resume_game_button; GtkWidget *preferences_button; GtkWidget *quit_button; GtkWidget *help_button; GtkWidget *close_button; GtkAccelGroup *accel_group; control_center = (GtkWindow *) gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_control_center_window_created (control_center); gtk_utils_null_pointer_on_destroy (&control_center, TRUE); gtk_window_set_title (control_center, _("Quarry Control Center")); gtk_window_set_resizable (control_center, FALSE); gtk_container_set_border_width (GTK_CONTAINER (control_center), QUARRY_SPACING); accel_group = gtk_accel_group_new (); gtk_window_add_accel_group (control_center, accel_group); new_game_button = gtk_button_new_from_stock (QUARRY_STOCK_NEW_GAME); g_signal_connect (new_game_button, "clicked", G_CALLBACK (gtk_new_game_dialog_present), NULL); gtk_widget_add_accelerator (new_game_button, "clicked", accel_group, GDK_N, GDK_CONTROL_MASK, 0); new_game_record_button = gtk_button_new_with_mnemonic (_("Ne_w Game Record")); g_signal_connect (new_game_record_button, "clicked", G_CALLBACK (gtk_new_game_record_dialog_present), NULL); gtk_widget_add_accelerator (new_game_record_button, "clicked", accel_group, GDK_N, GDK_SHIFT_MASK | GDK_CONTROL_MASK, 0); open_game_record_button = gtk_button_new_from_stock (QUARRY_STOCK_OPEN_GAME_RECORD); g_signal_connect (open_game_record_button, "clicked", G_CALLBACK (gtk_parser_interface_present_default), NULL); gtk_widget_add_accelerator (open_game_record_button, "clicked", accel_group, GDK_O, GDK_CONTROL_MASK, 0); resume_game_button = gtk_button_new_with_mnemonic (_("_Resume Game")); g_signal_connect (resume_game_button, "clicked", G_CALLBACK (gtk_resume_game), NULL); preferences_button = gtk_button_new_from_stock (GTK_STOCK_PREFERENCES); g_signal_connect_swapped (preferences_button, "clicked", G_CALLBACK (gtk_preferences_dialog_present), GINT_TO_POINTER (-1)); quit_button = gtk_button_new_from_stock (GTK_STOCK_QUIT); g_signal_connect_swapped (quit_button, "clicked", G_CALLBACK (gtk_control_center_quit), NULL); gtk_widget_add_accelerator (quit_button, "clicked", accel_group, GDK_Q, GDK_CONTROL_MASK, 0); vbox = gtk_utils_pack_in_box (GTK_TYPE_VBOX, QUARRY_SPACING_SMALL, new_game_button, GTK_UTILS_FILL, new_game_record_button, GTK_UTILS_FILL, gtk_hseparator_new (), GTK_UTILS_FILL | QUARRY_SPACING_VERY_SMALL, open_game_record_button, GTK_UTILS_FILL, resume_game_button, GTK_UTILS_FILL, gtk_hseparator_new (), GTK_UTILS_FILL | QUARRY_SPACING_VERY_SMALL, preferences_button, GTK_UTILS_FILL, gtk_hseparator_new (), GTK_UTILS_FILL | QUARRY_SPACING_VERY_SMALL, quit_button, GTK_UTILS_FILL, NULL); gtk_container_add (GTK_CONTAINER (control_center), vbox); gtk_widget_show_all (vbox); /* Add invisible buttons, used only for adding accelerator. */ help_button = gtk_button_new (); g_signal_connect_swapped (help_button, "clicked", G_CALLBACK (gtk_help_display), NULL); gtk_widget_add_accelerator (help_button, "clicked", accel_group, GDK_F1, 0, 0); close_button = gtk_button_new (); g_signal_connect_swapped (close_button, "clicked", G_CALLBACK (gtk_widget_destroy), control_center); gtk_widget_add_accelerator (close_button, "clicked", accel_group, GDK_W, GDK_CONTROL_MASK, 0); #if GTK_2_4_OR_LATER g_signal_connect (help_button, "can-activate-accel", G_CALLBACK (gtk_true), NULL); g_signal_connect (close_button, "can-activate-accel", G_CALLBACK (gtk_true), NULL); #endif gtk_container_add (GTK_CONTAINER (vbox), help_button); gtk_container_add (GTK_CONTAINER (vbox), close_button); } gtk_window_present (control_center); } inline void gtk_control_center_window_created (GtkWindow *window) { windows = g_slist_prepend (windows, window); } gint gtk_control_center_window_destroyed (const GtkWindow *window) { GSList *element = g_slist_find (windows, window); if (element) { windows = g_slist_delete_link (windows, element); if (windows != NULL || num_other_reasons_to_live > 0) { if (control_center && windows->next == NULL) gtk_control_center_present (); } else gtk_main_quit (); return TRUE; } return FALSE; } inline void gtk_control_center_new_reason_to_live (void) { num_other_reasons_to_live++; } inline void gtk_control_center_lost_reason_to_live (void) { if (--num_other_reasons_to_live == 0 && windows == NULL) gtk_main_quit (); } void gtk_control_center_quit (void) { while (1) { GSList *element; for (element = windows; element; element = element->next) { if (GTK_IS_GOBAN_WINDOW (element->data)) { if (gtk_goban_window_stops_closing (GTK_GOBAN_WINDOW (element->data))) return; else { gtk_widget_destroy (GTK_WIDGET (element->data)); break; } } } if (!element) break; } if (control_center) gtk_widget_destroy (GTK_WIDGET (control_center)); while (windows) gtk_widget_destroy (GTK_WIDGET (windows->data)); } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/gtk-file-dialog.c0000644000175000017500000002317510456741325016756 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* Interface for hiding differences between GtkFileChooser and * GtkFileSelection. Since I personally don't like the former (not * very convenient for keyboard users), there is a preferences options * to use GtkFileSelection even on newer GTK+ versions. */ #include "gtk-file-dialog.h" #include "gtk-configuration.h" #include "gtk-control-center.h" #include "gtk-utils.h" #include "quarry-message-dialog.h" #include "quarry-stock.h" #include #include #if GTK_2_4_OR_LATER static void file_chooser_save_response (GtkWidget *dialog, gint response_id); #endif static void file_selection_open_response (GtkWidget *dialog, gint response_id); static void file_selection_save_response (GtkWidget *dialog, gint response_id); static gboolean check_if_directory_selected (GtkWidget *dialog, const gchar *filename); static gboolean check_if_overwriting_file (GtkWidget *dialog, const gchar *filename); static void overwrite_confirmation (GtkWidget *confirmation_dialog, gint response_id); GtkWidget * gtk_file_dialog_new (const gchar *title, GtkWindow *parent, gboolean for_opening, const gchar *affirmative_button_text) { GtkWidget *dialog; g_return_val_if_fail (title, NULL); g_return_val_if_fail (!parent || GTK_IS_WINDOW (parent), NULL); g_return_val_if_fail (affirmative_button_text, NULL); #if GTK_2_4_OR_LATER if (gtk_ui_configuration.use_gtk_file_chooser) { dialog = gtk_file_chooser_dialog_new (title, parent, (for_opening ? GTK_FILE_CHOOSER_ACTION_OPEN : GTK_FILE_CHOOSER_ACTION_SAVE), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, affirmative_button_text, GTK_RESPONSE_OK, NULL); gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK); if (!for_opening) { g_signal_connect (dialog, "response", G_CALLBACK (file_chooser_save_response), NULL); } } else { #endif /* GTK_2_4_OR_LATER */ dialog = gtk_file_selection_new (title); if (parent) { gtk_window_set_transient_for (GTK_WINDOW (dialog), parent); gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE); } g_signal_connect (dialog, "response", G_CALLBACK (for_opening ? file_selection_open_response : file_selection_save_response), NULL); #if GTK_2_4_OR_LATER } #endif return dialog; } gchar * gtk_file_dialog_get_filename (GtkWidget *dialog) { #if GTK_2_4_OR_LATER if (GTK_IS_FILE_CHOOSER (dialog)) return gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); #endif if (GTK_IS_FILE_SELECTION (dialog)) { return g_strdup (gtk_file_selection_get_filename (GTK_FILE_SELECTION (dialog))); } g_assert_not_reached (); return NULL; } /* Set current filename in the file selection dialog. `filename' * should be in UTF-8 rather than in file system encoding. */ void gtk_file_dialog_set_filename (GtkWidget *dialog, const gchar *filename) { #if GTK_2_4_OR_LATER if (GTK_IS_FILE_CHOOSER (dialog)) { if (g_path_is_absolute (filename)) { if (g_file_test (filename, G_FILE_TEST_EXISTS)) gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (dialog), filename); else { gchar *base_name = g_path_get_basename (filename); if (strcmp (base_name, G_DIR_SEPARATOR_S) != 0 && strcmp (base_name, ".") != 0) { gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), base_name); } g_free (base_name); } } else gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), filename); return; } #endif if (GTK_IS_FILE_SELECTION (dialog)) { gchar *file_system_filename = g_filename_from_utf8 (filename, -1, NULL, NULL, NULL); gtk_file_selection_set_filename (GTK_FILE_SELECTION (dialog), file_system_filename); g_free (file_system_filename); return; } g_assert_not_reached (); return; } void gtk_file_dialog_set_current_name (GtkWidget *dialog, const gchar *filename) { #if GTK_2_4_OR_LATER if (GTK_IS_FILE_CHOOSER (dialog)) { gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), filename); return; } #endif /* For GtkFileSelection there is no distinction. */ gtk_file_dialog_set_filename (dialog, filename); } #if GTK_2_4_OR_LATER static void file_chooser_save_response (GtkWidget *dialog, gint response_id) { if (response_id == GTK_RESPONSE_OK) { gchar *filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); gboolean confirmation_asked = check_if_overwriting_file (dialog, filename); g_free (filename); if (confirmation_asked) g_signal_stop_emission_by_name (dialog, "response"); } } #endif /* GTK_2_4_OR_LATER */ static void file_selection_open_response (GtkWidget *dialog, gint response_id) { if (response_id == GTK_RESPONSE_OK) { const gchar *filename = gtk_file_selection_get_filename (GTK_FILE_SELECTION (dialog)); if (check_if_directory_selected (dialog, filename)) g_signal_stop_emission_by_name (dialog, "response"); } } static void file_selection_save_response (GtkWidget *dialog, gint response_id) { if (response_id == GTK_RESPONSE_OK) { const gchar *filename = gtk_file_selection_get_filename (GTK_FILE_SELECTION (dialog)); if (check_if_directory_selected (dialog, filename)) { g_signal_stop_emission_by_name (dialog, "response"); return; } if (check_if_overwriting_file (dialog, filename)) g_signal_stop_emission_by_name (dialog, "response"); } } static gboolean check_if_directory_selected (GtkWidget *dialog, const gchar *filename) { if (*filename && g_file_test (filename, G_FILE_TEST_IS_DIR)) { /* Don't try to read directory, just browse into it. */ if (filename[strlen (filename) - 1] != G_DIR_SEPARATOR) { gchar *directory_name = g_strconcat (filename, G_DIR_SEPARATOR_S, NULL); gtk_file_selection_set_filename (GTK_FILE_SELECTION (dialog), directory_name); g_free (directory_name); } else gtk_file_selection_set_filename (GTK_FILE_SELECTION (dialog), filename); return TRUE; } return FALSE; } static gboolean check_if_overwriting_file (GtkWidget *dialog, const gchar *filename) { if (*filename && g_file_test (filename, G_FILE_TEST_EXISTS)) { static const gchar *hint = N_("Note that all information in the existing file will be lost " "permanently if you choose to overwrite it."); static const gchar *message_format_string = N_("File named `%s' already exists. " "Do you want to overwrite it with the one you are saving?"); gchar *filename_in_utf8 = g_filename_to_utf8 (filename, -1, NULL, NULL, NULL); GtkWidget *confirmation_dialog = quarry_message_dialog_new (GTK_WINDOW (dialog), GTK_BUTTONS_NONE, GTK_STOCK_DIALOG_WARNING, _(hint), _(message_format_string), filename_in_utf8); g_free (filename_in_utf8); gtk_dialog_add_buttons (GTK_DIALOG (confirmation_dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, QUARRY_STOCK_OVERWRITE, GTK_RESPONSE_YES, NULL); gtk_dialog_set_default_response (GTK_DIALOG (confirmation_dialog), GTK_RESPONSE_CANCEL); gtk_window_set_modal (GTK_WINDOW (confirmation_dialog), TRUE); g_signal_connect (confirmation_dialog, "response", G_CALLBACK (overwrite_confirmation), NULL); gtk_window_present (GTK_WINDOW (confirmation_dialog)); return TRUE; } return FALSE; } static void overwrite_confirmation (GtkWidget *confirmation_dialog, gint response_id) { GtkDialog *file_dialog = GTK_DIALOG (gtk_window_get_transient_for (GTK_WINDOW (confirmation_dialog))); gtk_widget_destroy (confirmation_dialog); if (response_id == GTK_RESPONSE_YES) { /* Disconnect our `response' handlers so that they don't pop * confirmation dialog up again. */ #if GTK_2_4_OR_LATER if (GTK_IS_FILE_CHOOSER (file_dialog)) { g_signal_handlers_disconnect_by_func (file_dialog, file_chooser_save_response, NULL); } else { #endif g_signal_handlers_disconnect_by_func (file_dialog, file_selection_save_response, NULL); #if GTK_2_4_OR_LATER } #endif gtk_dialog_response (file_dialog, GTK_RESPONSE_OK); } } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/gtk-file-selector.c0000644000175000017500000001473210371146005017324 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "gtk-utils.h" #if GTK_2_4_OR_LATER #include "gtk-file-selector.h" #include "quarry-marshal.h" #include #include static void gtk_file_selector_class_init (GtkFileSelectorClass *class); static void gtk_file_selector_init (GtkFileSelector *selector); static void gtk_file_selector_finalize (GObject *object); static gboolean entry_focus_out_event (GtkFileSelector *selector); static void free_glob_patterns (GtkFileSelector *selector); static GtkComboBoxEntryClass *parent_class; GType gtk_file_selector_get_type (void) { static GType file_selector_type = 0; if (!file_selector_type) { static const GTypeInfo file_selector_info = { sizeof (GtkFileSelectorClass), NULL, NULL, (GClassInitFunc) gtk_file_selector_class_init, NULL, NULL, sizeof (GtkFileSelector), 0, (GInstanceInitFunc) gtk_file_selector_init, NULL }; file_selector_type = g_type_register_static (GTK_TYPE_COMBO_BOX_ENTRY, "GtkFileSelector", &file_selector_info, 0); } return file_selector_type; } static void gtk_file_selector_class_init (GtkFileSelectorClass *class) { parent_class = g_type_class_peek_parent (class); G_OBJECT_CLASS (class)->finalize = gtk_file_selector_finalize; } static void gtk_file_selector_init (GtkFileSelector *selector) { GtkListStore *files_list = gtk_list_store_new (1, G_TYPE_STRING); gtk_combo_box_set_model (GTK_COMBO_BOX (selector), GTK_TREE_MODEL (files_list)); gtk_combo_box_entry_set_text_column (GTK_COMBO_BOX_ENTRY (selector), 0); g_object_unref (files_list); g_signal_connect_swapped (GTK_BIN (selector)->child, "focus-out-event", G_CALLBACK (entry_focus_out_event), selector); selector->glob_patterns = NULL; selector->last_directory = NULL; } GtkWidget * gtk_file_selector_new (void) { return g_object_new (GTK_TYPE_FILE_SELECTOR, NULL); } static gboolean entry_focus_out_event (GtkFileSelector *selector) { gtk_file_selector_repopulate (selector); return FALSE; } static void gtk_file_selector_finalize (GObject *object) { GtkFileSelector *selector = GTK_FILE_SELECTOR (object); g_free (selector->last_directory); free_glob_patterns (selector); G_OBJECT_CLASS (parent_class)->finalize (object); } void gtk_file_selector_set_glob_patterns (GtkFileSelector *selector, const gchar *patterns) { g_return_if_fail (GTK_IS_FILE_SELECTOR (selector)); free_glob_patterns (selector); if (patterns) { const gchar *pattern; for (pattern = patterns; *pattern; pattern += strlen (pattern) + 1) { selector->glob_patterns = g_slist_prepend (selector->glob_patterns, g_pattern_spec_new (pattern)); } } } void gtk_file_selector_set_text (GtkFileSelector *selector, const gchar *text) { g_return_if_fail (GTK_IS_FILE_SELECTOR (selector)); g_return_if_fail (text); gtk_entry_set_text (GTK_ENTRY (GTK_BIN (selector)->child), text); gtk_file_selector_repopulate (selector); } void gtk_file_selector_repopulate (GtkFileSelector *selector) { GtkEntry *entry; gchar *current_directory; g_return_if_fail (GTK_IS_FILE_SELECTOR (selector)); entry = GTK_ENTRY (GTK_BIN (selector)->child); current_directory = g_path_get_dirname (gtk_entry_get_text (entry)); if (!selector->last_directory || strcmp (current_directory, selector->last_directory) != 0) { GtkListStore *list_store = GTK_LIST_STORE (gtk_combo_box_get_model (GTK_COMBO_BOX (selector))); GDir *directory; GError *error = NULL; gtk_list_store_clear (list_store); g_free (selector->last_directory); selector->last_directory = current_directory; directory = g_dir_open (current_directory, 0, &error); if (!error) { const gchar *filename; while ((filename = g_dir_read_name (directory)) != NULL) { if (!g_file_test (filename, G_FILE_TEST_IS_DIR)) { gchar *filename_with_path; GtkTreeIter iterator; if (selector->glob_patterns) { GSList *item; guint filename_length = strlen (filename); gchar *filename_reversed = g_utf8_strreverse (filename, filename_length); for (item = selector->glob_patterns; item; item = item->next) { if (g_pattern_match ((GPatternSpec *) (item->data), filename_length, filename, filename_reversed)) break; } g_free (filename_reversed); if (!item) continue; } filename_with_path = g_strconcat (current_directory, G_DIR_SEPARATOR_S, filename, NULL); gtk_list_store_append (list_store, &iterator); gtk_list_store_set (list_store, &iterator, 0, filename_with_path, -1); g_free (filename_with_path); } } g_dir_close (directory); } else g_error_free (error); } else g_free (current_directory); } static void free_glob_patterns (GtkFileSelector *selector) { if (selector->glob_patterns) { g_slist_foreach (selector->glob_patterns, (GFunc) g_pattern_spec_free, NULL); g_slist_free (selector->glob_patterns); selector->glob_patterns = NULL; } } #endif /* GTK_2_4_OR_LATER */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/gtk-freezable-spin-button.c0000644000175000017500000001624310465451255021017 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "gtk-freezable-spin-button.h" #include #include static void gtk_freezable_spin_button_class_init (GtkFreezableSpinButtonClass *class); static void gtk_freezable_spin_button_editable_interface_init (GtkEditableClass *interface); static void gtk_freezable_spin_button_init (GtkFreezableSpinButton *spin_button); static gboolean gtk_freezable_spin_button_output (GtkFreezableSpinButton *spin_button); static gint gtk_freezable_spin_button_input (GtkFreezableSpinButton *spin_button, gdouble *new_value); static void gtk_freezable_spin_button_change_value (GtkSpinButton *spin_button, GtkScrollType scroll_type); static void gtk_freezable_spin_button_changed (GtkEditable *editable); static GtkSpinButtonClass *parent_class; static GtkEditableClass *parent_editable_interface; static guint input_signal_id; GtkType gtk_freezable_spin_button_get_type (void) { static GtkType freezable_spin_button_type = 0; if (!freezable_spin_button_type) { static const GTypeInfo freezable_spin_button_info = { sizeof (GtkFreezableSpinButtonClass), NULL, NULL, (GClassInitFunc) gtk_freezable_spin_button_class_init, NULL, NULL, sizeof (GtkFreezableSpinButton), 1, (GInstanceInitFunc) gtk_freezable_spin_button_init, NULL }; static const GInterfaceInfo editable_interface_info = { (GInterfaceInitFunc) gtk_freezable_spin_button_editable_interface_init, NULL, NULL }; freezable_spin_button_type = g_type_register_static (GTK_TYPE_SPIN_BUTTON, "GtkFreezableSpinButton", &freezable_spin_button_info, 0); g_type_add_interface_static (freezable_spin_button_type, GTK_TYPE_EDITABLE, &editable_interface_info); } return freezable_spin_button_type; } static void gtk_freezable_spin_button_class_init (GtkFreezableSpinButtonClass *class) { GTK_SPIN_BUTTON_CLASS (class)->change_value = gtk_freezable_spin_button_change_value; parent_class = g_type_class_peek_parent (class); parent_editable_interface = g_type_interface_peek (parent_class, GTK_TYPE_EDITABLE); input_signal_id = g_signal_lookup ("input", GTK_TYPE_SPIN_BUTTON); } static void gtk_freezable_spin_button_editable_interface_init (GtkEditableClass *interface) { interface->changed = gtk_freezable_spin_button_changed; } static void gtk_freezable_spin_button_init (GtkFreezableSpinButton *spin_button) { /* Unfrozen by default. */ spin_button->freezing_string = NULL; spin_button->is_in_output = FALSE; } GtkWidget * gtk_freezable_spin_button_new (GtkAdjustment *adjustment, gdouble climb_rate, guint digits) { GtkWidget *spin_button = g_object_new (GTK_TYPE_FREEZABLE_SPIN_BUTTON, NULL); g_return_val_if_fail (!adjustment || GTK_IS_ADJUSTMENT (adjustment), NULL); gtk_spin_button_configure (GTK_SPIN_BUTTON (spin_button), adjustment, climb_rate, digits); /* The reason to connect on each object instead of redefining in * class virtual table is that these signals are created as * `G_RUN_LAST', but we need our handlers to run first. */ g_signal_connect (spin_button, "output", G_CALLBACK (gtk_freezable_spin_button_output), NULL); g_signal_connect (spin_button, "input", G_CALLBACK (gtk_freezable_spin_button_input), NULL); return spin_button; } static gboolean gtk_freezable_spin_button_output (GtkFreezableSpinButton *spin_button) { if (spin_button->freezing_string) { GtkAdjustment* adjustment = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (spin_button)); if (gtk_adjustment_get_value (adjustment) != 0.0) gtk_freezable_spin_button_unfreeze (spin_button); } if (!spin_button->freezing_string) { /* Fall through to other handlers. */ return FALSE; } spin_button->is_in_output = TRUE; gtk_entry_set_text (GTK_ENTRY (spin_button), spin_button->freezing_string); spin_button->is_in_output = FALSE; return TRUE; } static gint gtk_freezable_spin_button_input (GtkFreezableSpinButton *spin_button, gdouble *new_value) { if (spin_button->freezing_string) { /* No input, this is not a real spin button right now. */ g_signal_stop_emission (spin_button, input_signal_id, 0); *new_value = 0.0; return TRUE; } return FALSE; } static void gtk_freezable_spin_button_change_value (GtkSpinButton *spin_button, GtkScrollType scroll_type) { gtk_freezable_spin_button_unfreeze (GTK_FREEZABLE_SPIN_BUTTON (spin_button)); parent_class->change_value (spin_button, scroll_type); } static void gtk_freezable_spin_button_changed (GtkEditable *editable) { GtkFreezableSpinButton *spin_button = GTK_FREEZABLE_SPIN_BUTTON (editable); if (spin_button->freezing_string && !spin_button->is_in_output) { const gchar *entry_text = gtk_entry_get_text (GTK_ENTRY (editable)); if (strcmp (entry_text, spin_button->freezing_string) != 0) gtk_freezable_spin_button_unfreeze (spin_button); } if (parent_editable_interface->changed) parent_editable_interface->changed (editable); } const gchar * gtk_freezable_spin_button_get_freezing_string (GtkFreezableSpinButton *spin_button) { g_return_val_if_fail (GTK_IS_FREEZABLE_SPIN_BUTTON (spin_button), NULL); return spin_button->freezing_string; } void gtk_freezable_spin_button_freeze (GtkFreezableSpinButton *spin_button, const gchar *freezing_string) { g_return_if_fail (GTK_IS_FREEZABLE_SPIN_BUTTON (spin_button)); spin_button->freezing_string = freezing_string; } void gtk_freezable_spin_button_freeze_and_stop_input (GtkFreezableSpinButton *spin_button, const gchar *freezing_string) { g_return_if_fail (freezing_string); gtk_freezable_spin_button_freeze (spin_button, freezing_string); g_signal_stop_emission (spin_button, input_signal_id, 0); } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/gtk-game-info-dialog.c0000644000175000017500000010710310522172556017671 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "gtk-game-info-dialog.h" #include "gtk-freezable-spin-button.h" #include "gtk-games.h" #include "gtk-help.h" #include "gtk-named-vbox.h" #include "gtk-utils.h" #include "quarry-marshal.h" #include "quarry-text-view.h" #include "sgf.h" #include "board.h" #include "utils.h" #include #include #include enum { GTK_GAME_INFO_DIALOG_RESPONSE_UNDO, GTK_GAME_INFO_DIALOG_RESPONSE_REDO }; typedef struct _SgfPropertyChangeData SgfPropertyChangeData; struct _SgfPropertyChangeData { GtkGameInfoDialog *dialog; SgfType sgf_property_type; }; static void gtk_game_info_dialog_class_init (GtkGameInfoDialogClass *class); static void gtk_game_info_dialog_init (GtkGameInfoDialog *dialog); static void update_title (GtkGameInfoDialog *dialog); static GtkEntry * create_and_pack_game_info_entry (const gchar *label_text, SgfType sgf_property_type, GtkWidget **hbox, GtkGameInfoDialog *dialog); static void gtk_game_info_dialog_response (GtkDialog *dialog, gint response_id); static void gtk_game_info_dialog_undo_history_action (GtkGameInfoDialog *dialog, gboolean undo); static void gtk_game_info_dialog_finalize (GObject *object); static void * get_field (GtkGameInfoDialog *dialog, SgfType sgf_property_type); static gint get_page_index (SgfType sgf_property_type); static SgfType get_property_type (GtkGameInfoDialog *dialog, void *field); static char * get_field_text (void *field); static void set_field_text (GtkGameInfoDialog *dialog, SgfType sgf_property_type); static void do_set_field_text (void *field, const gchar *value); static gboolean game_info_entry_focus_out_event (GtkEntry *entry, GdkEventFocus *event, gpointer sgf_property_type); static gboolean game_comment_focus_out_event (GtkGameInfoDialog *dialog, GdkEventFocus *event); static void game_info_spin_button_value_changed (GtkFreezableSpinButton *freezable_spin_button, GtkGameInfoDialog *dialog); static gboolean game_info_spin_button_focus_out_event (GtkFreezableSpinButton *freezable_spin_button, GdkEventFocus *event, GtkGameInfoDialog *dialog); static void enable_simple_undo (void *field, GtkGameInfoDialog *dialog); static void undo_or_redo_availability_changed (SgfUndoHistory *undo_history, void *user_data); static void update_property (GtkGameInfoDialog *dialog, SgfType sgf_property_type, char *new_value); static void property_has_changed (SgfPropertyChangeData *data); static GtkDialogClass *parent_class; enum { PROPERTY_CHANGED, UNDO_HISTORY_ACTION, NUM_SIGNALS }; static guint game_info_dialog_signals[NUM_SIGNALS]; static const SgfCustomUndoHistoryEntryData property_change_undo_entry_data = { (SgfCustomOperationEntryFunction) property_has_changed, (SgfCustomOperationEntryFunction) property_has_changed, (SgfCustomOperationEntryFunction) utils_free }; GType gtk_game_info_dialog_get_type (void) { static GType game_info_dialog_type = 0; if (!game_info_dialog_type) { static GTypeInfo game_info_dialog_info = { sizeof (GtkGameInfoDialogClass), NULL, NULL, (GClassInitFunc) gtk_game_info_dialog_class_init, NULL, NULL, sizeof (GtkGameInfoDialog), 1, (GInstanceInitFunc) gtk_game_info_dialog_init, NULL }; game_info_dialog_type = g_type_register_static (GTK_TYPE_DIALOG, "GtkGameInfoDialog", &game_info_dialog_info, 0); } return game_info_dialog_type; } static void gtk_game_info_dialog_class_init (GtkGameInfoDialogClass *class) { static GtkUtilsBindingInfo undo_redo_bindings[] = { { GDK_Z, GDK_CONTROL_MASK, TRUE }, { GDK_Z, GDK_CONTROL_MASK | GDK_SHIFT_MASK, FALSE } }; GtkBindingSet *binding_set; parent_class = g_type_class_peek_parent (class); G_OBJECT_CLASS (class)->finalize = gtk_game_info_dialog_finalize; GTK_DIALOG_CLASS (class)->response = gtk_game_info_dialog_response; class->property_changed = NULL; class->undo_history_action = gtk_game_info_dialog_undo_history_action; game_info_dialog_signals[PROPERTY_CHANGED] = g_signal_new ("property-changed", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GtkGameInfoDialogClass, property_changed), NULL, NULL, quarry_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT); game_info_dialog_signals[UNDO_HISTORY_ACTION] = g_signal_new ("undo-history-action", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GtkGameInfoDialogClass, undo_history_action), NULL, NULL, quarry_marshal_VOID__BOOLEAN, G_TYPE_NONE, 1, G_TYPE_BOOLEAN); binding_set = gtk_binding_set_by_class (class); gtk_utils_add_similar_bindings (binding_set, "undo-history-action", undo_redo_bindings, (sizeof undo_redo_bindings / sizeof (GtkUtilsBindingInfo))); } static void gtk_game_info_dialog_init (GtkGameInfoDialog *dialog) { GtkWidget *notebook = gtk_notebook_new (); GtkWidget *label; GtkWidget *handicap_spin_button; GtkWidget *komi_spin_button; GtkWidget *main_time_spin_button; GtkWidget *hbox1; GtkWidget *hbox2; GtkWidget *hbox3; GtkWidget *hbox4; GtkWidget *hbox5; GtkWidget *large_hbox1; GtkWidget *large_hbox2; GtkWidget *named_vbox1; GtkWidget *named_vbox2; GtkWidget *player_vboxes[NUM_COLORS]; GtkWidget *vbox; GtkWidget *alignment; GtkWidget *text_view; GtkWidget *scrolled_window; GtkWidget *page; GtkSizeGroup *size_group; int k; dialog->pages = GTK_NOTEBOOK (notebook); for (k = 0; k < NUM_COLORS; k++) { dialog->player_names[k] = create_and_pack_game_info_entry ((k == BLACK_INDEX ? _("N_ame:") : _("_Name:")), (k == BLACK_INDEX ? SGF_PLAYER_BLACK : SGF_PLAYER_WHITE), &hbox1, dialog); dialog->player_teams[k] = create_and_pack_game_info_entry (_("Team:"), (k == BLACK_INDEX ? SGF_BLACK_TEAM : SGF_WHITE_TEAM), &hbox2, dialog); dialog->player_ranks[k] = create_and_pack_game_info_entry (_("Rank:"), (k == BLACK_INDEX ? SGF_BLACK_RANK : SGF_WHITE_RANK), &hbox3, dialog); player_vboxes[k] = gtk_utils_pack_in_box (GTK_TYPE_NAMED_VBOX, QUARRY_SPACING_SMALL, hbox1, GTK_UTILS_FILL, hbox2, GTK_UTILS_FILL, hbox3, GTK_UTILS_FILL, NULL); gtk_named_vbox_set_label_text (GTK_NAMED_VBOX (player_vboxes[k]), (k == BLACK_INDEX ? _("Black Player") : _("White Player"))); } large_hbox1 = gtk_utils_pack_in_box (GTK_TYPE_HBOX, QUARRY_SPACING_VERY_BIG, player_vboxes[1], GTK_UTILS_PACK_DEFAULT, player_vboxes[0], GTK_UTILS_PACK_DEFAULT, NULL); gtk_box_set_homogeneous (GTK_BOX (large_hbox1), TRUE); size_group = gtk_utils_align_left_widgets (GTK_CONTAINER (large_hbox1), NULL); dialog->game_name = create_and_pack_game_info_entry (_("_Game name:"), SGF_GAME_NAME, &hbox1, dialog); dialog->place = create_and_pack_game_info_entry (_("_Place:"), SGF_PLACE, &hbox2, dialog); dialog->date = create_and_pack_game_info_entry (_("Da_te:"), SGF_DATE, &hbox3, dialog); dialog->event = create_and_pack_game_info_entry (_("_Event:"), SGF_EVENT, &hbox4, dialog); dialog->round = create_and_pack_game_info_entry (_("R_ound:"), SGF_ROUND, &hbox5, dialog); named_vbox1 = gtk_utils_pack_in_box (GTK_TYPE_NAMED_VBOX, QUARRY_SPACING_SMALL, hbox1, GTK_UTILS_FILL, hbox2, GTK_UTILS_FILL, hbox3, GTK_UTILS_FILL, hbox4, GTK_UTILS_FILL, hbox5, GTK_UTILS_FILL, NULL); gtk_named_vbox_set_label_text (GTK_NAMED_VBOX (named_vbox1), _("Game Information")); dialog->rule_set = create_and_pack_game_info_entry (_("Rule _set:"), SGF_RULE_SET, &hbox1, dialog); dialog->handicap = ((GtkAdjustment *) gtk_adjustment_new (0, 0, GTK_MAX_BOARD_SIZE * GTK_MAX_BOARD_SIZE, 1, 2, 0)); handicap_spin_button = gtk_utils_create_freezable_spin_button (dialog->handicap, 0.0, 0, TRUE); dialog->handicap_spin_button = GTK_FREEZABLE_SPIN_BUTTON (handicap_spin_button); gtk_utils_freeze_on_empty_input (dialog->handicap_spin_button); g_signal_connect (handicap_spin_button, "value-changed", G_CALLBACK (game_info_spin_button_value_changed), dialog); g_signal_connect (handicap_spin_button, "changed", G_CALLBACK (enable_simple_undo), dialog); /* Note: This *must* be `_after' so that `input' signal is sent * before our handler is invoked (that signal's handler can set the * freezing string.) */ g_signal_connect_after (handicap_spin_button, "focus-out-event", G_CALLBACK (game_info_spin_button_focus_out_event), dialog); label = gtk_utils_create_mnemonic_label (_("Han_dicap:"), handicap_spin_button); hbox2 = gtk_utils_pack_in_box (GTK_TYPE_HBOX, QUARRY_SPACING, label, 0, handicap_spin_button, GTK_UTILS_FILL, NULL); dialog->handicap_box = hbox2; dialog->komi = ((GtkAdjustment *) gtk_adjustment_new (0.0, -999.5, 999.5, 1.0, 5.0, 0.0)); komi_spin_button = gtk_utils_create_freezable_spin_button (dialog->komi, 0.0, 1, FALSE); dialog->komi_spin_button = GTK_FREEZABLE_SPIN_BUTTON (komi_spin_button); gtk_utils_freeze_on_empty_input (dialog->komi_spin_button); g_signal_connect (komi_spin_button, "value-changed", G_CALLBACK (game_info_spin_button_value_changed), dialog); g_signal_connect (komi_spin_button, "changed", G_CALLBACK (enable_simple_undo), dialog); g_signal_connect_after (komi_spin_button, "focus-out-event", G_CALLBACK (game_info_spin_button_focus_out_event), dialog); label = gtk_utils_create_mnemonic_label (_("_Komi:"), komi_spin_button); hbox3 = gtk_utils_pack_in_box (GTK_TYPE_HBOX, QUARRY_SPACING, label, 0, komi_spin_button, GTK_UTILS_FILL, NULL); dialog->komi_box = hbox3; dialog->main_time = ((GtkAdjustment *) gtk_adjustment_new (0.0, 0.0, 3600000.0 - 1.0, 60.0, 300.0, 0.0)); main_time_spin_button = gtk_utils_create_freezable_spin_button (dialog->main_time, 0.0, 0, FALSE); dialog->main_time_spin_button = GTK_FREEZABLE_SPIN_BUTTON (main_time_spin_button); gtk_utils_freeze_on_empty_input (dialog->main_time_spin_button); gtk_utils_convert_to_time_spin_button (GTK_SPIN_BUTTON (main_time_spin_button)); g_signal_connect (main_time_spin_button, "value-changed", G_CALLBACK (game_info_spin_button_value_changed), dialog); g_signal_connect (main_time_spin_button, "changed", G_CALLBACK (enable_simple_undo), dialog); g_signal_connect_after (main_time_spin_button, "focus-out-event", G_CALLBACK (game_info_spin_button_focus_out_event), dialog); label = gtk_utils_create_mnemonic_label (_("_Main time:"), main_time_spin_button); hbox4 = gtk_utils_pack_in_box (GTK_TYPE_HBOX, QUARRY_SPACING, label, 0, main_time_spin_button, GTK_UTILS_FILL, NULL); gtk_utils_create_size_group (GTK_SIZE_GROUP_HORIZONTAL, handicap_spin_button, komi_spin_button, main_time_spin_button, NULL); dialog->overtime = create_and_pack_game_info_entry (_("O_vertime:"), SGF_OVERTIME, &hbox5, dialog); named_vbox2 = gtk_utils_pack_in_box (GTK_TYPE_NAMED_VBOX, QUARRY_SPACING_SMALL, hbox1, GTK_UTILS_FILL, hbox2, GTK_UTILS_FILL, hbox3, GTK_UTILS_FILL, hbox4, GTK_UTILS_FILL, hbox5, GTK_UTILS_FILL, NULL); gtk_named_vbox_set_label_text (GTK_NAMED_VBOX (named_vbox2), _("Game Rules")); large_hbox2 = gtk_utils_pack_in_box (GTK_TYPE_HBOX, QUARRY_SPACING_VERY_BIG, named_vbox1, GTK_UTILS_PACK_DEFAULT, named_vbox2, GTK_UTILS_PACK_DEFAULT, NULL); gtk_box_set_homogeneous (GTK_BOX (large_hbox2), TRUE); gtk_utils_align_left_widgets (GTK_CONTAINER (large_hbox2), size_group); page = gtk_utils_pack_in_box (GTK_TYPE_VBOX, QUARRY_SPACING_BIG, large_hbox1, GTK_UTILS_FILL, large_hbox2, GTK_UTILS_FILL, NULL); gtk_container_set_border_width (GTK_CONTAINER (page), QUARRY_SPACING); gtk_widget_show_all (page); gtk_notebook_append_page (dialog->pages, page, gtk_label_new (_("General"))); dialog->result = create_and_pack_game_info_entry (_("Game re_sult:"), SGF_RESULT, &hbox1, dialog); dialog->opening = create_and_pack_game_info_entry (_("_Opening played:"), SGF_OPENING, &hbox2, dialog); vbox = gtk_utils_pack_in_box (GTK_TYPE_VBOX, QUARRY_SPACING_SMALL, hbox1, GTK_UTILS_FILL, hbox2, GTK_UTILS_FILL, NULL); gtk_utils_align_left_widgets (GTK_CONTAINER (vbox), NULL); alignment = gtk_alignment_new (0.0, 0.0, 0.4, 1.0); gtk_container_add (GTK_CONTAINER (alignment), vbox); text_view = gtk_text_view_new (); dialog->game_comment_text_view = text_view; dialog->game_comment = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text_view)); gtk_text_view_set_left_margin (GTK_TEXT_VIEW (text_view), QUARRY_SPACING_VERY_SMALL); gtk_text_view_set_right_margin (GTK_TEXT_VIEW (text_view), QUARRY_SPACING_VERY_SMALL); gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (text_view), GTK_WRAP_WORD); g_signal_connect (dialog->game_comment, "changed", G_CALLBACK (enable_simple_undo), dialog); g_signal_connect_swapped (text_view, "focus-out-event", G_CALLBACK (game_comment_focus_out_event), dialog); scrolled_window = gtk_utils_make_widget_scrollable (text_view, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); label = gtk_utils_create_mnemonic_label (_("Comment / _description:"), text_view); vbox = gtk_utils_pack_in_box (GTK_TYPE_VBOX, QUARRY_SPACING_SMALL, label, GTK_UTILS_FILL, scrolled_window, GTK_UTILS_PACK_DEFAULT, NULL); page = gtk_utils_pack_in_box (GTK_TYPE_VBOX, QUARRY_SPACING_BIG, alignment, GTK_UTILS_FILL, vbox, GTK_UTILS_PACK_DEFAULT, NULL); gtk_container_set_border_width (GTK_CONTAINER (page), QUARRY_SPACING); gtk_widget_show_all (page); gtk_notebook_append_page (dialog->pages, page, gtk_label_new (_("Description & Result"))); dialog->copyright = create_and_pack_game_info_entry (_("Co_pyright string:"), SGF_COPYRIGHT, &hbox1, dialog); dialog->annotator = create_and_pack_game_info_entry (_("_Annotator:"), SGF_ANNOTATOR, &hbox2, dialog); dialog->source = create_and_pack_game_info_entry (_("_Source:"), SGF_SOURCE, &hbox3, dialog); dialog->user = create_and_pack_game_info_entry (_("_Entered by:"), SGF_USER, &hbox4, dialog); named_vbox1 = gtk_utils_pack_in_box (GTK_TYPE_NAMED_VBOX, QUARRY_SPACING_SMALL, hbox1, GTK_UTILS_FILL, hbox2, GTK_UTILS_FILL, hbox3, GTK_UTILS_FILL, hbox4, GTK_UTILS_FILL, NULL); gtk_named_vbox_set_label_text (GTK_NAMED_VBOX (named_vbox1), _("Copyright & Credits")); alignment = gtk_alignment_new (0.0, 0.0, 0.4, 1.0); gtk_container_add (GTK_CONTAINER (alignment), named_vbox1); /* FIXME: Add second box with application etc. */ page = gtk_utils_pack_in_box (GTK_TYPE_VBOX, QUARRY_SPACING_BIG, alignment, GTK_UTILS_FILL, /* named_vbox2, GTK_UTILS_FILL, */ NULL); gtk_container_set_border_width (GTK_CONTAINER (page), QUARRY_SPACING); gtk_utils_align_left_widgets (GTK_CONTAINER (page), NULL); gtk_widget_show_all (page); gtk_notebook_append_page (dialog->pages, page, gtk_label_new (_("Game Record"))); gtk_widget_show (notebook); gtk_utils_standardize_dialog (&dialog->dialog, notebook); gtk_dialog_set_has_separator (&dialog->dialog, FALSE); gtk_dialog_add_buttons (&dialog->dialog, GTK_STOCK_UNDO, GTK_GAME_INFO_DIALOG_RESPONSE_UNDO, GTK_STOCK_REDO, GTK_GAME_INFO_DIALOG_RESPONSE_REDO, GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, NULL); gtk_utils_add_help_button (&dialog->dialog); dialog->sgf_tree = NULL; dialog->sgf_node = NULL; dialog->sgf_undo_history = NULL; dialog->simple_undo_field = NULL; dialog->simple_redo_field = NULL; dialog->simple_redo_value = NULL; update_title (dialog); } static void update_title (GtkGameInfoDialog *dialog) { if (dialog->sgf_node && sgf_node_get_text_property_value (dialog->sgf_node, SGF_GAME_NAME)) { gchar* title = g_strdup_printf ("%s - %s", sgf_node_get_text_property_value (dialog->sgf_node, SGF_GAME_NAME), _("Game Information")); gtk_window_set_title (GTK_WINDOW (dialog), title); g_free (title); } else gtk_window_set_title (GTK_WINDOW (dialog), _("Game Information")); } static GtkEntry * create_and_pack_game_info_entry (const gchar *label_text, SgfType sgf_property_type, GtkWidget **hbox, GtkGameInfoDialog *dialog) { GtkWidget *entry = gtk_utils_create_entry (NULL, RETURN_ADVANCES_FOCUS); GtkWidget *label = gtk_utils_create_mnemonic_label (label_text, entry); *hbox = gtk_utils_pack_in_box (GTK_TYPE_HBOX, QUARRY_SPACING, label, 0, entry, GTK_UTILS_PACK_DEFAULT, NULL); g_signal_connect (entry, "changed", G_CALLBACK (enable_simple_undo), dialog); g_signal_connect (entry, "focus-out-event", G_CALLBACK (game_info_entry_focus_out_event), GINT_TO_POINTER (sgf_property_type)); return GTK_ENTRY (entry); } GtkWidget * gtk_game_info_dialog_new (void) { return GTK_WIDGET (g_object_new (GTK_TYPE_GAME_INFO_DIALOG, NULL)); } static void gtk_game_info_dialog_response (GtkDialog *dialog, gint response_id) { if (response_id == GTK_RESPONSE_CLOSE) gtk_widget_destroy (GTK_WIDGET (dialog)); else if (response_id == GTK_GAME_INFO_DIALOG_RESPONSE_UNDO || response_id == GTK_GAME_INFO_DIALOG_RESPONSE_REDO) { g_signal_emit (dialog, game_info_dialog_signals[UNDO_HISTORY_ACTION], 0, response_id == GTK_GAME_INFO_DIALOG_RESPONSE_UNDO); } else if (response_id == GTK_RESPONSE_HELP) gtk_help_display ("game-information-dialog"); } static void gtk_game_info_dialog_undo_history_action (GtkGameInfoDialog *dialog, gboolean undo) { SgfGameTree *sgf_tree; SgfUndoHistory *saved_undo_history; void *field; g_return_if_fail (GTK_IS_GAME_INFO_DIALOG (dialog)); sgf_tree = dialog->sgf_tree; saved_undo_history = sgf_tree->undo_history; sgf_tree->undo_history = dialog->sgf_undo_history; if (undo) { if (!dialog->simple_undo_field) sgf_utils_undo (sgf_tree); else { dialog->simple_redo_field = dialog->simple_undo_field; dialog->simple_redo_value = get_field_text (dialog->simple_undo_field); field = dialog->simple_undo_field; set_field_text (dialog, get_property_type (dialog, field)); dialog->simple_undo_field = NULL; undo_or_redo_availability_changed (dialog->sgf_undo_history, dialog); goto undone_or_redone; } } else { if (!dialog->simple_redo_field) sgf_utils_redo (sgf_tree); else { field = dialog->simple_redo_field; do_set_field_text (field, dialog->simple_redo_value); dialog->simple_undo_field = dialog->simple_redo_field; dialog->simple_redo_field = NULL; g_free (dialog->simple_redo_value); dialog->simple_redo_value = NULL; undo_or_redo_availability_changed (dialog->sgf_undo_history, dialog); goto undone_or_redone; } } set_field_text (dialog, dialog->modified_property_type); gtk_notebook_set_current_page (dialog->pages, get_page_index (dialog->modified_property_type)); field = get_field (dialog, dialog->modified_property_type); g_signal_emit (dialog, game_info_dialog_signals[PROPERTY_CHANGED], 0, dialog->modified_property_type); undone_or_redone: sgf_tree->undo_history = saved_undo_history; if (GTK_IS_ENTRY (field)) gtk_widget_grab_focus (GTK_WIDGET (field)); else gtk_widget_grab_focus (dialog->game_comment_text_view); } static void gtk_game_info_dialog_finalize (GObject *object) { GtkGameInfoDialog *dialog = GTK_GAME_INFO_DIALOG (object); if (dialog->sgf_undo_history) sgf_undo_history_delete (dialog->sgf_undo_history, dialog->sgf_tree); g_free (dialog->simple_redo_value); G_OBJECT_CLASS (parent_class)->finalize (object); } void gtk_game_info_dialog_set_node (GtkGameInfoDialog *dialog, SgfGameTree *sgf_tree, SgfNode *sgf_node) { g_return_if_fail (GTK_IS_GAME_INFO_DIALOG (dialog)); g_return_if_fail (sgf_tree); g_return_if_fail (sgf_node); dialog->sgf_tree = sgf_tree; dialog->sgf_node = sgf_node; dialog->sgf_undo_history = sgf_undo_history_new (sgf_tree); sgf_undo_history_set_notification_callback (dialog->sgf_undo_history, undo_or_redo_availability_changed, dialog); /* Set the initial state. */ undo_or_redo_availability_changed (dialog->sgf_undo_history, dialog); /* Initializing "General" page. */ set_field_text (dialog, SGF_PLAYER_WHITE); set_field_text (dialog, SGF_WHITE_TEAM); set_field_text (dialog, SGF_WHITE_RANK); set_field_text (dialog, SGF_PLAYER_BLACK); set_field_text (dialog, SGF_BLACK_TEAM); set_field_text (dialog, SGF_BLACK_RANK); set_field_text (dialog, SGF_GAME_NAME); set_field_text (dialog, SGF_PLACE); set_field_text (dialog, SGF_DATE); set_field_text (dialog, SGF_EVENT); set_field_text (dialog, SGF_ROUND); set_field_text (dialog, SGF_RULE_SET); set_field_text (dialog, SGF_HANDICAP); set_field_text (dialog, SGF_KOMI); set_field_text (dialog, SGF_TIME_LIMIT); set_field_text (dialog, SGF_OVERTIME); gtk_widget_set_sensitive (dialog->handicap_box, sgf_tree->game == GAME_GO); gtk_widget_set_sensitive (dialog->komi_box, sgf_tree->game == GAME_GO); /* Initializing "Description & Result" page. */ set_field_text (dialog, SGF_RESULT); set_field_text (dialog, SGF_OPENING); set_field_text (dialog, SGF_GAME_COMMENT); /* Initializing "Game Record" page. */ set_field_text (dialog, SGF_COPYRIGHT); set_field_text (dialog, SGF_ANNOTATOR); set_field_text (dialog, SGF_SOURCE); set_field_text (dialog, SGF_USER); } static void * get_field (GtkGameInfoDialog *dialog, SgfType sgf_property_type) { switch (sgf_property_type) { case SGF_PLAYER_BLACK: case SGF_PLAYER_WHITE: return dialog->player_names[sgf_property_type == SGF_PLAYER_BLACK ? BLACK_INDEX : WHITE_INDEX]; case SGF_BLACK_TEAM: case SGF_WHITE_TEAM: return dialog->player_teams[sgf_property_type == SGF_BLACK_TEAM ? BLACK_INDEX : WHITE_INDEX]; case SGF_BLACK_RANK: case SGF_WHITE_RANK: return dialog->player_ranks[sgf_property_type == SGF_BLACK_RANK ? BLACK_INDEX : WHITE_INDEX]; case SGF_GAME_NAME: return dialog->game_name; case SGF_PLACE: return dialog->place; case SGF_DATE: return dialog->date; case SGF_EVENT: return dialog->event; case SGF_ROUND: return dialog->round; case SGF_RULE_SET: return dialog->rule_set; case SGF_HANDICAP: return dialog->handicap_spin_button; case SGF_KOMI: return dialog->komi_spin_button; case SGF_TIME_LIMIT: return dialog->main_time_spin_button; case SGF_OVERTIME: return dialog->overtime; case SGF_RESULT: return dialog->result; case SGF_OPENING: return dialog->opening; case SGF_GAME_COMMENT: return dialog->game_comment; case SGF_COPYRIGHT: return dialog->copyright; case SGF_ANNOTATOR: return dialog->annotator; case SGF_SOURCE: return dialog->source; case SGF_USER: return dialog->user; default: g_assert_not_reached (); return NULL; } } static gint get_page_index (SgfType sgf_property_type) { switch (sgf_property_type) { case SGF_PLAYER_BLACK: case SGF_PLAYER_WHITE: case SGF_BLACK_TEAM: case SGF_WHITE_TEAM: case SGF_BLACK_RANK: case SGF_WHITE_RANK: case SGF_GAME_NAME: case SGF_PLACE: case SGF_DATE: case SGF_EVENT: case SGF_ROUND: case SGF_RULE_SET: case SGF_HANDICAP: case SGF_KOMI: case SGF_TIME_LIMIT: case SGF_OVERTIME: return 0; case SGF_RESULT: case SGF_OPENING: case SGF_GAME_COMMENT: return 1; case SGF_COPYRIGHT: case SGF_ANNOTATOR: case SGF_SOURCE: case SGF_USER: return 2; default: g_assert_not_reached (); return -1; } } static SgfType get_property_type (GtkGameInfoDialog *dialog, void *field) { if (field == dialog->player_names[BLACK_INDEX]) return SGF_PLAYER_BLACK; if (field == dialog->player_names[WHITE_INDEX]) return SGF_PLAYER_WHITE; if (field == dialog->player_teams[BLACK_INDEX]) return SGF_BLACK_TEAM; if (field == dialog->player_teams[WHITE_INDEX]) return SGF_WHITE_TEAM; if (field == dialog->player_ranks[BLACK_INDEX]) return SGF_BLACK_RANK; if (field == dialog->player_ranks[WHITE_INDEX]) return SGF_WHITE_RANK; if (field == dialog->game_name) return SGF_GAME_NAME; if (field == dialog->place) return SGF_PLACE; if (field == dialog->date) return SGF_DATE; if (field == dialog->event) return SGF_EVENT; if (field == dialog->round) return SGF_ROUND; if (field == dialog->rule_set) return SGF_RULE_SET; if (field == dialog->handicap_spin_button) return SGF_HANDICAP; if (field == dialog->komi_spin_button) return SGF_KOMI; if (field == dialog->main_time_spin_button) return SGF_TIME_LIMIT; if (field == dialog->overtime) return SGF_OVERTIME; if (field == dialog->result) return SGF_RESULT; if (field == dialog->opening) return SGF_OPENING; if (field == dialog->game_comment) return SGF_GAME_COMMENT; if (field == dialog->copyright) return SGF_COPYRIGHT; if (field == dialog->annotator) return SGF_ANNOTATOR; if (field == dialog->source) return SGF_SOURCE; if (field == dialog->user) return SGF_USER; g_assert_not_reached (); return SGF_UNKNOWN; } static char * get_field_text (void *field) { /* Note that GtkEntry is a more generic type and must be checked for * after GtkFreezableSpinButton. */ if (GTK_IS_ENTRY (field)) return g_strdup (gtk_entry_get_text (GTK_ENTRY (field))); else if (GTK_IS_TEXT_BUFFER (field)) { GtkTextIter start_iterator; GtkTextIter end_iterator; gtk_text_buffer_get_bounds (GTK_TEXT_BUFFER (field), &start_iterator, &end_iterator); return gtk_text_iter_get_text (&start_iterator, &end_iterator); } else { g_assert_not_reached (); return NULL; } } static void set_field_text (GtkGameInfoDialog *dialog, SgfType sgf_property_type) { void *field = get_field (dialog, sgf_property_type); g_signal_handlers_block_by_func (field, G_CALLBACK (enable_simple_undo), dialog); if (sgf_property_type == SGF_HANDICAP) { if (dialog->sgf_tree->game == GAME_GO) { int handicap = sgf_node_get_handicap (dialog->sgf_node); if (handicap >= 0) { gtk_adjustment_set_value (dialog->handicap, (gdouble) handicap); goto text_set; } } } else if (sgf_property_type == SGF_KOMI) { double komi; if (dialog->sgf_tree->game == GAME_GO && sgf_node_get_komi (dialog->sgf_node, &komi)) { gtk_adjustment_set_value (dialog->komi, komi); goto text_set; } } else if (sgf_property_type == SGF_TIME_LIMIT) { double time_limit; if (sgf_node_get_time_limit (dialog->sgf_node, &time_limit)) { gtk_adjustment_set_value (dialog->main_time, time_limit); goto text_set; } } else if (sgf_property_type == SGF_GAME_NAME) update_title (dialog); do_set_field_text (field, sgf_node_get_text_property_value (dialog->sgf_node, sgf_property_type)); text_set: g_signal_handlers_unblock_by_func (field, G_CALLBACK (enable_simple_undo), dialog); } static void do_set_field_text (void *field, const gchar *value) { if (!value) value = ""; gtk_utils_block_signal_handlers (field, G_CALLBACK (enable_simple_undo)); /* Note that GtkEntry is a more generic type and must be checked for * after GtkFreezableSpinButton. */ if (GTK_IS_FREEZABLE_SPIN_BUTTON (field)) { gtk_freezable_spin_button_freeze (GTK_FREEZABLE_SPIN_BUTTON (field), value); } else if (GTK_IS_ENTRY (field)) gtk_entry_set_text (GTK_ENTRY (field), value); else if (GTK_IS_TEXT_BUFFER (field)) { gtk_utils_set_text_buffer_text (GTK_TEXT_BUFFER (field), value); gtk_text_buffer_set_modified (GTK_TEXT_BUFFER (field), FALSE); } else g_assert_not_reached (); gtk_utils_unblock_signal_handlers (field, G_CALLBACK (enable_simple_undo)); } static gboolean game_info_entry_focus_out_event (GtkEntry *entry, GdkEventFocus *event, gpointer sgf_property_type) { GtkWidget *top_level_widget; const gchar *entry_text = gtk_entry_get_text (entry); char *normalized_text = sgf_utils_normalize_text (entry_text, 1); UNUSED (event); /* If the normalized text is different, set it as the entry text. */ if (normalized_text != NULL ? strcmp (normalized_text, entry_text) != 0 : *entry_text) gtk_entry_set_text (entry, normalized_text ? normalized_text : ""); top_level_widget = gtk_widget_get_toplevel (GTK_WIDGET (entry)); update_property (GTK_GAME_INFO_DIALOG (top_level_widget), GPOINTER_TO_INT (sgf_property_type), normalized_text); return FALSE; } /* Only connected to game comment text view, so `sgf_property_type' is * constant and equals to `SGF_GAME_COMMENT'. */ static gboolean game_comment_focus_out_event (GtkGameInfoDialog *dialog, GdkEventFocus *event) { UNUSED (event); if (dialog->sgf_tree && gtk_text_buffer_get_modified (dialog->game_comment)) { GtkTextIter start_iterator; GtkTextIter end_iterator; gchar *text_buffer_text; char *normalized_text; gtk_text_buffer_get_bounds (dialog->game_comment, &start_iterator, &end_iterator); text_buffer_text = gtk_text_iter_get_text (&start_iterator, &end_iterator); normalized_text = sgf_utils_normalize_text (text_buffer_text, 0); update_property (dialog, SGF_GAME_COMMENT, normalized_text); g_free (text_buffer_text); gtk_text_buffer_set_modified (dialog->game_comment, FALSE); } return FALSE; } static void game_info_spin_button_value_changed (GtkFreezableSpinButton *freezable_spin_button, GtkGameInfoDialog *dialog) { if (gtk_freezable_spin_button_get_freezing_string (freezable_spin_button) == NULL) { if (dialog->handicap_spin_button == freezable_spin_button) { int handicap = gtk_adjustment_get_value (dialog->handicap); update_property (dialog, SGF_HANDICAP, utils_cprintf ("%d", handicap)); } else if (dialog->komi_spin_button == freezable_spin_button) { double komi = gtk_adjustment_get_value (dialog->komi); update_property (dialog, SGF_KOMI, utils_cprintf ("%.f", komi)); } else if (dialog->main_time_spin_button == freezable_spin_button) { double main_time = gtk_adjustment_get_value (dialog->main_time); update_property (dialog, SGF_TIME_LIMIT, utils_cprintf ("%.f", main_time)); } else g_assert_not_reached (); } } static gboolean game_info_spin_button_focus_out_event (GtkFreezableSpinButton *freezable_spin_button, GdkEventFocus *event, GtkGameInfoDialog *dialog) { UNUSED (event); if (dialog->sgf_tree) { const gchar *freezing_string = gtk_freezable_spin_button_get_freezing_string (freezable_spin_button); /* There is only one interesting case: when a property value is * removed. Check for it. */ if (freezing_string && ! *freezing_string) { SgfType sgf_property_type; if (dialog->handicap_spin_button == freezable_spin_button) sgf_property_type = SGF_HANDICAP; else if (dialog->komi_spin_button == freezable_spin_button) sgf_property_type = SGF_KOMI; else if (dialog->main_time_spin_button == freezable_spin_button) sgf_property_type = SGF_TIME_LIMIT; else { g_assert_not_reached (); return FALSE; } update_property (dialog, sgf_property_type, NULL); } } return FALSE; } static void enable_simple_undo (void *field, GtkGameInfoDialog *dialog) { if (dialog->simple_undo_field) return; if (GTK_IS_FREEZABLE_SPIN_BUTTON (field) && (gtk_freezable_spin_button_get_freezing_string (GTK_FREEZABLE_SPIN_BUTTON (field)))) return; dialog->simple_undo_field = field; sgf_undo_history_delete_redo_entries (dialog->sgf_undo_history, dialog->sgf_tree); dialog->simple_redo_field = NULL; g_free (dialog->simple_redo_value); dialog->simple_redo_value = NULL; undo_or_redo_availability_changed (dialog->sgf_undo_history, dialog); } static void undo_or_redo_availability_changed (SgfUndoHistory *undo_history, void *user_data) { GtkGameInfoDialog *dialog = GTK_GAME_INFO_DIALOG (user_data); SgfUndoHistory *saved_undo_history = dialog->sgf_tree->undo_history; gboolean can_undo; gboolean can_redo; UNUSED (undo_history); dialog->sgf_tree->undo_history = dialog->sgf_undo_history; can_undo = (dialog->simple_undo_field || sgf_utils_can_undo (dialog->sgf_tree)); can_redo = (dialog->simple_redo_field || sgf_utils_can_redo (dialog->sgf_tree)); dialog->sgf_tree->undo_history = saved_undo_history; gtk_dialog_set_response_sensitive (&dialog->dialog, GTK_GAME_INFO_DIALOG_RESPONSE_UNDO, can_undo); gtk_dialog_set_response_sensitive (&dialog->dialog, GTK_GAME_INFO_DIALOG_RESPONSE_REDO, can_redo); } static void update_property (GtkGameInfoDialog *dialog, SgfType sgf_property_type, char *new_value) { SgfGameTree *sgf_tree = dialog->sgf_tree; if (sgf_tree) { SgfUndoHistory *saved_undo_history = sgf_tree->undo_history; sgf_tree->undo_history = dialog->sgf_undo_history; sgf_utils_begin_action (sgf_tree); if (sgf_utils_set_text_property (dialog->sgf_node, sgf_tree, sgf_property_type, new_value, 1)) { SgfPropertyChangeData *data = utils_malloc (sizeof (SgfPropertyChangeData)); data->dialog = dialog; data->sgf_property_type = sgf_property_type; sgf_utils_apply_custom_undo_entry (sgf_tree, &property_change_undo_entry_data, data, NULL); g_signal_emit (dialog, game_info_dialog_signals[PROPERTY_CHANGED], 0, sgf_property_type); dialog->simple_undo_field = NULL; if (sgf_property_type == SGF_GAME_NAME) update_title (dialog); } sgf_utils_end_action (sgf_tree); sgf_tree->undo_history = saved_undo_history; } } static void property_has_changed (SgfPropertyChangeData *data) { data->dialog->modified_property_type = data->sgf_property_type; } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/gtk-games.c0000644000175000017500000001647710456741777015720 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "gtk-games.h" #include "gtk-utils.h" #include "gui-back-end.h" #include "board.h" #include "game-info.h" #include #include static void set_standard_board_size (GtkButton *size_button, GtkSpinButton *spin_button); const gchar *game_labels[NUM_SUPPORTED_GAMES] = { N_("_Go"), N_("_Amazons"), N_("_Reversi") }; const gchar *game_rules_labels[NUM_SUPPORTED_GAMES] = { N_("Go Rules"), N_("Amazons Rules"), N_("Reversi Rules"), }; const Game index_to_game[NUM_SUPPORTED_GAMES] = { GAME_GO, GAME_AMAZONS, GAME_REVERSI }; const gchar * gtk_games_get_capitalized_name (Game game) { static gchar *capitalized_names[LAST_GAME + 1]; static gboolean first_call = TRUE; g_return_val_if_fail (FIRST_GAME <= game && game <= LAST_GAME, NULL); if (first_call) { memset (capitalized_names, 0, sizeof capitalized_names); first_call = FALSE; } if (!capitalized_names[game]) { const gchar *game_name = _(game_info[game].name); gunichar first_character_capitalized = g_unichar_toupper (g_utf8_get_char (game_name)); gchar *first_character_string = g_ucs4_to_utf8 (&first_character_capitalized, 1, NULL, NULL, NULL); capitalized_names[game] = g_strconcat (first_character_string, g_utf8_next_char (game_name), NULL); gui_back_end_register_pointer_to_free (capitalized_names[game]); } return capitalized_names[game]; } gboolean gtk_games_engine_supports_game (GtpEngineListItem *engine_data, GtkGameIndex game_index) { g_return_val_if_fail (0 <= game_index && game_index < NUM_SUPPORTED_GAMES, FALSE); return (!engine_data || (string_list_find (&engine_data->supported_games, INDEX_TO_GAME_NAME (game_index)) != NULL)); } gint gtk_games_name_to_index (const gchar *game_name, gboolean case_sensitive) { return gtk_games_get_game_index (game_from_game_name (game_name, case_sensitive)); } GtkGameIndex gtk_games_get_game_index (Game game) { switch (game) { case GAME_GO: return GTK_GAME_GO; case GAME_AMAZONS: return GTK_GAME_AMAZONS; case GAME_REVERSI: return GTK_GAME_REVERSI; default: return GTK_GAME_UNSUPPORTED; } } GtkAdjustment * gtk_games_create_board_size_adjustment (GtkGameIndex game_index, gint initial_value) { g_return_val_if_fail (0 <= game_index && game_index < NUM_SUPPORTED_GAMES, NULL); if (initial_value <= 0) initial_value = game_info[index_to_game[game_index]].default_board_size; switch (game_index) { case GTK_GAME_GO: return ((GtkAdjustment *) gtk_adjustment_new (initial_value, GTK_MIN_BOARD_SIZE, GTK_MAX_BOARD_SIZE, 1, 2, 0)); case GTK_GAME_AMAZONS: return ((GtkAdjustment *) gtk_adjustment_new (initial_value, GTK_MIN_BOARD_SIZE, GTK_MAX_BOARD_SIZE, 1, 2, 0)); case GTK_GAME_REVERSI: return ((GtkAdjustment *) gtk_adjustment_new (initial_value, ROUND_UP (GTK_MIN_BOARD_SIZE, 2), ROUND_DOWN (GTK_MAX_BOARD_SIZE, 2), 2, 4, 0)); default: g_assert_not_reached (); return NULL; } } GtkWidget * gtk_games_create_board_size_selector_box (GtkGameIndex game_index, GtkAdjustment *adjustment, GtkWidget **board_size_spin_button) { Game game; GtkWidget *spin_button; GtkWidget *label; GtkWidget *hbox; g_return_val_if_fail (0 <= game_index && game_index < NUM_SUPPORTED_GAMES, NULL); g_return_val_if_fail (adjustment, NULL); spin_button = gtk_utils_create_spin_button (adjustment, 0.0, 0, TRUE); if (board_size_spin_button) *board_size_spin_button = spin_button; label = gtk_utils_create_mnemonic_label (_("Board _size:"), spin_button); hbox = gtk_utils_pack_in_box (GTK_TYPE_HBOX, QUARRY_SPACING, label, GTK_UTILS_FILL, spin_button, GTK_UTILS_FILL, NULL); game = index_to_game[game_index]; if (game_info[game].standard_board_sizes) { StringList standard_board_sizes = STATIC_STRING_LIST; const StringListItem *item; string_list_fill_from_string (&standard_board_sizes, game_info[game].standard_board_sizes); if (!string_list_is_empty (&standard_board_sizes)) { GtkSizeGroup *size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); for (item = standard_board_sizes.first; item; item = item->next) { GtkWidget *button = gtk_button_new_with_label (item->text); GTK_WIDGET_UNSET_FLAGS (button, GTK_CAN_FOCUS); gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_HALF); gtk_size_group_add_widget (size_group, button); gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0); g_signal_connect (button, "clicked", G_CALLBACK (set_standard_board_size), spin_button); } string_list_empty (&standard_board_sizes); } } return hbox; } GtkAdjustment * gtk_games_create_handicap_adjustment (gint initial_value) { return ((GtkAdjustment *) gtk_adjustment_new (initial_value, 0, GTK_MAX_BOARD_SIZE * GTK_MAX_BOARD_SIZE, 1, 2, 0)); } GtkAdjustment * gtk_games_create_komi_adjustmet (gdouble initial_value) { return ((GtkAdjustment *) gtk_adjustment_new (initial_value, -999.5, 999.5, 1.0, 5.0, 0.0)); } void gtk_games_set_handicap_adjustment_limits (gint board_width, gint board_height, GtkAdjustment *fixed_handicap_adjustment, GtkAdjustment *free_handicap_adjustment) { if (fixed_handicap_adjustment) { int max_fixed_handicap = go_get_max_fixed_handicap (board_width, board_height); fixed_handicap_adjustment->upper = (gdouble) max_fixed_handicap; gtk_adjustment_changed (fixed_handicap_adjustment); } if (free_handicap_adjustment) { free_handicap_adjustment->upper = ((gdouble) (board_width * board_height - 1)); gtk_adjustment_changed (free_handicap_adjustment); } } static void set_standard_board_size (GtkButton *size_button, GtkSpinButton *spin_button) { gtk_spin_button_set_value (spin_button, atoi (gtk_button_get_label (size_button))); gtk_widget_grab_focus (GTK_WIDGET (spin_button)); } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/gtk-goban.c0000644000175000017500000021106210456742044015661 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "gtk-goban.h" #include "gtk-configuration.h" #include "gtk-goban-base.h" #include "gtk-preferences.h" #include "gtk-tile-set.h" #include "gtk-utils.h" #include "quarry-marshal.h" #include "tile-renderer.h" #include "sgf.h" #include "board.h" #include "game-info.h" #include "utils.h" #include #include #include #include #ifdef HAVE_MEMORY_H #include #endif #define MODIFIER_MASK (GDK_SHIFT_MASK \ | GDK_CONTROL_MASK \ | GDK_MOD1_MASK \ | GDK_BUTTON1_MASK \ | GDK_BUTTON3_MASK) #define VERTICAL_LINE_GAP(goban) \ (4 + (10 * (goban)->character_height) / 9) enum { NO_CHECKERBOARD_PATTERN, CHECKERBOARD_PATTERN_WITH_PIXBUF, CHECKERBOARD_PATTERN_WITH_PIXMAP }; typedef struct _GtkGobanMargins GtkGobanMargins; struct _GtkGobanMargins { gint stones_left_margin; gint stones_top_margin; gint small_stones_left_margin; gint small_stones_top_margin; gint sgf_markup_left_margin; gint sgf_markup_top_margin; }; static void gtk_goban_class_init (GtkGobanClass *class); static void gtk_goban_init (GtkGoban *goban); static void gtk_goban_realize (GtkWidget *widget); static void gtk_goban_size_request (GtkWidget *widget, GtkRequisition *requisition); static void gtk_goban_size_allocate (GtkWidget *widget, GtkAllocation *allocation); static gboolean gtk_goban_expose (GtkWidget *widget, GdkEventExpose *event); inline static void draw_vertical_line_with_gaps (GtkGoban *goban, GdkWindow *window, GdkGC *gc, int x, gint window_x, gint extra_length); inline static void draw_horizontal_line_with_gaps (GtkGoban *goban, GdkWindow *window, GdkGC *gc, int y, gint window_y, gint extra_length); static void render_label (GtkGoban *goban, GdkDrawable *drawable, GdkGC *gc, PangoLayout **layout, const char *label_text, gint x, gint y, GdkColor *color); static gboolean gtk_goban_button_press_event (GtkWidget *widget, GdkEventButton *event); static gboolean gtk_goban_button_release_event (GtkWidget *widget, GdkEventButton *event); static gboolean gtk_goban_motion_notify_event (GtkWidget *widget, GdkEventMotion *event); static gboolean gtk_goban_enter_notify_event (GtkWidget *widget, GdkEventCrossing *event); static gboolean gtk_goban_leave_notify_event (GtkWidget *widget, GdkEventCrossing *event); static gboolean gtk_goban_scroll_event (GtkWidget *widget, GdkEventScroll *event); static gboolean gtk_goban_key_press_event (GtkWidget *widget, GdkEventKey *event); static gboolean gtk_goban_key_release_event (GtkWidget *widget, GdkEventKey *event); static gboolean gtk_goban_focus_in_or_out_event (GtkWidget *widget, GdkEventFocus *event); static void gtk_goban_allocate_screen_resources (GtkGobanBase *goban_base); static void gtk_goban_free_screen_resources (GtkGobanBase *goban_base); static void gtk_goban_click_canceled (GtkGoban *goban); static void gtk_goban_finalize (GObject *object); static void emit_pointer_moved (GtkGoban *goban, int x, int y, GdkModifierType modifiers); static void set_feedback_data (GtkGoban *goban, int x, int y, BoardPositionList *position_list, GtkGobanPointerFeedback feedback); static void set_overlay_data (GtkGoban *goban, int overlay_index, BoardPositionList *position_list, int tile, int goban_markup_tile, int sgf_markup_tile); static void compute_goban_margins (const GtkGoban *goban, GtkGobanMargins *margins); static void widget_coordinates_to_board (const GtkGoban *goban, int window_x, int window_y, int *board_x, int *board_y); static void create_label_text_pixbuf (GtkGoban *goban); static GdkPixbuf * get_or_create_label_feedback_pixbuf (GtkGoban *goban, gint background); static void free_label_feedback_data (GtkGoban *goban, gboolean including_label_text); static GtkGobanBaseClass *parent_class; enum { POINTER_MOVED, CLICK_CANCELED, GOBAN_CLICKED, NAVIGATE, NUM_SIGNALS }; static guint goban_signals[NUM_SIGNALS]; GType gtk_goban_get_type (void) { static GType goban_type = 0; if (!goban_type) { static GTypeInfo goban_info = { sizeof (GtkGobanClass), NULL, NULL, (GClassInitFunc) gtk_goban_class_init, NULL, NULL, sizeof (GtkGoban), 2, (GInstanceInitFunc) gtk_goban_init, NULL }; goban_type = g_type_register_static (GTK_TYPE_GOBAN_BASE, "GtkGoban", &goban_info, 0); } return goban_type; } static void gtk_goban_class_init (GtkGobanClass *class) { static GtkUtilsBindingInfo navigation_bindings[] = { {GDK_Left, 0, GOBAN_NAVIGATE_BACK}, {GDK_Page_Up, 0, GOBAN_NAVIGATE_BACK_FAST}, {GDK_Right, 0, GOBAN_NAVIGATE_FORWARD}, {GDK_Page_Down, 0, GOBAN_NAVIGATE_FORWARD_FAST}, {GDK_Up, 0, GOBAN_NAVIGATE_PREVIOUS_VARIATION}, {GDK_Down, 0, GOBAN_NAVIGATE_NEXT_VARIATION}, {GDK_Home, 0, GOBAN_NAVIGATE_ROOT}, {GDK_End, 0, GOBAN_NAVIGATE_VARIATION_END} }; GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class); GtkGobanBaseClass *base_class = GTK_GOBAN_BASE_CLASS (class); GtkBindingSet *binding_set; parent_class = g_type_class_peek_parent (class); G_OBJECT_CLASS (class)->finalize = gtk_goban_finalize; widget_class->realize = gtk_goban_realize; widget_class->size_request = gtk_goban_size_request; widget_class->size_allocate = gtk_goban_size_allocate; widget_class->expose_event = gtk_goban_expose; widget_class->button_press_event = gtk_goban_button_press_event; widget_class->button_release_event = gtk_goban_button_release_event; widget_class->motion_notify_event = gtk_goban_motion_notify_event; widget_class->enter_notify_event = gtk_goban_enter_notify_event; widget_class->leave_notify_event = gtk_goban_leave_notify_event; widget_class->scroll_event = gtk_goban_scroll_event; widget_class->key_press_event = gtk_goban_key_press_event; widget_class->key_release_event = gtk_goban_key_release_event; widget_class->focus_in_event = gtk_goban_focus_in_or_out_event; widget_class->focus_out_event = gtk_goban_focus_in_or_out_event; base_class->allocate_screen_resources = gtk_goban_allocate_screen_resources; base_class->free_screen_resources = gtk_goban_free_screen_resources; class->pointer_moved = NULL; class->click_canceled = gtk_goban_click_canceled; class->goban_clicked = NULL; class->navigate = NULL; goban_signals[POINTER_MOVED] = g_signal_new ("pointer-moved", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GtkGobanClass, pointer_moved), NULL, NULL, quarry_marshal_INT__POINTER, G_TYPE_INT, 1, G_TYPE_POINTER); goban_signals[CLICK_CANCELED] = g_signal_new ("click-canceled", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GtkGobanClass, click_canceled), NULL, NULL, quarry_marshal_VOID__VOID, G_TYPE_NONE, 0); goban_signals[GOBAN_CLICKED] = g_signal_new ("goban-clicked", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GtkGobanClass, goban_clicked), NULL, NULL, quarry_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); goban_signals[NAVIGATE] = g_signal_new ("navigate", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GtkGobanClass, navigate), NULL, NULL, quarry_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT); binding_set = gtk_binding_set_by_class (class); gtk_utils_add_similar_bindings (binding_set, "navigate", navigation_bindings, (sizeof navigation_bindings / sizeof (GtkUtilsBindingInfo))); } static void gtk_goban_init (GtkGoban *goban) { int k; int i; GTK_WIDGET_SET_FLAGS (GTK_WIDGET (goban), GTK_CAN_FOCUS); goban->width = 0; goban->height = 0; goban->font_size = 0; goban->checkerboard_pattern_object = NULL; goban->label_feedback_text = NULL; goban->label_text_pixbuf = NULL; for (k = 0; k < NUM_SGF_MARKUP_BACKGROUNDS; k++) { for (i = 0; i < NUM_LABEL_GHOST_LEVELS; i++) goban->label_ghost_pixbufs[i][k] = NULL; } goban->last_move_pos = NULL_POSITION; for (k = 0; k < NUM_OVERLAYS; k++) { goban->overlay_positon_lists[k] = NULL; goban->overlay_contents[k] = NULL; } set_feedback_data (goban, NULL_X, NULL_Y, NULL, GOBAN_FEEDBACK_NONE); goban->label_feedback_pos = NULL_POSITION; } GtkWidget * gtk_goban_new (void) { return GTK_WIDGET (g_object_new (GTK_TYPE_GOBAN, NULL)); } void gtk_goban_set_parameters (GtkGoban *goban, Game game, int width, int height) { g_return_if_fail (GTK_IS_GOBAN (goban)); g_return_if_fail (GAME_IS_SUPPORTED (game)); g_return_if_fail (width > 0 && height > 0); if (goban->width && goban->height) { int x; int y; for (y = 0; y < goban->height; y++) { for (x = 0; x < goban->width; x++) g_free (goban->sgf_labels[POSITION (x, y)]); } } goban->width = width; goban->height = height; grid_fill (goban->grid, goban->width, goban->height, TILE_NONE); grid_fill (goban->goban_markup, goban->width, goban->height, SGF_MARKUP_NONE); grid_fill (goban->sgf_markup, goban->width, goban->height, TILE_NONE); pointer_grid_fill ((void **) goban->sgf_labels, goban->width, goban->height, NULL); if (game == GAME_GO) { goban->num_hoshi_points = go_get_hoshi_points (width, height, goban->hoshi_points); } else goban->num_hoshi_points = 0; gtk_goban_base_set_game (GTK_GOBAN_BASE (goban), game); } static void gtk_goban_realize (GtkWidget *widget) { GtkGoban *goban = GTK_GOBAN (widget); GdkWindowAttr attributes; const gint attributes_mask = (GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP); const gint event_mask = (GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_ENTER_NOTIFY_MASK | GDK_SCROLL_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK); GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED); attributes.event_mask = gtk_widget_get_events (widget) | event_mask; attributes.x = widget->allocation.x; attributes.y = widget->allocation.y; attributes.width = widget->allocation.width; attributes.height = widget->allocation.height; attributes.wclass = GDK_INPUT_OUTPUT; attributes.visual = gtk_widget_get_visual (widget); attributes.colormap = gtk_widget_get_colormap (widget); attributes.window_type = GDK_WINDOW_CHILD; widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask); gdk_window_set_user_data (widget->window, goban); widget->style = gtk_style_attach (widget->style, widget->window); gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL); GTK_WIDGET_CLASS (parent_class)->realize (widget); } /* FIXME: write this function. */ static void gtk_goban_size_request (GtkWidget *widget, GtkRequisition *requisition) { UNUSED (widget); requisition->width = 500; requisition->height = 500; } static void gtk_goban_size_allocate (GtkWidget *widget, GtkAllocation *allocation) { GtkGoban *goban = GTK_GOBAN (widget); gint cell_size; Game game = goban->base.game; int grid_width = goban->width - (game == GAME_GO ? 1 : 0); int grid_height = goban->height - (game == GAME_GO ? 1 : 0); int font_size; float vertical_gap = (game == GAME_GO ? 0.65 : 0.8); float horizontal_gap = (goban->height < 10 && game == GAME_GO ? 0.65 : 0.8); int horizontal_deficit; int horizontal_gap_pixels; int vertical_padding; g_return_if_fail (goban->width != 0 && goban->height != 0); cell_size = floor (MIN (allocation->width / (goban->width + 2 * horizontal_gap), allocation->height / (goban->height + 2 * vertical_gap))); font_size = (3 * cell_size) / 7; if (font_size != goban->font_size) { PangoLayout *layout = gtk_widget_create_pango_layout (widget, "8"); goban->font_size = font_size; pango_font_description_set_size (goban->base.font_description, font_size * PANGO_SCALE); pango_layout_set_font_description (layout, goban->base.font_description); pango_layout_get_pixel_size (layout, &goban->digit_width, &goban->character_height); goban->digit_width += 2; g_object_unref (layout); } horizontal_deficit = (allocation->width - goban->width * cell_size - (goban->height < 10 ? 2 : 4) * goban->digit_width); if (horizontal_deficit < 0) cell_size -= (-horizontal_deficit + goban->width - 1) / goban->width; gtk_goban_base_set_cell_size (&goban->base, cell_size); goban->left_margin = (allocation->width - grid_width * cell_size) / 2; goban->right_margin = goban->left_margin + grid_width * cell_size; goban->top_margin = (allocation->height - grid_height * cell_size) / 2; goban->bottom_margin = goban->top_margin + grid_height * cell_size; goban->first_cell_center_x = (allocation->width - (goban->width - 1) * cell_size) / 2; goban->first_cell_center_y = (allocation->height - (goban->height - 1) * cell_size) / 2; horizontal_gap_pixels = MAX (horizontal_gap * cell_size, ((goban->height < 10 ? 1 : 2) * goban->digit_width)); vertical_padding = (vertical_gap * cell_size - goban->character_height) / 2; goban->coordinates_x_left = (goban->first_cell_center_x - cell_size / 2 - horizontal_gap_pixels / 2 - 1); goban->coordinates_x_right = (goban->coordinates_x_left + goban->width * cell_size + horizontal_gap_pixels - 1); goban->coordinates_y_side = (goban->first_cell_center_y - goban->character_height / 2); goban->coordinates_y_top = (goban->first_cell_center_y - (0.5 + vertical_gap) * cell_size + vertical_padding); goban->coordinates_y_bottom = (goban->first_cell_center_y + (-0.5 + goban->height) * cell_size + vertical_padding); g_signal_emit (goban, goban_signals[CLICK_CANCELED], 0); GTK_WIDGET_CLASS (parent_class)->size_allocate (widget, allocation); if (GTK_WIDGET_REALIZED (widget)) { int x; int y; GdkModifierType modifiers; gdk_window_get_pointer (widget->window, &x, &y, &modifiers); widget_coordinates_to_board (goban, x, y, &x, &y); if (x != goban->pointer_x || y != goban->pointer_y || (modifiers & MODIFIER_MASK) != goban->modifiers) emit_pointer_moved (goban, x, y, modifiers & MODIFIER_MASK); } } static gboolean gtk_goban_expose (GtkWidget *widget, GdkEventExpose *event) { int k; int x; int y; gint window_x; gint window_y; gint clip_left_margin = event->area.x; gint clip_right_margin = event->area.x + event->area.width; gint clip_top_margin = event->area.y; gint clip_bottom_margin = event->area.y + event->area.height; GtkGobanMargins margins; gint lower_limit; gint upper_limit; GdkRectangle row_rectangle; GdkRectangle cell_rectangle; PangoLayout *label_layout = NULL; GtkGoban *goban = GTK_GOBAN (widget); int cell_size = goban->base.cell_size; gint checkerboard_pattern_mode; GdkWindow *window = widget->window; GdkGC *gc = widget->style->fg_gc[GTK_STATE_NORMAL]; if (!GTK_WIDGET_DRAWABLE (widget)) return FALSE; if (GTK_WIDGET_HAS_FOCUS (widget)) { /* Draw a small rectangle to indicate focus. */ gdk_draw_rectangle (window, gc, FALSE, goban->coordinates_x_left - 1, (goban->coordinates_y_top + goban->character_height / 2 - 4), 7, 7); } if (goban->base.game == GAME_GO) { /* Draw grid lines. */ for (x = MAX (0, clip_left_margin - goban->left_margin) / cell_size, window_x = goban->left_margin + x * cell_size; window_x <= goban->right_margin && window_x < clip_right_margin; x++, window_x += cell_size) draw_vertical_line_with_gaps (goban, window, gc, x, window_x, 0); for (y = MAX (0, clip_top_margin - goban->top_margin) / cell_size, window_y = goban->top_margin + y * cell_size; window_y <= goban->bottom_margin && window_y < clip_bottom_margin; y++, window_y += cell_size) draw_horizontal_line_with_gaps (goban, window, gc, y, window_y, 0); /* Make the outmost grid lines thicker. */ if (clip_left_margin <= goban->left_margin - 1) { draw_vertical_line_with_gaps (goban, window, gc, 0, goban->left_margin - 1, 1); } if (clip_right_margin > goban->right_margin + 1) { draw_vertical_line_with_gaps (goban, window, gc, goban->width - 1, goban->right_margin + 1, 1); } if (clip_top_margin <= goban->top_margin - 1) { draw_horizontal_line_with_gaps (goban, window, gc, 0, goban->top_margin - 1, 1); } if (clip_bottom_margin > goban->bottom_margin + 1) { draw_horizontal_line_with_gaps (goban, window, gc, goban->height - 1, goban->bottom_margin + 1, 1); } } else { /* Draw grid lines. */ for (window_x = (goban->left_margin + ((MAX (0, clip_left_margin - goban->left_margin) / cell_size) * cell_size)); window_x <= goban->right_margin && window_x < clip_right_margin; window_x += cell_size) { gdk_draw_line (window, gc, window_x, goban->top_margin, window_x, goban->bottom_margin); } for (window_y = (goban->top_margin + ((MAX (0, clip_top_margin - goban->top_margin) / cell_size) * cell_size)); window_y <= goban->bottom_margin && window_y < clip_bottom_margin; window_y += cell_size) { gdk_draw_line (window, gc, goban->left_margin, window_y, goban->right_margin, window_y); } /* Make the outmost grid lines thicker. */ if (clip_left_margin <= goban->left_margin - 1) { gdk_draw_line (window, gc, goban->left_margin - 1, goban->top_margin, goban->left_margin - 1, goban->bottom_margin); } if (clip_right_margin > goban->right_margin + 1) { gdk_draw_line (window, gc, goban->right_margin + 1, goban->top_margin, goban->right_margin + 1, goban->bottom_margin); } if (clip_top_margin <= goban->top_margin - 1) { gdk_draw_line (window, gc, goban->left_margin - 1, goban->top_margin - 1, goban->right_margin + 1, goban->top_margin - 1); } if (clip_bottom_margin > goban->bottom_margin + 1) { gdk_draw_line (window, gc, goban->left_margin - 1, goban->bottom_margin + 1, goban->right_margin + 1, goban->bottom_margin + 1); } } /* Draw coordinate labels. */ if (clip_left_margin < goban->left_margin || clip_right_margin > goban->right_margin || clip_top_margin < goban->top_margin || clip_bottom_margin > goban->bottom_margin) { PangoLayout *coordinate_layout = gtk_widget_create_pango_layout (widget, NULL); const char *horizontal_coordinates = game_info[goban->base.game].horizontal_coordinates; pango_layout_set_font_description (coordinate_layout, goban->base.font_description); pango_layout_set_alignment (coordinate_layout, PANGO_ALIGN_CENTER); pango_layout_set_width (coordinate_layout, 2 * cell_size); /* Left and right label columns. */ if (clip_left_margin < goban->left_margin || clip_right_margin > goban->right_margin) { lower_limit = MAX (0, ((clip_top_margin - goban->coordinates_y_side) / cell_size)); upper_limit = MIN (goban->height, (1 + ((clip_bottom_margin - goban->coordinates_y_side) / cell_size))); for (k = lower_limit; k < upper_limit; k++) { char buffer[4]; sprintf (buffer, "%d", (game_info[goban->base.game].reversed_vertical_coordinates ? goban->height - k : k + 1)); pango_layout_set_text (coordinate_layout, buffer, -1); if (clip_left_margin < goban->left_margin) { gdk_draw_layout (widget->window, gc, goban->coordinates_x_left, goban->coordinates_y_side + k * cell_size, coordinate_layout); } if (clip_right_margin > goban->right_margin) { gdk_draw_layout (widget->window, gc, goban->coordinates_x_right, goban->coordinates_y_side + k * cell_size, coordinate_layout); } } } /* Top and bottom label rows. */ if (clip_top_margin < goban->top_margin || clip_bottom_margin > goban->bottom_margin) { lower_limit = MAX (0, ((clip_left_margin - (goban->first_cell_center_x - cell_size / 2)) / cell_size)); upper_limit = MIN (goban->width, (1 + ((clip_right_margin - (goban->first_cell_center_x - cell_size / 2)) / cell_size))); for (k = lower_limit; k < upper_limit; k++) { pango_layout_set_text (coordinate_layout, horizontal_coordinates + k, 1); if (clip_top_margin < goban->top_margin) { gdk_draw_layout (widget->window, gc, goban->first_cell_center_x + k * cell_size, goban->coordinates_y_top, coordinate_layout); } if (clip_bottom_margin > goban->bottom_margin) { gdk_draw_layout (widget->window, gc, goban->first_cell_center_x + k * cell_size, goban->coordinates_y_bottom, coordinate_layout); } } } g_object_unref (coordinate_layout); } /* FIXME: Not clipped now. Needs a rewrite anyway. */ for (k = 0; k < goban->num_hoshi_points; k++) { if (!goban->sgf_labels[POINT_TO_POSITION (goban->hoshi_points[k])]) { window_x = goban->left_margin + goban->hoshi_points[k].x * cell_size; window_y = goban->top_margin + goban->hoshi_points[k].y * cell_size; gdk_draw_rectangle (window, gc, FALSE, window_x - 2, window_y - 1, 4, 2); gdk_draw_rectangle (window, gc, FALSE, window_x - 1, window_y - 2, 2, 4); } } if (goban->checkerboard_pattern_object) { if (GDK_IS_PIXBUF (goban->checkerboard_pattern_object)) checkerboard_pattern_mode = CHECKERBOARD_PATTERN_WITH_PIXBUF; else { g_assert (GDK_IS_PIXMAP (goban->checkerboard_pattern_object)); checkerboard_pattern_mode = CHECKERBOARD_PATTERN_WITH_PIXMAP; } } else checkerboard_pattern_mode = NO_CHECKERBOARD_PATTERN; compute_goban_margins (goban, &margins); row_rectangle.x = event->area.x; row_rectangle.width = event->area.width; row_rectangle.y = (checkerboard_pattern_mode == NO_CHECKERBOARD_PATTERN ? margins.stones_top_margin : MIN (margins.stones_top_margin, goban->top_margin + 1)); if (checkerboard_pattern_mode == NO_CHECKERBOARD_PATTERN) row_rectangle.height = cell_size; else { row_rectangle.height = (MAX ((margins.stones_top_margin + goban->base.main_tile_set->tile_size), goban->top_margin + 1 + cell_size) - row_rectangle.y); } cell_rectangle.width = row_rectangle.height; cell_rectangle.height = row_rectangle.height; lower_limit = MAX (0, (clip_top_margin - row_rectangle.y) / cell_size); upper_limit = MIN (goban->height, (1 + ((clip_bottom_margin - (row_rectangle.y + (row_rectangle.height - cell_size))) / cell_size))); for (y = lower_limit, row_rectangle.y += lower_limit * cell_size; y < upper_limit; y++, row_rectangle.y += cell_size) { GdkRegion *row_region = gdk_region_rectangle (&row_rectangle); gdk_region_intersect (row_region, event->region); if (!gdk_region_empty (row_region)) { cell_rectangle.x = (checkerboard_pattern_mode == NO_CHECKERBOARD_PATTERN ? margins.stones_left_margin : MIN (margins.stones_left_margin, goban->left_margin + 1)); cell_rectangle.y = row_rectangle.y; for (x = 0; x < goban->width; x++, cell_rectangle.x += cell_size) { if (gdk_region_rect_in (row_region, &cell_rectangle) != GDK_OVERLAP_RECTANGLE_OUT) { int pos = POSITION (x, y); int tile = goban->grid[pos]; int markup_tile = ((unsigned char) goban->goban_markup[pos] & GOBAN_MARKUP_TILE_MASK); int sgf_markup_tile = (pos != goban->last_move_pos ? goban->sgf_markup[pos] : SGF_PSEUDO_MARKUP_LAST_MOVE); if (checkerboard_pattern_mode != NO_CHECKERBOARD_PATTERN && (x + y) % 2 == 1) { if (checkerboard_pattern_mode == CHECKERBOARD_PATTERN_WITH_PIXBUF) { gdk_draw_pixbuf (window, gc, ((GdkPixbuf *) goban->checkerboard_pattern_object), 0, 0, goban->left_margin + 1 + x * cell_size, goban->top_margin + 1 + y * cell_size, -1, -1, GDK_RGB_DITHER_NORMAL, 0, 0); } else { gdk_draw_drawable (window, gc, ((GdkDrawable *) goban->checkerboard_pattern_object), 0, 0, goban->left_margin + 1 + x * cell_size, goban->top_margin + 1 + y * cell_size, -1, -1); } } if (tile != TILE_NONE && tile != TILE_SPECIAL) { if (IS_STONE (tile)) { if (goban->goban_markup[pos] & GOBAN_MARKUP_GHOSTIFY) tile = STONE_50_TRANSPARENT + COLOR_INDEX (tile); else if (goban->goban_markup[pos] & GOBAN_MARKUP_GHOSTIFY_SLIGHTLY) tile = STONE_25_TRANSPARENT + COLOR_INDEX (tile); } gdk_draw_pixbuf (window, gc, goban->base.main_tile_set->tiles[tile], 0, 0, margins.stones_left_margin + x * cell_size, margins.stones_top_margin + y * cell_size, -1, -1, GDK_RGB_DITHER_NORMAL, 0, 0); } else if (tile == TILE_SPECIAL) { int base_x = goban->left_margin + x * cell_size; int base_y = goban->top_margin + y * cell_size; gdk_draw_line (window, gc, base_x, base_y, base_x + cell_size, base_y + cell_size); gdk_draw_line (window, gc, base_x, base_y + cell_size, base_x + cell_size, base_y); } if (markup_tile != TILE_NONE) { g_assert (markup_tile != TILE_SPECIAL); gdk_draw_pixbuf (window, gc, goban->small_tile_set->tiles[markup_tile], 0, 0, margins.small_stones_left_margin + x * cell_size, margins.small_stones_top_margin + y * cell_size, -1, -1, GDK_RGB_DITHER_NORMAL, 0, 0); } if (sgf_markup_tile != SGF_MARKUP_NONE) { gint background = (IS_STONE (goban->grid[pos]) ? goban->grid[pos] : EMPTY); GdkPixbuf *pixbuf; if (sgf_markup_tile < NUM_SGF_MARKUPS) { if (goban->goban_markup[pos] & GOBAN_MARKUP_GHOSTIFY_SGF_MARKUP) { sgf_markup_tile = (SGF_MARKUP_50_TRANSPARENT + (sgf_markup_tile % NUM_ALL_SGF_MARKUPS)); } else if (goban->goban_markup[pos] & GOBAN_MARKUP_GHOSTIFY_SGF_MARKUP_SLIGHTLY) { sgf_markup_tile = (SGF_MARKUP_25_TRANSPARENT + (sgf_markup_tile % NUM_ALL_SGF_MARKUPS)); } } pixbuf = (goban->base.sgf_markup_tile_set ->tiles[sgf_markup_tile][background]); gdk_draw_pixbuf (window, gc, pixbuf, 0, 0, margins.sgf_markup_left_margin + x * cell_size, margins.sgf_markup_top_margin + y * cell_size, -1, -1, GDK_RGB_DITHER_NORMAL, 0, 0); } if (goban->sgf_labels[pos] || pos == goban->label_feedback_pos) { gint background; if (IS_STONE (goban->grid[pos])) background = goban->grid[pos]; else { switch (markup_tile) { case BLACK_OPAQUE: case BLACK_25_TRANSPARENT: case BLACK_50_TRANSPARENT: background = BLACK; break; case WHITE_OPAQUE: case WHITE_25_TRANSPARENT: case WHITE_50_TRANSPARENT: background = WHITE; break; default: background = EMPTY; } } if (pos == goban->label_feedback_pos) { GdkPixbuf *pixbuf = get_or_create_label_feedback_pixbuf (goban, background); gdk_draw_pixbuf (window, gc, pixbuf, 0, 0, (goban->first_cell_center_x + x * cell_size - gdk_pixbuf_get_width (pixbuf) / 2), (goban->first_cell_center_y + y * cell_size - gdk_pixbuf_get_height (pixbuf) / 2), -1, -1, GDK_RGB_DITHER_NORMAL, 0, 0); } else { BoardAppearance *board_appearance = game_to_board_appearance_structure (goban->base.game); GdkColor color; gtk_utils_set_gdk_color (&color, board_appearance->markup_colors[background]); render_label (goban, widget->window, gc, &label_layout, goban->sgf_labels[pos], goban->first_cell_center_x + x * cell_size, goban->first_cell_center_y + y * cell_size, &color); } } } } } gdk_region_destroy (row_region); } if (label_layout) g_object_unref (label_layout); return FALSE; } /* Draw a vertical line, leaving gaps in places where there are labels * (to avoid cluttering them.) */ inline static void draw_vertical_line_with_gaps (GtkGoban *goban, GdkWindow *window, GdkGC *gc, int x, gint window_x, gint extra_length) { gint gap_half = VERTICAL_LINE_GAP (goban) / 2; gint top = goban->top_margin - extra_length; int y; gint window_y; for (y = 0, window_y = goban->first_cell_center_y; y < goban->height; y++, window_y += goban->base.cell_size) { if (goban->sgf_labels[POSITION (x, y)] || goban->label_feedback_pos == POSITION (x, y)) { if (window_y - gap_half > top) { gdk_draw_line (window, gc, window_x, top, window_x, window_y - gap_half); } top = window_y + gap_half; } } if (goban->bottom_margin > top) { gdk_draw_line (window, gc, window_x, top, window_x, goban->bottom_margin + extra_length); } } /* Just as draw_vertical_line_with_gaps(), but draws horizontally. */ inline static void draw_horizontal_line_with_gaps (GtkGoban *goban, GdkWindow *window, GdkGC *gc, int y, gint window_y, gint extra_length) { gint gap_half = (goban->base.cell_size - 1) / 2; gint left = goban->left_margin - extra_length; int x; gint window_x; for (x = 0, window_x = goban->first_cell_center_x; x < goban->width; x++, window_x += goban->base.cell_size) { if (goban->sgf_labels[POSITION (x, y)] || goban->label_feedback_pos == POSITION (x, y)) { if (window_x - gap_half > left) { gdk_draw_line (window, gc, left, window_y, window_x - gap_half, window_y); } left = window_x + gap_half; } } if (goban->right_margin > left) { gdk_draw_line (window, gc, left, window_y, goban->right_margin + extra_length, window_y); } } static void render_label (GtkGoban *goban, GdkDrawable *drawable, GdkGC *gc, PangoLayout **layout, const char *label_text, gint x, gint y, GdkColor *color) { if (! *layout) { *layout = gtk_widget_create_pango_layout (GTK_WIDGET (goban), NULL); pango_layout_set_font_description (*layout, goban->base.font_description); pango_layout_set_alignment (*layout, PANGO_ALIGN_CENTER); pango_layout_set_width (*layout, goban->base.cell_size - 2); } pango_layout_set_text (*layout, label_text, -1); gdk_draw_layout_with_colors (drawable, gc, x, y - goban->character_height / 2, *layout, color, NULL); } static gboolean gtk_goban_button_press_event (GtkWidget *widget, GdkEventButton *event) { if (event->button == 1 || event->button == 3) { GtkGoban *goban = GTK_GOBAN (widget); int x; int y; GdkModifierType modifiers; gdk_window_get_pointer (widget->window, &x, &y, &modifiers); widget_coordinates_to_board (goban, x, y, &x, &y); if (!IS_NULL_POINT (x, y)) { if (goban->button_pressed == 0) { goban->button_pressed = event->button; goban->press_x = x; goban->press_y = y; goban->press_modifiers = modifiers & MODIFIER_MASK; goban->feedback_tile_at_press = goban->feedback_tile; } else goban->button_pressed = -1; emit_pointer_moved (goban, x, y, modifiers & MODIFIER_MASK); } else if (goban->button_pressed == 0 && !GTK_WIDGET_HAS_FOCUS (widget)) gtk_widget_grab_focus (widget); } return FALSE; } static gboolean gtk_goban_button_release_event (GtkWidget *widget, GdkEventButton *event) { if (event->button == 1 || event->button == 3) { GtkGoban *goban = GTK_GOBAN (widget); GdkModifierType modifiers; GdkModifierType button_mask = (event->button == 1 ? GDK_BUTTON1_MASK : GDK_BUTTON3_MASK); GtkGobanClickData data; gdk_window_get_pointer (widget->window, &data.x, &data.y, &modifiers); widget_coordinates_to_board (goban, data.x, data.y, &data.x, &data.y); if (goban->button_pressed == event->button) { goban->button_pressed = 0; if ((goban->anti_slip_disabled || (data.x == goban->press_x && data.y == goban->press_y)) && (((modifiers & MODIFIER_MASK) | button_mask) == goban->press_modifiers)) { data.non_empty_feedback = goban->non_empty_feedback; data.button = event->button; data.modifiers = modifiers & ~button_mask; g_signal_emit (goban, goban_signals[GOBAN_CLICKED], 0, &data); } else g_signal_emit (goban, goban_signals[CLICK_CANCELED], 0); } else { if (!(modifiers & (GDK_BUTTON1_MASK | GDK_BUTTON3_MASK))) g_signal_emit (goban, goban_signals[CLICK_CANCELED], 0); } emit_pointer_moved (goban, data.x, data.y, modifiers & MODIFIER_MASK); } return FALSE; } static gboolean gtk_goban_motion_notify_event (GtkWidget *widget, GdkEventMotion *event) { GtkGoban *goban = GTK_GOBAN (widget); int x; int y; widget_coordinates_to_board (goban, event->x, event->y, &x, &y); if (x != goban->pointer_x || y != goban->pointer_y || (event->state & MODIFIER_MASK) != goban->modifiers) emit_pointer_moved (goban, x, y, event->state & MODIFIER_MASK); return FALSE; } static gboolean gtk_goban_enter_notify_event (GtkWidget *widget, GdkEventCrossing *event) { GtkGoban *goban = GTK_GOBAN (widget); int x; int y; widget_coordinates_to_board (goban, event->x, event->y, &x, &y); emit_pointer_moved (goban, x, y, event->state & MODIFIER_MASK); return FALSE; } static gboolean gtk_goban_leave_notify_event (GtkWidget *widget, GdkEventCrossing *event) { GtkGoban *goban = GTK_GOBAN (widget); UNUSED (event); if (goban->button_pressed) g_signal_emit (goban, goban_signals[CLICK_CANCELED], 0); set_feedback_data (goban, NULL_X, NULL_Y, NULL, GOBAN_FEEDBACK_NONE); gtk_goban_set_label_feedback (goban, NULL_X, NULL_Y, NULL, 0); return FALSE; } /* Navigate goban in respond to mouse wheel movement. Default is * navigating back/forth by moves. Shift causes switching between * variations, Ctrl makes navigation fast. */ static gboolean gtk_goban_scroll_event (GtkWidget *widget, GdkEventScroll *event) { gint direction; switch (event->direction) { case GDK_SCROLL_UP: if (!(event->state & GDK_SHIFT_MASK)) { direction = (event->state & GDK_CONTROL_MASK ? GOBAN_NAVIGATE_BACK_FAST : GOBAN_NAVIGATE_BACK); break; } case GDK_SCROLL_LEFT: direction = GOBAN_NAVIGATE_PREVIOUS_VARIATION; break; case GDK_SCROLL_DOWN: if (!(event->state & GDK_SHIFT_MASK)) { direction = (event->state & GDK_CONTROL_MASK ? GOBAN_NAVIGATE_FORWARD_FAST : GOBAN_NAVIGATE_FORWARD); break; } case GDK_SCROLL_RIGHT: direction = GOBAN_NAVIGATE_NEXT_VARIATION; break; default: return FALSE; } g_signal_emit (widget, goban_signals[NAVIGATE], 0, direction); return FALSE; } static gboolean gtk_goban_key_press_event (GtkWidget *widget, GdkEventKey *event) { GtkGoban *goban = GTK_GOBAN (widget); GdkModifierType modifiers; gdk_window_get_pointer (widget->window, NULL, NULL, &modifiers); if ((modifiers & MODIFIER_MASK) != goban->modifiers) { emit_pointer_moved (goban, goban->pointer_x, goban->pointer_y, modifiers & MODIFIER_MASK); } return GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event); } static gboolean gtk_goban_key_release_event (GtkWidget *widget, GdkEventKey *event) { GtkGoban *goban = GTK_GOBAN (widget); GdkModifierType modifiers; gdk_window_get_pointer (widget->window, NULL, NULL, &modifiers); if ((modifiers & MODIFIER_MASK) != goban->modifiers) { emit_pointer_moved (goban, goban->pointer_x, goban->pointer_y, modifiers & MODIFIER_MASK); } return GTK_WIDGET_CLASS (parent_class)->key_release_event (widget, event); } static gboolean gtk_goban_focus_in_or_out_event (GtkWidget *widget, GdkEventFocus *event) { GtkGoban *goban = GTK_GOBAN (widget); GdkRectangle rectangle = { goban->coordinates_x_left - 1, (goban->coordinates_y_top + goban->character_height / 2 - 4), 8, 8 }; UNUSED (event); gdk_window_invalidate_rect (widget->window, &rectangle, FALSE); /* Don't fallback to default handler, since we don't need full * widget redraw. */ return FALSE; } static void gtk_goban_allocate_screen_resources (GtkGobanBase *goban_base) { GtkGoban *goban = GTK_GOBAN (goban_base); gint cell_size = goban->base.cell_size; parent_class->allocate_screen_resources (goban_base); goban->small_tile_set = gtk_main_tile_set_create_or_reuse ((2 * cell_size - 1) / 3, goban->base.game); if (goban->base.game == GAME_AMAZONS) { QuarryColor color = amazons_board_appearance.checkerboard_pattern_color; double opacity = amazons_board_appearance.checkerboard_pattern_opacity; guint8 actual_opacity = G_MAXUINT8 * CLAMP (opacity, 0.0, 1.0); if (actual_opacity > 0) { if (!amazons_board_appearance.board_appearance.use_background_texture) { QuarryColor *background_color = &amazons_board_appearance.board_appearance.background_color; /* No point in using semi-transparent pixbuf if there is no * texture. Just mix the colors. */ color.red = (opacity * color.red + (1 - opacity) * background_color->red); color.green = (opacity * color.green + (1 - opacity) * background_color->green); color.blue = (opacity * color.blue + (1 - opacity) * background_color->blue); actual_opacity = G_MAXUINT8; } if (actual_opacity < G_MAXUINT8) { goban->checkerboard_pattern_object = (GObject *) gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, cell_size - 1, cell_size - 1); gdk_pixbuf_fill (GDK_PIXBUF (goban->checkerboard_pattern_object), (actual_opacity | (color.red << 24) | (color.green << 16) | (color.blue << 8))); } else { GdkGC *gc = gdk_gc_new (GTK_WIDGET (goban)->window); GdkColor gdk_color; gtk_utils_set_gdk_color (&gdk_color, color); gdk_gc_set_rgb_fg_color (gc, &gdk_color); goban->checkerboard_pattern_object = (GObject *) gdk_pixmap_new (GTK_WIDGET (goban)->window, cell_size - 1, cell_size - 1, -1); gdk_draw_rectangle (GDK_DRAWABLE (goban->checkerboard_pattern_object), gc, TRUE, 0, 0, cell_size - 1, cell_size - 1); g_object_unref (gc); } } } } static void gtk_goban_free_screen_resources (GtkGobanBase *goban_base) { GtkGoban *goban = GTK_GOBAN (goban_base); object_cache_unreference_object (>k_main_tile_set_cache, goban->small_tile_set); if (goban->checkerboard_pattern_object) { g_object_unref (goban->checkerboard_pattern_object); goban->checkerboard_pattern_object = NULL; } parent_class->free_screen_resources (goban_base); } static void gtk_goban_click_canceled (GtkGoban *goban) { goban->button_pressed = 0; } static void gtk_goban_finalize (GObject *object) { GtkGoban *goban = GTK_GOBAN (object); int k; if (goban->width && goban->height) { int x; int y; for (y = 0; y < goban->height; y++) { for (x = 0; x < goban->width; x++) g_free (goban->sgf_labels[POSITION (x, y)]); } } for (k = 0; k < NUM_OVERLAYS; k++) { if (goban->overlay_positon_lists[k]) { board_position_list_delete (goban->overlay_positon_lists[k]); g_free (goban->overlay_contents[k]); } } if (goban->checkerboard_pattern_object) g_object_unref (goban->checkerboard_pattern_object); free_label_feedback_data (goban, TRUE); G_OBJECT_CLASS (parent_class)->finalize (object); } gint gtk_goban_negotiate_width (GtkWidget *widget, gint height) { UNUSED (widget); UNUSED (height); return height; } gint gtk_goban_negotiate_height (GtkWidget *widget, gint width) { UNUSED (widget); UNUSED (width); return width; } void gtk_goban_update (GtkGoban *goban, const char grid[BOARD_GRID_SIZE], const char goban_markup[BOARD_GRID_SIZE], const char sgf_markup[BOARD_GRID_SIZE], const SgfLabelList *sgf_label_list, int last_move_x, int last_move_y) { GtkWidget *widget; gint width; gint height; gint cell_size; int k; int x; int y; int last_move_pos; g_return_if_fail (GTK_IS_GOBAN (goban)); for (k = NUM_OVERLAYS; --k >= 0;) set_overlay_data (goban, k, NULL, TILE_NONE, TILE_NONE, SGF_MARKUP_NONE); if (!grid) grid = goban->grid; if (!goban_markup) goban_markup = goban->goban_markup; if (!sgf_markup) sgf_markup = goban->sgf_markup; /* Never let last move markup to override real SGF markup. */ last_move_pos = POSITION (last_move_x, last_move_y); if (sgf_markup[last_move_pos] != SGF_MARKUP_NONE) last_move_pos = NULL_POSITION; widget = GTK_WIDGET (goban); width = goban->width; height = goban->height; cell_size = goban->base.cell_size; if (GTK_WIDGET_REALIZED (widget)) { GtkGobanMargins margins; GdkRectangle rectangle_stone; GdkRectangle rectangle_markup; GdkRectangle rectangle_sgf_markup; GdkRectangle rectangle_sgf_label; const SgfLabel *sgf_label = NULL; const SgfLabel *sgf_labels_limit = NULL; if (sgf_label_list && sgf_label_list != KEEP_SGF_LABELS) { sgf_label = sgf_label_list->labels; sgf_labels_limit = sgf_label_list->labels + sgf_label_list->num_labels; } rectangle_stone.width = goban->base.main_tile_set->tile_size; rectangle_stone.height = goban->base.main_tile_set->tile_size; rectangle_markup.width = goban->small_tile_set->tile_size; rectangle_markup.height = goban->small_tile_set->tile_size; rectangle_sgf_markup.width = goban->base.sgf_markup_tile_set->tile_size; rectangle_sgf_markup.height = goban->base.sgf_markup_tile_set->tile_size; rectangle_sgf_label.width = cell_size - 2; /* NOTE: Keep in sync with draw_vertical_line_with_gaps(). Or * maybe define a macro. */ rectangle_sgf_label.height = VERTICAL_LINE_GAP (goban); compute_goban_margins (goban, &margins); for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { int pos = POSITION (x, y); if (goban->grid[pos] != grid[pos] || ((goban->goban_markup[pos] & GOBAN_MARKUP_GRID_FLAGS_MASK) != (goban_markup[pos] & GOBAN_MARKUP_GRID_FLAGS_MASK))) { rectangle_stone.x = margins.stones_left_margin + x * cell_size; rectangle_stone.y = margins.stones_top_margin + y * cell_size; gdk_window_invalidate_rect (widget->window, &rectangle_stone, FALSE); goban->grid[pos] = grid[pos]; goban->goban_markup[pos] = goban_markup[pos]; goban->sgf_markup[pos] = sgf_markup[pos]; } else if (goban->sgf_markup[pos] != sgf_markup[pos] || ((pos == last_move_pos || pos == goban->last_move_pos) && last_move_pos != goban->last_move_pos)) { rectangle_sgf_markup.x = (margins.sgf_markup_left_margin + x * cell_size); rectangle_sgf_markup.y = (margins.sgf_markup_top_margin + y * cell_size); gdk_window_invalidate_rect (widget->window, &rectangle_sgf_markup, FALSE); goban->goban_markup[pos] = goban_markup[pos]; goban->sgf_markup[pos] = sgf_markup[pos]; } else if (goban->goban_markup[pos] != goban_markup[pos]) { rectangle_markup.x = (margins.small_stones_left_margin + x * cell_size); rectangle_markup.y = (margins.small_stones_top_margin + y * cell_size); gdk_window_invalidate_rect (widget->window, &rectangle_markup, FALSE); goban->goban_markup[pos] = goban_markup[pos]; } if (sgf_label_list != KEEP_SGF_LABELS) { char *label_text = ((sgf_label != sgf_labels_limit && sgf_label->point.x == x && sgf_label->point.y == y) ? sgf_label->text : NULL); if (goban->sgf_labels[pos] ? (!label_text || strcmp (goban->sgf_labels[pos], label_text) != 0) : label_text != NULL) { rectangle_sgf_label.x = (goban->first_cell_center_x - rectangle_sgf_label.width / 2 + x * cell_size); rectangle_sgf_label.y = (goban->first_cell_center_y - rectangle_sgf_label.height / 2 + y * cell_size); gdk_window_invalidate_rect (widget->window, &rectangle_sgf_label, FALSE); g_free (goban->sgf_labels[pos]); goban->sgf_labels[pos] = (label_text ? g_strdup (label_text) : NULL); } if (label_text) sgf_label++; } } } } else { grid_copy (goban->grid, grid, width, height); grid_copy (goban->goban_markup, goban_markup, width, height); grid_copy (goban->sgf_markup, sgf_markup, width, height); if (sgf_label_list != KEEP_SGF_LABELS) { for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { int pos = POSITION (x, y); g_free (goban->sgf_labels[pos]); goban->sgf_labels[pos] = NULL; } } if (sgf_label_list) { for (k = 0; k < sgf_label_list->num_labels; k++) { int pos = POINT_TO_POSITION (sgf_label_list->labels[k].point); goban->sgf_labels[pos] = g_strdup (sgf_label_list->labels[k].text); } } } } goban->last_move_pos = last_move_pos; } void gtk_goban_force_feedback_poll (GtkGoban *goban) { emit_pointer_moved (goban, goban->pointer_x, goban->pointer_y, goban->modifiers); } void gtk_goban_set_label_feedback (GtkGoban *goban, int x, int y, const char *label_text, int ghost_level) { int positions_to_invalidate[2] = { NULL_POSITION, NULL_POSITION }; gboolean free_data = TRUE; g_return_if_fail (GTK_IS_GOBAN (goban)); g_return_if_fail (0 <= ghost_level && ghost_level < NUM_LABEL_GHOST_LEVELS); if (ON_SIZED_GRID (goban->width, goban->height, x, y)) { g_return_if_fail (label_text && *label_text); if (goban->label_feedback_pos != POSITION (x, y)) { positions_to_invalidate[0] = goban->label_feedback_pos; positions_to_invalidate[1] = POSITION (x, y); goban->label_feedback_pos = POSITION (x, y); } else if (goban->label_feedback_ghost_level != ghost_level || !goban->label_feedback_text || strcmp (goban->label_feedback_text, label_text) != 0) positions_to_invalidate[0] = goban->label_feedback_pos; else free_data = FALSE; goban->label_feedback_ghost_level = ghost_level; } else { g_return_if_fail (x == NULL_X && y == NULL_Y && !label_text); positions_to_invalidate[0] = goban->label_feedback_pos; goban->label_feedback_pos = NULL_POSITION; } if (free_data) free_label_feedback_data (goban, TRUE); if (label_text && !goban->label_feedback_text) { goban->label_feedback_text = g_strdup (label_text); if (GTK_WIDGET_REALIZED (goban)) create_label_text_pixbuf (goban); } if (GTK_WIDGET_REALIZED (goban)) { gint cell_size = goban->base.cell_size; GdkRectangle rectangle; int k; rectangle.width = cell_size - 2; rectangle.height = VERTICAL_LINE_GAP (goban); for (k = 0; k < 2 && positions_to_invalidate[k]; k++) { rectangle.x = (goban->first_cell_center_x - rectangle.width / 2 + POSITION_X (positions_to_invalidate[k]) * cell_size); rectangle.y = (goban->first_cell_center_y - rectangle.height / 2 + POSITION_Y (positions_to_invalidate[k]) * cell_size); gdk_window_invalidate_rect (GTK_WIDGET (goban)->window, &rectangle, FALSE); } } } void gtk_goban_set_overlay_data (GtkGoban *goban, int overlay_index, BoardPositionList *position_list, int tile, int goban_markup_tile, int sgf_markup_tile) { const BoardPositionList *feedback_position_list = goban->overlay_positon_lists[FEEDBACK_OVERLAY]; int need_feedback_poll = (position_list && feedback_position_list && board_position_lists_overlap (feedback_position_list, position_list)); g_return_if_fail (goban); g_return_if_fail (0 <= overlay_index && overlay_index < NUM_OVERLAYS && overlay_index != FEEDBACK_OVERLAY); g_return_if_fail ((0 <= tile && tile < NUM_TILES) || tile == GOBAN_TILE_DONT_CHANGE); g_return_if_fail ((0 <= goban_markup_tile && goban_markup_tile < NUM_TILES) || goban_markup_tile == GOBAN_TILE_DONT_CHANGE); g_return_if_fail (tile != GOBAN_TILE_DONT_CHANGE || goban_markup_tile != GOBAN_TILE_DONT_CHANGE); if (need_feedback_poll) { set_overlay_data (goban, FEEDBACK_OVERLAY, NULL, TILE_NONE, TILE_NONE, SGF_MARKUP_NONE); } set_overlay_data (goban, overlay_index, position_list, tile, goban_markup_tile, sgf_markup_tile); if (need_feedback_poll) { emit_pointer_moved (goban, goban->pointer_x, goban->pointer_y, goban->modifiers); } } void gtk_goban_disable_anti_slip_mode (GtkGoban *goban) { g_return_if_fail (GTK_IS_GOBAN (goban)); g_return_if_fail (goban->button_pressed != 0); goban->anti_slip_disabled = TRUE; } void gtk_goban_set_contents (GtkGoban *goban, BoardPositionList *position_list, int grid_contents, int goban_markup_contents, int sgf_markup_contents) { int k; g_return_if_fail (GTK_IS_GOBAN (goban)); g_return_if_fail (goban->base.game != GAME_DUMMY); for (k = NUM_OVERLAYS; --k >= 0;) set_overlay_data (goban, k, NULL, TILE_NONE, TILE_NONE, SGF_MARKUP_NONE); set_overlay_data (goban, 0, position_list, grid_contents, goban_markup_contents, sgf_markup_contents); g_free (goban->overlay_contents[0]); goban->overlay_positon_lists[0] = NULL; } int gtk_goban_get_grid_contents (GtkGoban *goban, int x, int y) { int k; int pos = POSITION (x, y); g_return_val_if_fail (GTK_IS_GOBAN (goban), OFF_GRID); g_return_val_if_fail (goban->base.game != GAME_DUMMY, OFF_GRID); g_return_val_if_fail (ON_SIZED_GRID (goban->width, goban->height, x, y), OFF_GRID); for (k = NUM_OVERLAYS; --k >= 0;) { if (goban->overlay_positon_lists[k]) { int position_index = board_position_list_find_position (goban->overlay_positon_lists[k], pos); if (position_index != -1) return goban->overlay_contents[k][position_index]; } } return goban->grid[pos]; } int gtk_goban_get_sgf_markup_contents (GtkGoban *goban, int x, int y) { int k; int pos = POSITION (x, y); g_return_val_if_fail (GTK_IS_GOBAN (goban), SGF_MARKUP_NONE); g_return_val_if_fail (goban->base.game != GAME_DUMMY, SGF_MARKUP_NONE); g_return_val_if_fail (ON_SIZED_GRID (goban->width, goban->height, x, y), SGF_MARKUP_NONE); for (k = NUM_OVERLAYS; --k >= 0;) { if (goban->overlay_positon_lists[k]) { const BoardPositionList *position_list = goban->overlay_positon_lists[k]; int position_index = board_position_list_find_position (position_list, pos); if (position_index != -1) return goban->overlay_contents[k][2 * position_list->num_positions + position_index]; } } return goban->sgf_markup[pos]; } static void emit_pointer_moved (GtkGoban *goban, int x, int y, GdkModifierType modifiers) { if (ON_SIZED_GRID (goban->width, goban->height, x, y) && (goban->button_pressed == 0 || goban->press_modifiers == modifiers)) { GtkGobanPointerData data; GtkGobanPointerFeedback feedback; data.x = x; data.y = y; data.feedback_position_list = NULL; data.modifiers = modifiers; data.button = goban->button_pressed; data.press_x = goban->press_x; data.press_y = goban->press_y; g_signal_emit (goban, goban_signals[POINTER_MOVED], 0, &data, &feedback); g_assert (data.button || ((feedback & GOBAN_FEEDBACK_GRID_MASK) != GOBAN_FEEDBACK_PRESS_DEFAULT)); if (data.feedback_position_list) set_feedback_data (goban, x, y, data.feedback_position_list, feedback); else { int pos = POSITION (x, y); set_feedback_data (goban, x, y, board_position_list_new (&pos, 1), feedback); } } else { set_feedback_data (goban, NULL_X, NULL_Y, NULL, GOBAN_FEEDBACK_NONE); gtk_goban_set_label_feedback (goban, NULL_X, NULL_Y, NULL, 0); } goban->modifiers = modifiers; } static void set_feedback_data (GtkGoban *goban, int x, int y, BoardPositionList *position_list, GtkGobanPointerFeedback feedback) { int feedback_grid = feedback & GOBAN_FEEDBACK_GRID_MASK; int feedback_goban_markup = ((feedback & GOBAN_FEEDBACK_MARKUP_MASK) / GOBAN_FEEDBACK_MARKUP_FACTOR); int feedback_sgf_markup = ((feedback & GOBAN_FEEDBACK_SGF_MASK) / GOBAN_FEEDBACK_SGF_FACTOR); int feedback_tile; int goban_markup_feedback_tile; int sgf_markup_feedback_tile; switch (feedback_goban_markup) { case GOBAN_FEEDBACK_FORCE_TILE_NONE: goban_markup_feedback_tile = TILE_NONE; break; case GOBAN_FEEDBACK_BLACK_OPAQUE: case GOBAN_FEEDBACK_WHITE_OPAQUE: goban_markup_feedback_tile = (STONE_OPAQUE + (feedback_goban_markup - GOBAN_FEEDBACK_OPAQUE)); break; case GOBAN_FEEDBACK_BLACK_GHOST: case GOBAN_FEEDBACK_WHITE_GHOST: goban_markup_feedback_tile = (STONE_50_TRANSPARENT + (feedback_goban_markup - GOBAN_FEEDBACK_GHOST)); break; case GOBAN_FEEDBACK_THICK_BLACK_GHOST: case GOBAN_FEEDBACK_THICK_WHITE_GHOST: goban_markup_feedback_tile = (STONE_25_TRANSPARENT + (feedback_goban_markup - GOBAN_FEEDBACK_THICK_GHOST)); break; default: goban_markup_feedback_tile = GOBAN_TILE_DONT_CHANGE; } switch (feedback_grid) { case GOBAN_FEEDBACK_FORCE_TILE_NONE: feedback_tile = TILE_NONE; break; case GOBAN_FEEDBACK_BLACK_OPAQUE: case GOBAN_FEEDBACK_WHITE_OPAQUE: feedback_tile = (STONE_OPAQUE + (feedback_grid - GOBAN_FEEDBACK_OPAQUE)); break; case GOBAN_FEEDBACK_BLACK_GHOST: case GOBAN_FEEDBACK_WHITE_GHOST: feedback_tile = (STONE_50_TRANSPARENT + (feedback_grid - GOBAN_FEEDBACK_GHOST)); break; case GOBAN_FEEDBACK_GHOSTIFY: feedback_tile = GOBAN_TILE_DONT_CHANGE; goban_markup_feedback_tile |= GOBAN_MARKUP_GHOSTIFY; break; case GOBAN_FEEDBACK_THICK_BLACK_GHOST: case GOBAN_FEEDBACK_THICK_WHITE_GHOST: feedback_tile = (STONE_25_TRANSPARENT + (feedback_grid - GOBAN_FEEDBACK_THICK_GHOST)); break; case GOBAN_FEEDBACK_GHOSTIFY_SLIGHTLY: feedback_tile = GOBAN_TILE_DONT_CHANGE; goban_markup_feedback_tile |= GOBAN_MARKUP_GHOSTIFY_SLIGHTLY; break; case GOBAN_FEEDBACK_PRESS_DEFAULT: feedback_tile = GOBAN_TILE_DONT_CHANGE; if (x == goban->press_x && y == goban->press_y) { switch (goban->feedback_tile_at_press) { case BLACK_25_TRANSPARENT: case WHITE_25_TRANSPARENT: feedback_tile = (goban->feedback_tile_at_press + STONE_50_TRANSPARENT - STONE_25_TRANSPARENT); break; case BLACK_50_TRANSPARENT: case WHITE_50_TRANSPARENT: feedback_tile = (goban->feedback_tile_at_press + STONE_25_TRANSPARENT - STONE_50_TRANSPARENT); break; case TILE_SPECIAL: feedback_tile = TILE_SPECIAL; break; } } break; case GOBAN_FEEDBACK_BLACK_MOVE: case GOBAN_FEEDBACK_WHITE_MOVE: { int color_index = feedback_grid - GOBAN_FEEDBACK_MOVE; g_return_if_fail (position_list->num_positions == 1); if (COLOR_INDEX (goban->grid[POSITION (x, y)]) != color_index) feedback_tile = STONE_50_TRANSPARENT + color_index; else feedback_tile = STONE_25_TRANSPARENT + color_index; } break; case GOBAN_FEEDBACK_ADD_BLACK_OR_REMOVE: case GOBAN_FEEDBACK_ADD_WHITE_OR_REMOVE: { int contents = gtk_goban_get_grid_contents (goban, x, y); if (contents == EMPTY) { feedback_tile = (STONE_50_TRANSPARENT + (feedback_grid - GOBAN_FEEDBACK_ADD_OR_REMOVE)); } else if (IS_STONE (contents)) feedback_tile = STONE_25_TRANSPARENT + COLOR_INDEX (contents); else feedback_tile = GOBAN_TILE_DONT_CHANGE; } break; case GOBAN_FEEDBACK_SPECIAL: feedback_tile = TILE_SPECIAL; break; default: feedback_tile = GOBAN_TILE_DONT_CHANGE; } switch (feedback_sgf_markup) { case GOBAN_FEEDBACK_SGF_CROSS_OPAQUE: case GOBAN_FEEDBACK_SGF_CIRCLE_OPAQUE: case GOBAN_FEEDBACK_SGF_SQUARE_OPAQUE: case GOBAN_FEEDBACK_SGF_TRIANGLE_OPAQUE: case GOBAN_FEEDBACK_SGF_SELECTED_OPAQUE: case GOBAN_FEEDBACK_SGF_CROSS_GHOST: case GOBAN_FEEDBACK_SGF_CIRCLE_GHOST: case GOBAN_FEEDBACK_SGF_SQUARE_GHOST: case GOBAN_FEEDBACK_SGF_TRIANGLE_GHOST: case GOBAN_FEEDBACK_SGF_SELECTED_GHOST: case GOBAN_FEEDBACK_SGF_CROSS_THICK_GHOST: case GOBAN_FEEDBACK_SGF_CIRCLE_THICK_GHOST: case GOBAN_FEEDBACK_SGF_SQUARE_THICK_GHOST: case GOBAN_FEEDBACK_SGF_TRIANGLE_THICK_GHOST: case GOBAN_FEEDBACK_SGF_SELECTED_THICK_GHOST: sgf_markup_feedback_tile = (feedback_sgf_markup - GOBAN_FEEDBACK_SGF_TILE_BASE); break; case GOBAN_FEEDBACK_SGF_GHOSTIFY: sgf_markup_feedback_tile = GOBAN_SGF_MARKUP_TILE_DONT_CHANGE; goban_markup_feedback_tile |= GOBAN_MARKUP_GHOSTIFY_SGF_MARKUP; break; case GOBAN_FEEDBACK_SGF_GHOSTIFY_SLIGHTLY: sgf_markup_feedback_tile = GOBAN_SGF_MARKUP_TILE_DONT_CHANGE; goban_markup_feedback_tile |= GOBAN_MARKUP_GHOSTIFY_SGF_MARKUP_SLIGHTLY; break; default: sgf_markup_feedback_tile = GOBAN_SGF_MARKUP_TILE_DONT_CHANGE; }; if (feedback_tile != GOBAN_TILE_DONT_CHANGE || goban_markup_feedback_tile != GOBAN_TILE_DONT_CHANGE || sgf_markup_feedback_tile != GOBAN_SGF_MARKUP_TILE_DONT_CHANGE) { set_overlay_data (goban, FEEDBACK_OVERLAY, position_list, feedback_tile, goban_markup_feedback_tile, sgf_markup_feedback_tile); goban->non_empty_feedback = TRUE; } else { if (position_list) board_position_list_delete (position_list); set_overlay_data (goban, FEEDBACK_OVERLAY, NULL, TILE_NONE, TILE_NONE, SGF_MARKUP_NONE); goban->non_empty_feedback = FALSE; } goban->pointer_x = x; goban->pointer_y = y; goban->feedback_tile = feedback_tile; } static void set_overlay_data (GtkGoban *goban, int overlay_index, BoardPositionList *position_list, int tile, int goban_markup_tile, int sgf_markup_tile) { GtkWidget *widget = GTK_WIDGET (goban); BoardPositionList *old_position_list = goban->overlay_positon_lists[overlay_index]; int num_new_positions = (position_list ? position_list->num_positions : -1); int num_old_positions = (old_position_list ? old_position_list->num_positions : -1); char *const old_overlay_contents = goban->overlay_contents[overlay_index]; char *const grid = goban->grid; char *const goban_markup = goban->goban_markup; char *const sgf_markup = goban->sgf_markup; int i; int j; if (position_list == NULL && old_position_list == NULL) return; if (GTK_WIDGET_REALIZED (widget)) { int cell_size = goban->base.cell_size; GtkGobanMargins margins; GdkRectangle rectangle_stone; GdkRectangle rectangle_markup; GdkRectangle rectangle_sgf_markup; compute_goban_margins (goban, &margins); rectangle_stone.width = goban->base.main_tile_set->tile_size; rectangle_stone.height = goban->base.main_tile_set->tile_size; rectangle_markup.width = goban->small_tile_set->tile_size; rectangle_markup.height = goban->small_tile_set->tile_size; rectangle_sgf_markup.width = goban->base.sgf_markup_tile_set->tile_size; rectangle_sgf_markup.height = goban->base.sgf_markup_tile_set->tile_size; for (i = 0, j = 0; i < num_new_positions || j < num_old_positions;) { int pos; char new_tile; char new_goban_markup_tile; char new_sgf_markup_tile; if (i < num_new_positions && (j >= num_old_positions || (position_list->positions[i] <= old_position_list->positions[j]))) { int same_positions; pos = position_list->positions[i++]; same_positions = (j < num_old_positions && pos == old_position_list->positions[j]); if (tile != GOBAN_TILE_DONT_CHANGE) new_tile = tile; else { if (same_positions) new_tile = old_overlay_contents[j]; else new_tile = grid[pos]; } if ((goban_markup_tile & GOBAN_MARKUP_TILE_MASK) != GOBAN_TILE_DONT_CHANGE) new_goban_markup_tile = goban_markup_tile; else { if (same_positions) { new_goban_markup_tile = old_overlay_contents[num_old_positions + j]; } else new_goban_markup_tile = goban_markup[pos]; new_goban_markup_tile = ((new_goban_markup_tile & GOBAN_MARKUP_TILE_MASK) | (goban_markup_tile & GOBAN_MARKUP_FLAGS_MASK)); } if (sgf_markup_tile != GOBAN_SGF_MARKUP_TILE_DONT_CHANGE) new_sgf_markup_tile = sgf_markup_tile; else { if (same_positions) { new_sgf_markup_tile = old_overlay_contents[2 * num_old_positions + j]; } else new_sgf_markup_tile = sgf_markup[pos]; } if (same_positions) j++; } else { pos = old_position_list->positions[j]; new_tile = old_overlay_contents[j]; new_goban_markup_tile = old_overlay_contents[num_old_positions + j]; new_sgf_markup_tile = old_overlay_contents[2 * num_old_positions + j]; j++; } if (new_tile != grid[pos] || new_goban_markup_tile != goban_markup[pos] || new_sgf_markup_tile != sgf_markup[pos]) { int x = POSITION_X (pos); int y = POSITION_Y (pos); if (new_tile != grid[pos] || (new_goban_markup_tile & GOBAN_MARKUP_GRID_FLAGS_MASK) || (goban_markup[pos] & GOBAN_MARKUP_GRID_FLAGS_MASK)) { rectangle_stone.x = margins.stones_left_margin + x * cell_size; rectangle_stone.y = margins.stones_top_margin + y * cell_size; gdk_window_invalidate_rect (widget->window, &rectangle_stone, FALSE); } else if (new_sgf_markup_tile != sgf_markup[pos] || (new_sgf_markup_tile & GOBAN_MARKUP_SGF_FLAGS_MASK) || (sgf_markup[pos] & GOBAN_MARKUP_SGF_FLAGS_MASK)) { rectangle_sgf_markup.x = (margins.sgf_markup_left_margin + x * cell_size); rectangle_sgf_markup.y = (margins.sgf_markup_top_margin + y * cell_size); gdk_window_invalidate_rect (widget->window, &rectangle_sgf_markup, FALSE); } else { rectangle_markup.x = (margins.small_stones_left_margin + x * cell_size); rectangle_markup.y = (margins.small_stones_top_margin + y * cell_size); gdk_window_invalidate_rect (widget->window, &rectangle_markup, FALSE); } } } } if (old_position_list) { for (j = 0; j < num_old_positions; j++) { grid[old_position_list->positions[j]] = old_overlay_contents[j]; goban_markup[old_position_list->positions[j]] = old_overlay_contents[num_old_positions + j]; sgf_markup[old_position_list->positions[j]] = old_overlay_contents[2 * num_old_positions + j]; } board_position_list_delete (old_position_list); g_free (old_overlay_contents); } goban->overlay_positon_lists[overlay_index] = position_list; if (position_list) { goban->overlay_contents[overlay_index] = g_malloc ((3 * num_new_positions) * sizeof (char)); for (i = 0; i < num_new_positions; i++) { int pos = position_list->positions[i]; goban->overlay_contents[overlay_index][i] = grid[pos]; if (tile != GOBAN_TILE_DONT_CHANGE) grid[pos] = tile; goban->overlay_contents[overlay_index][num_new_positions + i] = goban_markup[pos]; if ((goban_markup_tile & GOBAN_MARKUP_TILE_MASK) != GOBAN_TILE_DONT_CHANGE) goban_markup[pos] = goban_markup_tile; else { goban_markup[pos] = ((goban_markup[pos] & GOBAN_MARKUP_TILE_MASK) | (goban_markup_tile & GOBAN_MARKUP_FLAGS_MASK)); } goban->overlay_contents[overlay_index][2 * num_new_positions + i] = sgf_markup[pos]; if (sgf_markup_tile != GOBAN_SGF_MARKUP_TILE_DONT_CHANGE) sgf_markup[pos] = sgf_markup_tile; } } } static void compute_goban_margins (const GtkGoban *goban, GtkGobanMargins *margins) { margins->stones_left_margin = goban->left_margin; margins->stones_top_margin = goban->top_margin; if (goban->base.game == GAME_GO) { margins->sgf_markup_left_margin = goban->left_margin - goban->base.sgf_markup_tile_set->tile_size / 2; margins->sgf_markup_top_margin = goban->top_margin - goban->base.sgf_markup_tile_set->tile_size / 2; } else { margins->stones_left_margin += goban->base.cell_size / 2; margins->stones_top_margin += goban->base.cell_size / 2; margins->sgf_markup_left_margin = goban->left_margin + 1; margins->sgf_markup_top_margin = goban->top_margin + 1; } margins->small_stones_left_margin = margins->stones_left_margin + goban->small_tile_set->stones_x_offset; margins->small_stones_top_margin = margins->stones_top_margin + goban->small_tile_set->stones_y_offset; margins->stones_left_margin += goban->base.main_tile_set->stones_x_offset; margins->stones_top_margin += goban->base.main_tile_set->stones_y_offset; } static void widget_coordinates_to_board (const GtkGoban *goban, int window_x, int window_y, int *board_x, int *board_y) { gint cell_size = goban->base.cell_size; window_x -= goban->first_cell_center_x - cell_size / 2; window_y -= goban->first_cell_center_y - cell_size / 2; if (window_x >= 0 && window_y >= 0) { *board_x = window_x / cell_size; *board_y = window_y / cell_size; if (*board_x < goban->width && *board_y < goban->height) return; } *board_x = NULL_X; *board_y = NULL_Y; } static void create_label_text_pixbuf (GtkGoban *goban) { GtkWidget *widget = GTK_WIDGET (goban); gint width = goban->base.cell_size - 2; gint height = VERTICAL_LINE_GAP (goban); GdkDrawable *drawable = GDK_DRAWABLE (gdk_pixmap_new (widget->window, width, height, -1)); PangoLayout *layout = NULL; gdk_draw_rectangle (drawable, widget->style->black_gc, TRUE, 0, 0, width, height); render_label (goban, drawable, GTK_WIDGET (goban)->style->white_gc, &layout, goban->label_feedback_text, width / 2, height / 2, NULL); goban->label_text_pixbuf = gdk_pixbuf_get_from_drawable (gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, width, height), drawable, NULL, 0, 0, 0, 0, width, height); g_object_unref (drawable); } static GdkPixbuf * get_or_create_label_feedback_pixbuf (GtkGoban *goban, gint background) { gint ghost_level = goban->label_feedback_ghost_level; if (!goban->label_ghost_pixbufs[ghost_level][background]) { gint width = gdk_pixbuf_get_width (goban->label_text_pixbuf); gint height = gdk_pixbuf_get_height (goban->label_text_pixbuf); guchar *pixel_data = gdk_pixbuf_get_pixels (goban->label_text_pixbuf); gint row_stride = gdk_pixbuf_get_rowstride (goban->label_text_pixbuf); BoardAppearance *board_appearance = game_to_board_appearance_structure (goban->base.game); QuarryColor color = board_appearance->markup_colors[background]; unsigned char *saturated_pixels; if (ghost_level == LABEL_25_TRANSPARENT) { saturated_pixels = saturate_and_set_alpha (color, 3, 4, width, height, pixel_data, row_stride); } else if (ghost_level == LABEL_50_TRANSPARENT) { saturated_pixels = saturate_and_set_alpha (color, 1, 2, width, height, pixel_data, row_stride); } else { g_assert_not_reached (); return NULL; } goban->label_ghost_pixbufs[ghost_level][background] = gdk_pixbuf_new_from_data (saturated_pixels, GDK_COLORSPACE_RGB, TRUE, 8, width, height, row_stride, (GdkPixbufDestroyNotify) utils_free, NULL); } return goban->label_ghost_pixbufs[ghost_level][background]; } static void free_label_feedback_data (GtkGoban *goban, gboolean including_label_text) { int k; int i; if (including_label_text) { g_free (goban->label_feedback_text); goban->label_feedback_text = NULL; if (goban->label_text_pixbuf) { g_object_unref (goban->label_text_pixbuf); goban->label_text_pixbuf = NULL; } } for (k = 0; k < NUM_SGF_MARKUP_BACKGROUNDS; k++) { for (i = 0; i < NUM_LABEL_GHOST_LEVELS; i++) { if (goban->label_ghost_pixbufs[i][k]) { g_object_unref (goban->label_ghost_pixbufs[i][k]); goban->label_ghost_pixbufs[i][k] = NULL; } } } } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/gtk-goban-base.c0000644000175000017500000001747010371146244016574 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "gtk-configuration.h" #include "gtk-goban-base.h" #include "gtk-preferences.h" #include "gtk-tile-set.h" #include "gtk-utils.h" #include "quarry-marshal.h" #include "board.h" #include "utils.h" #include static void gtk_goban_base_class_init (GtkGobanBaseClass *class); static void gtk_goban_base_init (GtkGobanBase *goban_base); static void gtk_goban_base_realize (GtkWidget *widget); static void gtk_goban_base_unrealize (GtkWidget *widget); static void gtk_goban_base_allocate_screen_resources (GtkGobanBase *goban_base); static void gtk_goban_base_free_screen_resources (GtkGobanBase *goban_base); static void gtk_goban_base_finalize (GObject *object); static void set_background (GtkGobanBase *goban_base); static GtkWidgetClass *parent_class; static GSList *all_goban_bases; enum { ALLOCATE_SCREEN_RESOURCES, FREE_SCREEN_RESOURCES, NUM_SIGNALS }; static guint goban_base_signals[NUM_SIGNALS]; GType gtk_goban_base_get_type (void) { static GType goban_base_type = 0; if (!goban_base_type) { static GTypeInfo goban_base_info = { sizeof (GtkGobanBaseClass), NULL, NULL, (GClassInitFunc) gtk_goban_base_class_init, NULL, NULL, sizeof (GtkGobanBase), 0, (GInstanceInitFunc) gtk_goban_base_init, NULL }; goban_base_type = g_type_register_static (GTK_TYPE_WIDGET, "GtkGobanBase", &goban_base_info, G_TYPE_FLAG_ABSTRACT); } return goban_base_type; } static void gtk_goban_base_class_init (GtkGobanBaseClass *class) { GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class); parent_class = g_type_class_peek_parent (class); G_OBJECT_CLASS (class)->finalize = gtk_goban_base_finalize; widget_class->realize = gtk_goban_base_realize; widget_class->unrealize = gtk_goban_base_unrealize; class->allocate_screen_resources = gtk_goban_base_allocate_screen_resources; class->free_screen_resources = gtk_goban_base_free_screen_resources; goban_base_signals[ALLOCATE_SCREEN_RESOURCES] = g_signal_new ("allocate-screen-resources", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GtkGobanBaseClass, allocate_screen_resources), NULL, NULL, quarry_marshal_VOID__VOID, G_TYPE_NONE, 0); goban_base_signals[FREE_SCREEN_RESOURCES] = g_signal_new ("free-screen-resources", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GtkGobanBaseClass, free_screen_resources), NULL, NULL, quarry_marshal_VOID__VOID, G_TYPE_NONE, 0); } static void gtk_goban_base_init (GtkGobanBase *goban_base) { goban_base->game = GAME_DUMMY; goban_base->cell_size = 0; goban_base->font_description = pango_font_description_copy (gtk_widget_get_default_style ()->font_desc); all_goban_bases = g_slist_prepend (all_goban_bases, goban_base); } static void gtk_goban_base_realize (GtkWidget *widget) { g_return_if_fail (GTK_GOBAN_BASE (widget)->cell_size != 0); g_signal_emit (widget, goban_base_signals[ALLOCATE_SCREEN_RESOURCES], 0); } static void gtk_goban_base_unrealize (GtkWidget *widget) { g_signal_emit (widget, goban_base_signals[FREE_SCREEN_RESOURCES], 0); parent_class->unrealize (widget); } static void gtk_goban_base_allocate_screen_resources (GtkGobanBase *goban_base) { gint main_tile_size = (goban_base->cell_size - (goban_base->game == GAME_GO ? 0 : 1)); goban_base->main_tile_set = gtk_main_tile_set_create_or_reuse (main_tile_size, goban_base->game); goban_base->sgf_markup_tile_set = gtk_sgf_markup_tile_set_create_or_reuse (main_tile_size, goban_base->game); } static void gtk_goban_base_free_screen_resources (GtkGobanBase *goban_base) { object_cache_unreference_object (>k_main_tile_set_cache, goban_base->main_tile_set); object_cache_unreference_object (>k_sgf_markup_tile_set_cache, goban_base->sgf_markup_tile_set); } static void gtk_goban_base_finalize (GObject *object) { GtkGobanBase *goban_base = GTK_GOBAN_BASE (object); pango_font_description_free (goban_base->font_description); all_goban_bases = g_slist_remove (all_goban_bases, goban_base); G_OBJECT_CLASS (parent_class)->finalize (object); } void gtk_goban_base_update_appearance (Game game) { GSList *item; g_return_if_fail (game >= FIRST_GAME && GAME_IS_SUPPORTED (game)); for (item = all_goban_bases; item; item = item->next) { GtkGobanBase *goban_base = (GtkGobanBase *) (item->data); if (goban_base->game == game) { set_background (goban_base); if (GTK_WIDGET_REALIZED (GTK_WIDGET (goban_base))) { g_signal_emit (goban_base, goban_base_signals[FREE_SCREEN_RESOURCES], 0); g_signal_emit (goban_base, goban_base_signals[ALLOCATE_SCREEN_RESOURCES], 0); } } } } /* The following non-static functions are meant to be protected (in * C++ sense.) They should only be called by descendant widgets. */ void gtk_goban_base_set_game (GtkGobanBase *goban_base, Game game) { g_return_if_fail (GTK_IS_GOBAN_BASE (goban_base)); g_return_if_fail (GAME_IS_SUPPORTED (game)); if (goban_base->game != game) { goban_base->game = game; set_background (goban_base); } } void gtk_goban_base_set_cell_size (GtkGobanBase *goban_base, gint cell_size) { g_return_if_fail (GTK_IS_GOBAN_BASE (goban_base)); g_return_if_fail (cell_size > 0); if (goban_base->cell_size != cell_size) { goban_base->cell_size = cell_size; if (GTK_WIDGET_REALIZED (GTK_WIDGET (goban_base))) { g_signal_emit (goban_base, goban_base_signals[FREE_SCREEN_RESOURCES], 0); g_signal_emit (goban_base, goban_base_signals[ALLOCATE_SCREEN_RESOURCES], 0); } } } static void set_background (GtkGobanBase *goban_base) { const BoardAppearance *board_appearance = game_to_board_appearance_structure (goban_base->game); GtkRcStyle *rc_style = gtk_rc_style_new (); rc_style->color_flags[GTK_STATE_NORMAL] = GTK_RC_FG | GTK_RC_BG; gtk_utils_set_gdk_color (&rc_style->fg[GTK_STATE_NORMAL], board_appearance->grid_and_labels_color); gtk_utils_set_gdk_color (&rc_style->bg[GTK_STATE_NORMAL], board_appearance->background_color); if (board_appearance->use_background_texture) { rc_style->bg_pixmap_name[GTK_STATE_NORMAL] = g_strdup (board_appearance->background_texture); } gtk_widget_modify_style (&goban_base->widget, rc_style); g_object_unref (rc_style); } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/gtk-goban-window.c0000644000175000017500000055542310520742074017175 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003 Paul Pogonyshev. * * Copyright (C) 2004 Paul Pogonyshev and Martin Holters. * * Copyright (C) 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* FIXME: Certain parts can be simplified by switching from explicit * function calls to hooking to the new GtkSgfTreeSignalProxy * signals. * * FIXME: Current synchronization between the "Tools" menu in the main * window menu and the menu available from the editing toolbar * is hackish and ugly. Should be possible to improve when we * drop support for pre-2.4 GTK+. * * FIXME: This file should be split up, it is too large. */ #include "gtk-goban-window.h" #include "gtk-add-or-edit-label-dialog.h" #include "gtk-clock.h" #include "gtk-configuration.h" #include "gtk-control-center.h" #include "gtk-file-dialog.h" #include "gtk-game-info-dialog.h" #include "gtk-goban.h" #include "gtk-go-to-named-node-dialog.h" #include "gtk-gtp-client-interface.h" #include "gtk-help.h" #include "gtk-named-vbox.h" #include "gtk-new-game-dialog.h" #include "gtk-new-game-record-dialog.h" #include "gtk-parser-interface.h" #include "gtk-preferences.h" #include "gtk-qhbox.h" #include "gtk-qvbox.h" #include "gtk-resume-game-dialog.h" #include "gtk-sgf-tree-signal-proxy.h" #include "gtk-sgf-tree-view.h" #include "gtk-utils.h" #include "quarry-find-dialog.h" #include "quarry-marshal.h" #include "quarry-message-dialog.h" #include "quarry-move-number-dialog.h" #include "quarry-save-confirmation-dialog.h" #include "quarry-stock.h" #include "quarry-text-buffer.h" #include "gui-utils.h" #include "time-control.h" #include "gtp-client.h" #include "sgf.h" #include "board.h" #include "game-info.h" #include "utils.h" #include #include #include #include #include #define NAVIGATE_FAST_NUM_MOVES 10 #define IS_DISPLAYING_GAME_NODE(goban_window) \ ((goban_window)->game_position.board_state \ == &(goban_window)->sgf_board_state) #define USER_CAN_PLAY_MOVES(goban_window) \ (!(goban_window)->in_game_mode \ || !IS_DISPLAYING_GAME_NODE (goban_window) \ || !((goban_window) \ ->players[COLOR_INDEX ((goban_window) \ ->sgf_board_state.color_to_play)])) #define GTP_ENGINE_CAN_PLAY_MOVES(goban_window, color) \ ((goban_window)->players[COLOR_INDEX (color)] \ && ((goban_window)->player_initialization_step[COLOR_INDEX (color)] \ == INITIALIZATION_COMPLETE)) #define USER_IS_TO_PLAY(goban_window) \ (!((goban_window) \ ->players[COLOR_INDEX ((goban_window) \ ->game_position.board_state \ ->color_to_play)])) #define IS_IN_SPECIAL_MODE(goban_window) \ GTK_WIDGET_VISIBLE ((goban_window)->mode_information_vbox) enum { INITIALIZATION_NOT_STARTED, INITIALIZATION_GAME_SET, INITIALIZATION_BOARD_SIZE_SET, INITIALIZATION_BOARD_CLEARED, INITIALIZATION_TIME_LIMITS_SET, INITIALIZATION_FIXED_HANDICAP_SET, INITIALIZATION_FREE_HANDICAP_PLACED, INITIALIZATION_HANDICAP_SET, INITIALIZATION_COMPLETE }; typedef void (* SpecialModeButtonClicked) (GtkGobanWindow *goban_window); enum { GTK_GOBAN_WINDOW_SAVE = 1, GTK_GOBAN_WINDOW_SAVE_AS, GTK_GOBAN_WINDOW_ADJOURN }; enum { GTK_GOBAN_WINDOW_NON_LABELS_MODE, GTK_GOBAN_WINDOW_TEXT_LABELS_MODE, GTK_GOBAN_WINDOW_NUMERIC_LABELS_MODE }; enum { GTK_GOBAN_WINDOW_HIDE_CHILD = FALSE, GTK_GOBAN_WINDOW_SHOW_CHILD = TRUE, GTK_GOBAN_WINDOW_TOGGLE_CHILD }; typedef struct _GtkGobanWindowUndoEntryData GtkGobanWindowUndoEntryData; typedef struct _GtkGobanWindowStateData GtkGobanWindowStateData; struct _GtkGobanWindowUndoEntryData { GtkGobanWindow *goban_window; QuarryTextBufferUndoEntry *undo_entry; }; struct _GtkGobanWindowStateData { GtkGobanWindow *goban_window; QuarryTextBufferState state_before; QuarryTextBufferState state_after; const SgfNode *sgf_node_after; }; typedef struct _SgfCopyData SgfCopyData; struct _SgfCopyData { char *sgf; int sgf_length; }; static void gtk_goban_window_class_init (GtkGobanWindowClass *class); static void gtk_goban_window_init (GtkGobanWindow *goban_window); static void gtk_goban_window_destroy (GtkObject *object); static void gtk_goban_window_finalize (GObject *object); static void force_minimal_width (GtkWidget *label, GtkRequisition *requisition); static void do_enter_game_mode (GtkGobanWindow *goban_window); static void leave_game_mode (GtkGobanWindow *goban_window); static void collection_modification_state_changed (SgfCollection *sgf_collection, void *user_data); static void undo_or_redo_availability_changed (SgfUndoHistory *undo_history, void *user_data); static void gtk_goban_window_save (GtkGobanWindow *goban_window, guint callback_action); static char * suggest_filename (GtkGobanWindow *goban_window); static void save_file_as_response (GtkWidget *file_dialog, gint response_id, GtkGobanWindow *goban_window); static gboolean do_save_collection (GtkGobanWindow *goban_window, const gchar *filename); static void game_has_been_adjourned (GtkGobanWindow *goban_window); static void export_ascii_diagram (GtkGobanWindow *goban_window); static void export_senseis_library_diagram (GtkGobanWindow *goban_window); static void do_export_diagram (GtkGobanWindow *goban_window, char *diagram_string, const gchar *message); static void gtk_goban_window_close (GtkGobanWindow *goban_window); static void show_find_dialog (GtkGobanWindow *goban_window); static void find_dialog_response (QuarryFindDialog *find_dialog, gint response_id, GtkGobanWindow *goban_window); static gboolean do_find_text (GtkGobanWindow *goban_window, QuarryFindDialogSearchDirection direction); static void show_game_information_dialog (GtkGobanWindow *goban_window); static void game_info_dialog_property_changed (GtkGobanWindow *goban_window, SgfType sgf_property_type); static void show_preferences_dialog (void); static void show_or_hide_main_toolbar (GtkGobanWindow *goban_window); static void show_or_hide_editing_toolbar (GtkGobanWindow *goban_window); static void show_or_hide_navigation_toolbar (GtkGobanWindow *goban_window); static void show_or_hide_game_action_buttons (GtkGobanWindow *goban_window); static void show_or_hide_sgf_tree_view (GtkGobanWindow *goban_window, guint callback_action); static void recenter_sgf_tree_view (GtkGobanWindow *goban_window); static void show_sgf_tree_view_automatically (GtkGobanWindow *goban_window, const SgfNode *sgf_node); #ifdef GTK_TYPE_GO_TO_NAMED_NODE_DIALOG static void show_go_to_named_node_dialog (GtkGobanWindow *goban_window); #endif static void show_about_dialog (void); static void show_help_contents (void); static void tools_option_menu_changed (GtkOptionMenu *option_menu, const GtkGobanWindow *goban_window); static void synchronize_tools_menus (const GtkGobanWindow *goban_window); static void update_territory_markup (GtkGobanWindow *goban_window); static void enter_special_mode (GtkGobanWindow *goban_window, const gchar *hint, SpecialModeButtonClicked done_callback, SpecialModeButtonClicked cancel_callback); static void leave_special_mode (GtkGobanWindow *goban_window); static void engine_has_scored (GtpClient *client, int successful, GtkGobanWindow *goban_window, GtpStoneStatus status, BoardPositionList *dead_stones); static void cancel_scoring (GtkProgressDialog *progress_dialog, GtkGobanWindow *goban_window); static void enter_scoring_mode (GtkGobanWindow *goban_window); static void go_scoring_mode_done (GtkGobanWindow *goban_window); static void go_scoring_mode_cancel (GtkGobanWindow *goban_window); static void handle_go_scoring_results (GtkGobanWindow *goban_window); static void free_handicap_mode_done (GtkGobanWindow *goban_window); static void play_pass_move (GtkGobanWindow *goban_window); static void resign_game (GtkGobanWindow *goban_window); static void do_resign_game (GtkGobanWindow *goban_window); static void set_current_tree (GtkGobanWindow *goban_window, SgfGameTree *sgf_tree); static void set_time_controls (GtkGobanWindow *goban_window, TimeControl *time_control); static void reenter_current_node (GtkGobanWindow *goban_window); static void about_to_change_node (GtkGobanWindow *goban_window); static void just_changed_node (GtkGobanWindow *goban_window); static void cancel_amazons_move (GtkGobanWindow *goban_window); static void reset_amazons_move_data (GtkGobanWindow *goban_window); static void set_goban_signal_handlers (GtkGobanWindow *goban_window, GCallback pointer_moved_handler, GCallback goban_clicked_handler); static GtkGobanPointerFeedback playing_mode_pointer_moved (GtkGobanWindow *goban_window, GtkGobanPointerData *data); static void playing_mode_goban_clicked (GtkGobanWindow *goban_window, GtkGobanClickData *data); static GtkGobanPointerFeedback setup_mode_pointer_moved (GtkGobanWindow *goban_window, GtkGobanPointerData *data); static void setup_mode_goban_clicked (GtkGobanWindow *goban_window, GtkGobanClickData *data); static GtkGobanPointerFeedback markup_mode_pointer_moved (GtkGobanWindow *goban_window, GtkGobanPointerData *data); static void markup_mode_goban_clicked (GtkGobanWindow *goban_window, GtkGobanClickData *data); static GtkGobanPointerFeedback label_mode_pointer_moved (GtkGobanWindow *goban_window, GtkGobanPointerData *data); static void label_mode_goban_clicked (GtkGobanWindow *goban_window, GtkGobanClickData *data); static GtkGobanPointerFeedback free_handicap_mode_pointer_moved (GtkGobanWindow *goban_window, GtkGobanPointerData *data); static void free_handicap_mode_goban_clicked (GtkGobanWindow *goban_window, GtkGobanClickData *data); static GtkGobanPointerFeedback go_scoring_mode_pointer_moved (GtkGobanWindow *goban_window, GtkGobanPointerData *data); static void go_scoring_mode_goban_clicked (GtkGobanWindow *goban_window, GtkGobanClickData *data); static void sgf_tree_view_clicked (GtkGobanWindow *goban_window, SgfNode *sgf_node, gint button_index); static void delete_drawn_position_list (GtkGobanWindow *goban_window); static void navigate_goban (GtkGobanWindow *goban_window, GtkGobanNavigationCommand command); static void switch_to_given_node (GtkGobanWindow *goban_window, SgfNode *sgf_node); static int find_variation_to_switch_to (GtkGobanWindow *goban_window, int x, int y, SgfDirection direction); static void update_children_for_new_node (GtkGobanWindow *goban_window, gboolean forced, gboolean text_handled); static void set_comment_and_node_name (GtkGobanWindow *goban_window, const SgfNode *sgf_node); static void update_game_information (GtkGobanWindow *goban_window); static void update_window_title (GtkGobanWindow *goban_window); static void update_player_information (GtkGobanWindow *goban_window, int player_color); static void update_game_specific_information (const GtkGobanWindow *goban_window); static void update_move_information (const GtkGobanWindow *goban_window); static void update_commands_sensitivity (const GtkGobanWindow *goban_window); static void update_set_player_to_move_commands (GtkGobanWindow *goban_window); static void insert_node_name (GtkGobanWindow *goban_window, const gchar *node_name); static void select_node_name (GtkGobanWindow *goban_window); static void text_buffer_insert_text (GtkTextBuffer *text_buffer, GtkTextIter *insertion_iterator, const gchar *text, guint length, GtkGobanWindow *goban_window); static void text_buffer_after_insert_text (GtkTextBuffer *text_buffer, GtkTextIter *insertion_iterator, const gchar *text, guint length, GtkGobanWindow *goban_window); static void text_buffer_mark_set (GtkTextBuffer *text_buffer, GtkTextIter *new_position_iterator, GtkTextMark *mark, GtkGobanWindow *goban_window); static void text_buffer_end_user_action (GtkTextBuffer *text_buffer, GtkGobanWindow *goban_window); static gboolean text_buffer_receive_undo_entry (QuarryTextBuffer *text_buffer, QuarryTextBufferUndoEntry *undo_entry, GtkGobanWindow *goban_window); static void text_buffer_undo (GtkGobanWindowUndoEntryData *undo_entry_data); static void text_buffer_redo (GtkGobanWindowUndoEntryData *undo_entry_data); static void text_buffer_set_state_undo (GtkGobanWindowStateData *state_data); static void text_buffer_set_state_redo (GtkGobanWindowStateData *state_data); static QuarryTextBufferState * update_comment_and_node_name_if_needed (GtkGobanWindow *goban_window, gboolean for_current_node); static gboolean fetch_comment_and_node_name (GtkGobanWindow *goban_window, gboolean for_current_node); static void set_move_number (GtkGobanWindow *goban_window); static void set_player_to_move (GtkGobanWindow *goban_window, guint callback_action, GtkCheckMenuItem *menu_item); static int initialize_gtp_player (GtpClient *client, int successful, GtkGobanWindow *goban_window, ...); static void free_handicap_has_been_placed (GtkGobanWindow *goban_window, BoardPositionList *handicap_stones); static void move_has_been_played (GtkGobanWindow *goban_window); static void move_has_been_generated (GtpClient *client, int successful, GtkGobanWindow *goban_window, int color, int x, int y, BoardAbstractMoveData *move_data); static void generate_move_via_gtp (GtkGobanWindow *goban_window); static void start_clock_if_needed (GtkGobanWindow *goban_window); static void player_is_out_of_time (GtkClock *clock, GtkGobanWindow *goban_window); static void undo_operation (GtkGobanWindow *goban_window); static void redo_operation (GtkGobanWindow *goban_window); static void cut_operation (GtkGobanWindow *goban_window); static void copy_operation (GtkGobanWindow *goban_window); static void paste_operation (GtkGobanWindow *goban_window); static void get_copied_sgf (GtkClipboard *clipboard, GtkSelectionData *selection_data, guint format, gpointer user_data); static void delete_copied_sgf (GtkClipboard *clipboard, gpointer user_data); static void receive_copied_sgf (GtkClipboard *clipboard, GtkSelectionData *selection_data, gpointer user_data); static void append_empty_variation (GtkGobanWindow *goban_window); static void swap_adjacent_branches (GtkGobanWindow *goban_window, guint use_previous_branch); static void delete_current_node (GtkGobanWindow *goban_window); static void delete_current_node_children (GtkGobanWindow *goban_window); static void activate_move_tool (GtkGobanWindow *goban_window, guint callback_action, GtkCheckMenuItem *menu_item); static void activate_setup_tool (GtkGobanWindow *goban_window, guint callback_action, GtkCheckMenuItem *menu_item); static void activate_scoring_tool (GtkGobanWindow *goban_window, guint callback_action, GtkCheckMenuItem *menu_item); static void activate_markup_tool (GtkGobanWindow *goban_window, gint sgf_markup_type, GtkCheckMenuItem *menu_item); static void activate_label_tool (GtkGobanWindow *goban_window, gint labels_mode, GtkCheckMenuItem *menu_item); static GtkUtilsToolbarEntry toolbar_open = { N_("Open"), N_("Open a game record"), GTK_STOCK_OPEN, (GtkUtilsToolbarEntryCallback) gtk_parser_interface_present_default, 0 }; static GtkUtilsToolbarEntry toolbar_save = { N_("Save"), N_("Save the current file"), GTK_STOCK_SAVE, (GtkUtilsToolbarEntryCallback) gtk_goban_window_save, GTK_GOBAN_WINDOW_SAVE }; static GtkUtilsToolbarEntry toolbar_find = { N_("Find"), N_("Search for a string in comments"), GTK_STOCK_FIND, (GtkUtilsToolbarEntryCallback) show_find_dialog, 0 }; static GtkUtilsToolbarEntry toolbar_game_information = { N_("Info"), N_("View and edit game information"), GTK_STOCK_PROPERTIES, (GtkUtilsToolbarEntryCallback) show_game_information_dialog, 0 }; static GtkUtilsToolbarEntry editing_toolbar_undo = { N_("Undo"), N_("Undo the last action"), GTK_STOCK_UNDO, (GtkUtilsToolbarEntryCallback) undo_operation, 0 }; static GtkUtilsToolbarEntry editing_toolbar_redo = { N_("Redo"), N_("Redo the last undone action"), GTK_STOCK_REDO, (GtkUtilsToolbarEntryCallback) redo_operation, 0 }; static GtkUtilsToolbarEntry editing_toolbar_delete = { N_("Delete"), N_("Delete the current node"), GTK_STOCK_DELETE, (GtkUtilsToolbarEntryCallback) delete_current_node, 0 }; static GtkUtilsToolbarEntry navigation_toolbar_root = { N_("Root"), N_("Go to the root node"), GTK_STOCK_GOTO_FIRST, (GtkUtilsToolbarEntryCallback) navigate_goban, GOBAN_NAVIGATE_ROOT }; static GtkUtilsToolbarEntry navigation_toolbar_back = { N_("Back"), N_("Go to the previous node"), GTK_STOCK_GO_BACK, (GtkUtilsToolbarEntryCallback) navigate_goban, GOBAN_NAVIGATE_BACK }; static GtkUtilsToolbarEntry navigation_toolbar_forward = { N_("Forward"), N_("Go to the next node"), GTK_STOCK_GO_FORWARD, (GtkUtilsToolbarEntryCallback) navigate_goban, GOBAN_NAVIGATE_FORWARD }; static GtkUtilsToolbarEntry navigation_toolbar_variation_end = { N_("End"), N_("Go to the current variation's last node"), GTK_STOCK_GOTO_LAST, (GtkUtilsToolbarEntryCallback) navigate_goban, GOBAN_NAVIGATE_VARIATION_END }; static GtkUtilsToolbarEntry navigation_toolbar_previous_variation = { N_("Previous"), N_("Switch to the previous variation"), GTK_STOCK_GO_UP, (GtkUtilsToolbarEntryCallback) navigate_goban, GOBAN_NAVIGATE_PREVIOUS_VARIATION }; static GtkUtilsToolbarEntry navigation_toolbar_next_variation = { N_("Next"), N_("Switch to the next variation"), GTK_STOCK_GO_DOWN, (GtkUtilsToolbarEntryCallback) navigate_goban, GOBAN_NAVIGATE_NEXT_VARIATION }; static GtkWindowClass *parent_class; static guint clicked_signal_id; static guint pointer_moved_signal_id; static guint click_canceled_signal_id; static guint goban_clicked_signal_id; static GtkWindow *about_dialog = NULL; static GtkTextTag *node_name_tag; static GtkTextTag *separator_tag; static GtkTextTagTable *node_name_tag_table; static const SgfCustomUndoHistoryEntryData quarry_text_buffer_undo_entry_data = { (SgfCustomOperationEntryFunction) text_buffer_undo, (SgfCustomOperationEntryFunction) text_buffer_redo, (SgfCustomOperationEntryFunction) g_free }; static const SgfCustomUndoHistoryEntryData quarry_text_buffer_state_data = { (SgfCustomOperationEntryFunction) text_buffer_set_state_undo, (SgfCustomOperationEntryFunction) text_buffer_set_state_redo, (SgfCustomOperationEntryFunction) g_free }; GType gtk_goban_window_get_type (void) { static GType goban_window_type = 0; if (!goban_window_type) { static GTypeInfo goban_window_info = { sizeof (GtkGobanWindowClass), NULL, NULL, (GClassInitFunc) gtk_goban_window_class_init, NULL, NULL, sizeof (GtkGobanWindow), 1, (GInstanceInitFunc) gtk_goban_window_init, NULL }; goban_window_type = g_type_register_static (GTK_TYPE_WINDOW, "GtkGobanWindow", &goban_window_info, 0); } return goban_window_type; } static void gtk_goban_window_class_init (GtkGobanWindowClass *class) { parent_class = g_type_class_peek_parent (class); G_OBJECT_CLASS (class)->finalize = gtk_goban_window_finalize; GTK_OBJECT_CLASS (class)->destroy = gtk_goban_window_destroy; GTK_WIDGET_CLASS (class)->delete_event = ((gboolean (*) (GtkWidget *, GdkEventAny *)) gtk_goban_window_stops_closing); /* Create the text tags and tag table we will be using in all * windows. The tags will be used to highlight node name. */ node_name_tag = gtk_text_tag_new (NULL); g_object_set (node_name_tag, "justification", GTK_JUSTIFY_CENTER, "pixels-below-lines", QUARRY_SPACING, "underline", TRUE, "weight", PANGO_WEIGHT_BOLD, NULL); separator_tag = gtk_text_tag_new (NULL); g_object_set (separator_tag, "editable", FALSE, NULL); node_name_tag_table = gtk_text_tag_table_new (); gui_back_end_register_object_to_finalize (node_name_tag_table); gtk_text_tag_table_add (node_name_tag_table, node_name_tag); g_object_unref (node_name_tag); gtk_text_tag_table_add (node_name_tag_table, separator_tag); g_object_unref (separator_tag); } static void gtk_goban_window_init (GtkGobanWindow *goban_window) { static GtkItemFactoryEntry menu_entries[] = { { N_("/_File"), NULL, NULL, 0, "" }, { N_("/File/_New Game..."), "N", gtk_new_game_dialog_present, 0, "", GTK_STOCK_NEW }, { N_("/File/Ne_w Game Record..."), "N", gtk_new_game_record_dialog_present, 0, "" }, { N_("/File/"), NULL, NULL, 0, "" }, { N_("/File/_Open..."), "O", gtk_parser_interface_present_default, 0, "", GTK_STOCK_OPEN }, { N_("/File/_Resume Game..."), "", gtk_resume_game, 0, "" }, { N_("/File/_Export..."), NULL, NULL, 0, "" }, { N_("/File/Export.../_ASCII Diagram"), NULL, export_ascii_diagram, 0, "" }, { N_("/File/Export.../_Sensei's Library Diagram"), NULL, export_senseis_library_diagram, 0, "" }, { N_("/File/"), NULL, NULL, 0, "" }, { N_("/File/_Save"), "S", gtk_goban_window_save, GTK_GOBAN_WINDOW_SAVE, "", GTK_STOCK_SAVE }, { N_("/File/Save _As..."), "S", gtk_goban_window_save, GTK_GOBAN_WINDOW_SAVE_AS, "", GTK_STOCK_SAVE_AS }, { N_("/File/"), NULL, NULL, 0, "" }, { N_("/File/_Close"), "W", gtk_goban_window_close, 0, "", GTK_STOCK_CLOSE }, { N_("/File/_Quit"), "Q", gtk_control_center_quit, 0, "", GTK_STOCK_QUIT }, { N_("/_Edit"), NULL, NULL, 0, "" }, { N_("/Edit/_Undo"), "Z", undo_operation, 0, "", GTK_STOCK_UNDO }, { N_("/Edit/_Redo"), "Z", redo_operation, 0, "", GTK_STOCK_REDO }, { N_("/Edit/"), NULL, NULL, 0, "" }, { N_("/Edit/Cu_t"), "", cut_operation, 0, "", GTK_STOCK_CUT }, { N_("/Edit/_Copy"), "", copy_operation, 0, "", GTK_STOCK_COPY }, { N_("/Edit/_Paste"), "", paste_operation, 0, "", GTK_STOCK_PASTE }, { N_("/Edit/_Delete Node"), "Delete", delete_current_node, 0, "", GTK_STOCK_DELETE }, { N_("/Edit/Delete Node's C_hildren"), "Delete", delete_current_node_children, 0, "" }, { N_("/Edit/"), NULL, NULL, 0, "" }, { N_("/Edit/T_ools"), NULL, NULL, 0, "" }, { N_("/Edit/Tools/_Move Tool"), "M", activate_move_tool, 0, "" }, { N_("/Edit/Tools/_Setup Tool"), "S", activate_setup_tool, 0, "/Edit/Tools/Move Tool" }, { N_("/Edit/Tools/"), NULL, NULL, 0, "" }, { N_("/Edit/Tools/C_ross Markup"), "1", activate_markup_tool, SGF_MARKUP_CROSS, "/Edit/Tools/Setup Tool" }, { N_("/Edit/Tools/_Circle Markup"), "2", activate_markup_tool, SGF_MARKUP_CIRCLE, "/Edit/Tools/Cross Markup" }, { N_("/Edit/Tools/S_quare Markup"), "3", activate_markup_tool, SGF_MARKUP_SQUARE, "/Edit/Tools/Circle Markup" }, { N_("/Edit/Tools/_Triangle Markup"), "4", activate_markup_tool, SGF_MARKUP_TRIANGLE, "/Edit/Tools/Square Markup" }, { N_("/Edit/Tools/S_elected Markup"), "5", activate_markup_tool, SGF_MARKUP_SELECTED, "/Edit/Tools/Triangle Markup" }, { N_("/Edit/Tools/"), NULL, NULL, 0, "" }, { N_("/Edit/Tools/_Label Tool"), "6", activate_label_tool, GTK_GOBAN_WINDOW_TEXT_LABELS_MODE, "/Edit/Tools/Selected Markup" }, { N_("/Edit/Tools/_Number Tool"), "7", activate_label_tool, GTK_GOBAN_WINDOW_NUMERIC_LABELS_MODE, "/Edit/Tools/Label Tool" }, { N_("/Edit/Tools/"), NULL, NULL, 0, "" }, { N_("/Edit/Tools/Scori_ng Tool"), NULL, activate_scoring_tool, 0, "/Edit/Tools/Number Tool" }, { N_("/Edit/_Add Empty Node"), NULL, append_empty_variation, 0, "" }, { N_("/Edit/"), NULL, NULL, 0, "" }, { N_("/Edit/Move _Branch Up"), NULL, swap_adjacent_branches, TRUE, "" }, { N_("/Edit/Move Branch Do_wn"), NULL, swap_adjacent_branches, FALSE, "" }, { N_("/Edit/"), NULL, NULL, 0, "" }, { N_("/Edit/Edit Node _Name"), "N", select_node_name, 0, "" }, { N_("/Edit/Set _Move Number"), NULL, set_move_number, 0, "" }, { N_("/Edit/P_layer to Move"), NULL, NULL, 0, "" }, { N_("/Edit/Player to Move/_White"), NULL, set_player_to_move, WHITE, "" }, { N_("/Edit/Player to Move/_Black"), NULL, set_player_to_move, BLACK, "/Edit/Player to Move/White" }, { N_("/Edit/Player to Move/By Game _Rules"), NULL, set_player_to_move, EMPTY, "/Edit/Player to Move/Black" }, { N_("/Edit/"), NULL, NULL, 0, "" }, { N_("/Edit/_Find"), "F", show_find_dialog, 0, "", GTK_STOCK_FIND }, { N_("/Edit/Find Ne_xt"), "G", (GtkItemFactoryCallback) do_find_text, QUARRY_FIND_DIALOG_FIND_NEXT, "" }, { N_("/Edit/Find Pre_vious"), "G", (GtkItemFactoryCallback) do_find_text, QUARRY_FIND_DIALOG_FIND_PREVIOUS, "" }, { N_("/Edit/"), NULL, NULL, 0, "" }, { N_("/Edit/Game _Information"), "Return", show_game_information_dialog, 0, "", GTK_STOCK_PROPERTIES }, { N_("/Edit/"), NULL, NULL, 0, "" }, { N_("/Edit/Pr_eferences"), "", show_preferences_dialog, 0, "", GTK_STOCK_PREFERENCES }, { N_("/_View"), NULL, NULL, 0, "" }, { N_("/View/_Main Toolbar"), NULL, show_or_hide_main_toolbar, 0, "" }, { N_("/View/_Editing Toolbar"), NULL, show_or_hide_editing_toolbar, 0, "" }, { N_("/View/_Navigation Toolbar"), NULL, show_or_hide_navigation_toolbar, 0, "" }, { N_("/View/"), NULL, NULL, 0, "" }, { N_("/View/_Game Action Buttons"), NULL, show_or_hide_game_action_buttons, 0, "" }, { N_("/View/"), NULL, NULL, 0, "" }, { N_("/View/Game _Tree"), NULL, show_or_hide_sgf_tree_view, GTK_GOBAN_WINDOW_TOGGLE_CHILD, "" }, { N_("/View/_Recenter on Current Node"), "C", recenter_sgf_tree_view, 0, "" }, { N_("/View/"), NULL, NULL, 0, "" }, { N_("/View/_Control Center"), NULL, gtk_control_center_present, 0, "" }, { N_("/_Play"), NULL, NULL, 0, "" }, { N_("/Play/_Pass"), NULL, play_pass_move, 0, "" }, { N_("/Play/"), NULL, NULL, 0, "" }, { N_("/Play/_Resign"), NULL, resign_game, 0, "" }, { N_("/Play/"), NULL, NULL, 0, "" }, { N_("/Play/_Adjourn Game"), "", gtk_goban_window_save, GTK_GOBAN_WINDOW_ADJOURN, "", GTK_STOCK_SAVE }, { N_("/_Go"), NULL, NULL, 0, "" }, { N_("/Go/_Previous Node"), "Left", navigate_goban, GOBAN_NAVIGATE_BACK, "", GTK_STOCK_GO_BACK }, { N_("/Go/_Next Node"), "Right", navigate_goban, GOBAN_NAVIGATE_FORWARD, "", GTK_STOCK_GO_FORWARD }, { N_("/Go/Ten Nodes _Backward"), "Page_Up", navigate_goban, GOBAN_NAVIGATE_BACK_FAST, "" }, { N_("/Go/Ten Nodes _Forward"), "Page_Down", navigate_goban, GOBAN_NAVIGATE_FORWARD_FAST, "" }, { N_("/Go/"), NULL, NULL, 0, "" }, { N_("/Go/_Root Node"), "Home", navigate_goban, GOBAN_NAVIGATE_ROOT, "", GTK_STOCK_GOTO_FIRST }, { N_("/Go/Variation _Last Node"), "End", navigate_goban, GOBAN_NAVIGATE_VARIATION_END, "", GTK_STOCK_GOTO_LAST }, { N_("/Go/"), NULL, NULL, 0, "" }, { N_("/Go/Pre_vious Variation"), "Up", navigate_goban, GOBAN_NAVIGATE_PREVIOUS_VARIATION, "", GTK_STOCK_GO_UP }, { N_("/Go/Ne_xt Variation"), "Down", navigate_goban, GOBAN_NAVIGATE_NEXT_VARIATION, "", GTK_STOCK_GO_DOWN }, #ifdef GTK_TYPE_GO_TO_NAMED_NODE_DIALOG { N_("/Go/"), NULL, NULL, 0, "" }, { N_("/Go/_Go to Named Node..."), "", show_go_to_named_node_dialog, 0, "", GTK_STOCK_JUMP_TO }, #endif { N_("/_Help"), NULL, NULL, 0, "" }, { N_("/Help/_Contents"), "F1", show_help_contents, 0, "", GTK_STOCK_HELP }, { N_("/Help/_About"), NULL, show_about_dialog, 0, QUARRY_STOCK_MENU_ITEM_ABOUT } }; static GtkItemFactoryEntry tools_menu_entries[] = { { N_("/Move Tool"), "M", NULL, 0, "" }, { N_("/Setup Tool"), "S", NULL, 0, "" }, { "/", NULL, NULL, 0, "" }, { N_("/Cross Markup"), "1", NULL, 0, "" }, { N_("/Circle Markup"), "2", NULL, 0, "" }, { N_("/Square Markup"), "3", NULL, 0, "" }, { N_("/Triangle Markup"), "4", NULL, 0, "" }, { N_("/Selected Markup"), "5", NULL, 0, "" }, { "/", NULL, NULL, 0, "" }, { N_("/Label Tool"), "6", NULL, 0, "" }, { N_("/Number Tool"), "7", NULL, 0, "" }, { "/", NULL, NULL, 0, "" }, { N_("/Scoring Tool"), NULL, NULL, 0, "" }, }; GtkWidget *goban; GtkWidget *frame; GtkWidget *table; GtkWidget *move_information_label; GtkWidget *mode_hint_label; GtkWidget *game_action_buttons_hbox; GtkWidget *hbox; GtkWidget *text_view; GtkWidget *scrolled_window; GtkWidget *vpaned; GtkWidget *sgf_tree_view; GtkWidget *vbox; GtkWidget *qhbox; GtkWidget *menu_bar; GtkWidget *main_toolbar; GtkWidget *main_handle_box; GtkWidget *editing_toolbar; GtkWidget *editing_handle_box; GtkWidget *tools_option_menu; GtkWidget *navigation_toolbar; GtkWidget *navigation_handle_box; GtkAccelGroup *accel_group; int k; gtk_control_center_window_created (GTK_WINDOW (goban_window)); /* Goban, the main thing in the window. Signal handlers are * connected later. */ goban = gtk_goban_new (); goban_window->goban = GTK_GOBAN (goban); /* Frame to make goban look sunken. */ frame = gtk_utils_sink_widget (goban); /* Table that holds players' information and clocks. */ table = gtk_table_new (2, 2, FALSE); gtk_table_set_row_spacings (GTK_TABLE (table), QUARRY_SPACING_SMALL); gtk_table_set_col_spacings (GTK_TABLE (table), QUARRY_SPACING_BIG); /* Information labels and clocks for each player. */ for (k = 0; k < NUM_COLORS; k++) { GtkWidget *player_label; GtkWidget *game_specific_info; GtkWidget *clock; GtkWidget *named_vbox; player_label = gtk_label_new (NULL); gtk_misc_set_alignment (GTK_MISC (player_label), 0.0, 0.5); goban_window->player_labels[k] = GTK_LABEL (player_label); game_specific_info = gtk_label_new (NULL); gtk_misc_set_alignment (GTK_MISC (game_specific_info), 0.0, 0.5); goban_window->game_specific_info[k] = GTK_LABEL (game_specific_info); named_vbox = gtk_utils_pack_in_box (GTK_TYPE_NAMED_VBOX, QUARRY_SPACING_VERY_SMALL, player_label, GTK_UTILS_FILL, game_specific_info, GTK_UTILS_FILL, NULL); gtk_named_vbox_set_label_text (GTK_NAMED_VBOX (named_vbox), (k == BLACK_INDEX ? _("Black") : _("White"))); gtk_table_attach (GTK_TABLE (table), named_vbox, 0, 1, OTHER_INDEX (k), OTHER_INDEX (k) + 1, GTK_FILL, 0, 0, 0); clock = gtk_clock_new (); gtk_table_attach (GTK_TABLE (table), gtk_utils_sink_widget (clock), 1, 2, OTHER_INDEX (k), OTHER_INDEX (k) + 1, GTK_FILL, 0, 0, 0); goban_window->clocks[k] = GTK_CLOCK (clock); } /* Pack the table together with a separator (which separates the * table and move information below.) */ vbox = gtk_utils_pack_in_box (GTK_TYPE_VBOX, QUARRY_SPACING_SMALL, gtk_utils_align_widget (table, 0.5, 0.5), GTK_UTILS_FILL, gtk_hseparator_new (), GTK_UTILS_FILL, NULL); /* Move information label. */ move_information_label = gtk_label_new (NULL); goban_window->move_information_label = GTK_LABEL (move_information_label); gtk_label_set_justify (goban_window->move_information_label, GTK_JUSTIFY_CENTER); /* Game action buttons: "Pass" and "Resign". */ goban_window->pass_button = gtk_button_new_with_label (_("Pass")); GTK_WIDGET_UNSET_FLAGS (goban_window->pass_button, GTK_CAN_FOCUS); g_signal_connect_swapped (goban_window->pass_button, "clicked", G_CALLBACK (play_pass_move), goban_window); goban_window->resign_button = gtk_button_new_with_label (_("Resign")); GTK_WIDGET_UNSET_FLAGS (goban_window->resign_button, GTK_CAN_FOCUS); g_signal_connect_swapped (goban_window->resign_button, "clicked", G_CALLBACK (resign_game), goban_window); game_action_buttons_hbox = gtk_utils_pack_in_box (GTK_TYPE_HBUTTON_BOX, QUARRY_SPACING_SMALL, goban_window->pass_button, 0, goban_window->resign_button, 0, NULL); gtk_container_set_border_width (GTK_CONTAINER (game_action_buttons_hbox), QUARRY_SPACING_SMALL); /* A label with hints about special window modes. */ mode_hint_label = gtk_label_new (NULL); gtk_label_set_line_wrap (GTK_LABEL (mode_hint_label), TRUE); gtk_label_set_justify (GTK_LABEL (mode_hint_label), GTK_JUSTIFY_CENTER); goban_window->mode_hint_label = GTK_LABEL (mode_hint_label); /* Buttons for ending special window modes. */ goban_window->done_button = gtk_button_new_from_stock (QUARRY_STOCK_DONE); goban_window->cancel_button = gtk_button_new_from_stock (GTK_STOCK_CANCEL); hbox = gtk_utils_pack_in_box (GTK_TYPE_HBUTTON_BOX, QUARRY_SPACING_SMALL, goban_window->done_button, 0, goban_window->cancel_button, 0, NULL); gtk_container_set_border_width (GTK_CONTAINER (hbox), QUARRY_SPACING_SMALL); /* Pack all mode information widgets together with a separator. */ goban_window->mode_information_vbox = gtk_utils_pack_in_box (GTK_TYPE_VBOX, QUARRY_SPACING_SMALL, gtk_hseparator_new (), GTK_UTILS_FILL, mode_hint_label, GTK_UTILS_FILL, gtk_utils_align_widget (hbox, 0.5, 0.5), GTK_UTILS_FILL, NULL); /* Multipurpose text view and its text buffer. */ goban_window->text_buffer = quarry_text_buffer_new (node_name_tag_table); g_signal_connect (goban_window->text_buffer, "insert-text", G_CALLBACK (text_buffer_insert_text), goban_window); g_signal_connect_after (goban_window->text_buffer, "insert-text", G_CALLBACK (text_buffer_after_insert_text), goban_window); g_signal_connect (goban_window->text_buffer, "mark-set", G_CALLBACK (text_buffer_mark_set), goban_window); g_signal_connect (goban_window->text_buffer, "end-user-action", G_CALLBACK (text_buffer_end_user_action), goban_window); g_signal_connect (goban_window->text_buffer, "receive-undo-entry", G_CALLBACK (text_buffer_receive_undo_entry), goban_window); text_view = gtk_text_view_new_with_buffer (goban_window->text_buffer); goban_window->text_view = GTK_TEXT_VIEW (text_view); gtk_text_view_set_left_margin (goban_window->text_view, QUARRY_SPACING_VERY_SMALL); gtk_text_view_set_right_margin (goban_window->text_view, QUARRY_SPACING_VERY_SMALL); gtk_text_view_set_wrap_mode (goban_window->text_view, GTK_WRAP_WORD); /* Scrolled window to keep text view in it. */ scrolled_window = gtk_utils_make_widget_scrollable (text_view, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); /* Paned control for text view and SGF tree view. */ vpaned = gtk_vpaned_new (); goban_window->vpaned = GTK_PANED (vpaned); gtk_paned_pack1 (goban_window->vpaned, scrolled_window, TRUE, FALSE); /* SGF tree view. */ sgf_tree_view = gtk_sgf_tree_view_new (); goban_window->sgf_tree_view = GTK_SGF_TREE_VIEW (sgf_tree_view); goban_window->sgf_tree_view_visibility_locked = FALSE; g_signal_connect_swapped (sgf_tree_view, "sgf-tree-view-clicked", G_CALLBACK (sgf_tree_view_clicked), goban_window); /* Make it scrollable. Note that we don't pack it in the `vpaned' * widget now, this is done only by show_or_hide_sgf_tree_view(). * Unlike most other containers, GtkPaned doesn't like hidden * children, so to show/hide `sgf_tree_view' we need to add/remove * it to the `vpaned'. */ scrolled_window = gtk_utils_make_widget_scrollable (sgf_tree_view, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); g_object_ref (scrolled_window); gtk_object_sink (GTK_OBJECT (scrolled_window)); /* Sidebar vertical box. */ vbox = gtk_utils_pack_in_box (GTK_TYPE_VBOX, 0, vbox, GTK_UTILS_FILL, move_information_label, GTK_UTILS_FILL | QUARRY_SPACING_SMALL, (gtk_utils_align_widget (game_action_buttons_hbox, 0.5, 0.5)), GTK_UTILS_FILL, goban_window->mode_information_vbox, GTK_UTILS_FILL, vpaned, GTK_UTILS_PACK_DEFAULT, NULL); g_signal_connect (vbox, "size-request", G_CALLBACK (force_minimal_width), NULL); /* Horizontal box containing goban and sidebar. */ qhbox = gtk_utils_pack_in_box (GTK_TYPE_QHBOX, QUARRY_SPACING_GOBAN_WINDOW, frame, GTK_UTILS_FILL, vbox, GTK_UTILS_PACK_DEFAULT, NULL); gtk_container_set_border_width (GTK_CONTAINER (qhbox), QUARRY_SPACING_GOBAN_WINDOW); gtk_qbox_set_ruling_widget (GTK_QBOX (qhbox), frame, gtk_goban_negotiate_height); /* Window menu bar and associated accelerator group. */ accel_group = gtk_accel_group_new (); goban_window->item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "", accel_group); #if ENABLE_NLS gtk_item_factory_set_translate_func (goban_window->item_factory, (GtkTranslateFunc) gettext, NULL, NULL); #endif gtk_item_factory_create_items (goban_window->item_factory, (sizeof menu_entries / sizeof (GtkItemFactoryEntry)), menu_entries, goban_window); menu_bar = gtk_item_factory_get_widget (goban_window->item_factory, ""); gtk_window_add_accel_group (GTK_WINDOW (goban_window), accel_group); /* Tools menu, used with the editing toolbar below. */ goban_window->tools_item_factory = gtk_item_factory_new (GTK_TYPE_MENU, "", NULL); #if ENABLE_NLS gtk_item_factory_set_translate_func (goban_window->tools_item_factory, (GtkTranslateFunc) gettext, NULL, NULL); #endif gtk_item_factory_create_items (goban_window->tools_item_factory, (sizeof tools_menu_entries / sizeof (GtkItemFactoryEntry)), tools_menu_entries, NULL); /* Main toolbar and a handle box for it. */ main_toolbar = gtk_toolbar_new (); goban_window->main_toolbar = GTK_TOOLBAR (main_toolbar); gtk_preferences_register_main_toolbar (goban_window->main_toolbar); /* Else the toolbar collapses to the arrow alone on GTK+ 2.4+. */ gtk_toolbar_set_show_arrow (goban_window->main_toolbar, FALSE); gtk_utils_append_toolbar_button (goban_window->main_toolbar, &toolbar_open, GTK_UTILS_IS_IMPORTANT, goban_window); gtk_utils_append_toolbar_button (goban_window->main_toolbar, &toolbar_save, 0, goban_window); gtk_utils_append_toolbar_space (goban_window->main_toolbar); gtk_utils_append_toolbar_button (goban_window->main_toolbar, &toolbar_find, 0, goban_window); gtk_utils_append_toolbar_space (goban_window->main_toolbar); gtk_utils_append_toolbar_button (goban_window->main_toolbar, &toolbar_game_information, 0, goban_window); main_handle_box = gtk_handle_box_new (); gtk_container_add (GTK_CONTAINER (main_handle_box), main_toolbar); /* Editing toolbar and a handle box for it. */ editing_toolbar = gtk_toolbar_new (); goban_window->editing_toolbar = GTK_TOOLBAR (editing_toolbar); gtk_preferences_register_editing_toolbar (goban_window->editing_toolbar); /* Else the toolbar collapses to the arrow alone on GTK+ 2.4+. */ gtk_toolbar_set_show_arrow (goban_window->editing_toolbar, FALSE); gtk_utils_append_toolbar_button (goban_window->editing_toolbar, &editing_toolbar_undo, GTK_UTILS_IS_IMPORTANT, goban_window); gtk_utils_append_toolbar_button (goban_window->editing_toolbar, &editing_toolbar_redo, 0, goban_window); gtk_utils_append_toolbar_space (goban_window->editing_toolbar); gtk_utils_append_toolbar_button (goban_window->editing_toolbar, &editing_toolbar_delete, GTK_UTILS_IS_IMPORTANT, goban_window); gtk_utils_append_toolbar_space (goban_window->editing_toolbar); tools_option_menu = gtk_option_menu_new (); goban_window->tools_option_menu = GTK_OPTION_MENU (tools_option_menu); gtk_option_menu_set_menu (goban_window->tools_option_menu, (gtk_item_factory_get_widget (goban_window->tools_item_factory, ""))); g_signal_connect (tools_option_menu, "changed", G_CALLBACK (tools_option_menu_changed), goban_window); #if GTK_2_4_OR_LATER { GtkToolItem *tool_item = gtk_tool_item_new (); gtk_container_add (GTK_CONTAINER (tool_item), gtk_utils_align_widget (tools_option_menu, 0.5, 0.5)); gtk_toolbar_insert (goban_window->editing_toolbar, tool_item, -1); } #else /* not GTK_2_4_OR_LATER */ gtk_toolbar_append_widget (goban_window->editing_toolbar, tools_option_menu, NULL, NULL); #endif /* not GTK_2_4_OR_LATER */ editing_handle_box = gtk_handle_box_new (); gtk_container_add (GTK_CONTAINER (editing_handle_box), editing_toolbar); /* Navigation toolbar and a handle box for it. */ navigation_toolbar = gtk_toolbar_new (); goban_window->navigation_toolbar = GTK_TOOLBAR (navigation_toolbar); gtk_preferences_register_navigation_toolbar (goban_window->navigation_toolbar); gtk_toolbar_set_show_arrow (goban_window->navigation_toolbar, TRUE); gtk_utils_append_toolbar_button (goban_window->navigation_toolbar, &navigation_toolbar_root, GTK_UTILS_IS_IMPORTANT, goban_window); gtk_utils_append_toolbar_button (goban_window->navigation_toolbar, &navigation_toolbar_back, 0, goban_window); gtk_utils_append_toolbar_space (goban_window->navigation_toolbar); gtk_utils_append_toolbar_button (goban_window->navigation_toolbar, &navigation_toolbar_forward, GTK_UTILS_IS_IMPORTANT, goban_window); gtk_utils_append_toolbar_button (goban_window->navigation_toolbar, &navigation_toolbar_variation_end, 0, goban_window); gtk_utils_append_toolbar_space (goban_window->navigation_toolbar); gtk_utils_append_toolbar_button (goban_window->navigation_toolbar, &navigation_toolbar_previous_variation, 0, goban_window); gtk_utils_append_toolbar_button (goban_window->navigation_toolbar, &navigation_toolbar_next_variation, 0, goban_window); navigation_handle_box = gtk_handle_box_new (); gtk_container_add (GTK_CONTAINER (navigation_handle_box), navigation_toolbar); /* Horizontal box with the toolbars. */ hbox = gtk_utils_pack_in_box (GTK_TYPE_HBOX, 0, main_handle_box, GTK_UTILS_FILL, editing_handle_box, GTK_UTILS_FILL, navigation_handle_box, GTK_UTILS_PACK_DEFAULT, NULL); /* Vertical box with menu bar, toolbars and actual window * contents. */ vbox = gtk_utils_pack_in_box (GTK_TYPE_VBOX, 0, menu_bar, GTK_UTILS_FILL, hbox, GTK_UTILS_FILL, qhbox, GTK_UTILS_PACK_DEFAULT, NULL); gtk_container_add (GTK_CONTAINER (goban_window), vbox); /* Starting with GTK+ 2.4 toolbars can grab focus, so we need to * explicitly transfer it to `goban'. */ gtk_widget_grab_focus (goban); /* Show everything but the window itself. Show toolbars' handle * boxes and game action buttons' box dependent on configuration. */ gtk_widget_show_all (vbox); gtk_widget_hide (main_handle_box); if (gtk_ui_configuration.show_main_toolbar) show_or_hide_main_toolbar (goban_window); gtk_widget_hide (editing_handle_box); if (gtk_ui_configuration.show_editing_toolbar) show_or_hide_editing_toolbar (goban_window); gtk_widget_hide (navigation_handle_box); if (gtk_ui_configuration.show_navigation_toolbar) show_or_hide_navigation_toolbar (goban_window); gtk_widget_hide (game_action_buttons_hbox); if (gtk_ui_configuration.show_game_action_buttons) show_or_hide_game_action_buttons (goban_window); if (game_tree_view.show_game_tree == SHOW_GAME_TREE_ALWAYS) show_or_hide_sgf_tree_view (goban_window, GTK_GOBAN_WINDOW_SHOW_CHILD); else { gtk_utils_set_menu_items_sensitive (goban_window->item_factory, FALSE, "/View/Recenter on Current Node", NULL); } /* Look up here when the classes are certainly loaded. */ clicked_signal_id = g_signal_lookup ("clicked", GTK_TYPE_BUTTON); pointer_moved_signal_id = g_signal_lookup ("pointer-moved", GTK_TYPE_GOBAN); click_canceled_signal_id = g_signal_lookup ("click-canceled", GTK_TYPE_GOBAN); goban_clicked_signal_id = g_signal_lookup ("goban-clicked", GTK_TYPE_GOBAN); /* set_goban_signal_handlers() uses `click_canceled_signal_id', so * we call it only now. */ set_goban_signal_handlers (goban_window, G_CALLBACK (playing_mode_pointer_moved), G_CALLBACK (playing_mode_goban_clicked)); g_signal_connect_swapped (goban, "click-canceled", G_CALLBACK (delete_drawn_position_list), goban_window); g_signal_connect_swapped (goban, "navigate", G_CALLBACK (navigate_goban), goban_window); /* But hide special mode section again. */ leave_special_mode (goban_window); goban_window->board = NULL; goban_window->in_game_mode = FALSE; goban_window->pending_free_handicap = 0; goban_window->players[BLACK_INDEX] = NULL; goban_window->players[WHITE_INDEX] = NULL; goban_window->time_controls[BLACK_INDEX] = NULL; goban_window->time_controls[WHITE_INDEX] = NULL; goban_window->drawn_position_list = NULL; goban_window->updating_set_player_commands = FALSE; goban_window->next_sgf_label = NULL; goban_window->labels_mode = GTK_GOBAN_WINDOW_NON_LABELS_MODE; goban_window->time_of_first_modification = 0; goban_window->filename = NULL; goban_window->save_as_dialog = NULL; goban_window->last_displayed_node = NULL; goban_window->last_game_info_node = NULL; goban_window->find_dialog = NULL; goban_window->text_to_find = NULL; goban_window->game_info_dialog = NULL; } /* NOTE: `filename' must be in file system encoding and absolute path, * if non-NULL! */ GtkWidget * gtk_goban_window_new (SgfCollection *sgf_collection, const char *filename) { GtkWidget *widget = GTK_WIDGET (g_object_new (GTK_TYPE_GOBAN_WINDOW, NULL)); GtkGobanWindow *goban_window = GTK_GOBAN_WINDOW (widget); g_return_val_if_fail (sgf_collection, NULL); g_return_val_if_fail (!filename || g_path_is_absolute (filename), NULL); goban_window->board = NULL; goban_window->dead_stones_list = NULL; goban_window->sgf_collection = sgf_collection; if (filename) { goban_window->filename = g_strdup (filename); gtk_utils_set_menu_items_sensitive (goban_window->item_factory, FALSE, "/File/Save", NULL); gtk_utils_set_toolbar_buttons_sensitive (goban_window->main_toolbar, FALSE, &toolbar_save, NULL); } sgf_collection_set_notification_callback (sgf_collection, collection_modification_state_changed, goban_window); set_current_tree (goban_window, sgf_collection->first_tree); return widget; } static void gtk_goban_window_destroy (GtkObject *object) { GtkGobanWindow *goban_window = GTK_GOBAN_WINDOW (object); if (goban_window->game_info_dialog) gtk_widget_destroy (GTK_WIDGET (goban_window->game_info_dialog)); if (gtk_control_center_window_destroyed (GTK_WINDOW (object))) { g_object_unref (gtk_widget_get_parent (GTK_WIDGET (goban_window->sgf_tree_view))); } GTK_OBJECT_CLASS (parent_class)->destroy (object); } gboolean gtk_goban_window_stops_closing (GtkGobanWindow *goban_window) { g_return_val_if_fail (GTK_IS_GOBAN_WINDOW (goban_window), FALSE); if (sgf_collection_is_modified (goban_window->sgf_collection)) { GtkWidget *question_dialog; gint response_id; if (goban_window->filename) { gchar *filename_in_utf8 = g_filename_to_utf8 (goban_window->filename, -1, NULL, NULL, NULL); question_dialog = (quarry_save_confirmation_dialog_new (GTK_WINDOW (goban_window), goban_window->time_of_first_modification, _("Save changes to game record `%s' before closing?"), filename_in_utf8)); g_free (filename_in_utf8); } else { question_dialog = (quarry_save_confirmation_dialog_new (GTK_WINDOW (goban_window), goban_window->time_of_first_modification, _("Save changes to the untitled game record before closing?"))); } response_id = gtk_dialog_run (GTK_DIALOG (question_dialog)); gtk_widget_destroy (question_dialog); switch (response_id) { case GTK_RESPONSE_NO: /* So do nothing. */ break; case GTK_RESPONSE_YES: gtk_goban_window_save (goban_window, GTK_GOBAN_WINDOW_SAVE); if (!goban_window->save_as_dialog) break; response_id = gtk_dialog_run (GTK_DIALOG (goban_window->save_as_dialog)); gtk_widget_destroy (goban_window->save_as_dialog); if (response_id == GTK_RESPONSE_OK) break; default: case GTK_RESPONSE_CANCEL: /* Don't allow closing then. */ return TRUE; } } return FALSE; } static void gtk_goban_window_finalize (GObject *object) { GtkGobanWindow *goban_window = GTK_GOBAN_WINDOW (object); g_object_unref (goban_window->item_factory); g_object_unref (goban_window->tools_item_factory); if (goban_window->board) board_delete (goban_window->board); if (goban_window->players[BLACK_INDEX]) gtk_schedule_gtp_client_deletion (goban_window->players[BLACK_INDEX]); if (goban_window->players[WHITE_INDEX]) gtk_schedule_gtp_client_deletion (goban_window->players[WHITE_INDEX]); if (goban_window->time_controls[BLACK_INDEX]) time_control_delete (goban_window->time_controls[BLACK_INDEX]); if (goban_window->time_controls[WHITE_INDEX]) time_control_delete (goban_window->time_controls[WHITE_INDEX]); if (goban_window->sgf_collection) sgf_collection_delete (goban_window->sgf_collection); g_free (goban_window->filename); if (goban_window->save_as_dialog) gtk_widget_destroy (goban_window->save_as_dialog); g_free (goban_window->text_to_find); if (goban_window->find_dialog) gtk_widget_destroy (GTK_WIDGET (goban_window->find_dialog)); G_OBJECT_CLASS (parent_class)->finalize (object); } static void force_minimal_width (GtkWidget *widget, GtkRequisition *requisition) { /* TRANSLATORS: Width of this string in default font is used to determine the minimal width of the right board window side. */ static const gchar *string = N_("A good width for the right side to have."); PangoLayout *layout = gtk_widget_create_pango_layout (widget, _(string)); gint width; pango_layout_get_pixel_size (layout, &width, NULL); if (width > requisition->width) requisition->width = width; g_object_unref (layout); } void gtk_goban_window_enter_game_record_mode (GtkGobanWindow *goban_window) { g_return_if_fail (GTK_IS_GOBAN_WINDOW (goban_window)); if (!goban_window->current_tree->undo_history) { goban_window->current_tree->undo_history = sgf_undo_history_new (goban_window->current_tree); sgf_undo_history_set_notification_callback (goban_window->current_tree->undo_history, undo_or_redo_availability_changed, goban_window); } } void gtk_goban_window_enter_game_mode (GtkGobanWindow *goban_window, GtpClient *black_player, GtpClient *white_player, TimeControl *time_control) { const SgfGameTree *game_tree; int handicap = -1; g_return_if_fail (GTK_IS_GOBAN_WINDOW (goban_window)); g_return_if_fail (!goban_window->in_game_mode); goban_window->in_game_mode = TRUE; goban_window->players[BLACK_INDEX] = black_player; goban_window->players[WHITE_INDEX] = white_player; set_time_controls (goban_window, time_control); goban_window->game_position.board_state = &goban_window->sgf_board_state; game_tree = goban_window->current_tree; handicap = sgf_node_get_handicap (game_tree->current_node); if (handicap > 0 && !sgf_node_get_list_of_point_property_value (game_tree->current_node, SGF_ADD_BLACK)) { goban_window->pending_free_handicap = handicap; goban_window->num_handicap_stones_placed = 0; if (!black_player) { /* TRANSLATORS: It can never be 1 stone, always at least 2. */ gchar *hint = g_strdup_printf (ngettext ("Please set up %d (or less)\n" "stone of free handicap", "Please set up %d (or less)\n" "stones of free handicap", handicap), handicap); gtk_widget_set_sensitive (goban_window->done_button, FALSE); enter_special_mode (goban_window, hint, free_handicap_mode_done, NULL); g_free (hint); set_goban_signal_handlers (goban_window, G_CALLBACK (free_handicap_mode_pointer_moved), G_CALLBACK (free_handicap_mode_goban_clicked)); } } do_enter_game_mode (goban_window); } /* FIXME: Get remaining time from the SGF tree and adjust time * controls accordingly. */ void gtk_goban_window_resume_game (GtkGobanWindow *goban_window, GtpClient *black_player, GtpClient *white_player) { SgfBoardState *const board_state = &goban_window->sgf_board_state; g_return_if_fail (GTK_IS_GOBAN_WINDOW (goban_window)); g_return_if_fail (!goban_window->in_game_mode); goban_window->in_game_mode = TRUE; goban_window->players[BLACK_INDEX] = black_player; goban_window->players[WHITE_INDEX] = white_player; goban_window->game_position.board_state = board_state; /* Resuming, skip'em played moves! */ sgf_utils_go_down_in_tree (goban_window->current_tree, -1); if (goban_window->time_controls[BLACK_INDEX]) { time_control_set_state (goban_window->time_controls[BLACK_INDEX], board_state->time_left[BLACK_INDEX], board_state->moves_left[BLACK_INDEX]); } if (goban_window->time_controls[WHITE_INDEX]) { time_control_set_state (goban_window->time_controls[WHITE_INDEX], board_state->time_left[WHITE_INDEX], board_state->moves_left[WHITE_INDEX]); } do_enter_game_mode (goban_window); } static void do_enter_game_mode (GtkGobanWindow *goban_window) { if (goban_window->players[BLACK_INDEX]) { goban_window->player_initialization_step[BLACK_INDEX] = INITIALIZATION_NOT_STARTED; initialize_gtp_player (goban_window->players[BLACK_INDEX], 1, goban_window); } if (goban_window->players[WHITE_INDEX]) { goban_window->player_initialization_step[WHITE_INDEX] = INITIALIZATION_NOT_STARTED; initialize_gtp_player (goban_window->players[WHITE_INDEX], 1, goban_window); } if (goban_window->time_controls[BLACK_INDEX] && goban_window->time_controls[WHITE_INDEX]) { gtk_clock_use_time_control (goban_window->clocks[BLACK_INDEX], goban_window->time_controls[BLACK_INDEX], ((GtkClockOutOfTimeCallback) player_is_out_of_time), goban_window); gtk_clock_use_time_control (goban_window->clocks[WHITE_INDEX], goban_window->time_controls[WHITE_INDEX], ((GtkClockOutOfTimeCallback) player_is_out_of_time), goban_window); } else { g_assert (!goban_window->time_controls[BLACK_INDEX] && !goban_window->time_controls[WHITE_INDEX]); } goban_window->last_displayed_node = NULL; update_children_for_new_node (goban_window, TRUE, FALSE); if (USER_IS_TO_PLAY (goban_window) && !goban_window->pending_free_handicap) start_clock_if_needed (goban_window); } static void leave_game_mode (GtkGobanWindow *goban_window) { goban_window->in_game_mode = FALSE; if (goban_window->time_controls[BLACK_INDEX]) { gtk_clock_use_time_control (goban_window->clocks[BLACK_INDEX], NULL, NULL, NULL); } if (goban_window->time_controls[WHITE_INDEX]) { gtk_clock_use_time_control (goban_window->clocks[WHITE_INDEX], NULL, NULL, NULL); } gtk_goban_window_enter_game_record_mode (goban_window); update_commands_sensitivity (goban_window); } static void collection_modification_state_changed (SgfCollection *sgf_collection, void *user_data) { GtkGobanWindow *goban_window = GTK_GOBAN_WINDOW (user_data); int is_modified = sgf_collection_is_modified (sgf_collection); int is_modified_effective = (is_modified || !goban_window->filename); if (is_modified && goban_window->time_of_first_modification == 0) { GTimeVal current_time; g_get_current_time (¤t_time); goban_window->time_of_first_modification = current_time.tv_sec; } gtk_utils_set_menu_items_sensitive (goban_window->item_factory, is_modified_effective, "/File/Save", NULL); gtk_utils_set_toolbar_buttons_sensitive (goban_window->main_toolbar, is_modified_effective, &toolbar_save, NULL); update_window_title (goban_window); } static void undo_or_redo_availability_changed (SgfUndoHistory *undo_history, void *user_data) { GtkGobanWindow *goban_window = GTK_GOBAN_WINDOW (user_data); gboolean can_undo = sgf_utils_can_undo (goban_window->current_tree); gboolean can_redo = sgf_utils_can_redo (goban_window->current_tree); UNUSED (undo_history); gtk_utils_set_menu_items_sensitive (goban_window->item_factory, can_undo, "/Edit/Undo", NULL); gtk_utils_set_toolbar_buttons_sensitive (goban_window->editing_toolbar, can_undo, &editing_toolbar_undo, NULL); gtk_utils_set_menu_items_sensitive (goban_window->item_factory, can_redo, "/Edit/Redo", NULL); gtk_utils_set_toolbar_buttons_sensitive (goban_window->editing_toolbar, can_redo, &editing_toolbar_redo, NULL); } static void gtk_goban_window_save (GtkGobanWindow *goban_window, guint callback_action) { if (callback_action != GTK_GOBAN_WINDOW_SAVE_AS && goban_window->filename) { if (do_save_collection (goban_window, goban_window->filename) && callback_action == GTK_GOBAN_WINDOW_ADJOURN) game_has_been_adjourned (goban_window); } else { /* "Save as..." command invoked or we don't have a filename. */ gboolean adjourning_game = (callback_action == GTK_GOBAN_WINDOW_ADJOURN); if (!goban_window->save_as_dialog || goban_window->adjourning_game != adjourning_game) { if (goban_window->save_as_dialog) gtk_widget_destroy (goban_window->save_as_dialog); goban_window->save_as_dialog = gtk_file_dialog_new ((adjourning_game ? _("Adjourn & Save As...") : _("Save As...")), GTK_WINDOW (goban_window), FALSE, GTK_STOCK_SAVE); g_signal_connect (goban_window->save_as_dialog, "response", G_CALLBACK (save_file_as_response), goban_window); if (goban_window->filename) { gtk_file_dialog_set_filename (goban_window->save_as_dialog, goban_window->filename); } else { char *filename = suggest_filename (goban_window); gtk_file_dialog_set_current_name (goban_window->save_as_dialog, filename); utils_free (filename); } goban_window->adjourning_game = adjourning_game; gtk_control_center_window_created (GTK_WINDOW (goban_window->save_as_dialog)); gtk_utils_null_pointer_on_destroy (((GtkWindow **) &goban_window->save_as_dialog), TRUE); } gtk_window_present (GTK_WINDOW (goban_window->save_as_dialog)); } } /* Returns a suggested filename for the current game record in UTF-8 * encoding. The return value must be utils_free'd. */ static char * suggest_filename (GtkGobanWindow *goban_window) { const SgfNode *game_info_node = goban_window->sgf_board_state.game_info_node; char *suggested_filename = NULL; if (goban_window->filename) return utils_duplicate_string (goban_window->filename); if (game_info_node) { const char *white_player = sgf_node_get_text_property_value (game_info_node, SGF_PLAYER_WHITE); const char *black_player = sgf_node_get_text_property_value (game_info_node, SGF_PLAYER_BLACK); if (white_player && black_player) { suggested_filename = utils_cat_strings (NULL, white_player, " vs ", black_player, ".sgf", NULL); } else { const char *game_name = sgf_node_get_text_property_value (game_info_node, SGF_GAME_NAME); if (game_name) suggested_filename = utils_cat_strings (NULL, game_name, ".sgf", NULL); } if (suggested_filename) { char *scan; /* For Windows spaces in names are standard anyway. */ #ifndef G_OS_WIN32 for (scan = suggested_filename; *scan; scan++) { /* It's difficult to provide sane alternative for other * characters shells have to escape in filenames, so we keep * those characters as they are. */ if (*scan == ' ') *scan = '-'; } #endif return suggested_filename; } } return NULL; } static void save_file_as_response (GtkWidget *file_dialog, gint response_id, GtkGobanWindow *goban_window) { if (response_id == GTK_RESPONSE_OK) { gchar *filename = gtk_file_dialog_get_filename (file_dialog); if (do_save_collection (goban_window, filename)) { g_free (goban_window->filename); goban_window->filename = filename; if (goban_window->adjourning_game) { game_has_been_adjourned (goban_window); return; } } else g_free (filename); } if (!gtk_window_get_modal (GTK_WINDOW (file_dialog)) && (response_id == GTK_RESPONSE_OK || response_id == GTK_RESPONSE_CANCEL)) gtk_widget_destroy (file_dialog); } static gboolean do_save_collection (GtkGobanWindow *goban_window, const gchar *filename) { char* error; SgfGameTree *sgf_tree = goban_window->current_tree; SgfUndoHistory *undo_history = sgf_tree->undo_history; /* Fetch comment and node name, but ensure that SGF properties are * changed only for the call to sgf_write_file(), by undo history * swapping. */ sgf_tree->undo_history = sgf_undo_history_new (sgf_tree); fetch_comment_and_node_name (goban_window, TRUE); error = sgf_write_file (filename, goban_window->sgf_collection, sgf_configuration.force_utf8); if (sgf_utils_can_undo (sgf_tree)) sgf_utils_undo (sgf_tree); sgf_undo_history_delete (sgf_tree->undo_history, sgf_tree); sgf_tree->undo_history = undo_history; if (!error) { sgf_collection_set_unmodified (goban_window->sgf_collection); goban_window->time_of_first_modification = 0; } else { GtkWidget *error_dialog = quarry_message_dialog_new (GTK_WINDOW (goban_window), GTK_BUTTONS_OK, GTK_STOCK_DIALOG_ERROR, error, _("Error saving to file `%s'"), filename); g_free (error); gtk_utils_show_and_forget_dialog (GTK_DIALOG (error_dialog)); } return error == NULL; } static void game_has_been_adjourned (GtkGobanWindow *goban_window) { static const gchar *hint = N_("You can later resume the game by pressing the `Resume Game' button " "in Quarry Control Center, or selecting `Resume Game' item from " "the `File' menu."); gchar *filename_in_utf8 = g_filename_to_utf8 (goban_window->filename, -1, NULL, NULL, NULL); gchar *message = g_strdup_printf (_("The game is adjourned and " "saved in file `%s'"), filename_in_utf8); GtkWidget *information_dialog = quarry_message_dialog_new (NULL, GTK_BUTTONS_OK, GTK_STOCK_DIALOG_INFO, _(hint), message); gtk_utils_show_and_forget_dialog (GTK_DIALOG (information_dialog)); g_free (filename_in_utf8); gtk_widget_destroy (GTK_WIDGET (goban_window)); } static void export_ascii_diagram (GtkGobanWindow *goban_window) { static const gchar *message = N_("ASCII diagram has been exported to clipboard"); do_export_diagram (goban_window, sgf_utils_export_position_as_ascii (goban_window->current_tree), _(message)); } static void export_senseis_library_diagram (GtkGobanWindow *goban_window) { static const gchar *message = N_("Sensei's Library diagram has been exported to clipboard"); do_export_diagram (goban_window, (sgf_utils_export_position_as_senseis_library_diagram (goban_window->current_tree)), _(message)); } static void do_export_diagram (GtkGobanWindow *goban_window, char *diagram_string, const gchar *message) { static const gchar *hint = N_("You can usually paste the diagram in another application using " "`Ctrl+C' key combination or by selecting appropriate menu item."); int diagram_string_length = strlen (diagram_string); GtkWidget *message_dialog; gtk_clipboard_set_text (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD), diagram_string, diagram_string_length); gtk_clipboard_set_text (gtk_clipboard_get (GDK_SELECTION_PRIMARY), diagram_string, diagram_string_length); utils_free (diagram_string); message_dialog = quarry_message_dialog_new (GTK_WINDOW (goban_window), GTK_BUTTONS_OK, GTK_STOCK_DIALOG_INFO, _(hint), message); gtk_utils_show_and_forget_dialog (GTK_DIALOG (message_dialog)); } static void gtk_goban_window_close (GtkGobanWindow *goban_window) { if (!gtk_goban_window_stops_closing (goban_window)) gtk_widget_destroy (GTK_WIDGET (goban_window)); } static void show_find_dialog (GtkGobanWindow *goban_window) { if (!goban_window->find_dialog) { goban_window->find_dialog = QUARRY_FIND_DIALOG (quarry_find_dialog_new (_("Find"))); gtk_utils_null_pointer_on_destroy (((GtkWindow **) &goban_window->find_dialog), FALSE); gtk_window_set_transient_for (GTK_WINDOW (goban_window->find_dialog), GTK_WINDOW (goban_window)); gtk_window_set_destroy_with_parent (GTK_WINDOW (goban_window->find_dialog), TRUE); if (!goban_window->text_to_find) { /* The dialog is opened for the first time for this * `goban_window'. Initialize local configuration. */ goban_window->case_sensitive = find_dialog_configuration.case_sensitive; goban_window->whole_words_only = find_dialog_configuration.whole_words_only; goban_window->wrap_around = find_dialog_configuration.wrap_around; goban_window->search_whole_game_tree = find_dialog_configuration.search_whole_game_tree; goban_window->search_in = find_dialog_configuration.search_in; goban_window->close_automatically = find_dialog_configuration.close_automatically; } else { quarry_find_dialog_set_text_to_find (goban_window->find_dialog, goban_window->text_to_find); } quarry_find_dialog_set_search_history (goban_window->find_dialog, &find_dialog_configuration.latest_search_strings); quarry_find_dialog_set_case_sensitive (goban_window->find_dialog, goban_window->case_sensitive); quarry_find_dialog_set_whole_words_only (goban_window->find_dialog, goban_window->whole_words_only); quarry_find_dialog_set_wrap_around (goban_window->find_dialog, goban_window->wrap_around); quarry_find_dialog_set_search_whole_game_tree (goban_window->find_dialog, goban_window->search_whole_game_tree); quarry_find_dialog_set_search_in (goban_window->find_dialog, goban_window->search_in); quarry_find_dialog_set_close_automatically (goban_window->find_dialog, goban_window->close_automatically); g_signal_connect (goban_window->find_dialog, "response", G_CALLBACK (find_dialog_response), goban_window); } gtk_window_present (GTK_WINDOW (goban_window->find_dialog)); } static void find_dialog_response (QuarryFindDialog *find_dialog, gint response_id, GtkGobanWindow *goban_window) { if (response_id == QUARRY_FIND_DIALOG_FIND_NEXT || response_id == QUARRY_FIND_DIALOG_FIND_PREVIOUS) { g_free (goban_window->text_to_find); goban_window->text_to_find = g_strdup (quarry_find_dialog_get_text_to_find (find_dialog)); goban_window->case_sensitive = quarry_find_dialog_get_case_sensitive (find_dialog); find_dialog_configuration.case_sensitive = goban_window->case_sensitive; goban_window->whole_words_only = quarry_find_dialog_get_whole_words_only (find_dialog); find_dialog_configuration.whole_words_only = goban_window->whole_words_only; goban_window->wrap_around = quarry_find_dialog_get_wrap_around (find_dialog); find_dialog_configuration.wrap_around = goban_window->wrap_around; goban_window->search_whole_game_tree = quarry_find_dialog_get_search_whole_game_tree (find_dialog); find_dialog_configuration.search_whole_game_tree = goban_window->search_whole_game_tree; goban_window->search_in = quarry_find_dialog_get_search_in (find_dialog); find_dialog_configuration.search_in = goban_window->search_in; goban_window->close_automatically = quarry_find_dialog_get_close_automatically (find_dialog); find_dialog_configuration.close_automatically = goban_window->close_automatically; if (!do_find_text (goban_window, response_id) || !find_dialog_configuration.close_automatically) { /* Don't close the dialog. */ return; } } else if (response_id == GTK_RESPONSE_HELP) { gtk_help_display ("find-dialog"); return; } gtk_widget_destroy (GTK_WIDGET (find_dialog)); } static gboolean do_find_text (GtkGobanWindow *goban_window, QuarryFindDialogSearchDirection direction) { if (!goban_window->text_to_find) { /* Don't have text to find yet. */ show_find_dialog (goban_window); return FALSE; } if (quarry_find_text (goban_window->text_to_find, direction, goban_window->case_sensitive, goban_window->whole_words_only, goban_window->wrap_around, goban_window->search_whole_game_tree, goban_window->search_in, goban_window->text_buffer, goban_window->node_name_inserted, goban_window->current_tree, ((QuarryFindDialogSwitchToGivenNode) switch_to_given_node), goban_window)) { gtk_text_view_scroll_to_mark (goban_window->text_view, gtk_text_buffer_get_insert (goban_window->text_buffer), 0.1, FALSE, 0.0, 0.0); StringListItem *item = string_list_find (&find_dialog_configuration.latest_search_strings, goban_window->text_to_find); if (item) { string_list_delete_item (&find_dialog_configuration.latest_search_strings, item); } else { /* Ten (maximal history size) minus one. Account for the item * to be added! */ string_list_clamp_size (&find_dialog_configuration.latest_search_strings, 9); } string_list_prepend (&find_dialog_configuration.latest_search_strings, utils_duplicate_string (goban_window->text_to_find)); if (goban_window->find_dialog) { quarry_find_dialog_set_search_history (goban_window->find_dialog, &find_dialog_configuration.latest_search_strings); } return TRUE; } else { if (goban_window->find_dialog) { if (goban_window->wrap_around || direction == QUARRY_FIND_DIALOG_FIND_NEXT) { gtk_dialog_set_response_sensitive (GTK_DIALOG (goban_window->find_dialog), QUARRY_FIND_DIALOG_FIND_NEXT, FALSE); } if (goban_window->wrap_around || direction == QUARRY_FIND_DIALOG_FIND_PREVIOUS) { gtk_dialog_set_response_sensitive (GTK_DIALOG (goban_window->find_dialog), QUARRY_FIND_DIALOG_FIND_PREVIOUS, FALSE); } } return FALSE; } } static void show_game_information_dialog (GtkGobanWindow *goban_window) { if (!goban_window->game_info_dialog) { goban_window->game_info_dialog = GTK_GAME_INFO_DIALOG (gtk_game_info_dialog_new ()); gtk_utils_null_pointer_on_destroy (((GtkWindow **) &goban_window->game_info_dialog), FALSE); gtk_window_set_transient_for (GTK_WINDOW (goban_window->game_info_dialog), GTK_WINDOW (goban_window)); g_signal_connect_swapped (goban_window->game_info_dialog, "property-changed", G_CALLBACK (game_info_dialog_property_changed), goban_window); gtk_game_info_dialog_set_node (goban_window->game_info_dialog, goban_window->current_tree, goban_window->last_game_info_node); } gtk_window_present (GTK_WINDOW (goban_window->game_info_dialog)); } static void game_info_dialog_property_changed (GtkGobanWindow *goban_window, SgfType sgf_property_type) { switch (sgf_property_type) { case SGF_GAME_NAME: update_window_title (goban_window); break; case SGF_PLAYER_BLACK: case SGF_BLACK_RANK: case SGF_BLACK_TEAM: update_player_information (goban_window, BLACK); break; case SGF_PLAYER_WHITE: case SGF_WHITE_RANK: case SGF_WHITE_TEAM: update_player_information (goban_window, WHITE); break; case SGF_KOMI: update_game_specific_information (goban_window); break; case SGF_RESULT: if (!goban_window->current_tree->current_node->child && !goban_window->sgf_board_state.last_main_variation_node) { /* The result is being displayed now, update the display. */ update_move_information (goban_window); } break; default: /* Silence warnings. */ break; } } static void show_preferences_dialog (void) { gtk_preferences_dialog_present (GINT_TO_POINTER (-1)); } static void show_or_hide_main_toolbar (GtkGobanWindow *goban_window) { GtkWidget *toolbar_handle_box = gtk_widget_get_parent (GTK_WIDGET (goban_window->main_toolbar)); GtkWidget *menu_item = gtk_item_factory_get_widget (goban_window->item_factory, "/View/Main Toolbar"); gtk_ui_configuration.show_main_toolbar = !GTK_WIDGET_VISIBLE (toolbar_handle_box); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menu_item), gtk_ui_configuration.show_main_toolbar); gtk_utils_set_widgets_visible (gtk_ui_configuration.show_main_toolbar, toolbar_handle_box, NULL); } static void show_or_hide_editing_toolbar (GtkGobanWindow *goban_window) { GtkWidget *toolbar_handle_box = gtk_widget_get_parent (GTK_WIDGET (goban_window->editing_toolbar)); GtkWidget *menu_item = gtk_item_factory_get_widget (goban_window->item_factory, "/View/Editing Toolbar"); gtk_ui_configuration.show_editing_toolbar = !GTK_WIDGET_VISIBLE (toolbar_handle_box); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menu_item), gtk_ui_configuration.show_editing_toolbar); gtk_utils_set_widgets_visible (gtk_ui_configuration.show_editing_toolbar, toolbar_handle_box, NULL); } static void show_or_hide_navigation_toolbar (GtkGobanWindow *goban_window) { GtkWidget *toolbar_handle_box = gtk_widget_get_parent (GTK_WIDGET (goban_window->navigation_toolbar)); GtkWidget *menu_item = gtk_item_factory_get_widget (goban_window->item_factory, "/View/Navigation Toolbar"); gtk_ui_configuration.show_navigation_toolbar = !GTK_WIDGET_VISIBLE (toolbar_handle_box); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menu_item), gtk_ui_configuration.show_navigation_toolbar); gtk_utils_set_widgets_visible (gtk_ui_configuration.show_navigation_toolbar, toolbar_handle_box, NULL); } static void show_or_hide_game_action_buttons (GtkGobanWindow *goban_window) { GtkWidget *game_action_buttons_box = gtk_widget_get_parent (goban_window->pass_button); GtkWidget *menu_item = gtk_item_factory_get_widget (goban_window->item_factory, "/View/Game Action Buttons"); gtk_ui_configuration.show_game_action_buttons = !GTK_WIDGET_VISIBLE (game_action_buttons_box); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menu_item), gtk_ui_configuration.show_game_action_buttons); gtk_utils_set_widgets_visible (gtk_ui_configuration.show_game_action_buttons, game_action_buttons_box, NULL); } static void show_or_hide_sgf_tree_view (GtkGobanWindow *goban_window, guint callback_action) { GtkWidget *sgf_tree_view_parent = gtk_widget_get_parent (GTK_WIDGET (goban_window->sgf_tree_view)); gboolean sgf_tree_view_is_visible = (gtk_widget_get_parent (sgf_tree_view_parent) != NULL); gboolean show_sgf_tree_view; if (callback_action == GTK_GOBAN_WINDOW_TOGGLE_CHILD) { show_sgf_tree_view = !sgf_tree_view_is_visible; goban_window->sgf_tree_view_visibility_locked = TRUE; } else show_sgf_tree_view = callback_action; if (show_sgf_tree_view != sgf_tree_view_is_visible) { GtkWidget *menu_item = gtk_item_factory_get_widget (goban_window->item_factory, "/View/Game Tree"); g_signal_handlers_block_by_func (menu_item, show_or_hide_sgf_tree_view, goban_window); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menu_item), show_sgf_tree_view); g_signal_handlers_unblock_by_func (menu_item, show_or_hide_sgf_tree_view, goban_window); gtk_utils_set_menu_items_sensitive (goban_window->item_factory, show_sgf_tree_view, "/View/Recenter on Current Node", NULL); if (show_sgf_tree_view) { gtk_paned_pack2 (goban_window->vpaned, sgf_tree_view_parent, TRUE, FALSE); /* Force reallocation of `sgf_tree_view' now: recentering * algorithm needs to know the widget size to find the center. */ gtk_container_check_resize (GTK_CONTAINER (goban_window->vpaned)); gtk_sgf_tree_view_center_on_current_node (goban_window->sgf_tree_view); } else { gtk_container_remove (GTK_CONTAINER (goban_window->vpaned), sgf_tree_view_parent); } } } static void recenter_sgf_tree_view (GtkGobanWindow *goban_window) { gtk_sgf_tree_view_center_on_current_node (goban_window->sgf_tree_view); } static void show_sgf_tree_view_automatically (GtkGobanWindow *goban_window, const SgfNode *sgf_node) { if (game_tree_view.show_game_tree == SHOW_GAME_TREE_AUTOMATICALLY && !goban_window->sgf_tree_view_visibility_locked && sgf_node && (sgf_node->next || (sgf_node->parent && sgf_node->parent->child != sgf_node))) show_or_hide_sgf_tree_view (goban_window, GTK_GOBAN_WINDOW_SHOW_CHILD); } #ifdef GTK_TYPE_GO_TO_NAMED_NODE_DIALOG static void show_go_to_named_node_dialog (GtkGobanWindow *goban_window) { GtkWidget *dialog = gtk_go_to_named_node_dialog_new (goban_window->current_tree); if (dialog == NULL) { dialog = quarry_message_dialog_new (NULL, GTK_BUTTONS_OK, GTK_STOCK_DIALOG_INFO, NULL, _("Sorry, there are no named " "nodes in this game tree")); } gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (goban_window)); if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK && GTK_IS_GO_TO_NAMED_NODE_DIALOG (dialog)) { switch_to_given_node (goban_window, GTK_GO_TO_NAMED_NODE_DIALOG (dialog)->selected_node); } gtk_widget_destroy (dialog); } #endif /* GTK_TYPE_GO_TO_NAMED_NODE_DIALOG */ static void show_about_dialog (void) { static const char *description_string = N_("A GUI program for Go, Amazons and Reversi board games"); static const char *copyright_string = N_("Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev and others"); if (!about_dialog) { #if GTK_2_6_OR_LATER GtkAboutDialog *dialog = GTK_ABOUT_DIALOG (gtk_about_dialog_new ()); gtk_about_dialog_set_name (dialog, PACKAGE_NAME); gtk_about_dialog_set_version (dialog, PACKAGE_VERSION); gtk_about_dialog_set_copyright (dialog, _(copyright_string)); gtk_about_dialog_set_comments (dialog, _(description_string)); about_dialog = GTK_WINDOW (dialog); #else /* not GTK_2_6_OR_LATER */ GtkWidget *dialog = gtk_dialog_new_with_buttons (_("About Quarry"), NULL, 0, GTK_STOCK_CLOSE, GTK_RESPONSE_CANCEL, NULL); GtkWidget *quarry_label; GtkWidget *description_label; GtkWidget *copyright_label; GtkWidget *vbox; gchar *copyright_markup = g_strconcat ("", _(copyright_string), "", NULL); about_dialog = GTK_WINDOW (dialog); gtk_utils_null_pointer_on_destroy (&about_dialog, FALSE); gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CANCEL); g_signal_connect (dialog, "response", G_CALLBACK (gtk_widget_destroy), NULL); quarry_label = gtk_label_new (NULL); gtk_label_set_markup (GTK_LABEL (quarry_label), ("" PACKAGE_STRING "")); description_label = gtk_label_new (_(description_string)); copyright_label = gtk_label_new (NULL); gtk_label_set_justify (GTK_LABEL (copyright_label), GTK_JUSTIFY_CENTER); gtk_label_set_markup (GTK_LABEL (copyright_label), copyright_markup); g_free (copyright_markup); vbox = gtk_utils_pack_in_box (GTK_TYPE_VBOX, QUARRY_SPACING, quarry_label, GTK_UTILS_FILL, description_label, GTK_UTILS_FILL, copyright_label, GTK_UTILS_FILL, NULL); gtk_utils_standardize_dialog (GTK_DIALOG (dialog), vbox); gtk_widget_show_all (vbox); #endif /* not GTK_2_6_OR_LATER */ } gtk_window_present (about_dialog); } static void show_help_contents (void) { gtk_help_display (NULL); } static void tools_option_menu_changed (GtkOptionMenu *option_menu, const GtkGobanWindow *goban_window) { gint tool_index = gtk_option_menu_get_history (option_menu); GtkMenuShell *tools_menu = GTK_MENU_SHELL (gtk_item_factory_get_widget (goban_window->item_factory, "/Edit/Tools")); GtkCheckMenuItem *menu_item = GTK_CHECK_MENU_ITEM (g_list_nth_data (tools_menu->children, tool_index)); gtk_check_menu_item_set_active (menu_item, TRUE); } static void synchronize_tools_menus (const GtkGobanWindow *goban_window) { GtkMenuShell *main_tools_menu = GTK_MENU_SHELL (gtk_item_factory_get_widget (goban_window->item_factory, "/Edit/Tools")); GtkMenuShell *toolbar_tools_menu = GTK_MENU_SHELL (gtk_option_menu_get_menu (goban_window->tools_option_menu)); GList *main_menu_child; GList *toolbar_menu_child; int k; for (main_menu_child = main_tools_menu->children, toolbar_menu_child = toolbar_tools_menu->children, k = 0; main_menu_child && toolbar_menu_child; main_menu_child = main_menu_child->next, toolbar_menu_child = toolbar_menu_child->next, k++) { gtk_widget_set_sensitive (GTK_WIDGET (toolbar_menu_child->data), GTK_WIDGET_SENSITIVE (main_menu_child->data)); if (GTK_IS_CHECK_MENU_ITEM (main_menu_child->data) && (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (main_menu_child->data)))) gtk_option_menu_set_history (goban_window->tools_option_menu, k); } } static void update_territory_markup (GtkGobanWindow *goban_window) { int x; int y; char goban_markup[BOARD_GRID_SIZE]; for (y = 0; y < goban_window->board->height; y++) { for (x = 0; x < goban_window->board->width; x++) { int pos = POSITION (x, y); if (!goban_window->dead_stones[pos]) goban_markup[pos] = TILE_NONE; else goban_markup[pos] = GOBAN_MARKUP_GHOSTIFY; } } go_mark_territory_on_grid (goban_window->board, goban_markup, goban_window->dead_stones, BLACK_OPAQUE | GOBAN_MARKUP_GHOSTIFY, WHITE_OPAQUE | GOBAN_MARKUP_GHOSTIFY); gtk_goban_update (goban_window->goban, NULL, goban_markup, NULL, KEEP_SGF_LABELS, goban_window->sgf_board_state.last_move_x, goban_window->sgf_board_state.last_move_y); } static void enter_special_mode (GtkGobanWindow *goban_window, const gchar *hint, SpecialModeButtonClicked done_callback, SpecialModeButtonClicked cancel_callback) { gtk_label_set_text (goban_window->mode_hint_label, hint); gtk_widget_show (goban_window->mode_information_vbox); gtk_widget_show (goban_window->done_button); g_signal_connect_swapped (goban_window->done_button, "clicked", G_CALLBACK (done_callback), goban_window); if (cancel_callback) { gtk_widget_show (goban_window->cancel_button); g_signal_connect_swapped (goban_window->cancel_button, "clicked", G_CALLBACK (cancel_callback), goban_window); } else gtk_widget_hide (goban_window->cancel_button); } static void leave_special_mode (GtkGobanWindow *goban_window) { g_signal_handlers_disconnect_matched (goban_window->done_button, (G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DATA), clicked_signal_id, 0, NULL, NULL, goban_window); g_signal_handlers_disconnect_matched (goban_window->cancel_button, (G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DATA), clicked_signal_id, 0, NULL, NULL, goban_window); gtk_widget_hide (goban_window->mode_information_vbox); } static void free_handicap_mode_done (GtkGobanWindow *goban_window) { BoardPositionList *difference_lists[NUM_ON_GRID_VALUES]; grid_diff (goban_window->board->grid, goban_window->goban->grid, goban_window->board->width, goban_window->board->height, difference_lists); g_assert ((difference_lists[BLACK]->num_positions == goban_window->num_handicap_stones_placed) && difference_lists[WHITE] == NULL && difference_lists[EMPTY] == NULL && difference_lists[SPECIAL_ON_GRID_VALUE] == NULL); leave_special_mode (goban_window); set_goban_signal_handlers (goban_window, G_CALLBACK (playing_mode_pointer_moved), G_CALLBACK (playing_mode_goban_clicked)); free_handicap_has_been_placed (goban_window, difference_lists[BLACK]); } static void go_scoring_mode_done (GtkGobanWindow *goban_window) { handle_go_scoring_results (goban_window); if (goban_window->in_game_mode) { set_goban_signal_handlers (goban_window, G_CALLBACK (playing_mode_pointer_moved), G_CALLBACK (playing_mode_goban_clicked)); } else { GtkWidget *move_tool_menu_item = gtk_item_factory_get_widget (goban_window->item_factory, "/Edit/Tools/Move Tool"); /* Activate move tool. */ gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (move_tool_menu_item), TRUE); } reenter_current_node (goban_window); } static void go_scoring_mode_cancel (GtkGobanWindow *goban_window) { GtkWidget *move_tool_menu_item = gtk_item_factory_get_widget (goban_window->item_factory, "/Edit/Tools/Move Tool"); /* Activate move tool. */ gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (move_tool_menu_item), TRUE); reenter_current_node (goban_window); } static void handle_go_scoring_results (GtkGobanWindow *goban_window) { SgfGameTree *current_tree = goban_window->current_tree; SgfNode *game_info_node = current_tree->board_state->game_info_node; double komi = 0.0; double score; StringBuffer detailed_score; BoardPositionList *black_territory; BoardPositionList *white_territory; sgf_node_get_komi (game_info_node, &komi); string_buffer_init (&detailed_score, 0x400, 0x200); go_score_game (current_tree->board, goban_window->dead_stones, komi, &score, &detailed_score, &black_territory, &white_territory); sgf_utils_begin_action (current_tree); fetch_comment_and_node_name (goban_window, TRUE); sgf_utils_append_text_property (current_tree->current_node, current_tree, SGF_COMMENT, string_buffer_steal_string (&detailed_score), "\n\n----------------\n\n", 0); set_comment_and_node_name (goban_window, current_tree->current_node); sgf_utils_set_list_of_point_property (current_tree->current_node, current_tree, SGF_BLACK_TERRITORY, black_territory, 0); sgf_utils_set_list_of_point_property (current_tree->current_node, current_tree, SGF_WHITE_TERRITORY, white_territory, 0); sgf_utils_set_score_result (game_info_node, current_tree, score, 1); sgf_utils_end_action (current_tree); g_free (goban_window->dead_stones); goban_window->dead_stones = NULL; } static void set_current_tree (GtkGobanWindow *goban_window, SgfGameTree *sgf_tree) { if (!goban_window->board && GAME_IS_SUPPORTED (sgf_tree->game)) { GtkLabel **game_specific_info = goban_window->game_specific_info; goban_window->board = board_new (sgf_tree->game, sgf_tree->board_width, sgf_tree->board_height); gtk_utils_set_widgets_visible (goban_window->board->game != GAME_AMAZONS, game_specific_info[BLACK_INDEX], game_specific_info[WHITE_INDEX], NULL); gtk_utils_set_widgets_visible (goban_window->board->game == GAME_GO, goban_window->pass_button, NULL); } /* Won't work from update_children_for_new_node() below, because the * tree is being changed. * * FIXME: Doesn't really work currently. Not important yet, since * we don't support switching the current tree anyway. */ update_comment_and_node_name_if_needed (goban_window, TRUE); gtk_sgf_tree_signal_proxy_attach (sgf_tree); goban_window->current_tree = sgf_tree; sgf_utils_enter_tree (sgf_tree, goban_window->board, &goban_window->sgf_board_state); gtk_goban_set_parameters (goban_window->goban, sgf_tree->game, sgf_tree->board_width, sgf_tree->board_height); set_time_controls (goban_window, time_control_new_from_sgf_node (sgf_tree->root)); update_game_information (goban_window); update_children_for_new_node (goban_window, TRUE, FALSE); undo_or_redo_availability_changed (NULL, goban_window); gtk_sgf_tree_view_set_sgf_tree (goban_window->sgf_tree_view, sgf_tree); if (game_tree_view.show_game_tree == SHOW_GAME_TREE_AUTOMATICALLY && !goban_window->sgf_tree_view_visibility_locked) { const SgfNode *sgf_node; for (sgf_node = sgf_tree->root->child; sgf_node; sgf_node = sgf_node->child) { if (sgf_node->next) break; } show_or_hide_sgf_tree_view (goban_window, (sgf_node ? GTK_GOBAN_WINDOW_SHOW_CHILD : GTK_GOBAN_WINDOW_HIDE_CHILD)); } } static void set_time_controls (GtkGobanWindow *goban_window, TimeControl *time_control) { if (goban_window->time_controls[BLACK_INDEX]) time_control_delete (goban_window->time_controls[BLACK_INDEX]); if (goban_window->time_controls[WHITE_INDEX]) time_control_delete (goban_window->time_controls[WHITE_INDEX]); goban_window->time_controls[BLACK_INDEX] = time_control; goban_window->time_controls[WHITE_INDEX] = (time_control ? time_control_duplicate (time_control) : NULL); } static void reenter_current_node (GtkGobanWindow *goban_window) { SgfGameTree *current_tree = goban_window->current_tree; if (current_tree->current_node->parent) { sgf_utils_go_up_in_tree (current_tree, 1); sgf_utils_go_down_in_tree (current_tree, 1); } else { sgf_utils_enter_tree (current_tree, goban_window->board, &goban_window->sgf_board_state); } /* `text_handled' is set to TRUE to avoid spoiling undo/redo history * and text buffer contents. */ update_children_for_new_node (goban_window, TRUE, TRUE); } /* This function must be called before changing to ``arbitrary'' in * some sense node. More exactly, when the node we are going to * switch to is not being added as a result of playing a move. */ static void about_to_change_node (GtkGobanWindow *goban_window) { g_signal_emit (goban_window->goban, click_canceled_signal_id, 0); if (goban_window->in_game_mode && IS_DISPLAYING_GAME_NODE (goban_window)) { /* Goban window is going to display something other than the game * position node. */ sgf_game_tree_get_state (goban_window->current_tree, &goban_window->game_position); goban_window->game_position.board = board_duplicate_without_stacks (goban_window->game_position.board); goban_window->game_position.board_state = &goban_window->game_position_board_state_holder; memcpy (&goban_window->game_position_board_state_holder, &goban_window->sgf_board_state, sizeof (SgfBoardState)); } } /* Similar to about_to_change_node(), but has to be called after the * current node is changed. */ static void just_changed_node (GtkGobanWindow *goban_window) { if (goban_window->in_game_mode && !IS_DISPLAYING_GAME_NODE (goban_window) && (goban_window->game_position.current_node == goban_window->current_tree->current_node)) { /* The goban window displayed something other than the game * position node, but has just navigated back to that node. */ board_delete (goban_window->game_position.board); goban_window->game_position.board_state = &goban_window->sgf_board_state; } } static void play_pass_move (GtkGobanWindow *goban_window) { g_assert (goban_window->board->game == GAME_GO && USER_CAN_PLAY_MOVES (goban_window)); sgf_utils_append_variation (goban_window->current_tree, goban_window->sgf_board_state.color_to_play, PASS_X, PASS_Y); if (goban_window->in_game_mode && IS_DISPLAYING_GAME_NODE (goban_window)) move_has_been_played (goban_window); update_children_for_new_node (goban_window, TRUE, FALSE); } static void resign_game (GtkGobanWindow *goban_window) { GtkWidget *question_dialog = quarry_message_dialog_new (GTK_WINDOW (goban_window), GTK_BUTTONS_NONE, GTK_STOCK_DIALOG_QUESTION, NULL, _("Really resign this game?")); gtk_dialog_add_buttons (GTK_DIALOG (question_dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, _("_Resign"), GTK_RESPONSE_OK, NULL); gtk_dialog_set_default_response (GTK_DIALOG (question_dialog), GTK_RESPONSE_OK); if (gtk_dialog_run (GTK_DIALOG (question_dialog)) == GTK_RESPONSE_OK) do_resign_game (goban_window); gtk_widget_destroy (question_dialog); } static void do_resign_game (GtkGobanWindow *goban_window) { int color = goban_window->sgf_board_state.color_to_play; char other_color_char = (color == BLACK ? 'W' : 'B'); SgfNode *game_info_node = goban_window->sgf_board_state.game_info_node; leave_game_mode (goban_window); sgf_utils_set_text_property (game_info_node, goban_window->current_tree, SGF_RESULT, utils_cprintf ("%c+Resign", other_color_char), 1); sgf_utils_append_variation (goban_window->current_tree, EMPTY); update_children_for_new_node (goban_window, TRUE, FALSE); } static void cancel_amazons_move (GtkGobanWindow *goban_window) { if (goban_window->amazons_move_stage == SHOOTING_ARROW) { gtk_goban_set_overlay_data (goban_window->goban, 1, NULL, TILE_NONE, TILE_NONE, SGF_MARKUP_NONE); } if (goban_window->amazons_move_stage != SELECTING_QUEEN) { gtk_goban_set_overlay_data (goban_window->goban, 0, NULL, TILE_NONE, TILE_NONE, SGF_MARKUP_NONE); } reset_amazons_move_data (goban_window); } static void reset_amazons_move_data (GtkGobanWindow *goban_window) { goban_window->amazons_move_stage = 0; goban_window->amazons_move.from.x = NULL_X; goban_window->amazons_move.from.y = NULL_Y; goban_window->amazons_to_x = NULL_X; goban_window->amazons_to_y = NULL_Y; goban_window->amazons_move.shoot_arrow_to.x = NULL_X; goban_window->amazons_move.shoot_arrow_to.y = NULL_Y; } static void set_goban_signal_handlers (GtkGobanWindow *goban_window, GCallback pointer_moved_handler, GCallback goban_clicked_handler) { /* Mode switching must cancel whatever is being done with mouse. */ g_signal_emit (goban_window->goban, click_canceled_signal_id, 0); g_signal_handlers_disconnect_matched (goban_window->goban, (G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DATA), pointer_moved_signal_id, 0, NULL, NULL, goban_window); g_signal_handlers_disconnect_matched (goban_window->goban, (G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DATA), goban_clicked_signal_id, 0, NULL, NULL, goban_window); g_signal_connect_swapped (goban_window->goban, "pointer-moved", pointer_moved_handler, goban_window); g_signal_connect_swapped (goban_window->goban, "goban-clicked", goban_clicked_handler, goban_window); gtk_goban_force_feedback_poll (goban_window->goban); } static GtkGobanPointerFeedback playing_mode_pointer_moved (GtkGobanWindow *goban_window, GtkGobanPointerData *data) { if (USER_CAN_PLAY_MOVES (goban_window)) { int color_to_play = goban_window->sgf_board_state.color_to_play; switch (data->button) { case 0: if (!(data->modifiers & GDK_SHIFT_MASK)) { if (color_to_play == EMPTY) break; if (goban_window->board->game != GAME_AMAZONS) { if (board_is_legal_move (goban_window->board, RULE_SET_DEFAULT, color_to_play, data->x, data->y)) return GOBAN_FEEDBACK_MOVE + COLOR_INDEX (color_to_play); } else { if (goban_window->amazons_move_stage == SELECTING_QUEEN) { goban_window->amazons_move.from.x = data->x; goban_window->amazons_move.from.y = data->y; } else if (goban_window->amazons_move_stage == MOVING_QUEEN) { goban_window->amazons_to_x = data->x; goban_window->amazons_to_y = data->y; } else { goban_window->amazons_move.shoot_arrow_to.x = data->x; goban_window->amazons_move.shoot_arrow_to.y = data->y; } if (board_is_legal_move (goban_window->board, RULE_SET_DEFAULT, color_to_play, goban_window->amazons_to_x, goban_window->amazons_to_y, goban_window->amazons_move)) { if (goban_window->amazons_move_stage == SELECTING_QUEEN) return GOBAN_FEEDBACK_MOVE + COLOR_INDEX (color_to_play); else if (goban_window->amazons_move_stage == MOVING_QUEEN) return GOBAN_FEEDBACK_GHOST + COLOR_INDEX (color_to_play); else return GOBAN_FEEDBACK_SPECIAL; } } } break; case 1: return GOBAN_FEEDBACK_PRESS_DEFAULT; case 3: if ((goban_window->board->game != GAME_AMAZONS || goban_window->amazons_move_stage == SELECTING_QUEEN) && data->x == data->press_x && data->y == data->press_y && find_variation_to_switch_to (goban_window, data->x, data->y, data->modifiers & GDK_SHIFT_MASK ? SGF_PREVIOUS : SGF_NEXT)) { return (GOBAN_FEEDBACK_THICK_GHOST + COLOR_INDEX (goban_window->node_to_switch_to->move_color)); } } } return GOBAN_FEEDBACK_NONE; } static void playing_mode_goban_clicked (GtkGobanWindow *goban_window, GtkGobanClickData *data) { switch (data->button) { case 1: if (data->non_empty_feedback && !(data->modifiers & GDK_SHIFT_MASK)) { int color_to_play = goban_window->sgf_board_state.color_to_play; if (color_to_play == EMPTY) return; if (goban_window->board->game != GAME_AMAZONS) { sgf_utils_append_variation (goban_window->current_tree, color_to_play, data->x, data->y); } else { int pos = POSITION (data->x, data->y); if (goban_window->amazons_move_stage == SELECTING_QUEEN) { goban_window->amazons_move_stage = MOVING_QUEEN; gtk_goban_set_overlay_data (goban_window->goban, 0, board_position_list_new (&pos, 1), (STONE_50_TRANSPARENT + COLOR_INDEX (color_to_play)), GOBAN_TILE_DONT_CHANGE, GOBAN_SGF_MARKUP_TILE_DONT_CHANGE); return; } else if (goban_window->amazons_move_stage == MOVING_QUEEN) { goban_window->amazons_move_stage = SHOOTING_ARROW; gtk_goban_set_overlay_data (goban_window->goban, 1, board_position_list_new (&pos, 1), (STONE_25_TRANSPARENT + COLOR_INDEX (color_to_play)), GOBAN_TILE_DONT_CHANGE, GOBAN_SGF_MARKUP_TILE_DONT_CHANGE); return; } else { sgf_utils_append_variation (goban_window->current_tree, color_to_play, goban_window->amazons_to_x, goban_window->amazons_to_y, goban_window->amazons_move); } } if (goban_window->in_game_mode && IS_DISPLAYING_GAME_NODE (goban_window)) move_has_been_played (goban_window); update_children_for_new_node (goban_window, TRUE, FALSE); } break; case 3: if (goban_window->board->game != GAME_AMAZONS || goban_window->amazons_move_stage == SELECTING_QUEEN) { if (!find_variation_to_switch_to (goban_window, data->x, data->y, data->modifiers & GDK_SHIFT_MASK ? SGF_PREVIOUS : SGF_NEXT)) return; about_to_change_node (goban_window); sgf_utils_switch_to_given_variation (goban_window->current_tree, goban_window->node_to_switch_to); just_changed_node (goban_window); update_children_for_new_node (goban_window, TRUE, FALSE); } else cancel_amazons_move (goban_window); break; } } static GtkGobanPointerFeedback setup_mode_pointer_moved (GtkGobanWindow *goban_window, GtkGobanPointerData *data) { Board *const board = goban_window->board; int pos = POSITION (data->x, data->y); switch (data->button) { case 0: if (data->modifiers & GDK_CONTROL_MASK && board->game == GAME_GO) { if (!IS_STONE (board->grid[pos])) break; data->feedback_position_list = go_get_string_stones (board, data->x, data->y); return GOBAN_FEEDBACK_THICK_GHOST + COLOR_INDEX (board->grid[pos]); } return (data->modifiers & GDK_SHIFT_MASK ? GOBAN_FEEDBACK_ADD_BLACK_OR_REMOVE : GOBAN_FEEDBACK_ADD_WHITE_OR_REMOVE); case 1: case 3: gtk_goban_disable_anti_slip_mode (goban_window->goban); if (data->modifiers & GDK_CONTROL_MASK && board->game == GAME_GO) { if (!IS_STONE (board->grid[POSITION (data->press_x, data->press_y)]) || !go_is_same_string (board, data->press_x, data->press_y, data->x, data->y)) break; data->feedback_position_list = go_get_string_stones (board, data->x, data->y); return GOBAN_FEEDBACK_GHOST + COLOR_INDEX (board->grid[pos]); } if (!goban_window->drawn_position_list) { if (IS_STONE (board->grid[pos])) goban_window->drawing_mode = EMPTY; else { goban_window->drawing_mode = ((data->button == 3 || (data->modifiers & GDK_SHIFT_MASK)) ? BLACK : WHITE); } } goban_window->drawn_position_list = board_position_list_add_position (goban_window->drawn_position_list, pos); data->feedback_position_list = board_position_list_duplicate (goban_window->drawn_position_list); switch (goban_window->drawing_mode) { case EMPTY: return GOBAN_FEEDBACK_GHOSTIFY; case BLACK: return GOBAN_FEEDBACK_THICK_BLACK_GHOST; case WHITE: return GOBAN_FEEDBACK_THICK_WHITE_GHOST; default: g_assert_not_reached (); } } return GOBAN_FEEDBACK_NONE; } static void setup_mode_goban_clicked (GtkGobanWindow *goban_window, GtkGobanClickData *data) { if (data->button != 1 && data->button != 3) return; if (data->modifiers & GDK_CONTROL_MASK && goban_window->board->game == GAME_GO) { BoardPositionList *string_stones; if (!data->non_empty_feedback) return; string_stones = go_get_string_stones (goban_window->board, data->x, data->y); gtk_goban_set_contents (goban_window->goban, string_stones, EMPTY, GOBAN_TILE_DONT_CHANGE, GOBAN_SGF_MARKUP_TILE_DONT_CHANGE); board_position_list_delete (string_stones); } else { gtk_goban_set_contents (goban_window->goban, goban_window->drawn_position_list, goban_window->drawing_mode, GOBAN_TILE_DONT_CHANGE, GOBAN_SGF_MARKUP_TILE_DONT_CHANGE); board_position_list_delete (goban_window->drawn_position_list); goban_window->drawn_position_list = NULL; } if (sgf_utils_apply_setup_changes (goban_window->current_tree, goban_window->goban->grid, 0)) update_children_for_new_node (goban_window, TRUE, FALSE); } static GtkGobanPointerFeedback markup_mode_pointer_moved (GtkGobanWindow *goban_window, GtkGobanPointerData *data) { GtkGoban *const goban = goban_window->goban; Board *const board = goban_window->board; int pos = POSITION (data->x, data->y); switch (data->button) { case 0: { int is_over_same_existing_markup = (gtk_goban_get_sgf_markup_contents (goban, data->x, data->y) == goban_window->sgf_markup_type); if (data->modifiers & GDK_CONTROL_MASK && board->game == GAME_GO) { if (!IS_STONE (board->grid[pos])) break; data->feedback_position_list = go_get_string_stones (board, data->x, data->y); if (is_over_same_existing_markup) { return (GOBAN_FEEDBACK_SGF_GHOSTIFY_SLIGHTLY * GOBAN_FEEDBACK_SGF_FACTOR); } } return (((is_over_same_existing_markup ? GOBAN_FEEDBACK_SGF_THICK_GHOST : GOBAN_FEEDBACK_SGF_GHOST) + goban_window->sgf_markup_type) * GOBAN_FEEDBACK_SGF_FACTOR); } case 1: case 3: gtk_goban_disable_anti_slip_mode (goban_window->goban); if (gtk_goban_get_sgf_markup_contents (goban, data->press_x, data->press_y) == goban_window->sgf_markup_type) goban_window->drawing_mode = SGF_MARKUP_NONE; else goban_window->drawing_mode = goban_window->sgf_markup_type; if (data->modifiers & GDK_CONTROL_MASK && board->game == GAME_GO) { if (!IS_STONE (board->grid[POSITION (data->press_x, data->press_y)]) || !go_is_same_string (board, data->press_x, data->press_y, data->x, data->y)) break; data->feedback_position_list = go_get_string_stones (board, data->x, data->y); } else { goban_window->drawn_position_list = board_position_list_add_position (goban_window->drawn_position_list, pos); data->feedback_position_list = board_position_list_duplicate (goban_window->drawn_position_list); } if (goban_window->drawing_mode == SGF_MARKUP_NONE) return GOBAN_FEEDBACK_SGF_GHOSTIFY * GOBAN_FEEDBACK_SGF_FACTOR; else { return ((GOBAN_FEEDBACK_SGF_THICK_GHOST + goban_window->drawing_mode) * GOBAN_FEEDBACK_SGF_FACTOR); } } return GOBAN_FEEDBACK_NONE; } static void markup_mode_goban_clicked (GtkGobanWindow *goban_window, GtkGobanClickData *data) { if (data->button != 1 && data->button != 3) return; if (data->modifiers & GDK_CONTROL_MASK && goban_window->board->game == GAME_GO) { BoardPositionList *string_stones; if (!data->non_empty_feedback) return; string_stones = go_get_string_stones (goban_window->board, data->x, data->y); gtk_goban_set_contents (goban_window->goban, string_stones, GOBAN_TILE_DONT_CHANGE, GOBAN_TILE_DONT_CHANGE, goban_window->drawing_mode); board_position_list_delete (string_stones); } else { gtk_goban_set_contents (goban_window->goban, goban_window->drawn_position_list, GOBAN_TILE_DONT_CHANGE, GOBAN_TILE_DONT_CHANGE, goban_window->drawing_mode); board_position_list_delete (goban_window->drawn_position_list); goban_window->drawn_position_list = NULL; } sgf_utils_apply_markup_changes (goban_window->current_tree, goban_window->goban->sgf_markup, 0); } static GtkGobanPointerFeedback label_mode_pointer_moved (GtkGobanWindow *goban_window, GtkGobanPointerData *data) { /* FIXME: Make configurable. E.g. some people may prefer upper-case * labels or a different alphabet. */ static const gchar *labels = "abcdefghijklmnopqrstuvwxyz"; if (data->button == 0 && !goban_window->next_sgf_label) { const SgfNode *current_node = goban_window->current_tree->current_node; const SgfLabelList *label_list = sgf_node_get_list_of_label_property_value (current_node, SGF_LABEL); int k; switch (goban_window->labels_mode) { case GTK_GOBAN_WINDOW_TEXT_LABELS_MODE: for (k = 0; k < strlen (labels); k++) { goban_window->next_sgf_label = utils_duplicate_as_string (labels + k, 1); if (!label_list || !sgf_label_list_contains_label (label_list, goban_window->next_sgf_label)) break; utils_free (goban_window->next_sgf_label); goban_window->next_sgf_label = NULL; } break; case GTK_GOBAN_WINDOW_NUMERIC_LABELS_MODE: for (k = 1; ; k++) { goban_window->next_sgf_label = utils_printf ("%d", k); if (!label_list || !sgf_label_list_contains_label (label_list, goban_window->next_sgf_label)) break; utils_free (goban_window->next_sgf_label); goban_window->next_sgf_label = NULL; } break; default: g_assert_not_reached (); } } if ((data->button == 1 && (data->modifiers & GDK_SHIFT_MASK)) || data->button == 3) return GOBAN_FEEDBACK_NONE; if (data->button == 0 || data->button == 1) { const gchar *label = goban_window->next_sgf_label; int ghost_level = (data->button == 0 ? LABEL_50_TRANSPARENT : LABEL_25_TRANSPARENT); const SgfNode *current_node = goban_window->current_tree->current_node; const SgfLabelList *label_list = sgf_node_get_list_of_label_property_value (current_node, SGF_LABEL); if (label_list) { BoardPoint point = { data->x, data->y }; const char *existing_label = sgf_label_list_get_label (label_list, point); if (existing_label) { label = existing_label; ghost_level = (data->button == 0 ? LABEL_25_TRANSPARENT : LABEL_50_TRANSPARENT); } } if (label) { gtk_goban_set_label_feedback (goban_window->goban, data->x, data->y, label, ghost_level); } else { gtk_goban_set_label_feedback (goban_window->goban, NULL_X, NULL_Y, NULL, 0); } } return GOBAN_FEEDBACK_NONE; } static void label_mode_goban_clicked (GtkGobanWindow *goban_window, GtkGobanClickData *data) { SgfNode *current_node = goban_window->current_tree->current_node; const SgfLabelList *old_label_list; const char *existing_label = NULL; BoardPoint point = { data->x, data->y }; SgfLabelList *new_label_list; if (data->button != 1 && data->button != 3) return; old_label_list = sgf_node_get_list_of_label_property_value (current_node, SGF_LABEL); if (old_label_list) existing_label = sgf_label_list_get_label (old_label_list, point); if (data->button == 1 && !(data->modifiers & GDK_SHIFT_MASK)) { if (!existing_label) { new_label_list = sgf_label_list_set_label (old_label_list, point, goban_window->next_sgf_label); goban_window->next_sgf_label = NULL; } else new_label_list = sgf_label_list_set_label (old_label_list, point, NULL); } else { GtkWidget *dialog = gtk_add_or_edit_label_dialog_new (); if (existing_label) { gtk_add_or_edit_label_dialog_set_label_text (GTK_ADD_OR_EDIT_LABEL_DIALOG (dialog), existing_label); gtk_window_set_title (GTK_WINDOW (dialog), _("Edit Board Label")); } else gtk_window_set_title (GTK_WINDOW (dialog), _("Add Board Label")); gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (goban_window)); if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) { const gchar *new_label_text = (gtk_add_or_edit_label_dialog_get_label_text (GTK_ADD_OR_EDIT_LABEL_DIALOG (dialog))); if (! *new_label_text) new_label_text = NULL; new_label_list = sgf_label_list_set_label (old_label_list, point, utils_duplicate_string (new_label_text)); gtk_widget_destroy (dialog); } else { gtk_widget_destroy (dialog); return; } } if (sgf_utils_set_list_of_label_property (current_node, goban_window->current_tree, SGF_LABEL, new_label_list, 0)) update_children_for_new_node (goban_window, TRUE, FALSE); } static GtkGobanPointerFeedback free_handicap_mode_pointer_moved (GtkGobanWindow *goban_window, GtkGobanPointerData *data) { switch (data->button) { case 0: if (!(data->modifiers & GDK_SHIFT_MASK)) { int contents = gtk_goban_get_grid_contents (goban_window->goban, data->x, data->y); if (contents == BLACK || (contents == EMPTY && (goban_window->num_handicap_stones_placed < goban_window->pending_free_handicap))) return GOBAN_FEEDBACK_ADD_BLACK_OR_REMOVE; } break; case 1: return GOBAN_FEEDBACK_PRESS_DEFAULT; } return GOBAN_FEEDBACK_NONE; } static void free_handicap_mode_goban_clicked (GtkGobanWindow *goban_window, GtkGobanClickData *data) { if (data->button == 1 && data->non_empty_feedback && !(data->modifiers & GDK_SHIFT_MASK)) { int contents = gtk_goban_get_grid_contents (goban_window->goban, data->x, data->y); int pos = POSITION (data->x, data->y); BoardPositionList *position_list = board_position_list_new (&pos, 1); if (contents == EMPTY) { contents = BLACK; goban_window->num_handicap_stones_placed++; } else if (contents == BLACK) { contents = EMPTY; goban_window->num_handicap_stones_placed--; } else { g_assert_not_reached (); return; } gtk_goban_set_contents (goban_window->goban, position_list, contents, GOBAN_TILE_DONT_CHANGE, GOBAN_SGF_MARKUP_TILE_DONT_CHANGE); board_position_list_delete (position_list); gtk_widget_set_sensitive (goban_window->done_button, goban_window->num_handicap_stones_placed >= 2); } } static GtkGobanPointerFeedback go_scoring_mode_pointer_moved (GtkGobanWindow *goban_window, GtkGobanPointerData *data) { BoardPositionList * (* const get_stones) (Board *board, int x, int y) = (data->modifiers & GDK_SHIFT_MASK ? go_get_string_stones : go_get_logically_dead_stones); int pos = POSITION (data->x, data->y); switch (data->button) { case 0: { BoardPositionList *stones = get_stones (goban_window->board, data->x, data->y); if (stones) { int color = goban_window->board->grid[pos]; data->feedback_position_list = stones; if (!goban_window->dead_stones[pos]) { return ((GOBAN_FEEDBACK_GHOST + COLOR_INDEX (OTHER_COLOR (color))) * GOBAN_FEEDBACK_MARKUP_FACTOR); } else { return ((GOBAN_FEEDBACK_THICK_GHOST + COLOR_INDEX (color)) + (GOBAN_FEEDBACK_FORCE_TILE_NONE * GOBAN_FEEDBACK_MARKUP_FACTOR)); } } } break; case 1: { BoardPositionList *stones = get_stones (goban_window->board, data->x, data->y); if (stones) { int color = goban_window->board->grid[pos]; data->feedback_position_list = stones; if (!goban_window->dead_stones[pos]) { return ((GOBAN_FEEDBACK_THICK_GHOST + COLOR_INDEX (color)) + ((GOBAN_FEEDBACK_GHOST + COLOR_INDEX (OTHER_COLOR (color))) * GOBAN_FEEDBACK_MARKUP_FACTOR)); } else { return ((GOBAN_FEEDBACK_OPAQUE + COLOR_INDEX (color)) + (GOBAN_FEEDBACK_FORCE_TILE_NONE * GOBAN_FEEDBACK_MARKUP_FACTOR)); } } } break; } return GOBAN_FEEDBACK_NONE; } static void go_scoring_mode_goban_clicked (GtkGobanWindow *goban_window, GtkGobanClickData *data) { if (data->button == 1) { BoardPositionList * (* const get_stones) (Board *board, int x, int y) = (data->modifiers & GDK_SHIFT_MASK ? go_get_string_stones : go_get_logically_dead_stones); BoardPositionList *stones = get_stones (goban_window->board, data->x, data->y); if (stones) { int pos = POSITION (data->x, data->y); board_position_list_mark_on_grid (stones, goban_window->dead_stones, !goban_window->dead_stones[pos]); board_position_list_delete (stones); update_territory_markup (goban_window); } } } static void sgf_tree_view_clicked (GtkGobanWindow *goban_window, SgfNode *sgf_node, gint button_index) { if (button_index == 1) switch_to_given_node (goban_window, sgf_node); else if (button_index == 3) { if (sgf_node->child) { sgf_utils_set_node_is_collapsed (goban_window->current_tree, sgf_node, !sgf_node->is_collapsed); } } } static void delete_drawn_position_list (GtkGobanWindow *goban_window) { if (goban_window->drawn_position_list) { board_position_list_delete (goban_window->drawn_position_list); goban_window->drawn_position_list = NULL; } } static void navigate_goban (GtkGobanWindow *goban_window, GtkGobanNavigationCommand command) { SgfGameTree *current_tree = goban_window->current_tree; SgfNode *current_node = current_tree->current_node; if (IS_IN_SPECIAL_MODE (goban_window)) return; /* Don't do anything if navigating the goban doesn't change * displayed node. */ switch (command) { case GOBAN_NAVIGATE_BACK: case GOBAN_NAVIGATE_BACK_FAST: case GOBAN_NAVIGATE_ROOT: if (!current_node->parent) return; break; case GOBAN_NAVIGATE_FORWARD: case GOBAN_NAVIGATE_FORWARD_FAST: case GOBAN_NAVIGATE_VARIATION_END: if (!current_node->child) return; break; case GOBAN_NAVIGATE_PREVIOUS_VARIATION: if (!current_node->parent || current_node->parent->child == current_node) return; break; case GOBAN_NAVIGATE_NEXT_VARIATION: if (!current_node->next) return; break; default: return; } about_to_change_node (goban_window); switch (command) { case GOBAN_NAVIGATE_BACK: sgf_utils_go_up_in_tree (current_tree, 1); break; case GOBAN_NAVIGATE_BACK_FAST: sgf_utils_go_up_in_tree (current_tree, NAVIGATE_FAST_NUM_MOVES); break; case GOBAN_NAVIGATE_FORWARD: sgf_utils_go_down_in_tree (current_tree, 1); break; case GOBAN_NAVIGATE_FORWARD_FAST: sgf_utils_go_down_in_tree (current_tree, NAVIGATE_FAST_NUM_MOVES); break; case GOBAN_NAVIGATE_PREVIOUS_VARIATION: sgf_utils_switch_to_variation (current_tree, SGF_PREVIOUS); break; case GOBAN_NAVIGATE_NEXT_VARIATION: sgf_utils_switch_to_variation (current_tree, SGF_NEXT); break; case GOBAN_NAVIGATE_ROOT: sgf_utils_go_up_in_tree (current_tree, -1); break; case GOBAN_NAVIGATE_VARIATION_END: sgf_utils_go_down_in_tree (current_tree, -1); break; } just_changed_node (goban_window); update_children_for_new_node (goban_window, TRUE, FALSE); } static void switch_to_given_node (GtkGobanWindow *goban_window, SgfNode *sgf_node) { about_to_change_node (goban_window); sgf_utils_switch_to_given_node (goban_window->current_tree, sgf_node); just_changed_node (goban_window); update_children_for_new_node (goban_window, FALSE, FALSE); } static int find_variation_to_switch_to (GtkGobanWindow *goban_window, int x, int y, SgfDirection direction) { if (x != goban_window->switching_x || y != goban_window->switching_y || direction != goban_window->switching_direction) { const SgfNode *current_node = goban_window->current_tree->current_node; int after_node = (IS_STONE (current_node->move_color) && current_node->move_point.x == x && current_node->move_point.y == y); goban_window->switching_x = x; goban_window->switching_y = y; goban_window->switching_direction = direction; goban_window->node_to_switch_to = sgf_utils_find_variation_at_position (goban_window->current_tree, x, y, direction, after_node); } return goban_window->node_to_switch_to != NULL; } static void update_children_for_new_node (GtkGobanWindow *goban_window, gboolean forced, gboolean text_handled) { const SgfBoardState *const board_state = &goban_window->sgf_board_state; SgfGameTree *current_tree = goban_window->current_tree; SgfNode *current_node = current_tree->current_node; QuarryTextBufferState *text_buffer_state = NULL; char goban_markup[BOARD_GRID_SIZE]; if (!forced && current_node == goban_window->last_displayed_node) return; if (goban_window->last_displayed_node && goban_window->last_displayed_node != current_node && !text_handled) { text_buffer_state = update_comment_and_node_name_if_needed (goban_window, FALSE); } reset_amazons_move_data (goban_window); /* FIXME: Probably not the right place for it. */ utils_free (goban_window->next_sgf_label); goban_window->next_sgf_label = NULL; if (!goban_window->last_displayed_node || current_node->parent != goban_window->last_displayed_node->parent) { sgf_utils_count_variations (current_tree, 1, goban_window->black_variations, goban_window->white_variations, NULL); } board_fill_grid (goban_window->board, goban_markup, TILE_NONE); gui_utils_mark_variations_on_grid (goban_markup, goban_window->board, goban_window->black_variations, goban_window->white_variations, BLACK_50_TRANSPARENT, WHITE_50_TRANSPARENT, MIXED_50_TRANSPARENT); sgf_utils_mark_territory_on_grid (current_tree, goban_markup, (BLACK_OPAQUE | GOBAN_MARKUP_GHOSTIFY), (WHITE_OPAQUE | GOBAN_MARKUP_GHOSTIFY)); sgf_utils_get_markup (current_tree, goban_window->sgf_markup); gtk_goban_update (goban_window->goban, goban_window->board->grid, goban_markup, goban_window->sgf_markup, sgf_node_get_list_of_label_property_value (current_node, SGF_LABEL), board_state->last_move_x, board_state->last_move_y); gtk_goban_force_feedback_poll (goban_window->goban); if (goban_window->last_game_info_node != board_state->game_info_node) update_game_information (goban_window); update_game_specific_information (goban_window); update_move_information (goban_window); if (!text_handled && (goban_window->last_displayed_node != current_node || !gtk_text_buffer_get_modified (goban_window->text_buffer))) set_comment_and_node_name (goban_window, current_node); if (text_buffer_state) { quarry_text_buffer_get_state (QUARRY_TEXT_BUFFER (goban_window->text_buffer), text_buffer_state); } if (!goban_window->in_game_mode) { int k; for (k = 0; k < NUM_COLORS; k++) { if (goban_window->time_controls[k]) { double time_left; int moves_left; time_control_apply_defaults_if_needed (goban_window->time_controls[k], board_state->time_left[k], board_state->moves_left[k], &time_left, &moves_left); gtk_clock_set_time (goban_window->clocks[k], time_left, moves_left); } else { gtk_clock_set_time (goban_window->clocks[k], board_state->time_left[k], board_state->moves_left[k]); } } } show_sgf_tree_view_automatically (goban_window, current_node); update_commands_sensitivity (goban_window); update_set_player_to_move_commands (goban_window); goban_window->switching_x = NULL_X; goban_window->switching_y = NULL_Y; goban_window->last_displayed_node = current_node; } static void set_comment_and_node_name (GtkGobanWindow *goban_window, const SgfNode *sgf_node) { const char *comment = sgf_node_get_text_property_value (sgf_node, SGF_COMMENT); const char *node_name = sgf_node_get_text_property_value (sgf_node, SGF_NODE_NAME); gtk_utils_block_signal_handlers (goban_window->text_buffer, text_buffer_receive_undo_entry); goban_window->node_name_inserted = FALSE; gtk_utils_set_text_buffer_text (goban_window->text_buffer, comment); if (node_name) insert_node_name (goban_window, node_name); gtk_text_buffer_set_modified (goban_window->text_buffer, FALSE); gtk_utils_unblock_signal_handlers (goban_window->text_buffer, text_buffer_receive_undo_entry); } static void update_game_information (GtkGobanWindow *goban_window) { SgfNode *game_info_node = goban_window->sgf_board_state.game_info_node; update_window_title (goban_window); update_player_information (goban_window, BLACK); update_player_information (goban_window, WHITE); goban_window->last_game_info_node = game_info_node; if (goban_window->game_info_dialog) { gtk_game_info_dialog_set_node (goban_window->game_info_dialog, goban_window->current_tree, game_info_node); } } static void update_window_title (GtkGobanWindow *goban_window) { const SgfNode *game_info_node = goban_window->sgf_board_state.game_info_node; const char *game_name = NULL; char *string_to_free = NULL; char *title; if (game_info_node) { game_name = sgf_node_get_text_property_value (game_info_node, SGF_GAME_NAME); if (!game_name) { const char *white_player = sgf_node_get_text_property_value (game_info_node, SGF_PLAYER_WHITE); const char *black_player = sgf_node_get_text_property_value (game_info_node, SGF_PLAYER_BLACK); if (white_player && black_player) { string_to_free = g_strdup_printf (_("%s (W) vs. %s"), white_player, black_player); game_name = string_to_free; } } } if (goban_window->filename) { gchar *filename_in_utf8 = g_filename_to_utf8 (goban_window->filename, -1, NULL, NULL, NULL); char *base_name = g_path_get_basename (filename_in_utf8); if (game_name) title = utils_cat_strings (NULL, game_name, " (", base_name, ")", NULL); else title = utils_duplicate_string (base_name); g_free (base_name); g_free (filename_in_utf8); } else { if (game_name) title = utils_duplicate_string (game_name); else title = utils_duplicate_string (_("Unnamed Game")); } if (sgf_collection_is_modified (goban_window->sgf_collection) || !goban_window->filename) title = utils_cat_strings (title, " [", _("modified"), "]", NULL); gtk_window_set_title (GTK_WINDOW (goban_window), title); utils_free (title); g_free (string_to_free); } static void update_player_information (GtkGobanWindow *goban_window, int player_color) { SgfNode *game_info_node = goban_window->sgf_board_state.game_info_node; const char *name = NULL; const char *rank = NULL; const char *team = NULL; char *label_text; if (game_info_node) { name = sgf_node_get_text_property_value (game_info_node, (player_color == BLACK ? SGF_PLAYER_BLACK : SGF_PLAYER_WHITE)); rank = sgf_node_get_text_property_value (game_info_node, (player_color == BLACK ? SGF_BLACK_RANK : SGF_WHITE_RANK)); team = sgf_node_get_text_property_value (game_info_node, (player_color == BLACK ? SGF_BLACK_TEAM : SGF_WHITE_TEAM)); } label_text = utils_duplicate_string (name ? name : _("[unknown]")); if (rank) { /* Heuristic: add a comma if the rank doesn't begin with a number * (i.e. "Honinbo".) */ label_text = utils_cat_strings (label_text, '0' <= *rank && *rank <= '9' ? " " : ", ", rank, NULL); } if (team) label_text = utils_cat_strings (label_text, " (", team, ")", NULL); gtk_label_set_text (goban_window->player_labels[COLOR_INDEX (player_color)], label_text); utils_free (label_text); } static void update_game_specific_information (const GtkGobanWindow *goban_window) { const Board *board = goban_window->board; gchar *black_string; gchar *white_string; if (board->game == GAME_GO) { const SgfNode *game_info_node = goban_window->sgf_board_state.game_info_node; double komi; black_string = g_strdup_printf (ngettext ("%d capture", "%d captures", board->data.go.prisoners[BLACK_INDEX]), board->data.go.prisoners[BLACK_INDEX]); white_string = g_strdup_printf (ngettext ("%d capture", "%d captures", board->data.go.prisoners[WHITE_INDEX]), board->data.go.prisoners[WHITE_INDEX]); if (game_info_node && sgf_node_get_komi (game_info_node, &komi) && komi != 0.0) { gchar *full_white_string; if ((fabs (fabs (komi) - floor (fabs (komi) + 0.005)) >= 0.005)) { full_white_string = g_strdup_printf (_("%s %s %.*f komi"), white_string, (komi >= 0.0 ? "+" : "\xe2\x88\x92"), ((int) floor (komi * 100.0 + 0.5) % 10 == 0 ? 1 : 2), fabs (komi)); } else { int absolute_integral_komi = (int) floor (fabs (komi) + 0.005); full_white_string = g_strdup_printf (ngettext ("%s %s %d komi", "%s %s %d komi", absolute_integral_komi), white_string, (komi >= 0.0 ? "+" : "\xe2\x88\x92"), absolute_integral_komi); } g_free (white_string); white_string = full_white_string; } } else if (board->game == GAME_REVERSI) { int num_black_disks; int num_white_disks; reversi_count_disks (board, &num_black_disks, &num_white_disks); black_string = g_strdup_printf (ngettext ("%d disk", "%d disks", num_black_disks), num_black_disks); white_string = g_strdup_printf (ngettext ("%d disk", "%d disks", num_white_disks), num_white_disks); } else return; gtk_label_set_text (goban_window->game_specific_info[BLACK_INDEX], black_string); gtk_label_set_text (goban_window->game_specific_info[WHITE_INDEX], white_string); g_free (black_string); g_free (white_string); } static void update_move_information (const GtkGobanWindow *goban_window) { const SgfNode *move_node = goban_window->sgf_board_state.last_move_node; const SgfNode *game_info_node = goban_window->sgf_board_state.game_info_node; SgfResult result = SGF_RESULT_NOT_SET; gboolean result_is_final; double score; StringBuffer buffer; string_buffer_init (&buffer, 0x100, 0x100); if (move_node) { if (goban_window->current_tree->current_node == move_node) { string_buffer_printf (&buffer, _("Move %d: "), goban_window->board->move_number); } else { string_buffer_printf (&buffer, _("Last move: %u, "), goban_window->board->move_number); } sgf_utils_format_node_move (goban_window->current_tree, move_node, &buffer, /* TRANSLATORS: This is an abbreviation of `Black'. */ _("B "), /* TRANSLATORS: This is an abbreviation of `White'. */ _("W "), _("pass")); } else string_buffer_cat_string (&buffer, _("Game beginning")); if (game_info_node && !goban_window->current_tree->current_node->child && !goban_window->sgf_board_state.last_main_variation_node) result = sgf_node_get_result (game_info_node, &score); result_is_final = (result != SGF_RESULT_NOT_SET && result != SGF_RESULT_UNKNOWN && result != SGF_RESULT_VOID && result != SGF_RESULT_INVALID); if (!result_is_final && !board_is_game_over (goban_window->board, RULE_SET_DEFAULT, goban_window->sgf_board_state.color_to_play)) { string_buffer_cat_string (&buffer, ((goban_window->sgf_board_state.color_to_play == BLACK) ? _("; black to play") : _("; white to play"))); } else string_buffer_cat_string (&buffer, _("; game over")); if (result_is_final) { string_buffer_add_character (&buffer, '\n'); switch (result) { case SGF_RESULT_BLACK_WIN: string_buffer_cat_string (&buffer, _("Black wins")); break; case SGF_RESULT_WHITE_WIN: string_buffer_cat_string (&buffer, _("White wins")); break; case SGF_RESULT_BLACK_WIN_BY_FORFEIT: string_buffer_cat_string (&buffer, _("Black wins by forfeit")); break; case SGF_RESULT_WHITE_WIN_BY_FORFEIT: string_buffer_cat_string (&buffer, _("White wins by forfeit")); break; case SGF_RESULT_BLACK_WIN_BY_RESIGNATION: string_buffer_cat_string (&buffer, _("White resigns")); break; case SGF_RESULT_WHITE_WIN_BY_RESIGNATION: string_buffer_cat_string (&buffer, _("Black resigns")); break; case SGF_RESULT_BLACK_WIN_BY_SCORE: case SGF_RESULT_WHITE_WIN_BY_SCORE: game_format_score_difference (goban_window->board->game, &buffer, (result == SGF_RESULT_BLACK_WIN_BY_SCORE ? score : -score)); break; case SGF_RESULT_BLACK_WIN_BY_TIME: string_buffer_cat_string (&buffer, _("White runs out of time and loses")); break; case SGF_RESULT_WHITE_WIN_BY_TIME: string_buffer_cat_string (&buffer, _("Black runs out of time and loses")); break; case SGF_RESULT_DRAW: string_buffer_cat_string (&buffer, _("Game is draw")); break; default: g_assert_not_reached (); } } gtk_label_set_text (goban_window->move_information_label, buffer.string); string_buffer_dispose (&buffer); } static void update_commands_sensitivity (const GtkGobanWindow *goban_window) { const SgfGameTree *current_tree = goban_window->current_tree; const SgfNode *current_node = current_tree->current_node; gboolean is_in_special_mode = IS_IN_SPECIAL_MODE (goban_window); gboolean pass_sensitive = (goban_window->board->game == GAME_GO && USER_CAN_PLAY_MOVES (goban_window) && !is_in_special_mode); gboolean resign_sensitive = (goban_window->in_game_mode && IS_DISPLAYING_GAME_NODE (goban_window) && USER_CAN_PLAY_MOVES (goban_window) && !is_in_special_mode); gboolean previous_node_sensitive = (current_node->parent != NULL && !is_in_special_mode); gboolean next_node_sensitive = (current_node->child != NULL && !is_in_special_mode); gboolean previous_variation_sensitive = (current_node->parent != NULL && (current_node->parent->child != current_node) && !is_in_special_mode); gboolean next_variation_sensitive = (current_node->next != NULL && !is_in_special_mode); /* "File" submenu, */ gtk_utils_set_menu_items_sensitive (goban_window->item_factory, goban_window->current_tree->game == GAME_GO, "/File/Export.../Sensei's Library Diagram", NULL); /* "Edit" submenu. */ gtk_utils_set_menu_items_sensitive (goban_window->item_factory, (!goban_window->in_game_mode && current_node->parent != NULL), "/Edit/Cut", NULL); gtk_utils_set_menu_items_sensitive (goban_window->item_factory, !goban_window->in_game_mode, "/Edit/Paste", NULL); gtk_utils_set_menu_items_sensitive (goban_window->item_factory, (USER_CAN_PLAY_MOVES (goban_window) && !is_in_special_mode), "/Edit/Add Empty Node", NULL); gtk_utils_set_menu_items_sensitive (goban_window->item_factory, previous_variation_sensitive, "/Edit/Move Branch Up", NULL); gtk_utils_set_menu_items_sensitive (goban_window->item_factory, next_variation_sensitive, "/Edit/Move Branch Down", NULL); gtk_utils_set_menu_items_sensitive (goban_window->item_factory, (!goban_window->in_game_mode && current_node->parent != NULL), "/Edit/Delete Node", NULL); gtk_utils_set_toolbar_buttons_sensitive (goban_window->editing_toolbar, (!goban_window->in_game_mode && current_node->parent != NULL), &editing_toolbar_delete, NULL); gtk_utils_set_menu_items_sensitive (goban_window->item_factory, (!goban_window->in_game_mode && current_node->child != NULL), "/Edit/Delete Node's Children", NULL); gtk_utils_set_menu_items_sensitive (goban_window->item_factory, /* FIXME: Not strictly following * SGF, but let's not * care for now. */ IS_STONE (current_node->move_color), "/Edit/Set Move Number", NULL); gtk_utils_set_menu_items_sensitive (goban_window->item_factory, !is_in_special_mode, "/Edit/Find", "/Edit/Find Next", "/Edit/Find Previous", NULL); gtk_utils_set_toolbar_buttons_sensitive (goban_window->main_toolbar, !is_in_special_mode, &toolbar_find, NULL); /* "Edit/Tools" submenu. */ /* Only desensitize when scoring a game. */ gtk_utils_set_menu_items_sensitive (goban_window->item_factory, (!goban_window->in_game_mode || !goban_window->dead_stones), "/Edit/Tools/Move Tool", NULL); /* Only desensitize when playing a game. */ gtk_utils_set_menu_items_sensitive (goban_window->item_factory, !goban_window->in_game_mode, "/Edit/Tools/Setup Tool", "/Edit/Tools/Cross Markup", "/Edit/Tools/Circle Markup", "/Edit/Tools/Square Markup", "/Edit/Tools/Triangle Markup", "/Edit/Tools/Selected Markup", "/Edit/Tools/Label Tool", "/Edit/Tools/Number Tool", NULL); /* Only desensitize when playing a game and not scoring already. */ gtk_utils_set_menu_items_sensitive (goban_window->item_factory, (!goban_window->in_game_mode || goban_window->dead_stones), "/Edit/Tools/Scoring Tool", NULL); synchronize_tools_menus (goban_window); /* "Play" submenu. */ gtk_utils_set_menu_items_sensitive (goban_window->item_factory, pass_sensitive, "/Play/Pass", NULL); gtk_widget_set_sensitive (goban_window->pass_button, pass_sensitive); gtk_utils_set_menu_items_sensitive (goban_window->item_factory, resign_sensitive, "/Play/Resign", NULL); gtk_widget_set_sensitive (goban_window->resign_button, resign_sensitive); gtk_utils_set_menu_items_sensitive (goban_window->item_factory, (goban_window->in_game_mode && !is_in_special_mode), "/Play/Adjourn Game", NULL); /* "Go" submenu. */ gtk_utils_set_menu_items_sensitive (goban_window->item_factory, previous_node_sensitive, "/Go/Previous Node", "/Go/Ten Nodes Backward", "/Go/Root Node", NULL); gtk_utils_set_toolbar_buttons_sensitive (goban_window->navigation_toolbar, previous_node_sensitive, &navigation_toolbar_back, &navigation_toolbar_root, NULL); gtk_utils_set_menu_items_sensitive (goban_window->item_factory, next_node_sensitive, "/Go/Next Node", "/Go/Ten Nodes Forward", "/Go/Variation Last Node", NULL); gtk_utils_set_toolbar_buttons_sensitive (goban_window->navigation_toolbar, next_node_sensitive, &navigation_toolbar_forward, &navigation_toolbar_variation_end, NULL); gtk_utils_set_menu_items_sensitive (goban_window->item_factory, previous_variation_sensitive, "/Go/Previous Variation", NULL); gtk_utils_set_toolbar_buttons_sensitive (goban_window->navigation_toolbar, previous_variation_sensitive, &navigation_toolbar_previous_variation, NULL); gtk_utils_set_menu_items_sensitive (goban_window->item_factory, next_variation_sensitive, "/Go/Next Variation", NULL); gtk_utils_set_toolbar_buttons_sensitive (goban_window->navigation_toolbar, next_variation_sensitive, &navigation_toolbar_next_variation, NULL); #ifdef GTK_TYPE_GO_TO_NAMED_NODE_DIALOG gtk_utils_set_menu_items_sensitive (goban_window->item_factory, !is_in_special_mode, "/Go/Go to Named Node...", NULL); #endif } static void update_set_player_to_move_commands (GtkGobanWindow *goban_window) { const SgfGameTree *game_tree = goban_window->current_tree; const gchar *menu_item_text; GtkWidget *menu_item; goban_window->updating_set_player_commands = TRUE; switch (game_tree->current_node->to_play_color) { case EMPTY: menu_item_text = "/Edit/Player to Move/By Game Rules"; break; case BLACK: menu_item_text = "/Edit/Player to Move/Black"; break; case WHITE: menu_item_text = "/Edit/Player to Move/White"; break; default: g_assert_not_reached (); return; } menu_item = gtk_item_factory_get_widget (goban_window->item_factory, menu_item_text); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menu_item), TRUE); menu_item = gtk_item_factory_get_widget (goban_window->item_factory, "/Edit/Player to Move/By Game Rules"); switch (sgf_utils_determine_player_to_move_by_rules (game_tree)) { case EMPTY: menu_item_text = _("By Game _Rules (Game Over)"); break; case BLACK: menu_item_text = _("By Game _Rules (Black)"); break; case WHITE: menu_item_text = _("By Game _Rules (White)"); break; } gtk_label_set_text_with_mnemonic (GTK_LABEL (GTK_BIN (menu_item)->child), menu_item_text); goban_window->updating_set_player_commands = FALSE; } static void insert_node_name (GtkGobanWindow *goban_window, const gchar *node_name) { static const gchar node_name_and_comment_separator = '\n'; GtkTextIter start_iterator; gtk_text_buffer_begin_user_action (goban_window->text_buffer); gtk_text_buffer_get_start_iter (goban_window->text_buffer, &start_iterator); gtk_text_buffer_insert_with_tags (goban_window->text_buffer, &start_iterator, node_name, -1, node_name_tag, NULL); gtk_text_buffer_insert_with_tags (goban_window->text_buffer, &start_iterator, &node_name_and_comment_separator, 1, node_name_tag, separator_tag, NULL); gtk_text_buffer_end_user_action (goban_window->text_buffer); } static void select_node_name (GtkGobanWindow *goban_window) { GtkTextIter start_iterator; GtkTextIter second_line_iterator; gtk_widget_grab_focus (GTK_WIDGET (goban_window->text_view)); if (!goban_window->node_name_inserted) { /* If it is not inserted, then there is no node name. Start with * a hint so that user knows what to do. */ insert_node_name (goban_window, _("insert node name here")); } gtk_text_buffer_get_start_iter (goban_window->text_buffer, &start_iterator); gtk_text_buffer_get_iter_at_line (goban_window->text_buffer, &second_line_iterator, 1); gtk_text_iter_backward_char (&second_line_iterator); gtk_text_buffer_select_range (goban_window->text_buffer, &second_line_iterator, &start_iterator); gtk_text_view_scroll_to_iter (goban_window->text_view, &start_iterator, 0.0, FALSE, 0.0, 0.0); } static void text_buffer_insert_text (GtkTextBuffer *text_buffer, GtkTextIter *insertion_iterator, const gchar *text, guint length, GtkGobanWindow *goban_window) { gint paragraph_delimiter_index; gint next_paragraph_start; gchar *new_text; gchar *new_text_pointer; gboolean first_time = TRUE; /* We only need to do anything if there is a node name in the buffer * and we are inserting something into it. Also don't accidentally * stop signal emission during undoing or redoing. */ if (!goban_window->node_name_inserted || gtk_text_iter_get_line (insertion_iterator) > 0 || quarry_text_buffer_is_undoing_or_redoing (QUARRY_TEXT_BUFFER (text_buffer))) return; /* Don't insert paragraph terminators in the node name. If there * are any, replace them with spaces and re-emit this signal. */ pango_find_paragraph_boundary (text, length, ¶graph_delimiter_index, &next_paragraph_start); if (paragraph_delimiter_index == length) return; /* We will not expand the text, only maybe shrink it. */ new_text = g_malloc (length); new_text_pointer = new_text; do { if (paragraph_delimiter_index > 0) { memcpy (new_text_pointer, text, paragraph_delimiter_index); new_text_pointer += paragraph_delimiter_index; } /* Insert a space if the paragraph was non-empty, or the * paragraph delimiter is at the very beginning/end of the * text. */ if (paragraph_delimiter_index > 0 || first_time || next_paragraph_start == length) *new_text_pointer++ = ' '; text += next_paragraph_start; length -= next_paragraph_start; first_time = FALSE; pango_find_paragraph_boundary (text, length, ¶graph_delimiter_index, &next_paragraph_start); } while (paragraph_delimiter_index < length); g_signal_stop_emission_by_name (text_buffer, "insert-text"); /* Block ourselves: there will not be any paragraphs this time. */ g_signal_handlers_block_by_func (text_buffer, text_buffer_insert_text, goban_window); gtk_text_buffer_insert (text_buffer, insertion_iterator, new_text, new_text_pointer - new_text); g_signal_handlers_unblock_by_func (text_buffer, text_buffer_insert_text, goban_window); g_free (new_text); } static void text_buffer_after_insert_text (GtkTextBuffer *text_buffer, GtkTextIter *insertion_iterator, const gchar *text, guint length, GtkGobanWindow *goban_window) { GtkTextIter start_iterator; if (!goban_window->node_name_inserted || (gtk_text_iter_get_offset (insertion_iterator) != g_utf8_strlen (text, length)) || quarry_text_buffer_is_undoing_or_redoing (QUARRY_TEXT_BUFFER (text_buffer))) return; /* We have inserted text before the node name. Apply the node name * tag to it. Note that `insertion_iterator' has been moved to * inserted text end by now. */ gtk_text_buffer_get_start_iter (text_buffer, &start_iterator); gtk_text_buffer_apply_tag (text_buffer, node_name_tag, &start_iterator, insertion_iterator); } static void text_buffer_mark_set (GtkTextBuffer *text_buffer, GtkTextIter *new_position_iterator, GtkTextMark *mark, GtkGobanWindow *goban_window) { GtkTextIter start_iterator; GtkTextIter bound_iterator; GtkTextIter node_name_end_iterator; if (!goban_window->node_name_inserted || mark != gtk_text_buffer_get_insert (text_buffer) || gtk_text_iter_get_line (new_position_iterator) == 0 || quarry_text_buffer_is_undoing_or_redoing (QUARRY_TEXT_BUFFER (text_buffer))) return; gtk_text_buffer_get_start_iter (text_buffer, &start_iterator); if (gtk_text_iter_get_char (&start_iterator) != '\n') return; gtk_text_buffer_get_iter_at_mark (text_buffer, &bound_iterator, (gtk_text_buffer_get_selection_bound (text_buffer))); if (gtk_text_iter_get_line (&bound_iterator) == 0) return; /* We have node name inserted in the text buffer, but it has become * empty and the cursor is somewhere else. Remove the node name * from the buffer. */ node_name_end_iterator = start_iterator; gtk_text_iter_forward_char (&node_name_end_iterator); gtk_text_buffer_begin_user_action (goban_window->text_buffer); gtk_text_buffer_delete (text_buffer, &start_iterator, &node_name_end_iterator); gtk_text_buffer_end_user_action (goban_window->text_buffer); } static void text_buffer_end_user_action (GtkTextBuffer *text_buffer, GtkGobanWindow *goban_window) { GtkTextIter start_iterator; GSList *tags; gtk_text_buffer_get_start_iter (text_buffer, &start_iterator); tags = gtk_text_iter_get_tags (&start_iterator); goban_window->node_name_inserted = (g_slist_find (tags, node_name_tag) != NULL); g_slist_free (tags); } static gboolean text_buffer_receive_undo_entry (QuarryTextBuffer *text_buffer, QuarryTextBufferUndoEntry *undo_entry, GtkGobanWindow *goban_window) { SgfGameTree *game_tree = goban_window->current_tree; SgfNode *node = game_tree->current_node; GtkGobanWindowUndoEntryData *undo_entry_data; if (game_tree->undo_history && (sgf_undo_history_is_last_applied_entry_single (game_tree->undo_history)) && (sgf_undo_history_check_last_applied_custom_entry_type (game_tree->undo_history, &quarry_text_buffer_undo_entry_data))) { undo_entry_data = ((GtkGobanWindowUndoEntryData *) (sgf_undo_history_get_last_applied_custom_entry_data (game_tree->undo_history))); if (quarry_text_buffer_combine_undo_entries (text_buffer, undo_entry_data->undo_entry, undo_entry)) { /* Entries combined. Return now. */ return TRUE; } } undo_entry_data = g_malloc (sizeof (GtkGobanWindowUndoEntryData)); /* Set to NULL so that quarry_text_buffer_redo() is not called this * time (it shouldn't.) */ undo_entry_data->goban_window = NULL; undo_entry_data->undo_entry = undo_entry; sgf_utils_apply_custom_undo_entry (game_tree, &quarry_text_buffer_undo_entry_data, undo_entry_data, node); if (game_tree->undo_history) undo_entry_data->goban_window = goban_window; return TRUE; } static void text_buffer_undo (GtkGobanWindowUndoEntryData *undo_entry_data) { if (undo_entry_data->goban_window) { quarry_text_buffer_undo ((QUARRY_TEXT_BUFFER (undo_entry_data->goban_window->text_buffer)), undo_entry_data->undo_entry); undo_entry_data->goban_window->text_buffer_modified = TRUE; } } static void text_buffer_redo (GtkGobanWindowUndoEntryData *undo_entry_data) { if (undo_entry_data->goban_window) { quarry_text_buffer_redo ((QUARRY_TEXT_BUFFER (undo_entry_data->goban_window->text_buffer)), undo_entry_data->undo_entry); undo_entry_data->goban_window->text_buffer_modified = TRUE; } } static void text_buffer_set_state_undo (GtkGobanWindowStateData *state_data) { if (state_data->goban_window) { GtkTextBuffer *text_buffer = state_data->goban_window->text_buffer; GtkTextIter start_iterator; GtkTextIter end_iterator; gtk_utils_block_signal_handlers (text_buffer, text_buffer_receive_undo_entry); gtk_text_buffer_get_bounds (text_buffer, &start_iterator, &end_iterator); gtk_text_buffer_delete (text_buffer, &start_iterator, &end_iterator); gtk_utils_unblock_signal_handlers (text_buffer, text_buffer_receive_undo_entry); quarry_text_buffer_set_state (QUARRY_TEXT_BUFFER (text_buffer), &state_data->state_before); } } static void text_buffer_set_state_redo (GtkGobanWindowStateData *state_data) { if (state_data->goban_window) { set_comment_and_node_name (state_data->goban_window, state_data->sgf_node_after); quarry_text_buffer_set_state (QUARRY_TEXT_BUFFER (state_data->goban_window->text_buffer), &state_data->state_after); } } static QuarryTextBufferState * update_comment_and_node_name_if_needed (GtkGobanWindow *goban_window, gboolean for_current_node) { SgfGameTree *current_tree = goban_window->current_tree; SgfGameTreeState current_tree_state; QuarryTextBufferState *text_buffer_state = NULL; if (!current_tree) return NULL; /* This is needed to suppress node changing signals. They are not * needed here and get in our way when `for_current_node' is FALSE. */ sgf_game_tree_get_state (current_tree, ¤t_tree_state); gtk_sgf_tree_signal_proxy_push_tree_state (current_tree, ¤t_tree_state); sgf_utils_begin_action (current_tree); if (fetch_comment_and_node_name (goban_window, for_current_node)) { GtkGobanWindowStateData *buffer_state = g_malloc (sizeof (GtkGobanWindowStateData)); GtkTextIter start_iterator; GtkTextIter end_iterator; gtk_text_buffer_get_bounds (goban_window->text_buffer, &start_iterator, &end_iterator); gtk_text_buffer_begin_user_action (goban_window->text_buffer); gtk_text_buffer_delete (goban_window->text_buffer, &start_iterator, &end_iterator); gtk_text_buffer_end_user_action (goban_window->text_buffer); buffer_state->goban_window = NULL; quarry_text_buffer_get_state (QUARRY_TEXT_BUFFER (goban_window->text_buffer), &buffer_state->state_before); buffer_state->sgf_node_after = current_tree->current_node; sgf_utils_apply_custom_undo_entry (current_tree, &quarry_text_buffer_state_data, buffer_state, NULL); if (current_tree->undo_history) { buffer_state->goban_window = goban_window; text_buffer_state = &buffer_state->state_after; sgf_undo_history_hide_last_applied_entry (current_tree->undo_history); } } sgf_utils_end_action (current_tree); /* In case we switched to `node' and it is different. */ sgf_utils_switch_to_given_node (current_tree, current_tree_state.current_node); gtk_sgf_tree_signal_proxy_pop_tree_state (current_tree, NULL); return text_buffer_state; } static gboolean fetch_comment_and_node_name (GtkGobanWindow *goban_window, gboolean for_current_node) { SgfGameTree *current_tree = goban_window->current_tree; SgfNode *node = (for_current_node ? current_tree->current_node : goban_window->last_displayed_node); gchar *new_comment; gchar *new_node_name = NULL; char *normalized_comment; char *normalized_node_name; GtkTextIter start_iterator; GtkTextIter end_iterator; gboolean any_changes; gtk_text_buffer_get_bounds (goban_window->text_buffer, &start_iterator, &end_iterator); if (goban_window->node_name_inserted) { GtkTextIter second_line_iterator; gtk_text_buffer_get_iter_at_line (goban_window->text_buffer, &second_line_iterator, 1); new_comment = gtk_text_iter_get_text (&second_line_iterator, &end_iterator); gtk_text_iter_backward_char (&second_line_iterator); new_node_name = gtk_text_iter_get_text (&start_iterator, &second_line_iterator); } else new_comment = gtk_text_iter_get_text (&start_iterator, &end_iterator); normalized_comment = sgf_utils_normalize_text (new_comment, 0); normalized_node_name = (new_node_name ? sgf_utils_normalize_text (new_node_name, 1) : NULL); any_changes = (sgf_utils_set_text_property (node, current_tree, SGF_COMMENT, normalized_comment, 0) || sgf_utils_set_text_property (node, current_tree, SGF_NODE_NAME, normalized_node_name, 0)); g_free (new_comment); g_free (new_node_name); return any_changes; } static void set_move_number (GtkGobanWindow *goban_window) { SgfGameTree *game_tree = goban_window->current_tree; GtkWidget *dialog = quarry_move_number_dialog_new (); QuarryMoveNumberDialog *move_number_dialog = QUARRY_MOVE_NUMBER_DIALOG (dialog); int move_number; gtk_window_set_title (GTK_WINDOW (dialog), _("Set Move Number")); gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (goban_window)); quarry_move_number_dialog_set_sequential_move_number (move_number_dialog, sgf_utils_get_sequential_move_number (game_tree)); if (sgf_node_get_number_property_value (game_tree->current_node, SGF_MOVE_NUMBER, &move_number)) { quarry_move_number_dialog_set_specific_move_number (move_number_dialog, move_number); quarry_move_number_dialog_set_use_sequential_move_number (move_number_dialog, FALSE); } else { quarry_move_number_dialog_set_use_sequential_move_number (move_number_dialog, TRUE); } if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) { int made_changes; if (quarry_move_number_dialog_get_use_sequential_move_number (move_number_dialog)) { made_changes = sgf_utils_delete_property (game_tree->current_node, game_tree, SGF_MOVE_NUMBER, 0); } else { move_number = (quarry_move_number_dialog_get_specific_move_number (move_number_dialog)); made_changes = sgf_utils_set_number_property (game_tree->current_node, game_tree, SGF_MOVE_NUMBER, move_number, 0); } if (made_changes) update_move_information (goban_window); } gtk_widget_destroy (dialog); } static void set_player_to_move (GtkGobanWindow *goban_window, guint callback_action, GtkCheckMenuItem *menu_item) { if (gtk_check_menu_item_get_active (menu_item) && !goban_window->updating_set_player_commands) { SgfGameTree *game_tree = goban_window->current_tree; SgfNode *node = game_tree->current_node; int created_new_node = 0; int player_to_move_changed; sgf_utils_begin_action (game_tree); if (IS_STONE (callback_action) && IS_STONE (game_tree->current_node->move_color)) { node = sgf_utils_append_variation (game_tree, EMPTY); created_new_node = 1; } player_to_move_changed = sgf_utils_set_color_property (node, game_tree, SGF_TO_PLAY, callback_action, 0); sgf_utils_end_action (game_tree); if (created_new_node) update_children_for_new_node (goban_window, FALSE, FALSE); else if (player_to_move_changed) { update_move_information (goban_window); update_set_player_to_move_commands (goban_window); } } } static int initialize_gtp_player (GtpClient *client, int successful, GtkGobanWindow *goban_window, ...) { const SgfGameTree *game_tree = goban_window->current_tree; const SgfNode *root_node = game_tree->root; int client_color = (client == goban_window->players[BLACK_INDEX] ? BLACK : WHITE); int client_color_index = COLOR_INDEX (client_color); int *initialization_step = (goban_window->player_initialization_step + client_color_index); if (!successful) { /* This should be the name as displayed in the Preferences dialog * and elsewhere, but let's not bother; we don't have pointers to * `GtpEngineListItem's currently. */ gchar* engine_name = g_strdup_printf ((client->engine_version ? "%s %s" : "%s"), client->engine_name, client->engine_version); gchar* message; int engine_error = 1; GtkWidget *error_dialog; g_return_val_if_fail (*initialization_step != INITIALIZATION_NOT_STARTED, 0); switch (*initialization_step) { case INITIALIZATION_GAME_SET: /* TRANSLATORS: Note that game name will be in `normal' form. */ message = g_strdup_printf (_("GTP engine `%s' reported it could handle " "%s game, but failed to initialize itself " "for it"), engine_name, _(game_info[game_tree->game].name)); break; case INITIALIZATION_BOARD_SIZE_SET: message = g_strdup_printf (_("GTP engine `%s' cannot handle %dx%d board " "size, sorry"), engine_name, game_tree->board_width, game_tree->board_width); engine_error = 0; break; case INITIALIZATION_BOARD_CLEARED: message = g_strdup_printf (_("GTP engine `%s' failed to clean " "the board"), engine_name); break; case INITIALIZATION_TIME_LIMITS_SET: message = g_strdup_printf (_("GTP engine `%s' failed to set initial " "time limits (it could ignore them, but " "not fail)"), engine_name); break; case INITIALIZATION_FIXED_HANDICAP_SET: case INITIALIZATION_FREE_HANDICAP_PLACED: message = g_strdup_printf (_("GTP engine `%s' failed to set handicap " "stones on board"), engine_name); break; default: g_assert_not_reached (); return 0; } error_dialog = quarry_message_dialog_new (GTK_WINDOW (goban_window), GTK_BUTTONS_OK, GTK_STOCK_DIALOG_ERROR, (engine_error ? _("This is an engine error. " "You may want to report it " "to engine authors.") : NULL), "%s", message); g_free (message); g_free (engine_name); gtk_widget_destroy (GTK_WIDGET (goban_window)); gtk_utils_show_and_forget_dialog (GTK_DIALOG (error_dialog)); return 0; } /* These special cases are needed to avoid nasty `goto's in `switch' * block below. */ if (*initialization_step == INITIALIZATION_FIXED_HANDICAP_SET) { /* FIXME: Validate handicap position. */ *initialization_step = INITIALIZATION_HANDICAP_SET; } else if (*initialization_step == INITIALIZATION_FREE_HANDICAP_PLACED) { va_list arguments; va_start (arguments, goban_window); free_handicap_has_been_placed (goban_window, va_arg (arguments, BoardPositionList *)); va_end (arguments); *initialization_step = INITIALIZATION_HANDICAP_SET; } /* Note that `case' branches here often fall through to next ones. * Often certain initializations are just not needed at all. */ switch (*initialization_step) { case INITIALIZATION_NOT_STARTED: if (gtp_client_is_known_command (client, "set_game")) { *initialization_step = INITIALIZATION_GAME_SET; gtp_client_set_game (client, (GtpClientResponseCallback) initialize_gtp_player, goban_window, game_tree->game); break; } case INITIALIZATION_GAME_SET: *initialization_step = INITIALIZATION_BOARD_SIZE_SET; g_assert (game_tree->board_width == game_tree->board_height); gtp_client_set_board_size (client, ((GtpClientResponseCallback) initialize_gtp_player), goban_window, game_tree->board_width); break; case INITIALIZATION_BOARD_SIZE_SET: *initialization_step = INITIALIZATION_BOARD_CLEARED; gtp_client_clear_board (client, (GtpClientResponseCallback) initialize_gtp_player, goban_window); break; case INITIALIZATION_BOARD_CLEARED: { TimeControl *time_control = goban_window->time_controls[client_color_index]; if (time_control) { *initialization_step = INITIALIZATION_TIME_LIMITS_SET; gtp_client_send_time_settings (client, ((GtpClientResponseCallback) initialize_gtp_player), goban_window, time_control->main_time, time_control->overtime_length, time_control->moves_per_overtime); break; } } case INITIALIZATION_TIME_LIMITS_SET: if (game_tree->game == GAME_GO) { int handicap = sgf_node_get_handicap (root_node); if (handicap > 0) { gboolean is_fixed_handicap = FALSE; const BoardPositionList *handicap_stones = sgf_node_get_list_of_point_property_value (root_node, SGF_ADD_BLACK); if (handicap_stones && (handicap_stones->num_positions <= go_get_max_fixed_handicap (game_tree->board_width, game_tree->board_height))) { BoardPositionList *fixed_handicap_stones = go_get_fixed_handicap_stones (game_tree->board_width, game_tree->board_height, handicap); if (board_position_lists_are_equal (fixed_handicap_stones, handicap_stones)) is_fixed_handicap = TRUE; board_position_list_delete (fixed_handicap_stones); } if (is_fixed_handicap) { *initialization_step = INITIALIZATION_FIXED_HANDICAP_SET; gtp_client_set_fixed_handicap (client, ((GtpClientResponseCallback) initialize_gtp_player), goban_window, handicap); break; } else { if (client_color == BLACK || !goban_window->pending_free_handicap) { *initialization_step = INITIALIZATION_FREE_HANDICAP_PLACED; gtp_client_place_free_handicap (client, ((GtpClientFreeHandicapCallback) initialize_gtp_player), goban_window, handicap); break; } else { /* Note that if `handicap_stones' are not set, then free * handicap placement has not been performed yet by the * black player (either another engine or the user). In * this case we just skip this step for now. When the * placement is determined, handicap will be set for this * client from free_handicap_has_been_placed(). */ if (handicap_stones) { gtp_client_set_free_handicap (client, NULL, NULL, handicap_stones); } } } } } case INITIALIZATION_HANDICAP_SET: if (game_tree->game == GAME_GO) { double komi; if (!sgf_node_get_komi (game_tree->current_node, &komi)) { /* Recently suggested default komi is 6.5, but if a game lacks * `KM' property it is more likely to be old. */ komi = (sgf_node_get_handicap (root_node) > 0 ? 0.5 : 5.5); } gtp_client_set_komi (client, NULL, NULL, komi); } *initialization_step = INITIALIZATION_COMPLETE; { const SgfNode *node; for (node = root_node; node; node = node->current_variation) { if (IS_STONE (node->move_color)) { gtp_client_play_move_from_sgf_node (client, NULL, NULL, game_tree, node); } } } if (client_color == goban_window->game_position.board_state->color_to_play) { generate_move_via_gtp (goban_window); start_clock_if_needed (goban_window); } break; default: /* Must never happen. */ g_assert_not_reached (); } return 1; } static void free_handicap_has_been_placed (GtkGobanWindow *goban_window, BoardPositionList *handicap_stones) { sgf_utils_add_free_handicap_stones (goban_window->current_tree, handicap_stones); reenter_current_node (goban_window); g_assert (goban_window->game_position.board_state->color_to_play == WHITE); if (GTP_ENGINE_CAN_PLAY_MOVES (goban_window, WHITE)) { /* The engine is initialized, but since free handicap placement * only became known at this point, the engine doesn't know about * it yet. */ gtp_client_set_free_handicap (goban_window->players[WHITE_INDEX], NULL, NULL, handicap_stones); generate_move_via_gtp (goban_window); } if (USER_IS_TO_PLAY (goban_window) || GTP_ENGINE_CAN_PLAY_MOVES (goban_window, WHITE)) start_clock_if_needed (goban_window); } static void move_has_been_played (GtkGobanWindow *goban_window) { /* This may be either the displayed board or an ``off-screen'' * board. In either case, it stores the game position. See * move_has_been_generated(). */ const Board *board = goban_window->current_tree->board; SgfNode *move_node = goban_window->game_position.board_state->last_move_node; TimeControl *time_control = goban_window->time_controls[COLOR_INDEX (move_node->move_color)]; int color_to_play = goban_window->game_position.board_state->color_to_play; if (time_control) { time_control_stop (time_control, NULL); gtk_clock_time_control_state_changed (goban_window->clocks[COLOR_INDEX (move_node->move_color)]); time_control_save_state_in_sgf_node (time_control, move_node, goban_window->current_tree, move_node->move_color, 0); } if (GTP_ENGINE_CAN_PLAY_MOVES (goban_window, OTHER_COLOR (move_node->move_color))) { GtpClient *other_player = goban_window->players[COLOR_INDEX (OTHER_COLOR (move_node->move_color))]; /* Other player is a GTP engine which is already initialized. * Inform it about the move that has just been played. */ gtp_client_play_move_from_sgf_node (other_player, NULL, NULL, goban_window->current_tree, move_node); } if (!board_is_game_over (board, RULE_SET_DEFAULT, color_to_play)) { if (GTP_ENGINE_CAN_PLAY_MOVES (goban_window, color_to_play)) { /* If the next move is to be played by a GTP engine and the engine * is ready, ask for a move now. */ generate_move_via_gtp (goban_window); } else if (goban_window->players[COLOR_INDEX (color_to_play)]) return; start_clock_if_needed (goban_window); } else { SgfNode *game_info_node = goban_window->game_position.board_state->game_info_node; switch (board->game) { case GAME_GO: { int player; goban_window->dead_stones = g_malloc (BOARD_GRID_SIZE * sizeof (char)); board_fill_grid (board, goban_window->dead_stones, 0); goban_window->scoring_engine_player = -1; for (player = 0; player < NUM_COLORS; player++) { if (goban_window->players[player]) { goban_window->dead_stones_list = NULL; goban_window->engine_scoring_cancelled = FALSE; goban_window->scoring_progress_dialog = ((GtkProgressDialog *) gtk_progress_dialog_new (NULL, "Quarry", _("GTP engine is scoring..."), NULL, ((GtkProgressDialogCallback) cancel_scoring), goban_window)); gtk_progress_dialog_set_fraction ((goban_window ->scoring_progress_dialog), 0.0, NULL); goban_window->scoring_engine_player = player; gtp_client_final_status_list (goban_window->players[player], (GtpClientFinalStatusListCallback) engine_has_scored, goban_window, GTP_DEAD); /* Note that we skip leave_game_mode() below in this case. * One reason is that we need the game position intact. */ return; } } enter_scoring_mode (goban_window); } break; case GAME_AMAZONS: { char *result = utils_duplicate_string (move_node->move_color == BLACK ? "B+" : "W+"); sgf_utils_set_text_property (game_info_node, goban_window->current_tree, SGF_RESULT, result, 1); } break; case GAME_REVERSI: { int num_black_disks; int num_white_disks; reversi_count_disks (board, &num_black_disks, &num_white_disks); sgf_utils_set_score_result (game_info_node, goban_window->current_tree, num_black_disks - num_white_disks, 1); } break; default: g_assert_not_reached (); } leave_game_mode (goban_window); } } static void engine_has_scored (GtpClient *client, int successful, GtkGobanWindow *goban_window, GtpStoneStatus status, BoardPositionList *dead_stones) { int player; UNUSED (client); if (goban_window->engine_scoring_cancelled) return; if (successful) { g_assert (status == GTP_DEAD); board_position_list_mark_on_grid (dead_stones, goban_window->dead_stones, 1); } for (player = goban_window->scoring_engine_player + 1; player < NUM_COLORS; player++) { if (goban_window->players[player]) { /* Store dead stone list of first engine and let second engine * score. */ goban_window->dead_stones_list = board_position_list_duplicate (dead_stones); gtk_progress_dialog_set_fraction (goban_window->scoring_progress_dialog, 0.5, NULL); goban_window->scoring_engine_player = player; gtp_client_final_status_list (goban_window->players[player], ((GtpClientFinalStatusListCallback) engine_has_scored), goban_window, GTP_DEAD); break; } } if (goban_window->scoring_engine_player != player) { gtk_widget_destroy ((GtkWidget*) goban_window->scoring_progress_dialog); if (!goban_window->dead_stones_list || !board_position_lists_are_equal (goban_window->dead_stones_list, dead_stones)) { /* Either one human player or engines disagree. */ if (!IS_DISPLAYING_GAME_NODE (goban_window)) { switch_to_given_node (goban_window, goban_window->game_position.current_node); } enter_scoring_mode (goban_window); } else { /* Need to add scoring results to the proper node. */ if (!IS_DISPLAYING_GAME_NODE (goban_window)) { gtk_sgf_tree_signal_proxy_push_tree_state (goban_window->current_tree, &goban_window->game_position); } handle_go_scoring_results (goban_window); if (IS_DISPLAYING_GAME_NODE (goban_window)) reenter_current_node (goban_window); else { gtk_sgf_tree_signal_proxy_pop_tree_state (goban_window->current_tree, NULL); } } if (goban_window->dead_stones_list) { board_position_list_delete (goban_window->dead_stones_list); goban_window->dead_stones_list = NULL; } leave_game_mode (goban_window); } } static void cancel_scoring (GtkProgressDialog *progress_dialog, GtkGobanWindow *goban_window) { /* TODO: Would be nice to tell the GTP client about the * cancellation. /mh * * With GTP 2 it is not possible to tell the engine to cancel * a command execution. Or do you mean to have the client not * invoke engine_has_scored() callback? That might be a good * idea. /pp */ goban_window->engine_scoring_cancelled = TRUE; gtk_widget_destroy (GTK_WIDGET (progress_dialog)); if (!IS_DISPLAYING_GAME_NODE (goban_window)) { switch_to_given_node (goban_window, goban_window->game_position.current_node); } enter_scoring_mode (goban_window); leave_game_mode (goban_window); } static void enter_scoring_mode (GtkGobanWindow *goban_window) { GtkWidget *scoring_tool_menu_item = gtk_item_factory_get_widget (goban_window->item_factory, "/Edit/Tools/Scoring Tool"); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (scoring_tool_menu_item), TRUE); } static void move_has_been_generated (GtpClient *client, int successful, GtkGobanWindow *goban_window, int color, int x, int y, BoardAbstractMoveData *move_data) { UNUSED (client); /* If the engine has run out of time, we are not in game mode by * now. */ if (goban_window->in_game_mode && successful) { SgfGameTree *current_tree = goban_window->current_tree; if (x == RESIGNATION_X && y == RESIGNATION_Y) { do_resign_game (goban_window); return; } if (!IS_DISPLAYING_GAME_NODE (goban_window)) { gtk_sgf_tree_signal_proxy_push_tree_state (current_tree, &goban_window->game_position); } /* FIXME: Validate move and alert if it is illegal. */ if (goban_window->current_tree->game != GAME_AMAZONS) sgf_utils_append_variation (current_tree, color, x, y); else { sgf_utils_append_variation (current_tree, color, x, y, move_data->amazons); } move_has_been_played (goban_window); if (IS_DISPLAYING_GAME_NODE (goban_window)) update_children_for_new_node (goban_window, TRUE, FALSE); else { gtk_sgf_tree_signal_proxy_pop_tree_state (current_tree, &goban_window->game_position); show_sgf_tree_view_automatically (goban_window, goban_window->game_position.current_node); } } } static void generate_move_via_gtp (GtkGobanWindow *goban_window) { int color_to_play = goban_window->game_position.board_state->color_to_play; int color_to_play_index = COLOR_INDEX (color_to_play); TimeControl *time_control = goban_window->time_controls[color_to_play_index]; if (time_control) { int moves_left; double seconds_left = time_control_get_time_left (time_control, &moves_left); /* FIXME: OUT_OF_TIME shouldn't really happen here. * * Check if it still happens. Time control handling has * been significantly improved since this FIXME was added. */ if (seconds_left != NO_TIME_LIMITS && seconds_left != OUT_OF_TIME) { gtp_client_send_time_left (goban_window->players[color_to_play_index], NULL, NULL, color_to_play, floor (seconds_left + 0.5), moves_left); } } gtp_client_generate_move (goban_window->players[color_to_play_index], (GtpClientMoveCallback) move_has_been_generated, goban_window, color_to_play); } static void start_clock_if_needed (GtkGobanWindow *goban_window) { int color_to_play_index = COLOR_INDEX (goban_window->game_position.board_state->color_to_play); if (goban_window->time_controls[color_to_play_index]) { time_control_start (goban_window->time_controls[color_to_play_index]); gtk_clock_time_control_state_changed (goban_window->clocks[color_to_play_index]); } } /* FIXME; Almost identical to do_resign_game(). */ static void player_is_out_of_time (GtkClock *clock, GtkGobanWindow *goban_window) { int winner_color_char = (goban_window->clocks[BLACK_INDEX] == clock ? 'W' : 'B'); SgfNode *game_info_node = goban_window->sgf_board_state.game_info_node; leave_game_mode (goban_window); sgf_utils_set_text_property (game_info_node, goban_window->current_tree, SGF_RESULT, utils_cprintf ("%c+Time", winner_color_char), 1); sgf_utils_append_variation (goban_window->current_tree, EMPTY); update_children_for_new_node (goban_window, TRUE, FALSE); } /* Various editing functions. */ static void undo_operation (GtkGobanWindow *goban_window) { goban_window->text_buffer_modified = FALSE; sgf_utils_undo (goban_window->current_tree); update_children_for_new_node (goban_window, TRUE, goban_window->text_buffer_modified); } static void redo_operation (GtkGobanWindow *goban_window) { goban_window->text_buffer_modified = FALSE; sgf_utils_redo (goban_window->current_tree); update_children_for_new_node (goban_window, TRUE, goban_window->text_buffer_modified); } static void cut_operation (GtkGobanWindow *goban_window) { copy_operation (goban_window); delete_current_node (goban_window); } static void copy_operation (GtkGobanWindow *goban_window) { SgfGameTree *sgf_tree = goban_window->current_tree; SgfCopyData *sgf_data = g_malloc (sizeof (SgfCopyData)); static const GtkTargetEntry target = { SGF_MIME_TYPE, 0, 0 }; sgf_data->sgf = sgf_utils_create_subtree_sgf (sgf_tree, sgf_tree->current_node, &sgf_data->sgf_length); gtk_clipboard_set_with_data (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD), &target, 1, get_copied_sgf, delete_copied_sgf, sgf_data); } static void paste_operation (GtkGobanWindow *goban_window) { gtk_clipboard_request_contents (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD), gdk_atom_intern (SGF_MIME_TYPE, FALSE), receive_copied_sgf, goban_window); } static void get_copied_sgf (GtkClipboard *clipboard, GtkSelectionData *selection_data, guint format, gpointer user_data) { SgfCopyData *sgf_data = (SgfCopyData *) user_data; UNUSED (clipboard); UNUSED (format); gtk_selection_data_set (selection_data, selection_data->target, 8, sgf_data->sgf, sgf_data->sgf_length); } static void delete_copied_sgf (GtkClipboard *clipboard, gpointer user_data) { SgfCopyData *sgf_data = (SgfCopyData *) user_data; UNUSED (clipboard); utils_free (sgf_data->sgf); g_free (sgf_data); } static void receive_copied_sgf (GtkClipboard *clipboard, GtkSelectionData *selection_data, gpointer user_data) { static const gchar *not_clipboard_sgf_message = N_("Unable to paste game record fragment from clipboard since it is not " "intended for pasting"); static const gchar *not_clipboard_sgf_hint = N_("Clipboard SGF probably contains more than one game tree or " "not a single child of the root of the only game tree."); static const gchar *couldnt_paste_message = N_("Unable to paste game record fragment from clipboard"); static const gchar *couldnt_paste_hint /* TRANSLATORS: This message is shown if you e.g. copy a part of 13x13 game tree and try to paste it into a 19x19 game tree; or copy a part of a Reversi game tree and try to paste it into a Go game tree. */ = N_("Clipboard game record fragment must be of different game " "or board size."); static const gchar *invalid_sgf_message = N_("Clipboard contains an invalid game record fragment (SGF)"); GtkGobanWindow *goban_window = (GtkGobanWindow *) user_data; SgfGameTree *sgf_tree = goban_window->current_tree; SgfPasteResult result; GtkWidget *error_dialog; const gchar *message = NULL; const gchar *hint = NULL; UNUSED (clipboard); if (selection_data->type != gdk_atom_intern (SGF_MIME_TYPE, FALSE)) return; if (selection_data->length <= 0) return; result = sgf_utils_paste_sgf (sgf_tree, sgf_tree->current_node, selection_data->data, selection_data->length); switch (result) { case SGF_PASTED: return; case SGF_NOT_CLIPBOARD_SGF: message = _(not_clipboard_sgf_message); hint = _(not_clipboard_sgf_hint); break; case SGF_COULDNT_PASTE: message = _(couldnt_paste_message); hint = _(couldnt_paste_hint); break; case SGF_INVALID_SGF: message = _(invalid_sgf_message); hint = NULL; break; } error_dialog = quarry_message_dialog_new (GTK_WINDOW (goban_window), GTK_BUTTONS_OK, GTK_STOCK_DIALOG_ERROR, hint, message); gtk_utils_show_and_forget_dialog (GTK_DIALOG (error_dialog)); } static void append_empty_variation (GtkGobanWindow *goban_window) { sgf_utils_append_variation (goban_window->current_tree, EMPTY); update_children_for_new_node (goban_window, TRUE, FALSE); } static void swap_adjacent_branches (GtkGobanWindow *goban_window, guint use_previous_branch) { SgfGameTree *game_tree = goban_window->current_tree; SgfNode *swap_with = (use_previous_branch ? sgf_node_get_previous_node (game_tree->current_node) : game_tree->current_node->next); sgf_utils_swap_current_node_with (game_tree, swap_with); update_commands_sensitivity (goban_window); } static void delete_current_node (GtkGobanWindow *goban_window) { sgf_utils_delete_current_node (goban_window->current_tree); update_children_for_new_node (goban_window, TRUE, FALSE); } static void delete_current_node_children (GtkGobanWindow *goban_window) { sgf_utils_delete_current_node_children (goban_window->current_tree); update_commands_sensitivity (goban_window); } static void activate_move_tool (GtkGobanWindow *goban_window, guint callback_action, GtkCheckMenuItem *menu_item) { UNUSED (callback_action); if (gtk_check_menu_item_get_active (menu_item)) { synchronize_tools_menus (goban_window); set_goban_signal_handlers (goban_window, G_CALLBACK (playing_mode_pointer_moved), G_CALLBACK (playing_mode_goban_clicked)); } } static void activate_setup_tool (GtkGobanWindow *goban_window, guint callback_action, GtkCheckMenuItem *menu_item) { UNUSED (callback_action); if (gtk_check_menu_item_get_active (menu_item)) { synchronize_tools_menus (goban_window); set_goban_signal_handlers (goban_window, G_CALLBACK (setup_mode_pointer_moved), G_CALLBACK (setup_mode_goban_clicked)); } } static void activate_scoring_tool (GtkGobanWindow *goban_window, guint callback_action, GtkCheckMenuItem *menu_item) { UNUSED (callback_action); if (gtk_check_menu_item_get_active (menu_item)) { synchronize_tools_menus (goban_window); if (goban_window->in_game_mode) g_assert (goban_window->dead_stones); else { const SgfNode *current_node = goban_window->current_tree->current_node; const BoardPositionList *black_territory = sgf_node_get_list_of_point_property_value (current_node, SGF_BLACK_TERRITORY); const BoardPositionList *white_territory = sgf_node_get_list_of_point_property_value (current_node, SGF_WHITE_TERRITORY); g_assert (!goban_window->dead_stones); goban_window->dead_stones = g_malloc (BOARD_GRID_SIZE * sizeof (char)); board_fill_grid (goban_window->board, goban_window->dead_stones, 0); go_guess_dead_stones (goban_window->board, goban_window->dead_stones, black_territory, white_territory); } enter_special_mode (goban_window, _("Please select dead stones\nto score the game"), go_scoring_mode_done, (goban_window->in_game_mode ? NULL : go_scoring_mode_cancel)); set_goban_signal_handlers (goban_window, G_CALLBACK (go_scoring_mode_pointer_moved), G_CALLBACK (go_scoring_mode_goban_clicked)); update_territory_markup (goban_window); update_commands_sensitivity (goban_window); } else { /* Switching to a different tool, cancel scoring. * go_scoring_mode_done() also indirectly calls this function, and * in that case we actually leave scoring mode, not cancel it. */ g_free (goban_window->dead_stones); goban_window->dead_stones = NULL; leave_special_mode (goban_window); } } static void activate_markup_tool (GtkGobanWindow *goban_window, gint sgf_markup_type, GtkCheckMenuItem *menu_item) { if (gtk_check_menu_item_get_active (menu_item)) { synchronize_tools_menus (goban_window); goban_window->sgf_markup_type = sgf_markup_type; set_goban_signal_handlers (goban_window, G_CALLBACK (markup_mode_pointer_moved), G_CALLBACK (markup_mode_goban_clicked)); } } static void activate_label_tool (GtkGobanWindow *goban_window, gint labels_mode, GtkCheckMenuItem *menu_item) { if (gtk_check_menu_item_get_active (menu_item)) { if (labels_mode != goban_window->labels_mode) { utils_free (goban_window->next_sgf_label); goban_window->next_sgf_label = NULL; goban_window->labels_mode = labels_mode; synchronize_tools_menus (goban_window); set_goban_signal_handlers (goban_window, G_CALLBACK (label_mode_pointer_moved), G_CALLBACK (label_mode_goban_clicked)); } } else { /* Switching to a different tool, cancel label mode. */ utils_free (goban_window->next_sgf_label); goban_window->next_sgf_label = NULL; gtk_goban_set_label_feedback (goban_window->goban, NULL_X, NULL_Y, NULL, 0); goban_window->labels_mode = GTK_GOBAN_WINDOW_NON_LABELS_MODE; } } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/gtk-go-to-named-node-dialog.c0000644000175000017500000002525010520664527021065 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "gtk-go-to-named-node-dialog.h" #ifdef GTK_TYPE_GO_TO_NAMED_NODE_DIALOG #include "gtk-preferences.h" #include "gtk-utils.h" #include "gui-back-end.h" #include "quarry-stock.h" #include "time-control.h" #include "sgf.h" #include #include enum { NODE_NAME, NODE_OBJECT, NUM_COLUMNS }; static void gtk_go_to_named_node_dialog_class_init (GtkGoToNamedNodeDialogClass *class); static void gtk_go_to_named_node_dialog_init (GtkGoToNamedNodeDialog *dialog); static void gtk_go_to_named_node_dialog_finalize (GObject *object); static void free_node_list (const char *node_name, GSList *node_list); static void entered_node_name_changed (GtkEntry *node_name_entry, GtkGoToNamedNodeDialog *dialog); static gboolean match_selected (GtkGoToNamedNodeDialog *dialog, GtkTreeModel *tree_model, GtkTreeIter *iterator); static void set_selected_node (GtkGoToNamedNodeDialog *dialog, SgfNode *sgf_node); static GtkDialogClass *parent_class; static GtkTextTag *special_comment_tag; static GtkTextTagTable *dialog_tag_table; GType gtk_go_to_named_node_dialog_get_type (void) { static GType go_to_named_node_dialog_type = 0; if (!go_to_named_node_dialog_type) { static GTypeInfo go_to_named_node_dialog_info = { sizeof (GtkGoToNamedNodeDialogClass), NULL, NULL, (GClassInitFunc) gtk_go_to_named_node_dialog_class_init, NULL, NULL, sizeof (GtkGoToNamedNodeDialog), 0, (GInstanceInitFunc) gtk_go_to_named_node_dialog_init, NULL }; go_to_named_node_dialog_type = g_type_register_static (GTK_TYPE_DIALOG, "GtkGoToNamedNodeDialog", &go_to_named_node_dialog_info, 0); } return go_to_named_node_dialog_type; } static void gtk_go_to_named_node_dialog_class_init (GtkGoToNamedNodeDialogClass *class) { parent_class = g_type_class_peek_parent (class); G_OBJECT_CLASS (class)->finalize = gtk_go_to_named_node_dialog_finalize; /* Create the text tag and tag table that will be used in all * dialogs. The tag is used to emphasize "There is no such node" * text. */ special_comment_tag = gtk_text_tag_new (NULL); g_object_set (special_comment_tag, "style", PANGO_STYLE_ITALIC, NULL); dialog_tag_table = gtk_text_tag_table_new (); gui_back_end_register_object_to_finalize (dialog_tag_table); gtk_text_tag_table_add (dialog_tag_table, special_comment_tag); g_object_unref (special_comment_tag); } static void gtk_go_to_named_node_dialog_init (GtkGoToNamedNodeDialog *dialog) { GtkWidget *entry; GtkWidget *name_label; GtkWidget *hbox; GtkWidget *comment_label; GtkWidget *text_view_widget; GtkTextView *text_view; GtkWidget *scrolled_window; GtkWidget *vbox1; GtkWidget *vbox2; gtk_window_set_title (GTK_WINDOW (dialog), _("Go to Named Node")); entry = gtk_utils_create_entry (NULL, RETURN_ACTIVATES_DEFAULT); gtk_entry_set_width_chars (GTK_ENTRY (entry), 30); dialog->entry_changed_handler_id = g_signal_connect (entry, "changed", G_CALLBACK (entered_node_name_changed), dialog); dialog->entry_completion = gtk_entry_completion_new (); gtk_entry_set_completion (GTK_ENTRY (entry), dialog->entry_completion); g_signal_connect_swapped (dialog->entry_completion, "match-selected", G_CALLBACK (match_selected), dialog); name_label = gtk_utils_create_mnemonic_label (_("Node _name:"), entry); hbox = gtk_utils_pack_in_box (GTK_TYPE_HBOX, QUARRY_SPACING, name_label, GTK_UTILS_FILL, entry, GTK_UTILS_PACK_DEFAULT, NULL); comment_label = gtk_label_new (_("Node comment:")); gtk_utils_create_size_group (GTK_SIZE_GROUP_HORIZONTAL, name_label, comment_label, NULL); dialog->comment_buffer = gtk_text_buffer_new (dialog_tag_table); text_view_widget = gtk_text_view_new_with_buffer (dialog->comment_buffer); text_view = GTK_TEXT_VIEW (text_view_widget); gtk_text_view_set_editable (text_view, FALSE); gtk_text_view_set_left_margin (text_view, QUARRY_SPACING_VERY_SMALL); gtk_text_view_set_right_margin (text_view, QUARRY_SPACING_VERY_SMALL); gtk_text_view_set_wrap_mode (text_view, GTK_WRAP_WORD); scrolled_window = gtk_utils_make_widget_scrollable (text_view_widget, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); vbox1 = gtk_utils_pack_in_box (GTK_TYPE_VBOX, QUARRY_SPACING_SMALL, gtk_utils_align_widget (comment_label, 0.0, 0.0), GTK_UTILS_FILL, scrolled_window, GTK_UTILS_PACK_DEFAULT, NULL); dialog->comment_widgets = vbox1; vbox2 = gtk_utils_pack_in_box (GTK_TYPE_VBOX, QUARRY_SPACING, hbox, GTK_UTILS_FILL, vbox1, GTK_UTILS_PACK_DEFAULT, NULL); gtk_widget_show_all (vbox2); gtk_utils_standardize_dialog (&dialog->dialog, vbox2); gtk_dialog_add_buttons (&dialog->dialog, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, QUARRY_STOCK_GO_TO_NODE, GTK_RESPONSE_OK, NULL); gtk_dialog_set_default_response (&dialog->dialog, GTK_RESPONSE_OK); gtk_dialog_set_response_sensitive (&dialog->dialog, GTK_RESPONSE_OK, FALSE); gtk_dialog_set_has_separator (&dialog->dialog, FALSE); set_selected_node (dialog, NULL); } GtkWidget * gtk_go_to_named_node_dialog_new (SgfGameTree *sgf_tree) { SgfNode *sgf_node; GTree *completion_tree; GtkListStore *completions = gtk_list_store_new (NUM_COLUMNS, G_TYPE_STRING, G_TYPE_POINTER); g_return_val_if_fail (sgf_tree, NULL); /* Note: cannot use value destructor here, because we build values * ``incrementally'' with g_tree_replace() below. */ completion_tree = g_tree_new ((GCompareFunc) strcmp); for (sgf_node = sgf_game_tree_traverse_forward (sgf_tree); sgf_node; sgf_node = sgf_node_traverse_forward (sgf_node)) { const char *node_name = sgf_node_get_text_property_value (sgf_node, SGF_NODE_NAME); if (node_name) { GtkTreeIter iterator; GSList *node_list; node_list = g_tree_lookup (completion_tree, node_name); g_tree_replace (completion_tree, (gpointer) node_name, g_slist_append (node_list, sgf_node)); gtk_list_store_append (completions, &iterator); gtk_list_store_set (completions, &iterator, NODE_NAME, node_name, NODE_OBJECT, sgf_node, -1); } } if (g_tree_nnodes (completion_tree) > 0) { GObject *dialog_object = g_object_new (GTK_TYPE_GO_TO_NAMED_NODE_DIALOG, NULL); GtkGoToNamedNodeDialog *dialog = GTK_GO_TO_NAMED_NODE_DIALOG (dialog_object); dialog->completion_tree = completion_tree; gtk_entry_completion_set_model (dialog->entry_completion, GTK_TREE_MODEL (completions)); gtk_entry_completion_set_text_column (dialog->entry_completion, NODE_NAME); return GTK_WIDGET (dialog); } else { g_tree_destroy (completion_tree); g_object_unref (completions); return NULL; } } static void gtk_go_to_named_node_dialog_finalize (GObject *object) { GTree *completion_tree = GTK_GO_TO_NAMED_NODE_DIALOG (object)->completion_tree; g_tree_foreach (completion_tree, (GTraverseFunc) free_node_list, NULL); g_tree_destroy (completion_tree); G_OBJECT_CLASS (parent_class)->finalize (object); } static void free_node_list (const char *node_name, GSList *node_list) { UNUSED (node_name); g_slist_free (node_list); } static void entered_node_name_changed (GtkEntry *node_name_entry, GtkGoToNamedNodeDialog *dialog) { const gchar *node_name = gtk_entry_get_text (node_name_entry); GSList *node_list = (GSList *) g_tree_lookup (dialog->completion_tree, node_name); set_selected_node (dialog, node_list ? (SgfNode *) node_list->data : NULL); } static gboolean match_selected (GtkGoToNamedNodeDialog *dialog, GtkTreeModel *tree_model, GtkTreeIter *iterator) { GtkWidget *entry = gtk_entry_completion_get_entry (dialog->entry_completion); gchar *node_name; SgfNode *sgf_node; gtk_tree_model_get (tree_model, iterator, NODE_NAME, &node_name, NODE_OBJECT, &sgf_node, -1); set_selected_node (dialog, sgf_node); /* Replace entry text ourselves, allows to black * entered_node_name_changed() hook. */ g_signal_handler_block (entry, dialog->entry_changed_handler_id); gtk_entry_set_text (GTK_ENTRY (entry), node_name); gtk_editable_set_position (GTK_EDITABLE (entry), -1); g_signal_handler_unblock (entry, dialog->entry_changed_handler_id); g_free (node_name); return TRUE; } static void set_selected_node (GtkGoToNamedNodeDialog *dialog, SgfNode *sgf_node) { const char *node_comment = NULL; const char *comment_text; dialog->selected_node = sgf_node; if (sgf_node) { node_comment = sgf_node_get_text_property_value (sgf_node, SGF_COMMENT); comment_text = (node_comment ? node_comment : Q_("comment|Empty")); } else comment_text = _("There is no such node"); gtk_utils_set_text_buffer_text (dialog->comment_buffer, comment_text); if (!node_comment) { GtkTextIter start_iterator; GtkTextIter end_iterator; gtk_text_buffer_get_bounds (dialog->comment_buffer, &start_iterator, &end_iterator); gtk_text_buffer_apply_tag (dialog->comment_buffer, special_comment_tag, &start_iterator, &end_iterator); } gtk_widget_set_sensitive (dialog->comment_widgets, node_comment != NULL); gtk_dialog_set_response_sensitive (&dialog->dialog, GTK_RESPONSE_OK, sgf_node != NULL); } #endif /* GTK_TYPE_GO_TO_NAMED_NODE_DIALOG */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/gtk-gtp-client-interface.c0000644000175000017500000003210310377450656020603 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "gtk-gtp-client-interface.h" #include "gtp-client.h" #include "quarry-main.h" #include #include #include typedef struct _GtkGtpClientData GtkGtpClientData; struct _GtkGtpClientData { GtpClient *client; GIOChannel *engine_input; GIOChannel *engine_output; GIOChannel *engine_stderr; guint input_event_source_id; guint stderr_input_event_source_id; FILE *log_file; GtpClientInitializedCallback initialized_callback; GtkGtpClientDeletedCallback deleted_callback; void *user_data; GError *shutdown_reason; gboolean deletion_scheduled; }; static gboolean do_delete_client (gpointer client); static gboolean handle_engine_output (GIOChannel *read_output_from, GIOCondition condition, GtkGtpClientData *data); static gboolean handle_engine_stderr (GIOChannel *read_output_from, GIOCondition condition, GtkGtpClientData *data); static void send_to_engine (const char *command, GtkGtpClientData *data); static void client_initialized (GtpClient *client, GtkGtpClientData *data); static void log_gtp_stream (const char *line, int is_command, int internal_index, GtkGtpClientData *data); static void log_gtp_stream_error (GtpError error, int command_id, GtkGtpClientData *data); static void client_deleted (GtpClient *client, GtkGtpClientData *data); static GSList *clients; GtpClient * gtk_create_gtp_client (const gchar *command_line, GtpClientInitializedCallback initialized_callback, GtkGtpClientDeletedCallback deleted_callback, void *user_data, GError **error) { GtpClient *client = NULL; gchar **argv; g_return_val_if_fail (command_line, NULL); g_return_val_if_fail (error == NULL || *error == NULL, NULL); if (g_shell_parse_argv (command_line, NULL, &argv, error)) { gint child_pid; gint standard_input; gint standard_output; gint standard_error; if (g_spawn_async_with_pipes (NULL, argv, NULL, (G_SPAWN_SEARCH_PATH | (option_gtp_show_stderr ? 0 : G_SPAWN_STDERR_TO_DEV_NULL)), NULL, NULL, &child_pid, &standard_input, &standard_output, (option_gtp_show_stderr && option_gtp_log_base_name ? &standard_error : NULL), error)) { GtkGtpClientData *data = g_malloc (sizeof (GtkGtpClientData)); client = gtp_client_new ((GtpClientSendToEngine) send_to_engine, (GtpClientLineCallback) log_gtp_stream, (GtpClientErrorCallback) log_gtp_stream_error, (initialized_callback ? ((GtpClientInitializedCallback) client_initialized) : NULL), (GtpClientDeletedCallback) client_deleted, data); data->client = client; data->engine_input = g_io_channel_unix_new (standard_input); g_io_channel_set_encoding (data->engine_input, NULL, NULL); /* Since commands always consist of one string only, no * buffering is ever needed (and this saves from flushing the * channel constantly). */ g_io_channel_set_buffered (data->engine_input, FALSE); data->engine_output = g_io_channel_unix_new (standard_output); g_io_channel_set_encoding (data->engine_output, NULL, NULL); g_io_channel_set_flags (data->engine_output, G_IO_FLAG_NONBLOCK, NULL); data->input_event_source_id = g_io_add_watch (data->engine_output, G_IO_IN | G_IO_HUP, (GIOFunc) handle_engine_output, data); if (option_gtp_show_stderr && option_gtp_log_base_name) { data->engine_stderr = g_io_channel_unix_new (standard_error); g_io_channel_set_encoding (data->engine_stderr, NULL, NULL); g_io_channel_set_flags (data->engine_stderr, G_IO_FLAG_NONBLOCK, NULL); data->stderr_input_event_source_id = g_io_add_watch (data->engine_stderr, G_IO_IN | G_IO_HUP, (GIOFunc) handle_engine_stderr, data); } else data->engine_stderr = NULL; if (option_gtp_log_base_name) { if (strcmp (option_gtp_log_base_name, "-") != 0) { gchar *log_file_name = g_strdup_printf ("%s.%d", option_gtp_log_base_name, child_pid); data->log_file = fopen (log_file_name, "wb"); if (!data->log_file) { g_print (("Warning: unable to open file `%s' " "for logging GTP stream.\n" "Warning: logging to stdout instead.\n"), log_file_name); data->log_file = stdout; } g_free (log_file_name); } else data->log_file = stdout; gtp_client_echo_on (client); } else data->log_file = NULL; data->initialized_callback = initialized_callback; data->deleted_callback = deleted_callback; data->user_data = user_data; data->shutdown_reason = NULL; data->deletion_scheduled = FALSE; clients = g_slist_prepend (clients, data); } g_strfreev (argv); } return client; } /* Schedule deletion of a GTP client. The client must have been * created by a call to gtk_create_gtp_client() and all such clients * must be deleted with this function. This allows not to track if * the client is still alive because it's guaranteed it will be * deleted in a separate GTK+/GLib event loop iteration. */ gboolean gtk_schedule_gtp_client_deletion (const GtpClient *client) { GSList *item = clients; while (1) { GtkGtpClientData *data; g_return_val_if_fail (item, FALSE); data = (GtkGtpClientData *) (item->data); if (data->client == client) { if (!data->deletion_scheduled) { data->deletion_scheduled = TRUE; g_idle_add_full (G_PRIORITY_HIGH, do_delete_client, data->client, NULL); return TRUE; } return FALSE; } item = item->next; } } /* Delete the client and the idle event source (which is not needed * anymore). */ static gboolean do_delete_client (gpointer client) { gtp_client_delete ((GtpClient *) client); return FALSE; } static gboolean handle_engine_output (GIOChannel *read_output_from, GIOCondition condition, GtkGtpClientData *data) { if (!data->deletion_scheduled) { gchar buffer[0x1000]; gsize bytes_read; /* Check that the channel is readable. This loop throws * responses at the client and it can decide to delete itself * (on response to `quit'). Then the channel is closed and is * not readable even if there is still some bogus response. */ while (g_io_channel_get_flags (read_output_from) & G_IO_FLAG_IS_READABLE) { g_io_channel_read_chars (read_output_from, buffer, sizeof buffer, &bytes_read, &data->shutdown_reason); if (data->shutdown_reason) { /* Since this is happening in a separate event loop, we can * just delete the client without scheduling. We set * `deletion_scheduled' flag to avoid assertion failure in the * deletion callback though. */ data->deletion_scheduled = TRUE; gtp_client_delete (data->client); break; } if (bytes_read > 0) gtp_client_grab_response (data->client, buffer, bytes_read); if (bytes_read < sizeof buffer) { /* Certainly nothing more to read. */ break; } } if (condition == G_IO_HUP && g_slist_find (clients, data)) { /* We read everything left in the input channel, but the client * still hasn't been deleted. This means the engine hung up * before replying to `quit' command (if it was sent at all.) */ g_set_error (&data->shutdown_reason, 0, 0, _("Engine hung up")); /* It is OK not to schedule deletion (see comments above.) */ data->deletion_scheduled = TRUE; gtp_client_delete (data->client); } } return TRUE; } /* See handle_engine_output() for details. */ static gboolean handle_engine_stderr (GIOChannel *read_output_from, GIOCondition condition, GtkGtpClientData *data) { if (!data->deletion_scheduled) { gchar buffer[0x1000]; gsize bytes_read; while (g_io_channel_get_flags (read_output_from) & G_IO_FLAG_IS_READABLE) { GError *error = NULL; g_io_channel_read_chars (read_output_from, buffer, sizeof buffer, &bytes_read, &error); if (error) { g_io_channel_shutdown (read_output_from, TRUE, NULL); g_io_channel_unref (read_output_from); data->engine_stderr = NULL; return FALSE; } if (bytes_read > 0) { g_return_val_if_fail (data->log_file, FALSE); /* FIXME: Handle partial lines nicely. Prepend some character * (maybe '!') to indicate stderr output. */ fwrite (buffer, bytes_read, 1, data->log_file); } if (bytes_read < sizeof buffer) break; } if (condition == G_IO_HUP && g_slist_find (clients, data)) { g_io_channel_shutdown (read_output_from, TRUE, NULL); g_io_channel_unref (read_output_from); data->engine_stderr = NULL; return FALSE; } } return TRUE; } static void send_to_engine (const char *command, GtkGtpClientData *data) { if (!data->deletion_scheduled) { g_io_channel_write_chars (data->engine_input, command, -1, NULL, &data->shutdown_reason); if (data->shutdown_reason) { /* `send_to_engine' callback is invoked from within GTP client * code, so we cannot just delete the client. Deletion is * scheduled instead. */ gtk_schedule_gtp_client_deletion (data->client); } } } static void client_initialized (GtpClient *client, GtkGtpClientData *data) { data->initialized_callback (client, data->user_data); } static void log_gtp_stream (const char *line, int is_command, int internal_index, GtkGtpClientData *data) { UNUSED (internal_index); g_return_if_fail (data->log_file); fprintf (data->log_file, "%c %s", (is_command ? '>' : ' '), line); } static void log_gtp_stream_error (GtpError error, int command_id, GtkGtpClientData *data) { if (!data->log_file) return; switch (error) { case GTP_ERROR_WRONG_RESPONSE_FORMAT: fputs (_("* ERROR: wrong response format\n"), data->log_file); break; case GTP_WARNING_UNEXPECTED_OUTPUT: fputs (_("* WARNING: unexpected response:\n"), data->log_file); break; case GTP_ERROR_UNRECOGNIZED_RESPONSE: fputs (_("* ERROR: unrecognized response line:\n"), data->log_file); break; case GTP_ERROR_MISMATCHED_ID: fprintf (data->log_file, _("* ERROR: mismatched ID (%d expected):\n"), command_id); break; case GTP_ERROR_UNEXPECTED_ID: fputs (_("* ERROR: unexpected ID in response (the command had none):\n"), data->log_file); break; case GTP_WARNING_FUTURE_GTP_VERSION: /* TRANSLATORS: Don't put ellipsis here, this string will most often go to fixed-width font terminals. */ fputs (_("* WARNING: future GTP version, I don't know about it...\n"), data->log_file); break; default: g_warning ("unhandled GTP error code %d", error); } } static void client_deleted (GtpClient *client, GtkGtpClientData *data) { /* Forbid explicit gtp_client_delete() from outside this module. * Other code must use gtk_gtp_client_schedule_deletion(). */ g_return_if_fail (client->operation_stage == GTP_CLIENT_QUIT || data->deletion_scheduled); clients = g_slist_remove (clients, data); if (data->deleted_callback) data->deleted_callback (client, data->shutdown_reason, data->user_data); if (data->shutdown_reason) g_error_free (data->shutdown_reason); g_source_remove (data->input_event_source_id); g_io_channel_shutdown (data->engine_input, TRUE, NULL); g_io_channel_unref (data->engine_input); g_io_channel_shutdown (data->engine_output, TRUE, NULL); g_io_channel_unref (data->engine_output); if (data->engine_stderr) { g_source_remove (data->stderr_input_event_source_id); g_io_channel_shutdown (data->engine_stderr, TRUE, NULL); g_io_channel_unref (data->engine_stderr); } if (data->log_file && data->log_file != stdout) fclose (data->log_file); g_free (data); } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/gtk-help.c0000644000175000017500000001142310512241651015511 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "gtk-help.h" #include "gtk-utils.h" #include "quarry-message-dialog.h" #include #include #include #include void gtk_help_display (const gchar *link_id) { #if HAVE_SCROLLKEEPER static gboolean yelp_works = TRUE; #endif static gchar locale_directory[16] = ""; gchar *child_argv[3]; if (! *locale_directory) { /* Get the current locale and find help directory for it. */ const char *current_locale = setlocale (LC_MESSAGES, NULL); const char *current_locale_end = current_locale + strlen (current_locale); char *pointer; /* First remove anything after a dot or at-sign. */ pointer = strchr (current_locale, '@'); if (pointer) current_locale_end = pointer; pointer = strchr (current_locale, '.'); if (pointer && pointer < current_locale_end) current_locale_end = pointer; if (current_locale_end - current_locale < sizeof locale_directory) { gchar *full_path; struct stat dummy_info; memcpy (locale_directory, current_locale, current_locale_end - current_locale); locale_directory[current_locale_end - current_locale] = 0; full_path = g_strconcat (PACKAGE_DATA_DIR "/help/", locale_directory, "/quarry.xml", NULL); if (stat (full_path, &dummy_info)) { pointer = strchr (locale_directory, '_'); if (pointer) { /* Try removing part of locale name after '_'. */ *pointer = 0; full_path = g_strconcat (PACKAGE_DATA_DIR "/help/", locale_directory, "/quarry.xml", NULL); if (stat (full_path, &dummy_info)) strcpy (locale_directory, "C"); } else strcpy (locale_directory, "C"); } g_free (full_path); } else { /* A very weird long locale, if this can happen at all. */ strcpy (locale_directory, "C"); } } #if HAVE_SCROLLKEEPER if (yelp_works) { child_argv[0] = "yelp"; if (link_id) { child_argv[1] = g_strconcat (("ghelp://" PACKAGE_DATA_DIR "/help/C/quarry.xml?"), link_id, NULL); } else child_argv[1] = "ghelp://" PACKAGE_DATA_DIR "/help/C/quarry.xml"; child_argv[2] = NULL; if (!g_spawn_async (NULL, child_argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, NULL)) yelp_works = FALSE; if (link_id) g_free (child_argv[1]); } if (!yelp_works) { #endif GError *error = NULL; /* FIXME: Make fallback browser configurable. */ child_argv[0] = "mozilla"; if (link_id) { child_argv[1] = g_strconcat (("file://" PACKAGE_DATA_DIR "/help/C/quarry.html#"), link_id, NULL); } else child_argv[1] = PACKAGE_DATA_DIR "/help/C/quarry.html"; child_argv[2] = NULL; g_spawn_async (NULL, child_argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, &error); if (error) { gchar* error_message = g_strdup_printf (_("Neither Yelp nor Mozilla works. You may browse " "help with a different browser, see file `%s'."), PACKAGE_DATA_DIR "/help/C/quarry.html"); GtkWidget *error_dialog = quarry_message_dialog_new (NULL, GTK_BUTTONS_OK, GTK_STOCK_DIALOG_ERROR, error_message, "%s", error->message); g_free (error_message); g_error_free (error); gtk_utils_show_and_forget_dialog (GTK_DIALOG (error_dialog)); } if (link_id) g_free (child_argv[1]); #if HAVE_SCROLLKEEPER } #endif } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/gtk-named-vbox.c0000644000175000017500000001556310455530166016642 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "gtk-named-vbox.h" #include "gtk-utils.h" #include static void gtk_named_vbox_class_init (GtkNamedVBoxClass *class); static void gtk_named_vbox_init (GtkNamedVBox *named_vbox); static void gtk_named_vbox_forall (GtkContainer *container, gboolean include_internals, GtkCallback callback, gpointer callback_data); static void gtk_named_vbox_style_set (GtkWidget *widget, GtkStyle *previous_style); static void gtk_named_vbox_size_request (GtkWidget *widget, GtkRequisition *requisition); static void gtk_named_vbox_size_allocate (GtkWidget *widget, GtkAllocation *allocation); static GtkVBoxClass *parent_class; GType gtk_named_vbox_get_type (void) { static GType named_vbox_type = 0; if (!named_vbox_type) { static GTypeInfo named_vbox_info = { sizeof (GtkNamedVBoxClass), NULL, NULL, (GClassInitFunc) gtk_named_vbox_class_init, NULL, NULL, sizeof (GtkNamedVBox), 4, (GInstanceInitFunc) gtk_named_vbox_init, NULL }; named_vbox_type = g_type_register_static (GTK_TYPE_VBOX, "GtkNamedVBox", &named_vbox_info, 0); } return named_vbox_type; } static void gtk_named_vbox_class_init (GtkNamedVBoxClass *class) { GtkWidgetClass *widget_class = (GtkWidgetClass *) class; parent_class = g_type_class_peek_parent (class); widget_class->style_set = gtk_named_vbox_style_set; widget_class->size_request = gtk_named_vbox_size_request; widget_class->size_allocate = gtk_named_vbox_size_allocate; GTK_CONTAINER_CLASS (class)->forall = gtk_named_vbox_forall; } static void gtk_named_vbox_init (GtkNamedVBox *named_vbox) { GtkWidget *label = gtk_utils_create_left_aligned_label (NULL); gtk_widget_set_name (label, "quarry-sub-header"); gtk_widget_set_parent (label, GTK_WIDGET (named_vbox)); named_vbox->label = label; named_vbox->left_padding = 0; } GtkWidget * gtk_named_vbox_new (const gchar *label_text, gboolean homogeneous, gint spacing) { GtkWidget *widget = GTK_WIDGET (g_object_new (GTK_TYPE_NAMED_VBOX, NULL)); GtkBox *box = GTK_BOX (widget); box->homogeneous = homogeneous; box->spacing = spacing; gtk_named_vbox_set_label_text (GTK_NAMED_VBOX (widget), label_text); return widget; } static void gtk_named_vbox_forall (GtkContainer *container, gboolean include_internals, GtkCallback callback, gpointer callback_data) { if (include_internals) callback (GTK_NAMED_VBOX (container)->label, callback_data); GTK_CONTAINER_CLASS (parent_class)->forall (container, include_internals, callback, callback_data); } static void gtk_named_vbox_style_set (GtkWidget *widget, GtkStyle *previous_style) { PangoLayout *layout; UNUSED (previous_style); /* Calculate padding. Padding is equal to width of four spaces * (recommended by GNOME style guide). */ layout = gtk_widget_create_pango_layout (widget, " "); pango_layout_get_pixel_size (layout, & GTK_NAMED_VBOX (widget)->left_padding, NULL); g_object_unref (layout); } static void gtk_named_vbox_size_request (GtkWidget *widget, GtkRequisition *requisition) { GtkNamedVBox *named_vbox = GTK_NAMED_VBOX (widget); GTK_WIDGET_CLASS (parent_class)->size_request (widget, (&named_vbox ->vbox_requisition)); if (GTK_WIDGET_VISIBLE (named_vbox->label)) { GtkRequisition label_requisition; gtk_widget_size_request (named_vbox->label, &label_requisition); requisition->width = MAX ((named_vbox->vbox_requisition.width + named_vbox->left_padding), label_requisition.width); requisition->height = (label_requisition.height + QUARRY_SPACING_SMALL + named_vbox->vbox_requisition.height); } else *requisition = named_vbox->vbox_requisition; } static void gtk_named_vbox_size_allocate (GtkWidget *widget, GtkAllocation *allocation) { GtkNamedVBox *named_vbox = GTK_NAMED_VBOX (widget); GtkRequisition widget_requisition; GtkAllocation child_allocation; gint label_height_with_padding; if (GTK_WIDGET_VISIBLE (named_vbox->label)) { GtkRequisition label_requisition; gtk_widget_get_child_requisition (named_vbox->label, &label_requisition); child_allocation.x = allocation->x; child_allocation.y = allocation->y; child_allocation.width = allocation->width; child_allocation.height = label_requisition.height; gtk_widget_size_allocate (named_vbox->label, &child_allocation); label_height_with_padding = (label_requisition.height + QUARRY_SPACING_SMALL); } else label_height_with_padding = 0; child_allocation.x = allocation->x + named_vbox->left_padding; child_allocation.y = allocation->y + label_height_with_padding; child_allocation.width = allocation->width - named_vbox->left_padding; child_allocation.height = allocation->height - label_height_with_padding; widget_requisition = widget->requisition; widget->requisition = named_vbox->vbox_requisition; GTK_WIDGET_CLASS (parent_class)->size_allocate (widget, &child_allocation); widget->requisition = widget_requisition; widget->allocation = *allocation; } void gtk_named_vbox_set_label_text (GtkNamedVBox *named_vbox, const gchar *label_text) { g_return_if_fail (GTK_IS_NAMED_VBOX (named_vbox)); gtk_label_set_text (GTK_LABEL (named_vbox->label), label_text); if (label_text && *label_text) gtk_widget_show (named_vbox->label); else gtk_widget_hide (named_vbox->label); } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/gtk-new-game-dialog.c0000644000175000017500000010234510512241734017524 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "gtk-new-game-dialog.h" #include "gtk-configuration.h" #include "gtk-control-center.h" #include "gtk-games.h" #include "gtk-goban-window.h" #include "gtk-gtp-client-interface.h" #include "gtk-named-vbox.h" #include "gtk-preferences.h" #include "gtk-utils.h" #include "quarry-assistant.h" #include "quarry-stock.h" #include "time-control.h" #include "sgf.h" #include "board.h" #include "game-info.h" #include static void gtk_new_game_dialog_init (GtkNewGameDialog *dialog); static void update_game_and_players_page (GtkWidget *widget, gpointer user_data); static void swap_players (GtkNewGameDialog *dialog); static GtkGameIndex get_selected_game (GtkNewGameDialog *dialog); static void show_game_specific_rules (GtkNewGameDialog *dialog); static void set_handicap_adjustment_limits (GtkAdjustment *board_size_adjustment, GtkNewGameDialog *dialog); static void time_control_type_changed (GtkWidget *selector, GtkNotebook *notebook); static const gchar * get_game_rules_help_link_id (GtkNewGameDialog *dialog); static gboolean instantiate_players (GtkNewGameDialog *dialog); static void begin_game (GtkEnginesInstantiationStatus status, gpointer user_data); GType gtk_new_game_dialog_get_type (void) { static GType new_game_dialog_type = 0; if (!new_game_dialog_type) { static GTypeInfo new_game_dialog_info = { sizeof (GtkNewGameDialogClass), NULL, NULL, NULL, NULL, NULL, sizeof (GtkNewGameDialog), 1, (GInstanceInitFunc) gtk_new_game_dialog_init, NULL }; new_game_dialog_type = g_type_register_static (QUARRY_TYPE_ASSISTANT, "GtkNewGameDialog", &new_game_dialog_info, 0); } return new_game_dialog_type; } static void gtk_new_game_dialog_init (GtkNewGameDialog *dialog) { static const gchar *hint_text = N_("Note that most GTP engines support only one game. Hence certain " "game / computer player combinations may be not possible to play."); static const gchar *handicap_radio_button_labels[2] = { N_("Fi_xed handicap:"), N_("_Free handicap:") }; static const gchar *time_control_types[] = { N_("No limit"), N_("Limited time for entire game"), N_("Limited time per move"), N_("Canadian overtime") }; gint game_index = gtk_games_name_to_index (new_game_configuration.game_name, FALSE); GtkWidget *vbox1; GtkWidget **radio_buttons; GtkWidget *label; GtkWidget *hbox; GtkWidget *named_vbox; GtkWidget *hboxes[3]; GtkWidget *player_vboxes[NUM_COLORS]; GtkWidget *button; GtkWidget *vbox2; GtkWidget *game_and_players_page; GtkWidget *games_notebook; GtkRadioButton *last_radio_button = NULL; int k; gtk_window_set_title (GTK_WINDOW (dialog), _("New Game")); gtk_utils_make_window_only_horizontally_resizable (GTK_WINDOW (dialog)); quarry_assistant_set_user_data (&dialog->assistant, dialog); quarry_assistant_set_finish_button (&dialog->assistant, QUARRY_STOCK_PLAY); /* "Game & Players" page. */ /* Vertical box for game radio buttons. */ vbox1 = gtk_vbox_new (FALSE, QUARRY_SPACING_SMALL); /* Create a radio button for each of the supported games. */ for (k = 0; k < NUM_SUPPORTED_GAMES; k++) { GtkWidget *radio_button; label = gtk_label_new_with_mnemonic (_(game_labels[k])); dialog->game_supported_icons[k] = gtk_image_new_from_stock (GTK_STOCK_YES, GTK_ICON_SIZE_MENU); hbox = gtk_utils_pack_in_box (GTK_TYPE_HBOX, QUARRY_SPACING_SMALL, label, GTK_UTILS_PACK_DEFAULT, dialog->game_supported_icons[k], 0, NULL); radio_button = gtk_radio_button_new_from_widget (last_radio_button); last_radio_button = GTK_RADIO_BUTTON (radio_button); dialog->game_radio_buttons[k] = GTK_TOGGLE_BUTTON (radio_button); gtk_container_add (GTK_CONTAINER (radio_button), hbox); gtk_box_pack_start (GTK_BOX (vbox1), radio_button, FALSE, TRUE, 0); g_signal_connect (radio_button, "toggled", G_CALLBACK (update_game_and_players_page), dialog); } /* Hint about engine/game (non-)compatibility. */ label = gtk_utils_create_left_aligned_label (_(hint_text)); gtk_label_set_line_wrap (GTK_LABEL (label), TRUE); /* Pack the radio buttons and the hint next to each other. */ hbox = gtk_utils_pack_in_box (GTK_TYPE_HBOX, QUARRY_SPACING_VERY_BIG, vbox1, GTK_UTILS_FILL, label, GTK_UTILS_PACK_DEFAULT, NULL); /* And pack everything into a box with caption saying "Game". */ named_vbox = gtk_named_vbox_new (_("Game"), FALSE, QUARRY_SPACING_SMALL); gtk_box_pack_start_defaults (GTK_BOX (named_vbox), hbox); /* Create identical set of controls for each of the players. */ for (k = 0; k < NUM_COLORS; k++) { static const char *radio_labels[NUM_COLORS][2] = { { N_("Hu_man"), N_("Com_puter") }, { N_("H_uman"), N_("C_omputer") } }; GtkWidget *entry; const GtpEngineListItem *engine_data = (gtk_preferences_guess_engine_by_name (new_game_configuration.engine_names[k], GTK_GAME_ANY)); /* Two radio buttons for selecting who is controlling this * player--human or computer. */ radio_buttons = (GtkWidget **) dialog->player_radio_buttons[k]; gtk_utils_create_radio_chain (radio_buttons, radio_labels[k], 2); if (new_game_configuration.player_is_computer[k]) gtk_toggle_button_set_active (dialog->player_radio_buttons[k][1], TRUE); /* Text entry for human's name. */ entry = gtk_utils_create_entry (new_game_configuration.player_names[k], RETURN_ACTIVATES_DEFAULT); dialog->human_name_entries[k] = GTK_ENTRY (entry); gtk_utils_set_sensitive_on_toggle (dialog->player_radio_buttons[k][0], entry, FALSE); /* Pack it together with corresponding radio button. */ hboxes[0] = gtk_utils_pack_in_box (GTK_TYPE_HBOX, QUARRY_SPACING_VERY_BIG, radio_buttons[0], 0, entry, GTK_UTILS_PACK_DEFAULT, NULL); /* Selector (combo box/option menu) for computer player. */ dialog->engine_selectors[k] = gtk_preferences_create_engine_selector (GTK_GAME_GO, FALSE, engine_data, update_game_and_players_page, dialog); gtk_utils_set_sensitive_on_toggle (dialog->player_radio_buttons[k][1], dialog->engine_selectors[k], FALSE); g_signal_connect (radio_buttons[1], "toggled", G_CALLBACK (update_game_and_players_page), dialog); /* Horizontal box with a radio button and the selector. */ hboxes[1] = gtk_utils_pack_in_box (GTK_TYPE_HBOX, QUARRY_SPACING_VERY_BIG, radio_buttons[1], 0, dialog->engine_selectors[k], GTK_UTILS_PACK_DEFAULT, NULL); /* And pack everything into a box with corresponding caption. */ player_vboxes[k] = gtk_utils_pack_in_box (GTK_TYPE_NAMED_VBOX, QUARRY_SPACING_SMALL, hboxes[0], GTK_UTILS_FILL, hboxes[1], GTK_UTILS_FILL, NULL); gtk_named_vbox_set_label_text (GTK_NAMED_VBOX (player_vboxes[k]), (k == BLACK_INDEX ? _("Black Player") : _("White Player"))); } /* Make sure the radio buttons line up nicely. */ gtk_utils_create_size_group (GTK_SIZE_GROUP_HORIZONTAL, dialog->player_radio_buttons[WHITE_INDEX][0], dialog->player_radio_buttons[WHITE_INDEX][1], dialog->player_radio_buttons[BLACK_INDEX][0], dialog->player_radio_buttons[BLACK_INDEX][1], vbox1, NULL); /* Button which opens "Preferences" dialog at "GTP Engines" page. */ button = gtk_button_new_with_mnemonic (_("Manage _Engine List")); g_signal_connect_swapped (button, "clicked", G_CALLBACK (gtk_preferences_dialog_present), GINT_TO_POINTER (PREFERENCES_PAGE_GTP_ENGINES)); /* Pack boxes for the two players and the button vertically. In * GUI, White always comes before Black. */ vbox1 = gtk_utils_pack_in_box (GTK_TYPE_VBOX, QUARRY_SPACING_BIG, player_vboxes[WHITE_INDEX], GTK_UTILS_FILL, player_vboxes[BLACK_INDEX], GTK_UTILS_FILL, gtk_utils_align_widget (button, 1.0, 0.5), GTK_UTILS_FILL, NULL); /* Top padding for the "Swap" button below. */ label = gtk_label_new (NULL); gtk_utils_create_size_group (GTK_SIZE_GROUP_VERTICAL, button, label, NULL); /* A button that allows to quickly swap colors of the players. */ button = gtk_button_new_with_mnemonic (_("_Swap")); g_signal_connect_swapped (button, "clicked", G_CALLBACK (swap_players), dialog); /* Pack the button into a box with top and bottom padding so it ends * up just between two players' control sets. */ vbox2 = gtk_utils_pack_in_box (GTK_TYPE_VBOX, QUARRY_SPACING_SMALL, gtk_label_new (NULL), 0, button, GTK_UTILS_EXPAND, label, (QUARRY_SPACING_BIG - QUARRY_SPACING_SMALL) / 2, NULL); /* Pack players' control sets and the "Swap" button box just to the * right of them. */ hbox = gtk_utils_pack_in_box (GTK_TYPE_HBOX, QUARRY_SPACING, vbox1, GTK_UTILS_PACK_DEFAULT, vbox2, GTK_UTILS_FILL, NULL); /* Finally pack everything into a vertical box and add it as the * assistant dialog page. */ game_and_players_page = gtk_utils_pack_in_box (GTK_TYPE_VBOX, QUARRY_SPACING_BIG, named_vbox, GTK_UTILS_FILL, hbox, GTK_UTILS_FILL, NULL); quarry_assistant_add_page (&dialog->assistant, game_and_players_page, GTK_STOCK_REFRESH, _("Game & Players"), NULL, NULL); quarry_assistant_set_page_help_link_id (&dialog->assistant, game_and_players_page, "new-game-dialog-game-and-players"); gtk_widget_show_all (game_and_players_page); if (game_index != GTK_GAME_UNSUPPORTED) { gtk_toggle_button_set_active (dialog->game_radio_buttons[game_index], TRUE); } update_game_and_players_page (NULL, dialog); /* "Game Rules" page. */ /* Notebook with a page for each game. */ games_notebook = gtk_utils_create_invisible_notebook (); dialog->games_notebook = GTK_NOTEBOOK (games_notebook); for (k = 0; k < NUM_SUPPORTED_GAMES; k++) { NewGameDialogTimeControlData *const time_control_data = dialog->time_control_data + k; const TimeControlConfiguration *time_control_configuration = NULL; gint initial_board_size = 0; GtkWidget *rules_vbox_widget; GtkBox *rules_vbox; GtkWidget *board_size_spin_button; GtkWidget *time_control_type; GtkWidget *time_control_notebook; GtkWidget *check_button; GtkWidget *game_time_limit_spin_button; GtkWidget *move_time_limit_spin_button; GtkWidget *main_time_spin_button; GtkWidget *overtime_period_spin_button; GtkWidget *moves_per_overtime_spin_button; GtkWidget *time_control_named_vbox; GtkSizeGroup *spin_buttons_size_group; if (k == GTK_GAME_GO) { time_control_configuration = &new_go_game_configuration.time_control; initial_board_size = new_go_game_configuration.board_size; } else if (k == GTK_GAME_AMAZONS) { time_control_configuration = &new_amazons_game_configuration.time_control; initial_board_size = new_amazons_game_configuration.board_size; } else if (k == GTK_GAME_REVERSI) { time_control_configuration = &new_reversi_game_configuration.time_control; initial_board_size = new_reversi_game_configuration.board_size; } /* "Game Rules" named vertical box. */ rules_vbox_widget = gtk_named_vbox_new (_(game_rules_labels[k]), FALSE, QUARRY_SPACING_SMALL); rules_vbox = GTK_BOX (rules_vbox_widget); /* Board size controls. */ dialog->board_sizes[k] = gtk_games_create_board_size_adjustment (k, initial_board_size); hbox = gtk_games_create_board_size_selector_box (k, dialog->board_sizes[k], &board_size_spin_button); gtk_box_pack_start (rules_vbox, hbox, FALSE, TRUE, 0); /* A combo box (option menu for pre-2.4) for selecting time * control type and a label for it.. */ time_control_type = gtk_utils_create_selector (time_control_types, (sizeof time_control_types / sizeof (const gchar *)), -1); label = gtk_utils_create_mnemonic_label (_("Time control _type:"), time_control_type); /* Pack the selector and the label together. */ hbox = gtk_utils_pack_in_box (GTK_TYPE_HBOX, QUARRY_SPACING, label, 0, time_control_type, GTK_UTILS_FILL, NULL); /* A notebook with a page for each type of time control. */ time_control_notebook = gtk_utils_create_invisible_notebook (); time_control_data->notebook = GTK_NOTEBOOK (time_control_notebook); g_signal_connect (time_control_type, "changed", G_CALLBACK (time_control_type_changed), time_control_notebook); /* Pack time control widgets together in a named box. */ time_control_named_vbox = gtk_utils_pack_in_box (GTK_TYPE_NAMED_VBOX, QUARRY_SPACING, hbox, GTK_UTILS_FILL, time_control_notebook, GTK_UTILS_FILL, NULL); gtk_named_vbox_set_label_text (GTK_NAMED_VBOX (time_control_named_vbox), _("Time Limit")); check_button = gtk_check_button_new_with_mnemonic (_("K_eep track of total time")); time_control_data->track_total_time_button = GTK_TOGGLE_BUTTON (check_button); if (time_control_configuration->track_total_time) { gtk_toggle_button_set_active (time_control_data->track_total_time_button, TRUE); } gtk_notebook_append_page (time_control_data->notebook, gtk_utils_align_widget (check_button, 0.0, 0.0), NULL); time_control_data->game_time_limit = ((GtkAdjustment *) gtk_adjustment_new (time_control_configuration->game_time_limit, 1.0, 3600000.0 - 1.0, 60.0, 300.0, 0.0)); game_time_limit_spin_button = gtk_utils_create_time_spin_button (time_control_data->game_time_limit, 60.0); label = gtk_utils_create_mnemonic_label (_("Time _limit for game:"), game_time_limit_spin_button); hbox = gtk_utils_pack_in_box (GTK_TYPE_HBOX, QUARRY_SPACING, label, GTK_UTILS_FILL, game_time_limit_spin_button, GTK_UTILS_FILL, gtk_label_new (_("(per player)")), GTK_UTILS_FILL, NULL); gtk_notebook_append_page (time_control_data->notebook, gtk_utils_align_widget (hbox, 0.0, 0.0), NULL); time_control_data->move_time_limit = ((GtkAdjustment *) gtk_adjustment_new (time_control_configuration->move_time_limit, 1.0, 360000.0 - 1.0, 5.0, 30.0, 0.0)); move_time_limit_spin_button = gtk_utils_create_time_spin_button (time_control_data->move_time_limit, 5.0); label = gtk_utils_create_mnemonic_label (_("Time _limit for move:"), move_time_limit_spin_button); hbox = gtk_utils_pack_in_box (GTK_TYPE_HBOX, QUARRY_SPACING, label, GTK_UTILS_FILL, move_time_limit_spin_button, GTK_UTILS_FILL, NULL); gtk_notebook_append_page (time_control_data->notebook, gtk_utils_align_widget (hbox, 0.0, 0.0), NULL); time_control_data->main_time = ((GtkAdjustment *) gtk_adjustment_new (time_control_configuration->main_time, 0.0, 3600000.0 - 1.0, 60.0, 300.0, 0.0)); main_time_spin_button = gtk_utils_create_time_spin_button (time_control_data->main_time, 60.0); label = gtk_utils_create_mnemonic_label (_("_Main time:"), main_time_spin_button); hboxes[0] = gtk_utils_pack_in_box (GTK_TYPE_HBOX, QUARRY_SPACING, label, GTK_UTILS_FILL, main_time_spin_button, GTK_UTILS_FILL, NULL); time_control_data->overtime_period = ((GtkAdjustment *) gtk_adjustment_new (time_control_configuration->overtime_period_length, 1.0, 3600000.0 - 1.0, 60.0, 300.0, 0.0)); overtime_period_spin_button = gtk_utils_create_time_spin_button (time_control_data->overtime_period, 60.0); label = gtk_utils_create_mnemonic_label (_("_Overtime period length:"), overtime_period_spin_button); hboxes[1] = gtk_utils_pack_in_box (GTK_TYPE_HBOX, QUARRY_SPACING, label, GTK_UTILS_FILL, overtime_period_spin_button, GTK_UTILS_FILL, NULL); time_control_data->moves_per_overtime = ((GtkAdjustment *) gtk_adjustment_new (time_control_configuration->moves_per_overtime, 1.0, 999.0, 1.0, 5.0, 0.0)); moves_per_overtime_spin_button = gtk_utils_create_spin_button (time_control_data->moves_per_overtime, 0.0, 0, TRUE); label = gtk_utils_create_mnemonic_label (_("Mo_ves per overtime:"), moves_per_overtime_spin_button); hboxes[2] = gtk_utils_pack_in_box (GTK_TYPE_HBOX, QUARRY_SPACING, label, GTK_UTILS_FILL, moves_per_overtime_spin_button, GTK_UTILS_FILL, NULL); vbox1 = gtk_utils_pack_in_box (GTK_TYPE_VBOX, QUARRY_SPACING_SMALL, hboxes[0], GTK_UTILS_FILL, hboxes[1], GTK_UTILS_FILL, hboxes[2], GTK_UTILS_FILL, NULL); gtk_notebook_append_page (time_control_data->notebook, vbox1, NULL); /* Select the last used time control type. */ if (0 <= time_control_configuration->type && time_control_configuration->type <= (sizeof time_control_types / sizeof (const gchar *))) { gtk_widget_show_all (time_control_notebook); gtk_utils_set_selector_active_item_index (time_control_type, (time_control_configuration ->type)); } /* Align spin buttons nicely. */ spin_buttons_size_group = gtk_utils_create_size_group (GTK_SIZE_GROUP_HORIZONTAL, board_size_spin_button, game_time_limit_spin_button, move_time_limit_spin_button, main_time_spin_button, overtime_period_spin_button, moves_per_overtime_spin_button, NULL); if (k == GTK_GAME_GO) { GtkWidget *handicap_spin_buttons[2]; GtkWidget *komi_spin_button; int i; /* Two radio buttons for choosing fixed (Japanese) or free * (Chinese) handicaps. */ radio_buttons = (GtkWidget **) dialog->handicap_toggle_buttons; gtk_utils_create_radio_chain (radio_buttons, handicap_radio_button_labels, 2); if (!new_go_game_configuration.handicap_is_fixed) { gtk_toggle_button_set_active (dialog->handicap_toggle_buttons[1], TRUE); } /* Handicap spin buttons and boxes to pack them together with * the radio buttons. */ for (i = 0; i < 2; i++) { dialog->handicaps[i] = (gtk_games_create_handicap_adjustment (i == 0 ? new_go_game_configuration.fixed_handicap : new_go_game_configuration.free_handicap)); handicap_spin_buttons[i] = gtk_utils_create_spin_button (dialog->handicaps[i], 0.0, 0, TRUE); gtk_utils_set_sensitive_on_toggle (dialog->handicap_toggle_buttons[i], handicap_spin_buttons[i], FALSE); hboxes[i] = gtk_utils_pack_in_box (GTK_TYPE_HBOX, QUARRY_SPACING, radio_buttons[i], 0, handicap_spin_buttons[i], GTK_UTILS_FILL, NULL); /* Force proper alignment of handicap spin buttons. */ gtk_size_group_add_widget (spin_buttons_size_group, handicap_spin_buttons[i]); } /* Pack all handicap controls in a vertical box and add it to * the rules box with a small padding. */ vbox1 = gtk_utils_pack_in_box (GTK_TYPE_VBOX, QUARRY_SPACING_SMALL, hboxes[0], GTK_UTILS_FILL, hboxes[1], GTK_UTILS_FILL, NULL); gtk_box_pack_start (rules_vbox, vbox1, FALSE, TRUE, QUARRY_SPACING_SMALL); set_handicap_adjustment_limits (dialog->board_sizes[GTK_GAME_GO], dialog); g_signal_connect (dialog->board_sizes[GTK_GAME_GO], "value-changed", G_CALLBACK (set_handicap_adjustment_limits), dialog); /* Komi spin button and label. */ dialog->komi = gtk_games_create_komi_adjustmet (new_go_game_configuration.komi); komi_spin_button = gtk_utils_create_spin_button (dialog->komi, 0.0, 1, FALSE); label = gtk_utils_create_mnemonic_label (_("_Komi:"), komi_spin_button); /* Pack the spin button and label together and add them to the * rules box. */ hbox = gtk_utils_pack_in_box (GTK_TYPE_HBOX, QUARRY_SPACING, label, 0, komi_spin_button, GTK_UTILS_FILL, NULL); gtk_box_pack_start (rules_vbox, hbox, FALSE, TRUE, 0); gtk_size_group_add_widget (spin_buttons_size_group, komi_spin_button); } /* Pack game-specific rules box and time control box together and * add them to the games notebook. */ vbox1 = gtk_utils_pack_in_box (GTK_TYPE_VBOX, QUARRY_SPACING_BIG, rules_vbox_widget, GTK_UTILS_FILL, time_control_named_vbox, GTK_UTILS_FILL, NULL); gtk_notebook_append_page (dialog->games_notebook, vbox1, NULL); /* Align all labels in one call. */ gtk_utils_align_left_widgets (GTK_CONTAINER (vbox1), NULL); } /* Finally, add the game rules notebook as an assistant page. */ quarry_assistant_add_page (&dialog->assistant, games_notebook, GTK_STOCK_PREFERENCES, _("Game Rules"), ((QuarryAssistantPageShownCallback) show_game_specific_rules), ((QuarryAssistantPageAcceptableCallback) instantiate_players)); quarry_assistant_set_page_help_link_id_callback (&dialog->assistant, games_notebook, (QuarryAssistantPageHelpLinkIDCallback) get_game_rules_help_link_id); gtk_widget_show_all (games_notebook); } void gtk_new_game_dialog_present (void) { static GtkWindow *new_game_dialog = NULL; if (!new_game_dialog) { new_game_dialog = GTK_WINDOW (g_object_new (GTK_TYPE_NEW_GAME_DIALOG, NULL)); gtk_control_center_window_created (new_game_dialog); gtk_utils_null_pointer_on_destroy (&new_game_dialog, TRUE); } gtk_window_present (new_game_dialog); } static void update_game_and_players_page (GtkWidget *widget, gpointer user_data) { GtkNewGameDialog *dialog = GTK_NEW_GAME_DIALOG (user_data); GtkGameIndex selected_game = get_selected_game (dialog); GtpEngineListItem *engine_datum[NUM_COLORS] = { NULL, NULL }; int k; UNUSED (widget); for (k = 0; k < NUM_COLORS; k++) { GtkWidget *selector = dialog->engine_selectors[k]; if (gtk_preferences_have_non_hidden_gtp_engine ()) { if (GTK_WIDGET_IS_SENSITIVE (selector)) { engine_datum[k] = gtk_preferences_get_engine_selector_selection (selector); } gtk_widget_set_sensitive (GTK_WIDGET (dialog->player_radio_buttons[k][1]), TRUE); } else { gtk_toggle_button_set_active (dialog->player_radio_buttons[k][0], TRUE); gtk_widget_set_sensitive (GTK_WIDGET (dialog->player_radio_buttons[k][1]), FALSE); } gtk_preferences_set_engine_selector_game_index (selector, selected_game); } for (k = 0; k < NUM_SUPPORTED_GAMES; k++) { gboolean game_is_supported = (gtk_games_engine_supports_game (engine_datum[BLACK_INDEX], k) && gtk_games_engine_supports_game (engine_datum[WHITE_INDEX], k)); if (gtk_toggle_button_get_active (dialog->game_radio_buttons[k])) { gtk_widget_set_sensitive (dialog->assistant.next_button, game_is_supported); } gtk_image_set_from_stock (GTK_IMAGE (dialog->game_supported_icons[k]), game_is_supported ? GTK_STOCK_YES : GTK_STOCK_NO, GTK_ICON_SIZE_MENU); } } static void swap_players (GtkNewGameDialog *dialog) { gboolean player_is_human[NUM_COLORS]; gchar *human_names[NUM_COLORS]; GtpEngineListItem *engine_datum[NUM_COLORS]; int k; for (k = 0; k < NUM_COLORS; k++) { GtkWidget *selector = dialog->engine_selectors[k]; player_is_human[k] = gtk_toggle_button_get_active (dialog->player_radio_buttons[k][0]); human_names[k] = g_strdup (gtk_entry_get_text (dialog->human_name_entries[k])); engine_datum[k] = gtk_preferences_get_engine_selector_selection (selector); } for (k = 0; k < NUM_COLORS; k++) { int other = OTHER_INDEX (k); gtk_entry_set_text (dialog->human_name_entries[other], human_names[k]); gtk_preferences_set_engine_selector_selection (dialog->engine_selectors[other], engine_datum[k]); gtk_toggle_button_set_active (dialog->player_radio_buttons[other][player_is_human[k] ? 0 : 1], TRUE); g_free (human_names[k]); } } static GtkGameIndex get_selected_game (GtkNewGameDialog *dialog) { gboolean selected_game; for (selected_game = 0; ; selected_game++) { if (gtk_toggle_button_get_active (dialog->game_radio_buttons[selected_game])) break; } return selected_game; } static void show_game_specific_rules (GtkNewGameDialog *dialog) { gtk_notebook_set_current_page (dialog->games_notebook, get_selected_game (dialog)); } static void set_handicap_adjustment_limits (GtkAdjustment *board_size_adjustment, GtkNewGameDialog *dialog) { gint board_size = gtk_adjustment_get_value (board_size_adjustment); gtk_games_set_handicap_adjustment_limits (board_size, board_size, dialog->handicaps[0], dialog->handicaps[1]); } static void time_control_type_changed (GtkWidget *selector, GtkNotebook *notebook) { gint time_control_type = gtk_utils_get_selector_active_item_index (selector); gtk_notebook_set_current_page (notebook, time_control_type); } static const gchar * get_game_rules_help_link_id (GtkNewGameDialog *dialog) { switch (get_selected_game (dialog)) { case GTK_GAME_GO: return "new-game-dialog-go-rules"; case GTK_GAME_AMAZONS: return "new-game-dialog-amazons-rules"; case GTK_GAME_REVERSI: return "new-game-dialog-reversi-rules"; default: g_warning ("unhandled game %s", INDEX_TO_GAME_NAME (get_selected_game (dialog))); return NULL; } } static gboolean instantiate_players (GtkNewGameDialog *dialog) { int k; GtkWindow *window = GTK_WINDOW (dialog); GtkEngineChain *engine_chain = gtk_preferences_create_engines_instantiation_chain (window, begin_game, dialog); for (k = 0; k < NUM_COLORS; k++) { if (GTK_WIDGET_IS_SENSITIVE (dialog->engine_selectors[k])) { gtk_preferences_instantiate_selected_engine (engine_chain, dialog->engine_selectors[k], &dialog->players[k]); } else dialog->players[k] = NULL; } gtk_preferences_do_instantiate_engines (engine_chain); return FALSE; } static void begin_game (GtkEnginesInstantiationStatus status, gpointer user_data) { GtkNewGameDialog *dialog; GtkGameIndex game_index; Game game; int board_size; gboolean player_is_computer[NUM_COLORS]; const char *human_names[NUM_COLORS]; const char *engine_screen_names[NUM_COLORS]; NewGameDialogTimeControlData * time_control_data; TimeControlConfiguration *time_control_configuration; TimeControl *time_control; SgfGameTree *game_tree; SgfCollection *sgf_collection; Board *board; SgfBoardState board_state; GtkWidget *goban_window; int k; if (status != ENGINES_INSTANTIATED) return; dialog = GTK_NEW_GAME_DIALOG (user_data); game_index = get_selected_game (dialog); game = index_to_game[game_index]; board_size = gtk_adjustment_get_value (dialog->board_sizes[game_index]); time_control_data = dialog->time_control_data + game_index; time_control_configuration = NULL; time_control = NULL; game_tree = sgf_game_tree_new_with_root (game, board_size, board_size, 1); game_tree->char_set = utils_duplicate_string ("UTF-8"); sgf_collection = sgf_collection_new (); sgf_collection_add_game_tree (sgf_collection, game_tree); board = board_new (game, board_size, board_size); sgf_utils_enter_tree (game_tree, board, &board_state); sgf_node_add_text_property (game_tree->root, game_tree, SGF_RESULT, utils_duplicate_string ("Void"), 0); for (k = 0; k < NUM_COLORS; k++) { GtpEngineListItem *engine_data = (gtk_preferences_get_engine_selector_selection (dialog->engine_selectors[k])); char *player_name; player_is_computer[k] = GTK_WIDGET_IS_SENSITIVE (dialog->engine_selectors[k]); human_names[k] = gtk_entry_get_text (dialog->human_name_entries[k]); engine_screen_names[k] = (engine_data ? engine_data->screen_name : NULL); player_name = sgf_utils_normalize_text ((player_is_computer[k] ? engine_screen_names[k] : human_names[k]), 1); if (player_name) { sgf_node_add_text_property (game_tree->root, game_tree, (k == BLACK_INDEX ? SGF_PLAYER_BLACK : SGF_PLAYER_WHITE), player_name, 0); } } if (game == GAME_GO) { gboolean handicap_is_fixed = gtk_toggle_button_get_active (dialog->handicap_toggle_buttons[0]); gint handicap = gtk_adjustment_get_value (dialog->handicaps[handicap_is_fixed ? 0 : 1]); gdouble komi = gtk_adjustment_get_value (dialog->komi); /* Don't bother user with handicap subtleties. */ if (handicap == 1) handicap = 0; sgf_utils_set_handicap (game_tree, handicap, handicap_is_fixed); sgf_node_add_text_property (game_tree->current_node, game_tree, SGF_KOMI, utils_cprintf ("%.f", komi), 0); new_go_game_configuration.board_size = board_size; new_go_game_configuration.handicap_is_fixed = handicap_is_fixed; if (handicap_is_fixed) new_go_game_configuration.fixed_handicap = handicap; else new_go_game_configuration.free_handicap = handicap; new_go_game_configuration.komi = komi; time_control_configuration = &new_go_game_configuration.time_control; } else if (game == GAME_AMAZONS) { new_amazons_game_configuration.board_size = board_size; time_control_configuration = &new_amazons_game_configuration.time_control; } else if (game == GAME_REVERSI) { new_reversi_game_configuration.board_size = board_size; time_control_configuration = &new_reversi_game_configuration.time_control; } time_control_configuration->type = gtk_notebook_get_current_page (time_control_data->notebook); if (time_control_configuration->type == 0) { GtkToggleButton *track_total_time_button = time_control_data->track_total_time_button; time_control_configuration->track_total_time = gtk_toggle_button_get_active (track_total_time_button); if (time_control_configuration->track_total_time) time_control = time_control_new (0, 0, 0); } else { switch (time_control_configuration->type) { /* FIXME: Should be an enumeration, not hardwired constants. */ case 1: time_control_configuration->game_time_limit = gtk_adjustment_get_value (time_control_data->game_time_limit); time_control = time_control_new (time_control_configuration->game_time_limit, 0, 0); break; case 2: time_control_configuration->move_time_limit = gtk_adjustment_get_value (time_control_data->move_time_limit); time_control = time_control_new (0, time_control_configuration->move_time_limit, 1); break; case 3: time_control_configuration->main_time = gtk_adjustment_get_value (time_control_data->main_time); time_control_configuration->overtime_period_length = gtk_adjustment_get_value (time_control_data->overtime_period); time_control_configuration->moves_per_overtime = gtk_adjustment_get_value (time_control_data->moves_per_overtime); time_control = time_control_new (time_control_configuration->main_time, time_control_configuration->overtime_period_length, time_control_configuration->moves_per_overtime); break; default: g_assert_not_reached (); } time_control_save_settings_in_sgf_node (time_control, game_tree->current_node, game_tree, 0); } configuration_set_string_value (&new_game_configuration.game_name, game_info[game].name); for (k = 0; k < NUM_COLORS; k++) { configuration_set_string_value (&new_game_configuration.player_names[k], human_names[k]); new_game_configuration.player_is_computer[k] = player_is_computer[k]; configuration_set_string_value (&new_game_configuration.engine_names[k], engine_screen_names[k]); } board_delete (board); game_tree->board = NULL; game_tree->board_state = NULL; goban_window = gtk_goban_window_new (sgf_collection, NULL); gtk_goban_window_enter_game_mode (GTK_GOBAN_WINDOW (goban_window), dialog->players[BLACK_INDEX], dialog->players[WHITE_INDEX], time_control); gtk_widget_show (goban_window); gtk_widget_destroy (GTK_WIDGET (dialog)); } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/gtk-new-game-record-dialog.c0000644000175000017500000004211610522172761021003 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "gtk-new-game-record-dialog.h" #include "gtk-configuration.h" #include "gtk-control-center.h" #include "gtk-freezable-spin-button.h" #include "gtk-games.h" #include "gtk-goban-window.h" #include "gtk-help.h" #include "gtk-named-vbox.h" #include "gtk-utils.h" #include "quarry-stock.h" #include "sgf.h" #include "board.h" #include "game-info.h" #include static void gtk_new_game_record_dialog_class_init (GtkNewGameRecordDialogClass *class); static void gtk_new_game_record_dialog_init (GtkNewGameRecordDialog *dialog); static void gtk_new_game_record_dialog_response (GtkDialog *dialog, gint response_id); static void change_rules_notebook_page (GtkRadioButton *radio_button, GtkNotebook *rules_notebook); static void set_handicap_adjustment_limit (GtkAdjustment *board_size_adjustment, GtkAdjustment *handicap_adjustment); static void set_place_stones_check_button_sensitivity (GtkNewGameRecordDialog *dialog); GType gtk_new_game_record_dialog_get_type (void) { static GType new_game_record_dialog_type = 0; if (!new_game_record_dialog_type) { static GTypeInfo new_game_record_dialog_info = { sizeof (GtkNewGameRecordDialogClass), NULL, NULL, (GClassInitFunc) gtk_new_game_record_dialog_class_init, NULL, NULL, sizeof (GtkNewGameRecordDialog), 1, (GInstanceInitFunc) gtk_new_game_record_dialog_init, NULL }; new_game_record_dialog_type = g_type_register_static (GTK_TYPE_DIALOG, "GtkNewGameRecordDialog", &new_game_record_dialog_info, 0); } return new_game_record_dialog_type; } static void gtk_new_game_record_dialog_class_init (GtkNewGameRecordDialogClass *class) { GTK_DIALOG_CLASS (class)->response = gtk_new_game_record_dialog_response; } static void gtk_new_game_record_dialog_init (GtkNewGameRecordDialog *dialog) { GtkWidget *radio_buttons[NUM_SUPPORTED_GAMES]; GtkWidget *game_named_vbox; GtkWidget *rules_notebook; GtkWidget *hbox; GtkWidget *entry; GtkWidget *label; GtkWidget *white_player_hbox; GtkWidget *black_player_hbox; GtkWidget *game_name_hbox; GtkWidget *game_info_named_vbox; GtkWidget *vbox; GtkSizeGroup *height_size_group = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL); GtkSizeGroup *labels_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); GtkSizeGroup *spin_button_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); gint game_index = gtk_games_name_to_index (new_game_record_configuration.game_name, FALSE); int k; gtk_window_set_title (GTK_WINDOW (dialog), _("New Game Record")); gtk_utils_make_window_only_horizontally_resizable (GTK_WINDOW (dialog)); gtk_utils_create_radio_chain (radio_buttons, game_labels, NUM_SUPPORTED_GAMES); dialog->game_radio_button_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio_buttons[0])); game_named_vbox = gtk_utils_pack_array_in_box (GTK_TYPE_NAMED_VBOX, QUARRY_SPACING_SMALL, radio_buttons, NUM_SUPPORTED_GAMES, GTK_UTILS_FILL); gtk_named_vbox_set_label_text (GTK_NAMED_VBOX (game_named_vbox), _("Game")); rules_notebook = gtk_utils_create_invisible_notebook (); for (k = 0; k < NUM_SUPPORTED_GAMES; k++) { GtkWidget *spin_button; GtkWidget *rules_named_vbox; int default_board_size = 0; gtk_size_group_add_widget (height_size_group, radio_buttons[k]); g_signal_connect (radio_buttons[k], "toggled", G_CALLBACK (change_rules_notebook_page), rules_notebook); if (k == GTK_GAME_GO) default_board_size = new_go_game_record_configuration.board_size; else if (k == GTK_GAME_AMAZONS) default_board_size = new_amazons_game_record_configuration.board_size; else if (k == GTK_GAME_REVERSI) default_board_size = new_reversi_game_record_configuration.board_size; dialog->board_sizes[k] = gtk_games_create_board_size_adjustment (k, default_board_size); hbox = gtk_games_create_board_size_selector_box (k, dialog->board_sizes[k], &spin_button); gtk_size_group_add_widget (spin_button_size_group, spin_button); gtk_size_group_add_widget (height_size_group, hbox); rules_named_vbox = gtk_named_vbox_new (_(game_rules_labels[k]), FALSE, QUARRY_SPACING_SMALL); gtk_box_pack_start (GTK_BOX (rules_named_vbox), hbox, FALSE, TRUE, 0); if (k == GTK_GAME_GO) { GtkAdjustment *handicap_adjustment = (gtk_games_create_handicap_adjustment (new_go_game_record_configuration.handicap)); GtkAdjustment *komi_adjustment = (gtk_games_create_komi_adjustmet (new_go_game_record_configuration.komi)); GtkWidget *place_stones; spin_button = gtk_utils_create_freezable_spin_button (handicap_adjustment, 0.0, 0, TRUE); dialog->handicap_spin_button = GTK_FREEZABLE_SPIN_BUTTON (spin_button); gtk_utils_freeze_on_empty_input (dialog->handicap_spin_button); if (new_go_game_record_configuration.handicap_is_null) { gtk_freezable_spin_button_freeze (GTK_FREEZABLE_SPIN_BUTTON (spin_button), ""); } gtk_size_group_add_widget (spin_button_size_group, spin_button); label = gtk_utils_create_mnemonic_label (_("Han_dicap:"), spin_button); place_stones = gtk_check_button_new_with_mnemonic (_("_Place stones")); dialog->place_stones = GTK_TOGGLE_BUTTON (place_stones); if (new_go_game_record_configuration.place_handicap_stones) gtk_toggle_button_set_active (dialog->place_stones, TRUE); set_handicap_adjustment_limit (dialog->board_sizes[k], handicap_adjustment); g_signal_connect (dialog->board_sizes[k], "value-changed", G_CALLBACK (set_handicap_adjustment_limit), handicap_adjustment); set_place_stones_check_button_sensitivity (dialog); g_signal_connect_swapped (dialog->board_sizes[k], "value-changed", (G_CALLBACK (set_place_stones_check_button_sensitivity)), dialog); g_signal_connect_swapped (handicap_adjustment, "value-changed", (G_CALLBACK (set_place_stones_check_button_sensitivity)), dialog); hbox = gtk_utils_pack_in_box (GTK_TYPE_HBOX, QUARRY_SPACING, label, 0, spin_button, GTK_UTILS_FILL, place_stones, GTK_UTILS_PACK_DEFAULT, NULL); gtk_size_group_add_widget (height_size_group, hbox); gtk_box_pack_start (GTK_BOX (rules_named_vbox), hbox, FALSE, TRUE, 0); spin_button = gtk_utils_create_freezable_spin_button (komi_adjustment, 0.0, 1, FALSE); dialog->komi_spin_button = GTK_FREEZABLE_SPIN_BUTTON (spin_button); gtk_utils_freeze_on_empty_input (dialog->komi_spin_button); if (new_go_game_record_configuration.komi_is_null) { gtk_freezable_spin_button_freeze (GTK_FREEZABLE_SPIN_BUTTON (spin_button), ""); } gtk_size_group_add_widget (spin_button_size_group, spin_button); label = gtk_utils_create_mnemonic_label (_("_Komi:"), spin_button); hbox = gtk_utils_pack_in_box (GTK_TYPE_HBOX, QUARRY_SPACING, label, 0, spin_button, GTK_UTILS_FILL, NULL); gtk_size_group_add_widget (height_size_group, hbox); gtk_box_pack_start (GTK_BOX (rules_named_vbox), hbox, FALSE, TRUE, 0); } gtk_utils_align_left_widgets (GTK_CONTAINER (rules_named_vbox), labels_size_group); gtk_notebook_append_page (GTK_NOTEBOOK (rules_notebook), rules_named_vbox, NULL); } /* Call it here when all signal callbacks and widgets are set up. */ if (game_index != GTK_GAME_UNSUPPORTED) { gtk_widget_show_all (rules_notebook); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio_buttons[game_index]), TRUE); } hbox = gtk_utils_pack_in_box (GTK_TYPE_HBOX, QUARRY_SPACING_VERY_BIG, game_named_vbox, GTK_UTILS_FILL, rules_notebook, GTK_UTILS_PACK_DEFAULT, NULL); entry = gtk_utils_create_entry ((new_game_record_configuration .player_names[WHITE_INDEX]), RETURN_ACTIVATES_DEFAULT); dialog->white_player = GTK_ENTRY (entry); label = gtk_utils_create_mnemonic_label (_("_White player:"), entry); white_player_hbox = gtk_utils_pack_in_box (GTK_TYPE_HBOX, QUARRY_SPACING, label, 0, entry, GTK_UTILS_PACK_DEFAULT, NULL); entry = gtk_utils_create_entry ((new_game_record_configuration .player_names[BLACK_INDEX]), RETURN_ACTIVATES_DEFAULT); dialog->black_player = GTK_ENTRY (entry); label = gtk_utils_create_mnemonic_label (_("_Black player:"), entry); black_player_hbox = gtk_utils_pack_in_box (GTK_TYPE_HBOX, QUARRY_SPACING, label, 0, entry, GTK_UTILS_PACK_DEFAULT, NULL); entry = gtk_utils_create_entry (new_game_record_configuration.game_record_name, RETURN_ACTIVATES_DEFAULT); dialog->game_name = GTK_ENTRY (entry); label = gtk_utils_create_mnemonic_label (_("Game _name:"), entry); game_name_hbox = gtk_utils_pack_in_box (GTK_TYPE_HBOX, QUARRY_SPACING, label, 0, entry, GTK_UTILS_PACK_DEFAULT, NULL); vbox = gtk_utils_pack_in_box (GTK_TYPE_VBOX, QUARRY_SPACING_SMALL, white_player_hbox, GTK_UTILS_FILL, black_player_hbox, GTK_UTILS_FILL, game_name_hbox, GTK_UTILS_FILL, NULL); gtk_utils_align_left_widgets (GTK_CONTAINER (vbox), NULL); label = (gtk_utils_create_left_aligned_label (_("You can always change and expand game information later. " "Just choose `Edit/Game Information' menu item or press " "`Info' button on the main toolbar."))); gtk_label_set_line_wrap (GTK_LABEL (label), TRUE); game_info_named_vbox = gtk_utils_pack_in_box (GTK_TYPE_NAMED_VBOX, QUARRY_SPACING, vbox, GTK_UTILS_FILL, label, GTK_UTILS_FILL, NULL); gtk_named_vbox_set_label_text (GTK_NAMED_VBOX (game_info_named_vbox), _("Short Game Information")); vbox = gtk_utils_pack_in_box (GTK_TYPE_VBOX, QUARRY_SPACING_BIG, hbox, GTK_UTILS_FILL, game_info_named_vbox, GTK_UTILS_FILL, NULL); gtk_widget_show_all (vbox); gtk_utils_standardize_dialog (&dialog->dialog, vbox); gtk_dialog_add_buttons (&dialog->dialog, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, QUARRY_STOCK_CREATE, GTK_RESPONSE_OK, NULL); gtk_utils_add_help_button (&dialog->dialog); gtk_dialog_set_default_response (&dialog->dialog, GTK_RESPONSE_OK); } void gtk_new_game_record_dialog_present (void) { static GtkWindow *new_game_record_dialog = NULL; if (!new_game_record_dialog) { new_game_record_dialog = GTK_WINDOW (g_object_new (GTK_TYPE_NEW_GAME_RECORD_DIALOG, NULL)); gtk_control_center_window_created (new_game_record_dialog); gtk_utils_null_pointer_on_destroy (&new_game_record_dialog, TRUE); } gtk_window_present (new_game_record_dialog); } static void gtk_new_game_record_dialog_response (GtkDialog *dialog, gint response_id) { if (response_id == GTK_RESPONSE_OK) { GtkNewGameRecordDialog *data = GTK_NEW_GAME_RECORD_DIALOG (dialog); gint game_index = gtk_utils_get_selected_radio_index (data->game_radio_button_group); Game game = index_to_game[game_index]; gint board_size = gtk_adjustment_get_value (data->board_sizes[game_index]); const gchar *white_player = gtk_entry_get_text (data->white_player); const gchar *black_player = gtk_entry_get_text (data->black_player); const gchar *game_name = gtk_entry_get_text (data->game_name); char *white_player_normalized = sgf_utils_normalize_text (white_player, 1); char *black_player_normalized = sgf_utils_normalize_text (black_player, 1); char *game_name_normalized = sgf_utils_normalize_text (game_name, 1); SgfGameTree *sgf_tree; SgfNode *root; SgfCollection *sgf_collection; GtkWidget *goban_window; gint handicap = -1; gboolean place_handicap = TRUE; gdouble komi = 0.0; gboolean komi_is_set = FALSE; sgf_tree = sgf_game_tree_new_with_root (game, board_size, board_size, 1); root = sgf_tree->root; if (white_player_normalized) { sgf_node_add_text_property (root, sgf_tree, SGF_PLAYER_WHITE, white_player_normalized, 0); } if (black_player_normalized) { sgf_node_add_text_property (root, sgf_tree, SGF_PLAYER_BLACK, black_player_normalized, 0); } if (game_name_normalized) { sgf_node_add_text_property (root, sgf_tree, SGF_GAME_NAME, game_name_normalized, 0); } if (game == GAME_GO) { place_handicap = (GTK_WIDGET_SENSITIVE (data->place_stones) && gtk_toggle_button_get_active (data->place_stones)); if ((gtk_freezable_spin_button_get_freezing_string (data->handicap_spin_button)) == NULL) { handicap = (gtk_spin_button_get_value (GTK_SPIN_BUTTON (data->handicap_spin_button))); /* Don't bother user with handicap subtleties. */ if (handicap == 1) handicap = 0; sgf_utils_set_handicap (sgf_tree, handicap, place_handicap); } if ((gtk_freezable_spin_button_get_freezing_string (data->komi_spin_button)) == NULL) { komi = gtk_spin_button_get_value (GTK_SPIN_BUTTON (data->komi_spin_button)); komi_is_set = TRUE; sgf_node_add_text_property (root, sgf_tree, SGF_KOMI, utils_cprintf ("%.f", komi), 0); } } configuration_set_string_value (&new_game_record_configuration.game_name, game_info[game].name); configuration_set_string_value (&new_game_record_configuration.player_names[WHITE_INDEX], white_player); configuration_set_string_value (&new_game_record_configuration.player_names[BLACK_INDEX], black_player); configuration_set_string_value (&new_game_record_configuration.game_record_name, game_name); if (game == GAME_GO) { new_go_game_record_configuration.board_size = board_size; new_go_game_record_configuration.handicap_is_null = (handicap < 0); new_go_game_record_configuration.handicap = handicap; new_go_game_record_configuration.place_handicap_stones = place_handicap; new_go_game_record_configuration.komi = komi; new_go_game_record_configuration.komi_is_null = !komi_is_set; } else if (game == GAME_AMAZONS) new_amazons_game_record_configuration.board_size = board_size; else if (game == GAME_REVERSI) new_reversi_game_record_configuration.board_size = board_size; sgf_collection = sgf_collection_new (); sgf_collection_add_game_tree (sgf_collection, sgf_tree); goban_window = gtk_goban_window_new (sgf_collection, NULL); gtk_goban_window_enter_game_record_mode (GTK_GOBAN_WINDOW (goban_window)); gtk_window_present (GTK_WINDOW (goban_window)); } else if (response_id == GTK_RESPONSE_HELP) { gtk_help_display ("new-game-record-dialog"); return; } gtk_widget_destroy (GTK_WIDGET (dialog)); } static void change_rules_notebook_page (GtkRadioButton *radio_button, GtkNotebook *rules_notebook) { if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (radio_button))) { GSList *radio_button_group = gtk_radio_button_get_group (radio_button); gint page_index = gtk_utils_get_selected_radio_index (radio_button_group); gtk_notebook_set_current_page (rules_notebook, page_index); } } static void set_handicap_adjustment_limit (GtkAdjustment *board_size_adjustment, GtkAdjustment *handicap_adjustment) { gint board_size = gtk_adjustment_get_value (board_size_adjustment); gtk_games_set_handicap_adjustment_limits (board_size, board_size, NULL, handicap_adjustment); } static void set_place_stones_check_button_sensitivity (GtkNewGameRecordDialog *dialog) { gint handicap = gtk_spin_button_get_value (GTK_SPIN_BUTTON (dialog->handicap_spin_button)); gint board_size = gtk_adjustment_get_value (dialog->board_sizes[GTK_GAME_GO]); gint max_fixed_handicap = go_get_max_fixed_handicap (board_size, board_size); gtk_widget_set_sensitive (GTK_WIDGET (dialog->place_stones), 2 <= handicap && handicap <= max_fixed_handicap); } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/gtk-parser-interface.c0000644000175000017500000002654010453267576020043 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* GTK+ wrapper module around SGF parser. Contains code for file * selection, creating GtkGobanWindow's on successful parsing and * popping message dialogs otherwise. File selection is optional, * i.e. this module can be entered to parse immediatly. * * When threads are supported by GLib, this module shows progress * dialog during parsing of huge files, thus providing feedback and a * way to cancel parsing. And you can actually do anything with * Quarry while it parses a file in another thread. */ #include "gtk-parser-interface.h" #include "gtk-control-center.h" #include "gtk-file-dialog.h" #include "gtk-goban-window.h" #include "gtk-thread-interface.h" #include "gtk-utils.h" #include "quarry-message-dialog.h" #include "sgf.h" #include "utils.h" #include /* For chdir() function. */ #if HAVE_UNISTD_H #include #elif defined (G_OS_WIN32) /* FIXME: verify that it works. */ #include #endif static const gchar *reading_error = N_("Error reading file `%s'"); static const gchar *not_sgf_file_error = N_("File `%s' doesn't appear to be a valid SGF file"); static const gchar *reading_error_hint = N_("Please check that the file exists " "and its permission allow you to read it."); static const gchar *not_sgf_file_error_hint = N_("Quarry uses SGF file format for storing game records. SGF files would " "normally have `sgf' extension, but that's not necessarily true. Please " "make sure you select a proper SGF file."); static void open_file_response (GtkWidget *file_dialog, gint response_id, GtkHandleParsedData callback); static void open_game_record (SgfCollection *sgf_collection, SgfErrorList *sgf_error_list, const gchar *filename); /* For hooking up as a callback. */ void gtk_parser_interface_present_default (void) { gtk_parser_interface_present (NULL, NULL, NULL); } void gtk_parser_interface_present (GtkWindow **dialog_window, const gchar *title, GtkHandleParsedData callback) { static GtkWindow *open_sgf_file_dialog = NULL; if (dialog_window == NULL) dialog_window = &open_sgf_file_dialog; if (*dialog_window == NULL) { GtkWidget *file_dialog = gtk_file_dialog_new ((title ? title : _("Open SGF File...")), NULL, TRUE, GTK_STOCK_OPEN); g_signal_connect (file_dialog, "response", G_CALLBACK (open_file_response), callback); *dialog_window = GTK_WINDOW (file_dialog); gtk_control_center_window_created (*dialog_window); gtk_utils_null_pointer_on_destroy (dialog_window, TRUE); } gtk_window_present (*dialog_window); } static void open_file_response (GtkWidget *file_dialog, gint response_id, GtkHandleParsedData callback) { if (response_id == GTK_RESPONSE_OK) { gchar *filename = gtk_file_dialog_get_filename (file_dialog); gtk_parse_sgf_file (filename, GTK_WINDOW (file_dialog), callback); g_free (filename); } else if (response_id == GTK_RESPONSE_CANCEL) gtk_widget_destroy (file_dialog); } static void open_game_record (SgfCollection *sgf_collection, SgfErrorList *sgf_error_list, const gchar *filename) { GtkWidget *goban_window = gtk_goban_window_new (sgf_collection, filename); gtk_goban_window_enter_game_record_mode (GTK_GOBAN_WINDOW (goban_window)); gtk_window_present (GTK_WINDOW (goban_window)); if (sgf_error_list) string_list_delete (sgf_error_list); } #if THREADS_SUPPORTED #include "gtk-progress-dialog.h" static gpointer thread_wrapped_sgf_parse_file (ParsingThreadData *data); static gboolean update_progress_bar (GtkProgressDialog *progress_dialog, ParsingThreadData *data); static gboolean cancel_parsing (GtkProgressDialog *progress_dialog, ParsingThreadData *data); static void analyze_parsed_data (void *result); /* NOTE: `filename' must be in file system encoding! */ void gtk_parse_sgf_file (const char *filename, GtkWindow *parent, GtkHandleParsedData callback) { ParsingThreadData *data; gchar *label_text; gchar *absolute_filename; gchar *filename_in_utf8; g_return_if_fail (filename); if (g_path_is_absolute (filename)) absolute_filename = g_strdup (filename); else { gchar *current_directory = g_get_current_dir (); absolute_filename = g_build_filename (current_directory, filename, NULL); g_free (current_directory); } data = g_malloc (sizeof (ParsingThreadData)); data->filename = absolute_filename; data->file_size = 0; data->bytes_parsed = 0; data->cancellation_flag = 0; data->parent = (parent ? GTK_WIDGET (parent) : NULL); data->callback = callback ? callback : open_game_record; filename_in_utf8 = g_filename_to_utf8 (absolute_filename, -1, NULL, NULL, NULL); label_text = g_strdup_printf (_("Parsing file `%s'..."), filename_in_utf8); g_free (filename_in_utf8); data->progress_dialog = gtk_progress_dialog_new (parent, "Quarry", label_text, (GtkProgressDialogCallback) update_progress_bar, (GtkProgressDialogCallback) cancel_parsing, data); g_object_ref (data->progress_dialog); g_free (label_text); gtk_control_center_new_reason_to_live (); g_thread_create ((GThreadFunc) thread_wrapped_sgf_parse_file, data, FALSE, NULL); } static gpointer thread_wrapped_sgf_parse_file (ParsingThreadData *data) { ThreadEventData *event_data; data->result = sgf_parse_file (data->filename, &data->sgf_collection, &data->error_list, &sgf_parser_defaults, &data->file_size, &data->bytes_parsed, &data->cancellation_flag); event_data = g_malloc (sizeof (ThreadEventData)); event_data->callback = analyze_parsed_data; event_data->result = data; g_async_queue_push (thread_events_queue, event_data); g_main_context_wakeup (NULL); return NULL; } static gboolean update_progress_bar (GtkProgressDialog *progress_dialog, ParsingThreadData *data) { if (!GTK_WIDGET_VISIBLE (progress_dialog)) { gtk_widget_show (GTK_WIDGET (progress_dialog)); if (data->parent) gtk_widget_hide (data->parent); } if (data->file_size > 0) { gtk_progress_dialog_set_fraction (progress_dialog, (((gdouble) data->bytes_parsed) / data->file_size), "Quarry"); } return TRUE; } static gboolean cancel_parsing (GtkProgressDialog *progress_dialog, ParsingThreadData *data) { UNUSED (progress_dialog); data->cancellation_flag = 1; return TRUE; } static void analyze_parsed_data (void *result) { ParsingThreadData *data = (ParsingThreadData *) result; gtk_widget_destroy (data->progress_dialog); if (data->result == SGF_PARSED) { if (data->parent) { gchar *directory = g_path_get_dirname (data->filename); chdir (directory); g_free (directory); gtk_widget_destroy (data->parent); } data->callback (data->sgf_collection, data->error_list, data->filename); } else if (data->result == SGF_PARSING_CANCELLED) { if (data->parent) gtk_widget_destroy (data->parent); } else { GtkProgressDialog *progress_dialog = GTK_PROGRESS_DIALOG (data->progress_dialog); GtkWidget *error_dialog; gchar *filename_in_utf8 = g_filename_to_utf8 (data->filename, -1, NULL, NULL, NULL); gtk_progress_dialog_recover_parent (progress_dialog); error_dialog = quarry_message_dialog_new ((data->parent ? GTK_WINDOW (data->parent) : NULL), GTK_BUTTONS_OK, GTK_STOCK_DIALOG_ERROR, (data->result == SGF_ERROR_READING_FILE ? _(reading_error_hint) : _(not_sgf_file_error_hint)), (data->result == SGF_ERROR_READING_FILE ? _(reading_error) : _(not_sgf_file_error)), filename_in_utf8); g_free (filename_in_utf8); if (data->parent) gtk_window_set_modal (GTK_WINDOW (error_dialog), TRUE); else { gtk_control_center_window_created (GTK_WINDOW (error_dialog)); g_signal_connect (error_dialog, "destroy", G_CALLBACK (gtk_control_center_window_destroyed), NULL); } gtk_utils_show_and_forget_dialog (GTK_DIALOG (error_dialog)); } g_object_unref (data->progress_dialog); g_free (data->filename); g_free (data); gtk_control_center_lost_reason_to_live (); } #else /* not THREADS_SUPPORTED */ void gtk_parse_sgf_file (const char *filename, GtkWindow *parent, GtkHandleParsedData callback) { gchar *absolute_filename; SgfCollection *sgf_collection; SgfErrorList *error_list; int result; if (g_path_is_absolute (filename)) absolute_filename = g_strdup (filename); else { gchar *current_directory = g_get_current_dir (); absolute_filename = g_build_filename (current_directory, filename, NULL); g_free (current_directory); } result = sgf_parse_file (absolute_filename, &sgf_collection, &error_list, &sgf_parser_defaults, NULL, NULL, NULL); if (result == SGF_PARSED) { if (parent) { gchar *directory = g_path_get_dirname (absolute_filename); chdir (directory); g_free (directory); gtk_widget_destroy (GTK_WIDGET (parent)); } if (!callback) callback = open_game_record; callback (sgf_collection, error_list, absolute_filename); } else { gchar *filename_in_utf8 = g_filename_to_utf8 (absolute_filename, -1, NULL, NULL, NULL); GtkWidget *message_dialog = quarry_message_dialog_new (parent ? GTK_WINDOW (parent) : NULL, GTK_BUTTONS_OK, GTK_STOCK_DIALOG_ERROR, (result == SGF_ERROR_READING_FILE ? _(reading_error_hint) : _(not_sgf_file_error_hint)), (result == SGF_ERROR_READING_FILE ? _(reading_error) : _(not_sgf_file_error)), filename_in_utf8); g_free (filename_in_utf8); if (parent) gtk_window_set_modal (GTK_WINDOW (message_dialog), TRUE); else { gtk_control_center_window_created (GTK_WINDOW (message_dialog)); g_signal_connect (message_dialog, "destroy", G_CALLBACK (gtk_control_center_window_destroyed), NULL); } gtk_utils_show_and_forget_dialog (GTK_DIALOG (message_dialog)); } } #endif /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/gtk-preferences.c0000644000175000017500000027021310522173436017074 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "gtk-preferences.h" #include "gtk-color-button.h" #include "gtk-configuration.h" #include "gtk-control-center.h" #include "gtk-file-selector.h" #include "gtk-games.h" #include "gtk-goban-base.h" #include "gtk-help.h" #include "gtk-named-vbox.h" #include "gtk-gtp-client-interface.h" #include "gtk-progress-dialog.h" #include "gtk-sgf-tree-view.h" #include "gtk-utils.h" #include "quarry-message-dialog.h" #include "quarry-stock.h" #include "markup-theme-configuration.h" #include "utils.h" #include #include typedef struct _PreferencesDialogCategory PreferencesDialogCategory; struct _PreferencesDialogCategory { GtkWidget * (* create_page) (void); const gchar *tree_icon_stock_id; const gchar *tree_title; const gchar *page_icon_stock_id; const gchar *page_title; }; enum { CATEGORIES_PAGE_INDEX, #if GTK_2_2_OR_LATER CATEGORIES_ICON, #endif CATEGORIES_TEXT, CATEGORIES_NUM_COLUMNS }; enum { ENGINES_DATA, ENGINES_IS_VISIBLE, ENGINES_NAME, #if GTK_2_4_OR_LATER ENGINES_COMMAND_LINE, #endif ENGINES_NUM_COLUMNS }; typedef struct _GtkToolbarList GtkToolbarList; struct _GtkToolbarList { GSList *toolbars; int *toolbar_style; }; typedef struct _UseThemeDefaultsData UseThemeDefaultsData; struct _UseThemeDefaultsData { Game game; GtkWidget *vbox; GtkRange *size_range; GtkToggleButton *size_is_relative_toggle_button; GtkRange *opacity_range; }; typedef struct _GtkEngineSelectorData GtkEngineSelectorData; struct _GtkEngineSelectorData { GtkEngineChanged callback; GtkWidget *selector; gpointer *user_data; GtkGameIndex selector_game_index; #if GTK_2_4_OR_LATER GtkCellRenderer *pixbuf_cell; #else gboolean only_this_game; GtpEngineListItem *last_selection; #endif }; typedef struct _GtkEngineDialogData GtkEngineDialogData; struct _GtkEngineDialogData { GtpEngineListItem *engine_data; gboolean engine_deleted; GtkWindow *window; GtkEntry *command_line_entry; GtkEntry *name_entry; GtpClient *client; GtkWidget *progress_dialog; }; typedef struct _GtkChainEngineData GtkChainEngineData; struct _GtkChainEngineData { GtpEngineListItem *engine_data; GtkEngineChain *engine_chain; }; static void handle_drag_and_drop (GtkTreeModel *gtp_engines_tree_model, GtkTreePath *tree_path, GtkTreeIter *iterator); static GtkWidget * create_gtk_ui_page (void); static GtkWidget * create_toolbar_style_box (gint item_to_select, GtkToolbarList *toolbar_list, const gchar *label_text); static GtkWidget * create_gtp_engines_page (void); static GtkWidget * create_game_tree_page (void); static GtkWidget * create_saving_sgf_page (void); static GtkWidget * create_go_board_appearance_page (void); static GtkWidget * create_amazons_board_appearance_page (void); static GtkWidget * create_reversi_board_appearance_page (void); static GtkWidget * create_background_table (GtkGameIndex game_index, gint num_table_rows); static GtkWidget * create_markup_box (GtkGameIndex game_index, const gchar *labels[4]); static GtkWidget * create_board_appearance_notebook_page (GtkWidget *background_widget, GtkWidget *markup_widget); static void gtk_preferences_dialog_change_page (GtkTreeSelection *selection, GtkNotebook *notebook); static void gtk_preferences_dialog_response (GtkWindow *window, gint response_id); static void change_toolbar_style (GtkWidget *selector, GtkToolbarList *toolbar_list); static void gtk_preferences_dialog_update_gtp_engine_info (GtkTreeSelection *selection); static void show_or_hide_gtp_engine (GtkCellRendererToggle *cell, gchar *path_string, gpointer user_data); static void do_remove_gtp_engine (void); static void do_move_gtp_engine (gpointer move_upwards); static GSList * find_gtp_engine_dialog_by_engine_data (GtpEngineListItem *engine_data); static void gtk_gtp_engine_dialog_present (gpointer new_engine); static void gtk_gtp_engine_dialog_destroy (GtkWindow *window, GtkEngineDialogData *data); static void gtk_gtp_engine_dialog_response (GtkWindow *window, gint response_id, GtkEngineDialogData *data); static void client_initialized (GtpClient *client, void *user_data); static void client_deleted (GtpClient *client, GError *shutdown_reason, void *user_data); static gboolean show_progress_dialog (GtkProgressDialog *progress_dialog, gpointer user_data); static gboolean cancel_engine_query (GtkProgressDialog *progress_dialog, GtkEngineDialogData *data); static void store_toggle_setting (GtkToggleButton *toggle_button, int *value_storage); static void store_radio_button_setting (GtkRadioButton *radio_button, int *value_storage); static void update_game_tree_tooltips_status (GtkToggleButton *toggle_button); static gboolean update_board_background_texture (GtkEntry *entry, GdkEventFocus *event, gpointer game_index); #ifdef GTK_TYPE_FILE_SELECTOR static void board_background_texture_changed (GtkFileSelector *file_selector, gpointer game_index); #endif static void update_board_appearance (GtkWidget *widget, gpointer value_storage); static void update_board_markup_theme (GtkWidget *widget, UseThemeDefaultsData *data); static void update_markup_theme_defaults_usage (GtkToggleButton *toggle_button, UseThemeDefaultsData *data); static inline BoardAppearance * game_index_to_board_appearance_structure (GtkGameIndex game_index); static void do_register_toolbar (GtkToolbar *toolbar, GtkToolbarList *toolbar_list); static void unregister_toolbar (GtkToolbar *toolbar, GtkToolbarList *toolbar_list); static void set_toolbar_style (GtkToolbar *toolbar, int style); static void engine_selector_changed (GtkWidget *selector, GtkEngineSelectorData *data); static void engine_selector_destroyed (GtkEngineSelectorData *data); #if GTK_2_4_OR_LATER #define prepare_to_rebuild_menus() #define rebuild_all_menus() static void set_pixbuf_cell_image (GtkCellLayout *cell_layout, GtkCellRenderer *cell, GtkTreeModel *gtp_engines_tree_model, GtkTreeIter *iterator, gpointer data); static gboolean engine_is_visible_and_supports_game (GtkTreeModel *tree_model, GtkTreeIter *iterator, gpointer game_index); #else static void prepare_to_rebuild_menus (void); static void rebuild_all_menus (void); static void build_and_attach_menu (GtkWidget *option_menu, GtkGameIndex game_index, gboolean only_this_game); #endif static void chain_client_initialized (GtpClient *client, void *user_data); static void update_engine_screen_name (GtpEngineListItem *engine_data, gboolean update_tree_model); static void find_gtp_tree_model_iterator_by_engines_data (const GtpEngineListItem *engine_data, GtkTreeIter *iterator); static gint last_selected_page = 0; static GtkToolbarList main_toolbar_list = { NULL, >k_ui_configuration.main_toolbar_style }; static GtkToolbarList editing_toolbar_list = { NULL, >k_ui_configuration.editing_toolbar_style }; static GtkToolbarList navigation_toolbar_list = { NULL, >k_ui_configuration.navigation_toolbar_style }; static GtkListStore *gtp_engines_list_store; static GSList *gtp_engine_selectors = NULL; #if GTK_2_4_OR_LATER static GtkTreeModel *non_hidden_gtp_engines_tree_model; static GtkTreeModel *only_one_game_gtp_engines_tree_model[NUM_SUPPORTED_GAMES]; #endif static GtkWindow *preferences_dialog = NULL; static GtkTreeView *category_tree_view; static GtkTreeView *gtp_engines_tree_view; static GtkTreeSelection *gtp_engines_tree_selection; static GtkWidget *modify_gtp_engine; static GtkWidget *remove_gtp_engine; static GtkWidget *move_gtp_engine_up; static GtkWidget *move_gtp_engine_down; static GtkWidget *gtp_engine_info; static GtkLabel *gtp_engine_name; static GtkLabel *gtp_engine_version; static GtkLabel *gtp_engine_supported_games_label; static GtkLabel *gtp_engine_supported_games; static GtkLabel *gtp_engine_command_line; static GtkLabel *gtp_engine_additional_info; static GSList *gtp_engine_dialogs = NULL; void gtk_preferences_init (void) { GtpEngineListItem *engine_data; #if GTK_2_4_OR_LATER int k; gtp_engines_list_store = gtk_list_store_new (ENGINES_NUM_COLUMNS, G_TYPE_POINTER, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_STRING); #else gtp_engines_list_store = gtk_list_store_new (ENGINES_NUM_COLUMNS, G_TYPE_POINTER, G_TYPE_BOOLEAN, G_TYPE_STRING); #endif for (engine_data = gtp_engines.first; engine_data; engine_data = engine_data->next) { GtkTreeIter iterator; /* Force name specified by `screen_name'. */ update_engine_screen_name (engine_data, FALSE); gtk_list_store_append (gtp_engines_list_store, &iterator); #if GTK_2_4_OR_LATER gtk_list_store_set (gtp_engines_list_store, &iterator, ENGINES_DATA, engine_data, ENGINES_IS_VISIBLE, !engine_data->is_hidden, ENGINES_NAME, engine_data->screen_name, ENGINES_COMMAND_LINE, engine_data->command_line, -1); #else gtk_list_store_set (gtp_engines_list_store, &iterator, ENGINES_DATA, engine_data, ENGINES_IS_VISIBLE, !engine_data->is_hidden, ENGINES_NAME, engine_data->screen_name, -1); #endif } g_signal_connect (GTK_TREE_MODEL (gtp_engines_list_store), "row-changed", G_CALLBACK (handle_drag_and_drop), NULL); gui_back_end_register_object_to_finalize (gtp_engines_list_store); #if GTK_2_4_OR_LATER non_hidden_gtp_engines_tree_model = gtk_tree_model_filter_new (GTK_TREE_MODEL (gtp_engines_list_store), NULL); gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (non_hidden_gtp_engines_tree_model), ENGINES_IS_VISIBLE); gui_back_end_register_object_to_finalize (non_hidden_gtp_engines_tree_model); for (k = 0; k < NUM_SUPPORTED_GAMES; k++) { only_one_game_gtp_engines_tree_model[k] = gtk_tree_model_filter_new (GTK_TREE_MODEL (gtp_engines_list_store), NULL); gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (only_one_game_gtp_engines_tree_model[k]), engine_is_visible_and_supports_game, GINT_TO_POINTER (k), NULL); gui_back_end_register_object_to_finalize (only_one_game_gtp_engines_tree_model[k]); } #endif } static void handle_drag_and_drop (GtkTreeModel *gtp_engines_tree_model, GtkTreePath *tree_path, GtkTreeIter *iterator) { GtpEngineListItem *engine_data; GtpEngineListItem *notch = NULL; gtk_tree_model_get (gtp_engines_tree_model, iterator, ENGINES_DATA, &engine_data, -1); if (gtk_tree_path_prev (tree_path)) { GtkTreeIter notch_iterator; gtk_tree_model_get_iter (gtp_engines_tree_model, ¬ch_iterator, tree_path); gtk_tree_model_get (gtp_engines_tree_model, ¬ch_iterator, ENGINES_DATA, ¬ch, -1); /* Restore tree path just in case GTK+ needs it. */ gtk_tree_path_next (tree_path); if (engine_data == notch) { /* Nothing to do. */ return; } } prepare_to_rebuild_menus (); string_list_move (>p_engines, engine_data, notch); rebuild_all_menus (); } void gtk_preferences_dialog_present (gpointer page_to_select) { static const PreferencesDialogCategory preferences_dialog_categories[] = { { NULL, GTK_STOCK_INDEX, N_("General"), NULL, NULL }, { create_gtk_ui_page, NULL, N_("Interface"), NULL, N_("General Interface") }, { NULL, GTK_STOCK_CUT, N_("Editing & Viewing"), NULL, NULL }, { create_game_tree_page, NULL, N_("Game Tree"), NULL, N_("Game Tree") }, { NULL, GTK_STOCK_PREFERENCES, N_("GTP"), NULL, NULL }, { create_gtp_engines_page, NULL, N_("GTP Engines"), GTK_STOCK_EXECUTE, N_("GTP Engines") }, { NULL, QUARRY_STOCK_ICON_FILE, N_("Game Records (SGF)"), NULL, NULL }, { create_saving_sgf_page, NULL, N_("Saving"), GTK_STOCK_SAVE, N_("Saving Game Records") }, { NULL, GTK_STOCK_SELECT_COLOR, N_("Board Appearance"), NULL, NULL }, { create_go_board_appearance_page, NULL, NULL, GTK_STOCK_SELECT_COLOR, N_("Go Board Appearance") }, { create_amazons_board_appearance_page, NULL, NULL, GTK_STOCK_SELECT_COLOR, N_("Amazons Board Appearance") }, { create_reversi_board_appearance_page, NULL, NULL, GTK_STOCK_SELECT_COLOR, N_("Reversi Board Appearance") } }; int k; GtkTreePath *tree_path; gint page_to_select_gint = (GPOINTER_TO_INT (page_to_select) >= 0 ? GPOINTER_TO_INT (page_to_select) : last_selected_page); if (!preferences_dialog) { GtkWidget *dialog = gtk_dialog_new_with_buttons (_("Preferences"), NULL, 0, GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, NULL); GtkTreeStore *categories; GtkWidget *category_list; GtkWidget *label; GtkCellRenderer *renderer; GtkTreeViewColumn *column; GtkWidget *notebook_widget; GtkNotebook *notebook; GtkWidget *vbox; GtkWidget *hbox; GtkTreeIter category_parent; int page_index; int game_index; preferences_dialog = GTK_WINDOW (dialog); gtk_control_center_window_created (preferences_dialog); gtk_utils_null_pointer_on_destroy (&preferences_dialog, TRUE); gtk_utils_add_help_button (GTK_DIALOG (dialog)); g_signal_connect (preferences_dialog, "response", G_CALLBACK (gtk_preferences_dialog_response), NULL); categories = gtk_tree_store_new (CATEGORIES_NUM_COLUMNS, G_TYPE_INT, #if GTK_2_2_OR_LATER G_TYPE_STRING, #endif G_TYPE_STRING); category_list = gtk_tree_view_new_with_model (GTK_TREE_MODEL (categories)); category_tree_view = GTK_TREE_VIEW (category_list); gtk_tree_view_set_headers_visible (category_tree_view, FALSE); g_object_unref (categories); label = gtk_utils_create_mnemonic_label (_("Categor_y:"), category_list); vbox = gtk_utils_pack_in_box (GTK_TYPE_VBOX, QUARRY_SPACING_SMALL, label, GTK_UTILS_FILL, gtk_utils_sink_widget (category_list), GTK_UTILS_PACK_DEFAULT, NULL); #if GTK_2_2_OR_LATER renderer = gtk_cell_renderer_pixbuf_new (); column = gtk_tree_view_column_new_with_attributes (NULL, renderer, "stock-id", CATEGORIES_ICON, NULL); gtk_tree_view_append_column (category_tree_view, column); #endif renderer = gtk_cell_renderer_text_new (); column = gtk_tree_view_column_new_with_attributes (NULL, renderer, "markup", CATEGORIES_TEXT, NULL); gtk_tree_view_append_column (category_tree_view, column); notebook_widget = gtk_utils_create_invisible_notebook (); notebook = GTK_NOTEBOOK (notebook_widget); g_signal_connect (gtk_tree_view_get_selection (category_tree_view), "changed", G_CALLBACK (gtk_preferences_dialog_change_page), notebook); for (k = 0, page_index = 0, game_index = 0; k < (sizeof preferences_dialog_categories / sizeof (PreferencesDialogCategory)); k++) { GtkTreeIter iterator; const PreferencesDialogCategory *category_data = preferences_dialog_categories + k; const gchar *tree_title; int this_page_index; if (category_data->create_page) { GtkWidget *page = gtk_utils_create_titled_page (category_data->create_page (), category_data->page_icon_stock_id, _(category_data->page_title)); gtk_notebook_append_page (notebook, page, NULL); gtk_tree_store_append (categories, &iterator, &category_parent); this_page_index = page_index++; } else { gtk_tree_store_append (categories, &category_parent, NULL); iterator = category_parent; this_page_index = -1; } if (category_data->tree_title) tree_title = _(category_data->tree_title); else { tree_title = gtk_games_get_capitalized_name (index_to_game[game_index++]); } gtk_tree_store_set (categories, &iterator, CATEGORIES_PAGE_INDEX, this_page_index, #if GTK_2_2_OR_LATER CATEGORIES_ICON, category_data->tree_icon_stock_id, #endif CATEGORIES_TEXT, tree_title, -1); } gtk_tree_view_expand_all (category_tree_view); hbox = gtk_utils_pack_in_box (GTK_TYPE_HBOX, QUARRY_SPACING, vbox, GTK_UTILS_FILL, gtk_vseparator_new (), GTK_UTILS_FILL, notebook_widget, GTK_UTILS_PACK_DEFAULT, NULL); gtk_utils_standardize_dialog (GTK_DIALOG (dialog), hbox); gtk_widget_show_all (hbox); } if (page_to_select_gint < NUM_PREFERENCES_DIALOG_PAGES) { int category_to_select; int subcategory_to_select; for (category_to_select = -1, subcategory_to_select = -1, k = 0; page_to_select_gint >= 0; k++) { if (preferences_dialog_categories[k].create_page) { page_to_select_gint--; subcategory_to_select++; } else { category_to_select++; subcategory_to_select = -1; } } #if GTK_2_2_OR_LATER tree_path = gtk_tree_path_new_from_indices (category_to_select, subcategory_to_select, -1); #else tree_path = gtk_tree_path_new (); gtk_tree_path_append_index (tree_path, category_to_select); gtk_tree_path_append_index (tree_path, subcategory_to_select); #endif gtk_tree_view_set_cursor (category_tree_view, tree_path, NULL, FALSE); gtk_tree_path_free (tree_path); } else g_warning ("unknown page index %d", page_to_select_gint); gtk_window_present (preferences_dialog); } static GtkWidget * create_gtk_ui_page (void) { #if GTK_2_4_OR_LATER static const gchar *radio_labels[2] = { N_("Use _newer (GTK+ 2.4) file chooser"), N_("Use _old-style file selection dialog") }; GtkWidget *radio_buttons[2]; GtkWidget *file_chooser_named_vbox; #endif GtkWidget *main_toolbar_hbox; GtkWidget *editing_toolbar_hbox; GtkWidget *navigation_toolbar_hbox; GtkWidget *toolbars_named_vbox; #if GTK_2_4_OR_LATER gtk_utils_create_radio_chain (radio_buttons, radio_labels, 2); if (!gtk_ui_configuration.use_gtk_file_chooser) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio_buttons[1]), TRUE); g_signal_connect (radio_buttons[0], "toggled", G_CALLBACK (store_toggle_setting), >k_ui_configuration.use_gtk_file_chooser); file_chooser_named_vbox = gtk_utils_pack_in_box (GTK_TYPE_NAMED_VBOX, QUARRY_SPACING_SMALL, radio_buttons[0], GTK_UTILS_FILL, radio_buttons[1], GTK_UTILS_FILL, NULL); gtk_named_vbox_set_label_text (GTK_NAMED_VBOX (file_chooser_named_vbox), _("File Chooser Dialog Style")); #endif /* GTK_2_4_OR_LATER */ /* Let's be over-secure (a compile-time error would have been * better...) */ g_assert (TOOLBAR_STYLE_DEFAULT == 0 && TOOLBAR_STYLE_BOTH == 1 && TOOLBAR_STYLE_BOTH_HORIZONTALLY == 2 && TOOLBAR_STYLE_ICONS_ONLY == 3 && TOOLBAR_STYLE_TEXT_ONLY == 4); main_toolbar_hbox = create_toolbar_style_box (gtk_ui_configuration.main_toolbar_style, &main_toolbar_list, _("_Main toolbar style:")); editing_toolbar_hbox = create_toolbar_style_box (gtk_ui_configuration.editing_toolbar_style, &editing_toolbar_list, _("_Editing toolbar style:")); navigation_toolbar_hbox = create_toolbar_style_box (gtk_ui_configuration.navigation_toolbar_style, &navigation_toolbar_list, _("N_avigation toolbar style:")); toolbars_named_vbox = gtk_utils_pack_in_box (GTK_TYPE_NAMED_VBOX, QUARRY_SPACING_SMALL, main_toolbar_hbox, GTK_UTILS_FILL, editing_toolbar_hbox, GTK_UTILS_FILL, navigation_toolbar_hbox, GTK_UTILS_FILL, NULL); gtk_named_vbox_set_label_text (GTK_NAMED_VBOX (toolbars_named_vbox), _("Toolbar Styles")); gtk_utils_align_left_widgets (GTK_CONTAINER (toolbars_named_vbox), NULL); #if GTK_2_4_OR_LATER return gtk_utils_pack_in_box (GTK_TYPE_VBOX, QUARRY_SPACING_BIG, file_chooser_named_vbox, GTK_UTILS_FILL, toolbars_named_vbox, GTK_UTILS_FILL, NULL); #else return toolbars_named_vbox; #endif } static GtkWidget * create_toolbar_style_box (gint item_to_select, GtkToolbarList *toolbar_list, const gchar *label_text) { /* NOTE: Keep in sync with values in `gtk-configuration.list'. */ static const gchar *toolbar_styles[] = { N_("Desktop default"), N_("Text below icons"), #if GTK_2_4_OR_LATER /* I don't know of a simple way of making this work on earlier * GTK+ versions. */ N_("Text beside important icons"), #endif N_("Icons only"), N_("Text only") }; GtkWidget *selector; GtkWidget *label; #if !GTK_2_4_OR_LATER /* See toolbar_styles[] for explanation. */ if (item_to_select >= TOOLBAR_STYLE_BOTH_HORIZONTALLY) item_to_select--; #endif selector = gtk_utils_create_selector (toolbar_styles, (sizeof toolbar_styles / sizeof (const gchar *)), item_to_select); g_signal_connect (selector, "changed", G_CALLBACK (change_toolbar_style), toolbar_list); label = gtk_utils_create_mnemonic_label (label_text, selector); return gtk_utils_pack_in_box (GTK_TYPE_HBOX, QUARRY_SPACING, label, GTK_UTILS_FILL, selector, GTK_UTILS_FILL, NULL); } static GtkWidget * create_gtp_engines_page (void) { GtkWidget *gtp_engines_widget; GtkWidget *label; GtkCellRenderer *renderer; GtkTreeViewColumn *column; GtkWidget *scrolled_window; GtkWidget *add_gtp_engine; GtkWidget *button_box; GtkWidget *hbox; GtkWidget *vbox; GtkWidget *info_label; GtkWidget *name_hbox; GtkWidget *version_hbox; GtkWidget *supported_games_hbox; GtkWidget *command_line_hbox; GtkWidget *info_vbox; gtp_engines_widget = gtk_tree_view_new_with_model (GTK_TREE_MODEL (gtp_engines_list_store)); gtp_engines_tree_view = GTK_TREE_VIEW (gtp_engines_widget); gtk_tree_view_set_reorderable (gtp_engines_tree_view, TRUE); renderer = gtk_cell_renderer_toggle_new (); g_object_set (renderer, "activatable", TRUE, NULL); g_signal_connect (renderer, "toggled", G_CALLBACK (show_or_hide_gtp_engine), NULL); column = gtk_tree_view_column_new_with_attributes (_("Show"), renderer, "active", ENGINES_IS_VISIBLE, NULL); gtk_tree_view_append_column (gtp_engines_tree_view, column); renderer = gtk_cell_renderer_text_new (); column = gtk_tree_view_column_new_with_attributes (_("Name"), renderer, "text", ENGINES_NAME, NULL); gtk_tree_view_append_column (gtp_engines_tree_view, column); scrolled_window = gtk_utils_make_widget_scrollable (gtp_engines_widget, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); label = gtk_utils_create_mnemonic_label (_("_List of GTP engines:"), gtp_engines_widget); add_gtp_engine = gtk_button_new_from_stock (GTK_STOCK_ADD); g_signal_connect_swapped (add_gtp_engine, "clicked", G_CALLBACK (gtk_gtp_engine_dialog_present), GINT_TO_POINTER (TRUE)); modify_gtp_engine = gtk_button_new_from_stock (QUARRY_STOCK_MODIFY); g_signal_connect_swapped (modify_gtp_engine, "clicked", G_CALLBACK (gtk_gtp_engine_dialog_present), GINT_TO_POINTER (FALSE)); remove_gtp_engine = gtk_button_new_from_stock (GTK_STOCK_REMOVE); g_signal_connect (remove_gtp_engine, "clicked", G_CALLBACK (do_remove_gtp_engine), NULL); move_gtp_engine_up = gtk_button_new_from_stock (QUARRY_STOCK_MOVE_UP); g_signal_connect_swapped (move_gtp_engine_up, "clicked", G_CALLBACK (do_move_gtp_engine), GINT_TO_POINTER (TRUE)); move_gtp_engine_down = gtk_button_new_from_stock (QUARRY_STOCK_MOVE_DOWN); g_signal_connect_swapped (move_gtp_engine_down, "clicked", G_CALLBACK (do_move_gtp_engine), GINT_TO_POINTER (FALSE)); button_box = gtk_utils_pack_in_box (GTK_TYPE_VBUTTON_BOX, QUARRY_SPACING_SMALL, add_gtp_engine, 0, modify_gtp_engine, 0, remove_gtp_engine, 0, move_gtp_engine_up, 0, move_gtp_engine_down, 0, NULL); gtk_button_box_set_layout (GTK_BUTTON_BOX (button_box), GTK_BUTTONBOX_START); gtk_button_box_set_child_secondary (GTK_BUTTON_BOX (button_box), move_gtp_engine_up, TRUE); gtk_button_box_set_child_secondary (GTK_BUTTON_BOX (button_box), move_gtp_engine_down, TRUE); hbox = gtk_utils_pack_in_box (GTK_TYPE_HBOX, QUARRY_SPACING, scrolled_window, GTK_UTILS_PACK_DEFAULT, button_box, GTK_UTILS_FILL, NULL); vbox = gtk_utils_pack_in_box (GTK_TYPE_VBOX, QUARRY_SPACING_SMALL, label, GTK_UTILS_FILL, hbox, GTK_UTILS_PACK_DEFAULT, NULL); label = gtk_utils_create_left_aligned_label (_("Name:")); info_label = gtk_utils_create_left_aligned_label (NULL); gtp_engine_name = GTK_LABEL (info_label); gtk_label_set_selectable (gtp_engine_name, TRUE); name_hbox = gtk_utils_pack_in_box (GTK_TYPE_HBOX, QUARRY_SPACING, label, GTK_UTILS_FILL, info_label, GTK_UTILS_PACK_DEFAULT, NULL); label = gtk_utils_create_left_aligned_label (_("Version:")); info_label = gtk_utils_create_left_aligned_label (NULL); gtp_engine_version = GTK_LABEL (info_label); gtk_label_set_selectable (gtp_engine_version, TRUE); version_hbox = gtk_utils_pack_in_box (GTK_TYPE_HBOX, QUARRY_SPACING, label, GTK_UTILS_FILL, info_label, GTK_UTILS_PACK_DEFAULT, NULL); label = gtk_utils_create_left_aligned_label (_("Supported game:")); gtp_engine_supported_games_label = GTK_LABEL (label); info_label = gtk_utils_create_left_aligned_label (NULL); gtp_engine_supported_games = GTK_LABEL (info_label); gtk_label_set_selectable (gtp_engine_supported_games, TRUE); supported_games_hbox = gtk_utils_pack_in_box (GTK_TYPE_HBOX, QUARRY_SPACING, label, GTK_UTILS_FILL, info_label, GTK_UTILS_PACK_DEFAULT, NULL); label = gtk_utils_create_left_aligned_label (_("Command line:")); info_label = gtk_utils_create_left_aligned_label (NULL); gtp_engine_command_line = GTK_LABEL (info_label); gtk_label_set_selectable (gtp_engine_command_line, TRUE); command_line_hbox = gtk_utils_pack_in_box (GTK_TYPE_HBOX, QUARRY_SPACING, label, GTK_UTILS_FILL, info_label, GTK_UTILS_PACK_DEFAULT, NULL); info_vbox = gtk_utils_pack_in_box (GTK_TYPE_VBOX, QUARRY_SPACING_SMALL, name_hbox, GTK_UTILS_FILL, version_hbox, GTK_UTILS_FILL, supported_games_hbox, GTK_UTILS_FILL, command_line_hbox, GTK_UTILS_FILL, NULL); label = gtk_utils_create_left_aligned_label (NULL); gtp_engine_additional_info = GTK_LABEL (label); gtp_engine_info = gtk_utils_pack_in_box (GTK_TYPE_NAMED_VBOX, QUARRY_SPACING_BIG, info_vbox, GTK_UTILS_FILL, label, GTK_UTILS_FILL, NULL); gtk_named_vbox_set_label_text (GTK_NAMED_VBOX (gtp_engine_info), _("GTP Engine Information")); gtk_utils_align_left_widgets (GTK_CONTAINER (gtp_engine_info), NULL); gtp_engines_tree_selection = gtk_tree_view_get_selection (gtp_engines_tree_view); g_signal_connect (gtp_engines_tree_selection, "changed", G_CALLBACK (gtk_preferences_dialog_update_gtp_engine_info), NULL); gtk_preferences_dialog_update_gtp_engine_info (gtp_engines_tree_selection); return gtk_utils_pack_in_box (GTK_TYPE_VBOX, QUARRY_SPACING_BIG, vbox, GTK_UTILS_PACK_DEFAULT, gtp_engine_info, GTK_UTILS_FILL, NULL); } static GtkWidget * create_game_tree_page (void) { static const gchar *show_game_tree_radio_labels[3] = { N_("_Always"), N_("A_utomatically"), N_("_Never") }; static const gchar *track_current_node_radio_labels[3] = { N_("Al_ways"), N_("Aut_omatically"), N_("Ne_ver") }; static const gchar *scroll_method_radio_labels[2] = { N_("Scroll _minimal distance"), N_("_Recenter view on the current node") }; static const gchar *show_game_tree_hint = N_("In automatic mode the game tree is shown only if it has at least " "one variation. In any case, you can show/hide game tree in each " "window separately."); static const gchar *track_current_node_hint = N_("In automatic mode the game tree view scrolls to show the current " "node only if it has been showing current node before. I.e. unless " "you scrolled it away manually."); GtkWidget *radio_buttons[3]; GtkWidget *label; GtkWidget *show_game_tree_named_vbox; GtkWidget *scroll_method_radio_buttons[2]; GtkWidget *track_current_node_named_vbox; GtkWidget *tooltips_check_button; GtkWidget *tooltips_named_vbox; int k; /* Let's be over-secure (a compile-time error would have been * better...) */ g_assert (SHOW_GAME_TREE_ALWAYS == 0 && SHOW_GAME_TREE_AUTOMATICALLY == 1 && SHOW_GAME_TREE_NEVER == 2 && TRACK_CURRENT_NODE_ALWAYS == 0 && TRACK_CURRENT_NODE_AUTOMATICALLY == 1 && TRACK_CURRENT_NODE_NEVER == 2); gtk_utils_create_radio_chain (radio_buttons, show_game_tree_radio_labels, 3); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio_buttons[game_tree_view.show_game_tree]), TRUE); for (k = 0; k < sizeof radio_buttons / sizeof (GtkWidget *); k++) { g_signal_connect (radio_buttons[k], "toggled", G_CALLBACK (store_radio_button_setting), &game_tree_view.show_game_tree); } label = gtk_utils_create_left_aligned_label (_(show_game_tree_hint)); gtk_label_set_line_wrap (GTK_LABEL (label), TRUE); show_game_tree_named_vbox = gtk_utils_pack_in_box (GTK_TYPE_NAMED_VBOX, QUARRY_SPACING_SMALL, radio_buttons[0], GTK_UTILS_FILL, radio_buttons[1], GTK_UTILS_FILL, radio_buttons[2], GTK_UTILS_FILL, label, GTK_UTILS_FILL, NULL); gtk_named_vbox_set_label_text (GTK_NAMED_VBOX (show_game_tree_named_vbox), _("Show Game Tree")); gtk_utils_create_radio_chain (radio_buttons, track_current_node_radio_labels, 3); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio_buttons[game_tree_view.track_current_node]), TRUE); for (k = 0; k < sizeof radio_buttons / sizeof (GtkWidget *); k++) { g_signal_connect (radio_buttons[k], "toggled", G_CALLBACK (store_radio_button_setting), &game_tree_view.track_current_node); } gtk_utils_create_radio_chain (scroll_method_radio_buttons, scroll_method_radio_labels, 2); if (game_tree_view.center_on_current_node) { gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (scroll_method_radio_buttons[1]), TRUE); } g_signal_connect (scroll_method_radio_buttons[1], "toggled", G_CALLBACK (store_toggle_setting), &game_tree_view.center_on_current_node); gtk_utils_set_sensitive_on_toggle (GTK_TOGGLE_BUTTON (radio_buttons[2]), scroll_method_radio_buttons[0], TRUE); gtk_utils_set_sensitive_on_toggle (GTK_TOGGLE_BUTTON (radio_buttons[2]), scroll_method_radio_buttons[1], TRUE); label = gtk_utils_create_left_aligned_label (_(track_current_node_hint)); gtk_label_set_line_wrap (GTK_LABEL (label), TRUE); track_current_node_named_vbox = gtk_utils_pack_in_box (GTK_TYPE_NAMED_VBOX, QUARRY_SPACING_SMALL, radio_buttons[0], GTK_UTILS_FILL, radio_buttons[1], GTK_UTILS_FILL, radio_buttons[2], GTK_UTILS_FILL, label, GTK_UTILS_FILL | QUARRY_SPACING_SMALL, scroll_method_radio_buttons[0], GTK_UTILS_FILL, scroll_method_radio_buttons[1], GTK_UTILS_FILL, NULL); gtk_named_vbox_set_label_text (GTK_NAMED_VBOX (track_current_node_named_vbox), _("Track Tree's Current Node")); tooltips_check_button = gtk_check_button_new_with_mnemonic (_("Show _tooltips")); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (tooltips_check_button), game_tree_view.show_tooltips); g_signal_connect (tooltips_check_button, "toggled", G_CALLBACK (update_game_tree_tooltips_status), NULL); tooltips_named_vbox = gtk_named_vbox_new (_("Tooltips"), FALSE, QUARRY_SPACING_SMALL); gtk_box_pack_start (GTK_BOX (tooltips_named_vbox), tooltips_check_button, TRUE, FALSE, 0); return gtk_utils_pack_in_box (GTK_TYPE_VBOX, QUARRY_SPACING_BIG, show_game_tree_named_vbox, GTK_UTILS_FILL, track_current_node_named_vbox, GTK_UTILS_FILL, tooltips_named_vbox, GTK_UTILS_FILL, NULL); } static GtkWidget * create_saving_sgf_page (void) { static const gchar *radio_labels[2] = { N_("Always use _UTF-8 (recommended)"), N_("Preserve _original encoding") }; static const gchar *hint = N_("Note that many characters cannot be represented in non-UTF-8 " "encodings and thus some information may be lost if you use them. " "Quarry also works fastest with UTF-8; this may be important " "if you have very large SGF files."); GtkWidget *radio_buttons[2]; GtkWidget *label; GtkWidget *named_vbox; gtk_utils_create_radio_chain (radio_buttons, radio_labels, 2); if (!sgf_configuration.force_utf8) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio_buttons[1]), TRUE); g_signal_connect (radio_buttons[0], "toggled", G_CALLBACK (store_toggle_setting), &sgf_configuration.force_utf8); label = gtk_utils_create_left_aligned_label (_(hint)); gtk_label_set_line_wrap (GTK_LABEL (label), TRUE); named_vbox = gtk_utils_pack_in_box (GTK_TYPE_NAMED_VBOX, QUARRY_SPACING_SMALL, radio_buttons[0], GTK_UTILS_FILL, radio_buttons[1], GTK_UTILS_FILL, label, GTK_UTILS_FILL, NULL); gtk_named_vbox_set_label_text (GTK_NAMED_VBOX (named_vbox), _("Encoding")); return named_vbox; } static GtkWidget * create_go_board_appearance_page (void) { static const gchar *labels[4] = { N_("_Relative to stone size"), N_("On _white stones:"), N_("On _black stones:"), N_("On _empty intersections:") }; GtkWidget *background_table = create_background_table (GTK_GAME_GO, 3); GtkWidget *markup_box = create_markup_box (GTK_GAME_GO, labels); return create_board_appearance_notebook_page (background_table, markup_box); } static GtkWidget * create_amazons_board_appearance_page (void) { static const gchar *labels[4] = { N_("_Relative to amazon size"), N_("On _white amazons:"), N_("On _black amazons:"), N_("On _empty fields:") }; GtkWidget *background_table = create_background_table (GTK_GAME_AMAZONS, 5); GtkTable *table = GTK_TABLE (background_table); GtkWidget *markup_box = create_markup_box (GTK_GAME_AMAZONS, labels); QuarryColor *quarry_color = &amazons_board_appearance.checkerboard_pattern_color; GdkColor color; GtkWidget *color_button; GtkWidget *label; double opacity = amazons_board_appearance.checkerboard_pattern_opacity; GtkWidget *scale; gtk_table_set_row_spacing (table, 3, QUARRY_SPACING); gtk_utils_set_gdk_color (&color, *quarry_color); color_button = gtk_color_button_new_with_color (&color); gtk_color_button_set_title (GTK_COLOR_BUTTON (color_button), _("Pick Checkerboard Pattern Color")); g_signal_connect (color_button, "color-set", G_CALLBACK (update_board_appearance), &amazons_board_appearance.checkerboard_pattern_color); gtk_table_attach (table, color_button, 1, 2, 2, 3, GTK_EXPAND | GTK_FILL, 0, 0, 0); label = gtk_utils_create_mnemonic_label (_("Checkerboard _pattern color:"), color_button); gtk_table_attach (table, label, 0, 1, 2, 3, GTK_FILL, 0, 0, 0); scale = gtk_hscale_new_with_range (0.0, 1.0, 0.05); gtk_scale_set_draw_value (GTK_SCALE (scale), FALSE); gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_DELAYED); gtk_range_set_value (GTK_RANGE (scale), opacity); g_signal_connect (scale, "value-changed", G_CALLBACK (update_board_appearance), &amazons_board_appearance.checkerboard_pattern_opacity); gtk_table_attach (table, scale, 1, 2, 3, 4, GTK_EXPAND | GTK_FILL, 0, 0, 0); label = gtk_utils_create_mnemonic_label (_("Checkerboard pattern _opacity:"), scale); gtk_table_attach (table, label, 0, 1, 3, 4, GTK_FILL, 0, 0, 0); return create_board_appearance_notebook_page (background_table, markup_box); } static GtkWidget * create_reversi_board_appearance_page (void) { static const gchar *labels[4] = { N_("_Relative to disk size"), N_("On _white disks:"), N_("On _black disks:"), N_("On _empty fields:") }; GtkWidget *background_table = create_background_table (GTK_GAME_REVERSI, 3); GtkWidget *markup_box = create_markup_box (GTK_GAME_REVERSI, labels); return create_board_appearance_notebook_page (background_table, markup_box); } static GtkWidget * create_background_table (GtkGameIndex game_index, gint num_table_rows) { static const gchar *radio_button_labels[2] = { N_("Use _texture:"), N_("Use _solid color:") }; BoardAppearance *board_appearance = game_index_to_board_appearance_structure (game_index); GtkWidget *table_widget = gtk_table_new (num_table_rows, 3, FALSE); GtkTable *table = GTK_TABLE (table_widget); GdkColor color; GtkWidget *radio_buttons[2]; GtkWidget *label; GtkWidget *file_selector; GtkWidget *button; GtkWidget *color_button; gtk_table_set_row_spacings (table, QUARRY_SPACING_SMALL); gtk_table_set_row_spacing (table, 1, QUARRY_SPACING); gtk_table_set_col_spacing (table, 0, QUARRY_SPACING); gtk_table_set_col_spacing (table, 1, QUARRY_SPACING_SMALL); gtk_utils_create_radio_chain (radio_buttons, radio_button_labels, 2); if (!board_appearance->use_background_texture) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio_buttons[1]), TRUE); g_signal_connect (radio_buttons[0], "toggled", G_CALLBACK (update_board_appearance), &board_appearance->use_background_texture); gtk_table_attach (table, radio_buttons[0], 0, 1, 0, 1, GTK_FILL, 0, 0, 0); gtk_table_attach (table, radio_buttons[1], 0, 1, 1, 2, GTK_FILL, 0, 0, 0); #ifdef GTK_TYPE_FILE_SELECTOR file_selector = gtk_file_selector_new (); gtk_file_selector_set_glob_patterns (GTK_FILE_SELECTOR (file_selector), "*.jpg\0*.png\0"); if (board_appearance->background_texture) { gtk_file_selector_set_text (GTK_FILE_SELECTOR (file_selector), board_appearance->background_texture); } #else /* not defined GTK_TYPE_FILE_SELECTOR */ file_selector = gtk_utils_create_entry (board_appearance->background_texture, RETURN_DEFAULT_MODE); #endif /* not defined GTK_TYPE_FILE_SELECTOR */ /* We use the name `file_selector' for the entry only to have fewer * forks on whether GTK_TYPE_FILE_SELECTOR is defined. */ gtk_utils_set_sensitive_on_toggle (GTK_TOGGLE_BUTTON (radio_buttons[0]), file_selector, FALSE); #ifdef GTK_TYPE_FILE_SELECTOR g_signal_connect (GTK_BIN (file_selector)->child, "focus-out-event", G_CALLBACK (update_board_background_texture), GINT_TO_POINTER (game_index)); g_signal_connect (file_selector, "changed", G_CALLBACK (board_background_texture_changed), GINT_TO_POINTER (game_index)); #else /* not defined GTK_TYPE_FILE_SELECTOR */ g_signal_connect (file_selector, "focus-out-event", G_CALLBACK (update_board_background_texture), GINT_TO_POINTER (game_index)); #endif /* not defined GTK_TYPE_FILE_SELECTOR */ gtk_table_attach (table, file_selector, 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, 0, 0, 0); button = gtk_utils_create_browse_button (FALSE, file_selector, FALSE, _("Choose a Background Texture..."), update_board_background_texture, GINT_TO_POINTER (game_index)); gtk_utils_set_sensitive_on_toggle (GTK_TOGGLE_BUTTON (radio_buttons[0]), button, FALSE); gtk_table_attach (table, button, 2, 3, 0, 1, GTK_FILL, 0, GTK_FILL, 0); gtk_utils_set_gdk_color (&color, board_appearance->background_color); color_button = gtk_color_button_new_with_color (&color); gtk_color_button_set_title (GTK_COLOR_BUTTON (color_button), _("Pick Background Color")); gtk_utils_set_sensitive_on_toggle (GTK_TOGGLE_BUTTON (radio_buttons[1]), color_button, FALSE); g_signal_connect (color_button, "color-set", G_CALLBACK (update_board_appearance), &board_appearance->background_color); gtk_table_attach (table, color_button, 1, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 0, 0); gtk_utils_set_gdk_color (&color, board_appearance->grid_and_labels_color); color_button = gtk_color_button_new_with_color (&color); gtk_color_button_set_title (GTK_COLOR_BUTTON (color_button), _("Pick Color for Grid and Labels")); g_signal_connect (color_button, "color-set", G_CALLBACK (update_board_appearance), &board_appearance->grid_and_labels_color); gtk_table_attach (table, color_button, 1, 2, num_table_rows - 1, num_table_rows, GTK_EXPAND | GTK_FILL, 0, 0, 0); label = gtk_utils_create_mnemonic_label (_("_Grid and labels color:"), color_button); gtk_table_attach (table, label, 0, 1, num_table_rows - 1, num_table_rows, GTK_FILL, 0, 0, 0); return table_widget; } static GtkWidget * create_markup_box (GtkGameIndex game_index, const gchar *labels[4]) { UseThemeDefaultsData *use_theme_defaults_data = g_malloc (sizeof (UseThemeDefaultsData)); BoardAppearance *board_appearance = game_index_to_board_appearance_structure (game_index); GtkWidget *selector; GtkWidget *theme_label; GtkWidget *theme_hbox; GtkWidget *use_theme_defaults_check_button; GtkWidget *scale; GtkWidget *label; GtkWidget *hbox; GtkWidget *check_button; GtkWidget *vbox; GtkWidget *size_and_opacity_named_vbox; GtkWidget *color_named_vbox; GtkSizeGroup *size_group; int k; use_theme_defaults_data->game = index_to_game[game_index]; selector = gtk_utils_create_selector_from_string_list (&markup_themes, (board_appearance ->markup_theme)); g_signal_connect (selector, "changed", G_CALLBACK (update_board_markup_theme), use_theme_defaults_data); theme_label = gtk_utils_create_mnemonic_label (_("_Theme:"), selector); theme_hbox = gtk_utils_pack_in_box (GTK_TYPE_HBOX, 0, theme_label, 0, selector, GTK_UTILS_FILL | QUARRY_SPACING, NULL); use_theme_defaults_check_button = gtk_check_button_new_with_mnemonic (_("Use theme _defaults")); g_signal_connect (use_theme_defaults_check_button, "toggled", G_CALLBACK (update_markup_theme_defaults_usage), use_theme_defaults_data); g_signal_connect_swapped (use_theme_defaults_check_button, "destroy", G_CALLBACK (g_free), use_theme_defaults_data); scale = gtk_hscale_new_with_range (0.2, 1.0, 0.05); use_theme_defaults_data->size_range = GTK_RANGE (scale); gtk_scale_set_draw_value (GTK_SCALE (scale), FALSE); gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_DELAYED); g_signal_connect (scale, "value-changed", G_CALLBACK (update_board_appearance), &board_appearance->markup_size); label = gtk_utils_create_mnemonic_label (_("_Size:"), scale); hbox = gtk_utils_pack_in_box (GTK_TYPE_HBOX, QUARRY_SPACING, label, 0, scale, GTK_UTILS_PACK_DEFAULT, NULL); check_button = gtk_check_button_new_with_mnemonic (_(labels[0])); use_theme_defaults_data->size_is_relative_toggle_button = GTK_TOGGLE_BUTTON (check_button); vbox = gtk_utils_pack_in_box (GTK_TYPE_VBOX, QUARRY_SPACING_SMALL, hbox, GTK_UTILS_FILL, check_button, GTK_UTILS_FILL, NULL); g_signal_connect (check_button, "toggled", G_CALLBACK (update_board_appearance), &board_appearance->markup_size_is_relative); scale = gtk_hscale_new_with_range (0.2, 1.0, 0.05); use_theme_defaults_data->opacity_range = GTK_RANGE (scale); gtk_scale_set_draw_value (GTK_SCALE (scale), FALSE); gtk_range_set_update_policy (use_theme_defaults_data->opacity_range, GTK_UPDATE_DELAYED); g_signal_connect (scale, "value-changed", G_CALLBACK (update_board_appearance), &board_appearance->markup_opacity); label = gtk_utils_create_mnemonic_label (_("_Opacity:"), scale); hbox = gtk_utils_pack_in_box (GTK_TYPE_HBOX, QUARRY_SPACING, label, 0, scale, GTK_UTILS_PACK_DEFAULT, NULL); use_theme_defaults_data->vbox = gtk_utils_pack_in_box (GTK_TYPE_VBOX, QUARRY_SPACING, vbox, GTK_UTILS_FILL, hbox, GTK_UTILS_FILL, NULL); size_and_opacity_named_vbox = gtk_utils_pack_in_box (GTK_TYPE_NAMED_VBOX, QUARRY_SPACING, use_theme_defaults_check_button, GTK_UTILS_FILL, use_theme_defaults_data->vbox, GTK_UTILS_FILL, NULL); gtk_named_vbox_set_label_text (GTK_NAMED_VBOX (size_and_opacity_named_vbox), _("Size & Opacity")); size_group = (gtk_utils_align_left_widgets (GTK_CONTAINER (size_and_opacity_named_vbox), NULL)); gtk_size_group_add_widget (size_group, theme_label); if (board_appearance->use_theme_defaults) { gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (use_theme_defaults_check_button), TRUE); } else { update_markup_theme_defaults_usage (GTK_TOGGLE_BUTTON (use_theme_defaults_check_button), use_theme_defaults_data); } color_named_vbox = gtk_named_vbox_new (_("Color"), FALSE, QUARRY_SPACING_SMALL); size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); for (k = 0; k < NUM_SGF_MARKUP_BACKGROUNDS; k++) { GdkColor color; GtkWidget *color_button; int color_index = (NUM_SGF_MARKUP_BACKGROUNDS - 1) - k; gtk_utils_set_gdk_color (&color, board_appearance->markup_colors[color_index]); color_button = gtk_color_button_new_with_color (&color); gtk_color_button_set_title (GTK_COLOR_BUTTON (color_button), _("Pick Color for Markup")); g_signal_connect (color_button, "color-set", G_CALLBACK (update_board_appearance), &board_appearance->markup_colors[color_index]); label = gtk_utils_create_mnemonic_label (_(labels[1 + k]), color_button); hbox = gtk_utils_pack_in_box (GTK_TYPE_HBOX, QUARRY_SPACING, label, 0, color_button, GTK_UTILS_PACK_DEFAULT, NULL); gtk_box_pack_start_defaults (GTK_BOX (color_named_vbox), hbox); gtk_size_group_add_widget (size_group, label); } return gtk_utils_pack_in_box (GTK_TYPE_VBOX, QUARRY_SPACING_BIG, (gtk_utils_pack_in_box (GTK_TYPE_NAMED_VBOX, 0, theme_hbox, GTK_UTILS_FILL, NULL)), GTK_UTILS_FILL, size_and_opacity_named_vbox, GTK_UTILS_FILL, color_named_vbox, GTK_UTILS_FILL, NULL); } static GtkWidget * create_board_appearance_notebook_page (GtkWidget *background_widget, GtkWidget *markup_widget) { GtkWidget *notebook_widget = gtk_notebook_new (); GtkNotebook *notebook = GTK_NOTEBOOK (notebook_widget); gtk_container_set_border_width (GTK_CONTAINER (background_widget), QUARRY_SPACING); gtk_container_set_border_width (GTK_CONTAINER (markup_widget), QUARRY_SPACING); gtk_notebook_append_page (notebook, background_widget, gtk_label_new (_("Background"))); gtk_notebook_append_page (notebook, markup_widget, gtk_label_new (_("Markup"))); return notebook_widget; } static void gtk_preferences_dialog_change_page (GtkTreeSelection *selection, GtkNotebook *notebook) { GtkTreeIter iterator; GtkTreeModel *categories_tree_model; if (gtk_tree_selection_get_selected (selection, &categories_tree_model, &iterator)) { gint page_index; gtk_tree_model_get (categories_tree_model, &iterator, CATEGORIES_PAGE_INDEX, &page_index, -1); if (page_index != -1) { last_selected_page = page_index; gtk_notebook_set_current_page (notebook, last_selected_page); } } } static void gtk_preferences_dialog_response (GtkWindow *window, gint response_id) { g_return_if_fail (window == preferences_dialog); if (response_id == GTK_RESPONSE_HELP) { switch (last_selected_page) { case PREFERENCES_PAGE_GTK_UI: gtk_help_display ("preferences-gtk-ui"); break; case PREFERENCES_PAGE_GAME_TREE: gtk_help_display ("preferences-game-tree"); break; case PREFERENCES_PAGE_GTP_ENGINES: gtk_help_display ("preferences-gtp-engines"); break; case PREFERENCES_PAGE_SGF_SAVING: gtk_help_display ("preferences-saving-game-records"); break; case PREFERENCES_PAGE_GO_BOARD_APPEARANCE: gtk_help_display ("preferences-go-board-appearance"); break; case PREFERENCES_PAGE_AMAZONS_BOARD_APPEARANCE: gtk_help_display ("preferences-amazons-board-appearance"); break; case PREFERENCES_PAGE_REVERSI_BOARD_APPEARANCE: gtk_help_display ("preferences-reversi-board-appearance"); break; } } else gtk_widget_destroy (GTK_WIDGET (preferences_dialog)); } static void change_toolbar_style (GtkWidget *selector, GtkToolbarList *toolbar_list) { GSList *item; *toolbar_list->toolbar_style = gtk_utils_get_selector_active_item_index (selector); #if !GTK_2_4_OR_LATER /* See create_toolbar_style_box() for explanation. */ if (*toolbar_list->toolbar_style >= TOOLBAR_STYLE_BOTH_HORIZONTALLY) (*toolbar_list->toolbar_style)++; #endif for (item = toolbar_list->toolbars; item; item = item->next) set_toolbar_style (GTK_TOOLBAR (item->data), *toolbar_list->toolbar_style); } static void gtk_preferences_dialog_update_gtp_engine_info (GtkTreeSelection *selection) { GtkTreeModel *gtp_engines_tree_model; GtkTreeIter iterator; GtpEngineListItem *engine_data = NULL; char *supported_games = NULL; gint num_supported_games = 0; if (gtk_tree_selection_get_selected (selection, >p_engines_tree_model, &iterator)) { StringListItem *item; gtk_tree_model_get (gtp_engines_tree_model, &iterator, ENGINES_DATA, &engine_data, -1); for (item = engine_data->supported_games.first; item; item = item->next, num_supported_games++) { Game game = game_from_game_name (item->text, 1); if (supported_games) supported_games = utils_cat_string (supported_games, ", "); if (game != GAME_INVALID) { if (supported_games) { supported_games = utils_cat_string (supported_games, _(game_info[game].name)); } else { supported_games = utils_duplicate_string (gtk_games_get_capitalized_name (game)); } } else supported_games = utils_cat_string (supported_games, item->text); } } gtk_widget_set_sensitive (modify_gtp_engine, engine_data != NULL); gtk_widget_set_sensitive (remove_gtp_engine, (engine_data != NULL && engine_data->site_configuration_name == NULL)); gtk_widget_set_sensitive (move_gtp_engine_up, (engine_data != NULL && engine_data != gtp_engines.first)); gtk_widget_set_sensitive (move_gtp_engine_down, (engine_data != NULL && engine_data != gtp_engines.last)); gtk_widget_set_sensitive (gtp_engine_info, engine_data != NULL); gtk_label_set_text (gtp_engine_name, (engine_data ? engine_data->name : NULL)); gtk_label_set_text (gtp_engine_version, (engine_data ? engine_data->version : NULL)); gtk_label_set_text (gtp_engine_supported_games_label, (num_supported_games <= 1 ? _("Supported game:") : _("Supported games:"))); gtk_label_set_text (gtp_engine_supported_games, supported_games); gtk_label_set_text (gtp_engine_command_line, (engine_data ? engine_data->command_line : NULL)); gtk_label_set_text (gtp_engine_additional_info, (engine_data && engine_data->site_configuration_name ? _("This engine comes from site configuration.") : NULL)); utils_free (supported_games); } static void show_or_hide_gtp_engine (GtkCellRendererToggle *cell_renderer, gchar *path_string, gpointer user_data) { GtkTreeModel *gtp_engines_tree_model = GTK_TREE_MODEL (gtp_engines_list_store); GtkTreePath *tree_path = gtk_tree_path_new_from_string (path_string); GtkTreeIter iterator; GtpEngineListItem *engine_data; #if !GTK_2_4_OR_LATER gboolean had_non_hidden_engine = gtk_preferences_have_non_hidden_gtp_engine (); #endif UNUSED (cell_renderer); UNUSED (user_data); gtk_tree_model_get_iter (gtp_engines_tree_model, &iterator, tree_path); gtk_tree_path_free (tree_path); gtk_tree_model_get (gtp_engines_tree_model, &iterator, ENGINES_DATA, &engine_data, -1); prepare_to_rebuild_menus (); engine_data->is_hidden = !engine_data->is_hidden; rebuild_all_menus (); gtk_list_store_set (gtp_engines_list_store, &iterator, ENGINES_IS_VISIBLE, !engine_data->is_hidden, -1); #if !GTK_2_4_OR_LATER if (gtk_preferences_have_non_hidden_gtp_engine () != had_non_hidden_engine) { GSList *item; for (item = gtp_engine_selectors; item; item = item->next) { GtkEngineSelectorData *data = (GtkEngineSelectorData *) (item->data); data->callback (data->selector, data->user_data); } } #endif } static void do_remove_gtp_engine (void) { GtkTreeModel *gtp_engines_tree_model; GtkTreeIter iterator; GtpEngineListItem *engine_data; #if !GTK_2_4_OR_LATER gboolean deleting_last_item; #endif GSList *item; GtkTreePath *tree_path; if (!gtk_tree_selection_get_selected (gtp_engines_tree_selection, >p_engines_tree_model, &iterator)) { g_warning ("attempt to remove an engine while none is selected"); return; } gtk_tree_model_get (gtp_engines_tree_model, &iterator, ENGINES_DATA, &engine_data, -1); item = find_gtp_engine_dialog_by_engine_data (engine_data); #if !GTK_2_4_OR_LATER deleting_last_item = (engine_data->next == NULL); #endif if (item) { GtkEngineDialogData *data = (GtkEngineDialogData *) (item->data); if (data->progress_dialog) { data->engine_deleted = TRUE; gtk_schedule_gtp_client_deletion (data->client); } gtk_widget_destroy (GTK_WIDGET (data->window)); } prepare_to_rebuild_menus (); string_list_delete_item (>p_engines, engine_data); rebuild_all_menus (); #if !GTK_2_4_OR_LATER if (!gtk_preferences_have_non_hidden_gtp_engine ()) { for (item = gtp_engine_selectors; item; item = item->next) { GtkEngineSelectorData *data = (GtkEngineSelectorData *) (item->data); data->callback (data->selector, data->user_data); } } #endif tree_path = gtk_tree_model_get_path (gtp_engines_tree_model, &iterator); #if GTK_2_4_OR_LATER if (!gtk_list_store_remove (gtp_engines_list_store, &iterator)) gtk_tree_path_prev (tree_path); #else gtk_list_store_remove (gtp_engines_list_store, &iterator); if (deleting_last_item) gtk_tree_path_prev (tree_path); #endif gtk_tree_view_set_cursor (gtp_engines_tree_view, tree_path, NULL, FALSE); gtk_tree_path_free (tree_path); } static void do_move_gtp_engine (gpointer move_upwards) { GtkTreeModel *gtp_engines_tree_model; GtkTreeIter first_iterator; GtkTreeIter second_iterator; GtpEngineListItem *first_engine_data; GtpEngineListItem *second_engine_data; GtkTreePath *tree_path; if (!gtk_tree_selection_get_selected (gtp_engines_tree_selection, >p_engines_tree_model, &first_iterator)) { g_warning ("attempt to move an engine while none is selected"); return; } gtk_tree_model_get (gtp_engines_tree_model, &first_iterator, ENGINES_DATA, &first_engine_data, -1); tree_path = gtk_tree_model_get_path (gtp_engines_tree_model, &first_iterator); prepare_to_rebuild_menus (); if (GPOINTER_TO_INT (move_upwards)) { string_list_swap_with_previous (>p_engines, first_engine_data); second_engine_data = first_engine_data->next; gtk_tree_path_prev (tree_path); } else { second_engine_data = first_engine_data->next; string_list_swap_with_next (>p_engines, first_engine_data); gtk_tree_path_next (tree_path); } rebuild_all_menus (); gtk_tree_model_get_iter (gtp_engines_tree_model, &second_iterator, tree_path); #if GTK_2_2_OR_LATER gtk_tree_path_free (tree_path); gtk_list_store_swap (gtp_engines_list_store, &first_iterator, &second_iterator); gtk_preferences_dialog_update_gtp_engine_info (gtp_engines_tree_selection); #else /* not GTK_2_2_OR_LATER */ gtk_utils_block_signal_handlers (gtp_engines_list_store, handle_drag_and_drop); gtk_list_store_set (gtp_engines_list_store, &first_iterator, ENGINES_DATA, second_engine_data, ENGINES_IS_VISIBLE, !second_engine_data->is_hidden, ENGINES_NAME, second_engine_data->screen_name, -1); gtk_list_store_set (gtp_engines_list_store, &second_iterator, ENGINES_DATA, first_engine_data, ENGINES_IS_VISIBLE, !first_engine_data->is_hidden, ENGINES_NAME, first_engine_data->screen_name, -1); gtk_utils_unblock_signal_handlers (gtp_engines_list_store, handle_drag_and_drop); gtk_tree_view_set_cursor (gtp_engines_tree_view, tree_path, NULL, FALSE); gtk_tree_path_free (tree_path); #endif /* not GTK_2_2_OR_LATER */ } static GSList * find_gtp_engine_dialog_by_engine_data (GtpEngineListItem *engine_data) { GSList *item; for (item = gtp_engine_dialogs; item; item = item->next) { if (((GtkEngineDialogData *) (item->data))->engine_data == engine_data) break; } return item; } static void gtk_gtp_engine_dialog_present (gpointer new_engine) { static const gchar *hint_text = N_("You can use `%n' and `%v' strings in Screen name field. " "They will substituted with name and version of the engine " "correspondingly. By default, `%n %v' is used."); GtpEngineListItem *engine_data = NULL; GtkEngineDialogData *data; GtkTreeModel *gtp_engines_tree_model = GTK_TREE_MODEL (gtp_engines_list_store); GtkTreeIter iterator; GSList *item; GtkWidget *dialog; GtkWidget *button; GtkWidget *table_widget; GtkTable *table; GtkWidget *entry; GtkWidget *label; if (!GPOINTER_TO_INT (new_engine)) { if (!gtk_tree_selection_get_selected (gtp_engines_tree_selection, NULL, &iterator)) { g_warning ("attempt to edit an engine while none is selected"); return; } gtk_tree_model_get (gtp_engines_tree_model, &iterator, ENGINES_DATA, &engine_data, -1); } item = find_gtp_engine_dialog_by_engine_data (engine_data); if (item) { data = (GtkEngineDialogData *) (item->data); gtk_window_present (data->window); if (data->progress_dialog) gtk_window_present (GTK_WINDOW (data->progress_dialog)); return; } data = g_malloc (sizeof (GtkEngineDialogData)); data->engine_data = engine_data; data->engine_deleted = FALSE; data->progress_dialog = NULL; gtp_engine_dialogs = g_slist_prepend (gtp_engine_dialogs, data); dialog = gtk_dialog_new_with_buttons ((engine_data ? _("Modify GTP Engine Information") : _("New GTP Engine")), NULL, 0, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, NULL); data->window = GTK_WINDOW (dialog); gtk_control_center_window_created (data->window); gtk_utils_make_window_only_horizontally_resizable (data->window); button = gtk_dialog_add_button (GTK_DIALOG (dialog), (engine_data ? GTK_STOCK_OK : GTK_STOCK_ADD), GTK_RESPONSE_OK); gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK); g_signal_connect (dialog, "destroy", G_CALLBACK (gtk_gtp_engine_dialog_destroy), data); g_signal_connect (dialog, "response", G_CALLBACK (gtk_gtp_engine_dialog_response), data); table_widget = gtk_table_new (3, 3, FALSE); table = GTK_TABLE (table_widget); gtk_table_set_row_spacing (table, 0, QUARRY_SPACING); gtk_table_set_row_spacing (table, 1, QUARRY_SPACING_SMALL); gtk_table_set_col_spacing (table, 0, QUARRY_SPACING); gtk_table_set_col_spacing (table, 1, QUARRY_SPACING_SMALL); #if GTK_2_4_OR_LATER entry = gtk_combo_box_entry_new_with_model (gtp_engines_tree_model, ENGINES_COMMAND_LINE); if (engine_data) gtk_combo_box_set_active_iter (GTK_COMBO_BOX (entry), &iterator); data->command_line_entry = GTK_ENTRY (GTK_BIN (entry)->child); gtk_entry_set_activates_default (data->command_line_entry, TRUE); #else entry = gtk_utils_create_entry ((engine_data ? engine_data->command_line : NULL), RETURN_ACTIVATES_DEFAULT); data->command_line_entry = GTK_ENTRY (entry); #endif gtk_utils_set_sensitive_on_input (data->command_line_entry, button); gtk_table_attach (table, entry, 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, 0, 0, 0); label = gtk_utils_create_mnemonic_label (_("Command _line:"), entry); gtk_table_attach (table, label, 0, 1, 0, 1, GTK_FILL, 0, 0, 0); button = gtk_utils_create_browse_button (TRUE, GTK_WIDGET (data->command_line_entry), TRUE, _("Choose GTP Engine..."), NULL, NULL); gtk_table_attach (table, button, 2, 3, 0, 1, GTK_FILL, 0, 0, 0); entry = gtk_utils_create_entry ((engine_data && engine_data->screen_name_format ? engine_data->screen_name_format : "%n %v"), RETURN_ACTIVATES_DEFAULT); data->name_entry = GTK_ENTRY (entry); gtk_table_attach (table, entry, 1, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 0, 0); label = gtk_utils_create_mnemonic_label (_("Screen _name:"), entry); gtk_table_attach (table, label, 0, 1, 1, 2, GTK_FILL, 0, 0, 0); label = gtk_utils_create_left_aligned_label (NULL); gtk_label_set_line_wrap (GTK_LABEL (label), TRUE); gtk_label_set_markup (GTK_LABEL (label), _(hint_text)); gtk_table_attach (table, label, 0, 2, 2, 3, GTK_EXPAND | GTK_FILL, 0, 0, 0); gtk_utils_standardize_dialog (GTK_DIALOG (dialog), table_widget); gtk_widget_show_all (dialog); } static void gtk_gtp_engine_dialog_destroy (GtkWindow *window, GtkEngineDialogData *data) { if (gtk_control_center_window_destroyed (window)) { GSList *item = find_gtp_engine_dialog_by_engine_data (data->engine_data); g_return_if_fail (item); gtp_engine_dialogs = g_slist_delete_link (gtp_engine_dialogs, item); g_free (data); } } static void gtk_gtp_engine_dialog_response (GtkWindow *window, gint response_id, GtkEngineDialogData *data) { if (response_id == GTK_RESPONSE_OK) { const gchar *command_line = gtk_entry_get_text (data->command_line_entry); if (!data->engine_data || !data->engine_data->command_line || strcmp (data->engine_data->command_line, command_line) != 0) { GError *error = NULL; data->client = gtk_create_gtp_client (command_line, client_initialized, client_deleted, data, &error); if (data->client) { data->progress_dialog = gtk_progress_dialog_new (window, "Quarry", _("Querying engine's " "name, version and known commands..."), show_progress_dialog, ((GtkProgressDialogCallback) cancel_engine_query), data); /* FIXME: I'd like this to display * `preferences-gtp-engine-information-dialog-freeze'. * Do newer versions of `yelp' still have this bug? */ gtk_progress_dialog_set_help_link_id (GTK_PROGRESS_DIALOG (data->progress_dialog), "preferences-gtp-engine-information-dialog"); g_object_ref (data->progress_dialog); gtp_client_setup_connection (data->client); } else { GtkWidget *error_dialog = quarry_message_dialog_new (window, GTK_BUTTONS_OK, GTK_STOCK_DIALOG_ERROR, _("Please make sure you typed " "engine's filename correctly and " "that you have permission to " "execute it."), error->message); g_error_free (error); gtk_utils_show_and_forget_dialog (GTK_DIALOG (error_dialog)); gtk_widget_grab_focus (GTK_WIDGET (data->command_line_entry)); } } else { const gchar *name = gtk_entry_get_text (data->name_entry); if (! *name) name = "%n %v"; configuration_set_string_value (&data->engine_data->screen_name_format, name); update_engine_screen_name (data->engine_data, TRUE); gtk_widget_destroy (GTK_WIDGET (window)); } } else if (response_id == GTK_RESPONSE_CANCEL) gtk_widget_destroy (GTK_WIDGET (window)); } static void client_initialized (GtpClient *client, void *user_data) { GtkWidget *progress_dialog = ((GtkEngineDialogData *) user_data)->progress_dialog; gtp_client_quit (client); gtk_label_set_text (GTK_PROGRESS_DIALOG (progress_dialog)->label, _("Waiting for the engine to quit...")); } static void client_deleted (GtpClient *client, GError *shutdown_reason, void *user_data) { GtkEngineDialogData *data = (GtkEngineDialogData *) user_data; GtkWidget *progress_dialog = data->progress_dialog; if (!data->engine_deleted) { if (client->operation_stage == GTP_CLIENT_QUIT) { static const ConfigurationSection *gtp_engines_section = >k_configuration_sections[SECTION_GTP_ENGINES]; GtpEngineListItem *engine_data = data->engine_data; const gchar *command_line; const gchar *name; char *screen_name; GtkTreeIter iterator; GtkTreePath *tree_path; GSList *item; command_line = gtk_entry_get_text (data->command_line_entry); name = gtk_entry_get_text (data->name_entry); if (! *name) name = "%n %v"; screen_name = utils_special_printf (name, 'n', client->engine_name, 'v', client->engine_version, 0); if (engine_data) { utils_free (engine_data->screen_name); engine_data->screen_name = screen_name; } else { string_list_add_ready (>p_engines, screen_name); configuration_init_repeatable_section (gtp_engines_section, gtp_engines.last); engine_data = gtp_engines.last; } configuration_set_string_value (&engine_data->screen_name_format, name); configuration_set_string_value (&engine_data->name, client->engine_name); configuration_set_string_value (&engine_data->version, client->engine_version); configuration_set_string_list_value_steal_strings (&engine_data->supported_games, &client->supported_games); configuration_set_string_value (&engine_data->command_line, command_line); if (data->engine_data) find_gtp_tree_model_iterator_by_engines_data (engine_data, &iterator); else { gtk_utils_block_signal_handlers (gtp_engines_list_store, handle_drag_and_drop); gtk_list_store_append (gtp_engines_list_store, &iterator); } gtk_list_store_set (gtp_engines_list_store, &iterator, ENGINES_DATA, engine_data, ENGINES_IS_VISIBLE, !engine_data->is_hidden, ENGINES_NAME, screen_name, #if GTK_2_4_OR_LATER ENGINES_COMMAND_LINE, engine_data->command_line, #endif -1); prepare_to_rebuild_menus (); rebuild_all_menus (); if (!data->engine_data) { gtk_utils_unblock_signal_handlers (gtp_engines_list_store, handle_drag_and_drop); if (string_list_is_single_string (>p_engines)) { for (item = gtp_engine_selectors; item; item = item->next) { GtkEngineSelectorData *data = ((GtkEngineSelectorData *) (item->data)); data->callback (data->selector, data->user_data); #if GTK_2_4_OR_LATER gtk_combo_box_set_active (GTK_COMBO_BOX (data->selector), 0); #endif } } } tree_path = gtk_tree_model_get_path (GTK_TREE_MODEL (gtp_engines_list_store), &iterator); gtk_tree_view_set_cursor (gtp_engines_tree_view, tree_path, NULL, FALSE); gtk_tree_path_free (tree_path); gtk_preferences_dialog_update_gtp_engine_info (gtp_engines_tree_selection); gtk_widget_destroy (GTK_WIDGET (data->window)); } else { static const gchar *hint = N_("The engine might have crashed, quit prematurely or " "disconnected. Please verify command line, including options, " "and consult engine's documentation if needed."); gtk_progress_dialog_recover_parent (GTK_PROGRESS_DIALOG (progress_dialog)); data->progress_dialog = NULL; gtk_widget_grab_focus (GTK_WIDGET (data->command_line_entry)); if (shutdown_reason) { GtkWidget *error_dialog = quarry_message_dialog_new (data->window, GTK_BUTTONS_OK, GTK_STOCK_DIALOG_ERROR, _(hint), _("Lost connection to GTP Engine (%s)"), shutdown_reason->message); gtk_utils_show_and_forget_dialog (GTK_DIALOG (error_dialog)); } } } gtk_widget_destroy (progress_dialog); g_object_unref (progress_dialog); } static gboolean show_progress_dialog (GtkProgressDialog *progress_dialog, gpointer user_data) { UNUSED (user_data); gtk_widget_show (GTK_WIDGET (progress_dialog)); return FALSE; } static gboolean cancel_engine_query (GtkProgressDialog *progress_dialog, GtkEngineDialogData *data) { UNUSED (progress_dialog); gtk_schedule_gtp_client_deletion (data->client); return TRUE; } static void store_toggle_setting (GtkToggleButton *toggle_button, int *value_storage) { *value_storage = gtk_toggle_button_get_active (toggle_button); } static void store_radio_button_setting (GtkRadioButton *radio_button, int *value_storage) { if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (radio_button))) { GSList *radio_button_group = gtk_radio_button_get_group (radio_button); *value_storage = ((g_slist_length (radio_button_group) - 1) - g_slist_index (radio_button_group, radio_button)); } } static void update_game_tree_tooltips_status (GtkToggleButton *toggle_button) { gtk_sgf_tree_view_set_tooltips_enabled (gtk_toggle_button_get_active (toggle_button)); } static gboolean update_board_background_texture (GtkEntry *entry, GdkEventFocus *event, gpointer game_index) { BoardAppearance *board_appearance = game_index_to_board_appearance_structure (GPOINTER_TO_INT (game_index)); const gchar *new_texture = gtk_entry_get_text (entry); UNUSED (event); if (!board_appearance->background_texture || strcmp (new_texture, board_appearance->background_texture) != 0) { configuration_set_string_value (&board_appearance->background_texture, new_texture); gtk_goban_base_update_appearance (index_to_game[GPOINTER_TO_INT (game_index)]); } return FALSE; } #ifdef GTK_TYPE_FILE_SELECTOR static void board_background_texture_changed (GtkFileSelector *file_selector, gpointer game_index) { /* This signal is also emitted when the entry is changed, in which * case there is no active item. Updating background texture after * a symbol is typed is wrong. */ if (gtk_combo_box_get_active (GTK_COMBO_BOX (file_selector)) != -1) { GtkEntry *entry = GTK_ENTRY (GTK_BIN (file_selector)->child); update_board_background_texture (entry, NULL, game_index); } } #endif /* defined GTK_TYPE_FILE_SELECTOR */ static void update_board_appearance (GtkWidget *widget, gpointer value_storage) { Game game; if ((gpointer) &go_board_appearance <= value_storage && value_storage < (gpointer) (&go_board_appearance + 1)) game = GAME_GO; else if ((gpointer) &amazons_board_appearance <= value_storage && value_storage < ((gpointer) (&amazons_board_appearance + 1))) game = GAME_AMAZONS; else if ((gpointer) &reversi_board_appearance <= value_storage && value_storage < (gpointer) (&reversi_board_appearance + 1)) game = GAME_REVERSI; else { g_critical ("unhandled game type"); return; } if (GTK_IS_RANGE (widget)) * (double *) value_storage = gtk_range_get_value (GTK_RANGE (widget)); else if (GTK_IS_TOGGLE_BUTTON (widget)) { * (int *) value_storage = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)); } else if (GTK_IS_COLOR_BUTTON (widget)) { GdkColor gdk_color; QuarryColor quarry_color; gtk_color_button_get_color (GTK_COLOR_BUTTON (widget), &gdk_color); gtk_utils_set_quarry_color (&quarry_color, &gdk_color); if (QUARRY_COLORS_ARE_EQUAL (quarry_color, * (QuarryColor *) value_storage)) return; * (QuarryColor *) value_storage = quarry_color; } else { g_critical ("unhandled widget type %s", G_OBJECT_TYPE_NAME (widget)); return; } gtk_goban_base_update_appearance (game); } static void update_board_markup_theme (GtkWidget *widget, UseThemeDefaultsData *data) { BoardAppearance *board_appearance = game_to_board_appearance_structure (data->game); gint selected_theme_index = gtk_utils_get_selector_active_item_index (widget); MarkupThemeListItem *selected_theme = markup_theme_list_get_item (&markup_themes, selected_theme_index); if (strcmp (board_appearance->markup_theme, selected_theme->name) != 0) { configuration_set_string_value (&board_appearance->markup_theme, selected_theme->name); /* Call it, because it blocks signal handlers. */ update_markup_theme_defaults_usage (NULL, data); } } static void update_markup_theme_defaults_usage (GtkToggleButton *toggle_button, UseThemeDefaultsData *data) { BoardAppearance *board_appearance = game_to_board_appearance_structure (data->game); gboolean use_theme_defaults; gdouble markup_size; gboolean markup_size_is_relative; gdouble markup_opacity; if (toggle_button) { use_theme_defaults = gtk_toggle_button_get_active (toggle_button); board_appearance->use_theme_defaults = use_theme_defaults; gtk_widget_set_sensitive (data->vbox, !use_theme_defaults); } else use_theme_defaults = board_appearance->use_theme_defaults; if (toggle_button || use_theme_defaults) { gtk_utils_block_signal_handlers (data->size_range, update_board_appearance); gtk_utils_block_signal_handlers (data->size_is_relative_toggle_button, update_board_appearance); gtk_utils_block_signal_handlers (data->opacity_range, update_board_appearance); if (use_theme_defaults) { MarkupThemeListItem *current_theme = markup_theme_list_find (&markup_themes, board_appearance->markup_theme); markup_size = current_theme->default_size; markup_size_is_relative = current_theme->size_is_relative; markup_opacity = current_theme->default_opacity; } else { markup_size = board_appearance->markup_size; markup_size_is_relative = board_appearance->markup_size_is_relative; markup_opacity = board_appearance->markup_opacity; } gtk_range_set_value (data->size_range, markup_size); gtk_toggle_button_set_active (data->size_is_relative_toggle_button, markup_size_is_relative); gtk_range_set_value (data->opacity_range, markup_opacity); gtk_utils_unblock_signal_handlers (data->size_range, update_board_appearance); gtk_utils_unblock_signal_handlers (data->size_is_relative_toggle_button, update_board_appearance); gtk_utils_unblock_signal_handlers (data->opacity_range, update_board_appearance); } gtk_goban_base_update_appearance (data->game); } BoardAppearance * game_to_board_appearance_structure (Game game) { if (game == GAME_GO) return &go_board_appearance; if (game == GAME_AMAZONS) return &amazons_board_appearance.board_appearance; if (game == GAME_REVERSI) return &reversi_board_appearance; g_critical ("unhandled game %s", game_info[game].name); return NULL; } static inline BoardAppearance * game_index_to_board_appearance_structure (GtkGameIndex game_index) { if (game_index == GTK_GAME_GO) return &go_board_appearance; if (game_index == GTK_GAME_AMAZONS) return &amazons_board_appearance.board_appearance; if (game_index == GTK_GAME_REVERSI) return &reversi_board_appearance; g_critical ("unhandled game %s", INDEX_TO_GAME_NAME (game_index)); return NULL; } void gtk_preferences_register_main_toolbar (GtkToolbar *toolbar) { do_register_toolbar (toolbar, &main_toolbar_list); } void gtk_preferences_register_editing_toolbar (GtkToolbar *toolbar) { do_register_toolbar (toolbar, &editing_toolbar_list); } void gtk_preferences_register_navigation_toolbar (GtkToolbar *toolbar) { do_register_toolbar (toolbar, &navigation_toolbar_list); } static void do_register_toolbar (GtkToolbar *toolbar, GtkToolbarList *toolbar_list) { g_return_if_fail (GTK_IS_TOOLBAR (toolbar)); toolbar_list->toolbars = g_slist_prepend (toolbar_list->toolbars, toolbar); g_signal_connect (toolbar, "destroy", G_CALLBACK (unregister_toolbar), toolbar_list); set_toolbar_style (toolbar, *toolbar_list->toolbar_style); } static void unregister_toolbar (GtkToolbar *toolbar, GtkToolbarList *toolbar_list) { toolbar_list->toolbars = g_slist_remove (toolbar_list->toolbars, toolbar); } static void set_toolbar_style (GtkToolbar *toolbar, int style) { switch (style) { case TOOLBAR_STYLE_DEFAULT: gtk_toolbar_unset_style (toolbar); break; case TOOLBAR_STYLE_BOTH_HORIZONTALLY: /* Safety check. Shouldn't happen unless someone edits his * configuration file by hands. */ #if GTK_2_4_OR_LATER gtk_toolbar_set_style (toolbar, GTK_TOOLBAR_BOTH_HORIZ); break; #endif case TOOLBAR_STYLE_BOTH: gtk_toolbar_set_style (toolbar, GTK_TOOLBAR_BOTH); break; case TOOLBAR_STYLE_ICONS_ONLY: gtk_toolbar_set_style (toolbar, GTK_TOOLBAR_ICONS); break; case TOOLBAR_STYLE_TEXT_ONLY: gtk_toolbar_set_style (toolbar, GTK_TOOLBAR_TEXT); break; default: g_warning ("unknown toolbar style %d", style); } } gboolean gtk_preferences_have_non_hidden_gtp_engine (void) { GtpEngineListItem *engine_data; for (engine_data = gtp_engines.first; engine_data; engine_data = engine_data->next) { if (!engine_data->is_hidden) return TRUE; } return FALSE; } /* FIXME: Can be substantially improved. */ GtpEngineListItem * gtk_preferences_guess_engine_by_name (const gchar *name, GtkGameIndex game_index) { GtpEngineListItem *best_guess = NULL; if (name) { GtpEngineListItem *engine_data; for (engine_data = gtp_engines.first; engine_data; engine_data = engine_data->next) { if (!engine_data->is_hidden && (game_index == GTK_GAME_ANY || gtk_games_engine_supports_game (engine_data, game_index))) { if (strcmp (engine_data->screen_name, name) == 0) { /* Exact match. */ return engine_data; } if (strstr (name, engine_data->name)) { /* Engine base name is a substring of player name. */ best_guess = engine_data; } } } } return best_guess; } GtkWidget * gtk_preferences_create_engine_selector (GtkGameIndex game_index, gboolean only_this_game, const GtpEngineListItem *engine_data, GtkEngineChanged callback, gpointer user_data) { GtkEngineSelectorData *data = g_malloc (sizeof (GtkEngineSelectorData)); #if GTK_2_4_OR_LATER GtkWidget *widget; GtkCellRenderer *cell_renderer; if (only_this_game) { widget = (gtk_combo_box_new_with_model (only_one_game_gtp_engines_tree_model[game_index])); } else widget = gtk_combo_box_new_with_model (non_hidden_gtp_engines_tree_model); cell_renderer = gtk_cell_renderer_text_new (); gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (widget), cell_renderer, FALSE); gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (widget), cell_renderer, "text", ENGINES_NAME); if (!only_this_game) { data->pixbuf_cell = gtk_cell_renderer_pixbuf_new (); g_object_set (data->pixbuf_cell, "xpad", QUARRY_SPACING_SMALL, NULL); gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (widget), data->pixbuf_cell, FALSE); gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (widget), data->pixbuf_cell, set_pixbuf_cell_image, GINT_TO_POINTER (game_index), NULL); data->selector_game_index = GTK_GAME_UNSUPPORTED; } else data->selector_game_index = game_index; #else /* not GTK_2_4_OR_LATER */ GtkWidget *widget = gtk_option_menu_new (); build_and_attach_menu (widget, game_index, only_this_game); data->selector_game_index = game_index; data->only_this_game = only_this_game; #endif /* not GTK_2_4_OR_LATER */ data->callback = callback; data->selector = widget; data->user_data = user_data; gtp_engine_selectors = g_slist_prepend (gtp_engine_selectors, data); gtk_preferences_set_engine_selector_selection (widget, engine_data); g_signal_connect (widget, "changed", G_CALLBACK (engine_selector_changed), data); g_signal_connect_swapped (widget, "destroy", G_CALLBACK (engine_selector_destroyed), data); return widget; } void gtk_preferences_set_engine_selector_game_index (GtkWidget *selector, GtkGameIndex game_index) { GSList *item; g_return_if_fail (0 <= game_index && game_index < NUM_SUPPORTED_GAMES); for (item = gtp_engine_selectors; ; item = item->next) { GtkEngineSelectorData *data = (GtkEngineSelectorData *) (item->data); g_return_if_fail (item); if (data->selector == selector) { #if GTK_2_4_OR_LATER g_return_if_fail (data->selector_game_index == GTK_GAME_UNSUPPORTED); gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (selector), data->pixbuf_cell, set_pixbuf_cell_image, GINT_TO_POINTER (game_index), NULL); #else g_return_if_fail (!data->only_this_game); if (game_index != data->selector_game_index) { GtpEngineListItem *current_selection = gtk_preferences_get_engine_selector_selection (data->selector); gtk_utils_block_signal_handlers (data->selector, engine_selector_changed); build_and_attach_menu (data->selector, game_index, FALSE); gtk_preferences_set_engine_selector_selection (data->selector, current_selection); gtk_utils_unblock_signal_handlers (data->selector, engine_selector_changed); } data->selector_game_index = game_index; #endif break; } } } void gtk_preferences_set_engine_selector_selection (GtkWidget *selector, const GtpEngineListItem *engine_data) { gint engine_to_select; if (engine_data) { GSList *item; GtpEngineListItem *engine_scan; GtkEngineSelectorData *data; for (item = gtp_engine_selectors; ; item = item->next) { g_return_if_fail (item); data = (GtkEngineSelectorData *) (item->data); if (data->selector == selector) break; } for (engine_scan = gtp_engines.first, engine_to_select = 0; engine_scan && engine_scan != engine_data; engine_scan = engine_scan->next) { if (!engine_scan->is_hidden) { #if GTK_2_4_OR_LATER if (data->pixbuf_cell || gtk_games_engine_supports_game (engine_scan, data->selector_game_index)) engine_to_select++; #else if (!data->only_this_game || gtk_games_engine_supports_game (engine_scan, data->selector_game_index)) engine_to_select++; #endif } } if (!engine_scan) engine_to_select = 0; } else engine_to_select = 0; #if GTK_2_4_OR_LATER gtk_combo_box_set_active (GTK_COMBO_BOX (selector), engine_to_select); #else gtk_option_menu_set_history (GTK_OPTION_MENU (selector), engine_to_select); #endif } GtpEngineListItem * gtk_preferences_get_engine_selector_selection (GtkWidget *selector) { GSList *item; GtkEngineSelectorData *data; GtpEngineListItem *engine_data; gint selected_engine = gtk_utils_get_selector_active_item_index (selector); for (item = gtp_engine_selectors; ; item = item->next) { g_return_val_if_fail (item, NULL); data = (GtkEngineSelectorData *) (item->data); if (data->selector == selector) break; } for (engine_data = gtp_engines.first; engine_data; engine_data = engine_data->next) { if (!engine_data->is_hidden) { #if GTK_2_4_OR_LATER if (data->pixbuf_cell || gtk_games_engine_supports_game (engine_data, data->selector_game_index)) { if (selected_engine-- == 0) break; } #else if (!data->only_this_game || gtk_games_engine_supports_game (engine_data, data->selector_game_index)) { if (selected_engine-- == 0) break; } #endif } } return engine_data; } static void engine_selector_changed (GtkWidget *selector, GtkEngineSelectorData *data) { data->callback (selector, data->user_data); } static void engine_selector_destroyed (GtkEngineSelectorData *data) { gtp_engine_selectors = g_slist_remove (gtp_engine_selectors, data); g_free (data); } #if GTK_2_4_OR_LATER static void set_pixbuf_cell_image (GtkCellLayout *cell_layout, GtkCellRenderer *cell, GtkTreeModel *gtp_engines_tree_model, GtkTreeIter *iterator, gpointer data) { GtpEngineListItem *engine_data; const gchar *stock_id; UNUSED (cell_layout); gtk_tree_model_get (gtp_engines_tree_model, iterator, ENGINES_DATA, &engine_data, -1); stock_id = (gtk_games_engine_supports_game (engine_data, GPOINTER_TO_INT (data)) ? GTK_STOCK_YES : GTK_STOCK_NO); g_object_set (cell, "stock-id", stock_id, NULL); } static gboolean engine_is_visible_and_supports_game (GtkTreeModel *tree_model, GtkTreeIter *iterator, gpointer game_index) { GtpEngineListItem *engine_data; gtk_tree_model_get (tree_model, iterator, ENGINES_DATA, &engine_data, -1); /* This function is also called immediately after * gtk_list_store_append(), when data is not yet set. */ if (!engine_data) return FALSE; return (!engine_data->is_hidden && gtk_games_engine_supports_game (engine_data, GPOINTER_TO_INT (game_index))); } #else /* not GTK_2_4_OR_LATER */ static void prepare_to_rebuild_menus (void) { GSList *item; for (item = gtp_engine_selectors; item; item = item->next) { GtkEngineSelectorData *data = (GtkEngineSelectorData *) (item->data); data->last_selection = gtk_preferences_get_engine_selector_selection (data->selector); } } static void rebuild_all_menus (void) { GSList *item; for (item = gtp_engine_selectors; item; item = item->next) { GtkEngineSelectorData *data = (GtkEngineSelectorData *) (item->data); gtk_utils_block_signal_handlers (data->selector, engine_selector_changed); build_and_attach_menu (data->selector, data->selector_game_index, data->only_this_game); gtk_preferences_set_engine_selector_selection (data->selector, data->last_selection); gtk_utils_unblock_signal_handlers (data->selector, engine_selector_changed); } } static void build_and_attach_menu (GtkWidget *option_menu, GtkGameIndex game_index, gboolean only_this_game) { GtkWidget *menu = gtk_menu_new (); GtpEngineListItem *engine_data; for (engine_data = gtp_engines.first; engine_data; engine_data = engine_data->next) { gboolean engine_supports_game = gtk_games_engine_supports_game (engine_data, game_index); if (!engine_data->is_hidden) { if (!only_this_game) { GtkWidget *menu_item = gtk_menu_item_new (); GtkWidget *icon; GtkWidget *hbox; icon = gtk_image_new_from_stock ((engine_supports_game ? GTK_STOCK_YES : GTK_STOCK_NO), GTK_ICON_SIZE_MENU); hbox = gtk_utils_pack_in_box (GTK_TYPE_HBOX, QUARRY_SPACING_SMALL, gtk_label_new (engine_data->screen_name), GTK_UTILS_FILL, icon, GTK_UTILS_FILL, NULL); gtk_container_add (GTK_CONTAINER (menu_item), hbox); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item); } else if (gtk_games_engine_supports_game (engine_data, game_index)) { gtk_menu_shell_append (GTK_MENU_SHELL (menu), gtk_menu_item_new_with_label (engine_data->screen_name)); } } } gtk_widget_show_all (menu); gtk_option_menu_set_menu (GTK_OPTION_MENU (option_menu), menu); } #endif /* not GTK_2_4_OR_LATER */ /* FIXME: the functions below need to be written properly. */ GtkEngineChain * gtk_preferences_create_engines_instantiation_chain (GtkWindow *parent_window, GtkEnginesInstantiated callback, gpointer user_data) { GtkEngineChain *engine_chain = g_malloc (sizeof (GtkEngineChain)); engine_chain->parent_window = parent_window; engine_chain->instantiation_callback = callback; engine_chain->user_data = user_data; engine_chain->chain_engine_datum = NULL; engine_chain->have_error = FALSE; return engine_chain; } void gtk_preferences_instantiate_selected_engine (GtkEngineChain *engine_chain, GtkWidget *selector, GtpClient **gtp_client) { g_return_if_fail (engine_chain); g_return_if_fail (selector); g_return_if_fail (gtp_client); if (!engine_chain->have_error) { GtpEngineListItem *engine_data = gtk_preferences_get_engine_selector_selection (selector); GError *error = NULL; GtkChainEngineData *chain_engine_data = g_malloc (sizeof (GtkChainEngineData)); g_assert (engine_data); chain_engine_data->engine_data = engine_data; chain_engine_data->engine_chain = engine_chain; *gtp_client = gtk_create_gtp_client (engine_data->command_line, ((GtpClientInitializedCallback) chain_client_initialized), NULL, chain_engine_data, &error); if (*gtp_client) { gtp_client_setup_connection (*gtp_client); engine_chain->chain_engine_datum = g_slist_prepend (engine_chain->chain_engine_datum, chain_engine_data); } else { GtkWidget *error_dialog = quarry_message_dialog_new (engine_chain->parent_window, GTK_BUTTONS_OK, GTK_STOCK_DIALOG_ERROR, _("Perhaps engine's binary has been " "deleted or changed. You will probably " "need to alter engine's command line " "in the Preferences dialog."), error->message); g_free (chain_engine_data); g_error_free (error); gtk_utils_show_and_forget_dialog (GTK_DIALOG (error_dialog)); engine_chain->have_error = TRUE; } } else *gtp_client = NULL; } void gtk_preferences_do_instantiate_engines (GtkEngineChain *engine_chain) { GtkEnginesInstantiationStatus status; if (!engine_chain->have_error) { if (engine_chain->chain_engine_datum != NULL) { /* FIXME: What should be here? */ return; } else status = ENGINES_INSTANTIATED; } else status = INSTANTIATION_FAILED; if (engine_chain->instantiation_callback) engine_chain->instantiation_callback (status, engine_chain->user_data); g_free (engine_chain); } static void chain_client_initialized (GtpClient *client, void *user_data) { GtkChainEngineData *chain_engine_data = (GtkChainEngineData *) user_data; GtkEngineChain *engine_chain = chain_engine_data->engine_chain; GtpEngineListItem *engine_data = chain_engine_data->engine_data; configuration_set_string_value (&engine_data->name, client->engine_name); configuration_set_string_value (&engine_data->version, client->engine_version); update_engine_screen_name (engine_data, TRUE); configuration_set_string_list_value (&engine_data->supported_games, &client->supported_games); engine_chain->chain_engine_datum = g_slist_remove (engine_chain->chain_engine_datum, chain_engine_data); g_free (chain_engine_data); if (engine_chain->chain_engine_datum == NULL) { if (engine_chain->instantiation_callback) { engine_chain->instantiation_callback (ENGINES_INSTANTIATED, engine_chain->user_data); } g_free (engine_chain); } } static void update_engine_screen_name (GtpEngineListItem *engine_data, gboolean update_tree_model) { char *new_screen_name = utils_special_printf (engine_data->screen_name_format, 'n', engine_data->name, 'v', engine_data->version, 0); if (strcmp (engine_data->screen_name, new_screen_name) != 0) { utils_free (engine_data->screen_name); engine_data->screen_name = new_screen_name; if (update_tree_model) { GtkTreeIter iterator; find_gtp_tree_model_iterator_by_engines_data (engine_data, &iterator); gtk_list_store_set (gtp_engines_list_store, &iterator, ENGINES_NAME, new_screen_name, -1); } } else utils_free (new_screen_name); } static void find_gtp_tree_model_iterator_by_engines_data (const GtpEngineListItem *engine_data, GtkTreeIter *iterator) { GtkTreeModel *gtp_engines_tree_model = GTK_TREE_MODEL (gtp_engines_list_store); GtpEngineListItem *this_engine_data; gtk_tree_model_get_iter_first (gtp_engines_tree_model, iterator); while (gtk_tree_model_get (gtp_engines_tree_model, iterator, ENGINES_DATA, &this_engine_data, -1), this_engine_data != engine_data) gtk_tree_model_iter_next (gtp_engines_tree_model, iterator); } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/gtk-progress-dialog.c0000644000175000017500000002124610522173057017673 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "gtk-control-center.h" #include "gtk-help.h" #include "gtk-progress-dialog.h" #include "gtk-utils.h" #include #include #include static void gtk_progress_dialog_class_init (GtkProgressDialogClass *class); static void gtk_progress_dialog_init (GtkProgressDialog *progress_dialog); static gboolean gtk_progress_dialog_update (GtkProgressDialog *progress_dialog); static void gtk_progress_dialog_response (GtkDialog *dialog, gint response_id); static gboolean gtk_progress_dialog_delete_event (GtkWidget *widget, GdkEventAny *event); static void gtk_progress_dialog_destroy (GtkObject *object); static GtkDialogClass *parent_class; GType gtk_progress_dialog_get_type (void) { static GType progress_dialog_type = 0; if (!progress_dialog_type) { static GTypeInfo progress_dialog_info = { sizeof (GtkProgressDialogClass), NULL, NULL, (GClassInitFunc) gtk_progress_dialog_class_init, NULL, NULL, sizeof (GtkProgressDialog), 1, (GInstanceInitFunc) gtk_progress_dialog_init, NULL }; progress_dialog_type = g_type_register_static (GTK_TYPE_DIALOG, "GtkProgressDialog", &progress_dialog_info, 0); } return progress_dialog_type; } static void gtk_progress_dialog_class_init (GtkProgressDialogClass *class) { parent_class = g_type_class_peek_parent (class); GTK_OBJECT_CLASS (class)->destroy = gtk_progress_dialog_destroy; GTK_WIDGET_CLASS (class)->delete_event = gtk_progress_dialog_delete_event; GTK_DIALOG_CLASS (class)->response = gtk_progress_dialog_response; } static void gtk_progress_dialog_init (GtkProgressDialog *progress_dialog) { GtkWindow *window = GTK_WINDOW (progress_dialog); GtkWidget *label; GtkWidget *progress_bar; GtkWidget *contents; gtk_control_center_window_created (window); gtk_window_set_resizable (window, FALSE); gtk_window_set_skip_pager_hint (window, TRUE); label = gtk_label_new (NULL); gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0); progress_dialog->label = GTK_LABEL (label); gtk_widget_show (label); progress_bar = gtk_progress_bar_new (); progress_dialog->progress_bar = GTK_PROGRESS_BAR (progress_bar); contents = gtk_utils_pack_in_box (GTK_TYPE_VBOX, QUARRY_SPACING_SMALL, label, GTK_UTILS_FILL, progress_bar, GTK_UTILS_FILL, NULL); gtk_utils_standardize_dialog (&progress_dialog->dialog, contents); gtk_widget_show (contents); gtk_dialog_set_has_separator (&progress_dialog->dialog, FALSE); progress_dialog->last_displayed_percentage = 0; progress_dialog->help_link_id = NULL; } GtkWidget * gtk_progress_dialog_new (GtkWindow *parent, const gchar *title, const gchar *label_text, GtkProgressDialogCallback update_callback, GtkProgressDialogCallback cancel_callback, gpointer user_data) { GtkWidget *widget; GtkProgressDialog *progress_dialog; g_return_val_if_fail (!parent || GTK_IS_WINDOW (parent), NULL); widget = GTK_WIDGET (g_object_new (GTK_TYPE_PROGRESS_DIALOG, NULL)); progress_dialog = GTK_PROGRESS_DIALOG (widget); progress_dialog->parent = (parent ? GTK_WIDGET (parent) : NULL); if (progress_dialog->parent) { g_object_ref (progress_dialog->parent); gtk_widget_set_sensitive (progress_dialog->parent, FALSE); g_signal_connect (progress_dialog->parent, "delete-event", G_CALLBACK (gtk_true), NULL); } if (title) gtk_window_set_title (GTK_WINDOW (progress_dialog), title); if (label_text) gtk_label_set_text (progress_dialog->label, label_text); if (cancel_callback) { gtk_dialog_add_button (&progress_dialog->dialog, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL); } progress_dialog->update_callback = update_callback; progress_dialog->cancel_callback = cancel_callback; progress_dialog->user_data = user_data; progress_dialog->timeout_handler_id = g_timeout_add (200, (GSourceFunc) gtk_progress_dialog_update, progress_dialog); return widget; } void gtk_progress_dialog_set_help_link_id (GtkProgressDialog *dialog, const gchar *help_link_id) { g_return_if_fail (GTK_IS_PROGRESS_DIALOG (dialog)); g_return_if_fail (!dialog->help_link_id); dialog->help_link_id = help_link_id; gtk_utils_add_help_button (&dialog->dialog); } static gboolean gtk_progress_dialog_update (GtkProgressDialog *progress_dialog) { gboolean keep_timeout; if (progress_dialog->update_callback) { keep_timeout = progress_dialog->update_callback (progress_dialog, progress_dialog->user_data); } else { if (!GTK_WIDGET_VISIBLE (progress_dialog)) { gtk_widget_show (GTK_WIDGET (progress_dialog)); if (progress_dialog->parent) gtk_widget_hide (progress_dialog->parent); } keep_timeout = FALSE; } if (!keep_timeout) progress_dialog->timeout_handler_id = -1; return keep_timeout; } static void gtk_progress_dialog_response (GtkDialog *dialog, gint response_id) { GtkProgressDialog *progress_dialog = GTK_PROGRESS_DIALOG (dialog); if (response_id != GTK_RESPONSE_HELP) { if (progress_dialog->cancel_callback && progress_dialog->cancel_callback (progress_dialog, progress_dialog->user_data)) gtk_widget_destroy (GTK_WIDGET (dialog)); } else gtk_help_display (progress_dialog->help_link_id); } static gboolean gtk_progress_dialog_delete_event (GtkWidget *widget, GdkEventAny *event) { GtkProgressDialog *progress_dialog = GTK_PROGRESS_DIALOG (widget); UNUSED (event); return (progress_dialog->cancel_callback && progress_dialog->cancel_callback (progress_dialog, progress_dialog->user_data) ? TRUE : FALSE); } static void gtk_progress_dialog_destroy (GtkObject *object) { GtkProgressDialog *progress_dialog = GTK_PROGRESS_DIALOG (object); if (gtk_control_center_window_destroyed (GTK_WINDOW (object))) { if (progress_dialog->parent) g_object_unref (progress_dialog->parent); if (progress_dialog->timeout_handler_id >= 0) g_source_remove (progress_dialog->timeout_handler_id); } GTK_OBJECT_CLASS (parent_class)->destroy (object); } void gtk_progress_dialog_set_fraction (GtkProgressDialog *progress_dialog, gdouble fraction, const gchar *title_part) { g_return_if_fail (GTK_IS_PROGRESS_DIALOG (progress_dialog)); gtk_progress_bar_set_fraction (progress_dialog->progress_bar, fraction); if (!GTK_WIDGET_VISIBLE (progress_dialog->progress_bar)) gtk_widget_show (GTK_WIDGET (progress_dialog->progress_bar)); if (title_part) { int percentage = floor (fraction * 100.0); if (percentage != progress_dialog->last_displayed_percentage) { gchar *full_title; full_title = g_strdup_printf ("[%d%%]%s%s", percentage, *title_part ? " " : "", title_part); gtk_window_set_title (GTK_WINDOW (progress_dialog), full_title); g_free (full_title); progress_dialog->last_displayed_percentage = percentage; } } } void gtk_progress_dialog_recover_parent (GtkProgressDialog *progress_dialog) { g_return_if_fail (GTK_IS_PROGRESS_DIALOG (progress_dialog)); if (progress_dialog->parent) { g_signal_handlers_disconnect_by_func (progress_dialog->parent, gtk_true, NULL); gtk_widget_set_sensitive (progress_dialog->parent, TRUE); gtk_widget_show (progress_dialog->parent); } } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/gtk-qbox.c0000644000175000017500000000776410371152300015542 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* This file contains implementation of QBox GTK+ class. It is the base for * QHBox and QVBox classes, which provide all necessary functionality for * smart goban placing inside Quarry windows. Practically, they allow * additional size negotiation after receiving `size_allocate' signal. * * This is kept reasonably separated from the rest of Quarry to be useful in * other programs. However, some things (e.g. properties) are missing from * the implementation, so this won't count as a completed GTK+ component. */ #include "gtk-qbox.h" static void gtk_qbox_class_init (GtkQBoxClass *klass); static void gtk_qbox_init (GtkQBox *qbox); static void gtk_qbox_remove (GtkContainer *container, GtkWidget *widget); static GtkContainerClass *parent_class; GType gtk_qbox_get_type (void) { static GtkType qbox_type = 0; if (!qbox_type) { static GTypeInfo qbox_info = { sizeof (GtkQBoxClass), NULL, NULL, (GClassInitFunc) gtk_qbox_class_init, NULL, NULL, sizeof (GtkQBox), 0, (GInstanceInitFunc) gtk_qbox_init, NULL }; qbox_type = g_type_register_static (GTK_TYPE_BOX, "GtkQBox", &qbox_info, 0); } return qbox_type; } static void gtk_qbox_class_init (GtkQBoxClass *class) { GtkContainerClass *container_class = GTK_CONTAINER_CLASS (class); parent_class = g_type_class_peek_parent (class); container_class->remove = gtk_qbox_remove; } static void gtk_qbox_init (GtkQBox *qbox) { qbox->ruling_widget = NULL; qbox->widget_callback = NULL; } /* We need to forget about the ruling widget if it is it being * removed from the box. */ static void gtk_qbox_remove (GtkContainer *container, GtkWidget *widget) { GtkQBox *qbox = GTK_QBOX (container); if (widget == qbox->ruling_widget) { qbox->ruling_widget = NULL; qbox->widget_callback = NULL; } parent_class->remove (container, widget); } void gtk_qbox_set_ruling_widget (GtkQBox *qbox, GtkWidget *widget, GtkQBoxCallback widget_callback) { g_return_if_fail (GTK_IS_QBOX (qbox)); if (widget != NULL) { g_return_if_fail (gtk_widget_get_parent (widget) == GTK_WIDGET (qbox)); g_return_if_fail (widget_callback); } else widget_callback = NULL; qbox->ruling_widget = widget; qbox->widget_callback = widget_callback; } GtkWidget * gtk_qbox_get_ruling_widget (GtkQBox *qbox) { g_return_val_if_fail (GTK_IS_QBOX (qbox), NULL); return qbox->ruling_widget; } GtkQBoxCallback gtk_qbox_get_ruling_widget_callback (GtkQBox *qbox) { g_return_val_if_fail (GTK_IS_QBOX (qbox), NULL); return qbox->widget_callback; } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/gtk-qhbox.c0000644000175000017500000001773010370756360015723 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and * * Josh MacDonald. * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* This file includes modified code from gtkhbox.c which is * distributed with GTK+. GTK+ can be found at * ftp://ftp.gtk.org/pub/gtk/. * * This file contains implementation of QHBox GTK+ class. It is * basically the same as GtkHBox, but allows some additional size * negotiation via callbacks. It also cannot be homogeneous (using * gtk_box_set_homogeneous() won't have any effect). * * This is kept reasonably separated from the rest of Quarry to be * useful in other programs. However, some things (e.g. properties) * are missing from the implementation, so this won't count as a * completed GTK+ component. */ #include "gtk-qhbox.h" static void gtk_qhbox_class_init (GtkQHBoxClass *class); static void gtk_qhbox_size_request (GtkWidget *widget, GtkRequisition *requisition); static void gtk_qhbox_size_allocate (GtkWidget *widget, GtkAllocation *allocation); GType gtk_qhbox_get_type (void) { static GType qhbox_type = 0; if (!qhbox_type) { static GTypeInfo qhbox_info = { sizeof (GtkQHBoxClass), NULL, NULL, (GClassInitFunc) gtk_qhbox_class_init, NULL, NULL, sizeof (GtkQHBox), 0, NULL, NULL }; qhbox_type = g_type_register_static (GTK_TYPE_QBOX, "GtkQHBox", &qhbox_info, 0); } return qhbox_type; } static void gtk_qhbox_class_init (GtkQHBoxClass *class) { GtkWidgetClass *widget_class = (GtkWidgetClass *) class; widget_class->size_request = gtk_qhbox_size_request; widget_class->size_allocate = gtk_qhbox_size_allocate; } GtkWidget * gtk_qhbox_new (gint spacing) { GtkWidget *widget = GTK_WIDGET (g_object_new (GTK_TYPE_QHBOX, NULL)); GtkBox *box = GTK_BOX (widget); box->homogeneous = FALSE; box->spacing = spacing; return widget; } static void gtk_qhbox_size_request (GtkWidget *widget, GtkRequisition *requisition) { GtkBox *box = GTK_BOX (widget); GList *children; gint visible_children = 0; gint double_border_width; double_border_width = GTK_CONTAINER (widget)->border_width * 2; requisition->width = double_border_width; requisition->height = double_border_width; for (children = box->children; children; children = children->next) { GtkBoxChild *child = children->data; if (GTK_WIDGET_VISIBLE (child->widget)) { GtkRequisition child_requisition; visible_children++; gtk_widget_size_request (child->widget, &child_requisition); requisition->width += child_requisition.width + child->padding * 2; requisition->height = MAX (requisition->height, child_requisition.height); } } if (visible_children > 0) requisition->width += (visible_children - 1) * box->spacing; } static void gtk_qhbox_size_allocate (GtkWidget *widget, GtkAllocation *allocation) { GtkBox *box = GTK_BOX (widget); GList *children; gint visible_children = 0; gint expandable_children = 0; widget->allocation = *allocation; for (children = box->children; children; children = children->next) { GtkBoxChild *child = children->data; if (GTK_WIDGET_VISIBLE (child->widget)) { visible_children++; if (child->expand) expandable_children++; } } if (visible_children > 0) { GtkQBox *qbox = GTK_QBOX (widget); GtkRequisition child_requisition; GtkAllocation child_allocation; gint border_width = GTK_CONTAINER (widget)->border_width; gint extra_width = allocation->width - widget->requisition.width; gint extra_width_share = 0; gint ruling_widget_width = 0; GtkTextDirection direction = gtk_widget_get_direction (widget); gint pack_start_x; gint pack_end_x; child_allocation.y = allocation->y + border_width; child_allocation.height = MAX (1, allocation->height - border_width * 2); if (qbox->ruling_widget && GTK_WIDGET_VISIBLE (qbox->ruling_widget)) { gtk_widget_get_child_requisition (qbox->ruling_widget, &child_requisition); ruling_widget_width = child_requisition.width; if (extra_width > 0) { gint requested_width = qbox->widget_callback (qbox->ruling_widget, child_allocation.height); if (requested_width >= child_requisition.width + extra_width) { ruling_widget_width = child_requisition.width + extra_width; extra_width = 0; } else if (requested_width > child_requisition.width) { ruling_widget_width = requested_width; extra_width -= requested_width - child_requisition.width; } } } if (expandable_children > 0) extra_width_share = extra_width / expandable_children; else extra_width = 0; pack_start_x = allocation->x + border_width; pack_end_x = ((allocation->x + allocation->width - border_width) + box->spacing); for (children = box->children; children; children = children->next) { GtkBoxChild *child = children->data; if (GTK_WIDGET_VISIBLE (child->widget)) { gint child_extra_width = 0; gint full_child_width; gtk_widget_get_child_requisition (child->widget, &child_requisition); if (child->widget == qbox->ruling_widget) child_allocation.width = ruling_widget_width; else child_allocation.width = child_requisition.width; if (child->expand) { if (expandable_children == 1) child_extra_width = extra_width; else { child_extra_width = extra_width_share; extra_width -= extra_width_share; expandable_children--; } } full_child_width = (child_allocation.width + child_extra_width + child->padding * 2 + box->spacing); if (child->pack == GTK_PACK_START) { child_allocation.x = pack_start_x + child->padding; pack_start_x += full_child_width; } else { pack_end_x -= full_child_width; child_allocation.x = pack_end_x + child->padding; } if (child->fill) child_allocation.width += child_extra_width; else child_allocation.x += child_extra_width / 2; if (direction == GTK_TEXT_DIR_RTL) { child_allocation.x = (allocation->x + allocation->width - (child_allocation.x - allocation->x) - child_allocation.width); } gtk_widget_size_allocate (child->widget, &child_allocation); } } } } gint gtk_qhbox_negotiate_height (GtkWidget *widget, gint width) { GtkQBox *qbox = GTK_QBOX (widget); GtkRequisition child_requisition; if (qbox->ruling_widget == NULL || !GTK_WIDGET_VISIBLE (qbox->ruling_widget)) return 0; gtk_widget_get_child_requisition (qbox->ruling_widget, &child_requisition); return qbox->widget_callback (qbox->ruling_widget, (child_requisition.width + width - widget->requisition.width)); } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/gtk-qvbox.c0000644000175000017500000002000610370756360015727 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and * * Josh MacDonald. * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* This file includes modified code from gtkhbox.c which is * distributed with GTK+. GTK+ can be found at * ftp://ftp.gtk.org/pub/gtk/. * * This file contains implementation of QVBox GTK+ class. It is * basically the same as GtkVBox, but allows some additional size * negotiation via callbacks. It also cannot be homogeneous (using * gtk_box_set_homogeneous() won't have any effect). * * This is kept reasonably separated from the rest of Quarry to be * useful in other programs. However, some things (e.g. properties) * are missing from the implementation, so this won't count as a * completed GTK+ component. */ #include "gtk-qvbox.h" static void gtk_qvbox_class_init (GtkQVBoxClass *class); static void gtk_qvbox_size_request (GtkWidget *widget, GtkRequisition *requisition); static void gtk_qvbox_size_allocate (GtkWidget *widget, GtkAllocation *allocation); GType gtk_qvbox_get_type (void) { static GType qvbox_type = 0; if (!qvbox_type) { static GTypeInfo qvbox_info = { sizeof (GtkQVBoxClass), NULL, NULL, (GClassInitFunc) gtk_qvbox_class_init, NULL, NULL, sizeof (GtkQVBox), 0, NULL, NULL }; qvbox_type = g_type_register_static (GTK_TYPE_QBOX, "GtkQVBox", &qvbox_info, 0); } return qvbox_type; } static void gtk_qvbox_class_init (GtkQVBoxClass *class) { GtkWidgetClass *widget_class = (GtkWidgetClass *) class; widget_class->size_request = gtk_qvbox_size_request; widget_class->size_allocate = gtk_qvbox_size_allocate; } GtkWidget * gtk_qvbox_new (gint spacing) { GtkWidget *widget = GTK_WIDGET (g_object_new (GTK_TYPE_QVBOX, NULL)); GtkBox *box = GTK_BOX (widget); box->homogeneous = FALSE; box->spacing = spacing; return widget; } static void gtk_qvbox_size_request (GtkWidget *widget, GtkRequisition *requisition) { GtkBox *box = GTK_BOX (widget); GList *children; gint visible_children = 0; gint double_border_width; double_border_width = GTK_CONTAINER (widget)->border_width * 2; requisition->width = double_border_width; requisition->height = double_border_width; for (children = box->children; children; children = children->next) { GtkBoxChild *child = children->data; if (GTK_WIDGET_VISIBLE (child->widget)) { GtkRequisition child_requisition; visible_children++; gtk_widget_size_request (child->widget, &child_requisition); requisition->width = MAX (requisition->width, child_requisition.width); requisition->height += child_requisition.height + child->padding * 2; } } if (visible_children > 0) requisition->height += (visible_children - 1) * box->spacing; } static void gtk_qvbox_size_allocate (GtkWidget *widget, GtkAllocation *allocation) { GtkBox *box = GTK_BOX (widget); GList *children; gint visible_children = 0; gint expandable_children = 0; widget->allocation = *allocation; for (children = box->children; children; children = children->next) { GtkBoxChild *child = children->data; if (GTK_WIDGET_VISIBLE (child->widget)) { visible_children++; if (child->expand) expandable_children++; } } if (visible_children > 0) { GtkQBox *qbox = GTK_QBOX (widget); GtkRequisition child_requisition; GtkAllocation child_allocation; gint border_width = GTK_CONTAINER (widget)->border_width; gint extra_height = allocation->height - widget->requisition.height; gint extra_height_share = 0; gint ruling_widget_height = 0; GtkTextDirection direction = gtk_widget_get_direction (widget); gint pack_start_y; gint pack_end_y; child_allocation.x = allocation->x + border_width; child_allocation.width = MAX (1, allocation->width - border_width * 2); if (qbox->ruling_widget && GTK_WIDGET_VISIBLE (qbox->ruling_widget)) { gtk_widget_get_child_requisition (qbox->ruling_widget, &child_requisition); ruling_widget_height = child_requisition.height; if (extra_height > 0) { gint requested_height = qbox->widget_callback (qbox->ruling_widget, child_allocation.width); if (requested_height >= child_requisition.height + extra_height) { ruling_widget_height = child_requisition.height + extra_height; extra_height = 0; } else if (requested_height > child_requisition.height) { ruling_widget_height = requested_height; extra_height -= requested_height - child_requisition.height; } } } if (expandable_children > 0) extra_height_share = extra_height / expandable_children; else extra_height = 0; pack_start_y = allocation->y + border_width; pack_end_y = ((allocation->y + allocation->height - border_width) + box->spacing); for (children = box->children; children; children = children->next) { GtkBoxChild *child = children->data; if (GTK_WIDGET_VISIBLE (child->widget)) { gint child_extra_height = 0; gint full_child_height; gtk_widget_get_child_requisition (child->widget, &child_requisition); if (child->widget == qbox->ruling_widget) child_allocation.height = ruling_widget_height; else child_allocation.height = child_requisition.height; if (child->expand) { if (expandable_children == 1) child_extra_height = extra_height; else { child_extra_height = extra_height_share; extra_height -= extra_height_share; expandable_children--; } } full_child_height = (child_allocation.height + child_extra_height + child->padding * 2 + box->spacing); if (child->pack == GTK_PACK_START) { child_allocation.y = pack_start_y + child->padding; pack_start_y += full_child_height; } else { pack_end_y -= full_child_height; child_allocation.y = pack_end_y + child->padding; } if (child->fill) child_allocation.height += child_extra_height; else child_allocation.y += child_extra_height / 2; if (direction == GTK_TEXT_DIR_RTL) { child_allocation.y = (allocation->y + allocation->height - (child_allocation.y - allocation->y) - child_allocation.height); } gtk_widget_size_allocate (child->widget, &child_allocation); } } } } gint gtk_qvbox_negotiate_width (GtkWidget *widget, gint height) { GtkQBox *qbox = GTK_QBOX (widget); GtkRequisition child_requisition; if (qbox->ruling_widget == NULL || !GTK_WIDGET_VISIBLE (qbox->ruling_widget)) return 0; gtk_widget_get_child_requisition (qbox->ruling_widget, &child_requisition); return qbox->widget_callback (qbox->ruling_widget, (child_requisition.height + height - widget->requisition.height)); } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/gtk-resume-game-dialog.c0000644000175000017500000003560410522173460020237 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "gtk-resume-game-dialog.h" #include "gtk-configuration.h" #include "gtk-control-center.h" #include "gtk-games.h" #include "gtk-goban-window.h" #include "gtk-help.h" #include "gtk-named-vbox.h" #include "gtk-parser-interface.h" #include "gtk-preferences.h" #include "gtk-utils.h" #include "quarry-message-dialog.h" #include "time-control.h" #include "sgf.h" #include "board.h" #include "game-info.h" #include #include #include #include typedef struct _GameRecordData GameRecordData; typedef struct _ResumeGameDialogData ResumeGameDialogData; struct _GameRecordData { SgfCollection *sgf_collection; gchar *filename; }; struct _ResumeGameDialogData { GtkWidget *dialog; SgfCollection *sgf_collection; gchar *filename; GtkEntry *name_entries[NUM_COLORS]; GtkToggleButton *player_radio_buttons[NUM_COLORS][2]; GtkWidget *engine_selectors[NUM_COLORS]; GtpClient *players[NUM_COLORS]; }; static void analyze_game_to_be_resumed (SgfCollection *sgf_collection, SgfErrorList *sgf_error_list, const gchar *filename); static void maybe_open_game_record (GtkWidget *dialog, gint response_id, GameRecordData *data); static void gtk_resume_game_dialog_present (SgfCollection *sgf_collection, const gchar *filename); static void set_computer_opponent_sensitivity (GtkWidget *selector, ResumeGameDialogData *data); static void gtk_resume_game_dialog_response (GtkWidget *dialog, gint response_id, ResumeGameDialogData *data); static void do_resume_game (GtkEnginesInstantiationStatus status, gpointer user_data); void gtk_resume_game (void) { static GtkWindow *resume_game_dialog = NULL; gtk_parser_interface_present (&resume_game_dialog, _("Resume Game..."), analyze_game_to_be_resumed); } static void analyze_game_to_be_resumed (SgfCollection *sgf_collection, SgfErrorList *sgf_error_list, const gchar *filename) { gchar *filename_in_utf8 = g_filename_to_utf8 (filename, -1, NULL, NULL, NULL); const SgfGameTree *const sgf_tree = sgf_collection->first_tree; SgfResult game_result; if (sgf_error_list) string_list_delete (sgf_error_list); if (!GAME_IS_SUPPORTED (sgf_tree->game)) { GtkWidget *error_dialog = quarry_message_dialog_new (NULL, GTK_BUTTONS_OK, GTK_STOCK_DIALOG_ERROR, NULL, _("The game stored in file `%s' (%s) " "is not supported by Quarry"), filename_in_utf8, _(game_info[sgf_tree->game].name)); g_free (filename_in_utf8); gtk_utils_show_and_forget_dialog (GTK_DIALOG (error_dialog)); sgf_collection_delete (sgf_collection); return; } game_result = sgf_node_get_result (sgf_tree->root, NULL); if (game_result != SGF_RESULT_NOT_SET && game_result != SGF_RESULT_VOID && game_result != SGF_RESULT_UNKNOWN) { GameRecordData *data = g_malloc (sizeof (GameRecordData)); GtkWidget *error_dialog = quarry_message_dialog_new (NULL, GTK_BUTTONS_NONE, GTK_STOCK_DIALOG_ERROR, NULL, _("This game appears to have been " "finished. Open it for viewing " "and/or editing instead?")); g_free (filename_in_utf8); gtk_dialog_add_buttons (GTK_DIALOG (error_dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL); gtk_dialog_set_default_response (GTK_DIALOG (error_dialog), GTK_RESPONSE_OK); data->sgf_collection = sgf_collection; data->filename = g_strdup (filename); g_signal_connect (error_dialog, "response", G_CALLBACK (maybe_open_game_record), data); gtk_window_present (GTK_WINDOW (error_dialog)); return; } gtk_resume_game_dialog_present (sgf_collection, filename); } static void maybe_open_game_record (GtkWidget *dialog, gint response_id, GameRecordData *data) { if (response_id == GTK_RESPONSE_OK) { GtkWidget *goban_window = gtk_goban_window_new (data->sgf_collection, data->filename); gtk_window_present (GTK_WINDOW (goban_window)); } else sgf_collection_delete (data->sgf_collection); gtk_widget_destroy (dialog); g_free (data->filename); g_free (data); } /* FIXME: Show information about game time control and remaining time * for both players. */ static void gtk_resume_game_dialog_present (SgfCollection *sgf_collection, const gchar *filename) { static gchar buffer[64]; gchar *filename_in_utf8 = g_filename_to_utf8 (filename, -1, NULL, NULL, NULL); gchar *base_name = g_path_get_basename (filename_in_utf8); const SgfGameTree *const sgf_tree = sgf_collection->first_tree; GtkGameIndex game_index = gtk_games_get_game_index (sgf_tree->game); ResumeGameDialogData *data = g_malloc (sizeof (ResumeGameDialogData)); GtkWidget *dialog; GtkWidget *game_information_vbox; GtkBox *game_information_box; GtkWidget *field_name_label; GtkWidget *field_value_label; GtkWidget *hbox1; GtkWidget *hbox2; GtkWidget *vbox; GtkWidget *player_vboxes[NUM_COLORS]; int k; data->sgf_collection = sgf_collection; data->filename = g_strdup (filename); dialog = gtk_dialog_new_with_buttons (_("Resuming Game"), NULL, 0, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, _("_Resume"), GTK_RESPONSE_OK, NULL); gtk_utils_add_help_button (GTK_DIALOG (dialog)); data->dialog = dialog; gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK); gtk_utils_make_window_only_horizontally_resizable (GTK_WINDOW (dialog)); gtk_control_center_window_created (GTK_WINDOW (dialog)); g_signal_connect (dialog, "response", G_CALLBACK (gtk_resume_game_dialog_response), data); g_signal_connect (dialog, "destroy", G_CALLBACK (gtk_control_center_window_destroyed), NULL); game_information_vbox = gtk_named_vbox_new (_("Short Game Information"), FALSE, QUARRY_SPACING_SMALL); game_information_box = GTK_BOX (game_information_vbox); field_name_label = gtk_utils_create_left_aligned_label (_("Game:")); field_value_label = (gtk_utils_create_left_aligned_label (gtk_games_get_capitalized_name (sgf_tree->game))); hbox1 = gtk_utils_pack_in_box (GTK_TYPE_HBOX, QUARRY_SPACING, field_name_label, GTK_UTILS_FILL, field_value_label, GTK_UTILS_FILL, NULL); sprintf (buffer, "%d", sgf_tree->board_width); field_name_label = gtk_utils_create_left_aligned_label (_("Board size:")); field_value_label = gtk_utils_create_left_aligned_label (buffer); hbox2 = gtk_utils_pack_in_box (GTK_TYPE_HBOX, QUARRY_SPACING, field_name_label, GTK_UTILS_FILL, field_value_label, GTK_UTILS_FILL, NULL); if (sgf_tree->game == GAME_GO) { GtkWidget *vbox2; const gchar *handicap = sgf_node_get_text_property_value (sgf_tree->root, SGF_HANDICAP); const gchar *komi = sgf_node_get_text_property_value (sgf_tree->root, SGF_KOMI); vbox = gtk_utils_pack_in_box (GTK_TYPE_VBOX, QUARRY_SPACING_SMALL, hbox1, GTK_UTILS_FILL, hbox2, GTK_UTILS_FILL, NULL); field_name_label = gtk_utils_create_left_aligned_label (_("Handicap:")); field_value_label = gtk_utils_create_left_aligned_label (handicap ? handicap : Q_("handicap|Not set")); hbox1 = gtk_utils_pack_in_box (GTK_TYPE_HBOX, QUARRY_SPACING, field_name_label, GTK_UTILS_FILL, field_value_label, GTK_UTILS_FILL, NULL); field_name_label = gtk_utils_create_left_aligned_label (_("Komi:")); field_value_label = gtk_utils_create_left_aligned_label (komi ? komi : Q_("komi|Not set")); hbox2 = gtk_utils_pack_in_box (GTK_TYPE_HBOX, QUARRY_SPACING, field_name_label, GTK_UTILS_FILL, field_value_label, GTK_UTILS_FILL, NULL); vbox2 = gtk_utils_pack_in_box (GTK_TYPE_VBOX, QUARRY_SPACING_SMALL, hbox1, GTK_UTILS_FILL, hbox2, GTK_UTILS_FILL, NULL); hbox1 = gtk_utils_pack_in_box (GTK_TYPE_HBOX, QUARRY_SPACING_VERY_BIG, vbox, GTK_UTILS_FILL, vbox2, GTK_UTILS_FILL, NULL); gtk_box_set_homogeneous (GTK_BOX (hbox1), TRUE); gtk_box_pack_start (game_information_box, hbox1, FALSE, TRUE, 0); } else { gtk_box_pack_start (game_information_box, hbox1, FALSE, TRUE, 0); gtk_box_pack_start (game_information_box, hbox2, FALSE, TRUE, 0); } field_name_label = gtk_utils_create_left_aligned_label (_("Filename:")); field_value_label = gtk_utils_create_left_aligned_label (base_name); g_free (base_name); g_free (filename_in_utf8); hbox1 = gtk_utils_pack_in_box (GTK_TYPE_HBOX, QUARRY_SPACING, field_name_label, GTK_UTILS_FILL, field_value_label, GTK_UTILS_FILL, NULL); gtk_box_pack_start (game_information_box, hbox1, FALSE, TRUE, 0); for (k = 0; k < NUM_COLORS; k++) { /* Same as in New Game dialog. */ static const char *radio_labels[NUM_COLORS][2] = { { N_("Hu_man"), N_("Compu_ter") }, { N_("H_uman"), N_("Com_puter") } }; GtkWidget **radio_buttons = (GtkWidget **) data->player_radio_buttons[k]; GtkWidget *entry; GtkWidget *hbox3; const gchar *player_name = sgf_node_get_text_property_value (sgf_tree->root, (k == WHITE_INDEX ? SGF_PLAYER_WHITE : SGF_PLAYER_BLACK)); const GtpEngineListItem *engine_data = gtk_preferences_guess_engine_by_name (player_name, game_index); entry = gtk_utils_create_entry (player_name, RETURN_ACTIVATES_DEFAULT); data->name_entries[k] = GTK_ENTRY (entry); field_name_label = gtk_utils_create_mnemonic_label (k == WHITE_INDEX ? _("_Name:") : _("N_ame:"), entry); hbox1 = gtk_utils_pack_in_box (GTK_TYPE_HBOX, QUARRY_SPACING, field_name_label, GTK_UTILS_FILL, entry, GTK_UTILS_PACK_DEFAULT, NULL); gtk_utils_create_radio_chain (radio_buttons, radio_labels[k], 2); hbox2 = gtk_utils_pack_in_box (GTK_TYPE_HBOX, QUARRY_SPACING, radio_buttons[0], 0, NULL); data->engine_selectors[k] = (gtk_preferences_create_engine_selector (game_index, TRUE, engine_data, (GtkEngineChanged) set_computer_opponent_sensitivity, data)); if (engine_data) gtk_toggle_button_set_active (data->player_radio_buttons[k][1], TRUE); gtk_utils_set_sensitive_on_toggle (data->player_radio_buttons[k][1], data->engine_selectors[k], FALSE); hbox3 = gtk_utils_pack_in_box (GTK_TYPE_HBOX, QUARRY_SPACING, radio_buttons[1], GTK_UTILS_FILL, data->engine_selectors[k], GTK_UTILS_PACK_DEFAULT, NULL); vbox = gtk_utils_pack_in_box (GTK_TYPE_VBOX, QUARRY_SPACING_SMALL, hbox2, GTK_UTILS_FILL, hbox3, GTK_UTILS_FILL, NULL); player_vboxes[k] = gtk_utils_pack_in_box (GTK_TYPE_NAMED_VBOX, QUARRY_SPACING, hbox1, GTK_UTILS_FILL, vbox, GTK_UTILS_FILL); gtk_named_vbox_set_label_text (GTK_NAMED_VBOX (player_vboxes[k]), (k == BLACK_INDEX ? _("Black Player") : _("White Player"))); } vbox = gtk_utils_pack_in_box (GTK_TYPE_VBOX, QUARRY_SPACING_BIG, game_information_vbox, GTK_UTILS_FILL, player_vboxes[WHITE_INDEX], GTK_UTILS_FILL, player_vboxes[BLACK_INDEX], GTK_UTILS_FILL, NULL); gtk_utils_align_left_widgets (GTK_CONTAINER (vbox), NULL); gtk_widget_show_all (vbox); gtk_utils_standardize_dialog (GTK_DIALOG (dialog), vbox); gtk_window_present (GTK_WINDOW (dialog)); } static void set_computer_opponent_sensitivity (GtkWidget *selector, ResumeGameDialogData *data) { UNUSED (selector); if (gtk_preferences_have_non_hidden_gtp_engine ()) { gtk_widget_set_sensitive (GTK_WIDGET (data->player_radio_buttons[BLACK_INDEX][1]), TRUE); gtk_widget_set_sensitive (GTK_WIDGET (data->player_radio_buttons[WHITE_INDEX][1]), TRUE); } else { gtk_toggle_button_set_active (data->player_radio_buttons[BLACK_INDEX][0], TRUE); gtk_toggle_button_set_active (data->player_radio_buttons[WHITE_INDEX][0], TRUE); gtk_widget_set_sensitive (GTK_WIDGET (data->player_radio_buttons[BLACK_INDEX][1]), FALSE); gtk_widget_set_sensitive (GTK_WIDGET (data->player_radio_buttons[WHITE_INDEX][1]), FALSE); } } static void gtk_resume_game_dialog_response (GtkWidget *dialog, gint response_id, ResumeGameDialogData *data) { if (response_id == GTK_RESPONSE_OK) { int k; GtkWindow *window = GTK_WINDOW (dialog); GtkEngineChain *engine_chain = gtk_preferences_create_engines_instantiation_chain (window, do_resume_game, data); for (k = 0; k < NUM_COLORS; k++) { if (GTK_WIDGET_IS_SENSITIVE (data->engine_selectors[k])) { gtk_preferences_instantiate_selected_engine (engine_chain, data->engine_selectors[k], &data->players[k]); } else data->players[k] = NULL; } gtk_preferences_do_instantiate_engines (engine_chain); } else if (response_id == GTK_RESPONSE_HELP) gtk_help_display ("resuming-game-dialog"); else { sgf_collection_delete (data->sgf_collection); g_free (data->filename); g_free (data); gtk_widget_destroy (dialog); } } static void do_resume_game (GtkEnginesInstantiationStatus status, gpointer user_data) { ResumeGameDialogData *data; GtkWidget *goban_window; if (status != ENGINES_INSTANTIATED) return; data = (ResumeGameDialogData *) user_data; goban_window = gtk_goban_window_new (data->sgf_collection, data->filename); gtk_goban_window_resume_game (GTK_GOBAN_WINDOW (goban_window), data->players[BLACK_INDEX], data->players[WHITE_INDEX]); gtk_window_present (GTK_WINDOW (goban_window)); gtk_widget_destroy (data->dialog); g_free (data->filename); g_free (data); } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/gtk-sgf-tree-signal-proxy.c0000644000175000017500000002226310371152510020731 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "gtk-sgf-tree-signal-proxy.h" #include "quarry-marshal.h" #include "sgf.h" #include static void gtk_sgf_tree_signal_proxy_class_init (GtkSgfTreeSignalProxyClass *class); static void gtk_sgf_tree_signal_proxy_finalize (GObject *object); static void receive_notification (SgfGameTree *sgf_tree, SgfGameTreeNotificationCode notification_code, GtkSgfTreeSignalProxy *proxy); enum { ABOUT_TO_MODIFY_MAP, ABOUT_TO_MODIFY_TREE, ABOUT_TO_CHANGE_CURRENT_NODE, CURRENT_NODE_CHANGED, TREE_MODIFIED, MAP_MODIFIED, NUM_SIGNALS }; static guint sgf_tree_signal_proxy_signals[NUM_SIGNALS]; GType gtk_sgf_tree_signal_proxy_get_type (void) { static GType sgf_tree_signal_proxy_type = 0; if (!sgf_tree_signal_proxy_type) { static GTypeInfo sgf_tree_signal_proxy_info = { sizeof (GtkSgfTreeSignalProxyClass), NULL, NULL, (GClassInitFunc) gtk_sgf_tree_signal_proxy_class_init, NULL, NULL, sizeof (GtkSgfTreeSignalProxy), 1, NULL, NULL }; sgf_tree_signal_proxy_type = g_type_register_static (G_TYPE_OBJECT, "GtkSgfTreeSignalProxy", &sgf_tree_signal_proxy_info, 0); } return sgf_tree_signal_proxy_type; } static void gtk_sgf_tree_signal_proxy_class_init (GtkSgfTreeSignalProxyClass *class) { G_OBJECT_CLASS (class)->finalize = gtk_sgf_tree_signal_proxy_finalize; class->about_to_modify_map = NULL; class->about_to_modify_tree = NULL; class->about_to_change_current_node = NULL; class->current_node_changed = NULL; class->tree_modified = NULL; class->map_modified = NULL; sgf_tree_signal_proxy_signals[ABOUT_TO_MODIFY_MAP] = g_signal_new ("about-to-modify-map", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GtkSgfTreeSignalProxyClass, about_to_modify_map), NULL, NULL, quarry_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); sgf_tree_signal_proxy_signals[ABOUT_TO_MODIFY_TREE] = g_signal_new ("about-to-modify-tree", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GtkSgfTreeSignalProxyClass, about_to_modify_tree), NULL, NULL, quarry_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); sgf_tree_signal_proxy_signals[ABOUT_TO_CHANGE_CURRENT_NODE] = g_signal_new ("about-to-change-current-node", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GtkSgfTreeSignalProxyClass, about_to_change_current_node), NULL, NULL, quarry_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); sgf_tree_signal_proxy_signals[CURRENT_NODE_CHANGED] = g_signal_new ("current-node-changed", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GtkSgfTreeSignalProxyClass, current_node_changed), NULL, NULL, quarry_marshal_VOID__POINTER_POINTER, G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_POINTER); sgf_tree_signal_proxy_signals[TREE_MODIFIED] = g_signal_new ("tree-modified", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GtkSgfTreeSignalProxyClass, tree_modified), NULL, NULL, quarry_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); sgf_tree_signal_proxy_signals[MAP_MODIFIED] = g_signal_new ("map-modified", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GtkSgfTreeSignalProxyClass, map_modified), NULL, NULL, quarry_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); } static void gtk_sgf_tree_signal_proxy_finalize (GObject *object) { GtkSgfTreeSignalProxy *proxy = GTK_SGF_TREE_SIGNAL_PROXY (object); if (proxy->state_stack) { g_warning ("warning: finalizing SGF tree signal proxy" " with non-empty state stack"); g_slist_foreach (proxy->state_stack, (GFunc) g_free, NULL); g_slist_free (proxy->state_stack); } } GObject * gtk_sgf_tree_signal_proxy_attach (SgfGameTree *sgf_tree) { g_return_val_if_fail (sgf_tree, NULL); if (sgf_tree->user_data) { g_return_val_if_fail (GTK_IS_SGF_TREE_SIGNAL_PROXY (sgf_tree->user_data), NULL); return G_OBJECT (sgf_tree->user_data); } else { GObject *proxy = g_object_new (GTK_TYPE_SGF_TREE_SIGNAL_PROXY, NULL); GTK_SGF_TREE_SIGNAL_PROXY (proxy)->sgf_tree = sgf_tree; GTK_SGF_TREE_SIGNAL_PROXY (proxy)->state_stack = NULL; sgf_game_tree_set_notification_callback (sgf_tree, ((SgfGameTreeNotificationCallback) receive_notification), proxy); return proxy; } } void gtk_sgf_tree_signal_proxy_push_tree_state (SgfGameTree *sgf_tree, const SgfGameTreeState *new_state) { GtkSgfTreeSignalProxy *proxy; SgfGameTreeState *old_state; g_return_if_fail (sgf_tree); g_return_if_fail (GTK_IS_SGF_TREE_SIGNAL_PROXY (sgf_tree->user_data)); proxy = GTK_SGF_TREE_SIGNAL_PROXY (sgf_tree->user_data); old_state = g_malloc (sizeof (SgfGameTreeState)); sgf_game_tree_get_state (sgf_tree, old_state); sgf_game_tree_set_state (sgf_tree, new_state); proxy->state_stack = g_slist_prepend (proxy->state_stack, old_state); } void gtk_sgf_tree_signal_proxy_pop_tree_state (SgfGameTree *sgf_tree, SgfGameTreeState *old_state) { GtkSgfTreeSignalProxy *proxy; GSList *popped_link; g_return_if_fail (sgf_tree); g_return_if_fail (GTK_IS_SGF_TREE_SIGNAL_PROXY (sgf_tree->user_data)); proxy = GTK_SGF_TREE_SIGNAL_PROXY (sgf_tree->user_data); g_return_if_fail (proxy->state_stack); if (old_state) sgf_game_tree_get_state (sgf_tree, old_state); popped_link = proxy->state_stack; proxy->state_stack = popped_link->next; sgf_game_tree_set_state (sgf_tree, (SgfGameTreeState *) popped_link->data); g_free (popped_link->data); g_slist_free_1 (popped_link); } static void receive_notification (SgfGameTree *sgf_tree, SgfGameTreeNotificationCode notification_code, GtkSgfTreeSignalProxy *proxy) { SgfGameTreeState current_tree_state; g_return_if_fail (proxy->sgf_tree == sgf_tree); if (proxy->state_stack) { if (notification_code == SGF_ABOUT_TO_CHANGE_CURRENT_NODE || notification_code == SGF_CURRENT_NODE_CHANGED) { /* These are suppressed when working with ``secondary'' game * tree states. */ return; } /* Signal handlers are kept unaware of board state changes. */ sgf_game_tree_get_state (sgf_tree, ¤t_tree_state); sgf_game_tree_set_state (sgf_tree, ((SgfGameTreeState *) g_slist_last (proxy->state_stack)->data)); } switch (notification_code) { case SGF_ABOUT_TO_MODIFY_MAP: g_signal_emit (proxy, sgf_tree_signal_proxy_signals[ABOUT_TO_MODIFY_MAP], 0, sgf_tree); break; case SGF_ABOUT_TO_MODIFY_TREE: g_signal_emit (proxy, sgf_tree_signal_proxy_signals[ABOUT_TO_MODIFY_TREE], 0, sgf_tree); break; case SGF_ABOUT_TO_CHANGE_CURRENT_NODE: g_signal_emit (proxy, sgf_tree_signal_proxy_signals[ABOUT_TO_CHANGE_CURRENT_NODE], 0, sgf_tree); return; case SGF_CURRENT_NODE_CHANGED: g_signal_emit (proxy, sgf_tree_signal_proxy_signals[CURRENT_NODE_CHANGED], 0, sgf_tree, proxy->old_current_node); return; case SGF_TREE_MODIFIED: g_signal_emit (proxy, sgf_tree_signal_proxy_signals[TREE_MODIFIED], 0, sgf_tree); break; case SGF_MAP_MODIFIED: g_signal_emit (proxy, sgf_tree_signal_proxy_signals[MAP_MODIFIED], 0, sgf_tree); break; case SGF_GAME_TREE_DELETED: g_object_unref (proxy); break; default: g_critical ("unhandled SGF notification code %d", notification_code); return; } if (proxy->state_stack) { /* Restore current game tree state. */ sgf_game_tree_set_state (sgf_tree, ¤t_tree_state); } } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/gtk-sgf-tree-view.c0000644000175000017500000012142210530064032017242 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* FIXME: Implement smarter invalidation of view: only invalidate the * changed part, not the whole widget. */ #include "gtk-sgf-tree-view.h" #include "gtk-configuration.h" #include "gtk-goban-base.h" #include "gtk-sgf-tree-signal-proxy.h" #include "gtk-tile-set.h" #include "gtk-utils.h" #include "gui-back-end.h" #include "quarry-marshal.h" #include "sgf.h" #include "board.h" #include "utils.h" #include #if HAVE_MEMORY_H #include #endif /* FIXME: Make it zoomable and delete this (or, rather, throw them to * `gtk-configuration.list'. */ #define DEFAULT_CELL_SIZE 24 #define PADDING_WIDTH(cell_size) \ ((gint) (((cell_size) + 6) / 12)) #define FULL_CELL_SIZE(view) \ ((view)->base.cell_size + 2 * PADDING_WIDTH ((view)->base.cell_size)) #define VIEW_PORT_NODE(view, x, y) \ * ((view)->view_port_nodes \ + (((y) - (view)->view_port_y0) \ * ((view)->view_port_x1 - (view)->view_port_x0)) \ + ((x) - (view)->view_port_x0)) #define SHOULD_TRACK_CURRENT_NODE(view) \ ((view)->current_tree \ && (game_tree_view.track_current_node == TRACK_CURRENT_NODE_ALWAYS \ || ((game_tree_view.track_current_node \ == TRACK_CURRENT_NODE_AUTOMATICALLY) \ && (sgf_game_tree_node_is_within_view_port \ ((view)->current_tree, \ (view)->current_tree->current_node, \ (view)->view_port_x0, (view)->view_port_y0, \ (view)->view_port_x1, (view)->view_port_y1, \ NULL, NULL))))) static void gtk_sgf_tree_view_class_init (GtkSgfTreeViewClass *class); static void gtk_sgf_tree_view_init (GtkSgfTreeView *view); static void gtk_sgf_tree_view_realize (GtkWidget *widget); static void gtk_sgf_tree_view_size_request (GtkWidget *widget, GtkRequisition *requisition); static void gtk_sgf_tree_view_size_allocate (GtkWidget *widget, GtkAllocation *allocation); static void gtk_sgf_tree_view_set_scroll_adjustments (GtkSgfTreeView *view, GtkAdjustment *hadjustment, GtkAdjustment *vadjustment); static void gtk_sgf_tree_view_style_set (GtkWidget *widget, GtkStyle *previous_style); static gboolean gtk_sgf_tree_view_expose (GtkWidget *widget, GdkEventExpose *event); static gboolean gtk_sgf_tree_view_button_press_event (GtkWidget *widget, GdkEventButton *event); static gboolean gtk_sgf_tree_view_button_release_event (GtkWidget *widget, GdkEventButton *event); static gboolean gtk_sgf_tree_view_motion_notify_event (GtkWidget *widget, GdkEventMotion *event); static void gtk_sgf_tree_view_unrealize (GtkWidget *widget); static void gtk_sgf_tree_view_finalize (GObject *object); static void gtk_sgf_tree_view_destroy (GtkObject *object); static void configure_adjustment (GtkSgfTreeView *view, gboolean horizontal, gint original_value); static void disconnect_adjustment (GtkSgfTreeView *view, GtkAdjustment *adjustment); static void scroll_adjustment_value_changed (GtkSgfTreeView *view); static void center_on_current_node (GtkSgfTreeView *view); static void track_current_node (GtkSgfTreeView *view); static void update_view_port (GtkSgfTreeView *view); static gboolean update_view_port_and_maybe_move_or_resize_window (GtkSgfTreeView *view, gint original_hadjustment_value, gint original_vadjustment_value); static void about_to_modify_map (GtkSgfTreeView *view); static void about_to_change_current_node (GtkSgfTreeView *view); static void current_node_changed (GtkSgfTreeView *view); static void map_modified (GtkSgfTreeView *view); static GtkTooltips * get_shared_tooltips (void); static void append_limited_text (StringBuffer *buffer, const char *text, gint num_characters_limit); static void synthesize_enter_notify_event (GdkEvent *event); static GtkGobanBaseClass *parent_class; enum { SGF_TREE_VIEW_CLICKED, NUM_SIGNALS }; static guint sgf_tree_view_signals[NUM_SIGNALS]; GType gtk_sgf_tree_view_get_type (void) { static GType sgf_tree_view_type = 0; if (!sgf_tree_view_type) { static GTypeInfo sgf_tree_view_info = { sizeof (GtkSgfTreeViewClass), NULL, NULL, (GClassInitFunc) gtk_sgf_tree_view_class_init, NULL, NULL, sizeof (GtkSgfTreeView), 1, (GInstanceInitFunc) gtk_sgf_tree_view_init, NULL }; sgf_tree_view_type = g_type_register_static (GTK_TYPE_GOBAN_BASE, "GtkSgfTreeView", &sgf_tree_view_info, 0); } return sgf_tree_view_type; } static void gtk_sgf_tree_view_class_init (GtkSgfTreeViewClass *class) { GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class); parent_class = g_type_class_peek_parent (class); G_OBJECT_CLASS (class)->finalize = gtk_sgf_tree_view_finalize; GTK_OBJECT_CLASS (class)->destroy = gtk_sgf_tree_view_destroy; widget_class->realize = gtk_sgf_tree_view_realize; widget_class->unrealize = gtk_sgf_tree_view_unrealize; widget_class->size_request = gtk_sgf_tree_view_size_request; widget_class->size_allocate = gtk_sgf_tree_view_size_allocate; widget_class->style_set = gtk_sgf_tree_view_style_set; widget_class->expose_event = gtk_sgf_tree_view_expose; widget_class->button_press_event = gtk_sgf_tree_view_button_press_event; widget_class->button_release_event = gtk_sgf_tree_view_button_release_event; widget_class->motion_notify_event = gtk_sgf_tree_view_motion_notify_event; class->set_scroll_adjustments = gtk_sgf_tree_view_set_scroll_adjustments; class->sgf_tree_view_clicked = NULL; widget_class->set_scroll_adjustments_signal = g_signal_new ("set-scroll-adjustments", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GtkSgfTreeViewClass, set_scroll_adjustments), NULL, NULL, quarry_marshal_VOID__OBJECT_OBJECT, G_TYPE_NONE, 2, GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT); sgf_tree_view_signals[SGF_TREE_VIEW_CLICKED] = g_signal_new ("sgf-tree-view-clicked", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GtkSgfTreeViewClass, sgf_tree_view_clicked), NULL, NULL, quarry_marshal_VOID__POINTER_INT, G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_INT); } static void gtk_sgf_tree_view_init (GtkSgfTreeView *view) { /* FIXME */ gtk_goban_base_set_cell_size (GTK_GOBAN_BASE (view), DEFAULT_CELL_SIZE); view->hadjustment = NULL; view->vadjustment = NULL; view->ignore_adjustment_changes = FALSE; view->current_tree = NULL; view->map_width = 1; view->map_height = 1; view->last_tooltips_node = NULL; } GtkWidget * gtk_sgf_tree_view_new (void) { return GTK_WIDGET (g_object_new (GTK_TYPE_SGF_TREE_VIEW, NULL)); } static void gtk_sgf_tree_view_realize (GtkWidget *widget) { GtkSgfTreeView *view = GTK_SGF_TREE_VIEW (widget); GdkWindowAttr attributes; const gint attributes_mask = (GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP); const gint event_mask = (GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK); if (!view->hadjustment || !view->vadjustment) gtk_sgf_tree_view_set_scroll_adjustments (view, NULL, NULL); if (view->current_tree) { sgf_game_tree_get_map_dimensions (view->current_tree, &view->map_width, &view->map_height); update_view_port (view); } GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED); attributes.event_mask = 0; attributes.x = widget->allocation.x; attributes.y = widget->allocation.y; attributes.width = widget->allocation.width; attributes.height = widget->allocation.height; attributes.wclass = GDK_INPUT_OUTPUT; attributes.visual = gtk_widget_get_visual (widget); attributes.colormap = gtk_widget_get_colormap (widget); attributes.window_type = GDK_WINDOW_CHILD; widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask); gdk_window_set_user_data (widget->window, view); gdk_window_set_back_pixmap (widget->window, NULL, FALSE); attributes.event_mask = gtk_widget_get_events (widget) | event_mask; attributes.x = - view->hadjustment->value; attributes.y = - view->vadjustment->value; attributes.width = view->hadjustment->upper; attributes.height = view->vadjustment->upper; view->output_window = gdk_window_new (widget->window, &attributes, attributes_mask); gdk_window_set_user_data (view->output_window, view); widget->style = gtk_style_attach (widget->style, widget->window); gtk_style_set_background (widget->style, view->output_window, GTK_STATE_NORMAL); gdk_window_show (view->output_window); GTK_WIDGET_CLASS (parent_class)->realize (widget); } static void gtk_sgf_tree_view_size_request (GtkWidget *widget, GtkRequisition *requisition) { GtkSgfTreeView *view = GTK_SGF_TREE_VIEW (widget); gint full_cell_size = FULL_CELL_SIZE (view); requisition->width = view->map_width * full_cell_size; requisition->height = view->map_height * full_cell_size; } static void gtk_sgf_tree_view_size_allocate (GtkWidget *widget, GtkAllocation *allocation) { GtkSgfTreeView *view = GTK_SGF_TREE_VIEW (widget); GTK_WIDGET_CLASS (parent_class)->size_allocate (widget, allocation); update_view_port_and_maybe_move_or_resize_window (view, (gint) view->hadjustment->value, (gint) view->vadjustment->value); } static void gtk_sgf_tree_view_set_scroll_adjustments (GtkSgfTreeView *view, GtkAdjustment *hadjustment, GtkAdjustment *vadjustment) { if (hadjustment) g_return_if_fail (GTK_IS_ADJUSTMENT (hadjustment)); else { hadjustment = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0)); } if (view->hadjustment != hadjustment) { disconnect_adjustment (view, view->hadjustment); view->hadjustment = hadjustment; g_object_ref (hadjustment); gtk_object_sink (GTK_OBJECT (hadjustment)); configure_adjustment (view, TRUE, 0); g_signal_connect_swapped (hadjustment, "value-changed", G_CALLBACK (scroll_adjustment_value_changed), view); } if (vadjustment) g_return_if_fail (GTK_IS_ADJUSTMENT (vadjustment)); else { vadjustment = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0)); } if (view->vadjustment != vadjustment) { disconnect_adjustment (view, view->vadjustment); view->vadjustment = vadjustment; g_object_ref (vadjustment); gtk_object_sink (GTK_OBJECT (vadjustment)); configure_adjustment (view, FALSE, 0); g_signal_connect_swapped (vadjustment, "value-changed", G_CALLBACK (scroll_adjustment_value_changed), view); } } /* We need to set style background not on `widget->window', but on the * `output_window'. Therefore the override. */ static void gtk_sgf_tree_view_style_set (GtkWidget *widget, GtkStyle *previous_style) { UNUSED (previous_style); if (GTK_WIDGET_REALIZED (widget)) { gtk_style_set_background (widget->style, GTK_SGF_TREE_VIEW (widget)->output_window, GTK_STATE_NORMAL); } } static gboolean gtk_sgf_tree_view_expose (GtkWidget *widget, GdkEventExpose *event) { UNUSED (event); if (GTK_WIDGET_DRAWABLE (widget)) { GtkSgfTreeView *view = GTK_SGF_TREE_VIEW (widget); int x; int y; int map_offset; int k; SgfGameTreeMapLine *lines_scan; gint full_cell_size = FULL_CELL_SIZE (view); gint full_cell_size_half = full_cell_size / 2; gint stones_left_margin = (full_cell_size / 2 + view->base.main_tile_set->stones_x_offset); gint stones_top_margin = (full_cell_size / 2 + view->base.main_tile_set->stones_y_offset); /* FIXME: Something is not aligned well... */ gint sgf_markup_margin = ((full_cell_size - view->base.sgf_markup_tile_set->tile_size) / 2) + 1; GdkWindow *window = view->output_window; GdkGC *gc = widget->style->fg_gc[GTK_STATE_NORMAL]; g_return_val_if_fail (view->current_tree, FALSE); g_return_val_if_fail (view->view_port_nodes, FALSE); g_return_val_if_fail (view->view_port_lines, FALSE); g_return_val_if_fail (view->tile_map, FALSE); g_return_val_if_fail (view->sgf_markup_tile_map, FALSE); gdk_gc_set_line_attributes (gc, 2, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND); for (lines_scan = view->view_port_lines, k = 0; k < view->num_view_port_lines; lines_scan++, k++) { GdkPoint points[4]; GdkPoint *next_point = points; GdkPoint *point_scan; gint y2 = lines_scan->y1 + (lines_scan->x2 - lines_scan->x0); /* The clipping below is a workaround for X drawing functions' * bug: they cannot handle line lengths over 32K properly. */ if (lines_scan->x2 >= view->view_port_x0) { if (lines_scan->x0 >= view->view_port_x0) { if (lines_scan->y1 >= view->view_port_y0) { if (lines_scan->y0 < lines_scan->y1) { next_point->x = lines_scan->x0; next_point->y = MAX (lines_scan->y0, view->view_port_y0 - 1); next_point++; } if (lines_scan->y1 < view->view_port_y1) { next_point->x = lines_scan->x0; next_point->y = lines_scan->y1; next_point++; } else { next_point->x = lines_scan->x0; next_point->y = view->view_port_y1; next_point++; goto line_clipped; } } else { next_point->y = view->view_port_y0 - 1; next_point->x = lines_scan->x0 + (next_point->y - lines_scan->y1); next_point++; } } else { next_point->x = view->view_port_x0 - 1; next_point->y = lines_scan->y1 + (next_point->x - lines_scan->x0); next_point++; } if (y2 > lines_scan->y1) { if ((view->view_port_x1 - (next_point - 1)->x) > (view->view_port_y1 - (next_point - 1)->y)) { next_point->y = MIN (y2, view->view_port_y1); next_point->x = lines_scan->x0 + (next_point->y - lines_scan->y1); next_point++; } else { next_point->x = MIN (lines_scan->x2, view->view_port_x1); next_point->y = lines_scan->y1 + (next_point->x - lines_scan->x0); next_point++; } } } else { next_point->x = view->view_port_x0 - 1; next_point->y = y2; next_point++; } if (y2 < view->view_port_y1) { next_point->x = MIN (lines_scan->x3, view->view_port_x1); next_point->y = y2; next_point++; } line_clipped: for (point_scan = points; point_scan < next_point; point_scan++) { point_scan->x = point_scan->x * full_cell_size + full_cell_size_half; point_scan->y = point_scan->y * full_cell_size + full_cell_size_half; } gdk_draw_lines (window, gc, points, next_point - points); } for (map_offset = 0, y = view->view_port_y0; y < view->view_port_y1; y++) { for (x = view->view_port_x0; x < view->view_port_x1; map_offset++, x++) { const SgfNode *sgf_node = view->view_port_nodes[map_offset]; gint main_tile = view->tile_map[map_offset]; gint sgf_markup_tile = view->sgf_markup_tile_map[map_offset]; if (sgf_node == view->current_tree->current_node) { /* FIXME: Improve. */ gdk_draw_rectangle (window, gc, FALSE, x * full_cell_size + 1, y * full_cell_size + 1, full_cell_size - 2, full_cell_size - 2); } if (main_tile != TILE_NONE) { gdk_draw_pixbuf (window, gc, view->base.main_tile_set->tiles[main_tile], 0, 0, stones_left_margin + x * full_cell_size, stones_top_margin + y * full_cell_size, -1, -1, GDK_RGB_DITHER_NORMAL, 0, 0); } if (sgf_markup_tile != SGF_MARKUP_NONE) { gint background = (sgf_node->move_color != SETUP_NODE ? sgf_node->move_color : EMPTY); gdk_draw_pixbuf (window, gc, (view->base.sgf_markup_tile_set ->tiles[sgf_markup_tile][background]), 0, 0, sgf_markup_margin + x * full_cell_size, sgf_markup_margin + y * full_cell_size, -1, -1, GDK_RGB_DITHER_NORMAL, 0, 0); } } } gdk_gc_set_line_attributes (gc, 0, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER); } return FALSE; } static gboolean gtk_sgf_tree_view_button_press_event (GtkWidget *widget, GdkEventButton *event) { if (event->button == 1 || event->button == 3) { GtkSgfTreeView *view = GTK_SGF_TREE_VIEW (widget); gint full_cell_size = FULL_CELL_SIZE (view); gint x; gint y; gdk_window_get_pointer (view->output_window, &x, &y, NULL); x /= full_cell_size; y /= full_cell_size; if (view->button_pressed == 0) { view->button_pressed = event->button; view->press_x = x; view->press_y = y; } else view->button_pressed = -1; } return FALSE; } static gboolean gtk_sgf_tree_view_button_release_event (GtkWidget *widget, GdkEventButton *event) { if (event->button == 1 || event->button == 3) { GtkSgfTreeView *view = GTK_SGF_TREE_VIEW (widget); if (view->button_pressed == event->button) { gint full_cell_size = FULL_CELL_SIZE (view); gint x; gint y; gdk_window_get_pointer (view->output_window, &x, &y, NULL); x /= full_cell_size; y /= full_cell_size; if (x == view->press_x && y == view->press_y) { SgfNode *clicked_node = VIEW_PORT_NODE (view, x, y); if (clicked_node) { g_signal_emit (G_OBJECT (view), sgf_tree_view_signals[SGF_TREE_VIEW_CLICKED], 0, clicked_node, event->button); } } } view->button_pressed = 0; } /* Make sure tooltips reappear now. */ synthesize_enter_notify_event ((GdkEvent *) event); return FALSE; } static gboolean gtk_sgf_tree_view_motion_notify_event (GtkWidget *widget, GdkEventMotion *event) { GtkSgfTreeView *view = GTK_SGF_TREE_VIEW (widget); gint full_cell_size = FULL_CELL_SIZE (view); const SgfNode *node = VIEW_PORT_NODE (view, (int) event->x / full_cell_size, (int) event->y / full_cell_size); if (node != view->last_tooltips_node) { /* FIXME: I would like some markup in the tooltip, e.g. boldened * node name. However, this is not very important, let's * see if GTK+ provides advanced tooltips itself before * inventing our own. */ GtkTooltips *tooltips = get_shared_tooltips (); StringBuffer tooltip_text; gboolean had_tooltip_set = (gtk_tooltips_data_get (widget) != NULL); string_buffer_init (&tooltip_text, 0x400, 0x200); if (node) { const char *node_name = sgf_node_get_text_property_value (node, SGF_NODE_NAME); const char *comment = sgf_node_get_text_property_value (node, SGF_COMMENT); if (IS_STONE (node->move_color)) { int move_number = sgf_utils_get_node_move_number (node, view->current_tree); string_buffer_printf (&tooltip_text, _("Move %d: "), move_number); sgf_utils_format_node_move (view->current_tree, node, &tooltip_text, _("B "), _("W "), _("pass")); } if (node_name) { if (tooltip_text.length) string_buffer_add_characters (&tooltip_text, '\n', 2); string_buffer_cat_string (&tooltip_text, _("Node name: ")); append_limited_text (&tooltip_text, node_name, 80); } if (comment) { if (tooltip_text.length) string_buffer_add_characters (&tooltip_text, '\n', 2); append_limited_text (&tooltip_text, comment, 400); } } gtk_tooltips_set_tip (tooltips, GTK_WIDGET (view), (tooltip_text.length ? tooltip_text.string : NULL), NULL); if (tooltip_text.length && !had_tooltip_set) synthesize_enter_notify_event ((GdkEvent *) event); string_buffer_dispose (&tooltip_text); view->last_tooltips_node = node; } return FALSE; } static void gtk_sgf_tree_view_unrealize (GtkWidget *widget) { GtkSgfTreeView *view = GTK_SGF_TREE_VIEW (widget); gdk_window_set_user_data (view->output_window, NULL); gdk_window_destroy (view->output_window); utils_free (view->view_port_nodes); utils_free (view->view_port_lines); utils_free (view->tile_map); utils_free (view->sgf_markup_tile_map); view->view_port_nodes = NULL; view->view_port_lines = NULL; view->tile_map = NULL; view->sgf_markup_tile_map = NULL; GTK_WIDGET_CLASS (parent_class)->unrealize (widget); } static void gtk_sgf_tree_view_destroy (GtkObject *object) { GtkSgfTreeView *view = GTK_SGF_TREE_VIEW (object); disconnect_adjustment (view, view->hadjustment); disconnect_adjustment (view, view->vadjustment); GTK_OBJECT_CLASS (parent_class)->destroy (object); } static void gtk_sgf_tree_view_finalize (GObject *object) { GtkSgfTreeView *view = GTK_SGF_TREE_VIEW (object); disconnect_adjustment (view, view->hadjustment); disconnect_adjustment (view, view->vadjustment); if (view->last_tooltips_node) { gtk_tooltips_set_tip (get_shared_tooltips (), GTK_WIDGET (view), NULL, NULL); } G_OBJECT_CLASS (parent_class)->finalize (object); } void gtk_sgf_tree_view_set_sgf_tree (GtkSgfTreeView *view, SgfGameTree *sgf_tree) { GObject *proxy; g_return_if_fail (GTK_IS_SGF_TREE_VIEW (view)); g_return_if_fail (sgf_tree); if (view->current_tree) { GObject *old_proxy = GET_SIGNAL_PROXY (view->current_tree); g_signal_handlers_disconnect_by_func (old_proxy, about_to_modify_map, view); g_signal_handlers_disconnect_by_func (old_proxy, about_to_change_current_node, view); g_signal_handlers_disconnect_by_func (old_proxy, current_node_changed, view); g_signal_handlers_disconnect_by_func (old_proxy, map_modified, view); } view->current_tree = sgf_tree; proxy = GET_SIGNAL_PROXY (sgf_tree); g_signal_connect_swapped (proxy, "about-to-modify-map", G_CALLBACK (about_to_modify_map), view); g_signal_connect_swapped (proxy, "about-to-change-current-node", G_CALLBACK (about_to_change_current_node), view); g_signal_connect_swapped (proxy, "current-node-changed", G_CALLBACK (current_node_changed), view); g_signal_connect_swapped (proxy, "map-modified", G_CALLBACK (map_modified), view); gtk_goban_base_set_game (GTK_GOBAN_BASE (view), sgf_tree->game); if (!view->hadjustment || !view->vadjustment) gtk_sgf_tree_view_set_scroll_adjustments (view, NULL, NULL); } void gtk_sgf_tree_view_update_view_port (GtkSgfTreeView *view) { g_return_if_fail (GTK_IS_SGF_TREE_VIEW (view)); update_view_port (view); /* FIXME: Suboptimal. */ gtk_widget_queue_draw (GTK_WIDGET (view)); } void gtk_sgf_tree_view_center_on_current_node (GtkSgfTreeView *view) { gint view_x; gint view_y; g_return_if_fail (GTK_IS_SGF_TREE_VIEW (view)); view_x = (gint) view->hadjustment->value; view_y = (gint) view->vadjustment->value; center_on_current_node (view); update_view_port_and_maybe_move_or_resize_window (view, view_x, view_y); } gboolean gtk_sgf_tree_view_get_tooltips_enabled (void) { return game_tree_view.show_tooltips; } void gtk_sgf_tree_view_set_tooltips_enabled (gboolean enabled) { game_tree_view.show_tooltips = enabled; if (enabled) gtk_tooltips_enable (get_shared_tooltips ()); else gtk_tooltips_disable (get_shared_tooltips ()); } static void configure_adjustment (GtkSgfTreeView *view, gboolean horizontal, gint original_value) { GtkAdjustment *adjustment = (horizontal ? view->hadjustment : view->vadjustment); GtkWidget *widget = GTK_WIDGET (view); gboolean adjustment_has_changed = FALSE; gboolean value_has_changed = (original_value != (gint) adjustment->value); gint page_size = (horizontal ? widget->allocation.width : widget->allocation.height); gint full_cell_size = FULL_CELL_SIZE (view); gint upper = MAX (((horizontal ? view->map_width : view->map_height) * full_cell_size), page_size); if (adjustment->lower != 0.0) { adjustment->lower = 0.0; adjustment_has_changed = TRUE; } if ((gint) adjustment->upper != upper) { adjustment->upper = upper; adjustment_has_changed = TRUE; } if ((gint) adjustment->page_size != page_size) { adjustment->page_size = page_size; adjustment_has_changed = TRUE; } if ((gint) adjustment->page_increment != (gint) (page_size * 0.9)) { adjustment->page_increment = (gint) (page_size * 0.9); adjustment_has_changed = TRUE; } if ((gint) adjustment->step_increment != full_cell_size) { adjustment->step_increment = full_cell_size; adjustment_has_changed = TRUE; } if (adjustment->value < 0.0 || (upper - page_size) < adjustment->value) { adjustment->value = (adjustment->value < 0.0 ? 0.0 : upper - page_size); value_has_changed = TRUE; } if (adjustment_has_changed) gtk_adjustment_changed (adjustment); if (value_has_changed) gtk_adjustment_value_changed (adjustment); } static void disconnect_adjustment (GtkSgfTreeView *view, GtkAdjustment *adjustment) { if (adjustment) { g_signal_handlers_disconnect_by_func (adjustment, scroll_adjustment_value_changed, view); g_object_unref (adjustment); if (view->hadjustment == adjustment) view->hadjustment = NULL; else view->vadjustment = NULL; } } static void scroll_adjustment_value_changed (GtkSgfTreeView *view) { if (GTK_WIDGET_REALIZED (view) && !view->ignore_adjustment_changes) { gint old_x_value; gint old_y_value; gint new_x_value = - view->hadjustment->value; gint new_y_value = - view->vadjustment->value; gdk_window_get_position (view->output_window, &old_x_value, &old_y_value); if (old_x_value != new_x_value || old_y_value != new_y_value) { update_view_port (view); gdk_window_move (view->output_window, new_x_value, new_y_value); gdk_window_process_updates (view->output_window, FALSE); } } } /* See if we need to move the view port to keep the current node * within it, and if so, set adjustment values. */ static void track_current_node (GtkSgfTreeView *view) { gint view_x = (gint) view->hadjustment->value; gint view_y = (gint) view->vadjustment->value; gint view_width = GTK_WIDGET (view)->allocation.width; gint view_height = GTK_WIDGET (view)->allocation.height; gint full_cell_size = FULL_CELL_SIZE (view); gint current_node_x; gint current_node_y; if (!view->current_tree) { /* No tree to begin with, so nothing to track. */ return; } if (!sgf_game_tree_get_node_coordinates (view->current_tree, view->current_tree->current_node, ¤t_node_x, ¤t_node_y)) { /* This means the current node is in a collapsed subtree. Nothing * to track, return now. */ return; } current_node_x *= full_cell_size; current_node_y *= full_cell_size; if (current_node_x < view_x || view_x + view_width - full_cell_size < current_node_x || (view_width > 4 * full_cell_size && (current_node_x < view_x + full_cell_size || (view_x + view_width - 2 * full_cell_size < current_node_x))) || current_node_y < view_y || view_y + view_height - full_cell_size < current_node_y || (view_height > 4 * full_cell_size && (current_node_y < view_y + full_cell_size || (view_y + view_height - 2 * full_cell_size < current_node_y)))) { if (game_tree_view.center_on_current_node) center_on_current_node (view); else { if (view_width > 4 * full_cell_size) { if (view_x > current_node_x - full_cell_size) view->hadjustment->value = current_node_x - full_cell_size; else { gint minimal_value = (((current_node_x - view_width + (8 * full_cell_size) / 3) / full_cell_size) * full_cell_size); if (view_x < minimal_value) view->hadjustment->value = minimal_value; } } else { if (view_x > current_node_x) view->hadjustment->value = current_node_x; else { gint minimal_value = (((current_node_x - view_width + (5 * full_cell_size) / 3) / full_cell_size) * full_cell_size); if (view_x < minimal_value) view->hadjustment->value = minimal_value; } } if (view_height > 4 * full_cell_size) { if (view_y > current_node_y - full_cell_size) view->vadjustment->value = current_node_y - full_cell_size; else { gint minimal_value = (((current_node_y - view_height + (8 * full_cell_size) / 3) / full_cell_size) * full_cell_size); if (view_y < minimal_value) view->vadjustment->value = minimal_value; } } else { if (view_y > current_node_y) view->vadjustment->value = current_node_y; else { gint minimal_value = (((current_node_y - view_height + 2 * full_cell_size) / full_cell_size) * full_cell_size); if (view_y < minimal_value) view->vadjustment->value = minimal_value; } } } update_view_port_and_maybe_move_or_resize_window (view, view_x, view_y); } } /* Center the view on current node. This function only sets * adjustment values, but doesn't update view port---the caller is * supposed to do that. */ static void center_on_current_node (GtkSgfTreeView *view) { gint current_node_x; gint current_node_y; if (view->current_tree && sgf_game_tree_get_node_coordinates (view->current_tree, view->current_tree->current_node, ¤t_node_x, ¤t_node_y)) { gint view_width = GTK_WIDGET (view)->allocation.width; gint view_height = GTK_WIDGET (view)->allocation.height; gint full_cell_size = FULL_CELL_SIZE (view); view->hadjustment->value = (((current_node_x * full_cell_size - (2 * view_width - 3 * full_cell_size) / 4) / full_cell_size) * full_cell_size); view->vadjustment->value = (((current_node_y * full_cell_size - (2 * view_height - 3 * full_cell_size) / 4) / full_cell_size) * full_cell_size); } } static void update_view_port (GtkSgfTreeView *view) { GtkAllocation *allocation = & GTK_WIDGET (view)->allocation; gint full_cell_size = FULL_CELL_SIZE (view); const SgfNode **view_port_scan; char *tile_map_scan; char *sgf_markup_tile_map_scan; int x; int y; view->view_port_x0 = (gint) view->hadjustment->value / full_cell_size; view->view_port_y0 = (gint) view->vadjustment->value / full_cell_size; view->view_port_x1 = (((gint) view->hadjustment->value + allocation->width + full_cell_size - 1) / full_cell_size); view->view_port_y1 = (((gint) view->vadjustment->value + allocation->height + full_cell_size - 1) / full_cell_size); utils_free (view->view_port_nodes); utils_free (view->view_port_lines); utils_free (view->tile_map); utils_free (view->sgf_markup_tile_map); if (view->current_tree) { sgf_game_tree_fill_map_view_port (view->current_tree, view->view_port_x0, view->view_port_y0, view->view_port_x1, view->view_port_y1, &view->view_port_nodes, &view->view_port_lines, &view->num_view_port_lines); view->tile_map = sgf_game_tree_get_current_branch_marks (view->current_tree, view->view_port_x0, view->view_port_y0, view->view_port_x1, view->view_port_y1); } else { view->view_port_nodes = utils_malloc0 (((view->view_port_x1 - view->view_port_x0) * (view->view_port_y1 - view->view_port_y0)) * sizeof (SgfNode *)); view->view_port_lines = NULL; view->num_view_port_lines = 0; } view->sgf_markup_tile_map = utils_malloc (((view->view_port_x1 - view->view_port_x0) * (view->view_port_y1 - view->view_port_y0)) * sizeof (char)); for (view_port_scan = (const SgfNode **) view->view_port_nodes, tile_map_scan = view->tile_map, sgf_markup_tile_map_scan = view->sgf_markup_tile_map, y = view->view_port_y0; y < view->view_port_y1; y++) { for (x = view->view_port_x0; x < view->view_port_x1; view_port_scan++, tile_map_scan++, sgf_markup_tile_map_scan++, x++) { const SgfNode *sgf_node = *view_port_scan; if (sgf_node && IS_STONE (sgf_node->move_color)) { switch (*tile_map_scan) { case SGF_NON_CURRENT_BRANCH_NODE: *tile_map_scan = (sgf_node->move_color == BLACK ? BLACK_50_TRANSPARENT : WHITE_50_TRANSPARENT); break; case SGF_CURRENT_BRANCH_HEAD_NODE: case SGF_CURRENT_NODE: case SGF_CURRENT_BRANCH_TAIL_NODE: *tile_map_scan = (sgf_node->move_color == BLACK ? BLACK_OPAQUE : WHITE_OPAQUE); break; default: g_critical ("unknown SGF map code %d", *tile_map_scan); *tile_map_scan = TILE_NONE; } *sgf_markup_tile_map_scan = (sgf_node->is_collapsed ? SGF_MARKUP_CROSS : SGF_MARKUP_NONE); } else { *tile_map_scan = TILE_NONE; *sgf_markup_tile_map_scan = SGF_MARKUP_NONE; } } } } static gboolean update_view_port_and_maybe_move_or_resize_window (GtkSgfTreeView *view, gint original_hadjustment_value, gint original_vadjustment_value) { gint original_hadjustment_upper = view->hadjustment->upper; gint original_vadjustment_upper = view->vadjustment->upper; gboolean need_to_resize_window; gboolean need_to_move_window; if (view->current_tree) { sgf_game_tree_get_map_dimensions (view->current_tree, &view->map_width, &view->map_height); } else { view->map_width = 1; view->map_height = 1; } view->ignore_adjustment_changes = TRUE; configure_adjustment (view, TRUE, original_hadjustment_value); configure_adjustment (view, FALSE, original_vadjustment_value); view->ignore_adjustment_changes = FALSE; need_to_resize_window = ((original_hadjustment_upper != (gint) view->hadjustment->upper) || (original_vadjustment_upper != (gint) view->vadjustment->upper)); need_to_move_window = ((original_hadjustment_value != (gint) view->hadjustment->value) || (original_vadjustment_value != (gint) view->vadjustment->value)); if (GTK_WIDGET_REALIZED (view)) { update_view_port (view); if (need_to_resize_window || need_to_move_window) { if (need_to_resize_window) { if (need_to_move_window) { gdk_window_move_resize (view->output_window, - (gint) view->hadjustment->value, - (gint) view->vadjustment->value, (gint) view->hadjustment->upper, (gint) view->vadjustment->upper); } else { gdk_window_resize (view->output_window, (gint) view->hadjustment->upper, (gint) view->vadjustment->upper); } } else { gdk_window_move (view->output_window, - (gint) view->hadjustment->value, - (gint) view->vadjustment->value); } /* FIXME: Improve. */ gtk_widget_queue_draw (GTK_WIDGET (view)); gdk_window_process_updates (view->output_window, FALSE); return TRUE; } } return FALSE; } static void about_to_modify_map (GtkSgfTreeView *view) { if (GTK_WIDGET_REALIZED (view)) { view->expect_map_modification = TRUE; view->do_track_current_node = SHOULD_TRACK_CURRENT_NODE (view); } } static void about_to_change_current_node (GtkSgfTreeView *view) { if (GTK_WIDGET_REALIZED (view) && !view->expect_map_modification) view->do_track_current_node = SHOULD_TRACK_CURRENT_NODE (view); } static void current_node_changed (GtkSgfTreeView *view) { if (GTK_WIDGET_REALIZED (view)) { if (view->expect_map_modification) return; if (view->do_track_current_node) { gint view_x = (gint) view->hadjustment->value; gint view_y = (gint) view->vadjustment->value; track_current_node (view); if (!update_view_port_and_maybe_move_or_resize_window (view, view_x, view_y)) { /* FIXME: Suboptimal. */ gtk_widget_queue_draw (GTK_WIDGET (view)); } } else { update_view_port (view); /* FIXME: Suboptimal. */ gtk_widget_queue_draw (GTK_WIDGET (view)); } } } static void map_modified (GtkSgfTreeView *view) { if (GTK_WIDGET_REALIZED (view)) { gint view_x = (gint) view->hadjustment->value; gint view_y = (gint) view->vadjustment->value; if (view->do_track_current_node) track_current_node (view); if (!update_view_port_and_maybe_move_or_resize_window (view, view_x, view_y)) { /* FIXME: Suboptimal. */ gtk_widget_queue_draw (GTK_WIDGET (view)); } } view->expect_map_modification = FALSE; } /* Append not more than about `num_characters_limit' of `text' to the * given string `buffer'. Note that `num_characters_limit' is * considered to be advisory only and more text can be appended still. */ static void append_limited_text (StringBuffer *buffer, const char *text, gint num_characters_limit) { int k; const char *limit; const char *scan; for (k = 0, limit = text; k < num_characters_limit; k++) { if (!*limit) { /* All the text doesn't exceed the limit. Append everything. */ string_buffer_cat_as_string (buffer, text, limit - text); return; } limit = g_utf8_next_char (limit); } /* Let's not cut off 10% of text. */ for (k = 0, scan = limit; k < num_characters_limit / 10; k++) { if (!*scan) { string_buffer_cat_as_string (buffer, text, scan - text); return; } scan = g_utf8_next_char (scan); } /* OK, so the text is quite long. Now let's determine an * appropriate cutting point. For now, we only uncoditionally skip * backward all whitespace-like and control-like characters. * * FIXME: Improve. In particular, try to not cut words apart. * Maybe try using Pango for really good behavior... */ for (scan = limit; scan > text; ) { GUnicodeType type; scan = g_utf8_prev_char (scan); type = g_unichar_type (g_utf8_get_char (scan)); if (type != G_UNICODE_CONTROL && type != G_UNICODE_CONTROL && type != G_UNICODE_FORMAT && type != G_UNICODE_UNASSIGNED && type != G_UNICODE_PRIVATE_USE && type != G_UNICODE_SURROGATE && type != G_UNICODE_COMBINING_MARK && type != G_UNICODE_ENCLOSING_MARK && type != G_UNICODE_NON_SPACING_MARK && type != G_UNICODE_LINE_SEPARATOR && type != G_UNICODE_PARAGRAPH_SEPARATOR && type != G_UNICODE_SPACE_SEPARATOR) break; } string_buffer_cat_as_string (buffer, text, g_utf8_next_char (scan) - text); /* Append ellipsis to indicate text truncation. */ string_buffer_cat_string (buffer, "\342\200\246"); } static GtkTooltips * get_shared_tooltips (void) { static GtkTooltips *shared_tooltips = NULL; if (!shared_tooltips) { shared_tooltips = gtk_tooltips_new (); g_object_ref (shared_tooltips); gtk_object_sink (GTK_OBJECT (shared_tooltips)); gui_back_end_register_object_to_finalize (shared_tooltips); /* Enable or disable the tooltips, as appropriate. */ gtk_sgf_tree_view_set_tooltips_enabled (game_tree_view.show_tooltips); } return shared_tooltips; } /* This is a workaround for GTK+ deficiency: if you set tooltip for * the widget under the pointer and it didn't have one before, the * tooltip won't appear. We synthesize an `enter-notify' event so * that GtkTooltips will think the pointer has just entered the widget * window. This function is also called after clicks on the widget. */ static void synthesize_enter_notify_event (GdkEvent *event) { GdkEventCrossing synthesized_event; synthesized_event.type = GDK_ENTER_NOTIFY; synthesized_event.window = event->any.window; synthesized_event.send_event = TRUE; synthesized_event.subwindow = event->any.window; synthesized_event.time = gdk_event_get_time (event); synthesized_event.mode = GDK_CROSSING_NORMAL; synthesized_event.detail = GDK_NOTIFY_UNKNOWN; synthesized_event.focus = FALSE; gdk_event_get_coords (event, &synthesized_event.x, &synthesized_event.y); gdk_event_get_root_coords (event, &synthesized_event.x_root, &synthesized_event.y_root); gdk_event_get_state (event, &synthesized_event.state); /* Note: this works better than gtk_main_do_event(). Apparently, * GtkTooltips won't show tooltips when a button is still pressed * and we call this function from * gtk_sgf_tree_view_button_release_event() too. */ gdk_event_put ((GdkEvent *) &synthesized_event); } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/gtk-tile-set.c0000644000175000017500000004526010371153132016314 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "gtk-configuration.h" #include "gtk-preferences.h" #include "markup-theme-configuration.h" #include "tile-renderer.h" #include "sgf.h" #include "board.h" #include "game-info.h" #include "utils.h" #include "gtk-tile-set.h" #include #include #include #include #if HAVE_MEMORY_H #include #endif typedef struct _GtkMainTileSetKey GtkMainTileSetKey; typedef struct _GtkSgfMarkupTileSetKey GtkSgfMarkupTileSetKey; struct _GtkMainTileSetKey { gint tile_size; Game game; }; struct _GtkSgfMarkupTileSetKey { gint tile_size; const gchar *theme_directory; gdouble scale; QuarryColor colors[NUM_SGF_MARKUP_BACKGROUNDS]; gdouble opacity; }; static int gtk_main_tile_set_compare_keys (const GtkMainTileSetKey *first_key, const GtkMainTileSetKey *second_key); static void * gtk_main_tile_set_duplicate_key (const GtkMainTileSetKey *key); static void * gtk_main_tile_set_create (const GtkMainTileSetKey *key); static void gtk_main_tile_set_delete (GtkMainTileSet *tile_set); static int gtk_sgf_markup_tile_set_compare_keys (const GtkSgfMarkupTileSetKey *first_key, const GtkSgfMarkupTileSetKey *second_key); static void * gtk_sgf_markup_tile_set_duplicate_key (const GtkSgfMarkupTileSetKey *key); static void * gtk_sgf_markup_tile_set_create (const GtkSgfMarkupTileSetKey *key); static void gtk_sgf_markup_tile_set_delete (GtkSgfMarkupTileSet *tile_set); static GdkPixbuf * scale_and_paint_svg_image (guchar *buffer, const guchar *buffer_end, gint tile_size, gdouble scale, QuarryColor color, gdouble opacity); static void set_pixbuf_size (gint *width, gint *height, gpointer tile_size); inline static GdkPixbuf * create_pixbuf_from_pixel_data (int tile_size, unsigned char *pixel_data, int row_stride); ObjectCache gtk_main_tile_set_cache = { NULL, NULL, 0, 20, (ObjectCacheCompareKeys) gtk_main_tile_set_compare_keys, (ObjectCacheCreate) gtk_main_tile_set_duplicate_key, (ObjectCacheCreate) gtk_main_tile_set_create, (ObjectCacheDelete) g_free, (ObjectCacheDelete) gtk_main_tile_set_delete }; ObjectCache gtk_sgf_markup_tile_set_cache = { NULL, NULL, 0, 10, (ObjectCacheCompareKeys) gtk_sgf_markup_tile_set_compare_keys, (ObjectCacheCreate) gtk_sgf_markup_tile_set_duplicate_key, (ObjectCacheCreate) gtk_sgf_markup_tile_set_create, (ObjectCacheDelete) g_free, (ObjectCacheDelete) gtk_sgf_markup_tile_set_delete }; GtkMainTileSet * gtk_main_tile_set_create_or_reuse (gint tile_size, Game game) { const GtkMainTileSetKey key = { (game == GAME_GO ? (tile_size - 1) | 1 : tile_size), game }; g_return_val_if_fail (tile_size > 0, NULL); g_return_val_if_fail (GAME_IS_SUPPORTED (game), NULL); return ((GtkMainTileSet *) object_cache_create_or_reuse_object (>k_main_tile_set_cache, &key)); } static int gtk_main_tile_set_compare_keys (const GtkMainTileSetKey *first_key, const GtkMainTileSetKey *second_key) { return (first_key->tile_size == second_key->tile_size && first_key->game == second_key->game); } static void * gtk_main_tile_set_duplicate_key (const GtkMainTileSetKey *key) { GtkMainTileSetKey *key_copy = g_malloc (sizeof (GtkMainTileSetKey)); key_copy->tile_size = key->tile_size; key_copy->game = key->game; return key_copy; } static void * gtk_main_tile_set_create (const GtkMainTileSetKey *key) { GtkMainTileSet *tile_set = g_malloc (sizeof (GtkMainTileSet)); gint tile_size = key->tile_size; unsigned char *black_pixel_data; unsigned char *white_pixel_data; int row_stride; unsigned char *pixel_data; unsigned char *black_50_transparent_pixel_data; unsigned char *white_50_transparent_pixel_data; tile_set->tile_size = tile_size; tile_set->tiles[BLACK_OPAQUE] = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, tile_size, tile_size); tile_set->tiles[WHITE_OPAQUE] = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, tile_size, tile_size); black_pixel_data = gdk_pixbuf_get_pixels (tile_set->tiles[BLACK_OPAQUE]); white_pixel_data = gdk_pixbuf_get_pixels (tile_set->tiles[WHITE_OPAQUE]); row_stride = gdk_pixbuf_get_rowstride (tile_set->tiles[BLACK_OPAQUE]); g_assert (gdk_pixbuf_get_rowstride (tile_set->tiles[WHITE_OPAQUE]) == row_stride); if (key->game != GAME_REVERSI) { render_go_stones (tile_size, &go_stones_defaults, black_pixel_data, row_stride, white_pixel_data, row_stride, &tile_set->stones_x_offset, &tile_set->stones_y_offset); } else { render_reversi_disks (tile_size, &reversi_disks_defaults, black_pixel_data, row_stride, white_pixel_data, row_stride, &tile_set->stones_x_offset, &tile_set->stones_y_offset); } pixel_data = duplicate_and_adjust_alpha (3, 4, tile_size, tile_size, black_pixel_data, row_stride); tile_set->tiles[BLACK_25_TRANSPARENT] = create_pixbuf_from_pixel_data (tile_size, pixel_data, row_stride); pixel_data = duplicate_and_adjust_alpha (3, 4, tile_size, tile_size, white_pixel_data, row_stride); tile_set->tiles[WHITE_25_TRANSPARENT] = create_pixbuf_from_pixel_data (tile_size, pixel_data, row_stride); black_50_transparent_pixel_data = duplicate_and_adjust_alpha (1, 2, tile_size, tile_size, black_pixel_data, row_stride); tile_set->tiles[BLACK_50_TRANSPARENT] = create_pixbuf_from_pixel_data (tile_size, black_50_transparent_pixel_data, row_stride); white_50_transparent_pixel_data = duplicate_and_adjust_alpha (1, 2, tile_size, tile_size, white_pixel_data, row_stride); tile_set->tiles[WHITE_50_TRANSPARENT] = create_pixbuf_from_pixel_data (tile_size, white_50_transparent_pixel_data, row_stride); pixel_data = combine_pixels_diagonally (tile_size, black_50_transparent_pixel_data, white_50_transparent_pixel_data, row_stride); tile_set->tiles[MIXED_50_TRANSPARENT] = create_pixbuf_from_pixel_data (tile_size, pixel_data, row_stride); return tile_set; } static void gtk_main_tile_set_delete (GtkMainTileSet *tile_set) { int k; for (k = 0; k < NUM_TILES; k++) { if (k != TILE_NONE && k != TILE_SPECIAL) g_object_unref (tile_set->tiles[k]); } g_free (tile_set); } GtkSgfMarkupTileSet * gtk_sgf_markup_tile_set_create_or_reuse (gint tile_size, Game game) { BoardAppearance *board_appearance = game_to_board_appearance_structure (game); GtkSgfMarkupTileSetKey key; MarkupThemeListItem *theme_item = NULL; int k; if (board_appearance->markup_theme) { theme_item = markup_theme_list_find (&markup_themes, board_appearance->markup_theme); } if (!theme_item) theme_item = markup_theme_list_find (&markup_themes, "Default"); g_assert (theme_item); key.tile_size = tile_size; key.theme_directory = theme_item->directory; if (board_appearance->use_theme_defaults) { key.scale = CLAMP (theme_item->default_size, 0.2, 1.0); key.opacity = CLAMP (theme_item->default_opacity, 0.2, 1.0); /* FIXME */ if (theme_item->size_is_relative) key.scale *= 0.91; } else { key.scale = CLAMP (board_appearance->markup_size, 0.2, 1.0); key.opacity = CLAMP (board_appearance->markup_opacity, 0.2, 1.0); /* FIXME */ if (board_appearance->markup_size_is_relative) key.scale *= 0.91; } for (k = 0; k < NUM_SGF_MARKUP_BACKGROUNDS; k++) key.colors[k] = board_appearance->markup_colors[k]; /* For Go, markup can only be properly centered if it is * odd-sized. */ if (game == GAME_GO && tile_size % 2 == 0) { key.tile_size--; key.scale = MIN (1.0, (key.scale * tile_size) / (tile_size - 1)); } return ((GtkSgfMarkupTileSet *) object_cache_create_or_reuse_object (>k_sgf_markup_tile_set_cache, &key)); } static int gtk_sgf_markup_tile_set_compare_keys (const GtkSgfMarkupTileSetKey *first_key, const GtkSgfMarkupTileSetKey *second_key) { int k; if (first_key->tile_size != second_key->tile_size || strcmp (first_key->theme_directory, second_key->theme_directory) != 0 || first_key->scale != second_key->scale || first_key->opacity != second_key->opacity) return 0; for (k = 0; k < NUM_SGF_MARKUP_BACKGROUNDS; k++) { if (!QUARRY_COLORS_ARE_EQUAL (first_key->colors[k], second_key->colors[k])) return 0; } return 1; } static void * gtk_sgf_markup_tile_set_duplicate_key (const GtkSgfMarkupTileSetKey *key) { GtkSgfMarkupTileSetKey *key_copy = g_malloc (sizeof (GtkSgfMarkupTileSetKey)); int k; key_copy->tile_size = key->tile_size; key_copy->theme_directory = key->theme_directory; key_copy->scale = key->scale; for (k = 0; k < NUM_SGF_MARKUP_BACKGROUNDS; k++) key_copy->colors[k] = key->colors[k]; key_copy->opacity = key->opacity; return key_copy; } static void * gtk_sgf_markup_tile_set_create (const GtkSgfMarkupTileSetKey *key) { /* NOTE: Keep in the order defined in `sgf.h'! */ static const gchar *svg_file_base_names[NUM_ALL_SGF_MARKUPS] = { "cross", "circle", "square", "triangle", "selected", "last-move" }; GtkSgfMarkupTileSet *tile_set = g_malloc (sizeof (GtkSgfMarkupTileSet)); gint tile_size = key->tile_size; int k; tile_set->tile_size = tile_size; for (k = 0; k < NUM_ALL_SGF_MARKUPS; k++) { gchar *filename = g_strdup_printf ((PACKAGE_DATA_DIR "/markup-themes/%s/%s.svg"), key->theme_directory, svg_file_base_names[k]); FILE *file = fopen (filename, "rb"); int i; if (file && fseek (file, 0, SEEK_END) != -1) { int file_size = ftell (file); guchar *buffer = g_malloc (file_size); rewind (file); if (fread (buffer, file_size, 1, file) != 1) { /* FIXME: Too severe. */ g_assert (0); } fclose (file); for (i = 0; i < NUM_SGF_MARKUP_BACKGROUNDS; i++) { int j; for (j = 0; j < i; j++) { if (QUARRY_COLORS_ARE_EQUAL (key->colors[j], key->colors[i])) break; } if (j == i) { GdkPixbuf *tile; unsigned char *pixel_data; unsigned char *transparent_pixel_data; int row_stride; tile = scale_and_paint_svg_image (buffer, buffer + file_size, tile_size, key->scale, key->colors[i], key->opacity); tile_set->tiles[SGF_MARKUP_OPAQUE + k][i] = tile; pixel_data = gdk_pixbuf_get_pixels (tile); row_stride = gdk_pixbuf_get_rowstride (tile); transparent_pixel_data = duplicate_and_adjust_alpha (3, 4, tile_size, tile_size, pixel_data, row_stride); tile_set->tiles[SGF_MARKUP_25_TRANSPARENT + k][i] = create_pixbuf_from_pixel_data (tile_size, transparent_pixel_data, row_stride); transparent_pixel_data = duplicate_and_adjust_alpha (1, 2, tile_size, tile_size, pixel_data, row_stride); tile_set->tiles[SGF_MARKUP_50_TRANSPARENT + k][i] = create_pixbuf_from_pixel_data (tile_size, transparent_pixel_data, row_stride); } else { int shade; /* Reuse tiles and add reference. */ for (shade = SGF_MARKUP_OPAQUE; shade < NUM_ALL_SGF_MARKUP_SHADES; shade += NUM_ALL_SGF_MARKUPS) { tile_set->tiles[shade + k][i] = tile_set->tiles[shade + k][j]; g_object_ref (tile_set->tiles[shade + k][i]); } } } g_free (buffer); } else { /* GDK will print some warnings to stderr. */ for (i = 0; i < NUM_SGF_MARKUP_BACKGROUNDS; i++) { tile_set->tiles[SGF_MARKUP_OPAQUE + k][i] = NULL; tile_set->tiles[SGF_MARKUP_25_TRANSPARENT + k][i] = NULL; tile_set->tiles[SGF_MARKUP_50_TRANSPARENT + k][i] = NULL; } } g_free (filename); } return tile_set; } static void gtk_sgf_markup_tile_set_delete (GtkSgfMarkupTileSet *tile_set) { int k; int i; for (k = 0; k < NUM_ALL_SGF_MARKUP_SHADES; k++) { for (i = 0; i < NUM_SGF_MARKUP_BACKGROUNDS; i++) g_object_unref (tile_set->tiles[k][i]); } g_free (tile_set); } static GdkPixbuf * scale_and_paint_svg_image (guchar *buffer, const guchar *buffer_end, gint tile_size, gdouble scale, QuarryColor color, gdouble opacity) { GdkPixbuf *pixbuf; const guchar *written_up_to; guchar *scan; RsvgHandle *rsvg_handle = rsvg_handle_new (); char color_string[8]; char *scale_string = utils_cprintf (" scale(%.f)", scale); char *opacity_string = utils_cprintf ("%.f", opacity); sprintf (color_string, "#%02x%02x%02x", color.red, color.green, color.blue); rsvg_handle_set_size_callback (rsvg_handle, set_pixbuf_size, GINT_TO_POINTER (tile_size), NULL); for (scan = buffer, written_up_to = buffer; (scan < buffer_end && (scan = memchr (scan, '<', buffer_end - scan)) != NULL); ) { scan++; if (scan < buffer_end - 12 && memcmp (scan, "!-- [Quarry]", 12) == 0) { int scale_this_tag = 0; int blend_this_tag = 0; StringList color_properties = STATIC_STRING_LIST; scan += 12; while (1) { const guchar *keyword; while (scan < buffer_end && (*scan == ' ' || *scan == '\t' || *scan == '\n' || *scan == '\r')) scan++; keyword = scan; while (scan < buffer_end && *scan != ' ' && *scan != '\t' && *scan != '\n' && *scan != '\r' && *scan != '>') scan++; if (scan < buffer_end && *scan != '>') { if (scan - keyword == 5 && memcmp (keyword, "scale", 5) == 0) scale_this_tag = 1; else if (scan - keyword == 5 && memcmp (keyword, "blend", 5) == 0) blend_this_tag = 1; else { string_list_add_from_buffer (&color_properties, (char *) keyword, scan - keyword); } } else break; } scan = memchr (scan, '<', buffer_end - scan); while (scan < buffer_end && *scan != ' ' && *scan != '\t' && *scan != '\n' && *scan != '\r' && *scan != '>' && *scan != '/') scan++; while (1) { const guchar *property_name; while (scan < buffer_end && (*scan == ' ' || *scan == '\t' || *scan == '\n' || *scan == '\r')) scan++; property_name = scan; while (scan < buffer_end && *scan != ' ' && *scan != '\t' && *scan != '\n' && *scan != '\r' && *scan != '=' && *scan != '/' && *scan != '>') scan++; if (scan < buffer_end - 1 && *scan == '=' && *(scan + 1) == '"') { if (scale_this_tag && scan - property_name == 9 && memcmp (property_name, "transform", 9) == 0) { scan += 2; while (scan < buffer_end && *scan != '"') scan++; rsvg_handle_write (rsvg_handle, written_up_to, scan - written_up_to, NULL); written_up_to = scan; rsvg_handle_write (rsvg_handle, (guchar *) scale_string, strlen (scale_string), NULL); scale_this_tag = 0; } else if (blend_this_tag && scan - property_name == 7 && memcmp (property_name, "opacity", 7) == 0) { scan += 2; rsvg_handle_write (rsvg_handle, written_up_to, scan - written_up_to, NULL); while (scan < buffer_end && *scan != '"') scan++; written_up_to = scan; rsvg_handle_write (rsvg_handle, (guchar *) opacity_string, strlen (opacity_string), NULL); blend_this_tag = 0; } else { StringListItem *color_property; *scan = 0; color_property = string_list_find (&color_properties, (char *) property_name); *scan = '='; scan += 2; if (color_property) { string_list_delete_item (&color_properties, color_property); rsvg_handle_write (rsvg_handle, written_up_to, scan - written_up_to, NULL); rsvg_handle_write (rsvg_handle, (guchar *) color_string, 7, NULL); while (scan < buffer_end && *scan != '"') scan++; written_up_to = scan; } } while (scan < buffer_end && *scan != '"') scan++; if (scan < buffer_end) scan++; } else { if (scan < buffer_end && (*scan == '>' || *scan == '/') && (scale_this_tag || blend_this_tag)) { rsvg_handle_write (rsvg_handle, written_up_to, scan - written_up_to, NULL); written_up_to = scan; if (scale_this_tag) { char *scale_full_string = g_strdup_printf (" transform=\"%s\"", scale_string + 1); rsvg_handle_write (rsvg_handle, (guchar *) scale_full_string, strlen (scale_full_string), NULL); g_free (scale_full_string); } if (blend_this_tag) { char *opacity_full_string = g_strdup_printf (" opacity=\"%s\"", opacity_string); rsvg_handle_write (rsvg_handle, (guchar *) opacity_full_string, strlen (opacity_full_string), NULL); g_free (opacity_full_string); } } break; } } string_list_empty (&color_properties); } } rsvg_handle_write (rsvg_handle, written_up_to, buffer_end - written_up_to, NULL); rsvg_handle_close (rsvg_handle, NULL); pixbuf = rsvg_handle_get_pixbuf (rsvg_handle); rsvg_handle_free (rsvg_handle); utils_free (scale_string); utils_free (opacity_string); return pixbuf; } static void set_pixbuf_size (gint *width, gint *height, gpointer tile_size) { *width = GPOINTER_TO_INT (tile_size); *height = GPOINTER_TO_INT (tile_size); } inline static GdkPixbuf * create_pixbuf_from_pixel_data (int tile_size, unsigned char *pixel_data, int row_stride) { return gdk_pixbuf_new_from_data (pixel_data, GDK_COLORSPACE_RGB, TRUE, 8, tile_size, tile_size, row_stride, (GdkPixbufDestroyNotify) utils_free, NULL); } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/gtk-utils.c0000644000175000017500000010374310522173146015734 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "gtk-utils.h" #include "gtk-control-center.h" #include "gtk-file-dialog.h" #include "gtk-file-selector.h" #include "gtk-freezable-spin-button.h" #include "quarry-stock.h" #include "utils.h" #include #include #include typedef struct _GtkUtilsBrowseButtonData GtkUtilsBrowseButtonData; struct _GtkUtilsBrowseButtonData { GtkWidget *browsing_dialog; const gchar *browsing_dialog_caption; GtkWidget *associated_entry; gboolean is_command_line_entry; GtkUtilsBrowsingDoneCallback callback; gpointer user_data; }; typedef struct _GtkUtilsToolbarCallbackArguments GtkUtilsToolbarCallbackArguments; struct _GtkUtilsToolbarCallbackArguments { gboolean are_sensitive; va_list entries; }; static void null_pointer_on_destroy (GtkWindow *window, GtkWindow **window_pointer); static void null_pointer_on_destroy_ask_control_center (GtkWindow *window, GtkWindow **window_pointer); static void browse_button_clicked (GtkWidget *button, GtkUtilsBrowseButtonData *data); static void browsing_dialog_response (GtkWidget *file_dialog, gint response_id, GtkUtilsBrowseButtonData *data); static void advance_focus (GtkWidget *widget); static gboolean time_spin_button_output (GtkSpinButton *spin_button); static gint time_spin_button_input (GtkSpinButton *spin_button, gdouble *new_value); static void block_key_signal (GtkWidget *widget, GdkEventKey *event, gpointer signal_id); static void do_align_left_widgets (GtkWidget *first_level_child, GtkSizeGroup *size_group); static void do_align_left_widget (GtkWidget *widget, GtkSizeGroup **size_group); static void invoke_toolbar_button_callback (GObject *button, gpointer user_data); static void set_toolbar_item_sensitive (GtkWidget *button, const GtkUtilsToolbarCallbackArguments *arguments); static void set_widget_sensitivity_on_toggle (GtkToggleButton *toggle_button, GtkWidget *widget); static void set_widget_sensitivity_on_toggle_reversed (GtkToggleButton *toggle_button, GtkWidget *widget); static void set_widget_sensitivity_on_input (GtkEntry *entry, GtkWidget *widget); static gint freeze_on_empty_input (GtkFreezableSpinButton *freezable_spin_button, gdouble *new_value); static GQuark toolbar_button_entry_quark = 0; void gtk_utils_add_similar_bindings (GtkBindingSet *binding_set, const gchar *signal_name, GtkUtilsBindingInfo *bindings, int num_bindings) { int k; g_return_if_fail (binding_set); g_return_if_fail (signal_name); g_return_if_fail (bindings); g_return_if_fail (num_bindings > 0); for (k = 0; k < num_bindings; k++) { gtk_binding_entry_add_signal (binding_set, bindings[k].keyval, bindings[k].modifiers, signal_name, 1, G_TYPE_INT, bindings[k].signal_parameter); } } #if GTK_2_2_OR_LATER void gtk_utils_make_window_only_horizontally_resizable (GtkWindow *window) { GdkGeometry geometry; g_return_if_fail (GTK_IS_WINDOW (window)); geometry.max_width = G_MAXINT; geometry.max_height = -1; gtk_window_set_geometry_hints (window, NULL, &geometry, GDK_HINT_MAX_SIZE); } #endif void gtk_utils_standardize_dialog (GtkDialog *dialog, GtkWidget *contents) { g_return_if_fail (GTK_IS_DIALOG (dialog)); g_return_if_fail (GTK_IS_CONTAINER (contents)); gtk_widget_set_name (GTK_WIDGET (dialog), "quarry-dialog"); gtk_box_set_spacing (GTK_BOX (dialog->vbox), QUARRY_SPACING); gtk_box_pack_start_defaults (GTK_BOX (dialog->vbox), contents); } GtkWidget* gtk_utils_add_help_button (GtkDialog* dialog) { GtkAccelGroup* accel_group = gtk_accel_group_new (); GtkWidget* help_button = gtk_dialog_add_button (dialog, GTK_STOCK_HELP, GTK_RESPONSE_HELP); gtk_widget_add_accelerator (help_button, "clicked", accel_group, GDK_F1, 0, 0); gtk_window_add_accel_group (GTK_WINDOW (dialog), accel_group); return help_button; } void gtk_utils_show_and_forget_dialog (GtkDialog *dialog) { g_return_if_fail (GTK_IS_DIALOG (dialog)); g_signal_connect (dialog, "response", G_CALLBACK (gtk_widget_destroy), NULL); gtk_window_present (GTK_WINDOW (dialog)); } void gtk_utils_null_pointer_on_destroy (GtkWindow **window_pointer, gboolean ask_control_center) { g_return_if_fail (window_pointer && GTK_IS_WINDOW (*window_pointer)); g_signal_connect (*window_pointer, "destroy", G_CALLBACK (ask_control_center ? null_pointer_on_destroy_ask_control_center : null_pointer_on_destroy), window_pointer); } static void null_pointer_on_destroy (GtkWindow *window, GtkWindow **window_pointer) { g_return_if_fail (window == *window_pointer); *window_pointer = NULL; } static void null_pointer_on_destroy_ask_control_center (GtkWindow *window, GtkWindow **window_pointer) { g_return_if_fail (window == *window_pointer); if (gtk_control_center_window_destroyed (window)) *window_pointer = NULL; } #if !GTK_2_2_OR_LATER #undef gtk_dialog_set_default_response /* Workaround GTK+ 2.0 focus slipping problem. */ void gtk_utils_workaround_set_default_response (GtkDialog *dialog, gint response_id) { GtkWidget *focused_widget = gtk_window_get_focus (GTK_WINDOW (dialog)); gtk_dialog_set_default_response (dialog, response_id); /* Can't use gtk_widget_grab_focus() since `focused_widget' can be * NULL. */ gtk_window_set_focus (GTK_WINDOW (dialog), focused_widget); } #define gtk_dialog_set_default_response(dialog, response_id) \ gtk_utils_workaround_set_default_response (dialog, response_id) #endif /* not GTK_2_2_OR_LATER */ /* GTK+ has an annoying "feature" (I tend to consider it a bug): if * you activate a button from keyboard (i.e. Alt+O for "OK" button), * then keyboard changes in the currently focused spin button are not * saved. This might be true for some other widgets too. * * Every dialog with spin buttons should call this function from all * button/response handlers. */ void gtk_utils_workaround_focus_bug (GtkWindow *window) { GtkWidget *focused_widget = gtk_window_get_focus (window); if (focused_widget) { if (GTK_IS_SPIN_BUTTON (focused_widget)) gtk_spin_button_update (GTK_SPIN_BUTTON (focused_widget)); } } #if !GTK_2_4_OR_LATER gboolean g_signal_accumulator_true_handled (GSignalInvocationHint *hint, GValue *return_accumulator, const GValue *handler_return, gpointer user_data) { gboolean signal_handled; UNUSED (hint); UNUSED (user_data); signal_handled = g_value_get_boolean (handler_return); g_value_set_boolean (return_accumulator, signal_handled); return !signal_handled; } #endif /* not GTK_2_4_OR_LATER */ GtkWidget * gtk_utils_create_titled_page (GtkWidget *contents, const gchar *icon_stock_id, const gchar *title) { GtkWidget *image = NULL; GtkWidget *label = NULL; GtkWidget *title_widget; GtkWidget *hseparator; g_return_val_if_fail (GTK_IS_WIDGET (contents), NULL); g_return_val_if_fail (icon_stock_id || title, NULL); if (icon_stock_id) { image = gtk_image_new_from_stock (icon_stock_id, GTK_ICON_SIZE_LARGE_TOOLBAR); } if (title) { gchar *title_escaped = g_markup_escape_text (title, -1); char *marked_up_title = utils_cat_strings (NULL, "", title_escaped, "", NULL); g_free (title_escaped); label = gtk_label_new (NULL); gtk_label_set_markup (GTK_LABEL (label), marked_up_title); utils_free (marked_up_title); } if (image && label) { title_widget = gtk_utils_pack_in_box (GTK_TYPE_HBOX, QUARRY_SPACING_SMALL, image, GTK_UTILS_FILL, label, 0, NULL); } else if (label) { gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); title_widget = label; } else title_widget = image; gtk_widget_show_all (title_widget); hseparator = gtk_hseparator_new (); gtk_widget_show (hseparator); return gtk_utils_pack_in_box (GTK_TYPE_VBOX, QUARRY_SPACING_SMALL, title_widget, GTK_UTILS_FILL, hseparator, GTK_UTILS_FILL, contents, GTK_UTILS_PACK_DEFAULT, NULL); } GtkWidget * gtk_utils_pack_in_box (GType box_type, gint spacing, ...) { void (* packing_function) (GtkBox *box, GtkWidget *widget, gboolean expand, gboolean fill, guint padding) = gtk_box_pack_start; GtkBox *box = GTK_BOX (g_object_new (box_type, NULL)); GtkWidget *widget; va_list arguments; gtk_box_set_spacing (box, spacing); va_start (arguments, spacing); while ((widget = va_arg (arguments, GtkWidget *)) != NULL) { guint packing_parameters = va_arg (arguments, guint); if (GTK_IS_WIDGET (widget)) { if (packing_parameters & GTK_UTILS_PACK_END) packing_function = gtk_box_pack_end; packing_function (box, widget, packing_parameters & GTK_UTILS_EXPAND ? TRUE : FALSE, packing_parameters & GTK_UTILS_FILL ? TRUE : FALSE, packing_parameters & GTK_UTILS_PACK_PADDING_MASK); } else { g_critical ("argument of type %s is not a widget", G_OBJECT_TYPE_NAME (widget)); } } return GTK_WIDGET (box); } GtkWidget * gtk_utils_pack_array_in_box (GType box_type, gint spacing, GtkWidget **widgets, gint num_widgets, guint packing_parameters) { int k; GtkBox *box = GTK_BOX (g_object_new (box_type, NULL)); gtk_box_set_spacing (box, spacing); for (k = 0; k < num_widgets; k++) { gtk_box_pack_start (box, widgets[k], packing_parameters & GTK_UTILS_EXPAND ? TRUE : FALSE, packing_parameters & GTK_UTILS_FILL ? TRUE : FALSE, packing_parameters & GTK_UTILS_PACK_PADDING_MASK); } return GTK_WIDGET (box); } GtkWidget * gtk_utils_align_widget (GtkWidget *widget, gfloat x_alignment, gfloat y_alignment) { GtkWidget *alignment = gtk_alignment_new (x_alignment, y_alignment, 0.0, 0.0); gtk_container_add (GTK_CONTAINER (alignment), widget); return alignment; } GtkWidget * gtk_utils_sink_widget (GtkWidget *widget) { GtkWidget *frame = gtk_frame_new (NULL); gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN); gtk_container_add (GTK_CONTAINER (frame), widget); return frame; } GtkWidget * gtk_utils_make_widget_scrollable (GtkWidget *widget, GtkPolicyType hscrollbar_policy, GtkPolicyType vscrollbar_policy) { GtkWidget *scrolled_window = gtk_scrolled_window_new (NULL, NULL); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), hscrollbar_policy, vscrollbar_policy); gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window), GTK_SHADOW_IN); gtk_container_add (GTK_CONTAINER (scrolled_window), widget); gtk_widget_show_all (scrolled_window); return scrolled_window; } GtkWidget * gtk_utils_create_left_aligned_label (const gchar *label_text) { GtkWidget *label = gtk_label_new (label_text); gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); return label; } GtkWidget * gtk_utils_create_mnemonic_label (const gchar *label_text, GtkWidget *mnemonic_widget) { GtkWidget *label = gtk_label_new_with_mnemonic (label_text); gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); gtk_label_set_mnemonic_widget (GTK_LABEL (label), mnemonic_widget); return label; } GtkWidget * gtk_utils_create_entry (const gchar *text, GtkUtilsEntryActivationMode mode) { GtkWidget *entry = gtk_entry_new (); if (text) gtk_entry_set_text (GTK_ENTRY (entry), text); switch (mode) { case RETURN_ACTIVATES_DEFAULT: gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE); break; case RETURN_ADVANCES_FOCUS: g_signal_connect (entry, "activate", G_CALLBACK (advance_focus), NULL); break; case RETURN_DEFAULT_MODE: /* It's the default mode, do nothing. */ break; } return entry; } static void advance_focus (GtkWidget *widget) { do widget = gtk_widget_get_parent (widget); while (widget && !GTK_IS_WINDOW (widget)); if (widget) g_signal_emit_by_name (widget, "move-focus", GTK_DIR_TAB_FORWARD); } GtkWidget * gtk_utils_create_browse_button (gboolean with_text, GtkWidget *associated_entry, gboolean is_command_line_entry, const gchar *browsing_dialog_caption, GtkUtilsBrowsingDoneCallback callback, gpointer user_data) { GtkWidget *button; GtkUtilsBrowseButtonData *data; g_return_val_if_fail (browsing_dialog_caption, NULL); #ifdef GTK_TYPE_FILE_SELECTOR g_return_val_if_fail (GTK_IS_ENTRY (associated_entry) || GTK_IS_FILE_SELECTOR (associated_entry), NULL); #else g_return_val_if_fail (GTK_IS_ENTRY (associated_entry), NULL); #endif data = g_malloc (sizeof (GtkUtilsBrowseButtonData)); if (with_text) button = gtk_button_new_from_stock (QUARRY_STOCK_BROWSE); else { button = gtk_button_new (); gtk_container_add (GTK_CONTAINER (button), gtk_image_new_from_stock (QUARRY_STOCK_BROWSE, GTK_ICON_SIZE_BUTTON)); } data->browsing_dialog = NULL; data->browsing_dialog_caption = browsing_dialog_caption; data->associated_entry = associated_entry; data->is_command_line_entry = is_command_line_entry; data->callback = callback; data->user_data = user_data; g_signal_connect (button, "clicked", G_CALLBACK (browse_button_clicked), data); g_signal_connect_swapped (button, "destroy", G_CALLBACK (g_free), data); return button; } static void browse_button_clicked (GtkWidget *button, GtkUtilsBrowseButtonData *data) { if (!data->browsing_dialog) { GtkEntry *entry = GTK_ENTRY (GTK_IS_ENTRY (data->associated_entry) ? data->associated_entry : GTK_BIN (data->associated_entry)->child); const gchar *current_entry_text = gtk_entry_get_text (entry); data->browsing_dialog = gtk_file_dialog_new (data->browsing_dialog_caption, GTK_WINDOW (gtk_widget_get_toplevel (button)), TRUE, GTK_STOCK_OPEN); g_signal_connect (data->browsing_dialog, "response", G_CALLBACK (browsing_dialog_response), data); if (*current_entry_text) { if (data->is_command_line_entry) { gchar **argv; if (g_shell_parse_argv (current_entry_text, NULL, &argv, NULL)) { gtk_file_dialog_set_filename (data->browsing_dialog, argv[0]); g_strfreev (argv); } } else { gtk_file_dialog_set_filename (data->browsing_dialog, current_entry_text); } } } gtk_window_present (GTK_WINDOW (data->browsing_dialog)); } static void browsing_dialog_response (GtkWidget *file_dialog, gint response_id, GtkUtilsBrowseButtonData *data) { if (response_id == GTK_RESPONSE_OK) { GtkEntry *entry; const gchar *filename = gtk_file_dialog_get_filename (file_dialog); gchar *filename_in_utf8 = g_filename_to_utf8 (filename, -1, NULL, NULL, NULL); if (GTK_IS_ENTRY (data->associated_entry)) { entry = GTK_ENTRY (data->associated_entry); gtk_entry_set_text (entry, filename_in_utf8); } #ifdef GTK_TYPE_FILE_SELECTOR else if (GTK_IS_FILE_SELECTOR (data->associated_entry)) { entry = GTK_ENTRY (GTK_BIN (data->associated_entry)->child); gtk_file_selector_set_text (GTK_FILE_SELECTOR (data->associated_entry), filename_in_utf8); } #endif /* defined GTK_TYPE_FILE_SELECTOR */ else { g_critical ("unhandled entry type %s", G_OBJECT_TYPE_NAME (data->associated_entry)); return; } gtk_widget_grab_focus (data->associated_entry); g_free (filename_in_utf8); if (data->callback) data->callback (entry, NULL, data->user_data); } gtk_widget_destroy (file_dialog); data->browsing_dialog = NULL; } GtkWidget * gtk_utils_create_spin_button (GtkAdjustment *adjustment, gdouble climb_rate, guint num_digits, gboolean snap_to_ticks) { GtkWidget *spin_button = gtk_spin_button_new (adjustment, climb_rate, num_digits); gtk_spin_button_set_snap_to_ticks (GTK_SPIN_BUTTON (spin_button), snap_to_ticks); gtk_entry_set_alignment (GTK_ENTRY (spin_button), 1.0); gtk_entry_set_activates_default (GTK_ENTRY (spin_button), TRUE); return spin_button; } GtkWidget * gtk_utils_create_freezable_spin_button (GtkAdjustment *adjustment, gdouble climb_rate, guint num_digits, gboolean snap_to_ticks) { GtkWidget *spin_button = gtk_freezable_spin_button_new (adjustment, climb_rate, num_digits); gtk_spin_button_set_snap_to_ticks (GTK_SPIN_BUTTON (spin_button), snap_to_ticks); gtk_entry_set_alignment (GTK_ENTRY (spin_button), 1.0); gtk_entry_set_activates_default (GTK_ENTRY (spin_button), TRUE); return spin_button; } void gtk_utils_convert_to_time_spin_button (GtkSpinButton *spin_button) { GtkAdjustment *adjustment = gtk_spin_button_get_adjustment (spin_button); gdouble upper_limit; gint max_width; g_return_if_fail (adjustment); g_signal_connect (spin_button, "output", G_CALLBACK (time_spin_button_output), NULL); g_signal_connect (spin_button, "input", G_CALLBACK (time_spin_button_input), NULL); if (adjustment->upper > 60.0 * 60.0) { /* One less, since two colons would normally take space of only * one "common" char. Anyway Quarry time upper bounds are not * something one would use. */ for (max_width = 6, upper_limit = adjustment->upper / (60.0 * 60.0); upper_limit >= 10.0; upper_limit /= 10.0) max_width++; } else max_width = 5; gtk_entry_set_width_chars (GTK_ENTRY (spin_button), max_width); } GtkWidget * gtk_utils_create_time_spin_button (GtkAdjustment *adjustment, gdouble climb_rate) { GtkWidget *spin_button = gtk_utils_create_spin_button (adjustment, climb_rate, 0, FALSE); gtk_utils_convert_to_time_spin_button (GTK_SPIN_BUTTON (spin_button)); return spin_button; } static gboolean time_spin_button_output (GtkSpinButton *spin_button) { gint value = gtk_spin_button_get_adjustment (spin_button)->value; char buffer[32]; /* Don't print zero hours. In Quarry context hours are probably * used only occasionally. */ if (value >= 60 * 60) { utils_ncprintf (buffer, sizeof buffer, "%d:%02d:%02d", value / (60 * 60), (value / 60) % 60, value % 60); } else { utils_ncprintf (buffer, sizeof buffer, "%02d:%02d", value / 60, value % 60); } gtk_entry_set_text (GTK_ENTRY (spin_button), buffer); return TRUE; } static gint time_spin_button_input (GtkSpinButton *spin_button, gdouble *new_value) { int seconds = utils_parse_time (gtk_entry_get_text (GTK_ENTRY (spin_button))); if (seconds >= 0) { *new_value = (gdouble) seconds; return TRUE; } return GTK_INPUT_ERROR; } GtkWidget * gtk_utils_create_selector (const gchar **items, gint num_items, gint selected_item) { GtkWidget *widget; int k; g_return_val_if_fail (items, NULL); g_return_val_if_fail (num_items > 0, NULL); #if GTK_2_4_OR_LATER widget = gtk_combo_box_new_text (); { GtkComboBox *combo_box = GTK_COMBO_BOX (widget); for (k = 0; k < num_items; k++) gtk_combo_box_append_text (combo_box, _(items[k])); gtk_combo_box_set_active (combo_box, (0 <= selected_item && selected_item < num_items ? selected_item : 0)); } #else /* not GTK_2_4_OR_LATER */ widget = gtk_option_menu_new (); { GtkWidget *menu = gtk_menu_new (); GtkMenuShell *menu_shell = GTK_MENU_SHELL (menu); for (k = 0; k < num_items; k++) { gtk_menu_shell_append (menu_shell, gtk_menu_item_new_with_label (_(items[k]))); } gtk_widget_show_all (menu); gtk_option_menu_set_menu (GTK_OPTION_MENU (widget), menu); } if (0 <= selected_item && selected_item < num_items) gtk_option_menu_set_history (GTK_OPTION_MENU (widget), selected_item); #endif /* not GTK_2_4_OR_LATER */ return widget; } GtkWidget * gtk_utils_create_selector_from_string_list (void *abstract_list, const gchar *selected_item) { GtkWidget *widget; StringList *string_list = (StringList *) abstract_list; StringListItem *list_item; int k; g_return_val_if_fail (string_list, NULL); g_return_val_if_fail (string_list->first, NULL); #if GTK_2_4_OR_LATER widget = gtk_combo_box_new_text (); { GtkComboBox *combo_box = GTK_COMBO_BOX (widget); for (list_item = string_list->first, k = 0; list_item; list_item = list_item->next, k++) { gtk_combo_box_append_text (combo_box, list_item->text); if (selected_item && strcmp (list_item->text, selected_item) == 0) { gtk_combo_box_set_active (combo_box, k); selected_item = NULL; } } } #else /* not GTK_2_4_OR_LATER */ widget = gtk_option_menu_new (); { GtkWidget *menu = gtk_menu_new (); GtkMenuShell *menu_shell = GTK_MENU_SHELL (menu); int selected_item_index = -1; for (list_item = string_list->first, k = 0; list_item; list_item = list_item->next, k++) { gtk_menu_shell_append (menu_shell, gtk_menu_item_new_with_label (list_item->text)); if (selected_item && strcmp (list_item->text, selected_item) == 0) { selected_item_index = k; selected_item = NULL; } } gtk_widget_show_all (menu); gtk_option_menu_set_menu (GTK_OPTION_MENU (widget), menu); if (selected_item_index != -1) { gtk_option_menu_set_history (GTK_OPTION_MENU (widget), selected_item_index); } } #endif /* not GTK_2_4_OR_LATER */ return widget; } GtkWidget * gtk_utils_create_invisible_notebook (void) { GtkWidget *notebook = gtk_notebook_new (); gtk_notebook_set_show_tabs (GTK_NOTEBOOK (notebook), FALSE); gtk_notebook_set_show_border (GTK_NOTEBOOK (notebook), FALSE); g_signal_connect (notebook, "key-press-event", G_CALLBACK (block_key_signal), GINT_TO_POINTER (g_signal_lookup ("key-press-event", GTK_TYPE_WIDGET))); g_signal_connect (notebook, "key-release-event", G_CALLBACK (block_key_signal), GINT_TO_POINTER (g_signal_lookup ("key-release-event", GTK_TYPE_WIDGET))); return notebook; } static void block_key_signal (GtkWidget *widget, GdkEventKey *event, gpointer signal_id) { UNUSED (event); g_signal_stop_emission (widget, GPOINTER_TO_INT (signal_id), 0); } void gtk_utils_create_radio_chain (GtkWidget **radio_buttons, const gchar **label_texts, gint num_radio_buttons) { GtkRadioButton *last_button = NULL; int k; g_return_if_fail (radio_buttons); g_return_if_fail (label_texts); for (k = 0; k < num_radio_buttons; k++) { radio_buttons[k] = gtk_radio_button_new_with_mnemonic_from_widget (last_button, _(label_texts[k])); last_button = GTK_RADIO_BUTTON (radio_buttons[k]); } } GtkSizeGroup * gtk_utils_create_size_group (GtkSizeGroupMode mode, ...) { GtkSizeGroup *size_group = gtk_size_group_new (mode); GtkWidget *widget; va_list arguments; va_start (arguments, mode); while ((widget = va_arg (arguments, GtkWidget *)) != NULL) gtk_size_group_add_widget (size_group, widget); va_end (arguments); g_object_unref (size_group); return size_group; } GtkSizeGroup * gtk_utils_align_left_widgets (GtkContainer *container, GtkSizeGroup *size_group) { g_return_val_if_fail (GTK_IS_CONTAINER (container), NULL); g_return_val_if_fail (!size_group || GTK_IS_SIZE_GROUP (size_group), NULL); if (!size_group) size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); gtk_container_foreach (container, (GtkCallback) do_align_left_widgets, size_group); return size_group; } static void do_align_left_widgets (GtkWidget *first_level_child, GtkSizeGroup *size_group) { if (GTK_IS_HBOX (first_level_child) || GTK_IS_HBUTTON_BOX (first_level_child)) { GtkSizeGroup *size_group_copy = size_group; gtk_container_foreach (GTK_CONTAINER (first_level_child), (GtkCallback) do_align_left_widget, &size_group_copy); } else if (GTK_IS_CONTAINER (first_level_child)) { gtk_container_foreach (GTK_CONTAINER (first_level_child), (GtkCallback) do_align_left_widgets, size_group); } } static void do_align_left_widget (GtkWidget *widget, GtkSizeGroup **size_group) { if (*size_group) { if (!GTK_IS_BOX (widget)) { gtk_size_group_add_widget (*size_group, widget); *size_group = NULL; } else do_align_left_widgets (widget, *size_group); } } GtkWidget * gtk_utils_append_toolbar_button (GtkToolbar *toolbar, GtkUtilsToolbarEntry *entry, GtkUtilsToolbarButtonFlags flags, gpointer user_data) { #if GTK_2_4_OR_LATER GtkToolItem *button; g_return_val_if_fail (entry, NULL); button = gtk_tool_button_new ((gtk_image_new_from_stock (entry->icon_stock_id, gtk_toolbar_get_icon_size (toolbar))), (entry->label_text ? _(entry->label_text) : NULL)); if (entry->tooltip_text) { gtk_tool_item_set_tooltip (button, toolbar->tooltips, _(entry->tooltip_text), NULL); } gtk_tool_item_set_homogeneous (button, ((flags & GTK_UTILS_HOMOGENEOUS) ? TRUE : FALSE)); gtk_tool_item_set_is_important (button, ((flags & GTK_UTILS_IS_IMPORTANT) ? TRUE : FALSE)); g_signal_connect (button, "clicked", G_CALLBACK (invoke_toolbar_button_callback), user_data); gtk_toolbar_insert (toolbar, button, -1); #else GtkWidget *button; g_return_val_if_fail (entry, NULL); UNUSED (flags); button = (gtk_toolbar_append_item (toolbar, (entry->label_text ? _(entry->label_text) : NULL), _(entry->tooltip_text), NULL, gtk_image_new_from_stock (entry->icon_stock_id, gtk_toolbar_get_icon_size (toolbar)), (GtkSignalFunc) invoke_toolbar_button_callback, user_data)); #endif if (!toolbar_button_entry_quark) { toolbar_button_entry_quark = g_quark_from_static_string ("quarry-toolbar-button-entry"); } g_object_set_qdata (G_OBJECT (button), toolbar_button_entry_quark, entry); /* For GTK+ 2.4 and up. It is certainly a widget. */ return (GtkWidget *) button; } static void invoke_toolbar_button_callback (GObject *button, gpointer user_data) { const GtkUtilsToolbarEntry *entry = g_object_get_qdata (button, toolbar_button_entry_quark); entry->callback (user_data, entry->callback_action); } void gtk_utils_set_toolbar_buttons_sensitive (GtkToolbar *toolbar, gboolean are_sensitive, ...) { GtkUtilsToolbarCallbackArguments callback_arguments; g_return_if_fail (GTK_IS_TOOLBAR (toolbar)); g_return_if_fail (toolbar_button_entry_quark); callback_arguments.are_sensitive = are_sensitive; va_start (callback_arguments.entries, are_sensitive); gtk_container_foreach (GTK_CONTAINER (toolbar), (GtkCallback) set_toolbar_item_sensitive, &callback_arguments); va_end (callback_arguments.entries); } static void set_toolbar_item_sensitive (GtkWidget *button, const GtkUtilsToolbarCallbackArguments *arguments) { const GtkUtilsToolbarEntry *button_entry = g_object_get_qdata (G_OBJECT (button), toolbar_button_entry_quark); if (button_entry) { va_list entries_copy; const GtkUtilsToolbarEntry *entry; QUARRY_VA_COPY (entries_copy, arguments->entries); while ((entry = va_arg (entries_copy, const GtkUtilsToolbarEntry *)) != NULL) { if (entry == button_entry) { gtk_widget_set_sensitive (button, arguments->are_sensitive); break; } } va_end (entries_copy); } } /* Set `text_buffer's text. This is a convenient function. If `text' * doesn't end in a newline, it silently appends one, to ease editing. * If `text' is NULL, then it sets text buffer's text to be empty * string. Finally, it resets text buffer's `modified' flag. */ void gtk_utils_set_text_buffer_text (GtkTextBuffer *text_buffer, const gchar *text) { g_return_if_fail (GTK_IS_TEXT_BUFFER (text_buffer)); if (text && *text) { gint length = strlen (text); GtkTextIter start_iterator; gtk_text_buffer_set_text (text_buffer, text, length); gtk_text_buffer_get_start_iter (text_buffer, &start_iterator); gtk_text_buffer_place_cursor (text_buffer, &start_iterator); if (text[length - 1] != '\n') { GtkTextIter end_iterator; gtk_text_buffer_get_end_iter (text_buffer, &end_iterator); gtk_text_buffer_insert (text_buffer, &end_iterator, "\n", 1); } } else gtk_text_buffer_set_text (text_buffer, "", 0); } #if !GTK_2_4_OR_LATER /* It is recommended to use this function with 2.4 and up. For * earlier versions, we define it ourselves. */ void gtk_text_buffer_select_range (GtkTextBuffer *text_buffer, GtkTextIter *insertion_iterator, GtkTextIter *bound_iterator) { gtk_text_buffer_move_mark (text_buffer, gtk_text_buffer_get_insert (text_buffer), insertion_iterator); gtk_text_buffer_move_mark (text_buffer, gtk_text_buffer_get_selection_bound (text_buffer), bound_iterator); } #endif /* not GTK_2_4_OR_LATER */ gint gtk_utils_get_selected_radio_index (GSList *radio_button_group) { int k; int length = g_slist_length (radio_button_group); for (k = 0; radio_button_group; k++, radio_button_group = radio_button_group->next) { gpointer *radio_button = radio_button_group->data; if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (radio_button))) return (length - 1) - k; } return -1; } void gtk_utils_set_sensitive_on_toggle (GtkToggleButton *toggle_button, GtkWidget *widget, gboolean reverse_meaning) { void (* set_widget_sensitivity_function) (GtkToggleButton *toggle_button, GtkWidget *widget) = (reverse_meaning ? set_widget_sensitivity_on_toggle_reversed : set_widget_sensitivity_on_toggle); g_return_if_fail (GTK_IS_TOGGLE_BUTTON (toggle_button)); g_return_if_fail (GTK_IS_WIDGET (widget)); set_widget_sensitivity_function (toggle_button, widget); g_signal_connect (toggle_button, "toggled", G_CALLBACK (set_widget_sensitivity_function), widget); } static void set_widget_sensitivity_on_toggle (GtkToggleButton *toggle_button, GtkWidget *widget) { gtk_widget_set_sensitive (widget, gtk_toggle_button_get_active (toggle_button)); } static void set_widget_sensitivity_on_toggle_reversed (GtkToggleButton *toggle_button, GtkWidget *widget) { gtk_widget_set_sensitive (widget, !gtk_toggle_button_get_active (toggle_button)); } void gtk_utils_set_sensitive_on_input (GtkEntry *entry, GtkWidget *widget) { g_return_if_fail (GTK_IS_ENTRY (entry)); g_return_if_fail (GTK_IS_WIDGET (widget)); set_widget_sensitivity_on_input (entry, widget); g_signal_connect (entry, "changed", G_CALLBACK (set_widget_sensitivity_on_input), widget); } static void set_widget_sensitivity_on_input (GtkEntry *entry, GtkWidget *widget) { const gchar *text = gtk_entry_get_text (entry); gtk_widget_set_sensitive (widget, *text ? TRUE : FALSE); } void gtk_utils_freeze_on_empty_input (GtkFreezableSpinButton *freezable_spin_button) { g_return_if_fail (GTK_IS_FREEZABLE_SPIN_BUTTON (freezable_spin_button)); g_signal_connect (freezable_spin_button, "input", G_CALLBACK (freeze_on_empty_input), NULL); } static gint freeze_on_empty_input (GtkFreezableSpinButton *freezable_spin_button, gdouble *new_value) { const gchar *entry_text = gtk_entry_get_text (GTK_ENTRY (freezable_spin_button)); while (*entry_text == ' ' || *entry_text == '\t' || *entry_text == '\n' || *entry_text == '\r' || *entry_text == '\v' || *entry_text == '\f') entry_text++; if (*entry_text) return FALSE; *new_value = 0.0; gtk_freezable_spin_button_freeze_and_stop_input (freezable_spin_button, ""); return TRUE; } void gtk_utils_set_widgets_visible (gboolean visible, ...) { GtkWidget *widget; va_list arguments; va_start (arguments, visible); while ((widget = va_arg (arguments, GtkWidget *)) != NULL) { if (visible && !GTK_WIDGET_VISIBLE (widget)) gtk_widget_show (widget); else if (!visible && GTK_WIDGET_VISIBLE (widget)) gtk_widget_hide (widget); } va_end (arguments); } void gtk_utils_set_menu_items_sensitive (GtkItemFactory *item_factory, gboolean are_sensitive, ...) { va_list arguments; const gchar *path; g_return_if_fail (GTK_IS_ITEM_FACTORY (item_factory)); va_start (arguments, are_sensitive); while ((path = va_arg (arguments, const gchar *)) != NULL) { gtk_widget_set_sensitive (gtk_item_factory_get_widget (item_factory, path), are_sensitive); } va_end (arguments); } void gtk_utils_set_gdk_color (GdkColor *gdk_color, QuarryColor quarry_color) { g_return_if_fail (gdk_color); gdk_color->red = (quarry_color.red * G_MAXUINT16) / G_MAXUINT8; gdk_color->green = (quarry_color.green * G_MAXUINT16) / G_MAXUINT8; gdk_color->blue = (quarry_color.blue * G_MAXUINT16) / G_MAXUINT8; } void gtk_utils_set_quarry_color (QuarryColor *quarry_color, const GdkColor *gdk_color) { g_return_if_fail (quarry_color); g_return_if_fail (gdk_color); quarry_color->red = (gdk_color->red * G_MAXUINT8) / G_MAXUINT16; quarry_color->green = (gdk_color->green * G_MAXUINT8) / G_MAXUINT16; quarry_color->blue = (gdk_color->blue * G_MAXUINT8) / G_MAXUINT16; } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/gui-back-end.c0000644000175000017500000001756710513274707016254 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "gtk-configuration.h" #include "gtk-control-center.h" #include "gtk-parser-interface.h" #include "gtk-preferences.h" #include "gtk-thread-interface.h" #include "gtk-tile-set.h" #include "gtk-utils.h" #include "gui-back-end.h" #include "quarry-stock.h" #include "configuration.h" #include "time-control.h" #include "utils.h" #include #include #include #include static void initialize_main_loop (void); static void run_main_loop (void); static gboolean run_cleanup_tasks (gpointer data); const char *user_real_name; static gchar *configuration_file; static GPtrArray *objects_to_finalize = NULL; static GPtrArray *pointers_to_free = NULL; int gui_back_end_init (int *argc, char **argv[]) { #if THREADS_SUPPORTED /* gdk_threads_init() is not called because only one (main) thread * deals with GUI. */ g_thread_init (NULL); #endif gtk_rc_add_default_file (PACKAGE_DATA_DIR "/gtkrc"); return gtk_init_check (argc, argv); } int gui_back_end_main_default (void) { initialize_main_loop (); gtk_control_center_present (); run_main_loop (); return 0; } int gui_back_end_main_open_files (int num_files, char **filenames) { int k; initialize_main_loop (); for (k = 0; k < num_files; k++) gtk_parse_sgf_file (filenames[k], NULL, NULL); run_main_loop (); return 0; } void gui_back_end_register_object_to_finalize (void *object) { g_return_if_fail (G_IS_OBJECT (object)); if (!objects_to_finalize) objects_to_finalize = g_ptr_array_new (); g_ptr_array_add (objects_to_finalize, object); } void gui_back_end_register_pointer_to_free (void *pointer) { if (pointer) { if (!pointers_to_free) pointers_to_free = g_ptr_array_new (); g_ptr_array_add (pointers_to_free, pointer); } } void * gui_back_end_timer_restart (void *timer_object) { if (timer_object) { g_timer_start ((GTimer *) timer_object); return timer_object; } return g_timer_new (); } void gui_back_end_timer_delete (void *timer_object) { g_timer_destroy ((GTimer *) timer_object); } double gui_back_end_timer_get_seconds_elapsed (void *timer_object) { return g_timer_elapsed ((GTimer *) timer_object, NULL); } #if THREADS_SUPPORTED static gboolean thread_event_callback (gpointer data); static gboolean thread_events_prepare (GSource *source, gint *timeout); static gboolean thread_events_check (GSource *source); static gboolean thread_events_dispatch (GSource *source, GSourceFunc callback, gpointer user_data); static GSourceFuncs thread_events_functions = { thread_events_prepare, thread_events_check, thread_events_dispatch, NULL, }; static GSource *thread_events; GAsyncQueue *thread_events_queue; static gboolean thread_event_callback (gpointer data) { ThreadEventData *thread_completion_data = (ThreadEventData *) data; thread_completion_data->callback (thread_completion_data->result); return TRUE; } static gboolean thread_events_prepare (GSource *source, gint *timeout) { UNUSED (source); *timeout = -1; return g_async_queue_length (thread_events_queue) > 0; } static gboolean thread_events_check (GSource *source) { UNUSED (source); return g_async_queue_length (thread_events_queue) > 0; } static gboolean thread_events_dispatch (GSource *source, GSourceFunc callback, gpointer user_data) { gpointer data = g_async_queue_pop (thread_events_queue); gboolean result = callback (data); UNUSED (source); UNUSED (user_data); g_free (data); return result; } #endif /* THREADS_SUPPORTED */ static void initialize_main_loop (void) { GtpEngineList site_configuration_engines; #if THREADS_SUPPORTED thread_events_queue = g_async_queue_new (); thread_events = g_source_new (&thread_events_functions, sizeof (GSource)); g_source_set_callback (thread_events, thread_event_callback, NULL, NULL); g_source_attach (thread_events, NULL); #endif quarry_stock_init (); user_real_name = g_get_real_name (); configuration_init (gtk_configuration_sections, NUM_GTK_CONFIGURATION_SECTIONS); /* Try to read site configuration file. Later, * configuration_write_to_file() will effectively copy all * site-default settings to user's configuration, with any changes * she has made. * * Site configuration file is meant for distributions, to * e.g. automatically register GNU Go with Quarry. */ configuration_read_from_file (gtk_configuration_sections, NUM_GTK_CONFIGURATION_SECTIONS, PACKAGE_DATA_DIR "/quarry.cfg"); gtp_engine_list_init (&site_configuration_engines); string_list_steal_items (&site_configuration_engines, >p_engines); configuration_file = g_build_path (G_DIR_SEPARATOR_S, g_get_home_dir (), ".quarry", NULL); configuration_read_from_file (gtk_configuration_sections, NUM_GTK_CONFIGURATION_SECTIONS, configuration_file); configuration_combine_string_lists (>p_engines, &site_configuration_engines, (G_STRUCT_OFFSET (GtpEngineListItem, site_configuration_name))); gtk_preferences_init (); #if GTK_2_2_OR_LATER gtk_window_set_default_icon_from_file (DATA_DIR "/pixmaps/quarry.png", NULL); #endif } static void run_main_loop (void) { int k; g_timeout_add_full (G_PRIORITY_LOW, 10000, run_cleanup_tasks, NULL, NULL); gtk_main (); object_cache_free (>k_main_tile_set_cache); object_cache_free (>k_sgf_markup_tile_set_cache); #if THREADS_SUPPORTED g_source_destroy (thread_events); g_async_queue_unref (thread_events_queue); #endif if (objects_to_finalize) { /* FIXME: Use g_ptr_array_foreach() when we drop support for * pre-2.4 GTK+. */ for (k = 0; k < objects_to_finalize->len; k++) g_object_unref (g_ptr_array_index (objects_to_finalize, k)); g_ptr_array_free (objects_to_finalize, TRUE); } if (pointers_to_free) { /* FIXME: Likewise. */ for (k = 0; k < pointers_to_free->len; k++) g_free (g_ptr_array_index (pointers_to_free, k)); g_ptr_array_free (pointers_to_free, TRUE); } configuration_write_to_file (gtk_configuration_sections, NUM_GTK_CONFIGURATION_SECTIONS, configuration_file); g_free (configuration_file); configuration_dispose (gtk_configuration_sections, NUM_GTK_CONFIGURATION_SECTIONS); } static gboolean run_cleanup_tasks (gpointer data) { UNUSED (data); object_cache_recycle_dump (>k_main_tile_set_cache, 0); object_cache_recycle_dump (>k_sgf_markup_tile_set_cache, 0); return TRUE; } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/quarry-assistant.c0000644000175000017500000002752510522173233017343 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "quarry-assistant.h" #include "gtk-control-center.h" #include "gtk-help.h" #include "gtk-utils.h" #include "quarry-stock.h" #include #define ASSISTANT_RESPONSE_NEXT 1 #define ASSISTANT_RESPONSE_BACK 2 typedef struct _QuarryAssistantPage QuarryAssistantPage; struct _QuarryAssistantPage { QuarryAssistantPageShownCallback shown_callback; QuarryAssistantPageAcceptableCallback acceptable_callback; const gchar *help_link_id; QuarryAssistantPageHelpLinkIDCallback help_link_id_callback; }; static void quarry_assistant_class_init (QuarryAssistantClass *class); static void quarry_assistant_init (QuarryAssistant *assistant); static void quarry_assistant_update_buttons (QuarryAssistant *assistant); static void quarry_assistant_response (GtkDialog *dialog, gint response_id); static void quarry_assistant_destroy (GtkObject *object); static GtkDialogClass *parent_class; static GQuark assistant_page_quark; GType quarry_assistant_get_type (void) { static GType assistant_type = 0; if (!assistant_type) { static GTypeInfo assistant_info = { sizeof (QuarryAssistantClass), NULL, NULL, (GClassInitFunc) quarry_assistant_class_init, NULL, NULL, sizeof (QuarryAssistant), 1, (GInstanceInitFunc) quarry_assistant_init, NULL }; assistant_type = g_type_register_static (GTK_TYPE_DIALOG, "QuarryAssistant", &assistant_info, 0); } return assistant_type; } static void quarry_assistant_class_init (QuarryAssistantClass *class) { parent_class = g_type_class_peek_parent (class); GTK_OBJECT_CLASS (class)->destroy = quarry_assistant_destroy; GTK_DIALOG_CLASS (class)->response = quarry_assistant_response; assistant_page_quark = g_quark_from_static_string ("quarry-assistant-page"); } static void quarry_assistant_init (QuarryAssistant *assistant) { GtkWidget *notebook; gtk_control_center_window_created (GTK_WINDOW (assistant)); notebook = gtk_utils_create_invisible_notebook (); assistant->notebook = GTK_NOTEBOOK (notebook); gtk_widget_show (notebook); gtk_utils_standardize_dialog (&assistant->dialog, notebook); g_signal_connect_data (notebook, "switch-page", G_CALLBACK (quarry_assistant_update_buttons), assistant, NULL, G_CONNECT_AFTER | G_CONNECT_SWAPPED); gtk_dialog_add_button (&assistant->dialog, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL); assistant->back_button = gtk_dialog_add_button (&assistant->dialog, GTK_STOCK_GO_BACK, ASSISTANT_RESPONSE_BACK); assistant->next_button = gtk_dialog_add_button (&assistant->dialog, GTK_STOCK_GO_FORWARD, ASSISTANT_RESPONSE_NEXT); assistant->finish_button = gtk_dialog_add_button (&assistant->dialog, GTK_STOCK_OK, GTK_RESPONSE_OK); assistant->help_button = NULL; assistant->user_data = NULL; } GtkWidget * quarry_assistant_new (const char *title, gpointer user_data) { GtkWidget *widget = GTK_WIDGET (g_object_new (QUARRY_TYPE_ASSISTANT, NULL)); gtk_window_set_title (GTK_WINDOW (widget), title); QUARRY_ASSISTANT (widget)->user_data = user_data; return widget; } void quarry_assistant_set_user_data (QuarryAssistant *assistant, gpointer user_data) { g_return_if_fail (QUARRY_IS_ASSISTANT (assistant)); assistant->user_data = user_data; } static void quarry_assistant_update_buttons (QuarryAssistant *assistant) { gint current_page_index = gtk_notebook_get_current_page (assistant->notebook); if (current_page_index >= 0) { int is_last_page; /* Workaround GTK+ 2.0 problem. Causes annoying warning without * this hack in certain cases. */ #if !GTK_2_2_OR_LATER GtkWidget *current_page = gtk_notebook_get_nth_page (assistant->notebook, current_page_index); GtkWidget *window = gtk_widget_get_toplevel (current_page); if (!window || !GTK_WIDGET_TOPLEVEL (window)) return; #endif /* This is not very important for Quarry, but pre-2.2 determining * if the page is last is somewhat hackish. Therefore I think it * is better to #if here. */ #if GTK_2_2_OR_LATER is_last_page = (current_page_index == gtk_notebook_get_n_pages (assistant->notebook) - 1); #else is_last_page = (gtk_notebook_get_nth_page (assistant->notebook, current_page_index + 1) == NULL); #endif if (current_page_index > 0) gtk_widget_show (assistant->back_button); else gtk_widget_hide (assistant->back_button); if (!is_last_page) { gtk_widget_show (assistant->next_button); gtk_widget_hide (assistant->finish_button); gtk_dialog_set_default_response (&assistant->dialog, ASSISTANT_RESPONSE_NEXT); } else { gtk_widget_hide (assistant->next_button); gtk_widget_show (assistant->finish_button); gtk_dialog_set_default_response (&assistant->dialog, GTK_RESPONSE_OK); } if (assistant->help_button) { GtkWidget *current_page = gtk_notebook_get_nth_page (assistant->notebook, current_page_index); QuarryAssistantPage *page_data = g_object_get_qdata (G_OBJECT (current_page), assistant_page_quark); gtk_widget_set_sensitive (assistant->help_button, (page_data->help_link_id != NULL || page_data->help_link_id_callback != NULL)); } } else { gtk_widget_hide (assistant->back_button); gtk_widget_hide (assistant->next_button); gtk_widget_hide (assistant->finish_button); if (assistant->help_button) gtk_widget_set_sensitive (assistant->help_button, FALSE); } } static void quarry_assistant_response (GtkDialog *dialog, gint response_id) { QuarryAssistant *assistant = QUARRY_ASSISTANT (dialog); GtkNotebook *notebook = assistant->notebook; gint current_page_index; GtkWidget *current_page; QuarryAssistantPage *page_data; if (response_id == GTK_RESPONSE_HELP) { current_page_index = gtk_notebook_get_current_page (notebook); current_page = gtk_notebook_get_nth_page (notebook, current_page_index); page_data = g_object_get_qdata (G_OBJECT (current_page), assistant_page_quark); g_assert (page_data->help_link_id || page_data->help_link_id_callback); gtk_help_display (page_data->help_link_id ? page_data->help_link_id : (page_data->help_link_id_callback (assistant->user_data))); } /* Assistant pages might contain spin buttons. */ gtk_utils_workaround_focus_bug (GTK_WINDOW (assistant)); if (response_id == ASSISTANT_RESPONSE_NEXT || response_id == GTK_RESPONSE_OK) { current_page_index = gtk_notebook_get_current_page (notebook); current_page = gtk_notebook_get_nth_page (notebook, current_page_index); page_data = g_object_get_qdata (G_OBJECT (current_page), assistant_page_quark); if (page_data && page_data->acceptable_callback && !page_data->acceptable_callback (assistant->user_data)) return; } if (response_id == ASSISTANT_RESPONSE_NEXT || response_id == ASSISTANT_RESPONSE_BACK) { if (response_id == ASSISTANT_RESPONSE_NEXT) gtk_notebook_next_page (notebook); else gtk_notebook_prev_page (notebook); current_page_index = gtk_notebook_get_current_page (notebook); current_page = gtk_notebook_get_nth_page (notebook, current_page_index); page_data = g_object_get_qdata (G_OBJECT (current_page), assistant_page_quark); if (page_data && page_data->shown_callback) page_data->shown_callback (assistant->user_data); } if (response_id == GTK_RESPONSE_OK || response_id == GTK_RESPONSE_CANCEL) gtk_widget_destroy (GTK_WIDGET (dialog)); } static void quarry_assistant_destroy (GtkObject *object) { gtk_control_center_window_destroyed (GTK_WINDOW (object)); GTK_OBJECT_CLASS (parent_class)->destroy (object); } void quarry_assistant_add_page (QuarryAssistant *assistant, GtkWidget *widget, const gchar *icon_stock_id, const gchar *title, QuarryAssistantPageShownCallback shown_callback, QuarryAssistantPageAcceptableCallback acceptable_callback) { GtkWidget *page = widget; QuarryAssistantPage *page_data = g_malloc (sizeof (QuarryAssistantPage)); g_return_if_fail (QUARRY_IS_ASSISTANT (assistant)); g_return_if_fail (GTK_IS_WIDGET (widget)); if (icon_stock_id || title) page = gtk_utils_create_titled_page (widget, icon_stock_id, title); gtk_notebook_append_page (assistant->notebook, page, NULL); gtk_widget_show (page); quarry_assistant_update_buttons (assistant); page_data->shown_callback = shown_callback; page_data->acceptable_callback = acceptable_callback; page_data->help_link_id = NULL; page_data->help_link_id_callback = NULL; g_object_set_qdata_full (G_OBJECT (page), assistant_page_quark, page_data, g_free); } void quarry_assistant_set_page_help_link_id (QuarryAssistant *assistant, GtkWidget *page, const gchar *help_link_id) { QuarryAssistantPage *page_data; g_return_if_fail (QUARRY_IS_ASSISTANT (assistant)); g_return_if_fail (GTK_IS_WIDGET (page)); g_return_if_fail (help_link_id); page_data = g_object_get_qdata (G_OBJECT (page), assistant_page_quark); if (!page_data) { page_data = g_object_get_qdata (G_OBJECT (gtk_widget_get_parent (GTK_WIDGET (page))), assistant_page_quark); g_assert (page_data); } page_data->help_link_id = help_link_id; if (!assistant->help_button) assistant->help_button = gtk_utils_add_help_button (&assistant->dialog); } void quarry_assistant_set_page_help_link_id_callback (QuarryAssistant *assistant, GtkWidget *page, QuarryAssistantPageHelpLinkIDCallback callback) { QuarryAssistantPage *page_data; g_return_if_fail (QUARRY_IS_ASSISTANT (assistant)); g_return_if_fail (GTK_IS_WIDGET (page)); g_return_if_fail (callback); page_data = g_object_get_qdata (G_OBJECT (page), assistant_page_quark); if (!page_data) { page_data = g_object_get_qdata (G_OBJECT (gtk_widget_get_parent (GTK_WIDGET (page))), assistant_page_quark); g_assert (page_data); } page_data->help_link_id_callback = callback; if (!assistant->help_button) assistant->help_button = gtk_utils_add_help_button (&assistant->dialog); } void quarry_assistant_set_finish_button (QuarryAssistant *assistant, const gchar *stock_id) { g_return_if_fail (QUARRY_IS_ASSISTANT (assistant)); g_return_if_fail (stock_id); gtk_widget_destroy (assistant->finish_button); assistant->finish_button = gtk_dialog_add_button (&assistant->dialog, stock_id, GTK_RESPONSE_OK); } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/quarry-find-dialog.c0000644000175000017500000007020510522173343017502 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "quarry-find-dialog.h" #include "gtk-configuration.h" #include "gtk-named-vbox.h" #include "gtk-utils.h" #include "quarry-stock.h" #include "sgf.h" #include #include static void quarry_find_dialog_class_init (QuarryFindDialogClass *class); static void quarry_find_dialog_init (QuarryFindDialog *dialog); static void parameters_changed (QuarryFindDialog *dialog); static char * strstr_whole_word (const char *haystack, const char *needle); static char * strrstr_whole_word (const char *haystack, const char *needle); static char * get_top_buffer_part (GtkTextBuffer *text_buffer, gboolean node_name_inserted, const GtkTextIter *boundary_iterator, gint search_in); static char * get_bottom_buffer_part (GtkTextBuffer *text_buffer, gboolean node_name_inserted, const GtkTextIter *boundary_iterator, gint search_in); static gboolean char_is_word_constituent (const gchar *character); inline static gchar * get_normalized_text (const gchar *text, gint length, gboolean case_sensitive); static gint get_offset_in_original_text (const gchar *text, gint length, gint normalized_text_offset, gboolean case_sensitive, gint first_guess); static GtkDialog *parent_class; GType quarry_find_dialog_get_type (void) { static GType quarry_find_dialog_type = 0; if (!quarry_find_dialog_type) { static const GTypeInfo quarry_find_dialog_info = { sizeof (QuarryFindDialogClass), NULL, NULL, (GClassInitFunc) quarry_find_dialog_class_init, NULL, NULL, sizeof (QuarryFindDialog), 0, (GInstanceInitFunc) quarry_find_dialog_init, NULL }; quarry_find_dialog_type = g_type_register_static (GTK_TYPE_DIALOG, "QuarryFindDialog", &quarry_find_dialog_info, 0); } return quarry_find_dialog_type; } static void quarry_find_dialog_class_init (QuarryFindDialogClass *class) { parent_class = g_type_class_peek_parent (class); } static void quarry_find_dialog_init (QuarryFindDialog *dialog) { static const gchar *tree_scope_radio_button_labels[2] = { N_("Whole game _tree"), N_("Current no_de only") }; static const gchar *properties_scope_radio_button_labels[3] = { N_("C_omments & node names"), N_("Comm_ents only"), N_("Node na_mes only") }; GtkWidget *entry; GtkWidget *label; GtkWidget *hbox; GtkWidget *case_sensitive_check_button; GtkWidget *whole_words_only_check_button; GtkWidget *wrap_around_check_button; GtkWidget *vbox1; GtkWidget *close_automatically_check_button; GtkWidget *options_named_vbox; GtkWidget *tree_scope_radio_buttons[2]; GtkWidget *properties_scope_radio_buttons[3]; GtkWidget *vbox2; GtkWidget *scope_named_vbox; int k; gtk_dialog_add_buttons (&dialog->dialog, GTK_STOCK_CLOSE, GTK_RESPONSE_CANCEL, QUARRY_STOCK_FIND_PREVIOUS, QUARRY_FIND_DIALOG_FIND_PREVIOUS, QUARRY_STOCK_FIND_NEXT, QUARRY_FIND_DIALOG_FIND_NEXT, NULL); gtk_utils_add_help_button (&dialog->dialog); gtk_dialog_set_default_response (&dialog->dialog, QUARRY_FIND_DIALOG_FIND_NEXT); gtk_utils_make_window_only_horizontally_resizable (GTK_WINDOW (dialog)); #if GTK_2_4_OR_LATER entry = gtk_combo_box_entry_new_text (); dialog->search_for_entry = GTK_ENTRY (GTK_BIN (entry)->child); gtk_entry_set_activates_default (dialog->search_for_entry, TRUE); #else /* not GTK_2_4_OR_LATER */ entry = gtk_utils_create_entry (NULL, RETURN_ACTIVATES_DEFAULT); dialog->search_for_entry = GTK_ENTRY (entry); #endif /* not GTK_2_4_OR_LATER */ g_signal_connect_swapped (entry, "changed", G_CALLBACK (parameters_changed), dialog); label = gtk_utils_create_mnemonic_label (_("Search _for:"), entry); hbox = gtk_utils_pack_in_box (GTK_TYPE_HBOX, QUARRY_SPACING, label, GTK_UTILS_FILL, entry, GTK_UTILS_PACK_DEFAULT, NULL); case_sensitive_check_button = gtk_check_button_new_with_mnemonic (_("Case _sensitive")); dialog->case_sensitive_toggle_button = GTK_TOGGLE_BUTTON (case_sensitive_check_button); g_signal_connect_swapped (case_sensitive_check_button, "toggled", G_CALLBACK (parameters_changed), dialog); whole_words_only_check_button = gtk_check_button_new_with_mnemonic (_("Whole _words only")); dialog->whole_words_only_toggle_button = GTK_TOGGLE_BUTTON (whole_words_only_check_button); g_signal_connect_swapped (whole_words_only_check_button, "toggled", G_CALLBACK (parameters_changed), dialog); wrap_around_check_button = gtk_check_button_new_with_mnemonic (_("Wrap _around")); dialog->wrap_around_toggle_button = GTK_TOGGLE_BUTTON (wrap_around_check_button); g_signal_connect_swapped (wrap_around_check_button, "toggled", G_CALLBACK (parameters_changed), dialog); vbox1 = gtk_utils_pack_in_box (GTK_TYPE_VBOX, QUARRY_SPACING_SMALL, case_sensitive_check_button, GTK_UTILS_FILL, whole_words_only_check_button, GTK_UTILS_FILL, wrap_around_check_button, GTK_UTILS_FILL, NULL); close_automatically_check_button = gtk_check_button_new_with_mnemonic (_("A_uto-close this dialog")); dialog->close_automatically_toggle_button = GTK_TOGGLE_BUTTON (close_automatically_check_button); options_named_vbox = gtk_utils_pack_in_box (GTK_TYPE_NAMED_VBOX, QUARRY_SPACING_BIG, vbox1, GTK_UTILS_FILL, close_automatically_check_button, GTK_UTILS_FILL, NULL); gtk_named_vbox_set_label_text (GTK_NAMED_VBOX (options_named_vbox), _("Options")); gtk_utils_create_radio_chain (tree_scope_radio_buttons, tree_scope_radio_button_labels, 2); dialog->search_current_node_only_toggle_button = GTK_TOGGLE_BUTTON (tree_scope_radio_buttons[1]); g_signal_connect_swapped (tree_scope_radio_buttons[0], "toggled", G_CALLBACK (parameters_changed), dialog); vbox1 = gtk_utils_pack_in_box (GTK_TYPE_VBOX, QUARRY_SPACING_SMALL, tree_scope_radio_buttons[0], GTK_UTILS_FILL, tree_scope_radio_buttons[1], GTK_UTILS_FILL, NULL); /* Let's be over-secure (a compile-time error would have been * better...) */ g_assert (SEARCH_EVERYWHERE == 0 && SEARCH_IN_COMMENTS == 1 && SEARCH_IN_NODE_NAMES == 2); gtk_utils_create_radio_chain (properties_scope_radio_buttons, properties_scope_radio_button_labels, 3); for (k = 0; k < 3; k++) { dialog->search_scope_toggle_buttons[k] = GTK_TOGGLE_BUTTON (properties_scope_radio_buttons[k]); } g_signal_connect_swapped (properties_scope_radio_buttons[0], "toggled", G_CALLBACK (parameters_changed), dialog); g_signal_connect_swapped (properties_scope_radio_buttons[1], "toggled", G_CALLBACK (parameters_changed), dialog); vbox2 = gtk_utils_pack_in_box (GTK_TYPE_VBOX, QUARRY_SPACING_SMALL, properties_scope_radio_buttons[0], GTK_UTILS_FILL, properties_scope_radio_buttons[1], GTK_UTILS_FILL, properties_scope_radio_buttons[2], GTK_UTILS_FILL, NULL); scope_named_vbox = gtk_utils_pack_in_box (GTK_TYPE_NAMED_VBOX, QUARRY_SPACING_BIG, vbox1, GTK_UTILS_FILL, vbox2, GTK_UTILS_FILL, NULL); gtk_named_vbox_set_label_text (GTK_NAMED_VBOX (scope_named_vbox), _("Search Scope")); vbox1 = gtk_utils_pack_in_box (GTK_TYPE_VBOX, QUARRY_SPACING_BIG, hbox, GTK_UTILS_FILL, (gtk_utils_pack_in_box (GTK_TYPE_HBOX, QUARRY_SPACING_VERY_BIG, options_named_vbox, GTK_UTILS_FILL, scope_named_vbox, GTK_UTILS_FILL, NULL)), GTK_UTILS_FILL, NULL); gtk_widget_show_all (vbox1); gtk_utils_standardize_dialog (&dialog->dialog, vbox1); /* Desensitize buttons. */ parameters_changed (dialog); } GtkWidget * quarry_find_dialog_new (const gchar *title) { GtkWidget *dialog = GTK_WIDGET (g_object_new (QUARRY_TYPE_FIND_DIALOG, NULL)); gtk_window_set_title (GTK_WINDOW (dialog), title); return dialog; } const gchar * quarry_find_dialog_get_text_to_find (QuarryFindDialog *dialog) { g_return_val_if_fail (QUARRY_IS_FIND_DIALOG (dialog), NULL); return gtk_entry_get_text (dialog->search_for_entry); } gboolean quarry_find_dialog_get_case_sensitive (QuarryFindDialog *dialog) { g_return_val_if_fail (QUARRY_IS_FIND_DIALOG (dialog), FALSE); return gtk_toggle_button_get_active (dialog->case_sensitive_toggle_button); } gboolean quarry_find_dialog_get_whole_words_only (QuarryFindDialog *dialog) { g_return_val_if_fail (QUARRY_IS_FIND_DIALOG (dialog), FALSE); return gtk_toggle_button_get_active (dialog->whole_words_only_toggle_button); } gboolean quarry_find_dialog_get_wrap_around (QuarryFindDialog *dialog) { g_return_val_if_fail (QUARRY_IS_FIND_DIALOG (dialog), FALSE); return gtk_toggle_button_get_active (dialog->wrap_around_toggle_button); } gboolean quarry_find_dialog_get_search_whole_game_tree (QuarryFindDialog *dialog) { g_return_val_if_fail (QUARRY_IS_FIND_DIALOG (dialog), FALSE); return !(gtk_toggle_button_get_active (dialog->search_current_node_only_toggle_button)); } gint quarry_find_dialog_get_search_in (QuarryFindDialog *dialog) { g_return_val_if_fail (QUARRY_IS_FIND_DIALOG (dialog), SEARCH_EVERYWHERE); if (gtk_toggle_button_get_active (dialog->search_scope_toggle_buttons[SEARCH_EVERYWHERE])) return SEARCH_EVERYWHERE; else if (gtk_toggle_button_get_active (dialog->search_scope_toggle_buttons[SEARCH_IN_COMMENTS])) return SEARCH_IN_COMMENTS; else return SEARCH_IN_NODE_NAMES; } gboolean quarry_find_dialog_get_close_automatically (QuarryFindDialog *dialog) { g_return_val_if_fail (QUARRY_IS_FIND_DIALOG (dialog), FALSE); return (gtk_toggle_button_get_active (dialog->close_automatically_toggle_button)); } void quarry_find_dialog_set_text_to_find (QuarryFindDialog *dialog, const gchar *text_to_find) { g_return_if_fail (QUARRY_IS_FIND_DIALOG (dialog)); gtk_entry_set_text (dialog->search_for_entry, text_to_find); } void quarry_find_dialog_set_search_history (QuarryFindDialog *dialog, const StringList *strings) { #if GTK_2_4_OR_LATER GtkComboBox *combo_box; GtkTreeModel *tree_model; GtkTreeIter dummy_iterator; StringListItem *item; g_return_if_fail (QUARRY_IS_FIND_DIALOG (dialog)); g_return_if_fail (strings != NULL); combo_box = GTK_COMBO_BOX (gtk_widget_get_parent (GTK_WIDGET (dialog->search_for_entry))); tree_model = gtk_combo_box_get_model (combo_box); while (gtk_tree_model_get_iter_first (tree_model, &dummy_iterator)) gtk_combo_box_remove_text (combo_box, 0); for (item = strings->first; item; item = item->next) gtk_combo_box_append_text (combo_box, item->text); #else /* not GTK_2_4_OR_LATER */ UNUSED (dialog); UNUSED (strings); #endif /* not GTK_2_4_OR_LATER */ } void quarry_find_dialog_set_case_sensitive (QuarryFindDialog *dialog, gboolean case_sensitive) { g_return_if_fail (QUARRY_IS_FIND_DIALOG (dialog)); gtk_toggle_button_set_active (dialog->case_sensitive_toggle_button, case_sensitive); } void quarry_find_dialog_set_whole_words_only (QuarryFindDialog *dialog, gboolean whole_words_only) { g_return_if_fail (QUARRY_IS_FIND_DIALOG (dialog)); gtk_toggle_button_set_active (dialog->whole_words_only_toggle_button, whole_words_only); } void quarry_find_dialog_set_wrap_around (QuarryFindDialog *dialog, gboolean wrap_around) { g_return_if_fail (QUARRY_IS_FIND_DIALOG (dialog)); gtk_toggle_button_set_active (dialog->wrap_around_toggle_button, wrap_around); } void quarry_find_dialog_set_search_whole_game_tree (QuarryFindDialog *dialog, gboolean search_whole_game_tree) { g_return_if_fail (QUARRY_IS_FIND_DIALOG (dialog)); gtk_toggle_button_set_active (dialog->search_current_node_only_toggle_button, !search_whole_game_tree); } void quarry_find_dialog_set_search_in (QuarryFindDialog *dialog, gint search_in) { g_return_if_fail (QUARRY_IS_FIND_DIALOG (dialog)); g_return_if_fail (search_in == SEARCH_EVERYWHERE || search_in == SEARCH_IN_COMMENTS || search_in == SEARCH_IN_NODE_NAMES); gtk_toggle_button_set_active (dialog->search_scope_toggle_buttons[search_in], TRUE); } void quarry_find_dialog_set_close_automatically (QuarryFindDialog *dialog, gboolean close_automatically) { g_return_if_fail (QUARRY_IS_FIND_DIALOG (dialog)); gtk_toggle_button_set_active (dialog->close_automatically_toggle_button, close_automatically); } static void parameters_changed (QuarryFindDialog *dialog) { gboolean sensitive = (* gtk_entry_get_text (dialog->search_for_entry) != 0); gtk_dialog_set_response_sensitive (&dialog->dialog, QUARRY_FIND_DIALOG_FIND_NEXT, sensitive); gtk_dialog_set_response_sensitive (&dialog->dialog, QUARRY_FIND_DIALOG_FIND_PREVIOUS, sensitive); } /* This function finds text occurences in comments of current SGF game * tree's nodes. We don't use GtkTreeBuffer built-in search, because * it would have been very inefficient: we would have had to load each * comment in a buffer before searching. Also, GtkTreeBuffer * apparently doesn't care much for Unicode character collation etc. * * FIMXE: Arguments are really many... */ gboolean quarry_find_text (const gchar *text_to_find, QuarryFindDialogSearchDirection direction, gboolean case_sensitive, gboolean whole_words_only, gboolean wrap_around, gboolean search_whole_game_tree, gint search_in, GtkTextBuffer *text_buffer, gboolean node_name_inserted, SgfGameTree *sgf_tree, void (* switch_to_given_node) (void *, SgfNode *), void *user_data) { GtkTextIter selection_iterator; gchar *text_to_find_normalized; const gchar *text_to_search_in; gchar *text_to_search_in_normalized; gchar *text_to_free; const gchar *occurence; gint base_offset = 0; SgfType property_type; char * (* do_search) (const char *haystack, const char *needle); text_to_find_normalized = get_normalized_text (text_to_find, -1, case_sensitive); if (direction == QUARRY_FIND_DIALOG_FIND_NEXT) do_search = (whole_words_only ? strstr_whole_word : strstr); else { /* Apparently, g_strrstr() uses naive search, but let's not care. */ do_search = (whole_words_only ? strrstr_whole_word : g_strrstr); } /* First search in the right portion of the current node's * comments. */ if (direction == QUARRY_FIND_DIALOG_FIND_NEXT) { gtk_text_buffer_get_selection_bounds (text_buffer, NULL, &selection_iterator); text_to_free = get_bottom_buffer_part (text_buffer, node_name_inserted, &selection_iterator, search_in); } else { gtk_text_buffer_get_selection_bounds (text_buffer, &selection_iterator, NULL); text_to_free = get_top_buffer_part (text_buffer, node_name_inserted, &selection_iterator, search_in); } if (text_to_free) { text_to_search_in_normalized = get_normalized_text (text_to_free, -1, case_sensitive); occurence = do_search (text_to_search_in_normalized, text_to_find_normalized); if (occurence) { text_to_search_in = text_to_free; property_type = SGF_UNKNOWN; if (direction == QUARRY_FIND_DIALOG_FIND_NEXT) base_offset = gtk_text_iter_get_offset (&selection_iterator); goto found; } g_free (text_to_search_in_normalized); g_free (text_to_free); } /* Next traverse the game tree if requested. */ if (search_whole_game_tree) { SgfNode *occurence_node = sgf_tree->current_node; SgfNode * (* do_traverse) (const SgfNode *sgf_node) = (direction == QUARRY_FIND_DIALOG_FIND_NEXT ? sgf_node_traverse_forward : sgf_node_traverse_backward); SgfType first_property_type; switch (search_in) { case SEARCH_EVERYWHERE: first_property_type = (direction == QUARRY_FIND_DIALOG_FIND_NEXT ? SGF_NODE_NAME : SGF_COMMENT); break; case SEARCH_IN_COMMENTS: first_property_type = SGF_COMMENT; break; case SEARCH_IN_NODE_NAMES: first_property_type = SGF_NODE_NAME; break; default: g_assert_not_reached (); return FALSE; } while (1) { occurence_node = do_traverse (occurence_node); if (!occurence_node) { if (!wrap_around) break; if (direction == QUARRY_FIND_DIALOG_FIND_NEXT) occurence_node = sgf_game_tree_traverse_forward (sgf_tree); else occurence_node = sgf_game_tree_traverse_backward (sgf_tree); } /* Can happen when wrapping around. */ if (occurence_node == sgf_tree->current_node) break; property_type = first_property_type; do { text_to_search_in = sgf_node_get_text_property_value (occurence_node, property_type); if (text_to_search_in) { text_to_search_in_normalized = get_normalized_text (text_to_search_in, -1, case_sensitive); occurence = do_search (text_to_search_in_normalized, text_to_find_normalized); if (occurence) { switch_to_given_node (user_data, occurence_node); text_to_free = NULL; goto found; } g_free (text_to_search_in_normalized); } if (search_in != SEARCH_EVERYWHERE) break; property_type = (SGF_COMMENT + SGF_NODE_NAME) - property_type; } while (property_type != first_property_type); } } /* Finally, wrap around in the current node's comment, if * requested. */ if (wrap_around) { /* The `selection_iterator' is already set. */ if (direction == QUARRY_FIND_DIALOG_FIND_NEXT) text_to_free = get_top_buffer_part (text_buffer, node_name_inserted, &selection_iterator, search_in); else text_to_free = get_bottom_buffer_part (text_buffer, node_name_inserted, &selection_iterator, search_in); if (text_to_free) { text_to_search_in_normalized = get_normalized_text (text_to_free, -1, case_sensitive); occurence = do_search (text_to_search_in_normalized, text_to_find_normalized); if (occurence) { text_to_search_in = text_to_free; property_type = SGF_UNKNOWN; if (direction == QUARRY_FIND_DIALOG_FIND_PREVIOUS) base_offset = gtk_text_iter_get_offset (&selection_iterator); goto found; } g_free (text_to_search_in_normalized); g_free (text_to_free); } } /* Nothing found. */ g_free (text_to_find_normalized); return FALSE; found: { /* We need to find the boundaries of the found string to adjust * selection in the `text_buffer'. * * The main problem is that g_utf8_normalize() can change the * length of string in characters (not the case with simple ASCII * strings, but we at Unicode handling here.) So, we find how * `text_to_search_in' maps onto `text_to_search_in_normalized' * here. */ const gchar *last_line; const gchar *last_line_normalized; const gchar *scan; gint num_lines; gint remaining_text_length; gint last_line_offset; GtkTextIter insertion_iterator; GtkTextIter bound_iterator; /* If `text_to_search_in' doesn't include node name, while the * text buffer does, increase `base_offset' accordingly. */ if (node_name_inserted && (property_type == SGF_COMMENT || (property_type == SGF_UNKNOWN && base_offset == 0 && search_in == SEARCH_IN_COMMENTS))) { GtkTextIter second_line_iterator; gtk_text_buffer_get_iter_at_line (text_buffer, &second_line_iterator, 1); base_offset += gtk_text_iter_get_offset (&second_line_iterator); } if (property_type == SGF_COMMENT) { /* First skip all full lines, to speed the things up in case of * a very long text. */ for (last_line_normalized = text_to_search_in_normalized, scan = text_to_search_in_normalized, num_lines = 0; scan < occurence; scan++) { if (*scan == '\n') { num_lines++; last_line_normalized = scan + 1; } } for (last_line = text_to_search_in; num_lines > 0; last_line++) { if (IS_UTF8_STARTER (*last_line)) { /* Also adjust `base_offset' as we scan the text. */ base_offset++; if (*last_line == '\n') num_lines--; } } /* Only search in the next line. */ remaining_text_length = 0; while (last_line[remaining_text_length] && last_line[remaining_text_length] != '\n') remaining_text_length++; } else { last_line_normalized = text_to_search_in_normalized; last_line = text_to_search_in; remaining_text_length = strlen (last_line); } last_line_offset = get_offset_in_original_text (last_line, remaining_text_length, occurence - last_line_normalized, case_sensitive, occurence - last_line_normalized); gtk_text_buffer_get_iter_at_offset (text_buffer, &insertion_iterator, base_offset + last_line_offset); last_line_offset = get_offset_in_original_text (last_line, remaining_text_length, ((occurence + strlen (text_to_find_normalized)) - last_line_normalized), case_sensitive, last_line_offset + strlen (text_to_find)); gtk_text_buffer_get_iter_at_offset (text_buffer, &bound_iterator, base_offset + last_line_offset); gtk_text_buffer_select_range (text_buffer, &insertion_iterator, &bound_iterator); } g_free (text_to_find_normalized); g_free (text_to_search_in_normalized); g_free (text_to_free); return TRUE; } static char * strstr_whole_word (const char *haystack, const char *needle) { gchar *occurence = strstr (haystack, needle); if (occurence) { gint needle_length = strlen (needle); gboolean first_char_is_word_constituent = char_is_word_constituent (needle); gboolean last_char_is_word_constituent = char_is_word_constituent (g_utf8_prev_char (needle + needle_length)); do { if ((!first_char_is_word_constituent || occurence == haystack || !char_is_word_constituent (g_utf8_prev_char (occurence))) && (!last_char_is_word_constituent || *(occurence + needle_length) == 0 || !char_is_word_constituent (occurence + needle_length))) return occurence; occurence = strstr (occurence + 1, needle); } while (occurence); } return NULL; } static char * strrstr_whole_word (const char *haystack, const char *needle) { gchar *occurence = g_strrstr (haystack, needle); if (occurence) { gint needle_length = strlen (needle); gboolean first_char_is_word_constituent = char_is_word_constituent (needle); gboolean last_char_is_word_constituent = char_is_word_constituent (g_utf8_prev_char (needle + needle_length)); do { if ((!first_char_is_word_constituent || occurence == haystack || !char_is_word_constituent (g_utf8_prev_char (occurence))) && (!last_char_is_word_constituent || *(occurence + needle_length) == 0 || !char_is_word_constituent (occurence + needle_length))) return occurence; occurence = g_strrstr_len (haystack, occurence + (needle_length - 1) - haystack, needle); } while (occurence); } return NULL; } static char * get_top_buffer_part (GtkTextBuffer *text_buffer, gboolean node_name_inserted, const GtkTextIter *boundary_iterator, gint search_in) { GtkTextIter start_iterator; GtkTextIter real_boundary_iterator = *boundary_iterator; if (search_in != SEARCH_IN_COMMENTS || !node_name_inserted) { gtk_text_buffer_get_start_iter (text_buffer, &start_iterator); } else gtk_text_buffer_get_iter_at_line (text_buffer, &start_iterator, 1); if (search_in == SEARCH_IN_NODE_NAMES) { if (!node_name_inserted) return NULL; if (gtk_text_iter_get_line (&real_boundary_iterator) > 0) { gtk_text_buffer_get_iter_at_line (text_buffer, &real_boundary_iterator, 1); gtk_text_iter_backward_char (&real_boundary_iterator); } } if (gtk_text_iter_compare (&start_iterator, &real_boundary_iterator) >= 0) return NULL; return gtk_text_iter_get_text (&start_iterator, &real_boundary_iterator); } static char * get_bottom_buffer_part (GtkTextBuffer *text_buffer, gboolean node_name_inserted, const GtkTextIter *boundary_iterator, gint search_in) { GtkTextIter real_boundary_iterator = *boundary_iterator; GtkTextIter end_iterator; if (search_in == SEARCH_IN_COMMENTS && node_name_inserted && gtk_text_iter_get_line (&real_boundary_iterator) == 0) gtk_text_buffer_get_iter_at_line (text_buffer, &real_boundary_iterator, 1); if (search_in != SEARCH_IN_NODE_NAMES) gtk_text_buffer_get_end_iter (text_buffer, &end_iterator); else { if (!node_name_inserted) return NULL; gtk_text_buffer_get_iter_at_line (text_buffer, &end_iterator, 1); gtk_text_iter_backward_char (&end_iterator); } if (gtk_text_iter_compare (&real_boundary_iterator, &end_iterator) >= 0) return NULL; return gtk_text_iter_get_text (&real_boundary_iterator, &end_iterator); } static gboolean char_is_word_constituent (const gchar *character) { GUnicodeType character_type = g_unichar_type (g_utf8_get_char (character)); return (character_type == G_UNICODE_LOWERCASE_LETTER || character_type == G_UNICODE_MODIFIER_LETTER || character_type == G_UNICODE_OTHER_LETTER || character_type == G_UNICODE_TITLECASE_LETTER || character_type == G_UNICODE_UPPERCASE_LETTER || character_type == G_UNICODE_DECIMAL_NUMBER || character_type == G_UNICODE_LETTER_NUMBER || character_type == G_UNICODE_OTHER_NUMBER); } inline static gchar * get_normalized_text (const gchar *text, gint length, gboolean case_sensitive) { gchar *normalized_text; if (case_sensitive) normalized_text = g_utf8_normalize (text, length, G_NORMALIZE_ALL_COMPOSE); else { gchar *case_folded_text = g_utf8_casefold (text, length); normalized_text = g_utf8_normalize (case_folded_text, -1, G_NORMALIZE_ALL_COMPOSE); g_free (case_folded_text); } return normalized_text; } static gint get_offset_in_original_text (const gchar *text, gint length, gint normalized_text_offset, gboolean case_sensitive, gint first_guess) { gint byte_offset = MIN (first_guess, length - 1); gint offset; const gchar *scan; if (normalized_text_offset == 0) return 0; while (byte_offset < length && !IS_UTF8_STARTER (text[byte_offset])) byte_offset++; while (1) { gchar *normalized_text = get_normalized_text (text, byte_offset, case_sensitive); gint length = strlen (normalized_text); g_free (normalized_text); if (length == normalized_text_offset) break; /* FIXME: Maybe implement something more efficient than one UTF-8 * character at a time. */ if (length < normalized_text_offset) { do byte_offset++; while (byte_offset < length && !IS_UTF8_STARTER (text[byte_offset])); if (byte_offset == length) break; } else { do byte_offset--; while (byte_offset > 0 && !IS_UTF8_STARTER (text[byte_offset])); if (byte_offset == 0) return 0; } } for (offset = 0, scan = text; scan < text + byte_offset; scan++) { if (IS_UTF8_STARTER (*scan)) offset++; } return offset; } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/quarry-history-text-buffer.c0000644000175000017500000001456010371154113021255 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "quarry-history-text-buffer.h" #include static void quarry_history_text_buffer_class_init (QuarryHistoryTextBufferClass *class); static void quarry_history_text_buffer_init (QuarryHistoryTextBuffer *buffer); static gboolean quarry_history_text_buffer_receive_undo_entry (QuarryTextBuffer *text_buffer, QuarryTextBufferUndoEntry *undo_entry); static void quarry_history_text_buffer_finalize (GObject *object); GType quarry_history_text_buffer_get_type (void) { static GType quarry_history_text_buffer_type = 0; if (!quarry_history_text_buffer_type) { static const GTypeInfo quarry_history_text_buffer_info = { sizeof (QuarryHistoryTextBufferClass), NULL, NULL, (GClassInitFunc) quarry_history_text_buffer_class_init, NULL, NULL, sizeof (QuarryHistoryTextBuffer), 0, (GInstanceInitFunc) quarry_history_text_buffer_init, NULL }; quarry_history_text_buffer_type = g_type_register_static (QUARRY_TYPE_TEXT_BUFFER, "QuarryHistoryTextBuffer", &quarry_history_text_buffer_info, 0); } return quarry_history_text_buffer_type; } static void quarry_history_text_buffer_class_init (QuarryHistoryTextBufferClass *class) { G_OBJECT_CLASS (class)->finalize = quarry_history_text_buffer_finalize; QUARRY_TEXT_BUFFER_CLASS (class)->receive_undo_entry = quarry_history_text_buffer_receive_undo_entry; } static void quarry_history_text_buffer_init (QuarryHistoryTextBuffer *buffer) { buffer->undo_history_begin = NULL; buffer->undo_history_end = NULL; buffer->last_applied_entry = NULL; } GtkTextBuffer * quarry_history_text_buffer_new (GtkTextTagTable *tag_table) { return GTK_TEXT_BUFFER (g_object_new (QUARRY_TYPE_HISTORY_TEXT_BUFFER, "tag-table", tag_table, NULL)); } static gboolean quarry_history_text_buffer_receive_undo_entry (QuarryTextBuffer *text_buffer, QuarryTextBufferUndoEntry *undo_entry) { QuarryHistoryTextBuffer *buffer = QUARRY_HISTORY_TEXT_BUFFER (text_buffer); GList *undo_history_tail = (buffer->last_applied_entry ? buffer->last_applied_entry->next : buffer->undo_history_begin); if (undo_history_tail) { buffer->undo_history_end = undo_history_tail->prev; undo_history_tail->prev = NULL; if (buffer->undo_history_end) buffer->undo_history_end->next = NULL; else buffer->undo_history_begin = NULL; g_list_foreach (undo_history_tail, (GFunc) quarry_text_buffer_undo_entry_delete, NULL); g_list_free (undo_history_tail); } else if (buffer->last_applied_entry) { QuarryTextBufferUndoEntry *last_undo_entry = (QuarryTextBufferUndoEntry *) buffer->last_applied_entry->data; if (quarry_text_buffer_combine_undo_entries (text_buffer, last_undo_entry, undo_entry)) { /* The new entry is merged into the previous, we are done. */ return TRUE; } } if (buffer->undo_history_end) { buffer->undo_history_end = g_list_append (buffer->undo_history_end, undo_entry)->next; } else { buffer->undo_history_begin = g_list_append (NULL, undo_entry); buffer->undo_history_end = buffer->undo_history_begin; } buffer->last_applied_entry = buffer->undo_history_end; return TRUE; } static void quarry_history_text_buffer_finalize (GObject *object) { quarry_history_text_buffer_reset_history (QUARRY_HISTORY_TEXT_BUFFER (object)); } gboolean quarry_history_text_buffer_can_undo (const QuarryHistoryTextBuffer *buffer) { g_return_val_if_fail (QUARRY_IS_HISTORY_TEXT_BUFFER (buffer), FALSE); return buffer->last_applied_entry != NULL; } gboolean quarry_history_text_buffer_can_redo (const QuarryHistoryTextBuffer *buffer) { g_return_val_if_fail (QUARRY_IS_HISTORY_TEXT_BUFFER (buffer), FALSE); return buffer->last_applied_entry != buffer->undo_history_end; } void quarry_history_text_buffer_undo (QuarryHistoryTextBuffer *buffer) { g_return_if_fail (quarry_history_text_buffer_can_undo (buffer)); quarry_text_buffer_undo (&buffer->text_buffer, ((const QuarryTextBufferUndoEntry *) buffer->last_applied_entry->data)); buffer->last_applied_entry = buffer->last_applied_entry->prev; } void quarry_history_text_buffer_redo (QuarryHistoryTextBuffer *buffer) { g_return_if_fail (quarry_history_text_buffer_can_redo (buffer)); buffer->last_applied_entry = (buffer->last_applied_entry ? buffer->last_applied_entry->next : buffer->undo_history_begin); quarry_text_buffer_redo (&buffer->text_buffer, ((const QuarryTextBufferUndoEntry *) buffer->last_applied_entry->data)); } void quarry_history_text_buffer_reset_history (QuarryHistoryTextBuffer *buffer) { g_return_if_fail (QUARRY_IS_HISTORY_TEXT_BUFFER (buffer)); g_list_foreach (buffer->undo_history_begin, (GFunc) quarry_text_buffer_undo_entry_delete, NULL); g_list_free (buffer->undo_history_begin); buffer->undo_history_begin = NULL; buffer->undo_history_end = NULL; buffer->last_applied_entry = NULL; } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/quarry-message-dialog.c0000644000175000017500000002315510376703602020214 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "quarry-message-dialog.h" #include "gtk-utils.h" #include #include #include static void quarry_message_dialog_class_init (QuarryMessageDialogClass *class); static void quarry_message_dialog_init (QuarryMessageDialog *dialog); static void quarry_message_dialog_finalize (GObject *object); static void set_label_text (QuarryMessageDialog *dialog); static GtkDialogClass *parent_class; GType quarry_message_dialog_get_type (void) { static GType message_dialog_type = 0; if (!message_dialog_type) { static const GTypeInfo message_dialog_info = { sizeof (QuarryMessageDialogClass), NULL, NULL, (GClassInitFunc) quarry_message_dialog_class_init, NULL, NULL, sizeof (QuarryMessageDialog), 1, (GInstanceInitFunc) quarry_message_dialog_init, NULL }; message_dialog_type = g_type_register_static (GTK_TYPE_DIALOG, "QuarryMessageDialog", &message_dialog_info, 0); } return message_dialog_type; } static void quarry_message_dialog_class_init (QuarryMessageDialogClass *class) { parent_class = g_type_class_peek_parent (class); G_OBJECT_CLASS (class)->finalize = quarry_message_dialog_finalize; } static void quarry_message_dialog_init (QuarryMessageDialog *dialog) { GtkWindow *window = GTK_WINDOW (dialog); GtkWidget *label; GtkWidget *hbox; gtk_window_set_title (window, ""); gtk_window_set_resizable (window, FALSE); gtk_window_set_skip_pager_hint (window, TRUE); /* Note: disabled because KDE window manager doesn't give focus to * message dialog after this call (is it a bug or what?) */ #if 0 gtk_window_set_skip_taskbar_hint (window, TRUE); #endif gtk_dialog_set_has_separator (&dialog->dialog, FALSE); dialog->image = gtk_image_new (); gtk_misc_set_alignment (GTK_MISC (dialog->image), 0.5, 0.0); label = gtk_label_new (NULL); dialog->label = GTK_LABEL (label); gtk_label_set_line_wrap (dialog->label, TRUE); gtk_label_set_selectable (dialog->label, TRUE); gtk_misc_set_alignment (GTK_MISC (dialog->label), 0.0, 0.0); gtk_widget_show (label); hbox = gtk_utils_pack_in_box (GTK_TYPE_HBOX, QUARRY_SPACING, dialog->image, GTK_UTILS_FILL, label, GTK_UTILS_FILL, NULL); gtk_widget_show (hbox); gtk_utils_standardize_dialog (&dialog->dialog, hbox); gtk_box_set_spacing (GTK_BOX (dialog->dialog.vbox), QUARRY_SPACING_VERY_BIG); dialog->primary_text = NULL; dialog->secondary_text = NULL; } GtkWidget * quarry_message_dialog_new (GtkWindow *parent, GtkButtonsType buttons, const gchar *icon_stock_id, const gchar *secondary_text, const gchar *primary_text_format_string, ...) { GtkWidget *dialog; va_list arguments; va_start (arguments, primary_text_format_string); dialog = quarry_message_dialog_new_valist (parent, buttons, icon_stock_id, secondary_text, primary_text_format_string, arguments); va_end (arguments); return dialog; } GtkWidget * quarry_message_dialog_new_valist (GtkWindow *parent, GtkButtonsType buttons, const gchar *icon_stock_id, const gchar *secondary_text, const gchar *primary_text_format_string, va_list arguments) { QuarryMessageDialog *dialog = g_object_new (QUARRY_TYPE_MESSAGE_DIALOG, NULL); if (parent) gtk_window_set_transient_for (GTK_WINDOW (dialog), parent); switch (buttons) { case GTK_BUTTONS_NONE: break; case GTK_BUTTONS_OK: /* To enable Escape key. */ gtk_dialog_add_button (&dialog->dialog, GTK_STOCK_OK, GTK_RESPONSE_CANCEL); break; case GTK_BUTTONS_CLOSE: gtk_dialog_add_button (&dialog->dialog, GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE); break; case GTK_BUTTONS_CANCEL: gtk_dialog_add_button (&dialog->dialog, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL); break; case GTK_BUTTONS_YES_NO: gtk_dialog_add_buttons (&dialog->dialog, GTK_STOCK_NO, GTK_RESPONSE_NO, GTK_STOCK_YES, GTK_RESPONSE_YES, NULL); break; case GTK_BUTTONS_OK_CANCEL: gtk_dialog_add_buttons (&dialog->dialog, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OK, GTK_RESPONSE_OK, NULL); default: g_critical ("unhandled button set type %d", buttons); } quarry_message_dialog_set_icon (dialog, icon_stock_id); quarry_message_dialog_format_primary_text_valist (dialog, primary_text_format_string, arguments); quarry_message_dialog_set_secondary_text (dialog, secondary_text); return GTK_WIDGET (dialog); } void quarry_message_dialog_finalize (GObject *object) { QuarryMessageDialog *dialog = QUARRY_MESSAGE_DIALOG (object); g_free (dialog->primary_text); g_free (dialog->secondary_text); G_OBJECT_CLASS (parent_class)->finalize (object); } void quarry_message_dialog_set_icon (QuarryMessageDialog *dialog, const gchar *icon_stock_id) { g_return_if_fail (QUARRY_IS_MESSAGE_DIALOG (dialog)); gtk_image_set_from_stock (GTK_IMAGE (dialog->image), icon_stock_id, GTK_ICON_SIZE_DIALOG); if (icon_stock_id) gtk_widget_show (dialog->image); else gtk_widget_hide (dialog->image); } void quarry_message_dialog_set_primary_text (QuarryMessageDialog *dialog, const gchar *primary_text) { g_return_if_fail (QUARRY_IS_MESSAGE_DIALOG (dialog)); if (primary_text != NULL ? (dialog->primary_text == NULL || strcmp (dialog->primary_text, primary_text) != 0) : dialog->primary_text != NULL) { g_free (dialog->primary_text); dialog->primary_text = g_strdup (primary_text); set_label_text (dialog); } } void quarry_message_dialog_format_primary_text (QuarryMessageDialog *dialog, const gchar *primary_text_format_string, ...) { va_list arguments; va_start (arguments, primary_text_format_string); quarry_message_dialog_format_primary_text_valist (dialog, primary_text_format_string, arguments); va_end (arguments); } void quarry_message_dialog_format_primary_text_valist (QuarryMessageDialog *dialog, const gchar *primary_text_format_string, va_list arguments) { gchar *primary_text = g_strdup_vprintf (primary_text_format_string, arguments); quarry_message_dialog_set_primary_text (dialog, primary_text); g_free (primary_text); } void quarry_message_dialog_set_secondary_text (QuarryMessageDialog *dialog, const gchar *secondary_text) { g_return_if_fail (QUARRY_IS_MESSAGE_DIALOG (dialog)); if (secondary_text != NULL ? (dialog->secondary_text == NULL || strcmp (dialog->secondary_text, secondary_text) != 0) : dialog->secondary_text != NULL) { g_free (dialog->secondary_text); dialog->secondary_text = g_strdup (secondary_text); set_label_text (dialog); } } void quarry_message_dialog_format_secondary_text (QuarryMessageDialog *dialog, const gchar *secondary_text_format_string, ...) { va_list arguments; va_start (arguments, secondary_text_format_string); quarry_message_dialog_format_secondary_text_valist (dialog, secondary_text_format_string, arguments); va_end (arguments); } void quarry_message_dialog_format_secondary_text_valist (QuarryMessageDialog *dialog, const gchar *secondary_text_format_string, va_list arguments) { gchar *secondary_text = g_strdup_vprintf (secondary_text_format_string, arguments); quarry_message_dialog_set_secondary_text (dialog, secondary_text); g_free (secondary_text); } static void set_label_text (QuarryMessageDialog *dialog) { if (dialog->primary_text) { gchar *escaped_primary_text = g_markup_escape_text (dialog->primary_text, -1); gchar *marked_up_text; if (dialog->secondary_text) { gchar *escaped_secondary_text = g_markup_escape_text (dialog->secondary_text, -1); marked_up_text = g_strconcat ("", escaped_primary_text, "\n\n", escaped_secondary_text, NULL); g_free (escaped_secondary_text); } else { marked_up_text = g_strconcat ("", escaped_primary_text, "", NULL); } gtk_label_set_markup (dialog->label, marked_up_text); g_free (marked_up_text); g_free (escaped_primary_text); } else gtk_label_set_text (dialog->label, dialog->secondary_text); } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/quarry-move-number-dialog.c0000644000175000017500000001304310371425271021015 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "quarry-move-number-dialog.h" #include "gtk-utils.h" #include static void quarry_move_number_dialog_init (QuarryMoveNumberDialog *dialog); GType quarry_move_number_dialog_get_type (void) { static GType move_number_dialog_type = 0; if (!move_number_dialog_type) { static const GTypeInfo move_number_dialog_info = { sizeof (QuarryMoveNumberDialogClass), NULL, NULL, NULL, NULL, NULL, sizeof (QuarryMoveNumberDialog), 0, (GInstanceInitFunc) quarry_move_number_dialog_init, NULL }; move_number_dialog_type = g_type_register_static (GTK_TYPE_DIALOG, "QuarryMoveNumberDialog", &move_number_dialog_info, 0); } return move_number_dialog_type; } static void quarry_move_number_dialog_init (QuarryMoveNumberDialog *dialog) { static const gchar *radio_labels[2] = { N_("Use se_quential move number"), N_("_Set specific move number:") }; GtkWidget **radio_buttons = (GtkWidget **) dialog->toggle_buttons; GtkWidget *spin_button; GtkWidget *hbox; GtkWidget *vbox; gtk_utils_create_radio_chain (radio_buttons, radio_labels, 2); dialog->move_number_adjustment = ((GtkAdjustment *) gtk_adjustment_new (1.0, 1.0, G_MAXINT, 1.0, 10.0, 0.0)); spin_button = gtk_utils_create_spin_button (dialog->move_number_adjustment, 0.0, 0, TRUE); gtk_utils_set_sensitive_on_toggle (dialog->toggle_buttons[1], spin_button, FALSE); hbox = gtk_utils_pack_in_box (GTK_TYPE_HBOX, QUARRY_SPACING, radio_buttons[1], GTK_UTILS_FILL, spin_button, GTK_UTILS_FILL, NULL); vbox = gtk_utils_pack_in_box (GTK_TYPE_VBOX, QUARRY_SPACING_SMALL, radio_buttons[0], GTK_UTILS_FILL, hbox, GTK_UTILS_FILL, NULL); gtk_widget_show_all (vbox); gtk_utils_standardize_dialog (&dialog->dialog, vbox); gtk_dialog_add_buttons (&dialog->dialog, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OK, GTK_RESPONSE_OK, NULL); gtk_dialog_set_default_response (&dialog->dialog, GTK_RESPONSE_OK); gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE); dialog->sequential_move_number = 1; } GtkWidget * quarry_move_number_dialog_new (void) { return GTK_WIDGET (g_object_new (QUARRY_TYPE_MOVE_NUMBER_DIALOG, NULL)); } gboolean quarry_move_number_dialog_get_use_sequential_move_number (const QuarryMoveNumberDialog *dialog) { g_return_val_if_fail (QUARRY_IS_MOVE_NUMBER_DIALOG (dialog), TRUE); return gtk_toggle_button_get_active (dialog->toggle_buttons[0]); } gint quarry_move_number_dialog_get_specific_move_number (const QuarryMoveNumberDialog *dialog) { g_return_val_if_fail (QUARRY_IS_MOVE_NUMBER_DIALOG (dialog), 1); g_return_val_if_fail ((gtk_toggle_button_get_active (dialog->toggle_buttons[1])), dialog->sequential_move_number); return gtk_adjustment_get_value (dialog->move_number_adjustment); } void quarry_move_number_dialog_set_sequential_move_number (QuarryMoveNumberDialog *dialog, gint move_number) { GtkLabel *label; gchar *text; g_return_if_fail (QUARRY_IS_MOVE_NUMBER_DIALOG (dialog)); g_return_if_fail (move_number >= 0); dialog->sequential_move_number = move_number; text = g_strdup_printf ("%s (%d)", _("Use se_quential move number"), move_number); label = GTK_LABEL (gtk_bin_get_child (GTK_BIN (dialog->toggle_buttons[0]))); gtk_label_set_text_with_mnemonic (label, text); g_free (text); } void quarry_move_number_dialog_set_specific_move_number (QuarryMoveNumberDialog *dialog, gint move_number) { g_return_if_fail (QUARRY_IS_MOVE_NUMBER_DIALOG (dialog)); g_return_if_fail (move_number > 0); gtk_adjustment_set_value (dialog->move_number_adjustment, move_number); } void quarry_move_number_dialog_set_use_sequential_move_number (QuarryMoveNumberDialog *dialog, gboolean use_sequential_move_number) { g_return_if_fail (QUARRY_IS_MOVE_NUMBER_DIALOG (dialog)); if (use_sequential_move_number) { gtk_adjustment_set_value (dialog->move_number_adjustment, dialog->sequential_move_number); gtk_toggle_button_set_active (dialog->toggle_buttons[0], TRUE); } else gtk_toggle_button_set_active (dialog->toggle_buttons[1], TRUE); } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/quarry-save-confirmation-dialog.c0000644000175000017500000001741510524131633022210 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "quarry-save-confirmation-dialog.h" #include "quarry-message-dialog.h" #include #include static void quarry_save_confirmation_dialog_class_init (QuarrySaveConfirmationDialogClass *class); static void quarry_save_confirmation_dialog_init (QuarrySaveConfirmationDialog *dialog); static void quarry_save_confirmation_dialog_finalize (GObject *object); static gboolean update_secondary_text (QuarrySaveConfirmationDialog *dialog); static QuarryMessageDialogClass *parent_class; GType quarry_save_confirmation_dialog_get_type (void) { static GType quarry_save_confirmation_dialog_type = 0; if (!quarry_save_confirmation_dialog_type) { static const GTypeInfo quarry_save_confirmation_dialog_info = { sizeof (QuarrySaveConfirmationDialogClass), NULL, NULL, (GClassInitFunc) quarry_save_confirmation_dialog_class_init, NULL, NULL, sizeof (QuarrySaveConfirmationDialog), 0, (GInstanceInitFunc) quarry_save_confirmation_dialog_init, NULL }; quarry_save_confirmation_dialog_type = g_type_register_static (QUARRY_TYPE_MESSAGE_DIALOG, "QuarrySaveConfirmationDialog", &quarry_save_confirmation_dialog_info, 0); } return quarry_save_confirmation_dialog_type; } static void quarry_save_confirmation_dialog_class_init (QuarrySaveConfirmationDialogClass *class) { parent_class = g_type_class_peek_parent (class); G_OBJECT_CLASS (class)->finalize = quarry_save_confirmation_dialog_finalize; } static void quarry_save_confirmation_dialog_init (QuarrySaveConfirmationDialog *dialog) { gtk_dialog_add_buttons (GTK_DIALOG (dialog), _("Close _without Saving"), GTK_RESPONSE_NO, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, GTK_RESPONSE_YES, NULL); gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_YES); quarry_message_dialog_set_icon (QUARRY_MESSAGE_DIALOG (dialog), GTK_STOCK_DIALOG_WARNING); dialog->timeout_source_id = 0; } static void quarry_save_confirmation_dialog_finalize (GObject *object) { QuarrySaveConfirmationDialog *dialog = QUARRY_SAVE_CONFIRMATION_DIALOG (object); if (dialog->timeout_source_id) g_source_remove (dialog->timeout_source_id); G_OBJECT_CLASS (parent_class)->finalize (object); } GtkWidget * quarry_save_confirmation_dialog_new (GtkWindow *parent, glong time_of_first_modification, const gchar *primary_text_format_string, ...) { GtkWidget *dialog; va_list arguments; va_start (arguments, primary_text_format_string); dialog = quarry_save_confirmation_dialog_new_valist (parent, time_of_first_modification, primary_text_format_string, arguments); va_end (arguments); return dialog; } GtkWidget * quarry_save_confirmation_dialog_new_valist (GtkWindow *parent, glong time_of_first_modification, const gchar *primary_text_format_string, va_list arguments) { QuarrySaveConfirmationDialog *dialog = g_object_new (QUARRY_TYPE_SAVE_CONFIRMATION_DIALOG, NULL); if (parent) { gtk_window_present (parent); gtk_window_set_transient_for (GTK_WINDOW (dialog), parent); } quarry_message_dialog_format_primary_text_valist (QUARRY_MESSAGE_DIALOG (dialog), primary_text_format_string, arguments); dialog->time_of_first_modification = time_of_first_modification; update_secondary_text (dialog); return GTK_WIDGET (dialog); } static gboolean update_secondary_text (QuarrySaveConfirmationDialog *dialog) { GTimeVal current_time; glong num_seconds_elapsed; gchar *secondary_text; g_get_current_time (¤t_time); num_seconds_elapsed = (current_time.tv_sec - dialog->time_of_first_modification); /* The ranges are taken from gedit code. */ if (num_seconds_elapsed < 55) { secondary_text = g_strdup_printf (ngettext ("If you don't save, changes from the last " "%d second will be lost permanently.", "If you don't save, changes from the last " "%d seconds will be lost permanently.", num_seconds_elapsed), (gint) num_seconds_elapsed); } else if (num_seconds_elapsed < 60 + 15) { secondary_text = g_strdup (_("If you don't save, changes from the last " "minute will be discarded.")); } else if (num_seconds_elapsed < 60 + 50) { secondary_text /* TRANSLATORS: Cannot be one minute one second, actually. */ = g_strdup_printf (ngettext ("If you don't save, changes from the last " "minute and %d second will be lost " "permanently.", "If you don't save, changes from the last " "minute and %d seconds will be lost " "permanently.", num_seconds_elapsed - 60), (gint) (num_seconds_elapsed - 60)); } else if (num_seconds_elapsed < 60 * 60) { secondary_text = g_strdup_printf (ngettext ("If you don't save, changes from the last " "%d minute will be lost permanently.", "If you don't save, changes from the last " "%d minutes will be lost permanently.", num_seconds_elapsed / 60), (gint) (num_seconds_elapsed / 60)); } else if (60 * 60 + 5 * 60 <= num_seconds_elapsed && num_seconds_elapsed < 2 * 60 * 60) { /* Between 1:05:00 and 2:00:00. */ gint minutes = (num_seconds_elapsed - 60 * 60) / 60; secondary_text /* TRANSLATORS: Cannot be one hour one minute, actually. */ = g_strdup_printf (ngettext ("If you don't save, changes from the last " "hour and %d minute will be lost " "permanently.", "If you don't save, changes from the last " "hour and %d minutes will be lost " "permanently.", minutes), minutes); } else { secondary_text = g_strdup_printf (ngettext ("If you don't save, changes from the last " "%d hour will be lost permanently.", "If you don't save, changes from the last " "%d hours will be lost permanently.", num_seconds_elapsed / (60 * 60)), (gint) (num_seconds_elapsed / (60 * 60))); } quarry_message_dialog_set_secondary_text (QUARRY_MESSAGE_DIALOG (dialog), secondary_text); if (dialog->timeout_source_id) g_source_remove (dialog->timeout_source_id); /* FIXME: Try adding timeouts for the period the text will change * after, not just one second. */ dialog->timeout_source_id = g_timeout_add (1 * 1000, (GSourceFunc) update_secondary_text, dialog); return FALSE; } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/quarry-stock.c0000644000175000017500000001010110453270356016442 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "quarry-stock.h" #include "utils.h" #include typedef struct _IconMap IconMap; struct _IconMap { const gchar *quarry_stock_id; const gchar *gtk_stock_id; }; static const IconMap quarry_icon_map[] = { { QUARRY_STOCK_NEW_GAME, GTK_STOCK_NEW }, { QUARRY_STOCK_OPEN_GAME_RECORD, GTK_STOCK_OPEN }, { QUARRY_STOCK_BROWSE, GTK_STOCK_OPEN }, { QUARRY_STOCK_CREATE, GTK_STOCK_NEW }, { QUARRY_STOCK_DONE, GTK_STOCK_OK }, { QUARRY_STOCK_GO_TO_NODE, GTK_STOCK_JUMP_TO }, { QUARRY_STOCK_MODIFY, GTK_STOCK_PROPERTIES }, { QUARRY_STOCK_MOVE_UP, GTK_STOCK_GO_UP }, { QUARRY_STOCK_MOVE_DOWN, GTK_STOCK_GO_DOWN }, { QUARRY_STOCK_FIND_NEXT, GTK_STOCK_GO_FORWARD }, { QUARRY_STOCK_OVERWRITE, GTK_STOCK_SAVE }, { QUARRY_STOCK_PLAY, GTK_STOCK_OK }, { QUARRY_STOCK_FIND_PREVIOUS, GTK_STOCK_GO_BACK } }; static GtkStockItem quarry_stock_items[] = { { QUARRY_STOCK_NEW_GAME, N_("_New Game"), 0, 0, NULL }, { QUARRY_STOCK_OPEN_GAME_RECORD, N_("_Open Game Record"), 0, 0, NULL }, { QUARRY_STOCK_BROWSE, N_("_Browse..."), 0, 0, NULL }, { QUARRY_STOCK_CREATE, N_("Crea_te"), 0, 0, NULL }, { QUARRY_STOCK_DONE, N_("_Done"), 0, 0, NULL }, { QUARRY_STOCK_GO_TO_NODE, N_("_Go to Node"), 0, 0, NULL }, { QUARRY_STOCK_MODIFY, N_("_Modify"), 0, 0, NULL }, { QUARRY_STOCK_MOVE_UP, N_("Move _Up"), 0, 0, NULL }, { QUARRY_STOCK_MOVE_DOWN, N_("Move _Down"), 0, 0, NULL }, { QUARRY_STOCK_FIND_NEXT, N_("find|_Next"), 0, 0, NULL }, { QUARRY_STOCK_OVERWRITE, N_("_Overwrite"), 0, 0, NULL }, { QUARRY_STOCK_PLAY, N_("_Play"), 0, 0, NULL }, { QUARRY_STOCK_FIND_PREVIOUS, N_("find|_Previous"), 0, 0, NULL } }; void quarry_stock_init (void) { GtkIconFactory *icon_factory = gtk_icon_factory_new (); int k; for (k = 0; k < (int) (sizeof quarry_icon_map / sizeof (IconMap)); k++) { GtkIconSet *icon_set = gtk_icon_factory_lookup_default (quarry_icon_map[k].gtk_stock_id); gtk_icon_factory_add (icon_factory, quarry_icon_map[k].quarry_stock_id, icon_set); } gtk_icon_factory_add_default (icon_factory); /* Gettextize labels first. */ for (k = 0; k < (int) (sizeof quarry_stock_items / sizeof (GtkStockItem)); k++) { /* Most labels don't have contexts, but that's not a problem: * utils_gettext_with_context() will do the right thing. */ quarry_stock_items[k].label = (gchar *) Q_(quarry_stock_items[k].label); } gtk_stock_add_static (quarry_stock_items, sizeof quarry_stock_items / sizeof (GtkStockItem)); } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/quarry-text-buffer.c0000644000175000017500000010277010456740766017602 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "quarry-text-buffer.h" /* For g_signal_accumulator_true_handled() on old GTK+ versions. */ #include "gtk-utils.h" #include "quarry-marshal.h" #include #include /* NOTE: Keep in sync with operations[]. */ typedef enum { OPERATION_TEXT_DELETION, OPERATION_TEXT_INSERTION, OPERATION_TAG_APPLICATION, OPERATION_TAG_REMOVAL, NUM_TEXT_BUFFER_OPERATIONS } OperationType; typedef struct _QuarryTextBufferOperation QuarryTextBufferOperation; typedef struct _QuarryTextBufferTextOperation QuarryTextBufferTextOperation; typedef struct _QuarryTextBufferTagOperation QuarryTextBufferTagOperation; struct _QuarryTextBufferUndoEntry { QuarryTextBufferOperation *first; QuarryTextBufferOperation *last; gint cursor_offset_before; gint cursor_offset_after; guint state_index_before; guint state_index_after; }; struct _QuarryTextBufferOperation { QuarryTextBufferOperation *next; QuarryTextBufferOperation *previous; OperationType type; }; struct _QuarryTextBufferTextOperation { QuarryTextBufferOperation operation; gchar *text; gint offset; }; struct _QuarryTextBufferTagOperation { QuarryTextBufferOperation operation; GtkTextTag *tag; gint from_offset; gint to_offset; }; typedef struct _QuarryTextBufferOperationInfo QuarryTextBufferOperationInfo; struct _QuarryTextBufferOperationInfo { void (* undo) (const QuarryTextBufferOperation *operation, QuarryTextBuffer *buffer); void (* redo) (const QuarryTextBufferOperation *operation, QuarryTextBuffer *buffer); void (* free_data) (const QuarryTextBufferOperation *operation); }; static void quarry_text_buffer_class_init (QuarryTextBufferClass *class); static void quarry_text_buffer_init (QuarryTextBuffer *buffer); static void quarry_text_buffer_delete_range (GtkTextBuffer *text_buffer, GtkTextIter *from, GtkTextIter *to); static void quarry_text_buffer_insert_text (GtkTextBuffer *text_buffer, GtkTextIter *where, const gchar *text, gint length); static void quarry_text_buffer_apply_tag (GtkTextBuffer *text_buffer, GtkTextTag *tag, const GtkTextIter *from, const GtkTextIter *to); static void quarry_text_buffer_remove_tag (GtkTextBuffer *text_buffer, GtkTextTag *tag, const GtkTextIter *from, const GtkTextIter *to); static void quarry_text_buffer_modification_guard (QuarryTextBuffer *buffer); static void quarry_text_buffer_modified_changed (GtkTextBuffer *text_buffer); static void quarry_text_buffer_begin_user_action (GtkTextBuffer *text_buffer); static void quarry_text_buffer_end_user_action (GtkTextBuffer *text_buffer); static gboolean quarry_text_buffer_receive_undo_entry (QuarryTextBuffer *buffer, QuarryTextBufferUndoEntry *undo_entry); static void quarry_text_buffer_finalize (GObject *object); static void undo_or_redo (QuarryTextBuffer *buffer, const QuarryTextBufferUndoEntry *undo_entry, gboolean undo); static QuarryTextBufferTextOperation * get_text_operation (QuarryTextBufferUndoEntry *undo_entry, gboolean current_entry); static void adjust_operation_offsets (QuarryTextBufferOperation *operation, gint start_offset, gint adjustment); static QuarryTextBufferOperation * add_operation (QuarryTextBufferUndoEntry *undo_entry, OperationType operation_type, gint operation_structure_size); static void delete_operation (QuarryTextBufferUndoEntry *undo_entry, QuarryTextBufferOperation *operation); static void insert_text (const QuarryTextBufferOperation *operation, QuarryTextBuffer *buffer); static void delete_text (const QuarryTextBufferOperation *operation, QuarryTextBuffer *buffer); static void free_text (const QuarryTextBufferOperation *operation); static void apply_tag (const QuarryTextBufferOperation *operation, QuarryTextBuffer *buffer); static void remove_tag (const QuarryTextBufferOperation *operation, QuarryTextBuffer *buffer); /* NOTE: Keep in sync with OperationType. * * We could use a parser similar to one used with SGF undo histories, * but it seems like an overkill in this case. */ static const QuarryTextBufferOperationInfo operations[] = { { insert_text, delete_text, free_text }, { delete_text, insert_text, free_text }, { remove_tag, apply_tag, NULL }, { apply_tag, remove_tag, NULL } }; static GtkTextBufferClass *parent_class; enum { RECEIVE_UNDO_ENTRY, NUM_SIGNALS }; static guint text_buffer_signals[NUM_SIGNALS]; GType quarry_text_buffer_get_type (void) { static GType quarry_text_buffer_type = 0; if (!quarry_text_buffer_type) { static const GTypeInfo quarry_text_buffer_info = { sizeof (QuarryTextBufferClass), NULL, NULL, (GClassInitFunc) quarry_text_buffer_class_init, NULL, NULL, sizeof (QuarryTextBuffer), 1, (GInstanceInitFunc) quarry_text_buffer_init, NULL }; quarry_text_buffer_type = g_type_register_static (GTK_TYPE_TEXT_BUFFER, "QuarryTextBuffer", &quarry_text_buffer_info, 0); } return quarry_text_buffer_type; } static void quarry_text_buffer_class_init (QuarryTextBufferClass *class) { GtkTextBufferClass *text_buffer_class = GTK_TEXT_BUFFER_CLASS (class); parent_class = g_type_class_peek_parent (class); G_OBJECT_CLASS (class)->finalize = quarry_text_buffer_finalize; text_buffer_class->delete_range = quarry_text_buffer_delete_range; text_buffer_class->insert_text = quarry_text_buffer_insert_text; text_buffer_class->apply_tag = quarry_text_buffer_apply_tag; text_buffer_class->remove_tag = quarry_text_buffer_remove_tag; text_buffer_class->modified_changed = quarry_text_buffer_modified_changed; /* FIXME: Is it needed? */ #if 0 text_buffer_class->mark_deleted = quarry_text_buffer_mark_deleted; text_buffer_class->mark_set = quarry_text_buffer_mark_set; #endif text_buffer_class->begin_user_action = quarry_text_buffer_begin_user_action; text_buffer_class->end_user_action = quarry_text_buffer_end_user_action; class->receive_undo_entry = quarry_text_buffer_receive_undo_entry; text_buffer_signals[RECEIVE_UNDO_ENTRY] = g_signal_new ("receive-undo-entry", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (QuarryTextBufferClass, receive_undo_entry), g_signal_accumulator_true_handled, NULL, quarry_marshal_BOOLEAN__POINTER, G_TYPE_BOOLEAN, 1, G_TYPE_POINTER); } static void quarry_text_buffer_init (QuarryTextBuffer *buffer) { buffer->current_undo_entry = NULL; buffer->state_index = 0; buffer->last_assigned_state_index = 0; buffer->unmodified_state_index = 0; buffer->is_undoing_or_redoing = FALSE; buffer->block_all_modifications = FALSE; buffer->last_modification_time = 0; buffer->previous_modification_time = 0; /* This handler ensures that all modifications of the buffer that * occur during undo and redo operations are part of that operation * and not initiated by a user handler. In other words, it prevents * accidental spoiling of the buffer during undoing or redoing. */ g_signal_connect (buffer, "delete-range", G_CALLBACK (quarry_text_buffer_modification_guard), NULL); g_signal_connect (buffer, "insert-text", G_CALLBACK (quarry_text_buffer_modification_guard), NULL); g_signal_connect (buffer, "apply-tag", G_CALLBACK (quarry_text_buffer_modification_guard), NULL); g_signal_connect (buffer, "remove-tag", G_CALLBACK (quarry_text_buffer_modification_guard), NULL); } GtkTextBuffer * quarry_text_buffer_new (GtkTextTagTable *tag_table) { return GTK_TEXT_BUFFER (g_object_new (QUARRY_TYPE_TEXT_BUFFER, "tag-table", tag_table, NULL)); } static void quarry_text_buffer_delete_range (GtkTextBuffer *text_buffer, GtkTextIter *from, GtkTextIter *to) { QuarryTextBuffer *buffer = QUARRY_TEXT_BUFFER (text_buffer); if (buffer->current_undo_entry) { QuarryTextBufferTextOperation *operation; /* This is the simplest way to store all tags data in the undo * entry: quarry_text_buffer_remove_tag() will be called as * needed. */ gtk_text_buffer_remove_all_tags (text_buffer, from, to); operation = ((QuarryTextBufferTextOperation *) add_operation (buffer->current_undo_entry, OPERATION_TEXT_DELETION, sizeof (QuarryTextBufferTextOperation))); operation->text = gtk_text_iter_get_text (from, to); operation->offset = gtk_text_iter_get_offset (from); } if (buffer->is_undoing_or_redoing) buffer->state_index = ++buffer->last_assigned_state_index; parent_class->delete_range (text_buffer, from, to); buffer->block_all_modifications = FALSE; } static void quarry_text_buffer_insert_text (GtkTextBuffer *text_buffer, GtkTextIter *where, const gchar *text, gint length) { QuarryTextBuffer *buffer = QUARRY_TEXT_BUFFER (text_buffer); gint offset = 0; if (buffer->current_undo_entry) { QuarryTextBufferTextOperation *operation = ((QuarryTextBufferTextOperation *) add_operation (buffer->current_undo_entry, OPERATION_TEXT_INSERTION, sizeof (QuarryTextBufferTextOperation))); offset = gtk_text_iter_get_offset (where); operation->text = g_strndup (text, length); operation->offset = offset; } if (!buffer->is_undoing_or_redoing) buffer->state_index = ++buffer->last_assigned_state_index; if (length < 0) length = strlen (text); parent_class->insert_text (text_buffer, where, text, length); if (buffer->current_undo_entry) { GtkTextIter start_iterator; QuarryTextBufferOperation *operation; /* This is the simplest way to store all inherited tags data in * the undo entry: quarry_text_buffer_remove_tag() will be called * as needed. */ gtk_text_buffer_get_iter_at_offset (text_buffer, &start_iterator, offset); gtk_text_buffer_remove_all_tags (text_buffer, &start_iterator, where); /* Reapply tags as needed and fix operation type. */ for (operation = buffer->current_undo_entry->last; operation->type == OPERATION_TAG_REMOVAL; operation = operation->previous) { operation->type = OPERATION_TAG_APPLICATION; operations[OPERATION_TAG_APPLICATION].redo (operation, buffer); } } buffer->block_all_modifications = FALSE; } static void quarry_text_buffer_apply_tag (GtkTextBuffer *text_buffer, GtkTextTag *tag, const GtkTextIter *from, const GtkTextIter *to) { QuarryTextBuffer *buffer = QUARRY_TEXT_BUFFER (text_buffer); if (buffer->current_undo_entry) { QuarryTextBufferTagOperation *operation = ((QuarryTextBufferTagOperation *) add_operation (buffer->current_undo_entry, OPERATION_TAG_APPLICATION, sizeof (QuarryTextBufferTagOperation))); operation->tag = tag; operation->from_offset = gtk_text_iter_get_offset (from); operation->to_offset = gtk_text_iter_get_offset (to); } if (!buffer->is_undoing_or_redoing) buffer->state_index = ++buffer->last_assigned_state_index; parent_class->apply_tag (text_buffer, tag, from, to); buffer->block_all_modifications = FALSE; } static void quarry_text_buffer_remove_tag (GtkTextBuffer *text_buffer, GtkTextTag *tag, const GtkTextIter *from, const GtkTextIter *to) { QuarryTextBuffer *buffer = QUARRY_TEXT_BUFFER (text_buffer); if (buffer->current_undo_entry) { QuarryTextBufferTagOperation *operation = ((QuarryTextBufferTagOperation *) add_operation (buffer->current_undo_entry, OPERATION_TAG_REMOVAL, sizeof (QuarryTextBufferTagOperation))); operation->tag = tag; operation->from_offset = gtk_text_iter_get_offset (from); operation->to_offset = gtk_text_iter_get_offset (to); } if (!buffer->is_undoing_or_redoing) buffer->state_index = ++buffer->last_assigned_state_index; parent_class->remove_tag (text_buffer, tag, from, to); buffer->block_all_modifications = FALSE; } static void quarry_text_buffer_modification_guard (QuarryTextBuffer *buffer) { if (buffer->is_undoing_or_redoing) { if (buffer->block_all_modifications) { GSignalInvocationHint *signal_data = g_signal_get_invocation_hint (buffer); g_signal_stop_emission (buffer, signal_data->signal_id, signal_data->detail); } else { /* Entering modification signal invocation initiated by undo or * redo command. Block all other modifications until this one * is performed (essentially, we block all modifications during * execution of undo/redo commands except for those that * directly come from undo entries.) */ buffer->block_all_modifications = TRUE; } } } static void quarry_text_buffer_modified_changed (GtkTextBuffer *text_buffer) { QuarryTextBuffer *buffer = QUARRY_TEXT_BUFFER (text_buffer); if (gtk_text_buffer_get_modified (text_buffer)) { if (buffer->state_index == buffer->unmodified_state_index) { /* The current state is explicitly set to `modified.' Assume * there is no unmodified state at all. */ buffer->unmodified_state_index = G_MAXUINT; } } else { /* The current state is declared to be unmodified. Or maybe we * just returned to an unmodified state (in this case the below * operator does nothing anyway.) */ buffer->unmodified_state_index = buffer->state_index; } if (parent_class->modified_changed) parent_class->modified_changed (text_buffer); } static void quarry_text_buffer_begin_user_action (GtkTextBuffer *text_buffer) { QuarryTextBuffer *buffer = QUARRY_TEXT_BUFFER (text_buffer); GtkTextIter cursor_iterator; GTimeVal current_time; if (!buffer->current_undo_entry) { gtk_text_buffer_get_iter_at_mark (text_buffer, &cursor_iterator, gtk_text_buffer_get_insert (text_buffer)); buffer->current_undo_entry = quarry_text_buffer_undo_entry_new (); buffer->current_undo_entry->cursor_offset_before = gtk_text_iter_get_offset (&cursor_iterator); buffer->current_undo_entry->state_index_before = buffer->state_index; g_get_current_time (¤t_time); buffer->previous_modification_time = buffer->last_modification_time; buffer->last_modification_time = current_time.tv_sec; } else g_critical ("inconsistent text buffer state..."); if (parent_class->begin_user_action) parent_class->begin_user_action (text_buffer); } static void quarry_text_buffer_end_user_action (GtkTextBuffer *text_buffer) { QuarryTextBuffer *buffer = QUARRY_TEXT_BUFFER (text_buffer); if (buffer->current_undo_entry) { if (0&&quarry_text_buffer_undo_entry_is_empty (buffer->current_undo_entry)) quarry_text_buffer_undo_entry_delete (buffer->current_undo_entry); else { GtkTextIter cursor_iterator; /* Actually, we know that the result will be TRUE and don't * really care, but GLib doesn't allow passing NULL for result * value location. */ gboolean result; gtk_text_buffer_get_iter_at_mark (text_buffer, &cursor_iterator, (gtk_text_buffer_get_insert (text_buffer))); buffer->current_undo_entry->cursor_offset_after = gtk_text_iter_get_offset (&cursor_iterator); buffer->current_undo_entry->state_index_after = buffer->state_index; g_signal_emit (buffer, text_buffer_signals[RECEIVE_UNDO_ENTRY], 0, buffer->current_undo_entry, &result); } buffer->current_undo_entry = NULL; } if (parent_class->end_user_action) parent_class->end_user_action (text_buffer); } static gboolean quarry_text_buffer_receive_undo_entry (QuarryTextBuffer *buffer, QuarryTextBufferUndoEntry *undo_entry) { UNUSED (buffer); /* If this gets called, it means nobody cared for the entry. Since * we don't maintain an undo history here, just delete the entry. */ quarry_text_buffer_undo_entry_delete (undo_entry); return TRUE; } static void quarry_text_buffer_finalize (GObject *object) { QuarryTextBufferUndoEntry *undo_entry = QUARRY_TEXT_BUFFER (object)->current_undo_entry; if (undo_entry) quarry_text_buffer_undo_entry_delete (undo_entry); } gboolean quarry_text_buffer_is_undoing_or_redoing (const QuarryTextBuffer *buffer) { g_return_val_if_fail (QUARRY_IS_TEXT_BUFFER (buffer), FALSE); return QUARRY_TEXT_BUFFER (buffer)->is_undoing_or_redoing; } void quarry_text_buffer_undo (QuarryTextBuffer *buffer, const QuarryTextBufferUndoEntry *undo_entry) { undo_or_redo (buffer, undo_entry, TRUE); } void quarry_text_buffer_redo (QuarryTextBuffer *buffer, const QuarryTextBufferUndoEntry *undo_entry) { undo_or_redo (buffer, undo_entry, FALSE); } static void undo_or_redo (QuarryTextBuffer *buffer, const QuarryTextBufferUndoEntry *undo_entry, gboolean undo) { GtkTextIter cursor_iterator; const QuarryTextBufferOperation *operation; g_return_if_fail (QUARRY_IS_TEXT_BUFFER (buffer)); g_return_if_fail (!buffer->current_undo_entry); g_return_if_fail (undo_entry); g_return_if_fail ((undo ? undo_entry->state_index_after : undo_entry->state_index_before) == buffer->state_index); buffer->is_undoing_or_redoing = TRUE; if (undo) { for (operation = undo_entry->last; operation; operation = operation->previous) operations[operation->type].undo (operation, buffer); } else { for (operation = undo_entry->first; operation; operation = operation->next) operations[operation->type].redo (operation, buffer); } buffer->state_index = (undo ? undo_entry->state_index_before : undo_entry->state_index_after); gtk_text_buffer_get_iter_at_offset (&buffer->text_buffer, &cursor_iterator, (undo ? undo_entry->cursor_offset_before : undo_entry->cursor_offset_after)); gtk_text_buffer_place_cursor (&buffer->text_buffer, &cursor_iterator); if (buffer->state_index == buffer->unmodified_state_index) gtk_text_buffer_set_modified (&buffer->text_buffer, FALSE); buffer->is_undoing_or_redoing = FALSE; /* This a semi-hackish way to prevent undo entry combinations after * an undo operation, see quarry_text_buffer_combine_undo_entries(). */ buffer->last_modification_time = 0; } gboolean quarry_text_buffer_combine_undo_entries (QuarryTextBuffer *buffer, QuarryTextBufferUndoEntry *previous_undo_entry, QuarryTextBufferUndoEntry *current_undo_entry) { QuarryTextBufferTextOperation *current_operation; QuarryTextBufferTextOperation *previous_operation; QuarryTextBufferOperation *operation; gchar *combined_text; gint offset_adjustment; g_return_val_if_fail (QUARRY_IS_TEXT_BUFFER (buffer), FALSE); /* Don't combine if the user made a significant pause. Sometimes we * also specifically set things up for this check to fail to inhibit * undo entry combination. */ if (buffer->last_modification_time - buffer->previous_modification_time >= 15) return FALSE; /* Basic checks. */ if (!previous_undo_entry || !current_undo_entry || quarry_text_buffer_undo_entry_is_empty (current_undo_entry) || quarry_text_buffer_undo_entry_is_empty (previous_undo_entry)) return FALSE; /* State checks: can only combine the two latest undo entries. */ if (current_undo_entry->state_index_after != buffer->state_index || (previous_undo_entry->state_index_after != current_undo_entry->state_index_before)) return FALSE; current_operation = get_text_operation (current_undo_entry, TRUE); if (!current_operation) return FALSE; previous_operation = get_text_operation (previous_undo_entry, FALSE); if (!previous_operation) return FALSE; /* Operation types must match. */ if (current_operation->operation.type != previous_operation->operation.type) return FALSE; /* Only work with single character operations. Ideally, should only * count _typed/backspaced/deleted_ characters, but I don't see a * way to determine that. */ if (!*current_operation->text || *g_utf8_next_char (current_operation->text)) return FALSE; /* Probably not ideal, but it seems gedit behaves like this. Don't * combine on the edge of whitespace/non-whitespace. Also, never * combine if either of the characters is `special.' */ switch (g_unichar_type (g_utf8_get_char (current_operation->text))) { case G_UNICODE_CONTROL: case G_UNICODE_FORMAT: case G_UNICODE_UNASSIGNED: case G_UNICODE_PRIVATE_USE: case G_UNICODE_SURROGATE: case G_UNICODE_COMBINING_MARK: case G_UNICODE_ENCLOSING_MARK: case G_UNICODE_NON_SPACING_MARK: case G_UNICODE_LINE_SEPARATOR: case G_UNICODE_PARAGRAPH_SEPARATOR: /* Treat tab as space separator even though it is a control * character in Unicode. */ if (*current_operation->text != '\t') return FALSE; case G_UNICODE_SPACE_SEPARATOR: break; default: { const gchar *previous_character = g_utf8_prev_char (previous_operation->text + strlen (previous_operation->text)); switch (g_unichar_type (g_utf8_get_char (previous_character))) { case G_UNICODE_CONTROL: case G_UNICODE_FORMAT: case G_UNICODE_UNASSIGNED: case G_UNICODE_PRIVATE_USE: case G_UNICODE_SURROGATE: case G_UNICODE_COMBINING_MARK: case G_UNICODE_ENCLOSING_MARK: case G_UNICODE_NON_SPACING_MARK: case G_UNICODE_LINE_SEPARATOR: case G_UNICODE_PARAGRAPH_SEPARATOR: return FALSE; case G_UNICODE_SPACE_SEPARATOR: return FALSE; default: break; } } } if (current_operation->operation.type == OPERATION_TEXT_DELETION) { if (current_operation->offset == previous_operation->offset) { /* Deleting with the Delete key. */ combined_text = g_strconcat (previous_operation->text, current_operation->text, NULL); offset_adjustment = -g_utf8_strlen (previous_operation->text, -1); } else if (current_operation->offset == previous_operation->offset - 1) { /* Deleting with the Backspace key. */ previous_operation->offset--; combined_text = g_strconcat (current_operation->text, previous_operation->text, NULL); offset_adjustment = 0; } else { /* Distant changes, don't combine. */ return FALSE; } g_free (current_operation->text); current_operation->text = combined_text; } else { if (current_operation->offset != (previous_operation->offset + g_utf8_strlen (previous_operation->text, -1))) { /* Distant changes, don't combine.*/ return FALSE; } combined_text = g_strconcat (previous_operation->text, current_operation->text, NULL); offset_adjustment = -1; g_free (previous_operation->text); previous_operation->text = combined_text; } /* Adjust offsets in the passed operations. */ for (operation = previous_operation->operation.next; operation; operation = operation->next) { adjust_operation_offsets (operation, current_operation->offset, offset_adjustment); } for (operation = current_undo_entry->first; operation != ¤t_operation->operation; operation = operation->next) { adjust_operation_offsets (operation, current_operation->offset, offset_adjustment); } previous_undo_entry->cursor_offset_after = current_undo_entry->cursor_offset_after; previous_undo_entry->state_index_after = current_undo_entry->state_index_after; if (current_operation->operation.type == OPERATION_TEXT_DELETION) delete_operation (previous_undo_entry, &previous_operation->operation); else delete_operation (current_undo_entry, ¤t_operation->operation); /* Append all the operations (except for the just removed text one) * from `current_undo_entry' to the end of `previous_undo_entry'. */ if (!quarry_text_buffer_undo_entry_is_empty (current_undo_entry)) { if (quarry_text_buffer_undo_entry_is_empty (previous_undo_entry)) previous_undo_entry->first = current_undo_entry->first; else { previous_undo_entry->last->next = current_undo_entry->first; current_undo_entry->first->previous = previous_undo_entry->last; } previous_undo_entry->last = current_undo_entry->last; } /* Delete the `current_undo_entry'. */ current_undo_entry->first = NULL; current_undo_entry->last = NULL; quarry_text_buffer_undo_entry_delete (current_undo_entry); return TRUE; } void quarry_text_buffer_get_state (QuarryTextBuffer *buffer, QuarryTextBufferState *state) { g_return_if_fail (QUARRY_IS_TEXT_BUFFER (buffer)); g_return_if_fail (state); state->state_index = buffer->state_index; state->unmodified_state_index = buffer->unmodified_state_index; } void quarry_text_buffer_set_state (QuarryTextBuffer *buffer, const QuarryTextBufferState *state) { g_return_if_fail (QUARRY_IS_TEXT_BUFFER (buffer)); g_return_if_fail (state); g_return_if_fail (buffer->current_undo_entry == NULL && !buffer->is_undoing_or_redoing); buffer->state_index = state->state_index; buffer->unmodified_state_index = state->unmodified_state_index; /* This a semi-hackish way to prevent undo entry combinations, see * quarry_text_buffer_combine_undo_entries(). */ buffer->last_modification_time = 0; } /* Return combinable text operation in the `undo_entry'. If * `current_undo_entry' is FAKSE, the entry is allowed to contain one * text operation or text deletion, then removal. Else only single * operation is permitted. */ static QuarryTextBufferTextOperation * get_text_operation (QuarryTextBufferUndoEntry *undo_entry, gboolean current_undo_entry) { QuarryTextBufferOperation *text_operation = NULL; QuarryTextBufferOperation *operation; for (operation = undo_entry->first; operation; operation = operation->next) { if (operation->type == OPERATION_TEXT_DELETION || operation->type == OPERATION_TEXT_INSERTION) { if (text_operation) { if (!current_undo_entry && text_operation->type == OPERATION_TEXT_DELETION && operation->type == OPERATION_TEXT_INSERTION) current_undo_entry = TRUE; else { /* More than one text operation and not * `current_undo_entry'. */ return NULL; } } text_operation = operation; } } return (QuarryTextBufferTextOperation *) text_operation; } static void adjust_operation_offsets (QuarryTextBufferOperation *operation, gint start_offset, gint adjustment) { /* FIXME: I'm not particularly sure that this is correct. It works * for its current usage, but should be verified/fixed if you * call this function from a new context. */ switch (operation->type) { case OPERATION_TEXT_DELETION: case OPERATION_TEXT_INSERTION: { QuarryTextBufferTextOperation *text_operation = (QuarryTextBufferTextOperation *) operation; if (text_operation->offset >= start_offset) text_operation->offset += adjustment; } break; case OPERATION_TAG_APPLICATION: case OPERATION_TAG_REMOVAL: { QuarryTextBufferTagOperation *tag_operation = (QuarryTextBufferTagOperation *) operation; if (tag_operation->to_offset >= start_offset) { tag_operation->to_offset -= adjustment; if (tag_operation->from_offset >= start_offset) tag_operation->from_offset -= adjustment; } } break; default: g_assert_not_reached (); } } QuarryTextBufferUndoEntry * quarry_text_buffer_undo_entry_new (void) { QuarryTextBufferUndoEntry *undo_entry = g_malloc (sizeof (QuarryTextBufferUndoEntry)); undo_entry->first = NULL; undo_entry->last = NULL; return undo_entry; } void quarry_text_buffer_undo_entry_delete (QuarryTextBufferUndoEntry *undo_entry) { QuarryTextBufferOperation *operation; g_return_if_fail (undo_entry); operation = undo_entry->first; while (operation) { QuarryTextBufferOperation *next_operation = operation->next; if (operations[operation->type].free_data) operations[operation->type].free_data (operation); g_free (operation); operation = next_operation; } g_free (undo_entry); } inline gboolean quarry_text_buffer_undo_entry_is_empty (const QuarryTextBufferUndoEntry *undo_entry) { g_return_val_if_fail (undo_entry, TRUE); return undo_entry->first == NULL; } static QuarryTextBufferOperation * add_operation (QuarryTextBufferUndoEntry *undo_entry, OperationType operation_type, gint operation_structure_size) { QuarryTextBufferOperation *operation = g_malloc (operation_structure_size); operation->next = NULL; operation->previous = undo_entry->last; operation->type = operation_type; if (undo_entry->first == NULL) undo_entry->first = operation; else undo_entry->last->next = operation; undo_entry->last = operation; return operation; } static void delete_operation (QuarryTextBufferUndoEntry *undo_entry, QuarryTextBufferOperation *operation) { /* First unlink the operation from the list. */ if (operation->next) operation->next->previous = operation->previous; else undo_entry->last = operation->previous; if (operation->previous) operation->previous->next = operation->next; else undo_entry->first = operation->next; /* And free the allocated memory. */ if (operations[operation->type].free_data) operations[operation->type].free_data (operation); g_free (operation); } static void insert_text (const QuarryTextBufferOperation *operation, QuarryTextBuffer *buffer) { const QuarryTextBufferTextOperation *text_operation = (const QuarryTextBufferTextOperation *) operation; GtkTextIter iterator; GtkTextIter start_iterator; gtk_text_buffer_get_iter_at_offset (&buffer->text_buffer, &iterator, text_operation->offset); gtk_text_buffer_insert (&buffer->text_buffer, &iterator, text_operation->text, -1); /* Note: GTK+ automatically inherits tags from the surrouding text * here. However, this can spoil undo/redo operations, so we make * sure the inserted text is free of tags, which are later applied * from apply_tag() function, if needed. Since there appears to be * no way of inserting text without tag inheriting, we remove the * already inherited tags instead. */ gtk_text_buffer_get_iter_at_offset (&buffer->text_buffer, &start_iterator, text_operation->offset); gtk_text_buffer_remove_all_tags (&buffer->text_buffer, &start_iterator, &iterator); } static void delete_text (const QuarryTextBufferOperation *operation, QuarryTextBuffer *buffer) { const QuarryTextBufferTextOperation *text_operation = (const QuarryTextBufferTextOperation *) operation; int end_offset = (text_operation->offset + g_utf8_strlen (text_operation->text, -1)); GtkTextIter start_iterator; GtkTextIter end_iterator; gtk_text_buffer_get_iter_at_offset (&buffer->text_buffer, &start_iterator, text_operation->offset); gtk_text_buffer_get_iter_at_offset (&buffer->text_buffer, &end_iterator, end_offset); gtk_text_buffer_delete (&buffer->text_buffer, &start_iterator, &end_iterator); } static void free_text (const QuarryTextBufferOperation *operation) { g_free (((QuarryTextBufferTextOperation *) operation)->text); } static void apply_tag (const QuarryTextBufferOperation *operation, QuarryTextBuffer *buffer) { const QuarryTextBufferTagOperation *tag_operation = (const QuarryTextBufferTagOperation *) operation; GtkTextIter from_iterator; GtkTextIter to_iterator; gtk_text_buffer_get_iter_at_offset (&buffer->text_buffer, &from_iterator, tag_operation->from_offset); gtk_text_buffer_get_iter_at_offset (&buffer->text_buffer, &to_iterator, tag_operation->to_offset); gtk_text_buffer_apply_tag (&buffer->text_buffer, tag_operation->tag, &from_iterator, &to_iterator); } static void remove_tag (const QuarryTextBufferOperation *operation, QuarryTextBuffer *buffer) { const QuarryTextBufferTagOperation *tag_operation = (const QuarryTextBufferTagOperation *) operation; GtkTextIter from_iterator; GtkTextIter to_iterator; gtk_text_buffer_get_iter_at_offset (&buffer->text_buffer, &from_iterator, tag_operation->from_offset); gtk_text_buffer_get_iter_at_offset (&buffer->text_buffer, &to_iterator, tag_operation->to_offset); gtk_text_buffer_remove_tag (&buffer->text_buffer, tag_operation->tag, &from_iterator, &to_iterator); } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/quarry-text-view.c0000644000175000017500000001506010371154414017257 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "quarry-text-view.h" #include "gtk-utils.h" #include "quarry-history-text-buffer.h" #include "quarry-marshal.h" #include #include static void quarry_text_view_class_init (QuarryTextViewClass *class); static void quarry_text_view_populate_popup (GtkTextView *text_view, GtkMenu *menu); static void quarry_text_view_undo_real (QuarryTextView *view); static void quarry_text_view_redo_real (QuarryTextView *view); static GtkTextViewClass *parent_class; enum { UNDO, REDO, NUM_SIGNALS }; static guint text_view_signals[NUM_SIGNALS]; GType quarry_text_view_get_type (void) { static GType quarry_text_view_type = 0; if (!quarry_text_view_type) { static const GTypeInfo quarry_text_view_info = { sizeof (QuarryTextViewClass), NULL, NULL, (GClassInitFunc) quarry_text_view_class_init, NULL, NULL, sizeof (QuarryTextView), 0, NULL, NULL }; quarry_text_view_type = g_type_register_static (GTK_TYPE_TEXT_VIEW, "QuarryTextView", &quarry_text_view_info, 0); } return quarry_text_view_type; } static void quarry_text_view_class_init (QuarryTextViewClass *class) { GtkBindingSet *binding_set; parent_class = g_type_class_peek_parent (class); GTK_TEXT_VIEW_CLASS (class)->populate_popup = quarry_text_view_populate_popup; class->undo = quarry_text_view_undo_real; class->redo = quarry_text_view_redo_real; text_view_signals[UNDO] = g_signal_new ("undo", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (QuarryTextViewClass, undo), NULL, NULL, quarry_marshal_VOID__VOID, G_TYPE_NONE, 0); text_view_signals[REDO] = g_signal_new ("redo", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (QuarryTextViewClass, redo), NULL, NULL, quarry_marshal_VOID__VOID, G_TYPE_NONE, 0); binding_set = gtk_binding_set_by_class (class); gtk_binding_entry_add_signal (binding_set, GDK_z, GDK_CONTROL_MASK, "undo", 0); gtk_binding_entry_add_signal (binding_set, GDK_z, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "redo", 0); } GtkWidget * quarry_text_view_new (void) { return quarry_text_view_new_with_buffer (quarry_history_text_buffer_new (NULL)); } GtkWidget * quarry_text_view_new_with_buffer (GtkTextBuffer *buffer) { GtkWidget *widget = GTK_WIDGET (g_object_new (QUARRY_TYPE_TEXT_VIEW, NULL)); gtk_text_view_set_buffer (GTK_TEXT_VIEW (widget), buffer); return widget; } static void quarry_text_view_populate_popup (GtkTextView *text_view, GtkMenu *menu) { GtkTextBuffer *buffer = gtk_text_view_get_buffer (text_view); if (QUARRY_IS_HISTORY_TEXT_BUFFER (buffer)) { QuarryHistoryTextBuffer *history_buffer = QUARRY_HISTORY_TEXT_BUFFER (buffer); GtkMenuShell *menu_shell = GTK_MENU_SHELL (menu); GtkWidget *menu_item; /* `Undo' and `Redo' menu items normally go first, so we are saved * from heuristics for finding a place for them. */ menu_item = gtk_separator_menu_item_new (); gtk_widget_show (menu_item); gtk_menu_shell_prepend (menu_shell, menu_item); menu_item = gtk_image_menu_item_new_from_stock (GTK_STOCK_REDO, NULL); gtk_widget_set_sensitive (menu_item, (quarry_history_text_buffer_can_redo (history_buffer))); gtk_widget_show (menu_item); gtk_menu_shell_prepend (menu_shell, menu_item); g_signal_connect_swapped (menu_item, "activate", G_CALLBACK (quarry_text_view_redo), text_view); menu_item = gtk_image_menu_item_new_from_stock (GTK_STOCK_UNDO, NULL); gtk_widget_set_sensitive (menu_item, (quarry_history_text_buffer_can_undo (history_buffer))); gtk_widget_show (menu_item); gtk_menu_shell_prepend (menu_shell, menu_item); g_signal_connect_swapped (menu_item, "activate", G_CALLBACK (quarry_text_view_undo), text_view); } if (parent_class->populate_popup) parent_class->populate_popup (text_view, menu); } void quarry_text_view_undo (QuarryTextView *view) { g_return_if_fail (QUARRY_IS_TEXT_VIEW (view)); g_signal_emit (view, text_view_signals[UNDO], 0); } void quarry_text_view_redo (QuarryTextView *view) { g_return_if_fail (QUARRY_IS_TEXT_VIEW (view)); g_signal_emit (view, text_view_signals[REDO], 0); } static void quarry_text_view_undo_real (QuarryTextView *view) { GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)); if (QUARRY_IS_HISTORY_TEXT_BUFFER (buffer)) { QuarryHistoryTextBuffer *history_buffer = QUARRY_HISTORY_TEXT_BUFFER (buffer); if (quarry_history_text_buffer_can_undo (history_buffer)) quarry_history_text_buffer_undo (history_buffer); } } static void quarry_text_view_redo_real (QuarryTextView *view) { GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)); if (QUARRY_IS_HISTORY_TEXT_BUFFER (buffer)) { QuarryHistoryTextBuffer *history_buffer = QUARRY_HISTORY_TEXT_BUFFER (buffer); if (quarry_history_text_buffer_can_redo (history_buffer)) quarry_history_text_buffer_redo (history_buffer); } } /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/gtk-add-or-edit-label-dialog.h0000644000175000017500000000576610367245453021222 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef QUARRY_GTK_ADD_OR_EDIT_LABEL_DIALOG_H #define QUARRY_GTK_ADD_OR_EDIT_LABEL_DIALOG_H #include #define GTK_TYPE_ADD_OR_EDIT_LABEL_DIALOG \ (gtk_add_or_edit_label_dialog_get_type ()) #define GTK_ADD_OR_EDIT_LABEL_DIALOG(object) \ GTK_CHECK_CAST ((object), GTK_TYPE_ADD_OR_EDIT_LABEL_DIALOG, \ GtkAddOrEditLabelDialog) #define GTK_ADD_OR_EDIT_LABEL_DIALOG_CLASS(class) \ GTK_CHECK_CLASS_CAST ((class), GTK_TYPE_ADD_OR_EDIT_LABEL_DIALOG, \ GtkAddOrEditLabelDialogClass) #define GTK_IS_ADD_OR_EDIT_LABEL_DIALOG(object) \ GTK_CHECK_TYPE ((object), GTK_TYPE_ADD_OR_EDIT_LABEL_DIALOG) #define GTK_IS_ADD_OR_EDIT_LABEL_DIALOG_CLASS(class) \ GTK_CHECK_CLASS_TYPE ((class), GTK_TYPE_ADD_OR_EDIT_LABEL_DIALOG) #define GTK_ADD_OR_EDIT_LABEL_DIALOG_GET_CLASS(object) \ GTK_CHECK_GET_CLASS ((object), GTK_TYPE_ADD_OR_EDIT_LABEL_DIALOG, \ GtkAddOrEditLabelDialogClass) typedef struct _GtkAddOrEditLabelDialog GtkAddOrEditLabelDialog; typedef struct _GtkAddOrEditLabelDialogClass GtkAddOrEditLabelDialogClass; struct _GtkAddOrEditLabelDialog { GtkDialog dialog; GtkEntry *label_entry; }; struct _GtkAddOrEditLabelDialogClass { GtkDialogClass parent_class; }; GType gtk_add_or_edit_label_dialog_get_type (void); GtkWidget * gtk_add_or_edit_label_dialog_new (void); void gtk_add_or_edit_label_dialog_set_label_text (GtkAddOrEditLabelDialog *dialog, const gchar *label_text); const gchar * gtk_add_or_edit_label_dialog_get_label_text (GtkAddOrEditLabelDialog *dialog); #endif /* QUARRY_GTK_ADD_OR_EDIT_LABEL_DIALOG_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/gtk-clock.h0000644000175000017500000000647710367244226015707 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef QUARRY_GTK_CLOCK_H #define QUARRY_GTK_CLOCK_H #include "time-control.h" #include "quarry.h" #include #define GTK_TYPE_CLOCK (gtk_clock_get_type ()) #define GTK_CLOCK(obj) GTK_CHECK_CAST ((obj), GTK_TYPE_CLOCK, \ GtkClock) #define GTK_CLOCK_CLASS(klass) \ GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_CLOCK, GtkClockClass) #define GTK_IS_CLOCK(obj) GTK_CHECK_TYPE ((obj), GTK_TYPE_CLOCK) #define GTK_IS_CLOCK_CLASS(klass) \ GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_CLOCK) #define GTK_CLOCK_GET_CLASS(obj) \ GTK_CHECK_GET_CLASS ((obj), GTK_TYPE_CLOCK, GtkClockClass) typedef struct _GtkClockSymbolParameters GtkClockSymbolParameters; typedef struct _GtkClock GtkClock; typedef struct _GtkClockClass GtkClockClass; typedef void (* GtkClockOutOfTimeCallback) (GtkClock *clock, gpointer user_data); struct _GtkClockSymbolParameters { gint segment_length; gint segment_thickness; }; struct _GtkClock { GtkWidget widget; GtkClockSymbolParameters normal_symbol_parameters; GtkClockSymbolParameters small_symbol_parameters; gint max_hours_positions; gint max_moves_positions; gint seconds; gint moves; gboolean is_highlighted; const TimeControl *time_control; GSource *time_control_watch_source; GtkClockOutOfTimeCallback out_of_time_callback; gpointer user_data; }; struct _GtkClockClass { GtkWidgetClass parent_class; }; GType gtk_clock_get_type (void); GtkWidget * gtk_clock_new (void); void gtk_clock_set_time (GtkClock *clock, gdouble seconds, gint moves); void gtk_clock_use_time_control (GtkClock *clock, const TimeControl *time_control, GtkClockOutOfTimeCallback out_of_time_callback, gpointer user_data); void gtk_clock_time_control_state_changed (GtkClock *clock); #endif /* QUARRY_GTK_CLOCK_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/gtk-color-button.h0000644000175000017500000001132310237132522017214 0ustar bartbart/* * GTK - The GIMP Toolkit * Copyright (C) 1998, 1999 Red Hat, Inc. * All rights reserved. * * This Library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This Library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with the Gnome Library; see the file COPYING.LIB. If * not, write to the Free Software Foundation, Inc., 51 Franklin * Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* Color picker button for GNOME * * Author: Federico Mena * * Modified by the GTK+ Team and others 2003. See the AUTHORS * file for a list of people on the GTK+ Team. See the ChangeLog * files for a list of changes. These files are distributed with * GTK+ at ftp://ftp.gtk.org/pub/gtk/. */ /* 2005-05-07 Paul Pogonyshev * * Update FSF address in the legal notice above. * * 2004-04-27 Paul Pogonyshev * * Move `GtkColorButtonPrivate' into `GtkColorButton' (apparently * pre-2.4 GLib doesn't have support for privates). * * 2004-04-26 Paul Pogonyshev * * Include into Quarry to backport to pre-2.4 GTK+. Modify to * compile with Quarry. Modify to exclude all declarations if * compiling with GTK+ 2.4 or later. */ #include "gtk-utils.h" #include "quarry.h" #if !GTK_2_4_OR_LATER #ifndef __GTK_COLOR_BUTTON_H__ #define __GTK_COLOR_BUTTON_H__ #include G_BEGIN_DECLS /* The GtkColorSelectionButton widget is a simple color picker in a button. * The button displays a sample of the currently selected color. When * the user clicks on the button, a color selection dialog pops up. * The color picker emits the "color_set" signal when the color is set. */ #define GTK_TYPE_COLOR_BUTTON (gtk_color_button_get_type ()) #define GTK_COLOR_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_COLOR_BUTTON, GtkColorButton)) #define GTK_COLOR_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_COLOR_BUTTON, GtkColorButtonClass)) #define GTK_IS_COLOR_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_COLOR_BUTTON)) #define GTK_IS_COLOR_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_COLOR_BUTTON)) #define GTK_COLOR_BUTTON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_COLOR_BUTTON, GtkColorButtonClass)) typedef struct _GtkColorButtonPrivate GtkColorButtonPrivate; typedef struct _GtkColorButton GtkColorButton; typedef struct _GtkColorButtonClass GtkColorButtonClass; struct _GtkColorButtonPrivate { GdkPixbuf *pixbuf; /* Pixbuf for rendering sample */ GdkGC *gc; /* GC for drawing */ GtkWidget *drawing_area;/* Drawing area for color sample */ GtkWidget *cs_dialog; /* Color selection dialog */ gchar *title; /* Title for the color selection window */ GdkColor color; guint16 alpha; guint use_alpha : 1; /* Use alpha or not */ }; struct _GtkColorButton { GtkButton button; /*< private >*/ GtkColorButtonPrivate *priv; GtkColorButtonPrivate the_priv; }; struct _GtkColorButtonClass { GtkButtonClass parent_class; void (* color_set) (GtkColorButton *cp); /* Padding for future expansion */ void (*_gtk_reserved1) (void); void (*_gtk_reserved2) (void); void (*_gtk_reserved3) (void); void (*_gtk_reserved4) (void); }; GType gtk_color_button_get_type (void) G_GNUC_CONST; GtkWidget *gtk_color_button_new (void); GtkWidget *gtk_color_button_new_with_color (const GdkColor *color); void gtk_color_button_set_color (GtkColorButton *color_button, const GdkColor *color); void gtk_color_button_set_alpha (GtkColorButton *color_button, guint16 alpha); void gtk_color_button_get_color (GtkColorButton *color_button, GdkColor *color); guint16 gtk_color_button_get_alpha (GtkColorButton *color_button); void gtk_color_button_set_use_alpha (GtkColorButton *color_button, gboolean use_alpha); gboolean gtk_color_button_get_use_alpha (GtkColorButton *color_button); void gtk_color_button_set_title (GtkColorButton *color_button, const gchar *title); G_CONST_RETURN gchar *gtk_color_button_get_title (GtkColorButton *color_button); G_END_DECLS #endif /* __GTK_COLOR_BUTTON_H__ */ #endif /* !GTK_2_4_OR_LATER */ quarry-0.2.0/src/gui-gtk/gtk-control-center.h0000644000175000017500000000364310367244460017542 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef QUARRY_GTK_CONTROL_CENTER_H #define QUARRY_GTK_CONTROL_CENTER_H #include "quarry.h" #include void gtk_control_center_present (void); inline void gtk_control_center_window_created (GtkWindow *window); gint gtk_control_center_window_destroyed (const GtkWindow *window); inline void gtk_control_center_new_reason_to_live (void); inline void gtk_control_center_lost_reason_to_live (void); void gtk_control_center_quit (void); #endif /* QUARRY_GTK_CONTROL_CENTER_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/gtk-file-dialog.h0000644000175000017500000000372210376150105016746 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef QUARRY_GTK_FILE_DIALOG_H #define QUARRY_GTK_FILE_DIALOG_H #include "quarry.h" #include GtkWidget * gtk_file_dialog_new (const gchar *title, GtkWindow *parent, gboolean for_opening, const gchar *affirmative_button_text); gchar * gtk_file_dialog_get_filename (GtkWidget *dialog); void gtk_file_dialog_set_filename (GtkWidget *dialog, const gchar *filename); void gtk_file_dialog_set_current_name (GtkWidget *dialog, const gchar *filename); #endif /* QUARRY_GTK_FILE_DIALOG_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/gtk-file-selector.h0000644000175000017500000000577210367244506017347 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef QUARRY_GTK_FILE_SELECTOR_H #define QUARRY_GTK_FILE_SELECTOR_H #include "gtk-utils.h" #include "quarry.h" /* FIXME: Try to do the same with GtkCombo for pre-2.4 GTK+? */ #if GTK_2_4_OR_LATER #include #define GTK_TYPE_FILE_SELECTOR (gtk_file_selector_get_type ()) #define GTK_FILE_SELECTOR(object) \ GTK_CHECK_CAST ((object), GTK_TYPE_FILE_SELECTOR, GtkFileSelector) #define GTK_FILE_SELECTOR_CLASS(class) \ GTK_CHECK_CLASS_CAST ((class), GTK_TYPE_FILE_SELECTOR, \ GtkFileSelectorClass) #define GTK_IS_FILE_SELECTOR(object) \ GTK_CHECK_TYPE ((object), GTK_TYPE_FILE_SELECTOR) #define GTK_IS_FILE_SELECTOR_CLASS(class) \ GTK_CHECK_CLASS_TYPE ((class), GTK_TYPE_FILE_SELECTOR) #define GTK_FILE_SELECTOR_GET_CLASS(object) \ GTK_CHECK_GET_CLASS ((object), GTK_TYPE_FILE_SELECTOR, \ GtkFileSelectorClass) typedef struct _GtkFileSelector GtkFileSelector; typedef struct _GtkFileSelectorClass GtkFileSelectorClass; struct _GtkFileSelector { GtkComboBoxEntry combo_box_entry; GSList *glob_patterns; gchar *last_directory; }; struct _GtkFileSelectorClass { GtkComboBoxEntryClass parent_class; }; GType gtk_file_selector_get_type (void); GtkWidget * gtk_file_selector_new (void); void gtk_file_selector_set_glob_patterns (GtkFileSelector *selector, const gchar *patterns); void gtk_file_selector_set_text (GtkFileSelector *selector, const gchar *text); void gtk_file_selector_repopulate (GtkFileSelector *selector); #endif /* GTK_2_4_OR_LATER */ #endif /* QUARRY_GTK_FILE_SELECTOR_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/gtk-freezable-spin-button.h0000644000175000017500000000655110367244524021025 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef QUARRY_GTK_FREEZABLE_SPIN_BUTTON_H #define QUARRY_GTK_FREEZABLE_SPIN_BUTTON_H #include "quarry.h" #include #define GTK_TYPE_FREEZABLE_SPIN_BUTTON \ (gtk_freezable_spin_button_get_type ()) #define GTK_FREEZABLE_SPIN_BUTTON(object) \ GTK_CHECK_CAST ((object), GTK_TYPE_FREEZABLE_SPIN_BUTTON, \ GtkFreezableSpinButton) #define GTK_TYPE_FREEZABLE_SPIN_BUTTON_CLASS(class) \ GTK_CHECK_CLASS_CAST ((class), GTK_TYPE_FREEZABLE_SPIN_BUTTON, \ GtkFreezableSpinButtonClass) #define GTK_IS_FREEZABLE_SPIN_BUTTON(object) \ GTK_CHECK_TYPE ((object), GTK_TYPE_FREEZABLE_SPIN_BUTTON) #define GTK_IS_FREEZABLE_SPIN_BUTTON_CLASS(class) \ GTK_CHECK_CLASS_TYPE ((class), GTK_TYPE_FREEZABLE_SPIN_BUTTON) #define GTK_FREEZABLE_SPIN_BUTTON_GET_CLASS(object) \ GTK_CHECK_GET_CLASS ((object), GTK_TYPE_FREEZABLE_SPIN_BUTTON, \ GtkFreezableSpinButtonClass) typedef struct _GtkFreezableSpinButton GtkFreezableSpinButton; typedef struct _GtkFreezableSpinButtonClass GtkFreezableSpinButtonClass; struct _GtkFreezableSpinButton { GtkSpinButton spin_button; const gchar *freezing_string; gboolean is_in_output; }; struct _GtkFreezableSpinButtonClass { GtkSpinButtonClass parent_class; }; GtkType gtk_freezable_spin_button_get_type (void); GtkWidget * gtk_freezable_spin_button_new (GtkAdjustment *adjustment, gdouble climb_rate, guint digits); const gchar * gtk_freezable_spin_button_get_freezing_string (GtkFreezableSpinButton *spin_button); void gtk_freezable_spin_button_freeze (GtkFreezableSpinButton *spin_button, const gchar *freezing_string); void gtk_freezable_spin_button_freeze_and_stop_input (GtkFreezableSpinButton *spin_button, const gchar *freezing_string); #define gtk_freezable_spin_button_unfreeze(spin_button) \ gtk_freezable_spin_button_freeze ((spin_button), NULL) #endif /* QUARRY_GTK_FREEZABLE_SPIN_BUTTON_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/gtk-game-info-dialog.h0000644000175000017500000001002310455252540017665 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef QUARRY_GTK_GAME_INFO_DIALOG_H #define QUARRY_GTK_GAME_INFO_DIALOG_H #include "gtk-freezable-spin-button.h" #include "sgf.h" #include "board.h" #include "quarry.h" #include #define GTK_TYPE_GAME_INFO_DIALOG \ (gtk_game_info_dialog_get_type ()) #define GTK_GAME_INFO_DIALOG(object) \ GTK_CHECK_CAST ((object), GTK_TYPE_GAME_INFO_DIALOG, \ GtkGameInfoDialog) #define GTK_GAME_INFO_DIALOG_CLASS(class) \ GTK_CHECK_CLASS_CAST ((class), GTK_TYPE_GAME_INFO_DIALOG, \ GtkGameInfoDialogClass) #define GTK_IS_GAME_INFO_DIALOG(object) \ GTK_CHECK_TYPE ((object), GTK_TYPE_GAME_INFO_DIALOG) #define GTK_IS_GAME_INFO_DIALOG_CLASS(class) \ GTK_CHECK_CLASS_TYPE ((class), GTK_TYPE_GAME_INFO_DIALOG) #define GTK_GAME_INFO_DIALOG_GET_CLASS(object) \ GTK_CHECK_GET_CLASS ((object), GTK_TYPE_GAME_INFO_DIALOG, \ GtkGameInfoDialogClass) typedef struct _GtkGameInfoDialog GtkGameInfoDialog; typedef struct _GtkGameInfoDialogClass GtkGameInfoDialogClass; struct _GtkGameInfoDialog { GtkDialog dialog; SgfGameTree *sgf_tree; SgfNode *sgf_node; SgfUndoHistory *sgf_undo_history; GtkNotebook *pages; GtkEntry *player_names[NUM_COLORS]; GtkEntry *player_teams[NUM_COLORS]; GtkEntry *player_ranks[NUM_COLORS]; GtkEntry *game_name; GtkEntry *place; GtkEntry *date; GtkEntry *event; GtkEntry *round; GtkEntry *rule_set; GtkAdjustment *handicap; GtkFreezableSpinButton *handicap_spin_button; GtkAdjustment *komi; GtkFreezableSpinButton *komi_spin_button; GtkAdjustment *main_time; GtkFreezableSpinButton *main_time_spin_button; GtkEntry *overtime; GtkWidget *handicap_box; GtkWidget *komi_box; GtkEntry *result; GtkEntry *opening; GtkTextBuffer *game_comment; GtkWidget *game_comment_text_view; GtkEntry *copyright; GtkEntry *annotator; GtkEntry *source; GtkEntry *user; void * simple_undo_field; void * simple_redo_field; gchar * simple_redo_value; SgfType modified_property_type; }; struct _GtkGameInfoDialogClass { GtkDialogClass parent_class; void (* property_changed) (GtkGameInfoDialog *game_info_dialog, SgfType sgf_property_type); void (* undo_history_action) (GtkGameInfoDialog *game_info_dialog, gboolean undo); }; GType gtk_game_info_dialog_get_type (void); GtkWidget * gtk_game_info_dialog_new (void); void gtk_game_info_dialog_set_node (GtkGameInfoDialog *dialog, SgfGameTree *sgf_tree, SgfNode *sgf_node); #endif /* QUARRY_GTK_GAME_INFO_DIALOG_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/gtk-games.h0000644000175000017500000000672710376455601015707 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef QUARRY_GTK_GAMES_H #define QUARRY_GTK_GAMES_H #include "gtk-configuration.h" #include "gtp-client.h" #include "board.h" #include "game-info.h" #include "quarry.h" #include /* These two macros don't exactly concern games, but there seem to be * no better place. Define minimal and maximal board sizes so that * there is no chance to conflict with any of the modules. */ #define GTK_MIN_BOARD_SIZE \ MAX (MAX (BOARD_MIN_WIDTH, BOARD_MIN_HEIGHT), \ MAX (SGF_MIN_BOARD_SIZE, GTP_MIN_BOARD_SIZE)) #define GTK_MAX_BOARD_SIZE \ MIN (MIN (BOARD_MAX_WIDTH, BOARD_MAX_HEIGHT), \ MIN (SGF_MAX_BOARD_SIZE, GTP_MAX_BOARD_SIZE)) typedef enum { GTK_GAME_GO, GTK_GAME_AMAZONS, GTK_GAME_REVERSI, NUM_SUPPORTED_GAMES, GTK_GAME_UNSUPPORTED = NUM_SUPPORTED_GAMES, GTK_GAME_ANY = NUM_SUPPORTED_GAMES } GtkGameIndex; extern const gchar *game_labels[NUM_SUPPORTED_GAMES]; extern const gchar *game_rules_labels[NUM_SUPPORTED_GAMES]; extern const Game index_to_game[NUM_SUPPORTED_GAMES]; #define INDEX_TO_GAME_NAME(game_index) \ (game_info[index_to_game[game_index]].name) const gchar * gtk_games_get_capitalized_name (Game game); gboolean gtk_games_engine_supports_game (GtpEngineListItem *engine_data, GtkGameIndex game_index); gint gtk_games_name_to_index (const gchar *game_name, gboolean case_sensitive); GtkGameIndex gtk_games_get_game_index (Game game); GtkAdjustment * gtk_games_create_board_size_adjustment (GtkGameIndex game_index, gint initial_value); GtkWidget * gtk_games_create_board_size_selector_box (GtkGameIndex game_index, GtkAdjustment *adjustment, GtkWidget **board_size_spin_button); GtkAdjustment * gtk_games_create_handicap_adjustment (gint initial_value); GtkAdjustment * gtk_games_create_komi_adjustmet (gdouble initial_value); void gtk_games_set_handicap_adjustment_limits (gint board_width, gint board_height, GtkAdjustment *fixed_handicap_adjustment, GtkAdjustment *free_handicap_adjustment); #endif /* QUARRY_GTK_GAMES_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/gtk-goban.h0000644000175000017500000002543310367244612015672 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef QUARRY_GTK_GOBAN_H #define QUARRY_GTK_GOBAN_H #include "gtk-goban-base.h" #include "gtk-tile-set.h" #include "sgf.h" #include "board.h" #include "quarry.h" #include #define GTK_TYPE_GOBAN (gtk_goban_get_type ()) #define GTK_GOBAN(object) \ GTK_CHECK_CAST ((object), GTK_TYPE_GOBAN, GtkGoban) #define GTK_GOBAN_CLASS(class) \ GTK_CHECK_CLASS_CAST ((class), GTK_TYPE_GOBAN, GtkGobanClass) #define GTK_IS_GOBAN(object) \ GTK_CHECK_TYPE ((object), GTK_TYPE_GOBAN) #define GTK_IS_GOBAN_CLASS(class) \ GTK_CHECK_CLASS_TYPE ((class), GTK_TYPE_GOBAN) #define GTK_GOBAN_GET_CLASS(object) \ (GTK_CHECK_GET_CLASS ((object), GTK_TYPE_GOBAN, GtkGobanClass) typedef struct _GtkGobanPointerData GtkGobanPointerData; typedef struct _GtkGobanClickData GtkGobanClickData; struct _GtkGobanPointerData { gint x; gint y; BoardPositionList *feedback_position_list; GdkModifierType modifiers; gint button; gint press_x; gint press_y; }; struct _GtkGobanClickData { gint x; gint y; gint non_empty_feedback; GdkModifierType modifiers; gint button; }; typedef enum { GOBAN_FEEDBACK_NONE, GOBAN_FEEDBACK_FORCE_TILE_NONE, GOBAN_FEEDBACK_OPAQUE, GOBAN_FEEDBACK_BLACK_OPAQUE = GOBAN_FEEDBACK_OPAQUE + BLACK_INDEX, GOBAN_FEEDBACK_WHITE_OPAQUE = GOBAN_FEEDBACK_OPAQUE + WHITE_INDEX, GOBAN_FEEDBACK_GHOST, GOBAN_FEEDBACK_BLACK_GHOST = GOBAN_FEEDBACK_GHOST + BLACK_INDEX, GOBAN_FEEDBACK_WHITE_GHOST = GOBAN_FEEDBACK_GHOST + WHITE_INDEX, GOBAN_FEEDBACK_GHOSTIFY, GOBAN_FEEDBACK_THICK_GHOST, GOBAN_FEEDBACK_THICK_BLACK_GHOST = (GOBAN_FEEDBACK_THICK_GHOST + BLACK_INDEX), GOBAN_FEEDBACK_THICK_WHITE_GHOST = (GOBAN_FEEDBACK_THICK_GHOST + WHITE_INDEX), GOBAN_FEEDBACK_GHOSTIFY_SLIGHTLY, GOBAN_FEEDBACK_PRESS_DEFAULT, GOBAN_FEEDBACK_MOVE, GOBAN_FEEDBACK_BLACK_MOVE = GOBAN_FEEDBACK_MOVE + BLACK_INDEX, GOBAN_FEEDBACK_WHITE_MOVE = GOBAN_FEEDBACK_MOVE + WHITE_INDEX, GOBAN_FEEDBACK_ADD_OR_REMOVE, GOBAN_FEEDBACK_ADD_BLACK_OR_REMOVE = (GOBAN_FEEDBACK_ADD_OR_REMOVE + BLACK_INDEX), GOBAN_FEEDBACK_ADD_WHITE_OR_REMOVE = (GOBAN_FEEDBACK_ADD_OR_REMOVE + WHITE_INDEX), GOBAN_FEEDBACK_SPECIAL, /* Must be more than enough. */ GOBAN_FEEDBACK_MARKUP_FACTOR = 1 << 8, /* SGF markup feedback. */ GOBAN_FEEDBACK_SGF_FACTOR = 1 << 16, GOBAN_FEEDBACK_SGF_NONE = 0, GOBAN_FEEDBACK_SGF_TILE_BASE, GOBAN_FEEDBACK_SGF_OPAQUE = (GOBAN_FEEDBACK_SGF_TILE_BASE + SGF_MARKUP_OPAQUE), GOBAN_FEEDBACK_SGF_CROSS_OPAQUE = (GOBAN_FEEDBACK_SGF_OPAQUE + SGF_MARKUP_CROSS), GOBAN_FEEDBACK_SGF_CIRCLE_OPAQUE = (GOBAN_FEEDBACK_SGF_OPAQUE + SGF_MARKUP_CIRCLE), GOBAN_FEEDBACK_SGF_SQUARE_OPAQUE = (GOBAN_FEEDBACK_SGF_OPAQUE + SGF_MARKUP_SQUARE), GOBAN_FEEDBACK_SGF_TRIANGLE_OPAQUE = (GOBAN_FEEDBACK_SGF_OPAQUE + SGF_MARKUP_TRIANGLE), GOBAN_FEEDBACK_SGF_SELECTED_OPAQUE = (GOBAN_FEEDBACK_SGF_OPAQUE + SGF_MARKUP_SELECTED), GOBAN_FEEDBACK_SGF_GHOST = (GOBAN_FEEDBACK_SGF_TILE_BASE + SGF_MARKUP_50_TRANSPARENT), GOBAN_FEEDBACK_SGF_CROSS_GHOST = (GOBAN_FEEDBACK_SGF_GHOST + SGF_MARKUP_CROSS), GOBAN_FEEDBACK_SGF_CIRCLE_GHOST = (GOBAN_FEEDBACK_SGF_GHOST + SGF_MARKUP_CIRCLE), GOBAN_FEEDBACK_SGF_SQUARE_GHOST = (GOBAN_FEEDBACK_SGF_GHOST + SGF_MARKUP_SQUARE), GOBAN_FEEDBACK_SGF_TRIANGLE_GHOST = (GOBAN_FEEDBACK_SGF_GHOST + SGF_MARKUP_TRIANGLE), GOBAN_FEEDBACK_SGF_SELECTED_GHOST = (GOBAN_FEEDBACK_SGF_GHOST + SGF_MARKUP_SELECTED), GOBAN_FEEDBACK_SGF_THICK_GHOST = (GOBAN_FEEDBACK_SGF_TILE_BASE + SGF_MARKUP_25_TRANSPARENT), GOBAN_FEEDBACK_SGF_CROSS_THICK_GHOST = (GOBAN_FEEDBACK_SGF_THICK_GHOST + SGF_MARKUP_CROSS), GOBAN_FEEDBACK_SGF_CIRCLE_THICK_GHOST = (GOBAN_FEEDBACK_SGF_THICK_GHOST + SGF_MARKUP_CIRCLE), GOBAN_FEEDBACK_SGF_SQUARE_THICK_GHOST = (GOBAN_FEEDBACK_SGF_THICK_GHOST + SGF_MARKUP_SQUARE), GOBAN_FEEDBACK_SGF_TRIANGLE_THICK_GHOST = (GOBAN_FEEDBACK_SGF_THICK_GHOST + SGF_MARKUP_TRIANGLE), GOBAN_FEEDBACK_SGF_SELECTED_THICK_GHOST = (GOBAN_FEEDBACK_SGF_THICK_GHOST + SGF_MARKUP_SELECTED), GOBAN_FEEDBACK_SGF_GHOSTIFY = NUM_ALL_SGF_MARKUP_SHADES, GOBAN_FEEDBACK_SGF_GHOSTIFY_SLIGHTLY, /* Masks for the three feedback parts. */ GOBAN_FEEDBACK_GRID_MASK = GOBAN_FEEDBACK_MARKUP_FACTOR - 1, GOBAN_FEEDBACK_MARKUP_MASK = ((GOBAN_FEEDBACK_SGF_FACTOR - 1) ^ GOBAN_FEEDBACK_GRID_MASK), GOBAN_FEEDBACK_SGF_MASK = ~(GOBAN_FEEDBACK_GRID_MASK | GOBAN_FEEDBACK_MARKUP_MASK) } GtkGobanPointerFeedback; /* Note that there _must not_ be zero enumeration element. These * constants are used in `gtk-goban-window.c' in `callback_action' * field of GtkItemFactoryEntry and zero has special meaning in that * context. */ typedef enum { GOBAN_NAVIGATE_BACK = 1, GOBAN_NAVIGATE_BACK_FAST, GOBAN_NAVIGATE_FORWARD, GOBAN_NAVIGATE_FORWARD_FAST, GOBAN_NAVIGATE_PREVIOUS_VARIATION, GOBAN_NAVIGATE_NEXT_VARIATION, GOBAN_NAVIGATE_ROOT, GOBAN_NAVIGATE_VARIATION_END } GtkGobanNavigationCommand; /* Goban markup flags controlling appearance of stones in marked * positions. Tiles are enumerated in `gui-utils/tile-set.h'. */ #if NUM_TILES >= 1 << 4 #error Too many tiles, need to adjust GOBAN_MARKUP_* flags. #endif enum { GOBAN_TILE_DONT_CHANGE = NUM_TILES, GOBAN_MARKUP_GHOSTIFY = 1 << 4, GOBAN_MARKUP_GHOSTIFY_SLIGHTLY = 1 << 5, GOBAN_MARKUP_GHOSTIFY_SGF_MARKUP = 1 << 6, GOBAN_MARKUP_GHOSTIFY_SGF_MARKUP_SLIGHTLY = 1 << 7, GOBAN_MARKUP_GRID_FLAGS_MASK = (GOBAN_MARKUP_GHOSTIFY | GOBAN_MARKUP_GHOSTIFY_SLIGHTLY), GOBAN_MARKUP_SGF_FLAGS_MASK = (GOBAN_MARKUP_GHOSTIFY_SGF_MARKUP | GOBAN_MARKUP_GHOSTIFY_SGF_MARKUP_SLIGHTLY), GOBAN_MARKUP_FLAGS_MASK = (GOBAN_MARKUP_GRID_FLAGS_MASK | GOBAN_MARKUP_SGF_FLAGS_MASK), GOBAN_MARKUP_TILE_MASK = ~GOBAN_MARKUP_FLAGS_MASK }; enum { GOBAN_SGF_MARKUP_TILE_DONT_CHANGE = NUM_ALL_SGF_MARKUP_SHADES, }; enum { LABEL_25_TRANSPARENT, LABEL_50_TRANSPARENT, NUM_LABEL_GHOST_LEVELS }; #define NUM_OVERLAYS 4 #define FEEDBACK_OVERLAY (NUM_OVERLAYS - 1) typedef struct _GtkGoban GtkGoban; typedef struct _GtkGobanClass GtkGobanClass; struct _GtkGoban { GtkGobanBase base; int width; int height; char grid[BOARD_GRID_SIZE]; char goban_markup[BOARD_GRID_SIZE]; char sgf_markup[BOARD_GRID_SIZE]; gchar *sgf_labels[BOARD_GRID_SIZE]; BoardPositionList *overlay_positon_lists[NUM_OVERLAYS]; char *overlay_contents[NUM_OVERLAYS]; int last_move_pos; gint font_size; gint character_height; gint digit_width; gint left_margin; gint right_margin; gint top_margin; gint bottom_margin; gint first_cell_center_x; gint first_cell_center_y; gint coordinates_x_left; gint coordinates_x_right; gint coordinates_y_side; gint coordinates_y_top; gint coordinates_y_bottom; int num_hoshi_points; BoardPoint hoshi_points[9]; GtkMainTileSet *small_tile_set; GObject *checkerboard_pattern_object; gchar *label_feedback_text; GdkPixbuf *label_text_pixbuf; GdkPixbuf *label_ghost_pixbufs[NUM_LABEL_GHOST_LEVELS] [NUM_SGF_MARKUP_BACKGROUNDS]; int pointer_x; int pointer_y; int feedback_tile; int non_empty_feedback; int label_feedback_pos; int label_feedback_ghost_level; GdkModifierType modifiers; unsigned int button_pressed; gint press_x; gint press_y; gboolean anti_slip_disabled; GdkModifierType press_modifiers; int feedback_tile_at_press; }; struct _GtkGobanClass { GtkGobanBaseClass parent_class; GtkGobanPointerFeedback (* pointer_moved) (GtkGoban *goban, GtkGobanPointerData *data); void (* click_canceled) (GtkGoban *goban); void (* goban_clicked) (GtkGoban *goban, GtkGobanClickData *data); void (* navigate) (GtkGoban *goban, GtkGobanNavigationCommand command); }; #define KEEP_SGF_LABELS ((const SgfLabelList *) -1) GType gtk_goban_get_type (void); GtkWidget * gtk_goban_new (void); void gtk_goban_set_parameters (GtkGoban *goban, Game game, int width, int height); void gtk_goban_update (GtkGoban *goban, const char grid[BOARD_GRID_SIZE], const char goban_markup[BOARD_GRID_SIZE], const char sgf_markup[BOARD_GRID_SIZE], const SgfLabelList *sgf_label_list, int last_move_x, int last_move_y); void gtk_goban_force_feedback_poll (GtkGoban *goban); void gtk_goban_set_label_feedback (GtkGoban *goban, int x, int y, const char *label_text, int ghost_level); void gtk_goban_disable_anti_slip_mode (GtkGoban *goban); void gtk_goban_set_overlay_data (GtkGoban *goban, int overlay_index, BoardPositionList *position_list, int tile, int goban_markup_tile, int sgf_markup_tile); void gtk_goban_set_contents (GtkGoban *goban, BoardPositionList *position_list, int grid_contents, int goban_markup_contents, int sgf_markup_contents); int gtk_goban_get_grid_contents (GtkGoban *goban, int x, int y); int gtk_goban_get_sgf_markup_contents (GtkGoban *goban, int x, int y); gint gtk_goban_negotiate_width (GtkWidget *widget, gint height); gint gtk_goban_negotiate_height (GtkWidget *widget, gint width); #endif /* QUARRY_GTK_GOBAN_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/gtk-goban-base.h0000644000175000017500000000570110367244576016607 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef QUARRY_GTK_GOBAN_BASE_H #define QUARRY_GTK_GOBAN_BASE_H #include "gtk-tile-set.h" #include "board.h" #include "quarry.h" #include #define GTK_TYPE_GOBAN_BASE (gtk_goban_base_get_type ()) #define GTK_GOBAN_BASE(object) \ GTK_CHECK_CAST ((object), GTK_TYPE_GOBAN_BASE, GtkGobanBase) #define GTK_GOBAN_BASE_CLASS(class) \ GTK_CHECK_CLASS_CAST ((class), GTK_TYPE_GOBAN_BASE, \ GtkGobanBaseClass) #define GTK_IS_GOBAN_BASE(object) \ GTK_CHECK_TYPE ((object), GTK_TYPE_GOBAN_BASE) #define GTK_IS_GOBAN_BASE_CLASS(class) \ GTK_CHECK_CLASS_TYPE ((class), GTK_TYPE_GOBAN_BASE) #define GTK_GOBAN_BASE_GET_CLASS(object) \ (GTK_CHECK_GET_CLASS ((object), GTK_TYPE_GOBAN_BASE, \ GtkGobanBaseClass) typedef struct _GtkGobanBase GtkGobanBase; typedef struct _GtkGobanBaseClass GtkGobanBaseClass; struct _GtkGobanBase { GtkWidget widget; Game game; gint cell_size; GtkMainTileSet *main_tile_set; GtkSgfMarkupTileSet *sgf_markup_tile_set; PangoFontDescription *font_description; }; struct _GtkGobanBaseClass { GtkWidgetClass parent_class; void (* allocate_screen_resources) (GtkGobanBase *goban_base); void (* free_screen_resources) (GtkGobanBase *goban_base); }; GtkType gtk_goban_base_get_type (void); void gtk_goban_base_update_appearance (Game game); void gtk_goban_base_set_game (GtkGobanBase *goban_base, Game game); void gtk_goban_base_set_cell_size (GtkGobanBase *goban_base, gint cell_size); #endif /* QUARRY_GTK_GOBAN_BASE_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/gtk-goban-window.h0000644000175000017500000001372710453514442017177 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003 Paul Pogonyshev. * * Copyright (C) 2004 Paul Pogonyshev and Martin Holters. * * Copyright (C) 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef QUARRY_GTK_GOBAN_WINDOW_H #define QUARRY_GTK_GOBAN_WINDOW_H #include "gtk-clock.h" #include "gtk-game-info-dialog.h" #include "gtk-goban.h" #include "gtk-sgf-tree-view.h" #include "gtk-progress-dialog.h" #include "quarry-find-dialog.h" #include "time-control.h" #include "gtp-client.h" #include "sgf.h" #include "board.h" #include "quarry.h" #include #define GTK_TYPE_GOBAN_WINDOW (gtk_goban_window_get_type ()) #define GTK_GOBAN_WINDOW(obj) \ GTK_CHECK_CAST ((obj), GTK_TYPE_GOBAN_WINDOW, GtkGobanWindow) #define GTK_GOBAN_WINDOW_CLASS(klass) \ GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_GOBAN_WINDOW, \ GtkGobanWindowClass) #define GTK_IS_GOBAN_WINDOW(obj) \ GTK_CHECK_TYPE ((obj), GTK_TYPE_GOBAN_WINDOW) #define GTK_IS_GOBAN_WINDOW_CLASS(klass) \ GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_GOBAN_WINDOW) #define GTK_GOBAN_WINDOW_GET_CLASS(obj) \ GTK_CHECK_GET_CLASS ((obj), GTK_TYPE_GOBAN_WINDOW, \ GtkGobanWindowClass) enum { SELECTING_QUEEN, MOVING_QUEEN, SHOOTING_ARROW }; typedef struct _GtkGobanWindow GtkGobanWindow; typedef struct _GtkGobanWindowClass GtkGobanWindowClass; struct _GtkGobanWindow { GtkWindow window; GtkItemFactory *item_factory; GtkItemFactory *tools_item_factory; GtkToolbar *main_toolbar; GtkToolbar *editing_toolbar; GtkToolbar *navigation_toolbar; GtkOptionMenu *tools_option_menu; GtkGoban *goban; GtkLabel *player_labels[NUM_COLORS]; GtkLabel *game_specific_info[NUM_COLORS]; GtkClock *clocks[NUM_COLORS]; GtkLabel *move_information_label; GtkWidget *pass_button; GtkWidget *resign_button; GtkWidget *mode_information_vbox; GtkLabel *mode_hint_label; GtkWidget *done_button; GtkWidget *cancel_button; GtkTextView *text_view; GtkTextBuffer *text_buffer; gboolean text_buffer_modified; gboolean node_name_inserted; GtkPaned *vpaned; GtkSgfTreeView *sgf_tree_view; gboolean sgf_tree_view_visibility_locked; Board *board; SgfBoardState sgf_board_state; SgfGameTreeState game_position; SgfBoardState game_position_board_state_holder; gboolean in_game_mode; gint pending_free_handicap; gint num_handicap_stones_placed; GtpClient *players[NUM_COLORS]; gboolean player_initialization_step[NUM_COLORS]; TimeControl *time_controls[NUM_COLORS]; int amazons_move_stage; int amazons_to_x; int amazons_to_y; BoardAmazonsMoveData amazons_move; BoardPositionList *drawn_position_list; int drawing_mode; gboolean updating_set_player_commands; int sgf_markup_type; gchar *next_sgf_label; gint labels_mode; int black_variations[BOARD_GRID_SIZE]; int white_variations[BOARD_GRID_SIZE]; char sgf_markup[BOARD_GRID_SIZE]; char *dead_stones; BoardPositionList *dead_stones_list; int scoring_engine_player; gboolean engine_scoring_cancelled; SgfCollection *sgf_collection; SgfGameTree *current_tree; glong time_of_first_modification; /* NOTE: In file system encoding! */ char *filename; GtkWidget *save_as_dialog; gboolean adjourning_game; SgfNode *last_displayed_node; SgfNode *last_game_info_node; int switching_x; int switching_y; SgfDirection switching_direction; SgfNode *node_to_switch_to; QuarryFindDialog *find_dialog; gchar *text_to_find; gboolean case_sensitive; gboolean whole_words_only; gboolean wrap_around; gboolean search_whole_game_tree; gint search_in; gboolean close_automatically; GtkGameInfoDialog *game_info_dialog; GtkProgressDialog *scoring_progress_dialog; }; struct _GtkGobanWindowClass { GtkWindowClass parent_class; }; GType gtk_goban_window_get_type (void); GtkWidget * gtk_goban_window_new (SgfCollection *sgf_collection, const char *filename); void gtk_goban_window_enter_game_record_mode (GtkGobanWindow *goban_window); void gtk_goban_window_enter_game_mode (GtkGobanWindow *goban_window, GtpClient *black_player, GtpClient *white_player, TimeControl *time_control); void gtk_goban_window_resume_game (GtkGobanWindow *goban_window, GtpClient *black_player, GtpClient *white_player); gboolean gtk_goban_window_stops_closing (GtkGobanWindow *goban_window); #endif /* QUARRY_GTK_GOBAN_WINDOW_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/gtk-go-to-named-node-dialog.h0000644000175000017500000000611410367245467021077 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef QUARRY_GTK_GO_TO_NAMED_NODE_DIALOG_H #define QUARRY_GTK_GO_TO_NAMED_NODE_DIALOG_H #include "gtk-utils.h" #if GTK_2_4_OR_LATER #include "sgf.h" #include #define GTK_TYPE_GO_TO_NAMED_NODE_DIALOG \ (gtk_go_to_named_node_dialog_get_type ()) #define GTK_GO_TO_NAMED_NODE_DIALOG(object) \ GTK_CHECK_CAST ((object), GTK_TYPE_GO_TO_NAMED_NODE_DIALOG, \ GtkGoToNamedNodeDialog) #define GTK_GO_TO_NAMED_NODE_DIALOG_CLASS(class) \ GTK_CHECK_CLASS_CAST ((class), GTK_TYPE_GO_TO_NAMED_NODE_DIALOG, \ GtkGoToNamedNodeDialogClass) #define GTK_IS_GO_TO_NAMED_NODE_DIALOG(object) \ GTK_CHECK_TYPE ((object), GTK_TYPE_GO_TO_NAMED_NODE_DIALOG) #define GTK_IS_GO_TO_NAMED_NODE_DIALOG_CLASS(class) \ GTK_CHECK_CLASS_TYPE ((class), GTK_TYPE_GO_TO_NAMED_NODE_DIALOG) #define GTK_GO_TO_NAMED_NODE_DIALOG_GET_CLASS(object) \ GTK_CHECK_GET_CLASS ((object), GTK_TYPE_GO_TO_NAMED_NODE_DIALOG, \ GtkGoToNamedNodeDialogClass) typedef struct _GtkGoToNamedNodeDialog GtkGoToNamedNodeDialog; typedef struct _GtkGoToNamedNodeDialogClass GtkGoToNamedNodeDialogClass; struct _GtkGoToNamedNodeDialog { GtkDialog dialog; GtkEntryCompletion *entry_completion; GTree *completion_tree; gulong entry_changed_handler_id; GtkTextBuffer *comment_buffer; GtkWidget *comment_widgets; SgfNode *selected_node; }; struct _GtkGoToNamedNodeDialogClass { GtkDialogClass parent_class; }; GType gtk_go_to_named_node_dialog_get_type (void); GtkWidget * gtk_go_to_named_node_dialog_new (SgfGameTree *sgf_tree); #endif /* GTK_2_4_OR_LATER */ #endif /* QUARRY_GTK_GO_TO_NAMED_NODE_DIALOG_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/gtk-gtp-client-interface.h0000644000175000017500000000403710367244673020614 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef QUARRY_GTK_GTP_CLIENT_INTERFACE_H #define QUARRY_GTK_GTP_CLIENT_INTERFACE_H #include "gtp-client.h" #include "quarry.h" #include typedef void (* GtkGtpClientDeletedCallback) (GtpClient *client, GError *shutdown_reason, void *user_data); GtpClient * gtk_create_gtp_client (const gchar *command_line, GtpClientInitializedCallback initialized_callback, GtkGtpClientDeletedCallback deleted_callback, void *user_data, GError **error); gboolean gtk_schedule_gtp_client_deletion (const GtpClient *client); #endif /* QUARRY_GTK_GTP_CLIENT_INTERFACE_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/gtk-help.h0000644000175000017500000000314410367244712015530 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef QUARRY_GTK_HELP_H #define QUARRY_GTK_HELP_H #include "quarry.h" #include void gtk_help_display (const gchar *link_id); #endif /* QUARRY_GTK_HELP_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/gtk-named-vbox.h0000644000175000017500000000524010367244733016642 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef QUARRY_GTK_NAMED_VBOX_H #define QUARRY_GTK_NAMED_VBOX_H #include "quarry.h" #include #define GTK_TYPE_NAMED_VBOX (gtk_named_vbox_get_type ()) #define GTK_NAMED_VBOX(obj) \ GTK_CHECK_CAST ((obj), GTK_TYPE_NAMED_VBOX, GtkNamedVBox) #define GTK_NAMED_VBOX_CLASS(klass) \ GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_NAMED_VBOX, \ GtkNamedVBoxClass) #define GTK_IS_NAMED_VBOX(obj) \ GTK_CHECK_TYPE ((obj), GTK_TYPE_NAMED_VBOX) #define GTK_IS_NAMED_VBOX_CLASS(klass) \ GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_NAMED_VBOX) #define GTK_NAMED_VBOX_GET_CLASS(obj) \ GTK_CHECK_GET_CLASS ((obj), GTK_TYPE_NAMED_VBOX, GtkNamedVBoxClass) typedef struct _GtkNamedVBox GtkNamedVBox; typedef struct _GtkNamedVBoxClass GtkNamedVBoxClass; struct _GtkNamedVBox { GtkVBox vbox; GtkWidget *label; int left_padding; GtkRequisition vbox_requisition; }; struct _GtkNamedVBoxClass { GtkVBoxClass parent_class; }; GType gtk_named_vbox_get_type (void); GtkWidget * gtk_named_vbox_new (const gchar *label_text, gboolean homogeneous, gint spacing); void gtk_named_vbox_set_label_text (GtkNamedVBox *named_vbox, const gchar *label_text); #endif /* QUARRY_GTK_NAMED_VBOX_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/gtk-new-game-dialog.h0000644000175000017500000000703510440041174017525 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef QUARRY_GTK_NEW_GAME_DIALOG_H #define QUARRY_GTK_NEW_GAME_DIALOG_H #include "gtk-games.h" #include "quarry-assistant.h" #include "board.h" #include "quarry.h" #include #define GTK_TYPE_NEW_GAME_DIALOG (gtk_new_game_dialog_get_type ()) #define GTK_NEW_GAME_DIALOG(obj) \ GTK_CHECK_CAST ((obj), GTK_TYPE_NEW_GAME_DIALOG, GtkNewGameDialog) #define GTK_NEW_GAME_DIALOG_CLASS(klass) \ GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_NEW_GAME_DIALOG, \ GtkNewGameDialogClass) #define GTK_IS_NEW_GAME_DIALOG(obj) \ GTK_CHECK_TYPE ((obj), GTK_TYPE_NEW_GAME_DIALOG) #define GTK_IS_NEW_GAME_DIALOG_CLASS(klass) \ GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_NEW_GAME_DIALOG) #define GTK_NEW_GAME_DIALOG_GET_CLASS(obj) \ GTK_CHECK_GET_CLASS ((obj), GTK_TYPE_NEW_GAME_DIALOG, \ GtkNewGameDialogClass) typedef struct _NewGameDialogTimeControlData NewGameDialogTimeControlData; typedef struct _GtkNewGameDialog GtkNewGameDialog; typedef struct _GtkNewGameDialogClass GtkNewGameDialogClass; struct _NewGameDialogTimeControlData { GtkNotebook *notebook; GtkToggleButton *track_total_time_button; GtkAdjustment *game_time_limit; GtkAdjustment *move_time_limit; GtkAdjustment *main_time; GtkAdjustment *overtime_period; GtkAdjustment *moves_per_overtime; }; struct _GtkNewGameDialog { QuarryAssistant assistant; GtkToggleButton *game_radio_buttons[NUM_SUPPORTED_GAMES]; GtkWidget *game_supported_icons[NUM_SUPPORTED_GAMES]; GtkToggleButton *player_radio_buttons[NUM_COLORS][2]; GtkEntry *human_name_entries[NUM_COLORS]; GtkWidget *engine_selectors[NUM_COLORS]; GtkNotebook *games_notebook; GtkAdjustment *board_sizes[NUM_SUPPORTED_GAMES]; GtkToggleButton *handicap_toggle_buttons[2]; GtkAdjustment *handicaps[2]; GtkAdjustment *komi; NewGameDialogTimeControlData time_control_data[NUM_SUPPORTED_GAMES]; GtpClient *players[NUM_COLORS]; }; struct _GtkNewGameDialogClass { QuarryAssistantClass parent_class; }; GType gtk_new_game_dialog_get_type (void); void gtk_new_game_dialog_present (void); #endif /* QUARRY_GTK_NEW_GAME_DIALOG_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/gtk-new-game-record-dialog.h0000644000175000017500000000612610370756360021015 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef QUARRY_GTK_NEW_GAME_RECORD_DIALOG_H #define QUARRY_GTK_NEW_GAME_RECORD_DIALOG_H #include "gtk-freezable-spin-button.h" #include "gtk-games.h" #include "quarry.h" #include #define GTK_TYPE_NEW_GAME_RECORD_DIALOG \ (gtk_new_game_record_dialog_get_type ()) #define GTK_NEW_GAME_RECORD_DIALOG(obj) \ GTK_CHECK_CAST ((obj), GTK_TYPE_NEW_GAME_RECORD_DIALOG, \ GtkNewGameRecordDialog) #define GTK_NEW_GAME_RECORD_DIALOG_CLASS(klass) \ GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_NEW_GAME_RECORD_DIALOG, \ GtkNewGameRecordDialogClass) #define GTK_IS_NEW_GAME_RECORD_DIALOG(obj) \ GTK_CHECK_TYPE ((obj), GTK_TYPE_NEW_GAME_RECORD_DIALOG) #define GTK_IS_NEW_GAME_RECORD_DIALOG_CLASS(klass) \ GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_NEW_GAME_RECORD_DIALOG) #define GTK_NEW_GAME_RECORD_DIALOG_GET_CLASS(obj) \ GTK_CHECK_GET_CLASS ((obj), GTK_TYPE_NEW_GAME_RECORD_DIALOG, \ GtkNewGameRecordDialogClass) typedef struct _GtkNewGameRecordDialog GtkNewGameRecordDialog; typedef struct _GtkNewGameRecordDialogClass GtkNewGameRecordDialogClass; struct _GtkNewGameRecordDialog { GtkDialog dialog; GSList *game_radio_button_group; GtkAdjustment *board_sizes[NUM_SUPPORTED_GAMES]; GtkFreezableSpinButton *handicap_spin_button; GtkToggleButton *place_stones; GtkFreezableSpinButton *komi_spin_button; GtkEntry *white_player; GtkEntry *black_player; GtkEntry *game_name; }; struct _GtkNewGameRecordDialogClass { GtkDialogClass parent_class; }; GType gtk_new_game_record_dialog_get_type (void); void gtk_new_game_record_dialog_present (void); #endif /* QUARRY_GTK_NEW_GAME_RECORD_DIALOG_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/gtk-parser-interface.h0000644000175000017500000000403510367244774020042 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef QUARRY_GTK_PARSER_INTERFACE_H #define QUARRY_GTK_PARSER_INTERFACE_H #include "sgf.h" #include "quarry.h" #include typedef void (* GtkHandleParsedData) (SgfCollection *sgf_collection, SgfErrorList *error_list, const gchar *filename); void gtk_parser_interface_present_default (void); void gtk_parser_interface_present (GtkWindow **dialog_window, const gchar *title, GtkHandleParsedData callback); void gtk_parse_sgf_file (const char *filename, GtkWindow *parent, GtkHandleParsedData callback); #endif /* QUARRY_GTK_PARSER_INTERFACE_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/gtk-preferences.h0000644000175000017500000001004410367245006017073 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef QUARRY_GTK_PREFERENCES_H #define QUARRY_GTK_PREFERENCES_H #include "gtk-configuration.h" #include "gtk-games.h" #include "gui-back-end.h" #include "gtp-client.h" #include "quarry.h" #include enum { PREFERENCES_PAGE_GTK_UI, PREFERENCES_PAGE_GAME_TREE, PREFERENCES_PAGE_GTP_ENGINES, PREFERENCES_PAGE_SGF_SAVING, PREFERENCES_PAGE_GO_BOARD_APPEARANCE, PREFERENCES_PAGE_AMAZONS_BOARD_APPEARANCE, PREFERENCES_PAGE_REVERSI_BOARD_APPEARANCE, NUM_PREFERENCES_DIALOG_PAGES }; typedef void (* GtkEngineChanged) (GtkWidget *selector, gpointer user_data); typedef enum { ENGINES_INSTANTIATED, INSTANTIATION_FAILED, INSTANTIATION_CANCELLED } GtkEnginesInstantiationStatus; typedef void (* GtkEnginesInstantiated) (GtkEnginesInstantiationStatus status, gpointer user_data); typedef struct _GtkEngineChain GtkEngineChain; struct _GtkEngineChain { GtkWindow *parent_window; GtkEnginesInstantiated instantiation_callback; gpointer user_data; GSList *chain_engine_datum; gboolean have_error; }; void gtk_preferences_init (void); void gtk_preferences_dialog_present (gpointer page_to_select); void gtk_preferences_register_main_toolbar (GtkToolbar *toolbar); void gtk_preferences_register_editing_toolbar (GtkToolbar *toolbar); void gtk_preferences_register_navigation_toolbar (GtkToolbar *toolbar); BoardAppearance * game_to_board_appearance_structure (Game game); gboolean gtk_preferences_have_non_hidden_gtp_engine (void); GtpEngineListItem * gtk_preferences_guess_engine_by_name (const gchar *name, GtkGameIndex game_index); GtkWidget * gtk_preferences_create_engine_selector (GtkGameIndex game_index, gboolean only_this_game, const GtpEngineListItem *engine_data, GtkEngineChanged callback, gpointer user_data); void gtk_preferences_set_engine_selector_game_index (GtkWidget *selector, GtkGameIndex game_index); void gtk_preferences_set_engine_selector_selection (GtkWidget *selector, const GtpEngineListItem *engine_data); GtpEngineListItem * gtk_preferences_get_engine_selector_selection (GtkWidget *selector); GtkEngineChain * gtk_preferences_create_engines_instantiation_chain (GtkWindow *parent_window, GtkEnginesInstantiated callback, gpointer user_data); void gtk_preferences_instantiate_selected_engine (GtkEngineChain *engine_chain, GtkWidget *selector, GtpClient **gtp_client); void gtk_preferences_do_instantiate_engines (GtkEngineChain *engine_chain); #endif /* QUARRY_GTK_PREFERENCES_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/gtk-progress-dialog.h0000644000175000017500000000676210367245024017707 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef QUARRY_GTK_PROGRESS_DIALOG_H #define QUARRY_GTK_PROGRESS_DIALOG_H #include "quarry.h" #include #define GTK_TYPE_PROGRESS_DIALOG (gtk_progress_dialog_get_type ()) #define GTK_PROGRESS_DIALOG(obj) \ GTK_CHECK_CAST ((obj), GTK_TYPE_PROGRESS_DIALOG, GtkProgressDialog) #define GTK_PROGRESS_DIALOG_CLASS(klass) \ GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_PROGRESS_DIALOG, \ GtkProgressDialogClass) #define GTK_IS_PROGRESS_DIALOG(obj) \ GTK_CHECK_TYPE ((obj), GTK_TYPE_PROGRESS_DIALOG) #define GTK_IS_PROGRESS_DIALOG_CLASS(klass) \ GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_PROGRESS_DIALOG) #define GTK_PROGRESS_DIALOG_GET_CLASS(obj) \ GTK_CHECK_GET_CLASS ((obj), GTK_TYPE_PROGRESS_DIALOG, \ GtkProgressDialogClass) typedef struct _GtkProgressDialog GtkProgressDialog; typedef struct _GtkProgressDialogClass GtkProgressDialogClass; typedef gboolean (* GtkProgressDialogCallback) (GtkProgressDialog *progress_dialog, gpointer user_data); struct _GtkProgressDialog { GtkDialog dialog; GtkWidget *parent; GtkLabel *label; GtkProgressBar *progress_bar; GtkProgressDialogCallback update_callback; GtkProgressDialogCallback cancel_callback; gpointer user_data; gint last_displayed_percentage; guint timeout_handler_id; const gchar *help_link_id; }; struct _GtkProgressDialogClass { GtkDialogClass parent_class; }; GType gtk_progress_dialog_get_type (void); GtkWidget * gtk_progress_dialog_new (GtkWindow *parent, const gchar *title, const gchar *label_text, GtkProgressDialogCallback update_callback, GtkProgressDialogCallback cancel_callback, gpointer user_data); void gtk_progress_dialog_set_help_link_id (GtkProgressDialog *dialog, const gchar *help_link_id); void gtk_progress_dialog_set_fraction (GtkProgressDialog *progress_dialog, gdouble fraction, const gchar *title_part); void gtk_progress_dialog_recover_parent (GtkProgressDialog *progress_dialog); #endif /* QUARRY_GTK_PROGRESS_DIALOG_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/gtk-qbox.h0000644000175000017500000000530310370756360015551 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef QUARRY_GTK_QBOX_H #define QUARRY_GTK_QBOX_H #include "quarry.h" #include #define GTK_TYPE_QBOX (gtk_qbox_get_type ()) #define GTK_QBOX(obj) GTK_CHECK_CAST ((obj), GTK_TYPE_QBOX, \ GtkQBox) #define GTK_QBOX_CLASS(klass) \ GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_QBOX, GtkQBoxClass) #define GTK_IS_QBOX(obj) GTK_CHECK_TYPE ((obj), GTK_TYPE_QBOX) #define GTK_IS_QBOX_CLASS(klass) \ GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_QBOX) #define GTK_QBOX_GET_CLASS(obj) \ GTK_CHECK_GET_CLASS ((obj), GTK_TYPE_QBOX, GtkQBoxClass) typedef gint (* GtkQBoxCallback) (GtkWidget *widget, gint dimension); typedef struct _GtkQBox GtkQBox; typedef struct _GtkQBoxClass GtkQBoxClass; struct _GtkQBox { GtkBox box; GtkWidget *ruling_widget; GtkQBoxCallback widget_callback; }; struct _GtkQBoxClass { GtkBoxClass parent_class; }; GType gtk_qbox_get_type (void); void gtk_qbox_set_ruling_widget (GtkQBox *qbox, GtkWidget *widget, GtkQBoxCallback widget_callback); #define gtk_qbox_unset_ruling_widget(qbox) \ gtk_qbox_set_ruling_widget ((qbox), NULL, NULL) GtkWidget * gtk_qbox_get_ruling_widget (GtkQBox *qbox); GtkQBoxCallback gtk_qbox_get_ruling_widget_callback (GtkQBox *qbox); #endif /* QUARRY_GTK_QBOX_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/gtk-qhbox.h0000644000175000017500000000454310370756360015726 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef QUARRY_GTK_QHBOX_H #define QUARRY_GTK_QHBOX_H #include "quarry.h" #include "gtk-qbox.h" #define GTK_TYPE_QHBOX (gtk_qhbox_get_type ()) #define GTK_QHBOX(obj) GTK_CHECK_CAST ((obj), GTK_TYPE_QHBOX, \ GtkQHBox) #define GTK_QHBOX_CLASS(klass) \ GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_QHBOX, GtkQHBoxClass) #define GTK_IS_QHBOX(obj) GTK_CHECK_TYPE ((obj), GTK_TYPE_QHBOX) #define GTK_IS_QHBOX_CLASS(klass) \ GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_QHBOX) #define GTK_QHBOX_GET_CLASS(obj) \ GTK_CHECK_GET_CLASS ((obj), GTK_TYPE_QHBOX, GtkQHBoxClass) typedef struct _GtkQHBox GtkQHBox; typedef struct _GtkQHBoxClass GtkQHBoxClass; struct _GtkQHBox { GtkQBox qbox; }; struct _GtkQHBoxClass { GtkQBoxClass parent_class; }; GType gtk_qhbox_get_type (void); GtkWidget * gtk_qhbox_new (gint spacing); gint gtk_qhbox_negotiate_height (GtkWidget *widget, gint width); #endif /* QUARRY_GTK_QHBOX_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/gtk-qvbox.h0000644000175000017500000000454510370756360015746 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef QUARRY_GTK_QVBOX_H #define QUARRY_GTK_QVBOX_H #include "quarry.h" #include "gtk-qbox.h" #define GTK_TYPE_QVBOX (gtk_qvbox_get_type ()) #define GTK_QVBOX(obj) GTK_CHECK_CAST ((obj), GTK_TYPE_QVBOX, \ GtkQVBox) #define GTK_QVBOX_CLASS(klass) \ GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_QVBOX, GtkQVBoxClass) #define GTK_IS_QVBOX(obj) GTK_CHECK_TYPE ((obj), GTK_TYPE_QVBOX) #define GTK_IS_QVBOX_CLASS(klass) \ GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_QVBOX) #define GTK_QVBOX_GET_CLASS(obj) \ GTK_CHECK_GET_CLASS ((obj), GTK_TYPE_QVBOX, GtkQVBoxClass) typedef struct _GtkQVBox GtkQVBox; typedef struct _GtkQVBoxClass GtkQVBoxClass; struct _GtkQVBox { GtkQBox qbox; }; struct _GtkQVBoxClass { GtkQBoxClass parent_class; }; GtkType gtk_qvbox_get_type (void); GtkWidget * gtk_qvbox_new (gint spacing); gint gtk_qvbox_negotiate_width (GtkWidget *widget, gint height); #endif /* QUARRY_GTK_QVBOX_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/gtk-resume-game-dialog.h0000644000175000017500000000314710367245160020245 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef QUARRY_GTK_RESUME_GAME_DIALOG_H #define QUARRY_GTK_RESUME_GAME_DIALOG_H #include "quarry.h" void gtk_resume_game (void); #endif /* QUARRY_GTK_RESUME_GAME_DIALOG_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/gtk-sgf-tree-signal-proxy.h0000644000175000017500000000731010367245511020743 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef QUARRY_GTK_SGF_TREE_SIGNAL_PROXY_H #define QUARRY_GTK_SGF_TREE_SIGNAL_PROXY_H #include "sgf.h" #include #define GTK_TYPE_SGF_TREE_SIGNAL_PROXY \ (gtk_sgf_tree_signal_proxy_get_type ()) #define GTK_SGF_TREE_SIGNAL_PROXY(object) \ GTK_CHECK_CAST ((object), GTK_TYPE_SGF_TREE_SIGNAL_PROXY, \ GtkSgfTreeSignalProxy) #define GTK_SGF_TREE_SIGNAL_PROXY_CLASS(class) \ GTK_CHECK_CLASS_CAST ((class), GTK_TYPE_SGF_TREE_SIGNAL_PROXY, \ GtkSgfTreeSignalProxyClass) #define GTK_IS_SGF_TREE_SIGNAL_PROXY(object) \ GTK_CHECK_TYPE ((object), GTK_TYPE_SGF_TREE_SIGNAL_PROXY) #define GTK_IS_SGF_TREE_SIGNAL_PROXY_CLASS(class) \ GTK_CHECK_CLASS_TYPE ((class), GTK_TYPE_SGF_TREE_SIGNAL_PROXY) #define GTK_SGF_TREE_SIGNAL_PROXY_GET_CLASS(object) \ GTK_CHECK_GET_CLASS ((object), GTK_TYPE_SGF_TREE_SIGNAL_PROXY, \ GtkSgfTreeSignalProxyClass) typedef struct _GtkSgfTreeSignalProxy GtkSgfTreeSignalProxy; typedef struct _GtkSgfTreeSignalProxyClass GtkSgfTreeSignalProxyClass; struct _GtkSgfTreeSignalProxy { GObject object; SgfGameTree *sgf_tree; SgfNode *old_current_node; GSList *state_stack; }; struct _GtkSgfTreeSignalProxyClass { GObjectClass parent_class; void (* about_to_modify_map) (GtkSgfTreeSignalProxy *proxy, SgfGameTree *sgf_tree); void (* about_to_modify_tree) (GtkSgfTreeSignalProxy *proxy, SgfGameTree *sgf_tree); void (* about_to_change_current_node) (GtkSgfTreeSignalProxy *proxy, SgfGameTree *sgf_tree); void (* current_node_changed) (GtkSgfTreeSignalProxy *proxy, SgfGameTree *sgf_tree, SgfNode *old_current_node); void (* tree_modified) (GtkSgfTreeSignalProxy *proxy, SgfGameTree *sgf_tree); void (* map_modified) (GtkSgfTreeSignalProxy *proxy, SgfGameTree *sgf_tree); }; GType gtk_sgf_tree_signal_proxy_get_type (void); GObject * gtk_sgf_tree_signal_proxy_attach (SgfGameTree *sgf_tree); void gtk_sgf_tree_signal_proxy_push_tree_state (SgfGameTree *sgf_tree, const SgfGameTreeState *new_state); void gtk_sgf_tree_signal_proxy_pop_tree_state (SgfGameTree *sgf_tree, SgfGameTreeState *old_state); #define GET_SIGNAL_PROXY(sgf_tree) \ ((GObject *) GTK_SGF_TREE_SIGNAL_PROXY ((sgf_tree)->user_data)) #endif /* QUARRY_GTK_SGF_TREE_SIGNAL_PROXY_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/gtk-sgf-tree-view.h0000644000175000017500000000753110377144703017270 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef QUARRY_GTK_SGF_TREE_VIEW_H #define QUARRY_GTK_SGF_TREE_VIEW_H #include "gtk-goban-base.h" #include "gtk-tile-set.h" #include "sgf.h" #include "board.h" #include "quarry.h" #include #define GTK_TYPE_SGF_TREE_VIEW (gtk_sgf_tree_view_get_type ()) #define GTK_SGF_TREE_VIEW(object) \ GTK_CHECK_CAST ((object), GTK_TYPE_SGF_TREE_VIEW, GtkSgfTreeView) #define GTK_SGF_TREE_VIEW_CLASS(class) \ GTK_CHECK_CLASS_CAST ((class), GTK_TYPE_SGF_TREE_VIEW, \ GtkSgfTreeViewClass) #define GTK_IS_SGF_TREE_VIEW(object) \ GTK_CHECK_TYPE ((object), GTK_TYPE_SGF_TREE_VIEW) #define GTK_IS_SGF_TREE_VIEW_CLASS(class) \ GTK_CHECK_CLASS_TYPE ((class), GTK_TYPE_SGF_TREE_VIEW) #define GTK_SGF_TREE_VIEW_GET_CLASS(object) \ GTK_CHECK_GET_CLASS ((object), GTK_TYPE_SGF_TREE_VIEW, \ GtkSgfTreeViewClass) typedef struct _GtkSgfTreeView GtkSgfTreeView; typedef struct _GtkSgfTreeViewClass GtkSgfTreeViewClass; struct _GtkSgfTreeView { GtkGobanBase base; GdkWindow *output_window; GtkAdjustment *hadjustment; GtkAdjustment *vadjustment; gboolean ignore_adjustment_changes; SgfGameTree *current_tree; gboolean do_track_current_node; gboolean expect_map_modification; gint map_width; gint map_height; gint view_port_x0; gint view_port_y0; gint view_port_x1; gint view_port_y1; SgfNode **view_port_nodes; SgfGameTreeMapLine *view_port_lines; gint num_view_port_lines; char *tile_map; char *sgf_markup_tile_map; unsigned int button_pressed; gint press_x; gint press_y; const SgfNode *last_tooltips_node; }; struct _GtkSgfTreeViewClass { GtkGobanBaseClass parent_class; void (* set_scroll_adjustments) (GtkSgfTreeView *view, GtkAdjustment *hadjustment, GtkAdjustment *vadjustment); void (* sgf_tree_view_clicked) (GtkSgfTreeView *view, SgfNode *sgf_node, gint button_index); }; GType gtk_sgf_tree_view_get_type (void); GtkWidget * gtk_sgf_tree_view_new (void); void gtk_sgf_tree_view_set_sgf_tree (GtkSgfTreeView *view, SgfGameTree *sgf_tree); void gtk_sgf_tree_view_update_view_port (GtkSgfTreeView *view); void gtk_sgf_tree_view_center_on_current_node (GtkSgfTreeView *view); gboolean gtk_sgf_tree_view_get_tooltips_enabled (void); void gtk_sgf_tree_view_set_tooltips_enabled (gboolean enabled); #endif /* QUARRY_GTK_SGF_TREE_VIEW_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/gtk-thread-interface.h0000644000175000017500000000463510367245211020006 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef QUARRY_GTK_THREAD_INTERFACE_H #define QUARRY_GTK_THREAD_INTERFACE_H #include "quarry.h" #include #define THREADS_SUPPORTED (defined(G_THREADS_ENABLED) \ && !defined(G_THREADS_IMPL_NONE)) #if THREADS_SUPPORTED #include "gtk-parser-interface.h" #include "sgf.h" #include typedef void (* ThreadEventCallback) (void *result); typedef struct _ThreadEventData ThreadEventData; struct _ThreadEventData { ThreadEventCallback callback; void *result; }; typedef struct _ParsingThreadData ParsingThreadData; struct _ParsingThreadData { char *filename; SgfCollection *sgf_collection; SgfErrorList *error_list; int file_size; int bytes_parsed; int cancellation_flag; int result; GtkWidget *parent; GtkWidget *progress_dialog; GtkHandleParsedData callback; }; extern GAsyncQueue *thread_events_queue; #endif /* THREADS_SUPPORTED */ #endif /* QUARRY_GTK_THREAD_INTERFACE_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/gtk-tile-set.h0000644000175000017500000000654610367245223016335 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef QUARRY_GTK_TILE_SET_H #define QUARRY_GTK_TILE_SET_H #include "sgf.h" #include "board.h" #include "utils.h" #include "quarry.h" #include #define NUM_SGF_MARKUP_BACKGROUNDS (MAX (BLACK, WHITE) + 1) /* We consider ``last move markup'' a pseudo-SGF markup in the GTK+ * GUI. So, we need to tweak things a little here. */ #define SGF_PSEUDO_MARKUP_LAST_MOVE NUM_SGF_MARKUPS #define NUM_ALL_SGF_MARKUPS (SGF_PSEUDO_MARKUP_LAST_MOVE + 1) #define SGF_MARKUP_OPAQUE 0 #define SGF_MARKUP_25_TRANSPARENT NUM_ALL_SGF_MARKUPS #define SGF_MARKUP_50_TRANSPARENT (SGF_MARKUP_25_TRANSPARENT \ + NUM_ALL_SGF_MARKUPS) #define NUM_ALL_SGF_MARKUP_SHADES (SGF_MARKUP_50_TRANSPARENT \ + NUM_ALL_SGF_MARKUPS) enum { TILE_NONE = EMPTY, STONE_OPAQUE = FIRST_COLOR, BLACK_OPAQUE = STONE_OPAQUE + BLACK_INDEX, WHITE_OPAQUE = STONE_OPAQUE + WHITE_INDEX, TILE_SPECIAL = SPECIAL_ON_GRID_VALUE, STONE_25_TRANSPARENT, BLACK_25_TRANSPARENT = STONE_25_TRANSPARENT + BLACK_INDEX, WHITE_25_TRANSPARENT = STONE_25_TRANSPARENT + WHITE_INDEX, STONE_50_TRANSPARENT, BLACK_50_TRANSPARENT = STONE_50_TRANSPARENT + BLACK_INDEX, WHITE_50_TRANSPARENT = STONE_50_TRANSPARENT + WHITE_INDEX, MIXED_50_TRANSPARENT, NUM_TILES }; typedef struct _GtkMainTileSet GtkMainTileSet; typedef struct _GtkSgfMarkupTileSet GtkSgfMarkupTileSet; struct _GtkMainTileSet { gint tile_size; gint stones_x_offset; gint stones_y_offset; GdkPixbuf *tiles[NUM_TILES]; }; struct _GtkSgfMarkupTileSet { gint tile_size; GdkPixbuf *tiles[NUM_ALL_SGF_MARKUP_SHADES][NUM_SGF_MARKUP_BACKGROUNDS]; }; GtkMainTileSet * gtk_main_tile_set_create_or_reuse (gint tile_size, Game game); GtkSgfMarkupTileSet * gtk_sgf_markup_tile_set_create_or_reuse (gint tile_size, Game game); extern ObjectCache gtk_main_tile_set_cache; extern ObjectCache gtk_sgf_markup_tile_set_cache; #endif /* QUARRY_GTK_TILE_SET_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/gtk-utils.h0000644000175000017500000002471310522173157015742 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef QUARRY_GTK_UTILS_H #define QUARRY_GTK_UTILS_H #include "gtk-freezable-spin-button.h" #include "utils.h" #include "quarry.h" #include #define QUARRY_SPACING_VERY_SMALL 2 #define QUARRY_SPACING_GOBAN_WINDOW 4 #define QUARRY_SPACING_SMALL 6 #define QUARRY_SPACING 12 #define QUARRY_SPACING_BIG 18 #define QUARRY_SPACING_VERY_BIG 24 /* These limits appeared only in GLib 2.4. */ #ifndef G_MAXUINT8 #define G_MAXUINT8 ((guint8) 0xff) #endif #ifndef G_MAXUINT16 #define G_MAXUINT16 ((guint16) 0xffff) #endif #define GTK_2_2_OR_LATER \ (GTK_MAJOR_VERSION >= 2 && GTK_MINOR_VERSION >= 2) #define GTK_2_4_OR_LATER \ (GTK_MAJOR_VERSION >= 2 && GTK_MINOR_VERSION >= 4) #define GTK_2_6_OR_LATER \ (GTK_MAJOR_VERSION >= 2 && GTK_MINOR_VERSION >= 6) #if !GTK_2_2_OR_LATER /* Workaround a function name change between GTK+ 2.0 and GTK+ 2.2. */ #define gdk_draw_pixbuf(drawable, gc, pixbuf, \ src_x, src_y, dest_x, dest_y, width, height, \ dither, x_dither, y_dither) \ gdk_pixbuf_render_to_drawable ((pixbuf), (drawable), (gc), \ (src_x), (src_y), (dest_x), (dest_y), \ (width), (height), \ (dither), (x_dither), (y_dither)) /* Certain functions are not present in GTK+ 2.0 */ #define gtk_window_set_skip_taskbar_hint(window, setting) #define gtk_window_set_skip_pager_hint(window, setting) /* Workaround GTK+ 2.0 focus slipping problem. */ #define gtk_dialog_set_default_response(dialog, response_id) \ gtk_utils_workaround_set_default_response (dialog, response_id) #endif /* not GTK_2_2_OR_LATER */ #if !GTK_2_4_OR_LATER /* The manual doesn't say this, but apparently the function is only * introduced in GTK+ 2.4. */ #define gtk_entry_set_alignment(entry, alignment) #endif #if !GTK_2_4_OR_LATER gboolean g_signal_accumulator_true_handled (GSignalInvocationHint *hint, GValue *return_accumulator, const GValue *handler_return, gpointer user_data); #endif /* Much like g_signal_handlers_block_by_func() and * g_signal_handlers_unblock_by_func(), but don't require to match * data. */ #define gtk_utils_block_signal_handlers(instance, function) \ g_signal_handlers_block_matched ((instance), G_SIGNAL_MATCH_FUNC, \ 0, 0, NULL, (function), NULL) #define gtk_utils_unblock_signal_handlers(instance, function) \ g_signal_handlers_unblock_matched ((instance), G_SIGNAL_MATCH_FUNC, \ 0, 0, NULL, (function), NULL) typedef struct _GtkUtilsBindingInfo GtkUtilsBindingInfo; struct _GtkUtilsBindingInfo { guint keyval; GdkModifierType modifiers; gint signal_parameter; }; typedef enum { RETURN_ACTIVATES_DEFAULT, RETURN_ADVANCES_FOCUS, RETURN_DEFAULT_MODE } GtkUtilsEntryActivationMode; typedef enum { GTK_UTILS_HOMOGENEOUS = 1 << 0, GTK_UTILS_IS_IMPORTANT = 1 << 1, } GtkUtilsToolbarButtonFlags; typedef void (* GtkUtilsToolbarEntryCallback) (gpointer user_data, guint callback_action); typedef struct _GtkUtilsToolbarEntry GtkUtilsToolbarEntry; struct _GtkUtilsToolbarEntry { const gchar *label_text; const gchar *tooltip_text; const gchar *icon_stock_id; GtkUtilsToolbarEntryCallback callback; guint callback_action; }; /* This is the same as the prototype of the `focus-out-event' handler * since this callback should basically do the same job. Note that * `dummy_event' will be `NULL'. */ typedef gboolean (* GtkUtilsBrowsingDoneCallback) (GtkEntry *entry, GdkEventFocus *dummy_event, gpointer user_data); #define GTK_UTILS_EXPAND (1 << 16) #define GTK_UTILS_FILL (1 << 17) #define GTK_UTILS_PACK_DEFAULT (GTK_UTILS_EXPAND | GTK_UTILS_FILL) #define GTK_UTILS_PACK_END (1 << 18) #define GTK_UTILS_PACK_PADDING_MASK 0xFFFF void gtk_utils_add_similar_bindings (GtkBindingSet *binding_set, const gchar *signal_name, GtkUtilsBindingInfo *bindings, gint num_bindings); #if GTK_2_2_OR_LATER void gtk_utils_make_window_only_horizontally_resizable (GtkWindow *window); #else #define gtk_utils_make_window_only_horizontally_resizable(window) void gtk_utils_workaround_set_default_response (GtkDialog *dialog, gint response_id); #endif void gtk_utils_standardize_dialog (GtkDialog *dialog, GtkWidget *contents); GtkWidget * gtk_utils_add_help_button (GtkDialog* dialog); void gtk_utils_show_and_forget_dialog (GtkDialog *dialog); void gtk_utils_null_pointer_on_destroy (GtkWindow **window, gboolean ask_control_center); void gtk_utils_workaround_focus_bug (GtkWindow *window); GtkWidget * gtk_utils_create_titled_page (GtkWidget *contents, const gchar *icon_stock_id, const gchar *title); GtkWidget * gtk_utils_pack_in_box (GType box_type, gint spacing, ...); GtkWidget * gtk_utils_pack_array_in_box (GType box_type, gint spacing, GtkWidget **widgets, gint num_widgets, guint packing_parameters); GtkWidget * gtk_utils_align_widget (GtkWidget *widget, gfloat x_alignment, gfloat y_alignment); GtkWidget * gtk_utils_sink_widget (GtkWidget *widget); GtkWidget * gtk_utils_make_widget_scrollable (GtkWidget *widget, GtkPolicyType hscrollbar_policy, GtkPolicyType vscrollbar_policy); GtkWidget * gtk_utils_create_left_aligned_label (const gchar *label_text); GtkWidget * gtk_utils_create_mnemonic_label (const gchar *label_text, GtkWidget *mnemonic_widget); GtkWidget * gtk_utils_create_entry (const gchar *text, GtkUtilsEntryActivationMode mode); GtkWidget * gtk_utils_create_browse_button (gboolean with_text, GtkWidget *associated_entry, gboolean is_command_line_entry, const gchar *browsing_dialog_caption, GtkUtilsBrowsingDoneCallback callback, gpointer user_data); GtkWidget * gtk_utils_create_spin_button (GtkAdjustment *adjustment, gdouble climb_rate, guint num_digits, gboolean snap_to_ticks); GtkWidget * gtk_utils_create_freezable_spin_button (GtkAdjustment *adjustment, gdouble climb_rate, guint num_digits, gboolean snap_to_ticks); void gtk_utils_convert_to_time_spin_button (GtkSpinButton *spin_button); GtkWidget * gtk_utils_create_time_spin_button (GtkAdjustment *adjustment, gdouble climb_rate); GtkWidget * gtk_utils_create_selector (const gchar **items, gint num_items, gint selected_item); GtkWidget * gtk_utils_create_selector_from_string_list (void *abstract_list, const gchar *selected_item); GtkWidget * gtk_utils_create_invisible_notebook (void); void gtk_utils_create_radio_chain (GtkWidget **radio_buttons, const gchar **label_texts, gint num_radio_buttons); GtkSizeGroup * gtk_utils_create_size_group (GtkSizeGroupMode mode, ...); GtkSizeGroup * gtk_utils_align_left_widgets (GtkContainer *container, GtkSizeGroup *size_group); GtkWidget * gtk_utils_append_toolbar_button (GtkToolbar *toolbar, GtkUtilsToolbarEntry *entry, GtkUtilsToolbarButtonFlags flags, gpointer user_data); void gtk_utils_set_toolbar_buttons_sensitive (GtkToolbar *toolbar, gboolean are_sensitive, ...); #if GTK_2_4_OR_LATER #define gtk_utils_append_toolbar_space(toolbar) \ gtk_toolbar_insert ((toolbar), gtk_separator_tool_item_new (), -1) #else /* not GTK_2_4_OR_LATER */ #define gtk_utils_append_toolbar_space(toolbar) \ gtk_toolbar_append_space (toolbar) /* Not defined in older GTK+ versions. */ #define gtk_toolbar_set_show_arrow(toolbar, show_arrow) #endif /* not GTK_2_4_OR_LATER */ void gtk_utils_set_text_buffer_text (GtkTextBuffer *text_buffer, const gchar *text); #if !GTK_2_4_OR_LATER /* It is recommended to use this function with 2.4 and up. For * earlier versions, we define it ourselves. */ void gtk_text_buffer_select_range (GtkTextBuffer *text_buffer, GtkTextIter *insertion_iterator, GtkTextIter *bound_iterator); #endif gint gtk_utils_get_selected_radio_index (GSList *radio_button_group); void gtk_utils_set_sensitive_on_toggle (GtkToggleButton *toggle_button, GtkWidget *widget, gboolean reverse_meaning); void gtk_utils_set_sensitive_on_input (GtkEntry *entry, GtkWidget *widget); void gtk_utils_freeze_on_empty_input (GtkFreezableSpinButton *freezable_spin_button); void gtk_utils_set_widgets_visible (gboolean visible, ...); void gtk_utils_set_menu_items_sensitive (GtkItemFactory *item_factory, gboolean are_sensitive, ...); void gtk_utils_set_gdk_color (GdkColor *gdk_color, QuarryColor quarry_color); void gtk_utils_set_quarry_color (QuarryColor *quarry_color, const GdkColor *gdk_color); #if GTK_2_4_OR_LATER #define gtk_utils_get_selector_active_item_index(selector) \ gtk_combo_box_get_active (GTK_COMBO_BOX (selector)) #define gtk_utils_set_selector_active_item_index(selector, index) \ gtk_combo_box_set_active (GTK_COMBO_BOX (selector), (index)) #else #define gtk_utils_get_selector_active_item_index(selector) \ gtk_option_menu_get_history (GTK_OPTION_MENU (selector)) #define gtk_utils_set_selector_active_item_index(selector, index) \ gtk_option_menu_set_history (GTK_OPTION_MENU (selector), (index)) #endif #endif /* QUARRY_GTK_UTILS_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/gui-back-end.h0000644000175000017500000000373510367245255016254 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef QUARRY_GTK_GUI_BACK_END_H #define QUARRY_GTK_GUI_BACK_END_H #include "quarry.h" int gui_back_end_init (int *argc, char **argv[]); int gui_back_end_main_default (void); int gui_back_end_main_open_files (int num_files, char **filenames); /* We can't use `gpointer' here, because GTK+ headers are not visible * from `src/' directory. */ void gui_back_end_register_object_to_finalize (void *object); void gui_back_end_register_pointer_to_free (void *pointer); extern const char *user_real_name; #endif /* QUARRY_GTK_GUI_BACK_END_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/quarry-assistant.h0000644000175000017500000000725510440010133017332 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef QUARRY_QUARRY_ASSISTANT_H #define QUARRY_QUARRY_ASSISTANT_H #include "quarry.h" #include #define QUARRY_TYPE_ASSISTANT (quarry_assistant_get_type ()) #define QUARRY_ASSISTANT(object) \ GTK_CHECK_CAST ((object), QUARRY_TYPE_ASSISTANT, QuarryAssistant) #define QUARRY_ASSISTANT_CLASS(class) \ GTK_CHECK_CLASS_CAST ((class), QUARRY_TYPE_ASSISTANT, \ QuarryAssistantClass) #define QUARRY_IS_ASSISTANT(object) \ GTK_CHECK_TYPE ((object), QUARRY_TYPE_ASSISTANT) #define QUARRY_IS_ASSISTANT_CLASS(class) \ GTK_CHECK_CLASS_TYPE ((class), QUARRY_TYPE_ASSISTANT) #define QUARRY_ASSISTANT_GET_CLASS(object) \ GTK_CHECK_GET_CLASS ((object), QUARRY_TYPE_ASSISTANT, \ QuarryAssistantClass) typedef struct _QuarryAssistant QuarryAssistant; typedef struct _QuarryAssistantClass QuarryAssistantClass; struct _QuarryAssistant { GtkDialog dialog; GtkNotebook *notebook; GtkWidget *back_button; GtkWidget *next_button; GtkWidget *finish_button; GtkWidget *help_button; gpointer user_data; }; struct _QuarryAssistantClass { GtkDialogClass parent_class; }; typedef void (* QuarryAssistantPageShownCallback) (gpointer user_data); typedef gboolean (* QuarryAssistantPageAcceptableCallback) (gpointer user_data); typedef const gchar * (* QuarryAssistantPageHelpLinkIDCallback) (gpointer user_data); GType quarry_assistant_get_type (void); GtkWidget * quarry_assistant_new (const gchar *title, gpointer user_data); void quarry_assistant_set_user_data (QuarryAssistant *assistant, gpointer user_data); void quarry_assistant_add_page (QuarryAssistant *assistant, GtkWidget *widget, const gchar *icon_stock_id, const gchar *title, QuarryAssistantPageShownCallback shown_callback, QuarryAssistantPageAcceptableCallback acceptable_callback); void quarry_assistant_set_page_help_link_id (QuarryAssistant *assistant, GtkWidget *page, const gchar *help_link_id); void quarry_assistant_set_page_help_link_id_callback (QuarryAssistant *assistant, GtkWidget *page, QuarryAssistantPageHelpLinkIDCallback callback); void quarry_assistant_set_finish_button (QuarryAssistant *assistant, const gchar *stock_id); #endif /* QUARRY_QUARRY_ASSISTANT_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/quarry-find-dialog.h0000644000175000017500000001166210453527047017520 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef QUARRY_QUARRY_FIND_DIALOG_H #define QUARRY_QUARRY_FIND_DIALOG_H #include "sgf.h" #include "quarry.h" #include #define QUARRY_TYPE_FIND_DIALOG (quarry_find_dialog_get_type ()) #define QUARRY_FIND_DIALOG(object) \ GTK_CHECK_CAST ((object), QUARRY_TYPE_FIND_DIALOG, QuarryFindDialog) #define QUARRY_FIND_DIALOG_CLASS(class) \ GTK_CHECK_CLASS_CAST ((class), QUARRY_TYPE_FIND_DIALOG, \ QuarryFindDialogClass) #define QUARRY_IS_FIND_DIALOG(object) \ GTK_CHECK_TYPE ((object), QUARRY_TYPE_FIND_DIALOG) #define QUARRY_IS_FIND_DIALOG_CLASS(class) \ GTK_CHECK_CLASS_TYPE ((class), QUARRY_TYPE_FIND_DIALOG) #define QUARRY_FIND_DIALOG_GET_CLASS(object) \ GTK_CHECK_GET_CLASS ((object), QUARRY_TYPE_FIND_DIALOG, \ QuarryFindDialogClass) typedef struct _QuarryFindDialog QuarryFindDialog; typedef struct _QuarryFindDialogClass QuarryFindDialogClass; struct _QuarryFindDialog { GtkDialog dialog; GtkEntry *search_for_entry; GtkToggleButton *case_sensitive_toggle_button; GtkToggleButton *wrap_around_toggle_button; GtkToggleButton *whole_words_only_toggle_button; GtkToggleButton *close_automatically_toggle_button; GtkToggleButton *search_current_node_only_toggle_button; GtkToggleButton *search_scope_toggle_buttons[3]; }; struct _QuarryFindDialogClass { GtkDialogClass parent_class; }; typedef enum { QUARRY_FIND_DIALOG_FIND_NEXT = 1, QUARRY_FIND_DIALOG_FIND_PREVIOUS } QuarryFindDialogSearchDirection; typedef void (* QuarryFindDialogSwitchToGivenNode) (void *user_data, SgfNode *sgf_node); GType quarry_find_dialog_get_type (void); GtkWidget * quarry_find_dialog_new (const gchar *title); const gchar * quarry_find_dialog_get_text_to_find (QuarryFindDialog *dialog); gboolean quarry_find_dialog_get_case_sensitive (QuarryFindDialog *dialog); gboolean quarry_find_dialog_get_whole_words_only (QuarryFindDialog *dialog); gboolean quarry_find_dialog_get_wrap_around (QuarryFindDialog *dialog); gboolean quarry_find_dialog_get_search_whole_game_tree (QuarryFindDialog *dialog); gint quarry_find_dialog_get_search_in (QuarryFindDialog *dialog); gboolean quarry_find_dialog_get_close_automatically (QuarryFindDialog *dialog); void quarry_find_dialog_set_text_to_find (QuarryFindDialog *dialog, const gchar *text_to_find); void quarry_find_dialog_set_search_history (QuarryFindDialog *dialog, const StringList *strings); void quarry_find_dialog_set_case_sensitive (QuarryFindDialog *dialog, gboolean case_sensitive); void quarry_find_dialog_set_whole_words_only (QuarryFindDialog *dialog, gboolean whole_words_only); void quarry_find_dialog_set_wrap_around (QuarryFindDialog *dialog, gboolean wrap_around); void quarry_find_dialog_set_search_whole_game_tree (QuarryFindDialog *dialog, gboolean search_whole_game_tree); void quarry_find_dialog_set_search_in (QuarryFindDialog *dialog, gint search_in); void quarry_find_dialog_set_close_automatically (QuarryFindDialog *dialog, gboolean close_automatically); gboolean quarry_find_text (const gchar *text_to_find, QuarryFindDialogSearchDirection direction, gboolean case_sensitive, gboolean whole_words_only, gboolean wrap_around, gboolean search_whole_game_tree, gint search_in, GtkTextBuffer *text_buffer, gboolean node_name_inserted, SgfGameTree *sgf_tree, QuarryFindDialogSwitchToGivenNode switch_to_given_node, void *user_data); #endif /* QUARRY_QUARRY_SAVE_CONFIRMATION_DIALOG_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/quarry-history-text-buffer.h0000644000175000017500000000653410367757334021307 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef QUARRY_QUARRY_HISTORY_TEXT_BUFFER_H #define QUARRY_QUARRY_HISTORY_TEXT_BUFFER_H #include "quarry-text-buffer.h" #include "quarry.h" #include #define QUARRY_TYPE_HISTORY_TEXT_BUFFER \ (quarry_history_text_buffer_get_type ()) #define QUARRY_HISTORY_TEXT_BUFFER(object) \ GTK_CHECK_CAST ((object), QUARRY_TYPE_HISTORY_TEXT_BUFFER, \ QuarryHistoryTextBuffer) #define QUARRY_HISTORY_TEXT_BUFFER_CLASS(class) \ GTK_CHECK_CLASS_CAST ((class), QUARRY_TYPE_HISTORY_TEXT_BUFFER, \ QuarryHistoryTextBufferClass) #define QUARRY_IS_HISTORY_TEXT_BUFFER(object) \ GTK_CHECK_TYPE ((object), QUARRY_TYPE_HISTORY_TEXT_BUFFER) #define QUARRY_IS_HISTORY_TEXT_BUFFER_CLASS(class) \ GTK_CHECK_CLASS_TYPE ((class), QUARRY_TYPE_HISTORY_TEXT_BUFFER) #define QUARRY_HISTORY_TEXT_BUFFER_GET_CLASS(object) \ GTK_CHECK_GET_CLASS ((object), QUARRY_TYPE_HISTORY_TEXT_BUFFER, \ QuarryHistoryTextBufferClass) typedef struct _QuarryHistoryTextBuffer QuarryHistoryTextBuffer; typedef struct _QuarryHistoryTextBufferClass QuarryHistoryTextBufferClass; struct _QuarryHistoryTextBuffer { QuarryTextBuffer text_buffer; GList *undo_history_begin; GList *undo_history_end; GList *last_applied_entry; }; struct _QuarryHistoryTextBufferClass { QuarryTextBufferClass parent_class; }; GType quarry_history_text_buffer_get_type (void); GtkTextBuffer * quarry_history_text_buffer_new (GtkTextTagTable *tag_table); gboolean quarry_history_text_buffer_can_undo (const QuarryHistoryTextBuffer *buffer); gboolean quarry_history_text_buffer_can_redo (const QuarryHistoryTextBuffer *buffer); void quarry_history_text_buffer_undo (QuarryHistoryTextBuffer *buffer); void quarry_history_text_buffer_redo (QuarryHistoryTextBuffer *buffer); void quarry_history_text_buffer_reset_history (QuarryHistoryTextBuffer *buffer); #endif /* QUARRY_QUARRY_HISTORY_TEXT_BUFFER_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/quarry-message-dialog.h0000644000175000017500000001002610376701130020204 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef QUARRY_QUARRY_MESSAGE_DIALOG_H #define QUARRY_QUARRY_MESSAGE_DIALOG_H #include "quarry.h" #include #include #define QUARRY_TYPE_MESSAGE_DIALOG \ (quarry_message_dialog_get_type ()) #define QUARRY_MESSAGE_DIALOG(object) \ GTK_CHECK_CAST ((object), QUARRY_TYPE_MESSAGE_DIALOG, \ QuarryMessageDialog) #define QUARRY_MESSAGE_DIALOG_CLASS(class) \ GTK_CHECK_CLASS_CAST ((class), QUARRY_TYPE_MESSAGE_DIALOG, \ QuarryMessageDialogClass) #define QUARRY_IS_MESSAGE_DIALOG(object) \ GTK_CHECK_TYPE ((object), QUARRY_TYPE_MESSAGE_DIALOG) #define QUARRY_IS_MESSAGE_DIALOG_CLASS(class) \ GTK_CHECK_CLASS_TYPE ((class), QUARRY_TYPE_MESSAGE_DIALOG) #define QUARRY_MESSAGE_DIALOG_GET_CLASS(object) \ GTK_CHECK_GET_CLASS ((object), QUARRY_TYPE_MESSAGE_DIALOG, \ QuarryMessageDialogClass) typedef struct _QuarryMessageDialog QuarryMessageDialog; typedef struct _QuarryMessageDialogClass QuarryMessageDialogClass; struct _QuarryMessageDialog { GtkDialog dialog; GtkWidget *image; GtkLabel *label; gchar *primary_text; gchar *secondary_text; }; struct _QuarryMessageDialogClass { GtkDialogClass parent_class; }; GType quarry_message_dialog_get_type (void); GtkWidget * quarry_message_dialog_new (GtkWindow *parent, GtkButtonsType buttons, const gchar *icon_stock_id, const gchar *secondary_text, const gchar *primary_text_format_string, ...); GtkWidget * quarry_message_dialog_new_valist (GtkWindow *parent, GtkButtonsType buttons, const gchar *icon_stock_id, const gchar *secondary_text, const gchar *primary_text_format_string, va_list arguments); void quarry_message_dialog_set_icon (QuarryMessageDialog *dialog, const gchar *icon_stock_id); void quarry_message_dialog_set_primary_text (QuarryMessageDialog *dialog, const gchar *primary_text); void quarry_message_dialog_format_primary_text (QuarryMessageDialog *dialog, const gchar *primary_text_format_string, ...); void quarry_message_dialog_format_primary_text_valist (QuarryMessageDialog *dialog, const gchar *primary_text_format_string, va_list arguments); void quarry_message_dialog_set_secondary_text (QuarryMessageDialog *dialog, const gchar *secondary_text); void quarry_message_dialog_format_secondary_text (QuarryMessageDialog *dialog, const gchar *secondary_text_format_string, ...); void quarry_message_dialog_format_secondary_text_valist (QuarryMessageDialog *dialog, const gchar *secondary_text_format_string, va_list arguments); #endif /* QUARRY_QUARRY_MESSAGE_DIALOG_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/quarry-move-number-dialog.h0000644000175000017500000000667410371415443021036 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef QUARRY_QUARRY_MOVE_NUMBER_DIALOG_H #define QUARRY_QUARRY_MOVE_NUMBER_DIALOG_H #include "quarry.h" #include #include #define QUARRY_TYPE_MOVE_NUMBER_DIALOG \ (quarry_move_number_dialog_get_type ()) #define QUARRY_MOVE_NUMBER_DIALOG(object) \ GTK_CHECK_CAST ((object), QUARRY_TYPE_MOVE_NUMBER_DIALOG, \ QuarryMoveNumberDialog) #define QUARRY_MOVE_NUMBER_DIALOG_CLASS(class) \ GTK_CHECK_CLASS_CAST ((class), QUARRY_TYPE_MOVE_NUMBER_DIALOG, \ QuarryMoveNumberDialogClass) #define QUARRY_IS_MOVE_NUMBER_DIALOG(object) \ GTK_CHECK_TYPE ((object), QUARRY_TYPE_MOVE_NUMBER_DIALOG) #define QUARRY_IS_MOVE_NUMBER_DIALOG_CLASS(class) \ GTK_CHECK_CLASS_TYPE ((class), QUARRY_TYPE_MOVE_NUMBER_DIALOG) #define QUARRY_MOVE_NUMBER__DIALOG_GET_CLASS(object) \ GTK_CHECK_GET_CLASS ((object), QUARRY_TYPE_MOVE_NUMBER_DIALOG, \ QuarryMoveNumberDialogClass) typedef struct _QuarryMoveNumberDialog QuarryMoveNumberDialog; typedef struct _QuarryMoveNumberDialogClass QuarryMoveNumberDialogClass; struct _QuarryMoveNumberDialog { GtkDialog dialog; GtkToggleButton *toggle_buttons[2]; GtkAdjustment *move_number_adjustment; gint sequential_move_number; }; struct _QuarryMoveNumberDialogClass { GtkDialogClass parent_class; }; GType quarry_move_number_dialog_get_type (void); GtkWidget * quarry_move_number_dialog_new (void); gboolean quarry_move_number_dialog_get_use_sequential_move_number (const QuarryMoveNumberDialog *dialog); gint quarry_move_number_dialog_get_specific_move_number (const QuarryMoveNumberDialog *dialog); void quarry_move_number_dialog_set_sequential_move_number (QuarryMoveNumberDialog *dialog, gint move_number); void quarry_move_number_dialog_set_specific_move_number (QuarryMoveNumberDialog *dialog, gint move_number); void quarry_move_number_dialog_set_use_sequential_move_number (QuarryMoveNumberDialog *dialog, gboolean use_sequential_move_number); #endif /* QUARRY_QUARRY_MOVE_NUMBER_DIALOG_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/quarry-save-confirmation-dialog.h0000644000175000017500000000646210367245311022221 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef QUARRY_QUARRY_SAVE_CONFIRMATION_DIALOG_H #define QUARRY_QUARRY_SAVE_CONFIRMATION_DIALOG_H #include "quarry-message-dialog.h" #include "quarry.h" #include #include #define QUARRY_TYPE_SAVE_CONFIRMATION_DIALOG \ (quarry_save_confirmation_dialog_get_type ()) #define QUARRY_SAVE_CONFIRMATION_DIALOG(object) \ GTK_CHECK_CAST ((object), QUARRY_TYPE_SAVE_CONFIRMATION_DIALOG, \ QuarrySaveConfirmationDialog) #define QUARRY_SAVE_CONFIRMATION_DIALOG_CLASS(class) \ GTK_CHECK_CLASS_CAST ((class), QUARRY_TYPE_SAVE_CONFIRMATION_DIALOG, \ QuarrySaveConfirmationDialogClass) #define QUARRY_IS_SAVE_CONFIRMATION_DIALOG(object) \ GTK_CHECK_TYPE ((object), QUARRY_TYPE_SAVE_CONFIRMATION_DIALOG) #define QUARRY_IS_SAVE_CONFIRMATION_DIALOG_CLASS(class) \ GTK_CHECK_CLASS_TYPE ((class), QUARRY_TYPE_SAVE_CONFIRMATION_DIALOG) #define QUARRY_SAVE_CONFIRMATION_DIALOG_GET_CLASS(object) \ GTK_CHECK_GET_CLASS ((object), QUARRY_TYPE_SAVE_CONFIRMATION_DIALOG, \ QuarrySaveConfirmationDialogClass) typedef struct _QuarrySaveConfirmationDialog QuarrySaveConfirmationDialog; typedef struct _QuarrySaveConfirmationDialogClass QuarrySaveConfirmationDialogClass; struct _QuarrySaveConfirmationDialog { QuarryMessageDialog dialog; glong time_of_first_modification; guint timeout_source_id; }; struct _QuarrySaveConfirmationDialogClass { QuarryMessageDialogClass parent_class; }; GType quarry_save_confirmation_dialog_get_type (void); GtkWidget * quarry_save_confirmation_dialog_new (GtkWindow *parent, glong time_of_first_modification, const gchar *primary_text_format_string, ...); GtkWidget * quarry_save_confirmation_dialog_new_valist (GtkWindow *parent, glong time_of_first_modification, const gchar *primary_text_format_string, va_list arguments); #endif /* QUARRY_QUARRY_SAVE_CONFIRMATION_DIALOG_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/quarry-stock.h0000644000175000017500000000563010367245325016464 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef QUARRY_QUARRY_STOCK_H #define QUARRY_QUARRY_STOCK_H #include "quarry.h" #include /* Control Center buttons. */ #define QUARRY_STOCK_NEW_GAME "quarry-new-game" #define QUARRY_STOCK_OPEN_GAME_RECORD "quarry-open-game-record" /* Other buttons. */ #define QUARRY_STOCK_BROWSE "quarry-browse" #define QUARRY_STOCK_CREATE "quarry-create" #define QUARRY_STOCK_DONE "quarry-done" #define QUARRY_STOCK_GO_TO_NODE "quarry-go-to-node" #define QUARRY_STOCK_MODIFY "quarry-modify" #define QUARRY_STOCK_MOVE_UP "quarry-move-up" #define QUARRY_STOCK_MOVE_DOWN "quarry-move-down" #define QUARRY_STOCK_FIND_NEXT "quarry-find-next" #define QUARRY_STOCK_OVERWRITE "quarry-overwrite" #define QUARRY_STOCK_PLAY "quarry-play" #define QUARRY_STOCK_FIND_PREVIOUS "quarry-find-previous" /* Backward-compatible wrappers around evolving GTK+ stock. Fallbacks * are either similar icons or no icons. * * A prefix `ICON' or `MENU_ITEM' is used to show that these are not * real stock identifiers. */ #if GTK_2_6_OR_LATER #define QUARRY_STOCK_ICON_DIRECTORY GTK_STOCK_DIRECTORY #define QUARRY_STOCK_ICON_FILE GTK_STOCK_FILE #define QUARRY_STOCK_MENU_ITEM_ABOUT \ "", GTK_STOCK_ABOUT #else /* not GTK_2_6_OR_LATER */ #define QUARRY_STOCK_ICON_DIRECTORY GTK_STOCK_OPEN #define QUARRY_STOCK_ICON_FILE GTK_STOCK_NEW #define QUARRY_STOCK_MENU_ITEM_ABOUT \ "" #endif /* not GTK_2_6_OR_LATER */ void quarry_stock_init (void); #endif /* QUARRY_QUARRY_STOCK_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/quarry-text-buffer.h0000644000175000017500000001040110447531707017565 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2005, 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef QUARRY_QUARRY_TEXT_BUFFER_H #define QUARRY_QUARRY_TEXT_BUFFER_H #include "quarry.h" #include #define QUARRY_TYPE_TEXT_BUFFER (quarry_text_buffer_get_type ()) #define QUARRY_TEXT_BUFFER(object) \ GTK_CHECK_CAST ((object), QUARRY_TYPE_TEXT_BUFFER, \ QuarryTextBuffer) #define QUARRY_TEXT_BUFFER_CLASS(class) \ GTK_CHECK_CLASS_CAST ((class), QUARRY_TYPE_TEXT_BUFFER, \ QuarryTextBufferClass) #define QUARRY_IS_TEXT_BUFFER(object) \ GTK_CHECK_TYPE ((object), QUARRY_TYPE_TEXT_BUFFER) #define QUARRY_IS_TEXT_BUFFER_CLASS(class) \ GTK_CHECK_CLASS_TYPE ((class), QUARRY_TYPE_TEXT_BUFFER) #define QUARRY_TEXT_BUFFER_GET_CLASS(object) \ GTK_CHECK_GET_CLASS ((object), QUARRY_TYPE_TEXT_BUFFER, \ QuarryTextBufferClass) typedef struct _QuarryTextBufferUndoEntry QuarryTextBufferUndoEntry; typedef struct _QuarryTextBuffer QuarryTextBuffer; typedef struct _QuarryTextBufferClass QuarryTextBufferClass; struct _QuarryTextBuffer { GtkTextBuffer text_buffer; QuarryTextBufferUndoEntry *current_undo_entry; guint state_index; guint last_assigned_state_index; guint unmodified_state_index; guint is_undoing_or_redoing : 1; guint block_all_modifications : 1; glong last_modification_time; glong previous_modification_time; }; struct _QuarryTextBufferClass { GtkTextBufferClass parent_class; gboolean (* receive_undo_entry) (QuarryTextBuffer *buffer, QuarryTextBufferUndoEntry *undo_entry); }; typedef struct _QuarryTextBufferState QuarryTextBufferState; struct _QuarryTextBufferState { guint state_index; guint unmodified_state_index; }; GType quarry_text_buffer_get_type (void); GtkTextBuffer * quarry_text_buffer_new (GtkTextTagTable *tag_table); gboolean quarry_text_buffer_is_undoing_or_redoing (const QuarryTextBuffer *buffer); void quarry_text_buffer_undo (QuarryTextBuffer *buffer, const QuarryTextBufferUndoEntry *undo_entry); void quarry_text_buffer_redo (QuarryTextBuffer *buffer, const QuarryTextBufferUndoEntry *undo_entry); gboolean quarry_text_buffer_combine_undo_entries (QuarryTextBuffer *buffer, QuarryTextBufferUndoEntry *previous_undo_entry, QuarryTextBufferUndoEntry *current_undo_entry); void quarry_text_buffer_get_state (QuarryTextBuffer *buffer, QuarryTextBufferState *state); void quarry_text_buffer_set_state (QuarryTextBuffer *buffer, const QuarryTextBufferState *state); QuarryTextBufferUndoEntry * quarry_text_buffer_undo_entry_new (void); void quarry_text_buffer_undo_entry_delete (QuarryTextBufferUndoEntry *undo_entry); inline gboolean quarry_text_buffer_undo_entry_is_empty (const QuarryTextBufferUndoEntry *undo_entry); #endif /* QUARRY_QUARRY_TEXT_BUFFER_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/quarry-text-view.h0000644000175000017500000000540410367167473017303 0ustar bartbart/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * This file is part of Quarry. * * * * Copyright (C) 2006 Paul Pogonyshev. * * * * 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 2 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, write to the Free * * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef QUARRY_QUARRY_TEXT_VIEW_H #define QUARRY_QUARRY_TEXT_VIEW_H #include "quarry.h" #include #define QUARRY_TYPE_TEXT_VIEW (quarry_text_view_get_type ()) #define QUARRY_TEXT_VIEW(object) \ GTK_CHECK_CAST ((object), QUARRY_TYPE_TEXT_VIEW, QuarryTextView) #define QUARRY_TEXT_VIEW_CLASS(class) \ GTK_CHECK_CLASS_CAST ((class), QUARRY_TYPE_TEXT_VIEW, \ QuarryTextViewClass) #define QUARRY_IS_TEXT_VIEW(object) \ GTK_CHECK_TYPE ((object), QUARRY_TYPE_TEXT_VIEW) #define QUARRY_IS_TEXT_VIEW_CLASS(class) \ GTK_CHECK_CLASS_TYPE ((class), QUARRY_TYPE_TEXT_VIEW) #define QUARRY_TEXT_VIEW_GET_CLASS(object) \ GTK_CHECK_GET_CLASS ((object), QUARRY_TYPE_TEXT_VIEW, \ QuarryTextViewClass) typedef struct _QuarryTextView QuarryTextView; typedef struct _QuarryTextViewClass QuarryTextViewClass; struct _QuarryTextView { GtkTextView text_view; }; struct _QuarryTextViewClass { GtkTextViewClass parent_class; void (* undo) (QuarryTextView *view); void (* redo) (QuarryTextView *view); }; GType quarry_text_view_get_type (void); GtkWidget * quarry_text_view_new (void); GtkWidget * quarry_text_view_new_with_buffer (GtkTextBuffer *buffer); void quarry_text_view_undo (QuarryTextView *view); void quarry_text_view_redo (QuarryTextView *view); #endif /* QUARRY_QUARRY_TEXT_VIEW_H */ /* * Local Variables: * tab-width: 8 * c-basic-offset: 2 * End: */ quarry-0.2.0/src/gui-gtk/gtk-configuration.list0000644000175000017500000003013210520515335020161 0ustar bartbart# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # This file is part of Quarry # # # # Copyright (C) 2003, 2004, 2005, 2006 Paul Pogonyshev. # # # # 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 2 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, write to the Free # # Software Foundation, Inc., 51 Franklin Street, Fifth Floor, # # Boston, MA 02110-1301, USA. # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # @mode configuration @h_include "configuration.h" @h_include "board.h" @h_include "utils.h" @c_include "gtk-configuration.h" @c_include "gtk-games.h" @c_include "gui-back-end.h" @c_include "utils.h" section_list unnamed gtk_configuration_sections { @include_list $top_srcdir$/src/gui-utils/common-configuration-sections.list SECTION_GTK_UI "GTK+ User Interface" single new GtkUIConfiguration gtk_ui_configuration_dispose gtk_ui_configuration gtk_ui_section_values gtk_ui_defaults SECTION_NEW_GAME_DIALOG "New Game Parameters" single new NewGameConfiguration new_game_configuration_dispose new_game_configuration new_game_section_values new_game_defaults SECTION_NEW_GO_GAME "New Go Game Parameters" single new NewGoGameConfiguration new_go_game_configuration_dispose new_go_game_configuration new_go_game_section_values new_go_game_defaults SECTION_NEW_AMAZONS_GAME "New Amazons Game Parameters" single new NewAmazonsGameConfiguration new_amazons_game_configuration_dispose new_amazons_game_configuration new_amazons_game_section_values new_amazons_game_defaults SECTION_NEW_REVERSI_GAME "New Reversi Game Parameters" single new NewReversiGameConfiguration new_reversi_game_configuration_dispose new_reversi_game_configuration new_reversi_game_section_values new_reversi_game_defaults SECTION_NEW_GAME_RECORD_DIALOG "New Game Record Parameters" single new NewGameRecordConfiguration new_game_record_configuration_dispose new_game_record_configuration new_game_record_section_values new_game_record_defaults SECTION_NEW_GO_GAME_RECORD "New Go Game Record Parameters" single new NewGoGameRecordConfiguration new_go_game_record_configuration_dispose new_go_game_record_configuration new_go_game_record_section_values new_go_game_record_defaults SECTION_NEW_AMAZONS_GAME_RECORD "New Amazons Game Record Parameters" single new NewAmazonsGameRecordConfiguration new_amazons_game_record_configuration_dispose new_amazons_game_record_configuration new_amazons_game_record_section_values new_amazons_game_record_defaults SECTION_NEW_REVERSI_GAME_RECORD "New Reversi Game Record Parameters" single new NewReversiGameRecordConfiguration new_reversi_game_record_configuration_dispose new_reversi_game_record_configuration new_reversi_game_record_section_values new_reversi_game_record_defaults SECTION_FIND_DIALOG "Find Dialog Parameters" single new FindDialogConfiguration find_dialog_configuration_dispose find_dialog_configuration find_dialog_section_values find_dialog_defaults + NUM_GTK_CONFIGURATION_SECTIONS } @include_list $top_srcdir$/src/gui-utils/common-configuration-values.list values - gtk_ui_section_values { "Use GtkFileChooser if possible" use_gtk_file_chooser boolean "Show main toolbar" show_main_toolbar boolean "Main toolbar style" main_toolbar_style enumeration new TOOLBAR_STYLE_DEFAULT "Default" "Desktop" "Desktop default" "System" "System default" TOOLBAR_STYLE_BOTH "Both" "Both vertically" "Vertically" "Text below icons" TOOLBAR_STYLE_BOTH_HORIZONTALLY "Both horizontally" "Horizontally" "Text beside icons" "Text beside important icons" TOOLBAR_STYLE_ICONS_ONLY "Icons only" "Icons" TOOLBAR_STYLE_TEXT_ONLY "Text only" "Text" end "Show editing toolbar" show_editing_toolbar boolean "Editing toolbar style" editing_toolbar_style enumeration existing TOOLBAR_STYLE_DEFAULT "Default" "Desktop" "Desktop default" "System" "System default" TOOLBAR_STYLE_BOTH "Both" "Both vertically" "Vertically" "Text below icons" TOOLBAR_STYLE_BOTH_HORIZONTALLY "Both horizontally" "Horizontally" "Text beside icons" "Text beside important icons" TOOLBAR_STYLE_ICONS_ONLY "Icons only" "Icons" TOOLBAR_STYLE_TEXT_ONLY "Text only" "Text" end "Show navigation toolbar" show_navigation_toolbar boolean "Navigation toolbar style" navigation_toolbar_style enumeration existing TOOLBAR_STYLE_DEFAULT "Default" "Desktop" "Desktop default" "System" "System default" TOOLBAR_STYLE_BOTH "Both" "Both vertically" "Vertically" "Text below icons" TOOLBAR_STYLE_BOTH_HORIZONTALLY "Both horizontally" "Horizontally" "Text beside icons" "Text beside important icons" TOOLBAR_STYLE_ICONS_ONLY "Icons only" "Icons" TOOLBAR_STYLE_TEXT_ONLY "Text only" "Text" end "Show game action buttons" show_game_action_buttons boolean } values - new_game_section_values { "Game" game_name string "White player name" player_names[WHITE_INDEX] string "White is computer" player_is_computer[WHITE_INDEX] boolean "Engine playing white" engine_names[WHITE_INDEX] string "Black player name" player_names[BLACK_INDEX] string "Black is computer" player_is_computer[BLACK_INDEX] boolean "Engine playing black" engine_names[BLACK_INDEX] string } values - new_go_game_section_values { "Board size" board_size int "Handicap is fixed" handicap_is_fixed boolean "Fixed handicap" fixed_handicap int "Free handicap" free_handicap int "Komi" komi real "Time control type" time_control.type int "Keep track of total time" time_control.track_total_time int "Time limit for game" time_control.game_time_limit time "Time limit for move" time_control.move_time_limit time "Main time" time_control.main_time time "Overtime period length" time_control.overtime_period_length time "Moves per overtime" time_control.moves_per_overtime int } values - new_amazons_game_section_values { "Board size" board_size int "Time control type" time_control.type int "Keep track of total time" time_control.track_total_time int "Time limit for game" time_control.game_time_limit time "Time limit for move" time_control.move_time_limit time "Main time" time_control.main_time time "Overtime period length" time_control.overtime_period_length time "Moves per overtime" time_control.moves_per_overtime int } values - new_reversi_game_section_values { "Board size" board_size int "Time control type" time_control.type int "Keep track of total time" time_control.track_total_time int "Time limit for game" time_control.game_time_limit time "Time limit for move" time_control.move_time_limit time "Main time" time_control.main_time time "Overtime period length" time_control.overtime_period_length time "Moves per overtime" time_control.moves_per_overtime int } values - new_game_record_section_values { "Game" game_name string "White player name" player_names[WHITE_INDEX] string "Black player name" player_names[BLACK_INDEX] string "Game name" game_record_name string } values - new_go_game_record_section_values { "Board size" board_size int "Handicap" handicap nullable int "Place handicap stones" place_handicap_stones boolean "Komi" komi nullable real } values - new_amazons_game_record_section_values { "Board size" board_size int } values - new_reversi_game_record_section_values { "Board size" board_size int } values - find_dialog_section_values { "Latest search strings" latest_search_strings string_list "Case sensitive" case_sensitive boolean "Whole words only" whole_words_only boolean "Wrap around" wrap_around boolean "Search whole game tree" search_whole_game_tree boolean "Search in" search_in enumeration new SEARCH_EVERYWHERE "Nodes and comments" "Everywhere" "Both" SEARCH_IN_COMMENTS "Comments" "Comments only" SEARCH_IN_NODE_NAMES "Node names" "Node names only" end "Auto-close search dialog" close_automatically boolean } @include_list $top_srcdir$/src/gui-utils/common-configuration-defaults.list defaults - gtk_ui_defaults { use_gtk_file_chooser boolean true show_main_toolbar boolean true main_toolbar_style enumeration TOOLBAR_STYLE_DEFAULT show_editing_toolbar boolean true editing_toolbar_style enumeration TOOLBAR_STYLE_DEFAULT show_navigation_toolbar boolean true navigation_toolbar_style enumeration TOOLBAR_STYLE_DEFAULT show_game_action_buttons boolean true } defaults - new_game_defaults { game_name string "Go" player_names array [NUM_COLORS] string [BLACK_INDEX] user_real_name [WHITE_INDEX] user_real_name end player_is_computer array [NUM_COLORS] boolean [BLACK_INDEX] false [WHITE_INDEX] false end engine_names array [NUM_COLORS] string [BLACK_INDEX] NULL [WHITE_INDEX] NULL end } defaults - new_go_game_defaults { board_size int 19 handicap_is_fixed boolean true fixed_handicap int 0 free_handicap int 0 komi real 6.5 time_control structure new TimeControlConfiguration time_control_configuration_dispose type int 0 track_total_time int 0 game_time_limit time 30:00 move_time_limit time 00:30 main_time time 10:00 overtime_period_length time 10:00 moves_per_overtime int 25 end } defaults - new_amazons_game_defaults { board_size int 10 time_control structure new TimeControlConfiguration time_control_configuration_dispose type int 0 track_total_time int 0 game_time_limit time 15:00 move_time_limit time 00:20 main_time time 00:00 overtime_period_length time 05:00 moves_per_overtime int 10 end } defaults - new_reversi_game_defaults { board_size int 8 time_control structure new TimeControlConfiguration time_control_configuration_dispose type int 0 track_total_time int 0 game_time_limit time 10:00 move_time_limit time 00:15 main_time time 00:00 overtime_period_length time 05:00 moves_per_overtime int 10 end } defaults - new_game_record_defaults { game_name string "Go" player_names array [NUM_COLORS] string # FIXME: Maybe should be `user_real_name' instead? Or should be # translated appropriately? [BLACK_INDEX] "Black" [WHITE_INDEX] "White" end game_record_name string NULL } defaults - new_go_game_record_defaults { board_size int 19 handicap nullable int null place_handicap_stones boolean true komi nullable real 6.5 } defaults - new_amazons_game_record_defaults { board_size int 10 } defaults - new_reversi_game_record_defaults { board_size int 8 } defaults - find_dialog_defaults { latest_search_strings string_list - case_sensitive boolean false whole_words_only boolean false wrap_around boolean true search_whole_game_tree boolean true search_in enumeration SEARCH_EVERYWHERE close_automatically boolean false } quarry-0.2.0/src/gui-gtk/quarry-marshal.glist0000644000175000017500000000250210455252026017650 0ustar bartbart# Marshallers used by Quarry widgets. # See glib-genmarshal(1) for a detailed description of the file format, # possible parameter types are: # # VOID indicates no return type, or no extra # parameters. if VOID is used as the parameter # list, no additional parameters may be present. # BOOLEAN for boolean types (gboolean) # CHAR for signed char types (gchar) # UCHAR for unsigned char types (guchar) # INT for signed integer types (gint) # UINT for unsigned integer types (guint) # LONG for signed long integer types (glong) # ULONG for unsigned long integer types (gulong) # ENUM for enumeration types (gint) # FLAGS for flag enumeration types (guint) # FLOAT for single-precision float types (gfloat) # DOUBLE for double-precision float types (gdouble) # STRING for string types (gchar*) # BOXED for boxed (anonymous but reference counted) types (GBoxed*) # POINTER for anonymous pointer types (gpointer) # OBJECT for GObject or derived types (GObject*) # NONE deprecated alias for VOID # BOOL deprecated alias for BOOLEAN VOID:VOID VOID:BOOLEAN VOID:INT VOID:POINTER VOID:POINTER,INT VOID:POINTER,POINTER VOID:OBJECT,OBJECT BOOLEAN:POINTER INT:POINTER