~ubuntu-branches/ubuntu/karmic/emacs-snapshot/karmic

« back to all changes in this revision

Viewing changes to src/xfont.c

  • Committer: Bazaar Package Importer
  • Author(s): Romain Francoise
  • Date: 2008-02-28 20:55:55 UTC
  • mfrom: (1.1.25 upstream)
  • Revision ID: james.westby@ubuntu.com-20080228205555-ceojhq23xapxavpp
Tags: 1:20080228-1
* New snapshot.

* debian/rules:
  + Build emacs-nox without sound support.
  + Use bzip2 compression to save bandwidth.

* debian/patches/tmp-fixes.diff: Revert a bunch of commits which break
  reverse video in the modeline.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* xfont.c -- X core font driver.
 
2
   Copyright (C) 2006, 2007, 2008 Free Software Foundation, Inc.
 
3
   Copyright (C) 2006, 2007, 2008
 
4
     National Institute of Advanced Industrial Science and Technology (AIST)
 
5
     Registration Number H13PRO009
 
6
 
 
7
This file is part of GNU Emacs.
 
8
 
 
9
GNU Emacs is free software; you can redistribute it and/or modify
 
10
it under the terms of the GNU General Public License as published by
 
11
the Free Software Foundation; either version 3, or (at your option)
 
12
any later version.
 
13
 
 
14
GNU Emacs is distributed in the hope that it will be useful,
 
15
but WITHOUT ANY WARRANTY; without even the implied warranty of
 
16
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
17
GNU General Public License for more details.
 
18
 
 
19
You should have received a copy of the GNU General Public License
 
20
along with GNU Emacs; see the file COPYING.  If not, write to
 
21
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 
22
Boston, MA 02110-1301, USA.  */
 
23
 
 
24
#include <config.h>
 
25
#include <stdio.h>
 
26
#include <X11/Xlib.h>
 
27
 
 
28
#include "lisp.h"
 
29
#include "dispextern.h"
 
30
#include "xterm.h"
 
31
#include "frame.h"
 
32
#include "blockinput.h"
 
33
#include "character.h"
 
34
#include "charset.h"
 
35
#include "fontset.h"
 
36
#include "font.h"
 
37
 
 
38
 
 
39
/* X core font driver.  */
 
40
 
 
41
/* Prototypes of support functions.  */
 
42
extern void x_clear_errors P_ ((Display *));
 
43
 
 
44
static char *xfont_query_font P_ ((Display *, char *, Lisp_Object));
 
45
static XCharStruct *xfont_get_pcm P_ ((XFontStruct *, XChar2b *));
 
46
static int xfont_registry_charsets P_ ((Lisp_Object, struct charset **,
 
47
                                        struct charset **));
 
48
 
 
49
static char *
 
50
xfont_query_font (display, name, spec)
 
51
     Display *display;
 
52
     char *name;
 
53
     Lisp_Object spec;
 
54
{
 
55
  XFontStruct *font;
 
56
 
 
57
  BLOCK_INPUT;
 
58
  x_catch_errors (display);
 
59
  font = XLoadQueryFont (display, name);
 
60
  name = NULL;
 
61
  if (x_had_errors_p (display))
 
62
    {
 
63
      /* This error is perhaps due to insufficient memory on X
 
64
         server.  Let's just ignore it.  */
 
65
      x_clear_errors (display);
 
66
    }
 
67
  else if (font)
 
68
    {
 
69
      unsigned long value;
 
70
 
 
71
      if (XGetFontProperty (font, XA_FONT, &value))
 
72
        {
 
73
          char *n = (char *) XGetAtomName (display, (Atom) value);
 
74
 
 
75
          if (font_parse_xlfd (n, spec) >= 0)
 
76
            name = n;
 
77
          else
 
78
            XFree (n);
 
79
        }
 
80
      XFreeFont (display, font);
 
81
    }
 
82
  x_uncatch_errors ();
 
83
  UNBLOCK_INPUT;
 
84
 
 
85
  return name;
 
86
}
 
87
 
 
88
 
 
89
/* Get metrics of character CHAR2B in XFONT.  Value is null if CHAR2B
 
90
   is not contained in the font.  */
 
91
 
 
92
static XCharStruct *
 
93
xfont_get_pcm (xfont, char2b)
 
94
     XFontStruct *xfont;
 
95
     XChar2b *char2b;
 
