Install engines as ./exefile in XBoard
[xboard.git] / backend.c
index 3cd2f0c..b1d35a9 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -920,6 +920,7 @@ Load (ChessProgramState *cps, int i)
        p[-1] = 0;
        appData.directory[i] = strdup(engineName);
        p[-1] = SLASH;
+       if(SLASH == '/' && p - engineName > 1) *(p -= 2) = '.'; // for XBoard use ./exeName as command after split!
     } else appData.directory[i] = ".";
     if(params[0]) {
        if(strchr(p, ' ') && !strchr(p, '"')) snprintf(buf2, MSG_SIZ, "\"%s\"", p), p = buf2; // quote if it contains spaces
@@ -1485,6 +1486,8 @@ MatchEvent (int mode)
        NextMatchGame();
 }
 
+char *comboLine = NULL; // [HGM] recent: WinBoard's first-engine combobox line
+
 void
 InitBackEnd3 P((void))
 {
@@ -1498,7 +1501,7 @@ InitBackEnd3 P((void))
        free(programVersion);
        programVersion = (char*) malloc(8 + strlen(PACKAGE_STRING) + strlen(first.tidy));
        sprintf(programVersion, "%s + %s", PACKAGE_STRING, first.tidy);
-       FloatToFront(&appData.recentEngineList, appData.firstChessProgram);
+       FloatToFront(&appData.recentEngineList, comboLine ? comboLine : appData.firstChessProgram);
     }
 
     if (appData.icsActive) {
@@ -2614,6 +2617,13 @@ SeekGraphClick (ClickType click, int x, int y, int moving)
 {
     static int lastDown = 0, displayed = 0, lastSecond;
     if(y < 0) return FALSE;
+    if(!(appData.seekGraph && appData.icsActive && loggedOn &&
+       (gameMode == BeginningOfGame || gameMode == IcsIdle))) {
+       if(!seekGraphUp) return FALSE;
+       seekGraphUp = FALSE; // seek graph is up when it shouldn't be: take it down
+       DrawPosition(TRUE, NULL);
+       return TRUE;
+    }
     if(!seekGraphUp) { // initiate cration of seek graph by requesting seek-ad list
        if(click == Release || moving) return FALSE;
        nrOfSeekAds = 0;
@@ -3560,7 +3570,7 @@ read_from_ics (InputSourceRef isr, VOIDSTAR closure, char *data, int count, int
            if (looking_at(buf, &i, "% ") ||
                ((started == STARTED_MOVES || started == STARTED_MOVES_NOHIDE)
                 && looking_at(buf, &i, "}*"))) { char *bookHit = NULL; // [HGM] book
-               if(soughtPending) { // [HGM] seekgraph: on ICC sought-list has no termination line
+               if(soughtPending && nrOfSeekAds) { // [HGM] seekgraph: on ICC sought-list has no termination line
                    soughtPending = FALSE;
                    seekGraphUp = TRUE;
                    DrawSeekGraph();
@@ -4208,6 +4218,7 @@ ParseBoard12 (char *string)
        newGameMode =
          ((relation == RELATION_PLAYING_MYMOVE) == (to_play == 'W')) ?
            IcsPlayingWhite : IcsPlayingBlack;
+       soughtPending =FALSE; // [HGM] seekgraph: solve race condition
        break;
       case RELATION_EXAMINING:
        newGameMode = IcsExamining;
@@ -4507,7 +4518,10 @@ ParseBoard12 (char *string)
         r = boards[moveNum][CASTLING][5] = initialRights[5];
     }
     /* [HGM] e.p. rights. Assume that ICS sends file number here? */
-    boards[moveNum][EP_STATUS] = double_push == -1 ? EP_NONE : double_push + BOARD_LEFT;
+    boards[moveNum][EP_STATUS] = EP_NONE;
+    if(str[0] == 'P') boards[moveNum][EP_STATUS] = EP_PAWN_MOVE;
+    if(strchr(move_str, 'x')) boards[moveNum][EP_STATUS] = EP_CAPTURE;
+    if(double_push !=  -1) boards[moveNum][EP_STATUS] = double_push + BOARD_LEFT;
 
 
     if (ics_getting_history == H_GOT_REQ_HEADER ||
@@ -6824,11 +6838,7 @@ LeftClick (ClickType clickType, int xPix, int yPix)
     char promoChoice = NULLCHAR;
     ChessSquare piece;
 
-    if(appData.seekGraph && appData.icsActive && loggedOn &&
-       (gameMode == BeginningOfGame || gameMode == IcsIdle)) {
-       SeekGraphClick(clickType, xPix, yPix, 0);
-       return;
-    }
+    if(SeekGraphClick(clickType, xPix, yPix, 0)) return;
 
     if (clickType == Press) ErrorPopDown();
 
@@ -6877,6 +6887,12 @@ LeftClick (ClickType clickType, int xPix, int yPix)
               || x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize) )
        return;
 
+    if(gotPremove && x == premoveFromX && y == premoveFromY && clickType == Release) {
+       // could be static click on premove from-square: abort premove
+       gotPremove = 0;
+       ClearPremoveHighlights();
+    }
+
     if(clickType == Press && fromX == x && fromY == y && promoDefaultAltered)
        fromX = fromY = -1; // second click on piece after altering default promo piece treated as first click
 
@@ -8348,7 +8364,7 @@ if(appData.debugMode) fprintf(debugFP, "nodes = %d, %lld\n", (int) programStats.
 
     /*
      * If chess program startup fails, exit with an error message.
-     * Attempts to recover here are futile.
+     * Attempts to recover here are futile. [HGM] Well, we try anyway
      */
     if ((StrStr(message, "unknown host") != NULL)
        || (StrStr(message, "No remote directory") != NULL)
@@ -8362,7 +8378,14 @@ if(appData.debugMode) fprintf(debugFP, "nodes = %d, %lld\n", (int) programStats.
                _(cps->which), cps->program, cps->host, message);
        RemoveInputSource(cps->isr);
        if(appData.icsActive) DisplayFatalError(buf1, 0, 1); else {
-           if(cps == &first) appData.noChessProgram = TRUE;
+           if(cps == &first) {
+               appData.noChessProgram = TRUE;
+               gameMode = MachinePlaysBlack; ModeHighlight(); // kludge to unmark Machine Black menu
+               gameMode = BeginningOfGame; ModeHighlight();
+               SetNCPMode();
+           }
+           if(GetDelayedEvent()) CancelDelayedEvent(), ThawUI(); // [HGM] cancel remaining loading effort scheduled after feature timeout
+           DisplayMessage("", ""); // erase waiting message
            DisplayError(buf1, 0);
        }
        return;
@@ -13671,6 +13694,7 @@ EditPositionEvent ()
     currentMove = forwardMostMove = backwardMostMove = 0;
     HistorySet(parseList, backwardMostMove, forwardMostMove, currentMove-1);
     DisplayMove(-1);
+    if(!appData.pieceMenu) DisplayMessage("Click clock to clear board", "");
 }
 
 void