- Install a desktop file to get an entry in the applications menu on Linux (works on both Gnome and KDE)

- New (optional) dependency on the libconfig library, to save/load configuration files.
 - On Unix, the location of the configuration file respects the XDG Base Directory Specification.
 - The contrib system automatically fetches and builds libconfig for Windows cross-compilation
 - Fixed make distcheck
This commit is contained in:
Olivier Teulière 2008-09-22 21:21:38 +00:00
parent 9fff1eb70f
commit 9498d044f8
16 changed files with 589 additions and 109 deletions

View file

@ -1,4 +1,4 @@
SUBDIRS = intl dic game utils wxwin qt po
SUBDIRS = intl dic game utils wxwin qt po extras
ACLOCAL_AMFLAGS = -I m4

View file

@ -76,7 +76,7 @@ dnl --------------------------------------------------------------
dnl Checks for header files.
dnl --------------------------------------------------------------
AC_HEADER_STDC
AC_CHECK_HEADERS(fcntl.h unistd.h sys/wait.h)
AC_CHECK_HEADERS(fcntl.h unistd.h sys/wait.h sys/stats.h sys/types.h)
AC_CHECK_HEADERS(arpa/inet.h netinet/in.h)
AC_CHECK_HEADERS([readline/readline.h], [has_readline=1], [has_readline=0])
AM_CONDITIONAL(HAS_READLINE, test "$has_readline" = "1")
@ -108,12 +108,17 @@ dnl --------------------------------------------------------------
dnl Check for the Boost libraries (in fact we only need the headers)
AX_BOOST_BASE([1.33.1])
PKG_CHECK_MODULES(LIBCONFIG, [libconfig++],
[has_libconfig=1
AC_DEFINE(HAVE_LIBCONFIG, 1, [Define to 1 if you have the libconfig library])],
[has_libconfig=0])
dnl Check for wxWidgets
AC_ARG_ENABLE([wxwidgets],AC_HELP_STRING([--enable-wxwidgets],[wxWidgets interface support (default disabled)]))
if test "${enable_wxwidgets}" = "yes"
then
AM_PATH_WXCONFIG(2.6.0, [wxWin=1], [wxWin=0], [], [--unicode])
if test "${wxWin}" != 1; then
AM_PATH_WXCONFIG(2.6.0, [wxWin=1], [wxWin=0], [], [--unicode])
if test "${wxWin}" != 1; then
AC_MSG_ERROR([
wxWidgets (unicode build) must be installed on your system
but wx-config script couldn't be found.
@ -123,11 +128,11 @@ then
'wx-config --libs' command) is in LD_LIBRARY_PATH or
equivalent variable and wxWidgets version is 2.6.0 or above.
])
fi
AM_CPPFLAGS="$AM_CPPFLAGS $WX_CPPFLAGS"
AM_CXXFLAGS="$AM_CXXFLAGS $WX_CXXFLAGS_ONLY"
AM_CFLAGS="$AM_CFLAGS $WX_CFLAGS_ONLY"
AM_LDFLAGS="$AM_LDFLAGS $WX_LIBS"
fi
AM_CPPFLAGS="$AM_CPPFLAGS $WX_CPPFLAGS"
AM_CXXFLAGS="$AM_CXXFLAGS $WX_CXXFLAGS_ONLY"
AM_CFLAGS="$AM_CFLAGS $WX_CFLAGS_ONLY"
AM_LDFLAGS="$AM_LDFLAGS $WX_LIBS"
fi
AM_CONDITIONAL([BUILD_WXWIDGETS], [test "${wxWin}" = "1"])
@ -206,5 +211,15 @@ game/Makefile
utils/Makefile
wxwin/Makefile
qt/Makefile
extras/Makefile
Makefile)
AC_OUTPUT
if test "$has_libconfig" != "1"; then
echo
echo "@@@@@@@@@@@"
echo "Warning!"
echo "libconfig++ was not detected on your system: saving and loading the configuration will be impossible!"
echo "libconfig++ can be downloaded here: http://www.hyperrealm.com/main.php?s=libconfig"
echo "@@@@@@@@@@@"
fi

10
extras/Makefile.am Normal file
View file

@ -0,0 +1,10 @@
# Install the desktop icon (at least for Gnome)
shortcutdir = $(datadir)/applications
shortcut_DATA = eliot.desktop
icondir = $(datadir)/icons
icon_DATA = eliot.xpm
EXTRA_DIST = $(shortcut_DATA) $(icon_DATA)

View file

