Fix help clicks in Engine Settings dialogs
[xboard.git] / dialogs.c
index ca9f71c..306bc97 100644 (file)
--- a/dialogs.c
+++ b/dialogs.c
@@ -66,6 +66,7 @@ extern char *getenv();
 
 int values[MAX_OPTIONS];
 ChessProgramState *currentCps;
 
 int values[MAX_OPTIONS];
 ChessProgramState *currentCps;
+char manDir[MSG_SIZ] = MANDIR;
 
 //----------------------------Generic dialog --------------------------------------------
 
 
 //----------------------------Generic dialog --------------------------------------------
 
@@ -545,7 +546,7 @@ Pick (int n)
        }
 
        gameInfo.variant = v;
        }
 
        gameInfo.variant = v;
-       appData.variant = VariantName(v);
+       ASSIGN(appData.variant, VariantName(v));
 
        shuffleOpenings = FALSE; /* [HGM] shuffle: possible shuffle reset when we switch */
        startedFromPositionFile = FALSE; /* [HGM] loadPos: no longer valid in new variant */
 
        shuffleOpenings = FALSE; /* [HGM] shuffle: possible shuffle reset when we switch */
        startedFromPositionFile = FALSE; /* [HGM] loadPos: no longer valid in new variant */
@@ -554,8 +555,9 @@ Pick (int n)
        appData.NrFiles = filesTmp;
        appData.holdingsSize = sizeTmp;
        appData.pieceToCharTable = NULL;
        appData.NrFiles = filesTmp;
        appData.holdingsSize = sizeTmp;
        appData.pieceToCharTable = NULL;
-       appData.pieceNickNames = "";
-       appData.colorNickNames = "";
+       ASSIGN(appData.pieceNickNames, "");
+       ASSIGN(appData.colorNickNames, "");
+       ASSIGN(appData.men, "");
         PopDown(TransientDlg);
        Reset(True, True);
         return;
         PopDown(TransientDlg);
        Reset(True, True);
         return;
@@ -1259,7 +1261,7 @@ NewTagsPopup (char *text, char *msg, char *ttl)
     if(tagsText) free(tagsText); tagsText = strdup(text);
     tagsOptions[0].name = msg;
     MarkMenu("View.Tags", TagsDlg);
     if(tagsText) free(tagsText); tagsText = strdup(text);
     tagsOptions[0].name = msg;
     MarkMenu("View.Tags", TagsDlg);
-    GenericPopUp(tagsOptions, title, TagsDlg, BoardWindow, NONMODAL, appData.topLevel);
+    GenericPopUp(tagsOptions + (msg == NULL), title, TagsDlg, BoardWindow, NONMODAL, appData.topLevel);
 }
 
 void
 }
 
 void
@@ -1310,10 +1312,12 @@ char *icsText;
 #define HISTORY_SIZE 64
 static char *history[HISTORY_SIZE];
 static int histIn = 0, histP = 0;
 #define HISTORY_SIZE 64
 static char *history[HISTORY_SIZE];
 static int histIn = 0, histP = 0;
