Add Save Selected Games menu item
authorH.G.Muller <hgm@hgm-xboard.(none)>
Mon, 1 Sep 2014 12:44:54 +0000 (14:44 +0200)
committerH.G.Muller <hgm@hgm-xboard.(none)>
Mon, 1 Sep 2014 14:53:13 +0000 (16:53 +0200)
A menu item to save all selected games in the Game List on a single
file is added.

backend.c
backend.h
menus.c
ngamelist.c
winboard/resource.h
winboard/wgamelist.c
winboard/winboard.c
winboard/winboard.rc
winboard/woptions.c

index c81e0fd..f5b4e59 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -12368,7 +12368,7 @@ QuickScan (Board board, Move *move)
     do {
        int piece = move->piece;
        int to = move->to, from = pieceList[piece];
-       if(!found) { // if already found just scan to game end for final piece count
+       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) ||
@@ -12380,7 +12380,7 @@ QuickScan (Board board, Move *move)
            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 && !appData.minPieces) return found;
+         if(found >= 0 && !appData.minPieces) return found;
        }
        if(piece <= Q_PROMO) { // special moves encoded by otherwise invalid piece numbers 1-4
          if(!piece) return (appData.minPieces && (total < appData.minPieces || total > appData.maxPieces) ? -1 : found);
@@ -12408,7 +12408,7 @@ 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;
@@ -13366,9 +13366,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;
@@ -13528,7 +13528,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;
@@ -15823,6 +15829,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++;
+       }
+        lg = (ListGame *) lg->node.succ;
+    }
+
+    fclose(g);
+    creatingBook = FALSE;
+
+    return cnt;
+}
+
 void
 CreateBookEvent ()
 {
index 2acd187..d895155 100644 (file)
--- a/backend.h
+++ b/backend.h
@@ -106,6 +106,7 @@ int LoadGame P((FILE *f, int n, char *title, int useList));
 int LoadGameFromFile P((char *filename, int n, char *title, int useList));
 int CmailLoadGame P((FILE *f, int n, char *title, int useList));
 int ReloadGame P((int offset));
+int SaveSelected P((FILE *f, int dummy, char *dummy2));
 int SaveGame P((FILE *f, int dummy, char *dummy2));
 int SaveGameToFile P((char *filename, int append));
 int LoadPosition P((FILE *f, int n, char *title));
diff --git a/menus.c b/menus.c
index 0b8dcd4..65a154e 100644 (file)
--- a/menus.c
+++ b/menus.c
@@ -580,6 +580,15 @@ CreateBookDelayed ()
   ScheduleDelayedEvent(CreateBookEvent, 50);
 }
 
+void
+SaveSelectedProc ()
+{
+  FileNamePopUp(_("Save game file name?"),
+                 "",
+                 ".pgn",
+                 SaveSelected, "a");
+}
+
 /*
  *  Menu definition tables
  */
@@ -596,6 +605,7 @@ MenuItem fileMenu[] = {
   {"----",                      NULL,               NULL,                  NothingProc},
   {N_("Save Game"),            "<Ctrl>s",          "SaveGame",             SaveGameProc},
   {N_("Save Position"),        "<Ctrl><Shift>s",   "SavePosition",         SavePositionProc},
+  {N_("Save Selected Games"),   NULL,              "SaveSelected",         SaveSelectedProc},
   {N_("Save Games as Book"),    NULL,              "CreateBook",           CreateBookDelayed},
   {"----",                      NULL,               NULL,                  NothingProc},
   {N_("Mail Move"),             NULL,              "MailMove",             MailMoveEvent},
@@ -1218,4 +1228,5 @@ InitMenuMarkers()
     if (saveSettingsOnExit) {
        MarkMenuItem("Options.SaveSettingsonExit", True);
     }
+    EnableNamedMenuItem("File.SaveSelected", False);
 }
index c843d38..43de988 100644 (file)
@@ -242,6 +242,7 @@ GameListPopUp (FILE *fp, char *filename)
     page = 0;
     GameListReplace(0); // [HGM] filter: code put in separate routine, and also called to set title
     MarkMenu("View.GameList", GameListDlg);
+    EnableNamedMenuItem("File.SaveSelected", TRUE);
 }
 
 FILE *
