Merge branch 'v4.7.x' into master
[xboard.git] / xaw / xoptions.c
index 1353b8b..1f406cb 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * xoptions.c -- Move list window, part of X front end for XBoard
  *
- * Copyright 2000, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
+ * Copyright 2000, 2009, 2010, 2011, 2012, 2013, 2014 Free Software Foundation, Inc.
  * ------------------------------------------------------------------------
  *
  * GNU XBoard is free software: you can redistribute it and/or modify
@@ -201,7 +201,8 @@ LoadListBox (Option *opt, char *emptyText, int n1, int n2)
 {
     static char *dummyList[2];
     dummyList[0] = emptyText; // empty listboxes tend to crash X, so display user-supplied warning string instead
-    XawListChange(opt->handle, *(char*)opt->target ? opt->target : dummyList, 0, 0, True);
+    XawListChange(opt->handle, *(char**)opt->target ? opt->target : dummyList, 0, 0, True);
+//printf("listbox data = %x\n", opt->target);
 }
 
 int
@@ -405,14 +406,68 @@ format_accel (char *input)
     key = strdup(input);
   else
     key = strdup(++test); // remove ">"
+  if(strlen(key) == 1) key[0] = ToUpper(key[0]);
 
   output = realloc(output, strlen(output) + strlen(_(key))+2);
-  strncat(output, _(key), strlen(key) +1);
+  strncat(output, _(key), strlen(_(key)) +1);
 
   free(key);
   return output;
 }
 
+int
+pixlen (char *s)
+{
+#if 0
+    int dummy;
+    XCharStruct overall;
+    XTextExtents(messageFontStruct, s, strlen(s), &dummy, &dummy, &dummy, &overall);
+    return overall.width;
+#else
+    float tot = 0;
+    while(*s) switch(*s++) {
+       case '.': tot += 0.45; break;
+       case ' ': tot += 0.55; break;
+       case 'i': tot += 0.45; break;
+       case 'l': tot += 0.45; break;
+       case 'j': tot += 0.45; break;
+       case 'f': tot += 0.45; break;
+       case 'I': tot += 0.45; break;
+       case 't': tot += 0.45; break;
+       case 'k': tot += 0.83; break;
+       case 's': tot += 0.83; break;
+       case 'x': tot += 0.83; break;
+       case 'z': tot += 0.83; break;
+       case 'r': tot += 0.55; break;
+       case 'w': tot += 1.3; break;
+       case 'm': tot += 1.3; break;
+       case 'A': tot += 1.3; break;
+       case 'C': tot += 1.3; break;
+       case 'D': tot += 1.3; break;
+       case 'G': tot += 1.3; break;
+       case 'H': tot += 1.3; break;
+       case 'N': tot += 1.3; break;
+       case 'V': tot += 1.3; break;
+       case 'X': tot += 1.3; break;
+       case 'Y': tot += 1.3; break;
+       case 'Z': tot += 1.3; break;
+       case 'M': tot += 1.6; break;
+       case 'W': tot += 1.6; break;
+       case 'B': tot += 1.1; break;
+       case 'E': tot += 1.1; break;
+       case 'F': tot += 1.1; break;
+       case 'K': tot += 1.1; break;
+       case 'P': tot += 1.1; break;
+       case 'R': tot += 1.1; break;
+       case 'S': tot += 1.1; break;
+       case 'O': tot += 1.4; break;
+       case 'Q': tot += 1.4; break;
+       default:  tot++;
+    }
+    return tot;
+#endif
+}
+
 static Widget
 CreateComboPopup (Widget parent, Option *opt, int n, int fromList, int def)
 {   // fromList determines if the item texts are taken from a list of strings, or from a menu table
@@ -421,16 +476,19 @@ CreateComboPopup (Widget parent, Option *opt, int n, int fromList, int def)
     Arg arg;
     MenuItem *mb = (MenuItem *) opt->choice;
     char **list = (char **) opt->choice;
-    int maxlength=0;
+    int maxlength=0, menuLen[1000];
 
 
     if(list[0] == NULL) return NULL; // avoid empty menus, as they cause crash
     menu = XtCreatePopupShell(opt->name, simpleMenuWidgetClass, parent, NULL, 0);
 
     if(!fromList)
-      for (i=0; mb[i].string; i++)
-       if (maxlength < strlen(_(mb[i].string)) )
-         maxlength = strlen(_(mb[i].string) );
+      for (i=0; mb[i].string; i++) if(mb[i].accel) {
+       int len = pixlen(_(mb[i].string));
+       menuLen[i] = len;
+       if (maxlength < len )
+         maxlength = len;
+      }
 
     for (i=0; 1; i++)
       {
@@ -444,12 +502,13 @@ CreateComboPopup (Widget parent, Option *opt, int n, int fromList, int def)
            char *menuname = opt->min & NO_GETTEXT ? msg : _(msg);
            char *accel = format_accel(mb[i].accel);
            size_t len;
-           int fill = maxlength - strlen(menuname) +2+strlen(accel);
+//         int fill = maxlength - strlen(menuname) +2+strlen(accel);
+           int fill = (maxlength - menuLen[i] + 3)*1.8;
 
-           len = strlen(menuname)+fill+1;
+           len = strlen(menuname)+fill+strlen(accel)+1;
            label = malloc(len);
 
-           snprintf(label,len,"%s%*s",menuname,fill,accel);
+           snprintf(label,len,"%s%*s%s",menuname,fill," ",accel);
            free(accel);
          }
        else
@@ -649,8 +708,15 @@ GraphEventProc(Widget widget, caddr_t client_data, XEvent *event)
                         // to give drawing routines opportunity to use it before first expose event
                         // (which are only processed when main gets to the event loop, so after all init!)
                         // so only change when size is no longer good
+               cairo_t *cr;
                if(graph->choice) cairo_surface_destroy((cairo_surface_t *) graph->choice);
                graph->choice = (char**) cairo_image_surface_create (CAIRO_FORMAT_ARGB32, w, h);
+               // paint white, to prevent weirdness when people maximize window and drag pieces over space next to board
+               cr = cairo_create ((cairo_surface_t *) graph->choice);
+               cairo_rectangle (cr, 0, 0, w, h);
+               cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 1.0);
+               cairo_fill(cr);
+               cairo_destroy (cr);
                break;
            }
            w = ((XExposeEvent*)event)->width;
