X-Git-Url: http://winboard.nl/cgi-bin?a=blobdiff_plain;f=winboard%2Fwengineo.c;h=b56295916d7b0aac4a2440b2750ab8b70dc29685;hb=bb1c4f8ed2489e4891fe044532a35107d33174d2;hp=0623e3d9daf20dcd14afb66fdbfde4e208c3c5ec;hpb=762e18baef5f815cc46019ba3e082bd5ec1980f6;p=xboard.git diff --git a/winboard/wengineo.c b/winboard/wengineo.c index 0623e3d..b562959 100644 --- a/winboard/wengineo.c +++ b/winboard/wengineo.c @@ -3,22 +3,26 @@ * * Author: Alessandro Scotti (Dec 2005) * + * Copyright 2005 Alessandro Scotti + * * ------------------------------------------------------------------------ - * This program is free software; you can redistribute it and/or modify + * + * 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 2 of the License, or - * (at your option) any later version. + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. * - * This program 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. + * 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, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * ------------------------------------------------------------------------ - */ + * along with this program. If not, see http://www.gnu.org/licenses/. * + * + *------------------------------------------------------------------------ + ** See the file ChangeLog for a revision history. */ + #include "config.h" #include /* required for all Windows applications */ @@ -36,24 +40,48 @@ #include "wsnap.h" -VOID EngineOutputPopUp(); -VOID EngineOutputPopDown(); -BOOL EngineOutputIsUp(); +// [HGM] define numbers to indicate icons, for referring to them in platform-independent way +#define nColorBlack 1 +#define nColorWhite 2 +#define nColorUnknown 3 +#define nClear 4 +#define nPondering 5 +#define nThinking 6 +#define nAnalyzing 7 + +HICON icons[8]; // [HGM] this front-end array translates back-end icon indicator to handle + +// [HGM] same for output fields (note that there are two of each type, one per color) +#define nColorIcon 1 +#define nStateIcon 2 +#define nLabel 3 +#define nStateData 4 +#define nLabelNPS 5 +#define nMemo 6 + +HWND outputField[2][7]; // [HGM] front-end array to translate output field to window handle + +void EngineOutputPopUp(); +void EngineOutputPopDown(); +int EngineOutputIsUp(); #define SHOW_PONDERING /* Imports from backend.c */ char * SavePart(char *str); +extern int opponentKibitzes; /* Imports from winboard.c */ extern HWND engineOutputDialog; -extern BOOLEAN engineOutputDialogUp; +extern int engineOutputDialogUp; extern HINSTANCE hInst; extern HWND hwndMain; extern WindowPlacement wpEngineOutput; +extern BoardSize boardSize; + /* Module variables */ #define H_MARGIN 2 #define V_MARGIN 2 @@ -70,31 +98,23 @@ extern WindowPlacement wpEngineOutput; static int windowMode = 1; -static BOOL needInit = TRUE; - -static HICON hiColorBlack = NULL; -static HICON hiColorWhite = NULL; -static HICON hiColorUnknown = NULL; -static HICON hiClear = NULL; -static HICON hiPondering = NULL; -static HICON hiThinking = NULL; -static HICON hiAnalyzing = NULL; +static int needInit = TRUE; static int lastDepth[2] = { -1, -1 }; static int lastForwardMostMove[2] = { -1, -1 }; static int engineState[2] = { -1, -1 }; typedef struct { - HWND hColorIcon; - HWND hLabel; - HWND hStateIcon; - HWND hStateData; - HWND hLabelNPS; - HWND hMemo; +// HWND hColorIcon; // [HGM] the output-control handles are no loger passed, +// HWND hLabel; // to give better front-end / back-end separation +// HWND hStateIcon; // the front-end routines now get them from a (front-end) +// HWND hStateData; // table, indexed by output-field indicators. +// HWND hLabelNPS; +// HWND hMemo; char * name; int which; int depth; - unsigned long nodes; + u64 nodes; int score; int time; char * pv; @@ -103,26 +123,52 @@ typedef struct { int an_move_count; } EngineOutputData; +static void VerifyDisplayMode(); +static void UpdateControls( EngineOutputData * ed ); +static void SetEngineState( int which, int state, char * state_data ); + +// front end static HICON LoadIconEx( int id ) { return LoadImage( hInst, MAKEINTRESOURCE(id), IMAGE_ICON, ICON_SIZE, ICON_SIZE, 0 ); } -static VOID InitializeEngineOutput() +// [HGM] the platform-dependent way of indicating where output should go is now all +// concentrated here, where a table of platform-dependent handles are initialized. +// This cleanses most other routines of front-end stuff, so they can go into the back end. +static void InitializeEngineOutput() { - if( needInit ) { - hiColorBlack = LoadIconEx( IDI_BLACK_14 ); - hiColorWhite = LoadIconEx( IDI_WHITE_14 ); - hiColorUnknown = LoadIconEx( IDI_UNKNOWN_14 ); - hiClear = LoadIconEx( IDI_TRANS_14 ); - hiPondering = LoadIconEx( IDI_PONDER_14 ); - hiThinking = LoadIconEx( IDI_CLOCK_14 ); - hiAnalyzing = LoadIconEx( IDI_ANALYZE2_14 ); - needInit = FALSE; - } + // if( needInit ) { // needInit was already tested before call + // [HGM] made this into a table, rather than separate global variables + icons[nColorBlack] = LoadIconEx( IDI_BLACK_14 ); + icons[nColorWhite] = LoadIconEx( IDI_WHITE_14 ); + icons[nColorUnknown] = LoadIconEx( IDI_UNKNOWN_14 ); + icons[nClear] = LoadIconEx( IDI_TRANS_14 ); + icons[nPondering] = LoadIconEx( IDI_PONDER_14 ); + icons[nThinking] = LoadIconEx( IDI_CLOCK_14 ); + icons[nAnalyzing] = LoadIconEx( IDI_ANALYZE2_14 ); + + // [HGM] also make a table of handles to output controls + // Note that engineOutputDialog must be defined first! + outputField[0][nColorIcon] = GetDlgItem( engineOutputDialog, IDC_Color1 ); + outputField[0][nLabel] = GetDlgItem( engineOutputDialog, IDC_EngineLabel1 ); + outputField[0][nStateIcon] = GetDlgItem( engineOutputDialog, IDC_StateIcon1 ); + outputField[0][nStateData] = GetDlgItem( engineOutputDialog, IDC_StateData1 ); + outputField[0][nLabelNPS] = GetDlgItem( engineOutputDialog, IDC_Engine1_NPS ); + outputField[0][nMemo] = GetDlgItem( engineOutputDialog, IDC_EngineMemo1 ); + + outputField[1][nColorIcon] = GetDlgItem( engineOutputDialog, IDC_Color2 ); + outputField[1][nLabel] = GetDlgItem( engineOutputDialog, IDC_EngineLabel2 ); + outputField[1][nStateIcon] = GetDlgItem( engineOutputDialog, IDC_StateIcon2 ); + outputField[1][nStateData] = GetDlgItem( engineOutputDialog, IDC_StateData2 ); + outputField[1][nLabelNPS] = GetDlgItem( engineOutputDialog, IDC_Engine2_NPS ); + outputField[1][nMemo] = GetDlgItem( engineOutputDialog, IDC_EngineMemo2 ); +// needInit = FALSE; +// } } -static VOID SetControlPos( HWND hDlg, int id, int x, int y, int width, int height ) +// front end +static void SetControlPos( HWND hDlg, int id, int x, int y, int width, int height ) { HWND hControl = GetDlgItem( hDlg, id ); @@ -132,7 +178,8 @@ static VOID SetControlPos( HWND hDlg, int id, int x, int y, int width, int heigh #define HIDDEN_X 20000 #define HIDDEN_Y 20000 -static VOID HideControl( HWND hDlg, int id ) +// front end +static void HideControl( HWND hDlg, int id ) { HWND hControl = GetDlgItem( hDlg, id ); RECT rc; @@ -148,6 +195,7 @@ static VOID HideControl( HWND hDlg, int id ) } } +// front end, although we might make GetWindowRect front end instead static int GetControlWidth( HWND hDlg, int id ) { RECT rc; @@ -157,6 +205,7 @@ static int GetControlWidth( HWND hDlg, int id ) return rc.right - rc.left; } +// front end? static int GetControlHeight( HWND hDlg, int id ) { RECT rc; @@ -175,76 +224,9 @@ static int GetHeaderHeight() return result; } -#define ENGINE_COLOR_WHITE 'w' -#define ENGINE_COLOR_BLACK 'b' -#define ENGINE_COLOR_UNKNOWN ' ' - -char GetEngineColor( int which ) -{ - char result = ENGINE_COLOR_UNKNOWN; - - if( which == 0 || which == 1 ) { - ChessProgramState * cps; - - switch (gameMode) { - case MachinePlaysBlack: - case IcsPlayingBlack: - result = ENGINE_COLOR_BLACK; - break; - case MachinePlaysWhite: - case IcsPlayingWhite: - result = ENGINE_COLOR_WHITE; - break; - case AnalyzeMode: - case AnalyzeFile: - result = WhiteOnMove(forwardMostMove) ? ENGINE_COLOR_WHITE : ENGINE_COLOR_BLACK; - break; - case TwoMachinesPlay: - cps = (which == 0) ? &first : &second; - result = cps->twoMachinesColor[0]; - result = result == 'w' ? ENGINE_COLOR_WHITE : ENGINE_COLOR_BLACK; - break; - } - } - - return result; -} - -char GetActiveEngineColor() -{ - char result = ENGINE_COLOR_UNKNOWN; - - if( gameMode == TwoMachinesPlay ) { - result = WhiteOnMove(forwardMostMove) ? ENGINE_COLOR_WHITE : ENGINE_COLOR_BLACK; - } - - return result; -} - -static int IsEnginePondering( int which ) -{ - int result = FALSE; - - switch (gameMode) { - case MachinePlaysBlack: - case IcsPlayingBlack: - if( WhiteOnMove(forwardMostMove) ) result = TRUE; - break; - case MachinePlaysWhite: - case IcsPlayingWhite: - if( ! WhiteOnMove(forwardMostMove) ) result = TRUE; - break; - case TwoMachinesPlay: - if( GetActiveEngineColor() != ENGINE_COLOR_UNKNOWN ) { - if( GetEngineColor( which ) != GetActiveEngineColor() ) result = TRUE; - } - break; - } - - return result; -} - -static VOID PositionControlSet( HWND hDlg, int x, int y, int clientWidth, int memoHeight, int idColor, int idEngineLabel, int idNPS, int idMemo, int idStateIcon, int idStateData ) +// The size calculations should be backend? If setControlPos is a platform-dependent way of doing things, +// a platform-independent wrapper for it should be supplied. +static void PositionControlSet( HWND hDlg, int x, int y, int clientWidth, int memoHeight, int idColor, int idEngineLabel, int idNPS, int idMemo, int idStateIcon, int idStateData ) { int label_x = x + ICON_SIZE + H_MARGIN; int label_h = GetControlHeight( hDlg, IDC_EngineLabel1 ); @@ -265,13 +247,14 @@ static VOID PositionControlSet( HWND hDlg, int x, int y, int clientWidth, int me SetControlPos( hDlg, idMemo, x, memo_y, max_w, memoHeight ); } -static VOID ResizeWindowControls( HWND hDlg, int mode ) +// Also here some of the size calculations should go to the back end, and their actual application to a front-end routine +static void ResizeWindowControls( HWND hDlg, int mode ) { RECT rc; int headerHeight = GetHeaderHeight(); - int labelHeight = GetControlHeight( hDlg, IDC_EngineLabel1 ); - int labelOffset = H_MARGIN + ICON_SIZE + H_MARGIN; - int labelDeltaY = ICON_SIZE - labelHeight; +// int labelHeight = GetControlHeight( hDlg, IDC_EngineLabel1 ); +// int labelOffset = H_MARGIN + ICON_SIZE + H_MARGIN; +// int labelDeltaY = ICON_SIZE - labelHeight; int clientWidth; int clientHeight; int maxControlWidth; @@ -322,107 +305,396 @@ static VOID ResizeWindowControls( HWND hDlg, int mode ) InvalidateRect( GetDlgItem(hDlg,IDC_EngineMemo2), NULL, FALSE ); } -static VOID SetDisplayMode( int mode ) +// front end. Actual printing of PV lines into the output field +static void InsertIntoMemo( int which, char * text ) { - if( windowMode != mode ) { - windowMode = mode; + SendMessage( outputField[which][nMemo], EM_SETSEL, 0, 0 ); - ResizeWindowControls( engineOutputDialog, mode ); + SendMessage( outputField[which][nMemo], EM_REPLACESEL, (WPARAM) FALSE, (LPARAM) text ); +} + +// front end. Associates an icon with an output field ("control" in Windows jargon). +// [HGM] let it find out the output field from the 'which' number by itself +static void SetIcon( int which, int field, int nIcon ) +{ + + if( nIcon != 0 ) { + SendMessage( outputField[which][field], STM_SETICON, (WPARAM) icons[nIcon], 0 ); } } -static VOID VerifyDisplayMode() +// front end wrapper for SetWindowText, taking control number in stead of handle +void DoSetWindowText(int which, int field, char *s_label) { - int mode; + SetWindowText( outputField[which][field], s_label ); +} + +// This seems pure front end +LRESULT CALLBACK EngineOutputProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam ) +{ + static SnapData sd; + + switch (message) { + case WM_INITDIALOG: + if( engineOutputDialog == NULL ) { + engineOutputDialog = hDlg; + + RestoreWindowPlacement( hDlg, &wpEngineOutput ); /* Restore window placement */ + + ResizeWindowControls( hDlg, windowMode ); + + /* Set font */ + SendDlgItemMessage( engineOutputDialog, IDC_EngineMemo1, WM_SETFONT, (WPARAM)font[boardSize][MOVEHISTORY_FONT]->hf, MAKELPARAM(TRUE, 0 )); + SendDlgItemMessage( engineOutputDialog, IDC_EngineMemo2, WM_SETFONT, (WPARAM)font[boardSize][MOVEHISTORY_FONT]->hf, MAKELPARAM(TRUE, 0 )); + + SetEngineState( 0, STATE_IDLE, "" ); + SetEngineState( 1, STATE_IDLE, "" ); + } + + return FALSE; + + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDOK: + EndDialog(hDlg, TRUE); + return TRUE; + + case IDCANCEL: + EndDialog(hDlg, FALSE); + return TRUE; + + default: + break; + } - /* Get proper mode for current game */ - switch( gameMode ) { - case AnalyzeMode: - case AnalyzeFile: - case MachinePlaysWhite: - case MachinePlaysBlack: - case IcsPlayingWhite: - case IcsPlayingBlack: - mode = 0; break; - case TwoMachinesPlay: - mode = 1; + + case WM_GETMINMAXINFO: + { + MINMAXINFO * mmi = (MINMAXINFO *) lParam; + + mmi->ptMinTrackSize.x = 100; + mmi->ptMinTrackSize.y = 160; + } break; - default: - /* Do not change */ - return; + + case WM_CLOSE: + EngineOutputPopDown(); + break; + + case WM_SIZE: + ResizeWindowControls( hDlg, windowMode ); + break; + + case WM_ENTERSIZEMOVE: + return OnEnterSizeMove( &sd, hDlg, wParam, lParam ); + + case WM_SIZING: + return OnSizing( &sd, hDlg, wParam, lParam ); + + case WM_MOVING: + return OnMoving( &sd, hDlg, wParam, lParam ); + + case WM_EXITSIZEMOVE: + return OnExitSizeMove( &sd, hDlg, wParam, lParam ); } - SetDisplayMode( mode ); + return FALSE; } -static VOID InsertIntoMemo( HWND hMemo, char * text ) +// front end +void EngineOutputPopUp() { - SendMessage( hMemo, EM_SETSEL, 0, 0 ); + FARPROC lpProc; + + CheckMenuItem(GetMenu(hwndMain), IDM_ShowEngineOutput, MF_CHECKED); - SendMessage( hMemo, EM_REPLACESEL, (WPARAM) FALSE, (LPARAM) text ); -} + if( engineOutputDialog ) { + SendMessage( engineOutputDialog, WM_INITDIALOG, 0, 0 ); -static VOID SetIcon( HWND hControl, HICON hIcon ) -{ - if( hIcon != NULL ) { - SendMessage( hControl, STM_SETICON, (WPARAM) hIcon, 0 ); + if( ! engineOutputDialogUp ) { + ShowWindow(engineOutputDialog, SW_SHOW); } + } + else { + lpProc = MakeProcInstance( (FARPROC) EngineOutputProc, hInst ); + + /* Note to self: dialog must have the WS_VISIBLE style set, otherwise it's not shown! */ + CreateDialog( hInst, MAKEINTRESOURCE(DLG_EngineOutput), hwndMain, (DLGPROC)lpProc ); + + FreeProcInstance(lpProc); + } + + // [HGM] displaced to after creation of dialog, to allow initialization of output fields + if( needInit ) { + InitializeEngineOutput(); + needInit = FALSE; + } + + engineOutputDialogUp = TRUE; } -static VOID SetEngineColorIcon( HWND hControl, int which ) +// front end +void EngineOutputPopDown() { - char color = GetEngineColor(which); - HICON hicon = NULL; + CheckMenuItem(GetMenu(hwndMain), IDM_ShowEngineOutput, MF_UNCHECKED); - if( color == ENGINE_COLOR_BLACK ) - hicon = hiColorBlack; - else if( color == ENGINE_COLOR_WHITE ) - hicon = hiColorWhite; - else - hicon = hiColorUnknown; + if( engineOutputDialog ) { + ShowWindow(engineOutputDialog, SW_HIDE); + } + + engineOutputDialogUp = FALSE; +} - SetIcon( hControl, hicon ); +// front end. [HGM] Takes handle of output control from table, so only number is passed +void DoClearMemo(int which) +{ + SendMessage( outputField[which][nMemo], WM_SETTEXT, 0, (LPARAM) "" ); } -static SetEngineState( int which, int state, char * state_data ) +//------------------------ pure back-end routines ------------------------------- + + +// back end, due to front-end wrapper for SetWindowText, and new SetIcon arguments +static void SetEngineState( int which, int state, char * state_data ) { int x_which = 1 - which; - HWND hStateIcon = GetDlgItem( engineOutputDialog, which == 0 ? IDC_StateIcon1 : IDC_StateIcon2 ); - HWND hStateData = GetDlgItem( engineOutputDialog, which == 0 ? IDC_StateData1 : IDC_StateData2 ); if( engineState[ which ] != state ) { engineState[ which ] = state; switch( state ) { case STATE_THINKING: - SetIcon( hStateIcon, hiThinking ); + SetIcon( which, nStateIcon, nThinking ); if( engineState[ x_which ] == STATE_THINKING ) { SetEngineState( x_which, STATE_IDLE, "" ); } break; case STATE_PONDERING: - SetIcon( hStateIcon, hiPondering ); + SetIcon( which, nStateIcon, nPondering ); break; case STATE_ANALYZING: - SetIcon( hStateIcon, hiAnalyzing ); + SetIcon( which, nStateIcon, nAnalyzing ); break; default: - SetIcon( hStateIcon, hiClear ); + SetIcon( which, nStateIcon, nClear ); break; } } if( state_data != 0 ) { - SetWindowText( hStateData, state_data ); + DoSetWindowText( which, nStateData, state_data ); } } +// back end, now the front-end wrapper ClearMemo is used, and ed no longer contains handles. +void EngineOutputUpdate( FrontEndProgramStats * stats ) +{ + EngineOutputData ed; + int clearMemo = FALSE; + int which; + int depth; + + if( stats == 0 ) { + SetEngineState( 0, STATE_IDLE, "" ); + SetEngineState( 1, STATE_IDLE, "" ); + return; + } + + if(gameMode == IcsObserving && !appData.icsEngineAnalyze) + return; // [HGM] kibitz: shut up engine if we are observing an ICS game + + which = stats->which; + depth = stats->depth; + + if( which < 0 || which > 1 || depth < 0 || stats->time < 0 || stats->pv == 0 ) { + return; + } + + if( engineOutputDialog == NULL ) { + return; + } + + VerifyDisplayMode(); + + ed.which = which; + ed.depth = depth; + ed.nodes = stats->nodes; + ed.score = stats->score; + ed.time = stats->time; + ed.pv = stats->pv; + ed.hint = stats->hint; + ed.an_move_index = stats->an_move_index; + ed.an_move_count = stats->an_move_count; + + /* Get target control. [HGM] this is moved to front end, which get them from a table */ + if( which == 0 ) { + ed.name = first.tidy; + } + else { + ed.name = second.tidy; + } + + /* Clear memo if needed */ + if( lastDepth[which] > depth || (lastDepth[which] == depth && depth <= 1) ) { + clearMemo = TRUE; + } + + if( lastForwardMostMove[which] != forwardMostMove ) { + clearMemo = TRUE; + } + + if( clearMemo ) DoClearMemo(which); + + /* Update */ + lastDepth[which] = depth; + lastForwardMostMove[which] = forwardMostMove; + + if( ed.pv != 0 && ed.pv[0] == ' ' ) { + if( strncmp( ed.pv, " no PV", 6 ) == 0 ) { /* Hack on hack! :-O */ + ed.pv = ""; + } + } + + UpdateControls( &ed ); +} + +#define ENGINE_COLOR_WHITE 'w' +#define ENGINE_COLOR_BLACK 'b' +#define ENGINE_COLOR_UNKNOWN ' ' + +// pure back end +char GetEngineColor( int which ) +{ + char result = ENGINE_COLOR_UNKNOWN; + + if( which == 0 || which == 1 ) { + ChessProgramState * cps; + + switch (gameMode) { + case MachinePlaysBlack: + case IcsPlayingBlack: + result = ENGINE_COLOR_BLACK; + break; + case MachinePlaysWhite: + case IcsPlayingWhite: + result = ENGINE_COLOR_WHITE; + break; + case AnalyzeMode: + case AnalyzeFile: + result = WhiteOnMove(forwardMostMove) ? ENGINE_COLOR_WHITE : ENGINE_COLOR_BLACK; + break; + case TwoMachinesPlay: + cps = (which == 0) ? &first : &second; + result = cps->twoMachinesColor[0]; + result = result == 'w' ? ENGINE_COLOR_WHITE : ENGINE_COLOR_BLACK; + break; + default: ; // does not happen, but suppresses pedantic warnings + } + } + + return result; +} + +// pure back end +char GetActiveEngineColor() +{ + char result = ENGINE_COLOR_UNKNOWN; + + if( gameMode == TwoMachinesPlay ) { + result = WhiteOnMove(forwardMostMove) ? ENGINE_COLOR_WHITE : ENGINE_COLOR_BLACK; + } + + return result; +} + +// pure back end +static int IsEnginePondering( int which ) +{ + int result = FALSE; + + switch (gameMode) { + case MachinePlaysBlack: + case IcsPlayingBlack: + if( WhiteOnMove(forwardMostMove) ) result = TRUE; + break; + case MachinePlaysWhite: + case IcsPlayingWhite: + if( ! WhiteOnMove(forwardMostMove) ) result = TRUE; + break; + case TwoMachinesPlay: + if( GetActiveEngineColor() != ENGINE_COLOR_UNKNOWN ) { + if( GetEngineColor( which ) != GetActiveEngineColor() ) result = TRUE; + } + break; + default: ; // does not happen, but suppresses pedantic warnings + } + + return result; +} + +// back end +static void SetDisplayMode( int mode ) +{ + if( windowMode != mode ) { + windowMode = mode; + + ResizeWindowControls( engineOutputDialog, mode ); + } +} + +// pure back end +static void VerifyDisplayMode() +{ + int mode; + + /* Get proper mode for current game */ + switch( gameMode ) { + case IcsObserving: // [HGM] ICS analyze + if(!appData.icsEngineAnalyze) return; + case AnalyzeMode: + case AnalyzeFile: + case MachinePlaysWhite: + case MachinePlaysBlack: + mode = 0; + break; + case IcsPlayingWhite: + case IcsPlayingBlack: + mode = appData.zippyPlay && opponentKibitzes; // [HGM] kibitz + break; + case TwoMachinesPlay: + mode = 1; + break; + default: + /* Do not change */ + return; + } + + SetDisplayMode( mode ); +} + +// back end. Determine what icon to se in the color-icon field, and print it +static void SetEngineColorIcon( int which ) +{ + char color = GetEngineColor(which); + int nicon = 0; + + if( color == ENGINE_COLOR_BLACK ) + nicon = nColorBlack; + else if( color == ENGINE_COLOR_WHITE ) + nicon = nColorWhite; + else + nicon = nColorUnknown; + + SetIcon( which, nColorIcon, nicon ); +} + #define MAX_NAME_LENGTH 32 -static VOID UpdateControls( EngineOutputData * ed ) +// pure back end, now SetWindowText is called via wrapper DoSetWindowText +static void UpdateControls( EngineOutputData * ed ) { - BOOL isPondering = FALSE; +// int isPondering = FALSE; char s_label[MAX_NAME_LENGTH + 32]; @@ -464,7 +736,8 @@ static VOID UpdateControls( EngineOutputData * ed ) else if( gameMode == TwoMachinesPlay ) { SetEngineState( ed->which, STATE_THINKING, "" ); } - else if( gameMode == AnalyzeMode || gameMode == AnalyzeFile ) { + else if( gameMode == AnalyzeMode || gameMode == AnalyzeFile + || (gameMode == IcsObserving && appData.icsEngineAnalyze)) { // [HGM] ICS-analyze char buf[64]; int time_secs = ed->time / 100; int time_mins = time_secs / 60; @@ -487,7 +760,7 @@ static VOID UpdateControls( EngineOutputData * ed ) } #endif - SetWindowText( ed->hLabel, s_label ); + DoSetWindowText( ed->which, nLabel, s_label ); s_label[0] = '\0'; @@ -502,7 +775,7 @@ static VOID UpdateControls( EngineOutputData * ed ) } } - SetWindowText( ed->hLabelNPS, s_label ); + DoSetWindowText( ed->which, nLabelNPS, s_label ); /* Memo */ if( ed->pv != 0 && *ed->pv != '\0' ) { @@ -516,10 +789,10 @@ static VOID UpdateControls( EngineOutputData * ed ) /* Nodes */ if( ed->nodes < 1000000 ) { - sprintf( s_nodes, "%lu", ed->nodes ); + sprintf( s_nodes, u64Display, ed->nodes ); } else { - sprintf( s_nodes, "%.1fM", ed->nodes / 1000000.0 ); + sprintf( s_nodes, "%.1fM", u64ToDouble(ed->nodes) / 1000000.0 ); } /* Score */ @@ -546,206 +819,36 @@ static VOID UpdateControls( EngineOutputData * ed ) strcat( buf + buflen, "\r\n" ); /* Update memo */ - InsertIntoMemo( ed->hMemo, buf ); + InsertIntoMemo( ed->which, buf ); } /* Colors */ - SetEngineColorIcon( ed->hColorIcon, ed->which ); + SetEngineColorIcon( ed->which ); } -LRESULT CALLBACK EngineOutputProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam ) -{ - static SnapData sd; - - switch (message) { - case WM_INITDIALOG: - if( engineOutputDialog == NULL ) { - engineOutputDialog = hDlg; - - RestoreWindowPlacement( hDlg, &wpEngineOutput ); /* Restore window placement */ - - ResizeWindowControls( hDlg, windowMode ); - - SetEngineState( 0, STATE_IDLE, "" ); - SetEngineState( 1, STATE_IDLE, "" ); - } - - return FALSE; - - case WM_COMMAND: - switch (LOWORD(wParam)) { - case IDOK: - EndDialog(hDlg, TRUE); - return TRUE; - - case IDCANCEL: - EndDialog(hDlg, FALSE); - return TRUE; - - default: - break; - } - - break; - - case WM_GETMINMAXINFO: - { - MINMAXINFO * mmi = (MINMAXINFO *) lParam; - - mmi->ptMinTrackSize.x = 100; - mmi->ptMinTrackSize.y = 160; - } - break; - - case WM_CLOSE: - EngineOutputPopDown(); - break; - - case WM_SIZE: - ResizeWindowControls( hDlg, windowMode ); - break; - - case WM_ENTERSIZEMOVE: - return OnEnterSizeMove( &sd, hDlg, wParam, lParam ); - - case WM_SIZING: - return OnSizing( &sd, hDlg, wParam, lParam ); - - case WM_MOVING: - return OnMoving( &sd, hDlg, wParam, lParam ); - - case WM_EXITSIZEMOVE: - return OnExitSizeMove( &sd, hDlg, wParam, lParam ); - } - - return FALSE; -} - -VOID EngineOutputPopUp() -{ - FARPROC lpProc; - - if( needInit ) { - InitializeEngineOutput(); - } - - CheckMenuItem(GetMenu(hwndMain), IDM_ShowEngineOutput, MF_CHECKED); - - if( engineOutputDialog ) { - SendMessage( engineOutputDialog, WM_INITDIALOG, 0, 0 ); - - if( ! engineOutputDialogUp ) { - ShowWindow(engineOutputDialog, SW_SHOW); - } - } - else { - lpProc = MakeProcInstance( (FARPROC) EngineOutputProc, hInst ); - - /* Note to self: dialog must have the WS_VISIBLE style set, otherwise it's not shown! */ - CreateDialog( hInst, MAKEINTRESOURCE(DLG_EngineOutput), hwndMain, (DLGPROC)lpProc ); - - FreeProcInstance(lpProc); - } - - engineOutputDialogUp = TRUE; - ShowThinkingEvent(); // [HGM] thinking: might need to prompt engine for thinking output -} - -VOID EngineOutputPopDown() -{ - CheckMenuItem(GetMenu(hwndMain), IDM_ShowEngineOutput, MF_UNCHECKED); - - if( engineOutputDialog ) { - ShowWindow(engineOutputDialog, SW_HIDE); - } - - engineOutputDialogUp = FALSE; - ShowThinkingEvent(); // [HGM] thinking: might need to shut off thinking output -} - -BOOL EngineOutputIsUp() +// back end +int EngineOutputIsUp() { return engineOutputDialogUp; } -VOID EngineOutputUpdate( FrontEndProgramStats * stats ) +// [HGM] kibitz: write kibitz line; split window for it if necessary +void OutputKibitz(int window, char *text) { - EngineOutputData ed; - BOOL clearMemo = FALSE; - int which; - int depth; - - if( stats == 0 ) { - SetEngineState( 0, STATE_IDLE, "" ); - SetEngineState( 1, STATE_IDLE, "" ); - return; - } - - which = stats->which; - depth = stats->depth; - - if( which < 0 || which > 1 || depth < 0 || stats->time < 0 || stats->pv == 0 ) { - return; - } - - if( engineOutputDialog == NULL ) { - return; - } - - VerifyDisplayMode(); - - ed.which = which; - ed.depth = depth; - ed.nodes = stats->nodes; - ed.score = stats->score; - ed.time = stats->time; - ed.pv = stats->pv; - ed.hint = stats->hint; - ed.an_move_index = stats->an_move_index; - ed.an_move_count = stats->an_move_count; - - /* Get target control */ - if( which == 0 ) { - ed.hColorIcon = GetDlgItem( engineOutputDialog, IDC_Color1 ); - ed.hLabel = GetDlgItem( engineOutputDialog, IDC_EngineLabel1 ); - ed.hStateIcon = GetDlgItem( engineOutputDialog, IDC_StateIcon1 ); - ed.hStateData = GetDlgItem( engineOutputDialog, IDC_StateData1 ); - ed.hLabelNPS = GetDlgItem( engineOutputDialog, IDC_Engine1_NPS ); - ed.hMemo = GetDlgItem( engineOutputDialog, IDC_EngineMemo1 ); - ed.name = first.tidy; - } - else { - ed.hColorIcon = GetDlgItem( engineOutputDialog, IDC_Color2 ); - ed.hLabel = GetDlgItem( engineOutputDialog, IDC_EngineLabel2 ); - ed.hStateIcon = GetDlgItem( engineOutputDialog, IDC_StateIcon2 ); - ed.hStateData = GetDlgItem( engineOutputDialog, IDC_StateData2 ); - ed.hLabelNPS = GetDlgItem( engineOutputDialog, IDC_Engine2_NPS ); - ed.hMemo = GetDlgItem( engineOutputDialog, IDC_EngineMemo2 ); - ed.name = second.tidy; - } - - /* Clear memo if needed */ - if( lastDepth[which] > depth || (lastDepth[which] == depth && depth <= 1) ) { - clearMemo = TRUE; - } - - if( lastForwardMostMove[which] != forwardMostMove ) { - clearMemo = TRUE; - } - - if( clearMemo ) { - SendMessage( ed.hMemo, WM_SETTEXT, 0, (LPARAM) "" ); - } - - /* Update */ - lastDepth[which] = depth; - lastForwardMostMove[which] = forwardMostMove; - - if( ed.pv != 0 && ed.pv[0] == ' ' ) { - if( strncmp( ed.pv, " no PV", 6 ) == 0 ) { /* Hack on hack! :-O */ - ed.pv = ""; - } - } - - UpdateControls( &ed ); + if(!EngineOutputIsUp()) return; + if(!opponentKibitzes) { // on first kibitz of game, clear memos + DoClearMemo(1); + if(gameMode == IcsObserving) DoClearMemo(0); + } + opponentKibitzes = TRUE; // this causes split window DisplayMode in ICS modes. + VerifyDisplayMode(); + if(gameMode == IcsObserving) { + DoSetWindowText(0, nLabel, gameInfo.white); + SetIcon( 0, nColorIcon, nColorWhite); + SetIcon( 0, nStateIcon, nClear); + } + DoSetWindowText(1, nLabel, gameMode == IcsPlayingBlack ? gameInfo.white : gameInfo.black); // opponent name + SetIcon( 1, nColorIcon, gameMode == IcsPlayingBlack ? nColorWhite : nColorBlack); + SetIcon( 1, nStateIcon, nClear); + InsertIntoMemo(window-1, text); }