David Nickerson reports that it's possible to lay a line over a 'no
[sgt/puzzles] / midend.c
index 1ba0fa3..c1f3a01 100644 (file)
--- a/midend.c
+++ b/midend.c
@@ -156,6 +156,15 @@ midend *midend_new(frontend *fe, const game *ourgame,
     return me;
 }
 
+static void midend_purge_states(midend *me)
+{
+    while (me->nstates > me->statepos) {
+        me->ourgame->free_game(me->states[--me->nstates].state);
+        if (me->states[me->nstates].movestr)
+            sfree(me->states[me->nstates].movestr);
+    }
+}
+
 static void midend_free_game(midend *me)
 {
     while (me->nstates > 0) {
@@ -419,6 +428,16 @@ void midend_new_game(midend *me)
     me->pressed_mouse_button = 0;
 }
 
+int midend_can_undo(midend *me)
+{
+    return (me->statepos > 1);
+}
+
+int midend_can_redo(midend *me)
+{
+    return (me->statepos < me->nstates);
+}
+
 static int midend_undo(midend *me)
 {
     if (me->statepos > 1) {
@@ -511,8 +530,7 @@ void midend_restart_game(midend *me)
      * Now enter the restarted state as the next move.
      */
     midend_stop_anim(me);
-    while (me->nstates > me->statepos)
-       me->ourgame->free_game(me->states[--me->nstates].state);
+    midend_purge_states(me);
     ensure(me);
     me->states[me->nstates].state = s;
     me->states[me->nstates].movestr = dupstr(me->desc);
@@ -587,8 +605,7 @@ static int midend_really_process_key(midend *me, int x, int y, int button)
             goto done;
         } else if (s) {
            midend_stop_anim(me);
-            while (me->nstates > me->statepos)
-                me->ourgame->free_game(me->states[--me->nstates].state);
+            midend_purge_states(me);
             ensure(me);
             assert(movestr != NULL);
             me->states[me->nstates].state = s;
@@ -1292,11 +1309,7 @@ char *midend_solve(midend *me)
      * Now enter the solved state as the next move.
      */
     midend_stop_anim(me);
-    while (me->nstates > me->statepos) {
-       me->ourgame->free_game(me->states[--me->nstates].state);
-        if (me->states[me->nstates].movestr)
-            sfree(me->states[me->nstates].movestr);
-    }
+    midend_purge_states(me);
     ensure(me);
     me->states[me->nstates].state = s;
     me->states[me->nstates].movestr = movestr;
@@ -1318,11 +1331,29 @@ char *midend_solve(midend *me)
        me->anim_time = 0.0;
        midend_finish_move(me);
     }
-    midend_redraw(me);
+    if (me->drawing)
+        midend_redraw(me);
     midend_set_timer(me);
     return NULL;
 }
 
+int midend_status(midend *me)
+{
+    /*
+     * We should probably never be called when the state stack has no
+     * states on it at all - ideally, midends should never be left in
+     * that state for long enough to get put down and forgotten about.
+     * But if we are, I think we return _true_ - pedantically speaking
+     * a midend in that state is 'vacuously solved', and more
+     * practically, a user whose midend has been left in that state
+     * probably _does_ want the 'new game' option to be prominent.
+     */
+    if (me->statepos == 0)
+        return +1;
+
+    return me->ourgame->status(me->states[me->statepos-1].state);
+}
+
 char *midend_rewrite_statusbar(midend *me, char *text)
 {
     /*