(Fmessage_or_box): Doc fix.
[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 char *p;
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 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;
349 char *p, *q;
350
351 if (!fontp->seeked) return NULL;
352
353 start = fontp->seeked;
354 len = fontp->size - (start - fontp->font);
355
356 do {
357 flag = proceed_file_line("ENCODING", start, &len, &p, &q);
358 if (!flag)
359 {
360 fontp->seeked = NULL;
361 return NULL;
362 }
363 font_index = atoi(p);
364 result = cache_char_offset(fontp, font_index, q);
365 if (!result) return NULL;
366
367 start = result->offset;
368 } while (font_index != index);
369 fontp->seeked = start;
370
371 return result;
372 }
373
374 #define GET_HEX_VAL(x) ((isdigit(x)) ? ((x) - '0') : \
375 (((x) >= 'A') && ((x) <= 'Z')) ? ((x) - 'A' + 10) : \
376 (((x) >= 'a') && ((x) <= 'z')) ? ((x) - 'a' + 10) : \
377 (-1))
378
379 int
380 w32_get_bdf_glyph(bdffont *fontp, int index, int size, glyph_struct *glyph)
381 {
382 font_char *pch;
383 unsigned char *start, *bitmapp;
384 char *p, *q;
385 char val1, val2;
386 int i, j, len, flag;
387
388 pch = get_cached_font_char(fontp, index);
389 if (!pch)
390 {
391 pch = seek_char(fontp, index);
392 if (!pch)
393 return 0;
394 }
395
396 start = pch->offset;
397
398 if ((size == 0) && pch->pcbmp)
399 {
400 glyph->metric = pch->pcbmp->metric;
401 return 1;
402 }
403
404 len = fontp->size - (start - fontp->font);
405
406 flag = proceed_file_line("DWIDTH", start, &len, &p, &q);
407 if (!flag)
408 return 0;
409 glyph->metric.dwidth = atoi(p);
410
411 start = q;
412 flag = proceed_file_line("BBX", start, &len, &p, &q);
413 if (!flag)
414 return 0;
415 glyph->metric.bbw = strtol(p, &start, 10);
416 p = start;
417 glyph->metric.bbh = strtol(p, &start, 10);
418 p = start;
419 glyph->metric.bbox = strtol(p, &start, 10);
420 p = start;
421 glyph->metric.bboy = strtol(p, &start, 10);
422
423 if (size == 0) return 1;
424
425 start = q;
426 flag = proceed_file_line("BITMAP", start, &len, &p, &q);
427 if (!flag)
428 return 0;
429
430 p = q;
431 bitmapp = glyph->bitmap;
432 for(i = 0;i < glyph->metric.bbh;i++)
433 {
434 q = memchr(p, '\n', len);
435 if (!q) return 0;
436 for(j = 0;((q > p) && (j < ((glyph->metric.bbw + 7) / 8 )));j++)
437 {
438 val1 = GET_HEX_VAL(*p);
439 if (val1 == -1) return 0;
440 p++;
441 val2 = GET_HEX_VAL(*p);
442 if (val2 == -1) return 0;
443 p++;
444 size--;
445 if (size <= 0) return 0;
446 /* NAND Operation. */
447 *bitmapp++ = (unsigned char)~((val1 << 4) | val2);
448 }
449 /* CreateBitmap requires WORD alignment. */
450 if (j % 2)
451 {
452 *bitmapp++ = 0xff;
453 }
454 p = q + 1;
455 }
456
457 return 1;
458 }
459
460 #define NEXT_CACHE_SLOT(n) (((n) + 1 >= BDF_FONT_CACHE_SIZE) ? 0 : ((n) + 1))
461
462 static
463 cache_bitmap*
464 get_bitmap_with_cache(bdffont *fontp, int index)
465 {
466 int bitmap_size;
467 font_char *pch;
468 cache_bitmap* pcb;
469 HBITMAP hbmp;
470 glyph_struct glyph;
471 static cache_bitmap cached_bitmap_slots[BDF_FONT_CACHE_SIZE];
472 static int cache_in_slot = 0; /* the next slot to use */
473 static int cache_out_slot = 0; /* the last slot allocated */
474 static int cache_occupancy = 0; /* current cache occupancy */
475 static int cache_limit = BDF_FONT_CACHE_SIZE; /* allowed maximum occupancy */
476
477 pch = get_cached_font_char(fontp, index);
478 if (pch)
479 {
480 pcb = pch->pcbmp;
481 if (pcb) return pcb;
482 }
483
484 bitmap_size = ((fontp->urx - fontp->llx) / 8 + 2) * (fontp->ury - fontp->lly)
485 + 256;
486 glyph.bitmap = (unsigned char*) alloca(sizeof(unsigned char) * bitmap_size);
487
488 if (!w32_get_bdf_glyph(fontp, index, bitmap_size, &glyph))
489 return NULL;
490
491 pch = get_cached_font_char(fontp, index);
492 if (!pch) return NULL;
493
494 hbmp = CreateBitmap(glyph.metric.bbw, glyph.metric.bbh, 1, 1, glyph.bitmap);
495
496 /* if bitmap allocation fails reduce the limit of the occupancy so
497 that we can hope it will not happen again. */
498 if (hbmp == NULL)
499 cache_limit = cache_occupancy * CACHE_GDI_ALLOWANCE;
500
501 /* if cache occupancy reaches at the limit release some cache slots */
502 if (cache_occupancy >= cache_limit)
503 {
504 register int size_to_clear = cache_limit * BDF_FONT_CLEAR_SIZE
505 / BDF_FONT_CACHE_SIZE;
506 for (; size_to_clear; size_to_clear--,
507 cache_out_slot = NEXT_CACHE_SLOT(cache_out_slot))
508 {
509 register cache_bitmap *p = &cached_bitmap_slots[cache_out_slot];
510 if (p->psrc)
511 {
512 DeleteObject(p->hbmp);
513 p->psrc->pcbmp = NULL;
514 p->psrc = NULL;
515 cache_occupancy--;
516 }
517 }
518 }
519
520 if (hbmp == NULL)
521 hbmp = CreateBitmap (glyph.metric.bbw, glyph.metric.bbh,
522 1, 1, glyph.bitmap);
523
524 pcb = &cached_bitmap_slots[cache_in_slot];
525
526 pcb->psrc = pch;
527 pcb->metric = glyph.metric;
528 pcb->hbmp = hbmp;
529
530 pch->pcbmp = pcb;
531
532 cache_in_slot = NEXT_CACHE_SLOT(cache_in_slot);
533 cache_occupancy++;
534
535 return pcb;
536 }
537
538 int
539 w32_BDF_TextOut(bdffont *fontp, HDC hdc, int left,
540 int top, unsigned char *text, int dim, int bytelen,
541 int fixed_pitch_size)
542 {
543 int index, btop;
544 unsigned char *textp;
545 HDC hCompatDC = 0;
546 cache_bitmap *pcb;
547 HBITMAP hBMP;
548 HBRUSH hFgBrush, hOrgBrush;
549 HANDLE horgobj = 0;
550 UINT textalign;
551 int flag = 0;
552
553 hCompatDC = CreateCompatibleDC(hdc);
554
555 textalign = GetTextAlign(hdc);
556
557 SaveDC(hdc);
558
559 hFgBrush = CreateSolidBrush(GetTextColor(hdc));
560 hOrgBrush = SelectObject(hdc, hFgBrush);
561 SetTextColor(hdc, RGB(0, 0, 0));
562 SetBkColor(hdc, RGB(0xff, 0xff, 0xff));
563
564 textp = text;
565 while(bytelen > 0)
566 {
567 if (dim == 1)
568 {
569 index = *textp++;
570 bytelen--;
571 }
572 else
573 {
574 bytelen -= 2;
575 if (bytelen < 0) break;
576 index = MAKELENDSHORT(textp[1], textp[0]);
577 textp += 2;
578 }
579 pcb = get_bitmap_with_cache(fontp, index);
580 if (!pcb)
581 {
582 if (horgobj)
583 {
584 SelectObject(hCompatDC, horgobj);
585 DeleteObject(hBMP);
586 }
587 DeleteDC(hCompatDC);
588 return 0;
589 }
590 hBMP = pcb->hbmp;
591
592 if (textalign & TA_BASELINE)
593 btop = top - (pcb->metric.bbh + pcb->metric.bboy);
594 else if (textalign & TA_BOTTOM)
595 btop = top - pcb->metric.bbh;
596 else
597 btop = top;
598
599 if (horgobj)
600 SelectObject(hCompatDC, hBMP);
601 else
602 horgobj = SelectObject(hCompatDC, hBMP);
603 #if 0
604 BitBlt(hdc, left, btop, pcb->metric.bbw, pcb->metric.bbh, hCompatDC, 0, 0, SRCCOPY);
605 #else
606 BitBlt(hdc, left, btop, pcb->metric.bbw, pcb->metric.bbh, hCompatDC, 0, 0, 0xB8074A);
607 #endif
608 if (fixed_pitch_size)
609 left += fixed_pitch_size;
610 else
611 left += pcb->metric.dwidth;
612 }
613 SelectObject(hCompatDC, horgobj);
614 SelectObject(hdc, hOrgBrush);
615 DeleteObject(hFgBrush);
616 DeleteDC(hCompatDC);
617 RestoreDC(hdc, -1);
618
619 return 1;
620 }
621
622 struct font_info *w32_load_bdf_font (struct frame *f, char *fontname,
623 int size, char* filename)
624 {
625 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
626 struct font_info *fontp;
627 XFontStruct *font;
628 bdffont* bdf_font;
629
630 bdf_font = w32_init_bdf_font (filename);
631
632 if (!bdf_font) return NULL;
633
634 font = (XFontStruct *) xmalloc (sizeof (XFontStruct));
635
636 font->bdf = bdf_font;
637 font->hfont = 0;
638
639 /* NTEMACS_TODO: Recognize DBCS fonts. */
640 font->double_byte_p = 0;
641
642 /* Do we need to create the table? */
643 if (dpyinfo->font_table_size == 0)
644 {
645 dpyinfo->font_table_size = 16;
646 dpyinfo->font_table
647 = (struct font_info *) xmalloc (dpyinfo->font_table_size
648 * sizeof (struct font_info));
649 }
650 /* Do we need to grow the table? */
651 else if (dpyinfo->n_fonts
652 >= dpyinfo->font_table_size)
653 {
654 dpyinfo->font_table_size *= 2;
655 dpyinfo->font_table
656 = (struct font_info *) xrealloc (dpyinfo->font_table,
657 (dpyinfo->font_table_size
658 * sizeof (struct font_info)));
659 }
660
661 fontp = dpyinfo->font_table + dpyinfo->n_fonts;
662
663 /* Now fill in the slots of *FONTP. */
664 BLOCK_INPUT;
665 fontp->font = font;
666 fontp->font_idx = dpyinfo->n_fonts;
667 fontp->name = (char *) xmalloc (strlen (fontname) + 1);
668 bcopy (fontname, fontp->name, strlen (fontname) + 1);
669 fontp->full_name = fontp->name;
670 fontp->size = FONT_WIDTH (font);
671 fontp->height = FONT_HEIGHT (font);
672
673 /* The slot `encoding' specifies how to map a character
674 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
675 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF, 0:0x2020..0x7F7F,
676 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF,
677 0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF, or
678 2:0xA020..0xFF7F). For the moment, we don't know which charset
679 uses this font. So, we set informatoin in fontp->encoding[1]
680 which is never used by any charset. If mapping can't be
681 decided, set FONT_ENCODING_NOT_DECIDED. */
682 fontp->encoding[1] = FONT_ENCODING_NOT_DECIDED;
683 fontp->baseline_offset = bdf_font->yoffset;
684 fontp->relative_compose = bdf_font->relative_compose;
685 fontp->default_ascent = bdf_font->default_ascent;
686
687 UNBLOCK_INPUT;
688 dpyinfo->n_fonts++;
689 return fontp;
690 }
691
692 /* Check a file for an XFLD string describing it. */
693 int w32_BDF_to_x_font (char *file, char* xstr, int len)
694 {
695 HANDLE hfile, hfilemap;
696 BY_HANDLE_FILE_INFORMATION fileinfo;
697 char *font, *start, *p, *q;
698 int flag, size, retval = 0;
699
700 hfile = CreateFile (file, GENERIC_READ, FILE_SHARE_READ, NULL,
701 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
702 if (hfile == INVALID_HANDLE_VALUE) return 0;
703 if (!GetFileInformationByHandle(hfile, &fileinfo) ||
704 (fileinfo.nFileSizeHigh != 0) ||
705 (fileinfo.nFileSizeLow > BDF_FILE_SIZE_MAX))
706 {
707 CloseHandle (hfile);
708 return 0;
709 }
710 size = fileinfo.nFileSizeLow;
711
712 hfilemap = CreateFileMapping (hfile, NULL, PAGE_READONLY, 0, 0, NULL);
713 if (hfilemap == INVALID_HANDLE_VALUE)
714 {
715 CloseHandle (hfile);
716 return 0;
717 }
718
719 font = MapViewOfFile (hfilemap, FILE_MAP_READ, 0, 0, 0);
720 if (!font)
721 {
722 CloseHandle (hfile);
723 CloseHandle (hfilemap);
724 return 0;
725 }
726 start = font;
727
728 flag = proceed_file_line ("FONT ", start, &size, &p, &q);
729 if (flag)
730 {
731 /* If font provides a description of itself, check it is a
732 full XLFD before accepting it. */
733 int count = 0;
734 char *s;
735
736 for (s = p; s < q; s++)
737 if (*s == '\n')
738 break;
739 else if (*s == '-')
740 count++;
741 if (count == 14 && q - p - 1 <= len)
742 {
743 strncpy (xstr, p, q-p-1);
744 xstr[q-p-1] = '\0';
745 /* Files may have DOS line ends (ie still ^M on end). */
746 if (iscntrl(xstr[q-p-2]))
747 xstr[q-p-2] = '\0';
748
749 retval = 1;
750 }
751 }
752 CloseHandle (hfile);
753 CloseHandle (hfilemap);
754 return retval;
755 }