replaced linked lists with WMBag, added progress indicator
[wmaker-crm.git] / WINGs / wfontpanel.c
blob02c0e842742c8fe6d01945645fcf0d22ab242d7f
5 #include "WINGsP.h"
7 #include <strings.h>
10 typedef struct W_FontPanel {
11 WMWindow *win;
13 WMFrame *upperF;
14 WMLabel *sampleL;
16 WMSplitView *split;
18 WMFrame *lowerF;
19 WMLabel *famL;
20 WMList *famLs;
21 WMLabel *typL;
22 WMList *typLs;
23 WMLabel *sizL;
24 WMTextField *sizT;
25 WMList *sizLs;
27 WMFrame *xlfdF;
28 WMTextField *xlfdT;
30 WMFrame *encF;
31 WMPopUpButton *encP;
33 WMButton *revertB;
34 WMButton *previewB;
35 WMButton *setB;
37 proplist_t fdb;
38 } FontPanel;
41 #define MIN_UPPER_HEIGHT 20
42 #define MIN_LOWER_HEIGHT 140
45 #define MAX_FONTS_TO_RETRIEVE 2000
48 #define MIN_WIDTH 250
49 #define MIN_HEIGHT MIN_UPPER_HEIGHT+MIN_LOWER_HEIGHT+70
52 static char *scalableFontSizes[] = {
53 "8",
54 "10",
55 "11",
56 "12",
57 "14",
58 "16",
59 "18",
60 "20",
61 "24",
62 "36",
63 "48",
64 "64"
66 */
71 static void arrangeLowerFrame(FontPanel *panel);
74 static void listFamilies(WMScreen *scr, WMFontPanel *panel);
76 static void
77 splitViewConstrainCallback(WMSplitView *sPtr, int divIndex, int *min, int *max)
79 *min = MIN_UPPER_HEIGHT;
80 *max = WMWidgetHeight(sPtr)-WMGetSplitViewDividerThickness(sPtr)-MIN_LOWER_HEIGHT;
84 static void
85 notificationObserver(void *self, WMNotification *notif)
87 WMFontPanel *panel = (WMFontPanel*)self;
88 void *object = WMGetNotificationObject(notif);
90 if (WMGetNotificationName(notif) == WMViewSizeDidChangeNotification) {
91 if (object == WMWidgetView(panel->win)) {
92 int h = WMWidgetHeight(panel->win);
93 int w = WMWidgetWidth(panel->win);
95 WMResizeWidget(panel->split, w, h-40);
97 WMMoveWidget(panel->setB, w-80, h-35);
98 WMMoveWidget(panel->previewB, w-160, h-35);
99 WMMoveWidget(panel->revertB, w-240, h-35);
100 } else if (object == WMWidgetView(panel->upperF)) {
101 WMResizeWidget(panel->sampleL, WMWidgetWidth(panel->upperF)-20,
102 WMWidgetHeight(panel->upperF)-10);
103 } else if (object == WMWidgetView(panel->lowerF)) {
105 if (WMWidgetHeight(panel->lowerF) < MIN_LOWER_HEIGHT) {
106 int h;
108 h = WMWidgetHeight(panel->split)-MIN_LOWER_HEIGHT
109 - WMGetSplitViewDividerThickness(panel->split);
111 WMResizeWidget(panel->upperF, WMWidgetWidth(panel->upperF), h);
113 WMMoveWidget(panel->lowerF, 0, WMWidgetHeight(panel->upperF)
114 + WMGetSplitViewDividerThickness(panel->split));
115 WMResizeWidget(panel->lowerF, WMWidgetWidth(panel->lowerF),
116 MIN_LOWER_HEIGHT);
117 } else {
118 arrangeLowerFrame(panel);
126 static void
127 familyClick(WMWidget *w, void *data)
129 WMList *lPtr = (WMList*)w;
130 FontPanel *panel = (FontPanel*)data;
137 WMFontPanel*
138 WMGetFontPanel(WMScreen *scr)
140 FontPanel *panel;
141 WMColor *dark, *white;
142 WMFont *font;
143 int divThickness;
145 if (scr->sharedFontPanel)
146 return scr->sharedFontPanel;
149 panel = wmalloc(sizeof(FontPanel));
150 memset(panel, 0, sizeof(FontPanel));
152 panel->win = WMCreateWindow(scr, "fontPanel");
153 WMResizeWidget(panel->win, 320, 370);
154 WMSetWindowMinSize(panel->win, MIN_WIDTH, MIN_HEIGHT);
155 WMSetViewNotifySizeChanges(WMWidgetView(panel->win), True);
157 panel->split = WMCreateSplitView(panel->win);
158 WMResizeWidget(panel->split, 320, 330);
159 WMSetSplitViewConstrainProc(panel->split, splitViewConstrainCallback);
161 divThickness = WMGetSplitViewDividerThickness(panel->split);
163 panel->upperF = WMCreateFrame(panel->win);
164 WMSetFrameRelief(panel->upperF, WRFlat);
165 WMSetViewNotifySizeChanges(WMWidgetView(panel->upperF), True);
166 panel->lowerF = WMCreateFrame(panel->win);
167 WMSetFrameRelief(panel->lowerF, WRFlat);
168 WMSetViewNotifySizeChanges(WMWidgetView(panel->lowerF), True);
170 WMAddSplitViewSubview(panel->split, W_VIEW(panel->upperF));
171 WMAddSplitViewSubview(panel->split, W_VIEW(panel->lowerF));
173 WMResizeWidget(panel->upperF, 320, 60);
174 WMResizeWidget(panel->lowerF, 320, 330-60-divThickness);
175 WMMoveWidget(panel->lowerF, 0, 60+divThickness);
177 white = WMWhiteColor(scr);
178 dark = WMDarkGrayColor(scr);
180 panel->sampleL = WMCreateLabel(panel->upperF);
181 WMResizeWidget(panel->sampleL, 300, 50);
182 WMMoveWidget(panel->sampleL, 10, 10);
183 WMSetWidgetBackgroundColor(panel->sampleL, white);
184 WMSetLabelRelief(panel->sampleL, WRSunken);
185 WMSetLabelText(panel->sampleL, "It is not yet completed!!!");
187 font = WMBoldSystemFontOfSize(scr, 12);
189 panel->famL = WMCreateLabel(panel->lowerF);
190 WMSetWidgetBackgroundColor(panel->famL, dark);
191 WMSetLabelText(panel->famL, "Family");
192 WMSetLabelFont(panel->famL, font);
193 WMSetLabelTextColor(panel->famL, white);
194 WMSetLabelRelief(panel->famL, WRSunken);
195 WMSetLabelTextAlignment(panel->famL, WACenter);
197 panel->famLs = WMCreateList(panel->lowerF);
199 panel->typL = WMCreateLabel(panel->lowerF);
200 WMSetWidgetBackgroundColor(panel->typL, dark);
201 WMSetLabelText(panel->typL, "Typeface");
202 WMSetLabelFont(panel->typL, font);
203 WMSetLabelTextColor(panel->typL, white);
204 WMSetLabelRelief(panel->typL, WRSunken);
205 WMSetLabelTextAlignment(panel->typL, WACenter);
207 panel->typLs = WMCreateList(panel->lowerF);
209 panel->sizL = WMCreateLabel(panel->lowerF);
210 WMSetWidgetBackgroundColor(panel->sizL, dark);
211 WMSetLabelText(panel->sizL, "Size");
212 WMSetLabelFont(panel->sizL, font);
213 WMSetLabelTextColor(panel->sizL, white);
214 WMSetLabelRelief(panel->sizL, WRSunken);
215 WMSetLabelTextAlignment(panel->sizL, WACenter);
217 panel->sizT = WMCreateTextField(panel->lowerF);
219 panel->sizLs = WMCreateList(panel->lowerF);
221 WMReleaseFont(font);
222 WMReleaseColor(white);
223 WMReleaseColor(dark);
225 panel->encF = WMCreateFrame(panel->lowerF);
226 WMSetFrameTitle(panel->encF, "Encoding");
227 WMResizeWidget(panel->encF, 130, 50);
229 panel->encP = WMCreatePopUpButton(panel->encF);
230 WMMoveWidget(panel->encP, 10, 20);
231 WMResizeWidget(panel->encP, 112, 20);
233 WMMapSubwidgets(panel->encF);
235 panel->xlfdF = WMCreateFrame(panel->lowerF);
236 WMSetFrameTitle(panel->xlfdF, "Xtra Long Font Description");
238 panel->xlfdT = WMCreateTextField(panel->xlfdF);
239 WMMoveWidget(panel->xlfdT, 10, 20);
241 WMMapSubwidgets(panel->xlfdF);
243 arrangeLowerFrame(panel);
245 panel->setB = WMCreateCommandButton(panel->win);
246 WMResizeWidget(panel->setB, 70, 24);
247 WMMoveWidget(panel->setB, 240, 335);
248 WMSetButtonText(panel->setB, "Set");
250 panel->previewB = WMCreateCommandButton(panel->win);
251 WMResizeWidget(panel->previewB, 70, 24);
252 WMMoveWidget(panel->previewB, 160, 335);
253 WMSetButtonText(panel->previewB, "Preview");
255 panel->revertB = WMCreateCommandButton(panel->win);
256 WMResizeWidget(panel->revertB, 70, 24);
257 WMMoveWidget(panel->revertB, 80, 335);
258 WMSetButtonText(panel->revertB, "Revert");
260 WMRealizeWidget(panel->win);
262 WMMapSubwidgets(panel->upperF);
263 WMMapSubwidgets(panel->lowerF);
264 WMMapSubwidgets(panel->split);
265 WMMapSubwidgets(panel->win);
267 scr->sharedFontPanel = panel;
270 /* register notification observers */
271 WMAddNotificationObserver(notificationObserver, panel,
272 WMViewSizeDidChangeNotification,
273 WMWidgetView(panel->win));
274 WMAddNotificationObserver(notificationObserver, panel,
275 WMViewSizeDidChangeNotification,
276 WMWidgetView(panel->upperF));
277 WMAddNotificationObserver(notificationObserver, panel,
278 WMViewSizeDidChangeNotification,
279 WMWidgetView(panel->lowerF));
282 listFamilies(scr, panel);
285 return panel;
289 void
290 WMFreeFontPanel(WMFontPanel *panel)
292 if (panel == WMWidgetScreen(panel->win)->sharedFontPanel) {
293 WMWidgetScreen(panel->win)->sharedFontPanel = NULL;
295 WMRemoveNotificationObserver(panel);
296 WMUnmapWidget(panel->win);
297 WMDestroyWidget(panel->win);
298 free(panel);
302 void
303 WMShowFontPanel(WMFontPanel *panel)
305 WMMapWidget(panel->win);
308 void
309 WMHideFontPanel(WMFontPanel *panel)
311 WMUnmapWidget(panel->win);
315 void
316 WMSetFontPanelFont(WMFontPanel *panel, WMFont *font)
321 WMFont*
322 WMGetFontPanelFont(WMFontPanel *panel)
324 return NULL;
328 char*
329 WMGetFontPanelFontName(WMFontPanel *panel)
331 return NULL;
337 static void
338 arrangeLowerFrame(FontPanel *panel)
340 int width = WMWidgetWidth(panel->lowerF) - 55 - 30;
341 int height = WMWidgetHeight(panel->lowerF);
342 int oheight = 330-60-WMGetSplitViewDividerThickness(panel->split);
343 int fw, tw, sw;
344 int h;
346 height -= 20 + 3 + 10 + 50;
347 oheight -= 20 + 3 + 10 + 50;
349 fw = (125*width) / 235;
350 tw = (110*width) / 235;
351 sw = 55;
353 h = (174*height) / oheight;
355 WMMoveWidget(panel->famL, 10, 0);
356 WMResizeWidget(panel->famL, fw, 20);
358 WMMoveWidget(panel->famLs, 10, 23);
359 WMResizeWidget(panel->famLs, fw, h);
361 WMMoveWidget(panel->typL, 10+fw+3, 0);
362 WMResizeWidget(panel->typL, tw, 20);
364 WMMoveWidget(panel->typLs, 10+fw+3, 23);
365 WMResizeWidget(panel->typLs, tw, h);
367 WMMoveWidget(panel->sizL, 10+fw+3+tw+3, 0);
368 WMResizeWidget(panel->sizL, sw+4, 20);
370 WMMoveWidget(panel->sizT, 10+fw+3+tw+3, 23);
371 WMResizeWidget(panel->sizT, sw+4, 20);
373 WMMoveWidget(panel->sizLs, 10+fw+3+tw+3, 46);
374 WMResizeWidget(panel->sizLs, sw+4, h-22);
376 WMMoveWidget(panel->encF, 10, WMWidgetHeight(panel->lowerF)-55);
378 WMMoveWidget(panel->xlfdF, 145, WMWidgetHeight(panel->lowerF)-55);
379 WMResizeWidget(panel->xlfdF, WMWidgetWidth(panel->lowerF)-155, 50);
381 WMResizeWidget(panel->xlfdT, WMWidgetWidth(panel->lowerF)-155-20, 20);
387 #define ALL_FONTS_MASK "-*-*-*-*-*-*-*-*-*-*-*-*-*-*"
389 #define FOUNDRY 0
390 #define FAMILY 1
391 #define WEIGHT 2
392 #define SLANT 3
393 #define SETWIDTH 4
394 #define ADD_STYLE 5
395 #define PIXEL_SIZE 6
396 #define POINT_SIZE 7
397 #define RES_X 8
398 #define RES_Y 9
399 #define SPACING 10
400 #define AV_WIDTH 11
401 #define REGISTRY 12
402 #define ENCODING 13
404 #define NUM_FIELDS 14
407 #if 1
409 static Bool
410 parseFont(char *font, char values[NUM_FIELDS][256])
412 char *ptr;
413 int part;
414 char buffer[256], *bptr;
416 part = FOUNDRY;
417 ptr = font;
418 ptr++; /* skip first - */
419 bptr = buffer;
420 while (*ptr) {
421 if (*ptr == '-') {
422 *bptr = 0;
423 strcpy(values[part], buffer);
424 bptr = buffer;
425 part++;
426 } else {
427 *bptr++ = *ptr;
429 ptr++;
431 *bptr = 0;
432 strcpy(values[part], buffer);
434 return True;
439 static int
440 isXLFD(char *font, int *length_ret)
442 int c = 0;
444 *length_ret = 0;
445 while (*font) {
446 (*length_ret)++;
447 if (*font++ == '-')
448 c++;
451 return c==NUM_FIELDS;
457 typedef struct {
458 char *weight;
459 char *slant;
461 char *setWidth;
462 char *addStyle;
464 char showWeight; /* not Medium */
465 char showSlant; /* not R */
466 char showSetWidth; /* when duplicated */
467 char showAddStyle; /* when duplicated */
468 } Typeface;
471 typedef struct {
472 char *name;
474 char *foundry;
475 char *registry, *encoding;
477 char showFoundry; /* when duplicated */
478 char showRegistry; /* when duplicated */
480 WMBag *typefaces;
481 } Family;
485 static void
486 addTypefaceToFamily(Family *family, char fontFields[NUM_FIELDS][256])
494 * families (same family name) (Hashtable of family -> bag)
495 * registries (same family but different registries)
499 static void
500 addFontToFamily(WMHashTable *families, char fontFields[NUM_FIELDS][256])
502 int i;
503 Family *fam;
504 WMBag *family;
506 family = WMHashGet(families, fontFields[FAMILY]);
508 if (family) {
509 /* look for same encoding/registry and foundry */
510 for (i = 0; i < WMGetBagItemCount(family); i++) {
511 int enc, reg, found;
513 fam = WMGetFromBag(family, i);
515 enc = (strcmp(fam->encoding, fontFields[ENCODING]) == 0);
516 reg = (strcmp(fam->registry, fontFields[REGISTRY]) == 0);
517 found = (strcmp(fam->foundry, fontFields[FOUNDRY]) == 0);
519 if (enc && reg && found) {
520 addTypefaceToFamily(fam, fontFields);
521 return;
524 /* look for same encoding/registry */
525 for (i = 0; i < WMGetBagItemCount(family); i++) {
526 int enc, reg;
528 fam = WMGetFromBag(family, i);
530 enc = (strcmp(fam->encoding, fontFields[ENCODING]) == 0);
531 reg = (strcmp(fam->registry, fontFields[REGISTRY]) == 0);
533 if (enc && reg) {
534 /* has the same encoding, but the foundry is different */
535 fam->showRegistry = 1;
537 fam = wmalloc(sizeof(Family));
538 memset(fam, 0, sizeof(Family));
540 fam->name = wstrdup(fontFields[FAMILY]);
541 fam->foundry = wstrdup(fontFields[FOUNDRY]);
542 fam->registry = wstrdup(fontFields[REGISTRY]);
543 fam->encoding = wstrdup(fontFields[ENCODING]);
544 fam->showRegistry = 1;
546 addTypefaceToFamily(fam, fontFields);
548 WMPutInBag(family, fam);
550 return;
553 /* look for same foundry */
554 for (i = 0; i < WMGetBagItemCount(family); i++) {
555 int found;
557 fam = WMGetFromBag(family, i);
559 found = (strcmp(fam->foundry, fontFields[FOUNDRY]) == 0);
561 if (found) {
562 /* has the same foundry, but encoding is different */
563 fam->showFoundry = 1;
565 fam = wmalloc(sizeof(Family));
566 memset(fam, 0, sizeof(Family));
568 fam->name = wstrdup(fontFields[FAMILY]);
569 fam->foundry = wstrdup(fontFields[FOUNDRY]);
570 fam->registry = wstrdup(fontFields[REGISTRY]);
571 fam->encoding = wstrdup(fontFields[ENCODING]);
572 fam->showFoundry = 1;
574 addTypefaceToFamily(fam, fontFields);
576 WMPutInBag(family, fam);
578 return;
581 /* foundry and encoding do not match anything known */
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]);
590 addTypefaceToFamily(fam, fontFields);
592 WMPutInBag(family, fam);
594 return;
597 family = WMCreateBag(8);
599 fam = wmalloc(sizeof(Family));
600 memset(fam, 0, sizeof(Family));
602 fam->name = wstrdup(fontFields[FAMILY]);
603 fam->foundry = wstrdup(fontFields[FOUNDRY]);
604 fam->registry = wstrdup(fontFields[REGISTRY]);
605 fam->encoding = wstrdup(fontFields[ENCODING]);
607 addTypefaceToFamily(fam, fontFields);
609 WMPutInBag(family, fam);
611 WMHashInsert(families, fam->name, family);
616 static void
617 listFamilies(WMScreen *scr, WMFontPanel *panel)
619 char **fontList;
620 int count;
621 int i;
622 WMHashTable *families = WMCreateHashTable(WMStringHashCallbacks);
623 char fields[NUM_FIELDS][256];
625 fontList = XListFonts(scr->display, ALL_FONTS_MASK, MAX_FONTS_TO_RETRIEVE,
626 &count);
627 if (!fontList) {
628 WMRunAlertPanel(scr, panel->win, "Error",
629 "Could not retrieve font list", "OK", NULL, NULL);
630 return;
633 for (i = 0; i < count; i++) {
634 int fname_len;
636 if (!isXLFD(fontList[i], &fname_len)) {
637 *fontList[i] = '\0';
638 continue;
640 if (fname_len > 255) {
641 wwarning("font name %s is longer than 256, which is invalid.",
642 fontList[i]);
643 *fontList[i] = '\0';
644 continue;
646 if (!parseFont(fontList[i], fields)) {
647 *fontList[i] = '\0';
648 continue;
650 addFontToFamily(families, (char**)fields);
656 #endif