Always render svg pieces anew on size change
[xboard.git] / dialogs.c
index 47efff8..42e6379 100644 (file)
--- a/dialogs.c
+++ b/dialogs.c
@@ -752,12 +752,14 @@ SoundOptionsProc ()
 static void DefColor P((int n));
 static void AdjustColor P((int i));
 
+static char oldPngDir[MSG_SIZ];
+static char oldSvgDir[MSG_SIZ];
+
 static int
 BoardOptionsOK (int n)
 {
     if(appData.overrideLineGap >= 0) lineGap = appData.overrideLineGap; else lineGap = defaultLineGap;
-    useImages = useImageSqs = 0;
-    InitDrawingParams();
+    InitDrawingParams(strcmp(oldPngDir, appData.pngDirectory) || strcmp(oldSvgDir, appData.svgDirectory));
     InitDrawingSizes(-1, 0);
     DrawPosition(True, NULL);
     return 1;
@@ -811,8 +813,8 @@ static Option boardOptions[] = {
 { 0, 0, 0, NULL, (void*) &appData.useBitmaps, "", NULL, CheckBox, N_("Use Board Textures") },
 { 0, 0, 0, NULL, (void*) &appData.liteBackTextureFile, ".xpm", NULL, FileName, N_("Light-Squares Texture File:") },
 { 0, 0, 0, NULL, (void*) &appData.darkBackTextureFile, ".xpm", NULL, FileName, N_("Dark-Squares Texture File:") },
-{ 0, 0, 0, NULL, (void*) &appData.bitmapDirectory, "", NULL, PathName, N_("Directory with Bitmap Pieces:") },
-{ 0, 0, 0, NULL, (void*) &appData.pixmapDirectory, "", NULL, PathName, N_("Directory with Pixmap Pieces:") },
+{ 0, 0, 0, NULL, (void*) &appData.pngDirectory, "", NULL, PathName, N_("Directory with PNG Pieces:") },
+{ 0, 0, 0, NULL, (void*) &appData.svgDirectory, "", NULL, PathName, N_("Directory with SVG Pieces:") },
 { 0, 0, 0, NULL, (void*) &BoardOptionsOK, "", NULL, EndMark , "" }
 };
 
@@ -861,6 +863,8 @@ AdjustColor (int i)
 void
 BoardOptionsProc ()
 {
+   strncpy(oldPngDir, appData.pngDirectory, MSG_SIZ-1); // to see if it changed
+   strncpy(oldSvgDir, appData.svgDirectory, MSG_SIZ-1); // to see if it changed
    GenericPopUp(boardOptions, _("Board Options"), TransientDlg, BoardWindow, MODAL, 0);
 }
 
@@ -892,6 +896,7 @@ IcsTextProc ()
    if((p = icsTextMenuString) == NULL) return;
    do {
        q = r = p; while(*p && *p != ';') p++;
+       if(textOptions[i].name == NULL) textOptions[i].name = (char*) malloc(MSG_SIZ);
        for(j=0; j<p-q; j++) textOptions[i].name[j] = *r++;
        textOptions[i].name[j++] = 0;
        if(!*p) break;
@@ -1066,8 +1071,8 @@ NextInHistory ()
 // end of borrowed code
 
 Option boxOptions[] = {
-{  30,  0,  400, NULL, (void*) &icsText, "", NULL, TextBox, "" },
-{  0,SAME_ROW | NO_OK, 0, NULL, NULL, "", NULL, EndMark , "" }
+{  30, T_TOP, 400, NULL, (void*) &icsText, "", NULL, TextBox, "" },
+{  0,  NO_OK,   0, NULL, NULL, "", NULL, EndMark , "" }
 };
 
 void
@@ -1113,6 +1118,7 @@ PutText (char *text, int pos)
     }
     SetWidgetText(&boxOptions[0], text, TextMenuDlg);
     SetInsertPos(&boxOptions[0], pos);
+    HardSetFocus(&boxOptions[0]);
 }
 
 void
@@ -1134,8 +1140,8 @@ IcsInputBoxProc ()
 static int TypeInOK P((int n));
 
 Option typeOptions[] = {
-{ 30,  0,            400, NULL, (void*) &icsText, "", NULL, TextBox, "" },
-{ 0, SAME_ROW | NO_OK, 0, NULL, (void*) &TypeInOK, "", NULL, EndMark , "" }
+{ 30, T_TOP, 400, NULL, (void*) &icsText, "", NULL, TextBox, "" },
+{ 0,  NO_OK,   0, NULL, (void*) &TypeInOK, "", NULL, EndMark , "" }
 };
 
 static int
