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

« back to all changes in this revision

Viewing changes to unix/xc/programs/xfd/grid.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
/*
 
2
 * $Xorg: grid.c,v 1.4 2001/02/09 02:05:41 xorgcvs Exp $
 
3
 *
 
4
 * 
 
5
Copyright 1989, 1998  The Open Group
 
6
 
 
7
Permission to use, copy, modify, distribute, and sell this software and its
 
8
documentation for any purpose is hereby granted without fee, provided that
 
9
the above copyright notice appear in all copies and that both that
 
10
copyright notice and this permission notice appear in supporting
 
11
documentation.
 
12
 
 
13
The above copyright notice and this permission notice shall be included in
 
14
all copies or substantial portions of the Software.
 
15
 
 
16
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
17
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
18
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
 
19
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 
20
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 
21
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
22
 
 
23
Except as contained in this notice, the name of The Open Group shall not be
 
24
used in advertising or otherwise to promote the sale, use or other dealings
 
25
in this Software without prior written authorization from The Open Group.
 
26
 * *
 
27
 * Author:  Jim Fulton, MIT X Consortium
 
28
 */
 
29
/* $XFree86: xc/programs/xfd/grid.c,v 1.9 2002/07/06 00:46:42 keithp Exp $ */
 
30
 
 
31
 
 
32
#include <X11/IntrinsicP.h>
 
33
#include <X11/StringDefs.h>
 
34
#include <X11/Xaw/SimpleP.h>
 
35
#include <X11/Xmu/Converters.h>
 
36
#include "gridP.h"
 
37
 
 
38
#ifdef XKB
 
39
#include <X11/extensions/XKBbells.h>
 
40
#else
 
41
#define XkbBI_MinorError                2
 
42
#define XkbBI_Ignore                    11
 
43
#endif
 
44
 
 
45
#ifdef XKB
 
46
#define Bell(w,n) XkbStdBell(XtDisplay(w), XtWindow(w), 50, n)
 
47
#else
 
48
#define Bell(w,n) XBell(XtDisplay(w), 0)
 
49
#endif
 
50
 
 
51
static GC get_gc(FontGridWidget fgw, Pixel fore);
 
52
static void ClassInitialize(void);
 
53
static void Initialize(Widget request, Widget new, ArgList args, 
 
54
                       Cardinal *num_args);
 
55
static void Realize(Widget gw, Mask *valueMask, 
 
56
                    XSetWindowAttributes *attributes);
 
57
static void Destroy(Widget gw);
 
58
static void Resize(Widget gw);
 
59
static void Redisplay(Widget gw, XEvent *event, Region region);
 
60
static void paint_grid(FontGridWidget fgw, int col, int row, 
 
61
                       int ncols, int nrows);
 
62
static Boolean SetValues(Widget current, Widget request, Widget new, 
 
63
                         ArgList args, Cardinal *num_args);
 
64
static void Notify(Widget gw, XEvent *event, String *params, 
 
65
                   Cardinal *nparams);
 
66
 
 
67
#define Offset(field) XtOffsetOf(FontGridRec, fontgrid.field)
 
68
 
 
69
static XtResource resources[] = {
 
70
    { XtNfont, XtCFont, XtRFontStruct, sizeof(XFontStruct *),
 
71
        Offset(text_font), XtRString, (XtPointer) NULL },
 
72
    { XtNcellColumns, XtCCellColumns, XtRInt, sizeof(int),
 
73
        Offset(cell_cols), XtRImmediate, (XtPointer) 0 },
 
74
    { XtNcellRows, XtCCellRows, XtRInt, sizeof(int),
 
75
        Offset(cell_rows), XtRImmediate, (XtPointer) 0 },
 
76
    { XtNcellWidth, XtCCellWidth, XtRInt, sizeof(int),
 
77
        Offset(cell_width), XtRImmediate, (XtPointer) 0 },
 
78
    { XtNcellHeight, XtCCellHeight, XtRInt, sizeof(int),
 
79
        Offset(cell_height), XtRImmediate, (XtPointer) 0 },
 
80
    { XtNstartChar, XtCStartChar, XtRLong, sizeof(long),
 
81
        Offset(start_char), XtRImmediate, (XtPointer) 0xffffffff },
 
82
#ifndef XRENDER
 
83
    { XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
 
84
        Offset(foreground_pixel), XtRString, (XtPointer) XtDefaultForeground },
 
85
#endif
 
86
    { XtNcenterChars, XtCCenterChars, XtRBoolean, sizeof(Boolean),
 
87
        Offset(center_chars), XtRImmediate, (XtPointer) FALSE },
 
88
    { XtNboxChars, XtCBoxChars, XtRBoolean, sizeof(Boolean),
 
89
        Offset(box_chars), XtRImmediate, (XtPointer) FALSE },
 
90
    { XtNboxColor, XtCForeground, XtRPixel, sizeof(Pixel),
 
91
        Offset(box_pixel), XtRString, (XtPointer) XtDefaultForeground },
 
92
    { XtNcallback, XtCCallback, XtRCallback, sizeof(XtPointer),
 
93
        Offset(callbacks), XtRCallback, (XtPointer) NULL },
 
94
    { XtNinternalPad, XtCInternalPad, XtRInt, sizeof(int),
 
95
        Offset(internal_pad), XtRImmediate, (XtPointer) 4 },
 
96
    { XtNgridWidth, XtCGridWidth, XtRInt, sizeof(int),
 
97
        Offset(grid_width), XtRImmediate, (XtPointer) 1 },
 
98
#ifdef XRENDER
 
99
    {XtNforeground, XtCForeground, XtRXftColor, sizeof(XftColor),
 
100
        Offset(fg_color), XtRString, XtDefaultForeground},
 
101
    {XtNface, XtCFace, XtRXftFont, sizeof (XftFont *),
 
102
        Offset (text_face), XtRString, 0},
 
103
#endif
 
104
};
 
