+ err = TRUE;
+
+ /*
+ * Now search around the boundary of the loop to
+ * highlight it.
+ *
+ * We have to do this in two passes. The first
+ * time, we toggle ERR_SQUARE_TMP on each edge;
+ * this pass terminates with ERR_SQUARE_TMP set on
+ * exactly the loop edges. In the second pass, we
+ * trace round that loop again and turn
+ * ERR_SQUARE_TMP into ERR_SQUARE. We have to do
+ * this because otherwise we might cancel part of a
+ * loop highlighted in a previous iteration of the
+ * outer loop.
+ */
+
+ for (pass = 0; pass < 2; pass++) {
+
+ x1 = i1 % W;
+ y1 = i1 / W;
+ x2 = i2 % W;
+ y2 = i2 / W;
+
+ do {
+ /* Mark this edge. */
+ if (pass == 0) {
+ state->errors[min(y1,y2)*W+min(x1,x2)] ^=
+ ERR_SQUARE_TMP;
+ } else {
+ state->errors[min(y1,y2)*W+min(x1,x2)] |=
+ ERR_SQUARE;
+ state->errors[min(y1,y2)*W+min(x1,x2)] &=
+ ~ERR_SQUARE_TMP;
+ }
+
+ /*
+ * Progress to the next edge by turning as
+ * sharply right as possible. In fact we do
+ * this by facing back along the edge and
+ * turning _left_ until we see an edge we
+ * can follow.
+ */
+ dx = x1 - x2;
+ dy = y1 - y2;
+
+ for (i = 0; i < 4; i++) {
+ /*
+ * Rotate (dx,dy) to the left.
+ */
+ dt = dx; dx = dy; dy = -dt;
+
+ /*
+ * See if (x2,y2) has an edge in direction
+ * (dx,dy).
+ */
+ if (x2+dx < 0 || x2+dx >= W ||
+ y2+dy < 0 || y2+dy >= H)
+ continue; /* off the side of the grid */
+ /* In the second pass, ignore unmarked edges. */
+ if (pass == 1 &&
+ !(state->errors[(y2-(dy<0))*W+x2-(dx<0)] &
+ ERR_SQUARE_TMP))
+ continue;
+ if (state->soln[(y2-(dy<0))*w+x2-(dx<0)] ==
+ (dx==dy ? -1 : +1))
+ break;
+ }
+
+ /*
+ * In pass 0, we expect to have found
+ * _some_ edge we can follow, even if it
+ * was found by rotating all the way round
+ * and going back the way we came.
+ *
+ * In pass 1, because we're removing the
+ * mark on each edge that allows us to
+ * follow it, we expect to find _no_ edge
+ * we can follow when we've come all the
+ * way round the loop.
+ */
+ if (pass == 1 && i == 4)
+ break;
+ assert(i < 4);
+
+ /*
+ * Set x1,y1 to x2,y2, and x2,y2 to be the
+ * other end of the new edge.
+ */
+ x1 = x2;
+ y1 = y2;
+ x2 += dx;
+ y2 += dy;
+ } while (y2*W+x2 != i2);
+
+ }
+
+ } else
+ dsf_merge(dsf, i1, i2);
+ }