1 /*
2 * sf_fonts.c - SDL interface, generic font handling
3 *
4 * This file is part of Frotz.
5 *
6 * Frotz 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 of the License, or
9 * (at your option) any later version.
10 *
11 * Frotz 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 this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 * Or visit http://www.fsf.org/
20 */
21
22 #include "sf_frotz.h"
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <unistd.h>
28
29 /* font handling */
30
31 typedef struct {
32 int refcount;
33 word minchar, maxchar, defchar;
34 byte ascent, descent;
35 int glyphs[0]; /* offsets to glyphs from start of rec */
36 } SF_bdffont;
37
38 char *m_fontfiles[9];
39
40 extern z_header_t z_header;
41
42 static char s[1026];
43
starts(char * s,char * id)44 static char *starts(char *s, char *id)
45 {
46 int len = strlen(id);
47 while (*s == ' ')
48 s++;
49 if (memcmp(s, id, len) == 0)
50 return (s + len);
51 return NULL;
52 }
53
54
hexd(char c)55 static int hexd(char c)
56 {
57 if (c >= '0' && c <= '9')
58 return c - '0';
59 if (c >= 'A' && c <= 'F')
60 return c - 'A' + 10;
61 if (c >= 'a' && c <= 'f')
62 return c - 'a' + 10;
63 return 0;
64 }
65
66
gethex(char * p,byte * dst,int n)67 static void gethex(char *p, byte * dst, int n)
68 {
69 while (n--) {
70 *dst++ = 16 * hexd(p[0]) + hexd(p[1]);
71 p += 2;
72 }
73 }
74
75
76 #define ERRET(n) { *err = n; return font;}
77
sBDXload(FILE * f,int * err,int * size,int MAXCHAR)78 static SF_bdffont *sBDXload(FILE * f, int *err, int *size, int MAXCHAR)
79 {
80 int totb, i, k = 0, wh[4];
81 byte *po, *pbeg;
82 char *p, *q;
83 char *fontname = "", *copyright = "unknown";
84 int fngot = 0, cpgot = 0;
85 int hasenc, hasbbx;
86 SF_bdffont *font = NULL;
87 int foffs, minch, maxch, rejected = 0;
88 int defchar = -1, descent = -1, ascent = -1, nprop, nchars;
89 /* NOTE: file MUST be opened as binary on MSDOS, otherwise
90 * ftell() won't return correct values if the file does not
91 * have CR's (as is usually the case, since BDF files frequently
92 * come from Unix systems)
93 */
94
95 /* header */
96 for (;;) {
97 fgets(s, 1024, f);
98 if (feof(f))
99 ERRET(-1) /* errorexit(99,"unexpected EOF\n"); */
100 if ((p = starts(s, "FONT "))) {
101 while (*p == ' ')
102 p++;
103 q = p;
104 while (*p >= ' ')
105 p++;
106 *p = 0;
107 fontname = strdup(q);
108 fngot = 1;
109 }
110 if ((p = starts(s, "STARTPROPERTIES "))) {
111 nprop = atoi(p);
112 break;
113 }
114 }
115 for (i = 0; i < nprop; i++) {
116 fgets(s, 1024, f);
117 if (feof(f))
118 ERRET(-51) /* errorexit(99,"unexpected EOF\n"); */
119 if ((p = starts(s, "COPYRIGHT "))) {
120 while (*p == ' ')
121 p++;
122 q = p;
123 while (*p >= ' ')
124 p++;
125 *p = 0;
126 copyright = strdup(q);
127 cpgot = 1;
128 }
129 if ((p = starts(s, "DEFAULT_CHAR ")))
130 defchar = atoi(p);
131 if ((p = starts(s, "FONT_ASCENT ")))
132 ascent = atoi(p);
133 if ((p = starts(s, "FONT_DESCENT ")))
134 descent = atoi(p);
135 }
136 for (;;) {
137 fgets(s, 1024, f);
138 if (feof(f))
139 ERRET(-61) /* errorexit(99,"unexpected EOF\n"); */
140 if ((p = starts(s, "CHARS "))) {
141 nchars = atoi(p);
142 break;
143 }
144 }
145 foffs = ftell(f);
146
147 /* first pass */
148 totb = 0;
149 minch = 65536;
150 maxch = -1;
151 hasenc = 0;
152 for (i = 0; i < nchars;) {
153 fgets(s, 1024, f);
154 if (feof(f))
155 ERRET(-71) /* errorexit(99,"unexpected EOF\n"); */
156 if ((p = starts(s, "ENCODING "))) {
157 k = atoi(p);
158 k &= 0xffff;
159 if (k <= MAXCHAR) {
160 if (k < minch)
161 minch = k;
162 if (k > maxch)
163 maxch = k;
164 } else
165 rejected++;
166 hasenc = 1;
167 }
168 if ((p = starts(s, "BBX "))) {
169 if (!hasenc)
170 ERRET(-10)
171 sscanf(p, "%d %d", wh, wh + 1);
172 if (k <= MAXCHAR) {
173 totb +=
174 ((wh[0] + 7) / 8) * wh[1] +
175 sizeof(SF_glyph);
176 }
177 i++;
178 hasenc = 0;
179 }
180 }
181 if (ascent < 0 || descent < 0 || nchars != i)
182 ERRET(-2)
183 if (defchar < minch || defchar > maxch) {
184 if (defchar < minch)
185 defchar = minch;
186 if (defchar > maxch)
187 defchar = maxch;
188 }
189 totb +=
190 (maxch - minch + 1) * sizeof(int) + sizeof(SF_bdffont) +
191 strlen(fontname) + strlen(copyright) + 2;
192 font = calloc(1, totb);
193 if (!font)
194 ERRET(-3)
195 font->minchar = minch;
196 font->maxchar = maxch;
197 font->defchar = defchar;
198 font->ascent = ascent;
199 font->descent = descent;
200 pbeg = (byte *) font;
201 po = (byte *) (&(font->glyphs[maxch - minch + 1]));
202 k = strlen(fontname) + 1;
203 memmove(po, fontname, k);
204 po += k;
205 if (fngot)
206 free(fontname);
207 k = strlen(copyright) + 1;
208 memmove(po, copyright, k);
209 po += k;
210 if (cpgot)
211 free(copyright);
212 for (i = minch; i <= maxch; i++)
213 font->glyphs[i - minch] = 0;
214
215 /* second pass */
216 fseek(f, foffs, 0);
217 for (k = 0; k < nchars; k++) {
218 SF_glyph *bg;
219 int j;
220 int dwid, w, h;
221
222 /* Unclear what the default for dwid should be */
223 dwid = 0;
224 bg = (SF_glyph *) po;
225 hasenc = hasbbx = 0;
226 for (;;) {
227 fgets(s, 1024, f);
228 if (feof(f))
229 ERRET(-81)
230 if ((p = starts(s, "ENCODING "))) {
231 i = atoi(p);
232 i &= 0xffff;
233 if (i <= MAXCHAR)
234 font->glyphs[i - minch] =
235 po - pbeg;
236 hasenc = 1;
237 }
238 if ((p = starts(s, "DWIDTH "))) {
239 if (!hasenc)
240 ERRET(-11)
241 dwid = atoi(p);
242 }
243 if ((p = starts(s, "BBX "))) {
244 if (!hasenc)
245 ERRET(-12)
246 sscanf(p, "%d %d %d %d", wh, wh + 1,
247 wh + 2, wh + 3);
248 hasbbx = 1;
249 }
250 if (starts(s, "BITMAP"))
251 break;
252 }
253 if (!hasenc || !hasbbx)
254 ERRET(-13)
255 if (i <= MAXCHAR) {
256 bg->dx = dwid;
257 bg->w = wh[0];
258 w = (wh[0] + 7) / 8;
259 bg->h = h = wh[1];
260 bg->xof = wh[2];
261 bg->yof = wh[3];
262 po = (byte *) (&(bg->bitmap[0]));
263 for (j = 0; j < h; j++) {
264 fgets(s, 1024, f);
265 if (feof(f))
266 ERRET(-91)
267 gethex(s, po, w);
268 po += w;
269 }
270 }
271 }
272 *err = 0;
273 *size = totb;
274 return font;
275 }
276
277
278 /* destructor for fonts with all dynamic data */
bdestroy(SFONT * s)279 static void bdestroy(SFONT * s)
280 {
281 if (s) {
282 if (s->data)
283 free(s->data);
284 free(s);
285 }
286 }
287
288
bheight(SFONT * s)289 static int bheight(SFONT * s)
290 {
291 if (s) {
292 if (s->data) {
293 SF_bdffont *f = s->data;
294 return ((int)(f->ascent) + (int)(f->descent));
295 }
296 }
297 return 0;
298 }
299
300
bascent(SFONT * s)301 static int bascent(SFONT * s)
302 {
303 if (s) {
304 if (s->data)
305 return (int)((SF_bdffont *) (s->data))->ascent;
306 }
307 return 0;
308 }
309
310
bdescent(SFONT * s)311 static int bdescent(SFONT * s)
312 {
313 if (s) {
314 if (s->data)
315 return (int)((SF_bdffont *) (s->data))->descent;
316 }
317 return 0;
318 }
319
320
bminchar(SFONT * s)321 static int bminchar(SFONT * s)
322 {
323 if (s) {
324 if (s->data)
325 return (int)((SF_bdffont *) (s->data))->minchar;
326 }
327 return 0;
328 }
329
bmaxchar(SFONT * s)330 static int bmaxchar(SFONT * s)
331 {
332 if (s) {
333 if (s->data)
334 return (int)((SF_bdffont *) (s->data))->maxchar;
335 }
336 return 0;
337 }
338
getglyph(SFONT * fo,word c,int allowdef)339 static SF_glyph *getglyph(SFONT * fo, word c, int allowdef)
340 {
341 int m;
342 SF_bdffont *b;
343 if (!fo)
344 return NULL;
345 b = fo->data;
346 if (!b)
347 return NULL;
348 if (c < b->minchar || c > b->maxchar) {
349 if (allowdef)
350 c = b->defchar;
351 else
352 return NULL;
353 }
354 m = b->glyphs[c - b->minchar];
355 if (!m) {
356 if (allowdef)
357 m = b->glyphs[0];
358 else
359 return NULL;
360 }
361 return (SF_glyph *) (((byte *) b) + m);
362 }
363
364
hasglyph(SFONT * fo,word c,int allowdef)365 static int hasglyph(SFONT * fo, word c, int allowdef)
366 {
367 return (getglyph(fo, c, allowdef) != NULL);
368 }
369
370
makefont(SF_bdffont * b)371 static SFONT *makefont(SF_bdffont * b)
372 {
373 SFONT *res;
374 if (!b)
375 return NULL;
376 res = calloc(1, sizeof(SFONT));
377 if (!res) {
378 free(b);
379 return NULL;
380 }
381 res->destroy = bdestroy;
382 res->height = bheight;
383 res->data = b;
384 res->ascent = bascent;
385 res->descent = bdescent;
386 res->minchar = bminchar;
387 res->maxchar = bmaxchar;
388 res->hasglyph = hasglyph;
389 res->getglyph = getglyph;
390 return res;
391 }
392
393
loadfont(char * fname,int * err,int * size)394 static SFONT *loadfont(char *fname, int *err, int *size)
395 {
396 SF_bdffont *font;
397 SFONT *res;
398 FILE *f;
399 *err = 0;
400 if (!fname) {
401 *err = -8;
402 return NULL;
403 }
404 /* NOTE: file MUST be opened as binary on MSDOS, otherwise
405 * ftell() won't return correct values if the file does not
406 * have CR's (as is usually the case, since BDF files frequently
407 * come from Unix systems)
408 */
409 f = fopen(fname, "rb");
410 if (!f) {
411 *err = -7;
412 return NULL;
413 }
414 font = sBDXload(f, err, size, 65535);
415 fclose(f);
416 if (*err) {
417 if (font)
418 free(font);
419 return NULL;
420 }
421 res = makefont(font);
422 if (!res) {
423 free(font);
424 *err = -9999;
425 return NULL;
426 }
427 return res;
428 }
429
430
431 /*
432 * these are the 8 fonts needed
433 * PROPORTIONAL FONT
434 * ROMAN
435 * ROMAN BOLD
436 * ITALIC
437 * ITALIC BOLD
438 * FIXED FONT
439 * ROMAN
440 * ROMAN BOLD
441 * ITALIC
442 * ITALIC BOLD
443 */
444 #define NUMFONTS 9
445
446 static SFONT *myfonts[9] =
447 { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
448
styleidx(int zfont,int style)449 static int styleidx(int zfont, int style)
450 {
451 int k = 0;
452 if (zfont == GRAPHICS_FONT)
453 return 8;
454 if (zfont != TEXT_FONT)
455 zfont = FIXED_WIDTH_FONT;
456 if (style & FIXED_WIDTH_STYLE)
457 zfont = FIXED_WIDTH_FONT;
458 if (z_header.flags & FIXED_FONT_FLAG)
459 zfont = FIXED_WIDTH_FONT;
460 if (zfont != TEXT_FONT)
461 k += 4;
462 if (style & EMPHASIS_STYLE)
463 k += 2;
464 if (style & BOLDFACE_STYLE)
465 k++;
466 return k;
467 }
468
469 static SF_textsetting current;
470 #define MAXSTACK 16
471 static SF_textsetting tsstack[MAXSTACK];
472 static int tsstackptr = 0;
473
474 /* does not increase the refcount of f - user must do that */
setfontk(int k,SFONT * f)475 static void setfontk(int k, SFONT * f)
476 {
477 if (myfonts[k]) {
478 myfonts[k]->refcount--;
479 if (myfonts[k]->refcount == 0)
480 myfonts[k]->destroy(myfonts[k]);
481 }
482 myfonts[k] = f;
483 }
484
485
cleanfonts()486 static void cleanfonts()
487 {
488 int i;
489 for (i = 0; i < 8; i++)
490 setfontk(i, NULL);
491 /* for (i=0;i<8;i++)
492 if (m_fontfiles[i]){ free(m_fontfiles[i]); m_fontfiles[i] = NULL;}*/
493 }
494
495
sf_curtextsetting()496 SF_textsetting *sf_curtextsetting()
497 {
498 return ¤t;
499 }
500
501
sf_pushtextsettings()502 void sf_pushtextsettings()
503 {
504 if (tsstackptr < MAXSTACK) {
505 tsstack[tsstackptr] = current;
506 tsstackptr++;
507 }
508 }
509
510
sf_poptextsettings()511 void sf_poptextsettings()
512 {
513 if (tsstackptr) {
514 tsstackptr--;
515 current = tsstack[tsstackptr];
516 }
517 }
518
519
520 /*
521 * os_check_unicode
522 *
523 * Return with bit 0 set if the Unicode character can be
524 * displayed, and bit 1 if it can be input.
525 *
526 *
527 */
os_check_unicode(int font,zchar c)528 int os_check_unicode(int font, zchar c)
529 {
530 return ((current.font->hasglyph(current.font, c, 0) != 0) ? 3 : 2);
531 }
532
533
sf_charwidth(zword c,int * oh)534 int sf_charwidth(zword c, int *oh)
535 {
536 SF_glyph *g;
537 int ww = 0;
538 if (c == ZC_INDENT)
539 return (3 * sf_charwidth(' ', oh));
540 if (c == ZC_GAP)
541 return (2 * sf_charwidth(' ', oh));
542 *oh = 0;
543 g = current.font->getglyph(current.font, c, 1);
544 if (g) {
545 int ext = g->w + g->xof;
546 if (ext > g->dx)
547 *oh = ext - g->dx;
548 ww = (g->dx);
549 }
550 return ww;
551 }
552
553
554 /*
555 * os_char_width
556 *
557 * Return the length of the character in screen units.
558 *
559 */
os_char_width(zchar c)560 int os_char_width(zchar c)
561 {
562 int w, oh;
563 w = sf_charwidth(c, &oh);
564 return (w + oh);
565 }
566
567
setfont(int zfont)568 static void setfont(int zfont)
569 {
570 int k = styleidx(zfont, current.style);
571 current.font = myfonts[k];
572 current.zfontnum = zfont;
573 current.proportional = (k < 4);
574 }
575
576
setstyle(int style)577 static void setstyle(int style)
578 {
579 current.style = style;
580 setfont(current.zfontnum);
581 }
582
583
584 /*
585 * os_font_data
586 *
587 * Return true if the given font is available. The font can be
588 *
589 * TEXT_FONT
590 * PICTURE_FONT
591 * GRAPHICS_FONT
592 * FIXED_WIDTH_FONT
593 *
594 * The font size should be stored in "height" and "width". If
595 * the given font is unavailable then these values must _not_
596 * be changed.
597 *
598 * Font can also be 0 to query the size of the current font in the current
599 * style. Not all front end support this. Those that do return true.
600 */
os_font_data(int font,int * height,int * width)601 int os_font_data(int font, int *height, int *width)
602 {
603 switch (font) {
604 case TEXT_FONT:
605 case FIXED_WIDTH_FONT:
606 case GRAPHICS_FONT:
607 sf_pushtextsettings();
608 setfont(font);
609 setstyle(0);
610 *height = current.font->height(current.font);
611 *width = os_char_width((zword) ('0'));
612 sf_poptextsettings();
613 return 1;
614 case 0:
615 *height = current.font->height(current.font);
616 *width = os_char_width((zword) ('0'));
617 return 1;
618 default:
619 return 0;
620 }
621 }
622
623
624 /*
625 * os_set_font
626 *
627 * Set the font for text output. The interpreter takes care not to
628 * choose fonts which aren't supported by the interface.
629 *
630 */
os_set_font(int new_font)631 void os_set_font(int new_font)
632 {
633 sf_flushtext();
634 setfont(new_font);
635 }
636
637
638 /*
639 * os_set_text_style
640 *
641 * Set the current text style. Following flags can be set:
642 *
643 * REVERSE_STYLE
644 * BOLDFACE_STYLE
645 * EMPHASIS_STYLE (aka underline aka italics)
646 * FIXED_WIDTH_STYLE
647 *
648 */
os_set_text_style(int new_style)649 void os_set_text_style(int new_style)
650 {
651 sf_flushtext();
652 setstyle(new_style);
653 }
654
655
656 /*
657 * os_string_width
658 *
659 * Calculate the length of a word in screen units. Apart from letters,
660 * the word may contain special codes:
661 *
662 * ZC_NEW_STYLE - next character is a new text style
663 * ZC_NEW_FONT - next character is a new font
664 *
665 */
os_string_width(const zchar * s)666 int os_string_width(const zchar * s)
667 {
668 int width = 0, wacc = 0, oh = 0;
669 zword c;
670
671 setfont(current.zfontnum);
672 /* Look for style or font changes, or indents */
673 sf_pushtextsettings();
674 while ((c = *s++)) {
675 if (c == ZC_NEW_STYLE) {
676 wacc += oh;
677 os_set_text_style(*s++);
678 } else if (c == ZC_NEW_FONT) {
679 wacc += oh;
680 os_set_font(*s++);
681 } else
682 width += sf_charwidth(c, &oh);
683 }
684 sf_poptextsettings();
685
686 return (width + oh + wacc);
687 }
688
689
690 /*
691 * os_display_string
692 *
693 * Pass a string of characters to os_display_char.
694 *
695 */
os_display_string(const zchar * s)696 void os_display_string(const zchar * s)
697 {
698 zword c;
699 while ((c = *s++) != 0) {
700 if (c == ZC_NEW_FONT)
701 os_set_font(*s++);
702 else if (c == ZC_NEW_STYLE)
703 os_set_text_style(*s++);
704 else
705 os_display_char(c);
706 }
707 }
708
709
710 /*
711 * os_display_char
712 *
713 * Display a character of the current font using the current colours and
714 * text style. The cursor moves to the next position. Printable codes are
715 * all ASCII values from 32 to 126, ISO Latin-1 characters from 160 to
716 * 255, ZC_GAP (gap between two sentences) and ZC_INDENT (paragraph
717 * indentation), and Unicode characters above 255. The screen should not
718 * be scrolled after printing to the bottom right corner.
719 *
720 */
os_display_char(zchar c)721 void os_display_char(zchar c)
722 {
723 if (c == ZC_INDENT) {
724 os_display_char(' ');
725 os_display_char(' ');
726 os_display_char(' ');
727 } else if (c == ZC_GAP) {
728 os_display_char(' ');
729 os_display_char(' ');
730 } else if ((c >= 32 && c <= 126) || (c >= 160)) {
731 SF_glyph *g;
732 setfont(current.zfontnum);
733 g = current.font->getglyph(current.font, c, 1);
734 if (g) {
735 sf_writeglyph(g);
736 m_exitPause = true;
737 }
738 }
739 }
740
741 /*
742 * os_buffer_screen
743 *
744 * Set the screen buffering mode, and return the previous mode.
745 * Possible values for mode are:
746 *
747 * 0 - update the display to reflect changes when possible
748 * 1 - do not update the display
749 * -1 - redraw the screen, do not change the mode
750 *
751 */
os_buffer_screen(int mode)752 int os_buffer_screen(int mode)
753 {
754 if (mode == -1)
755 sf_flushdisplay();
756 return 0;
757 }
758
759
760 /*
761 * os_wrap_window
762 *
763 * Return non-zero if the window should have text wrapped.
764 *
765 */
os_wrap_window(int win)766 int os_wrap_window(int win)
767 {
768 return 1;
769 }
770
771
772 /*
773 * os_window_height
774 *
775 * Called when the height of a window is changed.
776 *
777 */
os_window_height(int win,int height)778 void os_window_height(int win, int height)
779 {
780 }
781
782
783 /*
784 * os_set_cursor
785 *
786 * Place the text cursor at the given coordinates. Top left is (1,1).
787 *
788 */
os_set_cursor(int row,int col)789 void os_set_cursor(int row, int col)
790 {
791 sf_flushtext();
792 current.cx = col - 1;
793 current.cy = row - 1;
794 }
795
796
797 extern SF_bdffont *SF_defaultfont;
798 extern int SF_defaultfontsize;
799
destroySFonly(SFONT * f)800 static void destroySFonly(SFONT * f)
801 {
802 if (f)
803 free(f);
804 }
805
806 extern SFONT *SF_font3, *SF_font3double;
807
808 SFONT *(*ttfontloader)(char *fspec, SFONT * like, int *err) = NULL;
809 void (*ttfontsdone)() = NULL;
810
811
tryloadfont(char * fspec,SFONT * like)812 static SFONT *tryloadfont(char *fspec, SFONT * like)
813 {
814 char buf[FILENAME_MAX];
815 int err, size = DEFSIZE;
816 char *fn = NULL;
817 char *p, *at;
818 int fnlen = -1;
819 SFONT *b = NULL;
820
821 at = strchr(fspec, '@');
822 if (at) {
823 fnlen = at - fspec;
824 size = atoi(at + 1);
825 }
826
827 if (m_fontdir != NULL)
828 fn = sf_searchfile(fspec, fnlen, buf, m_fontdir);
829
830 for (;;) {
831 p = strchr(fspec, '|');
832 if (p)
833 *p = 0;
834
835 if (ttfontloader)
836 b = ttfontloader(fspec, like, &err);
837 if (!b)
838 b = loadfont(fn, &err, &size);
839 if (b)
840 break;
841 if (p) {
842 *p = '|';
843 fspec = p + 1;
844 } else
845 break;
846 }
847 return b;
848 }
849
850 SFONT *sf_VGA_SFONT;
851
852
853 /* ensure a font loaded */
sf_initfonts()854 void sf_initfonts()
855 {
856 int i, j, size = 0;
857 byte *cfont, *bmp;
858 SF_glyph *g;
859 SF_bdffont *norm, *emph, *bold, *bemp;
860 SFONT *Norm, *Emph = NULL, *Bold = NULL, *Bemp = NULL;
861
862 norm = SF_defaultfont;
863 sf_VGA_SFONT = Norm = makefont(norm);
864 if (!Norm)
865 os_fatal("malloc() failure in initfonts()");
866 Norm->destroy = destroySFonly;
867
868 /* get size of default font */
869 size = SF_defaultfontsize;
870
871 /* copy norm to emphasized */
872 emph = malloc(size);
873 if (!emph)
874 os_fatal("malloc() failure in initfonts()");
875 Emph = makefont(emph);
876 if (!Emph)
877 os_fatal("malloc() failure in initfonts()");
878 memmove(emph, norm, size);
879 /* emphasize (underline)... */
880 cfont = (byte *) emph;
881 for (i = norm->minchar; i <= norm->maxchar; i++) {
882 int m = norm->glyphs[i - norm->minchar];
883 if (!m)
884 continue;
885 g = (SF_glyph *) (cfont + m);
886 bmp = (byte *) (&(g->bitmap[0]));
887 bmp[g->h - 2] = 0xff;
888 }
889 /* make a copy for bold */
890 bold = malloc(size);
891 if (!bold)
892 os_fatal("malloc() failure in initfonts()");
893 Bold = makefont(bold);
894 if (!Bold)
895 os_fatal("malloc() failure in initfonts()");
896 memmove(bold, norm, size);
897 /* boldify... */
898 cfont = (byte *) bold;
899 for (i = norm->minchar; i <= norm->maxchar; i++) {
900 int h, m = norm->glyphs[i - norm->minchar];
901 if (!m)
902 continue;
903 g = (SF_glyph *) (cfont + m);
904 h = g->h;
905 bmp = (byte *) (&(g->bitmap[0]));
906 for (j = 0; j < h; j++) {
907 int c = bmp[j];
908 bmp[j] = (c) | (c >> 1);
909 }
910 }
911 /* copy bold to bold, emphasized */
912 bemp = malloc(size);
913 if (!bemp)
914 os_fatal("malloc() failure in initfonts()");
915 Bemp = makefont(bemp);
916 if (!Bemp)
917 os_fatal("malloc() failure in initfonts()");
918 memmove(bemp, bold, size);
919 /* emphasize (underline)... */
920 cfont = (byte *) bemp;
921 for (i = norm->minchar; i <= norm->maxchar; i++) {
922 int m = norm->glyphs[i - norm->minchar];
923 if (!m)
924 continue;
925 g = (SF_glyph *) (cfont + m);
926 bmp = (byte *) (&(g->bitmap[0]));
927 bmp[g->h - 2] = 0xff;
928 }
929
930 myfonts[0] = myfonts[4] = Norm;
931 norm->refcount = 2;
932 myfonts[1] = myfonts[5] = Bold;
933 bold->refcount = 2;
934 myfonts[2] = myfonts[6] = Emph;
935 emph->refcount = 2;
936 myfonts[3] = myfonts[7] = Bemp;
937 bemp->refcount = 2;
938
939 CLEANREG(cleanfonts);
940
941 if (!m_vga_fonts) {
942 for (i = 0; i <= 8; i++)
943 if (m_fontfiles[i]) {
944 SFONT *b = tryloadfont(m_fontfiles[i],
945 i == 8 ? myfonts[FIXED_WIDTH_FONT]
946 : NULL);
947 if (!b)
948 fprintf(stderr,
949 "WARNING: could not load font%d [%s%c%s]\n",
950 i, m_fontdir, PATH_SEPARATOR, m_fontfiles[i]);
951 else {
952 setfontk(i, b);
953 b->refcount = 1;
954 }
955 }
956 }
957
958 if (ttfontsdone)
959 ttfontsdone();
960 /* now set the graphics font */
961 if (!myfonts[8]) {
962 if (myfonts[4]->height(myfonts[4]) < 16)
963 myfonts[8] = SF_font3;
964 else
965 myfonts[8] = SF_font3double;
966 }
967 }
968
969
sf_searchfile(char * fn,int fnlen,char * buf,char * paths)970 char *sf_searchfile(char *fn, int fnlen, char *buf, char *paths)
971 {
972 char *p;
973 if (!fn)
974 return NULL;
975 if (!paths)
976 paths = "";
977 if (fnlen < 0)
978 fnlen = strlen(fn);
979 if (!fnlen)
980 return NULL;
981 for (;;) {
982 int plen;
983 p = strchr(paths, OS_PATHSEP);
984 if (p)
985 plen = p - paths;
986 else
987 plen = strlen(paths);
988 if (plen)
989 strncpy(buf, paths, plen);
990 buf[plen] = 0;
991 if ((plen) && (buf[plen - 1] != '\\') && (buf[plen - 1] != '/'))
992 strcat(buf, "/");
993 plen = strlen(buf);
994 strncpy(buf + plen, fn, fnlen);
995 buf[plen + fnlen] = 0;
996 if (access(buf, F_OK) == 0)
997 return buf;
998 if (p)
999 paths = p + 1;
1000 else
1001 break;
1002 }
1003 return NULL;
1004 }
1005