X-Git-Url: http://winboard.nl/cgi-bin?a=blobdiff_plain;f=xboard.c;h=934f903d81fb4040c5ce59639635c986700eee6a;hb=b9c6b5e9fcd6321336ec28f25833530db79b928d;hp=f344499c5741d13913ce5c36567945023c6ba8ac;hpb=f5883cc4e2222df9c0a504a0c50da4acd6b77fb0;p=xboard.git diff --git a/xboard.c b/xboard.c index f344499..934f903 100644 --- a/xboard.c +++ b/xboard.c @@ -204,6 +204,7 @@ extern char *getenv(); #include "xhistory.h" #include "xedittags.h" #include "menus.h" +#include "board.h" #include "gettext.h" @@ -251,7 +252,6 @@ void ReadBitmap P((Pixmap *pm, String name, unsigned char bits[], u_int wreq, u_int hreq)); void CreateGrid P((void)); int EventToSquare P((int x, int limit)); -void DrawSquare P((int row, int column, ChessSquare piece, int do_flash)); void EventProc P((Widget widget, caddr_t unused, XEvent *event)); void DelayedDrag P((void)); void MoveTypeInProc P((Widget widget, caddr_t unused, XEvent *event)); @@ -308,14 +308,9 @@ void ManInner P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); void DisplayMove P((int moveNumber)); void DisplayTitle P((char *title)); void ICSInitScript P((void)); -int LoadGamePopUp P((FILE *f, int gameNumber, char *title)); void ErrorPopUp P((char *title, char *text, int modal)); void ErrorPopDown P((void)); static char *ExpandPathName P((char *path)); -static void CreateAnimVars P((void)); -static void DragPieceMove P((int x, int y)); -static void DrawDragPiece P((void)); -char *ModeToWidgetName P((GameMode mode)); void SelectMove P((Widget w, XEvent * event, String * params, Cardinal * nParams)); void GameListOptionsPopDown P(()); void GenericPopDown P(()); @@ -346,7 +341,6 @@ Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget, menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell, ICSInputShell, fileNameShell, askQuestionShell; Widget historyShell, evalGraphShell, gameListShell; -int hOffset; // [HGM] dual XSegment secondSegments[BOARD_RANKS + BOARD_FILES + 2]; XSegment gridSegments[BOARD_RANKS + BOARD_FILES + 2]; XSegment jailGridSegments[BOARD_RANKS + BOARD_FILES + 6]; @@ -373,20 +367,17 @@ BoardSize boardSize; Boolean chessProgram; int minX, minY; // [HGM] placement: volatile limits on upper-left corner -int squareSize, smallLayout = 0, tinyLayout = 0, +int smallLayout = 0, tinyLayout = 0, marginW, marginH, // [HGM] for run-time resizing fromX = -1, fromY = -1, toX, toY, commentUp = False, analysisUp = False, ICSInputBoxUp = False, askQuestionUp = False, filenameUp = False, promotionUp = False, pmFromX = -1, pmFromY = -1, - errorUp = False, errorExitStatus = -1, lineGap, defaultLineGap; + errorUp = False, errorExitStatus = -1, defaultLineGap; Dimension textHeight; Pixel timerForegroundPixel, timerBackgroundPixel; Pixel buttonForegroundPixel, buttonBackgroundPixel; -char *chessDir, *programName, *programVersion, - *gameCopyFilename, *gamePasteFilename; +char *chessDir, *programName, *programVersion; Boolean alwaysOnTop = False; -Boolean saveSettingsOnExit; -char *settingsFileName; char *icsTextMenuString; char *icsNames; char *firstChessProgramNames; @@ -424,26 +415,6 @@ XImage *xim_Cross; #define White(piece) ((int)(piece) < (int)BlackPawn) -/* Variables for doing smooth animation. This whole thing - would be much easier if the board was double-buffered, - but that would require a fairly major rewrite. */ - -typedef struct { - Pixmap saveBuf; - Pixmap newBuf; - GC blitGC, pieceGC, outlineGC; - XPoint startSquare, prevFrame, mouseDelta; - int startColor; - int dragPiece; - Boolean dragActive; - int startBoardX, startBoardY; - } AnimState; - -/* There can be two pieces being animated at once: a player - can begin dragging a piece before the remote opponent has moved. */ - -static AnimState game, player; - /* Bitmaps for use as masks when drawing XPM pieces. Need one for each black and white piece. */ static Pixmap xpmMask[BlackKing + 1]; @@ -1416,79 +1387,35 @@ ParseIcsTextColors () } int -MakeColors () -{ // [HGM] taken out of main(), so it can be called from BoardOptions dialog +MakeOneColor (char *name, Pixel *color) +{ XrmValue vFrom, vTo; - int forceMono = False; - - if (!appData.monoMode) { - vFrom.addr = (caddr_t) appData.lightSquareColor; - vFrom.size = strlen(appData.lightSquareColor); - XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo); - if (vTo.addr == NULL) { - appData.monoMode = True; - forceMono = True; - } else { - lightSquareColor = *(Pixel *) vTo.addr; - } - } - if (!appData.monoMode) { - vFrom.addr = (caddr_t) appData.darkSquareColor; - vFrom.size = strlen(appData.darkSquareColor); - XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo); - if (vTo.addr == NULL) { - appData.monoMode = True; - forceMono = True; - } else { - darkSquareColor = *(Pixel *) vTo.addr; - } - } - if (!appData.monoMode) { - vFrom.addr = (caddr_t) appData.whitePieceColor; - vFrom.size = strlen(appData.whitePieceColor); - XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo); - if (vTo.addr == NULL) { - appData.monoMode = True; - forceMono = True; - } else { - whitePieceColor = *(Pixel *) vTo.addr; - } - } if (!appData.monoMode) { - vFrom.addr = (caddr_t) appData.blackPieceColor; - vFrom.size = strlen(appData.blackPieceColor); + vFrom.addr = (caddr_t) name; + vFrom.size = strlen(name); XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo); if (vTo.addr == NULL) { appData.monoMode = True; - forceMono = True; + return True; } else { - blackPieceColor = *(Pixel *) vTo.addr; + *color = *(Pixel *) vTo.addr; } } + return False; +} - if (!appData.monoMode) { - vFrom.addr = (caddr_t) appData.highlightSquareColor; - vFrom.size = strlen(appData.highlightSquareColor); - XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo); - if (vTo.addr == NULL) { - appData.monoMode = True; - forceMono = True; - } else { - highlightSquareColor = *(Pixel *) vTo.addr; - } - } +int +MakeColors () +{ // [HGM] taken out of main(), so it can be called from BoardOptions dialog + int forceMono = False; + + forceMono |= MakeOneColor(appData.lightSquareColor, &lightSquareColor); + forceMono |= MakeOneColor(appData.darkSquareColor, &darkSquareColor); + forceMono |= MakeOneColor(appData.whitePieceColor, &whitePieceColor); + forceMono |= MakeOneColor(appData.blackPieceColor, &blackPieceColor); + forceMono |= MakeOneColor(appData.highlightSquareColor, &highlightSquareColor); + forceMono |= MakeOneColor(appData.premoveHighlightColor, &premoveHighlightColor); - if (!appData.monoMode) { - vFrom.addr = (caddr_t) appData.premoveHighlightColor; - vFrom.size = strlen(appData.premoveHighlightColor); - XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo); - if (vTo.addr == NULL) { - appData.monoMode = True; - forceMono = True; - } else { - premoveHighlightColor = *(Pixel *) vTo.addr; - } - } return forceMono; } @@ -2069,104 +1996,7 @@ XBoard square size (hint): %d\n\ */ ReadBitmap(&xMarkPixmap, "checkmark.bm", checkmark_bits, checkmark_width, checkmark_height); - XtSetArg(args[0], XtNleftBitmap, xMarkPixmap); -#ifndef OPTIONSDIALOG - if (appData.alwaysPromoteToQueen) { - XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"), - args, 1); - } - if (appData.animateDragging) { - XtSetValues(XtNameToWidget(menuBarWidget, - "menuOptions.Animate Dragging"), - args, 1); - } - if (appData.animate) { - XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"), - args, 1); - } - if (appData.autoCallFlag) { - XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"), - args, 1); - } - if (appData.autoFlipView) { - XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Auto Flip View"), - args, 1); - } - if (appData.blindfold) { - XtSetValues(XtNameToWidget(menuBarWidget, - "menuOptions.Blindfold"), args, 1); - } - if (appData.flashCount > 0) { - XtSetValues(XtNameToWidget(menuBarWidget, - "menuOptions.Flash Moves"), - args, 1); - } -#if HIGHDRAG - if (appData.highlightDragging) { - XtSetValues(XtNameToWidget(menuBarWidget, - "menuOptions.Highlight Dragging"), - args, 1); - } -#endif - if (appData.highlightLastMove) { - XtSetValues(XtNameToWidget(menuBarWidget, - "menuOptions.Highlight Last Move"), - args, 1); - } - if (appData.highlightMoveWithArrow) { - XtSetValues(XtNameToWidget(menuBarWidget, - "menuOptions.Arrow"), - args, 1); - } -// if (appData.icsAlarm) { -// XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.ICS Alarm"), -// args, 1); -// } - if (appData.ringBellAfterMoves) { - XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"), - args, 1); - } - if (appData.oneClick) { - XtSetValues(XtNameToWidget(menuBarWidget, - "menuOptions.OneClick"), args, 1); - } - if (appData.periodicUpdates) { - XtSetValues(XtNameToWidget(menuBarWidget, - "menuOptions.Periodic Updates"), args, 1); - } - if (appData.ponderNextMove) { - XtSetValues(XtNameToWidget(menuBarWidget, - "menuOptions.Ponder Next Move"), args, 1); - } - if (appData.popupExitMessage) { - XtSetValues(XtNameToWidget(menuBarWidget, - "menuOptions.Popup Exit Message"), args, 1); - } - if (appData.popupMoveErrors) { - XtSetValues(XtNameToWidget(menuBarWidget, - "menuOptions.Popup Move Errors"), args, 1); - } -// if (appData.premove) { -// XtSetValues(XtNameToWidget(menuBarWidget, -// "menuOptions.Premove"), args, 1); -// } - if (appData.showCoords) { - XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"), - args, 1); - } - if (appData.hideThinkingFromHuman) { - XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"), - args, 1); - } - if (appData.testLegality) { - XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Test Legality"), - args, 1); - } -#endif - if (saveSettingsOnExit) { - XtSetValues(XtNameToWidget(menuBarWidget,"menuOptions.Save Settings on Exit"), - args, 1); - } + InitMenuMarkers(); /* * Create an icon. @@ -2262,6 +2092,7 @@ XBoard square size (hint): %d\n\ signal(SIGUSR1, CmailSigHandler); } } + gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes() InitPosition(TRUE); // XtSetKeyboardFocus(shellWidget, formWidget); @@ -2361,294 +2192,6 @@ ResetFrontEnd () return; } -typedef struct { - char *name; - Boolean value; -} Enables; - -void -GreyRevert (Boolean grey) -{ - Widget w; - if (!menuBarWidget) return; - w = XtNameToWidget(menuBarWidget, "menuEdit.Revert"); - if (w == NULL) { - DisplayError("menuEdit.Revert", 0); - } else { - XtSetSensitive(w, !grey); - } - w = XtNameToWidget(menuBarWidget, "menuEdit.Annotate"); - if (w == NULL) { - DisplayError("menuEdit.Annotate", 0); - } else { - XtSetSensitive(w, !grey); - } -} - -void -SetMenuEnables (Enables *enab) -{ - Widget w; - if (!menuBarWidget) return; - while (enab->name != NULL) { - w = XtNameToWidget(menuBarWidget, enab->name); - if (w == NULL) { - DisplayError(enab->name, 0); - } else { - XtSetSensitive(w, enab->value); - } - enab++; - } -} - -Enables icsEnables[] = { - { "menuFile.Mail Move", False }, - { "menuFile.Reload CMail Message", False }, - { "menuMode.Machine Black", False }, - { "menuMode.Machine White", False }, - { "menuMode.Analysis Mode", False }, - { "menuMode.Analyze File", False }, - { "menuMode.Two Machines", False }, - { "menuMode.Machine Match", False }, -#ifndef ZIPPY - { "menuEngine.Hint", False }, - { "menuEngine.Book", False }, - { "menuEngine.Move Now", False }, -#ifndef OPTIONSDIALOG - { "menuOptions.Periodic Updates", False }, - { "menuOptions.Hide Thinking", False }, - { "menuOptions.Ponder Next Move", False }, -#endif -#endif - { "menuEngine.Engine #1 Settings", False }, - { "menuEngine.Engine #2 Settings", False }, - { "menuEngine.Load Engine", False }, - { "menuEdit.Annotate", False }, - { "menuOptions.Match", False }, - { NULL, False } -}; - -Enables ncpEnables[] = { - { "menuFile.Mail Move", False }, - { "menuFile.Reload CMail Message", False }, - { "menuMode.Machine White", False }, - { "menuMode.Machine Black", False }, - { "menuMode.Analysis Mode", False }, - { "menuMode.Analyze File", False }, - { "menuMode.Two Machines", False }, - { "menuMode.Machine Match", False }, - { "menuMode.ICS Client", False }, - { "menuView.ICStex", False }, - { "menuView.ICS Input Box", False }, - { "Action", False }, - { "menuEdit.Revert", False }, - { "menuEdit.Annotate", False }, - { "menuEngine.Engine #1 Settings", False }, - { "menuEngine.Engine #2 Settings", False }, - { "menuEngine.Move Now", False }, - { "menuEngine.Retract Move", False }, - { "menuOptions.ICS", False }, -#ifndef OPTIONSDIALOG - { "menuOptions.Auto Flag", False }, - { "menuOptions.Auto Flip View", False }, -// { "menuOptions.ICS Alarm", False }, - { "menuOptions.Move Sound", False }, - { "menuOptions.Hide Thinking", False }, - { "menuOptions.Periodic Updates", False }, - { "menuOptions.Ponder Next Move", False }, -#endif - { "menuEngine.Hint", False }, - { "menuEngine.Book", False }, - { NULL, False } -}; - -Enables gnuEnables[] = { - { "menuMode.ICS Client", False }, - { "menuView.ICStex", False }, - { "menuView.ICS Input Box", False }, - { "menuAction.Accept", False }, - { "menuAction.Decline", False }, - { "menuAction.Rematch", False }, - { "menuAction.Adjourn", False }, - { "menuAction.Stop Examining", False }, - { "menuAction.Stop Observing", False }, - { "menuAction.Upload to Examine", False }, - { "menuEdit.Revert", False }, - { "menuEdit.Annotate", False }, - { "menuOptions.ICS", False }, - - /* The next two options rely on SetCmailMode being called *after* */ - /* SetGNUMode so that when GNU is being used to give hints these */ - /* menu options are still available */ - - { "menuFile.Mail Move", False }, - { "menuFile.Reload CMail Message", False }, - // [HGM] The following have been added to make a switch from ncp to GNU mode possible - { "menuMode.Machine White", True }, - { "menuMode.Machine Black", True }, - { "menuMode.Analysis Mode", True }, - { "menuMode.Analyze File", True }, - { "menuMode.Two Machines", True }, - { "menuMode.Machine Match", True }, - { "menuEngine.Engine #1 Settings", True }, - { "menuEngine.Engine #2 Settings", True }, - { "menuEngine.Hint", True }, - { "menuEngine.Book", True }, - { "menuEngine.Move Now", True }, - { "menuEngine.Retract Move", True }, - { "Action", True }, - { NULL, False } -}; - -Enables cmailEnables[] = { - { "Action", True }, - { "menuAction.Call Flag", False }, - { "menuAction.Draw", True }, - { "menuAction.Adjourn", False }, - { "menuAction.Abort", False }, - { "menuAction.Stop Observing", False }, - { "menuAction.Stop Examining", False }, - { "menuFile.Mail Move", True }, - { "menuFile.Reload CMail Message", True }, - { NULL, False } -}; - -Enables trainingOnEnables[] = { - { "menuMode.Edit Comment", False }, - { "menuMode.Pause", False }, - { "menuEdit.Forward", False }, - { "menuEdit.Backward", False }, - { "menuEdit.Forward to End", False }, - { "menuEdit.Back to Start", False }, - { "menuEngine.Move Now", False }, - { "menuEdit.Truncate Game", False }, - { NULL, False } -}; - -Enables trainingOffEnables[] = { - { "menuMode.Edit Comment", True }, - { "menuMode.Pause", True }, - { "menuEdit.Forward", True }, - { "menuEdit.Backward", True }, - { "menuEdit.Forward to End", True }, - { "menuEdit.Back to Start", True }, - { "menuEngine.Move Now", True }, - { "menuEdit.Truncate Game", True }, - { NULL, False } -}; - -Enables machineThinkingEnables[] = { - { "menuFile.Load Game", False }, -// { "menuFile.Load Next Game", False }, -// { "menuFile.Load Previous Game", False }, -// { "menuFile.Reload Same Game", False }, - { "menuEdit.Paste Game", False }, - { "menuFile.Load Position", False }, -// { "menuFile.Load Next Position", False }, -// { "menuFile.Load Previous Position", False }, -// { "menuFile.Reload Same Position", False }, - { "menuEdit.Paste Position", False }, - { "menuMode.Machine White", False }, - { "menuMode.Machine Black", False }, - { "menuMode.Two Machines", False }, -// { "menuMode.Machine Match", False }, - { "menuEngine.Retract Move", False }, - { NULL, False } -}; - -Enables userThinkingEnables[] = { - { "menuFile.Load Game", True }, -// { "menuFile.Load Next Game", True }, -// { "menuFile.Load Previous Game", True }, -// { "menuFile.Reload Same Game", True }, - { "menuEdit.Paste Game", True }, - { "menuFile.Load Position", True }, -// { "menuFile.Load Next Position", True }, -// { "menuFile.Load Previous Position", True }, -// { "menuFile.Reload Same Position", True }, - { "menuEdit.Paste Position", True }, - { "menuMode.Machine White", True }, - { "menuMode.Machine Black", True }, - { "menuMode.Two Machines", True }, -// { "menuMode.Machine Match", True }, - { "menuEngine.Retract Move", True }, - { NULL, False } -}; - -void -SetICSMode () -{ - SetMenuEnables(icsEnables); - -#if ZIPPY - if (appData.zippyPlay && !appData.noChessProgram) { /* [DM] icsEngineAnalyze */ - XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Analysis Mode"), True); - XtSetSensitive(XtNameToWidget(menuBarWidget, "menuEngine.Engine #1 Settings"), True); - } -#endif -} - -void -SetNCPMode () -{ - SetMenuEnables(ncpEnables); -} - -void -SetGNUMode () -{ - SetMenuEnables(gnuEnables); -} - -void -SetCmailMode () -{ - SetMenuEnables(cmailEnables); -} - -void -SetTrainingModeOn () -{ - SetMenuEnables(trainingOnEnables); - if (appData.showButtonBar) { - XtSetSensitive(buttonBarWidget, False); - } - CommentPopDown(); -} - -void -SetTrainingModeOff () -{ - SetMenuEnables(trainingOffEnables); - if (appData.showButtonBar) { - XtSetSensitive(buttonBarWidget, True); - } -} - -void -SetUserThinkingEnables () -{ - if (appData.noChessProgram) return; - SetMenuEnables(userThinkingEnables); -} - -void -SetMachineThinkingEnables () -{ - if (appData.noChessProgram) return; - SetMenuEnables(machineThinkingEnables); - switch (gameMode) { - case MachinePlaysBlack: - case MachinePlaysWhite: - case TwoMachinesPlay: - XtSetSensitive(XtNameToWidget(menuBarWidget, - ModeToWidgetName(gameMode)), True); - break; - default: - break; - } -} - // [HGM] code borrowed from winboard.c (which should thus go to backend.c!) #define HISTORY_SIZE 64 static char *history[HISTORY_SIZE]; @@ -2876,6 +2419,16 @@ DeleteGCs () } } +static GC +CreateOneGC (XGCValues *gc_values, Pixel foreground, Pixel background) +{ + XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground + | GCBackground | GCFunction | GCPlaneMask; + gc_values->foreground = foreground; + gc_values->background = background; + return XtGetGC(shellWidget, value_mask, gc_values); +} + void CreateGCs (int redo) { @@ -2883,6 +2436,8 @@ CreateGCs (int redo) | GCBackground | GCFunction | GCPlaneMask; XGCValues gc_values; GC copyInvertedGC; + Pixel white = XWhitePixel(xDisplay, xScreen); + Pixel black = XBlackPixel(xDisplay, xScreen); gc_values.plane_mask = AllPlanes; gc_values.line_width = lineGap; @@ -2892,40 +2447,25 @@ CreateGCs (int redo) if(redo) { DeleteGCs(); // called a second time; clean up old GCs first } else { // [HGM] grid and font GCs created on first call only - gc_values.foreground = XBlackPixel(xDisplay, xScreen); - gc_values.background = XWhitePixel(xDisplay, xScreen); - coordGC = XtGetGC(shellWidget, value_mask, &gc_values); + coordGC = CreateOneGC(&gc_values, black, white); XSetFont(xDisplay, coordGC, coordFontID); // [HGM] make font for holdings counts (white on black) - gc_values.foreground = XWhitePixel(xDisplay, xScreen); - gc_values.background = XBlackPixel(xDisplay, xScreen); - countGC = XtGetGC(shellWidget, value_mask, &gc_values); + countGC = CreateOneGC(&gc_values, white, black); XSetFont(xDisplay, countGC, countFontID); } - gc_values.foreground = XBlackPixel(xDisplay, xScreen); - gc_values.background = XBlackPixel(xDisplay, xScreen); - lineGC = XtGetGC(shellWidget, value_mask, &gc_values); + lineGC = CreateOneGC(&gc_values, black, black); if (appData.monoMode) { - gc_values.foreground = XWhitePixel(xDisplay, xScreen); - gc_values.background = XWhitePixel(xDisplay, xScreen); - highlineGC = XtGetGC(shellWidget, value_mask, &gc_values); - gc_values.foreground = XWhitePixel(xDisplay, xScreen); - gc_values.background = XBlackPixel(xDisplay, xScreen); - lightSquareGC = wbPieceGC - = XtGetGC(shellWidget, value_mask, &gc_values); - - gc_values.foreground = XBlackPixel(xDisplay, xScreen); - gc_values.background = XWhitePixel(xDisplay, xScreen); - darkSquareGC = bwPieceGC - = XtGetGC(shellWidget, value_mask, &gc_values); + highlineGC = CreateOneGC(&gc_values, white, white); + lightSquareGC = wbPieceGC = CreateOneGC(&gc_values, white, black); + darkSquareGC = bwPieceGC = CreateOneGC(&gc_values, black, white); if (DefaultDepth(xDisplay, xScreen) == 1) { /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */ gc_values.function = GXcopyInverted; - copyInvertedGC = XtGetGC(shellWidget, value_mask, &gc_values); + copyInvertedGC = CreateOneGC(&gc_values, black, white); gc_values.function = GXcopy; if (XBlackPixel(xDisplay, xScreen) == 1) { bwPieceGC = darkSquareGC; @@ -2936,49 +2476,18 @@ CreateGCs (int redo) } } } else { - gc_values.foreground = highlightSquareColor; - gc_values.background = highlightSquareColor; - highlineGC = XtGetGC(shellWidget, value_mask, &gc_values); - - gc_values.foreground = premoveHighlightColor; - gc_values.background = premoveHighlightColor; - prelineGC = XtGetGC(shellWidget, value_mask, &gc_values); - - gc_values.foreground = lightSquareColor; - gc_values.background = darkSquareColor; - lightSquareGC = XtGetGC(shellWidget, value_mask, &gc_values); - - gc_values.foreground = darkSquareColor; - gc_values.background = lightSquareColor; - darkSquareGC = XtGetGC(shellWidget, value_mask, &gc_values); - - gc_values.foreground = jailSquareColor; - gc_values.background = jailSquareColor; - jailSquareGC = XtGetGC(shellWidget, value_mask, &gc_values); - - gc_values.foreground = whitePieceColor; - gc_values.background = darkSquareColor; - wdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values); - gc_values.foreground = whitePieceColor; - gc_values.background = lightSquareColor; - wlPieceGC = XtGetGC(shellWidget, value_mask, &gc_values); - - gc_values.foreground = whitePieceColor; - gc_values.background = jailSquareColor; - wjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values); - - gc_values.foreground = blackPieceColor; - gc_values.background = darkSquareColor; - bdPieceGC = XtGetGC(shellWidget, value_mask, &gc_values); - - gc_values.foreground = blackPieceColor; - gc_values.background = lightSquareColor; - blPieceGC = XtGetGC(shellWidget, value_mask, &gc_values); - - gc_values.foreground = blackPieceColor; - gc_values.background = jailSquareColor; - bjPieceGC = XtGetGC(shellWidget, value_mask, &gc_values); + highlineGC = CreateOneGC(&gc_values, highlightSquareColor, highlightSquareColor); + prelineGC = CreateOneGC(&gc_values, premoveHighlightColor, premoveHighlightColor); + lightSquareGC = CreateOneGC(&gc_values, lightSquareColor, darkSquareColor); + darkSquareGC = CreateOneGC(&gc_values, darkSquareColor, lightSquareColor); + jailSquareGC = CreateOneGC(&gc_values, jailSquareColor, jailSquareColor); + wdPieceGC = CreateOneGC(&gc_values, whitePieceColor, darkSquareColor); + wlPieceGC = CreateOneGC(&gc_values, whitePieceColor, lightSquareColor); + wjPieceGC = CreateOneGC(&gc_values, whitePieceColor, jailSquareColor); + bdPieceGC = CreateOneGC(&gc_values, blackPieceColor, darkSquareColor); + blPieceGC = CreateOneGC(&gc_values, blackPieceColor, lightSquareColor); + bjPieceGC = CreateOneGC(&gc_values, blackPieceColor, jailSquareColor); } } @@ -3453,6 +2962,7 @@ CreateGrid () } int nrOfMenuItems = 7; +Widget menuWidget[150]; MenuListItem menuItemList[150] = { { "LoadNextGameProc", LoadNextGameProc }, { "LoadPrevGameProc", LoadPrevGameProc }, @@ -3487,6 +2997,40 @@ MenuListItem menuItemList[150] = { {NULL, NothingProc} }; +void +MarkMenuItem (char *menuRef, int state) +{ + int nr = MenuToNumber(menuRef); + if(nr >= 0) { + Arg args[2]; + XtSetArg(args[0], XtNleftBitmap, state ? xMarkPixmap : None); + XtSetValues(menuWidget[nr], args, 1); + } +} + +void +EnableMenuItem (char *menuRef, int state) +{ + int nr = MenuToNumber(menuRef); + if(nr >= 0) XtSetSensitive(menuWidget[nr], state); +} + +void +EnableButtonBar (int state) +{ + XtSetSensitive(buttonBarWidget, state); +} + + +void +SetMenuEnables (Enables *enab) +{ + while (enab->name != NULL) { + EnableMenuItem(enab->name, enab->value); + enab++; + } +} + int Equal(char *p, char *s) { // compare strings skipping spaces in second @@ -3549,6 +3093,7 @@ AppendMenuItem (char *text, char *name, MenuProc *action) XtAddCallback(entry, XtNcallback, (XtCallbackProc) (strcmp(name, "recent") ? MenuBarSelect : MenuEngineSelect), (caddr_t) action); + menuWidget[nrOfMenuItems] = entry; } } @@ -3786,128 +3331,23 @@ BlackClock (Widget w, XEvent *event, String *prms, Cardinal *nprms) } -/* - * If the user selects on a border boundary, return -1; if off the board, - * return -2. Otherwise map the event coordinate to the square. - */ -int -EventToSquare (int x, int limit) -{ - if (x <= 0) - return -2; - if (x < lineGap) - return -1; - x -= lineGap; - if ((x % (squareSize + lineGap)) >= squareSize) - return -1; - x /= (squareSize + lineGap); - if (x >= limit) - return -2; - return x; -} - static void do_flash_delay (unsigned long msec) { TimeDelay(msec); } -static void -drawHighlight (int file, int rank, GC gc) +void +DrawBorder (int x, int y, int type) { - int x, y; + GC gc = lineGC; - if (lineGap == 0) return; - - if (flipView) { - x = lineGap/2 + ((BOARD_WIDTH-1)-file) * - (squareSize + lineGap); - y = lineGap/2 + rank * (squareSize + lineGap); - } else { - x = lineGap/2 + file * (squareSize + lineGap); - y = lineGap/2 + ((BOARD_HEIGHT-1)-rank) * - (squareSize + lineGap); - } + if(type == 1) gc = highlineGC; else if(type == 2) gc = prelineGC; XDrawRectangle(xDisplay, xBoardWindow, gc, x, y, squareSize+lineGap, squareSize+lineGap); } -int hi1X = -1, hi1Y = -1, hi2X = -1, hi2Y = -1; -int pm1X = -1, pm1Y = -1, pm2X = -1, pm2Y = -1; - -void -SetHighlights (int fromX, int fromY, int toX, int toY) -{ - if (hi1X != fromX || hi1Y != fromY) { - if (hi1X >= 0 && hi1Y >= 0) { - drawHighlight(hi1X, hi1Y, lineGC); - } - } // [HGM] first erase both, then draw new! - - if (hi2X != toX || hi2Y != toY) { - if (hi2X >= 0 && hi2Y >= 0) { - drawHighlight(hi2X, hi2Y, lineGC); - } - } - if (hi1X != fromX || hi1Y != fromY) { - if (fromX >= 0 && fromY >= 0) { - drawHighlight(fromX, fromY, highlineGC); - } - } - if (hi2X != toX || hi2Y != toY) { - if (toX >= 0 && toY >= 0) { - drawHighlight(toX, toY, highlineGC); - } - } - - if(toX<0) // clearing the highlights must have damaged arrow - DrawArrowHighlight(hi1X, hi1Y, hi2X, hi2Y); // for now, redraw it (should really be cleared!) - - hi1X = fromX; - hi1Y = fromY; - hi2X = toX; - hi2Y = toY; -} - -void -ClearHighlights () -{ - SetHighlights(-1, -1, -1, -1); -} - - -void -SetPremoveHighlights (int fromX, int fromY, int toX, int toY) -{ - if (pm1X != fromX || pm1Y != fromY) { - if (pm1X >= 0 && pm1Y >= 0) { - drawHighlight(pm1X, pm1Y, lineGC); - } - if (fromX >= 0 && fromY >= 0) { - drawHighlight(fromX, fromY, prelineGC); - } - } - if (pm2X != toX || pm2Y != toY) { - if (pm2X >= 0 && pm2Y >= 0) { - drawHighlight(pm2X, pm2Y, lineGC); - } - if (toX >= 0 && toY >= 0) { - drawHighlight(toX, toY, prelineGC); - } - } - pm1X = fromX; - pm1Y = fromY; - pm2X = toX; - pm2Y = toY; -} - -void -ClearPremoveHighlights () -{ - SetPremoveHighlights(-1, -1, -1, -1); -} - static int CutOutSquare (int x, int y, int *x0, int *y0, int kind) { @@ -4104,154 +3544,71 @@ ChooseDrawFunc () } } -/* [HR] determine square color depending on chess variant. */ -static int -SquareColor (int row, int column) -{ - int square_color; - - if (gameInfo.variant == VariantXiangqi) { - if (column >= 3 && column <= 5 && row >= 0 && row <= 2) { - square_color = 1; - } else if (column >= 3 && column <= 5 && row >= 7 && row <= 9) { - square_color = 0; - } else if (row <= 4) { - square_color = 0; - } else { - square_color = 1; - } - } else { - square_color = ((column + row) % 2) == 1; - } - - /* [hgm] holdings: next line makes all holdings squares light */ - if(column < BOARD_LEFT || column >= BOARD_RGHT) square_color = 1; - - return square_color; +void +DrawDot (int marker, int x, int y, int r) +{ + if(appData.monoMode) { + XFillArc(xDisplay, xBoardWindow, marker == 2 ? darkSquareGC : lightSquareGC, + x, y, r, r, 0, 64*360); + XDrawArc(xDisplay, xBoardWindow, marker == 2 ? lightSquareGC : darkSquareGC, + x, y, r, r, 0, 64*360); + } else + XFillArc(xDisplay, xBoardWindow, marker == 2 ? prelineGC : highlineGC, + x, y, r, r, 0, 64*360); } void -DrawSquare (int row, int column, ChessSquare piece, int do_flash) -{ - int square_color, x, y, direction, font_ascent, font_descent; - int i; - char string[2]; +DrawOneSquare (int x, int y, ChessSquare piece, int square_color, int marker, char *string, int align) +{ // basic front-end board-draw function: takes care of everything that can be in square: + // piece, background, coordinate/count, marker dot + int direction, font_ascent, font_descent; XCharStruct overall; DrawFunc drawfunc; - int flash_delay; - - /* Calculate delay in milliseconds (2-delays per complete flash) */ - flash_delay = 500 / appData.flashRate; - if (flipView) { - x = lineGap + ((BOARD_WIDTH-1)-column) * - (squareSize + lineGap); - y = lineGap + row * (squareSize + lineGap); + if (piece == EmptySquare) { + BlankSquare(x, y, square_color, piece, xBoardWindow, 1); } else { - x = lineGap + column * (squareSize + lineGap); - y = lineGap + ((BOARD_HEIGHT-1)-row) * - (squareSize + lineGap); - } - - if(twoBoards && partnerUp) x += hOffset; // [HGM] dual: draw second board - - square_color = SquareColor(row, column); - - if ( // [HGM] holdings: blank out area between board and holdings - column == BOARD_LEFT-1 || column == BOARD_RGHT - || (column == BOARD_LEFT-2 && row < BOARD_HEIGHT-gameInfo.holdingsSize) - || (column == BOARD_RGHT+1 && row >= gameInfo.holdingsSize) ) { - BlankSquare(x, y, 2, EmptySquare, xBoardWindow, 1); - - // [HGM] print piece counts next to holdings - string[1] = NULLCHAR; - if (column == (flipView ? BOARD_LEFT-1 : BOARD_RGHT) && piece > 1 ) { - string[0] = '0' + piece; - XTextExtents(countFontStruct, string, 1, &direction, - &font_ascent, &font_descent, &overall); - if (appData.monoMode) { - XDrawImageString(xDisplay, xBoardWindow, countGC, - x + squareSize - overall.width - 2, - y + font_ascent + 1, string, 1); - } else { - XDrawString(xDisplay, xBoardWindow, countGC, - x + squareSize - overall.width - 2, - y + font_ascent + 1, string, 1); - } - } - if (column == (flipView ? BOARD_RGHT : BOARD_LEFT-1) && piece > 1) { - string[0] = '0' + piece; - XTextExtents(countFontStruct, string, 1, &direction, - &font_ascent, &font_descent, &overall); - if (appData.monoMode) { - XDrawImageString(xDisplay, xBoardWindow, countGC, - x + 2, y + font_ascent + 1, string, 1); - } else { - XDrawString(xDisplay, xBoardWindow, countGC, - x + 2, y + font_ascent + 1, string, 1); - } - } - } else { - if (piece == EmptySquare || appData.blindfold) { - BlankSquare(x, y, square_color, piece, xBoardWindow, 1); - } else { - drawfunc = ChooseDrawFunc(); - - if (do_flash && appData.flashCount > 0) { - for (i=0; i= BOARD_LEFT && column < BOARD_RGHT) { - string[0] = 'a' + column - BOARD_LEFT; - XTextExtents(coordFontStruct, string, 1, &direction, - &font_ascent, &font_descent, &overall); - if (appData.monoMode) { - XDrawImageString(xDisplay, xBoardWindow, coordGC, - x + squareSize - overall.width - 2, - y + squareSize - font_descent - 1, string, 1); - } else { - XDrawString(xDisplay, xBoardWindow, coordGC, - x + squareSize - overall.width - 2, - y + squareSize - font_descent - 1, string, 1); + drawfunc = ChooseDrawFunc(); + drawfunc(piece, square_color, x, y, xBoardWindow); + } + + if(align) { // square carries inscription (coord or piece count) + int xx = x, yy = y; + GC hGC = align < 3 ? coordGC : countGC; + // first calculate where it goes + XTextExtents(countFontStruct, string, 1, &direction, + &font_ascent, &font_descent, &overall); + if (align == 1) { + xx += squareSize - overall.width - 2; + yy += squareSize - font_descent - 1; + } else if (align == 2) { + xx += 2, yy += font_ascent + 1; + } else if (align == 3) { + xx += squareSize - overall.width - 2; + yy += font_ascent + 1; + } else if (align == 4) { + xx += 2, yy += font_ascent + 1; } - } - if (appData.showCoords && column == (flipView ? BOARD_RGHT-1 : BOARD_LEFT)) { - string[0] = ONE + row; - XTextExtents(coordFontStruct, string, 1, &direction, - &font_ascent, &font_descent, &overall); + // then draw it if (appData.monoMode) { - XDrawImageString(xDisplay, xBoardWindow, coordGC, - x + 2, y + font_ascent + 1, string, 1); + XDrawImageString(xDisplay, xBoardWindow, hGC, xx, yy, string, 1); } else { - XDrawString(xDisplay, xBoardWindow, coordGC, - x + 2, y + font_ascent + 1, string, 1); + XDrawString(xDisplay, xBoardWindow, hGC, xx, yy, string, 1); } } - if(!partnerUp && marker[row][column]) { - if(appData.monoMode) { - XFillArc(xDisplay, xBoardWindow, marker[row][column] == 2 ? darkSquareGC : lightSquareGC, - x + squareSize/4, y+squareSize/4, squareSize/2, squareSize/2, 0, 64*360); - XDrawArc(xDisplay, xBoardWindow, marker[row][column] == 2 ? lightSquareGC : darkSquareGC, - x + squareSize/4, y+squareSize/4, squareSize/2, squareSize/2, 0, 64*360); - } else - XFillArc(xDisplay, xBoardWindow, marker[row][column] == 2 ? prelineGC : highlineGC, - x + squareSize/4, y+squareSize/4, squareSize/2, squareSize/2, 0, 64*360); + + if(marker) { // print fat marker dot, if requested + DrawDot(marker, x + squareSize/4, y+squareSize/4, squareSize/2); } } +void +FlashDelay (int flash_delay) +{ + XSync(xDisplay, False); + if(flash_delay) do_flash_delay(flash_delay); +} + double Fraction (int x, int start, int stop) { @@ -4311,7 +3668,7 @@ DragProc () if(EvalGraphIsUp()) CoDrag(evalGraphShell, &wpEvalGraph); if(GameListIsUp()) CoDrag(gameListShell, &wpGameList); wpMain = wpNew; - XDrawPosition(boardWidget, True, NULL); + DrawPosition(True, NULL); delayedDragID = 0; // now drag executed, make sure next DelayedDrag will not cancel timer event (which could now be used by other) } @@ -4337,10 +3694,10 @@ EventProc (Widget widget, caddr_t unused, XEvent *event) break; case Expose: if (event->xexpose.count > 0) return; /* no clipping is done */ - XDrawPosition(widget, True, NULL); + DrawPosition(True, NULL); if(twoBoards) { // [HGM] dual: draw other board in other orientation flipView = !flipView; partnerUp = !partnerUp; - XDrawPosition(widget, True, NULL); + DrawPosition(True, NULL); flipView = !flipView; partnerUp = !partnerUp; } break; @@ -4352,77 +3709,6 @@ EventProc (Widget widget, caddr_t unused, XEvent *event) } /* end why */ -void -DrawPosition (int fullRedraw, Board board) -{ - XDrawPosition(boardWidget, fullRedraw, board); -} - -/* Returns 1 if there are "too many" differences between b1 and b2 - (i.e. more than 1 move was made) */ -static int -too_many_diffs (Board b1, Board b2) -{ - int i, j; - int c = 0; - - for (i=0; i 4) /* Castling causes 4 diffs */ - return 1; - } - } - } - return 0; -} - -/* Matrix describing castling maneuvers */ -/* Row, ColRookFrom, ColKingFrom, ColRookTo, ColKingTo */ -static int castling_matrix[4][5] = { - { 0, 0, 4, 3, 2 }, /* 0-0-0, white */ - { 0, 7, 4, 5, 6 }, /* 0-0, white */ - { 7, 0, 4, 3, 2 }, /* 0-0-0, black */ - { 7, 7, 4, 5, 6 } /* 0-0, black */ -}; - -/* Checks whether castling occurred. If it did, *rrow and *rcol - are set to the destination (row,col) of the rook that moved. - - Returns 1 if castling occurred, 0 if not. - - Note: Only handles a max of 1 castling move, so be sure - to call too_many_diffs() first. - */ -static int -check_castle_draw (Board newb, Board oldb, int *rrow, int *rcol) -{ - int i, *r, j; - int match; - - /* For each type of castling... */ - for (i=0; i<4; ++i) { - r = castling_matrix[i]; - - /* Check the 4 squares involved in the castling move */ - match = 0; - for (j=1; j<=4; ++j) { - if (newb[r[0]][r[j]] == oldb[r[0]][r[j]]) { - match = 1; - break; - } - } - - if (!match) { - /* All 4 changed, so it must be a castling move */ - *rrow = r[0]; - *rcol = r[3]; - return 1; - } - } - return 0; -} - // [HGM] seekgraph: some low-level drawing routines cloned from xevalgraph void DrawSeekAxis (int x, int y, int xTo, int yTo) @@ -4457,113 +3743,12 @@ DrawSeekDot (int x, int y, int colorNr) x-squareSize/8, y-squareSize/8, squareSize/4, squareSize/4, 0, 64*360); } -static int damage[2][BOARD_RANKS][BOARD_FILES]; - -/* - * event handler for redrawing the board - */ void -XDrawPosition (Widget w, int repaint, Board board) +DrawGrid (int second) { - int i, j, do_flash; - static int lastFlipView = 0; - static int lastBoardValid[2] = {0, 0}; - static Board lastBoard[2]; - Arg args[16]; - int rrow, rcol; - int nr = twoBoards*partnerUp; - - if(DrawSeekGraph()) return; // [HGM] seekgraph: suppress any drawing if seek graph up - - if (board == NULL) { - if (!lastBoardValid[nr]) return; - board = lastBoard[nr]; - } - if (!lastBoardValid[nr] || (nr == 0 && lastFlipView != flipView)) { - XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None)); - XtSetValues(XtNameToWidget(menuBarWidget, "menuView.Flip View"), - args, 1); - } - - /* - * It would be simpler to clear the window with XClearWindow() - * but this causes a very distracting flicker. - */ - - if (!repaint && lastBoardValid[nr] && (nr == 1 || lastFlipView == flipView)) { - - if ( lineGap && IsDrawArrowEnabled()) - XDrawSegments(xDisplay, xBoardWindow, lineGC, - gridSegments, BOARD_HEIGHT + BOARD_WIDTH + 2); - - /* If too much changes (begin observing new game, etc.), don't - do flashing */ - do_flash = too_many_diffs(board, lastBoard[nr]) ? 0 : 1; - - /* Special check for castling so we don't flash both the king - and the rook (just flash the king). */ - if (do_flash) { - if (check_castle_draw(board, lastBoard[nr], &rrow, &rcol)) { - /* Draw rook with NO flashing. King will be drawn flashing later */ - DrawSquare(rrow, rcol, board[rrow][rcol], 0); - lastBoard[nr][rrow][rcol] = board[rrow][rcol]; - } - } - - /* First pass -- Draw (newly) empty squares and repair damage. - This prevents you from having a piece show up twice while it - is flashing on its new square */ - for (i = 0; i < BOARD_HEIGHT; i++) - for (j = 0; j < BOARD_WIDTH; j++) - if ((board[i][j] != lastBoard[nr][i][j] && board[i][j] == EmptySquare) - || damage[nr][i][j]) { - DrawSquare(i, j, board[i][j], 0); - damage[nr][i][j] = False; - } - - /* Second pass -- Draw piece(s) in new position and flash them */ - for (i = 0; i < BOARD_HEIGHT; i++) - for (j = 0; j < BOARD_WIDTH; j++) - if (board[i][j] != lastBoard[nr][i][j]) { - DrawSquare(i, j, board[i][j], do_flash); - } - } else { - if (lineGap > 0) XDrawSegments(xDisplay, xBoardWindow, lineGC, - twoBoards & partnerUp ? secondSegments : // [HGM] dual + second ? secondSegments : // [HGM] dual gridSegments, BOARD_HEIGHT + BOARD_WIDTH + 2); - - for (i = 0; i < BOARD_HEIGHT; i++) - for (j = 0; j < BOARD_WIDTH; j++) { - DrawSquare(i, j, board[i][j], 0); - damage[nr][i][j] = False; - } - } - - CopyBoard(lastBoard[nr], board); - lastBoardValid[nr] = 1; - if(nr == 0) { // [HGM] dual: no highlights on second board yet - lastFlipView = flipView; - - /* Draw highlights */ - if (pm1X >= 0 && pm1Y >= 0) { - drawHighlight(pm1X, pm1Y, prelineGC); - } - if (pm2X >= 0 && pm2Y >= 0) { - drawHighlight(pm2X, pm2Y, prelineGC); - } - if (hi1X >= 0 && hi1Y >= 0) { - drawHighlight(hi1X, hi1Y, highlineGC); - } - if (hi2X >= 0 && hi2Y >= 0) { - drawHighlight(hi2X, hi2Y, highlineGC); - } - DrawArrowHighlight(hi1X, hi1Y, hi2X, hi2Y); - } - /* If piece being dragged around board, must redraw that too */ - DrawDragPiece(); - - XSync(xDisplay, False); } @@ -4573,7 +3758,7 @@ XDrawPosition (Widget w, int repaint, Board board) void DrawPositionProc (Widget w, XEvent *event, String *prms, Cardinal *nprms) { - XDrawPosition(w, True, NULL); + DrawPosition(True, NULL); } @@ -5010,48 +4195,6 @@ ThawUI () frozen = 0; } -char * -ModeToWidgetName (GameMode mode) -{ - switch (mode) { - case BeginningOfGame: - if (appData.icsActive) - return "menuMode.ICS Client"; - else if (appData.noChessProgram || - *appData.cmailGameName != NULLCHAR) - return "menuMode.Edit Game"; - else - return "menuMode.Machine Black"; - case MachinePlaysBlack: - return "menuMode.Machine Black"; - case MachinePlaysWhite: - return "menuMode.Machine White"; - case AnalyzeMode: - return "menuMode.Analysis Mode"; - case AnalyzeFile: - return "menuMode.Analyze File"; - case TwoMachinesPlay: - return "menuMode.Two Machines"; - case EditGame: - return "menuMode.Edit Game"; - case PlayFromGameFile: - return "menuFile.Load Game"; - case EditPosition: - return "menuMode.Edit Position"; - case Training: - return "menuMode.Training"; - case IcsPlayingWhite: - case IcsPlayingBlack: - case IcsObserving: - case IcsIdle: - case IcsExamining: - return "menuMode.ICS Client"; - default: - case EndOfGame: - return NULL; - } -} - void ModeHighlight () { @@ -5064,13 +4207,7 @@ ModeHighlight () if (pausing != oldPausing) { oldPausing = pausing; - if (pausing) { - XtSetArg(args[0], XtNleftBitmap, xMarkPixmap); - } else { - XtSetArg(args[0], XtNleftBitmap, None); - } - XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Pause"), - args, 1); + MarkMenuItem("Pause", pausing); if (appData.showButtonBar) { /* Always toggle, don't set. Previous code messes up when @@ -5091,21 +4228,17 @@ ModeHighlight () wname = ModeToWidgetName(oldmode); if (wname != NULL) { - XtSetArg(args[0], XtNleftBitmap, None); - XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1); + MarkMenuItem(wname, False); } wname = ModeToWidgetName(gameMode); if (wname != NULL) { - XtSetArg(args[0], XtNleftBitmap, xMarkPixmap); - XtSetValues(XtNameToWidget(menuBarWidget, wname), args, 1); + MarkMenuItem(wname, True); } oldmode = gameMode; - XtSetArg(args[0], XtNleftBitmap, matchMode && matchGame < appData.matchGames ? xMarkPixmap : None); - XtSetValues(XtNameToWidget(menuBarWidget, "menuMode.Machine Match"), args, 1); + MarkMenuItem("Machine Match", matchMode && matchGame < appData.matchGames); /* Maybe all the enables should be handled here, not just this one */ - XtSetSensitive(XtNameToWidget(menuBarWidget, "menuMode.Training"), - gameMode == Training || gameMode == PlayFromGameFile); + EnableMenuItem("Training", gameMode == Training || gameMode == PlayFromGameFile); } @@ -5131,84 +4264,6 @@ LoadGamePopUp (FILE *f, int gameNumber, char *title) return LoadGame(f, gameNumber, title, FALSE); } -void -LoadGameProc () -{ - if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) { - Reset(FALSE, TRUE); - } - FileNamePopUp(_("Load game file name?"), "", ".pgn .game", LoadGamePopUp, "rb"); -} - -void -LoadNextGameProc () -{ - ReloadGame(1); -} - -void -LoadPrevGameProc () -{ - ReloadGame(-1); -} - -void -ReloadGameProc () -{ - ReloadGame(0); -} - -void -LoadNextPositionProc () -{ - ReloadPosition(1); -} - -void -LoadPrevPositionProc () -{ - ReloadPosition(-1); -} - -void -ReloadPositionProc () -{ - ReloadPosition(0); -} - -void -LoadPositionProc() -{ - if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) { - Reset(FALSE, TRUE); - } - FileNamePopUp(_("Load position file name?"), "", ".fen .epd .pos", LoadPosition, "rb"); -} - -void -SaveGameProc () -{ - FileNamePopUp(_("Save game file name?"), - DefaultFileName(appData.oldSaveStyle ? "game" : "pgn"), - appData.oldSaveStyle ? ".game" : ".pgn", - SaveGame, "a"); -} - -void -SavePositionProc () -{ - FileNamePopUp(_("Save position file name?"), - DefaultFileName(appData.oldSaveStyle ? "pos" : "fen"), - appData.oldSaveStyle ? ".pos" : ".fen", - SavePosition, "a"); -} - -void -ReloadCmailMsgProc () -{ - ReloadCmailMsgEvent(FALSE); -} - /* this variable is shared between CopyPositionProc and SendPositionSelection */ char *selected_fen_position=NULL; @@ -5285,12 +4340,6 @@ CopyPositionProc () NULL/* transfer_done_proc */); } -void -CopyFENToClipboard () -{ // wrapper to make call from back-end possible - CopyPositionProc(); -} - /* function called when the data to Paste is ready */ static void PastePositionCB (Widget w, XtPointer client_data, Atom *selection, @@ -5398,24 +4447,6 @@ CopySomething () /* note: when called from menu all parameters are NULL, so no clue what the * Widget which was clicked on was, or what the click event was */ -void -CopyGameProc () -{ - int ret; - - ret = SaveGameToFile(gameCopyFilename, FALSE); - if (!ret) return; - - CopySomething(); -} - -void -CopyGameListProc () -{ - if(!SaveGameListAsText(fopen(gameCopyFilename, "w"))) return; - CopySomething(); -} - /* function called when the data to Paste is ready */ static void PasteGameCB (Widget w, XtPointer client_data, Atom *selection, @@ -5456,137 +4487,12 @@ PasteGameProc () void -AutoSaveGame () -{ - SaveGameProc(); -} - - -void -QuitProc () -{ - ExitEvent(0); -} - -void QuitWrapper (Widget w, XEvent *event, String *prms, Cardinal *nprms) { QuitProc(); } void -AnalyzeModeProc () -{ - char buf[MSG_SIZ]; - - if (!first.analysisSupport) { - snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy); - DisplayError(buf, 0); - return; - } - /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */ - if (appData.icsActive) { - if (gameMode != IcsObserving) { - snprintf(buf, MSG_SIZ, _("You are not observing a game")); - DisplayError(buf, 0); - /* secure check */ - if (appData.icsEngineAnalyze) { - if (appData.debugMode) - fprintf(debugFP, _("Found unexpected active ICS engine analyze \n")); - ExitAnalyzeMode(); - ModeHighlight(); - } - return; - } - /* if enable, use want disable icsEngineAnalyze */ - if (appData.icsEngineAnalyze) { - ExitAnalyzeMode(); - ModeHighlight(); - return; - } - appData.icsEngineAnalyze = TRUE; - if (appData.debugMode) - fprintf(debugFP, _("ICS engine analyze starting... \n")); - } -#ifndef OPTIONSDIALOG - if (!appData.showThinking) - ShowThinkingProc(); -#endif - - AnalyzeModeEvent(); -} - -void -AnalyzeFileProc () -{ - if (!first.analysisSupport) { - char buf[MSG_SIZ]; - snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy); - DisplayError(buf, 0); - return; - } -// Reset(FALSE, TRUE); -#ifndef OPTIONSDIALOG - if (!appData.showThinking) - ShowThinkingProc(); -#endif - AnalyzeFileEvent(); -// FileNamePopUp(_("File to analyze"), "", ".pgn .game", LoadGamePopUp, "rb"); - AnalysisPeriodicEvent(1); -} - -void -MatchProc () -{ - MatchEvent(2); -} - -void -EditCommentProc () -{ - Arg args[5]; - int j; - if (PopDown(1)) { // popdown succesful - j = 0; - XtSetArg(args[j], XtNleftBitmap, None); j++; - XtSetValues(XtNameToWidget(menuBarWidget, "menuEdit.Edit Comment"), args, j); - XtSetValues(XtNameToWidget(menuBarWidget, "menuView.Show Comments"), args, j); - } else // was not up - EditCommentEvent(); -} - -void -IcsInputBoxProc () -{ - if (!PopDown(4)) ICSInputBoxPopUp(); -} - -void -AdjuWhiteProc () -{ - UserAdjudicationEvent(+1); -} - -void -AdjuBlackProc () -{ - UserAdjudicationEvent(-1); -} - -void -AdjuDrawProc () -{ - UserAdjudicationEvent(0); -} - -void -EnterKeyProc (Widget w, XEvent *event, String *prms, Cardinal *nprms) -{ - if (shellUp[4] == True) - ICSInputSendText(); -} - -void UpKeyProc (Widget w, XEvent *event, String *prms, Cardinal *nprms) { // [HGM] input: let up-arrow recall previous line from history Widget edit; @@ -5630,6 +4536,13 @@ DownKeyProc (Widget w, XEvent *event, String *prms, Cardinal *nprms) } void +EnterKeyProc (Widget w, XEvent *event, String *prms, Cardinal *nprms) +{ + if (shellUp[4] == True) + ICSInputSendText(); +} + +void TempBackwardProc (Widget w, XEvent *event, String *prms, Cardinal *nprms) { if (!TempBackwardActive) { @@ -5655,420 +4568,6 @@ TempForwardProc (Widget w, XEvent *event, String *prms, Cardinal *nprms) } void -RevertProc () -{ - RevertEvent(False); -} - -void -AnnotateProc () -{ - RevertEvent(True); -} - -void -FlipViewProc () -{ - flipView = !flipView; - DrawPosition(True, NULL); -} - -void -PonderNextMoveProc () -{ - Arg args[16]; - - PonderNextMoveEvent(!appData.ponderNextMove); -#ifndef OPTIONSDIALOG - if (appData.ponderNextMove) { - XtSetArg(args[0], XtNleftBitmap, xMarkPixmap); - } else { - XtSetArg(args[0], XtNleftBitmap, None); - } - XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Ponder Next Move"), - args, 1); -#endif -} - -#ifndef OPTIONSDIALOG -void -AlwaysQueenProc () -{ - Arg args[16]; - - appData.alwaysPromoteToQueen = !appData.alwaysPromoteToQueen; - - if (appData.alwaysPromoteToQueen) { - XtSetArg(args[0], XtNleftBitmap, xMarkPixmap); - } else { - XtSetArg(args[0], XtNleftBitmap, None); - } - XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Always Queen"), - args, 1); -} - -void -AnimateDraggingProc () -{ - Arg args[16]; - - appData.animateDragging = !appData.animateDragging; - - if (appData.animateDragging) { - XtSetArg(args[0], XtNleftBitmap, xMarkPixmap); - CreateAnimVars(); - } else { - XtSetArg(args[0], XtNleftBitmap, None); - } - XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Dragging"), - args, 1); -} - -void -AnimateMovingProc () -{ - Arg args[16]; - - appData.animate = !appData.animate; - - if (appData.animate) { - XtSetArg(args[0], XtNleftBitmap, xMarkPixmap); - CreateAnimVars(); - } else { - XtSetArg(args[0], XtNleftBitmap, None); - } - XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Animate Moving"), - args, 1); -} - -void -AutoflagProc () -{ - Arg args[16]; - - appData.autoCallFlag = !appData.autoCallFlag; - - if (appData.autoCallFlag) { - XtSetArg(args[0], XtNleftBitmap, xMarkPixmap); - } else { - XtSetArg(args[0], XtNleftBitmap, None); - } - XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flag"), - args, 1); -} - -void -AutoflipProc () -{ - Arg args[16]; - - appData.autoFlipView = !appData.autoFlipView; - - if (appData.autoFlipView) { - XtSetArg(args[0], XtNleftBitmap, xMarkPixmap); - } else { - XtSetArg(args[0], XtNleftBitmap, None); - } - XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Auto Flip View"), - args, 1); -} - -void -BlindfoldProc () -{ - Arg args[16]; - - appData.blindfold = !appData.blindfold; - - if (appData.blindfold) { - XtSetArg(args[0], XtNleftBitmap, xMarkPixmap); - } else { - XtSetArg(args[0], XtNleftBitmap, None); - } - XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Blindfold"), - args, 1); - - DrawPosition(True, NULL); -} - -void -TestLegalityProc () -{ - Arg args[16]; - - appData.testLegality = !appData.testLegality; - - if (appData.testLegality) { - XtSetArg(args[0], XtNleftBitmap, xMarkPixmap); - } else { - XtSetArg(args[0], XtNleftBitmap, None); - } - XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Test Legality"), - args, 1); -} - - -void -FlashMovesProc () -{ - Arg args[16]; - - if (appData.flashCount == 0) { - appData.flashCount = 3; - } else { - appData.flashCount = -appData.flashCount; - } - - if (appData.flashCount > 0) { - XtSetArg(args[0], XtNleftBitmap, xMarkPixmap); - } else { - XtSetArg(args[0], XtNleftBitmap, None); - } - XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flash Moves"), - args, 1); -} - -#if HIGHDRAG -void -HighlightDraggingProc () -{ - Arg args[16]; - - appData.highlightDragging = !appData.highlightDragging; - - if (appData.highlightDragging) { - XtSetArg(args[0], XtNleftBitmap, xMarkPixmap); - } else { - XtSetArg(args[0], XtNleftBitmap, None); - } - XtSetValues(XtNameToWidget(menuBarWidget, - "menuOptions.Highlight Dragging"), args, 1); -} -#endif - -void -HighlightLastMoveProc () -{ - Arg args[16]; - - appData.highlightLastMove = !appData.highlightLastMove; - - if (appData.highlightLastMove) { - XtSetArg(args[0], XtNleftBitmap, xMarkPixmap); - } else { - XtSetArg(args[0], XtNleftBitmap, None); - } - XtSetValues(XtNameToWidget(menuBarWidget, - "menuOptions.Highlight Last Move"), args, 1); -} - -void -HighlightArrowProc () -{ - Arg args[16]; - - appData.highlightMoveWithArrow = !appData.highlightMoveWithArrow; - - if (appData.highlightMoveWithArrow) { - XtSetArg(args[0], XtNleftBitmap, xMarkPixmap); - } else { - XtSetArg(args[0], XtNleftBitmap, None); - } - XtSetValues(XtNameToWidget(menuBarWidget, - "menuOptions.Arrow"), args, 1); -} - -#if 0 -void -IcsAlarmProc () -{ - Arg args[16]; - - appData.icsAlarm = !appData.icsAlarm; - - if (appData.icsAlarm) { - XtSetArg(args[0], XtNleftBitmap, xMarkPixmap); - } else { - XtSetArg(args[0], XtNleftBitmap, None); - } - XtSetValues(XtNameToWidget(menuBarWidget, - "menuOptions.ICS Alarm"), args, 1); -} -#endif - -void -MoveSoundProc () -{ - Arg args[16]; - - appData.ringBellAfterMoves = !appData.ringBellAfterMoves; - - if (appData.ringBellAfterMoves) { - XtSetArg(args[0], XtNleftBitmap, xMarkPixmap); - } else { - XtSetArg(args[0], XtNleftBitmap, None); - } - XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Move Sound"), - args, 1); -} - -void -OneClickProc () -{ - Arg args[16]; - - appData.oneClick = !appData.oneClick; - - if (appData.oneClick) { - XtSetArg(args[0], XtNleftBitmap, xMarkPixmap); - } else { - XtSetArg(args[0], XtNleftBitmap, None); - } - XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.OneClick"), - args, 1); -} - -void -PeriodicUpdatesProc () -{ - Arg args[16]; - - PeriodicUpdatesEvent(!appData.periodicUpdates); - - if (appData.periodicUpdates) { - XtSetArg(args[0], XtNleftBitmap, xMarkPixmap); - } else { - XtSetArg(args[0], XtNleftBitmap, None); - } - XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Periodic Updates"), - args, 1); -} - -void -PopupExitMessageProc () -{ - Arg args[16]; - - appData.popupExitMessage = !appData.popupExitMessage; - - if (appData.popupExitMessage) { - XtSetArg(args[0], XtNleftBitmap, xMarkPixmap); - } else { - XtSetArg(args[0], XtNleftBitmap, None); - } - XtSetValues(XtNameToWidget(menuBarWidget, - "menuOptions.Popup Exit Message"), args, 1); -} - -void -PopupMoveErrorsProc () -{ - Arg args[16]; - - appData.popupMoveErrors = !appData.popupMoveErrors; - - if (appData.popupMoveErrors) { - XtSetArg(args[0], XtNleftBitmap, xMarkPixmap); - } else { - XtSetArg(args[0], XtNleftBitmap, None); - } - XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Popup Move Errors"), - args, 1); -} - -#if 0 -void -PremoveProc () -{ - Arg args[16]; - - appData.premove = !appData.premove; - - if (appData.premove) { - XtSetArg(args[0], XtNleftBitmap, xMarkPixmap); - } else { - XtSetArg(args[0], XtNleftBitmap, None); - } - XtSetValues(XtNameToWidget(menuBarWidget, - "menuOptions.Premove"), args, 1); -} -#endif - -void -ShowCoordsProc () -{ - Arg args[16]; - - appData.showCoords = !appData.showCoords; - - if (appData.showCoords) { - XtSetArg(args[0], XtNleftBitmap, xMarkPixmap); - } else { - XtSetArg(args[0], XtNleftBitmap, None); - } - XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Show Coords"), - args, 1); - - DrawPosition(True, NULL); -} - -void -ShowThinkingProc () -{ - appData.showThinking = !appData.showThinking; // [HGM] thinking: tken out of ShowThinkingEvent - ShowThinkingEvent(); -} - -void -HideThinkingProc () -{ - Arg args[16]; - - appData.hideThinkingFromHuman = !appData.hideThinkingFromHuman; // [HGM] thinking: tken out of ShowThinkingEvent - ShowThinkingEvent(); - - if (appData.hideThinkingFromHuman) { - XtSetArg(args[0], XtNleftBitmap, xMarkPixmap); - } else { - XtSetArg(args[0], XtNleftBitmap, None); - } - XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Hide Thinking"), - args, 1); -} -#endif - -void -SaveOnExitProc () -{ - Arg args[16]; - - saveSettingsOnExit = !saveSettingsOnExit; - - if (saveSettingsOnExit) { - XtSetArg(args[0], XtNleftBitmap, xMarkPixmap); - } else { - XtSetArg(args[0], XtNleftBitmap, None); - } - XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Save Settings on Exit"), - args, 1); -} - -void -SaveSettingsProc () -{ - SaveSettings(settingsFileName); -} - -void -InfoProc () -{ - char buf[MSG_SIZ]; - snprintf(buf, sizeof(buf), "xterm -e info --directory %s --directory . -f %s &", - INFODIR, INFOFILE); - system(buf); -} - -void ManInner (Widget w, XEvent *event, String *prms, Cardinal *nprms) { // called as key binding char buf[MSG_SIZ]; @@ -6082,80 +4581,6 @@ ManInner (Widget w, XEvent *event, String *prms, Cardinal *nprms) } void -ManProc () -{ // called from menu - ManInner(NULL, NULL, NULL, NULL); -} - -void -BugReportProc () -{ - char buf[MSG_SIZ]; - snprintf(buf, MSG_SIZ, "%s mailto:bug-xboard@gnu.org", appData.sysOpen); - system(buf); -} - -void -GuideProc () -{ - char buf[MSG_SIZ]; - snprintf(buf, MSG_SIZ, "%s http://www.gnu.org/software/xboard/user_guide/UserGuide.html", appData.sysOpen); - system(buf); -} - -void -HomePageProc () -{ - char buf[MSG_SIZ]; - snprintf(buf, MSG_SIZ, "%s http://www.gnu.org/software/xboard/", appData.sysOpen); - system(buf); -} - -void -NewsPageProc () -{ - char buf[MSG_SIZ]; - snprintf(buf, MSG_SIZ, "%s http://www.gnu.org/software/xboard/whats_new/portal.html", appData.sysOpen); - system(buf); -} - -void -AboutProc () -{ - char buf[2 * MSG_SIZ]; -#if ZIPPY - char *zippy = _(" (with Zippy code)"); -#else - char *zippy = ""; -#endif - snprintf(buf, sizeof(buf), -_("%s%s\n\n" -"Copyright 1991 Digital Equipment Corporation\n" -"Enhancements Copyright 1992-2012 Free Software Foundation\n" -"Enhancements Copyright 2005 Alessandro Scotti\n\n" -"%s is free software and carries NO WARRANTY;" -"see the file COPYING for more information.\n\n" -"Visit XBoard on the web at: http://www.gnu.org/software/xboard/\n" -"Check out the newest features at: http://www.gnu.org/software/xboard/whats_new.html\n\n" -"Report bugs via email at: \n\n" - ), - programVersion, zippy, PACKAGE); - ErrorPopUp(_("About XBoard"), buf, FALSE); -} - -void -DebugProc () -{ - appData.debugMode = !appData.debugMode; -} - -void -NothingProc () -{ - return; -} - -void DisplayMessage (char *message, char *extMessage) { /* display a message in the message widget */ @@ -7261,18 +5686,7 @@ OutputToProcessDelayed (ProcRef pr, char *message, int count, int *outError, lon return outCount; } -/**** Animation code by Hugh Fisher, DCS, ANU. - - Known problem: if a window overlapping the board is - moved away while a piece is being animated underneath, - the newly exposed area won't be updated properly. - I can live with this. - - Known problem: if you look carefully at the animation - of pieces in mono mode, they are being drawn as solid - shapes without interior detail while moving. Fixing - this would be a major complication for minimal return. -****/ +/**** Animation code by Hugh Fisher, DCS, ANU. ****/ /* Masks for XPM pieces. Black and white pieces can have different shapes, but in the interest of retaining my @@ -7281,6 +5695,8 @@ OutputToProcessDelayed (ProcRef pr, char *message, int count, int *outError, lon background square colors/images. */ static int xpmDone = 0; +static Pixmap animBufs[3*NrOfAnims]; // newBuf, saveBuf +static GC animGCs[3*NrOfAnims]; // blitGC, pieceGC, outlineGC; static void CreateAnimMasks (int pieceDepth) @@ -7361,15 +5777,16 @@ CreateAnimMasks (int pieceDepth) } static void -InitAnimState (AnimState *anim, XWindowAttributes *info) +InitAnimState (AnimNr anr, XWindowAttributes *info) { XtGCMask mask; XGCValues values; /* Each buffer is square size, same depth as window */ - anim->saveBuf = XCreatePixmap(xDisplay, xBoardWindow, + animBufs[anr+4] = xBoardWindow; + animBufs[anr+2] = XCreatePixmap(xDisplay, xBoardWindow, squareSize, squareSize, info->depth); - anim->newBuf = XCreatePixmap(xDisplay, xBoardWindow, + animBufs[anr] = XCreatePixmap(xDisplay, xBoardWindow, squareSize, squareSize, info->depth); /* Create a plain GC for blitting */ @@ -7380,17 +5797,17 @@ InitAnimState (AnimState *anim, XWindowAttributes *info) values.function = GXcopy; values.plane_mask = AllPlanes; values.graphics_exposures = False; - anim->blitGC = XCreateGC(xDisplay, xBoardWindow, mask, &values); + animGCs[anr] = XCreateGC(xDisplay, xBoardWindow, mask, &values); /* Piece will be copied from an existing context at the start of each new animation/drag. */ - anim->pieceGC = XCreateGC(xDisplay, xBoardWindow, 0, &values); + animGCs[anr+2] = XCreateGC(xDisplay, xBoardWindow, 0, &values); /* Outline will be a read-only copy of an existing */ - anim->outlineGC = None; + animGCs[anr+4] = None; } -static void +void CreateAnimVars () { XWindowAttributes info; @@ -7399,8 +5816,8 @@ CreateAnimVars () if(xpmDone) oldVariant = gameInfo.variant; // first time pieces might not be created yet XGetWindowAttributes(xDisplay, xBoardWindow, &info); - InitAnimState(&game, &info); - InitAnimState(&player, &info); + InitAnimState(Game, &info); + InitAnimState(Player, &info); /* For XPM pieces, we need bitmaps to use as masks. */ if (useImages) @@ -7419,7 +5836,7 @@ FrameAlarm (int sig) signal(SIGALRM, FrameAlarm); } -static void +void FrameDelay (int time) { struct itimerval delay; @@ -7443,7 +5860,7 @@ FrameDelay (int time) #else -static void +void FrameDelay (int time) { XSync(xDisplay, False); @@ -7453,159 +5870,6 @@ FrameDelay (int time) #endif -void -DoSleep (int n) -{ - FrameDelay(n); -} - -/* Convert board position to corner of screen rect and color */ - -static void -ScreenSquare (int column, int row, XPoint *pt, int *color) -{ - if (flipView) { - pt->x = lineGap + ((BOARD_WIDTH-1)-column) * (squareSize + lineGap); - pt->y = lineGap + row * (squareSize + lineGap); - } else { - pt->x = lineGap + column * (squareSize + lineGap); - pt->y = lineGap + ((BOARD_HEIGHT-1)-row) * (squareSize + lineGap); - } - *color = SquareColor(row, column); -} - -/* Convert window coords to square */ - -static void -BoardSquare (int x, int y, int *column, int *row) -{ - *column = EventToSquare(x, BOARD_WIDTH); - if (flipView && *column >= 0) - *column = BOARD_WIDTH - 1 - *column; - *row = EventToSquare(y, BOARD_HEIGHT); - if (!flipView && *row >= 0) - *row = BOARD_HEIGHT - 1 - *row; -} - -/* Utilities */ - -#undef Max /* just in case */ -#undef Min -#define Max(a, b) ((a) > (b) ? (a) : (b)) -#define Min(a, b) ((a) < (b) ? (a) : (b)) - -static void -SetRect (XRectangle *rect, int x, int y, int width, int height) -{ - rect->x = x; - rect->y = y; - rect->width = width; - rect->height = height; -} - -/* Test if two frames overlap. If they do, return - intersection rect within old and location of - that rect within new. */ - -static Boolean -Intersect ( XPoint *old, XPoint *new, int size, XRectangle *area, XPoint *pt) -{ - if (old->x > new->x + size || new->x > old->x + size || - old->y > new->y + size || new->y > old->y + size) { - return False; - } else { - SetRect(area, Max(new->x - old->x, 0), Max(new->y - old->y, 0), - size - abs(old->x - new->x), size - abs(old->y - new->y)); - pt->x = Max(old->x - new->x, 0); - pt->y = Max(old->y - new->y, 0); - return True; - } -} - -/* For two overlapping frames, return the rect(s) - in the old that do not intersect with the new. */ - -static void -CalcUpdateRects (XPoint *old, XPoint *new, int size, XRectangle update[], int *nUpdates) -{ - int count; - - /* If old = new (shouldn't happen) then nothing to draw */ - if (old->x == new->x && old->y == new->y) { - *nUpdates = 0; - return; - } - /* Work out what bits overlap. Since we know the rects - are the same size we don't need a full intersect calc. */ - count = 0; - /* Top or bottom edge? */ - if (new->y > old->y) { - SetRect(&(update[count]), old->x, old->y, size, new->y - old->y); - count ++; - } else if (old->y > new->y) { - SetRect(&(update[count]), old->x, old->y + size - (old->y - new->y), - size, old->y - new->y); - count ++; - } - /* Left or right edge - don't overlap any update calculated above. */ - if (new->x > old->x) { - SetRect(&(update[count]), old->x, Max(new->y, old->y), - new->x - old->x, size - abs(new->y - old->y)); - count ++; - } else if (old->x > new->x) { - SetRect(&(update[count]), new->x + size, Max(new->y, old->y), - old->x - new->x, size - abs(new->y - old->y)); - count ++; - } - /* Done */ - *nUpdates = count; -} - -/* Generate a series of frame coords from start->mid->finish. - The movement rate doubles until the half way point is - reached, then halves back down to the final destination, - which gives a nice slow in/out effect. The algorithmn - may seem to generate too many intermediates for short - moves, but remember that the purpose is to attract the - viewers attention to the piece about to be moved and - then to where it ends up. Too few frames would be less - noticeable. */ - -static void -Tween (XPoint *start, XPoint *mid, XPoint *finish, int factor, XPoint frames[], int *nFrames) -{ - int fraction, n, count; - - count = 0; - - /* Slow in, stepping 1/16th, then 1/8th, ... */ - fraction = 1; - for (n = 0; n < factor; n++) - fraction *= 2; - for (n = 0; n < factor; n++) { - frames[count].x = start->x + (mid->x - start->x) / fraction; - frames[count].y = start->y + (mid->y - start->y) / fraction; - count ++; - fraction = fraction / 2; - } - - /* Midpoint */ - frames[count] = *mid; - count ++; - - /* Slow out, stepping 1/2, then 1/4, ... */ - fraction = 2; - for (n = 0; n < factor; n++) { - frames[count].x = finish->x - (finish->x - mid->x) / fraction; - frames[count].y = finish->y - (finish->y - mid->y) / fraction; - count ++; - fraction = fraction * 2; - } - *nFrames = count; -} - -/* Draw a piece on the screen without disturbing what's there */ - static void SelectGCMask (ChessSquare piece, GC *clip, GC *outline, Pixmap *mask) { @@ -7674,329 +5938,32 @@ OverlayPiece (ChessSquare piece, GC clip, GC outline, Drawable dest) } } -/* Animate the movement of a single piece */ - -static void -BeginAnimation (AnimState *anim, ChessSquare piece, int startColor, XPoint *start) -{ - Pixmap mask; - - if(appData.upsideDown && flipView) piece += piece < BlackPawn ? BlackPawn : -BlackPawn; - /* The old buffer is initialised with the start square (empty) */ - BlankSquare(start->x, start->y, startColor, EmptySquare, anim->saveBuf, 0); - anim->prevFrame = *start; - - /* The piece will be drawn using its own bitmap as a matte */ - SelectGCMask(piece, &anim->pieceGC, &anim->outlineGC, &mask); - XSetClipMask(xDisplay, anim->pieceGC, mask); -} - -static void -AnimationFrame (AnimState *anim, XPoint *frame, ChessSquare piece) -{ - XRectangle updates[4]; - XRectangle overlap; - XPoint pt; - int count, i; - - /* Save what we are about to draw into the new buffer */ - XCopyArea(xDisplay, xBoardWindow, anim->newBuf, anim->blitGC, - frame->x, frame->y, squareSize, squareSize, - 0, 0); - - /* Erase bits of the previous frame */ - if (Intersect(&anim->prevFrame, frame, squareSize, &overlap, &pt)) { - /* Where the new frame overlapped the previous, - the contents in newBuf are wrong. */ - XCopyArea(xDisplay, anim->saveBuf, anim->newBuf, anim->blitGC, - overlap.x, overlap.y, - overlap.width, overlap.height, - pt.x, pt.y); - /* Repaint the areas in the old that don't overlap new */ - CalcUpdateRects(&anim->prevFrame, frame, squareSize, updates, &count); - for (i = 0; i < count; i++) - XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC, - updates[i].x - anim->prevFrame.x, - updates[i].y - anim->prevFrame.y, - updates[i].width, updates[i].height, - updates[i].x, updates[i].y); - } else { - /* Easy when no overlap */ - XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC, - 0, 0, squareSize, squareSize, - anim->prevFrame.x, anim->prevFrame.y); - } - - /* Save this frame for next time round */ - XCopyArea(xDisplay, anim->newBuf, anim->saveBuf, anim->blitGC, - 0, 0, squareSize, squareSize, - 0, 0); - anim->prevFrame = *frame; - - /* Draw piece over original screen contents, not current, - and copy entire rect. Wipes out overlapping piece images. */ - OverlayPiece(piece, anim->pieceGC, anim->outlineGC, anim->newBuf); - XCopyArea(xDisplay, anim->newBuf, xBoardWindow, anim->blitGC, - 0, 0, squareSize, squareSize, - frame->x, frame->y); -} - -static void -EndAnimation (AnimState *anim, XPoint *finish) -{ - XRectangle updates[4]; - XRectangle overlap; - XPoint pt; - int count, i; - - /* The main code will redraw the final square, so we - only need to erase the bits that don't overlap. */ - if (Intersect(&anim->prevFrame, finish, squareSize, &overlap, &pt)) { - CalcUpdateRects(&anim->prevFrame, finish, squareSize, updates, &count); - for (i = 0; i < count; i++) - XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC, - updates[i].x - anim->prevFrame.x, - updates[i].y - anim->prevFrame.y, - updates[i].width, updates[i].height, - updates[i].x, updates[i].y); - } else { - XCopyArea(xDisplay, anim->saveBuf, xBoardWindow, anim->blitGC, - 0, 0, squareSize, squareSize, - anim->prevFrame.x, anim->prevFrame.y); - } -} - -static void -FrameSequence (AnimState *anim, ChessSquare piece, int startColor, XPoint *start, XPoint *finish, XPoint frames[], int nFrames) -{ - int n; - - BeginAnimation(anim, piece, startColor, start); - for (n = 0; n < nFrames; n++) { - AnimationFrame(anim, &(frames[n]), piece); - FrameDelay(appData.animSpeed); - } - EndAnimation(anim, finish); -} - void -AnimateAtomicCapture (Board board, int fromX, int fromY, int toX, int toY) +InsertPiece (AnimNr anr, ChessSquare piece) { - int i, x, y; - ChessSquare piece = board[fromY][toY]; - board[fromY][toY] = EmptySquare; - DrawPosition(FALSE, board); - if (flipView) { - x = lineGap + ((BOARD_WIDTH-1)-toX) * (squareSize + lineGap); - y = lineGap + toY * (squareSize + lineGap); - } else { - x = lineGap + toX * (squareSize + lineGap); - y = lineGap + ((BOARD_HEIGHT-1)-toY) * (squareSize + lineGap); - } - for(i=1; i<4*kFactor; i++) { - int r = squareSize * 9 * i/(20*kFactor - 5); - XFillArc(xDisplay, xBoardWindow, highlineGC, - x + squareSize/2 - r, y+squareSize/2 - r, 2*r, 2*r, 0, 64*360); - FrameDelay(appData.animSpeed); - } - board[fromY][toY] = piece; + OverlayPiece(piece, animGCs[anr+2], animGCs[anr+4], animBufs[anr]); } -/* Main control logic for deciding what to animate and how */ - void -AnimateMove (Board board, int fromX, int fromY, int toX, int toY) +DrawBlank (AnimNr anr, int x, int y, int startColor) { - ChessSquare piece; - int hop; - XPoint start, finish, mid; - XPoint frames[kFactor * 2 + 1]; - int nFrames, startColor, endColor; - - /* Are we animating? */ - if (!appData.animate || appData.blindfold) - return; - - if(board[toY][toX] == WhiteRook && board[fromY][fromX] == WhiteKing || - board[toY][toX] == BlackRook && board[fromY][fromX] == BlackKing) - return; // [HGM] FRC: no animtion of FRC castlings, as to-square is not true to-square - - if (fromY < 0 || fromX < 0 || toX < 0 || toY < 0) return; - piece = board[fromY][fromX]; - if (piece >= EmptySquare) return; - -#if DONT_HOP - hop = FALSE; -#else - hop = abs(fromX-toX) == 1 && abs(fromY-toY) == 2 || abs(fromX-toX) == 2 && abs(fromY-toY) == 1; -#endif - - ScreenSquare(fromX, fromY, &start, &startColor); - ScreenSquare(toX, toY, &finish, &endColor); - - if (hop) { - /* Knight: make straight movement then diagonal */ - if (abs(toY - fromY) < abs(toX - fromX)) { - mid.x = start.x + (finish.x - start.x) / 2; - mid.y = start.y; - } else { - mid.x = start.x; - mid.y = start.y + (finish.y - start.y) / 2; - } - } else { - mid.x = start.x + (finish.x - start.x) / 2; - mid.y = start.y + (finish.y - start.y) / 2; - } - - /* Don't use as many frames for very short moves */ - if (abs(toY - fromY) + abs(toX - fromX) <= 2) - Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames); - else - Tween(&start, &mid, &finish, kFactor, frames, &nFrames); - FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames); - if(Explode(board, fromX, fromY, toX, toY)) { // mark as damaged - int i,j; - for(i=0; i= 0 && player.dragPiece < EmptySquare) { - player.dragActive = True; - BeginAnimation(&player, player.dragPiece, color, &corner); - /* Mark this square as needing to be redrawn. Note that - we don't remove the piece though, since logically (ie - as seen by opponent) the move hasn't been made yet. */ - if(boardX == BOARD_RGHT+1 && PieceForSquare(boardX-1, boardY) > 1 || - boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1) - XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC, - corner.x, corner.y, squareSize, squareSize, - 0, 0); // [HGM] zh: unstack in stead of grab - if(gatingPiece != EmptySquare) { - /* Kludge alert: When gating we want the introduced - piece to appear on the from square. To generate an - image of it, we draw it on the board, copy the image, - and draw the original piece again. */ - ChessSquare piece = boards[currentMove][boardY][boardX]; - DrawSquare(boardY, boardX, gatingPiece, 0); - XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC, - corner.x, corner.y, squareSize, squareSize, 0, 0); - DrawSquare(boardY, boardX, piece, 0); - } - damage[0][boardY][boardX] = True; - } else { - player.dragActive = False; - } + XCopyArea(xDisplay, animBufs[anr+srcBuf], animBufs[anr+destBuf], animGCs[anr], + srcX, srcY, width, height, destX, destY); } void -ChangeDragPiece (ChessSquare piece) +SetDragPiece (AnimNr anr, ChessSquare piece) { Pixmap mask; - player.dragPiece = piece; /* The piece will be drawn using its own bitmap as a matte */ - SelectGCMask(piece, &player.pieceGC, &player.outlineGC, &mask); - XSetClipMask(xDisplay, player.pieceGC, mask); -} - -static void -DragPieceMove (int x, int y) -{ - XPoint corner; - - /* Are we animating? */ - if (!appData.animateDragging || appData.blindfold) - return; - - /* Sanity check */ - if (! player.dragActive) - return; - /* Move piece, maintaining same relative position - of mouse within square */ - corner.x = x - player.mouseDelta.x; - corner.y = y - player.mouseDelta.y; - AnimationFrame(&player, &corner, player.dragPiece); -#if HIGHDRAG*0 - if (appData.highlightDragging) { - int boardX, boardY; - BoardSquare(x, y, &boardX, &boardY); - SetHighlights(fromX, fromY, boardX, boardY); - } -#endif -} - -void -DragPieceEnd (int x, int y) -{ - int boardX, boardY, color; - XPoint corner; - - /* Are we animating? */ - if (!appData.animateDragging || appData.blindfold) - return; - - /* Sanity check */ - if (! player.dragActive) - return; - /* Last frame in sequence is square piece is - placed on, which may not match mouse exactly. */ - BoardSquare(x, y, &boardX, &boardY); - ScreenSquare(boardX, boardY, &corner, &color); - EndAnimation(&player, &corner); - - /* Be sure end square is redrawn */ - damage[0][boardY][boardX] = True; - - /* This prevents weird things happening with fast successive - clicks which on my Sun at least can cause motion events - without corresponding press/release. */ - player.dragActive = False; -} - -/* Handle expose event while piece being dragged */ - -static void -DrawDragPiece () -{ - if (!player.dragActive || appData.blindfold) - return; - - /* What we're doing: logically, the move hasn't been made yet, - so the piece is still in it's original square. But visually - it's being dragged around the board. So we erase the square - that the piece is on and draw it at the last known drag point. */ - BlankSquare(player.startSquare.x, player.startSquare.y, - player.startColor, EmptySquare, xBoardWindow, 1); - AnimationFrame(&player, &player.prevFrame, player.dragPiece); - damage[0][player.startBoardY][player.startBoardX] = TRUE; + SelectGCMask(piece, &animGCs[anr+2], &animGCs[anr+4], &mask); + XSetClipMask(xDisplay, animGCs[anr+2], mask); } #include @@ -8039,209 +6006,14 @@ NotifyFrontendLogin () /* [AS] Arrow highlighting support */ -static double A_WIDTH = 5; /* Width of arrow body */ - -#define A_HEIGHT_FACTOR 6 /* Length of arrow "point", relative to body width */ -#define A_WIDTH_FACTOR 3 /* Width of arrow "point", relative to body width */ - -static double -Sqr (double x) -{ - return x*x; -} - -static int -Round (double x) -{ - return (int) (x + 0.5); -} - -void -SquareToPos (int rank, int file, int *x, int *y) -{ - if (flipView) { - *x = lineGap + ((BOARD_WIDTH-1)-file) * (squareSize + lineGap); - *y = lineGap + rank * (squareSize + lineGap); - } else { - *x = lineGap + file * (squareSize + lineGap); - *y = lineGap + ((BOARD_HEIGHT-1)-rank) * (squareSize + lineGap); - } -} - -/* Draw an arrow between two points using current settings */ -void -DrawArrowBetweenPoints (int s_x, int s_y, int d_x, int d_y) -{ - XPoint arrow[8]; - double dx, dy, j, k, x, y; - - if( d_x == s_x ) { - int h = (d_y > s_y) ? +A_WIDTH*A_HEIGHT_FACTOR : -A_WIDTH*A_HEIGHT_FACTOR; - - arrow[0].x = s_x + A_WIDTH + 0.5; - arrow[0].y = s_y; - - arrow[1].x = s_x + A_WIDTH + 0.5; - arrow[1].y = d_y - h; - - arrow[2].x = arrow[1].x + A_WIDTH*(A_WIDTH_FACTOR-1) + 0.5; - arrow[2].y = d_y - h; - - arrow[3].x = d_x; - arrow[3].y = d_y; - - arrow[5].x = arrow[1].x - 2*A_WIDTH + 0.5; - arrow[5].y = d_y - h; - - arrow[4].x = arrow[5].x - A_WIDTH*(A_WIDTH_FACTOR-1) + 0.5; - arrow[4].y = d_y - h; - - arrow[6].x = arrow[1].x - 2*A_WIDTH + 0.5; - arrow[6].y = s_y; - } - else if( d_y == s_y ) { - int w = (d_x > s_x) ? +A_WIDTH*A_HEIGHT_FACTOR : -A_WIDTH*A_HEIGHT_FACTOR; - - arrow[0].x = s_x; - arrow[0].y = s_y + A_WIDTH + 0.5; - - arrow[1].x = d_x - w; - arrow[1].y = s_y + A_WIDTH + 0.5; - - arrow[2].x = d_x - w; - arrow[2].y = arrow[1].y + A_WIDTH*(A_WIDTH_FACTOR-1) + 0.5; - - arrow[3].x = d_x; - arrow[3].y = d_y; - - arrow[5].x = d_x - w; - arrow[5].y = arrow[1].y - 2*A_WIDTH + 0.5; - - arrow[4].x = d_x - w; - arrow[4].y = arrow[5].y - A_WIDTH*(A_WIDTH_FACTOR-1) + 0.5; - - arrow[6].x = s_x; - arrow[6].y = arrow[1].y - 2*A_WIDTH + 0.5; - } - else { - /* [AS] Needed a lot of paper for this! :-) */ - dy = (double) (d_y - s_y) / (double) (d_x - s_x); - dx = (double) (s_x - d_x) / (double) (s_y - d_y); - - j = sqrt( Sqr(A_WIDTH) / (1.0 + Sqr(dx)) ); - - k = sqrt( Sqr(A_WIDTH*A_HEIGHT_FACTOR) / (1.0 + Sqr(dy)) ); - - x = s_x; - y = s_y; - - arrow[0].x = Round(x - j); - arrow[0].y = Round(y + j*dx); - - arrow[1].x = Round(arrow[0].x + 2*j); // [HGM] prevent width to be affected by rounding twice - arrow[1].y = Round(arrow[0].y - 2*j*dx); - - if( d_x > s_x ) { - x = (double) d_x - k; - y = (double) d_y - k*dy; - } - else { - x = (double) d_x + k; - y = (double) d_y + k*dy; - } - - x = Round(x); y = Round(y); // [HGM] make sure width of shaft is rounded the same way on both ends - - arrow[6].x = Round(x - j); - arrow[6].y = Round(y + j*dx); - - arrow[2].x = Round(arrow[6].x + 2*j); - arrow[2].y = Round(arrow[6].y - 2*j*dx); - - arrow[3].x = Round(arrow[2].x + j*(A_WIDTH_FACTOR-1)); - arrow[3].y = Round(arrow[2].y - j*(A_WIDTH_FACTOR-1)*dx); - - arrow[4].x = d_x; - arrow[4].y = d_y; - - arrow[5].x = Round(arrow[6].x - j*(A_WIDTH_FACTOR-1)); - arrow[5].y = Round(arrow[6].y + j*(A_WIDTH_FACTOR-1)*dx); - } - - XFillPolygon(xDisplay, xBoardWindow, highlineGC, arrow, 7, Nonconvex, CoordModeOrigin); - if(appData.monoMode) arrow[7] = arrow[0], XDrawLines(xDisplay, xBoardWindow, darkSquareGC, arrow, 8, CoordModeOrigin); -// Polygon( hdc, arrow, 7 ); -} - void -ArrowDamage (int s_col, int s_row, int d_col, int d_row) +DrawPolygon (Pnt arrow[], int nr) { - int hor, vert, i; - hor = 64*s_col + 32; vert = 64*s_row + 32; - for(i=0; i<= 64; i++) { - damage[0][vert+6>>6][hor+6>>6] = True; - damage[0][vert-6>>6][hor+6>>6] = True; - damage[0][vert+6>>6][hor-6>>6] = True; - damage[0][vert-6>>6][hor-6>>6] = True; - hor += d_col - s_col; vert += d_row - s_row; - } -} - -/* [AS] Draw an arrow between two squares */ -void -DrawArrowBetweenSquares (int s_col, int s_row, int d_col, int d_row) -{ - int s_x, s_y, d_x, d_y; - - if( s_col == d_col && s_row == d_row ) { - return; - } - - /* Get source and destination points */ - SquareToPos( s_row, s_col, &s_x, &s_y); - SquareToPos( d_row, d_col, &d_x, &d_y); - - if( d_y > s_y ) { - d_y += squareSize / 2 - squareSize / 4; // [HGM] round towards same centers on all sides! - } - else if( d_y < s_y ) { - d_y += squareSize / 2 + squareSize / 4; - } - else { - d_y += squareSize / 2; - } - - if( d_x > s_x ) { - d_x += squareSize / 2 - squareSize / 4; - } - else if( d_x < s_x ) { - d_x += squareSize / 2 + squareSize / 4; - } - else { - d_x += squareSize / 2; - } - - s_x += squareSize / 2; - s_y += squareSize / 2; - - /* Adjust width */ - A_WIDTH = squareSize / 14.; //[HGM] make float - - DrawArrowBetweenPoints( s_x, s_y, d_x, d_y ); - ArrowDamage(s_col, s_row, d_col, d_row); -} - -Boolean -IsDrawArrowEnabled () -{ - return appData.highlightMoveWithArrow && squareSize >= 32; -} - -void -DrawArrowHighlight (int fromX, int fromY, int toX,int toY) -{ - if( IsDrawArrowEnabled() && fromX >= 0 && fromY >= 0 && toX >= 0 && toY >= 0) - DrawArrowBetweenSquares(fromX, fromY, toX, toY); + XPoint pts[10]; + int i; + for(i=0; i<10; i++) pts[i].x = arrow[i].x, pts[i].y = arrow[i].y; + XFillPolygon(xDisplay, xBoardWindow, highlineGC, pts, nr, Nonconvex, CoordModeOrigin); + if(appData.monoMode) arrow[nr] = arrow[0], XDrawLines(xDisplay, xBoardWindow, darkSquareGC, pts, nr+1, CoordModeOrigin); } void