1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26
27 #include <Xm/XmAll.h>
28 #include <Xm/XmP.h>
29
30 #include <X11/Xft/Xft.h>
31 #include <fontconfig/fontconfig.h>
32
33 #include "nedit_malloc.h"
34 #include "misc.h"
35
36 #include "fontsel.h"
37
38 #define PREVIEW_STR "ABCDEFGHIJabcdefghijklmn[](){}.:,;-_$%&/\"''"
39
40 #define MONOSPACE_ONLY_DEFAULT 1
41
42 static XftColor default_fg_color;
43 static Pixel default_bg_pix;
44 static int default_colors_set =
0;
45
46 typedef struct FontSelector {
47 FcPattern *filter;
48 FcFontSet *list;
49
50 Widget pattern;
51 Widget fontlist;
52 Widget size;
53 Widget preview;
54 Widget name;
55
56 XftFont *font;
57 XftFont *bold;
58 XftFont *italic;
59 XftDraw *draw;
60 XftColor color;
61 Boolean enable_bg;
62
63 int selected_item;
64 int end;
65 int cancel;
66 } FontSelector;
67
68 static void UpdatePreview(FontSelector *sel,
const char *fontStr)
69 {
70 Display *dp = XtDisplay(sel->preview);
71 XftFont *font = XftFontOpenName(dp, DefaultScreen(dp), fontStr);
72 if(!font) {
73 return;
74 }
75 if(sel->font) {
76 XftFontClose(dp, sel->font);
77 }
78
79 size_t fontStrLen = strlen(fontStr);
80 char *boldFontStr = FontNameAddAttribute(fontStr, fontStrLen,
81 "weight",
"bold");
82 char *italicFontStr = FontNameAddAttribute(fontStr, fontStrLen,
83 "slant",
"italic");
84
85 XftFont *boldFont = XftFontOpenName(dp, DefaultScreen(dp), boldFontStr);
86 XftFont *italicFont = XftFontOpenName(dp, DefaultScreen(dp), italicFontStr);
87
88 NEditFree(boldFontStr);
89 NEditFree(italicFontStr);
90
91 if(sel->bold) {
92 XftFontClose(dp, sel->bold);
93 }
94 if(sel->italic) {
95 XftFontClose(dp, sel->italic);
96 }
97
98 sel->font = font;
99 sel->bold = boldFont;
100 sel->italic = italicFont;
101 }
102
103 static void InitXftDraw(FontSelector *sel)
104 {
105 if(sel->draw) {
106 return;
107 }
108
109 XWindowAttributes attributes;
110 XGetWindowAttributes(XtDisplay(sel->preview), XtWindow(sel->preview), &attributes);
111 Screen *screen = XtScreen(sel->preview);
112 Visual *visual = screen->root_visual;
113
114 Cardinal depth;
115 Colormap colormap;
116 XtVaGetValues(sel->preview, XtNdepth, &depth, XtNcolormap, &colormap,
NULL);
117
118 for(
int i=
0;i<screen->ndepths;i++) {
119 Depth d = screen->depths[i];
120 if(d.depth == depth) {
121 visual = d.visuals;
122 break;
123 }
124 }
125
126 Display *dp = XtDisplay(sel->preview);
127 sel->draw = XftDrawCreate(
128 dp,
129 XtWindow(sel->preview),
130 visual,
131 colormap);
132
133 Pixel previewFg;
134 XtVaGetValues(sel->preview, XmNforeground, &previewFg,
NULL);
135
136 XColor xcolor;
137 memset(&xcolor,
0,
sizeof(XColor));
138 xcolor.pixel = previewFg;
139 XQueryColor(XtDisplay(sel->preview), sel->preview->core.colormap, &xcolor);
140
141 sel->color.pixel = previewFg;
142 sel->color.color.red = xcolor.red;
143 sel->color.color.green = xcolor.green;
144 sel->color.color.blue = xcolor.blue;
145 sel->color.color.alpha = 0xFFFF;
146
147 if(default_colors_set) {
148 sel->color = default_fg_color;
149 sel->enable_bg = True;
150 XtVaSetValues(sel->preview, XmNbackground, default_bg_pix,
NULL);
151 }
152 }
153
154 static void exposeFontPreview(Widget w, FontSelector *sel, XtPointer data)
155 {
156 InitXftDraw(sel);
157 if(!sel->font) {
158 return;
159 }
160
161 Dimension width, height;
162 XtVaGetValues(
163 w,
164 XmNwidth,
165 &width,
166 XmNheight,
167 &height,
168 NULL);
169
170 XClearWindow(XtDisplay(w), XtWindow(w));
171
172 int fontHeight = sel->font->ascent + sel->font->descent;
173
174 int boldHeight =
0;
175 int italicHeight =
0;
176 int extraSpace =
0;
177 if(sel->bold) {
178 boldHeight = sel->bold->ascent + sel->bold->descent;
179 extraSpace +=
5;
180 }
181 if(sel->italic) {
182 italicHeight = sel->italic->ascent + sel->italic->descent;
183 extraSpace +=
5;
184 }
185
186 int space = height - fontHeight - boldHeight - italicHeight - extraSpace;
187
188 int y = space/
2;
189 XftDrawStringUtf8(
190 sel->draw,
191 &sel->color,
192 sel->font,
193 10,
194 y + sel->font->ascent,
195 (
unsigned char*)
PREVIEW_STR,
196 sizeof(
PREVIEW_STR)-
1);
197 y += fontHeight +
5;
198
199 if(sel->bold) {
200 XftDrawStringUtf8(
201 sel->draw,
202 &sel->color,
203 sel->bold,
204 10,
205 y + sel->bold->ascent,
206 (
unsigned char*)
PREVIEW_STR,
207 sizeof(
PREVIEW_STR)-
1);
208 y += boldHeight +
5;
209 }
210 if(sel->italic) {
211 XftDrawStringUtf8(
212 sel->draw,
213 &sel->color,
214 sel->italic,
215 10,
216 y + sel->italic->ascent,
217 (
unsigned char*)
PREVIEW_STR,
218 sizeof(
PREVIEW_STR)-
1);
219 }
220 }
221
222 static int compare_font(
const void *d1,
const void *d2) {
223 const FcPattern *f1 = *((
const FcPattern**)d1);
224 const FcPattern *f2 = *((
const FcPattern**)d2);
225
226 FcChar8 *name1 =
NULL;
227 FcChar8 *name2 =
NULL;
228 FcPatternGetString(f1,
FC_FULLNAME,
0, &name1);
229 FcPatternGetString(f2,
FC_FULLNAME,
0, &name2);
230
231 FcChar8 *family1 =
NULL;
232 FcChar8 *family2 =
NULL;
233 FcPatternGetString(f1,
FC_FAMILY,
0, &family1);
234 FcPatternGetString(f2,
FC_FAMILY,
0, &family2);
235
236 if(name1 && name2) {
237 return strcmp((
char*)name1, (
char*)name2);
238 }
else if(family1 && family2) {
239 return strcmp((
char*)family1, (
char*)family2);
240 }
else {
241 return 0;
242 }
243 }
244
245 static char* CreateFontName(FcChar8 *family, FcChar8 *style) {
246 size_t flen = family ? strlen((
char*)family) :
0;
247 size_t slen = style ? strlen((
char*)style) :
0;
248
249 size_t len = flen + slen +
4;
250 char *name = NEditMalloc(len);
251
252 if(!family) {
253 snprintf(name, len,
"-");
254 }
else if(style) {
255 snprintf(name, len,
"%s %s", (
char*)family, (
char*)style);
256 }
else {
257 snprintf(name, len,
"%s", (
char*)family);
258 }
259 return name;
260 }
261
262 static void UpdateFontList(FontSelector *sel,
const char *pattern)
263 {
264 XmStringTable items;
265 FcChar8 *name;
266 FcChar8 *family;
267 FcChar8 *style;
268 int nfonts, nfound;
269
270 if(pattern) {
271 if(sel->filter) {
272 FcPatternDestroy(sel->filter);
273 sel->filter =
NULL;
274 }
275 sel->filter = FcNameParse((FcChar8*)pattern);
276 }
277 if(!sel->filter) {
278 sel->filter = FcPatternCreate();
279 }
280
281 FcObjectSet *os = FcObjectSetCreate();
282 FcObjectSetAdd(os,
FC_FAMILY);
283 FcObjectSetAdd(os,
FC_STYLE);
284 FcObjectSetAdd(os,
FC_FULLNAME);
285 FcObjectSetAdd(os,
FC_SCALABLE);
286 FcObjectSetAdd(os,
FC_SPACING);
287
288 if(sel->list) {
289 FcFontSetDestroy(sel->list);
290 }
291 sel->list = FcFontList(
NULL, sel->filter, os);
292 FcObjectSetDestroy(os);
293
294 nfonts = sel->list->nfont;
295 nfound =
0;
296
297
298 qsort(sel->list->fonts, nfonts,
sizeof(FcPattern*), compare_font);
299
300 items = NEditCalloc(sel->list->nfont,
sizeof(XmString));
301 for(
int i=
0;i<nfonts;i++) {
302 FcBool scalable =
0;
303 FcPatternGetBool(sel->list->fonts[i],
FC_SCALABLE,
0, &scalable);
304 int spacing =
0;
305 FcPatternGetInteger(sel->list->fonts[i],
FC_SPACING,
0, &spacing);
306
307 name =
NULL;
308 FcPatternGetString(sel->list->fonts[i],
FC_FULLNAME,
0, &name);
309
310 family =
NULL;
311 FcPatternGetString(sel->list->fonts[i],
FC_FAMILY,
0, &family);
312
313 style =
NULL;
314 FcPatternGetString(sel->list->fonts[i],
FC_STYLE,
0, &style);
315
316 if(name) {
317 items[nfound] = XmStringCreateSimple((
char*)name);
318 }
else {
319 name = (FcChar8*)CreateFontName(family, style);
320 items[nfound] = XmStringCreateSimple((
char*)name);
321 NEditFree(name);
322 }
323
324 nfound++;
325 }
326
327 XtVaSetValues(sel->fontlist, XmNitems, items, XmNitemCount, nfound,
NULL);
328 for(
int i=
0;i<nfound;i++) {
329 XmStringFree(items[i]);
330 }
331 NEditFree(items);
332 }
333
334 static void MatchFont(
const char *name, XmString *retName, XmString *retSize)
335 {
336 *retName =
NULL;
337 *retSize =
NULL;
338
339 FcPattern* pat = FcNameParse((
const FcChar8*)name);
340
341 FcConfigSubstitute(
NULL, pat, FcMatchPattern);
342 FcDefaultSubstitute(pat);
343 FcResult result;
344 FcPattern* font = FcFontMatch(
NULL, pat, &result);
345 if(font) {
346 FcChar8* nameStr =
NULL;
347 FcChar8* familyStr =
NULL;
348 double fontSize =
0;
349 if (FcPatternGetString(font,
FC_FULLNAME,
0, &nameStr) == FcResultMatch) {
350 *retName = XmStringCreateSimple((
char*)nameStr);
351 }
else if (FcPatternGetString(font,
FC_FAMILY,
0, &familyStr) == FcResultMatch) {
352 FcChar8 *styleStr =
NULL;
353 FcPatternGetString(font,
FC_STYLE,
0, &styleStr);
354 if(styleStr) {
355 char *fontName = CreateFontName(familyStr, styleStr);
356 *retName = XmStringCreateSimple(fontName);
357 NEditFree(fontName);
358 }
359 }
360 if(FcPatternGetDouble(font,
FC_SIZE,
0, &fontSize) == FcResultMatch) {
361 char buf[
8];
362 snprintf(buf,
8,
"%d", (
int)fontSize);
363 *retSize = XmStringCreateSimple(buf);
364 }
365 FcPatternDestroy(font);
366 }
367 FcPatternDestroy(pat);
368 }
369
370 static void CreateSizeList(Widget w)
371 {
372 XmStringTable items = NEditCalloc(
30,
sizeof(XmString));
373 char buf[
8];
374 for(
int i=
0;i<
30;i++) {
375 snprintf(buf,
8,
"%d", i+
5);
376 items[i] = XmStringCreateSimple(buf);
377 }
378
379 XtVaSetValues(w, XmNitems, items, XmNitemCount,
30,
NULL);
380 for(
int i=
0;i<
30;i++) {
381 XmStringFree(items[i]);
382 }
383 NEditFree(items);
384 }
385
386 static char* GetFontString(FontSelector *sel)
387 {
388 XmStringTable table =
NULL;
389 int count =
0;
390 int i = sel->selected_item -
1;
391 char *font =
NULL;
392 char *style =
NULL;
393 char *size =
NULL;
394 size_t fontLen, styleLen, sizeLen, outLen;
395 char *out;
396
397 if(i <
0)
return NULL;
398
399 FcPatternGetString(sel->list->fonts[i],
FC_FAMILY,
0, (FcChar8**)&font);
400 FcPatternGetString(sel->list->fonts[i],
FC_STYLE,
0, (FcChar8**)&style);
401
402 XtVaGetValues(
403 sel->size,
404 XmNselectedItems,
405 &table,
406 XmNselectedItemCount,
407 &count,
408 NULL);
409 if(count >
0) {
410 XmStringGetLtoR(table[
0], XmFONTLIST_DEFAULT_TAG, &size);
411 }
412
413 if(style && !strcmp(style,
"Regular")) {
414 style =
NULL;
415 }
416
417 fontLen = font ? strlen(font) :
0;
418 styleLen = style ? strlen(style) :
0;
419 sizeLen = size ? strlen(size) :
0;
420
421 if(style && size) {
422 outLen = fontLen + styleLen + sizeLen +
16;
423 out = XtMalloc(outLen);
424 snprintf(out, outLen,
"%s:style=%s:size=%s", font, style, size);
425 XmTextSetString(sel->name, out);
426 XtFree(size);
427 return out;
428 }
else if(size) {
429 outLen = fontLen + sizeLen +
16;
430 out = XtMalloc(outLen);
431 snprintf(out, outLen,
"%s:size=%s", font, size);
432 XmTextSetString(sel->name, out);
433 XtFree(size);
434 return out;
435 }
else {
436 return font;
437 }
438 }
439
440 static void UpdateFontName(FontSelector *sel)
441 {
442 char *fontStr = GetFontString(sel);
443 if(fontStr) {
444 UpdatePreview(sel, fontStr);
445 exposeFontPreview(sel->preview, sel,
NULL);
446 XmTextSetString(sel->name, fontStr);
447 XtFree(fontStr);
448 }
449 }
450
451 static void fontlist_callback(Widget w, FontSelector *sel, XmListCallbackStruct *cb)
452 {
453 sel->selected_item = cb->item_position;
454 UpdateFontName(sel);
455 }
456
457 static void SetMonospaceFilter(FontSelector *sel, Boolean on)
458 {
459 if(sel->filter) {
460 FcPatternDestroy(sel->filter);
461 }
462 sel->filter = FcPatternCreate();
463 if(on) {
464 FcPatternAddInteger(sel->filter,
FC_SPACING,
FC_MONO);
465 }
466 }
467
468 void fontlist_toggle_monospace(Widget w, FontSelector *sel, XmToggleButtonCallbackStruct *cb)
469 {
470 SetMonospaceFilter(sel, cb->set);
471 UpdateFontList(sel,
NULL);
472 }
473
474 void size_callback (Widget w, FontSelector *sel, XtPointer data)
475 {
476 UpdateFontName(sel);
477 }
478
479 static void ok_callback(Widget w, FontSelector *sel, XtPointer data)
480 {
481 sel->end =
1;
482 }
483
484 static void cancel_callback(Widget w, FontSelector *sel, XtPointer data)
485 {
486 sel->end =
1;
487 sel->cancel =
1;
488 }
489
490 static void FreeFontSelector(FontSelector *sel)
491 {
492 FcPatternDestroy(sel->filter);
493 Display *dp = XtDisplay(sel->preview);
494
495 XftDrawDestroy(sel->draw);
496 if(sel->font) {
497 XftFontClose(dp, sel->font);
498 }
499 if(sel->bold) {
500 XftFontClose(dp, sel->bold);
501 }
502 if(sel->italic) {
503 XftFontClose(dp, sel->italic);
504 }
505 if(sel->list) {
506 FcFontSetDestroy(sel->list);
507 }
508
509 NEditFree(sel);
510 }
511
512 char *FontSel(Widget parent,
const char *curFont)
513 {
514 Arg args[
32];
515 int n =
0;
516 XmString str;
517
518 FontSelector *sel = NEditMalloc(
sizeof(FontSelector));
519 memset(sel,
0,
sizeof(FontSelector));
520
521 Widget dialog = CreateDialogShell(parent,
"Font Selector", args,
0);
522 AddMotifCloseCallback(dialog, (XtCallbackProc)cancel_callback, sel);
523 Widget form = XmCreateForm(dialog,
"form", args,
0);
524
525
526 n =
0;
527 str = XmStringCreateSimple(
"OK");
528 XtSetArg(args[n], XmNtopOffset,
2); n++;
529 XtSetArg(args[n], XmNleftOffset,
5); n++;
530 XtSetArg(args[n], XmNbottomOffset,
5); n++;
531 XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
532 XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
533 XtSetArg(args[n], XmNlabelString, str); n++;
534 Widget okButton = XmCreatePushButton(form,
"button", args, n);
535 XtManageChild(okButton);
536 XmStringFree(str);
537 XtAddCallback(
538 okButton,
539 XmNactivateCallback,
540 (XtCallbackProc)ok_callback,
541 sel);
542
543
544 n =
0;
545 str = XmStringCreateSimple(
"Cancel");
546 XtSetArg(args[n], XmNtopOffset,
2); n++;
547 XtSetArg(args[n], XmNrightOffset,
5); n++;
548 XtSetArg(args[n], XmNbottomOffset,
5); n++;
549 XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
550 XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
551 XtSetArg(args[n], XmNlabelString, str); n++;
552 Widget cancelButton = XmCreatePushButton(form,
"button", args, n);
553 XtManageChild(cancelButton);
554 XmStringFree(str);
555 XtAddCallback(
556 cancelButton,
557 XmNactivateCallback,
558 (XtCallbackProc)cancel_callback,
559 sel);
560
561
562 n =
0;
563 XtSetArg(args[n], XmNbottomOffset,
2); n++;
564 XtSetArg(args[n], XmNleftOffset,
5); n++;
565 XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
566 XtSetArg(args[n], XmNleftOffset,
5); n++;
567 XtSetArg(args[n], XmNrightOffset,
5); n++;
568 XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
569 XtSetArg(args[n], XmNwidth,
400); n++;
570 XtSetArg(args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
571 XtSetArg(args[n], XmNbottomWidget, okButton); n++;
572 sel->name = XmCreateText(form,
"fcname_textfield", args, n);
573 XtManageChild(sel->name);
574
575
576 n =
0;
577 str = XmStringCreateSimple(
"Font name:");
578 XtSetArg(args[n], XmNbottomOffset,
2); n++;
579 XtSetArg(args[n], XmNleftOffset,
5); n++;
580 XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
581 XtSetArg(args[n], XmNlabelString, str); n++;
582 XtSetArg(args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
583 XtSetArg(args[n], XmNbottomWidget, sel->name); n++;
584 Widget fontNameLabel = XmCreateLabel(form,
"label", args, n);
585 XtManageChild(fontNameLabel);
586 XmStringFree(str);
587
588
589 n =
0;
590 XtSetArg(args[n], XmNbottomOffset,
2); n++;
591 XtSetArg(args[n], XmNleftOffset,
5); n++;
592 XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
593 XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
594 XtSetArg(args[n], XmNrightOffset,
5); n++;
595 XtSetArg(args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
596 XtSetArg(args[n], XmNbottomWidget, fontNameLabel); n++;
597 XtSetArg(args[n], XmNshadowType, XmSHADOW_IN); n++;
598 XtSetArg(args[n], XmNmarginWidth,
3); n++;
599 XtSetArg(args[n], XmNmarginHeight,
3); n++;
600 Widget previewFrame = XmCreateFrame(form,
"frame", args, n);
601 XtManageChild(previewFrame);
602
603 n =
0;
604 sel->preview = XmCreateDrawingArea(previewFrame,
"fontpreview", args, n);
605 Dimension w, h;
606 XtMakeResizeRequest(sel->preview,
450,
180, &w, &h);
607 XtManageChild(sel->preview);
608
609 XtAddCallback(
610 sel->preview,
611 XmNexposeCallback,
612 (XtCallbackProc)exposeFontPreview,
613 sel);
614
615
616 n =
0;
617 str = XmStringCreateSimple(
"Show only non-proportional fonts");
618 XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
619 XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
620 XtSetArg(args[n], XmNtopOffset,
5); n++;
621 XtSetArg(args[n], XmNleftOffset,
5); n++;
622 XtSetArg(args[n], XmNlabelString, str); n++;
623 XtSetArg(args[n], XmNset,
MONOSPACE_ONLY_DEFAULT); n++;
624 Widget toggleMonospace = XmCreateToggleButton(form,
"toggle_monospace", args, n);
625 XtManageChild(toggleMonospace);
626 XmStringFree(str);
627 XtAddCallback(
628 toggleMonospace,
629 XmNvalueChangedCallback,
630 (XtCallbackProc)fontlist_toggle_monospace,
631 sel);
632
633
634 n =
0;
635 str = XmStringCreateSimple(
"Font:");
636 XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
637 XtSetArg(args[n], XmNtopWidget, toggleMonospace); n++;
638 XtSetArg(args[n], XmNtopOffset,
5); n++;
639 XtSetArg(args[n], XmNleftOffset,
5); n++;
640 XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
641 XtSetArg(args[n], XmNlabelString, str); n++;
642 Widget fontListLabel = XmCreateLabel(form,
"label", args, n);
643 XtManageChild(fontListLabel);
644 XmStringFree(str);
645
646 n =
0;
647 str = XmStringCreateSimple(
"Size:");
648 XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
649 XtSetArg(args[n], XmNtopWidget, toggleMonospace); n++;
650 XtSetArg(args[n], XmNtopOffset,
5); n++;
651 XtSetArg(args[n], XmNrightOffset,
5); n++;
652 XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
653 XtSetArg(args[n], XmNlabelString, str); n++;
654 Widget fontSizeLabel = XmCreateLabel(form,
"label", args, n);
655 XtManageChild(fontSizeLabel);
656 XmStringFree(str);
657
658
659 n =
0;
660 XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
661 XtSetArg(args[n], XmNtopWidget, fontSizeLabel); n++;
662 XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
663 XtSetArg(args[n], XmNrightOffset,
5); n++;
664 XtSetArg(args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
665 XtSetArg(args[n], XmNbottomWidget, previewFrame); n++;
666 XtSetArg(args[n], XmNleftOffset,
2); n++;
667 XtSetArg(args[n], XmNbottomOffset,
2); n++;
668 XtSetArg(args[n], XmNtopOffset,
2); n++;
669 sel->size = XmCreateScrolledList(form,
"sizelist", args, n);
670 CreateSizeList(sel->size);
671 XtAddCallback (sel->size, XmNbrowseSelectionCallback, (XtCallbackProc)size_callback, sel);
672 XmListSelectPos(sel->size,
6,
0);
673 XtManageChild(sel->size);
674
675 Dimension szListWidth;
676 XtVaGetValues(sel->size, XmNwidth, &szListWidth,
NULL);
677 if(szListWidth >
0 && szListWidth <
40) {
678 XtVaSetValues(sel->size, XmNwidth,
40,
NULL);
679 }
680
681
682 n =
0;
683 XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
684 XtSetArg(args[n], XmNtopWidget, fontListLabel); n++;
685 XtSetArg(args[n], XmNtopOffset,
2); n++;
686 XtSetArg(args[n], XmNbottomOffset,
2); n++;
687 XtSetArg(args[n], XmNleftOffset,
5); n++;
688 XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
689 XtSetArg(args[n], XmNrightAttachment, XmATTACH_WIDGET); n++;
690 XtSetArg(args[n], XmNrightWidget, sel->size); n++;
691 XtSetArg(args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
692 XtSetArg(args[n], XmNbottomWidget, previewFrame); n++;
693 XtSetArg(args[n], XmNvisibleItemCount,
10); n++;
694 sel->fontlist = XmCreateScrolledList(form,
"fontlist", args, n);
695 AddMouseWheelSupport(sel->fontlist);
696 XtManageChild(sel->fontlist);
697 XtAddCallback(
698 sel->fontlist,
699 XmNbrowseSelectionCallback,
700 (XtCallbackProc)fontlist_callback,
701 sel);
702
703
704 UpdatePreview(sel, curFont);
705
706 SetMonospaceFilter(sel,
MONOSPACE_ONLY_DEFAULT);
707 UpdateFontList(sel,
NULL);
708 XmString fontSelection;
709 XmString sizeSelection;
710 MatchFont(curFont, &fontSelection, &sizeSelection);
711 if(fontSelection) {
712 XmListSelectItem(sel->fontlist, fontSelection,
0);
713 XmStringFree(fontSelection);
714 int *pos;
715 int selcount =
0;
716 if(XmListGetSelectedPos(sel->fontlist, &pos, &selcount)) {
717 sel->selected_item = pos[
0];
718 XtFree((
void*)pos);
719 }
720 }
721 if(sizeSelection) {
722 XmListSelectItem(sel->size, sizeSelection,
0);
723 XmStringFree(sizeSelection);
724 }
725
726 ManageDialogCenteredOnPointer(form);
727
728 XtAppContext app = XtWidgetToApplicationContext(dialog);
729 while(!sel->end && !XtAppGetExitFlag(app)) {
730 XEvent event;
731 XtAppNextEvent(app, &event);
732 XtDispatchEvent(&event);
733 }
734
735 XtDestroyWidget(dialog);
736 char *retStr =
NULL;
737 if(!sel->cancel) {
738 retStr = GetFontString(sel);
739 }
740 if(!retStr) {
741 retStr = NEditStrdup(curFont);
742 }
743
744 FreeFontSelector(sel);
745 return retStr;
746 }
747
748
749 char* FontNameAddAttribute(
750 const char *name,
751 size_t len,
752 const char *attribute,
753 const char *value)
754 {
755 size_t attributelen = strlen(attribute);
756 size_t valuelen = strlen(value);
757 size_t newlen = len + attributelen + valuelen +
4;
758 char *attr = NEditMalloc(attributelen+
3);
759 char *newfont = NEditMalloc(newlen);
760 char *oldattr;
761 int i = len;
762 int b =
0;
763 int e =
0;
764
765
766 attr[
0] =
':';
767 memcpy(attr+
1, attribute, attributelen);
768 attr[attributelen+
1] =
'=';
769 attr[attributelen+
2] =
'\0';
770 oldattr = strstr(name, attr);
771 if(oldattr) {
772 b = (
int)(oldattr - name)+
1;
773 e = len;
774 for(i=b;i<len;i++) {
775 if(name[i] ==
':') {
776 e = i;
777 break;
778 }
779 }
780 }
781 NEditFree(attr);
782
783 if(b < len) {
784 if(b >
0 && name[b-
1] ==
':') b--;
785 snprintf(newfont, newlen,
"%.*s%.*s:%s=%s", b, name, (
int)(len-e), name+e, attribute, value);
786 }
else {
787 snprintf(newfont, newlen,
"%s:%s=%s", name, attribute, value);
788 }
789
790 return newfont;
791 }
792
793 void FontSelSetColors(XftColor fg, Pixel bg) {
794 default_fg_color = fg;
795 default_bg_pix = bg;
796 default_colors_set =
1;
797 }
798