+static Boolean noEcho;
 
 static void
 SaveInHistory (char *cmd)
 {
 
 static void
 SaveInHistory (char *cmd)
 {
+  if(noEcho) return; // do not save password!
   if (history[histIn] != NULL) {
     free(history[histIn]);
     history[histIn] = NULL;
   if (history[histIn] != NULL) {
     free(history[histIn]);
     history[histIn] = NULL;
@@ -1603,10 +1607,10 @@ static Option shuffleOptions[] = {
 static void
 SetRandom (int n)
 {
 static void
 SetRandom (int n)
 {
-    int r = n==2 ? -1 : random() & (1<<30)-1;
+    int r = n==3 ? -1 : random() & (1<<30)-1;
     char buf[MSG_SIZ];
     snprintf(buf, MSG_SIZ,  "%d", r);
     char buf[MSG_SIZ];
     snprintf(buf, MSG_SIZ,  "%d", r);
-    SetWidgetText(&shuffleOptions[1], buf, TransientDlg);
+    SetWidgetText(&shuffleOptions[2], buf, TransientDlg);
     SetWidgetState(&shuffleOptions[0], True);
 }
 
     SetWidgetState(&shuffleOptions[0], True);
 }
 
@@ -1616,6 +1620,131 @@ ShuffleMenuProc ()
     GenericPopUp(shuffleOptions, _("New Shuffle Game"), TransientDlg, BoardWindow, MODAL, 0);
 }
 
     GenericPopUp(shuffleOptions, _("New Shuffle Game"), TransientDlg, BoardWindow, MODAL, 0);
 }
 
+//--------------------------------------------------- Fonts ------------------------------
+
+static void AdjustFont P((int n));
+
+static int
+FontsOK (int n)
+{
+    extern Option historyOptions[], engoutOptions[], gamesOptions[], chatOptions[];
+    int i;
+    DisplayBothClocks();
+    ApplyFont(&mainOptions[W_MESSG], NULL);
+    for(i=1; i<6; i++) ApplyFont(&mainOptions[W_BUTTON+i], NULL);
+    ApplyFont(&tagsOptions[1], NULL);
+    ApplyFont(&historyOptions[0], NULL);
+    ApplyFont(&engoutOptions[5], NULL);
+    ApplyFont(&engoutOptions[12], NULL);
+    ApplyFont(&gamesOptions[0], NULL);
+    ApplyFont(&chatOptions[11], appData.icsFont);
+    AppendColorized(&chatOptions[6], NULL, 0); // kludge to replace font tag
+    DrawPosition(TRUE, NULL); // for coord font
+    return 1;
+}
+
+static Option fontOptions[] = {
+  { 0,        60, 200, NULL, (void*) &appData.clockFont, NULL, NULL, TextBox, N_("Clocks (requires restart):") },
+  {    1, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("+") },
+  {    2, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("-") },
+  {    3, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("B") },
+  {    4, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("I") },
+  {  666, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("*") },
+  { 0,         60, 70, NULL, (void*) &appData.font, NULL, NULL, TextBox, N_("Message (above board):") },
+  {    1, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("+") },
+  {    2, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("-") },
+  {    3, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("B") },
+  {    4, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("I") },
+  {  666, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("*") },
+  { 0,         60, 70, NULL, (void*) &appData.icsFont, NULL, NULL, TextBox, N_("ICS Chat/Console:") },
+  {    1, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("+") },
+  {    2, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("-") },
+  {    3, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("B") },
+  {    4, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("I") },
+  {  666, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("*") },
+  { 0,         60, 70, NULL, (void*) &appData.tagsFont, NULL, NULL, TextBox, N_("Edit tags / book / engine list:") },
+  {    1, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("+") },
+  {    2, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("-") },
+  {    3, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("B") },
+  {    4, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("I") },
+  {  666, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("*") },
+  { 0,         60, 70, NULL, (void*) &appData.commentFont, NULL, NULL, TextBox, N_("Edit comments:") },
+  {    1, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("+") },
+  {    2, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("-") },
+  {    3, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("B") },
+  {    4, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("I") },
+  {  666, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("*") },
+  { 0,         60, 70, NULL, (void*) &appData.historyFont, NULL, NULL, TextBox, N_("Move history / Engine Output:") },
+  {    1, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("+") },
+  {    2, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("-") },
+  {    3, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("B") },
+  {    4, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("I") },
+  {  666, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("*") },
+  { 0,         60, 70, NULL, (void*) &appData.gameListFont, NULL, NULL, TextBox, N_("Game list:") },
+  {    1, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("+") },
+  {    2, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("-") },
+  {    3, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("B") },
+  {    4, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("I") },
+  {  666, SAME_ROW, 0, NULL, (void*) &AdjustFont, NULL, NULL, Button, N_("*") },
+  {   0,  0,    0, NULL, NULL, NULL, NULL, Label, N_("\nThe * buttons will set the font to the one selected below:") },
+  {   0,  0,    0, NULL, NULL, NULL, NULL, Button, "fontsel" },
+  { 0, 0, 0, NULL, (void*) &FontsOK, "", NULL, EndMark , "" }
+};
+
+static char name[MSG_SIZ], *bold, *ital, points;
+
+static void
+BreakUp (char *font)
+{
+    char *p = name, *norm;
+    safeStrCpy(name, font, MSG_SIZ);
+    bold = StrCaseStr(name, "bold");
+    ital = StrCaseStr(name, "ital");
+    norm = StrCaseStr(name, "normal");
+    points = 0;
+    while(p && *p && !(points = atoi(p))) p = strchr(p+1, ' ');
+    if(points) p[*p == ' '] = 0;
+    if(bold) *bold = 0;
+    if(ital) *ital = 0;
+    if(norm) *norm = 0;
+}
+
+static void
+Collect ()
+{
+    if(bold) strcat(name, "Bold ");
+    if(ital) strcat(name, "Italic ");
+    if(!ital && !bold && strlen(name) < 2) strncpy(name, "Normal ", MSG_SIZ);
+    if(points) sprintf(name + strlen(name), "%d", points); else strcat(name, "%d");
+}
+
+static void
+AdjustFont (int n)
+{
+    int button = fontOptions[n].value, base = n - button;
+    char *oldFont;
+    GetWidgetText(&fontOptions[base], &oldFont);
+    BreakUp(oldFont); // take apart old font name
+    switch(button) {
+      case 1: points++; break;
+      case 2: points--; break;
+      case 3: if(bold) bold = NULL; else bold = name; break;
+      case 4: if(ital) ital = NULL; else ital = name; break;
+    }
+    Collect();
+    SetWidgetText(&fontOptions[base], name, TransientDlg);
+    ApplyFont(&fontOptions[base], name);
+}
+
+void
+FontsProc ()
+{
+    int i;
+    if(strstr(appData.font, "-*-")) { DisplayNote(_("This only works in the GTK build")); return; }
+    GenericPopUp(fontOptions, _("Fonts"), TransientDlg, BoardWindow, MODAL, 0);
+    for(i=0; i<6; i++) ApplyFont(&fontOptions[6*i], *(char**)fontOptions[6*i].target);
+}
+
 //------------------------------------------------------ Time Control -----------------------------------
 
 static int TcOK P((int n));
 //------------------------------------------------------ Time Control -----------------------------------
 
 static int TcOK P((int n));
@@ -2116,6 +2245,10 @@ void
 ConsoleWrite(char *message, int count)
 {
     if(shellUp[ChatDlg] && chatOptions[CHAT_ICS].type != Skip) { // in Xaw this is a no-op
 ConsoleWrite(char *message, int count)
 {
     if(shellUp[ChatDlg] && chatOptions[CHAT_ICS].type != Skip) { // in Xaw this is a no-op
+       if(*message == 7) {
+           message++; // remove bell
+           if(strcmp(message, "\n")) return;
+       }
        AppendColorized(&chatOptions[CHAT_ICS], message, count);
        SetInsertPos(&chatOptions[CHAT_ICS], 999999);
     }
        AppendColorized(&chatOptions[CHAT_ICS], message, count);
        SetInsertPos(&chatOptions[CHAT_ICS], 999999);
     }
@@ -2156,8 +2289,6 @@ ConsoleAutoPopUp (char *buf)
        } else PopUpMoveDialog(*buf);
 }
 
        } else PopUpMoveDialog(*buf);
 }
 
-static Boolean noEcho;
-
 void
 EchoOn ()
 {
 void
 EchoOn ()
 {
@@ -2296,7 +2427,7 @@ ErrorPopDown ()
     if (errorExitStatus != -1) ExitEvent(errorExitStatus);
 }
 
     if (errorExitStatus != -1) ExitEvent(errorExitStatus);
 }
 
-static int
+int
 ErrorOK (int n)
 {
     dialogError = errorUp = False;
 ErrorOK (int n)
 {
     dialogError = errorUp = False;
@@ -2445,12 +2576,22 @@ DisplayTitle (char *text)
     SetWindowTitle(text, title, icon);
 }
 
     SetWindowTitle(text, title, icon);
 }
 
+char *textPtr;
+char *texEscapes[] = { "s-1", "s0", "&", "*(L", "*(R", NULL };
+
+int
+GetNext(FILE *f)
+{
+    if(textPtr) return *textPtr ? *textPtr++ : EOF;
+    return fgetc(f);
+}
+
 static char *
 ReadLine (FILE *f)
 {
     static char buf[MSG_SIZ];
     int i = 0, c;
 static char *
 ReadLine (FILE *f)
 {
     static char buf[MSG_SIZ];
     int i = 0, c;
-    while((c = fgetc(f)) != '\n') { if(c == EOF) return NULL; buf[i++] = c; }
+    while((c = GetNext(f)) != '\n') { if(c == EOF) return NULL; buf[i++] = c; }
     buf[i] = NULLCHAR;
     return buf;
 }
     buf[i] = NULLCHAR;
     return buf;
 }
@@ -2458,44 +2599,93 @@ ReadLine (FILE *f)
 void
 GetHelpText (FILE *f, char *name)
 {
 void
 GetHelpText (FILE *f, char *name)
 {
-    char *line, buf[MSG_SIZ], text[10000], *p = text, *q = text;
+    char *line, buf[MSG_SIZ], title[MSG_SIZ], text[10000], *p = text, *q = text;
     int len, cnt = 0;
     int len, cnt = 0;
+    while(*name == '\n') name++;
     snprintf(buf, MSG_SIZ, ".B %s", name);
     len = strlen(buf);
     snprintf(buf, MSG_SIZ, ".B %s", name);
     len = strlen(buf);
-    for(len=1; buf[len] == ' ' || isalpha(buf[len]) || isdigit(buf[len]); len++);
+    for(len=3; buf[len] && buf[len] != '(' && buf[len] != ':' && buf[len] != '.' && buf[len] != '?' && buf[len] != '\n'; len++);
     buf[len] = NULLCHAR;
     buf[len] = NULLCHAR;
-    while(buf[--len] == ' ') buf[len] = NULLCHAR;
+    while(buf[--len] == ' ') buf[len] = NULLCHAR; len++;
+    snprintf(title, MSG_SIZ, "Help on '%s'", buf+3);
     while((line = ReadLine(f))) {
     while((line = ReadLine(f))) {
-       if(!strncmp(line, buf, len) && (strncmp(line, ".SS ", 4) || strncmp(line+4, buf+3, len-3))) {
-           while((line = ReadLine(f)) && (cnt == 0 || strncmp(line, ".B ", 3))) {
+       if(!strncmp(line, buf, len) || !strncmp(line, ".SS ", 4) && !strncmp(line+4, buf+3, len-3)
+                             || !strncmp(line, ".IX Item \"", 10) && !strncmp(line+10, buf+3, len-3)) {
+           while((line = ReadLine(f)) && (cnt == 0 || strncmp(line, ".B ", 3) && strncmp(line, ".SS ", 4) && strncmp(line, ".IX ", 4))) {
                if(!*line) { *p++ = '\n'; *p++ = '\n'; q = p; continue; }
                if(*line == '.') continue;
                *p++ = ' '; cnt++;
                while(*line) {
                    if(*line < ' ') { line++; continue;}
                if(!*line) { *p++ = '\n'; *p++ = '\n'; q = p; continue; }
                if(*line == '.') continue;
                *p++ = ' '; cnt++;
                while(*line) {
                    if(*line < ' ') { line++; continue;}
+                   if(*line == '\\') {
+                       char **esc;
+                       line++;
+                       for(esc = texEscapes; *esc; esc++) {
+                           len = strlen(*esc);
+                           if(!strncmp(*esc, line, len)) {
+                               line += len;
+                               break;
+                           }
+                       }
+                       continue;
+                   }
                    if(*line == ' ' && p - q > 80) *line = '\n', q = p;
                    *p++ = *line++;
                }
                if(p - text > 9900) break;
            }
            *p = NULLCHAR;
                    if(*line == ' ' && p - q > 80) *line = '\n', q = p;
                    *p++ = *line++;
                }
                if(p - text > 9900) break;
            }
            *p = NULLCHAR;
-           DisplayNote(text);
+           ErrorPopUp(title, text, FALSE);
            return;
        }
     }
            return;
        }
     }
-    snprintf(text, MSG_SIZ, "No help on '%s'\n", buf+3);
+    snprintf(text, MSG_SIZ, "No help available on '%s'\n", buf+3);
     DisplayNote(text);
 }
 
 void
 DisplayHelp (char *name)
 {
     DisplayNote(text);
 }
 
 void
 DisplayHelp (char *name)
 {
-    char *manFile = DATADIR "/../../man/man6/xboard.6";
-    FILE *f = fopen(manFile, "r");
+    static char *xboardMan, *manText[2], tidy[MSG_SIZ], engMan[MSG_SIZ];
+    char buf[MSG_SIZ], adapter[MSG_SIZ], *eng;
+    int n = 0;
+    FILE *f;
+    if(!xboardMan) {
+       xboardMan = BufferCommandOutput("man -w xboard", MSG_SIZ); // obtain path to XBoard's man file
+       if(xboardMan) xboardMan[strlen(xboardMan)-1] = NULLCHAR;   // strip off traling linefeed
+    }
+    if(currentCps) { // for engine options we have to look in engine manual
+       snprintf(buf, MSG_SIZ, "man -w ");            // get (tidied) engine name in buf
+       TidyProgramName(currentCps->program, "localhost", adapter);       // name of binary we are actually running
+       TidyProgramName(currentCps == &first ? appData.firstChessProgram : appData.secondChessProgram, "localhost", buf+7);
+       if(strcmp(buf+7, adapter) && StrCaseStr(name, adapter) == name) { // option starts with name of apparent proxy for engine
+           safeStrCpy(buf+7, adapter, MSG_SIZ-7);    // use adapter manual
+           name += strlen(adapter);                  // strip adapter name of option
+           while(*name == ' ') name++;
+       }
+       if(strcmp(buf, tidy)) {                       // is different engine from last time
+           FREE(manText[1]); manText[1] = NULL;      // so any currently held text is worthless
+           safeStrCpy(tidy, buf, MSG_SIZ);           // remember current engine
+           eng = BufferCommandOutput(tidy, MSG_SIZ); // obtain path to  its man file
+           safeStrCpy(engMan, eng, strlen(eng));     // and remember that too
+           FREE(eng);
+       }
+       safeStrCpy(buf, engMan, MSG_SIZ); n = 1;      // use engine man
+    } else snprintf(buf, MSG_SIZ, "%s", xboardMan);   // use xboard man
+    f = fopen(buf, "r");
     if(f) {
     if(f) {
+       char *msg = "Right-clicking menu item or dialog text pops up help on it";
+       ASSIGN(appData.suppress, msg);
+       if(strstr(buf, ".gz")) { // man file is gzipped
+           if(!manText[n]) {    // unzipped text not buffered yet
+               snprintf(tidy, MSG_SIZ, "gunzip -c %s", buf);
+               manText[n] = BufferCommandOutput(tidy, 250000); // store unzipped in buffer
+           }
+           textPtr = manText[n];// use buffered unzipped text
+       } else textPtr = NULL;   // use plaintext man file directly
        GetHelpText(f, name);
        fclose(f);
        GetHelpText(f, name);
        fclose(f);
-    }
+    } else if(currentCps) DisplayNote("No manual is installed for this engine");
 }
 
 #define PAUSE_BUTTON "P"
 }
 
 #define PAUSE_BUTTON "P"
@@ -2892,6 +3082,7 @@ static char *Extensions[] = {
 ".trn",
 ".bin",
 ".wav",
 ".trn",
 ".bin",
 ".wav",
+".png",
 ".ini",
 ".log",
 "",
 ".ini",
 ".log",
 "",