X-Git-Url: http://winboard.nl/cgi-bin?a=blobdiff_plain;f=xboard.c;h=ae13c6f5000152a492f0dbc11ab2814f7a6fa20e;hb=c551a728b8fa7649b043fffb32b7f1d11c67b38a;hp=8106b9c80e7ff0419f0f99f065160189ad399d81;hpb=c2e98d83b9ec8220a8d43cdac2fcde23a0314da9;p=xboard.git diff --git a/xboard.c b/xboard.c index 8106b9c..ae13c6f 100644 --- a/xboard.c +++ b/xboard.c @@ -5,7 +5,7 @@ * Massachusetts. * * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006, - * 2007, 2008, 2009 Free Software Foundation, Inc. + * 2007, 2008, 2009, 2010 Free Software Foundation, Inc. * * The following terms apply to Digital Equipment Corporation's copyright * interest in XBoard: @@ -233,6 +233,8 @@ typedef struct { } Menu; int main P((int argc, char **argv)); +FILE * XsraSelFile P((Widget w, char *prompt, char *ok, char *cancel, char *failed, + char *init_path, char *mode, int (*show_entry)(), char **name_return)); RETSIGTYPE CmailSigHandler P((int sig)); RETSIGTYPE IntSigHandler P((int sig)); RETSIGTYPE TermSizeSigHandler P((int sig)); @@ -260,6 +262,10 @@ void AnimateUserMove P((Widget w, XEvent * event, String * params, Cardinal * nParams)); void HandlePV P((Widget w, XEvent * event, String * params, Cardinal * nParams)); +void SelectPV P((Widget w, XEvent * event, + String * params, Cardinal * nParams)); +void StopPV P((Widget w, XEvent * event, + String * params, Cardinal * nParams)); void WhiteClock P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); void BlackClock P((Widget w, XEvent *event, @@ -268,6 +274,8 @@ void DrawPositionProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); void XDrawPosition P((Widget w, /*Boolean*/int repaint, Board board)); +void CommentClick P((Widget w, XEvent * event, + String * params, Cardinal * nParams)); void CommentPopUp P((char *title, char *label)); void CommentPopDown P((void)); void CommentCallback P((Widget w, XtPointer client_data, @@ -355,15 +363,19 @@ void AdjuWhiteProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); void AdjuBlackProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); void AdjuDrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); +void UpKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); +void DownKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); void StopObservingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); void StopExaminingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); +void UploadProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); void BackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); void ForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); void ToStartProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); void ToEndProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); void RevertProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); +void AnnotateProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); void TruncateGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); void RetractMoveProc P((Widget w, XEvent *event, String *prms, @@ -444,6 +456,8 @@ void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)) void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); +void GameListOptionsPopUp P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); +void GameListOptionsPopDown P(()); void ShufflePopDown P(()); void EnginePopDown P(()); void UciPopDown P(()); @@ -474,6 +488,8 @@ 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]; Font clockFontID, coordFontID, countFontID; @@ -636,6 +652,7 @@ MenuItem actionMenu[] = { {"----", NothingProc}, {N_("Stop Observing"), StopObservingProc}, {N_("Stop Examining"), StopExaminingProc}, + {N_("Upload to Examine"), UploadProc}, {"----", NothingProc}, {N_("Adjudicate to White"), AdjuWhiteProc}, {N_("Adjudicate to Black"), AdjuBlackProc}, @@ -649,6 +666,7 @@ MenuItem stepMenu[] = { {N_("Back to Start"), ToStartProc}, {N_("Forward to End"), ToEndProc}, {N_("Revert"), RevertProc}, + {N_("Annotate"), AnnotateProc}, {N_("Truncate Game"), TruncateGameProc}, {"----", NothingProc}, {N_("Move Now"), MoveNowProc}, @@ -664,6 +682,7 @@ MenuItem optionsMenu[] = { {N_("Engine #1 Settings ..."), FirstSettingsProc}, {N_("Engine #2 Settings ..."), SecondSettingsProc}, {N_("Time Control ..."), TimeControlProc}, + {N_("Game List ..."), GameListOptionsPopUp}, {"----", NothingProc}, {N_("Always Queen"), AlwaysQueenProc}, {N_("Animate Dragging"), AnimateDraggingProc}, @@ -837,7 +856,8 @@ XtActionsRec boardActions[] = { { "HandleUserMove", HandleUserMove }, { "AnimateUserMove", AnimateUserMove }, { "HandlePV", HandlePV }, - { "UnLoadPV", UnLoadPV }, + { "SelectPV", SelectPV }, + { "StopPV", StopPV }, { "FileNameAction", FileNameAction }, { "AskQuestionProc", AskQuestionProc }, { "AskQuestionReplyAction", AskQuestionReplyAction }, @@ -846,10 +866,12 @@ XtActionsRec boardActions[] = { { "BlackClock", BlackClock }, { "Iconify", Iconify }, { "ResetProc", ResetProc }, + { "NewVariantProc", NewVariantProc }, { "LoadGameProc", LoadGameProc }, { "LoadNextGameProc", LoadNextGameProc }, { "LoadPrevGameProc", LoadPrevGameProc }, { "LoadSelectedProc", LoadSelectedProc }, + { "SetFilterProc", SetFilterProc }, { "ReloadGameProc", ReloadGameProc }, { "LoadPositionProc", LoadPositionProc }, { "LoadNextPositionProc", LoadNextPositionProc }, @@ -894,16 +916,23 @@ XtActionsRec boardActions[] = { { "AdjuBlackProc", AdjuBlackProc }, { "AdjuDrawProc", AdjuDrawProc }, { "EnterKeyProc", EnterKeyProc }, + { "UpKeyProc", UpKeyProc }, + { "DownKeyProc", DownKeyProc }, { "StopObservingProc", StopObservingProc }, { "StopExaminingProc", StopExaminingProc }, + { "UploadProc", UploadProc }, { "BackwardProc", BackwardProc }, { "ForwardProc", ForwardProc }, { "ToStartProc", ToStartProc }, { "ToEndProc", ToEndProc }, { "RevertProc", RevertProc }, + { "AnnotateProc", AnnotateProc }, { "TruncateGameProc", TruncateGameProc }, { "MoveNowProc", MoveNowProc }, { "RetractMoveProc", RetractMoveProc }, + { "EngineMenuProc", (XtActionProc) EngineMenuProc }, + { "UciMenuProc", (XtActionProc) UciMenuProc }, + { "TimeControlProc", (XtActionProc) TimeControlProc }, { "AlwaysQueenProc", AlwaysQueenProc }, { "AnimateDraggingProc", AnimateDraggingProc }, { "AnimateMovingProc", AnimateMovingProc }, @@ -943,6 +972,7 @@ XtActionsRec boardActions[] = { { "AboutProc", AboutProc }, { "DebugProc", DebugProc }, { "NothingProc", NothingProc }, + { "CommentClick", (XtActionProc) CommentClick }, { "CommentPopDown", (XtActionProc) CommentPopDown }, { "EditCommentPopDown", (XtActionProc) EditCommentPopDown }, { "TagsPopDown", (XtActionProc) TagsPopDown }, @@ -951,6 +981,7 @@ XtActionsRec boardActions[] = { { "FileNamePopDown", (XtActionProc) FileNamePopDown }, { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown }, { "GameListPopDown", (XtActionProc) GameListPopDown }, + { "GameListOptionsPopDown", (XtActionProc) GameListOptionsPopDown }, { "PromotionPopDown", (XtActionProc) PromotionPopDown }, { "HistoryPopDown", (XtActionProc) HistoryPopDown }, { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown }, @@ -965,26 +996,64 @@ XtActionsRec boardActions[] = { }; char globalTranslations[] = - ":R: ResignProc() \n \ - :r: ResetProc() \n \ - :g: LoadGameProc() \n \ - :N: LoadNextGameProc() \n \ - :P: LoadPrevGameProc() \n \ - :Q: QuitProc() \n \ - :F: ToEndProc() \n \ - :f: ForwardProc() \n \ - :B: ToStartProc() \n \ - :b: BackwardProc() \n \ - :p: PauseProc() \n \ - :d: DrawProc() \n \ - :t: CallFlagProc() \n \ - :i: Iconify() \n \ - :c: Iconify() \n \ - :v: FlipViewProc() \n \ - Control_L: BackwardProc() \n \ - Control_L: ForwardProc() \n \ - Control_R: BackwardProc() \n \ - Control_R: ForwardProc() \n \ + ":F9: ResignProc() \n \ + :Ctrln: ResetProc() \n \ + :MetaV: NewVariantProc() \n \ + :Ctrlo: LoadGameProc() \n \ + :MetaNext: LoadNextGameProc() \n \ + :MetaPrior: LoadPrevGameProc() \n \ + :Ctrls: SaveGameProc() \n \ + :Ctrlc: CopyGameProc() \n \ + :Ctrlv: PasteGameProc() \n \ + :CtrlO: LoadPositionProc() \n \ + :Shift MetaNext: LoadNextPositionProc() \n \ + :Shift MetaPrior: LoadPrevPositionProc() \n \ + :CtrlS: SavePositionProc() \n \ + :CtrlC: CopyPositionProc() \n \ + :CtrlV: PastePositionProc() \n \ + :Ctrlq: QuitProc() \n \ + :Ctrlw: MachineWhiteProc() \n \ + :Ctrlb: MachineBlackProc() \n \ + :Ctrlt: TwoMachinesProc() \n \ + :Ctrla: AnalysisModeProc() \n \ + :Ctrlf: AnalyzeFileProc() \n \ + :Ctrle: EditGameProc() \n \ + :CtrlE: EditPositionProc() \n \ + :MetaO: EngineOutputProc() \n \ + :MetaE: EvalGraphProc() \n \ + :MetaG: ShowGameListProc() \n \ + :MetaH: ShowMoveListProc() \n \ + :Pause: PauseProc() \n \ + :F3: AcceptProc() \n \ + :F4: DeclineProc() \n \ + :F12: RematchProc() \n \ + :F5: CallFlagProc() \n \ + :F6: DrawProc() \n \ + :F7: AdjournProc() \n \ + :F8: AbortProc() \n \ + :F10: StopObservingProc() \n \ + :F11: StopExaminingProc() \n \ + :Meta CtrlF12: DebugProc() \n \ + :MetaEnd: ToEndProc() \n \ + :MetaRight: ForwardProc() \n \ + :MetaHome: ToStartProc() \n \ + :MetaLeft: BackwardProc() \n \ + :Ctrlm: MoveNowProc() \n \ + :Ctrlx: RetractMoveProc() \n \ + :MetaJ: EngineMenuProc() \n \ + :MetaU: UciMenuProc() \n \ + :MetaT: TimeControlProc() \n \ + :CtrlQ: AlwaysQueenProc() \n \ + :CtrlF: AutoflagProc() \n \ + :CtrlA: AnimateMovingProc() \n \ + :CtrlP: PonderNextMoveProc() \n \ + :CtrlL: TestLegalityProc() \n \ + :CtrlH: HideThinkingProc() \n \ + :-: Iconify() \n \ + :F1: ManProc() \n \ + :F2: FlipViewProc() \n \ + .: BackwardProc() \n \ + .: ForwardProc() \n \ Shift1: AskQuestionProc(\"Direct command\",\ \"Send to chess program:\",,1) \n \ Shift2: AskQuestionProc(\"Direct command\",\ @@ -995,7 +1064,7 @@ char boardTranslations[] = : HandleUserMove() \n \ : AnimateUserMove() \n \ : HandlePV() \n \ - : UnLoadPV() \n \ + : PieceMenuPopup(menuB) \n \ Shift: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\ PieceMenuPopup(menuB) \n \ Any: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \ @@ -1009,8 +1078,14 @@ char whiteTranslations[] = ": WhiteClock()\n"; char blackTranslations[] = ": BlackClock()\n"; char ICSInputTranslations[] = + "Up: UpKeyProc() \n " + "Down: DownKeyProc() \n " "Return: EnterKeyProc() \n"; +// [HGM] vari: another hideous kludge: call extend-end first so we can be sure select-start works, +// as the widget is destroyed before the up-click can call extend-end +char commentTranslations[] = ": extend-end() select-start() CommentClick() \n"; + String xboardResources[] = { "*fileName*value.translations: #override\\n Return: FileNameAction()", "*question*value.translations: #override\\n Return: AskQuestionReplyAction()", @@ -1295,9 +1370,25 @@ colorVariable[] = { NULL }; +// [HGM] font: keep a font for each square size, even non-stndard ones +#define NUM_SIZES 18 +#define MAX_SIZE 130 +Boolean fontSet[NUM_FONTS], fontValid[NUM_FONTS][MAX_SIZE]; +char *fontTable[NUM_FONTS][MAX_SIZE]; + void ParseFont(char *name, int number) { // in XBoard, only 2 of the fonts are currently implemented, and we just copy their name + int size; + if(sscanf(name, "size%d:", &size)) { + // [HGM] font: font is meant for specific boardSize (likely from settings file); + // defer processing it until we know if it matches our board size + if(size >= 0 && sizeargLoc) { + char *name, buf[MSG_SIZ]; + int i, n = (int)ad->argLoc; + switch(n) { case 0: // CLOCK_FONT name = appData.clockFont; break; @@ -1372,9 +1465,14 @@ SaveFontArg(FILE *f, ArgDescriptor *ad) default: return; } -// Do not save fonts for now, as the saved font would be board-size specific -// and not suitable for a re-start at another board size -// fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, name); + for(i=0; iargName, i, fontTable[n][i]); } void @@ -1504,6 +1602,8 @@ ConvertToLine(int argc, char **argv) //-------------------------------------------------------------------------------------------- +extern Boolean twoBoards, partnerUp; + #ifdef IDSIZES // eventually, all layout determining code should go into a subroutine, but until then IDSIZE remains undefined #else @@ -1524,7 +1624,7 @@ void InitDrawingSizes(BoardSize boardSize, int flags) shellArgs[1].value = (XtArgVal) &h; XtGetValues(shellWidget, shellArgs, 2); - shellArgs[4].value = 2*w; shellArgs[2].value = 10; + shellArgs[4].value = 3*w; shellArgs[2].value = 10; shellArgs[5].value = 2*h; shellArgs[3].value = 10; XtSetValues(shellWidget, &shellArgs[2], 4); @@ -1534,6 +1634,12 @@ void InitDrawingSizes(BoardSize boardSize, int flags) boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap); boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap); CreateGrid(); + hOffset = boardWidth + 10; + for(i=0; ifontPxlSize; smallLayout = szd->smallLayout; tinyLayout = szd->tinyLayout; + // [HGM] font: use defaults from settings file if available and not overruled } + if(!fontSet[CLOCK_FONT] && fontValid[CLOCK_FONT][squareSize]) + appData.clockFont = fontTable[CLOCK_FONT][squareSize]; + if(!fontSet[MESSAGE_FONT] && fontValid[MESSAGE_FONT][squareSize]) + appData.font = fontTable[MESSAGE_FONT][squareSize]; + if(!fontSet[COORD_FONT] && fontValid[COORD_FONT][squareSize]) + appData.coordFont = fontTable[COORD_FONT][squareSize]; /* Now, using squareSize as a hint, find a good XPM/XIM set size */ if (strlen(appData.pixmapDirectory) > 0) { @@ -2434,7 +2534,7 @@ XBoard square size (hint): %d\n\ /* Why is the following needed on some versions of X instead * of a translation? */ - XtAddEventHandler(boardWidget, ExposureMask, False, + XtAddEventHandler(boardWidget, ExposureMask|PointerMotionMask, False, (XtEventHandler) EventProc, NULL); /* end why */ @@ -2473,6 +2573,7 @@ XBoard square size (hint): %d\n\ } gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes() InitPosition(TRUE); + XtSetKeyboardFocus(shellWidget, formWidget); XtAppMainLoop(appContext); if (appData.debugMode) fclose(debugFP); // [DM] debug @@ -2578,6 +2679,12 @@ GreyRevert(grey) } else { XtSetSensitive(w, !grey); } + w = XtNameToWidget(menuBarWidget, "menuStep.Annotate"); + if (w == NULL) { + DisplayError("menuStep.Annotate", 0); + } else { + XtSetSensitive(w, !grey); + } } void @@ -2613,6 +2720,7 @@ Enables icsEnables[] = { { "menuOptions.Hide Thinking", False }, { "menuOptions.Ponder Next Move", False }, #endif + { "menuStep.Annotate", False }, { NULL, False } }; @@ -2628,6 +2736,7 @@ Enables ncpEnables[] = { { "menuMode.ICS Input Box", False }, { "Action", False }, { "menuStep.Revert", False }, + { "menuStep.Annotate", False }, { "menuStep.Move Now", False }, { "menuStep.Retract Move", False }, { "menuOptions.Auto Comment", False }, @@ -2656,7 +2765,9 @@ Enables gnuEnables[] = { { "menuAction.Adjourn", False }, { "menuAction.Stop Examining", False }, { "menuAction.Stop Observing", False }, + { "menuAction.Upload to Examine", False }, { "menuStep.Revert", False }, + { "menuStep.Annotate", False }, { "menuOptions.Auto Comment", False }, { "menuOptions.Auto Observe", False }, { "menuOptions.Auto Raise Board", False }, @@ -2817,6 +2928,51 @@ SetMachineThinkingEnables() } } +// [HGM] code borrowed from winboard.c (which should thus go to backend.c!) +#define HISTORY_SIZE 64 +static char *history[HISTORY_SIZE]; +int histIn = 0, histP = 0; + +void +SaveInHistory(char *cmd) +{ + if (history[histIn] != NULL) { + free(history[histIn]); + history[histIn] = NULL; + } + if (*cmd == NULLCHAR) return; + history[histIn] = StrSave(cmd); + histIn = (histIn + 1) % HISTORY_SIZE; + if (history[histIn] != NULL) { + free(history[histIn]); + history[histIn] = NULL; + } + histP = histIn; +} + +char * +PrevInHistory(char *cmd) +{ + int newhp; + if (histP == histIn) { + if (history[histIn] != NULL) free(history[histIn]); + history[histIn] = StrSave(cmd); + } + newhp = (histP - 1 + HISTORY_SIZE) % HISTORY_SIZE; + if (newhp == histIn || history[newhp] == NULL) return NULL; + histP = newhp; + return history[histP]; +} + +char * +NextInHistory() +{ + if (histP == histIn) return NULL; + histP = (histP + 1) % HISTORY_SIZE; + return history[histP]; +} +// end of borrowed code + #define Abs(n) ((n)<0 ? -(n) : (n)) /* @@ -3679,54 +3835,18 @@ void PieceMenuPopup(w, event, params, num_params) String *params; Cardinal *num_params; { - String whichMenu; - - if (event->type != ButtonRelease) UnLoadPV(); // [HGM] pv - if (event->type != ButtonPress) return; - if (errorUp) ErrorPopDown(); - switch (gameMode) { - case EditPosition: - case IcsExamining: - whichMenu = params[0]; - break; - case IcsObserving: - if(!appData.icsEngineAnalyze) return; - case IcsPlayingWhite: - case IcsPlayingBlack: - if(!appData.zippyPlay) goto noZip; - case AnalyzeMode: - case AnalyzeFile: - case MachinePlaysWhite: - case MachinePlaysBlack: - case TwoMachinesPlay: // [HGM] pv: use for showing PV - if (!appData.dropMenu) { - LoadPV(event->xbutton.x, event->xbutton.y); - return; - } - if(gameMode == TwoMachinesPlay || gameMode == AnalyzeMode || - gameMode == AnalyzeFile || gameMode == IcsObserving) return; - case EditGame: - noZip: - if (!appData.dropMenu || appData.testLegality && - gameInfo.variant != VariantBughouse && - gameInfo.variant != VariantCrazyhouse) return; - SetupDropMenu(); - whichMenu = "menuD"; - break; - default: - return; + String whichMenu; int menuNr; + if (event->type == ButtonRelease) + menuNr = RightClick(Release, event->xbutton.x, event->xbutton.y, &pmFromX, &pmFromY); + else if (event->type == ButtonPress) + menuNr = RightClick(Press, event->xbutton.x, event->xbutton.y, &pmFromX, &pmFromY); + switch(menuNr) { + case 0: whichMenu = params[0]; break; + case 1: SetupDropMenu(); whichMenu = "menuD"; break; + case 2: + case -1: if (errorUp) ErrorPopDown(); + default: return; } - - if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) || - ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) { - pmFromX = pmFromY = -1; - return; - } - if (flipView) - pmFromX = BOARD_WIDTH - 1 - pmFromX; - else - pmFromY = BOARD_HEIGHT - 1 - pmFromY; - XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu)); } @@ -3834,14 +3954,18 @@ SetHighlights(fromX, fromY, toX, toY) 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 (hi2X >= 0 && hi2Y >= 0) { - drawHighlight(hi2X, hi2Y, lineGC); - } if (toX >= 0 && toY >= 0) { drawHighlight(toX, toY, highlineGC); } @@ -4114,6 +4238,8 @@ void DrawSquare(row, column, piece, do_flash) (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 @@ -4199,7 +4325,7 @@ void DrawSquare(row, column, piece, do_flash) x + 2, y + font_ascent + 1, string, 1); } } - if(marker[row][column]) { + if(!partnerUp && marker[row][column]) { XFillArc(xDisplay, xBoardWindow, marker[row][column] == 2 ? prelineGC : highlineGC, x + squareSize/4, y+squareSize/4, squareSize/2, squareSize/2, 0, 64*360); } @@ -4219,7 +4345,14 @@ void EventProc(widget, unused, event) case Expose: if (event->xexpose.count > 0) return; /* no clipping is done */ XDrawPosition(widget, True, NULL); + if(twoBoards) { // [HGM] dual: draw other board in other orientation + flipView = !flipView; partnerUp = !partnerUp; + XDrawPosition(widget, True, NULL); + flipView = !flipView; partnerUp = !partnerUp; + } break; + case MotionNotify: + if(SeekGraphClick(Press, event->xbutton.x, event->xbutton.y, 1)) break; default: return; } @@ -4300,7 +4433,37 @@ static int check_castle_draw(newb, oldb, rrow, rcol) return 0; } -static int damage[BOARD_RANKS][BOARD_FILES]; +// [HGM] seekgraph: some low-level drawing routines cloned from xevalgraph +void DrawSeekAxis( int x, int y, int xTo, int yTo ) +{ + XDrawLine(xDisplay, xBoardWindow, lineGC, x, y, xTo, yTo); +} + +void DrawSeekBackground( int left, int top, int right, int bottom ) +{ + XFillRectangle(xDisplay, xBoardWindow, lightSquareGC, left, top, right-left, bottom-top); +} + +void DrawSeekText(char *buf, int x, int y) +{ + XDrawString(xDisplay, xBoardWindow, coordGC, x, y+4, buf, strlen(buf)); +} + +void DrawSeekDot(int x, int y, int colorNr) +{ + int square = colorNr & 0x80; + GC color; + colorNr &= 0x7F; + color = colorNr == 0 ? prelineGC : colorNr == 1 ? darkSquareGC : highlineGC; + if(square) + XFillRectangle(xDisplay, xBoardWindow, color, + x-squareSize/9, y-squareSize/9, 2*squareSize/9, 2*squareSize/9); + else + XFillArc(xDisplay, xBoardWindow, color, + 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 @@ -4312,16 +4475,19 @@ void XDrawPosition(w, repaint, board) { int i, j, do_flash; static int lastFlipView = 0; - static int lastBoardValid = 0; - static Board lastBoard; + 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) return; - board = lastBoard; + board = lastBoard[nr]; } - if (!lastBoardValid || lastFlipView != flipView) { + if (!lastBoardValid[nr] || (nr == 0 && lastFlipView != flipView)) { XtSetArg(args[0], XtNleftBitmap, (flipView ? xMarkPixmap : None)); XtSetValues(XtNameToWidget(menuBarWidget, "menuOptions.Flip View"), args, 1); @@ -4332,19 +4498,19 @@ void XDrawPosition(w, repaint, board) * but this causes a very distracting flicker. */ - if (!repaint && lastBoardValid && lastFlipView == flipView) { + if (!repaint && lastBoardValid[nr] && (nr == 1 || lastFlipView == flipView)) { /* If too much changes (begin observing new game, etc.), don't do flashing */ - do_flash = too_many_diffs(board, lastBoard) ? 0 : 1; + 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, &rrow, &rcol)) { + 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[rrow][rcol] = board[rrow][rcol]; + lastBoard[nr][rrow][rcol] = board[rrow][rcol]; } } @@ -4353,32 +4519,34 @@ void XDrawPosition(w, repaint, board) 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[i][j] && board[i][j] == EmptySquare) - || damage[i][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[i][j] = False; + 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[i][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 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[i][j] = False; + damage[nr][i][j] = False; } } - CopyBoard(lastBoard, board); - lastBoardValid = 1; + CopyBoard(lastBoard[nr], board); + lastBoardValid[nr] = 1; + if(nr == 0) { // [HGM] dual: no highlights on second board yet lastFlipView = flipView; /* Draw highlights */ @@ -4394,7 +4562,7 @@ void XDrawPosition(w, repaint, board) if (hi2X >= 0 && hi2Y >= 0) { drawHighlight(hi2X, hi2Y, highlineGC); } - + } /* If piece being dragged around board, must redraw that too */ DrawDragPiece(); @@ -4513,6 +4681,7 @@ Widget CommentCreate(name, text, mutable, callback, lines) XtSetArg(args[j], XtNwrap, XawtextWrapWord); j++; edit = XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j); + XtOverrideTranslations(edit, XtParseTranslationTable(commentTranslations)); if (mutable) { j = 0; @@ -4721,6 +4890,20 @@ Widget MiscCreate(name, text, mutable, callback, lines) static int savedIndex; /* gross that this is global */ +void CommentClick (Widget w, XEvent * event, String * params, Cardinal * nParams) +{ + String val; + XawTextPosition index, dummy; + Arg arg; + + XawTextGetSelectionPos(w, &index, &dummy); + XtSetArg(arg, XtNstring, &val); + XtGetValues(w, &arg, 1); + ReplaceComment(savedIndex, val); + if(savedIndex != currentMove) ToNrEvent(savedIndex); + LoadVariation( index, val ); // [HGM] also does the actual moving to it, now +} + void EditCommentPopUp(index, title, text) int index; char *title, *text; @@ -4854,6 +5037,7 @@ void ICSInputSendText() j = 0; XtSetArg(args[j], XtNstring, &val); j++; XtGetValues(edit, args, j); + SaveInHistory(val); SendMultiLineToICS(val); XtCallActionProc(edit, "select-all", NULL, NULL, 0); XtCallActionProc(edit, "kill-selection", NULL, NULL, 0); @@ -4881,6 +5065,7 @@ void CommentPopUp(title, text) int j; Widget edit; + savedIndex = currentMove; // [HGM] vari if (commentShell == NULL) { commentShell = CommentCreate(title, text, False, CommentCallback, 4); @@ -4956,45 +5141,14 @@ void FileNamePopUp(label, def, proc, openMode) fileProc = proc; /* I can't see a way not */ fileOpenMode = openMode; /* to use globals here */ - - i = 0; - XtSetArg(args[i], XtNresizable, True); i++; - XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++; - XtSetArg(args[i], XtNtitle, XtNewString(_("File name prompt"))); i++; - fileNameShell = popup = - XtCreatePopupShell("File name prompt", transientShellWidgetClass, - shellWidget, args, i); - - layout = - XtCreateManagedWidget(layoutName, formWidgetClass, popup, - layoutArgs, XtNumber(layoutArgs)); - - i = 0; - XtSetArg(args[i], XtNlabel, label); i++; - XtSetArg(args[i], XtNvalue, def); i++; - XtSetArg(args[i], XtNborderWidth, 0); i++; - dialog = XtCreateManagedWidget("fileName", dialogWidgetClass, - layout, args, i); - - XawDialogAddButton(dialog, _("ok"), FileNameCallback, (XtPointer) dialog); - XawDialogAddButton(dialog, _("cancel"), FileNameCallback, - (XtPointer) dialog); - - XtRealizeWidget(popup); - CatchDeleteWindow(popup, "FileNamePopDown"); - - XQueryPointer(xDisplay, xBoardWindow, &root, &child, - &x, &y, &win_x, &win_y, &mask); - - XtSetArg(args[0], XtNx, x - 10); - XtSetArg(args[1], XtNy, y - 30); - XtSetValues(popup, args, 2); - - XtPopup(popup, XtGrabExclusive); - filenameUp = True; - - edit = XtNameToWidget(dialog, "*value"); - XtSetKeyboardFocus(popup, edit); + { // [HGM] use file-selector dialog stolen from Ghostview + char *name; + int index; // this is not supported yet + FILE *f; + if(f = XsraSelFile(shellWidget, label, NULL, NULL, "could not open: ", + def, openMode, NULL, &name)) + (void) (*fileProc)(f, index=0, name); + } } void FileNamePopDown() @@ -6063,6 +6217,55 @@ void EnterKeyProc(w, event, prms, nprms) ICSInputSendText(); } +void UpKeyProc(w, event, prms, nprms) + Widget w; + XEvent *event; + String *prms; + Cardinal *nprms; +{ // [HGM] input: let up-arrow recall previous line from history + Widget edit; + int j; + Arg args[16]; + String val; + XawTextBlock t; + + if (!ICSInputBoxUp) return; + edit = XtNameToWidget(ICSInputShell, "*form.text"); + j = 0; + XtSetArg(args[j], XtNstring, &val); j++; + XtGetValues(edit, args, j); + val = PrevInHistory(val); + XtCallActionProc(edit, "select-all", NULL, NULL, 0); + XtCallActionProc(edit, "kill-selection", NULL, NULL, 0); + if(val) { + t.ptr = val; t.firstPos = 0; t.length = strlen(val); t.format = XawFmt8Bit; + XawTextReplace(edit, 0, 0, &t); + XawTextSetInsertionPoint(edit, 9999); + } +} + +void DownKeyProc(w, event, prms, nprms) + Widget w; + XEvent *event; + String *prms; + Cardinal *nprms; +{ // [HGM] input: let down-arrow recall next line from history + Widget edit; + String val; + XawTextBlock t; + + if (!ICSInputBoxUp) return; + edit = XtNameToWidget(ICSInputShell, "*form.text"); + val = NextInHistory(); + XtCallActionProc(edit, "select-all", NULL, NULL, 0); + XtCallActionProc(edit, "kill-selection", NULL, NULL, 0); + if(val) { + t.ptr = val; t.firstPos = 0; t.length = strlen(val); t.format = XawFmt8Bit; + XawTextReplace(edit, 0, 0, &t); + XawTextSetInsertionPoint(edit, 9999); + } +} + void StopObservingProc(w, event, prms, nprms) Widget w; XEvent *event; @@ -6081,6 +6284,15 @@ void StopExaminingProc(w, event, prms, nprms) StopExaminingEvent(); } +void UploadProc(w, event, prms, nprms) + Widget w; + XEvent *event; + String *prms; + Cardinal *nprms; +{ + UploadGameEvent(); +} + void ForwardProc(w, event, prms, nprms) Widget w; @@ -6125,7 +6337,16 @@ void RevertProc(w, event, prms, nprms) String *prms; Cardinal *nprms; { - RevertEvent(); + RevertEvent(False); +} + +void AnnotateProc(w, event, prms, nprms) + Widget w; + XEvent *event; + String *prms; + Cardinal *nprms; +{ + RevertEvent(True); } void TruncateGameProc(w, event, prms, nprms) @@ -8574,7 +8795,7 @@ AnimateMove(board, fromX, fromY, toX, toY) FrameSequence(&game, piece, startColor, &start, &finish, frames, nFrames); /* Be sure end square is redrawn */ - damage[toY][toX] = True; + damage[0][toY][toX] = True; } void @@ -8614,7 +8835,7 @@ DragPieceBegin(x, y) XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC, corner.x, corner.y, squareSize, squareSize, 0, 0); // [HGM] zh: unstack in stead of grab - damage[boardY][boardX] = True; + damage[0][boardY][boardX] = True; } else { player.dragActive = False; } @@ -8668,7 +8889,7 @@ DragPieceEnd(x, y) EndAnimation(&player, &corner); /* Be sure end square is redrawn */ - damage[boardY][boardX] = True; + damage[0][boardY][boardX] = True; /* This prevents weird things happening with fast successive clicks which on my Sun at least can cause motion events @@ -8691,7 +8912,7 @@ DrawDragPiece () BlankSquare(player.startSquare.x, player.startSquare.y, player.startColor, EmptySquare, xBoardWindow); AnimationFrame(&player, &player.prevFrame, player.dragPiece); - damage[player.startBoardY][player.startBoardX] = TRUE; + damage[0][player.startBoardY][player.startBoardX] = TRUE; } #include