In TeX, we initiate tables of the form
Such tables translate to dvi tables of the form
The option ‘@’ asks to start puting the entries over the following groups.
Two problems arise:
<..halign specials..>
int i;
i = 0;
special_n--;
switch ( get_char() ){
case ’8’: { i++; }
case ’7’: { i++; }
case ’6’: { i++; }
case ’5’: { i++; }
case ’4’: { i++; }
case ’3’: { i++; }
case ’2’: { i++; }
case ’1’: { <.new halign setting.> break; }
case ’/’: { if( special_n ){
<.consume unused specials.>
} else { <.output end halign table.> }
break;
}
case ’&’: { i++; }
case ’@’: { i++;
if( special_n ){
<.consume unused specials.>
} else {
<.start halign table.>
}
break;
}
default: { <.consume unused specials.> }
}
-_-_-
The base entries are stored in a set of global variables ‘str[i]’, and the number of usages is stored in ‘refs[i]’. The strings can be used from the global shared base or the local groups.
<..vars..>+
static struct halign_rec *halign[8];
-_-_-
<..defines..>+
struct halign_rec{
char * str;
int refs;
};
-_-_-
<..main’s init..>+
{ int i;
for( i=8; i--; ){
halign[i] = m_alloc(struct halign_rec, 1);
halign[i]->str = m_alloc(char, 1);
*(halign[i]->str) = ’\0’;
halign[i]->refs = 1;
}
}
-_-_-
<..new halign setting..>
if( halign[i]->refs == 1 ){
free((void *) halign[i]->str );
} else {
(halign[i]->refs)--;
halign[i] = m_alloc(struct halign_rec, 1);
halign[i]->refs = 1;
}
halign[i]->str = get_str( (int) special_n );
special_n=0;
-_-_-
Each group level has its local set of variables. Whenever a request ‘@’ or ‘&’arrives, we verify that the the local entries equal to the current global entries. If not, the local entries are replaced with copies of the current ones.
<..struct stack_entry..>
struct halign_rec *halign[8];
BOOL halign_on, halign_info, row_no, col_no;
-_-_-
<..initialized entries for grouping stack..>
stack[i].halign_info = FALSE;
stack[i].halign_on = FALSE;
-_-_-
Upon requesting an insertion for \halign, through \special{t4ht*@} or \special{t4ht*&}, we modify the entries on the current group.
<..start halign table..>
new_halign = i * TRUE;
-_-_-
<..vars..>+
static BOOL new_halign = FALSE;
-_-_-
<..insert start of halign..>
stack[stack_n].halign_on = new_halign;
if( stack[stack_n].halign_info )
{ int j;
for( j=8; j--; ){
if( stack[stack_n].halign[j] != halign[j] ){
if( ! (--(stack[stack_n].halign[j]->refs) ) ){
free((void *) stack[stack_n].halign[j]->str );
free((void *) stack[stack_n].halign[j] );
}
stack[stack_n].halign[j] = halign[j];
(halign[j]->refs)++;
}
}
} else { int j;
stack[stack_n].halign_info = TRUE;
for( j=8; j--; ){
stack[stack_n].halign[j] = halign[j];
(halign[j]->refs)++;
} }
print_f( stack[stack_n].halign[0]->str );
stack[stack_n].row_no = 0;
new_halign = FALSE;
-_-_-
The following are for introducing tabular tags for containing rows and cols of tables. They are encounter before stack_n changes its value.
<..halign at entry to group..>
if( new_halign ){
<.insert start of halign.>
}
if( stack[stack_n].halign_on )
{
print_f( stack[stack_n].halign[2]->str );
if( stack[stack_n].halign_on > TRUE ){
stack[stack_n].row_no++;
stack[stack_n].col_no = 0;
(IGNORED) fprintf(cur_o_file, "%d%s",
stack[stack_n].row_no, stack[stack_n].halign[6]->str );
} }
if( stack_n ){
if( stack[stack_n-1].halign_on )
{
print_f( stack[stack_n-1].halign[4]->str );
if( stack[stack_n-1].halign_on > TRUE ){
stack[stack_n-1].col_no ++;
(IGNORED) fprintf(cur_o_file, "%d%s",
stack[stack_n-1].col_no, stack[stack_n-1].halign[7]->str );
}
} }
-_-_-
<..halign at exit from group..>
<.output end halign table.>
<.output end halign row.>
<.output end halign col.>
if( stack[stack_n].halign_info )
{ int j;
for( j=8; j--; ){
if( ! (--(stack[stack_n].halign[j]->refs) ) ){
free((void *) stack[stack_n].halign[j]->str );
free((void *) stack[stack_n].halign[j] );
} }
stack[stack_n].halign_info = FALSE;
}
-_-_-
The ouput for end of table is for the current level of table, for end of row is an immediately containig tables, and for a col is for second generation containing table.
<..auto quit halign..>
if( stack[stack_n].halign_on )
{
switch( ch ){
case <.mv ver 1-byte.>: { ; }
case <.mv ver 2-byte.>: { ; }
case <.mv ver 3-byte.>: { ; }
case <.mv ver 4-byte.>: { ; }
case <.mv ver dist dy.1.>: { ; }
case <.dy.1 store and mv ver 1-byte.>: { ; }
case <.dy.1 store and mv ver 2-byte.>: { ; }
case <.dy.1 store and mv ver 3-byte.>: { ; }
case <.dy.1 store and mv ver 4-byte.>: { ; }
case <.mv ver dist dy.2.>: { ; }
case <.dy.2 store and mv ver 1-byte.>: { ; }
case <.dy.2 store and mv ver 2-byte.>: { ; }
case <.dy.2 store and mv ver 3-byte.>: { ; }
case <.dy.2 store and mv ver 4-byte.>: { ; }
case <.insert rule + move op.>: { ; }
case <.insert rule + nomove op.>: { ; }
case <.font 1-byte.>: { ; }
case <.font 2-bytes.>: { ; }
case <.font 3-bytes.>: { ; }
case <.font int.>: { ; }
case <.sv loc op.>:
{ break; }
default: { <.print end of halign table.> }
} }
-_-_-
<..output end halign table..>
if( stack[stack_n].halign_on )
{ <.print end of halign table.> }
-_-_-
<..print end of halign table..>
print_f( stack[stack_n].halign[1]->str );
stack[stack_n].halign_on = FALSE;
-_-_-
<..output end halign row..>
if( stack_n ){
if( stack[stack_n-1].halign_on )
{
print_f( stack[stack_n-1].halign[3]->str );
} }
-_-_-
<..output end halign col..>
if( stack_n-1 ){
if( stack[stack_n-2].halign_on )
{
print_f( stack[stack_n-2].halign[5]->str );
} }
-_-_-