Revert "adding gnu-readline support"
[xboard.git] / backend.c
index 05f7dfc..4c9390e 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -318,11 +318,11 @@ safeStrCpy( char *dst, const char *src, size_t count )
   assert( count > 0 );
 
   for(i=0; i<count; i++) if((dst[i] = src[i]) == NULLCHAR) break;
-  if(  i == count-1 && dst[i] != NULLCHAR)
+  if(  i == count && dst[count-1] != NULLCHAR)
     {
       dst[ count-1 ] = '\0'; // make sure incomplete copy still null-terminated
       if(appData.debugMode)
-      printf("safeStrCpy: copying %s into %s didn't work, not enough space %d\n",src,dst,count);
+      fprintf(debugFP, "safeStrCpy: copying %s into %s didn't work, not enough space %d\n",src,dst,count);
     }
 
   return dst;
@@ -448,9 +448,6 @@ long lastNodeCount=0;
 int shiftKey; // [HGM] set by mouse handler
 
 int have_sent_ICS_logon = 0;
-int sending_ICS_login    = 0;
-int sending_ICS_password = 0;
-
 int movesPerSession;
 int suddenDeath, whiteStartMove, blackStartMove; /* [HGM] for implementation of 'any per time' sessions, as in first part of byoyomi TC */
 long whiteTimeRemaining, blackTimeRemaining, timeControl, timeIncrement, lastWhite, lastBlack;
