Add -afterTourney option
[xboard.git] / xboard.c
index 68650ab..0424641 100644 (file)
--- a/xboard.c
+++ b/xboard.c
@@ -387,6 +387,9 @@ void StopExaminingProc P((Widget w, XEvent *event, String *prms,
 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 TempBackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void TempForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+Boolean TempBackwardActive = False;
 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));
@@ -980,6 +983,8 @@ XtActionsRec boardActions[] = {
     { "UploadProc", UploadProc },
     { "BackwardProc", BackwardProc },
     { "ForwardProc", ForwardProc },
+    { "TempBackwardProc", TempBackwardProc },
+    { "TempForwardProc", TempForwardProc },
     { "ToStartProc", ToStartProc },
     { "ToEndProc", ToEndProc },
     { "RevertProc", RevertProc },
@@ -1108,11 +1113,11 @@ char globalTranslations[] =
    "\
    :<Key>F1: ManProc() \n \
    :<Key>F2: FlipViewProc() \n \
-   <KeyDown>.: BackwardProc() \n \
-   <KeyUp>.: ForwardProc() \n \
-   Shift<Key>1: AskQuestionProc(\"Direct command\",\
+   :Ctrl<KeyDown>.: TempBackwardProc() \n \
+   :Ctrl<KeyUp>.: TempForwardProc() \n \
+   :Ctrl<Key>1: AskQuestionProc(\"Direct command\",\
                                 \"Send to chess program:\",,1) \n \
-   Shift<Key>2: AskQuestionProc(\"Direct command\",\
+   :Ctrl<Key>2: AskQuestionProc(\"Direct command\",\
                                 \"Send to second chess program:\",,2) \n";
 
 char boardTranslations[] =
@@ -5119,6 +5124,7 @@ void PromotionPopUp()
     Position x, y;
     Dimension bw_width, pw_width;
     int j;
+    char *PromoChars = "wglcqrbnkac+=\0";
 
     j = 0;
     XtSetArg(args[j], XtNwidth, &bw_width); j++;
@@ -5142,47 +5148,33 @@ void PromotionPopUp()
 
   if(gameInfo.variant != VariantShogi) {
    if(gameInfo.variant == VariantSpartan && !WhiteOnMove(currentMove)) {
-      XawDialogAddButton(dialog, _("Warlord"), PromotionCallback,
-                        (XtPointer) dialog);
-      XawDialogAddButton(dialog, _("General"), PromotionCallback,
-                        (XtPointer) dialog);
-      XawDialogAddButton(dialog, _("Lieutenant"), PromotionCallback,
-                        (XtPointer) dialog);
-      XawDialogAddButton(dialog, _("Captain"), PromotionCallback,
-                        (XtPointer) dialog);
+      XawDialogAddButton(dialog, _("Warlord"), PromotionCallback, PromoChars + 0);
+      XawDialogAddButton(dialog, _("General"), PromotionCallback, PromoChars + 1);
+      XawDialogAddButton(dialog, _("Lieutenant"), PromotionCallback, PromoChars + 2);
+      XawDialogAddButton(dialog, _("Captain"), PromotionCallback, PromoChars + 3);
     } else {
-    XawDialogAddButton(dialog, _("Queen"), PromotionCallback,
-                      (XtPointer) dialog);
-    XawDialogAddButton(dialog, _("Rook"), PromotionCallback,
-                      (XtPointer) dialog);
-    XawDialogAddButton(dialog, _("Bishop"), PromotionCallback,
-                      (XtPointer) dialog);
-    XawDialogAddButton(dialog, _("Knight"), PromotionCallback,
-                      (XtPointer) dialog);
+    XawDialogAddButton(dialog, _("Queen"), PromotionCallback, PromoChars + 4);
+    XawDialogAddButton(dialog, _("Rook"), PromotionCallback, PromoChars + 5);
+    XawDialogAddButton(dialog, _("Bishop"), PromotionCallback, PromoChars + 6);
+    XawDialogAddButton(dialog, _("Knight"), PromotionCallback, PromoChars + 7);
     }
     if (!appData.testLegality || gameInfo.variant == VariantSuicide ||
         gameInfo.variant == VariantSpartan && !WhiteOnMove(currentMove) ||
         gameInfo.variant == VariantGiveaway) {
-      XawDialogAddButton(dialog, _("King"), PromotionCallback,
-                        (XtPointer) dialog);
+      XawDialogAddButton(dialog, _("King"), PromotionCallback, PromoChars + 8);
     }
     if(gameInfo.variant == VariantCapablanca ||
        gameInfo.variant == VariantGothic ||
        gameInfo.variant == VariantCapaRandom) {
-      XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback,
-                        (XtPointer) dialog);
-      XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback,
-                        (XtPointer) dialog);
+      XawDialogAddButton(dialog, _("Archbishop"), PromotionCallback, PromoChars + 9);
+      XawDialogAddButton(dialog, _("Chancellor"), PromotionCallback, PromoChars + 10);
     }
   } else // [HGM] shogi
   {
-      XawDialogAddButton(dialog, _("Promote"), PromotionCallback,
-                        (XtPointer) dialog);
-      XawDialogAddButton(dialog, _("Defer"), PromotionCallback,
-                        (XtPointer) dialog);
+      XawDialogAddButton(dialog, _("Promote"), PromotionCallback, PromoChars + 11);
+      XawDialogAddButton(dialog, _("Defer"), PromotionCallback, PromoChars + 12);
   }
