Remove SOL body flags
[neverball] / share / gui.c
index c12af2f..9da7434 100644 (file)
@@ -70,6 +70,8 @@ struct widget
 
     int text_obj_w;
     int text_obj_h;
+
+    enum trunc trunc;
 };
 
 /*---------------------------------------------------------------------------*/
@@ -231,7 +233,7 @@ static const char *pick_font_path(void)
 
     if (!fs_exists(path))
     {
-        fprintf(stderr, _("Font \"%s\" doesn't exist, trying default font.\n"),
+        fprintf(stderr, _("Font '%s' doesn't exist, trying default font.\n"),
                 path);
 
         path = GUI_FACE;
@@ -265,7 +267,7 @@ void gui_init(void)
 
         if (!(fontdata = fs_load(fontpath, &fontdatalen)))
         {
-            fprintf(stderr, _("Could not load font %s.\n"), fontpath);
+            fprintf(stderr, _("Could not load font '%s'.\n"), fontpath);
             /* Return or no return, we'll probably crash now. */
             return;
         }
@@ -399,6 +401,7 @@ static int gui_widget(int pd, int type)
             widget[id].color0   = gui_wht;
             widget[id].color1   = gui_wht;
             widget[id].scale    = 1.0f;
+            widget[id].trunc    = TRUNC_NONE;
 
             widget[id].text_obj_w = 0;
             widget[id].text_obj_h = 0;
@@ -433,6 +436,101 @@ int gui_filler(int pd) { return gui_widget(pd, GUI_FILLER); }
 
 /*---------------------------------------------------------------------------*/
 
+struct size
+{
+    int w, h;
+};
+
+
+static struct size gui_measure(const char *text, TTF_Font *font)
+{
+    struct size size = { 0, 0 };
+    TTF_SizeUTF8(font, text, &size.w, &size.h);
+    return size;
+}
+
+static char *gui_trunc_head(const char *text,
+                            const int maxwidth,
+                            TTF_Font *font)
+{
+    int left, right, mid;
+    char *str = NULL;
+
+    left  = 0;
+    right = strlen(text);
+
+    while (right - left > 1)
+    {
+        mid = (left + right) / 2;
+
+        str = concat_string("...", text + mid, NULL);
+
+        if (gui_measure(str, font).w <= maxwidth)
+            right = mid;
+        else
+            left = mid;
+
+        free(str);
+    }
+
+    return concat_string("...", text + right, NULL);
+}
+
+static char *gui_trunc_tail(const char *text,
+                            const int maxwidth,
+                            TTF_Font *font)
+{
+    int left, right, mid;
+    char *str = NULL;
+
+    left  = 0;
+    right = strlen(text);
+
+    while (right - left > 1)
+    {
+        mid = (left + right) / 2;
+
+        str = malloc(mid + sizeof ("..."));
+
+        memcpy(str,       text,  mid);
+        memcpy(str + mid, "...", sizeof ("..."));
+
+        if (gui_measure(str, font).w <= maxwidth)
+            left = mid;
+        else
+            right = mid;
+
+        free(str);
+    }
+
+    str = malloc(left + sizeof ("..."));
+
+    memcpy(str,        text,  left);
+    memcpy(str + left, "...", sizeof ("..."));
+
+    return str;
+}
+
+static char *gui_truncate(const char *text,
+                          const int maxwidth,
+                          TTF_Font *font,
+                          enum trunc trunc)
+{
+    if (gui_measure(text, font).w <= maxwidth)
+        return strdup(text);
+
+    switch (trunc)
+    {
+    case TRUNC_NONE: return strdup(text);                         break;
+    case TRUNC_HEAD: return gui_trunc_head(text, maxwidth, font); break;
+    case TRUNC_TAIL: return gui_trunc_tail(text, maxwidth, font); break;
+    }
+
+    return NULL;
+}
+
+/*---------------------------------------------------------------------------*/
+
 void gui_set_image(int id, const char *file)
 {
     if (glIsTexture(widget[id].text_img))
@@ -450,6 +548,10 @@ void gui_set_label(int id, const char *text)
     if (glIsList(widget[id].text_obj))
         glDeleteLists(widget[id].text_obj, 1);
 
+    text = gui_truncate(text, widget[id].w - radius,
+                        font[widget[id].size],
+                        widget[id].trunc);
+
     widget[id].text_img = make_image_from_font(NULL, NULL, &w, &h,
                                                text, font[widget[id].size]);
     widget[id].text_obj = gui_list(-w / 2, -h / 2, w, h,
@@ -457,6 +559,8 @@ void gui_set_label(int id, const char *text)
 
     widget[id].text_obj_w = w;
     widget[id].text_obj_h = h;
+
+    free((void *) text);
 }
 
 void gui_set_count(int id, int value)
@@ -524,6 +628,11 @@ void gui_set_multi(int id, const char *text)
         gui_set_label(jd, s[i]);
 }
 
+void gui_set_trunc(int id, enum trunc trunc)
+{
+    widget[id].trunc = trunc;
+}
+
 /*---------------------------------------------------------------------------*/
 
 int gui_image(int pd, const char *file, int w, int h)
@@ -806,6 +915,7 @@ static void gui_widget_up(int id)
         case GUI_VARRAY: gui_varray_up(id); break;
         case GUI_HSTACK: gui_hstack_up(id); break;
         case GUI_VSTACK: gui_vstack_up(id); break;
+        case GUI_FILLER:                    break;
         default:         gui_button_up(id); break;
         }
 }