chiark / gitweb /
Dariusz Olszewski's changes to support compiling for PocketPC. This
authorSimon Tatham <anakin@pobox.com>
Mon, 26 Feb 2007 20:35:47 +0000 (20:35 +0000)
committerSimon Tatham <anakin@pobox.com>
Mon, 26 Feb 2007 20:35:47 +0000 (20:35 +0000)
is mostly done with ifdefs in windows.c; so mkfiles.pl generates a
new makefile (Makefile.wce) and Recipe enables it, but it's hardly
any different from Makefile.vc apart from a few definitions at the
top of the files.

Currently the PocketPC build is not enabled in the build script, but
with any luck I'll be able to do so reasonably soon.

[originally from svn r7337]

24 files changed:
LICENCE
Recipe
blackbox.c
bridges.c
filling.c
galaxies.c
icons/Makefile
inertia.c
latin.c
loopy.c
map.c
mines.c
mkfiles.pl
net.c
padtoolbar.bmp [new file with mode: 0644]
pattern.c
puzzles.h
puzzles.rc2 [new file with mode: 0644]
rect.c
resource.h [new file with mode: 0644]
solo.c
tents.c
unequal.c
windows.c

diff --git a/LICENCE b/LICENCE
index 8cfd89ddf187f100d8b991a36252b51e80dd8e18..a3937f41a1284601d86682047b14afbbefd6af6b 100644 (file)
--- a/LICENCE
+++ b/LICENCE
@@ -1,7 +1,7 @@
 This software is copyright (c) 2004-2007 Simon Tatham.
 
-Portions copyright Richard Boulton, James Harvey, Mike Pinna and
-Jonas Kölker.
+Portions copyright Richard Boulton, James Harvey, Mike Pinna, Jonas
+Kölker and Dariusz Olszewski.
 
 Permission is hereby granted, free of charge, to any person
 obtaining a copy of this software and associated documentation files
diff --git a/Recipe b/Recipe
index b2c6502ddd6a281f4eab9296b90ced9cf6319906..885b0d7845f938f5d405a7f8d170bba202c6ac41 100644 (file)
--- a/Recipe
+++ b/Recipe
@@ -10,6 +10,7 @@
 
 !makefile gtk Makefile
 !makefile vc Makefile.vc
+!makefile wce Makefile.wce
 !makefile cygwin Makefile.cyg
 !makefile osx Makefile.osx
 
@@ -89,6 +90,11 @@ version.obj: *.c *.h
        cl $(VER) $(CFLAGS) /c version.c
 !end
 !specialobj vc version
+!begin wce
+version.obj: *.c *.h
+       $(CC) $(VER) $(CFLAGS) /c version.c
+!end
+!specialobj wce version
 !begin cygwin
 version.o: FORCE;
 FORCE:
index dbb499981b667ab11766924f193c8c35bc6fcbf8..458c0b805000184d45e97a7f5b4c44ebcc505259 100644 (file)
@@ -1431,7 +1431,7 @@ const struct game thegame = {
     FALSE, FALSE, game_print_size, game_print,
     TRUE,                             /* wants_statusbar */
     FALSE, game_timing_state,
-    0,                                /* flags */
+    REQUIRE_RBUTTON,                  /* flags */
 };
 
 /* vim: set shiftwidth=4 tabstop=8: */
index a8fd8b3a9df9620fea7f7c82de6278d4ef85ba9d..d56f287eeefee80f4ee6a30927e293c248eb5191 100644 (file)
--- a/bridges.c
+++ b/bridges.c
@@ -2662,7 +2662,7 @@ const struct game thegame = {
     TRUE, FALSE, game_print_size, game_print,
     FALSE,                            /* wants_statusbar */
     FALSE, game_timing_state,
-    0,                                /* flags */
+    REQUIRE_RBUTTON,                  /* flags */
 };
 
 /* vim: set shiftwidth=4 tabstop=8: */
index fba86e5df3b6818e69b81a42bcdfc50ff54e3b5d..6f6c6c34cfccb287304a5e0fa1aec78b79b1ac8a 100644 (file)
--- a/filling.c
+++ b/filling.c
@@ -47,7 +47,6 @@
 
 #include <assert.h>
 #include <ctype.h>
-#include <errno.h>
 #include <math.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -984,9 +983,8 @@ static game_state *execute_move(game_state *state, char *move)
         new_state->cheated = TRUE;
     } else {
         char *endptr;
-        const int i = strtol(move, &endptr, errno = 0);
+        const int i = strtol(move, &endptr, 0);
         int value;
-        if (errno == ERANGE) return NULL;
         if (endptr == move) return NULL;
         if (*endptr != '_') return NULL;
         move = endptr + 1;
index 9487a54518260b6de90662edc443979981e9082b..d7a90a45055a530e3f5041a90f6380553b3c3f3c 100644 (file)
@@ -3234,7 +3234,7 @@ const struct game thegame = {
     FALSE,                            /* wants_statusbar */
 #endif
     FALSE, game_timing_state,
-    0,                                /* flags */
+    REQUIRE_RBUTTON,                  /* flags */
 };
 
 #ifdef STANDALONE_SOLVER
index 78abb3526f32fe4b7614405dae726f093bb6b2c0..3ab0e995b68d6711fe7a3d2d3761c19b708c2349 100644 (file)
@@ -126,7 +126,8 @@ $(ICONS): %.ico: %-48d24.png %-48d8.png %-48d4.png \
 
 # Build the .RC files which bind the icons into the applications.
 $(RC): %.rc:
-       echo '200 ICON "$*.ico"' > $@
+       echo '#include "puzzles.rc2"' > $@
+       echo '200 ICON "$*.ico"' >> $@
 
 # Build the GTK icon source files.
 $(CICONS): %-icon.c: %-16d24.png %-32d24.png %-48d24.png
index 10ea53856a7ff90ef5a2bd811bb064255574396b..4e84f56f3a1f7ed4664995c2d191db7974fe07c5 100644 (file)
--- a/inertia.c
+++ b/inertia.c
@@ -88,8 +88,11 @@ static game_params *default_params(void)
     game_params *ret = snew(game_params);
 
     ret->w = 10;
+#ifdef PORTRAIT_SCREEN
+    ret->h = 10;
+#else
     ret->h = 8;
-
+#endif
     return ret;
 }
 
@@ -106,9 +109,15 @@ static game_params *dup_params(game_params *params)
 }
 
 static const struct game_params inertia_presets[] = {
+#ifdef PORTRAIT_SCREEN
+    { 10, 10 },
+    { 12, 12 },
+    { 16, 16 },
+#else
     { 10, 8 },
     { 15, 12 },
     { 20, 16 },
+#endif
 };
 
 static int game_fetch_preset(int i, char **name, game_params **params)
@@ -1511,7 +1520,11 @@ struct game_drawstate {
 
 #define PREFERRED_TILESIZE 32
 #define TILESIZE (ds->tilesize)
+#ifdef SMALL_SCREEN
+#define BORDER    (TILESIZE / 4)
+#else
 #define BORDER    (TILESIZE)
+#endif
 #define HIGHLIGHT_WIDTH (TILESIZE / 10)
 #define COORD(x)  ( (x) * TILESIZE + BORDER )
 #define FROMCOORD(x)  ( ((x) - BORDER + TILESIZE) / TILESIZE - 1 )
diff --git a/latin.c b/latin.c
index 2d6ae747bdc642e4fb4e795c0646a10edbe299c3..dc2af8f9dc8ded5b9655ca0d4d67a1fa00bd8ebd 100644 (file)
--- a/latin.c
+++ b/latin.c
 
 #include "latin.h"
 
+static void assert_f(p)
+{
+    assert(p);
+}
+
 /* --------------------------------------------------------
  * Solver.
  */
@@ -26,7 +31,7 @@ void latin_solver_place(struct latin_solver *solver, int x, int y, int n)
     int i, o = solver->o;
 
     assert(n <= o);
-    assert(cube(x,y,n));
+    assert_f(cube(x,y,n));
 
     /*
      * Rule out all other numbers in this square.
@@ -1188,7 +1193,7 @@ int latin_check(digit *sq, int order)
                lcp = snew(lcparams);
                lcp->elt = ELT(sq, c, r);
                lcp->count = 1;
-               assert(add234(dict, lcp) == lcp);
+               assert_f(add234(dict, lcp) == lcp);
            } else {
                lcp->count++;
            }
diff --git a/loopy.c b/loopy.c
index 8f1e3450541f333d33a7107ffa2439d69f4502bf..f0344fefd440bb97f117c7dce502be3424c459cd 100644 (file)
--- a/loopy.c
+++ b/loopy.c
@@ -512,10 +512,12 @@ static const game_params presets[] = {
     { 15, 15, DIFF_EASY, 0 },
     { 15, 15, DIFF_NORMAL, 0 },
     { 15, 15, DIFF_HARD, 0 },
+#ifndef SMALL_SCREEN
     { 30, 20, DIFF_EASY, 0 },
     { 30, 20, DIFF_NORMAL, 0 },
     { 30, 20, DIFF_HARD, 0 }
 #endif
+#endif
 };
 
 static int game_fetch_preset(int i, char **name, game_params **params)
diff --git a/map.c b/map.c
index 098fc47d355c2d0343c207dccf3f9d456f3ee723..b6b61947372c23605c545949518c7b29786f8635 100644 (file)
--- a/map.c
+++ b/map.c
@@ -100,8 +100,13 @@ static game_params *default_params(void)
 {
     game_params *ret = snew(game_params);
 
+#ifdef PORTRAIT_SCREEN
+    ret->w = 16;
+    ret->h = 18;
+#else
     ret->w = 20;
     ret->h = 15;
+#endif
     ret->n = 30;
     ret->diff = DIFF_NORMAL;
 
@@ -109,12 +114,21 @@ static game_params *default_params(void)
 }
 
 static const struct game_params map_presets[] = {
+#ifdef PORTRAIT_SCREEN
+    {16, 18, 30, DIFF_EASY},
+    {16, 18, 30, DIFF_NORMAL},
+    {16, 18, 30, DIFF_HARD},
+    {16, 18, 30, DIFF_RECURSE},
+    {25, 30, 75, DIFF_NORMAL},
+    {25, 30, 75, DIFF_HARD},
+#else
     {20, 15, 30, DIFF_EASY},
     {20, 15, 30, DIFF_NORMAL},
     {20, 15, 30, DIFF_HARD},
     {20, 15, 30, DIFF_RECURSE},
     {30, 25, 75, DIFF_NORMAL},
     {30, 25, 75, DIFF_HARD},
+#endif
 };
 
 static int game_fetch_preset(int i, char **name, game_params **params)
@@ -2517,10 +2531,18 @@ static void game_set_size(drawing *dr, game_drawstate *ds,
 }
 
 const float map_colours[FOUR][3] = {
+#ifdef VIVID_COLOURS
+    // Use more vivid colours (e.g. on the Pocket PC)
+    {0.75F, 0.25F, 0.25F},
+    {0.3F,  0.7F,  0.3F},
+    {0.3F,  0.3F,  0.7F},
+    {0.85F, 0.85F, 0.1F},
+#else
     {0.7F, 0.5F, 0.4F},
     {0.8F, 0.7F, 0.4F},
     {0.5F, 0.6F, 0.4F},
     {0.55F, 0.45F, 0.35F},
+#endif
 };
 const int map_hatching[FOUR] = {
     HATCH_VERT, HATCH_SLASH, HATCH_HORIZ, HATCH_BACKSLASH
diff --git a/mines.c b/mines.c
index 73aea0b247ef78b8085f3dc60c623ef1c97b8b6d..3c4dc13f326984df2d84d286a375b8b7d74ec1d8 100644 (file)
--- a/mines.c
+++ b/mines.c
@@ -28,7 +28,11 @@ enum {
 
 #define PREFERRED_TILE_SIZE 20
 #define TILE_SIZE (ds->tilesize)
+#ifdef SMALL_SCREEN
+#define BORDER 8
+#else
 #define BORDER (TILE_SIZE * 3 / 2)
+#endif
 #define HIGHLIGHT_WIDTH (TILE_SIZE / 10)
 #define OUTER_HIGHLIGHT_WIDTH (BORDER / 10)
 #define COORD(x)  ( (x) * TILE_SIZE + BORDER )
@@ -102,8 +106,10 @@ static const struct game_params mines_presets[] = {
   {9, 9, 35, TRUE},
   {16, 16, 40, TRUE},
   {16, 16, 99, TRUE},
+#ifndef SMALL_SCREEN
   {30, 16, 99, TRUE},
   {30, 16, 170, TRUE},
+#endif
 };
 
 static int game_fetch_preset(int i, char **name, game_params **params)
@@ -3103,7 +3109,7 @@ const struct game thegame = {
     FALSE, FALSE, game_print_size, game_print,
     TRUE,                             /* wants_statusbar */
     TRUE, game_timing_state,
-    BUTTON_BEATS(LEFT_BUTTON, RIGHT_BUTTON),
+    BUTTON_BEATS(LEFT_BUTTON, RIGHT_BUTTON) | REQUIRE_RBUTTON,
 };
 
 #ifdef STANDALONE_OBFUSCATOR
