11 typedef struct W_FontPanel
{
42 #define MIN_UPPER_HEIGHT 20
43 #define MIN_LOWER_HEIGHT 140
46 #define MAX_FONTS_TO_RETRIEVE 2000
50 #define MIN_HEIGHT MIN_UPPER_HEIGHT+MIN_LOWER_HEIGHT+70
53 static char *scalableFontSizes[] = {
72 static void arrangeLowerFrame(FontPanel
*panel
);
74 static void familyClick(WMWidget
*, void *);
75 static void typefaceClick(WMWidget
*, void *);
76 static void sizeClick(WMWidget
*, void *);
79 static void listFamilies(WMScreen
*scr
, WMFontPanel
*panel
);
82 splitViewConstrainCallback(WMSplitView
*sPtr
, int divIndex
, int *min
, int *max
)
84 *min
= MIN_UPPER_HEIGHT
;
85 *max
= WMWidgetHeight(sPtr
)-WMGetSplitViewDividerThickness(sPtr
)-MIN_LOWER_HEIGHT
;
90 notificationObserver(void *self
, WMNotification
*notif
)
92 WMFontPanel
*panel
= (WMFontPanel
*)self
;
93 void *object
= WMGetNotificationObject(notif
);
95 if (WMGetNotificationName(notif
) == WMViewSizeDidChangeNotification
) {
96 if (object
== WMWidgetView(panel
->win
)) {
97 int h
= WMWidgetHeight(panel
->win
);
98 int w
= WMWidgetWidth(panel
->win
);
100 WMResizeWidget(panel
->split
, w
, h
-40);
102 WMMoveWidget(panel
->setB
, w
-80, h
-35);
103 WMMoveWidget(panel
->previewB
, w
-160, h
-35);
104 WMMoveWidget(panel
->revertB
, w
-240, h
-35);
105 } else if (object
== WMWidgetView(panel
->upperF
)) {
106 WMResizeWidget(panel
->sampleL
, WMWidgetWidth(panel
->upperF
)-20,
107 WMWidgetHeight(panel
->upperF
)-10);
108 } else if (object
== WMWidgetView(panel
->lowerF
)) {
110 if (WMWidgetHeight(panel
->lowerF
) < MIN_LOWER_HEIGHT
) {
113 h
= WMWidgetHeight(panel
->split
)-MIN_LOWER_HEIGHT
114 - WMGetSplitViewDividerThickness(panel
->split
);
116 WMResizeWidget(panel
->upperF
, WMWidgetWidth(panel
->upperF
), h
);
118 WMMoveWidget(panel
->lowerF
, 0, WMWidgetHeight(panel
->upperF
)
119 + WMGetSplitViewDividerThickness(panel
->split
));
120 WMResizeWidget(panel
->lowerF
, WMWidgetWidth(panel
->lowerF
),
123 arrangeLowerFrame(panel
);
132 familyClick(WMWidget *w, void *data)
134 WMList *lPtr = (WMList*)w;
135 FontPanel *panel = (FontPanel*)data;
143 WMGetFontPanel(WMScreen
*scr
)
146 WMColor
*dark
, *white
;
150 if (scr
->sharedFontPanel
)
151 return scr
->sharedFontPanel
;
154 panel
= wmalloc(sizeof(FontPanel
));
155 memset(panel
, 0, sizeof(FontPanel
));
157 panel
->win
= WMCreateWindow(scr
, "fontPanel");
158 WMResizeWidget(panel
->win
, 320, 370);
159 WMSetWindowMinSize(panel
->win
, MIN_WIDTH
, MIN_HEIGHT
);
160 WMSetViewNotifySizeChanges(WMWidgetView(panel
->win
), True
);
162 panel
->split
= WMCreateSplitView(panel
->win
);
163 WMResizeWidget(panel
->split
, 320, 330);
164 WMSetSplitViewConstrainProc(panel
->split
, splitViewConstrainCallback
);
166 divThickness
= WMGetSplitViewDividerThickness(panel
->split
);
168 panel
->upperF
= WMCreateFrame(panel
->win
);
169 WMSetFrameRelief(panel
->upperF
, WRFlat
);
170 WMSetViewNotifySizeChanges(WMWidgetView(panel
->upperF
), True
);
171 panel
->lowerF
= WMCreateFrame(panel
->win
);
172 WMSetFrameRelief(panel
->lowerF
, WRFlat
);
173 WMSetViewNotifySizeChanges(WMWidgetView(panel
->lowerF
), True
);
175 WMAddSplitViewSubview(panel
->split
, W_VIEW(panel
->upperF
));
176 WMAddSplitViewSubview(panel
->split
, W_VIEW(panel
->lowerF
));
178 WMResizeWidget(panel
->upperF
, 320, 60);
179 WMResizeWidget(panel
->lowerF
, 320, 330-60-divThickness
);
180 WMMoveWidget(panel
->lowerF
, 0, 60+divThickness
);
182 white
= WMWhiteColor(scr
);
183 dark
= WMDarkGrayColor(scr
);
185 panel
->sampleL
= WMCreateLabel(panel
->upperF
);
186 WMResizeWidget(panel
->sampleL
, 300, 50);
187 WMMoveWidget(panel
->sampleL
, 10, 10);
188 WMSetWidgetBackgroundColor(panel
->sampleL
, white
);
189 WMSetLabelRelief(panel
->sampleL
, WRSunken
);
190 WMSetLabelText(panel
->sampleL
, "It is not yet completed!!!");
192 font
= WMBoldSystemFontOfSize(scr
, 12);
194 panel
->famL
= WMCreateLabel(panel
->lowerF
);
195 WMSetWidgetBackgroundColor(panel
->famL
, dark
);
196 WMSetLabelText(panel
->famL
, "Family");
197 WMSetLabelFont(panel
->famL
, font
);
198 WMSetLabelTextColor(panel
->famL
, white
);
199 WMSetLabelRelief(panel
->famL
, WRSunken
);
200 WMSetLabelTextAlignment(panel
->famL
, WACenter
);
202 panel
->famLs
= WMCreateList(panel
->lowerF
);
203 WMSetListAction(panel
->famLs
, familyClick
, panel
);
205 panel
->typL
= WMCreateLabel(panel
->lowerF
);
206 WMSetWidgetBackgroundColor(panel
->typL
, dark
);
207 WMSetLabelText(panel
->typL
, "Typeface");
208 WMSetLabelFont(panel
->typL
, font
);
209 WMSetLabelTextColor(panel
->typL
, white
);
210 WMSetLabelRelief(panel
->typL
, WRSunken
);
211 WMSetLabelTextAlignment(panel
->typL
, WACenter
);
213 panel
->typLs
= WMCreateList(panel
->lowerF
);
214 WMSetListAction(panel
->typLs
, typefaceClick
, panel
);
216 panel
->sizL
= WMCreateLabel(panel
->lowerF
);
217 WMSetWidgetBackgroundColor(panel
->sizL
, dark
);
218 WMSetLabelText(panel
->sizL
, "Size");
219 WMSetLabelFont(panel
->sizL
, font
);
220 WMSetLabelTextColor(panel
->sizL
, white
);
221 WMSetLabelRelief(panel
->sizL
, WRSunken
);
222 WMSetLabelTextAlignment(panel
->sizL
, WACenter
);
224 panel
->sizT
= WMCreateTextField(panel
->lowerF
);
226 panel
->sizLs
= WMCreateList(panel
->lowerF
);
227 WMSetListAction(panel
->sizLs
, sizeClick
, panel
);
230 WMReleaseColor(white
);
231 WMReleaseColor(dark
);
233 panel
->encF
= WMCreateFrame(panel
->lowerF
);
234 WMSetFrameTitle(panel
->encF
, "Encoding");
235 WMResizeWidget(panel
->encF
, 130, 50);
237 panel
->encP
= WMCreatePopUpButton(panel
->encF
);
238 WMMoveWidget(panel
->encP
, 10, 20);
239 WMResizeWidget(panel
->encP
, 112, 20);
241 WMMapSubwidgets(panel
->encF
);
243 panel
->xlfdF
= WMCreateFrame(panel
->lowerF
);
244 WMSetFrameTitle(panel
->xlfdF
, "Xtra Long Font Description");
246 panel
->xlfdT
= WMCreateTextField(panel
->xlfdF
);
247 WMMoveWidget(panel
->xlfdT
, 10, 20);
249 WMMapSubwidgets(panel
->xlfdF
);
251 arrangeLowerFrame(panel
);
253 panel
->setB
= WMCreateCommandButton(panel
->win
);
254 WMResizeWidget(panel
->setB
, 70, 24);
255 WMMoveWidget(panel
->setB
, 240, 335);
256 WMSetButtonText(panel
->setB
, "Set");
258 panel
->previewB
= WMCreateCommandButton(panel
->win
);
259 WMResizeWidget(panel
->previewB
, 70, 24);
260 WMMoveWidget(panel
->previewB
, 160, 335);
261 WMSetButtonText(panel
->previewB
, "Preview");
263 panel
->revertB
= WMCreateCommandButton(panel
->win
);
264 WMResizeWidget(panel
->revertB
, 70, 24);
265 WMMoveWidget(panel
->revertB
, 80, 335);
266 WMSetButtonText(panel
->revertB
, "Revert");
268 WMRealizeWidget(panel
->win
);
270 WMMapSubwidgets(panel
->upperF
);
271 WMMapSubwidgets(panel
->lowerF
);
272 WMMapSubwidgets(panel
->split
);
273 WMMapSubwidgets(panel
->win
);
275 scr
->sharedFontPanel
= panel
;
278 /* register notification observers */
279 WMAddNotificationObserver(notificationObserver
, panel
,
280 WMViewSizeDidChangeNotification
,
281 WMWidgetView(panel
->win
));
282 WMAddNotificationObserver(notificationObserver
, panel
,
283 WMViewSizeDidChangeNotification
,
284 WMWidgetView(panel
->upperF
));
285 WMAddNotificationObserver(notificationObserver
, panel
,
286 WMViewSizeDidChangeNotification
,
287 WMWidgetView(panel
->lowerF
));
290 listFamilies(scr
, panel
);
298 WMFreeFontPanel(WMFontPanel
*panel
)
300 if (panel
== WMWidgetScreen(panel
->win
)->sharedFontPanel
) {
301 WMWidgetScreen(panel
->win
)->sharedFontPanel
= NULL
;
303 WMRemoveNotificationObserver(panel
);
304 WMUnmapWidget(panel
->win
);
305 WMDestroyWidget(panel
->win
);
311 WMShowFontPanel(WMFontPanel
*panel
)
313 WMMapWidget(panel
->win
);
318 WMHideFontPanel(WMFontPanel
*panel
)
320 WMUnmapWidget(panel
->win
);
325 WMSetFontPanelFont(WMFontPanel
*panel
, WMFont
*font
)
331 WMGetFontPanelFont(WMFontPanel
*panel
)
338 WMGetFontPanelFontName(WMFontPanel
*panel
)
347 arrangeLowerFrame(FontPanel
*panel
)
349 int width
= WMWidgetWidth(panel
->lowerF
) - 55 - 30;
350 int height
= WMWidgetHeight(panel
->lowerF
);
351 int oheight
= 330-60-WMGetSplitViewDividerThickness(panel
->split
);
355 height
-= 20 + 3 + 10 + 50;
356 oheight
-= 20 + 3 + 10 + 50;
358 fw
= (125*width
) / 235;
359 tw
= (110*width
) / 235;
362 h
= (174*height
) / oheight
;
364 WMMoveWidget(panel
->famL
, 10, 0);
365 WMResizeWidget(panel
->famL
, fw
, 20);
367 WMMoveWidget(panel
->famLs
, 10, 23);
368 WMResizeWidget(panel
->famLs
, fw
, h
);
370 WMMoveWidget(panel
->typL
, 10+fw
+3, 0);
371 WMResizeWidget(panel
->typL
, tw
, 20);
373 WMMoveWidget(panel
->typLs
, 10+fw
+3, 23);
374 WMResizeWidget(panel
->typLs
, tw
, h
);
376 WMMoveWidget(panel
->sizL
, 10+fw
+3+tw
+3, 0);
377 WMResizeWidget(panel
->sizL
, sw
+4, 20);
379 WMMoveWidget(panel
->sizT
, 10+fw
+3+tw
+3, 23);
380 WMResizeWidget(panel
->sizT
, sw
+4, 20);
382 WMMoveWidget(panel
->sizLs
, 10+fw
+3+tw
+3, 46);
383 WMResizeWidget(panel
->sizLs
, sw
+4, h
-22);
385 WMMoveWidget(panel
->encF
, 10, WMWidgetHeight(panel
->lowerF
)-55);
387 WMMoveWidget(panel
->xlfdF
, 145, WMWidgetHeight(panel
->lowerF
)-55);
388 WMResizeWidget(panel
->xlfdF
, WMWidgetWidth(panel
->lowerF
)-155, 50);
390 WMResizeWidget(panel
->xlfdT
, WMWidgetWidth(panel
->lowerF
)-155-20, 20);
396 #define ALL_FONTS_MASK "-*-*-*-*-*-*-*-*-*-*-*-*-*-*"
413 #define NUM_FIELDS 14
419 parseFont(char *font
, char values
[NUM_FIELDS
][256])
423 char buffer
[256], *bptr
;
427 ptr
++; /* skip first - */
432 strcpy(values
[part
], buffer
);
441 strcpy(values
[part
], buffer
);
449 isXLFD(char *font
, int *length_ret
)
460 return c
==NUM_FIELDS
;
473 char showSetWidth
; /* when duplicated */
474 char showAddStyle
; /* when duplicated */
484 char *registry
, *encoding
;
486 char showFoundry
; /* when duplicated */
487 char showRegistry
; /* when duplicated */
495 addTypefaceToFamily(Family
*family
, char fontFields
[NUM_FIELDS
][256])
500 if (family
->typefaces
) {
501 for (i
= 0; i
< WMGetBagItemCount(family
->typefaces
); i
++) {
504 face
= WMGetFromBag(family
->typefaces
, i
);
506 if (strcmp(face
->weight
, fontFields
[WEIGHT
]) != 0) {
509 if (strcmp(face
->slant
, fontFields
[SLANT
]) != 0) {
513 size
= atoi(fontFields
[POINT_SIZE
]);
514 WMPutInBag(face
->sizes
, (void*)size
);
519 family
->typefaces
= WMCreateBag(4);
522 face
= wmalloc(sizeof(Typeface
));
523 memset(face
, 0, sizeof(Typeface
));
525 face
->weight
= wstrdup(fontFields
[WEIGHT
]);
526 face
->slant
= wstrdup(fontFields
[SLANT
]);
527 face
->setWidth
= wstrdup(fontFields
[SETWIDTH
]);
528 face
->addStyle
= wstrdup(fontFields
[ADD_STYLE
]);
530 face
->sizes
= WMCreateBag(4);
531 WMPutInBag(face
->sizes
, (void*)atoi(fontFields
[POINT_SIZE
]));
533 WMPutInBag(family
->typefaces
, face
);
539 * families (same family name) (Hashtable of family -> bag)
540 * registries (same family but different registries)
545 addFontToFamily(WMHashTable
*families
, char fontFields
[NUM_FIELDS
][256])
551 family
= WMHashGet(families
, fontFields
[FAMILY
]);
554 /* look for same encoding/registry and foundry */
555 for (i
= 0; i
< WMGetBagItemCount(family
); i
++) {
558 fam
= WMGetFromBag(family
, i
);
560 enc
= (strcmp(fam
->encoding
, fontFields
[ENCODING
]) == 0);
561 reg
= (strcmp(fam
->registry
, fontFields
[REGISTRY
]) == 0);
562 found
= (strcmp(fam
->foundry
, fontFields
[FOUNDRY
]) == 0);
564 if (enc
&& reg
&& found
) {
565 addTypefaceToFamily(fam
, fontFields
);
569 /* look for same encoding/registry */
570 for (i
= 0; i
< WMGetBagItemCount(family
); i
++) {
573 fam
= WMGetFromBag(family
, i
);
575 enc
= (strcmp(fam
->encoding
, fontFields
[ENCODING
]) == 0);
576 reg
= (strcmp(fam
->registry
, fontFields
[REGISTRY
]) == 0);
579 /* has the same encoding, but the foundry is different */
580 fam
->showRegistry
= 1;
582 fam
= wmalloc(sizeof(Family
));
583 memset(fam
, 0, sizeof(Family
));
585 fam
->name
= wstrdup(fontFields
[FAMILY
]);
586 fam
->foundry
= wstrdup(fontFields
[FOUNDRY
]);
587 fam
->registry
= wstrdup(fontFields
[REGISTRY
]);
588 fam
->encoding
= wstrdup(fontFields
[ENCODING
]);
589 fam
->showRegistry
= 1;
591 addTypefaceToFamily(fam
, fontFields
);
593 WMPutInBag(family
, fam
);
598 /* look for same foundry */
599 for (i
= 0; i
< WMGetBagItemCount(family
); i
++) {
602 fam
= WMGetFromBag(family
, i
);
604 found
= (strcmp(fam
->foundry
, fontFields
[FOUNDRY
]) == 0);
607 /* has the same foundry, but encoding is different */
608 fam
->showFoundry
= 1;
610 fam
= wmalloc(sizeof(Family
));
611 memset(fam
, 0, sizeof(Family
));
613 fam
->name
= wstrdup(fontFields
[FAMILY
]);
614 fam
->foundry
= wstrdup(fontFields
[FOUNDRY
]);
615 fam
->registry
= wstrdup(fontFields
[REGISTRY
]);
616 fam
->encoding
= wstrdup(fontFields
[ENCODING
]);
617 fam
->showFoundry
= 1;
619 addTypefaceToFamily(fam
, fontFields
);
621 WMPutInBag(family
, fam
);
626 /* foundry and encoding do not match anything known */
627 fam
= wmalloc(sizeof(Family
));
628 memset(fam
, 0, sizeof(Family
));
630 fam
->name
= wstrdup(fontFields
[FAMILY
]);
631 fam
->foundry
= wstrdup(fontFields
[FOUNDRY
]);
632 fam
->registry
= wstrdup(fontFields
[REGISTRY
]);
633 fam
->encoding
= wstrdup(fontFields
[ENCODING
]);
634 fam
->showFoundry
= 1;
635 fam
->showRegistry
= 1;
637 addTypefaceToFamily(fam
, fontFields
);
639 WMPutInBag(family
, fam
);
644 family
= WMCreateBag(8);
646 fam
= wmalloc(sizeof(Family
));
647 memset(fam
, 0, sizeof(Family
));
649 fam
->name
= wstrdup(fontFields
[FAMILY
]);
650 fam
->foundry
= wstrdup(fontFields
[FOUNDRY
]);
651 fam
->registry
= wstrdup(fontFields
[REGISTRY
]);
652 fam
->encoding
= wstrdup(fontFields
[ENCODING
]);
654 addTypefaceToFamily(fam
, fontFields
);
656 WMPutInBag(family
, fam
);
658 WMHashInsert(families
, fam
->name
, family
);
664 listFamilies(WMScreen
*scr
, WMFontPanel
*panel
)
669 WMHashTable
*families
= WMCreateHashTable(WMStringHashCallbacks
);
670 char fields
[NUM_FIELDS
][256];
671 WMHashEnumerator enumer
;
674 fontList
= XListFonts(scr
->display
, ALL_FONTS_MASK
, MAX_FONTS_TO_RETRIEVE
,
677 WMRunAlertPanel(scr
, panel
->win
, "Error",
678 "Could not retrieve font list", "OK", NULL
, NULL
);
682 for (i
= 0; i
< count
; i
++) {
685 if (!isXLFD(fontList
[i
], &fname_len
)) {
689 if (fname_len
> 255) {
690 wwarning("font name %s is longer than 256, which is invalid.",
695 if (!parseFont(fontList
[i
], fields
)) {
699 addFontToFamily(families
, fields
);
702 enumer
= WMEnumerateHashTable(families
);
704 while ((bag
= WMNextHashEnumeratorItem(&enumer
))) {
710 for (i
= 0; i
< WMGetBagItemCount(bag
); i
++) {
711 fam
= WMGetFromBag(bag
, i
);
713 strcpy(buffer
, fam
->name
);
715 if (fam
->showFoundry
) {
717 strcat(buffer
, fam
->foundry
);
720 if (fam
->showRegistry
) {
721 strcat(buffer
, " (");
722 strcat(buffer
, fam
->registry
);
724 strcat(buffer
, fam
->encoding
);
727 item
= WMAddSortedListItem(panel
->famLs
, buffer
);
729 item
->clientData
= fam
;
734 WMFreeHashTable(families
);
740 familyClick(WMWidget
*w
, void *data
)
742 WMList
*lPtr
= (WMList
*)w
;
745 FontPanel
*panel
= (FontPanel
*)data
;
749 item
= WMGetListSelectedItem(lPtr
);
750 family
= (Family
*)item
->clientData
;
752 WMClearList(panel
->typLs
);
755 for (i
= 0; i
< WMGetBagItemCount(family
->typefaces
); i
++) {
758 face
= WMGetFromBag(family
->typefaces
, i
);
760 strcpy(buffer
, face
->weight
);
762 strcat(buffer
, face
->slant
);
764 WMAddListItem(panel
->typLs
, buffer
);
771 typefaceClick(WMWidget
*w
, void *data
)
773 WMList
*lPtr
= (WMList
*)w
;
774 FontPanel
*panel
= (FontPanel
*)data
;
779 sizeClick(WMWidget
*w
, void *data
)
781 WMList
*lPtr
= (WMList
*)w
;
782 FontPanel
*panel
= (FontPanel
*)data
;