96
{
 
97
  /* The result metric information.  */
 
98
  XCharStruct *pcm = NULL;
 
99
 
 
100
  xassert (xfont && char2b);
 
101
 
 
102
  if (xfont->per_char != NULL)
 
103
    {
 
104
      if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
 
105
        {
 
106
          /* min_char_or_byte2 specifies the linear character index
 
107
             corresponding to the first element of the per_char array,
 
108
             max_char_or_byte2 is the index of the last character.  A
 
109
             character with non-zero CHAR2B->byte1 is not in the font.
 
110
             A character with byte2 less than min_char_or_byte2 or
 
111
             greater max_char_or_byte2 is not in the font.  */
 
112
          if (char2b->byte1 == 0
 
113
              && char2b->byte2 >= xfont->min_char_or_byte2
 
114
              && char2b->byte2 <= xfont->max_char_or_byte2)
 
115
            pcm = xfont->per_char + char2b->byte2 - xfont->min_char_or_byte2;
 
116
        }
 
117
      else
 
118
        {
 
119
          /* If either min_byte1 or max_byte1 are nonzero, both
 
120
             min_char_or_byte2 and max_char_or_byte2 are less than
 
121
             256, and the 2-byte character index values corresponding
 
122
             to the per_char array element N (counting from 0) are:
 
123
 
 
124
             byte1 = N/D + min_byte1
 
125
             byte2 = N\D + min_char_or_byte2
 
126
 
 
127
             where:
 
128
 
 
129
             D = max_char_or_byte2 - min_char_or_byte2 + 1
 
130
             / = integer division
 
131
             \ = integer modulus  */
 
132
          if (char2b->byte1 >= xfont->min_byte1
 
133
              && char2b->byte1 <= xfont->max_byte1
 
134
              && char2b->byte2 >= xfont->min_char_or_byte2
 
135
              && char2b->byte2 <= xfont->max_char_or_byte2)
 
136
            pcm = (xfont->per_char
 
137
                   + ((xfont->max_char_or_byte2 - xfont->min_char_or_byte2 + 1)
 
138
                      * (char2b->byte1 - xfont->min_byte1))
 
139
                   + (char2b->byte2 - xfont->min_char_or_byte2));
 
140
        }
 
141
    }
 
142
  else
 
143
    {
 
144
      /* If the per_char pointer is null, all glyphs between the first
 
145
         and last character indexes inclusive have the same
 
146
         information, as given by both min_bounds and max_bounds.  */
 
147
      if (char2b->byte2 >= xfont->min_char_or_byte2
 
148
          && char2b->byte2 <= xfont->max_char_or_byte2)
 
149
        pcm = &xfont->max_bounds;
 
150
    }
 
151
 
 
152
  return ((pcm == NULL
 
153
           || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
 
154
          ? NULL : pcm);
 
155
}
 
156
 
 
157
static Lisp_Object xfont_get_cache P_ ((FRAME_PTR));
 
158
static Lisp_Object xfont_list P_ ((Lisp_Object, Lisp_Object));
 
159
static Lisp_Object xfont_match P_ ((Lisp_Object, Lisp_Object));
 
160
static Lisp_Object xfont_list_family P_ ((Lisp_Object));
 
161
static struct font *xfont_open P_ ((FRAME_PTR, Lisp_Object, int));
 
162
static void xfont_close P_ ((FRAME_PTR, struct font *));
 
163
static int xfont_prepare_face P_ ((FRAME_PTR, struct face *));
 
164
#if 0
 
165
static void xfont_done_face P_ ((FRAME_PTR, struct face *));
 
166
#endif
 
167
static int xfont_has_char P_ ((Lisp_Object, int));
 
168
static unsigned xfont_encode_char P_ ((struct font *, int));
 
169
static int xfont_text_extents P_ ((struct font *, unsigned *, int,
 
170
                                   struct font_metrics *));
 
171
static int xfont_draw P_ ((struct glyph_string *, int, int, int, int, int));
 
172
 
 
173
struct font_driver xfont_driver =
 
174
  {
 
175
    0,                          /* Qx */
 
176
    xfont_get_cache,
 
177
    xfont_list,
 
178
    xfont_match,
 
179
    xfont_list_family,
 
180
    NULL,
 
181
    xfont_open,
 
182
    xfont_close,
 
183
    xfont_prepare_face,
 
184
    NULL /*xfont_done_face*/,
 
185
    xfont_has_char,
 
186
    xfont_encode_char,
 
187
    xfont_text_extents,
 
188
    xfont_draw
 
189
  };
 
190
 
 
191
extern Lisp_Object QCname;
 
192
 
 
193
static Lisp_Object
 
194
xfont_get_cache (f)
 
195
     FRAME_PTR f;
 
196
{
 
197
  Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
 
198
 
 
199
  return (dpyinfo->name_list_element);
 
200
}
 
201
 
 
202
extern Lisp_Object Vface_alternative_font_registry_alist;
 
203
 
 
204
static Lisp_Object
 
205
xfont_list_pattern (frame, display, pattern)
 
206
     Lisp_Object frame;
 
207
     Display *display;
 
208
     char *pattern;
 
209
{
 
210
  Lisp_Object list = Qnil;
 
211
  int i, limit, num_fonts;
 
212
  char **names;
 
213
 
 
214
  BLOCK_INPUT;
 
215
  x_catch_errors (display);
 
216
 
 
217
  for (limit = 512; ; limit *= 2)
 
218
    {
 
219
      names = XListFonts (display, pattern, limit, &num_fonts);
 
220
      if (x_had_errors_p (display))
 
221
        {
 
222
          /* This error is perhaps due to insufficient memory on X
 
223
             server.  Let's just ignore it.  */
 
224
          x_clear_errors (display);
 
225
          num_fonts = 0;
 
226
          break;
 
227
        }
 
228
      if (num_fonts < limit)
 
229
        break;
 
230
      XFreeFontNames (names);
 
231
    }
 
232
 
 
233
  for (i = 0; i < num_fonts; i++)
 
234
    {
 
235
      Lisp_Object entity = Fmake_vector (make_number (FONT_ENTITY_MAX), Qnil);
 
236
      int result;
 
237
 
 
238
      ASET (entity, FONT_TYPE_INDEX, Qx);
 
239
      ASET (entity, FONT_FRAME_INDEX, frame);
 
240
 
 
241
      result = font_parse_xlfd (names[i], entity);
 
242
      if (result < 0)
 
243
        {
 
244
          /* This may be an alias name.  Try to get the full XLFD name
 
245
             from XA_FONT property of the font.  */
 
246
          XFontStruct *font = XLoadQueryFont (display, names[i]);
 
247
          unsigned long value;
 
248
 
 
249
          if (! font)
 
250
            continue;
 
251
          if (XGetFontProperty (font, XA_FONT, &value))
 
252
            {
 
253
              char *name = (char *) XGetAtomName (display, (Atom) value);
 
254
              int len = strlen (name);
 
255
 
 
256
              /* If DXPC (a Differential X Protocol Compressor)
 
257
                 Ver.3.7 is running, XGetAtomName will return null
 
258
                 string.  We must avoid such a name.  */
 
259
              if (len > 0)
 
260
                result = font_parse_xlfd (name, entity);
 
261
              XFree (name);
 
262
            }
 
263
          XFreeFont (display, font);
 
264
        }
 
265
 
 
266
      if (result == 0)
 
267
        {
 
268
          Lisp_Object val = AREF (entity, FONT_EXTRA_INDEX);
 
269
          char *p = (char *) SDATA (SYMBOL_NAME (val));
 
270
 
 
271
          /* P == "RESX-RESY-SPACING-AVGWIDTH.  We rejust this font if
 
272
             it's an autoscaled one (i.e. RESX > 0 && AVGWIDTH == 0).  */
 
273
          if (atoi (p) > 0)
 
274
            {
 
275
              p += SBYTES (SYMBOL_NAME (val));
 
276
              while (p[-1] != '-') p--;
 
277
              if (atoi (p) == 0)
 
278
                continue;
 
279
            }
 
280
          list = Fcons (entity, list);
 
281
        }
 
282
    }
 
283
 
 
284
  x_uncatch_errors ();
 
285
  UNBLOCK_INPUT;
 
286
 
 
287
  return list;
 
288
}
 
289
 
 
290
static Lisp_Object
 
291
xfont_list (frame, spec)
 
292
     Lisp_Object frame, spec;
 
293
{
 
294
  FRAME_PTR f = XFRAME (frame);
 
295
  Display *display = FRAME_X_DISPLAY_INFO (f)->display;
 
296
  Lisp_Object list, val, extra, font_name;
 
297
  int len;
 
298
  char name[256];
 
299
  
 
300
  extra = AREF (spec, FONT_EXTRA_INDEX);
 
301
  font_name = Qnil;
 
302
  if (CONSP (extra))
 
303
    {
 
304
      val = assq_no_quit (QCotf, extra);
 
305
      if (! NILP (val))
 
306
        return null_vector;
 
307
      val = assq_no_quit (QCscript, extra);
 
308
      if (! NILP (val))
 
309
        return null_vector;
 
310
      val = assq_no_quit (QClanguage, extra);
 
311
      if (! NILP (val))
 
312
        return null_vector;
 
313
      val = assq_no_quit (QCname, extra);
 
314
      if (CONSP (val))
 
315
        font_name = XCDR (val);
 
316
    }
 
317
 
 
318
  if (STRINGP (font_name)
 
319
      && ! strchr ((char *) SDATA (font_name), ':'))
 
320
    list = xfont_list_pattern (frame, display, (char *) SDATA (font_name));
 
321
  else if ((len = font_unparse_xlfd (spec, 0, name, 256)) < 0)
 
322
    return null_vector;
 
323
  else
 
324
    {
 
325
      list = xfont_list_pattern (frame, display, name);
 
326
      if (NILP (list))
 
327
        {
 
328
          Lisp_Object registry = AREF (spec, FONT_REGISTRY_INDEX);
 
329
          Lisp_Object alter;
 
330
 
 
331
          if (! NILP (registry)
 
332
              && (alter = Fassoc (SYMBOL_NAME (registry),
 
333
                                  Vface_alternative_font_registry_alist),
 
334
                  CONSP (alter)))
 
335
            {
 
336
              /* Pointer to REGISTRY-ENCODING field.  */
 
337
              char *r = name + len - SBYTES (SYMBOL_NAME (registry));
 
338
 
 
339
              for (alter = XCDR (alter); CONSP (alter); alter = XCDR (alter))
 
340
                if (STRINGP (XCAR (alter))
 
341
                    && ((r - name) + SBYTES (XCAR (alter))) < 255)
 
342
                  {
 
343
                    strcpy (r, (char *) SDATA (XCAR (alter)));
 
344
                    list = xfont_list_pattern (frame, display, name);
 
345
                    if (! NILP (list))
 
346
                      break;
 
347
                  }
 
348
            }
 
349
        }
 
350
    }
 
351
 
 
352
  return (NILP (list) ? null_vector : Fvconcat (1, &list));
 
353
}
 
354
 
 
355
static Lisp_Object
 
356
xfont_match (frame, spec)
 
357
     Lisp_Object frame, spec;
 
358
{
 
359
  FRAME_PTR f = XFRAME (frame);
 
360
  Display *display = FRAME_X_DISPLAY_INFO (f)->display;
 
361
  Lisp_Object extra, val, entity;
 
362
  char *name;
 
363
  XFontStruct *xfont;
 
364
  unsigned long value;
 
365
 
 
366
  extra = AREF (spec, FONT_EXTRA_INDEX);
 
367
  val = assq_no_quit (QCname, extra);
 
368
  if (! CONSP (val) || ! STRINGP (XCDR (val)))
 
369
    return Qnil;
 
370
 
 
371
  BLOCK_INPUT;
 
372
  entity = Qnil;
 
373
  name = (char *) SDATA (XCDR (val));
 
374
  xfont = XLoadQueryFont (display, name);
 
375
  if (xfont)
 
376
    {
 
377
      if (XGetFontProperty (xfont, XA_FONT, &value))
 
378
        {
 
379
          int len;
 
380
 
 
381
          name = (char *) XGetAtomName (display, (Atom) value);
 
382
          len = strlen (name);
 
383
 
 
384
          /* If DXPC (a Differential X Protocol Compressor)
 
385
             Ver.3.7 is running, XGetAtomName will return null
 
386
             string.  We must avoid such a name.  */
 
387
          if (len > 0)
 
388
            {
 
389
              entity = Fmake_vector (make_number (FONT_ENTITY_MAX), Qnil);
 
390
              ASET (entity, FONT_TYPE_INDEX, Qx);
 
391
              ASET (entity, FONT_FRAME_INDEX, frame);
 
392
              if (font_parse_xlfd (name, entity) < 0)
 
393
                entity = Qnil;
 
394
            }
 
395
          XFree (name);
 
396
        }
 
397
      XFreeFont (display, xfont);
 
398
    }
 
399
  UNBLOCK_INPUT;
 
400
 
 
401
  return entity;
 
402
}
 
403
 
 
404
static int
 
405
memq_no_quit (elt, list)
 
406
     Lisp_Object elt, list;
 
407
{
 
408
  while (CONSP (list) && ! EQ (XCAR (list), elt))
 
409
    list = XCDR (list);
 
410
  return (CONSP (list));
 
411
}
 
412
 
 
413
static Lisp_Object
 
414
xfont_list_family (frame)
 
415
     Lisp_Object frame;
 
416
{
 
417
  FRAME_PTR f = XFRAME (frame);
 
418
  Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
 
419
  char **names;
 
420
  int num_fonts, i;
 
421
  Lisp_Object list;
 
422
  char *last_family;
 
423
  int last_len;
 
424
 
 
425
  BLOCK_INPUT;
 
426
  x_catch_errors (dpyinfo->display);
 
427
  names = XListFonts (dpyinfo->display, "-*-*-*-*-*-*-*-*-*-*-*-*-*-*",
 
428
                      0x8000, &num_fonts);
 
429
  if (x_had_errors_p (dpyinfo->display))
 
430
    {
 
431
      /* This error is perhaps due to insufficient memory on X server.
 
432
         Let's just ignore it.  */
 
433
      x_clear_errors (dpyinfo->display);
 
434
      num_fonts = 0;
 
435
    }
 
436
 
 
437
  list = Qnil;
 
438
  for (i = 0, last_len = 0; i < num_fonts; i++)
 
439
    {
 
440
      char *p0 = names[i], *p1;
 
441
      Lisp_Object family;
 
442
 
 
443
      p0++;                     /* skip the leading '-' */
 
444
      while (*p0 && *p0 != '-') p0++; /* skip foundry */
 
445
      if (! *p0)
 
446
        continue;
 
447
      p1 = ++p0;
 
448
      while (*p1 && *p1 != '-') p1++; /* find the end of family */
 
449
      if (! *p1 || p1 == p0)
 
450
        continue;
 
451
      if (last_len == p1 - p0
 
452
          && bcmp (last_family, p0, last_len) == 0)
 
453
        continue;
 
454
      last_len = p1 - p0;
 
455
      last_family = p0;
 
456
      family = intern_downcase (p0, last_len);
 
457
      if (! memq_no_quit (family, list))
 
458
        list = Fcons (family, list);
 
459
    }
 
460
 
 
461
  XFreeFontNames (names);
 
462
  x_uncatch_errors ();
 
463
  UNBLOCK_INPUT;
 
464
 
 
465
  return list;
 
466
}
 
467
 
 
468
static struct font *
 
469
xfont_open (f, entity, pixel_size)
 
470
     FRAME_PTR f;
 
471
     Lisp_Object entity;
 
472
     int pixel_size;
 
473
{
 
474
  Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
 
475
  Display *display = dpyinfo->display;
 
476
  char name[256];
 
477
  int len;
 
478
  unsigned long value;
 
479
  Lisp_Object registry;
 
480
  struct charset *encoding, *repertory;
 
481
  struct font *font;
 
482
  XFontStruct *xfont;
 
483
 
 
484
  /* At first, check if we know how to encode characters for this
 
485
     font.  */
 
486
  registry = AREF (entity, FONT_REGISTRY_INDEX);
 
487
  if (font_registry_charsets (registry, &encoding, &repertory) < 0)
 
488
    return NULL;
 
489
 
 
490
  if (XINT (AREF (entity, FONT_SIZE_INDEX)) != 0)
 
491
    pixel_size = XINT (AREF (entity, FONT_SIZE_INDEX));
 
492
  len = font_unparse_xlfd (entity, pixel_size, name, 256);
 
493
  if (len <= 0)
 
494
    return NULL;
 
495
 
 
496
  BLOCK_INPUT;
 
497
  x_catch_errors (display);
 
498
  xfont = XLoadQueryFont (display, name);
 
499
  if (x_had_errors_p (display))
 
500
    {
 
501
      /* This error is perhaps due to insufficient memory on X server.
 
502
         Let's just ignore it.  */
 
503
      x_clear_errors (display);
 
504
      xfont = NULL;
 
505
    }
 
506
  x_uncatch_errors ();
 
507
  UNBLOCK_INPUT;
 
508
 
 
509
  if (! xfont)
 
510
    return NULL;
 
511
  font = malloc (sizeof (struct font));
 
512
  font->format = Qx;
 
513
  font->font.font = xfont;
 
514
  font->entity = entity;
 
515
  font->pixel_size = pixel_size;
 
516
  font->driver = &xfont_driver;
 
517
  font->font.name = malloc (len + 1);
 
518
  if (! font->font.name)
 
519
    {
 
520
      XFreeFont (display, xfont);
 
521
      free (font);
 
522
      return NULL;
 
523
    }
 
524
  bcopy (name, font->font.name, len + 1);
 
525
  font->font.charset = encoding->id;
 
526
  font->encoding_charset = encoding->id;
 
527
  font->repertory_charset = repertory ? repertory->id : -1;
 
528
  font->ascent = xfont->ascent;
 
529
  font->descent = xfont->descent;
 
530
 
 
531
  if (xfont->min_bounds.width == xfont->max_bounds.width)
 
532
    {
 
533
      /* Fixed width font.  */
 
534
      font->font.average_width = font->font.space_width
 
535
        = xfont->min_bounds.width;
 
536
    }
 
537
  else
 
538
    {
 
539
      XChar2b char2b;
 
540
      XCharStruct *pcm;
 
541
 
 
542
      char2b.byte1 = 0x00, char2b.byte2 = 0x20;
 
543
      pcm = xfont_get_pcm (xfont, &char2b);
 
544
      if (pcm)
 
545
        font->font.space_width = pcm->width;
 
546
      else
 
547
        font->font.space_width = xfont->max_bounds.width;
 
548
 
 
549
      font->font.average_width
 
550
        = (XGetFontProperty (xfont, dpyinfo->Xatom_AVERAGE_WIDTH, &value)
 
551
           ? (long) value / 10 : 0);
 
552
      if (font->font.average_width < 0)
 
553
        font->font.average_width = - font->font.average_width;
 
554
      if (font->font.average_width == 0)
 
555
        {
 
556
          if (pcm)
 
557
            {
 
558
              int width = pcm->width;
 
559
              for (char2b.byte2 = 33; char2b.byte2 <= 126; char2b.byte2++)
 
560
                if ((pcm = xfont_get_pcm (xfont, &char2b)) != NULL)
 
561
                  width += pcm->width;
 
562
              font->font.average_width = width / 95;
 
563
            }
 
564
          else
 
565
            font->font.average_width = xfont->max_bounds.width;
 
566
        }
 
567
    }
 
568
  font->min_width = xfont->min_bounds.width;
 
569
  if (font->min_width <= 0)
 
570
    font->min_width = font->font.space_width;
 
571
 
 
572
  BLOCK_INPUT;
 
573
  /* Try to get the full name of FONT.  Put it in FULL_NAME.  */
 
574
  if (XGetFontProperty (xfont, XA_FONT, &value))
 
575
    {
 
576
      char *full_name = NULL, *p0, *p;
 
577
      int dashes = 0;
 
578
 
 
579
      p0 = p = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);;
 
580
      /* Count the number of dashes in the "full name".
 
581
         If it is too few, this isn't really the font's full name,
 
582
         so don't use it.
 
583
         In X11R4, the fonts did not come with their canonical names
 
584
         stored in them.  */
 
585
      while (*p)
 
586
        {
 
587
          if (*p == '-')
 
588
            dashes++;
 
589
          p++;
 
590
        }
 
591
 
 
592
      if (dashes >= 13)
 
593
        {
 
594
          full_name = (char *) malloc (p - p0 + 1);
 
595
          if (full_name)
 
596
            bcopy (p0, full_name, p - p0 + 1);
 
597
        }
 
598
      XFree (p0);
 
599
 
 
600
      if (full_name)
 
601
        font->font.full_name = full_name;
 
602
      else
 
603
        font->font.full_name = font->font.name;
 
604
    }
 
605
  font->file_name = NULL;
 
606
 
 
607
  font->font.size = xfont->max_bounds.width;
 
608
  font->font.height = xfont->ascent + xfont->descent;
 
609
  font->font.baseline_offset
 
610
    = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
 
611
       ? (long) value : 0);
 
