1 /*
2
3 Copyright (c) 1985-1989 X Consortium
4
5 Permission is hereby granted, free of charge, to any person obtaining
6 a copy of this software and associated documentation files (the
7 "Software"), to deal in the Software without restriction, including
8 without limitation the rights to use, copy, modify, merge, publish,
9 distribute, sublicense, and/or sell copies of the Software, and to
10 permit persons to whom the Software is furnished to do so, subject to
11 the following conditions:
12
13 The above copyright notice and this permission notice shall be included
14 in all copies or substantial portions of the Software.
15
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 OTHER DEALINGS IN THE SOFTWARE.
23
24 Except as contained in this notice, the name of the X Consortium shall
25 not be used in advertising or otherwise to promote the sale, use or
26 other dealings in this Software without prior written authorization
27 from the X Consortium.
28
29 Author: Ralph R. Swick, DEC/MIT Project Athena
30 one weekend in November, 1989
31 Modified: Mark Leisher <mleisher@crl.nmsu.edu> to deal with UCS sample text.
32 */
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <X11/Intrinsic.h>
37 #include <X11/StringDefs.h>
38 #include <X11/Xatom.h>
39 #include <X11/Xaw/AsciiText.h>
40 #include <X11/Xaw/Box.h>
41 #include <X11/Xaw/Cardinals.h>
42 #include <X11/Xaw/Command.h>
43 #include <X11/Xaw/Form.h>
44 #include <X11/Xaw/MenuButton.h>
45 #include <X11/Xaw/Paned.h>
46 #include <X11/Xaw/SimpleMenu.h>
47 #include <X11/Xaw/SmeBSB.h>
48 #include <X11/Xaw/Toggle.h>
49 #include <X11/Xaw/Viewport.h>
50 #include <X11/Xmu/Atoms.h>
51 #include <X11/Xmu/StdSel.h>
52 #include <X11/Xfuncs.h>
53 #include "ULabel.h"
54
55 #define MIN_APP_DEFAULTS_VERSION 1
56 #define FIELD_COUNT 14
57 #define DELIM '-'
58
59 /* number of font names to parse in each background iteration */
60 #ifndef PARSE_QUANTUM
61 #define PARSE_QUANTUM 25
62 #endif
63
64 #define NZ NULL,ZERO
65 #define BACKGROUND 10
66
67 void GetFontNames(XtPointer closure);
68 Boolean Matches(String pattern, String fontName, Boolean fields[], int *maxfields);
69 Boolean DoWorkPiece(XtPointer closure);
70 void Quit(Widget w, XtPointer closure, XtPointer callData);
71 void OwnSelection(Widget w, XtPointer closure, XtPointer callData);
72 void SelectField(Widget w, XtPointer closure, XtPointer callData);
73 void ParseFontNames(XtPointer closure);
74 void SortFields(XtPointer closure);
75 void FixScalables(XtPointer closure);
76 void MakeFieldMenu(XtPointer closure);
77 void SelectValue(Widget w, XtPointer closure, XtPointer callData);
78 void AnyValue(Widget w, XtPointer closure, XtPointer callData);
79 void EnableOtherValues(Widget w, XtPointer closure, XtPointer callData);
80 void EnableMenu(XtPointer closure);
81 void SetCurrentFont(XtPointer closure);
82 void QuitAction(Widget w, XEvent *event, String *params, Cardinal *num_params);
83
84 static XtActionsRec xfontsel_actions[] = {
85 {"Quit", QuitAction}
86 };
87
88 static Atom wm_delete_window;
89
90 Boolean IsXLFDFontName(String fontName);
91
92 typedef void (*XtProc)(XtPointer closure);
93
94 static struct _appRes {
95 int app_defaults_version;
96 Cursor cursor;
97 String pattern;
98 String pixelSizeList;
99 String pointSizeList;
100 Boolean print_on_quit;
101 String sample_text;
102 String sample_text16;
103 String sample_textUCS;
104 Boolean scaled_fonts;
105 } AppRes;
106
107 #define DEFAULTPATTERN "-*-*-*-*-*-*-*-*-*-*-*-*-*-*"
108
109 static XtResource resources[] = {
110 { "cursor", "Cursor", XtRCursor, sizeof(Cursor),
111 XtOffsetOf( struct _appRes, cursor ),
112 XtRImmediate, NULL },
113 { "pattern", "Pattern", XtRString, sizeof(String),
114 XtOffsetOf( struct _appRes, pattern ),
115 XtRString, (XtPointer)DEFAULTPATTERN },
116 { "pixelSizeList", "PixelSizeList", XtRString, sizeof(String),
117 XtOffsetOf( struct _appRes, pixelSizeList ),
118 XtRString, (XtPointer)"" },
119 { "pointSizeList", "PointSizeList", XtRString, sizeof(String),
120 XtOffsetOf( struct _appRes, pointSizeList ),
121 XtRString, (XtPointer)"" },
122 { "printOnQuit", "PrintOnQuit", XtRBoolean, sizeof(Boolean),
123 XtOffsetOf( struct _appRes, print_on_quit ),
124 XtRImmediate, (XtPointer)False },
125 { "appDefaultsVersion", "AppDefaultsVersion", XtRInt, sizeof(int),
126 XtOffsetOf( struct _appRes, app_defaults_version ),
127 XtRImmediate, (XtPointer)0 },
128 { "sampleText", "Text", XtRString, sizeof(String),
129 XtOffsetOf( struct _appRes, sample_text ),
130 XtRString, (XtPointer)"" },
131 { "sampleText16", "Text16", XtRString, sizeof(String),
132 XtOffsetOf( struct _appRes, sample_text16 ),
133 XtRString, (XtPointer)"" },
134 { "sampleTextUCS", "TextUCS", XtRString, sizeof(String),
135 XtOffsetOf( struct _appRes, sample_textUCS ),
136 XtRString, (XtPointer)"" },
137 { "scaledFonts", "ScaledFonts", XtRBoolean, sizeof(Boolean),
138 XtOffsetOf( struct _appRes, scaled_fonts ),
139 XtRImmediate, (XtPointer)False },
140 };
141
142 static XrmOptionDescRec options[] = {
143 {"-pattern", "pattern", XrmoptionSepArg, NULL},
144 {"-print", "printOnQuit", XrmoptionNoArg, "True"},
145 {"-sample", "sampleText", XrmoptionSepArg, NULL},
146 {"-sample16", "sampleText16", XrmoptionSepArg, NULL},
147 {"-sampleUCS", "sampleTextUCS",XrmoptionSepArg, NULL},
148 {"-scaled", "scaledFonts", XrmoptionNoArg, "True"},
149 };
150
Syntax(const char * call)151 static void Syntax(const char *call)
152 {
153 fprintf (stderr, "usage: %s [-options ...] -fn font\n\n%s\n", call,
154 "where options include:\n"
155 " -display dpy X server to contact\n"
156 " -geometry geom size and location of window\n"
157 " -pattern fontspec font name pattern to match against\n"
158 " -print print selected font name on exit\n"
159 " -sample string sample text to use for 1-byte fonts\n"
160 " -sample16 string sample text to use for 2-byte fonts\n"
161 " -sampleUCS string sample text to use for ISO10646 fonts\n"
162 " -scaled use scaled instances of fonts\n");
163 exit (1);
164 }
165
166
167 typedef struct FieldValue FieldValue;
168 struct FieldValue {
169 int field;
170 String string;
171 Widget menu_item;
172 int count; /* of fonts */
173 int allocated;
174 int *font;
175 Boolean enable;
176 };
177
178
179 typedef struct FieldValueList FieldValueList;
180 struct FieldValueList {
181 int count; /* of values */
182 int allocated;
183 Boolean show_unselectable;
184 FieldValue value[1]; /* really [allocated] */
185 };
186
187
188 typedef struct FontValues FontValues;
189 struct FontValues {
190 int value_index[FIELD_COUNT];
191 };
192
193
194 typedef struct FieldMenuRec FieldMenuRec;
195 struct FieldMenuRec {
196 int field;
197 Widget button;
198 };
199
200
201 typedef struct Choice Choice;
202 struct Choice {
203 Choice *prev;
204 FieldValue *value;
205 };
206
207
208 static XtResource menuResources[] = {
209 { "showUnselectable", "ShowUnselectable", XtRBoolean, sizeof(Boolean),
210 XtOffsetOf( FieldValueList, show_unselectable ),
211 XtRImmediate, (XtPointer)True },
212 };
213
214
215 typedef enum {ValidateCurrentField, SkipCurrentField} ValidateAction;
216
217 static void EnableAllItems(int field);
218 static void EnableRemainingItems(ValidateAction current_field_action);
219 static void FlushXqueue(Display *dpy);
220 static void MarkInvalidFonts(Boolean *set, FieldValue *val);
221 static void ScheduleWork(XtProc proc, XtPointer closure, int priority);
222 static void SetCurrentFontCount(void);
223 static void SetNoFonts(void);
224 static void SetParsingFontCount(int count);
225
226 static XtAppContext appCtx;
227 static int numFonts;
228 static int numBadFonts;
229 static FontValues *fonts;
230 static int *scaledFonts;
231 static int numScaledFonts;
232 static FieldValueList *fieldValues[FIELD_COUNT];
233 static FontValues currentFont;
234 static int matchingFontCount;
235 static Boolean anyDisabled = False;
236 static Widget ownButton;
237 static Widget fieldBox;
238 static Widget countLabel;
239 static Widget currentFontName;
240 static String currentFontNameString;
241 static int currentFontNameSize;
242 static Widget sampleText;
243 static int textEncoding = -1;
244 static XFontStruct *sampleFont = NULL;
245 static Boolean *fontInSet;
246 static Choice *choiceList = NULL;
247 static int enabledMenuIndex;
248 static Boolean patternFieldSpecified[FIELD_COUNT]; /* = 0 */
249
250 int
main(int argc,char ** argv)251 main(int argc, char **argv)
252 {
253 Widget topLevel, pane;
254
255 XtSetLanguageProc(NULL, (XtLanguageProc) NULL, NULL);
256
257 topLevel = XtAppInitialize(&appCtx, "XFontSel", options, XtNumber(options),
258 &argc, argv, NULL, NULL, 0);
259
260 if (argc != 1) Syntax(argv[0]);
261
262 XtAppAddActions(appCtx, xfontsel_actions, XtNumber(xfontsel_actions));
263 XtOverrideTranslations
264 (topLevel, XtParseTranslationTable ("<Message>WM_PROTOCOLS: Quit()"));
265
266 XtGetApplicationResources( topLevel, (XtPointer)&AppRes,
267 resources, XtNumber(resources), NZ );
268 if (AppRes.app_defaults_version < MIN_APP_DEFAULTS_VERSION) {
269 XrmDatabase rdb = XtDatabase(XtDisplay(topLevel));
270 XtWarning( "app-defaults file not properly installed." );
271 XrmPutLineResource( &rdb,
272 "*sampleText*UCSLabel:XFontSel app-defaults file not properly installed;\\n\
273 see 'xfontsel' manual page."
274 );
275 }
276
277 ScheduleWork(GetFontNames, (XtPointer)XtDisplay(topLevel), 0);
278
279 pane = XtCreateManagedWidget("pane",panedWidgetClass,topLevel,NZ);
280 {
281 Widget commandBox, /* fieldBox, currentFontName,*/ viewPort;
282
283 commandBox = XtCreateManagedWidget("commandBox",formWidgetClass,pane,NZ);
284 {
285 Widget quitButton /*, ownButton , countLabel*/;
286
287 quitButton =
288 XtCreateManagedWidget("quitButton",commandWidgetClass,commandBox,NZ);
289
290 ownButton =
291 XtCreateManagedWidget("ownButton",toggleWidgetClass,commandBox,NZ);
292
293 countLabel =
294 XtCreateManagedWidget("countLabel",labelWidgetClass,commandBox,NZ);
295
296 XtAddCallback(quitButton, XtNcallback, Quit, NULL);
297 XtAddCallback(ownButton,XtNcallback,OwnSelection,(XtPointer)True);
298 }
299
300 fieldBox = XtCreateManagedWidget("fieldBox", boxWidgetClass, pane, NZ);
301 {
302 Widget /*dash,*/ field /*[FIELD_COUNT]*/;
303 int f;
304
305 for (f = 0; f < FIELD_COUNT; f++) {
306 char name[10];
307 FieldMenuRec *makeRec = XtNew(FieldMenuRec);
308 snprintf( name, sizeof(name), "field%d", f );
309 XtCreateManagedWidget("dash",labelWidgetClass,fieldBox,NZ);
310 field = XtCreateManagedWidget(name, menuButtonWidgetClass,
311 fieldBox, NZ);
312 XtAddCallback(field, XtNcallback, SelectField,
313 (XtPointer)(long)f);
314 makeRec->field = f;
315 makeRec->button = field;
316 ScheduleWork(MakeFieldMenu, (XtPointer)makeRec, 2);
317 ScheduleWork((XtProc)XtFree, (XtPointer)makeRec, 2);
318 }
319 }
320
321 /* currentFontName = */
322 {
323 Arg args[1];
324 currentFontNameSize = strlen(AppRes.pattern);
325 if (currentFontNameSize < 128) currentFontNameSize = 128;
326 currentFontNameString = (String)XtMalloc(currentFontNameSize);
327 strcpy(currentFontNameString, AppRes.pattern);
328 XtSetArg(args[0], XtNlabel, currentFontNameString);
329 currentFontName =
330 XtCreateManagedWidget("fontName",labelWidgetClass,pane,args,ONE);
331 }
332
333 viewPort =
334 XtCreateManagedWidget("viewPort",viewportWidgetClass,pane,NZ);
335 sampleText =
336 XtCreateManagedWidget("sampleText",ucsLabelWidgetClass,viewPort,NZ);
337 }
338
339 XtRealizeWidget(topLevel);
340 XDefineCursor( XtDisplay(topLevel), XtWindow(topLevel), AppRes.cursor );
341 {
342 int f;
343 for (f = 0; f < FIELD_COUNT; f++) currentFont.value_index[f] = -1;
344 }
345 wm_delete_window = XInternAtom(XtDisplay(topLevel), "WM_DELETE_WINDOW",
346 False);
347 (void) XSetWMProtocols (XtDisplay(topLevel), XtWindow(topLevel),
348 &wm_delete_window, 1);
349 XtAppMainLoop(appCtx);
350
351 return 0;
352 }
353
354
355 typedef struct WorkPiece WorkPieceRec, *WorkPiece;
356 struct WorkPiece {
357 WorkPiece next;
358 int priority;
359 XtProc proc;
360 XtPointer closure;
361 };
362 static WorkPiece workQueue = NULL;
363
364
365 /*
366 * ScheduleWork( XtProc proc, XtPointer closure, int priority )
367 *
368 * Adds a WorkPiece to the workQueue in FIFO order by priority.
369 * Lower numbered priority work is completed before higher numbered
370 * priorities.
371 *
372 * If the workQueue was previously empty, then makes sure that
373 * Xt knows we have (background) work to do.
374 */
375
ScheduleWork(XtProc proc,XtPointer closure,int priority)376 static void ScheduleWork(XtProc proc, XtPointer closure, int priority)
377 {
378 WorkPiece piece = XtNew(WorkPieceRec);
379
380 piece->priority = priority;
381 piece->proc = proc;
382 piece->closure = closure;
383 if (workQueue == NULL) {
384 piece->next = NULL;
385 workQueue = piece;
386 XtAppAddWorkProc(appCtx, DoWorkPiece, NULL);
387 } else {
388 if (workQueue->priority > priority) {
389 piece->next = workQueue;
390 workQueue = piece;
391 }
392 else {
393 WorkPiece n;
394 for (n = workQueue; n->next && n->next->priority <= priority;)
395 n = n->next;
396 piece->next = n->next;
397 n->next = piece;
398 }
399 }
400 }
401
402 /* ARGSUSED */
DoWorkPiece(XtPointer closure)403 Boolean DoWorkPiece(XtPointer closure)
404 {
405 WorkPiece piece = workQueue;
406
407 if (piece) {
408 (*piece->proc)(piece->closure);
409 workQueue = piece->next;
410 XtFree((XtPointer)piece);
411 if (workQueue != NULL)
412 return False;
413 }
414 return True;
415 }
416
417
418 /*
419 * FinishWork()
420 *
421 * Drains foreground tasks from the workQueue.
422 * Foreground == (priority < BACKGROUND)
423 */
424
FinishWork(void)425 static void FinishWork(void)
426 {
427 while (workQueue && workQueue->priority < BACKGROUND)
428 DoWorkPiece(NULL);
429 }
430
431
432 typedef struct ParseRec ParseRec;
433 struct ParseRec {
434 char **fontNames;
435 int num_fonts;
436 int start, end;
437 FontValues *fonts;
438 FieldValueList **fieldValues;
439 };
440
441
GetFontNames(XtPointer closure)442 void GetFontNames(XtPointer closure)
443 {
444 Display *dpy = (Display*)closure;
445 ParseRec *parseRec;
446 int f, field, count;
447 String *fontNames;
448 Boolean *b;
449 int work_priority = 0;
450
451 fontNames = XListFonts(dpy, AppRes.pattern, 32767, &numFonts);
452
453 fonts = (FontValues*)XtMalloc( numFonts*sizeof(FontValues) );
454 fontInSet = (Boolean*)XtMalloc( numFonts*sizeof(Boolean) );
455 for (f = numFonts, b = fontInSet; f; f--, b++) *b = True;
456 for (field = 0; field < FIELD_COUNT; field++) {
457 fieldValues[field] = (FieldValueList*)XtMalloc(sizeof(FieldValueList));
458 fieldValues[field]->allocated = 1;
459 fieldValues[field]->count = 0;
460 }
461 if (numFonts == 0) {
462 SetNoFonts();
463 return;
464 }
465 count = matchingFontCount = numFonts;
466 numBadFonts = 0;
467 parseRec = XtNew(ParseRec);
468 *parseRec = (ParseRec) {
469 .fontNames = fontNames,
470 .num_fonts = count,
471 .start = 0,
472 .fonts = fonts,
473 .fieldValues = fieldValues
474 };
475 /* this is bogus; the task should be responsible for quantizing...*/
476 while (count > PARSE_QUANTUM) {
477 ParseRec *prevRec = parseRec;
478 parseRec->end = parseRec->start + PARSE_QUANTUM;
479 ScheduleWork(ParseFontNames, (XtPointer)parseRec, work_priority);
480 ScheduleWork((XtProc)XtFree, (XtPointer)parseRec, work_priority);
481 parseRec = XtNew(ParseRec);
482 *parseRec = *prevRec;
483 parseRec->start += PARSE_QUANTUM;
484 parseRec->fonts += PARSE_QUANTUM;
485 parseRec->fontNames += PARSE_QUANTUM;
486 count -= PARSE_QUANTUM;
487 work_priority = 1;
488 }
489 parseRec->end = numFonts;
490 ScheduleWork(ParseFontNames,(XtPointer)parseRec,work_priority);
491 ScheduleWork((XtProc)XFreeFontNames,(XtPointer)fontNames,work_priority);
492 ScheduleWork((XtProc)XtFree, (XtPointer)parseRec, work_priority);
493 if (AppRes.scaled_fonts)
494 ScheduleWork(FixScalables,(XtPointer)0,work_priority);
495 ScheduleWork(SortFields,(XtPointer)0,work_priority);
496 SetParsingFontCount(matchingFontCount);
497 if (strcmp(AppRes.pattern, DEFAULTPATTERN)) {
498 int maxField, f;
499 for (f = 0; f < numFonts && !IsXLFDFontName(fontNames[f]); f++);
500 if (f != numFonts) {
501 if (Matches(AppRes.pattern, fontNames[f],
502 patternFieldSpecified, &maxField)) {
503 for (f = 0; f <= maxField; f++) {
504 if (patternFieldSpecified[f])
505 currentFont.value_index[f] = 0;
506 }
507 }
508 else
509 XtAppWarning( appCtx,
510 "internal error; pattern didn't match first font" );
511 }
512 else {
513 SetNoFonts();
514 return;
515 }
516 }
517 ScheduleWork(SetCurrentFont, NULL, 1);
518 }
519
520
ParseFontNames(XtPointer closure)521 void ParseFontNames(XtPointer closure)
522 {
523 ParseRec *parseRec = (ParseRec*)closure;
524 char **fontNames = parseRec->fontNames;
525 int num_fonts = parseRec->end;
526 FieldValueList **fieldValues = parseRec->fieldValues;
527 FontValues *fontValues = parseRec->fonts - numBadFonts;
528 int i, font;
529
530 for (font = parseRec->start; font < num_fonts; font++) {
531 char *p;
532 int f, len;
533 FieldValue *v;
534
535 if (!IsXLFDFontName(*fontNames)) {
536 numFonts--;
537 numBadFonts++;
538 continue;
539 }
540
541 for (f = 0, p = *fontNames++; f < FIELD_COUNT; f++) {
542 const char *fieldP;
543
544 if (*p) ++p;
545 if (*p == DELIM || *p == '\0') {
546 fieldP = "";
547 len = 0;
548 } else {
549 fieldP = p;
550 while (*p && *++p != DELIM);
551 len = p - fieldP;
552 }
553 for (i=fieldValues[f]->count,v=fieldValues[f]->value; i;i--,v++) {
554 if (len == 0) {
555 if (v->string == NULL) break;
556 }
557 else
558 if (v->string &&
559 strncmp( v->string, fieldP, len ) == 0 &&
560 (v->string)[len] == '\0')
561 break;
562 }
563 if (i == 0) {
564 int count = fieldValues[f]->count++;
565 if (count == fieldValues[f]->allocated) {
566 int allocated = (fieldValues[f]->allocated += 10);
567 fieldValues[f] = (FieldValueList*)
568 XtRealloc( (char *) fieldValues[f],
569 sizeof(FieldValueList) +
570 (allocated-1) * sizeof(FieldValue) );
571 }
572 v = &fieldValues[f]->value[count];
573 v->field = f;
574 if (len == 0)
575 v->string = NULL;
576 else {
577 v->string = (String)XtMalloc( len+1 );
578 strncpy( v->string, fieldP, len );
579 v->string[len] = '\0';
580 }
581 v->font = (int*)XtMalloc( 10*sizeof(int) );
582 v->allocated = 10;
583 v->count = 0;
584 v->enable = True;
585 i = 1;
586 }
587 fontValues->value_index[f] = fieldValues[f]->count - i;
588 if ((i = v->count++) == v->allocated) {
589 int allocated = (v->allocated += 10);
590 v->font = (int*)XtRealloc( (char *) v->font,
591 allocated * sizeof(int) );
592 }
593 v->font[i] = font - numBadFonts;
594 }
595 fontValues++;
596 }
597 SetParsingFontCount(numFonts - num_fonts);
598 }
599
600
601 /* Add the list of scalable fonts to the match-list of every value instance
602 * for field f. Must produce sorted order. Must deal with duplicates
603 * since we need to do this for resolution fields which can be nonzero in
604 * the scalable fonts.
605 */
AddScalables(int f)606 static void AddScalables(int f)
607 {
608 int i;
609 int max = fieldValues[f]->count;
610 FieldValue *fval = fieldValues[f]->value;
611
612 for (i = 0; i < max; i++, fval++) {
613 int *oofonts, *ofonts, *nfonts, *fonts;
614 int ocount, ncount, count;
615
616 if (fval->string && !strcmp(fval->string, "0"))
617 continue;
618 count = numScaledFonts;
619 fonts = scaledFonts;
620 ocount = fval->count;
621 ncount = ocount + count;
622 nfonts = (int *)XtMalloc( ncount * sizeof(int) );
623 oofonts = ofonts = fval->font;
624 fval->font = nfonts;
625 fval->count = ncount;
626 fval->allocated = ncount;
627 while (count && ocount) {
628 if (*fonts < *ofonts) {
629 *nfonts++ = *fonts++;
630 count--;
631 } else if (*fonts == *ofonts) {
632 *nfonts++ = *fonts++;
633 count--;
634 ofonts++;
635 ocount--;
636 fval->count--;
637 } else {
638 *nfonts++ = *ofonts++;
639 ocount--;
640 }
641 }
642 while (ocount) {
643 *nfonts++ = *ofonts++;
644 ocount--;
645 }
646 while (count) {
647 *nfonts++ = *fonts++;
648 count--;
649 }
650 XtFree((char *)oofonts);
651 }
652 }
653
654
655 /* Merge in specific scaled sizes (specified in a comma-separated string)
656 * for field f. Weed out duplicates. The set of matching fonts is just
657 * the set of scalable fonts.
658 */
NewScalables(int f,char * slist)659 static void NewScalables(int f, char *slist)
660 {
661 char endc = 1;
662 char *str;
663 int i, count;
664 FieldValue *v;
665
666 while (endc) {
667 while (*slist == ' ' || *slist == ',')
668 slist++;
669 if (!*slist)
670 break;
671 str = slist;
672 while ((endc = *slist) && endc != ' ' && endc != ',')
673 slist++;
674 *slist++ = '\0';
675 for (i=fieldValues[f]->count,v=fieldValues[f]->value; --i >= 0; v++) {
676 if (v->string && !strcmp(v->string, str))
677 break;
678 }
679 if (i >= 0)
680 continue;
681 count = fieldValues[f]->count++;
682 if (count == fieldValues[f]->allocated) {
683 int allocated = (fieldValues[f]->allocated += 10);
684 fieldValues[f] = (FieldValueList*)
685 XtRealloc( (char *) fieldValues[f],
686 sizeof(FieldValueList) +
687 (allocated-1) * sizeof(FieldValue) );
688 }
689 v = &fieldValues[f]->value[count];
690 v->field = f;
691 v->string = str;
692 v->count = numScaledFonts;
693 v->font = scaledFonts;
694 v->allocated = 0;
695 v->enable = True;
696 }
697 }
698
699
700 /* Find all scalable fonts, defined as the set matching "0" in the pixel
701 * size field (field 6). Augment the match-lists for all other fields
702 * that are scalable. Add in new scalable pixel and point sizes given
703 * in resources.
704 */
705 /*ARGSUSED*/
FixScalables(XtPointer closure)706 void FixScalables(XtPointer closure)
707 {
708 int i;
709 FieldValue *fval = fieldValues[6]->value;
710
711 for (i = fieldValues[6]->count; --i >= 0; fval++) {
712 if (fval->string && !strcmp(fval->string, "0")) {
713 scaledFonts = fval->font;
714 numScaledFonts = fval->count;
715 AddScalables(6);
716 NewScalables(6, AppRes.pixelSizeList);
717 AddScalables(7);
718 NewScalables(7, AppRes.pointSizeList);
719 AddScalables(8);
720 AddScalables(9);
721 AddScalables(11);
722 break;
723 }
724 }
725 }
726
727
728 /* A verbatim copy from xc/lib/font/fontfile/fontdir.c */
729
730 /*
731 * Compare two strings just like strcmp, but preserve decimal integer
732 * sorting order, i.e. "2" < "10" or "iso8859-2" < "iso8859-10" <
733 * "iso10646-1". Strings are sorted as if sequences of digits were
734 * prefixed by a length indicator (i.e., does not ignore leading zeroes).
735 *
736 * Markus Kuhn <Markus.Kuhn@cl.cam.ac.uk>
737 */
738 #define Xisdigit(c) ('\060' <= (c) && (c) <= '\071')
739
strcmpn(const char * s1,const char * s2)740 static int strcmpn(const char *s1, const char *s2)
741 {
742 int digits, predigits = 0;
743 const char *ss1, *ss2;
744
745 while (1) {
746 if (*s1 == 0 && *s2 == 0)
747 return 0;
748 digits = Xisdigit(*s1) && Xisdigit(*s2);
749 if (digits && !predigits) {
750 ss1 = s1;
751 ss2 = s2;
752 while (Xisdigit(*ss1) && Xisdigit(*ss2))
753 ss1++, ss2++;
754 if (!Xisdigit(*ss1) && Xisdigit(*ss2))
755 return -1;
756 if (Xisdigit(*ss1) && !Xisdigit(*ss2))
757 return 1;
758 }
759 if ((unsigned char)*s1 < (unsigned char)*s2)
760 return -1;
761 if ((unsigned char)*s1 > (unsigned char)*s2)
762 return 1;
763 predigits = digits;
764 s1++, s2++;
765 }
766 }
767
768
769 /* Order is *, (nil), rest */
AlphabeticSort(_Xconst void * fval1,_Xconst void * fval2)770 static int AlphabeticSort(_Xconst void *fval1, _Xconst void *fval2)
771 {
772 # define fval1 ((_Xconst FieldValue *)fval1)
773 # define fval2 ((_Xconst FieldValue *)fval2)
774
775 if (fval1->string && !strcmp(fval1->string, "*"))
776 return -1;
777 if (fval2->string && !strcmp(fval2->string, "*"))
778 return 1;
779 if (!fval1->string)
780 return -1;
781 if (!fval2->string)
782 return 1;
783
784 return strcmpn(fval1->string, fval2->string);
785
786 # undef fval1
787 # undef fval2
788 }
789
790
791 /* Order is *, (nil), rest */
NumericSort(_Xconst void * fval1,_Xconst void * fval2)792 static int NumericSort(_Xconst void *fval1, _Xconst void *fval2)
793 {
794 # define fval1 ((_Xconst FieldValue *)fval1)
795 # define fval2 ((_Xconst FieldValue *)fval2)
796
797 if (fval1->string && !strcmp(fval1->string, "*"))
798 return -1;
799 if (fval2->string && !strcmp(fval2->string, "*"))
800 return 1;
801 if (!fval1->string)
802 return -1;
803 if (!fval2->string)
804 return 1;
805
806 return atoi(fval1->string) - atoi(fval2->string);
807
808 # undef fval1
809 # undef fval2
810 }
811
812
813 /* Resort each field, to get reasonable menus. Sort alphabetically or
814 * numerically, depending on the field. Since the fonts have indexes
815 * into the fields, we need to deal with updating those indexes after the
816 * sort.
817 */
818 /*ARGSUSED*/
SortFields(XtPointer closure)819 void SortFields(XtPointer closure)
820 {
821 int i, j, count;
822 FieldValue *vals;
823 int *indexes;
824 int *idx;
825
826 for (i = 0; i < FIELD_COUNT; i++) {
827 count = fieldValues[i]->count;
828 vals = fieldValues[i]->value;
829 indexes = (int *)XtMalloc(count * sizeof(int));
830 /* temporarily use the field component, will restore it below */
831 for (j = 0; j < count; j++)
832 vals[j].field = j;
833 switch (i) {
834 case 6: case 7: case 8: case 9: case 11:
835 qsort((char *)vals, count, sizeof(FieldValue), NumericSort);
836 break;
837 default:
838 qsort((char *)vals, count, sizeof(FieldValue), AlphabeticSort);
839 break;
840 }
841 for (j = 0; j < count; j++) {
842 indexes[vals[j].field] = j;
843 vals[j].field = i;
844 }
845 for (j = 0; j < numFonts; j++) {
846 idx = &fonts[j].value_index[i];
847 if (*idx >= 0)
848 *idx = indexes[*idx];
849 }
850 XtFree((char *)indexes);
851 }
852 }
853
854
IsXLFDFontName(String fontName)855 Boolean IsXLFDFontName(String fontName)
856 {
857 int f;
858 for (f = 0; *fontName;) if (*fontName++ == DELIM) f++;
859 return (f == FIELD_COUNT);
860 }
861
862
MakeFieldMenu(XtPointer closure)863 void MakeFieldMenu(XtPointer closure)
864 {
865 FieldMenuRec *makeRec = (FieldMenuRec*)closure;
866 Widget menu;
867 FieldValueList *values = fieldValues[makeRec->field];
868 FieldValue *val = values->value;
869 int i;
870 Arg args[1];
871 register Widget item;
872
873 if (numFonts)
874 menu =
875 XtCreatePopupShell("menu",simpleMenuWidgetClass,makeRec->button,NZ);
876 else {
877 SetNoFonts();
878 return;
879 }
880 XtGetSubresources(menu, (XtPointer) values, "options", "Options",
881 menuResources, XtNumber(menuResources), NZ);
882 XtAddCallback(menu, XtNpopupCallback, EnableOtherValues,
883 (XtPointer)(long)makeRec->field );
884
885 if (!patternFieldSpecified[val->field]) {
886 XtSetArg( args[0], XtNlabel, "*" );
887 item = XtCreateManagedWidget("any",smeBSBObjectClass,menu,args,ONE);
888 XtAddCallback(item, XtNcallback, AnyValue, (XtPointer)(long)val->field);
889 }
890
891 for (i = values->count; i; i--, val++) {
892 XtSetArg( args[0], XtNlabel, val->string ? val->string : "(nil)" );
893 item =
894 XtCreateManagedWidget(val->string ? val->string : "nil",
895 smeBSBObjectClass, menu, args, ONE);
896 XtAddCallback(item, XtNcallback, SelectValue, (XtPointer)val);
897 val->menu_item = item;
898 }
899 }
900
901
SetNoFonts(void)902 static void SetNoFonts(void)
903 {
904 matchingFontCount = 0;
905 SetCurrentFontCount();
906 XtSetSensitive(fieldBox, False);
907 XtSetSensitive(ownButton, False);
908 if (AppRes.app_defaults_version >= MIN_APP_DEFAULTS_VERSION) {
909 XtUnmapWidget(sampleText);
910 }
911 }
912
913
Matches(register String pattern,register String fontName,Boolean fields[],int * maxField)914 Boolean Matches(register String pattern, register String fontName,
915 Boolean fields[/*FIELD_COUNT*/], int *maxField)
916 {
917 register int field = (*fontName == DELIM) ? -1 : 0;
918 register Boolean marked_this_field = False;
919
920 while (*pattern) {
921 if (*pattern == *fontName || *pattern == '?') {
922 pattern++;
923 if (*fontName++ == DELIM) {
924 field++;
925 marked_this_field = False;
926 }
927 else if (!marked_this_field)
928 fields[field] = marked_this_field = True;
929 continue;
930 }
931 if (*pattern == '*') {
932 if (*++pattern == '\0') {
933 *maxField = field;
934 return True;
935 }
936 while (*fontName) {
937 Boolean field_bits[FIELD_COUNT];
938 int max_field;
939 if (*fontName == DELIM) field++;
940 bzero( field_bits, sizeof(field_bits) );
941 if (Matches(pattern, fontName++, field_bits, &max_field)) {
942 int f;
943 *maxField = field + max_field;
944 for (f = 0; f <= max_field; field++, f++)
945 fields[field] = field_bits[f];
946 return True;
947 }
948 }
949 return False;
950 }
951 else /* (*pattern != '*') */
952 return False;
953 }
954 if (*fontName)
955 return False;
956
957 *maxField = field;
958 return True;
959 }
960
961
962 /* ARGSUSED */
SelectValue(Widget w,XtPointer closure,XtPointer callData)963 void SelectValue(Widget w, XtPointer closure, XtPointer callData)
964 {
965 FieldValue *val = (FieldValue*)closure;
966 #ifdef LOG_CHOICES
967 Choice *choice = XtNew(Choice);
968 #else
969 static Choice pChoice;
970 Choice *choice = &pChoice;
971 #endif
972
973 #ifdef notdef
974 Widget button = XtParent(XtParent(w));
975 Arg args[1];
976
977 XtSetArg(args[0], XtNlabel, val->string);
978 XtSetValues( button, args, ONE );
979 #endif
980
981 currentFont.value_index[val->field] = val - fieldValues[val->field]->value;
982
983 choice->prev = choiceList;
984 choice->value = val;
985 choiceList = choice;
986
987 SetCurrentFont(NULL);
988 EnableRemainingItems(SkipCurrentField);
989 }
990
991
992 /* ARGSUSED */
AnyValue(Widget w,XtPointer closure,XtPointer callData)993 void AnyValue(Widget w, XtPointer closure, XtPointer callData)
994 {
995 int field = (long)closure;
996 currentFont.value_index[field] = -1;
997 SetCurrentFont(NULL);
998 EnableAllItems(field);
999 EnableRemainingItems(ValidateCurrentField);
1000 }
1001
1002
SetCurrentFontCount(void)1003 static void SetCurrentFontCount(void)
1004 {
1005 char label[80];
1006 Arg args[1];
1007 if (matchingFontCount == 1)
1008 strcpy( label, "1 name matches" );
1009 else if (matchingFontCount)
1010 snprintf( label, sizeof(label), "%d names match", matchingFontCount );
1011 else
1012 strcpy( label, "no names match" );
1013 XtSetArg( args[0], XtNlabel, label );
1014 XtSetValues( countLabel, args, ONE );
1015 }
1016
1017
SetParsingFontCount(int count)1018 static void SetParsingFontCount(int count)
1019 {
1020 char label[80];
1021 Arg args[1];
1022 if (count == 1)
1023 strcpy( label, "1 name to parse" );
1024 else
1025 snprintf( label, sizeof(label), "%d names to parse", count );
1026 XtSetArg( args[0], XtNlabel, label );
1027 XtSetValues( countLabel, args, ONE );
1028 FlushXqueue(XtDisplay(countLabel));
1029 }
1030
1031 /* ARGSUSED */
IsISO10646(Display * dpy,XFontStruct * font)1032 static Boolean IsISO10646(Display *dpy, XFontStruct *font)
1033 {
1034 Boolean ok;
1035 int i;
1036 char *regname;
1037 Atom registry;
1038 XFontProp *xfp;
1039
1040 ok = False;
1041 registry = XInternAtom(dpy, "CHARSET_REGISTRY", False);
1042
1043 for (i = 0, xfp = font->properties;
1044 ok == False && i < font->n_properties; xfp++, i++) {
1045 if (xfp->name == registry) {
1046 regname = XGetAtomName(dpy, (Atom) xfp->card32);
1047 if (strcmp(regname, "ISO10646") == 0 ||
1048 strcmp(regname, "iso10646") == 0)
1049 ok = True;
1050 XFree(regname);
1051 }
1052 }
1053 return ok;
1054 }
1055
1056 /* ARGSUSED */
SetCurrentFont(XtPointer closure)1057 void SetCurrentFont(XtPointer closure)
1058 {
1059 int f;
1060 Boolean *b;
1061
1062 if (numFonts == 0) {
1063 SetNoFonts();
1064 return;
1065 }
1066 for (f = numFonts, b = fontInSet; f; f--, b++) *b = True;
1067
1068 {
1069 int bytesLeft = currentFontNameSize;
1070 int pos = 0;
1071
1072 for (f = 0; f < FIELD_COUNT; f++) {
1073 int len, i;
1074 String str;
1075
1076 currentFontNameString[pos++] = DELIM;
1077 if ((i = currentFont.value_index[f]) != -1) {
1078 FieldValue *val = &fieldValues[f]->value[i];
1079 if ((str = val->string))
1080 len = strlen(str);
1081 else {
1082 str = "";
1083 len = 0;
1084 }
1085 MarkInvalidFonts(fontInSet, val);
1086 } else {
1087 str = "*";
1088 len = 1;
1089 }
1090 if (len+1 > --bytesLeft) {
1091 currentFontNameString = (String)
1092 XtRealloc(currentFontNameString, currentFontNameSize+=128);
1093 bytesLeft += 128;
1094 }
1095 strcpy( ¤tFontNameString[pos], str );
1096 pos += len;
1097 bytesLeft -= len;
1098 }
1099 }
1100 {
1101 Arg args[1];
1102 XtSetArg( args[0], XtNlabel, currentFontNameString );
1103 XtSetValues( currentFontName, args, ONE );
1104 }
1105 matchingFontCount = 0;
1106 for (f = numFonts, b = fontInSet; f; f--, b++) {
1107 if (*b) matchingFontCount++;
1108 }
1109
1110 SetCurrentFontCount();
1111
1112 {
1113 Widget mapWidget = sampleText;
1114 Display *dpy = XtDisplay(mapWidget);
1115 XFontStruct *font = XLoadQueryFont(dpy, currentFontNameString);
1116 String sample_text;
1117 if (font == NULL)
1118 XtSetSensitive(mapWidget, False);
1119 else {
1120 int nargs = 1;
1121 Arg args[3];
1122 int encoding;
1123 if (font->min_byte1 || font->max_byte1) {
1124 if (IsISO10646(dpy, font) == True) {
1125 encoding = XawTextEncodingUCS;
1126 sample_text = AppRes.sample_textUCS;
1127 } else {
1128 encoding = XawTextEncodingChar2b;
1129 sample_text = AppRes.sample_text16;
1130 }
1131 } else {
1132 encoding = XawTextEncoding8bit;
1133 sample_text = AppRes.sample_text;
1134 }
1135 XtSetArg( args[0], XtNfont, font );
1136 if (encoding != textEncoding) {
1137 XtSetArg(args[1], XtNencoding, encoding);
1138 XtSetArg(args[2], XtNlabel, sample_text);
1139 textEncoding = encoding;
1140 nargs = 3;
1141 }
1142 XtSetValues( sampleText, args, nargs );
1143 XtSetSensitive(mapWidget, True);
1144 XtMapWidget(mapWidget);
1145 if (sampleFont) XFreeFont( dpy, sampleFont );
1146 sampleFont = font;
1147 OwnSelection( sampleText, (XtPointer)False, (XtPointer)True );
1148 }
1149 FlushXqueue(dpy);
1150 }
1151 }
1152
1153
MarkInvalidFonts(Boolean * set,FieldValue * val)1154 static void MarkInvalidFonts(Boolean *set, FieldValue *val)
1155 {
1156 int fi = 0, vi;
1157 int *fp = val->font;
1158 for (vi = val->count; vi; vi--, fp++) {
1159 while (fi < *fp) {
1160 set[fi] = False;
1161 fi++;
1162 }
1163 fi++;
1164 }
1165 while (fi < numFonts) {
1166 set[fi] = False;
1167 fi++;
1168 }
1169 }
1170
1171
EnableRemainingItems(ValidateAction current_field_action)1172 static void EnableRemainingItems(ValidateAction current_field_action)
1173 {
1174 if (matchingFontCount == 0 || matchingFontCount == numFonts) {
1175 if (anyDisabled) {
1176 int field;
1177 for (field = 0; field < FIELD_COUNT; field++) {
1178 EnableAllItems(field);
1179 }
1180 anyDisabled = False;
1181 }
1182 }
1183 else {
1184 int field;
1185 for (field = 0; field < FIELD_COUNT; field++) {
1186 FieldValue *value = fieldValues[field]->value;
1187 int count;
1188 if (current_field_action == SkipCurrentField &&
1189 field == choiceList->value->field)
1190 continue;
1191 for (count = fieldValues[field]->count; count; count--, value++) {
1192 int *fp = value->font;
1193 int fontCount;
1194 for (fontCount = value->count; fontCount; fontCount--, fp++) {
1195 if (fontInSet[*fp]) {
1196 value->enable = True;
1197 goto NextValue;
1198 }
1199 }
1200 value->enable = False;
1201 NextValue:;
1202 }
1203 }
1204 anyDisabled = True;
1205 }
1206 enabledMenuIndex = -1;
1207 {
1208 int f;
1209 for (f = 0; f < FIELD_COUNT; f++)
1210 ScheduleWork(EnableMenu, (XtPointer)(long)f, BACKGROUND);
1211 }
1212 }
1213
1214
EnableAllItems(int field)1215 static void EnableAllItems(int field)
1216 {
1217 FieldValue *value = fieldValues[field]->value;
1218 int count;
1219 for (count = fieldValues[field]->count; count; count--, value++) {
1220 value->enable = True;
1221 }
1222 }
1223
1224
1225 /* ARGSUSED */
SelectField(Widget w,XtPointer closure,XtPointer callData)1226 void SelectField(Widget w, XtPointer closure, XtPointer callData)
1227 {
1228 int field = (long)closure;
1229 FieldValue *values = fieldValues[field]->value;
1230 int count = fieldValues[field]->count;
1231 printf( "field %d:\n", field );
1232 while (count--) {
1233 printf( " %s: %d fonts\n", values->string, values->count );
1234 values++;
1235 }
1236 printf( "\n" );
1237 }
1238
1239
1240 /* When 2 out of 3 y-related scalable fields are set, we need to restrict
1241 * the third set to only match on exact matches, that is, ignore the
1242 * matching to scalable fonts. Because choosing a random third value
1243 * will almost always produce an illegal font name, and it isn't worth
1244 * trying to compute which choices might be legal to the font scaler.
1245 */
DisableScaled(int f,int f1,int f2)1246 static void DisableScaled(int f, int f1, int f2)
1247 {
1248 int i, j;
1249 FieldValue *v;
1250 int *font;
1251
1252 for (i = fieldValues[f]->count, v = fieldValues[f]->value; --i >= 0; v++) {
1253 if (!v->enable || !v->string || !strcmp(v->string, "0"))
1254 continue;
1255 for (j = v->count, font = v->font; --j >= 0; font++) {
1256 if (fontInSet[*font] &&
1257 fonts[*font].value_index[f1] == currentFont.value_index[f1] &&
1258 fonts[*font].value_index[f2] == currentFont.value_index[f2])
1259 break;
1260 }
1261 if (j < 0) {
1262 v->enable = False;
1263 XtSetSensitive(v->menu_item, False);
1264 }
1265 }
1266 }
1267
1268 /* ARGSUSED */
EnableOtherValues(Widget w,XtPointer closure,XtPointer callData)1269 void EnableOtherValues(Widget w, XtPointer closure, XtPointer callData)
1270 {
1271 int field = (long)closure;
1272 Boolean *font_in_set = (Boolean*)XtMalloc(numFonts*sizeof(Boolean));
1273 Boolean *b;
1274 int f, count;
1275
1276 FinishWork();
1277 for (f = numFonts, b = font_in_set; f; f--, b++) *b = True;
1278 for (f = 0; f < FIELD_COUNT; f++) {
1279 int i;
1280 if (f != field && (i = currentFont.value_index[f]) != -1) {
1281 MarkInvalidFonts( font_in_set, &fieldValues[f]->value[i] );
1282 }
1283 }
1284 if (scaledFonts)
1285 {
1286 /* Check for 2 out of 3 scalable y fields being set */
1287 char *str;
1288 Bool specificPxl, specificPt, specificY;
1289
1290 f = currentFont.value_index[6];
1291 specificPxl = (f >= 0 &&
1292 (str = fieldValues[6]->value[f].string) &&
1293 strcmp(str, "0"));
1294 f = currentFont.value_index[7];
1295 specificPt = (f >= 0 &&
1296 (str = fieldValues[7]->value[f].string) &&
1297 strcmp(str, "0"));
1298 f = currentFont.value_index[9];
1299 specificY = (f >= 0 &&
1300 (str = fieldValues[9]->value[f].string) &&
1301 strcmp(str, "0"));
1302 if (specificPt && specificY)
1303 DisableScaled(6, 7, 9);
1304 if (specificPxl && specificY)
1305 DisableScaled(7, 6, 9);
1306 if (specificPxl && specificPt)
1307 DisableScaled(9, 6, 7);
1308 }
1309 count = 0;
1310 for (f = numFonts, b = font_in_set; f; f--, b++) {
1311 if (*b) count++;
1312 }
1313 if (count != matchingFontCount) {
1314 Boolean *sp = fontInSet;
1315 FieldValueList *fieldValue = fieldValues[field];
1316 for (b = font_in_set, f = 0; f < numFonts; f++, b++, sp++) {
1317 if (*b != *sp) {
1318 int i = fonts[f].value_index[field];
1319 FieldValue *val = &fieldValue->value[i];
1320 val->enable = True;
1321 XtSetSensitive(val->menu_item, True);
1322 if (++count == matchingFontCount) break;
1323 }
1324 }
1325 }
1326 XtFree((char *)font_in_set);
1327 if (enabledMenuIndex < field)
1328 EnableMenu((XtPointer)(long)field);
1329 }
1330
1331
EnableMenu(XtPointer closure)1332 void EnableMenu(XtPointer closure)
1333 {
1334 int field = (long)closure;
1335 FieldValue *val = fieldValues[field]->value;
1336 int f;
1337 Widget *managed = NULL, *pManaged = NULL;
1338 Widget *unmanaged = NULL, *pUnmanaged = NULL;
1339 Boolean showUnselectable = fieldValues[field]->show_unselectable;
1340
1341 for (f = fieldValues[field]->count; f; f--, val++) {
1342 if (showUnselectable) {
1343 if (val->enable != XtIsSensitive(val->menu_item))
1344 XtSetSensitive(val->menu_item, val->enable);
1345 }
1346 else {
1347 if (val->enable != XtIsManaged(val->menu_item)) {
1348 if (val->enable) {
1349 if (managed == NULL) {
1350 managed = (Widget*)
1351 XtMalloc(fieldValues[field]->count*sizeof(Widget));
1352 pManaged = managed;
1353 }
1354 *pManaged++ = val->menu_item;
1355 }
1356 else {
1357 if (unmanaged == NULL) {
1358 unmanaged = (Widget*)
1359 XtMalloc(fieldValues[field]->count*sizeof(Widget));
1360 pUnmanaged = unmanaged;
1361 }
1362 *pUnmanaged++ = val->menu_item;
1363 }
1364 }
1365 }
1366 }
1367 if (pManaged != managed) {
1368 XtManageChildren(managed, pManaged - managed);
1369 XtFree((char *) managed);
1370 }
1371 if (pUnmanaged != unmanaged) {
1372 XtUnmanageChildren(unmanaged, pUnmanaged - unmanaged);
1373 XtFree((char *) unmanaged);
1374 }
1375 enabledMenuIndex = field;
1376 }
1377
1378
FlushXqueue(Display * dpy)1379 static void FlushXqueue(Display *dpy)
1380 {
1381 XSync(dpy, False);
1382 while (XtAppPending(appCtx)) XtAppProcessEvent(appCtx, XtIMAll);
1383 }
1384
1385
1386 /* ARGSUSED */
Quit(Widget w,XtPointer closure,XtPointer callData)1387 void Quit(Widget w, XtPointer closure, XtPointer callData)
1388 {
1389 XtCloseDisplay(XtDisplay(w));
1390 if (AppRes.print_on_quit) printf( "%s", currentFontNameString );
1391 exit(0);
1392 }
1393
1394
1395 static Boolean
ConvertSelection(Widget w,Atom * selection,Atom * target,Atom * type,XtPointer * value,unsigned long * length,int * format)1396 ConvertSelection(Widget w, Atom *selection, Atom *target, Atom *type,
1397 XtPointer *value, unsigned long *length, int *format)
1398 {
1399 /* XmuConvertStandardSelection will use the second parameter only when
1400 * converting to the target TIMESTAMP. However, it will never be
1401 * called upon to perform this conversion, because Xt will handle it
1402 * internally. CurrentTime will never be used.
1403 */
1404 if (XmuConvertStandardSelection(w, CurrentTime, selection, target, type,
1405 (XPointer *) value, length, format))
1406 return True;
1407
1408 if (*target == XA_STRING) {
1409 *type = XA_STRING;
1410 *value = currentFontNameString;
1411 *length = strlen(*value);
1412 *format = 8;
1413 return True;
1414 }
1415 else {
1416 return False;
1417 }
1418 }
1419
1420 static AtomPtr _XA_PRIMARY_FONT = NULL;
1421 #define XA_PRIMARY_FONT XmuInternAtom(XtDisplay(w),_XA_PRIMARY_FONT)
1422
1423 /* ARGSUSED */
LoseSelection(Widget w,Atom * selection)1424 static void LoseSelection(Widget w, Atom *selection)
1425 {
1426 Arg args[1];
1427 XtSetArg( args[0], XtNstate, False );
1428 XtSetValues( w, args, ONE );
1429 if (*selection == XA_PRIMARY_FONT) {
1430 XtSetSensitive(currentFontName, False);
1431 }
1432 }
1433
1434
1435 /* ARGSUSED */
DoneSelection(Widget w,Atom * selection,Atom * target)1436 static void DoneSelection(Widget w, Atom *selection, Atom *target)
1437 {
1438 /* do nothing */
1439 }
1440
1441
1442 /* ARGSUSED */
OwnSelection(Widget w,XtPointer closure,XtPointer callData)1443 void OwnSelection(Widget w, XtPointer closure, XtPointer callData)
1444 {
1445 Time time = XtLastTimestampProcessed(XtDisplay(w));
1446 Boolean primary = (Boolean) (long) closure;
1447 Boolean own = (Boolean) (long) callData;
1448
1449 if (_XA_PRIMARY_FONT == NULL)
1450 _XA_PRIMARY_FONT = XmuMakeAtom("PRIMARY_FONT");
1451
1452 if (own) {
1453 XtOwnSelection( w, XA_PRIMARY_FONT, time,
1454 ConvertSelection, LoseSelection, DoneSelection );
1455 if (primary)
1456 XtOwnSelection( w, XA_PRIMARY, time,
1457 ConvertSelection, LoseSelection, DoneSelection );
1458 if (!XtIsSensitive(currentFontName)) {
1459 XtSetSensitive(currentFontName, True);
1460 }
1461 }
1462 else {
1463 XtDisownSelection(w, XA_PRIMARY_FONT, time);
1464 if (primary)
1465 XtDisownSelection(w, XA_PRIMARY, time);
1466 XtSetSensitive(currentFontName, False);
1467 }
1468 }
1469
1470 /*ARGSUSED*/
1471 void
QuitAction(Widget w,XEvent * event,String * params,Cardinal * num_params)1472 QuitAction(Widget w, XEvent *event, String *params, Cardinal *num_params)
1473 {
1474 exit (0);
1475 }
1476