X-Git-Url: http://winboard.nl/cgi-bin?p=xboard.git;a=blobdiff_plain;f=xboard.c;h=86fda447f8691c579a12804426b1d32bbe2cc968;hp=1675b790f99eba15a66098730aff6b26546074a7;hb=76d2f540a0bc0a54bbb2aba5e29d5412e7f2191c;hpb=7b4dacf6fe9f8c10b6eb4d6070869a3d933dbeb5 diff --git a/xboard.c b/xboard.c index 1675b79..86fda44 100644 --- a/xboard.c +++ b/xboard.c @@ -2,9 +2,10 @@ * xboard.c -- X front end for XBoard * * Copyright 1991 by Digital Equipment Corporation, Maynard, - * Massachusetts. Enhancements Copyright - * 1992-2001,2002,2003,2004,2005,2006,2007,2008,2009 Free Software - * Foundation, Inc. + * Massachusetts. + * + * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006, + * 2007, 2008, 2009 Free Software Foundation, Inc. * * The following terms apply to Digital Equipment Corporation's copyright * interest in XBoard: @@ -231,6 +232,7 @@ typedef struct { int main P((int argc, char **argv)); RETSIGTYPE CmailSigHandler P((int sig)); RETSIGTYPE IntSigHandler P((int sig)); +RETSIGTYPE TermSizeSigHandler P((int sig)); void CreateGCs P((void)); void CreateXIMPieces P((void)); void CreateXPMPieces P((void)); @@ -445,6 +447,8 @@ void UciPopDown P(()); void TimeControlPopDown P(()); void NewVariantPopDown P(()); void SettingsPopDown P(()); +void update_ics_width P(()); +int get_term_width P(()); /* * XBoard depends on Xt R4 or higher */ @@ -1021,7 +1025,7 @@ XtResource clientResources[] = { { "localLineEditing", "localLineEditing", XtRBoolean, sizeof(Boolean), XtOffset(AppDataPtr, localLineEditing), XtRImmediate, (XtPointer) True }, /* not implemented, must be True */ -#ifdef ZIPPY +#if ZIPPY { "zippyTalk", "zippyTalk", XtRBoolean, sizeof(Boolean), XtOffset(AppDataPtr, zippyTalk), XtRImmediate, (XtPointer) ZIPPY_TALK }, @@ -1228,6 +1232,9 @@ XtResource clientResources[] = { { "adjudicateLossThreshold", "adjudicateLossThreshold", XtRInt, sizeof(int), XtOffset(AppDataPtr, adjudicateLossThreshold), XtRImmediate, (XtPointer) 0}, + { "adjudicateDrawMoves", "adjudicateDrawMoves", XtRInt, + sizeof(int), XtOffset(AppDataPtr, adjudicateDrawMoves), + XtRImmediate, (XtPointer) 0}, { "pgnEventHeader", "pgnEventHeader", XtRString, sizeof(String), XtOffset(AppDataPtr, pgnEventHeader), XtRImmediate, (XtPointer) "Computer Chess Game" }, @@ -1343,7 +1350,7 @@ XtResource clientResources[] = { XtRImmediate, (XtPointer) "xboard.debug"}, { "engineDebugOutput", "engineDebugOutput", XtRInt, sizeof(int), XtOffset(AppDataPtr, engineComments), - XtRImmediate, (XtPointer) 0}, + XtRImmediate, (XtPointer) 1}, { "noGUI", "noGUI", XtRBoolean, sizeof(Boolean), XtOffset(AppDataPtr, noGUI), XtRImmediate, (XtPointer) 0}, @@ -1397,6 +1404,15 @@ XtResource clientResources[] = { { "delayAfterQuit", "delayAfterQuit", XtRInt, sizeof(int), XtOffset(AppDataPtr, delayAfterQuit), XtRImmediate, (XtPointer) 0}, + { "keepAlive", "keepAlive", XtRInt, + sizeof(int), XtOffset(AppDataPtr, keepAlive), + XtRImmediate, (XtPointer) 0}, + { "forceIllegalMoves", "forceIllegalMoves", XtRBoolean, + sizeof(Boolean), XtOffset(AppDataPtr, forceIllegal), + XtRImmediate, (XtPointer) False}, + { "keepLineBreaksICS", "keepLineBreaksICS", XtRBoolean, + sizeof(Boolean), XtOffset(AppDataPtr, noJoin), + XtRImmediate, (XtPointer) True}, }; XrmOptionDescRec shellOptions[] = { @@ -1696,6 +1712,7 @@ XrmOptionDescRec shellOptions[] = { { "-pgnExtendedInfo", "pgnExtendedInfo", XrmoptionSepArg, NULL }, { "-hideThinkingFromHuman", "hideThinkingFromHuman", XrmoptionSepArg, NULL }, { "-adjudicateLossThreshold", "adjudicateLossThreshold", XrmoptionSepArg, NULL }, + { "-adjudicateDrawMoves", "adjudicateDrawMoves", XrmoptionSepArg, NULL }, { "-pgnEventHeader", "pgnEventHeader", XrmoptionSepArg, NULL }, { "-firstIsUCI", "firstIsUCI", XrmoptionSepArg, NULL }, { "-secondIsUCI", "secondIsUCI", XrmoptionSepArg, NULL }, @@ -1763,6 +1780,9 @@ XrmOptionDescRec shellOptions[] = { { "-secondOptions", "secondOptions", XrmoptionSepArg, NULL }, { "-firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XrmoptionSepArg, NULL }, { "-secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XrmoptionSepArg, NULL }, + { "-keepAlive", "keepAlive", XrmoptionSepArg, NULL }, + { "-forceIllegalMoves", "forceIllegalMoves", XrmoptionNoArg, "True" }, + { "-keepLineBreaksICS", "keepLineBreaksICS", XrmoptionSepArg, NULL }, }; @@ -2285,7 +2305,7 @@ void InitDrawingSizes(BoardSize boardSize, int flags) } #ifdef GOTHIC if(gameInfo.variant == VariantGothic) { - ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[i][(int)WhiteSilver]; + ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver]; } #endif #endif @@ -2315,6 +2335,19 @@ void InitDrawingSizes(BoardSize boardSize, int flags) } #endif +void EscapeExpand(char *p, char *q) +{ // [HGM] initstring: routine to shape up string arguments + while(*p++ = *q++) if(p[-1] == '\\') + switch(*q++) { + case 'n': p[-1] = '\n'; break; + case 'r': p[-1] = '\r'; break; + case 't': p[-1] = '\t'; break; + case '\\': p[-1] = '\\'; break; + case 0: *p = 0; return; + default: p[-1] = q[-1]; break; + } +} + int main(argc, argv) int argc; @@ -2366,13 +2399,7 @@ main(argc, argv) argvCopy[j] = NULL; argv = argvCopy; argc = j; -#if 0 - if(appData.debugMode,1) { // OK, appData is not initialized here yet... - for(i=0; i 1) { + if (argc > 1) + { /* left over command line arguments, print out help and exit. + * Use two columns to print help + */ fprintf(stderr, _("%s: unrecognized argument %s\n"), programName, argv[1]); + fprintf(stderr, "Recognized options:\n"); - for(i = 0; i < XtNumber(shellOptions); i++) { + for(i = 0; i < XtNumber(shellOptions); i++) + { + /* print first column */ j = fprintf(stderr, " %s%s", shellOptions[i].option, (shellOptions[i].argKind == XrmoptionSepArg ? " ARG" : "")); - if (i++ < XtNumber(shellOptions)) { + /* print second column and end line */ + if (++i < XtNumber(shellOptions)) + { fprintf(stderr, "%*c%s%s\n", 40 - j, ' ', shellOptions[i].option, (shellOptions[i].argKind == XrmoptionSepArg ? " ARG" : "")); - } else { + } + else + { fprintf(stderr, "\n"); - } - } + }; + }; exit(2); - } - - if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) { - chessDir = "."; - } else { - if (chdir(chessDir) != 0) { - fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName); - perror(chessDir); - exit(1); - } - } + }; p = getenv("HOME"); if (p == NULL) p = "/tmp"; @@ -2436,6 +2463,28 @@ main(argc, argv) clientResources, XtNumber(clientResources), NULL, 0); + { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string. + static char buf[MSG_SIZ]; + EscapeExpand(buf, appData.initString); + appData.initString = strdup(buf); + EscapeExpand(buf, appData.secondInitString); + appData.secondInitString = strdup(buf); + EscapeExpand(buf, appData.firstComputerString); + appData.firstComputerString = strdup(buf); + EscapeExpand(buf, appData.secondComputerString); + appData.secondComputerString = strdup(buf); + } + + if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) { + chessDir = "."; + } else { + if (chdir(chessDir) != 0) { + fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName); + perror(chessDir); + exit(1); + } + } + if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) { /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */ if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL) { @@ -2462,19 +2511,6 @@ main(argc, argv) gameInfo.variant = StringToVariant(appData.variant); InitPosition(FALSE); -#if 0 - /* - * Determine boardSize - */ - gameInfo.boardWidth = gameInfo.boardHeight = 8; // [HGM] boardsize: make sure we start as 8x8 - -//#ifndef IDSIZE - // [HGM] as long as we have not created the possibility to change size while running, start with requested size - gameInfo.boardWidth = appData.NrFiles > 0 ? appData.NrFiles : 8; - gameInfo.boardHeight = appData.NrRanks > 0 ? appData.NrRanks : 8; - gameInfo.holdingsWidth = appData.holdingsSize > 0 ? 2 : 0; -#endif - #ifdef IDSIZE InitDrawingSizes(-1, 0); // [HGM] initsize: make this into a subroutine @@ -3178,6 +3214,11 @@ ShutDownFrontEnd() unlink(gamePasteFilename); } +RETSIGTYPE TermSizeSigHandler(int sig) +{ + update_ics_width(); +} + RETSIGTYPE IntSigHandler(sig) int sig; @@ -3871,14 +3912,6 @@ void CreateXPMPieces() static char *xpmkind[] = { "ll", "ld", "dl", "dd" }; XpmColorSymbol symbols[4]; -#if 0 - /* Apparently some versions of Xpm don't define XpmFormat at all --tpm */ - if (appData.debugMode) { - fprintf(stderr, "XPM Library Version: %d.%d%c\n", - XpmFormat, XpmVersion, (char)('a' + XpmRevision - 1)); - } -#endif - /* The XSynchronize calls were copied from CreatePieces. Not sure if needed, but can't hurt */ XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */ @@ -3948,9 +3981,23 @@ void CreateXPMPieces() if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf, &(xpmPieceBitmap2[kind][piece]), NULL, &attr)) != 0) { - fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), - r, buf); - exit(1); + if(piece != (int)WhiteKing && piece > (int)WhiteQueen) { + // [HGM] missing: read of unorthodox piece failed; substitute King. + snprintf(buf, sizeof(buf), "%s/k%s%u.xpm", + ExpandPathName(appData.pixmapDirectory), + xpmkind[kind], ss); + if (appData.debugMode) { + fprintf(stderr, _("(Replace by File:%s:) "), buf); + } + r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf, + &(xpmPieceBitmap2[kind][piece]), + NULL, &attr); + } + if (r != 0) { + fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), + r, buf); + exit(1); + } } if(piece <= (int) WhiteKing) xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece]; @@ -4094,14 +4141,7 @@ void ReadBitmap(pm, name, bits, wreq, hreq) return; } } - if (bits == NULL) { -#if 0 - fprintf(stderr, _("%s: No built-in bitmap for %s; giving up\n"), - programName, name); - exit(1); -#endif - ; // [HGM] bitmaps: make it non-fatal if we have no bitmap; - } else { + if (bits != NULL) { *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits, wreq, hreq); } @@ -5084,10 +5124,40 @@ void HandleUserMove(w, event, prms, nprms) { int x, y; Boolean saveAnimate; - static int second = 0; + static int second = 0, promotionChoice = 0; + ChessMove moveType; if (w != boardWidget || errorExitStatus != -1) return; + x = EventToSquare(event->xbutton.x, BOARD_WIDTH); + y = EventToSquare(event->xbutton.y, BOARD_HEIGHT); + if (!flipView && y >= 0) { + y = BOARD_HEIGHT - 1 - y; + } + if (flipView && x >= 0) { + x = BOARD_WIDTH - 1 - x; + } + + if(promotionChoice) { // we are waiting for a click to indicate promotion piece + if(event->type == ButtonRelease) return; // ignore upclick of click-click destination + promotionChoice = FALSE; // only one chance: if click not OK it is interpreted as cancel + if(appData.debugMode) fprintf(debugFP, "promotion click, x=%d, y=%d\n", x, y); + if(gameInfo.holdingsWidth && + (WhiteOnMove(currentMove) + ? x == BOARD_WIDTH-1 && y < gameInfo.holdingsSize && y > 0 + : x == 0 && y >= BOARD_HEIGHT - gameInfo.holdingsSize && y < BOARD_HEIGHT-1) ) { + // click in right holdings, for determining promotion piece + ChessSquare p = boards[currentMove][y][x]; + if(appData.debugMode) fprintf(debugFP, "square contains %d\n", (int)p); + if(p != EmptySquare) { + FinishMove(NormalMove, fromX, fromY, toX, toY, ToLower(PieceToChar(p))); + fromX = fromY = -1; + return; + } + } + DrawPosition(FALSE, boards[currentMove]); + return; + } if (event->type == ButtonPress) ErrorPopDown(); if (promotionUp) { @@ -5102,15 +5172,6 @@ void HandleUserMove(w, event, prms, nprms) } } - x = EventToSquare(event->xbutton.x, BOARD_WIDTH); - y = EventToSquare(event->xbutton.y, BOARD_HEIGHT); - if (!flipView && y >= 0) { - y = BOARD_HEIGHT - 1 - y; - } - if (flipView && x >= 0) { - x = BOARD_WIDTH - 1 - x; - } - /* [HGM] holdings: next 5 lines: ignore all clicks between board and holdings */ if(event->type == ButtonPress && ( x == BOARD_LEFT-1 || x == BOARD_RGHT @@ -5120,7 +5181,7 @@ void HandleUserMove(w, event, prms, nprms) if (fromX == -1) { if (event->type == ButtonPress) { - /* First square */ + /* First square, prepare to drag */ if (OKToStartUserMove(x, y)) { fromX = x; fromY = y; @@ -5135,35 +5196,8 @@ void HandleUserMove(w, event, prms, nprms) } /* fromX != -1 */ - if (event->type == ButtonPress && gameMode != EditPosition && - x >= 0 && y >= 0) { - ChessSquare fromP; - ChessSquare toP; - - /* Check if clicking again on the same color piece */ - fromP = boards[currentMove][fromY][fromX]; - toP = boards[currentMove][y][x]; - if ((WhitePawn <= fromP && fromP < WhiteKing && // [HGM] this test should go, as UserMoveTest now does it. - WhitePawn <= toP && toP <= WhiteKing) || // For now I made it less critical by exempting King - (BlackPawn <= fromP && fromP < BlackKing && // moves, to not interfere with FRC castlings. - BlackPawn <= toP && toP <= BlackKing)) { - /* Clicked again on same color piece -- changed his mind */ - second = (x == fromX && y == fromY); - if (appData.highlightDragging) { - SetHighlights(x, y, -1, -1); - } else { - ClearHighlights(); - } - if (OKToStartUserMove(x, y)) { - fromX = x; - fromY = y; - DragPieceBegin(event->xbutton.x, event->xbutton.y); - } - return; - } - } - if (event->type == ButtonRelease && x == fromX && y == fromY) { + /* Click on single square in stead of drag-drop */ DragPieceEnd(event->xbutton.x, event->xbutton.y); if (appData.animateDragging) { /* Undo animation damage if any */ @@ -5183,7 +5217,34 @@ void HandleUserMove(w, event, prms, nprms) return; } - /* Completed move */ + moveType = UserMoveTest(fromX, fromY, x, y, NULLCHAR, event->type == ButtonRelease); + + if (moveType == Comment) { // kludge for indicating capture-own on Press + /* Clicked again on same color piece -- changed his mind */ + /* note that re-clicking same square always hits same color piece */ + second = (x == fromX && y == fromY); + if (appData.highlightDragging) { + SetHighlights(x, y, -1, -1); + } else { + ClearHighlights(); + } + if (OKToStartUserMove(x, y)) { + fromX = x; + fromY = y; + DragPieceBegin(event->xbutton.x, event->xbutton.y); + } + return; + } + + if(moveType == AmbiguousMove) { // kludge to indicate edit-position move + fromX = fromY = -1; + ClearHighlights(); + DragPieceEnd(event->xbutton.x, event->xbutton.y); + DrawPosition(FALSE, boards[currentMove]); + return; + } + + /* Complete move; (x,y) is now different from (fromX, fromY) on both Press and Release */ toX = x; toY = y; saveAnimate = appData.animate; @@ -5205,22 +5266,38 @@ void HandleUserMove(w, event, prms, nprms) /* Don't animate move and drag both */ appData.animate = FALSE; } - if (IsPromotion(fromX, fromY, toX, toY)) { - if (appData.alwaysPromoteToQueen) { - UserMoveEvent(fromX, fromY, toX, toY, 'q'); + if (moveType == WhitePromotionKnight || moveType == BlackPromotionKnight || + (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen) && + appData.alwaysPromoteToQueen) { // promotion, but no choice + FinishMove(moveType, fromX, fromY, toX, toY, 'q'); + } else + if (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen ) { + SetHighlights(fromX, fromY, toX, toY); + if(gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat) { + // [HGM] super: promotion to captured piece selected from holdings + ChessSquare p = boards[currentMove][fromY][fromX], q = boards[currentMove][toY][toX]; + promotionChoice = TRUE; + // kludge follows to temporarily execute move on display, without promoting yet + boards[currentMove][fromY][fromX] = EmptySquare; // move Pawn to 8th rank + boards[currentMove][toY][toX] = p; + DrawPosition(FALSE, boards[currentMove]); + boards[currentMove][fromY][fromX] = p; // take back, but display stays + boards[currentMove][toY][toX] = q; + DisplayMessage("Click in holdings to choose piece", ""); + return; + } + PromotionPopUp(); + goto skipClearingFrom; // the skipped stuff is done asynchronously by PromotionCallback + } else + if(moveType != ImpossibleMove) { // valid move, but no promotion + FinishMove(moveType, fromX, fromY, toX, toY, NULLCHAR); + } else { // invalid move; could have set premove + ClearHighlights(); + } if (!appData.highlightLastMove || gotPremove) ClearHighlights(); if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY); fromX = fromY = -1; - } else { - SetHighlights(fromX, fromY, toX, toY); - PromotionPopUp(); - } - } else { - UserMoveEvent(fromX, fromY, toX, toY, NULLCHAR); - if (!appData.highlightLastMove || gotPremove) ClearHighlights(); - if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY); - fromX = fromY = -1; - } +skipClearingFrom: appData.animate = saveAnimate; if (appData.animate || appData.animateDragging) { /* Undo animation damage if needed */ @@ -5279,12 +5356,8 @@ Widget CommentCreate(name, text, mutable, callback, lines) XtSetArg(args[j], XtNright, XtChainRight); j++; XtSetArg(args[j], XtNresizable, True); j++; XtSetArg(args[j], XtNwidth, bw_width); j++; /*force wider than buttons*/ -#if 0 - XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++; -#else /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */ XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++; -#endif XtSetArg(args[j], XtNautoFill, True); j++; XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++; edit = @@ -5437,12 +5510,8 @@ Widget MiscCreate(name, text, mutable, callback, lines) XtSetArg(args[j], XtNleft, XtChainLeft); j++; XtSetArg(args[j], XtNright, XtChainRight); j++; XtSetArg(args[j], XtNresizable, True); j++; -#if 0 - XtSetArg(args[j], XtNscrollVertical, XawtextScrollWhenNeeded); j++; -#else /* !!Work around an apparent bug in XFree86 4.0.1 (X11R6.4.3) */ XtSetArg(args[j], XtNscrollVertical, XawtextScrollAlways); j++; -#endif XtSetArg(args[j], XtNautoFill, True); j++; XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++; edit = @@ -6005,7 +6074,7 @@ void PromotionCallback(w, client_data, call_data) promoChar = ToLower(name[0]); } - UserMoveEvent(fromX, fromY, toX, toY, promoChar); + FinishMove(NormalMove, fromX, fromY, toX, toY, promoChar); if (!appData.highlightLastMove || gotPremove) ClearHighlights(); if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY); @@ -6181,15 +6250,6 @@ void ModeHighlight() args, 1); if (appData.showButtonBar) { -#if 0 - if (pausing) { - XtSetArg(args[0], XtNbackground, buttonForegroundPixel); - XtSetArg(args[1], XtNforeground, buttonBackgroundPixel); - } else { - XtSetArg(args[0], XtNbackground, buttonBackgroundPixel); - XtSetArg(args[1], XtNforeground, buttonForegroundPixel); - } -#else /* Always toggle, don't set. Previous code messes up when invoked while the button is pressed, as releasing it toggles the state again. */ @@ -6202,7 +6262,6 @@ void ModeHighlight() XtSetArg(args[0], XtNbackground, oldfg); XtSetArg(args[1], XtNforeground, oldbg); } -#endif XtSetValues(XtNameToWidget(buttonBarWidget, PAUSE_BUTTON), args, 2); } } @@ -7447,16 +7506,6 @@ void ShowThinkingProc(w, event, prms, nprms) appData.showThinking = !appData.showThinking; // [HGM] thinking: tken out of ShowThinkingEvent ShowThinkingEvent(); -#if 0 - // [HGM] thinking: currently no suc menu item; replaced by Hide Thinking (From Human) - if (appData.showThinking) { - XtSetArg(args[0], XtNleftBitmap, xMarkPixmap); - } else { - XtSetArg(args[0], XtNleftBitmap, None); - } - XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Thinking"), - args, 1); -#endif } void HideThinkingProc(w, event, prms, nprms) @@ -7542,7 +7591,7 @@ void AboutProc(w, event, prms, nprms) "Copyright 1991 Digital Equipment Corporation", "Enhancements Copyright 1992-2009 Free Software Foundation", "Enhancements Copyright 2005 Alessandro Scotti", - PRODUCT, " is free software and carries NO WARRANTY;", + PACKAGE, " is free software and carries NO WARRANTY;", "see the file COPYING for more information."); ErrorPopUp(_("About XBoard"), buf, FALSE); } @@ -7590,19 +7639,34 @@ void Iconify(w, event, prms, nprms) void DisplayMessage(message, extMessage) char *message, *extMessage; { - char buf[MSG_SIZ]; - Arg arg; - - if (extMessage) { - if (*message) { - snprintf(buf, sizeof(buf), "%s %s", message, extMessage); - message = buf; - } else { - message = extMessage; - } - } - XtSetArg(arg, XtNlabel, message); - XtSetValues(messageWidget, &arg, 1); + /* display a message in the message widget */ + + char buf[MSG_SIZ]; + Arg arg; + + if (extMessage) + { + if (*message) + { + snprintf(buf, sizeof(buf), "%s %s", message, extMessage); + message = buf; + } + else + { + message = extMessage; + }; + }; + + /* need to test if messageWidget already exists, since this function + can also be called during the startup, if for example a Xresource + is not set up correctly */ + if(messageWidget) + { + XtSetArg(arg, XtNlabel, message); + XtSetValues(messageWidget, &arg, 1); + }; + + return; } void DisplayTitle(text) @@ -8093,6 +8157,9 @@ void ScheduleDelayedEvent(cb, millisec) DelayedEventCallback cb; long millisec; { + if(delayedEventTimerXID && delayedEventCallback == cb) + // [HGM] alive: replace, rather than add or flush identical event + XtRemoveTimeOut(delayedEventTimerXID); delayedEventCallback = cb; delayedEventTimerXID = XtAppAddTimeOut(appContext, millisec, @@ -8331,6 +8398,10 @@ int StartChildProcess(cmdLine, dir, pr) SetUpChildIO(to_prog, from_prog); + #ifdef SIGWINCH + signal(SIGWINCH, TermSizeSigHandler); + #endif + if ((pid = fork()) == 0) { /* Child process */ // [HGM] PSWBTM: made order resistant against case where fd of created pipe was 0 or 1 @@ -8869,12 +8940,7 @@ FrameDelay (time) delay.it_interval.tv_usec = delay.it_value.tv_usec = (time % 1000) * 1000; setitimer(ITIMER_REAL, &delay, NULL); -#if 0 - /* Ugh -- busy-wait! --tpm */ - while (frameWaiting); -#else while (frameWaiting) pause(); -#endif delay.it_interval.tv_sec = delay.it_value.tv_sec = 0; delay.it_interval.tv_usec = delay.it_value.tv_usec = 0; setitimer(ITIMER_REAL, &delay, NULL); @@ -9323,19 +9389,10 @@ DragPieceBegin(x, y) ScreenSquare(boardX, boardY, &corner, &color); player.startSquare = corner; player.startColor = color; -#if 0 - /* Start from exactly where the piece is. This can be confusing - if you start dragging far from the center of the square; most - or all of the piece can be over a different square from the one - the mouse pointer is in. */ - player.mouseDelta.x = x - corner.x; - player.mouseDelta.y = y - corner.y; -#else /* As soon as we start dragging, the piece will jump slightly to be centered over the mouse pointer. */ player.mouseDelta.x = squareSize/2; player.mouseDelta.y = squareSize/2; -#endif /* Initialise animation */ player.dragPiece = PieceForSquare(boardX, boardY); /* Sanity check */ @@ -9437,3 +9494,38 @@ SetProgramStats( FrontEndProgramStats * stats ) // [HGM] done, but perhaps backend should call this directly? EngineOutputUpdate( stats ); } + +#include +int get_term_width() +{ + int fd, default_width; + + fd = STDIN_FILENO; + default_width = 79; // this is FICS default anyway... + +#if !defined(TIOCGWINSZ) && defined(TIOCGSIZE) + struct ttysize win; + if (!ioctl(fd, TIOCGSIZE, &win)) + default_width = win.ts_cols; +#elif defined(TIOCGWINSZ) + struct winsize win; + if (!ioctl(fd, TIOCGWINSZ, &win)) + default_width = win.ws_col; +#endif + return default_width; +} + +void update_ics_width() +{ + static int old_width = 0; + int new_width = get_term_width(); + + if (old_width != new_width) + ics_printf("set width %d\n", new_width); + old_width = new_width; +} + +void NotifyFrontendLogin() +{ + update_ics_width(); +}