68 Commits

Author SHA1 Message Date
ec4335e07f js: Hide type menu if there's only one preset and no configuration
It seems a bit silly to display it when there's only one option.
2023-02-16 19:15:42 +00:00
1eba6388bf kaios: Hack out everything that needs dialogue boxes
They're proving to be a right nuisance and will probably require a
substantial overhaul to how they work across the entire JavaScript
front-end.  I don't think any of the functionality provided by the
dialogue boxes is critical, so in the interests of getting a minimum
viable product actually released I've disabled those features.

In most cases, this just involves commenting out bits of HTML.  The
"Custom..." menu item is added by C code, though, so there I've fallen
back to the standard Puzzles way to implement a nasty hack: an
environment variable.
2023-01-19 20:34:48 +00:00
81b6bccab6 js: Remove an outdated reference to the "invisible Custom option" 2023-01-19 20:34:48 +00:00
9d7b044c01 js: Simpler and more robust startup procedure
Previously, we initialised all of the JavaScript event handlers as soon
at the DOM was loaded, and then called main() ourselves once the
Emscripten runtime was ready.  This was slightly dangerous since it
depended on none of those event handlers' being called before main().
In practice this was difficult because most of the elements the event
handlers were attached to were invisible, but it did limit what event
handlers could safely be used.

Now, the event handlers are initialised from main().  This makes things
work in a sufficiently conventional way that we can just let the
Emscripten run-time call main() in its usual way, rather than involving
ourselves in the minutiae of Emscripten's startup.
2023-01-19 20:34:48 +00:00
420663d477 js: Use current_key_label() to label feature phone softkeys 2023-01-19 20:34:48 +00:00
e5604ccf37 js: Rename update_undo_redo() as post_move()
I want to do more things with it.
2023-01-19 20:34:48 +00:00
ebb7b4277e js: Don't treat SoftRight as CURSOR_SELECT2
I was hoping that I could treat SoftLeft and SoftRight the same in C and
arrange to filter one of them out in JavaScript, but that turned out to
be impractical.
2022-12-10 19:07:47 +00:00
33b5c48429 js: Add a new function whereby C can ask JS for a preferred board size
Currently JS has no opinion.
2022-12-10 18:33:00 +00:00
14eb35da4a js: Set the default colour from the CSS background of the canvas
This allows the HTML/CSS to decide that it would like a different
background colour without the need to recompile.  The default if the CSS
specifies no colour (and hence the canvas is transparent) is the same
grey as before.
2022-12-10 17:58:41 +00:00
02f1d55a02 js: Allow CSS to set the font used by the puzzle
This means that the calculated font properties of the HTML canvas now
control what font is used.  The size is overridden, and for monospaced
text so is the family.

I'd like to be able to also specify the monospaced font, maybe using a
CSS variable, but that looks like being quite a lot of extra complexity.

My experience when testing this was that constructing a valid "font"
string for a canvas context is prone to breakage, but broke in a way
that left the font unchanged, so we always set a simple specification
first before trying to construct one from CSS.
2022-12-10 15:30:49 +00:00
ea223a2350 js: Put the puzzle background colour in a CSS variable
It's sometimes useful to be able to have an HTML element that visually
forms an extension of the puzzle's border.  By putting the puzzle's
colour 0 (which we assume to be its background) into a CSS variable,
such elements can do something like "background-color:
var(--puzzle-background)" to get that effect even if the puzzle uses a
non-default background colour.
2022-12-05 23:25:12 +00:00
b967a3ea86 js: Remove support for creating the status bar in JavaScript
Now we depend on its being in the HTML.
2022-11-28 22:51:15 +00:00
271fb7f47c js: More conventional marking of menu item types
Menu items that open dialogue boxes are now marked with ellipses, while
menu items that lead to submenus have pointing triangles.

The triangles are implemented as SVG files embedded in data: URLs in the
CSS, which is kind of silly but also works really well.  There are
suitable characters in Unicode, but some of my test systems don't have
fonts containing them, so maybe the SVG is better.
2022-11-24 16:24:59 +00:00
77c8b50834 js: Allow status bar to be present in the HTML
I'm generally in favour of putting HTML in HTML rather the constructing
it in JavaScript, and this will allow for simplifying the code
eventually.  This only changes the JavaScript to make sure that's in
people's caches before I change the HTML itself.
2022-11-20 19:10:23 +00:00
a90bb4a4ef js: Better handling of games without presets and/or solve
Games with neither presets nor configuration (which may only be the Null
Game) have been slightly broken since the introduction of hierarchical
preset menus, in that the code to remove the "Type..." menu stopped
being called then.  My switch to using radio buttons in menus then broke
them utterly because it's not possible to set the value of an empty
radio group, causing a crash at startup.

Fix this by detected when there's no preset menu, removing the item from
the menu bar, and setting the variable that's meant to indicate this has
been done.