@@ -522,8 +519,8 @@ ChessSquare  KnightmateArray[2][BOARD_FILES] = {
 ChessSquare fairyArray[2][BOARD_FILES] = { /* [HGM] Queen side differs from King side */
     { WhiteRook, WhiteKnight, WhiteBishop, WhiteQueen,
         WhiteKing, WhiteBishop, WhiteKnight, WhiteRook },
-    { BlackLance, BlackAlfil, BlackMarshall, BlackAngel,
-       BlackKing, BlackMarshall, BlackAlfil, BlackLance }
+    { BlackCardinal, BlackAlfil, BlackMarshall, BlackAngel,
+       BlackKing, BlackMarshall, BlackAlfil, BlackCardinal }
 };
 
 ChessSquare ShatranjArray[2][BOARD_FILES] = { /* [HGM] (movGen knows about Shatranj Q and P) */
@@ -1089,16 +1086,16 @@ ParseTimeControl(tc, ti, mps)
 
     if(mps)
       snprintf(buf, MSG_SIZ, ":%d/%s+%g", mps, mytc, ti);
-    else
+    else 
       snprintf(buf, MSG_SIZ, ":%s+%g", mytc, ti);
   } else {
     if(mps)
       snprintf(buf, MSG_SIZ, ":%d/%s", mps, mytc);
-    else
+    else 
       snprintf(buf, MSG_SIZ, ":%s", mytc);
   }
   fullTimeControlString = StrSave(buf); // this should now be in PGN format
-
+  
   if( NextTimeControlFromString( &tc, &tc1 ) != 0 ) {
     return FALSE;
   }
@@ -3116,23 +3113,8 @@ read_from_ics(isr, closure, data, count, error)
            if (!have_sent_ICS_logon && looking_at(buf, &i, "login:")) {
                ICSInitScript();
                have_sent_ICS_logon = 1;
-               /* if we don't send the login/password via icsLogon, use special readline
-                  code for it */
-               if (strlen(appData.icsLogon)==0)
-                 {
-                   sending_ICS_password = 0; // in case we come back to login
-                   sending_ICS_login = 1;
-                 };
                continue;
            }
-           /* need to shadow the password */
-           if (!sending_ICS_password && looking_at(buf, &i, "password:")) {
-             /* if we don't send the login/password via icsLogon, use special readline
-                code for it */
-             if (strlen(appData.icsLogon)==0)
-               sending_ICS_password = 1;
-             continue;
-           }
 
            if (ics_getting_history != H_GETTING_MOVES /*smpos kludge*/ &&
                (looking_at(buf, &i, "\n<12> ") ||
@@ -3855,7 +3837,7 @@ ParseBoard12(string)
     int j, k, n, moveNum, white_stren, black_stren, white_time, black_time, takeback;
     int double_push, castle_ws, castle_wl, castle_bs, castle_bl, irrev_count;
     char to_play, board_chars[200];
-    char move_str[500], str[500], elapsed_time[500];
+    char move_str[MSG_SIZ], str[MSG_SIZ], elapsed_time[MSG_SIZ];
     char black[32], white[32];
     Board board;
     int prevMove = currentMove;
@@ -3896,7 +3878,7 @@ ParseBoard12(string)
               &ticking);
 
     if (n < 21) {
-        snprintf(str, sizeof(str), _("Failed to parse board string:\n\"%s\""), string);
+        snprintf(str, MSG_SIZ, _("Failed to parse board string:\n\"%s\""), string);
        DisplayError(str, 0);
        return;
     }
@@ -4345,7 +4327,7 @@ ParseBoard12(string)
          if(!appData.testLegality && move_str[1] != '@') { // drops never ambiguous (parser chokes on long form!)
                if(appData.debugMode)
                        fprintf(debugFP, "replaced ICS move '%s' by '%s'\n", move_str, buf);
-               safeStrCpy(move_str, buf, sizeof(move_str)/sizeof(move_str[0]));
+               safeStrCpy(move_str, buf, MSG_SIZ);
           }
          valid = ParseOneMove(move_str, moveNum - 1, &moveType,
                                &fromX, &fromY, &toX, &toY, &promoChar)
@@ -6082,15 +6064,15 @@ UserMoveEvent(fromX, fromY, toX, toY, promoChar)
     pup = boards[currentMove][toY][toX];
 
     /* [HGM] If move started in holdings, it means a drop. Convert to standard form */
-    if( fromX == BOARD_LEFT-2 || fromX == BOARD_RGHT+1) {
+    if( fromX == BOARD_LEFT-2 || fromX == BOARD_RGHT+1) { 
          if( pup != EmptySquare ) return;
          moveType = WhiteOnMove(currentMove) ? WhiteDrop : BlackDrop;
-          if(appData.debugMode) fprintf(debugFP, "Drop move %d, curr=%d, x=%d,y=%d, p=%d\n",
+          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]);
           // 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
-          while(PieceToChar(fromX) == '.' || PieceToNumber(fromX) != fromY && fromX != (int) EmptySquare) fromX++;
+          while(PieceToChar(fromX) == '.' || PieceToNumber(fromX) != fromY && fromX != (int) EmptySquare) fromX++; 
          fromY = DROP_RANK;
     }
 
@@ -6340,6 +6322,8 @@ Explode(Board board, int fromX, int fromY, int toX, int toY)
     return FALSE;
 }
 
+ChessSquare gatingPiece = EmptySquare; // exported to front-end, for dragging
+
 void LeftClick(ClickType clickType, int xPix, int yPix)
 {
     int x, y;
@@ -6396,8 +6380,15 @@ void LeftClick(ClickType clickType, int xPix, int yPix)
     autoQueen = appData.alwaysPromoteToQueen;
 
     if (fromX == -1) {
+      gatingPiece = EmptySquare;
+      if (clickType != Press) {
+       if(dragging) { // [HGM] from-square must have been reset due to game end since last press
+           DragPieceEnd(xPix, yPix); dragging = 0;
+           DrawPosition(FALSE, NULL);
+       }
+       return;
+      }
       if(!appData.oneClick || !OnlyMove(&x, &y, FALSE)) {
-       if (clickType == Press) {
            /* First square */
            if (OKToStartUserMove(x, y)) {
                fromX = x;
@@ -6409,12 +6400,8 @@ void LeftClick(ClickType clickType, int xPix, int yPix)
                    SetHighlights(x, y, -1, -1);
                }
            }
-       } else if(dragging) { // [HGM] from-square must have been reset due to game end since last press
-           DragPieceEnd(xPix, yPix); dragging = 0;
-           DrawPosition(FALSE, NULL);
+           return;
        }
-       return;
-      }
     }
 
     /* fromX != -1 */
@@ -6429,7 +6416,7 @@ void LeftClick(ClickType clickType, int xPix, int yPix)
        /* Check if clicking again on the same color piece */
        fromP = boards[currentMove][fromY][fromX];
        toP = boards[currentMove][y][x];
-       frc = gameInfo.variant == VariantFischeRandom || gameInfo.variant == VariantCapaRandom;
+       frc = gameInfo.variant == VariantFischeRandom || gameInfo.variant == VariantCapaRandom || gameInfo.variant == VariantSChess;
        if ((WhitePawn <= fromP && fromP <= WhiteKing &&
             WhitePawn <= toP && toP <= WhiteKing &&
             !(fromP == WhiteKing && toP == WhiteRook && frc) &&
@@ -6447,6 +6434,11 @@ void LeftClick(ClickType clickType, int xPix, int yPix)
                ClearHighlights();
            }
            if (OKToStartUserMove(x, y)) {
+               if(gameInfo.variant == VariantSChess && // S-Chess: back-rank piece selected after holdings means gating
+                 (fromX == BOARD_LEFT-2 || fromX == BOARD_RGHT+1) &&
+               y == (toP < BlackPawn ? 0 : BOARD_HEIGHT-1))
+                 gatingPiece = boards[currentMove][fromY][fromX];
+               else gatingPiece = EmptySquare;
                fromX = x;
                fromY = y; dragging = 1;
                MarkTargetSquares(0);
@@ -6470,6 +6462,7 @@ void LeftClick(ClickType clickType, int xPix, int yPix)
            /* Second up/down in same square; just abort move */
            second = 0;
            fromX = fromY = -1;
+           gatingPiece = EmptySquare;
            ClearHighlights();
            gotPremove = 0;
            ClearPremoveHighlights();
@@ -6534,6 +6527,8 @@ void LeftClick(ClickType clickType, int xPix, int yPix)
     // off-board moves should not be highlighted
     if(x < 0 || y < 0) ClearHighlights();
 
+    if(gatingPiece != EmptySquare) promoChoice = ToLower(PieceToChar(gatingPiece));
+
     if (HasPromotionChoice(fromX, fromY, toX, toY, &promoChoice)) {
        SetHighlights(fromX, fromY, toX, toY);
        if(gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat) {
@@ -8406,6 +8401,9 @@ ApplyMove(fromX, fromY, toX, toY, promoChar, board)
   } else {
       int i;
 
+      if( board[fromY][fromX] == WhiteLance || board[fromY][fromX] == BlackLance ) {
+           if( gameInfo.variant == VariantFairy ) board[EP_STATUS] = EP_PAWN_MOVE; // Lance in fairy is Pawn-like
+      } else
       if( board[fromY][fromX] == WhitePawn ) {
            if(fromY != toY) // [HGM] Xiangqi sideway Pawn moves should not count as 50-move breakers
               board[EP_STATUS] = EP_PAWN_MOVE;
@@ -8669,8 +8667,8 @@ ApplyMove(fromX, fromY, toX, toY, promoChar, board)
     } else if(!appData.testLegality && promoChar != NULLCHAR && promoChar != '=') { // without legality testing, unconditionally believe promoChar
         board[toY][toX] = CharToPiece(piece < BlackPawn ? ToUpper(promoChar) : ToLower(promoChar));
     }
-    if((gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat)
-               && promoChar != NULLCHAR && gameInfo.holdingsSize) {
+    if((gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat) 
+               && promoChar != NULLCHAR && gameInfo.holdingsSize) { 
        // [HGM] superchess: take promotion piece out of holdings
        int k = PieceToNumber(CharToPiece(ToUpper(promoChar)));
        if((int)piece < (int)BlackPawn) { // determine stm from piece color
@@ -8895,6 +8893,8 @@ InitChessProgram(cps, setup)
            overruled = gameInfo.boardWidth != 8 || gameInfo.boardHeight != 8 || gameInfo.holdingsSize != 8;
       if( gameInfo.variant == VariantGreat )
            overruled = gameInfo.boardWidth != 10 || gameInfo.boardHeight != 8 || gameInfo.holdingsSize != 8;
+      if( gameInfo.variant == VariantSChess )
+           overruled = gameInfo.boardWidth != 8 || gameInfo.boardHeight != 8 || gameInfo.holdingsSize != 7;
 
       if(overruled) {
        snprintf(b, MSG_SIZ, "%dx%d+%d_%s", gameInfo.boardWidth, gameInfo.boardHeight,
@@ -13358,7 +13358,7 @@ if(appData.debugMode) fprintf(debugFP, "Append: in='%s' %d\n", text, addBraces);
        while(commentList[index][oldlen-1] ==  '\n')
          commentList[index][--oldlen] = NULLCHAR;
        commentList[index] = (char *) malloc(oldlen + len + 6); // might waste 4
-       safeStrCpy(commentList[index], old, oldlen);
+       safeStrCpy(commentList[index], old, oldlen + len + 6);
        free(old);
        // [HGM] braces: join "{A\n}\n" + "{\nB}" as "{A\nB\n}"
        if(commentList[index][oldlen-1] == '}' && (text[0] == '{' || addBraces)) {