105
 
 
106
#undef Offset
 
107
 
 
108
static char defaultTranslations[] = 
 
109
  "<ButtonPress>:  notify()";
 
110
 
 
111
static XtActionsRec actions_list[] = {
 
112
    { "notify",         Notify },
 
113
};
 
114
 
 
115
FontGridClassRec fontgridClassRec = {
 
116
  { /* core fields */
 
117
    /* superclass               */      (WidgetClass) &simpleClassRec,
 
118
    /* class_name               */      "FontGrid",
 
119
    /* widget_size              */      sizeof(FontGridRec),
 
120
    /* class_initialize         */      ClassInitialize,
 
121
    /* class_part_initialize    */      NULL,
 
122
    /* class_inited             */      FALSE,
 
123
    /* initialize               */      Initialize,
 
124
    /* initialize_hook          */      NULL,
 
125
    /* realize                  */      Realize,
 
126
    /* actions                  */      actions_list,
 
127
    /* num_actions              */      XtNumber(actions_list),
 
128
    /* resources                */      resources,
 
129
    /* num_resources            */      XtNumber(resources),
 
130
    /* xrm_class                */      NULLQUARK,
 
131
    /* compress_motion          */      TRUE,
 
132
    /* compress_exposure        */      TRUE,
 
133
    /* compress_enterleave      */      TRUE,
 
134
    /* visible_interest         */      FALSE,
 
135
    /* destroy                  */      Destroy,
 
136
    /* resize                   */      Resize,
 
137
    /* expose                   */      Redisplay,
 
138
    /* set_values               */      SetValues,
 
139
    /* set_values_hook          */      NULL,
 
140
    /* set_values_almost        */      XtInheritSetValuesAlmost,
 
141
    /* get_values_hook          */      NULL,
 
142
    /* accept_focus             */      NULL,
 
143
    /* version                  */      XtVersion,
 
144
    /* callback_private         */      NULL,
 
145
    /* tm_table                 */      defaultTranslations,
 
146
    /* query_geometry           */      XtInheritQueryGeometry,
 
147
    /* display_accelerator      */      XtInheritDisplayAccelerator,
 
148
    /* extension                */      NULL
 
149
  },
 
150
  { /* simple fields */
 
151
    /* change_sensitive         */      XtInheritChangeSensitive
 
152
  }
 
153
};
 
154
 
 
155
WidgetClass fontgridWidgetClass = (WidgetClass) &fontgridClassRec;
 
156
 
 
157
 
 
158
long
 
159
GridFirstChar (Widget w)
 
160
{
 
161
    FontGridWidget      fgw = (FontGridWidget) w;
 
162
    XFontStruct         *fs = fgw->fontgrid.text_font;
 
163
#ifdef XRENDER
 
164
    XftFont             *xft = fgw->fontgrid.text_face;
 
165
    if (xft)
 
166
    {
 
167
        FcChar32    map[FC_CHARSET_MAP_SIZE];
 
168
        FcChar32    next;
 
169
        FcChar32    first;
 
170
        int         i;
 
171
 
 
172
        first = FcCharSetFirstPage (xft->charset, map, &next);
 
173
        for (i = 0; i < FC_CHARSET_MAP_SIZE; i++)
 
174
            if (map[i])
 
175
            {
 
176
                FcChar32    bits = map[i];
 
177
                first += i * 32;
 
178
                while (!(bits & 0x1))
 
179
                {
 
180
                    bits >>= 1;
 
181
                    first++;
 
182
                }
 
183
                break;
 
184
            }
 
185
        return first;
 
186
    }
 
187
    else
 
188
#endif
 
189
    if (fs)
 
190
    {
 
191
        return (fs->min_byte1 << 8) | (fs->min_char_or_byte2);
 
192
    }
 
193
    else
 
194
        return 0;
 
195
}
 
196
 
 
197
long
 
198
GridLastChar (Widget w)
 
199
{
 
200
    FontGridWidget      fgw = (FontGridWidget) w;
 
201
    XFontStruct         *fs = fgw->fontgrid.text_font;
 
202
#ifdef XRENDER
 
203
    XftFont             *xft = fgw->fontgrid.text_face;
 
204
    if (xft)
 
205
    {
 
206
        FcChar32    this, last, next;
 
207
        FcChar32    map[FC_CHARSET_MAP_SIZE];
 
208
        int         i;
 
209
        last = FcCharSetFirstPage (xft->charset, map, &next);
 
210
        while ((this = FcCharSetNextPage (xft->charset, map, &next)) != FC_CHARSET_DONE)
 
211
            last = this;
 
212
        last &= ~0xff;
 
213
        for (i = FC_CHARSET_MAP_SIZE - 1; i >= 0; i--)
 
214
            if (map[i])
 
215
            {
 
216
                FcChar32    bits = map[i];
 
217
                last += i * 32 + 31;
 
218
                while (!(bits & 0x80000000))
 
219
                {
 
220
                    last--;
 
221
                    bits <<= 1;
 
222
                }
 
223
                break;
 
224
            }
 
225
        return (long) last;
 
226
    }
 
227
    else
 
228
#endif
 
229
    if (fs)
 
230
    {
 
231
        return (fs->max_byte1 << 8) | (fs->max_char_or_byte2);
 
232
    }
 
233
    else
 
234
        return 0;
 
235
}
 