612
  font->font.relative_compose
 
613
    = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
 
614
       ? (long) value : 0);
 
615
  font->font.default_ascent
 
616
    = (XGetFontProperty (xfont, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
 
617
       ? (long) value : 0);
 
618
  font->font.vertical_centering
 
619
    = (STRINGP (Vvertical_centering_font_regexp)
 
620
       && (fast_c_string_match_ignore_case
 
621
           (Vvertical_centering_font_regexp, font->font.full_name) >= 0));
 
622
 
 
623
  UNBLOCK_INPUT;
 
624
 
 
625
  dpyinfo->n_fonts++;
 
626
 
 
627
  /* Set global flag fonts_changed_p to non-zero if the font loaded
 
628
     has a character with a smaller width than any other character
 
629
     before, or if the font loaded has a smaller height than any other
 
630
     font loaded before.  If this happens, it will make a glyph matrix
 
631
     reallocation necessary.  */
 
632
  if (dpyinfo->n_fonts == 1)
 
633
    {
 
634
      dpyinfo->smallest_font_height = font->font.height;
 
635
      dpyinfo->smallest_char_width = font->min_width;
 
636
      fonts_changed_p = 1;
 
637
    }
 
638
  else
 
639
    {
 
640
      if (dpyinfo->smallest_font_height > font->font.height)
 
641
        dpyinfo->smallest_font_height = font->font.height, fonts_changed_p |= 1;
 
642
      if (dpyinfo->smallest_char_width > font->min_width)
 
643
        dpyinfo->smallest_char_width = font->min_width, fonts_changed_p |= 1;
 
644
    }
 
645
 
 
646
  return font;
 
647
}
 
