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>
28 #define SAMPLE_TEXT "The Lazy Fox Jumped Ipsum Foobar 1234 - 56789"
50 typedef struct _Panel
{
56 CallbackRec callbacks
;
60 WMPopUpButton
*optionP
;
73 #define ICON_FILE "fonts"
80 {"WindowTitleFont", N_("Window Title")},
81 {"MenuTitleFont", N_("Menu Title")},
82 {"MenuTextFont", N_("Menu Text")},
83 {"IconTitleFont", N_("Icon Title")},
84 {"ClipTitleFont", N_("Clip Title")},
85 {"LargeDisplayFont", N_("Desktop Caption")},
90 static char *standardSizes
[]= {
119 {FC_WEIGHT_THIN
, "Thin"},
120 {FC_WEIGHT_EXTRALIGHT
, "ExtraLight"},
121 {FC_WEIGHT_LIGHT
, "Light"},
122 {FC_WEIGHT_NORMAL
, "Normal"},
123 {FC_WEIGHT_MEDIUM
, ""}, /*"medium"},*/
124 {FC_WEIGHT_DEMIBOLD
, "DemiBold"},
125 {FC_WEIGHT_BOLD
, "Bold"},
126 {FC_WEIGHT_EXTRABOLD
, "ExtraBold"},
127 {FC_WEIGHT_BLACK
, "Black"},
135 {FC_SLANT_ROMAN
, ""}, /*"Roman"},*/
136 {FC_SLANT_ITALIC
, "Italic"},
137 {FC_SLANT_OBLIQUE
, "Oblique"},
145 {FC_WIDTH_ULTRACONDENSED
, "UltraCondensed"},
146 {FC_WIDTH_EXTRACONDENSED
, "ExtraCondensed"},
147 {FC_WIDTH_CONDENSED
, "Condensed"},
148 {FC_WIDTH_SEMICONDENSED
, "SemiCondensed"},
149 {FC_WIDTH_NORMAL
, ""}, /*"normal"},*/
150 {FC_WIDTH_SEMIEXPANDED
, "SemiExpanded"},
151 {FC_WIDTH_EXPANDED
, "Expanded"},
152 {FC_WIDTH_EXTRAEXPANDED
, "ExtraExpanded"},
153 {FC_WIDTH_ULTRAEXPANDED
, "UltraExpanded"},
161 static int compare_family(const void *a
, const void *b
)
163 FontFamily
*fa
= (FontFamily
*)a
;
164 FontFamily
*fb
= (FontFamily
*)b
;
165 return strcasecmp(fa
->name
, fb
->name
);
170 lookup_available_fonts(_Panel
*panel
)
172 FcPattern
*pat
= FcPatternCreate();
177 os
= FcObjectSetBuild(FC_FAMILY
, FC_WEIGHT
, FC_WIDTH
, FC_SLANT
, NULL
);
179 fonts
= FcFontList(0, pat
, os
);
185 panel
->fonts
= wmalloc(sizeof(FontList
));
186 panel
->fonts
->familyn
= 0;
187 panel
->fonts
->families
= wmalloc(sizeof(FontFamily
)*fonts
->nfont
);
189 for (i
= 0; i
< fonts
->nfont
; i
++)
192 int weight
, slant
, width
;
195 if (FcPatternGetString(fonts
->fonts
[i
], FC_FAMILY
, 0, &name
) != FcResultMatch
)
198 if (FcPatternGetInteger(fonts
->fonts
[i
], FC_WEIGHT
, 0, &weight
) != FcResultMatch
)
199 weight
= FC_WEIGHT_MEDIUM
;
201 if (FcPatternGetInteger(fonts
->fonts
[i
], FC_WIDTH
, 0, &width
) != FcResultMatch
)
202 width
= FC_WIDTH_NORMAL
;
204 if (FcPatternGetInteger(fonts
->fonts
[i
], FC_SLANT
, 0, &slant
) != FcResultMatch
)
205 slant
= FC_SLANT_ROMAN
;
208 for (j
= 0; j
< panel
->fonts
->familyn
&& found
<0; j
++)
209 if (strcasecmp(panel
->fonts
->families
[j
].name
, name
)==0)
214 panel
->fonts
->families
[panel
->fonts
->familyn
++].name
= wstrdup(name
);
215 family
= panel
->fonts
->families
+ panel
->fonts
->familyn
-1;
217 family
->styles
= NULL
;
220 family
= panel
->fonts
->families
+found
;
223 family
->styles
= wrealloc(family
->styles
, sizeof(FontStyle
)*family
->stylen
);
224 family
->styles
[family
->stylen
-1].weight
= weight
;
225 family
->styles
[family
->stylen
-1].slant
= slant
;
226 family
->styles
[family
->stylen
-1].width
= width
;
228 qsort(panel
->fonts
->families
, panel
->fonts
->familyn
, sizeof(FontFamily
),
231 FcFontSetDestroy(fonts
);
234 FcObjectSetDestroy(os
);
236 FcPatternDestroy(pat
);
238 panel
->fonts
->families
[panel
->fonts
->familyn
++].name
= wstrdup("sans");
239 family
= panel
->fonts
->families
+ panel
->fonts
->familyn
-1;
240 family
->styles
= wmalloc(sizeof(FontStyle
)*2);
242 family
->styles
[0].weight
= FC_WEIGHT_MEDIUM
;
243 family
->styles
[0].slant
= FC_SLANT_ROMAN
;
244 family
->styles
[0].width
= FC_WIDTH_NORMAL
;
245 family
->styles
[1].weight
= FC_WEIGHT_BOLD
;
246 family
->styles
[1].slant
= FC_SLANT_ROMAN
;
247 family
->styles
[1].width
= FC_WIDTH_NORMAL
;
249 panel
->fonts
->families
[panel
->fonts
->familyn
++].name
= wstrdup("serif");
250 family
= panel
->fonts
->families
+ panel
->fonts
->familyn
-1;
251 family
->styles
= wmalloc(sizeof(FontStyle
)*2);
253 family
->styles
[0].weight
= FC_WEIGHT_MEDIUM
;
254 family
->styles
[0].slant
= FC_SLANT_ROMAN
;
255 family
->styles
[0].width
= FC_WIDTH_NORMAL
;
256 family
->styles
[1].weight
= FC_WEIGHT_BOLD
;
257 family
->styles
[1].slant
= FC_SLANT_ROMAN
;
258 family
->styles
[1].width
= FC_WIDTH_NORMAL
;
263 getSelectedFont(_Panel
*panel
, char *curfont
)
266 FcPattern
*pat
= FcNameParse(curfont
);
269 item
= WMGetListSelectedItem(panel
->familyL
);
272 FcPatternDel(pat
, FC_FAMILY
);
273 FcPatternAddString(pat
, FC_FAMILY
, item
->text
);
276 item
= WMGetListSelectedItem(panel
->styleL
);
279 FontStyle
*style
= (FontStyle
*)item
->clientData
;
281 FcPatternDel(pat
, FC_WEIGHT
);
282 FcPatternAddInteger(pat
, FC_WEIGHT
, style
->weight
);
284 FcPatternDel(pat
, FC_WIDTH
);
285 FcPatternAddInteger(pat
, FC_WIDTH
, style
->width
);
287 FcPatternDel(pat
, FC_SLANT
);
288 FcPatternAddInteger(pat
, FC_SLANT
, style
->slant
);
291 item
= WMGetListSelectedItem(panel
->sizeL
);
294 FcPatternDel(pat
, FC_PIXEL_SIZE
);
295 FcPatternAddDouble(pat
, FC_PIXEL_SIZE
, atoi(item
->text
));
298 name
= FcNameUnparse(pat
);
299 FcPatternDestroy(pat
);
307 updateSampleFont(_Panel
*panel
)
309 WMMenuItem
*item
= WMGetPopUpButtonMenuItem(panel
->optionP
,
310 WMGetPopUpButtonSelectedItem(panel
->optionP
));
311 char *fn
= WMGetMenuItemRepresentedObject(item
);
312 WMFont
*font
= WMCreateFont(WMWidgetScreen(panel
->box
), fn
);
316 WMSetTextFieldFont(panel
->sampleT
, font
);
325 selectedFamily(WMWidget
*w
, void *data
)
327 _Panel
*panel
= (_Panel
*)data
;
329 FontStyle
*oldStyle
= NULL
;
332 item
= WMGetListSelectedItem(panel
->styleL
);
334 oldStyle
= (FontStyle
*)item
->clientData
;
336 item
= WMGetListSelectedItem(panel
->familyL
);
340 FontFamily
*family
= (FontFamily
*)item
->clientData
;
341 int i
, oldi
= 0, oldscore
= 0;
343 WMClearList(panel
->styleL
);
344 for (i
= 0; i
< family
->stylen
; i
++)
347 char *weight
= "", *slant
= "", *width
= "";
350 for (j
= 0; fontWeights
[j
].name
; j
++)
351 if (fontWeights
[j
].weight
== family
->styles
[i
].weight
)
353 weight
= fontWeights
[j
].name
;
356 for (j
= 0; fontWidths
[j
].name
; j
++)
357 if (fontWidths
[j
].width
== family
->styles
[i
].width
)
359 width
= fontWidths
[j
].name
;
362 for (j
= 0; fontSlants
[j
].name
; j
++)
363 if (fontSlants
[j
].slant
== family
->styles
[i
].slant
)
365 slant
= fontSlants
[j
].name
;
368 sprintf(buffer
, "%s%s%s%s%s",
369 weight
, *weight
?" ":"",
370 slant
, (*slant
|| *weight
)?" ":"",
373 strcpy(buffer
, "Roman");
375 item
= WMAddListItem(panel
->styleL
, buffer
);
376 item
->clientData
= family
->styles
+i
;
381 if (oldStyle
->width
== family
->styles
[i
].width
)
383 if (oldStyle
->weight
== family
->styles
[i
].weight
)
385 if (oldStyle
->slant
== family
->styles
[i
].slant
)
388 if (score
> oldscore
)
395 WMSelectListItem(panel
->styleL
, oldi
);
398 int index
= WMGetPopUpButtonSelectedItem(panel
->optionP
);
399 WMMenuItem
*item
= WMGetPopUpButtonMenuItem(panel
->optionP
, index
);
402 ofont
= (char*)WMGetMenuItemRepresentedObject(item
);
404 nfont
= getSelectedFont(panel
, ofont
);
406 WMSetMenuItemRepresentedObject(item
, nfont
);
408 updateSampleFont(panel
);
414 selected(WMWidget
*w
, void *data
)
416 _Panel
*panel
= (_Panel
*)data
;
417 int index
= WMGetPopUpButtonSelectedItem(panel
->optionP
);
418 WMMenuItem
*item
= WMGetPopUpButtonMenuItem(panel
->optionP
, index
);
421 ofont
= (char*)WMGetMenuItemRepresentedObject(item
);
423 nfont
= getSelectedFont(panel
, ofont
);
425 WMSetMenuItemRepresentedObject(item
, nfont
);
427 updateSampleFont(panel
);
432 selectedOption(WMWidget
*w
, void *data
)
434 _Panel
*panel
= (_Panel
*)data
;
435 int index
= WMGetPopUpButtonSelectedItem(panel
->optionP
);
436 WMMenuItem
*item
= WMGetPopUpButtonMenuItem(panel
->optionP
, index
);
439 font
= (char*)WMGetMenuItemRepresentedObject(item
);
444 pat
= FcNameParse(font
);
448 int weight
, slant
, width
;
453 FcDefaultSubstitute(pat
);
455 if (FcPatternGetString(pat
, FC_FAMILY
, 0, &name
) != FcResultMatch
)
460 for (i
= 0; i
< WMGetListNumberOfRows(panel
->familyL
); i
++)
462 WMListItem
*item
= WMGetListItem(panel
->familyL
, i
);
463 FontFamily
*family
= (FontFamily
*)item
->clientData
;
465 if (strcasecmp(family
->name
, name
)==0)
468 WMSelectListItem(panel
->familyL
, i
);
469 WMSetListPosition(panel
->familyL
, i
);
474 WMSelectListItem(panel
->familyL
, -1);
475 selectedFamily(panel
->familyL
, panel
);
478 if (FcPatternGetInteger(pat
, FC_WEIGHT
, 0, &weight
) != FcResultMatch
)
479 weight
= FC_WEIGHT_NORMAL
;
480 if (FcPatternGetInteger(pat
, FC_WIDTH
, 0, &width
) != FcResultMatch
)
481 width
= FC_WIDTH_NORMAL
;
482 if (FcPatternGetInteger(pat
, FC_SLANT
, 0, &slant
) != FcResultMatch
)
483 slant
= FC_SLANT_ROMAN
;
485 if (FcPatternGetDouble(pat
, FC_PIXEL_SIZE
, 0, &size
) != FcResultMatch
)
489 for (i
= 0; i
< WMGetListNumberOfRows(panel
->styleL
); i
++)
491 WMListItem
*item
= WMGetListItem(panel
->styleL
, i
);
492 FontStyle
*style
= (FontStyle
*)item
->clientData
;
493 if (style
->weight
== weight
494 && style
->width
== width
495 && style
->slant
== slant
)
498 WMSelectListItem(panel
->styleL
, i
);
499 WMSetListPosition(panel
->styleL
, i
);
504 WMSelectListItem(panel
->styleL
, -1);
508 int closest
= 100000, index
= -1;
510 for (i
= 0; i
< WMGetListNumberOfRows(panel
->sizeL
); i
++)
512 WMListItem
*item
= WMGetListItem(panel
->sizeL
, i
);
515 tmp
= atoi(item
->text
);
516 if (abs(tmp
-size
) < abs(tmp
-closest
))
522 WMSelectListItem(panel
->sizeL
, index
);
523 WMSetListPosition(panel
->sizeL
, index
);
526 selected(NULL
, panel
);
529 wwarning("Can't parse font '%s'", font
);
532 updateSampleFont(panel
);
537 createListLabel(WMScreen
*scr
, WMWidget
*parent
, char *text
)
541 WMFont
*boldFont
= WMBoldSystemFontOfSize(scr
, 12);
543 label
= WMCreateLabel(parent
);
544 WMSetLabelFont(label
, boldFont
);
545 WMSetLabelText(label
, text
);
546 WMSetLabelRelief(label
, WRSunken
);
547 WMSetLabelTextAlignment(label
, WACenter
);
548 color
= WMDarkGrayColor(scr
);
549 WMSetWidgetBackgroundColor(label
, color
);
550 WMReleaseColor(color
);
551 color
= WMWhiteColor(scr
);
552 WMSetLabelTextColor(label
, color
);
553 WMReleaseColor(color
);
555 WMReleaseFont(boldFont
);
562 showData(_Panel
*panel
)
567 for (i
= 0; i
< WMGetPopUpButtonNumberOfItems(panel
->optionP
); i
++)
571 item
= WMGetPopUpButtonMenuItem(panel
->optionP
, i
);
573 ofont
= WMGetMenuItemRepresentedObject(item
);
577 font
= GetStringForKey(fontOptions
[i
].option
);
580 WMSetMenuItemRepresentedObject(item
, font
);
583 WMSetPopUpButtonSelectedItem(panel
->optionP
, 0);
584 selectedOption(panel
->optionP
, panel
);
589 storeData(_Panel
*panel
)
593 for (i
= 0; i
< WMGetPopUpButtonNumberOfItems(panel
->optionP
); i
++)
597 item
= WMGetPopUpButtonMenuItem(panel
->optionP
, i
);
599 font
= WMGetMenuItemRepresentedObject(item
);
602 SetStringForKey(font
, fontOptions
[i
].option
);
609 createPanel(Panel
*p
)
611 _Panel
*panel
= (_Panel
*)p
;
612 WMScreen
*scr
= WMWidgetScreen(panel
->parent
);
617 lookup_available_fonts(panel
);
619 panel
->box
= WMCreateBox(panel
->parent
);
620 WMSetViewExpandsToParent(WMWidgetView(panel
->box
), 5, 2, 5, 5);
621 WMSetBoxHorizontal(panel
->box
, False
);
622 WMSetBoxBorderWidth(panel
->box
, 8);
623 WMMapWidget(panel
->box
);
625 hbox
= WMCreateBox(panel
->box
);
626 WMSetBoxHorizontal(hbox
, True
);
627 WMAddBoxSubview(panel
->box
, WMWidgetView(hbox
), False
, True
, 40, 22, 8);
629 vbox
= WMCreateBox(hbox
);
630 WMAddBoxSubview(hbox
, WMWidgetView(vbox
), False
, True
, 130, 0, 10);
631 WMSetBoxHorizontal(vbox
, False
);
632 panel
->optionP
= WMCreatePopUpButton(vbox
);
633 WMAddBoxSubviewAtEnd(vbox
, WMWidgetView(panel
->optionP
), False
, True
, 24, 0, 8);
634 for (i
= 0; fontOptions
[i
].option
; i
++)
636 WMAddPopUpButtonItem(panel
->optionP
, _(fontOptions
[i
].label
));
638 WMSetPopUpButtonAction(panel
->optionP
, selectedOption
, panel
);
640 label
= WMCreateLabel(hbox
);
641 WMSetLabelText(label
, _("Sample Text"));
642 WMSetLabelTextAlignment(label
, WARight
);
643 WMAddBoxSubview(hbox
, WMWidgetView(label
), False
, True
, 80, 0, 2);
645 panel
->sampleT
= WMCreateTextField(hbox
);
646 WMSetViewExpandsToParent(WMWidgetView(panel
->sampleT
), 10, 18, 10, 10);
647 WMSetTextFieldText(panel
->sampleT
, SAMPLE_TEXT
);
648 WMAddBoxSubview(hbox
, WMWidgetView(panel
->sampleT
), True
, True
, 60, 0, 0);
651 hbox
= WMCreateBox(panel
->box
);
652 WMSetBoxHorizontal(hbox
, True
);
653 WMAddBoxSubview(panel
->box
, WMWidgetView(hbox
), True
, True
, 100, 0, 2);
655 vbox
= WMCreateBox(hbox
);
656 WMSetBoxHorizontal(vbox
, False
);
657 WMAddBoxSubview(hbox
, WMWidgetView(vbox
), False
, True
, 240, 20, 4);
659 label
= createListLabel(scr
, vbox
, _("Family"));
660 WMAddBoxSubview(vbox
, WMWidgetView(label
), False
, True
, 20, 0, 2);
663 panel
->familyL
= WMCreateList(vbox
);
664 WMAddBoxSubview(vbox
, WMWidgetView(panel
->familyL
), True
, True
, 0, 0, 0);
668 for (i
= 0; i
< panel
->fonts
->familyn
; i
++)
670 item
= WMAddListItem(panel
->familyL
, panel
->fonts
->families
[i
].name
);
671 item
->clientData
= panel
->fonts
->families
+i
;
675 WMAddListItem(panel
->familyL
, "sans");
677 WMSetListAction(panel
->familyL
, selectedFamily
, panel
);
679 vbox
= WMCreateBox(hbox
);
680 WMSetBoxHorizontal(vbox
, False
);
681 WMAddBoxSubview(hbox
, WMWidgetView(vbox
), True
, True
, 10, 0, 0);
684 WMBox
*box
= WMCreateBox(vbox
);
685 WMSetBoxHorizontal(box
, True
);
686 WMAddBoxSubview(vbox
, WMWidgetView(box
), False
, True
, 20, 0, 2);
688 label
= createListLabel(scr
, box
, _("Style"));
689 WMAddBoxSubview(box
, WMWidgetView(label
), True
, True
, 20, 0, 4);
691 label
= createListLabel(scr
, box
, _("Size"));
692 WMAddBoxSubview(box
, WMWidgetView(label
), False
, True
, 60, 0, 0);
694 box
= WMCreateBox(vbox
);
695 WMSetBoxHorizontal(box
, True
);
696 WMAddBoxSubview(vbox
, WMWidgetView(box
), True
, True
, 20, 0, 4);
698 panel
->styleL
= WMCreateList(box
);
699 WMAddBoxSubview(box
, WMWidgetView(panel
->styleL
), True
, True
, 0, 0, 4);
700 WMSetListAction(panel
->styleL
, selected
, panel
);
702 panel
->sizeL
= WMCreateList(box
);
703 WMAddBoxSubview(box
, WMWidgetView(panel
->sizeL
), False
, True
, 60, 0, 0);
704 for (i
= 0; standardSizes
[i
]; i
++)
706 WMAddListItem(panel
->sizeL
, standardSizes
[i
]);
708 WMSetListAction(panel
->sizeL
, selected
, panel
);
712 WMMapSubwidgets(panel
->box
);
713 WMMapWidget(panel
->box
);
714 WMRealizeWidget(panel
->box
);
722 InitFontSimple(WMScreen
*scr
, WMWidget
*parent
)
726 panel
= wmalloc(sizeof(_Panel
));
727 memset(panel
, 0, sizeof(_Panel
));
729 panel
->sectionName
= _("Font Configuration");
731 panel
->description
= _("Configure fonts for Window Maker titlebars, menus etc.");
733 panel
->parent
= parent
;
735 panel
->callbacks
.createWidgets
= createPanel
;
736 panel
->callbacks
.updateDomain
= storeData
;
738 AddSection(panel
, ICON_FILE
);