@@ -922,6 +988,7 @@ GenericPopUp (Option *option, char *title, DialogClass dlgNr, DialogClass parent
            } else texts[h] = dialog = NULL; // kludge to position from left margin
            w = option[i].type == Spin || option[i].type == Fractional ? 70 : option[i].max ? option[i].max : 205;
            if(option[i].type == FileName || option[i].type == PathName) w -= 55;
+           if(squareSize > 33) w += (squareSize - 33)/2;
            j = SetPositionAndSize(args, dialog, last, 1 /* border */,
                                   w /* w */, option[i].type == TextBox ? option[i].value : 0 /* h */, 0x91 /* chain full width */);
            if(option[i].type == TextBox) { // decorations for multi-line text-edits
@@ -1020,8 +1087,8 @@ GenericPopUp (Option *option, char *title, DialogClass dlgNr, DialogClass parent
                                   option[i].max /* w */, shrink ? textHeight : 0 /* h */, option[i].min & 0xE | chain /* chain */);
            XtSetArg(args[j], XtNlabel, _(option[i].name));  j++;
            if(option[i].textValue) { // special for buttons of New Variant dialog
-               XtSetArg(args[j], XtNsensitive, appData.noChessProgram || option[i].value < 0
-                                        || strstr(first.variants, VariantName(option[i].value))); j++;
+               XtSetArg(args[j], XtNsensitive, option[i].value >= 0 && (appData.noChessProgram
+                                        || strstr(first.variants, VariantName(option[i].value)))); j++;
                XtSetArg(args[j], XtNborderWidth, (gameInfo.variant == option[i].value)+1); j++;
            }
            option[i].handle = (void*)
@@ -1204,7 +1271,7 @@ GenericPopUp (Option *option, char *title, DialogClass dlgNr, DialogClass parent
     XtAddCallback(b_ok, XtNcallback, GenericCallback, (XtPointer)(intptr_t) (30001 + (dlgNr<<16)));
     if(!(option[i].min & NO_CANCEL)) {
       XtSetArg(args[1], XtNfromHoriz, b_ok); // overwrites!
-      b_cancel = XtCreateManagedWidget(_("cancel"), commandWidgetClass, form, args, j);
+      b_cancel = XtCreateManagedWidget(_("Cancel"), commandWidgetClass, form, args, j);
       XtAddCallback(b_cancel, XtNcallback, GenericCallback, (XtPointer)(intptr_t) (30000 + (dlgNr<<16)));
     }
   }
@@ -1225,13 +1292,17 @@ GenericPopUp (Option *option, char *title, DialogClass dlgNr, DialogClass parent
     shellUp[dlgNr]++; // count rather than flag
     previous = NULL;
     if(textField) SetFocus(textField, popup, (XEvent*) NULL, False);
-    if(dlgNr && wp[dlgNr] && wp[dlgNr]->width > 0) { // if persistent window-info available, reposition
+    if(dlgNr && wp[dlgNr]) { // if persistent window-info available, reposition
        j = 0;
-       XtSetArg(args[j], XtNheight, (Dimension) (wp[dlgNr]->height));  j++;
-       XtSetArg(args[j], XtNwidth,  (Dimension) (wp[dlgNr]->width));  j++;
-       XtSetArg(args[j], XtNx, (Position) (wp[dlgNr]->x));  j++;
-       XtSetArg(args[j], XtNy, (Position) (wp[dlgNr]->y));  j++;
-       XtSetValues(popup, args, j);
+       if(wp[dlgNr]->width > 0 && wp[dlgNr]->height > 0) {
+         XtSetArg(args[j], XtNheight, (Dimension) (wp[dlgNr]->height));  j++;
+         XtSetArg(args[j], XtNwidth,  (Dimension) (wp[dlgNr]->width));  j++;
+       }
+       if(wp[dlgNr]->x > 0 && wp[dlgNr]->y > 0) {
+         XtSetArg(args[j], XtNx, (Position) (wp[dlgNr]->x));  j++;
+         XtSetArg(args[j], XtNy, (Position) (wp[dlgNr]->y));  j++;
+       }
+       if(j) XtSetValues(popup, args, j);
     }
     RaiseWindow(dlgNr);
     return 1; // tells caller he must do initialization (e.g. add specific event handlers)