648
 
 
649
static void
 
650
xfont_close (f, font)
 
651
     FRAME_PTR f;
 
652
     struct font *font;
 
653
{
 
654
  BLOCK_INPUT;
 
655
  XFreeFont (FRAME_X_DISPLAY (f), font->font.font);
 
656
  UNBLOCK_INPUT;
 
657
 
 
658
  if (font->font.name != font->font.full_name)
 
659
    free (font->font.full_name);
 
660
  free (font->font.name);
 
661
  free (font);
 
662
  FRAME_X_DISPLAY_INFO (f)->n_fonts--;
 
663
}
 
664
 
 
665
static int
 
666
xfont_prepare_face (f, face)
 
667
     FRAME_PTR f;
 
668
     struct face *face;
 
669
{
 
670
  BLOCK_INPUT;
 
671
  XSetFont (FRAME_X_DISPLAY (f), face->gc, face->font->fid);
 
672
  UNBLOCK_INPUT;
 
673
 
 
674
  return 0;
 
675
}
 
676
 
 
677
#if 0
 
678
static void
 
679
xfont_done_face (f, face)
 
680
     FRAME_PTR f;
 
681
     struct face *face;
 
682
{
 
683
  if (face->extra)
 
684
    {
 
685
      BLOCK_INPUT;
 
686
      XFreeGC (FRAME_X_DISPLAY (f), (GC) face->extra);
 
687
      UNBLOCK_INPUT;
 
688
      face->extra = NULL;
 
689
    }
 
690
}
 