236
 
 
237
/*
 
238
 * CI_GET_CHAR_INFO_1D - return the charinfo struct for the indicated 8bit
 
239
 * character.  If the character is in the column and exists, then return the
 
240
 * appropriate metrics (note that fonts with common per-character metrics will
 
241
 * return min_bounds).
 
242
 */
 
243
 
 
244
#define CI_NONEXISTCHAR(cs) (((cs)->width == 0) && \
 
245
                             (((cs)->rbearing|(cs)->lbearing| \
 
246
                               (cs)->ascent|(cs)->descent) == 0))
 
247
 
 
248
#define CI_GET_CHAR_INFO_1D(fs,col,cs) \
 
249
{ \
 
250
    cs = 0; \
 
251
    if (col >= fs->min_char_or_byte2 && col <= fs->max_char_or_byte2) { \
 
252
        if (fs->per_char == NULL) { \
 
253
            cs = &fs->min_bounds; \
 
254
        } else { \
 
255
            cs = &fs->per_char[(col - fs->min_char_or_byte2)]; \
 
256
        } \
 
257
        if (CI_NONEXISTCHAR(cs)) \
 
258
            cs = 0; \
 
259
    } \
 
260
}
 
261
 
 
262
/*
 
263
 * CI_GET_CHAR_INFO_2D - return the charinfo struct for the indicated row and 
 
264
 * column.  This is used for fonts that have more than row zero.
 
265
 */
 
266
#define CI_GET_CHAR_INFO_2D(fs,row,col,cs) \
 
267
{ \
 
268
    cs = 0; \
 
269
    if (row >= fs->min_byte1 && row <= fs->max_byte1 && \
 
270
        col >= fs->min_char_or_byte2 && col <= fs->max_char_or_byte2) { \
 
271
        if (fs->per_char == NULL) { \
 
272
            cs = &fs->min_bounds; \
 
273
        } else { \
 
274
            cs = &fs->per_char[((row - fs->min_byte1) * \
 
275
                                (fs->max_char_or_byte2 - \
 
276
                                 fs->min_char_or_byte2 + 1)) + \
 
277
                               (col - fs->min_char_or_byte2)]; \
 
278
        } \
 
279
        if (CI_NONEXISTCHAR(cs)) \
 
280
            cs = 0; \
 
281
    } \
 
282
}
 
283
 
 
284
static Boolean
 
285
GridHasChar (Widget w, long ch)
 
286
{
 
287
    FontGridWidget      fgw = (FontGridWidget) w;
 
288
#ifdef XRENDER
 
289
    XftFont             *xft = fgw->fontgrid.text_face;
 
290
    if (xft)
 
291
    {
 
292
        return FcCharSetHasChar (xft->charset, (FcChar32) ch);
 
293
    }
 
294
    else
 
295
#endif
 
296
    {
 
297
        XFontStruct     *fs = fgw->fontgrid.text_font;
 
298
        XCharStruct     *cs;
 
299
        
 
300
        if (!fs)
 
301
            return False;
 
302
        if (fs->max_byte1 == 0)
 
303
        {
 
304
            CI_GET_CHAR_INFO_1D (fs, ch, cs);
 
305
        }
 
306
        else
 
307
        {
 
308
            unsigned int        r = (ch >> 8);
 
309
            unsigned int        c = (ch & 0xff);
 
310
            CI_GET_CHAR_INFO_2D (fs, r, c, cs);
 
311
        }
 
312
        return cs != 0;
 
313
    }
 
314
}
 
315
 
 
316
/*
 
317
 * public routines
 
318
 */
 
319
 
 
320
void 
 
321
GetFontGridCellDimensions(Widget w, long *startp, 
 
322
                          int *ncolsp, int *nrowsp)
 
323
{
 
324
    FontGridWidget fgw = (FontGridWidget) w;
 
325
    *startp = fgw->fontgrid.start_char;
 
326
    *ncolsp = fgw->fontgrid.cell_cols;
 
327
    *nrowsp = fgw->fontgrid.cell_rows;
 
328
}
 
329
 
 
330
 
 
331
void 
 
332
GetPrevNextStates(Widget w, Bool *prevvalidp, Bool *nextvalidp,
 
333
                  Bool *prev16validp, Bool *next16validp)
 
334
{
 
335
    FontGridWidget fgw = (FontGridWidget) w;
 
336
    long minn = (long) GridFirstChar (w);
 
337
    long maxn = (long) GridLastChar (w);
 
338
 
 
339
    *prev16validp = (fgw->fontgrid.start_char - 0xf00 > minn);
 
340
    *prevvalidp = (fgw->fontgrid.start_char > minn);
 
341
    *nextvalidp = (fgw->fontgrid.start_char +
 
342
                   (fgw->fontgrid.cell_cols * fgw->fontgrid.cell_rows)
 
343
                   < maxn);
 
344
    *next16validp =((fgw->fontgrid.start_char + 0xf00 +
 
345
                    (fgw->fontgrid.cell_cols * fgw->fontgrid.cell_rows))
 
346
                   < maxn);
 
347
}
 
348
 
 
349
 
 
350
 
 
351
/*
 
352
 * private routines and methods
 
353
 */
 
354
 
 
355
 
 
356
static GC 
 
357
get_gc(FontGridWidget fgw, Pixel fore)
 
