1
/* FontSimple.c- simplified font configuration panel
3
* WPrefs - Window Maker Preferences Program
5
* Copyright (c) 1998-2004 Alfredo K. Kojima
7
* This program is free software; you can redistribute it and/or modify
8
* it under the terms of the GNU General Public License as published by
9
* the Free Software Foundation; either version 2 of the License, or
10
* (at your option) any later version.
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
17
* You should have received a copy of the GNU General Public License
18
* along with this program; if not, write to the Free Software
19
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
26
#include <fontconfig/fontconfig.h>
29
/* workaround for older fontconfig, that doesn't define these constants */
30
#ifndef FC_WEIGHT_NORMAL
32
# define FC_WEIGHT_THIN 10
33
# define FC_WEIGHT_EXTRALIGHT 40
34
# define FC_WEIGHT_ULTRALIGHT FC_WEIGHT_EXTRALIGHT
35
# define FC_WEIGHT_REGULAR 80
36
# define FC_WEIGHT_NORMAL FC_WEIGHT_REGULAR
37
# define FC_WEIGHT_SEMIBOLD FC_WEIGHT_DEMIBOLD
38
# define FC_WEIGHT_EXTRABOLD 205
39
# define FC_WEIGHT_ULTRABOLD FC_WEIGHT_EXTRABOLD
40
# define FC_WEIGHT_HEAVY FC_WEIGHT_BLACK
42
# define FC_WIDTH_ULTRACONDENSED 50
43
# define FC_WIDTH_EXTRACONDENSED 63
44
# define FC_WIDTH_CONDENSED 75
45
# define FC_WIDTH_SEMICONDENSED 87
46
# define FC_WIDTH_NORMAL 100
47
# define FC_WIDTH_SEMIEXPANDED 113
48
# define FC_WIDTH_EXPANDED 125
49
# define FC_WIDTH_EXTRAEXPANDED 150
50
# define FC_WIDTH_ULTRAEXPANDED 200
54
#define SAMPLE_TEXT "The Lazy Fox Jumped Ipsum Foobar 1234 - 56789"
76
typedef struct _Panel {
82
CallbackRec callbacks;
86
WMPopUpButton *optionP;
99
#define ICON_FILE "fonts"
106
{"WindowTitleFont", N_("Window Title")},
107
{"MenuTitleFont", N_("Menu Title")},
108
{"MenuTextFont", N_("Menu Text")},
109
{"IconTitleFont", N_("Icon Title")},
110
{"ClipTitleFont", N_("Clip Title")},
111
{"LargeDisplayFont", N_("Desktop Caption")},
116
static char *standardSizes[]= {
145
{FC_WEIGHT_THIN, "Thin"},
146
{FC_WEIGHT_EXTRALIGHT, "ExtraLight"},
147
{FC_WEIGHT_LIGHT, "Light"},
148
{FC_WEIGHT_NORMAL, "Normal"},
149
{FC_WEIGHT_MEDIUM, ""}, /*"medium"},*/
150
{FC_WEIGHT_DEMIBOLD, "DemiBold"},
151
{FC_WEIGHT_BOLD, "Bold"},
152
{FC_WEIGHT_EXTRABOLD, "ExtraBold"},
153
{FC_WEIGHT_BLACK, "Black"},
161
{FC_SLANT_ROMAN, ""}, /*"Roman"},*/
162
{FC_SLANT_ITALIC, "Italic"},
163
{FC_SLANT_OBLIQUE, "Oblique"},
171
{FC_WIDTH_ULTRACONDENSED, "UltraCondensed"},
172
{FC_WIDTH_EXTRACONDENSED, "ExtraCondensed"},
173
{FC_WIDTH_CONDENSED, "Condensed"},
174
{FC_WIDTH_SEMICONDENSED, "SemiCondensed"},
175
{FC_WIDTH_NORMAL, ""}, /*"normal"},*/
176
{FC_WIDTH_SEMIEXPANDED, "SemiExpanded"},
177
{FC_WIDTH_EXPANDED, "Expanded"},
178
{FC_WIDTH_EXTRAEXPANDED, "ExtraExpanded"},
179
{FC_WIDTH_ULTRAEXPANDED, "UltraExpanded"},
187
static int compare_family(const void *a, const void *b)
189
FontFamily *fa= (FontFamily*)a;
190
FontFamily *fb= (FontFamily*)b;
191
return strcmp(fa->name, fb->name);
195
static int compare_styles(const void *a, const void *b)
197
FontStyle *sa= (FontStyle*)a;
198
FontStyle *sb= (FontStyle*)b;
201
compare = sa->weight - sb->weight;
204
compare = sa->slant - sb->slant;
207
return (sa->width - sb->width);
212
lookup_available_fonts(_Panel *panel)
214
FcPattern *pat = FcPatternCreate();
219
os = FcObjectSetBuild(FC_FAMILY, FC_WEIGHT, FC_WIDTH, FC_SLANT, NULL);
221
fonts = FcFontList(0, pat, os);
227
panel->fonts= wmalloc(sizeof(FontList));
228
panel->fonts->familyn= 0;
229
panel->fonts->families= wmalloc(sizeof(FontFamily)*fonts->nfont);
231
for (i= 0; i < fonts->nfont; i++)
234
int weight, slant, width;
237
if (FcPatternGetString(fonts->fonts[i], FC_FAMILY, 0, &name) != FcResultMatch)
240
if (FcPatternGetInteger(fonts->fonts[i], FC_WEIGHT, 0, &weight) != FcResultMatch)
241
weight= FC_WEIGHT_MEDIUM;
243
if (FcPatternGetInteger(fonts->fonts[i], FC_WIDTH, 0, &width) != FcResultMatch)
244
width= FC_WIDTH_NORMAL;
246
if (FcPatternGetInteger(fonts->fonts[i], FC_SLANT, 0, &slant) != FcResultMatch)
247
slant= FC_SLANT_ROMAN;
250
for (j = 0; j < panel->fonts->familyn && found<0; j++)
251
if (strcasecmp(panel->fonts->families[j].name, name)==0)
256
panel->fonts->families[panel->fonts->familyn++].name= wstrdup(name);
257
family= panel->fonts->families + panel->fonts->familyn-1;
259
family->styles= NULL;
262
family= panel->fonts->families+found;
265
family->styles= wrealloc(family->styles, sizeof(FontStyle)*family->stylen);
266
family->styles[family->stylen-1].weight= weight;
267
family->styles[family->stylen-1].slant= slant;
268
family->styles[family->stylen-1].width= width;
270
qsort(panel->fonts->families, panel->fonts->familyn, sizeof(FontFamily),
273
for (i=0; i < panel->fonts->familyn; i++)
275
qsort(panel->fonts->families[i].styles, panel->fonts->families[i].stylen,
276
sizeof(FontStyle), compare_styles);
279
FcFontSetDestroy(fonts);
282
FcObjectSetDestroy(os);
284
FcPatternDestroy(pat);
286
panel->fonts->families[panel->fonts->familyn++].name= wstrdup("sans serif");
287
family= panel->fonts->families + panel->fonts->familyn-1;
288
family->styles= wmalloc(sizeof(FontStyle)*2);
290
family->styles[0].weight= FC_WEIGHT_MEDIUM;
291
family->styles[0].slant= FC_SLANT_ROMAN;
292
family->styles[0].width= FC_WIDTH_NORMAL;
293
family->styles[1].weight= FC_WEIGHT_BOLD;
294
family->styles[1].slant= FC_SLANT_ROMAN;
295
family->styles[1].width= FC_WIDTH_NORMAL;
297
panel->fonts->families[panel->fonts->familyn++].name= wstrdup("serif");
298
family= panel->fonts->families + panel->fonts->familyn-1;
299
family->styles= wmalloc(sizeof(FontStyle)*2);
301
family->styles[0].weight= FC_WEIGHT_MEDIUM;
302
family->styles[0].slant= FC_SLANT_ROMAN;
303
family->styles[0].width= FC_WIDTH_NORMAL;
304
family->styles[1].weight= FC_WEIGHT_BOLD;
305
family->styles[1].slant= FC_SLANT_ROMAN;
306
family->styles[1].width= FC_WIDTH_NORMAL;
311
getSelectedFont(_Panel *panel, char *curfont)
314
FcPattern *pat= FcNameParse(curfont);
317
item= WMGetListSelectedItem(panel->familyL);
320
FcPatternDel(pat, FC_FAMILY);
321
FcPatternAddString(pat, FC_FAMILY, item->text);
324
item= WMGetListSelectedItem(panel->styleL);
327
FontStyle *style= (FontStyle*)item->clientData;
329
FcPatternDel(pat, FC_WEIGHT);
330
FcPatternAddInteger(pat, FC_WEIGHT, style->weight);
332
FcPatternDel(pat, FC_WIDTH);
333
FcPatternAddInteger(pat, FC_WIDTH, style->width);
335
FcPatternDel(pat, FC_SLANT);
336
FcPatternAddInteger(pat, FC_SLANT, style->slant);
339
item= WMGetListSelectedItem(panel->sizeL);
342
FcPatternDel(pat, FC_PIXEL_SIZE);
343
FcPatternAddDouble(pat, FC_PIXEL_SIZE, atoi(item->text));
346
name= FcNameUnparse(pat);
347
FcPatternDestroy(pat);
355
updateSampleFont(_Panel *panel)
357
WMMenuItem *item= WMGetPopUpButtonMenuItem(panel->optionP,
358
WMGetPopUpButtonSelectedItem(panel->optionP));
359
char *fn= WMGetMenuItemRepresentedObject(item);
360
WMFont *font= WMCreateFont(WMWidgetScreen(panel->box), fn);
364
WMSetTextFieldFont(panel->sampleT, font);
373
selectedFamily(WMWidget *w, void *data)
375
_Panel *panel= (_Panel*)data;
377
FontStyle *oldStyle= NULL;
380
item= WMGetListSelectedItem(panel->styleL);
382
oldStyle= (FontStyle*)item->clientData;
384
item= WMGetListSelectedItem(panel->familyL);
388
FontFamily *family= (FontFamily*)item->clientData;
389
int i, oldi= 0, oldscore= 0;
391
WMClearList(panel->styleL);
392
for (i = 0; i < family->stylen; i++)
395
char *weight= "", *slant= "", *width= "";
398
for (j= 0; fontWeights[j].name; j++)
399
if (fontWeights[j].weight == family->styles[i].weight)
401
weight= fontWeights[j].name;
404
for (j= 0; fontWidths[j].name; j++)
405
if (fontWidths[j].width == family->styles[i].width)
407
width= fontWidths[j].name;
410
for (j= 0; fontSlants[j].name; j++)
411
if (fontSlants[j].slant == family->styles[i].slant)
413
slant= fontSlants[j].name;
416
sprintf(buffer, "%s%s%s%s%s",
417
weight, *weight?" ":"",
418
slant, (*slant || *weight)?" ":"",
421
strcpy(buffer, "Roman");
423
item= WMAddListItem(panel->styleL, buffer);
424
item->clientData= family->styles+i;
429
if (oldStyle->width == family->styles[i].width)
431
if (oldStyle->weight == family->styles[i].weight)
433
if (oldStyle->slant == family->styles[i].slant)
436
if (score > oldscore)
443
WMSelectListItem(panel->styleL, oldi);
446
int index= WMGetPopUpButtonSelectedItem(panel->optionP);
447
WMMenuItem *item= WMGetPopUpButtonMenuItem(panel->optionP, index);
450
ofont= (char*)WMGetMenuItemRepresentedObject(item);
452
nfont= getSelectedFont(panel, ofont);
454
WMSetMenuItemRepresentedObject(item, nfont);
456
updateSampleFont(panel);
462
selected(WMWidget *w, void *data)
464
_Panel *panel= (_Panel*)data;
465
int index= WMGetPopUpButtonSelectedItem(panel->optionP);
466
WMMenuItem *item= WMGetPopUpButtonMenuItem(panel->optionP, index);
469
ofont= (char*)WMGetMenuItemRepresentedObject(item);
471
nfont= getSelectedFont(panel, ofont);
473
WMSetMenuItemRepresentedObject(item, nfont);
475
updateSampleFont(panel);
480
selectedOption(WMWidget *w, void *data)
482
_Panel *panel= (_Panel*)data;
483
int index = WMGetPopUpButtonSelectedItem(panel->optionP);
484
WMMenuItem *item= WMGetPopUpButtonMenuItem(panel->optionP, index);
487
font= (char*)WMGetMenuItemRepresentedObject(item);
492
pat= FcNameParse(font);
496
int weight, slant, width;
498
int distance, closest, found;
501
FcDefaultSubstitute(pat);
503
if (FcPatternGetString(pat, FC_FAMILY, 0, &name) != FcResultMatch)
508
for (i= 0; i < WMGetListNumberOfRows(panel->familyL); i++)
510
WMListItem *item= WMGetListItem(panel->familyL, i);
511
FontFamily *family= (FontFamily*)item->clientData;
513
if (strcasecmp(family->name, name)==0)
516
WMSelectListItem(panel->familyL, i);
517
WMSetListPosition(panel->familyL, i);
522
WMSelectListItem(panel->familyL, -1);
523
selectedFamily(panel->familyL, panel);
526
if (FcPatternGetInteger(pat, FC_WEIGHT, 0, &weight) != FcResultMatch)
527
weight= FC_WEIGHT_NORMAL;
528
if (FcPatternGetInteger(pat, FC_WIDTH, 0, &width) != FcResultMatch)
529
width= FC_WIDTH_NORMAL;
530
if (FcPatternGetInteger(pat, FC_SLANT, 0, &slant) != FcResultMatch)
531
slant= FC_SLANT_ROMAN;
533
if (FcPatternGetDouble(pat, FC_PIXEL_SIZE, 0, &size) != FcResultMatch)
536
for (i=0, found=0, closest=0; i < WMGetListNumberOfRows(panel->styleL); i++)
538
WMListItem *item= WMGetListItem(panel->styleL, i);
539
FontStyle *style= (FontStyle*)item->clientData;
541
distance = ((abs(style->weight - weight) << 16) +
542
(abs(style->slant - slant) << 8) +
543
(abs(style->width - width)));
545
if (i==0 || distance < closest) {
549
break; /* perfect match */
553
WMSelectListItem(panel->styleL, found);
554
WMSetListPosition(panel->styleL, found);
556
for (i=0, found=0, closest=0; i < WMGetListNumberOfRows(panel->sizeL); i++)
558
WMListItem *item= WMGetListItem(panel->sizeL, i);
561
distance = abs(size - atoi(item->text));
563
if (i==0 || distance < closest) {
567
break; /* perfect match */
571
WMSelectListItem(panel->sizeL, found);
572
WMSetListPosition(panel->sizeL, found);
574
selected(NULL, panel);
577
wwarning("Can't parse font '%s'", font);
580
updateSampleFont(panel);
585
createListLabel(WMScreen *scr, WMWidget *parent, char *text)
589
WMFont *boldFont= WMBoldSystemFontOfSize(scr, 12);
591
label = WMCreateLabel(parent);
592
WMSetLabelFont(label, boldFont);
593
WMSetLabelText(label, text);
594
WMSetLabelRelief(label, WRSunken);
595
WMSetLabelTextAlignment(label, WACenter);
596
color = WMDarkGrayColor(scr);
597
WMSetWidgetBackgroundColor(label, color);
598
WMReleaseColor(color);
599
color = WMWhiteColor(scr);
600
WMSetLabelTextColor(label, color);
601
WMReleaseColor(color);
603
WMReleaseFont(boldFont);
610
showData(_Panel *panel)
615
for (i= 0; i < WMGetPopUpButtonNumberOfItems(panel->optionP); i++)
619
item= WMGetPopUpButtonMenuItem(panel->optionP, i);
621
ofont= WMGetMenuItemRepresentedObject(item);
625
font= GetStringForKey(fontOptions[i].option);
628
WMSetMenuItemRepresentedObject(item, font);
631
WMSetPopUpButtonSelectedItem(panel->optionP, 0);
632
selectedOption(panel->optionP, panel);
637
storeData(_Panel *panel)
641
for (i= 0; i < WMGetPopUpButtonNumberOfItems(panel->optionP); i++)
645
item= WMGetPopUpButtonMenuItem(panel->optionP, i);
647
font= WMGetMenuItemRepresentedObject(item);
650
SetStringForKey(font, fontOptions[i].option);
657
createPanel(Panel *p)
659
_Panel *panel = (_Panel*)p;
660
WMScreen *scr = WMWidgetScreen(panel->parent);
665
lookup_available_fonts(panel);
667
panel->box = WMCreateBox(panel->parent);
668
WMSetViewExpandsToParent(WMWidgetView(panel->box), 5, 2, 5, 5);
669
WMSetBoxHorizontal(panel->box, False);
670
WMSetBoxBorderWidth(panel->box, 8);
671
WMMapWidget(panel->box);
673
hbox = WMCreateBox(panel->box);
674
WMSetBoxHorizontal(hbox, True);
675
WMAddBoxSubview(panel->box, WMWidgetView(hbox), False, True, 40, 22, 8);
677
vbox= WMCreateBox(hbox);
678
WMAddBoxSubview(hbox, WMWidgetView(vbox), False, True, 130, 0, 10);
679
WMSetBoxHorizontal(vbox, False);
680
panel->optionP = WMCreatePopUpButton(vbox);
681
WMAddBoxSubviewAtEnd(vbox, WMWidgetView(panel->optionP), False, True, 20, 0, 8);
682
for (i= 0; fontOptions[i].option; i++)
684
WMAddPopUpButtonItem(panel->optionP, _(fontOptions[i].label));
686
WMSetPopUpButtonAction(panel->optionP, selectedOption, panel);
688
label = WMCreateLabel(hbox);
689
WMSetLabelText(label, _("Sample Text"));
690
WMSetLabelTextAlignment(label, WARight);
691
WMAddBoxSubview(hbox, WMWidgetView(label), False, True, 80, 0, 2);
693
panel->sampleT= WMCreateTextField(hbox);
694
WMSetViewExpandsToParent(WMWidgetView(panel->sampleT), 10, 18, 10, 10);
695
WMSetTextFieldText(panel->sampleT, SAMPLE_TEXT);
696
WMAddBoxSubview(hbox, WMWidgetView(panel->sampleT), True, True, 60, 0, 0);
699
hbox = WMCreateBox(panel->box);
700
WMSetBoxHorizontal(hbox, True);
701
WMAddBoxSubview(panel->box, WMWidgetView(hbox), True, True, 100, 0, 2);
703
vbox = WMCreateBox(hbox);
704
WMSetBoxHorizontal(vbox, False);
705
WMAddBoxSubview(hbox, WMWidgetView(vbox), False, True, 240, 20, 4);
707
label = createListLabel(scr, vbox, _("Family"));
708
WMAddBoxSubview(vbox, WMWidgetView(label), False, True, 20, 0, 2);
711
panel->familyL = WMCreateList(vbox);
712
WMAddBoxSubview(vbox, WMWidgetView(panel->familyL), True, True, 0, 0, 0);
716
for (i= 0; i < panel->fonts->familyn; i++)
718
item = WMAddListItem(panel->familyL, panel->fonts->families[i].name);
719
item->clientData= panel->fonts->families+i;
723
WMAddListItem(panel->familyL, "sans serif");
725
WMSetListAction(panel->familyL, selectedFamily, panel);
727
vbox = WMCreateBox(hbox);
728
WMSetBoxHorizontal(vbox, False);
729
WMAddBoxSubview(hbox, WMWidgetView(vbox), True, True, 10, 0, 0);
732
WMBox *box = WMCreateBox(vbox);
733
WMSetBoxHorizontal(box, True);
734
WMAddBoxSubview(vbox, WMWidgetView(box), False, True, 20, 0, 2);
736
label = createListLabel(scr, box, _("Style"));
737
WMAddBoxSubview(box, WMWidgetView(label), True, True, 20, 0, 4);
739
label = createListLabel(scr, box, _("Size"));
740
WMAddBoxSubview(box, WMWidgetView(label), False, True, 60, 0, 0);
742
box = WMCreateBox(vbox);
743
WMSetBoxHorizontal(box, True);
744
WMAddBoxSubview(vbox, WMWidgetView(box), True, True, 20, 0, 0);
746
panel->styleL = WMCreateList(box);
747
WMAddBoxSubview(box, WMWidgetView(panel->styleL), True, True, 0, 0, 4);
748
WMSetListAction(panel->styleL, selected, panel);
750
panel->sizeL = WMCreateList(box);
751
WMAddBoxSubview(box, WMWidgetView(panel->sizeL), False, True, 60, 0, 0);
752
for (i= 0; standardSizes[i]; i++)
754
WMAddListItem(panel->sizeL, standardSizes[i]);
756
WMSetListAction(panel->sizeL, selected, panel);
760
WMMapSubwidgets(panel->box);
761
WMMapWidget(panel->box);
762
WMRealizeWidget(panel->box);
770
InitFontSimple(WMScreen *scr, WMWidget *parent)
774
panel = wmalloc(sizeof(_Panel));
775
memset(panel, 0, sizeof(_Panel));
777
panel->sectionName = _("Font Configuration");
779
panel->description = _("Configure fonts for Window Maker titlebars, menus etc.");
781
panel->parent = parent;
783
panel->callbacks.createWidgets = createPanel;
784
panel->callbacks.updateDomain = storeData;
786
AddSection(panel, ICON_FILE);