Tex assignes class numbers 0–7 to the atoms of math formulas: 0–ordinary symbol, 1–large operator, 2–binary operation, 3–relational operation, 4–math delimiter, 5–right delimiter, 6–punctuation mark, and 7–adjustable. We use classes 7, 8, 9 as extra free ones.
‘{\everypar{}\special{t4ht^i}$sym... i=0, 1, 2, 3, 4,..., a, b, ...., ~ $\special{t4ht^}}’
A right delimiter immediately after a math openimiter ammuses a matching pair.
<..classes for math symbols..>
switch( special_n ){
case 0:{ if( math_class_on ){
open_del = 256; pause_class = ignore_subclass_del = 0;
math_class_on = FALSE; <.recall intrusive flags.>
} else { show_class = !show_class; }
break;
}
case 1:{ <.save intrusive flags.>
special_n--;
if( (math_class = scan_class(1)) == <.num of math classes: 79.> )
{ math_class = 0; }
else math_class_on = TRUE;
break;
}
case 2:{ <.class delimiters on group.>
break; }
default:{ <.set config class dels.> }
}
-_-_-
<..vars..>+
static BOOL math_class_on = FALSE, show_class = FALSE;
static int open_del = 256, math_class, pause_class, ignore_subclass_del;
-_-_-
‘open_del’ is used by close delimiter, if they are immediate neighbors.
<..vars..>+
static int sv_group_dvi, sv_trace_dvi_C, sv_in_trace_char, sv_span_on,
sv_in_span_ch;
-_-_-
<..save intrusive flags..>
sv_group_dvi = group_dvi;
sv_trace_dvi_C = trace_dvi_C;
sv_in_trace_char = in_trace_char;
sv_span_on = span_on;
sv_in_span_ch = in_span_ch;
-_-_-
<..recall intrusive flags..>
group_dvi = sv_group_dvi;
trace_dvi_C = sv_trace_dvi_C;
in_trace_char = sv_in_trace_char;
span_on = sv_span_on;
in_span_ch = sv_in_span_ch;
-_-_-
<..header functions..>+
static int scan_class( ARG_I(int) );
-_-_-
<..functions..>+
static int scan_class( flag )
int flag
;{ int math_class;
math_class = get_char();
if( (math_class >= ’0’ )
&& (math_class < ’0’ + <.num of math classes: 79.>) ){
{ math_class -= ’0’; }
} else {
if( flag== 1 ) {
switch( math_class ){
case ’-’: { math_class = <.num of math classes: 79.>;
pause_class++; break; }
case ’+’: { math_class = <.num of math classes: 79.>;
pause_class--; break; }
default: { math_class = 0; }
} } else if( flag== 2 ) {
switch( math_class ){
case <.ignore sub dels ch.>: {
math_class = <.ignore sub dels val.>; break; }
case <.end ignore sub dels ch.>:
{ math_class = <.end ignore sub dels val.>; break; }
default: { math_class = 0; }
}
} else { math_class = 0; }
}
return math_class;
}
-_-_-
<..header functions..>+
static INTEGER set_ch_class( ARG_I(int) );
-_-_-
<..functions..>+
static INTEGER set_ch_class(ch) int ch
;{ int r_ch;
r_ch = ch - font_tbl[cur_fnt].char_f;
if( math_class == <.math close.> ){
store_bit_I( font_tbl[cur_fnt].math_closing, r_ch );
*(font_tbl[cur_fnt].math + r_ch) =
(char) ((open_del == 256)? ch : open_del);
} else {
store_bit_Z( font_tbl[cur_fnt].math_closing, r_ch );
*(font_tbl[cur_fnt].math + r_ch) = math_class;
}
open_del = ( math_class == <.math open.> )? ch : 256;
<.return char width.>
}
-_-_-
<..set-ch-class(ch-1)..>
set_ch_class(ch_1)
-_-_-
<..set config class dels..>
{ U_CHAR str[256], *p, ch, **q;
math_class = scan_class(2); ch = get_char();
special_n -= 2; p = str;
while( special_n-- > 0 ){
if( (*(p++) = get_char()) == ch ){ p--; break; }
}
*p = ’\0’;
q = (math_class > <.math classes 0..78.>)? &(<.push class del := ....>)
: &(open_class[math_class]);
*q = (char *) r_alloc((void *) open_class[math_class],
1 + (size_t) strlen((char *) str));
(IGNORED) strcpy((char *) *q, (char *) str);
q = (math_class > <.math classes 0..78.>) ? &(<.pop class del := ....>)
: &(close_class[math_class]);
p = *q = (char *) r_alloc((void *) *q, 1 + (size_t) special_n);
while( special_n-- > 0 ){ *(p++) = get_char(); }
*p = ’\0’;
if( math_class > <.math classes 0..78.>){ <.next delimiters on group.> }
}
-_-_-
When ‘math_class > max math class’ is true, the delimiters are placed on the next group. In such a case a math class of ‘)’ also requests that no subdelimiter will be placed there.
<..header functions..>+
static int math_class_of( ARG_II(int,int) );
-_-_-
<..functions..>+
static int math_class_of(ch,cur_fnt) int ch; int cur_fnt
;{ int math_class;
math_class = ch - font_tbl[cur_fnt].char_f;
return ((get_bit( font_tbl[cur_fnt].math_closing, math_class))?
<.math close.> : *( math_class + font_tbl[cur_fnt].math));
}
-_-_-
<..vars..>+
static U_CHAR *open_class[<.mems for math classes (79 + 2 ).>],
*close_class[<.mems for math classes (79 + 2 ).>];
-_-_-
There are 79 characters in the range between the digit ‘0’ and the character ‘~’.
<..math classes 0..78..>
78
-_-_-
<..num of math classes: 79..>
79
-_-_-
The following should be characters below the digit ‘0’
<..ignore sub dels ch..>
’)’
-_-_-
<..end ignore sub dels ch..>
’(’
-_-_-
<..ignore sub dels val..>
(<.num of math classes: 79.> + 1)
-_-_-
<..end ignore sub dels val..>
(<.num of math classes: 79.> + 2)
-_-_-
<..mems for math classes (79 + 2 )..>
82 one extra is needed?
-_-_-
<..main’s init..>+
for( math_class=0; math_class<<.num of math classes: 79.>; math_class++ ){
open_class[math_class] = m_alloc(char, 1);
close_class[math_class] = m_alloc(char, 1);
*(open_class[math_class]) = *(close_class[math_class]) = ’\0’;
}
-_-_-
<..entries for math classes..>
char *math, *math_closing;
-_-_-
<..memory for math classes..>
new_font.math_closing = m_alloc(char, n_gif_bytes );
new_font.math = m_alloc(char, n_gif );
-_-_-
<..init math-closing..>
new_font.math_closing[i] =
-_-_-
<..init math..>
new_font.math[i] =
-_-_-
<..merge math entries..>
free((void *) new_font.math_closing );
new_font.math_closing = font_tbl[ k ].math_closing;
free((void *) new_font.math );
new_font.math = font_tbl[ k ].math;
-_-_-
‘\special{t4ht^ix}’–put delimiters of class i on next group/token. If x=‘)’ ignore delimiters within the group.
<..class delimiters on group..>
special_n -= 2; math_class = scan_class(0);
stack[stack_n+1].ignore_subclass_del =
(<.ignore sub dels ch.> == get_char());
stack[stack_n+1].active_class_del = TRUE;
stack[stack_n+1].temp_class_del = FALSE;
stack[stack_n+1].no_left_del = TRUE;
stack[stack_n+1].class_open = open_class[math_class];
stack[stack_n+1].class_close = close_class[math_class];
-_-_-
‘\special{t4ht^)x*...*...}’–put the specified delimiters of class on next group, instead of the default ones. If x=‘)’, ignore delimiters within the group.
<..next delimiters on group..>
stack[stack_n+1].ignore_subclass_del =
(math_class == <.ignore sub dels val.>);
stack[stack_n+1].temp_class_del = TRUE;
stack[stack_n+1].active_class_del = TRUE;
-_-_-
<..pop class del := .....>
stack[stack_n+1].temp_class_close
-_-_-
<..push class del := .....>
stack[stack_n+1].temp_class_open
-_-_-
<..add push class del..>
if( stack[stack_n].active_class_del ){
if( show_class && !pause_class && !ignore_subclass_del ){
<.print open del of group class.>
}
ignore_subclass_del = ignore_subclass_del
+ stack[stack_n].ignore_subclass_del;
stack[stack_n+1].no_left_del= FALSE;
}
-_-_-
<..add pop class del..>
if( stack[stack_n].active_class_del ){
ignore_subclass_del = ignore_subclass_del
- stack[stack_n].ignore_subclass_del;
if( show_class && !pause_class && !ignore_subclass_del ){
<.print right del of group class.>
}
stack[stack_n].active_class_del = FALSE;
}
-_-_-
<..struct stack_entry..>+
char *class_open, *class_close,
*temp_class_open, *temp_class_close;
BOOL temp_class_del, ignore_subclass_del, active_class_del,
no_left_del, sv_no_left_del;
-_-_-
The math class can be on a group or a token. Upon reaching the \special, the no_left_del is set to false. Upon reaching to the start of the next group (not token), the flag is set to true.
<..initialized entries for grouping stack..>+
stack[i].class_open = stack[i].class_close
= (char *) 0;
stack[i].temp_class_open = m_alloc(char, 1 );
stack[i].temp_class_close = m_alloc(char, 1 );
stack[i].ignore_subclass_del = stack[i].temp_class_del
= stack[i].active_class_del
= FALSE;
-_-_-
<..left class delNO..>
if( show_class && !pause_class && !ignore_subclass_del){
if(stack[stack_n+1].no_left_del && stack[stack_n+1].active_class_del ){
<.open del of group class on ch.>
} else {
math_class = math_class_of( ch, cur_fnt );
(IGNORED) print_f( open_class[math_class]);
} }
-_-_-
<..left class del..>
if( show_class && !pause_class && !ignore_subclass_del){
if( !stack[stack_n].no_left_del && stack[stack_n+1].active_class_del ){
<.open del of group class on ch.>
if( !stack[stack_n+1].ignore_subclass_del ){
<.left del of class on ch.>
}
} else {
<.left del of class on ch.>
} }
-_-_-
<..left del of class on ch..>
math_class = math_class_of( ch, cur_fnt );
(IGNORED) print_f( open_class[math_class]);
-_-_-
The ‘stack[stack_n].no_left_del’ is true if we have a request for math delimiters on next group/token, and no left delimiter had been placed on a group.
<..right class delNO..>
if( show_class && !pause_class && !ignore_subclass_del ){
if(stack[stack_n+1].no_left_del && stack[stack_n+1].active_class_del ){
<.right del of group class on ch.>
stack[stack_n+1].active_class_del = FALSE;
} else {
(IGNORED) print_f( close_class[math_class]);
}
}
-_-_-
<..right class del..>
if( show_class && !pause_class && !ignore_subclass_del ){
if( !stack[stack_n].no_left_del && stack[stack_n+1].active_class_del ){
if( !stack[stack_n+1].ignore_subclass_del ){
<.right del of class on ch.>
}
<.right del of group class on ch.>
stack[stack_n+1].active_class_del = FALSE;
} else {
<.right del of class on ch.>
stack[stack_n+1].active_class_del = FALSE; %%%%%%%NEW%%%%
}
}
-_-_-
<..right del of class on ch..>
(IGNORED) print_f( close_class[math_class]);
-_-_-
<..print right del of group class..>
(IGNORED) print_f( (stack[stack_n].temp_class_del)?
stack[stack_n].temp_class_close
: stack[stack_n].class_close);
-_-_-
<..right del of group class on ch..>
(IGNORED) print_f( (stack[stack_n+1].temp_class_del)?
stack[stack_n+1].temp_class_close
: stack[stack_n+1].class_close);
-_-_-
<..print open del of group class..>
(IGNORED) print_f( (stack[stack_n].temp_class_del)?
stack[stack_n].temp_class_open
: stack[stack_n].class_open);
-_-_-
<..open del of group class on ch..>
(IGNORED) print_f( (stack[stack_n+1].temp_class_del)?
stack[stack_n+1].temp_class_open
: stack[stack_n+1].class_open);
-_-_-