358
{
 
359
    XtGCMask mask;
 
360
    XGCValues gcv;
 
361
 
 
362
    mask = (GCForeground | GCBackground | GCFunction);
 
363
    gcv.foreground = fore;
 
364
    gcv.background = fgw->core.background_pixel;
 
365
    gcv.function = GXcopy;
 
366
    if (fgw->fontgrid.text_font)
 
367
    {
 
368
        mask |= GCFont;
 
369
        gcv.font = fgw->fontgrid.text_font->fid;
 
370
    }
 
371
    gcv.cap_style = CapProjecting;
 
372
    mask |= GCCapStyle;
 
373
    if (fgw->fontgrid.grid_width > 0) {
 
374
        mask |= GCLineWidth;
 
375
        gcv.line_width = ((fgw->fontgrid.grid_width < 2) ? 0 : 
 
376
                          fgw->fontgrid.grid_width);
 
377
    }
 
378
    return (XtGetGC ((Widget) fgw, mask, &gcv));
 
379
}
 
380
 
 
381
 
 
382
#ifdef XRENDER
 
383
XtConvertArgRec xftColorConvertArgs[] = {
 
384
    {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.screen),
 
385
     sizeof(Screen *)},
 
386
    {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.colormap),
 
387
     sizeof(Colormap)}
 
388
};
 
389
 
 
390
#define donestr(type, value, tstr) \
 
391
        {                                                       \
 
392
            if (toVal->addr != NULL) {                          \
 
393
                if (toVal->size < sizeof(type)) {               \
 
394
                    toVal->size = sizeof(type);                 \
 
395
                    XtDisplayStringConversionWarning(dpy,       \
 
396
                        (char*) fromVal->addr, tstr);           \
 
397
                    return False;                               \
 
398
                }                                               \
 
399
                *(type*)(toVal->addr) = (value);                \
 
400
            }                                                   \
 
401
            else {                                              \
 
402
                static type static_val;                         \
 
403
                static_val = (value);                           \
 
404
                toVal->addr = (XPointer)&static_val;            \
 
405
            }                                                   \
 
406
            toVal->size = sizeof(type);                         \
 
407
            return True;                                        \
 
408
        }
 
409
 
 
410
static void
 
411
XmuFreeXftColor (XtAppContext app, XrmValuePtr toVal, XtPointer closure,
 
412
                 XrmValuePtr args, Cardinal *num_args)
 
413
{
 
414
    Screen      *screen;
 
415
    Colormap    colormap;
 
416
    XftColor    *color;
 
417
    
 
418
    if (*num_args != 2)
 
419
    {
 
420
        XtAppErrorMsg (app,
 
421
                       "freeXftColor", "wrongParameters",
 
422
                       "XtToolkitError",
 
423
                       "Freeing an XftColor requires screen and colormap arguments",
 
424
                       (String *) NULL, (Cardinal *)NULL);
 
425
        return;
 
426
    }
 
427
 
 
428
    screen = *((Screen **) args[0].addr);
 
429
    colormap = *((Colormap *) args[1].addr);
 
430
    color = (XftColor *) toVal->addr;
 
431
    XftColorFree (DisplayOfScreen (screen),
 
432
                  DefaultVisual (DisplayOfScreen (screen),
 
433
                                 XScreenNumberOfScreen (screen)),
 
434
                  colormap, color);
 
435
}
 
436
    
 
437
static Boolean
 
438
XmuCvtStringToXftColor(Display *dpy,
 
439
                       XrmValue *args, Cardinal *num_args,
 
440
                       XrmValue *fromVal, XrmValue *toVal,
 
441
                       XtPointer *converter_data)
 
442
{
 
443
    char            *spec;
 
444
    XRenderColor    renderColor;
 
445
    XftColor        xftColor;
 
446
    Screen          *screen;
 
447
    Colormap        colormap;
 
448
    
 
449
    if (*num_args != 2)
 
450
    {
 
451
        XtAppErrorMsg (XtDisplayToApplicationContext (dpy),
 
452
                       "cvtStringToXftColor", "wrongParameters",
 
453
                       "XtToolkitError",
 
454
                       "String to render color conversion needs screen and colormap arguments",
 
455
                       (String *) NULL, (Cardinal *)NULL);
 
456
        return False;
 
457
    }
 
458
 
 
459
    screen = *((Screen **) args[0].addr);
 
460
    colormap = *((Colormap *) args[1].addr);
 
461
 
 
462
    spec = (char *) fromVal->addr;
 
463
    if (strcasecmp (spec, XtDefaultForeground) == 0)
 
464
    {
 
465
        renderColor.red = 0;
 
466
        renderColor.green = 0;
 
467
        renderColor.blue = 0;
 
468
        renderColor.alpha = 0xffff;
 
469
    }
 
470
    else if (strcasecmp (spec, XtDefaultBackground) == 0)
 
471
    {
 
472
        renderColor.red = 0xffff;
 
473
        renderColor.green = 0xffff;
 
474
        renderColor.blue = 0xffff;
 
475
        renderColor.alpha = 0xffff;
 
476
    }
 
477
    else if (!XRenderParseColor (dpy, spec, &renderColor))
 
478
        return False;
 
479
    if (!XftColorAllocValue (dpy, 
 
480
                             DefaultVisual (dpy,
 
481
                                            XScreenNumberOfScreen (screen)),
 
482
                             colormap,
 
483
                             &renderColor,
 
484
                             &xftColor))
 
485
        return False;
 
486
    
 
487
    donestr (XftColor, xftColor, XtRXftColor);
 
488
}
 
489
 
 
490
static void
 
491
XmuFreeXftFont (XtAppContext app, XrmValuePtr toVal, XtPointer closure,
 
492
                XrmValuePtr args, Cardinal *num_args)
 