@@ -254,6 +255,7 @@ void
 GameListDestroy ()
 {
     if (glc == NULL) return;
+    EnableNamedMenuItem("File.SaveSelected", FALSE);
     PopDown(GameListDlg);
     if (glc->strings != NULL) {
        char **st;
index 1634a3d..c6ca2e5 100644 (file)
 #define OPT_GameListFind                1981\r
 #define OPT_Grid                        1983\r
 #define IDM_LoadProg2                   1984\r
-#define OPT_Range                       1985\r
+#define OPT_Counts                      1985\r
 #define OPT_Ranget                      1986\r
+#define IDM_SaveSelected                1987\r
 \r
 \r
 // Next default values for new objects\r
index fe8acec..17e78f1 100644 (file)
@@ -406,6 +406,7 @@ VOID GameListPopUp(FILE *fp, char *filename)
     gameFileName = StrSave(filename);\r
   }\r
   CheckMenuItem(GetMenu(hwndMain), IDM_ShowGameList, MF_CHECKED);\r
+  EnableMenuItem(GetMenu(hwndMain), IDM_SaveSelected, MF_ENABLED);\r
   if (gameListDialog) {\r
     SendMessage(gameListDialog, WM_INITDIALOG, 0, 0);\r
     if (!gameListUp) ShowWindow(gameListDialog, SW_SHOW);\r
@@ -427,6 +428,7 @@ FILE *GameFile()
 VOID GameListPopDown(void)\r
 {\r
   CheckMenuItem(GetMenu(hwndMain), IDM_ShowGameList, MF_UNCHECKED);\r
+  EnableMenuItem(GetMenu(hwndMain), IDM_SaveSelected, MF_GRAYED);\r
   if (gameListDialog) ShowWindow(gameListDialog, SW_HIDE);\r
   gameListUp = FALSE;\r
 }\r
index a31fa7c..088badb 100644 (file)
@@ -1228,6 +1228,7 @@ InitMenuChecks()
   (void) CheckMenuItem(hmenu, IDM_SaveSettingsOnExit,\r
                       MF_BYCOMMAND|(saveSettingsOnExit ?\r
                                     MF_CHECKED : MF_UNCHECKED));\r
+  EnableMenuItem(hmenu, IDM_SaveSelected, MF_GRAYED);\r
 }\r
 \r
 //---------------------------------------------------------------------------------------------------------\r
@@ -4918,6 +4919,16 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
       }\r
       break;\r
 \r
+    case IDM_SaveSelected:\r
+      f = OpenFileDialog(hwnd, "a", "",\r
+                        "pgn",\r
+                        GAME_FILT,\r
+                        _("Save Game to File"), NULL, fileTitle, NULL);\r
+      if (f != NULL) {\r
+       SaveSelected(f, 0, "");\r
+      }\r
+      break;\r
+\r
     case IDM_CreateBook:\r
       CreateBookEvent();\r
       break;\r
index 7e06085..7c48808 100644 (file)
@@ -108,25 +108,25 @@ BEGIN
     EDITTEXT        OPT_date,16,90,28,14,ES_AUTOHSCROLL\r
     LTEXT           "co&nsecutive positions",OPT_Stretcht,46,114,94,8,NOT WS_GROUP\r
     EDITTEXT        OPT_Stretch,16,110,28,14,ES_AUTOHSCROLL\r
+    LTEXT           "final piece count",OPT_Ranget,46,134,94,8,NOT WS_GROUP\r
+    EDITTEXT        OPT_Counts,16,130,28,14,ES_AUTOHSCROLL\r
     CONTROL         "Match exact &position",OPT_Exact,"Button",\r
-                    BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,6,136,159,10\r
+                    BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,6,156,159,10\r
     CONTROL         "Match if position is s&ubset",OPT_Subset,"Button",\r
-                    BS_AUTORADIOBUTTON | WS_TABSTOP,6,149,159,10\r
+                    BS_AUTORADIOBUTTON | WS_TABSTOP,6,169,159,10\r
     CONTROL         "Match material with e&xact pawn structure",OPT_Struct,"Button",\r
