This provides a standard way to get a boolean from an environment
variable. It treats the variable as true iff its value begins with 'y'
or 'Y', like most of the current implementations. The function takes a
default value which it returns if the environment variable is undefined.
This replaces the various ad-hoc tests of environment variable scattered
around and mostly doesn't change their behaviour. The exceptions are
TOWERS_2D in Towers and DEBUG_PUZZLES in the Windows front end. Both of
those were treated as true if they were defined at all, but now follow
the same rules as other boolean environment variables.
This adds a new bool * argument, which can be NULL if front ends don't
care whether the keypress was handled. Currently they all do that.
Currently, "undo" and "redo" keys are treated as not handled if there's
no move to undo or redo. This may be a little too strict.
The device pixel ratio indicates how many physical pixels there are in
the platonic ideal of a pixel, at least approximately. In Web browsers,
the device pixel ratio is used to represent "retina" displays with
particularly high pixel densities, and also to reflect user-driven
zooming of the page to different text sizes.
The mid-end uses the device pixel ratio to adjust the tile size at
startup, and can also respond to changes in device pixel ratio by
adjusting the time size later. This is accomplished through a new
argument to midend_size() which can simply be passed as 1.0 in any front
end that doesn't care about this.
The purpose of check_window_size is to be run after we try to resize
the puzzle window, decide whether the window size needs a further
update, and if so, make it. But the SetWindowPos call that actually
made the update (triggered by the subroutine check_window_resize
returning true to indicate that a change was needed) had mysteriously
gone missing.
An example case where this goes wrong: start up a puzzle at a game
size large enough to need a tile size smaller than default. Then
change the setting to one so small that the menu bar is now the
limiting factor on how small the window can be. (For example, changing
Mosaic from its 50x50 preset to 3x3, if your monitor isn't so huge
that the former fits.) The window comes out the wrong size, and with
this SetWindowPos reinstated, now it gets corrected.
What seems to have happened was that the SetWindowPos was originally
under #ifndef _WIN32_WCE, i.e. we only want to do it on desktop
Windows, not on CE. Then commit 39d299f579da3e9 (introducing manual
window resizing in the Windows front end) moved the call into a
different function, and in the process, accidentally reversed the
sense of the #ifdef. And then commit ff3e762fd007883 (removing the
bit-rotted Windows CE support completely) removed it, along with
everything else under #ifndef _WIN32_WCE!
It was originally supposed to be _enabled_ on desktop Windows, not
disabled. So I've put it back now.
These came from Visual Studio, and seem to be real problems - we're
casting pointers to 32-bit integers, which surely only works by luck
of address-space allocation.
The WinCE version of these puzzles hasn't been built for years, and
the last vestiges of its build system vanished with the migration to
CMake. So this seems like a good moment to lose the rest of it.
So the supporting Perl script wceinf.pl is deleted, and so is all the
unused code under '#ifdef _WIN32_WCE' in windows.c. (I removed that
using unifdef, which did a more reliable job than I would have done by
hand!)
Thanks to Rocco Matano for reporting that in the -DCOMBINED version of
the Windows front end, switching games causes a crash because the
presets menu from the old midend is still left over in fe, and its
presence inhibits the setup code from making a new one. Now we throw
it out at the same time as we throw out the old midend itself.
Also, the condition 'if (!fe->preset_menu)' was misguided. I think the
point of that was to avoid pointlessly tearing down and rebuilding the
preset menu when we're _not_ changing game - but that's a cost too
small to worry about if it causes the slightest trouble. Now
fe->preset_menu should always be NULL at that point in the function,
so I've replaced the if with an assert.
This is the main bulk of this boolification work, but although it's
making the largest actual change, it should also be the least
disruptive to anyone interacting with this code base downstream of me,
because it doesn't modify any interface between modules: all the
inter-module APIs were updated one by one in the previous commits.
This just cleans up the code within each individual source file to use
bool in place of int where I think that makes things clearer.
This commit removes the old #defines of TRUE and FALSE from puzzles.h,
and does a mechanical search-and-replace throughout the code to
replace them with the C99 standard lowercase spellings.
Not many changes here: the 'dotted' flag passed to print_line_dotted
is bool, and so is the printing_in_colour flag passed to
print_get_colour. Also ps_init() takes a bool.
line_dotted is also a method in the drawing API structure, but it's
not actually filled in for any non-print-oriented implementation of
that API. So only front ends that do platform-specific _printing_
should need to make a corresponding change. In-tree, for example,
windows.c needed a fix because it prints via Windows GDI, but gtk.c
didn't have to do anything, because its CLI-based printing facility
just delegates to ps.c.
This changes parameters of midend_size and midend_print_puzzle, the
return types of midend_process_key, midend_wants_statusbar,
midend_can_format_as_text_now and midend_can_{undo,redo}, the 'bval'
field in struct config_item, and finally the return type of the
function pointer passed to midend_deserialise and identify_game.
The last of those changes requires a corresponding fix in clients of
midend_deserialise and identify_game, so in this commit I've also
updated all the in-tree front ends to match. I expect downstream front
ends will need to do the same when they merge this change.
I went through all the char * parameters and return values I could see
in puzzles.h by eye and spotted ones that surely ought to have been
const all along.
This allows me to use different types for the mutable, dynamically
allocated string value in a C_STRING control and the fixed constant
list of option names in a C_CHOICES.
If I increase clang-cl's warning pickiness, it starts objecting to my
cast to HMENU from a (potentially, in 64 bits) smaller integer type.
Actually I don't think there's a problem there - all the integer ids I
cast to HMENU are nice small numbers and a widening cast is just fine.
But I can suppress the warning by using INT_PTR instead of int in the
prototype for mkctrl, so it's easiest just to do that.
This is in addition to the existing keystrokes r, ^R and ^Y. I've
become used to Ctrl-Shift-Z in other GUI games, and my fingers keep
getting confused when my own puzzles don't handle it the same way.
This fixes an amusing UI bug that I think can currently only come up
in the unpublished puzzle 'Group', but there's no reason why other
puzzles _couldn't_ do the thing that triggers the bug, if they wanted
to.
Group has unusual keyboard handling, in that sometimes (when a cell is
selected for input and the key in question is valid for the current
puzzle size) the game's interpret_move function will eat keystrokes
like 'n' and 'u' that would otherwise trigger special UI events like
New Game or Undo.
The bug is that fake keypress events generated from the GUI menus
looked enough like those keystrokes that interpret_move would eat
those too. So if you start, say, a 16x16 Group puzzle, select an empty
cell, and then choose 'new game' from the menu, Group will enter 'n'
into the cell instead of starting a new game!
I've fixed this by inventing a new set of special keystroke values
called things like UI_NEWGAME and UI_UNDO, and having the GUI menus in
all my front ends generate those in place of 'n' and 'u'. So now the
midend can tell the difference between 'n' on the keyboard and New
Game from the menu, and so Group can treat them differently too. In
fact, out of sheer overcaution, midend.c will spot keystrokes in this
range and not even _pass_ them to the game back end, so Group
shouldn't be able to override these special events even by mistake.
One fiddly consequence is that in gtk.c I've had to rethink the menu
accelerator system. I was adding visible menu accelerators to a few
menu items, so that (for example) 'U' and 'R' showed up to the right
of Undo and Redo in the menu. Of course this had the side effect of
making them real functioning accelerators from GTK's point of view,
which activate the menu item in the same way as usual, causing it to
send whatever keystroke the menu item generates. In other words,
whenever I entered 'n' into a cell in a large Group game, this was the
route followed by even a normal 'n' originated from a real keystroke -
it activated the New Game menu item by mistake, which would then send
'n' by mistake instead of starting a new game!
Those mistakes cancelled each other out, but now I've fixed the
latter, I've had to fix the former too or else the GTK front end would
now undo all of this good work, by _always_ translating 'n' on the
keyboard to UI_NEWGAME, even if the puzzle would have wanted to treat
a real press of 'n' differently. So I've fixed _that_ in turn by
putting those menu accelerators in a GtkAccelGroup that is never
actually enabled on the main window, so the accelerator keys will be
displayed in the menu but not processed by GTK's keyboard handling.
(Also, while I was redoing this code, I've removed the logic in
add_menu_item_with_key that reverse-engineered an ASCII value into
Control and Shift modifiers plus a base key, because the only
arguments to that function were fixed at compile time anyway so it's
easier to just write the results of that conversion directly into the
call sites; and I've added the GTK_ACCEL_LOCKED flag, in recognition
of the fact that _because_ these accelerators are processed by a weird
mechanism, they cannot be dynamically reconfigured by users and
actually work afterwards.)
To do this, I've completely replaced the API between mid-end and front
end, so any downstream front end maintainers will have to do some
rewriting of their own (sorry). I've done the necessary work in all
five of the front ends I keep in-tree here - Windows, GTK, OS X,
Javascript/Emscripten, and Java/NestedVM - and I've done it in various
different styles (as each front end found most convenient), so that
should provide a variety of sample code to show downstreams how, if
they should need it.
I've left in the old puzzle back-end API function to return a flat
list of presets, so for the moment, all the puzzle backends are
unchanged apart from an extra null pointer appearing in their
top-level game structure. In a future commit I'll actually use the new
feature in a puzzle; perhaps in the further future it might make sense
to migrate all the puzzles to the new API and stop providing back ends
with two alternative ways of doing things, but this seemed like enough
upheaval for one day.
MultiByteToWideChar expects a WCHAR[256] output buffer if you pass it
an output length of 256. TCHAR[256] is entirely the wrong size, though
for some reason Visual Studio seems not to have thrown a compile error
pointing that out.
Thanks to Jason Hood for spotting this.
The Windows puzzles now accept similar command-line syntax to the GTK
ones, in that you can give them either a game ID (descriptive, random
or just plain params) or the name of a save file. Unlike the GTK ones,
however, the save file interpretation is tried first; this is because
some puzzles (e.g. Black Box) will interpret any old string as a valid
(if boring) game ID, and unlike the GTK puzzles it's not feasible to
require users to disambiguate via a command-line option, because on
Windows a thing that might easily happen is that a user passes a save
file to a puzzle binary via 'Open With' in the GUI shell, where they
don't get the chance to add extra options.
In order to make this work sensibly in the all-in-one Windows app, I
had to get round to another thing I've been planning to do for a
while, which is to write a function to examine a saved game file and
find out which puzzle it's for. So the combined Windows binary will
auto-switch to the right game if you pass a save file on its command
line, and also if you use Load while the program is running.
Another utility function I needed is one to split the WinMain single
command line string into argv. For this I've imported a copy of
split_into_argv() from Windows PuTTY (which doesn't affect this
package's list of copyright holders, since that function was all my
own code anyway).
[originally from svn r9749]
new function in the drawing API which permits the display of text
from outside basic ASCII. A fallback mechanism is provided so that
puzzles can give a list of strings they'd like to display in order
of preference and the system will return the best one it can manage;
puzzles are required to cope with ASCII-only front ends.
[originally from svn r8793]
alongside the individual puzzle binaries, on Windows only. (MacOS
already has it, of course; Unix would require about as much work
again.)
[originally from svn r8396]
_conditionally_ able to format the current puzzle as text to be sent
to the clipboard. For instance, if a game were to support playing on
a square grid and on other kinds of grid such as hexagonal, then it
might reasonably feel that only the former could be sensibly
rendered in ASCII art; so it can now arrange for the "Copy" menu
item to be greyed out depending on the game_params.
To do this I've introduced a new backend function
(can_format_as_text_now()), and renamed the existing static backend
field "can_format_as_text" to "can_format_as_text_ever". The latter
will cause compile errors for anyone maintaining a third-party front
end; if any such person is reading this, I apologise to them for the
inconvenience, but I did do it deliberately so that they'd know to
update their front end.
As yet, no checked-in game actually uses this feature; all current
games can still either copy always or copy never.
[originally from svn r8161]
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]
Windows puzzle binaries. This checkin involves several distinct
changes:
- mkfiles.pl now has an extra feature: if an object file is listed
in Recipe with a trailing question mark, it will be considered
optional, and silently dropped from the makefile if its primary
source file isn't present at the time mkfiles.pl runs. This means
people who check out the puzzles from Subversion and just run
mkfiles.pl shouldn't get build failures; they just won't get the
icons.
- all the .R files now use this feature to include an optional
Windows resource file.
- the .rc resource source files are built by icons/Makefile.
- windows.c finds the icon if present and uses it in place of the
standard Windows application icon.
[originally from svn r7020]
midend_rewrite_statusbar() and check the result against the last
string returned. This is now done centrally in drawing.c, and the
front end status bar function need only do what it says on the tin.
While I'm modifying the prototype of drawing_init(), I've also
renamed it drawing_new() for the same reason as random_new() (it
_allocates_ a drawing object, rather than just initialising one
passed in).
[originally from svn r6420]