The solve button problem was more subtle, in that only the <button> was
being hidden and not the <li> containing it, which led to the right border of the menu bar being two pixels thick.  Switch to fully removing
the <li> from the DOM, like we now do with the presets menu, since that
also makes my keyboard handler (in another branch) simpler.
2022-11-13 14:05:55 +00:00
c5a2446fae js: Cancel UI events when the mid end says they've been handled
This means that if a key doesn't do anything in a puzzle, it can operate
the browser instead.
2022-11-08 10:27:19 +00:00
4a37f7cf78 Add a way for midend_process_key() to report whether it handled a keypress
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.
2022-11-08 10:27:19 +00:00
4fdcc54975 js: Make SoftRight act as CURSOR_SELECT2 as well
This way, the front end can intercept one of SoftLeft and SoftRight as a
menu key and leave the other one for the puzzle.  And while we don't
have a working menu, I can use whichever is more convenient.
2022-11-08 10:27:19 +00:00
ee5b02b0ca js: Map the "SoftLeft" key to CURSOR_SELECT2
This is the left soft key on KaiOS phones.  The centre soft key
already sends "Enter", which eventually becomes CURSOR_SELECT.  The
right soft key I'm planning to use to open the menu.
2022-11-08 10:27:19 +00:00
ad9ee5a524 js: Move much of the handling of device pixel ratios to the mid-end
Now that the mid-end knows how to do it, we can remove some complexity
from the front end.
2022-11-08 10:27:02 +00:00
e45cd43aaa Teach the mid-end about device pixel ratios
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.
2022-11-08 00:57:36 +00:00
1e8169ea94 js: Take device pixel ratio into account when setting default size
This is a bit of a hack.  When setting the puzzle to its default size,
either at startup or from a right-click on the resize handle, we now
scale the default size from midend_size() by the device pixel ratio,
and then pass that back to midend_size().  This does more or less the
right thing, in that the puzzle now starts up at a size that scales
with the font size.

There are still some slight inconsistencies, where sequences of DPR
changes and puzzle parameter changes can have order-dependent effects
on the size of the puzzle.  Happily these effects are small and fairly
hard to observe.
2022-10-27 22:51:54 +01:00
fa58dd85b7 js: Distinguish manual resizes from device pixel ratio changes
This adds a new callback, rescale_puzzle(), that's called when the
device pixel ratio changes.  This means that resize_puzzle() can safely
set the nominal canvas size, which means that manual resizing of the
puzzle now sticks.

Still missing: paying attention to the device pixel ratio when choosing
the initial (or reset) size.
2022-10-27 22:51:54 +01:00
9783bbfbc0 js: Split setting nominal and actual canvas size
Now zooming in and out repeatedly doesn't cause the canvas to wither
away, but user resizes don't stick any more.  Still more to do.
2022-10-27 22:51:54 +01:00
5fae5ca0db js: Be more subtle about cancelling keydown events
Now we only cancel a keydown event if the C keyboard handler recognises
the key and passes it on to the midend.  This doesn't necessarily mean
that the midend has actually done anything with it, of course.  Still,
this is enough to allow F12 to open the developer tools even when the
input focus is on the puzzle.  It also allows for tabbing out of the
puzzle into the links below it.
2022-10-25 20:38:37 +01:00
43c89dd5e1 js: Add a comment explaining the two halves of the key-matching code 2022-10-25 00:50:47 +01:00
d94d671bf9 js: Handle KeyboardEvent.key == "Spacebar"
This is apparently generated in place of " " by Internet Explorer.
2022-10-25 00:48:58 +01:00
35d382019f js: Recognise KeyboardEvent.key == "Escape" 2022-10-24 23:33:09 +01:00
f5ac13c847 js: Add mapping for UI_REDO based on KeyboardEvent.key 2022-10-24 23:19:56 +01:00
768ef770a3 js: Use KeyboardEvent.key for ASCII keystrokes
This requires passing in KeyboardEvent.location from JavaScript so
that we can detect the numeric keypad properly.  Out of caution we
currently only set MOD_NUM_KEYPAD on numbers, like we always have,
but we have enough information to set it on arrow keys, Enter, "+",
etc.

This finally gets '/' and '\' working in Slant again.
2022-10-24 23:13:33 +01:00
0db5fb525b js: Remove the charCode argument from key()
It hasn't been used in a while.
2022-10-24 22:37:30 +01:00
9698732d65 js: Add modern "key" values for Delete and arrow keys
Firefox has emitted "Delete", "ArrowDown" etc since 2015.
2022-10-24 22:22:33 +01:00
322a439d80 js: Use KeyboardEvent.keyCode and .char only as fallbacks
KeyboardEvent.keyCode is a platform-dependent mess.
KeyboardEvent.char is better-defined, but in my browser it's always
null.  KeyboardEvent.key is the right thing to use when we want to
know the semantics of a key.

