Change to the linux kernel coding style
[wmaker-crm.git] / WINGs / wfontpanel.c
dissimilarity index 92%
index c03a779..523f85c 100644 (file)
-
-
-
-
-#include "WINGsP.h"
-#include "WUtil.h"
-#include "wconfig.h"
-
-#include <ctype.h>
-#include <string.h>
-#include <stdint.h>
-
-#include <X11/Xft/Xft.h>
-#include <fontconfig/fontconfig.h>
-
-
-/* XXX TODO */
-char *WMFontPanelFontChangedNotification = "WMFontPanelFontChangedNotification";
-
-
-
-
-typedef struct W_FontPanel {
-    WMWindow *win;
-
-    WMFrame *upperF;
-    WMTextField *sampleT;
-
-    WMSplitView *split;
-
-    WMFrame *lowerF;
-    WMLabel *famL;
-    WMList *famLs;
-    WMLabel *typL;
-    WMList *typLs;
-    WMLabel *sizL;
-    WMTextField *sizT;
-    WMList *sizLs;
-
-    WMAction2 *action;
-    void *data;
-
-    WMButton *revertB;
-    WMButton *setB;
-
-    WMPropList *fdb;
-} FontPanel;
-
-
-#define MIN_UPPER_HEIGHT       20
-#define MIN_LOWER_HEIGHT       140
-
-
-#define MAX_FONTS_TO_RETRIEVE  2000
-
-#define BUTTON_SPACE_HEIGHT 40
-
-#define MIN_WIDTH      250
-#define MIN_HEIGHT     (MIN_UPPER_HEIGHT+MIN_LOWER_HEIGHT+BUTTON_SPACE_HEIGHT)
-
-#define DEF_UPPER_HEIGHT 60
-#define DEF_LOWER_HEIGHT 310
-
-#define DEF_WIDTH      320
-#define DEF_HEIGHT     (DEF_UPPER_HEIGHT+DEF_LOWER_HEIGHT)
-
-
-
-
-static int scalableFontSizes[] = {
-    8,
-    10,
-    11,
-    12,
-    14,
-    16,
-    18,
-    20,
-    24,
-    36,
-    48,
-    64
-};
-
-
-
-static void setFontPanelFontName(FontPanel *panel, char *family, char *style, double size);
-
-static int isXLFD(char *font, int *length_ret);
-
-static void arrangeLowerFrame(FontPanel *panel);
-
-static void familyClick(WMWidget *, void *);
-static void typefaceClick(WMWidget *, void *);
-static void sizeClick(WMWidget *, void *);
-
-
-static void listFamilies(WMScreen *scr, WMFontPanel *panel);
-
-
-static void
-splitViewConstrainCallback(WMSplitView *sPtr, int indView, int *min, int *max)
-{
-    if (indView == 0)
-        *min = MIN_UPPER_HEIGHT;
-    else
-        *min = MIN_LOWER_HEIGHT;
-}
-
-static void
-notificationObserver(void *self, WMNotification *notif)
-{
-    WMFontPanel *panel = (WMFontPanel*)self;
-    void *object = WMGetNotificationObject(notif);
-
-    if (WMGetNotificationName(notif) == WMViewSizeDidChangeNotification) {
-        if (object == WMWidgetView(panel->win)) {
-            int h = WMWidgetHeight(panel->win);
-            int w = WMWidgetWidth(panel->win);
-
-            WMResizeWidget(panel->split, w, h-BUTTON_SPACE_HEIGHT);
-
-            WMMoveWidget(panel->setB, w-80, h-(BUTTON_SPACE_HEIGHT-5));
-
-            WMMoveWidget(panel->revertB, w-240, h-(BUTTON_SPACE_HEIGHT-5));
-
-        } else if (object == WMWidgetView(panel->upperF)) {
-
-            if (WMWidgetHeight(panel->upperF) < MIN_UPPER_HEIGHT) {
-                WMResizeWidget(panel->upperF, WMWidgetWidth(panel->upperF),
-                               MIN_UPPER_HEIGHT);
-            } else {
-                WMResizeWidget(panel->sampleT, WMWidgetWidth(panel->upperF)-20,
-                               WMWidgetHeight(panel->upperF)-10);
-            }
-
-        } else if (object == WMWidgetView(panel->lowerF)) {
-
-            if (WMWidgetHeight(panel->lowerF) < MIN_LOWER_HEIGHT) {
-                WMResizeWidget(panel->upperF, WMWidgetWidth(panel->upperF),
-                               MIN_UPPER_HEIGHT);
-
-                WMMoveWidget(panel->lowerF, 0, WMWidgetHeight(panel->upperF)
-                             + WMGetSplitViewDividerThickness(panel->split));
-
-                WMResizeWidget(panel->lowerF, WMWidgetWidth(panel->lowerF),
-                               WMWidgetWidth(panel->split) - MIN_UPPER_HEIGHT
-                               - WMGetSplitViewDividerThickness(panel->split));
-            } else {
-                arrangeLowerFrame(panel);
-            }
-        }
-    }
-}
-
-
-static void
-closeWindow(WMWidget *w, void *data)
-{
-    FontPanel *panel = (FontPanel*)data;
-
-    WMHideFontPanel(panel);
-}
-
-
-
-
-static void
-setClickedAction(WMWidget *w, void *data)
-{
-    FontPanel *panel = (FontPanel*)data;
-
-    if (panel->action)
-        (*panel->action)(panel, panel->data);
-}
-
-
-static void
-revertClickedAction(WMWidget *w, void *data)
-{
-    /*FontPanel *panel = (FontPanel*)data;*/
-    /* XXX TODO */
-}
-
-
-
-WMFontPanel*
-WMGetFontPanel(WMScreen *scr)
-{
-    FontPanel *panel;
-    WMColor *dark, *white;
-    WMFont *font;
-    int divThickness;
-
-    if (scr->sharedFontPanel)
-        return scr->sharedFontPanel;
-
-
-    panel = wmalloc(sizeof(FontPanel));
-    memset(panel, 0, sizeof(FontPanel));
-
-    panel->win = WMCreateWindow(scr, "fontPanel");
-    /*    WMSetWidgetBackgroundColor(panel->win, WMWhiteColor(scr));*/
-    WMSetWindowTitle(panel->win, _("Font Panel"));
-    WMResizeWidget(panel->win, DEF_WIDTH, DEF_HEIGHT);
-    WMSetWindowMinSize(panel->win, MIN_WIDTH, MIN_HEIGHT);
-    WMSetViewNotifySizeChanges(WMWidgetView(panel->win), True);
-
-    WMSetWindowCloseAction(panel->win, closeWindow, panel);
-
-    panel->split = WMCreateSplitView(panel->win);
-    WMResizeWidget(panel->split, DEF_WIDTH, DEF_HEIGHT - BUTTON_SPACE_HEIGHT);
-    WMSetSplitViewConstrainProc(panel->split, splitViewConstrainCallback);
-
-    divThickness = WMGetSplitViewDividerThickness(panel->split);
-
-    panel->upperF = WMCreateFrame(panel->win);
-    WMSetFrameRelief(panel->upperF, WRFlat);
-    WMSetViewNotifySizeChanges(WMWidgetView(panel->upperF), True);
-    panel->lowerF = WMCreateFrame(panel->win);
-    /*    WMSetWidgetBackgroundColor(panel->lowerF, WMBlackColor(scr));*/
-    WMSetFrameRelief(panel->lowerF, WRFlat);
-    WMSetViewNotifySizeChanges(WMWidgetView(panel->lowerF), True);
-
-    WMAddSplitViewSubview(panel->split, W_VIEW(panel->upperF));
-    WMAddSplitViewSubview(panel->split, W_VIEW(panel->lowerF));
-
-    WMResizeWidget(panel->upperF, DEF_WIDTH, DEF_UPPER_HEIGHT);
-
-    WMResizeWidget(panel->lowerF, DEF_WIDTH, DEF_LOWER_HEIGHT);
-
-    WMMoveWidget(panel->lowerF, 0, 60+divThickness);
-
-    white = WMWhiteColor(scr);
-    dark = WMDarkGrayColor(scr);
-
-    panel->sampleT = WMCreateTextField(panel->upperF);
-    WMResizeWidget(panel->sampleT, DEF_WIDTH - 20, 50);
-    WMMoveWidget(panel->sampleT, 10, 10);
-    WMSetTextFieldText(panel->sampleT, _("The quick brown fox jumps over the lazy dog"));
-
-    font = WMBoldSystemFontOfSize(scr, 12);
-
-    panel->famL = WMCreateLabel(panel->lowerF);
-    WMSetWidgetBackgroundColor(panel->famL, dark);
-    WMSetLabelText(panel->famL, _("Family"));
-    WMSetLabelFont(panel->famL, font);
-    WMSetLabelTextColor(panel->famL, white);
-    WMSetLabelRelief(panel->famL, WRSunken);
-    WMSetLabelTextAlignment(panel->famL, WACenter);
-
-    panel->famLs = WMCreateList(panel->lowerF);
-    WMSetListAction(panel->famLs, familyClick, panel);
-
-    panel->typL = WMCreateLabel(panel->lowerF);
-    WMSetWidgetBackgroundColor(panel->typL, dark);
-    WMSetLabelText(panel->typL, _("Typeface"));
-    WMSetLabelFont(panel->typL, font);
-    WMSetLabelTextColor(panel->typL, white);
-    WMSetLabelRelief(panel->typL, WRSunken);
-    WMSetLabelTextAlignment(panel->typL, WACenter);
-
-    panel->typLs = WMCreateList(panel->lowerF);
-    WMSetListAction(panel->typLs, typefaceClick, panel);
-
-    panel->sizL = WMCreateLabel(panel->lowerF);
-    WMSetWidgetBackgroundColor(panel->sizL, dark);
-    WMSetLabelText(panel->sizL, _("Size"));
-    WMSetLabelFont(panel->sizL, font);
-    WMSetLabelTextColor(panel->sizL, white);
-    WMSetLabelRelief(panel->sizL, WRSunken);
-    WMSetLabelTextAlignment(panel->sizL, WACenter);
-
-    panel->sizT = WMCreateTextField(panel->lowerF);
-    /*    WMSetTextFieldAlignment(panel->sizT, WARight);*/
-
-    panel->sizLs = WMCreateList(panel->lowerF);
-    WMSetListAction(panel->sizLs, sizeClick, panel);
-
-    WMReleaseFont(font);
-    WMReleaseColor(white);
-    WMReleaseColor(dark);
-
-    panel->setB = WMCreateCommandButton(panel->win);
-    WMResizeWidget(panel->setB, 70, 24);
-    WMMoveWidget(panel->setB, 240, DEF_HEIGHT - (BUTTON_SPACE_HEIGHT-5));
-    WMSetButtonText(panel->setB, _("Set"));
-    WMSetButtonAction(panel->setB, setClickedAction, panel);
-
-    panel->revertB = WMCreateCommandButton(panel->win);
-    WMResizeWidget(panel->revertB, 70, 24);
-    WMMoveWidget(panel->revertB, 80, DEF_HEIGHT - (BUTTON_SPACE_HEIGHT-5));
-    WMSetButtonText(panel->revertB, _("Revert"));
-    WMSetButtonAction(panel->revertB, revertClickedAction, panel);
-
-
-    WMRealizeWidget(panel->win);
-
-    WMMapSubwidgets(panel->upperF);
-    WMMapSubwidgets(panel->lowerF);
-    WMMapSubwidgets(panel->split);
-    WMMapSubwidgets(panel->win);
-
-    WMUnmapWidget(panel->revertB);
-
-    arrangeLowerFrame(panel);
-
-    scr->sharedFontPanel = panel;
-
-
-    /* register notification observers */
-    WMAddNotificationObserver(notificationObserver, panel,
-                              WMViewSizeDidChangeNotification,
-                              WMWidgetView(panel->win));
-    WMAddNotificationObserver(notificationObserver, panel,
-                              WMViewSizeDidChangeNotification,
-                              WMWidgetView(panel->upperF));
-    WMAddNotificationObserver(notificationObserver, panel,
-                              WMViewSizeDidChangeNotification,
-                              WMWidgetView(panel->lowerF));
-
-
-    listFamilies(scr, panel);
-
-
-    return panel;
-}
-
-
-void
-WMFreeFontPanel(WMFontPanel *panel)
-{
-    if (panel == WMWidgetScreen(panel->win)->sharedFontPanel) {
-        WMWidgetScreen(panel->win)->sharedFontPanel = NULL;
-    }
-    WMRemoveNotificationObserver(panel);
-    WMUnmapWidget(panel->win);
-    WMDestroyWidget(panel->win);
-    wfree(panel);
-}
-
-
-void
-WMShowFontPanel(WMFontPanel *panel)
-{
-    WMMapWidget(panel->win);
-}
-
-
-void
-WMHideFontPanel(WMFontPanel *panel)
-{
-    WMUnmapWidget(panel->win);
-}
-
-
-WMFont*
-WMGetFontPanelFont(WMFontPanel *panel)
-{
-    return WMGetTextFieldFont(panel->sampleT);
-}
-
-
-void
-WMSetFontPanelFont(WMFontPanel *panel, char *fontName)
-{
-    int fname_len;
-    FcPattern *pattern;
-    FcChar8 *family, *style;
-    double size;
-
-    if (!isXLFD(fontName, &fname_len)) {
-        /* maybe its proper fontconfig and we can parse it */
-        pattern = FcNameParse((FcChar8*)fontName);
-    } else {
-        /* maybe its proper xlfd and we can convert it to an FcPattern */
-        pattern = XftXlfdParse(fontName, False, False);
-        /*//FcPatternPrint(pattern);*/
-    }
-
-    if (!pattern)
-        return;
-
-    if (FcPatternGetString(pattern, FC_FAMILY, 0, &family)==FcResultMatch)
-        if (FcPatternGetString(pattern, FC_STYLE, 0, &style)==FcResultMatch)
-            if (FcPatternGetDouble(pattern, "pixelsize", 0, &size)==FcResultMatch)
-                setFontPanelFontName(panel, (char*)family, (char*)style, size);
-
-    FcPatternDestroy(pattern);
-}
-
-
-void
-WMSetFontPanelAction(WMFontPanel *panel, WMAction2 *action, void *data)
-{
-    panel->action = action;
-    panel->data = data;
-}
-
-
-
-
-
-static void
-arrangeLowerFrame(FontPanel *panel)
-{
-    int width = WMWidgetWidth(panel->lowerF) - 55 - 30;
-    int height = WMWidgetHeight(panel->split) - WMWidgetHeight(panel->upperF);
-    int fw, tw, sw;
-
-#define LABEL_HEIGHT 20
-
-    height -= WMGetSplitViewDividerThickness(panel->split);
-
-
-    height -= LABEL_HEIGHT + 8;
-
-    fw = (125*width) / 235;
-    tw = (110*width) / 235;
-    sw = 55;
-
-    WMMoveWidget(panel->famL, 10, 0);
-    WMResizeWidget(panel->famL, fw, LABEL_HEIGHT);
-
-    WMMoveWidget(panel->famLs, 10, 23);
-    WMResizeWidget(panel->famLs, fw, height);
-
-    WMMoveWidget(panel->typL, 10+fw+3, 0);
-    WMResizeWidget(panel->typL, tw, LABEL_HEIGHT);
-
-    WMMoveWidget(panel->typLs, 10+fw+3, 23);
-    WMResizeWidget(panel->typLs, tw, height);
-
-    WMMoveWidget(panel->sizL, 10+fw+3+tw+3, 0);
-    WMResizeWidget(panel->sizL, sw+4, LABEL_HEIGHT);
-
-    WMMoveWidget(panel->sizT, 10+fw+3+tw+3, 23);
-    WMResizeWidget(panel->sizT, sw+4, 20);
-
-    WMMoveWidget(panel->sizLs, 10+fw+3+tw+3, 46);
-    WMResizeWidget(panel->sizLs, sw+4, height-23);
-}
-
-
-
-#define NUM_FIELDS 14
-
-
-static int
-isXLFD(char *font, int *length_ret)
-{
-    int c = 0;
-
-    *length_ret = 0;
-    while (*font) {
-        (*length_ret)++;
-        if (*font++ == '-')
-            c++;
-    }
-
-    return c==NUM_FIELDS;
-}
-
-
-typedef struct {
-    char *typeface;
-    WMArray *sizes;
-} Typeface;
-
-typedef struct {
-    char *name; /* gotta love simplicity */
-    WMArray *typefaces;
-} Family;
-
-
-static int
-compare_int(const void *a, const void *b)
-{
-    int i1 = *(int*)a;
-    int i2 = *(int*)b;
-
-    if (i1 < i2)
-        return -1;
-    else if (i1 > i2)
-        return 1;
-    else
-        return 0;
-}
-
-
-static void
-addSizeToTypeface(Typeface *face, int size)
-{
-    if (size == 0) {
-        int j;
-
-        for (j = 0; j < sizeof(scalableFontSizes)/sizeof(int); j++) {
-            size = scalableFontSizes[j];
-
-            if (!WMCountInArray(face->sizes, (void*)(uintptr_t)size)) {
-                WMAddToArray(face->sizes, (void*)(uintptr_t)size);
-            }
-        }
-        WMSortArray(face->sizes, compare_int);
-    } else {
-        if (!WMCountInArray(face->sizes, (void*)(uintptr_t)size)) {
-            WMAddToArray(face->sizes, (void*)(uintptr_t)size);
-            WMSortArray(face->sizes, compare_int);
-        }
-    }
-}
-
-static void
-addTypefaceToXftFamily(Family *fam, char *style)
-{
-    Typeface *face;
-    WMArrayIterator i;
-
-    if(fam->typefaces) {
-        WM_ITERATE_ARRAY(fam->typefaces, face, i) {
-            if(strcmp(face->typeface, style) != 0)
-                continue; /* go to next interation */
-            addSizeToTypeface(face, 0);
-            return;
-        }
-    } else {
-        fam->typefaces = WMCreateArray(4);
-    }
-
-    face = wmalloc(sizeof(Typeface));
-    memset(face, 0 , sizeof(Typeface));
-
-    face->typeface = wstrdup(style);
-    face->sizes = WMCreateArray(4);
-    addSizeToTypeface(face, 0);
-
-    WMAddToArray(fam->typefaces, face);
-}
-
-/*
- * families (same family name) (Hashtable of family -> array)
- *     registries (same family but different registries)
- *
- */
-static void
-addFontToXftFamily(WMHashTable *families, char *name, char *style)
-{
-    WMArrayIterator i;
-    WMArray *array;
-    Family *fam;
-
-    array = WMHashGet(families, name);
-    if(array) {
-        WM_ITERATE_ARRAY(array, fam, i) {
-            if(strcmp(fam->name, name) == 0 )
-                addTypefaceToXftFamily(fam, style);
-            return;
-        }
-    }
-
-    array = WMCreateArray(8);
-
-    fam = wmalloc(sizeof(Family));
-    memset(fam, 0, sizeof(Family));
-
-    fam->name = wstrdup(name);
-
-    addTypefaceToXftFamily(fam, style);
-
-    WMAddToArray(array, fam);
-
-    WMHashInsert(families, fam->name, array);
-}
-
-
-static void
-listFamilies(WMScreen *scr, WMFontPanel *panel)
-{
-    FcObjectSet *os = 0;
-    FcFontSet  *fs;
-    FcPattern  *pat;
-    WMHashTable *families;
-    WMHashEnumerator enumer;
-    WMArray *array;
-    int i;
-
-    pat = FcPatternCreate();
-    os = FcObjectSetBuild(FC_FAMILY, FC_STYLE, NULL);
-    fs = FcFontList(0, pat, os);
-    if (!fs) {
-        WMRunAlertPanel(scr, panel->win, _("Error"),
-                        _("Could not init font config library\n"), _("OK"), NULL, NULL);
-        return;
-    }
-    if (pat)
-        FcPatternDestroy (pat);
-
-    families = WMCreateHashTable(WMStringPointerHashCallbacks);
-
-    if(fs) {
-        for (i = 0; i < fs->nfont; i++) {
-            FcChar8 *family;
-            FcChar8 *style;
-
-            if (FcPatternGetString(fs->fonts[i],FC_FAMILY,0,&family)==FcResultMatch)
-                if (FcPatternGetString(fs->fonts[i],FC_STYLE,0,&style)==FcResultMatch)
-                    addFontToXftFamily(families, (char*)family, (char*)style);
-        }
-        FcFontSetDestroy(fs);
-    }
-
-    enumer = WMEnumerateHashTable(families);
-
-    while ((array = WMNextHashEnumeratorItem(&enumer))) {
-        WMArrayIterator i;
-        Family *fam;
-        char buffer[256];
-        WMListItem *item;
-
-        WM_ITERATE_ARRAY(array, fam, i) {
-            strcpy(buffer, fam->name);
-            item = WMAddListItem(panel->famLs, buffer);
-
-            item->clientData = fam;
-        }
-
-        WMFreeArray(array);
-    }
-
-    WMSortListItems(panel->famLs);
-
-    WMFreeHashTable(families);
-}
-
-
-static void
-getSelectedFont(FontPanel *panel, char buffer[], int bufsize)
-{
-    WMListItem *item;
-    Family *family;
-    Typeface *face;
-    char *size;
-
-
-    item = WMGetListSelectedItem(panel->famLs);
-    if (!item)
-        return;
-    family = (Family*)item->clientData;
-
-    item = WMGetListSelectedItem(panel->typLs);
-    if (!item)
-        return;
-    face = (Typeface*)item->clientData;
-
-    size = WMGetTextFieldText(panel->sizT);
-
-    snprintf(buffer, bufsize, "%s:style=%s:pixelsize=%s",
-             family->name,
-             face->typeface,
-             size);
-
-    wfree(size);
-}
-
-
-
-static void
-preview(FontPanel *panel)
-{
-    char buffer[512];
-    WMFont *font;
-
-    getSelectedFont(panel, buffer, sizeof(buffer));
-    font = WMCreateFont(WMWidgetScreen(panel->win), buffer);
-    if (font) {
-        WMSetTextFieldFont(panel->sampleT, font);
-        WMReleaseFont(font);
-    }
-}
-
-
-
-static void
-familyClick(WMWidget *w, void *data)
-{
-    WMList *lPtr = (WMList*)w;
-    WMListItem *item;
-    Family *family;
-    Typeface *face;
-    FontPanel *panel = (FontPanel*)data;
-    WMArrayIterator i;
-    /* current typeface and size */
-    char *oface = NULL;
-    char *osize = NULL;
-    int facei = -1;
-    int sizei = -1;
-
-    /* must try to keep the same typeface and size for the new family */
-    item = WMGetListSelectedItem(panel->typLs);
-    if (item)
-        oface = wstrdup(item->text);
-
-    osize = WMGetTextFieldText(panel->sizT);
-
-
-    item = WMGetListSelectedItem(lPtr);
-    family = (Family*)item->clientData;
-
-    WMClearList(panel->typLs);
-
-
-    WM_ITERATE_ARRAY(family->typefaces, face, i) {
-        char buffer[256];
-        int top=0;
-        WMListItem *fitem;
-
-        strcpy(buffer, face->typeface);
-        if(strcasecmp(face->typeface, "Roman") == 0)
-            top = 1;
-        if(strcasecmp(face->typeface, "Regular") == 0)
-            top = 1;
-        if (top)
-            fitem = WMInsertListItem(panel->typLs, 0, buffer);
-        else
-            fitem = WMAddListItem(panel->typLs, buffer);
-        fitem->clientData = face;
-    }
-
-    if (oface) {
-        facei = WMFindRowOfListItemWithTitle(panel->typLs, oface);
-        wfree(oface);
-    }
-    if (facei < 0) {
-        facei = 0;
-    }
-    WMSelectListItem(panel->typLs, facei);
-    typefaceClick(panel->typLs, panel);
-
-    if (osize) {
-        sizei = WMFindRowOfListItemWithTitle(panel->sizLs, osize);
-    }
-    if (sizei >= 0) {
-        WMSelectListItem(panel->sizLs, sizei);
-        sizeClick(panel->sizLs, panel);
-    }
-
-    if (osize)
-        wfree(osize);
-
-
-    preview(panel);
-}
-
-
-static void
-typefaceClick(WMWidget *w, void *data)
-{
-    FontPanel *panel = (FontPanel*)data;
-    WMListItem *item;
-    Typeface *face;
-    WMArrayIterator i;
-    char buffer[32];
-
-    char *osize = NULL;
-    int sizei = -1;
-    void *size;
-
-    osize = WMGetTextFieldText(panel->sizT);
-
-
-    item = WMGetListSelectedItem(panel->typLs);
-    face = (Typeface*)item->clientData;
-
-    WMClearList(panel->sizLs);
-
-    WM_ITERATE_ARRAY(face->sizes, size, i) {
-        if ((int)(uintptr_t)size != 0) {
-            sprintf(buffer, "%i", (int)(uintptr_t)size);
-
-            WMAddListItem(panel->sizLs, buffer);
-        }
-    }
-
-    if (osize) {
-        sizei = WMFindRowOfListItemWithTitle(panel->sizLs, osize);
-    }
-    if (sizei < 0) {
-        sizei = WMFindRowOfListItemWithTitle(panel->sizLs, "12");
-    }
-    if (sizei < 0) {
-        sizei = 0;
-    }
-    WMSelectListItem(panel->sizLs, sizei);
-    WMSetListPosition(panel->sizLs, sizei);
-    sizeClick(panel->sizLs, panel);
-
-    if (osize)
-        wfree(osize);
-
-    preview(panel);
-}
-
-static void
-sizeClick(WMWidget *w, void *data)
-{
-    FontPanel *panel = (FontPanel*)data;
-    WMListItem *item;
-
-    item = WMGetListSelectedItem(panel->sizLs);
-    WMSetTextFieldText(panel->sizT, item->text);
-
-    WMSelectTextFieldRange(panel->sizT, wmkrange(0, strlen(item->text)));
-
-    preview(panel);
-}
-
-
-static void
-setFontPanelFontName(FontPanel *panel, char *family, char *style, double size)
-{
-    int famrow;
-    int stlrow;
-    int sz;
-    char asize[64];
-    void *vsize;
-    WMListItem *item;
-    Family *fam;
-    Typeface *face;
-    WMArrayIterator i;
-
-    famrow = WMFindRowOfListItemWithTitle(panel->famLs, family);
-    if (famrow < 0 ){
-        famrow = 0;
-        return;
-    }
-    WMSelectListItem(panel->famLs, famrow);
-    WMSetListPosition(panel->famLs, famrow);
-
-    WMClearList(panel->typLs);
-
-    item = WMGetListSelectedItem(panel->famLs);
-
-    fam = (Family*)item->clientData;
-    WM_ITERATE_ARRAY(fam->typefaces, face, i) {
-        char buffer[256];
-        int top=0;
-        WMListItem *fitem;
-
-        strcpy(buffer, face->typeface);
-        if(strcasecmp(face->typeface, "Roman") == 0)
-            top = 1;
-        if (top)
-            fitem = WMInsertListItem(panel->typLs, 0, buffer);
-        else
-            fitem = WMAddListItem(panel->typLs, buffer);
-        fitem->clientData = face;
-    }
-
-
-    stlrow = WMFindRowOfListItemWithTitle(panel->typLs, style);
-
-    if (stlrow < 0) {
-        stlrow = 0;
-        return;
-    }
-
-    WMSelectListItem(panel->typLs, stlrow);
-
-    item = WMGetListSelectedItem(panel->typLs);
-
-    face = (Typeface*)item->clientData;
-
-    WMClearList(panel->sizLs);
-
-
-    WM_ITERATE_ARRAY(face->sizes, vsize, i) {
-        char buffer[32];
-        if ((int)(uintptr_t)vsize != 0) {
-            sprintf(buffer, "%i", (int)(uintptr_t)vsize);
-
-            WMAddListItem(panel->sizLs, buffer);
-        }
-    }
-
-    snprintf(asize, sizeof(asize)-1, "%d",(int)(size+0.5));
-
-    sz = WMFindRowOfListItemWithTitle(panel->sizLs, asize);
-
-    if (sz < 0) {
-        sz = 4;
-        return;
-    }
-
-    WMSelectListItem(panel->sizLs, sz);
-    sizeClick(panel->sizLs, panel);
-
-    return;
-}
-
-
+
+#include "WINGsP.h"
+#include "WUtil.h"
+#include "wconfig.h"
+
+#include <ctype.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <X11/Xft/Xft.h>
+#include <fontconfig/fontconfig.h>
+
+/* XXX TODO */
+char *WMFontPanelFontChangedNotification = "WMFontPanelFontChangedNotification";
+
+typedef struct W_FontPanel {
+       WMWindow *win;
+
+       WMFrame *upperF;
+       WMTextField *sampleT;
+
+       WMSplitView *split;
+
+       WMFrame *lowerF;
+       WMLabel *famL;
+       WMList *famLs;
+       WMLabel *typL;
+       WMList *typLs;
+       WMLabel *sizL;
+       WMTextField *sizT;
+       WMList *sizLs;
+
+       WMAction2 *action;
+       void *data;
+
+       WMButton *revertB;
+       WMButton *setB;
+
+       WMPropList *fdb;
+} FontPanel;
+
+#define MIN_UPPER_HEIGHT       20
+#define MIN_LOWER_HEIGHT       140
+
+#define MAX_FONTS_TO_RETRIEVE  2000
+
+#define BUTTON_SPACE_HEIGHT 40
+
+#define MIN_WIDTH      250
+#define MIN_HEIGHT     (MIN_UPPER_HEIGHT+MIN_LOWER_HEIGHT+BUTTON_SPACE_HEIGHT)
+
+#define DEF_UPPER_HEIGHT 60
+#define DEF_LOWER_HEIGHT 310
+
+#define DEF_WIDTH      320
+#define DEF_HEIGHT     (DEF_UPPER_HEIGHT+DEF_LOWER_HEIGHT)
+
+static int scalableFontSizes[] = {
+       8,
+       10,
+       11,
+       12,
+       14,
+       16,
+       18,
+       20,
+       24,
+       36,
+       48,
+       64
+};
+
+static void setFontPanelFontName(FontPanel * panel, char *family, char *style, double size);
+
+static int isXLFD(char *font, int *length_ret);
+
+static void arrangeLowerFrame(FontPanel * panel);
+
+static void familyClick(WMWidget *, void *);
+static void typefaceClick(WMWidget *, void *);
+static void sizeClick(WMWidget *, void *);
+
+static void listFamilies(WMScreen * scr, WMFontPanel * panel);
+
+static void splitViewConstrainCallback(WMSplitView * sPtr, int indView, int *min, int *max)
+{
+       if (indView == 0)
+               *min = MIN_UPPER_HEIGHT;
+       else
+               *min = MIN_LOWER_HEIGHT;
+}
+
+static void notificationObserver(void *self, WMNotification * notif)
+{
+       WMFontPanel *panel = (WMFontPanel *) self;
+       void *object = WMGetNotificationObject(notif);
+
+       if (WMGetNotificationName(notif) == WMViewSizeDidChangeNotification) {
+               if (object == WMWidgetView(panel->win)) {
+                       int h = WMWidgetHeight(panel->win);
+                       int w = WMWidgetWidth(panel->win);
+
+                       WMResizeWidget(panel->split, w, h - BUTTON_SPACE_HEIGHT);
+
+                       WMMoveWidget(panel->setB, w - 80, h - (BUTTON_SPACE_HEIGHT - 5));
+
+                       WMMoveWidget(panel->revertB, w - 240, h - (BUTTON_SPACE_HEIGHT - 5));
+
+               } else if (object == WMWidgetView(panel->upperF)) {
+
+                       if (WMWidgetHeight(panel->upperF) < MIN_UPPER_HEIGHT) {
+                               WMResizeWidget(panel->upperF, WMWidgetWidth(panel->upperF), MIN_UPPER_HEIGHT);
+                       } else {
+                               WMResizeWidget(panel->sampleT, WMWidgetWidth(panel->upperF) - 20,
+                                              WMWidgetHeight(panel->upperF) - 10);
+                       }
+
+               } else if (object == WMWidgetView(panel->lowerF)) {
+
+                       if (WMWidgetHeight(panel->lowerF) < MIN_LOWER_HEIGHT) {
+                               WMResizeWidget(panel->upperF, WMWidgetWidth(panel->upperF), MIN_UPPER_HEIGHT);
+
+                               WMMoveWidget(panel->lowerF, 0, WMWidgetHeight(panel->upperF)
+                                            + WMGetSplitViewDividerThickness(panel->split));
+
+                               WMResizeWidget(panel->lowerF, WMWidgetWidth(panel->lowerF),
+                                              WMWidgetWidth(panel->split) - MIN_UPPER_HEIGHT
+                                              - WMGetSplitViewDividerThickness(panel->split));
+                       } else {
+                               arrangeLowerFrame(panel);
+                       }
+               }
+       }
+}
+
+static void closeWindow(WMWidget * w, void *data)
+{
+       FontPanel *panel = (FontPanel *) data;
+
+       WMHideFontPanel(panel);
+}
+
+static void setClickedAction(WMWidget * w, void *data)
+{
+       FontPanel *panel = (FontPanel *) data;
+
+       if (panel->action)
+               (*panel->action) (panel, panel->data);
+}
+
+static void revertClickedAction(WMWidget * w, void *data)
+{
+       /*FontPanel *panel = (FontPanel*)data; */
+       /* XXX TODO */
+}
+
+WMFontPanel *WMGetFontPanel(WMScreen * scr)
+{
+       FontPanel *panel;
+       WMColor *dark, *white;
+       WMFont *font;
+       int divThickness;
+
+       if (scr->sharedFontPanel)
+               return scr->sharedFontPanel;
+
+       panel = wmalloc(sizeof(FontPanel));
+       memset(panel, 0, sizeof(FontPanel));
+
+       panel->win = WMCreateWindow(scr, "fontPanel");
+       /*    WMSetWidgetBackgroundColor(panel->win, WMWhiteColor(scr)); */
+       WMSetWindowTitle(panel->win, _("Font Panel"));
+       WMResizeWidget(panel->win, DEF_WIDTH, DEF_HEIGHT);
+       WMSetWindowMinSize(panel->win, MIN_WIDTH, MIN_HEIGHT);
+       WMSetViewNotifySizeChanges(WMWidgetView(panel->win), True);
+
+       WMSetWindowCloseAction(panel->win, closeWindow, panel);
+
+       panel->split = WMCreateSplitView(panel->win);
+       WMResizeWidget(panel->split, DEF_WIDTH, DEF_HEIGHT - BUTTON_SPACE_HEIGHT);
+       WMSetSplitViewConstrainProc(panel->split, splitViewConstrainCallback);
+
+       divThickness = WMGetSplitViewDividerThickness(panel->split);
+
+       panel->upperF = WMCreateFrame(panel->win);
+       WMSetFrameRelief(panel->upperF, WRFlat);
+       WMSetViewNotifySizeChanges(WMWidgetView(panel->upperF), True);
+       panel->lowerF = WMCreateFrame(panel->win);
+       /*    WMSetWidgetBackgroundColor(panel->lowerF, WMBlackColor(scr)); */
+       WMSetFrameRelief(panel->lowerF, WRFlat);
+       WMSetViewNotifySizeChanges(WMWidgetView(panel->lowerF), True);
+
+       WMAddSplitViewSubview(panel->split, W_VIEW(panel->upperF));
+       WMAddSplitViewSubview(panel->split, W_VIEW(panel->lowerF));
+
+       WMResizeWidget(panel->upperF, DEF_WIDTH, DEF_UPPER_HEIGHT);
+
+       WMResizeWidget(panel->lowerF, DEF_WIDTH, DEF_LOWER_HEIGHT);
+
+       WMMoveWidget(panel->lowerF, 0, 60 + divThickness);
+
+       white = WMWhiteColor(scr);
+       dark = WMDarkGrayColor(scr);
+
+       panel->sampleT = WMCreateTextField(panel->upperF);
+       WMResizeWidget(panel->sampleT, DEF_WIDTH - 20, 50);
+       WMMoveWidget(panel->sampleT, 10, 10);
+       WMSetTextFieldText(panel->sampleT, _("The quick brown fox jumps over the lazy dog"));
+
+       font = WMBoldSystemFontOfSize(scr, 12);
+
+       panel->famL = WMCreateLabel(panel->lowerF);
+       WMSetWidgetBackgroundColor(panel->famL, dark);
+       WMSetLabelText(panel->famL, _("Family"));
+       WMSetLabelFont(panel->famL, font);
+       WMSetLabelTextColor(panel->famL, white);
+       WMSetLabelRelief(panel->famL, WRSunken);
+       WMSetLabelTextAlignment(panel->famL, WACenter);
+
+       panel->famLs = WMCreateList(panel->lowerF);
+       WMSetListAction(panel->famLs, familyClick, panel);
+
+       panel->typL = WMCreateLabel(panel->lowerF);
+       WMSetWidgetBackgroundColor(panel->typL, dark);
+       WMSetLabelText(panel->typL, _("Typeface"));
+       WMSetLabelFont(panel->typL, font);
+       WMSetLabelTextColor(panel->typL, white);
+       WMSetLabelRelief(panel->typL, WRSunken);
+       WMSetLabelTextAlignment(panel->typL, WACenter);
+
+       panel->typLs = WMCreateList(panel->lowerF);
+       WMSetListAction(panel->typLs, typefaceClick, panel);
+
+       panel->sizL = WMCreateLabel(panel->lowerF);
+       WMSetWidgetBackgroundColor(panel->sizL, dark);
+       WMSetLabelText(panel->sizL, _("Size"));
+       WMSetLabelFont(panel->sizL, font);
+       WMSetLabelTextColor(panel->sizL, white);
+       WMSetLabelRelief(panel->sizL, WRSunken);
+       WMSetLabelTextAlignment(panel->sizL, WACenter);
+
+       panel->sizT = WMCreateTextField(panel->lowerF);
+       /*    WMSetTextFieldAlignment(panel->sizT, WARight); */
+
+       panel->sizLs = WMCreateList(panel->lowerF);
+       WMSetListAction(panel->sizLs, sizeClick, panel);
+
+       WMReleaseFont(font);
+       WMReleaseColor(white);
+       WMReleaseColor(dark);
+
+       panel->setB = WMCreateCommandButton(panel->win);
+       WMResizeWidget(panel->setB, 70, 24);
+       WMMoveWidget(panel->setB, 240, DEF_HEIGHT - (BUTTON_SPACE_HEIGHT - 5));
+       WMSetButtonText(panel->setB, _("Set"));
+       WMSetButtonAction(panel->setB, setClickedAction, panel);
+
+       panel->revertB = WMCreateCommandButton(panel->win);
+       WMResizeWidget(panel->revertB, 70, 24);
+       WMMoveWidget(panel->revertB, 80, DEF_HEIGHT - (BUTTON_SPACE_HEIGHT - 5));
+       WMSetButtonText(panel->revertB, _("Revert"));
+       WMSetButtonAction(panel->revertB, revertClickedAction, panel);
+
+       WMRealizeWidget(panel->win);
+
+       WMMapSubwidgets(panel->upperF);
+       WMMapSubwidgets(panel->lowerF);
+       WMMapSubwidgets(panel->split);
+       WMMapSubwidgets(panel->win);
+
+       WMUnmapWidget(panel->revertB);
+
+       arrangeLowerFrame(panel);
+
+       scr->sharedFontPanel = panel;
+
+       /* register notification observers */
+       WMAddNotificationObserver(notificationObserver, panel,
+                                 WMViewSizeDidChangeNotification, WMWidgetView(panel->win));
+       WMAddNotificationObserver(notificationObserver, panel,
+                                 WMViewSizeDidChangeNotification, WMWidgetView(panel->upperF));
+       WMAddNotificationObserver(notificationObserver, panel,
+                                 WMViewSizeDidChangeNotification, WMWidgetView(panel->lowerF));
+
+       listFamilies(scr, panel);
+
+       return panel;
+}
+
+void WMFreeFontPanel(WMFontPanel * panel)
+{
+       if (panel == WMWidgetScreen(panel->win)->sharedFontPanel) {
+               WMWidgetScreen(panel->win)->sharedFontPanel = NULL;
+       }
+       WMRemoveNotificationObserver(panel);
+       WMUnmapWidget(panel->win);
+       WMDestroyWidget(panel->win);
+       wfree(panel);
+}
+
+void WMShowFontPanel(WMFontPanel * panel)
+{
+       WMMapWidget(panel->win);
+}
+
+void WMHideFontPanel(WMFontPanel * panel)
+{
+       WMUnmapWidget(panel->win);
+}
+
+WMFont *WMGetFontPanelFont(WMFontPanel * panel)
+{
+       return WMGetTextFieldFont(panel->sampleT);
+}
+
+void WMSetFontPanelFont(WMFontPanel * panel, char *fontName)
+{
+       int fname_len;
+       FcPattern *pattern;
+       FcChar8 *family, *style;
+       double size;
+
+       if (!isXLFD(fontName, &fname_len)) {
+               /* maybe its proper fontconfig and we can parse it */
+               pattern = FcNameParse((FcChar8 *) fontName);
+       } else {
+               /* maybe its proper xlfd and we can convert it to an FcPattern */
+               pattern = XftXlfdParse(fontName, False, False);
+               /*//FcPatternPrint(pattern); */
+       }
+
+       if (!pattern)
+               return;
+
+       if (FcPatternGetString(pattern, FC_FAMILY, 0, &family) == FcResultMatch)
+               if (FcPatternGetString(pattern, FC_STYLE, 0, &style) == FcResultMatch)
+                       if (FcPatternGetDouble(pattern, "pixelsize", 0, &size) == FcResultMatch)
+                               setFontPanelFontName(panel, (char *)family, (char *)style, size);
+
+       FcPatternDestroy(pattern);
+}
+
+void WMSetFontPanelAction(WMFontPanel * panel, WMAction2 * action, void *data)
+{
+       panel->action = action;
+       panel->data = data;
+}
+
+static void arrangeLowerFrame(FontPanel * panel)
+{
+       int width = WMWidgetWidth(panel->lowerF) - 55 - 30;
+       int height = WMWidgetHeight(panel->split) - WMWidgetHeight(panel->upperF);
+       int fw, tw, sw;
+
+#define LABEL_HEIGHT 20
+
+       height -= WMGetSplitViewDividerThickness(panel->split);
+
+       height -= LABEL_HEIGHT + 8;
+
+       fw = (125 * width) / 235;
+       tw = (110 * width) / 235;
+       sw = 55;
+
+       WMMoveWidget(panel->famL, 10, 0);
+       WMResizeWidget(panel->famL, fw, LABEL_HEIGHT);
+
+       WMMoveWidget(panel->famLs, 10, 23);
+       WMResizeWidget(panel->famLs, fw, height);
+
+       WMMoveWidget(panel->typL, 10 + fw + 3, 0);
+       WMResizeWidget(panel->typL, tw, LABEL_HEIGHT);
+
+       WMMoveWidget(panel->typLs, 10 + fw + 3, 23);
+       WMResizeWidget(panel->typLs, tw, height);
+
+       WMMoveWidget(panel->sizL, 10 + fw + 3 + tw + 3, 0);
+       WMResizeWidget(panel->sizL, sw + 4, LABEL_HEIGHT);
+
+       WMMoveWidget(panel->sizT, 10 + fw + 3 + tw + 3, 23);
+       WMResizeWidget(panel->sizT, sw + 4, 20);
+
+       WMMoveWidget(panel->sizLs, 10 + fw + 3 + tw + 3, 46);
+       WMResizeWidget(panel->sizLs, sw + 4, height - 23);
+}
+
+#define NUM_FIELDS 14
+
+static int isXLFD(char *font, int *length_ret)
+{
+       int c = 0;
+
+       *length_ret = 0;
+       while (*font) {
+               (*length_ret)++;
+               if (*font++ == '-')
+                       c++;
+       }
+
+       return c == NUM_FIELDS;
+}
+
+typedef struct {
+       char *typeface;
+       WMArray *sizes;
+} Typeface;
+
+typedef struct {
+       char *name;             /* gotta love simplicity */
+       WMArray *typefaces;
+} Family;
+
+static int compare_int(const void *a, const void *b)
+{
+       int i1 = *(int *)a;
+       int i2 = *(int *)b;
+
+       if (i1 < i2)
+               return -1;
+       else if (i1 > i2)
+               return 1;
+       else
+               return 0;
+}
+
+static void addSizeToTypeface(Typeface * face, int size)
+{
+       if (size == 0) {
+               int j;
+
+               for (j = 0; j < sizeof(scalableFontSizes) / sizeof(int); j++) {
+                       size = scalableFontSizes[j];
+
+                       if (!WMCountInArray(face->sizes, (void *)(uintptr_t) size)) {
+                               WMAddToArray(face->sizes, (void *)(uintptr_t) size);
+                       }
+               }
+               WMSortArray(face->sizes, compare_int);
+       } else {
+               if (!WMCountInArray(face->sizes, (void *)(uintptr_t) size)) {
+                       WMAddToArray(face->sizes, (void *)(uintptr_t) size);
+                       WMSortArray(face->sizes, compare_int);
+               }
+       }
+}
+
+static void addTypefaceToXftFamily(Family * fam, char *style)
+{
+       Typeface *face;
+       WMArrayIterator i;
+
+       if (fam->typefaces) {
+               WM_ITERATE_ARRAY(fam->typefaces, face, i) {
+                       if (strcmp(face->typeface, style) != 0)
+                               continue;       /* go to next interation */
+                       addSizeToTypeface(face, 0);
+                       return;
+               }
+       } else {
+               fam->typefaces = WMCreateArray(4);
+       }
+
+       face = wmalloc(sizeof(Typeface));
+       memset(face, 0, sizeof(Typeface));
+
+       face->typeface = wstrdup(style);
+       face->sizes = WMCreateArray(4);
+       addSizeToTypeface(face, 0);
+
+       WMAddToArray(fam->typefaces, face);
+}
+
+/*
+ * families (same family name) (Hashtable of family -> array)
+ *     registries (same family but different registries)
+ *
+ */
+static void addFontToXftFamily(WMHashTable * families, char *name, char *style)
+{
+       WMArrayIterator i;
+       WMArray *array;
+       Family *fam;
+
+       array = WMHashGet(families, name);
+       if (array) {
+               WM_ITERATE_ARRAY(array, fam, i) {
+                       if (strcmp(fam->name, name) == 0)
+                               addTypefaceToXftFamily(fam, style);
+                       return;
+               }
+       }
+
+       array = WMCreateArray(8);
+
+       fam = wmalloc(sizeof(Family));
+       memset(fam, 0, sizeof(Family));
+
+       fam->name = wstrdup(name);
+
+       addTypefaceToXftFamily(fam, style);
+
+       WMAddToArray(array, fam);
+
+       WMHashInsert(families, fam->name, array);
+}
+
+static void listFamilies(WMScreen * scr, WMFontPanel * panel)
+{
+       FcObjectSet *os = 0;
+       FcFontSet *fs;
+       FcPattern *pat;
+       WMHashTable *families;
+       WMHashEnumerator enumer;
+       WMArray *array;
+       int i;
+
+       pat = FcPatternCreate();
+       os = FcObjectSetBuild(FC_FAMILY, FC_STYLE, NULL);
+       fs = FcFontList(0, pat, os);
+       if (!fs) {
+               WMRunAlertPanel(scr, panel->win, _("Error"),
+                               _("Could not init font config library\n"), _("OK"), NULL, NULL);
+               return;
+       }
+       if (pat)
+               FcPatternDestroy(pat);
+
+       families = WMCreateHashTable(WMStringPointerHashCallbacks);
+
+       if (fs) {
+               for (i = 0; i < fs->nfont; i++) {
+                       FcChar8 *family;
+                       FcChar8 *style;
+
+                       if (FcPatternGetString(fs->fonts[i], FC_FAMILY, 0, &family) == FcResultMatch)
+                               if (FcPatternGetString(fs->fonts[i], FC_STYLE, 0, &style) == FcResultMatch)
+                                       addFontToXftFamily(families, (char *)family, (char *)style);
+               }
+               FcFontSetDestroy(fs);
+       }
+
+       enumer = WMEnumerateHashTable(families);
+
+       while ((array = WMNextHashEnumeratorItem(&enumer))) {
+               WMArrayIterator i;
+               Family *fam;
+               char buffer[256];
+               WMListItem *item;
+
+               WM_ITERATE_ARRAY(array, fam, i) {
+                       strcpy(buffer, fam->name);
+                       item = WMAddListItem(panel->famLs, buffer);
+
+                       item->clientData = fam;
+               }
+
+               WMFreeArray(array);
+       }
+
+       WMSortListItems(panel->famLs);
+
+       WMFreeHashTable(families);
+}
+
+static void getSelectedFont(FontPanel * panel, char buffer[], int bufsize)
+{
+       WMListItem *item;
+       Family *family;
+       Typeface *face;
+       char *size;
+
+       item = WMGetListSelectedItem(panel->famLs);
+       if (!item)
+               return;
+       family = (Family *) item->clientData;
+
+       item = WMGetListSelectedItem(panel->typLs);
+       if (!item)
+               return;
+       face = (Typeface *) item->clientData;
+
+       size = WMGetTextFieldText(panel->sizT);
+
+       snprintf(buffer, bufsize, "%s:style=%s:pixelsize=%s", family->name, face->typeface, size);
+
+       wfree(size);
+}
+
+static void preview(FontPanel * panel)
+{
+       char buffer[512];
+       WMFont *font;
+
+       getSelectedFont(panel, buffer, sizeof(buffer));
+       font = WMCreateFont(WMWidgetScreen(panel->win), buffer);
+       if (font) {
+               WMSetTextFieldFont(panel->sampleT, font);
+               WMReleaseFont(font);
+       }
+}
+
+static void familyClick(WMWidget * w, void *data)
+{
+       WMList *lPtr = (WMList *) w;
+       WMListItem *item;
+       Family *family;
+       Typeface *face;
+       FontPanel *panel = (FontPanel *) data;
+       WMArrayIterator i;
+       /* current typeface and size */
+       char *oface = NULL;
+       char *osize = NULL;
+       int facei = -1;
+       int sizei = -1;
+
+       /* must try to keep the same typeface and size for the new family */
+       item = WMGetListSelectedItem(panel->typLs);
+       if (item)
+               oface = wstrdup(item->text);
+
+       osize = WMGetTextFieldText(panel->sizT);
+
+       item = WMGetListSelectedItem(lPtr);
+       family = (Family *) item->clientData;
+
+       WMClearList(panel->typLs);
+
+       WM_ITERATE_ARRAY(family->typefaces, face, i) {
+               char buffer[256];
+               int top = 0;
+               WMListItem *fitem;
+
+               strcpy(buffer, face->typeface);
+               if (strcasecmp(face->typeface, "Roman") == 0)
+                       top = 1;
+               if (strcasecmp(face->typeface, "Regular") == 0)
+                       top = 1;
+               if (top)
+                       fitem = WMInsertListItem(panel->typLs, 0, buffer);
+               else
+                       fitem = WMAddListItem(panel->typLs, buffer);
+               fitem->clientData = face;
+       }
+
+       if (oface) {
+               facei = WMFindRowOfListItemWithTitle(panel->typLs, oface);
+               wfree(oface);
+       }
+       if (facei < 0) {
+               facei = 0;
+       }
+       WMSelectListItem(panel->typLs, facei);
+       typefaceClick(panel->typLs, panel);
+
+       if (osize) {
+               sizei = WMFindRowOfListItemWithTitle(panel->sizLs, osize);
+       }
+       if (sizei >= 0) {
+               WMSelectListItem(panel->sizLs, sizei);
+               sizeClick(panel->sizLs, panel);
+       }
+
+       if (osize)
+               wfree(osize);
+
+       preview(panel);
+}
+
+static void typefaceClick(WMWidget * w, void *data)
+{
+       FontPanel *panel = (FontPanel *) data;
+       WMListItem *item;
+       Typeface *face;
+       WMArrayIterator i;
+       char buffer[32];
+
+       char *osize = NULL;
+       int sizei = -1;
+       void *size;
+
+       osize = WMGetTextFieldText(panel->sizT);
+
+       item = WMGetListSelectedItem(panel->typLs);
+       face = (Typeface *) item->clientData;
+
+       WMClearList(panel->sizLs);
+
+       WM_ITERATE_ARRAY(face->sizes, size, i) {
+               if ((int)(uintptr_t) size != 0) {
+                       sprintf(buffer, "%i", (int)(uintptr_t) size);
+
+                       WMAddListItem(panel->sizLs, buffer);
+               }
+       }
+
+       if (osize) {
+               sizei = WMFindRowOfListItemWithTitle(panel->sizLs, osize);
+       }
+       if (sizei < 0) {
+               sizei = WMFindRowOfListItemWithTitle(panel->sizLs, "12");
+       }
+       if (sizei < 0) {
+               sizei = 0;
+       }
+       WMSelectListItem(panel->sizLs, sizei);
+       WMSetListPosition(panel->sizLs, sizei);
+       sizeClick(panel->sizLs, panel);
+
+       if (osize)
+               wfree(osize);
+
+       preview(panel);
+}
+
+static void sizeClick(WMWidget * w, void *data)
+{
+       FontPanel *panel = (FontPanel *) data;
+       WMListItem *item;
+
+       item = WMGetListSelectedItem(panel->sizLs);
+       WMSetTextFieldText(panel->sizT, item->text);
+
+       WMSelectTextFieldRange(panel->sizT, wmkrange(0, strlen(item->text)));
+
+       preview(panel);
+}
+
+static void setFontPanelFontName(FontPanel * panel, char *family, char *style, double size)
+{
+       int famrow;
+       int stlrow;
+       int sz;
+       char asize[64];
+       void *vsize;
+       WMListItem *item;
+       Family *fam;
+       Typeface *face;
+       WMArrayIterator i;
+
+       famrow = WMFindRowOfListItemWithTitle(panel->famLs, family);
+       if (famrow < 0) {
+               famrow = 0;
+               return;
+       }
+       WMSelectListItem(panel->famLs, famrow);
+       WMSetListPosition(panel->famLs, famrow);
+
+       WMClearList(panel->typLs);
+
+       item = WMGetListSelectedItem(panel->famLs);
+
+       fam = (Family *) item->clientData;
+       WM_ITERATE_ARRAY(fam->typefaces, face, i) {
+               char buffer[256];
+               int top = 0;
+               WMListItem *fitem;
+
+               strcpy(buffer, face->typeface);
+               if (strcasecmp(face->typeface, "Roman") == 0)
+                       top = 1;
+               if (top)
+                       fitem = WMInsertListItem(panel->typLs, 0, buffer);
+               else
+                       fitem = WMAddListItem(panel->typLs, buffer);
+               fitem->clientData = face;
+       }
+
+       stlrow = WMFindRowOfListItemWithTitle(panel->typLs, style);
+
+       if (stlrow < 0) {
+               stlrow = 0;
+               return;
+       }
+
+       WMSelectListItem(panel->typLs, stlrow);
+
+       item = WMGetListSelectedItem(panel->typLs);
+
+       face = (Typeface *) item->clientData;
+
+       WMClearList(panel->sizLs);
+
+       WM_ITERATE_ARRAY(face->sizes, vsize, i) {
+               char buffer[32];
+               if ((int)(uintptr_t) vsize != 0) {
+                       sprintf(buffer, "%i", (int)(uintptr_t) vsize);
+
+                       WMAddListItem(panel->sizLs, buffer);
+               }
+       }
+
+       snprintf(asize, sizeof(asize) - 1, "%d", (int)(size + 0.5));
+
+       sz = WMFindRowOfListItemWithTitle(panel->sizLs, asize);
+
+       if (sz < 0) {
+               sz = 4;
+               return;
+       }
+
+       WMSelectListItem(panel->sizLs, sz);
+       sizeClick(panel->sizLs, panel);
+
+       return;
+}