mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-11-17 09:02:38 -05:00
puzzles: resync with upstream
This brings puzzles to upstream commit 84d3fd2. Change-Id: I808a197f868032d771fc101a15666c5ec4b9f94b
This commit is contained in:
parent
ea679de837
commit
b9386109e8
26 changed files with 1037 additions and 583 deletions
|
|
@ -54,24 +54,30 @@ in puzzles do make -f Makefile.doc clean
|
|||
in puzzles do make -f Makefile.doc # build help files for installer
|
||||
in puzzles do mason.pl --args '{"version":"$(Version)","descfile":"gamedesc.txt"}' winwix.mc > puzzles.wxs
|
||||
in puzzles do perl winiss.pl $(Version) gamedesc.txt > puzzles.iss
|
||||
delegate windows
|
||||
# FIXME: Cygwin alternative?
|
||||
in puzzles with visualstudio do/win nmake -f Makefile.vc clean
|
||||
in puzzles with visualstudio do/win nmake -f Makefile.vc VER=-DVER=$(Version)
|
||||
ifneq "$(VISUAL_STUDIO)" "yes" then
|
||||
in puzzles with clangcl64 do Platform=x64 make -f Makefile.clangcl clean
|
||||
in puzzles with clangcl64 do Platform=x64 make -f Makefile.clangcl VER=-DVER=$(Version)
|
||||
# Code-sign the binaries, if the local bob config provides a script
|
||||
# to do so. We assume here that the script accepts an -i option to
|
||||
# provide a 'more info' URL, and an optional -n option to provide a
|
||||
# program name, and that it can take multiple .exe filename
|
||||
# arguments and sign them all in place.
|
||||
ifneq "$(winsigncode)" "" in puzzles do $(winsigncode) -i https://www.chiark.greenend.org.uk/~sgtatham/puzzles/ *.exe
|
||||
ifneq "$(cross_winsigncode)" "" in puzzles do $(cross_winsigncode) -i https://www.chiark.greenend.org.uk/~sgtatham/puzzles/ *.exe
|
||||
# Build installers.
|
||||
in puzzles with wix do/win candle puzzles.wxs && light -ext WixUIExtension -sval puzzles.wixobj
|
||||
in puzzles with innosetup do/win iscc puzzles.iss
|
||||
ifneq "$(winsigncode)" "" in puzzles do $(winsigncode) -i https://www.chiark.greenend.org.uk/~sgtatham/puzzles/ -n "Simon Tatham's Portable Puzzle Collection Installer" puzzles.msi Output/installer.exe
|
||||
return puzzles/*.exe
|
||||
return puzzles/Output/installer.exe
|
||||
return puzzles/puzzles.msi
|
||||
enddelegate
|
||||
in puzzles with wixonlinux do candle -arch x64 puzzles.wxs && light -ext WixUIExtension -sval puzzles.wixobj
|
||||
ifneq "$(cross_winsigncode)" "" in puzzles do $(cross_winsigncode) -i https://www.chiark.greenend.org.uk/~sgtatham/puzzles/ -n "Simon Tatham's Portable Puzzle Collection Installer" puzzles.msi
|
||||
else
|
||||
delegate windows
|
||||
in puzzles with visualstudio do/win nmake -f Makefile.vc clean
|
||||
in puzzles with visualstudio do/win nmake -f Makefile.vc VER=-DVER=$(Version)
|
||||
ifneq "$(winsigncode)" "" in puzzles do $(winsigncode) -i https://www.chiark.greenend.org.uk/~sgtatham/puzzles/ *.exe
|
||||
# Build installers.
|
||||
in puzzles with wix do/win candle puzzles.wxs && light -ext WixUIExtension -sval puzzles.wixobj
|
||||
in puzzles with innosetup do/win iscc puzzles.iss
|
||||
return puzzles/*.exe
|
||||
return puzzles/puzzles.msi
|
||||
enddelegate
|
||||
endif
|
||||
in puzzles do chmod +x *.exe
|
||||
|
||||
# Build the Pocket PC binaries and CAB.
|
||||
|
|
@ -152,13 +158,22 @@ delegate emscripten
|
|||
return puzzles/js/*.js
|
||||
enddelegate
|
||||
|
||||
# Build a set of wrapping HTML pages for easy testing of the
|
||||
# Javascript puzzles. These aren't quite the same as the versions that
|
||||
# will go on my live website, because those ones will substitute in a
|
||||
# different footer, and not have to link to the .js files with the
|
||||
# ../js/ prefix. But these ones should be good enough to just open
|
||||
# using a file:// URL in a browser after running a build, and make
|
||||
# sure the main functionality works.
|
||||
in puzzles do mkdir jstest
|
||||
in puzzles/jstest do ../html/jspage.pl --jspath=../js/ /dev/null ../html/*.html
|
||||
|
||||
# Set up .htaccess containing a redirect for the archive filename.
|
||||
in puzzles do echo "AddType application/octet-stream .chm" > .htaccess
|
||||
in puzzles do echo "AddType application/octet-stream .hlp" >> .htaccess
|
||||
in puzzles do echo "AddType application/octet-stream .cnt" >> .htaccess
|
||||
in . do set -- puzzles*.tar.gz; echo RedirectMatch temp '(.*/)'puzzles.tar.gz '$$1'"$$1" >> puzzles/.htaccess
|
||||
in puzzles do echo RedirectMatch temp '(.*/)'puzzles-installer.msi '$$1'puzzles-$(Version)-installer.msi >> .htaccess
|
||||
in puzzles do echo RedirectMatch temp '(.*/)'puzzles-installer.exe '$$1'puzzles-$(Version)-installer.exe >> .htaccess
|
||||
|
||||
# Phew, we're done. Deliver everything!
|
||||
deliver puzzles/icons/*-web.png $@
|
||||
|
|
@ -172,9 +187,9 @@ deliver puzzles/puzzles.hlp $@
|
|||
deliver puzzles/puzzles.cnt $@
|
||||
deliver puzzles/puzzles.zip $@
|
||||
deliver puzzles/puzzles.msi puzzles-$(Version)-installer.msi
|
||||
deliver puzzles/Output/installer.exe puzzles-$(Version)-installer.exe
|
||||
deliver puzzles/*.jar java/$@
|
||||
deliver puzzles/js/*.js js/$@
|
||||
deliver puzzles/jstest/*.html jstest/$@
|
||||
deliver puzzles/html/*.html html/$@
|
||||
deliver puzzles/html/*.pl html/$@
|
||||
deliver puzzles/wwwspans.html $@
|
||||
|
|
|
|||
|
|
@ -61,19 +61,19 @@ public class PuzzleApplet extends JApplet implements Runtime.CallJavaCB {
|
|||
JMenuBar menubar = new JMenuBar();
|
||||
JMenu jm;
|
||||
menubar.add(jm = new JMenu("Game"));
|
||||
addMenuItemWithKey(jm, "New", 'n');
|
||||
addMenuItemCallback(jm, "New", "jcallback_newgame_event");
|
||||
addMenuItemCallback(jm, "Restart", "jcallback_restart_event");
|
||||
addMenuItemCallback(jm, "Specific...", "jcallback_config_event", CFG_DESC);
|
||||
addMenuItemCallback(jm, "Random Seed...", "jcallback_config_event", CFG_SEED);
|
||||
jm.addSeparator();
|
||||
addMenuItemWithKey(jm, "Undo", 'u');
|
||||
addMenuItemWithKey(jm, "Redo", 'r');
|
||||
addMenuItemCallback(jm, "Undo", "jcallback_undo_event");
|
||||
addMenuItemCallback(jm, "Redo", "jcallback_redo_event");
|
||||
jm.addSeparator();
|
||||
solveCommand = addMenuItemCallback(jm, "Solve", "jcallback_solve_event");
|
||||
solveCommand.setEnabled(false);
|
||||
if (mainWindow != null) {
|
||||
jm.addSeparator();
|
||||
addMenuItemWithKey(jm, "Exit", 'q');
|
||||
addMenuItemCallback(jm, "Exit", "jcallback_quit_event");
|
||||
}
|
||||
menubar.add(typeMenu = new JMenu("Type"));
|
||||
typeMenu.setVisible(false);
|
||||
|
|
@ -126,7 +126,12 @@ public class PuzzleApplet extends JApplet implements Runtime.CallJavaCB {
|
|||
}
|
||||
}
|
||||
public void keyTyped(KeyEvent e) {
|
||||
runtimeCall("jcallback_key_event", new int[] {0, 0, e.getKeyChar()});
|
||||
int key = e.getKeyChar();
|
||||
if (key == 26 && e.isShiftDown() && e.isControlDown()) {
|
||||
runtimeCall("jcallback_redo_event", new int[0]);
|
||||
return;
|
||||
}
|
||||
runtimeCall("jcallback_key_event", new int[] {0, 0, key});
|
||||
}
|
||||
});
|
||||
pp.addMouseListener(new MouseAdapter() {
|
||||
|
|
@ -217,10 +222,6 @@ public class PuzzleApplet extends JApplet implements Runtime.CallJavaCB {
|
|||
runtimeCall("jcallback_resize", new int[] {pp.getWidth(), pp.getHeight()});
|
||||
}
|
||||
|
||||
private void addMenuItemWithKey(JMenu jm, String name, int key) {
|
||||
addMenuItemCallback(jm, name, "jcallback_menu_key_event", key);
|
||||
}
|
||||
|
||||
private JMenuItem addMenuItemCallback(JMenu jm, String name, final String callback, final int arg) {
|
||||
return addMenuItemCallback(jm, name, callback, new int[] {arg}, false);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
!makefile gnustep Makefile.gnustep
|
||||
!makefile nestedvm Makefile.nestedvm
|
||||
!makefile emcc Makefile.emcc
|
||||
!makefile clangcl Makefile.clangcl
|
||||
|
||||
!srcdir icons/
|
||||
|
||||
|
|
|
|||
|
|
@ -1,21 +0,0 @@
|
|||
\# File containing the magic HTML configuration directives to create
|
||||
\# an MS HTML Help project. We put this on the end of the Puzzles
|
||||
\# docs build command line to build the HHP and friends.
|
||||
|
||||
\cfg{html-leaf-level}{infinite}
|
||||
\cfg{html-leaf-contains-contents}{false}
|
||||
\cfg{html-suppress-navlinks}{true}
|
||||
\cfg{html-suppress-address}{true}
|
||||
|
||||
\cfg{html-contents-filename}{index.html}
|
||||
\cfg{html-template-filename}{%k.html}
|
||||
\cfg{html-template-fragment}{%k}
|
||||
|
||||
\cfg{html-mshtmlhelp-chm}{puzzles.chm}
|
||||
\cfg{html-mshtmlhelp-project}{puzzles.hhp}
|
||||
\cfg{html-mshtmlhelp-contents}{puzzles.hhc}
|
||||
\cfg{html-mshtmlhelp-index}{puzzles.hhk}
|
||||
|
||||
\cfg{html-body-end}{}
|
||||
|
||||
\cfg{html-head-end}{<link rel="stylesheet" type="text/css" href="chm.css">}
|
||||
|
|
@ -1928,6 +1928,9 @@ Indeed, even horizontal or vertical lines may be anti-aliased.
|
|||
|
||||
This function may be used for both drawing and printing.
|
||||
|
||||
If the specified thickness is less than 1.0, 1.0 is used.
|
||||
This ensures that thin lines are visible even at small scales.
|
||||
|
||||
\S{drawing-draw-text} \cw{draw_text()}
|
||||
|
||||
\c void draw_text(drawing *dr, int x, int y, int fonttype,
|
||||
|
|
|
|||
|
|
@ -90,6 +90,8 @@ void draw_line(drawing *dr, int x1, int y1, int x2, int y2, int colour)
|
|||
void draw_thick_line(drawing *dr, float thickness,
|
||||
float x1, float y1, float x2, float y2, int colour)
|
||||
{
|
||||
if (thickness < 1.0)
|
||||
thickness = 1.0;
|
||||
if (dr->api->draw_thick_line) {
|
||||
dr->api->draw_thick_line(dr->handle, thickness,
|
||||
x1, y1, x2, y2, colour);
|
||||
|
|
|
|||
|
|
@ -310,6 +310,8 @@ void key(int keycode, int charcode, const char *key, const char *chr,
|
|||
keyevent = MOD_NUM_KEYPAD | '7';
|
||||
} else if (!strnullcmp(key, "PageUp") || keycode==33) {
|
||||
keyevent = MOD_NUM_KEYPAD | '9';
|
||||
} else if (shift && ctrl && (keycode & 0x1F) == 26) {
|
||||
keyevent = UI_REDO;
|
||||
} else if (chr && chr[0] && !chr[1]) {
|
||||
keyevent = chr[0] & 0xFF;
|
||||
} else if (keycode >= 96 && keycode < 106) {
|
||||
|
|
@ -323,10 +325,10 @@ void key(int keycode, int charcode, const char *key, const char *chr,
|
|||
}
|
||||
|
||||
if (keyevent >= 0) {
|
||||
if (shift && keyevent >= 0x100)
|
||||
if (shift && (keyevent >= 0x100 && !IS_UI_FAKE_KEY(keyevent)))
|
||||
keyevent |= MOD_SHFT;
|
||||
|
||||
if (ctrl) {
|
||||
if (ctrl && !IS_UI_FAKE_KEY(keyevent)) {
|
||||
if (keyevent >= 0x100)
|
||||
keyevent |= MOD_CTRL;
|
||||
else
|
||||
|
|
@ -725,7 +727,7 @@ void command(int n)
|
|||
update_undo_redo();
|
||||
break;
|
||||
case 5: /* New Game */
|
||||
midend_process_key(me, 0, 0, 'n');
|
||||
midend_process_key(me, 0, 0, UI_NEWGAME);
|
||||
update_undo_redo();
|
||||
js_focus_canvas();
|
||||
break;
|
||||
|
|
@ -735,12 +737,12 @@ void command(int n)
|
|||
js_focus_canvas();
|
||||
break;
|
||||
case 7: /* Undo */
|
||||
midend_process_key(me, 0, 0, 'u');
|
||||
midend_process_key(me, 0, 0, UI_UNDO);
|
||||
update_undo_redo();
|
||||
js_focus_canvas();
|
||||
break;
|
||||
case 8: /* Redo */
|
||||
midend_process_key(me, 0, 0, 'r');
|
||||
midend_process_key(me, 0, 0, UI_REDO);
|
||||
update_undo_redo();
|
||||
js_focus_canvas();
|
||||
break;
|
||||
|
|
@ -756,6 +758,83 @@ void command(int n)
|
|||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
* Called from JS to prepare a save-game file, and free one after it's
|
||||
* been used.
|
||||
*/
|
||||
|
||||
struct savefile_write_ctx {
|
||||
char *buffer;
|
||||
size_t pos;
|
||||
};
|
||||
|
||||
static void savefile_write(void *vctx, void *buf, int len)
|
||||
{
|
||||
struct savefile_write_ctx *ctx = (struct savefile_write_ctx *)vctx;
|
||||
if (ctx->buffer)
|
||||
memcpy(ctx->buffer + ctx->pos, buf, len);
|
||||
ctx->pos += len;
|
||||
}
|
||||
|
||||
char *get_save_file(void)
|
||||
{
|
||||
struct savefile_write_ctx ctx;
|
||||
size_t size;
|
||||
|
||||
/* First pass, to count up the size */
|
||||
ctx.buffer = NULL;
|
||||
ctx.pos = 0;
|
||||
midend_serialise(me, savefile_write, &ctx);
|
||||
size = ctx.pos;
|
||||
|
||||
/* Second pass, to actually write out the data */
|
||||
ctx.buffer = snewn(size, char);
|
||||
ctx.pos = 0;
|
||||
midend_serialise(me, savefile_write, &ctx);
|
||||
assert(ctx.pos == size);
|
||||
|
||||
return ctx.buffer;
|
||||
}
|
||||
|
||||
void free_save_file(char *buffer)
|
||||
{
|
||||
sfree(buffer);
|
||||
}
|
||||
|
||||
struct savefile_read_ctx {
|
||||
const char *buffer;
|
||||
int len_remaining;
|
||||
};
|
||||
|
||||
static int savefile_read(void *vctx, void *buf, int len)
|
||||
{
|
||||
struct savefile_read_ctx *ctx = (struct savefile_read_ctx *)vctx;
|
||||
if (ctx->len_remaining < len)
|
||||
return FALSE;
|
||||
memcpy(buf, ctx->buffer, len);
|
||||
ctx->len_remaining -= len;
|
||||
ctx->buffer += len;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void load_game(const char *buffer, int len)
|
||||
{
|
||||
struct savefile_read_ctx ctx;
|
||||
const char *err;
|
||||
|
||||
ctx.buffer = buffer;
|
||||
ctx.len_remaining = len;
|
||||
err = midend_deserialise(me, savefile_read, &ctx);
|
||||
|
||||
if (err) {
|
||||
js_error_box(err);
|
||||
} else {
|
||||
select_appropriate_preset();
|
||||
resize();
|
||||
midend_redraw(me);
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
* Setup function called at page load time. It's called main() because
|
||||
* that's the most convenient thing in Emscripten, but it's not main()
|
||||
|
|
|
|||
|
|
@ -108,7 +108,6 @@ mergeInto(LibraryManager.library, {
|
|||
item.appendChild(tick);
|
||||
item.appendChild(document.createTextNode(name));
|
||||
var submenu = document.createElement("ul");
|
||||
submenu.className = "left";
|
||||
item.appendChild(submenu);
|
||||
gametypesubmenus[menuid].appendChild(item);
|
||||
var toret = gametypesubmenus.length;
|
||||
|
|
@ -575,38 +574,7 @@ mergeInto(LibraryManager.library, {
|
|||
* overlay on top of the rest of the puzzle web page.
|
||||
*/
|
||||
js_dialog_init: function(titletext) {
|
||||
// Create an overlay on the page which darkens everything
|
||||
// beneath it.
|
||||
dlg_dimmer = document.createElement("div");
|
||||
dlg_dimmer.style.width = "100%";
|
||||
dlg_dimmer.style.height = "100%";
|
||||
dlg_dimmer.style.background = '#000000';
|
||||
dlg_dimmer.style.position = 'fixed';
|
||||
dlg_dimmer.style.opacity = 0.3;
|
||||
dlg_dimmer.style.top = dlg_dimmer.style.left = 0;
|
||||
dlg_dimmer.style["z-index"] = 99;
|
||||
|
||||
// Now create a form which sits on top of that in turn.
|
||||
dlg_form = document.createElement("form");
|
||||
dlg_form.style.width = (window.innerWidth * 2 / 3) + "px";
|
||||
dlg_form.style.opacity = 1;
|
||||
dlg_form.style.background = '#ffffff';
|
||||
dlg_form.style.color = '#000000';
|
||||
dlg_form.style.position = 'absolute';
|
||||
dlg_form.style.border = "2px solid black";
|
||||
dlg_form.style.padding = "20px";
|
||||
dlg_form.style.top = (window.innerHeight / 10) + "px";
|
||||
dlg_form.style.left = (window.innerWidth / 6) + "px";
|
||||
dlg_form.style["z-index"] = 100;
|
||||
|
||||
var title = document.createElement("p");
|
||||
title.style.marginTop = "0px";
|
||||
title.appendChild(document.createTextNode
|
||||
(Pointer_stringify(titletext)));
|
||||
dlg_form.appendChild(title);
|
||||
|
||||
dlg_return_funcs = [];
|
||||
dlg_next_id = 0;
|
||||
dialog_init(Pointer_stringify(titletext));
|
||||
},
|
||||
|
||||
/*
|
||||
|
|
@ -701,29 +669,13 @@ mergeInto(LibraryManager.library, {
|
|||
* everything else on the page.
|
||||
*/
|
||||
js_dialog_launch: function() {
|
||||
// Put in the OK and Cancel buttons at the bottom.
|
||||
var button;
|
||||
|
||||
button = document.createElement("input");
|
||||
button.type = "button";
|
||||
button.value = "OK";
|
||||
button.onclick = function(event) {
|
||||
dialog_launch(function(event) {
|
||||
for (var i in dlg_return_funcs)
|
||||
dlg_return_funcs[i]();
|
||||
command(3);
|
||||
}
|
||||
dlg_form.appendChild(button);
|
||||
|
||||
button = document.createElement("input");
|
||||
button.type = "button";
|
||||
button.value = "Cancel";
|
||||
button.onclick = function(event) {
|
||||
command(4);
|
||||
}
|
||||
dlg_form.appendChild(button);
|
||||
|
||||
document.body.appendChild(dlg_dimmer);
|
||||
document.body.appendChild(dlg_form);
|
||||
command(3); // OK
|
||||
}, function(event) {
|
||||
command(4); // Cancel
|
||||
});
|
||||
},
|
||||
|
||||
/*
|
||||
|
|
@ -733,10 +685,7 @@ mergeInto(LibraryManager.library, {
|
|||
* associated with it.
|
||||
*/
|
||||
js_dialog_cleanup: function() {
|
||||
document.body.removeChild(dlg_dimmer);
|
||||
document.body.removeChild(dlg_form);
|
||||
dlg_dimmer = dlg_form = null;
|
||||
onscreen_canvas.focus();
|
||||
dialog_cleanup();
|
||||
},
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -129,6 +129,72 @@ function disable_menu_item(item, disabledFlag) {
|
|||
item.className = "";
|
||||
}
|
||||
|
||||
// Dialog-box functions called from both C and JS.
|
||||
function dialog_init(titletext) {
|
||||
// Create an overlay on the page which darkens everything
|
||||
// beneath it.
|
||||
dlg_dimmer = document.createElement("div");
|
||||
dlg_dimmer.style.width = "100%";
|
||||
dlg_dimmer.style.height = "100%";
|
||||
dlg_dimmer.style.background = '#000000';
|
||||
dlg_dimmer.style.position = 'fixed';
|
||||
dlg_dimmer.style.opacity = 0.3;
|
||||
dlg_dimmer.style.top = dlg_dimmer.style.left = 0;
|
||||
dlg_dimmer.style["z-index"] = 99;
|
||||
|
||||
// Now create a form which sits on top of that in turn.
|
||||
dlg_form = document.createElement("form");
|
||||
dlg_form.style.width = (window.innerWidth * 2 / 3) + "px";
|
||||
dlg_form.style.opacity = 1;
|
||||
dlg_form.style.background = '#ffffff';
|
||||
dlg_form.style.color = '#000000';
|
||||
dlg_form.style.position = 'absolute';
|
||||
dlg_form.style.border = "2px solid black";
|
||||
dlg_form.style.padding = "20px";
|
||||
dlg_form.style.top = (window.innerHeight / 10) + "px";
|
||||
dlg_form.style.left = (window.innerWidth / 6) + "px";
|
||||
dlg_form.style["z-index"] = 100;
|
||||
|
||||
var title = document.createElement("p");
|
||||
title.style.marginTop = "0px";
|
||||
title.appendChild(document.createTextNode(titletext));
|
||||
dlg_form.appendChild(title);
|
||||
|
||||
dlg_return_funcs = [];
|
||||
dlg_next_id = 0;
|
||||
}
|
||||
|
||||
function dialog_launch(ok_function, cancel_function) {
|
||||
// Put in the OK and Cancel buttons at the bottom.
|
||||
var button;
|
||||
|
||||
if (ok_function) {
|
||||
button = document.createElement("input");
|
||||
button.type = "button";
|
||||
button.value = "OK";
|
||||
button.onclick = ok_function;
|
||||
dlg_form.appendChild(button);
|
||||
}
|
||||
|
||||
if (cancel_function) {
|
||||
button = document.createElement("input");
|
||||
button.type = "button";
|
||||
button.value = "Cancel";
|
||||
button.onclick = cancel_function;
|
||||
dlg_form.appendChild(button);
|
||||
}
|
||||
|
||||
document.body.appendChild(dlg_dimmer);
|
||||
document.body.appendChild(dlg_form);
|
||||
}
|
||||
|
||||
function dialog_cleanup() {
|
||||
document.body.removeChild(dlg_dimmer);
|
||||
document.body.removeChild(dlg_form);
|
||||
dlg_dimmer = dlg_form = null;
|
||||
onscreen_canvas.focus();
|
||||
}
|
||||
|
||||
// Init function called from body.onload.
|
||||
function initPuzzle() {
|
||||
// Construct the off-screen canvas used for double buffering.
|
||||
|
|
@ -230,6 +296,58 @@ function initPuzzle() {
|
|||
command(9);
|
||||
};
|
||||
|
||||
// 'number' is used for C pointers
|
||||
get_save_file = Module.cwrap('get_save_file', 'number', []);
|
||||
free_save_file = Module.cwrap('free_save_file', 'void', ['number']);
|
||||
load_game = Module.cwrap('load_game', 'void', ['string', 'number']);
|
||||
|
||||
document.getElementById("save").onclick = function(event) {
|
||||
if (dlg_dimmer === null) {
|
||||
var savefile_ptr = get_save_file();
|
||||
var savefile_text = Pointer_stringify(savefile_ptr);
|
||||
free_save_file(savefile_ptr);
|
||||
dialog_init("Download saved-game file");
|
||||
dlg_form.appendChild(document.createTextNode(
|
||||
"Click to download the "));
|
||||
var a = document.createElement("a");
|
||||
a.download = "puzzle.sav";
|
||||
a.href = "data:application/octet-stream," +
|
||||
encodeURIComponent(savefile_text);
|
||||
a.appendChild(document.createTextNode("saved-game file"));
|
||||
dlg_form.appendChild(a);
|
||||
dlg_form.appendChild(document.createTextNode("."));
|
||||
dlg_form.appendChild(document.createElement("br"));
|
||||
dialog_launch(function(event) {
|
||||
dialog_cleanup();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
document.getElementById("load").onclick = function(event) {
|
||||
if (dlg_dimmer === null) {
|
||||
dialog_init("Upload saved-game file");
|
||||
var input = document.createElement("input");
|
||||
input.type = "file";
|
||||
input.multiple = false;
|
||||
dlg_form.appendChild(input);
|
||||
dlg_form.appendChild(document.createElement("br"));
|
||||
dialog_launch(function(event) {
|
||||
if (input.files.length == 1) {
|
||||
var file = input.files.item(0);
|
||||
var reader = new FileReader();
|
||||
reader.addEventListener("loadend", function() {
|
||||
var string = reader.result;
|
||||
load_game(string, string.length);
|
||||
});
|
||||
reader.readAsBinaryString(file);
|
||||
}
|
||||
dialog_cleanup();
|
||||
}, function(event) {
|
||||
dialog_cleanup();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
gametypelist = document.getElementById("gametype");
|
||||
gametypesubmenus.push(gametypelist);
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,10 @@
|
|||
'_timer_callback',
|
||||
// Callback from button presses in the UI outside the canvas
|
||||
'_command',
|
||||
// Game-saving and game-loading functions
|
||||
'_get_save_file',
|
||||
'_free_save_file',
|
||||
'_load_game',
|
||||
// Callbacks to return values from dialog boxes
|
||||
'_dlg_return_sval',
|
||||
'_dlg_return_ival',
|
||||
|
|
|
|||
|
|
@ -140,7 +140,7 @@ struct font {
|
|||
*/
|
||||
struct frontend {
|
||||
GtkWidget *window;
|
||||
GtkAccelGroup *accelgroup;
|
||||
GtkAccelGroup *dummy_accelgroup;
|
||||
GtkWidget *area;
|
||||
GtkWidget *statusbar;
|
||||
GtkWidget *menubar;
|
||||
|
|
@ -1160,16 +1160,6 @@ static gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
|
|||
if (!backing_store_ok(fe))
|
||||
return TRUE;
|
||||
|
||||
#if !GTK_CHECK_VERSION(2,0,0)
|
||||
/* Gtk 1.2 passes a key event to this function even if it's also
|
||||
* defined as an accelerator.
|
||||
* Gtk 2 doesn't do this, and this function appears not to exist there. */
|
||||
if (fe->accelgroup &&
|
||||
gtk_accel_group_get_entry(fe->accelgroup,
|
||||
event->keyval, event->state))
|
||||
return TRUE;
|
||||
#endif
|
||||
|
||||
/* Handle mnemonics. */
|
||||
if (gtk_window_activate_key(GTK_WINDOW(fe->window), event))
|
||||
return TRUE;
|
||||
|
|
@ -1216,6 +1206,8 @@ static gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
|
|||
event->keyval == GDK_KEY_Delete ||
|
||||
event->keyval == GDK_KEY_KP_Delete)
|
||||
keyval = '\177';
|
||||
else if ((event->keyval == 'z' || event->keyval == 'Z') && shift && ctrl)
|
||||
keyval = UI_REDO;
|
||||
else if (event->string[0] && !event->string[1])
|
||||
keyval = (unsigned char)event->string[0];
|
||||
else
|
||||
|
|
@ -2348,32 +2340,34 @@ static void menu_about_event(GtkMenuItem *menuitem, gpointer data)
|
|||
#endif
|
||||
}
|
||||
|
||||
static GtkWidget *add_menu_item_with_key(frontend *fe, GtkContainer *cont,
|
||||
char *text, int key)
|
||||
static GtkWidget *add_menu_ui_item(
|
||||
frontend *fe, GtkContainer *cont, char *text, int action,
|
||||
int accel_key, int accel_keyqual)
|
||||
{
|
||||
GtkWidget *menuitem = gtk_menu_item_new_with_label(text);
|
||||
int keyqual;
|
||||
gtk_container_add(cont, menuitem);
|
||||
g_object_set_data(G_OBJECT(menuitem), "user-data", GINT_TO_POINTER(key));
|
||||
g_object_set_data(G_OBJECT(menuitem), "user-data",
|
||||
GINT_TO_POINTER(action));
|
||||
g_signal_connect(G_OBJECT(menuitem), "activate",
|
||||
G_CALLBACK(menu_key_event), fe);
|
||||
switch (key & ~0x1F) {
|
||||
case 0x00:
|
||||
key += 0x60;
|
||||
keyqual = GDK_CONTROL_MASK;
|
||||
break;
|
||||
case 0x40:
|
||||
key += 0x20;
|
||||
keyqual = GDK_SHIFT_MASK;
|
||||
break;
|
||||
default:
|
||||
keyqual = 0;
|
||||
break;
|
||||
|
||||
if (accel_key) {
|
||||
/*
|
||||
* Display a keyboard accelerator alongside this menu item.
|
||||
* Actually this won't be processed via the usual GTK
|
||||
* accelerator system, because we add it to a dummy
|
||||
* accelerator group which is never actually activated on the
|
||||
* main window; this permits back ends to override special
|
||||
* keys like 'n' and 'r' and 'u' in some UI states. So
|
||||
* whatever keystroke we display here will still go to
|
||||
* key_event and be handled in the normal way.
|
||||
*/
|
||||
gtk_widget_add_accelerator(menuitem,
|
||||
"activate", fe->dummy_accelgroup,
|
||||
accel_key, accel_keyqual,
|
||||
GTK_ACCEL_VISIBLE | GTK_ACCEL_LOCKED);
|
||||
}
|
||||
gtk_widget_add_accelerator(menuitem,
|
||||
"activate", fe->accelgroup,
|
||||
key, keyqual,
|
||||
GTK_ACCEL_VISIBLE);
|
||||
|
||||
gtk_widget_show(menuitem);
|
||||
return menuitem;
|
||||
}
|
||||
|
|
@ -2535,8 +2529,11 @@ static frontend *new_window(char *arg, int argtype, char **error)
|
|||
gtk_container_add(GTK_CONTAINER(fe->window), GTK_WIDGET(vbox));
|
||||
gtk_widget_show(GTK_WIDGET(vbox));
|
||||
|
||||
fe->accelgroup = gtk_accel_group_new();
|
||||
gtk_window_add_accel_group(GTK_WINDOW(fe->window), fe->accelgroup);
|
||||
fe->dummy_accelgroup = gtk_accel_group_new();
|
||||
/*
|
||||
* Intentionally _not_ added to the window via
|
||||
* gtk_window_add_accel_group; see menu_key_event
|
||||
*/
|
||||
|
||||
hbox = GTK_BOX(gtk_hbox_new(FALSE, 0));
|
||||
gtk_box_pack_start(vbox, GTK_WIDGET(hbox), FALSE, FALSE, 0);
|
||||
|
|
@ -2553,7 +2550,7 @@ static frontend *new_window(char *arg, int argtype, char **error)
|
|||
menu = gtk_menu_new();
|
||||
gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), menu);
|
||||
|
||||
add_menu_item_with_key(fe, GTK_CONTAINER(menu), "New", 'n');
|
||||
add_menu_ui_item(fe, GTK_CONTAINER(menu), "New", UI_NEWGAME, 'n', 0);
|
||||
|
||||
menuitem = gtk_menu_item_new_with_label("Restart");
|
||||
gtk_container_add(GTK_CONTAINER(menu), menuitem);
|
||||
|
|
@ -2623,8 +2620,8 @@ static frontend *new_window(char *arg, int argtype, char **error)
|
|||
gtk_widget_show(menuitem);
|
||||
#ifndef STYLUS_BASED
|
||||
add_menu_separator(GTK_CONTAINER(menu));
|
||||
add_menu_item_with_key(fe, GTK_CONTAINER(menu), "Undo", 'u');
|
||||
add_menu_item_with_key(fe, GTK_CONTAINER(menu), "Redo", 'r');
|
||||
add_menu_ui_item(fe, GTK_CONTAINER(menu), "Undo", UI_UNDO, 'u', 0);
|
||||
add_menu_ui_item(fe, GTK_CONTAINER(menu), "Redo", UI_REDO, 'r', 0);
|
||||
#endif
|
||||
if (thegame.can_format_as_text_ever) {
|
||||
add_menu_separator(GTK_CONTAINER(menu));
|
||||
|
|
@ -2646,7 +2643,7 @@ static frontend *new_window(char *arg, int argtype, char **error)
|
|||
gtk_widget_show(menuitem);
|
||||
}
|
||||
add_menu_separator(GTK_CONTAINER(menu));
|
||||
add_menu_item_with_key(fe, GTK_CONTAINER(menu), "Exit", 'q');
|
||||
add_menu_ui_item(fe, GTK_CONTAINER(menu), "Exit", UI_QUIT, 'q', 0);
|
||||
|
||||
menuitem = gtk_menu_item_new_with_mnemonic("_Help");
|
||||
gtk_container_add(GTK_CONTAINER(fe->menubar), menuitem);
|
||||
|
|
@ -2664,7 +2661,7 @@ static frontend *new_window(char *arg, int argtype, char **error)
|
|||
#ifdef STYLUS_BASED
|
||||
menuitem=gtk_button_new_with_mnemonic("_Redo");
|
||||
g_object_set_data(G_OBJECT(menuitem), "user-data",
|
||||
GINT_TO_POINTER((int)('r')));
|
||||
GINT_TO_POINTER(UI_REDO));
|
||||
g_signal_connect(G_OBJECT(menuitem), "clicked",
|
||||
G_CALLBACK(menu_key_event), fe);
|
||||
gtk_box_pack_end(hbox, menuitem, FALSE, FALSE, 0);
|
||||
|
|
@ -2672,7 +2669,7 @@ static frontend *new_window(char *arg, int argtype, char **error)
|
|||
|
||||
menuitem=gtk_button_new_with_mnemonic("_Undo");
|
||||
g_object_set_data(G_OBJECT(menuitem), "user-data",
|
||||
GINT_TO_POINTER((int)('u')));
|
||||
GINT_TO_POINTER(UI_UNDO));
|
||||
g_signal_connect(G_OBJECT(menuitem), "clicked",
|
||||
G_CALLBACK(menu_key_event), fe);
|
||||
gtk_box_pack_end(hbox, menuitem, FALSE, FALSE, 0);
|
||||
|
|
|
|||
|
|
@ -3,6 +3,17 @@
|
|||
use strict;
|
||||
use warnings;
|
||||
|
||||
my $jspath = "";
|
||||
while ($ARGV[0] =~ /^-/) {
|
||||
my $opt = shift @ARGV;
|
||||
last if $opt eq "--";
|
||||
if ($opt =~ /^--jspath=(.+)$/) {
|
||||
$jspath = $1;
|
||||
} else {
|
||||
die "jspage.pl: unrecognised option '$opt'\n";
|
||||
}
|
||||
}
|
||||
|
||||
open my $footerfile, "<", shift @ARGV or die "footer: open: $!\n";
|
||||
my $footer = "";
|
||||
$footer .= $_ while <$footerfile>;
|
||||
|
|
@ -62,7 +73,7 @@ EOF
|
|||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ASCII" />
|
||||
<title>${puzzlename}, ${unfinishedtitlefragment}from Simon Tatham's Portable Puzzle Collection</title>
|
||||
<script type="text/javascript" src="${filename}.js"></script>
|
||||
<script type="text/javascript" src="${jspath}${filename}.js"></script>
|
||||
<style class="text/css">
|
||||
/* Margins and centring on the top-level div for the game menu */
|
||||
#gamemenu { margin-top: 0; margin-bottom: 0.5em; text-align: center }
|
||||
|
|
@ -103,6 +114,15 @@ EOF
|
|||
color: rgba(0,0,0,0.5);
|
||||
}
|
||||
|
||||
#gamemenu ul li.separator {
|
||||
color: transparent;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
#gamemenu ul li.afterseparator {
|
||||
border-left: 1px solid rgba(0,0,0,0.3);
|
||||
}
|
||||
|
||||
#gamemenu ul li:first-of-type {
|
||||
/* Reinstate the left border for the leftmost top-level menu item */
|
||||
border-left: 1px solid rgba(0,0,0,0.3);
|
||||
|
|
@ -196,14 +216,19 @@ ${unfinishedpara}
|
|||
|
||||
<hr>
|
||||
<div id="puzzle" style="display: none">
|
||||
<div id="gamemenu"><ul><li id="new">New game</li
|
||||
<div id="gamemenu"><ul><li>Game...<ul
|
||||
><li id="specific">Enter game ID</li
|
||||
><li id="random">Enter random seed</li
|
||||
><li id="save">Download save file</li
|
||||
><li id="load">Upload save file</li
|
||||
></ul></li
|
||||
><li>Type...<ul id="gametype"></ul></li
|
||||
><li class="separator"></li
|
||||
><li id="new" class="afterseparator">New game</li
|
||||
><li id="restart">Restart game</li
|
||||
><li id="undo">Undo move</li
|
||||
><li id="redo">Redo move</li
|
||||
><li id="solve">Solve game</li
|
||||
><li id="specific">Enter game ID</li
|
||||
><li id="random">Enter random seed</li
|
||||
><li>Select game type<ul id="gametype" class="left"></ul></li
|
||||
></ul></div>
|
||||
<div align=center>
|
||||
<div id="resizable" style="position:relative; left:0; top:0">
|
||||
|
|
|
|||
|
|
@ -288,7 +288,7 @@ static void check_caches(const solver_state* sstate);
|
|||
{amin, omin, \
|
||||
"Width and height for this grid type must both be at least " #amin, \
|
||||
"At least one of width and height for this grid type must be at least " #omin,},
|
||||
enum { GRIDLIST(GRID_LOOPYTYPE) };
|
||||
enum { GRIDLIST(GRID_LOOPYTYPE) LOOPY_GRID_DUMMY_TERMINATOR };
|
||||
static char const *const gridnames[] = { GRIDLIST(GRID_NAME) };
|
||||
#define GRID_CONFIGS GRIDLIST(GRID_CONFIG)
|
||||
static grid_type grid_types[] = { GRIDLIST(GRID_GRIDTYPE) };
|
||||
|
|
|
|||
|
|
@ -590,33 +590,40 @@ static int midend_really_process_key(midend *me, int x, int y, int button)
|
|||
int type = MOVE, gottype = FALSE, ret = 1;
|
||||
float anim_time;
|
||||
game_state *s;
|
||||
char *movestr;
|
||||
char *movestr = NULL;
|
||||
|
||||
movestr =
|
||||
me->ourgame->interpret_move(me->states[me->statepos-1].state,
|
||||
me->ui, me->drawstate, x, y, button);
|
||||
if (!IS_UI_FAKE_KEY(button)) {
|
||||
movestr = me->ourgame->interpret_move(
|
||||
me->states[me->statepos-1].state,
|
||||
me->ui, me->drawstate, x, y, button);
|
||||
}
|
||||
|
||||
if (!movestr) {
|
||||
if (button == 'n' || button == 'N' || button == '\x0E') {
|
||||
if (button == 'n' || button == 'N' || button == '\x0E' ||
|
||||
button == UI_NEWGAME) {
|
||||
midend_new_game(me);
|
||||
midend_redraw(me);
|
||||
goto done; /* never animate */
|
||||
} else if (button == 'u' || button == 'U' ||
|
||||
button == '\x1A' || button == '\x1F') {
|
||||
button == '\x1A' || button == '\x1F' ||
|
||||
button == UI_UNDO) {
|
||||
midend_stop_anim(me);
|
||||
type = me->states[me->statepos-1].movetype;
|
||||
gottype = TRUE;
|
||||
if (!midend_undo(me))
|
||||
goto done;
|
||||
} else if (button == 'r' || button == 'R' ||
|
||||
button == '\x12' || button == '\x19') {
|
||||
button == '\x12' || button == '\x19' ||
|
||||
button == UI_REDO) {
|
||||
midend_stop_anim(me);
|
||||
if (!midend_redo(me))
|
||||
goto done;
|
||||
} else if (button == '\x13' && me->ourgame->can_solve) {
|
||||
} else if ((button == '\x13' || button == UI_SOLVE) &&
|
||||
me->ourgame->can_solve) {
|
||||
if (midend_solve(me))
|
||||
goto done;
|
||||
} else if (button == 'q' || button == 'Q' || button == '\x11') {
|
||||
} else if (button == 'q' || button == 'Q' || button == '\x11' ||
|
||||
button == UI_QUIT) {
|
||||
ret = 0;
|
||||
goto done;
|
||||
} else
|
||||
|
|
@ -2059,6 +2066,8 @@ char *midend_deserialise(midend *me,
|
|||
me->ourgame->new_drawstate(me->drawing,
|
||||
me->states[me->statepos-1].state);
|
||||
midend_size_new_drawstate(me);
|
||||
if (me->game_id_change_notify_function)
|
||||
me->game_id_change_notify_function(me->game_id_change_notify_ctx);
|
||||
|
||||
ret = NULL; /* success! */
|
||||
|
||||
|
|
|
|||
|
|
@ -2963,7 +2963,7 @@ static void game_redraw(drawing *dr, game_drawstate *ds,
|
|||
float animtime, float flashtime)
|
||||
{
|
||||
int x, y;
|
||||
int mines, markers, bg;
|
||||
int mines, markers, closed, bg;
|
||||
int cx = -1, cy = -1, cmoved;
|
||||
|
||||
if (flashtime) {
|
||||
|
|
@ -3013,13 +3013,15 @@ static void game_redraw(drawing *dr, game_drawstate *ds,
|
|||
|
||||
/*
|
||||
* Now draw the tiles. Also in this loop, count up the number
|
||||
* of mines and mine markers.
|
||||
* of mines, mine markers, and closed squares.
|
||||
*/
|
||||
mines = markers = 0;
|
||||
mines = markers = closed = 0;
|
||||
for (y = 0; y < ds->h; y++)
|
||||
for (x = 0; x < ds->w; x++) {
|
||||
int v = state->grid[y*ds->w+x], cc = 0;
|
||||
|
||||
if (v < 0)
|
||||
closed++;
|
||||
if (v == -1)
|
||||
markers++;
|
||||
if (state->layout->mines && state->layout->mines[y*ds->w+x])
|
||||
|
|
@ -3078,7 +3080,42 @@ static void game_redraw(drawing *dr, game_drawstate *ds,
|
|||
else
|
||||
sprintf(statusbar, "COMPLETED!");
|
||||
} else {
|
||||
int safe_closed = closed - mines;
|
||||
sprintf(statusbar, "Marked: %d / %d", markers, mines);
|
||||
if (safe_closed > 0 && safe_closed <= 9) {
|
||||
/*
|
||||
* In the situation where there's a very small number
|
||||
* of _non_-mine squares left unopened, it's helpful
|
||||
* to mention that number in the status line, to save
|
||||
* the player from having to count it up
|
||||
* painstakingly. This is particularly important if
|
||||
* the player has turned up the mine density to the
|
||||
* point where game generation resorts to its weird
|
||||
* pathological fallback of a very dense mine area
|
||||
* with a clearing in the middle, because that often
|
||||
* leads to a deduction you can only make by knowing
|
||||
* that there is (say) exactly one non-mine square to
|
||||
* find, and it's a real pain to have to count up two
|
||||
* large numbers of squares and subtract them to get
|
||||
* that value of 1.
|
||||
*
|
||||
* The threshold value of 8 for displaying this
|
||||
* information is because that's the largest number of
|
||||
* non-mine squares that might conceivably fit around
|
||||
* a single central square, and the most likely way to
|
||||
* _use_ this information is to observe that if all
|
||||
* the remaining safe squares are adjacent to _this_
|
||||
* square then everything else can be immediately
|
||||
* flagged as a mine.
|
||||
*/
|
||||
if (safe_closed == 1) {
|
||||
sprintf(statusbar + strlen(statusbar),
|
||||
" (1 safe square remains)");
|
||||
} else {
|
||||
sprintf(statusbar + strlen(statusbar),
|
||||
" (%d safe squares remain)", safe_closed);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ui->deaths)
|
||||
sprintf(statusbar + strlen(statusbar),
|
||||
|
|
|
|||
|
|
@ -375,7 +375,7 @@ void copy_left_justified(char *buf, size_t sz, const char *str)
|
|||
/* another kludge for platforms without %g support in *printf() */
|
||||
int ftoa(char *buf, float f)
|
||||
{
|
||||
return sprintf(buf, "%d.%06d", (int)f, (int)((f - (int)f)*1e6));
|
||||
return sprintf(buf, "%d.%06d", (int)f, abs((int)((f - (int)f)*1e6)));
|
||||
}
|
||||
|
||||
/* vim: set shiftwidth=4 tabstop=8: */
|
||||
|
|
|
|||
|
|
@ -319,7 +319,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","am","mpw","nestedvm","osx","wce","gnustep","emcc")) {
|
||||
("vc","vcproj","cygwin","borland","lcc","gtk","am","mpw","nestedvm","osx","wce","gnustep","emcc","clangcl")) {
|
||||
return 1;
|
||||
}
|
||||
warn "$.:unknown makefile type '$type'\n";
|
||||
|
|
@ -503,6 +503,151 @@ $orig_dir = cwd;
|
|||
|
||||
# Now we're ready to output the actual Makefiles.
|
||||
|
||||
if (defined $makefiles{'clangcl'}) {
|
||||
$mftyp = 'clangcl';
|
||||
$dirpfx = &dirpfx($makefiles{'clangcl'}, "/");
|
||||
|
||||
##-- Makefile for cross-compiling using clang-cl, lld-link, and
|
||||
## MinGW's windres for resource compilation.
|
||||
#
|
||||
# This makefile allows a complete Linux-based cross-compile, but
|
||||
# using the real Visual Studio header files and libraries. In
|
||||
# order to run it, you will need:
|
||||
#
|
||||
# - MinGW windres on your PATH.
|
||||
# * On Ubuntu as of 16.04, you can apt-get install
|
||||
# binutils-mingw-w64-x86-64 and binutils-mingw-w64-i686
|
||||
# which will provide (respectively) 64- and 32-bit versions,
|
||||
# under the names to which RCCMD is defined below.
|
||||
# - clang-cl and lld-link on your PATH.
|
||||
# * I built these from the up-to-date LLVM project trunk git
|
||||
# repositories, as of 2017-02-05.
|
||||
# - case-mashed copies of the Visual Studio include directories.
|
||||
# * On a real VS installation, run vcvars32.bat and look at
|
||||
# the resulting value of %INCLUDE%. Take a full copy of each
|
||||
# of those directories, and inside the copy, for each
|
||||
# include file that has an uppercase letter in its name,
|
||||
# make a lowercased symlink to it. Additionally, one of the
|
||||
# directories will contain files called driverspecs.h and
|
||||
# specstrings.h, and those will need symlinks called
|
||||
# DriverSpecs.h and SpecStrings.h.
|
||||
# * Now, on Linux, define the environment variable INCLUDE to
|
||||
# be a list, separated by *semicolons* (in the Windows
|
||||
# style), of those directories, but before all of them you
|
||||
# must also include lib/clang/5.0.0/include from the clang
|
||||
# installation area (which contains in particular a
|
||||
# clang-compatible stdarg.h overriding the Visual Studio
|
||||
# one).
|
||||
# - similarly case-mashed copies of the library directories.
|
||||
# * Again, on a real VS installation, run vcvars32 or
|
||||
# vcvarsx86_amd64 (as appropriate), look at %LIB%, make a
|
||||
# copy of each directory, and provide symlinks within that
|
||||
# directory so that all the files can be opened as
|
||||
# lowercase.
|
||||
# * Then set LIB to be a semicolon-separated list of those
|
||||
# directories (but you'll need to change which set of
|
||||
# directories depending on whether you want to do a 32-bit
|
||||
# or 64-bit build).
|
||||
# - for a 64-bit build, set 'Platform=x64' in the environment as
|
||||
# well, or else on the make command line.
|
||||
# * This is a variable understood only by this makefile - none
|
||||
# of the tools we invoke will know it - but it's consistent
|
||||
# with the way the VS scripts like vcvarsx86_amd64.bat set
|
||||
# things up, and since the environment has to change
|
||||
# _anyway_ between 32- and 64-bit builds (different set of
|
||||
# paths in $LIB) it's reasonable to have the choice of
|
||||
# compilation target driven by another environment variable
|
||||
# set in parallel with that one.
|
||||
# - for older versions of the VS libraries you may also have to
|
||||
# set EXTRA_console and/or EXTRA_windows to the name of an
|
||||
# object file manually extracted from one of those libraries.
|
||||
# * This is because old VS seems to manage its startup code by
|
||||
# having libcmt.lib contain lots of *crt0.obj objects, one
|
||||
# for each possible user entry point (main, WinMain and the
|
||||
# wide-char versions of both), of which the linker arranges
|
||||
# to include the right one by special-case code. But lld
|
||||
# only seems to mimic half of that code - it does include
|
||||
# the right crt0 object, but it doesn't also deliberately
|
||||
# _avoid_ including the _wrong_ ones, and since all those
|
||||
# objects define a common set of global symbols for other
|
||||
# parts of the library to use, lld may well select an
|
||||
# arbitrary one of them the first time it sees a reference
|
||||
# to one of those global symbols, and then later also select
|
||||
# the _right_ one for the application's entry point, causing
|
||||
# a multiple-definitions crash.
|
||||
# * So the workaround is to explicitly include the right
|
||||
# *crt0.obj file on the linker command line before lld even
|
||||
# begins searching libraries. Hence, for a console
|
||||
# application, you might extract crt0.obj from the library
|
||||
# in question and set EXTRA_console=crt0.obj, and for a GUI
|
||||
# application, do the same with wincrt0.obj. Then this
|
||||
# makefile will include the right one of those objects
|
||||
# alongside the matching /subsystem linker option.
|
||||
|
||||
open OUT, ">$makefiles{'clangcl'}"; select OUT;
|
||||
print
|
||||
"# Makefile for cross-compiling $project_name using clang-cl, lld-link,\n".
|
||||
"# and MinGW's windres, using GNU make on Linux.\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".
|
||||
"CCCMD = clang-cl\n".
|
||||
"ifeq (\$(Platform),x64)\n".
|
||||
"CCTARGET = x86_64-pc-windows-msvc18.0.0\n".
|
||||
"RCCMD = x86_64-w64-mingw32-windres\n".
|
||||
"else\n".
|
||||
"CCTARGET = i386-pc-windows-msvc18.0.0\n".
|
||||
"RCCMD = i686-w64-mingw32-windres\n".
|
||||
"endif\n".
|
||||
"CC = \$(CCCMD) --target=\$(CCTARGET)\n".
|
||||
&splitline("RC = \$(RCCMD) --preprocessor=\$(CCCMD) ".
|
||||
"--preprocessor-arg=/TC --preprocessor-arg=/E")."\n".
|
||||
"LD = lld-link\n".
|
||||
"\n".
|
||||
"# C compilation flags\n".
|
||||
&splitline("CFLAGS = /nologo /W3 /O1 " .
|
||||
(join " ", map {"-I$dirpfx$_"} @srcdirs) .
|
||||
" /D_WINDOWS /D_WIN32_WINDOWS=0x401 /DWINVER=0x401 ".
|
||||
"/D_CRT_SECURE_NO_WARNINGS")."\n".
|
||||
"LFLAGS = /incremental:no /dynamicbase /nxcompat\n".
|
||||
&splitline("RCFLAGS = ".(join " ", map {"-I$dirpfx$_"} @srcdirs).
|
||||
" -DWIN32 -D_WIN32 -DWINVER=0x0400 --define MINGW32_FIX=1")."\n".
|
||||
"\n".
|
||||
"\n";
|
||||
print &splitline("all:" . join "", map { " \$(BUILDDIR)$_.exe" } &progrealnames("G:C"));
|
||||
print "\n\n";
|
||||
foreach $p (&prognames("G:C")) {
|
||||
($prog, $type) = split ",", $p;
|
||||
$objstr = &objects($p, "\$(BUILDDIR)X.obj", "\$(BUILDDIR)X.res", undef);
|
||||
print &splitline("\$(BUILDDIR)$prog.exe: " . $objstr), "\n";
|
||||
|
||||
$objstr = &objects($p, "\$(BUILDDIR)X.obj", "\$(BUILDDIR)X.res", "X.lib");
|
||||
$subsys = ($type eq "G") ? "windows" : "console";
|
||||
print &splitline("\t\$(LD) \$(LFLAGS) \$(XLFLAGS) ".
|
||||
"/out:\$(BUILDDIR)$prog.exe ".
|
||||
"/lldmap:\$(BUILDDIR)$prog.map ".
|
||||
"/subsystem:$subsys\$(SUBSYSVER) ".
|
||||
"\$(EXTRA_$subsys) $objstr")."\n\n";
|
||||
}
|
||||
foreach $d (&deps("\$(BUILDDIR)X.obj", "\$(BUILDDIR)X.res", $dirpfx, "/", "vc")) {
|
||||
print &splitline(sprintf("%s: %s", $d->{obj},
|
||||
join " ", @{$d->{deps}})), "\n";
|
||||
if ($d->{obj} =~ /\.res$/) {
|
||||
print "\t\$(RC) \$(RCFLAGS) ".$d->{deps}->[0]." -o ".$d->{obj}."\n\n";
|
||||
} else {
|
||||
$deflist = join "", map { " /D$_" } @{$d->{defs}};
|
||||
print "\t\$(CC) /Fo\$(BUILDDIR)".$d->{obj}." \$(COMPAT) \$(CFLAGS) \$(XFLAGS)$deflist /c \$<\n\n";
|
||||
}
|
||||
}
|
||||
print "\nclean:\n".
|
||||
&splitline("\trm -f \$(BUILDDIR)*.obj \$(BUILDDIR)*.exe ".
|
||||
"\$(BUILDDIR)*.res \$(BUILDDIR)*.map ".
|
||||
"\$(BUILDDIR)*.exe.manifest")."\n";
|
||||
select STDOUT; close OUT;
|
||||
}
|
||||
|
||||
if (defined $makefiles{'cygwin'}) {
|
||||
$mftyp = 'cygwin';
|
||||
$dirpfx = &dirpfx($makefiles{'cygwin'}, "/");
|
||||
|
|
|
|||
|
|
@ -305,10 +305,34 @@ static int get_config(frontend *fe, int which)
|
|||
return fe->cfgret;
|
||||
}
|
||||
|
||||
int jcallback_menu_key_event(int key)
|
||||
int jcallback_newgame_event(void)
|
||||
{
|
||||
frontend *fe = (frontend *)_fe;
|
||||
if (!midend_process_key(fe->me, 0, 0, key))
|
||||
if (!midend_process_key(fe->me, 0, 0, UI_NEWGAME))
|
||||
return 42;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int jcallback_undo_event(void)
|
||||
{
|
||||
frontend *fe = (frontend *)_fe;
|
||||
if (!midend_process_key(fe->me, 0, 0, UI_UNDO))
|
||||
return 42;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int jcallback_redo_event(void)
|
||||
{
|
||||
frontend *fe = (frontend *)_fe;
|
||||
if (!midend_process_key(fe->me, 0, 0, UI_REDO))
|
||||
return 42;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int jcallback_quit_event(void)
|
||||
{
|
||||
frontend *fe = (frontend *)_fe;
|
||||
if (!midend_process_key(fe->me, 0, 0, UI_QUIT))
|
||||
return 42;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -687,6 +687,10 @@ struct frontend {
|
|||
if (c >= '0' && c <= '9' && ([ev modifierFlags] & NSNumericPadKeyMask))
|
||||
c |= MOD_NUM_KEYPAD;
|
||||
|
||||
if (c == 26 &&
|
||||
!((NSShiftKeyMask | NSControlKeyMask) & ~[ev modifierFlags]))
|
||||
c = UI_REDO;
|
||||
|
||||
[self processKey:c];
|
||||
}
|
||||
}
|
||||
|
|
@ -735,7 +739,7 @@ struct frontend {
|
|||
|
||||
- (void)newGame:(id)sender
|
||||
{
|
||||
[self processKey:'n'];
|
||||
[self processKey:UI_NEWGAME];
|
||||
}
|
||||
- (void)restartGame:(id)sender
|
||||
{
|
||||
|
|
@ -809,11 +813,11 @@ struct frontend {
|
|||
}
|
||||
- (void)undoMove:(id)sender
|
||||
{
|
||||
[self processKey:'u'];
|
||||
[self processKey:UI_UNDO];
|
||||
}
|
||||
- (void)redoMove:(id)sender
|
||||
{
|
||||
[self processKey:'r'&0x1F];
|
||||
[self processKey:UI_REDO];
|
||||
}
|
||||
|
||||
- (void)copy:(id)sender
|
||||
|
|
|
|||
|
|
@ -310,7 +310,18 @@ static void generate(random_state *rs, int w, int h, unsigned char *retgrid)
|
|||
fgrid2 = snewn(w*h, float);
|
||||
memcpy(fgrid2, fgrid, w*h*sizeof(float));
|
||||
qsort(fgrid2, w*h, sizeof(float), float_compare);
|
||||
threshold = fgrid2[w*h/2];
|
||||
/* Choose a threshold that makes half the pixels black. In case of
|
||||
* an odd number of pixels, select randomly between just under and
|
||||
* just over half. */
|
||||
{
|
||||
int index = w * h / 2;
|
||||
if (w & h & 1)
|
||||
index += random_upto(rs, 2);
|
||||
if (index < w*h)
|
||||
threshold = fgrid2[index];
|
||||
else
|
||||
threshold = fgrid2[w*h-1] + 1;
|
||||
}
|
||||
sfree(fgrid2);
|
||||
|
||||
for (i = 0; i < h; i++) {
|
||||
|
|
@ -448,6 +459,8 @@ static int do_row(unsigned char *known, unsigned char *deduced,
|
|||
|
||||
if (rowlen == 0) {
|
||||
memset(deduced, DOT, len);
|
||||
} else if (rowlen == 1 && data[0] == len) {
|
||||
memset(deduced, BLOCK, len);
|
||||
} else {
|
||||
do_recurse(known, deduced, row, minpos_done, maxpos_done, minpos_ok,
|
||||
maxpos_ok, data, len, freespace, 0, 0);
|
||||
|
|
|
|||
|
|
@ -47,6 +47,15 @@ enum {
|
|||
CURSOR_RIGHT,
|
||||
CURSOR_SELECT,
|
||||
CURSOR_SELECT2,
|
||||
/* UI_* are special keystrokes generated by front ends in response
|
||||
* to menu actions, never passed to back ends */
|
||||
UI_LOWER_BOUND,
|
||||
UI_QUIT,
|
||||
UI_NEWGAME,
|
||||
UI_SOLVE,
|
||||
UI_UNDO,
|
||||
UI_REDO,
|
||||
UI_UPPER_BOUND,
|
||||
|
||||
/* made smaller because of 'limited range of datatype' errors. */
|
||||
MOD_CTRL = 0x1000,
|
||||
|
|
@ -64,6 +73,7 @@ enum {
|
|||
#define IS_CURSOR_MOVE(m) ( (m) == CURSOR_UP || (m) == CURSOR_DOWN || \
|
||||
(m) == CURSOR_RIGHT || (m) == CURSOR_LEFT )
|
||||
#define IS_CURSOR_SELECT(m) ( (m) == CURSOR_SELECT || (m) == CURSOR_SELECT2)
|
||||
#define IS_UI_FAKE_KEY(m) ( (m) > UI_LOWER_BOUND && (m) < UI_UPPER_BOUND )
|
||||
|
||||
/*
|
||||
* Flags in the back end's `flags' word.
|
||||
|
|
|
|||
|
|
@ -1718,7 +1718,10 @@ static void game_changed_state(game_ui *ui, const game_state *oldstate,
|
|||
#define TILE_SIZE (ds->sz6*6)
|
||||
|
||||
#define BORDER (TILE_SIZE/8)
|
||||
#define BORDER_WIDTH (max(TILE_SIZE / 32, 1))
|
||||
#define LINE_THICK (TILE_SIZE/16)
|
||||
#define GRID_LINE_TL (ds->grid_line_tl)
|
||||
#define GRID_LINE_BR (ds->grid_line_br)
|
||||
#define GRID_LINE_ALL (ds->grid_line_all)
|
||||
|
||||
#define COORD(x) ( (x+1) * TILE_SIZE + BORDER )
|
||||
#define CENTERED_COORD(x) ( COORD(x) + TILE_SIZE/2 )
|
||||
|
|
@ -1738,7 +1741,7 @@ static void game_changed_state(game_ui *ui, const game_state *oldstate,
|
|||
#define DS_CSHIFT 20 /* R/U/L/D shift, for cursor-on-edge */
|
||||
|
||||
struct game_drawstate {
|
||||
int sz6;
|
||||
int sz6, grid_line_all, grid_line_tl, grid_line_br;
|
||||
int started;
|
||||
|
||||
int w, h, sz;
|
||||
|
|
@ -2118,7 +2121,6 @@ static void game_compute_size(const game_params *params, int tilesize,
|
|||
int sz6;
|
||||
} ads, *ds = &ads;
|
||||
ads.sz6 = tilesize/6;
|
||||
|
||||
*x = (params->w+2) * TILE_SIZE + 2 * BORDER;
|
||||
*y = (params->h+2) * TILE_SIZE + 2 * BORDER;
|
||||
}
|
||||
|
|
@ -2127,6 +2129,9 @@ static void game_set_size(drawing *dr, game_drawstate *ds,
|
|||
const game_params *params, int tilesize)
|
||||
{
|
||||
ds->sz6 = tilesize/6;
|
||||
ds->grid_line_all = max(LINE_THICK, 1);
|
||||
ds->grid_line_br = ds->grid_line_all / 2;
|
||||
ds->grid_line_tl = ds->grid_line_all - ds->grid_line_br;
|
||||
}
|
||||
|
||||
enum {
|
||||
|
|
@ -2346,14 +2351,13 @@ static void draw_square(drawing *dr, game_drawstate *ds,
|
|||
/* Clip to the grid square. */
|
||||
clip(dr, ox, oy, TILE_SIZE, TILE_SIZE);
|
||||
|
||||
/* Clear the square. */
|
||||
/* Clear the square so that it's got an appropriately-sized border
|
||||
* in COL_GRID and a central area in the right background colour. */
|
||||
best_bits((flags & DS_TRACK) == DS_TRACK,
|
||||
(flags_drag & DS_TRACK) == DS_TRACK, &bg);
|
||||
draw_rect(dr, ox, oy, TILE_SIZE, TILE_SIZE, bg);
|
||||
|
||||
/* Draw outline of grid square */
|
||||
draw_line(dr, ox, oy, COORD(x+1), oy, COL_GRID);
|
||||
draw_line(dr, ox, oy, ox, COORD(y+1), COL_GRID);
|
||||
draw_rect(dr, ox, oy, TILE_SIZE, TILE_SIZE, COL_GRID);
|
||||
draw_rect(dr, ox + GRID_LINE_TL, oy + GRID_LINE_TL,
|
||||
TILE_SIZE - GRID_LINE_ALL, TILE_SIZE - GRID_LINE_ALL, bg);
|
||||
|
||||
/* More outlines for clue squares. */
|
||||
if (flags & DS_CURSOR) {
|
||||
|
|
@ -2389,8 +2393,8 @@ static void draw_square(drawing *dr, game_drawstate *ds,
|
|||
(flags_drag & DS_NOTRACK) == DS_NOTRACK, &c);
|
||||
if (flags_best) {
|
||||
off = HALFSZ/2;
|
||||
draw_line(dr, cx - off, cy - off, cx + off, cy + off, c);
|
||||
draw_line(dr, cx - off, cy + off, cx + off, cy - off, c);
|
||||
draw_thick_line(dr, LINE_THICK, cx - off, cy - off, cx + off, cy + off, c);
|
||||
draw_thick_line(dr, LINE_THICK, cx - off, cy + off, cx + off, cy - off, c);
|
||||
}
|
||||
|
||||
c = COL_TRACK;
|
||||
|
|
@ -2404,8 +2408,8 @@ static void draw_square(drawing *dr, game_drawstate *ds,
|
|||
cx += (d == R) ? t2 : (d == L) ? -t2 : 0;
|
||||
cy += (d == D) ? t2 : (d == U) ? -t2 : 0;
|
||||
|
||||
draw_line(dr, cx - off, cy - off, cx + off, cy + off, c);
|
||||
draw_line(dr, cx - off, cy + off, cx + off, cy - off, c);
|
||||
draw_thick_line(dr, LINE_THICK, cx - off, cy - off, cx + off, cy + off, c);
|
||||
draw_thick_line(dr, LINE_THICK, cx - off, cy + off, cx + off, cy - off, c);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2426,12 +2430,14 @@ static void draw_clue(drawing *dr, game_drawstate *ds, int w, int clue, int i, i
|
|||
cy = CENTERED_COORD(i-w);
|
||||
}
|
||||
|
||||
draw_rect(dr, cx - tsz + BORDER, cy - tsz + BORDER,
|
||||
TILE_SIZE - BORDER, TILE_SIZE - BORDER, COL_BACKGROUND);
|
||||
draw_rect(dr, cx - tsz + GRID_LINE_TL, cy - tsz + GRID_LINE_TL,
|
||||
TILE_SIZE - GRID_LINE_ALL, TILE_SIZE - GRID_LINE_ALL,
|
||||
COL_BACKGROUND);
|
||||
sprintf(buf, "%d", clue);
|
||||
draw_text(dr, cx, cy, FONT_VARIABLE, tsz, ALIGN_VCENTRE|ALIGN_HCENTRE,
|
||||
col, buf);
|
||||
draw_update(dr, cx - tsz, cy - tsz, TILE_SIZE, TILE_SIZE);
|
||||
draw_update(dr, cx - tsz + GRID_LINE_TL, cy - tsz + GRID_LINE_TL,
|
||||
TILE_SIZE - GRID_LINE_ALL, TILE_SIZE - GRID_LINE_ALL);
|
||||
}
|
||||
|
||||
static void draw_loop_ends(drawing *dr, game_drawstate *ds,
|
||||
|
|
@ -2498,8 +2504,9 @@ static void game_redraw(drawing *dr, game_drawstate *ds, const game_state *oldst
|
|||
|
||||
draw_loop_ends(dr, ds, state, COL_CLUE);
|
||||
|
||||
draw_line(dr, COORD(ds->w), COORD(0), COORD(ds->w), COORD(ds->h), COL_GRID);
|
||||
draw_line(dr, COORD(0), COORD(ds->h), COORD(ds->w), COORD(ds->h), COL_GRID);
|
||||
draw_rect(dr, COORD(0) - GRID_LINE_BR, COORD(0) - GRID_LINE_BR,
|
||||
ds->w * TILE_SIZE + GRID_LINE_ALL,
|
||||
ds->h * TILE_SIZE + GRID_LINE_ALL, COL_GRID);
|
||||
|
||||
draw_update(dr, 0, 0, (w+2)*TILE_SIZE + 2*BORDER, (h+2)*TILE_SIZE + 2*BORDER);
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ while (<$desc>) {
|
|||
'<span class="puzzle"><table>'.
|
||||
'<tr><th align="center">%s</th></tr>'.
|
||||
'<tr><td align="center">'.
|
||||
'<img style="margin: 0.5em" alt="" title="%s" width=150 height=150 border=0 src="%s-web.png" />'.
|
||||
'<a href="js/%s.html"><img style="margin: 0.5em" alt="" title="%s" width=150 height=150 border=0 src="%s-web.png" /></a>'.
|
||||
'</td></tr>'.
|
||||
'<tr><td align="center" style="font-size: 70%%"><code>[</code>'.
|
||||
' <a href="java/%s.html">java</a> '.
|
||||
|
|
@ -41,6 +41,7 @@ while (<$desc>) {
|
|||
'<tr><td align="center">%s</td></tr></table></span>'.
|
||||
"\n",
|
||||
encode_entities($displayname),
|
||||
encode_entities($id),
|
||||
encode_entities($description),
|
||||
encode_entities($id),
|
||||
encode_entities($id),
|
||||
|
|
|
|||
|
|
@ -1545,7 +1545,7 @@ static frontend *frontend_new(HINSTANCE inst)
|
|||
fe->statusbar = NULL;
|
||||
fe->bitmap = NULL;
|
||||
|
||||
SetWindowLong(fe->hwnd, GWL_USERDATA, (LONG)fe);
|
||||
SetWindowLongPtr(fe->hwnd, GWLP_USERDATA, (LONG_PTR)fe);
|
||||
|
||||
return fe;
|
||||
}
|
||||
|
|
@ -1992,7 +1992,7 @@ static void make_dialog_full_screen(HWND hwnd)
|
|||
static int CALLBACK AboutDlgProc(HWND hwnd, UINT msg,
|
||||
WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
frontend *fe = (frontend *)GetWindowLong(hwnd, GWL_USERDATA);
|
||||
frontend *fe = (frontend *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
|
||||
switch (msg) {
|
||||
case WM_INITDIALOG:
|
||||
|
|
@ -2249,7 +2249,7 @@ static void create_config_controls(frontend * fe)
|
|||
static int CALLBACK ConfigDlgProc(HWND hwnd, UINT msg,
|
||||
WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
frontend *fe = (frontend *)GetWindowLong(hwnd, GWL_USERDATA);
|
||||
frontend *fe = (frontend *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
config_item *i;
|
||||
struct cfg_aux *j;
|
||||
|
||||
|
|
@ -2260,7 +2260,7 @@ static int CALLBACK ConfigDlgProc(HWND hwnd, UINT msg,
|
|||
char *title;
|
||||
|
||||
fe = (frontend *) lParam;
|
||||
SetWindowLong(hwnd, GWL_USERDATA, lParam);
|
||||
SetWindowLongPtr(hwnd, GWLP_USERDATA, lParam);
|
||||
fe->cfgbox = hwnd;
|
||||
|
||||
fe->cfg = frontend_get_config(fe, fe->cfg_which, &title);
|
||||
|
|
@ -2479,8 +2479,8 @@ static void about(frontend *fe)
|
|||
|
||||
SendMessage(fe->cfgbox, WM_SETFONT, (WPARAM)fe->cfgfont, FALSE);
|
||||
|
||||
SetWindowLong(fe->cfgbox, GWL_USERDATA, (LONG)fe);
|
||||
SetWindowLong(fe->cfgbox, DWL_DLGPROC, (LONG)AboutDlgProc);
|
||||
SetWindowLongPtr(fe->cfgbox, GWLP_USERDATA, (LONG_PTR)fe);
|
||||
SetWindowLongPtr(fe->cfgbox, DWLP_DLGPROC, (LONG_PTR)AboutDlgProc);
|
||||
|
||||
id = 1000;
|
||||
y = height/2;
|
||||
|
|
@ -2660,8 +2660,8 @@ static int get_config(frontend *fe, int which)
|
|||
|
||||
SendMessage(fe->cfgbox, WM_SETFONT, (WPARAM)fe->cfgfont, FALSE);
|
||||
|
||||
SetWindowLong(fe->cfgbox, GWL_USERDATA, (LONG)fe);
|
||||
SetWindowLong(fe->cfgbox, DWL_DLGPROC, (LONG)ConfigDlgProc);
|
||||
SetWindowLongPtr(fe->cfgbox, GWLP_USERDATA, (LONG_PTR)fe);
|
||||
SetWindowLongPtr(fe->cfgbox, DWLP_DLGPROC, (LONG_PTR)ConfigDlgProc);
|
||||
|
||||
/*
|
||||
* Count the controls so we can allocate cfgaux.
|
||||
|
|
@ -2975,7 +2975,7 @@ static int is_alt_pressed(void)
|
|||
static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
|
||||
WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
frontend *fe = (frontend *)GetWindowLong(hwnd, GWL_USERDATA);
|
||||
frontend *fe = (frontend *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
int cmd;
|
||||
|
||||
switch (message) {
|
||||
|
|
@ -2993,18 +2993,18 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
|
|||
cmd = wParam & ~0xF; /* low 4 bits reserved to Windows */
|
||||
switch (cmd) {
|
||||
case IDM_NEW:
|
||||
if (!midend_process_key(fe->me, 0, 0, 'n'))
|
||||
if (!midend_process_key(fe->me, 0, 0, UI_NEWGAME))
|
||||
PostQuitMessage(0);
|
||||
break;
|
||||
case IDM_RESTART:
|
||||
midend_restart_game(fe->me);
|
||||
break;
|
||||
case IDM_UNDO:
|
||||
if (!midend_process_key(fe->me, 0, 0, 'u'))
|
||||
if (!midend_process_key(fe->me, 0, 0, UI_UNDO))
|
||||
PostQuitMessage(0);
|
||||
break;
|
||||
case IDM_REDO:
|
||||
if (!midend_process_key(fe->me, 0, 0, '\x12'))
|
||||
if (!midend_process_key(fe->me, 0, 0, UI_REDO))
|
||||
PostQuitMessage(0);
|
||||
break;
|
||||
case IDM_COPY:
|
||||
|
|
@ -3026,7 +3026,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
|
|||
}
|
||||
break;
|
||||
case IDM_QUIT:
|
||||
if (!midend_process_key(fe->me, 0, 0, 'q'))
|
||||
if (!midend_process_key(fe->me, 0, 0, UI_QUIT))
|
||||
PostQuitMessage(0);
|
||||
break;
|
||||
case IDM_CONFIG:
|
||||
|
|
@ -3405,8 +3405,18 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
|
|||
}
|
||||
break;
|
||||
case WM_CHAR:
|
||||
if (!midend_process_key(fe->me, 0, 0, (unsigned char)wParam))
|
||||
PostQuitMessage(0);
|
||||
{
|
||||
int key = (unsigned char)wParam;
|
||||
if (key == '\x1A') {
|
||||
BYTE keystate[256];
|
||||
if (GetKeyboardState(keystate) &&
|
||||
(keystate[VK_SHIFT] & 0x80) &&
|
||||
(keystate[VK_CONTROL] & 0x80))
|
||||
key = UI_REDO;
|
||||
}
|
||||
if (!midend_process_key(fe->me, 0, 0, key))
|
||||
PostQuitMessage(0);
|
||||
}
|
||||
return 0;
|
||||
case WM_TIMER:
|
||||
if (fe->timer) {
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ has 'descfile' => (required => 1);
|
|||
% # (individual files or shortcuts or additions to PATH) that are
|
||||
% # installed.
|
||||
<Directory Id="TARGETDIR" Name="SourceDir">
|
||||
<Directory Id="ProgramFilesFolder" Name="PFiles">
|
||||
<Directory Id="ProgramFiles64Folder" Name="PFiles">
|
||||
<Directory Id="INSTALLDIR" Name="Simon Tatham's Portable Puzzle Collection">
|
||||
|
||||
% # The following components all install things in the main
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue