Implement Tournament Manager
[xboard.git] / xoptions.c
index 688e185..2408184 100644 (file)
@@ -80,22 +80,6 @@ extern char *getenv();
 # define N_(s)  s
 #endif
 
-extern void SendToProgram P((char *message, ChessProgramState *cps));
-FILE * XsraSelFile P((Widget w, char *prompt, char *ok, char *cancel, char *failed,
-               char *init_path, char *filter, char *mode, int (*show_entry)(), char **name_return));
-
-extern Widget formWidget, shellWidget, boardWidget, menuBarWidget;
-extern Display *xDisplay;
-extern int squareSize;
-extern Pixmap xMarkPixmap;
-extern char *layoutName;
-extern Window xBoardWindow;
-extern Arg layoutArgs[2], formArgs[2];
-Pixel timerForegroundPixel, timerBackgroundPixel;
-extern int searchTime;
-extern Atom wm_delete_window;
-extern int lineGap;
-
 // [HGM] the following code for makng menu popups was cloned from the FileNamePopUp routines
 
 static Widget previous = NULL;
@@ -119,8 +103,6 @@ void SetFocus(Widget w, XtPointer data, XEvent *event, Boolean *b)
 }
 
 //--------------------------- New Shuffle Game --------------------------------------------
-extern int shuffleOpenings;
-extern int startedFromPositionFile;
 int shuffleUp;
 Widget shuffleShell;
 
@@ -332,7 +314,7 @@ void TimeControlCallback(w, client_data, call_data)
         return;
     }
     if (strcmp(name, _(" OK ")) == 0) {
-       int inc, mps, ok;
+       int inc, mps, ok=0;
        XtSetArg(args[0], XtNstring, &txt);
        XtGetValues(tcData, args, 1);
        switch(tcInc) {
@@ -620,11 +602,13 @@ void TimeControlProc(w, event, prms, nprms)
 
 //--------------------------- Engine-specific options menu ----------------------------------
 
+typedef void ButtonCallback(int n);
+
 int values[MAX_OPTIONS];
 ChessProgramState *currentCps;
 static Option *currentOption;
-extern Widget shells[];
 static Boolean browserUp;
+ButtonCallback *comboCallback;
 
 void CheckCallback(Widget ww, XtPointer data, XEvent *event, Boolean *b)
 {
@@ -694,8 +678,10 @@ void ComboSelect(w, addr, index) // callback for all combo items
     int j = 255 & (intptr_t) addr;
 
     values[i] = j; // store in temporary, for transfer at OK
-    XtSetArg(args[0], XtNlabel, ((char**)currentOption[i].textValue)[j]);
+    XtSetArg(args[0], XtNlabel, _(((char**)currentOption[i].textValue)[j]));
     XtSetValues(currentOption[i].handle, args, 1);
+
+    if(currentOption[i].min & 1 && !currentCps && comboCallback) (comboCallback)(i);
 }
 
 void CreateComboPopup(parent, name, n, mb)
@@ -712,6 +698,7 @@ void CreateComboPopup(parent, name, n, mb)
                              parent, NULL, 0);
     j = 0;
     XtSetArg(args[j], XtNwidth, 100);  j++;
+    XtSetArg(args[j], XtNlabel, _(mb[i]));  j++;
 //    XtSetArg(args[j], XtNright, XtChainRight);  j++;
     while (mb[i] != NULL) {
            entry = XtCreateManagedWidget(mb[i], smeBSBObjectClass,
@@ -728,8 +715,6 @@ void CreateComboPopup(parent, name, n, mb)
 
 // cloned from Engine Settings dialog (and later merged with it)
 
-typedef void ButtonCallback(int n);
-
 extern WindowPlacement wpComment, wpTags;
 char *trialSound;
 static int oldCores, oldPonder;
@@ -786,20 +771,53 @@ void GenericPopDown(w, event, prms, nprms)
      String *prms;
      Cardinal *nprms;
 {
-    int n;
     if(browserUp) return; // prevent closing dialog when it has an open file-browse daughter
     PopDown(prms[0][0] - '0');
 }
 
+char *engineName, *engineDir, *engineChoice, *engineLine;
+Boolean isUCI, hasBook, storeVariant, v1, addToList;
+extern Option installOptions[], matchOptions[];
+char *engineNr[] = { N_("First Engine"), N_("Second Engine"), NULL };
+char *engineList[100] = {" "}, *engineMnemonic[100] = {""};
+
+void AddToTourney(int n)
+{
+    Arg args[2];
+    char *p, *val, buf[10000];
+    XawTextBlock t;
+
+    GenericReadout(4);  // selected engine
+    t.ptr = engineChoice; t.firstPos = 0; t.length = strlen(engineChoice); t.format = XawFmt8Bit;
+    XawTextReplace(matchOptions[3].handle, 9999, 9999, &t);
+    t.ptr = "\n"; t.length = 1;
+    XawTextReplace(matchOptions[3].handle, 9999, 9999, &t);
+}
+
+void MatchOK(int n)
+{
+    if(appData.participants && appData.participants[0]) free(appData.participants);
+    appData.participants = strdup(engineName);
+    PopDown(0); // early popdown to prevent FreezeUI called through MatchEvent from causing XtGrab warning
+    if(CreateTourney(appData.tourneyFile)) MatchEvent(2); // start tourney
+}
+
 Option matchOptions[] = {
-{ 0,  2, 1000000000, NULL, (void*) &appData.defaultMatchGames, "", NULL, Spin, N_("Default Number of Games in Match:") },
+{ 0,  0,          0, NULL, (void*) &appData.tourneyFile, "", NULL, FileName, N_("Tournament file:") },
+{ 0,  0,          0, NULL, (void*) &appData.roundSync, "", NULL, CheckBox, N_("Sync after round    (for concurrent playing of a single") },
+{ 0,  0,          0, NULL, (void*) &appData.cycleSync, "", NULL, CheckBox, N_("Sync after cycle      tourney with multiple XBoards)") },
+{ 0xD, 150,       0, NULL, (void*) &engineName, "", NULL, TextBox, "Tourney participants:" },
+{ 0,  1,          0, NULL, (void*) &engineChoice, (char*) (engineMnemonic+1), (engineMnemonic+1), ComboBox, N_("Select Engine:") },
+{ 0,  0,         10, NULL, (void*) &appData.tourneyType, "", NULL, Spin, N_("Tourney type (0 = round-robin, 1 = gauntlet):") },
+{ 0,  1, 1000000000, NULL, (void*) &appData.tourneyCycles, "", NULL, Spin, N_("Number of tourney cycles:") },
+{ 0,  1, 1000000000, NULL, (void*) &appData.defaultMatchGames, "", NULL, Spin, N_("Default Number of Games in Match (or Pairing):") },
 { 0,  0, 1000000000, NULL, (void*) &appData.matchPause, "", NULL, Spin, N_("Pause between Match Games (msec):") },
 { 0,  0,          0, NULL, (void*) &appData.loadGameFile, "", NULL, FileName, N_("Game File with Opening Lines:") },
 { 0, -2, 1000000000, NULL, (void*) &appData.loadGameIndex, "", NULL, Spin, N_("Game Number (-1 or -2 = Auto-Increment):") },
 { 0,  0,          0, NULL, (void*) &appData.loadPositionFile, "", NULL, FileName, N_("File with Start Positions:") },
 { 0, -2, 1000000000, NULL, (void*) &appData.loadPositionIndex, "", NULL, Spin, N_("Position Number (-1 or -2 = Auto-Increment):") },
 { 0,  0, 1000000000, NULL, (void*) &appData.rewindIndex, "", NULL, Spin, N_("Rewind Index after this many Games (0 = never):") },
-{ 0, 0, 0, NULL, NULL, "", NULL, EndMark , "" }
+{ 0, 0, 0, NULL, (void*) &MatchOK, "", NULL, EndMark , "" }
 };
 
 void GeneralOptionsOK(int n)
@@ -1092,7 +1110,7 @@ void SetColor(char *colorName, Widget box)
            } else {
                buttonColor = *(Pixel *) vTo.addr;
            }
-       }
+       } else buttonColor = (Pixel) 0;
        XtSetArg(args[0], XtNbackground, buttonColor);;
        XtSetValues(box, args, 1);
 }