493
{
 
494
    Screen  *screen;
 
495
    XftFont *font;
 
496
    
 
497
    if (*num_args != 1)
 
498
    {
 
499
        XtAppErrorMsg (app,
 
500
                       "freeXftFont", "wrongParameters",
 
501
                       "XtToolkitError",
 
502
                       "Freeing an XftFont requires screen argument",
 
503
                       (String *) NULL, (Cardinal *)NULL);
 
504
        return;
 
505
    }
 
506
 
 
507
    screen = *((Screen **) args[0].addr);
 
508
    font = *((XftFont **) toVal->addr);
 
509
    if (font)
 
510
        XftFontClose (DisplayOfScreen (screen), font);
 
511
}
 
512
 
 
513
static Boolean
 
514
XmuCvtStringToXftFont(Display *dpy,
 
515
                      XrmValue *args, Cardinal *num_args,
 
516
                      XrmValue *fromVal, XrmValue *toVal,
 
517
                      XtPointer *converter_data)
 
518
{
 
519
    char    *name;
 
520
    XftFont *font;
 
521
    Screen  *screen;
 
522
    
 
523
    if (*num_args != 1)
 
524
    {
 
525
        XtAppErrorMsg (XtDisplayToApplicationContext (dpy),
 
526
                       "cvtStringToXftFont", "wrongParameters",
 
527
                       "XtToolkitError",
 
528
                       "String to XftFont conversion needs screen argument",
 
529
                       (String *) NULL, (Cardinal *)NULL);
 
530
        return False;
 
531
    }
 
532
 
 
533
    screen = *((Screen **) args[0].addr);
 
534
    name = (char *) fromVal->addr;
 
535
    
 
536
    font = 0;
 
537
    if (name)
 
538
    {
 
539
        font = XftFontOpenName (dpy,
 
540
                                XScreenNumberOfScreen (screen),
 
541
                                name);
 
542
        if (!font)
 
543
        {
 
544
            XtDisplayStringConversionWarning(dpy, (char *) fromVal->addr, XtRXftFont);
 
545
            return False;
 
546
        }
 
547
    }
 
548
    donestr (XftFont *, font, XtRXftFont);
 
549
}
 
550
 
 
551
static XtConvertArgRec xftFontConvertArgs[] = {
 
552
    {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.screen),
 
553
     sizeof(Screen *)},
 
554
};
 
555
 
 
556
#endif
 
557
 
 
558
static void 
 
559
ClassInitialize(void)
 
560
{
 
561
    XtAddConverter (XtRString, XtRLong, XmuCvtStringToLong, NULL, 0);
 
562
#ifdef XRENDER
 
563
    XtSetTypeConverter (XtRString, XtRXftColor, 
 
564
                        XmuCvtStringToXftColor, 
 
565
                        xftColorConvertArgs, XtNumber(xftColorConvertArgs),
 
566
                        XtCacheByDisplay, XmuFreeXftColor);
 
567
    XtSetTypeConverter (XtRString, XtRXftFont,
 
568
                        XmuCvtStringToXftFont,
 
569
                        xftFontConvertArgs, XtNumber(xftFontConvertArgs),
 
570
                        XtCacheByDisplay, XmuFreeXftFont);
 
571
#endif
 
572
}
 
573
 
 
574
 
 
575
static void 
 
576
Initialize(Widget request, Widget new, ArgList args, Cardinal *num_args)
 
577
{
 
578
    FontGridWidget reqfg = (FontGridWidget) request;
 
579
    FontGridWidget newfg = (FontGridWidget) new;
 
580
    XFontStruct *fs = newfg->fontgrid.text_font;
 
581
#ifdef XRENDER
 
582
    XftFont *xft = newfg->fontgrid.text_face;
 
583
#endif
 
584
    unsigned maxn;
 
585
 
 
586
    if (reqfg->fontgrid.cell_cols <= 0)
 
587
      newfg->fontgrid.cell_cols = 16;
 
588
 
 
589
    if (reqfg->fontgrid.cell_rows <= 0) {
 
590
#ifdef XRENDER
 
591
        if (xft)
 
592
            newfg->fontgrid.cell_rows = 16;
 
593
        else
 
594
#endif
 
595
        if (fs && fs->max_byte1 == 0) {
 
596
            newfg->fontgrid.cell_rows = (fs->max_char_or_byte2 / 
 
597
                                         newfg->fontgrid.cell_cols) + 1;
 
598
            if (newfg->fontgrid.cell_rows > 16)
 
599
              newfg->fontgrid.cell_rows = 16;
 
600
        } else
 
601
          newfg->fontgrid.cell_rows = 16;
 
602
    }
 
603
 
 
604
    if (reqfg->fontgrid.cell_width <= 0)
 
605
      newfg->fontgrid.cell_width = DefaultCellWidth (newfg);
 
606
    if (reqfg->fontgrid.cell_height <= 0)
 
607
      newfg->fontgrid.cell_height = DefaultCellHeight (newfg);
 
608
 
 
609
    /* give a nice size that fits one screen full */
 
610
    if (newfg->core.width == 0)
 
611
      newfg->core.width = (newfg->fontgrid.cell_width *
 
612
                           newfg->fontgrid.cell_cols +
 
613
                           newfg->fontgrid.grid_width *
 
614
                           (newfg->fontgrid.cell_cols + 1));
 
615
 
 
616
    if (newfg->core.height == 0) 
 
617
      newfg->core.height = (newfg->fontgrid.cell_height * 
 
618
                            newfg->fontgrid.cell_rows +
 
619
                            newfg->fontgrid.grid_width *
 
620
                            (newfg->fontgrid.cell_rows + 1));
 
621
 
 
622
    /*
 
623
     * select the first character
 
624
     */
 
625
 
 
626
    if (newfg->fontgrid.start_char == 0xffffffff)
 
627
        newfg->fontgrid.start_char = GridFirstChar(new) & ~0xff;
 
628
    maxn = GridLastChar (new);
 
629
    if (newfg->fontgrid.start_char > maxn) 
 
630
        newfg->fontgrid.start_char = (maxn + 1 - 
 
631
                                      (newfg->fontgrid.cell_cols * 
 
632
                                       newfg->fontgrid.cell_rows));
 
633
}
 
