Change the semantics of 'FontSpec' so that it's a dynamically
authorsimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Sat, 1 Oct 2011 17:38:59 +0000 (17:38 +0000)
committersimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Sat, 1 Oct 2011 17:38:59 +0000 (17:38 +0000)
allocated type.

The main reason for this is to stop it from taking up a fixed large
amount of space in every 'struct value' subunion in conf.c, although
that makes little difference so far because Filename is still doing
the same thing (and is therefore next on my list). However, the
removal of its arbitrary length limit is not to be sneezed at.

git-svn-id: svn://svn.tartarus.org/sgt/putty@9314 cda61777-01e9-0310-a592-d414129be87e

19 files changed:
conf.c
config.c
dialog.h
putty.h
settings.c
storage.h
unix/gtkdlg.c
unix/gtkwin.c
unix/unix.h
unix/uxmisc.c
unix/uxplink.c
unix/uxsftp.c
unix/uxstore.c
windows/winctrls.c
windows/windefs.c
windows/window.c
windows/winmisc.c
windows/winstore.c
windows/winstuff.h

diff --git a/conf.c b/conf.c
index 3268449..e3ce258 100644 (file)
--- a/conf.c
+++ b/conf.c
@@ -44,7 +44,7 @@ struct value {
        int intval;
        char *stringval;
        Filename fileval;
-       FontSpec fontval;
+       FontSpec *fontval;
     } u;
 };
 
@@ -125,6 +125,8 @@ static void free_value(struct value *val, int type)
 {
     if (type == TYPE_STR)
        sfree(val->u.stringval);
+    else if (type == TYPE_FONT)
+       fontspec_free(val->u.fontval);
 }
 
 /*
@@ -144,7 +146,7 @@ static void copy_value(struct value *to, struct value *from, int type)
        to->u.fileval = from->u.fileval;
        break;
       case TYPE_FONT:
-       to->u.fontval = from->u.fontval;
+       to->u.fontval = fontspec_copy(from->u.fontval);
        break;
     }
 }
@@ -343,7 +345,7 @@ FontSpec *conf_get_fontspec(Conf *conf, int primary)
     key.primary = primary;
     entry = find234(conf->tree, &key, NULL);
     assert(entry);
-    return &entry->value.u.fontval;
+    return entry->value.u.fontval;
 }
 
 void conf_set_int(Conf *conf, int primary, int value)
@@ -427,7 +429,7 @@ void conf_set_fontspec(Conf *conf, int primary, const FontSpec *value)
     assert(subkeytypes[primary] == TYPE_NONE);
     assert(valuetypes[primary] == TYPE_FONT);
     entry->key.primary = primary;
-    entry->value.u.fontval = *value;   /* structure copy */
+    entry->value.u.fontval = fontspec_copy(value);
     conf_insert(conf, entry);
 }
 
@@ -458,7 +460,7 @@ int conf_serialised_size(Conf *conf)
            size += sizeof(entry->value.u.fileval);
            break;
          case TYPE_FONT:
-           size += sizeof(entry->value.u.fontval);
+           size += fontspec_serialise(entry->value.u.fontval, NULL);
            break;
        }
     }
@@ -507,9 +509,7 @@ void conf_serialise(Conf *conf, void *vdata)
            data += sizeof(entry->value.u.fileval);
            break;
          case TYPE_FONT:
-           memcpy(data, &entry->value.u.fontval,
-                  sizeof(entry->value.u.fontval));
-           data += sizeof(entry->value.u.fontval);
+            data += fontspec_serialise(entry->value.u.fontval, data);
            break;
        }
     }
@@ -522,7 +522,7 @@ int conf_deserialise(Conf *conf, void *vdata, int maxsize)
     unsigned char *data = (unsigned char *)vdata;
     unsigned char *start = data;
     struct conf_entry *entry;
