Let repeated right-clicking upgrade placed piece in Edit Position mode
[xboard.git] / backend.c
index b7f36b2..ad19851 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -4907,7 +4907,7 @@ ParseBoard12 (char *string)
                && gameInfo.variant != VariantGrand&& gameInfo.variant != VariantSChess) // inherit info that ICS does not give from previous board
               for(k=0; k<ranks; k++) for(j=BOARD_LEFT; j<BOARD_RGHT; j++) {
                 ChessSquare old, new = boards[moveNum][k][j];
-                  if(fromY == DROP_RANK && k==toY && j==toX) continue; // dropped pieces always stand for themselves
+                  if(new == EmptySquare || fromY == DROP_RANK && k==toY && j==toX) continue; // dropped pieces always stand for themselves
                   old = (k==toY && j==toX) ? boards[moveNum-1][fromY][fromX] : boards[moveNum-1][k][j]; // trace back mover
                   if(old == new) continue;
                   if(old == PROMOTED(new)) boards[moveNum][k][j] = old;// prevent promoted pieces to revert to primordial ones
@@ -4915,7 +4915,7 @@ ParseBoard12 (char *string)
                       if(old < WhiteCannon || old >= BlackPawn && old < BlackCannon)
                            boards[moveNum][k][j] = PROMOTED(old); // choose correct type of Gold in promotion
                       else boards[moveNum][k][j] = old; // preserve type of Gold
-                  } else if((old == WhitePawn || old == BlackPawn) && new != EmptySquare) // Pawn promotions (but not e.p.capture!)
+                  } else if(old == WhitePawn || old == BlackPawn) // Pawn promotions (but not e.p.capture!)
                       boards[moveNum][k][j] = PROMOTED(new); // use non-primordial representation of chosen piece
               }
          } else {
@@ -7581,6 +7581,7 @@ void ReportClick(char *action, int x, int y)
 
 Boolean right; // instructs front-end to use button-1 events as if they were button 3
 Boolean deferChoice;
+int createX = -1, createY = -1; // square where we last created a piece in EditPosition mode
 
 void
 LeftClick (ClickType clickType, int xPix, int yPix)
@@ -7618,13 +7619,16 @@ LeftClick (ClickType clickType, int xPix, int yPix)
        } else if(y == BOARD_HEIGHT-1) { handOffsets &= ~2; DrawPosition(TRUE, boards[currentMove]); return; }
     }
 
-    if(appData.monoMouse && gameMode == EditPosition && fromX < 0 && clickType == Press && boards[currentMove][y][x] == EmptySquare) {
+    if(appData.monoMouse && gameMode == EditPosition && fromX < 0 && clickType == Press && 
+       (boards[currentMove][y][x] == EmptySquare || x == createX && y == createY) ) {
        static int dummy;
        RightClick(clickType, xPix, yPix, &dummy, &dummy);
        right = TRUE;
        return;
     }
 
+    createX = createY = -1;
+
     if(SeekGraphClick(clickType, xPix, yPix, 0)) return;
 
     prevClickTime = lastClickTime; GetTimeMark(&lastClickTime);
@@ -8055,9 +8059,15 @@ RightClick (ClickType action, int x, int y, int *fromX, int *fromY)
        if (xSqr == BOARD_LEFT-1 || xSqr == BOARD_RGHT) return -1;
        if (xSqr < 0 || ySqr < 0) return -1;
        if(appData.pieceMenu) { whichMenu = 0; break; } // edit-position menu
+       if(flipView) xSqr = BOARD_WIDTH - 1 - xSqr; else ySqr = BOARD_HEIGHT - 1 - ySqr;
+       if(xSqr == createX && ySqr == createY && xSqr != BOARD_LEFT-2 && xSqr != BOARD_RGHT+1) {
+           ChessSquare p = boards[currentMove][ySqr][xSqr];
+           do { if(++p == EmptySquare) p = WhitePawn; } while(PieceToChar(p) == '.');
+           boards[currentMove][ySqr][xSqr] = p; DrawPosition(FALSE, boards[currentMove]);
+           return -2;
+        }
        pieceSweep = shiftKey ? BlackPawn : WhitePawn;  // [HGM] sweep: prepare selecting piece by mouse sweep
-       toX = xSqr; toY = ySqr; lastX = x, lastY = y;
-       if(flipView) toX = BOARD_WIDTH - 1 - toX; else toY = BOARD_HEIGHT - 1 - toY;
+       createX = toX = xSqr; createY = toY = ySqr; lastX = x, lastY = y;
        NextPiece(0);
        return 2; // grab
       case IcsObserving:
@@ -11449,6 +11459,7 @@ RecentEngineEvent (int nr)
     if(mnemonic[n]) { // if somehow the engine with the selected nickname is no longer found in the list, we skip
        ReplaceEngine(&first, 0);
        FloatToFront(&appData.recentEngineList, command[n]);
+       ASSIGN(currentEngine[0], command[n]);
     }
 }
 
