fixed compiler warning for file-browser code
[xboard.git] / backend.c
index 206676d..f806abe 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -2755,6 +2755,7 @@ read_from_ics(isr, closure, data, count, error)
                for(p=0; p<MAX_CHAT; p++) {
                    if(channel == atoi(chatPartner[p])) {
                    talker[0] = '['; strcat(talker, "] ");
+                   Colorize(channel == 1 ? ColorChannel1 : ColorChannel, FALSE);
                    chattingPartner = p; break;
                    }
                } else
@@ -2768,18 +2769,19 @@ read_from_ics(isr, closure, data, count, error)
                if(buf[i-3] == 't' || buf[oldi+2] == '>') // shout, c-shout or it; look if there is a 'shouts' chatbox
                for(p=0; p<MAX_CHAT; p++) {
                    if(!strcmp("shouts", chatPartner[p])) {
-                       if(buf[oldi+2] == '>') { talker[0] = '<'; strcat(talker, "> "); }
-                       else if(buf[i-8] == '-') { talker[0] = '('; strcat(talker, ") "); }
-                       else { talker[0] = '['; strcat(talker, "] "); }
+                       if(buf[oldi+2] == '>') { talker[0] = '<'; strcat(talker, "> "); Colorize(ColorShout, FALSE); }
+                       else if(buf[i-8] == '-') { talker[0] = '('; strcat(talker, ") "); Colorize(ColorSShout, FALSE); }
+                       else { talker[0] = '['; strcat(talker, "] "); Colorize(ColorShout, FALSE); }
                        chattingPartner = p; break;
                    }
                }
                if(chattingPartner<0) // if not, look if there is a chatbox for this indivdual
                for(p=0; p<MAX_CHAT; p++) if(!StrCaseCmp(talker+1, chatPartner[p])) {
-                   talker[0] = 0;
+                   talker[0] = 0; Colorize(ColorTell, FALSE);
                    chattingPartner = p; break;
                }
                if(chattingPartner<0) i = oldi; else {
+                   Colorize(curColor, TRUE); // undo the bogus colorations we just made to trigger the souds
                    if(oldi > 0 && buf[oldi-1] == '\n') oldi--;
                    if (oldi > next_out) SendToPlayer(&buf[next_out], oldi - next_out);
                    started = STARTED_COMMENT;
@@ -3645,7 +3647,7 @@ read_from_ics(isr, closure, data, count, error)
                                    gameInfo.white, white_holding,
                                    gameInfo.black, black_holding);
                        }
-
+                       if(!partnerUp) // [HGM] bughouse: when peeking at partner game we already know what he captured...
                         DrawPosition(FALSE, boards[currentMove]);
                        DisplayTitle(str);
                      } else if(appData.bgObserve) { // [HGM] bughouse: holdings of other game => background
@@ -4713,6 +4715,8 @@ AlphaRank(char *move, int n)
     }
 }
 
+char yy_textstr[8000];
+
 /* Parser for moves from gnuchess, ICS, or user typein box */
 Boolean
 ParseOneMove(move, moveNum, moveType, fromX, fromY, toX, toY, promoChar)
@@ -4725,7 +4729,7 @@ ParseOneMove(move, moveNum, moveType, fromX, fromY, toX, toY, promoChar)
     if (appData.debugMode) {
         fprintf(debugFP, "move to parse: %s\n", move);
     }
