#define DoSleep( n ) if( (n) != 0 ) Sleep( (n) );
+int flock(int f, int code);
+#define LOCK_EX 2
+
#else
#define DoSleep( n ) if( (n) >= 0) sleep(n)
extern int chatCount;
int chattingPartner;
char marker[BOARD_RANKS][BOARD_FILES]; /* [HGM] marks for target squares */
+char lastMsg[MSG_SIZ];
ChessSquare pieceSweep = EmptySquare;
ChessSquare promoSweep = EmptySquare, defaultPromoChoice;
int promoDefaultAltered;
{
dst[ count-1 ] = '\0'; // make sure incomplete copy still null-terminated
if(appData.debugMode)
- fprintf(debugFP, "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, (int)count);
}
return dst;
appData.noChessProgram = False;
appData.clockMode = True;
InitEngine(cps, n);
+ if(n) return; // only startup first engine immediately; second can wait
savCps = cps; // parameter to LoadEngine passed as globals, to allow scheduled calling :-(
LoadEngine();
}
DisplayMessage("", "");
if (StrCaseCmp(appData.initialMode, "") == 0) {
initialMode = BeginningOfGame;
+ if(!appData.icsActive && appData.noChessProgram) { // [HGM] could be fall-back
+ gameMode = MachinePlaysBlack; // "Machine Black" might have been implicitly highlighted
+ ModeHighlight(); // make sure XBoard knows it is highlighted, so it will un-highlight it
+ gameMode = BeginningOfGame; // in case BeginningOfGame now means "Edit Position"
+ ModeHighlight();
+ }
} else if (StrCaseCmp(appData.initialMode, "TwoMachines") == 0) {
initialMode = TwoMachinesPlay;
} else if (StrCaseCmp(appData.initialMode, "AnalyzeFile") == 0) {
}
} // [HGM] chat: end of patch
+ backup = i;
if (appData.zippyTalk || appData.zippyPlay) {
/* [DM] Backup address for color zippy lines */
- backup = i;
#if ZIPPY
if (loggedOn == TRUE)
if (ZippyControl(buf, &backup) || ZippyConverse(buf, &backup) ||
continue;
}
+ if(i < backup) { i = backup; continue; } // [HGM] for if ZippyControl matches, but the colorie code doesn't
+
if (looking_at(buf, &i, "\\ ")) {
if (prevColor != ColorNormal) {
if (oldi > next_out) {
snprintf(buf1, sizeof(buf1), _("Failed to start %s chess program %s on %s: %s\n"),
_(cps->which), cps->program, cps->host, message);
RemoveInputSource(cps->isr);
- DisplayFatalError(buf1, 0, 1);
+ if(appData.icsActive) DisplayFatalError(buf1, 0, 1); else {
+ if(cps == &first) appData.noChessProgram = TRUE;
+ DisplayError(buf1, 0);
+ }
return;
}
{
FILE *f;
char buf[MSG_SIZ];
+ int result;
if (strcmp(filename, "-") == 0) {
return SaveGame(stdout, 0, NULL);
DisplayError(buf, errno);
return FALSE;
} else {
- return SaveGame(f, 0, NULL);
+ safeStrCpy(buf, lastMsg, MSG_SIZ);
+ DisplayMessage(_("Waiting for access to save file"), "");
+ flock(fileno(f), LOCK_EX); // [HGM] lock: lock file while we are writing
+ DisplayMessage(_("Saving game"), "");
+ if(lseek(fileno(f), 0, SEEK_END) == -1) DisplayError("Bad Seek", errno); // better safe than sorry...
+ result = SaveGame(f, 0, NULL);
+ DisplayMessage(buf, "");
+ return result;
}
}
}
DisplayError(buf, errno);
return FALSE;
} else {
+ safeStrCpy(buf, lastMsg, MSG_SIZ);
+ DisplayMessage(_("Waiting for access to save file"), "");
+ flock(fileno(f), LOCK_EX); // [HGM] lock
+ DisplayMessage(_("Saving position"), "");
+ lseek(fileno(f), 0, SEEK_END); // better safe than sorry...
SavePosition(f, 0, NULL);
+ DisplayMessage(buf, "");
return TRUE;
}
}
outCount = OutputToProcess(cps->pr, message, count, &error);
if (outCount < count && !exiting
&& !endingGame) { /* [HGM] crash: to not hang GameEnds() writing to deceased engines */
+ if(!cps->initDone) return; // [HGM] should not generate fatal error during engine load
snprintf(buf, MSG_SIZ, _("Error writing to %s chess program"), _(cps->which));
if(gameInfo.resultDetails==NULL) { /* [HGM] crash: if game in progress, give reason for abort */
if((signed char)boards[forwardMostMove][EP_STATUS] <= EP_DRAWS) {