- Check whether libXft is at least version 2.1.2 else refuse to compile.
[wmaker-crm.git] / WINGs / wfontpanel.c
blob48fe933f7924388521f560af7a090b2e137c8fcc
5 #include "WINGsP.h"
6 #include "WUtil.h"
7 #include "wconfig.h"
9 #include <ctype.h>
10 #include <string.h>
12 #ifdef XFT
13 #include <X11/Xft/Xft.h>
14 #include <fontconfig/fontconfig.h>
15 #endif
18 /* XXX TODO */
19 char *WMFontPanelFontChangedNotification = "WMFontPanelFontChangedNotification";
24 typedef struct W_FontPanel {
25 WMWindow *win;
27 WMFrame *upperF;
28 WMTextField *sampleT;
30 WMSplitView *split;
32 WMFrame *lowerF;
33 WMLabel *famL;
34 WMList *famLs;
35 WMLabel *typL;
36 WMList *typLs;
37 WMLabel *sizL;
38 WMTextField *sizT;
39 WMList *sizLs;
41 WMAction2 *action;
42 void *data;
44 WMButton *revertB;
45 WMButton *setB;
47 WMPropList *fdb;
48 } FontPanel;
51 #define MIN_UPPER_HEIGHT 20
52 #define MIN_LOWER_HEIGHT 140
55 #define MAX_FONTS_TO_RETRIEVE 2000
57 #define BUTTON_SPACE_HEIGHT 40
59 #define MIN_WIDTH 250
60 #define MIN_HEIGHT (MIN_UPPER_HEIGHT+MIN_LOWER_HEIGHT+BUTTON_SPACE_HEIGHT)
62 #define DEF_UPPER_HEIGHT 60
63 #define DEF_LOWER_HEIGHT 310
65 #define DEF_WIDTH 320
66 #define DEF_HEIGHT (DEF_UPPER_HEIGHT+DEF_LOWER_HEIGHT)
71 static int scalableFontSizes[] = {
73 10,
74 11,
75 12,
76 14,
77 16,
78 18,
79 20,
80 24,
81 36,
82 48,
88 #ifdef XFT
89 static void setFontPanelFontName(FontPanel *panel, FcChar8 *family, FcChar8 *style, double size);
90 #endif
92 static int isXLFD(char *font, int *length_ret);
94 static void arrangeLowerFrame(FontPanel *panel);
96 static void familyClick(WMWidget *, void *);
97 static void typefaceClick(WMWidget *, void *);
98 static void sizeClick(WMWidget *, void *);
101 static void listFamilies(WMScreen *scr, WMFontPanel *panel);
104 static void
105 splitViewConstrainCallback(WMSplitView *sPtr, int indView, int *min, int *max)
107 if (indView == 0)
108 *min = MIN_UPPER_HEIGHT;
109 else
110 *min = MIN_LOWER_HEIGHT;
113 static void
114 notificationObserver(void *self, WMNotification *notif)
116 WMFontPanel *panel = (WMFontPanel*)self;
117 void *object = WMGetNotificationObject(notif);
119 if (WMGetNotificationName(notif) == WMViewSizeDidChangeNotification) {
120 if (object == WMWidgetView(panel->win)) {
121 int h = WMWidgetHeight(panel->win);
122 int w = WMWidgetWidth(panel->win);
124 WMResizeWidget(panel->split, w, h-BUTTON_SPACE_HEIGHT);
126 WMMoveWidget(panel->setB, w-80, h-(BUTTON_SPACE_HEIGHT-5));
128 WMMoveWidget(panel->revertB, w-240, h-(BUTTON_SPACE_HEIGHT-5));
130 } else if (object == WMWidgetView(panel->upperF)) {
132 if (WMWidgetHeight(panel->upperF) < MIN_UPPER_HEIGHT) {
133 WMResizeWidget(panel->upperF, WMWidgetWidth(panel->upperF),
134 MIN_UPPER_HEIGHT);
135 } else {
136 WMResizeWidget(panel->sampleT, WMWidgetWidth(panel->upperF)-20,
137 WMWidgetHeight(panel->upperF)-10);
140 } else if (object == WMWidgetView(panel->lowerF)) {
142 if (WMWidgetHeight(panel->lowerF) < MIN_LOWER_HEIGHT) {
143 WMResizeWidget(panel->upperF, WMWidgetWidth(panel->upperF),
144 MIN_UPPER_HEIGHT);
146 WMMoveWidget(panel->lowerF, 0, WMWidgetHeight(panel->upperF)
147 + WMGetSplitViewDividerThickness(panel->split));
149 WMResizeWidget(panel->lowerF, WMWidgetWidth(panel->lowerF),
150 WMWidgetWidth(panel->split) - MIN_UPPER_HEIGHT
151 - WMGetSplitViewDividerThickness(panel->split));
152 } else {
153 arrangeLowerFrame(panel);
160 static void
161 closeWindow(WMWidget *w, void *data)
163 FontPanel *panel = (FontPanel*)data;
165 WMHideFontPanel(panel);
171 static void
172 setClickedAction(WMWidget *w, void *data)
174 FontPanel *panel = (FontPanel*)data;
176 if (panel->action)
177 (*panel->action)(panel, panel->data);
181 static void
182 revertClickedAction(WMWidget *w, void *data)
184 /*FontPanel *panel = (FontPanel*)data;*/
185 /* XXX TODO */
190 WMFontPanel*
191 WMGetFontPanel(WMScreen *scr)
193 FontPanel *panel;
194 WMColor *dark, *white;
195 WMFont *font;
196 int divThickness;
198 if (scr->sharedFontPanel)
199 return scr->sharedFontPanel;
202 panel = wmalloc(sizeof(FontPanel));
203 memset(panel, 0, sizeof(FontPanel));
205 panel->win = WMCreateWindow(scr, "fontPanel");
206 /* WMSetWidgetBackgroundColor(panel->win, WMWhiteColor(scr));*/
207 WMSetWindowTitle(panel->win, _("Font Panel"));
208 WMResizeWidget(panel->win, DEF_WIDTH, DEF_HEIGHT);
209 WMSetWindowMinSize(panel->win, MIN_WIDTH, MIN_HEIGHT);
210 WMSetViewNotifySizeChanges(WMWidgetView(panel->win), True);
212 WMSetWindowCloseAction(panel->win, closeWindow, panel);
214 panel->split = WMCreateSplitView(panel->win);
215 WMResizeWidget(panel->split, DEF_WIDTH, DEF_HEIGHT - BUTTON_SPACE_HEIGHT);
216 WMSetSplitViewConstrainProc(panel->split, splitViewConstrainCallback);
218 divThickness = WMGetSplitViewDividerThickness(panel->split);
220 panel->upperF = WMCreateFrame(panel->win);
221 WMSetFrameRelief(panel->upperF, WRFlat);
222 WMSetViewNotifySizeChanges(WMWidgetView(panel->upperF), True);
223 panel->lowerF = WMCreateFrame(panel->win);
224 /* WMSetWidgetBackgroundColor(panel->lowerF, WMBlackColor(scr));*/
225 WMSetFrameRelief(panel->lowerF, WRFlat);
226 WMSetViewNotifySizeChanges(WMWidgetView(panel->lowerF), True);
228 WMAddSplitViewSubview(panel->split, W_VIEW(panel->upperF));
229 WMAddSplitViewSubview(panel->split, W_VIEW(panel->lowerF));
231 WMResizeWidget(panel->upperF, DEF_WIDTH, DEF_UPPER_HEIGHT);
233 WMResizeWidget(panel->lowerF, DEF_WIDTH, DEF_LOWER_HEIGHT);
235 WMMoveWidget(panel->lowerF, 0, 60+divThickness);
237 white = WMWhiteColor(scr);
238 dark = WMDarkGrayColor(scr);
240 panel->sampleT = WMCreateTextField(panel->upperF);
241 WMResizeWidget(panel->sampleT, DEF_WIDTH - 20, 50);
242 WMMoveWidget(panel->sampleT, 10, 10);
243 WMSetTextFieldText(panel->sampleT, _("The quick brown fox jumps over the lazy dog"));
245 font = WMBoldSystemFontOfSize(scr, 12);
247 panel->famL = WMCreateLabel(panel->lowerF);
248 WMSetWidgetBackgroundColor(panel->famL, dark);
249 WMSetLabelText(panel->famL, _("Family"));
250 WMSetLabelFont(panel->famL, font);
251 WMSetLabelTextColor(panel->famL, white);
252 WMSetLabelRelief(panel->famL, WRSunken);
253 WMSetLabelTextAlignment(panel->famL, WACenter);
255 panel->famLs = WMCreateList(panel->lowerF);
256 WMSetListAction(panel->famLs, familyClick, panel);
258 panel->typL = WMCreateLabel(panel->lowerF);
259 WMSetWidgetBackgroundColor(panel->typL, dark);
260 WMSetLabelText(panel->typL, _("Typeface"));
261 WMSetLabelFont(panel->typL, font);
262 WMSetLabelTextColor(panel->typL, white);
263 WMSetLabelRelief(panel->typL, WRSunken);
264 WMSetLabelTextAlignment(panel->typL, WACenter);
266 panel->typLs = WMCreateList(panel->lowerF);
267 WMSetListAction(panel->typLs, typefaceClick, panel);
269 panel->sizL = WMCreateLabel(panel->lowerF);
270 WMSetWidgetBackgroundColor(panel->sizL, dark);
271 WMSetLabelText(panel->sizL, _("Size"));
272 WMSetLabelFont(panel->sizL, font);
273 WMSetLabelTextColor(panel->sizL, white);
274 WMSetLabelRelief(panel->sizL, WRSunken);
275 WMSetLabelTextAlignment(panel->sizL, WACenter);
277 panel->sizT = WMCreateTextField(panel->lowerF);
278 /* WMSetTextFieldAlignment(panel->sizT, WARight);*/
280 panel->sizLs = WMCreateList(panel->lowerF);
281 WMSetListAction(panel->sizLs, sizeClick, panel);
283 WMReleaseFont(font);
284 WMReleaseColor(white);
285 WMReleaseColor(dark);
287 panel->setB = WMCreateCommandButton(panel->win);
288 WMResizeWidget(panel->setB, 70, 24);
289 WMMoveWidget(panel->setB, 240, DEF_HEIGHT - (BUTTON_SPACE_HEIGHT-5));
290 WMSetButtonText(panel->setB, _("Set"));
291 WMSetButtonAction(panel->setB, setClickedAction, panel);
293 panel->revertB = WMCreateCommandButton(panel->win);
294 WMResizeWidget(panel->revertB, 70, 24);
295 WMMoveWidget(panel->revertB, 80, DEF_HEIGHT - (BUTTON_SPACE_HEIGHT-5));
296 WMSetButtonText(panel->revertB, _("Revert"));
297 WMSetButtonAction(panel->revertB, revertClickedAction, panel);
300 WMRealizeWidget(panel->win);
302 WMMapSubwidgets(panel->upperF);
303 WMMapSubwidgets(panel->lowerF);
304 WMMapSubwidgets(panel->split);
305 WMMapSubwidgets(panel->win);
307 WMUnmapWidget(panel->revertB);
309 arrangeLowerFrame(panel);
311 scr->sharedFontPanel = panel;
314 /* register notification observers */
315 WMAddNotificationObserver(notificationObserver, panel,
316 WMViewSizeDidChangeNotification,
317 WMWidgetView(panel->win));
318 WMAddNotificationObserver(notificationObserver, panel,
319 WMViewSizeDidChangeNotification,
320 WMWidgetView(panel->upperF));
321 WMAddNotificationObserver(notificationObserver, panel,
322 WMViewSizeDidChangeNotification,
323 WMWidgetView(panel->lowerF));
326 listFamilies(scr, panel);
329 return panel;
333 void
334 WMFreeFontPanel(WMFontPanel *panel)
336 if (panel == WMWidgetScreen(panel->win)->sharedFontPanel) {
337 WMWidgetScreen(panel->win)->sharedFontPanel = NULL;
339 WMRemoveNotificationObserver(panel);
340 WMUnmapWidget(panel->win);
341 WMDestroyWidget(panel->win);
342 wfree(panel);
346 void
347 WMShowFontPanel(WMFontPanel *panel)
349 WMMapWidget(panel->win);
353 void
354 WMHideFontPanel(WMFontPanel *panel)
356 WMUnmapWidget(panel->win);
360 WMFont*
361 WMGetFontPanelFont(WMFontPanel *panel)
363 return WMGetTextFieldFont(panel->sampleT);
367 void
368 WMSetFontPanelFont(WMFontPanel *panel, char *fontName)
370 #ifdef XFT
371 int fname_len;
372 FcPattern *pattern;
373 FcChar8 *family, *style;
374 double size;
376 if (!isXLFD(fontName, &fname_len)) {
377 /* maybe its proper fontconfig and we can parse it */
378 pattern = FcNameParse(fontName);
379 } else {
380 /* maybe its proper xlfd and we can convert it to an FcPattern */
381 pattern = XftXlfdParse(fontName, False, False);
382 //FcPatternPrint(pattern);
385 if (!pattern)
386 return;
388 if (FcPatternGetString(pattern, FC_FAMILY, 0, &family)==FcResultMatch)
389 if (FcPatternGetString(pattern, FC_STYLE, 0, &style)==FcResultMatch)
390 if (FcPatternGetDouble(pattern, "pixelsize", 0, &size)==FcResultMatch)
391 setFontPanelFontName(panel, family, style, size);
393 FcPatternDestroy(pattern);
394 #endif
398 void
399 WMSetFontPanelAction(WMFontPanel *panel, WMAction2 *action, void *data)
401 panel->action = action;
402 panel->data = data;
409 static void
410 arrangeLowerFrame(FontPanel *panel)
412 int width = WMWidgetWidth(panel->lowerF) - 55 - 30;
413 int height = WMWidgetHeight(panel->split) - WMWidgetHeight(panel->upperF);
414 int fw, tw, sw;
416 #define LABEL_HEIGHT 20
418 height -= WMGetSplitViewDividerThickness(panel->split);
421 height -= LABEL_HEIGHT + 8;
423 fw = (125*width) / 235;
424 tw = (110*width) / 235;
425 sw = 55;
427 WMMoveWidget(panel->famL, 10, 0);
428 WMResizeWidget(panel->famL, fw, LABEL_HEIGHT);
430 WMMoveWidget(panel->famLs, 10, 23);
431 WMResizeWidget(panel->famLs, fw, height);
433 WMMoveWidget(panel->typL, 10+fw+3, 0);
434 WMResizeWidget(panel->typL, tw, LABEL_HEIGHT);
436 WMMoveWidget(panel->typLs, 10+fw+3, 23);
437 WMResizeWidget(panel->typLs, tw, height);
439 WMMoveWidget(panel->sizL, 10+fw+3+tw+3, 0);
440 WMResizeWidget(panel->sizL, sw+4, LABEL_HEIGHT);
442 WMMoveWidget(panel->sizT, 10+fw+3+tw+3, 23);
443 WMResizeWidget(panel->sizT, sw+4, 20);
445 WMMoveWidget(panel->sizLs, 10+fw+3+tw+3, 46);
446 WMResizeWidget(panel->sizLs, sw+4, height-23);
452 #define ALL_FONTS_MASK "-*-*-*-*-*-*-*-*-*-*-*-*-*-*"
454 #define FOUNDRY 0
455 #define FAMILY 1
456 #define WEIGHT 2
457 #define SLANT 3
458 #define SETWIDTH 4
459 #define ADD_STYLE 5
460 #define PIXEL_SIZE 6
461 #define POINT_SIZE 7
462 #define RES_X 8
463 #define RES_Y 9
464 #define SPACING 10
465 #define AV_WIDTH 11
466 #define REGISTRY 12
467 #define ENCODING 13
469 #define NUM_FIELDS 14
473 static int
474 isXLFD(char *font, int *length_ret)
476 int c = 0;
478 *length_ret = 0;
479 while (*font) {
480 (*length_ret)++;
481 if (*font++ == '-')
482 c++;
485 return c==NUM_FIELDS;
488 #ifndef XFT
489 static Bool
490 parseFont(char *font, char values[NUM_FIELDS][256])
492 char *ptr;
493 int part;
494 char buffer[256], *bptr;
496 part = FOUNDRY;
497 ptr = font;
498 ptr++; /* skip first - */
499 bptr = buffer;
500 while (*ptr) {
501 if (*ptr == '-') {
502 *bptr = 0;
503 strcpy(values[part], buffer);
504 bptr = buffer;
505 part++;
506 } else {
507 *bptr++ = *ptr;
509 ptr++;
511 *bptr = 0;
512 strcpy(values[part], buffer);
514 return True;
521 typedef struct {
522 char *weight;
523 char *slant;
525 char *setWidth;
526 char *addStyle;
528 char showSetWidth; /* when duplicated */
529 char showAddStyle; /* when duplicated */
531 WMArray *sizes;
532 } Typeface;
535 typedef struct {
536 char *name;
538 char *foundry;
539 char *registry, *encoding;
541 char showFoundry; /* when duplicated */
542 char showRegistry; /* when duplicated */
544 WMArray *typefaces;
545 } Family;
546 #endif
547 #ifdef XFT
548 typedef struct {
549 char *typeface;
550 WMArray *sizes;
551 } Xft_Typeface;
553 typedef struct {
554 char *name; /* gotta love simplicity */
555 WMArray *typefaces;
556 } Xft_Family;
557 #endif
562 static int
563 compare_int(const void *a, const void *b)
565 int i1 = *(int*)a;
566 int i2 = *(int*)b;
568 if (i1 < i2)
569 return -1;
570 else if (i1 > i2)
571 return 1;
572 else
573 return 0;
577 static void
578 #ifdef XFT
579 addSizeToTypeface(Xft_Typeface *face, int size)
580 #else
581 addSizeToTypeface(Typeface *face, int size)
582 #endif
584 if (size == 0) {
585 int j;
587 for (j = 0; j < sizeof(scalableFontSizes)/sizeof(int); j++) {
588 size = scalableFontSizes[j];
590 if (!WMCountInArray(face->sizes, (void*)size)) {
591 WMAddToArray(face->sizes, (void*)size);
594 WMSortArray(face->sizes, compare_int);
595 } else {
596 if (!WMCountInArray(face->sizes, (void*)size)) {
597 WMAddToArray(face->sizes, (void*)size);
598 WMSortArray(face->sizes, compare_int);
603 #ifdef XFT
604 static void
605 addTypefaceToXftFamily(Xft_Family *fam, char *style)
607 Xft_Typeface *face;
608 WMArrayIterator i;
610 if(fam->typefaces) {
611 WM_ITERATE_ARRAY(fam->typefaces, face, i) {
612 if(strcmp(face->typeface, style) != 0)
613 continue; /* go to next interation */
614 addSizeToTypeface(face, 0);
615 return;
617 } else {
618 fam->typefaces = WMCreateArray(4);
621 face = wmalloc(sizeof(Xft_Typeface));
622 memset(face, 0 , sizeof(Xft_Typeface));
624 face->typeface = wstrdup(style);
625 face->sizes = WMCreateArray(4);
626 addSizeToTypeface(face, 0);
628 WMAddToArray(fam->typefaces, face);
631 #else /* XFT */
633 static void
634 addTypefaceToFamily(Family *family, char fontFields[NUM_FIELDS][256])
636 Typeface *face;
637 WMArrayIterator i;
639 if (family->typefaces) {
640 WM_ITERATE_ARRAY(family->typefaces, face, i) {
641 int size;
643 if (strcmp(face->weight, fontFields[WEIGHT]) != 0) {
644 continue;
646 if (strcmp(face->slant, fontFields[SLANT]) != 0) {
647 continue;
650 size = atoi(fontFields[PIXEL_SIZE]);
652 addSizeToTypeface(face, size);
654 return;
656 } else {
657 family->typefaces = WMCreateArray(4);
660 face = wmalloc(sizeof(Typeface));
661 memset(face, 0, sizeof(Typeface));
663 face->weight = wstrdup(fontFields[WEIGHT]);
664 face->slant = wstrdup(fontFields[SLANT]);
665 face->setWidth = wstrdup(fontFields[SETWIDTH]);
666 face->addStyle = wstrdup(fontFields[ADD_STYLE]);
668 face->sizes = WMCreateArray(4);
669 addSizeToTypeface(face, atoi(fontFields[PIXEL_SIZE]));
671 WMAddToArray(family->typefaces, face);
673 #endif
676 * families (same family name) (Hashtable of family -> array)
677 * registries (same family but different registries)
681 #ifdef XFT
682 static void
683 addFontToXftFamily(WMHashTable *families, char *name, char *style)
685 WMArrayIterator i;
686 WMArray *array;
687 Xft_Family *fam;
689 array = WMHashGet(families, name);
690 if(array) {
691 WM_ITERATE_ARRAY(array, fam, i) {
692 if(strcmp(fam->name, name) == 0 )
693 addTypefaceToXftFamily(fam, style);
694 return;
698 array = WMCreateArray(8);
700 fam = wmalloc(sizeof(Xft_Family));
701 memset(fam, 0, sizeof(Xft_Family));
703 fam->name = wstrdup(name);
705 addTypefaceToXftFamily(fam, style);
707 WMAddToArray(array, fam);
709 WMHashInsert(families, fam->name, array);
712 #else /* XFT */
714 static void
715 addFontToFamily(WMHashTable *families, char fontFields[NUM_FIELDS][256])
717 WMArrayIterator i;
718 Family *fam;
719 WMArray *family;
722 family = WMHashGet(families, fontFields[FAMILY]);
724 if (family) {
725 /* look for same encoding/registry and foundry */
726 WM_ITERATE_ARRAY(family, fam, i) {
727 int enc, reg, found;
729 enc = (strcmp(fam->encoding, fontFields[ENCODING]) == 0);
730 reg = (strcmp(fam->registry, fontFields[REGISTRY]) == 0);
731 found = (strcmp(fam->foundry, fontFields[FOUNDRY]) == 0);
733 if (enc && reg && found) {
734 addTypefaceToFamily(fam, fontFields);
735 return;
738 /* look for same encoding/registry */
739 WM_ITERATE_ARRAY(family, fam, i) {
740 int enc, reg;
742 enc = (strcmp(fam->encoding, fontFields[ENCODING]) == 0);
743 reg = (strcmp(fam->registry, fontFields[REGISTRY]) == 0);
745 if (enc && reg) {
746 /* has the same encoding, but the foundry is different */
747 fam->showFoundry = 1;
749 fam = wmalloc(sizeof(Family));
750 memset(fam, 0, sizeof(Family));
752 fam->name = wstrdup(fontFields[FAMILY]);
753 fam->foundry = wstrdup(fontFields[FOUNDRY]);
754 fam->registry = wstrdup(fontFields[REGISTRY]);
755 fam->encoding = wstrdup(fontFields[ENCODING]);
756 fam->showFoundry = 1;
758 addTypefaceToFamily(fam, fontFields);
760 WMAddToArray(family, fam);
761 return;
764 /* look for same foundry */
765 WM_ITERATE_ARRAY(family, fam, i) {
766 int found;
768 found = (strcmp(fam->foundry, fontFields[FOUNDRY]) == 0);
770 if (found) {
771 /* has the same foundry, but encoding is different */
772 fam->showRegistry = 1;
774 fam = wmalloc(sizeof(Family));
775 memset(fam, 0, sizeof(Family));
777 fam->name = wstrdup(fontFields[FAMILY]);
778 fam->foundry = wstrdup(fontFields[FOUNDRY]);
779 fam->registry = wstrdup(fontFields[REGISTRY]);
780 fam->encoding = wstrdup(fontFields[ENCODING]);
781 fam->showRegistry = 1;
783 addTypefaceToFamily(fam, fontFields);
785 WMAddToArray(family, fam);
786 return;
789 /* foundry and encoding do not match anything known */
790 fam = wmalloc(sizeof(Family));
791 memset(fam, 0, sizeof(Family));
793 fam->name = wstrdup(fontFields[FAMILY]);
794 fam->foundry = wstrdup(fontFields[FOUNDRY]);
795 fam->registry = wstrdup(fontFields[REGISTRY]);
796 fam->encoding = wstrdup(fontFields[ENCODING]);
797 fam->showFoundry = 1;
798 fam->showRegistry = 1;
800 addTypefaceToFamily(fam, fontFields);
802 WMAddToArray(family, fam);
803 return;
806 family = WMCreateArray(8);
808 fam = wmalloc(sizeof(Family));
809 memset(fam, 0, sizeof(Family));
811 fam->name = wstrdup(fontFields[FAMILY]);
812 fam->foundry = wstrdup(fontFields[FOUNDRY]);
813 fam->registry = wstrdup(fontFields[REGISTRY]);
814 fam->encoding = wstrdup(fontFields[ENCODING]);
816 addTypefaceToFamily(fam, fontFields);
818 WMAddToArray(family, fam);
820 WMHashInsert(families, fam->name, family);
822 #endif /* XFT */
826 static void
827 listFamilies(WMScreen *scr, WMFontPanel *panel)
829 #ifdef XFT
830 FcObjectSet *os = 0;
831 FcFontSet *fs;
832 FcPattern *pat;
833 #else /* XFT */
834 char **fontList;
835 char fields[NUM_FIELDS][256];
836 int count;
837 #endif /* XFT */
838 WMHashTable *families;
839 WMHashEnumerator enumer;
840 WMArray *array;
841 int i;
843 #ifdef XFT
844 pat = FcPatternCreate();
845 os = FcObjectSetBuild(FC_FAMILY, FC_STYLE, 0);
846 fs = FcFontList(0, pat, os);
847 if (!fs) {
848 WMRunAlertPanel(scr, panel->win, _("Error"),
849 _("Could not init font config library\n"), _("OK"), NULL, NULL);
850 return;
852 if (pat)
853 FcPatternDestroy (pat);
854 #else /* XFT */
855 fontList = XListFonts(scr->display, ALL_FONTS_MASK, MAX_FONTS_TO_RETRIEVE,
856 &count);
857 if (!fontList) {
858 WMRunAlertPanel(scr, panel->win, _("Error"),
859 _("Could not retrieve font list"), _("OK"), NULL, NULL);
860 return;
862 #endif /* XFT */
864 families = WMCreateHashTable(WMStringPointerHashCallbacks);
866 #ifdef XFT
867 if(fs) {
868 for (i = 0; i < fs->nfont; i++) {
869 FcChar8 *family;
870 FcChar8 *style;
872 if (FcPatternGetString(fs->fonts[i],FC_FAMILY,0,&family)==FcResultMatch)
873 if (FcPatternGetString(fs->fonts[i],FC_STYLE,0,&style)==FcResultMatch)
874 addFontToXftFamily(families, family, style);
876 FcFontSetDestroy(fs);
878 #else /* XFT */
879 for (i = 0; i < count; i++) {
880 int fname_len;
882 if (!isXLFD(fontList[i], &fname_len)) {
883 *fontList[i] = '\0';
884 continue;
886 if (fname_len > 255) {
887 wwarning(_("font name %s is longer than 256, which is invalid."),
888 fontList[i]);
889 *fontList[i] = '\0';
890 continue;
892 if (!parseFont(fontList[i], fields)) {
893 *fontList[i] = '\0';
894 continue;
896 addFontToFamily(families, fields);
898 #endif /* XFT */
900 enumer = WMEnumerateHashTable(families);
902 #ifdef XFT
903 while ((array = WMNextHashEnumeratorItem(&enumer))) {
904 WMArrayIterator i;
905 Xft_Family *fam;
906 char buffer[256];
907 WMListItem *item;
909 WM_ITERATE_ARRAY(array, fam, i) {
910 strcpy(buffer, fam->name);
911 item = WMAddListItem(panel->famLs, buffer);
913 item->clientData = fam;
916 WMFreeArray(array);
918 #else /* XFT */
919 while ((array = WMNextHashEnumeratorItem(&enumer))) {
920 WMArrayIterator i;
921 Family *fam;
922 char buffer[256];
923 WMListItem *item;
925 WM_ITERATE_ARRAY(array, fam, i) {
926 strcpy(buffer, fam->name);
928 if (fam->showFoundry) {
929 strcat(buffer, " ");
930 strcat(buffer, fam->foundry);
931 strcat(buffer, " ");
933 if (fam->showRegistry) {
934 strcat(buffer, " (");
935 strcat(buffer, fam->registry);
936 strcat(buffer, "-");
937 strcat(buffer, fam->encoding);
938 strcat(buffer, ")");
940 item = WMAddListItem(panel->famLs, buffer);
942 item->clientData = fam;
944 WMFreeArray(array);
946 #endif /* XFT */
947 WMSortListItems(panel->famLs);
949 WMFreeHashTable(families);
953 static void
954 getSelectedFont(FontPanel *panel, char buffer[], int bufsize)
956 WMListItem *item;
957 #ifdef XFT
958 Xft_Family *family;
959 Xft_Typeface *face;
960 #else
961 Family *family;
962 Typeface *face;
963 #endif
964 char *size;
967 item = WMGetListSelectedItem(panel->famLs);
968 if (!item)
969 return;
970 #ifdef XFT
971 family = (Xft_Family*)item->clientData;
972 #else
973 family = (Family*)item->clientData;
974 #endif
976 item = WMGetListSelectedItem(panel->typLs);
977 if (!item)
978 return;
979 #ifdef XFT
980 face = (Xft_Typeface*)item->clientData;
981 #else
982 face = (Typeface*)item->clientData;
983 #endif
985 size = WMGetTextFieldText(panel->sizT);
987 #ifdef XFT
988 snprintf(buffer, bufsize, "%s:style=%s:pixelsize=%s",
989 family->name,
990 face->typeface,
991 size);
992 #else
993 snprintf(buffer, bufsize, "-%s-%s-%s-%s-%s-%s-%s-*-*-*-*-*-%s-%s",
994 family->foundry,
995 family->name,
996 face->weight,
997 face->slant,
998 face->setWidth,
999 face->addStyle,
1000 size,
1001 family->registry,
1002 family->encoding);
1003 #endif /* XFT */
1004 wfree(size);
1009 static void
1010 preview(FontPanel *panel)
1012 char buffer[512];
1013 WMFont *font;
1015 getSelectedFont(panel, buffer, sizeof(buffer));
1016 font = WMCreateFont(WMWidgetScreen(panel->win), buffer);
1017 if (font) {
1018 WMSetTextFieldFont(panel->sampleT, font);
1019 WMReleaseFont(font);
1025 static void
1026 familyClick(WMWidget *w, void *data)
1028 WMList *lPtr = (WMList*)w;
1029 WMListItem *item;
1030 #ifdef XFT
1031 Xft_Family *family;
1032 Xft_Typeface *face;
1033 #else
1034 Family *family;
1035 Typeface *face;
1036 #endif
1037 FontPanel *panel = (FontPanel*)data;
1038 WMArrayIterator i;
1039 /* current typeface and size */
1040 char *oface = NULL;
1041 char *osize = NULL;
1042 int facei = -1;
1043 int sizei = -1;
1045 /* must try to keep the same typeface and size for the new family */
1046 item = WMGetListSelectedItem(panel->typLs);
1047 if (item)
1048 oface = wstrdup(item->text);
1050 osize = WMGetTextFieldText(panel->sizT);
1053 item = WMGetListSelectedItem(lPtr);
1054 #ifdef XFT
1055 family = (Xft_Family*)item->clientData;
1056 #else
1057 family = (Family*)item->clientData;
1058 #endif
1060 WMClearList(panel->typLs);
1063 WM_ITERATE_ARRAY(family->typefaces, face, i) {
1064 char buffer[256];
1065 int top=0;
1066 WMListItem *fitem;
1068 #ifdef XFT
1069 strcpy(buffer, face->typeface);
1070 if(strcasecmp(face->typeface, "Roman") == 0)
1071 top = 1;
1072 if(strcasecmp(face->typeface, "Regular") == 0)
1073 top = 1;
1074 #else
1075 if (strcmp(face->weight, "medium") == 0) {
1076 buffer[0] = 0;
1077 } else {
1078 if (*face->weight) {
1079 strcpy(buffer, face->weight);
1080 buffer[0] = toupper(buffer[0]);
1081 strcat(buffer, " ");
1082 } else {
1083 buffer[0] = 0;
1087 if (strcmp(face->slant, "r") == 0) {
1088 strcat(buffer, _("Roman"));
1089 top = 1;
1090 } else if (strcmp(face->slant, "i") == 0) {
1091 strcat(buffer, _("Italic"));
1092 } else if (strcmp(face->slant, "o") == 0) {
1093 strcat(buffer, _("Oblique"));
1094 } else if (strcmp(face->slant, "ri") == 0) {
1095 strcat(buffer, _("Rev Italic"));
1096 } else if (strcmp(face->slant, "ro") == 0) {
1097 strcat(buffer, _("Rev Oblique"));
1098 } else {
1099 strcat(buffer, face->slant);
1102 if (buffer[0] == 0) {
1103 strcpy(buffer, _("Normal"));
1105 #endif
1106 if (top)
1107 fitem = WMInsertListItem(panel->typLs, 0, buffer);
1108 else
1109 fitem = WMAddListItem(panel->typLs, buffer);
1110 fitem->clientData = face;
1113 if (oface) {
1114 facei = WMFindRowOfListItemWithTitle(panel->typLs, oface);
1115 wfree(oface);
1117 if (facei < 0) {
1118 facei = 0;
1120 WMSelectListItem(panel->typLs, facei);
1121 typefaceClick(panel->typLs, panel);
1123 if (osize) {
1124 sizei = WMFindRowOfListItemWithTitle(panel->sizLs, osize);
1126 if (sizei >= 0) {
1127 WMSelectListItem(panel->sizLs, sizei);
1128 sizeClick(panel->sizLs, panel);
1131 if (osize)
1132 wfree(osize);
1135 preview(panel);
1139 static void
1140 typefaceClick(WMWidget *w, void *data)
1142 FontPanel *panel = (FontPanel*)data;
1143 WMListItem *item;
1144 #ifdef XFT
1145 Xft_Typeface *face;
1146 #else
1147 Typeface *face;
1148 #endif
1149 WMArrayIterator i;
1150 char buffer[32];
1152 char *osize = NULL;
1153 int sizei = -1;
1154 void *size;
1156 osize = WMGetTextFieldText(panel->sizT);
1159 item = WMGetListSelectedItem(panel->typLs);
1160 #ifdef XFT
1161 face = (Xft_Typeface*)item->clientData;
1162 #else
1163 face = (Typeface*)item->clientData;
1164 #endif
1166 WMClearList(panel->sizLs);
1168 WM_ITERATE_ARRAY(face->sizes, size, i) {
1169 if ((int)size != 0) {
1170 sprintf(buffer, "%i", (int)size);
1172 WMAddListItem(panel->sizLs, buffer);
1176 if (osize) {
1177 sizei = WMFindRowOfListItemWithTitle(panel->sizLs, osize);
1179 if (sizei < 0) {
1180 sizei = WMFindRowOfListItemWithTitle(panel->sizLs, "12");
1182 if (sizei < 0) {
1183 sizei = 0;
1185 WMSelectListItem(panel->sizLs, sizei);
1186 WMSetListPosition(panel->sizLs, sizei);
1187 sizeClick(panel->sizLs, panel);
1189 if (osize)
1190 wfree(osize);
1192 preview(panel);
1195 static void
1196 sizeClick(WMWidget *w, void *data)
1198 FontPanel *panel = (FontPanel*)data;
1199 WMListItem *item;
1201 item = WMGetListSelectedItem(panel->sizLs);
1202 WMSetTextFieldText(panel->sizT, item->text);
1204 WMSelectTextFieldRange(panel->sizT, wmkrange(0, strlen(item->text)));
1206 preview(panel);
1210 #ifdef XFT
1211 static void
1212 setFontPanelFontName(FontPanel *panel, FcChar8 *family, FcChar8 *style, double size)
1214 int famrow;
1215 int stlrow;
1216 int sz;
1217 char asize[64];
1218 void *vsize;
1219 WMListItem *item;
1220 Xft_Family *fam;
1221 Xft_Typeface *face;
1222 WMArrayIterator i;
1224 famrow = WMFindRowOfListItemWithTitle(panel->famLs, family);
1225 if (famrow < 0 ){
1226 famrow = 0;
1227 return;
1229 WMSelectListItem(panel->famLs, famrow);
1230 WMSetListPosition(panel->famLs, famrow);
1232 WMClearList(panel->typLs);
1234 item = WMGetListSelectedItem(panel->famLs);
1236 fam = (Xft_Family*)item->clientData;
1237 WM_ITERATE_ARRAY(fam->typefaces, face, i) {
1238 char buffer[256];
1239 int top=0;
1240 WMListItem *fitem;
1242 strcpy(buffer, face->typeface);
1243 if(strcasecmp(face->typeface, "Roman") == 0)
1244 top = 1;
1245 if (top)
1246 fitem = WMInsertListItem(panel->typLs, 0, buffer);
1247 else
1248 fitem = WMAddListItem(panel->typLs, buffer);
1249 fitem->clientData = face;
1253 stlrow = WMFindRowOfListItemWithTitle(panel->typLs, style);
1255 if (stlrow < 0) {
1256 stlrow = 0;
1257 return;
1260 WMSelectListItem(panel->typLs, stlrow);
1262 item = WMGetListSelectedItem(panel->typLs);
1264 face = (Xft_Typeface*)item->clientData;
1266 WMClearList(panel->sizLs);
1269 WM_ITERATE_ARRAY(face->sizes, vsize, i) {
1270 char buffer[32];
1271 if ((int)vsize != 0) {
1272 sprintf(buffer, "%i", (int)vsize);
1274 WMAddListItem(panel->sizLs, buffer);
1278 snprintf(asize, sizeof(asize)-1, "%d",(int)(size+0.5));
1280 sz = WMFindRowOfListItemWithTitle(panel->sizLs, asize);
1282 if (sz < 0) {
1283 sz = 4;
1284 return;
1287 WMSelectListItem(panel->sizLs, sz);
1288 sizeClick(panel->sizLs, panel);
1290 return;
1293 #endif