634
 
 
635
static void 
 
636
Realize(Widget gw, Mask *valueMask, XSetWindowAttributes *attributes)
 
637
{
 
638
    FontGridWidget fgw = (FontGridWidget) gw;
 
639
    FontGridPart *p = &fgw->fontgrid;
 
640
 
 
641
    p->text_gc = get_gc (fgw, GridForeground (fgw));
 
642
    p->box_gc = get_gc (fgw, p->box_pixel);
 
643
    Resize (gw);
 
644
 
 
645
    (*(XtSuperclass(gw)->core_class.realize)) (gw, valueMask, attributes);
 
646
#ifdef XRENDER
 
647
    p->draw = XftDrawCreate (XtDisplay (gw), XtWindow (gw),
 
648
                             DefaultVisual (XtDisplay (gw),
 
649
                                            DefaultScreen(XtDisplay (gw))),
 
650
                             fgw->core.colormap);
 
651
#endif
 
652
    return;
 
653
}
 
654
 
 
655
 
 
656
 
 
657
static void 
 
658
Destroy(Widget gw)
 
659
{
 
660
    FontGridWidget fgw = (FontGridWidget) gw;
 
661
 
 
662
    XtReleaseGC (gw, fgw->fontgrid.text_gc);
 
663
    XtReleaseGC (gw, fgw->fontgrid.box_gc);
 
664
}
 
665
 
 
666
 
 
667
static void 
 
668
Resize(Widget gw)
 
669
{
 
670
    FontGridWidget fgw = (FontGridWidget) gw;
 
671
 
 
672
    /* recompute in case we've changed size */
 
673
    fgw->fontgrid.cell_width = CellWidth (fgw);
 
674
    if (fgw->fontgrid.cell_width <= 0)
 
675
        fgw->fontgrid.cell_width = 1;
 
676
    fgw->fontgrid.cell_height = CellHeight (fgw);
 
677
    if (fgw->fontgrid.cell_height <= 0)
 
678
        fgw->fontgrid.cell_height = 1;
 
679
    fgw->fontgrid.xoff = (fgw->fontgrid.cell_width -
 
680
                            DefaultCellWidth (fgw)) / 2;
 
681
    fgw->fontgrid.yoff = (fgw->fontgrid.cell_height -
 
682
                            DefaultCellHeight (fgw)) / 2;
 
683
 
 
684
}
 
685
 
 
686
 
 
687
/* ARGSUSED */
 
688
static void 
 
689
Redisplay(Widget gw, XEvent *event, Region region)
 
690
{
 
691
    FontGridWidget fgw = (FontGridWidget) gw;
 
692
    XRectangle rect;                    /* bounding rect for region */
 
693
    int left, right, top, bottom;       /* which cells were damaged */
 
694
    int cw, ch;                         /* cell size */
 
695
 
 
696
#ifdef XRENDER
 
697
    if (!fgw->fontgrid.text_face)
 
698
#endif
 
699
    if (!fgw->fontgrid.text_font) {
 
700
        Bell (gw, XkbBI_BadValue);
 
701
        return;
 
702
    }
 
703
 
 
704
    /*
 
705
     * compute the left, right, top, and bottom cells that were damaged
 
706
     */
 
707
    XClipBox (region, &rect);
 
708
    cw = fgw->fontgrid.cell_width + fgw->fontgrid.grid_width;
 
709
    ch = fgw->fontgrid.cell_height + fgw->fontgrid.grid_width;
 
710
    if ((left = (((int) rect.x) / cw)) < 0) left = 0;
 
711
    right = (((int) (rect.x + rect.width - 1)) / cw);
 
712
    if ((top = (((int) rect.y) / ch)) < 0) top = 0;
 
713
    bottom = (((int) (rect.y + rect.height - 1)) / ch);
 
714
 
 
715
    paint_grid (fgw, left, top, right - left + 1, bottom - top + 1);
 
716
}
 
717
 
 
718
 
 
719
static void 
 
720
paint_grid(FontGridWidget fgw,          /* widget in which to draw */ 
 
721
           int col, int row,            /* where to start */          
 
722
           int ncols, int nrows)        /* number of cells */         
 
