2 * Move history for WinBoard
4 * Author: Alessandro Scotti (Dec 2005)
5 * back-end part split off by HGM
7 * Copyright 2005 Alessandro Scotti
9 * ------------------------------------------------------------------------
11 * GNU XBoard is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation, either version 3 of the License, or (at
14 * your option) any later version.
16 * GNU XBoard is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program. If not, see http://www.gnu.org/licenses/.
24 * ------------------------------------------------------------------------
25 ** See the file ChangeLog for a revision history. */
37 /* templates for low-level front-end tasks (requiring platform-dependent implementation) */
38 void ClearHistoryMemo P((void)); // essential
39 int AppendToHistoryMemo P(( char * text, int bold, int colorNr )); // essential (coloring / styling optional)
40 void HighlightMove P(( int from, int to, Boolean highlight )); // optional (can be dummy)
41 void ScrollToCurrent P((int caretPos)); // optional (can be dummy)
43 /* templates for front-end entry point to allow inquiring about front-end state */
44 Boolean MoveHistoryDialogExists P((void));
45 Boolean MoveHistoryIsUp P((void));
48 typedef char MoveHistoryString[ MOVE_LEN*2 ];
50 static int lastFirst = 0;
51 static int lastLast = 0;
52 static int lastCurrent = -1;
54 static char lastLastMove[ MOVE_LEN ];
56 static MoveHistoryString * currMovelist;
57 static ChessProgramStats_Move * currPvInfo;
58 static int currFirst = 0;
59 static int currLast = 0;
60 static int currCurrent = -1;
67 static HistoryMove histMoves[ MAX_MOVES ];
69 /* Note: in the following code a "Memo" is a Rich Edit control (it's Delphi lingo) */
71 // back-end after replacing Windows data-types by equivalents
72 static Boolean OnlyCurrentPositionChanged()
74 Boolean result = FALSE;
77 lastLast >= lastFirst &&
78 lastCurrent >= lastFirst &&
79 currFirst == lastFirst &&
80 currLast == lastLast &&
86 /* Special case: last move changed */
87 if( currCurrent == currLast-1 ) {
88 if( strcmp( currMovelist[currCurrent], lastLastMove ) != 0 ) {
97 // back-end, after replacing Windows data types
98 static Boolean OneMoveAppended()
100 Boolean result = FALSE;
102 if( lastCurrent >= 0 && lastCurrent >= lastFirst && lastLast >= lastFirst &&
103 currCurrent >= 0 && currCurrent >= currFirst && currLast >= currFirst &&
104 lastFirst == currFirst &&
105 lastLast == (currLast-1) &&
106 lastCurrent == (currCurrent-1) &&
107 currCurrent == (currLast-1) &&
116 // back-end, now that color and font-style are passed as numbers
117 static void AppendMoveToMemo( int index )
121 if( index < 0 || index >= MAX_MOVES ) {
128 if( (index % 2) == 0 ) {
129 sprintf( buf, "%d.%s ", (index / 2)+1, index & 1 ? ".." : "" );
130 AppendToHistoryMemo( buf, 1, 0 ); // [HGM] 1 means bold, 0 default color
134 safeStrCpy( buf, SavePart( currMovelist[index]) , sizeof( buf)/sizeof( buf[0]) );
137 histMoves[index].memoOffset = AppendToHistoryMemo( buf, 0, 0 );
138 histMoves[index].memoLength = strlen(buf)-1;
140 /* PV info (if any) */
141 if( appData.showEvalInMoveHistory && currPvInfo[index].depth > 0 ) {
142 sprintf( buf, "{%s%.2f/%d} ",
143 currPvInfo[index].score >= 0 ? "+" : "",
144 currPvInfo[index].score / 100.0,
145 currPvInfo[index].depth );
147 AppendToHistoryMemo( buf, 0, 1); // [HGM] 1 means gray
152 void RefreshMemoContent()
158 for( i=currFirst; i<currLast; i++ ) {
159 AppendMoveToMemo( i );
163 // back-end part taken out of HighlightMove to determine character positions
164 static void DoHighlight(int index, int onoff)
166 if( index >= 0 && index < MAX_MOVES ) {
167 HighlightMove( histMoves[index].memoOffset,
168 histMoves[index].memoOffset + histMoves[index].memoLength, onoff );
172 // back-end, now that a wrapper is provided for the front-end code to do the actual scrolling
173 void MemoContentUpdated()
177 DoHighlight( lastCurrent, FALSE );
178 DoHighlight( currCurrent, TRUE );
180 lastFirst = currFirst;
182 lastCurrent = currCurrent;
183 lastLastMove[0] = '\0';
186 safeStrCpy( lastLastMove, SavePart( currMovelist[lastLast-1] ) , sizeof( lastLastMove)/sizeof( lastLastMove[0]) );
189 /* Deselect any text, move caret to end of memo */
190 if( currCurrent >= 0 ) {
191 caretPos = histMoves[currCurrent].memoOffset + histMoves[currCurrent].memoLength;
197 ScrollToCurrent(caretPos);
200 // back-end. Must be called as double-click call-back on move-history text edit
201 void FindMoveByCharIndex( int char_index )
205 for( index=currFirst; index<currLast; index++ ) {
206 if( char_index >= histMoves[index].memoOffset &&
207 char_index < (histMoves[index].memoOffset + histMoves[index].memoLength) )
209 ToNrEvent( index + 1 ); // moved here from call-back
214 // back-end. In WinBoard called by call-back, but could be called directly by SetIfExists?
215 void UpdateMoveHistory()
218 if( OnlyCurrentPositionChanged() ) {
219 /* Only "cursor" changed, no need to update memo content */
221 else if( OneMoveAppended() ) {
222 AppendMoveToMemo( currCurrent );
225 RefreshMemoContent();
228 MemoContentUpdated();
232 void MoveHistorySet( char movelist[][2*MOVE_LEN], int first, int last, int current, ChessProgramStats_Move * pvInfo )
234 /* [AS] Danger! For now we rely on the movelist parameter being a static variable! */
236 currMovelist = movelist;
239 currCurrent = current;
242 if(MoveHistoryDialogExists())
243 UpdateMoveHistory(); // [HGM] call this directly, in stead of through call-back