@ -1,4 +1,5 @@
ICONV_VERSION = 1.12
LIBCONFIG_VERSION = 1.3.1
WX_VERSION = 2.6.4
BOOST_VERSION = 1_34_1
QT_VERSION = 4.4.1
@ -10,14 +11,14 @@ WGET = wget -c
CC = i586-mingw32msvc-gcc
CXX = i586-mingw32msvc-g++
CPPFLAGS += -I$(PREFIX)/include
CONFIGURE = CC=$(CC) CXX=$(CXX) CPPFLAGS=$(CPPFLAGS) ./configure --host=i586-mingw32msvc --build=i386-linux --prefix=$(PREFIX)
CONFIGURE = CC="$(CC)" CXX="$(CXX)" CPPFLAGS="$(CPPFLAGS)" ./configure --host=i586-mingw32msvc --build=i386-linux --prefix=$(PREFIX)
.PHONY: help all
help:
echo "Usage: make all"
all: .iconv .wxWidgets .boost .qt .libconfig
all: .iconv .wxWidgets .boost .qt
help:
@echo "Usage: make all"
### iconv ###
@ -34,6 +35,20 @@ $(ICONV_DIR):
touch $@
### libconfig ###
LIBCONFIG_DIR = libconfig-$(LIBCONFIG_VERSION)
LIBCONFIG_ARCHIVE = libconfig-$(LIBCONFIG_VERSION).tar.gz
$(LIBCONFIG_DIR):
$(WGET) http://www.hyperrealm.com/libconfig/$(LIBCONFIG_ARCHIVE)
tar xvf $(LIBCONFIG_ARCHIVE)
.libconfig: $(LIBCONFIG_DIR)
(cd $< && CFLAGS=-DLIBCONFIG_STATIC CXXFLAGS=-DLIBCONFIG_STATIC $(CONFIGURE) --enable-static --disable-shared && make && make install)
touch $@
### wxWidgets ###
WX_ARCHIVE = wxMSW-$(WX_VERSION).zip
@ -68,7 +83,6 @@ $(BOOST_DIR):
touch $@
### Qt ###
# FIXME: No automated way at the moment :-(

10
extras/eliot.desktop Normal file
View file

@ -0,0 +1,10 @@
[Desktop Entry]
Name=Eliot
Comment=A Scrabble (TM) game
Comment[fr]=Un jeu de Scrabble (TM)
Exec=eliot
Icon=eliot.xpm
Terminal=0
Type=Application
Categories=Game;

315
extras/eliot.xpm Normal file
View file

