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