diff --git a/apps/filetree.c b/apps/filetree.c
index 35bb2a8..b986035 100644
--- a/apps/filetree.c
+++ b/apps/filetree.c
@@ -404,27 +404,30 @@ int ft_load(struct tree_context* c, const char* tempdir)
 #ifdef HAVE_LCD_BITMAP
 static void ft_load_font(char *file)
 {
+    int current_font_id;
+    enum screen_type screen = SCREEN_MAIN;
 #if NB_SCREENS > 1
     MENUITEM_STRINGLIST(menu, ID2P(LANG_CUSTOM_FONT), NULL, 
                         ID2P(LANG_MAIN_SCREEN), ID2P(LANG_REMOTE_SCREEN))
     switch (do_menu(&menu, NULL, NULL, false))
     {
-        case 0: /* main lcd */        
-            splash(0, ID2P(LANG_WAIT));
-            font_load(NULL, file);
+        case 0: /* main lcd */
+            screen = SCREEN_MAIN;
             set_file(file, (char *)global_settings.font_file, MAX_FILENAME);
             break;
         case 1: /* remote */
-            splash(0, ID2P(LANG_WAIT));
-            font_load_remoteui(file);
+            screen = SCREEN_REMOTE;
             set_file(file, (char *)global_settings.remote_font_file, MAX_FILENAME);
             break;
     }
 #else
-    splash(0, ID2P(LANG_WAIT));
-    font_load(NULL, file);
     set_file(file, (char *)global_settings.font_file, MAX_FILENAME);
 #endif
+    splash(0, ID2P(LANG_WAIT));
+    current_font_id = global_status.font_id[screen];
+    if (current_font_id >= 0)
+        font_unload(current_font_id);
+    global_status.font_id[screen] = font_load(file);
 }    
 #endif
 
diff --git a/apps/gui/skin_engine/skin_engine.h b/apps/gui/skin_engine/skin_engine.h
index c8104f9..79a9e3e 100644
--- a/apps/gui/skin_engine/skin_engine.h
+++ b/apps/gui/skin_engine/skin_engine.h
@@ -44,8 +44,7 @@ enum skinnable_screens {
 
 #ifdef HAVE_LCD_BITMAP
 
-#define SKIN_BUFFER_SIZE (2048 + SKIN_FONT_SIZE) + \
-                         (WPS_MAX_TOKENS * \
+#define SKIN_BUFFER_SIZE (WPS_MAX_TOKENS * \
                          (sizeof(struct wps_token) + (sizeof(struct skin_element))))
 #endif
 
diff --git a/apps/gui/skin_engine/skin_fonts.c b/apps/gui/skin_engine/skin_fonts.c
index a89b762..530a655 100644
--- a/apps/gui/skin_engine/skin_fonts.c
+++ b/apps/gui/skin_engine/skin_fonts.c
@@ -31,10 +31,8 @@
 #include "skin_fonts.h"
 
 static struct skin_font_info {
-    struct font font;
     int font_id;
     char name[MAX_PATH];
-    char *buffer;
     int ref_count; /* how many times has this font been loaded? */
 } font_table[MAXUSERFONTS];
 
@@ -49,8 +47,6 @@ void skin_font_init(void)
         if (!first_load)
             font_unload(font_table[i].font_id);
         font_table[i].font_id = -1;
-        font_table[i].name[0] = '\0';
-        font_table[i].buffer = NULL;
         font_table[i].ref_count = 0;
     }
     first_load = false;
@@ -61,15 +57,14 @@ int skin_font_load(char* font_name, int glyphs)
 {
     int i;
     int skin_font_size = 0;
-    struct font *pf;
     struct skin_font_info *font = NULL;
     char filename[MAX_PATH];
     
     if (!strcmp(font_name, global_settings.font_file))
-        return FONT_UI;
+        return global_status.font_id[SCREEN_MAIN];
 #ifdef HAVE_REMOTE_LCD
     if (!strcmp(font_name, global_settings.remote_font_file))
-        return FONT_UI_REMOTE;
+        return global_status.font_id[SCREEN_MAIN];
 #endif
     snprintf(filename, MAX_PATH, FONT_DIR "/%s.fnt", font_name);
     
@@ -88,32 +83,8 @@ int skin_font_load(char* font_name, int glyphs)
     }
     if (!font)
         return -1; /* too many fonts loaded */