@ -0,0 +1,315 @@
/* XPM */
static char * eliot_xpm[] = {
"48 48 264 2",
" c None",
". c #E2E2E2",
"+ c #EFEFEF",
"@ c #EEEFEE",
"# c #EEEEEE",
"$ c #DBDBDB",
"% c #EDEEED",
"& c #D9DAD9",
"* c #FFFFFF",
"= c #CACACA",
"- c #F0F0F0",
"; c #BEBEBE",
"> c #E1E1E1",
", c #C7C7C7",
"' c #BCBCBC",
") c #D3D3D3",
"! c #A3A3A3",
"~ c #F9F9F9",
"{ c #A0A0A0",
"] c #C1C1C1",
"^ c #E0E0E0",
"/ c #B5B5B5",
"( c #D2D2D2",
"_ c #CDCDCD",
": c #B4B4B4",
"< c #B9B9B9",
"[ c #FDFDFD",
"} c #C3C3C3",
"| c #D4D4D4",
"1 c #F5F5F5",
"2 c #969696",
"3 c #EDEDED",
"4 c #A9A9A9",
"5 c #A6A6A6",
"6 c #BFBFBF",
"7 c #A8A8A8",
"8 c #E5E6E5",
"9 c #FBFBFB",
"0 c #E5E2E2",
"a c #E2DFDF",
"b c #E4E3E2",
"c c #E3E3E3",
"d c #DCDCDC",
"e c #E4E5E4",
"f c #E2E3E2",
"g c #E2E4E4",
"h c #CED1D2",
"i c #DEE1E2",
"j c #DEDEDE",
"k c #E5E5E5",
"l c #DFE0DF",
"m c #E4E4E4",
"n c #DFDCDC",
"o c #E4E4E3",
"p c #E0E1E0",
"q c #E0E4E5",
"r c #D5D9D9",
"s c #DFE1E1",
"t c #E4E3E3",
"u c #DEDBDA",
"v c #F6505A",
"w c #DF787D",
"x c #64C0E0",
"y c #1DAEE2",
"z c #20BEF6",
"A c #C3DCE4",
"B c #FAFAFA",
"C c #EAEBEA",
"D c #E3BBBD",
"E c #E19EA2",
"F c #E7E8E7",
"G c #21BDF4",
"H c #51BADF",
"I c #E0868B",
"J c #E3C5C6",
"K c #CC878C",
"L c #E5CFD9",
"M c #CFC6CA",
"N c #7EB9CC",
"O c #52ADCD",
"P c #59BDDF",
"Q c #BACACE",
"R c #AABAD2",
"S c #B5C6E3",
"T c #AAB8CE",
"U c #CEB6B6",
"V c #CDA4A5",
"W c #B2BDCE",
"X c #CECFCF",
"Y c #D1D2D1",
"Z c #59BCDE",
"` c #73B5CC",
" . c #CFC8CB",
".. c #CC8E93",
"+. c #DFCCCD",
"@. c #FF91C5",
"#. c #E5B5CB",
"$. c #EAEAEA",
"%. c #2268E3",
"&. c #1869F6",
"*. c #3171DE",
"=. c #5789DF",
"-. c #DDE0E5",
";. c #E5BED0",
">. c #E5C6D4",
",. c #9A9A9A",
"'. c #CFAABB",
"). c #E5BACE",
"!. c #CFC5CA",
"~. c #D2D3D2",
"{. c #CFD0CF",
"]. c #7B9BD0",
"^. c #7FA3E1",
"/. c #7B9BCC",
"(. c #8DCCE1",
"_. c #9BC1CD",
":. c #AAC5CE",
"<. c #7DA2CC",
"[. c #CCCECF",
"}. c #E3E4E3",
"|. c #CFC9CB",
"1. c #CFC2C8",
"2. c #C9C9C9",
"3. c #E5C9D6",
"4. c #D9E2E5",
"5. c #61BFE0",
"6. c #86CAE1",
"7. c #B4D7E3",
"8. c #E5D3DB",
"9. c #E5B1C9",
"0. c #CFCFCF",
"a. c #CFA4B8",
"b. c #D298B3",
"c. c #E5A6C3",
"d. c #CFC7CA",
"e. c #D4D5D4",
"f. c #CCCFCF",
"g. c #ACD5E3",
"h. c #8EBDCD",
"i. c #82BACC",
"j. c #C3CDCF",
"k. c #E3A5C2",
"l. c #CFA1B7",
"m. c #CFC3C8",
"n. c #89BCCC",
"o. c #C8DADF",
"p. c #ACACAC",
"q. c #D8DBDC",
"r. c #EA85B5",
"s. c #E5D5DC",
"t. c #AFD6E3",
"u. c #8ACBE1",
"v. c #FD90C4",
"w. c #E59DBF",
"x. c #6CC2E0",
"y. c #BBD9E3",
"z. c #D6E1E4",
"A. c #C6CDCF",
"B. c #CFCCCD",
"C. c #D2CCCE",
"D. c #E5DEE1",
"E. c #CF96B0",
"F. c #E591B9",
"G. c #E090B6",
"H. c #C9CECF",
"I. c #CF8DAC",
"J. c #D18BAB",
"K. c #E3DCDF",
"L. c #CFCBCD",
"M. c #C7CECF",
"N. c #DDE0E0",
"O. c #9F9F9F",
"P. c #E59ABD",
"Q. c #FA8FC2",
"R. c #E58EB7",
"S. c #E78AB6",
"T. c #D6D6D6",
"U. c #D9D9D9",
"V. c #D694B3",
"W. c #ED8CB9",
"X. c #E88BB6",
"Y. c #DADBDA",
"Z. c #D689AD",
"`. c #D886AC",
" + c #EBEBEB",
".+ c #F7F8F7",
"++ c #B1C2DD",
"@+ c #1C69EF",
"#+ c #7EA0DB",
"$+ c #DFDFDF",
"%+ c #F2F3F2",
"&+ c #2568DC",
"*+ c #3370D8",
"=+ c #5888D9",
"-+ c #D7DADE",
";+ c #F5F6F5",
">+ c #90ACDC",
",+ c #9FB6DC",
"'+ c #C2C2C2",
")+ c #92B0E2",
"!+ c #A2BAE2",
"~+ c #AEBBCE",
"{+ c #447DDF",
"]+ c #7C9FCC",
"^+ c #C6DDE4",
"/+ c #487ACE",
"(+ c #507ECA",
"_+ c #BDCBCF",
":+ c #C2CCCF",
"<+ c #668ECB",
"[+ c #CACDCF",
"}+ c #CACFCF",
"|+ c #87A7CC",
"1+ c #A1B2CE",
"2+ c #E1E2E1",
"3+ c #BFDAE3",
"4+ c #7BC7E1",
"5+ c #ADADAD",
"6+ c #E2ADB0",
"7+ c #CDADAE",
"8+ c #A3C3CE",
"9+ c #73C4E0",
"0+ c #88BCCC",
"a+ c #90BFCF",
"b+ c #9DD0E2",
"c+ c #C4CDCF",
"d+ c #8CB4C8",
"e+ c #E5C2D2",
"f+ c #9FB4C6",
"g+ c #B6C9CE",
"h+ c #9CCFE0",
"i+ c #8CBDCD",
"j+ c #99C0CD",
"k+ c #CEB1B2",
"l+ c #E0D6D6",
"m+ c #E5CBD7",
"n+ c #E582B1",
"o+ c #E5B9CD",
"p+ c #E7E7E7",
"q+ c #E6E7E6",
"r+ c #CCCCCC",
"s+ c #E8E8E8",
"t+ c #F2F2F2",
"u+ c #989898",
"v+ c #FEFEFE",
"w+ c #E3E4E4",
"x+ c #F1F1F1",
"y+ c #B6B6B6",
"z+ c #DCD9D9",
"A+ c #DADADA",
"B+ c #F7F7F7",
"C+ c #E4D3D4",
"D+ c #E2D8D8",
"E+ c #D5DFE2",
"F+ c #BDCCD1",
"G+ c #CEDFE4",
"H+ c #DFE2E2",
"I+ c #E2DFDE",
"J+ c #E2DCDB",
"K+ c #D3DEE2",
"L+ c #E2D9D9",
"M+ c #F3F0F0",
"N+ c #D7D8D7",
"O+ c #CECFCE",
". + + + @ + + # + @ # + $ @ + # + + # + + % + + # + @ @ + @ # + @ @ + # + @ # + @ @ + # # + + & ",
"+ * * * = * - ; * > , * ' ) * ! ~ * { * * ] * ^ / * ( _ * : < [ } | 1 2 3 = 4 * = 5 * 6 7 * * 8 ",
"+ * 9 0 a b c d e f . g h i e j k k l e 8 f m 0 n o p f e f l e f . q r s f l e f f t a u 1 * 8 ",
"+ + 0 v v w * * 8 * * x y z A * B C * 8 * * D v v E * * 8 * * 8 * F G z H * * 8 * * I v v J * 8 ",
"@ ! 0 v v w * * 8 * * x y z A * B C * 8 * * D v v E * * 8 * * 8 * F G z H * * 8 * * I v v J * 8 ",
"+ * b w w K L L M 8 8 N O P Q 8 p R S T 8 8 U w w V 8 8 W S S X 8 Y Z P ` 8 8 .L L ..w w +.* 8 ",
"+ , 8 * * L @.@.#.* * 8 $.* 8 * B %.&.*.* * 8 * * 8 * * =.&.&.-.* F [ * 8 * * ;.@.@.>.* * 8 * 8 ",
"+ ,.8 * * L @.@.#.* * 8 $.* 8 * B %.&.*.* * 8 * * 8 * * =.&.&.-.* F [ * 8 * * ;.@.@.>.* * 8 * 8 ",
"+ * e 8 8 M #.#.'.).).!.~.8 {.8 p ].^./.(.(._.8 8 :.(.(.<.^.^.[.8 Y }.8 |.).).'.#.#.1.8 8 p * 8 ",
"+ 2.f * * 8 * * ).@.@.3.$.* 8 * B C * 4.z z 5.* * 6.z z 7.* * 8 * F [ * 8.@.@.9.* * 8 * * 8 * 8 ",
"+ 0.f * * 8 * * ).@.@.3.$.* 8 * B C * 4.z z 5.* * 6.z z 7.* * 8 * F [ * 8.@.@.9.* * 8 * * 8 * 8 ",
"+ * g x x N 8 8 !.3.3.a.b.c.d.8 p e.8 f.g.g.h.x x i.g.g.j.8 8 {.8 Y k.c.l.3.3.m.8 8 n.x x o.* 8 ",
"+ p.q.z z P * * 8 * * c.r.@.s.* B C * 8 * * t.z z u.* * 8 * * 8 * F v.@.w.* * 8 * * x.z z y.* 8 ",
"+ 0.q z z P * * 8 * * c.r.@.s.* B C * 8 * * t.z z u.* * 8 * * 8 * F v.@.w.* * 8 * * x.z z y.* 8 ",
"+ 9 e z.z.A.8 8 {.8 8 B.C.D.E.F.G.e.8 {.8 8 f.z.z.H.8 8 {.8 8 I.F.J.K.D.L.8 8 {.8 8 M.z.z.N.* 8 ",
"+ O.8 * * 8 * * 8 * * 8 $.* P.@.Q.C * 8 * * 8 * * 8 * * 8 * * R.@.S.[ * 8 * * 8 * * 8 * * 8 * 8 ",
"+ . k 3 3 T.3 3 T.3 3 T.U.3 V.W.X.Y.3 T.3 3 T.3 3 T.3 3 T.3 3 Z.W.`. +3 T.3 3 T.3 3 T.3 3 . * 8 ",
"+ j k .+.+++@+@+#+.+.+$+c .+$+.+%+&+@+*+.+.+$+.+.+$+.+.+=+@+@+-+.+> ;+.+$+.+.+>+@+@+,+.+.+m * 8 ",
"+ '+8 * * S &.&.^.* * 8 $.* 8 * B %.&.*.* * 8 * * 8 * * =.&.&.-.* F [ * 8 * * )+&.&.!+* * 8 * 8 ",
"+ * e 8 8 ~+{+{+]+^+^+M.~.8 {.8 p /+{+(+^+^+_+8 8 :+^+^+<+{+{+[+8 Y }.8 }+^+^+|+{+{+1+8 8 p * 8 ",
"@ 0.2+* * 8 * * (.z z g.$.* 8 * B C * 4.z z 5.* * 6.z z 7.* * 8 * F [ * 3+z z 4+* * 8 * * 8 * 8 ",
"# 5+Y.* * 8 * * (.z z g.$.* 8 * B C * 4.z z 5.* * 6.z z 7.* * 8 * F [ * 3+z z 4+* * 8 * * 8 * 8 ",
"+ * o 6+6+7+8 8 8+9+9+0+a+b+c+8 p e.8 H.9+9+d+e+e+f+9+9+g+8 8 {.8 Y h+b+i+9+9+j+8 8 k+6+6+l+* 8 ",
"+ '+0 v v w * * 8 * * x y z A * B C * 8 * * m+n+n+o+$ ^ 8 p+* 8 6 q+G z H * * 8 * * I v v J * 8 ",
"+ '+0 v v w * * 8 * * x y z A * B C * 8 * * m+v.n+o+$ ^ 8 ) B 8 6 q+G z H * * 8 * * I v v J * 8 ",
"+ * o 6+6+7+8 8 8+9+9+0+a+b+c+8 p e.8 H.9+9+d+e+e+f+9+9+g+8 8 {.8 Y h+b+i+9+9+j+8 8 k+6+6+l+* 8 ",
"+ $+8 * * 8 * * (.z z g.$.* 8 * B C * 4.z z 5.* * 6.z z 7.* * 8 * F [ * 3+z z 4+* * 8 * * 8 * 8 ",
"+ # 8 * * 8 * * (.z z g.$.* 8 * B C * 4.z z 5.* * 6.z z 7.* * 8 * F [ * 3+z z 4+* * 8 * * 8 * 8 ",
"+ * e 8 8 ~+{+{+]+^+^+M.~.8 {.8 p /+{+(+^+^+_+8 8 :+^+^+<+{+{+[+8 Y }.8 }+^+^+|+{+{+1+8 8 p * 8 ",
"+ r+8 * * S &.&.^.* * 8 $.* 8 * B %.&.*.* * 8 * * 8 * * =.&.&.-.* F [ * 8 * * )+&.&.!+* * 8 * 8 ",
"+ s+k .+.+++@+@+#+.+.+$+c .+$+.+%+&+@+*+.+.+$+.+.+$+.+.+=+@+@+-+.+> ;+.+$+.+.+>+@+@+,+.+.+m * 8 ",
"+ t+}.3 3 T.3 3 T.3 3 T.U.3 V.W.X.Y.3 T.3 3 T.3 3 T.3 3 T.3 3 Z.W.`. +3 T.3 3 T.3 3 T.3 3 . * 8 ",
"+ u+2+* * 8 * * 8 * * 8 $.* P.@.Q.C * 8 * * 8 * * 8 * * 8 * * R.@.S.[ * 8 * * 8 * * 8 * * 8 * 8 ",
"+ v+w+z.z.A.8 8 {.8 8 B.C.D.E.F.G.e.8 {.8 8 f.z.z.H.8 8 {.8 8 I.F.J.K.D.L.8 8 {.8 8 M.z.z.N.* 8 ",
"+ x+q z z P * * 8 * * c.r.@.s.* B C * 8 * * t.z z u.* * 8 * * 8 * F v.@.w.* * 8 * * x.z z y.* 8 ",
"+ } q z z P * * 8 * * c.r.@.s.* B C * 8 * * t.z z u.* * 8 * * 8 * F v.@.w.* * 8 * * x.z z y.* 8 ",
"+ * g x x N 8 8 !.3.3.a.b.c.d.8 p e.8 f.g.g.h.x x i.g.g.j.8 8 {.8 Y k.c.l.3.3.m.8 8 n.x x o.* 8 ",
"# ( Y * * 8 * * ).@.@.3.$.* 8 * B C * 4.z z 5.* * 6.z z 7.* * 8 * F [ * 8.@.@.9.* * 8 * * 8 * 8 ",
"% y+r+* * 8 * * ).@.@.3.$.* 8 * B C * 4.z z 5.* * 6.z z 7.* * 8 * F [ * 8.@.@.9.* * 8 * * 8 * 8 ",
"+ * e 8 8 M #.#.'.).).!.~.8 {.8 p ].^./.(.(._.8 8 :.(.(.<.^.^.[.8 Y }.8 |.).).'.#.#.1.8 8 p * 8 ",
"+ p.8 * * L @.@.#.* * 8 $.* 8 * B %.&.*.* * 8 * * 8 * * =.&.&.-.* F [ * 8 * * ;.@.@.>.* * 8 * 8 ",
"+ = 8 * * L @.@.#.* * 8 $.* 8 * B %.&.*.* * 8 * * 8 * * =.&.&.-.* F [ * 8 * * ;.@.@.>.* * 8 * 8 ",
"+ * b w w K L L M 8 8 N O P Q 8 p R S T 8 8 U w w V 8 8 W S S X 8 Y Z P ` 8 8 .L L ..w w +.* 8 ",
"# 4 z+v v w * * 8 * * x y z A * B C * 8 * * D v v E * * 8 * * 8 * F G z H * * 8 * * I v v J * 8 ",
"+ A+0 v v w * * 8 * * x y z A * B C * 8 * * D v v E * * 8 * * 8 * F G z H * * 8 * * I v v J * 8 ",
"+ * B+C+C+D+8 8 f 8 8 E+F+G+H+8 e c 8 f 8 8 I+C+C+J+8 8 f 8 8 f 8 c G+G+K+8 8 f 8 8 L+C+C+M+* 8 ",
"+ * * * * * * * * * * * $.* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 8 ",
"N+. . . . . . . . . . . 0.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . O+"};