691
#endif  /* 0 */
 
692
 
 
693
static int
 
694
xfont_has_char (entity, c)
 
695
     Lisp_Object entity;
 
696
     int c;
 
697
{
 
698
  Lisp_Object registry = AREF (entity, FONT_REGISTRY_INDEX);
 
699
  struct charset *repertory;
 
700
 
 
701
  if (font_registry_charsets (registry, NULL, &repertory) < 0)
 
702
    return -1;
 
703
  if (! repertory)
 
704
    return -1;
 
705
  return (ENCODE_CHAR (repertory, c) != CHARSET_INVALID_CODE (repertory));
 
706
}
 
707
 
 
708
static unsigned
 
709
xfont_encode_char (font, c)
 
710
     struct font *font;
 
711
     int c;
 
712
{
 
713
  struct charset *charset;
 
714
  unsigned code;
 
715
  XChar2b char2b;
 
716
 
 
717
  charset = CHARSET_FROM_ID (font->encoding_charset);
 
718
  code = ENCODE_CHAR (charset, c);
 
719
  if (code == CHARSET_INVALID_CODE (charset))
 
720
    return FONT_INVALID_CODE;
 
721
  if (font->repertory_charset >= 0)
 
722
    {
 
723
      charset = CHARSET_FROM_ID (font->repertory_charset);
 
724
      return (ENCODE_CHAR (charset, c) != CHARSET_INVALID_CODE (charset)
 
725
              ? code : FONT_INVALID_CODE);
 
726
    }
 
727
  char2b.byte1 = code >> 8;
 
728
  char2b.byte2 = code & 0xFF;
 
729
  return (xfont_get_pcm (font->font.font, &char2b) ? code : FONT_INVALID_CODE);
 
730
}
 
