Make system open command configurable
[xboard.git] / xboard.c
index 8cbcfda..80db398 100644 (file)
--- 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}
 };
@@ -1746,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
@@ -1820,6 +1833,7 @@ InitDrawingSizes (BoardSize boardSize, int flags)
       }
     }
     oldMono = -10; // kludge to force recreation of animation masks
+    oldVariant = gameInfo.variant;
   }
 #if HAVE_LIBXPM
   if(appData.monoMode != oldMono)
@@ -3900,7 +3914,7 @@ MenuBarSelect (Widget w, caddr_t addr, caddr_t index)
 static void
 MenuEngineSelect (Widget w, caddr_t addr, caddr_t index)
 {
-    RecentEngineEvent((int) addr);
+    RecentEngineEvent((int) (intptr_t) addr);
 }
 
 void
@@ -3912,7 +3926,7 @@ AppendEnginesToMenu (Widget menu, char *list)
     Arg args[16];
     char *p;
 
-    if(appData.recentEngines <= 0) return;
+    if(appData.icsActive || appData.recentEngines <= 0) return;
     recentEngines = strdup(list);
     j = 0;
     XtSetArg(args[j], XtNleftMargin, 20);   j++;
@@ -3925,7 +3939,7 @@ AppendEnginesToMenu (Widget menu, char *list)
        entry = XtCreateManagedWidget("engine", smeBSBObjectClass, menu, args, j+1);
        XtAddCallback(entry, XtNcallback,
                          (XtCallbackProc) MenuEngineSelect,
-                         (caddr_t) i);
+                         (caddr_t) (intptr_t) i);
        i++; *p = '\n'; list = p + 1;
     }
 }
@@ -4649,6 +4663,14 @@ 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
@@ -4662,8 +4684,25 @@ CoDrag (Widget sh, WindowPlacement *wp)
     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);
@@ -4673,12 +4712,14 @@ void
 DragProc ()
 {
        GetActualPlacement(shellWidget, &wpNew);
-       if(wpNew.x == wpMain.x && wpNew.y == wpMain.y) return; // not moved, false alarm
+       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.x = wpNew.x; wpMain.y = wpNew.y;
+       wpMain = wpNew;
        XDrawPosition(boardWidget, True, NULL);
 }
 
@@ -6629,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
@@ -6643,7 +6716,11 @@ _("%s%s\n\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: <bug-xboard@gnu.org>\n\n"
+  ),
            programVersion, zippy, PACKAGE);
     ErrorPopUp(_("About XBoard"), buf, FALSE);
 }