-    *moveType = yylexstr(moveNum, move);
+    *moveType = yylexstr(moveNum, move, yy_textstr, sizeof yy_textstr);
 
     switch (*moveType) {
       case WhitePromotionChancellor:
@@ -4814,7 +4818,7 @@ ParseOneMove(move, moveNum, moveType, fromX, fromY, toX, toY, promoChar)
 
 
 void
-ParsePV(char *pv)
+ParsePV(char *pv, Boolean storeComments)
 { // Parse a string of PV moves, and append to current game, behind forwardMostMove
   int fromX, fromY, toX, toY; char promoChar;
   ChessMove moveType;
@@ -4823,11 +4827,11 @@ ParsePV(char *pv)
 
   endPV = forwardMostMove;
   do {
-    while(*pv == ' ') pv++;
-    if(*pv == '(') pv++; // first (ponder) move can be in parentheses
+    while(*pv == ' ' || *pv == '\n' || *pv == '\t') pv++; // must still read away whitespace
+    if(nr == 0 && !storeComments && *pv == '(') pv++; // first (ponder) move can be in parentheses
     valid = ParseOneMove(pv, endPV, &moveType, &fromX, &fromY, &toX, &toY, &promoChar);
 if(appData.debugMode){
-fprintf(debugFP,"parsePV: %d %c%c%c%c '%s'\n", valid, fromX+AAA, fromY+ONE, toX+AAA, toY+ONE, pv);
+fprintf(debugFP,"parsePV: %d %c%c%c%c yy='%s'\nPV = '%s'\n", valid, fromX+AAA, fromY+ONE, toX+AAA, toY+ONE, yy_textstr, pv);
 }
     if(!valid && nr == 0 &&
        ParseOneMove(pv, endPV-1, &moveType, &fromX, &fromY, &toX, &toY, &promoChar)){ 
@@ -4846,9 +4850,13 @@ fprintf(debugFP,"parsePV: %d %c%c%c%c '%s'\n", valid, fromX+AAA, fromY+ONE, toX+
           strcpy(moveList[endPV-2], "_0_0"); // suppress premove highlight on takeback move
         }
       }
+    pv = strstr(pv, yy_textstr) + strlen(yy_textstr); // skip what we parsed
+    if(nr == 0 && !storeComments && *pv == ')') pv++; // closing parenthesis of ponder move;
+    if(moveType == Comment && storeComments) AppendComment(endPV, yy_textstr, FALSE);
+    if(moveType == Comment || moveType == NAG || moveType == ElapsedTime) {
+       valid++; // allow comments in PV
+       continue;
     }
-    while(*pv && *pv++ != ' '); // skip what we parsed; assume space separators
-    if(moveType == Comment) { valid++; continue; } // allow comments in PV
     nr++;
     if(endPV+1 > framePtr) break; // no space, truncate
     if(!valid) break;
@@ -4859,7 +4867,13 @@ fprintf(debugFP,"parsePV: %d %c%c%c%c '%s'\n", valid, fromX+AAA, fromY+ONE, toX+
     moveList[endPV-1][1] = fromY + ONE;
     moveList[endPV-1][2] = toX + AAA;
     moveList[endPV-1][3] = toY + ONE;
-    parseList[endPV-1][0] = NULLCHAR;
+    if(storeComments)
+       CoordsToAlgebraic(boards[endPV - 1],
+                            PosFlags(endPV - 1),
+                            fromY, fromX, toY, toX, promoChar,
+                            parseList[endPV - 1]);
+    else
+       parseList[endPV-1][0] = NULLCHAR;
   } while(valid);
   currentMove = endPV;
   if(currentMove == forwardMostMove) ClearPremoveHighlights(); else
@@ -4874,16 +4888,19 @@ Boolean
 LoadMultiPV(int x, int y, char *buf, int index, int *start, int *end)
 {
        int startPV;
+       char *p;
 
        if(index < 0 || index >= strlen(buf)) return FALSE; // sanity
        lastX = x; lastY = y;
        while(index > 0 && buf[index-1] != '\n') index--; // beginning of line
        startPV = index;
-      while(buf[index] != '\n') if(buf[index++] == '\t') startPV = index;
-      index = startPV;
-       while(buf[index] && buf[index] != '\n') index++;
+       while(buf[index] != '\n') if(buf[index++] == '\t') startPV = index;
+       if(index == startPV && (p = StrCaseStr(buf+index, "PV="))) startPV = p - buf + 3;
+       index = startPV;
+       do{ while(buf[index] && buf[index] != '\n') index++;
+       } while(buf[index] == '\n' && buf[index+1] == '\\' && buf[index+2] == ' ' && index++); // join kibitzed PV continuation line
        buf[index] = 0;
-       ParsePV(buf+startPV);
+       ParsePV(buf+startPV, FALSE);
        *start = startPV; *end = index-1;
        return TRUE;
 }
@@ -4893,7 +4910,7 @@ LoadPV(int x, int y)
 { // called on right mouse click to load PV
   int which = gameMode == TwoMachinesPlay && (WhiteOnMove(forwardMostMove) == (second.twoMachinesColor[0] == 'w'));
   lastX = x; lastY = y;
-  ParsePV(lastPV[which]); // load the PV of the thinking engine in the boards array.
+  ParsePV(lastPV[which], FALSE); // load the PV of the thinking engine in the boards array.
   return TRUE;
 }
 
@@ -12665,9 +12682,9 @@ ToNrEvent(int to)
 }
 
 void
-RevertEvent()
+RevertEvent(Boolean annotate)
 {
-    if(PopTail(TRUE)) { // [HGM] vari: restore old game tail
+    if(PopTail(annotate)) { // [HGM] vari: restore old game tail
        return;
     }
     if (gameMode != IcsExamining) {
@@ -15028,7 +15045,7 @@ PushTail(int firstMove, int lastMove)
        }
 
        storedGames++;
-       forwardMostMove = currentMove; // truncte game so we can start variation
+       forwardMostMove = firstMove; // truncate game so we can start variation
        if(storedGames == 1) GreyRevert(FALSE);
 }
 
@@ -15040,6 +15057,7 @@ PopTail(Boolean annotate)
 
        if(appData.icsActive) return FALSE; // only in local mode
        if(!storedGames) return FALSE; // sanity
+       CommentPopDown(); // make sure no stale variation comments to the destroyed line can remain open
 
        storedGames--;
        ToNrEvent(savedFirst[storedGames]); // sets currentMove
@@ -15053,11 +15071,12 @@ PopTail(Boolean annotate)
                             sprintf(moveBuf, " %d. %s", i+2>>1, SavePart(parseList[i]));
                        else sprintf(moveBuf, " %s", SavePart(parseList[i]));
                        strcat(buf, moveBuf);
+                       if(commentList[i]) { strcat(buf, " "); strcat(buf, commentList[i]); }
                        if(!--cnt) { strcat(buf, "\n"); cnt = 10; }
                }
                strcat(buf, ")");
        }
-       for(i=1; i<nrMoves; i++) { // copy last variation back
+       for(i=1; i<=nrMoves; i++) { // copy last variation back
            CopyBoard(boards[currentMove+i], boards[framePtr+i]);
            for(j=0; j<MOVE_LEN; j++)
                moveList[currentMove+i-1][j] = moveList[framePtr+i][j];
@@ -15098,3 +15117,35 @@ CleanupTail()
        framePtr = MAX_MOVES-1;
        storedGames = 0;
 }
+
+void
+LoadVariation(int index, char *text)
+{       // [HGM] vari: shelve previous line and load new variation, parsed from text around text[index]
+       char *p = text, *start = NULL, *end = NULL, wait = NULLCHAR;
+       int level = 0, move;
+
+       if(gameMode != EditGame && gameMode != AnalyzeMode) return;
+       // first find outermost bracketing variation
+       while(*p) { // hope I got this right... Non-nesting {} and [] can screen each other and nesting ()
+           if(!wait) { // while inside [] pr {}, ignore everyting except matching closing ]}
+               if(*p == '{') wait = '}'; else
+               if(*p == '[') wait = ']'; else
+               if(*p == '(' && level++ == 0 && p-text < index) start = p+1;
+               if(*p == ')' && level > 0 && --level == 0 && p-text > index && end == NULL) end = p-1;
+           }
+           if(*p == wait) wait = NULLCHAR; // closing ]} found
+           p++;
+       }
+       if(!start || !end) return; // no variation found, or syntax error in PGN: ignore click
+       if(appData.debugMode) fprintf(debugFP, "at move %d load variation '%s'\n", currentMove, start);
+       end[1] = NULLCHAR; // clip off comment beyond variation
+       ToNrEvent(currentMove-1);
+       PushTail(currentMove, forwardMostMove); // shelve main variation. This truncates game
+       // kludge: use ParsePV() to append variation to game
+       move = currentMove;
+       ParsePV(start, TRUE);
+       forwardMostMove = endPV; endPV = -1; currentMove = move; // cleanup what ParsePV did
+       ClearPremoveHighlights();
+       CommentPopDown();
+       ToNrEvent(currentMove+1);
+}