Back to index

tetex-bin  3.0
char_routines.c
Go to the documentation of this file.
00001 /* char_routines.c: Data structures for character information
00002 
00003 This file is part of Omega,
00004 which is based on the web2c distribution of TeX,
00005 
00006 Copyright (c) 1994--2001 John Plaice and Yannis Haralambous
00007 
00008 Omega is free software; you can redistribute it and/or modify
00009 it under the terms of the GNU General Public License as published by
00010 the Free Software Foundation; either version 2 of the License, or
00011 (at your option) any later version.
00012 
00013 Omega is distributed in the hope that it will be useful,
00014 but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016 GNU General Public License for more details.
00017 
00018 You should have received a copy of the GNU General Public License
00019 along with Omega; if not, write to the Free Software Foundation, Inc.,
00020 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
00021 
00022 */
00023 
00024 #include "cpascal.h"
00025 #include "manifests.h"
00026 #include "list_routines.h"
00027 #include "char_routines.h"
00028 #include "print_routines.h"
00029 #include "out_routines.h"
00030 #include "error_routines.h"
00031 #include "ligkern_routines.h"
00032 #include "dimen_routines.h"
00033 #include "header_routines.h"
00034 #include "font_routines.h"
00035 #include "out_ofm.h"
00036 #include "omfonts.h"
00037 #include "dvi.h"
00038 
00039 #define PLANE        0x10000
00040 #define HALFPLANE    0x08000
00041 
00042 #define MAX_START_OFM       65535
00043 #define MAX_START_TFM       255
00044 
00045 /*
00046  * Characters can range from 0x0 to 0x7fffffff (31 bits unsigned),
00047  * which is a lot of characters.  We would expect characters to either
00048  * be bunched up in a given region, or else sparsely defined throughout
00049  * the range.  The data structure to hold them is an array of HALFPLANE
00050  * arrays, each of which holds a full PLANE (0x10000) of characters.
00051  *
00052  * At all times, init_character ensures that planes[0] to planes[plane_max]
00053  * are either NULL or allocated arrays of PLANE characters.
00054  *
00055  * For allocated array p, init_character also ensures that planes[p][0]
00056  * to planes[p][char_max[p]] are either NULL or pointers to allocated
00057  * char_entry values.
00058  *
00059  * init_character can be called when actually reading a CHARACTER definition
00060  * or when the character is referenced in a charlist cycle, an extensible
00061  * piece or in a ligature/kerning table.  In the latter case, ensure_existence
00062  * is called, and it sets the defined field of the character to be FALSE;
00063  * 
00064  * init_character also sets current_character to the character entry;
00065  * 
00066  */
00067 
00068 unsigned bc=0x7fffffff;
00069 unsigned ec=0x0;
00070 unsigned ne=0;
00071 
00072 char_entry **planes[HALFPLANE];
00073 unsigned char_max[HALFPLANE];
00074 unsigned plane_max = 0;
00075 
00076 char_entry *current_character = NULL;
00077 char_entry *current_secondary_character = NULL;
00078 
00079 queue exten_queue;
00080 four_pieces **exten_table = NULL;
00081 
00082 unsigned no_labels = 0;
00083 label_entry *label_table;
00084 int label_ptr, sort_ptr;
00085 int lk_offset;
00086 boolean extra_loc_needed;
00087 
00088 extern unsigned bchar;
00089 
00090 void
00091 init_planes(void)
00092 {
00093     plane_max = 0;
00094     planes[plane_max] = NULL;
00095     char_max[plane_max] = 0;
00096 }
00097 
00098 void
00099 init_character(unsigned c, char_entry *ready_made)
00100 {
00101     register unsigned i, index, plane;
00102 
00103     if ((c<CHAR_MINIMUM) || (c>CHAR_MAXIMUM)) {
00104         warning_1("CHARACTER index (H %X) not 31-bit unsigned integer; "
00105                   "ignored", c);
00106         current_character = NULL;
00107         return;
00108     }
00109     plane = c / PLANE;
00110     index = c % PLANE;
00111     for (i=plane_max+1; i<=plane; i++) {
00112            planes[plane] = NULL;
00113     }
00114     if (planes[plane]==NULL) {
00115         planes[plane] = (char_entry **)xmalloc(PLANE * sizeof(char_entry *));
00116         char_max[plane] = 0;
00117         planes[plane][0] = NULL;
00118     }
00119     for (i=char_max[plane]+1; i<=index; i++) {
00120         planes[plane][i] = NULL;
00121     }
00122     if (plane>plane_max)       plane_max = plane;
00123     if (index>char_max[plane]) char_max[plane] = index;
00124 
00125     if (planes[plane][index] != NULL) {
00126         if (planes[plane][index]->defined == FALSE) {
00127             current_character = planes[plane][index];
00128             current_character->defined = TRUE;
00129             return;
00130         }
00131         warning_1("CHARACTER index (H %X) previously defined; "
00132                   "old definition ignored", c);
00133         free(current_character);
00134         current_character = NULL;
00135     }
00136     if (ready_made != NULL) {
00137         current_character = ready_made;
00138         planes[plane][index] = current_character;
00139     } else {
00140         current_character = (char_entry *)xmalloc(sizeof(char_entry));
00141         planes[plane][index] = current_character;
00142         for (i=C_MIN; i<=C_MAX; i++) {
00143             current_character->indices[i] = NULL;
00144             current_character->index_indices[i] = 0;
00145         }
00146         current_character->c = c;
00147         current_character->copies = 0;
00148         current_character->remainder = 0;
00149         current_character->tag = TAG_NONE;
00150         current_character->defined = TRUE;
00151         current_character->accent = ACC_NONE;
00152         current_character->ovf_packet_length = 0;
00153         current_character->ovf_packet = NULL;
00154         cur_packet = NULL;
00155     }
00156 }
00157 
00158 void
00159 copy_characters(unsigned c, unsigned copies)
00160 {
00161     unsigned i=0;
00162     unsigned plane, index;
00163     char_entry *the_entry;
00164 
00165     if ((c<CHAR_MINIMUM) || (c>CHAR_MAXIMUM)) {
00166         warning_1("CHARACTER index (H %X) not 31-bit unsigned integer; "
00167                   "ignored", c);
00168         current_character = NULL;
00169         return;
00170     }
00171     plane = c / PLANE;
00172     index = c % PLANE;
00173     if (planes[plane]==NULL)
00174         internal_error_1("copy_characters (plane %d)", plane);
00175     the_entry = planes[plane][index];
00176     if (the_entry==NULL)
00177         internal_error_1("copy_characters (index %d)", index);
00178     the_entry->copies = copies;
00179     for (i=(c+1); i<=(c+copies); i++)
00180         init_character(i, the_entry);
00181 }
00182 
00183 void
00184 ensure_existence(unsigned c)
00185 {
00186     register unsigned index, plane;
00187     plane = c / PLANE;
00188     index = c % PLANE;
00189 
00190     if ((planes[plane]==NULL) || (planes[plane][index]==NULL)) {
00191         init_character(c, NULL);
00192         planes[plane][index]->defined = FALSE;
00193     }
00194     current_secondary_character = planes[plane][index];
00195 }
00196 
00197 #define FOR_ALL_CHARACTERS(FOR_ALL_CHARACTERS_ACTION) \
00198     for (plane = 0; plane <=plane_max; plane++) { \
00199         if (planes[plane] != NULL) { \
00200             for (index = 0; index <=char_max[plane]; index++) { \
00201                 entry = planes[plane][index]; \
00202                 c = plane*PLANE + index; \
00203                 if (entry != NULL) {  \
00204                     FOR_ALL_CHARACTERS_ACTION \
00205                 } \
00206             } \
00207         } \
00208     }
00209 
00210 #define FOR_ALL_EXISTING_CHARACTERS(FOR_ALL_EXISTING_CHARACTERS_ACTION) \
00211     FOR_ALL_CHARACTERS( \
00212         if (entry->defined == TRUE) { \
00213             FOR_ALL_EXISTING_CHARACTERS_ACTION \
00214         } \
00215     )
00216 
00217 void
00218 output_ovf_chars(void)
00219 {
00220     register unsigned index, plane, c, k;
00221     char_entry *entry;
00222     fix wd;
00223 
00224     FOR_ALL_EXISTING_CHARACTERS(
00225         wd = lval(entry->indices[C_WD]);
00226         if (design_units != UNITY)
00227             wd = zround(((double)wd) / ((double)design_units) * 1048576.0);
00228         if ((entry->ovf_packet_length>241) ||
00229             (wd < 0) || (wd >= 0x1000000) ||
00230             (c < 0) || (c >255)) {
00231             out_ovf(242); out_ovf_4(entry->ovf_packet_length);
00232             out_ovf_4(c); out_ovf_4(wd);
00233         } else {
00234             out_ovf(entry->ovf_packet_length); out_ovf(c);
00235             out_ovf((wd >>16) & 0xff); out_ovf((wd >>8) & 0xff);
00236             out_ovf(wd & 0xff);
00237         }
00238         for (k=0; k<entry->ovf_packet_length; k++)
00239             out_ovf(entry->ovf_packet[k]);
00240     )
00241 }
00242 
00243 
00244 void
00245 check_existence_all_character_fields(void)
00246 {
00247     register unsigned index, plane, c;
00248     char_entry *entry;
00249     unsigned *exten;
00250     unsigned j;
00251  
00252     FOR_ALL_EXISTING_CHARACTERS(
00253         switch(entry->tag) {
00254             case TAG_NONE: { break; }
00255             case TAG_LIG: {
00256                 check_ligature_program(c, entry->remainder);
00257                 break;
00258             }
00259             case TAG_LIST:{
00260                 check_existence_and_safety(c, entry->remainder, NULL,
00261                     "%sCharacter (H %X) NEXTLARGER than (H %X) "
00262                     "has no CHARACTER spec");
00263                 break;
00264             }
00265             case TAG_EXT:{
00266                 exten = entry->extens;
00267                 for (j=E_MIN; j<=E_MAX; j++) {
00268                     if (exten[j]!=0)
00269                         check_existence_and_safety(c, exten[j],
00270                             extensible_pieces[j],
00271                             "%s piece (H %X) of character (H %X) "
00272                             "has no CHARACTER spec");
00273                 }
00274                 break;
00275             }
00276         }
00277     )
00278 }  
00279 
00280 void
00281 clear_ligature_entries(void)
00282 {
00283     register unsigned index, plane, c;
00284     char_entry *entry;
00285 
00286     FOR_ALL_EXISTING_CHARACTERS(
00287         if (entry->tag == TAG_LIG) {
00288             entry->tag = TAG_NONE;
00289             entry->remainder = 0;
00290         }
00291     )
00292 }
00293 
00294 void
00295 check_existence_and_safety(unsigned c, unsigned g, string extra, string fmt)
00296 {
00297     char_entry *gentry = planes[g/PLANE][g%PLANE];
00298 
00299     if ((g<CHAR_MINIMUM) || (g>CHAR_MAXIMUM))
00300         internal_error_1("check_existence_and_safety (g=%d)", g);
00301     gentry = planes[g/PLANE][g%PLANE];
00302     if ((g>=128) && (c<128))
00303         seven_bit_calculated = 0;
00304     if ((gentry==NULL) || (gentry->defined == FALSE)) {
00305         warning_s_2(fmt, extra, g, c);
00306         current_character = gentry;
00307         set_character_measure(C_WD, 0);
00308     }
00309 }
00310 
00311 void
00312 doublecheck_existence(unsigned g, string extra, char*fmt)
00313 {
00314     char_entry *gentry = planes[g/PLANE][g%PLANE];
00315 
00316     if ((g<CHAR_MINIMUM) || (g>CHAR_MAXIMUM))
00317         internal_error_1("doublecheck_existence (g=%d)", g);
00318     gentry = planes[g/PLANE][g%PLANE];
00319     if ((gentry==NULL) || (gentry->defined == FALSE)) {
00320         warning_s_1(fmt, extra, g);
00321         current_character = gentry;
00322 /*
00323         set_character_measure(C_WD, 0);
00324 */
00325     }
00326 }
00327 
00328 extern string character_measures[];
00329 
00330 void
00331 print_characters(boolean read_ovf)
00332 {
00333     register unsigned index, plane, c;
00334     char_entry *entry;
00335     four_pieces *exten;
00336     four_entries *lentry;
00337     unsigned j,k;
00338 
00339     FOR_ALL_CHARACTERS(
00340         if (entry->index_indices[C_WD] != 0) {
00341         print_character(c);
00342         for (k=C_MIN; k<C_MAX; k++) {
00343             if (entry->index_indices[k] != 0) {
00344                 print_character_measure(k,
00345                   dimen_tables[k][entry->index_indices[k]]);
00346             }
00347         }
00348         fflush(file_output);
00349         switch (entry->tag) {
00350             case TAG_NONE: { break; }
00351             case TAG_LIG:  {
00352                 left();
00353                 out("COMMENT"); out_ln();
00354                 lentry = lig_kern_table + entry->remainder;
00355                 if (lentry->entries[0] > STOP_FLAG) {
00356                     lentry = lig_kern_table +
00357                              (256*lentry->entries[2]+lentry->entries[3]); 
00358                 }
00359               do {
00360                     print_one_lig_kern_entry(lentry, FALSE);
00361                   if (lentry->entries[0] >= STOP_FLAG) {
00362                         lentry = lig_kern_table + nl;
00363                     } else {
00364                         lentry = lentry + 1 + lentry->entries[0];
00365                     }
00366                 } while (lentry < (lig_kern_table + nl));
00367                 right();
00368                 break;
00369             }
00370             case TAG_LIST: {
00371                 print_next_larger(entry->remainder);
00372                 break;
00373             }
00374             case TAG_EXT: {
00375                print_var_character();
00376                 exten = exten_table[entry->remainder];
00377                 for (j=E_MIN; j<=E_MAX; j++) {
00378                     if (exten->pieces[j]!=0)
00379                         print_extensible_piece(j,exten->pieces[j]);
00380                 }
00381                 right();
00382                 break;
00383             }
00384         }
00385         if ((read_ovf==TRUE) && (entry->ovf_packet_length>0)) {
00386             print_map();
00387             print_packet(entry->ovf_packet, entry->ovf_packet_length);
00388             right();
00389         }
00390         right();
00391         fflush(file_output);
00392         }
00393     )
00394 }
00395 
00396 unsigned stack_top = 0;
00397 int wstack[1000];
00398 int xstack[1000];
00399 int ystack[1000];
00400 int zstack[1000];
00401 
00402 void
00403 print_packet(unsigned char *packet_start, unsigned packet_length)
00404 {
00405    unsigned cmd, arg;
00406    fix fix_arg, fix_arg1;
00407    unsigned char *packet = packet_start;
00408    unsigned char *max_packet = packet+packet_length;
00409 
00410    stack_top = 0;
00411    wstack[stack_top] = xstack[stack_top] =
00412    ystack[stack_top] = zstack[stack_top] = 0;
00413    while (packet <max_packet) {
00414    if (*packet <= DVI_SET_CHAR_127) {
00415          arg = *packet; packet++;
00416          print_set_char(arg);
00417    } else if ((*packet >= DVI_FNT_NUM_0) && (*packet <= DVI_FNT_NUM_63)) {
00418          arg = *packet - DVI_FNT_NUM_0; packet++;
00419          print_select_font(arg);
00420    } else switch(*packet) {
00421       case DVI_SET_1: case DVI_SET_2: case DVI_SET_3: case DVI_SET_4:
00422          cmd = *packet; packet++;
00423          arg = ovf_get_arg(&packet, cmd - DVI_SET_1 + 1, FALSE);
00424          print_set_char(arg);
00425          break;
00426       case DVI_NOP: 
00427          packet++;
00428          break;
00429       case DVI_PUSH:
00430          cmd = DVI_PUSH; packet++; stack_top++;
00431          wstack[stack_top] = wstack[stack_top-1];
00432          xstack[stack_top] = xstack[stack_top-1];
00433          ystack[stack_top] = ystack[stack_top-1];
00434          zstack[stack_top] = zstack[stack_top-1];
00435          print_push();
00436          break;
00437       case DVI_POP:
00438          cmd = DVI_PUSH; packet++; stack_top--;
00439          print_pop();
00440          break;
00441       case DVI_SET_RULE:
00442          cmd = DVI_SET_RULE; packet++; fix_arg = ovf_get_arg(&packet, 4, TRUE);
00443          fix_arg1 = ovf_get_arg(&packet, 4, TRUE);
00444          print_set_rule(fix_arg, fix_arg1);
00445          break;
00446       case DVI_PUT_RULE:
00447          cmd = DVI_PUT_RULE; packet++; fix_arg = ovf_get_arg(&packet, 4, TRUE);
00448          fix_arg1 = ovf_get_arg(&packet, 4, TRUE);
00449          print_put_rule(fix_arg, fix_arg1);
00450          break;
00451       case DVI_RIGHT_1: case DVI_RIGHT_2: case DVI_RIGHT_3: case DVI_RIGHT_4:
00452          cmd = *packet; packet++;
00453          fix_arg = ovf_get_arg(&packet, cmd - DVI_RIGHT_1 + 1, TRUE);
00454          print_move(M_RIGHT, fix_arg);
00455          break;
00456       case DVI_DOWN_1:  case DVI_DOWN_2:  case DVI_DOWN_3:  case DVI_DOWN_4:
00457          cmd = *packet; packet++;
00458          fix_arg = ovf_get_arg(&packet, cmd - DVI_DOWN_1 + 1, TRUE);
00459          print_move(M_DOWN, fix_arg);
00460          break;
00461       case DVI_W_0:
00462          cmd = DVI_W_0; packet++;
00463          print_move(M_RIGHT, wstack[stack_top]);
00464          break;
00465       case DVI_W_1: case DVI_W_2: case DVI_W_3: case DVI_W_4:
00466          cmd = *packet; packet++;
00467          wstack[stack_top] = ovf_get_arg(&packet, cmd - DVI_W_1 + 1, TRUE);
00468          print_move(M_RIGHT, wstack[stack_top]);
00469          break;
00470       case DVI_X_0:
00471          cmd = DVI_X_0; packet++;
00472          print_move(M_RIGHT, xstack[stack_top]);
00473          break;
00474       case DVI_X_1: case DVI_X_2: case DVI_X_3: case DVI_X_4:
00475          cmd = *packet; packet++;
00476          xstack[stack_top] = ovf_get_arg(&packet, cmd - DVI_X_1 + 1, TRUE);
00477          print_move(M_RIGHT, xstack[stack_top]);
00478          break;
00479       case DVI_Y_0:
00480          cmd = DVI_Y_0; packet++;
00481          print_move(M_DOWN, ystack[stack_top]);
00482          break;
00483       case DVI_Y_1: case DVI_Y_2: case DVI_Y_3: case DVI_Y_4:
00484          cmd = *packet; packet++;
00485          ystack[stack_top] = ovf_get_arg(&packet, cmd - DVI_Y_1 + 1, TRUE);
00486          print_move(M_DOWN, ystack[stack_top]);
00487          break;
00488       case DVI_Z_0:
00489          cmd = DVI_Z_0; packet++;
00490          print_move(M_DOWN, zstack[stack_top]);
00491          break;
00492       case DVI_Z_1: case DVI_Z_2: case DVI_Z_3: case DVI_Z_4:
00493          cmd = *packet; packet++;
00494          zstack[stack_top] = ovf_get_arg(&packet, cmd - DVI_Z_1 + 1, TRUE);
00495          print_move(M_DOWN, zstack[stack_top]);
00496          break;
00497       case DVI_PUT_1: case DVI_PUT_2: case DVI_PUT_3: case DVI_PUT_4:
00498          cmd = *packet; packet++;
00499          fix_arg = ovf_get_arg(&packet, cmd - DVI_PUT_1 + 1, FALSE);
00500          print_put_char(fix_arg);
00501          break;
00502       case DVI_XXX_1: case DVI_XXX_2: case DVI_XXX_3: case DVI_XXX_4:
00503          cmd = *packet; packet++;
00504          fix_arg = ovf_get_arg(&packet, cmd - DVI_XXX_1 + 1, FALSE);
00505          break;
00506       case DVI_FNT_1: case DVI_FNT_2: case DVI_FNT_3: case DVI_FNT_4:
00507          cmd = *packet; packet++;
00508          fix_arg = ovf_get_arg(&packet, cmd - DVI_FNT_1 + 1, FALSE);
00509          print_select_font(fix_arg);
00510          break;
00511       default:
00512          internal_error_1("Unrecognized DVI packet (%d)\n", *packet);
00513    }
00514    }
00515    fflush(file_output);
00516    fflush(stderr);
00517 }
00518 
00519 void
00520 check_char_tag(unsigned c)
00521 {
00522     ensure_existence(c);
00523 }
00524 
00525 void
00526 set_char_tag(unsigned c, unsigned tag)
00527 {
00528     ensure_existence(c);
00529     planes[c/PLANE][c%PLANE]->tag = tag;
00530 }
00531 
00532 void
00533 set_char_remainder(unsigned c, unsigned remainder)
00534 {
00535     ensure_existence(c);
00536     planes[c/PLANE][c%PLANE]->remainder = remainder;
00537 }
00538 
00539 int
00540 get_char_remainder(unsigned c)
00541 {
00542     ensure_existence(c);
00543     return planes[c/PLANE][c%PLANE]->remainder;
00544 }
00545 
00546 void
00547 set_next_larger(unsigned larger)
00548 {
00549     check_char_tag(current_character->c);
00550     set_char_tag(current_character->c, TAG_LIST);
00551     set_char_remainder(current_character->c, larger);
00552 }
00553 
00554 void
00555 init_var_character(void)
00556 {
00557     four_pieces *entry = (four_pieces *) xmalloc(sizeof(four_pieces));
00558     unsigned j;
00559 
00560     check_char_tag(current_character->c);
00561     set_char_tag(current_character->c, TAG_EXT);
00562     append_to_queue(&exten_queue, entry);
00563     for (j=E_MIN; j<=E_MAX; j++) {
00564         entry->pieces[j] = 0;
00565     }
00566     set_char_remainder(current_character->c, ne);
00567     current_character->extens = (unsigned int *)entry->pieces;
00568     ne++;
00569 }
00570 
00571 void
00572 set_extensible_piece(unsigned piece, unsigned val)
00573 {
00574     unsigned *exten = current_character->extens;
00575 
00576     if ((piece < E_MIN) || (piece > E_MAX))
00577         internal_error_1("set_extensible_piece (piece=%d)", piece);
00578     if (exten[piece]!=0)
00579         warning_0("value already defined");
00580     exten[piece] = val;
00581 }
00582 
00583 void
00584 adjust_labels(boolean play_with_starts)
00585 {
00586     unsigned plane, index;
00587     unsigned c;
00588     char_entry *entry;
00589     int max_start = (ofm_level==OFM_TFM) ? MAX_START_TFM : MAX_START_OFM;
00590 
00591     label_table = (label_entry *)xmalloc((no_labels+2)*sizeof(label_entry));
00592     label_ptr = 0;
00593     label_table[0].rr = -1; /* sentinel */
00594     FOR_ALL_CHARACTERS(
00595         if ((c>=bc) && (c<=ec) && (entry->tag == TAG_LIG)) {
00596             sort_ptr = label_ptr; /* hole at position sort_ptr+1 */
00597             while (label_table[sort_ptr].rr > (int)(entry->remainder)) {
00598                 label_table[sort_ptr+1] = label_table[sort_ptr];
00599                 sort_ptr--; /* move the hole */
00600             }
00601             label_table[sort_ptr+1].cc = c;
00602             label_table[sort_ptr+1].rr = entry->remainder;
00603             label_ptr++;
00604         }
00605     )
00606     if (play_with_starts) {
00607       if (bchar != CHAR_BOUNDARY) {
00608         extra_loc_needed = TRUE; lk_offset = 1;
00609       } else {
00610         extra_loc_needed = FALSE; lk_offset = 0;
00611       }
00612       sort_ptr = label_ptr; /* the largest unallocated label */
00613       if ((label_table[sort_ptr].rr + lk_offset) > max_start) {
00614         lk_offset=0; extra_loc_needed=FALSE;
00615         /* location 0 can do double duty */
00616         do {
00617             set_char_remainder(label_table[sort_ptr].cc, lk_offset);
00618             while (label_table[sort_ptr-1].rr == label_table[sort_ptr].rr) {
00619                 sort_ptr--;
00620                 set_char_remainder(label_table[sort_ptr].cc, lk_offset);
00621             }
00622             lk_offset++; sort_ptr--;
00623         } while ((lk_offset+label_table[sort_ptr].rr) > max_start);
00624         /* N.B. lk_offset=MAX_START+1 satisfies this when sort_ptr=0 */
00625       }
00626       if (lk_offset>0) {
00627         while (sort_ptr>0) {
00628             set_char_remainder(label_table[sort_ptr].cc,
00629                                get_char_remainder(label_table[sort_ptr].cc)
00630                                +lk_offset);
00631             sort_ptr--;
00632         }
00633       }
00634     }
00635 }
00636 
00637 void
00638 print_labels(void)
00639 {
00640     unsigned i;
00641 
00642     if (label_ptr>0) {
00643         left(); out("COMMENT"); out_ln();
00644         for (i=1; i<=label_ptr; i++) {
00645             left(); out("LABEL_ENTRY"); out(" ");
00646             out_int(i,10); out(" ");
00647             out_char(label_table[i].cc); out(" ");
00648             out_int(label_table[i].rr, 10); right();
00649         }
00650         right();
00651     }
00652 }
00653 
00654 void
00655 check_and_correct(void)
00656 {
00657     build_kern_table();
00658     build_dimen_tables();
00659     build_exten_table();
00660     check_ligature_ends_properly();
00661     compute_ofm_character_info();
00662     adjust_labels(TRUE);
00663     check_existence_all_character_fields();
00664     calculate_seven_bit_safe_flag();
00665     check_ligature_infinite_loops();
00666     check_charlist_infinite_loops();
00667     doublecheck_ligatures();
00668     doublecheck_extens();
00669 }
00670 
00671 void
00672 check_charlist_infinite_loops(void)
00673 {
00674     unsigned plane, index;
00675     unsigned c;
00676     char_entry *entry;
00677     unsigned g;
00678 
00679     FOR_ALL_CHARACTERS(
00680         if (entry->tag == TAG_LIST) {
00681             g = entry->remainder;
00682             while ((g < c) && (planes[g/PLANE][g%PLANE]->tag == TAG_LIST)) {
00683                 g = planes[g/PLANE][g%PLANE]->remainder;
00684             }
00685             if (g == c) {
00686                 entry->tag = TAG_NONE;
00687                 entry->remainder = 0;
00688                 warning_1("Cycle of NEXTLARGER characters "
00689                           "has been broken at ",c);
00690             }
00691         }
00692     )
00693 }
00694 
00695 void
00696 build_exten_table(void)
00697 {
00698     list L1 = exten_queue.front, L2;
00699     unsigned i = 0;
00700 
00701     exten_table = (four_pieces **) xmalloc(ne*sizeof(four_pieces *));
00702     while (L1 != NULL) {
00703         exten_table[i] = (four_pieces *)L1->contents;
00704         L2 = L1->ptr;
00705         free(L1); L1 = L2;
00706         i++;
00707     }
00708 }
00709 
00710 void
00711 retrieve_exten_table(unsigned char *table)
00712 {
00713     unsigned i = 0, j;
00714     four_pieces *entry;
00715 
00716     exten_table = (four_pieces **) xmalloc(ne*sizeof(four_pieces *));
00717     for (i=0; i<ne; i++) {
00718         exten_table[i] = entry = (four_pieces *) xmalloc(sizeof(four_pieces));
00719         for (j=E_MIN; j<=E_MAX; j++) {
00720             if (ofm_level==OFM_TFM) {
00721                 entry->pieces[j] = table[4*i+j] & 0xff;
00722             } else {
00723                 entry->pieces[j] =
00724                   ((table[8*i+j*2] & 0xff) << 8) |
00725                   (table[8*i+j*2+1] & 0xff);
00726             }
00727         }
00728     }
00729 }
00730 
00731 void
00732 print_extens(void)
00733 {
00734     unsigned i,j;
00735 
00736     if (ne>0) {
00737         left(); out("COMMENT"); out_ln();
00738         for (i=0; i<ne; i++) {
00739             left(); out("EXTEN_ENTRY");
00740             out(" "); out_int(i,10); out_ln();
00741             for (j=E_MIN; j<=E_MAX; j++) {
00742                 if (exten_table[i]->pieces[j] != 0)
00743                     print_extensible_piece(j,exten_table[i]->pieces[j]);
00744             }
00745             right();
00746         }
00747         right();
00748     }
00749 }
00750 
00751 void
00752 doublecheck_extens(void)
00753 {
00754     unsigned i,j;
00755 
00756     if (ne>0) {
00757         for (i=0; i<ne; i++) {
00758             for (j=E_MIN; j<=E_MAX; j++) {
00759                 if (exten_table[i]->pieces[j] != 0)
00760                     doublecheck_existence(
00761                         exten_table[i]->pieces[j], extensible_pieces[j],
00762                         "Unused %s piece (H %X) refers to "
00763                         "nonexistent character");
00764             }
00765         }
00766     }
00767 }
00768 
00769 void
00770 compute_ligkern_offset(void)
00771 {
00772 }
00773 
00774 void
00775 compute_character_info_size(void)
00776 {
00777 }
00778 
00779 void
00780 output_ofm_extensible(void)
00781 {
00782     unsigned i,j;
00783 
00784     for (i=0; i<ne; i++) {
00785         for (j=E_MIN; j<=E_MAX; j++) {
00786             if (exten_table[i]->pieces[j] != 0)
00787                 out_ofm_char(exten_table[i]->pieces[j]);
00788             else out_ofm_char(0);
00789         }
00790     }
00791 }
00792 
00793 void
00794 compute_ofm_character_info(void)
00795 {
00796     unsigned plane, index;
00797     unsigned c;
00798     char_entry *entry;
00799 
00800     bc = 0x7fffffff; ec=0;
00801     switch (ofm_level) {
00802         case OFM_TFM: {
00803             FOR_ALL_EXISTING_CHARACTERS(
00804                 if (c < bc) bc = c;
00805                 if (c > ec) ec = c;
00806             )
00807             break;
00808         }
00809         case OFM_LEVEL0: {
00810             FOR_ALL_EXISTING_CHARACTERS(
00811                 if (c < bc) bc = c;
00812                 if (c > ec) ec = c;
00813             )
00814             break;
00815         }
00816 /* Level 1 only uses plane 0.  Take advantage of this fact. */
00817         case OFM_LEVEL1: {
00818             FOR_ALL_CHARACTERS(
00819                 if (c < bc) bc = c;
00820                 if (c > ec) ec = c;
00821             )
00822             break;
00823         }
00824         default: { internal_error_0("compute_ofm_character_info"); }
00825     }
00826 }
00827 
00828 void
00829 output_ofm_character_info(void)
00830 {
00831     unsigned plane, index;
00832     unsigned c;
00833     char_entry *entry;
00834     unsigned wd, ht, dp, ic;
00835 
00836     switch (ofm_level) {
00837         case OFM_TFM: {
00838             plane=0;
00839             for (index = bc; index <=ec; index++) {
00840                 entry = planes[plane][index]; 
00841                 c = plane*PLANE + index;
00842                 if (entry == NULL) { 
00843                     out_ofm_4(0);
00844                 } else {
00845                     if (entry->indices[C_WD] != NULL)
00846                         wd = entry->indices[C_WD]->index;
00847                     else wd = 0;
00848                     if (entry->indices[C_HT] != NULL)
00849                         ht = entry->indices[C_HT]->index;
00850                     else ht = 0;
00851                     if (entry->indices[C_DP] != NULL)
00852                         dp = entry->indices[C_DP]->index;
00853                     else dp = 0;
00854                     if (entry->indices[C_IC] != NULL)
00855                         ic = entry->indices[C_IC]->index;
00856                     else ic = 0;
00857                     out_ofm(wd);
00858                     out_ofm(ht*16 + dp);
00859                     out_ofm(ic*4 + entry->tag);
00860                     out_ofm(entry->remainder);
00861                 }
00862             }
00863             break;
00864         }
00865         case OFM_LEVEL0: {
00866             plane=0;
00867             for (index = bc; index <=ec; index++) {
00868                 entry = planes[plane][index]; 
00869                 c = plane*PLANE + index;
00870                 if (entry == NULL) { 
00871                     out_ofm_4(0); out_ofm_4(0);
00872                 } else {
00873                     if (entry->indices[C_WD] != NULL)
00874                         wd = entry->indices[C_WD]->index;
00875                     else wd = 0;
00876                     if (entry->indices[C_HT] != NULL)
00877                         ht = entry->indices[C_HT]->index;
00878                     else ht = 0;
00879                     if (entry->indices[C_DP] != NULL)
00880                         dp = entry->indices[C_DP]->index;
00881                     else dp = 0;
00882                     if (entry->indices[C_IC] != NULL)
00883                         ic = entry->indices[C_IC]->index;
00884                     else ic = 0;
00885                     out_ofm_2(wd);
00886                     out_ofm(ht);
00887                     out_ofm(dp);
00888                     out_ofm(ic);
00889                     out_ofm(entry->tag);
00890                     out_ofm_2(entry->remainder);
00891                 }
00892             }
00893             break;
00894         }
00895         case OFM_LEVEL1: {
00896             internal_error_0("OFM level 1 not currently supported");
00897             break;
00898         }
00899         default: { internal_error_0("compute_ofm_character_info"); }
00900     }
00901 }