@@ -1529,10 +1535,100 @@ PromotionPopUp ()
 
 //---------------------------- Chat Windows ----------------------------------------------
 
+static char *line, *memo, *partner, *texts[MAX_CHAT], dirty[MAX_CHAT];
+static int activePartner;
+
+void ChatSwitch P((int n));
+int  ChatOK P((int n));
+
+Option chatOptions[] = {
+{ 0,   T_TOP,    100, NULL, (void*) &partner, NULL, NULL, TextBox, N_("Chat partner:") },
+{ 1, SAME_ROW|TT, 75, NULL, (void*) &ChatSwitch, NULL, NULL, Button, "" },
+{ 2, SAME_ROW|TT, 75, NULL, (void*) &ChatSwitch, NULL, NULL, Button, "" },
+{ 3, SAME_ROW|TT, 75, NULL, (void*) &ChatSwitch, NULL, NULL, Button, "" },
+{ 4, SAME_ROW|TT, 75, NULL, (void*) &ChatSwitch, NULL, NULL, Button, "" },
+{ 100, T_VSCRL | T_FILL | T_WRAP | T_TOP,    510, NULL, (void*) &memo, NULL, NULL, TextBox, "" },
+{  0,    0,  510, NULL, (void*) &line, NULL, NULL, TextBox, "" },
+{ 0, NO_OK|SAME_ROW, 0, NULL, (void*) &ChatOK, NULL, NULL, EndMark , "" }
+};
+
 void
 OutputChatMessage (int partner, char *mess)
 {
-    return; // dummy
+    char *p = texts[partner];
+    int len = strlen(mess) + 1;
+
+    if(p) len += strlen(p);
+    texts[partner] = (char*) malloc(len);
+    snprintf(texts[partner], len, "%s%s", p ? p : "", mess);
+    FREE(p);
+    if(partner == activePartner) {
+       AppendText(&chatOptions[5], mess);
+       SetInsertPos(&chatOptions[5], len-2);
+    } else {
+       SetColor("#FFC000", &chatOptions[partner + (partner < activePartner)]);
+       dirty[partner] = 1;
+    }
+}
+
+int
+ChatOK (int n)
+{   // can only be called through <Enter> in chat-partner text-edit, as there is no OK button
+    char buf[MSG_SIZ];
+    if(!partner || strcmp(partner, chatPartner[activePartner])) {
+       safeStrCpy(chatPartner[activePartner], partner, MSG_SIZ);
+       SetWidgetText(&chatOptions[5], "", -1); // clear text if we alter partner
+       SetWidgetText(&chatOptions[6], "", ChatDlg); // clear text if we alter partner
+       HardSetFocus(&chatOptions[6]);
+    }
+    if(line[0]) { // something was typed
+       SetWidgetText(&chatOptions[6], "", ChatDlg);
+       // from here on it could be back-end
+       if(line[strlen(line)-1] == '\n') line[strlen(line)-1] = NULLCHAR;
+       SaveInHistory(line);
+       if(!strcmp("whispers", chatPartner[activePartner]))
+             snprintf(buf, MSG_SIZ, "whisper %s\n", line); // WHISPER box uses "whisper" to send
+       else if(!strcmp("shouts", chatPartner[activePartner]))
+             snprintf(buf, MSG_SIZ, "shout %s\n", line); // SHOUT box uses "shout" to send
+       else {
+           if(!atoi(chatPartner[activePartner])) {
+               snprintf(buf, MSG_SIZ, "> %s\n", line); // echo only tells to handle, not channel
+               OutputChatMessage(activePartner, buf);
+               snprintf(buf, MSG_SIZ, "xtell %s %s\n", chatPartner[activePartner], line);
+           } else
+               snprintf(buf, MSG_SIZ, "tell %s %s\n", chatPartner[activePartner], line);
+       }
+       SendToICS(buf);
+    }
+    return FALSE; // never pop down
+}
+
+void
+ChatSwitch (int n)
+{
+    int i, j;
+    if(n <= activePartner) n--;
+    activePartner = n;
+    if(!texts[n]) texts[n] = strdup("");
+    dirty[n] = 0;
+    SetWidgetText(&chatOptions[5], texts[n], ChatDlg);
+    SetInsertPos(&chatOptions[5], strlen(texts[n]));
+    SetWidgetText(&chatOptions[0], chatPartner[n], ChatDlg);
+    for(i=j=0; i<MAX_CHAT; i++) {
+       if(i == activePartner) continue;
+       SetWidgetLabel(&chatOptions[++j], chatPartner[i]);
+       SetColor(dirty[i] ? "#FFC000" : "#FFFFFF", &chatOptions[j]);
+    }
+    SetWidgetText(&chatOptions[6], "", ChatDlg);
+    HardSetFocus(&chatOptions[6]);
+}
+
+void
+ChatProc ()
+{
+    if(GenericPopUp(chatOptions, _("Chat box"), ChatDlg, BoardWindow, NONMODAL, 0))
+       AddHandler(&chatOptions[0], 2), AddHandler(&chatOptions[6], 2); // treats return as OK
+    MarkMenu("View.OpenChatWindow", ChatDlg);
 }
 
 //--------------------------------- Game-List options dialog ------------------------------------------