-    int primary;
+    int primary, used;
     unsigned char *zero;
 
     while (maxsize >= 4) {
@@ -592,16 +592,16 @@ int conf_deserialise(Conf *conf, void *vdata, int maxsize)
            maxsize -= sizeof(entry->value.u.fileval);
            break;
          case TYPE_FONT:
-           if (maxsize < sizeof(entry->value.u.fontval)) {
+            entry->value.u.fontval =
+                fontspec_deserialise(data, maxsize, &used);
+            if (!entry->value.u.fontval) {
                if (subkeytypes[entry->key.primary] == TYPE_STR)
                    sfree(entry->key.secondary.s);
                sfree(entry);
                goto done;
            }
-           memcpy(&entry->value.u.fontval, data,
-                  sizeof(entry->value.u.fontval));
-           data += sizeof(entry->value.u.fontval);
-           maxsize -= sizeof(entry->value.u.fontval);
+           data += used;
+           maxsize -= used;
            break;
        }
        conf_insert(conf, entry);
index a03116b..a7236d1 100644 (file)
--- a/config.c
+++ b/config.c
@@ -147,12 +147,11 @@ void conf_fontsel_handler(union control *ctrl, void *dlg,
     Conf *conf = (Conf *)data;
 
     if (event == EVENT_REFRESH) {
-       dlg_fontsel_set(ctrl, dlg, *conf_get_fontspec(conf, key));
+       dlg_fontsel_set(ctrl, dlg, conf_get_fontspec(conf, key));
     } else if (event == EVENT_VALCHANGE) {
-       FontSpec fontspec;
-       dlg_fontsel_get(ctrl, dlg, &fontspec);
-       conf_set_fontspec(conf, key, &fontspec);
-       /* If FontSpecs ever become dynamic, free this one. */
+       FontSpec *fontspec = dlg_fontsel_get(ctrl, dlg);
+       conf_set_fontspec(conf, key, fontspec);
+        fontspec_free(fontspec);
     }
 }
 
index fb89b6b..eb7ce0e 100644 (file)
--- a/dialog.h
+++ b/dialog.h
@@ -567,8 +567,8 @@ void dlg_listbox_select(union control *ctrl, void *dlg, int index);
 void dlg_text_set(union control *ctrl, void *dlg, char const *text);
 void dlg_filesel_set(union control *ctrl, void *dlg, Filename fn);
 void dlg_filesel_get(union control *ctrl, void *dlg, Filename *fn);
-void dlg_fontsel_set(union control *ctrl, void *dlg, FontSpec fn);
-void dlg_fontsel_get(union control *ctrl, void *dlg, FontSpec *fn);
+void dlg_fontsel_set(union control *ctrl, void *dlg, FontSpec *fn);
+FontSpec *dlg_fontsel_get(union control *ctrl, void *dlg);
 /*
  * Bracketing a large set of updates in these two functions will
  * cause the front end (if possible) to delay updating the screen
diff --git a/putty.h b/putty.h
index 377bf6b..b1c30c8 100644 (file)
--- a/putty.h
+++ b/putty.h
@@ -859,7 +859,7 @@ int conf_get_int_int(Conf *conf, int key, int subkey);
 char *conf_get_str(Conf *conf, int key);   /* result still owned by conf */
 char *conf_get_str_str(Conf *conf, int key, const char *subkey);
 Filename *conf_get_filename(Conf *conf, int key);
-FontSpec *conf_get_fontspec(Conf *conf, int key);
+FontSpec *conf_get_fontspec(Conf *conf, int key); /* still owned by conf */
 /* Optional accessor function: return NULL if key does not exist. */
 char *conf_get_str_str_opt(Conf *conf, int key, const char *subkey);
 /* Accessor function to step through a string-subkeyed list.
@@ -884,6 +884,20 @@ void conf_serialise(Conf *conf, void *data);
 int conf_deserialise(Conf *conf, void *data, int maxsize);/*returns size used*/
 
 /*
+ * Functions to copy, free, serialise and deserialise FontSpecs.
+ * Provided per-platform, to go with the platform's idea of a
+ * FontSpec's contents.
+ *
+ * fontspec_serialise returns the number of bytes written, and can
+ * handle data==NULL without crashing. So you can call it once to find
+ * out a size, then again once you've allocated a buffer.
+ */
+FontSpec *fontspec_copy(const FontSpec *f);
+void fontspec_free(FontSpec *f);
+int fontspec_serialise(FontSpec *f, void *data);
+FontSpec *fontspec_deserialise(void *data, int maxsize, int *used);
+
+/*
  * Exports from noise.c.
  */
 void noise_get_heavy(void (*func) (void *, int));
@@ -917,11 +931,14 @@ void registry_cleanup(void);
  * function is perfectly all right returning NULL, of course. The
  * Filename and FontSpec functions are _not allowed_ to fail to
  * return, since these defaults _must_ be per-platform.)
+ *
+ * The 'FontSpec *' returned by platform_default_fontspec has
+ * ownership transferred to the caller, and must be freed.
  */
 char *platform_default_s(const char *name);
 int platform_default_i(const char *name, int def);
 Filename platform_default_filename(const char *name);
