2 * Copyright (c) 2014 - 2017 Steffen (Daode) Nurpmeso <steffen@sdaoden.eu>.
4 * Copyright (C) 1989 - 1992, 2000 - 2006, 2008
5 * Free Software Foundation, Inc.
6 * Written by James Clark (jjc@jclark.com)
8 * This is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU General Public License as published by the Free
10 * Software Foundation; either version 2, or (at your option) any later
13 * This is distributed in the hope that it will be useful, but WITHOUT ANY
14 * WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 * You should have received a copy of the GNU General Public License along
19 * with groff; see the file COPYING. If not, write to the Free Software
20 * Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA.
34 #include "file_case.h"
37 #include "searchpath.h"
40 const char * const WS
= " \t\n\r"; // FIXME lib.h?
42 struct font_char_metric
{
49 int italic_correction
;
50 int subscript_correction
;
51 char *special_device_coding
;
62 font_kern_list(glyph
*, glyph
*, int, font_kern_list
* = 0);
65 class font_widths_cache
68 font_widths_cache
*next
;
72 font_widths_cache(int, int, font_widths_cache
* = 0);
85 text_file(file_case
*fcp
);
88 void error(const char *format
,
89 const errarg
&arg1
= empty_errarg
,
90 const errarg
&arg2
= empty_errarg
,
91 const errarg
&arg3
= empty_errarg
);
94 text_file::text_file(file_case
*fcp
)
95 : fcp(fcp
), lineno(0), size(0), skip_comments(1), silent(0), buf(0)
99 text_file::~text_file()
106 int text_file::next()
117 int c
= fcp
->get_c();
120 if (invalid_input_char(c
))
121 error("invalid input character code `%1'", int(c
));
125 buf
= new char[size
*2];
126 memcpy(buf
, old_buf
, size
);
140 while (csspace(*ptr
))
142 if (*ptr
!= 0 && (!skip_comments
|| *ptr
!= '#'))
148 void text_file::error(const char *format
,
154 error_with_file_and_line(fcp
->path(), lineno
, format
, arg1
, arg2
, arg3
);
157 font::font(const char *s
)
158 : ligatures(0), kern_hash_table(0), space_width(0), special(0),
159 ch_index(0), nindices(0), ch(0), ch_used(0), ch_size(0), widths_cache(0)
161 name
= new char[strlen(s
) + 1];
166 // load(); // for testing
171 for (int i
= 0; i
< ch_used
; i
++)
172 if (ch
[i
].special_device_coding
)
173 a_delete ch
[i
].special_device_coding
;
176 if (kern_hash_table
) {
177 for (int i
= 0; i
< KERN_HASH_TABLE_SIZE
; i
++) {
178 font_kern_list
*kerns
= kern_hash_table
[i
];
180 font_kern_list
*tem
= kerns
;
185 a_delete kern_hash_table
;
188 a_delete internalname
;
189 while (widths_cache
) {
190 font_widths_cache
*tem
= widths_cache
;
191 widths_cache
= widths_cache
->next
;
196 static int scale_round(int n
, int x
, int y
)
198 assert(x
>= 0 && y
> 0);
203 if (n
<= (INT_MAX
- y2
) / x
)
204 return (n
* x
+ y2
) / y
;
205 return int(n
* double(x
) / double(y
) + .5);
208 if (-(unsigned)n
<= (-(unsigned)INT_MIN
- y2
) / x
)
209 return (n
* x
- y2
) / y
;
210 return int(n
* double(x
) / double(y
) - .5);
214 static int scale_round(int n
, int x
, int y
, int z
)
216 assert(x
>= 0 && y
> 0 && z
> 0);
220 return int((n
* double(x
) / double(y
)) * (double(z
) / 1000.0) + .5);
222 return int((n
* double(x
) / double(y
)) * (double(z
) / 1000.0) - .5);
225 inline int font::scale(int w
, int sz
)
228 return scale_round(w
, sz
, unitwidth
, zoom
);
230 return sz
== unitwidth
? w
: scale_round(w
, sz
, unitwidth
);
233 int font::unit_scale(double *value
, char unit
)
235 // we scale everything to inch
261 int font::get_skew(glyph
*g
, int point_size
, int sl
)
263 int h
= get_height(g
, point_size
);
264 return int(h
* tan((slant
+ sl
) * PI
/ 180.0) + .5);
267 int font::contains(glyph
*g
)
269 int idx
= glyph_to_index(g
);
271 // Explicitly enumerated glyph?
272 if (idx
< nindices
&& ch_index
[idx
] >= 0)
276 const char *nm
= glyph_to_name(g
);
279 if (nm
[0] == 'c' && nm
[1] == 'h' && nm
[2] == 'a' && nm
[3] == 'r'
280 && (nm
[4] >= '0' && nm
[4] <= '9')) {
281 int n
= (nm
[4] - '0');
284 if (n
> 0 && (nm
[5] >= '0' && nm
[5] <= '9')) {
285 n
= 10*n
+ (nm
[5] - '0');
288 if (nm
[6] >= '0' && nm
[6] <= '9') {
289 n
= 10*n
+ (nm
[6] - '0');
290 if (nm
[7] == '\0' && n
< 128)
295 // Unicode character?
296 if (check_unicode_name(nm
))
298 // If `nm' is a single letter `x', the glyph name is `\x'.
299 char buf
[] = { '\\', '\0', '\0' };
304 // groff glyph name that maps to Unicode?
305 const char *unicode
= glyph_name_to_unicode(nm
);
306 if (unicode
!= NULL
&& strchr(unicode
, '_') == NULL
)
309 // Numbered character?
310 int n
= glyph_to_number(g
);
317 int font::is_special()
322 font_widths_cache::font_widths_cache(int ps
, int ch_size
,
323 font_widths_cache
*p
)
324 : next(p
), point_size(ps
)
326 width
= new int[ch_size
];
327 for (int i
= 0; i
< ch_size
; i
++)
331 font_widths_cache::~font_widths_cache()
336 int font::get_width(glyph
*g
, int point_size
)
338 int idx
= glyph_to_index(g
);
342 real_size
= point_size
;
345 if (point_size
<= (INT_MAX
- 500) / zoom
)
346 real_size
= (point_size
* zoom
+ 500) / 1000;
348 real_size
= int(point_size
* double(zoom
) / 1000.0 + .5);
350 if (idx
< nindices
&& ch_index
[idx
] >= 0) {
351 // Explicitly enumerated glyph
352 int i
= ch_index
[idx
];
353 if (real_size
== unitwidth
|| font::unscaled_charwidths
)
357 widths_cache
= new font_widths_cache(real_size
, ch_size
);
358 else if (widths_cache
->point_size
!= real_size
) {
359 font_widths_cache
**p
;
360 for (p
= &widths_cache
; *p
; p
= &(*p
)->next
)
361 if ((*p
)->point_size
== real_size
)
364 font_widths_cache
*tem
= *p
;
366 tem
->next
= widths_cache
;
370 widths_cache
= new font_widths_cache(real_size
, ch_size
,
373 int &w
= widths_cache
->width
[i
];
375 w
= scale(ch
[i
].width
, point_size
);
380 int width
= 24; // value found in the original font files
381 // XXX: this must be eventually moved back to the
382 // font description file!
383 if (real_size
== unitwidth
|| font::unscaled_charwidths
)
386 return scale(width
, point_size
);
391 int font::get_height(glyph
*g
, int point_size
)
393 int idx
= glyph_to_index(g
);
395 if (idx
< nindices
&& ch_index
[idx
] >= 0) {
396 // Explicitly enumerated glyph
397 return scale(ch
[ch_index
[idx
]].height
, point_size
);
401 return 0; // value found in the original font files
402 // XXX: this must be eventually moved back to the
403 // font description file!
408 int font::get_depth(glyph
*g
, int point_size
)
410 int idx
= glyph_to_index(g
);
412 if (idx
< nindices
&& ch_index
[idx
] >= 0) {
413 // Explicitly enumerated glyph
414 return scale(ch
[ch_index
[idx
]].depth
, point_size
);
418 return 0; // value found in the original font files
419 // XXX: this must be eventually moved back to the
420 // font description file!
425 int font::get_italic_correction(glyph
*g
, int point_size
)
427 int idx
= glyph_to_index(g
);
429 if (idx
< nindices
&& ch_index
[idx
] >= 0) {
430 // Explicitly enumerated glyph
431 return scale(ch
[ch_index
[idx
]].italic_correction
, point_size
);
435 return 0; // value found in the original font files
436 // XXX: this must be eventually moved back to the
437 // font description file!
442 int font::get_left_italic_correction(glyph
*g
, int point_size
)
444 int idx
= glyph_to_index(g
);
446 if (idx
< nindices
&& ch_index
[idx
] >= 0) {
447 // Explicitly enumerated glyph
448 return scale(ch
[ch_index
[idx
]].pre_math_space
, point_size
);
452 return 0; // value found in the original font files
453 // XXX: this must be eventually moved back to the
454 // font description file!
459 int font::get_subscript_correction(glyph
*g
, int point_size
)
461 int idx
= glyph_to_index(g
);
463 if (idx
< nindices
&& ch_index
[idx
] >= 0) {
464 // Explicitly enumerated glyph
465 return scale(ch
[ch_index
[idx
]].subscript_correction
, point_size
);
469 return 0; // value found in the original font files
470 // XXX: this must be eventually moved back to the
471 // font description file!
476 void font::set_zoom(int factor
)
490 int font::get_space_width(int point_size
)
492 return scale(space_width
, point_size
);
495 font_kern_list::font_kern_list(glyph
*g1
, glyph
*g2
, int n
, font_kern_list
*p
)
496 : glyph1(g1
), glyph2(g2
), amount(n
), next(p
)
500 inline int font::hash_kern(glyph
*g1
, glyph
*g2
)
502 int n
= ((glyph_to_index(g1
) << 10) + glyph_to_index(g2
))
503 % KERN_HASH_TABLE_SIZE
;
504 return n
< 0 ? -n
: n
;
507 void font::add_kern(glyph
*g1
, glyph
*g2
, int amount
)
509 if (!kern_hash_table
) {
510 kern_hash_table
= new font_kern_list
*[int(KERN_HASH_TABLE_SIZE
)];
511 for (int i
= 0; i
< KERN_HASH_TABLE_SIZE
; i
++)
512 kern_hash_table
[i
] = 0;
514 font_kern_list
**p
= kern_hash_table
+ hash_kern(g1
, g2
);
515 *p
= new font_kern_list(g1
, g2
, amount
, *p
);
518 int font::get_kern(glyph
*g1
, glyph
*g2
, int point_size
)
520 if (kern_hash_table
) {
521 for (font_kern_list
*p
= kern_hash_table
[hash_kern(g1
, g2
)]; p
;
523 if (g1
== p
->glyph1
&& g2
== p
->glyph2
)
524 return scale(p
->amount
, point_size
);
529 int font::has_ligature(int mask
)
531 return mask
& ligatures
;
534 int font::get_character_type(glyph
*g
)
536 int idx
= glyph_to_index(g
);
538 if (idx
< nindices
&& ch_index
[idx
] >= 0) {
539 // Explicitly enumerated glyph
540 return ch
[ch_index
[idx
]].type
;
544 return 0; // value found in the original font files
545 // XXX: this must be eventually moved back to the
546 // font description file!
551 int font::get_code(glyph
*g
)
553 int idx
= glyph_to_index(g
);
555 if (idx
< nindices
&& ch_index
[idx
] >= 0) {
556 // Explicitly enumerated glyph
557 return ch
[ch_index
[idx
]].code
;
561 const char *nm
= glyph_to_name(g
);
564 if (nm
[0] == 'c' && nm
[1] == 'h' && nm
[2] == 'a' && nm
[3] == 'r'
565 && (nm
[4] >= '0' && nm
[4] <= '9')) {
566 int n
= (nm
[4] - '0');
569 if (n
> 0 && (nm
[5] >= '0' && nm
[5] <= '9')) {
570 n
= 10*n
+ (nm
[5] - '0');
573 if (nm
[6] >= '0' && nm
[6] <= '9') {
574 n
= 10*n
+ (nm
[6] - '0');
575 if (nm
[7] == '\0' && n
< 128)
580 // Unicode character?
581 if (check_unicode_name(nm
)) {
583 return (int)strtol(nm
+ 1, &ignore
, 16);
585 // If `nm' is a single letter `x', the glyph name is `\x'.
586 char buf
[] = { '\\', '\0', '\0' };
591 // groff glyphs that map to Unicode?
592 const char *unicode
= glyph_name_to_unicode(nm
);
593 if (unicode
!= NULL
&& strchr(unicode
, '_') == NULL
) {
595 return (int)strtol(unicode
, &ignore
, 16);
598 // Numbered character?
599 int n
= glyph_to_number(g
);
603 // The caller must check `contains(g)' before calling get_code(g).
607 const char *font::get_name()
612 const char *font::get_internal_name()
617 const char *font::get_special_device_encoding(glyph
*g
)
619 int idx
= glyph_to_index(g
);
621 if (idx
< nindices
&& ch_index
[idx
] >= 0) {
622 // Explicitly enumerated glyph
623 return ch
[ch_index
[idx
]].special_device_coding
;
632 const char *font::get_image_generator()
634 return image_generator
;
637 void font::alloc_ch_index(int idx
)
643 ch_index
= new int[nindices
];
644 for (int i
= 0; i
< nindices
; i
++)
648 int old_nindices
= nindices
;
652 int *old_ch_index
= ch_index
;
653 ch_index
= new int[nindices
];
654 memcpy(ch_index
, old_ch_index
, sizeof(int)*old_nindices
);
655 for (int i
= old_nindices
; i
< nindices
; i
++)
657 a_delete old_ch_index
;
661 void font::extend_ch()
664 ch
= new font_char_metric
[ch_size
= 16];
666 int old_ch_size
= ch_size
;
668 font_char_metric
*old_ch
= ch
;
669 ch
= new font_char_metric
[ch_size
];
670 memcpy(ch
, old_ch
, old_ch_size
*sizeof(font_char_metric
));
678 for (i
= nindices
- 1; i
>= 0; i
--)
679 if (ch_index
[i
] >= 0)
683 int *old_ch_index
= ch_index
;
684 ch_index
= new int[i
];
685 memcpy(ch_index
, old_ch_index
, i
*sizeof(int));
686 a_delete old_ch_index
;
689 if (ch_used
< ch_size
) {
690 font_char_metric
*old_ch
= ch
;
691 ch
= new font_char_metric
[ch_used
];
692 memcpy(ch
, old_ch
, ch_used
*sizeof(font_char_metric
));
698 void font::add_entry(glyph
*g
, const font_char_metric
&metric
)
700 int idx
= glyph_to_index(g
);
704 assert(idx
< nindices
);
705 if (ch_used
+ 1 >= ch_size
)
707 assert(ch_used
+ 1 < ch_size
);
708 ch_index
[idx
] = ch_used
;
709 ch
[ch_used
++] = metric
;
712 void font::copy_entry(glyph
*new_glyph
, glyph
*old_glyph
)
714 int new_index
= glyph_to_index(new_glyph
);
715 int old_index
= glyph_to_index(old_glyph
);
716 assert(new_index
>= 0 && old_index
>= 0 && old_index
< nindices
);
717 if (new_index
>= nindices
)
718 alloc_ch_index(new_index
);
719 ch_index
[new_index
] = ch_index
[old_index
];
722 font
*font::load_font(const char *s
, int *not_found
, int head_only
)
724 font
*f
= new font(s
);
725 if (!f
->load(not_found
, head_only
)) {
732 static char *trim_arg(char *p
)
738 char *q
= strchr(p
, '\0');
739 while (q
> p
&& csspace(q
[-1]))
745 int font::scan_papersize(const char *p
,
746 const char **size
, double *length
, double *width
)
755 if (sscanf(pp
, "%lf%1[ipPc],%lf%1[ipPc]", &l
, lu
, &w
, wu
) == 4
757 && unit_scale(&l
, lu
[0]) && unit_scale(&w
, wu
[0])) {
769 for (i
= 0; i
< NUM_PAPERSIZES
; i
++)
770 if (strcasecmp(papersizes
[i
].name
, pp
) == 0) {
772 *length
= papersizes
[i
].length
;
774 *width
= papersizes
[i
].width
;
776 *size
= papersizes
[i
].name
;
780 FILE *f
= fopen(p
, "r");
785 char *linep
= strchr(line
, '\0');
786 // skip final newline, if any
787 if (*(--linep
) == '\n')
797 // If the font can't be found, then if not_found is non-NULL, it will be set
798 // to 1 otherwise a message will be printed.
800 int font::load(int *not_found
, int head_only
)
802 if (strcmp(name
, "DESC") == 0) {
806 error("`DESC' is not a valid font file name");
810 if ((fcp
= open_file(name
)) == NULL
) {
814 error("can't find font file `%1'", name
);
819 t
.silent
= head_only
;
826 p
= strtok(t
.buf
, WS
);
827 if (strcmp(p
, "name") == 0) {
829 else if (strcmp(p
, "spacewidth") == 0) {
832 if (p
== 0 || sscanf(p
, "%d", &n
) != 1 || n
<= 0) {
833 t
.error("bad argument for `spacewidth' command");
838 else if (strcmp(p
, "slant") == 0) {
841 if (p
== 0 || sscanf(p
, "%lf", &n
) != 1 || n
>= 90.0 || n
<= -90.0) {
842 t
.error("bad argument for `slant' command", p
);
847 else if (strcmp(p
, "ligatures") == 0) {
850 if (p
== 0 || strcmp(p
, "0") == 0)
852 if (strcmp(p
, "ff") == 0)
854 else if (strcmp(p
, "fi") == 0)
856 else if (strcmp(p
, "fl") == 0)
858 else if (strcmp(p
, "ffi") == 0)
859 ligatures
|= LIG_ffi
;
860 else if (strcmp(p
, "ffl") == 0)
861 ligatures
|= LIG_ffl
;
863 t
.error("unrecognised ligature `%1'", p
);
868 else if (strcmp(p
, "internalname") == 0) {
871 t
.error("`internalname' command requires argument");
874 internalname
= new char[strlen(p
) + 1];
875 strcpy(internalname
, p
);
877 else if (strcmp(p
, "special") == 0) {
880 else if (strcmp(p
, "kernpairs") != 0 && strcmp(p
, "charset") != 0) {
883 handle_unknown_font_command(command
, trim_arg(p
), t
.fcp
->path(),
892 t
.error("missing charset command");
899 if (strcmp(command
, "kernpairs") == 0) {
907 char *c1
= strtok(t
.buf
, WS
);
910 char *c2
= strtok(0, WS
);
917 t
.error("missing kern amount");
921 if (sscanf(p
, "%d", &n
) != 1) {
922 t
.error("bad kern amount `%1'", p
);
925 glyph
*g1
= name_to_glyph(c1
);
926 glyph
*g2
= name_to_glyph(c2
);
930 else if (strcmp(command
, "charset") == 0) {
934 glyph
*last_glyph
= NULL
;
940 char *nm
= strtok(t
.buf
, WS
);
942 continue; // I dont think this should happen
949 if (last_glyph
== NULL
) {
950 t
.error("first charset entry is duplicate");
953 if (strcmp(nm
, "---") == 0) {
954 t
.error("unnamed character cannot be duplicate");
957 glyph
*g
= name_to_glyph(nm
);
958 copy_entry(g
, last_glyph
);
961 font_char_metric metric
;
964 metric
.pre_math_space
= 0;
965 metric
.italic_correction
= 0;
966 metric
.subscript_correction
= 0;
967 int nparms
= sscanf(p
, "%d,%d,%d,%d,%d,%d",
968 &metric
.width
, &metric
.height
, &metric
.depth
,
969 &metric
.italic_correction
,
970 &metric
.pre_math_space
,
971 &metric
.subscript_correction
);
973 t
.error("bad width for `%1'", nm
);
978 t
.error("missing character type for `%1'", nm
);
982 if (sscanf(p
, "%d", &type
) != 1) {
983 t
.error("bad character type for `%1'", nm
);
986 if (type
< 0 || type
> 255) {
987 t
.error("character type `%1' out of range", type
);
993 t
.error("missing code for `%1'", nm
);
997 metric
.code
= (int)strtol(p
, &ptr
, 0);
998 if (metric
.code
== 0 && ptr
== p
) {
999 t
.error("bad code `%1' for character `%2'", p
, nm
);
1003 if ((p
== NULL
) || (strcmp(p
, "--") == 0)) {
1004 metric
.special_device_coding
= NULL
;
1007 char *nam
= new char[strlen(p
) + 1];
1009 metric
.special_device_coding
= nam
;
1011 if (strcmp(nm
, "---") == 0) {
1012 last_glyph
= number_to_glyph(metric
.code
);
1013 add_entry(last_glyph
, metric
);
1016 last_glyph
= name_to_glyph(nm
);
1017 add_entry(last_glyph
, metric
);
1018 copy_entry(number_to_glyph(metric
.code
), last_glyph
);
1022 if (last_glyph
== NULL
) {
1023 t
.error("I didn't seem to find any characters");
1028 t
.error("unrecognised command `%1' "
1029 "after `kernpairs' or `charset' command",
1036 if (!is_unicode
&& !had_charset
) {
1037 t
.error("missing `charset' command");
1040 if (space_width
== 0) {
1042 space_width
= scale_round(unitwidth
, res
, 72 * 3 * sizescale
, zoom
);
1044 space_width
= scale_round(unitwidth
, res
, 72 * 3 * sizescale
);
1050 const char *command
;
1052 } table
[] = { // FIXME const?
1053 { "res", &font::res
},
1054 { "hor", &font::hor
},
1055 { "vert", &font::vert
},
1056 { "unitwidth", &font::unitwidth
},
1057 { "paperwidth", &font::paperwidth
},
1058 { "paperlength", &font::paperlength
},
1059 { "spare1", &font::biggestfont
},
1060 { "biggestfont", &font::biggestfont
},
1061 { "spare2", &font::spare2
},
1062 { "sizescale", &font::sizescale
},
1065 int font::load_desc()
1069 if ((fcp
= open_file("DESC")) == NULL
) {
1070 error("can't find `DESC' file");
1074 t
.skip_comments
= 1;
1077 char *p
= strtok(t
.buf
, WS
);
1080 for (idx
= 0; !found
&& idx
< sizeof(table
)/sizeof(table
[0]); idx
++)
1081 if (strcmp(table
[idx
].command
, p
) == 0)
1084 char *q
= strtok(0, WS
);
1086 t
.error("missing value for command `%1'", p
);
1089 //int *ptr = &(this->*(table[idx-1].ptr));
1090 int *ptr
= table
[idx
-1].ptr
;
1091 if (sscanf(q
, "%d", ptr
) != 1) {
1092 t
.error("bad number `%1'", q
);
1096 else if (strcmp("family", p
) == 0) {
1099 t
.error("family command requires an argument");
1102 char *tem
= new char[strlen(p
)+1];
1106 else if (strcmp("fonts", p
) == 0) {
1108 if (!p
|| sscanf(p
, "%d", &nfonts
) != 1 || nfonts
<= 0) {
1109 t
.error("bad number of fonts `%1'", p
);
1112 font_name_table
= (const char **)new char *[nfonts
+1];
1113 for (int i
= 0; i
< nfonts
; i
++) {
1117 t
.error("end of file while reading list of fonts");
1120 p
= strtok(t
.buf
, WS
);
1122 char *temp
= new char[strlen(p
)+1];
1124 font_name_table
[i
] = temp
;
1128 t
.error("font count does not match number of fonts");
1131 font_name_table
[nfonts
] = 0;
1133 else if (strcmp("papersize", p
) == 0) {
1136 t
.error("papersize command requires an argument");
1139 int found_paper
= 0;
1141 double unscaled_paperwidth
, unscaled_paperlength
;
1142 if (scan_papersize(p
, &papersize
, &unscaled_paperlength
,
1143 &unscaled_paperwidth
)) {
1144 paperwidth
= int(unscaled_paperwidth
* res
+ 0.5);
1145 paperlength
= int(unscaled_paperlength
* res
+ 0.5);
1152 t
.error("bad paper size");
1156 else if (strcmp("unscaled_charwidths", p
) == 0)
1157 unscaled_charwidths
= 1;
1158 else if (strcmp("pass_filenames", p
) == 0)
1160 else if (strcmp("sizes", p
) == 0) {
1168 t
.error("list of sizes must be terminated by `0'");
1171 p
= strtok(t
.buf
, WS
);
1174 switch (sscanf(p
, "%d-%d", &lower
, &upper
)) {
1179 if (lower
<= upper
&& lower
>= 0)
1183 t
.error("bad size range `%1'", p
);
1187 int *old_sizes
= sizes
;
1188 sizes
= new int[n
*2];
1189 memcpy(sizes
, old_sizes
, n
*sizeof(int));
1199 t
.error("must have some sizes");
1203 else if (strcmp("styles", p
) == 0) {
1204 int style_table_size
= 5;
1205 style_table
= (const char **)new char *[style_table_size
];
1207 for (j
= 0; j
< style_table_size
; j
++)
1214 // leave room for terminating 0
1215 if (i
+ 1 >= style_table_size
) {
1216 const char **old_style_table
= style_table
;
1217 style_table_size
*= 2;
1218 style_table
= (const char **)new char*[style_table_size
];
1219 for (j
= 0; j
< i
; j
++)
1220 style_table
[j
] = old_style_table
[j
];
1221 for (; j
< style_table_size
; j
++)
1223 a_delete old_style_table
;
1225 char *tem
= new char[strlen(p
) + 1];
1227 style_table
[i
++] = tem
;
1230 else if (strcmp("tcommand", p
) == 0)
1232 else if (strcmp("use_charnames_in_special", p
) == 0)
1233 use_charnames_in_special
= 1;
1234 else if (strcmp("unicode", p
) == 0)
1236 else if (strcmp("image_generator", p
) == 0) {
1239 t
.error("image_generator command requires an argument");
1242 image_generator
= strsave(p
);
1244 else if (strcmp("charset", p
) == 0)
1246 else if (unknown_desc_command_handler
) {
1248 p
= strtok(0, "\n");
1249 (*unknown_desc_command_handler
)(command
, trim_arg(p
), t
.fcp
->path(),
1254 t
.error("missing `res' command");
1257 if (unitwidth
== 0) {
1258 t
.error("missing `unitwidth' command");
1261 if (font_name_table
== 0) {
1262 t
.error("missing `fonts' command");
1266 t
.error("missing `sizes' command");
1269 if (sizescale
< 1) {
1270 t
.error("bad `sizescale' value");
1274 t
.error("bad `hor' value");
1278 t
.error("bad `vert' value");
1284 void font::handle_unknown_font_command(const char *, const char *,
1289 FONT_COMMAND_HANDLER
1290 font::set_unknown_desc_command_handler(FONT_COMMAND_HANDLER func
)
1292 FONT_COMMAND_HANDLER prev
= unknown_desc_command_handler
;
1293 unknown_desc_command_handler
= func
;