~ubuntu-branches/ubuntu/gutsy/vnc4/gutsy

« back to all changes in this revision

Viewing changes to unix/xc/programs/xfontsel/xfontsel.c

  • Committer: Bazaar Package Importer
  • Author(s): Ola Lundqvist
  • Date: 2006-05-15 20:35:17 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060515203517-l4lre1ku942mn26k
Tags: 4.1.1+X4.3.0-10
* Correction of critical security issue. Thanks to Martin Kogler
  <e9925248@student.tuwien.ac.at> that informed me about the issue,
  and provided the patch.
  This flaw was originally found by Steve Wiseman of intelliadmin.com.
* Applied patch from Javier Kohen <jkohen@users.sourceforge.net> that
  inform the user that only 8 first characters of the password will
  actually be used when typing more than 8 characters, closes:
  #355619.

Show diffs side-by-side

added added

removed removed

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