-FontSpec platform_default_fontspec(const char *name);
+FontSpec *platform_default_fontspec(const char *name);
 
 /*
  * Exports from terminal.c.
index af5a1b2..7a2bd37 100644 (file)
@@ -108,10 +108,11 @@ static void gpps(void *handle, const char *name, const char *def,
  */
 static void gppfont(void *handle, const char *name, Conf *conf, int primary)
 {
-    FontSpec result;
-    if (!read_setting_fontspec(handle, name, &result))
-       result = platform_default_fontspec(name);
-    conf_set_fontspec(conf, primary, &result);
+    FontSpec *result = read_setting_fontspec(handle, name);
+    if (!result)
+        result = platform_default_fontspec(name);
+    conf_set_fontspec(conf, primary, result);
+    fontspec_free(result);
 }
 static void gppfile(void *handle, const char *name, Conf *conf, int primary)
 {
@@ -553,7 +554,7 @@ void save_open_settings(void *sesskey, Conf *conf)
     write_setting_s(sesskey, "WinTitle", conf_get_str(conf, CONF_wintitle));
     write_setting_i(sesskey, "TermWidth", conf_get_int(conf, CONF_width));
     write_setting_i(sesskey, "TermHeight", conf_get_int(conf, CONF_height));
-    write_setting_fontspec(sesskey, "Font", *conf_get_fontspec(conf, CONF_font));
+    write_setting_fontspec(sesskey, "Font", conf_get_fontspec(conf, CONF_font));
     write_setting_i(sesskey, "FontQuality", conf_get_int(conf, CONF_font_quality));
     write_setting_i(sesskey, "FontVTMode", conf_get_int(conf, CONF_vtmode));
     write_setting_i(sesskey, "UseSystemColours", conf_get_int(conf, CONF_system_colour));
@@ -621,9 +622,9 @@ void save_open_settings(void *sesskey, Conf *conf)
     write_setting_i(sesskey, "StampUtmp", conf_get_int(conf, CONF_stamp_utmp));
     write_setting_i(sesskey, "LoginShell", conf_get_int(conf, CONF_login_shell));
     write_setting_i(sesskey, "ScrollbarOnLeft", conf_get_int(conf, CONF_scrollbar_on_left));
-    write_setting_fontspec(sesskey, "BoldFont", *conf_get_fontspec(conf, CONF_boldfont));
-    write_setting_fontspec(sesskey, "WideFont", *conf_get_fontspec(conf, CONF_widefont));
-    write_setting_fontspec(sesskey, "WideBoldFont", *conf_get_fontspec(conf, CONF_wideboldfont));
+    write_setting_fontspec(sesskey, "BoldFont", conf_get_fontspec(conf, CONF_boldfont));
+    write_setting_fontspec(sesskey, "WideFont", conf_get_fontspec(conf, CONF_widefont));
+    write_setting_fontspec(sesskey, "WideBoldFont", conf_get_fontspec(conf, CONF_wideboldfont));
     write_setting_i(sesskey, "ShadowBold", conf_get_int(conf, CONF_shadowbold));
     write_setting_i(sesskey, "ShadowBoldOffset", conf_get_int(conf, CONF_shadowboldoffset));
     write_setting_s(sesskey, "SerialLine", conf_get_str(conf, CONF_serline));
index 01cfb03..f7fe613 100644 (file)
--- a/storage.h
+++ b/storage.h
@@ -32,7 +32,7 @@ void *open_settings_w(const char *sessionname, char **errmsg);
 void write_setting_s(void *handle, const char *key, const char *value);
 void write_setting_i(void *handle, const char *key, int value);
 void write_setting_filename(void *handle, const char *key, Filename value);
-void write_setting_fontspec(void *handle, const char *key, FontSpec font);
+void write_setting_fontspec(void *handle, const char *key, FontSpec *font);
 void close_settings_w(void *handle);
 
 /*
@@ -56,7 +56,7 @@ void *open_settings_r(const char *sessionname);
 char *read_setting_s(void *handle, const char *key);
 int read_setting_i(void *handle, const char *key, int defvalue);
 int read_setting_filename(void *handle, const char *key, Filename *value);
-int read_setting_fontspec(void *handle, const char *key, FontSpec *font);
+FontSpec *read_setting_fontspec(void *handle, const char *key);
 void close_settings_r(void *handle);
 
 /*
index ec7ae43..84c9d3a 100644 (file)
@@ -926,24 +926,22 @@ void dlg_filesel_get(union control *ctrl, void *dlg, Filename *fn)
     fn->path[lenof(fn->path)-1] = '\0';
 }
 
-void dlg_fontsel_set(union control *ctrl, void *dlg, FontSpec fs)
+void dlg_fontsel_set(union control *ctrl, void *dlg, FontSpec *fs)
 {
     struct dlgparam *dp = (struct dlgparam *)dlg;
     struct uctrl *uc = dlg_find_byctrl(dp, ctrl);
     assert(uc->ctrl->generic.type == CTRL_FONTSELECT);
     assert(uc->entry != NULL);
-    gtk_entry_set_text(GTK_ENTRY(uc->entry), fs.name);
+    gtk_entry_set_text(GTK_ENTRY(uc->entry), fs->name);
 }
 
-void dlg_fontsel_get(union control *ctrl, void *dlg, FontSpec *fs)
+FontSpec *dlg_fontsel_get(union control *ctrl, void *dlg)
 {
     struct dlgparam *dp = (struct dlgparam *)dlg;
     struct uctrl *uc = dlg_find_byctrl(dp, ctrl);
     assert(uc->ctrl->generic.type == CTRL_FONTSELECT);
     assert(uc->entry != NULL);
-    strncpy(fs->name, gtk_entry_get_text(GTK_ENTRY(uc->entry)),
-           lenof(fs->name));
-    fs->name[lenof(fs->name)-1] = '\0';
+    return fontspec_new(gtk_entry_get_text(GTK_ENTRY(uc->entry)));
 }
 
 /*
index c9455a5..996e424 100644 (file)
@@ -151,14 +151,12 @@ void connection_fatal(void *frontend, char *p, ...)
 /*
  * Default settings that are specific to pterm.
  */
-FontSpec platform_default_fontspec(const char *name)
+FontSpec *platform_default_fontspec(const char *name)
 {
-    FontSpec ret;
     if (!strcmp(name, "Font"))
-       strcpy(ret.name, "server:fixed");
+       return fontspec_new("server:fixed");
     else
-       *ret.name = '\0';
-    return ret;
+        return fontspec_new("");
 }
 
 Filename platform_default_filename(const char *name)
@@ -2541,36 +2539,36 @@ int do_cmdline(int argc, char **argv, int do_everything, int *allow_launch,
         }
 
        if (!strcmp(p, "-fn") || !strcmp(p, "-font")) {
-           FontSpec fs;
+           FontSpec *fs;
            EXPECTS_ARG;
            SECOND_PASS_ONLY;
-           strncpy(fs.name, val, sizeof(fs.name));
-           fs.name[sizeof(fs.name)-1] = '\0';
-           conf_set_fontspec(conf, CONF_font, &fs);
+            fs = fontspec_new(val);
+           conf_set_fontspec(conf, CONF_font, fs);
+            fontspec_free(fs);
 
        } else if (!strcmp(p, "-fb")) {
-           FontSpec fs;
+           FontSpec *fs;
            EXPECTS_ARG;
            SECOND_PASS_ONLY;
-           strncpy(fs.name, val, sizeof(fs.name));
-           fs.name[sizeof(fs.name)-1] = '\0';
-           conf_set_fontspec(conf, CONF_boldfont, &fs);
+            fs = fontspec_new(val);
+           conf_set_fontspec(conf, CONF_font, fs);
+            fontspec_free(fs);
 
        } else if (!strcmp(p, "-fw")) {
-           FontSpec fs;
+           FontSpec *fs;
            EXPECTS_ARG;
            SECOND_PASS_ONLY;
-           strncpy(fs.name, val, sizeof(fs.name));
-           fs.name[sizeof(fs.name)-1] = '\0';
-           conf_set_fontspec(conf, CONF_widefont, &fs);
+            fs = fontspec_new(val);
+           conf_set_fontspec(conf, CONF_font, fs);
+            fontspec_free(fs);
 
        } else if (!strcmp(p, "-fwb")) {
-           FontSpec fs;
+           FontSpec *fs;
            EXPECTS_ARG;
            SECOND_PASS_ONLY;
-           strncpy(fs.name, val, sizeof(fs.name));
-           fs.name[sizeof(fs.name)-1] = '\0';
-           conf_set_fontspec(conf, CONF_wideboldfont, &fs);
+            fs = fontspec_new(val);
+           conf_set_fontspec(conf, CONF_font, fs);
+            fontspec_free(fs);
 
        } else if (!strcmp(p, "-cs")) {
            EXPECTS_ARG;
index faf5600..aa44c9b 100644 (file)
@@ -18,8 +18,9 @@ struct Filename {
 FILE *f_open(struct Filename, char const *, int);
 
 struct FontSpec {
-    char name[256];
+    char *name;    /* may be "" to indicate no selected font at all */
 };
+struct FontSpec *fontspec_new(const char *name);
 
 typedef void *Context;                 /* FIXME: probably needs changing */
 
index dd04e6f..222d559 100644 (file)
@@ -150,3 +150,35 @@ FILE *f_open(struct Filename filename, char const *mode, int is_private)
        return fdopen(fd, mode);
     }
 }
+
+FontSpec *fontspec_new(const char *name)
+{
+    FontSpec *f = snew(FontSpec);
+    f->name = dupstr(name);
+    return f;
+}
+FontSpec *fontspec_copy(const FontSpec *f)
+{
+    return fontspec_new(f->name);
+}
+void fontspec_free(FontSpec *f)
+{
+    sfree(f->name);
+    sfree(f);
+}
+int fontspec_serialise(FontSpec *f, void *data)
+{
+    int len = strlen(f->name);
+    if (data)
+        strcpy(data, f->name);
+    return len + 1;                    /* include trailing NUL */
+}
+FontSpec *fontspec_deserialise(void *vdata, int maxsize, int *used)
+{
+    char *data = (char *)vdata;
+    char *end = memchr(data, '\0', maxsize);
+    if (!end)
+        return NULL;
+    *used = end - data + 1;
+    return fontspec_new(data);
+}
index aeb37f6..fc8100c 100644 (file)
@@ -125,11 +125,9 @@ int platform_default_i(const char *name, int def)
     return def;
 }
 
