Put new options in WB ICS-options dialog
[xboard.git] / xboard.c
index edf20c6..2ce05c6 100644 (file)
--- a/xboard.c
+++ b/xboard.c
@@ -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));
@@ -355,15 +357,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,
@@ -476,6 +482,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;
@@ -638,6 +646,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},
@@ -651,6 +660,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},
@@ -898,13 +908,17 @@ 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 },
@@ -1014,6 +1028,8 @@ char whiteTranslations[] = "<BtnDown>: WhiteClock()\n";
 char blackTranslations[] = "<BtnDown>: BlackClock()\n";
 
 char ICSInputTranslations[] =
+    "<Key>Up: UpKeyProc() \n "
+    "<Key>Down: DownKeyProc() \n "
     "<Key>Return: EnterKeyProc() \n";
 
 String xboardResources[] = {
@@ -1532,6 +1548,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
@@ -1552,7 +1570,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);
 
@@ -1562,6 +1580,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; i<BOARD_WIDTH+BOARD_HEIGHT+2; i++) { // [HGM] dual: grid for second board
+       secondSegments[i] = gridSegments[i];
+       secondSegments[i].x1 += hOffset;
+       secondSegments[i].x2 += hOffset;
+    }
 
     XtSetArg(args[0], XtNwidth, boardWidth);
     XtSetArg(args[1], XtNheight, boardHeight);
@@ -1600,7 +1624,7 @@ void InitDrawingSizes(BoardSize boardSize, int flags)
     /*
      * Inhibit shell resizing.
      */
-    shellArgs[0].value = w = (XtArgVal) boardWidth + marginW;
+    shellArgs[0].value = w = (XtArgVal) boardWidth + marginW + twoBoards*hOffset; // [HGM] dual
     shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
     shellArgs[4].value = shellArgs[2].value = w;
     shellArgs[5].value = shellArgs[3].value = h;
@@ -2613,6 +2637,12 @@ GreyRevert(grey)
     } else {
       XtSetSensitive(w, !grey);
     }
+    w = XtNameToWidget(menuBarWidget, "menuStep.Annotate");
+    if (w == NULL) {
+      DisplayError("menuStep.Annotate", 0);
+    } else {
+      XtSetSensitive(w, !grey);
+    }
 }
 
 void
@@ -2648,6 +2678,7 @@ Enables icsEnables[] = {
     { "menuOptions.Hide Thinking", False },
     { "menuOptions.Ponder Next Move", False },
 #endif
+    { "menuStep.Annotate", False },
     { NULL, False }
 };
 
@@ -2663,6 +2694,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 },
@@ -2691,7 +2723,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 },
@@ -2852,6 +2886,51 @@ SetMachineThinkingEnables()
   }
 }
 
+// [HGM] code borrowed from winboard.c (which should thus go to backend.c!)
+#define HISTORY_SIZE 64\r
+static char *history[HISTORY_SIZE];\r
+int histIn = 0, histP = 0;\r
+\r
+void\r
+SaveInHistory(char *cmd)\r
+{\r
+  if (history[histIn] != NULL) {\r
+    free(history[histIn]);\r
+    history[histIn] = NULL;\r
+  }\r
+  if (*cmd == NULLCHAR) return;\r
+  history[histIn] = StrSave(cmd);\r
+  histIn = (histIn + 1) % HISTORY_SIZE;\r
+  if (history[histIn] != NULL) {\r
+    free(history[histIn]);\r
+    history[histIn] = NULL;\r
+  }\r
+  histP = histIn;\r
+}\r
+\r
+char *\r
+PrevInHistory(char *cmd)\r
+{\r
+  int newhp;\r
+  if (histP == histIn) {\r
+    if (history[histIn] != NULL) free(history[histIn]);\r
+    history[histIn] = StrSave(cmd);\r
+  }\r
+  newhp = (histP - 1 + HISTORY_SIZE) % HISTORY_SIZE;\r
+  if (newhp == histIn || history[newhp] == NULL) return NULL;\r
+  histP = newhp;\r
+  return history[histP];\r
+}\r
+\r
+char *\r
+NextInHistory()\r
+{\r
+  if (histP == histIn) return NULL;\r
+  histP = (histP + 1) % HISTORY_SIZE;\r
+  return history[histP];   \r
+}
+// end of borrowed code\r
+\r
 #define Abs(n) ((n)<0 ? -(n) : (n))
 
 /*
@@ -4117,6 +4196,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
@@ -4353,6 +4434,7 @@ void XDrawPosition(w, repaint, board)
     int rrow, rcol;
 
     if(DrawSeekGraph()) return; // [HGM] seekgraph: suppress any drawing if seek graph up
+    if(twoBoards) repaint = True;
 
     if (board == NULL) {
        if (!lastBoardValid) return;
@@ -4405,6 +4487,7 @@ void XDrawPosition(w, repaint, board)
     } 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++)
@@ -4891,6 +4974,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);
@@ -4993,45 +5077,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: ",
+           NULL, openMode, NULL, &name))
+               (void) (*fileProc)(f, index=0, name);
+    }
 }
 
 void FileNamePopDown()
@@ -6100,6 +6153,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;
@@ -6118,6 +6220,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;
@@ -6162,7 +6273,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)