
#include "WINGsP.h"
#include "WUtil.h"
#include "wconfig.h"

#include <ctype.h>
#include <string.h>
#include <strings.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 const int scalableFontSizes[] = {
	8,
	10,
	11,
	12,
	14,
	16,
	18,
	20,
	24,
	36,
	48,
	64
};

static void setFontPanelFontName(FontPanel * panel, const char *family, const char *style, double size);

static int isXLFD(const 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)
{
	/* Parameter not used, but tell the compiler that it is ok */
	(void) sPtr;
	(void) 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;

	/* Parameter not used, but tell the compiler that it is ok */
	(void) w;

	WMHideFontPanel(panel);
}

static void setClickedAction(WMWidget * w, void *data)
{
	FontPanel *panel = (FontPanel *) data;

	/* Parameter not used, but tell the compiler that it is ok */
	(void) w;

	if (panel->action)
		(*panel->action) (panel, panel->data);
}

static void revertClickedAction(WMWidget * w, void *data)
{
	/* Parameter not used, but tell the compiler that it is ok */
	(void) 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));

	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, const 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((const 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(const 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 < wlengthof(scalableFontSizes); 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, const 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));

	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, const char *name, const 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));

	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) {
			wstrlcpy(buffer, fam->name, sizeof(buffer));
			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;

		wstrlcpy(buffer, face->typeface, sizeof(buffer));
		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;

	/* Parameter not used, but tell the compiler that it is ok */
	(void) w;

	osize = WMGetTextFieldText(panel->sizT);

	item = WMGetListSelectedItem(panel->typLs);
	face = (Typeface *) item->clientData;

	WMClearList(panel->sizLs);

	WM_ITERATE_ARRAY(face->sizes, size, i) {
		if ((uintptr_t)size != 0) {
			sprintf(buffer, "%li", (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;

	/* Parameter not used, but tell the compiler that it is ok */
	(void) w;

	item = WMGetListSelectedItem(panel->sizLs);
	WMSetTextFieldText(panel->sizT, item->text);

	WMSelectTextFieldRange(panel->sizT, wmkrange(0, strlen(item->text)));

	preview(panel);
}

static void setFontPanelFontName(FontPanel * panel, const char *family, const 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;

		wstrlcpy(buffer, face->typeface, sizeof(buffer));
		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 ((uintptr_t)vsize != 0) {
			sprintf(buffer, "%li", (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) {
		return;
	}

	WMSelectListItem(panel->sizLs, sz);
	sizeClick(panel->sizLs, panel);

	return;
}