-FontSpec platform_default_fontspec(const char *name)
+FontSpec *platform_default_fontspec(const char *name)
 {
-    FontSpec ret;
-    *ret.name = '\0';
-    return ret;
+    return fontspec_new("");
 }
 
 Filename platform_default_filename(const char *name)
index 651047e..c19df12 100644 (file)
@@ -53,11 +53,9 @@ int platform_default_i(const char *name, int def)
     return def;
 }
 
-FontSpec platform_default_fontspec(const char *name)
+FontSpec *platform_default_fontspec(const char *name)
 {
-    FontSpec ret;
-    *ret.name = '\0';
-    return ret;
+    return fontspec_new("");
 }
 
 Filename platform_default_filename(const char *name)
index 8d49e48..d9f6013 100644 (file)
@@ -357,7 +357,7 @@ int read_setting_i(void *handle, const char *key, int defvalue)
        return atoi(val);
 }
 
-int read_setting_fontspec(void *handle, const char *name, FontSpec *result)
+FontSpec *read_setting_fontspec(void *handle, const char *name)
 {
     /*
      * In GTK1-only PuTTY, we used to store font names simply as a
@@ -375,25 +375,24 @@ int read_setting_fontspec(void *handle, const char *name, FontSpec *result)
     char *tmp;
 
     if ((tmp = read_setting_s(handle, suffname)) != NULL) {
-       strncpy(result->name, tmp, sizeof(result->name)-1);
-       result->name[sizeof(result->name)-1] = '\0';
+        FontSpec *fs = fontspec_new(tmp);
        sfree(suffname);
        sfree(tmp);
-       return TRUE;                   /* got new-style name */
+       return fs;                     /* got new-style name */
     }
     sfree(suffname);
 
     /* Fall back to old-style name. */
     tmp = read_setting_s(handle, name);
     if (tmp && *tmp) {
-       strcpy(result->name, "server:");
-       strncpy(result->name + 7, tmp, sizeof(result->name) - 8);
-       result->name[sizeof(result->name)-1] = '\0';
+        char *tmp2 = dupcat("server:", tmp, NULL);
+        FontSpec *fs = fontspec_new(tmp2);
+       sfree(tmp2);
        sfree(tmp);
-       return TRUE;
+       return fs;
     } else {
        sfree(tmp);
-       return FALSE;
+       return NULL;
     }
 }
 int read_setting_filename(void *handle, const char *name, Filename *result)