index 52c9a741e101da465e17c48bbe96182b6798b85a..b25d86ca72256d559f53a74f6bb7c8cb6543d0e6 100755 (executable)
@@ -284,7 +284,7 @@ sub mfval($) {
     # Returns true if the argument is a known makefile type. Otherwise,
     # prints a warning and returns false;
     if (grep { $type eq $_ }
-       ("vc","vcproj","cygwin","borland","lcc","gtk","mpw","osx")) {
+       ("vc","vcproj","cygwin","borland","lcc","gtk","mpw","osx","wce")) {
            return 1;
        }
     warn "$.:unknown makefile type '$type'\n";
@@ -719,6 +719,114 @@ if (defined $makefiles{'vc'}) {
     select STDOUT; close OUT;
 }
 
+if (defined $makefiles{'wce'}) {
+    $mftyp = 'wce';
+    $dirpfx = &dirpfx($makefiles{'wce'}, "\\");
+
+    ##-- eMbedded Visual C PocketPC makefile
+    open OUT, ">$makefiles{'wce'}"; select OUT;
+    print
+      "# Makefile for $project_name on PocketPC using eMbedded Visual C.\n".
+      "#\n# This file was created by `mkfiles.pl' from the `Recipe' file.\n".
+      "# DO NOT EDIT THIS FILE DIRECTLY; edit Recipe or mkfiles.pl instead.\n";
+    print $help;
+    print
+      "\n".
+      "# If you rename this file to `Makefile', you should change this line,\n".
+      "# so that the .rsp files still depend on the correct makefile.\n".
+      "MAKEFILE = Makefile.wce\n".
+      "\n".
+      "# This makefile expects the environment to have been set up by one\n".
+      "# of the PocketPC batch files wcearmv4.bat and wceemulator.bat. No\n".
+      "# other build targets are currently supported, because they would\n".
+      "# need a section in this if statement.\n".
+      "!if \"\$(TARGETCPU)\" == \"emulator\"\n".
+      "PLATFORM_DEFS=/D \"_i386_\" /D \"i_386_\" /D \"_X86_\" /D \"x86\"\n".
+      "CC=cl\n".
+      "BASELIBS=commctrl.lib coredll.lib corelibc.lib aygshell.lib\n".
+      "MACHINE=IX86\n".
+      "!else\n".
+      "PLATFORM_DEFS=/D \"ARM\" /D \"_ARM_\" /D \"ARMV4\"\n".
+      "CC=clarm\n".
+      "BASELIBS=commctrl.lib coredll.lib aygshell.lib\n".
+      "MACHINE=ARM\n".
+      "!endif\n".
+      "\n".
+      "# C compilation flags\n".
+      "CFLAGS = /nologo /W3 /O1 /MC /D _WIN32_WCE=420 /D \"WIN32_PLATFORM_PSPC=400\" /D UNDER_CE=420 \\\n".
+      "         \$(PLATFORM_DEFS) \\\n".
+      "         /D \"UNICODE\" /D \"_UNICODE\" /D \"NDEBUG\" /D \"NO_HTMLHELP\"\n".
+      "\n".
+      "LFLAGS = /nologo /incremental:no \\\n".
+      "         /base:0x00010000 /stack:0x10000,0x1000 /entry:WinMainCRTStartup \\\n".
+      "         /nodefaultlib:libc.lib /nodefaultlib:libcmt.lib /nodefaultlib:msvcrt.lib /nodefaultlib:OLDNAMES.lib \\\n".
+      "         /subsystem:windowsce,4.20 /align:4096 /MACHINE:\$(MACHINE)\n".
+      "\n".
+      "RCFL = /d UNDER_CE=420 /d _WIN32_WCE=420 /d \"WIN32_PLATFORM_PSPC=400\" \\\n".
+      "       \$(PLATFORM_DEFS) \\\n".
+      "       /d \"NDEBUG\" /d \"UNICODE\" /d \"_UNICODE\"\n".
+      "\n";
+    print &splitline("all:" . join "", map { " $_.exe" } &progrealnames("G"));
+    print "\n\n";
+    foreach $p (&prognames("G")) {
+       ($prog, $type) = split ",", $p;
+       $objstr = &objects($p, "X.obj", "X.res", undef);
+       print &splitline("$prog.exe: " . $objstr . " $prog.rsp"), "\n";
+       print "\tlink \$(LFLAGS) -out:$prog.exe -map:$prog.map \@$prog.rsp\n\n";
+    }
+    foreach $p (&prognames("G")) {
+       ($prog, $type) = split ",", $p;
+       print $prog, ".rsp: \$(MAKEFILE)\n";
+       $objstr = &objects($p, "X.obj", "X.res", undef);
+       @objlist = split " ", $objstr;
+       @objlines = ("");
+       foreach $i (@objlist) {
+           if (length($objlines[$#objlines] . " $i") > 50) {
+               push @objlines, "";
+           }
+           $objlines[$#objlines] .= " $i";
+       }
+       print "\techo \$(BASELIBS) > $prog.rsp\n";
+       for ($i=0; $i<=$#objlines; $i++) {
+           print "\techo$objlines[$i] >> $prog.rsp\n";
+       }
+       print "\n";
+    }
+    foreach $d (&deps("X.obj", "X.res", $dirpfx, "\\")) {
+       print &splitline(sprintf("%s: %s", $d->{obj}, join " ", @{$d->{deps}})),
+         "\n";
+       if ($d->{obj} =~ /\.res$/) {
+           print "\trc \$(FWHACK) \$(RCFL) -r -fo".
+             $d->{obj}." ".$d->{deps}->[0]."\n";
+       } else {
+           $deflist = join "", map { " /D$_" } @{$d->{defs}};
+           print "\t\$(CC) \$(COMPAT) \$(FWHACK) \$(CFLAGS) \$(XFLAGS)$deflist".
+             " /c ".$d->{deps}->[0]." /Fo$d->{obj}\n";
+       }
+    }
+    print "\n";
+    print $makefile_extra{'wce'};
+    print "\nclean: tidy\n".
+      "\t-del *.exe\n\n".
+      "tidy:\n".
+      "\t-del *.obj\n".
+      "\t-del *.res\n".
+      "\t-del *.pch\n".
+      "\t-del *.aps\n".
+      "\t-del *.ilk\n".
+      "\t-del *.pdb\n".
+      "\t-del *.rsp\n".
+      "\t-del *.dsp\n".
+      "\t-del *.dsw\n".
+      "\t-del *.ncb\n".
+      "\t-del *.opt\n".
+      "\t-del *.plg\n".
+      "\t-del *.map\n".
+      "\t-del *.idb\n".
+      "\t-del debug.log\n";
+    select STDOUT; close OUT;
+}
+
 if (defined $makefiles{'vcproj'}) {
     $mftyp = 'vcproj';
 
diff --git a/net.c b/net.c
index eb83a1617d35832deb401bd598fef926a6c63688..bf0f7e7e48c825df01172edfcbed15219518ca63 100644 (file)
--- a/net.c
+++ b/net.c
 #define PREFERRED_TILE_SIZE 32
 #define TILE_SIZE (ds->tilesize)
 #define TILE_BORDER 1
+#ifdef SMALL_SCREEN
+#define WINDOW_OFFSET 4
+#else
 #define WINDOW_OFFSET 16
+#endif
 
 #define ROTATE_TIME 0.13F
 #define FLASH_FRAME 0.07F
@@ -150,12 +154,16 @@ static const struct game_params net_presets[] = {
     {7, 7, FALSE, TRUE, 0.0},
     {9, 9, FALSE, TRUE, 0.0},
     {11, 11, FALSE, TRUE, 0.0},
+#ifndef SMALL_SCREEN
     {13, 11, FALSE, TRUE, 0.0},
+#endif
     {5, 5, TRUE, TRUE, 0.0},
     {7, 7, TRUE, TRUE, 0.0},
     {9, 9, TRUE, TRUE, 0.0},
     {11, 11, TRUE, TRUE, 0.0},
+#ifndef SMALL_SCREEN
     {13, 11, TRUE, TRUE, 0.0},
+#endif
 };
 
 static int game_fetch_preset(int i, char **name, game_params **params)
diff --git a/padtoolbar.bmp b/padtoolbar.bmp
new file mode 100644 (file)
index 0000000..46c3e0d
Binary files /dev/null and b/padtoolbar.bmp differ
index a85877f9ba79012eb404d2174d14f5215c0b1dbc..2c24ad259a493f14782a231344d13d7cdcc96852 100644 (file)
--- a/pattern.c
+++ b/pattern.c
@@ -1276,7 +1276,7 @@ const struct game thegame = {
     TRUE, FALSE, game_print_size, game_print,
     FALSE,                            /* wants_statusbar */
     FALSE, game_timing_state,
-    0,                                /* flags */
+    REQUIRE_RBUTTON,                  /* flags */
 };
 
 #ifdef STANDALONE_SOLVER
index 30ffcb0465add8378aac01a26bd72cca3558b1b0..ff991ad1fc612385602cb2408d7a3555cc4c570c 100644 (file)
--- a/puzzles.h
+++ b/puzzles.h
@@ -67,8 +67,19 @@ enum {
 #define BUTTON_BEATS(x,y) ( 1 << (((x)-LEFT_BUTTON)*3+(y)-LEFT_BUTTON) )
 /* Flag indicating that Solve operations should be animated */
 #define SOLVE_ANIMATES ( 1 << 9 )
+/* Pocket PC: Game requires right mouse button emulation */
+#define REQUIRE_RBUTTON ( 1 << 10 )
+/* Pocket PC: Game requires numeric input */
+#define REQUIRE_NUMPAD ( 1 << 11 )
 /* end of `flags' word definitions */
 
+#ifdef _WIN32_WCE
+  /* Pocket PC devices have small, portrait screen that requires more vivid colours */
+  #define SMALL_SCREEN
+  #define PORTRAIT_SCREEN
+  #define VIVID_COLOURS
+#endif
+
 #define IGNOREARG(x) ( (x) = (x) )
 
 typedef struct frontend frontend;
diff --git a/puzzles.rc2 b/puzzles.rc2
new file mode 100644 (file)
index 0000000..4442a9b
--- /dev/null
@@ -0,0 +1,65 @@
+/* Standard stuff that goes into the Windows resources for all puzzles. */
+
+#ifdef _WIN32_WCE
+
+#include <winuser.h>
+#include <commctrl.h>
+
+#define SHMENUBAR       RCDATA
+#define I_IMAGENONE     (-2)
+#define IDC_STATIC      (-1)
+
+#include "resource.h"
+
+IDR_MENUBAR1 MENU DISCARDABLE 
+BEGIN
+    POPUP "Game"
+    BEGIN
+        MENUITEM "Dummy", 0
+    END
+    POPUP "Type"
+    BEGIN
+        MENUITEM "Dummy", 0
+    END
+END
+
+IDR_MENUBAR1 SHMENUBAR DISCARDABLE 
+BEGIN
+    IDR_MENUBAR1, 2,
+    I_IMAGENONE, ID_GAME, TBSTATE_ENABLED, 
+    TBSTYLE_DROPDOWN | TBSTYLE_AUTOSIZE, IDS_CAP_GAME, 0, 0,
+    I_IMAGENONE, ID_TYPE, TBSTATE_ENABLED, 
+    TBSTYLE_DROPDOWN | TBSTYLE_AUTOSIZE, IDS_CAP_TYPE, 0, 1,
+END
+
+STRINGTABLE DISCARDABLE 
+BEGIN
+    IDS_CAP_GAME            "Game"
+    IDS_CAP_TYPE            "Type"
+END
+
+IDD_ABOUT DIALOG DISCARDABLE  0, 0, 0, 0
+STYLE WS_POPUP
+FONT 8, "Tahoma"
+BEGIN
+    LTEXT "", IDC_ABOUT_CAPTION,        4,  4, 150,  8
+    LTEXT "", IDC_ABOUT_LINE,           4, 16, 150,  1, WS_BORDER
+    LTEXT "", IDC_ABOUT_GAME,           4, 22, 150,  8
+    LTEXT "from Simon Tatham's Portable Puzzle Collection",
+             IDC_STATIC,               4, 36, 150,  8, SS_LEFTNOWORDWRAP
+    LTEXT "Pocket PC port by Darek Olszewski",
+             IDC_STATIC,               4, 46, 150,  8
+    LTEXT "", IDC_ABOUT_VERSION,        4, 60, 150,  8
+END
+
+IDD_CONFIG DIALOG DISCARDABLE  0, 0, 0, 0
+STYLE WS_POPUP
+FONT 8, "Tahoma"
+BEGIN
+    LTEXT "", IDC_CONFIG_CAPTION,       4,  4, 150,  8
+    LTEXT "", IDC_CONFIG_LINE,          4, 16, 150,  1, WS_BORDER
+END
+
+IDR_PADTOOLBAR BITMAP DISCARDABLE "padtoolbar.bmp"
+
+#endif /* _WIN32_WCE */
diff --git a/rect.c b/rect.c
index e73db7df21b545971510a0458d88b8a58080052b..281b4f54b4414d714304ddd2bfbc7489af1510e0 100644 (file)
--- a/rect.c
+++ b/rect.c
@@ -60,7 +60,11 @@ struct game_params {
 
 #define PREFERRED_TILE_SIZE 24
 #define TILE_SIZE (ds->tilesize)
+#ifdef SMALL_SCREEN
+#define BORDER (2)
+#else
 #define BORDER (TILE_SIZE * 3 / 4)
+#endif
 
 #define CORNER_TOLERANCE 0.15F
 #define CENTRE_TOLERANCE 0.15F
@@ -102,8 +106,10 @@ static int game_fetch_preset(int i, char **name, game_params **params)
       case 2: w = 11, h = 11; break;
       case 3: w = 13, h = 13; break;
       case 4: w = 15, h = 15; break;
+#ifndef SMALL_SCREEN
       case 5: w = 17, h = 17; break;
       case 6: w = 19, h = 19; break;
+#endif
       default: return FALSE;
     }
 
diff --git a/resource.h b/resource.h
new file mode 100644 (file)
index 0000000..f0bfa16
--- /dev/null
@@ -0,0 +1,20 @@
+
+#define IDR_MENUBAR1                    101
+
+#define ID_GAME                         40005
+#define ID_TYPE                         40006
+
+#define IDS_CAP_GAME                    40105
+#define IDS_CAP_TYPE                    40106
+
+#define IDD_ABOUT                      2000
+#define IDC_ABOUT_CAPTION              2001
+#define IDC_ABOUT_LINE                 2002
+#define IDC_ABOUT_GAME                 2003
+#define IDC_ABOUT_VERSION              2004
+
+#define IDD_CONFIG                     2100
+#define IDC_CONFIG_CAPTION             2101
+#define IDC_CONFIG_LINE                        2102
+
+#define IDR_PADTOOLBAR                  4000
diff --git a/solo.c b/solo.c
index 0a4e852bfb31200f06012ab14e347c1ef70442c7..19d91b4b30ca5610e6083baf1dfdb5ea5d529c4e 100644 (file)
--- a/solo.c
+++ b/solo.c
@@ -3085,7 +3085,7 @@ const struct game thegame = {
     TRUE, FALSE, game_print_size, game_print,
     FALSE,                            /* wants_statusbar */
     FALSE, game_timing_state,
-    0,                                /* flags */
+    REQUIRE_RBUTTON | REQUIRE_NUMPAD,  /* flags */
 };
 
 #ifdef STANDALONE_SOLVER
diff --git a/tents.c b/tents.c
index e5e8c6f3b781966987f65a32586976221c1e02be..de203004e5c583ad92c3f68e99e1a23b6b37c4ef 100644 (file)
--- a/tents.c
+++ b/tents.c
@@ -2086,7 +2086,7 @@ const struct game thegame = {
     TRUE, FALSE, game_print_size, game_print,
     FALSE,                            /* wants_statusbar */
     FALSE, game_timing_state,
-    0,                                /* flags */
+    REQUIRE_RBUTTON,                  /* flags */
 };
 
 #ifdef STANDALONE_SOLVER
index 81720e47232ef3f8df2b808ea81fe3c9446a5919..8006ea1f1a3614917678cd0f1466270e1c630e20 100644 (file)
--- a/unequal.c
+++ b/unequal.c
 #include "puzzles.h"
 #include "latin.h" /* contains typedef for digit */
 
+static void assert_f(p)
+{
+    assert(p);
+}
+
 /* ----------------------------------------------------------
  * Constant and structure definitions
  */
@@ -971,7 +976,7 @@ static void game_strip(game_state *new, int *scratch, digit *latin,
         gg_solved++;
         if (solver_state(copy, difficulty) != 1) {
             /* put clue back, we can't solve without it. */
-            assert(gg_place_clue(new, scratch[i], latin, 0) == 1);
+            assert_f(gg_place_clue(new, scratch[i], latin, 0) == 1);
         } else {
 #ifdef STANDALONE_SOLVER
             if (solver_show_working)
@@ -1355,7 +1360,7 @@ static game_state *execute_move(game_state *state, char *move)
             p++;
         }
         if (*p) goto badmove;
-        assert(check_complete(ret->nums, ret, 1) > 0);
+       assert_f(check_complete(ret->nums, ret, 1) > 0);
         return ret;
     } else if (move[0] == 'H') {
         return solver_hint(state, NULL, DIFF_EASY, DIFF_EASY);
@@ -1748,7 +1753,7 @@ const struct game thegame = {
     TRUE, FALSE, game_print_size, game_print,
     FALSE,                            /* wants_statusbar */
     FALSE, game_timing_state,
-    0,                                /* flags */
+    REQUIRE_RBUTTON | REQUIRE_NUMPAD,  /* flags */
 };
 
 /* ----------------------------------------------------------------------
index 82767e40285fa4178dc503e070ea4c2c98872f38..ba0ed52aa00a929ff6ccbade2ff0bee5653c4632 100644 (file)
--- a/windows.c
+++ b/windows.c
@@ -8,6 +8,11 @@
 #include <htmlhelp.h>
 #endif /* NO_HTMLHELP */
 
+#ifdef _WIN32_WCE
+#include <commdlg.h>
+#include <aygshell.h>
+#endif
+
 #include <stdio.h>
 #include <assert.h>
 #include <ctype.h>
 
 #include "puzzles.h"
 
+#ifdef _WIN32_WCE
+#include "resource.h"
+#endif
+
 #define IDM_NEW       0x0010
 #define IDM_RESTART   0x0020
 #define IDM_UNDO      0x0030
@@ -36,6 +45,8 @@
 #define IDM_PRINT     0x0100
 #define IDM_PRESETS   0x0110
 
+#define IDM_KEYEMUL   0x0400
+
 #define HELP_FILE_NAME  "puzzles.hlp"
 #define HELP_CNT_NAME   "puzzles.cnt"
 #ifndef NO_HTMLHELP
@@ -52,6 +63,58 @@ char *help_path;
 const char *help_topic;
 int help_has_contents;
 
+#ifndef FILENAME_MAX
+#define        FILENAME_MAX    (260)
+#endif
+
+#ifndef HGDI_ERROR
+#define HGDI_ERROR ((HANDLE)GDI_ERROR)
+#endif
+
+#ifdef _WIN32_WCE
+
+/*
+ * Wrapper implementations of functions not supplied by the
+ * PocketPC API.
+ */
+
+#define SHGetSubMenu(hWndMB,ID_MENU) (HMENU)SendMessage((hWndMB), SHCMBM_GETSUBMENU, (WPARAM)0, (LPARAM)ID_MENU)
+
+#undef MessageBox
+
+int MessageBox(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType)
+{
+    TCHAR wText[2048];
+    TCHAR wCaption[2048];
+
+    MultiByteToWideChar (CP_ACP, 0, lpText,    -1, wText,    2048);
+    MultiByteToWideChar (CP_ACP, 0, lpCaption, -1, wCaption, 2048);
+
+    return MessageBoxW (hWnd, wText, wCaption, uType);
+}
+
+BOOL SetDlgItemTextA(HWND hDlg, int nIDDlgItem, LPCSTR lpString)
+{
+    TCHAR wText[256];
+
+    MultiByteToWideChar (CP_ACP, 0, lpString, -1, wText, 256);
+    return SetDlgItemTextW(hDlg, nIDDlgItem, wText);
+}
+
+LPCSTR getenv(LPCSTR buf)
+{
+    return NULL;
+}
+
+BOOL GetKeyboardState(PBYTE pb)
+{
+  return FALSE;
+}
+
+static TCHAR wGameName[256];
+
+#endif
+
 #ifdef DEBUGGING
 static FILE *debug_fp = NULL;
 static HANDLE debug_hdl = INVALID_HANDLE_VALUE;
@@ -90,8 +153,12 @@ void debug_printf(char *fmt, ...)
 }
 #endif
 
+#ifndef _WIN32_WCE
 #define WINFLAGS (WS_OVERLAPPEDWINDOW &~ \
                      (WS_THICKFRAME | WS_MAXIMIZEBOX | WS_OVERLAPPED))
+#else
+#define WINFLAGS (WS_CAPTION | WS_SYSMENU)
+#endif
 
 static void new_game_size(frontend *fe);
 
@@ -116,8 +183,12 @@ enum { CFG_PRINT = CFG_FRONTEND_SPECIFIC };
 struct frontend {
     midend *me;
     HWND hwnd, statusbar, cfgbox;
+#ifdef _WIN32_WCE
+    HWND numpad;  /* window handle for the numeric pad */
+#endif
     HINSTANCE inst;
     HBITMAP bitmap, prevbm;
+    RECT bitmapPosition;  /* game bitmap position within game window */
     HDC hdc;
     COLORREF *colours;
     HBRUSH *brushes;
@@ -185,17 +256,29 @@ char *geterrstr(void)
 
 void get_random_seed(void **randseed, int *randseedsize)
 {
-    time_t *tp = snew(time_t);
-    time(tp);
-    *randseed = (void *)tp;
-    *randseedsize = sizeof(time_t);
+    SYSTEMTIME *st = snew(SYSTEMTIME);
+
+    GetLocalTime(st);
+
+    *randseed = (void *)st;
+    *randseedsize = sizeof(SYSTEMTIME);
 }
 
 static void win_status_bar(void *handle, char *text)
 {
+#ifdef _WIN32_WCE
+    TCHAR wText[255];
+#endif
     frontend *fe = (frontend *)handle;
 
+#ifdef _WIN32_WCE
+    MultiByteToWideChar (CP_ACP, 0, text, -1, wText, 255);
+    SendMessage(fe->statusbar, SB_SETTEXT,
+                (WPARAM) 255 | SBT_NOBORDERS,
+                (LPARAM) wText);
+#else
     SetWindowText(fe->statusbar, text);
+#endif
 }
 
 static blitter *win_blitter_new(void *handle, int w, int h)
@@ -334,13 +417,20 @@ static void win_set_brush(frontend *fe, int colour)
        float r, g, b;
        print_get_colour(fe->dr, colour, &hatch, &r, &g, &b);
 
-       if (fe->printcolour)
+       if (fe->printcolour) {
            br = CreateSolidBrush(RGB(r * 255, g * 255, b * 255));
-       else if (hatch == HATCH_SOLID)
+       } else if (hatch == HATCH_SOLID) {
            br = CreateSolidBrush(RGB(0,0,0));
-       else if (hatch == HATCH_CLEAR)
+       } else if (hatch == HATCH_CLEAR) {
            br = CreateSolidBrush(RGB(255,255,255));
-       else
+       } else {
+#ifdef _WIN32_WCE
+           /*
+            * This is only ever required during printing, and the
+            * PocketPC port doesn't support printing.
+            */
+           fatal("CreateHatchBrush not supported");
+#else
            br = CreateHatchBrush(hatch == HATCH_BACKSLASH ? HS_FDIAGONAL :
                                  hatch == HATCH_SLASH ? HS_BDIAGONAL :
                                  hatch == HATCH_HORIZ ? HS_HORIZONTAL :
@@ -348,6 +438,8 @@ static void win_set_brush(frontend *fe, int colour)
                                  hatch == HATCH_PLUS ? HS_CROSS :
                                  /* hatch == HATCH_X ? */ HS_DIAGCROSS,
                                  RGB(0,0,0));
+#endif
+       }
     } else {
        br = fe->brushes[colour];
     }
@@ -433,6 +525,7 @@ static void win_draw_text(void *handle, int x, int y, int fonttype,
     frontend *fe = (frontend *)handle;
     POINT xy;
     int i;
+    LOGFONT lf;
 
     if (fe->drawstatus == NOTHING)
        return;
@@ -460,15 +553,21 @@ static void win_draw_text(void *handle, int x, int y, int fonttype,
         fe->fonts[i].type = fonttype;
         fe->fonts[i].size = fontsize;
 
-        fe->fonts[i].font = CreateFont(-fontsize, 0, 0, 0,
-                                      fe->drawstatus == PRINTING ? 0 : FW_BOLD,
-                                      FALSE, FALSE, FALSE, DEFAULT_CHARSET,
-                                      OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
-                                      DEFAULT_QUALITY,
-                                      (fonttype == FONT_FIXED ?
-                                       FIXED_PITCH | FF_DONTCARE :
-                                       VARIABLE_PITCH | FF_SWISS),
-                                      NULL);
+        memset (&lf, 0, sizeof(LOGFONT));
+        lf.lfHeight = -fontsize;
+        lf.lfWeight = (fe->drawstatus == PRINTING ? 0 : FW_BOLD);
+        lf.lfCharSet = DEFAULT_CHARSET;
+        lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
+        lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
+        lf.lfQuality = DEFAULT_QUALITY;
+        lf.lfPitchAndFamily = (fonttype == FONT_FIXED ?
+                               FIXED_PITCH | FF_DONTCARE :
+                               VARIABLE_PITCH | FF_SWISS);
+#ifdef _WIN32_WCE
+        wcscpy(lf.lfFaceName, TEXT("Tahoma"));
+#endif
+
+        fe->fonts[i].font = CreateFontIndirect(&lf);
     }
 
     /*
@@ -478,6 +577,10 @@ static void win_draw_text(void *handle, int x, int y, int fonttype,
        HFONT oldfont;
        TEXTMETRIC tm;
        SIZE size;
+#ifdef _WIN32_WCE
+       TCHAR wText[256];
+       MultiByteToWideChar (CP_ACP, 0, text, -1, wText, 256);
+#endif
 
        oldfont = SelectObject(fe->hdc, fe->fonts[i].font);
        if (GetTextMetrics(fe->hdc, &tm)) {
@@ -486,7 +589,11 @@ static void win_draw_text(void *handle, int x, int y, int fonttype,
            else
                xy.y -= tm.tmAscent;
        }
+#ifndef _WIN32_WCE
        if (GetTextExtentPoint32(fe->hdc, text, strlen(text), &size)) {
+#else
+       if (GetTextExtentPoint32(fe->hdc, wText, wcslen(wText), &size)) {
+#endif
            if (align & ALIGN_HCENTRE)
                xy.x -= size.cx / 2;
            else if (align & ALIGN_HRIGHT)
@@ -494,7 +601,11 @@ static void win_draw_text(void *handle, int x, int y, int fonttype,
        }
        SetBkMode(fe->hdc, TRANSPARENT);
        win_text_colour(fe, colour);
+#ifndef _WIN32_WCE
        TextOut(fe->hdc, xy.x, xy.y, text, strlen(text));
+#else
+       ExtTextOut(fe->hdc, xy.x, xy.y, 0, NULL, wText, wcslen(wText), NULL);
+#endif
        SelectObject(fe->hdc, oldfont);
     }
 }
@@ -529,18 +640,17 @@ static void win_draw_rect(void *handle, int x, int y, int w, int h, int colour)
 static void win_draw_line(void *handle, int x1, int y1, int x2, int y2, int colour)
 {
     frontend *fe = (frontend *)handle;
-    POINT p, q;
+    POINT pp[2];
 
     if (fe->drawstatus == NOTHING)
        return;
 
     win_set_pen(fe, colour, FALSE);
-    p = win_transform_point(fe, x1, y1);
-    q = win_transform_point(fe, x2, y2);
-    MoveToEx(fe->hdc, p.x, p.y, NULL);
-    LineTo(fe->hdc, q.x, q.y);
+    pp[0] = win_transform_point(fe, x1, y1);
+    pp[1] = win_transform_point(fe, x2, y2);
+    Polyline(fe->hdc, pp, 2);
     if (fe->drawstatus == DRAWING)
-       SetPixel(fe->hdc, q.x, q.y, fe->colours[colour]);
+       SetPixel(fe->hdc, pp[1].x, pp[1].y, fe->colours[colour]);
     win_reset_pen(fe);
 }
 
@@ -548,29 +658,24 @@ static void win_draw_circle(void *handle, int cx, int cy, int radius,
                            int fillcolour, int outlinecolour)
 {
     frontend *fe = (frontend *)handle;
-    POINT p, q, r;
+    POINT p, q;
 
     assert(outlinecolour >= 0);
 
     if (fe->drawstatus == NOTHING)
        return;
 
-    if (fillcolour >= 0) {
+    if (fillcolour >= 0)
        win_set_brush(fe, fillcolour);
-       win_set_pen(fe, outlinecolour, FALSE);
-       p = win_transform_point(fe, cx - radius, cy - radius);
-       q = win_transform_point(fe, cx + radius, cy + radius);
-       Ellipse(fe->hdc, p.x, p.y, q.x+1, q.y+1);
-       win_reset_brush(fe);
-       win_reset_pen(fe);
-    } else {
-       win_set_pen(fe, outlinecolour, FALSE);
-       p = win_transform_point(fe, cx - radius, cy - radius);
-       q = win_transform_point(fe, cx + radius, cy + radius);
-       r = win_transform_point(fe, cx - radius, cy);
-       Arc(fe->hdc, p.x, p.y, q.x+1, q.y+1, r.x, r.y, r.x, r.y);
-       win_reset_pen(fe);
-    }
+    else
+       fe->oldbr = SelectObject(fe->hdc, GetStockObject(NULL_BRUSH));
+
+    win_set_pen(fe, outlinecolour, FALSE);
+    p = win_transform_point(fe, cx - radius, cy - radius);
+    q = win_transform_point(fe, cx + radius, cy + radius);
+    Ellipse(fe->hdc, p.x, p.y, q.x+1, q.y+1);
+    win_reset_brush(fe);
+    win_reset_pen(fe);
 }
 
 static void win_draw_polygon(void *handle, int *coords, int npoints,
@@ -619,7 +724,9 @@ static void win_start_draw(void *handle)
     fe->prevbm = SelectObject(fe->hdc, fe->bitmap);
     ReleaseDC(fe->hwnd, hdc_win);
     fe->clip = NULL;
+#ifndef _WIN32_WCE
     SetMapMode(fe->hdc, MM_TEXT);
+#endif
     fe->drawstatus = DRAWING;
 }
 
@@ -636,6 +743,7 @@ static void win_draw_update(void *handle, int x, int y, int w, int h)
     r.right = x + w;
     r.bottom = y + h;
 
+    OffsetRect(&r, fe->bitmapPosition.left, fe->bitmapPosition.top);
     InvalidateRect(fe->hwnd, &r, FALSE);
 }
 
@@ -838,6 +946,7 @@ const struct drawing_api win_drawing = {
 
 void print(frontend *fe)
 {
+#ifndef _WIN32_WCE
     PRINTDLG pd;
     char doctitle[256];
     document *doc;
@@ -928,6 +1037,7 @@ void print(frontend *fe)
 
     DeleteDC(pd.hDC);
     document_free(doc);
+#endif
 }
 
 void deactivate_timer(frontend *fe)
@@ -943,7 +1053,7 @@ void activate_timer(frontend *fe)
     if (!fe)
        return;                        /* for non-interactive midend */
     if (!fe->timer) {
-       fe->timer = SetTimer(fe->hwnd, fe->timer, 20, NULL);
+       fe->timer = SetTimer(fe->hwnd, 1, 20, NULL);
        fe->timer_last_tickcount = GetTickCount();
     }
 }
@@ -1000,6 +1110,7 @@ void write_clip(HWND hwnd, char *data)
  */
 static void init_help(void)
 {
+#ifndef _WIN32_WCE
     char b[2048], *p, *q, *r;
     FILE *fp;
 
@@ -1066,8 +1177,11 @@ static void init_help(void)
     }
 
     help_type = NONE;         /* didn't find any */
+#endif
 }
 
+#ifndef _WIN32_WCE
+
 /*
  * Start Help.
  */
@@ -1137,6 +1251,8 @@ static void stop_help(frontend *fe)
     }
 }
 
+#endif
+
 /*
  * Terminate Help on process exit.
  */
@@ -1177,14 +1293,18 @@ static void check_window_size(frontend *fe, int *px, int *py)
        r.right = x;
        r.bottom = y + sy;
        AdjustWindowRectEx(&r, WINFLAGS, TRUE, 0);
+#ifndef _WIN32_WCE
        SetWindowPos(fe->hwnd, NULL, 0, 0, r.right - r.left, r.bottom - r.top,
                     SWP_NOMOVE | SWP_NOZORDER);
+#endif
     }
 
     if (fe->statusbar) {
        GetClientRect(fe->hwnd, &r);
+#ifndef _WIN32_WCE
        SetWindowPos(fe->statusbar, NULL, 0, r.bottom-r.top-sy, r.right-r.left,
                     sy, SWP_NOZORDER);
+#endif
     }
 
     *px = x;
@@ -1215,6 +1335,23 @@ static void get_max_puzzle_size(frontend *fe, int *x, int *y)
     }
 }
 