723
{
 
724
    FontGridPart *p = &fgw->fontgrid;
 
725
    int i, j;
 
726
    Display *dpy = XtDisplay(fgw);
 
727
    Window wind = XtWindow(fgw);
 
728
    int cw = p->cell_width + p->grid_width;
 
729
    int ch = p->cell_height + p->grid_width;
 
730
    int tcols = p->cell_cols;
 
731
    int trows = p->cell_rows;
 
732
    int x1, y1, x2, y2, x, y;
 
733
    unsigned maxn = GridLastChar ((Widget) fgw);
 
734
    unsigned n, prevn;
 
735
    int startx;
 
736
 
 
737
    if (col + ncols >= tcols) {
 
738
        ncols = tcols - col;
 
739
        if (ncols < 1) return;
 
740
    }
 
741
 
 
742
    if (row + nrows >= trows) {
 
743
        nrows = trows - row;
 
744
        if (nrows < 1) return;
 
745
    }
 
746
 
 
747
    /*
 
748
     * paint the grid lines for the indicated rows 
 
749
     */
 
750
    if (p->grid_width > 0) {
 
751
        int half_grid_width = p->grid_width >> 1;
 
752
        x1 = col * cw + half_grid_width;
 
753
        y1 = row * ch + half_grid_width;
 
754
        x2 = x1 + ncols * cw;
 
755
        y2 = y1 + nrows * ch;
 
756
        for (i = 0, x = x1; i <= ncols; i++, x += cw) {
 
757
            XDrawLine (dpy, wind, p->box_gc, x, y1, x, y2);
 
758
        }
 
759
        for (i = 0, y = y1; i <= nrows; i++, y += ch) {
 
760
            XDrawLine (dpy, wind, p->box_gc, x1, y, x2, y);
 
761
        }
 
762
    }
 
763
    /*
 
764
     * Draw a character in every box; treat all fonts as if they were 16bit
 
765
     * fonts.  Store the high eight bits in byte1 and the low eight bits in 
 
766
     * byte2.
 
767
     */
 
768
    prevn = p->start_char + col + row * tcols;
 
769
    startx = col * cw + p->internal_pad + p->grid_width;
 
770
    for (j = 0,
 
771
         y = row * ch + p->internal_pad + p->grid_width + GridFontAscent (fgw);
 
772
         j < nrows; j++, y += ch) {
 
773
        n = prevn;
 
774
        for (i = 0, x = startx; i < ncols; i++, x += cw) {
 
775
            int xoff = p->xoff, yoff = p->yoff;
 
776
            if (n > maxn) goto done;    /* no break out of nested */
 
777
 
 
778
#ifdef XRENDER
 
779
            if (fgw->fontgrid.text_face)
 
780
            {
 
781
                XftFont *xft = p->text_face;
 
782
                FcChar32    c = n;
 
783
                XGlyphInfo  extents;
 
784
                XftTextExtents32 (dpy, xft, &c, 1, &extents);
 
785
                if (p->center_chars)
 
786
                {
 
787
                    xoff = (p->cell_width - extents.width) / 2 - extents.x;
 
788
                    yoff = (p->cell_height - extents.height) / 2 - extents.y;
 
789
                }
 
790
                if (extents.width && extents.height)
 
791
                {
 
792
                    XClearArea (dpy, wind, x + xoff - extents.x, 
 
793
                                y + yoff - extents.y,
 
794
                                extents.width, extents.height, False);
 
795
                    if (p->box_chars)
 
796
                        XDrawRectangle (dpy, wind, p->box_gc,
 
797
                                        x + xoff - extents.x, 
 
798
                                        y + yoff - extents.y,
 
799
                                        extents.width - 1,
 
800
                                        extents.height - 1);
 
801
                }
 
802
                XftDrawString32 (p->draw, &p->fg_color, xft,
 
803
                                 x + xoff, y + yoff, &c, 1);
 
804
            }
 
805
            else
 
806
#endif
 
807
            {
 
808
            XChar2b thechar;
 
809
 
 
810
            thechar.byte1 = (n >> 8);   /* high eight bits */
 
811
            thechar.byte2 = (n & 255);  /* low eight bits */
 
812
            if (p->box_chars || p->center_chars) {
 
813
                XCharStruct metrics;
 
814
                int direction, fontascent, fontdescent;
 
815
 
 
816
                XTextExtents16 (p->text_font, &thechar, 1, &direction,
 
817
                                &fontascent, &fontdescent, &metrics);
 
818
 
 
819
                if (p->center_chars) {
 
820
                    /*
 
821
                     * We want to move the origin by enough to center the ink
 
822
                     * within the cell.  The left edge will then be at 
 
823
                     * (cell_width - (rbearing - lbearing)) / 2; so we subtract
 
824
                     * the lbearing to find the origin.  Ditto for vertical.
 
825
                     */
 
826
                    xoff = (((p->cell_width -
 
827
                              (metrics.rbearing - metrics.lbearing)) / 2) -
 
828
                            p->internal_pad - metrics.lbearing);
 
829
                    yoff = (((p->cell_height - 
 
830
                              (metrics.descent + metrics.ascent)) / 2) -
 
831
                            p->internal_pad -
 
832
                            p->text_font->ascent + metrics.ascent);
 
833
                }
 
834
                if (p->box_chars) {
 
835
                    XDrawRectangle (dpy, wind, p->box_gc,
 
836
                                    x + xoff, y + yoff - p->text_font->ascent, 
 
837
                                    metrics.width - 1,
 
838
                                    fontascent + fontdescent - 1);
 
839
                }
 
840
            }
 
841
            XDrawString16 (dpy, wind, p->text_gc, x + xoff, y + yoff,
 
842
                           &thechar, 1);
 
843
            }
 
844
            n++;
 
845
        }
 
846
        prevn += tcols;
 
847
    }
 
848
 
 
849
  done:
 
850
    /*
 
851
     * paint the grid lines for the indicated rows 
 
852
     */
 
853
    if (p->grid_width > 0) {
 
854
        int half_grid_width = p->grid_width >> 1;
 
855
        x1 = col * cw + half_grid_width;
 
856
        y1 = row * ch + half_grid_width;
 
857
        x2 = x1 + ncols * cw;
 
858
        y2 = y1 + nrows * ch;
 
859
        for (i = 0, x = x1; i <= ncols; i++, x += cw) {
 
860
            XDrawLine (dpy, wind, p->box_gc, x, y1, x, y2);
 
861
        }
 
862
        for (i = 0, y = y1; i <= nrows; i++, y += ch) {
 
863
            XDrawLine (dpy, wind, p->box_gc, x1, y, x2, y);
 
864
        }
 
865
    }
 
866
 
 
867
        
 
868
    return;
 
869
}
 