View file

@ -19,7 +19,7 @@
noinst_LIBRARIES = libgame.a
AM_CPPFLAGS = -I$(top_srcdir)/dic -I../intl -I$(top_srcdir)/intl
AM_CPPFLAGS = -I$(top_srcdir)/dic -I../intl -I$(top_srcdir)/intl @LIBCONFIG_CFLAGS@
libgame_a_SOURCES= \
ai_percent.cpp ai_percent.h \

View file

@ -43,7 +43,7 @@ int Duplicate::play(const wstring &iCoord, const wstring &iWord)
// Perform all the validity checks, and try to fill a round
Round round;
int res = checkPlayedWord(iCoord, iWord, round);
if (res != 0 && Settings::Instance().getBool("duplicate-reject-invalid"))
if (res != 0 && Settings::Instance().getBool("duplicate.reject-invalid"))
{
return res;
}
@ -182,7 +182,7 @@ void Duplicate::endTurn()
// Handle solo bonus
// First check whether there are enough players in the game for the
// bonus to apply
int minNbPlayers = Settings::Instance().getInt("duplicate-solo-players");
int minNbPlayers = Settings::Instance().getInt("duplicate.solo-players");
if (getNPlayers() >= (unsigned int)minNbPlayers &&
m_players[imax]->getLastMove().getType() == Move::VALID_ROUND)
{
@ -200,7 +200,7 @@ void Duplicate::endTurn()
if (!otherWithSameScore)
{
// Give the bonus to player imax
int bonus = Settings::Instance().getInt("duplicate-solo-value");
int bonus = Settings::Instance().getInt("duplicate.solo-value");
m_players[imax]->addPoints(bonus);
// TODO: keep a trace of the solo, so the interface
// can be aware of it...

View file

@ -48,7 +48,7 @@ int FreeGame::play(const wstring &iCoord, const wstring &iWord)
// Perform all the validity checks, and try to fill a round
Round round;
int res = checkPlayedWord(iCoord, iWord, round);
if (res != 0 && Settings::Instance().getBool("freegame-reject-invalid"))
if (res != 0 && Settings::Instance().getBool("freegame.reject-invalid"))
{
return res;
}

View file

@ -18,11 +18,28 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*****************************************************************************/
#include "config.h"
#include <cstdlib>
#ifdef HAVE_LIBCONFIG
# define LIBCONFIG_STATIC
# include <libconfig.h++>
#endif
#ifdef WIN32
# include <windows.h>
# include <shlobj.h>
#else
# if defined(HAVE_SYS_STAT_H) && defined(HAVE_SYS_TYPES_H)
# include <sys/stat.h>
# include <sys/types.h>
# endif
#endif
#include "settings.h"
#include "game_exception.h"
using namespace libconfig;
Settings *Settings::m_instance = NULL;
@ -44,90 +61,202 @@ void Settings::Destroy()
}
namespace
{
string getConfigFileName()
{
string fileName;
#ifdef WIN32
char szPath[MAX_PATH];
// Get the AppData directory
if (SHGetFolderPath(NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE,
NULL, 0, szPath) == S_OK)
{
fileName = szPath + string("\\eliot");
#if 1
strncpy(szPath, fileName.c_str(), MAX_PATH);
// Try to create the directory
// We don't care about the results
CreateDirectory(fileName.c_str(), NULL);
#endif
}
if (fileName != "")
fileName += "\\";
fileName += "eliot.cfg";
#else
// Follow the XDG Base Directory Specification (from freedesktop.org)
// XXX: In fact we don't follow it to the letter, because the location
// of the config file could be different when reading and writing.
// But in the case of Eliot it's not very important (we don't try to
// merge config files)...
const char *configDir = getenv("XDG_CONFIG_HOME");
if (configDir != NULL)
fileName = configDir;
else
{
// Fallback to the default value: $HOME/.config
configDir = getenv("HOME");
if (configDir)
fileName = configDir + string("/.config");
}
fileName += "/eliot";
#if defined(HAVE_SYS_STAT_H) && defined(HAVE_SYS_TYPES_H)
// Create the directory if it doesn't exist
struct stat sb;
if (fileName != "" && stat(fileName.c_str(), &sb) == -1)
{
// Try to create the directory with mode 0700
if (mkdir(fileName.c_str(), S_IRWXU))
{
// The directory could not be created. Too bad...
// Saving the configuration file will definitely fail.
}
}
#endif
fileName += "/eliot.cfg";
#endif
return fileName;
}
}
Settings::Settings()
{
// ============== General options ==============
#ifdef HAVE_LIBCONFIG
m_fileName = ::getConfigFileName();
m_conf = new Config;
// ============== General options ==============
// ============== Training mode options ==============
// ============== Duplicate mode options ==============
Setting &dupli = m_conf->getRoot().add("duplicate", Setting::TypeGroup);
// Minimum number of players in a duplicate game needed to apply a "solo" bonus
// (16 is the ODS value)
m_intHandler.addOption("duplicate-solo-players", 16);
dupli.add("solo-players", Setting::TypeInt) = 16;
// Number of points granted for a solo (10 is the ODS value)
m_intHandler.addOption("duplicate-solo-value", 10);
dupli.add("solo-value", Setting::TypeInt) = 10;
// If true, Eliot complains when the player does something illegal
// If false, the word is accepted (with a score of 0) and the player does
// not get a second chance
m_boolHandler.addOption("duplicate-reject-invalid", true);
dupli.add("reject-invalid", Setting::TypeBoolean) = true;
// ============== Freegame mode options ==============
Setting &freegame = m_conf->getRoot().add("freegame", Setting::TypeGroup);
// If true, Eliot complains when the player does something illegal
// If false, the word is accepted (with a score of 0) and the player does
// not get a second chance.
// Trying to change letters or to pass the turn in an incorrect way will
// be rejected in any case.
m_boolHandler.addOption("freegame-reject-invalid", true);
freegame.add("reject-invalid", Setting::TypeBoolean) = true;
// Try to read the values from the configuration file
try
{
m_conf->readFile(m_fileName.c_str());
}
catch (...)
{
// Ignore the exception
}
#endif
}
Settings::~Settings()
{
#ifdef HAVE_LIBCONFIG
delete m_conf;
#endif
}
void Settings::save() const
{
#ifdef HAVE_LIBCONFIG
try
{
m_conf->writeFile(m_fileName.c_str());
}
catch (FileIOException &e)
{
throw GameException("The configuration file cannot be written (" +
m_fileName + ")");
}
#endif
}
void Settings::setBool(const string &iName, bool iValue)
{
m_boolHandler.setOption(iName, iValue);
setValue<bool>(iName, iValue);
}
bool Settings::getBool(const string &iName) const
{
return m_boolHandler.getOption(iName);
#ifdef HAVE_LIBCONFIG
try
{
return m_conf->lookup(iName);
}
catch (SettingNotFoundException &e)
{
throw GameException("No such option: " + iName);
}
#else
// Dummy implementation
return true;
#endif
}
void Settings::setInt(const string &iName, int iValue)
{
m_intHandler.setOption(iName, iValue);
setValue<int>(iName, iValue);
}
int Settings::getInt(const string &iName) const
{
return m_intHandler.getOption(iName);
}
template <typename T>
void Settings::OptionsHandler<T>::addOption(const string &iName, const T &iValue)
{
m_options[iName] = iValue;
}
template <typename T>
void Settings::OptionsHandler<T>::setOption(const string &iName, const T &iValue)
{
typename map<string, T>::iterator it = m_options.find(iName);
if (it == m_options.end())
#ifdef HAVE_LIBCONFIG
try
{
return m_conf->lookup(iName);
}
catch (SettingNotFoundException &e)
{
throw GameException("No such option: " + iName);
}
it->second = iValue;
#else
// Dummy implementation
if (iName == "duplicate.solo-players")
return 16;
else if (iName == "duplicate.solo-bonus")
return 10;
return 0;
#endif
}
template <typename T>
const T& Settings::OptionsHandler<T>::getOption(const string &iName) const
template<class T>
void Settings::setValue(const string &iName, T iValue)
{
typename map<string, T>::const_iterator it = m_options.find(iName);
if (it == m_options.end())
#ifdef HAVE_LIBCONFIG
try
{
m_conf->lookup(iName) = iValue;
}
catch (SettingNotFoundException &e)
{
throw GameException("No such option: " + iName);
}
return it->second;
#endif
}

View file

@ -27,18 +27,20 @@
using std::string;
using std::map;
namespace libconfig
{
class Config;
}
/**
* This class centralizes the various configuration options of Eliot.
* It implements the Singleton pattern.
*
* Currently, there are few settings, and their initial value is hard-coded.
* In a later phase, this class will be able to export/import settings
* to/from a configuration file, and it should be possible to override
* configuration settings with settings given on the command-line (TODO).
* The boost::program_options library could be useful for this.
*
* This class will also be helpful for the "Settings" dialog box of the GUI.
* It is possible to load/save the settings from/to a configuration file.
* In a later phase, it should be possible to override configuration
* settings with settings given on the command-line (TODO).
*/
class Settings
{
@ -48,6 +50,11 @@ public:
/// Destroy the singleton cleanly
static void Destroy();
~Settings();
/// Save the current value of the settinfs to a configuration file
void save() const;
void setBool(const string &iName, bool iValue);
bool getBool(const string &iName) const;
@ -56,47 +63,17 @@ public:
private:
/**
* This nested class is simply there to handle storage and retrieval
* for options of a particular type (and factorize code)
*/
template <typename T>
class OptionsHandler
{
public:
/// Set the value of an option
/**
* If the option already exists, its value is replaced,
* otherwise the option is created
*/
void addOption(const string &iName, const T &iValue);
/**
* Change the value of an existing option.
* An exception is thrown if the option doesn't exist yet
*/
void setOption(const string &iName, const T &iValue);
/**
* Query the value of an option.
* An exception is thrown if the option doesn't exist
*/
const T& getOption(const string &iName) const;
private:
map<string, T> m_options;
};
/// Singleton instance
static Settings *m_instance;
Settings();
/// The settings can be of various types
OptionsHandler<bool> m_boolHandler;
OptionsHandler<int> m_intHandler;
// Add types as needed...
/// Name of the file used to store the settings
string m_fileName;
libconfig::Config *m_conf;
template<class T>
void setValue(const string &iName, T iValue);
};
#endif

View file

@ -76,7 +76,7 @@ eliot_SOURCES = \
main.cpp
eliot_SOURCES += $(BUILT_SOURCES)
eliot_LDADD = @QT_LIBS@ ../game/libgame.a ../dic/libdic.a @LIBINTL@
eliot_LDADD = ../game/libgame.a ../dic/libdic.a @QT_LIBS@ @LIBINTL@ @LIBCONFIG_LIBS@
# Generate a cpp file from the resources
resources.cpp: eliot.qrc $(RESOURCES)
@ -104,12 +104,13 @@ BUILT_SOURCES += win32icon.rc
eliot_SOURCES += win32icon.rc
eliot_LDADD += win32icon.o
win32icon.rc: images/eliot.ico
echo "IDI_ICON1 ICON DISCARDABLE \"$(top_srcdir)/qt/images/eliot.ico\"" > $@
win32icon.o: win32icon.rc
i586-mingw32msvc-windres -o $@ -i $<
endif
# This target is out of the conditional, so that make distcheck is happy
win32icon.rc: images/eliot.ico
echo "IDI_ICON1 ICON DISCARDABLE \"$(top_srcdir)/qt/images/eliot.ico\"" > $@
endif

View file

@ -46,9 +46,9 @@ PrefsDialog::PrefsDialog(QWidget *iParent)
lineEditIntfDicPath->setText(qs.value(kINTF_DIC_PATH, "").toString());
// Duplicate settings
checkBoxDuplRefuseInvalid->setChecked(Settings::Instance().getBool("duplicate-reject-invalid"));
spinBoxDuplSoloPlayers->setValue(Settings::Instance().getInt("duplicate-solo-players"));
spinBoxDuplSoloValue->setValue(Settings::Instance().getInt("duplicate-solo-value"));
checkBoxDuplRefuseInvalid->setChecked(Settings::Instance().getBool("duplicate.reject-invalid"));
spinBoxDuplSoloPlayers->setValue(Settings::Instance().getInt("duplicate.solo-players"));
spinBoxDuplSoloValue->setValue(Settings::Instance().getInt("duplicate.solo-value"));
}
catch (GameException &e)
{
@ -57,7 +57,7 @@ PrefsDialog::PrefsDialog(QWidget *iParent)
}
// Freegame settings
checkBoxFreeRefuseInvalid->setChecked(Settings::Instance().getBool("freegame-reject-invalid"));
checkBoxFreeRefuseInvalid->setChecked(Settings::Instance().getBool("freegame.reject-invalid"));
// Training settings
// XXX: Hide them until there is something to show
@ -71,6 +71,15 @@ PrefsDialog::PrefsDialog(QWidget *iParent)
void PrefsDialog::accept()
{
updateSettings();
try
{
Settings::Instance().save();
}
catch (GameException &e)
{
QMessageBox::warning(this, _q("%1 error").arg(PACKAGE_NAME),
_q("Cannot save the preferences: %1").arg(e.what()));
}
QDialog::accept();
}
@ -92,15 +101,15 @@ void PrefsDialog::updateSettings()
qs.setValue(kINTF_DIC_PATH, lineEditIntfDicPath->text());
// Duplicate settings
Settings::Instance().setBool("duplicate-reject-invalid",
Settings::Instance().setBool("duplicate.reject-invalid",
checkBoxDuplRefuseInvalid->isChecked());
Settings::Instance().setInt("duplicate-solo-players",
Settings::Instance().setInt("duplicate.solo-players",
spinBoxDuplSoloPlayers->value());
Settings::Instance().setInt("duplicate-solo-value",
Settings::Instance().setInt("duplicate.solo-value",
spinBoxDuplSoloValue->value());
// Freegame settings
Settings::Instance().setBool("freegame-reject-invalid",
Settings::Instance().setBool("freegame.reject-invalid",
checkBoxFreeRefuseInvalid->isChecked());
// Training settings

View file

@ -53,6 +53,6 @@
#define _q(s) qfl(_(s))
// Used for QSettings
#define ORGANIZATION "Eliot"
#define ORGANIZATION "eliot"
#endif

View file

@ -25,7 +25,7 @@ bin_PROGRAMS =
if BUILD_TEXT
noinst_PROGRAMS += eliottxt
eliottxt_SOURCES = game_io.h game_io.cpp eliottxt.cpp
eliottxt_LDADD = $(top_builddir)/game/libgame.a $(top_builddir)/dic/libdic.a @LIBINTL@
eliottxt_LDADD = $(top_builddir)/game/libgame.a $(top_builddir)/dic/libdic.a @LIBINTL@ @LIBCONFIG_LIBS@
if HAS_READLINE
eliottxt_LDADD += -lreadline
endif
@ -34,6 +34,6 @@ endif
if BUILD_NCURSES
bin_PROGRAMS += eliotcurses
eliotcurses_SOURCES = ncurses.cpp ncurses.h
eliotcurses_LDADD = ../game/libgame.a ../dic/libdic.a -lncursesw @LIBINTL@
eliotcurses_LDADD = ../game/libgame.a ../dic/libdic.a -lncursesw @LIBINTL@ @LIBCONFIG_LIBS@
endif

View file

@ -36,7 +36,7 @@ wxeliot_SOURCES = \
mainframe.cc mainframe.h \
main.cc ewx.h
wxeliot_LDADD = @WX_LIBS@ ../game/libgame.a ../dic/libdic.a @LIBINTL@
wxeliot_LDADD = @WX_LIBS@ ../game/libgame.a ../dic/libdic.a @LIBINTL@ @LIBCONFIG_LIBS@
EXTRA_DIST = \
eliot.xpm \