Call DoEvents during time-consuming operations
[xboard.git] / backend.c
index f05359c..36eca33 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -8371,10 +8371,10 @@ BitbaseProbe ()
     // probe EGBB
     if(loaded == 2) return 13; // loading failed before
     if(loaded == 0) {
-       loaded = 2; // prepare for failure
        char *p, *path = strstr(appData.egtFormats, "scorpio:"), buf[MSG_SIZ];
        HMODULE lib;
        PLOAD_EGBB loadBB;
+       loaded = 2; // prepare for failure
        if(!path) return 13; // no egbb installed
        strncpy(buf, path + 8, MSG_SIZ);
        if(p = strchr(buf, ',')) *p = NULLCHAR; else p = buf + strlen(buf);
@@ -9421,6 +9421,9 @@ printf("score=%d count=%d\n",score,count);
            if (sscanf(message, "%d%c %d %d " u64Display " %[^\n]\n",
                       &plylev, &plyext, &curscore, &time, &nodes, buf1) >= 5) {
 
+               if(nodes>>32 == u64Const(0xFFFFFFFF))   // [HGM] negative node count read
+                   nodes += u64Const(0x100000000);
+
                if (plyext != ' ' && plyext != '\t') {
                    time *= 100;
                }
@@ -12364,12 +12367,26 @@ QuickCompare (Board board, int *minCounts, int *maxCounts)
 int
 QuickScan (Board board, Move *move)
 {   // reconstruct game,and compare all positions in it
-    int cnt=0, stretch=0, total = MakePieceList(board, counts);
+    int cnt=0, stretch=0, found = -1, total = MakePieceList(board, counts);
     do {
        int piece = move->piece;
        int to = move->to, from = pieceList[piece];
+       if(found < 0) { // if already found just scan to game end for final piece count
+         if(QuickCompare(soughtBoard, minSought, maxSought) ||
+          appData.ignoreColors && QuickCompare(reverseBoard, minReverse, maxReverse) ||
+          flipSearch && (QuickCompare(flipBoard, minSought, maxSought) ||
+                               appData.ignoreColors && QuickCompare(rotateBoard, minReverse, maxReverse))
+           ) {
+           static int lastCounts[EmptySquare+1];
+           int i;
+           if(stretch) for(i=0; i<EmptySquare; i++) if(lastCounts[i] != counts[i]) { stretch = 0; break; } // reset if material changes
+           if(stretch++ == 0) for(i=0; i<EmptySquare; i++) lastCounts[i] = counts[i]; // remember actual material
+         } else stretch = 0;
+         if(stretch && (appData.searchMode == 1 || stretch >= appData.stretch)) found = cnt + 1 - stretch;
+         if(found >= 0 && !appData.minPieces) return found;
+       }
        if(piece <= Q_PROMO) { // special moves encoded by otherwise invalid piece numbers 1-4
-         if(!piece) return -1;
+         if(!piece) return (appData.minPieces && (total < appData.minPieces || total > appData.maxPieces) ? -1 : found);
          if(piece == Q_PROMO) { // promotion, encoded as (Q_PROMO, to) + (piece, promoType)
            piece = (++move)->piece;
            from = pieceList[piece];
@@ -12394,23 +12411,12 @@ QuickScan (Board board, Move *move)
          }
        }
        if(appData.searchMode > 2) counts[pieceType[quickBoard[to]]]--; // account capture
-       if((total -= (quickBoard[to] != 0)) < soughtTotal) return -1; // piece count dropped below what we search for
+       if((total -= (quickBoard[to] != 0)) < soughtTotal && found < 0) return -1; // piece count dropped below what we search for
        quickBoard[from] = 0;
       aftercastle:
        quickBoard[to] = piece;
        pieceList[piece] = to;
        cnt++; turn ^= 3;
-       if(QuickCompare(soughtBoard, minSought, maxSought) ||
-          appData.ignoreColors && QuickCompare(reverseBoard, minReverse, maxReverse) ||
-          flipSearch && (QuickCompare(flipBoard, minSought, maxSought) ||
-                               appData.ignoreColors && QuickCompare(rotateBoard, minReverse, maxReverse))
-         ) {
-           static int lastCounts[EmptySquare+1];
-           int i;
-           if(stretch) for(i=0; i<EmptySquare; i++) if(lastCounts[i] != counts[i]) { stretch = 0; break; } // reset if material changes
-           if(stretch++ == 0) for(i=0; i<EmptySquare; i++) lastCounts[i] = counts[i]; // remember actual material
-       } else stretch = 0;
-       if(stretch && (appData.searchMode == 1 || stretch >= appData.stretch)) return cnt + 1 - stretch;
        move++;
     } while(1);
 }
@@ -13363,9 +13369,9 @@ GetOutOfBookInfo (char * buf)
     }
 }
 
-/* Save game in PGN style and close the file */
-int
-SaveGamePGN (FILE *f)
+/* Save game in PGN style */
+static void
+SaveGamePGN2 (FILE *f)
 {
     int i, offset, linelen, newblock;
 //    char *movetext;
@@ -13525,7 +13531,13 @@ SaveGamePGN (FILE *f)
     } else {
        fprintf(f, "%s\n\n", PGNResult(gameInfo.result));
     }
+}
 
+/* Save game in PGN style and close the file */
+int
+SaveGamePGN (FILE *f)
+{
+    SaveGamePGN2(f);
     fclose(f);
     lastSavedGame = GameCheckSum(); // [HGM] save: remember ID of last saved game to prevent double saving
     return TRUE;
@@ -15820,6 +15832,36 @@ HintEvent ()
     hintRequested = TRUE;
 }
 
+int
+SaveSelected (FILE *g, int dummy, char *dummy2)
+{
+    ListGame * lg = (ListGame *) gameList.head;
+    int nItem, cnt=0;
+    FILE *f;
+
+    if( !(f = GameFile()) || ((ListGame *) gameList.tailPred)->number <= 0 ) {
+        DisplayError(_("Game list not loaded or empty"), 0);
+        return 0;
+    }
+
+    creatingBook = TRUE; // suppresses stuff during load game
+
+    /* Get list size */
+    for (nItem = 1; nItem <= ((ListGame *) gameList.tailPred)->number; nItem++){
+       if(lg->position >= 0) { // selected?
+           LoadGame(f, nItem, "", TRUE);
+           SaveGamePGN2(g); // leaves g open
+           cnt++; DoEvents();
+       }
+        lg = (ListGame *) lg->node.succ;
+    }
+
+    fclose(g);
+    creatingBook = FALSE;
+
+    return cnt;
+}
+
 void
 CreateBookEvent ()
 {
@@ -15845,8 +15887,11 @@ CreateBookEvent ()
 
     /* Get list size */
     for (nItem = 1; nItem <= ((ListGame *) gameList.tailPred)->number; nItem++){
-       LoadGame(f, nItem, "", TRUE);
-       AddGameToBook(TRUE);
+       if(lg->position >= 0) {
+           LoadGame(f, nItem, "", TRUE);
+           AddGameToBook(TRUE);
+           DoEvents();
+       }
         lg = (ListGame *) lg->node.succ;
     }