Change to the linux kernel coding style
[wmaker-crm.git] / WINGs / wfontpanel.c
1
2 #include "WINGsP.h"
3 #include "WUtil.h"
4 #include "wconfig.h"
5
6 #include <ctype.h>
7 #include <string.h>
8 #include <stdint.h>
9
10 #include <X11/Xft/Xft.h>
11 #include <fontconfig/fontconfig.h>
12
13 /* XXX TODO */
14 char *WMFontPanelFontChangedNotification = "WMFontPanelFontChangedNotification";
15
16 typedef struct W_FontPanel {
17         WMWindow *win;
18
19         WMFrame *upperF;
20         WMTextField *sampleT;
21
22         WMSplitView *split;
23
24         WMFrame *lowerF;
25         WMLabel *famL;
26         WMList *famLs;
27         WMLabel *typL;
28         WMList *typLs;
29         WMLabel *sizL;
30         WMTextField *sizT;
31         WMList *sizLs;
32
33         WMAction2 *action;
34         void *data;
35
36         WMButton *revertB;
37         WMButton *setB;
38
39         WMPropList *fdb;
40 } FontPanel;
41
42 #define MIN_UPPER_HEIGHT        20
43 #define MIN_LOWER_HEIGHT        140
44
45 #define MAX_FONTS_TO_RETRIEVE   2000
46
47 #define BUTTON_SPACE_HEIGHT 40
48
49 #define MIN_WIDTH       250
50 #define MIN_HEIGHT      (MIN_UPPER_HEIGHT+MIN_LOWER_HEIGHT+BUTTON_SPACE_HEIGHT)
51
52 #define DEF_UPPER_HEIGHT 60
53 #define DEF_LOWER_HEIGHT 310
54
55 #define DEF_WIDTH       320
56 #define DEF_HEIGHT      (DEF_UPPER_HEIGHT+DEF_LOWER_HEIGHT)
57
58 static int scalableFontSizes[] = {
59         8,
60         10,
61         11,
62         12,
63         14,
64         16,
65         18,
66         20,
67         24,
68         36,
69         48,
70         64
71 };
72
73 static void setFontPanelFontName(FontPanel * panel, char *family, char *style, double size);
74
75 static int isXLFD(char *font, int *length_ret);
76
77 static void arrangeLowerFrame(FontPanel * panel);
78
79 static void familyClick(WMWidget *, void *);
80 static void typefaceClick(WMWidget *, void *);
81 static void sizeClick(WMWidget *, void *);
82
83 static void listFamilies(WMScreen * scr, WMFontPanel * panel);
84
85 static void splitViewConstrainCallback(WMSplitView * sPtr, int indView, int *min, int *max)
86 {
87         if (indView == 0)
88                 *min = MIN_UPPER_HEIGHT;
89         else
90                 *min = MIN_LOWER_HEIGHT;
91 }
92
93 static void notificationObserver(void *self, WMNotification * notif)
94 {
95         WMFontPanel *panel = (WMFontPanel *) self;
96         void *object = WMGetNotificationObject(notif);
97
98         if (WMGetNotificationName(notif) == WMViewSizeDidChangeNotification) {
99                 if (object == WMWidgetView(panel->win)) {
100                         int h = WMWidgetHeight(panel->win);
101                         int w = WMWidgetWidth(panel->win);
102
103                         WMResizeWidget(panel->split, w, h - BUTTON_SPACE_HEIGHT);
104
105                         WMMoveWidget(panel->setB, w - 80, h - (BUTTON_SPACE_HEIGHT - 5));
106
107                         WMMoveWidget(panel->revertB, w - 240, h - (BUTTON_SPACE_HEIGHT - 5));
108
109                 } else if (object == WMWidgetView(panel->upperF)) {
110
111                         if (WMWidgetHeight(panel->upperF) < MIN_UPPER_HEIGHT) {
112                                 WMResizeWidget(panel->upperF, WMWidgetWidth(panel->upperF), MIN_UPPER_HEIGHT);
113                         } else {
114                                 WMResizeWidget(panel->sampleT, WMWidgetWidth(panel->upperF) - 20,
115                                                WMWidgetHeight(panel->upperF) - 10);
116                         }
117
118                 } else if (object == WMWidgetView(panel->lowerF)) {
119
120                         if (WMWidgetHeight(panel->lowerF) < MIN_LOWER_HEIGHT) {
121                                 WMResizeWidget(panel->upperF, WMWidgetWidth(panel->upperF), MIN_UPPER_HEIGHT);
122
123                                 WMMoveWidget(panel->lowerF, 0, WMWidgetHeight(panel->upperF)
124                                              + WMGetSplitViewDividerThickness(panel->split));
125
126                                 WMResizeWidget(panel->lowerF, WMWidgetWidth(panel->lowerF),
127                                                WMWidgetWidth(panel->split) - MIN_UPPER_HEIGHT
128                                                - WMGetSplitViewDividerThickness(panel->split));
129                         } else {
130                                 arrangeLowerFrame(panel);
131                         }
132                 }
133         }
134 }
135
136 static void closeWindow(WMWidget * w, void *data)
137 {
138         FontPanel *panel = (FontPanel *) data;
139
140         WMHideFontPanel(panel);
141 }
142
143 static void setClickedAction(WMWidget * w, void *data)
144 {
145         FontPanel *panel = (FontPanel *) data;
146
147         if (panel->action)
148                 (*panel->action) (panel, panel->data);
149 }
150
151 static void revertClickedAction(WMWidget * w, void *data)
152 {
153         /*FontPanel *panel = (FontPanel*)data; */
154         /* XXX TODO */
155 }
156
157 WMFontPanel *WMGetFontPanel(WMScreen * scr)
158 {
159         FontPanel *panel;
160         WMColor *dark, *white;
161         WMFont *font;
162         int divThickness;
163
164         if (scr->sharedFontPanel)
165                 return scr->sharedFontPanel;
166
167         panel = wmalloc(sizeof(FontPanel));
168         memset(panel, 0, sizeof(FontPanel));
169
170         panel->win = WMCreateWindow(scr, "fontPanel");
171         /*    WMSetWidgetBackgroundColor(panel->win, WMWhiteColor(scr)); */
172         WMSetWindowTitle(panel->win, _("Font Panel"));
173         WMResizeWidget(panel->win, DEF_WIDTH, DEF_HEIGHT);
174         WMSetWindowMinSize(panel->win, MIN_WIDTH, MIN_HEIGHT);
175         WMSetViewNotifySizeChanges(WMWidgetView(panel->win), True);
176
177         WMSetWindowCloseAction(panel->win, closeWindow, panel);
178
179         panel->split = WMCreateSplitView(panel->win);
180         WMResizeWidget(panel->split, DEF_WIDTH, DEF_HEIGHT - BUTTON_SPACE_HEIGHT);
181         WMSetSplitViewConstrainProc(panel->split, splitViewConstrainCallback);
182
183         divThickness = WMGetSplitViewDividerThickness(panel->split);
184
185         panel->upperF = WMCreateFrame(panel->win);
186         WMSetFrameRelief(panel->upperF, WRFlat);
187         WMSetViewNotifySizeChanges(WMWidgetView(panel->upperF), True);
188         panel->lowerF = WMCreateFrame(panel->win);
189         /*    WMSetWidgetBackgroundColor(panel->lowerF, WMBlackColor(scr)); */
190         WMSetFrameRelief(panel->lowerF, WRFlat);
191         WMSetViewNotifySizeChanges(WMWidgetView(panel->lowerF), True);
192
193         WMAddSplitViewSubview(panel->split, W_VIEW(panel->upperF));
194         WMAddSplitViewSubview(panel->split, W_VIEW(panel->lowerF));
195
196         WMResizeWidget(panel->upperF, DEF_WIDTH, DEF_UPPER_HEIGHT);
197
198         WMResizeWidget(panel->lowerF, DEF_WIDTH, DEF_LOWER_HEIGHT);
199
200         WMMoveWidget(panel->lowerF, 0, 60 + divThickness);
201
202         white = WMWhiteColor(scr);
203         dark = WMDarkGrayColor(scr);
204
205         panel->sampleT = WMCreateTextField(panel->upperF);
206         WMResizeWidget(panel->sampleT, DEF_WIDTH - 20, 50);
207         WMMoveWidget(panel->sampleT, 10, 10);
208         WMSetTextFieldText(panel->sampleT, _("The quick brown fox jumps over the lazy dog"));
209
210         font = WMBoldSystemFontOfSize(scr, 12);
211
212         panel->famL = WMCreateLabel(panel->lowerF);
213         WMSetWidgetBackgroundColor(panel->famL, dark);
214         WMSetLabelText(panel->famL, _("Family"));
215         WMSetLabelFont(panel->famL, font);
216         WMSetLabelTextColor(panel->famL, white);
217         WMSetLabelRelief(panel->famL, WRSunken);
218         WMSetLabelTextAlignment(panel->famL, WACenter);
219
220         panel->famLs = WMCreateList(panel->lowerF);
221         WMSetListAction(panel->famLs, familyClick, panel);
222
223         panel->typL = WMCreateLabel(panel->lowerF);
224         WMSetWidgetBackgroundColor(panel->typL, dark);
225         WMSetLabelText(panel->typL, _("Typeface"));
226         WMSetLabelFont(panel->typL, font);
227         WMSetLabelTextColor(panel->typL, white);
228         WMSetLabelRelief(panel->typL, WRSunken);
229         WMSetLabelTextAlignment(panel->typL, WACenter);
230
231         panel->typLs = WMCreateList(panel->lowerF);
232         WMSetListAction(panel->typLs, typefaceClick, panel);
233
234         panel->sizL = WMCreateLabel(panel->lowerF);
235         WMSetWidgetBackgroundColor(panel->sizL, dark);
236         WMSetLabelText(panel->sizL, _("Size"));
237         WMSetLabelFont(panel->sizL, font);
238         WMSetLabelTextColor(panel->sizL, white);
239         WMSetLabelRelief(panel->sizL, WRSunken);
240         WMSetLabelTextAlignment(panel->sizL, WACenter);
241
242         panel->sizT = WMCreateTextField(panel->lowerF);
243         /*    WMSetTextFieldAlignment(panel->sizT, WARight); */
244
245         panel->sizLs = WMCreateList(panel->lowerF);
246         WMSetListAction(panel->sizLs, sizeClick, panel);
247
248         WMReleaseFont(font);
249         WMReleaseColor(white);
250         WMReleaseColor(dark);
251
252         panel->setB = WMCreateCommandButton(panel->win);
253         WMResizeWidget(panel->setB, 70, 24);
254         WMMoveWidget(panel->setB, 240, DEF_HEIGHT - (BUTTON_SPACE_HEIGHT - 5));
255         WMSetButtonText(panel->setB, _("Set"));
256         WMSetButtonAction(panel->setB, setClickedAction, panel);
257
258         panel->revertB = WMCreateCommandButton(panel->win);
259         WMResizeWidget(panel->revertB, 70, 24);
260         WMMoveWidget(panel->revertB, 80, DEF_HEIGHT - (BUTTON_SPACE_HEIGHT - 5));
261         WMSetButtonText(panel->revertB, _("Revert"));
262         WMSetButtonAction(panel->revertB, revertClickedAction, panel);
263
264         WMRealizeWidget(panel->win);
265
266         WMMapSubwidgets(panel->upperF);
267         WMMapSubwidgets(panel->lowerF);
268         WMMapSubwidgets(panel->split);
269         WMMapSubwidgets(panel->win);
270
271         WMUnmapWidget(panel->revertB);
272
273         arrangeLowerFrame(panel);
274
275         scr->sharedFontPanel = panel;
276
277         /* register notification observers */
278         WMAddNotificationObserver(notificationObserver, panel,
279                                   WMViewSizeDidChangeNotification, WMWidgetView(panel->win));
280         WMAddNotificationObserver(notificationObserver, panel,
281                                   WMViewSizeDidChangeNotification, WMWidgetView(panel->upperF));
282         WMAddNotificationObserver(notificationObserver, panel,
283                                   WMViewSizeDidChangeNotification, WMWidgetView(panel->lowerF));
284
285         listFamilies(scr, panel);
286
287         return panel;
288 }
289
290 void WMFreeFontPanel(WMFontPanel * panel)
291 {
292         if (panel == WMWidgetScreen(panel->win)->sharedFontPanel) {
293                 WMWidgetScreen(panel->win)->sharedFontPanel = NULL;
294         }
295         WMRemoveNotificationObserver(panel);
296         WMUnmapWidget(panel->win);
297         WMDestroyWidget(panel->win);
298         wfree(panel);
299 }
300
301 void WMShowFontPanel(WMFontPanel * panel)
302 {
303         WMMapWidget(panel->win);
304 }
305
306 void WMHideFontPanel(WMFontPanel * panel)
307 {
308         WMUnmapWidget(panel->win);
309 }
310
311 WMFont *WMGetFontPanelFont(WMFontPanel * panel)
312 {
313         return WMGetTextFieldFont(panel->sampleT);
314 }
315
316 void WMSetFontPanelFont(WMFontPanel * panel, char *fontName)
317 {
318         int fname_len;
319         FcPattern *pattern;
320         FcChar8 *family, *style;
321         double size;
322
323         if (!isXLFD(fontName, &fname_len)) {
324                 /* maybe its proper fontconfig and we can parse it */
325                 pattern = FcNameParse((FcChar8 *) fontName);
326         } else {
327                 /* maybe its proper xlfd and we can convert it to an FcPattern */
328                 pattern = XftXlfdParse(fontName, False, False);
329                 /*//FcPatternPrint(pattern); */
330         }
331
332         if (!pattern)
333                 return;
334
335         if (FcPatternGetString(pattern, FC_FAMILY, 0, &family) == FcResultMatch)
336                 if (FcPatternGetString(pattern, FC_STYLE, 0, &style) == FcResultMatch)
337                         if (FcPatternGetDouble(pattern, "pixelsize", 0, &size) == FcResultMatch)
338                                 setFontPanelFontName(panel, (char *)family, (char *)style, size);
339
340         FcPatternDestroy(pattern);
341 }
342
343 void WMSetFontPanelAction(WMFontPanel * panel, WMAction2 * action, void *data)
344 {
345         panel->action = action;
346         panel->data = data;
347 }
348
349 static void arrangeLowerFrame(FontPanel * panel)
350 {
351         int width = WMWidgetWidth(panel->lowerF) - 55 - 30;
352         int height = WMWidgetHeight(panel->split) - WMWidgetHeight(panel->upperF);
353         int fw, tw, sw;
354
355 #define LABEL_HEIGHT 20
356
357         height -= WMGetSplitViewDividerThickness(panel->split);
358
359         height -= LABEL_HEIGHT + 8;
360
361         fw = (125 * width) / 235;
362         tw = (110 * width) / 235;
363         sw = 55;
364
365         WMMoveWidget(panel->famL, 10, 0);
366         WMResizeWidget(panel->famL, fw, LABEL_HEIGHT);
367
368         WMMoveWidget(panel->famLs, 10, 23);
369         WMResizeWidget(panel->famLs, fw, height);
370
371         WMMoveWidget(panel->typL, 10 + fw + 3, 0);
372         WMResizeWidget(panel->typL, tw, LABEL_HEIGHT);
373
374         WMMoveWidget(panel->typLs, 10 + fw + 3, 23);
375         WMResizeWidget(panel->typLs, tw, height);
376
377         WMMoveWidget(panel->sizL, 10 + fw + 3 + tw + 3, 0);
378         WMResizeWidget(panel->sizL, sw + 4, LABEL_HEIGHT);
379
380         WMMoveWidget(panel->sizT, 10 + fw + 3 + tw + 3, 23);
381         WMResizeWidget(panel->sizT, sw + 4, 20);
382
383         WMMoveWidget(panel->sizLs, 10 + fw + 3 + tw + 3, 46);
384         WMResizeWidget(panel->sizLs, sw + 4, height - 23);
385 }
386
387 #define NUM_FIELDS 14
388
389 static int isXLFD(char *font, int *length_ret)
390 {
391         int c = 0;
392
393         *length_ret = 0;
394         while (*font) {
395                 (*length_ret)++;
396                 if (*font++ == '-')
397                         c++;
398         }
399
400         return c == NUM_FIELDS;
401 }
402
403 typedef struct {
404         char *typeface;
405         WMArray *sizes;
406 } Typeface;
407
408 typedef struct {
409         char *name;             /* gotta love simplicity */
410         WMArray *typefaces;
411 } Family;
412
413 static int compare_int(const void *a, const void *b)
414 {
415         int i1 = *(int *)a;
416         int i2 = *(int *)b;
417
418         if (i1 < i2)
419                 return -1;
420         else if (i1 > i2)
421                 return 1;
422         else
423                 return 0;
424 }
425
426 static void addSizeToTypeface(Typeface * face, int size)
427 {
428         if (size == 0) {
429                 int j;
430
431                 for (j = 0; j < sizeof(scalableFontSizes) / sizeof(int); j++) {
432                         size = scalableFontSizes[j];
433
434                         if (!WMCountInArray(face->sizes, (void *)(uintptr_t) size)) {
435                                 WMAddToArray(face->sizes, (void *)(uintptr_t) size);
436                         }
437                 }
438                 WMSortArray(face->sizes, compare_int);
439         } else {
440                 if (!WMCountInArray(face->sizes, (void *)(uintptr_t) size)) {
441                         WMAddToArray(face->sizes, (void *)(uintptr_t) size);
442                         WMSortArray(face->sizes, compare_int);
443                 }
444         }
445 }
446
447 static void addTypefaceToXftFamily(Family * fam, char *style)
448 {
449         Typeface *face;
450         WMArrayIterator i;
451
452         if (fam->typefaces) {
453                 WM_ITERATE_ARRAY(fam->typefaces, face, i) {
454                         if (strcmp(face->typeface, style) != 0)
455                                 continue;       /* go to next interation */
456                         addSizeToTypeface(face, 0);
457                         return;
458                 }
459         } else {
460                 fam->typefaces = WMCreateArray(4);
461         }
462
463         face = wmalloc(sizeof(Typeface));
464         memset(face, 0, sizeof(Typeface));
465
466         face->typeface = wstrdup(style);
467         face->sizes = WMCreateArray(4);
468         addSizeToTypeface(face, 0);
469
470         WMAddToArray(fam->typefaces, face);
471 }
472
473 /*
474  * families (same family name) (Hashtable of family -> array)
475  *      registries (same family but different registries)
476  *
477  */
478 static void addFontToXftFamily(WMHashTable * families, char *name, char *style)
479 {
480         WMArrayIterator i;
481         WMArray *array;
482         Family *fam;
483
484         array = WMHashGet(families, name);
485         if (array) {
486                 WM_ITERATE_ARRAY(array, fam, i) {
487                         if (strcmp(fam->name, name) == 0)
488                                 addTypefaceToXftFamily(fam, style);
489                         return;
490                 }
491         }
492
493         array = WMCreateArray(8);
494
495         fam = wmalloc(sizeof(Family));
496         memset(fam, 0, sizeof(Family));
497
498         fam->name = wstrdup(name);
499
500         addTypefaceToXftFamily(fam, style);
501
502         WMAddToArray(array, fam);
503
504         WMHashInsert(families, fam->name, array);
505 }
506
507 static void listFamilies(WMScreen * scr, WMFontPanel * panel)
508 {
509         FcObjectSet *os = 0;
510         FcFontSet *fs;
511         FcPattern *pat;
512         WMHashTable *families;
513         WMHashEnumerator enumer;
514         WMArray *array;
515         int i;
516
517         pat = FcPatternCreate();
518         os = FcObjectSetBuild(FC_FAMILY, FC_STYLE, NULL);
519         fs = FcFontList(0, pat, os);
520         if (!fs) {
521                 WMRunAlertPanel(scr, panel->win, _("Error"),
522                                 _("Could not init font config library\n"), _("OK"), NULL, NULL);
523                 return;
524         }
525         if (pat)
526                 FcPatternDestroy(pat);
527
528         families = WMCreateHashTable(WMStringPointerHashCallbacks);
529
530         if (fs) {
531                 for (i = 0; i < fs->nfont; i++) {
532                         FcChar8 *family;
533                         FcChar8 *style;
534
535                         if (FcPatternGetString(fs->fonts[i], FC_FAMILY, 0, &family) == FcResultMatch)
536                                 if (FcPatternGetString(fs->fonts[i], FC_STYLE, 0, &style) == FcResultMatch)
537                                         addFontToXftFamily(families, (char *)family, (char *)style);
538                 }
539                 FcFontSetDestroy(fs);
540         }
541
542         enumer = WMEnumerateHashTable(families);
543
544         while ((array = WMNextHashEnumeratorItem(&enumer))) {
545                 WMArrayIterator i;
546                 Family *fam;
547                 char buffer[256];
548                 WMListItem *item;
549
550                 WM_ITERATE_ARRAY(array, fam, i) {
551                         strcpy(buffer, fam->name);
552                         item = WMAddListItem(panel->famLs, buffer);
553
554                         item->clientData = fam;
555                 }
556
557                 WMFreeArray(array);
558         }
559
560         WMSortListItems(panel->famLs);
561
562         WMFreeHashTable(families);
563 }
564
565 static void getSelectedFont(FontPanel * panel, char buffer[], int bufsize)
566 {
567         WMListItem *item;
568         Family *family;
569         Typeface *face;
570         char *size;
571
572         item = WMGetListSelectedItem(panel->famLs);
573         if (!item)
574                 return;
575         family = (Family *) item->clientData;
576
577         item = WMGetListSelectedItem(panel->typLs);
578         if (!item)
579                 return;
580         face = (Typeface *) item->clientData;
581
582         size = WMGetTextFieldText(panel->sizT);
583
584         snprintf(buffer, bufsize, "%s:style=%s:pixelsize=%s", family->name, face->typeface, size);
585
586         wfree(size);
587 }
588
589 static void preview(FontPanel * panel)
590 {
591         char buffer[512];
592         WMFont *font;
593
594         getSelectedFont(panel, buffer, sizeof(buffer));
595         font = WMCreateFont(WMWidgetScreen(panel->win), buffer);
596         if (font) {
597                 WMSetTextFieldFont(panel->sampleT, font);
598                 WMReleaseFont(font);
599         }
600 }
601
602 static void familyClick(WMWidget * w, void *data)
603 {
604         WMList *lPtr = (WMList *) w;
605         WMListItem *item;
606         Family *family;
607         Typeface *face;
608         FontPanel *panel = (FontPanel *) data;
609         WMArrayIterator i;
610         /* current typeface and size */
611         char *oface = NULL;
612         char *osize = NULL;
613         int facei = -1;
614         int sizei = -1;
615
616         /* must try to keep the same typeface and size for the new family */
617         item = WMGetListSelectedItem(panel->typLs);
618         if (item)
619                 oface = wstrdup(item->text);
620
621         osize = WMGetTextFieldText(panel->sizT);
622
623         item = WMGetListSelectedItem(lPtr);
624         family = (Family *) item->clientData;
625
626         WMClearList(panel->typLs);
627
628         WM_ITERATE_ARRAY(family->typefaces, face, i) {
629                 char buffer[256];
630                 int top = 0;
631                 WMListItem *fitem;
632
633                 strcpy(buffer, face->typeface);
634                 if (strcasecmp(face->typeface, "Roman") == 0)
635                         top = 1;
636                 if (strcasecmp(face->typeface, "Regular") == 0)
637                         top = 1;
638                 if (top)
639                         fitem = WMInsertListItem(panel->typLs, 0, buffer);
640                 else
641                         fitem = WMAddListItem(panel->typLs, buffer);
642                 fitem->clientData = face;
643         }
644
645         if (oface) {
646                 facei = WMFindRowOfListItemWithTitle(panel->typLs, oface);
647                 wfree(oface);
648         }
649         if (facei < 0) {
650                 facei = 0;
651         }
652         WMSelectListItem(panel->typLs, facei);
653         typefaceClick(panel->typLs, panel);
654
655         if (osize) {
656                 sizei = WMFindRowOfListItemWithTitle(panel->sizLs, osize);
657         }
658         if (sizei >= 0) {
659                 WMSelectListItem(panel->sizLs, sizei);
660                 sizeClick(panel->sizLs, panel);
661         }
662
663         if (osize)
664                 wfree(osize);
665
666         preview(panel);
667 }
668
669 static void typefaceClick(WMWidget * w, void *data)
670 {
671         FontPanel *panel = (FontPanel *) data;
672         WMListItem *item;
673         Typeface *face;
674         WMArrayIterator i;
675         char buffer[32];
676
677         char *osize = NULL;
678         int sizei = -1;
679         void *size;
680
681         osize = WMGetTextFieldText(panel->sizT);
682
683         item = WMGetListSelectedItem(panel->typLs);
684         face = (Typeface *) item->clientData;
685
686         WMClearList(panel->sizLs);
687
688         WM_ITERATE_ARRAY(face->sizes, size, i) {
689                 if ((int)(uintptr_t) size != 0) {
690                         sprintf(buffer, "%i", (int)(uintptr_t) size);
691
692                         WMAddListItem(panel->sizLs, buffer);
693                 }
694         }
695
696         if (osize) {
697                 sizei = WMFindRowOfListItemWithTitle(panel->sizLs, osize);
698         }
699         if (sizei < 0) {
700                 sizei = WMFindRowOfListItemWithTitle(panel->sizLs, "12");
701         }
702         if (sizei < 0) {
703                 sizei = 0;
704         }
705         WMSelectListItem(panel->sizLs, sizei);
706         WMSetListPosition(panel->sizLs, sizei);
707         sizeClick(panel->sizLs, panel);
708
709         if (osize)
710                 wfree(osize);
711
712         preview(panel);
713 }
714
715 static void sizeClick(WMWidget * w, void *data)
716 {
717         FontPanel *panel = (FontPanel *) data;
718         WMListItem *item;
719
720         item = WMGetListSelectedItem(panel->sizLs);
721         WMSetTextFieldText(panel->sizT, item->text);
722
723         WMSelectTextFieldRange(panel->sizT, wmkrange(0, strlen(item->text)));
724
725         preview(panel);
726 }
727
728 static void setFontPanelFontName(FontPanel * panel, char *family, char *style, double size)
729 {
730         int famrow;
731         int stlrow;
732         int sz;
733         char asize[64];
734         void *vsize;
735         WMListItem *item;
736         Family *fam;
737         Typeface *face;
738         WMArrayIterator i;
739
740         famrow = WMFindRowOfListItemWithTitle(panel->famLs, family);
741         if (famrow < 0) {
742                 famrow = 0;
743                 return;
744         }
745         WMSelectListItem(panel->famLs, famrow);
746         WMSetListPosition(panel->famLs, famrow);
747
748         WMClearList(panel->typLs);
749
750         item = WMGetListSelectedItem(panel->famLs);
751
752         fam = (Family *) item->clientData;
753         WM_ITERATE_ARRAY(fam->typefaces, face, i) {
754                 char buffer[256];
755                 int top = 0;
756                 WMListItem *fitem;
757
758                 strcpy(buffer, face->typeface);
759                 if (strcasecmp(face->typeface, "Roman") == 0)
760                         top = 1;
761                 if (top)
762                         fitem = WMInsertListItem(panel->typLs, 0, buffer);
763                 else
764                         fitem = WMAddListItem(panel->typLs, buffer);
765                 fitem->clientData = face;
766         }
767
768         stlrow = WMFindRowOfListItemWithTitle(panel->typLs, style);
769
770         if (stlrow < 0) {
771                 stlrow = 0;
772                 return;
773         }
774
775         WMSelectListItem(panel->typLs, stlrow);
776
777         item = WMGetListSelectedItem(panel->typLs);
778
779         face = (Typeface *) item->clientData;
780
781         WMClearList(panel->sizLs);
782
783         WM_ITERATE_ARRAY(face->sizes, vsize, i) {
784                 char buffer[32];
785                 if ((int)(uintptr_t) vsize != 0) {
786                         sprintf(buffer, "%i", (int)(uintptr_t) vsize);
787
788                         WMAddListItem(panel->sizLs, buffer);
789                 }
790         }
791
792         snprintf(asize, sizeof(asize) - 1, "%d", (int)(size + 0.5));
793
794         sz = WMFindRowOfListItemWithTitle(panel->sizLs, asize);
795
796         if (sz < 0) {
797                 sz = 4;
798                 return;
799         }
800
801         WMSelectListItem(panel->sizLs, sz);
802         sizeClick(panel->sizLs, panel);
803
804         return;
805 }