Chapter 7
Tables

   7.1 The Options
   7.2 Info for Entries
      Inilialization of Base
      Modifications to Base
      Initializations for Groups
      Modifications for Groups at Requests
      Release at Starts of Groups
      Release at Ends of Groups

7.1 The Options

In TeX, we initiate tables of the form

\haligh{ 
  ... & ... & ... \cr 
  ... & ... & ... \cr 
} 

Such tables translate to dvi tables of the form

<group> 
    <group> ... </group> 
    <group> ... </group> 
    <group> ... </group> 
</group> 
 
<group> 
    <group> ... </group> 
    <group> ... </group> 
    <group> ... </group> 
</group> 

The option ‘@’ asks to start puting the entries over the following groups.

Two problems arise:

  1. Unless the tables are followed by external end-groups, we don’t have any mark telling where they end. The ‘/’ special can be used in the sources to identify the ends.

  2. The ‘\nohalign’ commands provide dirty entries between the rows.

<..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.> }
 }
 -_-_-

7.2 Info for Entries

Inilialization of Base

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;
   }
 }
 -_-_-

Modifications to Base

<..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;
 -_-_-

Initializations for Groups

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;
 -_-_-

Modifications for Groups at Requests

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;
 -_-_-

Release at Starts of Groups

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 );
      }
 }  }
 -_-_-

Release at Ends of Groups

<..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 );
 } }
 -_-_-