+#ifdef _WIN32_WCE
+/* Toolbar buttons on the numeric pad */
+static TBBUTTON tbNumpadButtons[] =
+{
+    {0, IDM_KEYEMUL + '1', TBSTATE_ENABLED, TBSTYLE_BUTTON,  0, -1},
+    {1, IDM_KEYEMUL + '2', TBSTATE_ENABLED, TBSTYLE_BUTTON,  0, -1},
+    {2, IDM_KEYEMUL + '3', TBSTATE_ENABLED, TBSTYLE_BUTTON,  0, -1},
+    {3, IDM_KEYEMUL + '4', TBSTATE_ENABLED, TBSTYLE_BUTTON,  0, -1},
+    {4, IDM_KEYEMUL + '5', TBSTATE_ENABLED, TBSTYLE_BUTTON,  0, -1},
+    {5, IDM_KEYEMUL + '6', TBSTATE_ENABLED, TBSTYLE_BUTTON,  0, -1},
+    {6, IDM_KEYEMUL + '7', TBSTATE_ENABLED, TBSTYLE_BUTTON,  0, -1},
+    {7, IDM_KEYEMUL + '8', TBSTATE_ENABLED, TBSTYLE_BUTTON,  0, -1},
+    {8, IDM_KEYEMUL + '9', TBSTATE_ENABLED, TBSTYLE_BUTTON,  0, -1},
+    {9, IDM_KEYEMUL + ' ', TBSTATE_ENABLED, TBSTYLE_BUTTON,  0, -1}
+};
+#endif
+
 static frontend *new_window(HINSTANCE inst, char *game_id, char **error)
 {
     frontend *fe;
@@ -1271,7 +1408,7 @@ static frontend *new_window(HINSTANCE inst, char *game_id, char **error)
     }
 
     if (midend_wants_statusbar(fe->me)) {
-       fe->statusbar = CreateWindowEx(0, STATUSCLASSNAME, "ooh",
+       fe->statusbar = CreateWindowEx(0, STATUSCLASSNAME, TEXT("ooh"),
                                       WS_CHILD | WS_VISIBLE,
                                       0, 0, 0, 0, /* status bar does these */
                                       NULL, NULL, inst, NULL);
@@ -1286,53 +1423,123 @@ static frontend *new_window(HINSTANCE inst, char *game_id, char **error)
     r.bottom = y;
     AdjustWindowRectEx(&r, WINFLAGS, TRUE, 0);
 
+#ifdef _WIN32_WCE
+    fe->hwnd = CreateWindowEx(0, wGameName, wGameName,
+                             WS_VISIBLE,
+                             CW_USEDEFAULT, CW_USEDEFAULT,
+                             CW_USEDEFAULT, CW_USEDEFAULT,
+                             NULL, NULL, inst, NULL);
+
+    {
+       SHMENUBARINFO mbi;
+       RECT rc, rcBar, rcTB, rcClient;
+
+       memset (&mbi, 0, sizeof(SHMENUBARINFO));
+       mbi.cbSize     = sizeof(SHMENUBARINFO);
+       mbi.hwndParent = fe->hwnd;
+       mbi.nToolBarId = IDR_MENUBAR1;
+       mbi.hInstRes   = inst;
+
+       SHCreateMenuBar(&mbi);
+
+       GetWindowRect(fe->hwnd, &rc);
+       GetWindowRect(mbi.hwndMB, &rcBar);
+       rc.bottom -= rcBar.bottom - rcBar.top;
+       MoveWindow(fe->hwnd, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, FALSE);
+
+       if (thegame.flags & REQUIRE_NUMPAD)
+       {
+           fe->numpad = CreateToolbarEx (fe->hwnd,
+                                         WS_VISIBLE | WS_CHILD | CCS_NOPARENTALIGN | TBSTYLE_FLAT,
+                                         0, 10, inst, IDR_PADTOOLBAR,
+                                         tbNumpadButtons, sizeof (tbNumpadButtons) / sizeof (TBBUTTON),
+                                         0, 0, 14, 15, sizeof (TBBUTTON));
+           GetWindowRect(fe->numpad, &rcTB);
+           GetClientRect(fe->hwnd, &rcClient);
+           MoveWindow(fe->numpad, 
+                      0, 
+                      rcClient.bottom - (rcTB.bottom - rcTB.top) - 1,
+                      rcClient.right,
+                      rcTB.bottom - rcTB.top,
+                      FALSE);
+           SendMessage(fe->numpad, TB_SETINDENT, (rcClient.right - (10 * 21)) / 2, 0);
+       }
+       else
+           fe->numpad = NULL;
+    }
+#else
     fe->hwnd = CreateWindowEx(0, thegame.name, thegame.name,
                              WS_OVERLAPPEDWINDOW &~
                              (WS_THICKFRAME | WS_MAXIMIZEBOX),
                              CW_USEDEFAULT, CW_USEDEFAULT,
                              r.right - r.left, r.bottom - r.top,
                              NULL, NULL, inst, NULL);
+#endif
 
     if (midend_wants_statusbar(fe->me)) {
        RECT sr;
        DestroyWindow(fe->statusbar);
-       fe->statusbar = CreateWindowEx(0, STATUSCLASSNAME, "ooh",
+       fe->statusbar = CreateWindowEx(0, STATUSCLASSNAME, TEXT("ooh"),
                                       WS_CHILD | WS_VISIBLE,
                                       0, 0, 0, 0, /* status bar does these */
                                       fe->hwnd, NULL, inst, NULL);
+#ifdef _WIN32_WCE
+       /* Flat status bar looks better on the Pocket PC */
+       SendMessage(fe->statusbar, SB_SIMPLE, (WPARAM) TRUE, 0);
+       SendMessage(fe->statusbar, SB_SETTEXT,
+                               (WPARAM) 255 | SBT_NOBORDERS,
+                               (LPARAM) L"");
+#endif
+
        /*
         * Now resize the window to take account of the status bar.
         */
        GetWindowRect(fe->statusbar, &sr);
        GetWindowRect(fe->hwnd, &r);
+#ifndef _WIN32_WCE
        SetWindowPos(fe->hwnd, NULL, 0, 0, r.right - r.left,
                     r.bottom - r.top + sr.bottom - sr.top,
                     SWP_NOMOVE | SWP_NOZORDER);
+#endif
     } else {
        fe->statusbar = NULL;
     }
 
     {
+#ifndef _WIN32_WCE
        HMENU bar = CreateMenu();
        HMENU menu = CreateMenu();
 
        AppendMenu(bar, MF_ENABLED|MF_POPUP, (UINT)menu, "Game");
-       AppendMenu(menu, MF_ENABLED, IDM_NEW, "New");
-       AppendMenu(menu, MF_ENABLED, IDM_RESTART, "Restart");
-       AppendMenu(menu, MF_ENABLED, IDM_DESC, "Specific...");
-       AppendMenu(menu, MF_ENABLED, IDM_SEED, "Random Seed...");
+#else
+       HMENU menu = SHGetSubMenu(SHFindMenuBar(fe->hwnd), ID_GAME);
+       DeleteMenu(menu, 0, MF_BYPOSITION);
+#endif
+       AppendMenu(menu, MF_ENABLED, IDM_NEW, TEXT("New"));
+       AppendMenu(menu, MF_ENABLED, IDM_RESTART, TEXT("Restart"));
+#ifndef _WIN32_WCE
+       AppendMenu(menu, MF_ENABLED, IDM_DESC, TEXT("Specific..."));
+       AppendMenu(menu, MF_ENABLED, IDM_SEED, TEXT("Random Seed..."));
+#endif
 
        if ((fe->npresets = midend_num_presets(fe->me)) > 0 ||
            thegame.can_configure) {
-           HMENU sub = CreateMenu();
            int i;
+#ifndef _WIN32_WCE
+           HMENU sub = CreateMenu();
 
            AppendMenu(bar, MF_ENABLED|MF_POPUP, (UINT)sub, "Type");
-
+#else
+           HMENU sub = SHGetSubMenu(SHFindMenuBar(fe->hwnd), ID_TYPE);
+           DeleteMenu(sub, 0, MF_BYPOSITION);
+#endif
            fe->presets = snewn(fe->npresets, game_params *);
 
            for (i = 0; i < fe->npresets; i++) {
                char *name;
+#ifdef _WIN32_WCE
+               TCHAR wName[255];
+#endif
 
                midend_fetch_preset(fe->me, i, &name, &fe->presets[i]);
 
@@ -1341,40 +1548,51 @@ static frontend *new_window(HINSTANCE inst, char *game_id, char **error)
                 * with ampersands here.
                 */
 
+#ifndef _WIN32_WCE
                AppendMenu(sub, MF_ENABLED, IDM_PRESETS + 0x10 * i, name);
+#else
+               MultiByteToWideChar (CP_ACP, 0, name, -1, wName, 255);
+               AppendMenu(sub, MF_ENABLED, IDM_PRESETS + 0x10 * i, wName);
+#endif
            }
-
            if (thegame.can_configure) {
-               AppendMenu(sub, MF_ENABLED, IDM_CONFIG, "Custom...");
+               AppendMenu(sub, MF_ENABLED, IDM_CONFIG, TEXT("Custom..."));
            }
        }
 
        AppendMenu(menu, MF_SEPARATOR, 0, 0);
-       AppendMenu(menu, MF_ENABLED, IDM_LOAD, "Load...");
-       AppendMenu(menu, MF_ENABLED, IDM_SAVE, "Save...");
+#ifndef _WIN32_WCE
+       AppendMenu(menu, MF_ENABLED, IDM_LOAD, TEXT("Load..."));
+       AppendMenu(menu, MF_ENABLED, IDM_SAVE, TEXT("Save..."));
        AppendMenu(menu, MF_SEPARATOR, 0, 0);
        if (thegame.can_print) {
-           AppendMenu(menu, MF_ENABLED, IDM_PRINT, "Print...");
+           AppendMenu(menu, MF_ENABLED, IDM_PRINT, TEXT("Print..."));
            AppendMenu(menu, MF_SEPARATOR, 0, 0);
        }
-       AppendMenu(menu, MF_ENABLED, IDM_UNDO, "Undo");
-       AppendMenu(menu, MF_ENABLED, IDM_REDO, "Redo");
+#endif
+       AppendMenu(menu, MF_ENABLED, IDM_UNDO, TEXT("Undo"));
+       AppendMenu(menu, MF_ENABLED, IDM_REDO, TEXT("Redo"));
+#ifndef _WIN32_WCE
        if (thegame.can_format_as_text) {
            AppendMenu(menu, MF_SEPARATOR, 0, 0);
-           AppendMenu(menu, MF_ENABLED, IDM_COPY, "Copy");
+           AppendMenu(menu, MF_ENABLED, IDM_COPY, TEXT("Copy"));
        }
+#endif
        if (thegame.can_solve) {
            AppendMenu(menu, MF_SEPARATOR, 0, 0);
-           AppendMenu(menu, MF_ENABLED, IDM_SOLVE, "Solve");
+           AppendMenu(menu, MF_ENABLED, IDM_SOLVE, TEXT("Solve"));
        }
        AppendMenu(menu, MF_SEPARATOR, 0, 0);
-       AppendMenu(menu, MF_ENABLED, IDM_QUIT, "Exit");
+#ifndef _WIN32_WCE
+       AppendMenu(menu, MF_ENABLED, IDM_QUIT, TEXT("Exit"));
        menu = CreateMenu();
-       AppendMenu(bar, MF_ENABLED|MF_POPUP, (UINT)menu, "Help");
-       AppendMenu(menu, MF_ENABLED, IDM_ABOUT, "About");
+       AppendMenu(bar, MF_ENABLED|MF_POPUP, (UINT)menu, TEXT("Help"));
+#endif
+       AppendMenu(menu, MF_ENABLED, IDM_ABOUT, TEXT("About"));
+#ifndef _WIN32_WCE
         if (help_type != NONE) {
            AppendMenu(menu, MF_SEPARATOR, 0, 0);
-            AppendMenu(menu, MF_ENABLED, IDM_HELPC, "Contents");
+            AppendMenu(menu, MF_ENABLED, IDM_HELPC, TEXT("Contents"));
             if (help_topic) {
                 char *item;
                 assert(thegame.name);
@@ -1385,6 +1603,7 @@ static frontend *new_window(HINSTANCE inst, char *game_id, char **error)
             }
         }
        SetMenu(fe->hwnd, bar);
+#endif
     }
 
     fe->bitmap = NULL;
@@ -1393,7 +1612,7 @@ static frontend *new_window(HINSTANCE inst, char *game_id, char **error)
 
     SetWindowLong(fe->hwnd, GWL_USERDATA, (LONG)fe);
 
-    ShowWindow(fe->hwnd, SW_NORMAL);
+    ShowWindow(fe->hwnd, SW_SHOWNORMAL);
     SetForegroundWindow(fe->hwnd);
 
     midend_redraw(fe->me);
@@ -1401,6 +1620,36 @@ static frontend *new_window(HINSTANCE inst, char *game_id, char **error)
     return fe;
 }
 
+#ifdef _WIN32_WCE
+static HFONT dialog_title_font()
+{
+    static HFONT hf = NULL;
+    LOGFONT lf;
+
+    if (hf)
+       return hf;
+
+    memset (&lf, 0, sizeof(LOGFONT));
+    lf.lfHeight = -11; /* - ((8 * GetDeviceCaps(hdc, LOGPIXELSY)) / 72) */
+    lf.lfWeight = FW_BOLD;
+    wcscpy(lf.lfFaceName, TEXT("Tahoma"));
+
+    return hf = CreateFontIndirect(&lf);
+}
+
+static void make_dialog_full_screen(HWND hwnd)
+{
+    SHINITDLGINFO shidi;
+
+    /* Make dialog full screen */
+    shidi.dwMask = SHIDIM_FLAGS;
+    shidi.dwFlags = SHIDIF_DONEBUTTON | SHIDIF_SIZEDLGFULLSCREEN |
+                    SHIDIF_EMPTYMENU;
+    shidi.hDlg = hwnd;
+    SHInitDialog(&shidi);
+}
+#endif
+
 static int CALLBACK AboutDlgProc(HWND hwnd, UINT msg,
                                 WPARAM wParam, LPARAM lParam)
 {
@@ -1408,17 +1657,39 @@ static int CALLBACK AboutDlgProc(HWND hwnd, UINT msg,
 
     switch (msg) {
       case WM_INITDIALOG:
-       return 0;
+#ifdef _WIN32_WCE
+       {
+           char title[256];
+
+           make_dialog_full_screen(hwnd);
+
+           sprintf(title, "About %.250s", thegame.name);
+           SetDlgItemTextA(hwnd, IDC_ABOUT_CAPTION, title);
+
+           SendDlgItemMessage(hwnd, IDC_ABOUT_CAPTION, WM_SETFONT,
+                              (WPARAM) dialog_title_font(), 0);
+
+           SetDlgItemTextA(hwnd, IDC_ABOUT_GAME, thegame.name);
+           SetDlgItemTextA(hwnd, IDC_ABOUT_VERSION, ver);
+       }
+#endif
+       return TRUE;
 
       case WM_COMMAND:
-       if ((HIWORD(wParam) == BN_CLICKED ||
-            HIWORD(wParam) == BN_DOUBLECLICKED) &&
-           LOWORD(wParam) == IDOK)
+       if (LOWORD(wParam) == IDOK)
+#ifdef _WIN32_WCE
+           EndDialog(hwnd, 1);
+#else
            fe->dlg_done = 1;
+#endif
        return 0;
 
       case WM_CLOSE:
+#ifdef _WIN32_WCE
+       EndDialog(hwnd, 1);
+#else
        fe->dlg_done = 1;
+#endif
        return 0;
     }
 
@@ -1525,6 +1796,117 @@ static char *frontend_set_config(frontend *fe, int which, config_item *cfg)
     }
 }
 
+#ifdef _WIN32_WCE
+/* Separate version of mkctrl function for the Pocket PC. */
+/* Control coordinates should be specified in dialog units. */
+HWND mkctrl(frontend *fe, int x1, int x2, int y1, int y2,
+           LPCTSTR wclass, int wstyle,
+           int exstyle, const char *wtext, int wid)
+{
+    RECT rc;
+    TCHAR wwtext[256];
+
+    /* Convert dialog units into pixels */
+    rc.left = x1;  rc.right  = x2;
+    rc.top  = y1;  rc.bottom = y2;
+    MapDialogRect(fe->cfgbox, &rc);
+
+    MultiByteToWideChar (CP_ACP, 0, wtext, -1, wwtext, 256);
+
+    return CreateWindowEx(exstyle, wclass, wwtext,
+                         wstyle | WS_CHILD | WS_VISIBLE,
+                         rc.left, rc.top,
+                         rc.right - rc.left, rc.bottom - rc.top,
+                         fe->cfgbox, (HMENU) wid, fe->inst, NULL);
+}
+
+static void create_config_controls(frontend * fe)
+{
+    int id, nctrls;
+    int col1l, col1r, col2l, col2r, y;
+    config_item *i;
+    struct cfg_aux *j;
+    HWND ctl;
+
+    /* Control placement done in dialog units */
+    col1l = 4;   col1r = 96;   /* Label column */
+    col2l = 100; col2r = 154;  /* Input column (edit boxes and combo boxes) */
+
+    /*
+     * Count the controls so we can allocate cfgaux.
+     */
+    for (nctrls = 0, i = fe->cfg; i->type != C_END; i++)
+       nctrls++;
+    fe->cfgaux = snewn(nctrls, struct cfg_aux);
+
+    id = 1000;
+    y = 22; /* Leave some room for the dialog title */
+    for (i = fe->cfg, j = fe->cfgaux; i->type != C_END; i++, j++) {
+       switch (i->type) {
+         case C_STRING:
+           /*
+            * Edit box with a label beside it.
+            */
+           mkctrl(fe, col1l, col1r, y + 1, y + 11,
+                  TEXT("Static"), SS_LEFTNOWORDWRAP, 0, i->name, id++);
+           mkctrl(fe, col2l, col2r, y, y + 12,
+                  TEXT("EDIT"), WS_BORDER | WS_TABSTOP | ES_AUTOHSCROLL,
+                  0, "", (j->ctlid = id++));
+           SetDlgItemTextA(fe->cfgbox, j->ctlid, i->sval);
+           break;
+
+         case C_BOOLEAN:
+           /*
+            * Simple checkbox.
+            */
+           mkctrl(fe, col1l, col2r, y + 1, y + 11, TEXT("BUTTON"),
+                  BS_NOTIFY | BS_AUTOCHECKBOX | WS_TABSTOP,
+                  0, i->name, (j->ctlid = id++));
+           CheckDlgButton(fe->cfgbox, j->ctlid, (i->ival != 0));
+           break;
+
+         case C_CHOICES:
+           /*
+            * Drop-down list with a label beside it.
+            */
+           mkctrl(fe, col1l, col1r, y + 1, y + 11,
+                  TEXT("STATIC"), SS_LEFTNOWORDWRAP, 0, i->name, id++);
+           ctl = mkctrl(fe, col2l, col2r, y, y + 48,
+                        TEXT("COMBOBOX"), WS_BORDER | WS_TABSTOP |
+                        CBS_DROPDOWNLIST | CBS_HASSTRINGS,
+                        0, "", (j->ctlid = id++));
+           {
+               char c, *p, *q, *str;
+
+               p = i->sval;
+               c = *p++;
+               while (*p) {
+                   q = p;
+                   while (*q && *q != c) q++;
+                   str = snewn(q-p+1, char);
+                   strncpy(str, p, q-p);
+                   str[q-p] = '\0';
+                   {
+                       TCHAR ws[50];
+                       MultiByteToWideChar (CP_ACP, 0, str, -1, ws, 50);
+                       SendMessage(ctl, CB_ADDSTRING, 0, (LPARAM)ws);
+                   }
+                   
+                   sfree(str);
+                   if (*q) q++;
+                   p = q;
+               }
+           }
+           SendMessage(ctl, CB_SETCURSEL, i->ival, 0);
+           break;
+       }
+
+       y += 15;
+    }
+
+}
+#endif
+
 static int CALLBACK ConfigDlgProc(HWND hwnd, UINT msg,
                                  WPARAM wParam, LPARAM lParam)
 {
@@ -1534,15 +1916,32 @@ static int CALLBACK ConfigDlgProc(HWND hwnd, UINT msg,
 
     switch (msg) {
       case WM_INITDIALOG:
-       return 0;
+#ifdef _WIN32_WCE
+       {
+            char *title;
+
+           fe = (frontend *) lParam;
+           SetWindowLong(hwnd, GWL_USERDATA, lParam);
+           fe->cfgbox = hwnd;
+
+            fe->cfg = frontend_get_config(fe, fe->cfg_which, &title);
+
+           make_dialog_full_screen(hwnd);
+
+           SetDlgItemTextA(hwnd, IDC_CONFIG_CAPTION, title);
+           SendDlgItemMessage(hwnd, IDC_CONFIG_CAPTION, WM_SETFONT,
+                              (WPARAM) dialog_title_font(), 0);
+
+           create_config_controls(fe);
+       }
+#endif
+       return TRUE;
 
       case WM_COMMAND:
        /*
         * OK and Cancel are special cases.
         */
-       if ((HIWORD(wParam) == BN_CLICKED ||
-            HIWORD(wParam) == BN_DOUBLECLICKED) &&
-           (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)) {
+       if ((LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)) {
            if (LOWORD(wParam) == IDOK) {
                char *err = frontend_set_config(fe, fe->cfg_which, fe->cfg);
 
@@ -1550,10 +1949,18 @@ static int CALLBACK ConfigDlgProc(HWND hwnd, UINT msg,
                    MessageBox(hwnd, err, "Validation error",
                               MB_ICONERROR | MB_OK);
                } else {
+#ifdef _WIN32_WCE
+                   EndDialog(hwnd, 2);
+#else
                    fe->dlg_done = 2;
+#endif
                }
            } else {
+#ifdef _WIN32_WCE
+               EndDialog(hwnd, 1);
+#else
                fe->dlg_done = 1;
+#endif
            }
            return 0;
        }
@@ -1570,13 +1977,19 @@ static int CALLBACK ConfigDlgProc(HWND hwnd, UINT msg,
 
        if (i->type == C_STRING && HIWORD(wParam) == EN_CHANGE) {
            char buffer[4096];
+#ifdef _WIN32_WCE
+           TCHAR wBuffer[4096];
+           GetDlgItemText(fe->cfgbox, j->ctlid, wBuffer, 4096);
+           WideCharToMultiByte(CP_ACP, 0, wBuffer, -1, buffer, 4096, NULL, NULL);
+#else
            GetDlgItemText(fe->cfgbox, j->ctlid, buffer, lenof(buffer));
+#endif
            buffer[lenof(buffer)-1] = '\0';
            sfree(i->sval);
            i->sval = dupstr(buffer);
        } else if (i->type == C_BOOLEAN && 
                   (HIWORD(wParam) == BN_CLICKED ||
-                   HIWORD(wParam) == BN_DOUBLECLICKED)) {
+                   HIWORD(wParam) == BN_DBLCLK)) {
            i->ival = IsDlgButtonChecked(fe->cfgbox, j->ctlid);
        } else if (i->type == C_CHOICES &&
                   HIWORD(wParam) == CBN_SELCHANGE) {
@@ -1594,6 +2007,7 @@ static int CALLBACK ConfigDlgProc(HWND hwnd, UINT msg,
     return 0;
 }
 
+#ifndef _WIN32_WCE
 HWND mkctrl(frontend *fe, int x1, int x2, int y1, int y2,
            char *wclass, int wstyle,
            int exstyle, const char *wtext, int wid)
@@ -1605,9 +2019,13 @@ HWND mkctrl(frontend *fe, int x1, int x2, int y1, int y2,
     SendMessage(ret, WM_SETFONT, (WPARAM)fe->cfgfont, MAKELPARAM(TRUE, 0));
     return ret;
 }
+#endif
 
 static void about(frontend *fe)
 {
+#ifdef _WIN32_WCE
+    DialogBox(fe->inst, MAKEINTRESOURCE(IDD_ABOUT), fe->hwnd, AboutDlgProc);
+#else
     int i;
     WNDCLASS wc;
     MSG msg;
@@ -1629,7 +2047,7 @@ static void about(frontend *fe)
     strings[nstrings++] = "from Simon Tatham's Portable Puzzle Collection";
     strings[nstrings++] = ver;
 
-    wc.style = CS_DBLCLKS | CS_SAVEBITS | CS_BYTEALIGNWINDOW;
+    wc.style = CS_DBLCLKS | CS_SAVEBITS;
     wc.lpfnWndProc = DefDlgProc;
     wc.cbClsExtra = 0;
     wc.cbWndExtra = DLGWINDOWEXTRA + 8;
@@ -1745,7 +2163,7 @@ static void about(frontend *fe)
     SendMessage(fe->cfgbox, WM_INITDIALOG, 0, 0);
 
     EnableWindow(fe->hwnd, FALSE);
-    ShowWindow(fe->cfgbox, SW_NORMAL);
+    ShowWindow(fe->cfgbox, SW_SHOWNORMAL);
     while ((gm=GetMessage(&msg, NULL, 0, 0)) > 0) {
        if (!IsDialogMessage(fe->cfgbox, &msg))
            DispatchMessage(&msg);
@@ -1756,10 +2174,19 @@ static void about(frontend *fe)
     SetForegroundWindow(fe->hwnd);
     DestroyWindow(fe->cfgbox);
     DeleteObject(fe->cfgfont);
+#endif
 }
 
 static int get_config(frontend *fe, int which)
 {
+#ifdef _WIN32_WCE
+    fe->cfg_which = which;
+
+    return DialogBoxParam(fe->inst,
+                         MAKEINTRESOURCE(IDD_CONFIG),
+                         fe->hwnd, ConfigDlgProc,
+                         (LPARAM) fe) == 2;
+#else
     config_item *i;
     struct cfg_aux *j;
     char *title;
@@ -1774,7 +2201,7 @@ static int get_config(frontend *fe, int which)
     int winwidth, winheight, col1l, col1r, col2l, col2r, y;
     int height, width, maxlabel, maxcheckbox;
 
-    wc.style = CS_DBLCLKS | CS_SAVEBITS | CS_BYTEALIGNWINDOW;
+    wc.style = CS_DBLCLKS | CS_SAVEBITS;
     wc.lpfnWndProc = DefDlgProc;
     wc.cbClsExtra = 0;
     wc.cbWndExtra = DLGWINDOWEXTRA + 8;
@@ -1981,7 +2408,7 @@ static int get_config(frontend *fe, int which)
     SendMessage(fe->cfgbox, WM_INITDIALOG, 0, 0);
 
     EnableWindow(fe->hwnd, FALSE);
-    ShowWindow(fe->cfgbox, SW_NORMAL);
+    ShowWindow(fe->cfgbox, SW_SHOWNORMAL);
     while ((gm=GetMessage(&msg, NULL, 0, 0)) > 0) {
        if (!IsDialogMessage(fe->cfgbox, &msg))
            DispatchMessage(&msg);
@@ -1997,8 +2424,48 @@ static int get_config(frontend *fe, int which)
     sfree(fe->cfgaux);
 
     return (fe->dlg_done == 2);
+#endif
 }
 
+#ifdef _WIN32_WCE
+static void calculate_bitmap_position(frontend *fe, int x, int y)
+{
+    /* Pocket PC - center the game in the full screen window */
+    int yMargin;
+    RECT rcClient;
+
+    GetClientRect(fe->hwnd, &rcClient);
+    fe->bitmapPosition.left = (rcClient.right  - x) / 2;
+    yMargin = rcClient.bottom - y;
+
+    if (fe->numpad != NULL) {
+       RECT rcPad;
+       GetWindowRect(fe->numpad, &rcPad);
+       yMargin -= rcPad.bottom - rcPad.top;
+    }
+
+    if (fe->statusbar != NULL) {
+       RECT rcStatus;
+       GetWindowRect(fe->statusbar, &rcStatus);
+       yMargin -= rcStatus.bottom - rcStatus.top;
+    }
+
+    fe->bitmapPosition.top = yMargin / 2;
+
+    fe->bitmapPosition.right  = fe->bitmapPosition.left + x;
+    fe->bitmapPosition.bottom = fe->bitmapPosition.top  + y;
+}
+#else
+static void calculate_bitmap_position(frontend *fe, int x, int y)
+{
+    /* Plain Windows - position the game in the upper-left corner */
+    fe->bitmapPosition.left = 0;
+    fe->bitmapPosition.top = 0;
+    fe->bitmapPosition.right  = fe->bitmapPosition.left + x;
+    fe->bitmapPosition.bottom = fe->bitmapPosition.top  + y;
+}
+#endif
+
 static void new_game_size(frontend *fe)
 {
     RECT r, sr;
@@ -2018,23 +2485,31 @@ static void new_game_size(frontend *fe)
     } else {
        sr.left = sr.right = sr.top = sr.bottom = 0;
     }
+#ifndef _WIN32_WCE
     SetWindowPos(fe->hwnd, NULL, 0, 0,
                 r.right - r.left,
                 r.bottom - r.top + sr.bottom - sr.top,
                 SWP_NOMOVE | SWP_NOZORDER);
+#endif
 
     check_window_size(fe, &x, &y);
 
+#ifndef _WIN32_WCE
     if (fe->statusbar != NULL)
        SetWindowPos(fe->statusbar, NULL, 0, y, x,
                     sr.bottom - sr.top, SWP_NOZORDER);
+#endif
 
     if (fe->bitmap) DeleteObject(fe->bitmap);
 
     hdc = GetDC(fe->hwnd);
     fe->bitmap = CreateCompatibleBitmap(hdc, x, y);
+    calculate_bitmap_position(fe, x, y);
     ReleaseDC(fe->hwnd, hdc);
 
+#ifdef _WIN32_WCE
+    InvalidateRect(fe->hwnd, NULL, TRUE);
+#endif
     midend_redraw(fe->me);
 }
 
@@ -2083,6 +2558,13 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
        DestroyWindow(hwnd);
        return 0;
       case WM_COMMAND:
+#ifdef _WIN32_WCE
+       /* Numeric pad sends WM_COMMAND messages */
+       if ((wParam >= IDM_KEYEMUL) && (wParam < IDM_KEYEMUL + 256))
+       {
+           midend_process_key(fe->me, 0, 0, wParam - IDM_KEYEMUL);
+       }
+#endif
        cmd = wParam & ~0xF;           /* low 4 bits reserved to Windows */
        switch (cmd) {
          case IDM_NEW:
@@ -2227,12 +2709,14 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
            }
 
            break;
+#ifndef _WIN32_WCE
           case IDM_HELPC:
            start_help(fe, NULL);
            break;
           case IDM_GAMEHELP:
            start_help(fe, help_topic);
             break;
+#endif
          default:
            {
                int p = ((wParam &~ 0xF) - IDM_PRESETS) / 0x10;
@@ -2246,7 +2730,9 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
        }
        break;
       case WM_DESTROY:
+#ifndef _WIN32_WCE
        stop_help(fe);
+#endif
        PostQuitMessage(0);
        return 0;
       case WM_PAINT:
@@ -2254,16 +2740,22 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
            PAINTSTRUCT p;
            HDC hdc, hdc2;
            HBITMAP prevbm;
+           RECT rcDest;
 
            hdc = BeginPaint(hwnd, &p);
            hdc2 = CreateCompatibleDC(hdc);
            prevbm = SelectObject(hdc2, fe->bitmap);
+#ifdef _WIN32_WCE
+           FillRect(hdc, &(p.rcPaint), (HBRUSH) GetStockObject(WHITE_BRUSH));
+#endif
+           IntersectRect(&rcDest, &(fe->bitmapPosition), &(p.rcPaint));
            BitBlt(hdc,
-                  p.rcPaint.left, p.rcPaint.top,
-                  p.rcPaint.right - p.rcPaint.left,
-                  p.rcPaint.bottom - p.rcPaint.top,
+                  rcDest.left, rcDest.top,
+                  rcDest.right - rcDest.left,
+                  rcDest.bottom - rcDest.top,
                   hdc2,
-                  p.rcPaint.left, p.rcPaint.top,
+                  rcDest.left - fe->bitmapPosition.left,
+                  rcDest.top - fe->bitmapPosition.top,
                   SRCCOPY);
            SelectObject(hdc2, prevbm);
            DeleteDC(hdc2);
@@ -2368,10 +2860,32 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
            else if (message == WM_RBUTTONDOWN || is_alt_pressed())
                button = RIGHT_BUTTON;
            else
+#ifndef _WIN32_WCE
                button = LEFT_BUTTON;
+#else
+               if ((thegame.flags & REQUIRE_RBUTTON) == 0)
+                   button = LEFT_BUTTON;
+               else
+               {
+                   SHRGINFO shrgi;
+
+                   shrgi.cbSize     = sizeof(SHRGINFO);
+                   shrgi.hwndClient = hwnd;
+                   shrgi.ptDown.x   = (signed short)LOWORD(lParam);
+                   shrgi.ptDown.y   = (signed short)HIWORD(lParam);
+                   shrgi.dwFlags    = SHRG_RETURNCMD;
+
+                   if (GN_CONTEXTMENU == SHRecognizeGesture(&shrgi))
+                       button = RIGHT_BUTTON;
+                   else
+                       button = LEFT_BUTTON;
+               }
+#endif
 
-           if (!midend_process_key(fe->me, (signed short)LOWORD(lParam),
-                                   (signed short)HIWORD(lParam), button))
+           if (!midend_process_key(fe->me,
+                                   (signed short)LOWORD(lParam) - fe->bitmapPosition.left,
+                                   (signed short)HIWORD(lParam) - fe->bitmapPosition.top,
+                                   button))
                PostQuitMessage(0);
 
            SetCapture(hwnd);
@@ -2395,8 +2909,10 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
            else
                button = LEFT_RELEASE;
 
-           if (!midend_process_key(fe->me, (signed short)LOWORD(lParam),
-                                   (signed short)HIWORD(lParam), button))
+           if (!midend_process_key(fe->me,
+                                   (signed short)LOWORD(lParam) - fe->bitmapPosition.left,
+                                   (signed short)HIWORD(lParam) - fe->bitmapPosition.top,
+                                   button))
                PostQuitMessage(0);
 
            ReleaseCapture();
@@ -2413,8 +2929,10 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
            else
                button = LEFT_DRAG;
            
-           if (!midend_process_key(fe->me, (signed short)LOWORD(lParam),
-                                   (signed short)HIWORD(lParam), button))
+           if (!midend_process_key(fe->me,
+                                   (signed short)LOWORD(lParam) - fe->bitmapPosition.left,
+                                   (signed short)HIWORD(lParam) - fe->bitmapPosition.top,
+                                   button))
                PostQuitMessage(0);
        }
        break;
@@ -2435,11 +2953,34 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
     return DefWindowProc(hwnd, message, wParam, lParam);
 }
 
+#ifdef _WIN32_WCE
+static int FindPreviousInstance()
+{
+    /* Check if application is running. If it's running then focus on the window */
+    HWND hOtherWnd = NULL;
+
+    hOtherWnd = FindWindow (wGameName, wGameName);
+    if (hOtherWnd)
+    {
+        SetForegroundWindow (hOtherWnd);
+        return TRUE;
+    }
+
+    return FALSE;
+}
+#endif
+
 int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
 {
     MSG msg;
     char *error;
 
+#ifdef _WIN32_WCE
+    MultiByteToWideChar (CP_ACP, 0, thegame.name, -1, wGameName, 256);
+    if (FindPreviousInstance ())
+        return 0;
+#endif
+
     InitCommonControls();
 
     if (!prev) {
@@ -2451,12 +2992,18 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
        wndclass.cbWndExtra = 0;
        wndclass.hInstance = inst;
        wndclass.hIcon = LoadIcon(inst, MAKEINTRESOURCE(200));
+#ifndef _WIN32_WCE
        if (!wndclass.hIcon)           /* in case resource file is absent */
            wndclass.hIcon = LoadIcon(inst, IDI_APPLICATION);
+#endif
        wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
        wndclass.hbrBackground = NULL;
        wndclass.lpszMenuName = NULL;
+#ifdef _WIN32_WCE
+       wndclass.lpszClassName = wGameName;
+#else
        wndclass.lpszClassName = thegame.name;
+#endif
 
        RegisterClass(&wndclass);
     }