@@ -408,7 +407,7 @@ int read_setting_filename(void *handle, const char *name, Filename *result)
        return FALSE;
 }
 
-void write_setting_fontspec(void *handle, const char *name, FontSpec result)
+void write_setting_fontspec(void *handle, const char *name, FontSpec *fs)
 {
     /*
      * read_setting_fontspec had to handle two cases, but when
@@ -416,7 +415,7 @@ void write_setting_fontspec(void *handle, const char *name, FontSpec result)
      * new-style name.
      */
     char *suffname = dupcat(name, "Name", NULL);
-    write_setting_s(handle, suffname, result.name);
+    write_setting_s(handle, suffname, fs->name);
     sfree(suffname);
 }
 void write_setting_filename(void *handle, const char *name, Filename result)
index 8453e2e..4afd3d0 100644 (file)
@@ -1639,8 +1639,8 @@ void winctrl_layout(struct dlgparam *dp, struct winctrls *wc,
            shortcuts[nshortcuts++] = ctrl->fontselect.shortcut;
            statictext(&pos, escaped, 1, base_id);
            staticbtn(&pos, "", base_id+1, "Change...", base_id+2);
+            data = fontspec_new("", 0, 0, 0);
            sfree(escaped);
-           data = snew(FontSpec);
            break;
          default:
            assert(!"Can't happen");
@@ -1934,21 +1934,21 @@ int winctrl_handle_command(struct dlgparam *dp, UINT msg,
            CHOOSEFONT cf;
            LOGFONT lf;
            HDC hdc;
-           FontSpec fs = *(FontSpec *)c->data;
-           
+           FontSpec *fs = (FontSpec *)c->data;
+
            hdc = GetDC(0);
-           lf.lfHeight = -MulDiv(fs.height,
+           lf.lfHeight = -MulDiv(fs->height,
                                  GetDeviceCaps(hdc, LOGPIXELSY), 72);
            ReleaseDC(0, hdc);
            lf.lfWidth = lf.lfEscapement = lf.lfOrientation = 0;
            lf.lfItalic = lf.lfUnderline = lf.lfStrikeOut = 0;
-           lf.lfWeight = (fs.isbold ? FW_BOLD : 0);
-           lf.lfCharSet = fs.charset;
+           lf.lfWeight = (fs->isbold ? FW_BOLD : 0);
+           lf.lfCharSet = fs->charset;
            lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
            lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
            lf.lfQuality = DEFAULT_QUALITY;
            lf.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
-           strncpy(lf.lfFaceName, fs.name,
+           strncpy(lf.lfFaceName, fs->name,
                    sizeof(lf.lfFaceName) - 1);
            lf.lfFaceName[sizeof(lf.lfFaceName) - 1] = '\0';
 
@@ -1959,13 +1959,11 @@ int winctrl_handle_command(struct dlgparam *dp, UINT msg,
                 CF_FORCEFONTEXIST | CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS;
 
            if (ChooseFont(&cf)) {
-               strncpy(fs.name, lf.lfFaceName,
-                       sizeof(fs.name) - 1);
-               fs.name[sizeof(fs.name) - 1] = '\0';
-               fs.isbold = (lf.lfWeight == FW_BOLD);
-               fs.charset = lf.lfCharSet;
-               fs.height = cf.iPointSize / 10;
+                fs = fontspec_new(lf.lfFaceName, (lf.lfWeight == FW_BOLD),
+                                  cf.iPointSize / 10, lf.lfCharSet);
                dlg_fontsel_set(ctrl, dp, fs);
+                fontspec_free(fs);
+
                ctrl->generic.handler(ctrl, dp, dp->data, EVENT_VALCHANGE);
            }
        }
@@ -2313,34 +2311,35 @@ void dlg_filesel_get(union control *ctrl, void *dlg, Filename *fn)
     fn->path[lenof(fn->path)-1] = '\0';
 }
 
-void dlg_fontsel_set(union control *ctrl, void *dlg, FontSpec fs)
+void dlg_fontsel_set(union control *ctrl, void *dlg, FontSpec *fs)
 {
     char *buf, *boldstr;
     struct dlgparam *dp = (struct dlgparam *)dlg;
     struct winctrl *c = dlg_findbyctrl(dp, ctrl);
     assert(c && c->ctrl->generic.type == CTRL_FONTSELECT);
 
-    *(FontSpec *)c->data = fs;        /* structure copy */
+    fontspec_free((FontSpec *)c->data);
+    c->data = fontspec_copy(fs);
 
-    boldstr = (fs.isbold ? "bold, " : "");
-    if (fs.height == 0)
-       buf = dupprintf("Font: %s, %sdefault height", fs.name, boldstr);
+    boldstr = (fs->isbold ? "bold, " : "");
+    if (fs->height == 0)
+       buf = dupprintf("Font: %s, %sdefault height", fs->name, boldstr);
     else
-       buf = dupprintf("Font: %s, %s%d-%s", fs.name, boldstr,
-                       (fs.height < 0 ? -fs.height : fs.height),
-                       (fs.height < 0 ? "pixel" : "point"));
+       buf = dupprintf("Font: %s, %s%d-%s", fs->name, boldstr,
+                       (fs->height < 0 ? -fs->height : fs->height),
+                       (fs->height < 0 ? "pixel" : "point"));
     SetDlgItemText(dp->hwnd, c->base_id+1, buf);
     sfree(buf);
 
     dlg_auto_set_fixed_pitch_flag(dp);
 }
 
-void dlg_fontsel_get(union control *ctrl, void *dlg, FontSpec *fs)
+FontSpec *dlg_fontsel_get(union control *ctrl, void *dlg)
 {
     struct dlgparam *dp = (struct dlgparam *)dlg;
     struct winctrl *c = dlg_findbyctrl(dp, ctrl);
     assert(c && c->ctrl->generic.type == CTRL_FONTSELECT);
-    *fs = *(FontSpec *)c->data;               /* structure copy */
+    return fontspec_copy((FontSpec *)c->data);
 }
 
 /*
@@ -2482,7 +2481,7 @@ void dlg_auto_set_fixed_pitch_flag(void *dlg)
 {
     struct dlgparam *dp = (struct dlgparam *)dlg;
     Conf *conf = (Conf *)dp->data;
-    FontSpec *font;
+    FontSpec *fs;
     int quality;
     HFONT hfont;
     HDC hdc;
@@ -2500,14 +2499,14 @@ void dlg_auto_set_fixed_pitch_flag(void *dlg)
      */
 
     quality = conf_get_int(conf, CONF_font_quality);
-    font = conf_get_fontspec(conf, CONF_font);
+    fs = conf_get_fontspec(conf, CONF_font);
 
     hfont = CreateFont(0, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE,
                        DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
                        CLIP_DEFAULT_PRECIS, FONT_QUALITY(quality),
-                       FIXED_PITCH | FF_DONTCARE, font->name);
+                       FIXED_PITCH | FF_DONTCARE, fs->name);
     hdc = GetDC(NULL);
-    if (font && hdc && SelectObject(hdc, hfont) && GetTextMetrics(hdc, &tm)) {
+    if (hdc && SelectObject(hdc, hfont) && GetTextMetrics(hdc, &tm)) {
         /* Note that the TMPF_FIXED_PITCH bit is defined upside down :-( */
         is_var = (tm.tmPitchAndFamily & TMPF_FIXED_PITCH);
     } else {
index 6fd6f0c..4296bb0 100644 (file)
@@ -6,18 +6,12 @@
 
 #include <commctrl.h>
 
-FontSpec platform_default_fontspec(const char *name)
+FontSpec *platform_default_fontspec(const char *name)
 {
-    FontSpec ret;
-    if (!strcmp(name, "Font")) {
-       strcpy(ret.name, "Courier New");
-       ret.isbold = 0;
-       ret.charset = ANSI_CHARSET;
-       ret.height = 10;
-    } else {
-       ret.name[0] = '\0';
-    }
-    return ret;
+    if (!strcmp(name, "Font"))
+        return fontspec_new("Courier New", 0, 10, ANSI_CHARSET);
+    else
+        return fontspec_new("", 0, 0, 0);
 }
 
 Filename platform_default_filename(const char *name)
index 04661fd..fabf96e 100644 (file)
@@ -2315,7 +2315,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
                {
                    FontSpec *font = conf_get_fontspec(conf, CONF_font);
                    FontSpec *prev_font = conf_get_fontspec(prev_conf,
-                                                           CONF_font);
+                                                             CONF_font);
 
                    if (!strcmp(font->name, prev_font->name) ||
                        !strcmp(conf_get_str(conf, CONF_line_codepage),
index d05a07a..a7ac0e5 100644 (file)
@@ -379,3 +379,51 @@ void *minefield_c_realloc(void *p, size_t size)
 }
 
 #endif                         /* MINEFIELD */
+
+FontSpec *fontspec_new(const char *name,
+                        int bold, int height, int charset)
+{
+    FontSpec *f = snew(FontSpec);
+    f->name = dupstr(name);
+    f->isbold = bold;
+    f->height = height;
+    f->charset = charset;
+    return f;
+}
+FontSpec *fontspec_copy(const FontSpec *f)
+{
+    return fontspec_new(f->name, f->isbold, f->height, f->charset);
+}
+void fontspec_free(FontSpec *f)
+{
+    sfree(f->name);
+    sfree(f);
+}
+int fontspec_serialise(FontSpec *f, void *vdata)
+{
+    char *data = (char *)vdata;
+    int len = strlen(f->name) + 1;     /* include trailing NUL */
+    if (data) {
+        strcpy(data, f->name);
+        PUT_32BIT_MSB_FIRST(data + len, f->isbold);
+        PUT_32BIT_MSB_FIRST(data + len + 4, f->height);
+        PUT_32BIT_MSB_FIRST(data + len + 8, f->charset);
+    }
+    return len + 12;                   /* also include three 4-byte ints */
+}
+FontSpec *fontspec_deserialise(void *vdata, int maxsize, int *used)
+{
+    char *data = (char *)vdata;
+    char *end;
+    if (maxsize < 13)
+        return NULL;
+    end = memchr(data, '\0', maxsize-12);
+    if (!end)
+        return NULL;
+    end++;
+    *used = end - data + 12;
+    return fontspec_new(data,
+                        GET_32BIT_MSB_FIRST(end),
+                        GET_32BIT_MSB_FIRST(end + 4),
+                        GET_32BIT_MSB_FIRST(end + 8));
+}
index 12d6cdd..c165676 100644 (file)
@@ -186,50 +186,47 @@ int read_setting_i(void *handle, const char *key, int defvalue)
        return val;
 }
 
-int read_setting_fontspec(void *handle, const char *name, FontSpec *result)
+FontSpec *read_setting_fontspec(void *handle, const char *name)
 {
     char *settingname;
-    FontSpec ret;
     char *fontname;
+    int isbold, height, charset;
 
     fontname = read_setting_s(handle, name);
     if (!fontname)
-       return 0;
-    strncpy(ret.name, fontname, sizeof(ret.name)-1);
-    ret.name[sizeof(ret.name)-1] = '\0';
-    sfree(fontname);
+       return NULL;
 
     settingname = dupcat(name, "IsBold", NULL);
-    ret.isbold = read_setting_i(handle, settingname, -1);
+    isbold = read_setting_i(handle, settingname, -1);
     sfree(settingname);
-    if (ret.isbold == -1) return 0;
+    if (isbold == -1) return NULL;
 
     settingname = dupcat(name, "CharSet", NULL);
-    ret.charset = read_setting_i(handle, settingname, -1);
+    charset = read_setting_i(handle, settingname, -1);
     sfree(settingname);
-    if (ret.charset == -1) return 0;
+    if (charset == -1) return NULL;
 
     settingname = dupcat(name, "Height", NULL);
-    ret.height = read_setting_i(handle, settingname, INT_MIN);
+    height = read_setting_i(handle, settingname, INT_MIN);
     sfree(settingname);
-    if (ret.height == INT_MIN) return 0;
-    *result = ret;
-    return 1;
+    if (height == INT_MIN) return NULL;
+
+    return fontspec_new(fontname, isbold, height, charset);
 }
 
-void write_setting_fontspec(void *handle, const char *name, FontSpec font)
+void write_setting_fontspec(void *handle, const char *name, FontSpec *font)
 {
     char *settingname;
 
-    write_setting_s(handle, name, font.name);
+    write_setting_s(handle, name, font->name);
     settingname = dupcat(name, "IsBold", NULL);
-    write_setting_i(handle, settingname, font.isbold);
+    write_setting_i(handle, settingname, font->isbold);
     sfree(settingname);
     settingname = dupcat(name, "CharSet", NULL);
-    write_setting_i(handle, settingname, font.charset);
+    write_setting_i(handle, settingname, font->charset);
     sfree(settingname);
     settingname = dupcat(name, "Height", NULL);
-    write_setting_i(handle, settingname, font.height);
+    write_setting_i(handle, settingname, font->height);
     sfree(settingname);
 }
 
index 8738ccf..e23ed4e 100644 (file)
@@ -21,11 +21,13 @@ struct Filename {
 #define f_open(filename, mode, isprivate) ( fopen((filename).path, (mode)) )
 
 struct FontSpec {
-    char name[64];
+    char *name;
     int isbold;
     int height;
     int charset;
 };
+struct FontSpec *fontspec_new(const char *name,
+                               int bold, int height, int charset);
 
 #ifndef CLEARTYPE_QUALITY
 #define CLEARTYPE_QUALITY 5