fixed build on openbsd
[xboard.git] / backend.c
index 8cf3a43..11d447d 100755 (executable)
--- a/backend.c
+++ b/backend.c
@@ -461,7 +461,7 @@ char *savedDetails[MAX_VARIATIONS];
 ChessMove savedResult[MAX_VARIATIONS];
 
 void PushTail P((int firstMove, int lastMove));
-Boolean PopTail P((void));
+Boolean PopTail P((Boolean annotate));
 void CleanupTail P((void));
 
 ChessSquare  FIDEArray[2][BOARD_FILES] = {
@@ -5314,7 +5314,7 @@ UserMoveTest(fromX, fromY, toX, toY, promoChar, captureOwn)
             return ImpossibleMove;
        }
     }
-if(appData.debugMode) fprintf(debugFP, "moveType 3 = %d, promochar = %x\n", moveType, promoChar);
+
     return moveType;
     /* [HGM] <popupFix> in stead of calling FinishMove directly, this
        function is made into one that returns an OK move type if FinishMove
@@ -5333,7 +5333,7 @@ FinishMove(moveType, fromX, fromY, toX, toY, promoChar)
      /*char*/int promoChar;
 {
     char *bookHit = 0;
-if(appData.debugMode) fprintf(debugFP, "moveType 5 = %d, promochar = %x\n", moveType, promoChar);
+
     if((gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat) && promoChar != NULLCHAR) { 
        // [HGM] superchess: suppress promotions to non-available piece
        int k = PieceToNumber(CharToPiece(ToUpper(promoChar)));
@@ -5348,13 +5348,12 @@ if(appData.debugMode) fprintf(debugFP, "moveType 5 = %d, promochar = %x\n", move
        move type in caller when we know the move is a legal promotion */
     if(moveType == NormalMove && promoChar)
         moveType = PromoCharToMoveType(WhiteOnMove(currentMove), promoChar);
-if(appData.debugMode) fprintf(debugFP, "moveType 1 = %d, promochar = %x\n", moveType, promoChar);
+
     /* [HGM] convert drag-and-drop piece drops to standard form */
     if( fromX == BOARD_LEFT-2 || fromX == BOARD_RGHT+1) {
          moveType = WhiteOnMove(currentMove) ? WhiteDrop : BlackDrop;
           if(appData.debugMode) fprintf(debugFP, "Drop move %d, curr=%d, x=%d,y=%d, p=%d\n", 
                moveType, currentMove, fromX, fromY, boards[currentMove][fromY][fromX]);
-//         fromX = boards[currentMove][fromY][fromX];
           // holdings might not be sent yet in ICS play; we have to figure out which piece belongs here
           if(fromX == 0) fromY = BOARD_HEIGHT-1 - fromY; // black holdings upside-down
           fromX = fromX ? WhitePawn : BlackPawn; // first piece type in selected holdings
@@ -5363,7 +5362,7 @@ if(appData.debugMode) fprintf(debugFP, "moveType 1 = %d, promochar = %x\n", move
     }
 
     /* [HGM] <popupFix> The following if has been moved here from
-       UserMoveEvent(). Because it seemed to belon here (why not allow
+       UserMoveEvent(). Because it seemed to belong here (why not allow
        piece drops in training games?), and because it can only be
        performed after it is known to what we promote. */
     if (gameMode == Training) {
@@ -5438,7 +5437,7 @@ if(appData.debugMode) fprintf(debugFP, "moveType 1 = %d, promochar = %x\n", move
     }
     ModeHighlight();
   }
-if(appData.debugMode) fprintf(debugFP, "moveType 2 = %d, promochar = %x\n", moveType, promoChar);
+
   /* Relay move to ICS or chess engine */
   if (appData.icsActive) {
     if (gameMode == IcsPlayingWhite || gameMode == IcsPlayingBlack ||
@@ -9863,7 +9862,7 @@ SaveGamePGN(f)
        /* Print comments preceding this move */
        if (commentList[i] != NULL) {
            if (linelen > 0) fprintf(f, "\n");
-           fprintf(f, "%s\n", commentList[i]);
+           fprintf(f, "%s", commentList[i]);
            linelen = 0;
            newblock = TRUE;
        }
@@ -9916,17 +9915,9 @@ SaveGamePGN(f)
         /* [AS] Add PV info if present */
         if( i >= 0 && appData.saveExtendedInfoInPGN && pvInfoList[i].depth > 0 ) {
             /* [HGM] add time */
-            char buf[MSG_SIZ]; int seconds = 0;
+            char buf[MSG_SIZ]; int seconds;
 
-            if(i >= backwardMostMove) {
-               if(WhiteOnMove(i))
-                       seconds = timeRemaining[0][i] - timeRemaining[0][i+1]
-                                 + GetTimeQuota(i/2) / (1000*WhitePlayer()->timeOdds);
-               else
-                       seconds = timeRemaining[1][i] - timeRemaining[1][i+1]
-                                  + GetTimeQuota(i/2) / (1000*WhitePlayer()->other->timeOdds);
-            }
-            seconds = (seconds+50)/100; // deci-seconds, rounded to nearest
+            seconds = (pvInfoList[i].time+5)/10; // deci-seconds, rounded to nearest
 
             if( seconds <= 0) buf[0] = 0; else
             if( seconds < 30 ) sprintf(buf, " %3.1f%c", seconds/10., 0); else {
@@ -10096,6 +10087,7 @@ SavePosition(f, dummy, dummy2)
     time_t tm;
     char *fen;
     
+    if (gameMode == EditPosition) EditPositionDone(TRUE);
     if (appData.oldSaveStyle) {
        tm = time((time_t *) NULL);
     
@@ -11797,7 +11789,7 @@ void
 ToStartEvent()
 {
     if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
-       /* to optimze, we temporarily turn off analysis mode while we undo
+       /* to optimize, we temporarily turn off analysis mode while we undo
         * all the moves. Otherwise we get analysis output after each undo.
         */ 
         if (first.analysisSupport) {
@@ -11838,7 +11830,7 @@ ToNrEvent(int to)
 void
 RevertEvent()
 {
-    if(PopTail()) { // [HGM] vari: restore old game tail
+    if(PopTail(TRUE)) { // [HGM] vari: restore old game tail
        return;
     }
     if (gameMode != IcsExamining) {
@@ -12101,6 +12093,14 @@ SetGameInfo()
 {
     /* This routine is used only for certain modes */
     VariantClass v = gameInfo.variant;
+    ChessMove r = GameUnfinished;
+    char *p = NULL;
+
+    if(gameMode == EditGame) { // [HGM] vari: do not erase result on EditGame
+       r = gameInfo.result; 
+       p = gameInfo.resultDetails; 
+       gameInfo.resultDetails = NULL;
+    }
     ClearGameInfo(&gameInfo);
     gameInfo.variant = v;
 
@@ -12153,6 +12153,8 @@ SetGameInfo()
        gameInfo.round = StrSave("-");
        gameInfo.white = StrSave("-");
        gameInfo.black = StrSave("-");
+       gameInfo.result = r;
+       gameInfo.resultDetails = p;
        break;
 
       case EditPosition:
@@ -12202,7 +12204,9 @@ ReplaceComment(index, text)
        commentList[index] = NULL;
        return;
     }
-  if(*text == '{' || *text == '(' || *text == '[') {
+  if( *text == '{' && strchr(text, '}') || // [HGM] braces: if certainy malformed, put braces
+      *text == '[' && strchr(text, ']') || // otherwise hope the user knows what he is doing
+      *text == '(' && strchr(text, ')')) { // (perhaps check if this parses as comment-only?)
     commentList[index] = (char *) malloc(len + 2);
     strncpy(commentList[index], text, len);
     commentList[index][len] = '\n';
@@ -12212,9 +12216,10 @@ ReplaceComment(index, text)
     char *p;
     commentList[index] = (char *) malloc(len + 6);
     strcpy(commentList[index], "{\n");
-    strcat(commentList[index], text);
+    strncpy(commentList[index]+2, text, len);
+    commentList[index][len+2] = NULLCHAR;
     while(p = strchr(commentList[index], '}')) *p = ')'; // kill all } to make it one comment
-    strcat(commentList[index], "\n}");
+    strcat(commentList[index], "\n}\n");
   }
 }
 
@@ -12255,25 +12260,30 @@ if(appData.debugMode) fprintf(debugFP, "Append: in='%s' %d\n", text, addBraces);
     if (commentList[index] != NULL) {
        old = commentList[index];
        oldlen = strlen(old);
-       commentList[index] = (char *) malloc(oldlen + len + 4); // might waste 2
+       while(commentList[index][oldlen-1] ==  '\n')
+         commentList[index][--oldlen] = NULLCHAR;
+       commentList[index] = (char *) malloc(oldlen + len + 6); // might waste 4
        strcpy(commentList[index], old);
        free(old);
-       // [HGM] braces: join "{A\n}" + "{B}" as "{A\nB\n}"
+       // [HGM] braces: join "{A\n}\n" + "{\nB}" as "{A\nB\n}"
        if(commentList[index][oldlen-1] == '}' && (text[0] == '{' || addBraces)) {
          if(addBraces) addBraces = FALSE; else { text++; len--; }
          while (*text == '\n') { text++; len--; }
-         commentList[index][oldlen-1] = NULLCHAR;
-         oldlen--;
+         commentList[index][--oldlen] = NULLCHAR;
       }
-       strncpy(&commentList[index][oldlen], text, len);
-       if(addBraces) strcpy(&commentList[index][oldlen + len], "\n}");
-       else          strcpy(&commentList[index][oldlen + len], "\n");
+       if(addBraces) strcat(commentList[index], "\n{\n");
+       else          strcat(commentList[index], "\n");
+       strcat(commentList[index], text);
+       if(addBraces) strcat(commentList[index], "\n}\n");
+       else          strcat(commentList[index], "\n");
     } else {
-       commentList[index] = (char *) malloc(len + 4); // perhaps wastes 2...
-       if(addBraces) commentList[index][0] = '{';
-       strcpy(commentList[index] + addBraces, text);
+       commentList[index] = (char *) malloc(len + 6); // perhaps wastes 4...
+       if(addBraces)
+            strcpy(commentList[index], "{\n");
+       else commentList[index][0] = NULLCHAR;
+       strcat(commentList[index], text);
        strcat(commentList[index], "\n");
-       if(addBraces) strcat(commentList[index], "}");
+       if(addBraces) strcat(commentList[index], "}\n");
     }
 }
 
@@ -12405,7 +12415,7 @@ SendToProgram(message, cps)
             } else {
                 gameInfo.result = cps->twoMachinesColor[0]=='w' ? BlackWins : WhiteWins;
             }
-            gameInfo.resultDetails = buf;
+            gameInfo.resultDetails = StrSave(buf);
         }
         DisplayFatalError(buf, error, 1);
     }
@@ -12436,7 +12446,7 @@ ReceiveFromProgram(isr, closure, message, count, error)
                 } else {
                     gameInfo.result = cps->twoMachinesColor[0]=='w' ? BlackWins : WhiteWins;
                 }
-                gameInfo.resultDetails = buf;
+                gameInfo.resultDetails = StrSave(buf);
             }
            RemoveInputSource(cps->isr);
            DisplayFatalError(buf, 0, 1);
@@ -14174,10 +14184,11 @@ PushTail(int firstMove, int lastMove)
        if(storedGames == 1) GreyRevert(FALSE);
 }
 
-Boolean 
-PopTail()
+Boolean
+PopTail(Boolean annotate)
 {
        int i, j, nrMoves;
+       char buf[8000], moveBuf[20];
 
        if(appData.icsActive) return FALSE; // only in local mode
        if(!storedGames) return FALSE; // sanity
@@ -14185,6 +14196,19 @@ PopTail()
        storedGames--;
        ToNrEvent(savedFirst[storedGames]); // sets currentMove
        nrMoves = savedLast[storedGames] - currentMove;
+       if(annotate) {
+               int cnt = 10;
+               if(!WhiteOnMove(currentMove)) sprintf(buf, "(%d...", currentMove+2>>1);
+               else strcpy(buf, "(");
+               for(i=currentMove; i<forwardMostMove; i++) {
+                       if(WhiteOnMove(i))
+                            sprintf(moveBuf, " %d. %s", i+2>>1, SavePart(parseList[i]));
+                       else sprintf(moveBuf, " %s", SavePart(parseList[i]));
+                       strcat(buf, moveBuf);
+                       if(!--cnt) { strcat(buf, "\n"); cnt = 10; }
+               }
+               strcat(buf, ")");
+       }
        for(i=1; i<nrMoves; i++) { // copy last variation back
            CopyBoard(boards[currentMove+i], boards[framePtr+i]);
            for(j=0; j<MOVE_LEN; j++)
@@ -14198,6 +14222,7 @@ PopTail()
            commentList[currentMove+i] = commentList[framePtr+i];
            commentList[framePtr+i] = NULL;
        }
+       if(annotate) AppendComment(currentMove+1, buf, FALSE);
        framePtr = savedFramePtr[storedGames];
        gameInfo.result = savedResult[storedGames];
        if(gameInfo.resultDetails != NULL) {