-    
-    pf = &font->font;
-    if (!font->buffer)
-    {
-        if (!glyphs) 
-            glyphs = GLYPHS_TO_CACHE;
-#ifndef __PCTOOL__
-        skin_font_size = font_glyphs_to_bufsize(filename, glyphs);
-#else
-        skin_font_size = 1;
-#endif
-        if ( !skin_font_size )
-            return -1;
-        pf->buffer_start = (char*)skin_buffer_alloc(skin_font_size);
-        if (!pf->buffer_start)
-            return -1;
-        font->buffer = pf->buffer_start;
-        pf->buffer_size = skin_font_size;
-    }
-    else
-    {
-        pf->buffer_start = font->buffer;
-    }
-    
-    pf->fd = -1;
-    font->font_id = font_load(pf, filename);
+    skin_font_size = font_glyphs_to_bufsize(filename, glyphs); // fixme
+    font->font_id = font_load(filename);
     
     if (font->font_id < 0)
         return -1;
diff --git a/apps/gui/skin_engine/skin_parser.c b/apps/gui/skin_engine/skin_parser.c
index d6091f9..cf5de4e 100644
--- a/apps/gui/skin_engine/skin_parser.c
+++ b/apps/gui/skin_engine/skin_parser.c
@@ -415,8 +415,13 @@ static int parse_font_load(struct skin_element *element,
         glyphs = element->params[2].data.number;
     else
         glyphs = GLYPHS_TO_CACHE;
+    if (id < 2)
+    {
+        DEBUGF("font id must be >= 2\n");
+        return 1;
+    }
 #if defined(DEBUG) || defined(SIMULATOR)
-    if (skinfonts[id-FONT_FIRSTUSERFONT].name != NULL)
+    if (skinfonts[id-2].name != NULL)
     {
         DEBUGF("font id %d already being used\n", id);
     }
@@ -426,9 +431,9 @@ static int parse_font_load(struct skin_element *element,
     ptr = strchr(filename, '.');
     if (!ptr || strncmp(ptr, ".fnt", 4))
         return WPS_ERROR_INVALID_PARAM;
-    skinfonts[id-FONT_FIRSTUSERFONT].id = -1;
-    skinfonts[id-FONT_FIRSTUSERFONT].name = filename;
-    skinfonts[id-FONT_FIRSTUSERFONT].glyphs = glyphs;
+    skinfonts[id-2].id = -1;
+    skinfonts[id-2].name = filename;
+    skinfonts[id-2].glyphs = glyphs;
 
     return 0;
 }
@@ -1616,18 +1621,20 @@ static bool skin_load_fonts(struct wps_data *data)
         struct viewport *vp = &skin_vp->vp;
 
 
-        if (vp->font <= FONT_UI)
+        if (vp->font == 1)
         {   /* the usual case -> built-in fonts */
-#ifdef HAVE_REMOTE_LCD
-            if (vp->font == FONT_UI)
-                vp->font += curr_screen;
-#endif
+            vp->font = global_status.font_id[curr_screen];
+            continue;
+        }
+        else if (vp->font <= 0)
+        {
+            vp->font = FONT_SYSFIXED;
             continue;
         }
         font_id = vp->font;
 
         /* now find the corresponding skin_font */
-        struct skin_font *font = &skinfonts[font_id-FONT_FIRSTUSERFONT];
+        struct skin_font *font = &skinfonts[font_id-2];
         if (!font->name)
         {
             if (success)
@@ -1682,12 +1689,10 @@ static int convert_viewport(struct wps_data *data, struct skin_element* element)
     curr_viewport_element = element;
     
     viewport_set_defaults(&skin_vp->vp, curr_screen);
-#ifdef HAVE_REMOTE_LCD
     /* viewport_set_defaults() sets the font to FONT_UI+curr_screen.
      * This parser requires font 1 to always be the UI font, 
      * so force it back to FONT_UI and handle the screen number at the end */
-    skin_vp->vp.font = FONT_UI;
-#endif
+    skin_vp->vp.font = 1;
     
 #if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1))
     skin_vp->start_fgcolour = skin_vp->vp.fg_pattern;
diff --git a/apps/gui/usb_screen.c b/apps/gui/usb_screen.c
index 66b7094..b47cec6 100644
--- a/apps/gui/usb_screen.c
+++ b/apps/gui/usb_screen.c
@@ -265,10 +265,8 @@ void gui_usb_screen_run(bool early_usb)
     {
         /* The font system leaves the .fnt fd's open, so we need for force close them all */
 #ifdef HAVE_LCD_BITMAP
-        font_reset(NULL);
-#ifdef HAVE_REMOTE_LCD
-        font_load_remoteui(NULL);
-#endif
+        FOR_NB_SCREENS(i)
+            font_unload(global_status.font_id[i]);
         skin_font_init(); /* unload all the skin fonts */
 #endif
     }
diff --git a/apps/gui/viewport.c b/apps/gui/viewport.c
index 34ebbf9..a78e381 100644
--- a/apps/gui/viewport.c
+++ b/apps/gui/viewport.c
@@ -324,7 +324,7 @@ void viewport_set_fullscreen(struct viewport *vp,
 #ifndef __PCTOOL__
     set_default_align_flags(vp);
 #endif
-    vp->font = FONT_UI + screen; /* default to UI to discourage SYSFONT use */
+    vp->font = global_status.font_id[screen];
     vp->drawmode = DRMODE_SOLID;
 #if LCD_DEPTH > 1
 #ifdef HAVE_REMOTE_LCD
diff --git a/apps/main.c b/apps/main.c
index 07a8bba..babd575 100644
--- a/apps/main.c
+++ b/apps/main.c
@@ -336,6 +336,7 @@ static void init_tagcache(void)
 
 static void init(void)
 {
+    int i;
     system_init();
     core_allocator_init();
     kernel_init();
@@ -347,6 +348,8 @@ static void init(void)
 #ifdef HAVE_REMOTE_LCD
     lcd_remote_init();
 #endif
+    FOR_NB_SCREENS(i)
+        global_status.font_id[i] = FONT_SYSFIXED;
     font_init();
     show_logo();
     button_init();
@@ -451,6 +454,8 @@ static void init(void)
 #ifdef HAVE_REMOTE_LCD
     lcd_remote_init();
 #endif
+    FOR_NB_SCREENS(rc)
+        global_status.font_id[rc] = FONT_SYSFIXED;
     font_init();
 
     CHART(">show_logo");
diff --git a/apps/plugin.h b/apps/plugin.h
index 941c193..cea148a 100644
--- a/apps/plugin.h
+++ b/apps/plugin.h
@@ -272,7 +272,7 @@ struct plugin_api {
     bool (*is_diacritic)(const unsigned short char_code, bool *is_rtl);
 #endif
     const unsigned char *(*font_get_bits)( struct font *pf, unsigned short char_code );
-    int (*font_load)(struct font*, const char *path);
+    int (*font_load)(const char *path);
     struct font* (*font_get)(int font);
     int  (*font_getstringsize)(const unsigned char *str, int *w, int *h,
                                int fontnumber);
diff --git a/apps/screen_access.c b/apps/screen_access.c
index b83e842..b76b1e5 100644
--- a/apps/screen_access.c
+++ b/apps/screen_access.c
@@ -67,6 +67,13 @@ static int screen_helper_getnblines(void)
     return height / screens[0].getcharheight();
 }
 
+static void screen_helper_setfont(int font)
+{
+    if (font == FONT_UI)
+        font = global_status.font_id[0];
+    lcd_setfont(font);
+}
+
 #if NB_SCREENS == 2
 static int screen_helper_remote_getcharwidth(void)
 {
@@ -99,6 +106,13 @@ static int screen_helper_remote_getnblines(void)
 #endif
     return height / screens[1].getcharheight();
 }
+
+static void screen_helper_remote_setfont(int font)
+{
+    if (font == FONT_UI)
+        font = global_status.font_id[1];
+    lcd_remote_setfont(font);
+}
 #endif
 
 struct screen screens[NB_SCREENS] =
@@ -129,7 +143,7 @@ struct screen screens[NB_SCREENS] =
         .getheight=&lcd_getheight,
         .getstringsize=&lcd_getstringsize,
 #ifdef HAVE_LCD_BITMAP
-        .setfont=&lcd_setfont,
+        .setfont=screen_helper_setfont,
         .getfont=&lcd_getfont,
         .mono_bitmap=&lcd_mono_bitmap,
         .mono_bitmap_part=&lcd_mono_bitmap_part,
@@ -229,7 +243,7 @@ struct screen screens[NB_SCREENS] =
         .getheight=&lcd_remote_getheight,
         .getstringsize=&lcd_remote_getstringsize,
 #if 1 /* all remote LCDs are bitmapped so far */
-        .setfont=&lcd_remote_setfont,
+        .setfont=screen_helper_setfont,
         .getfont=&lcd_remote_getfont,
         .mono_bitmap=&lcd_remote_mono_bitmap,
         .mono_bitmap_part=&lcd_remote_mono_bitmap_part,
diff --git a/apps/settings.c b/apps/settings.c
index 258face..d9dc643 100644
--- a/apps/settings.c
+++ b/apps/settings.c
@@ -880,26 +880,20 @@ void settings_apply(bool read_disk)
             snprintf(buf, sizeof buf, FONT_DIR "/%s.fnt",
                      global_settings.font_file);
             CHART2(">font_load ", global_settings.font_file);
-            rc = font_load(NULL, buf);
+            rc = font_load(buf);
             CHART2("<font_load ", global_settings.font_file);
-            if (rc < 0)
-                font_reset(NULL);
+            global_status.font_id[SCREEN_MAIN] = rc;
         }
-        else
-            font_reset(NULL);
 #ifdef HAVE_REMOTE_LCD        
         if ( global_settings.remote_font_file[0]
             && global_settings.remote_font_file[0] != '-') {
             snprintf(buf, sizeof buf, FONT_DIR "/%s.fnt",
                      global_settings.remote_font_file);
             CHART2(">font_load_remoteui ", global_settings.remote_font_file);
-            rc = font_load_remoteui(buf);
+            rc = font_load(buf);
             CHART2("<font_load_remoteui ", global_settings.remote_font_file);
-            if (rc < 0)
-                font_load_remoteui(NULL);
+            global_status.font_id[SCREEN_REMOTE] = rc;
         }
-        else
-            font_load_remoteui(NULL);
 #endif
         if ( global_settings.kbd_file[0]
              && global_settings.kbd_file[0] != '-') {
diff --git a/apps/settings.h b/apps/settings.h
index d7a7226..77fb7aa 100644
--- a/apps/settings.h
+++ b/apps/settings.h
@@ -278,6 +278,7 @@ struct system_status
     signed char last_screen;
     int  viewer_icon_count;
     int last_volume_change; /* tick the last volume change happened. skins use this */
+    int font_id[NB_SCREENS]; /* font id of the settings font for each screen */
 };
 
 struct user_settings
diff --git a/firmware/export/font.h b/firmware/export/font.h
index a85f95e..a86af63 100644
--- a/firmware/export/font.h
+++ b/firmware/export/font.h
@@ -22,6 +22,7 @@
 #define _FONT_H
 
 #include "inttypes.h"
+#include "stdbool.h"
 
 /*
  * Incore font and image definitions
@@ -46,18 +47,14 @@
  * Fonts are specified in firmware/font.c.
  */
 enum {
-    FONT_SYSFIXED, /* system fixed pitch font*/
-    FONT_UI,       /* system porportional font*/
-#ifdef HAVE_REMOTE_LCD
-    FONT_UI_REMOTE, /* UI font for remote LCD */
-#endif
-    SYSTEMFONTCOUNT, /* Number of fonts reserved for the system and ui */
-    FONT_FIRSTUSERFONT = 2
+    FONT_SYSFIXED = -1, /* system fixed pitch font*/
+    FONT_FIRSTUSERFONT = 0, /* first id for the user fonts */
 };
 #define MAXUSERFONTS 8
 
 /* SYSFONT, FONT_UI, FONT_UI_REMOTE + MAXUSERFONTS fonts in skins */
-#define MAXFONTS (SYSTEMFONTCOUNT + MAXUSERFONTS)
+#define MAXFONTS (FONT_FIRSTUSERFONT + MAXUSERFONTS)
+#define FONT_UI MAXFONTS
 
 /*
  * .fnt loadable font file format definition
@@ -105,7 +102,8 @@ struct font {
     unsigned char *buffer_start;    /* buffer to store the font in */       
     unsigned char *buffer_position; /* position in the buffer */    
     unsigned char *buffer_end;      /* end of the buffer */
-    int          buffer_size;       /* size of the buffer in bytes */
+    int            buffer_size;     /* size of the buffer in bytes */
+    bool           handle_locked;   /* is the buflib handle currently locked? */
 #ifndef __PCTOOL__    
     struct font_cache cache;
     uint32_t file_width_offset;    /* offset to file width data    */
@@ -117,17 +115,13 @@ struct font {
 
 /* font routines*/
 void font_init(void) INIT_ATTR;
-#ifdef HAVE_REMOTE_LCD
-/* Load a font into the special remote ui font slot */
-int font_load_remoteui(const char* path);
-#endif
-int font_load(struct font* pf, const char *path);
+int font_load(const char *path);
 int font_glyphs_to_bufsize(const char *path, int glyphs);
 void font_unload(int font_id);
 
 struct font* font_get(int font);
 
-void font_reset(struct font *pf);
+void font_reset(int font_id);
 int font_getstringsize(const unsigned char *str, int *w, int *h, int fontnumber);
 int font_get_width(struct font* ft, unsigned short ch);
 const unsigned char * font_get_bits(struct font* ft, unsigned short ch);
diff --git a/firmware/font.c b/firmware/font.c
index 0f9f453..7678c55 100644
--- a/firmware/font.c
+++ b/firmware/font.c
@@ -34,6 +34,7 @@
 #include "system.h"
 #include "font.h"
 #include "file.h"
+#include "core_alloc.h"
 #include "debug.h"
 #include "panic.h"
 #include "rbunicode.h"
@@ -74,19 +75,50 @@ extern struct font sysfont;
 
 #ifndef BOOTLOADER
 
-/* structure filled in by font_load */
-static struct font font_ui;
-/* static buffer allocation structures */
-static unsigned char main_buf[MAX_FONT_SIZE] CACHEALIGN_ATTR;
-#ifdef HAVE_REMOTE_LCD
-#define REMOTE_FONT_SIZE 10000
-static struct font remote_font_ui;
-static unsigned char remote_buf[REMOTE_FONT_SIZE] CACHEALIGN_ATTR;
-#endif
+struct buflib_alloc_data {
+    struct font font;
+    unsigned char buffer[MAX_FONT_SIZE] CACHEALIGN_ATTR;
+};
+static int buflib_allocations[MAXFONTS];
+static int handle_for_glyphcache;
+
+static int buflibmove_callback(int handle, void* current, void* new)
+{
+    (void)handle;
+    struct buflib_alloc_data *alloc = (struct buflib_alloc_data*)current;
+    size_t diff = new - current;
+
+    if (alloc->font.handle_locked)
+        return BUFLIB_CB_CANNOT_MOVE;
+    alloc->font.bits += diff;
+    alloc->font.offset += diff;
+
+    alloc->font.buffer_start += diff;
+    alloc->font.buffer_end += diff;
+    alloc->font.buffer_position += diff;
+    return BUFLIB_CB_OK;
+}
+static void lock_font_handle(int handle, bool lock)
+{
+    struct buflib_alloc_data *alloc = core_get_data(handle);
+    alloc->font.handle_locked = lock;
+}
+
+static struct buflib_callbacks buflibops = {buflibmove_callback, NULL };
 
-/* system font table, in order of FONT_xxx definition */
-static struct font* sysfonts[MAXFONTS] = { &sysfont, &font_ui, NULL};
+static inline struct font *pf_from_handle(int handle)
+{
+    struct buflib_alloc_data *alloc = core_get_data(handle);
+    struct font *pf = &alloc->font;
+    return pf;
+}
 
+static inline unsigned char *buffer_from_handle(int handle)
+{
+    struct buflib_alloc_data *alloc = core_get_data(handle);
+    unsigned char* buffer = alloc->buffer;
+    return buffer;
+}
 
 /* Font cache structures */
 static void cache_create(struct font* pf);
@@ -95,13 +127,10 @@ static void glyph_cache_load(struct font* pf);
 
 void font_init(void)
 {
-    int i = SYSTEMFONTCOUNT;
+    int i = 0;
     while (i<MAXFONTS)
-        sysfonts[i++] = NULL;
-    font_reset(NULL);
-#ifdef HAVE_REMOTE_LCD
-    font_reset(&remote_font_ui);
-#endif
+        buflib_allocations[i++] = -1;
+    handle_for_glyphcache = -1;
 }
 
 /* Check if we have x bytes left in the file buffer */
@@ -139,26 +168,6 @@ static int glyph_bytes( struct font *pf, int width )
         width * ((pf->height + 7) / 8);
 }
 
-void font_reset(struct font *pf)
-{
-    unsigned char* buffer = NULL;
-    size_t buf_size = 0;
-    if (pf == NULL)
-        pf = &font_ui;
-    else
-    {
-        buffer = pf->buffer_start;
-        buf_size = pf->buffer_size;
-    }
-    memset(pf, 0, sizeof(struct font));
-    pf->fd = -1;
-    if (buffer)
-    {
-        pf->buffer_start = buffer;
-        pf->buffer_size = buf_size;
-    }
-}
-
 static struct font* font_load_header(struct font *pf)
 {
     /* Check we have enough data */
@@ -320,18 +329,18 @@ static struct font* font_load_cached(struct font* pf)
     return pf;
 }
 
-static bool internal_load_font(struct font* pf, const char *path,
+static bool internal_load_font(int font_id, const char *path,
                                char *buf, size_t buf_size)
 {
     int size;
-    
+    struct font* pf = pf_from_handle(buflib_allocations[font_id]);
     /* save loaded glyphs */
     glyph_cache_save(pf);
     /* Close font file handle */
     if (pf->fd >= 0)
         close(pf->fd);
 
-    font_reset(pf);
+    font_reset(font_id);
 
     /* open and read entire font file*/
     pf->fd = open(path, O_RDONLY|O_BINARY);
@@ -393,81 +402,85 @@ static bool internal_load_font(struct font* pf, const char *path,
     return true;
 }
 
-#ifdef HAVE_REMOTE_LCD
-/* Load a font into the special remote ui font slot */
-int font_load_remoteui(const char* path)
+static int alloc_and_init(int font_idx, const char* name)
 {
-    struct font* pf = &remote_font_ui;
-    if (!path)
-    {
-        if (sysfonts[FONT_UI_REMOTE] && sysfonts[FONT_UI_REMOTE] != sysfonts[FONT_UI])
-            font_unload(FONT_UI_REMOTE);
-        sysfonts[FONT_UI_REMOTE] = NULL;
-        return FONT_UI;
-    }
-    if (!internal_load_font(pf, path, remote_buf, REMOTE_FONT_SIZE))
-    {
-        sysfonts[FONT_UI_REMOTE] = NULL;
-        return -1;
-    }
-    
-    sysfonts[FONT_UI_REMOTE] = pf;
-    return FONT_UI_REMOTE;
+    int *phandle = &buflib_allocations[font_idx];
+    int handle = *phandle;
+    if (handle > 0)
+        return handle;
+    *phandle = core_alloc_ex(name, sizeof(struct buflib_alloc_data), &buflibops);
+    handle = *phandle;
+    if (handle < 0)
+        return handle;
+    struct font *pf = pf_from_handle(handle);
+    font_reset(font_idx);
+    pf->handle_locked = false;
+    pf->buffer_position = pf->buffer_start = buffer_from_handle(handle);
+    pf->buffer_size = MAX_FONT_SIZE;
+    return handle;
+}
+
+void font_reset(int font_id)
+{
+    struct font *pf = pf_from_handle(buflib_allocations[font_id]);
+    // fixme
+    memset(pf, 0, sizeof(struct font));
+    pf->fd = -1;
 }
-#endif
 
 /* read and load font into incore font structure,
  * returns the font number on success, -1 on failure */
-int font_load(struct font* pf, const char *path)
+int font_load(const char *path)
 {
-    int font_id = -1;
+    int font_id;
     char *buffer;
     size_t buffer_size;
-    if (pf == NULL)
-    {
-        pf = &font_ui;
-        font_id = FONT_UI;
-    }
-    else
+    int *handle;
+    for (font_id = FONT_FIRSTUSERFONT; font_id < MAXFONTS; font_id++)
     {
-        for (font_id = SYSTEMFONTCOUNT; font_id < MAXFONTS; font_id++)
+        handle = &buflib_allocations[font_id];
+        if (*handle < 0)
         {
-            if (sysfonts[font_id] == NULL)
-                break;
+            break;
         }
-        if (font_id == MAXFONTS)
-            return -1; /* too many fonts */
-    }
-    
-    if (font_id == FONT_UI)
-    {
-        /* currently, font loading replaces earlier font allocation*/
-        buffer = (unsigned char *)(((intptr_t)main_buf + 3) & ~3);
-        /* make sure above doesn't exceed */
-        buffer_size = MAX_FONT_SIZE-3; 
     }
-    else
+    handle = &buflib_allocations[font_id];
+    *handle = alloc_and_init(font_id, path);
+    if (*handle < 0)
+        return -1;
+
+    if (handle_for_glyphcache < 0)
+        handle_for_glyphcache = *handle;
+
+    buffer = buffer_from_handle(*handle);
+    buffer_size = MAX_FONT_SIZE; //FIXME
+    lock_font_handle(*handle, true);
+
+    if (!internal_load_font(font_id, path, buffer, buffer_size))
     {
-        buffer = pf->buffer_start;
-        buffer_size = pf->buffer_size;
-    }
-    
-    if (!internal_load_font(pf, path, buffer, buffer_size))
+        lock_font_handle(*handle, false);
+        core_free(*handle);
+        *handle = -1;
         return -1;
+    }
         
-    sysfonts[font_id] = pf;
+    lock_font_handle(*handle, false);
+    //printf("%s -> [%d] -> %d\n", path, font_id, *handle);
     return font_id; /* success!*/
 }
 
 void font_unload(int font_id)
 {
-    struct font* pf = sysfonts[font_id];
-    if (font_id >= SYSTEMFONTCOUNT && pf)
-    {
-        if (pf->fd >= 0)
-            close(pf->fd);
-        sysfonts[font_id] = NULL;
-    }
+    int *handle = &buflib_allocations[font_id];
+    struct font* pf = pf_from_handle(*handle);
+    if (pf && pf->fd >= 0)
+        close(pf->fd);
+    if (*handle > 0)
+        core_free(*handle);
+    if (handle_for_glyphcache == *handle)
+        handle_for_glyphcache = -1; // should find the next available handle
+    *handle = -1;
+    
 }
 
 /*
@@ -478,13 +491,18 @@ void font_unload(int font_id)
 struct font* font_get(int font)
 {
     struct font* pf;
+    if (font == FONT_UI)
+        font = MAXFONTS-1;
+    if (font <= FONT_SYSFIXED)
+        return &sysfont;
 
     while (1) {
-        pf = sysfonts[font];
+        struct buflib_alloc_data *alloc = core_get_data(buflib_allocations[font]);
+        pf = &alloc->font;
         if (pf && pf->height)
             return pf;
         if (--font < 0)
-            panicf("No font!");
+            return &sysfont;
     }
 }
 
@@ -594,7 +612,8 @@ static int cache_fd;
 static void glyph_file_write(void* data)
 {
     struct font_cache_entry* p = data;
-    struct font* pf = &font_ui;
+    int handle = handle_for_glyphcache;
+    struct font* pf = pf_from_handle(handle);
     unsigned short ch;
     unsigned char tmp[2];
 
@@ -617,9 +636,9 @@ static void glyph_file_write(void* data)
 /* save the char codes of the loaded glyphs to a file */
 void glyph_cache_save(struct font* pf)
 {
-    if (!pf)
-        pf = &font_ui;
-    if (pf->fd >= 0 && pf == &font_ui) 
+    if (pf != pf_from_handle(handle_for_glyphcache))
+        return;
+    if (pf->fd >= 0) 
     {
         cache_fd = open(GLYPH_CACHE_FILE, O_WRONLY|O_CREAT|O_TRUNC, 0666);
         if (cache_fd < 0)
@@ -677,7 +696,7 @@ static void glyph_cache_load(struct font* pf)
 {
 
 #define MAX_SORT 256
-    if (pf->fd >= 0) {
+    if (pf->fd >= 0 && pf == pf_from_handle(handle_for_glyphcache)) {
         int fd;
         int i, size;
         unsigned char tmp[2];
diff --git a/tools/convbdf.c b/tools/convbdf.c
index 84ee6b2..6708ce3 100644
--- a/tools/convbdf.c
+++ b/tools/convbdf.c
@@ -1401,10 +1401,10 @@ int gen_c_source(struct font* pf, char *path)
             "  %d,  /* defaultchar */\n"
             "  %d,  /* bits_size */\n"
             "  -1,  /* font fd */\n"
-            "  0,  /* buffer start */\n"
-            "  0,  /* ^ position */\n"
-            "  0,  /* ^ end */\n"
-            "  0,  /* ^ size  */\n"
+            /* This string gets awefully close to the C90 max string length
+             * so squeeze some fields into one line to save chars */
+            "  0,0,0,0,  /* buffer start, pos, end, size */\n"
+            "  0,  /* handle locked */\n"
             "  {{0,0,0,0,0},0,0,0},   /* cache  */\n"
             "  0,  /*   */\n"
             "  0,  /*   */\n"