@@ -1149,7 +1167,6 @@ void AdjustColor(int i)
 
 void BoardOptionsOK(int n)
 {
-    extern int defaultLineGap, useImages, useImageSqs;
     if(appData.overrideLineGap >= 0) lineGap = appData.overrideLineGap; else lineGap = defaultLineGap;
     useImages = useImageSqs = 0;
     MakeColors(); CreateGCs(True);
@@ -1209,7 +1226,7 @@ Option boardOptions[] = {
 void GenericReadout(int selected)
 {
     int i, j;
-    String name, val;
+    String val;
     Arg args[16];
     char buf[MSG_SIZ], **dest;
     float x;
@@ -1292,10 +1309,9 @@ void GenericCallback(w, client_data, call_data)
      Widget w;
      XtPointer client_data, call_data;
 {
-    String name, val;
+    String name;
     Arg args[16];
     char buf[MSG_SIZ];
-    int i, j;
     int data = (intptr_t) client_data;
 
     currentOption = dialogOptions[data>>16]; data &= 0xFFFF;
@@ -1325,7 +1341,7 @@ int
 GenericPopUp(Option *option, char *title, int dlgNr)
 {
     Arg args[16];
-    Widget popup, layout, dialog, edit=NULL, form,  last, b_ok, b_cancel, leftMargin = NULL, textField = NULL;
+    Widget popup, layout, dialog=NULL, edit=NULL, form,  last, b_ok, b_cancel, leftMargin = NULL, textField = NULL;
     Window root, child;
     int x, y, i, j, height=999, width=1, h, c, w;
     int win_x, win_y, maxWidth, maxTextWidth;
@@ -1348,9 +1364,10 @@ GenericPopUp(Option *option, char *title, int dlgNr)
 
     if(currentCps) { // Settings popup for engine: format through heuristic
        int n = currentCps->nrOptions;
+       if(!n) { DisplayNote(_("Engine has no options")); return 0; }
        if(n > 50) width = 4; else if(n>24) width = 2; else width = 1;
        height = n / width + 1;
-       if(currentOption[n-1].type == Button || currentOption[n-1].type == SaveButton) currentOption[n].min = 1; // OK on same line
+       if(n && (currentOption[n-1].type == Button || currentOption[n-1].type == SaveButton)) currentOption[n].min = 1; // OK on same line
        currentOption[n].type = EndMark; currentOption[n].target = NULL; // delimit list by callback-less end mark
     }
      i = 0;
@@ -1397,6 +1414,7 @@ GenericPopUp(Option *option, char *title, int dlgNr)
            XtSetArg(args[j], XtNright, XtChainLeft); j++;
            XtSetArg(args[j], XtNborderWidth, 0);  j++;
            XtSetArg(args[j], XtNjustify, XtJustifyLeft);  j++;
+           XtSetArg(args[j], XtNlabel, _(option[i].name));  j++;
            texts[h] =
            dialog = XtCreateManagedWidget(option[i].name, labelWidgetClass, form, args, j);
            } else texts[h] = dialog = NULL;
@@ -1439,7 +1457,7 @@ GenericPopUp(Option *option, char *title, int dlgNr)
            XtSetArg(args[j], XtNleft, XtChainRight); j++;
            XtSetArg(args[j], XtNright, XtChainRight); j++;
            if(option[i].type == FileName || option[i].type == PathName) {
-               w = 50; msg = "browse";
+               w = 50; msg = _("browse");
            } else {
                XtSetArg(args[j], XtNheight, 10);  j++;
                w = 20; msg = "+";
@@ -1481,6 +1499,7 @@ GenericPopUp(Option *option, char *title, int dlgNr)
            XtSetArg(args[j], XtNleft, XtChainLeft); j++;
            XtSetArg(args[j], XtNborderWidth, 0);  j++;
            XtSetArg(args[j], XtNjustify, XtJustifyLeft);  j++;
+           XtSetArg(args[j], XtNlabel, _(msg));  j++;
            last = XtCreateManagedWidget(msg, labelWidgetClass, form, args, j);
            if(option[i].type == CheckBox)
                XtAddEventHandler(last, ButtonPressMask, False, CheckCallback, (XtPointer)(intptr_t) i);
@@ -1489,6 +1508,7 @@ GenericPopUp(Option *option, char *title, int dlgNr)
          case Button:
            j=0;
            XtSetArg(args[j], XtNfromVert, option[i].min & 1 ? lastrow : last);  j++;
+           XtSetArg(args[j], XtNlabel, _(option[i].name));  j++;
            if(option[i].min & 1) { XtSetArg(args[j], XtNfromHoriz, last);  j++; }
            else  { XtSetArg(args[j], XtNfromHoriz, NULL);  j++; lastrow = forelast; }
            if(option[i].max) XtSetArg(args[j], XtNwidth, option[i].max);  j++;
@@ -1515,6 +1535,7 @@ GenericPopUp(Option *option, char *title, int dlgNr)
            XtSetArg(args[j], XtNright, XtChainLeft); j++;
            XtSetArg(args[j], XtNborderWidth, 0);  j++;
            XtSetArg(args[j], XtNjustify, XtJustifyLeft);  j++;
+           XtSetArg(args[j], XtNlabel, _(option[i].name));  j++;
            texts[h] = dialog = XtCreateManagedWidget(option[i].name, labelWidgetClass, form, args, j);
 
            if(currentCps) option[i].choice = (char**) option[i].textValue; else {
@@ -1529,7 +1550,7 @@ GenericPopUp(Option *option, char *title, int dlgNr)
            XtSetArg(args[j], XtNwidth, option[i].max && !currentCps ? option[i].max : 100);  j++;
            XtSetArg(args[j], XtNleft, XtChainLeft); j++;
            XtSetArg(args[j], XtNmenuName, XtNewString(option[i].name));  j++;
-           XtSetArg(args[j], XtNlabel, ((char**)option[i].textValue)[option[i].value]);  j++;
+           XtSetArg(args[j], XtNlabel, _(((char**)option[i].textValue)[option[i].value]));  j++;
            option[i].handle = (void*)
                (last = XtCreateManagedWidget(" ", menuButtonWidgetClass, form, args, j));
            CreateComboPopup(last, option[i].name, i, (char **) option[i].textValue);
@@ -1732,14 +1753,15 @@ void MatchOptionsProc(w, event, prms, nprms)
      String *prms;
      Cardinal *nprms;
 {
+   NamesToList(firstChessProgramNames, engineList, engineMnemonic);
+   comboCallback = &AddToTourney;
    GenericPopUp(matchOptions, _("Match Options"), 0);
 }
 
 Option textOptions[100];
-extern char *icsTextMenuString;
 void PutText P((char *text, int pos));
 
-SendString(char *p)
+void SendString(char *p)
 {
     char buf[MSG_SIZ], *q;
     if(q = strstr(p, "$input")) {
@@ -1902,7 +1924,6 @@ void NewTagsPopup(char *text, char *msg)
     GenericPopUp(tagsOptions, _("Tags"), 2);
 }
 
-extern char ICSInputTranslations[];
 char *icsText;
 
 Option boxOptions[] = {
@@ -1912,7 +1933,6 @@ Option boxOptions[] = {
 
 void PutText(char *text, int pos)
 {
-    Widget edit;
     Arg args[16];
     char buf[MSG_SIZ], *p;
 
@@ -2006,6 +2026,42 @@ void SecondSettingsProc(w, event, prms, nprms)
    SettingsPopUp(&second);
 }
 
+void InstallOK(int n)
+{
+    PopDown(0); // early popdown, to allow FreezeUI to instate grab
+    if(engineChoice[0] == engineNr[0][0])  Load(&first, 0); else Load(&second, 1);
+}
+
+Option installOptions[] = {
+{   0,  0,    0, NULL, (void*) &engineLine, (char*) engineMnemonic, engineList, ComboBox, N_("Select engine from list:") },
+{   0,  0,    0, NULL, NULL, NULL, NULL, Label, N_("or specify one below:") },
+{   0,  0,    0, NULL, (void*) &nickName, NULL, NULL, TextBox, N_("Nickname (optional):") },
+{   0,  0,    0, NULL, (void*) &engineDir, NULL, NULL, PathName, N_("Engine Directory:") },
+{   0,  0,    0, NULL, (void*) &engineName, NULL, NULL, FileName, N_("Engine Command:") },
+{   0,  0,    0, NULL, NULL, NULL, NULL, Label, N_("(Directory will be derived from engine path when empty)") },
+{   0,  0,    0, NULL, (void*) &isUCI, NULL, NULL, CheckBox, N_("UCI") },
+{   0,  0,    0, NULL, (void*) &v1, NULL, NULL, CheckBox, N_("WB protocol v1 (do not wait for engine features)") },
+{   0,  0,    0, NULL, (void*) &hasBook, NULL, NULL, CheckBox, N_("Must not use GUI book") },
+{   0,  0,    0, NULL, (void*) &addToList, NULL, NULL, CheckBox, N_("Add this engine to the list") },
+{   0,  0,    0, NULL, (void*) &storeVariant, NULL, NULL, CheckBox, N_("Force current variant with this engine") },
+{   0,  0,    0, NULL, (void*) &engineChoice, (char*) engineNr, engineNr, ComboBox, N_("Load mentioned engine as") },
+{   0,  1,    0, NULL, (void*) &InstallOK, "", NULL, EndMark , "" }
+};
+
+void LoadEngineProc(w, event, prms, nprms)
+     Widget w;
+     XEvent *event;
+     String *prms;
+     Cardinal *nprms;
+{
+   isUCI = addToList = storeVariant = v1 = False; hasBook = True; // defaults
+   engineDir = nickName = ""; 
+   if(engineChoice) free(engineChoice); engineChoice = strdup(engineNr[0]);
+   if(engineLine)   free(engineLine);   engineLine = strdup("");
+   NamesToList(firstChessProgramNames, engineList, engineMnemonic);
+   GenericPopUp(installOptions, _("Load engine"), 0);
+}
+
 //---------------------------- Chat Windows ----------------------------------------------
 
 void OutputChatMessage(int partner, char *mess)