This commit just re-organises the big "else if" chain in key() so
that all the tests on "key" come first.  That way at least if key and
keyCode disagree, we'll use the more trustworthy one.
2022-10-24 22:07:12 +01:00
c1059c07fb js: Remove braces from big else-if chain in keyboard handler
If there's ever a case where they're unnecessary noise, it's a long
chain of "else if"s guarding single assignment statements.
2022-10-24 21:57:53 +01:00
47905e9547 Revert "WASM: move save file encoding from JS into C."
Now that save files are (even more) officially ASCII, it's perfectly
safe to pass them to JavaScript as UTF-8 strings.

This means that the form in which save files are shipped from C to
JavaScript is the same is the form in which they're shipped from
JavaScript to C.  That allows for doing new things with them, like
writing them to local storage.

This reverts commit f729f51e475ff98d0caf529f0723ef810b1c88ef.
2022-10-21 00:25:34 +01:00
879a6922b0 js: Update permalinks and undo/redo buttons when loading
Without this, the "Undo" button ends up greyed even though it actually
works.  I'm not sure about whether updating the permalinks is necessary:
maybe we don't need that in new_game() either.
2022-10-15 18:23:15 +01:00
f11e93e3bd js: Update comment on possible future enhancements
Load/save has been in the JavaScript backend for a while, as have
prettier controls.  And JavaScript-capable touchscreens are all around
us, if still poorly supported by Puzzles.
2022-10-13 10:07:05 +01:00
a11a5726b2 Add a missing "const" to js_draw_poly and js_canvas_draw_poly 2022-10-13 00:13:00 +01:00
f729f51e47 WASM: move save file encoding from JS into C.
The previous fix worked OK, but it was conceptually wrong. Puzzles
save files are better regarded as binary, not text: the length fields
are measured in bytes, so translating the file into a different
multibyte character encoding would invalidate them.

So it was wrong to fetch a C byte string containing the exactly right
binary data, then translate it into a Javascript string as if decoding
from UTF-8, then retranslate to a representation of a bytewise
encoding via encodeURIComponent, and then label the result as
application/octet-stream.

This probably wouldn't have caused any problems in practice, because I
don't remember any situation in which my save files use characters
outside printable ASCII (plus newline). But it's not actually
forbidden, so a save file might choose to do that some day, so that
UTF-8 decode/reencode hidden in the JS was a latent bug.

Now the URI-encoding is done on the C side, while we still know
exactly what the binary data ought to look like and can be sure we're
translating it byte for byte into the output encoding for the data:
URI. By the time the JS receives a string pointer from get_save_file,
it's already URI-encoded, which _guarantees_ that it's in ASCII and
won't be messed about with by Emscripten's UTF8ToString.
2021-05-23 08:45:55 +01:00
5f5b284c0b Use C99 bool within source modules.
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.
2018-11-13 21:48:24 +00:00
a550ea0a47 Replace TRUE/FALSE with C99 true/false throughout.
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.
2018-11-13 21:48:24 +00:00
cd6cadbecf Adopt C99 bool in the midend API.
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.
2018-11-13 21:46:39 +00:00
3618f6a07f Fix NUL-termination bug in saving from Javascript.
The JS code that retrieves the save-file data from emcc.c doesn't
receive a separate length value, but instead expects the data to be in
the form of a NUL-terminated string. But emcc.c wasn't NUL-terminating
it, so the save data could come out with random cruft on the end.
2018-06-21 18:54:08 +01:00
a58c1b216b Make the code base clean under -Wwrite-strings.
I've also added that warning option and -Werror to the build script,
so that I'll find out if I break this property in future.
2017-10-01 16:35:40 +01:00
3276376d1b Assorted char * -> const char * API changes.
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.
2017-10-01 16:35:00 +01:00
b3243d7504 Return error messages as 'const char *', not 'char *'.
They're never dynamically allocated, and are almost always string
literals, so const is more appropriate.
2017-10-01 16:34:41 +01:00
de67801b0f Use a proper union in struct config_item.
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.
2017-10-01 16:34:41 +01:00
d72db91888 Map Ctrl-Shift-Z to Redo.
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.
2017-09-20 18:03:44 +01:00
e4d05c36d9 Generate special fake keypresses from menu options.
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.)
2017-09-20 18:01:52 +01:00
721119e4a6 Support for loading games in Javascript puzzles.
This is done by showing a dialog containing an <input type="file">
through which the user can 'upload' a save file - though, of course,
the 'upload' doesn't go to any HTTP server, but only into the mind of
the Javascript running in the same browser.

It would be even nicer to support drag-and-drop as an alternative UI
for getting the save file into the browser, but that isn't critical to
getting the first version of this feature out of the door.
2017-09-05 20:58:05 +01:00