-                    BS_AUTORADIOBUTTON | WS_TABSTOP,6,162,159,10\r
+                    BS_AUTORADIOBUTTON | WS_TABSTOP,6,182,159,10\r
     CONTROL         "Match &material",OPT_Material,"Button",\r
-                    BS_AUTORADIOBUTTON | WS_TABSTOP,6,175,159,10\r
+                    BS_AUTORADIOBUTTON | WS_TABSTOP,6,195,159,10\r
     CONTROL         "Material &range (upper board-half is optional)",OPT_Range,"Button",\r
-                    BS_AUTORADIOBUTTON | WS_TABSTOP,6,188,159,10\r
+                    BS_AUTORADIOBUTTON | WS_TABSTOP,6,208,159,10\r
     CONTROL         "Material &difference (optional material balanced)",OPT_Difference,"Button",\r
-                    BS_AUTORADIOBUTTON | WS_TABSTOP,6,201,159,10\r
-    GROUPBOX        "Search Mode: ",OPT_SearchMode,3,126,164,87,WS_GROUP\r
+                    BS_AUTORADIOBUTTON | WS_TABSTOP,6,221,159,10\r
+    GROUPBOX        "Search Mode: ",OPT_SearchMode,3,146,164,87,WS_GROUP\r
     CONTROL         "Also match reversed &colors",OPT_Reversed,"Button",\r
-                    BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,4,214,160,10\r
+                    BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,4,234,160,10\r
     CONTROL         "Also match &left-right mirror image",OPT_Mirror,"Button",\r
-                    BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,4,227,160,10\r
-    LTEXT           "final piece count",OPT_Ranget,46,242,94,8,NOT WS_GROUP\r
-    EDITTEXT        OPT_Range,16,242,28,14,ES_AUTOHSCROLL\r
+                    BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,4,247,160,10\r
     PUSHBUTTON      "OK",IDOK,56,262,50,14,WS_GROUP\r
     PUSHBUTTON      "Cancel",IDCANCEL,112,262,50,14\r
 END\r
@@ -1194,6 +1194,7 @@ BEGIN
         MENUITEM "S&ave Position...\tCtrl+Shift+S",IDM_SavePosition\r
         MENUITEM SEPARATOR\r
         MENUITEM "Save as &Diagram...",         IDM_SaveDiagram\r
+        MENUITEM "Save Selected Games...",      IDM_SaveSelected\r
         MENUITEM "Save Games to &Book",         IDM_CreateBook\r
         MENUITEM SEPARATOR\r
         MENUITEM "&Quit",                       IDM_Exit\r
index 2c92e4d..77e6eea 100644 (file)
@@ -2535,7 +2535,7 @@ LoadOptions(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
     SetDlgItemInt(hDlg, OPT_Stretch, appData.stretch, FALSE);\r
     CheckDlgButton(hDlg, OPT_Reversed, appData.ignoreColors);\r
     CheckDlgButton(hDlg, OPT_Mirror, appData.findMirror);\r
-    SetDlgItemText(hDlg, OPT_Range,  "");\r
+    SetDlgItemText(hDlg, OPT_Counts,  "");\r
     switch (appData.searchMode) {\r
     case 1:\r
       CheckDlgButton(hDlg, OPT_Exact, TRUE);\r
@@ -2580,9 +2580,9 @@ LoadOptions(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
       appData.searchMode = LoadOptionsWhichRadio(hDlg);\r
       appData.ignoreColors = IsDlgButtonChecked(hDlg, OPT_Reversed);\r
       appData.findMirror   = IsDlgButtonChecked(hDlg, OPT_Mirror);\r
-      appData.eloThreshold1 = GetDlgItemText(hDlg, OPT_Range, buf, MSG_SIZ);\r
+      GetDlgItemText(hDlg, OPT_Counts, buf, MSG_SIZ);\r
       appData.minPieces = appData.maxPieces = 0;\r
-      sscanf(buf, "%d-%d", appData.minPieces, appData.maxPieces);\r
+      sscanf(buf, "%d-%d", &appData.minPieces, &appData.maxPieces);\r
       if(appData.maxPieces < appData.minPieces) appData.maxPieces = appData.minPieces;\r
       EndDialog(hDlg, TRUE);\r
       return TRUE;\r