@@ -14784,18 +14795,25 @@ EditTagsEvent ()
 }
 
 void
-ToggleSecond ()
+StartSecond ()
 {
-  if(second.analyzing) {
-    SendToProgram("exit\n", &second);
-    second.analyzing = FALSE;
-  } else {
-    if (second.pr == NoProc) StartChessProgram(&second);
+    if(WaitForEngine(&second, StartSecond)) return;
     InitChessProgram(&second, FALSE);
     FeedMovesToProgram(&second, currentMove);
 
     SendToProgram("analyze\n", &second);
     second.analyzing = TRUE;
+    ThawUI();
+}
+
+void
+ToggleSecond ()
+{
+  if(second.analyzing) {
+    SendToProgram("exit\n", &second);
+    second.analyzing = FALSE;
+  } else {
+    StartSecond();
   }
 }
 
@@ -17362,6 +17380,8 @@ ParseOption (Option *opt, ChessProgramState *cps)
            opt->type = SaveButton;
        } else return FALSE;
        *p = 0; // terminate option name
+       *(int*) (opt->name + MSG_SIZ - 104) = opt->value; // hide default values somewhere
+       if(opt->target == &opt->textValue) strncpy(opt->name + MSG_SIZ - 100, opt->textValue, 99);
        // now look if the command-line options define a setting for this engine option.
        if(cps->optionSettings && cps->optionSettings[0])
            p = strstr(cps->optionSettings, opt->name); else p = NULL;
@@ -17374,6 +17394,8 @@ ParseOption (Option *opt, ChessProgramState *cps)
                            if(!strcmp(((char**)opt->textValue)[n], q+1)) opt->value = n;
                        break;
                    case TextBox:
+                   case FileName:
+                   case PathName:
                        safeStrCpy(opt->textValue, q+1, MSG_SIZ - (opt->textValue - opt->name));
                        break;
                    case Spin:
@@ -17385,8 +17407,6 @@ ParseOption (Option *opt, ChessProgramState *cps)
                strcat(buf, "\n");
                SendToProgram(buf, cps);
        }
-       *(int*) (opt->name + MSG_SIZ - 104) = opt->value; // hide default values somewhere
-       if(opt->target == &opt->textValue) strncpy(opt->name + MSG_SIZ - 100, opt->textValue, 99);
        return TRUE;
 }
 
@@ -17396,7 +17416,7 @@ FeatureDone (ChessProgramState *cps, int val)
   DelayedEventCallback cb = GetDelayedEvent();
   if ((cb == InitBackEnd3 && cps == &first) ||
       (cb == SettingsMenuIfReady && cps == &second) ||
-      (cb == LoadEngine) ||
+      (cb == LoadEngine) || (cb == StartSecond) ||
       (cb == TwoMachinesEventIfReady)) {
     CancelDelayedEvent();
     ScheduleDelayedEvent(cb, val ? 1 : 3600000);