+++ /dev/null
-/*
- * ngamelist.c -- Game list window, Xt-independent front-end code for XBoard
- *
- * Copyright 1995, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Free Software Foundation, Inc.
- * ------------------------------------------------------------------------
- *
- * GNU XBoard is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or (at
- * your option) any later version.
- *
- * GNU XBoard is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see http://www.gnu.org/licenses/. *
- *
- *------------------------------------------------------------------------
- ** See the file ChangeLog for a revision history. */
-
-#include "config.h"
-
-#include <stdio.h>
-#include <ctype.h>
-#include <errno.h>
-#include <sys/types.h>
-
-#if STDC_HEADERS
-# include <stdlib.h>
-# include <string.h>
-#else /* not STDC_HEADERS */
-extern char *getenv();
-# if HAVE_STRING_H
-# include <string.h>
-# else /* not HAVE_STRING_H */
-# include <strings.h>
-# endif /* not HAVE_STRING_H */
-#endif /* not STDC_HEADERS */
-
-#if HAVE_UNISTD_H
-# include <unistd.h>
-#endif
-
-#include "common.h"
-#include "frontend.h"
-#include "backend.h"
-#include "dialogs.h"
-#include "menus.h"
-#include "gettext.h"
-
-#ifdef ENABLE_NLS
-# define _(s) gettext (s)
-# define N_(s) gettext_noop (s)
-#else
-# define _(s) (s)
-# define N_(s) s
-#endif
-
-
-static char filterString[MSG_SIZ];
-static int listLength, wins, losses, draws, page;
-int narrowFlag;
-
-
-typedef struct {
- short int x, y;
- short int w, h;
- FILE *fp;
- char *filename;
- char **strings;
-} GameListClosure;
-static GameListClosure *glc = NULL;
-
-static char *filterPtr;
-static char *list[1003];
-static int listEnd;
-
-static int GameListPrepare P((int byPos, int narrow));
-static void GameListReplace P((int page));
-static void GL_Button P((int n));
-
-Option gamesOptions[] = {
-{ 200, LR|TB, 400, NULL, (void*) list, NULL, NULL, ListBox, "", &appData.gameListFont },
-{ 0, 0, 100, NULL, (void*) &filterPtr, "", NULL, TextBox, "" },
-{ 4, SAME_ROW, 0, NULL, (void*) &GL_Button, NULL, NULL, Button, N_("find position") },
-{ 2, SAME_ROW, 0, NULL, (void*) &GL_Button, NULL, NULL, Button, N_("narrow") }, // buttons referred to by ID in value (=first) field!
-{ 3, SAME_ROW, 0, NULL, (void*) &GL_Button, NULL, NULL, Button, N_("thresholds") },
-{ 9, SAME_ROW, 0, NULL, (void*) &GL_Button, NULL, NULL, Button, N_("tags") },
-{ 5, SAME_ROW, 0, NULL, (void*) &GL_Button, NULL, NULL, Button, N_("next") },
-{ 6, SAME_ROW, 0, NULL, (void*) &GL_Button, NULL, NULL, Button, N_("close") },
-{ 0, SAME_ROW | NO_OK, 0, NULL, NULL, "", NULL, EndMark , "" }
-};
-
-static void
-GL_Button (int n)
-{
- int index;
- n = gamesOptions[n].value; // use marker in option rather than n itself, for more easy adding/deletng of buttons
- if (n == 6) { // close
- PopDown(GameListDlg);
- return;
- }
- if (n == 3) { // thresholds
- LoadOptionsPopUp(GameListDlg);
- return;
- }
- if (n == 9) { // tags
- GameListOptionsPopUp(GameListDlg);
- return;
- }
- index = SelectedListBoxItem(&gamesOptions[0]);
- if (n == 7) { // load
- if (index < 0) {
- DisplayError(_("No game selected"), 0);
- return;
- }
- } else if (n == 5) { // next
- index++;
- if (index >= listLength || !list[index]) {
- DisplayError(_("Can't go forward any further"), 0);
- return;
- }
- HighlightWithScroll(&gamesOptions[0], index, listEnd);
- } else if (n == 8) { // prev
- index--;
- if (index < 0) {
- DisplayError(_("Can't back up any further"), 0);
- return;
- }
- HighlightWithScroll(&gamesOptions[0], index, listEnd);
- } else if (n == 2 || // narrow
- n == 4) { // find position
- char *text;
- GetWidgetText(&gamesOptions[1], &text);
- safeStrCpy(filterString, text, sizeof(filterString)/sizeof(filterString[0]));
- GameListPrepare(True, n == 2); GameListReplace(0);
- return;
- }
-
- index = atoi(list[index])-1; // [HGM] filter: read true index from sequence nr of line
- if (cmailMsgLoaded) {
- CmailLoadGame(glc->fp, index + 1, glc->filename, True);
- } else {
- LoadGame(glc->fp, index + 1, glc->filename, True);
- }
-}
-
-static int
-GameListCreate (char *name)
-{
- int new;
- if(new = GenericPopUp(gamesOptions, name, GameListDlg, BoardWindow, NONMODAL, appData.topLevel))
- AddHandler(&gamesOptions[1], GameListDlg, 4),
- AddHandler(&gamesOptions[0], GameListDlg, 5);
- FocusOnWidget(&gamesOptions[0], GameListDlg);
- return new;
-}
-
-static int
-GameListPrepare (int byPos, int narrow)
-{ // [HGM] filter: put in separate routine, to make callable from call-back
- int nstrings;
- ListGame *lg;
- char **st, *line;
- TimeMark t, t2;
-
- GetTimeMark(&t);
- if(st = glc->strings) while(*st) free(*st++);
- nstrings = ((ListGame *) gameList.tailPred)->number;
- glc->strings = (char **) malloc((nstrings + 1) * sizeof(char *));
- st = glc->strings;
- lg = (ListGame *) gameList.head;
- listLength = wins = losses = draws = 0;
- if(byPos) InitSearch();
- while (nstrings--) {
- int pos = -1;
- if(!narrow || lg->position >= 0) { // only consider already selected positions when narrowing
- line = GameListLine(lg->number, &lg->gameInfo);
- if((filterString[0] == NULLCHAR || SearchPattern( line, filterString )) && (!byPos || (pos=GameContainsPosition(glc->fp, lg)) >= 0) ) {
- *st++ = line; // [HGM] filter: make adding line conditional.
- listLength++;
- if( lg->gameInfo.result == WhiteWins ) wins++; else
- if( lg->gameInfo.result == BlackWins ) losses++; else
- if( lg->gameInfo.result == GameIsDrawn ) draws++;
- if(!byPos) pos = 0; // indicate selected
- }
- }
- if(lg->number % 2000 == 0) {
- char buf[MSG_SIZ];
- snprintf(buf, MSG_SIZ, _("Scanning through games (%d)"), lg->number);
- DisplayTitle(buf); DoEvents();
- }
- lg->position = pos;
- lg = (ListGame *) lg->node.succ;
- }
- if(appData.debugMode) { GetTimeMark(&t2);printf("GameListPrepare %ld msec\n", SubtractTimeMarks(&t2,&t)); }
- DisplayTitle("XBoard");
- *st = NULL;
- return listLength;
-}
-
-static void
-GameListReplace (int page)
-{
- // filter: put in separate routine, to make callable from call-back
- char buf[MSG_SIZ], **st=list;
- int i;
-
- if(page) *st++ = _("previous page"); else if(listLength > 1000) *st++ = "";
- for(i=0; i<1000; i++) if( !(*st++ = glc->strings[page+i]) ) { st--; break; }
- listEnd = st - list;
- if(page + 1000 <= listLength) *st++ = _("next page");
- *st = NULL;
-
- LoadListBox(&gamesOptions[0], _("no games matched your request"), -1, -1);
- HighlightWithScroll(&gamesOptions[0], listEnd > 1000, listEnd);
- snprintf(buf, MSG_SIZ, _("%s - %d/%d games (%d-%d-%d)"), glc->filename, listLength, ((ListGame *) gameList.tailPred)->number, wins, losses, draws);
- SetDialogTitle(GameListDlg, buf);
-}
-
-void
-GameListUpdate ()
-{
- if(!DialogExists(GameListDlg)) return;
- GameListPrepare(False, False);
- GameListReplace(0);
-}
-
-void
-GameListPopUp (FILE *fp, char *filename)
-{
- if (glc == NULL) {
- glc = (GameListClosure *) calloc(1, sizeof(GameListClosure));
- glc->x = glc->y = -1;
- glc->filename = NULL;
- }
-
- GameListPrepare(False, False); // [HGM] filter: code put in separate routine
-
- glc->fp = fp;
-
- if (glc->filename != NULL) free(glc->filename);
- glc->filename = StrSave(filename);
-
- if (!GameListCreate(filename))
- SetIconName(GameListDlg, 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 *
-GameFile ()
-{
- return glc ? glc->fp : NULL;
-}
-
-void
-GameListDestroy ()
-{
- if (glc == NULL) return;
- EnableNamedMenuItem("File.SaveSelected", FALSE);
- PopDown(GameListDlg);
- if (glc->strings != NULL) {
- char **st;
- st = glc->strings;
- while (*st) {
- free(*st++);
- }
- free(glc->strings);
- }
- free(glc);
- glc = NULL;
-}
-
-void
-ShowGameListProc ()
-{
- if (glc == NULL) {
- DisplayError(_("There is no game list"), 0);
- return;
- }
- if (shellUp[GameListDlg]) {
- PopDown(GameListDlg);
- return;
- }
- GenericPopUp(NULL, NULL, GameListDlg, BoardWindow, NONMODAL, appData.topLevel); // first two args ignored when shell exists!
- MarkMenu("View.GameList", GameListDlg);
- GameListHighlight(lastLoadGameNumber);
-}
-
-int
-GameListClicks (int direction)
-{
- int index;
-
- if (glc == NULL || listLength == 0) return 1;
- if(direction == 100) { FocusOnWidget(&gamesOptions[0], GameListDlg); return 1; }
- index = SelectedListBoxItem(&gamesOptions[0]);
-
- if (index < 0) return 1;
- if(page && (index == 0 && direction < 1 || direction == -4)) {
- page -= 1000;
- if(page < 0) page = 0; // safety
- GameListReplace(page);
- return 1;
- }
- if(index == 1001 && direction >= 0 || listEnd == 1001 && direction == 4) {
- page += 1000;
- GameListReplace(page);
- return 1;
- }
-
- if(direction != 0) {
- int doLoad = abs(direction) == 3;
- if(doLoad) direction /= 3;
- index += direction;
- if(direction < -1) index = 0;
- if(direction > 1) index = listEnd-1;
- if(index < 0 || index >= listEnd) return 1;
- HighlightWithScroll(&gamesOptions[0], index, listEnd);
- if(!doLoad) return 1;
- }
- index = atoi(list[index])-1; // [HGM] filter: read true index from sequence nr of line
- if (cmailMsgLoaded) {
- CmailLoadGame(glc->fp, index + 1, glc->filename, True);
- } else {
- LoadGame(glc->fp, index + 1, glc->filename, True);
- }
- return 0;
-}
-
-void
-SetFilter ()
-{
- char *name;
- GetWidgetText(&gamesOptions[1], &name);
- safeStrCpy(filterString, name, sizeof(filterString)/sizeof(filterString[0]));
- GameListPrepare(False, False); GameListReplace(0);
- UnCaret(); // filter text-edit
- FocusOnWidget(&gamesOptions[0], GameListDlg); // listbox
-}
-
-void
-GameListHighlight (int index)
-{
- int i=0; char **st;
- if (!shellUp[GameListDlg]) return;
- st = list;
- while(*st && atoi(*st)<index) st++,i++;
- HighlightWithScroll(&gamesOptions[0], i, listEnd);
-}
-
-int
-SaveGameListAsText (FILE *f)
-{
- ListGame * lg = (ListGame *) gameList.head;
- int nItem;
-
- if( !glc || ((ListGame *) gameList.tailPred)->number <= 0 ) {
- DisplayError(_("Game list not loaded or empty"), 0);
- return False;
- }
-
- /* Copy the list into the global memory block */
- if( f != NULL ) {
-
- lg = (ListGame *) gameList.head;
-
- for (nItem = 0; nItem < ((ListGame *) gameList.tailPred)->number; nItem++){
- char * st = GameListLineFull(lg->number, &lg->gameInfo);
- char *line = GameListLine(lg->number, &lg->gameInfo);
- if(filterString[0] == NULLCHAR || SearchPattern( line, filterString ) )
- fprintf( f, "%s\n", st );
- free(st); free(line);
- lg = (ListGame *) lg->node.succ;
- }
-
- fclose(f);
- return True;
- }
- return False;
-}