@@ -1838,7 +1934,7 @@ static int pmFromX = -1, pmFromY = -1;
 void *userLogo;
 
 void
-DisplayLogos (void *w1, void *w2)
+DisplayLogos (Option *w1, Option *w2)
 {
        void *whiteLogo = first.programLogo, *blackLogo = second.programLogo;
        if(appData.autoLogo) {
@@ -1925,14 +2021,14 @@ Option mainOptions[] = { // description of main window in terms of generic dialo
 Option *
 LogoW (int n, int x, int y)
 {
-    if(n == 10) DisplayLogos(mainOptions[W_WHITE-1].handle, NULL);
+    if(n == 10) DisplayLogos(&mainOptions[W_WHITE-1], NULL);
     return NULL;
 }
 
 Option *
 LogoB (int n, int x, int y)
 {
-    if(n == 10) DisplayLogos(NULL, mainOptions[W_BLACK+1].handle);
+    if(n == 10) DisplayLogos(NULL, &mainOptions[W_BLACK+1]);
     return NULL;
 }
 
@@ -1957,8 +2053,8 @@ MenuCallback (int n)
 static Option *
 Exp (int n, int x, int y)
 {
-    static int but1, but3;
-    int menuNr = -3;
+    static int but1, but3, oldW, oldH;
+    int menuNr = -3, sizing;
 
     if(n == 0) { // motion
        if(SeekGraphClick(Press, x, y, 1)) return NULL;
@@ -1978,6 +2074,10 @@ Exp (int n, int x, int y)
        case -2: shiftKey = !shiftKey;
        case -3: menuNr = RightClick(Release, x, y, &pmFromX, &pmFromY), but3 = 0; break;
        case 10:
+           sizing = (oldW != x || oldH != y);
+           oldW = x; oldH = y;
+           InitDrawingHandle(mainOptions + W_BOARD);
+           if(sizing) return NULL; // don't redraw while sizing
            DrawPosition(True, NULL);
        default:
            return NULL;
@@ -2004,7 +2104,7 @@ BoardPopUp (int squareSize, int lineGap, void *clockFontThingy)
     mainOptions[W_BOARD].max = mainOptions[W_SMALL].max = size; // board size
     mainOptions[W_SMALL].max = size - 2; // board title (subtract border!)
     mainOptions[W_BLACK].max = mainOptions[W_WHITE].max = size/2-3; // clock width
-    mainOptions[W_MESSG].max = appData.showButtonBar ? size-130 : size-2; // message
+    mainOptions[W_MESSG].max = appData.showButtonBar ? size-135 : size-2; // message
     mainOptions[W_MENU].max = size-40; // menu bar
     mainOptions[W_TITLE].type = appData.titleInWindow ? Label : -1 ;
     if(logo && logo <= size/4) { // Activate logos
@@ -2203,7 +2303,10 @@ BrowseOK (int n)
        }
        if(!fileName[0]) return FALSE; // refuse OK when no file
        if(!savMode[0]) { // browsing for name only (dialog Browse button)
-               snprintf(title, MSG_SIZ, "%s/%s", curDir, fileName);
+               if(fileName[0] == '/') // We already had a path name
+                   snprintf(title, MSG_SIZ, "%s", fileName);
+               else
+                   snprintf(title, MSG_SIZ, "%s/%s", curDir, fileName);
                SetWidgetText((Option*) savFP, title, TransientDlg);
                currentCps = savCps; // could return to Engine Settings dialog!
                return TRUE;