}\r
\r
// front end. Actual printing of PV lines into the output field\r
-static void InsertIntoMemo( int which, char * text )\r
+static void InsertIntoMemo( int which, char * text, int where )\r
{\r
- SendMessage( outputField[which][nMemo], EM_SETSEL, 0, 0 );\r
+ SendMessage( outputField[which][nMemo], EM_SETSEL, where, where ); // [HGM] multivar: choose insertion point\r
\r
SendMessage( outputField[which][nMemo], EM_REPLACESEL, (WPARAM) FALSE, (LPARAM) text );\r
}\r
\r
//------------------------ pure back-end routines -------------------------------\r
\r
+#define MAX_VAR 400\r
+static int scores[MAX_VAR], textEnd[MAX_VAR], curDepth[2], nrVariations[2];\r
\r
// back end, due to front-end wrapper for SetWindowText, and new SetIcon arguments\r
static void SetEngineState( int which, int state, char * state_data )\r
clearMemo = TRUE;\r
}\r
\r
- if( clearMemo ) DoClearMemo(which);\r
+ if( clearMemo ) { DoClearMemo(which); nrVariations[which] = 0; }\r
\r
/* Update */\r
lastDepth[which] = depth == 1 && ed.nodes == 0 ? 0 : depth; // [HGM] info-line kudge\r
\r
#define MAX_NAME_LENGTH 32\r
\r
+// [HGM] multivar: sort Thinking Output within one depth on score\r
+\r
+static int InsertionPoint( int len, EngineOutputData * ed )\r
+{\r
+ int i, offs = 0, newScore = ed->score, n = ed->which;\r
+\r
+ if(ed->nodes == 0 && ed->score == 0 && ed->time == 0)\r
+ newScore = 1e6; // info lines inserted on top\r
+ if(ed->depth != curDepth[n]) { // depth has changed\r
+ curDepth[n] = ed->depth;\r
+ nrVariations[n] = 0; // throw away everything we had\r
+ }\r
+ // loop through all lines. Note even / odd used for different panes\r
+ for(i=nrVariations[n]-2; i>=0; i-=2) {\r
+ // put new item behind those we haven't looked at\r
+ offs = textEnd[i+n];\r
+ textEnd[i+n+2] = offs + len;\r
+ scores[i+n+2] = newScore;\r
+ if(newScore < scores[i+n]) break;\r
+ // if it had higher score as previous, move previous in stead\r
+ scores[i+n+2] = scores[i+n];\r
+ textEnd[i+n+2] = textEnd[i+n] + len;\r
+ }\r
+ if(i<0) {\r
+ offs = 0;\r
+ textEnd[n] = offs + len;\r
+ scores[n] = newScore;\r
+ }\r
+ nrVariations[n] += 2;\r
+ return offs;\r
+}\r
+\r
// pure back end, now SetWindowText is called via wrapper DoSetWindowText\r
static void UpdateControls( EngineOutputData * ed )\r
{\r
strcat( buf + buflen, "\r\n" );\r
\r
/* Update memo */\r
- InsertIntoMemo( ed->which, buf );\r
+ InsertIntoMemo( ed->which, buf, InsertionPoint(strlen(buf), ed) );\r
}\r
\r
/* Colors */\r
DoSetWindowText(1, nLabel, gameMode == IcsPlayingBlack ? gameInfo.white : gameInfo.black); // opponent name\r
SetIcon( 1, nColorIcon, gameMode == IcsPlayingBlack ? nColorWhite : nColorBlack);\r
SetIcon( 1, nStateIcon, nClear);\r
- InsertIntoMemo(window-1, text);\r
+ InsertIntoMemo(window-1, text, 0); // [HGM] multivar: always at top\r
}\r
XtSetValues(outputField[which][field], &arg, 1);
}
-static void InsertIntoMemo( int which, char * text )
+static void InsertIntoMemo( int which, char * text, int where )
{
Arg arg; XawTextBlock t; Widget edit;
t.ptr = text; t.firstPos = 0; t.length = strlen(text); t.format = XawFmt8Bit;
edit = XtNameToWidget(engineOutputShell, which ? "*form2.text" : "*form.text");
- XawTextReplace(edit, 0, 0, &t);
+ XawTextReplace(edit, where, where, &t);
// XtSetArg(arg, XtNstring, (XtArgVal) text);
// XtSetValues(outputField[which][nMemo], &arg, 1);
}
//------------------------ pure back-end routines -------------------------------
+#define MAX_VAR 400
+static int scores[MAX_VAR], textEnd[MAX_VAR], curDepth[2], nrVariations[2];
+
// back end, due to front-end wrapper for SetWindowText, and new SetIcon arguments
static void SetEngineState( int which, int state, char * state_data )
{
#define MAX_NAME_LENGTH 32
+// [HGM] multivar: sort Thinking Output within one depth on score
+
+static int InsertionPoint( int len, EngineOutputData * ed )
+{
+ int i, offs = 0, newScore = ed->score, n = ed->which;
+
+ if(ed->nodes == 0 && ed->score == 0 && ed->time == 0)
+ newScore = 1e6; // info lines inserted on top
+ if(ed->depth != curDepth[n]) { // depth has changed
+ curDepth[n] = ed->depth;
+ nrVariations[n] = 0; // throw away everything we had
+ }
+ // loop through all lines. Note even / odd used for different panes
+ for(i=nrVariations[n]-2; i>=0; i-=2) {
+ // put new item behind those we haven't looked at
+ offs = textEnd[i+n];
+ textEnd[i+n+2] = offs + len;
+ scores[i+n+2] = newScore;
+ if(newScore < scores[i+n]) break;
+ // if it had higher score as previous, move previous in stead
+ scores[i+n+2] = scores[i+n];
+ textEnd[i+n+2] = textEnd[i+n] + len;
+ }
+ if(i<0) {
+ offs = 0;
+ textEnd[n] = offs + len;
+ scores[n] = newScore;
+ }
+ nrVariations[n] += 2;
+ return offs;
+}
+
// pure back end, now SetWindowText is called via wrapper DoSetWindowText
static void UpdateControls( EngineOutputData * ed )
{
strcat( buf + buflen, "\n" );
/* Update memo */
- InsertIntoMemo( ed->which, buf );
+ InsertIntoMemo( ed->which, buf, InsertionPoint(strlen(buf), ed) );
}
/* Colors */
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);
+ InsertIntoMemo(window-1, text, 0);
}