731
 
 
732
static int
 
733
xfont_text_extents (font, code, nglyphs, metrics)
 
734
     struct font *font;
 
735
     unsigned *code;
 
736
     int nglyphs;
 
737
     struct font_metrics *metrics;
 
738
{
 
739
  int width = 0;
 
740
  int i, x;
 
741
 
 
742
  if (metrics)
 
743
    bzero (metrics, sizeof (struct font_metrics));
 
744
  for (i = 0, x = 0; i < nglyphs; i++)
 
745
    {
 
746
      XChar2b char2b;
 
747
      static XCharStruct *pcm;
 
748
 
 
749
      if (code[i] >= 0x10000)
 
750
        continue;
 
751
      char2b.byte1 = code[i] >> 8, char2b.byte2 = code[i] & 0xFF;
 
752
      pcm = xfont_get_pcm (font->font.font, &char2b);
 
753
      if (! pcm)
 
754
        continue;
 
755
      if (metrics->lbearing > width + pcm->lbearing)
 
756
        metrics->lbearing = width + pcm->lbearing;
 
757
      if (metrics->rbearing < width + pcm->rbearing)
 
758
        metrics->rbearing = width + pcm->rbearing;
 
759
      if (metrics->ascent < pcm->ascent)
 
760
        metrics->ascent = pcm->ascent;
 
761
      if (metrics->descent < pcm->descent)
 
762
        metrics->descent = pcm->descent;
 
763
      width += pcm->width;
 
764
    }
 
765
  if (metrics)
 
766
    metrics->width = width;
 
767
  return width;
 
768
}
 
