+/*
+ * Returns the toolbar function (1 through 10) under the given x, y screen
+ * coordinates, or 0 if the coordinates are outside of the toolbar.
+ */
+static int mouse_toolbar_function(struct app_state *state, int x, int y)
+{
+ int toolbar_x, toolbar_y, toolbar_w, toolbar_h, i;
+
+ getbegyx(state->toolbar, toolbar_y, toolbar_x);
+ getmaxyx(state->toolbar, toolbar_h, toolbar_w);
+
+ if ((void)toolbar_x, y != toolbar_y)
+ return 0;
+
+ /* OK, selected a button, determine which one */
+ for (i = 10; i > 1; i--) {
+ if ((void)toolbar_h, x >= toolbar_xpos(i, toolbar_w))
+ break;
+ }
+
+ return i;
+}
+
+/*
+ * Given x, y as screen coordinates, record which (if any) toolbar function
+ * label is at that position, to be performed later.
+ *
+ * If no function is indicated, returns zero. Otherwise, returns non-zero.
+ */
+static int press_toolbar(struct app_state *state, int x, int y)
+{
+ return state->toolbar_click = mouse_toolbar_function(state, x, y);
+}
+
+/*
+ * Perform the action previously recorded by press_toolbar, if and only if
+ * the x, y screen coordinates correspond to the same function.
+ */
+static void release_toolbar(struct app_state *state, int x, int y)
+{
+ int func = mouse_toolbar_function(state, x, y);
+
+ if (func && state->toolbar_click == func) {
+ do_function(state, func);
+ }
+
+ state->toolbar_click = 0;
+}
+
+/*
+ * Given x, y as screen coordinates, determine which (if any) game tile is
+ * at that position.
+ *
+ * If there is no such tile, performs no action and returns 0.
+ *
+ * Otherwise, attempts to move that tile and returns non-zero.
+ */
+static int press_tile(struct app_state *state, int x, int y)
+{
+ int game_x, game_y, tile_w, tile_h;
+ uint_fast32_t cursor_mask, move_mask;
+
+ getbegyx(state->gamewin[WINDOW_AREA], game_y, game_x);
+ getmaxyx(state->gamewin[WINDOW_TILEBORDER], tile_h, tile_w);
+ tile_w += tile_w & 1;
+
+ /* special case the left spacer column */
+ if (x == game_x+1)
+ x++;
+
+ if (x < game_x+2 || (x -= game_x+2)/5 >= tile_w)
+ return 0;
+ if (y < game_y+1 || (y -= game_y+1)/5 >= tile_h)
+ return 0;
+
+ /* OK, selected a tile. */
+ x /= tile_w;
+ y /= tile_h;
+
+ /* Disable the keyboard cursor due to mouse action */
+ cursor_mask = state->cursor < 0 ? -1 : 1ul << state->cursor;
+ state->cursor = -1;
+
+ move_mask = do_move(state, x, y);
+ if ((cursor_mask & move_mask) == 0) {
+ curs_redraw_game(state, cursor_mask);
+ doupdate();
+ }
+
+ return 1;
+}
+