X-Git-Url: http://winboard.nl/cgi-bin?a=blobdiff_plain;f=xboard.c;h=80db3980ec7cef890d92a0eb9f7c4c63ea8857bf;hb=919bb8ce56406c6059ec9d3221d1bc96ad388d1c;hp=310274de2f24d1ab5904d9b6e17445f1b555551a;hpb=97d28802c3f1166f64a2cc32da74d829a60d8243;p=xboard.git diff --git a/xboard.c b/xboard.c index 310274d..80db398 100644 --- a/xboard.c +++ b/xboard.c @@ -273,6 +273,7 @@ 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)); void HandleUserMove P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); @@ -443,6 +444,10 @@ void SaveSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms) void SaveOnExitProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); void InfoProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); void ManProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); +void GuideProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); +void HomePageProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); +void NewsPageProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); +void BugReportProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); void HintProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); void BookProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); void AboutGameProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)); @@ -785,6 +790,11 @@ MenuItem helpMenu[] = { {N_("Info XBoard"), "Info XBoard", InfoProc}, {N_("Man XBoard F1"), "Man XBoard", ManProc}, {"----", NULL, NothingProc}, + {N_("XBoard Home Page"), "Home Page", HomePageProc}, + {N_("On-line User Guide"), "User Guide", GuideProc}, + {N_("Development News"), "News Page", NewsPageProc}, + {N_("e-Mail Bug Report"), "Bug Report", BugReportProc}, + {"----", NULL, NothingProc}, {N_("About XBoard"), "About XBoard", AboutProc}, {NULL, NULL, NULL} }; @@ -1125,7 +1135,9 @@ char boardTranslations[] = : HandleUserMove(0) \n \ : AnimateUserMove() \n \ : HandlePV() \n \ + : HandlePV() \n \ : PieceMenuPopup(menuB) \n \ + : PieceMenuPopup(menuB) \n \ Shift: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\ PieceMenuPopup(menuB) \n \ Any: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \ @@ -1553,6 +1565,7 @@ ParseCommPortSettings (char *s) } extern Widget engineOutputShell; +int frameX, frameY; void GetActualPlacement (Widget wg, WindowPlacement *wp) @@ -1560,20 +1573,20 @@ GetActualPlacement (Widget wg, WindowPlacement *wp) Arg args[16]; Dimension w, h; Position x, y; - int i; + XWindowAttributes winAt; + Window win, dummy; + int i, rx, ry; if(!wg) return; - i = 0; - XtSetArg(args[i], XtNx, &x); i++; - XtSetArg(args[i], XtNy, &y); i++; - XtSetArg(args[i], XtNwidth, &w); i++; - XtSetArg(args[i], XtNheight, &h); i++; - XtGetValues(wg, args, i); - wp->x = x - 4; - wp->y = y - 23; - wp->height = h; - wp->width = w; + win = XtWindow(wg); + XGetWindowAttributes(xDisplay, win, &winAt); // this works, where XtGetValues on XtNx, XtNy does not! + XTranslateCoordinates (xDisplay, win, winAt.root, -winAt.border_width, -winAt.border_width, &rx, &ry, &dummy); + wp->x = rx - winAt.x; + wp->y = ry - winAt.y; + wp->height = winAt.height; + wp->width = winAt.width; + frameX = winAt.x; frameY = winAt.y; // remember to decide if windows touch } void @@ -1743,6 +1756,9 @@ InitDrawingSizes (BoardSize boardSize, int flags) shellArgs[4].value = shellArgs[2].value = w; shellArgs[5].value = shellArgs[3].value = h; XtSetValues(shellWidget, &shellArgs[0], 6); + + XSync(xDisplay, False); + DelayedDrag(); } // [HGM] pieces: tailor piece bitmaps to needs of specific variant @@ -1816,6 +1832,8 @@ InitDrawingSizes (BoardSize boardSize, int flags) } } } + oldMono = -10; // kludge to force recreation of animation masks + oldVariant = gameInfo.variant; } #if HAVE_LIBXPM if(appData.monoMode != oldMono) @@ -2175,10 +2193,13 @@ XBoard square size (hint): %d\n\ /* For the coordFont, use the 0th font of the fontset. */ XFontSet coordFontSet = CreateFontSet(appData.coordFont); XFontStruct **font_struct_list; + XFontSetExtents *fontSize; char **font_name_list; XFontsOfFontSet(coordFontSet, &font_struct_list, &font_name_list); coordFontID = XLoadFont(xDisplay, font_name_list[0]); coordFontStruct = XQueryFont(xDisplay, coordFontID); + fontSize = XExtentsOfFontSet(fontSet); // [HGM] figure out how much vertical space font takes + textHeight = fontSize->max_logical_extent.height + 5; // add borderWidth } #else appData.font = FindFont(appData.font, fontPxlSize); @@ -2314,7 +2335,7 @@ XBoard square size (hint): %d\n\ messageArgs, XtNumber(messageArgs)); XtSetArg(args[0], XtNtop, XtChainTop); XtSetArg(args[1], XtNbottom, XtChainTop); - XtSetValues(messageWidget, args, 3); + XtSetValues(messageWidget, args, 2); widgetList[j++] = boardWidget = XtCreateWidget("board", widgetClass, formWidget, boardArgs, @@ -2460,8 +2481,8 @@ XBoard square size (hint): %d\n\ fprintf(stderr, _("%s: messageWidget geometry error %d %d %d %d %d\n"), programName, gres, w, h, wr, hr); } - textHeight = hr; // [HGM] save height for use in generic popup /* !! end hack */ + if(!textHeight) textHeight = hr; // [HGM] if !NLS textHeight is still undefined, and we grab it from here XtSetArg(args[0], XtNleft, XtChainLeft); // [HGM] glue ends for good run-time sizing XtSetArg(args[1], XtNright, XtChainRight); XtSetValues(messageWidget, args, 2); @@ -2656,6 +2677,8 @@ XBoard square size (hint): %d\n\ /* end why */ XtAddEventHandler(formWidget, KeyPressMask, False, (XtEventHandler) MoveTypeInProc, NULL); + XtAddEventHandler(shellWidget, StructureNotifyMask, False, + (XtEventHandler) EventProc, NULL); /* [AS] Restore layout */ if( wpMoveHistory.visible ) { @@ -3888,6 +3911,39 @@ MenuBarSelect (Widget w, caddr_t addr, caddr_t index) (proc)(NULL, NULL, NULL, NULL); } +static void +MenuEngineSelect (Widget w, caddr_t addr, caddr_t index) +{ + RecentEngineEvent((int) (intptr_t) addr); +} + +void +AppendEnginesToMenu (Widget menu, char *list) +{ + int i=0, j; + Widget entry; + MenuItem *mi; + Arg args[16]; + char *p; + + if(appData.icsActive || appData.recentEngines <= 0) return; + recentEngines = strdup(list); + j = 0; + XtSetArg(args[j], XtNleftMargin, 20); j++; + XtSetArg(args[j], XtNrightMargin, 20); j++; + while (*list) { + p = strchr(list, '\n'); if(p == NULL) break; + if(i == 0) XtCreateManagedWidget(_("----"), smeLineObjectClass, menu, args, j); // at least one valid item to add + *p = 0; + XtSetArg(args[j], XtNlabel, XtNewString(list)); + entry = XtCreateManagedWidget("engine", smeBSBObjectClass, menu, args, j+1); + XtAddCallback(entry, XtNcallback, + (XtCallbackProc) MenuEngineSelect, + (caddr_t) (intptr_t) i); + i++; *p = '\n'; list = p + 1; + } +} + void CreateMenuBarPopup (Widget parent, String name, Menu *mb) { @@ -3916,6 +3972,7 @@ CreateMenuBarPopup (Widget parent, String name, Menu *mb) } mi++; } + if(!strcmp(mb->name, "Engine")) AppendEnginesToMenu(menu, appData.recentEngineList); } Widget @@ -4044,6 +4101,7 @@ CreatePieceMenus () whitePieceMenu = CreatePieceMenu("menuW", 0); blackPieceMenu = CreatePieceMenu("menuB", 1); + if(appData.pieceMenu) // [HGM] sweep: no idea what this was good for, but it stopped reporting button events outside the window XtRegisterGrabAction(PieceMenuPopup, True, (unsigned)(ButtonPressMask|ButtonReleaseMask), GrabModeAsync, GrabModeAsync); @@ -4605,6 +4663,75 @@ DrawSquare (int row, int column, ChessSquare piece, int do_flash) } } +double +Fraction (int x, int start, int stop) +{ + double f = ((double) x - start)/(stop - start); + if(f > 1.) f = 1.; else if(f < 0.) f = 0.; + return f; +} + +static WindowPlacement wpNew; + +void +CoDrag (Widget sh, WindowPlacement *wp) +{ + Arg args[16]; + int j=0, touch=0, fudge = 2; + GetActualPlacement(sh, wp); + if(abs(wpMain.x + wpMain.width + 2*frameX - wp->x) < fudge) touch = 1; else // right touch + if(abs(wp->x + wp->width + 2*frameX - wpMain.x) < fudge) touch = 2; else // left touch + if(abs(wpMain.y + wpMain.height + frameX + frameY - wp->y) < fudge) touch = 3; else // bottom touch + if(abs(wp->y + wp->height + frameX + frameY - wpMain.y) < fudge) touch = 4; // top touch + if(!touch ) return; // only windows that touch co-move + if(touch < 3 && wpNew.height != wpMain.height) { // left or right and height changed + int heightInc = wpNew.height - wpMain.height; + double fracTop = Fraction(wp->y, wpMain.y, wpMain.y + wpMain.height + frameX + frameY); + double fracBot = Fraction(wp->y + wp->height + frameX + frameY + 1, wpMain.y, wpMain.y + wpMain.height + frameX + frameY); + wp->y += fracTop * heightInc; + heightInc = (int) (fracBot * heightInc) - (int) (fracTop * heightInc); + if(heightInc) XtSetArg(args[j], XtNheight, wp->height + heightInc), j++; + } else if(touch > 2 && wpNew.width != wpMain.width) { // top or bottom and width changed + int widthInc = wpNew.width - wpMain.width; + double fracLeft = Fraction(wp->x, wpMain.x, wpMain.x + wpMain.width + 2*frameX); + double fracRght = Fraction(wp->x + wp->width + 2*frameX + 1, wpMain.x, wpMain.x + wpMain.width + 2*frameX); + wp->y += fracLeft * widthInc; + widthInc = (int) (fracRght * widthInc) - (int) (fracLeft * widthInc); + if(widthInc) XtSetArg(args[j], XtNwidth, wp->width + widthInc), j++; + } + wp->x += wpNew.x - wpMain.x; + wp->y += wpNew.y - wpMain.y; + if(touch == 1) wp->x += wpNew.width - wpMain.width; else + if(touch == 3) wp->y += wpNew.height - wpMain.height; + XtSetArg(args[j], XtNx, wp->x); j++; + XtSetArg(args[j], XtNy, wp->y); j++; + XtSetValues(sh, args, j); +} + +void +DragProc () +{ + GetActualPlacement(shellWidget, &wpNew); + if(wpNew.x == wpMain.x && wpNew.y == wpMain.y && // not moved + wpNew.width == wpMain.width && wpNew.height == wpMain.height) // not sized + return; // false alarm + if(EngineOutputIsUp()) CoDrag(engineOutputShell, &wpEngineOutput); + if(MoveHistoryIsUp()) CoDrag(shells[7], &wpMoveHistory); + if(EvalGraphIsUp()) CoDrag(evalGraphShell, &wpEvalGraph); + if(GameListIsUp()) CoDrag(gameListShell, &wpGameList); + wpMain = wpNew; + XDrawPosition(boardWidget, True, NULL); +} + + +void +DelayedDrag () +{ + static XtIntervalId delayedDragID = 0; + if(delayedDragID) XtRemoveTimeOut(delayedDragID); // cancel pending + delayedDragID = + XtAppAddTimeOut(appContext, 50, (XtTimerCallbackProc) DragProc, (XtPointer) 0); // and schedule new one 50 msec later +} /* Why is this needed on some versions of X? */ void @@ -4612,8 +4739,11 @@ EventProc (Widget widget, caddr_t unused, XEvent *event) { if (!XtIsRealized(widget)) return; - switch (event->type) { + case ConfigureNotify: // main window is being dragged: drag attached windows with it + if(appData.useStickyWindows) + DelayedDrag(); // as long as events keep coming in faster than 50 msec, they destroy each other + break; case Expose: if (event->xexpose.count > 0) return; /* no clipping is done */ XDrawPosition(widget, True, NULL); @@ -5184,7 +5314,7 @@ PromotionCallback (Widget w, XtPointer client_data, XtPointer call_data) void ErrorCallback (Widget w, XtPointer client_data, XtPointer call_data) { - errorUp = False; + dialogError = errorUp = False; XtPopdown(w = XtParent(XtParent(XtParent(w)))); XtDestroyWidget(w); if (errorExitStatus != -1) ExitEvent(errorExitStatus); @@ -5195,7 +5325,7 @@ void ErrorPopDown () { if (!errorUp) return; - errorUp = False; + dialogError = errorUp = False; XtPopdown(errorShell); XtDestroyWidget(errorShell); if (errorExitStatus != -1) ExitEvent(errorExitStatus); @@ -5218,7 +5348,7 @@ ErrorPopUp (char *title, char *label, int modal) XtSetArg(args[i], XtNtitle, title); i++; errorShell = XtCreatePopupShell("errorpopup", transientShellWidgetClass, - shellWidget, args, i); + shellUp[0] ? (dialogError = modal = TRUE, shells[0]) : shellWidget, args, i); layout = XtCreateManagedWidget(layoutName, formWidgetClass, errorShell, layoutArgs, XtNumber(layoutArgs)); @@ -5576,6 +5706,12 @@ CopyPositionProc (Widget w, XEvent *event, String *prms, Cardinal *nprms) NULL/* transfer_done_proc */); } +void +CopyFENToClipboard () +{ // wrapper to make call from back-end possible + CopyPositionProc(NULL, NULL, NULL, NULL); +} + /* function called when the data to Paste is ready */ static void PastePositionCB (Widget w, XtPointer client_data, Atom *selection, @@ -6534,9 +6670,41 @@ BookProc (Widget w, XEvent *event, String *prms, Cardinal *nprms) } void -AboutProc (Widget w, XEvent *event, String *prms, Cardinal *nprms) +BugReportProc (Widget w, XEvent *event, String *prms, Cardinal *nprms) +{ + char buf[MSG_SIZ]; + snprintf(buf, MSG_SIZ, "%s mailto:bug-xboard@gnu.org", appData.sysOpen); + system(buf); +} + +void +GuideProc (Widget w, XEvent *event, String *prms, Cardinal *nprms) +{ + 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 (Widget w, XEvent *event, String *prms, Cardinal *nprms) +{ + char buf[MSG_SIZ]; + snprintf(buf, MSG_SIZ, "%s http://www.gnu.org/software/xboard/", appData.sysOpen); + system(buf); +} + +void +NewsPageProc (Widget w, XEvent *event, String *prms, Cardinal *nprms) { 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 (Widget w, XEvent *event, String *prms, Cardinal *nprms) +{ + char buf[2 * MSG_SIZ]; #if ZIPPY char *zippy = _(" (with Zippy code)"); #else @@ -6545,10 +6713,14 @@ AboutProc (Widget w, XEvent *event, String *prms, Cardinal *nprms) snprintf(buf, sizeof(buf), _("%s%s\n\n" "Copyright 1991 Digital Equipment Corporation\n" -"Enhancements Copyright 1992-2009 Free Software Foundation\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."), +"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); } @@ -7306,7 +7478,7 @@ StartChildProcess (char *cmdLine, char *dir, ProcRef *pr) char buf[MSG_SIZ]; if (appData.debugMode) { - fprintf(stderr, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine); + fprintf(debugFP, "StartChildProcess (dir=\"%s\") %s\n",dir, cmdLine); } /* We do NOT feed the cmdLine to the shell; we just @@ -8247,11 +8419,6 @@ AnimateMove (Board board, int fromX, int fromY, int toX, int toY) hop = abs(fromX-toX) == 1 && abs(fromY-toY) == 2 || abs(fromX-toX) == 2 && abs(fromY-toY) == 1; #endif - if (appData.debugMode) { - fprintf(debugFP, hop ? _("AnimateMove: piece %d hops from %d,%d to %d,%d \n") : - _("AnimateMove: piece %d slides from %d,%d to %d,%d \n"), - piece, fromX, fromY, toX, toY); } - ScreenSquare(fromX, fromY, &start, &startColor); ScreenSquare(toX, toY, &finish, &endColor);