The htf fonts are used only within the text part of the html files.
Each char code i in a font may be assigned a string representation and a gif option. When the gif option is provided, the character is taken to be a picture with ALT getting the string for nongraphical reviewers.
For character code i, 0 ≤ i ≤ 255, we maintain
In the ‘.htf’ files, uses line entries of the form ‘string1string2...’, where the strings have the same arbitrary open and close delimiters. An empty second string indicate no-option gif.
<..entries for html chars in font-tbl..>
char *name, *gif_on, *ch_str, ch255; 2000
unsigned U_CHAR **str, *ch, *gif1;
-_-_-
The following provides a value for characters of missing fonts out of the range 32–127. Within that range, the character codes are being used.
<..get ignored chars..>
char *digit = p+2;
ignore_ch = 0;
while( *digit != ’\0’ ){
if( (*digit < ’0’) || (*digit > ’9’) ){
ignore_ch = 0; break;
}
ignore_ch = 10 * ignore_ch + (*digit - ’0’);
if( ignore_ch > 255 ){ ignore_ch = 0; break; }
digit++;
}
-_-_-
<..vars..>+
static int ignore_ch = 0;
-_-_-
In case of shared htf fonts, we can have much more sharing below.
Lynx introduces a space before and after each figure.
<..get html characters..>
{ U_CHAR str[256];
int i, design_n, n_gif;
<.font looping variables.>
n_gif = new_font.char_l - new_font.char_f + 1;
new_font.ch255 = 0;
<.initiate gif flags.>
<.initiate htf accents.>
new_font.ch = m_alloc(unsigned char, n_gif );
<.set default characters.>
new_font.str = m_alloc(unsigned char*, n_gif);
new_font.str[0] = &null_str;
design_n = 0;
<.load file of characters.>
new_font.str = (unsigned U_CHAR **) r_alloc((void *) new_font.str,
(size_t) ( (design_n?design_n:1) * sizeof(char *)) );
<.merge new html font with old ones.>
}
-_-_-
A value 0 corresponds to an empty string. A value greater than 0 points to a character string. ‘ design_n = 0;’ had value 1 earlier. Probably because we had ‘design_n’, and not ‘(design_n?design_n:1)’, which asked for allocation of memory of size 0. This caused a problem to mallocate, because it produced a non-valid 0 ( ‘insuffient memory’) error
<..vars..>+
static unsigned U_CHAR null_str = ’\0’; /*NEW*/
-_-_-
<..initiate gif flags..>
{ int n_gif_bytes;
n_gif_bytes = (n_gif + 7) / 8;
new_font.gif_on = m_alloc(char, n_gif_bytes );
new_font.ch_str = m_alloc(char, n_gif_bytes );
<.memory for math classes.>
for( i=n_gif_bytes; i--; ) {
<.init math-closing.> new_font.ch_str[i] = new_font.gif_on[i] = 0;
}
new_font.gif1 = m_alloc(unsigned char, n_gif );
for( i=n_gif; i--; ) {
<.init math.> new_font.gif1[i] = 0;
} }
-_-_-
<..set default characters..>
for( i = new_font.char_f; i <= new_font.char_l ; i++ ){
new_font.ch[i - new_font.char_f] =
(char) (((31<i) && (i<128))? i : ignore_ch);
}
-_-_-
The first iteration searches for the font directly. The second iteration searches for aliased font.
<..load file of characters..>
{ char search_font_name [256];
(IGNORED) strcpy((char *) search_font_name, (char *) new_font.name);
while( 1 ){ BOOL flag;
<.font looping test.>
flag = TRUE;
for( ; font_name_n; font_name_n-- ){ FILE* file;
int char_f, char_l;
new_font_name[font_name_n] = ’\0’;
<.file = .htf file.>
if( file != NULL){
INTEGER x_char_l;
<.scan header line in html font file.>
if( x_char_l == HTF_ALIAS) {
<.scan aliased htf file.>
(IGNORED) fclose(file); flag = FALSE; break;
}
<.scan info of html font file.>
<.scan trailer line in html font file.>
htf_to_lg(html_font, new_font_name, fonts_n, file);
<.trace htf files.>
(IGNORED) fclose(file); break;
} }
if( flag ){ break; }
}
if( font_name_n == 0 ){
if( errCode == 0 ){ errCode= 21; }
warn_i_str(21,search_font_name);
(IGNORED) fprintf(stderr,
"%d--%d)\n", new_font.char_f, new_font.char_l);
dump_env();
} else { <.trace env file.> }
}
-_-_-
<..font looping variables..>
int loopBound = 0;
U_CHAR loopName[256];
loopName[0] = ’\0’;
-_-_-
<..font looping test..>
if( eq_str( new_font_name, loopName) ){
U_CHAR name[256];
(IGNORED) sprintf(name, "%s.htf", new_font_name);
err_i_str(1, name);
} else {
(IGNORED) strcpy((char *) loopName, (char *) new_font_name);
}
loopBound++;
if( loopBound > 10 ){
U_CHAR name[256];
(IGNORED) sprintf(name, "%s.htf", new_font_name);
err_i_str(1, name);
}
-_-_-
<..if alias return 0..>
if( ( name == new_font_name ) && (n == 19) && (ch==’.’) ){
return HTF_ALIAS;
}
-_-_-
<..defines..>+
#define HTF_ALIAS 10000000
-_-_-
[more]
<..scan aliased htf file..>
{ int chr;
font_name_n=0;
while( (chr = get_html_ch(file)) != ’\n’ ){
if( chr != ’ ’ ) search_font_name[font_name_n++] = chr;
}
search_font_name[font_name_n] = ’\0’;
if( eq_str( search_font_name, new_font_name) ){ err_i_str(20, new_font_name); }
(IGNORED) printf("Searching ‘%s.htf’ for ‘%s.htf’\n",
search_font_name, new_font.name);
htf_to_lg(html_font, new_font_name, fonts_n, file);
new_font_name = (char *) r_alloc((void *) new_font_name,
(size_t) (font_name_n+1));
(IGNORED) strcpy((char *) new_font_name, (char *) search_font_name);
font_name_n = strlen((char *) new_font_name);
}
-_-_-
<..get replacement fontNO..>
if( dot_file ){ BOOL tag;
(IGNORED) fseek(dot_file, 0L, <.abs file addr.>);
tag = TRUE;
while( tag ){
switch( getc(dot_file) ){
case EOF: { j++; tag = FALSE; break; } no replacement
case ’a’: { <.scan replacement font.> }
default: { int ch;
do ch = getc(dot_file);
while( (ch != ’\n’) && (ch != EOF) );
break; }
} } }
-_-_-
<..scan replacement fontNO..>
int chr;
U_CHAR *ch;
ch = new_font.name;
while( *ch++ == (chr = getc(dot_file)) );
if( chr==’ ’ ){
tag = FALSE;
while( (new_font_name[0] = getc(dot_file)) == ’ ’ );
font_name_n=1;
while( (chr = getc(dot_file)) != ’\n’ )
if( chr != ’ ’ ) new_font_name[font_name_n++] = chr;
new_font_name[font_name_n] = ’\0’;
(IGNORED) printf("Loading ‘%s.htf’ for ‘%s.htf’\n",
new_font_name, new_font.name);
}
-_-_-
Don’t we loose some vital info here? Were this comes from?
<..merge new html font with old ones..>
for( i = fonts_n; i--; )
if( eq_str(html_font[i].name, new_font_name) ){ int k;
k = html_font[i].i;
free((void *) new_font.gif1 ); new_font.gif1= font_tbl[ k ].gif1;
free((void *) new_font.ch ); new_font.ch = font_tbl[ k ].ch;
free((void *) new_font.str ); new_font.str = font_tbl[ k ].str;
free((void *) new_font.ch_str );
new_font.ch_str = font_tbl[ k ].ch_str;
<.merge math entries.>
break; }
if( i < 0 ){ <.record new tex4ht font.> }
-_-_-
<..record new tex4ht font..>
html_font = fonts_n? (struct html_font_rec *) r_alloc((void *) html_font,
(size_t) ((fonts_n+1) * sizeof(struct html_font_rec) ))
: m_alloc(struct html_font_rec, 1);
html_font[fonts_n].name = m_alloc(char, font_name_n + 1);
(IGNORED) strcpy((char *) html_font[fonts_n].name, (char *) new_font_name);
html_font[fonts_n].i = font_tbl_size;
fonts_n++;
-_-_-
<..scan fonts vars..>
int fonts_n;
struct html_font_rec *html_font=0;
-_-_-
<..init scan fonts vars..>
fonts_n = 0;
-_-_-
<..free html font memory..>
if( html_font ){
while( fonts_n-- ) free((void *) html_font[fonts_n].name);
free((void *) html_font );
}
-_-_-
EXPLAIN THE CONTENT OF THE FOLLOWING
<..types..>+
struct html_font_rec{ char* name;
int i; };
-_-_-
<..scan info of html font file..>
if( char_f <= new_font.char_l ){ U_CHAR del;
int j, n;
<.skip front part in font file.>
n = ((char_l < new_font.char_l)? char_l : new_font.char_l)
- char_f + 1;
for( i = char_f - new_font.char_f; i < n; i++ ){
<.scan html char in font file.>
<.store html character.> }
<.skip back part of font file.>
}
-_-_-
<..skip front part in font file..>
while( char_f < new_font.char_f ){
while( get_html_ch(file) != ’\n’ );
char_f++; }
-_-_-
<..skip back part of font file..>
while( char_l > new_font.char_l ){
while( get_html_ch(file) != ’\n’ );
char_l--; }
-_-_-
We should consider characters having representations of ‘\decimal digits\’, ‘\x hexadecimal digits\’, and ‘\o octal digits\’.
<..scan html char in font file..>
{ int indirect_ch, base=0, value=0, digit, ch1, ch2;
indirect_ch = 0;
del = get_html_ch(file); j=0;
while( (str[j++] = get_html_ch(file)) != del )
{ <.check for encoded chars.> };
str[j-1] = ’\0’;
while( get_html_ch(file) != del );
ch1 = 0;
while( ((ch = (int) get_html_ch(file)) != del) ){
if( (ch < ’0’) || (ch > ’9’) ) break;
ch1 = ch1 * 10 + ch - ’0’; }
<.propagate 4hf info into htf.>
new_font.gif1[i] = ch1 % 256;
do{
if( (ch = get_html_ch(file)) == del ){
<.scan htf accent.> break;
}
} while( ch != ’\n’ );
if( ch != ’\n’ ){
do{
if( (ch = get_html_ch(file)) == del ){
<.scan htf accented.> break;
}
} while( ch != ’\n’ );
}
if( ch != ’\n’ )
{ while( get_html_ch(file) != ’\n’ ); }
}
-_-_-
<..check for encoded chars..>
if( (digit=str[j-1]) == ’\\’ )
if( (indirect_ch = !indirect_ch) != 0) {
switch( value=get_html_ch(file) ){
case ’x’: { base = 16; value = 0; j--; break; }
case ’o’: { base = 8; value = 0; j--; break; }
default: {
if( (value < ’0’) || (value > ’9’) ) {
indirect_ch = !indirect_ch; str[j-1] = value;
} else { value -= ’0’; base = 10; j--; }
} } }
else{ if( value>255 ){
warn_i_int(28,value);
value = 32; dump_htf( file );
}
str[j-1] = value;
}
else if ( indirect_ch ){
j--; digit -= (digit>’9’)? ’A’-10 : ’0’;
if( (digit<0) || (digit>=base) ){
warn_i_int(29, str[j]);
digit = 0; dump_htf( file );
}
value = value*base + digit;
} else if ( str[j-1]==10 ){
dump_htf( file );
err_i_int(48, i+1);
}
-_-_-
We might be able in the following to share strings by comparing with corresponding characters in other fonts.
The variable j holds the number of characters in the string plus one.
<..store html character..>
add_bit( new_font.ch_str, i, j!=2 );
switch( j ){
case 1: { new_font.ch[i] = 0; break; }
case 2: { new_font.ch[i] = *str; break; }
default: { unsigned U_CHAR *p;
new_font.str[design_n] = p = m_alloc(unsigned char, j);
if( design_n>255 ){ design_n--; warn_i(35);}
if( i==255 ){
if( design_n == 255 ){
new_font.ch[i] = 0; new_font.ch255 = 1;
} else { new_font.ch[i] = ++design_n; }
} else { new_font.ch[i] = ++design_n; }
while( j-- ) p[j] = str[j]; 2000
} }
-_-_-
<..header functions..>+
static int get_html_ch( ARG_I(FILE*) );
-_-_-
<..functions..>+
static int get_html_ch( file ) FILE* file
;{ int ch;
if( (ch = (int) getc(file)) == EOF ) {
dump_htf( file );
err_i_str(20, new_font_name);
}
return ch;
}
-_-_-
<..header functions..>+
static FILE* f_open( ARG_II(const char*,const char*) );
-_-_-
<..functions..>+
static FILE* f_open( name, flags )
const char* name ;
const char* flags
;{ FILE* file;
if( (file = fopen(name,flags) ) != NULL ) {
(IGNORED) printf("(%s)\n",name);
}
return file;
}
-_-_-
<..header functions..>+
static void dump_htf( ARG_I(FILE*) );
-_-_-
<..functions..>+
static void dump_htf( file ) FILE* file
;{ int i, j, ch, chr=0;
(IGNORED) fseek(file, 0L, 0);
i=-1; j=0;
while( (ch = getc(file)) != EOF ){
if( !j ){ chr = ch; }
j += ch==chr;
(IGNORED) putc(ch,stderr);
if( ch == ’\n’ ){
if( (i>-1 ) && (j<4) && (dump_htf_files<2) ){
(IGNORED) printf("missing delimiter \n");
}
(IGNORED) fprintf(stderr,"%d: ",++i);
j=0;
} } }
-_-_-
<..vars..>+
static short dump_htf_files = 0;
static BOOL dump_env_files = FALSE;
-_-_-
<..dump htf files..>
dump_htf_files = 1;
-_-_-
<..dump env file..>
dump_env_files = TRUE;
-_-_-
<..trace htf files..>
if( dump_htf_files ){
dump_htf_files++; dump_htf( file ); dump_htf_files--;
}
-_-_-
<..trace env file..>
if( dump_env_files ){ dump_env(); }
-_-_-
<..header functions..>+
static void dump_env( ARG_I(void) );
-_-_-
<..functions..>+
static void dump_env( MYVOID )
{
int ch;
if( !dumped_env ){
dumped_env = TRUE;
(IGNORED) fseek(dot_file, 0L, <.abs file addr.>);
(IGNORED) fprintf(stderr,
"\n----------------------------------------------------\n");
(IGNORED) fprintf(stderr, "environment file\n");
(IGNORED) fprintf(stderr,
"----------------------------------------------------\n");
while( (ch = getc(dot_file)) != EOF ){
(IGNORED) putc(ch,stderr);
}
(IGNORED) fprintf(stderr,
"----------------------------------------------------\n");
} }
-_-_-
<..vars..>+
static BOOL dumped_env = FALSE;
-_-_-
<..header functions..>+
static void htf_to_lg( ARG_IV(struct html_font_rec*,char*,int,FILE*));
-_-_-
<..functions..>+
static void htf_to_lg(html_font, new_font_name, fonts_n, file)
struct html_font_rec* html_font;
char* new_font_name;
int fonts_n;
FILE* file
;{
int ch, i;
for( i = 0 ; i<fonts_n; ){
if( eq_str(html_font[i].name, new_font_name) ){ break; }
i++;
}
if( i == fonts_n ){
BOOL content;
int prev_ch;
prev_ch = ’\n’; content = FALSE;
while( (ch = (int) getc(file)) != EOF ) {
if( (ch != ’\n’) || (prev_ch != ’\n’) ){
(void) putc( ch, log_file );
prev_ch = ch; content = TRUE;
} }
if( content && (prev_ch != ’\n’) ){
(void) putc( ’\n’, log_file );
}
} }
-_-_-
<..scan header line in html font file..>
x_char_l =
get_html_file_id(file, new_font.char_f, new_font.char_l, 19);
if( x_char_l != HTF_ALIAS) {
char_f = (int) (x_char_l / 1000.0 + 0.5) + new_font.char_f;
x_char_l -= (char_f-new_font.char_f) * 1000 - new_font.char_l;
char_l = (int) x_char_l;
}
-_-_-
<..scan trailer line in html font file..>
(void) get_html_file_id(file, new_font.char_f, new_font.char_l, 18);
-_-_-
<..header functions..>+
static INTEGER get_html_file_id( ARG_IV(FILE*, int, int, int) );
-_-_-
<..functions..>+
static INTEGER get_html_file_id(file, first, last, n)
FILE* file;
int first; int last; int n
;{ int ch, i, bound, cnt;
INTEGER diff;
char* name;
name = new_font_name;
while( *name == (ch = get_html_ch(file)) ) name++;
<.if alias return 0.>
if( (*name != ’\0’) || (ch != ’ ’) ) warn_i_str(n, name);
bound = first; diff = 0;
for( cnt = 0; cnt < 2; cnt++ ){
while( ch == ’ ’ ) ch = get_html_ch(file);
i = 0;
while( (ch >= ’0’) && (ch <= ’9’) ){
i = i * 10 + ch - ’0’; ch = get_html_ch(file); }
if( i != bound ){
<.warning(22.>, new_font_name, i, bound); show_err_context();
diff = diff * 1000 + i - bound; }
bound = last; }
while( ch != ’\n’ ) ch = get_html_ch(file);
return diff;
}
-_-_-
<..defines..>+
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#ifndef BOOL
#define BOOL int
#endif
-_-_-
When next_char is not equal to -1, there is a character waiting to replace the current character.
<..insert ch to text..>
<.set begin accents.>
<.css for chars.> <.trace dvi char.>
<.left class del.> <.pos dvi ch.>
<.mark accented ch.>
if( <.next-char.> != -1 ) {
<.open output file.>
(IGNORED) put_4ht_ch( <.next-char.>, cur_o_file );
<.next-char.> = -1;
} else if( <.next-str.> ) {
<.current char for forwarded string.>
print_f_4ht(next_str); free((void *) next_str);
next_str = (char *) 0;
} else {
if( verb_ch ){
<.open output file.>
(IGNORED) put_4ht_ch( ch, cur_o_file );
} else { <.insert font char.> }
}
<.end mark accented ch.>
<.end pos dvi ch.> <.right class del.>
<.end trace dvi char.> <.end css for chars.>
<.set end accents.>
-_-_-
Does ‘verb_ch’ correspond to \Char?
<..insert font char..>
int gif_flag, chr, r_ch;
BOOL ch_str_flag;
r_ch = ch - font_tbl[cur_fnt].char_f;
gif_flag = font_tbl[cur_fnt].gif1[r_ch];
ch_str_flag = get_bit( font_tbl[cur_fnt].ch_str, r_ch);
chr = ((r_ch == 255) && font_tbl[cur_fnt].ch255 )? 256 :
*(font_tbl[cur_fnt].ch + r_ch);
if( (gif_flag % 2) || ch_str_flag ){ design_ch = ch;
{ <.insert design chr.> } design_ch = 0; }
else { <.insert standard char.> }
-_-_-
<..vars..>+
static BOOL verb_ch = FALSE;
-_-_-
A design character is either a picture (gif_flag) or a string character (ch_str_flag).
<..insert design chr..>
U_CHAR str[256], *p;
BOOL sv;
int mag;
sv = special_on; special_on = TRUE;
if( gif_ch && (gif_flag % 2) ){
<.open output file.>
if( !gif_open[gif_flag] ){
<.img char without template.>
} else if( !get_bit( class_on, gif_flag ) ) {
notify_class_info(gif_flag);
store_bit_I( class_on, gif_flag );
}
<.<IMG SRC="....>
<...."ALT="....>
<...."CLASS="family....>
<....gif font size....>
<....gif font mag....>
<....gif sym ord....>
<...."/IMG>.>
} else { <.insert string char.> }
special_on = sv;
-_-_-
<..header functions..>+
static void notify_class_info( ARG_I(int) );
-_-_-
<..functions..>+
static void notify_class_info( gif_flag ) int gif_flag
;{ U_CHAR str[256], *p;
str[0] = ’\0’;
p = gif_open[gif_flag];
if( p )
if( *p ) (IGNORED) strct(str,p);
p = gif_alt[gif_flag];
if( p )
if( *p ) (IGNORED) strct(str,p);
p = gif_class[gif_flag];
if( p )
if( *p ) (IGNORED) strct(str,p);
p = gif_size[gif_flag];
if( p )
if( *p ) (IGNORED) strct(str,p);
p = gif_mag[gif_flag];
if( p )
if( *p ) (IGNORED) strct(str,p);
p = gif_ord[gif_flag];
if( p )
if( *p ) (IGNORED) strct(str,p);
p = gif_end[gif_flag];
if( p )
if( *p ) (IGNORED) strct(str,p);
p = str;
while( *p ){
if( *p == ’\n’ ) *p = ’ ’;
p++;
}
(IGNORED) fprintf(log_file, class_fmt,
gif_flag,
gif_id[gif_flag]? gif_id[gif_flag] : "",
str);
}
-_-_-
For some reason, bordlan cc+ complains if the ‘p = gif_open[gif_flag]’ are placed within the if’s.
‘configuration for class %d’ below stands for ‘\\special{t4ht;|%d...}’
<..img char without template..>
(IGNORED) sprintf(str,
"configuration for htf class %d (char %d of %s.htf)",
gif_flag, ch,font_tbl[cur_fnt].name
);
warn_i_str(50,str);
-_-_-
<..img char without template..>+
gif_open[gif_flag] = m_alloc(char,
<.1 + strlen((char *) <IMG SRC="+"ALT="+++++">+).>);
(IGNORED) strcpy((char *) gif_open[gif_flag],
<.<IMG SRC="+"ALT="+++++">+.>);
gif_alt[gif_flag] = gif_open[gif_flag]+11;
*(gif_alt[gif_flag] - 1) = ’\0’;
gif_class[gif_flag] = gif_open[gif_flag]+19;
*(gif_class[gif_flag] - 1) = ’\0’;
gif_size[gif_flag] = gif_open[gif_flag]+20;
*(gif_size[gif_flag] - 1) = ’\0’;
gif_mag[gif_flag] = gif_open[gif_flag]+21;
*(gif_mag[gif_flag] - 1) = ’\0’;
gif_ord[gif_flag] = gif_open[gif_flag]+22;
*(gif_ord[gif_flag] - 1) = ’\0’;
gif_end[gif_flag] = gif_open[gif_flag]+23;
*(gif_end[gif_flag] - 1) = ’\0’;
gif_id[gif_flag] = gif_open[gif_flag]+28;
*(gif_id[gif_flag] - 1) = ’\0’;
-_-_-
<..<IMG SRC="+"ALT="+++++">+..>
"<img src=\"+\" alt=\"+++++\" />+"
-_-_-
<..1 + strlen((char *) <IMG SRC="+"ALT="+++++">+)..>
29
-_-_-
What is the difference between the following two cases?
<..insert standard char..>
if( !gif_flag || (gif_flag % 2) || ch_map_flag ) { put_char(chr);
} else{ <.put char(chr).> }
-_-_-
If ‘gif_flag % 2’ is the case we have a picture which we want to insert for it just the string part. (The !gif˙flag is for text with pattermn 0?)
<..insert string char..>
if( !gif_flag || (gif_flag % 2) || ch_map_flag ) {
put_alt_ch(chr,ch_str_flag); }
else{ <.put string-char(chr).> }
-_-_-
Font information, e.g., for style files.
<..h-defines..>+
#ifndef LGCLS
#define LGCLS "Font_Class(%d,\"%s\"): %s\n"
#endif
-_-_-
<..vars..>+
static U_CHAR *class_fmt = NULL;
-_-_-
<..get from tex4ht.env file..>+
class_fmt = (char *) get_script(class_fmt,LGCLS,’c’);
-_-_-
Symbol i from base font x gets into file ‘x-i.gif’, and from c-magnified font goes into ‘x-c-i.gif’. In old LaTeX, ‘\documentstyle[...12p..]{..}’ gives a based-10 font magnified into 12.
<..defines..>+
#define GIF_I "-%x%s"
#define GIF_II "-%x-%x%s"
#define GIF_VII "%s"
-_-_-
<..h-defines 2..>
#ifdef DOS
#define HTM
#endif
-_-_-
<..defines..>+
#ifdef HTM
#define DOS_GIF_FILE
#endif
-_-_-
<..insert gif symbol to html file..>
if( !dos_file_names ){
print_f(font_tbl[cur_fnt].name);
if( mag == 10 ) (IGNORED) sprintf(str, GIF_I, design_ch, gif);
else (IGNORED) sprintf(str, GIF_II, mag, design_ch, gif);
}
-_-_-
<..insert gif symbol to lg file..>
if( !dos_file_names ){
if( mag == 10 ) (IGNORED) sprintf(str, "%s-%x%s",
font_tbl[cur_fnt].name, ch, gif);
else (IGNORED) sprintf(str, "%s-%x-%x%s",
font_tbl[cur_fnt].name, mag, ch, gif);
}
-_-_-
Transform long file names to 8 characters.
<..insert gif symbol to html file..>+
#ifdef DOS_GIF_FILE
if( dos_file_names ){
dos_gif_file(str, mag, design_ch);
print_f(str);
(IGNORED) sprintf(str, GIF_VII, gif);
}
#endif
-_-_-
<..insert gif symbol to lg file..>+
#ifdef DOS_GIF_FILE
if( dos_file_names ){
(IGNORED) strcpy((char *) str, (char *) font_tbl[cur_fnt].name);
dos_gif_file(str, mag, ch);
strct(str,gif);
}
#endif
-_-_-
The following writes into the ‘.lg’ file. The ‘templt’ ends with a percent (%\0). The algorithm collects the characters until a % is encountered. Then it prints out the segment of characters accumulated, and goes to process whatever follows the ‘%’.
<..header functions..>+
static void script( ARG_IV(char *, U_CHAR *, int, U_CHAR *) );
-_-_-
<..functions..>+
static void script(templt, job, page, font)
U_CHAR *templt;
U_CHAR *job;
int page;
U_CHAR *font
;{ U_CHAR *ch, *p;
U_CHAR fmt[256];
job[ (int) strlen((char *) job) - 1 ] =’\0’;
p = ch = templt;
while( TRUE ){
if( *ch == ’%’ ){
<.print segment of templet.>
<.get format of output.>
switch( *(++ch) ){
case ’1’:{ *p = ’s’;
(IGNORED) fprintf(log_file, fmt, job); break;}
case ’2’:{ *p = ’d’;
(IGNORED) fprintf(log_file, fmt, page); break;}
case ’3’:{ *p = ’s’;
(IGNORED) fprintf(log_file, fmt, font); break;}
case ’%’:{ *p = ’c’;
(IGNORED) fprintf(log_file, fmt, ’%’); break;}
default:{ job[ (int) strlen((char *) job) ] =’.’; return;}
}
p = ++ch;
}else ch++;
} }
-_-_-
<..print segment of templet..>
*ch = ’\0’; (IGNORED) fprintf(log_file, "%s", p);
*(ch++) = ’%’;
-_-_-
The jobname var contains a period at the end, removed temporarily for the script. The default case above should have been an error, or at least a warning.
<..get format of output..>
p=fmt; *(p++) = ’%’;
if( *ch == ’\0’ ){ job[ (int) strlen((char *) job) ] =’.’; return; }
while( *ch != ’%’ ){ *(p++) = *(ch ++); }
*(p+1) = ’\0’;
-_-_-
<..h-defines..>+
#ifndef LGPIC
#define LGPIC "--- needs --- %%1.idv[%%2] ==> %%3 ---\n%"
#endif
-_-_-
<..vars..>+
static U_CHAR *font_gif = NULL;
-_-_-
<..get gif script from com ln..>
font_gif = p+2;
-_-_-
<..get from tex4ht.env file..>+
font_gif = (char *) get_script(font_gif,LGPIC,’s’);
<.inser percent-ch at end of s-script.>
-_-_-
<..inser percent-ch at end of s-script..>
{ int n;
n = (int) strlen((char *) font_gif);
if( font_gif[n-1] != ’%’ ){ font_gif[n] = ’%’; font_gif[n+1] = ’\0’; }
}
-_-_-
Separates general picturs from symbols.
<..h-defines..>+
#ifndef LGSEP
#define LGSEP "--- characters ---\n"
#endif
-_-_-
<..vars..>+
static U_CHAR *begin_char_gif = NULL;
-_-_-
<..get start char-gif from com ln..>
begin_char_gif = p+2;
-_-_-
<..get from tex4ht.env file..>+
begin_char_gif = (char *) get_script(begin_char_gif,LGSEP,’b’);
-_-_-
<..h-defines..>+
#ifndef LGTYP
#define LGTYP ".png"
#endif
-_-_-
<..vars..>+
static U_CHAR *gif = NULL;
-_-_-
<..get gif-type from com ln..>
gif = p+2;
-_-_-
In the extension name we don’t want the line break at the end.
<..get from tex4ht.env file..>+
gif = (char *) get_script(gif,LGTYP,’g’);
{ int n;
n = (int) strlen((char *) gif) - 1;
if( gif[n] == ’%’ ){ gif[n] = ’%’; }
else if( gif[n] == ’\n’ ) { gif[n] = ’\0’; }
}
-_-_-
We set font name + mag (2 chars) + ch number (2 ch). If the length is no greater than 8, we are done. Otherwise, we take the first n-2 characters and map them to a string of length 4. They are the most stable in the names, so they minimize replacements.
<..header functions..>+
#ifdef DOS_GIF_FILE
static void dos_gif_file( ARG_III(char *, int, int) );
#endif
-_-_-
<..functions..>+
#ifdef DOS_GIF_FILE
static void dos_gif_file(str, mag, design_ch)
U_CHAR *str;
int mag;
int design_ch
;{ int n, m, i;
struct gif_file_rec * p, * q;
U_CHAR *ch;
m = n = (int) strlen((char *) str);
if( n > 4 ){
<.p = prefix of font file.>
if( p == NULL ){ <.p = new prefix font file.> }
gif_file = p;
for( n=0; n<4; n++ ) str[n] = xeh[(int)(*(p->code + n))];
}
str[n++] = xeh[mag<16? 0: mag / 16];
str[n++] = xeh[mag % 16];
str[n++] = xeh[design_ch<16? 0: design_ch / 16];
str[n++] = xeh[design_ch % 16];
str[n] = ’\0’;
}
#endif
-_-_-
We keep collisions table to ensure agains collisions. We do it in circular linked list so that last visited in previous turn will be the first to be visited now. The prefix, and its suggested
<..types..>+
#ifdef DOS_GIF_FILE
struct gif_file_rec{
U_CHAR code[4];
U_CHAR *name;
struct gif_file_rec *next; };
#endif
-_-_-
<..vars..>+
#ifdef DOS_GIF_FILE
static struct gif_file_rec * gif_file = (struct gif_file_rec *) 0;
#endif
-_-_-
<..p = prefix of font file..>
if( (p = gif_file) != NULL ){
while( TRUE ){
if( eq_str( str, p->name ) ) break;
if( (p = p->next) == gif_file ){ p = NULL; break; }
} }
-_-_-
<..p = new prefix font file..>
p = m_alloc(struct gif_file_rec, 1);
<.get tentative prefix replacement.>
<.adjust prefix replacement.>
(IGNORED) printf("\nRenaming ‘%s____%s’ to ‘%c%c%c%c____%s’\n",
str, gif,
xeh[(int)(ch[0])], xeh[(int)(ch[1])],
xeh[(int)(ch[2])], xeh[(int)(ch[3])]
, gif);
p->name = m_alloc(char,m+1);
(IGNORED) strcpy((char *) p->name, (char *) str );
if( gif_file ){ p->next = gif_file->next; gif_file->next = p; }
else p->next = p;
-_-_-
We choose the scheme ‘sum(char codes of str) / 4’ to find a number i, and then we cycle around hex in jumps of i to choose four characters not starting with digit.
<..get tentative prefix replacement..>
for(i=str[n]; n; ){ i+=str[--n]; if( i > (INT_MAX / 8) ) i/=2; }
if( (n=i % BASE) <10 ) n+= 10 + i%(BASE-20);
*(ch = p->code)= n; n += i;
ch[1] = n%BASE; n += i;
ch[2] = n%BASE; n += i;
ch[3] = n%BASE;
-_-_-
To allow for adjustments, we srtoe indexes of xeh, and not the characters themselve. We allow BASE3 options of adjustments!!!
<..adjust prefix replacement..>
if( gif_file ){
q = gif_file->next;
while( TRUE ){
if( (*(q->code) == *ch) && (*(q->code+1) == ch[1]) &&
(*(q->code) == ch[2]) && (*(q->code+2) == ch[3]) ){
ch[3] ++; ch[2] += ch[3]/ BASE; ch[3] = ch[3] % BASE;
ch[1] += ch[2]/ BASE; ch[2] = ch[2] % BASE;
ch[1] = ch[1] % BASE;
q = gif_file;
} else if( q == gif_file ) break;
q = q->next;
} }
-_-_-
Instead of hex we take xeh.
<..defines..>+
#define BASE 36
-_-_-
<..vars..>+
#ifdef DOS_GIF_FILE
static U_CHAR xeh[]="0123456789abcdefghijklmnopqrstuvxyz";
#endif
-_-_-
‘<<’ is NOT a safe operation, beyond char size, for transporting across platforms.
<..defines..>+
#define store_bit_I(ch,i) ch[(i)/8]|=(1<<((i)%8));
#define store_bit_Z(ch,i) ch[(i)/8]&=~(1<<((i)%8))
#define add_bit(ch,i,b) ch[(i)/8] |= ((b) << ((i)%8))
#define get_bit(ch,i) ((ch[(i)/8] >> ((i)%8)) & 1)
-_-_-
<..header functions..>+
static void put_alt_ch( ARG_II( int, BOOL) );
-_-_-
<..functions..>+
static void put_alt_ch(chr,ch_str_flag)
int chr;
BOOL ch_str_flag
;{
if( !ch_str_flag ) put_char( chr );
else if( chr > 0 ){ <.put htf char string.> }
}
-_-_-
The ‘gif_ch’ is true when we put the character outside of ‘\special{t4ht|}...\special{t4ht|}’, and is false inside that range. Within that range, used in ALT’s, we want to eliminate the html comamnds ‘<...>’ and the delimiter characters ‘"’.
<..put htf char string..>
unsigned U_CHAR * p;
p = font_tbl[cur_fnt].str[chr-1];
if( gif_ch ) print_f( (char *) p ); /*new*/
else while( *p ){
switch( *p ){
case ’<’: { while( *p && (*p != ’>’) ) p++; break; }
case ’>’:
case ’"’: { p++; break; }
case ’\’’: { p++; break; }
default: { put_char( (int) *p ) ; p++; }
} }
-_-_-
<..vars..>+
static BOOL gif_ch = TRUE;
static int design_ch = 0;
-_-_-
‘\Configure{characters}{<SPAN\:newlnch NAME="}{">}{</SPAN>} {<IMG SRC="}{"ALT="}{"NAME="}{">}’
<..css for characters..>
int n, code;
U_CHAR *p, *q;
code = get_char();
n = 1 + ((--special_n>254)? 254 : special_n);
q = p = m_alloc(char, (int) n);
while( special_n > 254 ){ (void) get_char(); special_n--; }
while( special_n-- ) { *(q++) = get_char(); }
*q = ’\0’; q = p;
switch ( code ){
case ’8’: { pause_style--; break; }
case ’9’: { pause_style++; break; }
case ’-’: { default_font = font_tbl[cur_fnt].num;
base_font_size = font_tbl[cur_fnt].scale / 100;
break; }
case ’+’: { default_font = -1; break; }
case ’%’: { <.insert font size.> break; }
case ’=’: { <.insert css name of ch.> break; }
case ’|’: { <.record string for htf class.> break; }
case ’,’: { <.don’t report next htf class to lg.> break; }
default: { warn_i_int( 36, code); }
}
span_on = span_name_on && !pause_style;
if( q ) free((void *) q);
-_-_-
Since htf fonts are shred within tex fonts, and since they can easily be modified by scripts in the output html files, changes of their classes from within the 4ht files is not supported.
By taking integer for ‘pause_style’ we allow for nested pausing of fonts.
<..vars..>+
static int pause_style = 0, default_font = -1, base_font_size=6533;
static BOOL
span_name_on = FALSE,
span_on = FALSE;
-_-_-
<..record img-srcOUT..>
q = img_src; img_src = p;
-_-_-
<..varsOUT..>
static U_CHAR * img_src;
-_-_-
<..main’s initOUT..>
img_src = m_alloc(char, (int) 12);
(IGNORED) strcpy((char *) img_src, "<img \nsrc=\"" );
-_-_-
<..<IMG SRC=".....>
p= gif_open[gif_flag];
if( p )
if( *p ){
print_f(p); (IGNORED) strcpy((char *) str, (char *) font_tbl[cur_fnt].name);
mag = (int) ((double) font_tbl[cur_fnt].scale /
font_tbl[cur_fnt].design_sz * 10 );
<.insert gif symbol to html file.>
print_f(str);
add_bit( font_tbl[cur_fnt].gif_on, r_ch, 1 );
}
-_-_-
<..record img-altOUT..>
q = img_alt; img_alt = p;
-_-_-
<..varsOUT..>+
static U_CHAR * img_alt;
-_-_-
<..main’s initOUT..>+
img_alt = m_alloc(char, (int) 7);
(IGNORED) strcpy((char *) img_alt, "\"alt=\"" );
-_-_-
<....."ALT=".....>
p = gif_alt[gif_flag];
if( p )
if( *p ){
print_f(p); put_alt_ch(chr,ch_str_flag);
}
-_-_-
<....."CLASS="family.....>
p = gif_class[gif_flag];
if( p )
if( *p ){
(IGNORED) fprintf(cur_o_file, p,
font_tbl[cur_fnt].family_name); }
-_-_-
<.....gif font size.....>
p = gif_size[gif_flag];
if( p )
if( *p ){
(IGNORED) fprintf(cur_o_file, p,
font_tbl[cur_fnt].font_size); }
-_-_-
<.....gif font mag.....>
p = gif_mag[gif_flag];
if( p )
if( *p && (font_tbl[cur_fnt].mag != 100) ){
(IGNORED) fprintf(cur_o_file, p, font_tbl[cur_fnt].mag);
}
-_-_-
<.....gif sym ord.....>
p = gif_ord[gif_flag];
if( p )
if( *p ){
(IGNORED) fprintf(cur_o_file, p, ch);
}
-_-_-
<....."/IMG>..>
p = gif_end[gif_flag];
if( p )
if( *p ){ print_f( p ); }
-_-_-
<..record string for htf class..>
{ int bad_str, m;
U_CHAR ch, *t[<.n spans.>], err_str[256];
bad_str=<.n spans-1.>; (IGNORED) strcpy((char *) err_str, (char *) p);
if( n><.n spans+2.> ){
m = 100*( *p-’0’ ) + 10*( *(p+1)-’0’ )+ *(p+2)-’0’;
if( (m>-1) && (m<256) ){
ch = *(p + 3); t[0]=p;
while( (*p = *(p+4)) != ’\0’ ){
if( ch == *p ){ *p = ’\0’;
if( bad_str-- > 0 ) t[<.n spans-1.> - bad_str] = p+1;
}
p++;
} }
if( !bad_str ){
if( m==0 ){ span_name_on = n><.n spans+3.>; }
q = span_open[m]; span_open[m] = t[0];
span_name[m] = t[1]; span_size[m] = t[2];
span_mag[m] = t[3]; span_ord[m] = t[4];
span_ch[m] = t[5]; end_span[m] = t[6];
gif_id[m] = t[7];
if( not_notify ) {
store_bit_I( class_on, m );
not_notify = FALSE;
} else store_bit_Z( class_on, m );
}
}
if( bad_str ){ warn_i_str(37,err_str); }
}
-_-_-
<..don’t report next htf class to lg..>
not_notify = TRUE;
-_-_-
<..vars..>+
static BOOL not_notify = FALSE;
-_-_-
<..vars..>+
static U_CHAR * span_name[256], * span_open[256], * span_size[256],
* span_mag[256], * span_ch[256], * end_span[256],
* span_ord[256], * gif_id[256];
static U_CHAR class_on[32];
-_-_-
<..main’s init..>+
{ int i; i=256; while( i-- ) {
span_name[i] = span_open[i] = span_size[i] =
span_mag[i] = span_ch[i] = end_span[i] =
span_ord[i] = gif_id[i] = NULL;
if( (i>0) && !(i%2) ) { store_bit_Z( class_on, i ); }
else { store_bit_I( class_on, i ); }
}
}
-_-_-
<..defines..>+
#define gif_open span_open
#define gif_alt span_name
#define gif_class span_size
#define gif_size span_mag
#define gif_mag span_ord
#define gif_ord span_ch
#define gif_end end_span
-_-_-
‘0’: character without decoration; ‘1’ gif without decoration. Even numbers (‘...0’) are reserved for ch with decoration, and odd numbers (‘...1’) are for gifs with decoration.
A character template takes the form: +open + family-format + size-format + mag-format + ord + close +after-font-info; The delimiter can be +, or any other character.
<..put char(chr)..>
<.open output file.>
<.ensure for chr.>
if( span_on ){
<.open for chr.>
<.font-family of chr.>
<.font-size of chr.>
<.font-mag of chr.>
<.ord of chr.>
<.close for chr.>
}
put_char(chr);
if( span_on ){
<.end for chr.>
}
-_-_-
<..put string-char(chr)..>
<.ensure for chr.>
if( span_on ){
<.open for chr.>
<.font-family of chr.>
<.font-size of chr.>
<.font-mag of chr.>
<.ord of chr.>
<.close for chr.>
}
put_alt_ch(chr,ch_str_flag);
if( span_on ){
<.end for chr.>
}
-_-_-
<..ensure for chr..>
if( gif_flag && !get_bit( class_on, gif_flag ) ) {
notify_class_info(gif_flag);
store_bit_I( class_on, gif_flag );
}
-_-_-
<..open for chr..>
if( span_open[gif_flag] )
if( *span_open[gif_flag] ){
print_f( span_open[gif_flag] );
}
-_-_-
<..end for chr..>
if( end_span[gif_flag] )
if( *end_span[gif_flag] ){
print_f( end_span[gif_flag] );
}
-_-_-
<..close for chr..>
if( span_ch[gif_flag] )
if( *span_ch[gif_flag] ){
print_f( span_ch[gif_flag] );
}
-_-_-
<..font-family of chr..>
if( span_name[gif_flag] )
if( *span_name[gif_flag] ){
(IGNORED) fprintf(cur_o_file, span_name[gif_flag],
font_tbl[cur_fnt].family_name);
}
-_-_-
<..font-size of chr..>
if( span_size[gif_flag] )
if( *span_size[gif_flag] ){
(IGNORED) fprintf(cur_o_file, span_size[gif_flag],
font_tbl[cur_fnt].font_size);
}
-_-_-
<..font-mag of chr..>
if( span_mag[gif_flag] )
if( *span_mag[gif_flag] ){
(IGNORED) fprintf(cur_o_file, span_mag[gif_flag],
font_tbl[cur_fnt].mag);
}
-_-_-
<..ord of chr..>
if( span_ord[gif_flag] )
if( *span_ord[gif_flag] ){
(IGNORED) fprintf(cur_o_file, span_ord[gif_flag], chr);
}
-_-_-
<..insert font size..>
int f;
f = 0; while( *p ){ f = 10*f + *(p++) - ’0’; }
<.open output file.>
(IGNORED) fprintf(cur_o_file, "%d",
(font_tbl[cur_fnt].scale / base_font_size - 100) * f / 100 +100
);
-_-_-
<..insert css name of ch..>
<.open output file.>
(IGNORED) fprintf(cur_o_file, "%s", font_tbl[cur_fnt].name);
if( font_tbl[cur_fnt].mag != 100 ){
(IGNORED) fprintf(cur_o_file,"_%d", font_tbl[cur_fnt].mag);
}
-_-_-