870
 
 
871
static Boolean
 
872
PageBlank (Widget w, long first, long last)
 
873
{
 
874
    while (first <= last)
 
875
    {
 
876
        if (GridHasChar (w, first))
 
877
            return False;
 
878
        first++;
 
879
    }
 
880
    return True;
 
881
}
 
882
 
 
883
/*ARGSUSED*/
 
884
static Boolean 
 
885
SetValues(Widget current, Widget request, Widget new, 
 
886
          ArgList args, Cardinal *num_args)
 
887
{
 
888
    FontGridWidget curfg = (FontGridWidget) current;
 
889
    FontGridWidget newfg = (FontGridWidget) new;
 
890
    Boolean redisplay = FALSE;
 
891
 
 
892
    if (curfg->fontgrid.text_font != newfg->fontgrid.text_font ||
 
893
        curfg->fontgrid.internal_pad != newfg->fontgrid.internal_pad) {
 
894
        newfg->fontgrid.cell_width = DefaultCellWidth (newfg);
 
895
        newfg->fontgrid.cell_height = DefaultCellHeight (newfg);
 
896
        redisplay = TRUE;
 
897
    }
 
898
 
 
899
    if (GridForeground(curfg) != GridForeground (newfg)) {
 
900
        XtReleaseGC (new, curfg->fontgrid.text_gc);
 
901
        newfg->fontgrid.text_gc = get_gc (newfg, GridForeground (newfg));
 
902
        redisplay = TRUE;
 
903
    }
 
904
 
 
905
    if (curfg->fontgrid.box_pixel != newfg->fontgrid.box_pixel) {
 
906
        XtReleaseGC (new, curfg->fontgrid.text_gc);
 
907
        newfg->fontgrid.box_gc = get_gc (newfg, newfg->fontgrid.box_pixel);
 
908
        redisplay = TRUE;
 
909
    }
 
910
 
 
911
    if (curfg->fontgrid.center_chars != newfg->fontgrid.center_chars ||
 
912
        curfg->fontgrid.box_chars != newfg->fontgrid.box_chars)
 
913
      redisplay = TRUE;
 
914
 
 
915
    if (curfg->fontgrid.start_char != newfg->fontgrid.start_char) {
 
916
        long maxn = GridLastChar (new);
 
917
        long page = newfg->fontgrid.cell_cols * newfg->fontgrid.cell_rows;
 
918
        long dir = page;
 
919
        long start = newfg->fontgrid.start_char;
 
920
 
 
921
        if (start < curfg->fontgrid.start_char)
 
922
            dir = -page;
 
923
 
 
924
        if (start < 0)
 
925
            start = 0;
 
926
        if (start > maxn) 
 
927
          start = (maxn / page) * page;
 
928
        
 
929
        while (PageBlank (new, start, start + page - 1))
 
930
        {
 
931
            long    next = start + dir;
 
932
 
 
933
            if (next < 0 || maxn < next)
 
934
                break;
 
935
            start = next;
 
936
        }
 
937
 
 
938
        newfg->fontgrid.start_char = start;
 
939
        redisplay = (curfg->fontgrid.start_char != newfg->fontgrid.start_char);
 
940
    }
 
941
 
 
942
    return redisplay;
 
943
}
 
944
 
 
945
 
 
946
/* ARGSUSED */
 
947
static void 
 
948
Notify(Widget gw, XEvent *event, String *params, Cardinal *nparams)
 
949
{
 
950
    FontGridWidget fgw = (FontGridWidget) gw;
 
951
    int x, y;                           /* where the event happened */
 
952
    FontGridCharRec rec;                /* callback data */
 
953
 
 
954
    /*
 
955
     * only allow events with (x,y)
 
956
     */
 
957
    switch (event->type) {
 
958
      case KeyPress:
 
959
      case KeyRelease:
 
960
        x = event->xkey.x;
 
961
        y = event->xkey.y;
 
962
        break;
 
963
      case ButtonPress:
 
964
      case ButtonRelease:
 
965
        x = event->xbutton.x;
 
966
        y = event->xbutton.y;
 
967
        break;
 
968
      case MotionNotify:
 
969
        x = event->xmotion.x;
 
970
        y = event->xmotion.y;
 
971
        break;
 
972
      default:
 
973
        Bell (gw, XkbBI_Ignore);
 
974
        return;
 
975
    }
 
976
 
 
977
    /*
 
978
     * compute the callback data
 
979
     */
 
980
    {
 
981
        int cw = fgw->fontgrid.cell_width + fgw->fontgrid.grid_width;
 
982
        int ch = fgw->fontgrid.cell_height + fgw->fontgrid.grid_width;
 
983
        unsigned n;
 
984
 
 
985
        if (x > (fgw->fontgrid.cell_cols * cw)) {
 
986
            Bell (gw, XkbBI_InvalidLocation);
 
987
            return;
 
988
        }
 
989
 
 
990
        n= (fgw->fontgrid.start_char + 
 
991
            ((y / ch) * fgw->fontgrid.cell_cols) + (x / cw));
 
992
 
 
993
        rec.thefont = fgw->fontgrid.text_font;
 
994
#ifdef XRENDER
 
995
        rec.theface = fgw->fontgrid.text_face;
 
996
#endif
 
997
        rec.thechar = n;
 
998
    }
 
999
 
 
1000
    XtCallCallbacks (gw, XtNcallback, (XtPointer) &rec);
 
1001
}
 
1002