-    XawDialogAddButton(dialog, _("cancel"), PromotionCallback,
-                      (XtPointer) dialog);
+    XawDialogAddButton(dialog, _("cancel"), PromotionCallback, PromoChars + 13);
 
     XtRealizeWidget(promotionShell);
     CatchDeleteWindow(promotionShell, "PromotionPopDown");
@@ -5218,31 +5210,17 @@ void PromotionCallback(w, client_data, call_data)
      Widget w;
      XtPointer client_data, call_data;
 {
-    String name;
-    Arg args[16];
-    int promoChar;
-
-    XtSetArg(args[0], XtNlabel, &name);
-    XtGetValues(w, args, 1);
+    int promoChar = * (const char *) client_data;
 
     PromotionPopDown();
 
     if (fromX == -1) return;
 
-    if (strcmp(name, _("cancel")) == 0) {
+    if (! promoChar) {
        fromX = fromY = -1;
        ClearHighlights();
        return;
-    } else if (strcmp(name, _("Knight")) == 0) {
-       promoChar = 'n';
-    } else if (strcmp(name, _("Promote")) == 0) {
-       promoChar = '+';
-    } else if (strcmp(name, _("Defer")) == 0) {
-       promoChar = '=';
-    } else {
-       promoChar = ToLower(name[0]);
     }
-
     UserMoveEvent(fromX, fromY, toX, toY, promoChar);
 
     if (!appData.highlightLastMove || gotPremove) ClearHighlights();
@@ -5638,11 +5616,19 @@ SendPositionSelection(Widget w, Atom *selection, Atom *target,
     *value_return = targets_tmp;
     *type_return = XA_ATOM;
     *length_return = 2;
+#if 0
+    // This code leads to a read of value_return out of bounds on 64-bit systems.
+    // Other code which I have seen always sets *format_return to 32 independent of
+    // sizeof(Atom) without adjusting *length_return. For instance see TextConvertSelection()
+    // at http://cgit.freedesktop.org/xorg/lib/libXaw/tree/src/Text.c -- BJ
     *format_return = 8 * sizeof(Atom);
     if (*format_return > 32) {
       *length_return *= *format_return / 32;
       *format_return = 32;
     }
+#else
+    *format_return = 32;
+#endif
     return True;
   } else {
     return False;
@@ -5747,11 +5733,19 @@ SendGameSelection(Widget w, Atom *selection, Atom *target,
     *value_return = targets_tmp;
     *type_return = XA_ATOM;
     *length_return = 2;
+#if 0
+    // This code leads to a read of value_return out of bounds on 64-bit systems.
+    // Other code which I have seen always sets *format_return to 32 independent of
+    // sizeof(Atom) without adjusting *length_return. For instance see TextConvertSelection()
+    // at http://cgit.freedesktop.org/xorg/lib/libXaw/tree/src/Text.c -- BJ
     *format_return = 8 * sizeof(Atom);
     if (*format_return > 32) {
       *length_return *= *format_return / 32;
       *format_return = 32;
     }
+#else
+    *format_return = 32;
+#endif
     return True;
   } else {
     return False;
@@ -6241,6 +6235,37 @@ void BackwardProc(w, event, prms, nprms)
     BackwardEvent();
 }
 
+void TempBackwardProc(w, event, prms, nprms)
+     Widget w;
+     XEvent *event;
+     String *prms;
+     Cardinal *nprms;
+{
+       if (!TempBackwardActive) {
+               TempBackwardActive = True;
+               BackwardEvent();
+       }
+}
+
+void TempForwardProc(w, event, prms, nprms)
+     Widget w;
+     XEvent *event;
+     String *prms;
+     Cardinal *nprms;
+{
+       /* Check to see if triggered by a key release event for a repeating key.
+        * If so the next queued event will be a key press of the same key at the same time */
+       if (XEventsQueued(xDisplay, QueuedAfterReading)) {
+               XEvent next;
+               XPeekEvent(xDisplay, &next);
+               if (next.type == KeyPress && next.xkey.time == event->xkey.time &&
+                       next.xkey.keycode == event->xkey.keycode)
+                               return;
+       }
+    ForwardEvent();
+       TempBackwardActive = False;
+}
+
 void ToStartProc(w, event, prms, nprms)
      Widget w;
      XEvent *event;