769
 
 
770
static int
 
771
xfont_draw (s, from, to, x, y, with_background)
 
772
     struct glyph_string *s;
 
773
     int from, to, x, y, with_background;
 
774
{
 
775
  XFontStruct *xfont = s->face->font;
 
776
  int len = to - from;
 
777
  GC gc = s->gc;
 
778
  int i;
 
779
 
 
780
  if (gc != s->face->gc)
 
781
    {
 
782
      XGCValues xgcv;
 
783
      Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (s->f);
 
784
 
 
785
      BLOCK_INPUT;
 
786
      XGetGCValues (s->display, gc, GCFont, &xgcv);
 
787
      if (xgcv.font != xfont->fid)
 
788
        XSetFont (s->display, gc, xfont->fid);
 
789
      UNBLOCK_INPUT;
 
790
    }
 
791
 
 
792
  if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
 
793
    {
 
794
      char *str;
 
795
      USE_SAFE_ALLOCA;
 
796
 
 
797
      SAFE_ALLOCA (str, char *, len);
 
798
      for (i = 0; i < len ; i++)
 
799
        str[i] = XCHAR2B_BYTE2 (s->char2b + from + i);
 
800
      BLOCK_INPUT;
 
801
      if (with_background > 0)
 
802
        {
 
803
          if (s->padding_p)
 
804
            for (i = 0; i < len; i++)
 
805
              XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
 
806
                                gc, x + i, y, str + i, 1);
 
807
          else
 
808
            XDrawImageString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
 
809
                              gc, x, y, str, len);
 
810
        }
 
