X-Git-Url: http://winboard.nl/cgi-bin?a=blobdiff_plain;f=history.c;fp=history.c;h=4598799f2952ebf84173e1a7c7e02fe3f46040ec;hb=f1fbc14f88e6dfef22020dc193f3b4805952778c;hp=0000000000000000000000000000000000000000;hpb=3d14671eb68a945653366a390e7e27b5eaee9c22;p=xboard.git diff --git a/history.c b/history.c new file mode 100644 index 0000000..4598799 --- /dev/null +++ b/history.c @@ -0,0 +1,246 @@ +/* + * Move history for WinBoard + * + * Author: Alessandro Scotti (Dec 2005) + * back-end part split off by HGM + * + * Copyright 2005 Alessandro Scotti + * + * ------------------------------------------------------------------------ + * + * 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 +#include +#include +#include + +#include "common.h" +#include "frontend.h" +#include "backend.h" + +/* templates for low-level front-end tasks (requiring platform-dependent implementation) */ +void ClearHistoryMemo P((void)); // essential +int AppendToHistoryMemo P(( char * text, int bold, int colorNr )); // essential (coloring / styling optional) +void HighlightMove P(( int from, int to, Boolean highlight )); // optional (can be dummy) +void ScrollToCurrent P((int caretPos)); // optional (can be dummy) + +/* templates for front-end entry point to allow inquiring about front-end state */ +Boolean MoveHistoryDialogExists P((void)); +Boolean MoveHistoryIsUp P((void)); + +/* Module globals */ +typedef char MoveHistoryString[ MOVE_LEN*2 ]; + +static int lastFirst = 0; +static int lastLast = 0; +static int lastCurrent = -1; + +static char lastLastMove[ MOVE_LEN ]; + +static MoveHistoryString * currMovelist; +static ChessProgramStats_Move * currPvInfo; +static int currFirst = 0; +static int currLast = 0; +static int currCurrent = -1; + +typedef struct { + int memoOffset; + int memoLength; +} HistoryMove; + +static HistoryMove histMoves[ MAX_MOVES ]; + +/* Note: in the following code a "Memo" is a Rich Edit control (it's Delphi lingo) */ + +// back-end after replacing Windows data-types by equivalents +static Boolean OnlyCurrentPositionChanged() +{ + Boolean result = FALSE; + + if( lastFirst >= 0 && + lastLast >= lastFirst && + lastCurrent >= lastFirst && + currFirst == lastFirst && + currLast == lastLast && + currCurrent >= 0 && + TRUE ) + { + result = TRUE; + + /* Special case: last move changed */ + if( currCurrent == currLast-1 ) { + if( strcmp( currMovelist[currCurrent], lastLastMove ) != 0 ) { + result = FALSE; + } + } + } + + return result; +} + +// back-end, after replacing Windows data types +static Boolean OneMoveAppended() +{ + Boolean result = FALSE; + + if( lastCurrent >= 0 && lastCurrent >= lastFirst && lastLast >= lastFirst && + currCurrent >= 0 && currCurrent >= currFirst && currLast >= currFirst && + lastFirst == currFirst && + lastLast == (currLast-1) && + lastCurrent == (currCurrent-1) && + currCurrent == (currLast-1) && + TRUE ) + { + result = TRUE; + } + + return result; +} + +// back-end, now that color and font-style are passed as numbers +static void AppendMoveToMemo( int index ) +{ + char buf[64]; + + if( index < 0 || index >= MAX_MOVES ) { + return; + } + + buf[0] = '\0'; + + /* Move number */ + if( (index % 2) == 0 ) { + sprintf( buf, "%d.%s ", (index / 2)+1, index & 1 ? ".." : "" ); + AppendToHistoryMemo( buf, 1, 0 ); // [HGM] 1 means bold, 0 default color + } + + /* Move text */ + strcpy( buf, SavePart( currMovelist[index] ) ); + strcat( buf, " " ); + + histMoves[index].memoOffset = AppendToHistoryMemo( buf, 0, 0 ); + histMoves[index].memoLength = strlen(buf)-1; + + /* PV info (if any) */ + if( appData.showEvalInMoveHistory && currPvInfo[index].depth > 0 ) { + sprintf( buf, "{%s%.2f/%d} ", + currPvInfo[index].score >= 0 ? "+" : "", + currPvInfo[index].score / 100.0, + currPvInfo[index].depth ); + + AppendToHistoryMemo( buf, 0, 1); // [HGM] 1 means gray + } +} + +// back-end +void RefreshMemoContent() +{ + int i; + + ClearHistoryMemo(); + + for( i=currFirst; i= 0 && index < MAX_MOVES ) { + HighlightMove( histMoves[index].memoOffset, + histMoves[index].memoOffset + histMoves[index].memoLength, onoff ); + } +} + +// back-end, now that a wrapper is provided for the front-end code to do the actual scrolling +void MemoContentUpdated() +{ + int caretPos; + + DoHighlight( lastCurrent, FALSE ); + DoHighlight( currCurrent, TRUE ); + + lastFirst = currFirst; + lastLast = currLast; + lastCurrent = currCurrent; + lastLastMove[0] = '\0'; + + if( lastLast > 0 ) { + strcpy( lastLastMove, SavePart( currMovelist[lastLast-1] ) ); + } + + /* Deselect any text, move caret to end of memo */ + if( currCurrent >= 0 ) { + caretPos = histMoves[currCurrent].memoOffset + histMoves[currCurrent].memoLength; + } + else { + caretPos = -1; + } + + ScrollToCurrent(caretPos); +} + +// back-end. Must be called as double-click call-back on move-history text edit +void FindMoveByCharIndex( int char_index ) +{ + int index; + + for( index=currFirst; index= histMoves[index].memoOffset && + char_index < (histMoves[index].memoOffset + histMoves[index].memoLength) ) + { + ToNrEvent( index + 1 ); // moved here from call-back + } + } +} + +// back-end. In WinBoard called by call-back, but could be called directly by SetIfExists? +void UpdateMoveHistory() +{ + /* Update the GUI */ + if( OnlyCurrentPositionChanged() ) { + /* Only "cursor" changed, no need to update memo content */ + } + else if( OneMoveAppended() ) { + AppendMoveToMemo( currCurrent ); + } + else { + RefreshMemoContent(); + } + + MemoContentUpdated(); +} + +// back-end +void MoveHistorySet( char movelist[][2*MOVE_LEN], int first, int last, int current, ChessProgramStats_Move * pvInfo ) +{ + /* [AS] Danger! For now we rely on the movelist parameter being a static variable! */ + + currMovelist = movelist; + currFirst = first; + currLast = last; + currCurrent = current; + currPvInfo = pvInfo; + + if(MoveHistoryDialogExists()) + UpdateMoveHistory(); // [HGM] call this directly, in stead of through call-back +} +