new developer release
[xboard.git] / xboard.c
index c2910a3..edf20c6 100644 (file)
--- 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:
@@ -444,6 +444,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(());
@@ -664,6 +666,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},
@@ -850,6 +853,7 @@ XtActionsRec boardActions[] = {
     { "LoadNextGameProc", LoadNextGameProc },
     { "LoadPrevGameProc", LoadPrevGameProc },
     { "LoadSelectedProc", LoadSelectedProc },
+    { "SetFilterProc", SetFilterProc },
     { "ReloadGameProc", ReloadGameProc },
     { "LoadPositionProc", LoadPositionProc },
     { "LoadNextPositionProc", LoadNextPositionProc },
@@ -951,6 +955,7 @@ XtActionsRec boardActions[] = {
     { "FileNamePopDown", (XtActionProc) FileNamePopDown },
     { "AskQuestionPopDown", (XtActionProc) AskQuestionPopDown },
     { "GameListPopDown", (XtActionProc) GameListPopDown },
+    { "GameListOptionsPopDown", (XtActionProc) GameListOptionsPopDown },
     { "PromotionPopDown", (XtActionProc) PromotionPopDown },
     { "HistoryPopDown", (XtActionProc) HistoryPopDown },
     { "EngineOutputPopDown", (XtActionProc) EngineOutputPopDown },
@@ -995,7 +1000,7 @@ char boardTranslations[] =
    <Btn1Up>: HandleUserMove() \n \
    <Btn1Motion>: AnimateUserMove() \n \
    <Btn3Motion>: HandlePV() \n \
-   <Btn3Up>: UnLoadPV() \n \
+   <Btn3Up>: PieceMenuPopup(menuB) \n \
    Shift<Btn2Down>: XawPositionSimpleMenu(menuB) XawPositionSimpleMenu(menuD)\
                  PieceMenuPopup(menuB) \n \
    Any<Btn2Down>: XawPositionSimpleMenu(menuW) XawPositionSimpleMenu(menuD) \
@@ -1284,7 +1289,7 @@ colorVariable[] = {
   &appData.darkSquareColor, 
   &appData.highlightSquareColor,
   &appData.premoveHighlightColor,
-  NULL,
+  &appData.lowTimeWarningColor,
   NULL,
   NULL,
   NULL,
@@ -1295,9 +1300,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 && size<MAX_SIZE) { // for now, fixed limit
+       fontTable[number][size] = strdup(strchr(name, ':')+1);
+       fontValid[number][size] = True;
+    }
+    return;
+  }
   switch(number) {
     case 0: // CLOCK_FONT
        appData.clockFont = strdup(name);
@@ -1311,6 +1332,7 @@ ParseFont(char *name, int number)
     default:
       return;
   }
+  fontSet[number] = True; // [HGM] font: indicate a font was specified (not from settings file)
 }
 
 void
@@ -1358,8 +1380,9 @@ SetCommPortDefaults()
 void
 SaveFontArg(FILE *f, ArgDescriptor *ad)
 {
-  char *name;
-  switch((int)ad->argLoc) {
+  char *name, buf[MSG_SIZ];
+  int i, n = (int)ad->argLoc;
+  switch(n) {
     case 0: // CLOCK_FONT
        name = appData.clockFont;
       break;
@@ -1372,9 +1395,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; i<NUM_SIZES; i++) // [HGM] font: current font becomes standard for current size
+    if(sizeDefaults[i].squareSize == squareSize) { // only for standard sizes!
+       fontTable[n][squareSize] = strdup(name);
+       fontValid[n][squareSize] = True;
+       break;
+  }
+  for(i=0; i<MAX_SIZE; i++) if(fontValid[n][i]) // [HGM] font: store all standard fonts
+    fprintf(f, OPTCHAR "%s" SEPCHAR "size%d:%s\n", ad->argName, i, fontTable[n][i]); 
 }
 
 void
@@ -1815,7 +1843,14 @@ main(argc, argv)
        fontPxlSize = szd->fontPxlSize;
        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 +2469,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 */
 
@@ -3679,54 +3714,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;
-    }
-
-    if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_WIDTH)) < 0) ||
-       ((pmFromY = EventToSquare(event->xbutton.y, BOARD_HEIGHT)) < 0)) {
-       pmFromX = pmFromY = -1;
-       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 (flipView)
-      pmFromX = BOARD_WIDTH - 1 - pmFromX;
-    else
-      pmFromY = BOARD_HEIGHT - 1 - pmFromY;
-
     XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
 }
 
@@ -3834,14 +3833,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);
        }
@@ -4220,6 +4223,8 @@ void EventProc(widget, unused, event)
        if (event->xexpose.count > 0) return;  /* no clipping is done */
        XDrawPosition(widget, True, NULL);
        break;
+      case MotionNotify:
+        if(SeekGraphClick(Press, event->xbutton.x, event->xbutton.y, 1)) break;\r
       default:
        return;
     }
@@ -4300,6 +4305,36 @@ static int check_castle_draw(newb, oldb, rrow, rcol)
     return 0;
 }
 
+// [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[BOARD_RANKS][BOARD_FILES];
 
 /*
@@ -4317,6 +4352,8 @@ void XDrawPosition(w, repaint, board)
     Arg args[16];
     int rrow, rcol;
 
+    if(DrawSeekGraph()) return; // [HGM] seekgraph: suppress any drawing if seek graph up
+
     if (board == NULL) {
        if (!lastBoardValid) return;
        board = lastBoard;