(w32_load_bdf_font): Initialize font->double_byte_p.
[bpt/emacs.git] / src / w32bdf.c
1 /* Implementation of BDF font handling on the Microsoft W32 API.
2 Copyright (C) 1999 Free Software Foundation, Inc.
3
4 This file is part of GNU Emacs.
5
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
20
21 /* Based heavily on code by H. Miyashita for Meadow (a descendant of
22 MULE for W32). */
23
24 #include <windows.h>
25 #include "config.h"
26 #include "lisp.h"
27 #include "charset.h"
28 #include "frame.h"
29 #include "dispextern.h"
30 #include "fontset.h"
31 #include "blockinput.h"
32 #include "w32gui.h"
33 #include "w32term.h"
34 #include "w32bdf.h"
35
36 #define min(a, b) ((a) < (b) ? (a) : (b))
37 #define max(a, b) ((a) > (b) ? (a) : (b))
38
39 /* Portion of GDI Objects which the font cache is allowed to use. This
40 can be quite high, since the font cache is the only part of Emacs
41 that uses a large number of GDI objects, but there should still be
42 some GDI objects reserved for other uses. */
43 #define CACHE_GDI_ALLOWANCE 9 / 10
44
45 void w32_free_bdf_font(bdffont *fontp);
46 bdffont *w32_init_bdf_font(char *filename);
47
48 static int
49 search_file_line(char *key, char *start, int len, char **val, char **next)
50 {
51 int linelen;
52 unsigned char *p, *q;
53
54 p = memchr(start, '\n', len);
55 if (!p) return -1;
56 for (;start < p;start++)
57 {
58 if ((*start != ' ') || (*start != '\t')) break;
59 }
60 linelen = p - start + 1;
61 *next = p + 1;
62 if (strncmp(start, key, min(strlen(key), linelen)) == 0)
63 {
64 *val = start + strlen(key);
65 return 1;
66 }
67
68 return 0;
69 }
70
71 static int
72 proceed_file_line(char *key, char *start, int *len, char **val, char **next)
73 {
74 int flag = 0;
75
76 do {
77 flag = search_file_line(key, start, *len, val, next);
78 *len -= (int)(*next - start);
79 start = *next;
80 }while(flag == 0);
81
82 if (flag == -1) return 0;
83 return 1;
84 }
85
86 char*
87 get_quoted_string(char *start, char *end)
88 {
89 char *p, *q, *result;
90
91 p = memchr(start, '\"', end - start);
92 q = 0;
93
94 if (!p) return NULL;
95 p++;
96 q = memchr(p, '\"', end - q);
97 if (!q) return NULL;
98
99 result = (char*) xmalloc(q - p + 1);
100
101 memcpy(result, p, q - p);
102 result[q - p] = '\0';
103
104 return result;
105 }
106
107 static int
108 set_bdf_font_info(bdffont *fontp)
109 {
110 unsigned char *start, *p, *q;
111 int len, flag;
112 int bbw, bbh, bbx, bby;
113 int val1;
114
115 len = fontp->size;
116 start = fontp->font;
117
118 fontp->yoffset = 0;
119 fontp->relative_compose = 0;
120 fontp->default_ascent = 0;
121 fontp->registry = NULL;
122 fontp->encoding = NULL;
123 fontp->slant = NULL;
124 /* fontp->width = NULL; */
125
126 flag = proceed_file_line("FONTBOUNDINGBOX", start, &len, &p, &q);
127 if (!flag) return 0;
128 bbw = strtol(p, &start, 10);
129 p = start;
130 bbh = strtol(p, &start, 10);
131 p = start;
132 bbx = strtol(p, &start, 10);
133 p = start;
134 bby = strtol(p, &start, 10);
135
136 fontp->llx = bbx;
137 fontp->lly = bby;
138 fontp->urx = bbw + bbx;
139 fontp->ury = bbh + bby;
140 fontp->width = bbw;
141 fontp->height = bbh;
142 start = q;
143 flag = proceed_file_line("STARTPROPERTIES", start, &len, &p, &q);
144 if (!flag) return 1;
145
146 flag = 0;
147
148 do {
149 start = q;
150 if (search_file_line("PIXEL_SIZE", start, len, &p, &q) == 1)
151 {
152 val1 = atoi(p);
153 fontp->pixsz = val1;
154 }
155 else if (search_file_line("FONT_ASCENT", start, len, &p, &q) == 1)
156 {
157 val1 = atoi(p);
158 fontp->ury = val1;
159 }
160 else if (search_file_line("FONT_DESCENT", start, len, &p, &q) == 1)
161 {
162 val1 = atoi(p);
163 fontp->lly = -val1;
164 }
165 else if (search_file_line("_MULE_BASELINE_OFFSET", start, len, &p, &q) == 1)
166 {
167 val1 = atoi(p);
168 fontp->yoffset = val1;
169 }
170 else if (search_file_line("_MULE_RELATIVE_COMPOSE", start, len, &p, &q) == 1)
171 {
172 val1 = atoi(p);
173 fontp->relative_compose = val1;
174 }
175 else if (search_file_line("_MULE_DEFAULT_ASCENT", start, len, &p, &q) == 1)
176 {
177 val1 = atoi(p);
178 fontp->default_ascent = val1;
179 }
180 else if (search_file_line("CHARSET_REGISTRY", start, len, &p, &q) == 1)
181 {
182 fontp->registry = get_quoted_string(p, q);
183 }
184 else if (search_file_line("CHARSET_ENCODING", start, len, &p, &q) == 1)
185 {
186 fontp->encoding = get_quoted_string(p, q);
187 }
188 else if (search_file_line("SLANT", start, len, &p, &q) == 1)
189 {
190 fontp->slant = get_quoted_string(p, q);
191 }
192 /*
193 else if (search_file_line("SETWIDTH_NAME", start, len, &p, &q) == 1)
194 {
195 fontp->width = get_quoted_string(p, q);
196 }
197 */
198 else
199 {
200 flag = search_file_line("ENDPROPERTIES", start, len, &p, &q);
201 }
202 if (flag == -1) return 0;
203 len -= (q - start);
204 }while(flag == 0);
205 start = q;
206 flag = proceed_file_line("CHARS", start, &len, &p, &q);
207 if (!flag) return 0;
208 fontp->seeked = q;
209
210 return 1;
211 }
212
213 bdffont*
214 w32_init_bdf_font(char *filename)
215 {
216 HANDLE hfile, hfilemap;
217 bdffont *bdffontp;
218 unsigned char *font;
219 BY_HANDLE_FILE_INFORMATION fileinfo;
220 int i;
221
222 hfile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL,
223 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
224 if (hfile == INVALID_HANDLE_VALUE) return NULL;
225 if (!GetFileInformationByHandle(hfile, &fileinfo) ||
226 (fileinfo.nFileSizeHigh != 0) ||
227 (fileinfo.nFileSizeLow > BDF_FILE_SIZE_MAX))
228 {
229 CloseHandle(hfile);
230 error("Fail to open BDF file.");
231 }
232 hfilemap = CreateFileMapping(hfile, NULL, PAGE_READONLY, 0, 0, NULL);
233 if (hfilemap == INVALID_HANDLE_VALUE)
234 {
235 CloseHandle(hfile);
236 error("Can't map font.");
237 }
238
239 font = MapViewOfFile(hfilemap, FILE_MAP_READ, 0, 0, 0);
240
241 if (!font)
242 {
243 CloseHandle(hfile);
244 CloseHandle(hfilemap);
245 error("Can't view font.");
246 }
247
248 bdffontp = (bdffont *) xmalloc(sizeof(bdffont));
249
250 for(i = 0;i < BDF_FIRST_OFFSET_TABLE;i++)
251 bdffontp->chtbl[i] = NULL;
252 bdffontp->size = fileinfo.nFileSizeLow;
253 bdffontp->font = font;
254 bdffontp->hfile = hfile;
255 bdffontp->hfilemap = hfilemap;
256 bdffontp->filename = (char*) xmalloc(strlen(filename) + 1);
257 strcpy(bdffontp->filename, filename);
258
259 if (!set_bdf_font_info(bdffontp))
260 {
261 w32_free_bdf_font(bdffontp);
262 error("Invalid BDF font!");
263 }
264 return bdffontp;
265 }
266
267 void
268 w32_free_bdf_font(bdffont *fontp)
269 {
270 int i, j;
271 font_char *pch;
272 cache_bitmap *pcb;
273
274 UnmapViewOfFile(fontp->hfilemap);
275 CloseHandle(fontp->hfilemap);
276 CloseHandle(fontp->hfile);
277
278 if (fontp->registry) xfree(fontp->registry);
279 if (fontp->encoding) xfree(fontp->encoding);
280 if (fontp->slant) xfree(fontp->slant);
281 /* if (fontp->width) xfree(fontp->width); */
282
283 xfree(fontp->filename);
284 for(i = 0;i < BDF_FIRST_OFFSET_TABLE;i++)
285 {
286 pch = fontp->chtbl[i];
287 if (pch)
288 {
289 for (j = 0;j < BDF_SECOND_OFFSET_TABLE;j++)
290 {
291 pcb = pch[j].pcbmp;
292 if (pcb) pcb->psrc = NULL;
293 }
294 xfree(pch);
295 }
296 }
297 xfree(fontp);
298 }
299
300 static font_char*
301 get_cached_font_char(bdffont *fontp, int index)
302 {
303 font_char *pch, *result;
304 int i;
305
306 if (index > 0xffff)
307 return NULL;
308
309 pch = fontp->chtbl[BDF_FIRST_OFFSET(index)];
310 if (!pch)
311 return NULL;
312 result = &pch[BDF_SECOND_OFFSET(index)];
313
314 if (!result->offset) return NULL;
315
316 return result;
317 }
318
319 static font_char*
320 cache_char_offset(bdffont *fontp, int index, unsigned char *offset)
321 {
322 font_char *pch, *result;
323 int i;
324
325 if (index > 0xffff)
326 return NULL;
327
328 pch = fontp->chtbl[BDF_FIRST_OFFSET(index)];
329 if (!pch)
330 {
331 pch = fontp->chtbl[BDF_FIRST_OFFSET(index)] =
332 (font_char*) xmalloc(sizeof(font_char) *
333 BDF_SECOND_OFFSET_TABLE);
334 memset(pch, 0, sizeof(font_char) * BDF_SECOND_OFFSET_TABLE);
335 }
336
337 result = &pch[BDF_SECOND_OFFSET(index)];
338 result->offset = offset;
339
340 return result;
341 }
342
343 static font_char*
344 seek_char(bdffont *fontp, int index)
345 {
346 font_char *result;
347 int len, flag, font_index;
348 unsigned char *start, *p, *q;
349
350 if (!fontp->seeked) return NULL;
351
352 start = fontp->seeked;
353 len = fontp->size - (start - fontp->font);
354
355 do {
356 flag = proceed_file_line("ENCODING", start, &len, &p, &q);
357 if (!flag)
358 {
359 fontp->seeked = NULL;
360 return NULL;
361 }
362 font_index = atoi(p);
363 result = cache_char_offset(fontp, font_index, q);
364 if (!result) return NULL;
365
366 start = result->offset;
367 } while (font_index != index);
368 fontp->seeked = start;
369
370 return result;
371 }
372
373 #define GET_HEX_VAL(x) ((isdigit(x)) ? ((x) - '0') : \
374 (((x) >= 'A') && ((x) <= 'Z')) ? ((x) - 'A' + 10) : \
375 (((x) >= 'a') && ((x) <= 'z')) ? ((x) - 'a' + 10) : \
376 (-1))
377
378 int
379 w32_get_bdf_glyph(bdffont *fontp, int index, int size, glyph_struct *glyph)
380 {
381 font_char *pch;
382 unsigned char *start, *p, *q, *bitmapp;
383 unsigned char val1, val2;
384 int i, j, len, flag;
385
386 pch = get_cached_font_char(fontp, index);
387 if (!pch)
388 {
389 pch = seek_char(fontp, index);
390 if (!pch)
391 return 0;
392 }
393
394 start = pch->offset;
395
396 if ((size == 0) && pch->pcbmp)
397 {
398 glyph->metric = pch->pcbmp->metric;
399 return 1;
400 }
401
402 len = fontp->size - (start - fontp->font);
403
404 flag = proceed_file_line("DWIDTH", start, &len, &p, &q);
405 if (!flag)
406 return 0;
407 glyph->metric.dwidth = atoi(p);
408
409 start = q;
410 flag = proceed_file_line("BBX", start, &len, &p, &q);
411 if (!flag)
412 return 0;
413 glyph->metric.bbw = strtol(p, &start, 10);
414 p = start;
415 glyph->metric.bbh = strtol(p, &start, 10);
416 p = start;
417 glyph->metric.bbox = strtol(p, &start, 10);
418 p = start;
419 glyph->metric.bboy = strtol(p, &start, 10);
420
421 if (size == 0) return 1;
422
423 start = q;
424 flag = proceed_file_line("BITMAP", start, &len, &p, &q);
425 if (!flag)
426 return 0;
427
428 p = q;
429 bitmapp = glyph->bitmap;
430 for(i = 0;i < glyph->metric.bbh;i++)
431 {
432 q = memchr(p, '\n', len);
433 if (!q) return 0;
434 for(j = 0;((q > p) && (j < ((glyph->metric.bbw + 7) / 8 )));j++)
435 {
436 val1 = GET_HEX_VAL(*p);
437 if (val1 == -1) return 0;
438 p++;
439 val2 = GET_HEX_VAL(*p);
440 if (val2 == -1) return 0;
441 p++;
442 size--;
443 if (size <= 0) return 0;
444 /* NAND Operation. */
445 *bitmapp++ = (unsigned char)~((val1 << 4) | val2);
446 }
447 /* CreateBitmap requires WORD alignment. */
448 if (j % 2)
449 {
450 *bitmapp++ = 0xff;
451 }
452 p = q + 1;
453 }
454
455 return 1;
456 }
457
458 #define NEXT_CACHE_SLOT(n) (((n) + 1 >= BDF_FONT_CACHE_SIZE) ? 0 : ((n) + 1))
459
460 static
461 cache_bitmap*
462 get_bitmap_with_cache(bdffont *fontp, int index)
463 {
464 int bitmap_size;
465 font_char *pch;
466 cache_bitmap* pcb;
467 HBITMAP hbmp;
468 glyph_struct glyph;
469 static cache_bitmap cached_bitmap_slots[BDF_FONT_CACHE_SIZE];
470 static int cache_in_slot = 0; /* the next slot to use */
471 static int cache_out_slot = 0; /* the last slot allocated */
472 static int cache_occupancy = 0; /* current cache occupancy */
473 static int cache_limit = BDF_FONT_CACHE_SIZE; /* allowed maximum occupancy */
474
475 pch = get_cached_font_char(fontp, index);
476 if (pch)
477 {
478 pcb = pch->pcbmp;
479 if (pcb) return pcb;
480 }
481
482 bitmap_size = ((fontp->urx - fontp->llx) / 8 + 2) * (fontp->ury - fontp->lly)
483 + 256;
484 glyph.bitmap = (unsigned char*) alloca(sizeof(unsigned char) * bitmap_size);
485
486 if (!w32_get_bdf_glyph(fontp, index, bitmap_size, &glyph))
487 return NULL;
488
489 pch = get_cached_font_char(fontp, index);
490 if (!pch) return NULL;
491
492 hbmp = CreateBitmap(glyph.metric.bbw, glyph.metric.bbh, 1, 1, glyph.bitmap);
493
494 /* if bitmap allocation fails reduce the limit of the occupancy so
495 that we can hope it will not happen again. */
496 if (hbmp == NULL)
497 cache_limit = cache_occupancy * CACHE_GDI_ALLOWANCE;
498
499 /* if cache occupancy reaches at the limit release some cache slots */
500 if (cache_occupancy >= cache_limit)
501 {
502 register int size_to_clear = cache_limit * BDF_FONT_CLEAR_SIZE
503 / BDF_FONT_CACHE_SIZE;
504 for (; size_to_clear; size_to_clear--,
505 cache_out_slot = NEXT_CACHE_SLOT(cache_out_slot))
506 {
507 register cache_bitmap *p = &cached_bitmap_slots[cache_out_slot];
508 if (p->psrc)
509 {
510 DeleteObject(p->hbmp);
511 p->psrc->pcbmp = NULL;
512 p->psrc = NULL;
513 cache_occupancy--;
514 }
515 }
516 }
517
518 if (hbmp == NULL)
519 hbmp = CreateBitmap (glyph.metric.bbw, glyph.metric.bbh,
520 1, 1, glyph.bitmap);
521
522 pcb = &cached_bitmap_slots[cache_in_slot];
523
524 pcb->psrc = pch;
525 pcb->metric = glyph.metric;
526 pcb->hbmp = hbmp;
527
528 pch->pcbmp = pcb;
529
530 cache_in_slot = NEXT_CACHE_SLOT(cache_in_slot);
531 cache_occupancy++;
532
533 return pcb;
534 }
535
536 int
537 w32_BDF_TextOut(bdffont *fontp, HDC hdc, int left,
538 int top, unsigned char *text, int dim, int bytelen,
539 int fixed_pitch_size)
540 {
541 int index, btop;
542 unsigned char *textp;
543 HDC hCompatDC = 0;
544 cache_bitmap *pcb;
545 HBITMAP hBMP;
546 HBRUSH hFgBrush, hOrgBrush;
547 HANDLE horgobj = 0;
548 UINT textalign;
549 int flag = 0;
550
551 hCompatDC = CreateCompatibleDC(hdc);
552
553 textalign = GetTextAlign(hdc);
554
555 SaveDC(hdc);
556
557 hFgBrush = CreateSolidBrush(GetTextColor(hdc));
558 hOrgBrush = SelectObject(hdc, hFgBrush);
559 SetTextColor(hdc, RGB(0, 0, 0));
560 SetBkColor(hdc, RGB(0xff, 0xff, 0xff));
561
562 textp = text;
563 while(bytelen > 0)
564 {
565 if (dim == 1)
566 {
567 index = *textp++;
568 bytelen--;
569 }
570 else
571 {
572 bytelen -= 2;
573 if (bytelen < 0) break;
574 index = MAKELENDSHORT(textp[1], textp[0]);
575 textp += 2;
576 }
577 pcb = get_bitmap_with_cache(fontp, index);
578 if (!pcb)
579 {
580 if (horgobj)
581 {
582 SelectObject(hCompatDC, horgobj);
583 DeleteObject(hBMP);
584 }
585 DeleteDC(hCompatDC);
586 return 0;
587 }
588 hBMP = pcb->hbmp;
589
590 if (textalign & TA_BASELINE)
591 btop = top - (pcb->metric.bbh + pcb->metric.bboy);
592 else if (textalign & TA_BOTTOM)
593 btop = top - pcb->metric.bbh;
594 else
595 btop = top;
596
597 if (horgobj)
598 SelectObject(hCompatDC, hBMP);
599 else
600 horgobj = SelectObject(hCompatDC, hBMP);
601 #if 0
602 BitBlt(hdc, left, btop, pcb->metric.bbw, pcb->metric.bbh, hCompatDC, 0, 0, SRCCOPY);
603 #else
604 BitBlt(hdc, left, btop, pcb->metric.bbw, pcb->metric.bbh, hCompatDC, 0, 0, 0xB8074A);
605 #endif
606 if (fixed_pitch_size)
607 left += fixed_pitch_size;
608 else
609 left += pcb->metric.dwidth;
610 }
611 SelectObject(hCompatDC, horgobj);
612 SelectObject(hdc, hOrgBrush);
613 DeleteObject(hFgBrush);
614 DeleteDC(hCompatDC);
615 RestoreDC(hdc, -1);
616
617 return 1;
618 }
619
620 struct font_info *w32_load_bdf_font (struct frame *f, char *fontname,
621 int size, char* filename)
622 {
623 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
624 struct font_info *fontp;
625 XFontStruct *font;
626 bdffont* bdf_font;
627
628 bdf_font = w32_init_bdf_font (filename);
629
630 if (!bdf_font) return NULL;
631
632 font = (XFontStruct *) xmalloc (sizeof (XFontStruct));
633
634 font->bdf = bdf_font;
635 font->hfont = 0;
636
637 /* NTEMACS_TODO: Recognize DBCS fonts. */
638 font->double_byte_p = 0;
639
640 /* Do we need to create the table? */
641 if (dpyinfo->font_table_size == 0)
642 {
643 dpyinfo->font_table_size = 16;
644 dpyinfo->font_table
645 = (struct font_info *) xmalloc (dpyinfo->font_table_size
646 * sizeof (struct font_info));
647 }
648 /* Do we need to grow the table? */
649 else if (dpyinfo->n_fonts
650 >= dpyinfo->font_table_size)
651 {
652 dpyinfo->font_table_size *= 2;
653 dpyinfo->font_table
654 = (struct font_info *) xrealloc (dpyinfo->font_table,
655 (dpyinfo->font_table_size
656 * sizeof (struct font_info)));
657 }
658
659 fontp = dpyinfo->font_table + dpyinfo->n_fonts;
660
661 /* Now fill in the slots of *FONTP. */
662 BLOCK_INPUT;
663 fontp->font = font;
664 fontp->font_idx = dpyinfo->n_fonts;
665 fontp->name = (char *) xmalloc (strlen (fontname) + 1);
666 bcopy (fontname, fontp->name, strlen (fontname) + 1);
667 fontp->full_name = fontp->name;
668 fontp->size = FONT_WIDTH (font);
669 fontp->height = FONT_HEIGHT (font);
670
671 /* The slot `encoding' specifies how to map a character
672 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
673 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF, 0:0x2020..0x7F7F,
674 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF,
675 0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF, or
676 2:0xA020..0xFF7F). For the moment, we don't know which charset
677 uses this font. So, we set informatoin in fontp->encoding[1]
678 which is never used by any charset. If mapping can't be
679 decided, set FONT_ENCODING_NOT_DECIDED. */
680 fontp->encoding[1] = FONT_ENCODING_NOT_DECIDED;
681 fontp->baseline_offset = bdf_font->yoffset;
682 fontp->relative_compose = bdf_font->relative_compose;
683 fontp->default_ascent = bdf_font->default_ascent;
684
685 UNBLOCK_INPUT;
686 dpyinfo->n_fonts++;
687 return fontp;
688 }
689
690 /* Check a file for an XFLD string describing it. */
691 int w32_BDF_to_x_font (char *file, char* xstr, int len)
692 {
693 HANDLE hfile, hfilemap;
694 BY_HANDLE_FILE_INFORMATION fileinfo;
695 unsigned char *font, *start, *p, *q;
696 int flag, size, retval = 0;
697
698 hfile = CreateFile (file, GENERIC_READ, FILE_SHARE_READ, NULL,
699 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
700 if (hfile == INVALID_HANDLE_VALUE) return 0;
701 if (!GetFileInformationByHandle(hfile, &fileinfo) ||
702 (fileinfo.nFileSizeHigh != 0) ||
703 (fileinfo.nFileSizeLow > BDF_FILE_SIZE_MAX))
704 {
705 CloseHandle (hfile);
706 return 0;
707 }
708 size = fileinfo.nFileSizeLow;
709
710 hfilemap = CreateFileMapping (hfile, NULL, PAGE_READONLY, 0, 0, NULL);
711 if (hfilemap == INVALID_HANDLE_VALUE)
712 {
713 CloseHandle (hfile);
714 return 0;
715 }
716
717 font = MapViewOfFile (hfilemap, FILE_MAP_READ, 0, 0, 0);
718 if (!font)
719 {
720 CloseHandle (hfile);
721 CloseHandle (hfilemap);
722 return 0;
723 }
724 start = font;
725
726 flag = proceed_file_line ("FONT ", start, &size, &p, &q);
727 if (flag)
728 {
729 /* If font provides a description of itself, check it is a
730 full XLFD before accepting it. */
731 int count = 0;
732 char *s;
733
734 for (s = p; s < q; s++)
735 if (*s == '\n')
736 break;
737 else if (*s == '-')
738 count++;
739 if (count == 14 && q - p - 1 <= len)
740 {
741 strncpy (xstr, p, q-p-1);
742 xstr[q-p-1] = '\0';
743 /* Files may have DOS line ends (ie still ^M on end). */
744 if (iscntrl(xstr[q-p-2]))
745 xstr[q-p-2] = '\0';
746
747 retval = 1;
748 }
749 }
750 CloseHandle (hfile);
751 CloseHandle (hfilemap);
752 return retval;
753 }