811
      else
 
812
        {
 
813
          if (s->padding_p)
 
814
            for (i = 0; i < len; i++)
 
815
              XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
 
816
                           gc, x + i, y, str + i, 1);
 
817
          else
 
818
            XDrawString (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
 
819
                         gc, x, y, str, len);
 
820
        }
 
821
      UNBLOCK_INPUT;
 
822
      SAFE_FREE ();
 
823
      return s->nchars;
 
824
    }
 
825
 
 
826
  BLOCK_INPUT;
 
827
  if (with_background > 0)
 
828
    {
 
829
      if (s->padding_p)
 
830
        for (i = 0; i < len; i++)
 
831
          XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
 
832
                              gc, x + i, y, s->char2b + from + i, 1);
 
833
      else
 
834
        XDrawImageString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
 
835
                            gc, x, y, s->char2b + from, len);
 
836
    }
 
837
  else
 
838
    {
 
839
      if (s->padding_p)
 
840
        for (i = 0; i < len; i++)
 
841
          XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
 
842
                         gc, x + i, y, s->char2b + from + i, 1);
 
843
      else
 
844
        XDrawString16 (FRAME_X_DISPLAY (s->f), FRAME_X_WINDOW (s->f),
 
845
                       gc, x, y, s->char2b + from, len);
 
846
    }
 
847
  UNBLOCK_INPUT;
 
848
 
 
849
  return len;
 
850
}
 
851
 
 
852
 
 
853
void
 
854
syms_of_xfont ()
 
855
{
 
856
  xfont_driver.type = Qx;
 
857
  register_font_driver (&xfont_driver, NULL);
 
858
}
 
859
 
 
860
/* arch-tag: 23c5f366-a5ee-44b7-a3b7-90d6da7fd749
 
861
   (do not change this comment) */